archery/0000775000175000017500000000000014661133735013200 5ustar jamespagejamespagearchery/README.md0000644000175000017500000001222514661133735014457 0ustar jamespagejamespage[![Build Status](https://github.com/orium/archery/workflows/CI/badge.svg)](https://github.com/orium/archery/actions?query=workflow%3ACI) [![Code Coverage](https://codecov.io/gh/orium/archery/branch/main/graph/badge.svg)](https://codecov.io/gh/orium/archery) [![Dependency status](https://deps.rs/repo/github/orium/archery/status.svg)](https://deps.rs/repo/github/orium/archery) [![crates.io](https://img.shields.io/crates/v/archery.svg)](https://crates.io/crates/archery) [![Downloads](https://img.shields.io/crates/d/archery.svg)](https://crates.io/crates/archery) [![Github stars](https://img.shields.io/github/stars/orium/archery.svg?logo=github)](https://github.com/orium/archery/stargazers) [![Documentation](https://docs.rs/archery/badge.svg)](https://docs.rs/archery/) [![License](https://img.shields.io/crates/l/archery.svg)](./LICENSE.md) # `archery` `archery` is a rust library that offers a way to abstraction over [`Rc`](https://doc.rust-lang.org/stable/alloc/rc/struct.Rc.html) and [`Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html) smart pointers. This allows you to create data structures where the pointer type is parameterizable, so you can [avoid the overhead of `Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html#thread-safety) when you don’t need to share data across threads. In languages that supports [higher-kinded polymorphism](https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polymorphism) this would be simple to achieve without any library, but [rust does not support that yet](https://github.com/rust-lang/rfcs/issues/324). To mimic higher-kinded polymorphism `archery` implements the approach suggested by Joshua Liebow-Feeser in “[Rust has higher kinded types already… sort of](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/)”. While [other approaches](#alternative-approaches) exist, they seem to always offer poor ergonomics for the user. ## Setup To use `archery` add the following to your `Cargo.toml`: ```toml [dependencies] archery = "" ``` ## Using `archery` `archery` defines a [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html) that receives the [kind of pointer](https://docs.rs/archery/latest/archery/shared_pointer/kind/trait.SharedPointerKind.html) as a type parameter. This gives you a convenient and ergonomic way to abstract the pointer type away. ### Example Declare a data structure with the pointer kind as a type parameter bounded by [`SharedPointerKind`](https://docs.rs/archery/latest/archery/shared_pointer/kind/trait.SharedPointerKind.html): ```rust use archery::*; struct KeyValuePair { pub key: SharedPointer, pub value: SharedPointer, } impl KeyValuePair { fn new(key: K, value: V) -> KeyValuePair { KeyValuePair { key: SharedPointer::new(key), value: SharedPointer::new(value), } } } ``` To use it just plug-in the kind of pointer you want: ```rust let pair: KeyValuePair<_, _, RcK> = KeyValuePair::new("António Variações", 1944); assert_eq!(*pair.value, 1944); ``` ### `triomphe::Arc` You can also use [`triomphe::Arc`](https://docs.rs/triomphe/latest/triomphe/struct.Arc.html) as the backing implementation of a [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html). This is generally faster than [`std::sync::Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html). Read [`triomphe`’s crate documentation](https://docs.rs/triomphe/latest/triomphe/) to learn more about it. To use it you need to enable the `triomphe` feature in `archery`. Use `ArcTK` as the pointer kind in [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html). ### Serialization We support serialization through [serde](https://crates.io/crates/serde). To use it enable the `serde` feature. To do so change the archery dependency in your `Cargo.toml` to ```toml [dependencies] archery = { version = "", features = ["serde"] } ``` ## Limitations Currently it is not possible to have unsized types inside a [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html). As a workaround you can put the unsized type inside a [`Box`](https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html). ## Alternative approaches An alternative to the approach taken by `archery` is to use traits with associated types to encode type-level functions. This has been suggested [multiple](https://github.com/orium/rpds/issues/7#issuecomment-362635901) [times](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/#comment-4160863400), but offers ugly ergonomics (see [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L153) and [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L249)). archery/Cargo.toml0000644000175000017500000000541614661133735015134 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.60.0" name = "archery" version = "1.2.0" authors = ["Diogo Sousa "] include = [ "/src/**/*.rs", "/Cargo.toml", "/LICENSE.md", "/README.md", "/release-notes.md", ] description = "Abstract over the atomicity of reference-counting pointers" homepage = "https://github.com/orium/archery" documentation = "https://docs.rs/archery" readme = "README.md" keywords = [ "rc", "arc", "reference-counting", "no_std", ] categories = [ "concurrency", "memory-management", "rust-patterns", ] license = "MPL-2.0" repository = "https://github.com/orium/archery" [package.metadata.docs.rs] features = [ "triomphe", "serde", ] [[bench]] name = "std_rc" path = "benches/std_rc.rs" harness = false [[bench]] name = "std_arc" path = "benches/std_arc.rs" harness = false [[bench]] name = "archery_shared_pointer_rc" path = "benches/archery_shared_pointer_rc.rs" harness = false [[bench]] name = "archery_shared_pointer_arc" path = "benches/archery_shared_pointer_arc.rs" harness = false [[bench]] name = "archery_shared_pointer_arct" path = "benches/archery_shared_pointer_arct.rs" harness = false required-features = ["triomphe"] [dependencies.serde] version = "1.0.197" optional = true default-features = false [dependencies.static_assertions] version = "1.1.0" [dependencies.triomphe] version = "0.1.9" optional = true default-features = false [dev-dependencies.bincode] version = "1.3.3" [dev-dependencies.compiletest_rs] version = "0.10.2" [dev-dependencies.criterion] version = "0.5.1" features = ["html_reports"] [dev-dependencies.pretty_assertions] version = "1.2.1" [features] fatal-warnings = [] serde = ["dep:serde"] triomphe = ["dep:triomphe"] [badges.codecov] branch = "main" repository = "orium/archery" service = "github" [lints.clippy] correctness = "deny" explicit-deref-methods = "allow" if-not-else = "allow" inline-always = "allow" match-bool = "allow" missing-errors-doc = "allow" missing-safety-doc = "allow" module-name-repetitions = "allow" partialeq-ne-impl = "allow" similar-names = "allow" single-match-else = "allow" use-self = "allow" wildcard-imports = "allow" [lints.clippy.all] level = "warn" priority = -1 [lints.clippy.pedantic] level = "warn" priority = -1 [lints.rustdoc] redundant-explicit-links = "allow" archery/src/0000775000175000017500000000000014661133735013767 5ustar jamespagejamespagearchery/src/shared_pointer/0000775000175000017500000000000014661133735016775 5ustar jamespagejamespagearchery/src/shared_pointer/kind/0000775000175000017500000000000014661133735017722 5ustar jamespagejamespagearchery/src/shared_pointer/kind/arct/0000775000175000017500000000000014661133735020653 5ustar jamespagejamespagearchery/src/shared_pointer/kind/arct/test.rs0000644000175000017500000001056414661133735022204 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; use std::cell::Cell; use std::string::ToString; type PointerKind = ArcTK; assert_impl_all!(ArcTK: Send, Sync); #[test] fn test_from_box_t() { let mut ptr = PointerKind::from_box(Box::new(42)); unsafe { assert_eq!(ptr.deref::(), &42); ptr.drop::(); } } #[test] fn test_as_ptr() { let mut x = PointerKind::new::<&'static str>("hello"); unsafe { let mut y = PointerKind::clone::<&'static str>(&x); let x_ptr: *const &'static str = PointerKind::as_ptr(&x); assert_eq!(x_ptr, PointerKind::as_ptr(&y)); assert_eq!(*x_ptr, "hello"); x.drop::<&'static str>(); y.drop::<&'static str>(); } } #[test] fn test_deref() { let mut ptr_42 = PointerKind::new::(42); let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello")); unsafe { assert_eq!(ptr_42.deref::(), &42); assert_eq!(ptr_box_dyn_hello.deref::>().to_string(), "hello"); ptr_42.drop::(); ptr_box_dyn_hello.drop::>(); } } #[test] fn test_try_unwrap() { let ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.try_unwrap::().unwrap(), 42); } let ptr = PointerKind::new::(42); unsafe { let ptr_clone = ptr.clone::(); let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err(); let mut ptr = ptr.try_unwrap::().unwrap_err(); assert_eq!(ptr.deref::(), &42); assert_eq!(ptr_clone.deref::(), &42); ptr.drop::(); ptr_clone.drop::(); } } #[test] fn test_get_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.get_mut::().unwrap() += 1; assert_eq!(ptr.deref::(), &43); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.get_mut::(), None); assert_eq!(ptr_clone.get_mut::(), None); ptr.drop::(); *ptr_clone.get_mut::().unwrap() += 1; assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_make_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); // Clone to force make_mut to clone the data. let mut ptr_clone = ptr.clone::(); assert_eq!(ptr_clone.deref::(), &43); *ptr_clone.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); assert_eq!(ptr_clone.deref::(), &44); *ptr.make_mut::() *= 2; assert_eq!(ptr.deref::(), &(2 * 43)); assert_eq!(ptr_clone.deref::(), &44); ptr.drop::(); assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_strong_count() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.strong_count::(), 1); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.strong_count::(), 2); assert_eq!(ptr_clone.strong_count::(), 2); ptr.drop::(); assert_eq!(ptr_clone.strong_count::(), 1); ptr_clone.drop::(); } } #[test] fn test_clone() { let mut ptr = PointerKind::new::>(Cell::new(42)); unsafe { let mut ptr_clone = ptr.clone::>(); assert_eq!(ptr.deref::>().get(), 42); assert_eq!(ptr_clone.deref::>().get(), 42); ptr_clone.deref::>().set(3); assert_eq!(ptr.deref::>().get(), 3); assert_eq!(ptr_clone.deref::>().get(), 3); ptr.drop::>(); assert_eq!(ptr_clone.deref::>().get(), 3); ptr_clone.drop::>(); } } #[test] fn test_debug() { let mut ptr = PointerKind::new::(42); assert_eq!(format!("{:?}", ptr), "ArcTK"); unsafe { ptr.drop::(); } } archery/src/shared_pointer/kind/arct/mod.rs0000644000175000017500000000667614661133735022015 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use core::fmt; use core::fmt::Debug; use core::fmt::Formatter; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ops::DerefMut; use core::ptr; use triomphe::Arc; type UntypedArc = Arc<()>; /// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for /// [`triomphe::Arc`](triomphe::Arc) pointers. pub struct ArcTK { /// We use [`ManuallyDrop`] here, so that we can drop it explicitly as /// [`Arc`](triomphe::Arc). Not sure if it can be dropped as [`UntypedArc`], but it /// seems to be playing with fire (even more than we already are). inner: ManuallyDrop, } impl ArcTK { #[inline(always)] fn new_from_inner(arc: Arc) -> ArcTK { ArcTK { inner: ManuallyDrop::new(unsafe { mem::transmute(arc) }) } } #[inline(always)] unsafe fn take_inner(self) -> Arc { let arc: UntypedArc = ManuallyDrop::into_inner(self.inner); mem::transmute(arc) } #[inline(always)] unsafe fn as_inner_ref(&self) -> &Arc { let arc_t: *const Arc = (self.inner.deref() as *const UntypedArc).cast::>(); // Static check to make sure we are not messing up the sizes. // This could happen if we allowed for `T` to be unsized, because it would need to be // represented as a wide pointer inside `Arc`. // TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21 // gets fixed let _ = mem::transmute::>; &*arc_t } #[inline(always)] unsafe fn as_inner_mut(&mut self) -> &mut Arc { let arc_t: *mut Arc = (self.inner.deref_mut() as *mut UntypedArc).cast::>(); &mut *arc_t } } unsafe impl SharedPointerKind for ArcTK { #[inline(always)] fn new(v: T) -> ArcTK { ArcTK::new_from_inner(Arc::new(v)) } #[inline(always)] fn from_box(v: Box) -> ArcTK { ArcTK::new_from_inner::(Arc::from(v)) } #[inline(always)] unsafe fn as_ptr(&self) -> *const T { Arc::as_ptr(self.as_inner_ref()) } #[inline(always)] unsafe fn deref(&self) -> &T { self.as_inner_ref::().as_ref() } #[inline(always)] unsafe fn try_unwrap(self) -> Result { Arc::try_unwrap(self.take_inner()).map_err(ArcTK::new_from_inner) } #[inline(always)] unsafe fn get_mut(&mut self) -> Option<&mut T> { Arc::get_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn make_mut(&mut self) -> &mut T { Arc::make_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn strong_count(&self) -> usize { Arc::count(self.as_inner_ref::()) } #[inline(always)] unsafe fn clone(&self) -> ArcTK { ArcTK { inner: ManuallyDrop::new(Arc::clone(self.as_inner_ref())) } } #[inline(always)] unsafe fn drop(&mut self) { ptr::drop_in_place::>(self.as_inner_mut()); } } impl Debug for ArcTK { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { f.write_str("ArcTK") } } #[cfg(test)] mod test; archery/src/shared_pointer/kind/rc/0000775000175000017500000000000014661133735020326 5ustar jamespagejamespagearchery/src/shared_pointer/kind/rc/test.rs0000644000175000017500000001055214661133735021654 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use std::cell::Cell; use std::string::ToString; type PointerKind = RcK; #[test] fn test_from_box_t() { let mut ptr = PointerKind::from_box(Box::new(42)); unsafe { assert_eq!(ptr.deref::(), &42); ptr.drop::(); } } #[test] fn test_as_ptr() { let mut x = PointerKind::new::<&'static str>("hello from test_as_ptr"); unsafe { let mut y = PointerKind::clone::<&'static str>(&x); let x_ptr: *const &'static str = PointerKind::as_ptr(&x); assert_eq!(x_ptr, PointerKind::as_ptr(&y)); assert_eq!(*x_ptr, "hello from test_as_ptr"); x.drop::<&'static str>(); y.drop::<&'static str>(); } } #[test] fn test_deref() { let mut ptr_42 = PointerKind::new::(42); let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello from test_deref")); unsafe { assert_eq!(ptr_42.deref::(), &42); assert_eq!( ptr_box_dyn_hello.deref::>().to_string(), "hello from test_deref" ); ptr_42.drop::(); ptr_box_dyn_hello.drop::>(); } } #[test] fn test_try_unwrap() { let ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.try_unwrap::().unwrap(), 42); } let ptr = PointerKind::new::(42); unsafe { let ptr_clone = ptr.clone::(); let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err(); let mut ptr = ptr.try_unwrap::().unwrap_err(); assert_eq!(ptr.deref::(), &42); assert_eq!(ptr_clone.deref::(), &42); ptr.drop::(); ptr_clone.drop::(); } } #[test] fn test_get_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.get_mut::().unwrap() += 1; assert_eq!(ptr.deref::(), &43); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.get_mut::(), None); assert_eq!(ptr_clone.get_mut::(), None); ptr.drop::(); *ptr_clone.get_mut::().unwrap() += 1; assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_make_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); // Clone to force make_mut to clone the data. let mut ptr_clone = ptr.clone::(); assert_eq!(ptr_clone.deref::(), &43); *ptr_clone.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); assert_eq!(ptr_clone.deref::(), &44); *ptr.make_mut::() *= 2; assert_eq!(ptr.deref::(), &(2 * 43)); assert_eq!(ptr_clone.deref::(), &44); ptr.drop::(); assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_strong_count() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.strong_count::(), 1); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.strong_count::(), 2); assert_eq!(ptr_clone.strong_count::(), 2); ptr.drop::(); assert_eq!(ptr_clone.strong_count::(), 1); ptr_clone.drop::(); } } #[test] fn test_clone() { let mut ptr = PointerKind::new::>(Cell::new(42)); unsafe { let mut ptr_clone = ptr.clone::>(); assert_eq!(ptr.deref::>().get(), 42); assert_eq!(ptr_clone.deref::>().get(), 42); ptr_clone.deref::>().set(3); assert_eq!(ptr.deref::>().get(), 3); assert_eq!(ptr_clone.deref::>().get(), 3); ptr.drop::>(); assert_eq!(ptr_clone.deref::>().get(), 3); ptr_clone.drop::>(); } } #[test] fn test_debug() { let mut ptr = PointerKind::new::(42); assert_eq!(format!("{ptr:?}"), "RcK"); unsafe { ptr.drop::(); } } archery/src/shared_pointer/kind/rc/mod.rs0000644000175000017500000000662614661133735021463 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use alloc::rc::Rc; use core::fmt; use core::fmt::Debug; use core::fmt::Formatter; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ops::DerefMut; use core::ptr; type UntypedRc = Rc<()>; /// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for /// [`Rc`] pointers. pub struct RcK { /// We use [`ManuallyDrop`] here, so that we can drop it explicitly as [`Rc`](alloc::rc::Rc). /// Not sure if it can be dropped as [`UntypedRc`], but it seems to be playing with fire (even /// more than we already are). inner: ManuallyDrop, } impl RcK { #[inline(always)] fn new_from_inner(rc: Rc) -> RcK { RcK { inner: ManuallyDrop::new(unsafe { mem::transmute(rc) }) } } #[inline(always)] unsafe fn take_inner(self) -> Rc { let rc: UntypedRc = ManuallyDrop::into_inner(self.inner); mem::transmute(rc) } #[inline(always)] unsafe fn as_inner_ref(&self) -> &Rc { let rc_t: *const Rc = (self.inner.deref() as *const UntypedRc).cast::>(); // Static check to make sure we are not messing up the sizes. // This could happen if we allowed for `T` to be unsized, because it would need to be // represented as a wide pointer inside `Rc`. // TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21 // gets fixed let _ = mem::transmute::>; &*rc_t } #[inline(always)] unsafe fn as_inner_mut(&mut self) -> &mut Rc { let rc_t: *mut Rc = (self.inner.deref_mut() as *mut UntypedRc).cast::>(); &mut *rc_t } } unsafe impl SharedPointerKind for RcK { #[inline(always)] fn new(v: T) -> RcK { RcK::new_from_inner(Rc::new(v)) } #[inline(always)] fn from_box(v: Box) -> RcK { RcK::new_from_inner::(Rc::from(v)) } #[inline(always)] unsafe fn as_ptr(&self) -> *const T { Rc::as_ptr(self.as_inner_ref()) } #[inline(always)] unsafe fn deref(&self) -> &T { self.as_inner_ref::().as_ref() } #[inline(always)] unsafe fn try_unwrap(self) -> Result { Rc::try_unwrap(self.take_inner()).map_err(RcK::new_from_inner) } #[inline(always)] unsafe fn get_mut(&mut self) -> Option<&mut T> { Rc::get_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn make_mut(&mut self) -> &mut T { Rc::make_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn strong_count(&self) -> usize { Rc::strong_count(self.as_inner_ref::()) } #[inline(always)] unsafe fn clone(&self) -> RcK { RcK { inner: ManuallyDrop::new(Rc::clone(self.as_inner_ref())) } } #[inline(always)] unsafe fn drop(&mut self) { ptr::drop_in_place::>(self.as_inner_mut()); } } impl Debug for RcK { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { f.write_str("RcK") } } #[cfg(test)] mod test; archery/src/shared_pointer/kind/arc/0000775000175000017500000000000014661133735020467 5ustar jamespagejamespagearchery/src/shared_pointer/kind/arc/test.rs0000644000175000017500000001056114661133735022015 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; use std::cell::Cell; use std::string::ToString; type PointerKind = ArcK; assert_impl_all!(ArcK: Send, Sync); #[test] fn test_from_box_t() { let mut ptr = PointerKind::from_box(Box::new(42)); unsafe { assert_eq!(ptr.deref::(), &42); ptr.drop::(); } } #[test] fn test_as_ptr() { let mut x = PointerKind::new::<&'static str>("hello"); unsafe { let mut y = PointerKind::clone::<&'static str>(&x); let x_ptr: *const &'static str = PointerKind::as_ptr(&x); assert_eq!(x_ptr, PointerKind::as_ptr(&y)); assert_eq!(*x_ptr, "hello"); x.drop::<&'static str>(); y.drop::<&'static str>(); } } #[test] fn test_deref() { let mut ptr_42 = PointerKind::new::(42); let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello")); unsafe { assert_eq!(ptr_42.deref::(), &42); assert_eq!(ptr_box_dyn_hello.deref::>().to_string(), "hello"); ptr_42.drop::(); ptr_box_dyn_hello.drop::>(); } } #[test] fn test_try_unwrap() { let ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.try_unwrap::().unwrap(), 42); } let ptr = PointerKind::new::(42); unsafe { let ptr_clone = ptr.clone::(); let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err(); let mut ptr = ptr.try_unwrap::().unwrap_err(); assert_eq!(ptr.deref::(), &42); assert_eq!(ptr_clone.deref::(), &42); ptr.drop::(); ptr_clone.drop::(); } } #[test] fn test_get_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.get_mut::().unwrap() += 1; assert_eq!(ptr.deref::(), &43); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.get_mut::(), None); assert_eq!(ptr_clone.get_mut::(), None); ptr.drop::(); *ptr_clone.get_mut::().unwrap() += 1; assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_make_mut() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.deref::(), &42); *ptr.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); // Clone to force make_mut to clone the data. let mut ptr_clone = ptr.clone::(); assert_eq!(ptr_clone.deref::(), &43); *ptr_clone.make_mut::() += 1; assert_eq!(ptr.deref::(), &43); assert_eq!(ptr_clone.deref::(), &44); *ptr.make_mut::() *= 2; assert_eq!(ptr.deref::(), &(2 * 43)); assert_eq!(ptr_clone.deref::(), &44); ptr.drop::(); assert_eq!(ptr_clone.deref::(), &44); ptr_clone.drop::(); } } #[test] fn test_strong_count() { let mut ptr = PointerKind::new::(42); unsafe { assert_eq!(ptr.strong_count::(), 1); let mut ptr_clone = ptr.clone::(); assert_eq!(ptr.strong_count::(), 2); assert_eq!(ptr_clone.strong_count::(), 2); ptr.drop::(); assert_eq!(ptr_clone.strong_count::(), 1); ptr_clone.drop::(); } } #[test] fn test_clone() { let mut ptr = PointerKind::new::>(Cell::new(42)); unsafe { let mut ptr_clone = ptr.clone::>(); assert_eq!(ptr.deref::>().get(), 42); assert_eq!(ptr_clone.deref::>().get(), 42); ptr_clone.deref::>().set(3); assert_eq!(ptr.deref::>().get(), 3); assert_eq!(ptr_clone.deref::>().get(), 3); ptr.drop::>(); assert_eq!(ptr_clone.deref::>().get(), 3); ptr_clone.drop::>(); } } #[test] fn test_debug() { let mut ptr = PointerKind::new::(42); assert_eq!(format!("{:?}", ptr), "ArcK"); unsafe { ptr.drop::(); } } archery/src/shared_pointer/kind/arc/mod.rs0000644000175000017500000000672514661133735021624 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use alloc::sync::Arc; use core::fmt; use core::fmt::Debug; use core::fmt::Formatter; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ops::DerefMut; use core::ptr; type UntypedArc = Arc<()>; /// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for /// [`Arc`] pointers. pub struct ArcK { /// We use [`ManuallyDrop`] here, so that we can drop it explicitly as /// [`Arc`](alloc::sync::Arc). Not sure if it can be dropped as [`UntypedArc`], but it /// seems to be playing with fire (even more than we already are). inner: ManuallyDrop, } impl ArcK { #[inline(always)] fn new_from_inner(arc: Arc) -> ArcK { ArcK { inner: ManuallyDrop::new(unsafe { mem::transmute(arc) }) } } #[inline(always)] unsafe fn take_inner(self) -> Arc { let arc: UntypedArc = ManuallyDrop::into_inner(self.inner); mem::transmute(arc) } #[inline(always)] unsafe fn as_inner_ref(&self) -> &Arc { let arc_t: *const Arc = (self.inner.deref() as *const UntypedArc).cast::>(); // Static check to make sure we are not messing up the sizes. // This could happen if we allowed for `T` to be unsized, because it would need to be // represented as a wide pointer inside `Arc`. // TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21 // gets fixed let _ = mem::transmute::>; &*arc_t } #[inline(always)] unsafe fn as_inner_mut(&mut self) -> &mut Arc { let arc_t: *mut Arc = (self.inner.deref_mut() as *mut UntypedArc).cast::>(); &mut *arc_t } } unsafe impl SharedPointerKind for ArcK { #[inline(always)] fn new(v: T) -> ArcK { ArcK::new_from_inner(Arc::new(v)) } #[inline(always)] fn from_box(v: Box) -> ArcK { ArcK::new_from_inner::(Arc::from(v)) } #[inline(always)] unsafe fn as_ptr(&self) -> *const T { Arc::as_ptr(self.as_inner_ref()) } #[inline(always)] unsafe fn deref(&self) -> &T { self.as_inner_ref::().as_ref() } #[inline(always)] unsafe fn try_unwrap(self) -> Result { Arc::try_unwrap(self.take_inner()).map_err(ArcK::new_from_inner) } #[inline(always)] unsafe fn get_mut(&mut self) -> Option<&mut T> { Arc::get_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn make_mut(&mut self) -> &mut T { Arc::make_mut(self.as_inner_mut()) } #[inline(always)] unsafe fn strong_count(&self) -> usize { Arc::strong_count(self.as_inner_ref::()) } #[inline(always)] unsafe fn clone(&self) -> ArcK { ArcK { inner: ManuallyDrop::new(Arc::clone(self.as_inner_ref())) } } #[inline(always)] unsafe fn drop(&mut self) { ptr::drop_in_place::>(self.as_inner_mut()); } } impl Debug for ArcK { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { f.write_str("ArcK") } } #[cfg(test)] mod test; archery/src/shared_pointer/kind/mod.rs0000644000175000017500000000461514661133735021053 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use core::fmt::Debug; /// Trait for [type constructors](https://en.wikipedia.org/wiki/Type_constructor) of /// reference-counting pointers. /// /// # Safety /// /// `T` may be `!`[`Unpin`], and [`SharedPointer`][1] may be held in a pinned /// form ([`Pin`][2]`>`). /// As such, the implementation of this trait must uphold the pinning invariants /// for `T` while it's held in `Self`. Specifically, this necessitates the /// following: /// /// - `&mut T` is only exposed through the trait methods returning `&mut T`. /// /// - The implementor must not move out the contained `T` unless the semantics /// of trait methods demands that. /// /// - [`Self::drop`] drops `T` in place. /// /// [1]: crate::shared_pointer::SharedPointer /// [2]: core::pin::Pin // // There are two conditions for types implementing this trait to be used in a safe way: // // 1. Always use the correct type `T`. // 2. Make sure that you use it wrapped in something that derives the correct auto-traits taking // into account the type of `T`. // // To elaborate on point 2: a `ArcK` will always implement `Send + Sync`, but that // is only safe if the actually type that `ArcK` holds is in fact `Send + Sync`. // This means that a safe wrapper around this type must make sure it does not implement // `Send + Sync` unless `T: Send + Sync`. This is holds true for `SharedPointer` since it has a // phantom field with `T`, thus the compiler will only make `SharedPointer` implement // `Send + Sync` if `T: Send + Sync`. pub unsafe trait SharedPointerKind: Sized + Debug { fn new(v: T) -> Self; fn from_box(v: Box) -> Self; unsafe fn as_ptr(&self) -> *const T; unsafe fn deref(&self) -> &T; unsafe fn try_unwrap(self) -> Result; unsafe fn get_mut(&mut self) -> Option<&mut T>; unsafe fn make_mut(&mut self) -> &mut T; unsafe fn strong_count(&self) -> usize; #[must_use] unsafe fn clone(&self) -> Self; unsafe fn drop(&mut self); } mod arc; #[cfg(feature = "triomphe")] mod arct; mod rc; use alloc::boxed::Box; #[doc(inline)] pub use arc::ArcK; #[cfg(feature = "triomphe")] #[doc(inline)] pub use arct::ArcTK; #[doc(inline)] pub use rc::RcK; archery/src/shared_pointer/test.rs0000644000175000017500000002124714661133735020326 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![allow(clippy::eq_op)] use super::*; use kind::ArcK; use kind::RcK; use static_assertions::assert_impl_all; use std::cell::Cell; use std::mem; use std::string::ToString; assert_impl_all!(SharedPointer: Send, Sync); #[test] fn test_as_ptr() { let x = SharedPointer::<&'static str, RcK>::new("hello"); let y = SharedPointer::clone(&x); let x_ptr: *const &'static str = SharedPointer::as_ptr(&x); assert_eq!(x_ptr, SharedPointer::as_ptr(&y)); assert_eq!(unsafe { *x_ptr }, "hello"); } #[test] fn test_deref() { let ptr_42: SharedPointer = SharedPointer::new(42); let ptr_box_dyn_hello: SharedPointer, RcK> = SharedPointer::new(Box::new("hello")); assert_eq!(*ptr_42, 42); assert_eq!(ptr_box_dyn_hello.to_string(), "hello"); assert_eq!(*Borrow::::borrow(&ptr_42), 42); assert_eq!(Borrow::>::borrow(&ptr_box_dyn_hello).to_string(), "hello"); assert_eq!(*ptr_42.as_ref(), 42); assert_eq!(ptr_box_dyn_hello.as_ref().to_string(), "hello"); } #[test] fn test_try_unwrap() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(SharedPointer::try_unwrap(ptr).unwrap(), 42); let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_clone = SharedPointer::clone(&ptr); let ptr_clone = SharedPointer::try_unwrap(ptr_clone).unwrap_err(); let ptr = SharedPointer::try_unwrap(ptr).unwrap_err(); assert_eq!(*ptr, 42); assert_eq!(*ptr_clone, 42); } #[test] fn test_get_mut() { let mut ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(*ptr, 42); *SharedPointer::get_mut(&mut ptr).unwrap() += 1; assert_eq!(*ptr, 43); let mut ptr_clone = SharedPointer::clone(&ptr); assert_eq!(SharedPointer::get_mut(&mut ptr), None); assert_eq!(SharedPointer::get_mut(&mut ptr_clone), None); mem::drop(ptr); *SharedPointer::get_mut(&mut ptr_clone).unwrap() += 1; assert_eq!(*ptr_clone, 44); } #[test] fn test_strong_count() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(SharedPointer::strong_count(&ptr), 1); let ptr_clone = SharedPointer::clone(&ptr); assert_eq!(SharedPointer::strong_count(&ptr), 2); assert_eq!(SharedPointer::strong_count(&ptr_clone), 2); mem::drop(ptr); assert_eq!(SharedPointer::strong_count(&ptr_clone), 1); } #[test] fn test_ptr_eq() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_same_content: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_clone: SharedPointer<_, _> = SharedPointer::clone(&ptr); assert!(SharedPointer::ptr_eq(&ptr, &ptr)); assert!(!SharedPointer::ptr_eq(&ptr, &ptr_same_content)); assert!(SharedPointer::ptr_eq(&ptr, &ptr_clone)); } #[test] fn test_make_mut() { let mut ptr: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(*ptr, 42); *SharedPointer::make_mut(&mut ptr) += 1; assert_eq!(*ptr, 43); // Clone to force make_mut to clone the data. let mut ptr_clone = SharedPointer::clone(&ptr); assert_eq!(*ptr_clone, 43); *SharedPointer::make_mut(&mut ptr_clone) += 1; assert_eq!(*ptr, 43); assert_eq!(*ptr_clone, 44); *SharedPointer::make_mut(&mut ptr) *= 2; assert_eq!(*ptr, 2 * 43); assert_eq!(*ptr_clone, 44); mem::drop(ptr); assert_eq!(*ptr_clone, 44); } #[test] fn test_clone() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(Cell::new(42)); let ptr_clone = SharedPointer::clone(&ptr); assert_eq!(ptr.get(), 42); assert_eq!(ptr_clone.get(), 42); ptr_clone.set(3); assert_eq!(ptr.get(), 3); assert_eq!(ptr_clone.get(), 3); mem::drop(ptr); assert_eq!(ptr_clone.get(), 3); } fn hash(pointer: &SharedPointer) -> u64 { let mut hasher = std::collections::hash_map::DefaultHasher::new(); pointer.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let ptr_42: SharedPointer<_, RcK> = SharedPointer::new(42); let ptr_hello: SharedPointer<_, RcK> = SharedPointer::new("hello"); assert_eq!(hash(&ptr_42), hash(&SharedPointer::<_, RcK>::new(42))); assert_eq!(hash(&ptr_hello), hash(&SharedPointer::<_, RcK>::new("hello"))); } #[test] fn test_hash_pointer_kind_consistent() { let ptr_hello_rc: SharedPointer<_, RcK> = SharedPointer::new("hello"); let ptr_hello_arc: SharedPointer<_, ArcK> = SharedPointer::new("hello"); assert_eq!(hash(&ptr_hello_rc), hash(&ptr_hello_arc)); } #[allow(clippy::nonminimal_bool)] #[test] fn test_eq() { let ptr_22: SharedPointer<_, RcK> = SharedPointer::new(22); let ptr_42: SharedPointer<_, RcK> = SharedPointer::new(42); assert!(ptr_22 == SharedPointer::<_, RcK>::new(22)); assert!(ptr_22 == SharedPointer::<_, ArcK>::new(22)); assert!(ptr_22 == ptr_22); assert!(!(ptr_22 == SharedPointer::<_, RcK>::new(42))); assert!(!(ptr_22 == SharedPointer::<_, ArcK>::new(42))); assert!(!(ptr_22 == ptr_42)); assert!(ptr_22 != SharedPointer::<_, RcK>::new(42)); assert!(ptr_22 != SharedPointer::<_, ArcK>::new(42)); assert!(ptr_22 != ptr_42); assert!(!(ptr_22 != SharedPointer::<_, RcK>::new(22))); assert!(!(ptr_22 != SharedPointer::<_, ArcK>::new(22))); assert!(!(ptr_22 != ptr_22)); } #[allow(clippy::cognitive_complexity)] #[allow(clippy::nonminimal_bool)] #[test] fn test_ord() { let ptr_22: SharedPointer<_, RcK> = SharedPointer::new(22); let ptr_42: SharedPointer<_, RcK> = SharedPointer::new(42); assert_eq!(ptr_22.partial_cmp(&SharedPointer::<_, RcK>::new(22)), Some(Ordering::Equal)); assert_eq!(ptr_22.partial_cmp(&SharedPointer::<_, RcK>::new(42)), Some(Ordering::Less)); assert_eq!(ptr_42.partial_cmp(&SharedPointer::<_, RcK>::new(22)), Some(Ordering::Greater)); assert_eq!(ptr_22.cmp(&SharedPointer::<_, RcK>::new(22)), Ordering::Equal); assert_eq!(ptr_22.cmp(&SharedPointer::<_, RcK>::new(42)), Ordering::Less); assert_eq!(ptr_42.cmp(&SharedPointer::<_, RcK>::new(22)), Ordering::Greater); assert!(ptr_22 < SharedPointer::<_, RcK>::new(42)); assert!(ptr_22 < SharedPointer::<_, ArcK>::new(42)); assert!(ptr_22 < ptr_42); assert!(!(ptr_42 < SharedPointer::<_, RcK>::new(22))); assert!(!(ptr_42 < SharedPointer::<_, ArcK>::new(22))); assert!(!(ptr_42 < ptr_22)); assert!(!(ptr_22 < ptr_22)); assert!(ptr_22 <= SharedPointer::<_, RcK>::new(42)); assert!(ptr_22 <= SharedPointer::<_, ArcK>::new(42)); assert!(ptr_22 <= ptr_42); assert!(ptr_22 <= ptr_22); assert!(!(ptr_42 <= SharedPointer::<_, RcK>::new(22))); assert!(!(ptr_42 <= SharedPointer::<_, ArcK>::new(22))); assert!(!(ptr_42 <= ptr_22)); assert!(ptr_42 > SharedPointer::<_, RcK>::new(22)); assert!(ptr_42 > SharedPointer::<_, ArcK>::new(22)); assert!(ptr_42 > ptr_22); assert!(!(ptr_22 > SharedPointer::<_, RcK>::new(42))); assert!(!(ptr_22 > SharedPointer::<_, ArcK>::new(42))); assert!(!(ptr_22 > ptr_42)); assert!(!(ptr_42 > ptr_42)); assert!(ptr_42 >= SharedPointer::<_, RcK>::new(22)); assert!(ptr_42 >= SharedPointer::<_, ArcK>::new(22)); assert!(ptr_42 >= ptr_22); assert!(ptr_42 >= ptr_42); assert!(!(ptr_22 >= SharedPointer::<_, RcK>::new(42))); assert!(!(ptr_22 >= SharedPointer::<_, ArcK>::new(42))); assert!(!(ptr_22 >= ptr_42)); } #[test] fn test_default() { let ptr: SharedPointer = SharedPointer::default(); assert_eq!(*ptr, 0); } #[test] fn test_from_box_t() { let ptr: SharedPointer = SharedPointer::from(Box::new(42)); assert_eq!(*ptr, 42); } #[test] fn test_from_t() { let ptr: SharedPointer = SharedPointer::from(42); assert_eq!(*ptr, 42); } #[test] fn test_debug() { let ptr: SharedPointer<_, RcK> = SharedPointer::new([1, 2, 3]); assert_eq!(format!("{ptr:?}"), "[1, 2, 3]"); } #[cfg(not(miri))] // Miri doesn't like this one. #[test] fn test_fmt_pointer() { let ptr: SharedPointer<_, RcK> = SharedPointer::new(314); assert_eq!(format!("{ptr:p}"), format!("{:p}", ptr.deref() as *const i32)); } #[test] fn test_display() { let ptr: SharedPointer<_, RcK> = SharedPointer::new("hello"); assert_eq!(format!("{ptr}"), "hello"); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let ptr: SharedPointer<_, RcK> = SharedPointer::new("hello"); let encoded = serialize(&ptr).unwrap(); let decoded: SharedPointer<_, RcK> = deserialize(&encoded).unwrap(); pretty_assertions::assert_eq!(ptr, decoded); } archery/src/shared_pointer/mod.rs0000644000175000017500000002210614661133735020121 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::shared_pointer::kind::SharedPointerKind; use alloc::boxed::Box; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt; use core::fmt::Debug; use core::fmt::Display; use core::fmt::Formatter; use core::hash::Hash; use core::hash::Hasher; use core::marker::PhantomData; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::pin::Pin; use core::ptr; /// Pointer to shared data with reference-counting. /// /// The type parameter `P` is a [type constructor](https://en.wikipedia.org/wiki/Type_constructor) /// of the underlying pointer type, offering a way to abstraction over [`Rc`](alloc::rc::Rc) and /// [`Arc`](alloc::sync::Arc) smart pointers. /// This allows you to create data structures where the pointer type is parameterizable, so you can /// [avoid the overhead of `Arc`](alloc::sync::Arc#thread-safety) /// when you don’t need to share data across threads. /// /// # Example /// /// Declare a data structure with the pointer kind as a type parameter bounded by /// [`SharedPointerKind`]: /// /// ```rust /// use archery::*; /// /// struct KeyValuePair { /// pub key: SharedPointer, /// pub value: SharedPointer, /// } /// /// impl KeyValuePair { /// fn new(key: K, value: V) -> KeyValuePair { /// KeyValuePair { /// key: SharedPointer::new(key), /// value: SharedPointer::new(value), /// } /// } /// } /// ``` /// /// To use it just plug-in the kind of pointer you want: /// /// ```rust /// # use archery::*; /// # /// # struct KeyValuePair { /// # pub key: SharedPointer, /// # pub value: SharedPointer, /// # } /// # /// # impl KeyValuePair { /// # fn new(key: K, value: V) -> KeyValuePair { /// # KeyValuePair { /// # key: SharedPointer::new(key), /// # value: SharedPointer::new(value), /// # } /// # } /// # } /// # /// let pair: KeyValuePair<_, _, RcK> = /// KeyValuePair::new("António Variações", 1944); /// /// assert_eq!(*pair.value, 1944); /// ``` pub struct SharedPointer where P: SharedPointerKind, { ptr: ManuallyDrop

, _phantom_t: PhantomData, _phantom_no_send_sync: PhantomData<*mut ()>, } unsafe impl Send for SharedPointer where P: SharedPointerKind {} unsafe impl Sync for SharedPointer where P: SharedPointerKind {} impl Unpin for SharedPointer where P: SharedPointerKind {} impl SharedPointer where P: SharedPointerKind, { #[inline(always)] fn new_from_inner(ptr: P) -> SharedPointer { SharedPointer { ptr: ManuallyDrop::new(ptr), _phantom_t: PhantomData, _phantom_no_send_sync: PhantomData, } } #[inline(always)] pub fn new(v: T) -> SharedPointer { SharedPointer::new_from_inner(P::new::(v)) } #[inline(always)] pub fn pin(v: T) -> Pin> { unsafe { Pin::new_unchecked(Self::new(v)) } } #[inline(always)] pub fn as_ptr(this: &Self) -> *const T { unsafe { this.ptr.as_ptr::() } } #[inline(always)] pub fn try_unwrap(mut this: SharedPointer) -> Result> { let ptr: P = unsafe { ManuallyDrop::take(&mut this.ptr) }; mem::forget(this); unsafe { ptr.try_unwrap::() }.map_err(SharedPointer::new_from_inner) } #[inline(always)] pub fn get_mut(this: &mut SharedPointer) -> Option<&mut T> { unsafe { this.ptr.get_mut::() } } #[inline(always)] pub fn strong_count(this: &Self) -> usize { unsafe { this.ptr.strong_count::() } } #[inline(always)] pub fn ptr_eq( this: &SharedPointer, other: &SharedPointer, ) -> bool { ptr::eq(this.deref(), other.deref()) } } impl SharedPointer where T: Clone, P: SharedPointerKind, { #[inline(always)] pub fn make_mut(this: &mut SharedPointer) -> &mut T { unsafe { this.ptr.make_mut::() } } } impl Default for SharedPointer where T: Default, P: SharedPointerKind, { #[inline(always)] fn default() -> SharedPointer { SharedPointer::new(Default::default()) } } impl Deref for SharedPointer where P: SharedPointerKind, { type Target = T; #[inline(always)] fn deref(&self) -> &T { unsafe { self.ptr.deref().deref() } } } impl Borrow for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn borrow(&self) -> &T { self.deref() } } impl AsRef for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn as_ref(&self) -> &T { self.deref() } } impl Clone for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn clone(&self) -> SharedPointer { SharedPointer::new_from_inner(unsafe { self.ptr.deref().clone::() }) } } impl Hash for SharedPointer where T: Hash, P: SharedPointerKind, { #[inline(always)] fn hash(&self, state: &mut H) { self.deref().hash(state); } } impl PartialEq> for SharedPointer where T: PartialEq, P: SharedPointerKind, PO: SharedPointerKind, { #[inline(always)] fn eq(&self, other: &SharedPointer) -> bool { self.deref().eq(other.deref()) } #[inline(always)] fn ne(&self, other: &SharedPointer) -> bool { self.deref().ne(other.deref()) } } impl Eq for SharedPointer where T: Eq, P: SharedPointerKind, { } impl PartialOrd> for SharedPointer where T: PartialOrd, P: SharedPointerKind, PO: SharedPointerKind, { #[inline(always)] fn partial_cmp(&self, other: &SharedPointer) -> Option { self.deref().partial_cmp(other.deref()) } #[inline(always)] fn lt(&self, other: &SharedPointer) -> bool { self.deref().lt(other.deref()) } #[inline(always)] fn le(&self, other: &SharedPointer) -> bool { self.deref().le(other.deref()) } #[inline(always)] fn gt(&self, other: &SharedPointer) -> bool { self.deref().gt(other.deref()) } #[inline(always)] fn ge(&self, other: &SharedPointer) -> bool { self.deref().ge(other.deref()) } } impl Ord for SharedPointer where T: Ord, P: SharedPointerKind, { #[inline(always)] fn cmp(&self, other: &SharedPointer) -> Ordering { self.deref().cmp(other.deref()) } } impl From for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn from(other: T) -> SharedPointer { SharedPointer::new(other) } } impl From> for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn from(v: Box) -> SharedPointer { SharedPointer::new_from_inner(P::from_box(v)) } } impl Debug for SharedPointer where T: Debug, P: SharedPointerKind, { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { Debug::fmt(self.deref(), f) } } impl fmt::Pointer for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&core::ptr::addr_of!(**self), f) } } impl Display for SharedPointer where T: Display, P: SharedPointerKind, { #[inline(always)] fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> { Display::fmt(self.deref(), f) } } impl Drop for SharedPointer where P: SharedPointerKind, { #[inline(always)] fn drop(&mut self) { unsafe { self.ptr.drop::(); } } } pub mod kind; #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer}; use ::serde::ser::{Serialize, Serializer}; impl Serialize for SharedPointer where T: Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { self.as_ref().serialize(serializer) } } impl<'de, T, P> Deserialize<'de> for SharedPointer where T: Deserialize<'de>, P: SharedPointerKind, { fn deserialize>( deserializer: D, ) -> Result, D::Error> { T::deserialize(deserializer).map(SharedPointer::new) } } } #[cfg(test)] mod test; archery/src/lib.rs0000644000175000017500000001235014661133735015102 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![no_std] #![cfg_attr(feature = "fatal-warnings", deny(warnings))] // Note: If you change this remember to update `README.md`. To do so run `cargo rdme`. //! `archery` is a rust library that offers a way to abstraction over //! [`Rc`](::alloc::rc::Rc) and //! [`Arc`](::alloc::sync::Arc) smart pointers. //! This allows you to create data structures where the pointer type is parameterizable, so you can //! [avoid the overhead of `Arc`](::alloc::sync::Arc#thread-safety) //! when you don’t need to share data across threads. //! //! In languages that supports //! [higher-kinded polymorphism](https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polymorphism) //! this would be simple to achieve without any library, but //! [rust does not support that yet](https://github.com/rust-lang/rfcs/issues/324). //! To mimic higher-kinded polymorphism `archery` implements the approach suggested by //! Joshua Liebow-Feeser in //! “[Rust has higher kinded types already… sort of](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/)”. //! While [other approaches](#alternative-approaches) exist, they seem to always offer poor //! ergonomics for the user. //! //! # Setup //! //! To use `archery` add the following to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! archery = "" //! ``` //! //! # Using `archery` //! //! `archery` defines a [`SharedPointer`](crate::shared_pointer::SharedPointer) //! that receives the [kind of pointer](crate::shared_pointer::kind::SharedPointerKind) //! as a type parameter. This gives you a convenient and ergonomic way to abstract the pointer //! type away. //! //! ## Example //! //! Declare a data structure with the pointer kind as a type parameter bounded by //! [`SharedPointerKind`](crate::shared_pointer::kind::SharedPointerKind): //! //! ```rust //! use archery::*; //! //! struct KeyValuePair { //! pub key: SharedPointer, //! pub value: SharedPointer, //! } //! //! impl KeyValuePair { //! fn new(key: K, value: V) -> KeyValuePair { //! KeyValuePair { //! key: SharedPointer::new(key), //! value: SharedPointer::new(value), //! } //! } //! } //! ``` //! //! To use it just plug-in the kind of pointer you want: //! //! ```rust //! # use archery::*; //! # //! # struct KeyValuePair { //! # pub key: SharedPointer, //! # pub value: SharedPointer, //! # } //! # //! # impl KeyValuePair { //! # fn new(key: K, value: V) -> KeyValuePair { //! # KeyValuePair { //! # key: SharedPointer::new(key), //! # value: SharedPointer::new(value), //! # } //! # } //! # } //! # //! let pair: KeyValuePair<_, _, RcK> = //! KeyValuePair::new("António Variações", 1944); //! //! assert_eq!(*pair.value, 1944); //! ``` //! //! ## `triomphe::Arc` //! //! You can also use [`triomphe::Arc`](https://docs.rs/triomphe/latest/triomphe/struct.Arc.html) //! as the backing implementation of a [`SharedPointer`](crate::shared_pointer::SharedPointer). //! This is generally faster than [`std::sync::Arc`](::alloc::sync::Arc). //! Read [`triomphe`’s crate documentation](https://docs.rs/triomphe/latest/triomphe/) to learn more //! about it. //! //! To use it you need to enable the `triomphe` feature in `archery`. Use `ArcTK` as the pointer //! kind in [`SharedPointer`](crate::shared_pointer::SharedPointer). //! //! ## Serialization //! //! We support serialization through [serde](https://crates.io/crates/serde). To use it //! enable the `serde` feature. To do so change the archery dependency in your `Cargo.toml` to //! //! ```toml //! [dependencies] //! archery = { version = "", features = ["serde"] } //! ``` //! # Limitations //! //! Currently it is not possible to have unsized types inside a //! [`SharedPointer`](crate::shared_pointer::SharedPointer). As a workaround you can put the //! unsized type inside a [`Box`](::alloc::boxed::Box). //! //! # Alternative approaches //! //! An alternative to the approach taken by `archery` is to use traits with associated types to encode //! type-level functions. This has been suggested //! [multiple](https://github.com/orium/rpds/issues/7#issuecomment-362635901) //! [times](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/#comment-4160863400), //! but offers ugly ergonomics (see //! [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L153) //! and [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L249)). extern crate alloc; #[cfg(test)] #[macro_use] extern crate std; pub mod shared_pointer; pub use shared_pointer::SharedPointer; pub use shared_pointer::kind::SharedPointerKind; #[doc(no_inline)] pub use shared_pointer::kind::ArcK; #[cfg(feature = "triomphe")] #[doc(no_inline)] pub use shared_pointer::kind::ArcTK; #[doc(no_inline)] pub use shared_pointer::kind::RcK; archery/LICENSE.md0000644000175000017500000003627614661133735014620 0ustar jamespagejamespageMozilla Public License Version 2.0 ================================== ### 1. Definitions **1.1. “Contributor”** means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. **1.2. “Contributor Version”** means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. **1.3. “Contribution”** means Covered Software of a particular Contributor. **1.4. “Covered Software”** means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. **1.5. “Incompatible With Secondary Licenses”** means * **(a)** that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or * **(b)** that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. **1.6. “Executable Form”** means any form of the work other than Source Code Form. **1.7. “Larger Work”** means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. **1.8. “License”** means this document. **1.9. “Licensable”** means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. **1.10. “Modifications”** means any of the following: * **(a)** any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or * **(b)** any new file in Source Code Form that contains any Covered Software. **1.11. “Patent Claims” of a Contributor** means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. **1.12. “Secondary License”** means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. **1.13. “Source Code Form”** means the form of the work preferred for making modifications. **1.14. “You” (or “Your”)** means an individual or a legal entity exercising rights under this License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means **(a)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(b)** ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. ### 2. License Grants and Conditions #### 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: * **(a)** under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and * **(b)** under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. #### 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. #### 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: * **(a)** for any code that a Contributor has removed from Covered Software; or * **(b)** for infringements caused by: **(i)** Your and any other third party's modifications of Covered Software, or **(ii)** the combination of its Contributions with other software (except as part of its Contributor Version); or * **(c)** under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). #### 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). #### 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. #### 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. #### 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. ### 3. Responsibilities #### 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. #### 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: * **(a)** such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and * **(b)** You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. #### 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). #### 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. #### 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. ### 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: **(a)** comply with the terms of this License to the maximum extent possible; and **(b)** describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. ### 5. Termination **5.1.** The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated **(a)** provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and **(b)** on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. **5.2.** If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. **5.3.** In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ### 6. Disclaimer of Warranty > Covered Software is provided under this License on an “as is” > basis, without warranty of any kind, either expressed, implied, or > statutory, including, without limitation, warranties that the > Covered Software is free of defects, merchantable, fit for a > particular purpose or non-infringing. The entire risk as to the > quality and performance of the Covered Software is with You. > Should any Covered Software prove defective in any respect, You > (not any Contributor) assume the cost of any necessary servicing, > repair, or correction. This disclaimer of warranty constitutes an > essential part of this License. No use of any Covered Software is > authorized under this License except under this disclaimer. ### 7. Limitation of Liability > Under no circumstances and under no legal theory, whether tort > (including negligence), contract, or otherwise, shall any > Contributor, or anyone who distributes Covered Software as > permitted above, be liable to You for any direct, indirect, > special, incidental, or consequential damages of any character > including, without limitation, damages for lost profits, loss of > goodwill, work stoppage, computer failure or malfunction, or any > and all other commercial damages or losses, even if such party > shall have been informed of the possibility of such damages. This > limitation of liability shall not apply to liability for death or > personal injury resulting from such party's negligence to the > extent applicable law prohibits such limitation. Some > jurisdictions do not allow the exclusion or limitation of > incidental or consequential damages, so this exclusion and > limitation may not apply to You. ### 8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. ### 9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. ### 10. Versions of the License #### 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. #### 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. #### 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). #### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. ## Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. ## Exhibit B - “Incompatible With Secondary Licenses” Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. archery/.cargo-checksum.json0000664000175000017500000000260314661133735017045 0ustar jamespagejamespage{"files":{"Cargo.toml":"5f21233ee79402656de319ca76f58914767741c7e828ae447dea916d6625a3ac","LICENSE.md":"e6b6566f085df5746515c6d7e2edcaec0d2b77d527ac40d91409d783fb6c8508","README.md":"2c98a47c49a07873c97824edb9729e810ed55827a5e208dec2e2758d7d1b134e","release-notes.md":"7951c8026f6fb40c389bda26ba72d25685b4c09bdc7730ef351d6ace91cbdd1b","src/lib.rs":"976adeb8261a16db129fd2360af401de61397a842787462abf93d4db2368fd93","src/shared_pointer/kind/arc/mod.rs":"e022d7eb472b8d31676560977c4e1872f894b16a087afa31f9ffe71db9bca9a4","src/shared_pointer/kind/arc/test.rs":"a5dd63cf8e25acd42db6c2561f67dfc4cae6669cea620ae6cef54a67f42232a6","src/shared_pointer/kind/arct/mod.rs":"0a99a8d7b0df12cbd2a75dc9faaef641ae9475bc78392120734c9ec5cb024428","src/shared_pointer/kind/arct/test.rs":"94b8487bc28df6ca57ca1778f8ffce3c7aa4a7027a65bd6f4e789e6be65b8651","src/shared_pointer/kind/mod.rs":"023c78aad4bafeeaf8126aabc0ec18f165ea0757563a5da201c14004bc85f218","src/shared_pointer/kind/rc/mod.rs":"4969cef62b06ddae8713470e54f1ec550dec3a7cdecf962b4dbcbac317ba719f","src/shared_pointer/kind/rc/test.rs":"bd5f2bfb67a2a7c16b2f1caed38dc0c1b7097b5a5f4fe7160458bc9219619962","src/shared_pointer/mod.rs":"356acb59f9cb46143e6e61d2d923142ade87e8ab7cc2b56556b422b3f56d8d38","src/shared_pointer/test.rs":"fb8c5e300717bdb5e7049120f0dc2c9575f80a05d0c619f8bfd5718ae1efdcd6"},"package":"8967cd1cc9e9e1954f644e14fbd6042fe9a37da96c52a67e44a2ac18261f8561"}archery/release-notes.md0000644000175000017500000000236114661133735016270 0ustar jamespagejamespage# Release notes ## 1.2.0 * Added support for serde. This gated behind the `serde` feature. ## 1.1.0 * Added support for `triomphe::Arc` as a pointer kind. This gated behind the `triomphe` feature. ## 1.0.0 * No changes. It’s just time to commit to a stable release :). ## 0.5.0 * Fix `Send`/`Sync` unsoundness in `SharedPointer`. See issue [#18](https://github.com/orium/archery/issues/18). * Added `SharedPointer::pin()`. * Added `SharedPointer::as_ptr()`. * Updated dependencies. * Updated to 2021 edition. ## 0.4.0 * Added support for `no_std`. ## 0.3.0 * Renamed `SharedPointerKindRc` and `SharedPointerKindArc` to `RcK` and `ArcK`, respectively. ## 0.2.1 * Minor fix in README. ## 0.2.0 * Added some functionality to `SharedPointer` that you would expect from `Rc`/`Arc`. * Functions: * `SharedPointer::try_unwrap()`. * `SharedPointer::get_mut()`. * `SharedPointer::strong_count()`. * `SharedPointer::ptr_eq()`. * Traits: * `Default`. * `From`. * `From>`. * `std::fmt::Pointer`. ## 0.1.0 * Initial release with `SharedPointer`, `SharedPointerKind`, `SharedPointerKindRc`, and `SharedPointerKindArc`. * Functionality exposed from the underlying pointers: `deref()`, `make_mut()`, `clone()`. autocfg/0000775000175000017500000000000014661133735013173 5ustar jamespagejamespageautocfg/README.md0000644000175000017500000000633614661133735014460 0ustar jamespagejamespageautocfg ======= [![autocfg crate](https://img.shields.io/crates/v/autocfg.svg)](https://crates.io/crates/autocfg) [![autocfg documentation](https://docs.rs/autocfg/badge.svg)](https://docs.rs/autocfg) ![minimum rustc 1.0](https://img.shields.io/badge/rustc-1.0+-red.svg) ![build status](https://github.com/cuviper/autocfg/workflows/master/badge.svg) A Rust library for build scripts to automatically configure code based on compiler support. Code snippets are dynamically tested to see if the `rustc` will accept them, rather than hard-coding specific version support. ## Usage Add this to your `Cargo.toml`: ```toml [build-dependencies] autocfg = "1" ``` Then use it in your `build.rs` script to detect compiler features. For example, to test for 128-bit integer support, it might look like: ```rust extern crate autocfg; fn main() { let ac = autocfg::new(); ac.emit_has_type("i128"); // (optional) We don't need to rerun for anything external. autocfg::rerun_path("build.rs"); } ``` If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that should only be used when the compiler supports it. ## Release Notes - 1.3.0 (2024-05-03) - Add `probe_raw` for direct control of the code that will be test-compiled. - Use wrappers when querying the `rustc` version information too. - 1.2.0 (2024-03-25) - Add `no_std` and `set_no_std` to control the use of `#![no_std]` in probes. - Use `RUSTC_WRAPPER` and `RUSTC_WORKSPACE_WRAPPER` when they are set. - 1.1.0 (2022-02-07) - Use `CARGO_ENCODED_RUSTFLAGS` when it is set. - 1.0.1 (2020-08-20) - Apply `RUSTFLAGS` for more `--target` scenarios, by @adamreichold. - 1.0.0 (2020-01-08) - 🎉 Release 1.0! 🎉 (no breaking changes) - Add `probe_expression` and `emit_expression_cfg` to test arbitrary expressions. - Add `probe_constant` and `emit_constant_cfg` to test arbitrary constant expressions. - 0.1.7 (2019-10-20) - Apply `RUSTFLAGS` when probing `$TARGET != $HOST`, mainly for sysroot, by @roblabla. - 0.1.6 (2019-08-19) - Add `probe`/`emit_sysroot_crate`, by @leo60228. - 0.1.5 (2019-07-16) - Mask some warnings from newer rustc. - 0.1.4 (2019-05-22) - Relax `std`/`no_std` probing to a warning instead of an error. - Improve `rustc` bootstrap compatibility. - 0.1.3 (2019-05-21) - Auto-detects if `#![no_std]` is needed for the `$TARGET`. - 0.1.2 (2019-01-16) - Add `rerun_env(ENV)` to print `cargo:rerun-if-env-changed=ENV`. - Add `rerun_path(PATH)` to print `cargo:rerun-if-changed=PATH`. ## Minimum Rust version policy This crate's minimum supported `rustc` version is `1.0.0`. Compatibility is its entire reason for existence, so this crate will be extremely conservative about raising this requirement. If this is ever deemed necessary, it will be treated as a major breaking change for semver purposes. ## License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) at your option. autocfg/examples/0000775000175000017500000000000014661133735015011 5ustar jamespagejamespageautocfg/examples/nightly.rs0000644000175000017500000000107714661133735017040 0ustar jamespagejamespageextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); // When this feature was stabilized, it also renamed the method to // `chunk_by`, so it's important to *use* the feature in your probe. let code = r#" #![feature(slice_group_by)] pub fn probe(slice: &[i32]) -> impl Iterator { slice.group_by(|a, b| a == b) } "#; if ac.probe_raw(code).is_ok() { autocfg::emit("has_slice_group_by"); } } autocfg/examples/paths.rs0000644000175000017500000000124014661133735016471 0ustar jamespagejamespageextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); // since ancient times... ac.emit_has_path("std::vec::Vec"); ac.emit_path_cfg("std::vec::Vec", "has_vec"); // rustc 1.10.0 ac.emit_has_path("std::panic::PanicInfo"); ac.emit_path_cfg("std::panic::PanicInfo", "has_panic_info"); // rustc 1.20.0 ac.emit_has_path("std::mem::ManuallyDrop"); ac.emit_path_cfg("std::mem::ManuallyDrop", "has_manually_drop"); // rustc 1.25.0 ac.emit_has_path("std::ptr::NonNull"); ac.emit_path_cfg("std::ptr::NonNull", "has_non_null"); } autocfg/examples/integers.rs0000644000175000017500000000035314661133735017176 0ustar jamespagejamespageextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); for i in 3..8 { ac.emit_has_type(&format!("i{}", 1 << i)); } } autocfg/examples/versions.rs0000644000175000017500000000033714661133735017230 0ustar jamespagejamespageextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); for i in 0..100 { ac.emit_rustc_version(1, i); } } autocfg/examples/traits.rs0000644000175000017500000000147214661133735016667 0ustar jamespagejamespageextern crate autocfg; fn main() { // Normally, cargo will set `OUT_DIR` for build scripts. let ac = autocfg::AutoCfg::with_dir("target").unwrap(); // since ancient times... ac.emit_has_trait("std::ops::Add"); ac.emit_trait_cfg("std::ops::Add", "has_ops"); // trait parameters have to be provided ac.emit_has_trait("std::borrow::Borrow"); ac.emit_trait_cfg("std::borrow::Borrow", "has_borrow"); // rustc 1.8.0 ac.emit_has_trait("std::ops::AddAssign"); ac.emit_trait_cfg("std::ops::AddAssign", "has_assign_ops"); // rustc 1.12.0 ac.emit_has_trait("std::iter::Sum"); ac.emit_trait_cfg("std::iter::Sum", "has_sum"); // rustc 1.28.0 ac.emit_has_trait("std::alloc::GlobalAlloc"); ac.emit_trait_cfg("std::alloc::GlobalAlloc", "has_global_alloc"); } autocfg/LICENSE-APACHE0000644000175000017500000002513714661133735015125 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. autocfg/Cargo.toml0000644000175000017500000000163614661133735015127 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] rust-version = "1.0" name = "autocfg" version = "1.3.0" authors = ["Josh Stone "] exclude = ["/.github/**"] description = "Automatic cfg for Rust compiler features" documentation = "https://docs.rs/autocfg/" readme = "README.md" keywords = [ "rustc", "build", "autoconf", ] categories = ["development-tools::build-utils"] license = "Apache-2.0 OR MIT" repository = "https://github.com/cuviper/autocfg" [dependencies] autocfg/tests/0000775000175000017500000000000014661133735014335 5ustar jamespagejamespageautocfg/tests/wrap_ignored0000755000175000017500000000044414661133735016743 0ustar jamespagejamespage#!/bin/bash for arg in "$@"; do case "$arg" in # Add our own version so we can check that the wrapper is used for that. "--version") echo "release: 12345.6789.0" ;; # Read all input so the writer doesn't get EPIPE when we exit. "-") read -d "" PROBE ;; esac done exit 0 autocfg/tests/rustflags.rs0000644000175000017500000000224014661133735016711 0ustar jamespagejamespageextern crate autocfg; use std::env; /// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS /// environment variables when running rustc. #[test] fn test_with_sysroot() { // Use the same path as this test binary. let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf(); env::set_var("OUT_DIR", &format!("{}", dir.display())); // If we have encoded rustflags, they take precedence, even if empty. env::set_var("CARGO_ENCODED_RUSTFLAGS", ""); env::set_var("RUSTFLAGS", &format!("-L {}", dir.display())); let ac = autocfg::AutoCfg::new().unwrap(); assert!(ac.probe_sysroot_crate("std")); assert!(!ac.probe_sysroot_crate("autocfg")); // Now try again with useful encoded args. env::set_var( "CARGO_ENCODED_RUSTFLAGS", &format!("-L\x1f{}", dir.display()), ); let ac = autocfg::AutoCfg::new().unwrap(); assert!(ac.probe_sysroot_crate("autocfg")); // Try the old-style RUSTFLAGS, ensuring HOST != TARGET. env::remove_var("CARGO_ENCODED_RUSTFLAGS"); env::set_var("HOST", "lol"); let ac = autocfg::AutoCfg::new().unwrap(); assert!(ac.probe_sysroot_crate("autocfg")); } autocfg/tests/wrappers.rs0000644000175000017500000000411214661133735016542 0ustar jamespagejamespageextern crate autocfg; use std::env; /// Tests that autocfg uses the RUSTC_WRAPPER and/or RUSTC_WORKSPACE_WRAPPER /// environment variables when running rustc. #[test] #[cfg(unix)] // we're using system binaries as wrappers fn test_wrappers() { fn set(name: &str, value: Option) { match value { Some(true) => env::set_var(name, "/usr/bin/env"), Some(false) => env::set_var(name, "/bin/false"), None => env::remove_var(name), } } // Use the same path as this test binary. let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf(); env::set_var("OUT_DIR", &format!("{}", dir.display())); // This is used as a heuristic to detect rust-lang/cargo#9601. env::set_var("CARGO_ENCODED_RUSTFLAGS", ""); // No wrapper, a good pass-through wrapper, and a bad wrapper. let variants = [None, Some(true), Some(false)]; for &workspace in &variants { for &rustc in &variants { set("RUSTC_WRAPPER", rustc); set("RUSTC_WORKSPACE_WRAPPER", workspace); let ac = autocfg::AutoCfg::new().unwrap(); if rustc == Some(false) || workspace == Some(false) { // Everything should fail with bad wrappers. assert!(!ac.probe_type("usize")); } else { // Try known good and bad types for the wrapped rustc. assert!(ac.probe_type("usize")); assert!(!ac.probe_type("mesize")); } // Either way, we should have found the inner rustc version. assert!(ac.probe_rustc_version(1, 0)); } } // Finally, make sure that `RUSTC_WRAPPER` is applied outermost // by using something that doesn't pass through at all. env::set_var("RUSTC_WRAPPER", "./tests/wrap_ignored"); env::set_var("RUSTC_WORKSPACE_WRAPPER", "/bin/false"); let ac = autocfg::AutoCfg::new().unwrap(); assert!(ac.probe_type("mesize")); // anything goes! // Make sure we also got the version from that wrapper. assert!(ac.probe_rustc_version(12345, 6789)); } autocfg/tests/no_std.rs0000644000175000017500000000145414661133735016173 0ustar jamespagejamespageextern crate autocfg; use std::env; /// Tests that we can control the use of `#![no_std]`. #[test] fn no_std() { // Clear the CI `TARGET`, if any, so we're just dealing with the // host target which always has `std` available. env::remove_var("TARGET"); // Use the same path as this test binary. let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf(); env::set_var("OUT_DIR", &format!("{}", dir.display())); let mut ac = autocfg::AutoCfg::new().unwrap(); assert!(!ac.no_std()); assert!(ac.probe_path("std::mem")); // `#![no_std]` was stabilized in Rust 1.6 if ac.probe_rustc_version(1, 6) { ac.set_no_std(true); assert!(ac.no_std()); assert!(!ac.probe_path("std::mem")); assert!(ac.probe_path("core::mem")); } } autocfg/LICENSE-MIT0000644000175000017500000000203614661133735014626 0ustar jamespagejamespageCopyright (c) 2018 Josh Stone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. autocfg/src/0000775000175000017500000000000014661133735013762 5ustar jamespagejamespageautocfg/src/rustc.rs0000644000175000017500000000525414661133735015474 0ustar jamespagejamespageuse std::env; use std::ffi::OsString; use std::path::PathBuf; use std::process::Command; use super::error::Error; use super::version::Version; #[derive(Clone, Debug)] pub struct Rustc { rustc: PathBuf, rustc_wrapper: Option, rustc_workspace_wrapper: Option, } impl Rustc { pub fn new() -> Self { Rustc { rustc: env::var_os("RUSTC") .unwrap_or_else(|| "rustc".into()) .into(), rustc_wrapper: get_rustc_wrapper(false), rustc_workspace_wrapper: get_rustc_wrapper(true), } } /// Build the command with possible wrappers. pub fn command(&self) -> Command { let mut rustc = self .rustc_wrapper .iter() .chain(self.rustc_workspace_wrapper.iter()) .chain(Some(&self.rustc)); let mut command = Command::new(rustc.next().unwrap()); for arg in rustc { command.arg(arg); } command } /// Try to get the `rustc` version. pub fn version(&self) -> Result { // Some wrappers like clippy-driver don't pass through version commands, // so we try to fall back to combinations without each wrapper. macro_rules! try_version { ($command:expr) => { if let Ok(value) = Version::from_command($command) { return Ok(value); } }; } let rustc = &self.rustc; if let Some(ref rw) = self.rustc_wrapper { if let Some(ref rww) = self.rustc_workspace_wrapper { try_version!(Command::new(rw).args(&[rww, rustc])); } try_version!(Command::new(rw).arg(rustc)); } if let Some(ref rww) = self.rustc_workspace_wrapper { try_version!(Command::new(rww).arg(rustc)); } Version::from_command(&mut Command::new(rustc)) } } fn get_rustc_wrapper(workspace: bool) -> Option { // We didn't really know whether the workspace wrapper is applicable until Cargo started // deliberately setting or unsetting it in rust-lang/cargo#9601. We'll use the encoded // rustflags as a proxy for that change for now, but we could instead check version 1.55. if workspace && env::var_os("CARGO_ENCODED_RUSTFLAGS").is_none() { return None; } let name = if workspace { "RUSTC_WORKSPACE_WRAPPER" } else { "RUSTC_WRAPPER" }; if let Some(wrapper) = env::var_os(name) { // NB: `OsStr` didn't get `len` or `is_empty` until 1.9. if wrapper != OsString::new() { return Some(wrapper.into()); } } None } autocfg/src/lib.rs0000644000175000017500000004326114661133735015102 0ustar jamespagejamespage//! A Rust library for build scripts to automatically configure code based on //! compiler support. Code snippets are dynamically tested to see if the `rustc` //! will accept them, rather than hard-coding specific version support. //! //! //! ## Usage //! //! Add this to your `Cargo.toml`: //! //! ```toml //! [build-dependencies] //! autocfg = "1" //! ``` //! //! Then use it in your `build.rs` script to detect compiler features. For //! example, to test for 128-bit integer support, it might look like: //! //! ```rust //! extern crate autocfg; //! //! fn main() { //! # // Normally, cargo will set `OUT_DIR` for build scripts. //! # std::env::set_var("OUT_DIR", "target"); //! let ac = autocfg::new(); //! ac.emit_has_type("i128"); //! //! // (optional) We don't need to rerun for anything external. //! autocfg::rerun_path("build.rs"); //! } //! ``` //! //! If the type test succeeds, this will write a `cargo:rustc-cfg=has_i128` line //! for Cargo, which translates to Rust arguments `--cfg has_i128`. Then in the //! rest of your Rust code, you can add `#[cfg(has_i128)]` conditions on code that //! should only be used when the compiler supports it. //! //! ## Caution //! //! Many of the probing methods of `AutoCfg` document the particular template they //! use, **subject to change**. The inputs are not validated to make sure they are //! semantically correct for their expected use, so it's _possible_ to escape and //! inject something unintended. However, such abuse is unsupported and will not //! be considered when making changes to the templates. #![deny(missing_debug_implementations)] #![deny(missing_docs)] // allow future warnings that can't be fixed while keeping 1.0 compatibility #![allow(unknown_lints)] #![allow(bare_trait_objects)] #![allow(ellipsis_inclusive_range_patterns)] /// Local macro to avoid `std::try!`, deprecated in Rust 1.39. macro_rules! try { ($result:expr) => { match $result { Ok(value) => value, Err(error) => return Err(error), } }; } use std::env; use std::ffi::OsString; use std::fmt::Arguments; use std::fs; use std::io::{stderr, Write}; use std::path::{Path, PathBuf}; use std::process::Stdio; #[allow(deprecated)] use std::sync::atomic::ATOMIC_USIZE_INIT; use std::sync::atomic::{AtomicUsize, Ordering}; mod error; pub use error::Error; mod rustc; use rustc::Rustc; mod version; use version::Version; #[cfg(test)] mod tests; /// Helper to detect compiler features for `cfg` output in build scripts. #[derive(Clone, Debug)] pub struct AutoCfg { out_dir: PathBuf, rustc: Rustc, rustc_version: Version, target: Option, no_std: bool, rustflags: Vec, } /// Writes a config flag for rustc on standard out. /// /// This looks like: `cargo:rustc-cfg=CFG` /// /// Cargo will use this in arguments to rustc, like `--cfg CFG`. pub fn emit(cfg: &str) { println!("cargo:rustc-cfg={}", cfg); } /// Writes a line telling Cargo to rerun the build script if `path` changes. /// /// This looks like: `cargo:rerun-if-changed=PATH` /// /// This requires at least cargo 0.7.0, corresponding to rustc 1.6.0. Earlier /// versions of cargo will simply ignore the directive. pub fn rerun_path(path: &str) { println!("cargo:rerun-if-changed={}", path); } /// Writes a line telling Cargo to rerun the build script if the environment /// variable `var` changes. /// /// This looks like: `cargo:rerun-if-env-changed=VAR` /// /// This requires at least cargo 0.21.0, corresponding to rustc 1.20.0. Earlier /// versions of cargo will simply ignore the directive. pub fn rerun_env(var: &str) { println!("cargo:rerun-if-env-changed={}", var); } /// Creates a new `AutoCfg` instance. /// /// # Panics /// /// Panics if `AutoCfg::new()` returns an error. pub fn new() -> AutoCfg { AutoCfg::new().unwrap() } impl AutoCfg { /// Creates a new `AutoCfg` instance. /// /// # Common errors /// /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`. /// - The version output from `rustc` can't be parsed. /// - `OUT_DIR` is not set in the environment, or is not a writable directory. /// pub fn new() -> Result { match env::var_os("OUT_DIR") { Some(d) => Self::with_dir(d), None => Err(error::from_str("no OUT_DIR specified!")), } } /// Creates a new `AutoCfg` instance with the specified output directory. /// /// # Common errors /// /// - `rustc` can't be executed, from `RUSTC` or in the `PATH`. /// - The version output from `rustc` can't be parsed. /// - `dir` is not a writable directory. /// pub fn with_dir>(dir: T) -> Result { let rustc = Rustc::new(); let rustc_version = try!(rustc.version()); let target = env::var_os("TARGET"); // Sanity check the output directory let dir = dir.into(); let meta = try!(fs::metadata(&dir).map_err(error::from_io)); if !meta.is_dir() || meta.permissions().readonly() { return Err(error::from_str("output path is not a writable directory")); } let mut ac = AutoCfg { rustflags: rustflags(&target, &dir), out_dir: dir, rustc: rustc, rustc_version: rustc_version, target: target, no_std: false, }; // Sanity check with and without `std`. if !ac.probe_raw("").is_ok() { if ac.probe_raw("#![no_std]").is_ok() { ac.no_std = true; } else { // Neither worked, so assume nothing... let warning = b"warning: autocfg could not probe for `std`\n"; stderr().write_all(warning).ok(); } } Ok(ac) } /// Returns whether `AutoCfg` is using `#![no_std]` in its probes. /// /// This is automatically detected during construction -- if an empty probe /// fails while one with `#![no_std]` succeeds, then the attribute will be /// used for all further probes. This is usually only necessary when the /// `TARGET` lacks `std` altogether. If neither succeeds, `no_std` is not /// set, but that `AutoCfg` will probably only work for version checks. /// /// This attribute changes the implicit [prelude] from `std` to `core`, /// which may affect the paths you need to use in other probes. It also /// restricts some types that otherwise get additional methods in `std`, /// like floating-point trigonometry and slice sorting. /// /// See also [`set_no_std`](#method.set_no_std). /// /// [prelude]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute pub fn no_std(&self) -> bool { self.no_std } /// Sets whether `AutoCfg` should use `#![no_std]` in its probes. /// /// See also [`no_std`](#method.no_std). pub fn set_no_std(&mut self, no_std: bool) { self.no_std = no_std; } /// Tests whether the current `rustc` reports a version greater than /// or equal to "`major`.`minor`". pub fn probe_rustc_version(&self, major: usize, minor: usize) -> bool { self.rustc_version >= Version::new(major, minor, 0) } /// Sets a `cfg` value of the form `rustc_major_minor`, like `rustc_1_29`, /// if the current `rustc` is at least that version. pub fn emit_rustc_version(&self, major: usize, minor: usize) { if self.probe_rustc_version(major, minor) { emit(&format!("rustc_{}_{}", major, minor)); } } fn probe_fmt<'a>(&self, source: Arguments<'a>) -> Result<(), Error> { #[allow(deprecated)] static ID: AtomicUsize = ATOMIC_USIZE_INIT; let id = ID.fetch_add(1, Ordering::Relaxed); let mut command = self.rustc.command(); command .arg("--crate-name") .arg(format!("probe{}", id)) .arg("--crate-type=lib") .arg("--out-dir") .arg(&self.out_dir) .arg("--emit=llvm-ir"); if let Some(target) = self.target.as_ref() { command.arg("--target").arg(target); } command.args(&self.rustflags); command.arg("-").stdin(Stdio::piped()); let mut child = try!(command.spawn().map_err(error::from_io)); let mut stdin = child.stdin.take().expect("rustc stdin"); try!(stdin.write_fmt(source).map_err(error::from_io)); drop(stdin); match child.wait() { Ok(status) if status.success() => Ok(()), Ok(status) => Err(error::from_exit(status)), Err(error) => Err(error::from_io(error)), } } fn probe<'a>(&self, code: Arguments<'a>) -> bool { let result = if self.no_std { self.probe_fmt(format_args!("#![no_std]\n{}", code)) } else { self.probe_fmt(code) }; result.is_ok() } /// Tests whether the given code can be compiled as a Rust library. /// /// This will only return `Ok` if the compiler ran and exited successfully, /// per `ExitStatus::success()`. /// The code is passed to the compiler exactly as-is, notably not even /// adding the [`#![no_std]`][Self::no_std] attribute like other probes. /// /// Raw probes are useful for testing functionality that's not yet covered /// by the rest of the `AutoCfg` API. For example, the following attribute /// **must** be used at the crate level, so it wouldn't work within the code /// templates used by other `probe_*` methods. /// /// ``` /// # extern crate autocfg; /// # // Normally, cargo will set `OUT_DIR` for build scripts. /// # std::env::set_var("OUT_DIR", "target"); /// let ac = autocfg::new(); /// assert!(ac.probe_raw("#![no_builtins]").is_ok()); /// ``` /// /// Rust nightly features could be tested as well -- ideally including a /// code sample to ensure the unstable feature still works as expected. /// For example, `slice::group_by` was renamed to `chunk_by` when it was /// stabilized, even though the feature name was unchanged, so testing the /// `#![feature(..)]` alone wouldn't reveal that. For larger snippets, /// [`include_str!`] may be useful to load them from separate files. /// /// ``` /// # extern crate autocfg; /// # // Normally, cargo will set `OUT_DIR` for build scripts. /// # std::env::set_var("OUT_DIR", "target"); /// let ac = autocfg::new(); /// let code = r#" /// #![feature(slice_group_by)] /// pub fn probe(slice: &[i32]) -> impl Iterator { /// slice.group_by(|a, b| a == b) /// } /// "#; /// if ac.probe_raw(code).is_ok() { /// autocfg::emit("has_slice_group_by"); /// } /// ``` pub fn probe_raw(&self, code: &str) -> Result<(), Error> { self.probe_fmt(format_args!("{}", code)) } /// Tests whether the given sysroot crate can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// extern crate CRATE as probe; /// ``` pub fn probe_sysroot_crate(&self, name: &str) -> bool { // Note: `as _` wasn't stabilized until Rust 1.33 self.probe(format_args!("extern crate {} as probe;", name)) } /// Emits a config value `has_CRATE` if `probe_sysroot_crate` returns true. pub fn emit_sysroot_crate(&self, name: &str) { if self.probe_sysroot_crate(name) { emit(&format!("has_{}", mangle(name))); } } /// Tests whether the given path can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub use PATH; /// ``` pub fn probe_path(&self, path: &str) -> bool { self.probe(format_args!("pub use {};", path)) } /// Emits a config value `has_PATH` if `probe_path` returns true. /// /// Any non-identifier characters in the `path` will be replaced with /// `_` in the generated config value. pub fn emit_has_path(&self, path: &str) { if self.probe_path(path) { emit(&format!("has_{}", mangle(path))); } } /// Emits the given `cfg` value if `probe_path` returns true. pub fn emit_path_cfg(&self, path: &str, cfg: &str) { if self.probe_path(path) { emit(cfg); } } /// Tests whether the given trait can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub trait Probe: TRAIT + Sized {} /// ``` pub fn probe_trait(&self, name: &str) -> bool { self.probe(format_args!("pub trait Probe: {} + Sized {{}}", name)) } /// Emits a config value `has_TRAIT` if `probe_trait` returns true. /// /// Any non-identifier characters in the trait `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_trait(&self, name: &str) { if self.probe_trait(name) { emit(&format!("has_{}", mangle(name))); } } /// Emits the given `cfg` value if `probe_trait` returns true. pub fn emit_trait_cfg(&self, name: &str, cfg: &str) { if self.probe_trait(name) { emit(cfg); } } /// Tests whether the given type can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub type Probe = TYPE; /// ``` pub fn probe_type(&self, name: &str) -> bool { self.probe(format_args!("pub type Probe = {};", name)) } /// Emits a config value `has_TYPE` if `probe_type` returns true. /// /// Any non-identifier characters in the type `name` will be replaced with /// `_` in the generated config value. pub fn emit_has_type(&self, name: &str) { if self.probe_type(name) { emit(&format!("has_{}", mangle(name))); } } /// Emits the given `cfg` value if `probe_type` returns true. pub fn emit_type_cfg(&self, name: &str, cfg: &str) { if self.probe_type(name) { emit(cfg); } } /// Tests whether the given expression can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub fn probe() { let _ = EXPR; } /// ``` pub fn probe_expression(&self, expr: &str) -> bool { self.probe(format_args!("pub fn probe() {{ let _ = {}; }}", expr)) } /// Emits the given `cfg` value if `probe_expression` returns true. pub fn emit_expression_cfg(&self, expr: &str, cfg: &str) { if self.probe_expression(expr) { emit(cfg); } } /// Tests whether the given constant expression can be used. /// /// The test code is subject to change, but currently looks like: /// /// ```ignore /// pub const PROBE: () = ((), EXPR).0; /// ``` pub fn probe_constant(&self, expr: &str) -> bool { self.probe(format_args!("pub const PROBE: () = ((), {}).0;", expr)) } /// Emits the given `cfg` value if `probe_constant` returns true. pub fn emit_constant_cfg(&self, expr: &str, cfg: &str) { if self.probe_constant(expr) { emit(cfg); } } } fn mangle(s: &str) -> String { s.chars() .map(|c| match c { 'A'...'Z' | 'a'...'z' | '0'...'9' => c, _ => '_', }) .collect() } fn dir_contains_target( target: &Option, dir: &Path, cargo_target_dir: Option, ) -> bool { target .as_ref() .and_then(|target| { dir.to_str().and_then(|dir| { let mut cargo_target_dir = cargo_target_dir .map(PathBuf::from) .unwrap_or_else(|| PathBuf::from("target")); cargo_target_dir.push(target); cargo_target_dir .to_str() .map(|cargo_target_dir| dir.contains(cargo_target_dir)) }) }) .unwrap_or(false) } fn rustflags(target: &Option, dir: &Path) -> Vec { // Starting with rust-lang/cargo#9601, shipped in Rust 1.55, Cargo always sets // CARGO_ENCODED_RUSTFLAGS for any host/target build script invocation. This // includes any source of flags, whether from the environment, toml config, or // whatever may come in the future. The value is either an empty string, or a // list of arguments separated by the ASCII unit separator (US), 0x1f. if let Ok(a) = env::var("CARGO_ENCODED_RUSTFLAGS") { return if a.is_empty() { Vec::new() } else { a.split('\x1f').map(str::to_string).collect() }; } // Otherwise, we have to take a more heuristic approach, and we don't // support values from toml config at all. // // Cargo only applies RUSTFLAGS for building TARGET artifact in // cross-compilation environment. Sadly, we don't have a way to detect // when we're building HOST artifact in a cross-compilation environment, // so for now we only apply RUSTFLAGS when cross-compiling an artifact. // // See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030. if *target != env::var_os("HOST") || dir_contains_target(target, dir, env::var_os("CARGO_TARGET_DIR")) { if let Ok(rustflags) = env::var("RUSTFLAGS") { // This is meant to match how cargo handles the RUSTFLAGS environment variable. // See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441 return rustflags .split(' ') .map(str::trim) .filter(|s| !s.is_empty()) .map(str::to_string) .collect(); } } Vec::new() } autocfg/src/error.rs0000644000175000017500000000341614661133735015463 0ustar jamespagejamespageuse std::error; use std::fmt; use std::io; use std::num; use std::process; use std::str; /// A common error type for the `autocfg` crate. #[derive(Debug)] pub struct Error { kind: ErrorKind, } impl error::Error for Error { fn description(&self) -> &str { "AutoCfg error" } fn cause(&self) -> Option<&error::Error> { match self.kind { ErrorKind::Io(ref e) => Some(e), ErrorKind::Num(ref e) => Some(e), ErrorKind::Utf8(ref e) => Some(e), ErrorKind::Process(_) | ErrorKind::Other(_) => None, } } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match self.kind { ErrorKind::Io(ref e) => e.fmt(f), ErrorKind::Num(ref e) => e.fmt(f), ErrorKind::Utf8(ref e) => e.fmt(f), ErrorKind::Process(ref status) => { // Same message as the newer `ExitStatusError` write!(f, "process exited unsuccessfully: {}", status) } ErrorKind::Other(s) => s.fmt(f), } } } #[derive(Debug)] enum ErrorKind { Io(io::Error), Num(num::ParseIntError), Process(process::ExitStatus), Utf8(str::Utf8Error), Other(&'static str), } pub fn from_exit(status: process::ExitStatus) -> Error { Error { kind: ErrorKind::Process(status), } } pub fn from_io(e: io::Error) -> Error { Error { kind: ErrorKind::Io(e), } } pub fn from_num(e: num::ParseIntError) -> Error { Error { kind: ErrorKind::Num(e), } } pub fn from_utf8(e: str::Utf8Error) -> Error { Error { kind: ErrorKind::Utf8(e), } } pub fn from_str(s: &'static str) -> Error { Error { kind: ErrorKind::Other(s), } } autocfg/src/version.rs0000644000175000017500000000417414661133735016021 0ustar jamespagejamespageuse std::process::Command; use std::str; use super::{error, Error}; /// A version structure for making relative comparisons. #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Version { major: usize, minor: usize, patch: usize, } impl Version { /// Creates a `Version` instance for a specific `major.minor.patch` version. pub fn new(major: usize, minor: usize, patch: usize) -> Self { Version { major: major, minor: minor, patch: patch, } } pub fn from_command(command: &mut Command) -> Result { // Get rustc's verbose version let output = try!(command .args(&["--version", "--verbose"]) .output() .map_err(error::from_io)); if !output.status.success() { return Err(error::from_str("could not execute rustc")); } let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8)); // Find the release line in the verbose version output. let release = match output.lines().find(|line| line.starts_with("release: ")) { Some(line) => &line["release: ".len()..], None => return Err(error::from_str("could not find rustc release")), }; // Strip off any extra channel info, e.g. "-beta.N", "-nightly" let version = match release.find('-') { Some(i) => &release[..i], None => release, }; // Split the version into semver components. let mut iter = version.splitn(3, '.'); let major = try!(iter .next() .ok_or_else(|| error::from_str("missing major version"))); let minor = try!(iter .next() .ok_or_else(|| error::from_str("missing minor version"))); let patch = try!(iter .next() .ok_or_else(|| error::from_str("missing patch version"))); Ok(Version::new( try!(major.parse().map_err(error::from_num)), try!(minor.parse().map_err(error::from_num)), try!(patch.parse().map_err(error::from_num)), )) } } autocfg/src/tests.rs0000644000175000017500000001270614661133735015476 0ustar jamespagejamespageuse super::AutoCfg; use std::env; use std::path::Path; impl AutoCfg { fn core_std(&self, path: &str) -> String { let krate = if self.no_std { "core" } else { "std" }; format!("{}::{}", krate, path) } fn assert_std(&self, probe_result: bool) { assert_eq!(!self.no_std, probe_result); } fn assert_min(&self, major: usize, minor: usize, probe_result: bool) { assert_eq!(self.probe_rustc_version(major, minor), probe_result); } fn for_test() -> Result { match env::var_os("TESTS_TARGET_DIR") { Some(d) => Self::with_dir(d), None => Self::with_dir("target"), } } } #[test] fn autocfg_version() { let ac = AutoCfg::for_test().unwrap(); println!("version: {:?}", ac.rustc_version); assert!(ac.probe_rustc_version(1, 0)); } #[test] fn version_cmp() { use super::version::Version; let v123 = Version::new(1, 2, 3); assert!(Version::new(1, 0, 0) < v123); assert!(Version::new(1, 2, 2) < v123); assert!(Version::new(1, 2, 3) == v123); assert!(Version::new(1, 2, 4) > v123); assert!(Version::new(1, 10, 0) > v123); assert!(Version::new(2, 0, 0) > v123); } #[test] fn probe_add() { let ac = AutoCfg::for_test().unwrap(); let add = ac.core_std("ops::Add"); let add_rhs = add.clone() + ""; let add_rhs_output = add.clone() + ""; let dyn_add_rhs_output = "dyn ".to_string() + &*add_rhs_output; assert!(ac.probe_path(&add)); assert!(ac.probe_trait(&add)); assert!(ac.probe_trait(&add_rhs)); assert!(ac.probe_trait(&add_rhs_output)); ac.assert_min(1, 27, ac.probe_type(&dyn_add_rhs_output)); } #[test] fn probe_as_ref() { let ac = AutoCfg::for_test().unwrap(); let as_ref = ac.core_std("convert::AsRef"); let as_ref_str = as_ref.clone() + ""; let dyn_as_ref_str = "dyn ".to_string() + &*as_ref_str; assert!(ac.probe_path(&as_ref)); assert!(ac.probe_trait(&as_ref_str)); assert!(ac.probe_type(&as_ref_str)); ac.assert_min(1, 27, ac.probe_type(&dyn_as_ref_str)); } #[test] fn probe_i128() { let ac = AutoCfg::for_test().unwrap(); let i128_path = ac.core_std("i128"); ac.assert_min(1, 26, ac.probe_path(&i128_path)); ac.assert_min(1, 26, ac.probe_type("i128")); } #[test] fn probe_sum() { let ac = AutoCfg::for_test().unwrap(); let sum = ac.core_std("iter::Sum"); let sum_i32 = sum.clone() + ""; let dyn_sum_i32 = "dyn ".to_string() + &*sum_i32; ac.assert_min(1, 12, ac.probe_path(&sum)); ac.assert_min(1, 12, ac.probe_trait(&sum)); ac.assert_min(1, 12, ac.probe_trait(&sum_i32)); ac.assert_min(1, 12, ac.probe_type(&sum_i32)); ac.assert_min(1, 27, ac.probe_type(&dyn_sum_i32)); } #[test] fn probe_std() { let ac = AutoCfg::for_test().unwrap(); ac.assert_std(ac.probe_sysroot_crate("std")); } #[test] fn probe_alloc() { let ac = AutoCfg::for_test().unwrap(); ac.assert_min(1, 36, ac.probe_sysroot_crate("alloc")); } #[test] fn probe_bad_sysroot_crate() { let ac = AutoCfg::for_test().unwrap(); assert!(!ac.probe_sysroot_crate("doesnt_exist")); } #[test] fn probe_no_std() { let ac = AutoCfg::for_test().unwrap(); assert!(ac.probe_type("i32")); assert!(ac.probe_type("[i32]")); ac.assert_std(ac.probe_type("Vec")); } #[test] fn probe_expression() { let ac = AutoCfg::for_test().unwrap(); assert!(ac.probe_expression(r#""test".trim_left()"#)); ac.assert_min(1, 30, ac.probe_expression(r#""test".trim_start()"#)); ac.assert_std(ac.probe_expression("[1, 2, 3].to_vec()")); } #[test] fn probe_constant() { let ac = AutoCfg::for_test().unwrap(); assert!(ac.probe_constant("1 + 2 + 3")); ac.assert_min(1, 33, ac.probe_constant("{ let x = 1 + 2 + 3; x * x }")); ac.assert_min(1, 39, ac.probe_constant(r#""test".len()"#)); } #[test] fn probe_raw() { let ac = AutoCfg::for_test().unwrap(); let prefix = if ac.no_std { "#![no_std]\n" } else { "" }; let f = |s| format!("{}{}", prefix, s); // This attribute **must** be used at the crate level. assert!(ac.probe_raw(&f("#![no_builtins]")).is_ok()); assert!(ac.probe_raw(&f("#![deny(dead_code)] fn x() {}")).is_err()); assert!(ac.probe_raw(&f("#![allow(dead_code)] fn x() {}")).is_ok()); assert!(ac .probe_raw(&f("#![deny(dead_code)] pub fn x() {}")) .is_ok()); } #[test] fn dir_does_not_contain_target() { assert!(!super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new("/project/target/debug/build/project-ea75983148559682/out"), None, )); } #[test] fn dir_does_contain_target() { assert!(super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new( "/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out" ), None, )); } #[test] fn dir_does_not_contain_target_with_custom_target_dir() { assert!(!super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new("/project/custom/debug/build/project-ea75983148559682/out"), Some("custom".into()), )); } #[test] fn dir_does_contain_target_with_custom_target_dir() { assert!(super::dir_contains_target( &Some("x86_64-unknown-linux-gnu".into()), Path::new( "/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out" ), Some("custom".into()), )); } autocfg/.cargo-checksum.json0000664000175000017500000000323614661133735017043 0ustar jamespagejamespage{"files":{"Cargo.lock":"8e60b691c883629c1e19c8dad7c4c18cded1a85c2e8f2e2a77e7a96957f865a7","Cargo.toml":"f8c2d5675773b7ddff8801c3c17ff9d26e9632fe2027a6b81ceb7bda67d71bfd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"51238410cbbb06b149a794d954ff4d5943da566a97e71dc3aa8b5fa5a9b538b6","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/nightly.rs":"ac8b5a9aa1e04465e44f5053b3c899b635e07af058c73aa8b45176bf4b5912f9","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"fd8ff67c64f7cd1b9f81325a81de4baa34c39d6ae298bdb33f9829cc91acac39","src/lib.rs":"7b00cd501b52bab797bf047ada2a446e16fc2b8b05567670d8b8b7ada3179f55","src/rustc.rs":"a8a213ddb64a05c1a1af933bcb331a98879e942b167c33d8f94f9f60ebb14e29","src/tests.rs":"594a1cff6fef4a0f8b5f962a668fda4030db5005f37f01eeb06d692fc48a60df","src/version.rs":"4f7d23b36f01c7be1871be86c038d6cb4689e145d67c82d3793690e9aa05b133","tests/no_std.rs":"cc5619466c6e955552f30ed2f80ba8ddf45c3d5d257f628f54dedc0da978f6aa","tests/rustflags.rs":"5c8169b88216055019db61b5d7baf4abdf675e3b14b54f5037bb1e3acd0a5d3f","tests/wrap_ignored":"a9e241edf584a0702066b25bc15c5bbfd8a1019e14fb655fc4f47a67360065ca","tests/wrappers.rs":"e8eb0eb5ac28ecd9e3473b5ddc321b1d4d523a6fb0c072255ac37d40674aa35c"},"package":"0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"}autocfg/Cargo.lock0000644000175000017500000000022714661133735015077 0ustar jamespagejamespage# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "autocfg" version = "1.3.0" cc/0000775000175000017500000000000014661133735012130 5ustar jamespagejamespagecc/README.md0000644000175000017500000000204714661133735013410 0ustar jamespagejamespage# cc-rs A library for [Cargo build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html) to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo to link into the crate being built. This crate does not compile code itself; it calls out to the default compiler for the platform. This crate will automatically detect situations such as cross compilation and various environment variables and will build code appropriately. Refer to the [documentation](https://docs.rs/cc) for detailed usage instructions. ## License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in cc-rs by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. cc/LICENSE-APACHE0000644000175000017500000002513714661133735014062 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. cc/Cargo.toml0000644000175000017500000000257014661133735014062 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.53" name = "cc" version = "1.0.90" authors = ["Alex Crichton "] exclude = [ "/.github", "tests", "src/bin", ] description = """ A build-time dependency for Cargo build scripts to assist in invoking the native C compiler to compile native C code into a static archive to be linked into Rust code. """ homepage = "https://github.com/rust-lang/cc-rs" documentation = "https://docs.rs/cc" readme = "README.md" keywords = ["build-dependencies"] categories = ["development-tools::build-utils"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/cc-rs" [dependencies.jobserver] version = "0.1.20" optional = true default-features = false [dev-dependencies.tempfile] version = "3" [features] parallel = [ "libc", "jobserver", ] [target."cfg(unix)".dependencies.libc] version = "0.2.62" optional = true default-features = false cc/LICENSE-MIT0000644000175000017500000000204114661133735013557 0ustar jamespagejamespageCopyright (c) 2014 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cc/src/0000775000175000017500000000000014661133735012717 5ustar jamespagejamespagecc/src/command_helpers.rs0000644000175000017500000003253414661133735016432 0ustar jamespagejamespage//! Miscellaneous helpers for running commands use std::{ collections::hash_map, ffi::OsString, fmt::Display, fs, hash::Hasher, io::{self, Read, Write}, path::Path, process::{Child, ChildStderr, Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, Arc, }, }; use crate::{Error, ErrorKind, Object}; #[derive(Clone, Debug)] pub(crate) struct CargoOutput { pub(crate) metadata: bool, pub(crate) warnings: bool, pub(crate) debug: bool, checked_dbg_var: Arc, } impl CargoOutput { pub(crate) fn new() -> Self { Self { metadata: true, warnings: true, debug: std::env::var_os("CC_ENABLE_DEBUG_OUTPUT").is_some(), checked_dbg_var: Arc::new(AtomicBool::new(false)), } } pub(crate) fn print_metadata(&self, s: &dyn Display) { if self.metadata { println!("{}", s); } } pub(crate) fn print_warning(&self, arg: &dyn Display) { if self.warnings { println!("cargo:warning={}", arg); } } pub(crate) fn print_debug(&self, arg: &dyn Display) { if self.metadata && !self.checked_dbg_var.load(Ordering::Relaxed) { self.checked_dbg_var.store(true, Ordering::Relaxed); println!("cargo:rerun-if-env-changed=CC_ENABLE_DEBUG_OUTPUT"); } if self.debug { println!("{}", arg); } } fn stdio_for_warnings(&self) -> Stdio { if self.warnings { Stdio::piped() } else { Stdio::null() } } } pub(crate) struct StderrForwarder { inner: Option<(ChildStderr, Vec)>, #[cfg(feature = "parallel")] is_non_blocking: bool, #[cfg(feature = "parallel")] bytes_available_failed: bool, } const MIN_BUFFER_CAPACITY: usize = 100; impl StderrForwarder { pub(crate) fn new(child: &mut Child) -> Self { Self { inner: child .stderr .take() .map(|stderr| (stderr, Vec::with_capacity(MIN_BUFFER_CAPACITY))), #[cfg(feature = "parallel")] is_non_blocking: false, #[cfg(feature = "parallel")] bytes_available_failed: false, } } #[allow(clippy::uninit_vec)] fn forward_available(&mut self) -> bool { if let Some((stderr, buffer)) = self.inner.as_mut() { loop { let old_data_end = buffer.len(); // For non-blocking we check to see if there is data available, so we should try to // read at least that much. For blocking, always read at least the minimum amount. #[cfg(not(feature = "parallel"))] let to_reserve = MIN_BUFFER_CAPACITY; #[cfg(feature = "parallel")] let to_reserve = if self.is_non_blocking && !self.bytes_available_failed { match crate::parallel::stderr::bytes_available(stderr) { #[cfg(windows)] Ok(0) => return false, #[cfg(unix)] Ok(0) => { // On Unix, depending on the implementation, we may sometimes get 0 in a // loop (either there is data available or the pipe is broken), so // continue with the non-blocking read anyway. MIN_BUFFER_CAPACITY } #[cfg(windows)] Err(_) => { // On Windows, if we get an error then the pipe is broken, so flush // the buffer and bail. if !buffer.is_empty() { write_warning(&buffer[..]); } self.inner = None; return true; } #[cfg(unix)] Err(_) => { // On Unix, depending on the implementation, we may get spurious // errors so make a note not to use bytes_available again and try // the non-blocking read anyway. self.bytes_available_failed = true; MIN_BUFFER_CAPACITY } Ok(bytes_available) => MIN_BUFFER_CAPACITY.max(bytes_available), } } else { MIN_BUFFER_CAPACITY }; buffer.reserve(to_reserve); // SAFETY: 1) the length is set to the capacity, so we are never using memory beyond // the underlying buffer and 2) we always call `truncate` below to set the len back // to the initialized data. unsafe { buffer.set_len(buffer.capacity()); } match stderr.read(&mut buffer[old_data_end..]) { Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { // No data currently, yield back. buffer.truncate(old_data_end); return false; } Err(err) if err.kind() == std::io::ErrorKind::Interrupted => { // Interrupted, try again. buffer.truncate(old_data_end); } Ok(0) | Err(_) => { // End of stream: flush remaining data and bail. if old_data_end > 0 { write_warning(&buffer[..old_data_end]); } self.inner = None; return true; } Ok(bytes_read) => { buffer.truncate(old_data_end + bytes_read); let mut consumed = 0; for line in buffer.split_inclusive(|&b| b == b'\n') { // Only forward complete lines, leave the rest in the buffer. if let Some((b'\n', line)) = line.split_last() { consumed += line.len() + 1; write_warning(line); } } buffer.drain(..consumed); } } } } else { true } } #[cfg(feature = "parallel")] pub(crate) fn set_non_blocking(&mut self) -> Result<(), Error> { assert!(!self.is_non_blocking); #[cfg(unix)] if let Some((stderr, _)) = self.inner.as_ref() { crate::parallel::stderr::set_non_blocking(stderr)?; } self.is_non_blocking = true; Ok(()) } #[cfg(feature = "parallel")] fn forward_all(&mut self) { while !self.forward_available() {} } #[cfg(not(feature = "parallel"))] fn forward_all(&mut self) { let forward_result = self.forward_available(); assert!(forward_result, "Should have consumed all data"); } } fn write_warning(line: &[u8]) { let stdout = io::stdout(); let mut stdout = stdout.lock(); stdout.write_all(b"cargo:warning=").unwrap(); stdout.write_all(line).unwrap(); stdout.write_all(b"\n").unwrap(); } fn wait_on_child( cmd: &Command, program: &str, child: &mut Child, cargo_output: &CargoOutput, ) -> Result<(), Error> { StderrForwarder::new(child).forward_all(); let status = match child.wait() { Ok(s) => s, Err(e) => { return Err(Error::new( ErrorKind::ToolExecError, format!( "Failed to wait on spawned child process, command {:?} with args {:?}: {}.", cmd, program, e ), )); } }; cargo_output.print_debug(&status); if status.success() { Ok(()) } else { Err(Error::new( ErrorKind::ToolExecError, format!( "Command {:?} with args {:?} did not execute successfully (status code {}).", cmd, program, status ), )) } } /// Find the destination object path for each file in the input source files, /// and store them in the output Object. pub(crate) fn objects_from_files(files: &[Arc], dst: &Path) -> Result, Error> { let mut objects = Vec::with_capacity(files.len()); for file in files { let basename = file .file_name() .ok_or_else(|| { Error::new( ErrorKind::InvalidArgument, "No file_name for object file path!", ) })? .to_string_lossy(); let dirname = file .parent() .ok_or_else(|| { Error::new( ErrorKind::InvalidArgument, "No parent for object file path!", ) })? .to_string_lossy(); // Hash the dirname. This should prevent conflicts if we have multiple // object files with the same filename in different subfolders. let mut hasher = hash_map::DefaultHasher::new(); hasher.write(dirname.to_string().as_bytes()); let obj = dst .join(format!("{:016x}-{}", hasher.finish(), basename)) .with_extension("o"); match obj.parent() { Some(s) => fs::create_dir_all(s)?, None => { return Err(Error::new( ErrorKind::InvalidArgument, "dst is an invalid path with no parent", )); } }; objects.push(Object::new(file.to_path_buf(), obj)); } Ok(objects) } pub(crate) fn run( cmd: &mut Command, program: &str, cargo_output: &CargoOutput, ) -> Result<(), Error> { let mut child = spawn(cmd, program, cargo_output)?; wait_on_child(cmd, program, &mut child, cargo_output) } pub(crate) fn run_output( cmd: &mut Command, program: &str, cargo_output: &CargoOutput, ) -> Result, Error> { cmd.stdout(Stdio::piped()); let mut child = spawn(cmd, program, cargo_output)?; let mut stdout = vec![]; child .stdout .take() .unwrap() .read_to_end(&mut stdout) .unwrap(); wait_on_child(cmd, program, &mut child, cargo_output)?; Ok(stdout) } pub(crate) fn spawn( cmd: &mut Command, program: &str, cargo_output: &CargoOutput, ) -> Result { struct ResetStderr<'cmd>(&'cmd mut Command); impl Drop for ResetStderr<'_> { fn drop(&mut self) { // Reset stderr to default to release pipe_writer so that print thread will // not block forever. self.0.stderr(Stdio::inherit()); } } cargo_output.print_debug(&format_args!("running: {:?}", cmd)); let cmd = ResetStderr(cmd); let child = cmd.0.stderr(cargo_output.stdio_for_warnings()).spawn(); match child { Ok(child) => Ok(child), Err(ref e) if e.kind() == io::ErrorKind::NotFound => { let extra = if cfg!(windows) { " (see https://github.com/rust-lang/cc-rs#compile-time-requirements \ for help)" } else { "" }; Err(Error::new( ErrorKind::ToolNotFound, format!("Failed to find tool. Is `{}` installed?{}", program, extra), )) } Err(e) => Err(Error::new( ErrorKind::ToolExecError, format!( "Command {:?} with args {:?} failed to start: {:?}", cmd.0, program, e ), )), } } pub(crate) fn command_add_output_file( cmd: &mut Command, dst: &Path, cuda: bool, msvc: bool, clang: bool, gnu: bool, is_asm: bool, is_arm: bool, ) { if msvc && !clang && !gnu && !cuda && !(is_asm && is_arm) { let mut s = OsString::from("-Fo"); s.push(dst); cmd.arg(s); } else { cmd.arg("-o").arg(dst); } } #[cfg(feature = "parallel")] pub(crate) fn try_wait_on_child( cmd: &Command, program: &str, child: &mut Child, stdout: &mut dyn io::Write, stderr_forwarder: &mut StderrForwarder, ) -> Result, Error> { stderr_forwarder.forward_available(); match child.try_wait() { Ok(Some(status)) => { stderr_forwarder.forward_all(); let _ = writeln!(stdout, "{}", status); if status.success() { Ok(Some(())) } else { Err(Error::new( ErrorKind::ToolExecError, format!( "Command {:?} with args {:?} did not execute successfully (status code {}).", cmd, program, status ), )) } } Ok(None) => Ok(None), Err(e) => { stderr_forwarder.forward_all(); Err(Error::new( ErrorKind::ToolExecError, format!( "Failed to wait on spawned child process, command {:?} with args {:?}: {}.", cmd, program, e ), )) } } } cc/src/lib.rs0000644000175000017500000046356014661133735014047 0ustar jamespagejamespage//! A library for [Cargo build scripts](https://doc.rust-lang.org/cargo/reference/build-scripts.html) //! to compile a set of C/C++/assembly/CUDA files into a static archive for Cargo //! to link into the crate being built. This crate does not compile code itself; //! it calls out to the default compiler for the platform. This crate will //! automatically detect situations such as cross compilation and //! [various environment variables](#external-configuration-via-environment-variables) and will build code appropriately. //! //! # Example //! //! First, you'll want to both add a build script for your crate (`build.rs`) and //! also add this crate to your `Cargo.toml` via: //! //! ```toml //! [build-dependencies] //! cc = "1.0" //! ``` //! //! Next up, you'll want to write a build script like so: //! //! ```rust,no_run //! // build.rs //! //! fn main() { //! cc::Build::new() //! .file("foo.c") //! .file("bar.c") //! .compile("foo"); //! } //! ``` //! //! And that's it! Running `cargo build` should take care of the rest and your Rust //! application will now have the C files `foo.c` and `bar.c` compiled into a file //! named `libfoo.a`. If the C files contain //! //! ```c //! void foo_function(void) { ... } //! ``` //! //! and //! //! ```c //! int32_t bar_function(int32_t x) { ... } //! ``` //! //! you can call them from Rust by declaring them in //! your Rust code like so: //! //! ```rust,no_run //! extern "C" { //! fn foo_function(); //! fn bar_function(x: i32) -> i32; //! } //! //! pub fn call() { //! unsafe { //! foo_function(); //! bar_function(42); //! } //! } //! //! fn main() { //! call(); //! } //! ``` //! //! See [the Rustonomicon](https://doc.rust-lang.org/nomicon/ffi.html) for more details. //! //! # External configuration via environment variables //! //! To control the programs and flags used for building, the builder can set a //! number of different environment variables. //! //! * `CFLAGS` - a series of space separated flags passed to compilers. Note that //! individual flags cannot currently contain spaces, so doing //! something like: `-L=foo\ bar` is not possible. //! * `CC` - the actual C compiler used. Note that this is used as an exact //! executable name, so (for example) no extra flags can be passed inside //! this variable, and the builder must ensure that there aren't any //! trailing spaces. This compiler must understand the `-c` flag. For //! certain `TARGET`s, it also is assumed to know about other flags (most //! common is `-fPIC`). //! * `AR` - the `ar` (archiver) executable to use to build the static library. //! * `CRATE_CC_NO_DEFAULTS` - the default compiler flags may cause conflicts in //! some cross compiling scenarios. Setting this variable //! will disable the generation of default compiler //! flags. //! * `CC_ENABLE_DEBUG_OUTPUT` - if set, compiler command invocations and exit codes will //! be logged to stdout. This is useful for debugging build script issues, but can be //! overly verbose for normal use. //! * `CXX...` - see [C++ Support](#c-support). //! //! Furthermore, projects using this crate may specify custom environment variables //! to be inspected, for example via the `Build::try_flags_from_environment` //! function. Consult the project’s own documentation or its use of the `cc` crate //! for any additional variables it may use. //! //! Each of these variables can also be supplied with certain prefixes and suffixes, //! in the following prioritized order: //! //! 1. `_` - for example, `CC_x86_64-unknown-linux-gnu` //! 2. `_` - for example, `CC_x86_64_unknown_linux_gnu` //! 3. `_` - for example, `HOST_CC` or `TARGET_CFLAGS` //! 4. `` - a plain `CC`, `AR` as above. //! //! If none of these variables exist, cc-rs uses built-in defaults. //! //! In addition to the above optional environment variables, `cc-rs` has some //! functions with hard requirements on some variables supplied by [cargo's //! build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`, //! and `HOST` variables. //! //! [cargo]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script //! //! # Optional features //! //! ## Parallel //! //! Currently cc-rs supports parallel compilation (think `make -jN`) but this //! feature is turned off by default. To enable cc-rs to compile C/C++ in parallel, //! you can change your dependency to: //! //! ```toml //! [build-dependencies] //! cc = { version = "1.0", features = ["parallel"] } //! ``` //! //! By default cc-rs will limit parallelism to `$NUM_JOBS`, or if not present it //! will limit it to the number of cpus on the machine. If you are using cargo, //! use `-jN` option of `build`, `test` and `run` commands as `$NUM_JOBS` //! is supplied by cargo. //! //! # Compile-time Requirements //! //! To work properly this crate needs access to a C compiler when the build script //! is being run. This crate does not ship a C compiler with it. The compiler //! required varies per platform, but there are three broad categories: //! //! * Unix platforms require `cc` to be the C compiler. This can be found by //! installing cc/clang on Linux distributions and Xcode on macOS, for example. //! * Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`) //! require Visual Studio to be installed. `cc-rs` attempts to locate it, and //! if it fails, `cl.exe` is expected to be available in `PATH`. This can be //! set up by running the appropriate developer tools shell. //! * Windows platforms targeting MinGW (e.g. your target triple ends in `-gnu`) //! require `cc` to be available in `PATH`. We recommend the //! [MinGW-w64](https://www.mingw-w64.org/) distribution, which is using the //! [Win-builds](http://win-builds.org/) installation system. //! You may also acquire it via //! [MSYS2](https://www.msys2.org/), as explained [here][msys2-help]. Make sure //! to install the appropriate architecture corresponding to your installation of //! rustc. GCC from older [MinGW](http://www.mingw.org/) project is compatible //! only with 32-bit rust compiler. //! //! [msys2-help]: https://github.com/rust-lang/rust#building-on-windows //! //! # C++ support //! //! `cc-rs` supports C++ libraries compilation by using the `cpp` method on //! `Build`: //! //! ```rust,no_run //! fn main() { //! cc::Build::new() //! .cpp(true) // Switch to C++ library compilation. //! .file("foo.cpp") //! .compile("foo"); //! } //! ``` //! //! For C++ libraries, the `CXX` and `CXXFLAGS` environment variables are used instead of `CC` and `CFLAGS`. //! //! The C++ standard library may be linked to the crate target. By default it's `libc++` for macOS, FreeBSD, and OpenBSD, `libc++_shared` for Android, nothing for MSVC, and `libstdc++` for anything else. It can be changed in one of two ways: //! //! 1. by using the `cpp_link_stdlib` method on `Build`: //! ```rust,no_run //! fn main() { //! cc::Build::new() //! .cpp(true) //! .file("foo.cpp") //! .cpp_link_stdlib("stdc++") // use libstdc++ //! .compile("foo"); //! } //! ``` //! 2. by setting the `CXXSTDLIB` environment variable. //! //! In particular, for Android you may want to [use `c++_static` if you have at most one shared library](https://developer.android.com/ndk/guides/cpp-support). //! //! Remember that C++ does name mangling so `extern "C"` might be required to enable Rust linker to find your functions. //! //! # CUDA C++ support //! //! `cc-rs` also supports compiling CUDA C++ libraries by using the `cuda` method //! on `Build`: //! //! ```rust,no_run //! fn main() { //! cc::Build::new() //! // Switch to CUDA C++ library compilation using NVCC. //! .cuda(true) //! .cudart("static") //! // Generate code for Maxwell (GTX 970, 980, 980 Ti, Titan X). //! .flag("-gencode").flag("arch=compute_52,code=sm_52") //! // Generate code for Maxwell (Jetson TX1). //! .flag("-gencode").flag("arch=compute_53,code=sm_53") //! // Generate code for Pascal (GTX 1070, 1080, 1080 Ti, Titan Xp). //! .flag("-gencode").flag("arch=compute_61,code=sm_61") //! // Generate code for Pascal (Tesla P100). //! .flag("-gencode").flag("arch=compute_60,code=sm_60") //! // Generate code for Pascal (Jetson TX2). //! .flag("-gencode").flag("arch=compute_62,code=sm_62") //! // Generate code in parallel //! .flag("-t0") //! .file("bar.cu") //! .compile("bar"); //! } //! ``` #![doc(html_root_url = "https://docs.rs/cc/1.0")] #![cfg_attr(test, deny(warnings))] #![allow(deprecated)] #![deny(missing_docs)] use std::borrow::Cow; use std::collections::HashMap; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt::{self, Display, Formatter}; use std::fs; use std::io::{self, Write}; use std::path::{Component, Path, PathBuf}; #[cfg(feature = "parallel")] use std::process::Child; use std::process::Command; use std::sync::{Arc, Mutex}; #[cfg(feature = "parallel")] mod parallel; mod windows; // Regardless of whether this should be in this crate's public API, // it has been since 2015, so don't break it. pub use windows::find_tools as windows_registry; mod command_helpers; use command_helpers::*; mod tool; pub use tool::Tool; use tool::ToolFamily; /// A builder for compilation of a native library. /// /// A `Build` is the main type of the `cc` crate and is used to control all the /// various configuration options and such of a compile. You'll find more /// documentation on each method itself. #[derive(Clone, Debug)] pub struct Build { include_directories: Vec>, definitions: Vec<(Arc, Option>)>, objects: Vec>, flags: Vec>, flags_supported: Vec>, known_flag_support_status: Arc>>, ar_flags: Vec>, asm_flags: Vec>, no_default_flags: bool, files: Vec>, cpp: bool, cpp_link_stdlib: Option>>, cpp_set_stdlib: Option>, cuda: bool, cudart: Option>, std: Option>, target: Option>, host: Option>, out_dir: Option>, opt_level: Option>, debug: Option, force_frame_pointer: Option, env: Vec<(Arc, Arc)>, compiler: Option>, archiver: Option>, ranlib: Option>, cargo_output: CargoOutput, link_lib_modifiers: Vec>, pic: Option, use_plt: Option, static_crt: Option, shared_flag: Option, static_flag: Option, warnings_into_errors: bool, warnings: Option, extra_warnings: Option, env_cache: Arc>>>>, apple_sdk_root_cache: Arc>>, apple_versions_cache: Arc>>, emit_rerun_if_env_changed: bool, cached_compiler_family: Arc, ToolFamily>>>, } /// Represents the types of errors that may occur while using cc-rs. #[derive(Clone, Debug)] enum ErrorKind { /// Error occurred while performing I/O. IOError, /// Invalid architecture supplied. ArchitectureInvalid, /// Environment variable not found, with the var in question as extra info. EnvVarNotFound, /// Error occurred while using external tools (ie: invocation of compiler). ToolExecError, /// Error occurred due to missing external tools. ToolNotFound, /// One of the function arguments failed validation. InvalidArgument, #[cfg(feature = "parallel")] /// jobserver helpthread failure JobserverHelpThreadError, } /// Represents an internal error that occurred, with an explanation. #[derive(Clone, Debug)] pub struct Error { /// Describes the kind of error that occurred. kind: ErrorKind, /// More explanation of error that occurred. message: Cow<'static, str>, } impl Error { fn new(kind: ErrorKind, message: impl Into>) -> Error { Error { kind, message: message.into(), } } } impl From for Error { fn from(e: io::Error) -> Error { Error::new(ErrorKind::IOError, format!("{}", e)) } } impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}: {}", self.kind, self.message) } } impl std::error::Error for Error {} /// Represents an object. /// /// This is a source file -> object file pair. #[derive(Clone, Debug)] struct Object { src: PathBuf, dst: PathBuf, } impl Object { /// Create a new source file -> object file pair. fn new(src: PathBuf, dst: PathBuf) -> Object { Object { src, dst } } } impl Build { /// Construct a new instance of a blank set of configuration. /// /// This builder is finished with the [`compile`] function. /// /// [`compile`]: struct.Build.html#method.compile pub fn new() -> Build { Build { include_directories: Vec::new(), definitions: Vec::new(), objects: Vec::new(), flags: Vec::new(), flags_supported: Vec::new(), known_flag_support_status: Arc::new(Mutex::new(HashMap::new())), ar_flags: Vec::new(), asm_flags: Vec::new(), no_default_flags: false, files: Vec::new(), shared_flag: None, static_flag: None, cpp: false, cpp_link_stdlib: None, cpp_set_stdlib: None, cuda: false, cudart: None, std: None, target: None, host: None, out_dir: None, opt_level: None, debug: None, force_frame_pointer: None, env: Vec::new(), compiler: None, archiver: None, ranlib: None, cargo_output: CargoOutput::new(), link_lib_modifiers: Vec::new(), pic: None, use_plt: None, static_crt: None, warnings: None, extra_warnings: None, warnings_into_errors: false, env_cache: Arc::new(Mutex::new(HashMap::new())), apple_sdk_root_cache: Arc::new(Mutex::new(HashMap::new())), apple_versions_cache: Arc::new(Mutex::new(HashMap::new())), emit_rerun_if_env_changed: true, cached_compiler_family: Arc::default(), } } /// Add a directory to the `-I` or include path for headers /// /// # Example /// /// ```no_run /// use std::path::Path; /// /// let library_path = Path::new("/path/to/library"); /// /// cc::Build::new() /// .file("src/foo.c") /// .include(library_path) /// .include("src") /// .compile("foo"); /// ``` pub fn include>(&mut self, dir: P) -> &mut Build { self.include_directories.push(dir.as_ref().into()); self } /// Add multiple directories to the `-I` include path. /// /// # Example /// /// ```no_run /// # use std::path::Path; /// # let condition = true; /// # /// let mut extra_dir = None; /// if condition { /// extra_dir = Some(Path::new("/path/to")); /// } /// /// cc::Build::new() /// .file("src/foo.c") /// .includes(extra_dir) /// .compile("foo"); /// ``` pub fn includes

(&mut self, dirs: P) -> &mut Build where P: IntoIterator, P::Item: AsRef, { for dir in dirs { self.include(dir); } self } /// Specify a `-D` variable with an optional value. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .define("FOO", "BAR") /// .define("BAZ", None) /// .compile("foo"); /// ``` pub fn define<'a, V: Into>>(&mut self, var: &str, val: V) -> &mut Build { self.definitions .push((var.into(), val.into().map(Into::into))); self } /// Add an arbitrary object file to link in pub fn object>(&mut self, obj: P) -> &mut Build { self.objects.push(obj.as_ref().into()); self } /// Add an arbitrary flag to the invocation of the compiler /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .flag("-ffunction-sections") /// .compile("foo"); /// ``` pub fn flag(&mut self, flag: &str) -> &mut Build { self.flags.push(flag.into()); self } /// Removes a compiler flag that was added by [`Build::flag`]. /// /// Will not remove flags added by other means (default flags, /// flags from env, and so on). /// /// # Example /// ``` /// cc::Build::new() /// .file("src/foo.c") /// .flag("unwanted_flag") /// .remove_flag("unwanted_flag"); /// ``` pub fn remove_flag(&mut self, flag: &str) -> &mut Build { self.flags.retain(|other_flag| &**other_flag != flag); self } /// Add a flag to the invocation of the ar /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .file("src/bar.c") /// .ar_flag("/NODEFAULTLIB:libc.dll") /// .compile("foo"); /// ``` pub fn ar_flag(&mut self, flag: &str) -> &mut Build { self.ar_flags.push(flag.into()); self } /// Add a flag that will only be used with assembly files. /// /// The flag will be applied to input files with either a `.s` or /// `.asm` extension (case insensitive). /// /// # Example /// /// ```no_run /// cc::Build::new() /// .asm_flag("-Wa,-defsym,abc=1") /// .file("src/foo.S") // The asm flag will be applied here /// .file("src/bar.c") // The asm flag will not be applied here /// .compile("foo"); /// ``` pub fn asm_flag(&mut self, flag: &str) -> &mut Build { self.asm_flags.push(flag.into()); self } fn ensure_check_file(&self) -> Result { let out_dir = self.get_out_dir()?; let src = if self.cuda { assert!(self.cpp); out_dir.join("flag_check.cu") } else if self.cpp { out_dir.join("flag_check.cpp") } else { out_dir.join("flag_check.c") }; if !src.exists() { let mut f = fs::File::create(&src)?; write!(f, "int main(void) {{ return 0; }}")?; } Ok(src) } /// Run the compiler to test if it accepts the given flag. /// /// For a convenience method for setting flags conditionally, /// see `flag_if_supported()`. /// /// It may return error if it's unable to run the compiler with a test file /// (e.g. the compiler is missing or a write to the `out_dir` failed). /// /// Note: Once computed, the result of this call is stored in the /// `known_flag_support` field. If `is_flag_supported(flag)` /// is called again, the result will be read from the hash table. pub fn is_flag_supported(&self, flag: &str) -> Result { let mut known_status = self.known_flag_support_status.lock().unwrap(); if let Some(is_supported) = known_status.get(flag).cloned() { return Ok(is_supported); } let out_dir = self.get_out_dir()?; let src = self.ensure_check_file()?; let obj = out_dir.join("flag_check"); let target = self.get_target()?; let host = self.get_host()?; let mut cfg = Build::new(); cfg.flag(flag) .cargo_metadata(self.cargo_output.metadata) .target(&target) .opt_level(0) .host(&host) .debug(false) .cpp(self.cpp) .cuda(self.cuda); if let Some(ref c) = self.compiler { cfg.compiler(c.clone()); } let mut compiler = cfg.try_get_compiler()?; // Clang uses stderr for verbose output, which yields a false positive // result if the CFLAGS/CXXFLAGS include -v to aid in debugging. if compiler.family.verbose_stderr() { compiler.remove_arg("-v".into()); } if compiler.family == ToolFamily::Clang { // Avoid reporting that the arg is unsupported just because the // compiler complains that it wasn't used. compiler.push_cc_arg("-Wno-unused-command-line-argument".into()); } let mut cmd = compiler.to_command(); let is_arm = target.contains("aarch64") || target.contains("arm"); let clang = compiler.family == ToolFamily::Clang; let gnu = compiler.family == ToolFamily::Gnu; command_add_output_file( &mut cmd, &obj, self.cuda, target.contains("msvc"), clang, gnu, false, is_arm, ); // Checking for compiler flags does not require linking cmd.arg("-c"); cmd.arg(&src); let output = cmd.output()?; let is_supported = output.status.success() && output.stderr.is_empty(); known_status.insert(flag.to_owned(), is_supported); Ok(is_supported) } /// Add an arbitrary flag to the invocation of the compiler if it supports it /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .flag_if_supported("-Wlogical-op") // only supported by GCC /// .flag_if_supported("-Wunreachable-code") // only supported by clang /// .compile("foo"); /// ``` pub fn flag_if_supported(&mut self, flag: &str) -> &mut Build { self.flags_supported.push(flag.into()); self } /// Add flags from the specified environment variable. /// /// Normally the `cc` crate will consult with the standard set of environment /// variables (such as `CFLAGS` and `CXXFLAGS`) to construct the compiler invocation. Use of /// this method provides additional levers for the end user to use when configuring the build /// process. /// /// Just like the standard variables, this method will search for an environment variable with /// appropriate target prefixes, when appropriate. /// /// # Examples /// /// This method is particularly beneficial in introducing the ability to specify crate-specific /// flags. /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .try_flags_from_environment(concat!(env!("CARGO_PKG_NAME"), "_CFLAGS")) /// .expect("the environment variable must be specified and UTF-8") /// .compile("foo"); /// ``` /// pub fn try_flags_from_environment(&mut self, environ_key: &str) -> Result<&mut Build, Error> { let flags = self.envflags(environ_key)?; self.flags.extend(flags.into_iter().map(Into::into)); Ok(self) } /// Set the `-shared` flag. /// /// When enabled, the compiler will produce a shared object which can /// then be linked with other objects to form an executable. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .compile("libfoo.so"); /// ``` pub fn shared_flag(&mut self, shared_flag: bool) -> &mut Build { self.shared_flag = Some(shared_flag); self } /// Set the `-static` flag. /// /// When enabled on systems that support dynamic linking, this prevents /// linking with the shared libraries. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .static_flag(true) /// .compile("foo"); /// ``` pub fn static_flag(&mut self, static_flag: bool) -> &mut Build { self.static_flag = Some(static_flag); self } /// Disables the generation of default compiler flags. The default compiler /// flags may cause conflicts in some cross compiling scenarios. /// /// Setting the `CRATE_CC_NO_DEFAULTS` environment variable has the same /// effect as setting this to `true`. The presence of the environment /// variable and the value of `no_default_flags` will be OR'd together. pub fn no_default_flags(&mut self, no_default_flags: bool) -> &mut Build { self.no_default_flags = no_default_flags; self } /// Add a file which will be compiled pub fn file>(&mut self, p: P) -> &mut Build { self.files.push(p.as_ref().into()); self } /// Add files which will be compiled pub fn files

(&mut self, p: P) -> &mut Build where P: IntoIterator, P::Item: AsRef, { for file in p.into_iter() { self.file(file); } self } /// Get the files which will be compiled pub fn get_files(&self) -> impl Iterator { self.files.iter().map(AsRef::as_ref) } /// Set C++ support. /// /// The other `cpp_*` options will only become active if this is set to /// `true`. /// /// The name of the C++ standard library to link is decided by: /// 1. If [`cpp_link_stdlib`](Build::cpp_link_stdlib) is set, use its value. /// 2. Else if the `CXXSTDLIB` environment variable is set, use its value. /// 3. Else the default is `libc++` for OS X and BSDs, `libc++_shared` for Android, /// `None` for MSVC and `libstdc++` for anything else. pub fn cpp(&mut self, cpp: bool) -> &mut Build { self.cpp = cpp; self } /// Set CUDA C++ support. /// /// Enabling CUDA will invoke the CUDA compiler, NVCC. While NVCC accepts /// the most common compiler flags, e.g. `-std=c++17`, some project-specific /// flags might have to be prefixed with "-Xcompiler" flag, for example as /// `.flag("-Xcompiler").flag("-fpermissive")`. See the documentation for /// `nvcc`, the CUDA compiler driver, at /// for more information. /// /// If enabled, this also implicitly enables C++ support. pub fn cuda(&mut self, cuda: bool) -> &mut Build { self.cuda = cuda; if cuda { self.cpp = true; self.cudart = Some("static".into()); } self } /// Link CUDA run-time. /// /// This option mimics the `--cudart` NVCC command-line option. Just like /// the original it accepts `{none|shared|static}`, with default being /// `static`. The method has to be invoked after `.cuda(true)`, or not /// at all, if the default is right for the project. pub fn cudart(&mut self, cudart: &str) -> &mut Build { if self.cuda { self.cudart = Some(cudart.into()); } self } /// Specify the C or C++ language standard version. /// /// These values are common to modern versions of GCC, Clang and MSVC: /// - `c11` for ISO/IEC 9899:2011 /// - `c17` for ISO/IEC 9899:2018 /// - `c++14` for ISO/IEC 14882:2014 /// - `c++17` for ISO/IEC 14882:2017 /// - `c++20` for ISO/IEC 14882:2020 /// /// Other values have less broad support, e.g. MSVC does not support `c++11` /// (`c++14` is the minimum), `c89` (omit the flag instead) or `c99`. /// /// For compiling C++ code, you should also set `.cpp(true)`. /// /// The default is that no standard flag is passed to the compiler, so the /// language version will be the compiler's default. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/modern.cpp") /// .cpp(true) /// .std("c++17") /// .compile("modern"); /// ``` pub fn std(&mut self, std: &str) -> &mut Build { self.std = Some(std.into()); self } /// Set warnings into errors flag. /// /// Disabled by default. /// /// Warning: turning warnings into errors only make sense /// if you are a developer of the crate using cc-rs. /// Some warnings only appear on some architecture or /// specific version of the compiler. Any user of this crate, /// or any other crate depending on it, could fail during /// compile time. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .warnings_into_errors(true) /// .compile("libfoo.a"); /// ``` pub fn warnings_into_errors(&mut self, warnings_into_errors: bool) -> &mut Build { self.warnings_into_errors = warnings_into_errors; self } /// Set warnings flags. /// /// Adds some flags: /// - "-Wall" for MSVC. /// - "-Wall", "-Wextra" for GNU and Clang. /// /// Enabled by default. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .warnings(false) /// .compile("libfoo.a"); /// ``` pub fn warnings(&mut self, warnings: bool) -> &mut Build { self.warnings = Some(warnings); self.extra_warnings = Some(warnings); self } /// Set extra warnings flags. /// /// Adds some flags: /// - nothing for MSVC. /// - "-Wextra" for GNU and Clang. /// /// Enabled by default. /// /// # Example /// /// ```no_run /// // Disables -Wextra, -Wall remains enabled: /// cc::Build::new() /// .file("src/foo.c") /// .extra_warnings(false) /// .compile("libfoo.a"); /// ``` pub fn extra_warnings(&mut self, warnings: bool) -> &mut Build { self.extra_warnings = Some(warnings); self } /// Set the standard library to link against when compiling with C++ /// support. /// /// If the `CXXSTDLIB` environment variable is set, its value will /// override the default value, but not the value explicitly set by calling /// this function. /// /// A value of `None` indicates that no automatic linking should happen, /// otherwise cargo will link against the specified library. /// /// The given library name must not contain the `lib` prefix. /// /// Common values: /// - `stdc++` for GNU /// - `c++` for Clang /// - `c++_shared` or `c++_static` for Android /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .shared_flag(true) /// .cpp_link_stdlib("stdc++") /// .compile("libfoo.so"); /// ``` pub fn cpp_link_stdlib<'a, V: Into>>( &mut self, cpp_link_stdlib: V, ) -> &mut Build { self.cpp_link_stdlib = Some(cpp_link_stdlib.into().map(|s| s.into())); self } /// Force the C++ compiler to use the specified standard library. /// /// Setting this option will automatically set `cpp_link_stdlib` to the same /// value. /// /// The default value of this option is always `None`. /// /// This option has no effect when compiling for a Visual Studio based /// target. /// /// This option sets the `-stdlib` flag, which is only supported by some /// compilers (clang, icc) but not by others (gcc). The library will not /// detect which compiler is used, as such it is the responsibility of the /// caller to ensure that this option is only used in conjunction with a /// compiler which supports the `-stdlib` flag. /// /// A value of `None` indicates that no specific C++ standard library should /// be used, otherwise `-stdlib` is added to the compile invocation. /// /// The given library name must not contain the `lib` prefix. /// /// Common values: /// - `stdc++` for GNU /// - `c++` for Clang /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .cpp_set_stdlib("c++") /// .compile("libfoo.a"); /// ``` pub fn cpp_set_stdlib<'a, V: Into>>( &mut self, cpp_set_stdlib: V, ) -> &mut Build { let cpp_set_stdlib = cpp_set_stdlib.into(); self.cpp_set_stdlib = cpp_set_stdlib.map(|s| s.into()); self.cpp_link_stdlib(cpp_set_stdlib); self } /// Configures the target this configuration will be compiling for. /// /// This option is automatically scraped from the `TARGET` environment /// variable by build scripts, so it's not required to call this function. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .target("aarch64-linux-android") /// .compile("foo"); /// ``` pub fn target(&mut self, target: &str) -> &mut Build { self.target = Some(target.into()); self } /// Configures the host assumed by this configuration. /// /// This option is automatically scraped from the `HOST` environment /// variable by build scripts, so it's not required to call this function. /// /// # Example /// /// ```no_run /// cc::Build::new() /// .file("src/foo.c") /// .host("arm-linux-gnueabihf") /// .compile("foo"); /// ``` pub fn host(&mut self, host: &str) -> &mut Build { self.host = Some(host.into()); self } /// Configures the optimization level of the generated object files. /// /// This option is automatically scraped from the `OPT_LEVEL` environment /// variable by build scripts, so it's not required to call this function. pub fn opt_level(&mut self, opt_level: u32) -> &mut Build { self.opt_level = Some(opt_level.to_string().into()); self } /// Configures the optimization level of the generated object files. /// /// This option is automatically scraped from the `OPT_LEVEL` environment /// variable by build scripts, so it's not required to call this function. pub fn opt_level_str(&mut self, opt_level: &str) -> &mut Build { self.opt_level = Some(opt_level.into()); self } /// Configures whether the compiler will emit debug information when /// generating object files. /// /// This option is automatically scraped from the `DEBUG` environment /// variable by build scripts, so it's not required to call this function. pub fn debug(&mut self, debug: bool) -> &mut Build { self.debug = Some(debug); self } /// Configures whether the compiler will emit instructions to store /// frame pointers during codegen. /// /// This option is automatically enabled when debug information is emitted. /// Otherwise the target platform compiler's default will be used. /// You can use this option to force a specific setting. pub fn force_frame_pointer(&mut self, force: bool) -> &mut Build { self.force_frame_pointer = Some(force); self } /// Configures the output directory where all object files and static /// libraries will be located. /// /// This option is automatically scraped from the `OUT_DIR` environment /// variable by build scripts, so it's not required to call this function. pub fn out_dir>(&mut self, out_dir: P) -> &mut Build { self.out_dir = Some(out_dir.as_ref().into()); self } /// Configures the compiler to be used to produce output. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn compiler>(&mut self, compiler: P) -> &mut Build { self.compiler = Some(compiler.as_ref().into()); self } /// Configures the tool used to assemble archives. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn archiver>(&mut self, archiver: P) -> &mut Build { self.archiver = Some(archiver.as_ref().into()); self } /// Configures the tool used to index archives. /// /// This option is automatically determined from the target platform or a /// number of environment variables, so it's not required to call this /// function. pub fn ranlib>(&mut self, ranlib: P) -> &mut Build { self.ranlib = Some(ranlib.as_ref().into()); self } /// Define whether metadata should be emitted for cargo allowing it to /// automatically link the binary. Defaults to `true`. /// /// The emitted metadata is: /// /// - `rustc-link-lib=static=`*compiled lib* /// - `rustc-link-search=native=`*target folder* /// - When target is MSVC, the ATL-MFC libs are added via `rustc-link-search=native=` /// - When C++ is enabled, the C++ stdlib is added via `rustc-link-lib` /// - If `emit_rerun_if_env_changed` is not `false`, `rerun-if-env-changed=`*env* /// pub fn cargo_metadata(&mut self, cargo_metadata: bool) -> &mut Build { self.cargo_output.metadata = cargo_metadata; self } /// Define whether compile warnings should be emitted for cargo. Defaults to /// `true`. /// /// If disabled, compiler messages will not be printed. /// Issues unrelated to the compilation will always produce cargo warnings regardless of this setting. pub fn cargo_warnings(&mut self, cargo_warnings: bool) -> &mut Build { self.cargo_output.warnings = cargo_warnings; self } /// Define whether debug information should be emitted for cargo. Defaults to whether /// or not the environment variable `CC_ENABLE_DEBUG_OUTPUT` is set. /// /// If enabled, the compiler will emit debug information when generating object files, /// such as the command invoked and the exit status. pub fn cargo_debug(&mut self, cargo_debug: bool) -> &mut Build { self.cargo_output.debug = cargo_debug; self } /// Adds a native library modifier that will be added to the /// `rustc-link-lib=static:MODIFIERS=LIBRARY_NAME` metadata line /// emitted for cargo if `cargo_metadata` is enabled. /// See /// for the list of modifiers accepted by rustc. pub fn link_lib_modifier(&mut self, link_lib_modifier: &str) -> &mut Build { self.link_lib_modifiers.push(link_lib_modifier.into()); self } /// Configures whether the compiler will emit position independent code. /// /// This option defaults to `false` for `windows-gnu` and bare metal targets and /// to `true` for all other targets. pub fn pic(&mut self, pic: bool) -> &mut Build { self.pic = Some(pic); self } /// Configures whether the Procedure Linkage Table is used for indirect /// calls into shared libraries. /// /// The PLT is used to provide features like lazy binding, but introduces /// a small performance loss due to extra pointer indirection. Setting /// `use_plt` to `false` can provide a small performance increase. /// /// Note that skipping the PLT requires a recent version of GCC/Clang. /// /// This only applies to ELF targets. It has no effect on other platforms. pub fn use_plt(&mut self, use_plt: bool) -> &mut Build { self.use_plt = Some(use_plt); self } /// Define whether metadata should be emitted for cargo to detect environment /// changes that should trigger a rebuild. /// /// This has no effect if the `cargo_metadata` option is `false`. /// /// This option defaults to `true`. pub fn emit_rerun_if_env_changed(&mut self, emit_rerun_if_env_changed: bool) -> &mut Build { self.emit_rerun_if_env_changed = emit_rerun_if_env_changed; self } /// Configures whether the /MT flag or the /MD flag will be passed to msvc build tools. /// /// This option defaults to `false`, and affect only msvc targets. pub fn static_crt(&mut self, static_crt: bool) -> &mut Build { self.static_crt = Some(static_crt); self } #[doc(hidden)] pub fn __set_env(&mut self, a: A, b: B) -> &mut Build where A: AsRef, B: AsRef, { self.env.push((a.as_ref().into(), b.as_ref().into())); self } /// Run the compiler, generating the file `output` /// /// This will return a result instead of panicking; see compile() for the complete description. pub fn try_compile(&self, output: &str) -> Result<(), Error> { let mut output_components = Path::new(output).components(); match (output_components.next(), output_components.next()) { (Some(Component::Normal(_)), None) => {} _ => { return Err(Error::new( ErrorKind::InvalidArgument, "argument of `compile` must be a single normal path component", )); } } let (lib_name, gnu_lib_name) = if output.starts_with("lib") && output.ends_with(".a") { (&output[3..output.len() - 2], output.to_owned()) } else { let mut gnu = String::with_capacity(5 + output.len()); gnu.push_str("lib"); gnu.push_str(output); gnu.push_str(".a"); (output, gnu) }; let dst = self.get_out_dir()?; let objects = objects_from_files(&self.files, &dst)?; self.compile_objects(&objects)?; self.assemble(lib_name, &dst.join(gnu_lib_name), &objects)?; if self.get_target()?.contains("msvc") { let compiler = self.get_base_compiler()?; let atlmfc_lib = compiler .env() .iter() .find(|&(var, _)| var.as_os_str() == OsStr::new("LIB")) .and_then(|(_, lib_paths)| { env::split_paths(lib_paths).find(|path| { let sub = Path::new("atlmfc/lib"); path.ends_with(sub) || path.parent().map_or(false, |p| p.ends_with(sub)) }) }); if let Some(atlmfc_lib) = atlmfc_lib { self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-search=native={}", atlmfc_lib.display() )); } } if self.link_lib_modifiers.is_empty() { self.cargo_output .print_metadata(&format_args!("cargo:rustc-link-lib=static={}", lib_name)); } else { let m = self.link_lib_modifiers.join(","); self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-lib=static:{}={}", m, lib_name )); } self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-search=native={}", dst.display() )); // Add specific C++ libraries, if enabled. if self.cpp { if let Some(stdlib) = self.get_cpp_link_stdlib()? { self.cargo_output .print_metadata(&format_args!("cargo:rustc-link-lib={}", stdlib)); } } let cudart = match &self.cudart { Some(opt) => &*opt, // {none|shared|static} None => "none", }; if cudart != "none" { if let Some(nvcc) = which(&self.get_compiler().path, None) { // Try to figure out the -L search path. If it fails, // it's on user to specify one by passing it through // RUSTFLAGS environment variable. let mut libtst = false; let mut libdir = nvcc; libdir.pop(); // remove 'nvcc' libdir.push(".."); let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); if cfg!(target_os = "linux") { libdir.push("targets"); libdir.push(target_arch.to_owned() + "-linux"); libdir.push("lib"); libtst = true; } else if cfg!(target_env = "msvc") { libdir.push("lib"); match target_arch.as_str() { "x86_64" => { libdir.push("x64"); libtst = true; } "x86" => { libdir.push("Win32"); libtst = true; } _ => libtst = false, } } if libtst && libdir.is_dir() { self.cargo_output.print_metadata(&format_args!( "cargo:rustc-link-search=native={}", libdir.to_str().unwrap() )); } // And now the -l flag. let lib = match cudart { "shared" => "cudart", "static" => "cudart_static", bad => panic!("unsupported cudart option: {}", bad), }; self.cargo_output .print_metadata(&format_args!("cargo:rustc-link-lib={}", lib)); } } Ok(()) } /// Run the compiler, generating the file `output` /// /// # Library name /// /// The `output` string argument determines the file name for the compiled /// library. The Rust compiler will create an assembly named "lib"+output+".a". /// MSVC will create a file named output+".lib". /// /// The choice of `output` is close to arbitrary, but: /// /// - must be nonempty, /// - must not contain a path separator (`/`), /// - must be unique across all `compile` invocations made by the same build /// script. /// /// If your build script compiles a single source file, the base name of /// that source file would usually be reasonable: /// /// ```no_run /// cc::Build::new().file("blobstore.c").compile("blobstore"); /// ``` /// /// Compiling multiple source files, some people use their crate's name, or /// their crate's name + "-cc". /// /// Otherwise, please use your imagination. /// /// For backwards compatibility, if `output` starts with "lib" *and* ends /// with ".a", a second "lib" prefix and ".a" suffix do not get added on, /// but this usage is deprecated; please omit `lib` and `.a` in the argument /// that you pass. /// /// # Panics /// /// Panics if `output` is not formatted correctly or if one of the underlying /// compiler commands fails. It can also panic if it fails reading file names /// or creating directories. pub fn compile(&self, output: &str) { if let Err(e) = self.try_compile(output) { fail(&e.message); } } /// Run the compiler, generating intermediate files, but without linking /// them into an archive file. /// /// This will return a list of compiled object files, in the same order /// as they were passed in as `file`/`files` methods. pub fn compile_intermediates(&self) -> Vec { match self.try_compile_intermediates() { Ok(v) => v, Err(e) => fail(&e.message), } } /// Run the compiler, generating intermediate files, but without linking /// them into an archive file. /// /// This will return a result instead of panicking; see `compile_intermediates()` for the complete description. pub fn try_compile_intermediates(&self) -> Result, Error> { let dst = self.get_out_dir()?; let objects = objects_from_files(&self.files, &dst)?; self.compile_objects(&objects)?; Ok(objects.into_iter().map(|v| v.dst).collect()) } #[cfg(feature = "parallel")] fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> { use std::cell::Cell; use parallel::async_executor::{block_on, YieldOnce}; if objs.len() <= 1 { for obj in objs { let (mut cmd, name) = self.create_compile_object_cmd(obj)?; run(&mut cmd, &name, &self.cargo_output)?; } return Ok(()); } // Limit our parallelism globally with a jobserver. let tokens = parallel::job_token::ActiveJobTokenServer::new()?; // When compiling objects in parallel we do a few dirty tricks to speed // things up: // // * First is that we use the `jobserver` crate to limit the parallelism // of this build script. The `jobserver` crate will use a jobserver // configured by Cargo for build scripts to ensure that parallelism is // coordinated across C compilations and Rust compilations. Before we // compile anything we make sure to wait until we acquire a token. // // Note that this jobserver is cached globally so we only used one per // process and only worry about creating it once. // // * Next we use spawn the process to actually compile objects in // parallel after we've acquired a token to perform some work // // With all that in mind we compile all objects in a loop here, after we // acquire the appropriate tokens, Once all objects have been compiled // we wait on all the processes and propagate the results of compilation. let pendings = Cell::new(Vec::<( Command, String, KillOnDrop, parallel::job_token::JobToken, )>::new()); let is_disconnected = Cell::new(false); let has_made_progress = Cell::new(false); let wait_future = async { let mut error = None; // Buffer the stdout let mut stdout = io::BufWriter::with_capacity(128, io::stdout()); loop { // If the other end of the pipe is already disconnected, then we're not gonna get any new jobs, // so it doesn't make sense to reuse the tokens; in fact, // releasing them as soon as possible (once we know that the other end is disconnected) is beneficial. // Imagine that the last file built takes an hour to finish; in this scenario, // by not releasing the tokens before that last file is done we would effectively block other processes from // starting sooner - even though we only need one token for that last file, not N others that were acquired. let mut pendings_is_empty = false; cell_update(&pendings, |mut pendings| { // Try waiting on them. parallel::retain_unordered_mut( &mut pendings, |(cmd, program, child, _token)| { match try_wait_on_child( cmd, program, &mut child.0, &mut stdout, &mut child.1, ) { Ok(Some(())) => { // Task done, remove the entry has_made_progress.set(true); false } Ok(None) => true, // Task still not finished, keep the entry Err(err) => { // Task fail, remove the entry. // Since we can only return one error, log the error to make // sure users always see all the compilation failures. has_made_progress.set(true); if self.cargo_output.warnings { let _ = writeln!(stdout, "cargo:warning={}", err); } error = Some(err); false } } }, ); pendings_is_empty = pendings.is_empty(); pendings }); if pendings_is_empty && is_disconnected.get() { break if let Some(err) = error { Err(err) } else { Ok(()) }; } YieldOnce::default().await; } }; let spawn_future = async { for obj in objs { let (mut cmd, program) = self.create_compile_object_cmd(obj)?; let token = tokens.acquire().await?; let mut child = spawn(&mut cmd, &program, &self.cargo_output)?; let mut stderr_forwarder = StderrForwarder::new(&mut child); stderr_forwarder.set_non_blocking()?; cell_update(&pendings, |mut pendings| { pendings.push((cmd, program, KillOnDrop(child, stderr_forwarder), token)); pendings }); has_made_progress.set(true); } is_disconnected.set(true); Ok::<_, Error>(()) }; return block_on(wait_future, spawn_future, &has_made_progress); struct KillOnDrop(Child, StderrForwarder); impl Drop for KillOnDrop { fn drop(&mut self) { let child = &mut self.0; child.kill().ok(); } } fn cell_update(cell: &Cell, f: F) where T: Default, F: FnOnce(T) -> T, { let old = cell.take(); let new = f(old); cell.set(new); } } #[cfg(not(feature = "parallel"))] fn compile_objects(&self, objs: &[Object]) -> Result<(), Error> { for obj in objs { let (mut cmd, name) = self.create_compile_object_cmd(obj)?; run(&mut cmd, &name, &self.cargo_output)?; } Ok(()) } fn create_compile_object_cmd(&self, obj: &Object) -> Result<(Command, String), Error> { let asm_ext = AsmFileExt::from_path(&obj.src); let is_asm = asm_ext.is_some(); let target = self.get_target()?; let msvc = target.contains("msvc"); let compiler = self.try_get_compiler()?; let clang = compiler.family == ToolFamily::Clang; let gnu = compiler.family == ToolFamily::Gnu; let is_assembler_msvc = msvc && asm_ext == Some(AsmFileExt::DotAsm); let (mut cmd, name) = if is_assembler_msvc { self.msvc_macro_assembler()? } else { let mut cmd = compiler.to_command(); for (a, b) in self.env.iter() { cmd.env(a, b); } ( cmd, compiler .path .file_name() .ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))? .to_string_lossy() .into_owned(), ) }; let is_arm = target.contains("aarch64") || target.contains("arm"); command_add_output_file( &mut cmd, &obj.dst, self.cuda, msvc, clang, gnu, is_asm, is_arm, ); // armasm and armasm64 don't requrie -c option if !is_assembler_msvc || !is_arm { cmd.arg("-c"); } if self.cuda && self.cuda_file_count() > 1 { cmd.arg("--device-c"); } if is_asm { cmd.args(self.asm_flags.iter().map(std::ops::Deref::deref)); } if compiler.family == (ToolFamily::Msvc { clang_cl: true }) && !is_assembler_msvc { // #513: For `clang-cl`, separate flags/options from the input file. // When cross-compiling macOS -> Windows, this avoids interpreting // common `/Users/...` paths as the `/U` flag and triggering // `-Wslash-u-filename` warning. cmd.arg("--"); } cmd.arg(&obj.src); if cfg!(target_os = "macos") { self.fix_env_for_apple_os(&mut cmd)?; } Ok((cmd, name)) } /// This will return a result instead of panicking; see expand() for the complete description. pub fn try_expand(&self) -> Result, Error> { let compiler = self.try_get_compiler()?; let mut cmd = compiler.to_command(); for (a, b) in self.env.iter() { cmd.env(a, b); } cmd.arg("-E"); assert!( self.files.len() <= 1, "Expand may only be called for a single file" ); let is_asm = self .files .iter() .map(std::ops::Deref::deref) .find_map(AsmFileExt::from_path) .is_some(); if compiler.family == (ToolFamily::Msvc { clang_cl: true }) && !is_asm { // #513: For `clang-cl`, separate flags/options from the input file. // When cross-compiling macOS -> Windows, this avoids interpreting // common `/Users/...` paths as the `/U` flag and triggering // `-Wslash-u-filename` warning. cmd.arg("--"); } cmd.args(self.files.iter().map(std::ops::Deref::deref)); let name = compiler .path .file_name() .ok_or_else(|| Error::new(ErrorKind::IOError, "Failed to get compiler path."))? .to_string_lossy() .into_owned(); Ok(run_output(&mut cmd, &name, &self.cargo_output)?) } /// Run the compiler, returning the macro-expanded version of the input files. /// /// This is only relevant for C and C++ files. /// /// # Panics /// Panics if more than one file is present in the config, or if compiler /// path has an invalid file name. /// /// # Example /// ```no_run /// let out = cc::Build::new().file("src/foo.c").expand(); /// ``` pub fn expand(&self) -> Vec { match self.try_expand() { Err(e) => fail(&e.message), Ok(v) => v, } } /// Get the compiler that's in use for this configuration. /// /// This function will return a `Tool` which represents the culmination /// of this configuration at a snapshot in time. The returned compiler can /// be inspected (e.g. the path, arguments, environment) to forward along to /// other tools, or the `to_command` method can be used to invoke the /// compiler itself. /// /// This method will take into account all configuration such as debug /// information, optimization level, include directories, defines, etc. /// Additionally, the compiler binary in use follows the standard /// conventions for this path, e.g. looking at the explicitly set compiler, /// environment variables (a number of which are inspected here), and then /// falling back to the default configuration. /// /// # Panics /// /// Panics if an error occurred while determining the architecture. pub fn get_compiler(&self) -> Tool { match self.try_get_compiler() { Ok(tool) => tool, Err(e) => fail(&e.message), } } /// Get the compiler that's in use for this configuration. /// /// This will return a result instead of panicking; see /// [`get_compiler()`](Self::get_compiler) for the complete description. pub fn try_get_compiler(&self) -> Result { let opt_level = self.get_opt_level()?; let target = self.get_target()?; let mut cmd = self.get_base_compiler()?; // Disable default flag generation via `no_default_flags` or environment variable let no_defaults = self.no_default_flags || self.getenv("CRATE_CC_NO_DEFAULTS").is_some(); if !no_defaults { self.add_default_flags(&mut cmd, &target, &opt_level)?; } else { println!("Info: default compiler flags are disabled"); } if let Some(ref std) = self.std { let separator = match cmd.family { ToolFamily::Msvc { .. } => ':', ToolFamily::Gnu | ToolFamily::Clang => '=', }; cmd.push_cc_arg(format!("-std{}{}", separator, std).into()); } if let Ok(flags) = self.envflags(if self.cpp { "CXXFLAGS" } else { "CFLAGS" }) { for arg in flags { cmd.push_cc_arg(arg.into()); } } for directory in self.include_directories.iter() { cmd.args.push("-I".into()); cmd.args.push(directory.as_os_str().into()); } // If warnings and/or extra_warnings haven't been explicitly set, // then we set them only if the environment doesn't already have // CFLAGS/CXXFLAGS, since those variables presumably already contain // the desired set of warnings flags. if self.warnings.unwrap_or(!self.has_flags()) { let wflags = cmd.family.warnings_flags().into(); cmd.push_cc_arg(wflags); } if self.extra_warnings.unwrap_or(!self.has_flags()) { if let Some(wflags) = cmd.family.extra_warnings_flags() { cmd.push_cc_arg(wflags.into()); } } for flag in self.flags.iter() { cmd.args.push((**flag).into()); } for flag in self.flags_supported.iter() { if self.is_flag_supported(flag).unwrap_or(false) { cmd.push_cc_arg((**flag).into()); } } for (key, value) in self.definitions.iter() { if let Some(ref value) = *value { cmd.args.push(format!("-D{}={}", key, value).into()); } else { cmd.args.push(format!("-D{}", key).into()); } } if self.warnings_into_errors { let warnings_to_errors_flag = cmd.family.warnings_to_errors_flag().into(); cmd.push_cc_arg(warnings_to_errors_flag); } Ok(cmd) } fn add_default_flags( &self, cmd: &mut Tool, target: &str, opt_level: &str, ) -> Result<(), Error> { // Non-target flags // If the flag is not conditioned on target variable, it belongs here :) match cmd.family { ToolFamily::Msvc { .. } => { cmd.push_cc_arg("-nologo".into()); let crt_flag = match self.static_crt { Some(true) => "-MT", Some(false) => "-MD", None => { let features = self.getenv("CARGO_CFG_TARGET_FEATURE"); let features = features.as_deref().unwrap_or_default(); if features.contains("crt-static") { "-MT" } else { "-MD" } } }; cmd.push_cc_arg(crt_flag.into()); match &opt_level[..] { // Msvc uses /O1 to enable all optimizations that minimize code size. "z" | "s" | "1" => cmd.push_opt_unless_duplicate("-O1".into()), // -O3 is a valid value for gcc and clang compilers, but not msvc. Cap to /O2. "2" | "3" => cmd.push_opt_unless_duplicate("-O2".into()), _ => {} } } ToolFamily::Gnu | ToolFamily::Clang => { // arm-linux-androideabi-gcc 4.8 shipped with Android NDK does // not support '-Oz' if opt_level == "z" && cmd.family != ToolFamily::Clang { cmd.push_opt_unless_duplicate("-Os".into()); } else { cmd.push_opt_unless_duplicate(format!("-O{}", opt_level).into()); } if cmd.family == ToolFamily::Clang && target.contains("windows") { // Disambiguate mingw and msvc on Windows. Problem is that // depending on the origin clang can default to a mismatchig // run-time. cmd.push_cc_arg(format!("--target={}", target).into()); } if cmd.family == ToolFamily::Clang && target.contains("android") { // For compatibility with code that doesn't use pre-defined `__ANDROID__` macro. // If compiler used via ndk-build or cmake (officially supported build methods) // this macros is defined. // See https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/build/cmake/android.toolchain.cmake#456 // https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/build/core/build-binary.mk#141 cmd.push_opt_unless_duplicate("-DANDROID".into()); } if !target.contains("apple-ios") && !target.contains("apple-watchos") && !target.contains("apple-tvos") { cmd.push_cc_arg("-ffunction-sections".into()); cmd.push_cc_arg("-fdata-sections".into()); } // Disable generation of PIC on bare-metal for now: rust-lld doesn't support this yet if self.pic.unwrap_or( !target.contains("windows") && !target.contains("-none-") && !target.contains("uefi"), ) { cmd.push_cc_arg("-fPIC".into()); // PLT only applies if code is compiled with PIC support, // and only for ELF targets. if target.contains("linux") && !self.use_plt.unwrap_or(true) { cmd.push_cc_arg("-fno-plt".into()); } } } } if self.get_debug() { if self.cuda { // NVCC debug flag cmd.args.push("-G".into()); } let family = cmd.family; family.add_debug_flags(cmd, self.get_dwarf_version()); } if self.get_force_frame_pointer() { let family = cmd.family; family.add_force_frame_pointer(cmd); } if !cmd.is_like_msvc() { if target.contains("i686") || target.contains("i586") { cmd.args.push("-m32".into()); } else if target == "x86_64-unknown-linux-gnux32" { cmd.args.push("-mx32".into()); } else if target.contains("x86_64") || target.contains("powerpc64") { cmd.args.push("-m64".into()); } } // Target flags match cmd.family { ToolFamily::Clang => { if !cmd.has_internal_target_arg && !(target.contains("android") && android_clang_compiler_uses_target_arg_internally(&cmd.path)) { if target.contains("darwin") { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { cmd.args .push(format!("--target={}-apple-darwin", arch).into()); } } else if target.contains("macabi") { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { cmd.args .push(format!("--target={}-apple-ios-macabi", arch).into()); } } else if target.contains("ios-sim") { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { let sdk_details = apple_os_sdk_parts(AppleOs::Ios, &AppleArchSpec::Simulator("")); let deployment_target = self.apple_deployment_version(AppleOs::Ios, None, &sdk_details.sdk); cmd.args.push( format!( "--target={}-apple-ios{}-simulator", arch, deployment_target ) .into(), ); } } else if target.contains("watchos-sim") { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { let sdk_details = apple_os_sdk_parts(AppleOs::WatchOs, &AppleArchSpec::Simulator("")); let deployment_target = self.apple_deployment_version( AppleOs::WatchOs, None, &sdk_details.sdk, ); cmd.args.push( format!( "--target={}-apple-watchos{}-simulator", arch, deployment_target ) .into(), ); } } else if target.contains("tvos-sim") || target.contains("x86_64-apple-tvos") { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { let sdk_details = apple_os_sdk_parts(AppleOs::TvOs, &AppleArchSpec::Simulator("")); let deployment_target = self.apple_deployment_version( AppleOs::TvOs, None, &sdk_details.sdk, ); cmd.args.push( format!( "--target={}-apple-tvos{}-simulator", arch, deployment_target ) .into(), ); } } else if target.contains("aarch64-apple-tvos") { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { let sdk_details = apple_os_sdk_parts(AppleOs::TvOs, &AppleArchSpec::Device("")); let deployment_target = self.apple_deployment_version( AppleOs::TvOs, None, &sdk_details.sdk, ); cmd.args.push( format!("--target={}-apple-tvos{}", arch, deployment_target).into(), ); } } else if target.starts_with("riscv64gc-") { cmd.args.push( format!("--target={}", target.replace("riscv64gc", "riscv64")).into(), ); } else if target.starts_with("riscv64imac-") { cmd.args.push( format!("--target={}", target.replace("riscv64imac", "riscv64")).into(), ); } else if target.starts_with("riscv32gc-") { cmd.args.push( format!("--target={}", target.replace("riscv32gc", "riscv32")).into(), ); } else if target.starts_with("riscv32i-") { cmd.args.push( format!("--target={}", target.replace("riscv32i", "riscv32")).into(), ) } else if target.starts_with("riscv32im-") { cmd.args.push( format!("--target={}", target.replace("riscv32im", "riscv32")).into(), ) } else if target.starts_with("riscv32imc-") { cmd.args.push( format!("--target={}", target.replace("riscv32imc", "riscv32")).into(), ) } else if target.starts_with("riscv32imac-") { cmd.args.push( format!("--target={}", target.replace("riscv32imac", "riscv32")).into(), ) } else if target.starts_with("riscv32imafc-") { cmd.args.push( format!("--target={}", target.replace("riscv32imafc", "riscv32")) .into(), ) } else if target.contains("uefi") { if target.contains("x86_64") { cmd.args.push("--target=x86_64-unknown-windows-gnu".into()); } else if target.contains("i686") { cmd.args.push("--target=i686-unknown-windows-gnu".into()) } else if target.contains("aarch64") { cmd.args.push("--target=aarch64-unknown-windows-gnu".into()) } } else if target.ends_with("-freebsd") { // FreeBSD only supports C++11 and above when compiling against libc++ // (available from FreeBSD 10 onwards). Under FreeBSD, clang uses libc++ by // default on FreeBSD 10 and newer unless `--target` is manually passed to // the compiler, in which case its default behavior differs: // * If --target=xxx-unknown-freebsdX(.Y) is specified and X is greater than // or equal to 10, clang++ uses libc++ // * If --target=xxx-unknown-freebsd is specified (without a version), // clang++ cannot assume libc++ is available and reverts to a default of // libstdc++ (this behavior was changed in llvm 14). // // This breaks C++11 (or greater) builds if targeting FreeBSD with the // generic xxx-unknown-freebsd triple on clang 13 or below *without* // explicitly specifying that libc++ should be used. // When cross-compiling, we can't infer from the rust/cargo target triple // which major version of FreeBSD we are targeting, so we need to make sure // that libc++ is used (unless the user has explicitly specified otherwise). // There's no compelling reason to use a different approach when compiling // natively. if self.cpp && self.cpp_set_stdlib.is_none() { cmd.push_cc_arg("-stdlib=libc++".into()); } cmd.push_cc_arg(format!("--target={}", target).into()); } else { cmd.push_cc_arg(format!("--target={}", target).into()); } } } ToolFamily::Msvc { clang_cl } => { // This is an undocumented flag from MSVC but helps with making // builds more reproducible by avoiding putting timestamps into // files. cmd.push_cc_arg("-Brepro".into()); if clang_cl { if target.contains("x86_64") { cmd.push_cc_arg("-m64".into()); } else if target.contains("86") { cmd.push_cc_arg("-m32".into()); cmd.push_cc_arg("-arch:IA32".into()); } else { cmd.push_cc_arg(format!("--target={}", target).into()); } } else { if target.contains("i586") { cmd.push_cc_arg("-arch:IA32".into()); } else if target.contains("arm64ec") { cmd.push_cc_arg("-arm64EC".into()); } } // There is a check in corecrt.h that will generate a // compilation error if // _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE is // not defined to 1. The check was added in Windows // 8 days because only store apps were allowed on ARM. // This changed with the release of Windows 10 IoT Core. // The check will be going away in future versions of // the SDK, but for all released versions of the // Windows SDK it is required. if target.contains("arm") || target.contains("thumb") { cmd.args .push("-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1".into()); } } ToolFamily::Gnu => { if target.contains("darwin") { if let Some(arch) = map_darwin_target_from_rust_to_compiler_architecture(target) { cmd.args.push("-arch".into()); cmd.args.push(arch.into()); } } if target.contains("-kmc-solid_") { cmd.args.push("-finput-charset=utf-8".into()); } if self.static_flag.is_none() { let features = self.getenv("CARGO_CFG_TARGET_FEATURE"); let features = features.as_deref().unwrap_or_default(); if features.contains("crt-static") { cmd.args.push("-static".into()); } } // armv7 targets get to use armv7 instructions if (target.starts_with("armv7") || target.starts_with("thumbv7")) && (target.contains("-linux-") || target.contains("-kmc-solid_")) { cmd.args.push("-march=armv7-a".into()); if target.ends_with("eabihf") { // lowest common denominator FPU cmd.args.push("-mfpu=vfpv3-d16".into()); } } // (x86 Android doesn't say "eabi") if target.contains("-androideabi") && target.contains("v7") { // -march=armv7-a handled above cmd.args.push("-mthumb".into()); if !target.contains("neon") { // On android we can guarantee some extra float instructions // (specified in the android spec online) // NEON guarantees even more; see below. cmd.args.push("-mfpu=vfpv3-d16".into()); } cmd.args.push("-mfloat-abi=softfp".into()); } if target.contains("neon") { cmd.args.push("-mfpu=neon-vfpv4".into()); } if target.starts_with("armv4t-unknown-linux-") { cmd.args.push("-march=armv4t".into()); cmd.args.push("-marm".into()); cmd.args.push("-mfloat-abi=soft".into()); } if target.starts_with("armv5te-unknown-linux-") { cmd.args.push("-march=armv5te".into()); cmd.args.push("-marm".into()); cmd.args.push("-mfloat-abi=soft".into()); } // For us arm == armv6 by default if target.starts_with("arm-unknown-linux-") { cmd.args.push("-march=armv6".into()); cmd.args.push("-marm".into()); if target.ends_with("hf") { cmd.args.push("-mfpu=vfp".into()); } else { cmd.args.push("-mfloat-abi=soft".into()); } } // We can guarantee some settings for FRC if target.starts_with("arm-frc-") { cmd.args.push("-march=armv7-a".into()); cmd.args.push("-mcpu=cortex-a9".into()); cmd.args.push("-mfpu=vfpv3".into()); cmd.args.push("-mfloat-abi=softfp".into()); cmd.args.push("-marm".into()); } // Turn codegen down on i586 to avoid some instructions. if target.starts_with("i586-unknown-linux-") { cmd.args.push("-march=pentium".into()); } // Set codegen level for i686 correctly if target.starts_with("i686-unknown-linux-") { cmd.args.push("-march=i686".into()); } // Looks like `musl-gcc` makes it hard for `-m32` to make its way // all the way to the linker, so we need to actually instruct the // linker that we're generating 32-bit executables as well. This'll // typically only be used for build scripts which transitively use // these flags that try to compile executables. if target == "i686-unknown-linux-musl" || target == "i586-unknown-linux-musl" { cmd.args.push("-Wl,-melf_i386".into()); } if target.starts_with("thumb") { cmd.args.push("-mthumb".into()); if target.ends_with("eabihf") { cmd.args.push("-mfloat-abi=hard".into()) } } if target.starts_with("thumbv6m") { cmd.args.push("-march=armv6s-m".into()); } if target.starts_with("thumbv7em") { cmd.args.push("-march=armv7e-m".into()); if target.ends_with("eabihf") { cmd.args.push("-mfpu=fpv4-sp-d16".into()) } } if target.starts_with("thumbv7m") { cmd.args.push("-march=armv7-m".into()); } if target.starts_with("thumbv8m.base") { cmd.args.push("-march=armv8-m.base".into()); } if target.starts_with("thumbv8m.main") { cmd.args.push("-march=armv8-m.main".into()); if target.ends_with("eabihf") { cmd.args.push("-mfpu=fpv5-sp-d16".into()) } } if target.starts_with("armebv7r") | target.starts_with("armv7r") { if target.starts_with("armeb") { cmd.args.push("-mbig-endian".into()); } else { cmd.args.push("-mlittle-endian".into()); } // ARM mode cmd.args.push("-marm".into()); // R Profile cmd.args.push("-march=armv7-r".into()); if target.ends_with("eabihf") { // Calling convention cmd.args.push("-mfloat-abi=hard".into()); // lowest common denominator FPU // (see Cortex-R4 technical reference manual) cmd.args.push("-mfpu=vfpv3-d16".into()) } else { // Calling convention cmd.args.push("-mfloat-abi=soft".into()); } } if target.starts_with("armv7a") { cmd.args.push("-march=armv7-a".into()); if target.ends_with("eabihf") { // lowest common denominator FPU cmd.args.push("-mfpu=vfpv3-d16".into()); } } if target.starts_with("riscv32") || target.starts_with("riscv64") { // get the 32i/32imac/32imc/64gc/64imac/... part let mut parts = target.split('-'); if let Some(arch) = parts.next() { let arch = &arch[5..]; if arch.starts_with("64") { if target.contains("linux") | target.contains("freebsd") | target.contains("netbsd") | target.contains("linux") { cmd.args.push(("-march=rv64gc").into()); cmd.args.push("-mabi=lp64d".into()); } else { cmd.args.push(("-march=rv".to_owned() + arch).into()); cmd.args.push("-mabi=lp64".into()); } } else if arch.starts_with("32") { if target.contains("linux") { cmd.args.push(("-march=rv32gc").into()); cmd.args.push("-mabi=ilp32d".into()); } else { cmd.args.push(("-march=rv".to_owned() + arch).into()); cmd.args.push("-mabi=ilp32".into()); } } else { cmd.args.push("-mcmodel=medany".into()); } } } } } if target.contains("-apple-") { self.apple_flags(cmd)?; } if self.static_flag.unwrap_or(false) { cmd.args.push("-static".into()); } if self.shared_flag.unwrap_or(false) { cmd.args.push("-shared".into()); } if self.cpp { match (self.cpp_set_stdlib.as_ref(), cmd.family) { (None, _) => {} (Some(stdlib), ToolFamily::Gnu) | (Some(stdlib), ToolFamily::Clang) => { cmd.push_cc_arg(format!("-stdlib=lib{}", stdlib).into()); } _ => { self.cargo_output.print_warning(&format_args!("cpp_set_stdlib is specified, but the {:?} compiler does not support this option, ignored", cmd.family)); } } } Ok(()) } fn has_flags(&self) -> bool { let flags_env_var_name = if self.cpp { "CXXFLAGS" } else { "CFLAGS" }; let flags_env_var_value = self.getenv_with_target_prefixes(flags_env_var_name); if let Ok(_) = flags_env_var_value { true } else { false } } fn msvc_macro_assembler(&self) -> Result<(Command, String), Error> { let target = self.get_target()?; let tool = if target.contains("x86_64") { "ml64.exe" } else if target.contains("arm") { "armasm.exe" } else if target.contains("aarch64") { "armasm64.exe" } else { "ml.exe" }; let mut cmd = windows_registry::find(&target, tool).unwrap_or_else(|| self.cmd(tool)); cmd.arg("-nologo"); // undocumented, yet working with armasm[64] for directory in self.include_directories.iter() { cmd.arg("-I").arg(&**directory); } if target.contains("aarch64") || target.contains("arm") { if self.get_debug() { cmd.arg("-g"); } for (key, value) in self.definitions.iter() { cmd.arg("-PreDefine"); if let Some(ref value) = *value { if let Ok(i) = value.parse::() { cmd.arg(&format!("{} SETA {}", key, i)); } else if value.starts_with('"') && value.ends_with('"') { cmd.arg(&format!("{} SETS {}", key, value)); } else { cmd.arg(&format!("{} SETS \"{}\"", key, value)); } } else { cmd.arg(&format!("{} SETL {}", key, "{TRUE}")); } } } else { if self.get_debug() { cmd.arg("-Zi"); } for (key, value) in self.definitions.iter() { if let Some(ref value) = *value { cmd.arg(&format!("-D{}={}", key, value)); } else { cmd.arg(&format!("-D{}", key)); } } } if target.contains("i686") || target.contains("i586") { cmd.arg("-safeseh"); } Ok((cmd, tool.to_string())) } fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> { // Delete the destination if it exists as we want to // create on the first iteration instead of appending. let _ = fs::remove_file(dst); // Add objects to the archive in limited-length batches. This helps keep // the length of the command line within a reasonable length to avoid // blowing system limits on limiting platforms like Windows. let objs: Vec<_> = objs .iter() .map(|o| o.dst.as_path()) .chain(self.objects.iter().map(std::ops::Deref::deref)) .collect(); for chunk in objs.chunks(100) { self.assemble_progressive(dst, chunk)?; } if self.cuda && self.cuda_file_count() > 0 { // Link the device-side code and add it to the target library, // so that non-CUDA linker can link the final binary. let out_dir = self.get_out_dir()?; let dlink = out_dir.join(lib_name.to_owned() + "_dlink.o"); let mut nvcc = self.get_compiler().to_command(); nvcc.arg("--device-link").arg("-o").arg(&dlink).arg(dst); run(&mut nvcc, "nvcc", &self.cargo_output)?; self.assemble_progressive(dst, &[dlink.as_path()])?; } let target = self.get_target()?; if target.contains("msvc") { // The Rust compiler will look for libfoo.a and foo.lib, but the // MSVC linker will also be passed foo.lib, so be sure that both // exist for now. let lib_dst = dst.with_file_name(format!("{}.lib", lib_name)); let _ = fs::remove_file(&lib_dst); match fs::hard_link(dst, &lib_dst).or_else(|_| { // if hard-link fails, just copy (ignoring the number of bytes written) fs::copy(dst, &lib_dst).map(|_| ()) }) { Ok(_) => (), Err(_) => { return Err(Error::new( ErrorKind::IOError, "Could not copy or create a hard-link to the generated lib file.", )); } }; } else { // Non-msvc targets (those using `ar`) need a separate step to add // the symbol table to archives since our construction command of // `cq` doesn't add it for us. let (mut ar, cmd, _any_flags) = self.get_ar()?; // NOTE: We add `s` even if flags were passed using $ARFLAGS/ar_flag, because `s` // here represents a _mode_, not an arbitrary flag. Further discussion of this choice // can be seen in https://github.com/rust-lang/cc-rs/pull/763. run(ar.arg("s").arg(dst), &cmd, &self.cargo_output)?; } Ok(()) } fn assemble_progressive(&self, dst: &Path, objs: &[&Path]) -> Result<(), Error> { let target = self.get_target()?; if target.contains("msvc") { let (mut cmd, program, any_flags) = self.get_ar()?; // NOTE: -out: here is an I/O flag, and so must be included even if $ARFLAGS/ar_flag is // in use. -nologo on the other hand is just a regular flag, and one that we'll skip if // the caller has explicitly dictated the flags they want. See // https://github.com/rust-lang/cc-rs/pull/763 for further discussion. let mut out = OsString::from("-out:"); out.push(dst); cmd.arg(out); if !any_flags { cmd.arg("-nologo"); } // If the library file already exists, add the library name // as an argument to let lib.exe know we are appending the objs. if dst.exists() { cmd.arg(dst); } cmd.args(objs); run(&mut cmd, &program, &self.cargo_output)?; } else { let (mut ar, cmd, _any_flags) = self.get_ar()?; // Set an environment variable to tell the OSX archiver to ensure // that all dates listed in the archive are zero, improving // determinism of builds. AFAIK there's not really official // documentation of this but there's a lot of references to it if // you search google. // // You can reproduce this locally on a mac with: // // $ touch foo.c // $ cc -c foo.c -o foo.o // // # Notice that these two checksums are different // $ ar crus libfoo1.a foo.o && sleep 2 && ar crus libfoo2.a foo.o // $ md5sum libfoo*.a // // # Notice that these two checksums are the same // $ export ZERO_AR_DATE=1 // $ ar crus libfoo1.a foo.o && sleep 2 && touch foo.o && ar crus libfoo2.a foo.o // $ md5sum libfoo*.a // // In any case if this doesn't end up getting read, it shouldn't // cause that many issues! ar.env("ZERO_AR_DATE", "1"); // NOTE: We add cq here regardless of whether $ARFLAGS/ar_flag have been used because // it dictates the _mode_ ar runs in, which the setter of $ARFLAGS/ar_flag can't // dictate. See https://github.com/rust-lang/cc-rs/pull/763 for further discussion. run(ar.arg("cq").arg(dst).args(objs), &cmd, &self.cargo_output)?; } Ok(()) } fn apple_flags(&self, cmd: &mut Tool) -> Result<(), Error> { let target = self.get_target()?; let os = if target.contains("-darwin") { AppleOs::MacOs } else if target.contains("-watchos") { AppleOs::WatchOs } else if target.contains("-tvos") { AppleOs::TvOs } else { AppleOs::Ios }; let is_mac = match os { AppleOs::MacOs => true, _ => false, }; let arch_str = target.split('-').nth(0).ok_or_else(|| { Error::new( ErrorKind::ArchitectureInvalid, format!("Unknown architecture for {:?} target.", os), ) })?; let is_catalyst = match target.split('-').nth(3) { Some(v) => v == "macabi", None => false, }; let is_arm_sim = match target.split('-').nth(3) { Some(v) => v == "sim", None => false, }; let arch = if is_mac { match arch_str { "i686" => AppleArchSpec::Device("-m32"), "x86_64" | "x86_64h" | "aarch64" => AppleArchSpec::Device("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, "Unknown architecture for macOS target.", )); } } } else if is_catalyst { match arch_str { "arm64e" => AppleArchSpec::Catalyst("arm64e"), "arm64" | "aarch64" => AppleArchSpec::Catalyst("arm64"), "x86_64" | "x86_64h" => AppleArchSpec::Catalyst("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, "Unknown architecture for iOS target.", )); } } } else if is_arm_sim { match arch_str { "arm64" | "aarch64" => AppleArchSpec::Simulator("arm64"), "x86_64" | "x86_64h" => AppleArchSpec::Simulator("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, "Unknown architecture for simulator target.", )); } } } else { match arch_str { "arm" | "armv7" | "thumbv7" => AppleArchSpec::Device("armv7"), "armv7k" => AppleArchSpec::Device("armv7k"), "armv7s" | "thumbv7s" => AppleArchSpec::Device("armv7s"), "arm64e" => AppleArchSpec::Device("arm64e"), "arm64" | "aarch64" => AppleArchSpec::Device("arm64"), "arm64_32" => AppleArchSpec::Device("arm64_32"), "i386" | "i686" => AppleArchSpec::Simulator("-m32"), "x86_64" | "x86_64h" => AppleArchSpec::Simulator("-m64"), _ => { return Err(Error::new( ErrorKind::ArchitectureInvalid, format!("Unknown architecture for {:?} target.", os), )); } } }; let sdk_details = apple_os_sdk_parts(os, &arch); let min_version = self.apple_deployment_version(os, Some(arch_str), &sdk_details.sdk); match arch { AppleArchSpec::Device(_) if is_mac => { cmd.args .push(format!("-mmacosx-version-min={}", min_version).into()); } AppleArchSpec::Device(arch) => { cmd.args.push("-arch".into()); cmd.args.push(arch.into()); cmd.args.push( format!("-m{}os-version-min={}", sdk_details.sdk_prefix, min_version).into(), ); } AppleArchSpec::Simulator(arch) => { if arch.starts_with('-') { // -m32 or -m64 cmd.args.push(arch.into()); } else { cmd.args.push("-arch".into()); cmd.args.push(arch.into()); } cmd.args.push( format!( "-m{}simulator-version-min={}", sdk_details.sim_prefix, min_version ) .into(), ); } AppleArchSpec::Catalyst(_) => {} }; // AppleClang sometimes requires sysroot even for darwin if cmd.is_xctoolchain_clang() || !target.ends_with("-darwin") { self.cargo_output.print_metadata(&format_args!( "Detecting {:?} SDK path for {}", os, sdk_details.sdk )); let sdk_path = self.apple_sdk_root(&sdk_details.sdk)?; cmd.args.push("-isysroot".into()); cmd.args.push(sdk_path); } if let AppleArchSpec::Catalyst(_) = arch { // Mac Catalyst uses the macOS SDK, but to compile against and // link to iOS-specific frameworks, we should have the support // library stubs in the include and library search path. let sdk_path = self.apple_sdk_root(&sdk_details.sdk)?; let ios_support = PathBuf::from(sdk_path).join("/System/iOSSupport"); cmd.args.extend([ // Header search path OsString::from("-isystem"), ios_support.join("/usr/include").into(), // Framework header search path OsString::from("-iframework"), ios_support.join("/System/Library/Frameworks").into(), // Library search path { let mut s = OsString::from("-L"); s.push(&ios_support.join("/usr/lib")); s }, // Framework linker search path { // Technically, we _could_ avoid emitting `-F`, as // `-iframework` implies it, but let's keep it in for // clarity. let mut s = OsString::from("-F"); s.push(&ios_support.join("/System/Library/Frameworks")); s }, ]); } Ok(()) } fn cmd>(&self, prog: P) -> Command { let mut cmd = Command::new(prog); for (a, b) in self.env.iter() { cmd.env(a, b); } cmd } fn get_base_compiler(&self) -> Result { if let Some(c) = &self.compiler { return Ok(Tool::new( (**c).to_owned(), &self.cached_compiler_family, &self.cargo_output, )); } let host = self.get_host()?; let target = self.get_target()?; let target = &*target; let (env, msvc, gnu, traditional, clang) = if self.cpp { ("CXX", "cl.exe", "g++", "c++", "clang++") } else { ("CC", "cl.exe", "gcc", "cc", "clang") }; // On historical Solaris systems, "cc" may have been Sun Studio, which // is not flag-compatible with "gcc". This history casts a long shadow, // and many modern illumos distributions today ship GCC as "gcc" without // also making it available as "cc". let default = if host.contains("solaris") || host.contains("illumos") { gnu } else { traditional }; let cl_exe = windows_registry::find_tool(target, "cl.exe"); let tool_opt: Option = self .env_tool(env) .map(|(tool, wrapper, args)| { // find the driver mode, if any const DRIVER_MODE: &str = "--driver-mode="; let driver_mode = args .iter() .find(|a| a.starts_with(DRIVER_MODE)) .map(|a| &a[DRIVER_MODE.len()..]); // Chop off leading/trailing whitespace to work around // semi-buggy build scripts which are shared in // makefiles/configure scripts (where spaces are far more // lenient) let mut t = Tool::with_clang_driver( tool, driver_mode, &self.cached_compiler_family, &self.cargo_output, ); if let Some(cc_wrapper) = wrapper { t.cc_wrapper_path = Some(PathBuf::from(cc_wrapper)); } for arg in args { t.cc_wrapper_args.push(arg.into()); } t }) .or_else(|| { if target.contains("emscripten") { let tool = if self.cpp { "em++" } else { "emcc" }; // Windows uses bat file so we have to be a bit more specific if cfg!(windows) { let mut t = Tool::new( PathBuf::from("cmd"), &self.cached_compiler_family, &self.cargo_output, ); t.args.push("/c".into()); t.args.push(format!("{}.bat", tool).into()); Some(t) } else { Some(Tool::new( PathBuf::from(tool), &self.cached_compiler_family, &self.cargo_output, )) } } else { None } }) .or_else(|| cl_exe.clone()); let tool = match tool_opt { Some(t) => t, None => { let compiler = if host.contains("windows") && target.contains("windows") { if target.contains("msvc") { msvc.to_string() } else { let cc = if target.contains("llvm") { clang } else { gnu }; format!("{}.exe", cc) } } else if target.contains("apple-ios") | target.contains("apple-watchos") | target.contains("apple-tvos") { clang.to_string() } else if target.contains("android") { autodetect_android_compiler(target, &host, gnu, clang) } else if target.contains("cloudabi") { format!("{}-{}", target, traditional) } else if target == "wasm32-wasi" || target == "wasm32-unknown-wasi" || target == "wasm32-unknown-unknown" { "clang".to_string() } else if target.contains("vxworks") { if self.cpp { "wr-c++".to_string() } else { "wr-cc".to_string() } } else if target.starts_with("armv7a-kmc-solid_") { format!("arm-kmc-eabi-{}", gnu) } else if target.starts_with("aarch64-kmc-solid_") { format!("aarch64-kmc-elf-{}", gnu) } else if &*self.get_host()? != target { let prefix = self.prefix_for_target(target); match prefix { Some(prefix) => { let cc = if target.contains("llvm") { clang } else { gnu }; format!("{}-{}", prefix, cc) } None => default.to_string(), } } else { default.to_string() }; let mut t = Tool::new( PathBuf::from(compiler), &self.cached_compiler_family, &self.cargo_output, ); if let Some(cc_wrapper) = Self::rustc_wrapper_fallback() { t.cc_wrapper_path = Some(PathBuf::from(cc_wrapper)); } t } }; let mut tool = if self.cuda { assert!( tool.args.is_empty(), "CUDA compilation currently assumes empty pre-existing args" ); let nvcc = match self.getenv_with_target_prefixes("NVCC") { Err(_) => PathBuf::from("nvcc"), Ok(nvcc) => PathBuf::from(&*nvcc), }; let mut nvcc_tool = Tool::with_features( nvcc, None, self.cuda, &self.cached_compiler_family, &self.cargo_output, ); nvcc_tool .args .push(format!("-ccbin={}", tool.path.display()).into()); nvcc_tool.family = tool.family; nvcc_tool } else { tool }; // New "standalone" C/C++ cross-compiler executables from recent Android NDK // are just shell scripts that call main clang binary (from Android NDK) with // proper `--target` argument. // // For example, armv7a-linux-androideabi16-clang passes // `--target=armv7a-linux-androideabi16` to clang. // // As the shell script calls the main clang binary, the command line limit length // on Windows is restricted to around 8k characters instead of around 32k characters. // To remove this limit, we call the main clang binary directly and construct the // `--target=` ourselves. if host.contains("windows") && android_clang_compiler_uses_target_arg_internally(&tool.path) { if let Some(path) = tool.path.file_name() { let file_name = path.to_str().unwrap().to_owned(); let (target, clang) = file_name.split_at(file_name.rfind('-').unwrap()); tool.has_internal_target_arg = true; tool.path.set_file_name(clang.trim_start_matches('-')); tool.path.set_extension("exe"); tool.args.push(format!("--target={}", target).into()); // Additionally, shell scripts for target i686-linux-android versions 16 to 24 // pass the `mstackrealign` option so we do that here as well. if target.contains("i686-linux-android") { let (_, version) = target.split_at(target.rfind('d').unwrap() + 1); if let Ok(version) = version.parse::() { if version > 15 && version < 25 { tool.args.push("-mstackrealign".into()); } } } }; } // If we found `cl.exe` in our environment, the tool we're returning is // an MSVC-like tool, *and* no env vars were set then set env vars for // the tool that we're returning. // // Env vars are needed for things like `link.exe` being put into PATH as // well as header include paths sometimes. These paths are automatically // included by default but if the `CC` or `CXX` env vars are set these // won't be used. This'll ensure that when the env vars are used to // configure for invocations like `clang-cl` we still get a "works out // of the box" experience. if let Some(cl_exe) = cl_exe { if tool.family == (ToolFamily::Msvc { clang_cl: true }) && tool.env.len() == 0 && target.contains("msvc") { for (k, v) in cl_exe.env.iter() { tool.env.push((k.to_owned(), v.to_owned())); } } } if target.contains("msvc") && tool.family == ToolFamily::Gnu { self.cargo_output .print_warning(&"GNU compiler is not supported for this target"); } Ok(tool) } /// Returns a fallback `cc_compiler_wrapper` by introspecting `RUSTC_WRAPPER` fn rustc_wrapper_fallback() -> Option { // No explicit CC wrapper was detected, but check if RUSTC_WRAPPER // is defined and is a build accelerator that is compatible with // C/C++ compilers (e.g. sccache) const VALID_WRAPPERS: &[&'static str] = &["sccache", "cachepot"]; let rustc_wrapper = std::env::var_os("RUSTC_WRAPPER")?; let wrapper_path = Path::new(&rustc_wrapper); let wrapper_stem = wrapper_path.file_stem()?; if VALID_WRAPPERS.contains(&wrapper_stem.to_str()?) { Some(rustc_wrapper.to_str()?.to_owned()) } else { None } } /// Returns compiler path, optional modifier name from whitelist, and arguments vec fn env_tool(&self, name: &str) -> Option<(PathBuf, Option, Vec)> { let tool = match self.getenv_with_target_prefixes(name) { Ok(tool) => tool, Err(_) => return None, }; // If this is an exact path on the filesystem we don't want to do any // interpretation at all, just pass it on through. This'll hopefully get // us to support spaces-in-paths. if Path::new(&*tool).exists() { return Some(( PathBuf::from(&*tool), Self::rustc_wrapper_fallback(), Vec::new(), )); } // Ok now we want to handle a couple of scenarios. We'll assume from // here on out that spaces are splitting separate arguments. Two major // features we want to support are: // // CC='sccache cc' // // aka using `sccache` or any other wrapper/caching-like-thing for // compilations. We want to know what the actual compiler is still, // though, because our `Tool` API support introspection of it to see // what compiler is in use. // // additionally we want to support // // CC='cc -flag' // // where the CC env var is used to also pass default flags to the C // compiler. // // It's true that everything here is a bit of a pain, but apparently if // you're not literally make or bash then you get a lot of bug reports. let known_wrappers = ["ccache", "distcc", "sccache", "icecc", "cachepot"]; let mut parts = tool.split_whitespace(); let maybe_wrapper = match parts.next() { Some(s) => s, None => return None, }; let file_stem = Path::new(maybe_wrapper) .file_stem() .unwrap() .to_str() .unwrap(); if known_wrappers.contains(&file_stem) { if let Some(compiler) = parts.next() { return Some(( compiler.into(), Some(maybe_wrapper.to_string()), parts.map(|s| s.to_string()).collect(), )); } } Some(( maybe_wrapper.into(), Self::rustc_wrapper_fallback(), parts.map(|s| s.to_string()).collect(), )) } /// Returns the C++ standard library: /// 1. If [`cpp_link_stdlib`](cc::Build::cpp_link_stdlib) is set, uses its value. /// 2. Else if the `CXXSTDLIB` environment variable is set, uses its value. /// 3. Else the default is `libc++` for OS X and BSDs, `libc++_shared` for Android, /// `None` for MSVC and `libstdc++` for anything else. fn get_cpp_link_stdlib(&self) -> Result, Error> { match &self.cpp_link_stdlib { Some(s) => Ok(s.as_ref().map(|s| (*s).to_string())), None => { if let Ok(stdlib) = self.getenv_with_target_prefixes("CXXSTDLIB") { if stdlib.is_empty() { Ok(None) } else { Ok(Some(stdlib.to_string())) } } else { let target = self.get_target()?; if target.contains("msvc") { Ok(None) } else if target.contains("apple") | target.contains("freebsd") | target.contains("openbsd") | target.contains("aix") | target.contains("linux-ohos") { Ok(Some("c++".to_string())) } else if target.contains("android") { Ok(Some("c++_shared".to_string())) } else { Ok(Some("stdc++".to_string())) } } } } } fn get_ar(&self) -> Result<(Command, String, bool), Error> { self.try_get_archiver_and_flags() } /// Get the archiver (ar) that's in use for this configuration. /// /// You can use [`Command::get_program`] to get just the path to the command. /// /// This method will take into account all configuration such as debug /// information, optimization level, include directories, defines, etc. /// Additionally, the compiler binary in use follows the standard /// conventions for this path, e.g. looking at the explicitly set compiler, /// environment variables (a number of which are inspected here), and then /// falling back to the default configuration. /// /// # Panics /// /// Panics if an error occurred while determining the architecture. pub fn get_archiver(&self) -> Command { match self.try_get_archiver() { Ok(tool) => tool, Err(e) => fail(&e.message), } } /// Get the archiver that's in use for this configuration. /// /// This will return a result instead of panicking; /// see [`Self::get_archiver`] for the complete description. pub fn try_get_archiver(&self) -> Result { Ok(self.try_get_archiver_and_flags()?.0) } fn try_get_archiver_and_flags(&self) -> Result<(Command, String, bool), Error> { let (mut cmd, name) = self.get_base_archiver()?; let mut any_flags = false; if let Ok(flags) = self.envflags("ARFLAGS") { any_flags = any_flags | !flags.is_empty(); cmd.args(flags); } for flag in &self.ar_flags { any_flags = true; cmd.arg(&**flag); } Ok((cmd, name, any_flags)) } fn get_base_archiver(&self) -> Result<(Command, String), Error> { if let Some(ref a) = self.archiver { return Ok((self.cmd(&**a), a.to_string_lossy().into_owned())); } self.get_base_archiver_variant("AR", "ar") } /// Get the ranlib that's in use for this configuration. /// /// You can use [`Command::get_program`] to get just the path to the command. /// /// This method will take into account all configuration such as debug /// information, optimization level, include directories, defines, etc. /// Additionally, the compiler binary in use follows the standard /// conventions for this path, e.g. looking at the explicitly set compiler, /// environment variables (a number of which are inspected here), and then /// falling back to the default configuration. /// /// # Panics /// /// Panics if an error occurred while determining the architecture. pub fn get_ranlib(&self) -> Command { match self.try_get_ranlib() { Ok(tool) => tool, Err(e) => fail(&e.message), } } /// Get the ranlib that's in use for this configuration. /// /// This will return a result instead of panicking; /// see [`Self::get_ranlib`] for the complete description. pub fn try_get_ranlib(&self) -> Result { let mut cmd = self.get_base_ranlib()?; if let Ok(flags) = self.envflags("RANLIBFLAGS") { cmd.args(flags); } Ok(cmd) } fn get_base_ranlib(&self) -> Result { if let Some(ref r) = self.ranlib { return Ok(self.cmd(&**r)); } Ok(self.get_base_archiver_variant("RANLIB", "ranlib")?.0) } fn get_base_archiver_variant(&self, env: &str, tool: &str) -> Result<(Command, String), Error> { let target = self.get_target()?; let mut name = String::new(); let tool_opt: Option = self .env_tool(env) .map(|(tool, _wrapper, args)| { let mut cmd = self.cmd(tool); cmd.args(args); cmd }) .or_else(|| { if target.contains("emscripten") { // Windows use bat files so we have to be a bit more specific if cfg!(windows) { let mut cmd = self.cmd("cmd"); name = format!("em{}.bat", tool); cmd.arg("/c").arg(&name); Some(cmd) } else { name = format!("em{}", tool); Some(self.cmd(&name)) } } else if target.starts_with("wasm32") { // Formally speaking one should be able to use this approach, // parsing -print-search-dirs output, to cover all clang targets, // including Android SDKs and other cross-compilation scenarios... // And even extend it to gcc targets by searching for "ar" instead // of "llvm-ar"... let compiler = self.get_base_compiler().ok()?; if compiler.family == ToolFamily::Clang { name = format!("llvm-{}", tool); search_programs(&mut self.cmd(&compiler.path), &name, &self.cargo_output) .map(|name| self.cmd(name)) } else { None } } else { None } }); let default = tool.to_string(); let tool = match tool_opt { Some(t) => t, None => { if target.contains("android") { name = format!("llvm-{}", tool); match Command::new(&name).arg("--version").status() { Ok(status) if status.success() => (), _ => name = format!("{}-{}", target.replace("armv7", "arm"), tool), } self.cmd(&name) } else if target.contains("msvc") { // NOTE: There isn't really a ranlib on msvc, so arguably we should return // `None` somehow here. But in general, callers will already have to be aware // of not running ranlib on Windows anyway, so it feels okay to return lib.exe // here. let compiler = self.get_base_compiler()?; let mut lib = String::new(); if compiler.family == (ToolFamily::Msvc { clang_cl: true }) { // See if there is 'llvm-lib' next to 'clang-cl' // Another possibility could be to see if there is 'clang' // next to 'clang-cl' and use 'search_programs()' to locate // 'llvm-lib'. This is because 'clang-cl' doesn't support // the -print-search-dirs option. if let Some(mut cmd) = which(&compiler.path, None) { cmd.pop(); cmd.push("llvm-lib.exe"); if let Some(llvm_lib) = which(&cmd, None) { lib = llvm_lib.to_str().unwrap().to_owned(); } } } if lib.is_empty() { name = String::from("lib.exe"); let mut cmd = match windows_registry::find(&target, "lib.exe") { Some(t) => t, None => self.cmd("lib.exe"), }; if target.contains("arm64ec") { cmd.arg("/machine:arm64ec"); } cmd } else { name = lib; self.cmd(&name) } } else if target.contains("illumos") { // The default 'ar' on illumos uses a non-standard flags, // but the OS comes bundled with a GNU-compatible variant. // // Use the GNU-variant to match other Unix systems. name = format!("g{}", tool); self.cmd(&name) } else if self.get_host()? != target { match self.prefix_for_target(&target) { Some(p) => { // GCC uses $target-gcc-ar, whereas binutils uses $target-ar -- try both. // Prefer -ar if it exists, as builds of `-gcc-ar` have been observed to be // outright broken (such as when targeting freebsd with `--disable-lto` // toolchain where the archiver attempts to load the LTO plugin anyway but // fails to find one). // // The same applies to ranlib. let mut chosen = default; for &infix in &["", "-gcc"] { let target_p = format!("{}{}-{}", p, infix, tool); if Command::new(&target_p).output().is_ok() { chosen = target_p; break; } } name = chosen; self.cmd(&name) } None => { name = default; self.cmd(&name) } } } else { name = default; self.cmd(&name) } } }; Ok((tool, name)) } fn prefix_for_target(&self, target: &str) -> Option { // Put aside RUSTC_LINKER's prefix to be used as second choice, after CROSS_COMPILE let linker_prefix = self .getenv("RUSTC_LINKER") .and_then(|var| var.strip_suffix("-gcc").map(str::to_string)); // CROSS_COMPILE is of the form: "arm-linux-gnueabi-" let cc_env = self.getenv("CROSS_COMPILE"); let cross_compile = cc_env.as_ref().map(|s| s.trim_end_matches('-').to_owned()); cross_compile.or(linker_prefix).or(match &target[..] { // Note: there is no `aarch64-pc-windows-gnu` target, only `-gnullvm` "aarch64-pc-windows-gnullvm" => Some("aarch64-w64-mingw32"), "aarch64-uwp-windows-gnu" => Some("aarch64-w64-mingw32"), "aarch64-unknown-linux-gnu" => Some("aarch64-linux-gnu"), "aarch64-unknown-linux-musl" => Some("aarch64-linux-musl"), "aarch64-unknown-netbsd" => Some("aarch64--netbsd"), "arm-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv4t-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv5te-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv5te-unknown-linux-musleabi" => Some("arm-linux-gnueabi"), "arm-frc-linux-gnueabi" => Some("arm-frc-linux-gnueabi"), "arm-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "arm-unknown-linux-musleabi" => Some("arm-linux-musleabi"), "arm-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "arm-unknown-netbsd-eabi" => Some("arm--netbsdelf-eabi"), "armv6-unknown-netbsd-eabihf" => Some("armv6--netbsdelf-eabihf"), "armv7-unknown-linux-gnueabi" => Some("arm-linux-gnueabi"), "armv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "armv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "armv7neon-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "armv7neon-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "thumbv7-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "thumbv7-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "thumbv7neon-unknown-linux-gnueabihf" => Some("arm-linux-gnueabihf"), "thumbv7neon-unknown-linux-musleabihf" => Some("arm-linux-musleabihf"), "armv7-unknown-netbsd-eabihf" => Some("armv7--netbsdelf-eabihf"), "hexagon-unknown-linux-musl" => Some("hexagon-linux-musl"), "i586-unknown-linux-musl" => Some("musl"), "i686-pc-windows-gnu" => Some("i686-w64-mingw32"), "i686-uwp-windows-gnu" => Some("i686-w64-mingw32"), "i686-unknown-linux-gnu" => self.find_working_gnu_prefix(&[ "i686-linux-gnu", "x86_64-linux-gnu", // transparently support gcc-multilib ]), // explicit None if not found, so caller knows to fall back "i686-unknown-linux-musl" => Some("musl"), "i686-unknown-netbsd" => Some("i486--netbsdelf"), "loongarch64-unknown-linux-gnu" => Some("loongarch64-linux-gnu"), "mips-unknown-linux-gnu" => Some("mips-linux-gnu"), "mips-unknown-linux-musl" => Some("mips-linux-musl"), "mipsel-unknown-linux-gnu" => Some("mipsel-linux-gnu"), "mipsel-unknown-linux-musl" => Some("mipsel-linux-musl"), "mips64-unknown-linux-gnuabi64" => Some("mips64-linux-gnuabi64"), "mips64el-unknown-linux-gnuabi64" => Some("mips64el-linux-gnuabi64"), "mipsisa32r6-unknown-linux-gnu" => Some("mipsisa32r6-linux-gnu"), "mipsisa32r6el-unknown-linux-gnu" => Some("mipsisa32r6el-linux-gnu"), "mipsisa64r6-unknown-linux-gnuabi64" => Some("mipsisa64r6-linux-gnuabi64"), "mipsisa64r6el-unknown-linux-gnuabi64" => Some("mipsisa64r6el-linux-gnuabi64"), "powerpc-unknown-linux-gnu" => Some("powerpc-linux-gnu"), "powerpc-unknown-linux-gnuspe" => Some("powerpc-linux-gnuspe"), "powerpc-unknown-netbsd" => Some("powerpc--netbsd"), "powerpc64-unknown-linux-gnu" => Some("powerpc-linux-gnu"), "powerpc64le-unknown-linux-gnu" => Some("powerpc64le-linux-gnu"), "riscv32i-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv32imac-esp-espidf" => Some("riscv32-esp-elf"), "riscv32imac-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv32imac-unknown-xous-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv32imc-esp-espidf" => Some("riscv32-esp-elf"), "riscv32imc-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv32-unknown-elf", "riscv64-unknown-elf", "riscv-none-embed", ]), "riscv64gc-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", ]), "riscv64imac-unknown-none-elf" => self.find_working_gnu_prefix(&[ "riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", ]), "riscv64gc-unknown-linux-gnu" => Some("riscv64-linux-gnu"), "riscv32gc-unknown-linux-gnu" => Some("riscv32-linux-gnu"), "riscv64gc-unknown-linux-musl" => Some("riscv64-linux-musl"), "riscv32gc-unknown-linux-musl" => Some("riscv32-linux-musl"), "riscv64gc-unknown-netbsd" => Some("riscv64--netbsd"), "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"), "sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"), "sparc64-unknown-linux-gnu" => Some("sparc64-linux-gnu"), "sparc64-unknown-netbsd" => Some("sparc64--netbsd"), "sparcv9-sun-solaris" => Some("sparcv9-sun-solaris"), "armv7a-none-eabi" => Some("arm-none-eabi"), "armv7a-none-eabihf" => Some("arm-none-eabi"), "armebv7r-none-eabi" => Some("arm-none-eabi"), "armebv7r-none-eabihf" => Some("arm-none-eabi"), "armv7r-none-eabi" => Some("arm-none-eabi"), "armv7r-none-eabihf" => Some("arm-none-eabi"), "armv8r-none-eabihf" => Some("arm-none-eabi"), "thumbv6m-none-eabi" => Some("arm-none-eabi"), "thumbv7em-none-eabi" => Some("arm-none-eabi"), "thumbv7em-none-eabihf" => Some("arm-none-eabi"), "thumbv7m-none-eabi" => Some("arm-none-eabi"), "thumbv8m.base-none-eabi" => Some("arm-none-eabi"), "thumbv8m.main-none-eabi" => Some("arm-none-eabi"), "thumbv8m.main-none-eabihf" => Some("arm-none-eabi"), "x86_64-pc-windows-gnu" => Some("x86_64-w64-mingw32"), "x86_64-pc-windows-gnullvm" => Some("x86_64-w64-mingw32"), "x86_64-uwp-windows-gnu" => Some("x86_64-w64-mingw32"), "x86_64-rumprun-netbsd" => Some("x86_64-rumprun-netbsd"), "x86_64-unknown-linux-gnu" => self.find_working_gnu_prefix(&[ "x86_64-linux-gnu", // rustfmt wrap ]), // explicit None if not found, so caller knows to fall back "x86_64-unknown-linux-musl" => Some("musl"), "x86_64-unknown-netbsd" => Some("x86_64--netbsd"), _ => None, } .map(|x| x.to_owned())) } /// Some platforms have multiple, compatible, canonical prefixes. Look through /// each possible prefix for a compiler that exists and return it. The prefixes /// should be ordered from most-likely to least-likely. fn find_working_gnu_prefix(&self, prefixes: &[&'static str]) -> Option<&'static str> { let suffix = if self.cpp { "-g++" } else { "-gcc" }; let extension = std::env::consts::EXE_SUFFIX; // Loop through PATH entries searching for each toolchain. This ensures that we // are more likely to discover the toolchain early on, because chances are good // that the desired toolchain is in one of the higher-priority paths. env::var_os("PATH") .as_ref() .and_then(|path_entries| { env::split_paths(path_entries).find_map(|path_entry| { for prefix in prefixes { let target_compiler = format!("{}{}{}", prefix, suffix, extension); if path_entry.join(&target_compiler).exists() { return Some(prefix); } } None }) }) .map(|prefix| *prefix) .or_else(|| // If no toolchain was found, provide the first toolchain that was passed in. // This toolchain has been shown not to exist, however it will appear in the // error that is shown to the user which should make it easier to search for // where it should be obtained. prefixes.first().map(|prefix| *prefix)) } fn get_target(&self) -> Result, Error> { match &self.target { Some(t) => Ok(t.clone()), None => self.getenv_unwrap("TARGET"), } } fn get_host(&self) -> Result, Error> { match &self.host { Some(h) => Ok(h.clone()), None => self.getenv_unwrap("HOST"), } } fn get_opt_level(&self) -> Result, Error> { match &self.opt_level { Some(ol) => Ok(ol.clone()), None => self.getenv_unwrap("OPT_LEVEL"), } } fn get_debug(&self) -> bool { self.debug.unwrap_or_else(|| match self.getenv("DEBUG") { Some(s) => &*s != "false", None => false, }) } fn get_dwarf_version(&self) -> Option { // Tentatively matches the DWARF version defaults as of rustc 1.62. let target = self.get_target().ok()?; if target.contains("android") || target.contains("apple") || target.contains("dragonfly") || target.contains("freebsd") || target.contains("netbsd") || target.contains("openbsd") || target.contains("windows-gnu") { Some(2) } else if target.contains("linux") { Some(4) } else { None } } fn get_force_frame_pointer(&self) -> bool { self.force_frame_pointer.unwrap_or_else(|| self.get_debug()) } fn get_out_dir(&self) -> Result, Error> { match &self.out_dir { Some(p) => Ok(Cow::Borrowed(&**p)), None => env::var_os("OUT_DIR") .map(PathBuf::from) .map(Cow::Owned) .ok_or_else(|| { Error::new( ErrorKind::EnvVarNotFound, "Environment variable OUT_DIR not defined.", ) }), } } fn getenv(&self, v: &str) -> Option> { // Returns true for environment variables cargo sets for build scripts: // https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts // // This handles more of the vars than we actually use (it tries to check // complete-ish set), just to avoid needing maintenance if/when new // calls to `getenv`/`getenv_unwrap` are added. fn provided_by_cargo(envvar: &str) -> bool { match envvar { v if v.starts_with("CARGO") || v.starts_with("RUSTC") => true, "HOST" | "TARGET" | "RUSTDOC" | "OUT_DIR" | "OPT_LEVEL" | "DEBUG" | "PROFILE" | "NUM_JOBS" | "RUSTFLAGS" => true, _ => false, } } let mut cache = self.env_cache.lock().unwrap(); if let Some(val) = cache.get(v) { return val.clone(); } if self.emit_rerun_if_env_changed && !provided_by_cargo(v) { self.cargo_output .print_metadata(&format_args!("cargo:rerun-if-env-changed={}", v)); } let r = env::var(v).ok().map(Arc::from); self.cargo_output .print_metadata(&format_args!("{} = {:?}", v, r)); cache.insert(v.to_string(), r.clone()); r } fn getenv_unwrap(&self, v: &str) -> Result, Error> { match self.getenv(v) { Some(s) => Ok(s), None => Err(Error::new( ErrorKind::EnvVarNotFound, format!("Environment variable {} not defined.", v), )), } } fn getenv_with_target_prefixes(&self, var_base: &str) -> Result, Error> { let target = self.get_target()?; let host = self.get_host()?; let kind = if host == target { "HOST" } else { "TARGET" }; let target_u = target.replace('-', "_"); let res = self .getenv(&format!("{}_{}", var_base, target)) .or_else(|| self.getenv(&format!("{}_{}", var_base, target_u))) .or_else(|| self.getenv(&format!("{}_{}", kind, var_base))) .or_else(|| self.getenv(var_base)); match res { Some(res) => Ok(res), None => Err(Error::new( ErrorKind::EnvVarNotFound, format!("Could not find environment variable {}.", var_base), )), } } fn envflags(&self, name: &str) -> Result, Error> { Ok(self .getenv_with_target_prefixes(name)? .split_ascii_whitespace() .map(|slice| slice.to_string()) .collect()) } fn fix_env_for_apple_os(&self, cmd: &mut Command) -> Result<(), Error> { let target = self.get_target()?; let host = self.get_host()?; if host.contains("apple-darwin") && target.contains("apple-darwin") { // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", // although this is apparently ignored when using the linker at "/usr/bin/ld". cmd.env_remove("IPHONEOS_DEPLOYMENT_TARGET"); } Ok(()) } fn apple_sdk_root(&self, sdk: &str) -> Result { if let Some(sdkroot) = env::var_os("SDKROOT") { return Ok(sdkroot); } let mut cache = self .apple_sdk_root_cache .lock() .expect("apple_sdk_root_cache lock failed"); if let Some(ret) = cache.get(sdk) { return Ok(ret.clone()); } let sdk_path = run_output( self.cmd("xcrun") .arg("--show-sdk-path") .arg("--sdk") .arg(sdk), "xcrun", &self.cargo_output, )?; let sdk_path = match String::from_utf8(sdk_path) { Ok(p) => p, Err(_) => { return Err(Error::new( ErrorKind::IOError, "Unable to determine Apple SDK path.", )); } }; let ret: OsString = sdk_path.trim().into(); cache.insert(sdk.into(), ret.clone()); Ok(ret) } fn apple_deployment_version(&self, os: AppleOs, arch_str: Option<&str>, sdk: &str) -> String { let default_deployment_from_sdk = || { let mut cache = self .apple_versions_cache .lock() .expect("apple_versions_cache lock failed"); if let Some(ret) = cache.get(sdk) { return Some(ret.clone()); } let version = run_output( self.cmd("xcrun") .arg("--show-sdk-platform-version") .arg("--sdk") .arg(sdk), "xcrun", &self.cargo_output, ) .ok()?; let version = std::str::from_utf8(&version).ok()?.trim().to_owned(); cache.insert(sdk.into(), version.clone()); Some(version) }; let deployment_from_env = |name: &str| { // note this isn't hit in production codepaths, its mostly just for tests which don't // set the real env if let Some((_, v)) = self.env.iter().find(|(k, _)| &**k == OsStr::new(name)) { Some(v.to_str().unwrap().to_string()) } else { env::var(name).ok() } }; // Determines if the acquired deployment target is too low to support modern C++ on some Apple platform. // // A long time ago they used libstdc++, but since macOS 10.9 and iOS 7 libc++ has been the library the SDKs provide to link against. // If a `cc`` config wants to use C++, we round up to these versions as the baseline. let maybe_cpp_version_baseline = |deployment_target_ver: String| -> Option { if !self.cpp { return Some(deployment_target_ver); } let mut deployment_target = deployment_target_ver .split('.') .map(|v| v.parse::().expect("integer version")); match os { AppleOs::MacOs => { let major = deployment_target.next().unwrap_or(0); let minor = deployment_target.next().unwrap_or(0); // If below 10.9, we ignore it and let the SDK's target definitions handle it. if major == 10 && minor < 9 { self.cargo_output.print_warning(&format_args!( "macOS deployment target ({}) too low, it will be increased", deployment_target_ver )); return None; } } AppleOs::Ios => { let major = deployment_target.next().unwrap_or(0); // If below 10.7, we ignore it and let the SDK's target definitions handle it. if major < 7 { self.cargo_output.print_warning(&format_args!( "iOS deployment target ({}) too low, it will be increased", deployment_target_ver )); return None; } } // watchOS, tvOS, and others are all new enough that libc++ is their baseline. _ => {} } // If the deployment target met or exceeded the C++ baseline Some(deployment_target_ver) }; // The hardcoded minimums here are subject to change in a future compiler release, // and only exist as last resort fallbacks. Don't consider them stable. // `cc` doesn't use rustc's `--print deployment-target`` because the compiler's defaults // don't align well with Apple's SDKs and other third-party libraries that require ~generally~ higher // deployment targets. rustc isn't interested in those by default though so its fine to be different here. // // If no explicit target is passed, `cc` defaults to the current Xcode SDK's `DefaultDeploymentTarget` for better // compatibility. This is also the crate's historical behavior and what has become a relied-on value. // // The ordering of env -> XCode SDK -> old rustc defaults is intentional for performance when using // an explicit target. match os { AppleOs::MacOs => deployment_from_env("MACOSX_DEPLOYMENT_TARGET") .and_then(maybe_cpp_version_baseline) .or_else(default_deployment_from_sdk) .unwrap_or_else(|| { if arch_str == Some("aarch64") { "11.0".into() } else { let default = "10.7"; maybe_cpp_version_baseline(default.into()).unwrap_or_else(|| default.into()) } }), AppleOs::Ios => deployment_from_env("IPHONEOS_DEPLOYMENT_TARGET") .and_then(maybe_cpp_version_baseline) .or_else(default_deployment_from_sdk) .unwrap_or_else(|| "7.0".into()), AppleOs::WatchOs => deployment_from_env("WATCHOS_DEPLOYMENT_TARGET") .or_else(default_deployment_from_sdk) .unwrap_or_else(|| "5.0".into()), AppleOs::TvOs => deployment_from_env("TVOS_DEPLOYMENT_TARGET") .or_else(default_deployment_from_sdk) .unwrap_or_else(|| "9.0".into()), } } fn cuda_file_count(&self) -> usize { self.files .iter() .filter(|file| file.extension() == Some(OsStr::new("cu"))) .count() } } impl Default for Build { fn default() -> Build { Build::new() } } fn fail(s: &str) -> ! { eprintln!("\n\nerror occurred: {}\n\n", s); std::process::exit(1); } #[derive(Clone, Copy, PartialEq)] enum AppleOs { MacOs, Ios, WatchOs, TvOs, } impl std::fmt::Debug for AppleOs { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { AppleOs::MacOs => f.write_str("macOS"), AppleOs::Ios => f.write_str("iOS"), AppleOs::WatchOs => f.write_str("WatchOS"), AppleOs::TvOs => f.write_str("AppleTVOS"), } } } struct AppleSdkTargetParts { sdk_prefix: &'static str, sim_prefix: &'static str, sdk: Cow<'static, str>, } fn apple_os_sdk_parts(os: AppleOs, arch: &AppleArchSpec) -> AppleSdkTargetParts { let (sdk_prefix, sim_prefix) = match os { AppleOs::MacOs => ("macosx", ""), AppleOs::Ios => ("iphone", "ios-"), AppleOs::WatchOs => ("watch", "watch"), AppleOs::TvOs => ("appletv", "appletv"), }; let sdk = match arch { AppleArchSpec::Device(_) if os == AppleOs::MacOs => Cow::Borrowed("macosx"), AppleArchSpec::Device(_) => format!("{}os", sdk_prefix).into(), AppleArchSpec::Simulator(_) => format!("{}simulator", sdk_prefix).into(), AppleArchSpec::Catalyst(_) => Cow::Borrowed("macosx"), }; AppleSdkTargetParts { sdk_prefix, sim_prefix, sdk, } } #[allow(dead_code)] enum AppleArchSpec { Device(&'static str), Simulator(&'static str), #[allow(dead_code)] Catalyst(&'static str), } // Use by default minimum available API level // See note about naming here // https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/docs/BuildSystemMaintainers.md#Clang static NEW_STANDALONE_ANDROID_COMPILERS: [&str; 4] = [ "aarch64-linux-android21-clang", "armv7a-linux-androideabi16-clang", "i686-linux-android16-clang", "x86_64-linux-android21-clang", ]; // New "standalone" C/C++ cross-compiler executables from recent Android NDK // are just shell scripts that call main clang binary (from Android NDK) with // proper `--target` argument. // // For example, armv7a-linux-androideabi16-clang passes // `--target=armv7a-linux-androideabi16` to clang. // So to construct proper command line check if // `--target` argument would be passed or not to clang fn android_clang_compiler_uses_target_arg_internally(clang_path: &Path) -> bool { if let Some(filename) = clang_path.file_name() { if let Some(filename_str) = filename.to_str() { if let Some(idx) = filename_str.rfind('-') { return filename_str.split_at(idx).0.contains("android"); } } } false } #[test] fn test_android_clang_compiler_uses_target_arg_internally() { for version in 16..21 { assert!(android_clang_compiler_uses_target_arg_internally( &PathBuf::from(format!("armv7a-linux-androideabi{}-clang", version)) )); assert!(android_clang_compiler_uses_target_arg_internally( &PathBuf::from(format!("armv7a-linux-androideabi{}-clang++", version)) )); } assert!(!android_clang_compiler_uses_target_arg_internally( &PathBuf::from("clang-i686-linux-android") )); assert!(!android_clang_compiler_uses_target_arg_internally( &PathBuf::from("clang") )); assert!(!android_clang_compiler_uses_target_arg_internally( &PathBuf::from("clang++") )); } fn autodetect_android_compiler(target: &str, host: &str, gnu: &str, clang: &str) -> String { let new_clang_key = match target { "aarch64-linux-android" => Some("aarch64"), "armv7-linux-androideabi" => Some("armv7a"), "i686-linux-android" => Some("i686"), "x86_64-linux-android" => Some("x86_64"), _ => None, }; let new_clang = new_clang_key .map(|key| { NEW_STANDALONE_ANDROID_COMPILERS .iter() .find(|x| x.starts_with(key)) }) .unwrap_or(None); if let Some(new_clang) = new_clang { if Command::new(new_clang).output().is_ok() { return (*new_clang).into(); } } let target = target .replace("armv7neon", "arm") .replace("armv7", "arm") .replace("thumbv7neon", "arm") .replace("thumbv7", "arm"); let gnu_compiler = format!("{}-{}", target, gnu); let clang_compiler = format!("{}-{}", target, clang); // On Windows, the Android clang compiler is provided as a `.cmd` file instead // of a `.exe` file. `std::process::Command` won't run `.cmd` files unless the // `.cmd` is explicitly appended to the command name, so we do that here. let clang_compiler_cmd = format!("{}-{}.cmd", target, clang); // Check if gnu compiler is present // if not, use clang if Command::new(&gnu_compiler).output().is_ok() { gnu_compiler } else if host.contains("windows") && Command::new(&clang_compiler_cmd).output().is_ok() { clang_compiler_cmd } else { clang_compiler } } // Rust and clang/cc don't agree on how to name the target. fn map_darwin_target_from_rust_to_compiler_architecture(target: &str) -> Option<&'static str> { if target.contains("x86_64h") { Some("x86_64h") } else if target.contains("x86_64") { Some("x86_64") } else if target.contains("arm64e") { Some("arm64e") } else if target.contains("aarch64") { Some("arm64") } else if target.contains("i686") { Some("i386") } else if target.contains("powerpc") { Some("ppc") } else if target.contains("powerpc64") { Some("ppc64") } else { None } } fn which(tool: &Path, path_entries: Option) -> Option { fn check_exe(exe: &mut PathBuf) -> bool { let exe_ext = std::env::consts::EXE_EXTENSION; exe.exists() || (!exe_ext.is_empty() && exe.set_extension(exe_ext) && exe.exists()) } // If |tool| is not just one "word," assume it's an actual path... if tool.components().count() > 1 { let mut exe = PathBuf::from(tool); return if check_exe(&mut exe) { Some(exe) } else { None }; } // Loop through PATH entries searching for the |tool|. let path_entries = path_entries.or(env::var_os("PATH"))?; env::split_paths(&path_entries).find_map(|path_entry| { let mut exe = path_entry.join(tool); if check_exe(&mut exe) { Some(exe) } else { None } }) } // search for |prog| on 'programs' path in '|cc| -print-search-dirs' output fn search_programs(cc: &mut Command, prog: &str, cargo_output: &CargoOutput) -> Option { let search_dirs = run_output( cc.arg("-print-search-dirs"), "cc", // this doesn't concern the compilation so we always want to show warnings. cargo_output, ) .ok()?; // clang driver appears to be forcing UTF-8 output even on Windows, // hence from_utf8 is assumed to be usable in all cases. let search_dirs = std::str::from_utf8(&search_dirs).ok()?; for dirs in search_dirs.split(|c| c == '\r' || c == '\n') { if let Some(path) = dirs.strip_prefix("programs: =") { return which(Path::new(prog), Some(OsString::from(path))); } } None } #[derive(Clone, Copy, PartialEq)] enum AsmFileExt { /// `.asm` files. On MSVC targets, we assume these should be passed to MASM /// (`ml{,64}.exe`). DotAsm, /// `.s` or `.S` files, which do not have the special handling on MSVC targets. DotS, } impl AsmFileExt { fn from_path(file: &Path) -> Option { if let Some(ext) = file.extension() { if let Some(ext) = ext.to_str() { let ext = ext.to_lowercase(); match &*ext { "asm" => return Some(AsmFileExt::DotAsm), "s" => return Some(AsmFileExt::DotS), _ => return None, } } } None } } cc/src/tool.rs0000644000175000017500000003166314661133735014251 0ustar jamespagejamespageuse std::{ collections::HashMap, ffi::OsString, path::{Path, PathBuf}, process::Command, sync::Mutex, }; use crate::command_helpers::{run_output, CargoOutput}; /// Configuration used to represent an invocation of a C compiler. /// /// This can be used to figure out what compiler is in use, what the arguments /// to it are, and what the environment variables look like for the compiler. /// This can be used to further configure other build systems (e.g. forward /// along CC and/or CFLAGS) or the `to_command` method can be used to run the /// compiler itself. #[derive(Clone, Debug)] #[allow(missing_docs)] pub struct Tool { pub(crate) path: PathBuf, pub(crate) cc_wrapper_path: Option, pub(crate) cc_wrapper_args: Vec, pub(crate) args: Vec, pub(crate) env: Vec<(OsString, OsString)>, pub(crate) family: ToolFamily, pub(crate) cuda: bool, pub(crate) removed_args: Vec, pub(crate) has_internal_target_arg: bool, } impl Tool { pub(crate) fn new( path: PathBuf, cached_compiler_family: &Mutex, ToolFamily>>, cargo_output: &CargoOutput, ) -> Self { Self::with_features(path, None, false, cached_compiler_family, cargo_output) } pub(crate) fn with_clang_driver( path: PathBuf, clang_driver: Option<&str>, cached_compiler_family: &Mutex, ToolFamily>>, cargo_output: &CargoOutput, ) -> Self { Self::with_features( path, clang_driver, false, cached_compiler_family, cargo_output, ) } /// Explicitly set the `ToolFamily`, skipping name-based detection. pub(crate) fn with_family(path: PathBuf, family: ToolFamily) -> Self { Self { path, cc_wrapper_path: None, cc_wrapper_args: Vec::new(), args: Vec::new(), env: Vec::new(), family, cuda: false, removed_args: Vec::new(), has_internal_target_arg: false, } } pub(crate) fn with_features( path: PathBuf, clang_driver: Option<&str>, cuda: bool, cached_compiler_family: &Mutex, ToolFamily>>, cargo_output: &CargoOutput, ) -> Self { fn detect_family_inner(path: &Path, cargo_output: &CargoOutput) -> ToolFamily { let mut cmd = Command::new(path); cmd.arg("--version"); let stdout = match run_output( &mut cmd, &path.to_string_lossy(), // tool detection issues should always be shown as warnings cargo_output, ) .ok() .and_then(|o| String::from_utf8(o).ok()) { Some(s) => s, None => { // --version failed. fallback to gnu cargo_output.print_warning(&format_args!("Failed to run: {:?}", cmd)); return ToolFamily::Gnu; } }; if stdout.contains("clang") { ToolFamily::Clang } else if stdout.contains("GCC") { ToolFamily::Gnu } else { // --version doesn't include clang for GCC cargo_output.print_warning(&format_args!( "Compiler version doesn't include clang or GCC: {:?}", cmd )); ToolFamily::Gnu } } let detect_family = |path: &Path| -> ToolFamily { if let Some(family) = cached_compiler_family.lock().unwrap().get(path) { return *family; } let family = detect_family_inner(path, cargo_output); cached_compiler_family .lock() .unwrap() .insert(path.into(), family); family }; // Try to detect family of the tool from its name, falling back to Gnu. let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) { if fname.contains("clang-cl") { ToolFamily::Msvc { clang_cl: true } } else if fname.ends_with("cl") || fname == "cl.exe" { ToolFamily::Msvc { clang_cl: false } } else if fname.contains("clang") { match clang_driver { Some("cl") => ToolFamily::Msvc { clang_cl: true }, _ => ToolFamily::Clang, } } else { detect_family(&path) } } else { detect_family(&path) }; Tool { path, cc_wrapper_path: None, cc_wrapper_args: Vec::new(), args: Vec::new(), env: Vec::new(), family, cuda, removed_args: Vec::new(), has_internal_target_arg: false, } } /// Add an argument to be stripped from the final command arguments. pub(crate) fn remove_arg(&mut self, flag: OsString) { self.removed_args.push(flag); } /// Push an "exotic" flag to the end of the compiler's arguments list. /// /// Nvidia compiler accepts only the most common compiler flags like `-D`, /// `-I`, `-c`, etc. Options meant specifically for the underlying /// host C++ compiler have to be prefixed with `-Xcompiler`. /// [Another possible future application for this function is passing /// clang-specific flags to clang-cl, which otherwise accepts only /// MSVC-specific options.] pub(crate) fn push_cc_arg(&mut self, flag: OsString) { if self.cuda { self.args.push("-Xcompiler".into()); } self.args.push(flag); } /// Checks if an argument or flag has already been specified or conflicts. /// /// Currently only checks optimization flags. pub(crate) fn is_duplicate_opt_arg(&self, flag: &OsString) -> bool { let flag = flag.to_str().unwrap(); let mut chars = flag.chars(); // Only duplicate check compiler flags if self.is_like_msvc() { if chars.next() != Some('/') { return false; } } else if self.is_like_gnu() || self.is_like_clang() { if chars.next() != Some('-') { return false; } } // Check for existing optimization flags (-O, /O) if chars.next() == Some('O') { return self .args() .iter() .any(|a| a.to_str().unwrap_or("").chars().nth(1) == Some('O')); } // TODO Check for existing -m..., -m...=..., /arch:... flags false } /// Don't push optimization arg if it conflicts with existing args. pub(crate) fn push_opt_unless_duplicate(&mut self, flag: OsString) { if self.is_duplicate_opt_arg(&flag) { println!("Info: Ignoring duplicate arg {:?}", &flag); } else { self.push_cc_arg(flag); } } /// Converts this compiler into a `Command` that's ready to be run. /// /// This is useful for when the compiler needs to be executed and the /// command returned will already have the initial arguments and environment /// variables configured. pub fn to_command(&self) -> Command { let mut cmd = match self.cc_wrapper_path { Some(ref cc_wrapper_path) => { let mut cmd = Command::new(cc_wrapper_path); cmd.arg(&self.path); cmd } None => Command::new(&self.path), }; cmd.args(&self.cc_wrapper_args); let value = self .args .iter() .filter(|a| !self.removed_args.contains(a)) .collect::>(); cmd.args(&value); for (k, v) in self.env.iter() { cmd.env(k, v); } cmd } /// Returns the path for this compiler. /// /// Note that this may not be a path to a file on the filesystem, e.g. "cc", /// but rather something which will be resolved when a process is spawned. pub fn path(&self) -> &Path { &self.path } /// Returns the default set of arguments to the compiler needed to produce /// executables for the target this compiler generates. pub fn args(&self) -> &[OsString] { &self.args } /// Returns the set of environment variables needed for this compiler to /// operate. /// /// This is typically only used for MSVC compilers currently. pub fn env(&self) -> &[(OsString, OsString)] { &self.env } /// Returns the compiler command in format of CC environment variable. /// Or empty string if CC env was not present /// /// This is typically used by configure script pub fn cc_env(&self) -> OsString { match self.cc_wrapper_path { Some(ref cc_wrapper_path) => { let mut cc_env = cc_wrapper_path.as_os_str().to_owned(); cc_env.push(" "); cc_env.push(self.path.to_path_buf().into_os_string()); for arg in self.cc_wrapper_args.iter() { cc_env.push(" "); cc_env.push(arg); } cc_env } None => OsString::from(""), } } /// Returns the compiler flags in format of CFLAGS environment variable. /// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS /// This is typically used by configure script pub fn cflags_env(&self) -> OsString { let mut flags = OsString::new(); for (i, arg) in self.args.iter().enumerate() { if i > 0 { flags.push(" "); } flags.push(arg); } flags } /// Whether the tool is GNU Compiler Collection-like. pub fn is_like_gnu(&self) -> bool { self.family == ToolFamily::Gnu } /// Whether the tool is Clang-like. pub fn is_like_clang(&self) -> bool { self.family == ToolFamily::Clang } /// Whether the tool is AppleClang under .xctoolchain #[cfg(target_vendor = "apple")] pub(crate) fn is_xctoolchain_clang(&self) -> bool { let path = self.path.to_string_lossy(); path.contains(".xctoolchain/") } #[cfg(not(target_vendor = "apple"))] pub(crate) fn is_xctoolchain_clang(&self) -> bool { false } /// Whether the tool is MSVC-like. pub fn is_like_msvc(&self) -> bool { match self.family { ToolFamily::Msvc { .. } => true, _ => false, } } } /// Represents the family of tools this tool belongs to. /// /// Each family of tools differs in how and what arguments they accept. /// /// Detection of a family is done on best-effort basis and may not accurately reflect the tool. #[derive(Copy, Clone, Debug, PartialEq)] pub enum ToolFamily { /// Tool is GNU Compiler Collection-like. Gnu, /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags /// and its cross-compilation approach is different. Clang, /// Tool is the MSVC cl.exe. Msvc { clang_cl: bool }, } impl ToolFamily { /// What the flag to request debug info for this family of tools look like pub(crate) fn add_debug_flags(&self, cmd: &mut Tool, dwarf_version: Option) { match *self { ToolFamily::Msvc { .. } => { cmd.push_cc_arg("-Z7".into()); } ToolFamily::Gnu | ToolFamily::Clang => { cmd.push_cc_arg( dwarf_version .map_or_else(|| "-g".into(), |v| format!("-gdwarf-{}", v)) .into(), ); } } } /// What the flag to force frame pointers. pub(crate) fn add_force_frame_pointer(&self, cmd: &mut Tool) { match *self { ToolFamily::Gnu | ToolFamily::Clang => { cmd.push_cc_arg("-fno-omit-frame-pointer".into()); } _ => (), } } /// What the flags to enable all warnings pub(crate) fn warnings_flags(&self) -> &'static str { match *self { ToolFamily::Msvc { .. } => "-W4", ToolFamily::Gnu | ToolFamily::Clang => "-Wall", } } /// What the flags to enable extra warnings pub(crate) fn extra_warnings_flags(&self) -> Option<&'static str> { match *self { ToolFamily::Msvc { .. } => None, ToolFamily::Gnu | ToolFamily::Clang => Some("-Wextra"), } } /// What the flag to turn warning into errors pub(crate) fn warnings_to_errors_flag(&self) -> &'static str { match *self { ToolFamily::Msvc { .. } => "-WX", ToolFamily::Gnu | ToolFamily::Clang => "-Werror", } } pub(crate) fn verbose_stderr(&self) -> bool { *self == ToolFamily::Clang } } cc/src/parallel/0000775000175000017500000000000014661133735014513 5ustar jamespagejamespagecc/src/parallel/async_executor.rs0000644000175000017500000000677614661133735020132 0ustar jamespagejamespageuse std::{ cell::Cell, future::Future, pin::Pin, ptr, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, thread, time::Duration, }; use crate::Error; const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new( // Cloning just returns a new no-op raw waker |_| NOOP_RAW_WAKER, // `wake` does nothing |_| {}, // `wake_by_ref` does nothing |_| {}, // Dropping does nothing as we don't allocate anything |_| {}, ); const NOOP_RAW_WAKER: RawWaker = RawWaker::new(ptr::null(), &NOOP_WAKER_VTABLE); #[derive(Default)] pub(crate) struct YieldOnce(bool); impl Future for YieldOnce { type Output = (); fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<()> { let flag = &mut std::pin::Pin::into_inner(self).0; if !*flag { *flag = true; Poll::Pending } else { Poll::Ready(()) } } } /// Execute the futures and return when they are all done. /// /// Here we use our own homebrew async executor since cc is used in the build /// script of many popular projects, pulling in additional dependencies would /// significantly slow down its compilation. pub(crate) fn block_on( mut fut1: Fut1, mut fut2: Fut2, has_made_progress: &Cell, ) -> Result<(), Error> where Fut1: Future>, Fut2: Future>, { // Shadows the future so that it can never be moved and is guaranteed // to be pinned. // // The same trick used in `pin!` macro. // // TODO: Once MSRV is bumped to 1.68, replace this with `std::pin::pin!` let mut fut1 = Some(unsafe { Pin::new_unchecked(&mut fut1) }); let mut fut2 = Some(unsafe { Pin::new_unchecked(&mut fut2) }); // TODO: Once `Waker::noop` stablised and our MSRV is bumped to the version // which it is stablised, replace this with `Waker::noop`. let waker = unsafe { Waker::from_raw(NOOP_RAW_WAKER) }; let mut context = Context::from_waker(&waker); let mut backoff_cnt = 0; loop { has_made_progress.set(false); if let Some(fut) = fut2.as_mut() { if let Poll::Ready(res) = fut.as_mut().poll(&mut context) { fut2 = None; res?; } } if let Some(fut) = fut1.as_mut() { if let Poll::Ready(res) = fut.as_mut().poll(&mut context) { fut1 = None; res?; } } if fut1.is_none() && fut2.is_none() { return Ok(()); } if !has_made_progress.get() { if backoff_cnt > 3 { // We have yielded at least three times without making' // any progress, so we will sleep for a while. let duration = Duration::from_millis(100 * (backoff_cnt - 3).min(10)); thread::sleep(duration); } else { // Given that we spawned a lot of compilation tasks, it is unlikely // that OS cannot find other ready task to execute. // // If all of them are done, then we will yield them and spawn more, // or simply return. // // Thus this will not be turned into a busy-wait loop and it will not // waste CPU resource. thread::yield_now(); } } backoff_cnt = if has_made_progress.get() { 0 } else { backoff_cnt + 1 }; } } cc/src/parallel/mod.rs0000644000175000017500000000073314661133735015641 0ustar jamespagejamespagepub(crate) mod async_executor; pub(crate) mod job_token; pub(crate) mod stderr; /// Remove all element in `vec` which `f(element)` returns `false`. /// /// TODO: Remove this once the MSRV is bumped to v1.61 pub(crate) fn retain_unordered_mut(vec: &mut Vec, mut f: F) where F: FnMut(&mut T) -> bool, { let mut i = 0; while i < vec.len() { if f(&mut vec[i]) { i += 1; } else { vec.swap_remove(i); } } } cc/src/parallel/stderr.rs0000644000175000017500000000513114661133735016362 0ustar jamespagejamespage/// Helpers functions for [ChildStderr]. use std::{convert::TryInto, process::ChildStderr}; use crate::{Error, ErrorKind}; #[cfg(all(not(unix), not(windows)))] compile_error!("Only unix and windows support non-blocking pipes! For other OSes, disable the parallel feature."); #[cfg(unix)] fn get_flags(fd: std::os::unix::io::RawFd) -> Result { let flags = unsafe { libc::fcntl(fd, libc::F_GETFL, 0) }; if flags == -1 { Err(Error::new( ErrorKind::IOError, format!( "Failed to get flags for pipe {}: {}", fd, std::io::Error::last_os_error() ), )) } else { Ok(flags) } } #[cfg(unix)] fn set_flags(fd: std::os::unix::io::RawFd, flags: std::os::raw::c_int) -> Result<(), Error> { if unsafe { libc::fcntl(fd, libc::F_SETFL, flags) } == -1 { Err(Error::new( ErrorKind::IOError, format!( "Failed to set flags for pipe {}: {}", fd, std::io::Error::last_os_error() ), )) } else { Ok(()) } } #[cfg(unix)] pub fn set_non_blocking(pipe: &impl std::os::unix::io::AsRawFd) -> Result<(), Error> { // On Unix, switch the pipe to non-blocking mode. // On Windows, we have a different way to be non-blocking. let fd = pipe.as_raw_fd(); let flags = get_flags(fd)?; set_flags(fd, flags | libc::O_NONBLOCK) } pub fn bytes_available(stderr: &mut ChildStderr) -> Result { let mut bytes_available = 0; #[cfg(windows)] { use crate::windows::windows_sys::PeekNamedPipe; use std::os::windows::io::AsRawHandle; use std::ptr::null_mut; if unsafe { PeekNamedPipe( stderr.as_raw_handle(), null_mut(), 0, null_mut(), &mut bytes_available, null_mut(), ) } == 0 { return Err(Error::new( ErrorKind::IOError, format!( "PeekNamedPipe failed with {}", std::io::Error::last_os_error() ), )); } } #[cfg(unix)] { use std::os::unix::io::AsRawFd; if unsafe { libc::ioctl(stderr.as_raw_fd(), libc::FIONREAD, &mut bytes_available) } != 0 { return Err(Error::new( ErrorKind::IOError, format!("ioctl failed with {}", std::io::Error::last_os_error()), )); } } Ok(bytes_available.try_into().unwrap()) } cc/src/parallel/job_token.rs0000644000175000017500000002131414661133735017032 0ustar jamespagejamespageuse std::{marker::PhantomData, mem::MaybeUninit, sync::Once}; use crate::Error; pub(crate) struct JobToken(PhantomData<()>); impl JobToken { fn new() -> Self { Self(PhantomData) } } impl Drop for JobToken { fn drop(&mut self) { match JobTokenServer::new() { JobTokenServer::Inherited(jobserver) => jobserver.release_token_raw(), JobTokenServer::InProcess(jobserver) => jobserver.release_token_raw(), } } } enum JobTokenServer { Inherited(inherited_jobserver::JobServer), InProcess(inprocess_jobserver::JobServer), } impl JobTokenServer { /// This function returns a static reference to the jobserver because /// - creating a jobserver from env is a bit fd-unsafe (e.g. the fd might /// be closed by other jobserver users in the process) and better do it /// at the start of the program. /// - in case a jobserver cannot be created from env (e.g. it's not /// present), we will create a global in-process only jobserver /// that has to be static so that it will be shared by all cc /// compilation. fn new() -> &'static Self { static INIT: Once = Once::new(); static mut JOBSERVER: MaybeUninit = MaybeUninit::uninit(); unsafe { INIT.call_once(|| { let server = inherited_jobserver::JobServer::from_env() .map(Self::Inherited) .unwrap_or_else(|| Self::InProcess(inprocess_jobserver::JobServer::new())); JOBSERVER = MaybeUninit::new(server); }); // TODO: Poor man's assume_init_ref, as that'd require a MSRV of 1.55. &*JOBSERVER.as_ptr() } } } pub(crate) enum ActiveJobTokenServer { Inherited(inherited_jobserver::ActiveJobServer<'static>), InProcess(&'static inprocess_jobserver::JobServer), } impl ActiveJobTokenServer { pub(crate) fn new() -> Result { match JobTokenServer::new() { JobTokenServer::Inherited(inherited_jobserver) => { inherited_jobserver.enter_active().map(Self::Inherited) } JobTokenServer::InProcess(inprocess_jobserver) => { Ok(Self::InProcess(inprocess_jobserver)) } } } pub(crate) async fn acquire(&self) -> Result { match &self { Self::Inherited(jobserver) => jobserver.acquire().await, Self::InProcess(jobserver) => Ok(jobserver.acquire().await), } } } mod inherited_jobserver { use super::JobToken; use crate::{parallel::async_executor::YieldOnce, Error, ErrorKind}; use std::{ io, mem, sync::{mpsc, Mutex, MutexGuard, PoisonError}, }; pub(super) struct JobServer { /// Implicit token for this process which is obtained and will be /// released in parent. Since JobTokens only give back what they got, /// there should be at most one global implicit token in the wild. /// /// Since Rust does not execute any `Drop` for global variables, /// we can't just put it back to jobserver and then re-acquire it at /// the end of the process. /// /// Use `Mutex` to avoid race between acquire and release. /// If an `AtomicBool` is used, then it's possible for: /// - `release_token_raw`: Tries to set `global_implicit_token` to true, but it is already /// set to `true`, continue to release it to jobserver /// - `acquire` takes the global implicit token, set `global_implicit_token` to false /// - `release_token_raw` now writes the token back into the jobserver, while /// `global_implicit_token` is `false` /// /// If the program exits here, then cc effectively increases parallelism by one, which is /// incorrect, hence we use a `Mutex` here. global_implicit_token: Mutex, inner: jobserver::Client, } impl JobServer { pub(super) unsafe fn from_env() -> Option { jobserver::Client::from_env().map(|inner| Self { inner, global_implicit_token: Mutex::new(true), }) } fn get_global_implicit_token(&self) -> MutexGuard<'_, bool> { self.global_implicit_token .lock() .unwrap_or_else(PoisonError::into_inner) } /// All tokens except for the global implicit token will be put back into the jobserver /// immediately and they cannot be cached, since Rust does not call `Drop::drop` on /// global variables. pub(super) fn release_token_raw(&self) { let mut global_implicit_token = self.get_global_implicit_token(); if *global_implicit_token { // There's already a global implicit token, so this token must // be released back into jobserver. // // `release_raw` should not block let _ = self.inner.release_raw(); } else { *global_implicit_token = true; } } pub(super) fn enter_active(&self) -> Result, Error> { ActiveJobServer::new(self) } } pub(crate) struct ActiveJobServer<'a> { jobserver: &'a JobServer, helper_thread: jobserver::HelperThread, /// When rx is dropped, all the token stored within it will be dropped. rx: mpsc::Receiver>, } impl<'a> ActiveJobServer<'a> { fn new(jobserver: &'a JobServer) -> Result { let (tx, rx) = mpsc::channel(); Ok(Self { rx, helper_thread: jobserver.inner.clone().into_helper_thread(move |res| { let _ = tx.send(res); })?, jobserver, }) } pub(super) async fn acquire(&self) -> Result { let mut has_requested_token = false; loop { // Fast path if mem::replace(&mut *self.jobserver.get_global_implicit_token(), false) { break Ok(JobToken::new()); } // Cold path, no global implicit token, obtain one match self.rx.try_recv() { Ok(res) => { let acquired = res?; acquired.drop_without_releasing(); break Ok(JobToken::new()); } Err(mpsc::TryRecvError::Disconnected) => { break Err(Error::new( ErrorKind::JobserverHelpThreadError, "jobserver help thread has returned before ActiveJobServer is dropped", )) } Err(mpsc::TryRecvError::Empty) => { if !has_requested_token { self.helper_thread.request_token(); has_requested_token = true; } YieldOnce::default().await } } } } } } mod inprocess_jobserver { use super::JobToken; use crate::parallel::async_executor::YieldOnce; use std::{ env::var, sync::atomic::{ AtomicU32, Ordering::{AcqRel, Acquire}, }, }; pub(crate) struct JobServer(AtomicU32); impl JobServer { pub(super) fn new() -> Self { // Use `NUM_JOBS` if set (it's configured by Cargo) and otherwise // just fall back to a semi-reasonable number. // // Note that we could use `num_cpus` here but it's an extra // dependency that will almost never be used, so // it's generally not too worth it. let mut parallelism = 4; // TODO: Use std::thread::available_parallelism as an upper bound // when MSRV is bumped. if let Ok(amt) = var("NUM_JOBS") { if let Ok(amt) = amt.parse() { parallelism = amt; } } Self(AtomicU32::new(parallelism)) } pub(super) async fn acquire(&self) -> JobToken { loop { let res = self .0 .fetch_update(AcqRel, Acquire, |tokens| tokens.checked_sub(1)); if res.is_ok() { break JobToken::new(); } YieldOnce::default().await } } pub(super) fn release_token_raw(&self) { self.0.fetch_add(1, AcqRel); } } } cc/src/windows/0000775000175000017500000000000014661133735014411 5ustar jamespagejamespagecc/src/windows/setup_config.rs0000644000175000017500000002127714661133735017453 0ustar jamespagejamespage// Copyright © 2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style)] #![allow(unused)] use crate::windows::{ com::{BStr, ComPtr}, winapi::{ IUnknown, IUnknownVtbl, Interface, LCID, LPCOLESTR, LPCWSTR, LPFILETIME, LPSAFEARRAY, PULONGLONG, ULONG, }, windows_sys::{CoCreateInstance, BSTR, CLSCTX_ALL, HRESULT, S_FALSE}, }; use std::{ ffi::OsString, ptr::{null, null_mut}, }; // Bindings to the Setup.Configuration stuff pub type InstanceState = u32; pub const eNone: InstanceState = 0; pub const eLocal: InstanceState = 1; pub const eRegistered: InstanceState = 2; pub const eNoRebootRequired: InstanceState = 4; pub const eComplete: InstanceState = -1i32 as u32; RIDL! {#[uuid(0xb41463c3, 0x8866, 0x43b5, 0xbc, 0x33, 0x2b, 0x06, 0x76, 0xf7, 0xf4, 0x2e)] interface ISetupInstance(ISetupInstanceVtbl): IUnknown(IUnknownVtbl) { fn GetInstanceId( pbstrInstanceId: *mut BSTR, ) -> HRESULT, fn GetInstallDate( pInstallDate: LPFILETIME, ) -> HRESULT, fn GetInstallationName( pbstrInstallationName: *mut BSTR, ) -> HRESULT, fn GetInstallationPath( pbstrInstallationPath: *mut BSTR, ) -> HRESULT, fn GetInstallationVersion( pbstrInstallationVersion: *mut BSTR, ) -> HRESULT, fn GetDisplayName( lcid: LCID, pbstrDisplayName: *mut BSTR, ) -> HRESULT, fn GetDescription( lcid: LCID, pbstrDescription: *mut BSTR, ) -> HRESULT, fn ResolvePath( pwszRelativePath: LPCOLESTR, pbstrAbsolutePath: *mut BSTR, ) -> HRESULT, }} RIDL! {#[uuid(0x89143c9a, 0x05af, 0x49b0, 0xb7, 0x17, 0x72, 0xe2, 0x18, 0xa2, 0x18, 0x5c)] interface ISetupInstance2(ISetupInstance2Vtbl): ISetupInstance(ISetupInstanceVtbl) { fn GetState( pState: *mut InstanceState, ) -> HRESULT, fn GetPackages( ppsaPackages: *mut LPSAFEARRAY, ) -> HRESULT, fn GetProduct( ppPackage: *mut *mut ISetupPackageReference, ) -> HRESULT, fn GetProductPath( pbstrProductPath: *mut BSTR, ) -> HRESULT, }} RIDL! {#[uuid(0x6380bcff, 0x41d3, 0x4b2e, 0x8b, 0x2e, 0xbf, 0x8a, 0x68, 0x10, 0xc8, 0x48)] interface IEnumSetupInstances(IEnumSetupInstancesVtbl): IUnknown(IUnknownVtbl) { fn Next( celt: ULONG, rgelt: *mut *mut ISetupInstance, pceltFetched: *mut ULONG, ) -> HRESULT, fn Skip( celt: ULONG, ) -> HRESULT, fn Reset() -> HRESULT, fn Clone( ppenum: *mut *mut IEnumSetupInstances, ) -> HRESULT, }} RIDL! {#[uuid(0x42843719, 0xdb4c, 0x46c2, 0x8e, 0x7c, 0x64, 0xf1, 0x81, 0x6e, 0xfd, 0x5b)] interface ISetupConfiguration(ISetupConfigurationVtbl): IUnknown(IUnknownVtbl) { fn EnumInstances( ppEnumInstances: *mut *mut IEnumSetupInstances, ) -> HRESULT, fn GetInstanceForCurrentProcess( ppInstance: *mut *mut ISetupInstance, ) -> HRESULT, fn GetInstanceForPath( wzPath: LPCWSTR, ppInstance: *mut *mut ISetupInstance, ) -> HRESULT, }} RIDL! {#[uuid(0x26aab78c, 0x4a60, 0x49d6, 0xaf, 0x3b, 0x3c, 0x35, 0xbc, 0x93, 0x36, 0x5d)] interface ISetupConfiguration2(ISetupConfiguration2Vtbl): ISetupConfiguration(ISetupConfigurationVtbl) { fn EnumAllInstances( ppEnumInstances: *mut *mut IEnumSetupInstances, ) -> HRESULT, }} RIDL! {#[uuid(0xda8d8a16, 0xb2b6, 0x4487, 0xa2, 0xf1, 0x59, 0x4c, 0xcc, 0xcd, 0x6b, 0xf5)] interface ISetupPackageReference(ISetupPackageReferenceVtbl): IUnknown(IUnknownVtbl) { fn GetId( pbstrId: *mut BSTR, ) -> HRESULT, fn GetVersion( pbstrVersion: *mut BSTR, ) -> HRESULT, fn GetChip( pbstrChip: *mut BSTR, ) -> HRESULT, fn GetLanguage( pbstrLanguage: *mut BSTR, ) -> HRESULT, fn GetBranch( pbstrBranch: *mut BSTR, ) -> HRESULT, fn GetType( pbstrType: *mut BSTR, ) -> HRESULT, fn GetUniqueId( pbstrUniqueId: *mut BSTR, ) -> HRESULT, }} RIDL! {#[uuid(0x42b21b78, 0x6192, 0x463e, 0x87, 0xbf, 0xd5, 0x77, 0x83, 0x8f, 0x1d, 0x5c)] interface ISetupHelper(ISetupHelperVtbl): IUnknown(IUnknownVtbl) { fn ParseVersion( pwszVersion: LPCOLESTR, pullVersion: PULONGLONG, ) -> HRESULT, fn ParseVersionRange( pwszVersionRange: LPCOLESTR, pullMinVersion: PULONGLONG, pullMaxVersion: PULONGLONG, ) -> HRESULT, }} DEFINE_GUID! {CLSID_SetupConfiguration, 0x177f0c4a, 0x1cd3, 0x4de7, 0xa3, 0x2c, 0x71, 0xdb, 0xbb, 0x9f, 0xa3, 0x6d} // Safe wrapper around the COM interfaces pub struct SetupConfiguration(ComPtr); impl SetupConfiguration { pub fn new() -> Result { let mut obj = null_mut(); let err = unsafe { CoCreateInstance( &CLSID_SetupConfiguration, null_mut(), CLSCTX_ALL, &ISetupConfiguration::uuidof(), &mut obj, ) }; if err < 0 { return Err(err); } let obj = unsafe { ComPtr::from_raw(obj as *mut ISetupConfiguration) }; Ok(SetupConfiguration(obj)) } pub fn get_instance_for_current_process(&self) -> Result { let mut obj = null_mut(); let err = unsafe { self.0.GetInstanceForCurrentProcess(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { SetupInstance::from_raw(obj) }) } pub fn enum_instances(&self) -> Result { let mut obj = null_mut(); let err = unsafe { self.0.EnumInstances(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { EnumSetupInstances::from_raw(obj) }) } pub fn enum_all_instances(&self) -> Result { let mut obj = null_mut(); let this = self.0.cast::()?; let err = unsafe { this.EnumAllInstances(&mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { EnumSetupInstances::from_raw(obj) }) } } pub struct SetupInstance(ComPtr); impl SetupInstance { pub unsafe fn from_raw(obj: *mut ISetupInstance) -> SetupInstance { SetupInstance(ComPtr::from_raw(obj)) } pub fn instance_id(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstanceId(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_name(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstallationName(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_path(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstallationPath(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn installation_version(&self) -> Result { let mut s = null(); let err = unsafe { self.0.GetInstallationVersion(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } pub fn product_path(&self) -> Result { let mut s = null(); let this = self.0.cast::()?; let err = unsafe { this.GetProductPath(&mut s) }; let bstr = unsafe { BStr::from_raw(s) }; if err < 0 { return Err(err); } Ok(bstr.to_osstring()) } } pub struct EnumSetupInstances(ComPtr); impl EnumSetupInstances { pub unsafe fn from_raw(obj: *mut IEnumSetupInstances) -> EnumSetupInstances { EnumSetupInstances(ComPtr::from_raw(obj)) } } impl Iterator for EnumSetupInstances { type Item = Result; fn next(&mut self) -> Option> { let mut obj = null_mut(); let err = unsafe { self.0.Next(1, &mut obj, null_mut()) }; if err < 0 { return Some(Err(err)); } if err == S_FALSE { return None; } Some(Ok(unsafe { SetupInstance::from_raw(obj) })) } } cc/src/windows/registry.rs0000644000175000017500000001445114661133735016632 0ustar jamespagejamespage// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use crate::windows::windows_sys::{ RegCloseKey, RegEnumKeyExW, RegOpenKeyExW, RegQueryValueExW, ERROR_NO_MORE_ITEMS, ERROR_SUCCESS, HKEY, HKEY_LOCAL_MACHINE, KEY_READ, KEY_WOW64_32KEY, REG_SZ, }; use std::{ ffi::{OsStr, OsString}, io, ops::RangeFrom, os::windows::prelude::*, ptr::null_mut, }; /// Must never be `HKEY_PERFORMANCE_DATA`. pub(crate) struct RegistryKey(Repr); #[allow(clippy::upper_case_acronyms)] type DWORD = u32; struct OwnedKey(HKEY); /// Note: must not encode `HKEY_PERFORMANCE_DATA` or one of its subkeys. enum Repr { /// `HKEY_LOCAL_MACHINE`. LocalMachine, /// A subkey of `HKEY_LOCAL_MACHINE`. Owned(OwnedKey), } pub struct Iter<'a> { idx: RangeFrom, key: &'a RegistryKey, } unsafe impl Sync for Repr {} unsafe impl Send for Repr {} pub(crate) const LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::LocalMachine); impl RegistryKey { fn raw(&self) -> HKEY { match self.0 { Repr::LocalMachine => HKEY_LOCAL_MACHINE, Repr::Owned(ref val) => val.0, } } /// Open a sub-key of `self`. pub fn open(&self, key: &OsStr) -> io::Result { let key = key.encode_wide().chain(Some(0)).collect::>(); let mut ret = null_mut(); let err = unsafe { RegOpenKeyExW( self.raw(), key.as_ptr(), 0, KEY_READ | KEY_WOW64_32KEY, &mut ret, ) }; if err == ERROR_SUCCESS { Ok(RegistryKey(Repr::Owned(OwnedKey(ret)))) } else { Err(io::Error::from_raw_os_error(err as i32)) } } pub fn iter(&self) -> Iter { Iter { idx: 0.., key: self, } } pub fn query_str(&self, name: &str) -> io::Result { let name: &OsStr = name.as_ref(); let name = name.encode_wide().chain(Some(0)).collect::>(); let mut len = 0; let mut kind = 0; unsafe { let err = RegQueryValueExW( self.raw(), name.as_ptr(), null_mut(), &mut kind, null_mut(), &mut len, ); if err != ERROR_SUCCESS { return Err(io::Error::from_raw_os_error(err as i32)); } if kind != REG_SZ { return Err(io::Error::new( io::ErrorKind::Other, "registry key wasn't a string", )); } // The length here is the length in bytes, but we're using wide // characters so we need to be sure to halve it for the length // passed in. assert!(len % 2 == 0, "impossible wide string size: {} bytes", len); let vlen = len as usize / 2; // Defensively initialized, see comment about // `HKEY_PERFORMANCE_DATA` below. let mut v = vec![0u16; vlen]; let err = RegQueryValueExW( self.raw(), name.as_ptr(), null_mut(), null_mut(), v.as_mut_ptr() as *mut _, &mut len, ); // We don't check for `ERROR_MORE_DATA` (which would if the value // grew between the first and second call to `RegQueryValueExW`), // both because it's extremely unlikely, and this is a bit more // defensive more defensive against weird types of registry keys. if err != ERROR_SUCCESS { return Err(io::Error::from_raw_os_error(err as i32)); } // The length is allowed to change, but should still be even, as // well as smaller. assert!(len % 2 == 0, "impossible wide string size: {} bytes", len); // If the length grew but returned a success code, it *probably* // indicates we're `HKEY_PERFORMANCE_DATA` or a subkey(?). We // consider this UB, since those keys write "undefined" or // "unpredictable" values to len, and need to use a completely // different loop structure. This should be impossible (and enforce // it in the API to the best of our ability), but to mitigate the // damage we do some smoke-checks on the len, and ensure `v` has // been fully initialized (rather than trusting the result of // `RegQueryValueExW`). let actual_len = len as usize / 2; assert!(actual_len <= v.len()); v.truncate(actual_len); // Some registry keys may have a terminating nul character, but // we're not interested in that, so chop it off if it's there. if !v.is_empty() && v[v.len() - 1] == 0 { v.pop(); } Ok(OsString::from_wide(&v)) } } } impl Drop for OwnedKey { fn drop(&mut self) { unsafe { RegCloseKey(self.0); } } } impl<'a> Iterator for Iter<'a> { type Item = io::Result; fn next(&mut self) -> Option> { self.idx.next().and_then(|i| unsafe { let mut v = Vec::with_capacity(256); let mut len = v.capacity() as DWORD; let ret = RegEnumKeyExW( self.key.raw(), i, v.as_mut_ptr(), &mut len, null_mut(), null_mut(), null_mut(), null_mut(), ); if ret == ERROR_NO_MORE_ITEMS { None } else if ret != ERROR_SUCCESS { Some(Err(io::Error::from_raw_os_error(ret as i32))) } else { v.set_len(len as usize); Some(Ok(OsString::from_wide(&v))) } }) } } cc/src/windows/com.rs0000644000175000017500000000760214661133735015540 0ustar jamespagejamespage// Copyright © 2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(unused)] use crate::windows::{ winapi::{IUnknown, Interface}, windows_sys::{ CoInitializeEx, SysFreeString, SysStringLen, BSTR, COINIT_MULTITHREADED, HRESULT, S_FALSE, S_OK, }, }; use std::{ convert::TryInto, ffi::{OsStr, OsString}, mem::ManuallyDrop, ops::Deref, os::windows::ffi::{OsStrExt, OsStringExt}, ptr::{null, null_mut}, slice::from_raw_parts, }; pub fn initialize() -> Result<(), HRESULT> { let err = unsafe { CoInitializeEx(null(), COINIT_MULTITHREADED.try_into().unwrap()) }; if err != S_OK && err != S_FALSE { // S_FALSE just means COM is already initialized Err(err) } else { Ok(()) } } pub struct ComPtr(*mut T) where T: Interface; impl ComPtr where T: Interface, { /// Creates a `ComPtr` to wrap a raw pointer. /// It takes ownership over the pointer which means it does __not__ call `AddRef`. /// `T` __must__ be a COM interface that inherits from `IUnknown`. pub unsafe fn from_raw(ptr: *mut T) -> ComPtr { assert!(!ptr.is_null()); ComPtr(ptr) } /// Casts up the inheritance chain pub fn up(self) -> ComPtr where T: Deref, U: Interface, { ComPtr(self.into_raw() as *mut U) } /// Extracts the raw pointer. /// You are now responsible for releasing it yourself. pub fn into_raw(self) -> *mut T { ManuallyDrop::new(self).0 } /// For internal use only. fn as_unknown(&self) -> &IUnknown { unsafe { &*(self.0 as *mut IUnknown) } } /// Performs `QueryInterface` fun. pub fn cast(&self) -> Result, i32> where U: Interface, { let mut obj = null_mut(); let err = unsafe { self.as_unknown().QueryInterface(&U::uuidof(), &mut obj) }; if err < 0 { return Err(err); } Ok(unsafe { ComPtr::from_raw(obj as *mut U) }) } } impl Deref for ComPtr where T: Interface, { type Target = T; fn deref(&self) -> &T { unsafe { &*self.0 } } } impl Clone for ComPtr where T: Interface, { fn clone(&self) -> Self { unsafe { self.as_unknown().AddRef(); ComPtr::from_raw(self.0) } } } impl Drop for ComPtr where T: Interface, { fn drop(&mut self) { unsafe { self.as_unknown().Release(); } } } pub struct BStr(BSTR); impl BStr { pub unsafe fn from_raw(s: BSTR) -> BStr { BStr(s) } pub fn to_osstring(&self) -> OsString { let len = unsafe { SysStringLen(self.0) }; let slice = unsafe { from_raw_parts(self.0, len as usize) }; OsStringExt::from_wide(slice) } } impl Drop for BStr { fn drop(&mut self) { unsafe { SysFreeString(self.0) }; } } pub trait ToWide { fn to_wide(&self) -> Vec; fn to_wide_null(&self) -> Vec; } impl ToWide for T where T: AsRef, { fn to_wide(&self) -> Vec { self.as_ref().encode_wide().collect() } fn to_wide_null(&self) -> Vec { self.as_ref().encode_wide().chain(Some(0)).collect() } } pub trait FromWide where Self: Sized, { fn from_wide(wide: &[u16]) -> Self; fn from_wide_null(wide: &[u16]) -> Self { let len = wide.iter().take_while(|&&c| c != 0).count(); Self::from_wide(&wide[..len]) } } impl FromWide for OsString { fn from_wide(wide: &[u16]) -> OsString { OsStringExt::from_wide(wide) } } cc/src/windows/mod.rs0000644000175000017500000000064114661133735015535 0ustar jamespagejamespage//! These modules are all glue to support reading the MSVC version from //! the registry and from COM interfaces. // This is used in the crate's public API, so don't use #[cfg(windows)] pub mod find_tools; #[cfg(windows)] pub(crate) mod windows_sys; #[cfg(windows)] mod registry; #[cfg(windows)] #[macro_use] mod winapi; #[cfg(windows)] mod com; #[cfg(windows)] mod setup_config; #[cfg(windows)] mod vs_instances; cc/src/windows/vs_instances.rs0000644000175000017500000001453414661133735017463 0ustar jamespagejamespageuse std::borrow::Cow; use std::collections::HashMap; use std::convert::TryFrom; use std::io::BufRead; use std::path::PathBuf; use crate::windows::setup_config::{EnumSetupInstances, SetupInstance}; pub enum VsInstance { Com(SetupInstance), Vswhere(VswhereInstance), } impl VsInstance { pub fn installation_name(&self) -> Option> { match self { VsInstance::Com(s) => s .installation_name() .ok() .and_then(|s| s.into_string().ok()) .map(Cow::from), VsInstance::Vswhere(v) => v.map.get("installationName").map(Cow::from), } } pub fn installation_path(&self) -> Option { match self { VsInstance::Com(s) => s.installation_path().ok().map(PathBuf::from), VsInstance::Vswhere(v) => v.map.get("installationPath").map(PathBuf::from), } } pub fn installation_version(&self) -> Option> { match self { VsInstance::Com(s) => s .installation_version() .ok() .and_then(|s| s.into_string().ok()) .map(Cow::from), VsInstance::Vswhere(v) => v.map.get("installationVersion").map(Cow::from), } } } pub enum VsInstances { ComBased(EnumSetupInstances), VswhereBased(VswhereInstance), } impl IntoIterator for VsInstances { type Item = VsInstance; #[allow(bare_trait_objects)] type IntoIter = Box>; fn into_iter(self) -> Self::IntoIter { match self { VsInstances::ComBased(e) => { Box::new(e.into_iter().filter_map(Result::ok).map(VsInstance::Com)) } VsInstances::VswhereBased(v) => Box::new(std::iter::once(VsInstance::Vswhere(v))), } } } #[derive(Debug)] pub struct VswhereInstance { map: HashMap, } impl TryFrom<&Vec> for VswhereInstance { type Error = &'static str; fn try_from(output: &Vec) -> Result { let map: HashMap<_, _> = output .lines() .filter_map(Result::ok) .filter_map(|s| { let mut splitn = s.splitn(2, ": "); Some((splitn.next()?.to_owned(), splitn.next()?.to_owned())) }) .collect(); if !map.contains_key("installationName") || !map.contains_key("installationPath") || !map.contains_key("installationVersion") { return Err("required properties not found"); } Ok(Self { map }) } } #[cfg(test)] mod tests_ { use std::borrow::Cow; use std::convert::TryFrom; use std::path::PathBuf; #[test] fn it_parses_vswhere_output_correctly() { let output = br"instanceId: 58104422 installDate: 21/02/2021 21:50:33 installationName: VisualStudio/16.9.2+31112.23 installationPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools installationVersion: 16.9.31112.23 productId: Microsoft.VisualStudio.Product.BuildTools productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat state: 4294967295 isComplete: 1 isLaunchable: 1 isPrerelease: 0 isRebootRequired: 0 displayName: Visual Studio Build Tools 2019 description: The Visual Studio Build Tools allows you to build native and managed MSBuild-based applications without requiring the Visual Studio IDE. There are options to install the Visual C++ compilers and libraries, MFC, ATL, and C++/CLI support. channelId: VisualStudio.16.Release channelUri: https://aka.ms/vs/16/release/channel enginePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\ServiceHub\Services\Microsoft.VisualStudio.Setup.Service releaseNotes: https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-v16.9#16.9.2 thirdPartyNotices: https://go.microsoft.com/fwlink/?LinkId=660909 updateDate: 2021-03-17T21:16:46.5963702Z catalog_buildBranch: d16.9 catalog_buildVersion: 16.9.31112.23 catalog_id: VisualStudio/16.9.2+31112.23 catalog_localBuild: build-lab catalog_manifestName: VisualStudio catalog_manifestType: installer catalog_productDisplayVersion: 16.9.2 catalog_productLine: Dev16 catalog_productLineVersion: 2019 catalog_productMilestone: RTW catalog_productMilestoneIsPreRelease: False catalog_productName: Visual Studio catalog_productPatchVersion: 2 catalog_productPreReleaseMilestoneSuffix: 1.0 catalog_productSemanticVersion: 16.9.2+31112.23 catalog_requiredEngineVersion: 2.9.3365.38425 properties_campaignId: 156063665.1613940062 properties_channelManifestId: VisualStudio.16.Release/16.9.2+31112.23 properties_nickname: properties_setupEngineFilePath: C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installershell.exe " .to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_ok()); let vs_instance = super::VsInstance::Vswhere(vswhere_instance.unwrap()); assert_eq!( vs_instance.installation_name(), Some(Cow::from("VisualStudio/16.9.2+31112.23")) ); assert_eq!( vs_instance.installation_path(), Some(PathBuf::from( r"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools" )) ); assert_eq!( vs_instance.installation_version(), Some(Cow::from("16.9.31112.23")) ); } #[test] fn it_returns_an_error_for_empty_output() { let output = b"".to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_err()); } #[test] fn it_returns_an_error_for_output_consisting_of_empty_lines() { let output = br" " .to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_err()); } #[test] fn it_returns_an_error_for_output_without_required_properties() { let output = br"instanceId: 58104422 installDate: 21/02/2021 21:50:33 productId: Microsoft.VisualStudio.Product.BuildTools productPath: C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\LaunchDevCmd.bat " .to_vec(); let vswhere_instance = super::VswhereInstance::try_from(&output); assert!(vswhere_instance.is_err()); } } cc/src/windows/windows_sys.rs0000644000175000017500000001367414661133735017360 0ustar jamespagejamespage// This file is autogenerated. // // To add bindings, edit windows_sys.lst then run: // // ``` // cd generate-windows-sys/ // cargo run // ``` // Bindings generated by `windows-bindgen` 0.53.0 #![allow( non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all )] #[link(name = "advapi32")] extern "system" { pub fn RegCloseKey(hkey: HKEY) -> WIN32_ERROR; } #[link(name = "advapi32")] extern "system" { pub fn RegEnumKeyExW( hkey: HKEY, dwindex: u32, lpname: PWSTR, lpcchname: *mut u32, lpreserved: *const u32, lpclass: PWSTR, lpcchclass: *mut u32, lpftlastwritetime: *mut FILETIME, ) -> WIN32_ERROR; } #[link(name = "advapi32")] extern "system" { pub fn RegOpenKeyExW( hkey: HKEY, lpsubkey: PCWSTR, uloptions: u32, samdesired: REG_SAM_FLAGS, phkresult: *mut HKEY, ) -> WIN32_ERROR; } #[link(name = "advapi32")] extern "system" { pub fn RegQueryValueExW( hkey: HKEY, lpvaluename: PCWSTR, lpreserved: *const u32, lptype: *mut REG_VALUE_TYPE, lpdata: *mut u8, lpcbdata: *mut u32, ) -> WIN32_ERROR; } #[link(name = "kernel32")] extern "system" { pub fn FreeLibrary(hlibmodule: HMODULE) -> BOOL; } #[link(name = "kernel32")] extern "system" { pub fn GetMachineTypeAttributes( machine: u16, machinetypeattributes: *mut MACHINE_ATTRIBUTES, ) -> HRESULT; } #[link(name = "kernel32")] extern "system" { pub fn GetProcAddress(hmodule: HMODULE, lpprocname: PCSTR) -> FARPROC; } #[link(name = "kernel32")] extern "system" { pub fn LoadLibraryA(lplibfilename: PCSTR) -> HMODULE; } #[link(name = "kernel32")] extern "system" { pub fn OpenSemaphoreA(dwdesiredaccess: u32, binherithandle: BOOL, lpname: PCSTR) -> HANDLE; } #[link(name = "kernel32")] extern "system" { pub fn PeekNamedPipe( hnamedpipe: HANDLE, lpbuffer: *mut ::core::ffi::c_void, nbuffersize: u32, lpbytesread: *mut u32, lptotalbytesavail: *mut u32, lpbytesleftthismessage: *mut u32, ) -> BOOL; } #[link(name = "kernel32")] extern "system" { pub fn ReleaseSemaphore( hsemaphore: HANDLE, lreleasecount: i32, lppreviouscount: *mut i32, ) -> BOOL; } #[link(name = "kernel32")] extern "system" { pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WAIT_EVENT; } #[link(name = "ole32")] extern "system" { pub fn CoCreateInstance( rclsid: *const GUID, punkouter: *mut ::core::ffi::c_void, dwclscontext: CLSCTX, riid: *const GUID, ppv: *mut *mut ::core::ffi::c_void, ) -> HRESULT; } #[link(name = "ole32")] extern "system" { pub fn CoInitializeEx(pvreserved: *const ::core::ffi::c_void, dwcoinit: u32) -> HRESULT; } #[link(name = "oleaut32")] extern "system" { pub fn SysFreeString(bstrstring: BSTR); } #[link(name = "oleaut32")] extern "system" { pub fn SysStringLen(pbstr: BSTR) -> u32; } pub type ADVANCED_FEATURE_FLAGS = u16; pub type BOOL = i32; pub type BSTR = *const u16; pub type CLSCTX = u32; pub const CLSCTX_ALL: CLSCTX = 23u32; pub type COINIT = i32; pub const COINIT_MULTITHREADED: COINIT = 0i32; pub const ERROR_NO_MORE_ITEMS: WIN32_ERROR = 259u32; pub const ERROR_SUCCESS: WIN32_ERROR = 0u32; pub const FALSE: BOOL = 0i32; pub type FARPROC = ::core::option::Option isize>; #[repr(C)] pub struct FILETIME { pub dwLowDateTime: u32, pub dwHighDateTime: u32, } impl ::core::marker::Copy for FILETIME {} impl ::core::clone::Clone for FILETIME { fn clone(&self) -> Self { *self } } #[repr(C)] pub struct GUID { pub data1: u32, pub data2: u16, pub data3: u16, pub data4: [u8; 8], } impl ::core::marker::Copy for GUID {} impl ::core::clone::Clone for GUID { fn clone(&self) -> Self { *self } } impl GUID { pub const fn from_u128(uuid: u128) -> Self { Self { data1: (uuid >> 96) as u32, data2: (uuid >> 80 & 0xffff) as u16, data3: (uuid >> 64 & 0xffff) as u16, data4: (uuid as u64).to_be_bytes(), } } } pub type HANDLE = *mut ::core::ffi::c_void; pub type HKEY = *mut ::core::ffi::c_void; pub const HKEY_LOCAL_MACHINE: HKEY = -2147483646i32 as _; pub type HMODULE = *mut ::core::ffi::c_void; pub type HRESULT = i32; pub type IMAGE_FILE_MACHINE = u16; pub const IMAGE_FILE_MACHINE_AMD64: IMAGE_FILE_MACHINE = 34404u16; pub const KEY_READ: REG_SAM_FLAGS = 131097u32; pub const KEY_WOW64_32KEY: REG_SAM_FLAGS = 512u32; pub type MACHINE_ATTRIBUTES = i32; pub type PCSTR = *const u8; pub type PCWSTR = *const u16; pub type PWSTR = *mut u16; pub type REG_SAM_FLAGS = u32; pub const REG_SZ: REG_VALUE_TYPE = 1u32; pub type REG_VALUE_TYPE = u32; #[repr(C)] pub struct SAFEARRAY { pub cDims: u16, pub fFeatures: ADVANCED_FEATURE_FLAGS, pub cbElements: u32, pub cLocks: u32, pub pvData: *mut ::core::ffi::c_void, pub rgsabound: [SAFEARRAYBOUND; 1], } impl ::core::marker::Copy for SAFEARRAY {} impl ::core::clone::Clone for SAFEARRAY { fn clone(&self) -> Self { *self } } #[repr(C)] pub struct SAFEARRAYBOUND { pub cElements: u32, pub lLbound: i32, } impl ::core::marker::Copy for SAFEARRAYBOUND {} impl ::core::clone::Clone for SAFEARRAYBOUND { fn clone(&self) -> Self { *self } } pub const SEMAPHORE_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32; pub type SYNCHRONIZATION_ACCESS_RIGHTS = u32; pub const S_FALSE: HRESULT = 0x1_u32 as _; pub const S_OK: HRESULT = 0x0_u32 as _; pub type THREAD_ACCESS_RIGHTS = u32; pub const THREAD_SYNCHRONIZE: THREAD_ACCESS_RIGHTS = 1048576u32; pub const UserEnabled: MACHINE_ATTRIBUTES = 1i32; pub const WAIT_ABANDONED: WAIT_EVENT = 128u32; pub type WAIT_EVENT = u32; pub const WAIT_FAILED: WAIT_EVENT = 4294967295u32; pub const WAIT_OBJECT_0: WAIT_EVENT = 0u32; pub const WAIT_TIMEOUT: WAIT_EVENT = 258u32; pub type WIN32_ERROR = u32; cc/src/windows/winapi.rs0000644000175000017500000001077614661133735016257 0ustar jamespagejamespage// Copyright © 2015-2017 winapi-rs developers // Licensed under the Apache License, Version 2.0 // or the MIT license // , at your option. // All files in the project carrying such notice may not be copied, modified, or distributed // except according to those terms. #![allow(bad_style, clippy::upper_case_acronyms)] use std::os::raw; pub type wchar_t = u16; pub use crate::windows::windows_sys::{FILETIME, GUID, HRESULT, SAFEARRAY}; pub type REFIID = *const IID; pub type IID = GUID; pub type ULONG = raw::c_ulong; pub type DWORD = u32; pub type LPFILETIME = *mut FILETIME; pub type OLECHAR = WCHAR; pub type WCHAR = wchar_t; pub type LPCOLESTR = *const OLECHAR; pub type LCID = DWORD; pub type LPCWSTR = *const WCHAR; pub type PULONGLONG = *mut ULONGLONG; pub type ULONGLONG = u64; pub trait Interface { fn uuidof() -> GUID; } pub type LPSAFEARRAY = *mut SAFEARRAY; macro_rules! DEFINE_GUID { ( $name:ident, $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr ) => { pub const $name: $crate::windows::winapi::GUID = $crate::windows::winapi::GUID { data1: $l, data2: $w1, data3: $w2, data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], }; }; } macro_rules! RIDL { (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( #[repr(C)] pub struct $vtbl { $(pub $method: unsafe extern "system" fn( This: *mut $interface, $($p: $t),* ) -> $rtr,)+ } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}} RIDL!{@uuid $interface $($uuid),+} ); (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) { }) => ( #[repr(C)] pub struct $vtbl { pub parent: $pvtbl, } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@deref $interface $pinterface} RIDL!{@uuid $interface $($uuid),+} ); (#[uuid($($uuid:expr),+)] interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( #[repr(C)] pub struct $vtbl { pub parent: $pvtbl, $(pub $method: unsafe extern "system" fn( This: *mut $interface, $($p: $t,)* ) -> $rtr,)+ } #[repr(C)] pub struct $interface { pub lpVtbl: *const $vtbl, } RIDL!{@impl $interface {$(fn $method($($p: $t,)*) -> $rtr,)+}} RIDL!{@deref $interface $pinterface} RIDL!{@uuid $interface $($uuid),+} ); (@deref $interface:ident $pinterface:ident) => ( impl ::std::ops::Deref for $interface { type Target = $pinterface; #[inline] fn deref(&self) -> &$pinterface { unsafe { &*(self as *const $interface as *const $pinterface) } } } ); (@impl $interface:ident {$( fn $method:ident($($p:ident : $t:ty,)*) -> $rtr:ty, )+}) => ( impl $interface { $(#[inline] pub unsafe fn $method(&self, $($p: $t,)*) -> $rtr { ((*self.lpVtbl).$method)(self as *const _ as *mut _, $($p,)*) })+ } ); (@uuid $interface:ident $l:expr, $w1:expr, $w2:expr, $b1:expr, $b2:expr, $b3:expr, $b4:expr, $b5:expr, $b6:expr, $b7:expr, $b8:expr ) => ( impl $crate::windows::winapi::Interface for $interface { #[inline] fn uuidof() -> $crate::windows::winapi::GUID { $crate::windows::winapi::GUID { data1: $l, data2: $w1, data3: $w2, data4: [$b1, $b2, $b3, $b4, $b5, $b6, $b7, $b8], } } } ); } RIDL! {#[uuid(0x00000000, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46)] interface IUnknown(IUnknownVtbl) { fn QueryInterface( riid: REFIID, ppvObject: *mut *mut raw::c_void, ) -> HRESULT, fn AddRef() -> ULONG, fn Release() -> ULONG, }} cc/src/windows/find_tools.rs0000644000175000017500000012073414661133735017124 0ustar jamespagejamespage// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A helper module to looking for windows-specific tools: //! 1. On Windows host, probe the Windows Registry if needed; //! 2. On non-Windows host, check specified environment variables. #![allow(clippy::upper_case_acronyms)] use std::process::Command; use crate::Tool; use crate::ToolFamily; const MSVC_FAMILY: ToolFamily = ToolFamily::Msvc { clang_cl: false }; #[derive(Copy, Clone)] struct TargetArch<'a>(pub &'a str); impl PartialEq<&str> for TargetArch<'_> { fn eq(&self, other: &&str) -> bool { self.0 == *other } } impl<'a> From> for &'a str { fn from(target: TargetArch<'a>) -> Self { target.0 } } /// Attempts to find a tool within an MSVC installation using the Windows /// registry as a point to search from. /// /// The `target` argument is the target that the tool should work for (e.g. /// compile or link for) and the `tool` argument is the tool to find (e.g. /// `cl.exe` or `link.exe`). /// /// This function will return `None` if the tool could not be found, or it will /// return `Some(cmd)` which represents a command that's ready to execute the /// tool with the appropriate environment variables set. /// /// Note that this function always returns `None` for non-MSVC targets. pub fn find(target: &str, tool: &str) -> Option { find_tool(target, tool).map(|c| c.to_command()) } /// Similar to the `find` function above, this function will attempt the same /// operation (finding a MSVC tool in a local install) but instead returns a /// `Tool` which may be introspected. pub fn find_tool(target: &str, tool: &str) -> Option { // This logic is all tailored for MSVC, if we're not that then bail out // early. if !target.contains("msvc") { return None; } // Split the target to get the arch. let target = TargetArch(target.split_once('-')?.0); // Looks like msbuild isn't located in the same location as other tools like // cl.exe and lib.exe. if tool.contains("msbuild") { return impl_::find_msbuild(target); } // Looks like devenv isn't located in the same location as other tools like // cl.exe and lib.exe. if tool.contains("devenv") { return impl_::find_devenv(target); } // Ok, if we're here, now comes the fun part of the probing. Default shells // or shells like MSYS aren't really configured to execute `cl.exe` and the // various compiler tools shipped as part of Visual Studio. Here we try to // first find the relevant tool, then we also have to be sure to fill in // environment variables like `LIB`, `INCLUDE`, and `PATH` to ensure that // the tool is actually usable. impl_::find_msvc_environment(tool, target) .or_else(|| impl_::find_msvc_15plus(tool, target)) .or_else(|| impl_::find_msvc_14(tool, target)) .or_else(|| impl_::find_msvc_12(tool, target)) } /// A version of Visual Studio #[derive(Debug, PartialEq, Eq, Copy, Clone)] #[non_exhaustive] pub enum VsVers { /// Visual Studio 12 (2013) Vs12, /// Visual Studio 14 (2015) Vs14, /// Visual Studio 15 (2017) Vs15, /// Visual Studio 16 (2019) Vs16, /// Visual Studio 17 (2022) Vs17, } /// Find the most recent installed version of Visual Studio /// /// This is used by the cmake crate to figure out the correct /// generator. pub fn find_vs_version() -> Result { match std::env::var("VisualStudioVersion") { Ok(version) => match &version[..] { "17.0" => Ok(VsVers::Vs17), "16.0" => Ok(VsVers::Vs16), "15.0" => Ok(VsVers::Vs15), "14.0" => Ok(VsVers::Vs14), "12.0" => Ok(VsVers::Vs12), vers => Err(format!( "\n\n\ unsupported or unknown VisualStudio version: {}\n\ if another version is installed consider running \ the appropriate vcvars script before building this \ crate\n\ ", vers )), }, _ => { // Check for the presence of a specific registry key // that indicates visual studio is installed. if impl_::has_msbuild_version("17.0") { Ok(VsVers::Vs17) } else if impl_::has_msbuild_version("16.0") { Ok(VsVers::Vs16) } else if impl_::has_msbuild_version("15.0") { Ok(VsVers::Vs15) } else if impl_::has_msbuild_version("14.0") { Ok(VsVers::Vs14) } else if impl_::has_msbuild_version("12.0") { Ok(VsVers::Vs12) } else { Err(format!( "\n\n\ couldn't determine visual studio generator\n\ if VisualStudio is installed, however, consider \ running the appropriate vcvars script before building \ this crate\n\ " )) } } } } /// Windows Implementation. #[cfg(windows)] mod impl_ { use crate::windows::com; use crate::windows::registry::{RegistryKey, LOCAL_MACHINE}; use crate::windows::setup_config::SetupConfiguration; use crate::windows::vs_instances::{VsInstances, VswhereInstance}; use crate::windows::windows_sys::{ FreeLibrary, GetMachineTypeAttributes, GetProcAddress, LoadLibraryA, UserEnabled, HMODULE, IMAGE_FILE_MACHINE_AMD64, MACHINE_ATTRIBUTES, S_OK, }; use std::convert::TryFrom; use std::env; use std::ffi::OsString; use std::fs::File; use std::io::Read; use std::iter; use std::mem; use std::path::{Path, PathBuf}; use std::process::Command; use std::str::FromStr; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Once; use super::{TargetArch, MSVC_FAMILY}; use crate::Tool; struct MsvcTool { tool: PathBuf, libs: Vec, path: Vec, include: Vec, } struct LibraryHandle(HMODULE); impl LibraryHandle { fn new(name: &[u8]) -> Option { let handle = unsafe { LoadLibraryA(name.as_ptr() as _) }; (!handle.is_null()).then(|| Self(handle)) } /// Get a function pointer to a function in the library. /// SAFETY: The caller must ensure that the function signature matches the actual function. /// The easiest way to do this is to add an entry to windows_sys_no_link.list and use the /// generated function for `func_signature`. unsafe fn get_proc_address(&self, name: &[u8]) -> Option { let symbol = unsafe { GetProcAddress(self.0, name.as_ptr() as _) }; symbol.map(|symbol| unsafe { mem::transmute_copy(&symbol) }) } } impl Drop for LibraryHandle { fn drop(&mut self) { unsafe { FreeLibrary(self.0) }; } } type GetMachineTypeAttributesFuncType = unsafe extern "system" fn(u16, *mut MACHINE_ATTRIBUTES) -> i32; const _: () = { // Ensure that our hand-written signature matches the actual function signature. // We can't use `GetMachineTypeAttributes` outside of a const scope otherwise we'll end up statically linking to // it, which will fail to load on older versions of Windows. let _: GetMachineTypeAttributesFuncType = GetMachineTypeAttributes; }; fn is_amd64_emulation_supported_inner() -> Option { // GetMachineTypeAttributes is only available on Win11 22000+, so dynamically load it. let kernel32 = LibraryHandle::new(b"kernel32.dll\0")?; // SAFETY: GetMachineTypeAttributesFuncType is checked to match the real function signature. let get_machine_type_attributes = unsafe { kernel32 .get_proc_address::(b"GetMachineTypeAttributes\0") }?; let mut attributes = Default::default(); if unsafe { get_machine_type_attributes(IMAGE_FILE_MACHINE_AMD64, &mut attributes) } == S_OK { Some((attributes & UserEnabled) != 0) } else { Some(false) } } fn is_amd64_emulation_supported() -> bool { // TODO: Replace with a OnceLock once MSRV is 1.70. static LOAD_VALUE: Once = Once::new(); static IS_SUPPORTED: AtomicBool = AtomicBool::new(false); // Using Relaxed ordering since the Once is providing synchronization. LOAD_VALUE.call_once(|| { IS_SUPPORTED.store( is_amd64_emulation_supported_inner().unwrap_or(false), Ordering::Relaxed, ); }); IS_SUPPORTED.load(Ordering::Relaxed) } impl MsvcTool { fn new(tool: PathBuf) -> MsvcTool { MsvcTool { tool, libs: Vec::new(), path: Vec::new(), include: Vec::new(), } } fn into_tool(self) -> Tool { let MsvcTool { tool, libs, path, include, } = self; let mut tool = Tool::with_family(tool, MSVC_FAMILY); add_env(&mut tool, "LIB", libs); add_env(&mut tool, "PATH", path); add_env(&mut tool, "INCLUDE", include); tool } } /// Checks to see if the `VSCMD_ARG_TGT_ARCH` environment variable matches the /// given target's arch. Returns `None` if the variable does not exist. fn is_vscmd_target(target: TargetArch<'_>) -> Option { let vscmd_arch = env::var("VSCMD_ARG_TGT_ARCH").ok()?; // Convert the Rust target arch to its VS arch equivalent. let arch = match target.into() { "x86_64" => "x64", "aarch64" | "arm64ec" => "arm64", "i686" | "i586" => "x86", "thumbv7a" => "arm", // An unrecognized arch. _ => return Some(false), }; Some(vscmd_arch == arch) } /// Attempt to find the tool using environment variables set by vcvars. pub(super) fn find_msvc_environment(tool: &str, target: TargetArch<'_>) -> Option { // Early return if the environment doesn't contain a VC install. if env::var_os("VCINSTALLDIR").is_none() { return None; } let vs_install_dir = env::var_os("VSINSTALLDIR")?.into(); // If the vscmd target differs from the requested target then // attempt to get the tool using the VS install directory. if is_vscmd_target(target) == Some(false) { // We will only get here with versions 15+. tool_from_vs15plus_instance(tool, target, &vs_install_dir) } else { // Fallback to simply using the current environment. env::var_os("PATH") .and_then(|path| { env::split_paths(&path) .map(|p| p.join(tool)) .find(|p| p.exists()) }) .map(|path| Tool::with_family(path, MSVC_FAMILY)) } } fn find_msbuild_vs17(target: TargetArch<'_>) -> Option { find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "17") } #[allow(bare_trait_objects)] fn vs16plus_instances( target: TargetArch<'_>, version: &'static str, ) -> Box> { let instances = if let Some(instances) = vs15plus_instances(target) { instances } else { return Box::new(iter::empty()); }; Box::new(instances.into_iter().filter_map(move |instance| { let installation_name = instance.installation_name()?; if installation_name.starts_with(&format!("VisualStudio/{}.", version)) { Some(instance.installation_path()?) } else if installation_name.starts_with(&format!("VisualStudioPreview/{}.", version)) { Some(instance.installation_path()?) } else { None } })) } fn find_tool_in_vs16plus_path( tool: &str, target: TargetArch<'_>, version: &'static str, ) -> Option { vs16plus_instances(target, version) .filter_map(|path| { let path = path.join(tool); if !path.is_file() { return None; } let mut tool = Tool::with_family(path, MSVC_FAMILY); if target == "x86_64" { tool.env.push(("Platform".into(), "X64".into())); } if target == "aarch64" || target == "arm64ec" { tool.env.push(("Platform".into(), "ARM64".into())); } Some(tool) }) .next() } fn find_msbuild_vs16(target: TargetArch<'_>) -> Option { find_tool_in_vs16plus_path(r"MSBuild\Current\Bin\MSBuild.exe", target, "16") } // In MSVC 15 (2017) MS once again changed the scheme for locating // the tooling. Now we must go through some COM interfaces, which // is super fun for Rust. // // Note that much of this logic can be found [online] wrt paths, COM, etc. // // [online]: https://blogs.msdn.microsoft.com/vcblog/2017/03/06/finding-the-visual-c-compiler-tools-in-visual-studio-2017/ // // Returns MSVC 15+ instances (15, 16 right now), the order should be consider undefined. // // However, on ARM64 this method doesn't work because VS Installer fails to register COM component on ARM64. // Hence, as the last resort we try to use vswhere.exe to list available instances. fn vs15plus_instances(target: TargetArch<'_>) -> Option { vs15plus_instances_using_com().or_else(|| vs15plus_instances_using_vswhere(target)) } fn vs15plus_instances_using_com() -> Option { com::initialize().ok()?; let config = SetupConfiguration::new().ok()?; let enum_setup_instances = config.enum_all_instances().ok()?; Some(VsInstances::ComBased(enum_setup_instances)) } fn vs15plus_instances_using_vswhere(target: TargetArch<'_>) -> Option { let program_files_path: PathBuf = env::var("ProgramFiles(x86)") .or_else(|_| env::var("ProgramFiles")) .ok()? .into(); let vswhere_path = program_files_path.join(r"Microsoft Visual Studio\Installer\vswhere.exe"); if !vswhere_path.exists() { return None; } let tools_arch = match target.into() { "i586" | "i686" | "x86_64" => Some("x86.x64"), "arm" | "thumbv7a" => Some("ARM"), "aarch64" | "arm64ec" => Some("ARM64"), _ => None, }; let vswhere_output = Command::new(vswhere_path) .args(&[ "-latest", "-products", "*", "-requires", &format!("Microsoft.VisualStudio.Component.VC.Tools.{}", tools_arch?), "-format", "text", "-nologo", ]) .stderr(std::process::Stdio::inherit()) .output() .ok()?; let vs_instances = VsInstances::VswhereBased(VswhereInstance::try_from(&vswhere_output.stdout).ok()?); Some(vs_instances) } // Inspired from official microsoft/vswhere ParseVersionString // i.e. at most four u16 numbers separated by '.' fn parse_version(version: &str) -> Option> { version .split('.') .map(|chunk| u16::from_str(chunk).ok()) .collect() } pub(super) fn find_msvc_15plus(tool: &str, target: TargetArch<'_>) -> Option { let iter = vs15plus_instances(target)?; iter.into_iter() .filter_map(|instance| { let version = parse_version(&instance.installation_version()?)?; let instance_path = instance.installation_path()?; let tool = tool_from_vs15plus_instance(tool, target, &instance_path)?; Some((version, tool)) }) .max_by(|(a_version, _), (b_version, _)| a_version.cmp(b_version)) .map(|(_version, tool)| tool) } // While the paths to Visual Studio 2017's devenv and MSBuild could // potentially be retrieved from the registry, finding them via // SetupConfiguration has shown to be [more reliable], and is preferred // according to Microsoft. To help head off potential regressions though, // we keep the registry method as a fallback option. // // [more reliable]: https://github.com/rust-lang/cc-rs/pull/331 fn find_tool_in_vs15_path(tool: &str, target: TargetArch<'_>) -> Option { let mut path = match vs15plus_instances(target) { Some(instances) => instances .into_iter() .filter_map(|instance| instance.installation_path()) .map(|path| path.join(tool)) .find(|path| path.is_file()), None => None, }; if path.is_none() { let key = r"SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"; path = LOCAL_MACHINE .open(key.as_ref()) .ok() .and_then(|key| key.query_str("15.0").ok()) .map(|path| PathBuf::from(path).join(tool)) .and_then(|path| if path.is_file() { Some(path) } else { None }); } path.map(|path| { let mut tool = Tool::with_family(path, MSVC_FAMILY); if target == "x86_64" { tool.env.push(("Platform".into(), "X64".into())); } else if target == "aarch64" { tool.env.push(("Platform".into(), "ARM64".into())); } tool }) } fn tool_from_vs15plus_instance( tool: &str, target: TargetArch<'_>, instance_path: &PathBuf, ) -> Option { let (root_path, bin_path, host_dylib_path, lib_path, alt_lib_path, include_path) = vs15plus_vc_paths(target, instance_path)?; let tool_path = bin_path.join(tool); if !tool_path.exists() { return None; }; let mut tool = MsvcTool::new(tool_path); tool.path.push(bin_path.clone()); tool.path.push(host_dylib_path); if let Some(alt_lib_path) = alt_lib_path { tool.libs.push(alt_lib_path); } tool.libs.push(lib_path); tool.include.push(include_path); if let Some((atl_lib_path, atl_include_path)) = atl_paths(target, &root_path) { tool.libs.push(atl_lib_path); tool.include.push(atl_include_path); } add_sdks(&mut tool, target)?; Some(tool.into_tool()) } fn vs15plus_vc_paths( target: TargetArch<'_>, instance_path: &Path, ) -> Option<(PathBuf, PathBuf, PathBuf, PathBuf, Option, PathBuf)> { let version = vs15plus_vc_read_version(instance_path)?; let hosts = match host_arch() { X86 => &["X86"], X86_64 => &["X64"], // Starting with VS 17.4, there is a natively hosted compiler on ARM64: // https://devblogs.microsoft.com/visualstudio/arm64-visual-studio-is-officially-here/ // On older versions of VS, we use x64 if running under emulation is supported, // otherwise use x86. AARCH64 => { if is_amd64_emulation_supported() { &["ARM64", "X64", "X86"][..] } else { &["ARM64", "X86"] } } _ => return None, }; let target = lib_subdir(target)?; // The directory layout here is MSVC/bin/Host$host/$target/ let path = instance_path.join(r"VC\Tools\MSVC").join(version); // We use the first available host architecture that can build for the target let (host_path, host) = hosts.iter().find_map(|&x| { let candidate = path.join("bin").join(format!("Host{}", x)); if candidate.join(target).exists() { Some((candidate, x)) } else { None } })?; // This is the path to the toolchain for a particular target, running // on a given host let bin_path = host_path.join(target); // But! we also need PATH to contain the target directory for the host // architecture, because it contains dlls like mspdb140.dll compiled for // the host architecture. let host_dylib_path = host_path.join(host.to_lowercase()); let lib_path = path.join("lib").join(target); let alt_lib_path = (target == "arm64ec").then(|| path.join("lib").join("arm64ec")); let include_path = path.join("include"); Some(( path, bin_path, host_dylib_path, lib_path, alt_lib_path, include_path, )) } fn vs15plus_vc_read_version(dir: &Path) -> Option { // Try to open the default version file. let mut version_path: PathBuf = dir.join(r"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"); let mut version_file = if let Ok(f) = File::open(&version_path) { f } else { // If the default doesn't exist, search for other version files. // These are in the form Microsoft.VCToolsVersion.v143.default.txt // where `143` is any three decimal digit version number. // This sorts versions by lexical order and selects the highest version. let mut version_file = String::new(); version_path.pop(); for file in version_path.read_dir().ok()? { let name = file.ok()?.file_name(); let name = name.to_str()?; if name.starts_with("Microsoft.VCToolsVersion.v") && name.ends_with(".default.txt") && name > &version_file { version_file.replace_range(.., name); } } if version_file.is_empty() { return None; } version_path.push(version_file); File::open(version_path).ok()? }; // Get the version string from the file we found. let mut version = String::new(); version_file.read_to_string(&mut version).ok()?; version.truncate(version.trim_end().len()); Some(version) } fn atl_paths(target: TargetArch<'_>, path: &Path) -> Option<(PathBuf, PathBuf)> { let atl_path = path.join("atlmfc"); let sub = lib_subdir(target)?; if atl_path.exists() { Some((atl_path.join("lib").join(sub), atl_path.join("include"))) } else { None } } // For MSVC 14 we need to find the Universal CRT as well as either // the Windows 10 SDK or Windows 8.1 SDK. pub(super) fn find_msvc_14(tool: &str, target: TargetArch<'_>) -> Option { let vcdir = get_vc_dir("14.0")?; let mut tool = get_tool(tool, &vcdir, target)?; add_sdks(&mut tool, target)?; Some(tool.into_tool()) } fn add_sdks(tool: &mut MsvcTool, target: TargetArch<'_>) -> Option<()> { let sub = lib_subdir(target)?; let (ucrt, ucrt_version) = get_ucrt_dir()?; let host = match host_arch() { X86 => "x86", X86_64 => "x64", AARCH64 => "arm64", _ => return None, }; tool.path .push(ucrt.join("bin").join(&ucrt_version).join(host)); let ucrt_include = ucrt.join("include").join(&ucrt_version); tool.include.push(ucrt_include.join("ucrt")); let ucrt_lib = ucrt.join("lib").join(&ucrt_version); tool.libs.push(ucrt_lib.join("ucrt").join(sub)); if let Some((sdk, version)) = get_sdk10_dir() { tool.path.push(sdk.join("bin").join(host)); let sdk_lib = sdk.join("lib").join(&version); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk.join("include").join(&version); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("cppwinrt")); tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } else if let Some(sdk) = get_sdk81_dir() { tool.path.push(sdk.join("bin").join(host)); let sdk_lib = sdk.join("lib").join("winv6.3"); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk.join("include"); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("winrt")); tool.include.push(sdk_include.join("shared")); } Some(()) } // For MSVC 12 we need to find the Windows 8.1 SDK. pub(super) fn find_msvc_12(tool: &str, target: TargetArch<'_>) -> Option { let vcdir = get_vc_dir("12.0")?; let mut tool = get_tool(tool, &vcdir, target)?; let sub = lib_subdir(target)?; let sdk81 = get_sdk81_dir()?; tool.path.push(sdk81.join("bin").join(sub)); let sdk_lib = sdk81.join("lib").join("winv6.3"); tool.libs.push(sdk_lib.join("um").join(sub)); let sdk_include = sdk81.join("include"); tool.include.push(sdk_include.join("shared")); tool.include.push(sdk_include.join("um")); tool.include.push(sdk_include.join("winrt")); Some(tool.into_tool()) } fn add_env(tool: &mut Tool, env: &str, paths: Vec) { let prev = env::var_os(env).unwrap_or(OsString::new()); let prev = env::split_paths(&prev); let new = paths.into_iter().chain(prev); tool.env .push((env.to_string().into(), env::join_paths(new).unwrap())); } // Given a possible MSVC installation directory, we look for the linker and // then add the MSVC library path. fn get_tool(tool: &str, path: &Path, target: TargetArch<'_>) -> Option { bin_subdir(target) .into_iter() .map(|(sub, host)| { ( path.join("bin").join(sub).join(tool), path.join("bin").join(host), ) }) .filter(|(path, _)| path.is_file()) .map(|(path, host)| { let mut tool = MsvcTool::new(path); tool.path.push(host); tool }) .filter_map(|mut tool| { let sub = vc_lib_subdir(target)?; tool.libs.push(path.join("lib").join(sub)); tool.include.push(path.join("include")); let atlmfc_path = path.join("atlmfc"); if atlmfc_path.exists() { tool.libs.push(atlmfc_path.join("lib").join(sub)); tool.include.push(atlmfc_path.join("include")); } Some(tool) }) .next() } // To find MSVC we look in a specific registry key for the version we are // trying to find. fn get_vc_dir(ver: &str) -> Option { let key = r"SOFTWARE\Microsoft\VisualStudio\SxS\VC7"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let path = key.query_str(ver).ok()?; Some(path.into()) } // To find the Universal CRT we look in a specific registry key for where // all the Universal CRTs are located and then sort them asciibetically to // find the newest version. While this sort of sorting isn't ideal, it is // what vcvars does so that's good enough for us. // // Returns a pair of (root, version) for the ucrt dir if found fn get_ucrt_dir() -> Option<(PathBuf, String)> { let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let root = key.query_str("KitsRoot10").ok()?; let readdir = Path::new(&root).join("lib").read_dir().ok()?; let max_libdir = readdir .filter_map(|dir| dir.ok()) .map(|dir| dir.path()) .filter(|dir| { dir.components() .last() .and_then(|c| c.as_os_str().to_str()) .map(|c| c.starts_with("10.") && dir.join("ucrt").is_dir()) .unwrap_or(false) }) .max()?; let version = max_libdir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) } // Vcvars finds the correct version of the Windows 10 SDK by looking // for the include `um\Windows.h` because sometimes a given version will // only have UCRT bits without the rest of the SDK. Since we only care about // libraries and not includes, we instead look for `um\x64\kernel32.lib`. // Since the 32-bit and 64-bit libraries are always installed together we // only need to bother checking x64, making this code a tiny bit simpler. // Like we do for the Universal CRT, we sort the possibilities // asciibetically to find the newest one as that is what vcvars does. // Before doing that, we check the "WindowsSdkDir" and "WindowsSDKVersion" // environment variables set by vcvars to use the environment sdk version // if one is already configured. fn get_sdk10_dir() -> Option<(PathBuf, String)> { if let (Ok(root), Ok(version)) = (env::var("WindowsSdkDir"), env::var("WindowsSDKVersion")) { return Some((root.into(), version.trim_end_matches('\\').to_string())); } let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let root = key.query_str("InstallationFolder").ok()?; let readdir = Path::new(&root).join("lib").read_dir().ok()?; let mut dirs = readdir .filter_map(|dir| dir.ok()) .map(|dir| dir.path()) .collect::>(); dirs.sort(); let dir = dirs .into_iter() .rev() .filter(|dir| dir.join("um").join("x64").join("kernel32.lib").is_file()) .next()?; let version = dir.components().last().unwrap(); let version = version.as_os_str().to_str().unwrap().to_string(); Some((root.into(), version)) } // Interestingly there are several subdirectories, `win7` `win8` and // `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same // applies to us. Note that if we were targeting kernel mode drivers // instead of user mode applications, we would care. fn get_sdk81_dir() -> Option { let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1"; let key = LOCAL_MACHINE.open(key.as_ref()).ok()?; let root = key.query_str("InstallationFolder").ok()?; Some(root.into()) } const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0; const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9; const PROCESSOR_ARCHITECTURE_ARM64: u16 = 12; const X86: u16 = PROCESSOR_ARCHITECTURE_INTEL; const X86_64: u16 = PROCESSOR_ARCHITECTURE_AMD64; const AARCH64: u16 = PROCESSOR_ARCHITECTURE_ARM64; // When choosing the tool to use, we have to choose the one which matches // the target architecture. Otherwise we end up in situations where someone // on 32-bit Windows is trying to cross compile to 64-bit and it tries to // invoke the native 64-bit compiler which won't work. // // For the return value of this function, the first member of the tuple is // the folder of the tool we will be invoking, while the second member is // the folder of the host toolchain for that tool which is essential when // using a cross linker. We return a Vec since on x64 there are often two // linkers that can target the architecture we desire. The 64-bit host // linker is preferred, and hence first, due to 64-bit allowing it more // address space to work with and potentially being faster. fn bin_subdir(target: TargetArch<'_>) -> Vec<(&'static str, &'static str)> { match (target.into(), host_arch()) { ("i586", X86) | ("i686", X86) => vec![("", "")], ("i586", X86_64) | ("i686", X86_64) => vec![("amd64_x86", "amd64"), ("", "")], ("x86_64", X86) => vec![("x86_amd64", "")], ("x86_64", X86_64) => vec![("amd64", "amd64"), ("x86_amd64", "")], ("arm", X86) | ("thumbv7a", X86) => vec![("x86_arm", "")], ("arm", X86_64) | ("thumbv7a", X86_64) => vec![("amd64_arm", "amd64"), ("x86_arm", "")], _ => vec![], } } fn lib_subdir(target: TargetArch<'_>) -> Option<&'static str> { match target.into() { "i586" | "i686" => Some("x86"), "x86_64" => Some("x64"), "arm" | "thumbv7a" => Some("arm"), "aarch64" | "arm64ec" => Some("arm64"), _ => None, } } // MSVC's x86 libraries are not in a subfolder fn vc_lib_subdir(target: TargetArch<'_>) -> Option<&'static str> { match target.into() { "i586" | "i686" => Some(""), "x86_64" => Some("amd64"), "arm" | "thumbv7a" => Some("arm"), "aarch64" => Some("arm64"), _ => None, } } #[allow(bad_style)] fn host_arch() -> u16 { type DWORD = u32; type WORD = u16; type LPVOID = *mut u8; type DWORD_PTR = usize; #[repr(C)] struct SYSTEM_INFO { wProcessorArchitecture: WORD, _wReserved: WORD, _dwPageSize: DWORD, _lpMinimumApplicationAddress: LPVOID, _lpMaximumApplicationAddress: LPVOID, _dwActiveProcessorMask: DWORD_PTR, _dwNumberOfProcessors: DWORD, _dwProcessorType: DWORD, _dwAllocationGranularity: DWORD, _wProcessorLevel: WORD, _wProcessorRevision: WORD, } extern "system" { fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO); } unsafe { let mut info = mem::zeroed(); GetNativeSystemInfo(&mut info); info.wProcessorArchitecture } } // Given a registry key, look at all the sub keys and find the one which has // the maximal numeric value. // // Returns the name of the maximal key as well as the opened maximal key. fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> { let mut max_vers = 0; let mut max_key = None; for subkey in key.iter().filter_map(|k| k.ok()) { let val = subkey .to_str() .and_then(|s| s.trim_left_matches("v").replace('.', "").parse().ok()); let val = match val { Some(s) => s, None => continue, }; if val > max_vers { if let Ok(k) = key.open(&subkey) { max_vers = val; max_key = Some((subkey, k)); } } } max_key } pub(super) fn has_msbuild_version(version: &str) -> bool { match version { "17.0" => { find_msbuild_vs17(TargetArch("x86_64")).is_some() || find_msbuild_vs17(TargetArch("i686")).is_some() || find_msbuild_vs17(TargetArch("aarch64")).is_some() } "16.0" => { find_msbuild_vs16(TargetArch("x86_64")).is_some() || find_msbuild_vs16(TargetArch("i686")).is_some() || find_msbuild_vs16(TargetArch("aarch64")).is_some() } "15.0" => { find_msbuild_vs15(TargetArch("x86_64")).is_some() || find_msbuild_vs15(TargetArch("i686")).is_some() || find_msbuild_vs15(TargetArch("aarch64")).is_some() } "12.0" | "14.0" => LOCAL_MACHINE .open(&OsString::from(format!( "SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\{}", version ))) .is_ok(), _ => false, } } pub(super) fn find_devenv(target: TargetArch<'_>) -> Option { find_devenv_vs15(target) } fn find_devenv_vs15(target: TargetArch<'_>) -> Option { find_tool_in_vs15_path(r"Common7\IDE\devenv.exe", target) } // see http://stackoverflow.com/questions/328017/path-to-msbuild pub(super) fn find_msbuild(target: TargetArch<'_>) -> Option { // VS 15 (2017) changed how to locate msbuild if let Some(r) = find_msbuild_vs17(target) { Some(r) } else if let Some(r) = find_msbuild_vs16(target) { return Some(r); } else if let Some(r) = find_msbuild_vs15(target) { return Some(r); } else { find_old_msbuild(target) } } fn find_msbuild_vs15(target: TargetArch<'_>) -> Option { find_tool_in_vs15_path(r"MSBuild\15.0\Bin\MSBuild.exe", target) } fn find_old_msbuild(target: TargetArch<'_>) -> Option { let key = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions"; LOCAL_MACHINE .open(key.as_ref()) .ok() .and_then(|key| { max_version(&key).and_then(|(_vers, key)| key.query_str("MSBuildToolsPath").ok()) }) .map(|path| { let mut path = PathBuf::from(path); path.push("MSBuild.exe"); let mut tool = Tool::with_family(path, MSVC_FAMILY); if target == "x86_64" { tool.env.push(("Platform".into(), "X64".into())); } tool }) } } /// Non-Windows Implementation. #[cfg(not(windows))] mod impl_ { use std::{env, ffi::OsString}; use super::{TargetArch, MSVC_FAMILY}; use crate::Tool; /// Finding msbuild.exe tool under unix system is not currently supported. /// Maybe can check it using an environment variable looks like `MSBUILD_BIN`. pub(super) fn find_msbuild(_target: TargetArch<'_>) -> Option { None } // Finding devenv.exe tool under unix system is not currently supported. // Maybe can check it using an environment variable looks like `DEVENV_BIN`. pub(super) fn find_devenv(_target: TargetArch<'_>) -> Option { None } /// Attempt to find the tool using environment variables set by vcvars. pub(super) fn find_msvc_environment(tool: &str, _target: TargetArch<'_>) -> Option { // Early return if the environment doesn't contain a VC install. let vc_install_dir = env::var_os("VCINSTALLDIR")?; let vs_install_dir = env::var_os("VSINSTALLDIR")?; let get_tool = |install_dir: OsString| { env::split_paths(&install_dir) .map(|p| p.join(tool)) .find(|p| p.exists()) .map(|path| Tool::with_family(path.into(), MSVC_FAMILY)) }; // Take the path of tool for the vc install directory. get_tool(vc_install_dir) // Take the path of tool for the vs install directory. .or_else(|| get_tool(vs_install_dir)) // Take the path of tool for the current path environment. .or_else(|| env::var_os("PATH").and_then(|path| get_tool(path))) } pub(super) fn find_msvc_15plus(_tool: &str, _target: TargetArch<'_>) -> Option { None } // For MSVC 14 we need to find the Universal CRT as well as either // the Windows 10 SDK or Windows 8.1 SDK. pub(super) fn find_msvc_14(_tool: &str, _target: TargetArch<'_>) -> Option { None } // For MSVC 12 we need to find the Windows 8.1 SDK. pub(super) fn find_msvc_12(_tool: &str, _target: TargetArch<'_>) -> Option { None } pub(super) fn has_msbuild_version(version: &str) -> bool { match version { "17.0" => false, "16.0" => false, "15.0" => false, "12.0" | "14.0" => false, _ => false, } } } cc/.cargo-checksum.json0000664000175000017500000000337214661133735016001 0ustar jamespagejamespage{"files":{"Cargo.toml":"ad60f12609a272a3d052258f9521807fd627181125e84dd988ddb2b2e7dfedf6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"f1ddbede208a5b78333a25dac0a7598e678e9b601a7d99a791069bddaf180dfe","src/command_helpers.rs":"3ef95bdcd79a43406fdab275d8a8f45ba787876399b54df34068955ec0109e69","src/lib.rs":"71e55cf18e32dab3b9feae2add4ff57932a10084cc5aad4680c12eb3a91ed124","src/parallel/async_executor.rs":"4ce24435fff6b6555b43fee042c16bd65d4150d0346567f246b9190d85b45983","src/parallel/job_token.rs":"0676c3177b5be9d7ede483bf4bd45c5ca0f5511073e4d1c9f181a0bc83db05dc","src/parallel/mod.rs":"aaffed5ad3dc0d28641533ab0d6f522bf34a059d4b1a239dc4d217cb5d58e232","src/parallel/stderr.rs":"a2d18ba3f2e04deb9047ece9ab7ca5452d9a76b515afbe20a76307e31597f34b","src/tool.rs":"172cfcbecd7c6a363ea841a48a10a75b0a01e83b83c0691107c601598b68dedf","src/windows/com.rs":"be1564756c9f3ef1398eafeed7b54ba610caba28e8f6258d28a997737ebf9535","src/windows/find_tools.rs":"f6f391294511c376c3ce10ac2fd29967fe6f21d256d9575d8733c1c7cb1befde","src/windows/mod.rs":"42f1ad7fee35a17686b003e6aa520d3d1940d47d2f531d626e9ae0c48ba49005","src/windows/registry.rs":"c521b72c825e8095843e73482ffa810ed066ad8bb9f86e6db0c5c143c171aba1","src/windows/setup_config.rs":"754439cbab492afd44c9755abcbec1a41c9b2c358131cee2df13c0e996dbbec8","src/windows/vs_instances.rs":"76e3cee74b5fd38ddaf533bba11fe401667c50dda5f9d064099840893eaa7587","src/windows/winapi.rs":"250d51c1826d1a2329e9889dd9f058cfce253dbf2a678b076147c6cdb5db046c","src/windows/windows_sys.rs":"f6b90b87f23e446284bde86749b53858c0d37b8a43515ed8d0e90b1ac8cf7771"},"package":"8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"}cfg-if/0000775000175000017500000000000014661133735012676 5ustar jamespagejamespagecfg-if/README.md0000644000175000017500000000214314661133735014153 0ustar jamespagejamespage# cfg-if [Documentation](https://docs.rs/cfg-if) A macro to ergonomically define an item depending on a large number of #[cfg] parameters. Structured like an if-else chain, the first matching branch is the item that gets emitted. ```toml [dependencies] cfg-if = "0.1" ``` ## Example ```rust cfg_if::cfg_if! { if #[cfg(unix)] { fn foo() { /* unix specific functionality */ } } else if #[cfg(target_pointer_width = "32")] { fn foo() { /* non-unix, 32-bit functionality */ } } else { fn foo() { /* fallback implementation */ } } } fn main() { foo(); } ``` # License This project is licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `cfg-if` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. cfg-if/LICENSE-APACHE0000644000175000017500000002513714661133735014630 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. cfg-if/Cargo.toml0000644000175000017500000000243414661133735014627 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "cfg-if" version = "1.0.0" authors = ["Alex Crichton "] description = "A macro to ergonomically define an item depending on a large number of #[cfg]\nparameters. Structured like an if-else chain, the first matching branch is the\nitem that gets emitted.\n" homepage = "https://github.com/alexcrichton/cfg-if" documentation = "https://docs.rs/cfg-if" readme = "README.md" license = "MIT/Apache-2.0" repository = "https://github.com/alexcrichton/cfg-if" [dependencies.compiler_builtins] version = "0.1.2" optional = true [dependencies.core] version = "1.0.0" optional = true package = "rustc-std-workspace-core" [features] rustc-dep-of-std = ["core", "compiler_builtins"] [badges.travis-ci] repository = "alexcrichton/cfg-if" cfg-if/tests/0000775000175000017500000000000014661133735014040 5ustar jamespagejamespagecfg-if/tests/xcrate.rs0000644000175000017500000000036514661133735015676 0ustar jamespagejamespagecfg_if::cfg_if! { if #[cfg(foo)] { fn works() -> bool { false } } else if #[cfg(test)] { fn works() -> bool { true } } else { fn works() -> bool { false } } } #[test] fn smoke() { assert!(works()); } cfg-if/LICENSE-MIT0000644000175000017500000000204114661133735014325 0ustar jamespagejamespageCopyright (c) 2014 Alex Crichton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cfg-if/src/0000775000175000017500000000000014661133735013465 5ustar jamespagejamespagecfg-if/src/lib.rs0000644000175000017500000001143514661133735014603 0ustar jamespagejamespage//! A macro for defining `#[cfg]` if-else statements. //! //! The macro provided by this crate, `cfg_if`, is similar to the `if/elif` C //! preprocessor macro by allowing definition of a cascade of `#[cfg]` cases, //! emitting the implementation which matches first. //! //! This allows you to conveniently provide a long list `#[cfg]`'d blocks of code //! without having to rewrite each clause multiple times. //! //! # Example //! //! ``` //! cfg_if::cfg_if! { //! if #[cfg(unix)] { //! fn foo() { /* unix specific functionality */ } //! } else if #[cfg(target_pointer_width = "32")] { //! fn foo() { /* non-unix, 32-bit functionality */ } //! } else { //! fn foo() { /* fallback implementation */ } //! } //! } //! //! # fn main() {} //! ``` #![no_std] #![doc(html_root_url = "https://docs.rs/cfg-if")] #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] /// The main macro provided by this crate. See crate documentation for more /// information. #[macro_export] macro_rules! cfg_if { // match if/else chains with a final `else` ($( if #[cfg($meta:meta)] { $($tokens:tt)* } ) else * else { $($tokens2:tt)* }) => { $crate::cfg_if! { @__items () ; $( ( ($meta) ($($tokens)*) ), )* ( () ($($tokens2)*) ), } }; // match if/else chains lacking a final `else` ( if #[cfg($i_met:meta)] { $($i_tokens:tt)* } $( else if #[cfg($e_met:meta)] { $($e_tokens:tt)* } )* ) => { $crate::cfg_if! { @__items () ; ( ($i_met) ($($i_tokens)*) ), $( ( ($e_met) ($($e_tokens)*) ), )* ( () () ), } }; // Internal and recursive macro to emit all the items // // Collects all the negated cfgs in a list at the beginning and after the // semicolon is all the remaining items (@__items ($($not:meta,)*) ; ) => {}; (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($tokens:tt)*) ), $($rest:tt)*) => { // Emit all items within one block, applying an appropriate #[cfg]. The // #[cfg] will require all `$m` matchers specified and must also negate // all previous matchers. #[cfg(all($($m,)* not(any($($not),*))))] $crate::cfg_if! { @__identity $($tokens)* } // Recurse to emit all other items in `$rest`, and when we do so add all // our `$m` matchers to the list of `$not` matchers as future emissions // will have to negate everything we just matched as well. $crate::cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } }; // Internal macro to make __apply work out right for different match types, // because of how macros matching/expand stuff. (@__identity $($tokens:tt)*) => { $($tokens)* }; } #[cfg(test)] mod tests { cfg_if! { if #[cfg(test)] { use core::option::Option as Option2; fn works1() -> Option2 { Some(1) } } else { fn works1() -> Option { None } } } cfg_if! { if #[cfg(foo)] { fn works2() -> bool { false } } else if #[cfg(test)] { fn works2() -> bool { true } } else { fn works2() -> bool { false } } } cfg_if! { if #[cfg(foo)] { fn works3() -> bool { false } } else { fn works3() -> bool { true } } } cfg_if! { if #[cfg(test)] { use core::option::Option as Option3; fn works4() -> Option3 { Some(1) } } } cfg_if! { if #[cfg(foo)] { fn works5() -> bool { false } } else if #[cfg(test)] { fn works5() -> bool { true } } } #[test] fn it_works() { assert!(works1().is_some()); assert!(works2()); assert!(works3()); assert!(works4().is_some()); assert!(works5()); } #[test] #[allow(clippy::assertions_on_constants)] fn test_usage_within_a_function() { cfg_if! {if #[cfg(debug_assertions)] { // we want to put more than one thing here to make sure that they // all get configured properly. assert!(cfg!(debug_assertions)); assert_eq!(4, 2+2); } else { assert!(works1().is_some()); assert_eq!(10, 5+5); }} } trait Trait { fn blah(&self); } #[allow(dead_code)] struct Struct; impl Trait for Struct { cfg_if! { if #[cfg(feature = "blah")] { fn blah(&self) { unimplemented!(); } } else { fn blah(&self) { unimplemented!(); } } } } } cfg-if/.cargo-checksum.json0000664000175000017500000000110114661133735016533 0ustar jamespagejamespage{"files":{"Cargo.toml":"5b2a8f6e5256957c029cf3a8912d51438e7faa5891c5c102c312f6d4599c1f00","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"2406e83ee174e30aa67f8ab266836fa78545012b196395aff37c152321e2c713","src/lib.rs":"54b0f108b0dc48a077c52c0bcd22b64ef4de083e5e2b7d405e50ae4d78224f1b","tests/xcrate.rs":"c0734dae6e63beafcd60bf53546115a2320735b51035c9e2387fdf9301580934"},"package":"baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"}heck/0000775000175000017500000000000014661133735012455 5ustar jamespagejamespageheck/README.md0000644000175000017500000000363714661133735013743 0ustar jamespagejamespage# **heck** is a case conversion library !["I specifically requested the opposite of this."](./no_step_on_snek.png) This library exists to provide case conversion between common cases like CamelCase and snake_case. It is intended to be unicode aware, internally consistent, and reasonably well performing. ## Definition of a word boundary Word boundaries are defined by non-alphanumeric characters, as well as within those words in this manner: 1. If an uppercase character is followed by lowercase letters, a word boundary is considered to be just prior to that uppercase character. 2. If multiple uppercase characters are consecutive, they are considered to be within a single word, except that the last will be part of the next word if it is followed by lowercase characters (see rule 1). That is, "HelloWorld" is segmented `Hello|World` whereas "XMLHttpRequest" is segmented `XML|Http|Request`. Characters not within words (such as spaces, punctuations, and underscores) are not included in the output string except as they are a part of the case being converted to. Multiple adjacent word boundaries (such as a series of underscores) are folded into one. ("hello__world" in snake case is therefore "hello_world", not the exact same string). Leading or trailing word boundary indicators are dropped, except insofar as CamelCase capitalizes the first word. ## Cases contained in this library: 1. UpperCamelCase 2. lowerCamelCase 3. snake_case 4. kebab-case 5. SHOUTY_SNAKE_CASE 6. Title Case 7. SHOUTY-KEBAB-CASE 8. Train-Case ## MSRV The minimum supported Rust version for this crate is 1.56.0. This may change in minor or patch releases, but we probably won't ever require a very recent version. If you would like to have a stronger guarantee than that, please open an issue. ## License heck is distributed under the terms of both the MIT license and the Apache License (Version 2.0). See LICENSE-APACHE and LICENSE-MIT for details. heck/LICENSE-APACHE0000644000175000017500000002513714661133735014407 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. heck/Cargo.toml0000644000175000017500000000157414661133735014412 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "heck" version = "0.5.0" include = [ "src/**/*", "LICENSE-*", "README.md", "CHANGELOG.md", ] description = "heck is a case conversion library." readme = "README.md" keywords = [ "string", "case", "camel", "snake", "unicode", ] categories = ["no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/withoutboats/heck" heck/LICENSE-MIT0000644000175000017500000000205714661133735014113 0ustar jamespagejamespageCopyright (c) 2015 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. heck/src/0000775000175000017500000000000014661133735013244 5ustar jamespagejamespageheck/src/train.rs0000644000175000017500000000547014661133735014733 0ustar jamespagejamespageuse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{capitalize, transform}; /// This trait defines a train case conversion. /// /// In Train-Case, word boundaries are indicated by hyphens and words start /// with Capital Letters. /// /// ## Example: /// /// ```rust /// use heck::ToTrainCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(sentence.to_train_case(), "We-Are-Going-To-Inherit-The-Earth"); /// ``` pub trait ToTrainCase: ToOwned { /// Convert this type to Train-Case. fn to_train_case(&self) -> Self::Owned; } impl ToTrainCase for str { fn to_train_case(&self) -> Self::Owned { AsTrainCase(self).to_string() } } /// This wrapper performs a train case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsTrainCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(format!("{}", AsTrainCase(sentence)), "We-Are-Going-To-Inherit-The-Earth"); /// ``` pub struct AsTrainCase>(pub T); impl> fmt::Display for AsTrainCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), capitalize, |f| write!(f, "-"), f) } } #[cfg(test)] mod tests { use super::ToTrainCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_train_case(), $s2) } }; } t!(test1: "CamelCase" => "Camel-Case"); t!(test2: "This is Human case." => "This-Is-Human-Case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "Mixed-Up-Camel-Case-With-Some-Spaces"); t!(test4: "mixed_up_ snake_case with some _spaces" => "Mixed-Up-Snake-Case-With-Some-Spaces"); t!(test5: "kebab-case" => "Kebab-Case"); t!(test6: "SHOUTY_SNAKE_CASE" => "Shouty-Snake-Case"); t!(test7: "snake_case" => "Snake-Case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "This-Contains-All-Kinds-Of-Word-Boundaries"); #[cfg(feature = "unicode")] t!(test9: "XΣXΣ baffle" => "Xσxς-Baffle"); t!(test10: "XMLHttpRequest" => "Xml-Http-Request"); t!(test11: "FIELD_NAME11" => "Field-Name11"); t!(test12: "99BOTTLES" => "99bottles"); t!(test13: "FieldNamE11" => "Field-Nam-E11"); t!(test14: "abc123def456" => "Abc123def456"); t!(test16: "abc123DEF456" => "Abc123-Def456"); t!(test17: "abc123Def456" => "Abc123-Def456"); t!(test18: "abc123DEf456" => "Abc123-D-Ef456"); t!(test19: "ABC123def456" => "Abc123def456"); t!(test20: "ABC123DEF456" => "Abc123def456"); t!(test21: "ABC123Def456" => "Abc123-Def456"); t!(test22: "ABC123DEf456" => "Abc123d-Ef456"); t!(test23: "ABC123dEEf456FOO" => "Abc123d-E-Ef456-Foo"); t!(test24: "abcDEF" => "Abc-Def"); t!(test25: "ABcDE" => "A-Bc-De"); } heck/src/shouty_snake.rs0000644000175000017500000000522414661133735016327 0ustar jamespagejamespageuse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{transform, uppercase}; /// This trait defines a shouty snake case conversion. /// /// In SHOUTY_SNAKE_CASE, word boundaries are indicated by underscores and all /// words are in uppercase. /// /// ## Example: /// /// ```rust /// use heck::ToShoutySnakeCase; /// /// let sentence = "That world is growing in this minute."; /// assert_eq!(sentence.to_shouty_snake_case(), "THAT_WORLD_IS_GROWING_IN_THIS_MINUTE"); /// ``` pub trait ToShoutySnakeCase: ToOwned { /// Convert this type to shouty snake case. fn to_shouty_snake_case(&self) -> Self::Owned; } /// Oh heck, `ToShoutySnekCase` is an alias for [`ToShoutySnakeCase`]. See /// ToShoutySnakeCase for more documentation. pub trait ToShoutySnekCase: ToOwned { /// CONVERT THIS TYPE TO SNEK CASE. #[allow(non_snake_case)] fn TO_SHOUTY_SNEK_CASE(&self) -> Self::Owned; } impl ToShoutySnekCase for T { fn TO_SHOUTY_SNEK_CASE(&self) -> Self::Owned { self.to_shouty_snake_case() } } impl ToShoutySnakeCase for str { fn to_shouty_snake_case(&self) -> Self::Owned { AsShoutySnakeCase(self).to_string() } } /// This wrapper performs a shouty snake case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsShoutySnakeCase; /// /// let sentence = "That world is growing in this minute."; /// assert_eq!(format!("{}", AsShoutySnakeCase(sentence)), "THAT_WORLD_IS_GROWING_IN_THIS_MINUTE"); /// ``` pub struct AsShoutySnakeCase>(pub T); impl> fmt::Display for AsShoutySnakeCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), uppercase, |f| write!(f, "_"), f) } } #[cfg(test)] mod tests { use super::ToShoutySnakeCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_shouty_snake_case(), $s2) } }; } t!(test1: "CamelCase" => "CAMEL_CASE"); t!(test2: "This is Human case." => "THIS_IS_HUMAN_CASE"); t!(test3: "MixedUP CamelCase, with some Spaces" => "MIXED_UP_CAMEL_CASE_WITH_SOME_SPACES"); t!(test4: "mixed_up_snake_case with some _spaces" => "MIXED_UP_SNAKE_CASE_WITH_SOME_SPACES"); t!(test5: "kebab-case" => "KEBAB_CASE"); t!(test6: "SHOUTY_SNAKE_CASE" => "SHOUTY_SNAKE_CASE"); t!(test7: "snake_case" => "SNAKE_CASE"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "THIS_CONTAINS_ALL_KINDS_OF_WORD_BOUNDARIES"); t!(test9: "XΣXΣ baffle" => "XΣXΣ_BAFFLE"); t!(test10: "XMLHttpRequest" => "XML_HTTP_REQUEST"); } heck/src/lib.rs0000644000175000017500000001454114661133735014363 0ustar jamespagejamespage//! **heck** is a case conversion library. //! //! This library exists to provide case conversion between common cases like //! CamelCase and snake_case. It is intended to be unicode aware, internally //! consistent, and reasonably well performing. //! //! ## Definition of a word boundary //! //! Word boundaries are defined by non-alphanumeric characters, as well as //! within those words in this manner: //! //! 1. If an uppercase character is followed by lowercase letters, a word //! boundary is considered to be just prior to that uppercase character. //! 2. If multiple uppercase characters are consecutive, they are considered to //! be within a single word, except that the last will be part of the next word //! if it is followed by lowercase characters (see rule 1). //! //! That is, "HelloWorld" is segmented `Hello|World` whereas "XMLHttpRequest" is //! segmented `XML|Http|Request`. //! //! Characters not within words (such as spaces, punctuations, and underscores) //! are not included in the output string except as they are a part of the case //! being converted to. Multiple adjacent word boundaries (such as a series of //! underscores) are folded into one. ("hello__world" in snake case is therefore //! "hello_world", not the exact same string). Leading or trailing word boundary //! indicators are dropped, except insofar as CamelCase capitalizes the first //! word. //! //! ### Cases contained in this library: //! //! 1. UpperCamelCase //! 2. lowerCamelCase //! 3. snake_case //! 4. kebab-case //! 5. SHOUTY_SNAKE_CASE //! 6. Title Case //! 7. SHOUTY-KEBAB-CASE //! 8. Train-Case #![deny(missing_docs)] #![forbid(unsafe_code)] #![no_std] extern crate alloc; mod kebab; mod lower_camel; mod shouty_kebab; mod shouty_snake; mod snake; mod title; mod train; mod upper_camel; pub use kebab::{AsKebabCase, ToKebabCase}; pub use lower_camel::{AsLowerCamelCase, ToLowerCamelCase}; pub use shouty_kebab::{AsShoutyKebabCase, ToShoutyKebabCase}; pub use shouty_snake::{ AsShoutySnakeCase, AsShoutySnakeCase as AsShoutySnekCase, ToShoutySnakeCase, ToShoutySnekCase, }; pub use snake::{AsSnakeCase, AsSnakeCase as AsSnekCase, ToSnakeCase, ToSnekCase}; pub use title::{AsTitleCase, ToTitleCase}; pub use train::{AsTrainCase, ToTrainCase}; pub use upper_camel::{ AsUpperCamelCase, AsUpperCamelCase as AsPascalCase, ToPascalCase, ToUpperCamelCase, }; use core::fmt; fn transform( s: &str, mut with_word: F, mut boundary: G, f: &mut fmt::Formatter, ) -> fmt::Result where F: FnMut(&str, &mut fmt::Formatter) -> fmt::Result, G: FnMut(&mut fmt::Formatter) -> fmt::Result, { /// Tracks the current 'mode' of the transformation algorithm as it scans /// the input string. /// /// The mode is a tri-state which tracks the case of the last cased /// character of the current word. If there is no cased character /// (either lowercase or uppercase) since the previous word boundary, /// than the mode is `Boundary`. If the last cased character is lowercase, /// then the mode is `Lowercase`. Othertherwise, the mode is /// `Uppercase`. #[derive(Clone, Copy, PartialEq)] enum WordMode { /// There have been no lowercase or uppercase characters in the current /// word. Boundary, /// The previous cased character in the current word is lowercase. Lowercase, /// The previous cased character in the current word is uppercase. Uppercase, } let mut first_word = true; for word in s.split(|c: char| !c.is_alphanumeric()) { let mut char_indices = word.char_indices().peekable(); let mut init = 0; let mut mode = WordMode::Boundary; while let Some((i, c)) = char_indices.next() { if let Some(&(next_i, next)) = char_indices.peek() { // The mode including the current character, assuming the // current character does not result in a word boundary. let next_mode = if c.is_lowercase() { WordMode::Lowercase } else if c.is_uppercase() { WordMode::Uppercase } else { mode }; // Word boundary after if current is not uppercase and next // is uppercase if next_mode == WordMode::Lowercase && next.is_uppercase() { if !first_word { boundary(f)?; } with_word(&word[init..next_i], f)?; first_word = false; init = next_i; mode = WordMode::Boundary; // Otherwise if current and previous are uppercase and next // is lowercase, word boundary before } else if mode == WordMode::Uppercase && c.is_uppercase() && next.is_lowercase() { if !first_word { boundary(f)?; } else { first_word = false; } with_word(&word[init..i], f)?; init = i; mode = WordMode::Boundary; // Otherwise no word boundary, just update the mode } else { mode = next_mode; } } else { // Collect trailing characters as a word if !first_word { boundary(f)?; } else { first_word = false; } with_word(&word[init..], f)?; break; } } } Ok(()) } fn lowercase(s: &str, f: &mut fmt::Formatter) -> fmt::Result { let mut chars = s.chars().peekable(); while let Some(c) = chars.next() { if c == 'Σ' && chars.peek().is_none() { write!(f, "ς")?; } else { write!(f, "{}", c.to_lowercase())?; } } Ok(()) } fn uppercase(s: &str, f: &mut fmt::Formatter) -> fmt::Result { for c in s.chars() { write!(f, "{}", c.to_uppercase())?; } Ok(()) } fn capitalize(s: &str, f: &mut fmt::Formatter) -> fmt::Result { let mut char_indices = s.char_indices(); if let Some((_, c)) = char_indices.next() { write!(f, "{}", c.to_uppercase())?; if let Some((i, _)) = char_indices.next() { lowercase(&s[i..], f)?; } } Ok(()) } heck/src/upper_camel.rs0000644000175000017500000000506214661133735016107 0ustar jamespagejamespageuse core::fmt; use alloc::{ borrow::ToOwned, string::{String, ToString}, }; use crate::{capitalize, transform}; /// This trait defines an upper camel case conversion. /// /// In UpperCamelCase, word boundaries are indicated by capital letters, /// including the first word. /// /// ## Example: /// /// ```rust /// use heck::ToUpperCamelCase; /// /// let sentence = "We are not in the least afraid of ruins."; /// assert_eq!(sentence.to_upper_camel_case(), "WeAreNotInTheLeastAfraidOfRuins"); /// ``` pub trait ToUpperCamelCase: ToOwned { /// Convert this type to upper camel case. fn to_upper_camel_case(&self) -> Self::Owned; } impl ToUpperCamelCase for str { fn to_upper_camel_case(&self) -> String { AsUpperCamelCase(self).to_string() } } /// `ToPascalCase` is an alias for [`ToUpperCamelCase`]. See ToUpperCamelCase for more /// documentation. pub trait ToPascalCase: ToOwned { /// Convert this type to upper camel case. fn to_pascal_case(&self) -> Self::Owned; } impl ToPascalCase for T { fn to_pascal_case(&self) -> Self::Owned { self.to_upper_camel_case() } } /// This wrapper performs a upper camel case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsUpperCamelCase; /// /// let sentence = "We are not in the least afraid of ruins."; /// assert_eq!(format!("{}", AsUpperCamelCase(sentence)), "WeAreNotInTheLeastAfraidOfRuins"); /// ``` pub struct AsUpperCamelCase>(pub T); impl> fmt::Display for AsUpperCamelCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), capitalize, |_| Ok(()), f) } } #[cfg(test)] mod tests { use super::ToUpperCamelCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_upper_camel_case(), $s2) } }; } t!(test1: "CamelCase" => "CamelCase"); t!(test2: "This is Human case." => "ThisIsHumanCase"); t!(test3: "MixedUP_CamelCase, with some Spaces" => "MixedUpCamelCaseWithSomeSpaces"); t!(test4: "mixed_up_ snake_case, with some _spaces" => "MixedUpSnakeCaseWithSomeSpaces"); t!(test5: "kebab-case" => "KebabCase"); t!(test6: "SHOUTY_SNAKE_CASE" => "ShoutySnakeCase"); t!(test7: "snake_case" => "SnakeCase"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "ThisContainsAllKindsOfWordBoundaries"); t!(test9: "XΣXΣ baffle" => "XσxςBaffle"); t!(test10: "XMLHttpRequest" => "XmlHttpRequest"); } heck/src/snake.rs0000644000175000017500000000616214661133735014716 0ustar jamespagejamespageuse alloc::{ borrow::ToOwned, fmt, string::{String, ToString}, }; use crate::{lowercase, transform}; /// This trait defines a snake case conversion. /// /// In snake_case, word boundaries are indicated by underscores. /// /// ## Example: /// /// ```rust /// use heck::ToSnakeCase; /// /// let sentence = "We carry a new world here, in our hearts."; /// assert_eq!(sentence.to_snake_case(), "we_carry_a_new_world_here_in_our_hearts"); /// ``` pub trait ToSnakeCase: ToOwned { /// Convert this type to snake case. fn to_snake_case(&self) -> Self::Owned; } /// Oh heck, `SnekCase` is an alias for [`ToSnakeCase`]. See ToSnakeCase for /// more documentation. pub trait ToSnekCase: ToOwned { /// Convert this type to snek case. fn to_snek_case(&self) -> Self::Owned; } impl ToSnekCase for T { fn to_snek_case(&self) -> Self::Owned { self.to_snake_case() } } impl ToSnakeCase for str { fn to_snake_case(&self) -> String { AsSnakeCase(self).to_string() } } /// This wrapper performs a snake case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsSnakeCase; /// /// let sentence = "We carry a new world here, in our hearts."; /// assert_eq!(format!("{}", AsSnakeCase(sentence)), "we_carry_a_new_world_here_in_our_hearts"); /// ``` pub struct AsSnakeCase>(pub T); impl> fmt::Display for AsSnakeCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), lowercase, |f| write!(f, "_"), f) } } #[cfg(test)] mod tests { use super::ToSnakeCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_snake_case(), $s2) } }; } t!(test1: "CamelCase" => "camel_case"); t!(test2: "This is Human case." => "this_is_human_case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "mixed_up_camel_case_with_some_spaces"); t!(test4: "mixed_up_ snake_case with some _spaces" => "mixed_up_snake_case_with_some_spaces"); t!(test5: "kebab-case" => "kebab_case"); t!(test6: "SHOUTY_SNAKE_CASE" => "shouty_snake_case"); t!(test7: "snake_case" => "snake_case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "this_contains_all_kinds_of_word_boundaries"); t!(test9: "XΣXΣ baffle" => "xσxς_baffle"); t!(test10: "XMLHttpRequest" => "xml_http_request"); t!(test11: "FIELD_NAME11" => "field_name11"); t!(test12: "99BOTTLES" => "99bottles"); t!(test13: "FieldNamE11" => "field_nam_e11"); t!(test14: "abc123def456" => "abc123def456"); t!(test16: "abc123DEF456" => "abc123_def456"); t!(test17: "abc123Def456" => "abc123_def456"); t!(test18: "abc123DEf456" => "abc123_d_ef456"); t!(test19: "ABC123def456" => "abc123def456"); t!(test20: "ABC123DEF456" => "abc123def456"); t!(test21: "ABC123Def456" => "abc123_def456"); t!(test22: "ABC123DEf456" => "abc123d_ef456"); t!(test23: "ABC123dEEf456FOO" => "abc123d_e_ef456_foo"); t!(test24: "abcDEF" => "abc_def"); t!(test25: "ABcDE" => "a_bc_de"); } heck/src/kebab.rs0000644000175000017500000000463214661133735014661 0ustar jamespagejamespageuse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{lowercase, transform}; /// This trait defines a kebab case conversion. /// /// In kebab-case, word boundaries are indicated by hyphens. /// /// ## Example: /// /// ```rust /// use heck::ToKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(sentence.to_kebab_case(), "we-are-going-to-inherit-the-earth"); /// ``` pub trait ToKebabCase: ToOwned { /// Convert this type to kebab case. fn to_kebab_case(&self) -> Self::Owned; } impl ToKebabCase for str { fn to_kebab_case(&self) -> Self::Owned { AsKebabCase(self).to_string() } } /// This wrapper performs a kebab case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(format!("{}", AsKebabCase(sentence)), "we-are-going-to-inherit-the-earth"); /// ``` pub struct AsKebabCase>(pub T); impl> fmt::Display for AsKebabCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), lowercase, |f| write!(f, "-"), f) } } #[cfg(test)] mod tests { use super::ToKebabCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_kebab_case(), $s2) } }; } t!(test1: "CamelCase" => "camel-case"); t!(test2: "This is Human case." => "this-is-human-case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "mixed-up-camel-case-with-some-spaces"); t!(test4: "mixed_up_ snake_case with some _spaces" => "mixed-up-snake-case-with-some-spaces"); t!(test5: "kebab-case" => "kebab-case"); t!(test6: "SHOUTY_SNAKE_CASE" => "shouty-snake-case"); t!(test7: "snake_case" => "snake-case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "this-contains-all-kinds-of-word-boundaries"); t!(test9: "XΣXΣ baffle" => "xσxς-baffle"); t!(test10: "XMLHttpRequest" => "xml-http-request"); t!(test11: "لِنَذْهَبْ إِلَى السِّيْنَمَا" => "لِنَذْهَبْ-إِلَى-السِّيْنَمَا"); // Japanese and Chinese do not have word separation. t!(test12: "ファイルを読み込み" => "ファイルを読み込み"); t!(test13: "祝你一天过得愉快" => "祝你一天过得愉快"); } heck/src/title.rs0000644000175000017500000000427214661133735014736 0ustar jamespagejamespageuse core::fmt; use alloc::{ borrow::ToOwned, string::{String, ToString}, }; use crate::{capitalize, transform}; /// This trait defines a title case conversion. /// /// In Title Case, word boundaries are indicated by spaces, and every word is /// capitalized. /// /// ## Example: /// /// ```rust /// use heck::ToTitleCase; /// /// let sentence = "We have always lived in slums and holes in the wall."; /// assert_eq!(sentence.to_title_case(), "We Have Always Lived In Slums And Holes In The Wall"); /// ``` pub trait ToTitleCase: ToOwned { /// Convert this type to title case. fn to_title_case(&self) -> Self::Owned; } impl ToTitleCase for str { fn to_title_case(&self) -> String { AsTitleCase(self).to_string() } } /// This wrapper performs a title case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsTitleCase; /// /// let sentence = "We have always lived in slums and holes in the wall."; /// assert_eq!(format!("{}", AsTitleCase(sentence)), "We Have Always Lived In Slums And Holes In The Wall"); /// ``` pub struct AsTitleCase>(pub T); impl> fmt::Display for AsTitleCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), capitalize, |f| write!(f, " "), f) } } #[cfg(test)] mod tests { use super::ToTitleCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_title_case(), $s2) } }; } t!(test1: "CamelCase" => "Camel Case"); t!(test2: "This is Human case." => "This Is Human Case"); t!(test3: "MixedUP CamelCase, with some Spaces" => "Mixed Up Camel Case With Some Spaces"); t!(test4: "mixed_up_ snake_case, with some _spaces" => "Mixed Up Snake Case With Some Spaces"); t!(test5: "kebab-case" => "Kebab Case"); t!(test6: "SHOUTY_SNAKE_CASE" => "Shouty Snake Case"); t!(test7: "snake_case" => "Snake Case"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "This Contains All Kinds Of Word Boundaries"); t!(test9: "XΣXΣ baffle" => "Xσxς Baffle"); t!(test10: "XMLHttpRequest" => "Xml Http Request"); } heck/src/shouty_kebab.rs0000644000175000017500000000440314661133735016270 0ustar jamespagejamespageuse core::fmt; use alloc::{borrow::ToOwned, string::ToString}; use crate::{transform, uppercase}; /// This trait defines a shouty kebab case conversion. /// /// In SHOUTY-KEBAB-CASE, word boundaries are indicated by hyphens and all /// words are in uppercase. /// /// ## Example: /// /// ```rust /// use heck::ToShoutyKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(sentence.to_shouty_kebab_case(), "WE-ARE-GOING-TO-INHERIT-THE-EARTH"); /// ``` pub trait ToShoutyKebabCase: ToOwned { /// Convert this type to shouty kebab case. fn to_shouty_kebab_case(&self) -> Self::Owned; } impl ToShoutyKebabCase for str { fn to_shouty_kebab_case(&self) -> Self::Owned { AsShoutyKebabCase(self).to_string() } } /// This wrapper performs a kebab case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsShoutyKebabCase; /// /// let sentence = "We are going to inherit the earth."; /// assert_eq!(format!("{}", AsShoutyKebabCase(sentence)), "WE-ARE-GOING-TO-INHERIT-THE-EARTH"); /// ``` pub struct AsShoutyKebabCase>(pub T); impl> fmt::Display for AsShoutyKebabCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { transform(self.0.as_ref(), uppercase, |f| write!(f, "-"), f) } } #[cfg(test)] mod tests { use super::ToShoutyKebabCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_shouty_kebab_case(), $s2) } }; } t!(test1: "CamelCase" => "CAMEL-CASE"); t!(test2: "This is Human case." => "THIS-IS-HUMAN-CASE"); t!(test3: "MixedUP CamelCase, with some Spaces" => "MIXED-UP-CAMEL-CASE-WITH-SOME-SPACES"); t!(test4: "mixed_up_ snake_case with some _spaces" => "MIXED-UP-SNAKE-CASE-WITH-SOME-SPACES"); t!(test5: "kebab-case" => "KEBAB-CASE"); t!(test6: "SHOUTY_SNAKE_CASE" => "SHOUTY-SNAKE-CASE"); t!(test7: "snake_case" => "SNAKE-CASE"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "THIS-CONTAINS-ALL-KINDS-OF-WORD-BOUNDARIES"); t!(test9: "XΣXΣ baffle" => "XΣXΣ-BAFFLE"); t!(test10: "XMLHttpRequest" => "XML-HTTP-REQUEST"); t!(test11: "SHOUTY-KEBAB-CASE" => "SHOUTY-KEBAB-CASE"); } heck/src/lower_camel.rs0000644000175000017500000000474614661133735016114 0ustar jamespagejamespageuse core::fmt; use alloc::{ borrow::ToOwned, string::{String, ToString}, }; use crate::{capitalize, lowercase, transform}; /// This trait defines a lower camel case conversion. /// /// In lowerCamelCase, word boundaries are indicated by capital letters, /// excepting the first word. /// /// ## Example: /// /// ```rust /// use heck::ToLowerCamelCase; /// /// let sentence = "It is we who built these palaces and cities."; /// assert_eq!(sentence.to_lower_camel_case(), "itIsWeWhoBuiltThesePalacesAndCities"); /// ``` pub trait ToLowerCamelCase: ToOwned { /// Convert this type to lower camel case. fn to_lower_camel_case(&self) -> Self::Owned; } impl ToLowerCamelCase for str { fn to_lower_camel_case(&self) -> String { AsLowerCamelCase(self).to_string() } } /// This wrapper performs a lower camel case conversion in [`fmt::Display`]. /// /// ## Example: /// /// ``` /// use heck::AsLowerCamelCase; /// /// let sentence = "It is we who built these palaces and cities."; /// assert_eq!(format!("{}", AsLowerCamelCase(sentence)), "itIsWeWhoBuiltThesePalacesAndCities"); /// ``` pub struct AsLowerCamelCase>(pub T); impl> fmt::Display for AsLowerCamelCase { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut first = true; transform( self.0.as_ref(), |s, f| { if first { first = false; lowercase(s, f) } else { capitalize(s, f) } }, |_| Ok(()), f, ) } } #[cfg(test)] mod tests { use super::ToLowerCamelCase; macro_rules! t { ($t:ident : $s1:expr => $s2:expr) => { #[test] fn $t() { assert_eq!($s1.to_lower_camel_case(), $s2) } }; } t!(test1: "CamelCase" => "camelCase"); t!(test2: "This is Human case." => "thisIsHumanCase"); t!(test3: "MixedUP CamelCase, with some Spaces" => "mixedUpCamelCaseWithSomeSpaces"); t!(test4: "mixed_up_ snake_case, with some _spaces" => "mixedUpSnakeCaseWithSomeSpaces"); t!(test5: "kebab-case" => "kebabCase"); t!(test6: "SHOUTY_SNAKE_CASE" => "shoutySnakeCase"); t!(test7: "snake_case" => "snakeCase"); t!(test8: "this-contains_ ALLKinds OfWord_Boundaries" => "thisContainsAllKindsOfWordBoundaries"); t!(test9: "XΣXΣ baffle" => "xσxςBaffle"); t!(test10: "XMLHttpRequest" => "xmlHttpRequest"); } heck/CHANGELOG.md0000644000175000017500000000130514661133735014263 0ustar jamespagejamespage# unreleased # 0.5.0 - Add `no_std` support. - Remove non-additive `unicode` feature. The library now uses `char::is_alphanumeric` instead of the `unicode-segmentation` library to determine word boundaries in all cases. # 0.4.1 Improvements: - Add Train-Case support # 0.4.0 Breaking changes: * Make unicode support optional (off by default). Enable the `unicode` crate feature if you need unicode support. * Rename all traits from `SomeCase` to `ToSomeCase`, matching `std`s convention of beginning trait names with a verb (`ToOwned`, `AsRef`, …) * Rename `ToMixedCase` to `ToLowerCamelCase` * Rename `ToCamelCase` to `ToUpperCamelCase` * Add `ToPascalCase` as an alias to `ToUpperCamelCase` heck/.cargo-checksum.json0000664000175000017500000000235014661133735016321 0ustar jamespagejamespage{"files":{"CHANGELOG.md":"972078362c7c30856e5ef46aa52c1c0ec3de40f417544566e225204b4cd4982a","Cargo.toml":"db0e63b72de157a2f5194458b73b6542c3f4e17e33ab34a71d0260bfc035467e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"c3c627aa49e64826aaf4914e5a3bd0aa2d1b304464c3e99cb6507190d3620a85","src/kebab.rs":"3075cf72c95404e6b5800494a5d8a3c5f6dd5066593ddb249cefcb376e30b450","src/lib.rs":"bffcc5144da472d2f915696d4654f7608e60861d168d3dd07b5dcb8f14211153","src/lower_camel.rs":"3b1e367db1ae22aa8c49b6800abf5e23e6befadf7cc89a252534f7286676e11f","src/shouty_kebab.rs":"8539eeddd4d78c10a8d0df3e19ad171409e95429debcdc6b7dbefd82d37b6928","src/shouty_snake.rs":"e8b6dcb77de87e2355067d5d47037537b68fa51c2601924a6acfae409c6d9920","src/snake.rs":"e13e8a4373e9388044bd91edff496362a1e7f6bd52f5f6be14a043878035245d","src/title.rs":"a12abc5057b48b8d5922d2a11b6029b230e13ae9a04109a40407d19505c2521b","src/train.rs":"0cbe348135852c12e9c56ab93233ca5c044218bc1b8818b620c3e80cd19973c2","src/upper_camel.rs":"9036542a600fd261b046ac4574622f831335abcf1366665aab56f4045fceb0d5"},"package":"2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"}indoc/0000775000175000017500000000000014661133735012637 5ustar jamespagejamespageindoc/README.md0000644000175000017500000001017314661133735014116 0ustar jamespagejamespageIndented Documents (indoc) ========================== [github](https://github.com/dtolnay/indoc) [crates.io](https://crates.io/crates/indoc) [docs.rs](https://docs.rs/indoc) [build status](https://github.com/dtolnay/indoc/actions?query=branch%3Amaster) This crate provides a procedural macro for indented string literals. The `indoc!()` macro takes a multiline string literal and un-indents it at compile time so the leftmost non-space character is in the first column. ```toml [dependencies] indoc = "2" ``` *Compiler requirement: rustc 1.56 or greater.*
## Using indoc ```rust use indoc::indoc; fn main() { let testing = indoc! {" def hello(): print('Hello, world!') hello() "}; let expected = "def hello():\n print('Hello, world!')\n\nhello()\n"; assert_eq!(testing, expected); } ``` Indoc also works with raw string literals: ```rust use indoc::indoc; fn main() { let testing = indoc! {r#" def hello(): print("Hello, world!") hello() "#}; let expected = "def hello():\n print(\"Hello, world!\")\n\nhello()\n"; assert_eq!(testing, expected); } ``` And byte string literals: ```rust use indoc::indoc; fn main() { let testing = indoc! {b" def hello(): print('Hello, world!') hello() "}; let expected = b"def hello():\n print('Hello, world!')\n\nhello()\n"; assert_eq!(testing[..], expected[..]); } ```
## Formatting macros The indoc crate exports five additional macros to substitute conveniently for the standard library's formatting macros: - `formatdoc!($fmt, ...)` — equivalent to `format!(indoc!($fmt), ...)` - `printdoc!($fmt, ...)` — equivalent to `print!(indoc!($fmt), ...)` - `eprintdoc!($fmt, ...)` — equivalent to `eprint!(indoc!($fmt), ...)` - `writedoc!($dest, $fmt, ...)` — equivalent to `write!($dest, indoc!($fmt), ...)` - `concatdoc!(...)` — equivalent to `concat!(...)` with each string literal wrapped in `indoc!` ```rust use indoc::{concatdoc, printdoc}; const HELP: &str = concatdoc! {" Usage: ", env!("CARGO_BIN_NAME"), " [options] Options: -h, --help "}; fn main() { printdoc! {" GET {url} Accept: {mime} ", url = "http://localhost:8080", mime = "application/json", } } ```
## Explanation The following rules characterize the behavior of the `indoc!()` macro: 1. Count the leading spaces of each line, ignoring the first line and any lines that are empty or contain spaces only. 2. Take the minimum. 3. If the first line is empty i.e. the string begins with a newline, remove the first line. 4. Remove the computed number of spaces from the beginning of each line.
## Unindent Indoc's indentation logic is available in the `unindent` crate. This may be useful for processing strings that are not statically known at compile time. The crate exposes two functions: - `unindent(&str) -> String` - `unindent_bytes(&[u8]) -> Vec` ```rust use unindent::unindent; fn main() { let indented = " line one line two"; assert_eq!("line one\nline two", unindent(indented)); } ```
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. indoc/LICENSE-APACHE0000644000175000017500000002277314661133735014574 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS indoc/Cargo.toml0000644000175000017500000000242314661133735014566 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "indoc" version = "2.0.5" authors = ["David Tolnay "] description = "Indented document literals" documentation = "https://docs.rs/indoc" readme = "README.md" keywords = [ "heredoc", "nowdoc", "multiline", "string", "literal", ] categories = [ "rust-patterns", "text-processing", "no-std", "no-std::no-alloc", ] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/indoc" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [lib] doc-scrape-examples = false proc-macro = true [dev-dependencies.rustversion] version = "1.0" [dev-dependencies.trybuild] version = "1.0.49" features = ["diff"] [dev-dependencies.unindent] version = "0.2.3" indoc/tests/0000775000175000017500000000000014661133735014001 5ustar jamespagejamespageindoc/tests/test_writedoc.rs0000644000175000017500000000170314661133735017225 0ustar jamespagejamespage#![allow(clippy::if_same_then_else, clippy::let_underscore_untyped)] use indoc::writedoc; use std::fmt::Write as _; #[test] fn test_write_to_string() { let mut s = String::new(); writedoc!( s, " one two ", ) .unwrap(); let expected = "one\ntwo\n"; assert_eq!(s, expected); } #[test] fn test_format_args() { let mut s = String::new(); writedoc!( s, " {} {} ", 0, 0, ) .unwrap(); let expected = "0\n0\n"; assert_eq!(s, expected); } #[test] fn test_angle_bracket_parsing() { const ZERO: usize = 0; struct Pair(A, B); impl Pair { const ONE: usize = 1; } let mut s = String::new(); let _ = writedoc! { if ZERO < Pair:: (), ()>::ONE { &mut s } else { &mut s }, "writedoc", }; let expected = "writedoc"; assert_eq!(s, expected); } indoc/tests/test_concat.rs0000644000175000017500000000053214661133735016653 0ustar jamespagejamespageuse indoc::concatdoc; macro_rules! env { ($var:literal) => { "test" }; } static HELP: &str = concatdoc! {" Usage: ", env!("CARGO_BIN_NAME"), " [options] Options: -h, --help "}; #[test] fn test_help() { let expected = "Usage: test [options]\n\nOptions:\n -h, --help\n"; assert_eq!(HELP, expected); } indoc/tests/test_unindent.rs0000644000175000017500000000225314661133735017232 0ustar jamespagejamespage#![allow(clippy::shadow_unrelated)] use unindent::{unindent, unindent_bytes, Unindent}; #[test] fn fn_unindent_str() { let s = " line one line two"; assert_eq!(unindent(s), "line one\nline two"); let s = "\n\t\t\tline one\n\t\t\tline two"; assert_eq!(unindent(s), "line one\nline two"); } #[test] fn fn_unindent_bytes() { let b = b" line one line two"; assert_eq!(unindent_bytes(b), b"line one\nline two"); let b = b"\n\t\t\tline one\n\t\t\tline two"; assert_eq!(unindent_bytes(b), b"line one\nline two"); } #[test] fn trait_unindent_str() { let s = " line one line two"; assert_eq!(s.unindent(), "line one\nline two"); let s = "\n\t\t\tline one\n\t\t\tline two"; assert_eq!(s.unindent(), "line one\nline two"); } #[test] fn trait_unindent_bytes() { let b = b" line one line two"; assert_eq!(b.unindent(), b"line one\nline two"); let b = b"\n\t\t\tline one\n\t\t\tline two"; assert_eq!(b.unindent(), b"line one\nline two"); } #[test] fn carriage_returns() { let s = "\r\n\tline one\r\n\tline two"; assert_eq!(unindent(s), "line one\r\nline two"); } indoc/tests/compiletest.rs0000644000175000017500000000024614661133735016677 0ustar jamespagejamespage#[rustversion::attr(not(nightly), ignore)] #[cfg_attr(miri, ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); } indoc/tests/ui/0000775000175000017500000000000014661133735014416 5ustar jamespagejamespageindoc/tests/ui/non-string.stderr0000644000175000017500000000017314661133735017740 0ustar jamespagejamespageerror: argument must be a single string literal --> tests/ui/non-string.rs:4:12 | 4 | indoc!(64); | ^^ indoc/tests/ui/three-arguments.rs0000644000175000017500000000013714661133735020075 0ustar jamespagejamespageuse indoc::indoc; fn main() { indoc!(" a b c " 64 128); } indoc/tests/ui/printdoc-no-arg.rs0000644000175000017500000000007114661133735017763 0ustar jamespagejamespageuse indoc::printdoc; fn main() { printdoc!("{}"); } indoc/tests/ui/printdoc-no-display.stderr0000644000175000017500000000112514661133735021537 0ustar jamespagejamespageerror[E0277]: `NoDisplay` doesn't implement `std::fmt::Display` --> tests/ui/printdoc-no-display.rs:6:21 | 6 | printdoc!("{}", NoDisplay); | ^^^^^^^^^ `NoDisplay` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `NoDisplay` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args` which comes from the expansion of the macro `printdoc` (in Nightly builds, run with -Z macro-backtrace for more info) indoc/tests/ui/non-string.rs0000644000175000017500000000006114661133735017055 0ustar jamespagejamespageuse indoc::indoc; fn main() { indoc!(64); } indoc/tests/ui/three-arguments.stderr0000644000175000017500000000026314661133735020754 0ustar jamespagejamespageerror: unexpected tokens in macro invocation; indoc argument must be a single string literal --> tests/ui/three-arguments.rs:8:11 | 8 | " 64 128); | ^^^^^^ indoc/tests/ui/printdoc-no-named-arg.stderr0000644000175000017500000000026614661133735021732 0ustar jamespagejamespageerror[E0425]: cannot find value `named` in this scope --> tests/ui/printdoc-no-named-arg.rs:4:17 | 4 | printdoc!("{named}"); | ^^^^^ not found in this scope indoc/tests/ui/two-arguments.rs0000644000175000017500000000013314661133735017573 0ustar jamespagejamespageuse indoc::indoc; fn main() { indoc!(" a b c " 64); } indoc/tests/ui/printdoc-extra-arg.rs0000644000175000017500000000007214661133735020473 0ustar jamespagejamespageuse indoc::printdoc; fn main() { printdoc!("", 0); } indoc/tests/ui/non-lit.stderr0000644000175000017500000000017414661133735017223 0ustar jamespagejamespageerror: argument must be a single string literal --> tests/ui/non-lit.rs:4:12 | 4 | indoc!(fail); | ^^^^ indoc/tests/ui/no-arguments.rs0000644000175000017500000000005714661133735017403 0ustar jamespagejamespageuse indoc::indoc; fn main() { indoc!(); } indoc/tests/ui/printdoc-binary.rs0000644000175000017500000000007014661133735020063 0ustar jamespagejamespageuse indoc::printdoc; fn main() { printdoc!(b""); } indoc/tests/ui/no-arguments.stderr0000644000175000017500000000040314661133735020255 0ustar jamespagejamespageerror: unexpected end of macro invocation, expected format string --> tests/ui/no-arguments.rs:4:5 | 4 | indoc!(); | ^^^^^^^^ | = note: this error originates in the macro `indoc` (in Nightly builds, run with -Z macro-backtrace for more info) indoc/tests/ui/two-arguments.stderr0000644000175000017500000000025014661133735020452 0ustar jamespagejamespageerror: unexpected token in macro invocation; indoc argument must be a single string literal --> tests/ui/two-arguments.rs:8:11 | 8 | " 64); | ^^ indoc/tests/ui/capture-var-nested.rs0000644000175000017500000000014114661133735020467 0ustar jamespagejamespageuse indoc::indoc; fn main() { let world = "world"; println!(indoc!("Hello {world}")); } indoc/tests/ui/printdoc-no-display.rs0000644000175000017500000000012714661133735020661 0ustar jamespagejamespageuse indoc::printdoc; struct NoDisplay; fn main() { printdoc!("{}", NoDisplay); } indoc/tests/ui/non-lit.rs0000644000175000017500000000006314661133735016341 0ustar jamespagejamespageuse indoc::indoc; fn main() { indoc!(fail); } indoc/tests/ui/printdoc-no-named-arg.rs0000644000175000017500000000007614661133735021052 0ustar jamespagejamespageuse indoc::printdoc; fn main() { printdoc!("{named}"); } indoc/tests/ui/printdoc-extra-arg.stderr0000644000175000017500000000032114661133735021347 0ustar jamespagejamespageerror: argument never used --> tests/ui/printdoc-extra-arg.rs:4:19 | 4 | printdoc!("", 0); | -- ^ argument never used | | | formatting specifier missing indoc/tests/ui/printdoc-no-arg.stderr0000644000175000017500000000024414661133735020644 0ustar jamespagejamespageerror: 1 positional argument in format string, but no arguments were given --> tests/ui/printdoc-no-arg.rs:4:16 | 4 | printdoc!("{}"); | ^^ indoc/tests/ui/capture-var-nested.stderr0000644000175000017500000000056714661133735021362 0ustar jamespagejamespageerror: there is no argument named `world` --> tests/ui/capture-var-nested.rs:5:21 | 5 | println!(indoc!("Hello {world}")); | ^^^^^^^^^^^^^^^ | = note: did you intend to capture a variable `world` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro indoc/tests/ui/printdoc-binary.stderr0000644000175000017500000000022314661133735020742 0ustar jamespagejamespageerror: byte strings are not supported in formatting macros --> tests/ui/printdoc-binary.rs:4:15 | 4 | printdoc!(b""); | ^^^ indoc/tests/test_formatdoc.rs0000644000175000017500000000376514661133735017375 0ustar jamespagejamespageuse indoc::formatdoc; #[test] fn carriage_return() { // Every line in the string ends with \r\n let indoc = formatdoc! {" {} \\{} {}", 'a', 'b', 'c' }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn empty_string() { let indoc = formatdoc! {""}; let expected = ""; assert_eq!(indoc, expected); } #[test] fn joined_first_line() { let indoc = formatdoc! {"\ {}", 'a' }; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn joined_lines() { let indoc = formatdoc! {" {}\ {} {}\ {} {}", 'a', 'b', 'c', 'd', 'e' }; let expected = "ab\ncd\ne"; assert_eq!(indoc, expected); } #[test] fn no_leading_newline() { let indoc = formatdoc! {"{} {} {}", 'a', 'b', 'c'}; let expected = "a\nb\nc"; assert_eq!(indoc, expected); } #[test] fn one_line() { let indoc = formatdoc! {"a"}; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn raw_string() { let indoc = formatdoc! {r#" {:?} \\{} {}"#, "a", 'b', 'c' }; let expected = "\"a\"\n\n \\\\b\nc"; assert_eq!(indoc, expected); } #[test] fn string() { let indoc = formatdoc! {" {} \\{} {}", 'a', 'b', 'c' }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn string_trailing_newline() { let indoc = formatdoc! {" {} \\{} {} ", 'a', 'b', 'c' }; let expected = "a\n\n \\b\nc\n"; assert_eq!(indoc, expected); } #[test] fn trailing_whitespace() { let indoc = formatdoc! {" {} {below} {} {below} {} {below} end", 2, 0, -2, below = "below" }; let expected = "2 below\n \n0 below\n\n-2 below\n\nend"; assert_eq!(indoc, expected); } indoc/tests/test_indoc.rs0000644000175000017500000000543514661133735016507 0ustar jamespagejamespageuse indoc::indoc; const HELP: &str = indoc! {" Usage: ./foo "}; #[test] fn test_global() { let expected = "Usage: ./foo\n"; assert_eq!(HELP, expected); } #[test] fn byte_string() { let indoc = indoc! {b" a \\b c" }; let expected = b"a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn carriage_return() { // Every line in the string ends with \r\n let indoc = indoc! {" a \\b c" }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn trailing_comma() { let indoc = indoc! { " test ", }; let expected = "test\n"; assert_eq!(indoc, expected); } #[test] fn empty_string() { let indoc = indoc! {""}; let expected = ""; assert_eq!(indoc, expected); } #[test] fn joined_first_line() { let indoc = indoc! {"\ a" }; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn joined_lines() { let indoc = indoc! {" a\ b c\ d e" }; let expected = "ab\ncd\ne"; assert_eq!(indoc, expected); } #[test] fn no_leading_newline() { let indoc = indoc! {"a b c"}; let expected = "a\nb\nc"; assert_eq!(indoc, expected); } #[test] fn one_line() { let indoc = indoc! {"a"}; let expected = "a"; assert_eq!(indoc, expected); } #[test] fn raw_byte_string() { let indoc = indoc! {br#" "a" \\b c"# }; let expected = b"\"a\"\n\n \\\\b\nc"; assert_eq!(indoc, expected); } #[test] fn raw_string() { let indoc = indoc! {r#" "a" \\b c"# }; let expected = "\"a\"\n\n \\\\b\nc"; assert_eq!(indoc, expected); } #[test] fn string() { let indoc = indoc! {" a \\b c" }; let expected = "a\n\n \\b\nc"; assert_eq!(indoc, expected); } #[test] fn string_trailing_newline() { let indoc = indoc! {" a \\b c "}; let expected = "a\n\n \\b\nc\n"; assert_eq!(indoc, expected); } #[test] fn trailing_whitespace() { let indoc = indoc! {" 2 below 0 below -2 below end" }; let expected = "2 below\n \n0 below\n\n-2 below\n\nend"; assert_eq!(indoc, expected); } #[test] fn indoc_as_format_string() { let s = format!(indoc! {"{}"}, true); assert_eq!(s, "true"); } #[test] fn test_metavariable() { macro_rules! indoc_wrapper { ($e:expr) => { indoc!($e) }; } let indoc = indoc_wrapper! {" macros, how do they work "}; let expected = "macros, how do they work\n"; assert_eq!(indoc, expected); } indoc/LICENSE-MIT0000644000175000017500000000177714661133735014305 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. indoc/src/0000775000175000017500000000000014661133735013426 5ustar jamespagejamespageindoc/src/lib.rs0000644000175000017500000003177414661133735014554 0ustar jamespagejamespage//! [![github]](https://github.com/dtolnay/indoc) [![crates-io]](https://crates.io/crates/indoc) [![docs-rs]](https://docs.rs/indoc) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! This crate provides a procedural macro for indented string literals. The //! `indoc!()` macro takes a multiline string literal and un-indents it at //! compile time so the leftmost non-space character is in the first column. //! //! ```toml //! [dependencies] //! indoc = "2" //! ``` //! //!
//! //! # Using indoc //! //! ``` //! use indoc::indoc; //! //! fn main() { //! let testing = indoc! {" //! def hello(): //! print('Hello, world!') //! //! hello() //! "}; //! let expected = "def hello():\n print('Hello, world!')\n\nhello()\n"; //! assert_eq!(testing, expected); //! } //! ``` //! //! Indoc also works with raw string literals: //! //! ``` //! use indoc::indoc; //! //! fn main() { //! let testing = indoc! {r#" //! def hello(): //! print("Hello, world!") //! //! hello() //! "#}; //! let expected = "def hello():\n print(\"Hello, world!\")\n\nhello()\n"; //! assert_eq!(testing, expected); //! } //! ``` //! //! And byte string literals: //! //! ``` //! use indoc::indoc; //! //! fn main() { //! let testing = indoc! {b" //! def hello(): //! print('Hello, world!') //! //! hello() //! "}; //! let expected = b"def hello():\n print('Hello, world!')\n\nhello()\n"; //! assert_eq!(testing[..], expected[..]); //! } //! ``` //! //!

//! //! # Formatting macros //! //! The indoc crate exports five additional macros to substitute conveniently //! for the standard library's formatting macros: //! //! - `formatdoc!($fmt, ...)` — equivalent to `format!(indoc!($fmt), ...)` //! - `printdoc!($fmt, ...)` — equivalent to `print!(indoc!($fmt), ...)` //! - `eprintdoc!($fmt, ...)` — equivalent to `eprint!(indoc!($fmt), ...)` //! - `writedoc!($dest, $fmt, ...)` — equivalent to `write!($dest, indoc!($fmt), ...)` //! - `concatdoc!(...)` — equivalent to `concat!(...)` with each string literal wrapped in `indoc!` //! //! ``` //! # macro_rules! env { //! # ($var:literal) => { //! # "example" //! # }; //! # } //! # //! use indoc::{concatdoc, printdoc}; //! //! const HELP: &str = concatdoc! {" //! Usage: ", env!("CARGO_BIN_NAME"), " [options] //! //! Options: //! -h, --help //! "}; //! //! fn main() { //! printdoc! {" //! GET {url} //! Accept: {mime} //! ", //! url = "http://localhost:8080", //! mime = "application/json", //! } //! } //! ``` //! //!

//! //! # Explanation //! //! The following rules characterize the behavior of the `indoc!()` macro: //! //! 1. Count the leading spaces of each line, ignoring the first line and any //! lines that are empty or contain spaces only. //! 2. Take the minimum. //! 3. If the first line is empty i.e. the string begins with a newline, remove //! the first line. //! 4. Remove the computed number of spaces from the beginning of each line. #![doc(html_root_url = "https://docs.rs/indoc/2.0.5")] #![allow( clippy::derive_partial_eq_without_eq, clippy::from_iter_instead_of_collect, clippy::module_name_repetitions, clippy::needless_doctest_main, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref, clippy::type_complexity )] mod error; mod expr; mod unindent; use crate::error::{Error, Result}; use crate::unindent::do_unindent; use proc_macro::token_stream::IntoIter as TokenIter; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::iter::{self, Peekable}; use std::str::FromStr; #[derive(Copy, Clone, PartialEq)] enum Macro { Indoc, Format, Print, Eprint, Write, Concat, } /// Unindent and produce `&'static str` or `&'static [u8]`. /// /// Supports normal strings, raw strings, bytestrings, and raw bytestrings. /// /// # Example /// /// ``` /// # use indoc::indoc; /// # /// // The type of `program` is &'static str /// let program = indoc! {" /// def hello(): /// print('Hello, world!') /// /// hello() /// "}; /// print!("{}", program); /// ``` /// /// ```text /// def hello(): /// print('Hello, world!') /// /// hello() /// ``` #[proc_macro] pub fn indoc(input: TokenStream) -> TokenStream { expand(input, Macro::Indoc) } /// Unindent and call `format!`. /// /// Argument syntax is the same as for [`std::format!`]. /// /// # Example /// /// ``` /// # use indoc::formatdoc; /// # /// let request = formatdoc! {" /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// }; /// println!("{}", request); /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn formatdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Format) } /// Unindent and call `print!`. /// /// Argument syntax is the same as for [`std::print!`]. /// /// # Example /// /// ``` /// # use indoc::printdoc; /// # /// printdoc! {" /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// } /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn printdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Print) } /// Unindent and call `eprint!`. /// /// Argument syntax is the same as for [`std::eprint!`]. /// /// # Example /// /// ``` /// # use indoc::eprintdoc; /// # /// eprintdoc! {" /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// } /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn eprintdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Eprint) } /// Unindent and call `write!`. /// /// Argument syntax is the same as for [`std::write!`]. /// /// # Example /// /// ``` /// # use indoc::writedoc; /// # use std::io::Write; /// # /// let _ = writedoc!( /// std::io::stdout(), /// " /// GET {url} /// Accept: {mime} /// ", /// url = "http://localhost:8080", /// mime = "application/json", /// ); /// ``` /// /// ```text /// GET http://localhost:8080 /// Accept: application/json /// ``` #[proc_macro] pub fn writedoc(input: TokenStream) -> TokenStream { expand(input, Macro::Write) } /// Unindent and call `concat!`. /// /// Argument syntax is the same as for [`std::concat!`]. /// /// # Example /// /// ``` /// # use indoc::concatdoc; /// # /// # macro_rules! env { /// # ($var:literal) => { /// # "example" /// # }; /// # } /// # /// const HELP: &str = concatdoc! {" /// Usage: ", env!("CARGO_BIN_NAME"), " [options] /// /// Options: /// -h, --help /// "}; /// /// print!("{}", HELP); /// ``` /// /// ```text /// Usage: example [options] /// /// Options: /// -h, --help /// ``` #[proc_macro] pub fn concatdoc(input: TokenStream) -> TokenStream { expand(input, Macro::Concat) } fn expand(input: TokenStream, mode: Macro) -> TokenStream { match try_expand(input, mode) { Ok(tokens) => tokens, Err(err) => err.to_compile_error(), } } fn try_expand(input: TokenStream, mode: Macro) -> Result { let mut input = input.into_iter().peekable(); let prefix = match mode { Macro::Indoc | Macro::Format | Macro::Print | Macro::Eprint => None, Macro::Write => { let require_comma = true; let mut expr = expr::parse(&mut input, require_comma)?; expr.extend(iter::once(input.next().unwrap())); // add comma Some(expr) } Macro::Concat => return do_concat(input), }; let first = input.next().ok_or_else(|| { Error::new( Span::call_site(), "unexpected end of macro invocation, expected format string", ) })?; let preserve_empty_first_line = false; let unindented_lit = lit_indoc(first, mode, preserve_empty_first_line)?; let macro_name = match mode { Macro::Indoc => { require_empty_or_trailing_comma(&mut input)?; return Ok(TokenStream::from(TokenTree::Literal(unindented_lit))); } Macro::Format => "format", Macro::Print => "print", Macro::Eprint => "eprint", Macro::Write => "write", Macro::Concat => unreachable!(), }; // #macro_name! { #unindented_lit #args } Ok(TokenStream::from_iter(vec![ TokenTree::Ident(Ident::new(macro_name, Span::call_site())), TokenTree::Punct(Punct::new('!', Spacing::Alone)), TokenTree::Group(Group::new( Delimiter::Brace, prefix .unwrap_or_else(TokenStream::new) .into_iter() .chain(iter::once(TokenTree::Literal(unindented_lit))) .chain(input) .collect(), )), ])) } fn do_concat(mut input: Peekable) -> Result { let mut result = TokenStream::new(); let mut first = true; while input.peek().is_some() { let require_comma = false; let mut expr = expr::parse(&mut input, require_comma)?; let mut expr_tokens = expr.clone().into_iter(); if let Some(token) = expr_tokens.next() { if expr_tokens.next().is_none() { let preserve_empty_first_line = !first; if let Ok(literal) = lit_indoc(token, Macro::Concat, preserve_empty_first_line) { result.extend(iter::once(TokenTree::Literal(literal))); expr = TokenStream::new(); } } } result.extend(expr); if let Some(comma) = input.next() { result.extend(iter::once(comma)); } else { break; } first = false; } // concat! { #result } Ok(TokenStream::from_iter(vec![ TokenTree::Ident(Ident::new("concat", Span::call_site())), TokenTree::Punct(Punct::new('!', Spacing::Alone)), TokenTree::Group(Group::new(Delimiter::Brace, result)), ])) } fn lit_indoc(token: TokenTree, mode: Macro, preserve_empty_first_line: bool) -> Result { let span = token.span(); let mut single_token = Some(token); while let Some(TokenTree::Group(group)) = single_token { single_token = if group.delimiter() == Delimiter::None { let mut token_iter = group.stream().into_iter(); token_iter.next().xor(token_iter.next()) } else { None }; } let single_token = single_token.ok_or_else(|| Error::new(span, "argument must be a single string literal"))?; let repr = single_token.to_string(); let is_string = repr.starts_with('"') || repr.starts_with('r'); let is_byte_string = repr.starts_with("b\"") || repr.starts_with("br"); if !is_string && !is_byte_string { return Err(Error::new(span, "argument must be a single string literal")); } if is_byte_string { match mode { Macro::Indoc => {} Macro::Format | Macro::Print | Macro::Eprint | Macro::Write => { return Err(Error::new( span, "byte strings are not supported in formatting macros", )); } Macro::Concat => { return Err(Error::new( span, "byte strings are not supported in concat macro", )); } } } let begin = repr.find('"').unwrap() + 1; let end = repr.rfind('"').unwrap(); let repr = format!( "{open}{content}{close}", open = &repr[..begin], content = do_unindent(&repr[begin..end], preserve_empty_first_line), close = &repr[end..], ); let mut lit = Literal::from_str(&repr).unwrap(); lit.set_span(span); Ok(lit) } fn require_empty_or_trailing_comma(input: &mut Peekable) -> Result<()> { let first = match input.next() { Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => match input.next() { Some(second) => second, None => return Ok(()), }, Some(first) => first, None => return Ok(()), }; let last = input.last(); let begin_span = first.span(); let end_span = last.as_ref().map_or(begin_span, TokenTree::span); let msg = format!( "unexpected {token} in macro invocation; indoc argument must be a single string literal", token = if last.is_some() { "tokens" } else { "token" } ); Err(Error::new2(begin_span, end_span, &msg)) } indoc/src/error.rs0000644000175000017500000000245114661133735015125 0ustar jamespagejamespageuse proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; pub type Result = std::result::Result; pub struct Error { begin: Span, end: Span, msg: String, } impl Error { pub fn new(span: Span, msg: &str) -> Self { Self::new2(span, span, msg) } pub fn new2(begin: Span, end: Span, msg: &str) -> Self { Error { begin, end, msg: msg.to_owned(), } } pub fn to_compile_error(&self) -> TokenStream { // compile_error! { $msg } TokenStream::from_iter(vec![ TokenTree::Ident(Ident::new("compile_error", self.begin)), TokenTree::Punct({ let mut punct = Punct::new('!', Spacing::Alone); punct.set_span(self.begin); punct }), TokenTree::Group({ let mut group = Group::new(Delimiter::Brace, { TokenStream::from_iter(vec![TokenTree::Literal({ let mut string = Literal::string(&self.msg); string.set_span(self.end); string })]) }); group.set_span(self.end); group }), ]) } } indoc/src/unindent.rs0000644000175000017500000000574214661133735015626 0ustar jamespagejamespageuse std::slice::Split; pub fn unindent(s: &str) -> String { let preserve_empty_first_line = false; do_unindent(s, preserve_empty_first_line) } // Compute the maximal number of spaces that can be removed from every line, and // remove them. pub fn unindent_bytes(s: &[u8]) -> Vec { let preserve_empty_first_line = false; do_unindent_bytes(s, preserve_empty_first_line) } pub(crate) fn do_unindent(s: &str, preserve_empty_first_line: bool) -> String { let bytes = s.as_bytes(); let unindented = do_unindent_bytes(bytes, preserve_empty_first_line); String::from_utf8(unindented).unwrap() } fn do_unindent_bytes(s: &[u8], preserve_empty_first_line: bool) -> Vec { // Document may start either on the same line as opening quote or // on the next line let ignore_first_line = !preserve_empty_first_line && (s.starts_with(b"\n") || s.starts_with(b"\r\n")); // Largest number of spaces that can be removed from every // non-whitespace-only line after the first let spaces = s .lines() .skip(1) .filter_map(count_spaces) .min() .unwrap_or(0); let mut result = Vec::with_capacity(s.len()); for (i, line) in s.lines().enumerate() { if i > 1 || (i == 1 && !ignore_first_line) { result.push(b'\n'); } if i == 0 { // Do not un-indent anything on same line as opening quote result.extend_from_slice(line); } else if line.len() > spaces { // Whitespace-only lines may have fewer than the number of spaces // being removed result.extend_from_slice(&line[spaces..]); } } result } pub trait Unindent { type Output; fn unindent(&self) -> Self::Output; } impl Unindent for str { type Output = String; fn unindent(&self) -> Self::Output { unindent(self) } } impl Unindent for String { type Output = String; fn unindent(&self) -> Self::Output { unindent(self) } } impl Unindent for [u8] { type Output = Vec; fn unindent(&self) -> Self::Output { unindent_bytes(self) } } impl<'a, T: ?Sized + Unindent> Unindent for &'a T { type Output = T::Output; fn unindent(&self) -> Self::Output { (**self).unindent() } } // Number of leading spaces in the line, or None if the line is entirely spaces. fn count_spaces(line: &[u8]) -> Option { for (i, ch) in line.iter().enumerate() { if *ch != b' ' && *ch != b'\t' { return Some(i); } } None } // Based on core::str::StrExt. trait BytesExt { fn lines(&self) -> Split bool>; } impl BytesExt for [u8] { fn lines(&self) -> Split bool> { fn is_newline(b: &u8) -> bool { *b == b'\n' } let bytestring = if self.starts_with(b"\r\n") { &self[1..] } else { self }; bytestring.split(is_newline as fn(&u8) -> bool) } } indoc/src/expr.rs0000644000175000017500000000417014661133735014752 0ustar jamespagejamespageuse crate::error::{Error, Result}; use proc_macro::token_stream::IntoIter as TokenIter; use proc_macro::{Spacing, Span, TokenStream, TokenTree}; use std::iter::{self, Peekable}; pub fn parse(input: &mut Peekable, require_comma: bool) -> Result { #[derive(PartialEq)] enum Lookbehind { JointColon, DoubleColon, JointHyphen, Other, } let mut expr = TokenStream::new(); let mut lookbehind = Lookbehind::Other; let mut angle_bracket_depth = 0; loop { if angle_bracket_depth == 0 { match input.peek() { Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => { return Ok(expr); } _ => {} } } match input.next() { Some(TokenTree::Punct(punct)) => { let ch = punct.as_char(); let spacing = punct.spacing(); expr.extend(iter::once(TokenTree::Punct(punct))); lookbehind = match ch { ':' if lookbehind == Lookbehind::JointColon => Lookbehind::DoubleColon, ':' if spacing == Spacing::Joint => Lookbehind::JointColon, '<' if lookbehind == Lookbehind::DoubleColon => { angle_bracket_depth += 1; Lookbehind::Other } '>' if angle_bracket_depth > 0 && lookbehind != Lookbehind::JointHyphen => { angle_bracket_depth -= 1; Lookbehind::Other } '-' if spacing == Spacing::Joint => Lookbehind::JointHyphen, _ => Lookbehind::Other, }; } Some(token) => expr.extend(iter::once(token)), None => { return if require_comma { Err(Error::new( Span::call_site(), "unexpected end of macro input", )) } else { Ok(expr) }; } } } } indoc/.cargo-checksum.json0000664000175000017500000000660414661133735016511 0ustar jamespagejamespage{"files":{"Cargo.toml":"abb758eba00c9acd0c028496de6c9b16d89047f46ef60c102dc1f6de5aa429e0","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"aa314ca47369e660f3ab12d1756e0c341e0de3903c8721d56815c1ebe6e9e4ab","src/error.rs":"82954a85793ea0648ccf640da5565be9599a761532d28b1da5471d0d378fee9c","src/expr.rs":"ea811c5c8f7aa699f8b96f5655e2921225aad9373a2355906702ca978935cb84","src/lib.rs":"a8180487806c28053ddcb4a6feeed81e41e72c33d68aec411af26c1e5e679754","src/unindent.rs":"988a92e473e8f033882e7236bab6d38ece304116f6ac9f6aaf6f25b4bb9f6d27","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_concat.rs":"8065592ad2fc58c51855af3f6213fed426e508963de24e6b48319906fc901ee1","tests/test_formatdoc.rs":"8b341b13758b6d55cdaedad16049369d9bd907fb1fbccb3a236e6024401b47fd","tests/test_indoc.rs":"bf0ff4dd0de04604d308c88ea31321e5cd666431a8b09628f0bcd820b9600832","tests/test_unindent.rs":"57ce28df0e6055b661097cb4dca3efa949e15535aa28d1bc8da6932d4cc1ed15","tests/test_writedoc.rs":"e313e4f49faec67b4b2cb3a69b468bd95e7d941f3686ee2193a8d6626cf48c49","tests/ui/capture-var-nested.rs":"01597020d34975817a627c213e1e35e58bd1809f3174a26d9c2795efba677297","tests/ui/capture-var-nested.stderr":"99d385c115680bb6d923e9dc30c9e2fcaa346fa0679931e1df20b998a5fb6682","tests/ui/no-arguments.rs":"d544b1a510efbef42a1fb7b7b40009da2d9be815a55ef76dd2362c8c7754734e","tests/ui/no-arguments.stderr":"50adb9ca3a1b1661ef7dbd9e9a74804353d18c294d2a28498f50ef91676f13d6","tests/ui/non-lit.rs":"3e7d7b4b5e141b5eb4c76d64b47f7a5f60325091a8e4d8cc2d97b7d590dd2857","tests/ui/non-lit.stderr":"f7ea54b55db14f756254e013150a3a45d3045cef4419e8a512cfd70ec29b858e","tests/ui/non-string.rs":"0b56f281761edaee1c7341c9ba231371c86752456179d84777c62f03f52ce173","tests/ui/non-string.stderr":"6a65eb94f57ef6733da6a1d855194708e124dd8dac424d3eebde6e79b966f9ad","tests/ui/printdoc-binary.rs":"0122fd6b783cb9c25c8aede8f0cc69c1c3ffcef656bf7d9ee476e8e0ff49e59f","tests/ui/printdoc-binary.stderr":"4b745df236fbca6ac1f314e6b1c26c069fc4d108edad84a8a69b7dcc2e6ca4ea","tests/ui/printdoc-extra-arg.rs":"fa31182019534b5b258f8335799c8ba53a7715c1d9e6fc9d25fbc0952d28bd7a","tests/ui/printdoc-extra-arg.stderr":"aebd5360f0a1b4e4faba9defc91d186a992248c00808e198ad31ae2110ab86ed","tests/ui/printdoc-no-arg.rs":"087d8e5295f7809abf596a076743401f6ba019fd5b3b2e290bfd6551b4bdcdf3","tests/ui/printdoc-no-arg.stderr":"a5e5d79415ef3fc357403c38b486acbb6ba3e5e565c358265694902afd476b9d","tests/ui/printdoc-no-display.rs":"afeafb1f41a6f7aa68bd5da14c2057e54f2756c1726098ac8be9ab0517a85879","tests/ui/printdoc-no-display.stderr":"0cd64b7e07571dd6c77dde0c2202a2a1b611222db0f1a7607b6d7c3988d5daf0","tests/ui/printdoc-no-named-arg.rs":"beeb8447ab95a0e0a21aec78872be79ad1b2a8fe1be4a276fe191f47f3b8082b","tests/ui/printdoc-no-named-arg.stderr":"c5e2f35a4c960e0ae86c2c3481645da90bf86b8f8ae8b6f8c8954d8c9917a44d","tests/ui/three-arguments.rs":"47b74a9918de87bad00cdd94dc7091a499a586edcfbc05035ef79ce0d52dbe27","tests/ui/three-arguments.stderr":"f3649c03bf13c18b863f0ee0986154c4530601138c574e30cf05f7916eb85c39","tests/ui/two-arguments.rs":"1607e7c149cc0ed5e3fb5984ac1d39d8dff0bd8325911518b02d05daa95b06b0","tests/ui/two-arguments.stderr":"a446346d0cb74e791174b22eed874130387d21038cfdb809b80eb068b4f24b92"},"package":"b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"}libc/0000775000175000017500000000000014661133735012454 5ustar jamespagejamespagelibc/build.rs0000644000175000017500000002261314661133735014123 0ustar jamespagejamespageuse std::env; use std::process::Command; use std::str; use std::string::String; // List of cfgs this build script is allowed to set. The list is needed to support check-cfg, as we // need to know all the possible cfgs that this script will set. If you need to set another cfg // make sure to add it to this list as well. const ALLOWED_CFGS: &'static [&'static str] = &[ "emscripten_new_stat_abi", "espidf_time64", "freebsd10", "freebsd11", "freebsd12", "freebsd13", "freebsd14", "freebsd15", "libc_align", "libc_cfg_target_vendor", "libc_const_extern_fn", "libc_const_extern_fn_unstable", "libc_const_size_of", "libc_core_cvoid", "libc_deny_warnings", "libc_int128", "libc_long_array", "libc_non_exhaustive", "libc_packedN", "libc_priv_mod_use", "libc_ptr_addr_of", "libc_thread_local", "libc_underscore_const_names", "libc_union", ]; // Extra values to allow for check-cfg. const CHECK_CFG_EXTRA: &'static [(&'static str, &'static [&'static str])] = &[ ("target_os", &["switch", "aix", "ohos", "hurd", "visionos"]), ("target_env", &["illumos", "wasi", "aix", "ohos"]), ( "target_arch", &["loongarch64", "mips32r6", "mips64r6", "csky"], ), ]; fn main() { // Avoid unnecessary re-building. println!("cargo:rerun-if-changed=build.rs"); let (rustc_minor_ver, is_nightly) = rustc_minor_nightly(); let rustc_dep_of_std = env::var("CARGO_FEATURE_RUSTC_DEP_OF_STD").is_ok(); let align_cargo_feature = env::var("CARGO_FEATURE_ALIGN").is_ok(); let const_extern_fn_cargo_feature = env::var("CARGO_FEATURE_CONST_EXTERN_FN").is_ok(); let libc_ci = env::var("LIBC_CI").is_ok(); let libc_check_cfg = env::var("LIBC_CHECK_CFG").is_ok() || rustc_minor_ver >= 80; if env::var("CARGO_FEATURE_USE_STD").is_ok() { println!( "cargo:warning=\"libc's use_std cargo feature is deprecated since libc 0.2.55; \ please consider using the `std` cargo feature instead\"" ); } // The ABI of libc used by std is backward compatible with FreeBSD 12. // The ABI of libc from crates.io is backward compatible with FreeBSD 11. // // On CI, we detect the actual FreeBSD version and match its ABI exactly, // running tests to ensure that the ABI is correct. match which_freebsd() { Some(10) if libc_ci => set_cfg("freebsd10"), Some(11) if libc_ci => set_cfg("freebsd11"), Some(12) if libc_ci || rustc_dep_of_std => set_cfg("freebsd12"), Some(13) if libc_ci => set_cfg("freebsd13"), Some(14) if libc_ci => set_cfg("freebsd14"), Some(15) if libc_ci => set_cfg("freebsd15"), Some(_) | None => set_cfg("freebsd11"), } match emcc_version_code() { Some(v) if (v >= 30142) => set_cfg("emscripten_new_stat_abi"), // Non-Emscripten or version < 3.1.42. Some(_) | None => (), } // On CI: deny all warnings if libc_ci { set_cfg("libc_deny_warnings"); } // Rust >= 1.15 supports private module use: if rustc_minor_ver >= 15 || rustc_dep_of_std { set_cfg("libc_priv_mod_use"); } // Rust >= 1.19 supports unions: if rustc_minor_ver >= 19 || rustc_dep_of_std { set_cfg("libc_union"); } // Rust >= 1.24 supports const mem::size_of: if rustc_minor_ver >= 24 || rustc_dep_of_std { set_cfg("libc_const_size_of"); } // Rust >= 1.25 supports repr(align): if rustc_minor_ver >= 25 || rustc_dep_of_std || align_cargo_feature { set_cfg("libc_align"); } // Rust >= 1.26 supports i128 and u128: if rustc_minor_ver >= 26 || rustc_dep_of_std { set_cfg("libc_int128"); } // Rust >= 1.30 supports `core::ffi::c_void`, so libc can just re-export it. // Otherwise, it defines an incompatible type to retaining // backwards-compatibility. if rustc_minor_ver >= 30 || rustc_dep_of_std { set_cfg("libc_core_cvoid"); } // Rust >= 1.33 supports repr(packed(N)) and cfg(target_vendor). if rustc_minor_ver >= 33 || rustc_dep_of_std { set_cfg("libc_packedN"); set_cfg("libc_cfg_target_vendor"); } // Rust >= 1.40 supports #[non_exhaustive]. if rustc_minor_ver >= 40 || rustc_dep_of_std { set_cfg("libc_non_exhaustive"); } // Rust >= 1.47 supports long array: if rustc_minor_ver >= 47 || rustc_dep_of_std { set_cfg("libc_long_array"); } if rustc_minor_ver >= 51 || rustc_dep_of_std { set_cfg("libc_ptr_addr_of"); } // Rust >= 1.37.0 allows underscores as anonymous constant names. if rustc_minor_ver >= 37 || rustc_dep_of_std { set_cfg("libc_underscore_const_names"); } // #[thread_local] is currently unstable if rustc_dep_of_std { set_cfg("libc_thread_local"); } // Rust >= 1.62.0 allows to use `const_extern_fn` for "Rust" and "C". if rustc_minor_ver >= 62 { set_cfg("libc_const_extern_fn"); } else { // Rust < 1.62.0 requires a crate feature and feature gate. if const_extern_fn_cargo_feature { if !is_nightly || rustc_minor_ver < 40 { panic!("const-extern-fn requires a nightly compiler >= 1.40"); } set_cfg("libc_const_extern_fn_unstable"); set_cfg("libc_const_extern_fn"); } } // check-cfg is a nightly cargo/rustc feature to warn when unknown cfgs are used across the // codebase. libc can configure it if the appropriate environment variable is passed. Since // rust-lang/rust enforces it, this is useful when using a custom libc fork there. // // https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg if libc_check_cfg { for cfg in ALLOWED_CFGS { if rustc_minor_ver >= 75 { println!("cargo:rustc-check-cfg=cfg({})", cfg); } else { println!("cargo:rustc-check-cfg=values({})", cfg); } } for &(name, values) in CHECK_CFG_EXTRA { let values = values.join("\",\""); if rustc_minor_ver >= 75 { println!("cargo:rustc-check-cfg=cfg({},values(\"{}\"))", name, values); } else { println!("cargo:rustc-check-cfg=values({},\"{}\")", name, values); } } } } fn rustc_minor_nightly() -> (u32, bool) { macro_rules! otry { ($e:expr) => { match $e { Some(e) => e, None => panic!("Failed to get rustc version"), } }; } let rustc = otry!(env::var_os("RUSTC")); let output = Command::new(rustc) .arg("--version") .output() .ok() .expect("Failed to get rustc version"); if !output.status.success() { panic!( "failed to run rustc: {}", String::from_utf8_lossy(output.stderr.as_slice()) ); } let version = otry!(str::from_utf8(&output.stdout).ok()); let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { panic!("Failed to get rustc version"); } let minor = pieces.next(); // If `rustc` was built from a tarball, its version string // will have neither a git hash nor a commit date // (e.g. "rustc 1.39.0"). Treat this case as non-nightly, // since a nightly build should either come from CI // or a git checkout let nightly_raw = otry!(pieces.next()).split('-').nth(1); let nightly = nightly_raw .map(|raw| raw.starts_with("dev") || raw.starts_with("nightly")) .unwrap_or(false); let minor = otry!(otry!(minor).parse().ok()); (minor, nightly) } fn which_freebsd() -> Option { let output = std::process::Command::new("freebsd-version").output().ok(); if output.is_none() { return None; } let output = output.unwrap(); if !output.status.success() { return None; } let stdout = String::from_utf8(output.stdout).ok(); if stdout.is_none() { return None; } let stdout = stdout.unwrap(); match &stdout { s if s.starts_with("10") => Some(10), s if s.starts_with("11") => Some(11), s if s.starts_with("12") => Some(12), s if s.starts_with("13") => Some(13), s if s.starts_with("14") => Some(14), s if s.starts_with("15") => Some(15), _ => None, } } fn emcc_version_code() -> Option { let output = std::process::Command::new("emcc") .arg("-dumpversion") .output() .ok(); if output.is_none() { return None; } let output = output.unwrap(); if !output.status.success() { return None; } let stdout = String::from_utf8(output.stdout).ok(); if stdout.is_none() { return None; } let version = stdout.unwrap(); // Some Emscripten versions come with `-git` attached, so split the // version string also on the `-` char. let mut pieces = version.trim().split(|c| c == '.' || c == '-'); let major = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0); let minor = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0); let patch = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0); Some(major * 10000 + minor * 100 + patch) } fn set_cfg(cfg: &str) { if !ALLOWED_CFGS.contains(&cfg) { panic!("trying to set cfg {}, but it is not in ALLOWED_CFGS", cfg); } println!("cargo:rustc-cfg={}", cfg); } libc/README.md0000644000175000017500000001046314661133735013735 0ustar jamespagejamespage# libc - Raw FFI bindings to platforms' system libraries [![GHA Status]][GitHub Actions] [![Cirrus CI Status]][Cirrus CI] [![Latest Version]][crates.io] [![Documentation]][docs.rs] ![License] `libc` provides all of the definitions necessary to easily interoperate with C code (or "C-like" code) on each of the platforms that Rust supports. This includes type definitions (e.g. `c_int`), constants (e.g. `EINVAL`) as well as function headers (e.g. `malloc`). This crate exports all underlying platform types, functions, and constants under the crate root, so all items are accessible as `libc::foo`. The types and values of all the exported APIs match the platform that libc is compiled for. More detailed information about the design of this library can be found in its [associated RFC][rfc]. [rfc]: https://github.com/rust-lang/rfcs/blob/HEAD/text/1291-promote-libc.md ## v0.3 Roadmap The main branch is now for v0.3 which has some breaking changes. For v0.2, please submit PRs to the `libc-0.2` branch instead. We will stop making new v0.2 releases once we release v0.3 on crates.io. See the [tracking issue](https://github.com/rust-lang/libc/issues/3248) for details. ## Usage Add the following to your `Cargo.toml`: ```toml [dependencies] libc = "0.2" ``` ## Features * `std`: by default `libc` links to the standard library. Disable this feature to remove this dependency and be able to use `libc` in `#![no_std]` crates. * `extra_traits`: all `struct`s implemented in `libc` are `Copy` and `Clone`. This feature derives `Debug`, `Eq`, `Hash`, and `PartialEq`. * `const-extern-fn`: Changes some `extern fn`s into `const extern fn`s. If you use Rust >= 1.62, this feature is implicitly enabled. Otherwise it requires a nightly rustc. * **deprecated**: `use_std` is deprecated, and is equivalent to `std`. ## Rust version support The minimum supported Rust toolchain version is currently **Rust 1.13.0**. (libc does not currently have any policy regarding changes to the minimum supported Rust version; such policy is a work in progress.) APIs requiring newer Rust features are only available on newer Rust toolchains: | Feature | Version | |----------------------|---------| | `union` | 1.19.0 | | `const mem::size_of` | 1.24.0 | | `repr(align)` | 1.25.0 | | `extra_traits` | 1.25.0 | | `core::ffi::c_void` | 1.30.0 | | `repr(packed(N))` | 1.33.0 | | `cfg(target_vendor)` | 1.33.0 | | `const-extern-fn` | 1.62.0 | ## Platform support You can see the platform(target)-specific docs on [docs.rs], select a platform you want to see. See [`ci/build.sh`](https://github.com/rust-lang/libc/blob/HEAD/ci/build.sh) for the platforms on which `libc` is guaranteed to build for each Rust toolchain. The test-matrix at [GitHub Actions] and [Cirrus CI] show the platforms in which `libc` tests are run.

## License This project is licensed under either of * [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) ([LICENSE-APACHE](https://github.com/rust-lang/libc/blob/HEAD/LICENSE-APACHE)) * [MIT License](https://opensource.org/licenses/MIT) ([LICENSE-MIT](https://github.com/rust-lang/libc/blob/HEAD/LICENSE-MIT)) at your option. ## Contributing We welcome all people who want to contribute. Please see the [contributing instructions] for more information. [contributing instructions]: https://github.com/rust-lang/libc/blob/HEAD/CONTRIBUTING.md Contributions in any form (issues, pull requests, etc.) to this project must adhere to Rust's [Code of Conduct]. [Code of Conduct]: https://www.rust-lang.org/policies/code-of-conduct Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in `libc` by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [GitHub Actions]: https://github.com/rust-lang/libc/actions [GHA Status]: https://github.com/rust-lang/libc/workflows/CI/badge.svg [Cirrus CI]: https://cirrus-ci.com/github/rust-lang/libc [Cirrus CI Status]: https://api.cirrus-ci.com/github/rust-lang/libc.svg [crates.io]: https://crates.io/crates/libc [Latest Version]: https://img.shields.io/crates/v/libc.svg [Documentation]: https://docs.rs/libc/badge.svg [docs.rs]: https://docs.rs/libc [License]: https://img.shields.io/crates/l/libc.svg libc/rustfmt.toml0000644000175000017500000000003614661133735015052 0ustar jamespagejamespageerror_on_line_overflow = true libc/LICENSE-APACHE0000644000175000017500000002277314661133735014411 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS libc/Cargo.toml0000644000175000017500000001157414661133735014412 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "libc" version = "0.2.155" authors = ["The Rust Project Developers"] build = "build.rs" exclude = [ "/ci/*", "/.github/*", "/.cirrus.yml", "/triagebot.toml", ] autobins = false autoexamples = false autotests = false autobenches = false description = """ Raw FFI bindings to platform libraries like libc. """ homepage = "https://github.com/rust-lang/libc" documentation = "https://docs.rs/libc/" readme = "README.md" keywords = [ "libc", "ffi", "bindings", "operating", "system", ] categories = [ "external-ffi-bindings", "no-std", "os", ] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/libc" [package.metadata.docs.rs] cargo-args = ["-Zbuild-std=core"] default-target = "x86_64-unknown-linux-gnu" features = [ "const-extern-fn", "extra_traits", ] targets = [ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-linux-android", "aarch64-pc-windows-msvc", "aarch64-unknown-freebsd", "aarch64-unknown-fuchsia", "aarch64-unknown-hermit", "aarch64-unknown-linux-gnu", "aarch64-unknown-linux-musl", "aarch64-unknown-netbsd", "aarch64-unknown-openbsd", "aarch64-wrs-vxworks", "arm-linux-androideabi", "arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabihf", "arm-unknown-linux-musleabi", "arm-unknown-linux-musleabihf", "armebv7r-none-eabi", "armebv7r-none-eabihf", "armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-musleabi", "armv7-linux-androideabi", "armv7-unknown-linux-gnueabihf", "armv7-unknown-linux-musleabihf", "armv7-wrs-vxworks-eabihf", "armv7r-none-eabi", "armv7r-none-eabihf", "hexagon-unknown-linux-musl", "i586-pc-windows-msvc", "i586-unknown-linux-gnu", "i586-unknown-linux-musl", "i686-linux-android", "i686-pc-windows-gnu", "i686-pc-windows-msvc", "i686-pc-windows-msvc", "i686-unknown-freebsd", "i686-unknown-haiku", "i686-unknown-linux-gnu", "i686-unknown-linux-musl", "i686-unknown-netbsd", "i686-unknown-openbsd", "i686-wrs-vxworks", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips64-unknown-linux-gnuabi64", "mips64-unknown-linux-muslabi64", "mips64el-unknown-linux-gnuabi64", "mips64el-unknown-linux-muslabi64", "mipsel-sony-psp", "mipsel-unknown-linux-gnu", "mipsel-unknown-linux-musl", "nvptx64-nvidia-cuda", "powerpc-unknown-linux-gnu", "powerpc-unknown-linux-gnuspe", "powerpc-unknown-netbsd", "powerpc-wrs-vxworks", "powerpc-wrs-vxworks-spe", "powerpc64-unknown-freebsd", "powerpc64-unknown-linux-gnu", "powerpc64-wrs-vxworks", "powerpc64le-unknown-linux-gnu", "riscv32gc-unknown-linux-gnu", "riscv32i-unknown-none-elf", "riscv32imac-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv64gc-unknown-freebsd", "riscv64gc-unknown-hermit", "riscv64gc-unknown-linux-gnu", "riscv64gc-unknown-linux-musl", "riscv64gc-unknown-none-elf", "riscv64imac-unknown-none-elf", "s390x-unknown-linux-gnu", "s390x-unknown-linux-musl", "sparc-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparc64-unknown-netbsd", "sparcv9-sun-solaris", "thumbv6m-none-eabi", "thumbv7em-none-eabi", "thumbv7em-none-eabihf", "thumbv7m-none-eabi", "thumbv7neon-linux-androideabi", "thumbv7neon-unknown-linux-gnueabihf", "wasm32-unknown-emscripten", "wasm32-unknown-unknown", "wasm32-wasi", "x86_64-apple-darwin", "x86_64-apple-ios", "x86_64-fortanix-unknown-sgx", "x86_64-linux-android", "x86_64-pc-solaris", "x86_64-pc-windows-gnu", "x86_64-pc-windows-msvc", "x86_64-unknown-dragonfly", "x86_64-unknown-freebsd", "x86_64-unknown-fuchsia", "x86_64-unknown-haiku", "x86_64-unknown-hermit", "x86_64-unknown-illumos", "x86_64-unknown-l4re-uclibc", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", "x86_64-unknown-openbsd", "x86_64-unknown-redox", "x86_64-wrs-vxworks", ] [lib] name = "libc" path = "src/lib.rs" [[test]] name = "const_fn" path = "tests/const_fn.rs" [dependencies.rustc-std-workspace-core] version = "1.0.0" optional = true [features] align = [] const-extern-fn = [] default = ["std"] extra_traits = [] rustc-dep-of-std = [ "align", "rustc-std-workspace-core", ] std = [] use_std = ["std"] libc/tests/0000775000175000017500000000000014661133735013616 5ustar jamespagejamespagelibc/tests/const_fn.rs0000644000175000017500000000033414661133735015773 0ustar jamespagejamespage#![cfg(libc_const_extern_fn)] // If this does not hold, the file is empty #[cfg(target_os = "linux")] const _FOO: libc::c_uint = unsafe { libc::CMSG_SPACE(1) }; //^ if CMSG_SPACE is not const, this will fail to compile libc/LICENSE-MIT0000644000175000017500000000206414661133735014110 0ustar jamespagejamespageCopyright (c) 2014-2020 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libc/src/0000775000175000017500000000000014661133735013243 5ustar jamespagejamespagelibc/src/xous.rs0000644000175000017500000000236014661133735014606 0ustar jamespagejamespage//! Xous C type definitions pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type off_t = i64; pub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = u32; pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } libc/src/sgx.rs0000644000175000017500000000230114661133735014404 0ustar jamespagejamespage//! SGX C types definition pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } libc/src/switch.rs0000644000175000017500000000236214661133735015113 0ustar jamespagejamespage//! Switch C type definitions pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type off_t = i64; pub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = u32; pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } libc/src/psp.rs0000644000175000017500000036756414661133735014436 0ustar jamespagejamespage//! PSP C type definitions //! //! These type declarations are not enough, as they must be ultimately resolved //! by the linker. Crates that use these definitions must, somewhere in the //! crate graph, include a stub provider crate such as the `psp` crate. pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } pub type SceKernelVTimerHandler = unsafe extern "C" fn( uid: SceUid, arg1: *mut SceKernelSysClock, arg2: *mut SceKernelSysClock, arg3: *mut c_void, ) -> u32; pub type SceKernelVTimerHandlerWide = unsafe extern "C" fn(uid: SceUid, arg1: i64, arg2: i64, arg3: *mut c_void) -> u32; pub type SceKernelThreadEventHandler = unsafe extern "C" fn(mask: i32, thid: SceUid, common: *mut c_void) -> i32; pub type SceKernelAlarmHandler = unsafe extern "C" fn(common: *mut c_void) -> u32; pub type SceKernelCallbackFunction = unsafe extern "C" fn(arg1: i32, arg2: i32, arg: *mut c_void) -> i32; pub type SceKernelThreadEntry = unsafe extern "C" fn(args: usize, argp: *mut c_void) -> i32; pub type PowerCallback = extern "C" fn(unknown: i32, power_info: i32); pub type IoPermissions = i32; pub type UmdCallback = fn(unknown: i32, event: i32) -> i32; pub type SceMpegRingbufferCb = ::Option i32>; pub type GuCallback = ::Option; pub type GuSwapBuffersCallback = ::Option; pub type SceNetAdhocctlHandler = ::Option; pub type AdhocMatchingCallback = ::Option< unsafe extern "C" fn( matching_id: i32, event: i32, mac: *mut u8, opt_len: i32, opt_data: *mut c_void, ), >; pub type SceNetApctlHandler = ::Option< unsafe extern "C" fn(oldState: i32, newState: i32, event: i32, error: i32, pArg: *mut c_void), >; pub type HttpMallocFunction = ::Option *mut c_void>; pub type HttpReallocFunction = ::Option *mut c_void>; pub type HttpFreeFunction = ::Option; pub type HttpPasswordCB = ::Option< unsafe extern "C" fn( request: i32, auth_type: HttpAuthType, realm: *const u8, username: *mut u8, password: *mut u8, need_entity: i32, entity_body: *mut *mut u8, entity_size: *mut usize, save: *mut i32, ) -> i32, >; pub type socklen_t = u32; e! { #[repr(u32)] pub enum AudioFormat { Stereo = 0, Mono = 0x10, } #[repr(u32)] pub enum DisplayMode { Lcd = 0, } #[repr(u32)] pub enum DisplayPixelFormat { Psm5650 = 0, Psm5551 = 1, Psm4444 = 2, Psm8888 = 3, } #[repr(u32)] pub enum DisplaySetBufSync { Immediate = 0, NextFrame = 1, } #[repr(i32)] pub enum AudioOutputFrequency { Khz48 = 48000, Khz44_1 = 44100, Khz32 = 32000, Khz24 = 24000, Khz22_05 = 22050, Khz16 = 16000, Khz12 = 12000, Khz11_025 = 11025, Khz8 = 8000, } #[repr(i32)] pub enum AudioInputFrequency { Khz44_1 = 44100, Khz22_05 = 22050, Khz11_025 = 11025, } #[repr(u32)] pub enum CtrlMode { Digital = 0, Analog, } #[repr(i32)] pub enum GeMatrixType { Bone0 = 0, Bone1, Bone2, Bone3, Bone4, Bone5, Bone6, Bone7, World, View, Projection, TexGen, } #[repr(i32)] pub enum GeListState { Done = 0, Queued, DrawingDone, StallReached, CancelDone, } #[repr(u8)] pub enum GeCommand { Nop = 0, Vaddr = 0x1, Iaddr = 0x2, Prim = 0x4, Bezier = 0x5, Spline = 0x6, BoundingBox = 0x7, Jump = 0x8, BJump = 0x9, Call = 0xa, Ret = 0xb, End = 0xc, Signal = 0xe, Finish = 0xf, Base = 0x10, VertexType = 0x12, OffsetAddr = 0x13, Origin = 0x14, Region1 = 0x15, Region2 = 0x16, LightingEnable = 0x17, LightEnable0 = 0x18, LightEnable1 = 0x19, LightEnable2 = 0x1a, LightEnable3 = 0x1b, DepthClampEnable = 0x1c, CullFaceEnable = 0x1d, TextureMapEnable = 0x1e, FogEnable = 0x1f, DitherEnable = 0x20, AlphaBlendEnable = 0x21, AlphaTestEnable = 0x22, ZTestEnable = 0x23, StencilTestEnable = 0x24, AntiAliasEnable = 0x25, PatchCullEnable = 0x26, ColorTestEnable = 0x27, LogicOpEnable = 0x28, BoneMatrixNumber = 0x2a, BoneMatrixData = 0x2b, MorphWeight0 = 0x2c, MorphWeight1 = 0x2d, MorphWeight2 = 0x2e, MorphWeight3 = 0x2f, MorphWeight4 = 0x30, MorphWeight5 = 0x31, MorphWeight6 = 0x32, MorphWeight7 = 0x33, PatchDivision = 0x36, PatchPrimitive = 0x37, PatchFacing = 0x38, WorldMatrixNumber = 0x3a, WorldMatrixData = 0x3b, ViewMatrixNumber = 0x3c, ViewMatrixData = 0x3d, ProjMatrixNumber = 0x3e, ProjMatrixData = 0x3f, TGenMatrixNumber = 0x40, TGenMatrixData = 0x41, ViewportXScale = 0x42, ViewportYScale = 0x43, ViewportZScale = 0x44, ViewportXCenter = 0x45, ViewportYCenter = 0x46, ViewportZCenter = 0x47, TexScaleU = 0x48, TexScaleV = 0x49, TexOffsetU = 0x4a, TexOffsetV = 0x4b, OffsetX = 0x4c, OffsetY = 0x4d, ShadeMode = 0x50, ReverseNormal = 0x51, MaterialUpdate = 0x53, MaterialEmissive = 0x54, MaterialAmbient = 0x55, MaterialDiffuse = 0x56, MaterialSpecular = 0x57, MaterialAlpha = 0x58, MaterialSpecularCoef = 0x5b, AmbientColor = 0x5c, AmbientAlpha = 0x5d, LightMode = 0x5e, LightType0 = 0x5f, LightType1 = 0x60, LightType2 = 0x61, LightType3 = 0x62, Light0X = 0x63, Light0Y, Light0Z, Light1X, Light1Y, Light1Z, Light2X, Light2Y, Light2Z, Light3X, Light3Y, Light3Z, Light0DirectionX = 0x6f, Light0DirectionY, Light0DirectionZ, Light1DirectionX, Light1DirectionY, Light1DirectionZ, Light2DirectionX, Light2DirectionY, Light2DirectionZ, Light3DirectionX, Light3DirectionY, Light3DirectionZ, Light0ConstantAtten = 0x7b, Light0LinearAtten, Light0QuadtraticAtten, Light1ConstantAtten, Light1LinearAtten, Light1QuadtraticAtten, Light2ConstantAtten, Light2LinearAtten, Light2QuadtraticAtten, Light3ConstantAtten, Light3LinearAtten, Light3QuadtraticAtten, Light0ExponentAtten = 0x87, Light1ExponentAtten, Light2ExponentAtten, Light3ExponentAtten, Light0CutoffAtten = 0x8b, Light1CutoffAtten, Light2CutoffAtten, Light3CutoffAtten, Light0Ambient = 0x8f, Light0Diffuse, Light0Specular, Light1Ambient, Light1Diffuse, Light1Specular, Light2Ambient, Light2Diffuse, Light2Specular, Light3Ambient, Light3Diffuse, Light3Specular, Cull = 0x9b, FrameBufPtr = 0x9c, FrameBufWidth = 0x9d, ZBufPtr = 0x9e, ZBufWidth = 0x9f, TexAddr0 = 0xa0, TexAddr1, TexAddr2, TexAddr3, TexAddr4, TexAddr5, TexAddr6, TexAddr7, TexBufWidth0 = 0xa8, TexBufWidth1, TexBufWidth2, TexBufWidth3, TexBufWidth4, TexBufWidth5, TexBufWidth6, TexBufWidth7, ClutAddr = 0xb0, ClutAddrUpper = 0xb1, TransferSrc, TransferSrcW, TransferDst, TransferDstW, TexSize0 = 0xb8, TexSize1, TexSize2, TexSize3, TexSize4, TexSize5, TexSize6, TexSize7, TexMapMode = 0xc0, TexShadeLs = 0xc1, TexMode = 0xc2, TexFormat = 0xc3, LoadClut = 0xc4, ClutFormat = 0xc5, TexFilter = 0xc6, TexWrap = 0xc7, TexLevel = 0xc8, TexFunc = 0xc9, TexEnvColor = 0xca, TexFlush = 0xcb, TexSync = 0xcc, Fog1 = 0xcd, Fog2 = 0xce, FogColor = 0xcf, TexLodSlope = 0xd0, FramebufPixFormat = 0xd2, ClearMode = 0xd3, Scissor1 = 0xd4, Scissor2 = 0xd5, MinZ = 0xd6, MaxZ = 0xd7, ColorTest = 0xd8, ColorRef = 0xd9, ColorTestmask = 0xda, AlphaTest = 0xdb, StencilTest = 0xdc, StencilOp = 0xdd, ZTest = 0xde, BlendMode = 0xdf, BlendFixedA = 0xe0, BlendFixedB = 0xe1, Dith0 = 0xe2, Dith1, Dith2, Dith3, LogicOp = 0xe6, ZWriteDisable = 0xe7, MaskRgb = 0xe8, MaskAlpha = 0xe9, TransferStart = 0xea, TransferSrcPos = 0xeb, TransferDstPos = 0xec, TransferSize = 0xee, Vscx = 0xf0, Vscy = 0xf1, Vscz = 0xf2, Vtcs = 0xf3, Vtct = 0xf4, Vtcq = 0xf5, Vcv = 0xf6, Vap = 0xf7, Vfc = 0xf8, Vscv = 0xf9, Unknown03 = 0x03, Unknown0D = 0x0d, Unknown11 = 0x11, Unknown29 = 0x29, Unknown34 = 0x34, Unknown35 = 0x35, Unknown39 = 0x39, Unknown4E = 0x4e, Unknown4F = 0x4f, Unknown52 = 0x52, Unknown59 = 0x59, Unknown5A = 0x5a, UnknownB6 = 0xb6, UnknownB7 = 0xb7, UnknownD1 = 0xd1, UnknownED = 0xed, UnknownEF = 0xef, UnknownFA = 0xfa, UnknownFB = 0xfb, UnknownFC = 0xfc, UnknownFD = 0xfd, UnknownFE = 0xfe, NopFF = 0xff, } #[repr(i32)] pub enum SceSysMemPartitionId { SceKernelUnknownPartition = 0, SceKernelPrimaryKernelPartition = 1, SceKernelPrimaryUserPartition = 2, SceKernelOtherKernelPartition1 = 3, SceKernelOtherKernelPartition2 = 4, SceKernelVshellPARTITION = 5, SceKernelScUserPartition = 6, SceKernelMeUserPartition = 7, SceKernelExtendedScKernelPartition = 8, SceKernelExtendedSc2KernelPartition = 9, SceKernelExtendedMeKernelPartition = 10, SceKernelVshellKernelPartition = 11, SceKernelExtendedKernelPartition = 12, } #[repr(i32)] pub enum SceSysMemBlockTypes { Low = 0, High, Addr, } #[repr(u32)] pub enum Interrupt { Gpio = 4, Ata = 5, Umd = 6, Mscm0 = 7, Wlan = 8, Audio = 10, I2c = 12, Sircs = 14, Systimer0 = 15, Systimer1 = 16, Systimer2 = 17, Systimer3 = 18, Thread0 = 19, Nand = 20, Dmacplus = 21, Dma0 = 22, Dma1 = 23, Memlmd = 24, Ge = 25, Vblank = 30, Mecodec = 31, Hpremote = 36, Mscm1 = 60, Mscm2 = 61, Thread1 = 65, Interrupt = 66, } #[repr(u32)] pub enum SubInterrupt { Gpio = Interrupt::Gpio as u32, Ata = Interrupt::Ata as u32, Umd = Interrupt::Umd as u32, Dmacplus = Interrupt::Dmacplus as u32, Ge = Interrupt::Ge as u32, Display = Interrupt::Vblank as u32, } #[repr(u32)] pub enum SceKernelIdListType { Thread = 1, Semaphore = 2, EventFlag = 3, Mbox = 4, Vpl = 5, Fpl = 6, Mpipe = 7, Callback = 8, ThreadEventHandler = 9, Alarm = 10, VTimer = 11, SleepThread = 64, DelayThread = 65, SuspendThread = 66, DormantThread = 67, } #[repr(i32)] pub enum UsbCamResolution { Px160_120 = 0, Px176_144 = 1, Px320_240 = 2, Px352_288 = 3, Px640_480 = 4, Px1024_768 = 5, Px1280_960 = 6, Px480_272 = 7, Px360_272 = 8, } #[repr(i32)] pub enum UsbCamResolutionEx { Px160_120 = 0, Px176_144 = 1, Px320_240 = 2, Px352_288 = 3, Px360_272 = 4, Px480_272 = 5, Px640_480 = 6, Px1024_768 = 7, Px1280_960 = 8, } #[repr(i32)] pub enum UsbCamDelay { NoDelay = 0, Delay10Sec = 1, Delay20Sec = 2, Delay30Sec = 3, } #[repr(i32)] pub enum UsbCamFrameRate { Fps3_75 = 0, Fps5 = 1, Fps7_5 = 2, Fps10 = 3, Fps15 = 4, Fps20 = 5, Fps30 = 6, Fps60 = 7, } #[repr(i32)] pub enum UsbCamWb { Auto = 0, Daylight = 1, Fluorescent = 2, Incadescent = 3, } #[repr(i32)] pub enum UsbCamEffectMode { Normal = 0, Negative = 1, Blackwhite = 2, Sepia = 3, Blue = 4, Red = 5, Green = 6, } #[repr(i32)] pub enum UsbCamEvLevel { Pos2_0 = 0, Pos1_7 = 1, Pos1_5 = 2, Pos1_3 = 3, Pos1_0 = 4, Pos0_7 = 5, Pos0_5 = 6, Pos0_3 = 7, Zero = 8, Neg0_3, Neg0_5, Neg0_7, Neg1_0, Neg1_3, Neg1_5, Neg1_7, Neg2_0, } #[repr(i32)] pub enum RtcCheckValidError { InvalidYear = -1, InvalidMonth = -2, InvalidDay = -3, InvalidHour = -4, InvalidMinutes = -5, InvalidSeconds = -6, InvalidMicroseconds = -7, } #[repr(u32)] pub enum PowerTick { All = 0, Suspend = 1, Display = 6, } #[repr(u32)] pub enum IoAssignPerms { RdWr = 0, RdOnly = 1, } #[repr(u32)] pub enum IoWhence { Set = 0, Cur = 1, End = 2, } #[repr(u32)] pub enum UmdType { Game = 0x10, Video = 0x20, Audio = 0x40, } #[repr(u32)] pub enum GuPrimitive { Points = 0, Lines = 1, LineStrip = 2, Triangles = 3, TriangleStrip = 4, TriangleFan = 5, Sprites = 6, } #[repr(u32)] pub enum PatchPrimitive { Points = 0, LineStrip = 2, TriangleStrip = 4, } #[repr(u32)] pub enum GuState { AlphaTest = 0, DepthTest = 1, ScissorTest = 2, StencilTest = 3, Blend = 4, CullFace = 5, Dither = 6, Fog = 7, ClipPlanes = 8, Texture2D = 9, Lighting = 10, Light0 = 11, Light1 = 12, Light2 = 13, Light3 = 14, LineSmooth = 15, PatchCullFace = 16, ColorTest = 17, ColorLogicOp = 18, FaceNormalReverse = 19, PatchFace = 20, Fragment2X = 21, } #[repr(u32)] pub enum MatrixMode { Projection = 0, View = 1, Model = 2, Texture = 3, } #[repr(u32)] pub enum TexturePixelFormat { Psm5650 = 0, Psm5551 = 1, Psm4444 = 2, Psm8888 = 3, PsmT4 = 4, PsmT8 = 5, PsmT16 = 6, PsmT32 = 7, PsmDxt1 = 8, PsmDxt3 = 9, PsmDxt5 = 10, } #[repr(u32)] pub enum SplineMode { FillFill = 0, OpenFill = 1, FillOpen = 2, OpenOpen = 3, } #[repr(u32)] pub enum ShadingModel { Flat = 0, Smooth = 1, } #[repr(u32)] pub enum LogicalOperation { Clear = 0, And = 1, AndReverse = 2, Copy = 3, AndInverted = 4, Noop = 5, Xor = 6, Or = 7, Nor = 8, Equiv = 9, Inverted = 10, OrReverse = 11, CopyInverted = 12, OrInverted = 13, Nand = 14, Set = 15, } #[repr(u32)] pub enum TextureFilter { Nearest = 0, Linear = 1, NearestMipmapNearest = 4, LinearMipmapNearest = 5, NearestMipmapLinear = 6, LinearMipmapLinear = 7, } #[repr(u32)] pub enum TextureMapMode { TextureCoords = 0, TextureMatrix = 1, EnvironmentMap = 2, } #[repr(u32)] pub enum TextureLevelMode { Auto = 0, Const = 1, Slope = 2, } #[repr(u32)] pub enum TextureProjectionMapMode { Position = 0, Uv = 1, NormalizedNormal = 2, Normal = 3, } #[repr(u32)] pub enum GuTexWrapMode { Repeat = 0, Clamp = 1, } #[repr(u32)] pub enum FrontFaceDirection { Clockwise = 0, CounterClockwise = 1, } #[repr(u32)] pub enum AlphaFunc { Never = 0, Always, Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual, } #[repr(u32)] pub enum StencilFunc { Never = 0, Always, Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual, } #[repr(u32)] pub enum ColorFunc { Never = 0, Always, Equal, NotEqual, } #[repr(u32)] pub enum DepthFunc { Never = 0, Always, Equal, NotEqual, Less, LessOrEqual, Greater, GreaterOrEqual, } #[repr(u32)] pub enum TextureEffect { Modulate = 0, Decal = 1, Blend = 2, Replace = 3, Add = 4, } #[repr(u32)] pub enum TextureColorComponent { Rgb = 0, Rgba = 1, } #[repr(u32)] pub enum MipmapLevel { None = 0, Level1, Level2, Level3, Level4, Level5, Level6, Level7, } #[repr(u32)] pub enum BlendOp { Add = 0, Subtract = 1, ReverseSubtract = 2, Min = 3, Max = 4, Abs = 5, } #[repr(u32)] pub enum BlendSrc { SrcColor = 0, OneMinusSrcColor = 1, SrcAlpha = 2, OneMinusSrcAlpha = 3, Fix = 10, } #[repr(u32)] pub enum BlendDst { DstColor = 0, OneMinusDstColor = 1, DstAlpha = 4, OneMinusDstAlpha = 5, Fix = 10, } #[repr(u32)] pub enum StencilOperation { Keep = 0, Zero = 1, Replace = 2, Invert = 3, Incr = 4, Decr = 5, } #[repr(u32)] pub enum LightMode { SingleColor = 0, SeparateSpecularColor = 1, } #[repr(u32)] pub enum LightType { Directional = 0, Pointlight = 1, Spotlight = 2, } #[repr(u32)] pub enum GuContextType { Direct = 0, Call = 1, Send = 2, } #[repr(u32)] pub enum GuQueueMode { Tail = 0, Head = 1, } #[repr(u32)] pub enum GuSyncMode { Finish = 0, Signal = 1, Done = 2, List = 3, Send = 4, } #[repr(u32)] pub enum GuSyncBehavior { Wait = 0, NoWait = 1, } #[repr(u32)] pub enum GuCallbackId { Signal = 1, Finish = 4, } #[repr(u32)] pub enum SignalBehavior { Suspend = 1, Continue = 2, } #[repr(u32)] pub enum ClutPixelFormat { Psm5650 = 0, Psm5551 = 1, Psm4444 = 2, Psm8888 = 3, } #[repr(C)] pub enum KeyType { Directory = 1, Integer = 2, String = 3, Bytes = 4, } #[repr(u32)] pub enum UtilityMsgDialogMode { Error, Text, } #[repr(u32)] pub enum UtilityMsgDialogPressed { Unknown1, Yes, No, Back, } #[repr(u32)] pub enum UtilityDialogButtonAccept { Circle, Cross, } #[repr(u32)] pub enum SceUtilityOskInputLanguage { Default, Japanese, English, French, Spanish, German, Italian, Dutch, Portugese, Russian, Korean, } #[repr(u32)] pub enum SceUtilityOskInputType { All, LatinDigit, LatinSymbol, LatinLowercase = 4, LatinUppercase = 8, JapaneseDigit = 0x100, JapaneseSymbol = 0x200, JapaneseLowercase = 0x400, JapaneseUppercase = 0x800, JapaneseHiragana = 0x1000, JapaneseHalfWidthKatakana = 0x2000, JapaneseKatakana = 0x4000, JapaneseKanji = 0x8000, RussianLowercase = 0x10000, RussianUppercase = 0x20000, Korean = 0x40000, Url = 0x80000, } #[repr(u32)] pub enum SceUtilityOskState { None, Initializing, Initialized, Visible, Quit, Finished, } #[repr(u32)] pub enum SceUtilityOskResult { Unchanged, Cancelled, Changed, } #[repr(u32)] pub enum SystemParamLanguage { Japanese, English, French, Spanish, German, Italian, Dutch, Portugese, Russian, Korean, ChineseTraditional, ChineseSimplified, } #[repr(u32)] pub enum SystemParamId { StringNickname = 1, AdhocChannel, WlanPowerSave, DateFormat, TimeFormat, Timezone, DaylightSavings, Language, Unknown, } #[repr(u32)] pub enum SystemParamAdhocChannel { ChannelAutomatic = 0, Channel1 = 1, Channel6 = 6, Channel11 = 11, } #[repr(u32)] pub enum SystemParamWlanPowerSaveState { Off, On, } #[repr(u32)] pub enum SystemParamDateFormat { YYYYMMDD, MMDDYYYY, DDMMYYYY, } #[repr(u32)] pub enum SystemParamTimeFormat { Hour24, Hour12, } #[repr(u32)] pub enum SystemParamDaylightSavings { Std, Dst, } #[repr(u32)] pub enum AvModule { AvCodec, SasCore, Atrac3Plus, MpegBase, Mp3, Vaudio, Aac, G729, } #[repr(u32)] pub enum Module { NetCommon = 0x100, NetAdhoc, NetInet, NetParseUri, NetHttp, NetSsl, UsbPspCm = 0x200, UsbMic, UsbCam, UsbGps, AvCodec = 0x300, AvSascore, AvAtrac3Plus, AvMpegBase, AvMp3, AvVaudio, AvAac, AvG729, NpCommon = 0x400, NpService, NpMatching2, NpDrm = 0x500, Irda = 0x600, } #[repr(u32)] pub enum NetModule { NetCommon = 1, NetAdhoc, NetInet, NetParseUri, NetHttp, NetSsl, } #[repr(u32)] pub enum UsbModule { UsbPspCm = 1, UsbAcc, UsbMic, UsbCam, UsbGps, } #[repr(u32)] pub enum NetParam { Name, Ssid, Secure, WepKey, IsStaticIp, Ip, NetMask, Route, ManualDns, PrimaryDns, SecondaryDns, ProxyUser, ProxyPass, UseProxy, ProxyServer, ProxyPort, Unknown1, Unknown2, } #[repr(u32)] pub enum UtilityNetconfAction { ConnectAP, DisplayStatus, ConnectAdhoc, } #[repr(u32)] pub enum UtilitySavedataMode { AutoLoad, AutoSave, Load, Save, ListLoad, ListSave, ListDelete, Delete, } #[repr(u32)] pub enum UtilitySavedataFocus { Unknown1, FirstList, LastList, Latest, Oldest, Unknown2, Unknown3, FirstEmpty, LastEmpty, } #[repr(u32)] pub enum UtilityGameSharingMode { Single = 1, Multiple, } #[repr(u32)] pub enum UtilityGameSharingDataType { File = 1, Memory, } #[repr(u32)] pub enum UtilityHtmlViewerInterfaceMode { Full, Limited, None, } #[repr(u32)] pub enum UtilityHtmlViewerCookieMode { Disabled = 0, Enabled, Confirm, Default, } #[repr(u32)] pub enum UtilityHtmlViewerTextSize { Large, Normal, Small, } #[repr(u32)] pub enum UtilityHtmlViewerDisplayMode { Normal, Fit, SmartFit, } #[repr(u32)] pub enum UtilityHtmlViewerConnectMode { Last, ManualOnce, ManualAll, } #[repr(u32)] pub enum UtilityHtmlViewerDisconnectMode { Enable, Disable, Confirm, } #[repr(u32)] pub enum ScePspnetAdhocPtpState { Closed, Listen, SynSent, SynReceived, Established, } #[repr(u32)] pub enum AdhocMatchingMode { Host = 1, Client, Ptp, } #[repr(u32)] pub enum ApctlState { Disconnected, Scanning, Joining, GettingIp, GotIp, EapAuth, KeyExchange, } #[repr(u32)] pub enum ApctlEvent { ConnectRequest, ScanRequest, ScanComplete, Established, GetIp, DisconnectRequest, Error, Info, EapAuth, KeyExchange, Reconnect, } #[repr(u32)] pub enum ApctlInfo { ProfileName, Bssid, Ssid, SsidLength, SecurityType, Strength, Channel, PowerSave, Ip, SubnetMask, Gateway, PrimaryDns, SecondaryDns, UseProxy, ProxyUrl, ProxyPort, EapType, StartBrowser, Wifisp, } #[repr(u32)] pub enum ApctlInfoSecurityType { None, Wep, Wpa, } #[repr(u32)] pub enum HttpMethod { Get, Post, Head, } #[repr(u32)] pub enum HttpAuthType { Basic, Digest, } } s_paren! { #[repr(transparent)] pub struct SceUid(pub i32); #[repr(transparent)] #[allow(dead_code)] pub struct SceMpeg(*mut *mut c_void); #[repr(transparent)] #[allow(dead_code)] pub struct SceMpegStream(*mut c_void); #[repr(transparent)] pub struct Mp3Handle(pub i32); #[repr(transparent)] #[allow(dead_code)] pub struct RegHandle(u32); } s! { pub struct sockaddr { pub sa_len: u8, pub sa_family: u8, pub sa_data: [u8;14], } pub struct in_addr { pub s_addr: u32, } pub struct AudioInputParams { pub unknown1: i32, pub gain: i32, pub unknown2: i32, pub unknown3: i32, pub unknown4: i32, pub unknown5: i32, } pub struct Atrac3BufferInfo { pub puc_write_position_first_buf: *mut u8, pub ui_writable_byte_first_buf: u32, pub ui_min_write_byte_first_buf: u32, pub ui_read_position_first_buf: u32, pub puc_write_position_second_buf: *mut u8, pub ui_writable_byte_second_buf: u32, pub ui_min_write_byte_second_buf: u32, pub ui_read_position_second_buf: u32, } pub struct SceCtrlData { pub timestamp: u32, pub buttons: i32, pub lx: u8, pub ly: u8, pub rsrv: [u8; 6], } pub struct SceCtrlLatch { pub ui_make: u32, pub ui_break: u32, pub ui_press: u32, pub ui_release: u32, } pub struct GeStack { pub stack: [u32; 8], } pub struct GeCallbackData { pub signal_func: ::Option, pub signal_arg: *mut c_void, pub finish_func: ::Option, pub finish_arg: *mut c_void, } pub struct GeListArgs { pub size: u32, pub context: *mut GeContext, pub num_stacks: u32, pub stacks: *mut GeStack, } pub struct GeBreakParam { pub buf: [u32; 4], } pub struct SceKernelLoadExecParam { pub size: usize, pub args: usize, pub argp: *mut c_void, pub key: *const u8, } pub struct timeval { pub tv_sec: i32, pub tv_usec: i32, } pub struct timezone { pub tz_minutes_west: i32, pub tz_dst_time: i32, } pub struct IntrHandlerOptionParam { size: i32, entry: u32, common: u32, gp: u32, intr_code: u16, sub_count: u16, intr_level: u16, enabled: u16, calls: u32, field_1c: u32, total_clock_lo: u32, total_clock_hi: u32, min_clock_lo: u32, min_clock_hi: u32, max_clock_lo: u32, max_clock_hi: u32, } pub struct SceKernelLMOption { pub size: usize, pub m_pid_text: SceUid, pub m_pid_data: SceUid, pub flags: u32, pub position: u8, pub access: u8, pub c_reserved: [u8; 2usize], } pub struct SceKernelSMOption { pub size: usize, pub m_pid_stack: SceUid, pub stack_size: usize, pub priority: i32, pub attribute: u32, } pub struct SceKernelModuleInfo { pub size: usize, pub n_segment: u8, pub reserved: [u8; 3usize], pub segment_addr: [i32; 4usize], pub segment_size: [i32; 4usize], pub entry_addr: u32, pub gp_value: u32, pub text_addr: u32, pub text_size: u32, pub data_size: u32, pub bss_size: u32, pub attribute: u16, pub version: [u8; 2usize], pub name: [u8; 28usize], } pub struct DebugProfilerRegs { pub enable: u32, pub systemck: u32, pub cpuck: u32, pub internal: u32, pub memory: u32, pub copz: u32, pub vfpu: u32, pub sleep: u32, pub bus_access: u32, pub uncached_load: u32, pub uncached_store: u32, pub cached_load: u32, pub cached_store: u32, pub i_miss: u32, pub d_miss: u32, pub d_writeback: u32, pub cop0_inst: u32, pub fpu_inst: u32, pub vfpu_inst: u32, pub local_bus: u32, } pub struct SceKernelSysClock { pub low: u32, pub hi: u32, } pub struct SceKernelThreadOptParam { pub size: usize, pub stack_mpid: SceUid, } pub struct SceKernelThreadInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub status: i32, pub entry: SceKernelThreadEntry, pub stack: *mut c_void, pub stack_size: i32, pub gp_reg: *mut c_void, pub init_priority: i32, pub current_priority: i32, pub wait_type: i32, pub wait_id: SceUid, pub wakeup_count: i32, pub exit_status: i32, pub run_clocks: SceKernelSysClock, pub intr_preempt_count: u32, pub thread_preempt_count: u32, pub release_count: u32, } pub struct SceKernelThreadRunStatus { pub size: usize, pub status: i32, pub current_priority: i32, pub wait_type: i32, pub wait_id: i32, pub wakeup_count: i32, pub run_clocks: SceKernelSysClock, pub intr_preempt_count: u32, pub thread_preempt_count: u32, pub release_count: u32, } pub struct SceKernelSemaOptParam { pub size: usize, } pub struct SceKernelSemaInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub init_count: i32, pub current_count: i32, pub max_count: i32, pub num_wait_threads: i32, } pub struct SceKernelEventFlagInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub init_pattern: u32, pub current_pattern: u32, pub num_wait_threads: i32, } pub struct SceKernelEventFlagOptParam { pub size: usize, } pub struct SceKernelMbxOptParam { pub size: usize, } pub struct SceKernelMbxInfo { pub size: usize, pub name: [u8; 32usize], pub attr: u32, pub num_wait_threads: i32, pub num_messages: i32, pub first_message: *mut c_void, } pub struct SceKernelVTimerInfo { pub size: usize, pub name: [u8; 32], pub active: i32, pub base: SceKernelSysClock, pub current: SceKernelSysClock, pub schedule: SceKernelSysClock, pub handler: SceKernelVTimerHandler, pub common: *mut c_void, } pub struct SceKernelThreadEventHandlerInfo { pub size: usize, pub name: [u8; 32], pub thread_id: SceUid, pub mask: i32, pub handler: SceKernelThreadEventHandler, pub common: *mut c_void, } pub struct SceKernelAlarmInfo { pub size: usize, pub schedule: SceKernelSysClock, pub handler: SceKernelAlarmHandler, pub common: *mut c_void, } pub struct SceKernelSystemStatus { pub size: usize, pub status: u32, pub idle_clocks: SceKernelSysClock, pub comes_out_of_idle_count: u32, pub thread_switch_count: u32, pub vfpu_switch_count: u32, } pub struct SceKernelMppInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub buf_size: i32, pub free_size: i32, pub num_send_wait_threads: i32, pub num_receive_wait_threads: i32, } pub struct SceKernelVplOptParam { pub size: usize, } pub struct SceKernelVplInfo { pub size: usize, pub name: [u8; 32], pub attr: u32, pub pool_size: i32, pub free_size: i32, pub num_wait_threads: i32, } pub struct SceKernelFplOptParam { pub size: usize, } pub struct SceKernelFplInfo { pub size: usize, pub name: [u8; 32usize], pub attr: u32, pub block_size: i32, pub num_blocks: i32, pub free_blocks: i32, pub num_wait_threads: i32, } pub struct SceKernelVTimerOptParam { pub size: usize, } pub struct SceKernelCallbackInfo { pub size: usize, pub name: [u8; 32usize], pub thread_id: SceUid, pub callback: SceKernelCallbackFunction, pub common: *mut c_void, pub notify_count: i32, pub notify_arg: i32, } pub struct UsbCamSetupStillParam { pub size: i32, pub resolution: UsbCamResolution, pub jpeg_size: i32, pub reverse_flags: i32, pub delay: UsbCamDelay, pub comp_level: i32, } pub struct UsbCamSetupStillExParam { pub size: i32, pub unk: u32, pub resolution: UsbCamResolutionEx, pub jpeg_size: i32, pub comp_level: i32, pub unk2: u32, pub unk3: u32, pub flip: i32, pub mirror: i32, pub delay: UsbCamDelay, pub unk4: [u32; 5usize], } pub struct UsbCamSetupVideoParam { pub size: i32, pub resolution: UsbCamResolution, pub framerate: UsbCamFrameRate, pub white_balance: UsbCamWb, pub saturation: i32, pub brightness: i32, pub contrast: i32, pub sharpness: i32, pub effect_mode: UsbCamEffectMode, pub frame_size: i32, pub unk: u32, pub evl_evel: UsbCamEvLevel, } pub struct UsbCamSetupVideoExParam { pub size: i32, pub unk: u32, pub resolution: UsbCamResolutionEx, pub framerate: UsbCamFrameRate, pub unk2: u32, pub unk3: u32, pub white_balance: UsbCamWb, pub saturation: i32, pub brightness: i32, pub contrast: i32, pub sharpness: i32, pub unk4: u32, pub unk5: u32, pub unk6: [u32; 3usize], pub effect_mode: UsbCamEffectMode, pub unk7: u32, pub unk8: u32, pub unk9: u32, pub unk10: u32, pub unk11: u32, pub frame_size: i32, pub unk12: u32, pub ev_level: UsbCamEvLevel, } pub struct ScePspDateTime { pub year: u16, pub month: u16, pub day: u16, pub hour: u16, pub minutes: u16, pub seconds: u16, pub microseconds: u32, } pub struct SceIoStat { pub st_mode: i32, pub st_attr: i32, pub st_size: i64, pub st_ctime: ScePspDateTime, pub st_atime: ScePspDateTime, pub st_mtime: ScePspDateTime, pub st_private: [u32; 6usize], } pub struct UmdInfo { pub size: u32, pub type_: UmdType, } pub struct SceMpegRingbuffer { pub packets: i32, pub unk0: u32, pub unk1: u32, pub unk2: u32, pub unk3: u32, pub data: *mut c_void, pub callback: SceMpegRingbufferCb, pub cb_param: *mut c_void, pub unk4: u32, pub unk5: u32, pub sce_mpeg: *mut c_void, } pub struct SceMpegAu { pub pts_msb: u32, pub pts: u32, pub dts_msb: u32, pub dts: u32, pub es_buffer: u32, pub au_size: u32, } pub struct SceMpegAvcMode { pub unk0: i32, pub pixel_format: super::DisplayPixelFormat, } #[repr(align(64))] pub struct SceMpegLLI { pub src: *mut c_void, pub dst: *mut c_void, pub next: *mut c_void, pub size: i32, } #[repr(align(64))] pub struct SceMpegYCrCbBuffer { pub frame_buffer_height16: i32, pub frame_buffer_width16: i32, pub unknown: i32, pub unknown2: i32, pub y_buffer: *mut c_void, pub y_buffer2: *mut c_void, pub cr_buffer: *mut c_void, pub cb_buffer: *mut c_void, pub cr_buffer2: *mut c_void, pub cb_buffer2: *mut c_void, pub frame_height: i32, pub frame_width: i32, pub frame_buffer_width: i32, pub unknown3: [i32; 11usize], } pub struct ScePspSRect { pub x: i16, pub y: i16, pub w: i16, pub h: i16, } pub struct ScePspIRect { pub x: i32, pub y: i32, pub w: i32, pub h: i32, } pub struct ScePspL64Rect { pub x: u64, pub y: u64, pub w: u64, pub h: u64, } pub struct ScePspSVector2 { pub x: i16, pub y: i16, } pub struct ScePspIVector2 { pub x: i32, pub y: i32, } pub struct ScePspL64Vector2 { pub x: u64, pub y: u64, } pub struct ScePspSVector3 { pub x: i16, pub y: i16, pub z: i16, } pub struct ScePspIVector3 { pub x: i32, pub y: i32, pub z: i32, } pub struct ScePspL64Vector3 { pub x: u64, pub y: u64, pub z: u64, } pub struct ScePspSVector4 { pub x: i16, pub y: i16, pub z: i16, pub w: i16, } pub struct ScePspIVector4 { pub x: i32, pub y: i32, pub z: i32, pub w: i32, } pub struct ScePspL64Vector4 { pub x: u64, pub y: u64, pub z: u64, pub w: u64, } pub struct ScePspIMatrix2 { pub x: ScePspIVector2, pub y: ScePspIVector2, } pub struct ScePspIMatrix3 { pub x: ScePspIVector3, pub y: ScePspIVector3, pub z: ScePspIVector3, } #[repr(align(16))] pub struct ScePspIMatrix4 { pub x: ScePspIVector4, pub y: ScePspIVector4, pub z: ScePspIVector4, pub w: ScePspIVector4, } pub struct ScePspIMatrix4Unaligned { pub x: ScePspIVector4, pub y: ScePspIVector4, pub z: ScePspIVector4, pub w: ScePspIVector4, } pub struct SceMp3InitArg { pub mp3_stream_start: u32, pub unk1: u32, pub mp3_stream_end: u32, pub unk2: u32, pub mp3_buf: *mut c_void, pub mp3_buf_size: i32, pub pcm_buf: *mut c_void, pub pcm_buf_size: i32, } pub struct OpenPSID { pub data: [u8; 16usize], } pub struct UtilityDialogCommon { pub size: u32, pub language: SystemParamLanguage, pub button_accept: UtilityDialogButtonAccept, pub graphics_thread: i32, pub access_thread: i32, pub font_thread: i32, pub sound_thread: i32, pub result: i32, pub reserved: [i32; 4usize], } pub struct UtilityNetconfAdhoc { pub name: [u8; 8usize], pub timeout: u32, } pub struct UtilityNetconfData { pub base: UtilityDialogCommon, pub action: UtilityNetconfAction, pub adhocparam: *mut UtilityNetconfAdhoc, pub hotspot: i32, pub hotspot_connected: i32, pub wifisp: i32, } pub struct UtilitySavedataFileData { pub buf: *mut c_void, pub buf_size: usize, pub size: usize, pub unknown: i32, } pub struct UtilitySavedataListSaveNewData { pub icon0: UtilitySavedataFileData, pub title: *mut u8, } pub struct UtilityGameSharingParams { pub base: UtilityDialogCommon, pub unknown1: i32, pub unknown2: i32, pub name: [u8; 8usize], pub unknown3: i32, pub unknown4: i32, pub unknown5: i32, pub result: i32, pub filepath: *mut u8, pub mode: UtilityGameSharingMode, pub datatype: UtilityGameSharingDataType, pub data: *mut c_void, pub datasize: u32, } pub struct UtilityHtmlViewerParam { pub base: UtilityDialogCommon, pub memaddr: *mut c_void, pub memsize: u32, pub unknown1: i32, pub unknown2: i32, pub initialurl: *mut u8, pub numtabs: u32, pub interfacemode: UtilityHtmlViewerInterfaceMode, pub options: i32, pub dldirname: *mut u8, pub dlfilename: *mut u8, pub uldirname: *mut u8, pub ulfilename: *mut u8, pub cookiemode: UtilityHtmlViewerCookieMode, pub unknown3: u32, pub homeurl: *mut u8, pub textsize: UtilityHtmlViewerTextSize, pub displaymode: UtilityHtmlViewerDisplayMode, pub connectmode: UtilityHtmlViewerConnectMode, pub disconnectmode: UtilityHtmlViewerDisconnectMode, pub memused: u32, pub unknown4: [i32; 10usize], } pub struct SceUtilityOskData { pub unk_00: i32, pub unk_04: i32, pub language: SceUtilityOskInputLanguage, pub unk_12: i32, pub inputtype: SceUtilityOskInputType, pub lines: i32, pub unk_24: i32, pub desc: *mut u16, pub intext: *mut u16, pub outtextlength: i32, pub outtext: *mut u16, pub result: SceUtilityOskResult, pub outtextlimit: i32, } pub struct SceUtilityOskParams { pub base: UtilityDialogCommon, pub datacount: i32, pub data: *mut SceUtilityOskData, pub state: SceUtilityOskState, pub unk_60: i32, } pub struct SceNetMallocStat { pub pool: i32, pub maximum: i32, pub free: i32, } pub struct SceNetAdhocctlAdhocId { pub unknown: i32, pub adhoc_id: [u8; 9usize], pub unk: [u8; 3usize], } pub struct SceNetAdhocctlScanInfo { pub next: *mut SceNetAdhocctlScanInfo, pub channel: i32, pub name: [u8; 8usize], pub bssid: [u8; 6usize], pub unknown: [u8; 2usize], pub unknown2: i32, } pub struct SceNetAdhocctlGameModeInfo { pub count: i32, pub macs: [[u8; 6usize]; 16usize], } pub struct SceNetAdhocPtpStat { pub next: *mut SceNetAdhocPtpStat, pub ptp_id: i32, pub mac: [u8; 6usize], pub peermac: [u8; 6usize], pub port: u16, pub peerport: u16, pub sent_data: u32, pub rcvd_data: u32, pub state: ScePspnetAdhocPtpState, } pub struct SceNetAdhocPdpStat { pub next: *mut SceNetAdhocPdpStat, pub pdp_id: i32, pub mac: [u8; 6usize], pub port: u16, pub rcvd_data: u32, } pub struct AdhocPoolStat { pub size: i32, pub maxsize: i32, pub freesize: i32, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct GeContext { pub context: [u32; 512], } #[allow(missing_debug_implementations)] pub struct SceKernelUtilsSha1Context { pub h: [u32; 5usize], pub us_remains: u16, pub us_computed: u16, pub ull_total_len: u64, pub buf: [u8; 64usize], } #[allow(missing_debug_implementations)] pub struct SceKernelUtilsMt19937Context { pub count: u32, pub state: [u32; 624usize], } #[allow(missing_debug_implementations)] pub struct SceKernelUtilsMd5Context { pub h: [u32; 4usize], pub pad: u32, pub us_remains: u16, pub us_computed: u16, pub ull_total_len: u64, pub buf: [u8; 64usize], } #[allow(missing_debug_implementations)] pub struct SceIoDirent { pub d_stat: SceIoStat, pub d_name: [u8; 256usize], pub d_private: *mut c_void, pub dummy: i32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFRect { pub x: f32, pub y: f32, pub w: f32, pub h: f32, } #[repr(align(16))] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector3 { pub x: f32, pub y: f32, pub z: f32, } #[repr(align(16))] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector4 { pub x: f32, pub y: f32, pub z: f32, pub w: f32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector4Unaligned { pub x: f32, pub y: f32, pub z: f32, pub w: f32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFVector2 { pub x: f32, pub y: f32, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFMatrix2 { pub x: ScePspFVector2, pub y: ScePspFVector2, } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct ScePspFMatrix3 { pub x: ScePspFVector3, pub y: ScePspFVector3, pub z: ScePspFVector3, } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(align(16))] pub struct ScePspFMatrix4 { pub x: ScePspFVector4, pub y: ScePspFVector4, pub z: ScePspFVector4, pub w: ScePspFVector4, } #[allow(missing_debug_implementations)] pub struct ScePspFMatrix4Unaligned { pub x: ScePspFVector4, pub y: ScePspFVector4, pub z: ScePspFVector4, pub w: ScePspFVector4, } #[allow(missing_debug_implementations)] pub union ScePspVector3 { pub fv: ScePspFVector3, pub iv: ScePspIVector3, pub f: [f32; 3usize], pub i: [i32; 3usize], } #[allow(missing_debug_implementations)] pub union ScePspVector4 { pub fv: ScePspFVector4, pub iv: ScePspIVector4, pub qw: u128, pub f: [f32; 4usize], pub i: [i32; 4usize], } #[allow(missing_debug_implementations)] pub union ScePspMatrix2 { pub fm: ScePspFMatrix2, pub im: ScePspIMatrix2, pub fv: [ScePspFVector2; 2usize], pub iv: [ScePspIVector2; 2usize], pub v: [ScePspVector2; 2usize], pub f: [[f32; 2usize]; 2usize], pub i: [[i32; 2usize]; 2usize], } #[allow(missing_debug_implementations)] pub union ScePspMatrix3 { pub fm: ScePspFMatrix3, pub im: ScePspIMatrix3, pub fv: [ScePspFVector3; 3usize], pub iv: [ScePspIVector3; 3usize], pub v: [ScePspVector3; 3usize], pub f: [[f32; 3usize]; 3usize], pub i: [[i32; 3usize]; 3usize], } #[allow(missing_debug_implementations)] pub union ScePspVector2 { pub fv: ScePspFVector2, pub iv: ScePspIVector2, pub f: [f32; 2usize], pub i: [i32; 2usize], } #[allow(missing_debug_implementations)] pub union ScePspMatrix4 { pub fm: ScePspFMatrix4, pub im: ScePspIMatrix4, pub fv: [ScePspFVector4; 4usize], pub iv: [ScePspIVector4; 4usize], pub v: [ScePspVector4; 4usize], pub f: [[f32; 4usize]; 4usize], pub i: [[i32; 4usize]; 4usize], } #[allow(missing_debug_implementations)] pub struct Key { pub key_type: KeyType, pub name: [u8; 256usize], pub name_len: u32, pub unk2: u32, pub unk3: u32, } #[allow(missing_debug_implementations)] pub struct UtilityMsgDialogParams { pub base: UtilityDialogCommon, pub unknown: i32, pub mode: UtilityMsgDialogMode, pub error_value: u32, pub message: [u8; 512usize], pub options: i32, pub button_pressed: UtilityMsgDialogPressed, } #[allow(missing_debug_implementations)] pub union UtilityNetData { pub as_uint: u32, pub as_string: [u8; 128usize], } #[allow(missing_debug_implementations)] pub struct UtilitySavedataSFOParam { pub title: [u8; 128usize], pub savedata_title: [u8; 128usize], pub detail: [u8; 1024usize], pub parental_level: u8, pub unknown: [u8; 3usize], } #[allow(missing_debug_implementations)] pub struct SceUtilitySavedataParam { pub base: UtilityDialogCommon, pub mode: UtilitySavedataMode, pub unknown1: i32, pub overwrite: i32, pub game_name: [u8; 13usize], pub reserved: [u8; 3usize], pub save_name: [u8; 20usize], pub save_name_list: *mut [u8; 20usize], pub file_name: [u8; 13usize], pub reserved1: [u8; 3usize], pub data_buf: *mut c_void, pub data_buf_size: usize, pub data_size: usize, pub sfo_param: UtilitySavedataSFOParam, pub icon0_file_data: UtilitySavedataFileData, pub icon1_file_data: UtilitySavedataFileData, pub pic1_file_data: UtilitySavedataFileData, pub snd0_file_data: UtilitySavedataFileData, pub new_data: *mut UtilitySavedataListSaveNewData, pub focus: UtilitySavedataFocus, pub unknown2: [i32; 4usize], pub key: [u8; 16], pub unknown3: [u8; 20], } #[allow(missing_debug_implementations)] pub struct SceNetAdhocctlPeerInfo { pub next: *mut SceNetAdhocctlPeerInfo, pub nickname: [u8; 128usize], pub mac: [u8; 6usize], pub unknown: [u8; 6usize], pub timestamp: u32, } #[allow(missing_debug_implementations)] pub struct SceNetAdhocctlParams { pub channel: i32, pub name: [u8; 8usize], pub bssid: [u8; 6usize], pub nickname: [u8; 128usize], } #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub union SceNetApctlInfo { pub name: [u8; 64usize], pub bssid: [u8; 6usize], pub ssid: [u8; 32usize], pub ssid_length: u32, pub security_type: u32, pub strength: u8, pub channel: u8, pub power_save: u8, pub ip: [u8; 16usize], pub sub_net_mask: [u8; 16usize], pub gateway: [u8; 16usize], pub primary_dns: [u8; 16usize], pub secondary_dns: [u8; 16usize], pub use_proxy: u32, pub proxy_url: [u8; 128usize], pub proxy_port: u16, pub eap_type: u32, pub start_browser: u32, pub wifisp: u32, } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const AUDIO_VOLUME_MAX: u32 = 0x8000; pub const AUDIO_CHANNEL_MAX: u32 = 8; pub const AUDIO_NEXT_CHANNEL: i32 = -1; pub const AUDIO_SAMPLE_MIN: u32 = 64; pub const AUDIO_SAMPLE_MAX: u32 = 65472; pub const PSP_CTRL_SELECT: i32 = 0x000001; pub const PSP_CTRL_START: i32 = 0x000008; pub const PSP_CTRL_UP: i32 = 0x000010; pub const PSP_CTRL_RIGHT: i32 = 0x000020; pub const PSP_CTRL_DOWN: i32 = 0x000040; pub const PSP_CTRL_LEFT: i32 = 0x000080; pub const PSP_CTRL_LTRIGGER: i32 = 0x000100; pub const PSP_CTRL_RTRIGGER: i32 = 0x000200; pub const PSP_CTRL_TRIANGLE: i32 = 0x001000; pub const PSP_CTRL_CIRCLE: i32 = 0x002000; pub const PSP_CTRL_CROSS: i32 = 0x004000; pub const PSP_CTRL_SQUARE: i32 = 0x008000; pub const PSP_CTRL_HOME: i32 = 0x010000; pub const PSP_CTRL_HOLD: i32 = 0x020000; pub const PSP_CTRL_NOTE: i32 = 0x800000; pub const PSP_CTRL_SCREEN: i32 = 0x400000; pub const PSP_CTRL_VOLUP: i32 = 0x100000; pub const PSP_CTRL_VOLDOWN: i32 = 0x200000; pub const PSP_CTRL_WLAN_UP: i32 = 0x040000; pub const PSP_CTRL_REMOTE: i32 = 0x080000; pub const PSP_CTRL_DISC: i32 = 0x1000000; pub const PSP_CTRL_MS: i32 = 0x2000000; pub const USB_CAM_PID: i32 = 0x282; pub const USB_BUS_DRIVER_NAME: &str = "USBBusDriver"; pub const USB_CAM_DRIVER_NAME: &str = "USBCamDriver"; pub const USB_CAM_MIC_DRIVER_NAME: &str = "USBCamMicDriver"; pub const USB_STOR_DRIVER_NAME: &str = "USBStor_Driver"; pub const ACTIVATED: i32 = 0x200; pub const CONNECTED: i32 = 0x020; pub const ESTABLISHED: i32 = 0x002; pub const USB_CAM_FLIP: i32 = 1; pub const USB_CAM_MIRROR: i32 = 0x100; pub const THREAD_ATTR_VFPU: i32 = 0x00004000; pub const THREAD_ATTR_USER: i32 = 0x80000000; pub const THREAD_ATTR_USBWLAN: i32 = 0xa0000000; pub const THREAD_ATTR_VSH: i32 = 0xc0000000; pub const THREAD_ATTR_SCRATCH_SRAM: i32 = 0x00008000; pub const THREAD_ATTR_NO_FILLSTACK: i32 = 0x00100000; pub const THREAD_ATTR_CLEAR_STACK: i32 = 0x00200000; pub const EVENT_WAIT_MULTIPLE: i32 = 0x200; pub const EVENT_WAIT_AND: i32 = 0; pub const EVENT_WAIT_OR: i32 = 1; pub const EVENT_WAIT_CLEAR: i32 = 0x20; pub const POWER_INFO_POWER_SWITCH: i32 = 0x80000000; pub const POWER_INFO_HOLD_SWITCH: i32 = 0x40000000; pub const POWER_INFO_STANDBY: i32 = 0x00080000; pub const POWER_INFO_RESUME_COMPLETE: i32 = 0x00040000; pub const POWER_INFO_RESUMING: i32 = 0x00020000; pub const POWER_INFO_SUSPENDING: i32 = 0x00010000; pub const POWER_INFO_AC_POWER: i32 = 0x00001000; pub const POWER_INFO_BATTERY_LOW: i32 = 0x00000100; pub const POWER_INFO_BATTERY_EXIST: i32 = 0x00000080; pub const POWER_INFO_BATTERY_POWER: i32 = 0x0000007; pub const FIO_S_IFLNK: i32 = 0x4000; pub const FIO_S_IFDIR: i32 = 0x1000; pub const FIO_S_IFREG: i32 = 0x2000; pub const FIO_S_ISUID: i32 = 0x0800; pub const FIO_S_ISGID: i32 = 0x0400; pub const FIO_S_ISVTX: i32 = 0x0200; pub const FIO_S_IRUSR: i32 = 0x0100; pub const FIO_S_IWUSR: i32 = 0x0080; pub const FIO_S_IXUSR: i32 = 0x0040; pub const FIO_S_IRGRP: i32 = 0x0020; pub const FIO_S_IWGRP: i32 = 0x0010; pub const FIO_S_IXGRP: i32 = 0x0008; pub const FIO_S_IROTH: i32 = 0x0004; pub const FIO_S_IWOTH: i32 = 0x0002; pub const FIO_S_IXOTH: i32 = 0x0001; pub const FIO_SO_IFLNK: i32 = 0x0008; pub const FIO_SO_IFDIR: i32 = 0x0010; pub const FIO_SO_IFREG: i32 = 0x0020; pub const FIO_SO_IROTH: i32 = 0x0004; pub const FIO_SO_IWOTH: i32 = 0x0002; pub const FIO_SO_IXOTH: i32 = 0x0001; pub const PSP_O_RD_ONLY: i32 = 0x0001; pub const PSP_O_WR_ONLY: i32 = 0x0002; pub const PSP_O_RD_WR: i32 = 0x0003; pub const PSP_O_NBLOCK: i32 = 0x0004; pub const PSP_O_DIR: i32 = 0x0008; pub const PSP_O_APPEND: i32 = 0x0100; pub const PSP_O_CREAT: i32 = 0x0200; pub const PSP_O_TRUNC: i32 = 0x0400; pub const PSP_O_EXCL: i32 = 0x0800; pub const PSP_O_NO_WAIT: i32 = 0x8000; pub const UMD_NOT_PRESENT: i32 = 0x01; pub const UMD_PRESENT: i32 = 0x02; pub const UMD_CHANGED: i32 = 0x04; pub const UMD_INITING: i32 = 0x08; pub const UMD_INITED: i32 = 0x10; pub const UMD_READY: i32 = 0x20; pub const PLAY_PAUSE: i32 = 0x1; pub const FORWARD: i32 = 0x4; pub const BACK: i32 = 0x8; pub const VOL_UP: i32 = 0x10; pub const VOL_DOWN: i32 = 0x20; pub const HOLD: i32 = 0x80; pub const GU_PI: f32 = 3.141593; pub const GU_TEXTURE_8BIT: i32 = 1; pub const GU_TEXTURE_16BIT: i32 = 2; pub const GU_TEXTURE_32BITF: i32 = 3; pub const GU_COLOR_5650: i32 = 4 << 2; pub const GU_COLOR_5551: i32 = 5 << 2; pub const GU_COLOR_4444: i32 = 6 << 2; pub const GU_COLOR_8888: i32 = 7 << 2; pub const GU_NORMAL_8BIT: i32 = 1 << 5; pub const GU_NORMAL_16BIT: i32 = 2 << 5; pub const GU_NORMAL_32BITF: i32 = 3 << 5; pub const GU_VERTEX_8BIT: i32 = 1 << 7; pub const GU_VERTEX_16BIT: i32 = 2 << 7; pub const GU_VERTEX_32BITF: i32 = 3 << 7; pub const GU_WEIGHT_8BIT: i32 = 1 << 9; pub const GU_WEIGHT_16BIT: i32 = 2 << 9; pub const GU_WEIGHT_32BITF: i32 = 3 << 9; pub const GU_INDEX_8BIT: i32 = 1 << 11; pub const GU_INDEX_16BIT: i32 = 2 << 11; pub const GU_WEIGHTS1: i32 = (((1 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS2: i32 = (((2 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS3: i32 = (((3 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS4: i32 = (((4 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS5: i32 = (((5 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS6: i32 = (((6 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS7: i32 = (((7 - 1) & 7) << 14) as i32; pub const GU_WEIGHTS8: i32 = (((8 - 1) & 7) << 14) as i32; pub const GU_VERTICES1: i32 = (((1 - 1) & 7) << 18) as i32; pub const GU_VERTICES2: i32 = (((2 - 1) & 7) << 18) as i32; pub const GU_VERTICES3: i32 = (((3 - 1) & 7) << 18) as i32; pub const GU_VERTICES4: i32 = (((4 - 1) & 7) << 18) as i32; pub const GU_VERTICES5: i32 = (((5 - 1) & 7) << 18) as i32; pub const GU_VERTICES6: i32 = (((6 - 1) & 7) << 18) as i32; pub const GU_VERTICES7: i32 = (((7 - 1) & 7) << 18) as i32; pub const GU_VERTICES8: i32 = (((8 - 1) & 7) << 18) as i32; pub const GU_TRANSFORM_2D: i32 = 1 << 23; pub const GU_TRANSFORM_3D: i32 = 0; pub const GU_COLOR_BUFFER_BIT: i32 = 1; pub const GU_STENCIL_BUFFER_BIT: i32 = 2; pub const GU_DEPTH_BUFFER_BIT: i32 = 4; pub const GU_FAST_CLEAR_BIT: i32 = 16; pub const GU_AMBIENT: i32 = 1; pub const GU_DIFFUSE: i32 = 2; pub const GU_SPECULAR: i32 = 4; pub const GU_UNKNOWN_LIGHT_COMPONENT: i32 = 8; pub const SYSTEM_REGISTRY: [u8; 7] = *b"/system"; pub const REG_KEYNAME_SIZE: u32 = 27; pub const UTILITY_MSGDIALOG_ERROR: i32 = 0; pub const UTILITY_MSGDIALOG_TEXT: i32 = 1; pub const UTILITY_MSGDIALOG_YES_NO_BUTTONS: i32 = 0x10; pub const UTILITY_MSGDIALOG_DEFAULT_NO: i32 = 0x100; pub const UTILITY_HTMLVIEWER_OPEN_SCE_START_PAGE: i32 = 0x000001; pub const UTILITY_HTMLVIEWER_DISABLE_STARTUP_LIMITS: i32 = 0x000002; pub const UTILITY_HTMLVIEWER_DISABLE_EXIT_DIALOG: i32 = 0x000004; pub const UTILITY_HTMLVIEWER_DISABLE_CURSOR: i32 = 0x000008; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_COMPLETE_DIALOG: i32 = 0x000010; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_START_DIALOG: i32 = 0x000020; pub const UTILITY_HTMLVIEWER_DISABLE_DOWNLOAD_DESTINATION_DIALOG: i32 = 0x000040; pub const UTILITY_HTMLVIEWER_LOCK_DOWNLOAD_DESTINATION_DIALOG: i32 = 0x000080; pub const UTILITY_HTMLVIEWER_DISABLE_TAB_DISPLAY: i32 = 0x000100; pub const UTILITY_HTMLVIEWER_ENABLE_ANALOG_HOLD: i32 = 0x000200; pub const UTILITY_HTMLVIEWER_ENABLE_FLASH: i32 = 0x000400; pub const UTILITY_HTMLVIEWER_DISABLE_LRTRIGGER: i32 = 0x000800; extern "C" { pub fn sceAudioChReserve(channel: i32, sample_count: i32, format: AudioFormat) -> i32; pub fn sceAudioChRelease(channel: i32) -> i32; pub fn sceAudioOutput(channel: i32, vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioOutputBlocking(channel: i32, vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioOutputPanned( channel: i32, left_vol: i32, right_vol: i32, buf: *mut c_void, ) -> i32; pub fn sceAudioOutputPannedBlocking( channel: i32, left_vol: i32, right_vol: i32, buf: *mut c_void, ) -> i32; pub fn sceAudioGetChannelRestLen(channel: i32) -> i32; pub fn sceAudioGetChannelRestLength(channel: i32) -> i32; pub fn sceAudioSetChannelDataLen(channel: i32, sample_count: i32) -> i32; pub fn sceAudioChangeChannelConfig(channel: i32, format: AudioFormat) -> i32; pub fn sceAudioChangeChannelVolume(channel: i32, left_vol: i32, right_vol: i32) -> i32; pub fn sceAudioOutput2Reserve(sample_count: i32) -> i32; pub fn sceAudioOutput2Release() -> i32; pub fn sceAudioOutput2ChangeLength(sample_count: i32) -> i32; pub fn sceAudioOutput2OutputBlocking(vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioOutput2GetRestSample() -> i32; pub fn sceAudioSRCChReserve( sample_count: i32, freq: AudioOutputFrequency, channels: i32, ) -> i32; pub fn sceAudioSRCChRelease() -> i32; pub fn sceAudioSRCOutputBlocking(vol: i32, buf: *mut c_void) -> i32; pub fn sceAudioInputInit(unknown1: i32, gain: i32, unknown2: i32) -> i32; pub fn sceAudioInputInitEx(params: *mut AudioInputParams) -> i32; pub fn sceAudioInputBlocking(sample_count: i32, freq: AudioInputFrequency, buf: *mut c_void); pub fn sceAudioInput(sample_count: i32, freq: AudioInputFrequency, buf: *mut c_void); pub fn sceAudioGetInputLength() -> i32; pub fn sceAudioWaitInputEnd() -> i32; pub fn sceAudioPollInputEnd() -> i32; pub fn sceAtracGetAtracID(ui_codec_type: u32) -> i32; pub fn sceAtracSetDataAndGetID(buf: *mut c_void, bufsize: usize) -> i32; pub fn sceAtracDecodeData( atrac_id: i32, out_samples: *mut u16, out_n: *mut i32, out_end: *mut i32, out_remain_frame: *mut i32, ) -> i32; pub fn sceAtracGetRemainFrame(atrac_id: i32, out_remain_frame: *mut i32) -> i32; pub fn sceAtracGetStreamDataInfo( atrac_id: i32, write_pointer: *mut *mut u8, available_bytes: *mut u32, read_offset: *mut u32, ) -> i32; pub fn sceAtracAddStreamData(atrac_id: i32, bytes_to_add: u32) -> i32; pub fn sceAtracGetBitrate(atrac_id: i32, out_bitrate: *mut i32) -> i32; pub fn sceAtracSetLoopNum(atrac_id: i32, nloops: i32) -> i32; pub fn sceAtracReleaseAtracID(atrac_id: i32) -> i32; pub fn sceAtracGetNextSample(atrac_id: i32, out_n: *mut i32) -> i32; pub fn sceAtracGetMaxSample(atrac_id: i32, out_max: *mut i32) -> i32; pub fn sceAtracGetBufferInfoForReseting( atrac_id: i32, ui_sample: u32, pbuffer_info: *mut Atrac3BufferInfo, ) -> i32; pub fn sceAtracGetChannel(atrac_id: i32, pui_channel: *mut u32) -> i32; pub fn sceAtracGetInternalErrorInfo(atrac_id: i32, pi_result: *mut i32) -> i32; pub fn sceAtracGetLoopStatus( atrac_id: i32, pi_loop_num: *mut i32, pui_loop_status: *mut u32, ) -> i32; pub fn sceAtracGetNextDecodePosition(atrac_id: i32, pui_sample_position: *mut u32) -> i32; pub fn sceAtracGetSecondBufferInfo( atrac_id: i32, pui_position: *mut u32, pui_data_byte: *mut u32, ) -> i32; pub fn sceAtracGetSoundSample( atrac_id: i32, pi_end_sample: *mut i32, pi_loop_start_sample: *mut i32, pi_loop_end_sample: *mut i32, ) -> i32; pub fn sceAtracResetPlayPosition( atrac_id: i32, ui_sample: u32, ui_write_byte_first_buf: u32, ui_write_byte_second_buf: u32, ) -> i32; pub fn sceAtracSetData(atrac_id: i32, puc_buffer_addr: *mut u8, ui_buffer_byte: u32) -> i32; pub fn sceAtracSetHalfwayBuffer( atrac_id: i32, puc_buffer_addr: *mut u8, ui_read_byte: u32, ui_buffer_byte: u32, ) -> i32; pub fn sceAtracSetHalfwayBufferAndGetID( puc_buffer_addr: *mut u8, ui_read_byte: u32, ui_buffer_byte: u32, ) -> i32; pub fn sceAtracSetSecondBuffer( atrac_id: i32, puc_second_buffer_addr: *mut u8, ui_second_buffer_byte: u32, ) -> i32; pub fn sceCtrlSetSamplingCycle(cycle: i32) -> i32; pub fn sceCtrlGetSamplingCycle(pcycle: *mut i32) -> i32; pub fn sceCtrlSetSamplingMode(mode: CtrlMode) -> i32; pub fn sceCtrlGetSamplingMode(pmode: *mut i32) -> i32; pub fn sceCtrlPeekBufferPositive(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlPeekBufferNegative(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlReadBufferPositive(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlReadBufferNegative(pad_data: *mut SceCtrlData, count: i32) -> i32; pub fn sceCtrlPeekLatch(latch_data: *mut SceCtrlLatch) -> i32; pub fn sceCtrlReadLatch(latch_data: *mut SceCtrlLatch) -> i32; pub fn sceCtrlSetIdleCancelThreshold(idlereset: i32, idleback: i32) -> i32; pub fn sceCtrlGetIdleCancelThreshold(idlereset: *mut i32, idleback: *mut i32) -> i32; pub fn sceDisplaySetMode(mode: DisplayMode, width: usize, height: usize) -> u32; pub fn sceDisplayGetMode(pmode: *mut i32, pwidth: *mut i32, pheight: *mut i32) -> i32; pub fn sceDisplaySetFrameBuf( top_addr: *const u8, buffer_width: usize, pixel_format: DisplayPixelFormat, sync: DisplaySetBufSync, ) -> u32; pub fn sceDisplayGetFrameBuf( top_addr: *mut *mut c_void, buffer_width: *mut usize, pixel_format: *mut DisplayPixelFormat, sync: DisplaySetBufSync, ) -> i32; pub fn sceDisplayGetVcount() -> u32; pub fn sceDisplayWaitVblank() -> i32; pub fn sceDisplayWaitVblankCB() -> i32; pub fn sceDisplayWaitVblankStart() -> i32; pub fn sceDisplayWaitVblankStartCB() -> i32; pub fn sceDisplayGetAccumulatedHcount() -> i32; pub fn sceDisplayGetCurrentHcount() -> i32; pub fn sceDisplayGetFramePerSec() -> f32; pub fn sceDisplayIsForeground() -> i32; pub fn sceDisplayIsVblank() -> i32; pub fn sceGeEdramGetSize() -> u32; pub fn sceGeEdramGetAddr() -> *mut u8; pub fn sceGeEdramSetAddrTranslation(width: i32) -> i32; pub fn sceGeGetCmd(cmd: i32) -> u32; pub fn sceGeGetMtx(type_: GeMatrixType, matrix: *mut c_void) -> i32; pub fn sceGeGetStack(stack_id: i32, stack: *mut GeStack) -> i32; pub fn sceGeSaveContext(context: *mut GeContext) -> i32; pub fn sceGeRestoreContext(context: *const GeContext) -> i32; pub fn sceGeListEnQueue( list: *const c_void, stall: *mut c_void, cbid: i32, arg: *mut GeListArgs, ) -> i32; pub fn sceGeListEnQueueHead( list: *const c_void, stall: *mut c_void, cbid: i32, arg: *mut GeListArgs, ) -> i32; pub fn sceGeListDeQueue(qid: i32) -> i32; pub fn sceGeListUpdateStallAddr(qid: i32, stall: *mut c_void) -> i32; pub fn sceGeListSync(qid: i32, sync_type: i32) -> GeListState; pub fn sceGeDrawSync(sync_type: i32) -> GeListState; pub fn sceGeBreak(mode: i32, p_param: *mut GeBreakParam) -> i32; pub fn sceGeContinue() -> i32; pub fn sceGeSetCallback(cb: *mut GeCallbackData) -> i32; pub fn sceGeUnsetCallback(cbid: i32) -> i32; pub fn sceKernelExitGame(); pub fn sceKernelRegisterExitCallback(id: SceUid) -> i32; pub fn sceKernelLoadExec(file: *const u8, param: *mut SceKernelLoadExecParam) -> i32; pub fn sceKernelAllocPartitionMemory( partition: SceSysMemPartitionId, name: *const u8, type_: SceSysMemBlockTypes, size: u32, addr: *mut c_void, ) -> SceUid; pub fn sceKernelGetBlockHeadAddr(blockid: SceUid) -> *mut c_void; pub fn sceKernelFreePartitionMemory(blockid: SceUid) -> i32; pub fn sceKernelTotalFreeMemSize() -> usize; pub fn sceKernelMaxFreeMemSize() -> usize; pub fn sceKernelDevkitVersion() -> u32; pub fn sceKernelSetCompiledSdkVersion(version: u32) -> i32; pub fn sceKernelGetCompiledSdkVersion() -> u32; pub fn sceKernelLibcTime(t: *mut i32) -> i32; pub fn sceKernelLibcClock() -> u32; pub fn sceKernelLibcGettimeofday(tp: *mut timeval, tzp: *mut timezone) -> i32; pub fn sceKernelDcacheWritebackAll(); pub fn sceKernelDcacheWritebackInvalidateAll(); pub fn sceKernelDcacheWritebackRange(p: *const c_void, size: u32); pub fn sceKernelDcacheWritebackInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelDcacheInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelIcacheInvalidateAll(); pub fn sceKernelIcacheInvalidateRange(p: *const c_void, size: u32); pub fn sceKernelUtilsMt19937Init(ctx: *mut SceKernelUtilsMt19937Context, seed: u32) -> i32; pub fn sceKernelUtilsMt19937UInt(ctx: *mut SceKernelUtilsMt19937Context) -> u32; pub fn sceKernelUtilsMd5Digest(data: *mut u8, size: u32, digest: *mut u8) -> i32; pub fn sceKernelUtilsMd5BlockInit(ctx: *mut SceKernelUtilsMd5Context) -> i32; pub fn sceKernelUtilsMd5BlockUpdate( ctx: *mut SceKernelUtilsMd5Context, data: *mut u8, size: u32, ) -> i32; pub fn sceKernelUtilsMd5BlockResult(ctx: *mut SceKernelUtilsMd5Context, digest: *mut u8) -> i32; pub fn sceKernelUtilsSha1Digest(data: *mut u8, size: u32, digest: *mut u8) -> i32; pub fn sceKernelUtilsSha1BlockInit(ctx: *mut SceKernelUtilsSha1Context) -> i32; pub fn sceKernelUtilsSha1BlockUpdate( ctx: *mut SceKernelUtilsSha1Context, data: *mut u8, size: u32, ) -> i32; pub fn sceKernelUtilsSha1BlockResult( ctx: *mut SceKernelUtilsSha1Context, digest: *mut u8, ) -> i32; pub fn sceKernelRegisterSubIntrHandler( int_no: i32, no: i32, handler: *mut c_void, arg: *mut c_void, ) -> i32; pub fn sceKernelReleaseSubIntrHandler(int_no: i32, no: i32) -> i32; pub fn sceKernelEnableSubIntr(int_no: i32, no: i32) -> i32; pub fn sceKernelDisableSubIntr(int_no: i32, no: i32) -> i32; pub fn QueryIntrHandlerInfo( intr_code: SceUid, sub_intr_code: SceUid, data: *mut IntrHandlerOptionParam, ) -> i32; pub fn sceKernelCpuSuspendIntr() -> u32; pub fn sceKernelCpuResumeIntr(flags: u32); pub fn sceKernelCpuResumeIntrWithSync(flags: u32); pub fn sceKernelIsCpuIntrSuspended(flags: u32) -> i32; pub fn sceKernelIsCpuIntrEnable() -> i32; pub fn sceKernelLoadModule( path: *const u8, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelLoadModuleMs( path: *const u8, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelLoadModuleByID( fid: SceUid, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelLoadModuleBufferUsbWlan( buf_size: usize, buf: *mut c_void, flags: i32, option: *mut SceKernelLMOption, ) -> SceUid; pub fn sceKernelStartModule( mod_id: SceUid, arg_size: usize, argp: *mut c_void, status: *mut i32, option: *mut SceKernelSMOption, ) -> i32; pub fn sceKernelStopModule( mod_id: SceUid, arg_size: usize, argp: *mut c_void, status: *mut i32, option: *mut SceKernelSMOption, ) -> i32; pub fn sceKernelUnloadModule(mod_id: SceUid) -> i32; pub fn sceKernelSelfStopUnloadModule(unknown: i32, arg_size: usize, argp: *mut c_void) -> i32; pub fn sceKernelStopUnloadSelfModule( arg_size: usize, argp: *mut c_void, status: *mut i32, option: *mut SceKernelSMOption, ) -> i32; pub fn sceKernelQueryModuleInfo(mod_id: SceUid, info: *mut SceKernelModuleInfo) -> i32; pub fn sceKernelGetModuleIdList( read_buf: *mut SceUid, read_buf_size: i32, id_count: *mut i32, ) -> i32; pub fn sceKernelVolatileMemLock(unk: i32, ptr: *mut *mut c_void, size: *mut i32) -> i32; pub fn sceKernelVolatileMemTryLock(unk: i32, ptr: *mut *mut c_void, size: *mut i32) -> i32; pub fn sceKernelVolatileMemUnlock(unk: i32) -> i32; pub fn sceKernelStdin() -> SceUid; pub fn sceKernelStdout() -> SceUid; pub fn sceKernelStderr() -> SceUid; pub fn sceKernelGetThreadmanIdType(uid: SceUid) -> SceKernelIdListType; pub fn sceKernelCreateThread( name: *const u8, entry: SceKernelThreadEntry, init_priority: i32, stack_size: i32, attr: i32, option: *mut SceKernelThreadOptParam, ) -> SceUid; pub fn sceKernelDeleteThread(thid: SceUid) -> i32; pub fn sceKernelStartThread(id: SceUid, arg_len: usize, arg_p: *mut c_void) -> i32; pub fn sceKernelExitThread(status: i32) -> i32; pub fn sceKernelExitDeleteThread(status: i32) -> i32; pub fn sceKernelTerminateThread(thid: SceUid) -> i32; pub fn sceKernelTerminateDeleteThread(thid: SceUid) -> i32; pub fn sceKernelSuspendDispatchThread() -> i32; pub fn sceKernelResumeDispatchThread(state: i32) -> i32; pub fn sceKernelSleepThread() -> i32; pub fn sceKernelSleepThreadCB() -> i32; pub fn sceKernelWakeupThread(thid: SceUid) -> i32; pub fn sceKernelCancelWakeupThread(thid: SceUid) -> i32; pub fn sceKernelSuspendThread(thid: SceUid) -> i32; pub fn sceKernelResumeThread(thid: SceUid) -> i32; pub fn sceKernelWaitThreadEnd(thid: SceUid, timeout: *mut u32) -> i32; pub fn sceKernelWaitThreadEndCB(thid: SceUid, timeout: *mut u32) -> i32; pub fn sceKernelDelayThread(delay: u32) -> i32; pub fn sceKernelDelayThreadCB(delay: u32) -> i32; pub fn sceKernelDelaySysClockThread(delay: *mut SceKernelSysClock) -> i32; pub fn sceKernelDelaySysClockThreadCB(delay: *mut SceKernelSysClock) -> i32; pub fn sceKernelChangeCurrentThreadAttr(unknown: i32, attr: i32) -> i32; pub fn sceKernelChangeThreadPriority(thid: SceUid, priority: i32) -> i32; pub fn sceKernelRotateThreadReadyQueue(priority: i32) -> i32; pub fn sceKernelReleaseWaitThread(thid: SceUid) -> i32; pub fn sceKernelGetThreadId() -> i32; pub fn sceKernelGetThreadCurrentPriority() -> i32; pub fn sceKernelGetThreadExitStatus(thid: SceUid) -> i32; pub fn sceKernelCheckThreadStack() -> i32; pub fn sceKernelGetThreadStackFreeSize(thid: SceUid) -> i32; pub fn sceKernelReferThreadStatus(thid: SceUid, info: *mut SceKernelThreadInfo) -> i32; pub fn sceKernelReferThreadRunStatus( thid: SceUid, status: *mut SceKernelThreadRunStatus, ) -> i32; pub fn sceKernelCreateSema( name: *const u8, attr: u32, init_val: i32, max_val: i32, option: *mut SceKernelSemaOptParam, ) -> SceUid; pub fn sceKernelDeleteSema(sema_id: SceUid) -> i32; pub fn sceKernelSignalSema(sema_id: SceUid, signal: i32) -> i32; pub fn sceKernelWaitSema(sema_id: SceUid, signal: i32, timeout: *mut u32) -> i32; pub fn sceKernelWaitSemaCB(sema_id: SceUid, signal: i32, timeout: *mut u32) -> i32; pub fn sceKernelPollSema(sema_id: SceUid, signal: i32) -> i32; pub fn sceKernelReferSemaStatus(sema_id: SceUid, info: *mut SceKernelSemaInfo) -> i32; pub fn sceKernelCreateEventFlag( name: *const u8, attr: i32, bits: i32, opt: *mut SceKernelEventFlagOptParam, ) -> SceUid; pub fn sceKernelSetEventFlag(ev_id: SceUid, bits: u32) -> i32; pub fn sceKernelClearEventFlag(ev_id: SceUid, bits: u32) -> i32; pub fn sceKernelPollEventFlag(ev_id: SceUid, bits: u32, wait: i32, out_bits: *mut u32) -> i32; pub fn sceKernelWaitEventFlag( ev_id: SceUid, bits: u32, wait: i32, out_bits: *mut u32, timeout: *mut u32, ) -> i32; pub fn sceKernelWaitEventFlagCB( ev_id: SceUid, bits: u32, wait: i32, out_bits: *mut u32, timeout: *mut u32, ) -> i32; pub fn sceKernelDeleteEventFlag(ev_id: SceUid) -> i32; pub fn sceKernelReferEventFlagStatus(event: SceUid, status: *mut SceKernelEventFlagInfo) -> i32; pub fn sceKernelCreateMbx( name: *const u8, attr: u32, option: *mut SceKernelMbxOptParam, ) -> SceUid; pub fn sceKernelDeleteMbx(mbx_id: SceUid) -> i32; pub fn sceKernelSendMbx(mbx_id: SceUid, message: *mut c_void) -> i32; pub fn sceKernelReceiveMbx(mbx_id: SceUid, message: *mut *mut c_void, timeout: *mut u32) -> i32; pub fn sceKernelReceiveMbxCB( mbx_id: SceUid, message: *mut *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelPollMbx(mbx_id: SceUid, pmessage: *mut *mut c_void) -> i32; pub fn sceKernelCancelReceiveMbx(mbx_id: SceUid, num: *mut i32) -> i32; pub fn sceKernelReferMbxStatus(mbx_id: SceUid, info: *mut SceKernelMbxInfo) -> i32; pub fn sceKernelSetAlarm( clock: u32, handler: SceKernelAlarmHandler, common: *mut c_void, ) -> SceUid; pub fn sceKernelSetSysClockAlarm( clock: *mut SceKernelSysClock, handler: *mut SceKernelAlarmHandler, common: *mut c_void, ) -> SceUid; pub fn sceKernelCancelAlarm(alarm_id: SceUid) -> i32; pub fn sceKernelReferAlarmStatus(alarm_id: SceUid, info: *mut SceKernelAlarmInfo) -> i32; pub fn sceKernelCreateCallback( name: *const u8, func: SceKernelCallbackFunction, arg: *mut c_void, ) -> SceUid; pub fn sceKernelReferCallbackStatus(cb: SceUid, status: *mut SceKernelCallbackInfo) -> i32; pub fn sceKernelDeleteCallback(cb: SceUid) -> i32; pub fn sceKernelNotifyCallback(cb: SceUid, arg2: i32) -> i32; pub fn sceKernelCancelCallback(cb: SceUid) -> i32; pub fn sceKernelGetCallbackCount(cb: SceUid) -> i32; pub fn sceKernelCheckCallback() -> i32; pub fn sceKernelGetThreadmanIdList( type_: SceKernelIdListType, read_buf: *mut SceUid, read_buf_size: i32, id_count: *mut i32, ) -> i32; pub fn sceKernelReferSystemStatus(status: *mut SceKernelSystemStatus) -> i32; pub fn sceKernelCreateMsgPipe( name: *const u8, part: i32, attr: i32, unk1: *mut c_void, opt: *mut c_void, ) -> SceUid; pub fn sceKernelDeleteMsgPipe(uid: SceUid) -> i32; pub fn sceKernelSendMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelSendMsgPipeCB( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelTrySendMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, ) -> i32; pub fn sceKernelReceiveMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelReceiveMsgPipeCB( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelTryReceiveMsgPipe( uid: SceUid, message: *mut c_void, size: u32, unk1: i32, unk2: *mut c_void, ) -> i32; pub fn sceKernelCancelMsgPipe(uid: SceUid, send: *mut i32, recv: *mut i32) -> i32; pub fn sceKernelReferMsgPipeStatus(uid: SceUid, info: *mut SceKernelMppInfo) -> i32; pub fn sceKernelCreateVpl( name: *const u8, part: i32, attr: i32, size: u32, opt: *mut SceKernelVplOptParam, ) -> SceUid; pub fn sceKernelDeleteVpl(uid: SceUid) -> i32; pub fn sceKernelAllocateVpl( uid: SceUid, size: u32, data: *mut *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelAllocateVplCB( uid: SceUid, size: u32, data: *mut *mut c_void, timeout: *mut u32, ) -> i32; pub fn sceKernelTryAllocateVpl(uid: SceUid, size: u32, data: *mut *mut c_void) -> i32; pub fn sceKernelFreeVpl(uid: SceUid, data: *mut c_void) -> i32; pub fn sceKernelCancelVpl(uid: SceUid, num: *mut i32) -> i32; pub fn sceKernelReferVplStatus(uid: SceUid, info: *mut SceKernelVplInfo) -> i32; pub fn sceKernelCreateFpl( name: *const u8, part: i32, attr: i32, size: u32, blocks: u32, opt: *mut SceKernelFplOptParam, ) -> i32; pub fn sceKernelDeleteFpl(uid: SceUid) -> i32; pub fn sceKernelAllocateFpl(uid: SceUid, data: *mut *mut c_void, timeout: *mut u32) -> i32; pub fn sceKernelAllocateFplCB(uid: SceUid, data: *mut *mut c_void, timeout: *mut u32) -> i32; pub fn sceKernelTryAllocateFpl(uid: SceUid, data: *mut *mut c_void) -> i32; pub fn sceKernelFreeFpl(uid: SceUid, data: *mut c_void) -> i32; pub fn sceKernelCancelFpl(uid: SceUid, pnum: *mut i32) -> i32; pub fn sceKernelReferFplStatus(uid: SceUid, info: *mut SceKernelFplInfo) -> i32; pub fn sceKernelUSec2SysClock(usec: u32, clock: *mut SceKernelSysClock) -> i32; pub fn sceKernelUSec2SysClockWide(usec: u32) -> i64; pub fn sceKernelSysClock2USec( clock: *mut SceKernelSysClock, low: *mut u32, high: *mut u32, ) -> i32; pub fn sceKernelSysClock2USecWide(clock: i64, low: *mut u32, high: *mut u32) -> i32; pub fn sceKernelGetSystemTime(time: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetSystemTimeWide() -> i64; pub fn sceKernelGetSystemTimeLow() -> u32; pub fn sceKernelCreateVTimer(name: *const u8, opt: *mut SceKernelVTimerOptParam) -> SceUid; pub fn sceKernelDeleteVTimer(uid: SceUid) -> i32; pub fn sceKernelGetVTimerBase(uid: SceUid, base: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetVTimerBaseWide(uid: SceUid) -> i64; pub fn sceKernelGetVTimerTime(uid: SceUid, time: *mut SceKernelSysClock) -> i32; pub fn sceKernelGetVTimerTimeWide(uid: SceUid) -> i64; pub fn sceKernelSetVTimerTime(uid: SceUid, time: *mut SceKernelSysClock) -> i32; pub fn sceKernelSetVTimerTimeWide(uid: SceUid, time: i64) -> i64; pub fn sceKernelStartVTimer(uid: SceUid) -> i32; pub fn sceKernelStopVTimer(uid: SceUid) -> i32; pub fn sceKernelSetVTimerHandler( uid: SceUid, time: *mut SceKernelSysClock, handler: SceKernelVTimerHandler, common: *mut c_void, ) -> i32; pub fn sceKernelSetVTimerHandlerWide( uid: SceUid, time: i64, handler: SceKernelVTimerHandlerWide, common: *mut c_void, ) -> i32; pub fn sceKernelCancelVTimerHandler(uid: SceUid) -> i32; pub fn sceKernelReferVTimerStatus(uid: SceUid, info: *mut SceKernelVTimerInfo) -> i32; pub fn sceKernelRegisterThreadEventHandler( name: *const u8, thread_id: SceUid, mask: i32, handler: SceKernelThreadEventHandler, common: *mut c_void, ) -> SceUid; pub fn sceKernelReleaseThreadEventHandler(uid: SceUid) -> i32; pub fn sceKernelReferThreadEventHandlerStatus( uid: SceUid, info: *mut SceKernelThreadEventHandlerInfo, ) -> i32; pub fn sceKernelReferThreadProfiler() -> *mut DebugProfilerRegs; pub fn sceKernelReferGlobalProfiler() -> *mut DebugProfilerRegs; pub fn sceUsbStart(driver_name: *const u8, size: i32, args: *mut c_void) -> i32; pub fn sceUsbStop(driver_name: *const u8, size: i32, args: *mut c_void) -> i32; pub fn sceUsbActivate(pid: u32) -> i32; pub fn sceUsbDeactivate(pid: u32) -> i32; pub fn sceUsbGetState() -> i32; pub fn sceUsbGetDrvState(driver_name: *const u8) -> i32; } extern "C" { pub fn sceUsbCamSetupStill(param: *mut UsbCamSetupStillParam) -> i32; pub fn sceUsbCamSetupStillEx(param: *mut UsbCamSetupStillExParam) -> i32; pub fn sceUsbCamStillInputBlocking(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamStillInput(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamStillWaitInputEnd() -> i32; pub fn sceUsbCamStillPollInputEnd() -> i32; pub fn sceUsbCamStillCancelInput() -> i32; pub fn sceUsbCamStillGetInputLength() -> i32; pub fn sceUsbCamSetupVideo( param: *mut UsbCamSetupVideoParam, work_area: *mut c_void, work_area_size: i32, ) -> i32; pub fn sceUsbCamSetupVideoEx( param: *mut UsbCamSetupVideoExParam, work_area: *mut c_void, work_area_size: i32, ) -> i32; pub fn sceUsbCamStartVideo() -> i32; pub fn sceUsbCamStopVideo() -> i32; pub fn sceUsbCamReadVideoFrameBlocking(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamReadVideoFrame(buf: *mut u8, size: usize) -> i32; pub fn sceUsbCamWaitReadVideoFrameEnd() -> i32; pub fn sceUsbCamPollReadVideoFrameEnd() -> i32; pub fn sceUsbCamGetReadVideoFrameSize() -> i32; pub fn sceUsbCamSetSaturation(saturation: i32) -> i32; pub fn sceUsbCamSetBrightness(brightness: i32) -> i32; pub fn sceUsbCamSetContrast(contrast: i32) -> i32; pub fn sceUsbCamSetSharpness(sharpness: i32) -> i32; pub fn sceUsbCamSetImageEffectMode(effect_mode: UsbCamEffectMode) -> i32; pub fn sceUsbCamSetEvLevel(exposure_level: UsbCamEvLevel) -> i32; pub fn sceUsbCamSetReverseMode(reverse_flags: i32) -> i32; pub fn sceUsbCamSetZoom(zoom: i32) -> i32; pub fn sceUsbCamGetSaturation(saturation: *mut i32) -> i32; pub fn sceUsbCamGetBrightness(brightness: *mut i32) -> i32; pub fn sceUsbCamGetContrast(contrast: *mut i32) -> i32; pub fn sceUsbCamGetSharpness(sharpness: *mut i32) -> i32; pub fn sceUsbCamGetImageEffectMode(effect_mode: *mut UsbCamEffectMode) -> i32; pub fn sceUsbCamGetEvLevel(exposure_level: *mut UsbCamEvLevel) -> i32; pub fn sceUsbCamGetReverseMode(reverse_flags: *mut i32) -> i32; pub fn sceUsbCamGetZoom(zoom: *mut i32) -> i32; pub fn sceUsbCamAutoImageReverseSW(on: i32) -> i32; pub fn sceUsbCamGetAutoImageReverseState() -> i32; pub fn sceUsbCamGetLensDirection() -> i32; pub fn sceUsbstorBootRegisterNotify(event_flag: SceUid) -> i32; pub fn sceUsbstorBootUnregisterNotify(event_flag: u32) -> i32; pub fn sceUsbstorBootSetCapacity(size: u32) -> i32; pub fn scePowerRegisterCallback(slot: i32, cbid: SceUid) -> i32; pub fn scePowerUnregisterCallback(slot: i32) -> i32; pub fn scePowerIsPowerOnline() -> i32; pub fn scePowerIsBatteryExist() -> i32; pub fn scePowerIsBatteryCharging() -> i32; pub fn scePowerGetBatteryChargingStatus() -> i32; pub fn scePowerIsLowBattery() -> i32; pub fn scePowerGetBatteryLifePercent() -> i32; pub fn scePowerGetBatteryLifeTime() -> i32; pub fn scePowerGetBatteryTemp() -> i32; pub fn scePowerGetBatteryElec() -> i32; pub fn scePowerGetBatteryVolt() -> i32; pub fn scePowerSetCpuClockFrequency(cpufreq: i32) -> i32; pub fn scePowerSetBusClockFrequency(busfreq: i32) -> i32; pub fn scePowerGetCpuClockFrequency() -> i32; pub fn scePowerGetCpuClockFrequencyInt() -> i32; pub fn scePowerGetCpuClockFrequencyFloat() -> f32; pub fn scePowerGetBusClockFrequency() -> i32; pub fn scePowerGetBusClockFrequencyInt() -> i32; pub fn scePowerGetBusClockFrequencyFloat() -> f32; pub fn scePowerSetClockFrequency(pllfreq: i32, cpufreq: i32, busfreq: i32) -> i32; pub fn scePowerLock(unknown: i32) -> i32; pub fn scePowerUnlock(unknown: i32) -> i32; pub fn scePowerTick(t: PowerTick) -> i32; pub fn scePowerGetIdleTimer() -> i32; pub fn scePowerIdleTimerEnable(unknown: i32) -> i32; pub fn scePowerIdleTimerDisable(unknown: i32) -> i32; pub fn scePowerRequestStandby() -> i32; pub fn scePowerRequestSuspend() -> i32; pub fn sceWlanDevIsPowerOn() -> i32; pub fn sceWlanGetSwitchState() -> i32; pub fn sceWlanGetEtherAddr(ether_addr: *mut u8) -> i32; pub fn sceWlanDevAttach() -> i32; pub fn sceWlanDevDetach() -> i32; pub fn sceRtcGetTickResolution() -> u32; pub fn sceRtcGetCurrentTick(tick: *mut u64) -> i32; pub fn sceRtcGetCurrentClock(tm: *mut ScePspDateTime, tz: i32) -> i32; pub fn sceRtcGetCurrentClockLocalTime(tm: *mut ScePspDateTime) -> i32; pub fn sceRtcConvertUtcToLocalTime(tick_utc: *const u64, tick_local: *mut u64) -> i32; pub fn sceRtcConvertLocalTimeToUTC(tick_local: *const u64, tick_utc: *mut u64) -> i32; pub fn sceRtcIsLeapYear(year: i32) -> i32; pub fn sceRtcGetDaysInMonth(year: i32, month: i32) -> i32; pub fn sceRtcGetDayOfWeek(year: i32, month: i32, day: i32) -> i32; pub fn sceRtcCheckValid(date: *const ScePspDateTime) -> i32; pub fn sceRtcSetTick(date: *mut ScePspDateTime, tick: *const u64) -> i32; pub fn sceRtcGetTick(date: *const ScePspDateTime, tick: *mut u64) -> i32; pub fn sceRtcCompareTick(tick1: *const u64, tick2: *const u64) -> i32; pub fn sceRtcTickAddTicks(dest_tick: *mut u64, src_tick: *const u64, num_ticks: u64) -> i32; pub fn sceRtcTickAddMicroseconds(dest_tick: *mut u64, src_tick: *const u64, num_ms: u64) -> i32; pub fn sceRtcTickAddSeconds(dest_tick: *mut u64, src_tick: *const u64, num_seconds: u64) -> i32; pub fn sceRtcTickAddMinutes(dest_tick: *mut u64, src_tick: *const u64, num_minutes: u64) -> i32; pub fn sceRtcTickAddHours(dest_tick: *mut u64, src_tick: *const u64, num_hours: u64) -> i32; pub fn sceRtcTickAddDays(dest_tick: *mut u64, src_tick: *const u64, num_days: u64) -> i32; pub fn sceRtcTickAddWeeks(dest_tick: *mut u64, src_tick: *const u64, num_weeks: u64) -> i32; pub fn sceRtcTickAddMonths(dest_tick: *mut u64, src_tick: *const u64, num_months: u64) -> i32; pub fn sceRtcTickAddYears(dest_tick: *mut u64, src_tick: *const u64, num_years: u64) -> i32; pub fn sceRtcSetTime_t(date: *mut ScePspDateTime, time: u32) -> i32; pub fn sceRtcGetTime_t(date: *const ScePspDateTime, time: *mut u32) -> i32; pub fn sceRtcSetTime64_t(date: *mut ScePspDateTime, time: u64) -> i32; pub fn sceRtcGetTime64_t(date: *const ScePspDateTime, time: *mut u64) -> i32; pub fn sceRtcSetDosTime(date: *mut ScePspDateTime, dos_time: u32) -> i32; pub fn sceRtcGetDosTime(date: *mut ScePspDateTime, dos_time: u32) -> i32; pub fn sceRtcSetWin32FileTime(date: *mut ScePspDateTime, time: *mut u64) -> i32; pub fn sceRtcGetWin32FileTime(date: *mut ScePspDateTime, time: *mut u64) -> i32; pub fn sceRtcParseDateTime(dest_tick: *mut u64, date_string: *const u8) -> i32; pub fn sceRtcFormatRFC3339( psz_date_time: *mut char, p_utc: *const u64, time_zone_minutes: i32, ) -> i32; pub fn sceRtcFormatRFC3339LocalTime(psz_date_time: *mut char, p_utc: *const u64) -> i32; pub fn sceRtcParseRFC3339(p_utc: *mut u64, psz_date_time: *const u8) -> i32; pub fn sceRtcFormatRFC2822( psz_date_time: *mut char, p_utc: *const u64, time_zone_minutes: i32, ) -> i32; pub fn sceRtcFormatRFC2822LocalTime(psz_date_time: *mut char, p_utc: *const u64) -> i32; pub fn sceIoOpen(file: *const u8, flags: i32, permissions: IoPermissions) -> SceUid; pub fn sceIoOpenAsync(file: *const u8, flags: i32, permissions: IoPermissions) -> SceUid; pub fn sceIoClose(fd: SceUid) -> i32; pub fn sceIoCloseAsync(fd: SceUid) -> i32; pub fn sceIoRead(fd: SceUid, data: *mut c_void, size: u32) -> i32; pub fn sceIoReadAsync(fd: SceUid, data: *mut c_void, size: u32) -> i32; pub fn sceIoWrite(fd: SceUid, data: *const c_void, size: usize) -> i32; pub fn sceIoWriteAsync(fd: SceUid, data: *const c_void, size: u32) -> i32; pub fn sceIoLseek(fd: SceUid, offset: i64, whence: IoWhence) -> i64; pub fn sceIoLseekAsync(fd: SceUid, offset: i64, whence: IoWhence) -> i32; pub fn sceIoLseek32(fd: SceUid, offset: i32, whence: IoWhence) -> i32; pub fn sceIoLseek32Async(fd: SceUid, offset: i32, whence: IoWhence) -> i32; pub fn sceIoRemove(file: *const u8) -> i32; pub fn sceIoMkdir(dir: *const u8, mode: IoPermissions) -> i32; pub fn sceIoRmdir(path: *const u8) -> i32; pub fn sceIoChdir(path: *const u8) -> i32; pub fn sceIoRename(oldname: *const u8, newname: *const u8) -> i32; pub fn sceIoDopen(dirname: *const u8) -> SceUid; pub fn sceIoDread(fd: SceUid, dir: *mut SceIoDirent) -> i32; pub fn sceIoDclose(fd: SceUid) -> i32; pub fn sceIoDevctl( dev: *const u8, cmd: u32, indata: *mut c_void, inlen: i32, outdata: *mut c_void, outlen: i32, ) -> i32; pub fn sceIoAssign( dev1: *const u8, dev2: *const u8, dev3: *const u8, mode: IoAssignPerms, unk1: *mut c_void, unk2: i32, ) -> i32; pub fn sceIoUnassign(dev: *const u8) -> i32; pub fn sceIoGetstat(file: *const u8, stat: *mut SceIoStat) -> i32; pub fn sceIoChstat(file: *const u8, stat: *mut SceIoStat, bits: i32) -> i32; pub fn sceIoIoctl( fd: SceUid, cmd: u32, indata: *mut c_void, inlen: i32, outdata: *mut c_void, outlen: i32, ) -> i32; pub fn sceIoIoctlAsync( fd: SceUid, cmd: u32, indata: *mut c_void, inlen: i32, outdata: *mut c_void, outlen: i32, ) -> i32; pub fn sceIoSync(device: *const u8, unk: u32) -> i32; pub fn sceIoWaitAsync(fd: SceUid, res: *mut i64) -> i32; pub fn sceIoWaitAsyncCB(fd: SceUid, res: *mut i64) -> i32; pub fn sceIoPollAsync(fd: SceUid, res: *mut i64) -> i32; pub fn sceIoGetAsyncStat(fd: SceUid, poll: i32, res: *mut i64) -> i32; pub fn sceIoCancel(fd: SceUid) -> i32; pub fn sceIoGetDevType(fd: SceUid) -> i32; pub fn sceIoChangeAsyncPriority(fd: SceUid, pri: i32) -> i32; pub fn sceIoSetAsyncCallback(fd: SceUid, cb: SceUid, argp: *mut c_void) -> i32; pub fn sceJpegInitMJpeg() -> i32; pub fn sceJpegFinishMJpeg() -> i32; pub fn sceJpegCreateMJpeg(width: i32, height: i32) -> i32; pub fn sceJpegDeleteMJpeg() -> i32; pub fn sceJpegDecodeMJpeg(jpeg_buf: *mut u8, size: usize, rgba: *mut c_void, unk: u32) -> i32; pub fn sceUmdCheckMedium() -> i32; pub fn sceUmdGetDiscInfo(info: *mut UmdInfo) -> i32; pub fn sceUmdActivate(unit: i32, drive: *const u8) -> i32; pub fn sceUmdDeactivate(unit: i32, drive: *const u8) -> i32; pub fn sceUmdWaitDriveStat(state: i32) -> i32; pub fn sceUmdWaitDriveStatWithTimer(state: i32, timeout: u32) -> i32; pub fn sceUmdWaitDriveStatCB(state: i32, timeout: u32) -> i32; pub fn sceUmdCancelWaitDriveStat() -> i32; pub fn sceUmdGetDriveStat() -> i32; pub fn sceUmdGetErrorStat() -> i32; pub fn sceUmdRegisterUMDCallBack(cbid: i32) -> i32; pub fn sceUmdUnRegisterUMDCallBack(cbid: i32) -> i32; pub fn sceUmdReplacePermit() -> i32; pub fn sceUmdReplaceProhibit() -> i32; pub fn sceMpegInit() -> i32; pub fn sceMpegFinish(); pub fn sceMpegRingbufferQueryMemSize(packets: i32) -> i32; pub fn sceMpegRingbufferConstruct( ringbuffer: *mut SceMpegRingbuffer, packets: i32, data: *mut c_void, size: i32, callback: SceMpegRingbufferCb, cb_param: *mut c_void, ) -> i32; pub fn sceMpegRingbufferDestruct(ringbuffer: *mut SceMpegRingbuffer); pub fn sceMpegRingbufferAvailableSize(ringbuffer: *mut SceMpegRingbuffer) -> i32; pub fn sceMpegRingbufferPut( ringbuffer: *mut SceMpegRingbuffer, num_packets: i32, available: i32, ) -> i32; pub fn sceMpegQueryMemSize(unk: i32) -> i32; pub fn sceMpegCreate( handle: SceMpeg, data: *mut c_void, size: i32, ringbuffer: *mut SceMpegRingbuffer, frame_width: i32, unk1: i32, unk2: i32, ) -> i32; pub fn sceMpegDelete(handle: SceMpeg); pub fn sceMpegQueryStreamOffset(handle: SceMpeg, buffer: *mut c_void, offset: *mut i32) -> i32; pub fn sceMpegQueryStreamSize(buffer: *mut c_void, size: *mut i32) -> i32; pub fn sceMpegRegistStream(handle: SceMpeg, stream_id: i32, unk: i32) -> SceMpegStream; pub fn sceMpegUnRegistStream(handle: SceMpeg, stream: SceMpegStream); pub fn sceMpegFlushAllStream(handle: SceMpeg) -> i32; pub fn sceMpegMallocAvcEsBuf(handle: SceMpeg) -> *mut c_void; pub fn sceMpegFreeAvcEsBuf(handle: SceMpeg, buf: *mut c_void); pub fn sceMpegQueryAtracEsSize(handle: SceMpeg, es_size: *mut i32, out_size: *mut i32) -> i32; pub fn sceMpegInitAu(handle: SceMpeg, es_buffer: *mut c_void, au: *mut SceMpegAu) -> i32; pub fn sceMpegGetAvcAu( handle: SceMpeg, stream: SceMpegStream, au: *mut SceMpegAu, unk: *mut i32, ) -> i32; pub fn sceMpegAvcDecodeMode(handle: SceMpeg, mode: *mut SceMpegAvcMode) -> i32; pub fn sceMpegAvcDecode( handle: SceMpeg, au: *mut SceMpegAu, iframe_width: i32, buffer: *mut c_void, init: *mut i32, ) -> i32; pub fn sceMpegAvcDecodeStop( handle: SceMpeg, frame_width: i32, buffer: *mut c_void, status: *mut i32, ) -> i32; pub fn sceMpegGetAtracAu( handle: SceMpeg, stream: SceMpegStream, au: *mut SceMpegAu, unk: *mut c_void, ) -> i32; pub fn sceMpegAtracDecode( handle: SceMpeg, au: *mut SceMpegAu, buffer: *mut c_void, init: i32, ) -> i32; pub fn sceMpegBaseYCrCbCopyVme(yuv_buffer: *mut c_void, buffer: *mut i32, type_: i32) -> i32; pub fn sceMpegBaseCscInit(width: i32) -> i32; pub fn sceMpegBaseCscVme( rgb_buffer: *mut c_void, rgb_buffer2: *mut c_void, width: i32, y_cr_cb_buffer: *mut SceMpegYCrCbBuffer, ) -> i32; pub fn sceMpegbase_BEA18F91(lli: *mut SceMpegLLI) -> i32; pub fn sceHprmPeekCurrentKey(key: *mut i32) -> i32; pub fn sceHprmPeekLatch(latch: *mut [u32; 4]) -> i32; pub fn sceHprmReadLatch(latch: *mut [u32; 4]) -> i32; pub fn sceHprmIsHeadphoneExist() -> i32; pub fn sceHprmIsRemoteExist() -> i32; pub fn sceHprmIsMicrophoneExist() -> i32; pub fn sceGuDepthBuffer(zbp: *mut c_void, zbw: i32); pub fn sceGuDispBuffer(width: i32, height: i32, dispbp: *mut c_void, dispbw: i32); pub fn sceGuDrawBuffer(psm: DisplayPixelFormat, fbp: *mut c_void, fbw: i32); pub fn sceGuDrawBufferList(psm: DisplayPixelFormat, fbp: *mut c_void, fbw: i32); pub fn sceGuDisplay(state: bool) -> bool; pub fn sceGuDepthFunc(function: DepthFunc); pub fn sceGuDepthMask(mask: i32); pub fn sceGuDepthOffset(offset: i32); pub fn sceGuDepthRange(near: i32, far: i32); pub fn sceGuFog(near: f32, far: f32, color: u32); pub fn sceGuInit(); pub fn sceGuTerm(); pub fn sceGuBreak(mode: i32); pub fn sceGuContinue(); pub fn sceGuSetCallback(signal: GuCallbackId, callback: GuCallback) -> GuCallback; pub fn sceGuSignal(behavior: SignalBehavior, signal: i32); pub fn sceGuSendCommandf(cmd: GeCommand, argument: f32); pub fn sceGuSendCommandi(cmd: GeCommand, argument: i32); pub fn sceGuGetMemory(size: i32) -> *mut c_void; pub fn sceGuStart(context_type: GuContextType, list: *mut c_void); pub fn sceGuFinish() -> i32; pub fn sceGuFinishId(id: u32) -> i32; pub fn sceGuCallList(list: *const c_void); pub fn sceGuCallMode(mode: i32); pub fn sceGuCheckList() -> i32; pub fn sceGuSendList(mode: GuQueueMode, list: *const c_void, context: *mut GeContext); pub fn sceGuSwapBuffers() -> *mut c_void; pub fn sceGuSync(mode: GuSyncMode, behavior: GuSyncBehavior) -> GeListState; pub fn sceGuDrawArray( prim: GuPrimitive, vtype: i32, count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuBeginObject( vtype: i32, count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuEndObject(); pub fn sceGuSetStatus(state: GuState, status: i32); pub fn sceGuGetStatus(state: GuState) -> bool; pub fn sceGuSetAllStatus(status: i32); pub fn sceGuGetAllStatus() -> i32; pub fn sceGuEnable(state: GuState); pub fn sceGuDisable(state: GuState); pub fn sceGuLight(light: i32, type_: LightType, components: i32, position: &ScePspFVector3); pub fn sceGuLightAtt(light: i32, atten0: f32, atten1: f32, atten2: f32); pub fn sceGuLightColor(light: i32, component: i32, color: u32); pub fn sceGuLightMode(mode: LightMode); pub fn sceGuLightSpot(light: i32, direction: &ScePspFVector3, exponent: f32, cutoff: f32); pub fn sceGuClear(flags: i32); pub fn sceGuClearColor(color: u32); pub fn sceGuClearDepth(depth: u32); pub fn sceGuClearStencil(stencil: u32); pub fn sceGuPixelMask(mask: u32); pub fn sceGuColor(color: u32); pub fn sceGuColorFunc(func: ColorFunc, color: u32, mask: u32); pub fn sceGuColorMaterial(components: i32); pub fn sceGuAlphaFunc(func: AlphaFunc, value: i32, mask: i32); pub fn sceGuAmbient(color: u32); pub fn sceGuAmbientColor(color: u32); pub fn sceGuBlendFunc(op: BlendOp, src: BlendSrc, dest: BlendDst, src_fix: u32, dest_fix: u32); pub fn sceGuMaterial(components: i32, color: u32); pub fn sceGuModelColor(emissive: u32, ambient: u32, diffuse: u32, specular: u32); pub fn sceGuStencilFunc(func: StencilFunc, ref_: i32, mask: i32); pub fn sceGuStencilOp(fail: StencilOperation, zfail: StencilOperation, zpass: StencilOperation); pub fn sceGuSpecular(power: f32); pub fn sceGuFrontFace(order: FrontFaceDirection); pub fn sceGuLogicalOp(op: LogicalOperation); pub fn sceGuSetDither(matrix: &ScePspIMatrix4); pub fn sceGuShadeModel(mode: ShadingModel); pub fn sceGuCopyImage( psm: DisplayPixelFormat, sx: i32, sy: i32, width: i32, height: i32, srcw: i32, src: *mut c_void, dx: i32, dy: i32, destw: i32, dest: *mut c_void, ); pub fn sceGuTexEnvColor(color: u32); pub fn sceGuTexFilter(min: TextureFilter, mag: TextureFilter); pub fn sceGuTexFlush(); pub fn sceGuTexFunc(tfx: TextureEffect, tcc: TextureColorComponent); pub fn sceGuTexImage( mipmap: MipmapLevel, width: i32, height: i32, tbw: i32, tbp: *const c_void, ); pub fn sceGuTexLevelMode(mode: TextureLevelMode, bias: f32); pub fn sceGuTexMapMode(mode: TextureMapMode, a1: u32, a2: u32); pub fn sceGuTexMode(tpsm: TexturePixelFormat, maxmips: i32, a2: i32, swizzle: i32); pub fn sceGuTexOffset(u: f32, v: f32); pub fn sceGuTexProjMapMode(mode: TextureProjectionMapMode); pub fn sceGuTexScale(u: f32, v: f32); pub fn sceGuTexSlope(slope: f32); pub fn sceGuTexSync(); pub fn sceGuTexWrap(u: GuTexWrapMode, v: GuTexWrapMode); pub fn sceGuClutLoad(num_blocks: i32, cbp: *const c_void); pub fn sceGuClutMode(cpsm: ClutPixelFormat, shift: u32, mask: u32, a3: u32); pub fn sceGuOffset(x: u32, y: u32); pub fn sceGuScissor(x: i32, y: i32, w: i32, h: i32); pub fn sceGuViewport(cx: i32, cy: i32, width: i32, height: i32); pub fn sceGuDrawBezier( v_type: i32, u_count: i32, v_count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuPatchDivide(ulevel: u32, vlevel: u32); pub fn sceGuPatchFrontFace(a0: u32); pub fn sceGuPatchPrim(prim: PatchPrimitive); pub fn sceGuDrawSpline( v_type: i32, u_count: i32, v_count: i32, u_edge: i32, v_edge: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGuSetMatrix(type_: MatrixMode, matrix: &ScePspFMatrix4); pub fn sceGuBoneMatrix(index: u32, matrix: &ScePspFMatrix4); pub fn sceGuMorphWeight(index: i32, weight: f32); pub fn sceGuDrawArrayN( primitive_type: GuPrimitive, v_type: i32, count: i32, a3: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawArray( prim: GuPrimitive, v_type: i32, count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawArrayN( prim: GuPrimitive, v_type: i32, count: i32, a3: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawBezier( v_type: i32, u_count: i32, v_count: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumDrawSpline( v_type: i32, u_count: i32, v_count: i32, u_edge: i32, v_edge: i32, indices: *const c_void, vertices: *const c_void, ); pub fn sceGumFastInverse(); pub fn sceGumFullInverse(); pub fn sceGumLoadIdentity(); pub fn sceGumLoadMatrix(m: &ScePspFMatrix4); pub fn sceGumLookAt(eye: &ScePspFVector3, center: &ScePspFVector3, up: &ScePspFVector3); pub fn sceGumMatrixMode(mode: MatrixMode); pub fn sceGumMultMatrix(m: &ScePspFMatrix4); pub fn sceGumOrtho(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32); pub fn sceGumPerspective(fovy: f32, aspect: f32, near: f32, far: f32); pub fn sceGumPopMatrix(); pub fn sceGumPushMatrix(); pub fn sceGumRotateX(angle: f32); pub fn sceGumRotateY(angle: f32); pub fn sceGumRotateZ(angle: f32); pub fn sceGumRotateXYZ(v: &ScePspFVector3); pub fn sceGumRotateZYX(v: &ScePspFVector3); pub fn sceGumScale(v: &ScePspFVector3); pub fn sceGumStoreMatrix(m: &mut ScePspFMatrix4); pub fn sceGumTranslate(v: &ScePspFVector3); pub fn sceGumUpdateMatrix(); pub fn sceMp3ReserveMp3Handle(args: *mut SceMp3InitArg) -> i32; pub fn sceMp3ReleaseMp3Handle(handle: Mp3Handle) -> i32; pub fn sceMp3InitResource() -> i32; pub fn sceMp3TermResource() -> i32; pub fn sceMp3Init(handle: Mp3Handle) -> i32; pub fn sceMp3Decode(handle: Mp3Handle, dst: *mut *mut i16) -> i32; pub fn sceMp3GetInfoToAddStreamData( handle: Mp3Handle, dst: *mut *mut u8, to_write: *mut i32, src_pos: *mut i32, ) -> i32; pub fn sceMp3NotifyAddStreamData(handle: Mp3Handle, size: i32) -> i32; pub fn sceMp3CheckStreamDataNeeded(handle: Mp3Handle) -> i32; pub fn sceMp3SetLoopNum(handle: Mp3Handle, loop_: i32) -> i32; pub fn sceMp3GetLoopNum(handle: Mp3Handle) -> i32; pub fn sceMp3GetSumDecodedSample(handle: Mp3Handle) -> i32; pub fn sceMp3GetMaxOutputSample(handle: Mp3Handle) -> i32; pub fn sceMp3GetSamplingRate(handle: Mp3Handle) -> i32; pub fn sceMp3GetBitRate(handle: Mp3Handle) -> i32; pub fn sceMp3GetMp3ChannelNum(handle: Mp3Handle) -> i32; pub fn sceMp3ResetPlayPosition(handle: Mp3Handle) -> i32; pub fn sceRegOpenRegistry(reg: *mut Key, mode: i32, handle: *mut RegHandle) -> i32; pub fn sceRegFlushRegistry(handle: RegHandle) -> i32; pub fn sceRegCloseRegistry(handle: RegHandle) -> i32; pub fn sceRegOpenCategory( handle: RegHandle, name: *const u8, mode: i32, dir_handle: *mut RegHandle, ) -> i32; pub fn sceRegRemoveCategory(handle: RegHandle, name: *const u8) -> i32; pub fn sceRegCloseCategory(dir_handle: RegHandle) -> i32; pub fn sceRegFlushCategory(dir_handle: RegHandle) -> i32; pub fn sceRegGetKeyInfo( dir_handle: RegHandle, name: *const u8, key_handle: *mut RegHandle, type_: *mut KeyType, size: *mut usize, ) -> i32; pub fn sceRegGetKeyInfoByName( dir_handle: RegHandle, name: *const u8, type_: *mut KeyType, size: *mut usize, ) -> i32; pub fn sceRegGetKeyValue( dir_handle: RegHandle, key_handle: RegHandle, buf: *mut c_void, size: usize, ) -> i32; pub fn sceRegGetKeyValueByName( dir_handle: RegHandle, name: *const u8, buf: *mut c_void, size: usize, ) -> i32; pub fn sceRegSetKeyValue( dir_handle: RegHandle, name: *const u8, buf: *const c_void, size: usize, ) -> i32; pub fn sceRegGetKeysNum(dir_handle: RegHandle, num: *mut i32) -> i32; pub fn sceRegGetKeys(dir_handle: RegHandle, buf: *mut u8, num: i32) -> i32; pub fn sceRegCreateKey(dir_handle: RegHandle, name: *const u8, type_: i32, size: usize) -> i32; pub fn sceRegRemoveRegistry(key: *mut Key) -> i32; pub fn sceOpenPSIDGetOpenPSID(openpsid: *mut OpenPSID) -> i32; pub fn sceUtilityMsgDialogInitStart(params: *mut UtilityMsgDialogParams) -> i32; pub fn sceUtilityMsgDialogShutdownStart(); pub fn sceUtilityMsgDialogGetStatus() -> i32; pub fn sceUtilityMsgDialogUpdate(n: i32); pub fn sceUtilityMsgDialogAbort() -> i32; pub fn sceUtilityNetconfInitStart(data: *mut UtilityNetconfData) -> i32; pub fn sceUtilityNetconfShutdownStart() -> i32; pub fn sceUtilityNetconfUpdate(unknown: i32) -> i32; pub fn sceUtilityNetconfGetStatus() -> i32; pub fn sceUtilityCheckNetParam(id: i32) -> i32; pub fn sceUtilityGetNetParam(conf: i32, param: NetParam, data: *mut UtilityNetData) -> i32; pub fn sceUtilitySavedataInitStart(params: *mut SceUtilitySavedataParam) -> i32; pub fn sceUtilitySavedataGetStatus() -> i32; pub fn sceUtilitySavedataShutdownStart() -> i32; pub fn sceUtilitySavedataUpdate(unknown: i32); pub fn sceUtilityGameSharingInitStart(params: *mut UtilityGameSharingParams) -> i32; pub fn sceUtilityGameSharingShutdownStart(); pub fn sceUtilityGameSharingGetStatus() -> i32; pub fn sceUtilityGameSharingUpdate(n: i32); pub fn sceUtilityHtmlViewerInitStart(params: *mut UtilityHtmlViewerParam) -> i32; pub fn sceUtilityHtmlViewerShutdownStart() -> i32; pub fn sceUtilityHtmlViewerUpdate(n: i32) -> i32; pub fn sceUtilityHtmlViewerGetStatus() -> i32; pub fn sceUtilitySetSystemParamInt(id: SystemParamId, value: i32) -> i32; pub fn sceUtilitySetSystemParamString(id: SystemParamId, str: *const u8) -> i32; pub fn sceUtilityGetSystemParamInt(id: SystemParamId, value: *mut i32) -> i32; pub fn sceUtilityGetSystemParamString(id: SystemParamId, str: *mut u8, len: i32) -> i32; pub fn sceUtilityOskInitStart(params: *mut SceUtilityOskParams) -> i32; pub fn sceUtilityOskShutdownStart() -> i32; pub fn sceUtilityOskUpdate(n: i32) -> i32; pub fn sceUtilityOskGetStatus() -> i32; pub fn sceUtilityLoadNetModule(module: NetModule) -> i32; pub fn sceUtilityUnloadNetModule(module: NetModule) -> i32; pub fn sceUtilityLoadAvModule(module: AvModule) -> i32; pub fn sceUtilityUnloadAvModule(module: AvModule) -> i32; pub fn sceUtilityLoadUsbModule(module: UsbModule) -> i32; pub fn sceUtilityUnloadUsbModule(module: UsbModule) -> i32; pub fn sceUtilityLoadModule(module: Module) -> i32; pub fn sceUtilityUnloadModule(module: Module) -> i32; pub fn sceUtilityCreateNetParam(conf: i32) -> i32; pub fn sceUtilitySetNetParam(param: NetParam, val: *const c_void) -> i32; pub fn sceUtilityCopyNetParam(src: i32, dest: i32) -> i32; pub fn sceUtilityDeleteNetParam(conf: i32) -> i32; pub fn sceNetInit( poolsize: i32, calloutprio: i32, calloutstack: i32, netintrprio: i32, netintrstack: i32, ) -> i32; pub fn sceNetTerm() -> i32; pub fn sceNetFreeThreadinfo(thid: i32) -> i32; pub fn sceNetThreadAbort(thid: i32) -> i32; pub fn sceNetEtherStrton(name: *mut u8, mac: *mut u8); pub fn sceNetEtherNtostr(mac: *mut u8, name: *mut u8); pub fn sceNetGetLocalEtherAddr(mac: *mut u8) -> i32; pub fn sceNetGetMallocStat(stat: *mut SceNetMallocStat) -> i32; pub fn sceNetAdhocctlInit( stacksize: i32, priority: i32, adhoc_id: *mut SceNetAdhocctlAdhocId, ) -> i32; pub fn sceNetAdhocctlTerm() -> i32; pub fn sceNetAdhocctlConnect(name: *const u8) -> i32; pub fn sceNetAdhocctlDisconnect() -> i32; pub fn sceNetAdhocctlGetState(event: *mut i32) -> i32; pub fn sceNetAdhocctlCreate(name: *const u8) -> i32; pub fn sceNetAdhocctlJoin(scaninfo: *mut SceNetAdhocctlScanInfo) -> i32; pub fn sceNetAdhocctlGetAdhocId(id: *mut SceNetAdhocctlAdhocId) -> i32; pub fn sceNetAdhocctlCreateEnterGameMode( name: *const u8, unknown: i32, num: i32, macs: *mut u8, timeout: u32, unknown2: i32, ) -> i32; pub fn sceNetAdhocctlJoinEnterGameMode( name: *const u8, hostmac: *mut u8, timeout: u32, unknown: i32, ) -> i32; pub fn sceNetAdhocctlGetGameModeInfo(gamemodeinfo: *mut SceNetAdhocctlGameModeInfo) -> i32; pub fn sceNetAdhocctlExitGameMode() -> i32; pub fn sceNetAdhocctlGetPeerList(length: *mut i32, buf: *mut c_void) -> i32; pub fn sceNetAdhocctlGetPeerInfo( mac: *mut u8, size: i32, peerinfo: *mut SceNetAdhocctlPeerInfo, ) -> i32; pub fn sceNetAdhocctlScan() -> i32; pub fn sceNetAdhocctlGetScanInfo(length: *mut i32, buf: *mut c_void) -> i32; pub fn sceNetAdhocctlAddHandler(handler: SceNetAdhocctlHandler, unknown: *mut c_void) -> i32; pub fn sceNetAdhocctlDelHandler(id: i32) -> i32; pub fn sceNetAdhocctlGetNameByAddr(mac: *mut u8, nickname: *mut u8) -> i32; pub fn sceNetAdhocctlGetAddrByName( nickname: *mut u8, length: *mut i32, buf: *mut c_void, ) -> i32; pub fn sceNetAdhocctlGetParameter(params: *mut SceNetAdhocctlParams) -> i32; pub fn sceNetAdhocInit() -> i32; pub fn sceNetAdhocTerm() -> i32; pub fn sceNetAdhocPdpCreate(mac: *mut u8, port: u16, buf_size: u32, unk1: i32) -> i32; pub fn sceNetAdhocPdpDelete(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocPdpSend( id: i32, dest_mac_addr: *mut u8, port: u16, data: *mut c_void, len: u32, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPdpRecv( id: i32, src_mac_addr: *mut u8, port: *mut u16, data: *mut c_void, data_length: *mut c_void, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocGetPdpStat(size: *mut i32, stat: *mut SceNetAdhocPdpStat) -> i32; pub fn sceNetAdhocGameModeCreateMaster(data: *mut c_void, size: i32) -> i32; pub fn sceNetAdhocGameModeCreateReplica(mac: *mut u8, data: *mut c_void, size: i32) -> i32; pub fn sceNetAdhocGameModeUpdateMaster() -> i32; pub fn sceNetAdhocGameModeUpdateReplica(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocGameModeDeleteMaster() -> i32; pub fn sceNetAdhocGameModeDeleteReplica(id: i32) -> i32; pub fn sceNetAdhocPtpOpen( srcmac: *mut u8, srcport: u16, destmac: *mut u8, destport: u16, buf_size: u32, delay: u32, count: i32, unk1: i32, ) -> i32; pub fn sceNetAdhocPtpConnect(id: i32, timeout: u32, nonblock: i32) -> i32; pub fn sceNetAdhocPtpListen( srcmac: *mut u8, srcport: u16, buf_size: u32, delay: u32, count: i32, queue: i32, unk1: i32, ) -> i32; pub fn sceNetAdhocPtpAccept( id: i32, mac: *mut u8, port: *mut u16, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPtpSend( id: i32, data: *mut c_void, data_size: *mut i32, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPtpRecv( id: i32, data: *mut c_void, data_size: *mut i32, timeout: u32, nonblock: i32, ) -> i32; pub fn sceNetAdhocPtpFlush(id: i32, timeout: u32, nonblock: i32) -> i32; pub fn sceNetAdhocPtpClose(id: i32, unk1: i32) -> i32; pub fn sceNetAdhocGetPtpStat(size: *mut i32, stat: *mut SceNetAdhocPtpStat) -> i32; } extern "C" { pub fn sceNetAdhocMatchingInit(memsize: i32) -> i32; pub fn sceNetAdhocMatchingTerm() -> i32; pub fn sceNetAdhocMatchingCreate( mode: AdhocMatchingMode, max_peers: i32, port: u16, buf_size: i32, hello_delay: u32, ping_delay: u32, init_count: i32, msg_delay: u32, callback: AdhocMatchingCallback, ) -> i32; pub fn sceNetAdhocMatchingDelete(matching_id: i32) -> i32; pub fn sceNetAdhocMatchingStart( matching_id: i32, evth_pri: i32, evth_stack: i32, inth_pri: i32, inth_stack: i32, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingStop(matching_id: i32) -> i32; pub fn sceNetAdhocMatchingSelectTarget( matching_id: i32, mac: *mut u8, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingCancelTarget(matching_id: i32, mac: *mut u8) -> i32; pub fn sceNetAdhocMatchingCancelTargetWithOpt( matching_id: i32, mac: *mut u8, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingSendData( matching_id: i32, mac: *mut u8, data_len: i32, data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingAbortSendData(matching_id: i32, mac: *mut u8) -> i32; pub fn sceNetAdhocMatchingSetHelloOpt( matching_id: i32, opt_len: i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingGetHelloOpt( matching_id: i32, opt_len: *mut i32, opt_data: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingGetMembers( matching_id: i32, length: *mut i32, buf: *mut c_void, ) -> i32; pub fn sceNetAdhocMatchingGetPoolMaxAlloc() -> i32; pub fn sceNetAdhocMatchingGetPoolStat(poolstat: *mut AdhocPoolStat) -> i32; } extern "C" { pub fn sceNetApctlInit(stack_size: i32, init_priority: i32) -> i32; pub fn sceNetApctlTerm() -> i32; pub fn sceNetApctlGetInfo(code: ApctlInfo, pinfo: *mut SceNetApctlInfo) -> i32; pub fn sceNetApctlAddHandler(handler: SceNetApctlHandler, parg: *mut c_void) -> i32; pub fn sceNetApctlDelHandler(handler_id: i32) -> i32; pub fn sceNetApctlConnect(conn_index: i32) -> i32; pub fn sceNetApctlDisconnect() -> i32; pub fn sceNetApctlGetState(pstate: *mut ApctlState) -> i32; pub fn sceNetInetInit() -> i32; pub fn sceNetInetTerm() -> i32; pub fn sceNetInetAccept(s: i32, addr: *mut sockaddr, addr_len: *mut socklen_t) -> i32; pub fn sceNetInetBind(s: i32, my_addr: *const sockaddr, addr_len: socklen_t) -> i32; pub fn sceNetInetConnect(s: i32, serv_addr: *const sockaddr, addr_len: socklen_t) -> i32; pub fn sceNetInetGetsockopt( s: i32, level: i32, opt_name: i32, opt_val: *mut c_void, optl_en: *mut socklen_t, ) -> i32; pub fn sceNetInetListen(s: i32, backlog: i32) -> i32; pub fn sceNetInetRecv(s: i32, buf: *mut c_void, len: usize, flags: i32) -> usize; pub fn sceNetInetRecvfrom( s: i32, buf: *mut c_void, flags: usize, arg1: i32, from: *mut sockaddr, from_len: *mut socklen_t, ) -> usize; pub fn sceNetInetSend(s: i32, buf: *const c_void, len: usize, flags: i32) -> usize; pub fn sceNetInetSendto( s: i32, buf: *const c_void, len: usize, flags: i32, to: *const sockaddr, to_len: socklen_t, ) -> usize; pub fn sceNetInetSetsockopt( s: i32, level: i32, opt_name: i32, opt_val: *const c_void, opt_len: socklen_t, ) -> i32; pub fn sceNetInetShutdown(s: i32, how: i32) -> i32; pub fn sceNetInetSocket(domain: i32, type_: i32, protocol: i32) -> i32; pub fn sceNetInetClose(s: i32) -> i32; pub fn sceNetInetGetErrno() -> i32; pub fn sceSslInit(unknown1: i32) -> i32; pub fn sceSslEnd() -> i32; pub fn sceSslGetUsedMemoryMax(memory: *mut u32) -> i32; pub fn sceSslGetUsedMemoryCurrent(memory: *mut u32) -> i32; pub fn sceHttpInit(unknown1: u32) -> i32; pub fn sceHttpEnd() -> i32; pub fn sceHttpCreateTemplate(agent: *mut u8, unknown1: i32, unknown2: i32) -> i32; pub fn sceHttpDeleteTemplate(templateid: i32) -> i32; pub fn sceHttpCreateConnection( templateid: i32, host: *mut u8, unknown1: *mut u8, port: u16, unknown2: i32, ) -> i32; pub fn sceHttpCreateConnectionWithURL(templateid: i32, url: *const u8, unknown1: i32) -> i32; pub fn sceHttpDeleteConnection(connection_id: i32) -> i32; pub fn sceHttpCreateRequest( connection_id: i32, method: HttpMethod, path: *mut u8, content_length: u64, ) -> i32; pub fn sceHttpCreateRequestWithURL( connection_id: i32, method: HttpMethod, url: *mut u8, content_length: u64, ) -> i32; pub fn sceHttpDeleteRequest(request_id: i32) -> i32; pub fn sceHttpSendRequest(request_id: i32, data: *mut c_void, data_size: u32) -> i32; pub fn sceHttpAbortRequest(request_id: i32) -> i32; pub fn sceHttpReadData(request_id: i32, data: *mut c_void, data_size: u32) -> i32; pub fn sceHttpGetContentLength(request_id: i32, content_length: *mut u64) -> i32; pub fn sceHttpGetStatusCode(request_id: i32, status_code: *mut i32) -> i32; pub fn sceHttpSetResolveTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpSetResolveRetry(id: i32, count: i32) -> i32; pub fn sceHttpSetConnectTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpSetSendTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpSetRecvTimeOut(id: i32, timeout: u32) -> i32; pub fn sceHttpEnableKeepAlive(id: i32) -> i32; pub fn sceHttpDisableKeepAlive(id: i32) -> i32; pub fn sceHttpEnableRedirect(id: i32) -> i32; pub fn sceHttpDisableRedirect(id: i32) -> i32; pub fn sceHttpEnableCookie(id: i32) -> i32; pub fn sceHttpDisableCookie(id: i32) -> i32; pub fn sceHttpSaveSystemCookie() -> i32; pub fn sceHttpLoadSystemCookie() -> i32; pub fn sceHttpAddExtraHeader(id: i32, name: *mut u8, value: *mut u8, unknown1: i32) -> i32; pub fn sceHttpDeleteHeader(id: i32, name: *const u8) -> i32; pub fn sceHttpsInit(unknown1: i32, unknown2: i32, unknown3: i32, unknown4: i32) -> i32; pub fn sceHttpsEnd() -> i32; pub fn sceHttpsLoadDefaultCert(unknown1: i32, unknown2: i32) -> i32; pub fn sceHttpDisableAuth(id: i32) -> i32; pub fn sceHttpDisableCache(id: i32) -> i32; pub fn sceHttpEnableAuth(id: i32) -> i32; pub fn sceHttpEnableCache(id: i32) -> i32; pub fn sceHttpEndCache() -> i32; pub fn sceHttpGetAllHeader(request: i32, header: *mut *mut u8, header_size: *mut u32) -> i32; pub fn sceHttpGetNetworkErrno(request: i32, err_num: *mut i32) -> i32; pub fn sceHttpGetProxy( id: i32, activate_flag: *mut i32, mode: *mut i32, proxy_host: *mut u8, len: usize, proxy_port: *mut u16, ) -> i32; pub fn sceHttpInitCache(max_size: usize) -> i32; pub fn sceHttpSetAuthInfoCB(id: i32, cbfunc: HttpPasswordCB) -> i32; pub fn sceHttpSetProxy( id: i32, activate_flag: i32, mode: i32, new_proxy_host: *const u8, new_proxy_port: u16, ) -> i32; pub fn sceHttpSetResHeaderMaxSize(id: i32, header_size: u32) -> i32; pub fn sceHttpSetMallocFunction( malloc_func: HttpMallocFunction, free_func: HttpFreeFunction, realloc_func: HttpReallocFunction, ) -> i32; pub fn sceNetResolverInit() -> i32; pub fn sceNetResolverCreate(rid: *mut i32, buf: *mut c_void, buf_length: u32) -> i32; pub fn sceNetResolverDelete(rid: i32) -> i32; pub fn sceNetResolverStartNtoA( rid: i32, hostname: *const u8, addr: *mut in_addr, timeout: u32, retry: i32, ) -> i32; pub fn sceNetResolverStartAtoN( rid: i32, addr: *const in_addr, hostname: *mut u8, hostname_len: u32, timeout: u32, retry: i32, ) -> i32; pub fn sceNetResolverStop(rid: i32) -> i32; pub fn sceNetResolverTerm() -> i32; } libc/src/hermit/0000775000175000017500000000000014661133735014533 5ustar jamespagejamespagelibc/src/hermit/x86_64.rs0000644000175000017500000000005614661133735016036 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; libc/src/hermit/mod.rs0000644000175000017500000000271014661133735015656 0ustar jamespagejamespage//! Hermit C types definition pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type c_long = i64; pub type c_ulong = u64; pub type wint_t = u32; pub type wctype_t = i64; pub type regoff_t = size_t; pub type off_t = c_long; cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else { // Unknown target_arch } } cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } libc/src/hermit/aarch64.rs0000644000175000017500000000005614661133735016330 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; libc/src/fixed_width_ints.rs0000644000175000017500000001142414661133735017144 0ustar jamespagejamespage//! This module contains type aliases for C's fixed-width integer types . //! //! These aliases are deprecated: use the Rust types instead. #[deprecated(since = "0.2.55", note = "Use i8 instead.")] pub type int8_t = i8; #[deprecated(since = "0.2.55", note = "Use i16 instead.")] pub type int16_t = i16; #[deprecated(since = "0.2.55", note = "Use i32 instead.")] pub type int32_t = i32; #[deprecated(since = "0.2.55", note = "Use i64 instead.")] pub type int64_t = i64; #[deprecated(since = "0.2.55", note = "Use u8 instead.")] pub type uint8_t = u8; #[deprecated(since = "0.2.55", note = "Use u16 instead.")] pub type uint16_t = u16; #[deprecated(since = "0.2.55", note = "Use u32 instead.")] pub type uint32_t = u32; #[deprecated(since = "0.2.55", note = "Use u64 instead.")] pub type uint64_t = u64; cfg_if! { if #[cfg(all(libc_int128, target_arch = "aarch64", not(target_os = "windows")))] { // This introduces partial support for FFI with __int128 and // equivalent types on platforms where Rust's definition is validated // to match the standard C ABI of that platform. // // Rust does not guarantee u128/i128 are sound for FFI, and its // definitions are in fact known to be incompatible. [0] // // However these problems aren't fundamental, and are just platform // inconsistencies. Specifically at the time of this writing: // // * For x64 SysV ABIs (everything but Windows), the types are underaligned. // * For all Windows ABIs, Microsoft doesn't actually officially define __int128, // and as a result different implementations don't actually agree on its ABI. // // But on the other major aarch64 platforms (android, linux, ios, macos) we have // validated that rustc has the right ABI for these types. This is important because // aarch64 uses these types in some fundamental OS types like user_fpsimd_struct, // which represents saved simd registers. // // Any API which uses these types will need to `#[ignore(improper_ctypes)]` // until the upstream rust issue is resolved, but this at least lets us make // progress on platforms where this type is important. // // The list of supported architectures and OSes is intentionally very restricted, // as careful work needs to be done to verify that a particular platform // has a conformant ABI. // // [0]: https://github.com/rust-lang/rust/issues/54341 /// C `__int128` (a GCC extension that's part of many ABIs) pub type __int128 = i128; /// C `unsigned __int128` (a GCC extension that's part of many ABIs) pub type __uint128 = u128; /// C __int128_t (alternate name for [__int128][]) pub type __int128_t = i128; /// C __uint128_t (alternate name for [__uint128][]) pub type __uint128_t = u128; cfg_if! { if #[cfg(libc_underscore_const_names)] { macro_rules! static_assert_eq { ($a:expr, $b:expr) => { const _: [(); $a] = [(); $b]; }; } // NOTE: if you add more platforms to here, you may need to cfg // these consts. They should always match the platform's values // for `sizeof(__int128)` and `_Alignof(__int128)`. const _SIZE_128: usize = 16; const _ALIGN_128: usize = 16; // Since Rust doesn't officially guarantee that these types // have compatible ABIs, we const assert that these values have the // known size/align of the target platform's libc. If rustc ever // tries to regress things, it will cause a compilation error. // // This isn't a bullet-proof solution because e.g. it doesn't // catch the fact that llvm and gcc disagree on how x64 __int128 // is actually *passed* on the stack (clang underaligns it for // the same reason that rustc *never* properly aligns it). static_assert_eq!(core::mem::size_of::<__int128>(), _SIZE_128); static_assert_eq!(core::mem::align_of::<__int128>(), _ALIGN_128); static_assert_eq!(core::mem::size_of::<__uint128>(), _SIZE_128); static_assert_eq!(core::mem::align_of::<__uint128>(), _ALIGN_128); static_assert_eq!(core::mem::size_of::<__int128_t>(), _SIZE_128); static_assert_eq!(core::mem::align_of::<__int128_t>(), _ALIGN_128); static_assert_eq!(core::mem::size_of::<__uint128_t>(), _SIZE_128); static_assert_eq!(core::mem::align_of::<__uint128_t>(), _ALIGN_128); } } } } libc/src/fuchsia/0000775000175000017500000000000014661133735014665 5ustar jamespagejamespagelibc/src/fuchsia/riscv64.rs0000644000175000017500000000222114661133735016526 0ustar jamespagejamespage// From psABI Calling Convention for RV64 pub type c_char = u8; pub type __u64 = ::c_ulonglong; pub type wchar_t = i32; pub type nlink_t = ::c_ulong; pub type blksize_t = ::c_long; pub type stat64 = stat; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 3], } // Not actually used, IPC calls just return ENOSYS pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } } libc/src/fuchsia/x86_64.rs0000644000175000017500000001070614661133735016173 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = ::c_long; pub type __u64 = ::c_ulonglong; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __reserved: [::c_long; 3], } pub struct mcontext_t { __private: [u64; 32], } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __unused1: ::c_long, __unused2: ::c_long } } s_no_extra_traits! { pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: ::sigset_t, __private: [u8; 512], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask && self .__private .iter() .zip(other.__private.iter()) .all(|(a,b)| a == b) } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // FIXME: .field("__private", &self.__private) .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); self.__private.hash(state); } } } } // offsets in user_regs_structs, from sys/reg.h pub const R15: ::c_int = 0; pub const R14: ::c_int = 1; pub const R13: ::c_int = 2; pub const R12: ::c_int = 3; pub const RBP: ::c_int = 4; pub const RBX: ::c_int = 5; pub const R11: ::c_int = 6; pub const R10: ::c_int = 7; pub const R9: ::c_int = 8; pub const R8: ::c_int = 9; pub const RAX: ::c_int = 10; pub const RCX: ::c_int = 11; pub const RDX: ::c_int = 12; pub const RSI: ::c_int = 13; pub const RDI: ::c_int = 14; pub const ORIG_RAX: ::c_int = 15; pub const RIP: ::c_int = 16; pub const CS: ::c_int = 17; pub const EFLAGS: ::c_int = 18; pub const RSP: ::c_int = 19; pub const SS: ::c_int = 20; pub const FS_BASE: ::c_int = 21; pub const GS_BASE: ::c_int = 22; pub const DS: ::c_int = 23; pub const ES: ::c_int = 24; pub const FS: ::c_int = 25; pub const GS: ::c_int = 26; pub const MAP_32BIT: ::c_int = 0x0040; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; libc/src/fuchsia/mod.rs0000644000175000017500000045050014661133735016014 0ustar jamespagejamespage//! Definitions found commonly among almost all Unix derivatives //! //! More functions and definitions can be found in the more specific modules //! according to the platform in question. // PUB_TYPE pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type locale_t = *mut ::c_void; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type pid_t = i32; pub type uid_t = u32; pub type gid_t = u32; pub type in_addr_t = u32; pub type in_port_t = u16; pub type sighandler_t = ::size_t; pub type cc_t = ::c_uchar; pub type sa_family_t = u16; pub type pthread_key_t = ::c_uint; pub type speed_t = ::c_uint; pub type tcflag_t = ::c_uint; pub type clockid_t = ::c_int; pub type key_t = ::c_int; pub type id_t = ::c_uint; pub type useconds_t = u32; pub type dev_t = u64; pub type socklen_t = u32; pub type pthread_t = c_ulong; pub type mode_t = u32; pub type ino64_t = u64; pub type off64_t = i64; pub type blkcnt64_t = i64; pub type rlim64_t = u64; pub type mqd_t = ::c_int; pub type nfds_t = ::c_ulong; pub type nl_item = ::c_int; pub type idtype_t = ::c_uint; pub type loff_t = ::c_longlong; pub type __u8 = ::c_uchar; pub type __u16 = ::c_ushort; pub type __s16 = ::c_short; pub type __u32 = ::c_uint; pub type __s32 = ::c_int; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type clock_t = c_long; pub type time_t = c_long; pub type suseconds_t = c_long; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; pub type shmatt_t = ::c_ulong; pub type msgqnum_t = ::c_ulong; pub type msglen_t = ::c_ulong; pub type fsblkcnt_t = ::c_ulonglong; pub type fsfilcnt_t = ::c_ulonglong; pub type rlim_t = ::c_ulonglong; pub type c_long = i64; pub type c_ulong = u64; // FIXME: why are these uninhabited types? that seems... wrong? // Presumably these should be `()` or an `extern type` (when that stabilizes). #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} impl ::Copy for DIR {} impl ::Clone for DIR { fn clone(&self) -> DIR { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME: fill this out with a struct impl ::Copy for fpos64_t {} impl ::Clone for fpos64_t { fn clone(&self) -> fpos64_t { *self } } // PUB_STRUCT s! { pub struct group { pub gr_name: *mut ::c_char, pub gr_passwd: *mut ::c_char, pub gr_gid: ::gid_t, pub gr_mem: *mut *mut ::c_char, } pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: ::c_long, } // FIXME: the rlimit and rusage related functions and types don't exist // within zircon. Are there reasons for keeping them around? pub struct rlimit { pub rlim_cur: rlim_t, pub rlim_max: rlim_t, } pub struct rusage { pub ru_utime: timeval, pub ru_stime: timeval, pub ru_maxrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad1: u32, pub ru_ixrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad2: u32, pub ru_idrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad3: u32, pub ru_isrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad4: u32, pub ru_minflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad5: u32, pub ru_majflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad6: u32, pub ru_nswap: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad7: u32, pub ru_inblock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad8: u32, pub ru_oublock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad9: u32, pub ru_msgsnd: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad10: u32, pub ru_msgrcv: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad11: u32, pub ru_nsignals: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad12: u32, pub ru_nvcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad13: u32, pub ru_nivcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad14: u32, } pub struct in_addr { pub s_addr: in_addr_t, } pub struct in6_addr { pub s6_addr: [u8; 16], } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::c_int, } pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: ::c_uint, } pub struct hostent { pub h_name: *mut ::c_char, pub h_aliases: *mut *mut ::c_char, pub h_addrtype: ::c_int, pub h_length: ::c_int, pub h_addr_list: *mut *mut ::c_char, } pub struct iovec { pub iov_base: *mut ::c_void, pub iov_len: ::size_t, } pub struct pollfd { pub fd: ::c_int, pub events: ::c_short, pub revents: ::c_short, } pub struct winsize { pub ws_row: ::c_ushort, pub ws_col: ::c_ushort, pub ws_xpixel: ::c_ushort, pub ws_ypixel: ::c_ushort, } pub struct linger { pub l_onoff: ::c_int, pub l_linger: ::c_int, } pub struct sigval { // Actually a union of an int and a void* pub sival_ptr: *mut ::c_void } // pub struct itimerval { pub it_interval: ::timeval, pub it_value: ::timeval, } // pub struct tms { pub tms_utime: ::clock_t, pub tms_stime: ::clock_t, pub tms_cutime: ::clock_t, pub tms_cstime: ::clock_t, } pub struct servent { pub s_name: *mut ::c_char, pub s_aliases: *mut *mut ::c_char, pub s_port: ::c_int, pub s_proto: *mut ::c_char, } pub struct protoent { pub p_name: *mut ::c_char, pub p_aliases: *mut *mut ::c_char, pub p_proto: ::c_int, } pub struct aiocb { pub aio_fildes: ::c_int, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_sigevent: ::sigevent, __td: *mut ::c_void, __lock: [::c_int; 2], __err: ::c_int, __ret: ::ssize_t, pub aio_offset: off_t, __next: *mut ::c_void, __prev: *mut ::c_void, #[cfg(target_pointer_width = "32")] __dummy4: [::c_char; 24], #[cfg(target_pointer_width = "64")] __dummy4: [::c_char; 16], } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], pub __c_ispeed: ::speed_t, pub __c_ospeed: ::speed_t, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct ucred { pub pid: ::pid_t, pub uid: ::uid_t, pub gid: ::gid_t, } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: socklen_t, pub ai_addr: *mut ::sockaddr, pub ai_canonname: *mut c_char, pub ai_next: *mut addrinfo, } pub struct sockaddr_ll { pub sll_family: ::c_ushort, pub sll_protocol: ::c_ushort, pub sll_ifindex: ::c_int, pub sll_hatype: ::c_ushort, pub sll_pkttype: ::c_uchar, pub sll_halen: ::c_uchar, pub sll_addr: [::c_uchar; 8] } pub struct fd_set { fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE], } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, pub tm_gmtoff: ::c_long, pub tm_zone: *const ::c_char, } pub struct sched_param { pub sched_priority: ::c_int, pub sched_ss_low_priority: ::c_int, pub sched_ss_repl_period: ::timespec, pub sched_ss_init_budget: ::timespec, pub sched_ss_max_repl: ::c_int, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct epoll_event { pub events: u32, pub u64: u64, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: ::c_uint, pub ifa_addr: *mut ::sockaddr, pub ifa_netmask: *mut ::sockaddr, pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union pub ifa_data: *mut ::c_void } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct spwd { pub sp_namp: *mut ::c_char, pub sp_pwdp: *mut ::c_char, pub sp_lstchg: ::c_long, pub sp_min: ::c_long, pub sp_max: ::c_long, pub sp_warn: ::c_long, pub sp_inact: ::c_long, pub sp_expire: ::c_long, pub sp_flag: ::c_ulong, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, #[cfg(target_endian = "little")] pub f_fsid: ::c_ulong, #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] __f_unused: ::c_int, #[cfg(target_endian = "big")] pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct dqblk { pub dqb_bhardlimit: u64, pub dqb_bsoftlimit: u64, pub dqb_curspace: u64, pub dqb_ihardlimit: u64, pub dqb_isoftlimit: u64, pub dqb_curinodes: u64, pub dqb_btime: u64, pub dqb_itime: u64, pub dqb_valid: u32, } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: u64, pub ssi_utime: u64, pub ssi_stime: u64, pub ssi_addr: u64, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } pub struct fsid_t { __val: [::c_int; 2], } pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] bits: [u32; 32], #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] bits: [u64; 16], } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } // System V IPC pub struct msginfo { pub msgpool: ::c_int, pub msgmap: ::c_int, pub msgmax: ::c_int, pub msgmnb: ::c_int, pub msgmni: ::c_int, pub msgssz: ::c_int, pub msgtql: ::c_int, pub msgseg: ::c_ushort, } pub struct mmsghdr { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct input_event { pub time: ::timeval, pub type_: ::__u16, pub code: ::__u16, pub value: ::__s32, } pub struct input_id { pub bustype: ::__u16, pub vendor: ::__u16, pub product: ::__u16, pub version: ::__u16, } pub struct input_absinfo { pub value: ::__s32, pub minimum: ::__s32, pub maximum: ::__s32, pub fuzz: ::__s32, pub flat: ::__s32, pub resolution: ::__s32, } pub struct input_keymap_entry { pub flags: ::__u8, pub len: ::__u8, pub index: ::__u16, pub keycode: ::__u32, pub scancode: [::__u8; 32], } pub struct input_mask { pub type_: ::__u32, pub codes_size: ::__u32, pub codes_ptr: ::__u64, } pub struct ff_replay { pub length: ::__u16, pub delay: ::__u16, } pub struct ff_trigger { pub button: ::__u16, pub interval: ::__u16, } pub struct ff_envelope { pub attack_length: ::__u16, pub attack_level: ::__u16, pub fade_length: ::__u16, pub fade_level: ::__u16, } pub struct ff_constant_effect { pub level: ::__s16, pub envelope: ff_envelope, } pub struct ff_ramp_effect { pub start_level: ::__s16, pub end_level: ::__s16, pub envelope: ff_envelope, } pub struct ff_condition_effect { pub right_saturation: ::__u16, pub left_saturation: ::__u16, pub right_coeff: ::__s16, pub left_coeff: ::__s16, pub deadband: ::__u16, pub center: ::__s16, } pub struct ff_periodic_effect { pub waveform: ::__u16, pub period: ::__u16, pub magnitude: ::__s16, pub offset: ::__s16, pub phase: ::__u16, pub envelope: ff_envelope, pub custom_len: ::__u32, pub custom_data: *mut ::__s16, } pub struct ff_rumble_effect { pub strong_magnitude: ::__u16, pub weak_magnitude: ::__u16, } pub struct ff_effect { pub type_: ::__u16, pub id: ::__s16, pub direction: ::__u16, pub trigger: ff_trigger, pub replay: ff_replay, // FIXME this is actually a union #[cfg(target_pointer_width = "64")] pub u: [u64; 4], #[cfg(target_pointer_width = "32")] pub u: [u32; 7], } pub struct dl_phdr_info { #[cfg(target_pointer_width = "64")] pub dlpi_addr: Elf64_Addr, #[cfg(target_pointer_width = "32")] pub dlpi_addr: Elf32_Addr, pub dlpi_name: *const ::c_char, #[cfg(target_pointer_width = "64")] pub dlpi_phdr: *const Elf64_Phdr, #[cfg(target_pointer_width = "32")] pub dlpi_phdr: *const Elf32_Phdr, #[cfg(target_pointer_width = "64")] pub dlpi_phnum: Elf64_Half, #[cfg(target_pointer_width = "32")] pub dlpi_phnum: Elf32_Half, pub dlpi_adds: ::c_ulonglong, pub dlpi_subs: ::c_ulonglong, pub dlpi_tls_modid: ::size_t, pub dlpi_tls_data: *mut ::c_void, } pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct pthread_attr_t { __size: [u64; 7] } pub struct sigset_t { __val: [::c_ulong; 16], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, __pad1: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, __pad2: ::socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub __pad1: ::c_int, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct sem_t { __val: [::c_int; 8], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct termios2 { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; 19], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } pub struct in6_pktinfo { pub ipi6_addr: ::in6_addr, pub ipi6_ifindex: ::c_uint, } } s_no_extra_traits! { pub struct sysinfo { pub uptime: ::c_ulong, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub __reserved: [::c_char; 256], } pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [::c_char; 108] } pub struct sockaddr_storage { pub ss_family: sa_family_t, __ss_pad2: [u8; 128 - 2 - 8], __ss_align: ::size_t, } pub struct utsname { pub sysname: [::c_char; 65], pub nodename: [::c_char; 65], pub release: [::c_char; 65], pub version: [::c_char; 65], pub machine: [::c_char; 65], pub domainname: [::c_char; 65] } pub struct dirent { pub d_ino: ::ino_t, pub d_off: ::off_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } pub struct dirent64 { pub d_ino: ::ino64_t, pub d_off: ::off64_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } // x32 compatibility // See https://sourceware.org/bugzilla/show_bug.cgi?id=21279 pub struct mq_attr { #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_flags: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_maxmsg: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_msgsize: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_curmsgs: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pad: [i64; 4], #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_flags: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_maxmsg: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_msgsize: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_curmsgs: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pad: [::c_long; 4], } pub struct sockaddr_nl { pub nl_family: ::sa_family_t, nl_pad: ::c_ushort, pub nl_pid: u32, pub nl_groups: u32 } pub struct sigevent { pub sigev_value: ::sigval, pub sigev_signo: ::c_int, pub sigev_notify: ::c_int, pub sigev_notify_function: fn(::sigval), pub sigev_notify_attributes: *mut pthread_attr_t, pub __pad: [::c_char; 56 - 3 * 8 /* 8 == sizeof(long) */], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sysinfo { fn eq(&self, other: &sysinfo) -> bool { self.uptime == other.uptime && self.loads == other.loads && self.totalram == other.totalram && self.freeram == other.freeram && self.sharedram == other.sharedram && self.bufferram == other.bufferram && self.totalswap == other.totalswap && self.freeswap == other.freeswap && self.procs == other.procs && self.pad == other.pad && self.totalhigh == other.totalhigh && self.freehigh == other.freehigh && self.mem_unit == other.mem_unit && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a,b)| a == b) } } impl Eq for sysinfo {} impl ::fmt::Debug for sysinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sysinfo") .field("uptime", &self.uptime) .field("loads", &self.loads) .field("totalram", &self.totalram) .field("freeram", &self.freeram) .field("sharedram", &self.sharedram) .field("bufferram", &self.bufferram) .field("totalswap", &self.totalswap) .field("freeswap", &self.freeswap) .field("procs", &self.procs) .field("pad", &self.pad) .field("totalhigh", &self.totalhigh) .field("freehigh", &self.freehigh) .field("mem_unit", &self.mem_unit) // FIXME: .field("__reserved", &self.__reserved) .finish() } } impl ::hash::Hash for sysinfo { fn hash(&self, state: &mut H) { self.uptime.hash(state); self.loads.hash(state); self.totalram.hash(state); self.freeram.hash(state); self.sharedram.hash(state); self.bufferram.hash(state); self.totalswap.hash(state); self.freeswap.hash(state); self.procs.hash(state); self.pad.hash(state); self.totalhigh.hash(state); self.freehigh.hash(state); self.mem_unit.hash(state); self.__reserved.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_un {} impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl ::hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_align", &self.__ss_align) // FIXME: .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a,b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a,b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a,b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a,b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a,b)| a == b) } } impl Eq for utsname {} impl ::fmt::Debug for utsname { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utsname") // FIXME: .field("sysname", &self.sysname) // FIXME: .field("nodename", &self.nodename) // FIXME: .field("release", &self.release) // FIXME: .field("version", &self.version) // FIXME: .field("machine", &self.machine) .finish() } } impl ::hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for dirent64 { fn eq(&self, other: &dirent64) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent64 {} impl ::fmt::Debug for dirent64 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent64") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent64 { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl ::fmt::Debug for mq_attr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl ::hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } impl PartialEq for sockaddr_nl { fn eq(&self, other: &sockaddr_nl) -> bool { self.nl_family == other.nl_family && self.nl_pid == other.nl_pid && self.nl_groups == other.nl_groups } } impl Eq for sockaddr_nl {} impl ::fmt::Debug for sockaddr_nl { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_nl") .field("nl_family", &self.nl_family) .field("nl_pid", &self.nl_pid) .field("nl_groups", &self.nl_groups) .finish() } } impl ::hash::Hash for sockaddr_nl { fn hash(&self, state: &mut H) { self.nl_family.hash(state); self.nl_pid.hash(state); self.nl_groups.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_value == other.sigev_value && self.sigev_signo == other.sigev_signo && self.sigev_notify == other.sigev_notify && self.sigev_notify_function == other.sigev_notify_function && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_value", &self.sigev_value) .field("sigev_signo", &self.sigev_signo) .field("sigev_notify", &self.sigev_notify) .field("sigev_notify_function", &self.sigev_notify_function) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_value.hash(state); self.sigev_signo.hash(state); self.sigev_notify.hash(state); self.sigev_notify_function.hash(state); self.sigev_notify_attributes.hash(state); } } } } // PUB_CONST pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const SIG_DFL: sighandler_t = 0 as sighandler_t; pub const SIG_IGN: sighandler_t = 1 as sighandler_t; pub const SIG_ERR: sighandler_t = !0 as sighandler_t; pub const DT_UNKNOWN: u8 = 0; pub const DT_FIFO: u8 = 1; pub const DT_CHR: u8 = 2; pub const DT_DIR: u8 = 4; pub const DT_BLK: u8 = 6; pub const DT_REG: u8 = 8; pub const DT_LNK: u8 = 10; pub const DT_SOCK: u8 = 12; pub const FD_CLOEXEC: ::c_int = 0x1; pub const USRQUOTA: ::c_int = 0; pub const GRPQUOTA: ::c_int = 1; pub const SIGIOT: ::c_int = 6; pub const S_ISUID: ::c_int = 0x800; pub const S_ISGID: ::c_int = 0x400; pub const S_ISVTX: ::c_int = 0x200; pub const IF_NAMESIZE: ::size_t = 16; pub const IFNAMSIZ: ::size_t = IF_NAMESIZE; pub const LOG_EMERG: ::c_int = 0; pub const LOG_ALERT: ::c_int = 1; pub const LOG_CRIT: ::c_int = 2; pub const LOG_ERR: ::c_int = 3; pub const LOG_WARNING: ::c_int = 4; pub const LOG_NOTICE: ::c_int = 5; pub const LOG_INFO: ::c_int = 6; pub const LOG_DEBUG: ::c_int = 7; pub const LOG_KERN: ::c_int = 0; pub const LOG_USER: ::c_int = 1 << 3; pub const LOG_MAIL: ::c_int = 2 << 3; pub const LOG_DAEMON: ::c_int = 3 << 3; pub const LOG_AUTH: ::c_int = 4 << 3; pub const LOG_SYSLOG: ::c_int = 5 << 3; pub const LOG_LPR: ::c_int = 6 << 3; pub const LOG_NEWS: ::c_int = 7 << 3; pub const LOG_UUCP: ::c_int = 8 << 3; pub const LOG_LOCAL0: ::c_int = 16 << 3; pub const LOG_LOCAL1: ::c_int = 17 << 3; pub const LOG_LOCAL2: ::c_int = 18 << 3; pub const LOG_LOCAL3: ::c_int = 19 << 3; pub const LOG_LOCAL4: ::c_int = 20 << 3; pub const LOG_LOCAL5: ::c_int = 21 << 3; pub const LOG_LOCAL6: ::c_int = 22 << 3; pub const LOG_LOCAL7: ::c_int = 23 << 3; pub const LOG_PID: ::c_int = 0x01; pub const LOG_CONS: ::c_int = 0x02; pub const LOG_ODELAY: ::c_int = 0x04; pub const LOG_NDELAY: ::c_int = 0x08; pub const LOG_NOWAIT: ::c_int = 0x10; pub const LOG_PRIMASK: ::c_int = 7; pub const LOG_FACMASK: ::c_int = 0x3f8; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; pub const PRIO_MIN: ::c_int = -20; pub const PRIO_MAX: ::c_int = 20; pub const IPPROTO_ICMP: ::c_int = 1; pub const IPPROTO_ICMPV6: ::c_int = 58; pub const IPPROTO_TCP: ::c_int = 6; pub const IPPROTO_UDP: ::c_int = 17; pub const IPPROTO_IP: ::c_int = 0; pub const IPPROTO_IPV6: ::c_int = 41; pub const INADDR_LOOPBACK: in_addr_t = 2130706433; pub const INADDR_ANY: in_addr_t = 0; pub const INADDR_BROADCAST: in_addr_t = 4294967295; pub const INADDR_NONE: in_addr_t = 4294967295; pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 2147483647; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 2; pub const _IOLBF: ::c_int = 1; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; // Linux-specific fcntls pub const F_SETLEASE: ::c_int = 1024; pub const F_GETLEASE: ::c_int = 1025; pub const F_NOTIFY: ::c_int = 1026; pub const F_CANCELLK: ::c_int = 1029; pub const F_DUPFD_CLOEXEC: ::c_int = 1030; pub const F_SETPIPE_SZ: ::c_int = 1031; pub const F_GETPIPE_SZ: ::c_int = 1032; pub const F_ADD_SEALS: ::c_int = 1033; pub const F_GET_SEALS: ::c_int = 1034; pub const F_SEAL_SEAL: ::c_int = 0x0001; pub const F_SEAL_SHRINK: ::c_int = 0x0002; pub const F_SEAL_GROW: ::c_int = 0x0004; pub const F_SEAL_WRITE: ::c_int = 0x0008; // FIXME(#235): Include file sealing fcntls once we have a way to verify them. pub const SIGTRAP: ::c_int = 5; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; pub const CLOCK_REALTIME: ::clockid_t = 0; pub const CLOCK_MONOTONIC: ::clockid_t = 1; pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3; pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4; pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5; pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6; pub const CLOCK_BOOTTIME: ::clockid_t = 7; pub const CLOCK_REALTIME_ALARM: ::clockid_t = 8; pub const CLOCK_BOOTTIME_ALARM: ::clockid_t = 9; pub const CLOCK_SGI_CYCLE: ::clockid_t = 10; pub const CLOCK_TAI: ::clockid_t = 11; pub const TIMER_ABSTIME: ::c_int = 1; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_LOCKS: ::c_int = 10; pub const RLIMIT_SIGPENDING: ::c_int = 11; pub const RLIMIT_MSGQUEUE: ::c_int = 12; pub const RLIMIT_NICE: ::c_int = 13; pub const RLIMIT_RTPRIO: ::c_int = 14; pub const RUSAGE_SELF: ::c_int = 0; pub const O_RDONLY: ::c_int = 0; pub const O_WRONLY: ::c_int = 1; pub const O_RDWR: ::c_int = 2; pub const S_IFIFO: ::mode_t = 4096; pub const S_IFCHR: ::mode_t = 8192; pub const S_IFBLK: ::mode_t = 24576; pub const S_IFDIR: ::mode_t = 16384; pub const S_IFREG: ::mode_t = 32768; pub const S_IFLNK: ::mode_t = 40960; pub const S_IFSOCK: ::mode_t = 49152; pub const S_IFMT: ::mode_t = 61440; pub const S_IRWXU: ::mode_t = 448; pub const S_IXUSR: ::mode_t = 64; pub const S_IWUSR: ::mode_t = 128; pub const S_IRUSR: ::mode_t = 256; pub const S_IRWXG: ::mode_t = 56; pub const S_IXGRP: ::mode_t = 8; pub const S_IWGRP: ::mode_t = 16; pub const S_IRGRP: ::mode_t = 32; pub const S_IRWXO: ::mode_t = 7; pub const S_IXOTH: ::mode_t = 1; pub const S_IWOTH: ::mode_t = 2; pub const S_IROTH: ::mode_t = 4; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const LC_CTYPE: ::c_int = 0; pub const LC_NUMERIC: ::c_int = 1; pub const LC_TIME: ::c_int = 2; pub const LC_COLLATE: ::c_int = 3; pub const LC_MONETARY: ::c_int = 4; pub const LC_MESSAGES: ::c_int = 5; pub const LC_ALL: ::c_int = 6; pub const LC_CTYPE_MASK: ::c_int = 1 << LC_CTYPE; pub const LC_NUMERIC_MASK: ::c_int = 1 << LC_NUMERIC; pub const LC_TIME_MASK: ::c_int = 1 << LC_TIME; pub const LC_COLLATE_MASK: ::c_int = 1 << LC_COLLATE; pub const LC_MONETARY_MASK: ::c_int = 1 << LC_MONETARY; pub const LC_MESSAGES_MASK: ::c_int = 1 << LC_MESSAGES; // LC_ALL_MASK defined per platform pub const MAP_FILE: ::c_int = 0x0000; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; // MS_ flags for msync(2) pub const MS_ASYNC: ::c_int = 0x0001; pub const MS_INVALIDATE: ::c_int = 0x0002; pub const MS_SYNC: ::c_int = 0x0004; // MS_ flags for mount(2) pub const MS_RDONLY: ::c_ulong = 0x01; pub const MS_NOSUID: ::c_ulong = 0x02; pub const MS_NODEV: ::c_ulong = 0x04; pub const MS_NOEXEC: ::c_ulong = 0x08; pub const MS_SYNCHRONOUS: ::c_ulong = 0x10; pub const MS_REMOUNT: ::c_ulong = 0x20; pub const MS_MANDLOCK: ::c_ulong = 0x40; pub const MS_DIRSYNC: ::c_ulong = 0x80; pub const MS_NOATIME: ::c_ulong = 0x0400; pub const MS_NODIRATIME: ::c_ulong = 0x0800; pub const MS_BIND: ::c_ulong = 0x1000; pub const MS_MOVE: ::c_ulong = 0x2000; pub const MS_REC: ::c_ulong = 0x4000; pub const MS_SILENT: ::c_ulong = 0x8000; pub const MS_POSIXACL: ::c_ulong = 0x010000; pub const MS_UNBINDABLE: ::c_ulong = 0x020000; pub const MS_PRIVATE: ::c_ulong = 0x040000; pub const MS_SLAVE: ::c_ulong = 0x080000; pub const MS_SHARED: ::c_ulong = 0x100000; pub const MS_RELATIME: ::c_ulong = 0x200000; pub const MS_KERNMOUNT: ::c_ulong = 0x400000; pub const MS_I_VERSION: ::c_ulong = 0x800000; pub const MS_STRICTATIME: ::c_ulong = 0x1000000; pub const MS_ACTIVE: ::c_ulong = 0x40000000; pub const MS_NOUSER: ::c_ulong = 0x80000000; pub const MS_MGC_VAL: ::c_ulong = 0xc0ed0000; pub const MS_MGC_MSK: ::c_ulong = 0xffff0000; pub const MS_RMT_MASK: ::c_ulong = 0x800051; pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EWOULDBLOCK: ::c_int = EAGAIN; pub const SCM_RIGHTS: ::c_int = 0x01; pub const SCM_CREDENTIALS: ::c_int = 0x02; pub const PROT_GROWSDOWN: ::c_int = 0x1000000; pub const PROT_GROWSUP: ::c_int = 0x2000000; pub const MAP_TYPE: ::c_int = 0x000f; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const MADV_FREE: ::c_int = 8; pub const MADV_REMOVE: ::c_int = 9; pub const MADV_DONTFORK: ::c_int = 10; pub const MADV_DOFORK: ::c_int = 11; pub const MADV_MERGEABLE: ::c_int = 12; pub const MADV_UNMERGEABLE: ::c_int = 13; pub const MADV_HUGEPAGE: ::c_int = 14; pub const MADV_NOHUGEPAGE: ::c_int = 15; pub const MADV_DONTDUMP: ::c_int = 16; pub const MADV_DODUMP: ::c_int = 17; pub const MADV_HWPOISON: ::c_int = 100; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const IFF_UP: ::c_int = 0x1; pub const IFF_BROADCAST: ::c_int = 0x2; pub const IFF_DEBUG: ::c_int = 0x4; pub const IFF_LOOPBACK: ::c_int = 0x8; pub const IFF_POINTOPOINT: ::c_int = 0x10; pub const IFF_NOTRAILERS: ::c_int = 0x20; pub const IFF_RUNNING: ::c_int = 0x40; pub const IFF_NOARP: ::c_int = 0x80; pub const IFF_PROMISC: ::c_int = 0x100; pub const IFF_ALLMULTI: ::c_int = 0x200; pub const IFF_MASTER: ::c_int = 0x400; pub const IFF_SLAVE: ::c_int = 0x800; pub const IFF_MULTICAST: ::c_int = 0x1000; pub const IFF_PORTSEL: ::c_int = 0x2000; pub const IFF_AUTOMEDIA: ::c_int = 0x4000; pub const IFF_DYNAMIC: ::c_int = 0x8000; pub const IFF_TUN: ::c_int = 0x0001; pub const IFF_TAP: ::c_int = 0x0002; pub const IFF_NO_PI: ::c_int = 0x1000; pub const SOL_IP: ::c_int = 0; pub const SOL_TCP: ::c_int = 6; pub const SOL_UDP: ::c_int = 17; pub const SOL_IPV6: ::c_int = 41; pub const SOL_ICMPV6: ::c_int = 58; pub const SOL_RAW: ::c_int = 255; pub const SOL_DECNET: ::c_int = 261; pub const SOL_X25: ::c_int = 262; pub const SOL_PACKET: ::c_int = 263; pub const SOL_ATM: ::c_int = 264; pub const SOL_AAL: ::c_int = 265; pub const SOL_IRDA: ::c_int = 266; pub const SOL_NETBEUI: ::c_int = 267; pub const SOL_LLC: ::c_int = 268; pub const SOL_DCCP: ::c_int = 269; pub const SOL_NETLINK: ::c_int = 270; pub const SOL_TIPC: ::c_int = 271; pub const AF_UNSPEC: ::c_int = 0; pub const AF_UNIX: ::c_int = 1; pub const AF_LOCAL: ::c_int = 1; pub const AF_INET: ::c_int = 2; pub const AF_AX25: ::c_int = 3; pub const AF_IPX: ::c_int = 4; pub const AF_APPLETALK: ::c_int = 5; pub const AF_NETROM: ::c_int = 6; pub const AF_BRIDGE: ::c_int = 7; pub const AF_ATMPVC: ::c_int = 8; pub const AF_X25: ::c_int = 9; pub const AF_INET6: ::c_int = 10; pub const AF_ROSE: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_NETBEUI: ::c_int = 13; pub const AF_SECURITY: ::c_int = 14; pub const AF_KEY: ::c_int = 15; pub const AF_NETLINK: ::c_int = 16; pub const AF_ROUTE: ::c_int = AF_NETLINK; pub const AF_PACKET: ::c_int = 17; pub const AF_ASH: ::c_int = 18; pub const AF_ECONET: ::c_int = 19; pub const AF_ATMSVC: ::c_int = 20; pub const AF_RDS: ::c_int = 21; pub const AF_SNA: ::c_int = 22; pub const AF_IRDA: ::c_int = 23; pub const AF_PPPOX: ::c_int = 24; pub const AF_WANPIPE: ::c_int = 25; pub const AF_LLC: ::c_int = 26; pub const AF_CAN: ::c_int = 29; pub const AF_TIPC: ::c_int = 30; pub const AF_BLUETOOTH: ::c_int = 31; pub const AF_IUCV: ::c_int = 32; pub const AF_RXRPC: ::c_int = 33; pub const AF_ISDN: ::c_int = 34; pub const AF_PHONET: ::c_int = 35; pub const AF_IEEE802154: ::c_int = 36; pub const AF_CAIF: ::c_int = 37; pub const AF_ALG: ::c_int = 38; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_UNIX: ::c_int = AF_UNIX; pub const PF_LOCAL: ::c_int = AF_LOCAL; pub const PF_INET: ::c_int = AF_INET; pub const PF_AX25: ::c_int = AF_AX25; pub const PF_IPX: ::c_int = AF_IPX; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_NETROM: ::c_int = AF_NETROM; pub const PF_BRIDGE: ::c_int = AF_BRIDGE; pub const PF_ATMPVC: ::c_int = AF_ATMPVC; pub const PF_X25: ::c_int = AF_X25; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_ROSE: ::c_int = AF_ROSE; pub const PF_DECnet: ::c_int = AF_DECnet; pub const PF_NETBEUI: ::c_int = AF_NETBEUI; pub const PF_SECURITY: ::c_int = AF_SECURITY; pub const PF_KEY: ::c_int = AF_KEY; pub const PF_NETLINK: ::c_int = AF_NETLINK; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_PACKET: ::c_int = AF_PACKET; pub const PF_ASH: ::c_int = AF_ASH; pub const PF_ECONET: ::c_int = AF_ECONET; pub const PF_ATMSVC: ::c_int = AF_ATMSVC; pub const PF_RDS: ::c_int = AF_RDS; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_IRDA: ::c_int = AF_IRDA; pub const PF_PPPOX: ::c_int = AF_PPPOX; pub const PF_WANPIPE: ::c_int = AF_WANPIPE; pub const PF_LLC: ::c_int = AF_LLC; pub const PF_CAN: ::c_int = AF_CAN; pub const PF_TIPC: ::c_int = AF_TIPC; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const PF_IUCV: ::c_int = AF_IUCV; pub const PF_RXRPC: ::c_int = AF_RXRPC; pub const PF_ISDN: ::c_int = AF_ISDN; pub const PF_PHONET: ::c_int = AF_PHONET; pub const PF_IEEE802154: ::c_int = AF_IEEE802154; pub const PF_CAIF: ::c_int = AF_CAIF; pub const PF_ALG: ::c_int = AF_ALG; pub const SOMAXCONN: ::c_int = 128; pub const MSG_OOB: ::c_int = 1; pub const MSG_PEEK: ::c_int = 2; pub const MSG_DONTROUTE: ::c_int = 4; pub const MSG_CTRUNC: ::c_int = 8; pub const MSG_TRUNC: ::c_int = 0x20; pub const MSG_DONTWAIT: ::c_int = 0x40; pub const MSG_EOR: ::c_int = 0x80; pub const MSG_WAITALL: ::c_int = 0x100; pub const MSG_FIN: ::c_int = 0x200; pub const MSG_SYN: ::c_int = 0x400; pub const MSG_CONFIRM: ::c_int = 0x800; pub const MSG_RST: ::c_int = 0x1000; pub const MSG_ERRQUEUE: ::c_int = 0x2000; pub const MSG_NOSIGNAL: ::c_int = 0x4000; pub const MSG_MORE: ::c_int = 0x8000; pub const MSG_WAITFORONE: ::c_int = 0x10000; pub const MSG_FASTOPEN: ::c_int = 0x20000000; pub const MSG_CMSG_CLOEXEC: ::c_int = 0x40000000; pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const IP_TOS: ::c_int = 1; pub const IP_TTL: ::c_int = 2; pub const IP_HDRINCL: ::c_int = 3; pub const IP_RECVTOS: ::c_int = 13; pub const IP_FREEBIND: ::c_int = 15; pub const IP_TRANSPARENT: ::c_int = 19; pub const IP_MULTICAST_IF: ::c_int = 32; pub const IP_MULTICAST_TTL: ::c_int = 33; pub const IP_MULTICAST_LOOP: ::c_int = 34; pub const IP_ADD_MEMBERSHIP: ::c_int = 35; pub const IP_DROP_MEMBERSHIP: ::c_int = 36; pub const IPV6_UNICAST_HOPS: ::c_int = 16; pub const IPV6_MULTICAST_IF: ::c_int = 17; pub const IPV6_MULTICAST_HOPS: ::c_int = 18; pub const IPV6_MULTICAST_LOOP: ::c_int = 19; pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20; pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21; pub const IPV6_V6ONLY: ::c_int = 26; pub const IPV6_RECVPKTINFO: ::c_int = 49; pub const IPV6_RECVTCLASS: ::c_int = 66; pub const IPV6_TCLASS: ::c_int = 67; pub const TCP_NODELAY: ::c_int = 1; pub const TCP_MAXSEG: ::c_int = 2; pub const TCP_CORK: ::c_int = 3; pub const TCP_KEEPIDLE: ::c_int = 4; pub const TCP_KEEPINTVL: ::c_int = 5; pub const TCP_KEEPCNT: ::c_int = 6; pub const TCP_SYNCNT: ::c_int = 7; pub const TCP_LINGER2: ::c_int = 8; pub const TCP_DEFER_ACCEPT: ::c_int = 9; pub const TCP_WINDOW_CLAMP: ::c_int = 10; pub const TCP_INFO: ::c_int = 11; pub const TCP_QUICKACK: ::c_int = 12; pub const TCP_CONGESTION: ::c_int = 13; pub const SO_DEBUG: ::c_int = 1; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 2; pub const PATH_MAX: ::c_int = 4096; pub const FD_SETSIZE: usize = 1024; pub const EPOLLIN: ::c_int = 0x1; pub const EPOLLPRI: ::c_int = 0x2; pub const EPOLLOUT: ::c_int = 0x4; pub const EPOLLRDNORM: ::c_int = 0x40; pub const EPOLLRDBAND: ::c_int = 0x80; pub const EPOLLWRNORM: ::c_int = 0x100; pub const EPOLLWRBAND: ::c_int = 0x200; pub const EPOLLMSG: ::c_int = 0x400; pub const EPOLLERR: ::c_int = 0x8; pub const EPOLLHUP: ::c_int = 0x10; pub const EPOLLET: ::c_int = 0x80000000; pub const EPOLL_CTL_ADD: ::c_int = 1; pub const EPOLL_CTL_MOD: ::c_int = 3; pub const EPOLL_CTL_DEL: ::c_int = 2; pub const MNT_DETACH: ::c_int = 0x2; pub const MNT_EXPIRE: ::c_int = 0x4; pub const Q_GETFMT: ::c_int = 0x800004; pub const Q_GETINFO: ::c_int = 0x800005; pub const Q_SETINFO: ::c_int = 0x800006; pub const QIF_BLIMITS: u32 = 1; pub const QIF_SPACE: u32 = 2; pub const QIF_ILIMITS: u32 = 4; pub const QIF_INODES: u32 = 8; pub const QIF_BTIME: u32 = 16; pub const QIF_ITIME: u32 = 32; pub const QIF_LIMITS: u32 = 5; pub const QIF_USAGE: u32 = 10; pub const QIF_TIMES: u32 = 48; pub const QIF_ALL: u32 = 63; pub const MNT_FORCE: ::c_int = 0x1; pub const Q_SYNC: ::c_int = 0x800001; pub const Q_QUOTAON: ::c_int = 0x800002; pub const Q_QUOTAOFF: ::c_int = 0x800003; pub const Q_GETQUOTA: ::c_int = 0x800007; pub const Q_SETQUOTA: ::c_int = 0x800008; pub const TCIOFF: ::c_int = 2; pub const TCION: ::c_int = 3; pub const TCOOFF: ::c_int = 0; pub const TCOON: ::c_int = 1; pub const TCIFLUSH: ::c_int = 0; pub const TCOFLUSH: ::c_int = 1; pub const TCIOFLUSH: ::c_int = 2; pub const NL0: ::c_int = 0x00000000; pub const NL1: ::c_int = 0x00000100; pub const TAB0: ::c_int = 0x00000000; pub const CR0: ::c_int = 0x00000000; pub const FF0: ::c_int = 0x00000000; pub const BS0: ::c_int = 0x00000000; pub const VT0: ::c_int = 0x00000000; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VLNEXT: usize = 15; pub const IGNBRK: ::tcflag_t = 0x00000001; pub const BRKINT: ::tcflag_t = 0x00000002; pub const IGNPAR: ::tcflag_t = 0x00000004; pub const PARMRK: ::tcflag_t = 0x00000008; pub const INPCK: ::tcflag_t = 0x00000010; pub const ISTRIP: ::tcflag_t = 0x00000020; pub const INLCR: ::tcflag_t = 0x00000040; pub const IGNCR: ::tcflag_t = 0x00000080; pub const ICRNL: ::tcflag_t = 0x00000100; pub const IXANY: ::tcflag_t = 0x00000800; pub const IMAXBEL: ::tcflag_t = 0x00002000; pub const OPOST: ::tcflag_t = 0x1; pub const CS5: ::tcflag_t = 0x00000000; pub const CRTSCTS: ::tcflag_t = 0x80000000; pub const ECHO: ::tcflag_t = 0x00000008; pub const OCRNL: ::tcflag_t = 0o000010; pub const ONOCR: ::tcflag_t = 0o000020; pub const ONLRET: ::tcflag_t = 0o000040; pub const OFILL: ::tcflag_t = 0o000100; pub const OFDEL: ::tcflag_t = 0o000200; pub const CLONE_VM: ::c_int = 0x100; pub const CLONE_FS: ::c_int = 0x200; pub const CLONE_FILES: ::c_int = 0x400; pub const CLONE_SIGHAND: ::c_int = 0x800; pub const CLONE_PTRACE: ::c_int = 0x2000; pub const CLONE_VFORK: ::c_int = 0x4000; pub const CLONE_PARENT: ::c_int = 0x8000; pub const CLONE_THREAD: ::c_int = 0x10000; pub const CLONE_NEWNS: ::c_int = 0x20000; pub const CLONE_SYSVSEM: ::c_int = 0x40000; pub const CLONE_SETTLS: ::c_int = 0x80000; pub const CLONE_PARENT_SETTID: ::c_int = 0x100000; pub const CLONE_CHILD_CLEARTID: ::c_int = 0x200000; pub const CLONE_DETACHED: ::c_int = 0x400000; pub const CLONE_UNTRACED: ::c_int = 0x800000; pub const CLONE_CHILD_SETTID: ::c_int = 0x01000000; pub const CLONE_NEWUTS: ::c_int = 0x04000000; pub const CLONE_NEWIPC: ::c_int = 0x08000000; pub const CLONE_NEWUSER: ::c_int = 0x10000000; pub const CLONE_NEWPID: ::c_int = 0x20000000; pub const CLONE_NEWNET: ::c_int = 0x40000000; pub const CLONE_IO: ::c_int = 0x80000000; pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; pub const WNOHANG: ::c_int = 0x00000001; pub const WUNTRACED: ::c_int = 0x00000002; pub const WSTOPPED: ::c_int = WUNTRACED; pub const WEXITED: ::c_int = 0x00000004; pub const WCONTINUED: ::c_int = 0x00000008; pub const WNOWAIT: ::c_int = 0x01000000; // ::Options set using PTRACE_SETOPTIONS. pub const PTRACE_O_TRACESYSGOOD: ::c_int = 0x00000001; pub const PTRACE_O_TRACEFORK: ::c_int = 0x00000002; pub const PTRACE_O_TRACEVFORK: ::c_int = 0x00000004; pub const PTRACE_O_TRACECLONE: ::c_int = 0x00000008; pub const PTRACE_O_TRACEEXEC: ::c_int = 0x00000010; pub const PTRACE_O_TRACEVFORKDONE: ::c_int = 0x00000020; pub const PTRACE_O_TRACEEXIT: ::c_int = 0x00000040; pub const PTRACE_O_TRACESECCOMP: ::c_int = 0x00000080; pub const PTRACE_O_EXITKILL: ::c_int = 0x00100000; pub const PTRACE_O_SUSPEND_SECCOMP: ::c_int = 0x00200000; pub const PTRACE_O_MASK: ::c_int = 0x003000ff; // Wait extended result codes for the above trace options. pub const PTRACE_EVENT_FORK: ::c_int = 1; pub const PTRACE_EVENT_VFORK: ::c_int = 2; pub const PTRACE_EVENT_CLONE: ::c_int = 3; pub const PTRACE_EVENT_EXEC: ::c_int = 4; pub const PTRACE_EVENT_VFORK_DONE: ::c_int = 5; pub const PTRACE_EVENT_EXIT: ::c_int = 6; pub const PTRACE_EVENT_SECCOMP: ::c_int = 7; // PTRACE_EVENT_STOP was added to glibc in 2.26 // pub const PTRACE_EVENT_STOP: ::c_int = 128; pub const __WNOTHREAD: ::c_int = 0x20000000; pub const __WALL: ::c_int = 0x40000000; pub const __WCLONE: ::c_int = 0x80000000; pub const SPLICE_F_MOVE: ::c_uint = 0x01; pub const SPLICE_F_NONBLOCK: ::c_uint = 0x02; pub const SPLICE_F_MORE: ::c_uint = 0x04; pub const SPLICE_F_GIFT: ::c_uint = 0x08; pub const RTLD_LOCAL: ::c_int = 0; pub const RTLD_LAZY: ::c_int = 1; pub const POSIX_FADV_NORMAL: ::c_int = 0; pub const POSIX_FADV_RANDOM: ::c_int = 1; pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_FADV_WILLNEED: ::c_int = 3; pub const AT_FDCWD: ::c_int = -100; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x100; pub const AT_REMOVEDIR: ::c_int = 0x200; pub const AT_EACCESS: ::c_int = 0x200; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; pub const AT_NO_AUTOMOUNT: ::c_int = 0x800; pub const AT_EMPTY_PATH: ::c_int = 0x1000; pub const LOG_CRON: ::c_int = 9 << 3; pub const LOG_AUTHPRIV: ::c_int = 10 << 3; pub const LOG_FTP: ::c_int = 11 << 3; pub const LOG_PERROR: ::c_int = 0x20; pub const PIPE_BUF: usize = 4096; pub const SI_LOAD_SHIFT: ::c_uint = 16; pub const CLD_EXITED: ::c_int = 1; pub const CLD_KILLED: ::c_int = 2; pub const CLD_DUMPED: ::c_int = 3; pub const CLD_TRAPPED: ::c_int = 4; pub const CLD_STOPPED: ::c_int = 5; pub const CLD_CONTINUED: ::c_int = 6; pub const SIGEV_SIGNAL: ::c_int = 0; pub const SIGEV_NONE: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 2; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const UTIME_OMIT: c_long = 1073741822; pub const UTIME_NOW: c_long = 1073741823; pub const POLLIN: ::c_short = 0x1; pub const POLLPRI: ::c_short = 0x2; pub const POLLOUT: ::c_short = 0x4; pub const POLLERR: ::c_short = 0x8; pub const POLLHUP: ::c_short = 0x10; pub const POLLNVAL: ::c_short = 0x20; pub const POLLRDNORM: ::c_short = 0x040; pub const POLLRDBAND: ::c_short = 0x080; pub const ABDAY_1: ::nl_item = 0x20000; pub const ABDAY_2: ::nl_item = 0x20001; pub const ABDAY_3: ::nl_item = 0x20002; pub const ABDAY_4: ::nl_item = 0x20003; pub const ABDAY_5: ::nl_item = 0x20004; pub const ABDAY_6: ::nl_item = 0x20005; pub const ABDAY_7: ::nl_item = 0x20006; pub const DAY_1: ::nl_item = 0x20007; pub const DAY_2: ::nl_item = 0x20008; pub const DAY_3: ::nl_item = 0x20009; pub const DAY_4: ::nl_item = 0x2000A; pub const DAY_5: ::nl_item = 0x2000B; pub const DAY_6: ::nl_item = 0x2000C; pub const DAY_7: ::nl_item = 0x2000D; pub const ABMON_1: ::nl_item = 0x2000E; pub const ABMON_2: ::nl_item = 0x2000F; pub const ABMON_3: ::nl_item = 0x20010; pub const ABMON_4: ::nl_item = 0x20011; pub const ABMON_5: ::nl_item = 0x20012; pub const ABMON_6: ::nl_item = 0x20013; pub const ABMON_7: ::nl_item = 0x20014; pub const ABMON_8: ::nl_item = 0x20015; pub const ABMON_9: ::nl_item = 0x20016; pub const ABMON_10: ::nl_item = 0x20017; pub const ABMON_11: ::nl_item = 0x20018; pub const ABMON_12: ::nl_item = 0x20019; pub const MON_1: ::nl_item = 0x2001A; pub const MON_2: ::nl_item = 0x2001B; pub const MON_3: ::nl_item = 0x2001C; pub const MON_4: ::nl_item = 0x2001D; pub const MON_5: ::nl_item = 0x2001E; pub const MON_6: ::nl_item = 0x2001F; pub const MON_7: ::nl_item = 0x20020; pub const MON_8: ::nl_item = 0x20021; pub const MON_9: ::nl_item = 0x20022; pub const MON_10: ::nl_item = 0x20023; pub const MON_11: ::nl_item = 0x20024; pub const MON_12: ::nl_item = 0x20025; pub const AM_STR: ::nl_item = 0x20026; pub const PM_STR: ::nl_item = 0x20027; pub const D_T_FMT: ::nl_item = 0x20028; pub const D_FMT: ::nl_item = 0x20029; pub const T_FMT: ::nl_item = 0x2002A; pub const T_FMT_AMPM: ::nl_item = 0x2002B; pub const ERA: ::nl_item = 0x2002C; pub const ERA_D_FMT: ::nl_item = 0x2002E; pub const ALT_DIGITS: ::nl_item = 0x2002F; pub const ERA_D_T_FMT: ::nl_item = 0x20030; pub const ERA_T_FMT: ::nl_item = 0x20031; pub const CODESET: ::nl_item = 14; pub const CRNCYSTR: ::nl_item = 0x4000F; pub const RUSAGE_THREAD: ::c_int = 1; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const RADIXCHAR: ::nl_item = 0x10000; pub const THOUSEP: ::nl_item = 0x10001; pub const YESEXPR: ::nl_item = 0x50000; pub const NOEXPR: ::nl_item = 0x50001; pub const YESSTR: ::nl_item = 0x50002; pub const NOSTR: ::nl_item = 0x50003; pub const FILENAME_MAX: ::c_uint = 4096; pub const L_tmpnam: ::c_uint = 20; pub const _PC_LINK_MAX: ::c_int = 0; pub const _PC_MAX_CANON: ::c_int = 1; pub const _PC_MAX_INPUT: ::c_int = 2; pub const _PC_NAME_MAX: ::c_int = 3; pub const _PC_PATH_MAX: ::c_int = 4; pub const _PC_PIPE_BUF: ::c_int = 5; pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_SYNC_IO: ::c_int = 9; pub const _PC_ASYNC_IO: ::c_int = 10; pub const _PC_PRIO_IO: ::c_int = 11; pub const _PC_SOCK_MAXBUF: ::c_int = 12; pub const _PC_FILESIZEBITS: ::c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; pub const _PC_REC_XFER_ALIGN: ::c_int = 17; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18; pub const _PC_SYMLINK_MAX: ::c_int = 19; pub const _PC_2_SYMLINKS: ::c_int = 20; pub const _SC_ARG_MAX: ::c_int = 0; pub const _SC_CHILD_MAX: ::c_int = 1; pub const _SC_CLK_TCK: ::c_int = 2; pub const _SC_NGROUPS_MAX: ::c_int = 3; pub const _SC_OPEN_MAX: ::c_int = 4; pub const _SC_STREAM_MAX: ::c_int = 5; pub const _SC_TZNAME_MAX: ::c_int = 6; pub const _SC_JOB_CONTROL: ::c_int = 7; pub const _SC_SAVED_IDS: ::c_int = 8; pub const _SC_REALTIME_SIGNALS: ::c_int = 9; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 10; pub const _SC_TIMERS: ::c_int = 11; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 12; pub const _SC_PRIORITIZED_IO: ::c_int = 13; pub const _SC_SYNCHRONIZED_IO: ::c_int = 14; pub const _SC_FSYNC: ::c_int = 15; pub const _SC_MAPPED_FILES: ::c_int = 16; pub const _SC_MEMLOCK: ::c_int = 17; pub const _SC_MEMLOCK_RANGE: ::c_int = 18; pub const _SC_MEMORY_PROTECTION: ::c_int = 19; pub const _SC_MESSAGE_PASSING: ::c_int = 20; pub const _SC_SEMAPHORES: ::c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 22; pub const _SC_AIO_LISTIO_MAX: ::c_int = 23; pub const _SC_AIO_MAX: ::c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 25; pub const _SC_DELAYTIMER_MAX: ::c_int = 26; pub const _SC_MQ_OPEN_MAX: ::c_int = 27; pub const _SC_MQ_PRIO_MAX: ::c_int = 28; pub const _SC_VERSION: ::c_int = 29; pub const _SC_PAGESIZE: ::c_int = 30; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: ::c_int = 31; pub const _SC_SEM_NSEMS_MAX: ::c_int = 32; pub const _SC_SEM_VALUE_MAX: ::c_int = 33; pub const _SC_SIGQUEUE_MAX: ::c_int = 34; pub const _SC_TIMER_MAX: ::c_int = 35; pub const _SC_BC_BASE_MAX: ::c_int = 36; pub const _SC_BC_DIM_MAX: ::c_int = 37; pub const _SC_BC_SCALE_MAX: ::c_int = 38; pub const _SC_BC_STRING_MAX: ::c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 40; pub const _SC_EXPR_NEST_MAX: ::c_int = 42; pub const _SC_LINE_MAX: ::c_int = 43; pub const _SC_RE_DUP_MAX: ::c_int = 44; pub const _SC_2_VERSION: ::c_int = 46; pub const _SC_2_C_BIND: ::c_int = 47; pub const _SC_2_C_DEV: ::c_int = 48; pub const _SC_2_FORT_DEV: ::c_int = 49; pub const _SC_2_FORT_RUN: ::c_int = 50; pub const _SC_2_SW_DEV: ::c_int = 51; pub const _SC_2_LOCALEDEF: ::c_int = 52; pub const _SC_UIO_MAXIOV: ::c_int = 60; pub const _SC_IOV_MAX: ::c_int = 60; pub const _SC_THREADS: ::c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 70; pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; pub const _SC_TTY_NAME_MAX: ::c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 73; pub const _SC_THREAD_KEYS_MAX: ::c_int = 74; pub const _SC_THREAD_STACK_MIN: ::c_int = 75; pub const _SC_THREAD_THREADS_MAX: ::c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 82; pub const _SC_NPROCESSORS_CONF: ::c_int = 83; pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; pub const _SC_PHYS_PAGES: ::c_int = 85; pub const _SC_AVPHYS_PAGES: ::c_int = 86; pub const _SC_ATEXIT_MAX: ::c_int = 87; pub const _SC_PASS_MAX: ::c_int = 88; pub const _SC_XOPEN_VERSION: ::c_int = 89; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90; pub const _SC_XOPEN_UNIX: ::c_int = 91; pub const _SC_XOPEN_CRYPT: ::c_int = 92; pub const _SC_XOPEN_ENH_I18N: ::c_int = 93; pub const _SC_XOPEN_SHM: ::c_int = 94; pub const _SC_2_CHAR_TERM: ::c_int = 95; pub const _SC_2_UPE: ::c_int = 97; pub const _SC_XOPEN_XPG2: ::c_int = 98; pub const _SC_XOPEN_XPG3: ::c_int = 99; pub const _SC_XOPEN_XPG4: ::c_int = 100; pub const _SC_NZERO: ::c_int = 109; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126; pub const _SC_XBS5_LP64_OFF64: ::c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128; pub const _SC_XOPEN_LEGACY: ::c_int = 129; pub const _SC_XOPEN_REALTIME: ::c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131; pub const _SC_ADVISORY_INFO: ::c_int = 132; pub const _SC_BARRIERS: ::c_int = 133; pub const _SC_CLOCK_SELECTION: ::c_int = 137; pub const _SC_CPUTIME: ::c_int = 138; pub const _SC_THREAD_CPUTIME: ::c_int = 139; pub const _SC_MONOTONIC_CLOCK: ::c_int = 149; pub const _SC_READER_WRITER_LOCKS: ::c_int = 153; pub const _SC_SPIN_LOCKS: ::c_int = 154; pub const _SC_REGEXP: ::c_int = 155; pub const _SC_SHELL: ::c_int = 157; pub const _SC_SPAWN: ::c_int = 159; pub const _SC_SPORADIC_SERVER: ::c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 161; pub const _SC_TIMEOUTS: ::c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 165; pub const _SC_2_PBS: ::c_int = 168; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 169; pub const _SC_2_PBS_LOCATE: ::c_int = 170; pub const _SC_2_PBS_MESSAGE: ::c_int = 171; pub const _SC_2_PBS_TRACK: ::c_int = 172; pub const _SC_SYMLOOP_MAX: ::c_int = 173; pub const _SC_STREAMS: ::c_int = 174; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 175; pub const _SC_V6_ILP32_OFF32: ::c_int = 176; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 177; pub const _SC_V6_LP64_OFF64: ::c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 179; pub const _SC_HOST_NAME_MAX: ::c_int = 180; pub const _SC_TRACE: ::c_int = 181; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 182; pub const _SC_TRACE_INHERIT: ::c_int = 183; pub const _SC_TRACE_LOG: ::c_int = 184; pub const _SC_IPV6: ::c_int = 235; pub const _SC_RAW_SOCKETS: ::c_int = 236; pub const _SC_V7_ILP32_OFF32: ::c_int = 237; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 238; pub const _SC_V7_LP64_OFF64: ::c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 240; pub const _SC_SS_REPL_MAX: ::c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 242; pub const _SC_TRACE_NAME_MAX: ::c_int = 243; pub const _SC_TRACE_SYS_MAX: ::c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 245; pub const _SC_XOPEN_STREAMS: ::c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248; pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; pub const GLOB_ERR: ::c_int = 1 << 0; pub const GLOB_MARK: ::c_int = 1 << 1; pub const GLOB_NOSORT: ::c_int = 1 << 2; pub const GLOB_DOOFFS: ::c_int = 1 << 3; pub const GLOB_NOCHECK: ::c_int = 1 << 4; pub const GLOB_APPEND: ::c_int = 1 << 5; pub const GLOB_NOESCAPE: ::c_int = 1 << 6; pub const GLOB_NOSPACE: ::c_int = 1; pub const GLOB_ABORTED: ::c_int = 2; pub const GLOB_NOMATCH: ::c_int = 3; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; pub const S_IREAD: mode_t = 256; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const IFF_LOWER_UP: ::c_int = 0x10000; pub const IFF_DORMANT: ::c_int = 0x20000; pub const IFF_ECHO: ::c_int = 0x40000; pub const ST_RDONLY: ::c_ulong = 1; pub const ST_NOSUID: ::c_ulong = 2; pub const ST_NODEV: ::c_ulong = 4; pub const ST_NOEXEC: ::c_ulong = 8; pub const ST_SYNCHRONOUS: ::c_ulong = 16; pub const ST_MANDLOCK: ::c_ulong = 64; pub const ST_WRITE: ::c_ulong = 128; pub const ST_APPEND: ::c_ulong = 256; pub const ST_IMMUTABLE: ::c_ulong = 512; pub const ST_NOATIME: ::c_ulong = 1024; pub const ST_NODIRATIME: ::c_ulong = 2048; pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void; pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; pub const RTLD_NODELETE: ::c_int = 0x1000; pub const RTLD_NOW: ::c_int = 0x2; pub const TCP_MD5SIG: ::c_int = 14; align_const! { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [0; __SIZEOF_PTHREAD_RWLOCK_T], }; } pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const RENAME_NOREPLACE: ::c_int = 1; pub const RENAME_EXCHANGE: ::c_int = 2; pub const RENAME_WHITEOUT: ::c_int = 4; pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const SCHED_BATCH: ::c_int = 3; pub const SCHED_IDLE: ::c_int = 5; // netinet/in.h // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: ::c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: ::c_int = 2; /// for compatibility pub const IPPROTO_IPIP: ::c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: ::c_int = 8; /// pup pub const IPPROTO_PUP: ::c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: ::c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: ::c_int = 29; /// DCCP pub const IPPROTO_DCCP: ::c_int = 33; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: ::c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: ::c_int = 44; /// resource reservation pub const IPPROTO_RSVP: ::c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: ::c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: ::c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: ::c_int = 51; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: ::c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: ::c_int = 60; pub const IPPROTO_MTP: ::c_int = 92; pub const IPPROTO_BEETPH: ::c_int = 94; /// encapsulation header pub const IPPROTO_ENCAP: ::c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: ::c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_COMP: ::c_int = 108; /// SCTP pub const IPPROTO_SCTP: ::c_int = 132; pub const IPPROTO_MH: ::c_int = 135; pub const IPPROTO_UDPLITE: ::c_int = 136; pub const IPPROTO_MPLS: ::c_int = 137; /// raw IP packet pub const IPPROTO_RAW: ::c_int = 255; pub const IPPROTO_MAX: ::c_int = 256; pub const AF_IB: ::c_int = 27; pub const AF_MPLS: ::c_int = 28; pub const AF_NFC: ::c_int = 39; pub const AF_VSOCK: ::c_int = 40; pub const PF_IB: ::c_int = AF_IB; pub const PF_MPLS: ::c_int = AF_MPLS; pub const PF_NFC: ::c_int = AF_NFC; pub const PF_VSOCK: ::c_int = AF_VSOCK; // System V IPC pub const IPC_PRIVATE: ::key_t = 0; pub const IPC_CREAT: ::c_int = 0o1000; pub const IPC_EXCL: ::c_int = 0o2000; pub const IPC_NOWAIT: ::c_int = 0o4000; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const IPC_INFO: ::c_int = 3; pub const MSG_STAT: ::c_int = 11; pub const MSG_INFO: ::c_int = 12; pub const MSG_NOERROR: ::c_int = 0o10000; pub const MSG_EXCEPT: ::c_int = 0o20000; pub const MSG_COPY: ::c_int = 0o40000; pub const SHM_R: ::c_int = 0o400; pub const SHM_W: ::c_int = 0o200; pub const SHM_RDONLY: ::c_int = 0o10000; pub const SHM_RND: ::c_int = 0o20000; pub const SHM_REMAP: ::c_int = 0o40000; pub const SHM_EXEC: ::c_int = 0o100000; pub const SHM_LOCK: ::c_int = 11; pub const SHM_UNLOCK: ::c_int = 12; pub const SHM_HUGETLB: ::c_int = 0o4000; pub const SHM_NORESERVE: ::c_int = 0o10000; pub const EPOLLRDHUP: ::c_int = 0x2000; pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; pub const EPOLLONESHOT: ::c_int = 0x40000000; pub const QFMT_VFS_OLD: ::c_int = 1; pub const QFMT_VFS_V0: ::c_int = 2; pub const QFMT_VFS_V1: ::c_int = 4; pub const EFD_SEMAPHORE: ::c_int = 0x1; pub const LOG_NFACILITIES: ::c_int = 24; pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t; pub const RB_AUTOBOOT: ::c_int = 0x01234567u32 as i32; pub const RB_HALT_SYSTEM: ::c_int = 0xcdef0123u32 as i32; pub const RB_ENABLE_CAD: ::c_int = 0x89abcdefu32 as i32; pub const RB_DISABLE_CAD: ::c_int = 0x00000000u32 as i32; pub const RB_POWER_OFF: ::c_int = 0x4321fedcu32 as i32; pub const RB_SW_SUSPEND: ::c_int = 0xd000fce2u32 as i32; pub const RB_KEXEC: ::c_int = 0x45584543u32 as i32; pub const AI_PASSIVE: ::c_int = 0x0001; pub const AI_CANONNAME: ::c_int = 0x0002; pub const AI_NUMERICHOST: ::c_int = 0x0004; pub const AI_V4MAPPED: ::c_int = 0x0008; pub const AI_ALL: ::c_int = 0x0010; pub const AI_ADDRCONFIG: ::c_int = 0x0020; pub const AI_NUMERICSERV: ::c_int = 0x0400; pub const EAI_BADFLAGS: ::c_int = -1; pub const EAI_NONAME: ::c_int = -2; pub const EAI_AGAIN: ::c_int = -3; pub const EAI_FAIL: ::c_int = -4; pub const EAI_FAMILY: ::c_int = -6; pub const EAI_SOCKTYPE: ::c_int = -7; pub const EAI_SERVICE: ::c_int = -8; pub const EAI_MEMORY: ::c_int = -10; pub const EAI_OVERFLOW: ::c_int = -12; pub const NI_NUMERICHOST: ::c_int = 1; pub const NI_NUMERICSERV: ::c_int = 2; pub const NI_NOFQDN: ::c_int = 4; pub const NI_NAMEREQD: ::c_int = 8; pub const NI_DGRAM: ::c_int = 16; pub const SYNC_FILE_RANGE_WAIT_BEFORE: ::c_uint = 1; pub const SYNC_FILE_RANGE_WRITE: ::c_uint = 2; pub const SYNC_FILE_RANGE_WAIT_AFTER: ::c_uint = 4; pub const EAI_SYSTEM: ::c_int = -11; pub const AIO_CANCELED: ::c_int = 0; pub const AIO_NOTCANCELED: ::c_int = 1; pub const AIO_ALLDONE: ::c_int = 2; pub const LIO_READ: ::c_int = 0; pub const LIO_WRITE: ::c_int = 1; pub const LIO_NOP: ::c_int = 2; pub const LIO_WAIT: ::c_int = 0; pub const LIO_NOWAIT: ::c_int = 1; pub const MREMAP_MAYMOVE: ::c_int = 1; pub const MREMAP_FIXED: ::c_int = 2; pub const PR_SET_PDEATHSIG: ::c_int = 1; pub const PR_GET_PDEATHSIG: ::c_int = 2; pub const PR_GET_DUMPABLE: ::c_int = 3; pub const PR_SET_DUMPABLE: ::c_int = 4; pub const PR_GET_UNALIGN: ::c_int = 5; pub const PR_SET_UNALIGN: ::c_int = 6; pub const PR_UNALIGN_NOPRINT: ::c_int = 1; pub const PR_UNALIGN_SIGBUS: ::c_int = 2; pub const PR_GET_KEEPCAPS: ::c_int = 7; pub const PR_SET_KEEPCAPS: ::c_int = 8; pub const PR_GET_FPEMU: ::c_int = 9; pub const PR_SET_FPEMU: ::c_int = 10; pub const PR_FPEMU_NOPRINT: ::c_int = 1; pub const PR_FPEMU_SIGFPE: ::c_int = 2; pub const PR_GET_FPEXC: ::c_int = 11; pub const PR_SET_FPEXC: ::c_int = 12; pub const PR_FP_EXC_SW_ENABLE: ::c_int = 0x80; pub const PR_FP_EXC_DIV: ::c_int = 0x010000; pub const PR_FP_EXC_OVF: ::c_int = 0x020000; pub const PR_FP_EXC_UND: ::c_int = 0x040000; pub const PR_FP_EXC_RES: ::c_int = 0x080000; pub const PR_FP_EXC_INV: ::c_int = 0x100000; pub const PR_FP_EXC_DISABLED: ::c_int = 0; pub const PR_FP_EXC_NONRECOV: ::c_int = 1; pub const PR_FP_EXC_ASYNC: ::c_int = 2; pub const PR_FP_EXC_PRECISE: ::c_int = 3; pub const PR_GET_TIMING: ::c_int = 13; pub const PR_SET_TIMING: ::c_int = 14; pub const PR_TIMING_STATISTICAL: ::c_int = 0; pub const PR_TIMING_TIMESTAMP: ::c_int = 1; pub const PR_SET_NAME: ::c_int = 15; pub const PR_GET_NAME: ::c_int = 16; pub const PR_GET_ENDIAN: ::c_int = 19; pub const PR_SET_ENDIAN: ::c_int = 20; pub const PR_ENDIAN_BIG: ::c_int = 0; pub const PR_ENDIAN_LITTLE: ::c_int = 1; pub const PR_ENDIAN_PPC_LITTLE: ::c_int = 2; pub const PR_GET_SECCOMP: ::c_int = 21; pub const PR_SET_SECCOMP: ::c_int = 22; pub const PR_CAPBSET_READ: ::c_int = 23; pub const PR_CAPBSET_DROP: ::c_int = 24; pub const PR_GET_TSC: ::c_int = 25; pub const PR_SET_TSC: ::c_int = 26; pub const PR_TSC_ENABLE: ::c_int = 1; pub const PR_TSC_SIGSEGV: ::c_int = 2; pub const PR_GET_SECUREBITS: ::c_int = 27; pub const PR_SET_SECUREBITS: ::c_int = 28; pub const PR_SET_TIMERSLACK: ::c_int = 29; pub const PR_GET_TIMERSLACK: ::c_int = 30; pub const PR_TASK_PERF_EVENTS_DISABLE: ::c_int = 31; pub const PR_TASK_PERF_EVENTS_ENABLE: ::c_int = 32; pub const PR_MCE_KILL: ::c_int = 33; pub const PR_MCE_KILL_CLEAR: ::c_int = 0; pub const PR_MCE_KILL_SET: ::c_int = 1; pub const PR_MCE_KILL_LATE: ::c_int = 0; pub const PR_MCE_KILL_EARLY: ::c_int = 1; pub const PR_MCE_KILL_DEFAULT: ::c_int = 2; pub const PR_MCE_KILL_GET: ::c_int = 34; pub const PR_SET_MM: ::c_int = 35; pub const PR_SET_MM_START_CODE: ::c_int = 1; pub const PR_SET_MM_END_CODE: ::c_int = 2; pub const PR_SET_MM_START_DATA: ::c_int = 3; pub const PR_SET_MM_END_DATA: ::c_int = 4; pub const PR_SET_MM_START_STACK: ::c_int = 5; pub const PR_SET_MM_START_BRK: ::c_int = 6; pub const PR_SET_MM_BRK: ::c_int = 7; pub const PR_SET_MM_ARG_START: ::c_int = 8; pub const PR_SET_MM_ARG_END: ::c_int = 9; pub const PR_SET_MM_ENV_START: ::c_int = 10; pub const PR_SET_MM_ENV_END: ::c_int = 11; pub const PR_SET_MM_AUXV: ::c_int = 12; pub const PR_SET_MM_EXE_FILE: ::c_int = 13; pub const PR_SET_MM_MAP: ::c_int = 14; pub const PR_SET_MM_MAP_SIZE: ::c_int = 15; pub const PR_SET_PTRACER: ::c_int = 0x59616d61; pub const PR_SET_PTRACER_ANY: ::c_ulong = 0xffffffffffffffff; pub const PR_SET_CHILD_SUBREAPER: ::c_int = 36; pub const PR_GET_CHILD_SUBREAPER: ::c_int = 37; pub const PR_SET_NO_NEW_PRIVS: ::c_int = 38; pub const PR_GET_NO_NEW_PRIVS: ::c_int = 39; pub const PR_GET_TID_ADDRESS: ::c_int = 40; pub const PR_SET_THP_DISABLE: ::c_int = 41; pub const PR_GET_THP_DISABLE: ::c_int = 42; pub const PR_MPX_ENABLE_MANAGEMENT: ::c_int = 43; pub const PR_MPX_DISABLE_MANAGEMENT: ::c_int = 44; pub const PR_SET_FP_MODE: ::c_int = 45; pub const PR_GET_FP_MODE: ::c_int = 46; pub const PR_FP_MODE_FR: ::c_int = 1 << 0; pub const PR_FP_MODE_FRE: ::c_int = 1 << 1; pub const PR_CAP_AMBIENT: ::c_int = 47; pub const PR_CAP_AMBIENT_IS_SET: ::c_int = 1; pub const PR_CAP_AMBIENT_RAISE: ::c_int = 2; pub const PR_CAP_AMBIENT_LOWER: ::c_int = 3; pub const PR_CAP_AMBIENT_CLEAR_ALL: ::c_int = 4; pub const ITIMER_REAL: ::c_int = 0; pub const ITIMER_VIRTUAL: ::c_int = 1; pub const ITIMER_PROF: ::c_int = 2; pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC; pub const TFD_NONBLOCK: ::c_int = O_NONBLOCK; pub const TFD_TIMER_ABSTIME: ::c_int = 1; pub const XATTR_CREATE: ::c_int = 0x1; pub const XATTR_REPLACE: ::c_int = 0x2; pub const _POSIX_VDISABLE: ::cc_t = 0; pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02; pub const FALLOC_FL_COLLAPSE_RANGE: ::c_int = 0x08; pub const FALLOC_FL_ZERO_RANGE: ::c_int = 0x10; pub const FALLOC_FL_INSERT_RANGE: ::c_int = 0x20; pub const FALLOC_FL_UNSHARE_RANGE: ::c_int = 0x40; // On Linux, libc doesn't define this constant, libattr does instead. // We still define it for Linux as it's defined by libc on other platforms, // and it's mentioned in the man pages for getxattr and setxattr. pub const ENOATTR: ::c_int = ::ENODATA; pub const SO_ORIGINAL_DST: ::c_int = 80; pub const IUTF8: ::tcflag_t = 0x00004000; pub const CMSPAR: ::tcflag_t = 0o10000000000; pub const MFD_CLOEXEC: ::c_uint = 0x0001; pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002; // these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has // the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32 // so we can use that type here to avoid having to cast. pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_NUM: u32 = 8; pub const PT_LOOS: u32 = 0x60000000; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_STACK: u32 = 0x6474e551; pub const PT_GNU_RELRO: u32 = 0x6474e552; // Ethernet protocol IDs. pub const ETH_P_LOOP: ::c_int = 0x0060; pub const ETH_P_PUP: ::c_int = 0x0200; pub const ETH_P_PUPAT: ::c_int = 0x0201; pub const ETH_P_IP: ::c_int = 0x0800; pub const ETH_P_X25: ::c_int = 0x0805; pub const ETH_P_ARP: ::c_int = 0x0806; pub const ETH_P_BPQ: ::c_int = 0x08FF; pub const ETH_P_IEEEPUP: ::c_int = 0x0a00; pub const ETH_P_IEEEPUPAT: ::c_int = 0x0a01; pub const ETH_P_BATMAN: ::c_int = 0x4305; pub const ETH_P_DEC: ::c_int = 0x6000; pub const ETH_P_DNA_DL: ::c_int = 0x6001; pub const ETH_P_DNA_RC: ::c_int = 0x6002; pub const ETH_P_DNA_RT: ::c_int = 0x6003; pub const ETH_P_LAT: ::c_int = 0x6004; pub const ETH_P_DIAG: ::c_int = 0x6005; pub const ETH_P_CUST: ::c_int = 0x6006; pub const ETH_P_SCA: ::c_int = 0x6007; pub const ETH_P_TEB: ::c_int = 0x6558; pub const ETH_P_RARP: ::c_int = 0x8035; pub const ETH_P_ATALK: ::c_int = 0x809B; pub const ETH_P_AARP: ::c_int = 0x80F3; pub const ETH_P_8021Q: ::c_int = 0x8100; pub const ETH_P_IPX: ::c_int = 0x8137; pub const ETH_P_IPV6: ::c_int = 0x86DD; pub const ETH_P_PAUSE: ::c_int = 0x8808; pub const ETH_P_SLOW: ::c_int = 0x8809; pub const ETH_P_WCCP: ::c_int = 0x883E; pub const ETH_P_MPLS_UC: ::c_int = 0x8847; pub const ETH_P_MPLS_MC: ::c_int = 0x8848; pub const ETH_P_ATMMPOA: ::c_int = 0x884c; pub const ETH_P_PPP_DISC: ::c_int = 0x8863; pub const ETH_P_PPP_SES: ::c_int = 0x8864; pub const ETH_P_LINK_CTL: ::c_int = 0x886c; pub const ETH_P_ATMFATE: ::c_int = 0x8884; pub const ETH_P_PAE: ::c_int = 0x888E; pub const ETH_P_AOE: ::c_int = 0x88A2; pub const ETH_P_8021AD: ::c_int = 0x88A8; pub const ETH_P_802_EX1: ::c_int = 0x88B5; pub const ETH_P_TIPC: ::c_int = 0x88CA; pub const ETH_P_8021AH: ::c_int = 0x88E7; pub const ETH_P_MVRP: ::c_int = 0x88F5; pub const ETH_P_1588: ::c_int = 0x88F7; pub const ETH_P_PRP: ::c_int = 0x88FB; pub const ETH_P_FCOE: ::c_int = 0x8906; pub const ETH_P_TDLS: ::c_int = 0x890D; pub const ETH_P_FIP: ::c_int = 0x8914; pub const ETH_P_80221: ::c_int = 0x8917; pub const ETH_P_LOOPBACK: ::c_int = 0x9000; pub const ETH_P_QINQ1: ::c_int = 0x9100; pub const ETH_P_QINQ2: ::c_int = 0x9200; pub const ETH_P_QINQ3: ::c_int = 0x9300; pub const ETH_P_EDSA: ::c_int = 0xDADA; pub const ETH_P_AF_IUCV: ::c_int = 0xFBFB; pub const ETH_P_802_3_MIN: ::c_int = 0x0600; pub const ETH_P_802_3: ::c_int = 0x0001; pub const ETH_P_AX25: ::c_int = 0x0002; pub const ETH_P_ALL: ::c_int = 0x0003; pub const ETH_P_802_2: ::c_int = 0x0004; pub const ETH_P_SNAP: ::c_int = 0x0005; pub const ETH_P_DDCMP: ::c_int = 0x0006; pub const ETH_P_WAN_PPP: ::c_int = 0x0007; pub const ETH_P_PPP_MP: ::c_int = 0x0008; pub const ETH_P_LOCALTALK: ::c_int = 0x0009; pub const ETH_P_CAN: ::c_int = 0x000C; pub const ETH_P_CANFD: ::c_int = 0x000D; pub const ETH_P_PPPTALK: ::c_int = 0x0010; pub const ETH_P_TR_802_2: ::c_int = 0x0011; pub const ETH_P_MOBITEX: ::c_int = 0x0015; pub const ETH_P_CONTROL: ::c_int = 0x0016; pub const ETH_P_IRDA: ::c_int = 0x0017; pub const ETH_P_ECONET: ::c_int = 0x0018; pub const ETH_P_HDLC: ::c_int = 0x0019; pub const ETH_P_ARCNET: ::c_int = 0x001A; pub const ETH_P_DSA: ::c_int = 0x001B; pub const ETH_P_TRAILER: ::c_int = 0x001C; pub const ETH_P_PHONET: ::c_int = 0x00F5; pub const ETH_P_IEEE802154: ::c_int = 0x00F6; pub const ETH_P_CAIF: ::c_int = 0x00F7; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 0x00040000; pub const O_NOATIME: ::c_int = 0x00002000; pub const O_CLOEXEC: ::c_int = 0x00000100; pub const O_TMPFILE: ::c_int = 0x00004000; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const BUFSIZ: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 10000; pub const FOPEN_MAX: ::c_uint = 1000; pub const O_PATH: ::c_int = 0x00400000; pub const O_EXEC: ::c_int = O_PATH; pub const O_SEARCH: ::c_int = O_PATH; pub const O_ACCMODE: ::c_int = 03 | O_SEARCH; pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const NI_MAXHOST: ::socklen_t = 255; pub const PTHREAD_STACK_MIN: ::size_t = 2048; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const RLIM_INFINITY: ::rlim_t = !0; pub const RLIMIT_RTTIME: ::c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::c_int = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = RLIMIT_NLIMITS; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const SOCK_DCCP: ::c_int = 6; pub const SOCK_PACKET: ::c_int = 10; pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15; pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16; pub const TCP_THIN_DUPACK: ::c_int = 17; pub const TCP_USER_TIMEOUT: ::c_int = 18; pub const TCP_REPAIR: ::c_int = 19; pub const TCP_REPAIR_QUEUE: ::c_int = 20; pub const TCP_QUEUE_SEQ: ::c_int = 21; pub const TCP_REPAIR_OPTIONS: ::c_int = 22; pub const TCP_FASTOPEN: ::c_int = 23; pub const TCP_TIMESTAMP: ::c_int = 24; pub const SIGUNUSED: ::c_int = ::SIGSYS; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const CPU_SETSIZE: ::c_int = 128; pub const PTRACE_TRACEME: ::c_int = 0; pub const PTRACE_PEEKTEXT: ::c_int = 1; pub const PTRACE_PEEKDATA: ::c_int = 2; pub const PTRACE_PEEKUSER: ::c_int = 3; pub const PTRACE_POKETEXT: ::c_int = 4; pub const PTRACE_POKEDATA: ::c_int = 5; pub const PTRACE_POKEUSER: ::c_int = 6; pub const PTRACE_CONT: ::c_int = 7; pub const PTRACE_KILL: ::c_int = 8; pub const PTRACE_SINGLESTEP: ::c_int = 9; pub const PTRACE_GETREGS: ::c_int = 12; pub const PTRACE_SETREGS: ::c_int = 13; pub const PTRACE_GETFPREGS: ::c_int = 14; pub const PTRACE_SETFPREGS: ::c_int = 15; pub const PTRACE_ATTACH: ::c_int = 16; pub const PTRACE_DETACH: ::c_int = 17; pub const PTRACE_GETFPXREGS: ::c_int = 18; pub const PTRACE_SETFPXREGS: ::c_int = 19; pub const PTRACE_SYSCALL: ::c_int = 24; pub const PTRACE_SETOPTIONS: ::c_int = 0x4200; pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201; pub const PTRACE_GETSIGINFO: ::c_int = 0x4202; pub const PTRACE_SETSIGINFO: ::c_int = 0x4203; pub const PTRACE_GETREGSET: ::c_int = 0x4204; pub const PTRACE_SETREGSET: ::c_int = 0x4205; pub const PTRACE_SEIZE: ::c_int = 0x4206; pub const PTRACE_INTERRUPT: ::c_int = 0x4207; pub const PTRACE_LISTEN: ::c_int = 0x4208; pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209; pub const EPOLLWAKEUP: ::c_int = 0x20000000; pub const EFD_NONBLOCK: ::c_int = ::O_NONBLOCK; pub const SFD_NONBLOCK: ::c_int = ::O_NONBLOCK; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const TIOCINQ: ::c_int = ::FIONREAD; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const SO_BINDTODEVICE: ::c_int = 25; pub const SO_TIMESTAMP: ::c_int = 29; pub const SO_MARK: ::c_int = 36; pub const SO_RXQ_OVFL: ::c_int = 40; pub const SO_PEEK_OFF: ::c_int = 42; pub const SO_BUSY_POLL: ::c_int = 46; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const O_ASYNC: ::c_int = 0x00000400; pub const FIOCLEX: ::c_int = 0x5451; pub const FIONBIO: ::c_int = 0x5421; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_AS: ::c_int = 9; pub const RLIMIT_NPROC: ::c_int = 6; pub const RLIMIT_MEMLOCK: ::c_int = 8; pub const O_APPEND: ::c_int = 0x00100000; pub const O_CREAT: ::c_int = 0x00010000; pub const O_EXCL: ::c_int = 0x00020000; pub const O_NOCTTY: ::c_int = 0x00000200; pub const O_NONBLOCK: ::c_int = 0x00000010; pub const O_SYNC: ::c_int = 0x00000040 | O_DSYNC; pub const O_RSYNC: ::c_int = O_SYNC; pub const O_DSYNC: ::c_int = 0x00000020; pub const SOCK_CLOEXEC: ::c_int = 0o2000000; pub const SOCK_NONBLOCK: ::c_int = 0o4000; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOL_SOCKET: ::c_int = 1; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; pub const SO_REUSEADDR: ::c_int = 2; pub const SO_TYPE: ::c_int = 3; pub const SO_ERROR: ::c_int = 4; pub const SO_DONTROUTE: ::c_int = 5; pub const SO_BROADCAST: ::c_int = 6; pub const SO_SNDBUF: ::c_int = 7; pub const SO_RCVBUF: ::c_int = 8; pub const SO_KEEPALIVE: ::c_int = 9; pub const SO_OOBINLINE: ::c_int = 10; pub const SO_NO_CHECK: ::c_int = 11; pub const SO_PRIORITY: ::c_int = 12; pub const SO_LINGER: ::c_int = 13; pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_REUSEPORT: ::c_int = 15; pub const SO_PASSCRED: ::c_int = 16; pub const SO_PEERCRED: ::c_int = 17; pub const SO_RCVLOWAT: ::c_int = 18; pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; pub const SO_ACCEPTCONN: ::c_int = 30; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_PROTOCOL: ::c_int = 38; pub const SO_DOMAIN: ::c_int = 39; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const TCGETS: ::c_int = 0x5401; pub const TCSETS: ::c_int = 0x5402; pub const TCSETSW: ::c_int = 0x5403; pub const TCSETSF: ::c_int = 0x5404; pub const TCGETA: ::c_int = 0x5405; pub const TCSETA: ::c_int = 0x5406; pub const TCSETAW: ::c_int = 0x5407; pub const TCSETAF: ::c_int = 0x5408; pub const TCSBRK: ::c_int = 0x5409; pub const TCXONC: ::c_int = 0x540A; pub const TCFLSH: ::c_int = 0x540B; pub const TIOCGSOFTCAR: ::c_int = 0x5419; pub const TIOCSSOFTCAR: ::c_int = 0x541A; pub const TIOCLINUX: ::c_int = 0x541C; pub const TIOCGSERIAL: ::c_int = 0x541E; pub const TIOCEXCL: ::c_int = 0x540C; pub const TIOCNXCL: ::c_int = 0x540D; pub const TIOCSCTTY: ::c_int = 0x540E; pub const TIOCGPGRP: ::c_int = 0x540F; pub const TIOCSPGRP: ::c_int = 0x5410; pub const TIOCOUTQ: ::c_int = 0x5411; pub const TIOCSTI: ::c_int = 0x5412; pub const TIOCGWINSZ: ::c_int = 0x5413; pub const TIOCSWINSZ: ::c_int = 0x5414; pub const TIOCMGET: ::c_int = 0x5415; pub const TIOCMBIS: ::c_int = 0x5416; pub const TIOCMBIC: ::c_int = 0x5417; pub const TIOCMSET: ::c_int = 0x5418; pub const FIONREAD: ::c_int = 0x541B; pub const TIOCCONS: ::c_int = 0x541D; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const TIOCM_LE: ::c_int = 0x001; pub const TIOCM_DTR: ::c_int = 0x002; pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_ST: ::c_int = 0x008; pub const TIOCM_SR: ::c_int = 0x010; pub const TIOCM_CTS: ::c_int = 0x020; pub const TIOCM_CAR: ::c_int = 0x040; pub const TIOCM_RNG: ::c_int = 0x080; pub const TIOCM_DSR: ::c_int = 0x100; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const O_DIRECTORY: ::c_int = 0x00080000; pub const O_DIRECT: ::c_int = 0x00000800; pub const O_LARGEFILE: ::c_int = 0x00001000; pub const O_NOFOLLOW: ::c_int = 0x00000080; pub const HUGETLB_FLAG_ENCODE_SHIFT: u32 = 26; pub const MAP_HUGE_SHIFT: u32 = 26; // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } // END_PUB_CONST f! { pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn major(dev: ::dev_t) -> ::c_uint { let mut major = 0; major |= (dev & 0x00000000000fff00) >> 8; major |= (dev & 0xfffff00000000000) >> 32; major as ::c_uint } pub fn minor(dev: ::dev_t) -> ::c_uint { let mut minor = 0; minor |= (dev & 0x00000000000000ff) >> 0; minor |= (dev & 0x00000ffffff00000) >> 12; minor as ::c_uint } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar { cmsg.offset(1) as *mut c_uchar } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as ::size_t) < ::mem::size_of::() { 0 as *mut cmsghdr } else if __CMSG_NEXT(cmsg).add(::mem::size_of::()) >= __MHDR_END(mhdr) { 0 as *mut cmsghdr } else { __CMSG_NEXT(cmsg).cast() } } pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as ::size_t >= ::mem::size_of::() { (*mhdr).msg_control.cast() } else { 0 as *mut cmsghdr } } pub {const} fn CMSG_ALIGN(len: ::size_t) -> ::size_t { (len + ::mem::size_of::<::size_t>() - 1) & !(::mem::size_of::<::size_t>() - 1) } pub {const} fn CMSG_SPACE(len: ::c_uint) -> ::c_uint { (CMSG_ALIGN(len as ::size_t) + CMSG_ALIGN(::mem::size_of::())) as ::c_uint } pub {const} fn CMSG_LEN(len: ::c_uint) -> ::c_uint { (CMSG_ALIGN(::mem::size_of::()) + len as ::size_t) as ::c_uint } } safe_f! { pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { status & 0x7f } pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0x80) != 0 } pub {const} fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int { (cmd << 8) | (type_ & 0x00ff) } pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= (major & 0x00000fff) << 8; dev |= (major & 0xfffff000) << 32; dev |= (minor & 0x000000ff) << 0; dev |= (minor & 0xffffff00) << 12; dev } } fn __CMSG_LEN(cmsg: *const cmsghdr) -> ::ssize_t { ((unsafe { (*cmsg).cmsg_len as ::size_t } + ::mem::size_of::<::c_long>() - 1) & !(::mem::size_of::<::c_long>() - 1)) as ::ssize_t } fn __CMSG_NEXT(cmsg: *const cmsghdr) -> *mut c_uchar { (unsafe { cmsg.offset(__CMSG_LEN(cmsg)) }) as *mut c_uchar } fn __MHDR_END(mhdr: *const msghdr) -> *mut c_uchar { unsafe { (*mhdr).msg_control.offset((*mhdr).msg_controllen as isize) }.cast() } // EXTERN_FN #[link(name = "c")] #[link(name = "fdio")] extern "C" {} #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl ::Copy for FILE {} impl ::Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME: fill this out with a struct impl ::Copy for fpos_t {} impl ::Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn _exit(status: c_int) -> !; pub fn atexit(cb: extern "C" fn()) -> c_int; pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn getpwnam(name: *const ::c_char) -> *mut passwd; pub fn getpwuid(uid: ::uid_t) -> *mut passwd; pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn scanf(format: *const ::c_char, ...) -> ::c_int; pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; pub fn socket(domain: ::c_int, ty: ::c_int, protocol: ::c_int) -> ::c_int; pub fn connect(socket: ::c_int, address: *const sockaddr, len: socklen_t) -> ::c_int; pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int; pub fn accept(socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> ::c_int; pub fn getpeername( socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t, ) -> ::c_int; pub fn getsockname( socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t, ) -> ::c_int; pub fn setsockopt( socket: ::c_int, level: ::c_int, name: ::c_int, value: *const ::c_void, option_len: socklen_t, ) -> ::c_int; pub fn socketpair( domain: ::c_int, type_: ::c_int, protocol: ::c_int, socket_vector: *mut ::c_int, ) -> ::c_int; pub fn sendto( socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int, addr: *const sockaddr, addrlen: socklen_t, ) -> ::ssize_t; pub fn shutdown(socket: ::c_int, how: ::c_int) -> ::c_int; pub fn chmod(path: *const c_char, mode: mode_t) -> ::c_int; pub fn fchmod(fd: ::c_int, mode: mode_t) -> ::c_int; pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> ::c_int; pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn pclose(stream: *mut ::FILE) -> ::c_int; pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE; pub fn fileno(stream: *mut ::FILE) -> ::c_int; pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; pub fn creat(path: *const c_char, mode: mode_t) -> ::c_int; pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn opendir(dirname: *const c_char) -> *mut ::DIR; pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent; pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) -> ::c_int; pub fn closedir(dirp: *mut ::DIR) -> ::c_int; pub fn rewinddir(dirp: *mut ::DIR); pub fn openat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int, ...) -> ::c_int; pub fn fchmodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, flags: ::c_int, ) -> ::c_int; pub fn fchown(fd: ::c_int, owner: ::uid_t, group: ::gid_t) -> ::c_int; pub fn fchownat( dirfd: ::c_int, pathname: *const ::c_char, owner: ::uid_t, group: ::gid_t, flags: ::c_int, ) -> ::c_int; pub fn fstatat( dirfd: ::c_int, pathname: *const ::c_char, buf: *mut stat, flags: ::c_int, ) -> ::c_int; pub fn linkat( olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, flags: ::c_int, ) -> ::c_int; pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn readlinkat( dirfd: ::c_int, pathname: *const ::c_char, buf: *mut ::c_char, bufsiz: ::size_t, ) -> ::ssize_t; pub fn renameat( olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, ) -> ::c_int; pub fn symlinkat( target: *const ::c_char, newdirfd: ::c_int, linkpath: *const ::c_char, ) -> ::c_int; pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; pub fn alarm(seconds: ::c_uint) -> ::c_uint; pub fn chdir(dir: *const c_char) -> ::c_int; pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; pub fn close(fd: ::c_int) -> ::c_int; pub fn dup(fd: ::c_int) -> ::c_int; pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> ::c_int; pub fn execle(path: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; pub fn execlp(file: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::c_int; pub fn execve( prog: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> ::c_int; pub fn execvp(c: *const c_char, argv: *const *const c_char) -> ::c_int; pub fn fork() -> pid_t; pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long; pub fn getcwd(buf: *mut c_char, size: ::size_t) -> *mut c_char; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t) -> ::c_int; pub fn getlogin() -> *mut c_char; pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn getpgid(pid: pid_t) -> pid_t; pub fn getpgrp() -> pid_t; pub fn getpid() -> pid_t; pub fn getppid() -> pid_t; pub fn getuid() -> uid_t; pub fn isatty(fd: ::c_int) -> ::c_int; pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int; pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; pub fn pause() -> ::c_int; pub fn pipe(fds: *mut ::c_int) -> ::c_int; pub fn posix_memalign(memptr: *mut *mut ::c_void, align: ::size_t, size: ::size_t) -> ::c_int; pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; pub fn rmdir(path: *const c_char) -> ::c_int; pub fn seteuid(uid: uid_t) -> ::c_int; pub fn setegid(gid: gid_t) -> ::c_int; pub fn setgid(gid: gid_t) -> ::c_int; pub fn setpgid(pid: pid_t, pgid: pid_t) -> ::c_int; pub fn setsid() -> pid_t; pub fn setuid(uid: uid_t) -> ::c_int; pub fn sleep(secs: ::c_uint) -> ::c_uint; pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> ::c_int; pub fn tcgetpgrp(fd: ::c_int) -> pid_t; pub fn tcsetpgrp(fd: ::c_int, pgrp: ::pid_t) -> ::c_int; pub fn ttyname(fd: ::c_int) -> *mut c_char; pub fn unlink(c: *const c_char) -> ::c_int; pub fn wait(status: *mut ::c_int) -> pid_t; pub fn waitpid(pid: pid_t, status: *mut ::c_int, options: ::c_int) -> pid_t; pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t; pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn umask(mask: mode_t) -> mode_t; pub fn utime(file: *const c_char, buf: *const utimbuf) -> ::c_int; pub fn kill(pid: pid_t, sig: ::c_int) -> ::c_int; pub fn mlock(addr: *const ::c_void, len: ::size_t) -> ::c_int; pub fn munlock(addr: *const ::c_void, len: ::size_t) -> ::c_int; pub fn mlockall(flags: ::c_int) -> ::c_int; pub fn munlockall() -> ::c_int; pub fn mmap( addr: *mut ::c_void, len: ::size_t, prot: ::c_int, flags: ::c_int, fd: ::c_int, offset: off_t, ) -> *mut ::c_void; pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int; pub fn if_nametoindex(ifname: *const c_char) -> ::c_uint; pub fn if_indextoname(ifindex: ::c_uint, ifname: *mut ::c_char) -> *mut ::c_char; pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn fsync(fd: ::c_int) -> ::c_int; pub fn setenv(name: *const c_char, val: *const c_char, overwrite: ::c_int) -> ::c_int; pub fn unsetenv(name: *const c_char) -> ::c_int; pub fn symlink(path1: *const c_char, path2: *const c_char) -> ::c_int; pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; pub fn signal(signum: ::c_int, handler: sighandler_t) -> sighandler_t; pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char) -> *mut ::c_char; pub fn flock(fd: ::c_int, operation: ::c_int) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn times(buf: *mut ::tms) -> ::clock_t; pub fn pthread_self() -> ::pthread_t; pub fn pthread_join(native: ::pthread_t, value: *mut *mut ::c_void) -> ::c_int; pub fn pthread_exit(value: *mut ::c_void) -> !; pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getstacksize( attr: *const ::pthread_attr_t, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setstacksize(attr: *mut ::pthread_attr_t, stack_size: ::size_t) -> ::c_int; pub fn pthread_attr_setdetachstate(attr: *mut ::pthread_attr_t, state: ::c_int) -> ::c_int; pub fn pthread_detach(thread: ::pthread_t) -> ::c_int; pub fn sched_yield() -> ::c_int; pub fn pthread_key_create( key: *mut pthread_key_t, dtor: ::Option, ) -> ::c_int; pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void; pub fn pthread_setspecific(key: pthread_key_t, value: *const ::c_void) -> ::c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> ::c_int; pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> ::c_int; pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> ::c_int; pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: ::c_int) -> ::c_int; pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> ::c_int; pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_cond_timedwait( cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> ::c_int; pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> ::c_int; pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> ::c_int; pub fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> ::c_int; pub fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> ::c_int; pub fn pthread_rwlock_init( lock: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t, ) -> ::c_int; pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> ::c_int; pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> ::c_int; pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn getsockopt( sockfd: ::c_int, level: ::c_int, optname: ::c_int, optval: *mut ::c_void, optlen: *mut ::socklen_t, ) -> ::c_int; pub fn raise(signum: ::c_int) -> ::c_int; pub fn sigaction(signum: ::c_int, act: *const sigaction, oldact: *mut sigaction) -> ::c_int; pub fn utimes(filename: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn dlopen(filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; pub fn dlerror() -> *mut ::c_char; pub fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void; pub fn dlclose(handle: *mut ::c_void) -> ::c_int; pub fn dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int; pub fn getaddrinfo( node: *const c_char, service: *const c_char, hints: *const addrinfo, res: *mut *mut addrinfo, ) -> ::c_int; pub fn freeaddrinfo(res: *mut addrinfo); pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char; pub fn res_init() -> ::c_int; pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn mktime(tm: *mut tm) -> time_t; pub fn time(time: *mut time_t) -> time_t; pub fn gmtime(time_p: *const time_t) -> *mut tm; pub fn localtime(time_p: *const time_t) -> *mut tm; pub fn mknod(pathname: *const ::c_char, mode: ::mode_t, dev: ::dev_t) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn getservbyname(name: *const ::c_char, proto: *const ::c_char) -> *mut servent; pub fn getprotobyname(name: *const ::c_char) -> *mut protoent; pub fn getprotobynumber(proto: ::c_int) -> *mut protoent; pub fn usleep(secs: ::c_uint) -> ::c_int; pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; pub fn putenv(string: *mut c_char) -> ::c_int; pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; pub fn select( nfds: ::c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *mut timeval, ) -> ::c_int; pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; pub fn localeconv() -> *mut lconv; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_wait(sem: *mut sem_t) -> ::c_int; pub fn sem_trywait(sem: *mut sem_t) -> ::c_int; pub fn sem_post(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> ::c_int; pub fn fstatvfs(fd: ::c_int, buf: *mut statvfs) -> ::c_int; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t; pub fn sigemptyset(set: *mut sigset_t) -> ::c_int; pub fn sigaddset(set: *mut sigset_t, signum: ::c_int) -> ::c_int; pub fn sigfillset(set: *mut sigset_t) -> ::c_int; pub fn sigdelset(set: *mut sigset_t, signum: ::c_int) -> ::c_int; pub fn sigismember(set: *const sigset_t, signum: ::c_int) -> ::c_int; pub fn sigprocmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sigpending(set: *mut sigset_t) -> ::c_int; pub fn timegm(tm: *mut ::tm) -> time_t; pub fn getsid(pid: pid_t) -> pid_t; pub fn sysconf(name: ::c_int) -> ::c_long; pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int; pub fn pselect( nfds: ::c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *const timespec, sigmask: *const sigset_t, ) -> ::c_int; pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; pub fn tcdrain(fd: ::c_int) -> ::c_int; pub fn cfgetispeed(termios: *const ::termios) -> ::speed_t; pub fn cfgetospeed(termios: *const ::termios) -> ::speed_t; pub fn cfmakeraw(termios: *mut ::termios); pub fn cfsetispeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn cfsetospeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn cfsetspeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn tcgetattr(fd: ::c_int, termios: *mut ::termios) -> ::c_int; pub fn tcsetattr(fd: ::c_int, optional_actions: ::c_int, termios: *const ::termios) -> ::c_int; pub fn tcflow(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcflush(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcgetsid(fd: ::c_int) -> ::pid_t; pub fn tcsendbreak(fd: ::c_int, duration: ::c_int) -> ::c_int; pub fn mkstemp(template: *mut ::c_char) -> ::c_int; pub fn mkdtemp(template: *mut ::c_char) -> *mut ::c_char; pub fn tmpnam(ptr: *mut ::c_char) -> *mut ::c_char; pub fn openlog(ident: *const ::c_char, logopt: ::c_int, facility: ::c_int); pub fn closelog(); pub fn setlogmask(maskpri: ::c_int) -> ::c_int; pub fn syslog(priority: ::c_int, message: *const ::c_char, ...); pub fn grantpt(fd: ::c_int) -> ::c_int; pub fn posix_openpt(flags: ::c_int) -> ::c_int; pub fn ptsname(fd: ::c_int) -> *mut ::c_char; pub fn unlockpt(fd: ::c_int) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn setgroups(ngroups: ::size_t, ptr: *const ::gid_t) -> ::c_int; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int, ) -> ::c_int; pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; pub fn clearenv() -> ::c_int; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; pub fn setreuid(ruid: ::uid_t, euid: ::uid_t) -> ::c_int; pub fn setregid(rgid: ::gid_t, egid: ::gid_t) -> ::c_int; pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, suid: *mut ::uid_t) -> ::c_int; pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, sgid: *mut ::gid_t) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; pub fn brk(addr: *mut ::c_void) -> ::c_int; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *const termios, winp: *const ::winsize, ) -> ::c_int; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn fexecve( fd: ::c_int, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; // System V IPC pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int; pub fn semop(semid: ::c_int, sops: *mut ::sembuf, nsops: ::size_t) -> ::c_int; pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn msgsnd( msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, msgflg: ::c_int, ) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn __errno_location() -> *mut ::c_int; pub fn fallocate(fd: ::c_int, mode: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn readahead(fd: ::c_int, offset: ::off64_t, count: ::size_t) -> ::ssize_t; pub fn signalfd(fd: ::c_int, mask: *const ::sigset_t, flags: ::c_int) -> ::c_int; pub fn timerfd_create(clockid: ::c_int, flags: ::c_int) -> ::c_int; pub fn timerfd_gettime(fd: ::c_int, curr_value: *mut itimerspec) -> ::c_int; pub fn timerfd_settime( fd: ::c_int, flags: ::c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> ::c_int; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn quotactl( cmd: ::c_int, special: *const ::c_char, id: ::c_int, data: *mut ::c_char, ) -> ::c_int; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn reboot(how_to: ::c_int) -> ::c_int; pub fn setfsgid(gid: ::gid_t) -> ::c_int; pub fn setfsuid(uid: ::uid_t) -> ::c_int; // Not available now on Android pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn sync_file_range( fd: ::c_int, offset: ::off64_t, nbytes: ::off64_t, flags: ::c_uint, ) -> ::c_int; pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn glob( pattern: *const c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn vhangup() -> ::c_int; pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint, flags: ::c_int, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint, flags: ::c_int, timeout: *mut ::timespec, ) -> ::c_int; pub fn sync(); pub fn syscall(num: ::c_long, ...) -> ::c_long; pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) -> ::c_int; pub fn sched_setaffinity( pid: ::pid_t, cpusetsize: ::size_t, cpuset: *const cpu_set_t, ) -> ::c_int; pub fn umount(target: *const ::c_char) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn tee(fd_in: ::c_int, fd_out: ::c_int, len: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn splice( fd_in: ::c_int, off_in: *mut ::loff_t, fd_out: ::c_int, off_out: *mut ::loff_t, len: ::size_t, flags: ::c_uint, ) -> ::ssize_t; pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn swapoff(puath: *const ::c_char) -> ::c_int; pub fn vmsplice( fd: ::c_int, iov: *const ::iovec, nr_segs: ::size_t, flags: ::c_uint, ) -> ::ssize_t; pub fn mount( src: *const ::c_char, target: *const ::c_char, fstype: *const ::c_char, flags: ::c_ulong, data: *const ::c_void, ) -> ::c_int; pub fn personality(persona: ::c_ulong) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int; pub fn ppoll( fds: *mut ::pollfd, nfds: nfds_t, timeout: *const ::timespec, sigmask: *const sigset_t, ) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn clone( cb: extern "C" fn(*mut ::c_void) -> ::c_int, child_stack: *mut ::c_void, flags: ::c_int, arg: *mut ::c_void, ... ) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; pub fn umount2(target: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn swapon(path: *const ::c_char, swapflags: ::c_int) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut ::group; pub fn getgrouplist( user: *const ::c_char, group: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut ::dl_phdr_info, size: ::size_t, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(any(target_arch = "riscv64"))] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } cfg_if! { if #[cfg(libc_align)] { #[macro_use] mod align; } else { #[macro_use] mod no_align; } } expand_align!(); cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } libc/src/fuchsia/aarch64.rs0000644000175000017500000000364014661133735016464 0ustar jamespagejamespagepub type c_char = u8; pub type __u64 = ::c_ulonglong; pub type wchar_t = u32; pub type nlink_t = ::c_ulong; pub type blksize_t = ::c_long; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad0: ::c_ulong, pub st_size: ::off_t, pub st_blksize: ::blksize_t, __pad1: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_uint; 2], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad0: ::c_ulong, pub st_size: ::off_t, pub st_blksize: ::blksize_t, __pad1: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_uint; 2], } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } } // From https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/third_party/ulib/musl/include/bits/signal.h;l=20-21;drc=0827b18ab9540c46f8037f407d17ea15a79e9ba7 pub const MINSIGSTKSZ: ::size_t = 6144; pub const SIGSTKSZ: ::size_t = 12288; libc/src/fuchsia/no_align.rs0000644000175000017500000001165414661133735017026 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { pub struct pthread_mutexattr_t { #[cfg(target_arch = "x86_64")] __align: [::c_int; 0], #[cfg(not(target_arch = "x86_64"))] __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } pub struct pthread_rwlockattr_t { __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCKATTR_T], } pub struct pthread_condattr_t { __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } s_no_extra_traits! { pub struct pthread_mutex_t { #[cfg(any(target_arch = "arm", all(target_arch = "x86_64", target_pointer_width = "32")))] __align: [::c_long; 0], #[cfg(not(any(target_arch = "arm", all(target_arch = "x86_64", target_pointer_width = "32"))))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } pub struct pthread_rwlock_t { __align: [::c_long; 0], __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } pub struct pthread_cond_t { __align: [*const ::c_void; 0], #[cfg(not(target_env = "musl"))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_COND_T], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { // Ignore __align field self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_cond_t {} impl ::fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_cond_t") // Ignore __align field // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { // Ignore __align field self.size.hash(state); } } impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { // Ignore __align field self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_mutex_t {} impl ::fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_mutex_t") // Ignore __align field // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { // Ignore __align field self.size.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { // Ignore __align field self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_rwlock_t {} impl ::fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_rwlock_t") // Ignore __align field // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { // Ignore __align field self.size.hash(state); } } } } }; } libc/src/fuchsia/align.rs0000644000175000017500000001255014661133735016326 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { #[cfg_attr( any( target_pointer_width = "32", target_arch = "x86_64" ), repr(align(4)))] #[cfg_attr( not(any( target_pointer_width = "32", target_arch = "x86_64" )), repr(align(8)))] pub struct pthread_mutexattr_t { size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct pthread_rwlockattr_t { size: [u8; ::__SIZEOF_PTHREAD_RWLOCKATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } s_no_extra_traits! { #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "arm", target_arch = "x86_64")), repr(align(4)))] #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "arm", target_arch = "x86_64"))), repr(align(8)))] pub struct pthread_mutex_t { size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "arm", target_arch = "x86_64")), repr(align(4)))] #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "arm", target_arch = "x86_64"))), repr(align(8)))] pub struct pthread_rwlock_t { size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] #[cfg_attr(target_arch = "x86", repr(align(4)))] #[cfg_attr(not(target_arch = "x86"), repr(align(8)))] pub struct pthread_cond_t { size: [u8; ::__SIZEOF_PTHREAD_COND_T], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_cond_t {} impl ::fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_cond_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_mutex_t {} impl ::fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_mutex_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_rwlock_t {} impl ::fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_rwlock_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } } } }; } libc/src/lib.rs0000644000175000017500000001101614661133735014354 0ustar jamespagejamespage//! libc - Raw FFI bindings to platforms' system libraries #![crate_name = "libc"] #![crate_type = "rlib"] #![allow( renamed_and_removed_lints, // Keep this order. unknown_lints, // Keep this order. bad_style, overflowing_literals, improper_ctypes, // This lint is renamed but we run CI for old stable rustc so should be here. redundant_semicolon, redundant_semicolons, unused_macros, unused_macro_rules, )] #![cfg_attr(libc_deny_warnings, deny(warnings))] // Attributes needed when building as part of the standard library #![cfg_attr(feature = "rustc-dep-of-std", feature(link_cfg, no_core))] #![cfg_attr(libc_thread_local, feature(thread_local))] // Enable extra lints: #![cfg_attr(feature = "extra_traits", deny(missing_debug_implementations))] #![deny(missing_copy_implementations, safe_packed_borrows)] #![cfg_attr(not(feature = "rustc-dep-of-std"), no_std)] #![cfg_attr(feature = "rustc-dep-of-std", no_core)] #![cfg_attr(libc_const_extern_fn_unstable, feature(const_extern_fn))] #[macro_use] mod macros; cfg_if! { if #[cfg(feature = "rustc-dep-of-std")] { extern crate rustc_std_workspace_core as core; #[allow(unused_imports)] use core::iter; #[allow(unused_imports)] use core::ops; #[allow(unused_imports)] use core::option; } } cfg_if! { if #[cfg(libc_priv_mod_use)] { #[cfg(libc_core_cvoid)] #[allow(unused_imports)] use core::ffi; #[allow(unused_imports)] use core::fmt; #[allow(unused_imports)] use core::hash; #[allow(unused_imports)] use core::num; #[allow(unused_imports)] use core::mem; #[doc(hidden)] #[allow(unused_imports)] use core::clone::Clone; #[doc(hidden)] #[allow(unused_imports)] use core::marker::{Copy, Send, Sync}; #[doc(hidden)] #[allow(unused_imports)] use core::option::Option; } else { #[doc(hidden)] #[allow(unused_imports)] pub use core::fmt; #[doc(hidden)] #[allow(unused_imports)] pub use core::hash; #[doc(hidden)] #[allow(unused_imports)] pub use core::num; #[doc(hidden)] #[allow(unused_imports)] pub use core::mem; #[doc(hidden)] #[allow(unused_imports)] pub use core::clone::Clone; #[doc(hidden)] #[allow(unused_imports)] pub use core::marker::{Copy, Send, Sync}; #[doc(hidden)] #[allow(unused_imports)] pub use core::option::Option; } } cfg_if! { if #[cfg(windows)] { mod fixed_width_ints; pub use fixed_width_ints::*; mod windows; pub use windows::*; } else if #[cfg(target_os = "fuchsia")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod fuchsia; pub use fuchsia::*; } else if #[cfg(target_os = "switch")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod switch; pub use switch::*; } else if #[cfg(target_os = "psp")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod psp; pub use psp::*; } else if #[cfg(target_os = "vxworks")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod vxworks; pub use vxworks::*; } else if #[cfg(target_os = "solid_asp3")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod solid; pub use solid::*; } else if #[cfg(unix)] { mod fixed_width_ints; pub use fixed_width_ints::*; mod unix; pub use unix::*; } else if #[cfg(target_os = "hermit")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod hermit; pub use hermit::*; } else if #[cfg(target_os = "teeos")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod teeos; pub use teeos::*; } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] { mod fixed_width_ints; pub use fixed_width_ints::*; mod sgx; pub use sgx::*; } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] { mod fixed_width_ints; pub use fixed_width_ints::*; mod wasi; pub use wasi::*; } else if #[cfg(target_os = "xous")] { mod fixed_width_ints; pub use fixed_width_ints::*; mod xous; pub use xous::*; } else { // non-supported targets: empty... } } libc/src/solid/0000775000175000017500000000000014661133735014355 5ustar jamespagejamespagelibc/src/solid/arm.rs0000644000175000017500000000013514661133735015477 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = u32; pub type c_long = i32; pub type c_ulong = u32; libc/src/solid/mod.rs0000644000175000017500000010065714661133735015511 0ustar jamespagejamespage//! Interface to the [SOLID] C library //! //! [SOLID]: https://solid.kmckk.com/ pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type uintptr_t = usize; pub type intptr_t = isize; pub type ptrdiff_t = isize; pub type size_t = ::uintptr_t; pub type ssize_t = ::intptr_t; pub type clock_t = c_uint; pub type time_t = i64; pub type clockid_t = c_int; pub type timer_t = c_int; pub type suseconds_t = c_int; pub type useconds_t = c_uint; pub type sighandler_t = size_t; // sys/ansi.h pub type __caddr_t = *mut c_char; pub type __gid_t = u32; pub type __in_addr_t = u32; pub type __in_port_t = u16; pub type __mode_t = u32; pub type __off_t = i64; pub type __pid_t = i32; pub type __sa_family_t = u8; pub type __socklen_t = c_uint; pub type __uid_t = u32; pub type __fsblkcnt_t = u64; pub type __fsfilcnt_t = u64; // locale.h pub type locale_t = usize; // nl_types.h pub type nl_item = c_long; // sys/types.h pub type __va_list = *mut c_char; pub type u_int8_t = u8; pub type u_int16_t = u16; pub type u_int32_t = u32; pub type u_int64_t = u64; pub type u_char = c_uchar; pub type u_short = c_ushort; pub type u_int = c_uint; pub type u_long = c_ulong; pub type unchar = c_uchar; pub type ushort = c_ushort; pub type uint = c_uint; pub type ulong = c_ulong; pub type u_quad_t = u64; pub type quad_t = i64; pub type qaddr_t = *mut quad_t; pub type longlong_t = i64; pub type u_longlong_t = u64; pub type blkcnt_t = i64; pub type blksize_t = i32; pub type fsblkcnt_t = __fsblkcnt_t; pub type fsfilcnt_t = __fsfilcnt_t; pub type caddr_t = __caddr_t; pub type daddr_t = i64; pub type dev_t = u64; pub type fixpt_t = u32; pub type gid_t = __gid_t; pub type idtype_t = c_int; pub type id_t = u32; pub type ino_t = u64; pub type key_t = c_long; pub type mode_t = __mode_t; pub type nlink_t = u32; pub type off_t = __off_t; pub type pid_t = __pid_t; pub type lwpid_t = i32; pub type rlim_t = u64; pub type segsz_t = i32; pub type swblk_t = i32; pub type mqd_t = c_int; pub type cpuid_t = c_ulong; pub type psetid_t = c_int; s! { // stat.h pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: c_short, pub st_nlink: c_short, pub st_uid: c_short, pub st_gid: c_short, pub st_rdev: dev_t, pub st_size: off_t, pub st_atime: time_t, pub st_mtime: time_t, pub st_ctime: time_t, pub st_blksize: blksize_t, } // time.h pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub tm_gmtoff: c_long, pub tm_zone: *mut c_char, } // stdlib.h pub struct qdiv_t { pub quot: quad_t, pub rem: quad_t, } pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong, } pub struct div_t { pub quot: c_int, pub rem: c_int, } pub struct ldiv_t { pub quot: c_long, pub rem: c_long, } // locale.h pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_n_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct timeval { pub tv_sec: c_long, pub tv_usec: c_long, } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const EXIT_FAILURE: c_int = 1; pub const EXIT_SUCCESS: c_int = 0; pub const RAND_MAX: c_int = 0x7fffffff; pub const EOF: c_int = -1; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const BUFSIZ: c_uint = 1024; pub const FOPEN_MAX: c_uint = 20; pub const FILENAME_MAX: c_uint = 1024; pub const O_RDONLY: c_int = 1; pub const O_WRONLY: c_int = 2; pub const O_RDWR: c_int = 4; pub const O_APPEND: c_int = 8; pub const O_CREAT: c_int = 0x10; pub const O_EXCL: c_int = 0x400; pub const O_TEXT: c_int = 0x100; pub const O_BINARY: c_int = 0x200; pub const O_TRUNC: c_int = 0x20; pub const S_IEXEC: c_short = 0x0040; pub const S_IWRITE: c_short = 0x0080; pub const S_IREAD: c_short = 0x0100; pub const S_IFCHR: c_short = 0x2000; pub const S_IFDIR: c_short = 0x4000; pub const S_IFMT: c_short = 0o160000; pub const S_IFIFO: c_short = 0o0010000; pub const S_IFBLK: c_short = 0o0060000; pub const S_IFREG: c_short = 0o0100000; pub const LC_ALL: c_int = 0; pub const LC_COLLATE: c_int = 1; pub const LC_CTYPE: c_int = 2; pub const LC_MONETARY: c_int = 3; pub const LC_NUMERIC: c_int = 4; pub const LC_TIME: c_int = 5; pub const LC_MESSAGES: c_int = 6; pub const _LC_LAST: c_int = 7; pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const EWOULDBLOCK: c_int = EAGAIN; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = EDEADLK; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EMULTIHOP: c_int = 72; pub const EDOTDOT: c_int = 73; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPORT: c_int = 93; pub const ESOCKTNOSUPPORT: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ENOTSUP: c_int = 132; pub const EFTYPE: c_int = 133; // signal codes pub const SIGHUP: c_int = 1; pub const SIGINT: c_int = 2; pub const SIGQUIT: c_int = 3; pub const SIGILL: c_int = 4; pub const SIGTRAP: c_int = 5; pub const SIGABRT: c_int = 6; pub const SIGIOT: c_int = SIGABRT; pub const SIGEMT: c_int = 7; pub const SIGFPE: c_int = 8; pub const SIGKILL: c_int = 9; pub const SIGBUS: c_int = 10; pub const SIGSEGV: c_int = 11; pub const SIGSYS: c_int = 12; pub const SIGPIPE: c_int = 13; pub const SIGALRM: c_int = 14; pub const SIGTERM: c_int = 15; pub const SIGURG: c_int = 16; pub const SIGSTOP: c_int = 17; pub const SIGTSTP: c_int = 18; pub const SIGCONT: c_int = 19; pub const SIGCHLD: c_int = 20; pub const SIGTTIN: c_int = 21; pub const SIGTTOU: c_int = 22; pub const SIGIO: c_int = 23; pub const SIGXCPU: c_int = 24; pub const SIGXFSZ: c_int = 25; pub const SIGVTALRM: c_int = 26; pub const SIGPROF: c_int = 27; pub const SIGWINCH: c_int = 28; pub const SIGINFO: c_int = 29; pub const SIGUSR1: c_int = 30; pub const SIGUSR2: c_int = 31; pub const SIGPWR: c_int = 32; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl ::Copy for FILE {} impl ::Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} impl ::Copy for fpos_t {} impl ::Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } extern "C" { // ctype.h pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; // stdio.h pub fn __get_stdio_file(fileno: c_int) -> *mut FILE; pub fn clearerr(arg1: *mut FILE); pub fn fclose(arg1: *mut FILE) -> c_int; pub fn feof(arg1: *mut FILE) -> c_int; pub fn ferror(arg1: *mut FILE) -> c_int; pub fn fflush(arg1: *mut FILE) -> c_int; pub fn fgetc(arg1: *mut FILE) -> c_int; pub fn fgets(arg1: *mut c_char, arg2: c_int, arg3: *mut FILE) -> *mut c_char; pub fn fopen(arg1: *const c_char, arg2: *const c_char) -> *mut FILE; pub fn fprintf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn fputc(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn fputs(arg1: *const c_char, arg2: *mut FILE) -> c_int; pub fn fread(arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: *mut FILE) -> size_t; pub fn freopen(arg1: *const c_char, arg2: *const c_char, arg3: *mut FILE) -> *mut FILE; pub fn fscanf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn fseek(arg1: *mut FILE, arg2: c_long, arg3: c_int) -> c_int; pub fn ftell(arg1: *mut FILE) -> c_long; pub fn fwrite(arg1: *const c_void, arg2: size_t, arg3: size_t, arg4: *mut FILE) -> size_t; pub fn getc(arg1: *mut FILE) -> c_int; pub fn getchar() -> c_int; pub fn perror(arg1: *const c_char); pub fn printf(arg1: *const c_char, ...) -> c_int; pub fn putc(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn putchar(arg1: c_int) -> c_int; pub fn puts(arg1: *const c_char) -> c_int; pub fn remove(arg1: *const c_char) -> c_int; pub fn rewind(arg1: *mut FILE); pub fn scanf(arg1: *const c_char, ...) -> c_int; pub fn setbuf(arg1: *mut FILE, arg2: *mut c_char); pub fn setvbuf(arg1: *mut FILE, arg2: *mut c_char, arg3: c_int, arg4: size_t) -> c_int; pub fn sscanf(arg1: *const c_char, arg2: *const c_char, ...) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn ungetc(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn vfprintf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vprintf(arg1: *const c_char, arg2: __va_list) -> c_int; pub fn gets(arg1: *mut c_char) -> *mut c_char; pub fn sprintf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn tmpnam(arg1: *const c_char) -> *mut c_char; pub fn vsprintf(arg1: *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn rename(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn asiprintf(arg1: *mut *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn fiprintf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn fiscanf(arg1: *mut FILE, arg2: *const c_char, ...) -> c_int; pub fn iprintf(arg1: *const c_char, ...) -> c_int; pub fn iscanf(arg1: *const c_char, ...) -> c_int; pub fn siprintf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn siscanf(arg1: *mut c_char, arg2: *const c_char, ...) -> c_int; pub fn sniprintf(arg1: *mut c_char, arg2: size_t, arg3: *const c_char, ...) -> c_int; pub fn vasiprintf(arg1: *mut *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vfiprintf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vfiscanf(arg1: *mut FILE, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn viprintf(arg1: *const c_char, arg2: __va_list) -> c_int; pub fn viscanf(arg1: *const c_char, arg2: __va_list) -> c_int; pub fn vsiprintf(arg1: *mut c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vsiscanf(arg1: *const c_char, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn vsniprintf( arg1: *mut c_char, arg2: size_t, arg3: *const c_char, arg4: __va_list, ) -> c_int; pub fn vdiprintf(arg1: c_int, arg2: *const c_char, arg3: __va_list) -> c_int; pub fn diprintf(arg1: c_int, arg2: *const c_char, ...) -> c_int; pub fn fgetpos(arg1: *mut FILE, arg2: *mut fpos_t) -> c_int; pub fn fsetpos(arg1: *mut FILE, arg2: *const fpos_t) -> c_int; pub fn fdopen(arg1: c_int, arg2: *const c_char) -> *mut FILE; pub fn fileno(arg1: *mut FILE) -> c_int; pub fn flockfile(arg1: *mut FILE); pub fn ftrylockfile(arg1: *mut FILE) -> c_int; pub fn funlockfile(arg1: *mut FILE); pub fn getc_unlocked(arg1: *mut FILE) -> c_int; pub fn getchar_unlocked() -> c_int; pub fn putc_unlocked(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn putchar_unlocked(arg1: c_int) -> c_int; pub fn snprintf(arg1: *mut c_char, arg2: size_t, arg3: *const c_char, ...) -> c_int; pub fn vsnprintf( arg1: *mut c_char, arg2: size_t, arg3: *const c_char, arg4: __va_list, ) -> c_int; pub fn getw(arg1: *mut FILE) -> c_int; pub fn putw(arg1: c_int, arg2: *mut FILE) -> c_int; pub fn tempnam(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn fseeko(stream: *mut FILE, offset: off_t, whence: c_int) -> c_int; pub fn ftello(stream: *mut FILE) -> off_t; // stdlib.h pub fn atof(arg1: *const c_char) -> f64; pub fn strtod(arg1: *const c_char, arg2: *mut *mut c_char) -> f64; pub fn drand48() -> f64; pub fn erand48(arg1: *mut c_ushort) -> f64; pub fn strtof(arg1: *const c_char, arg2: *mut *mut c_char) -> f32; pub fn strtold(arg1: *const c_char, arg2: *mut *mut c_char) -> f64; pub fn strtod_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f64; pub fn strtof_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f32; pub fn strtold_l(arg1: *const c_char, arg2: *mut *mut c_char, arg3: locale_t) -> f64; pub fn _Exit(arg1: c_int) -> !; pub fn abort() -> !; pub fn abs(arg1: c_int) -> c_int; pub fn atexit(arg1: ::Option) -> c_int; pub fn atoi(arg1: *const c_char) -> c_int; pub fn atol(arg1: *const c_char) -> c_long; pub fn itoa(arg1: c_int, arg2: *mut c_char, arg3: c_int) -> *mut c_char; pub fn ltoa(arg1: c_long, arg2: *mut c_char, arg3: c_int) -> *mut c_char; pub fn ultoa(arg1: c_ulong, arg2: *mut c_char, arg3: c_int) -> *mut c_char; pub fn bsearch( arg1: *const c_void, arg2: *const c_void, arg3: size_t, arg4: size_t, arg5: ::Option c_int>, ) -> *mut c_void; pub fn calloc(arg1: size_t, arg2: size_t) -> *mut c_void; pub fn div(arg1: c_int, arg2: c_int) -> div_t; pub fn exit(arg1: c_int) -> !; pub fn free(arg1: *mut c_void); pub fn getenv(arg1: *const c_char) -> *mut c_char; pub fn labs(arg1: c_long) -> c_long; pub fn ldiv(arg1: c_long, arg2: c_long) -> ldiv_t; pub fn malloc(arg1: size_t) -> *mut c_void; pub fn qsort( arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: ::Option c_int>, ); pub fn rand() -> c_int; pub fn realloc(arg1: *mut c_void, arg2: size_t) -> *mut c_void; pub fn srand(arg1: c_uint); pub fn strtol(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_long; pub fn strtoul(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulong; pub fn mblen(arg1: *const c_char, arg2: size_t) -> c_int; pub fn mbstowcs(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t) -> size_t; pub fn wctomb(arg1: *mut c_char, arg2: wchar_t) -> c_int; pub fn mbtowc(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t) -> c_int; pub fn wcstombs(arg1: *mut c_char, arg2: *const wchar_t, arg3: size_t) -> size_t; pub fn rand_r(arg1: *mut c_uint) -> c_int; pub fn jrand48(arg1: *mut c_ushort) -> c_long; pub fn lcong48(arg1: *mut c_ushort); pub fn lrand48() -> c_long; pub fn mrand48() -> c_long; pub fn nrand48(arg1: *mut c_ushort) -> c_long; pub fn seed48(arg1: *mut c_ushort) -> *mut c_ushort; pub fn srand48(arg1: c_long); pub fn putenv(arg1: *mut c_char) -> c_int; pub fn a64l(arg1: *const c_char) -> c_long; pub fn l64a(arg1: c_long) -> *mut c_char; pub fn random() -> c_long; pub fn setstate(arg1: *mut c_char) -> *mut c_char; pub fn initstate(arg1: c_uint, arg2: *mut c_char, arg3: size_t) -> *mut c_char; pub fn srandom(arg1: c_uint); pub fn mkostemp(arg1: *mut c_char, arg2: c_int) -> c_int; pub fn mkostemps(arg1: *mut c_char, arg2: c_int, arg3: c_int) -> c_int; pub fn mkdtemp(arg1: *mut c_char) -> *mut c_char; pub fn mkstemp(arg1: *mut c_char) -> c_int; pub fn mktemp(arg1: *mut c_char) -> *mut c_char; pub fn atoll(arg1: *const c_char) -> c_longlong; pub fn llabs(arg1: c_longlong) -> c_longlong; pub fn lldiv(arg1: c_longlong, arg2: c_longlong) -> lldiv_t; pub fn strtoll(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_longlong; pub fn strtoull(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulonglong; pub fn aligned_alloc(arg1: size_t, arg2: size_t) -> *mut c_void; pub fn at_quick_exit(arg1: ::Option) -> c_int; pub fn quick_exit(arg1: c_int); pub fn setenv(arg1: *const c_char, arg2: *const c_char, arg3: c_int) -> c_int; pub fn unsetenv(arg1: *const c_char) -> c_int; pub fn humanize_number( arg1: *mut c_char, arg2: size_t, arg3: i64, arg4: *const c_char, arg5: c_int, arg6: c_int, ) -> c_int; pub fn dehumanize_number(arg1: *const c_char, arg2: *mut i64) -> c_int; pub fn getenv_r(arg1: *const c_char, arg2: *mut c_char, arg3: size_t) -> c_int; pub fn heapsort( arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: ::Option c_int>, ) -> c_int; pub fn mergesort( arg1: *mut c_void, arg2: size_t, arg3: size_t, arg4: ::Option c_int>, ) -> c_int; pub fn radixsort( arg1: *mut *const c_uchar, arg2: c_int, arg3: *const c_uchar, arg4: c_uint, ) -> c_int; pub fn sradixsort( arg1: *mut *const c_uchar, arg2: c_int, arg3: *const c_uchar, arg4: c_uint, ) -> c_int; pub fn getprogname() -> *const c_char; pub fn setprogname(arg1: *const c_char); pub fn qabs(arg1: quad_t) -> quad_t; pub fn strtoq(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> quad_t; pub fn strtouq(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> u_quad_t; pub fn strsuftoll( arg1: *const c_char, arg2: *const c_char, arg3: c_longlong, arg4: c_longlong, ) -> c_longlong; pub fn strsuftollx( arg1: *const c_char, arg2: *const c_char, arg3: c_longlong, arg4: c_longlong, arg5: *mut c_char, arg6: size_t, ) -> c_longlong; pub fn l64a_r(arg1: c_long, arg2: *mut c_char, arg3: c_int) -> c_int; pub fn qdiv(arg1: quad_t, arg2: quad_t) -> qdiv_t; pub fn strtol_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_long; pub fn strtoul_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_ulong; pub fn strtoll_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_longlong; pub fn strtoull_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> c_ulonglong; pub fn strtoq_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> quad_t; pub fn strtouq_l( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, arg4: locale_t, ) -> u_quad_t; pub fn _mb_cur_max_l(arg1: locale_t) -> size_t; pub fn mblen_l(arg1: *const c_char, arg2: size_t, arg3: locale_t) -> c_int; pub fn mbstowcs_l( arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t, arg4: locale_t, ) -> size_t; pub fn wctomb_l(arg1: *mut c_char, arg2: wchar_t, arg3: locale_t) -> c_int; pub fn mbtowc_l(arg1: *mut wchar_t, arg2: *const c_char, arg3: size_t, arg4: locale_t) -> c_int; pub fn wcstombs_l( arg1: *mut c_char, arg2: *const wchar_t, arg3: size_t, arg4: locale_t, ) -> size_t; // string.h pub fn memchr(arg1: *const c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn memcmp(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; pub fn memcpy(arg1: *mut c_void, arg2: *const c_void, arg3: size_t) -> *mut c_void; pub fn memmove(arg1: *mut c_void, arg2: *const c_void, arg3: size_t) -> *mut c_void; pub fn memset(arg1: *mut c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn strcat(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn strchr(arg1: *const c_char, arg2: c_int) -> *mut c_char; pub fn strcmp(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn strcoll(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn strcpy(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn strcspn(arg1: *const c_char, arg2: *const c_char) -> size_t; pub fn strerror(arg1: c_int) -> *mut c_char; pub fn strlen(arg1: *const c_char) -> size_t; pub fn strncat(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; pub fn strncmp(arg1: *const c_char, arg2: *const c_char, arg3: size_t) -> c_int; pub fn strncpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; pub fn strpbrk(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn strrchr(arg1: *const c_char, arg2: c_int) -> *mut c_char; pub fn strspn(arg1: *const c_char, arg2: *const c_char) -> size_t; pub fn strstr(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn strtok(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn strtok_r(arg1: *mut c_char, arg2: *const c_char, arg3: *mut *mut c_char) -> *mut c_char; pub fn strerror_r(arg1: c_int, arg2: *mut c_char, arg3: size_t) -> c_int; pub fn strxfrm(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; pub fn memccpy( arg1: *mut c_void, arg2: *const c_void, arg3: c_int, arg4: size_t, ) -> *mut c_void; pub fn strdup(arg1: *const c_char) -> *mut c_char; pub fn stpcpy(arg1: *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn stpncpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> *mut c_char; pub fn strnlen(arg1: *const c_char, arg2: size_t) -> size_t; pub fn memmem( arg1: *const c_void, arg2: size_t, arg3: *const c_void, arg4: size_t, ) -> *mut c_void; pub fn strcasestr(arg1: *const c_char, arg2: *const c_char) -> *mut c_char; pub fn strlcat(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; pub fn strlcpy(arg1: *mut c_char, arg2: *const c_char, arg3: size_t) -> size_t; pub fn strsep(arg1: *mut *mut c_char, arg2: *const c_char) -> *mut c_char; pub fn stresep(arg1: *mut *mut c_char, arg2: *const c_char, arg3: c_int) -> *mut c_char; pub fn strndup(arg1: *const c_char, arg2: size_t) -> *mut c_char; pub fn memrchr(arg1: *const c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn explicit_memset(arg1: *mut c_void, arg2: c_int, arg3: size_t) -> *mut c_void; pub fn consttime_memequal(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; pub fn strcoll_l(arg1: *const c_char, arg2: *const c_char, arg3: locale_t) -> c_int; pub fn strxfrm_l( arg1: *mut c_char, arg2: *const c_char, arg3: size_t, arg4: locale_t, ) -> size_t; pub fn strerror_l(arg1: c_int, arg2: locale_t) -> *mut c_char; // strings.h pub fn bcmp(arg1: *const c_void, arg2: *const c_void, arg3: size_t) -> c_int; pub fn bcopy(arg1: *const c_void, arg2: *mut c_void, arg3: size_t); pub fn bzero(arg1: *mut c_void, arg2: size_t); pub fn ffs(arg1: c_int) -> c_int; pub fn popcount(arg1: c_uint) -> c_uint; pub fn popcountl(arg1: c_ulong) -> c_uint; pub fn popcountll(arg1: c_ulonglong) -> c_uint; pub fn popcount32(arg1: u32) -> c_uint; pub fn popcount64(arg1: u64) -> c_uint; pub fn rindex(arg1: *const c_char, arg2: c_int) -> *mut c_char; pub fn strcasecmp(arg1: *const c_char, arg2: *const c_char) -> c_int; pub fn strncasecmp(arg1: *const c_char, arg2: *const c_char, arg3: size_t) -> c_int; // signal.h pub fn signal(arg1: c_int, arg2: sighandler_t) -> sighandler_t; pub fn raise(arg1: c_int) -> c_int; // time.h pub fn asctime(arg1: *const tm) -> *mut c_char; pub fn clock() -> clock_t; pub fn ctime(arg1: *const time_t) -> *mut c_char; pub fn difftime(arg1: time_t, arg2: time_t) -> f64; pub fn gmtime(arg1: *const time_t) -> *mut tm; pub fn localtime(arg1: *const time_t) -> *mut tm; pub fn time(arg1: *mut time_t) -> time_t; pub fn mktime(arg1: *mut tm) -> time_t; pub fn strftime( arg1: *mut c_char, arg2: size_t, arg3: *const c_char, arg4: *const tm, ) -> size_t; pub fn utime(arg1: *const c_char, arg2: *mut time_t) -> c_int; pub fn asctime_r(arg1: *const tm, arg2: *mut c_char) -> *mut c_char; pub fn ctime_r(arg1: *const time_t, arg2: *mut c_char) -> *mut c_char; pub fn gmtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; pub fn localtime_r(arg1: *const time_t, arg2: *mut tm) -> *mut tm; // sys/stat.h pub fn stat(arg1: *const c_char, arg2: *mut stat) -> c_int; pub fn lstat(arg1: *const c_char, arg2: *mut stat) -> c_int; pub fn fstat(arg1: c_int, arg2: *mut stat) -> c_int; pub fn chmod(arg1: *const c_char, arg2: __mode_t) -> c_int; pub fn mkdir(arg1: *const c_char, arg2: __mode_t) -> c_int; // fcntl.h pub fn open(arg1: *const c_char, arg2: c_int, ...) -> c_int; pub fn creat(arg1: *const c_char, arg2: c_int) -> c_int; pub fn close(arg1: c_int) -> c_int; pub fn read(arg1: c_int, arg2: *mut c_void, arg3: c_int) -> c_int; pub fn write(arg1: c_int, arg2: *const c_void, arg3: c_int) -> c_int; pub fn unlink(arg1: *const c_char) -> c_int; pub fn tell(arg1: c_int) -> c_long; pub fn dup(arg1: c_int) -> c_int; pub fn dup2(arg1: c_int, arg2: c_int) -> c_int; pub fn access(arg1: *const c_char, arg2: c_int) -> c_int; pub fn rmdir(arg1: *const c_char) -> c_int; pub fn chdir(arg1: *const c_char) -> c_int; pub fn _exit(arg1: c_int); pub fn getwd(arg1: *mut c_char) -> *mut c_char; pub fn getcwd(arg1: *mut c_char, arg2: size_t) -> *mut c_char; pub static mut optarg: *mut c_char; pub static mut opterr: c_int; pub static mut optind: c_int; pub static mut optopt: c_int; pub static mut optreset: c_int; pub fn getopt(arg1: c_int, arg2: *mut *mut c_char, arg3: *const c_char) -> c_int; pub static mut suboptarg: *mut c_char; pub fn getsubopt( arg1: *mut *mut c_char, arg2: *const *mut c_char, arg3: *mut *mut c_char, ) -> c_int; pub fn fcntl(arg1: c_int, arg2: c_int, ...) -> c_int; pub fn getpid() -> pid_t; pub fn sleep(arg1: c_uint) -> c_uint; pub fn usleep(arg1: useconds_t) -> c_int; // locale.h pub fn localeconv() -> *mut lconv; pub fn setlocale(arg1: c_int, arg2: *const c_char) -> *mut c_char; pub fn duplocale(arg1: locale_t) -> locale_t; pub fn freelocale(arg1: locale_t); pub fn localeconv_l(arg1: locale_t) -> *mut lconv; pub fn newlocale(arg1: c_int, arg2: *const c_char, arg3: locale_t) -> locale_t; // langinfo.h pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn nl_langinfo_l(item: ::nl_item, locale: locale_t) -> *mut ::c_char; // malloc.h pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; // sys/types.h pub fn lseek(arg1: c_int, arg2: __off_t, arg3: c_int) -> __off_t; } cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(any(target_arch = "arm"))] { mod arm; pub use self::arm::*; } else { // Unknown target_arch } } libc/src/solid/aarch64.rs0000644000175000017500000000013514661133735016150 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = u32; pub type c_long = i64; pub type c_ulong = u64; libc/src/wasi.rs0000644000175000017500000007464714661133735014574 0ustar jamespagejamespageuse super::{Send, Sync}; pub use ffi::c_void; pub type c_char = i8; pub type c_uchar = u8; pub type c_schar = i8; pub type c_int = i32; pub type c_uint = u32; pub type c_short = i16; pub type c_ushort = u16; pub type c_long = i32; pub type c_ulong = u32; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ssize_t = isize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type off_t = i64; pub type pid_t = i32; pub type clock_t = c_longlong; pub type time_t = c_longlong; pub type c_double = f64; pub type c_float = f32; pub type ino_t = u64; pub type sigset_t = c_uchar; pub type suseconds_t = c_longlong; pub type mode_t = u32; pub type dev_t = u64; pub type uid_t = u32; pub type gid_t = u32; pub type nlink_t = u64; pub type blksize_t = c_long; pub type blkcnt_t = i64; pub type nfds_t = c_ulong; pub type wchar_t = i32; pub type nl_item = c_int; pub type __wasi_rights_t = u64; s_no_extra_traits! { #[repr(align(16))] #[allow(missing_debug_implementations)] pub struct max_align_t { priv_: [f64; 4] } } #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum __locale_struct {} pub type locale_t = *mut __locale_struct; s_paren! { // in wasi-libc clockid_t is const struct __clockid* (where __clockid is an opaque struct), // but that's an implementation detail that we don't want to have to deal with #[repr(transparent)] #[allow(dead_code)] pub struct clockid_t(*const u8); } unsafe impl Send for clockid_t {} unsafe impl Sync for clockid_t {} s! { #[repr(align(8))] pub struct fpos_t { data: [u8; 16], } pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub __tm_gmtoff: c_int, pub __tm_zone: *const c_char, pub __tm_nsec: c_int, } pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } pub struct tms { pub tms_utime: clock_t, pub tms_stime: clock_t, pub tms_cutime: clock_t, pub tms_cstime: clock_t, } pub struct itimerspec { pub it_interval: timespec, pub it_value: timespec, } pub struct iovec { pub iov_base: *mut c_void, pub iov_len: size_t, } pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, pub grouping: *mut c_char, pub int_curr_symbol: *mut c_char, pub currency_symbol: *mut c_char, pub mon_decimal_point: *mut c_char, pub mon_thousands_sep: *mut c_char, pub mon_grouping: *mut c_char, pub positive_sign: *mut c_char, pub negative_sign: *mut c_char, pub int_frac_digits: c_char, pub frac_digits: c_char, pub p_cs_precedes: c_char, pub p_sep_by_space: c_char, pub n_cs_precedes: c_char, pub n_sep_by_space: c_char, pub p_sign_posn: c_char, pub n_sign_posn: c_char, pub int_p_cs_precedes: c_char, pub int_p_sep_by_space: c_char, pub int_n_cs_precedes: c_char, pub int_n_sep_by_space: c_char, pub int_p_sign_posn: c_char, pub int_n_sign_posn: c_char, } pub struct pollfd { pub fd: c_int, pub events: c_short, pub revents: c_short, } pub struct rusage { pub ru_utime: timeval, pub ru_stime: timeval, } pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_nlink: nlink_t, pub st_mode: mode_t, pub st_uid: uid_t, pub st_gid: gid_t, __pad0: c_uint, pub st_rdev: dev_t, pub st_size: off_t, pub st_blksize: blksize_t, pub st_blocks: blkcnt_t, pub st_atim: timespec, pub st_mtim: timespec, pub st_ctim: timespec, __reserved: [c_longlong; 3], } } // Declare dirent outside of s! so that it doesn't implement Copy, Eq, Hash, // etc., since it contains a flexible array member with a dynamic size. #[repr(C)] #[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub struct dirent { pub d_ino: ino_t, pub d_type: c_uchar, /// d_name is declared in WASI libc as a flexible array member, which /// can't be directly expressed in Rust. As an imperfect workaround, /// declare it as a zero-length array instead. pub d_name: [c_char; 0], } pub const EXIT_SUCCESS: c_int = 0; pub const EXIT_FAILURE: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SEEK_SET: c_int = 0; pub const SEEK_CUR: c_int = 1; pub const SEEK_END: c_int = 2; pub const _IOFBF: c_int = 0; pub const _IONBF: c_int = 2; pub const _IOLBF: c_int = 1; pub const F_GETFD: c_int = 1; pub const F_SETFD: c_int = 2; pub const F_GETFL: c_int = 3; pub const F_SETFL: c_int = 4; pub const FD_CLOEXEC: c_int = 1; pub const FD_SETSIZE: size_t = 1024; pub const O_APPEND: c_int = 0x0001; pub const O_DSYNC: c_int = 0x0002; pub const O_NONBLOCK: c_int = 0x0004; pub const O_RSYNC: c_int = 0x0008; pub const O_SYNC: c_int = 0x0010; pub const O_CREAT: c_int = 0x0001 << 12; pub const O_DIRECTORY: c_int = 0x0002 << 12; pub const O_EXCL: c_int = 0x0004 << 12; pub const O_TRUNC: c_int = 0x0008 << 12; pub const O_NOFOLLOW: c_int = 0x01000000; pub const O_EXEC: c_int = 0x02000000; pub const O_RDONLY: c_int = 0x04000000; pub const O_SEARCH: c_int = 0x08000000; pub const O_WRONLY: c_int = 0x10000000; pub const O_CLOEXEC: c_int = 0x0; pub const O_RDWR: c_int = O_WRONLY | O_RDONLY; pub const O_ACCMODE: c_int = O_EXEC | O_RDWR | O_SEARCH; pub const O_NOCTTY: c_int = 0x0; pub const POSIX_FADV_DONTNEED: c_int = 4; pub const POSIX_FADV_NOREUSE: c_int = 5; pub const POSIX_FADV_NORMAL: c_int = 0; pub const POSIX_FADV_RANDOM: c_int = 2; pub const POSIX_FADV_SEQUENTIAL: c_int = 1; pub const POSIX_FADV_WILLNEED: c_int = 3; pub const AT_FDCWD: ::c_int = -2; pub const AT_EACCESS: c_int = 0x0; pub const AT_SYMLINK_NOFOLLOW: c_int = 0x1; pub const AT_SYMLINK_FOLLOW: c_int = 0x2; pub const AT_REMOVEDIR: c_int = 0x4; pub const UTIME_OMIT: c_long = 0xfffffffe; pub const UTIME_NOW: c_long = 0xffffffff; pub const S_IFIFO: mode_t = 49152; pub const S_IFCHR: mode_t = 8192; pub const S_IFBLK: mode_t = 24576; pub const S_IFDIR: mode_t = 16384; pub const S_IFREG: mode_t = 32768; pub const S_IFLNK: mode_t = 40960; pub const S_IFSOCK: mode_t = 49152; pub const S_IFMT: mode_t = 57344; pub const S_IRWXO: mode_t = 0x7; pub const S_IXOTH: mode_t = 0x1; pub const S_IWOTH: mode_t = 0x2; pub const S_IROTH: mode_t = 0x4; pub const S_IRWXG: mode_t = 0x38; pub const S_IXGRP: mode_t = 0x8; pub const S_IWGRP: mode_t = 0x10; pub const S_IRGRP: mode_t = 0x20; pub const S_IRWXU: mode_t = 0x1c0; pub const S_IXUSR: mode_t = 0x40; pub const S_IWUSR: mode_t = 0x80; pub const S_IRUSR: mode_t = 0x100; pub const S_ISVTX: mode_t = 0x200; pub const S_ISGID: mode_t = 0x400; pub const S_ISUID: mode_t = 0x800; pub const DT_UNKNOWN: u8 = 0; pub const DT_BLK: u8 = 1; pub const DT_CHR: u8 = 2; pub const DT_DIR: u8 = 3; pub const DT_REG: u8 = 4; pub const DT_LNK: u8 = 7; pub const FIONREAD: c_int = 1; pub const FIONBIO: c_int = 2; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const POLLIN: ::c_short = 0x1; pub const POLLOUT: ::c_short = 0x2; pub const POLLERR: ::c_short = 0x1000; pub const POLLHUP: ::c_short = 0x2000; pub const POLLNVAL: ::c_short = 0x4000; pub const POLLRDNORM: ::c_short = 0x1; pub const POLLWRNORM: ::c_short = 0x2; pub const E2BIG: c_int = 1; pub const EACCES: c_int = 2; pub const EADDRINUSE: c_int = 3; pub const EADDRNOTAVAIL: c_int = 4; pub const EAFNOSUPPORT: c_int = 5; pub const EAGAIN: c_int = 6; pub const EALREADY: c_int = 7; pub const EBADF: c_int = 8; pub const EBADMSG: c_int = 9; pub const EBUSY: c_int = 10; pub const ECANCELED: c_int = 11; pub const ECHILD: c_int = 12; pub const ECONNABORTED: c_int = 13; pub const ECONNREFUSED: c_int = 14; pub const ECONNRESET: c_int = 15; pub const EDEADLK: c_int = 16; pub const EDESTADDRREQ: c_int = 17; pub const EDOM: c_int = 18; pub const EDQUOT: c_int = 19; pub const EEXIST: c_int = 20; pub const EFAULT: c_int = 21; pub const EFBIG: c_int = 22; pub const EHOSTUNREACH: c_int = 23; pub const EIDRM: c_int = 24; pub const EILSEQ: c_int = 25; pub const EINPROGRESS: c_int = 26; pub const EINTR: c_int = 27; pub const EINVAL: c_int = 28; pub const EIO: c_int = 29; pub const EISCONN: c_int = 30; pub const EISDIR: c_int = 31; pub const ELOOP: c_int = 32; pub const EMFILE: c_int = 33; pub const EMLINK: c_int = 34; pub const EMSGSIZE: c_int = 35; pub const EMULTIHOP: c_int = 36; pub const ENAMETOOLONG: c_int = 37; pub const ENETDOWN: c_int = 38; pub const ENETRESET: c_int = 39; pub const ENETUNREACH: c_int = 40; pub const ENFILE: c_int = 41; pub const ENOBUFS: c_int = 42; pub const ENODEV: c_int = 43; pub const ENOENT: c_int = 44; pub const ENOEXEC: c_int = 45; pub const ENOLCK: c_int = 46; pub const ENOLINK: c_int = 47; pub const ENOMEM: c_int = 48; pub const ENOMSG: c_int = 49; pub const ENOPROTOOPT: c_int = 50; pub const ENOSPC: c_int = 51; pub const ENOSYS: c_int = 52; pub const ENOTCONN: c_int = 53; pub const ENOTDIR: c_int = 54; pub const ENOTEMPTY: c_int = 55; pub const ENOTRECOVERABLE: c_int = 56; pub const ENOTSOCK: c_int = 57; pub const ENOTSUP: c_int = 58; pub const ENOTTY: c_int = 59; pub const ENXIO: c_int = 60; pub const EOVERFLOW: c_int = 61; pub const EOWNERDEAD: c_int = 62; pub const EPERM: c_int = 63; pub const EPIPE: c_int = 64; pub const EPROTO: c_int = 65; pub const EPROTONOSUPPORT: c_int = 66; pub const EPROTOTYPE: c_int = 67; pub const ERANGE: c_int = 68; pub const EROFS: c_int = 69; pub const ESPIPE: c_int = 70; pub const ESRCH: c_int = 71; pub const ESTALE: c_int = 72; pub const ETIMEDOUT: c_int = 73; pub const ETXTBSY: c_int = 74; pub const EXDEV: c_int = 75; pub const ENOTCAPABLE: c_int = 76; pub const EOPNOTSUPP: c_int = ENOTSUP; pub const EWOULDBLOCK: c_int = EAGAIN; pub const _SC_PAGESIZE: c_int = 30; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_IOV_MAX: c_int = 60; pub const _SC_SYMLOOP_MAX: c_int = 173; pub static CLOCK_MONOTONIC: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_MONOTONIC)) }; pub static CLOCK_PROCESS_CPUTIME_ID: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_PROCESS_CPUTIME_ID)) }; pub static CLOCK_REALTIME: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_REALTIME)) }; pub static CLOCK_THREAD_CPUTIME_ID: clockid_t = unsafe { clockid_t(ptr_addr_of!(_CLOCK_THREAD_CPUTIME_ID)) }; pub const ABDAY_1: ::nl_item = 0x20000; pub const ABDAY_2: ::nl_item = 0x20001; pub const ABDAY_3: ::nl_item = 0x20002; pub const ABDAY_4: ::nl_item = 0x20003; pub const ABDAY_5: ::nl_item = 0x20004; pub const ABDAY_6: ::nl_item = 0x20005; pub const ABDAY_7: ::nl_item = 0x20006; pub const DAY_1: ::nl_item = 0x20007; pub const DAY_2: ::nl_item = 0x20008; pub const DAY_3: ::nl_item = 0x20009; pub const DAY_4: ::nl_item = 0x2000A; pub const DAY_5: ::nl_item = 0x2000B; pub const DAY_6: ::nl_item = 0x2000C; pub const DAY_7: ::nl_item = 0x2000D; pub const ABMON_1: ::nl_item = 0x2000E; pub const ABMON_2: ::nl_item = 0x2000F; pub const ABMON_3: ::nl_item = 0x20010; pub const ABMON_4: ::nl_item = 0x20011; pub const ABMON_5: ::nl_item = 0x20012; pub const ABMON_6: ::nl_item = 0x20013; pub const ABMON_7: ::nl_item = 0x20014; pub const ABMON_8: ::nl_item = 0x20015; pub const ABMON_9: ::nl_item = 0x20016; pub const ABMON_10: ::nl_item = 0x20017; pub const ABMON_11: ::nl_item = 0x20018; pub const ABMON_12: ::nl_item = 0x20019; pub const MON_1: ::nl_item = 0x2001A; pub const MON_2: ::nl_item = 0x2001B; pub const MON_3: ::nl_item = 0x2001C; pub const MON_4: ::nl_item = 0x2001D; pub const MON_5: ::nl_item = 0x2001E; pub const MON_6: ::nl_item = 0x2001F; pub const MON_7: ::nl_item = 0x20020; pub const MON_8: ::nl_item = 0x20021; pub const MON_9: ::nl_item = 0x20022; pub const MON_10: ::nl_item = 0x20023; pub const MON_11: ::nl_item = 0x20024; pub const MON_12: ::nl_item = 0x20025; pub const AM_STR: ::nl_item = 0x20026; pub const PM_STR: ::nl_item = 0x20027; pub const D_T_FMT: ::nl_item = 0x20028; pub const D_FMT: ::nl_item = 0x20029; pub const T_FMT: ::nl_item = 0x2002A; pub const T_FMT_AMPM: ::nl_item = 0x2002B; pub const ERA: ::nl_item = 0x2002C; pub const ERA_D_FMT: ::nl_item = 0x2002E; pub const ALT_DIGITS: ::nl_item = 0x2002F; pub const ERA_D_T_FMT: ::nl_item = 0x20030; pub const ERA_T_FMT: ::nl_item = 0x20031; pub const CODESET: ::nl_item = 14; pub const CRNCYSTR: ::nl_item = 0x4000F; pub const RADIXCHAR: ::nl_item = 0x10000; pub const THOUSEP: ::nl_item = 0x10001; pub const YESEXPR: ::nl_item = 0x50000; pub const NOEXPR: ::nl_item = 0x50001; pub const YESSTR: ::nl_item = 0x50002; pub const NOSTR: ::nl_item = 0x50003; #[cfg_attr( feature = "rustc-dep-of-std", link( name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static") ) )] #[cfg_attr( feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))) )] extern "C" { pub fn _Exit(code: c_int) -> !; pub fn _exit(code: c_int) -> !; pub fn abort() -> !; pub fn aligned_alloc(a: size_t, b: size_t) -> *mut c_void; pub fn calloc(amt: size_t, amt2: size_t) -> *mut c_void; pub fn exit(code: c_int) -> !; pub fn free(ptr: *mut c_void); pub fn getenv(s: *const c_char) -> *mut c_char; pub fn malloc(amt: size_t) -> *mut c_void; pub fn malloc_usable_size(ptr: *mut c_void) -> size_t; pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; pub fn rand() -> c_int; pub fn read(fd: c_int, ptr: *mut c_void, size: size_t) -> ssize_t; pub fn realloc(ptr: *mut c_void, amt: size_t) -> *mut c_void; pub fn setenv(k: *const c_char, v: *const c_char, a: c_int) -> c_int; pub fn unsetenv(k: *const c_char) -> c_int; pub fn clearenv() -> ::c_int; pub fn write(fd: c_int, ptr: *const c_void, size: size_t) -> ssize_t; pub static mut environ: *mut *mut c_char; pub fn fopen(a: *const c_char, b: *const c_char) -> *mut FILE; pub fn freopen(a: *const c_char, b: *const c_char, f: *mut FILE) -> *mut FILE; pub fn fclose(f: *mut FILE) -> c_int; pub fn remove(a: *const c_char) -> c_int; pub fn rename(a: *const c_char, b: *const c_char) -> c_int; pub fn feof(f: *mut FILE) -> c_int; pub fn ferror(f: *mut FILE) -> c_int; pub fn fflush(f: *mut FILE) -> c_int; pub fn clearerr(f: *mut FILE); pub fn fseek(f: *mut FILE, b: c_long, c: c_int) -> c_int; pub fn ftell(f: *mut FILE) -> c_long; pub fn rewind(f: *mut FILE); pub fn fgetpos(f: *mut FILE, pos: *mut fpos_t) -> c_int; pub fn fsetpos(f: *mut FILE, pos: *const fpos_t) -> c_int; pub fn fread(buf: *mut c_void, a: size_t, b: size_t, f: *mut FILE) -> size_t; pub fn fwrite(buf: *const c_void, a: size_t, b: size_t, f: *mut FILE) -> size_t; pub fn fgetc(f: *mut FILE) -> c_int; pub fn getc(f: *mut FILE) -> c_int; pub fn getchar() -> c_int; pub fn ungetc(a: c_int, f: *mut FILE) -> c_int; pub fn fputc(a: c_int, f: *mut FILE) -> c_int; pub fn putc(a: c_int, f: *mut FILE) -> c_int; pub fn putchar(a: c_int) -> c_int; pub fn fputs(a: *const c_char, f: *mut FILE) -> c_int; pub fn puts(a: *const c_char) -> c_int; pub fn perror(a: *const c_char); pub fn srand(a: c_uint); pub fn atexit(a: extern "C" fn()) -> c_int; pub fn at_quick_exit(a: extern "C" fn()) -> c_int; pub fn quick_exit(a: c_int) -> !; pub fn posix_memalign(a: *mut *mut c_void, b: size_t, c: size_t) -> c_int; pub fn rand_r(a: *mut c_uint) -> c_int; pub fn random() -> c_long; pub fn srandom(a: c_uint); pub fn putenv(a: *mut c_char) -> c_int; pub fn clock() -> clock_t; pub fn time(a: *mut time_t) -> time_t; pub fn difftime(a: time_t, b: time_t) -> c_double; pub fn mktime(a: *mut tm) -> time_t; pub fn strftime(a: *mut c_char, b: size_t, c: *const c_char, d: *const tm) -> size_t; pub fn gmtime(a: *const time_t) -> *mut tm; pub fn gmtime_r(a: *const time_t, b: *mut tm) -> *mut tm; pub fn localtime(a: *const time_t) -> *mut tm; pub fn localtime_r(a: *const time_t, b: *mut tm) -> *mut tm; pub fn asctime_r(a: *const tm, b: *mut c_char) -> *mut c_char; pub fn ctime_r(a: *const time_t, b: *mut c_char) -> *mut c_char; static _CLOCK_MONOTONIC: u8; static _CLOCK_PROCESS_CPUTIME_ID: u8; static _CLOCK_REALTIME: u8; static _CLOCK_THREAD_CPUTIME_ID: u8; pub fn nanosleep(a: *const timespec, b: *mut timespec) -> c_int; pub fn clock_getres(a: clockid_t, b: *mut timespec) -> c_int; pub fn clock_gettime(a: clockid_t, b: *mut timespec) -> c_int; pub fn clock_nanosleep(a: clockid_t, a2: c_int, b: *const timespec, c: *mut timespec) -> c_int; pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strndup(cs: *const c_char, n: size_t) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn scanf(format: *const ::c_char, ...) -> ::c_int; pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; pub fn shutdown(socket: ::c_int, how: ::c_int) -> ::c_int; pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> ::c_int; pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE; pub fn fileno(stream: *mut ::FILE) -> ::c_int; pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; pub fn creat(path: *const c_char, mode: mode_t) -> ::c_int; pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn opendir(dirname: *const c_char) -> *mut ::DIR; pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent; pub fn closedir(dirp: *mut ::DIR) -> ::c_int; pub fn rewinddir(dirp: *mut ::DIR); pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn openat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int, ...) -> ::c_int; pub fn fstatat( dirfd: ::c_int, pathname: *const ::c_char, buf: *mut stat, flags: ::c_int, ) -> ::c_int; pub fn linkat( olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, flags: ::c_int, ) -> ::c_int; pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn readlinkat( dirfd: ::c_int, pathname: *const ::c_char, buf: *mut ::c_char, bufsiz: ::size_t, ) -> ::ssize_t; pub fn renameat( olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, ) -> ::c_int; pub fn symlinkat( target: *const ::c_char, newdirfd: ::c_int, linkpath: *const ::c_char, ) -> ::c_int; pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; pub fn close(fd: ::c_int) -> ::c_int; pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long; pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn isatty(fd: ::c_int) -> ::c_int; pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int; pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; pub fn rmdir(path: *const c_char) -> ::c_int; pub fn sleep(secs: ::c_uint) -> ::c_uint; pub fn unlink(c: *const c_char) -> ::c_int; pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn fsync(fd: ::c_int) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn symlink(path1: *const c_char, path2: *const c_char) -> ::c_int; pub fn truncate(path: *const c_char, length: off_t) -> ::c_int; pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; pub fn getrusage(resource: ::c_int, usage: *mut rusage) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn times(buf: *mut ::tms) -> ::clock_t; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn usleep(secs: ::c_uint) -> ::c_int; pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; pub fn localeconv() -> *mut lconv; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t; pub fn timegm(tm: *mut ::tm) -> time_t; pub fn sysconf(name: ::c_int) -> ::c_long; pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn sched_yield() -> ::c_int; pub fn getcwd(buf: *mut c_char, size: ::size_t) -> *mut c_char; pub fn chdir(dir: *const c_char) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn nl_langinfo_l(item: ::nl_item, loc: ::locale_t) -> *mut ::c_char; pub fn __wasilibc_register_preopened_fd(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_fd_renumber(fd: c_int, newfd: c_int) -> c_int; pub fn __wasilibc_unlinkat(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_rmdirat(fd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_find_relpath( path: *const c_char, abs_prefix: *mut *const c_char, relative_path: *mut *mut c_char, relative_path_len: usize, ) -> c_int; pub fn __wasilibc_tell(fd: c_int) -> ::off_t; pub fn __wasilibc_nocwd___wasilibc_unlinkat(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd___wasilibc_rmdirat(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd_linkat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_symlinkat( target: *const c_char, dirfd: c_int, path: *const c_char, ) -> c_int; pub fn __wasilibc_nocwd_readlinkat( dirfd: c_int, path: *const c_char, buf: *mut c_char, bufsize: usize, ) -> isize; pub fn __wasilibc_nocwd_faccessat( dirfd: c_int, path: *const c_char, mode: c_int, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_renameat( olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, ) -> c_int; pub fn __wasilibc_nocwd_openat_nomode(dirfd: c_int, path: *const c_char, flags: c_int) -> c_int; pub fn __wasilibc_nocwd_fstatat( dirfd: c_int, path: *const c_char, buf: *mut stat, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_mkdirat_nomode(dirfd: c_int, path: *const c_char) -> c_int; pub fn __wasilibc_nocwd_utimensat( dirfd: c_int, path: *const c_char, times: *const ::timespec, flags: c_int, ) -> c_int; pub fn __wasilibc_nocwd_opendirat(dirfd: c_int, path: *const c_char) -> *mut ::DIR; pub fn __wasilibc_access(pathname: *const c_char, mode: c_int, flags: c_int) -> c_int; pub fn __wasilibc_stat(pathname: *const c_char, buf: *mut stat, flags: c_int) -> c_int; pub fn __wasilibc_utimens( pathname: *const c_char, times: *const ::timespec, flags: c_int, ) -> c_int; pub fn __wasilibc_link(oldpath: *const c_char, newpath: *const c_char, flags: c_int) -> c_int; pub fn __wasilibc_link_oldat( olddirfd: c_int, oldpath: *const c_char, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn __wasilibc_link_newat( oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_int, ) -> c_int; pub fn __wasilibc_rename_oldat( olddirfd: c_int, oldpath: *const c_char, newpath: *const c_char, ) -> c_int; pub fn __wasilibc_rename_newat( oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, ) -> c_int; pub fn arc4random() -> u32; pub fn arc4random_buf(a: *mut c_void, b: size_t); pub fn arc4random_uniform(a: u32) -> u32; pub fn __errno_location() -> *mut ::c_int; } libc/src/windows/0000775000175000017500000000000014661133735014735 5ustar jamespagejamespagelibc/src/windows/msvc/0000775000175000017500000000000014661133735015705 5ustar jamespagejamespagelibc/src/windows/msvc/mod.rs0000644000175000017500000000117714661133735017036 0ustar jamespagejamespagepub const L_tmpnam: ::c_uint = 260; pub const TMP_MAX: ::c_uint = 0x7fff_ffff; // POSIX Supplement (from errno.h) // This particular error code is only currently available in msvc toolchain pub const EOTHER: ::c_int = 131; extern "C" { #[link_name = "_stricmp"] pub fn stricmp(s1: *const ::c_char, s2: *const ::c_char) -> ::c_int; #[link_name = "_strnicmp"] pub fn strnicmp(s1: *const ::c_char, s2: *const ::c_char, n: ::size_t) -> ::c_int; #[link_name = "_memccpy"] pub fn memccpy( dest: *mut ::c_void, src: *const ::c_void, c: ::c_int, count: ::size_t, ) -> *mut ::c_void; } libc/src/windows/mod.rs0000644000175000017500000005302314661133735016063 0ustar jamespagejamespage//! Windows CRT definitions pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type sighandler_t = usize; pub type c_char = i8; pub type c_long = i32; pub type c_ulong = u32; pub type wchar_t = u16; pub type clock_t = i32; pub type errno_t = ::c_int; cfg_if! { if #[cfg(all(target_arch = "x86", target_env = "gnu"))] { pub type time_t = i32; } else { pub type time_t = i64; } } pub type off_t = i32; pub type dev_t = u32; pub type ino_t = u16; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } pub type time64_t = i64; pub type SOCKET = ::uintptr_t; s! { // note this is the struct called stat64 in Windows. Not stat, nor stati64. pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: u16, pub st_nlink: ::c_short, pub st_uid: ::c_short, pub st_gid: ::c_short, pub st_rdev: dev_t, pub st_size: i64, pub st_atime: time64_t, pub st_mtime: time64_t, pub st_ctime: time64_t, } // note that this is called utimbuf64 in Windows pub struct utimbuf { pub actime: time64_t, pub modtime: time64_t, } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, } pub struct timeval { pub tv_sec: c_long, pub tv_usec: c_long, } pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } pub struct sockaddr { pub sa_family: c_ushort, pub sa_data: [c_char; 14], } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 32767; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 4; pub const _IOLBF: ::c_int = 64; pub const BUFSIZ: ::c_uint = 512; pub const FOPEN_MAX: ::c_uint = 20; pub const FILENAME_MAX: ::c_uint = 260; // fcntl.h pub const O_RDONLY: ::c_int = 0x0000; pub const O_WRONLY: ::c_int = 0x0001; pub const O_RDWR: ::c_int = 0x0002; pub const O_APPEND: ::c_int = 0x0008; pub const O_CREAT: ::c_int = 0x0100; pub const O_TRUNC: ::c_int = 0x0200; pub const O_EXCL: ::c_int = 0x0400; pub const O_TEXT: ::c_int = 0x4000; pub const O_BINARY: ::c_int = 0x8000; pub const _O_WTEXT: ::c_int = 0x10000; pub const _O_U16TEXT: ::c_int = 0x20000; pub const _O_U8TEXT: ::c_int = 0x40000; pub const O_RAW: ::c_int = O_BINARY; pub const O_NOINHERIT: ::c_int = 0x0080; pub const O_TEMPORARY: ::c_int = 0x0040; pub const _O_SHORT_LIVED: ::c_int = 0x1000; pub const _O_OBTAIN_DIR: ::c_int = 0x2000; pub const O_SEQUENTIAL: ::c_int = 0x0020; pub const O_RANDOM: ::c_int = 0x0010; pub const S_IFCHR: ::c_int = 8192; pub const S_IFDIR: ::c_int = 16384; pub const S_IFREG: ::c_int = 32768; pub const S_IFMT: ::c_int = 61440; pub const S_IEXEC: ::c_int = 64; pub const S_IWRITE: ::c_int = 128; pub const S_IREAD: ::c_int = 256; pub const LC_ALL: ::c_int = 0; pub const LC_COLLATE: ::c_int = 1; pub const LC_CTYPE: ::c_int = 2; pub const LC_MONETARY: ::c_int = 3; pub const LC_NUMERIC: ::c_int = 4; pub const LC_TIME: ::c_int = 5; pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EDEADLK: ::c_int = 36; pub const EDEADLOCK: ::c_int = 36; pub const ENAMETOOLONG: ::c_int = 38; pub const ENOLCK: ::c_int = 39; pub const ENOSYS: ::c_int = 40; pub const ENOTEMPTY: ::c_int = 41; pub const EILSEQ: ::c_int = 42; pub const STRUNCATE: ::c_int = 80; // POSIX Supplement (from errno.h) pub const EADDRINUSE: ::c_int = 100; pub const EADDRNOTAVAIL: ::c_int = 101; pub const EAFNOSUPPORT: ::c_int = 102; pub const EALREADY: ::c_int = 103; pub const EBADMSG: ::c_int = 104; pub const ECANCELED: ::c_int = 105; pub const ECONNABORTED: ::c_int = 106; pub const ECONNREFUSED: ::c_int = 107; pub const ECONNRESET: ::c_int = 108; pub const EDESTADDRREQ: ::c_int = 109; pub const EHOSTUNREACH: ::c_int = 110; pub const EIDRM: ::c_int = 111; pub const EINPROGRESS: ::c_int = 112; pub const EISCONN: ::c_int = 113; pub const ELOOP: ::c_int = 114; pub const EMSGSIZE: ::c_int = 115; pub const ENETDOWN: ::c_int = 116; pub const ENETRESET: ::c_int = 117; pub const ENETUNREACH: ::c_int = 118; pub const ENOBUFS: ::c_int = 119; pub const ENODATA: ::c_int = 120; pub const ENOLINK: ::c_int = 121; pub const ENOMSG: ::c_int = 122; pub const ENOPROTOOPT: ::c_int = 123; pub const ENOSR: ::c_int = 124; pub const ENOSTR: ::c_int = 125; pub const ENOTCONN: ::c_int = 126; pub const ENOTRECOVERABLE: ::c_int = 127; pub const ENOTSOCK: ::c_int = 128; pub const ENOTSUP: ::c_int = 129; pub const EOPNOTSUPP: ::c_int = 130; pub const EOVERFLOW: ::c_int = 132; pub const EOWNERDEAD: ::c_int = 133; pub const EPROTO: ::c_int = 134; pub const EPROTONOSUPPORT: ::c_int = 135; pub const EPROTOTYPE: ::c_int = 136; pub const ETIME: ::c_int = 137; pub const ETIMEDOUT: ::c_int = 138; pub const ETXTBSY: ::c_int = 139; pub const EWOULDBLOCK: ::c_int = 140; // signal codes pub const SIGINT: ::c_int = 2; pub const SIGILL: ::c_int = 4; pub const SIGFPE: ::c_int = 8; pub const SIGSEGV: ::c_int = 11; pub const SIGTERM: ::c_int = 15; pub const SIGABRT: ::c_int = 22; pub const NSIG: ::c_int = 23; pub const SIG_ERR: ::c_int = -1; pub const SIG_DFL: ::sighandler_t = 0; pub const SIG_IGN: ::sighandler_t = 1; pub const SIG_GET: ::sighandler_t = 2; pub const SIG_SGE: ::sighandler_t = 3; pub const SIG_ACK: ::sighandler_t = 4; // inline comment below appeases style checker #[cfg(all(target_env = "msvc", feature = "rustc-dep-of-std"))] // " if " #[link(name = "msvcrt", cfg(not(target_feature = "crt-static")))] #[link(name = "libcmt", cfg(target_feature = "crt-static"))] extern "C" {} #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl ::Copy for FILE {} impl ::Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME: fill this out with a struct impl ::Copy for fpos_t {} impl ::Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } // Special handling for all print and scan type functions because of https://github.com/rust-lang/libc/issues/2860 cfg_if! { if #[cfg(not(feature = "rustc-dep-of-std"))] { #[cfg_attr( all(windows, target_env = "msvc"), link(name = "legacy_stdio_definitions") )] extern "C" { pub fn printf(format: *const c_char, ...) -> ::c_int; pub fn fprintf(stream: *mut FILE, format: *const c_char, ...) -> ::c_int; } } } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn _msize(p: *mut c_void) -> size_t; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn _exit(status: c_int) -> !; pub fn atexit(cb: extern "C" fn()) -> c_int; pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; pub fn abs(i: c_int) -> c_int; pub fn labs(i: c_long) -> c_long; pub fn rand() -> c_int; pub fn srand(seed: c_uint); pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t; pub fn raise(signum: c_int) -> c_int; #[link_name = "_gmtime64_s"] pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> ::c_int; #[link_name = "_localtime64_s"] pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> ::errno_t; #[link_name = "_time64"] pub fn time(destTime: *mut time_t) -> time_t; #[link_name = "_chmod"] pub fn chmod(path: *const c_char, mode: ::c_int) -> ::c_int; #[link_name = "_wchmod"] pub fn wchmod(path: *const wchar_t, mode: ::c_int) -> ::c_int; #[link_name = "_mkdir"] pub fn mkdir(path: *const c_char) -> ::c_int; #[link_name = "_wrmdir"] pub fn wrmdir(path: *const wchar_t) -> ::c_int; #[link_name = "_fstat64"] pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; #[link_name = "_stat64"] pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; #[link_name = "_wstat64"] pub fn wstat(path: *const wchar_t, buf: *mut stat) -> ::c_int; #[link_name = "_wutime64"] pub fn wutime(file: *const wchar_t, buf: *mut utimbuf) -> ::c_int; #[link_name = "_popen"] pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; #[link_name = "_pclose"] pub fn pclose(stream: *mut ::FILE) -> ::c_int; #[link_name = "_fdopen"] pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE; #[link_name = "_fileno"] pub fn fileno(stream: *mut ::FILE) -> ::c_int; #[link_name = "_open"] pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; #[link_name = "_wopen"] pub fn wopen(path: *const wchar_t, oflag: ::c_int, ...) -> ::c_int; #[link_name = "_creat"] pub fn creat(path: *const c_char, mode: ::c_int) -> ::c_int; #[link_name = "_access"] pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; #[link_name = "_chdir"] pub fn chdir(dir: *const c_char) -> ::c_int; #[link_name = "_close"] pub fn close(fd: ::c_int) -> ::c_int; #[link_name = "_dup"] pub fn dup(fd: ::c_int) -> ::c_int; #[link_name = "_dup2"] pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; #[link_name = "_execl"] pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexecl"] pub fn wexecl(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execle"] pub fn execle(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexecle"] pub fn wexecle(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execlp"] pub fn execlp(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexeclp"] pub fn wexeclp(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execlpe"] pub fn execlpe(path: *const c_char, arg0: *const c_char, ...) -> intptr_t; #[link_name = "_wexeclpe"] pub fn wexeclpe(path: *const wchar_t, arg0: *const wchar_t, ...) -> intptr_t; #[link_name = "_execv"] pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::intptr_t; #[link_name = "_execve"] pub fn execve( prog: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> ::c_int; #[link_name = "_execvp"] pub fn execvp(c: *const c_char, argv: *const *const c_char) -> ::c_int; #[link_name = "_execvpe"] pub fn execvpe( c: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> ::c_int; #[link_name = "_wexecv"] pub fn wexecv(prog: *const wchar_t, argv: *const *const wchar_t) -> ::intptr_t; #[link_name = "_wexecve"] pub fn wexecve( prog: *const wchar_t, argv: *const *const wchar_t, envp: *const *const wchar_t, ) -> ::intptr_t; #[link_name = "_wexecvp"] pub fn wexecvp(c: *const wchar_t, argv: *const *const wchar_t) -> ::intptr_t; #[link_name = "_wexecvpe"] pub fn wexecvpe( c: *const wchar_t, argv: *const *const wchar_t, envp: *const *const wchar_t, ) -> ::intptr_t; #[link_name = "_getcwd"] pub fn getcwd(buf: *mut c_char, size: ::c_int) -> *mut c_char; #[link_name = "_getpid"] pub fn getpid() -> ::c_int; #[link_name = "_isatty"] pub fn isatty(fd: ::c_int) -> ::c_int; #[link_name = "_lseek"] pub fn lseek(fd: ::c_int, offset: c_long, origin: ::c_int) -> c_long; #[link_name = "_lseeki64"] pub fn lseek64(fd: ::c_int, offset: c_longlong, origin: ::c_int) -> c_longlong; #[link_name = "_pipe"] pub fn pipe(fds: *mut ::c_int, psize: ::c_uint, textmode: ::c_int) -> ::c_int; #[link_name = "_read"] pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::c_uint) -> ::c_int; #[link_name = "_rmdir"] pub fn rmdir(path: *const c_char) -> ::c_int; #[link_name = "_unlink"] pub fn unlink(c: *const c_char) -> ::c_int; #[link_name = "_write"] pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::c_uint) -> ::c_int; #[link_name = "_commit"] pub fn commit(fd: ::c_int) -> ::c_int; #[link_name = "_get_osfhandle"] pub fn get_osfhandle(fd: ::c_int) -> ::intptr_t; #[link_name = "_open_osfhandle"] pub fn open_osfhandle(osfhandle: ::intptr_t, flags: ::c_int) -> ::c_int; pub fn setlocale(category: ::c_int, locale: *const c_char) -> *mut c_char; #[link_name = "_wsetlocale"] pub fn wsetlocale(category: ::c_int, locale: *const wchar_t) -> *mut wchar_t; #[link_name = "_aligned_malloc"] pub fn aligned_malloc(size: size_t, alignment: size_t) -> *mut c_void; #[link_name = "_aligned_free"] pub fn aligned_free(ptr: *mut ::c_void); #[link_name = "_putenv"] pub fn putenv(envstring: *const ::c_char) -> ::c_int; #[link_name = "_wputenv"] pub fn wputenv(envstring: *const ::wchar_t) -> ::c_int; #[link_name = "_putenv_s"] pub fn putenv_s(envstring: *const ::c_char, value_string: *const ::c_char) -> ::errno_t; #[link_name = "_wputenv_s"] pub fn wputenv_s(envstring: *const ::wchar_t, value_string: *const ::wchar_t) -> ::errno_t; } extern "system" { pub fn listen(s: SOCKET, backlog: ::c_int) -> ::c_int; pub fn accept(s: SOCKET, addr: *mut ::sockaddr, addrlen: *mut ::c_int) -> SOCKET; pub fn bind(s: SOCKET, name: *const ::sockaddr, namelen: ::c_int) -> ::c_int; pub fn connect(s: SOCKET, name: *const ::sockaddr, namelen: ::c_int) -> ::c_int; pub fn getpeername(s: SOCKET, name: *mut ::sockaddr, nameln: *mut ::c_int) -> ::c_int; pub fn getsockname(s: SOCKET, name: *mut ::sockaddr, nameln: *mut ::c_int) -> ::c_int; pub fn getsockopt( s: SOCKET, level: ::c_int, optname: ::c_int, optval: *mut ::c_char, optlen: *mut ::c_int, ) -> ::c_int; pub fn recvfrom( s: SOCKET, buf: *mut ::c_char, len: ::c_int, flags: ::c_int, from: *mut ::sockaddr, fromlen: *mut ::c_int, ) -> ::c_int; pub fn sendto( s: SOCKET, buf: *const ::c_char, len: ::c_int, flags: ::c_int, to: *const ::sockaddr, tolen: ::c_int, ) -> ::c_int; pub fn setsockopt( s: SOCKET, level: ::c_int, optname: ::c_int, optval: *const ::c_char, optlen: ::c_int, ) -> ::c_int; pub fn socket(af: ::c_int, socket_type: ::c_int, protocol: ::c_int) -> SOCKET; } cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } cfg_if! { if #[cfg(all(target_env = "gnu"))] { mod gnu; pub use self::gnu::*; } else if #[cfg(all(target_env = "msvc"))] { mod msvc; pub use self::msvc::*; } else { // Unknown target_env } } libc/src/windows/gnu/0000775000175000017500000000000014661133735015526 5ustar jamespagejamespagelibc/src/windows/gnu/mod.rs0000644000175000017500000000135514661133735016655 0ustar jamespagejamespagepub const L_tmpnam: ::c_uint = 14; pub const TMP_MAX: ::c_uint = 0x7fff; // stdio file descriptor numbers pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; extern "C" { pub fn strcasecmp(s1: *const ::c_char, s2: *const ::c_char) -> ::c_int; pub fn strncasecmp(s1: *const ::c_char, s2: *const ::c_char, n: ::size_t) -> ::c_int; // NOTE: For MSVC target, `wmemchr` is only a inline function in `` // header file. We cannot find a way to link to that symbol from Rust. pub fn wmemchr(cx: *const ::wchar_t, c: ::wchar_t, n: ::size_t) -> *mut ::wchar_t; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/windows/gnu/align.rs0000644000175000017500000000101514661133735017161 0ustar jamespagejamespagecfg_if! { if #[cfg(target_pointer_width = "64")] { s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } } else if #[cfg(target_pointer_width = "32")] { s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [i64; 6] } } } } libc/src/unix/0000775000175000017500000000000014661133735014226 5ustar jamespagejamespagelibc/src/unix/aix/0000775000175000017500000000000014661133735015007 5ustar jamespagejamespagelibc/src/unix/aix/mod.rs0000644000175000017500000035012614661133735016141 0ustar jamespagejamespagepub type c_char = u8; pub type caddr_t = *mut ::c_char; pub type clockid_t = ::c_longlong; pub type blkcnt_t = ::c_long; pub type clock_t = ::c_int; pub type daddr_t = ::c_long; pub type dev_t = ::c_ulong; pub type fpos64_t = ::c_longlong; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type idtype_t = ::c_int; pub type ino_t = ::c_ulong; pub type key_t = ::c_int; pub type mode_t = ::c_uint; pub type nlink_t = ::c_short; pub type rlim_t = ::c_ulong; pub type speed_t = ::c_uint; pub type tcflag_t = ::c_uint; pub type time_t = ::c_long; pub type time64_t = ::int64_t; pub type timer_t = ::c_long; pub type wchar_t = ::c_uint; pub type nfds_t = ::c_int; pub type projid_t = ::c_int; pub type id_t = ::c_uint; pub type blksize64_t = ::c_ulonglong; pub type blkcnt64_t = ::c_ulonglong; pub type sctp_assoc_t = ::uint32_t; pub type suseconds_t = ::c_int; pub type useconds_t = ::c_uint; pub type off_t = ::c_long; pub type off64_t = ::c_longlong; pub type socklen_t = ::c_uint; pub type sa_family_t = ::c_uchar; pub type in_port_t = ::c_ushort; pub type in_addr_t = ::c_uint; pub type signal_t = ::c_int; pub type pthread_t = ::c_uint; pub type pthread_key_t = ::c_uint; pub type thread_t = pthread_t; pub type blksize_t = ::c_long; pub type nl_item = ::c_int; pub type mqd_t = ::c_int; pub type shmatt_t = ::c_ulong; pub type regoff_t = ::c_long; pub type rlim64_t = ::c_ulonglong; pub type sem_t = ::c_int; pub type pollset_t = ::c_int; pub type pthread_rwlockattr_t = *mut ::c_void; pub type pthread_condattr_t = *mut ::c_void; pub type pthread_mutexattr_t = *mut ::c_void; pub type pthread_attr_t = *mut ::c_void; pub type pthread_barrierattr_t = *mut ::c_void; pub type posix_spawn_file_actions_t = *mut ::c_char; pub type iconv_t = *mut ::c_void; e! { pub enum uio_rw { UIO_READ = 0, UIO_WRITE, UIO_READ_NO_MOVE, UIO_WRITE_NO_MOVE, UIO_PWRITE, } } s! { pub struct fsid_t { pub val: [::c_uint; 2], } pub struct fsid64_t { pub val: [::uint64_t; 2], } pub struct timezone { pub tz_minuteswest: ::c_int, pub tz_dsttime: ::c_int, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct dirent { pub d_offset: ::c_ulong, pub d_ino: ::ino_t, pub d_reclen: ::c_ushort, pub d_namlen: ::c_ushort, pub d_name: [::c_char; 256] } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_cc: [::cc_t; ::NCCS] } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_sysid: ::c_uint, pub l_pid: ::pid_t, pub l_vfs: ::c_int, pub l_start: ::off64_t, pub l_len: ::off64_t, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: socklen_t, pub msg_flags: ::c_int, } pub struct statvfs64 { pub f_bsize: ::blksize64_t, pub f_frsize: ::blksize64_t, pub f_blocks: ::blkcnt64_t, pub f_bfree: ::blkcnt64_t, pub f_bavail: ::blkcnt64_t, pub f_files: ::blkcnt64_t, pub f_ffree: ::blkcnt64_t, pub f_favail: ::blkcnt64_t, pub f_fsid: fsid64_t, pub f_basetype: [::c_char; 16], pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub f_fstr: [::c_char; 32], pub f_filler: [::c_ulong; 16] } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub left_parenthesis: *mut ::c_char, pub right_parenthesis: *mut ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: ::c_ulong, pub ai_canonname: *mut ::c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut addrinfo, pub ai_eflags: ::c_int, } pub struct in_addr { pub s_addr: in_addr_t } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct sockaddr { pub sa_len: ::c_uchar, pub sa_family: sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, pub sdl_index: ::c_ushort, pub sdl_type: ::c_uchar, pub sdl_nlen: ::c_uchar, pub sdl_alen: ::c_uchar, pub sdl_slen: ::c_uchar, pub sdl_data: [::c_char; 120], } pub struct sockaddr_in { pub sin_len: ::c_uchar, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: in_addr, pub sin_zero: [::c_char; 8] } pub struct sockaddr_in6 { pub sin6_len: ::c_uchar, pub sin6_family: ::c_uchar, pub sin6_port: ::uint16_t, pub sin6_flowinfo: ::uint32_t, pub sin6_addr: ::in6_addr, pub sin6_scope_id: ::uint32_t } pub struct sockaddr_storage { pub __ss_len: ::c_uchar, pub ss_family: sa_family_t, __ss_pad1: [::c_char; 6], __ss_align: ::int64_t, __ss_pad2: [::c_char; 1265], } pub struct sockaddr_un { pub sun_len: ::c_uchar, pub sun_family: sa_family_t, pub sun_path: [::c_char; 1023] } pub struct st_timespec { pub tv_sec: ::time_t, pub tv_nsec: ::c_int, } pub struct statfs64 { pub f_version: ::c_int, pub f_type: ::c_int, pub f_bsize: blksize64_t, pub f_blocks: blkcnt64_t, pub f_bfree: blkcnt64_t, pub f_bavail: blkcnt64_t, pub f_files: ::uint64_t, pub f_ffree: ::uint64_t, pub f_fsid: fsid64_t, pub f_vfstype: ::c_int, pub f_fsize: blksize64_t, pub f_vfsnumber: ::c_int, pub f_vfsoff: ::c_int, pub f_vfslen: ::c_int, pub f_vfsvers: ::c_int, pub f_fname: [::c_char; 32], pub f_fpack: [::c_char; 32], pub f_name_max: ::c_int, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char } pub struct utsname { pub sysname: [::c_char; 32], pub nodename: [::c_char; 32], pub release: [::c_char; 32], pub version: [::c_char; 32], pub machine: [::c_char; 32], } pub struct xutsname { pub nid: ::c_uint, pub reserved: ::c_int, pub longnid: ::c_ulonglong, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct sigevent { pub sigev_value: ::sigval, pub sigev_signo: ::c_int, pub sigev_notify: ::c_int, pub sigev_notify_function: extern fn(val: ::sigval), pub sigev_notify_attributes: *mut pthread_attr_t, } // Should be union with another 'sival_int' pub struct sigval64 { pub sival_ptr: ::c_ulonglong, } pub struct sigevent64 { pub sigev_value: sigval64, pub sigev_signo: ::c_int, pub sigev_notify: ::c_int, pub sigev_notify_function: ::c_ulonglong, pub sigev_notify_attributes: ::c_ulonglong, } pub struct osigevent { pub sevt_value: *mut ::c_void, pub sevt_signo: signal_t, } pub struct poll_ctl { pub cmd: ::c_short, pub events: ::c_short, pub fd: ::c_int, } pub struct sf_parms { pub header_data: *mut ::c_void, pub header_length: ::c_uint, pub file_descriptor: ::c_int, pub file_size: ::uint64_t, pub file_offset: ::uint64_t, pub file_bytes: ::int64_t, pub trailer_data: *mut ::c_void, pub trailer_length: ::c_uint, pub bytes_sent: ::uint64_t, } pub struct mmsghdr { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } pub struct sched_param { pub sched_priority: ::c_int, pub sched_policy: ::c_int, pub sched_reserved: [::c_int; 6], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, pub __pad: [::c_int; 4], } pub struct posix_spawnattr_t { pub posix_attr_flags: ::c_short, pub posix_attr_pgroup: ::pid_t, pub posix_attr_sigmask: ::sigset_t, pub posix_attr_sigdefault: ::sigset_t, pub posix_attr_schedpolicy: ::c_int, pub posix_attr_schedparam: sched_param, } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: ::size_t, pub gl_padr: *mut ::c_void, pub gl_ptx: *mut ::c_void, } pub struct mallinfo { pub arena: ::c_ulong, pub ordblks: ::c_int, pub smblks: ::c_int, pub hblks: ::c_int, pub hblkhd: ::c_int, pub usmblks: ::c_ulong, pub fsmblks: ::c_ulong, pub uordblks: ::c_ulong, pub fordblks: ::c_ulong, pub keepcost: ::c_int, } pub struct utmp_exit_status { pub e_termination: ::c_short, pub e_exit: ::c_short, } pub struct utmp { pub ut_user: [::c_char; 256], pub ut_id: [::c_char; 14], pub ut_line: [::c_char; 64], pub ut_pid: ::pid_t, pub ut_type: ::c_short, pub ut_time: time64_t, pub ut_exit: utmp_exit_status, pub ut_host: [::c_char; 256], pub __dbl_word_pad: ::c_int, pub __reservedA: [::c_int; 2], pub __reservedV: [::c_int; 6], } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct regex_t { pub re_nsub: ::size_t, pub re_comp: *mut ::c_void, pub re_cflags: ::c_int, pub re_erroff: ::size_t, pub re_len: ::size_t, pub re_ucoll: [::wchar_t; 2], pub re_lsub: [*mut ::c_void; 24], pub re_esub: [*mut ::c_void; 24], pub re_map: *mut ::c_uchar, pub __maxsub: ::c_int, pub __unused: [*mut ::c_void; 34], } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct shmid_ds { pub shm_perm: ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: shmatt_t, pub shm_cnattch: shmatt_t, pub shm_atime: time_t, pub shm_dtime: time_t, pub shm_ctime: time_t, pub shm_handle: ::uint32_t, pub shm_extshm: ::c_int, pub shm_pagesize: ::int64_t, pub shm_lba: ::uint64_t, pub shm_reserved: ::int64_t, pub shm_reserved1: ::int64_t, } pub struct stat64 { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, pub st_nlink: nlink_t, pub st_flag: ::c_ushort, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: dev_t, pub st_ssize: ::c_int, pub st_atim: st_timespec, pub st_mtim: st_timespec, pub st_ctim: st_timespec, pub st_blksize: blksize_t, pub st_blocks: blkcnt_t, pub st_vfstype: ::c_int, pub st_vfs: ::c_uint, pub st_type: ::c_uint, pub st_gen: ::c_uint, pub st_reserved: [::c_uint; 10], pub st_size: off64_t, } pub struct mntent { pub mnt_fsname: *mut ::c_char, pub mnt_dir: *mut ::c_char, pub mnt_type: *mut ::c_char, pub mnt_opts: *mut ::c_char, pub mnt_freq: ::c_int, pub mnt_passno: ::c_int, } pub struct ipc_perm { pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: mode_t, pub seq: ::c_ushort, pub __reserved: ::c_ushort, pub key: key_t, } pub struct entry { pub key: *mut ::c_char, pub data: *mut ::c_void, } pub struct mq_attr { pub mq_flags: ::c_long, pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } } s_no_extra_traits! { #[cfg(libc_union)] pub union __sigaction_sa_union { pub __su_handler: extern fn(c: ::c_int), pub __su_sigaction: extern fn(c: ::c_int, info: *mut siginfo_t, ptr: *mut ::c_void), } pub struct sigaction { #[cfg(libc_union)] pub sa_union: __sigaction_sa_union, pub sa_mask: sigset_t, pub sa_flags: ::c_int, } #[cfg(libc_union)] pub union __poll_ctl_ext_u { pub addr: *mut ::c_void, pub data32: u32, pub data: u64, } pub struct poll_ctl_ext { pub version: u8, pub command: u8, pub events: ::c_short, pub fd: ::c_int, #[cfg(libc_union)] pub u: __poll_ctl_ext_u, pub reversed64: [u64; 6], } } cfg_if! { if #[cfg(feature = "extra_traits")] { #[cfg(libc_union)] impl PartialEq for __sigaction_sa_union { fn eq(&self, other: &__sigaction_sa_union) -> bool { unsafe { self.__su_handler == other.__su_handler && self.__su_sigaction == other.__su_sigaction } } } #[cfg(libc_union)] impl Eq for __sigaction_sa_union {} #[cfg(libc_union)] impl ::fmt::Debug for __sigaction_sa_union { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__sigaction_sa_union") .field("__su_handler", unsafe { &self.__su_handler }) .field("__su_sigaction", unsafe { &self.__su_sigaction }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __sigaction_sa_union { fn hash(&self, state: &mut H) { unsafe { self.__su_handler.hash(state); self.__su_sigaction.hash(state); } } } impl PartialEq for sigaction { fn eq(&self, other: &sigaction) -> bool { #[cfg(libc_union)] let union_eq = self.sa_union == other.sa_union; #[cfg(not(libc_union))] let union_eq = true; self.sa_mask == other.sa_mask && self.sa_flags == other.sa_flags && union_eq } } impl Eq for sigaction {} impl ::fmt::Debug for sigaction { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("sigaction"); #[cfg(libc_union)] struct_formatter.field("sa_union", &self.sa_union); struct_formatter.field("sa_mask", &self.sa_mask); struct_formatter.field("sa_flags", &self.sa_flags); struct_formatter.finish() } } impl ::hash::Hash for sigaction { fn hash(&self, state: &mut H) { #[cfg(libc_union)] self.sa_union.hash(state); self.sa_mask.hash(state); self.sa_flags.hash(state); } } #[cfg(libc_union)] impl PartialEq for __poll_ctl_ext_u { fn eq(&self, other: &__poll_ctl_ext_u) -> bool { unsafe { self.addr == other.addr && self.data32 == other.data32 && self.data == other.data } } } #[cfg(libc_union)] impl Eq for __poll_ctl_ext_u {} #[cfg(libc_union)] impl ::fmt::Debug for __poll_ctl_ext_u { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__poll_ctl_ext_u") .field("addr", unsafe { &self.addr }) .field("data32", unsafe { &self.data32 }) .field("data", unsafe { &self.data }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __poll_ctl_ext_u { fn hash(&self, state: &mut H) { unsafe { self.addr.hash(state); self.data32.hash(state); self.data.hash(state); } } } impl PartialEq for poll_ctl_ext { fn eq(&self, other: &poll_ctl_ext) -> bool { #[cfg(libc_union)] let union_eq = self.u == other.u; #[cfg(not(libc_union))] let union_eq = true; self.version == other.version && self.command == other.command && self.events == other.events && self.fd == other.fd && self.reversed64 == other.reversed64 && union_eq } } impl Eq for poll_ctl_ext {} impl ::fmt::Debug for poll_ctl_ext { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("poll_ctl_ext"); struct_formatter.field("version", &self.version); struct_formatter.field("command", &self.command); struct_formatter.field("events", &self.events); struct_formatter.field("fd", &self.fd); #[cfg(libc_union)] struct_formatter.field("u", &self.u); struct_formatter.field("reversed64", &self.reversed64); struct_formatter.finish() } } impl ::hash::Hash for poll_ctl_ext { fn hash(&self, state: &mut H) { self.version.hash(state); self.command.hash(state); self.events.hash(state); self.fd.hash(state); #[cfg(libc_union)] self.u.hash(state); self.reversed64.hash(state); } } } } // dlfcn.h pub const RTLD_LAZY: ::c_int = 0x4; pub const RTLD_NOW: ::c_int = 0x2; pub const RTLD_GLOBAL: ::c_int = 0x10000; pub const RTLD_LOCAL: ::c_int = 0x80000; pub const RTLD_DEFAULT: *mut ::c_void = -1isize as *mut ::c_void; pub const RTLD_MYSELF: *mut ::c_void = -2isize as *mut ::c_void; pub const RTLD_NEXT: *mut ::c_void = -3isize as *mut ::c_void; // fcntl.h pub const O_RDONLY: ::c_int = 0x0; pub const O_WRONLY: ::c_int = 0x1; pub const O_RDWR: ::c_int = 0x2; pub const O_NDELAY: ::c_int = 0x8000; pub const O_APPEND: ::c_int = 0x8; pub const O_DSYNC: ::c_int = 0x400000; pub const O_CREAT: ::c_int = 0x100; pub const O_EXCL: ::c_int = 0x400; pub const O_NOCTTY: ::c_int = 0x800; pub const O_TRUNC: ::c_int = 0x200; pub const O_NOFOLLOW: ::c_int = 0x1000000; pub const O_DIRECTORY: ::c_int = 0x80000; pub const O_SEARCH: ::c_int = 0x20; pub const O_EXEC: ::c_int = 0x20; pub const O_CLOEXEC: ::c_int = 0x800000; pub const O_ACCMODE: ::c_int = O_RDONLY | O_WRONLY | O_RDWR; pub const O_DIRECT: ::c_int = 0x8000000; pub const O_TTY_INIT: ::c_int = 0; pub const O_RSYNC: ::c_int = 0x200000; pub const O_LARGEFILE: ::c_int = 0x4000000; pub const F_CLOSEM: ::c_int = 10; pub const F_DUPFD_CLOEXEC: ::c_int = 16; pub const F_GETLK64: ::c_int = 11; pub const F_SETLK64: ::c_int = 12; pub const F_SETLKW64: ::c_int = 13; pub const F_DUP2FD: ::c_int = 14; pub const F_TSTLK: ::c_int = 15; pub const F_GETLK: ::c_int = F_GETLK64; pub const F_SETLK: ::c_int = F_SETLK64; pub const F_SETLKW: ::c_int = F_SETLKW64; pub const F_GETOWN: ::c_int = 8; pub const F_SETOWN: ::c_int = 9; pub const AT_FDCWD: ::c_int = -2; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 1; pub const AT_SYMLINK_FOLLOW: ::c_int = 2; pub const AT_REMOVEDIR: ::c_int = 1; pub const AT_EACCESS: ::c_int = 1; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const O_SYNC: ::c_int = 16; pub const O_NONBLOCK: ::c_int = 4; pub const FASYNC: ::c_int = 0x20000; pub const POSIX_FADV_NORMAL: ::c_int = 1; pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_FADV_RANDOM: ::c_int = 3; pub const POSIX_FADV_WILLNEED: ::c_int = 4; pub const POSIX_FADV_DONTNEED: ::c_int = 5; pub const POSIX_FADV_NOREUSE: ::c_int = 6; // glob.h pub const GLOB_APPEND: ::c_int = 0x1; pub const GLOB_DOOFFS: ::c_int = 0x2; pub const GLOB_ERR: ::c_int = 0x4; pub const GLOB_MARK: ::c_int = 0x8; pub const GLOB_NOCHECK: ::c_int = 0x10; pub const GLOB_NOSORT: ::c_int = 0x20; pub const GLOB_NOESCAPE: ::c_int = 0x80; pub const GLOB_NOSPACE: ::c_int = 0x2000; pub const GLOB_ABORTED: ::c_int = 0x1000; pub const GLOB_NOMATCH: ::c_int = 0x4000; pub const GLOB_NOSYS: ::c_int = 0x8000; // langinfo.h pub const DAY_1: ::nl_item = 13; pub const DAY_2: ::nl_item = 14; pub const DAY_3: ::nl_item = 15; pub const DAY_4: ::nl_item = 16; pub const DAY_5: ::nl_item = 17; pub const DAY_6: ::nl_item = 18; pub const DAY_7: ::nl_item = 19; pub const ABDAY_1: ::nl_item = 6; pub const ABDAY_2: ::nl_item = 7; pub const ABDAY_3: ::nl_item = 8; pub const ABDAY_4: ::nl_item = 9; pub const ABDAY_5: ::nl_item = 10; pub const ABDAY_6: ::nl_item = 11; pub const ABDAY_7: ::nl_item = 12; pub const MON_1: ::nl_item = 32; pub const MON_2: ::nl_item = 33; pub const MON_3: ::nl_item = 34; pub const MON_4: ::nl_item = 35; pub const MON_5: ::nl_item = 36; pub const MON_6: ::nl_item = 37; pub const MON_7: ::nl_item = 38; pub const MON_8: ::nl_item = 39; pub const MON_9: ::nl_item = 40; pub const MON_10: ::nl_item = 41; pub const MON_11: ::nl_item = 42; pub const MON_12: ::nl_item = 43; pub const ABMON_1: ::nl_item = 20; pub const ABMON_2: ::nl_item = 21; pub const ABMON_3: ::nl_item = 22; pub const ABMON_4: ::nl_item = 23; pub const ABMON_5: ::nl_item = 24; pub const ABMON_6: ::nl_item = 25; pub const ABMON_7: ::nl_item = 26; pub const ABMON_8: ::nl_item = 27; pub const ABMON_9: ::nl_item = 28; pub const ABMON_10: ::nl_item = 29; pub const ABMON_11: ::nl_item = 30; pub const ABMON_12: ::nl_item = 31; pub const RADIXCHAR: ::nl_item = 44; pub const THOUSEP: ::nl_item = 45; pub const YESSTR: ::nl_item = 46; pub const NOSTR: ::nl_item = 47; pub const CRNCYSTR: ::nl_item = 48; pub const D_T_FMT: ::nl_item = 1; pub const D_FMT: ::nl_item = 2; pub const T_FMT: ::nl_item = 3; pub const AM_STR: ::nl_item = 4; pub const PM_STR: ::nl_item = 5; pub const CODESET: ::nl_item = 49; pub const T_FMT_AMPM: ::nl_item = 55; pub const ERA: ::nl_item = 56; pub const ERA_D_FMT: ::nl_item = 57; pub const ERA_D_T_FMT: ::nl_item = 58; pub const ERA_T_FMT: ::nl_item = 59; pub const ALT_DIGITS: ::nl_item = 60; pub const YESEXPR: ::nl_item = 61; pub const NOEXPR: ::nl_item = 62; // locale.h pub const LC_GLOBAL_LOCALE: ::locale_t = -1isize as ::locale_t; pub const LC_CTYPE: ::c_int = 1; pub const LC_NUMERIC: ::c_int = 3; pub const LC_TIME: ::c_int = 4; pub const LC_COLLATE: ::c_int = 0; pub const LC_MONETARY: ::c_int = 2; pub const LC_MESSAGES: ::c_int = 4; pub const LC_ALL: ::c_int = -1; pub const LC_CTYPE_MASK: ::c_int = 2; pub const LC_NUMERIC_MASK: ::c_int = 16; pub const LC_TIME_MASK: ::c_int = 32; pub const LC_COLLATE_MASK: ::c_int = 1; pub const LC_MONETARY_MASK: ::c_int = 8; pub const LC_MESSAGES_MASK: ::c_int = 4; pub const LC_ALL_MASK: ::c_int = LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK | LC_MONETARY_MASK | LC_MESSAGES_MASK; // netdb.h pub const NI_MAXHOST: ::socklen_t = 1025; pub const NI_MAXSERV: ::socklen_t = 32; pub const NI_NOFQDN: ::socklen_t = 0x1; pub const NI_NUMERICHOST: ::socklen_t = 0x2; pub const NI_NAMEREQD: ::socklen_t = 0x4; pub const NI_NUMERICSERV: ::socklen_t = 0x8; pub const NI_DGRAM: ::socklen_t = 0x10; pub const NI_NUMERICSCOPE: ::socklen_t = 0x40; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_NODATA: ::c_int = 7; pub const EAI_NONAME: ::c_int = 8; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 13; pub const AI_CANONNAME: ::c_int = 0x01; pub const AI_PASSIVE: ::c_int = 0x02; pub const AI_NUMERICHOST: ::c_int = 0x04; pub const AI_ADDRCONFIG: ::c_int = 0x08; pub const AI_V4MAPPED: ::c_int = 0x10; pub const AI_ALL: ::c_int = 0x20; pub const AI_NUMERICSERV: ::c_int = 0x40; pub const AI_EXTFLAGS: ::c_int = 0x80; pub const AI_DEFAULT: ::c_int = AI_V4MAPPED | AI_ADDRCONFIG; pub const IPV6_ADDRFORM: ::c_int = 22; pub const IPV6_ADDR_PREFERENCES: ::c_int = 74; pub const IPV6_CHECKSUM: ::c_int = 39; pub const IPV6_DONTFRAG: ::c_int = 45; pub const IPV6_DSTOPTS: ::c_int = 54; pub const IPV6_FLOWINFO_FLOWLABEL: ::c_int = 16777215; pub const IPV6_FLOWINFO_PRIORITY: ::c_int = 251658240; pub const IPV6_HOPLIMIT: ::c_int = 40; pub const IPV6_HOPOPTS: ::c_int = 52; pub const IPV6_NEXTHOP: ::c_int = 48; pub const IPV6_PATHMTU: ::c_int = 46; pub const IPV6_PKTINFO: ::c_int = 33; pub const IPV6_PREFER_SRC_CGA: ::c_int = 16; pub const IPV6_PREFER_SRC_COA: ::c_int = 2; pub const IPV6_PREFER_SRC_HOME: ::c_int = 1; pub const IPV6_PREFER_SRC_NONCGA: ::c_int = 32; pub const IPV6_PREFER_SRC_PUBLIC: ::c_int = 4; pub const IPV6_PREFER_SRC_TMP: ::c_int = 8; pub const IPV6_RECVDSTOPTS: ::c_int = 56; pub const IPV6_RECVHOPLIMIT: ::c_int = 41; pub const IPV6_RECVHOPOPTS: ::c_int = 53; pub const IPV6_RECVPATHMTU: ::c_int = 47; pub const IPV6_RECVRTHDR: ::c_int = 51; pub const IPV6_RECVTCLASS: ::c_int = 42; pub const IPV6_RTHDR: ::c_int = 50; pub const IPV6_RTHDRDSTOPTS: ::c_int = 55; pub const IPV6_TCLASS: ::c_int = 43; // net/bpf.h pub const DLT_NULL: ::c_int = 0x18; pub const DLT_EN10MB: ::c_int = 0x6; pub const DLT_EN3MB: ::c_int = 0x1a; pub const DLT_AX25: ::c_int = 0x5; pub const DLT_PRONET: ::c_int = 0xd; pub const DLT_IEEE802: ::c_int = 0x7; pub const DLT_ARCNET: ::c_int = 0x23; pub const DLT_SLIP: ::c_int = 0x1c; pub const DLT_PPP: ::c_int = 0x17; pub const DLT_FDDI: ::c_int = 0xf; pub const DLT_ATM: ::c_int = 0x25; pub const DLT_IPOIB: ::c_int = 0xc7; pub const BIOCSETF: ::c_ulong = 0x80104267; pub const BIOCGRTIMEOUT: ::c_ulong = 0x4010426e; pub const BIOCGBLEN: ::c_int = 0x40044266; pub const BIOCSBLEN: ::c_int = 0xc0044266; pub const BIOCFLUSH: ::c_int = 0x20004268; pub const BIOCPROMISC: ::c_int = 0x20004269; pub const BIOCGDLT: ::c_int = 0x4004426a; pub const BIOCSRTIMEOUT: ::c_int = 0x8010426d; pub const BIOCGSTATS: ::c_int = 0x4008426f; pub const BIOCIMMEDIATE: ::c_int = 0x80044270; pub const BIOCVERSION: ::c_int = 0x40044271; pub const BIOCSDEVNO: ::c_int = 0x20004272; pub const BIOCGETIF: ::c_ulong = 0x4020426b; pub const BIOCSETIF: ::c_ulong = 0xffffffff8020426c; pub const BPF_ABS: ::c_int = 32; pub const BPF_ADD: ::c_int = 0; pub const BPF_ALIGNMENT: ::c_ulong = 4; pub const BPF_ALU: ::c_int = 4; pub const BPF_AND: ::c_int = 80; pub const BPF_B: ::c_int = 16; pub const BPF_DIV: ::c_int = 48; pub const BPF_H: ::c_int = 8; pub const BPF_IMM: ::c_int = 0; pub const BPF_IND: ::c_int = 64; pub const BPF_JA: ::c_int = 0; pub const BPF_JEQ: ::c_int = 16; pub const BPF_JGE: ::c_int = 48; pub const BPF_JGT: ::c_int = 32; pub const BPF_JMP: ::c_int = 5; pub const BPF_JSET: ::c_int = 64; pub const BPF_K: ::c_int = 0; pub const BPF_LD: ::c_int = 0; pub const BPF_LDX: ::c_int = 1; pub const BPF_LEN: ::c_int = 128; pub const BPF_LSH: ::c_int = 96; pub const BPF_MAXINSNS: ::c_int = 512; pub const BPF_MEM: ::c_int = 96; pub const BPF_MEMWORDS: ::c_int = 16; pub const BPF_MISC: ::c_int = 7; pub const BPF_MSH: ::c_int = 160; pub const BPF_MUL: ::c_int = 32; pub const BPF_NEG: ::c_int = 128; pub const BPF_OR: ::c_int = 64; pub const BPF_RET: ::c_int = 6; pub const BPF_RSH: ::c_int = 112; pub const BPF_ST: ::c_int = 2; pub const BPF_STX: ::c_int = 3; pub const BPF_SUB: ::c_int = 16; pub const BPF_W: ::c_int = 0; pub const BPF_X: ::c_int = 8; // net/if.h pub const IFNET_SLOWHZ: ::c_int = 1; pub const IFQ_MAXLEN: ::c_int = 50; pub const IF_NAMESIZE: ::c_int = 16; pub const IFNAMSIZ: ::c_int = 16; pub const IFF_UP: ::c_int = 0x1; pub const IFF_BROADCAST: ::c_int = 0x2; pub const IFF_DEBUG: ::c_int = 0x4; pub const IFF_LOOPBACK: ::c_int = 0x8; pub const IFF_POINTOPOINT: ::c_int = 0x10; pub const IFF_NOTRAILERS: ::c_int = 0x20; pub const IFF_RUNNING: ::c_int = 0x40; pub const IFF_NOARP: ::c_int = 0x80; pub const IFF_PROMISC: ::c_int = 0x100; pub const IFF_ALLMULTI: ::c_int = 0x200; pub const IFF_MULTICAST: ::c_int = 0x80000; pub const IFF_LINK0: ::c_int = 0x100000; pub const IFF_LINK1: ::c_int = 0x200000; pub const IFF_LINK2: ::c_int = 0x400000; pub const IFF_OACTIVE: ::c_int = 0x400; pub const IFF_SIMPLEX: ::c_int = 0x800; // net/if_arp.h pub const ARPHRD_ETHER: ::c_int = 1; pub const ARPHRD_802_5: ::c_int = 6; pub const ARPHRD_802_3: ::c_int = 6; pub const ARPHRD_FDDI: ::c_int = 1; pub const ARPOP_REQUEST: ::c_int = 1; pub const ARPOP_REPLY: ::c_int = 2; // net/route.h pub const RTM_ADD: ::c_int = 0x1; pub const RTM_DELETE: ::c_int = 0x2; pub const RTM_CHANGE: ::c_int = 0x3; pub const RTM_GET: ::c_int = 0x4; pub const RTM_LOSING: ::c_int = 0x5; pub const RTM_REDIRECT: ::c_int = 0x6; pub const RTM_MISS: ::c_int = 0x7; pub const RTM_LOCK: ::c_int = 0x8; pub const RTM_OLDADD: ::c_int = 0x9; pub const RTM_OLDDEL: ::c_int = 0xa; pub const RTM_RESOLVE: ::c_int = 0xb; pub const RTM_NEWADDR: ::c_int = 0xc; pub const RTM_DELADDR: ::c_int = 0xd; pub const RTM_IFINFO: ::c_int = 0xe; pub const RTM_EXPIRE: ::c_int = 0xf; pub const RTM_RTLOST: ::c_int = 0x10; pub const RTM_GETNEXT: ::c_int = 0x11; pub const RTM_SAMEADDR: ::c_int = 0x12; pub const RTM_SET: ::c_int = 0x13; pub const RTV_MTU: ::c_int = 0x1; pub const RTV_HOPCOUNT: ::c_int = 0x2; pub const RTV_EXPIRE: ::c_int = 0x4; pub const RTV_RPIPE: ::c_int = 0x8; pub const RTV_SPIPE: ::c_int = 0x10; pub const RTV_SSTHRESH: ::c_int = 0x20; pub const RTV_RTT: ::c_int = 0x40; pub const RTV_RTTVAR: ::c_int = 0x80; pub const RTA_DST: ::c_int = 0x1; pub const RTA_GATEWAY: ::c_int = 0x2; pub const RTA_NETMASK: ::c_int = 0x4; pub const RTA_GENMASK: ::c_int = 0x8; pub const RTA_IFP: ::c_int = 0x10; pub const RTA_IFA: ::c_int = 0x20; pub const RTA_AUTHOR: ::c_int = 0x40; pub const RTA_BRD: ::c_int = 0x80; pub const RTA_DOWNSTREAM: ::c_int = 0x100; pub const RTAX_DST: ::c_int = 0; pub const RTAX_GATEWAY: ::c_int = 1; pub const RTAX_NETMASK: ::c_int = 2; pub const RTAX_GENMASK: ::c_int = 3; pub const RTAX_IFP: ::c_int = 4; pub const RTAX_IFA: ::c_int = 5; pub const RTAX_AUTHOR: ::c_int = 6; pub const RTAX_BRD: ::c_int = 7; pub const RTAX_MAX: ::c_int = 8; pub const RTF_UP: ::c_int = 0x1; pub const RTF_GATEWAY: ::c_int = 0x2; pub const RTF_HOST: ::c_int = 0x4; pub const RTF_REJECT: ::c_int = 0x8; pub const RTF_DYNAMIC: ::c_int = 0x10; pub const RTF_MODIFIED: ::c_int = 0x20; pub const RTF_DONE: ::c_int = 0x40; pub const RTF_MASK: ::c_int = 0x80; pub const RTF_CLONING: ::c_int = 0x100; pub const RTF_XRESOLVE: ::c_int = 0x200; pub const RTF_LLINFO: ::c_int = 0x400; pub const RTF_STATIC: ::c_int = 0x800; pub const RTF_BLACKHOLE: ::c_int = 0x1000; pub const RTF_BUL: ::c_int = 0x2000; pub const RTF_PROTO2: ::c_int = 0x4000; pub const RTF_PROTO1: ::c_int = 0x8000; pub const RTF_CLONE: ::c_int = 0x10000; pub const RTF_CLONED: ::c_int = 0x20000; pub const RTF_PROTO3: ::c_int = 0x40000; pub const RTF_BCE: ::c_int = 0x80000; pub const RTF_PINNED: ::c_int = 0x100000; pub const RTF_LOCAL: ::c_int = 0x200000; pub const RTF_BROADCAST: ::c_int = 0x400000; pub const RTF_MULTICAST: ::c_int = 0x800000; pub const RTF_ACTIVE_DGD: ::c_int = 0x1000000; pub const RTF_STOPSRCH: ::c_int = 0x2000000; pub const RTF_FREE_IN_PROG: ::c_int = 0x4000000; pub const RTF_PERMANENT6: ::c_int = 0x8000000; pub const RTF_UNREACHABLE: ::c_int = 0x10000000; pub const RTF_CACHED: ::c_int = 0x20000000; pub const RTF_SMALLMTU: ::c_int = 0x40000; // netinet/in.h pub const IPPROTO_HOPOPTS: ::c_int = 0; pub const IPPROTO_IGMP: ::c_int = 2; pub const IPPROTO_GGP: ::c_int = 3; pub const IPPROTO_IPIP: ::c_int = 4; pub const IPPROTO_EGP: ::c_int = 8; pub const IPPROTO_PUP: ::c_int = 12; pub const IPPROTO_IDP: ::c_int = 22; pub const IPPROTO_TP: ::c_int = 29; pub const IPPROTO_ROUTING: ::c_int = 43; pub const IPPROTO_FRAGMENT: ::c_int = 44; pub const IPPROTO_QOS: ::c_int = 45; pub const IPPROTO_RSVP: ::c_int = 46; pub const IPPROTO_GRE: ::c_int = 47; pub const IPPROTO_ESP: ::c_int = 50; pub const IPPROTO_AH: ::c_int = 51; pub const IPPROTO_NONE: ::c_int = 59; pub const IPPROTO_DSTOPTS: ::c_int = 60; pub const IPPROTO_LOCAL: ::c_int = 63; pub const IPPROTO_EON: ::c_int = 80; pub const IPPROTO_BIP: ::c_int = 0x53; pub const IPPROTO_SCTP: ::c_int = 132; pub const IPPROTO_MH: ::c_int = 135; pub const IPPROTO_GIF: ::c_int = 140; pub const IPPROTO_RAW: ::c_int = 255; pub const IPPROTO_MAX: ::c_int = 256; pub const IP_OPTIONS: ::c_int = 1; pub const IP_HDRINCL: ::c_int = 2; pub const IP_TOS: ::c_int = 3; pub const IP_TTL: ::c_int = 4; pub const IP_UNICAST_HOPS: ::c_int = 4; pub const IP_RECVOPTS: ::c_int = 5; pub const IP_RECVRETOPTS: ::c_int = 6; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_RETOPTS: ::c_int = 8; pub const IP_MULTICAST_IF: ::c_int = 9; pub const IP_MULTICAST_TTL: ::c_int = 10; pub const IP_MULTICAST_HOPS: ::c_int = 10; pub const IP_MULTICAST_LOOP: ::c_int = 11; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; pub const IP_RECVMACHDR: ::c_int = 14; pub const IP_RECVIFINFO: ::c_int = 15; pub const IP_BROADCAST_IF: ::c_int = 16; pub const IP_DHCPMODE: ::c_int = 17; pub const IP_RECVIF: ::c_int = 20; pub const IP_ADDRFORM: ::c_int = 22; pub const IP_DONTFRAG: ::c_int = 25; pub const IP_FINDPMTU: ::c_int = 26; pub const IP_PMTUAGE: ::c_int = 27; pub const IP_RECVINTERFACE: ::c_int = 32; pub const IP_RECVTTL: ::c_int = 34; pub const IP_BLOCK_SOURCE: ::c_int = 58; pub const IP_UNBLOCK_SOURCE: ::c_int = 59; pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 60; pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 61; pub const IP_DEFAULT_MULTICAST_TTL: ::c_int = 1; pub const IP_DEFAULT_MULTICAST_LOOP: ::c_int = 1; pub const IP_INC_MEMBERSHIPS: ::c_int = 20; pub const IP_INIT_MEMBERSHIP: ::c_int = 20; pub const IPV6_UNICAST_HOPS: ::c_int = IP_TTL; pub const IPV6_MULTICAST_IF: ::c_int = IP_MULTICAST_IF; pub const IPV6_MULTICAST_HOPS: ::c_int = IP_MULTICAST_TTL; pub const IPV6_MULTICAST_LOOP: ::c_int = IP_MULTICAST_LOOP; pub const IPV6_RECVPKTINFO: ::c_int = 35; pub const IPV6_V6ONLY: ::c_int = 37; pub const IPV6_ADD_MEMBERSHIP: ::c_int = IP_ADD_MEMBERSHIP; pub const IPV6_DROP_MEMBERSHIP: ::c_int = IP_DROP_MEMBERSHIP; pub const IPV6_JOIN_GROUP: ::c_int = IP_ADD_MEMBERSHIP; pub const IPV6_LEAVE_GROUP: ::c_int = IP_DROP_MEMBERSHIP; pub const MCAST_BLOCK_SOURCE: ::c_int = 64; pub const MCAST_EXCLUDE: ::c_int = 2; pub const MCAST_INCLUDE: ::c_int = 1; pub const MCAST_JOIN_GROUP: ::c_int = 62; pub const MCAST_JOIN_SOURCE_GROUP: ::c_int = 66; pub const MCAST_LEAVE_GROUP: ::c_int = 63; pub const MCAST_LEAVE_SOURCE_GROUP: ::c_int = 67; pub const MCAST_UNBLOCK_SOURCE: ::c_int = 65; // netinet/ip.h pub const MAXTTL: ::c_int = 255; pub const IPDEFTTL: ::c_int = 64; pub const IPOPT_CONTROL: ::c_int = 0; pub const IPOPT_EOL: ::c_int = 0; pub const IPOPT_LSRR: ::c_int = 131; pub const IPOPT_MINOFF: ::c_int = 4; pub const IPOPT_NOP: ::c_int = 1; pub const IPOPT_OFFSET: ::c_int = 2; pub const IPOPT_OLEN: ::c_int = 1; pub const IPOPT_OPTVAL: ::c_int = 0; pub const IPOPT_RESERVED1: ::c_int = 0x20; pub const IPOPT_RESERVED2: ::c_int = 0x60; pub const IPOPT_RR: ::c_int = 7; pub const IPOPT_SSRR: ::c_int = 137; pub const IPOPT_TS: ::c_int = 68; pub const IPOPT_TS_PRESPEC: ::c_int = 3; pub const IPOPT_TS_TSANDADDR: ::c_int = 1; pub const IPOPT_TS_TSONLY: ::c_int = 0; pub const IPTOS_LOWDELAY: ::c_int = 16; pub const IPTOS_PREC_CRITIC_ECP: ::c_int = 160; pub const IPTOS_PREC_FLASH: ::c_int = 96; pub const IPTOS_PREC_FLASHOVERRIDE: ::c_int = 128; pub const IPTOS_PREC_IMMEDIATE: ::c_int = 64; pub const IPTOS_PREC_INTERNETCONTROL: ::c_int = 192; pub const IPTOS_PREC_NETCONTROL: ::c_int = 224; pub const IPTOS_PREC_PRIORITY: ::c_int = 32; pub const IPTOS_PREC_ROUTINE: ::c_int = 16; pub const IPTOS_RELIABILITY: ::c_int = 4; pub const IPTOS_THROUGHPUT: ::c_int = 8; pub const IPVERSION: ::c_int = 4; // netinet/tcp.h pub const TCP_NODELAY: ::c_int = 0x1; pub const TCP_MAXSEG: ::c_int = 0x2; pub const TCP_RFC1323: ::c_int = 0x4; pub const TCP_KEEPALIVE: ::c_int = 0x8; pub const TCP_KEEPIDLE: ::c_int = 0x11; pub const TCP_KEEPINTVL: ::c_int = 0x12; pub const TCP_KEEPCNT: ::c_int = 0x13; pub const TCP_NODELAYACK: ::c_int = 0x14; // pthread.h pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; pub const PTHREAD_PROCESS_SHARED: ::c_int = 0; pub const PTHREAD_PROCESS_PRIVATE: ::c_ushort = 1; pub const PTHREAD_STACK_MIN: ::size_t = PAGESIZE as ::size_t * 4; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 5; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 3; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 4; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_MUTEX_ROBUST: ::c_int = 1; pub const PTHREAD_MUTEX_STALLED: ::c_int = 0; pub const PTHREAD_PRIO_INHERIT: ::c_int = 3; pub const PTHREAD_PRIO_NONE: ::c_int = 1; pub const PTHREAD_PRIO_PROTECT: ::c_int = 2; // regex.h pub const REG_EXTENDED: ::c_int = 1; pub const REG_ICASE: ::c_int = 2; pub const REG_NEWLINE: ::c_int = 4; pub const REG_NOSUB: ::c_int = 8; pub const REG_NOTBOL: ::c_int = 0x100; pub const REG_NOTEOL: ::c_int = 0x200; pub const REG_NOMATCH: ::c_int = 1; pub const REG_BADPAT: ::c_int = 2; pub const REG_ECOLLATE: ::c_int = 3; pub const REG_ECTYPE: ::c_int = 4; pub const REG_EESCAPE: ::c_int = 5; pub const REG_ESUBREG: ::c_int = 6; pub const REG_EBRACK: ::c_int = 7; pub const REG_EPAREN: ::c_int = 8; pub const REG_EBRACE: ::c_int = 9; pub const REG_BADBR: ::c_int = 10; pub const REG_ERANGE: ::c_int = 11; pub const REG_ESPACE: ::c_int = 12; pub const REG_BADRPT: ::c_int = 13; pub const REG_ECHAR: ::c_int = 14; pub const REG_EBOL: ::c_int = 15; pub const REG_EEOL: ::c_int = 16; pub const REG_ENOSYS: ::c_int = 17; // rpcsvc/mount.h pub const NFSMNT_ACDIRMAX: ::c_int = 2048; pub const NFSMNT_ACDIRMIN: ::c_int = 1024; pub const NFSMNT_ACREGMAX: ::c_int = 512; pub const NFSMNT_ACREGMIN: ::c_int = 256; pub const NFSMNT_INT: ::c_int = 64; pub const NFSMNT_NOAC: ::c_int = 128; pub const NFSMNT_RETRANS: ::c_int = 16; pub const NFSMNT_RSIZE: ::c_int = 4; pub const NFSMNT_SOFT: ::c_int = 1; pub const NFSMNT_TIMEO: ::c_int = 8; pub const NFSMNT_WSIZE: ::c_int = 2; // rpcsvc/rstat.h pub const CPUSTATES: ::c_int = 4; // search.h pub const FIND: ::c_int = 0; pub const ENTER: ::c_int = 1; // semaphore.h pub const SEM_FAILED: *mut sem_t = -1isize as *mut ::sem_t; // spawn.h pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x1; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x2; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x4; pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x8; pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x10; pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x20; pub const POSIX_SPAWN_FORK_HANDLERS: ::c_int = 0x1000; // stdio.h pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const _IOFBF: ::c_int = 0o000; pub const _IONBF: ::c_int = 0o004; pub const _IOLBF: ::c_int = 0o100; pub const BUFSIZ: ::c_uint = 4096; pub const FOPEN_MAX: ::c_uint = 32767; pub const FILENAME_MAX: ::c_uint = 255; pub const L_tmpnam: ::c_uint = 21; pub const TMP_MAX: ::c_uint = 16384; // stdlib.h pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 32767; // sys/access.h pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; // sys/aio.h pub const LIO_NOP: ::c_int = 0; pub const LIO_READ: ::c_int = 1; pub const LIO_WRITE: ::c_int = 2; pub const LIO_NOWAIT: ::c_int = 0; pub const LIO_WAIT: ::c_int = 1; pub const AIO_ALLDONE: ::c_int = 2; pub const AIO_CANCELED: ::c_int = 0; pub const AIO_NOTCANCELED: ::c_int = 1; // sys/errno.h pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EDEADLK: ::c_int = 45; pub const ENOLCK: ::c_int = 49; pub const ECANCELED: ::c_int = 117; pub const ENOTSUP: ::c_int = 124; pub const EPROCLIM: ::c_int = 83; pub const EDQUOT: ::c_int = 88; pub const EOWNERDEAD: ::c_int = 95; pub const ENOTRECOVERABLE: ::c_int = 94; pub const ENOSTR: ::c_int = 123; pub const ENODATA: ::c_int = 122; pub const ETIME: ::c_int = 119; pub const ENOSR: ::c_int = 118; pub const EREMOTE: ::c_int = 93; pub const ENOATTR: ::c_int = 112; pub const ESAD: ::c_int = 113; pub const ENOTRUST: ::c_int = 114; pub const ENOLINK: ::c_int = 126; pub const EPROTO: ::c_int = 121; pub const EMULTIHOP: ::c_int = 125; pub const EBADMSG: ::c_int = 120; pub const ENAMETOOLONG: ::c_int = 86; pub const EOVERFLOW: ::c_int = 127; pub const EILSEQ: ::c_int = 116; pub const ENOSYS: ::c_int = 109; pub const ELOOP: ::c_int = 85; pub const ERESTART: ::c_int = 82; pub const ENOTEMPTY: ::c_int = 87; pub const EUSERS: ::c_int = 84; pub const ENOTSOCK: ::c_int = 57; pub const EDESTADDRREQ: ::c_int = 58; pub const EMSGSIZE: ::c_int = 59; pub const EPROTOTYPE: ::c_int = 60; pub const ENOPROTOOPT: ::c_int = 61; pub const EPROTONOSUPPORT: ::c_int = 62; pub const ESOCKTNOSUPPORT: ::c_int = 63; pub const EOPNOTSUPP: ::c_int = 64; pub const EPFNOSUPPORT: ::c_int = 65; pub const EAFNOSUPPORT: ::c_int = 66; pub const EADDRINUSE: ::c_int = 67; pub const EADDRNOTAVAIL: ::c_int = 68; pub const ENETDOWN: ::c_int = 69; pub const ENETUNREACH: ::c_int = 70; pub const ENETRESET: ::c_int = 71; pub const ECONNABORTED: ::c_int = 72; pub const ECONNRESET: ::c_int = 73; pub const ENOBUFS: ::c_int = 74; pub const EISCONN: ::c_int = 75; pub const ENOTCONN: ::c_int = 76; pub const ESHUTDOWN: ::c_int = 77; pub const ETOOMANYREFS: ::c_int = 115; pub const ETIMEDOUT: ::c_int = 78; pub const ECONNREFUSED: ::c_int = 79; pub const EHOSTDOWN: ::c_int = 80; pub const EHOSTUNREACH: ::c_int = 81; pub const EWOULDBLOCK: ::c_int = EAGAIN; pub const EALREADY: ::c_int = 56; pub const EINPROGRESS: ::c_int = 55; pub const ESTALE: ::c_int = 52; // sys/dr.h pub const LPAR_INFO_FORMAT1: ::c_int = 1; pub const LPAR_INFO_FORMAT2: ::c_int = 2; pub const WPAR_INFO_FORMAT: ::c_int = 3; pub const PROC_MODULE_INFO: ::c_int = 4; pub const NUM_PROC_MODULE_TYPES: ::c_int = 5; pub const LPAR_INFO_VRME_NUM_POOLS: ::c_int = 6; pub const LPAR_INFO_VRME_POOLS: ::c_int = 7; pub const LPAR_INFO_VRME_LPAR: ::c_int = 8; pub const LPAR_INFO_VRME_RESET_HWMARKS: ::c_int = 9; pub const LPAR_INFO_VRME_ALLOW_DESIRED: ::c_int = 10; pub const EMTP_INFO_FORMAT: ::c_int = 11; pub const LPAR_INFO_LPM_CAPABILITY: ::c_int = 12; pub const ENERGYSCALE_INFO: ::c_int = 13; // sys/file.h pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; // sys/flock.h pub const F_RDLCK: ::c_short = 0o01; pub const F_WRLCK: ::c_short = 0o02; pub const F_UNLCK: ::c_short = 0o03; // sys/fs/quota_common.h pub const Q_QUOTAON: ::c_int = 0x100; pub const Q_QUOTAOFF: ::c_int = 0x200; pub const Q_SETUSE: ::c_int = 0x500; pub const Q_SYNC: ::c_int = 0x600; pub const Q_GETQUOTA: ::c_int = 0x300; pub const Q_SETQLIM: ::c_int = 0x400; pub const Q_SETQUOTA: ::c_int = 0x400; // sys/ioctl.h pub const IOCPARM_MASK: ::c_int = 0x7f; pub const IOC_VOID: ::c_int = 0x20000000; pub const IOC_OUT: ::c_int = 0x40000000; pub const IOC_IN: ::c_int = 0x40000000 << 1; pub const IOC_INOUT: ::c_int = IOC_IN | IOC_OUT; pub const FIOCLEX: ::c_int = 536897025; pub const FIONCLEX: ::c_int = 536897026; pub const FIONREAD: ::c_int = 1074030207; pub const FIONBIO: ::c_int = -2147195266; pub const FIOASYNC: ::c_int = -2147195267; pub const FIOSETOWN: ::c_int = -2147195268; pub const FIOGETOWN: ::c_int = 1074030203; pub const TIOCGETD: ::c_int = 0x40047400; pub const TIOCSETD: ::c_int = 0x80047401; pub const TIOCHPCL: ::c_int = 0x20007402; pub const TIOCMODG: ::c_int = 0x40047403; pub const TIOCMODS: ::c_int = 0x80047404; pub const TIOCM_LE: ::c_int = 0x1; pub const TIOCM_DTR: ::c_int = 0x2; pub const TIOCM_RTS: ::c_int = 0x4; pub const TIOCM_ST: ::c_int = 0x8; pub const TIOCM_SR: ::c_int = 0x10; pub const TIOCM_CTS: ::c_int = 0x20; pub const TIOCM_CAR: ::c_int = 0x40; pub const TIOCM_CD: ::c_int = 0x40; pub const TIOCM_RNG: ::c_int = 0x80; pub const TIOCM_RI: ::c_int = 0x80; pub const TIOCM_DSR: ::c_int = 0x100; pub const TIOCGETP: ::c_int = 0x40067408; pub const TIOCSETP: ::c_int = 0x80067409; pub const TIOCSETN: ::c_int = 0x8006740a; pub const TIOCEXCL: ::c_int = 0x2000740d; pub const TIOCNXCL: ::c_int = 0x2000740e; pub const TIOCFLUSH: ::c_int = 0x80047410; pub const TIOCSETC: ::c_int = 0x80067411; pub const TIOCGETC: ::c_int = 0x40067412; pub const TANDEM: ::c_int = 0x1; pub const CBREAK: ::c_int = 0x2; pub const LCASE: ::c_int = 0x4; pub const MDMBUF: ::c_int = 0x800000; pub const XTABS: ::c_int = 0xc00; pub const SIOCADDMULTI: ::c_int = -2145359567; pub const SIOCADDRT: ::c_int = -2143784438; pub const SIOCDARP: ::c_int = -2142476000; pub const SIOCDELMULTI: ::c_int = -2145359566; pub const SIOCDELRT: ::c_int = -2143784437; pub const SIOCDIFADDR: ::c_int = -2144835303; pub const SIOCGARP: ::c_int = -1068734170; pub const SIOCGIFADDR: ::c_int = -1071093471; pub const SIOCGIFBRDADDR: ::c_int = -1071093469; pub const SIOCGIFCONF: ::c_int = -1072666299; pub const SIOCGIFDSTADDR: ::c_int = -1071093470; pub const SIOCGIFFLAGS: ::c_int = -1071093487; pub const SIOCGIFHWADDR: ::c_int = -1068209771; pub const SIOCGIFMETRIC: ::c_int = -1071093481; pub const SIOCGIFMTU: ::c_int = -1071093418; pub const SIOCGIFNETMASK: ::c_int = -1071093467; pub const SIOCSARP: ::c_int = -2142476002; pub const SIOCSIFADDR: ::c_int = -2144835316; pub const SIOCSIFBRDADDR: ::c_int = -2144835309; pub const SIOCSIFDSTADDR: ::c_int = -2144835314; pub const SIOCSIFFLAGS: ::c_int = -2144835312; pub const SIOCSIFMETRIC: ::c_int = -2144835304; pub const SIOCSIFMTU: ::c_int = -2144835240; pub const SIOCSIFNETMASK: ::c_int = -2144835306; pub const TIOCUCNTL: ::c_int = -2147191706; pub const TIOCCONS: ::c_int = -2147191710; pub const TIOCPKT: ::c_int = -2147191696; pub const TIOCPKT_DATA: ::c_int = 0; pub const TIOCPKT_FLUSHREAD: ::c_int = 1; pub const TIOCPKT_FLUSHWRITE: ::c_int = 2; pub const TIOCPKT_NOSTOP: ::c_int = 0x10; pub const TIOCPKT_DOSTOP: ::c_int = 0x20; pub const TIOCPKT_START: ::c_int = 8; pub const TIOCPKT_STOP: ::c_int = 4; // sys/ipc.h pub const IPC_ALLOC: ::c_int = 0o100000; pub const IPC_CREAT: ::c_int = 0o020000; pub const IPC_EXCL: ::c_int = 0o002000; pub const IPC_NOWAIT: ::c_int = 0o004000; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 101; pub const IPC_R: ::c_int = 0o0400; pub const IPC_W: ::c_int = 0o0200; pub const IPC_O: ::c_int = 0o1000; pub const IPC_NOERROR: ::c_int = 0o10000; pub const IPC_STAT: ::c_int = 102; pub const IPC_PRIVATE: ::key_t = -1; pub const SHM_LOCK: ::c_int = 201; pub const SHM_UNLOCK: ::c_int = 202; // sys/ldr.h pub const L_GETINFO: ::c_int = 2; pub const L_GETMESSAGE: ::c_int = 1; pub const L_GETLIBPATH: ::c_int = 3; pub const L_GETXINFO: ::c_int = 8; // sys/limits.h pub const PATH_MAX: ::c_int = 1023; pub const PAGESIZE: ::c_int = 4096; pub const IOV_MAX: ::c_int = 16; pub const AIO_LISTIO_MAX: ::c_int = 4096; pub const PIPE_BUF: usize = 32768; pub const OPEN_MAX: ::c_int = 65534; pub const MAX_INPUT: ::c_int = 512; pub const MAX_CANON: ::c_int = 256; pub const ARG_MAX: ::c_int = 1048576; pub const BC_BASE_MAX: ::c_int = 99; pub const BC_DIM_MAX: ::c_int = 0x800; pub const BC_SCALE_MAX: ::c_int = 99; pub const BC_STRING_MAX: ::c_int = 0x800; pub const CHARCLASS_NAME_MAX: ::c_int = 14; pub const CHILD_MAX: ::c_int = 128; pub const COLL_WEIGHTS_MAX: ::c_int = 4; pub const EXPR_NEST_MAX: ::c_int = 32; pub const NZERO: ::c_int = 20; // sys/lockf.h pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; // sys/machine.h pub const BIG_ENDIAN: ::c_int = 4321; pub const LITTLE_ENDIAN: ::c_int = 1234; pub const PDP_ENDIAN: ::c_int = 3412; // sys/mman.h pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const MAP_FILE: ::c_int = 0; pub const MAP_SHARED: ::c_int = 1; pub const MAP_PRIVATE: ::c_int = 2; pub const MAP_FIXED: ::c_int = 0x100; pub const MAP_ANON: ::c_int = 0x10; pub const MAP_ANONYMOUS: ::c_int = 0x10; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const MAP_TYPE: ::c_int = 0xf0; pub const MCL_CURRENT: ::c_int = 0x100; pub const MCL_FUTURE: ::c_int = 0x200; pub const MS_SYNC: ::c_int = 0x20; pub const MS_ASYNC: ::c_int = 0x10; pub const MS_INVALIDATE: ::c_int = 0x40; pub const POSIX_MADV_NORMAL: ::c_int = 1; pub const POSIX_MADV_RANDOM: ::c_int = 3; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 4; pub const POSIX_MADV_DONTNEED: ::c_int = 5; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; // sys/mode.h pub const S_IFMT: mode_t = 0o170000; pub const S_IFREG: mode_t = 0o100000; pub const S_IFDIR: mode_t = 0o40000; pub const S_IFBLK: mode_t = 0o60000; pub const S_IFCHR: mode_t = 0o20000; pub const S_IFIFO: mode_t = 0o10000; pub const S_IRWXU: mode_t = 0o700; pub const S_IRUSR: mode_t = 0o400; pub const S_IWUSR: mode_t = 0o200; pub const S_IXUSR: mode_t = 0o100; pub const S_IRWXG: mode_t = 0o70; pub const S_IRGRP: mode_t = 0o40; pub const S_IWGRP: mode_t = 0o20; pub const S_IXGRP: mode_t = 0o10; pub const S_IRWXO: mode_t = 7; pub const S_IROTH: mode_t = 4; pub const S_IWOTH: mode_t = 2; pub const S_IXOTH: mode_t = 1; pub const S_IFLNK: mode_t = 0o120000; pub const S_IFSOCK: mode_t = 0o140000; pub const S_IEXEC: mode_t = 0o100; pub const S_IWRITE: mode_t = 0o200; pub const S_IREAD: mode_t = 0o400; // sys/msg.h pub const MSG_NOERROR: ::c_int = 0o10000; // sys/m_signal.h pub const SIGSTKSZ: ::size_t = 4096; pub const MINSIGSTKSZ: ::size_t = 1200; // sys/params.h pub const MAXPATHLEN: ::c_int = PATH_MAX + 1; pub const MAXSYMLINKS: ::c_int = 20; pub const MAXHOSTNAMELEN: ::c_int = 256; pub const MAXUPRC: ::c_int = 128; pub const NGROUPS_MAX: ::c_ulong = 2048; pub const NGROUPS: ::c_ulong = NGROUPS_MAX; pub const NOFILE: ::c_int = OPEN_MAX; // sys/poll.h pub const POLLIN: ::c_short = 0x0001; pub const POLLPRI: ::c_short = 0x0004; pub const POLLOUT: ::c_short = 0x0002; pub const POLLERR: ::c_short = 0x4000; pub const POLLHUP: ::c_short = 0x2000; pub const POLLMSG: ::c_short = 0x0080; pub const POLLSYNC: ::c_short = 0x8000; pub const POLLNVAL: ::c_short = POLLSYNC; pub const POLLNORM: ::c_short = POLLIN; pub const POLLRDNORM: ::c_short = 0x0010; pub const POLLWRNORM: ::c_short = POLLOUT; pub const POLLRDBAND: ::c_short = 0x0020; pub const POLLWRBAND: ::c_short = 0x0040; // sys/pollset.h pub const PS_ADD: ::c_uchar = 0; pub const PS_MOD: ::c_uchar = 1; pub const PS_DELETE: ::c_uchar = 2; pub const PS_REPLACE: ::c_uchar = 3; // sys/ptrace.h pub const PT_TRACE_ME: ::c_int = 0; pub const PT_READ_I: ::c_int = 1; pub const PT_READ_D: ::c_int = 2; pub const PT_WRITE_I: ::c_int = 4; pub const PT_WRITE_D: ::c_int = 5; pub const PT_CONTINUE: ::c_int = 7; pub const PT_KILL: ::c_int = 8; pub const PT_STEP: ::c_int = 9; pub const PT_READ_GPR: ::c_int = 11; pub const PT_READ_FPR: ::c_int = 12; pub const PT_WRITE_GPR: ::c_int = 14; pub const PT_WRITE_FPR: ::c_int = 15; pub const PT_READ_BLOCK: ::c_int = 17; pub const PT_WRITE_BLOCK: ::c_int = 19; pub const PT_ATTACH: ::c_int = 30; pub const PT_DETACH: ::c_int = 31; pub const PT_REGSET: ::c_int = 32; pub const PT_REATT: ::c_int = 33; pub const PT_LDINFO: ::c_int = 34; pub const PT_MULTI: ::c_int = 35; pub const PT_NEXT: ::c_int = 36; pub const PT_SET: ::c_int = 37; pub const PT_CLEAR: ::c_int = 38; pub const PT_LDXINFO: ::c_int = 39; pub const PT_QUERY: ::c_int = 40; pub const PT_WATCH: ::c_int = 41; pub const PTT_CONTINUE: ::c_int = 50; pub const PTT_STEP: ::c_int = 51; pub const PTT_READ_SPRS: ::c_int = 52; pub const PTT_WRITE_SPRS: ::c_int = 53; pub const PTT_READ_GPRS: ::c_int = 54; pub const PTT_WRITE_GPRS: ::c_int = 55; pub const PTT_READ_FPRS: ::c_int = 56; pub const PTT_WRITE_FPRS: ::c_int = 57; pub const PTT_READ_VEC: ::c_int = 58; pub const PTT_WRITE_VEC: ::c_int = 59; pub const PTT_WATCH: ::c_int = 60; pub const PTT_SET_TRAP: ::c_int = 61; pub const PTT_CLEAR_TRAP: ::c_int = 62; pub const PTT_READ_UKEYSET: ::c_int = 63; pub const PT_GET_UKEY: ::c_int = 64; pub const PTT_READ_FPSCR_HI: ::c_int = 65; pub const PTT_WRITE_FPSCR_HI: ::c_int = 66; pub const PTT_READ_VSX: ::c_int = 67; pub const PTT_WRITE_VSX: ::c_int = 68; pub const PTT_READ_TM: ::c_int = 69; pub const PTRACE_ATTACH: ::c_int = 14; pub const PTRACE_CONT: ::c_int = 7; pub const PTRACE_DETACH: ::c_int = 15; pub const PTRACE_GETFPREGS: ::c_int = 12; pub const PTRACE_GETREGS: ::c_int = 10; pub const PTRACE_KILL: ::c_int = 8; pub const PTRACE_PEEKDATA: ::c_int = 2; pub const PTRACE_PEEKTEXT: ::c_int = 1; pub const PTRACE_PEEKUSER: ::c_int = 3; pub const PTRACE_POKEDATA: ::c_int = 5; pub const PTRACE_POKETEXT: ::c_int = 4; pub const PTRACE_POKEUSER: ::c_int = 6; pub const PTRACE_SETFPREGS: ::c_int = 13; pub const PTRACE_SETREGS: ::c_int = 11; pub const PTRACE_SINGLESTEP: ::c_int = 9; pub const PTRACE_SYSCALL: ::c_int = 16; pub const PTRACE_TRACEME: ::c_int = 0; // sys/resource.h pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_AS: ::c_int = 6; pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_THREADS: ::c_int = 8; pub const RLIMIT_NPROC: ::c_int = 9; pub const RUSAGE_SELF: ::c_int = 0; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; pub const RUSAGE_THREAD: ::c_int = 1; pub const RLIM_SAVED_MAX: ::c_ulong = RLIM_INFINITY - 1; pub const RLIM_SAVED_CUR: ::c_ulong = RLIM_INFINITY - 2; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 10; // sys/sched.h pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const SCHED_LOCAL: ::c_int = 3; pub const SCHED_GLOBAL: ::c_int = 4; pub const SCHED_FIFO2: ::c_int = 5; pub const SCHED_FIFO3: ::c_int = 6; pub const SCHED_FIFO4: ::c_int = 7; // sys/sem.h pub const SEM_UNDO: ::c_int = 0o10000; pub const GETNCNT: ::c_int = 3; pub const GETPID: ::c_int = 4; pub const GETVAL: ::c_int = 5; pub const GETALL: ::c_int = 6; pub const GETZCNT: ::c_int = 7; pub const SETVAL: ::c_int = 8; pub const SETALL: ::c_int = 9; // sys/shm.h pub const SHMLBA: ::c_int = 0x10000000; pub const SHMLBA_EXTSHM: ::c_int = 0x1000; pub const SHM_SHMAT: ::c_int = 0x80000000; pub const SHM_RDONLY: ::c_int = 0o10000; pub const SHM_RND: ::c_int = 0o20000; pub const SHM_PIN: ::c_int = 0o4000; pub const SHM_LGPAGE: ::c_int = 0o20000000000; pub const SHM_MAP: ::c_int = 0o4000; pub const SHM_FMAP: ::c_int = 0o2000; pub const SHM_COPY: ::c_int = 0o40000; pub const SHM_CLEAR: ::c_int = 0; pub const SHM_HGSEG: ::c_int = 0o10000000000; pub const SHM_R: ::c_int = IPC_R; pub const SHM_W: ::c_int = IPC_W; pub const SHM_DEST: ::c_int = 0o2000; // sys/signal.h pub const SA_ONSTACK: ::c_int = 0x00000001; pub const SA_RESETHAND: ::c_int = 0x00000002; pub const SA_RESTART: ::c_int = 0x00000008; pub const SA_SIGINFO: ::c_int = 0x00000100; pub const SA_NODEFER: ::c_int = 0x00000200; pub const SA_NOCLDWAIT: ::c_int = 0x00000400; pub const SA_NOCLDSTOP: ::c_int = 0x00000004; pub const SS_ONSTACK: ::c_int = 0x00000001; pub const SS_DISABLE: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 20; pub const SIGBUS: ::c_int = 10; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const SIG_SETMASK: ::c_int = 2; pub const SIGEV_NONE: ::c_int = 1; pub const SIGEV_SIGNAL: ::c_int = 2; pub const SIGEV_THREAD: ::c_int = 3; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGSYS: ::c_int = 12; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const SIGUSR1: ::c_int = 30; pub const SIGUSR2: ::c_int = 31; pub const SIGPWR: ::c_int = 29; pub const SIGWINCH: ::c_int = 28; pub const SIGURG: ::c_int = 16; pub const SIGPOLL: ::c_int = SIGIO; pub const SIGIO: ::c_int = 23; pub const SIGSTOP: ::c_int = 17; pub const SIGTSTP: ::c_int = 18; pub const SIGCONT: ::c_int = 19; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGVTALRM: ::c_int = 34; pub const SIGPROF: ::c_int = 32; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGTRAP: ::c_int = 5; pub const SIGCLD: ::c_int = 20; pub const SIGRTMAX: ::c_int = 57; pub const SIGRTMIN: ::c_int = 50; pub const SI_USER: ::c_int = 0; pub const SI_UNDEFINED: ::c_int = 8; pub const SI_EMPTY: ::c_int = 9; pub const BUS_ADRALN: ::c_int = 1; pub const BUS_ADRERR: ::c_int = 2; pub const BUS_OBJERR: ::c_int = 3; pub const BUS_UEGARD: ::c_int = 4; pub const CLD_EXITED: ::c_int = 10; pub const CLD_KILLED: ::c_int = 11; pub const CLD_DUMPED: ::c_int = 12; pub const CLD_TRAPPED: ::c_int = 13; pub const CLD_STOPPED: ::c_int = 14; pub const CLD_CONTINUED: ::c_int = 15; pub const FPE_INTDIV: ::c_int = 20; pub const FPE_INTOVF: ::c_int = 21; pub const FPE_FLTDIV: ::c_int = 22; pub const FPE_FLTOVF: ::c_int = 23; pub const FPE_FLTUND: ::c_int = 24; pub const FPE_FLTRES: ::c_int = 25; pub const FPE_FLTINV: ::c_int = 26; pub const FPE_FLTSUB: ::c_int = 27; pub const ILL_ILLOPC: ::c_int = 30; pub const ILL_ILLOPN: ::c_int = 31; pub const ILL_ILLADR: ::c_int = 32; pub const ILL_ILLTRP: ::c_int = 33; pub const ILL_PRVOPC: ::c_int = 34; pub const ILL_PRVREG: ::c_int = 35; pub const ILL_COPROC: ::c_int = 36; pub const ILL_BADSTK: ::c_int = 37; pub const ILL_TMBADTHING: ::c_int = 38; pub const POLL_IN: ::c_int = 40; pub const POLL_OUT: ::c_int = 41; pub const POLL_MSG: ::c_int = -3; pub const POLL_ERR: ::c_int = 43; pub const POLL_PRI: ::c_int = 44; pub const POLL_HUP: ::c_int = 45; pub const SEGV_MAPERR: ::c_int = 50; pub const SEGV_ACCERR: ::c_int = 51; pub const SEGV_KEYERR: ::c_int = 52; pub const TRAP_BRKPT: ::c_int = 60; pub const TRAP_TRACE: ::c_int = 61; pub const SI_QUEUE: ::c_int = 71; pub const SI_TIMER: ::c_int = 72; pub const SI_ASYNCIO: ::c_int = 73; pub const SI_MESGQ: ::c_int = 74; // sys/socket.h pub const AF_UNSPEC: ::c_int = 0; pub const AF_UNIX: ::c_int = 1; pub const AF_INET: ::c_int = 2; pub const AF_IMPLINK: ::c_int = 3; pub const AF_PUP: ::c_int = 4; pub const AF_CHAOS: ::c_int = 5; pub const AF_NS: ::c_int = 6; pub const AF_ECMA: ::c_int = 8; pub const AF_DATAKIT: ::c_int = 9; pub const AF_CCITT: ::c_int = 10; pub const AF_SNA: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_DLI: ::c_int = 13; pub const AF_LAT: ::c_int = 14; pub const SO_TIMESTAMPNS: ::c_int = 0x100a; pub const SOMAXCONN: ::c_int = 1024; pub const AF_LOCAL: ::c_int = AF_UNIX; pub const UIO_MAXIOV: ::c_int = 1024; pub const pseudo_AF_XTP: ::c_int = 19; pub const AF_HYLINK: ::c_int = 15; pub const AF_APPLETALK: ::c_int = 16; pub const AF_ISO: ::c_int = 7; pub const AF_OSI: ::c_int = AF_ISO; pub const AF_ROUTE: ::c_int = 17; pub const AF_LINK: ::c_int = 18; pub const AF_INET6: ::c_int = 24; pub const AF_INTF: ::c_int = 20; pub const AF_RIF: ::c_int = 21; pub const AF_NDD: ::c_int = 23; pub const AF_MAX: ::c_int = 30; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_UNIX: ::c_int = AF_UNIX; pub const PF_INET: ::c_int = AF_INET; pub const PF_IMPLINK: ::c_int = AF_IMPLINK; pub const PF_PUP: ::c_int = AF_PUP; pub const PF_CHAOS: ::c_int = AF_CHAOS; pub const PF_NS: ::c_int = AF_NS; pub const PF_ISO: ::c_int = AF_ISO; pub const PF_OSI: ::c_int = AF_ISO; pub const PF_ECMA: ::c_int = AF_ECMA; pub const PF_DATAKIT: ::c_int = AF_DATAKIT; pub const PF_CCITT: ::c_int = AF_CCITT; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_DECnet: ::c_int = AF_DECnet; pub const PF_DLI: ::c_int = AF_DLI; pub const PF_LAT: ::c_int = AF_LAT; pub const PF_HYLINK: ::c_int = AF_HYLINK; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_LINK: ::c_int = AF_LINK; pub const PF_XTP: ::c_int = 19; pub const PF_RIF: ::c_int = AF_RIF; pub const PF_INTF: ::c_int = AF_INTF; pub const PF_NDD: ::c_int = AF_NDD; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_MAX: ::c_int = AF_MAX; pub const SF_CLOSE: ::c_int = 1; pub const SF_REUSE: ::c_int = 2; pub const SF_DONT_CACHE: ::c_int = 4; pub const SF_SYNC_CACHE: ::c_int = 8; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x0001; pub const SO_ACCEPTCONN: ::c_int = 0x0002; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_USE_IFBUFS: ::c_int = 0x0400; pub const SO_CKSUMRECV: ::c_int = 0x0800; pub const SO_NOREUSEADDR: ::c_int = 0x1000; pub const SO_KERNACCEPT: ::c_int = 0x2000; pub const SO_NOMULTIPATH: ::c_int = 0x4000; pub const SO_AUDIT: ::c_int = 0x8000; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVLOWAT: ::c_int = 0x1004; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; pub const SCM_RIGHTS: ::c_int = 0x01; pub const MSG_OOB: ::c_int = 0x1; pub const MSG_PEEK: ::c_int = 0x2; pub const MSG_DONTROUTE: ::c_int = 0x4; pub const MSG_EOR: ::c_int = 0x8; pub const MSG_TRUNC: ::c_int = 0x10; pub const MSG_CTRUNC: ::c_int = 0x20; pub const MSG_WAITALL: ::c_int = 0x40; pub const MSG_MPEG2: ::c_int = 0x80; pub const MSG_NOSIGNAL: ::c_int = 0x100; pub const MSG_WAITFORONE: ::c_int = 0x200; pub const MSG_ARGEXT: ::c_int = 0x400; pub const MSG_NONBLOCK: ::c_int = 0x4000; pub const MSG_COMPAT: ::c_int = 0x8000; pub const MSG_MAXIOVLEN: ::c_int = 16; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; // sys/stat.h pub const UTIME_NOW: ::c_int = -2; pub const UTIME_OMIT: ::c_int = -3; // sys/statvfs.h pub const ST_RDONLY: ::c_ulong = 0x0001; pub const ST_NOSUID: ::c_ulong = 0x0040; pub const ST_NODEV: ::c_ulong = 0x0080; // sys/stropts.h pub const I_NREAD: ::c_int = 0x20005301; pub const I_PUSH: ::c_int = 0x20005302; pub const I_POP: ::c_int = 0x20005303; pub const I_LOOK: ::c_int = 0x20005304; pub const I_FLUSH: ::c_int = 0x20005305; pub const I_SRDOPT: ::c_int = 0x20005306; pub const I_GRDOPT: ::c_int = 0x20005307; pub const I_STR: ::c_int = 0x20005308; pub const I_SETSIG: ::c_int = 0x20005309; pub const I_GETSIG: ::c_int = 0x2000530a; pub const I_FIND: ::c_int = 0x2000530b; pub const I_LINK: ::c_int = 0x2000530c; pub const I_UNLINK: ::c_int = 0x2000530d; pub const I_PEEK: ::c_int = 0x2000530f; pub const I_FDINSERT: ::c_int = 0x20005310; pub const I_SENDFD: ::c_int = 0x20005311; pub const I_RECVFD: ::c_int = 0x20005312; pub const I_SWROPT: ::c_int = 0x20005314; pub const I_GWROPT: ::c_int = 0x20005315; pub const I_LIST: ::c_int = 0x20005316; pub const I_PLINK: ::c_int = 0x2000531d; pub const I_PUNLINK: ::c_int = 0x2000531e; pub const I_FLUSHBAND: ::c_int = 0x20005313; pub const I_CKBAND: ::c_int = 0x20005318; pub const I_GETBAND: ::c_int = 0x20005319; pub const I_ATMARK: ::c_int = 0x20005317; pub const I_SETCLTIME: ::c_int = 0x2000531b; pub const I_GETCLTIME: ::c_int = 0x2000531c; pub const I_CANPUT: ::c_int = 0x2000531a; // sys/syslog.h pub const LOG_CRON: ::c_int = 9 << 3; pub const LOG_AUTHPRIV: ::c_int = 10 << 3; pub const LOG_NFACILITIES: ::c_int = 24; pub const LOG_PERROR: ::c_int = 0x20; // sys/systemcfg.h pub const SC_ARCH: ::c_int = 1; pub const SC_IMPL: ::c_int = 2; pub const SC_VERS: ::c_int = 3; pub const SC_WIDTH: ::c_int = 4; pub const SC_NCPUS: ::c_int = 5; pub const SC_L1C_ATTR: ::c_int = 6; pub const SC_L1C_ISZ: ::c_int = 7; pub const SC_L1C_DSZ: ::c_int = 8; pub const SC_L1C_ICA: ::c_int = 9; pub const SC_L1C_DCA: ::c_int = 10; pub const SC_L1C_IBS: ::c_int = 11; pub const SC_L1C_DBS: ::c_int = 12; pub const SC_L1C_ILS: ::c_int = 13; pub const SC_L1C_DLS: ::c_int = 14; pub const SC_L2C_SZ: ::c_int = 15; pub const SC_L2C_AS: ::c_int = 16; pub const SC_TLB_ATTR: ::c_int = 17; pub const SC_ITLB_SZ: ::c_int = 18; pub const SC_DTLB_SZ: ::c_int = 19; pub const SC_ITLB_ATT: ::c_int = 20; pub const SC_DTLB_ATT: ::c_int = 21; pub const SC_RESRV_SZ: ::c_int = 22; pub const SC_PRI_LC: ::c_int = 23; pub const SC_PRO_LC: ::c_int = 24; pub const SC_RTC_TYPE: ::c_int = 25; pub const SC_VIRT_AL: ::c_int = 26; pub const SC_CAC_CONG: ::c_int = 27; pub const SC_MOD_ARCH: ::c_int = 28; pub const SC_MOD_IMPL: ::c_int = 29; pub const SC_XINT: ::c_int = 30; pub const SC_XFRAC: ::c_int = 31; pub const SC_KRN_ATTR: ::c_int = 32; pub const SC_PHYSMEM: ::c_int = 33; pub const SC_SLB_ATTR: ::c_int = 34; pub const SC_SLB_SZ: ::c_int = 35; pub const SC_MAX_NCPUS: ::c_int = 37; pub const SC_MAX_REALADDR: ::c_int = 38; pub const SC_ORIG_ENT_CAP: ::c_int = 39; pub const SC_ENT_CAP: ::c_int = 40; pub const SC_DISP_WHE: ::c_int = 41; pub const SC_CAPINC: ::c_int = 42; pub const SC_VCAPW: ::c_int = 43; pub const SC_SPLP_STAT: ::c_int = 44; pub const SC_SMT_STAT: ::c_int = 45; pub const SC_SMT_TC: ::c_int = 46; pub const SC_VMX_VER: ::c_int = 47; pub const SC_LMB_SZ: ::c_int = 48; pub const SC_MAX_XCPU: ::c_int = 49; pub const SC_EC_LVL: ::c_int = 50; pub const SC_AME_STAT: ::c_int = 51; pub const SC_ECO_STAT: ::c_int = 52; pub const SC_DFP_VER: ::c_int = 53; pub const SC_VRM_STAT: ::c_int = 54; pub const SC_PHYS_IMP: ::c_int = 55; pub const SC_PHYS_VER: ::c_int = 56; pub const SC_SPCM_STATUS: ::c_int = 57; pub const SC_SPCM_MAX: ::c_int = 58; pub const SC_TM_VER: ::c_int = 59; pub const SC_NX_CAP: ::c_int = 60; pub const SC_PKS_STATE: ::c_int = 61; pub const SC_MMA_VER: ::c_int = 62; pub const POWER_RS: ::c_int = 1; pub const POWER_PC: ::c_int = 2; pub const IA64: ::c_int = 3; pub const POWER_RS1: ::c_int = 0x1; pub const POWER_RSC: ::c_int = 0x2; pub const POWER_RS2: ::c_int = 0x4; pub const POWER_601: ::c_int = 0x8; pub const POWER_604: ::c_int = 0x10; pub const POWER_603: ::c_int = 0x20; pub const POWER_620: ::c_int = 0x40; pub const POWER_630: ::c_int = 0x80; pub const POWER_A35: ::c_int = 0x100; pub const POWER_RS64II: ::c_int = 0x200; pub const POWER_RS64III: ::c_int = 0x400; pub const POWER_4: ::c_int = 0x800; pub const POWER_RS64IV: ::c_int = POWER_4; pub const POWER_MPC7450: ::c_int = 0x1000; pub const POWER_5: ::c_int = 0x2000; pub const POWER_6: ::c_int = 0x4000; pub const POWER_7: ::c_int = 0x8000; pub const POWER_8: ::c_int = 0x10000; pub const POWER_9: ::c_int = 0x20000; // sys/time.h pub const FD_SETSIZE: usize = 65534; pub const TIMEOFDAY: ::c_int = 9; pub const CLOCK_REALTIME: ::clockid_t = TIMEOFDAY as clockid_t; pub const CLOCK_MONOTONIC: ::clockid_t = 10; pub const TIMER_ABSTIME: ::c_int = 999; pub const ITIMER_REAL: ::c_int = 0; pub const ITIMER_VIRTUAL: ::c_int = 1; pub const ITIMER_PROF: ::c_int = 2; pub const ITIMER_VIRT: ::c_int = 3; pub const ITIMER_REAL1: ::c_int = 20; pub const ITIMER_REAL_TH: ::c_int = ITIMER_REAL1; pub const DST_AUST: ::c_int = 2; pub const DST_CAN: ::c_int = 6; pub const DST_EET: ::c_int = 5; pub const DST_MET: ::c_int = 4; pub const DST_NONE: ::c_int = 0; pub const DST_USA: ::c_int = 1; pub const DST_WET: ::c_int = 3; // sys/termio.h pub const CSTART: ::tcflag_t = 0o21; pub const CSTOP: ::tcflag_t = 0o23; pub const TCGETA: ::c_int = TIOC | 5; pub const TCSETA: ::c_int = TIOC | 6; pub const TCSETAW: ::c_int = TIOC | 7; pub const TCSETAF: ::c_int = TIOC | 8; pub const TCSBRK: ::c_int = TIOC | 9; pub const TCXONC: ::c_int = TIOC | 11; pub const TCFLSH: ::c_int = TIOC | 12; pub const TCGETS: ::c_int = TIOC | 1; pub const TCSETS: ::c_int = TIOC | 2; pub const TCSANOW: ::c_int = 0; pub const TCSETSW: ::c_int = TIOC | 3; pub const TCSADRAIN: ::c_int = 1; pub const TCSETSF: ::c_int = TIOC | 4; pub const TCSAFLUSH: ::c_int = 2; pub const TCIFLUSH: ::c_int = 0; pub const TCOFLUSH: ::c_int = 1; pub const TCIOFLUSH: ::c_int = 2; pub const TCOOFF: ::c_int = 0; pub const TCOON: ::c_int = 1; pub const TCIOFF: ::c_int = 2; pub const TCION: ::c_int = 3; pub const TIOC: ::c_int = 0x5400; pub const TIOCGWINSZ: ::c_int = 0x40087468; pub const TIOCSWINSZ: ::c_int = 0x80087467; pub const TIOCLBIS: ::c_int = 0x8004747f; pub const TIOCLBIC: ::c_int = 0x8004747e; pub const TIOCLSET: ::c_int = 0x8004747d; pub const TIOCLGET: ::c_int = 0x4004747c; pub const TIOCSBRK: ::c_int = 0x2000747b; pub const TIOCCBRK: ::c_int = 0x2000747a; pub const TIOCSDTR: ::c_int = 0x20007479; pub const TIOCCDTR: ::c_int = 0x20007478; pub const TIOCSLTC: ::c_int = 0x80067475; pub const TIOCGLTC: ::c_int = 0x40067474; pub const TIOCOUTQ: ::c_int = 0x40047473; pub const TIOCNOTTY: ::c_int = 0x20007471; pub const TIOCSTOP: ::c_int = 0x2000746f; pub const TIOCSTART: ::c_int = 0x2000746e; pub const TIOCGPGRP: ::c_int = 0x40047477; pub const TIOCSPGRP: ::c_int = 0x80047476; pub const TIOCGSID: ::c_int = 0x40047448; pub const TIOCSTI: ::c_int = 0x80017472; pub const TIOCMSET: ::c_int = 0x8004746d; pub const TIOCMBIS: ::c_int = 0x8004746c; pub const TIOCMBIC: ::c_int = 0x8004746b; pub const TIOCMGET: ::c_int = 0x4004746a; pub const TIOCREMOTE: ::c_int = 0x80047469; // sys/user.h pub const MAXCOMLEN: ::c_int = 32; pub const UF_SYSTEM: ::c_int = 0x1000; // sys/vattr.h pub const AT_FLAGS: ::c_int = 0x80; pub const AT_GID: ::c_int = 8; pub const AT_UID: ::c_int = 4; // sys/wait.h pub const P_ALL: ::c_int = 0; pub const P_PID: ::c_int = 1; pub const P_PGID: ::c_int = 2; pub const WNOHANG: ::c_int = 0x1; pub const WUNTRACED: ::c_int = 0x2; pub const WEXITED: ::c_int = 0x04; pub const WCONTINUED: ::c_int = 0x01000000; pub const WNOWAIT: ::c_int = 0x10; pub const WSTOPPED: ::c_int = _W_STOPPED; pub const _W_STOPPED: ::c_int = 0x00000040; pub const _W_SLWTED: ::c_int = 0x0000007c; pub const _W_SEWTED: ::c_int = 0x0000007d; pub const _W_SFWTED: ::c_int = 0x0000007e; pub const _W_STRC: ::c_int = 0x0000007f; // termios.h pub const NCCS: usize = 16; pub const OLCUC: ::tcflag_t = 2; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS5: ::tcflag_t = 0x00000000; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const ECHO: ::tcflag_t = 0x20000; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOCTL: ::tcflag_t = 0x00020000; pub const ECHOPRT: ::tcflag_t = 0x00040000; pub const ECHOKE: ::tcflag_t = 0x00080000; pub const IGNBRK: ::tcflag_t = 0x00000001; pub const BRKINT: ::tcflag_t = 0x00000002; pub const IGNPAR: ::tcflag_t = 0x00000004; pub const PARMRK: ::tcflag_t = 0x00000008; pub const INPCK: ::tcflag_t = 0x00000010; pub const ISTRIP: ::tcflag_t = 0x00000020; pub const INLCR: ::tcflag_t = 0x00000040; pub const IGNCR: ::tcflag_t = 0x00000080; pub const ICRNL: ::tcflag_t = 0x00000100; pub const IXON: ::tcflag_t = 0x0001; pub const IXOFF: ::tcflag_t = 0x00000400; pub const IXANY: ::tcflag_t = 0x00001000; pub const IMAXBEL: ::tcflag_t = 0x00010000; pub const OPOST: ::tcflag_t = 0x00000001; pub const ONLCR: ::tcflag_t = 0x00000004; pub const OCRNL: ::tcflag_t = 0x00000008; pub const ONOCR: ::tcflag_t = 0x00000010; pub const ONLRET: ::tcflag_t = 0x00000020; pub const CREAD: ::tcflag_t = 0x00000080; pub const IEXTEN: ::tcflag_t = 0x00200000; pub const TOSTOP: ::tcflag_t = 0x00010000; pub const FLUSHO: ::tcflag_t = 0x00100000; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VEOF: usize = 4; pub const VEOL: usize = 5; pub const VSTART: usize = 7; pub const VSTOP: usize = 8; pub const VSUSP: usize = 9; pub const VMIN: usize = 4; pub const VTIME: usize = 5; pub const VEOL2: usize = 6; pub const VDSUSP: usize = 10; pub const VREPRINT: usize = 11; pub const VDISCRD: usize = 12; pub const VWERSE: usize = 13; pub const VLNEXT: usize = 14; pub const B0: ::speed_t = 0x0; pub const B50: ::speed_t = 0x1; pub const B75: ::speed_t = 0x2; pub const B110: ::speed_t = 0x3; pub const B134: ::speed_t = 0x4; pub const B150: ::speed_t = 0x5; pub const B200: ::speed_t = 0x6; pub const B300: ::speed_t = 0x7; pub const B600: ::speed_t = 0x8; pub const B1200: ::speed_t = 0x9; pub const B1800: ::speed_t = 0xa; pub const B2400: ::speed_t = 0xb; pub const B4800: ::speed_t = 0xc; pub const B9600: ::speed_t = 0xd; pub const B19200: ::speed_t = 0xe; pub const B38400: ::speed_t = 0xf; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const IUCLC: ::tcflag_t = 0x00000800; pub const OFILL: ::tcflag_t = 0x00000040; pub const OFDEL: ::tcflag_t = 0x00000080; pub const CRDLY: ::tcflag_t = 0x00000300; pub const CR0: ::tcflag_t = 0x00000000; pub const CR1: ::tcflag_t = 0x00000100; pub const CR2: ::tcflag_t = 0x00000200; pub const CR3: ::tcflag_t = 0x00000300; pub const TABDLY: ::tcflag_t = 0x00000c00; pub const TAB0: ::tcflag_t = 0x00000000; pub const TAB1: ::tcflag_t = 0x00000400; pub const TAB2: ::tcflag_t = 0x00000800; pub const TAB3: ::tcflag_t = 0x00000c00; pub const BSDLY: ::tcflag_t = 0x00001000; pub const BS0: ::tcflag_t = 0x00000000; pub const BS1: ::tcflag_t = 0x00001000; pub const FFDLY: ::tcflag_t = 0x00002000; pub const FF0: ::tcflag_t = 0x00000000; pub const FF1: ::tcflag_t = 0x00002000; pub const NLDLY: ::tcflag_t = 0x00004000; pub const NL0: ::tcflag_t = 0x00000000; pub const NL1: ::tcflag_t = 0x00004000; pub const VTDLY: ::tcflag_t = 0x00008000; pub const VT0: ::tcflag_t = 0x00000000; pub const VT1: ::tcflag_t = 0x00008000; pub const OXTABS: ::tcflag_t = 0x00040000; pub const ONOEOT: ::tcflag_t = 0x00080000; pub const CBAUD: ::tcflag_t = 0x0000000f; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const CIBAUD: ::tcflag_t = 0x000f0000; pub const IBSHIFT: ::tcflag_t = 16; pub const PAREXT: ::tcflag_t = 0x00100000; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const XCASE: ::tcflag_t = 0x00000004; pub const ALTWERASE: ::tcflag_t = 0x00400000; // time.h pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 11; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 12; // unistd.h pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const _POSIX_VDISABLE: ::c_int = 0xff; pub const _PC_LINK_MAX: ::c_int = 11; pub const _PC_MAX_CANON: ::c_int = 12; pub const _PC_MAX_INPUT: ::c_int = 13; pub const _PC_NAME_MAX: ::c_int = 14; pub const _PC_PATH_MAX: ::c_int = 16; pub const _PC_PIPE_BUF: ::c_int = 17; pub const _PC_NO_TRUNC: ::c_int = 15; pub const _PC_VDISABLE: ::c_int = 18; pub const _PC_CHOWN_RESTRICTED: ::c_int = 10; pub const _PC_ASYNC_IO: ::c_int = 19; pub const _PC_PRIO_IO: ::c_int = 21; pub const _PC_SYNC_IO: ::c_int = 20; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 26; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 27; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 28; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 29; pub const _PC_REC_XFER_ALIGN: ::c_int = 30; pub const _PC_SYMLINK_MAX: ::c_int = 25; pub const _PC_2_SYMLINKS: ::c_int = 31; pub const _PC_TIMESTAMP_RESOLUTION: ::c_int = 32; pub const _PC_FILESIZEBITS: ::c_int = 22; pub const _SC_ARG_MAX: ::c_int = 0; pub const _SC_CHILD_MAX: ::c_int = 1; pub const _SC_CLK_TCK: ::c_int = 2; pub const _SC_NGROUPS_MAX: ::c_int = 3; pub const _SC_OPEN_MAX: ::c_int = 4; pub const _SC_JOB_CONTROL: ::c_int = 7; pub const _SC_SAVED_IDS: ::c_int = 8; pub const _SC_VERSION: ::c_int = 9; pub const _SC_PASS_MAX: ::c_int = 45; pub const _SC_PAGESIZE: ::c_int = _SC_PAGE_SIZE; pub const _SC_PAGE_SIZE: ::c_int = 48; pub const _SC_XOPEN_VERSION: ::c_int = 46; pub const _SC_NPROCESSORS_CONF: ::c_int = 71; pub const _SC_NPROCESSORS_ONLN: ::c_int = 72; pub const _SC_STREAM_MAX: ::c_int = 5; pub const _SC_TZNAME_MAX: ::c_int = 6; pub const _SC_AIO_LISTIO_MAX: ::c_int = 75; pub const _SC_AIO_MAX: ::c_int = 76; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 77; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 78; pub const _SC_DELAYTIMER_MAX: ::c_int = 79; pub const _SC_FSYNC: ::c_int = 80; pub const _SC_MAPPED_FILES: ::c_int = 84; pub const _SC_MEMLOCK: ::c_int = 85; pub const _SC_MEMLOCK_RANGE: ::c_int = 86; pub const _SC_MEMORY_PROTECTION: ::c_int = 87; pub const _SC_MESSAGE_PASSING: ::c_int = 88; pub const _SC_MQ_OPEN_MAX: ::c_int = 89; pub const _SC_MQ_PRIO_MAX: ::c_int = 90; pub const _SC_PRIORITIZED_IO: ::c_int = 91; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 92; pub const _SC_REALTIME_SIGNALS: ::c_int = 93; pub const _SC_RTSIG_MAX: ::c_int = 94; pub const _SC_SEMAPHORES: ::c_int = 95; pub const _SC_SEM_NSEMS_MAX: ::c_int = 96; pub const _SC_SEM_VALUE_MAX: ::c_int = 97; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 98; pub const _SC_SIGQUEUE_MAX: ::c_int = 99; pub const _SC_SYNCHRONIZED_IO: ::c_int = 100; pub const _SC_TIMERS: ::c_int = 102; pub const _SC_TIMER_MAX: ::c_int = 103; pub const _SC_2_C_BIND: ::c_int = 51; pub const _SC_2_C_DEV: ::c_int = 32; pub const _SC_2_C_VERSION: ::c_int = 52; pub const _SC_2_FORT_DEV: ::c_int = 33; pub const _SC_2_FORT_RUN: ::c_int = 34; pub const _SC_2_LOCALEDEF: ::c_int = 35; pub const _SC_2_SW_DEV: ::c_int = 36; pub const _SC_2_UPE: ::c_int = 53; pub const _SC_2_VERSION: ::c_int = 31; pub const _SC_BC_BASE_MAX: ::c_int = 23; pub const _SC_BC_DIM_MAX: ::c_int = 24; pub const _SC_BC_SCALE_MAX: ::c_int = 25; pub const _SC_BC_STRING_MAX: ::c_int = 26; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 50; pub const _SC_EXPR_NEST_MAX: ::c_int = 28; pub const _SC_LINE_MAX: ::c_int = 29; pub const _SC_RE_DUP_MAX: ::c_int = 30; pub const _SC_XOPEN_CRYPT: ::c_int = 56; pub const _SC_XOPEN_ENH_I18N: ::c_int = 57; pub const _SC_XOPEN_SHM: ::c_int = 55; pub const _SC_2_CHAR_TERM: ::c_int = 54; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 109; pub const _SC_ATEXIT_MAX: ::c_int = 47; pub const _SC_IOV_MAX: ::c_int = 58; pub const _SC_XOPEN_UNIX: ::c_int = 73; pub const _SC_T_IOV_MAX: ::c_int = 0; pub const _SC_PHYS_PAGES: ::c_int = 113; pub const _SC_AVPHYS_PAGES: ::c_int = 114; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 101; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 81; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 82; pub const _SC_LOGIN_NAME_MAX: ::c_int = 83; pub const _SC_THREAD_KEYS_MAX: ::c_int = 68; pub const _SC_THREAD_STACK_MIN: ::c_int = 69; pub const _SC_THREAD_THREADS_MAX: ::c_int = 70; pub const _SC_TTY_NAME_MAX: ::c_int = 104; pub const _SC_THREADS: ::c_int = 60; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 61; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 62; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 64; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 65; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 66; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 59; pub const _SC_XOPEN_LEGACY: ::c_int = 112; pub const _SC_XOPEN_REALTIME: ::c_int = 110; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 111; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 105; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 106; pub const _SC_XBS5_LP64_OFF64: ::c_int = 107; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 108; pub const _SC_2_PBS: ::c_int = 132; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 133; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 134; pub const _SC_2_PBS_LOCATE: ::c_int = 135; pub const _SC_2_PBS_MESSAGE: ::c_int = 136; pub const _SC_2_PBS_TRACK: ::c_int = 137; pub const _SC_ADVISORY_INFO: ::c_int = 130; pub const _SC_BARRIERS: ::c_int = 138; pub const _SC_CLOCK_SELECTION: ::c_int = 139; pub const _SC_CPUTIME: ::c_int = 140; pub const _SC_HOST_NAME_MAX: ::c_int = 126; pub const _SC_MONOTONIC_CLOCK: ::c_int = 141; pub const _SC_READER_WRITER_LOCKS: ::c_int = 142; pub const _SC_REGEXP: ::c_int = 127; pub const _SC_SHELL: ::c_int = 128; pub const _SC_SPAWN: ::c_int = 143; pub const _SC_SPIN_LOCKS: ::c_int = 144; pub const _SC_SPORADIC_SERVER: ::c_int = 145; pub const _SC_SS_REPL_MAX: ::c_int = 156; pub const _SC_SYMLOOP_MAX: ::c_int = 129; pub const _SC_THREAD_CPUTIME: ::c_int = 146; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 147; pub const _SC_TIMEOUTS: ::c_int = 148; pub const _SC_TRACE: ::c_int = 149; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 150; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 157; pub const _SC_TRACE_INHERIT: ::c_int = 151; pub const _SC_TRACE_LOG: ::c_int = 152; pub const _SC_TRACE_NAME_MAX: ::c_int = 158; pub const _SC_TRACE_SYS_MAX: ::c_int = 159; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 160; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 153; pub const _SC_V6_ILP32_OFF32: ::c_int = 121; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 122; pub const _SC_V6_LP64_OFF64: ::c_int = 123; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 124; pub const _SC_XOPEN_STREAMS: ::c_int = 125; pub const _SC_IPV6: ::c_int = 154; pub const _SC_RAW_SOCKETS: ::c_int = 155; // utmp.h pub const EMPTY: ::c_short = -1; pub const RUN_LVL: ::c_short = 1; pub const BOOT_TIME: ::c_short = 2; pub const OLD_TIME: ::c_short = 3; pub const NEW_TIME: ::c_short = 4; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const USER_PROCESS: ::c_short = 7; pub const DEAD_PROCESS: ::c_short = 8; pub const ACCOUNTING: ::c_short = 9; f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= ::mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { CMSG_FIRSTHDR(mhdr) } else { if (cmsg as usize + (*cmsg).cmsg_len as usize + ::mem::size_of::<::cmsghdr>()) > ((*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize) { 0 as *mut ::cmsghdr } else { // AIX does not have any alignment/padding for ancillary data, so we don't need _CMSG_ALIGN here. (cmsg as usize + (*cmsg).cmsg_len as usize) as *mut cmsghdr } } } pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar).offset(::mem::size_of::<::cmsghdr>() as isize) } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { ::mem::size_of::<::cmsghdr>() as ::c_uint + length } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { ::mem::size_of::<::cmsghdr>() as ::c_uint + length } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of::<::c_long>() * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of::<::c_long>() * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let bits = ::mem::size_of::<::c_long>() * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0 } pub fn major(dev: ::dev_t) -> ::c_uint { let x = dev >> 16; x as ::c_uint } pub fn minor(dev: ::dev_t) -> ::c_uint { let y = dev & 0xFFFF; y as ::c_uint } pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= major << 16; dev |= minor; dev } } safe_f! { pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & _W_STOPPED) != 0 } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { if WIFSTOPPED(status) { (((status as ::c_uint) >> 8) & 0xff) as ::c_int } else { -1 } } pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0xFF) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { if WIFEXITED(status) { (((status as ::c_uint) >> 8) & 0xff) as ::c_int } else { -1 } } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { !WIFEXITED(status) && !WIFSTOPPED(status) } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { if WIFSIGNALED(status) { (((status as ::c_uint) >> 16) & 0xff) as ::c_int } else { -1 } } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { (status & WCONTINUED) != 0 } // AIX doesn't have native WCOREDUMP. pub {const} fn WCOREDUMP(_status: ::c_int) -> bool { false } } #[link(name = "thread")] extern "C" { pub fn thr_kill(id: thread_t, sig: ::c_int) -> ::c_int; pub fn thr_self() -> thread_t; } #[link(name = "pthread")] extern "C" { pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getschedparam( attr: *const ::pthread_attr_t, param: *mut sched_param, ) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setschedparam( attr: *mut ::pthread_attr_t, param: *const sched_param, ) -> ::c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const ::pthread_barrierattr_t, count: ::c_uint, ) -> ::c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_barrierattr_destroy(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_getpshared( attr: *const ::pthread_barrierattr_t, shared: *mut ::c_int, ) -> ::c_int; pub fn pthread_barrierattr_init(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_setpshared( attr: *mut ::pthread_barrierattr_t, shared: ::c_int, ) -> ::c_int; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_getcpuclockid(thread: ::pthread_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn pthread_getschedparam( thread: ::pthread_t, policy: *mut ::c_int, param: *mut sched_param, ) -> ::c_int; pub fn pthread_kill(thread: ::pthread_t, signal: ::c_int) -> ::c_int; pub fn pthread_mutex_consistent(mutex: *mut ::pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_mutexattr_getprotocol( attr: *const pthread_mutexattr_t, protocol: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_getrobust( attr: *mut ::pthread_mutexattr_t, robust: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setprotocol( attr: *mut pthread_mutexattr_t, protocol: ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setpshared( attr: *mut pthread_mutexattr_t, pshared: ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setrobust( attr: *mut ::pthread_mutexattr_t, robust: ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; pub fn pthread_setschedparam( thread: ::pthread_t, policy: ::c_int, param: *const sched_param, ) -> ::c_int; pub fn pthread_setschedprio(native: ::pthread_t, priority: ::c_int) -> ::c_int; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> ::c_int; } #[link(name = "iconv")] extern "C" { pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, inbytesleft: *mut ::size_t, outbuf: *mut *mut ::c_char, outbytesleft: *mut ::size_t, ) -> ::size_t; pub fn iconv_close(cd: iconv_t) -> ::c_int; pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; } extern "C" { pub fn acct(filename: *const ::c_char) -> ::c_int; pub fn aio_cancel(fildes: ::c_int, aiocbp: *mut ::aiocb) -> ::c_int; pub fn aio_error(aiocbp: *mut ::aiocb) -> ::c_int; #[link_name = "_posix_aio_fsync"] pub fn aio_fsync(op: ::c_int, aiocbp: *mut ::aiocb) -> ::c_int; pub fn aio_read(aiocbp: *mut ::aiocb) -> ::c_int; // pub fn aio_suspend // pub fn aio_write pub fn basename(path: *mut ::c_char) -> *mut ::c_char; pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn brk(addr: *mut ::c_void) -> ::c_int; pub fn clearenv() -> ::c_int; pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn clock_settime(clock_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn creat64(path: *const c_char, mode: mode_t) -> ::c_int; pub fn ctermid(s: *mut ::c_char) -> *mut ::c_char; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn drand48() -> ::c_double; pub fn duplocale(arg1: ::locale_t) -> ::locale_t; pub fn endgrent(); pub fn endmntent(streamp: *mut ::FILE) -> ::c_int; pub fn endpwent(); pub fn endutent(); pub fn endutxent(); pub fn erand48(xseed: *mut ::c_ushort) -> ::c_double; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn fattach(fildes: ::c_int, path: *const ::c_char) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn fexecve( fd: ::c_int, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn ffs(value: ::c_int) -> ::c_int; pub fn ffsl(value: ::c_long) -> ::c_int; pub fn ffsll(value: ::c_longlong) -> ::c_int; pub fn fgetgrent(file: *mut ::FILE) -> *mut ::group; pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int; pub fn fgetpwent(file: *mut ::FILE) -> *mut ::passwd; pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn freelocale(loc: ::locale_t); pub fn freopen64( filename: *const c_char, mode: *const c_char, file: *mut ::FILE, ) -> *mut ::FILE; pub fn fseeko64(stream: *mut ::FILE, offset: ::off64_t, whence: ::c_int) -> ::c_int; pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int; pub fn fstat64(fildes: ::c_int, buf: *mut stat64) -> ::c_int; pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn fstatfs64(fd: ::c_int, buf: *mut statfs64) -> ::c_int; pub fn fstatvfs64(fd: ::c_int, buf: *mut statvfs64) -> ::c_int; pub fn ftello64(stream: *mut ::FILE) -> ::off64_t; pub fn ftok(path: *const ::c_char, id: ::c_int) -> ::key_t; pub fn ftruncate64(fd: ::c_int, length: off64_t) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::c_int) -> ::c_int; pub fn getdtablesize() -> ::c_int; pub fn getgrent() -> *mut ::group; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getgrset(user: *mut ::c_char) -> *mut ::c_char; pub fn gethostid() -> ::c_long; pub fn getmntent(stream: *mut ::FILE) -> *mut ::mntent; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::size_t, host: *mut ::c_char, hostlen: ::size_t, serv: *mut ::c_char, servlen: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn getpagesize() -> ::c_int; pub fn getpeereid(socket: ::c_int, euid: *mut ::uid_t, egid: *mut ::gid_t) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn getpwent() -> *mut ::passwd; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn getitimer(which: ::c_int, curr_value: *mut ::itimerval) -> ::c_int; pub fn getutent() -> *mut utmp; pub fn getutid(u: *const utmp) -> *mut utmp; pub fn getutline(u: *const utmp) -> *mut utmp; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn glob( pattern: *const ::c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn hasmntopt(mnt: *const ::mntent, opt: *const ::c_char) -> *mut ::c_char; pub fn hcreate(nelt: ::size_t) -> ::c_int; pub fn hdestroy(); pub fn hsearch(entry: entry, action: ::c_int) -> *mut entry; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn if_nameindex() -> *mut if_nameindex; pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; pub fn ioctl(fildes: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn jrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn lcong48(p: *mut ::c_ushort); pub fn lfind( key: *const ::c_void, base: *const ::c_void, nelp: *mut ::size_t, width: ::size_t, compar: ::Option ::c_int>, ) -> *mut ::c_void; pub fn lio_listio( mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent, ) -> ::c_int; pub fn loadquery(flags: ::c_int, buf: *mut ::c_char, buflen: ::c_uint) -> ::c_int; pub fn lpar_get_info(command: ::c_int, buf: *mut ::c_void, bufsize: ::size_t) -> ::c_int; pub fn lpar_set_resources(id: ::c_int, resource: *mut ::c_void) -> ::c_int; pub fn lrand48() -> c_long; pub fn lsearch( key: *const ::c_void, base: *mut ::c_void, nelp: *mut ::size_t, width: ::size_t, compar: ::Option ::c_int>, ) -> *mut ::c_void; pub fn lseek64(fd: ::c_int, offset: off64_t, whence: ::c_int) -> off64_t; pub fn lstat64(path: *const c_char, buf: *mut stat64) -> ::c_int; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn makecontext(ucp: *mut ::ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); pub fn mallinfo() -> ::mallinfo; pub fn mallopt(param: ::c_int, value: ::c_int) -> ::c_int; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; pub fn memset_s(s: *mut ::c_void, smax: ::size_t, c: ::c_int, n: ::size_t) -> ::c_int; pub fn mincore(addr: *const ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn mount(device: *const ::c_char, path: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) -> ::c_int; pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_send( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, abs_timeout: *const ::timespec, ) -> ::ssize_t; pub fn mq_timedsend( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; pub fn mrand48() -> c_long; pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn msgsnd( msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, msgflg: ::c_int, ) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn nl_langinfo_l(item: ::nl_item, loc: ::locale_t) -> *mut ::c_char; pub fn nrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn open64(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; pub fn pollset_create(maxfd: ::c_int) -> pollset_t; pub fn pollset_ctl( ps: pollset_t, pollctl_array: *mut poll_ctl, array_length: ::c_int, ) -> ::c_int; pub fn pollset_destroy(ps: pollset_t) -> ::c_int; pub fn pollset_poll( ps: pollset_t, polldata_array: *mut ::pollfd, array_length: ::c_int, timeout: ::c_int, ) -> ::c_int; pub fn pollset_query(ps: pollset_t, pollfd_query: *mut ::pollfd) -> ::c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn posix_fadvise64( fd: ::c_int, offset: ::off64_t, len: ::off64_t, advise: ::c_int, ) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn posix_fallocate64(fd: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, newfd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, ) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut sigset_t, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const ::sched_param, ) -> ::c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn pread64(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off64_t) -> ::ssize_t; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn ptrace64( request: ::c_int, id: ::c_longlong, addr: ::c_longlong, data: ::c_int, buff: *mut ::c_int, ) -> ::c_int; pub fn pututline(u: *const utmp) -> *mut utmp; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn pwrite64( fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off64_t, ) -> ::ssize_t; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; #[link_name = "__linux_quotactl"] pub fn quotactl( cmd: ::c_int, special: *const ::c_char, id: ::c_int, data: *mut ::c_char, ) -> ::c_int; pub fn rand() -> ::c_int; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, timeout: *mut ::timespec, ) -> ::c_int; pub fn recvmsg(sockfd: ::c_int, msg: *mut msghdr, flags: ::c_int) -> ::ssize_t; pub fn regcomp(preg: *mut regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regerror( errcode: ::c_int, preg: *const ::regex_t, errbuf: *mut ::c_char, errbuf_size: ::size_t, ) -> ::size_t; pub fn regexec( preg: *const regex_t, input: *const ::c_char, nmatch: ::size_t, pmatch: *mut regmatch_t, eflags: ::c_int, ) -> ::c_int; pub fn regfree(preg: *mut regex_t); pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; pub fn sched_getparam(pid: ::pid_t, param: *mut sched_param) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sctp_opt_info( sd: ::c_int, id: ::sctp_assoc_t, opt: ::c_int, arg_size: *mut ::c_void, size: *mut ::size_t, ) -> ::c_int; pub fn sctp_peeloff(s: ::c_int, id: ::sctp_assoc_t) -> ::c_int; pub fn seed48(xseed: *mut ::c_ushort) -> *mut ::c_ushort; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int; pub fn semop(semid: ::c_int, sops: *mut sembuf, nsops: ::size_t) -> ::c_int; pub fn send_file(socket: *mut ::c_int, iobuf: *mut sf_parms, flags: ::c_uint) -> ::ssize_t; pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut mmsghdr, vlen: ::c_uint, flags: ::c_int, ) -> ::c_int; pub fn sendmsg(sockfd: ::c_int, msg: *const msghdr, flags: ::c_int) -> ::ssize_t; pub fn setcontext(ucp: *const ucontext_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn setgrent(); pub fn sethostid(hostid: ::c_int) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn setmntent(filename: *const ::c_char, ty: *const ::c_char) -> *mut ::FILE; pub fn setpriority(which: ::c_int, who: id_t, priority: ::c_int) -> ::c_int; pub fn setpwent(); pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int; pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn setitimer( which: ::c_int, new_value: *const ::itimerval, old_value: *mut ::itimerval, ) -> ::c_int; pub fn setutent(); pub fn setutxent(); pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn shmget(key: key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn splice(socket1: ::c_int, socket2: ::c_int, flags: ::c_int) -> ::c_int; pub fn srand(seed: ::c_uint); pub fn srand48(seed: ::c_long); pub fn stat64(path: *const ::c_char, buf: *mut stat64) -> ::c_int; pub fn stat64at( dirfd: ::c_int, path: *const ::c_char, buf: *mut stat64, flags: ::c_int, ) -> ::c_int; pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; pub fn statfs64(path: *const ::c_char, buf: *mut statfs64) -> ::c_int; pub fn statvfs64(path: *const ::c_char, buf: *mut statvfs64) -> ::c_int; pub fn statx( path: *const ::c_char, buf: *mut stat, length: ::c_int, command: ::c_int, ) -> ::c_int; pub fn strcasecmp_l( string1: *const ::c_char, string2: *const ::c_char, locale: ::locale_t, ) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn strftime( arg1: *mut c_char, arg2: ::size_t, arg3: *const c_char, arg4: *const tm, ) -> ::size_t; pub fn strncasecmp_l( string1: *const ::c_char, string2: *const ::c_char, length: ::size_t, locale: ::locale_t, ) -> ::c_int; pub fn strptime(s: *const ::c_char, format: *const ::c_char, tm: *mut ::tm) -> *mut ::c_char; pub fn strsep(string: *mut *mut ::c_char, delim: *const ::c_char) -> *mut ::c_char; pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; pub fn swapoff(puath: *const ::c_char) -> ::c_int; pub fn swapon(path: *const ::c_char) -> ::c_int; pub fn sync(); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn timer_create( clockid: ::clockid_t, sevp: *mut ::sigevent, timerid: *mut ::timer_t, ) -> ::c_int; pub fn timer_delete(timerid: timer_t) -> ::c_int; pub fn timer_getoverrun(timerid: timer_t) -> ::c_int; pub fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> ::c_int; pub fn timer_settime( timerid: ::timer_t, flags: ::c_int, new_value: *const ::itimerspec, old_value: *mut ::itimerspec, ) -> ::c_int; pub fn truncate64(path: *const c_char, length: off64_t) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn updwtmp(file: *const ::c_char, u: *mut utmp); pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn utmpname(file: *const ::c_char) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn wait4( pid: ::pid_t, status: *mut ::c_int, options: ::c_int, rusage: *mut ::rusage, ) -> ::pid_t; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; // Use AIX thread-safe version errno. pub fn _Errno() -> *mut ::c_int; } cfg_if! { if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } } libc/src/unix/aix/powerpc64.rs0000644000175000017500000005452414661133735017216 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; s! { pub struct sigset_t { pub ss_set: [c_ulong; 4], } pub struct fd_set { pub fds_bits: [c_long; 1024], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_sysid: ::c_uint, pub l_pid: ::pid_t, pub l_vfs: ::c_int, pub l_start: ::off_t, pub l_len: ::off_t, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_basetype: [::c_char; 16], pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub f_fstr: [::c_char; 32], pub f_filler: [::c_ulong; 16] } pub struct pthread_rwlock_t { __rw_word: [::c_long; 10], } pub struct pthread_cond_t { __cv_word: [::c_long; 6], } pub struct pthread_mutex_t { __mt_word: [::c_long; 8], } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_flag: ::c_ushort, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_ssize: ::c_int, pub st_atime: ::st_timespec, pub st_mtime: ::st_timespec, pub st_ctime: ::st_timespec, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_vfstype: ::c_int, pub st_vfs: ::c_uint, pub st_type: ::c_uint, pub st_gen: ::c_uint, pub st_reserved: [::c_uint; 9], pub st_padto_ll: ::c_uint, pub st_size: ::off_t, } pub struct statfs { pub f_version: ::c_int, pub f_type: ::c_int, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsblkcnt_t, pub f_ffree: ::fsblkcnt_t, pub f_fsid: ::fsid64_t, pub f_vfstype: ::c_int, pub f_fsize: ::c_ulong, pub f_vfsnumber: ::c_int, pub f_vfsoff: ::c_int, pub f_vfslen: ::c_int, pub f_vfsvers: ::c_int, pub f_fname: [::c_char; 32], pub f_fpack: [::c_char; 32], pub f_name_max: ::c_int, } pub struct aiocb { pub aio_lio_opcode: ::c_int, pub aio_fildes: ::c_int, pub aio_word1: ::c_int, pub aio_offset: ::off_t, pub aio_buf: *mut ::c_void, pub aio_return: ::ssize_t, pub aio_errno: ::c_int, pub aio_nbytes: ::size_t, pub aio_reqprio: ::c_int, pub aio_sigevent: ::sigevent, pub aio_word2: ::c_int, pub aio_fp: ::c_int, pub aio_handle: *mut aiocb, pub aio_reserved: [::c_uint; 2], pub aio_sigev_tid: c_long, } pub struct ucontext_t { pub __sc_onstack: ::c_int, pub uc_sigmask: ::sigset_t, pub __sc_uerror: ::c_int, pub uc_mcontext: ::mcontext_t, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, // Should be pointer to __extctx_t pub __extctx: *mut ::c_void, pub __extctx_magic: ::c_int, pub __pad: [::c_int; 1], } pub struct mcontext_t { pub gpr: [::c_ulonglong; 32], pub msr: ::c_ulonglong, pub iar: ::c_ulonglong, pub lr: ::c_ulonglong, pub ctr: ::c_ulonglong, pub cr: ::c_uint, pub xer: ::c_uint, pub fpscr: ::c_uint, pub fpscrx: ::c_uint, pub except: [::c_ulonglong; 1], // Should be array of double type pub fpr: [::uint64_t; 32], pub fpeu: ::c_char, pub fpinfo: ::c_char, pub fpscr24_31: ::c_char, pub pad: [::c_char; 1], pub excp_type: ::c_int, } pub struct utmpx { pub ut_user: [::c_char; 256], pub ut_id: [::c_char; 14], pub ut_line: [::c_char; 64], pub ut_pid: ::pid_t, pub ut_type: ::c_short, pub ut_tv: ::timeval, pub ut_host: [::c_char; 256], pub __dbl_word_pad: ::c_int, pub __reservedA: [::c_int; 2], pub __reservedV: [::c_int; 6], } pub struct pthread_spinlock_t { pub __sp_word: [::c_long; 3], } pub struct pthread_barrier_t { pub __br_word: [::c_long; 5], } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_first: ::c_uint, pub msg_last: ::c_uint, pub msg_cbytes: ::c_uint, pub msg_qnum: ::c_uint, pub msg_qbytes: ::c_ulong, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, pub msg_rwait: ::c_int, pub msg_wwait: ::c_int, pub msg_reqevents: ::c_ushort, } } s_no_extra_traits! { pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub si_pid: ::pid_t, pub si_uid: ::uid_t, pub si_status: ::c_int, pub si_addr: *mut ::c_void, pub si_band: ::c_long, pub si_value: ::sigval, pub __si_flags: ::c_int, pub __pad: [::c_int; 3], } #[cfg(libc_union)] pub union _kernel_simple_lock { pub _slock: ::c_long, // Should be pointer to 'lock_data_instrumented' pub _slockp: *mut ::c_void, } pub struct fileops_t { pub fo_rw: extern fn(file: *mut file, rw: ::uio_rw, io: *mut ::c_void, ext: ::c_long, secattr: *mut ::c_void) -> ::c_int, pub fo_ioctl: extern fn(file: *mut file, a: ::c_long, b: ::caddr_t, c: ::c_long, d: ::c_long) -> ::c_int, pub fo_select: extern fn(file: *mut file, a: ::c_int, b: *mut ::c_ushort, c: extern fn()) -> ::c_int, pub fo_close: extern fn(file: *mut file) -> ::c_int, pub fo_fstat: extern fn(file: *mut file, sstat: *mut ::stat) -> ::c_int, } pub struct file { pub f_flag: ::c_long, pub f_count: ::c_int, pub f_options: ::c_short, pub f_type: ::c_short, // Should be pointer to 'vnode' pub f_data: *mut ::c_void, pub f_offset: ::c_longlong, pub f_dir_off: ::c_long, // Should be pointer to 'cred' pub f_cred: *mut ::c_void, #[cfg(libc_union)] pub f_lock: _kernel_simple_lock, #[cfg(libc_union)] pub f_offset_lock: _kernel_simple_lock, pub f_vinfo: ::caddr_t, pub f_ops: *mut fileops_t, pub f_parentp: ::caddr_t, pub f_fnamep: ::caddr_t, pub f_fdata: [::c_char; 160], } #[cfg(libc_union)] pub union __ld_info_file { pub _ldinfo_fd: ::c_int, pub _ldinfo_fp: *mut file, pub _core_offset: ::c_long, } pub struct ld_info { pub ldinfo_next: ::c_uint, pub ldinfo_flags: ::c_uint, #[cfg(libc_union)] pub _file: __ld_info_file, pub ldinfo_textorg: *mut ::c_void, pub ldinfo_textsize: ::c_ulong, pub ldinfo_dataorg: *mut ::c_void, pub ldinfo_datasize: ::c_ulong, pub ldinfo_filename: [::c_char; 2], } #[cfg(libc_union)] pub union __pollfd_ext_u { pub addr: *mut ::c_void, pub data32: u32, pub data: u64, } pub struct pollfd_ext { pub fd: ::c_int, pub events: ::c_ushort, pub revents: ::c_ushort, #[cfg(libc_union)] pub data: __pollfd_ext_u, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { self.si_addr } pub unsafe fn si_value(&self) -> ::sigval { self.si_value } pub unsafe fn si_pid(&self) -> ::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.si_status } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { #[cfg(libc_union)] let value_eq = self.si_value == other.si_value; #[cfg(not(libc_union))] let value_eq = true; self.si_signo == other.si_signo && self.si_errno == other.si_errno && self.si_code == other.si_code && self.si_pid == other.si_pid && self.si_uid == other.si_uid && self.si_status == other.si_status && self.si_addr == other.si_addr && self.si_band == other.si_band && self.__si_flags == other.__si_flags && value_eq } } impl Eq for siginfo_t {} impl ::fmt::Debug for siginfo_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("siginfo_t"); struct_formatter.field("si_signo", &self.si_signo); struct_formatter.field("si_errno", &self.si_errno); struct_formatter.field("si_code", &self.si_code); struct_formatter.field("si_pid", &self.si_pid); struct_formatter.field("si_uid", &self.si_uid); struct_formatter.field("si_status", &self.si_status); struct_formatter.field("si_addr", &self.si_addr); struct_formatter.field("si_band", &self.si_band); #[cfg(libc_union)] struct_formatter.field("si_value", &self.si_value); struct_formatter.field("__si_flags", &self.__si_flags); struct_formatter.finish() } } impl ::hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_errno.hash(state); self.si_code.hash(state); self.si_pid.hash(state); self.si_uid.hash(state); self.si_status.hash(state); self.si_addr.hash(state); self.si_band.hash(state); #[cfg(libc_union)] self.si_value.hash(state); self.__si_flags.hash(state); } } #[cfg(libc_union)] impl PartialEq for _kernel_simple_lock { fn eq(&self, other: &_kernel_simple_lock) -> bool { unsafe { self._slock == other._slock && self._slockp == other._slockp } } } #[cfg(libc_union)] impl Eq for _kernel_simple_lock {} #[cfg(libc_union)] impl ::fmt::Debug for _kernel_simple_lock { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("_kernel_simple_lock") .field("_slock", unsafe { &self._slock }) .field("_slockp", unsafe { &self._slockp }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for _kernel_simple_lock { fn hash(&self, state: &mut H) { unsafe { self._slock.hash(state); self._slockp.hash(state); } } } impl PartialEq for fileops_t { fn eq(&self, other: &fileops_t) -> bool { self.fo_rw == other.fo_rw && self.fo_ioctl == other.fo_ioctl && self.fo_select == other.fo_select && self.fo_close == other.fo_close && self.fo_fstat == other.fo_fstat } } impl Eq for fileops_t {} impl ::fmt::Debug for fileops_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("fileops_t"); struct_formatter.field("fo_rw", &self.fo_rw); struct_formatter.field("fo_ioctl", &self.fo_ioctl); struct_formatter.field("fo_select", &self.fo_select); struct_formatter.field("fo_close", &self.fo_close); struct_formatter.field("fo_fstat", &self.fo_fstat); struct_formatter.finish() } } impl ::hash::Hash for fileops_t { fn hash(&self, state: &mut H) { self.fo_rw.hash(state); self.fo_ioctl.hash(state); self.fo_select.hash(state); self.fo_close.hash(state); self.fo_fstat.hash(state); } } impl PartialEq for file { fn eq(&self, other: &file) -> bool { #[cfg(libc_union)] let lock_eq = self.f_lock == other.f_lock && self.f_offset_lock == other.f_offset_lock; #[cfg(not(libc_union))] let lock_eq = true; self.f_flag == other.f_flag && self.f_count == other.f_count && self.f_options == other.f_options && self.f_type == other.f_type && self.f_data == other.f_data && self.f_offset == other.f_offset && self.f_dir_off == other.f_dir_off && self.f_cred == other.f_cred && self.f_vinfo == other.f_vinfo && self.f_ops == other.f_ops && self.f_parentp == other.f_parentp && self.f_fnamep == other.f_fnamep && self.f_fdata == other.f_fdata && lock_eq } } impl Eq for file {} impl ::fmt::Debug for file { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("file"); struct_formatter.field("f_flag", &self.f_flag); struct_formatter.field("f_count", &self.f_count); struct_formatter.field("f_options", &self.f_options); struct_formatter.field("f_type", &self.f_type); struct_formatter.field("f_data", &self.f_data); struct_formatter.field("f_offset", &self.f_offset); struct_formatter.field("f_dir_off", &self.f_dir_off); struct_formatter.field("f_cred", &self.f_cred); #[cfg(libc_union)] struct_formatter.field("f_lock", &self.f_lock); #[cfg(libc_union)] struct_formatter.field("f_offset_lock", &self.f_offset_lock); struct_formatter.field("f_vinfo", &self.f_vinfo); struct_formatter.field("f_ops", &self.f_ops); struct_formatter.field("f_parentp", &self.f_parentp); struct_formatter.field("f_fnamep", &self.f_fnamep); struct_formatter.field("f_fdata", &self.f_fdata); struct_formatter.finish() } } impl ::hash::Hash for file { fn hash(&self, state: &mut H) { self.f_flag.hash(state); self.f_count.hash(state); self.f_options.hash(state); self.f_type.hash(state); self.f_data.hash(state); self.f_offset.hash(state); self.f_dir_off.hash(state); self.f_cred.hash(state); #[cfg(libc_union)] self.f_lock.hash(state); #[cfg(libc_union)] self.f_offset_lock.hash(state); self.f_vinfo.hash(state); self.f_ops.hash(state); self.f_parentp.hash(state); self.f_fnamep.hash(state); self.f_fdata.hash(state); } } #[cfg(libc_union)] impl PartialEq for __ld_info_file { fn eq(&self, other: &__ld_info_file) -> bool { unsafe { self._ldinfo_fd == other._ldinfo_fd && self._ldinfo_fp == other._ldinfo_fp && self._core_offset == other._core_offset } } } #[cfg(libc_union)] impl Eq for __ld_info_file {} #[cfg(libc_union)] impl ::fmt::Debug for __ld_info_file { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__ld_info_file") .field("_ldinfo_fd", unsafe { &self._ldinfo_fd }) .field("_ldinfo_fp", unsafe { &self._ldinfo_fp }) .field("_core_offset", unsafe { &self._core_offset }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __ld_info_file { fn hash(&self, state: &mut H) { unsafe { self._ldinfo_fd.hash(state); self._ldinfo_fp.hash(state); self._core_offset.hash(state); } } } impl PartialEq for ld_info { fn eq(&self, other: &ld_info) -> bool { #[cfg(libc_union)] let file_eq = self._file == other._file; #[cfg(not(libc_union))] let file_eq = true; self.ldinfo_next == other.ldinfo_next && self.ldinfo_flags == other.ldinfo_flags && self.ldinfo_textorg == other.ldinfo_textorg && self.ldinfo_textsize == other.ldinfo_textsize && self.ldinfo_dataorg == other.ldinfo_dataorg && self.ldinfo_datasize == other.ldinfo_datasize && self.ldinfo_filename == other.ldinfo_filename && file_eq } } impl Eq for ld_info {} impl ::fmt::Debug for ld_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("ld_info"); struct_formatter.field("ldinfo_next", &self.ldinfo_next); struct_formatter.field("ldinfo_flags", &self.ldinfo_flags); struct_formatter.field("ldinfo_textorg", &self.ldinfo_textorg); struct_formatter.field("ldinfo_textsize", &self.ldinfo_textsize); struct_formatter.field("ldinfo_dataorg", &self.ldinfo_dataorg); struct_formatter.field("ldinfo_datasize", &self.ldinfo_datasize); struct_formatter.field("ldinfo_filename", &self.ldinfo_filename); #[cfg(libc_union)] struct_formatter.field("_file", &self._file); struct_formatter.finish() } } impl ::hash::Hash for ld_info { fn hash(&self, state: &mut H) { self.ldinfo_next.hash(state); self.ldinfo_flags.hash(state); self.ldinfo_textorg.hash(state); self.ldinfo_textsize.hash(state); self.ldinfo_dataorg.hash(state); self.ldinfo_datasize.hash(state); self.ldinfo_filename.hash(state); #[cfg(libc_union)] self._file.hash(state); } } #[cfg(libc_union)] impl PartialEq for __pollfd_ext_u { fn eq(&self, other: &__pollfd_ext_u) -> bool { unsafe { self.addr == other.addr && self.data32 == other.data32 && self.data == other.data } } } #[cfg(libc_union)] impl Eq for __pollfd_ext_u {} #[cfg(libc_union)] impl ::fmt::Debug for __pollfd_ext_u { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__pollfd_ext_u") .field("addr", unsafe { &self.addr }) .field("data32", unsafe { &self.data32 }) .field("data", unsafe { &self.data }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __pollfd_ext_u { fn hash(&self, state: &mut H) { unsafe { self.addr.hash(state); self.data.hash(state); self.data32.hash(state); } } } impl PartialEq for pollfd_ext { fn eq(&self, other: &pollfd_ext) -> bool { #[cfg(libc_union)] let data_eq = self.data == other.data; #[cfg(not(libc_union))] let data_eq = true; self.fd == other.fd && self.events == other.events && self.revents == other.revents && data_eq } } impl Eq for pollfd_ext {} impl ::fmt::Debug for pollfd_ext { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("pollfd_ext"); struct_formatter.field("fd", &self.fd); struct_formatter.field("events", &self.events); struct_formatter.field("revents", &self.revents); #[cfg(libc_union)] struct_formatter.field("data", &self.data); struct_formatter.finish() } } impl ::hash::Hash for pollfd_ext { fn hash(&self, state: &mut H) { self.fd.hash(state); self.events.hash(state); self.revents.hash(state); #[cfg(libc_union)] self.data.hash(state); } } } } pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __mt_word: [0, 2, 0, 0, 0, 0, 0, 0], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __cv_word: [0, 0, 0, 0, 2, 0], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __rw_word: [2, 0, 0, 0, 0, 0, 0, 0, 0, 0], }; pub const RLIM_INFINITY: ::c_ulong = 0x7fffffffffffffff; extern "C" { pub fn getsystemcfg(label: ::c_int) -> ::c_ulong; } libc/src/unix/linux_like/0000775000175000017500000000000014661133735016371 5ustar jamespagejamespagelibc/src/unix/linux_like/emscripten/0000775000175000017500000000000014661133735020542 5ustar jamespagejamespagelibc/src/unix/linux_like/emscripten/lfs64.rs0000644000175000017500000001211114661133735022040 0ustar jamespagejamespage// In-sync with ../linux/musl/lfs64.rs except for fallocate64, prlimit64 and sendfile64 #[inline] pub unsafe extern "C" fn creat64(path: *const ::c_char, mode: ::mode_t) -> ::c_int { ::creat(path, mode) } #[inline] pub unsafe extern "C" fn fgetpos64(stream: *mut ::FILE, pos: *mut ::fpos64_t) -> ::c_int { ::fgetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fopen64(pathname: *const ::c_char, mode: *const ::c_char) -> *mut ::FILE { ::fopen(pathname, mode) } #[inline] pub unsafe extern "C" fn freopen64( pathname: *const ::c_char, mode: *const ::c_char, stream: *mut ::FILE, ) -> *mut ::FILE { ::freopen(pathname, mode, stream) } #[inline] pub unsafe extern "C" fn fseeko64( stream: *mut ::FILE, offset: ::off64_t, whence: ::c_int, ) -> ::c_int { ::fseeko(stream, offset, whence) } #[inline] pub unsafe extern "C" fn fsetpos64(stream: *mut ::FILE, pos: *const ::fpos64_t) -> ::c_int { ::fsetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fstat64(fildes: ::c_int, buf: *mut ::stat64) -> ::c_int { ::fstat(fildes, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatat64( fd: ::c_int, path: *const ::c_char, buf: *mut ::stat64, flag: ::c_int, ) -> ::c_int { ::fstatat(fd, path, buf as *mut _, flag) } #[inline] pub unsafe extern "C" fn fstatfs64(fd: ::c_int, buf: *mut ::statfs64) -> ::c_int { ::fstatfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatvfs64(fd: ::c_int, buf: *mut ::statvfs64) -> ::c_int { ::fstatvfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn ftello64(stream: *mut ::FILE) -> ::off64_t { ::ftello(stream) } #[inline] pub unsafe extern "C" fn ftruncate64(fd: ::c_int, length: ::off64_t) -> ::c_int { ::ftruncate(fd, length) } #[inline] pub unsafe extern "C" fn getrlimit64(resource: ::c_int, rlim: *mut ::rlimit64) -> ::c_int { ::getrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn lseek64(fd: ::c_int, offset: ::off64_t, whence: ::c_int) -> ::off64_t { ::lseek(fd, offset, whence) } #[inline] pub unsafe extern "C" fn lstat64(path: *const ::c_char, buf: *mut ::stat64) -> ::c_int { ::lstat(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn mmap64( addr: *mut ::c_void, length: ::size_t, prot: ::c_int, flags: ::c_int, fd: ::c_int, offset: ::off64_t, ) -> *mut ::c_void { ::mmap(addr, length, prot, flags, fd, offset) } // These functions are variadic in the C ABI since the `mode` argument is "optional". Variadic // `extern "C"` functions are unstable in Rust so we cannot write a shim function for these // entrypoints. See https://github.com/rust-lang/rust/issues/44930. // // These aliases are mostly fine though, neither function takes a LFS64-namespaced type as an // argument, nor do their names clash with any declared types. pub use open as open64; pub use openat as openat64; #[inline] pub unsafe extern "C" fn posix_fadvise64( fd: ::c_int, offset: ::off64_t, len: ::off64_t, advice: ::c_int, ) -> ::c_int { ::posix_fadvise(fd, offset, len, advice) } #[inline] pub unsafe extern "C" fn posix_fallocate64( fd: ::c_int, offset: ::off64_t, len: ::off64_t, ) -> ::c_int { ::posix_fallocate(fd, offset, len) } #[inline] pub unsafe extern "C" fn pread64( fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: ::off64_t, ) -> ::ssize_t { ::pread(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn preadv64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t { ::preadv(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn pwrite64( fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: ::off64_t, ) -> ::ssize_t { ::pwrite(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn pwritev64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t { ::pwritev(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64 { ::readdir(dirp) as *mut _ } #[inline] pub unsafe extern "C" fn readdir64_r( dirp: *mut ::DIR, entry: *mut ::dirent64, result: *mut *mut ::dirent64, ) -> ::c_int { ::readdir_r(dirp, entry as *mut _, result as *mut _) } #[inline] pub unsafe extern "C" fn setrlimit64(resource: ::c_int, rlim: *const ::rlimit64) -> ::c_int { ::setrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn stat64(pathname: *const ::c_char, statbuf: *mut ::stat64) -> ::c_int { ::stat(pathname, statbuf as *mut _) } #[inline] pub unsafe extern "C" fn statfs64(pathname: *const ::c_char, buf: *mut ::statfs64) -> ::c_int { ::statfs(pathname, buf as *mut _) } #[inline] pub unsafe extern "C" fn statvfs64(path: *const ::c_char, buf: *mut ::statvfs64) -> ::c_int { ::statvfs(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn tmpfile64() -> *mut ::FILE { ::tmpfile() } #[inline] pub unsafe extern "C" fn truncate64(path: *const ::c_char, length: ::off64_t) -> ::c_int { ::truncate(path, length) } libc/src/unix/linux_like/emscripten/mod.rs0000644000175000017500000016360014661133735021673 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type useconds_t = u32; pub type dev_t = u32; pub type socklen_t = u32; pub type pthread_t = c_ulong; pub type mode_t = u32; pub type shmatt_t = ::c_ulong; pub type mqd_t = ::c_int; pub type msgqnum_t = ::c_ulong; pub type msglen_t = ::c_ulong; pub type nfds_t = ::c_ulong; pub type nl_item = ::c_int; pub type idtype_t = ::c_uint; pub type loff_t = i64; pub type pthread_key_t = ::c_uint; pub type clock_t = c_long; pub type time_t = c_long; pub type suseconds_t = c_long; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i32; pub type blksize_t = c_long; pub type fsblkcnt_t = u32; pub type fsfilcnt_t = u32; pub type rlim_t = u64; pub type c_long = i32; pub type c_ulong = u32; pub type nlink_t = u32; pub type ino64_t = ::ino_t; pub type off64_t = ::off_t; pub type blkcnt64_t = ::blkcnt_t; pub type rlim64_t = ::rlim_t; pub type rlimit64 = ::rlimit; pub type flock64 = ::flock; pub type stat64 = ::stat; pub type statfs64 = ::statfs; pub type statvfs64 = ::statvfs; pub type dirent64 = ::dirent; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME: fill this out with a struct impl ::Copy for fpos64_t {} impl ::Clone for fpos64_t { fn clone(&self) -> fpos64_t { *self } } s! { pub struct glob_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct spwd { pub sp_namp: *mut ::c_char, pub sp_pwdp: *mut ::c_char, pub sp_lstchg: ::c_long, pub sp_min: ::c_long, pub sp_max: ::c_long, pub sp_warn: ::c_long, pub sp_inact: ::c_long, pub sp_expire: ::c_long, pub sp_flag: ::c_ulong, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct dqblk { pub dqb_bhardlimit: u64, pub dqb_bsoftlimit: u64, pub dqb_curspace: u64, pub dqb_ihardlimit: u64, pub dqb_isoftlimit: u64, pub dqb_curinodes: u64, pub dqb_btime: u64, pub dqb_itime: u64, pub dqb_valid: u32, } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: u64, pub ssi_utime: u64, pub ssi_stime: u64, pub ssi_addr: u64, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct fsid_t { __val: [::c_int; 2], } pub struct cpu_set_t { bits: [u32; 32], } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } // System V IPC pub struct msginfo { pub msgpool: ::c_int, pub msgmap: ::c_int, pub msgmax: ::c_int, pub msgmnb: ::c_int, pub msgmni: ::c_int, pub msgssz: ::c_int, pub msgtql: ::c_int, pub msgseg: ::c_ushort, } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct aiocb { pub aio_fildes: ::c_int, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_sigevent: ::sigevent, __td: *mut ::c_void, __lock: [::c_int; 2], __err: ::c_int, __ret: ::ssize_t, pub aio_offset: off_t, __next: *mut ::c_void, __prev: *mut ::c_void, __dummy4: [::c_char; 24], } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __unused1: ::c_long, __unused2: ::c_long } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], pub __c_ispeed: ::speed_t, pub __c_ospeed: ::speed_t, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct pthread_attr_t { __size: [u32; 11] } pub struct sigset_t { __val: [::c_ulong; 32], } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct sem_t { __val: [::c_int; 4], } pub struct stat { pub st_dev: ::dev_t, #[cfg(not(emscripten_new_stat_abi))] __st_dev_padding: ::c_int, #[cfg(not(emscripten_new_stat_abi))] __st_ino_truncated: ::c_long, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, #[cfg(not(emscripten_new_stat_abi))] __st_rdev_padding: ::c_int, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino_t, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_int, pub shm_dtime: ::time_t, __unused2: ::c_int, pub shm_ctime: ::time_t, __unused3: ::c_int, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __unused1: ::c_int, pub msg_rtime: ::time_t, __unused2: ::c_int, pub msg_ctime: ::time_t, __unused3: ::c_int, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct arpd_request { pub req: ::c_ushort, pub ip: u32, pub dev: ::c_ulong, pub stamp: ::c_ulong, pub updated: ::c_ulong, pub ha: [::c_uchar; ::MAX_ADDR_LEN], } } s_no_extra_traits! { pub struct dirent { pub d_ino: ::ino_t, pub d_off: ::off_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } pub struct sysinfo { pub uptime: ::c_ulong, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub __reserved: [::c_char; 256], } pub struct mq_attr { pub mq_flags: ::c_long, pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, pad: [::c_long; 4] } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for sysinfo { fn eq(&self, other: &sysinfo) -> bool { self.uptime == other.uptime && self.loads == other.loads && self.totalram == other.totalram && self.freeram == other.freeram && self.sharedram == other.sharedram && self.bufferram == other.bufferram && self.totalswap == other.totalswap && self.freeswap == other.freeswap && self.procs == other.procs && self.pad == other.pad && self.totalhigh == other.totalhigh && self.freehigh == other.freehigh && self.mem_unit == other.mem_unit && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a,b)| a == b) } } impl Eq for sysinfo {} impl ::fmt::Debug for sysinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sysinfo") .field("uptime", &self.uptime) .field("loads", &self.loads) .field("totalram", &self.totalram) .field("freeram", &self.freeram) .field("sharedram", &self.sharedram) .field("bufferram", &self.bufferram) .field("totalswap", &self.totalswap) .field("freeswap", &self.freeswap) .field("procs", &self.procs) .field("pad", &self.pad) .field("totalhigh", &self.totalhigh) .field("freehigh", &self.freehigh) .field("mem_unit", &self.mem_unit) // FIXME: .field("__reserved", &self.__reserved) .finish() } } impl ::hash::Hash for sysinfo { fn hash(&self, state: &mut H) { self.uptime.hash(state); self.loads.hash(state); self.totalram.hash(state); self.freeram.hash(state); self.sharedram.hash(state); self.bufferram.hash(state); self.totalswap.hash(state); self.freeswap.hash(state); self.procs.hash(state); self.pad.hash(state); self.totalhigh.hash(state); self.freehigh.hash(state); self.mem_unit.hash(state); self.__reserved.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl ::fmt::Debug for mq_attr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl ::hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } } } pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MS_NOUSER: ::c_ulong = 0x80000000; pub const MS_RMT_MASK: ::c_ulong = 0x02800051; pub const ABDAY_1: ::nl_item = 0x20000; pub const ABDAY_2: ::nl_item = 0x20001; pub const ABDAY_3: ::nl_item = 0x20002; pub const ABDAY_4: ::nl_item = 0x20003; pub const ABDAY_5: ::nl_item = 0x20004; pub const ABDAY_6: ::nl_item = 0x20005; pub const ABDAY_7: ::nl_item = 0x20006; pub const DAY_1: ::nl_item = 0x20007; pub const DAY_2: ::nl_item = 0x20008; pub const DAY_3: ::nl_item = 0x20009; pub const DAY_4: ::nl_item = 0x2000A; pub const DAY_5: ::nl_item = 0x2000B; pub const DAY_6: ::nl_item = 0x2000C; pub const DAY_7: ::nl_item = 0x2000D; pub const ABMON_1: ::nl_item = 0x2000E; pub const ABMON_2: ::nl_item = 0x2000F; pub const ABMON_3: ::nl_item = 0x20010; pub const ABMON_4: ::nl_item = 0x20011; pub const ABMON_5: ::nl_item = 0x20012; pub const ABMON_6: ::nl_item = 0x20013; pub const ABMON_7: ::nl_item = 0x20014; pub const ABMON_8: ::nl_item = 0x20015; pub const ABMON_9: ::nl_item = 0x20016; pub const ABMON_10: ::nl_item = 0x20017; pub const ABMON_11: ::nl_item = 0x20018; pub const ABMON_12: ::nl_item = 0x20019; pub const MON_1: ::nl_item = 0x2001A; pub const MON_2: ::nl_item = 0x2001B; pub const MON_3: ::nl_item = 0x2001C; pub const MON_4: ::nl_item = 0x2001D; pub const MON_5: ::nl_item = 0x2001E; pub const MON_6: ::nl_item = 0x2001F; pub const MON_7: ::nl_item = 0x20020; pub const MON_8: ::nl_item = 0x20021; pub const MON_9: ::nl_item = 0x20022; pub const MON_10: ::nl_item = 0x20023; pub const MON_11: ::nl_item = 0x20024; pub const MON_12: ::nl_item = 0x20025; pub const AM_STR: ::nl_item = 0x20026; pub const PM_STR: ::nl_item = 0x20027; pub const D_T_FMT: ::nl_item = 0x20028; pub const D_FMT: ::nl_item = 0x20029; pub const T_FMT: ::nl_item = 0x2002A; pub const T_FMT_AMPM: ::nl_item = 0x2002B; pub const ERA: ::nl_item = 0x2002C; pub const ERA_D_FMT: ::nl_item = 0x2002E; pub const ALT_DIGITS: ::nl_item = 0x2002F; pub const ERA_D_T_FMT: ::nl_item = 0x20030; pub const ERA_T_FMT: ::nl_item = 0x20031; pub const CODESET: ::nl_item = 14; pub const CRNCYSTR: ::nl_item = 0x4000F; pub const RUSAGE_THREAD: ::c_int = 1; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const RADIXCHAR: ::nl_item = 0x10000; pub const THOUSEP: ::nl_item = 0x10001; pub const YESEXPR: ::nl_item = 0x50000; pub const NOEXPR: ::nl_item = 0x50001; pub const YESSTR: ::nl_item = 0x50002; pub const NOSTR: ::nl_item = 0x50003; pub const FILENAME_MAX: ::c_uint = 4096; pub const L_tmpnam: ::c_uint = 20; pub const _PC_LINK_MAX: ::c_int = 0; pub const _PC_MAX_CANON: ::c_int = 1; pub const _PC_MAX_INPUT: ::c_int = 2; pub const _PC_NAME_MAX: ::c_int = 3; pub const _PC_PATH_MAX: ::c_int = 4; pub const _PC_PIPE_BUF: ::c_int = 5; pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_SYNC_IO: ::c_int = 9; pub const _PC_ASYNC_IO: ::c_int = 10; pub const _PC_PRIO_IO: ::c_int = 11; pub const _PC_SOCK_MAXBUF: ::c_int = 12; pub const _PC_FILESIZEBITS: ::c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; pub const _PC_REC_XFER_ALIGN: ::c_int = 17; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18; pub const _PC_SYMLINK_MAX: ::c_int = 19; pub const _PC_2_SYMLINKS: ::c_int = 20; pub const _SC_ARG_MAX: ::c_int = 0; pub const _SC_CHILD_MAX: ::c_int = 1; pub const _SC_CLK_TCK: ::c_int = 2; pub const _SC_NGROUPS_MAX: ::c_int = 3; pub const _SC_OPEN_MAX: ::c_int = 4; pub const _SC_STREAM_MAX: ::c_int = 5; pub const _SC_TZNAME_MAX: ::c_int = 6; pub const _SC_JOB_CONTROL: ::c_int = 7; pub const _SC_SAVED_IDS: ::c_int = 8; pub const _SC_REALTIME_SIGNALS: ::c_int = 9; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 10; pub const _SC_TIMERS: ::c_int = 11; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 12; pub const _SC_PRIORITIZED_IO: ::c_int = 13; pub const _SC_SYNCHRONIZED_IO: ::c_int = 14; pub const _SC_FSYNC: ::c_int = 15; pub const _SC_MAPPED_FILES: ::c_int = 16; pub const _SC_MEMLOCK: ::c_int = 17; pub const _SC_MEMLOCK_RANGE: ::c_int = 18; pub const _SC_MEMORY_PROTECTION: ::c_int = 19; pub const _SC_MESSAGE_PASSING: ::c_int = 20; pub const _SC_SEMAPHORES: ::c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 22; pub const _SC_AIO_LISTIO_MAX: ::c_int = 23; pub const _SC_AIO_MAX: ::c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 25; pub const _SC_DELAYTIMER_MAX: ::c_int = 26; pub const _SC_MQ_OPEN_MAX: ::c_int = 27; pub const _SC_MQ_PRIO_MAX: ::c_int = 28; pub const _SC_VERSION: ::c_int = 29; pub const _SC_PAGESIZE: ::c_int = 30; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: ::c_int = 31; pub const _SC_SEM_NSEMS_MAX: ::c_int = 32; pub const _SC_SEM_VALUE_MAX: ::c_int = 33; pub const _SC_SIGQUEUE_MAX: ::c_int = 34; pub const _SC_TIMER_MAX: ::c_int = 35; pub const _SC_BC_BASE_MAX: ::c_int = 36; pub const _SC_BC_DIM_MAX: ::c_int = 37; pub const _SC_BC_SCALE_MAX: ::c_int = 38; pub const _SC_BC_STRING_MAX: ::c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 40; pub const _SC_EXPR_NEST_MAX: ::c_int = 42; pub const _SC_LINE_MAX: ::c_int = 43; pub const _SC_RE_DUP_MAX: ::c_int = 44; pub const _SC_2_VERSION: ::c_int = 46; pub const _SC_2_C_BIND: ::c_int = 47; pub const _SC_2_C_DEV: ::c_int = 48; pub const _SC_2_FORT_DEV: ::c_int = 49; pub const _SC_2_FORT_RUN: ::c_int = 50; pub const _SC_2_SW_DEV: ::c_int = 51; pub const _SC_2_LOCALEDEF: ::c_int = 52; pub const _SC_UIO_MAXIOV: ::c_int = 60; pub const _SC_IOV_MAX: ::c_int = 60; pub const _SC_THREADS: ::c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 70; pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; pub const _SC_TTY_NAME_MAX: ::c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 73; pub const _SC_THREAD_KEYS_MAX: ::c_int = 74; pub const _SC_THREAD_STACK_MIN: ::c_int = 75; pub const _SC_THREAD_THREADS_MAX: ::c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 82; pub const _SC_NPROCESSORS_CONF: ::c_int = 83; pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; pub const _SC_PHYS_PAGES: ::c_int = 85; pub const _SC_AVPHYS_PAGES: ::c_int = 86; pub const _SC_ATEXIT_MAX: ::c_int = 87; pub const _SC_PASS_MAX: ::c_int = 88; pub const _SC_XOPEN_VERSION: ::c_int = 89; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90; pub const _SC_XOPEN_UNIX: ::c_int = 91; pub const _SC_XOPEN_CRYPT: ::c_int = 92; pub const _SC_XOPEN_ENH_I18N: ::c_int = 93; pub const _SC_XOPEN_SHM: ::c_int = 94; pub const _SC_2_CHAR_TERM: ::c_int = 95; pub const _SC_2_UPE: ::c_int = 97; pub const _SC_XOPEN_XPG2: ::c_int = 98; pub const _SC_XOPEN_XPG3: ::c_int = 99; pub const _SC_XOPEN_XPG4: ::c_int = 100; pub const _SC_NZERO: ::c_int = 109; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126; pub const _SC_XBS5_LP64_OFF64: ::c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128; pub const _SC_XOPEN_LEGACY: ::c_int = 129; pub const _SC_XOPEN_REALTIME: ::c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131; pub const _SC_ADVISORY_INFO: ::c_int = 132; pub const _SC_BARRIERS: ::c_int = 133; pub const _SC_CLOCK_SELECTION: ::c_int = 137; pub const _SC_CPUTIME: ::c_int = 138; pub const _SC_THREAD_CPUTIME: ::c_int = 139; pub const _SC_MONOTONIC_CLOCK: ::c_int = 149; pub const _SC_READER_WRITER_LOCKS: ::c_int = 153; pub const _SC_SPIN_LOCKS: ::c_int = 154; pub const _SC_REGEXP: ::c_int = 155; pub const _SC_SHELL: ::c_int = 157; pub const _SC_SPAWN: ::c_int = 159; pub const _SC_SPORADIC_SERVER: ::c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 161; pub const _SC_TIMEOUTS: ::c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 165; pub const _SC_2_PBS: ::c_int = 168; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 169; pub const _SC_2_PBS_LOCATE: ::c_int = 170; pub const _SC_2_PBS_MESSAGE: ::c_int = 171; pub const _SC_2_PBS_TRACK: ::c_int = 172; pub const _SC_SYMLOOP_MAX: ::c_int = 173; pub const _SC_STREAMS: ::c_int = 174; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 175; pub const _SC_V6_ILP32_OFF32: ::c_int = 176; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 177; pub const _SC_V6_LP64_OFF64: ::c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 179; pub const _SC_HOST_NAME_MAX: ::c_int = 180; pub const _SC_TRACE: ::c_int = 181; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 182; pub const _SC_TRACE_INHERIT: ::c_int = 183; pub const _SC_TRACE_LOG: ::c_int = 184; pub const _SC_IPV6: ::c_int = 235; pub const _SC_RAW_SOCKETS: ::c_int = 236; pub const _SC_V7_ILP32_OFF32: ::c_int = 237; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 238; pub const _SC_V7_LP64_OFF64: ::c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 240; pub const _SC_SS_REPL_MAX: ::c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 242; pub const _SC_TRACE_NAME_MAX: ::c_int = 243; pub const _SC_TRACE_SYS_MAX: ::c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 245; pub const _SC_XOPEN_STREAMS: ::c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248; pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; pub const GLOB_ERR: ::c_int = 1 << 0; pub const GLOB_MARK: ::c_int = 1 << 1; pub const GLOB_NOSORT: ::c_int = 1 << 2; pub const GLOB_DOOFFS: ::c_int = 1 << 3; pub const GLOB_NOCHECK: ::c_int = 1 << 4; pub const GLOB_APPEND: ::c_int = 1 << 5; pub const GLOB_NOESCAPE: ::c_int = 1 << 6; pub const GLOB_NOSPACE: ::c_int = 1; pub const GLOB_ABORTED: ::c_int = 2; pub const GLOB_NOMATCH: ::c_int = 3; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; pub const S_IREAD: mode_t = 256; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const ST_RDONLY: ::c_ulong = 1; pub const ST_NOSUID: ::c_ulong = 2; pub const ST_NODEV: ::c_ulong = 4; pub const ST_NOEXEC: ::c_ulong = 8; pub const ST_SYNCHRONOUS: ::c_ulong = 16; pub const ST_MANDLOCK: ::c_ulong = 64; pub const ST_WRITE: ::c_ulong = 128; pub const ST_APPEND: ::c_ulong = 256; pub const ST_IMMUTABLE: ::c_ulong = 512; pub const ST_NOATIME: ::c_ulong = 1024; pub const ST_NODIRATIME: ::c_ulong = 2048; pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void; pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; pub const RTLD_NODELETE: ::c_int = 0x1000; pub const RTLD_NOW: ::c_int = 0x2; align_const! { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [0; __SIZEOF_PTHREAD_RWLOCK_T], }; } pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const SCHED_BATCH: ::c_int = 3; pub const SCHED_IDLE: ::c_int = 5; pub const AF_IB: ::c_int = 27; pub const AF_MPLS: ::c_int = 28; pub const AF_NFC: ::c_int = 39; pub const AF_VSOCK: ::c_int = 40; pub const PF_IB: ::c_int = AF_IB; pub const PF_MPLS: ::c_int = AF_MPLS; pub const PF_NFC: ::c_int = AF_NFC; pub const PF_VSOCK: ::c_int = AF_VSOCK; // System V IPC pub const IPC_PRIVATE: ::key_t = 0; pub const IPC_CREAT: ::c_int = 0o1000; pub const IPC_EXCL: ::c_int = 0o2000; pub const IPC_NOWAIT: ::c_int = 0o4000; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const IPC_INFO: ::c_int = 3; pub const MSG_STAT: ::c_int = 11; pub const MSG_INFO: ::c_int = 12; pub const MSG_NOERROR: ::c_int = 0o10000; pub const MSG_EXCEPT: ::c_int = 0o20000; pub const SHM_R: ::c_int = 0o400; pub const SHM_W: ::c_int = 0o200; pub const SHM_RDONLY: ::c_int = 0o10000; pub const SHM_RND: ::c_int = 0o20000; pub const SHM_REMAP: ::c_int = 0o40000; pub const SHM_EXEC: ::c_int = 0o100000; pub const SHM_LOCK: ::c_int = 11; pub const SHM_UNLOCK: ::c_int = 12; pub const SHM_HUGETLB: ::c_int = 0o4000; pub const SHM_NORESERVE: ::c_int = 0o10000; pub const QFMT_VFS_OLD: ::c_int = 1; pub const QFMT_VFS_V0: ::c_int = 2; pub const EFD_SEMAPHORE: ::c_int = 0x1; pub const LOG_NFACILITIES: ::c_int = 24; pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t; pub const RB_AUTOBOOT: ::c_int = 0x01234567u32 as i32; pub const RB_HALT_SYSTEM: ::c_int = 0xcdef0123u32 as i32; pub const RB_ENABLE_CAD: ::c_int = 0x89abcdefu32 as i32; pub const RB_DISABLE_CAD: ::c_int = 0x00000000u32 as i32; pub const RB_POWER_OFF: ::c_int = 0x4321fedcu32 as i32; pub const RB_SW_SUSPEND: ::c_int = 0xd000fce2u32 as i32; pub const RB_KEXEC: ::c_int = 0x45584543u32 as i32; pub const AI_PASSIVE: ::c_int = 0x0001; pub const AI_CANONNAME: ::c_int = 0x0002; pub const AI_NUMERICHOST: ::c_int = 0x0004; pub const AI_V4MAPPED: ::c_int = 0x0008; pub const AI_ALL: ::c_int = 0x0010; pub const AI_ADDRCONFIG: ::c_int = 0x0020; pub const AI_NUMERICSERV: ::c_int = 0x0400; pub const EAI_BADFLAGS: ::c_int = -1; pub const EAI_NONAME: ::c_int = -2; pub const EAI_AGAIN: ::c_int = -3; pub const EAI_FAIL: ::c_int = -4; pub const EAI_FAMILY: ::c_int = -6; pub const EAI_SOCKTYPE: ::c_int = -7; pub const EAI_SERVICE: ::c_int = -8; pub const EAI_MEMORY: ::c_int = -10; pub const EAI_OVERFLOW: ::c_int = -12; pub const NI_NUMERICHOST: ::c_int = 1; pub const NI_NUMERICSERV: ::c_int = 2; pub const NI_NOFQDN: ::c_int = 4; pub const NI_NAMEREQD: ::c_int = 8; pub const NI_DGRAM: ::c_int = 16; pub const SYNC_FILE_RANGE_WAIT_BEFORE: ::c_uint = 1; pub const SYNC_FILE_RANGE_WRITE: ::c_uint = 2; pub const SYNC_FILE_RANGE_WAIT_AFTER: ::c_uint = 4; pub const EAI_SYSTEM: ::c_int = -11; pub const AIO_CANCELED: ::c_int = 0; pub const AIO_NOTCANCELED: ::c_int = 1; pub const AIO_ALLDONE: ::c_int = 2; pub const LIO_READ: ::c_int = 0; pub const LIO_WRITE: ::c_int = 1; pub const LIO_NOP: ::c_int = 2; pub const LIO_WAIT: ::c_int = 0; pub const LIO_NOWAIT: ::c_int = 1; pub const MREMAP_MAYMOVE: ::c_int = 1; pub const MREMAP_FIXED: ::c_int = 2; pub const PR_SET_PDEATHSIG: ::c_int = 1; pub const PR_GET_PDEATHSIG: ::c_int = 2; pub const PR_GET_DUMPABLE: ::c_int = 3; pub const PR_SET_DUMPABLE: ::c_int = 4; pub const PR_GET_UNALIGN: ::c_int = 5; pub const PR_SET_UNALIGN: ::c_int = 6; pub const PR_UNALIGN_NOPRINT: ::c_int = 1; pub const PR_UNALIGN_SIGBUS: ::c_int = 2; pub const PR_GET_KEEPCAPS: ::c_int = 7; pub const PR_SET_KEEPCAPS: ::c_int = 8; pub const PR_GET_FPEMU: ::c_int = 9; pub const PR_SET_FPEMU: ::c_int = 10; pub const PR_FPEMU_NOPRINT: ::c_int = 1; pub const PR_FPEMU_SIGFPE: ::c_int = 2; pub const PR_GET_FPEXC: ::c_int = 11; pub const PR_SET_FPEXC: ::c_int = 12; pub const PR_FP_EXC_SW_ENABLE: ::c_int = 0x80; pub const PR_FP_EXC_DIV: ::c_int = 0x010000; pub const PR_FP_EXC_OVF: ::c_int = 0x020000; pub const PR_FP_EXC_UND: ::c_int = 0x040000; pub const PR_FP_EXC_RES: ::c_int = 0x080000; pub const PR_FP_EXC_INV: ::c_int = 0x100000; pub const PR_FP_EXC_DISABLED: ::c_int = 0; pub const PR_FP_EXC_NONRECOV: ::c_int = 1; pub const PR_FP_EXC_ASYNC: ::c_int = 2; pub const PR_FP_EXC_PRECISE: ::c_int = 3; pub const PR_GET_TIMING: ::c_int = 13; pub const PR_SET_TIMING: ::c_int = 14; pub const PR_TIMING_STATISTICAL: ::c_int = 0; pub const PR_TIMING_TIMESTAMP: ::c_int = 1; pub const PR_SET_NAME: ::c_int = 15; pub const PR_GET_NAME: ::c_int = 16; pub const PR_GET_ENDIAN: ::c_int = 19; pub const PR_SET_ENDIAN: ::c_int = 20; pub const PR_ENDIAN_BIG: ::c_int = 0; pub const PR_ENDIAN_LITTLE: ::c_int = 1; pub const PR_ENDIAN_PPC_LITTLE: ::c_int = 2; pub const PR_GET_SECCOMP: ::c_int = 21; pub const PR_SET_SECCOMP: ::c_int = 22; pub const PR_CAPBSET_READ: ::c_int = 23; pub const PR_CAPBSET_DROP: ::c_int = 24; pub const PR_GET_TSC: ::c_int = 25; pub const PR_SET_TSC: ::c_int = 26; pub const PR_TSC_ENABLE: ::c_int = 1; pub const PR_TSC_SIGSEGV: ::c_int = 2; pub const PR_GET_SECUREBITS: ::c_int = 27; pub const PR_SET_SECUREBITS: ::c_int = 28; pub const PR_SET_TIMERSLACK: ::c_int = 29; pub const PR_GET_TIMERSLACK: ::c_int = 30; pub const PR_TASK_PERF_EVENTS_DISABLE: ::c_int = 31; pub const PR_TASK_PERF_EVENTS_ENABLE: ::c_int = 32; pub const PR_MCE_KILL: ::c_int = 33; pub const PR_MCE_KILL_CLEAR: ::c_int = 0; pub const PR_MCE_KILL_SET: ::c_int = 1; pub const PR_MCE_KILL_LATE: ::c_int = 0; pub const PR_MCE_KILL_EARLY: ::c_int = 1; pub const PR_MCE_KILL_DEFAULT: ::c_int = 2; pub const PR_MCE_KILL_GET: ::c_int = 34; pub const PR_SET_MM: ::c_int = 35; pub const PR_SET_MM_START_CODE: ::c_int = 1; pub const PR_SET_MM_END_CODE: ::c_int = 2; pub const PR_SET_MM_START_DATA: ::c_int = 3; pub const PR_SET_MM_END_DATA: ::c_int = 4; pub const PR_SET_MM_START_STACK: ::c_int = 5; pub const PR_SET_MM_START_BRK: ::c_int = 6; pub const PR_SET_MM_BRK: ::c_int = 7; pub const PR_SET_MM_ARG_START: ::c_int = 8; pub const PR_SET_MM_ARG_END: ::c_int = 9; pub const PR_SET_MM_ENV_START: ::c_int = 10; pub const PR_SET_MM_ENV_END: ::c_int = 11; pub const PR_SET_MM_AUXV: ::c_int = 12; pub const PR_SET_MM_EXE_FILE: ::c_int = 13; pub const PR_SET_MM_MAP: ::c_int = 14; pub const PR_SET_MM_MAP_SIZE: ::c_int = 15; pub const PR_SET_PTRACER: ::c_int = 0x59616d61; pub const PR_SET_PTRACER_ANY: ::c_ulong = 0xffffffffffffffff; pub const PR_SET_CHILD_SUBREAPER: ::c_int = 36; pub const PR_GET_CHILD_SUBREAPER: ::c_int = 37; pub const PR_SET_NO_NEW_PRIVS: ::c_int = 38; pub const PR_GET_NO_NEW_PRIVS: ::c_int = 39; pub const PR_GET_TID_ADDRESS: ::c_int = 40; pub const PR_SET_THP_DISABLE: ::c_int = 41; pub const PR_GET_THP_DISABLE: ::c_int = 42; pub const PR_MPX_ENABLE_MANAGEMENT: ::c_int = 43; pub const PR_MPX_DISABLE_MANAGEMENT: ::c_int = 44; pub const PR_SET_FP_MODE: ::c_int = 45; pub const PR_GET_FP_MODE: ::c_int = 46; pub const PR_FP_MODE_FR: ::c_int = 1 << 0; pub const PR_FP_MODE_FRE: ::c_int = 1 << 1; pub const PR_CAP_AMBIENT: ::c_int = 47; pub const PR_CAP_AMBIENT_IS_SET: ::c_int = 1; pub const PR_CAP_AMBIENT_RAISE: ::c_int = 2; pub const PR_CAP_AMBIENT_LOWER: ::c_int = 3; pub const PR_CAP_AMBIENT_CLEAR_ALL: ::c_int = 4; pub const ITIMER_REAL: ::c_int = 0; pub const ITIMER_VIRTUAL: ::c_int = 1; pub const ITIMER_PROF: ::c_int = 2; pub const _POSIX_VDISABLE: ::cc_t = 0; pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02; // On Linux, libc doesn't define this constant, libattr does instead. // We still define it for Linux as it's defined by libc on other platforms, // and it's mentioned in the man pages for getxattr and setxattr. pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_CLOEXEC: ::c_int = 0x80000; // Defined as wasi value. pub const EPERM: ::c_int = 63; pub const ENOENT: ::c_int = 44; pub const ESRCH: ::c_int = 71; pub const EINTR: ::c_int = 27; pub const EIO: ::c_int = 29; pub const ENXIO: ::c_int = 60; pub const E2BIG: ::c_int = 1; pub const ENOEXEC: ::c_int = 45; pub const EBADF: ::c_int = 8; pub const ECHILD: ::c_int = 12; pub const EAGAIN: ::c_int = 6; pub const ENOMEM: ::c_int = 48; pub const EACCES: ::c_int = 2; pub const EFAULT: ::c_int = 21; pub const ENOTBLK: ::c_int = 105; pub const EBUSY: ::c_int = 10; pub const EEXIST: ::c_int = 20; pub const EXDEV: ::c_int = 75; pub const ENODEV: ::c_int = 43; pub const ENOTDIR: ::c_int = 54; pub const EISDIR: ::c_int = 31; pub const EINVAL: ::c_int = 28; pub const ENFILE: ::c_int = 41; pub const EMFILE: ::c_int = 33; pub const ENOTTY: ::c_int = 59; pub const ETXTBSY: ::c_int = 74; pub const EFBIG: ::c_int = 22; pub const ENOSPC: ::c_int = 51; pub const ESPIPE: ::c_int = 70; pub const EROFS: ::c_int = 69; pub const EMLINK: ::c_int = 34; pub const EPIPE: ::c_int = 64; pub const EDOM: ::c_int = 18; pub const ERANGE: ::c_int = 68; pub const EWOULDBLOCK: ::c_int = EAGAIN; pub const ENOLINK: ::c_int = 47; pub const EPROTO: ::c_int = 65; pub const EDEADLK: ::c_int = 16; pub const EDEADLOCK: ::c_int = EDEADLK; pub const ENAMETOOLONG: ::c_int = 37; pub const ENOLCK: ::c_int = 46; pub const ENOSYS: ::c_int = 52; pub const ENOTEMPTY: ::c_int = 55; pub const ELOOP: ::c_int = 32; pub const ENOMSG: ::c_int = 49; pub const EIDRM: ::c_int = 24; pub const EMULTIHOP: ::c_int = 36; pub const EBADMSG: ::c_int = 9; pub const EOVERFLOW: ::c_int = 61; pub const EILSEQ: ::c_int = 25; pub const ENOTSOCK: ::c_int = 57; pub const EDESTADDRREQ: ::c_int = 17; pub const EMSGSIZE: ::c_int = 35; pub const EPROTOTYPE: ::c_int = 67; pub const ENOPROTOOPT: ::c_int = 50; pub const EPROTONOSUPPORT: ::c_int = 66; pub const EAFNOSUPPORT: ::c_int = 5; pub const EADDRINUSE: ::c_int = 3; pub const EADDRNOTAVAIL: ::c_int = 4; pub const ENETDOWN: ::c_int = 38; pub const ENETUNREACH: ::c_int = 40; pub const ENETRESET: ::c_int = 39; pub const ECONNABORTED: ::c_int = 13; pub const ECONNRESET: ::c_int = 15; pub const ENOBUFS: ::c_int = 42; pub const EISCONN: ::c_int = 30; pub const ENOTCONN: ::c_int = 53; pub const ETIMEDOUT: ::c_int = 73; pub const ECONNREFUSED: ::c_int = 14; pub const EHOSTUNREACH: ::c_int = 23; pub const EALREADY: ::c_int = 7; pub const EINPROGRESS: ::c_int = 26; pub const ESTALE: ::c_int = 72; pub const EDQUOT: ::c_int = 19; pub const ECANCELED: ::c_int = 11; pub const EOWNERDEAD: ::c_int = 62; pub const ENOTRECOVERABLE: ::c_int = 56; pub const ENOSTR: ::c_int = 100; pub const EBFONT: ::c_int = 101; pub const EBADSLT: ::c_int = 102; pub const EBADRQC: ::c_int = 103; pub const ENOANO: ::c_int = 104; pub const ECHRNG: ::c_int = 106; pub const EL3HLT: ::c_int = 107; pub const EL3RST: ::c_int = 108; pub const ELNRNG: ::c_int = 109; pub const EUNATCH: ::c_int = 110; pub const ENOCSI: ::c_int = 111; pub const EL2HLT: ::c_int = 112; pub const EBADE: ::c_int = 113; pub const EBADR: ::c_int = 114; pub const EXFULL: ::c_int = 115; pub const ENODATA: ::c_int = 116; pub const ETIME: ::c_int = 117; pub const ENOSR: ::c_int = 118; pub const ENONET: ::c_int = 119; pub const ENOPKG: ::c_int = 120; pub const EREMOTE: ::c_int = 121; pub const EADV: ::c_int = 122; pub const ESRMNT: ::c_int = 123; pub const ECOMM: ::c_int = 124; pub const EDOTDOT: ::c_int = 125; pub const ENOTUNIQ: ::c_int = 126; pub const EBADFD: ::c_int = 127; pub const EREMCHG: ::c_int = 128; pub const ELIBACC: ::c_int = 129; pub const ELIBBAD: ::c_int = 130; pub const ELIBSCN: ::c_int = 131; pub const ELIBMAX: ::c_int = 132; pub const ELIBEXEC: ::c_int = 133; pub const ERESTART: ::c_int = 134; pub const ESTRPIPE: ::c_int = 135; pub const EUSERS: ::c_int = 136; pub const ESOCKTNOSUPPORT: ::c_int = 137; pub const EOPNOTSUPP: ::c_int = 138; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 139; pub const ESHUTDOWN: ::c_int = 140; pub const ETOOMANYREFS: ::c_int = 141; pub const EHOSTDOWN: ::c_int = 142; pub const EUCLEAN: ::c_int = 143; pub const ENOTNAM: ::c_int = 144; pub const ENAVAIL: ::c_int = 145; pub const EISNAM: ::c_int = 146; pub const EREMOTEIO: ::c_int = 147; pub const ENOMEDIUM: ::c_int = 148; pub const EMEDIUMTYPE: ::c_int = 149; pub const ENOKEY: ::c_int = 150; pub const EKEYEXPIRED: ::c_int = 151; pub const EKEYREVOKED: ::c_int = 152; pub const EKEYREJECTED: ::c_int = 153; pub const ERFKILL: ::c_int = 154; pub const EHWPOISON: ::c_int = 155; pub const EL2NSYNC: ::c_int = 156; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const BUFSIZ: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 10000; pub const FOPEN_MAX: ::c_uint = 1000; pub const O_PATH: ::c_int = 0o10000000; pub const O_EXEC: ::c_int = 0o10000000; pub const O_SEARCH: ::c_int = 0o10000000; pub const O_ACCMODE: ::c_int = 0o10000003; pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const NI_MAXHOST: ::socklen_t = 255; pub const PTHREAD_STACK_MIN: ::size_t = 2048; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const POSIX_MADV_DONTNEED: ::c_int = 0; pub const RLIM_INFINITY: ::rlim_t = !0; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::c_int = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = RLIMIT_NLIMITS; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; #[doc(hidden)] #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = ::SIGSYS; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const CPU_SETSIZE: ::c_int = 128; pub const QFMT_VFS_V1: ::c_int = 4; pub const PTRACE_TRACEME: ::c_int = 0; pub const PTRACE_PEEKTEXT: ::c_int = 1; pub const PTRACE_PEEKDATA: ::c_int = 2; pub const PTRACE_PEEKUSER: ::c_int = 3; pub const PTRACE_POKETEXT: ::c_int = 4; pub const PTRACE_POKEDATA: ::c_int = 5; pub const PTRACE_POKEUSER: ::c_int = 6; pub const PTRACE_CONT: ::c_int = 7; pub const PTRACE_KILL: ::c_int = 8; pub const PTRACE_SINGLESTEP: ::c_int = 9; pub const PTRACE_ATTACH: ::c_int = 16; pub const PTRACE_DETACH: ::c_int = 17; pub const PTRACE_SYSCALL: ::c_int = 24; pub const PTRACE_SETOPTIONS: ::c_int = 0x4200; pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201; pub const PTRACE_GETSIGINFO: ::c_int = 0x4202; pub const PTRACE_SETSIGINFO: ::c_int = 0x4203; pub const PTRACE_GETREGSET: ::c_int = 0x4204; pub const PTRACE_SETREGSET: ::c_int = 0x4205; pub const PTRACE_SEIZE: ::c_int = 0x4206; pub const PTRACE_INTERRUPT: ::c_int = 0x4207; pub const PTRACE_LISTEN: ::c_int = 0x4208; pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209; pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const PTRACE_GETREGS: ::c_uint = 12; pub const PTRACE_SETREGS: ::c_uint = 13; pub const EFD_NONBLOCK: ::c_int = ::O_NONBLOCK; pub const SFD_NONBLOCK: ::c_int = ::O_NONBLOCK; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const TIOCINQ: ::c_int = ::FIONREAD; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const CLOCK_SGI_CYCLE: ::clockid_t = 10; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const SO_BINDTODEVICE: ::c_int = 25; pub const SO_TIMESTAMP: ::c_int = 29; pub const SO_MARK: ::c_int = 36; pub const SO_RXQ_OVFL: ::c_int = 40; pub const SO_PEEK_OFF: ::c_int = 42; pub const SO_BUSY_POLL: ::c_int = 46; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 28; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_ASYNC: ::c_int = 0x2000; pub const FIOCLEX: ::c_int = 0x5451; pub const FIONBIO: ::c_int = 0x5421; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_AS: ::c_int = 9; pub const RLIMIT_NPROC: ::c_int = 6; pub const RLIMIT_MEMLOCK: ::c_int = 8; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_LOCKS: ::c_int = 10; pub const RLIMIT_SIGPENDING: ::c_int = 11; pub const RLIMIT_MSGQUEUE: ::c_int = 12; pub const RLIMIT_NICE: ::c_int = 13; pub const RLIMIT_RTPRIO: ::c_int = 14; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const SOCK_NONBLOCK: ::c_int = 2048; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_SEQPACKET: ::c_int = 5; pub const IPPROTO_MAX: ::c_int = 256; pub const SOL_SOCKET: ::c_int = 1; pub const SO_REUSEADDR: ::c_int = 2; pub const SO_TYPE: ::c_int = 3; pub const SO_ERROR: ::c_int = 4; pub const SO_DONTROUTE: ::c_int = 5; pub const SO_BROADCAST: ::c_int = 6; pub const SO_SNDBUF: ::c_int = 7; pub const SO_RCVBUF: ::c_int = 8; pub const SO_KEEPALIVE: ::c_int = 9; pub const SO_OOBINLINE: ::c_int = 10; pub const SO_LINGER: ::c_int = 13; pub const SO_REUSEPORT: ::c_int = 15; pub const SO_RCVLOWAT: ::c_int = 18; pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; pub const SO_ACCEPTCONN: ::c_int = 30; pub const IPV6_RTHDR_LOOSE: ::c_int = 0; pub const IPV6_RTHDR_STRICT: ::c_int = 1; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const F_GETLK: ::c_int = 12; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 13; pub const F_SETLKW: ::c_int = 14; pub const F_SETOWN: ::c_int = 8; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const TCGETS: ::c_int = 0x5401; pub const TCSETS: ::c_int = 0x5402; pub const TCSETSW: ::c_int = 0x5403; pub const TCSETSF: ::c_int = 0x5404; pub const TCGETA: ::c_int = 0x5405; pub const TCSETA: ::c_int = 0x5406; pub const TCSETAW: ::c_int = 0x5407; pub const TCSETAF: ::c_int = 0x5408; pub const TCSBRK: ::c_int = 0x5409; pub const TCXONC: ::c_int = 0x540A; pub const TCFLSH: ::c_int = 0x540B; pub const TIOCGSOFTCAR: ::c_int = 0x5419; pub const TIOCSSOFTCAR: ::c_int = 0x541A; pub const TIOCLINUX: ::c_int = 0x541C; pub const TIOCGSERIAL: ::c_int = 0x541E; pub const TIOCEXCL: ::c_int = 0x540C; pub const TIOCNXCL: ::c_int = 0x540D; pub const TIOCSCTTY: ::c_int = 0x540E; pub const TIOCGPGRP: ::c_int = 0x540F; pub const TIOCSPGRP: ::c_int = 0x5410; pub const TIOCOUTQ: ::c_int = 0x5411; pub const TIOCSTI: ::c_int = 0x5412; pub const TIOCGWINSZ: ::c_int = 0x5413; pub const TIOCSWINSZ: ::c_int = 0x5414; pub const TIOCMGET: ::c_int = 0x5415; pub const TIOCMBIS: ::c_int = 0x5416; pub const TIOCMBIC: ::c_int = 0x5417; pub const TIOCMSET: ::c_int = 0x5418; pub const FIONREAD: ::c_int = 0x541B; pub const TIOCCONS: ::c_int = 0x541D; pub const SYS_gettid: ::c_long = 224; // Valid for arm (32-bit) and x86 (32-bit) pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const TIOCM_LE: ::c_int = 0x001; pub const TIOCM_DTR: ::c_int = 0x002; pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_ST: ::c_int = 0x008; pub const TIOCM_SR: ::c_int = 0x010; pub const TIOCM_CTS: ::c_int = 0x020; pub const TIOCM_CAR: ::c_int = 0x040; pub const TIOCM_RNG: ::c_int = 0x080; pub const TIOCM_DSR: ::c_int = 0x100; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const O_TMPFILE: ::c_int = 0x400000; pub const MAX_ADDR_LEN: usize = 7; pub const ARPD_UPDATE: ::c_ushort = 0x01; pub const ARPD_LOOKUP: ::c_ushort = 0x02; pub const ARPD_FLUSH: ::c_ushort = 0x03; pub const ATF_MAGIC: ::c_int = 0x80; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; pub const SOMAXCONN: ::c_int = 128; f! { pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as usize) < ::mem::size_of::() { return 0 as *mut cmsghdr; }; let next = (cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.offset(1)) as usize > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn major(dev: ::dev_t) -> ::c_uint { // see // https://github.com/emscripten-core/emscripten/blob/ // main/system/lib/libc/musl/include/sys/sysmacros.h let mut major = 0; major |= (dev & 0x00000fff) >> 8; major |= (dev & 0xfffff000) >> 31 >> 1; major as ::c_uint } pub fn minor(dev: ::dev_t) -> ::c_uint { // see // https://github.com/emscripten-core/emscripten/blob/ // main/system/lib/libc/musl/include/sys/sysmacros.h let mut minor = 0; minor |= (dev & 0x000000ff) >> 0; minor |= (dev & 0xffffff00) >> 12; minor as ::c_uint } } safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= (major & 0x00000fff) << 8; dev |= (major & 0xfffff000) << 31 << 1; dev |= (minor & 0x000000ff) << 0; dev |= (minor & 0xffffff00) << 12; dev } } extern "C" { pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn __errno_location() -> *mut ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int, ) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn mremap( addr: *mut ::c_void, len: ::size_t, new_len: ::size_t, flags: ::c_int, ... ) -> *mut ::c_void; pub fn glob( pattern: *const c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_uint, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_uint, timeout: *mut ::timespec, ) -> ::c_int; pub fn sync(); pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; } // Alias to 64 to mimic glibc's LFS64 support mod lfs64; pub use self::lfs64::*; cfg_if! { if #[cfg(libc_align)] { #[macro_use] mod align; } else { #[macro_use] mod no_align; } } expand_align!(); libc/src/unix/linux_like/emscripten/no_align.rs0000644000175000017500000000402214661133735022672 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { pub struct pthread_mutex_t { __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } pub struct pthread_rwlock_t { __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } pub struct pthread_mutexattr_t { __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } pub struct pthread_rwlockattr_t { __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCKATTR_T], } pub struct pthread_condattr_t { __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } s_no_extra_traits! { pub struct pthread_cond_t { __align: [*const ::c_void; 0], size: [u8; ::__SIZEOF_PTHREAD_COND_T], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_cond_t {} impl ::fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_cond_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } } } }; } libc/src/unix/linux_like/emscripten/align.rs0000644000175000017500000000451014661133735022200 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { #[allow(missing_debug_implementations)] #[repr(align(4))] pub struct pthread_mutex_t { size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } #[repr(align(4))] pub struct pthread_rwlock_t { size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } #[repr(align(4))] pub struct pthread_mutexattr_t { size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(4))] pub struct pthread_rwlockattr_t { size: [u8; ::__SIZEOF_PTHREAD_RWLOCKATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } s_no_extra_traits! { #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct pthread_cond_t { size: [u8; ::__SIZEOF_PTHREAD_COND_T], } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.size .iter() .zip(other.size.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_cond_t {} impl ::fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_cond_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } } } }; } libc/src/unix/linux_like/linux/0000775000175000017500000000000014661133735017530 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/0000775000175000017500000000000014661133735020510 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/lfs64.rs0000644000175000017500000001314414661133735022015 0ustar jamespagejamespage#[inline] pub unsafe extern "C" fn creat64(path: *const ::c_char, mode: ::mode_t) -> ::c_int { ::creat(path, mode) } #[inline] pub unsafe extern "C" fn fallocate64( fd: ::c_int, mode: ::c_int, offset: ::off64_t, len: ::off64_t, ) -> ::c_int { ::fallocate(fd, mode, offset, len) } #[inline] pub unsafe extern "C" fn fgetpos64(stream: *mut ::FILE, pos: *mut ::fpos64_t) -> ::c_int { ::fgetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fopen64(pathname: *const ::c_char, mode: *const ::c_char) -> *mut ::FILE { ::fopen(pathname, mode) } #[inline] pub unsafe extern "C" fn freopen64( pathname: *const ::c_char, mode: *const ::c_char, stream: *mut ::FILE, ) -> *mut ::FILE { ::freopen(pathname, mode, stream) } #[inline] pub unsafe extern "C" fn fseeko64( stream: *mut ::FILE, offset: ::off64_t, whence: ::c_int, ) -> ::c_int { ::fseeko(stream, offset, whence) } #[inline] pub unsafe extern "C" fn fsetpos64(stream: *mut ::FILE, pos: *const ::fpos64_t) -> ::c_int { ::fsetpos(stream, pos as *mut _) } #[inline] pub unsafe extern "C" fn fstat64(fildes: ::c_int, buf: *mut ::stat64) -> ::c_int { ::fstat(fildes, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatat64( fd: ::c_int, path: *const ::c_char, buf: *mut ::stat64, flag: ::c_int, ) -> ::c_int { ::fstatat(fd, path, buf as *mut _, flag) } #[inline] pub unsafe extern "C" fn fstatfs64(fd: ::c_int, buf: *mut ::statfs64) -> ::c_int { ::fstatfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn fstatvfs64(fd: ::c_int, buf: *mut ::statvfs64) -> ::c_int { ::fstatvfs(fd, buf as *mut _) } #[inline] pub unsafe extern "C" fn ftello64(stream: *mut ::FILE) -> ::off64_t { ::ftello(stream) } #[inline] pub unsafe extern "C" fn ftruncate64(fd: ::c_int, length: ::off64_t) -> ::c_int { ::ftruncate(fd, length) } #[inline] pub unsafe extern "C" fn getrlimit64(resource: ::c_int, rlim: *mut ::rlimit64) -> ::c_int { ::getrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn lseek64(fd: ::c_int, offset: ::off64_t, whence: ::c_int) -> ::off64_t { ::lseek(fd, offset, whence) } #[inline] pub unsafe extern "C" fn lstat64(path: *const ::c_char, buf: *mut ::stat64) -> ::c_int { ::lstat(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn mmap64( addr: *mut ::c_void, length: ::size_t, prot: ::c_int, flags: ::c_int, fd: ::c_int, offset: ::off64_t, ) -> *mut ::c_void { ::mmap(addr, length, prot, flags, fd, offset) } // These functions are variadic in the C ABI since the `mode` argument is "optional". Variadic // `extern "C"` functions are unstable in Rust so we cannot write a shim function for these // entrypoints. See https://github.com/rust-lang/rust/issues/44930. // // These aliases are mostly fine though, neither function takes a LFS64-namespaced type as an // argument, nor do their names clash with any declared types. pub use open as open64; pub use openat as openat64; #[inline] pub unsafe extern "C" fn posix_fadvise64( fd: ::c_int, offset: ::off64_t, len: ::off64_t, advice: ::c_int, ) -> ::c_int { ::posix_fadvise(fd, offset, len, advice) } #[inline] pub unsafe extern "C" fn posix_fallocate64( fd: ::c_int, offset: ::off64_t, len: ::off64_t, ) -> ::c_int { ::posix_fallocate(fd, offset, len) } #[inline] pub unsafe extern "C" fn pread64( fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: ::off64_t, ) -> ::ssize_t { ::pread(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn preadv64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t { ::preadv(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn prlimit64( pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit64, old_limit: *mut ::rlimit64, ) -> ::c_int { ::prlimit(pid, resource, new_limit as *mut _, old_limit as *mut _) } #[inline] pub unsafe extern "C" fn pwrite64( fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: ::off64_t, ) -> ::ssize_t { ::pwrite(fd, buf, count, offset) } #[inline] pub unsafe extern "C" fn pwritev64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t { ::pwritev(fd, iov, iovcnt, offset) } #[inline] pub unsafe extern "C" fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64 { ::readdir(dirp) as *mut _ } #[inline] pub unsafe extern "C" fn readdir64_r( dirp: *mut ::DIR, entry: *mut ::dirent64, result: *mut *mut ::dirent64, ) -> ::c_int { ::readdir_r(dirp, entry as *mut _, result as *mut _) } #[inline] pub unsafe extern "C" fn sendfile64( out_fd: ::c_int, in_fd: ::c_int, offset: *mut ::off64_t, count: ::size_t, ) -> ::ssize_t { ::sendfile(out_fd, in_fd, offset, count) } #[inline] pub unsafe extern "C" fn setrlimit64(resource: ::c_int, rlim: *const ::rlimit64) -> ::c_int { ::setrlimit(resource, rlim as *mut _) } #[inline] pub unsafe extern "C" fn stat64(pathname: *const ::c_char, statbuf: *mut ::stat64) -> ::c_int { ::stat(pathname, statbuf as *mut _) } #[inline] pub unsafe extern "C" fn statfs64(pathname: *const ::c_char, buf: *mut ::statfs64) -> ::c_int { ::statfs(pathname, buf as *mut _) } #[inline] pub unsafe extern "C" fn statvfs64(path: *const ::c_char, buf: *mut ::statvfs64) -> ::c_int { ::statvfs(path, buf as *mut _) } #[inline] pub unsafe extern "C" fn tmpfile64() -> *mut ::FILE { ::tmpfile() } #[inline] pub unsafe extern "C" fn truncate64(path: *const ::c_char, length: ::off64_t) -> ::c_int { ::truncate(path, length) } libc/src/unix/linux_like/linux/musl/b32/0000775000175000017500000000000014661133735021076 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b32/powerpc.rs0000644000175000017500000007055414661133735023134 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_rdev_padding: ::c_short, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 2], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_rdev_padding: ::c_short, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 2], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __pad1: ::c_int, __pad2: ::c_longlong, __pad3: ::c_longlong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, __unused1: ::c_int, pub shm_atime: ::time_t, __unused2: ::c_int, pub shm_dtime: ::time_t, __unused3: ::c_int, pub shm_ctime: ::time_t, __unused4: ::c_int, pub shm_segsz: ::size_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, __unused1: ::c_int, pub msg_stime: ::time_t, __unused2: ::c_int, pub msg_rtime: ::time_t, __unused3: ::c_int, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, #[cfg(target_endian = "little")] pub f_fsid: ::c_ulong, __f_unused: ::c_int, #[cfg(target_endian = "big")] pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } } pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const SIGSTKSZ: ::size_t = 10240; pub const MINSIGSTKSZ: ::size_t = 4096; pub const O_DIRECT: ::c_int = 0x20000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_LARGEFILE: ::c_int = 0x10000; pub const MCL_CURRENT: ::c_int = 0x2000; pub const MCL_FUTURE: ::c_int = 0x4000; pub const MCL_ONFAULT: ::c_int = 0x8000; pub const CBAUD: ::tcflag_t = 0o0000377; pub const TAB1: ::c_int = 0x00000400; pub const TAB2: ::c_int = 0x00000800; pub const TAB3: ::c_int = 0x00000C00; pub const CR1: ::c_int = 0x00001000; pub const CR2: ::c_int = 0x00002000; pub const CR3: ::c_int = 0x00003000; pub const FF1: ::c_int = 0x00004000; pub const BS1: ::c_int = 0x00008000; pub const VT1: ::c_int = 0x00010000; pub const VWERASE: usize = 10; pub const VREPRINT: usize = 11; pub const VSUSP: usize = 12; pub const VSTART: usize = 13; pub const VSTOP: usize = 14; pub const VDISCARD: usize = 16; pub const VTIME: usize = 7; pub const IXON: ::tcflag_t = 0x00000200; pub const IXOFF: ::tcflag_t = 0x00000400; pub const ONLCR: ::tcflag_t = 0x00000002; pub const CSIZE: ::tcflag_t = 0x00000300; pub const CS6: ::tcflag_t = 0x00000100; pub const CS7: ::tcflag_t = 0x00000200; pub const CS8: ::tcflag_t = 0x00000300; pub const CSTOPB: ::tcflag_t = 0x00000400; pub const CREAD: ::tcflag_t = 0x00000800; pub const PARENB: ::tcflag_t = 0x00001000; pub const PARODD: ::tcflag_t = 0x00002000; pub const HUPCL: ::tcflag_t = 0x00004000; pub const CLOCAL: ::tcflag_t = 0x00008000; pub const ECHOKE: ::tcflag_t = 0x00000001; pub const ECHOE: ::tcflag_t = 0x00000002; pub const ECHOK: ::tcflag_t = 0x00000004; pub const ECHONL: ::tcflag_t = 0x00000010; pub const ECHOPRT: ::tcflag_t = 0x00000020; pub const ECHOCTL: ::tcflag_t = 0x00000040; pub const ISIG: ::tcflag_t = 0x00000080; pub const ICANON: ::tcflag_t = 0x00000100; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; pub const CIBAUD: ::tcflag_t = 0o00077600000; pub const CBAUDEX: ::tcflag_t = 0o000020; pub const VSWTC: usize = 9; pub const OLCUC: ::tcflag_t = 0o000004; pub const NLDLY: ::tcflag_t = 0o001400; pub const CRDLY: ::tcflag_t = 0o030000; pub const TABDLY: ::tcflag_t = 0o006000; pub const BSDLY: ::tcflag_t = 0o100000; pub const FFDLY: ::tcflag_t = 0o040000; pub const VTDLY: ::tcflag_t = 0o200000; pub const XTABS: ::tcflag_t = 0o006000; pub const B57600: ::speed_t = 0o000020; pub const B115200: ::speed_t = 0o000021; pub const B230400: ::speed_t = 0o000022; pub const B460800: ::speed_t = 0o000023; pub const B500000: ::speed_t = 0o000024; pub const B576000: ::speed_t = 0o000025; pub const B921600: ::speed_t = 0o000026; pub const B1000000: ::speed_t = 0o000027; pub const B1152000: ::speed_t = 0o000030; pub const B1500000: ::speed_t = 0o000031; pub const B2000000: ::speed_t = 0o000032; pub const B2500000: ::speed_t = 0o000033; pub const B3000000: ::speed_t = 0o000034; pub const B3500000: ::speed_t = 0o000035; pub const B4000000: ::speed_t = 0o000036; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x00080; pub const MAP_NORESERVE: ::c_int = 0x00040; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const PTRACE_SYSEMU: ::c_int = 0x1d; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_int = 0x1e; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EDEADLOCK: ::c_int = 58; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const EXTPROC: ::tcflag_t = 0x10000000; pub const F_GETLK: ::c_int = 12; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 13; pub const F_SETLKW: ::c_int = 14; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: ::tcflag_t = 0x00000400; pub const TOSTOP: ::tcflag_t = 0x00400000; pub const FLUSHO: ::tcflag_t = 0x00800000; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_break: ::c_long = 17; pub const SYS_oldstat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_stime: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_oldfstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_stty: ::c_long = 31; pub const SYS_gtty: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_ftime: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_prof: ::c_long = 44; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_lock: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_mpx: ::c_long = 56; pub const SYS_setpgid: ::c_long = 57; pub const SYS_ulimit: ::c_long = 58; pub const SYS_oldolduname: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_oldlstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_profil: ::c_long = 98; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_ioperm: ::c_long = 101; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_olduname: ::c_long = 109; pub const SYS_iopl: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_vm86: ::c_long = 113; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_modify_ldt: ::c_long = 123; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_query_module: ::c_long = 166; pub const SYS_poll: ::c_long = 167; pub const SYS_nfsservctl: ::c_long = 168; pub const SYS_setresgid: ::c_long = 169; pub const SYS_getresgid: ::c_long = 170; pub const SYS_prctl: ::c_long = 171; pub const SYS_rt_sigreturn: ::c_long = 172; pub const SYS_rt_sigaction: ::c_long = 173; pub const SYS_rt_sigprocmask: ::c_long = 174; pub const SYS_rt_sigpending: ::c_long = 175; pub const SYS_rt_sigtimedwait: ::c_long = 176; pub const SYS_rt_sigqueueinfo: ::c_long = 177; pub const SYS_rt_sigsuspend: ::c_long = 178; pub const SYS_pread64: ::c_long = 179; pub const SYS_pwrite64: ::c_long = 180; pub const SYS_chown: ::c_long = 181; pub const SYS_getcwd: ::c_long = 182; pub const SYS_capget: ::c_long = 183; pub const SYS_capset: ::c_long = 184; pub const SYS_sigaltstack: ::c_long = 185; pub const SYS_sendfile: ::c_long = 186; pub const SYS_getpmsg: ::c_long = 187; pub const SYS_putpmsg: ::c_long = 188; pub const SYS_vfork: ::c_long = 189; pub const SYS_ugetrlimit: ::c_long = 190; pub const SYS_readahead: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_pciconfig_read: ::c_long = 198; pub const SYS_pciconfig_write: ::c_long = 199; pub const SYS_pciconfig_iobase: ::c_long = 200; pub const SYS_multiplexer: ::c_long = 201; pub const SYS_getdents64: ::c_long = 202; pub const SYS_pivot_root: ::c_long = 203; pub const SYS_fcntl64: ::c_long = 204; pub const SYS_madvise: ::c_long = 205; pub const SYS_mincore: ::c_long = 206; pub const SYS_gettid: ::c_long = 207; pub const SYS_tkill: ::c_long = 208; pub const SYS_setxattr: ::c_long = 209; pub const SYS_lsetxattr: ::c_long = 210; pub const SYS_fsetxattr: ::c_long = 211; pub const SYS_getxattr: ::c_long = 212; pub const SYS_lgetxattr: ::c_long = 213; pub const SYS_fgetxattr: ::c_long = 214; pub const SYS_listxattr: ::c_long = 215; pub const SYS_llistxattr: ::c_long = 216; pub const SYS_flistxattr: ::c_long = 217; pub const SYS_removexattr: ::c_long = 218; pub const SYS_lremovexattr: ::c_long = 219; pub const SYS_fremovexattr: ::c_long = 220; pub const SYS_futex: ::c_long = 221; pub const SYS_sched_setaffinity: ::c_long = 222; pub const SYS_sched_getaffinity: ::c_long = 223; pub const SYS_tuxcall: ::c_long = 225; pub const SYS_sendfile64: ::c_long = 226; pub const SYS_io_setup: ::c_long = 227; pub const SYS_io_destroy: ::c_long = 228; pub const SYS_io_getevents: ::c_long = 229; pub const SYS_io_submit: ::c_long = 230; pub const SYS_io_cancel: ::c_long = 231; pub const SYS_set_tid_address: ::c_long = 232; pub const SYS_fadvise64: ::c_long = 233; pub const SYS_exit_group: ::c_long = 234; pub const SYS_lookup_dcookie: ::c_long = 235; pub const SYS_epoll_create: ::c_long = 236; pub const SYS_epoll_ctl: ::c_long = 237; pub const SYS_epoll_wait: ::c_long = 238; pub const SYS_remap_file_pages: ::c_long = 239; pub const SYS_timer_create: ::c_long = 240; pub const SYS_timer_settime: ::c_long = 241; pub const SYS_timer_gettime: ::c_long = 242; pub const SYS_timer_getoverrun: ::c_long = 243; pub const SYS_timer_delete: ::c_long = 244; pub const SYS_clock_settime: ::c_long = 245; pub const SYS_clock_gettime: ::c_long = 246; pub const SYS_clock_getres: ::c_long = 247; pub const SYS_clock_nanosleep: ::c_long = 248; pub const SYS_swapcontext: ::c_long = 249; pub const SYS_tgkill: ::c_long = 250; pub const SYS_utimes: ::c_long = 251; pub const SYS_statfs64: ::c_long = 252; pub const SYS_fstatfs64: ::c_long = 253; pub const SYS_fadvise64_64: ::c_long = 254; pub const SYS_rtas: ::c_long = 255; pub const SYS_sys_debug_setcontext: ::c_long = 256; pub const SYS_migrate_pages: ::c_long = 258; pub const SYS_mbind: ::c_long = 259; pub const SYS_get_mempolicy: ::c_long = 260; pub const SYS_set_mempolicy: ::c_long = 261; pub const SYS_mq_open: ::c_long = 262; pub const SYS_mq_unlink: ::c_long = 263; pub const SYS_mq_timedsend: ::c_long = 264; pub const SYS_mq_timedreceive: ::c_long = 265; pub const SYS_mq_notify: ::c_long = 266; pub const SYS_mq_getsetattr: ::c_long = 267; pub const SYS_kexec_load: ::c_long = 268; pub const SYS_add_key: ::c_long = 269; pub const SYS_request_key: ::c_long = 270; pub const SYS_keyctl: ::c_long = 271; pub const SYS_waitid: ::c_long = 272; pub const SYS_ioprio_set: ::c_long = 273; pub const SYS_ioprio_get: ::c_long = 274; pub const SYS_inotify_init: ::c_long = 275; pub const SYS_inotify_add_watch: ::c_long = 276; pub const SYS_inotify_rm_watch: ::c_long = 277; pub const SYS_spu_run: ::c_long = 278; pub const SYS_spu_create: ::c_long = 279; pub const SYS_pselect6: ::c_long = 280; pub const SYS_ppoll: ::c_long = 281; pub const SYS_unshare: ::c_long = 282; pub const SYS_splice: ::c_long = 283; pub const SYS_tee: ::c_long = 284; pub const SYS_vmsplice: ::c_long = 285; pub const SYS_openat: ::c_long = 286; pub const SYS_mkdirat: ::c_long = 287; pub const SYS_mknodat: ::c_long = 288; pub const SYS_fchownat: ::c_long = 289; pub const SYS_futimesat: ::c_long = 290; pub const SYS_fstatat64: ::c_long = 291; pub const SYS_unlinkat: ::c_long = 292; pub const SYS_renameat: ::c_long = 293; pub const SYS_linkat: ::c_long = 294; pub const SYS_symlinkat: ::c_long = 295; pub const SYS_readlinkat: ::c_long = 296; pub const SYS_fchmodat: ::c_long = 297; pub const SYS_faccessat: ::c_long = 298; pub const SYS_get_robust_list: ::c_long = 299; pub const SYS_set_robust_list: ::c_long = 300; pub const SYS_move_pages: ::c_long = 301; pub const SYS_getcpu: ::c_long = 302; pub const SYS_epoll_pwait: ::c_long = 303; pub const SYS_utimensat: ::c_long = 304; pub const SYS_signalfd: ::c_long = 305; pub const SYS_timerfd_create: ::c_long = 306; pub const SYS_eventfd: ::c_long = 307; pub const SYS_sync_file_range2: ::c_long = 308; pub const SYS_fallocate: ::c_long = 309; pub const SYS_subpage_prot: ::c_long = 310; pub const SYS_timerfd_settime: ::c_long = 311; pub const SYS_timerfd_gettime: ::c_long = 312; pub const SYS_signalfd4: ::c_long = 313; pub const SYS_eventfd2: ::c_long = 314; pub const SYS_epoll_create1: ::c_long = 315; pub const SYS_dup3: ::c_long = 316; pub const SYS_pipe2: ::c_long = 317; pub const SYS_inotify_init1: ::c_long = 318; pub const SYS_perf_event_open: ::c_long = 319; pub const SYS_preadv: ::c_long = 320; pub const SYS_pwritev: ::c_long = 321; pub const SYS_rt_tgsigqueueinfo: ::c_long = 322; pub const SYS_fanotify_init: ::c_long = 323; pub const SYS_fanotify_mark: ::c_long = 324; pub const SYS_prlimit64: ::c_long = 325; pub const SYS_socket: ::c_long = 326; pub const SYS_bind: ::c_long = 327; pub const SYS_connect: ::c_long = 328; pub const SYS_listen: ::c_long = 329; pub const SYS_accept: ::c_long = 330; pub const SYS_getsockname: ::c_long = 331; pub const SYS_getpeername: ::c_long = 332; pub const SYS_socketpair: ::c_long = 333; pub const SYS_send: ::c_long = 334; pub const SYS_sendto: ::c_long = 335; pub const SYS_recv: ::c_long = 336; pub const SYS_recvfrom: ::c_long = 337; pub const SYS_shutdown: ::c_long = 338; pub const SYS_setsockopt: ::c_long = 339; pub const SYS_getsockopt: ::c_long = 340; pub const SYS_sendmsg: ::c_long = 341; pub const SYS_recvmsg: ::c_long = 342; pub const SYS_recvmmsg: ::c_long = 343; pub const SYS_accept4: ::c_long = 344; pub const SYS_name_to_handle_at: ::c_long = 345; pub const SYS_open_by_handle_at: ::c_long = 346; pub const SYS_clock_adjtime: ::c_long = 347; pub const SYS_syncfs: ::c_long = 348; pub const SYS_sendmmsg: ::c_long = 349; pub const SYS_setns: ::c_long = 350; pub const SYS_process_vm_readv: ::c_long = 351; pub const SYS_process_vm_writev: ::c_long = 352; pub const SYS_finit_module: ::c_long = 353; pub const SYS_kcmp: ::c_long = 354; pub const SYS_sched_setattr: ::c_long = 355; pub const SYS_sched_getattr: ::c_long = 356; pub const SYS_renameat2: ::c_long = 357; pub const SYS_seccomp: ::c_long = 358; pub const SYS_getrandom: ::c_long = 359; pub const SYS_memfd_create: ::c_long = 360; pub const SYS_bpf: ::c_long = 361; pub const SYS_execveat: ::c_long = 362; pub const SYS_switch_endian: ::c_long = 363; pub const SYS_userfaultfd: ::c_long = 364; pub const SYS_membarrier: ::c_long = 365; pub const SYS_mlock2: ::c_long = 378; pub const SYS_copy_file_range: ::c_long = 379; pub const SYS_preadv2: ::c_long = 380; pub const SYS_pwritev2: ::c_long = 381; pub const SYS_kexec_file_load: ::c_long = 382; pub const SYS_statx: ::c_long = 383; pub const SYS_pkey_alloc: ::c_long = 384; pub const SYS_pkey_free: ::c_long = 385; pub const SYS_pkey_mprotect: ::c_long = 386; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; extern "C" { pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } libc/src/unix/linux_like/linux/musl/b32/arm/0000775000175000017500000000000014661133735021655 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b32/arm/mod.rs0000644000175000017500000007340014661133735023004 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; s! { pub struct stat { pub st_dev: ::dev_t, __st_dev_padding: ::c_int, __st_ino_truncated: ::c_long, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_rdev_padding: ::c_int, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino_t, } pub struct stat64 { pub st_dev: ::dev_t, __st_dev_padding: ::c_int, __st_ino_truncated: ::c_long, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_rdev_padding: ::c_int, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino_t, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __unused1: ::c_long, __unused2: ::c_long } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_int, pub shm_dtime: ::time_t, __unused2: ::c_int, pub shm_ctime: ::time_t, __unused3: ::c_int, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __unused1: ::c_int, pub msg_rtime: ::time_t, __unused2: ::c_int, pub msg_ctime: ::time_t, __unused3: ::c_int, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct mcontext_t { pub trap_no: ::c_ulong, pub error_code: ::c_ulong, pub oldmask: ::c_ulong, pub arm_r0: ::c_ulong, pub arm_r1: ::c_ulong, pub arm_r2: ::c_ulong, pub arm_r3: ::c_ulong, pub arm_r4: ::c_ulong, pub arm_r5: ::c_ulong, pub arm_r6: ::c_ulong, pub arm_r7: ::c_ulong, pub arm_r8: ::c_ulong, pub arm_r9: ::c_ulong, pub arm_r10: ::c_ulong, pub arm_fp: ::c_ulong, pub arm_ip: ::c_ulong, pub arm_sp: ::c_ulong, pub arm_lr: ::c_ulong, pub arm_pc: ::c_ulong, pub arm_cpsr: ::c_ulong, pub fault_address: ::c_ulong, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: ::sigset_t, pub uc_regspace: [::c_ulonglong; 64], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_link) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); } } } } pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_LARGEFILE: ::c_int = 0o400000; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_SYNC: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const F_GETLK: ::c_int = 12; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 13; pub const F_SETLKW: ::c_int = 14; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_ptrace: ::c_long = 26; pub const SYS_pause: ::c_long = 29; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_setpgid: ::c_long = 57; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_symlink: ::c_long = 83; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_vhangup: ::c_long = 111; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid: ::c_long = 170; pub const SYS_getresgid: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_chown: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_vfork: ::c_long = 190; pub const SYS_ugetrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_lchown32: ::c_long = 198; pub const SYS_getuid32: ::c_long = 199; pub const SYS_getgid32: ::c_long = 200; pub const SYS_geteuid32: ::c_long = 201; pub const SYS_getegid32: ::c_long = 202; pub const SYS_setreuid32: ::c_long = 203; pub const SYS_setregid32: ::c_long = 204; pub const SYS_getgroups32: ::c_long = 205; pub const SYS_setgroups32: ::c_long = 206; pub const SYS_fchown32: ::c_long = 207; pub const SYS_setresuid32: ::c_long = 208; pub const SYS_getresuid32: ::c_long = 209; pub const SYS_setresgid32: ::c_long = 210; pub const SYS_getresgid32: ::c_long = 211; pub const SYS_chown32: ::c_long = 212; pub const SYS_setuid32: ::c_long = 213; pub const SYS_setgid32: ::c_long = 214; pub const SYS_setfsuid32: ::c_long = 215; pub const SYS_setfsgid32: ::c_long = 216; pub const SYS_getdents64: ::c_long = 217; pub const SYS_pivot_root: ::c_long = 218; pub const SYS_mincore: ::c_long = 219; pub const SYS_madvise: ::c_long = 220; pub const SYS_fcntl64: ::c_long = 221; pub const SYS_gettid: ::c_long = 224; pub const SYS_readahead: ::c_long = 225; pub const SYS_setxattr: ::c_long = 226; pub const SYS_lsetxattr: ::c_long = 227; pub const SYS_fsetxattr: ::c_long = 228; pub const SYS_getxattr: ::c_long = 229; pub const SYS_lgetxattr: ::c_long = 230; pub const SYS_fgetxattr: ::c_long = 231; pub const SYS_listxattr: ::c_long = 232; pub const SYS_llistxattr: ::c_long = 233; pub const SYS_flistxattr: ::c_long = 234; pub const SYS_removexattr: ::c_long = 235; pub const SYS_lremovexattr: ::c_long = 236; pub const SYS_fremovexattr: ::c_long = 237; pub const SYS_tkill: ::c_long = 238; pub const SYS_sendfile64: ::c_long = 239; pub const SYS_futex: ::c_long = 240; pub const SYS_sched_setaffinity: ::c_long = 241; pub const SYS_sched_getaffinity: ::c_long = 242; pub const SYS_io_setup: ::c_long = 243; pub const SYS_io_destroy: ::c_long = 244; pub const SYS_io_getevents: ::c_long = 245; pub const SYS_io_submit: ::c_long = 246; pub const SYS_io_cancel: ::c_long = 247; pub const SYS_exit_group: ::c_long = 248; pub const SYS_lookup_dcookie: ::c_long = 249; pub const SYS_epoll_create: ::c_long = 250; pub const SYS_epoll_ctl: ::c_long = 251; pub const SYS_epoll_wait: ::c_long = 252; pub const SYS_remap_file_pages: ::c_long = 253; pub const SYS_set_tid_address: ::c_long = 256; pub const SYS_timer_create: ::c_long = 257; pub const SYS_timer_settime: ::c_long = 258; pub const SYS_timer_gettime: ::c_long = 259; pub const SYS_timer_getoverrun: ::c_long = 260; pub const SYS_timer_delete: ::c_long = 261; pub const SYS_clock_settime: ::c_long = 262; pub const SYS_clock_gettime: ::c_long = 263; pub const SYS_clock_getres: ::c_long = 264; pub const SYS_clock_nanosleep: ::c_long = 265; pub const SYS_statfs64: ::c_long = 266; pub const SYS_fstatfs64: ::c_long = 267; pub const SYS_tgkill: ::c_long = 268; pub const SYS_utimes: ::c_long = 269; pub const SYS_pciconfig_iobase: ::c_long = 271; pub const SYS_pciconfig_read: ::c_long = 272; pub const SYS_pciconfig_write: ::c_long = 273; pub const SYS_mq_open: ::c_long = 274; pub const SYS_mq_unlink: ::c_long = 275; pub const SYS_mq_timedsend: ::c_long = 276; pub const SYS_mq_timedreceive: ::c_long = 277; pub const SYS_mq_notify: ::c_long = 278; pub const SYS_mq_getsetattr: ::c_long = 279; pub const SYS_waitid: ::c_long = 280; pub const SYS_socket: ::c_long = 281; pub const SYS_bind: ::c_long = 282; pub const SYS_connect: ::c_long = 283; pub const SYS_listen: ::c_long = 284; pub const SYS_accept: ::c_long = 285; pub const SYS_getsockname: ::c_long = 286; pub const SYS_getpeername: ::c_long = 287; pub const SYS_socketpair: ::c_long = 288; pub const SYS_send: ::c_long = 289; pub const SYS_sendto: ::c_long = 290; pub const SYS_recv: ::c_long = 291; pub const SYS_recvfrom: ::c_long = 292; pub const SYS_shutdown: ::c_long = 293; pub const SYS_setsockopt: ::c_long = 294; pub const SYS_getsockopt: ::c_long = 295; pub const SYS_sendmsg: ::c_long = 296; pub const SYS_recvmsg: ::c_long = 297; pub const SYS_semop: ::c_long = 298; pub const SYS_semget: ::c_long = 299; pub const SYS_semctl: ::c_long = 300; pub const SYS_msgsnd: ::c_long = 301; pub const SYS_msgrcv: ::c_long = 302; pub const SYS_msgget: ::c_long = 303; pub const SYS_msgctl: ::c_long = 304; pub const SYS_shmat: ::c_long = 305; pub const SYS_shmdt: ::c_long = 306; pub const SYS_shmget: ::c_long = 307; pub const SYS_shmctl: ::c_long = 308; pub const SYS_add_key: ::c_long = 309; pub const SYS_request_key: ::c_long = 310; pub const SYS_keyctl: ::c_long = 311; pub const SYS_semtimedop: ::c_long = 312; pub const SYS_vserver: ::c_long = 313; pub const SYS_ioprio_set: ::c_long = 314; pub const SYS_ioprio_get: ::c_long = 315; pub const SYS_inotify_init: ::c_long = 316; pub const SYS_inotify_add_watch: ::c_long = 317; pub const SYS_inotify_rm_watch: ::c_long = 318; pub const SYS_mbind: ::c_long = 319; pub const SYS_get_mempolicy: ::c_long = 320; pub const SYS_set_mempolicy: ::c_long = 321; pub const SYS_openat: ::c_long = 322; pub const SYS_mkdirat: ::c_long = 323; pub const SYS_mknodat: ::c_long = 324; pub const SYS_fchownat: ::c_long = 325; pub const SYS_futimesat: ::c_long = 326; pub const SYS_fstatat64: ::c_long = 327; pub const SYS_unlinkat: ::c_long = 328; pub const SYS_renameat: ::c_long = 329; pub const SYS_linkat: ::c_long = 330; pub const SYS_symlinkat: ::c_long = 331; pub const SYS_readlinkat: ::c_long = 332; pub const SYS_fchmodat: ::c_long = 333; pub const SYS_faccessat: ::c_long = 334; pub const SYS_pselect6: ::c_long = 335; pub const SYS_ppoll: ::c_long = 336; pub const SYS_unshare: ::c_long = 337; pub const SYS_set_robust_list: ::c_long = 338; pub const SYS_get_robust_list: ::c_long = 339; pub const SYS_splice: ::c_long = 340; pub const SYS_tee: ::c_long = 342; pub const SYS_vmsplice: ::c_long = 343; pub const SYS_move_pages: ::c_long = 344; pub const SYS_getcpu: ::c_long = 345; pub const SYS_epoll_pwait: ::c_long = 346; pub const SYS_kexec_load: ::c_long = 347; pub const SYS_utimensat: ::c_long = 348; pub const SYS_signalfd: ::c_long = 349; pub const SYS_timerfd_create: ::c_long = 350; pub const SYS_eventfd: ::c_long = 351; pub const SYS_fallocate: ::c_long = 352; pub const SYS_timerfd_settime: ::c_long = 353; pub const SYS_timerfd_gettime: ::c_long = 354; pub const SYS_signalfd4: ::c_long = 355; pub const SYS_eventfd2: ::c_long = 356; pub const SYS_epoll_create1: ::c_long = 357; pub const SYS_dup3: ::c_long = 358; pub const SYS_pipe2: ::c_long = 359; pub const SYS_inotify_init1: ::c_long = 360; pub const SYS_preadv: ::c_long = 361; pub const SYS_pwritev: ::c_long = 362; pub const SYS_rt_tgsigqueueinfo: ::c_long = 363; pub const SYS_perf_event_open: ::c_long = 364; pub const SYS_recvmmsg: ::c_long = 365; pub const SYS_accept4: ::c_long = 366; pub const SYS_fanotify_init: ::c_long = 367; pub const SYS_fanotify_mark: ::c_long = 368; pub const SYS_prlimit64: ::c_long = 369; pub const SYS_name_to_handle_at: ::c_long = 370; pub const SYS_open_by_handle_at: ::c_long = 371; pub const SYS_clock_adjtime: ::c_long = 372; pub const SYS_syncfs: ::c_long = 373; pub const SYS_sendmmsg: ::c_long = 374; pub const SYS_setns: ::c_long = 375; pub const SYS_process_vm_readv: ::c_long = 376; pub const SYS_process_vm_writev: ::c_long = 377; pub const SYS_kcmp: ::c_long = 378; pub const SYS_finit_module: ::c_long = 379; pub const SYS_sched_setattr: ::c_long = 380; pub const SYS_sched_getattr: ::c_long = 381; pub const SYS_renameat2: ::c_long = 382; pub const SYS_seccomp: ::c_long = 383; pub const SYS_getrandom: ::c_long = 384; pub const SYS_memfd_create: ::c_long = 385; pub const SYS_bpf: ::c_long = 386; pub const SYS_execveat: ::c_long = 387; pub const SYS_userfaultfd: ::c_long = 388; pub const SYS_membarrier: ::c_long = 389; pub const SYS_mlock2: ::c_long = 390; pub const SYS_copy_file_range: ::c_long = 391; pub const SYS_preadv2: ::c_long = 392; pub const SYS_pwritev2: ::c_long = 393; pub const SYS_pkey_mprotect: ::c_long = 394; pub const SYS_pkey_alloc: ::c_long = 395; pub const SYS_pkey_free: ::c_long = 396; pub const SYS_statx: ::c_long = 397; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; extern "C" { pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/musl/b32/arm/align.rs0000644000175000017500000000022614661133735023313 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: (i64, i64) } } libc/src/unix/linux_like/linux/musl/b32/hexagon.rs0000644000175000017500000005653314661133735023107 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type stat64 = ::stat; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::c_ulonglong, pub st_mode: ::c_uint, pub st_nlink: ::c_uint, pub st_uid: ::c_uint, pub st_gid: ::c_uint, pub st_rdev: ::c_ulonglong, __st_rdev_padding: ::c_ulong, pub st_size: ::c_longlong, pub st_blksize: ::blksize_t, __st_blksize_padding: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int;2], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_ushort, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_int, pub shm_dtime: ::time_t, __unused2: ::c_int, pub shm_ctime: ::time_t, __unused3: ::c_int, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __unused1: ::c_int, pub msg_rtime: ::time_t, __unused2: ::c_int, pub msg_ctime: ::time_t, __unused3: ::c_int, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } } pub const AF_FILE: ::c_int = 1; pub const AF_KCM: ::c_int = 41; pub const AF_MAX: ::c_int = 43; pub const AF_QIPCRTR: ::c_int = 42; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const EAFNOSUPPORT: ::c_int = 97; pub const EALREADY: ::c_int = 114; pub const EBADE: ::c_int = 52; pub const EBADMSG: ::c_int = 74; pub const EBADR: ::c_int = 53; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const ECANCELED: ::c_int = 125; pub const ECHRNG: ::c_int = 44; pub const ECONNABORTED: ::c_int = 103; pub const ECONNREFUSED: ::c_int = 111; pub const ECONNRESET: ::c_int = 104; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = 35; pub const EDESTADDRREQ: ::c_int = 89; pub const EDQUOT: ::c_int = 122; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EHWPOISON: ::c_int = 133; pub const EIDRM: ::c_int = 43; pub const EILSEQ: ::c_int = 84; pub const EINPROGRESS: ::c_int = 115; pub const EISCONN: ::c_int = 106; pub const EISNAM: ::c_int = 120; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREJECTED: ::c_int = 129; pub const EKEYREVOKED: ::c_int = 128; pub const EL2HLT: ::c_int = 51; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBEXEC: ::c_int = 83; pub const ELIBMAX: ::c_int = 82; pub const ELIBSCN: ::c_int = 81; pub const ELNRNG: ::c_int = 48; pub const ELOOP: ::c_int = 40; pub const EMEDIUMTYPE: ::c_int = 124; pub const EMSGSIZE: ::c_int = 90; pub const EMULTIHOP: ::c_int = 72; pub const ENAMETOOLONG: ::c_int = 36; pub const ENAVAIL: ::c_int = 119; pub const ENETDOWN: ::c_int = 100; pub const ENETRESET: ::c_int = 102; pub const ENETUNREACH: ::c_int = 101; pub const ENOANO: ::c_int = 55; pub const ENOBUFS: ::c_int = 105; pub const ENOCSI: ::c_int = 50; pub const ENOKEY: ::c_int = 126; pub const ENOLCK: ::c_int = 37; pub const ENOMEDIUM: ::c_int = 123; pub const ENOMSG: ::c_int = 42; pub const ENOPROTOOPT: ::c_int = 92; pub const ENOSYS: ::c_int = 38; pub const ENOTCONN: ::c_int = 107; pub const ENOTEMPTY: ::c_int = 39; pub const ENOTNAM: ::c_int = 118; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ENOTSOCK: ::c_int = 88; pub const ENOTSUP: ::c_int = 95; pub const ENOTUNIQ: ::c_int = 76; pub const EOPNOTSUPP: ::c_int = 95; pub const EOVERFLOW: ::c_int = 75; pub const EOWNERDEAD: ::c_int = 130; pub const EPFNOSUPPORT: ::c_int = 96; pub const EREMCHG: ::c_int = 78; pub const ERESTART: ::c_int = 85; pub const ERFKILL: ::c_int = 132; pub const ESHUTDOWN: ::c_int = 108; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const ESTALE: ::c_int = 116; pub const ESTRPIPE: ::c_int = 86; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const EUCLEAN: ::c_int = 117; pub const EUNATCH: ::c_int = 49; pub const EUSERS: ::c_int = 87; pub const EXFULL: ::c_int = 54; pub const EXTPROC: ::c_int = 65536; pub const F_EXLCK: ::c_int = 4; pub const F_GETLK: ::c_int = 12; pub const F_GETOWN: ::c_int = 9; pub const F_GETOWNER_UIDS: ::c_int = 17; pub const F_GETOWN_EX: ::c_int = 16; pub const F_GETSIG: ::c_int = 11; pub const F_LINUX_SPECIFIC_BASE: ::c_int = 1024; pub const FLUSHO: ::c_int = 4096; pub const F_OWNER_PGRP: ::c_int = 2; pub const F_OWNER_PID: ::c_int = 1; pub const F_OWNER_TID: ::c_int = 0; pub const F_SETLK: ::c_int = 13; pub const F_SETLKW: ::c_int = 14; pub const F_SETOWN: ::c_int = 8; pub const F_SETOWN_EX: ::c_int = 15; pub const F_SETSIG: ::c_int = 10; pub const F_SHLCK: ::c_int = 8; pub const IEXTEN: ::c_int = 32768; pub const MAP_ANON: ::c_int = 32; pub const MAP_DENYWRITE: ::c_int = 2048; pub const MAP_EXECUTABLE: ::c_int = 4096; pub const MAP_GROWSDOWN: ::c_int = 256; pub const MAP_HUGETLB: ::c_int = 262144; pub const MAP_LOCKED: ::c_int = 8192; pub const MAP_NONBLOCK: ::c_int = 65536; pub const MAP_NORESERVE: ::c_int = 16384; pub const MAP_POPULATE: ::c_int = 32768; pub const MAP_STACK: ::c_int = 131072; pub const MAP_UNINITIALIZED: ::c_int = 0; pub const O_APPEND: ::c_int = 1024; pub const O_ASYNC: ::c_int = 8192; pub const O_CREAT: ::c_int = 64; pub const O_DIRECT: ::c_int = 16384; pub const O_DIRECTORY: ::c_int = 65536; pub const O_DSYNC: ::c_int = 4096; pub const O_EXCL: ::c_int = 128; pub const O_LARGEFILE: ::c_int = 32768; pub const O_NOCTTY: ::c_int = 256; pub const O_NOFOLLOW: ::c_int = 131072; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const PF_FILE: ::c_int = 1; pub const PF_KCM: ::c_int = 41; pub const PF_MAX: ::c_int = 43; pub const PF_QIPCRTR: ::c_int = 42; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGBUS: ::c_int = 7; pub const SIGCHLD: ::c_int = 17; pub const SIGCONT: ::c_int = 18; pub const SIGIO: ::c_int = 29; pub const SIGPOLL: ::c_int = 29; pub const SIGPROF: ::c_int = 27; pub const SIGPWR: ::c_int = 30; pub const SIGSTKFLT: ::c_int = 16; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const SIGSTOP: ::c_int = 19; pub const SIGSYS: ::c_int = 31; pub const SIGTSTP: ::c_int = 20; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGURG: ::c_int = 23; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGVTALRM: ::c_int = 26; pub const SIGWINCH: ::c_int = 28; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIG_SETMASK: ::c_int = 2; // FIXME check these pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_STREAM: ::c_int = 1; pub const SOL_CAIF: ::c_int = 278; pub const SOL_IUCV: ::c_int = 277; pub const SOL_KCM: ::c_int = 281; pub const SOL_NFC: ::c_int = 280; pub const SOL_PNPIPE: ::c_int = 275; pub const SOL_PPPOL2TP: ::c_int = 273; pub const SOL_RDS: ::c_int = 276; pub const SOL_RXRPC: ::c_int = 272; pub const SYS3264_fadvise64: ::c_int = 223; pub const SYS3264_fcntl: ::c_int = 25; pub const SYS3264_fstatat: ::c_int = 79; pub const SYS3264_fstat: ::c_int = 80; pub const SYS3264_fstatfs: ::c_int = 44; pub const SYS3264_ftruncate: ::c_int = 46; pub const SYS3264_lseek: ::c_int = 62; pub const SYS3264_lstat: ::c_int = 1039; pub const SYS3264_mmap: ::c_int = 222; pub const SYS3264_sendfile: ::c_int = 71; pub const SYS3264_stat: ::c_int = 1038; pub const SYS3264_statfs: ::c_int = 43; pub const SYS3264_truncate: ::c_int = 45; pub const SYS_accept4: ::c_int = 242; pub const SYS_accept: ::c_int = 202; pub const SYS_access: ::c_int = 1033; pub const SYS_acct: ::c_int = 89; pub const SYS_add_key: ::c_int = 217; pub const SYS_adjtimex: ::c_int = 171; pub const SYS_alarm: ::c_int = 1059; pub const SYS_arch_specific_syscall: ::c_int = 244; pub const SYS_bdflush: ::c_int = 1075; pub const SYS_bind: ::c_int = 200; pub const SYS_bpf: ::c_int = 280; pub const SYS_brk: ::c_int = 214; pub const SYS_capget: ::c_int = 90; pub const SYS_capset: ::c_int = 91; pub const SYS_chdir: ::c_int = 49; pub const SYS_chmod: ::c_int = 1028; pub const SYS_chown: ::c_int = 1029; pub const SYS_chroot: ::c_int = 51; pub const SYS_clock_adjtime: ::c_int = 266; pub const SYS_clock_getres: ::c_int = 114; pub const SYS_clock_gettime: ::c_int = 113; pub const SYS_clock_nanosleep: ::c_int = 115; pub const SYS_clock_settime: ::c_int = 112; pub const SYS_clone: ::c_int = 220; pub const SYS_close: ::c_int = 57; pub const SYS_connect: ::c_int = 203; pub const SYS_copy_file_range: ::c_int = -1; // FIXME pub const SYS_creat: ::c_int = 1064; pub const SYS_delete_module: ::c_int = 106; pub const SYS_dup2: ::c_int = 1041; pub const SYS_dup3: ::c_int = 24; pub const SYS_dup: ::c_int = 23; pub const SYS_epoll_create1: ::c_int = 20; pub const SYS_epoll_create: ::c_int = 1042; pub const SYS_epoll_ctl: ::c_int = 21; pub const SYS_epoll_pwait: ::c_int = 22; pub const SYS_epoll_wait: ::c_int = 1069; pub const SYS_eventfd2: ::c_int = 19; pub const SYS_eventfd: ::c_int = 1044; pub const SYS_execveat: ::c_int = 281; pub const SYS_execve: ::c_int = 221; pub const SYS_exit: ::c_int = 93; pub const SYS_exit_group: ::c_int = 94; pub const SYS_faccessat: ::c_int = 48; pub const SYS_fadvise64_64: ::c_int = 223; pub const SYS_fallocate: ::c_int = 47; pub const SYS_fanotify_init: ::c_int = 262; pub const SYS_fanotify_mark: ::c_int = 263; pub const SYS_fchdir: ::c_int = 50; pub const SYS_fchmodat: ::c_int = 53; pub const SYS_fchmod: ::c_int = 52; pub const SYS_fchownat: ::c_int = 54; pub const SYS_fchown: ::c_int = 55; pub const SYS_fcntl64: ::c_int = 25; pub const SYS_fcntl: ::c_int = 25; pub const SYS_fdatasync: ::c_int = 83; pub const SYS_fgetxattr: ::c_int = 10; pub const SYS_finit_module: ::c_int = 273; pub const SYS_flistxattr: ::c_int = 13; pub const SYS_flock: ::c_int = 32; pub const SYS_fork: ::c_int = 1079; pub const SYS_fremovexattr: ::c_int = 16; pub const SYS_fsetxattr: ::c_int = 7; pub const SYS_fstat64: ::c_int = 80; pub const SYS_fstatat64: ::c_int = 79; pub const SYS_fstatfs64: ::c_int = 44; pub const SYS_fstatfs: ::c_int = 44; pub const SYS_fsync: ::c_int = 82; pub const SYS_ftruncate64: ::c_int = 46; pub const SYS_ftruncate: ::c_int = 46; pub const SYS_futex: ::c_int = 98; pub const SYS_futimesat: ::c_int = 1066; pub const SYS_getcpu: ::c_int = 168; pub const SYS_getcwd: ::c_int = 17; pub const SYS_getdents64: ::c_int = 61; pub const SYS_getdents: ::c_int = 1065; pub const SYS_getegid: ::c_int = 177; pub const SYS_geteuid: ::c_int = 175; pub const SYS_getgid: ::c_int = 176; pub const SYS_getgroups: ::c_int = 158; pub const SYS_getitimer: ::c_int = 102; pub const SYS_get_mempolicy: ::c_int = 236; pub const SYS_getpeername: ::c_int = 205; pub const SYS_getpgid: ::c_int = 155; pub const SYS_getpgrp: ::c_int = 1060; pub const SYS_getpid: ::c_int = 172; pub const SYS_getppid: ::c_int = 173; pub const SYS_getpriority: ::c_int = 141; pub const SYS_getrandom: ::c_int = 278; pub const SYS_getresgid: ::c_int = 150; pub const SYS_getresuid: ::c_int = 148; pub const SYS_getrlimit: ::c_int = 163; pub const SYS_get_robust_list: ::c_int = 100; pub const SYS_getrusage: ::c_int = 165; pub const SYS_getsid: ::c_int = 156; pub const SYS_getsockname: ::c_int = 204; pub const SYS_getsockopt: ::c_int = 209; pub const SYS_gettid: ::c_int = 178; pub const SYS_gettimeofday: ::c_int = 169; pub const SYS_getuid: ::c_int = 174; pub const SYS_getxattr: ::c_int = 8; pub const SYS_init_module: ::c_int = 105; pub const SYS_inotify_add_watch: ::c_int = 27; pub const SYS_inotify_init1: ::c_int = 26; pub const SYS_inotify_init: ::c_int = 1043; pub const SYS_inotify_rm_watch: ::c_int = 28; pub const SYS_io_cancel: ::c_int = 3; pub const SYS_ioctl: ::c_int = 29; pub const SYS_io_destroy: ::c_int = 1; pub const SYS_io_getevents: ::c_int = 4; pub const SYS_ioprio_get: ::c_int = 31; pub const SYS_ioprio_set: ::c_int = 30; pub const SYS_io_setup: ::c_int = 0; pub const SYS_io_submit: ::c_int = 2; pub const SYS_kcmp: ::c_int = 272; pub const SYS_kexec_load: ::c_int = 104; pub const SYS_keyctl: ::c_int = 219; pub const SYS_kill: ::c_int = 129; pub const SYS_lchown: ::c_int = 1032; pub const SYS_lgetxattr: ::c_int = 9; pub const SYS_linkat: ::c_int = 37; pub const SYS_link: ::c_int = 1025; pub const SYS_listen: ::c_int = 201; pub const SYS_listxattr: ::c_int = 11; pub const SYS_llistxattr: ::c_int = 12; pub const SYS__llseek: ::c_int = 62; pub const SYS_lookup_dcookie: ::c_int = 18; pub const SYS_lremovexattr: ::c_int = 15; pub const SYS_lseek: ::c_int = 62; pub const SYS_lsetxattr: ::c_int = 6; pub const SYS_lstat64: ::c_int = 1039; pub const SYS_lstat: ::c_int = 1039; pub const SYS_madvise: ::c_int = 233; pub const SYS_mbind: ::c_int = 235; pub const SYS_memfd_create: ::c_int = 279; pub const SYS_migrate_pages: ::c_int = 238; pub const SYS_mincore: ::c_int = 232; pub const SYS_mkdirat: ::c_int = 34; pub const SYS_mkdir: ::c_int = 1030; pub const SYS_mknodat: ::c_int = 33; pub const SYS_mknod: ::c_int = 1027; pub const SYS_mlockall: ::c_int = 230; pub const SYS_mlock: ::c_int = 228; pub const SYS_mmap2: ::c_int = 222; pub const SYS_mount: ::c_int = 40; pub const SYS_move_pages: ::c_int = 239; pub const SYS_mprotect: ::c_int = 226; pub const SYS_mq_getsetattr: ::c_int = 185; pub const SYS_mq_notify: ::c_int = 184; pub const SYS_mq_open: ::c_int = 180; pub const SYS_mq_timedreceive: ::c_int = 183; pub const SYS_mq_timedsend: ::c_int = 182; pub const SYS_mq_unlink: ::c_int = 181; pub const SYS_mremap: ::c_int = 216; pub const SYS_msgctl: ::c_int = 187; pub const SYS_msgget: ::c_int = 186; pub const SYS_msgrcv: ::c_int = 188; pub const SYS_msgsnd: ::c_int = 189; pub const SYS_msync: ::c_int = 227; pub const SYS_munlockall: ::c_int = 231; pub const SYS_munlock: ::c_int = 229; pub const SYS_munmap: ::c_int = 215; pub const SYS_name_to_handle_at: ::c_int = 264; pub const SYS_nanosleep: ::c_int = 101; pub const SYS_newfstatat: ::c_int = 79; pub const SYS_nfsservctl: ::c_int = 42; pub const SYS_oldwait4: ::c_int = 1072; pub const SYS_openat: ::c_int = 56; pub const SYS_open_by_handle_at: ::c_int = 265; pub const SYS_open: ::c_int = 1024; pub const SYS_pause: ::c_int = 1061; pub const SYS_perf_event_open: ::c_int = 241; pub const SYS_personality: ::c_int = 92; pub const SYS_pipe2: ::c_int = 59; pub const SYS_pipe: ::c_int = 1040; pub const SYS_pivot_root: ::c_int = 41; pub const SYS_poll: ::c_int = 1068; pub const SYS_ppoll: ::c_int = 73; pub const SYS_prctl: ::c_int = 167; pub const SYS_pread64: ::c_int = 67; pub const SYS_preadv: ::c_int = 69; pub const SYS_prlimit64: ::c_int = 261; pub const SYS_process_vm_readv: ::c_int = 270; pub const SYS_process_vm_writev: ::c_int = 271; pub const SYS_pselect6: ::c_int = 72; pub const SYS_ptrace: ::c_int = 117; pub const SYS_pwrite64: ::c_int = 68; pub const SYS_pwritev: ::c_int = 70; pub const SYS_quotactl: ::c_int = 60; pub const SYS_readahead: ::c_int = 213; pub const SYS_read: ::c_int = 63; pub const SYS_readlinkat: ::c_int = 78; pub const SYS_readlink: ::c_int = 1035; pub const SYS_readv: ::c_int = 65; pub const SYS_reboot: ::c_int = 142; pub const SYS_recv: ::c_int = 1073; pub const SYS_recvfrom: ::c_int = 207; pub const SYS_recvmmsg: ::c_int = 243; pub const SYS_recvmsg: ::c_int = 212; pub const SYS_remap_file_pages: ::c_int = 234; pub const SYS_removexattr: ::c_int = 14; pub const SYS_renameat2: ::c_int = 276; pub const SYS_renameat: ::c_int = 38; pub const SYS_rename: ::c_int = 1034; pub const SYS_request_key: ::c_int = 218; pub const SYS_restart_syscall: ::c_int = 128; pub const SYS_rmdir: ::c_int = 1031; pub const SYS_rt_sigaction: ::c_int = 134; pub const SYS_rt_sigpending: ::c_int = 136; pub const SYS_rt_sigprocmask: ::c_int = 135; pub const SYS_rt_sigqueueinfo: ::c_int = 138; pub const SYS_rt_sigreturn: ::c_int = 139; pub const SYS_rt_sigsuspend: ::c_int = 133; pub const SYS_rt_sigtimedwait: ::c_int = 137; pub const SYS_rt_tgsigqueueinfo: ::c_int = 240; pub const SYS_sched_getaffinity: ::c_int = 123; pub const SYS_sched_getattr: ::c_int = 275; pub const SYS_sched_getparam: ::c_int = 121; pub const SYS_sched_get_priority_max: ::c_int = 125; pub const SYS_sched_get_priority_min: ::c_int = 126; pub const SYS_sched_getscheduler: ::c_int = 120; pub const SYS_sched_rr_get_interval: ::c_int = 127; pub const SYS_sched_setaffinity: ::c_int = 122; pub const SYS_sched_setattr: ::c_int = 274; pub const SYS_sched_setparam: ::c_int = 118; pub const SYS_sched_setscheduler: ::c_int = 119; pub const SYS_sched_yield: ::c_int = 124; pub const SYS_seccomp: ::c_int = 277; pub const SYS_select: ::c_int = 1067; pub const SYS_semctl: ::c_int = 191; pub const SYS_semget: ::c_int = 190; pub const SYS_semop: ::c_int = 193; pub const SYS_semtimedop: ::c_int = 192; pub const SYS_send: ::c_int = 1074; pub const SYS_sendfile64: ::c_int = 71; pub const SYS_sendfile: ::c_int = 71; pub const SYS_sendmmsg: ::c_int = 269; pub const SYS_sendmsg: ::c_int = 211; pub const SYS_sendto: ::c_int = 206; pub const SYS_setdomainname: ::c_int = 162; pub const SYS_setfsgid: ::c_int = 152; pub const SYS_setfsuid: ::c_int = 151; pub const SYS_setgid: ::c_int = 144; pub const SYS_setgroups: ::c_int = 159; pub const SYS_sethostname: ::c_int = 161; pub const SYS_setitimer: ::c_int = 103; pub const SYS_set_mempolicy: ::c_int = 237; pub const SYS_setns: ::c_int = 268; pub const SYS_setpgid: ::c_int = 154; pub const SYS_setpriority: ::c_int = 140; pub const SYS_setregid: ::c_int = 143; pub const SYS_setresgid: ::c_int = 149; pub const SYS_setresuid: ::c_int = 147; pub const SYS_setreuid: ::c_int = 145; pub const SYS_setrlimit: ::c_int = 164; pub const SYS_set_robust_list: ::c_int = 99; pub const SYS_setsid: ::c_int = 157; pub const SYS_setsockopt: ::c_int = 208; pub const SYS_set_tid_address: ::c_int = 96; pub const SYS_settimeofday: ::c_int = 170; pub const SYS_setuid: ::c_int = 146; pub const SYS_setxattr: ::c_int = 5; pub const SYS_shmat: ::c_int = 196; pub const SYS_shmctl: ::c_int = 195; pub const SYS_shmdt: ::c_int = 197; pub const SYS_shmget: ::c_int = 194; pub const SYS_shutdown: ::c_int = 210; pub const SYS_sigaltstack: ::c_int = 132; pub const SYS_signalfd4: ::c_int = 74; pub const SYS_signalfd: ::c_int = 1045; pub const SYS_socket: ::c_int = 198; pub const SYS_socketpair: ::c_int = 199; pub const SYS_splice: ::c_int = 76; pub const SYS_stat64: ::c_int = 1038; pub const SYS_stat: ::c_int = 1038; pub const SYS_statfs64: ::c_int = 43; pub const SYS_swapoff: ::c_int = 225; pub const SYS_swapon: ::c_int = 224; pub const SYS_symlinkat: ::c_int = 36; pub const SYS_symlink: ::c_int = 1036; pub const SYS_sync: ::c_int = 81; pub const SYS_sync_file_range2: ::c_int = 84; pub const SYS_sync_file_range: ::c_int = 84; pub const SYS_syncfs: ::c_int = 267; pub const SYS_syscalls: ::c_int = 1080; pub const SYS__sysctl: ::c_int = 1078; pub const SYS_sysinfo: ::c_int = 179; pub const SYS_syslog: ::c_int = 116; pub const SYS_tee: ::c_int = 77; pub const SYS_tgkill: ::c_int = 131; pub const SYS_time: ::c_int = 1062; pub const SYS_timer_create: ::c_int = 107; pub const SYS_timer_delete: ::c_int = 111; pub const SYS_timerfd_create: ::c_int = 85; pub const SYS_timerfd_gettime: ::c_int = 87; pub const SYS_timerfd_settime: ::c_int = 86; pub const SYS_timer_getoverrun: ::c_int = 109; pub const SYS_timer_gettime: ::c_int = 108; pub const SYS_timer_settime: ::c_int = 110; pub const SYS_times: ::c_int = 153; pub const SYS_tkill: ::c_int = 130; pub const SYS_truncate64: ::c_int = 45; pub const SYS_truncate: ::c_int = 45; pub const SYS_umask: ::c_int = 166; pub const SYS_umount2: ::c_int = 39; pub const SYS_umount: ::c_int = 1076; pub const SYS_uname: ::c_int = 160; pub const SYS_unlinkat: ::c_int = 35; pub const SYS_unlink: ::c_int = 1026; pub const SYS_unshare: ::c_int = 97; pub const SYS_uselib: ::c_int = 1077; pub const SYS_ustat: ::c_int = 1070; pub const SYS_utime: ::c_int = 1063; pub const SYS_utimensat: ::c_int = 88; pub const SYS_utimes: ::c_int = 1037; pub const SYS_vfork: ::c_int = 1071; pub const SYS_vhangup: ::c_int = 58; pub const SYS_vmsplice: ::c_int = 75; pub const SYS_wait4: ::c_int = 260; pub const SYS_waitid: ::c_int = 95; pub const SYS_write: ::c_int = 64; pub const SYS_writev: ::c_int = 66; pub const SYS_statx: ::c_int = 291; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const TIOCM_LOOP: ::c_int = 32768; pub const TIOCM_OUT1: ::c_int = 8192; pub const TIOCM_OUT2: ::c_int = 16384; pub const TIOCSER_TEMT: ::c_int = 1; pub const TOSTOP: ::c_int = 256; pub const VEOF: ::c_int = 4; pub const VEOL2: ::c_int = 16; pub const VEOL: ::c_int = 11; pub const VMIN: ::c_int = 6; libc/src/unix/linux_like/linux/musl/b32/riscv32/0000775000175000017500000000000014661133735022371 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs0000644000175000017500000006706314661133735023530 0ustar jamespagejamespage//! RISC-V-specific definitions for 32-bit linux-like values pub type c_char = u8; pub type wchar_t = ::c_int; s! { pub struct pthread_attr_t { __size: [::c_ulong; 7], } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2usize], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused5: ::c_ulong, __unused6: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __unused1: ::c_int, pub msg_rtime: ::time_t, __unused2: ::c_int, pub msg_ctime: ::time_t, __unused3: ::c_int, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } } //pub const RLIM_INFINITY: ::rlim_t = !0; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const TIOCGSOFTCAR: ::c_ulong = 21529; pub const TIOCSSOFTCAR: ::c_ulong = 21530; pub const TIOCGRS485: ::c_int = 21550; pub const TIOCSRS485: ::c_int = 21551; //pub const RLIMIT_RSS: ::__rlimit_resource_t = 5; //pub const RLIMIT_AS: ::__rlimit_resource_t = 9; //pub const RLIMIT_MEMLOCK: ::__rlimit_resource_t = 8; //pub const RLIMIT_NOFILE: ::__rlimit_resource_t = 7; //pub const RLIMIT_NPROC: ::__rlimit_resource_t = 6; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 1052672; pub const MAP_GROWSDOWN: ::c_int = 256; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 8; pub const SA_SIGINFO: ::c_int = 4; pub const SA_NOCLDWAIT: ::c_int = 2; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const POLLWRNORM: ::c_short = 256; pub const POLLWRBAND: ::c_short = 512; pub const O_ASYNC: ::c_int = 8192; pub const O_NDELAY: ::c_int = 2048; pub const EFD_NONBLOCK: ::c_int = 2048; pub const F_SETOWN: ::c_int = 8; pub const F_GETOWN: ::c_int = 9; pub const F_GETLK: ::c_int = 12; pub const F_SETLK: ::c_int = 13; pub const F_SETLKW: ::c_int = 14; pub const SFD_NONBLOCK: ::c_int = 2048; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const TIOCLINUX: ::c_ulong = 21532; pub const TIOCGSERIAL: ::c_ulong = 21534; pub const TIOCEXCL: ::c_ulong = 21516; pub const TIOCNXCL: ::c_ulong = 21517; pub const TIOCSCTTY: ::c_ulong = 21518; pub const TIOCSTI: ::c_ulong = 21522; pub const TIOCMGET: ::c_ulong = 21525; pub const TIOCMBIS: ::c_ulong = 21526; pub const TIOCMBIC: ::c_ulong = 21527; pub const TIOCMSET: ::c_ulong = 21528; pub const TIOCCONS: ::c_ulong = 21533; pub const TIOCM_ST: ::c_int = 8; pub const TIOCM_SR: ::c_int = 16; pub const TIOCM_CTS: ::c_int = 32; pub const TIOCM_CAR: ::c_int = 64; pub const TIOCM_RNG: ::c_int = 128; pub const TIOCM_DSR: ::c_int = 256; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const O_DIRECT: ::c_int = 16384; pub const O_DIRECTORY: ::c_int = 65536; pub const O_LARGEFILE: ::c_int = 0o0100000; pub const O_NOFOLLOW: ::c_int = 131072; pub const MAP_HUGETLB: ::c_int = 262144; pub const MAP_LOCKED: ::c_int = 8192; pub const MAP_NORESERVE: ::c_int = 16384; pub const MAP_ANON: ::c_int = 32; pub const MAP_ANONYMOUS: ::c_int = 32; pub const MAP_DENYWRITE: ::c_int = 2048; pub const MAP_EXECUTABLE: ::c_int = 4096; pub const MAP_POPULATE: ::c_int = 32768; pub const MAP_NONBLOCK: ::c_int = 65536; pub const MAP_STACK: ::c_int = 131072; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const FIOCLEX: ::c_int = 21585; pub const FIONCLEX: ::c_int = 21584; pub const FIONBIO: ::c_int = 21537; pub const MCL_CURRENT: ::c_int = 1; pub const MCL_FUTURE: ::c_int = 2; pub const MCL_ONFAULT: ::c_int = 4; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 4111; pub const TAB1: ::tcflag_t = 2048; pub const TAB2: ::tcflag_t = 4096; pub const TAB3: ::tcflag_t = 6144; pub const CR1: ::tcflag_t = 512; pub const CR2: ::tcflag_t = 1024; pub const CR3: ::tcflag_t = 1536; pub const FF1: ::tcflag_t = 32768; pub const BS1: ::tcflag_t = 8192; pub const VT1: ::tcflag_t = 16384; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 1024; pub const IXOFF: ::tcflag_t = 4096; pub const ONLCR: ::tcflag_t = 4; pub const CSIZE: ::tcflag_t = 48; pub const CS6: ::tcflag_t = 16; pub const CS7: ::tcflag_t = 32; pub const CS8: ::tcflag_t = 48; pub const CSTOPB: ::tcflag_t = 64; pub const CREAD: ::tcflag_t = 128; pub const PARENB: ::tcflag_t = 256; pub const PARODD: ::tcflag_t = 512; pub const HUPCL: ::tcflag_t = 1024; pub const CLOCAL: ::tcflag_t = 2048; pub const ECHOKE: ::tcflag_t = 2048; pub const ECHOE: ::tcflag_t = 16; pub const ECHOK: ::tcflag_t = 32; pub const ECHONL: ::tcflag_t = 64; pub const ECHOPRT: ::tcflag_t = 1024; pub const ECHOCTL: ::tcflag_t = 512; pub const ISIG: ::tcflag_t = 1; pub const ICANON: ::tcflag_t = 2; pub const PENDIN: ::tcflag_t = 16384; pub const NOFLSH: ::tcflag_t = 128; pub const CIBAUD: ::tcflag_t = 269418496; pub const CBAUDEX: ::tcflag_t = 4096; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 2; pub const NLDLY: ::tcflag_t = 256; pub const CRDLY: ::tcflag_t = 1536; pub const TABDLY: ::tcflag_t = 6144; pub const BSDLY: ::tcflag_t = 8192; pub const FFDLY: ::tcflag_t = 32768; pub const VTDLY: ::tcflag_t = 16384; pub const XTABS: ::tcflag_t = 6144; pub const B0: ::speed_t = 0; pub const B50: ::speed_t = 1; pub const B75: ::speed_t = 2; pub const B110: ::speed_t = 3; pub const B134: ::speed_t = 4; pub const B150: ::speed_t = 5; pub const B200: ::speed_t = 6; pub const B300: ::speed_t = 7; pub const B600: ::speed_t = 8; pub const B1200: ::speed_t = 9; pub const B1800: ::speed_t = 10; pub const B2400: ::speed_t = 11; pub const B4800: ::speed_t = 12; pub const B9600: ::speed_t = 13; pub const B19200: ::speed_t = 14; pub const B38400: ::speed_t = 15; pub const EXTA: ::speed_t = 14; pub const EXTB: ::speed_t = 15; pub const B57600: ::speed_t = 4097; pub const B115200: ::speed_t = 4098; pub const B230400: ::speed_t = 4099; pub const B460800: ::speed_t = 4100; pub const B500000: ::speed_t = 4101; pub const B576000: ::speed_t = 4102; pub const B921600: ::speed_t = 4103; pub const B1000000: ::speed_t = 4104; pub const B1152000: ::speed_t = 4105; pub const B1500000: ::speed_t = 4106; pub const B2000000: ::speed_t = 4107; pub const B2500000: ::speed_t = 4108; pub const B3000000: ::speed_t = 4109; pub const B3500000: ::speed_t = 4110; pub const B4000000: ::speed_t = 4111; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 32768; pub const TOSTOP: ::tcflag_t = 256; pub const FLUSHO: ::tcflag_t = 4096; pub const EXTPROC: ::tcflag_t = 65536; pub const TCGETS: ::c_int = 21505; pub const TCSETS: ::c_int = 21506; pub const TCSETSW: ::c_int = 21507; pub const TCSETSF: ::c_int = 21508; pub const TCGETA: ::c_int = 21509; pub const TCSETA: ::c_int = 21510; pub const TCSETAW: ::c_int = 21511; pub const TCSETAF: ::c_int = 21512; pub const TCSBRK: ::c_int = 21513; pub const TCXONC: ::c_int = 21514; pub const TCFLSH: ::c_int = 21515; pub const TIOCINQ: ::c_int = 21531; pub const TIOCGPGRP: ::c_int = 21519; pub const TIOCSPGRP: ::c_int = 21520; pub const TIOCOUTQ: ::c_int = 21521; pub const TIOCGWINSZ: ::c_int = 21523; pub const TIOCSWINSZ: ::c_int = 21524; pub const FIONREAD: ::c_int = 21531; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_close: ::c_long = 57; pub const SYS_fstat: ::c_long = 80; pub const SYS_lseek: ::c_long = 62; pub const SYS_mmap: ::c_long = 222; pub const SYS_mprotect: ::c_long = 226; pub const SYS_munmap: ::c_long = 215; pub const SYS_brk: ::c_long = 214; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_ioctl: ::c_long = 29; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_mremap: ::c_long = 216; pub const SYS_msync: ::c_long = 227; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmctl: ::c_long = 195; pub const SYS_dup: ::c_long = 23; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_getpid: ::c_long = 172; pub const SYS_sendfile: ::c_long = 71; pub const SYS_socket: ::c_long = 198; pub const SYS_connect: ::c_long = 203; pub const SYS_accept: ::c_long = 202; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_shutdown: ::c_long = 210; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_socketpair: ::c_long = 199; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_exit: ::c_long = 93; pub const SYS_wait4: ::c_long = 260; pub const SYS_kill: ::c_long = 129; pub const SYS_uname: ::c_long = 160; pub const SYS_semget: ::c_long = 190; pub const SYS_semop: ::c_long = 193; pub const SYS_semctl: ::c_long = 191; pub const SYS_shmdt: ::c_long = 197; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgctl: ::c_long = 187; pub const SYS_fcntl: ::c_long = 25; pub const SYS_flock: ::c_long = 32; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_getcwd: ::c_long = 17; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchown: ::c_long = 55; pub const SYS_umask: ::c_long = 166; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_getrusage: ::c_long = 165; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_times: ::c_long = 153; pub const SYS_ptrace: ::c_long = 117; pub const SYS_getuid: ::c_long = 174; pub const SYS_syslog: ::c_long = 116; pub const SYS_getgid: ::c_long = 176; pub const SYS_setuid: ::c_long = 146; pub const SYS_setgid: ::c_long = 144; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getegid: ::c_long = 177; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getppid: ::c_long = 173; pub const SYS_setsid: ::c_long = 157; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setregid: ::c_long = 143; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_getpgid: ::c_long = 155; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_getsid: ::c_long = 156; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_personality: ::c_long = 92; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_getpriority: ::c_long = 141; pub const SYS_setpriority: ::c_long = 140; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_prctl: ::c_long = 167; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_chroot: ::c_long = 51; pub const SYS_sync: ::c_long = 81; pub const SYS_acct: ::c_long = 89; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_mount: ::c_long = 40; pub const SYS_umount2: ::c_long = 39; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_reboot: ::c_long = 142; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_quotactl: ::c_long = 60; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_gettid: ::c_long = 178; pub const SYS_readahead: ::c_long = 213; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_tkill: ::c_long = 130; pub const SYS_futex: ::c_long = 98; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_getdents64: ::c_long = 61; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_fadvise64: ::c_long = 223; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_exit_group: ::c_long = 94; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_tgkill: ::c_long = 131; pub const SYS_mbind: ::c_long = 235; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_waitid: ::c_long = 95; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_openat: ::c_long = 56; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_mknodat: ::c_long = 33; pub const SYS_fchownat: ::c_long = 54; pub const SYS_newfstatat: ::c_long = 79; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_linkat: ::c_long = 37; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_faccessat: ::c_long = 48; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_unshare: ::c_long = 97; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_move_pages: ::c_long = 239; pub const SYS_utimensat: ::c_long = 88; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_fallocate: ::c_long = 47; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_accept4: ::c_long = 242; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_dup3: ::c_long = 24; pub const SYS_pipe2: ::c_long = 59; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_setns: ::c_long = 268; pub const SYS_getcpu: ::c_long = 168; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/musl/b32/riscv32/align.rs0000644000175000017500000000022614661133735024027 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: (i64, f64) } } libc/src/unix/linux_like/linux/musl/b32/mod.rs0000644000175000017500000000313314661133735022221 0ustar jamespagejamespagepub type c_long = i32; pub type c_ulong = u32; pub type nlink_t = u32; pub type blksize_t = ::c_long; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; pub type regoff_t = ::c_int; s! { pub struct pthread_attr_t { __size: [u32; 9] } pub struct sigset_t { __val: [::c_ulong; 32], } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct sem_t { __val: [::c_int; 4], } } pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; cfg_if! { if #[cfg(any(target_arch = "x86"))] { mod x86; pub use self::x86::*; } else if #[cfg(any(target_arch = "mips"))] { mod mips; pub use self::mips::*; } else if #[cfg(any(target_arch = "arm"))] { mod arm; pub use self::arm::*; } else if #[cfg(any(target_arch = "powerpc"))] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(any(target_arch = "hexagon"))] { mod hexagon; pub use self::hexagon::*; } else if #[cfg(any(target_arch = "riscv32"))] { mod riscv32; pub use self::riscv32::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/musl/b32/x86/0000775000175000017500000000000014661133735021523 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b32/x86/mod.rs0000644000175000017500000010333614661133735022654 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: ::dev_t, __st_dev_padding: ::c_int, __st_ino_truncated: ::c_long, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_rdev_padding: ::c_int, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino_t, } pub struct stat64 { pub st_dev: ::dev_t, __st_dev_padding: ::c_int, __st_ino_truncated: ::c_long, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_rdev_padding: ::c_int, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino_t, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __unused1: ::c_long, __unused2: ::c_long } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_int, pub shm_dtime: ::time_t, __unused2: ::c_int, pub shm_ctime: ::time_t, __unused3: ::c_int, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __unused1: ::c_int, pub msg_rtime: ::time_t, __unused2: ::c_int, pub msg_ctime: ::time_t, __unused3: ::c_int, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct mcontext_t { __private: [u32; 22] } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } } s_no_extra_traits! { pub struct user_fpxregs_struct { pub cwd: ::c_ushort, pub swd: ::c_ushort, pub twd: ::c_ushort, pub fop: ::c_ushort, pub fip: ::c_long, pub fcs: ::c_long, pub foo: ::c_long, pub fos: ::c_long, pub mxcsr: ::c_long, __reserved: ::c_long, pub st_space: [::c_long; 32], pub xmm_space: [::c_long; 32], padding: [::c_long; 56], } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: ::sigset_t, __private: [u8; 112], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpxregs_struct { fn eq(&self, other: &user_fpxregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.twd == other.twd && self.fop == other.fop && self.fip == other.fip && self.fcs == other.fcs && self.foo == other.foo && self.fos == other.fos && self.mxcsr == other.mxcsr // Ignore __reserved field && self.st_space == other.st_space && self.xmm_space == other.xmm_space // Ignore padding field } } impl Eq for user_fpxregs_struct {} impl ::fmt::Debug for user_fpxregs_struct { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("user_fpxregs_struct") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("twd", &self.twd) .field("fop", &self.fop) .field("fip", &self.fip) .field("fcs", &self.fcs) .field("foo", &self.foo) .field("fos", &self.fos) .field("mxcsr", &self.mxcsr) // Ignore __reserved field .field("st_space", &self.st_space) .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl ::hash::Hash for user_fpxregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.twd.hash(state); self.fop.hash(state); self.fip.hash(state); self.fcs.hash(state); self.foo.hash(state); self.fos.hash(state); self.mxcsr.hash(state); // Ignore __reserved field self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask && self .__private .iter() .zip(other.__private.iter()) .all(|(a,b)| a == b) } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); self.__private.hash(state); } } } } pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_LARGEFILE: ::c_int = 0o0100000; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_SYNC: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_32BIT: ::c_int = 0x0040; pub const F_GETLK: ::c_int = 12; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 13; pub const F_SETLKW: ::c_int = 14; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const PTRACE_SYSEMU: ::c_int = 31; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_int = 32; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_break: ::c_long = 17; pub const SYS_oldstat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_stime: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_oldfstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_stty: ::c_long = 31; pub const SYS_gtty: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_ftime: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_prof: ::c_long = 44; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_lock: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_mpx: ::c_long = 56; pub const SYS_setpgid: ::c_long = 57; pub const SYS_ulimit: ::c_long = 58; pub const SYS_oldolduname: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_oldlstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_profil: ::c_long = 98; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_ioperm: ::c_long = 101; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_olduname: ::c_long = 109; pub const SYS_iopl: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_vm86old: ::c_long = 113; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_modify_ldt: ::c_long = 123; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_vm86: ::c_long = 166; pub const SYS_query_module: ::c_long = 167; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid: ::c_long = 170; pub const SYS_getresgid: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_chown: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_getpmsg: ::c_long = 188; pub const SYS_putpmsg: ::c_long = 189; pub const SYS_vfork: ::c_long = 190; pub const SYS_ugetrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_lchown32: ::c_long = 198; pub const SYS_getuid32: ::c_long = 199; pub const SYS_getgid32: ::c_long = 200; pub const SYS_geteuid32: ::c_long = 201; pub const SYS_getegid32: ::c_long = 202; pub const SYS_setreuid32: ::c_long = 203; pub const SYS_setregid32: ::c_long = 204; pub const SYS_getgroups32: ::c_long = 205; pub const SYS_setgroups32: ::c_long = 206; pub const SYS_fchown32: ::c_long = 207; pub const SYS_setresuid32: ::c_long = 208; pub const SYS_getresuid32: ::c_long = 209; pub const SYS_setresgid32: ::c_long = 210; pub const SYS_getresgid32: ::c_long = 211; pub const SYS_chown32: ::c_long = 212; pub const SYS_setuid32: ::c_long = 213; pub const SYS_setgid32: ::c_long = 214; pub const SYS_setfsuid32: ::c_long = 215; pub const SYS_setfsgid32: ::c_long = 216; pub const SYS_pivot_root: ::c_long = 217; pub const SYS_mincore: ::c_long = 218; pub const SYS_madvise: ::c_long = 219; pub const SYS_getdents64: ::c_long = 220; pub const SYS_fcntl64: ::c_long = 221; pub const SYS_gettid: ::c_long = 224; pub const SYS_readahead: ::c_long = 225; pub const SYS_setxattr: ::c_long = 226; pub const SYS_lsetxattr: ::c_long = 227; pub const SYS_fsetxattr: ::c_long = 228; pub const SYS_getxattr: ::c_long = 229; pub const SYS_lgetxattr: ::c_long = 230; pub const SYS_fgetxattr: ::c_long = 231; pub const SYS_listxattr: ::c_long = 232; pub const SYS_llistxattr: ::c_long = 233; pub const SYS_flistxattr: ::c_long = 234; pub const SYS_removexattr: ::c_long = 235; pub const SYS_lremovexattr: ::c_long = 236; pub const SYS_fremovexattr: ::c_long = 237; pub const SYS_tkill: ::c_long = 238; pub const SYS_sendfile64: ::c_long = 239; pub const SYS_futex: ::c_long = 240; pub const SYS_sched_setaffinity: ::c_long = 241; pub const SYS_sched_getaffinity: ::c_long = 242; pub const SYS_set_thread_area: ::c_long = 243; pub const SYS_get_thread_area: ::c_long = 244; pub const SYS_io_setup: ::c_long = 245; pub const SYS_io_destroy: ::c_long = 246; pub const SYS_io_getevents: ::c_long = 247; pub const SYS_io_submit: ::c_long = 248; pub const SYS_io_cancel: ::c_long = 249; pub const SYS_fadvise64: ::c_long = 250; pub const SYS_exit_group: ::c_long = 252; pub const SYS_lookup_dcookie: ::c_long = 253; pub const SYS_epoll_create: ::c_long = 254; pub const SYS_epoll_ctl: ::c_long = 255; pub const SYS_epoll_wait: ::c_long = 256; pub const SYS_remap_file_pages: ::c_long = 257; pub const SYS_set_tid_address: ::c_long = 258; pub const SYS_timer_create: ::c_long = 259; pub const SYS_timer_settime: ::c_long = 260; pub const SYS_timer_gettime: ::c_long = 261; pub const SYS_timer_getoverrun: ::c_long = 262; pub const SYS_timer_delete: ::c_long = 263; pub const SYS_clock_settime: ::c_long = 264; pub const SYS_clock_gettime: ::c_long = 265; pub const SYS_clock_getres: ::c_long = 266; pub const SYS_clock_nanosleep: ::c_long = 267; pub const SYS_statfs64: ::c_long = 268; pub const SYS_fstatfs64: ::c_long = 269; pub const SYS_tgkill: ::c_long = 270; pub const SYS_utimes: ::c_long = 271; pub const SYS_fadvise64_64: ::c_long = 272; pub const SYS_vserver: ::c_long = 273; pub const SYS_mbind: ::c_long = 274; pub const SYS_get_mempolicy: ::c_long = 275; pub const SYS_set_mempolicy: ::c_long = 276; pub const SYS_mq_open: ::c_long = 277; pub const SYS_mq_unlink: ::c_long = 278; pub const SYS_mq_timedsend: ::c_long = 279; pub const SYS_mq_timedreceive: ::c_long = 280; pub const SYS_mq_notify: ::c_long = 281; pub const SYS_mq_getsetattr: ::c_long = 282; pub const SYS_kexec_load: ::c_long = 283; pub const SYS_waitid: ::c_long = 284; pub const SYS_add_key: ::c_long = 286; pub const SYS_request_key: ::c_long = 287; pub const SYS_keyctl: ::c_long = 288; pub const SYS_ioprio_set: ::c_long = 289; pub const SYS_ioprio_get: ::c_long = 290; pub const SYS_inotify_init: ::c_long = 291; pub const SYS_inotify_add_watch: ::c_long = 292; pub const SYS_inotify_rm_watch: ::c_long = 293; pub const SYS_migrate_pages: ::c_long = 294; pub const SYS_openat: ::c_long = 295; pub const SYS_mkdirat: ::c_long = 296; pub const SYS_mknodat: ::c_long = 297; pub const SYS_fchownat: ::c_long = 298; pub const SYS_futimesat: ::c_long = 299; pub const SYS_fstatat64: ::c_long = 300; pub const SYS_unlinkat: ::c_long = 301; pub const SYS_renameat: ::c_long = 302; pub const SYS_linkat: ::c_long = 303; pub const SYS_symlinkat: ::c_long = 304; pub const SYS_readlinkat: ::c_long = 305; pub const SYS_fchmodat: ::c_long = 306; pub const SYS_faccessat: ::c_long = 307; pub const SYS_pselect6: ::c_long = 308; pub const SYS_ppoll: ::c_long = 309; pub const SYS_unshare: ::c_long = 310; pub const SYS_set_robust_list: ::c_long = 311; pub const SYS_get_robust_list: ::c_long = 312; pub const SYS_splice: ::c_long = 313; pub const SYS_sync_file_range: ::c_long = 314; pub const SYS_tee: ::c_long = 315; pub const SYS_vmsplice: ::c_long = 316; pub const SYS_move_pages: ::c_long = 317; pub const SYS_getcpu: ::c_long = 318; pub const SYS_epoll_pwait: ::c_long = 319; pub const SYS_utimensat: ::c_long = 320; pub const SYS_signalfd: ::c_long = 321; pub const SYS_timerfd_create: ::c_long = 322; pub const SYS_eventfd: ::c_long = 323; pub const SYS_fallocate: ::c_long = 324; pub const SYS_timerfd_settime: ::c_long = 325; pub const SYS_timerfd_gettime: ::c_long = 326; pub const SYS_signalfd4: ::c_long = 327; pub const SYS_eventfd2: ::c_long = 328; pub const SYS_epoll_create1: ::c_long = 329; pub const SYS_dup3: ::c_long = 330; pub const SYS_pipe2: ::c_long = 331; pub const SYS_inotify_init1: ::c_long = 332; pub const SYS_preadv: ::c_long = 333; pub const SYS_pwritev: ::c_long = 334; pub const SYS_rt_tgsigqueueinfo: ::c_long = 335; pub const SYS_perf_event_open: ::c_long = 336; pub const SYS_recvmmsg: ::c_long = 337; pub const SYS_fanotify_init: ::c_long = 338; pub const SYS_fanotify_mark: ::c_long = 339; pub const SYS_prlimit64: ::c_long = 340; pub const SYS_name_to_handle_at: ::c_long = 341; pub const SYS_open_by_handle_at: ::c_long = 342; pub const SYS_clock_adjtime: ::c_long = 343; pub const SYS_syncfs: ::c_long = 344; pub const SYS_sendmmsg: ::c_long = 345; pub const SYS_setns: ::c_long = 346; pub const SYS_process_vm_readv: ::c_long = 347; pub const SYS_process_vm_writev: ::c_long = 348; pub const SYS_kcmp: ::c_long = 349; pub const SYS_finit_module: ::c_long = 350; pub const SYS_sched_setattr: ::c_long = 351; pub const SYS_sched_getattr: ::c_long = 352; pub const SYS_renameat2: ::c_long = 353; pub const SYS_seccomp: ::c_long = 354; pub const SYS_getrandom: ::c_long = 355; pub const SYS_memfd_create: ::c_long = 356; pub const SYS_bpf: ::c_long = 357; pub const SYS_execveat: ::c_long = 358; pub const SYS_socket: ::c_long = 359; pub const SYS_socketpair: ::c_long = 360; pub const SYS_bind: ::c_long = 361; pub const SYS_connect: ::c_long = 362; pub const SYS_listen: ::c_long = 363; pub const SYS_accept4: ::c_long = 364; pub const SYS_getsockopt: ::c_long = 365; pub const SYS_setsockopt: ::c_long = 366; pub const SYS_getsockname: ::c_long = 367; pub const SYS_getpeername: ::c_long = 368; pub const SYS_sendto: ::c_long = 369; pub const SYS_sendmsg: ::c_long = 370; pub const SYS_recvfrom: ::c_long = 371; pub const SYS_recvmsg: ::c_long = 372; pub const SYS_shutdown: ::c_long = 373; pub const SYS_userfaultfd: ::c_long = 374; pub const SYS_membarrier: ::c_long = 375; pub const SYS_mlock2: ::c_long = 376; pub const SYS_copy_file_range: ::c_long = 377; pub const SYS_preadv2: ::c_long = 378; pub const SYS_pwritev2: ::c_long = 379; pub const SYS_pkey_mprotect: ::c_long = 380; pub const SYS_pkey_alloc: ::c_long = 381; pub const SYS_pkey_free: ::c_long = 382; pub const SYS_statx: ::c_long = 383; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; // offsets in user_regs_structs, from sys/reg.h pub const EBX: ::c_int = 0; pub const ECX: ::c_int = 1; pub const EDX: ::c_int = 2; pub const ESI: ::c_int = 3; pub const EDI: ::c_int = 4; pub const EBP: ::c_int = 5; pub const EAX: ::c_int = 6; pub const DS: ::c_int = 7; pub const ES: ::c_int = 8; pub const FS: ::c_int = 9; pub const GS: ::c_int = 10; pub const ORIG_EAX: ::c_int = 11; pub const EIP: ::c_int = 12; pub const CS: ::c_int = 13; pub const EFL: ::c_int = 14; pub const UESP: ::c_int = 15; pub const SS: ::c_int = 16; extern "C" { pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/musl/b32/x86/align.rs0000644000175000017500000000022414661133735023157 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f64; 3] } } libc/src/unix/linux_like/linux/musl/b32/mips/0000775000175000017500000000000014661133735022046 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b32/mips/mod.rs0000644000175000017500000007447214661133735023207 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = ::c_int; s! { pub struct stat { pub st_dev: ::dev_t, __st_padding1: [::c_long; 2], pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_padding2: [::c_long; 2], pub st_size: ::off_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, __st_padding3: ::c_long, pub st_blocks: ::blkcnt_t, __st_padding4: [::c_long; 14], } pub struct stat64 { pub st_dev: ::dev_t, __st_padding1: [::c_long; 2], pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __st_padding2: [::c_long; 2], pub st_size: ::off_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, __st_padding3: ::c_long, pub st_blocks: ::blkcnt64_t, __st_padding4: [::c_long; 14], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __unused1: ::c_long, __unused2: ::c_long } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, #[cfg(target_endian = "big")] __unused1: ::c_int, pub msg_stime: ::time_t, #[cfg(target_endian = "little")] __unused1: ::c_int, #[cfg(target_endian = "big")] __unused2: ::c_int, pub msg_rtime: ::time_t, #[cfg(target_endian = "little")] __unused2: ::c_int, #[cfg(target_endian = "big")] __unused3: ::c_int, pub msg_ctime: ::time_t, #[cfg(target_endian = "little")] __unused3: ::c_int, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 5], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 5], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, #[cfg(target_endian = "little")] pub f_fsid: ::c_ulong, __f_unused: ::c_int, #[cfg(target_endian = "big")] pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } } pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const O_DIRECT: ::c_int = 0o100000; pub const O_DIRECTORY: ::c_int = 0o200000; pub const O_NOFOLLOW: ::c_int = 0o400000; pub const O_ASYNC: ::c_int = 0o10000; pub const O_LARGEFILE: ::c_int = 0x2000; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const O_APPEND: ::c_int = 0o010; pub const O_CREAT: ::c_int = 0o400; pub const O_EXCL: ::c_int = 0o2000; pub const O_NOCTTY: ::c_int = 0o4000; pub const O_NONBLOCK: ::c_int = 0o200; pub const O_SYNC: ::c_int = 0o40020; pub const O_RSYNC: ::c_int = 0o40020; pub const O_DSYNC: ::c_int = 0o020; pub const MAP_ANON: ::c_int = 0x800; pub const MAP_GROWSDOWN: ::c_int = 0x1000; pub const MAP_DENYWRITE: ::c_int = 0x2000; pub const MAP_EXECUTABLE: ::c_int = 0x4000; pub const MAP_LOCKED: ::c_int = 0x8000; pub const MAP_NORESERVE: ::c_int = 0x0400; pub const MAP_POPULATE: ::c_int = 0x10000; pub const MAP_NONBLOCK: ::c_int = 0x20000; pub const MAP_STACK: ::c_int = 0x40000; pub const MAP_HUGETLB: ::c_int = 0x80000; pub const EDEADLK: ::c_int = 45; pub const ENAMETOOLONG: ::c_int = 78; pub const ENOLCK: ::c_int = 46; pub const ENOSYS: ::c_int = 89; pub const ENOTEMPTY: ::c_int = 93; pub const ELOOP: ::c_int = 90; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EBADE: ::c_int = 50; pub const EBADR: ::c_int = 51; pub const EXFULL: ::c_int = 52; pub const ENOANO: ::c_int = 53; pub const EBADRQC: ::c_int = 54; pub const EBADSLT: ::c_int = 55; pub const EDEADLOCK: ::c_int = 56; pub const EMULTIHOP: ::c_int = 74; pub const EOVERFLOW: ::c_int = 79; pub const ENOTUNIQ: ::c_int = 80; pub const EBADFD: ::c_int = 81; pub const EBADMSG: ::c_int = 77; pub const EREMCHG: ::c_int = 82; pub const ELIBACC: ::c_int = 83; pub const ELIBBAD: ::c_int = 84; pub const ELIBSCN: ::c_int = 85; pub const ELIBMAX: ::c_int = 86; pub const ELIBEXEC: ::c_int = 87; pub const EILSEQ: ::c_int = 88; pub const ERESTART: ::c_int = 91; pub const ESTRPIPE: ::c_int = 92; pub const EUSERS: ::c_int = 94; pub const ENOTSOCK: ::c_int = 95; pub const EDESTADDRREQ: ::c_int = 96; pub const EMSGSIZE: ::c_int = 97; pub const EPROTOTYPE: ::c_int = 98; pub const ENOPROTOOPT: ::c_int = 99; pub const EPROTONOSUPPORT: ::c_int = 120; pub const ESOCKTNOSUPPORT: ::c_int = 121; pub const EOPNOTSUPP: ::c_int = 122; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 123; pub const EAFNOSUPPORT: ::c_int = 124; pub const EADDRINUSE: ::c_int = 125; pub const EADDRNOTAVAIL: ::c_int = 126; pub const ENETDOWN: ::c_int = 127; pub const ENETUNREACH: ::c_int = 128; pub const ENETRESET: ::c_int = 129; pub const ECONNABORTED: ::c_int = 130; pub const ECONNRESET: ::c_int = 131; pub const ENOBUFS: ::c_int = 132; pub const EISCONN: ::c_int = 133; pub const ENOTCONN: ::c_int = 134; pub const ESHUTDOWN: ::c_int = 143; pub const ETOOMANYREFS: ::c_int = 144; pub const ETIMEDOUT: ::c_int = 145; pub const ECONNREFUSED: ::c_int = 146; pub const EHOSTDOWN: ::c_int = 147; pub const EHOSTUNREACH: ::c_int = 148; pub const EALREADY: ::c_int = 149; pub const EINPROGRESS: ::c_int = 150; pub const ESTALE: ::c_int = 151; pub const EUCLEAN: ::c_int = 135; pub const ENOTNAM: ::c_int = 137; pub const ENAVAIL: ::c_int = 138; pub const EISNAM: ::c_int = 139; pub const EREMOTEIO: ::c_int = 140; pub const EDQUOT: ::c_int = 1133; pub const ENOMEDIUM: ::c_int = 159; pub const EMEDIUMTYPE: ::c_int = 160; pub const ECANCELED: ::c_int = 158; pub const ENOKEY: ::c_int = 161; pub const EKEYEXPIRED: ::c_int = 162; pub const EKEYREVOKED: ::c_int = 163; pub const EKEYREJECTED: ::c_int = 164; pub const EOWNERDEAD: ::c_int = 165; pub const ENOTRECOVERABLE: ::c_int = 166; pub const EHWPOISON: ::c_int = 168; pub const ERFKILL: ::c_int = 167; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 8; pub const SA_NOCLDWAIT: ::c_int = 0x10000; pub const SIGCHLD: ::c_int = 18; pub const SIGBUS: ::c_int = 10; pub const SIGTTIN: ::c_int = 26; pub const SIGTTOU: ::c_int = 27; pub const SIGXCPU: ::c_int = 30; pub const SIGXFSZ: ::c_int = 31; pub const SIGVTALRM: ::c_int = 28; pub const SIGPROF: ::c_int = 29; pub const SIGWINCH: ::c_int = 20; pub const SIGUSR1: ::c_int = 16; pub const SIGUSR2: ::c_int = 17; pub const SIGCONT: ::c_int = 25; pub const SIGSTOP: ::c_int = 23; pub const SIGTSTP: ::c_int = 24; pub const SIGURG: ::c_int = 21; pub const SIGIO: ::c_int = 22; pub const SIGSYS: ::c_int = 12; pub const SIGSTKFLT: ::c_int = 7; pub const SIGPOLL: ::c_int = ::SIGIO; pub const SIGPWR: ::c_int = 19; pub const SIG_SETMASK: ::c_int = 3; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const EXTPROC: ::tcflag_t = 0o200000; pub const F_GETLK: ::c_int = 33; pub const F_GETOWN: ::c_int = 23; pub const F_SETLK: ::c_int = 34; pub const F_SETLKW: ::c_int = 35; pub const F_SETOWN: ::c_int = 24; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: ::tcflag_t = 0o000400; pub const TOSTOP: ::tcflag_t = 0o100000; pub const FLUSHO: ::tcflag_t = 0o020000; pub const POLLWRNORM: ::c_short = 0x4; pub const POLLWRBAND: ::c_short = 0x100; pub const SYS_syscall: ::c_long = 4000 + 0; pub const SYS_exit: ::c_long = 4000 + 1; pub const SYS_fork: ::c_long = 4000 + 2; pub const SYS_read: ::c_long = 4000 + 3; pub const SYS_write: ::c_long = 4000 + 4; pub const SYS_open: ::c_long = 4000 + 5; pub const SYS_close: ::c_long = 4000 + 6; pub const SYS_waitpid: ::c_long = 4000 + 7; pub const SYS_creat: ::c_long = 4000 + 8; pub const SYS_link: ::c_long = 4000 + 9; pub const SYS_unlink: ::c_long = 4000 + 10; pub const SYS_execve: ::c_long = 4000 + 11; pub const SYS_chdir: ::c_long = 4000 + 12; pub const SYS_time: ::c_long = 4000 + 13; pub const SYS_mknod: ::c_long = 4000 + 14; pub const SYS_chmod: ::c_long = 4000 + 15; pub const SYS_lchown: ::c_long = 4000 + 16; pub const SYS_break: ::c_long = 4000 + 17; pub const SYS_lseek: ::c_long = 4000 + 19; pub const SYS_getpid: ::c_long = 4000 + 20; pub const SYS_mount: ::c_long = 4000 + 21; pub const SYS_umount: ::c_long = 4000 + 22; pub const SYS_setuid: ::c_long = 4000 + 23; pub const SYS_getuid: ::c_long = 4000 + 24; pub const SYS_stime: ::c_long = 4000 + 25; pub const SYS_ptrace: ::c_long = 4000 + 26; pub const SYS_alarm: ::c_long = 4000 + 27; pub const SYS_pause: ::c_long = 4000 + 29; pub const SYS_utime: ::c_long = 4000 + 30; pub const SYS_stty: ::c_long = 4000 + 31; pub const SYS_gtty: ::c_long = 4000 + 32; pub const SYS_access: ::c_long = 4000 + 33; pub const SYS_nice: ::c_long = 4000 + 34; pub const SYS_ftime: ::c_long = 4000 + 35; pub const SYS_sync: ::c_long = 4000 + 36; pub const SYS_kill: ::c_long = 4000 + 37; pub const SYS_rename: ::c_long = 4000 + 38; pub const SYS_mkdir: ::c_long = 4000 + 39; pub const SYS_rmdir: ::c_long = 4000 + 40; pub const SYS_dup: ::c_long = 4000 + 41; pub const SYS_pipe: ::c_long = 4000 + 42; pub const SYS_times: ::c_long = 4000 + 43; pub const SYS_prof: ::c_long = 4000 + 44; pub const SYS_brk: ::c_long = 4000 + 45; pub const SYS_setgid: ::c_long = 4000 + 46; pub const SYS_getgid: ::c_long = 4000 + 47; pub const SYS_signal: ::c_long = 4000 + 48; pub const SYS_geteuid: ::c_long = 4000 + 49; pub const SYS_getegid: ::c_long = 4000 + 50; pub const SYS_acct: ::c_long = 4000 + 51; pub const SYS_umount2: ::c_long = 4000 + 52; pub const SYS_lock: ::c_long = 4000 + 53; pub const SYS_ioctl: ::c_long = 4000 + 54; pub const SYS_fcntl: ::c_long = 4000 + 55; pub const SYS_mpx: ::c_long = 4000 + 56; pub const SYS_setpgid: ::c_long = 4000 + 57; pub const SYS_ulimit: ::c_long = 4000 + 58; pub const SYS_umask: ::c_long = 4000 + 60; pub const SYS_chroot: ::c_long = 4000 + 61; pub const SYS_ustat: ::c_long = 4000 + 62; pub const SYS_dup2: ::c_long = 4000 + 63; pub const SYS_getppid: ::c_long = 4000 + 64; pub const SYS_getpgrp: ::c_long = 4000 + 65; pub const SYS_setsid: ::c_long = 4000 + 66; pub const SYS_sigaction: ::c_long = 4000 + 67; pub const SYS_sgetmask: ::c_long = 4000 + 68; pub const SYS_ssetmask: ::c_long = 4000 + 69; pub const SYS_setreuid: ::c_long = 4000 + 70; pub const SYS_setregid: ::c_long = 4000 + 71; pub const SYS_sigsuspend: ::c_long = 4000 + 72; pub const SYS_sigpending: ::c_long = 4000 + 73; pub const SYS_sethostname: ::c_long = 4000 + 74; pub const SYS_setrlimit: ::c_long = 4000 + 75; pub const SYS_getrlimit: ::c_long = 4000 + 76; pub const SYS_getrusage: ::c_long = 4000 + 77; pub const SYS_gettimeofday: ::c_long = 4000 + 78; pub const SYS_settimeofday: ::c_long = 4000 + 79; pub const SYS_getgroups: ::c_long = 4000 + 80; pub const SYS_setgroups: ::c_long = 4000 + 81; pub const SYS_symlink: ::c_long = 4000 + 83; pub const SYS_readlink: ::c_long = 4000 + 85; pub const SYS_uselib: ::c_long = 4000 + 86; pub const SYS_swapon: ::c_long = 4000 + 87; pub const SYS_reboot: ::c_long = 4000 + 88; pub const SYS_readdir: ::c_long = 4000 + 89; pub const SYS_mmap: ::c_long = 4000 + 90; pub const SYS_munmap: ::c_long = 4000 + 91; pub const SYS_truncate: ::c_long = 4000 + 92; pub const SYS_ftruncate: ::c_long = 4000 + 93; pub const SYS_fchmod: ::c_long = 4000 + 94; pub const SYS_fchown: ::c_long = 4000 + 95; pub const SYS_getpriority: ::c_long = 4000 + 96; pub const SYS_setpriority: ::c_long = 4000 + 97; pub const SYS_profil: ::c_long = 4000 + 98; pub const SYS_statfs: ::c_long = 4000 + 99; pub const SYS_fstatfs: ::c_long = 4000 + 100; pub const SYS_ioperm: ::c_long = 4000 + 101; pub const SYS_socketcall: ::c_long = 4000 + 102; pub const SYS_syslog: ::c_long = 4000 + 103; pub const SYS_setitimer: ::c_long = 4000 + 104; pub const SYS_getitimer: ::c_long = 4000 + 105; pub const SYS_stat: ::c_long = 4000 + 106; pub const SYS_lstat: ::c_long = 4000 + 107; pub const SYS_fstat: ::c_long = 4000 + 108; pub const SYS_iopl: ::c_long = 4000 + 110; pub const SYS_vhangup: ::c_long = 4000 + 111; pub const SYS_idle: ::c_long = 4000 + 112; pub const SYS_vm86: ::c_long = 4000 + 113; pub const SYS_wait4: ::c_long = 4000 + 114; pub const SYS_swapoff: ::c_long = 4000 + 115; pub const SYS_sysinfo: ::c_long = 4000 + 116; pub const SYS_ipc: ::c_long = 4000 + 117; pub const SYS_fsync: ::c_long = 4000 + 118; pub const SYS_sigreturn: ::c_long = 4000 + 119; pub const SYS_clone: ::c_long = 4000 + 120; pub const SYS_setdomainname: ::c_long = 4000 + 121; pub const SYS_uname: ::c_long = 4000 + 122; pub const SYS_modify_ldt: ::c_long = 4000 + 123; pub const SYS_adjtimex: ::c_long = 4000 + 124; pub const SYS_mprotect: ::c_long = 4000 + 125; pub const SYS_sigprocmask: ::c_long = 4000 + 126; pub const SYS_create_module: ::c_long = 4000 + 127; pub const SYS_init_module: ::c_long = 4000 + 128; pub const SYS_delete_module: ::c_long = 4000 + 129; pub const SYS_get_kernel_syms: ::c_long = 4000 + 130; pub const SYS_quotactl: ::c_long = 4000 + 131; pub const SYS_getpgid: ::c_long = 4000 + 132; pub const SYS_fchdir: ::c_long = 4000 + 133; pub const SYS_bdflush: ::c_long = 4000 + 134; pub const SYS_sysfs: ::c_long = 4000 + 135; pub const SYS_personality: ::c_long = 4000 + 136; pub const SYS_afs_syscall: ::c_long = 4000 + 137; pub const SYS_setfsuid: ::c_long = 4000 + 138; pub const SYS_setfsgid: ::c_long = 4000 + 139; pub const SYS__llseek: ::c_long = 4000 + 140; pub const SYS_getdents: ::c_long = 4000 + 141; pub const SYS_flock: ::c_long = 4000 + 143; pub const SYS_msync: ::c_long = 4000 + 144; pub const SYS_readv: ::c_long = 4000 + 145; pub const SYS_writev: ::c_long = 4000 + 146; pub const SYS_cacheflush: ::c_long = 4000 + 147; pub const SYS_cachectl: ::c_long = 4000 + 148; pub const SYS_sysmips: ::c_long = 4000 + 149; pub const SYS_getsid: ::c_long = 4000 + 151; pub const SYS_fdatasync: ::c_long = 4000 + 152; pub const SYS__sysctl: ::c_long = 4000 + 153; pub const SYS_mlock: ::c_long = 4000 + 154; pub const SYS_munlock: ::c_long = 4000 + 155; pub const SYS_mlockall: ::c_long = 4000 + 156; pub const SYS_munlockall: ::c_long = 4000 + 157; pub const SYS_sched_setparam: ::c_long = 4000 + 158; pub const SYS_sched_getparam: ::c_long = 4000 + 159; pub const SYS_sched_setscheduler: ::c_long = 4000 + 160; pub const SYS_sched_getscheduler: ::c_long = 4000 + 161; pub const SYS_sched_yield: ::c_long = 4000 + 162; pub const SYS_sched_get_priority_max: ::c_long = 4000 + 163; pub const SYS_sched_get_priority_min: ::c_long = 4000 + 164; pub const SYS_sched_rr_get_interval: ::c_long = 4000 + 165; pub const SYS_nanosleep: ::c_long = 4000 + 166; pub const SYS_mremap: ::c_long = 4000 + 167; pub const SYS_accept: ::c_long = 4000 + 168; pub const SYS_bind: ::c_long = 4000 + 169; pub const SYS_connect: ::c_long = 4000 + 170; pub const SYS_getpeername: ::c_long = 4000 + 171; pub const SYS_getsockname: ::c_long = 4000 + 172; pub const SYS_getsockopt: ::c_long = 4000 + 173; pub const SYS_listen: ::c_long = 4000 + 174; pub const SYS_recv: ::c_long = 4000 + 175; pub const SYS_recvfrom: ::c_long = 4000 + 176; pub const SYS_recvmsg: ::c_long = 4000 + 177; pub const SYS_send: ::c_long = 4000 + 178; pub const SYS_sendmsg: ::c_long = 4000 + 179; pub const SYS_sendto: ::c_long = 4000 + 180; pub const SYS_setsockopt: ::c_long = 4000 + 181; pub const SYS_shutdown: ::c_long = 4000 + 182; pub const SYS_socket: ::c_long = 4000 + 183; pub const SYS_socketpair: ::c_long = 4000 + 184; pub const SYS_setresuid: ::c_long = 4000 + 185; pub const SYS_getresuid: ::c_long = 4000 + 186; pub const SYS_query_module: ::c_long = 4000 + 187; pub const SYS_poll: ::c_long = 4000 + 188; pub const SYS_nfsservctl: ::c_long = 4000 + 189; pub const SYS_setresgid: ::c_long = 4000 + 190; pub const SYS_getresgid: ::c_long = 4000 + 191; pub const SYS_prctl: ::c_long = 4000 + 192; pub const SYS_rt_sigreturn: ::c_long = 4000 + 193; pub const SYS_rt_sigaction: ::c_long = 4000 + 194; pub const SYS_rt_sigprocmask: ::c_long = 4000 + 195; pub const SYS_rt_sigpending: ::c_long = 4000 + 196; pub const SYS_rt_sigtimedwait: ::c_long = 4000 + 197; pub const SYS_rt_sigqueueinfo: ::c_long = 4000 + 198; pub const SYS_rt_sigsuspend: ::c_long = 4000 + 199; pub const SYS_chown: ::c_long = 4000 + 202; pub const SYS_getcwd: ::c_long = 4000 + 203; pub const SYS_capget: ::c_long = 4000 + 204; pub const SYS_capset: ::c_long = 4000 + 205; pub const SYS_sigaltstack: ::c_long = 4000 + 206; pub const SYS_sendfile: ::c_long = 4000 + 207; pub const SYS_getpmsg: ::c_long = 4000 + 208; pub const SYS_putpmsg: ::c_long = 4000 + 209; pub const SYS_mmap2: ::c_long = 4000 + 210; pub const SYS_truncate64: ::c_long = 4000 + 211; pub const SYS_ftruncate64: ::c_long = 4000 + 212; pub const SYS_stat64: ::c_long = 4000 + 213; pub const SYS_lstat64: ::c_long = 4000 + 214; pub const SYS_fstat64: ::c_long = 4000 + 215; pub const SYS_pivot_root: ::c_long = 4000 + 216; pub const SYS_mincore: ::c_long = 4000 + 217; pub const SYS_madvise: ::c_long = 4000 + 218; pub const SYS_getdents64: ::c_long = 4000 + 219; pub const SYS_fcntl64: ::c_long = 4000 + 220; pub const SYS_gettid: ::c_long = 4000 + 222; pub const SYS_readahead: ::c_long = 4000 + 223; pub const SYS_setxattr: ::c_long = 4000 + 224; pub const SYS_lsetxattr: ::c_long = 4000 + 225; pub const SYS_fsetxattr: ::c_long = 4000 + 226; pub const SYS_getxattr: ::c_long = 4000 + 227; pub const SYS_lgetxattr: ::c_long = 4000 + 228; pub const SYS_fgetxattr: ::c_long = 4000 + 229; pub const SYS_listxattr: ::c_long = 4000 + 230; pub const SYS_llistxattr: ::c_long = 4000 + 231; pub const SYS_flistxattr: ::c_long = 4000 + 232; pub const SYS_removexattr: ::c_long = 4000 + 233; pub const SYS_lremovexattr: ::c_long = 4000 + 234; pub const SYS_fremovexattr: ::c_long = 4000 + 235; pub const SYS_tkill: ::c_long = 4000 + 236; pub const SYS_sendfile64: ::c_long = 4000 + 237; pub const SYS_futex: ::c_long = 4000 + 238; pub const SYS_sched_setaffinity: ::c_long = 4000 + 239; pub const SYS_sched_getaffinity: ::c_long = 4000 + 240; pub const SYS_io_setup: ::c_long = 4000 + 241; pub const SYS_io_destroy: ::c_long = 4000 + 242; pub const SYS_io_getevents: ::c_long = 4000 + 243; pub const SYS_io_submit: ::c_long = 4000 + 244; pub const SYS_io_cancel: ::c_long = 4000 + 245; pub const SYS_exit_group: ::c_long = 4000 + 246; pub const SYS_lookup_dcookie: ::c_long = 4000 + 247; pub const SYS_epoll_create: ::c_long = 4000 + 248; pub const SYS_epoll_ctl: ::c_long = 4000 + 249; pub const SYS_epoll_wait: ::c_long = 4000 + 250; pub const SYS_remap_file_pages: ::c_long = 4000 + 251; pub const SYS_set_tid_address: ::c_long = 4000 + 252; pub const SYS_restart_syscall: ::c_long = 4000 + 253; pub const SYS_statfs64: ::c_long = 4000 + 255; pub const SYS_fstatfs64: ::c_long = 4000 + 256; pub const SYS_timer_create: ::c_long = 4000 + 257; pub const SYS_timer_settime: ::c_long = 4000 + 258; pub const SYS_timer_gettime: ::c_long = 4000 + 259; pub const SYS_timer_getoverrun: ::c_long = 4000 + 260; pub const SYS_timer_delete: ::c_long = 4000 + 261; pub const SYS_clock_settime: ::c_long = 4000 + 262; pub const SYS_clock_gettime: ::c_long = 4000 + 263; pub const SYS_clock_getres: ::c_long = 4000 + 264; pub const SYS_clock_nanosleep: ::c_long = 4000 + 265; pub const SYS_tgkill: ::c_long = 4000 + 266; pub const SYS_utimes: ::c_long = 4000 + 267; pub const SYS_mbind: ::c_long = 4000 + 268; pub const SYS_get_mempolicy: ::c_long = 4000 + 269; pub const SYS_set_mempolicy: ::c_long = 4000 + 270; pub const SYS_mq_open: ::c_long = 4000 + 271; pub const SYS_mq_unlink: ::c_long = 4000 + 272; pub const SYS_mq_timedsend: ::c_long = 4000 + 273; pub const SYS_mq_timedreceive: ::c_long = 4000 + 274; pub const SYS_mq_notify: ::c_long = 4000 + 275; pub const SYS_mq_getsetattr: ::c_long = 4000 + 276; pub const SYS_vserver: ::c_long = 4000 + 277; pub const SYS_waitid: ::c_long = 4000 + 278; /* pub const SYS_sys_setaltroot: ::c_long = 4000 + 279; */ pub const SYS_add_key: ::c_long = 4000 + 280; pub const SYS_request_key: ::c_long = 4000 + 281; pub const SYS_keyctl: ::c_long = 4000 + 282; pub const SYS_set_thread_area: ::c_long = 4000 + 283; pub const SYS_inotify_init: ::c_long = 4000 + 284; pub const SYS_inotify_add_watch: ::c_long = 4000 + 285; pub const SYS_inotify_rm_watch: ::c_long = 4000 + 286; pub const SYS_migrate_pages: ::c_long = 4000 + 287; pub const SYS_openat: ::c_long = 4000 + 288; pub const SYS_mkdirat: ::c_long = 4000 + 289; pub const SYS_mknodat: ::c_long = 4000 + 290; pub const SYS_fchownat: ::c_long = 4000 + 291; pub const SYS_futimesat: ::c_long = 4000 + 292; pub const SYS_unlinkat: ::c_long = 4000 + 294; pub const SYS_renameat: ::c_long = 4000 + 295; pub const SYS_linkat: ::c_long = 4000 + 296; pub const SYS_symlinkat: ::c_long = 4000 + 297; pub const SYS_readlinkat: ::c_long = 4000 + 298; pub const SYS_fchmodat: ::c_long = 4000 + 299; pub const SYS_faccessat: ::c_long = 4000 + 300; pub const SYS_pselect6: ::c_long = 4000 + 301; pub const SYS_ppoll: ::c_long = 4000 + 302; pub const SYS_unshare: ::c_long = 4000 + 303; pub const SYS_splice: ::c_long = 4000 + 304; pub const SYS_sync_file_range: ::c_long = 4000 + 305; pub const SYS_tee: ::c_long = 4000 + 306; pub const SYS_vmsplice: ::c_long = 4000 + 307; pub const SYS_move_pages: ::c_long = 4000 + 308; pub const SYS_set_robust_list: ::c_long = 4000 + 309; pub const SYS_get_robust_list: ::c_long = 4000 + 310; pub const SYS_kexec_load: ::c_long = 4000 + 311; pub const SYS_getcpu: ::c_long = 4000 + 312; pub const SYS_epoll_pwait: ::c_long = 4000 + 313; pub const SYS_ioprio_set: ::c_long = 4000 + 314; pub const SYS_ioprio_get: ::c_long = 4000 + 315; pub const SYS_utimensat: ::c_long = 4000 + 316; pub const SYS_signalfd: ::c_long = 4000 + 317; pub const SYS_timerfd: ::c_long = 4000 + 318; pub const SYS_eventfd: ::c_long = 4000 + 319; pub const SYS_fallocate: ::c_long = 4000 + 320; pub const SYS_timerfd_create: ::c_long = 4000 + 321; pub const SYS_timerfd_gettime: ::c_long = 4000 + 322; pub const SYS_timerfd_settime: ::c_long = 4000 + 323; pub const SYS_signalfd4: ::c_long = 4000 + 324; pub const SYS_eventfd2: ::c_long = 4000 + 325; pub const SYS_epoll_create1: ::c_long = 4000 + 326; pub const SYS_dup3: ::c_long = 4000 + 327; pub const SYS_pipe2: ::c_long = 4000 + 328; pub const SYS_inotify_init1: ::c_long = 4000 + 329; pub const SYS_preadv: ::c_long = 4000 + 330; pub const SYS_pwritev: ::c_long = 4000 + 331; pub const SYS_rt_tgsigqueueinfo: ::c_long = 4000 + 332; pub const SYS_perf_event_open: ::c_long = 4000 + 333; pub const SYS_accept4: ::c_long = 4000 + 334; pub const SYS_recvmmsg: ::c_long = 4000 + 335; pub const SYS_fanotify_init: ::c_long = 4000 + 336; pub const SYS_fanotify_mark: ::c_long = 4000 + 337; pub const SYS_prlimit64: ::c_long = 4000 + 338; pub const SYS_name_to_handle_at: ::c_long = 4000 + 339; pub const SYS_open_by_handle_at: ::c_long = 4000 + 340; pub const SYS_clock_adjtime: ::c_long = 4000 + 341; pub const SYS_syncfs: ::c_long = 4000 + 342; pub const SYS_sendmmsg: ::c_long = 4000 + 343; pub const SYS_setns: ::c_long = 4000 + 344; pub const SYS_process_vm_readv: ::c_long = 4000 + 345; pub const SYS_process_vm_writev: ::c_long = 4000 + 346; pub const SYS_kcmp: ::c_long = 4000 + 347; pub const SYS_finit_module: ::c_long = 4000 + 348; pub const SYS_sched_setattr: ::c_long = 4000 + 349; pub const SYS_sched_getattr: ::c_long = 4000 + 350; pub const SYS_renameat2: ::c_long = 4000 + 351; pub const SYS_seccomp: ::c_long = 4000 + 352; pub const SYS_getrandom: ::c_long = 4000 + 353; pub const SYS_memfd_create: ::c_long = 4000 + 354; pub const SYS_bpf: ::c_long = 4000 + 355; pub const SYS_execveat: ::c_long = 4000 + 356; pub const SYS_userfaultfd: ::c_long = 4000 + 357; pub const SYS_membarrier: ::c_long = 4000 + 358; pub const SYS_mlock2: ::c_long = 4000 + 359; pub const SYS_copy_file_range: ::c_long = 4000 + 360; pub const SYS_preadv2: ::c_long = 4000 + 361; pub const SYS_pwritev2: ::c_long = 4000 + 362; pub const SYS_pkey_mprotect: ::c_long = 4000 + 363; pub const SYS_pkey_alloc: ::c_long = 4000 + 364; pub const SYS_pkey_free: ::c_long = 4000 + 365; pub const SYS_statx: ::c_long = 4000 + 366; pub const SYS_pidfd_send_signal: ::c_long = 4000 + 424; pub const SYS_io_uring_setup: ::c_long = 4000 + 425; pub const SYS_io_uring_enter: ::c_long = 4000 + 426; pub const SYS_io_uring_register: ::c_long = 4000 + 427; pub const SYS_open_tree: ::c_long = 4000 + 428; pub const SYS_move_mount: ::c_long = 4000 + 429; pub const SYS_fsopen: ::c_long = 4000 + 430; pub const SYS_fsconfig: ::c_long = 4000 + 431; pub const SYS_fsmount: ::c_long = 4000 + 432; pub const SYS_fspick: ::c_long = 4000 + 433; pub const SYS_pidfd_open: ::c_long = 4000 + 434; pub const SYS_clone3: ::c_long = 4000 + 435; pub const SYS_close_range: ::c_long = 4000 + 436; pub const SYS_openat2: ::c_long = 4000 + 437; pub const SYS_pidfd_getfd: ::c_long = 4000 + 438; pub const SYS_faccessat2: ::c_long = 4000 + 439; pub const SYS_process_madvise: ::c_long = 4000 + 440; pub const SYS_epoll_pwait2: ::c_long = 4000 + 441; pub const SYS_mount_setattr: ::c_long = 4000 + 442; pub const SYS_quotactl_fd: ::c_long = 4000 + 443; pub const SYS_landlock_create_ruleset: ::c_long = 4000 + 444; pub const SYS_landlock_add_rule: ::c_long = 4000 + 445; pub const SYS_landlock_restrict_self: ::c_long = 4000 + 446; pub const SYS_memfd_secret: ::c_long = 4000 + 447; pub const SYS_process_mrelease: ::c_long = 4000 + 448; pub const SYS_futex_waitv: ::c_long = 4000 + 449; pub const SYS_set_mempolicy_home_node: ::c_long = 4000 + 450; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/musl/b32/mips/align.rs0000644000175000017500000000022414661133735023502 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f32; 4] } } libc/src/unix/linux_like/linux/musl/mod.rs0000644000175000017500000007171614661133735021647 0ustar jamespagejamespagepub type pthread_t = *mut ::c_void; pub type clock_t = c_long; #[cfg_attr( not(feature = "rustc-dep-of-std"), deprecated( since = "0.2.80", note = "This type is changed to 64-bit in musl 1.2.0, \ we'll follow that change in the future release. \ See #1848 for more info." ) )] pub type time_t = c_long; pub type suseconds_t = c_long; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; pub type shmatt_t = ::c_ulong; pub type msgqnum_t = ::c_ulong; pub type msglen_t = ::c_ulong; pub type fsblkcnt_t = ::c_ulonglong; pub type fsfilcnt_t = ::c_ulonglong; pub type rlim_t = ::c_ulonglong; cfg_if! { if #[cfg(doc)] { // Used in `linux::arch` to define ioctl constants. pub(crate) type Ioctl = ::c_int; } else { #[doc(hidden)] pub type Ioctl = ::c_int; } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, si_addr: *mut ::c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_si_value { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, _si_timerid: ::c_int, _si_overrun: ::c_int, si_value: ::sigval, } (*(self as *const siginfo_t as *const siginfo_si_value)).si_value } } cfg_if! { if #[cfg(libc_union)] { // Internal, for casts to access union fields #[repr(C)] struct sifields_sigchld { si_pid: ::pid_t, si_uid: ::uid_t, si_status: ::c_int, si_utime: ::c_long, si_stime: ::c_long, } impl ::Copy for sifields_sigchld {} impl ::Clone for sifields_sigchld { fn clone(&self) -> sifields_sigchld { *self } } // Internal, for casts to access union fields #[repr(C)] union sifields { _align_pointer: *mut ::c_void, sigchld: sifields_sigchld, } // Internal, for casts to access union fields. Note that some variants // of sifields start with a pointer, which makes the alignment of // sifields vary on 32-bit and 64-bit architectures. #[repr(C)] struct siginfo_f { _siginfo_base: [::c_int; 3], sifields: sifields, } impl siginfo_t { unsafe fn sifields(&self) -> &sifields { &(*(self as *const siginfo_t as *const siginfo_f)).sifields } pub unsafe fn si_pid(&self) -> ::pid_t { self.sifields().sigchld.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.sifields().sigchld.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.sifields().sigchld.si_status } pub unsafe fn si_utime(&self) -> ::c_long { self.sifields().sigchld.si_utime } pub unsafe fn si_stime(&self) -> ::c_long { self.sifields().sigchld.si_stime } } } } s! { pub struct aiocb { pub aio_fildes: ::c_int, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_sigevent: ::sigevent, __td: *mut ::c_void, __lock: [::c_int; 2], __err: ::c_int, __ret: ::ssize_t, pub aio_offset: off_t, __next: *mut ::c_void, __prev: *mut ::c_void, #[cfg(target_pointer_width = "32")] __dummy4: [::c_char; 24], #[cfg(target_pointer_width = "64")] __dummy4: [::c_char; 16], } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, #[cfg(target_endian = "little")] pub f_fsid: ::c_ulong, #[cfg(target_pointer_width = "32")] __f_unused: ::c_int, #[cfg(target_endian = "big")] pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], pub __c_ispeed: ::speed_t, pub __c_ospeed: ::speed_t, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct regex_t { __re_nsub: ::size_t, __opaque: *mut ::c_void, __padding: [*mut ::c_void; 4usize], __nsub2: ::size_t, __padding2: ::c_char, } pub struct rtentry { pub rt_pad1: ::c_ulong, pub rt_dst: ::sockaddr, pub rt_gateway: ::sockaddr, pub rt_genmask: ::sockaddr, pub rt_flags: ::c_ushort, pub rt_pad2: ::c_short, pub rt_pad3: ::c_ulong, pub rt_tos: ::c_uchar, pub rt_class: ::c_uchar, #[cfg(target_pointer_width = "64")] pub rt_pad4: [::c_short; 3usize], #[cfg(not(target_pointer_width = "64"))] pub rt_pad4: [::c_short; 1usize], pub rt_metric: ::c_short, pub rt_dev: *mut ::c_char, pub rt_mtu: ::c_ulong, pub rt_window: ::c_ulong, pub rt_irtt: ::c_ushort, } pub struct __exit_status { pub e_termination: ::c_short, pub e_exit: ::c_short, } pub struct Elf64_Chdr { pub ch_type: ::Elf64_Word, pub ch_reserved: ::Elf64_Word, pub ch_size: ::Elf64_Xword, pub ch_addralign: ::Elf64_Xword, } pub struct Elf32_Chdr { pub ch_type: ::Elf32_Word, pub ch_size: ::Elf32_Word, pub ch_addralign: ::Elf32_Word, } pub struct timex { pub modes: ::c_uint, pub offset: ::c_long, pub freq: ::c_long, pub maxerror: ::c_long, pub esterror: ::c_long, pub status: ::c_int, pub constant: ::c_long, pub precision: ::c_long, pub tolerance: ::c_long, pub time: ::timeval, pub tick: ::c_long, pub ppsfreq: ::c_long, pub jitter: ::c_long, pub shift: ::c_int, pub stabil: ::c_long, pub jitcnt: ::c_long, pub calcnt: ::c_long, pub errcnt: ::c_long, pub stbcnt: ::c_long, pub tai: ::c_int, pub __padding: [::c_int; 11], } pub struct ntptimeval { pub time: ::timeval, pub maxerror: ::c_long, pub esterror: ::c_long, } // linux/if_xdp.h pub struct sockaddr_xdp { pub sxdp_family: ::__u16, pub sxdp_flags: ::__u16, pub sxdp_ifindex: ::__u32, pub sxdp_queue_id: ::__u32, pub sxdp_shared_umem_fd: ::__u32, } pub struct xdp_ring_offset { pub producer: ::__u64, pub consumer: ::__u64, pub desc: ::__u64, pub flags: ::__u64, } pub struct xdp_mmap_offsets { pub rx: xdp_ring_offset, pub tx: xdp_ring_offset, pub fr: xdp_ring_offset, pub cr: xdp_ring_offset, } pub struct xdp_ring_offset_v1 { pub producer: ::__u64, pub consumer: ::__u64, pub desc: ::__u64, } pub struct xdp_mmap_offsets_v1 { pub rx: xdp_ring_offset_v1, pub tx: xdp_ring_offset_v1, pub fr: xdp_ring_offset_v1, pub cr: xdp_ring_offset_v1, } pub struct xdp_umem_reg { pub addr: ::__u64, pub len: ::__u64, pub chunk_size: ::__u32, pub headroom: ::__u32, pub flags: ::__u32, } pub struct xdp_umem_reg_v1 { pub addr: ::__u64, pub len: ::__u64, pub chunk_size: ::__u32, pub headroom: ::__u32, } pub struct xdp_statistics { pub rx_dropped: ::__u64, pub rx_invalid_descs: ::__u64, pub tx_invalid_descs: ::__u64, pub rx_ring_full: ::__u64, pub rx_fill_ring_empty_descs: ::__u64, pub tx_ring_empty_descs: ::__u64, } pub struct xdp_statistics_v1 { pub rx_dropped: ::__u64, pub rx_invalid_descs: ::__u64, pub tx_invalid_descs: ::__u64, } pub struct xdp_options { pub flags: ::__u32, } pub struct xdp_desc { pub addr: ::__u64, pub len: ::__u32, pub options: ::__u32, } } s_no_extra_traits! { pub struct sysinfo { pub uptime: ::c_ulong, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub __reserved: [::c_char; 256], } // FIXME: musl added paddings and adjusted // layout in 1.2.0 but our CI is still 1.1.24. // So, I'm leaving some fields as cfg for now. // ref. https://github.com/bminor/musl/commit/ // 1e7f0fcd7ff2096904fd93a2ee6d12a2392be392 // // OpenHarmony uses the musl 1.2 layout. pub struct utmpx { pub ut_type: ::c_short, __ut_pad1: ::c_short, pub ut_pid: ::pid_t, pub ut_line: [::c_char; 32], pub ut_id: [::c_char; 4], pub ut_user: [::c_char; 32], pub ut_host: [::c_char; 256], pub ut_exit: __exit_status, #[cfg(target_env = "musl")] pub ut_session: ::c_long, #[cfg(target_env = "ohos")] #[cfg(target_endian = "little")] pub ut_session: ::c_int, #[cfg(target_env = "ohos")] #[cfg(target_endian = "little")] __ut_pad2: ::c_int, #[cfg(target_env = "ohos")] #[cfg(not(target_endian = "little"))] __ut_pad2: ::c_int, #[cfg(target_env = "ohos")] #[cfg(not(target_endian = "little"))] pub ut_session: ::c_int, pub ut_tv: ::timeval, pub ut_addr_v6: [::c_uint; 4], __unused: [::c_char; 20], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sysinfo { fn eq(&self, other: &sysinfo) -> bool { self.uptime == other.uptime && self.loads == other.loads && self.totalram == other.totalram && self.freeram == other.freeram && self.sharedram == other.sharedram && self.bufferram == other.bufferram && self.totalswap == other.totalswap && self.freeswap == other.freeswap && self.procs == other.procs && self.pad == other.pad && self.totalhigh == other.totalhigh && self.freehigh == other.freehigh && self.mem_unit == other.mem_unit && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a,b)| a == b) } } impl Eq for sysinfo {} impl ::fmt::Debug for sysinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sysinfo") .field("uptime", &self.uptime) .field("loads", &self.loads) .field("totalram", &self.totalram) .field("freeram", &self.freeram) .field("sharedram", &self.sharedram) .field("bufferram", &self.bufferram) .field("totalswap", &self.totalswap) .field("freeswap", &self.freeswap) .field("procs", &self.procs) .field("pad", &self.pad) .field("totalhigh", &self.totalhigh) .field("freehigh", &self.freehigh) .field("mem_unit", &self.mem_unit) // FIXME: .field("__reserved", &self.__reserved) .finish() } } impl ::hash::Hash for sysinfo { fn hash(&self, state: &mut H) { self.uptime.hash(state); self.loads.hash(state); self.totalram.hash(state); self.freeram.hash(state); self.sharedram.hash(state); self.bufferram.hash(state); self.totalswap.hash(state); self.freeswap.hash(state); self.procs.hash(state); self.pad.hash(state); self.totalhigh.hash(state); self.freehigh.hash(state); self.mem_unit.hash(state); self.__reserved.hash(state); } } impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type //&& self.__ut_pad1 == other.__ut_pad1 && self.ut_pid == other.ut_pid && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_user == other.ut_user && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session //&& self.__ut_pad2 == other.__ut_pad2 && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.__unused == other.__unused } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) //.field("__ut_pad1", &self.__ut_pad1) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) //FIXME: .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) //.field("__ut_pad2", &self.__ut_pad2) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("__unused", &self.__unused) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); //self.__ut_pad1.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); //self.__ut_pad2.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.__unused.hash(state); } } } } // include/sys/mman.h /* * Huge page size encoding when MAP_HUGETLB is specified, and a huge page * size other than the default is desired. See hugetlb_encode.h. * All known huge page size encodings are provided here. It is the * responsibility of the application to know which sizes are supported on * the running system. See mmap(2) man page for details. */ pub const MAP_HUGE_SHIFT: ::c_int = 26; pub const MAP_HUGE_MASK: ::c_int = 0x3f; pub const MAP_HUGE_64KB: ::c_int = 16 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512KB: ::c_int = 19 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1MB: ::c_int = 20 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2MB: ::c_int = 21 << MAP_HUGE_SHIFT; pub const MAP_HUGE_8MB: ::c_int = 23 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16MB: ::c_int = 24 << MAP_HUGE_SHIFT; pub const MAP_HUGE_32MB: ::c_int = 25 << MAP_HUGE_SHIFT; pub const MAP_HUGE_256MB: ::c_int = 28 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512MB: ::c_int = 29 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1GB: ::c_int = 30 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2GB: ::c_int = 31 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16GB: ::c_int = 34 << MAP_HUGE_SHIFT; pub const MS_RMT_MASK: ::c_ulong = 0x02800051; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_CLOEXEC: ::c_int = 0x80000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const BUFSIZ: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 10000; pub const FOPEN_MAX: ::c_uint = 1000; pub const FILENAME_MAX: ::c_uint = 4096; pub const O_PATH: ::c_int = 0o10000000; pub const O_EXEC: ::c_int = 0o10000000; pub const O_SEARCH: ::c_int = 0o10000000; pub const O_ACCMODE: ::c_int = 0o10000003; pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const NI_MAXHOST: ::socklen_t = 255; pub const PTHREAD_STACK_MIN: ::size_t = 2048; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_DCCP: ::c_int = 6; pub const SOCK_NONBLOCK: ::c_int = O_NONBLOCK; pub const SOCK_PACKET: ::c_int = 10; pub const SOMAXCONN: ::c_int = 128; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = ::SIGSYS; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const CPU_SETSIZE: ::c_int = 128; pub const PTRACE_TRACEME: ::c_int = 0; pub const PTRACE_PEEKTEXT: ::c_int = 1; pub const PTRACE_PEEKDATA: ::c_int = 2; pub const PTRACE_PEEKUSER: ::c_int = 3; pub const PTRACE_POKETEXT: ::c_int = 4; pub const PTRACE_POKEDATA: ::c_int = 5; pub const PTRACE_POKEUSER: ::c_int = 6; pub const PTRACE_CONT: ::c_int = 7; pub const PTRACE_KILL: ::c_int = 8; pub const PTRACE_SINGLESTEP: ::c_int = 9; pub const PTRACE_GETREGS: ::c_int = 12; pub const PTRACE_SETREGS: ::c_int = 13; pub const PTRACE_GETFPREGS: ::c_int = 14; pub const PTRACE_SETFPREGS: ::c_int = 15; pub const PTRACE_ATTACH: ::c_int = 16; pub const PTRACE_DETACH: ::c_int = 17; pub const PTRACE_GETFPXREGS: ::c_int = 18; pub const PTRACE_SETFPXREGS: ::c_int = 19; pub const PTRACE_SYSCALL: ::c_int = 24; pub const PTRACE_SETOPTIONS: ::c_int = 0x4200; pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201; pub const PTRACE_GETSIGINFO: ::c_int = 0x4202; pub const PTRACE_SETSIGINFO: ::c_int = 0x4203; pub const PTRACE_GETREGSET: ::c_int = 0x4204; pub const PTRACE_SETREGSET: ::c_int = 0x4205; pub const PTRACE_SEIZE: ::c_int = 0x4206; pub const PTRACE_INTERRUPT: ::c_int = 0x4207; pub const PTRACE_LISTEN: ::c_int = 0x4208; pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209; pub const PTRACE_GETSIGMASK: ::c_uint = 0x420a; pub const PTRACE_SETSIGMASK: ::c_uint = 0x420b; pub const AF_IB: ::c_int = 27; pub const AF_MPLS: ::c_int = 28; pub const AF_NFC: ::c_int = 39; pub const AF_VSOCK: ::c_int = 40; pub const AF_XDP: ::c_int = 44; pub const PF_IB: ::c_int = AF_IB; pub const PF_MPLS: ::c_int = AF_MPLS; pub const PF_NFC: ::c_int = AF_NFC; pub const PF_VSOCK: ::c_int = AF_VSOCK; pub const PF_XDP: ::c_int = AF_XDP; pub const EFD_NONBLOCK: ::c_int = ::O_NONBLOCK; pub const SFD_NONBLOCK: ::c_int = ::O_NONBLOCK; pub const PIDFD_NONBLOCK: ::c_uint = O_NONBLOCK as ::c_uint; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const CLOCK_SGI_CYCLE: ::clockid_t = 10; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const REG_OK: ::c_int = 0; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; pub const ADJ_OFFSET: ::c_uint = 0x0001; pub const ADJ_FREQUENCY: ::c_uint = 0x0002; pub const ADJ_MAXERROR: ::c_uint = 0x0004; pub const ADJ_ESTERROR: ::c_uint = 0x0008; pub const ADJ_STATUS: ::c_uint = 0x0010; pub const ADJ_TIMECONST: ::c_uint = 0x0020; pub const ADJ_TAI: ::c_uint = 0x0080; pub const ADJ_SETOFFSET: ::c_uint = 0x0100; pub const ADJ_MICRO: ::c_uint = 0x1000; pub const ADJ_NANO: ::c_uint = 0x2000; pub const ADJ_TICK: ::c_uint = 0x4000; pub const ADJ_OFFSET_SINGLESHOT: ::c_uint = 0x8001; pub const ADJ_OFFSET_SS_READ: ::c_uint = 0xa001; pub const MOD_OFFSET: ::c_uint = ADJ_OFFSET; pub const MOD_FREQUENCY: ::c_uint = ADJ_FREQUENCY; pub const MOD_MAXERROR: ::c_uint = ADJ_MAXERROR; pub const MOD_ESTERROR: ::c_uint = ADJ_ESTERROR; pub const MOD_STATUS: ::c_uint = ADJ_STATUS; pub const MOD_TIMECONST: ::c_uint = ADJ_TIMECONST; pub const MOD_CLKB: ::c_uint = ADJ_TICK; pub const MOD_CLKA: ::c_uint = ADJ_OFFSET_SINGLESHOT; pub const MOD_TAI: ::c_uint = ADJ_TAI; pub const MOD_MICRO: ::c_uint = ADJ_MICRO; pub const MOD_NANO: ::c_uint = ADJ_NANO; pub const STA_PLL: ::c_int = 0x0001; pub const STA_PPSFREQ: ::c_int = 0x0002; pub const STA_PPSTIME: ::c_int = 0x0004; pub const STA_FLL: ::c_int = 0x0008; pub const STA_INS: ::c_int = 0x0010; pub const STA_DEL: ::c_int = 0x0020; pub const STA_UNSYNC: ::c_int = 0x0040; pub const STA_FREQHOLD: ::c_int = 0x0080; pub const STA_PPSSIGNAL: ::c_int = 0x0100; pub const STA_PPSJITTER: ::c_int = 0x0200; pub const STA_PPSWANDER: ::c_int = 0x0400; pub const STA_PPSERROR: ::c_int = 0x0800; pub const STA_CLOCKERR: ::c_int = 0x1000; pub const STA_NANO: ::c_int = 0x2000; pub const STA_MODE: ::c_int = 0x4000; pub const STA_CLK: ::c_int = 0x8000; pub const STA_RONLY: ::c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: ::c_int = 0; pub const TIME_INS: ::c_int = 1; pub const TIME_DEL: ::c_int = 2; pub const TIME_OOP: ::c_int = 3; pub const TIME_WAIT: ::c_int = 4; pub const TIME_ERROR: ::c_int = 5; pub const TIME_BAD: ::c_int = TIME_ERROR; pub const MAXTC: ::c_long = 6; pub const SOL_XDP: ::c_int = 283; // linux/if_xdp.h pub const XDP_SHARED_UMEM: ::__u16 = 1 << 0; pub const XDP_COPY: ::__u16 = 1 << 1; pub const XDP_ZEROCOPY: ::__u16 = 1 << 2; pub const XDP_USE_NEED_WAKEUP: ::__u16 = 1 << 3; pub const XDP_USE_SG: ::__u16 = 1 << 4; pub const XDP_UMEM_UNALIGNED_CHUNK_FLAG: ::__u32 = 1 << 0; pub const XDP_RING_NEED_WAKEUP: ::__u32 = 1 << 0; pub const XDP_MMAP_OFFSETS: ::c_int = 1; pub const XDP_RX_RING: ::c_int = 2; pub const XDP_TX_RING: ::c_int = 3; pub const XDP_UMEM_REG: ::c_int = 4; pub const XDP_UMEM_FILL_RING: ::c_int = 5; pub const XDP_UMEM_COMPLETION_RING: ::c_int = 6; pub const XDP_STATISTICS: ::c_int = 7; pub const XDP_OPTIONS: ::c_int = 8; pub const XDP_OPTIONS_ZEROCOPY: ::__u32 = 1 << 0; pub const XDP_PGOFF_RX_RING: ::off_t = 0; pub const XDP_PGOFF_TX_RING: ::off_t = 0x80000000; pub const XDP_UMEM_PGOFF_FILL_RING: ::c_ulonglong = 0x100000000; pub const XDP_UMEM_PGOFF_COMPLETION_RING: ::c_ulonglong = 0x180000000; pub const XSK_UNALIGNED_BUF_OFFSET_SHIFT: ::c_int = 48; pub const XSK_UNALIGNED_BUF_ADDR_MASK: ::c_ulonglong = (1 << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1; pub const XDP_PKT_CONTD: ::__u32 = 1 << 0; cfg_if! { if #[cfg(target_arch = "s390x")] { pub const POSIX_FADV_DONTNEED: ::c_int = 6; pub const POSIX_FADV_NOREUSE: ::c_int = 7; } else { pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; } } extern "C" { pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_uint, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_uint, timeout: *mut ::timespec, ) -> ::c_int; pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn prlimit( pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit, old_limit: *mut ::rlimit, ) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn ptrace(request: ::c_int, ...) -> ::c_long; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; // Musl targets need the `mask` argument of `fanotify_mark` be specified // `::c_ulonglong` instead of `u64` or there will be a type mismatch between // `long long unsigned int` and the expected `uint64_t`. pub fn fanotify_mark( fd: ::c_int, flags: ::c_uint, mask: ::c_ulonglong, dirfd: ::c_int, path: *const ::c_char, ) -> ::c_int; pub fn getauxval(type_: ::c_ulong) -> ::c_ulong; // Added in `musl` 1.1.20 pub fn explicit_bzero(s: *mut ::c_void, len: ::size_t); // Added in `musl` 1.2.2 pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn adjtimex(buf: *mut ::timex) -> ::c_int; pub fn clock_adjtime(clk_id: ::clockid_t, buf: *mut ::timex) -> ::c_int; pub fn ctermid(s: *mut ::c_char) -> *mut ::c_char; pub fn memfd_create(name: *const ::c_char, flags: ::c_uint) -> ::c_int; pub fn mlock2(addr: *const ::c_void, len: ::size_t, flags: ::c_uint) -> ::c_int; pub fn malloc_usable_size(ptr: *mut ::c_void) -> ::size_t; pub fn euidaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int; pub fn eaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int; pub fn asctime_r(tm: *const ::tm, buf: *mut ::c_char) -> *mut ::c_char; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; } // Alias to 64 to mimic glibc's LFS64 support mod lfs64; pub use self::lfs64::*; cfg_if! { if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "mips64", target_arch = "powerpc64", target_arch = "s390x", target_arch = "riscv64", target_arch = "loongarch64"))] { mod b64; pub use self::b64::*; } else if #[cfg(any(target_arch = "x86", target_arch = "mips", target_arch = "powerpc", target_arch = "hexagon", target_arch = "riscv32", target_arch = "arm"))] { mod b32; pub use self::b32::*; } else { } } libc/src/unix/linux_like/linux/musl/b64/0000775000175000017500000000000014661133735021103 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b64/mips64.rs0000644000175000017500000006613214661133735022601 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type __u64 = ::c_ulong; pub type __s64 = ::c_long; pub type nlink_t = u64; pub type blksize_t = i64; s! { pub struct stat { pub st_dev: ::dev_t, __pad1: [::c_int; 3], pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: [::c_uint; 2], pub st_size: ::off_t, __pad3: ::c_int, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, __pad4: ::c_uint, pub st_blocks: ::blkcnt_t, __pad5: [::c_int; 14], } pub struct stat64 { pub st_dev: ::dev_t, __pad1: [::c_int; 3], pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: [::c_uint; 2], pub st_size: ::off_t, __pad3: ::c_int, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, __pad4: ::c_uint, pub st_blocks: ::blkcnt_t, __pad5: [::c_int; 14], } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 5], } pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 5], } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __pad1: ::c_int, __unused1: ::c_ulong, __unused2: ::c_ulong } } pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const SYS_read: ::c_long = 5000 + 0; pub const SYS_write: ::c_long = 5000 + 1; pub const SYS_open: ::c_long = 5000 + 2; pub const SYS_close: ::c_long = 5000 + 3; pub const SYS_stat: ::c_long = 5000 + 4; pub const SYS_fstat: ::c_long = 5000 + 5; pub const SYS_lstat: ::c_long = 5000 + 6; pub const SYS_poll: ::c_long = 5000 + 7; pub const SYS_lseek: ::c_long = 5000 + 8; pub const SYS_mmap: ::c_long = 5000 + 9; pub const SYS_mprotect: ::c_long = 5000 + 10; pub const SYS_munmap: ::c_long = 5000 + 11; pub const SYS_brk: ::c_long = 5000 + 12; pub const SYS_rt_sigaction: ::c_long = 5000 + 13; pub const SYS_rt_sigprocmask: ::c_long = 5000 + 14; pub const SYS_ioctl: ::c_long = 5000 + 15; pub const SYS_pread64: ::c_long = 5000 + 16; pub const SYS_pwrite64: ::c_long = 5000 + 17; pub const SYS_readv: ::c_long = 5000 + 18; pub const SYS_writev: ::c_long = 5000 + 19; pub const SYS_access: ::c_long = 5000 + 20; pub const SYS_pipe: ::c_long = 5000 + 21; pub const SYS__newselect: ::c_long = 5000 + 22; pub const SYS_sched_yield: ::c_long = 5000 + 23; pub const SYS_mremap: ::c_long = 5000 + 24; pub const SYS_msync: ::c_long = 5000 + 25; pub const SYS_mincore: ::c_long = 5000 + 26; pub const SYS_madvise: ::c_long = 5000 + 27; pub const SYS_shmget: ::c_long = 5000 + 28; pub const SYS_shmat: ::c_long = 5000 + 29; pub const SYS_shmctl: ::c_long = 5000 + 30; pub const SYS_dup: ::c_long = 5000 + 31; pub const SYS_dup2: ::c_long = 5000 + 32; pub const SYS_pause: ::c_long = 5000 + 33; pub const SYS_nanosleep: ::c_long = 5000 + 34; pub const SYS_getitimer: ::c_long = 5000 + 35; pub const SYS_setitimer: ::c_long = 5000 + 36; pub const SYS_alarm: ::c_long = 5000 + 37; pub const SYS_getpid: ::c_long = 5000 + 38; pub const SYS_sendfile: ::c_long = 5000 + 39; pub const SYS_socket: ::c_long = 5000 + 40; pub const SYS_connect: ::c_long = 5000 + 41; pub const SYS_accept: ::c_long = 5000 + 42; pub const SYS_sendto: ::c_long = 5000 + 43; pub const SYS_recvfrom: ::c_long = 5000 + 44; pub const SYS_sendmsg: ::c_long = 5000 + 45; pub const SYS_recvmsg: ::c_long = 5000 + 46; pub const SYS_shutdown: ::c_long = 5000 + 47; pub const SYS_bind: ::c_long = 5000 + 48; pub const SYS_listen: ::c_long = 5000 + 49; pub const SYS_getsockname: ::c_long = 5000 + 50; pub const SYS_getpeername: ::c_long = 5000 + 51; pub const SYS_socketpair: ::c_long = 5000 + 52; pub const SYS_setsockopt: ::c_long = 5000 + 53; pub const SYS_getsockopt: ::c_long = 5000 + 54; pub const SYS_clone: ::c_long = 5000 + 55; pub const SYS_fork: ::c_long = 5000 + 56; pub const SYS_execve: ::c_long = 5000 + 57; pub const SYS_exit: ::c_long = 5000 + 58; pub const SYS_wait4: ::c_long = 5000 + 59; pub const SYS_kill: ::c_long = 5000 + 60; pub const SYS_uname: ::c_long = 5000 + 61; pub const SYS_semget: ::c_long = 5000 + 62; pub const SYS_semop: ::c_long = 5000 + 63; pub const SYS_semctl: ::c_long = 5000 + 64; pub const SYS_shmdt: ::c_long = 5000 + 65; pub const SYS_msgget: ::c_long = 5000 + 66; pub const SYS_msgsnd: ::c_long = 5000 + 67; pub const SYS_msgrcv: ::c_long = 5000 + 68; pub const SYS_msgctl: ::c_long = 5000 + 69; pub const SYS_fcntl: ::c_long = 5000 + 70; pub const SYS_flock: ::c_long = 5000 + 71; pub const SYS_fsync: ::c_long = 5000 + 72; pub const SYS_fdatasync: ::c_long = 5000 + 73; pub const SYS_truncate: ::c_long = 5000 + 74; pub const SYS_ftruncate: ::c_long = 5000 + 75; pub const SYS_getdents: ::c_long = 5000 + 76; pub const SYS_getcwd: ::c_long = 5000 + 77; pub const SYS_chdir: ::c_long = 5000 + 78; pub const SYS_fchdir: ::c_long = 5000 + 79; pub const SYS_rename: ::c_long = 5000 + 80; pub const SYS_mkdir: ::c_long = 5000 + 81; pub const SYS_rmdir: ::c_long = 5000 + 82; pub const SYS_creat: ::c_long = 5000 + 83; pub const SYS_link: ::c_long = 5000 + 84; pub const SYS_unlink: ::c_long = 5000 + 85; pub const SYS_symlink: ::c_long = 5000 + 86; pub const SYS_readlink: ::c_long = 5000 + 87; pub const SYS_chmod: ::c_long = 5000 + 88; pub const SYS_fchmod: ::c_long = 5000 + 89; pub const SYS_chown: ::c_long = 5000 + 90; pub const SYS_fchown: ::c_long = 5000 + 91; pub const SYS_lchown: ::c_long = 5000 + 92; pub const SYS_umask: ::c_long = 5000 + 93; pub const SYS_gettimeofday: ::c_long = 5000 + 94; pub const SYS_getrlimit: ::c_long = 5000 + 95; pub const SYS_getrusage: ::c_long = 5000 + 96; pub const SYS_sysinfo: ::c_long = 5000 + 97; pub const SYS_times: ::c_long = 5000 + 98; pub const SYS_ptrace: ::c_long = 5000 + 99; pub const SYS_getuid: ::c_long = 5000 + 100; pub const SYS_syslog: ::c_long = 5000 + 101; pub const SYS_getgid: ::c_long = 5000 + 102; pub const SYS_setuid: ::c_long = 5000 + 103; pub const SYS_setgid: ::c_long = 5000 + 104; pub const SYS_geteuid: ::c_long = 5000 + 105; pub const SYS_getegid: ::c_long = 5000 + 106; pub const SYS_setpgid: ::c_long = 5000 + 107; pub const SYS_getppid: ::c_long = 5000 + 108; pub const SYS_getpgrp: ::c_long = 5000 + 109; pub const SYS_setsid: ::c_long = 5000 + 110; pub const SYS_setreuid: ::c_long = 5000 + 111; pub const SYS_setregid: ::c_long = 5000 + 112; pub const SYS_getgroups: ::c_long = 5000 + 113; pub const SYS_setgroups: ::c_long = 5000 + 114; pub const SYS_setresuid: ::c_long = 5000 + 115; pub const SYS_getresuid: ::c_long = 5000 + 116; pub const SYS_setresgid: ::c_long = 5000 + 117; pub const SYS_getresgid: ::c_long = 5000 + 118; pub const SYS_getpgid: ::c_long = 5000 + 119; pub const SYS_setfsuid: ::c_long = 5000 + 120; pub const SYS_setfsgid: ::c_long = 5000 + 121; pub const SYS_getsid: ::c_long = 5000 + 122; pub const SYS_capget: ::c_long = 5000 + 123; pub const SYS_capset: ::c_long = 5000 + 124; pub const SYS_rt_sigpending: ::c_long = 5000 + 125; pub const SYS_rt_sigtimedwait: ::c_long = 5000 + 126; pub const SYS_rt_sigqueueinfo: ::c_long = 5000 + 127; pub const SYS_rt_sigsuspend: ::c_long = 5000 + 128; pub const SYS_sigaltstack: ::c_long = 5000 + 129; pub const SYS_utime: ::c_long = 5000 + 130; pub const SYS_mknod: ::c_long = 5000 + 131; pub const SYS_personality: ::c_long = 5000 + 132; pub const SYS_ustat: ::c_long = 5000 + 133; pub const SYS_statfs: ::c_long = 5000 + 134; pub const SYS_fstatfs: ::c_long = 5000 + 135; pub const SYS_sysfs: ::c_long = 5000 + 136; pub const SYS_getpriority: ::c_long = 5000 + 137; pub const SYS_setpriority: ::c_long = 5000 + 138; pub const SYS_sched_setparam: ::c_long = 5000 + 139; pub const SYS_sched_getparam: ::c_long = 5000 + 140; pub const SYS_sched_setscheduler: ::c_long = 5000 + 141; pub const SYS_sched_getscheduler: ::c_long = 5000 + 142; pub const SYS_sched_get_priority_max: ::c_long = 5000 + 143; pub const SYS_sched_get_priority_min: ::c_long = 5000 + 144; pub const SYS_sched_rr_get_interval: ::c_long = 5000 + 145; pub const SYS_mlock: ::c_long = 5000 + 146; pub const SYS_munlock: ::c_long = 5000 + 147; pub const SYS_mlockall: ::c_long = 5000 + 148; pub const SYS_munlockall: ::c_long = 5000 + 149; pub const SYS_vhangup: ::c_long = 5000 + 150; pub const SYS_pivot_root: ::c_long = 5000 + 151; pub const SYS__sysctl: ::c_long = 5000 + 152; pub const SYS_prctl: ::c_long = 5000 + 153; pub const SYS_adjtimex: ::c_long = 5000 + 154; pub const SYS_setrlimit: ::c_long = 5000 + 155; pub const SYS_chroot: ::c_long = 5000 + 156; pub const SYS_sync: ::c_long = 5000 + 157; pub const SYS_acct: ::c_long = 5000 + 158; pub const SYS_settimeofday: ::c_long = 5000 + 159; pub const SYS_mount: ::c_long = 5000 + 160; pub const SYS_umount2: ::c_long = 5000 + 161; pub const SYS_swapon: ::c_long = 5000 + 162; pub const SYS_swapoff: ::c_long = 5000 + 163; pub const SYS_reboot: ::c_long = 5000 + 164; pub const SYS_sethostname: ::c_long = 5000 + 165; pub const SYS_setdomainname: ::c_long = 5000 + 166; pub const SYS_create_module: ::c_long = 5000 + 167; pub const SYS_init_module: ::c_long = 5000 + 168; pub const SYS_delete_module: ::c_long = 5000 + 169; pub const SYS_get_kernel_syms: ::c_long = 5000 + 170; pub const SYS_query_module: ::c_long = 5000 + 171; pub const SYS_quotactl: ::c_long = 5000 + 172; pub const SYS_nfsservctl: ::c_long = 5000 + 173; pub const SYS_getpmsg: ::c_long = 5000 + 174; pub const SYS_putpmsg: ::c_long = 5000 + 175; pub const SYS_afs_syscall: ::c_long = 5000 + 176; pub const SYS_gettid: ::c_long = 5000 + 178; pub const SYS_readahead: ::c_long = 5000 + 179; pub const SYS_setxattr: ::c_long = 5000 + 180; pub const SYS_lsetxattr: ::c_long = 5000 + 181; pub const SYS_fsetxattr: ::c_long = 5000 + 182; pub const SYS_getxattr: ::c_long = 5000 + 183; pub const SYS_lgetxattr: ::c_long = 5000 + 184; pub const SYS_fgetxattr: ::c_long = 5000 + 185; pub const SYS_listxattr: ::c_long = 5000 + 186; pub const SYS_llistxattr: ::c_long = 5000 + 187; pub const SYS_flistxattr: ::c_long = 5000 + 188; pub const SYS_removexattr: ::c_long = 5000 + 189; pub const SYS_lremovexattr: ::c_long = 5000 + 190; pub const SYS_fremovexattr: ::c_long = 5000 + 191; pub const SYS_tkill: ::c_long = 5000 + 192; pub const SYS_futex: ::c_long = 5000 + 194; pub const SYS_sched_setaffinity: ::c_long = 5000 + 195; pub const SYS_sched_getaffinity: ::c_long = 5000 + 196; pub const SYS_cacheflush: ::c_long = 5000 + 197; pub const SYS_cachectl: ::c_long = 5000 + 198; pub const SYS_sysmips: ::c_long = 5000 + 199; pub const SYS_io_setup: ::c_long = 5000 + 200; pub const SYS_io_destroy: ::c_long = 5000 + 201; pub const SYS_io_getevents: ::c_long = 5000 + 202; pub const SYS_io_submit: ::c_long = 5000 + 203; pub const SYS_io_cancel: ::c_long = 5000 + 204; pub const SYS_exit_group: ::c_long = 5000 + 205; pub const SYS_lookup_dcookie: ::c_long = 5000 + 206; pub const SYS_epoll_create: ::c_long = 5000 + 207; pub const SYS_epoll_ctl: ::c_long = 5000 + 208; pub const SYS_epoll_wait: ::c_long = 5000 + 209; pub const SYS_remap_file_pages: ::c_long = 5000 + 210; pub const SYS_rt_sigreturn: ::c_long = 5000 + 211; pub const SYS_set_tid_address: ::c_long = 5000 + 212; pub const SYS_restart_syscall: ::c_long = 5000 + 213; pub const SYS_semtimedop: ::c_long = 5000 + 214; pub const SYS_fadvise64: ::c_long = 5000 + 215; pub const SYS_timer_create: ::c_long = 5000 + 216; pub const SYS_timer_settime: ::c_long = 5000 + 217; pub const SYS_timer_gettime: ::c_long = 5000 + 218; pub const SYS_timer_getoverrun: ::c_long = 5000 + 219; pub const SYS_timer_delete: ::c_long = 5000 + 220; pub const SYS_clock_settime: ::c_long = 5000 + 221; pub const SYS_clock_gettime: ::c_long = 5000 + 222; pub const SYS_clock_getres: ::c_long = 5000 + 223; pub const SYS_clock_nanosleep: ::c_long = 5000 + 224; pub const SYS_tgkill: ::c_long = 5000 + 225; pub const SYS_utimes: ::c_long = 5000 + 226; pub const SYS_mbind: ::c_long = 5000 + 227; pub const SYS_get_mempolicy: ::c_long = 5000 + 228; pub const SYS_set_mempolicy: ::c_long = 5000 + 229; pub const SYS_mq_open: ::c_long = 5000 + 230; pub const SYS_mq_unlink: ::c_long = 5000 + 231; pub const SYS_mq_timedsend: ::c_long = 5000 + 232; pub const SYS_mq_timedreceive: ::c_long = 5000 + 233; pub const SYS_mq_notify: ::c_long = 5000 + 234; pub const SYS_mq_getsetattr: ::c_long = 5000 + 235; pub const SYS_vserver: ::c_long = 5000 + 236; pub const SYS_waitid: ::c_long = 5000 + 237; /* pub const SYS_sys_setaltroot: ::c_long = 5000 + 238; */ pub const SYS_add_key: ::c_long = 5000 + 239; pub const SYS_request_key: ::c_long = 5000 + 240; pub const SYS_keyctl: ::c_long = 5000 + 241; pub const SYS_set_thread_area: ::c_long = 5000 + 242; pub const SYS_inotify_init: ::c_long = 5000 + 243; pub const SYS_inotify_add_watch: ::c_long = 5000 + 244; pub const SYS_inotify_rm_watch: ::c_long = 5000 + 245; pub const SYS_migrate_pages: ::c_long = 5000 + 246; pub const SYS_openat: ::c_long = 5000 + 247; pub const SYS_mkdirat: ::c_long = 5000 + 248; pub const SYS_mknodat: ::c_long = 5000 + 249; pub const SYS_fchownat: ::c_long = 5000 + 250; pub const SYS_futimesat: ::c_long = 5000 + 251; pub const SYS_newfstatat: ::c_long = 5000 + 252; pub const SYS_unlinkat: ::c_long = 5000 + 253; pub const SYS_renameat: ::c_long = 5000 + 254; pub const SYS_linkat: ::c_long = 5000 + 255; pub const SYS_symlinkat: ::c_long = 5000 + 256; pub const SYS_readlinkat: ::c_long = 5000 + 257; pub const SYS_fchmodat: ::c_long = 5000 + 258; pub const SYS_faccessat: ::c_long = 5000 + 259; pub const SYS_pselect6: ::c_long = 5000 + 260; pub const SYS_ppoll: ::c_long = 5000 + 261; pub const SYS_unshare: ::c_long = 5000 + 262; pub const SYS_splice: ::c_long = 5000 + 263; pub const SYS_sync_file_range: ::c_long = 5000 + 264; pub const SYS_tee: ::c_long = 5000 + 265; pub const SYS_vmsplice: ::c_long = 5000 + 266; pub const SYS_move_pages: ::c_long = 5000 + 267; pub const SYS_set_robust_list: ::c_long = 5000 + 268; pub const SYS_get_robust_list: ::c_long = 5000 + 269; pub const SYS_kexec_load: ::c_long = 5000 + 270; pub const SYS_getcpu: ::c_long = 5000 + 271; pub const SYS_epoll_pwait: ::c_long = 5000 + 272; pub const SYS_ioprio_set: ::c_long = 5000 + 273; pub const SYS_ioprio_get: ::c_long = 5000 + 274; pub const SYS_utimensat: ::c_long = 5000 + 275; pub const SYS_signalfd: ::c_long = 5000 + 276; pub const SYS_timerfd: ::c_long = 5000 + 277; pub const SYS_eventfd: ::c_long = 5000 + 278; pub const SYS_fallocate: ::c_long = 5000 + 279; pub const SYS_timerfd_create: ::c_long = 5000 + 280; pub const SYS_timerfd_gettime: ::c_long = 5000 + 281; pub const SYS_timerfd_settime: ::c_long = 5000 + 282; pub const SYS_signalfd4: ::c_long = 5000 + 283; pub const SYS_eventfd2: ::c_long = 5000 + 284; pub const SYS_epoll_create1: ::c_long = 5000 + 285; pub const SYS_dup3: ::c_long = 5000 + 286; pub const SYS_pipe2: ::c_long = 5000 + 287; pub const SYS_inotify_init1: ::c_long = 5000 + 288; pub const SYS_preadv: ::c_long = 5000 + 289; pub const SYS_pwritev: ::c_long = 5000 + 290; pub const SYS_rt_tgsigqueueinfo: ::c_long = 5000 + 291; pub const SYS_perf_event_open: ::c_long = 5000 + 292; pub const SYS_accept4: ::c_long = 5000 + 293; pub const SYS_recvmmsg: ::c_long = 5000 + 294; pub const SYS_fanotify_init: ::c_long = 5000 + 295; pub const SYS_fanotify_mark: ::c_long = 5000 + 296; pub const SYS_prlimit64: ::c_long = 5000 + 297; pub const SYS_name_to_handle_at: ::c_long = 5000 + 298; pub const SYS_open_by_handle_at: ::c_long = 5000 + 299; pub const SYS_clock_adjtime: ::c_long = 5000 + 300; pub const SYS_syncfs: ::c_long = 5000 + 301; pub const SYS_sendmmsg: ::c_long = 5000 + 302; pub const SYS_setns: ::c_long = 5000 + 303; pub const SYS_process_vm_readv: ::c_long = 5000 + 304; pub const SYS_process_vm_writev: ::c_long = 5000 + 305; pub const SYS_kcmp: ::c_long = 5000 + 306; pub const SYS_finit_module: ::c_long = 5000 + 307; pub const SYS_getdents64: ::c_long = 5000 + 308; pub const SYS_sched_setattr: ::c_long = 5000 + 309; pub const SYS_sched_getattr: ::c_long = 5000 + 310; pub const SYS_renameat2: ::c_long = 5000 + 311; pub const SYS_seccomp: ::c_long = 5000 + 312; pub const SYS_getrandom: ::c_long = 5000 + 313; pub const SYS_memfd_create: ::c_long = 5000 + 314; pub const SYS_bpf: ::c_long = 5000 + 315; pub const SYS_execveat: ::c_long = 5000 + 316; pub const SYS_userfaultfd: ::c_long = 5000 + 317; pub const SYS_membarrier: ::c_long = 5000 + 318; pub const SYS_mlock2: ::c_long = 5000 + 319; pub const SYS_copy_file_range: ::c_long = 5000 + 320; pub const SYS_preadv2: ::c_long = 5000 + 321; pub const SYS_pwritev2: ::c_long = 5000 + 322; pub const SYS_pkey_mprotect: ::c_long = 5000 + 323; pub const SYS_pkey_alloc: ::c_long = 5000 + 324; pub const SYS_pkey_free: ::c_long = 5000 + 325; pub const SYS_statx: ::c_long = 5000 + 326; pub const SYS_pidfd_send_signal: ::c_long = 5000 + 424; pub const SYS_io_uring_setup: ::c_long = 5000 + 425; pub const SYS_io_uring_enter: ::c_long = 5000 + 426; pub const SYS_io_uring_register: ::c_long = 5000 + 427; pub const SYS_open_tree: ::c_long = 5000 + 428; pub const SYS_move_mount: ::c_long = 5000 + 429; pub const SYS_fsopen: ::c_long = 5000 + 430; pub const SYS_fsconfig: ::c_long = 5000 + 431; pub const SYS_fsmount: ::c_long = 5000 + 432; pub const SYS_fspick: ::c_long = 5000 + 433; pub const SYS_pidfd_open: ::c_long = 5000 + 434; pub const SYS_clone3: ::c_long = 5000 + 435; pub const SYS_close_range: ::c_long = 5000 + 436; pub const SYS_openat2: ::c_long = 5000 + 437; pub const SYS_pidfd_getfd: ::c_long = 5000 + 438; pub const SYS_faccessat2: ::c_long = 5000 + 439; pub const SYS_process_madvise: ::c_long = 5000 + 440; pub const SYS_epoll_pwait2: ::c_long = 5000 + 441; pub const SYS_mount_setattr: ::c_long = 5000 + 442; pub const SYS_quotactl_fd: ::c_long = 5000 + 443; pub const SYS_landlock_create_ruleset: ::c_long = 5000 + 444; pub const SYS_landlock_add_rule: ::c_long = 5000 + 445; pub const SYS_landlock_restrict_self: ::c_long = 5000 + 446; pub const SYS_memfd_secret: ::c_long = 5000 + 447; pub const SYS_process_mrelease: ::c_long = 5000 + 448; pub const SYS_futex_waitv: ::c_long = 5000 + 449; pub const SYS_set_mempolicy_home_node: ::c_long = 5000 + 450; pub const O_DIRECT: ::c_int = 0x8000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_APPEND: ::c_int = 8; pub const O_CREAT: ::c_int = 256; pub const O_EXCL: ::c_int = 1024; pub const O_NOCTTY: ::c_int = 2048; pub const O_NONBLOCK: ::c_int = 128; pub const O_SYNC: ::c_int = 0x4010; pub const O_RSYNC: ::c_int = 0x4010; pub const O_DSYNC: ::c_int = 0x10; pub const O_ASYNC: ::c_int = 0x1000; pub const O_LARGEFILE: ::c_int = 0x2000; pub const EDEADLK: ::c_int = 45; pub const ENAMETOOLONG: ::c_int = 78; pub const ENOLCK: ::c_int = 46; pub const ENOSYS: ::c_int = 89; pub const ENOTEMPTY: ::c_int = 93; pub const ELOOP: ::c_int = 90; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EBADE: ::c_int = 50; pub const EBADR: ::c_int = 51; pub const EXFULL: ::c_int = 52; pub const ENOANO: ::c_int = 53; pub const EBADRQC: ::c_int = 54; pub const EBADSLT: ::c_int = 55; pub const EDEADLOCK: ::c_int = 56; pub const EMULTIHOP: ::c_int = 74; pub const EOVERFLOW: ::c_int = 79; pub const ENOTUNIQ: ::c_int = 80; pub const EBADFD: ::c_int = 81; pub const EBADMSG: ::c_int = 77; pub const EREMCHG: ::c_int = 82; pub const ELIBACC: ::c_int = 83; pub const ELIBBAD: ::c_int = 84; pub const ELIBSCN: ::c_int = 85; pub const ELIBMAX: ::c_int = 86; pub const ELIBEXEC: ::c_int = 87; pub const EILSEQ: ::c_int = 88; pub const ERESTART: ::c_int = 91; pub const ESTRPIPE: ::c_int = 92; pub const EUSERS: ::c_int = 94; pub const ENOTSOCK: ::c_int = 95; pub const EDESTADDRREQ: ::c_int = 96; pub const EMSGSIZE: ::c_int = 97; pub const EPROTOTYPE: ::c_int = 98; pub const ENOPROTOOPT: ::c_int = 99; pub const EPROTONOSUPPORT: ::c_int = 120; pub const ESOCKTNOSUPPORT: ::c_int = 121; pub const EOPNOTSUPP: ::c_int = 122; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 123; pub const EAFNOSUPPORT: ::c_int = 124; pub const EADDRINUSE: ::c_int = 125; pub const EADDRNOTAVAIL: ::c_int = 126; pub const ENETDOWN: ::c_int = 127; pub const ENETUNREACH: ::c_int = 128; pub const ENETRESET: ::c_int = 129; pub const ECONNABORTED: ::c_int = 130; pub const ECONNRESET: ::c_int = 131; pub const ENOBUFS: ::c_int = 132; pub const EISCONN: ::c_int = 133; pub const ENOTCONN: ::c_int = 134; pub const ESHUTDOWN: ::c_int = 143; pub const ETOOMANYREFS: ::c_int = 144; pub const ETIMEDOUT: ::c_int = 145; pub const ECONNREFUSED: ::c_int = 146; pub const EHOSTDOWN: ::c_int = 147; pub const EHOSTUNREACH: ::c_int = 148; pub const EALREADY: ::c_int = 149; pub const EINPROGRESS: ::c_int = 150; pub const ESTALE: ::c_int = 151; pub const EUCLEAN: ::c_int = 135; pub const ENOTNAM: ::c_int = 137; pub const ENAVAIL: ::c_int = 138; pub const EISNAM: ::c_int = 139; pub const EREMOTEIO: ::c_int = 140; pub const EDQUOT: ::c_int = 1133; pub const ENOMEDIUM: ::c_int = 159; pub const EMEDIUMTYPE: ::c_int = 160; pub const ECANCELED: ::c_int = 158; pub const ENOKEY: ::c_int = 161; pub const EKEYEXPIRED: ::c_int = 162; pub const EKEYREVOKED: ::c_int = 163; pub const EKEYREJECTED: ::c_int = 164; pub const EOWNERDEAD: ::c_int = 165; pub const ENOTRECOVERABLE: ::c_int = 166; pub const ERFKILL: ::c_int = 167; pub const MAP_ANON: ::c_int = 0x800; pub const MAP_GROWSDOWN: ::c_int = 0x1000; pub const MAP_DENYWRITE: ::c_int = 0x2000; pub const MAP_EXECUTABLE: ::c_int = 0x4000; pub const MAP_LOCKED: ::c_int = 0x8000; pub const MAP_NORESERVE: ::c_int = 0x400; pub const MAP_POPULATE: ::c_int = 0x10000; pub const MAP_NONBLOCK: ::c_int = 0x20000; pub const MAP_STACK: ::c_int = 0x40000; pub const MAP_HUGETLB: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000008; pub const SA_NOCLDWAIT: ::c_int = 0x00010000; pub const SIGCHLD: ::c_int = 18; pub const SIGBUS: ::c_int = 10; pub const SIGTTIN: ::c_int = 26; pub const SIGTTOU: ::c_int = 27; pub const SIGXCPU: ::c_int = 30; pub const SIGXFSZ: ::c_int = 31; pub const SIGVTALRM: ::c_int = 28; pub const SIGPROF: ::c_int = 29; pub const SIGWINCH: ::c_int = 20; pub const SIGUSR1: ::c_int = 16; pub const SIGUSR2: ::c_int = 17; pub const SIGCONT: ::c_int = 25; pub const SIGSTOP: ::c_int = 23; pub const SIGTSTP: ::c_int = 24; pub const SIGURG: ::c_int = 21; pub const SIGIO: ::c_int = 22; pub const SIGSYS: ::c_int = 12; pub const SIGPOLL: ::c_int = 22; pub const SIGPWR: ::c_int = 19; pub const SIG_SETMASK: ::c_int = 3; pub const SIG_BLOCK: ::c_int = 0x1; pub const SIG_UNBLOCK: ::c_int = 0x2; pub const POLLWRNORM: ::c_short = 0x004; pub const POLLWRBAND: ::c_short = 0x100; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: ::tcflag_t = 0x00000100; pub const TOSTOP: ::tcflag_t = 0x00008000; pub const FLUSHO: ::tcflag_t = 0x00002000; pub const EXTPROC: ::tcflag_t = 0o200000; pub const F_GETLK: ::c_int = 14; pub const F_GETOWN: ::c_int = 23; pub const F_SETOWN: ::c_int = 24; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const EHWPOISON: ::c_int = 168; libc/src/unix/linux_like/linux/musl/b64/aarch64/0000775000175000017500000000000014661133735022333 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs0000644000175000017500000000021614661133735023723 0ustar jamespagejamespages! { pub struct user_fpsimd_struct { pub vregs: [::__uint128_t; 32], pub fpsr: u32, pub fpcr: u32, } } libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs0000644000175000017500000005712414661133735023467 0ustar jamespagejamespagepub type c_char = u8; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; pub type wchar_t = u32; pub type nlink_t = u32; pub type blksize_t = ::c_int; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad0: ::c_ulong, pub st_size: ::off_t, pub st_blksize: ::blksize_t, __pad1: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_uint; 2], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad0: ::c_ulong, pub st_size: ::off_t, pub st_blksize: ::blksize_t, __pad1: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_uint; 2], } pub struct user_regs_struct { pub regs: [::c_ulonglong; 31], pub sp: ::c_ulonglong, pub pc: ::c_ulonglong, pub pstate: ::c_ulonglong, } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } } pub const O_APPEND: ::c_int = 1024; pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_LARGEFILE: ::c_int = 0x20000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_ASYNC: ::c_int = 0x2000; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; // bits/hwcap.h pub const HWCAP_FP: ::c_ulong = 1 << 0; pub const HWCAP_ASIMD: ::c_ulong = 1 << 1; pub const HWCAP_EVTSTRM: ::c_ulong = 1 << 2; pub const HWCAP_AES: ::c_ulong = 1 << 3; pub const HWCAP_PMULL: ::c_ulong = 1 << 4; pub const HWCAP_SHA1: ::c_ulong = 1 << 5; pub const HWCAP_SHA2: ::c_ulong = 1 << 6; pub const HWCAP_CRC32: ::c_ulong = 1 << 7; pub const HWCAP_ATOMICS: ::c_ulong = 1 << 8; pub const HWCAP_FPHP: ::c_ulong = 1 << 9; pub const HWCAP_ASIMDHP: ::c_ulong = 1 << 10; pub const HWCAP_CPUID: ::c_ulong = 1 << 11; pub const HWCAP_ASIMDRDM: ::c_ulong = 1 << 12; pub const HWCAP_JSCVT: ::c_ulong = 1 << 13; pub const HWCAP_FCMA: ::c_ulong = 1 << 14; pub const HWCAP_LRCPC: ::c_ulong = 1 << 15; pub const HWCAP_DCPOP: ::c_ulong = 1 << 16; pub const HWCAP_SHA3: ::c_ulong = 1 << 17; pub const HWCAP_SM3: ::c_ulong = 1 << 18; pub const HWCAP_SM4: ::c_ulong = 1 << 19; pub const HWCAP_ASIMDDP: ::c_ulong = 1 << 20; pub const HWCAP_SHA512: ::c_ulong = 1 << 21; pub const HWCAP_SVE: ::c_ulong = 1 << 22; pub const HWCAP_ASIMDFHM: ::c_ulong = 1 << 23; pub const HWCAP_DIT: ::c_ulong = 1 << 24; pub const HWCAP_USCAT: ::c_ulong = 1 << 25; pub const HWCAP_ILRCPC: ::c_ulong = 1 << 26; pub const HWCAP_FLAGM: ::c_ulong = 1 << 27; pub const HWCAP_SSBS: ::c_ulong = 1 << 28; pub const HWCAP_SB: ::c_ulong = 1 << 29; pub const HWCAP_PACA: ::c_ulong = 1 << 30; pub const HWCAP_PACG: ::c_ulong = 1 << 31; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const MINSIGSTKSZ: ::size_t = 6144; pub const SIGSTKSZ: ::size_t = 12288; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_getcwd: ::c_long = 17; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_dup: ::c_long = 23; pub const SYS_dup3: ::c_long = 24; pub const SYS_fcntl: ::c_long = 25; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_ioctl: ::c_long = 29; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_flock: ::c_long = 32; pub const SYS_mknodat: ::c_long = 33; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_linkat: ::c_long = 37; pub const SYS_renameat: ::c_long = 38; pub const SYS_umount2: ::c_long = 39; pub const SYS_mount: ::c_long = 40; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_fallocate: ::c_long = 47; pub const SYS_faccessat: ::c_long = 48; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_chroot: ::c_long = 51; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_fchownat: ::c_long = 54; pub const SYS_fchown: ::c_long = 55; pub const SYS_openat: ::c_long = 56; pub const SYS_close: ::c_long = 57; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pipe2: ::c_long = 59; pub const SYS_quotactl: ::c_long = 60; pub const SYS_getdents64: ::c_long = 61; pub const SYS_lseek: ::c_long = 62; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_newfstatat: ::c_long = 79; pub const SYS_fstat: ::c_long = 80; pub const SYS_sync: ::c_long = 81; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_utimensat: ::c_long = 88; pub const SYS_acct: ::c_long = 89; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_personality: ::c_long = 92; pub const SYS_exit: ::c_long = 93; pub const SYS_exit_group: ::c_long = 94; pub const SYS_waitid: ::c_long = 95; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_unshare: ::c_long = 97; pub const SYS_futex: ::c_long = 98; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_syslog: ::c_long = 116; pub const SYS_ptrace: ::c_long = 117; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_kill: ::c_long = 129; pub const SYS_tkill: ::c_long = 130; pub const SYS_tgkill: ::c_long = 131; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_setpriority: ::c_long = 140; pub const SYS_getpriority: ::c_long = 141; pub const SYS_reboot: ::c_long = 142; pub const SYS_setregid: ::c_long = 143; pub const SYS_setgid: ::c_long = 144; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setuid: ::c_long = 146; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_times: ::c_long = 153; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getpgid: ::c_long = 155; pub const SYS_getsid: ::c_long = 156; pub const SYS_setsid: ::c_long = 157; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_uname: ::c_long = 160; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_getrusage: ::c_long = 165; pub const SYS_umask: ::c_long = 166; pub const SYS_prctl: ::c_long = 167; pub const SYS_getcpu: ::c_long = 168; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_getpid: ::c_long = 172; pub const SYS_getppid: ::c_long = 173; pub const SYS_getuid: ::c_long = 174; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getgid: ::c_long = 176; pub const SYS_getegid: ::c_long = 177; pub const SYS_gettid: ::c_long = 178; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgctl: ::c_long = 187; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_semget: ::c_long = 190; pub const SYS_semctl: ::c_long = 191; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_semop: ::c_long = 193; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmctl: ::c_long = 195; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmdt: ::c_long = 197; pub const SYS_socket: ::c_long = 198; pub const SYS_socketpair: ::c_long = 199; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_accept: ::c_long = 202; pub const SYS_connect: ::c_long = 203; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_shutdown: ::c_long = 210; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_readahead: ::c_long = 213; pub const SYS_brk: ::c_long = 214; pub const SYS_munmap: ::c_long = 215; pub const SYS_mremap: ::c_long = 216; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_mmap: ::c_long = 222; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_mprotect: ::c_long = 226; pub const SYS_msync: ::c_long = 227; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_mbind: ::c_long = 235; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_move_pages: ::c_long = 239; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_accept4: ::c_long = 242; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_wait4: ::c_long = 260; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_setns: ::c_long = 268; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } cfg_if! { if #[cfg(libc_int128)] { mod int128; pub use self::int128::*; } } libc/src/unix/linux_like/linux/musl/b64/aarch64/align.rs0000644000175000017500000000207014661133735023770 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8] } } s! { pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub fault_address: ::c_ulong, pub regs: [::c_ulong; 31], pub sp: ::c_ulong, pub pc: ::c_ulong, pub pstate: ::c_ulong, __reserved: [[u64; 32]; 16], } #[repr(align(8))] pub struct clone_args { pub flags: ::c_ulonglong, pub pidfd: ::c_ulonglong, pub child_tid: ::c_ulonglong, pub parent_tid: ::c_ulonglong, pub exit_signal: ::c_ulonglong, pub stack: ::c_ulonglong, pub stack_size: ::c_ulonglong, pub tls: ::c_ulonglong, pub set_tid: ::c_ulonglong, pub set_tid_size: ::c_ulonglong, pub cgroup: ::c_ulonglong, } } libc/src/unix/linux_like/linux/musl/b64/riscv64/0000775000175000017500000000000014661133735022403 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs0000644000175000017500000006212014661133735023527 0ustar jamespagejamespage//! RISC-V-specific definitions for 64-bit linux-like values pub type c_char = u8; pub type wchar_t = ::c_int; pub type nlink_t = ::c_uint; pub type blksize_t = ::c_int; pub type fsblkcnt64_t = ::c_ulong; pub type fsfilcnt64_t = ::c_ulong; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct pthread_attr_t { __size: [::c_ulong; 7], } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2usize], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statfs64 { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_favail: ::fsfilcnt64_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused5: ::c_ulong, __unused6: ::c_ulong, } } pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_close: ::c_long = 57; pub const SYS_fstat: ::c_long = 80; pub const SYS_lseek: ::c_long = 62; pub const SYS_mmap: ::c_long = 222; pub const SYS_mprotect: ::c_long = 226; pub const SYS_munmap: ::c_long = 215; pub const SYS_brk: ::c_long = 214; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_ioctl: ::c_long = 29; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_mremap: ::c_long = 216; pub const SYS_msync: ::c_long = 227; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmctl: ::c_long = 195; pub const SYS_dup: ::c_long = 23; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_getpid: ::c_long = 172; pub const SYS_sendfile: ::c_long = 71; pub const SYS_socket: ::c_long = 198; pub const SYS_connect: ::c_long = 203; pub const SYS_accept: ::c_long = 202; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_shutdown: ::c_long = 210; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_socketpair: ::c_long = 199; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_exit: ::c_long = 93; pub const SYS_wait4: ::c_long = 260; pub const SYS_kill: ::c_long = 129; pub const SYS_uname: ::c_long = 160; pub const SYS_semget: ::c_long = 190; pub const SYS_semop: ::c_long = 193; pub const SYS_semctl: ::c_long = 191; pub const SYS_shmdt: ::c_long = 197; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgctl: ::c_long = 187; pub const SYS_fcntl: ::c_long = 25; pub const SYS_flock: ::c_long = 32; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_getcwd: ::c_long = 17; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchown: ::c_long = 55; pub const SYS_umask: ::c_long = 166; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_getrusage: ::c_long = 165; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_times: ::c_long = 153; pub const SYS_ptrace: ::c_long = 117; pub const SYS_getuid: ::c_long = 174; pub const SYS_syslog: ::c_long = 116; pub const SYS_getgid: ::c_long = 176; pub const SYS_setuid: ::c_long = 146; pub const SYS_setgid: ::c_long = 144; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getegid: ::c_long = 177; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getppid: ::c_long = 173; pub const SYS_setsid: ::c_long = 157; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setregid: ::c_long = 143; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_getpgid: ::c_long = 155; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_getsid: ::c_long = 156; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_personality: ::c_long = 92; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_getpriority: ::c_long = 141; pub const SYS_setpriority: ::c_long = 140; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_prctl: ::c_long = 167; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_chroot: ::c_long = 51; pub const SYS_sync: ::c_long = 81; pub const SYS_acct: ::c_long = 89; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_mount: ::c_long = 40; pub const SYS_umount2: ::c_long = 39; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_reboot: ::c_long = 142; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_quotactl: ::c_long = 60; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_gettid: ::c_long = 178; pub const SYS_readahead: ::c_long = 213; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_tkill: ::c_long = 130; pub const SYS_futex: ::c_long = 98; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_getdents64: ::c_long = 61; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_fadvise64: ::c_long = 223; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_exit_group: ::c_long = 94; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_tgkill: ::c_long = 131; pub const SYS_mbind: ::c_long = 235; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_waitid: ::c_long = 95; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_openat: ::c_long = 56; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_mknodat: ::c_long = 33; pub const SYS_fchownat: ::c_long = 54; pub const SYS_newfstatat: ::c_long = 79; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_linkat: ::c_long = 37; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_faccessat: ::c_long = 48; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_unshare: ::c_long = 97; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_move_pages: ::c_long = 239; pub const SYS_utimensat: ::c_long = 88; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_fallocate: ::c_long = 47; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_accept4: ::c_long = 242; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_dup3: ::c_long = 24; pub const SYS_pipe2: ::c_long = 59; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_setns: ::c_long = 268; pub const SYS_getcpu: ::c_long = 168; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const O_APPEND: ::c_int = 1024; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_LARGEFILE: ::c_int = 0; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_ASYNC: ::c_int = 0x2000; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const NGREG: usize = 32; pub const REG_PC: usize = 0; pub const REG_RA: usize = 1; pub const REG_SP: usize = 2; pub const REG_TP: usize = 4; pub const REG_S0: usize = 8; pub const REG_S1: usize = 9; pub const REG_A0: usize = 10; pub const REG_S2: usize = 18; pub const REG_NARGS: usize = 8; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/musl/b64/riscv64/align.rs0000644000175000017500000000227514661133735024047 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub __uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct mcontext_t { pub __gregs: [::c_ulong; 32], pub __fpregs: __riscv_mc_fp_state, } #[allow(missing_debug_implementations)] pub union __riscv_mc_fp_state { pub __f: __riscv_mc_f_ext_state, pub __d: __riscv_mc_d_ext_state, pub __q: __riscv_mc_q_ext_state, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_f_ext_state { pub __f: [::c_uint; 32], pub __fcsr: ::c_uint, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_d_ext_state { pub __f: [::c_ulonglong; 32], pub __fcsr: ::c_uint, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct __riscv_mc_q_ext_state { pub __f: [::c_ulonglong; 64], pub __fcsr: ::c_uint, pub __glibc_reserved: [::c_uint; 3], } } libc/src/unix/linux_like/linux/musl/b64/mod.rs0000644000175000017500000001055714661133735022236 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type regoff_t = ::c_long; s! { pub struct statfs64 { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct pthread_attr_t { __size: [u64; 7] } pub struct sigset_t { __val: [::c_ulong; 16], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::c_ulong, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __pad1: ::c_ulong, __pad2: ::c_ulong, } pub struct statfs { pub f_type: ::c_ulong, pub f_bsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_ulong, pub f_frsize: ::c_ulong, pub f_flags: ::c_ulong, pub f_spare: [::c_ulong; 4], } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, #[cfg(target_endian = "big")] __pad1: ::c_int, pub msg_iovlen: ::c_int, #[cfg(target_endian = "little")] __pad1: ::c_int, pub msg_control: *mut ::c_void, #[cfg(target_endian = "big")] __pad2: ::c_int, pub msg_controllen: ::socklen_t, #[cfg(target_endian = "little")] __pad2: ::c_int, pub msg_flags: ::c_int, } pub struct cmsghdr { #[cfg(target_endian = "big")] pub __pad1: ::c_int, pub cmsg_len: ::socklen_t, #[cfg(target_endian = "little")] pub __pad1: ::c_int, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct sem_t { __val: [::c_int; 8], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } } pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; extern "C" { pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "mips64")] { mod mips64; pub use self::mips64::*; } else if #[cfg(any(target_arch = "powerpc64"))] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(any(target_arch = "s390x"))] { mod s390x; pub use self::s390x::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(any(target_arch = "riscv64"))] { mod riscv64; pub use self::riscv64::*; } else if #[cfg(any(target_arch = "loongarch64"))] { mod loongarch64; pub use self::loongarch64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/musl/b64/s390x.rs0000644000175000017500000006307114661133735022344 0ustar jamespagejamespagepub type blksize_t = i64; pub type c_char = u8; pub type nlink_t = u64; pub type wchar_t = i32; pub type greg_t = u64; pub type __u64 = u64; pub type __s64 = i64; s! { pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __pad1: ::c_long, __pad2: ::c_long, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, __unused: [::c_long; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, __unused: [::c_long; 3], } pub struct statfs { pub f_type: ::c_uint, pub f_bsize: ::c_uint, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_uint, pub f_frsize: ::c_uint, pub f_flags: ::c_uint, pub f_spare: [::c_uint; 4], } pub struct statfs64 { pub f_type: ::c_uint, pub f_bsize: ::c_uint, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_uint, pub f_frsize: ::c_uint, pub f_flags: ::c_uint, pub f_spare: [::c_uint; 4], } } s_no_extra_traits! { // FIXME: This is actually a union. pub struct fpreg_t { pub d: ::c_double, // f: ::c_float, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpreg_t { fn eq(&self, other: &fpreg_t) -> bool { self.d == other.d } } impl Eq for fpreg_t {} impl ::fmt::Debug for fpreg_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpreg_t") .field("d", &self.d) .finish() } } impl ::hash::Hash for fpreg_t { fn hash(&self, state: &mut H) { let d: u64 = unsafe { ::mem::transmute(self.d) }; d.hash(state); } } } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ECONNABORTED: ::c_int = 103; pub const ECONNREFUSED: ::c_int = 111; pub const ECONNRESET: ::c_int = 104; pub const EDEADLK: ::c_int = 35; pub const ENOSYS: ::c_int = 38; pub const ENOTCONN: ::c_int = 107; pub const ETIMEDOUT: ::c_int = 110; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_LARGEFILE: ::c_int = 0x8000; pub const O_NONBLOCK: ::c_int = 2048; pub const SA_NOCLDWAIT: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 4; pub const SIGBUS: ::c_int = 7; pub const SIGSTKSZ: ::size_t = 0x2000; pub const MINSIGSTKSZ: ::size_t = 2048; pub const SIG_SETMASK: ::c_int = 2; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const O_NOCTTY: ::c_int = 256; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const PTRACE_SYSEMU: ::c_int = 31; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_int = 32; pub const EDEADLOCK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const O_ASYNC: ::c_int = 0x2000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const VTIME: usize = 5; pub const VSWTC: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const OLCUC: ::tcflag_t = 0o000002; pub const ONLCR: ::tcflag_t = 0o000004; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const TABDLY: ::tcflag_t = 0o014000; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const BSDLY: ::tcflag_t = 0o020000; pub const BS1: ::tcflag_t = 0x00002000; pub const FFDLY: ::tcflag_t = 0o100000; pub const FF1: ::tcflag_t = 0x00008000; pub const VTDLY: ::tcflag_t = 0o040000; pub const VT1: ::tcflag_t = 0x00004000; pub const XTABS: ::tcflag_t = 0o014000; pub const CBAUD: ::speed_t = 0o010017; pub const CSIZE: ::tcflag_t = 0o000060; pub const CS6: ::tcflag_t = 0o000020; pub const CS7: ::tcflag_t = 0o000040; pub const CS8: ::tcflag_t = 0o000060; pub const CSTOPB: ::tcflag_t = 0o000100; pub const CREAD: ::tcflag_t = 0o000200; pub const PARENB: ::tcflag_t = 0o000400; pub const PARODD: ::tcflag_t = 0o001000; pub const HUPCL: ::tcflag_t = 0o002000; pub const CLOCAL: ::tcflag_t = 0o004000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const ISIG: ::tcflag_t = 0o000001; pub const ICANON: ::tcflag_t = 0o000002; pub const XCASE: ::tcflag_t = 0o000004; pub const ECHOE: ::tcflag_t = 0o000020; pub const ECHOK: ::tcflag_t = 0o000040; pub const ECHONL: ::tcflag_t = 0o000100; pub const NOFLSH: ::tcflag_t = 0o000200; pub const ECHOCTL: ::tcflag_t = 0o001000; pub const ECHOPRT: ::tcflag_t = 0o002000; pub const ECHOKE: ::tcflag_t = 0o004000; pub const PENDIN: ::tcflag_t = 0o040000; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const IXON: ::tcflag_t = 0o002000; pub const IXOFF: ::tcflag_t = 0o010000; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_restart_syscall: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_brk: ::c_long = 45; pub const SYS_signal: ::c_long = 48; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_setpgid: ::c_long = 57; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_symlink: ::c_long = 83; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_lookup_dcookie: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; /* Syscall for Andrew File System */ pub const SYS_getdents: ::c_long = 141; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_query_module: ::c_long = 167; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_getpmsg: ::c_long = 188; pub const SYS_putpmsg: ::c_long = 189; pub const SYS_vfork: ::c_long = 190; pub const SYS_pivot_root: ::c_long = 217; pub const SYS_mincore: ::c_long = 218; pub const SYS_madvise: ::c_long = 219; pub const SYS_getdents64: ::c_long = 220; pub const SYS_readahead: ::c_long = 222; pub const SYS_setxattr: ::c_long = 224; pub const SYS_lsetxattr: ::c_long = 225; pub const SYS_fsetxattr: ::c_long = 226; pub const SYS_getxattr: ::c_long = 227; pub const SYS_lgetxattr: ::c_long = 228; pub const SYS_fgetxattr: ::c_long = 229; pub const SYS_listxattr: ::c_long = 230; pub const SYS_llistxattr: ::c_long = 231; pub const SYS_flistxattr: ::c_long = 232; pub const SYS_removexattr: ::c_long = 233; pub const SYS_lremovexattr: ::c_long = 234; pub const SYS_fremovexattr: ::c_long = 235; pub const SYS_gettid: ::c_long = 236; pub const SYS_tkill: ::c_long = 237; pub const SYS_futex: ::c_long = 238; pub const SYS_sched_setaffinity: ::c_long = 239; pub const SYS_sched_getaffinity: ::c_long = 240; pub const SYS_tgkill: ::c_long = 241; pub const SYS_io_setup: ::c_long = 243; pub const SYS_io_destroy: ::c_long = 244; pub const SYS_io_getevents: ::c_long = 245; pub const SYS_io_submit: ::c_long = 246; pub const SYS_io_cancel: ::c_long = 247; pub const SYS_exit_group: ::c_long = 248; pub const SYS_epoll_create: ::c_long = 249; pub const SYS_epoll_ctl: ::c_long = 250; pub const SYS_epoll_wait: ::c_long = 251; pub const SYS_set_tid_address: ::c_long = 252; pub const SYS_fadvise64: ::c_long = 253; pub const SYS_timer_create: ::c_long = 254; pub const SYS_timer_settime: ::c_long = 255; pub const SYS_timer_gettime: ::c_long = 256; pub const SYS_timer_getoverrun: ::c_long = 257; pub const SYS_timer_delete: ::c_long = 258; pub const SYS_clock_settime: ::c_long = 259; pub const SYS_clock_gettime: ::c_long = 260; pub const SYS_clock_getres: ::c_long = 261; pub const SYS_clock_nanosleep: ::c_long = 262; pub const SYS_statfs64: ::c_long = 265; pub const SYS_fstatfs64: ::c_long = 266; pub const SYS_remap_file_pages: ::c_long = 267; pub const SYS_mbind: ::c_long = 268; pub const SYS_get_mempolicy: ::c_long = 269; pub const SYS_set_mempolicy: ::c_long = 270; pub const SYS_mq_open: ::c_long = 271; pub const SYS_mq_unlink: ::c_long = 272; pub const SYS_mq_timedsend: ::c_long = 273; pub const SYS_mq_timedreceive: ::c_long = 274; pub const SYS_mq_notify: ::c_long = 275; pub const SYS_mq_getsetattr: ::c_long = 276; pub const SYS_kexec_load: ::c_long = 277; pub const SYS_add_key: ::c_long = 278; pub const SYS_request_key: ::c_long = 279; pub const SYS_keyctl: ::c_long = 280; pub const SYS_waitid: ::c_long = 281; pub const SYS_ioprio_set: ::c_long = 282; pub const SYS_ioprio_get: ::c_long = 283; pub const SYS_inotify_init: ::c_long = 284; pub const SYS_inotify_add_watch: ::c_long = 285; pub const SYS_inotify_rm_watch: ::c_long = 286; pub const SYS_migrate_pages: ::c_long = 287; pub const SYS_openat: ::c_long = 288; pub const SYS_mkdirat: ::c_long = 289; pub const SYS_mknodat: ::c_long = 290; pub const SYS_fchownat: ::c_long = 291; pub const SYS_futimesat: ::c_long = 292; pub const SYS_unlinkat: ::c_long = 294; pub const SYS_renameat: ::c_long = 295; pub const SYS_linkat: ::c_long = 296; pub const SYS_symlinkat: ::c_long = 297; pub const SYS_readlinkat: ::c_long = 298; pub const SYS_fchmodat: ::c_long = 299; pub const SYS_faccessat: ::c_long = 300; pub const SYS_pselect6: ::c_long = 301; pub const SYS_ppoll: ::c_long = 302; pub const SYS_unshare: ::c_long = 303; pub const SYS_set_robust_list: ::c_long = 304; pub const SYS_get_robust_list: ::c_long = 305; pub const SYS_splice: ::c_long = 306; pub const SYS_sync_file_range: ::c_long = 307; pub const SYS_tee: ::c_long = 308; pub const SYS_vmsplice: ::c_long = 309; pub const SYS_move_pages: ::c_long = 310; pub const SYS_getcpu: ::c_long = 311; pub const SYS_epoll_pwait: ::c_long = 312; pub const SYS_utimes: ::c_long = 313; pub const SYS_fallocate: ::c_long = 314; pub const SYS_utimensat: ::c_long = 315; pub const SYS_signalfd: ::c_long = 316; pub const SYS_timerfd: ::c_long = 317; pub const SYS_eventfd: ::c_long = 318; pub const SYS_timerfd_create: ::c_long = 319; pub const SYS_timerfd_settime: ::c_long = 320; pub const SYS_timerfd_gettime: ::c_long = 321; pub const SYS_signalfd4: ::c_long = 322; pub const SYS_eventfd2: ::c_long = 323; pub const SYS_inotify_init1: ::c_long = 324; pub const SYS_pipe2: ::c_long = 325; pub const SYS_dup3: ::c_long = 326; pub const SYS_epoll_create1: ::c_long = 327; pub const SYS_preadv: ::c_long = 328; pub const SYS_pwritev: ::c_long = 329; pub const SYS_rt_tgsigqueueinfo: ::c_long = 330; pub const SYS_perf_event_open: ::c_long = 331; pub const SYS_fanotify_init: ::c_long = 332; pub const SYS_fanotify_mark: ::c_long = 333; pub const SYS_prlimit64: ::c_long = 334; pub const SYS_name_to_handle_at: ::c_long = 335; pub const SYS_open_by_handle_at: ::c_long = 336; pub const SYS_clock_adjtime: ::c_long = 337; pub const SYS_syncfs: ::c_long = 338; pub const SYS_setns: ::c_long = 339; pub const SYS_process_vm_readv: ::c_long = 340; pub const SYS_process_vm_writev: ::c_long = 341; pub const SYS_s390_runtime_instr: ::c_long = 342; pub const SYS_kcmp: ::c_long = 343; pub const SYS_finit_module: ::c_long = 344; pub const SYS_sched_setattr: ::c_long = 345; pub const SYS_sched_getattr: ::c_long = 346; pub const SYS_renameat2: ::c_long = 347; pub const SYS_seccomp: ::c_long = 348; pub const SYS_getrandom: ::c_long = 349; pub const SYS_memfd_create: ::c_long = 350; pub const SYS_bpf: ::c_long = 351; pub const SYS_s390_pci_mmio_write: ::c_long = 352; pub const SYS_s390_pci_mmio_read: ::c_long = 353; pub const SYS_execveat: ::c_long = 354; pub const SYS_userfaultfd: ::c_long = 355; pub const SYS_membarrier: ::c_long = 356; pub const SYS_recvmmsg: ::c_long = 357; pub const SYS_sendmmsg: ::c_long = 358; pub const SYS_socket: ::c_long = 359; pub const SYS_socketpair: ::c_long = 360; pub const SYS_bind: ::c_long = 361; pub const SYS_connect: ::c_long = 362; pub const SYS_listen: ::c_long = 363; pub const SYS_accept4: ::c_long = 364; pub const SYS_getsockopt: ::c_long = 365; pub const SYS_setsockopt: ::c_long = 366; pub const SYS_getsockname: ::c_long = 367; pub const SYS_getpeername: ::c_long = 368; pub const SYS_sendto: ::c_long = 369; pub const SYS_sendmsg: ::c_long = 370; pub const SYS_recvfrom: ::c_long = 371; pub const SYS_recvmsg: ::c_long = 372; pub const SYS_shutdown: ::c_long = 373; pub const SYS_mlock2: ::c_long = 374; pub const SYS_copy_file_range: ::c_long = 375; pub const SYS_preadv2: ::c_long = 376; pub const SYS_pwritev2: ::c_long = 377; pub const SYS_lchown: ::c_long = 198; pub const SYS_setuid: ::c_long = 213; pub const SYS_getuid: ::c_long = 199; pub const SYS_setgid: ::c_long = 214; pub const SYS_getgid: ::c_long = 200; pub const SYS_geteuid: ::c_long = 201; pub const SYS_setreuid: ::c_long = 203; pub const SYS_setregid: ::c_long = 204; pub const SYS_getrlimit: ::c_long = 191; pub const SYS_getgroups: ::c_long = 205; pub const SYS_fchown: ::c_long = 207; pub const SYS_setresuid: ::c_long = 208; pub const SYS_setresgid: ::c_long = 210; pub const SYS_getresgid: ::c_long = 211; pub const SYS_select: ::c_long = 142; pub const SYS_getegid: ::c_long = 202; pub const SYS_setgroups: ::c_long = 206; pub const SYS_getresuid: ::c_long = 209; pub const SYS_chown: ::c_long = 212; pub const SYS_setfsuid: ::c_long = 215; pub const SYS_setfsgid: ::c_long = 216; pub const SYS_newfstatat: ::c_long = 293; pub const SYS_statx: ::c_long = 379; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs0000644000175000017500000006253014661133735023306 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = i32; pub type __u64 = ::c_ulong; pub type __s64 = ::c_long; pub type nlink_t = u64; pub type blksize_t = ::c_long; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __reserved: [::c_long; 3], } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __unused1: ::c_long, __unused2: ::c_long } } pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_32BIT: ::c_int = 0x0040; pub const O_APPEND: ::c_int = 1024; pub const O_DIRECT: ::c_int = 0x20000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_LARGEFILE: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_ASYNC: ::c_int = 0x2000; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const PTRACE_SYSEMU: ::c_int = 0x1d; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_int = 0x1e; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const SIGSTKSZ: ::size_t = 10240; pub const MINSIGSTKSZ: ::size_t = 4096; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_break: ::c_long = 17; pub const SYS_oldstat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_stime: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_oldfstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_stty: ::c_long = 31; pub const SYS_gtty: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_ftime: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_prof: ::c_long = 44; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_lock: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_mpx: ::c_long = 56; pub const SYS_setpgid: ::c_long = 57; pub const SYS_ulimit: ::c_long = 58; pub const SYS_oldolduname: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_oldlstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_profil: ::c_long = 98; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_ioperm: ::c_long = 101; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_olduname: ::c_long = 109; pub const SYS_iopl: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_vm86: ::c_long = 113; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_modify_ldt: ::c_long = 123; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; /* Syscall for Andrew File System */ pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_query_module: ::c_long = 166; pub const SYS_poll: ::c_long = 167; pub const SYS_nfsservctl: ::c_long = 168; pub const SYS_setresgid: ::c_long = 169; pub const SYS_getresgid: ::c_long = 170; pub const SYS_prctl: ::c_long = 171; pub const SYS_rt_sigreturn: ::c_long = 172; pub const SYS_rt_sigaction: ::c_long = 173; pub const SYS_rt_sigprocmask: ::c_long = 174; pub const SYS_rt_sigpending: ::c_long = 175; pub const SYS_rt_sigtimedwait: ::c_long = 176; pub const SYS_rt_sigqueueinfo: ::c_long = 177; pub const SYS_rt_sigsuspend: ::c_long = 178; pub const SYS_pread64: ::c_long = 179; pub const SYS_pwrite64: ::c_long = 180; pub const SYS_chown: ::c_long = 181; pub const SYS_getcwd: ::c_long = 182; pub const SYS_capget: ::c_long = 183; pub const SYS_capset: ::c_long = 184; pub const SYS_sigaltstack: ::c_long = 185; pub const SYS_sendfile: ::c_long = 186; pub const SYS_getpmsg: ::c_long = 187; /* some people actually want streams */ pub const SYS_putpmsg: ::c_long = 188; /* some people actually want streams */ pub const SYS_vfork: ::c_long = 189; pub const SYS_ugetrlimit: ::c_long = 190; /* SuS compliant getrlimit */ pub const SYS_readahead: ::c_long = 191; pub const SYS_pciconfig_read: ::c_long = 198; pub const SYS_pciconfig_write: ::c_long = 199; pub const SYS_pciconfig_iobase: ::c_long = 200; pub const SYS_multiplexer: ::c_long = 201; pub const SYS_getdents64: ::c_long = 202; pub const SYS_pivot_root: ::c_long = 203; pub const SYS_madvise: ::c_long = 205; pub const SYS_mincore: ::c_long = 206; pub const SYS_gettid: ::c_long = 207; pub const SYS_tkill: ::c_long = 208; pub const SYS_setxattr: ::c_long = 209; pub const SYS_lsetxattr: ::c_long = 210; pub const SYS_fsetxattr: ::c_long = 211; pub const SYS_getxattr: ::c_long = 212; pub const SYS_lgetxattr: ::c_long = 213; pub const SYS_fgetxattr: ::c_long = 214; pub const SYS_listxattr: ::c_long = 215; pub const SYS_llistxattr: ::c_long = 216; pub const SYS_flistxattr: ::c_long = 217; pub const SYS_removexattr: ::c_long = 218; pub const SYS_lremovexattr: ::c_long = 219; pub const SYS_fremovexattr: ::c_long = 220; pub const SYS_futex: ::c_long = 221; pub const SYS_sched_setaffinity: ::c_long = 222; pub const SYS_sched_getaffinity: ::c_long = 223; pub const SYS_tuxcall: ::c_long = 225; pub const SYS_io_setup: ::c_long = 227; pub const SYS_io_destroy: ::c_long = 228; pub const SYS_io_getevents: ::c_long = 229; pub const SYS_io_submit: ::c_long = 230; pub const SYS_io_cancel: ::c_long = 231; pub const SYS_set_tid_address: ::c_long = 232; pub const SYS_exit_group: ::c_long = 234; pub const SYS_lookup_dcookie: ::c_long = 235; pub const SYS_epoll_create: ::c_long = 236; pub const SYS_epoll_ctl: ::c_long = 237; pub const SYS_epoll_wait: ::c_long = 238; pub const SYS_remap_file_pages: ::c_long = 239; pub const SYS_timer_create: ::c_long = 240; pub const SYS_timer_settime: ::c_long = 241; pub const SYS_timer_gettime: ::c_long = 242; pub const SYS_timer_getoverrun: ::c_long = 243; pub const SYS_timer_delete: ::c_long = 244; pub const SYS_clock_settime: ::c_long = 245; pub const SYS_clock_gettime: ::c_long = 246; pub const SYS_clock_getres: ::c_long = 247; pub const SYS_clock_nanosleep: ::c_long = 248; pub const SYS_swapcontext: ::c_long = 249; pub const SYS_tgkill: ::c_long = 250; pub const SYS_utimes: ::c_long = 251; pub const SYS_statfs64: ::c_long = 252; pub const SYS_fstatfs64: ::c_long = 253; pub const SYS_rtas: ::c_long = 255; pub const SYS_sys_debug_setcontext: ::c_long = 256; pub const SYS_migrate_pages: ::c_long = 258; pub const SYS_mbind: ::c_long = 259; pub const SYS_get_mempolicy: ::c_long = 260; pub const SYS_set_mempolicy: ::c_long = 261; pub const SYS_mq_open: ::c_long = 262; pub const SYS_mq_unlink: ::c_long = 263; pub const SYS_mq_timedsend: ::c_long = 264; pub const SYS_mq_timedreceive: ::c_long = 265; pub const SYS_mq_notify: ::c_long = 266; pub const SYS_mq_getsetattr: ::c_long = 267; pub const SYS_kexec_load: ::c_long = 268; pub const SYS_add_key: ::c_long = 269; pub const SYS_request_key: ::c_long = 270; pub const SYS_keyctl: ::c_long = 271; pub const SYS_waitid: ::c_long = 272; pub const SYS_ioprio_set: ::c_long = 273; pub const SYS_ioprio_get: ::c_long = 274; pub const SYS_inotify_init: ::c_long = 275; pub const SYS_inotify_add_watch: ::c_long = 276; pub const SYS_inotify_rm_watch: ::c_long = 277; pub const SYS_spu_run: ::c_long = 278; pub const SYS_spu_create: ::c_long = 279; pub const SYS_pselect6: ::c_long = 280; pub const SYS_ppoll: ::c_long = 281; pub const SYS_unshare: ::c_long = 282; pub const SYS_splice: ::c_long = 283; pub const SYS_tee: ::c_long = 284; pub const SYS_vmsplice: ::c_long = 285; pub const SYS_openat: ::c_long = 286; pub const SYS_mkdirat: ::c_long = 287; pub const SYS_mknodat: ::c_long = 288; pub const SYS_fchownat: ::c_long = 289; pub const SYS_futimesat: ::c_long = 290; pub const SYS_newfstatat: ::c_long = 291; pub const SYS_unlinkat: ::c_long = 292; pub const SYS_renameat: ::c_long = 293; pub const SYS_linkat: ::c_long = 294; pub const SYS_symlinkat: ::c_long = 295; pub const SYS_readlinkat: ::c_long = 296; pub const SYS_fchmodat: ::c_long = 297; pub const SYS_faccessat: ::c_long = 298; pub const SYS_get_robust_list: ::c_long = 299; pub const SYS_set_robust_list: ::c_long = 300; pub const SYS_move_pages: ::c_long = 301; pub const SYS_getcpu: ::c_long = 302; pub const SYS_epoll_pwait: ::c_long = 303; pub const SYS_utimensat: ::c_long = 304; pub const SYS_signalfd: ::c_long = 305; pub const SYS_timerfd_create: ::c_long = 306; pub const SYS_eventfd: ::c_long = 307; pub const SYS_sync_file_range2: ::c_long = 308; pub const SYS_fallocate: ::c_long = 309; pub const SYS_subpage_prot: ::c_long = 310; pub const SYS_timerfd_settime: ::c_long = 311; pub const SYS_timerfd_gettime: ::c_long = 312; pub const SYS_signalfd4: ::c_long = 313; pub const SYS_eventfd2: ::c_long = 314; pub const SYS_epoll_create1: ::c_long = 315; pub const SYS_dup3: ::c_long = 316; pub const SYS_pipe2: ::c_long = 317; pub const SYS_inotify_init1: ::c_long = 318; pub const SYS_perf_event_open: ::c_long = 319; pub const SYS_preadv: ::c_long = 320; pub const SYS_pwritev: ::c_long = 321; pub const SYS_rt_tgsigqueueinfo: ::c_long = 322; pub const SYS_fanotify_init: ::c_long = 323; pub const SYS_fanotify_mark: ::c_long = 324; pub const SYS_prlimit64: ::c_long = 325; pub const SYS_socket: ::c_long = 326; pub const SYS_bind: ::c_long = 327; pub const SYS_connect: ::c_long = 328; pub const SYS_listen: ::c_long = 329; pub const SYS_accept: ::c_long = 330; pub const SYS_getsockname: ::c_long = 331; pub const SYS_getpeername: ::c_long = 332; pub const SYS_socketpair: ::c_long = 333; pub const SYS_send: ::c_long = 334; pub const SYS_sendto: ::c_long = 335; pub const SYS_recv: ::c_long = 336; pub const SYS_recvfrom: ::c_long = 337; pub const SYS_shutdown: ::c_long = 338; pub const SYS_setsockopt: ::c_long = 339; pub const SYS_getsockopt: ::c_long = 340; pub const SYS_sendmsg: ::c_long = 341; pub const SYS_recvmsg: ::c_long = 342; pub const SYS_recvmmsg: ::c_long = 343; pub const SYS_accept4: ::c_long = 344; pub const SYS_name_to_handle_at: ::c_long = 345; pub const SYS_open_by_handle_at: ::c_long = 346; pub const SYS_clock_adjtime: ::c_long = 347; pub const SYS_syncfs: ::c_long = 348; pub const SYS_sendmmsg: ::c_long = 349; pub const SYS_setns: ::c_long = 350; pub const SYS_process_vm_readv: ::c_long = 351; pub const SYS_process_vm_writev: ::c_long = 352; pub const SYS_finit_module: ::c_long = 353; pub const SYS_kcmp: ::c_long = 354; pub const SYS_sched_setattr: ::c_long = 355; pub const SYS_sched_getattr: ::c_long = 356; pub const SYS_renameat2: ::c_long = 357; pub const SYS_seccomp: ::c_long = 358; pub const SYS_getrandom: ::c_long = 359; pub const SYS_memfd_create: ::c_long = 360; pub const SYS_bpf: ::c_long = 361; pub const SYS_execveat: ::c_long = 362; pub const SYS_switch_endian: ::c_long = 363; pub const SYS_userfaultfd: ::c_long = 364; pub const SYS_membarrier: ::c_long = 365; pub const SYS_mlock2: ::c_long = 378; pub const SYS_copy_file_range: ::c_long = 379; pub const SYS_preadv2: ::c_long = 380; pub const SYS_pwritev2: ::c_long = 381; pub const SYS_kexec_file_load: ::c_long = 382; pub const SYS_statx: ::c_long = 383; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; pub const EDEADLK: ::c_int = 58; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EXTPROC: ::tcflag_t = 0x10000000; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: ::tcflag_t = 0x00000400; pub const TOSTOP: ::tcflag_t = 0x00400000; pub const FLUSHO: ::tcflag_t = 0x00800000; pub const MCL_CURRENT: ::c_int = 0x2000; pub const MCL_FUTURE: ::c_int = 0x4000; pub const MCL_ONFAULT: ::c_int = 0x8000; pub const CBAUD: ::tcflag_t = 0xff; pub const TAB1: ::c_int = 0x400; pub const TAB2: ::c_int = 0x800; pub const TAB3: ::c_int = 0xc00; pub const CR1: ::c_int = 0x1000; pub const CR2: ::c_int = 0x2000; pub const CR3: ::c_int = 0x3000; pub const FF1: ::c_int = 0x4000; pub const BS1: ::c_int = 0x8000; pub const VT1: ::c_int = 0x10000; pub const VWERASE: usize = 10; pub const VREPRINT: usize = 11; pub const VSUSP: usize = 12; pub const VSTART: usize = 13; pub const VSTOP: usize = 14; pub const VDISCARD: usize = 16; pub const VTIME: usize = 7; pub const IXON: ::tcflag_t = 0x00000200; pub const IXOFF: ::tcflag_t = 0x00000400; pub const ONLCR: ::tcflag_t = 0x2; pub const CSIZE: ::tcflag_t = 0x00000300; pub const CS6: ::tcflag_t = 0x00000100; pub const CS7: ::tcflag_t = 0x00000200; pub const CS8: ::tcflag_t = 0x00000300; pub const CSTOPB: ::tcflag_t = 0x00000400; pub const CREAD: ::tcflag_t = 0x00000800; pub const PARENB: ::tcflag_t = 0x00001000; pub const PARODD: ::tcflag_t = 0x00002000; pub const HUPCL: ::tcflag_t = 0x00004000; pub const CLOCAL: ::tcflag_t = 0x00008000; pub const ECHOKE: ::tcflag_t = 0x00000001; pub const ECHOE: ::tcflag_t = 0x00000002; pub const ECHOK: ::tcflag_t = 0x00000004; pub const ECHONL: ::tcflag_t = 0x00000010; pub const ECHOPRT: ::tcflag_t = 0x00000020; pub const ECHOCTL: ::tcflag_t = 0x00000040; pub const ISIG: ::tcflag_t = 0x00000080; pub const ICANON: ::tcflag_t = 0x00000100; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; pub const CIBAUD: ::tcflag_t = 0o77600000; pub const CBAUDEX: ::tcflag_t = 0o0000020; pub const VSWTC: usize = 9; pub const OLCUC: ::tcflag_t = 0o000004; pub const NLDLY: ::tcflag_t = 0o0001400; pub const CRDLY: ::tcflag_t = 0o0030000; pub const TABDLY: ::tcflag_t = 0o0006000; pub const BSDLY: ::tcflag_t = 0o0100000; pub const FFDLY: ::tcflag_t = 0o0040000; pub const VTDLY: ::tcflag_t = 0o0200000; pub const XTABS: ::tcflag_t = 0o00006000; pub const B57600: ::speed_t = 0o00020; pub const B115200: ::speed_t = 0o00021; pub const B230400: ::speed_t = 0o00022; pub const B460800: ::speed_t = 0o00023; pub const B500000: ::speed_t = 0o00024; pub const B576000: ::speed_t = 0o00025; pub const B921600: ::speed_t = 0o00026; pub const B1000000: ::speed_t = 0o00027; pub const B1152000: ::speed_t = 0o00030; pub const B1500000: ::speed_t = 0o00031; pub const B2000000: ::speed_t = 0o00032; pub const B2500000: ::speed_t = 0o00033; pub const B3000000: ::speed_t = 0o00034; pub const B3500000: ::speed_t = 0o00035; pub const B4000000: ::speed_t = 0o00036; libc/src/unix/linux_like/linux/musl/b64/loongarch64/0000775000175000017500000000000014661133735023231 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs0000644000175000017500000005703614661133735024367 0ustar jamespagejamespage//! LoongArch-specific definitions for 64-bit linux-like values pub type c_char = i8; pub type wchar_t = ::c_int; pub type nlink_t = ::c_uint; pub type blksize_t = ::c_int; pub type fsblkcnt64_t = ::c_ulong; pub type fsfilcnt64_t = ::c_ulong; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct pthread_attr_t { __size: [::c_ulong; 7], } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2usize], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statfs64 { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_uint, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } pub struct user_regs_struct { pub regs: [u64; 32], pub orig_a0: u64, pub csr_era: u64, pub csr_badv: u64, pub reserved: [u64; 10], } pub struct user_fp_struct { pub fpr: [u64; 32], pub fcc: u64, pub fcsr: u32, } } pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_getcwd: ::c_long = 17; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_dup: ::c_long = 23; pub const SYS_dup3: ::c_long = 24; pub const SYS_fcntl: ::c_long = 25; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_ioctl: ::c_long = 29; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_flock: ::c_long = 32; pub const SYS_mknodat: ::c_long = 33; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_linkat: ::c_long = 37; pub const SYS_umount2: ::c_long = 39; pub const SYS_mount: ::c_long = 40; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_fallocate: ::c_long = 47; pub const SYS_faccessat: ::c_long = 48; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_chroot: ::c_long = 51; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_fchownat: ::c_long = 54; pub const SYS_fchown: ::c_long = 55; pub const SYS_openat: ::c_long = 56; pub const SYS_close: ::c_long = 57; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pipe2: ::c_long = 59; pub const SYS_quotactl: ::c_long = 60; pub const SYS_getdents64: ::c_long = 61; pub const SYS_lseek: ::c_long = 62; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_sendfile: ::c_long = 71; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_sync: ::c_long = 81; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_utimensat: ::c_long = 88; pub const SYS_acct: ::c_long = 89; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_personality: ::c_long = 92; pub const SYS_exit: ::c_long = 93; pub const SYS_exit_group: ::c_long = 94; pub const SYS_waitid: ::c_long = 95; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_unshare: ::c_long = 97; pub const SYS_futex: ::c_long = 98; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_syslog: ::c_long = 116; pub const SYS_ptrace: ::c_long = 117; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_kill: ::c_long = 129; pub const SYS_tkill: ::c_long = 130; pub const SYS_tgkill: ::c_long = 131; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_setpriority: ::c_long = 140; pub const SYS_getpriority: ::c_long = 141; pub const SYS_reboot: ::c_long = 142; pub const SYS_setregid: ::c_long = 143; pub const SYS_setgid: ::c_long = 144; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setuid: ::c_long = 146; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_times: ::c_long = 153; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getpgid: ::c_long = 155; pub const SYS_getsid: ::c_long = 156; pub const SYS_setsid: ::c_long = 157; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_uname: ::c_long = 160; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_getrusage: ::c_long = 165; pub const SYS_umask: ::c_long = 166; pub const SYS_prctl: ::c_long = 167; pub const SYS_getcpu: ::c_long = 168; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_getpid: ::c_long = 172; pub const SYS_getppid: ::c_long = 173; pub const SYS_getuid: ::c_long = 174; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getgid: ::c_long = 176; pub const SYS_getegid: ::c_long = 177; pub const SYS_gettid: ::c_long = 178; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgctl: ::c_long = 187; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_semget: ::c_long = 190; pub const SYS_semctl: ::c_long = 191; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_semop: ::c_long = 193; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmctl: ::c_long = 195; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmdt: ::c_long = 197; pub const SYS_socket: ::c_long = 198; pub const SYS_socketpair: ::c_long = 199; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_accept: ::c_long = 202; pub const SYS_connect: ::c_long = 203; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_shutdown: ::c_long = 210; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_readahead: ::c_long = 213; pub const SYS_brk: ::c_long = 214; pub const SYS_munmap: ::c_long = 215; pub const SYS_mremap: ::c_long = 216; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_mmap: ::c_long = 222; pub const SYS_fadvise64: ::c_long = 223; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_mprotect: ::c_long = 226; pub const SYS_msync: ::c_long = 227; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_mbind: ::c_long = 235; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_move_pages: ::c_long = 239; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_accept4: ::c_long = 242; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_arch_specific_syscall: ::c_long = 244; pub const SYS_wait4: ::c_long = 260; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_setns: ::c_long = 268; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_io_pgetevents: ::c_long = 292; pub const SYS_rseq: ::c_long = 293; pub const SYS_kexec_file_load: ::c_long = 294; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; pub const SYS_cachestat: ::c_long = 451; pub const SYS_fchmodat2: ::c_long = 452; pub const SYS_map_shadow_stack: ::c_long = 453; pub const SYS_futex_wake: ::c_long = 454; pub const SYS_futex_wait: ::c_long = 455; pub const SYS_futex_requeue: ::c_long = 456; pub const O_APPEND: ::c_int = 1024; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_LARGEFILE: ::c_int = 0; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_ASYNC: ::c_int = 4096; pub const SIGSTKSZ: ::size_t = 16384; pub const MINSIGSTKSZ: ::size_t = 4096; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/musl/b64/loongarch64/align.rs0000644000175000017500000000201514661133735024665 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } s! { pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub __pc: ::c_ulonglong, pub __gregs: [::c_ulonglong; 32], pub __flags: ::c_uint, pub __extcontext: [::c_ulonglong; 0], } #[repr(align(8))] pub struct clone_args { pub flags: ::c_ulonglong, pub pidfd: ::c_ulonglong, pub child_tid: ::c_ulonglong, pub parent_tid: ::c_ulonglong, pub exit_signal: ::c_ulonglong, pub stack: ::c_ulonglong, pub stack_size: ::c_ulonglong, pub tls: ::c_ulonglong, pub set_tid: ::c_ulonglong, pub set_tid_size: ::c_ulonglong, pub cgroup: ::c_ulonglong, } } libc/src/unix/linux_like/linux/musl/b64/x86_64/0000775000175000017500000000000014661133735022041 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs0000644000175000017500000007772114661133735023202 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = ::c_long; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; pub type greg_t = i64; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __reserved: [::c_long; 3], } pub struct user_regs_struct { pub r15: ::c_ulong, pub r14: ::c_ulong, pub r13: ::c_ulong, pub r12: ::c_ulong, pub rbp: ::c_ulong, pub rbx: ::c_ulong, pub r11: ::c_ulong, pub r10: ::c_ulong, pub r9: ::c_ulong, pub r8: ::c_ulong, pub rax: ::c_ulong, pub rcx: ::c_ulong, pub rdx: ::c_ulong, pub rsi: ::c_ulong, pub rdi: ::c_ulong, pub orig_rax: ::c_ulong, pub rip: ::c_ulong, pub cs: ::c_ulong, pub eflags: ::c_ulong, pub rsp: ::c_ulong, pub ss: ::c_ulong, pub fs_base: ::c_ulong, pub gs_base: ::c_ulong, pub ds: ::c_ulong, pub es: ::c_ulong, pub fs: ::c_ulong, pub gs: ::c_ulong, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: ::c_int, pub i387: user_fpregs_struct, pub u_tsize: ::c_ulong, pub u_dsize: ::c_ulong, pub u_ssize: ::c_ulong, pub start_code: ::c_ulong, pub start_stack: ::c_ulong, pub signal: ::c_long, __reserved: ::c_int, #[cfg(target_pointer_width = "32")] __pad1: u32, pub u_ar0: *mut user_regs_struct, #[cfg(target_pointer_width = "32")] __pad2: u32, pub u_fpstate: *mut user_fpregs_struct, pub magic: ::c_ulong, pub u_comm: [::c_char; 32], pub u_debugreg: [::c_ulong; 8], } // GitHub repo: ifduyue/musl/ // commit: b4b1e10364c8737a632be61582e05a8d3acf5690 // file: arch/x86_64/bits/signal.h#L80-L84 pub struct mcontext_t { pub gregs: [greg_t; 23], __private: [u64; 9], } pub struct ipc_perm { pub __ipc_perm_key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_int, __unused1: ::c_long, __unused2: ::c_long } } s_no_extra_traits! { pub struct user_fpregs_struct { pub cwd: ::c_ushort, pub swd: ::c_ushort, pub ftw: ::c_ushort, pub fop: ::c_ushort, pub rip: ::c_ulong, pub rdp: ::c_ulong, pub mxcsr: ::c_uint, pub mxcr_mask: ::c_uint, pub st_space: [::c_uint; 32], pub xmm_space: [::c_uint; 64], padding: [::c_uint; 24], } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: ::sigset_t, __private: [u8; 512], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpregs_struct { fn eq(&self, other: &user_fpregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self.st_space == other.st_space && self .xmm_space .iter() .zip(other.xmm_space.iter()) .all(|(a,b)| a == b) // Ignore padding field } } impl Eq for user_fpregs_struct {} impl ::fmt::Debug for user_fpregs_struct { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("user_fpregs_struct") .field("cwd", &self.cwd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("st_space", &self.st_space) // FIXME: .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl ::hash::Hash for user_fpregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask && self .__private .iter() .zip(other.__private.iter()) .all(|(a,b)| a == b) } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); self.__private.hash(state); } } } } // Syscall table pub const SYS_read: ::c_long = 0; pub const SYS_write: ::c_long = 1; pub const SYS_open: ::c_long = 2; pub const SYS_close: ::c_long = 3; pub const SYS_stat: ::c_long = 4; pub const SYS_fstat: ::c_long = 5; pub const SYS_lstat: ::c_long = 6; pub const SYS_poll: ::c_long = 7; pub const SYS_lseek: ::c_long = 8; pub const SYS_mmap: ::c_long = 9; pub const SYS_mprotect: ::c_long = 10; pub const SYS_munmap: ::c_long = 11; pub const SYS_brk: ::c_long = 12; pub const SYS_rt_sigaction: ::c_long = 13; pub const SYS_rt_sigprocmask: ::c_long = 14; pub const SYS_rt_sigreturn: ::c_long = 15; pub const SYS_ioctl: ::c_long = 16; pub const SYS_pread64: ::c_long = 17; pub const SYS_pwrite64: ::c_long = 18; pub const SYS_readv: ::c_long = 19; pub const SYS_writev: ::c_long = 20; pub const SYS_access: ::c_long = 21; pub const SYS_pipe: ::c_long = 22; pub const SYS_select: ::c_long = 23; pub const SYS_sched_yield: ::c_long = 24; pub const SYS_mremap: ::c_long = 25; pub const SYS_msync: ::c_long = 26; pub const SYS_mincore: ::c_long = 27; pub const SYS_madvise: ::c_long = 28; pub const SYS_shmget: ::c_long = 29; pub const SYS_shmat: ::c_long = 30; pub const SYS_shmctl: ::c_long = 31; pub const SYS_dup: ::c_long = 32; pub const SYS_dup2: ::c_long = 33; pub const SYS_pause: ::c_long = 34; pub const SYS_nanosleep: ::c_long = 35; pub const SYS_getitimer: ::c_long = 36; pub const SYS_alarm: ::c_long = 37; pub const SYS_setitimer: ::c_long = 38; pub const SYS_getpid: ::c_long = 39; pub const SYS_sendfile: ::c_long = 40; pub const SYS_socket: ::c_long = 41; pub const SYS_connect: ::c_long = 42; pub const SYS_accept: ::c_long = 43; pub const SYS_sendto: ::c_long = 44; pub const SYS_recvfrom: ::c_long = 45; pub const SYS_sendmsg: ::c_long = 46; pub const SYS_recvmsg: ::c_long = 47; pub const SYS_shutdown: ::c_long = 48; pub const SYS_bind: ::c_long = 49; pub const SYS_listen: ::c_long = 50; pub const SYS_getsockname: ::c_long = 51; pub const SYS_getpeername: ::c_long = 52; pub const SYS_socketpair: ::c_long = 53; pub const SYS_setsockopt: ::c_long = 54; pub const SYS_getsockopt: ::c_long = 55; pub const SYS_clone: ::c_long = 56; pub const SYS_fork: ::c_long = 57; pub const SYS_vfork: ::c_long = 58; pub const SYS_execve: ::c_long = 59; pub const SYS_exit: ::c_long = 60; pub const SYS_wait4: ::c_long = 61; pub const SYS_kill: ::c_long = 62; pub const SYS_uname: ::c_long = 63; pub const SYS_semget: ::c_long = 64; pub const SYS_semop: ::c_long = 65; pub const SYS_semctl: ::c_long = 66; pub const SYS_shmdt: ::c_long = 67; pub const SYS_msgget: ::c_long = 68; pub const SYS_msgsnd: ::c_long = 69; pub const SYS_msgrcv: ::c_long = 70; pub const SYS_msgctl: ::c_long = 71; pub const SYS_fcntl: ::c_long = 72; pub const SYS_flock: ::c_long = 73; pub const SYS_fsync: ::c_long = 74; pub const SYS_fdatasync: ::c_long = 75; pub const SYS_truncate: ::c_long = 76; pub const SYS_ftruncate: ::c_long = 77; pub const SYS_getdents: ::c_long = 78; pub const SYS_getcwd: ::c_long = 79; pub const SYS_chdir: ::c_long = 80; pub const SYS_fchdir: ::c_long = 81; pub const SYS_rename: ::c_long = 82; pub const SYS_mkdir: ::c_long = 83; pub const SYS_rmdir: ::c_long = 84; pub const SYS_creat: ::c_long = 85; pub const SYS_link: ::c_long = 86; pub const SYS_unlink: ::c_long = 87; pub const SYS_symlink: ::c_long = 88; pub const SYS_readlink: ::c_long = 89; pub const SYS_chmod: ::c_long = 90; pub const SYS_fchmod: ::c_long = 91; pub const SYS_chown: ::c_long = 92; pub const SYS_fchown: ::c_long = 93; pub const SYS_lchown: ::c_long = 94; pub const SYS_umask: ::c_long = 95; pub const SYS_gettimeofday: ::c_long = 96; pub const SYS_getrlimit: ::c_long = 97; pub const SYS_getrusage: ::c_long = 98; pub const SYS_sysinfo: ::c_long = 99; pub const SYS_times: ::c_long = 100; pub const SYS_ptrace: ::c_long = 101; pub const SYS_getuid: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_getgid: ::c_long = 104; pub const SYS_setuid: ::c_long = 105; pub const SYS_setgid: ::c_long = 106; pub const SYS_geteuid: ::c_long = 107; pub const SYS_getegid: ::c_long = 108; pub const SYS_setpgid: ::c_long = 109; pub const SYS_getppid: ::c_long = 110; pub const SYS_getpgrp: ::c_long = 111; pub const SYS_setsid: ::c_long = 112; pub const SYS_setreuid: ::c_long = 113; pub const SYS_setregid: ::c_long = 114; pub const SYS_getgroups: ::c_long = 115; pub const SYS_setgroups: ::c_long = 116; pub const SYS_setresuid: ::c_long = 117; pub const SYS_getresuid: ::c_long = 118; pub const SYS_setresgid: ::c_long = 119; pub const SYS_getresgid: ::c_long = 120; pub const SYS_getpgid: ::c_long = 121; pub const SYS_setfsuid: ::c_long = 122; pub const SYS_setfsgid: ::c_long = 123; pub const SYS_getsid: ::c_long = 124; pub const SYS_capget: ::c_long = 125; pub const SYS_capset: ::c_long = 126; pub const SYS_rt_sigpending: ::c_long = 127; pub const SYS_rt_sigtimedwait: ::c_long = 128; pub const SYS_rt_sigqueueinfo: ::c_long = 129; pub const SYS_rt_sigsuspend: ::c_long = 130; pub const SYS_sigaltstack: ::c_long = 131; pub const SYS_utime: ::c_long = 132; pub const SYS_mknod: ::c_long = 133; pub const SYS_uselib: ::c_long = 134; pub const SYS_personality: ::c_long = 135; pub const SYS_ustat: ::c_long = 136; pub const SYS_statfs: ::c_long = 137; pub const SYS_fstatfs: ::c_long = 138; pub const SYS_sysfs: ::c_long = 139; pub const SYS_getpriority: ::c_long = 140; pub const SYS_setpriority: ::c_long = 141; pub const SYS_sched_setparam: ::c_long = 142; pub const SYS_sched_getparam: ::c_long = 143; pub const SYS_sched_setscheduler: ::c_long = 144; pub const SYS_sched_getscheduler: ::c_long = 145; pub const SYS_sched_get_priority_max: ::c_long = 146; pub const SYS_sched_get_priority_min: ::c_long = 147; pub const SYS_sched_rr_get_interval: ::c_long = 148; pub const SYS_mlock: ::c_long = 149; pub const SYS_munlock: ::c_long = 150; pub const SYS_mlockall: ::c_long = 151; pub const SYS_munlockall: ::c_long = 152; pub const SYS_vhangup: ::c_long = 153; pub const SYS_modify_ldt: ::c_long = 154; pub const SYS_pivot_root: ::c_long = 155; pub const SYS__sysctl: ::c_long = 156; pub const SYS_prctl: ::c_long = 157; pub const SYS_arch_prctl: ::c_long = 158; pub const SYS_adjtimex: ::c_long = 159; pub const SYS_setrlimit: ::c_long = 160; pub const SYS_chroot: ::c_long = 161; pub const SYS_sync: ::c_long = 162; pub const SYS_acct: ::c_long = 163; pub const SYS_settimeofday: ::c_long = 164; pub const SYS_mount: ::c_long = 165; pub const SYS_umount2: ::c_long = 166; pub const SYS_swapon: ::c_long = 167; pub const SYS_swapoff: ::c_long = 168; pub const SYS_reboot: ::c_long = 169; pub const SYS_sethostname: ::c_long = 170; pub const SYS_setdomainname: ::c_long = 171; pub const SYS_iopl: ::c_long = 172; pub const SYS_ioperm: ::c_long = 173; pub const SYS_create_module: ::c_long = 174; pub const SYS_init_module: ::c_long = 175; pub const SYS_delete_module: ::c_long = 176; pub const SYS_get_kernel_syms: ::c_long = 177; pub const SYS_query_module: ::c_long = 178; pub const SYS_quotactl: ::c_long = 179; pub const SYS_nfsservctl: ::c_long = 180; pub const SYS_getpmsg: ::c_long = 181; pub const SYS_putpmsg: ::c_long = 182; pub const SYS_afs_syscall: ::c_long = 183; pub const SYS_tuxcall: ::c_long = 184; pub const SYS_security: ::c_long = 185; pub const SYS_gettid: ::c_long = 186; pub const SYS_readahead: ::c_long = 187; pub const SYS_setxattr: ::c_long = 188; pub const SYS_lsetxattr: ::c_long = 189; pub const SYS_fsetxattr: ::c_long = 190; pub const SYS_getxattr: ::c_long = 191; pub const SYS_lgetxattr: ::c_long = 192; pub const SYS_fgetxattr: ::c_long = 193; pub const SYS_listxattr: ::c_long = 194; pub const SYS_llistxattr: ::c_long = 195; pub const SYS_flistxattr: ::c_long = 196; pub const SYS_removexattr: ::c_long = 197; pub const SYS_lremovexattr: ::c_long = 198; pub const SYS_fremovexattr: ::c_long = 199; pub const SYS_tkill: ::c_long = 200; pub const SYS_time: ::c_long = 201; pub const SYS_futex: ::c_long = 202; pub const SYS_sched_setaffinity: ::c_long = 203; pub const SYS_sched_getaffinity: ::c_long = 204; pub const SYS_set_thread_area: ::c_long = 205; pub const SYS_io_setup: ::c_long = 206; pub const SYS_io_destroy: ::c_long = 207; pub const SYS_io_getevents: ::c_long = 208; pub const SYS_io_submit: ::c_long = 209; pub const SYS_io_cancel: ::c_long = 210; pub const SYS_get_thread_area: ::c_long = 211; pub const SYS_lookup_dcookie: ::c_long = 212; pub const SYS_epoll_create: ::c_long = 213; pub const SYS_epoll_ctl_old: ::c_long = 214; pub const SYS_epoll_wait_old: ::c_long = 215; pub const SYS_remap_file_pages: ::c_long = 216; pub const SYS_getdents64: ::c_long = 217; pub const SYS_set_tid_address: ::c_long = 218; pub const SYS_restart_syscall: ::c_long = 219; pub const SYS_semtimedop: ::c_long = 220; pub const SYS_fadvise64: ::c_long = 221; pub const SYS_timer_create: ::c_long = 222; pub const SYS_timer_settime: ::c_long = 223; pub const SYS_timer_gettime: ::c_long = 224; pub const SYS_timer_getoverrun: ::c_long = 225; pub const SYS_timer_delete: ::c_long = 226; pub const SYS_clock_settime: ::c_long = 227; pub const SYS_clock_gettime: ::c_long = 228; pub const SYS_clock_getres: ::c_long = 229; pub const SYS_clock_nanosleep: ::c_long = 230; pub const SYS_exit_group: ::c_long = 231; pub const SYS_epoll_wait: ::c_long = 232; pub const SYS_epoll_ctl: ::c_long = 233; pub const SYS_tgkill: ::c_long = 234; pub const SYS_utimes: ::c_long = 235; pub const SYS_vserver: ::c_long = 236; pub const SYS_mbind: ::c_long = 237; pub const SYS_set_mempolicy: ::c_long = 238; pub const SYS_get_mempolicy: ::c_long = 239; pub const SYS_mq_open: ::c_long = 240; pub const SYS_mq_unlink: ::c_long = 241; pub const SYS_mq_timedsend: ::c_long = 242; pub const SYS_mq_timedreceive: ::c_long = 243; pub const SYS_mq_notify: ::c_long = 244; pub const SYS_mq_getsetattr: ::c_long = 245; pub const SYS_kexec_load: ::c_long = 246; pub const SYS_waitid: ::c_long = 247; pub const SYS_add_key: ::c_long = 248; pub const SYS_request_key: ::c_long = 249; pub const SYS_keyctl: ::c_long = 250; pub const SYS_ioprio_set: ::c_long = 251; pub const SYS_ioprio_get: ::c_long = 252; pub const SYS_inotify_init: ::c_long = 253; pub const SYS_inotify_add_watch: ::c_long = 254; pub const SYS_inotify_rm_watch: ::c_long = 255; pub const SYS_migrate_pages: ::c_long = 256; pub const SYS_openat: ::c_long = 257; pub const SYS_mkdirat: ::c_long = 258; pub const SYS_mknodat: ::c_long = 259; pub const SYS_fchownat: ::c_long = 260; pub const SYS_futimesat: ::c_long = 261; pub const SYS_newfstatat: ::c_long = 262; pub const SYS_unlinkat: ::c_long = 263; pub const SYS_renameat: ::c_long = 264; pub const SYS_linkat: ::c_long = 265; pub const SYS_symlinkat: ::c_long = 266; pub const SYS_readlinkat: ::c_long = 267; pub const SYS_fchmodat: ::c_long = 268; pub const SYS_faccessat: ::c_long = 269; pub const SYS_pselect6: ::c_long = 270; pub const SYS_ppoll: ::c_long = 271; pub const SYS_unshare: ::c_long = 272; pub const SYS_set_robust_list: ::c_long = 273; pub const SYS_get_robust_list: ::c_long = 274; pub const SYS_splice: ::c_long = 275; pub const SYS_tee: ::c_long = 276; pub const SYS_sync_file_range: ::c_long = 277; pub const SYS_vmsplice: ::c_long = 278; pub const SYS_move_pages: ::c_long = 279; pub const SYS_utimensat: ::c_long = 280; pub const SYS_epoll_pwait: ::c_long = 281; pub const SYS_signalfd: ::c_long = 282; pub const SYS_timerfd_create: ::c_long = 283; pub const SYS_eventfd: ::c_long = 284; pub const SYS_fallocate: ::c_long = 285; pub const SYS_timerfd_settime: ::c_long = 286; pub const SYS_timerfd_gettime: ::c_long = 287; pub const SYS_accept4: ::c_long = 288; pub const SYS_signalfd4: ::c_long = 289; pub const SYS_eventfd2: ::c_long = 290; pub const SYS_epoll_create1: ::c_long = 291; pub const SYS_dup3: ::c_long = 292; pub const SYS_pipe2: ::c_long = 293; pub const SYS_inotify_init1: ::c_long = 294; pub const SYS_preadv: ::c_long = 295; pub const SYS_pwritev: ::c_long = 296; pub const SYS_rt_tgsigqueueinfo: ::c_long = 297; pub const SYS_perf_event_open: ::c_long = 298; pub const SYS_recvmmsg: ::c_long = 299; pub const SYS_fanotify_init: ::c_long = 300; pub const SYS_fanotify_mark: ::c_long = 301; pub const SYS_prlimit64: ::c_long = 302; pub const SYS_name_to_handle_at: ::c_long = 303; pub const SYS_open_by_handle_at: ::c_long = 304; pub const SYS_clock_adjtime: ::c_long = 305; pub const SYS_syncfs: ::c_long = 306; pub const SYS_sendmmsg: ::c_long = 307; pub const SYS_setns: ::c_long = 308; pub const SYS_getcpu: ::c_long = 309; pub const SYS_process_vm_readv: ::c_long = 310; pub const SYS_process_vm_writev: ::c_long = 311; pub const SYS_kcmp: ::c_long = 312; pub const SYS_finit_module: ::c_long = 313; pub const SYS_sched_setattr: ::c_long = 314; pub const SYS_sched_getattr: ::c_long = 315; pub const SYS_renameat2: ::c_long = 316; pub const SYS_seccomp: ::c_long = 317; pub const SYS_getrandom: ::c_long = 318; pub const SYS_memfd_create: ::c_long = 319; pub const SYS_kexec_file_load: ::c_long = 320; pub const SYS_bpf: ::c_long = 321; pub const SYS_execveat: ::c_long = 322; pub const SYS_userfaultfd: ::c_long = 323; pub const SYS_membarrier: ::c_long = 324; pub const SYS_mlock2: ::c_long = 325; pub const SYS_copy_file_range: ::c_long = 326; pub const SYS_preadv2: ::c_long = 327; pub const SYS_pwritev2: ::c_long = 328; pub const SYS_pkey_mprotect: ::c_long = 329; pub const SYS_pkey_alloc: ::c_long = 330; pub const SYS_pkey_free: ::c_long = 331; pub const SYS_statx: ::c_long = 332; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; // offsets in user_regs_structs, from sys/reg.h pub const R15: ::c_int = 0; pub const R14: ::c_int = 1; pub const R13: ::c_int = 2; pub const R12: ::c_int = 3; pub const RBP: ::c_int = 4; pub const RBX: ::c_int = 5; pub const R11: ::c_int = 6; pub const R10: ::c_int = 7; pub const R9: ::c_int = 8; pub const R8: ::c_int = 9; pub const RAX: ::c_int = 10; pub const RCX: ::c_int = 11; pub const RDX: ::c_int = 12; pub const RSI: ::c_int = 13; pub const RDI: ::c_int = 14; pub const ORIG_RAX: ::c_int = 15; pub const RIP: ::c_int = 16; pub const CS: ::c_int = 17; pub const EFLAGS: ::c_int = 18; pub const RSP: ::c_int = 19; pub const SS: ::c_int = 20; pub const FS_BASE: ::c_int = 21; pub const GS_BASE: ::c_int = 22; pub const DS: ::c_int = 23; pub const ES: ::c_int = 24; pub const FS: ::c_int = 25; pub const GS: ::c_int = 26; // offsets in mcontext_t.gregs from bits/signal.h // GitHub repo: ifduyue/musl/ // commit: b4b1e10364c8737a632be61582e05a8d3acf5690 // file: arch/x86_64/bits/signal.h#L9-L56 pub const REG_R8: ::c_int = 0; pub const REG_R9: ::c_int = 1; pub const REG_R10: ::c_int = 2; pub const REG_R11: ::c_int = 3; pub const REG_R12: ::c_int = 4; pub const REG_R13: ::c_int = 5; pub const REG_R14: ::c_int = 6; pub const REG_R15: ::c_int = 7; pub const REG_RDI: ::c_int = 8; pub const REG_RSI: ::c_int = 9; pub const REG_RBP: ::c_int = 10; pub const REG_RBX: ::c_int = 11; pub const REG_RDX: ::c_int = 12; pub const REG_RAX: ::c_int = 13; pub const REG_RCX: ::c_int = 14; pub const REG_RSP: ::c_int = 15; pub const REG_RIP: ::c_int = 16; pub const REG_EFL: ::c_int = 17; pub const REG_CSGSFS: ::c_int = 18; pub const REG_ERR: ::c_int = 19; pub const REG_TRAPNO: ::c_int = 20; pub const REG_OLDMASK: ::c_int = 21; pub const REG_CR2: ::c_int = 22; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_32BIT: ::c_int = 0x0040; pub const O_APPEND: ::c_int = 1024; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_LARGEFILE: ::c_int = 0; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_ASYNC: ::c_int = 0x2000; pub const PTRACE_SYSEMU: ::c_int = 31; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_int = 32; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_SETOWN: ::c_int = 8; pub const VEOF: usize = 4; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::c_int = 0x00000800; pub const TAB2: ::c_int = 0x00001000; pub const TAB3: ::c_int = 0x00001800; pub const CR1: ::c_int = 0x00000200; pub const CR2: ::c_int = 0x00000400; pub const CR3: ::c_int = 0x00000600; pub const FF1: ::c_int = 0x00008000; pub const BS1: ::c_int = 0x00002000; pub const VT1: ::c_int = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/musl/b64/x86_64/align.rs0000644000175000017500000000115014661133735023474 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } s! { #[repr(align(8))] pub struct clone_args { pub flags: ::c_ulonglong, pub pidfd: ::c_ulonglong, pub child_tid: ::c_ulonglong, pub parent_tid: ::c_ulonglong, pub exit_signal: ::c_ulonglong, pub stack: ::c_ulonglong, pub stack_size: ::c_ulonglong, pub tls: ::c_ulonglong, pub set_tid: ::c_ulonglong, pub set_tid_size: ::c_ulonglong, pub cgroup: ::c_ulonglong, } } libc/src/unix/linux_like/linux/uclibc/0000775000175000017500000000000014661133735020771 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/uclibc/arm/0000775000175000017500000000000014661133735021550 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/uclibc/arm/mod.rs0000644000175000017500000007770314661133735022711 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = ::c_uint; pub type c_long = i32; pub type c_ulong = u32; pub type time_t = ::c_long; pub type clock_t = ::c_long; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type ino_t = ::c_ulong; pub type off_t = ::c_long; pub type pthread_t = ::c_ulong; pub type suseconds_t = ::c_long; pub type nlink_t = ::c_uint; pub type blksize_t = ::c_long; pub type blkcnt_t = ::c_long; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct cmsghdr { pub cmsg_len: ::size_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct pthread_attr_t { __size: [::c_long; 9], } pub struct stat { pub st_dev: ::c_ulonglong, __pad1: ::c_ushort, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulonglong, __pad2: ::c_ushort, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused4: ::c_ulong, __unused5: ::c_ulong, } pub struct stat64 { pub st_dev: ::c_ulonglong, pub __pad1: ::c_uint, pub __st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulonglong, pub __pad2: ::c_uint, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino64_t, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub _f: [::c_char; 8], } pub struct statfs { pub f_type: ::c_int, pub f_bsize: ::c_int, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_int, pub f_frsize: ::c_int, pub f_flags: ::c_int, pub f_spare: [::c_int; 4], } pub struct statfs64 { pub f_type: ::c_int, pub f_bsize: ::c_int, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_int, pub f_frsize: ::c_int, pub f_flags: ::c_int, pub f_spare: [::c_int; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct sigset_t { __val: [::c_ulong; 2], } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_flags: ::c_ulong, pub sa_restorer: ::Option, pub sa_mask: sigset_t, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __unused1: ::c_ulong, pub msg_rtime: ::time_t, __unused2: ::c_ulong, pub msg_ctime: ::time_t, __unused3: ::c_ulong, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __unused4: ::c_ulong, __unused5: ::c_ulong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_ulong, pub shm_dtime: ::time_t, __unused2: ::c_ulong, pub shm_ctime: ::time_t, __unused3: ::c_ulong, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong, } } pub const O_CLOEXEC: ::c_int = 0o2000000; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 36; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_COND_COMPAT_T: usize = 12; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const NCCS: usize = 32; // I wasn't able to find those constants // in uclibc build environment for armv7 pub const MAP_HUGETLB: ::c_int = 0x040000; // from linux/other/mod.rs // autogenerated constants with hand tuned types pub const B0: ::speed_t = 0; pub const B1000000: ::speed_t = 0x1008; pub const B110: ::speed_t = 0x3; pub const B115200: ::speed_t = 0x1002; pub const B1152000: ::speed_t = 0x1009; pub const B1200: ::speed_t = 0x9; pub const B134: ::speed_t = 0x4; pub const B150: ::speed_t = 0x5; pub const B1500000: ::speed_t = 0x100a; pub const B1800: ::speed_t = 0xa; pub const B19200: ::speed_t = 0xe; pub const B200: ::speed_t = 0x6; pub const B2000000: ::speed_t = 0x100b; pub const B230400: ::speed_t = 0x1003; pub const B2400: ::speed_t = 0xb; pub const B2500000: ::speed_t = 0x100c; pub const B300: ::speed_t = 0x7; pub const B3000000: ::speed_t = 0x100d; pub const B3500000: ::speed_t = 0x100e; pub const B38400: ::speed_t = 0xf; pub const B4000000: ::speed_t = 0x100f; pub const B460800: ::speed_t = 0x1004; pub const B4800: ::speed_t = 0xc; pub const B50: ::speed_t = 0x1; pub const B500000: ::speed_t = 0x1005; pub const B57600: ::speed_t = 0x1001; pub const B576000: ::speed_t = 0x1006; pub const B600: ::speed_t = 0x8; pub const B75: ::speed_t = 0x2; pub const B921600: ::speed_t = 0x1007; pub const B9600: ::speed_t = 0xd; pub const BS1: ::c_int = 0x2000; pub const BSDLY: ::c_int = 0x2000; pub const CBAUD: ::tcflag_t = 0x100f; pub const CBAUDEX: ::tcflag_t = 0x1000; pub const CIBAUD: ::tcflag_t = 0x100f0000; pub const CLOCAL: ::tcflag_t = 0x800; pub const CPU_SETSIZE: ::c_int = 0x400; pub const CR1: ::c_int = 0x200; pub const CR2: ::c_int = 0x400; pub const CR3: ::c_int = 0x600; pub const CRDLY: ::c_int = 0x600; pub const CREAD: ::tcflag_t = 0x80; pub const CS6: ::tcflag_t = 0x10; pub const CS7: ::tcflag_t = 0x20; pub const CS8: ::tcflag_t = 0x30; pub const CSIZE: ::tcflag_t = 0x30; pub const CSTOPB: ::tcflag_t = 0x40; pub const EADDRINUSE: ::c_int = 0x62; pub const EADDRNOTAVAIL: ::c_int = 0x63; pub const EADV: ::c_int = 0x44; pub const EAFNOSUPPORT: ::c_int = 0x61; pub const EALREADY: ::c_int = 0x72; pub const EBADE: ::c_int = 0x34; pub const EBADFD: ::c_int = 0x4d; pub const EBADMSG: ::c_int = 0x4a; pub const EBADR: ::c_int = 0x35; pub const EBADRQC: ::c_int = 0x38; pub const EBADSLT: ::c_int = 0x39; pub const EBFONT: ::c_int = 0x3b; pub const ECANCELED: ::c_int = 0x7d; pub const ECHOCTL: ::tcflag_t = 0x200; pub const ECHOE: ::tcflag_t = 0x10; pub const ECHOK: ::tcflag_t = 0x20; pub const ECHOKE: ::tcflag_t = 0x800; pub const ECHONL: ::tcflag_t = 0x40; pub const ECHOPRT: ::tcflag_t = 0x400; pub const ECHRNG: ::c_int = 0x2c; pub const ECOMM: ::c_int = 0x46; pub const ECONNABORTED: ::c_int = 0x67; pub const ECONNREFUSED: ::c_int = 0x6f; pub const ECONNRESET: ::c_int = 0x68; pub const EDEADLK: ::c_int = 0x23; pub const EDESTADDRREQ: ::c_int = 0x59; pub const EDOTDOT: ::c_int = 0x49; pub const EDQUOT: ::c_int = 0x7a; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const EHOSTDOWN: ::c_int = 0x70; pub const EHOSTUNREACH: ::c_int = 0x71; pub const EHWPOISON: ::c_int = 0x85; pub const EIDRM: ::c_int = 0x2b; pub const EILSEQ: ::c_int = 0x54; pub const EINPROGRESS: ::c_int = 0x73; pub const EISCONN: ::c_int = 0x6a; pub const EISNAM: ::c_int = 0x78; pub const EKEYEXPIRED: ::c_int = 0x7f; pub const EKEYREJECTED: ::c_int = 0x81; pub const EKEYREVOKED: ::c_int = 0x80; pub const EL2HLT: ::c_int = 0x33; pub const EL2NSYNC: ::c_int = 0x2d; pub const EL3HLT: ::c_int = 0x2e; pub const EL3RST: ::c_int = 0x2f; pub const ELIBACC: ::c_int = 0x4f; pub const ELIBBAD: ::c_int = 0x50; pub const ELIBEXEC: ::c_int = 0x53; pub const ELIBMAX: ::c_int = 0x52; pub const ELIBSCN: ::c_int = 0x51; pub const ELNRNG: ::c_int = 0x30; pub const ELOOP: ::c_int = 0x28; pub const EMEDIUMTYPE: ::c_int = 0x7c; pub const EMSGSIZE: ::c_int = 0x5a; pub const EMULTIHOP: ::c_int = 0x48; pub const ENAMETOOLONG: ::c_int = 0x24; pub const ENAVAIL: ::c_int = 0x77; pub const ENETDOWN: ::c_int = 0x64; pub const ENETRESET: ::c_int = 0x66; pub const ENETUNREACH: ::c_int = 0x65; pub const ENOANO: ::c_int = 0x37; pub const ENOBUFS: ::c_int = 0x69; pub const ENOCSI: ::c_int = 0x32; pub const ENODATA: ::c_int = 0x3d; pub const ENOKEY: ::c_int = 0x7e; pub const ENOLCK: ::c_int = 0x25; pub const ENOLINK: ::c_int = 0x43; pub const ENOMEDIUM: ::c_int = 0x7b; pub const ENOMSG: ::c_int = 0x2a; pub const ENONET: ::c_int = 0x40; pub const ENOPKG: ::c_int = 0x41; pub const ENOPROTOOPT: ::c_int = 0x5c; pub const ENOSR: ::c_int = 0x3f; pub const ENOSTR: ::c_int = 0x3c; pub const ENOSYS: ::c_int = 0x26; pub const ENOTCONN: ::c_int = 0x6b; pub const ENOTEMPTY: ::c_int = 0x27; pub const ENOTNAM: ::c_int = 0x76; pub const ENOTRECOVERABLE: ::c_int = 0x83; pub const ENOTSOCK: ::c_int = 0x58; pub const ENOTUNIQ: ::c_int = 0x4c; pub const EOPNOTSUPP: ::c_int = 0x5f; pub const EOVERFLOW: ::c_int = 0x4b; pub const EOWNERDEAD: ::c_int = 0x82; pub const EPFNOSUPPORT: ::c_int = 0x60; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EPROTO: ::c_int = 0x47; pub const EPROTONOSUPPORT: ::c_int = 0x5d; pub const EPROTOTYPE: ::c_int = 0x5b; pub const EREMCHG: ::c_int = 0x4e; pub const EREMOTE: ::c_int = 0x42; pub const EREMOTEIO: ::c_int = 0x79; pub const ERESTART: ::c_int = 0x55; pub const ERFKILL: ::c_int = 0x84; pub const ESHUTDOWN: ::c_int = 0x6c; pub const ESOCKTNOSUPPORT: ::c_int = 0x5e; pub const ESRMNT: ::c_int = 0x45; pub const ESTALE: ::c_int = 0x74; pub const ESTRPIPE: ::c_int = 0x56; pub const ETIME: ::c_int = 0x3e; pub const ETIMEDOUT: ::c_int = 0x6e; pub const ETOOMANYREFS: ::c_int = 0x6d; pub const EUCLEAN: ::c_int = 0x75; pub const EUNATCH: ::c_int = 0x31; pub const EUSERS: ::c_int = 0x57; pub const EXFULL: ::c_int = 0x36; pub const FF1: ::c_int = 0x8000; pub const FFDLY: ::c_int = 0x8000; pub const FLUSHO: ::tcflag_t = 0x1000; pub const F_GETLK: ::c_int = 0x5; pub const F_SETLK: ::c_int = 0x6; pub const F_SETLKW: ::c_int = 0x7; pub const HUPCL: ::tcflag_t = 0x400; pub const ICANON: ::tcflag_t = 0x2; pub const IEXTEN: ::tcflag_t = 0x8000; pub const ISIG: ::tcflag_t = 0x1; pub const IXOFF: ::tcflag_t = 0x1000; pub const IXON: ::tcflag_t = 0x400; pub const MAP_ANON: ::c_int = 0x20; pub const MAP_ANONYMOUS: ::c_int = 0x20; pub const MAP_DENYWRITE: ::c_int = 0x800; pub const MAP_EXECUTABLE: ::c_int = 0x1000; pub const MAP_GROWSDOWN: ::c_int = 0x100; pub const MAP_LOCKED: ::c_int = 0x2000; pub const MAP_NONBLOCK: ::c_int = 0x10000; pub const MAP_NORESERVE: ::c_int = 0x4000; pub const MAP_POPULATE: ::c_int = 0x8000; pub const MAP_STACK: ::c_int = 0x20000; pub const NLDLY: ::tcflag_t = 0x100; pub const NOFLSH: ::tcflag_t = 0x80; pub const OLCUC: ::tcflag_t = 0x2; pub const ONLCR: ::tcflag_t = 0x4; pub const O_ACCMODE: ::c_int = 0x3; pub const O_APPEND: ::c_int = 0x400; pub const O_ASYNC: ::c_int = 0o20000; pub const O_CREAT: ::c_int = 0x40; pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_DSYNC: ::c_int = O_SYNC; pub const O_EXCL: ::c_int = 0x80; pub const O_FSYNC: ::c_int = O_SYNC; pub const O_LARGEFILE: ::c_int = 0o400000; pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_NOCTTY: ::c_int = 0x100; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_NONBLOCK: ::c_int = 0x800; pub const O_PATH: ::c_int = 0o10000000; pub const O_RSYNC: ::c_int = O_SYNC; pub const O_SYNC: ::c_int = 0o10000; pub const O_TRUNC: ::c_int = 0x200; pub const PARENB: ::tcflag_t = 0x100; pub const PARODD: ::tcflag_t = 0x200; pub const PENDIN: ::tcflag_t = 0x4000; pub const POLLWRBAND: ::c_short = 0x200; pub const POLLWRNORM: ::c_short = 0x100; pub const PTHREAD_STACK_MIN: ::size_t = 16384; pub const RTLD_GLOBAL: ::c_int = 0x00100; pub const PIDFD_NONBLOCK: ::c_int = 0x800; // These are typed unsigned to match sigaction pub const SA_NOCLDSTOP: ::c_ulong = 0x1; pub const SA_NOCLDWAIT: ::c_ulong = 0x2; pub const SA_SIGINFO: ::c_ulong = 0x4; pub const SA_NODEFER: ::c_ulong = 0x40000000; pub const SA_ONSTACK: ::c_ulong = 0x8000000; pub const SA_RESETHAND: ::c_ulong = 0x80000000; pub const SA_RESTART: ::c_ulong = 0x10000000; pub const SFD_CLOEXEC: ::c_int = 0x80000; pub const SFD_NONBLOCK: ::c_int = 0x800; pub const SIGBUS: ::c_int = 0x7; pub const SIGCHLD: ::c_int = 0x11; pub const SIGCONT: ::c_int = 0x12; pub const SIGIO: ::c_int = 0x1d; pub const SIGPROF: ::c_int = 0x1b; pub const SIGPWR: ::c_int = 0x1e; pub const SIGSTKFLT: ::c_int = 0x10; pub const SIGSTKSZ: ::size_t = 8192; pub const SIGSTOP: ::c_int = 0x13; pub const SIGSYS: ::c_int = 0x1f; pub const SIGTSTP: ::c_int = 0x14; pub const SIGTTIN: ::c_int = 0x15; pub const SIGTTOU: ::c_int = 0x16; pub const SIGURG: ::c_int = 0x17; pub const SIGUSR1: ::c_int = 0xa; pub const SIGUSR2: ::c_int = 0xc; pub const SIGVTALRM: ::c_int = 0x1a; pub const SIGWINCH: ::c_int = 0x1c; pub const SIGXCPU: ::c_int = 0x18; pub const SIGXFSZ: ::c_int = 0x19; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_SETMASK: ::c_int = 0x2; pub const SIG_UNBLOCK: ::c_int = 0x1; pub const SOCK_DGRAM: ::c_int = 0x2; pub const SOCK_NONBLOCK: ::c_int = 0o0004000; pub const SOCK_SEQPACKET: ::c_int = 0x5; pub const SOCK_STREAM: ::c_int = 0x1; pub const TAB1: ::c_int = 0x800; pub const TAB2: ::c_int = 0x1000; pub const TAB3: ::c_int = 0x1800; pub const TABDLY: ::c_int = 0x1800; pub const TCSADRAIN: ::c_int = 0x1; pub const TCSAFLUSH: ::c_int = 0x2; pub const TCSANOW: ::c_int = 0; pub const TOSTOP: ::tcflag_t = 0x100; pub const VDISCARD: usize = 0xd; pub const VEOF: usize = 0x4; pub const VEOL: usize = 0xb; pub const VEOL2: usize = 0x10; pub const VMIN: usize = 0x6; pub const VREPRINT: usize = 0xc; pub const VSTART: usize = 0x8; pub const VSTOP: usize = 0x9; pub const VSUSP: usize = 0xa; pub const VSWTC: usize = 0x7; pub const VT1: ::c_int = 0x4000; pub const VTDLY: ::c_int = 0x4000; pub const VTIME: usize = 0x5; pub const VWERASE: usize = 0xe; pub const XTABS: ::tcflag_t = 0x1800; pub const MADV_SOFT_OFFLINE: ::c_int = 101; // Syscall table is copied from src/unix/notbsd/linux/musl/b32/arm.rs pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_ptrace: ::c_long = 26; pub const SYS_pause: ::c_long = 29; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_setpgid: ::c_long = 57; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_symlink: ::c_long = 83; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_vhangup: ::c_long = 111; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid: ::c_long = 170; pub const SYS_getresgid: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_chown: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_vfork: ::c_long = 190; pub const SYS_ugetrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_lchown32: ::c_long = 198; pub const SYS_getuid32: ::c_long = 199; pub const SYS_getgid32: ::c_long = 200; pub const SYS_geteuid32: ::c_long = 201; pub const SYS_getegid32: ::c_long = 202; pub const SYS_setreuid32: ::c_long = 203; pub const SYS_setregid32: ::c_long = 204; pub const SYS_getgroups32: ::c_long = 205; pub const SYS_setgroups32: ::c_long = 206; pub const SYS_fchown32: ::c_long = 207; pub const SYS_setresuid32: ::c_long = 208; pub const SYS_getresuid32: ::c_long = 209; pub const SYS_setresgid32: ::c_long = 210; pub const SYS_getresgid32: ::c_long = 211; pub const SYS_chown32: ::c_long = 212; pub const SYS_setuid32: ::c_long = 213; pub const SYS_setgid32: ::c_long = 214; pub const SYS_setfsuid32: ::c_long = 215; pub const SYS_setfsgid32: ::c_long = 216; pub const SYS_getdents64: ::c_long = 217; pub const SYS_pivot_root: ::c_long = 218; pub const SYS_mincore: ::c_long = 219; pub const SYS_madvise: ::c_long = 220; pub const SYS_fcntl64: ::c_long = 221; pub const SYS_gettid: ::c_long = 224; pub const SYS_readahead: ::c_long = 225; pub const SYS_setxattr: ::c_long = 226; pub const SYS_lsetxattr: ::c_long = 227; pub const SYS_fsetxattr: ::c_long = 228; pub const SYS_getxattr: ::c_long = 229; pub const SYS_lgetxattr: ::c_long = 230; pub const SYS_fgetxattr: ::c_long = 231; pub const SYS_listxattr: ::c_long = 232; pub const SYS_llistxattr: ::c_long = 233; pub const SYS_flistxattr: ::c_long = 234; pub const SYS_removexattr: ::c_long = 235; pub const SYS_lremovexattr: ::c_long = 236; pub const SYS_fremovexattr: ::c_long = 237; pub const SYS_tkill: ::c_long = 238; pub const SYS_sendfile64: ::c_long = 239; pub const SYS_futex: ::c_long = 240; pub const SYS_sched_setaffinity: ::c_long = 241; pub const SYS_sched_getaffinity: ::c_long = 242; pub const SYS_io_setup: ::c_long = 243; pub const SYS_io_destroy: ::c_long = 244; pub const SYS_io_getevents: ::c_long = 245; pub const SYS_io_submit: ::c_long = 246; pub const SYS_io_cancel: ::c_long = 247; pub const SYS_exit_group: ::c_long = 248; pub const SYS_lookup_dcookie: ::c_long = 249; pub const SYS_epoll_create: ::c_long = 250; pub const SYS_epoll_ctl: ::c_long = 251; pub const SYS_epoll_wait: ::c_long = 252; pub const SYS_remap_file_pages: ::c_long = 253; pub const SYS_set_tid_address: ::c_long = 256; pub const SYS_timer_create: ::c_long = 257; pub const SYS_timer_settime: ::c_long = 258; pub const SYS_timer_gettime: ::c_long = 259; pub const SYS_timer_getoverrun: ::c_long = 260; pub const SYS_timer_delete: ::c_long = 261; pub const SYS_clock_settime: ::c_long = 262; pub const SYS_clock_gettime: ::c_long = 263; pub const SYS_clock_getres: ::c_long = 264; pub const SYS_clock_nanosleep: ::c_long = 265; pub const SYS_statfs64: ::c_long = 266; pub const SYS_fstatfs64: ::c_long = 267; pub const SYS_tgkill: ::c_long = 268; pub const SYS_utimes: ::c_long = 269; pub const SYS_pciconfig_iobase: ::c_long = 271; pub const SYS_pciconfig_read: ::c_long = 272; pub const SYS_pciconfig_write: ::c_long = 273; pub const SYS_mq_open: ::c_long = 274; pub const SYS_mq_unlink: ::c_long = 275; pub const SYS_mq_timedsend: ::c_long = 276; pub const SYS_mq_timedreceive: ::c_long = 277; pub const SYS_mq_notify: ::c_long = 278; pub const SYS_mq_getsetattr: ::c_long = 279; pub const SYS_waitid: ::c_long = 280; pub const SYS_socket: ::c_long = 281; pub const SYS_bind: ::c_long = 282; pub const SYS_connect: ::c_long = 283; pub const SYS_listen: ::c_long = 284; pub const SYS_accept: ::c_long = 285; pub const SYS_getsockname: ::c_long = 286; pub const SYS_getpeername: ::c_long = 287; pub const SYS_socketpair: ::c_long = 288; pub const SYS_send: ::c_long = 289; pub const SYS_sendto: ::c_long = 290; pub const SYS_recv: ::c_long = 291; pub const SYS_recvfrom: ::c_long = 292; pub const SYS_shutdown: ::c_long = 293; pub const SYS_setsockopt: ::c_long = 294; pub const SYS_getsockopt: ::c_long = 295; pub const SYS_sendmsg: ::c_long = 296; pub const SYS_recvmsg: ::c_long = 297; pub const SYS_semop: ::c_long = 298; pub const SYS_semget: ::c_long = 299; pub const SYS_semctl: ::c_long = 300; pub const SYS_msgsnd: ::c_long = 301; pub const SYS_msgrcv: ::c_long = 302; pub const SYS_msgget: ::c_long = 303; pub const SYS_msgctl: ::c_long = 304; pub const SYS_shmat: ::c_long = 305; pub const SYS_shmdt: ::c_long = 306; pub const SYS_shmget: ::c_long = 307; pub const SYS_shmctl: ::c_long = 308; pub const SYS_add_key: ::c_long = 309; pub const SYS_request_key: ::c_long = 310; pub const SYS_keyctl: ::c_long = 311; pub const SYS_semtimedop: ::c_long = 312; pub const SYS_vserver: ::c_long = 313; pub const SYS_ioprio_set: ::c_long = 314; pub const SYS_ioprio_get: ::c_long = 315; pub const SYS_inotify_init: ::c_long = 316; pub const SYS_inotify_add_watch: ::c_long = 317; pub const SYS_inotify_rm_watch: ::c_long = 318; pub const SYS_mbind: ::c_long = 319; pub const SYS_get_mempolicy: ::c_long = 320; pub const SYS_set_mempolicy: ::c_long = 321; pub const SYS_openat: ::c_long = 322; pub const SYS_mkdirat: ::c_long = 323; pub const SYS_mknodat: ::c_long = 324; pub const SYS_fchownat: ::c_long = 325; pub const SYS_futimesat: ::c_long = 326; pub const SYS_fstatat64: ::c_long = 327; pub const SYS_unlinkat: ::c_long = 328; pub const SYS_renameat: ::c_long = 329; pub const SYS_linkat: ::c_long = 330; pub const SYS_symlinkat: ::c_long = 331; pub const SYS_readlinkat: ::c_long = 332; pub const SYS_fchmodat: ::c_long = 333; pub const SYS_faccessat: ::c_long = 334; pub const SYS_pselect6: ::c_long = 335; pub const SYS_ppoll: ::c_long = 336; pub const SYS_unshare: ::c_long = 337; pub const SYS_set_robust_list: ::c_long = 338; pub const SYS_get_robust_list: ::c_long = 339; pub const SYS_splice: ::c_long = 340; pub const SYS_tee: ::c_long = 342; pub const SYS_vmsplice: ::c_long = 343; pub const SYS_move_pages: ::c_long = 344; pub const SYS_getcpu: ::c_long = 345; pub const SYS_epoll_pwait: ::c_long = 346; pub const SYS_kexec_load: ::c_long = 347; pub const SYS_utimensat: ::c_long = 348; pub const SYS_signalfd: ::c_long = 349; pub const SYS_timerfd_create: ::c_long = 350; pub const SYS_eventfd: ::c_long = 351; pub const SYS_fallocate: ::c_long = 352; pub const SYS_timerfd_settime: ::c_long = 353; pub const SYS_timerfd_gettime: ::c_long = 354; pub const SYS_signalfd4: ::c_long = 355; pub const SYS_eventfd2: ::c_long = 356; pub const SYS_epoll_create1: ::c_long = 357; pub const SYS_dup3: ::c_long = 358; pub const SYS_pipe2: ::c_long = 359; pub const SYS_inotify_init1: ::c_long = 360; pub const SYS_preadv: ::c_long = 361; pub const SYS_pwritev: ::c_long = 362; pub const SYS_rt_tgsigqueueinfo: ::c_long = 363; pub const SYS_perf_event_open: ::c_long = 364; pub const SYS_recvmmsg: ::c_long = 365; pub const SYS_accept4: ::c_long = 366; pub const SYS_fanotify_init: ::c_long = 367; pub const SYS_fanotify_mark: ::c_long = 368; pub const SYS_prlimit64: ::c_long = 369; pub const SYS_name_to_handle_at: ::c_long = 370; pub const SYS_open_by_handle_at: ::c_long = 371; pub const SYS_clock_adjtime: ::c_long = 372; pub const SYS_syncfs: ::c_long = 373; pub const SYS_sendmmsg: ::c_long = 374; pub const SYS_setns: ::c_long = 375; pub const SYS_process_vm_readv: ::c_long = 376; pub const SYS_process_vm_writev: ::c_long = 377; pub const SYS_kcmp: ::c_long = 378; pub const SYS_finit_module: ::c_long = 379; pub const SYS_sched_setattr: ::c_long = 380; pub const SYS_sched_getattr: ::c_long = 381; pub const SYS_renameat2: ::c_long = 382; pub const SYS_seccomp: ::c_long = 383; pub const SYS_getrandom: ::c_long = 384; pub const SYS_memfd_create: ::c_long = 385; pub const SYS_bpf: ::c_long = 386; pub const SYS_execveat: ::c_long = 387; pub const SYS_userfaultfd: ::c_long = 388; pub const SYS_membarrier: ::c_long = 389; pub const SYS_mlock2: ::c_long = 390; pub const SYS_copy_file_range: ::c_long = 391; pub const SYS_preadv2: ::c_long = 392; pub const SYS_pwritev2: ::c_long = 393; pub const SYS_pkey_mprotect: ::c_long = 394; pub const SYS_pkey_alloc: ::c_long = 395; pub const SYS_pkey_free: ::c_long = 396; // FIXME: should be a `c_long` too, but a bug slipped in. pub const SYS_statx: ::c_int = 397; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } else { mod no_align; pub use self::no_align::*; } } libc/src/unix/linux_like/linux/uclibc/arm/no_align.rs0000644000175000017500000000040214661133735023676 0ustar jamespagejamespages! { // FIXME this is actually a union pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], __align: [::c_long; 0], } } libc/src/unix/linux_like/linux/uclibc/arm/align.rs0000644000175000017500000000057214661133735023212 0ustar jamespagejamespages! { // FIXME this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], } } libc/src/unix/linux_like/linux/uclibc/mod.rs0000644000175000017500000003101614661133735022115 0ustar jamespagejamespagepub type shmatt_t = ::c_ulong; pub type msgqnum_t = ::c_ulong; pub type msglen_t = ::c_ulong; pub type regoff_t = ::c_int; pub type rlim_t = ::c_ulong; pub type __rlimit_resource_t = ::c_ulong; pub type __priority_which_t = ::c_uint; cfg_if! { if #[cfg(doc)] { // Used in `linux::arch` to define ioctl constants. pub(crate) type Ioctl = ::c_ulong; } else { #[doc(hidden)] pub type Ioctl = ::c_ulong; } } s! { pub struct statvfs { // Different than GNU! pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, #[cfg(target_endian = "little")] pub f_fsid: ::c_ulong, #[cfg(target_pointer_width = "32")] __f_unused: ::c_int, #[cfg(target_endian = "big")] pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct regex_t { __buffer: *mut ::c_void, __allocated: ::size_t, __used: ::size_t, __syntax: ::c_ulong, __fastmap: *mut ::c_char, __translate: *mut ::c_char, __re_nsub: ::size_t, __bitfield: u8, } pub struct rtentry { pub rt_pad1: ::c_ulong, pub rt_dst: ::sockaddr, pub rt_gateway: ::sockaddr, pub rt_genmask: ::sockaddr, pub rt_flags: ::c_ushort, pub rt_pad2: ::c_short, pub rt_pad3: ::c_ulong, pub rt_tos: ::c_uchar, pub rt_class: ::c_uchar, #[cfg(target_pointer_width = "64")] pub rt_pad4: [::c_short; 3usize], #[cfg(not(target_pointer_width = "64"))] pub rt_pad4: ::c_short, pub rt_metric: ::c_short, pub rt_dev: *mut ::c_char, pub rt_mtu: ::c_ulong, pub rt_window: ::c_ulong, pub rt_irtt: ::c_ushort, } pub struct __exit_status { pub e_termination: ::c_short, pub e_exit: ::c_short, } pub struct ptrace_peeksiginfo_args { pub off: ::__u64, pub flags: ::__u32, pub nr: ::__s32, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, si_addr: *mut ::c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_si_value { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, _si_timerid: ::c_int, _si_overrun: ::c_int, si_value: ::sigval, } (*(self as *const siginfo_t as *const siginfo_si_value)).si_value } } pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const SIGEV_THREAD_ID: ::c_int = 4; pub const AF_VSOCK: ::c_int = 40; // Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the // following are only available on newer Linux versions than the versions // currently used in CI in some configurations, so we define them here. pub const BINDERFS_SUPER_MAGIC: ::c_long = 0x6c6f6f70; pub const XFS_SUPER_MAGIC: ::c_long = 0x58465342; pub const PTRACE_TRACEME: ::c_int = 0; pub const PTRACE_PEEKTEXT: ::c_int = 1; pub const PTRACE_PEEKDATA: ::c_int = 2; pub const PTRACE_PEEKUSER: ::c_int = 3; pub const PTRACE_POKETEXT: ::c_int = 4; pub const PTRACE_POKEDATA: ::c_int = 5; pub const PTRACE_POKEUSER: ::c_int = 6; pub const PTRACE_CONT: ::c_int = 7; pub const PTRACE_KILL: ::c_int = 8; pub const PTRACE_SINGLESTEP: ::c_int = 9; pub const PTRACE_GETREGS: ::c_int = 12; pub const PTRACE_SETREGS: ::c_int = 13; pub const PTRACE_GETFPREGS: ::c_int = 14; pub const PTRACE_SETFPREGS: ::c_int = 15; pub const PTRACE_ATTACH: ::c_int = 16; pub const PTRACE_DETACH: ::c_int = 17; pub const PTRACE_GETFPXREGS: ::c_int = 18; pub const PTRACE_SETFPXREGS: ::c_int = 19; pub const PTRACE_SYSCALL: ::c_int = 24; pub const PTRACE_SETOPTIONS: ::c_int = 0x4200; pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201; pub const PTRACE_GETSIGINFO: ::c_int = 0x4202; pub const PTRACE_SETSIGINFO: ::c_int = 0x4203; pub const PTRACE_GETREGSET: ::c_int = 0x4204; pub const PTRACE_SETREGSET: ::c_int = 0x4205; pub const PTRACE_SEIZE: ::c_int = 0x4206; pub const PTRACE_INTERRUPT: ::c_int = 0x4207; pub const PTRACE_LISTEN: ::c_int = 0x4208; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; // These are different than GNU! pub const LC_CTYPE: ::c_int = 0; pub const LC_NUMERIC: ::c_int = 1; pub const LC_TIME: ::c_int = 3; pub const LC_COLLATE: ::c_int = 4; pub const LC_MONETARY: ::c_int = 2; pub const LC_MESSAGES: ::c_int = 5; pub const LC_ALL: ::c_int = 6; // end different section // MS_ flags for mount(2) pub const MS_RMT_MASK: ::c_ulong = ::MS_RDONLY | ::MS_SYNCHRONOUS | ::MS_MANDLOCK | ::MS_I_VERSION; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const IPV6_JOIN_GROUP: ::c_int = 20; pub const IPV6_LEAVE_GROUP: ::c_int = 21; // These are different from GNU pub const ABDAY_1: ::nl_item = 0x300; pub const ABDAY_2: ::nl_item = 0x301; pub const ABDAY_3: ::nl_item = 0x302; pub const ABDAY_4: ::nl_item = 0x303; pub const ABDAY_5: ::nl_item = 0x304; pub const ABDAY_6: ::nl_item = 0x305; pub const ABDAY_7: ::nl_item = 0x306; pub const DAY_1: ::nl_item = 0x307; pub const DAY_2: ::nl_item = 0x308; pub const DAY_3: ::nl_item = 0x309; pub const DAY_4: ::nl_item = 0x30A; pub const DAY_5: ::nl_item = 0x30B; pub const DAY_6: ::nl_item = 0x30C; pub const DAY_7: ::nl_item = 0x30D; pub const ABMON_1: ::nl_item = 0x30E; pub const ABMON_2: ::nl_item = 0x30F; pub const ABMON_3: ::nl_item = 0x310; pub const ABMON_4: ::nl_item = 0x311; pub const ABMON_5: ::nl_item = 0x312; pub const ABMON_6: ::nl_item = 0x313; pub const ABMON_7: ::nl_item = 0x314; pub const ABMON_8: ::nl_item = 0x315; pub const ABMON_9: ::nl_item = 0x316; pub const ABMON_10: ::nl_item = 0x317; pub const ABMON_11: ::nl_item = 0x318; pub const ABMON_12: ::nl_item = 0x319; pub const MON_1: ::nl_item = 0x31A; pub const MON_2: ::nl_item = 0x31B; pub const MON_3: ::nl_item = 0x31C; pub const MON_4: ::nl_item = 0x31D; pub const MON_5: ::nl_item = 0x31E; pub const MON_6: ::nl_item = 0x31F; pub const MON_7: ::nl_item = 0x320; pub const MON_8: ::nl_item = 0x321; pub const MON_9: ::nl_item = 0x322; pub const MON_10: ::nl_item = 0x323; pub const MON_11: ::nl_item = 0x324; pub const MON_12: ::nl_item = 0x325; pub const AM_STR: ::nl_item = 0x326; pub const PM_STR: ::nl_item = 0x327; pub const D_T_FMT: ::nl_item = 0x328; pub const D_FMT: ::nl_item = 0x329; pub const T_FMT: ::nl_item = 0x32A; pub const T_FMT_AMPM: ::nl_item = 0x32B; pub const ERA: ::nl_item = 0x32C; pub const ERA_D_FMT: ::nl_item = 0x32E; pub const ALT_DIGITS: ::nl_item = 0x32F; pub const ERA_D_T_FMT: ::nl_item = 0x330; pub const ERA_T_FMT: ::nl_item = 0x331; pub const CODESET: ::nl_item = 10; pub const CRNCYSTR: ::nl_item = 0x215; pub const RADIXCHAR: ::nl_item = 0x100; pub const THOUSEP: ::nl_item = 0x101; pub const NOEXPR: ::nl_item = 0x501; pub const YESSTR: ::nl_item = 0x502; pub const NOSTR: ::nl_item = 0x503; // Different than Gnu. pub const FILENAME_MAX: ::c_uint = 4095; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; pub const SOMAXCONN: ::c_int = 128; pub const ST_RELATIME: ::c_ulong = 4096; pub const AF_NFC: ::c_int = PF_NFC; pub const BUFSIZ: ::c_int = 4096; pub const EDEADLOCK: ::c_int = EDEADLK; pub const EXTA: ::c_uint = B19200; pub const EXTB: ::c_uint = B38400; pub const EXTPROC: ::tcflag_t = 0200000; pub const FOPEN_MAX: ::c_int = 16; pub const F_GETOWN: ::c_int = 9; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const F_RDLCK: ::c_int = 0; pub const F_SETOWN: ::c_int = 8; pub const F_UNLCK: ::c_int = 2; pub const F_WRLCK: ::c_int = 1; pub const IPV6_MULTICAST_ALL: ::c_int = 29; pub const IPV6_ROUTER_ALERT_ISOLATE: ::c_int = 30; pub const MAP_HUGE_SHIFT: ::c_int = 26; pub const MAP_HUGE_MASK: ::c_int = 0x3f; pub const MAP_HUGE_64KB: ::c_int = 16 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512KB: ::c_int = 19 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1MB: ::c_int = 20 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2MB: ::c_int = 21 << MAP_HUGE_SHIFT; pub const MAP_HUGE_8MB: ::c_int = 23 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16MB: ::c_int = 24 << MAP_HUGE_SHIFT; pub const MAP_HUGE_32MB: ::c_int = 25 << MAP_HUGE_SHIFT; pub const MAP_HUGE_256MB: ::c_int = 28 << MAP_HUGE_SHIFT; pub const MAP_HUGE_512MB: ::c_int = 29 << MAP_HUGE_SHIFT; pub const MAP_HUGE_1GB: ::c_int = 30 << MAP_HUGE_SHIFT; pub const MAP_HUGE_2GB: ::c_int = 31 << MAP_HUGE_SHIFT; pub const MAP_HUGE_16GB: ::c_int = 34 << MAP_HUGE_SHIFT; pub const MINSIGSTKSZ: ::c_int = 2048; pub const MSG_COPY: ::c_int = 040000; pub const NI_MAXHOST: ::socklen_t = 1025; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const PACKET_MR_UNICAST: ::c_int = 3; pub const PF_NFC: ::c_int = 39; pub const PF_VSOCK: ::c_int = 40; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const PTRACE_EVENT_STOP: ::c_int = 128; pub const PTRACE_GETSIGMASK: ::c_uint = 0x420a; pub const PTRACE_PEEKSIGINFO: ::c_int = 0x4209; pub const PTRACE_SETSIGMASK: ::c_uint = 0x420b; pub const RTLD_NOLOAD: ::c_int = 0x00004; pub const RUSAGE_THREAD: ::c_int = 1; pub const SHM_EXEC: ::c_int = 0100000; pub const SIGPOLL: ::c_int = SIGIO; pub const SOCK_DCCP: ::c_int = 6; pub const SOCK_PACKET: ::c_int = 10; pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15; pub const UDP_GRO: ::c_int = 104; pub const UDP_SEGMENT: ::c_int = 103; pub const YESEXPR: ::c_int = ((5) << 8) | (0); extern "C" { pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn pthread_rwlockattr_getkind_np( attr: *const ::pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setkind_np( attr: *mut ::pthread_rwlockattr_t, val: ::c_int, ) -> ::c_int; pub fn ptrace(request: ::c_uint, ...) -> ::c_long; pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, timeout: *mut ::timespec, ) -> ::c_int; pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::c_int; pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::pid_t; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn pwritev( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t; pub fn preadv( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t; pub fn sethostid(hostid: ::c_long) -> ::c_int; pub fn fanotify_mark( fd: ::c_int, flags: ::c_uint, mask: u64, dirfd: ::c_int, path: *const ::c_char, ) -> ::c_int; pub fn getrlimit64(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit64) -> ::c_int; pub fn setrlimit64(resource: ::__rlimit_resource_t, rlim: *const ::rlimit64) -> ::c_int; pub fn getrlimit(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::__rlimit_resource_t, rlim: *const ::rlimit) -> ::c_int; pub fn getpriority(which: ::__priority_which_t, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::__priority_which_t, who: ::id_t, prio: ::c_int) -> ::c_int; } cfg_if! { if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { mod mips; pub use self::mips::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else { pub use unsupported_target; } } libc/src/unix/linux_like/linux/uclibc/no_align.rs0000644000175000017500000000376514661133735023136 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { pub struct pthread_mutex_t { #[cfg(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc"))] __align: [::c_long; 0], #[cfg(any(libc_align, target_arch = "mips", target_arch = "arm", target_arch = "powerpc"))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } pub struct pthread_rwlock_t { #[cfg(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc"))] __align: [::c_long; 0], #[cfg(not(any( target_arch = "mips", target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } pub struct pthread_mutexattr_t { #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64"))] __align: [::c_int; 0], #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")))] __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } pub struct pthread_cond_t { __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_COND_T], } pub struct pthread_condattr_t { __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } } } libc/src/unix/linux_like/linux/uclibc/align.rs0000644000175000017500000000206214661133735022427 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { #[cfg_attr(any(target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64"), repr(align(4)))] #[cfg_attr(not(any(target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")), repr(align(8)))] pub struct pthread_mutexattr_t { size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } }; } libc/src/unix/linux_like/linux/uclibc/x86_64/0000775000175000017500000000000014661133735021727 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs0000644000175000017500000002423614661133735023061 0ustar jamespagejamespage//! Definitions for uclibc on 64bit systems pub type blkcnt_t = i64; pub type blksize_t = i64; pub type clock_t = i64; pub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type fsword_t = ::c_long; pub type ino_t = ::c_ulong; pub type nlink_t = ::c_uint; pub type off_t = ::c_long; // [uClibc docs] Note stat64 has the same shape as stat for x86-64. pub type stat64 = stat; pub type suseconds_t = ::c_long; pub type time_t = ::c_int; pub type wchar_t = ::c_int; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; pub type __u64 = ::c_ulong; pub type __s64 = ::c_long; s! { pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, // read / write __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } #[cfg(not(target_os = "l4re"))] pub struct pthread_attr_t { __detachstate: ::c_int, __schedpolicy: ::c_int, __schedparam: __sched_param, __inheritsched: ::c_int, __scope: ::c_int, __guardsize: ::size_t, __stackaddr_set: ::c_int, __stackaddr: *mut ::c_void, // better don't use it __stacksize: ::size_t, } pub struct __sched_param { __sched_priority: ::c_int, } pub struct siginfo_t { si_signo: ::c_int, // signal number si_errno: ::c_int, // if not zero: error value of signal, see errno.h si_code: ::c_int, // signal code pub _pad: [::c_int; 28], // unported union _align: [usize; 0], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, // segment size in bytes pub shm_atime: ::time_t, // time of last shmat() pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __ignored1: ::c_ulong, __ignored2: ::c_ulong, } pub struct sockaddr { pub sa_family: ::sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in { pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_in6 { pub sin6_family: ::sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } // ------------------------------------------------------------ // definitions below are *unverified* and might **break** the software // pub struct in_addr { // pub s_addr: in_addr_t, // } // // pub struct in6_addr { // pub s6_addr: [u8; 16], // #[cfg(not(libc_align))] // __align: [u32; 0], // } pub struct stat { pub st_dev: ::c_ulong, pub st_ino: ::ino_t, // According to uclibc/libc/sysdeps/linux/x86_64/bits/stat.h, order of // nlink and mode are swapped on 64 bit systems. pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulong, // dev_t pub st_size: off_t, // file size pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_ulong, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_ulong, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_ulong, st_pad4: [::c_long; 3] } pub struct sigaction { pub sa_handler: ::sighandler_t, pub sa_flags: ::c_ulong, pub sa_restorer: ::Option, pub sa_mask: ::sigset_t, } pub struct stack_t { // FIXME pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct statfs { // FIXME pub f_type: fsword_t, pub f_bsize: fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: fsword_t, pub f_frsize: fsword_t, f_spare: [fsword_t; 5], } pub struct statfs64 { pub f_type: ::c_int, pub f_bsize: ::c_int, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_int, pub f_frsize: ::c_int, pub f_flags: ::c_int, pub f_spare: [::c_int; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct msghdr { // FIXME pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::size_t, pub msg_control: *mut ::c_void, pub msg_controllen: ::size_t, pub msg_flags: ::c_int, } pub struct termios { // FIXME pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], } pub struct sigset_t { // FIXME __val: [::c_ulong; 16], } pub struct sysinfo { // FIXME pub uptime: ::c_long, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub _f: [::c_char; 0], } pub struct glob_t { // FIXME pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct cpu_set_t { // FIXME #[cfg(target_pointer_width = "32")] bits: [u32; 32], #[cfg(target_pointer_width = "64")] bits: [u64; 16], } pub struct fsid_t { // FIXME __val: [::c_int; 2], } // FIXME this is actually a union pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], __align: [::c_long; 0], } pub struct cmsghdr { pub cmsg_len: ::size_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } } s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct dirent { pub d_ino: ::ino64_t, pub d_off: ::off64_t, pub d_reclen: u16, pub d_type: u8, pub d_name: [::c_char; 256], } } // constants pub const ENAMETOOLONG: ::c_int = 36; // File name too long pub const ENOTEMPTY: ::c_int = 39; // Directory not empty pub const ELOOP: ::c_int = 40; // Too many symbolic links encountered pub const EADDRINUSE: ::c_int = 98; // Address already in use pub const EADDRNOTAVAIL: ::c_int = 99; // Cannot assign requested address pub const ENETDOWN: ::c_int = 100; // Network is down pub const ENETUNREACH: ::c_int = 101; // Network is unreachable pub const ECONNABORTED: ::c_int = 103; // Software caused connection abort pub const ECONNREFUSED: ::c_int = 111; // Connection refused pub const ECONNRESET: ::c_int = 104; // Connection reset by peer pub const EDEADLK: ::c_int = 35; // Resource deadlock would occur pub const ENOSYS: ::c_int = 38; // Function not implemented pub const ENOTCONN: ::c_int = 107; // Transport endpoint is not connected pub const ETIMEDOUT: ::c_int = 110; // connection timed out pub const ESTALE: ::c_int = 116; // Stale file handle pub const EHOSTUNREACH: ::c_int = 113; // No route to host pub const EDQUOT: ::c_int = 122; // Quota exceeded pub const EOPNOTSUPP: ::c_int = 0x5f; pub const ENODATA: ::c_int = 0x3d; pub const O_APPEND: ::c_int = 02000; pub const O_ACCMODE: ::c_int = 0003; pub const O_CLOEXEC: ::c_int = 0x80000; pub const O_CREAT: ::c_int = 0100; pub const O_DIRECTORY: ::c_int = 0200000; pub const O_EXCL: ::c_int = 0200; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_NONBLOCK: ::c_int = 04000; pub const O_TRUNC: ::c_int = 01000; pub const NCCS: usize = 32; pub const SIG_SETMASK: ::c_int = 2; // Set the set of blocked signals pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const SOCK_DGRAM: ::c_int = 2; // connectionless, unreliable datagrams pub const SOCK_STREAM: ::c_int = 1; // …/common/bits/socket_type.h pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const PIDFD_NONBLOCK: ::c_int = 04000; cfg_if! { if #[cfg(target_os = "l4re")] { mod l4re; pub use self::l4re::*; } else { mod other; pub use other::*; } } libc/src/unix/linux_like/linux/uclibc/x86_64/other.rs0000644000175000017500000000025414661133735023415 0ustar jamespagejamespage// Thestyle checker discourages the use of #[cfg], so this has to go into a // separate module pub type pthread_t = ::c_ulong; pub const PTHREAD_STACK_MIN: usize = 16384; libc/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs0000644000175000017500000000350214661133735023141 0ustar jamespagejamespage/// L4Re specifics /// This module contains definitions required by various L4Re libc backends. /// Some of them are formally not part of the libc, but are a dependency of the /// libc and hence we should provide them here. pub type l4_umword_t = ::c_ulong; // Unsigned machine word. pub type pthread_t = *mut ::c_void; s! { /// CPU sets. pub struct l4_sched_cpu_set_t { // from the L4Re docs /// Combination of granularity and offset. /// /// The granularity defines how many CPUs each bit in map describes. /// The offset is the number of the first CPU described by the first /// bit in the bitmap. /// offset must be a multiple of 2^graularity. /// /// | MSB | LSB | /// | ---------------- | ------------------- | /// | 8bit granularity | 24bit offset .. | gran_offset: l4_umword_t , /// Bitmap of CPUs. map: l4_umword_t , } } #[cfg(target_os = "l4re")] #[allow(missing_debug_implementations)] pub struct pthread_attr_t { pub __detachstate: ::c_int, pub __schedpolicy: ::c_int, pub __schedparam: super::__sched_param, pub __inheritsched: ::c_int, pub __scope: ::c_int, pub __guardsize: ::size_t, pub __stackaddr_set: ::c_int, pub __stackaddr: *mut ::c_void, // better don't use it pub __stacksize: ::size_t, // L4Re specifics pub affinity: l4_sched_cpu_set_t, pub create_flags: ::c_uint, } // L4Re requires a min stack size of 64k; that isn't defined in uClibc, but // somewhere in the core libraries. uClibc wants 16k, but that's not enough. pub const PTHREAD_STACK_MIN: usize = 65536; // Misc other constants required for building. pub const SIGIO: ::c_int = 29; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; libc/src/unix/linux_like/linux/uclibc/mips/0000775000175000017500000000000014661133735021741 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/uclibc/mips/mips32/0000775000175000017500000000000014661133735023056 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs0000644000175000017500000006422514661133735024212 0ustar jamespagejamespagepub type c_char = i8; pub type c_long = i32; pub type c_ulong = u32; pub type clock_t = i32; pub type time_t = i32; pub type suseconds_t = i32; pub type wchar_t = i32; pub type off_t = i32; pub type ino_t = u32; pub type blkcnt_t = i32; pub type blksize_t = i32; pub type nlink_t = u32; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; s! { pub struct stat { pub st_dev: ::dev_t, st_pad1: [::c_long; 2], pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_pad2: [::c_long; 1], pub st_size: ::off_t, st_pad3: ::c_long, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, st_pad5: [::c_long; 14], } pub struct stat64 { pub st_dev: ::dev_t, st_pad1: [::c_long; 2], pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, st_pad2: [::c_long; 2], pub st_size: ::off64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, st_pad3: ::c_long, pub st_blocks: ::blkcnt64_t, st_pad5: [::c_long; 14], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_favail: ::fsfilcnt64_t, pub f_fsid: ::c_ulong, pub __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct pthread_attr_t { __size: [u32; 9] } pub struct sigaction { pub sa_flags: ::c_uint, pub sa_sigaction: ::sighandler_t, pub sa_mask: sigset_t, _restorer: *mut ::c_void, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct sigset_t { __val: [::c_ulong; 4], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, pub _pad: [::c_int; 29], } pub struct glob64_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut ::c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_uint, pub __seq: ::c_ushort, __pad1: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct msqid_ds { pub msg_perm: ::ipc_perm, #[cfg(target_endian = "big")] __glibc_reserved1: ::c_ulong, pub msg_stime: ::time_t, #[cfg(target_endian = "little")] __glibc_reserved1: ::c_ulong, #[cfg(target_endian = "big")] __glibc_reserved2: ::c_ulong, pub msg_rtime: ::time_t, #[cfg(target_endian = "little")] __glibc_reserved2: ::c_ulong, #[cfg(target_endian = "big")] __glibc_reserved3: ::c_ulong, pub msg_ctime: ::time_t, #[cfg(target_endian = "little")] __glibc_reserved3: ::c_ulong, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_frsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_files: ::fsblkcnt_t, pub f_ffree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, f_spare: [::c_long; 6], } pub struct statfs64 { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_frsize: ::c_long, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_files: ::fsblkcnt64_t, pub f_ffree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 5], } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::size_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::size_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_sysid: ::c_long, pub l_pid: ::pid_t, pad: [::c_long; 4], } pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub _f: [::c_char; 8], } } pub const __SIZEOF_PTHREAD_ATTR_T: usize = 36; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const SYS_syscall: ::c_long = 4000 + 0; pub const SYS_exit: ::c_long = 4000 + 1; pub const SYS_fork: ::c_long = 4000 + 2; pub const SYS_read: ::c_long = 4000 + 3; pub const SYS_write: ::c_long = 4000 + 4; pub const SYS_open: ::c_long = 4000 + 5; pub const SYS_close: ::c_long = 4000 + 6; pub const SYS_waitpid: ::c_long = 4000 + 7; pub const SYS_creat: ::c_long = 4000 + 8; pub const SYS_link: ::c_long = 4000 + 9; pub const SYS_unlink: ::c_long = 4000 + 10; pub const SYS_execve: ::c_long = 4000 + 11; pub const SYS_chdir: ::c_long = 4000 + 12; pub const SYS_time: ::c_long = 4000 + 13; pub const SYS_mknod: ::c_long = 4000 + 14; pub const SYS_chmod: ::c_long = 4000 + 15; pub const SYS_lchown: ::c_long = 4000 + 16; pub const SYS_break: ::c_long = 4000 + 17; pub const SYS_lseek: ::c_long = 4000 + 19; pub const SYS_getpid: ::c_long = 4000 + 20; pub const SYS_mount: ::c_long = 4000 + 21; pub const SYS_umount: ::c_long = 4000 + 22; pub const SYS_setuid: ::c_long = 4000 + 23; pub const SYS_getuid: ::c_long = 4000 + 24; pub const SYS_stime: ::c_long = 4000 + 25; pub const SYS_ptrace: ::c_long = 4000 + 26; pub const SYS_alarm: ::c_long = 4000 + 27; pub const SYS_pause: ::c_long = 4000 + 29; pub const SYS_utime: ::c_long = 4000 + 30; pub const SYS_stty: ::c_long = 4000 + 31; pub const SYS_gtty: ::c_long = 4000 + 32; pub const SYS_access: ::c_long = 4000 + 33; pub const SYS_nice: ::c_long = 4000 + 34; pub const SYS_ftime: ::c_long = 4000 + 35; pub const SYS_sync: ::c_long = 4000 + 36; pub const SYS_kill: ::c_long = 4000 + 37; pub const SYS_rename: ::c_long = 4000 + 38; pub const SYS_mkdir: ::c_long = 4000 + 39; pub const SYS_rmdir: ::c_long = 4000 + 40; pub const SYS_dup: ::c_long = 4000 + 41; pub const SYS_pipe: ::c_long = 4000 + 42; pub const SYS_times: ::c_long = 4000 + 43; pub const SYS_prof: ::c_long = 4000 + 44; pub const SYS_brk: ::c_long = 4000 + 45; pub const SYS_setgid: ::c_long = 4000 + 46; pub const SYS_getgid: ::c_long = 4000 + 47; pub const SYS_signal: ::c_long = 4000 + 48; pub const SYS_geteuid: ::c_long = 4000 + 49; pub const SYS_getegid: ::c_long = 4000 + 50; pub const SYS_acct: ::c_long = 4000 + 51; pub const SYS_umount2: ::c_long = 4000 + 52; pub const SYS_lock: ::c_long = 4000 + 53; pub const SYS_ioctl: ::c_long = 4000 + 54; pub const SYS_fcntl: ::c_long = 4000 + 55; pub const SYS_mpx: ::c_long = 4000 + 56; pub const SYS_setpgid: ::c_long = 4000 + 57; pub const SYS_ulimit: ::c_long = 4000 + 58; pub const SYS_umask: ::c_long = 4000 + 60; pub const SYS_chroot: ::c_long = 4000 + 61; pub const SYS_ustat: ::c_long = 4000 + 62; pub const SYS_dup2: ::c_long = 4000 + 63; pub const SYS_getppid: ::c_long = 4000 + 64; pub const SYS_getpgrp: ::c_long = 4000 + 65; pub const SYS_setsid: ::c_long = 4000 + 66; pub const SYS_sigaction: ::c_long = 4000 + 67; pub const SYS_sgetmask: ::c_long = 4000 + 68; pub const SYS_ssetmask: ::c_long = 4000 + 69; pub const SYS_setreuid: ::c_long = 4000 + 70; pub const SYS_setregid: ::c_long = 4000 + 71; pub const SYS_sigsuspend: ::c_long = 4000 + 72; pub const SYS_sigpending: ::c_long = 4000 + 73; pub const SYS_sethostname: ::c_long = 4000 + 74; pub const SYS_setrlimit: ::c_long = 4000 + 75; pub const SYS_getrlimit: ::c_long = 4000 + 76; pub const SYS_getrusage: ::c_long = 4000 + 77; pub const SYS_gettimeofday: ::c_long = 4000 + 78; pub const SYS_settimeofday: ::c_long = 4000 + 79; pub const SYS_getgroups: ::c_long = 4000 + 80; pub const SYS_setgroups: ::c_long = 4000 + 81; pub const SYS_symlink: ::c_long = 4000 + 83; pub const SYS_readlink: ::c_long = 4000 + 85; pub const SYS_uselib: ::c_long = 4000 + 86; pub const SYS_swapon: ::c_long = 4000 + 87; pub const SYS_reboot: ::c_long = 4000 + 88; pub const SYS_readdir: ::c_long = 4000 + 89; pub const SYS_mmap: ::c_long = 4000 + 90; pub const SYS_munmap: ::c_long = 4000 + 91; pub const SYS_truncate: ::c_long = 4000 + 92; pub const SYS_ftruncate: ::c_long = 4000 + 93; pub const SYS_fchmod: ::c_long = 4000 + 94; pub const SYS_fchown: ::c_long = 4000 + 95; pub const SYS_getpriority: ::c_long = 4000 + 96; pub const SYS_setpriority: ::c_long = 4000 + 97; pub const SYS_profil: ::c_long = 4000 + 98; pub const SYS_statfs: ::c_long = 4000 + 99; pub const SYS_fstatfs: ::c_long = 4000 + 100; pub const SYS_ioperm: ::c_long = 4000 + 101; pub const SYS_socketcall: ::c_long = 4000 + 102; pub const SYS_syslog: ::c_long = 4000 + 103; pub const SYS_setitimer: ::c_long = 4000 + 104; pub const SYS_getitimer: ::c_long = 4000 + 105; pub const SYS_stat: ::c_long = 4000 + 106; pub const SYS_lstat: ::c_long = 4000 + 107; pub const SYS_fstat: ::c_long = 4000 + 108; pub const SYS_iopl: ::c_long = 4000 + 110; pub const SYS_vhangup: ::c_long = 4000 + 111; pub const SYS_idle: ::c_long = 4000 + 112; pub const SYS_vm86: ::c_long = 4000 + 113; pub const SYS_wait4: ::c_long = 4000 + 114; pub const SYS_swapoff: ::c_long = 4000 + 115; pub const SYS_sysinfo: ::c_long = 4000 + 116; pub const SYS_ipc: ::c_long = 4000 + 117; pub const SYS_fsync: ::c_long = 4000 + 118; pub const SYS_sigreturn: ::c_long = 4000 + 119; pub const SYS_clone: ::c_long = 4000 + 120; pub const SYS_setdomainname: ::c_long = 4000 + 121; pub const SYS_uname: ::c_long = 4000 + 122; pub const SYS_modify_ldt: ::c_long = 4000 + 123; pub const SYS_adjtimex: ::c_long = 4000 + 124; pub const SYS_mprotect: ::c_long = 4000 + 125; pub const SYS_sigprocmask: ::c_long = 4000 + 126; pub const SYS_create_module: ::c_long = 4000 + 127; pub const SYS_init_module: ::c_long = 4000 + 128; pub const SYS_delete_module: ::c_long = 4000 + 129; pub const SYS_get_kernel_syms: ::c_long = 4000 + 130; pub const SYS_quotactl: ::c_long = 4000 + 131; pub const SYS_getpgid: ::c_long = 4000 + 132; pub const SYS_fchdir: ::c_long = 4000 + 133; pub const SYS_bdflush: ::c_long = 4000 + 134; pub const SYS_sysfs: ::c_long = 4000 + 135; pub const SYS_personality: ::c_long = 4000 + 136; pub const SYS_afs_syscall: ::c_long = 4000 + 137; pub const SYS_setfsuid: ::c_long = 4000 + 138; pub const SYS_setfsgid: ::c_long = 4000 + 139; pub const SYS__llseek: ::c_long = 4000 + 140; pub const SYS_getdents: ::c_long = 4000 + 141; pub const SYS__newselect: ::c_long = 4000 + 142; pub const SYS_flock: ::c_long = 4000 + 143; pub const SYS_msync: ::c_long = 4000 + 144; pub const SYS_readv: ::c_long = 4000 + 145; pub const SYS_writev: ::c_long = 4000 + 146; pub const SYS_cacheflush: ::c_long = 4000 + 147; pub const SYS_cachectl: ::c_long = 4000 + 148; pub const SYS_sysmips: ::c_long = 4000 + 149; pub const SYS_getsid: ::c_long = 4000 + 151; pub const SYS_fdatasync: ::c_long = 4000 + 152; pub const SYS__sysctl: ::c_long = 4000 + 153; pub const SYS_mlock: ::c_long = 4000 + 154; pub const SYS_munlock: ::c_long = 4000 + 155; pub const SYS_mlockall: ::c_long = 4000 + 156; pub const SYS_munlockall: ::c_long = 4000 + 157; pub const SYS_sched_setparam: ::c_long = 4000 + 158; pub const SYS_sched_getparam: ::c_long = 4000 + 159; pub const SYS_sched_setscheduler: ::c_long = 4000 + 160; pub const SYS_sched_getscheduler: ::c_long = 4000 + 161; pub const SYS_sched_yield: ::c_long = 4000 + 162; pub const SYS_sched_get_priority_max: ::c_long = 4000 + 163; pub const SYS_sched_get_priority_min: ::c_long = 4000 + 164; pub const SYS_sched_rr_get_interval: ::c_long = 4000 + 165; pub const SYS_nanosleep: ::c_long = 4000 + 166; pub const SYS_mremap: ::c_long = 4000 + 167; pub const SYS_accept: ::c_long = 4000 + 168; pub const SYS_bind: ::c_long = 4000 + 169; pub const SYS_connect: ::c_long = 4000 + 170; pub const SYS_getpeername: ::c_long = 4000 + 171; pub const SYS_getsockname: ::c_long = 4000 + 172; pub const SYS_getsockopt: ::c_long = 4000 + 173; pub const SYS_listen: ::c_long = 4000 + 174; pub const SYS_recv: ::c_long = 4000 + 175; pub const SYS_recvfrom: ::c_long = 4000 + 176; pub const SYS_recvmsg: ::c_long = 4000 + 177; pub const SYS_send: ::c_long = 4000 + 178; pub const SYS_sendmsg: ::c_long = 4000 + 179; pub const SYS_sendto: ::c_long = 4000 + 180; pub const SYS_setsockopt: ::c_long = 4000 + 181; pub const SYS_shutdown: ::c_long = 4000 + 182; pub const SYS_socket: ::c_long = 4000 + 183; pub const SYS_socketpair: ::c_long = 4000 + 184; pub const SYS_setresuid: ::c_long = 4000 + 185; pub const SYS_getresuid: ::c_long = 4000 + 186; pub const SYS_query_module: ::c_long = 4000 + 187; pub const SYS_poll: ::c_long = 4000 + 188; pub const SYS_nfsservctl: ::c_long = 4000 + 189; pub const SYS_setresgid: ::c_long = 4000 + 190; pub const SYS_getresgid: ::c_long = 4000 + 191; pub const SYS_prctl: ::c_long = 4000 + 192; pub const SYS_rt_sigreturn: ::c_long = 4000 + 193; pub const SYS_rt_sigaction: ::c_long = 4000 + 194; pub const SYS_rt_sigprocmask: ::c_long = 4000 + 195; pub const SYS_rt_sigpending: ::c_long = 4000 + 196; pub const SYS_rt_sigtimedwait: ::c_long = 4000 + 197; pub const SYS_rt_sigqueueinfo: ::c_long = 4000 + 198; pub const SYS_rt_sigsuspend: ::c_long = 4000 + 199; pub const SYS_pread64: ::c_long = 4000 + 200; pub const SYS_pwrite64: ::c_long = 4000 + 201; pub const SYS_chown: ::c_long = 4000 + 202; pub const SYS_getcwd: ::c_long = 4000 + 203; pub const SYS_capget: ::c_long = 4000 + 204; pub const SYS_capset: ::c_long = 4000 + 205; pub const SYS_sigaltstack: ::c_long = 4000 + 206; pub const SYS_sendfile: ::c_long = 4000 + 207; pub const SYS_getpmsg: ::c_long = 4000 + 208; pub const SYS_putpmsg: ::c_long = 4000 + 209; pub const SYS_mmap2: ::c_long = 4000 + 210; pub const SYS_truncate64: ::c_long = 4000 + 211; pub const SYS_ftruncate64: ::c_long = 4000 + 212; pub const SYS_stat64: ::c_long = 4000 + 213; pub const SYS_lstat64: ::c_long = 4000 + 214; pub const SYS_fstat64: ::c_long = 4000 + 215; pub const SYS_pivot_root: ::c_long = 4000 + 216; pub const SYS_mincore: ::c_long = 4000 + 217; pub const SYS_madvise: ::c_long = 4000 + 218; pub const SYS_getdents64: ::c_long = 4000 + 219; pub const SYS_fcntl64: ::c_long = 4000 + 220; pub const SYS_gettid: ::c_long = 4000 + 222; pub const SYS_readahead: ::c_long = 4000 + 223; pub const SYS_setxattr: ::c_long = 4000 + 224; pub const SYS_lsetxattr: ::c_long = 4000 + 225; pub const SYS_fsetxattr: ::c_long = 4000 + 226; pub const SYS_getxattr: ::c_long = 4000 + 227; pub const SYS_lgetxattr: ::c_long = 4000 + 228; pub const SYS_fgetxattr: ::c_long = 4000 + 229; pub const SYS_listxattr: ::c_long = 4000 + 230; pub const SYS_llistxattr: ::c_long = 4000 + 231; pub const SYS_flistxattr: ::c_long = 4000 + 232; pub const SYS_removexattr: ::c_long = 4000 + 233; pub const SYS_lremovexattr: ::c_long = 4000 + 234; pub const SYS_fremovexattr: ::c_long = 4000 + 235; pub const SYS_tkill: ::c_long = 4000 + 236; pub const SYS_sendfile64: ::c_long = 4000 + 237; pub const SYS_futex: ::c_long = 4000 + 238; pub const SYS_sched_setaffinity: ::c_long = 4000 + 239; pub const SYS_sched_getaffinity: ::c_long = 4000 + 240; pub const SYS_io_setup: ::c_long = 4000 + 241; pub const SYS_io_destroy: ::c_long = 4000 + 242; pub const SYS_io_getevents: ::c_long = 4000 + 243; pub const SYS_io_submit: ::c_long = 4000 + 244; pub const SYS_io_cancel: ::c_long = 4000 + 245; pub const SYS_exit_group: ::c_long = 4000 + 246; pub const SYS_lookup_dcookie: ::c_long = 4000 + 247; pub const SYS_epoll_create: ::c_long = 4000 + 248; pub const SYS_epoll_ctl: ::c_long = 4000 + 249; pub const SYS_epoll_wait: ::c_long = 4000 + 250; pub const SYS_remap_file_pages: ::c_long = 4000 + 251; pub const SYS_set_tid_address: ::c_long = 4000 + 252; pub const SYS_restart_syscall: ::c_long = 4000 + 253; pub const SYS_fadvise64: ::c_long = 4000 + 254; pub const SYS_statfs64: ::c_long = 4000 + 255; pub const SYS_fstatfs64: ::c_long = 4000 + 256; pub const SYS_timer_create: ::c_long = 4000 + 257; pub const SYS_timer_settime: ::c_long = 4000 + 258; pub const SYS_timer_gettime: ::c_long = 4000 + 259; pub const SYS_timer_getoverrun: ::c_long = 4000 + 260; pub const SYS_timer_delete: ::c_long = 4000 + 261; pub const SYS_clock_settime: ::c_long = 4000 + 262; pub const SYS_clock_gettime: ::c_long = 4000 + 263; pub const SYS_clock_getres: ::c_long = 4000 + 264; pub const SYS_clock_nanosleep: ::c_long = 4000 + 265; pub const SYS_tgkill: ::c_long = 4000 + 266; pub const SYS_utimes: ::c_long = 4000 + 267; pub const SYS_mbind: ::c_long = 4000 + 268; pub const SYS_get_mempolicy: ::c_long = 4000 + 269; pub const SYS_set_mempolicy: ::c_long = 4000 + 270; pub const SYS_mq_open: ::c_long = 4000 + 271; pub const SYS_mq_unlink: ::c_long = 4000 + 272; pub const SYS_mq_timedsend: ::c_long = 4000 + 273; pub const SYS_mq_timedreceive: ::c_long = 4000 + 274; pub const SYS_mq_notify: ::c_long = 4000 + 275; pub const SYS_mq_getsetattr: ::c_long = 4000 + 276; pub const SYS_vserver: ::c_long = 4000 + 277; pub const SYS_waitid: ::c_long = 4000 + 278; /* pub const SYS_sys_setaltroot: ::c_long = 4000 + 279; */ pub const SYS_add_key: ::c_long = 4000 + 280; pub const SYS_request_key: ::c_long = 4000 + 281; pub const SYS_keyctl: ::c_long = 4000 + 282; pub const SYS_set_thread_area: ::c_long = 4000 + 283; pub const SYS_inotify_init: ::c_long = 4000 + 284; pub const SYS_inotify_add_watch: ::c_long = 4000 + 285; pub const SYS_inotify_rm_watch: ::c_long = 4000 + 286; pub const SYS_migrate_pages: ::c_long = 4000 + 287; pub const SYS_openat: ::c_long = 4000 + 288; pub const SYS_mkdirat: ::c_long = 4000 + 289; pub const SYS_mknodat: ::c_long = 4000 + 290; pub const SYS_fchownat: ::c_long = 4000 + 291; pub const SYS_futimesat: ::c_long = 4000 + 292; pub const SYS_fstatat64: ::c_long = 4000 + 293; pub const SYS_unlinkat: ::c_long = 4000 + 294; pub const SYS_renameat: ::c_long = 4000 + 295; pub const SYS_linkat: ::c_long = 4000 + 296; pub const SYS_symlinkat: ::c_long = 4000 + 297; pub const SYS_readlinkat: ::c_long = 4000 + 298; pub const SYS_fchmodat: ::c_long = 4000 + 299; pub const SYS_faccessat: ::c_long = 4000 + 300; pub const SYS_pselect6: ::c_long = 4000 + 301; pub const SYS_ppoll: ::c_long = 4000 + 302; pub const SYS_unshare: ::c_long = 4000 + 303; pub const SYS_splice: ::c_long = 4000 + 304; pub const SYS_sync_file_range: ::c_long = 4000 + 305; pub const SYS_tee: ::c_long = 4000 + 306; pub const SYS_vmsplice: ::c_long = 4000 + 307; pub const SYS_move_pages: ::c_long = 4000 + 308; pub const SYS_set_robust_list: ::c_long = 4000 + 309; pub const SYS_get_robust_list: ::c_long = 4000 + 310; pub const SYS_kexec_load: ::c_long = 4000 + 311; pub const SYS_getcpu: ::c_long = 4000 + 312; pub const SYS_epoll_pwait: ::c_long = 4000 + 313; pub const SYS_ioprio_set: ::c_long = 4000 + 314; pub const SYS_ioprio_get: ::c_long = 4000 + 315; pub const SYS_utimensat: ::c_long = 4000 + 316; pub const SYS_signalfd: ::c_long = 4000 + 317; pub const SYS_timerfd: ::c_long = 4000 + 318; pub const SYS_eventfd: ::c_long = 4000 + 319; pub const SYS_fallocate: ::c_long = 4000 + 320; pub const SYS_timerfd_create: ::c_long = 4000 + 321; pub const SYS_timerfd_gettime: ::c_long = 4000 + 322; pub const SYS_timerfd_settime: ::c_long = 4000 + 323; pub const SYS_signalfd4: ::c_long = 4000 + 324; pub const SYS_eventfd2: ::c_long = 4000 + 325; pub const SYS_epoll_create1: ::c_long = 4000 + 326; pub const SYS_dup3: ::c_long = 4000 + 327; pub const SYS_pipe2: ::c_long = 4000 + 328; pub const SYS_inotify_init1: ::c_long = 4000 + 329; pub const SYS_preadv: ::c_long = 4000 + 330; pub const SYS_pwritev: ::c_long = 4000 + 331; pub const SYS_rt_tgsigqueueinfo: ::c_long = 4000 + 332; pub const SYS_perf_event_open: ::c_long = 4000 + 333; pub const SYS_accept4: ::c_long = 4000 + 334; pub const SYS_recvmmsg: ::c_long = 4000 + 335; pub const SYS_fanotify_init: ::c_long = 4000 + 336; pub const SYS_fanotify_mark: ::c_long = 4000 + 337; pub const SYS_prlimit64: ::c_long = 4000 + 338; pub const SYS_name_to_handle_at: ::c_long = 4000 + 339; pub const SYS_open_by_handle_at: ::c_long = 4000 + 340; pub const SYS_clock_adjtime: ::c_long = 4000 + 341; pub const SYS_syncfs: ::c_long = 4000 + 342; pub const SYS_sendmmsg: ::c_long = 4000 + 343; pub const SYS_setns: ::c_long = 4000 + 344; pub const SYS_process_vm_readv: ::c_long = 4000 + 345; pub const SYS_process_vm_writev: ::c_long = 4000 + 346; pub const SYS_kcmp: ::c_long = 4000 + 347; pub const SYS_finit_module: ::c_long = 4000 + 348; pub const SYS_sched_setattr: ::c_long = 4000 + 349; pub const SYS_sched_getattr: ::c_long = 4000 + 350; pub const SYS_renameat2: ::c_long = 4000 + 351; pub const SYS_seccomp: ::c_long = 4000 + 352; pub const SYS_getrandom: ::c_long = 4000 + 353; pub const SYS_memfd_create: ::c_long = 4000 + 354; pub const SYS_bpf: ::c_long = 4000 + 355; pub const SYS_execveat: ::c_long = 4000 + 356; pub const SYS_userfaultfd: ::c_long = 4000 + 357; pub const SYS_membarrier: ::c_long = 4000 + 358; pub const SYS_mlock2: ::c_long = 4000 + 359; pub const SYS_copy_file_range: ::c_long = 4000 + 360; pub const SYS_preadv2: ::c_long = 4000 + 361; pub const SYS_pwritev2: ::c_long = 4000 + 362; pub const SYS_pkey_mprotect: ::c_long = 4000 + 363; pub const SYS_pkey_alloc: ::c_long = 4000 + 364; pub const SYS_pkey_free: ::c_long = 4000 + 365; pub const SYS_statx: ::c_long = 4000 + 366; pub const SYS_pidfd_send_signal: ::c_long = 4000 + 424; pub const SYS_io_uring_setup: ::c_long = 4000 + 425; pub const SYS_io_uring_enter: ::c_long = 4000 + 426; pub const SYS_io_uring_register: ::c_long = 4000 + 427; pub const SYS_open_tree: ::c_long = 4000 + 428; pub const SYS_move_mount: ::c_long = 4000 + 429; pub const SYS_fsopen: ::c_long = 4000 + 430; pub const SYS_fsconfig: ::c_long = 4000 + 431; pub const SYS_fsmount: ::c_long = 4000 + 432; pub const SYS_fspick: ::c_long = 4000 + 433; pub const SYS_pidfd_open: ::c_long = 4000 + 434; pub const SYS_clone3: ::c_long = 4000 + 435; pub const SYS_close_range: ::c_long = 4000 + 436; pub const SYS_openat2: ::c_long = 4000 + 437; pub const SYS_pidfd_getfd: ::c_long = 4000 + 438; pub const SYS_faccessat2: ::c_long = 4000 + 439; pub const SYS_process_madvise: ::c_long = 4000 + 440; pub const SYS_epoll_pwait2: ::c_long = 4000 + 441; pub const SYS_mount_setattr: ::c_long = 4000 + 442; pub const SYS_quotactl_fd: ::c_long = 4000 + 443; pub const SYS_landlock_create_ruleset: ::c_long = 4000 + 444; pub const SYS_landlock_add_rule: ::c_long = 4000 + 445; pub const SYS_landlock_restrict_self: ::c_long = 4000 + 446; pub const SYS_memfd_secret: ::c_long = 4000 + 447; pub const SYS_process_mrelease: ::c_long = 4000 + 448; pub const SYS_futex_waitv: ::c_long = 4000 + 449; pub const SYS_set_mempolicy_home_node: ::c_long = 4000 + 450; #[link(name = "util")] extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn glob64( pattern: *const ::c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut glob64_t, ) -> ::c_int; pub fn globfree64(pglob: *mut glob64_t); pub fn pthread_attr_getaffinity_np( attr: *const ::pthread_attr_t, cpusetsize: ::size_t, cpuset: *mut ::cpu_set_t, ) -> ::c_int; pub fn pthread_attr_setaffinity_np( attr: *mut ::pthread_attr_t, cpusetsize: ::size_t, cpuset: *const ::cpu_set_t, ) -> ::c_int; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } else { mod no_align; pub use self::no_align::*; } } libc/src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs0000644000175000017500000000040214661133735025204 0ustar jamespagejamespages! { // FIXME this is actually a union pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], __align: [::c_long; 0], } } libc/src/unix/linux_like/linux/uclibc/mips/mips32/align.rs0000644000175000017500000000057214661133735024520 0ustar jamespagejamespages! { // FIXME this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], } } libc/src/unix/linux_like/linux/uclibc/mips/mod.rs0000644000175000017500000002406514661133735023073 0ustar jamespagejamespagepub type pthread_t = ::c_ulong; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_CLOEXEC: ::c_int = 0x80000; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const TMP_MAX: ::c_uint = 238328; pub const _SC_2_C_VERSION: ::c_int = 96; pub const O_ACCMODE: ::c_int = 3; pub const O_DIRECT: ::c_int = 0x8000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_NOATIME: ::c_int = 0x40000; pub const O_PATH: ::c_int = 0o010000000; pub const O_APPEND: ::c_int = 8; pub const O_CREAT: ::c_int = 256; pub const O_EXCL: ::c_int = 1024; pub const O_NOCTTY: ::c_int = 2048; pub const O_NONBLOCK: ::c_int = 128; pub const O_SYNC: ::c_int = 0x10; pub const O_RSYNC: ::c_int = 0x10; pub const O_DSYNC: ::c_int = 0x10; pub const O_FSYNC: ::c_int = 0x10; pub const O_ASYNC: ::c_int = 0x1000; pub const O_LARGEFILE: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x80; pub const SOCK_NONBLOCK: ::c_int = 128; pub const PIDFD_NONBLOCK: ::c_int = 128; pub const EDEADLK: ::c_int = 45; pub const ENAMETOOLONG: ::c_int = 78; pub const ENOLCK: ::c_int = 46; pub const ENOSYS: ::c_int = 89; pub const ENOTEMPTY: ::c_int = 93; pub const ELOOP: ::c_int = 90; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EBADE: ::c_int = 50; pub const EBADR: ::c_int = 51; pub const EXFULL: ::c_int = 52; pub const FFDLY: ::c_int = 0o0100000; pub const ENOANO: ::c_int = 53; pub const EBADRQC: ::c_int = 54; pub const EBADSLT: ::c_int = 55; pub const EMULTIHOP: ::c_int = 74; pub const EOVERFLOW: ::c_int = 79; pub const ENOTUNIQ: ::c_int = 80; pub const EBADFD: ::c_int = 81; pub const EBADMSG: ::c_int = 77; pub const EREMCHG: ::c_int = 82; pub const ELIBACC: ::c_int = 83; pub const ELIBBAD: ::c_int = 84; pub const ELIBSCN: ::c_int = 85; pub const ELIBMAX: ::c_int = 86; pub const ELIBEXEC: ::c_int = 87; pub const EILSEQ: ::c_int = 88; pub const ERESTART: ::c_int = 91; pub const ESTRPIPE: ::c_int = 92; pub const EUSERS: ::c_int = 94; pub const ENOTSOCK: ::c_int = 95; pub const EDESTADDRREQ: ::c_int = 96; pub const EMSGSIZE: ::c_int = 97; pub const EPROTOTYPE: ::c_int = 98; pub const ENOPROTOOPT: ::c_int = 99; pub const EPROTONOSUPPORT: ::c_int = 120; pub const ESOCKTNOSUPPORT: ::c_int = 121; pub const EOPNOTSUPP: ::c_int = 122; pub const EPFNOSUPPORT: ::c_int = 123; pub const EAFNOSUPPORT: ::c_int = 124; pub const EADDRINUSE: ::c_int = 125; pub const EADDRNOTAVAIL: ::c_int = 126; pub const ENETDOWN: ::c_int = 127; pub const ENETUNREACH: ::c_int = 128; pub const ENETRESET: ::c_int = 129; pub const ECONNABORTED: ::c_int = 130; pub const ECONNRESET: ::c_int = 131; pub const ENOBUFS: ::c_int = 132; pub const EISCONN: ::c_int = 133; pub const ENOTCONN: ::c_int = 134; pub const ESHUTDOWN: ::c_int = 143; pub const ETOOMANYREFS: ::c_int = 144; pub const ETIMEDOUT: ::c_int = 145; pub const ECONNREFUSED: ::c_int = 146; pub const EHOSTDOWN: ::c_int = 147; pub const EHOSTUNREACH: ::c_int = 148; pub const EALREADY: ::c_int = 149; pub const EINPROGRESS: ::c_int = 150; pub const ESTALE: ::c_int = 151; pub const EUCLEAN: ::c_int = 135; pub const ENOTNAM: ::c_int = 137; pub const ENAVAIL: ::c_int = 138; pub const EISNAM: ::c_int = 139; pub const EREMOTEIO: ::c_int = 140; pub const EDQUOT: ::c_int = 1133; pub const ENOMEDIUM: ::c_int = 159; pub const EMEDIUMTYPE: ::c_int = 160; pub const ECANCELED: ::c_int = 158; pub const ENOKEY: ::c_int = 161; pub const EKEYEXPIRED: ::c_int = 162; pub const EKEYREVOKED: ::c_int = 163; pub const EKEYREJECTED: ::c_int = 164; pub const EOWNERDEAD: ::c_int = 165; pub const ENOTRECOVERABLE: ::c_int = 166; pub const ERFKILL: ::c_int = 167; pub const MAP_NORESERVE: ::c_int = 0x400; pub const MAP_ANON: ::c_int = 0x800; pub const MAP_ANONYMOUS: ::c_int = 0x800; pub const MAP_GROWSDOWN: ::c_int = 0x1000; pub const MAP_DENYWRITE: ::c_int = 0x2000; pub const MAP_EXECUTABLE: ::c_int = 0x4000; pub const MAP_LOCKED: ::c_int = 0x8000; pub const MAP_POPULATE: ::c_int = 0x10000; pub const MAP_NONBLOCK: ::c_int = 0x20000; pub const MAP_STACK: ::c_int = 0x40000; pub const NLDLY: ::tcflag_t = 0o0000400; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SA_ONSTACK: ::c_uint = 0x08000000; pub const SA_SIGINFO: ::c_uint = 0x00000008; pub const SA_NOCLDWAIT: ::c_int = 0x00010000; pub const SIGCHLD: ::c_int = 18; pub const SIGBUS: ::c_int = 10; pub const SIGTTIN: ::c_int = 26; pub const SIGTTOU: ::c_int = 27; pub const SIGXCPU: ::c_int = 30; pub const SIGXFSZ: ::c_int = 31; pub const SIGVTALRM: ::c_int = 28; pub const SIGPROF: ::c_int = 29; pub const SIGWINCH: ::c_int = 20; pub const SIGUSR1: ::c_int = 16; pub const SIGUSR2: ::c_int = 17; pub const SIGCONT: ::c_int = 25; pub const SIGSTOP: ::c_int = 23; pub const SIGTSTP: ::c_int = 24; pub const SIGURG: ::c_int = 21; pub const SIGIO: ::c_int = 22; pub const SIGSYS: ::c_int = 12; pub const SIGPWR: ::c_int = 19; pub const SIG_SETMASK: ::c_int = 3; pub const SIG_BLOCK: ::c_int = 0x1; pub const SIG_UNBLOCK: ::c_int = 0x2; pub const POLLWRNORM: ::c_short = 0x004; pub const POLLWRBAND: ::c_short = 0x100; pub const PTHREAD_STACK_MIN: ::size_t = 16384; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: ::tcflag_t = 0x00000100; pub const TOSTOP: ::tcflag_t = 0x00008000; pub const FLUSHO: ::tcflag_t = 0x00002000; pub const TCSANOW: ::c_int = 0x540e; pub const TCSADRAIN: ::c_int = 0x540f; pub const TCSAFLUSH: ::c_int = 0x5410; pub const CPU_SETSIZE: ::c_int = 0x400; pub const EFD_NONBLOCK: ::c_int = 0x80; pub const F_GETLK: ::c_int = 14; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const SFD_NONBLOCK: ::c_int = 0x80; pub const RTLD_GLOBAL: ::c_int = 0x4; pub const SIGSTKSZ: ::size_t = 8192; pub const CBAUD: ::tcflag_t = 0o0010017; pub const CBAUDEX: ::tcflag_t = 0o0010000; pub const CIBAUD: ::tcflag_t = 0o002003600000; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const TABDLY: ::tcflag_t = 0o0014000; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const BSDLY: ::tcflag_t = 0o0020000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const XTABS: ::tcflag_t = 0o0014000; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSWTC: usize = 7; pub const VTDLY: ::c_int = 0o0040000; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const OLCUC: ::tcflag_t = 0o0000002; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CRDLY: ::c_int = 0o0003000; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const MAP_HUGETLB: ::c_int = 0x80000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; cfg_if! { if #[cfg(target_arch = "mips")] { mod mips32; pub use self::mips32::*; } else if #[cfg(target_arch = "mips64")] { mod mips64; pub use self::mips64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/uclibc/mips/mips64/0000775000175000017500000000000014661133735023063 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs0000644000175000017500000001253614661133735024215 0ustar jamespagejamespagepub type blkcnt_t = i64; pub type blksize_t = i64; pub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type ino_t = u64; pub type nlink_t = u64; pub type off_t = i64; pub type suseconds_t = i64; pub type time_t = i64; pub type wchar_t = i32; s! { pub struct stat { pub st_dev: ::c_ulong, st_pad1: [::c_long; 2], pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulong, st_pad2: [::c_ulong; 1], pub st_size: ::off_t, st_pad3: ::c_long, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, st_pad4: ::c_long, pub st_blocks: ::blkcnt_t, st_pad5: [::c_long; 7], } pub struct stat64 { pub st_dev: ::c_ulong, st_pad1: [::c_long; 2], pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulong, st_pad2: [::c_long; 2], pub st_size: ::off64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, st_pad3: ::c_long, pub st_blocks: ::blkcnt64_t, st_pad5: [::c_long; 7], } pub struct pthread_attr_t { __size: [::c_ulong; 7] } pub struct sigaction { pub sa_flags: ::c_int, pub sa_sigaction: ::sighandler_t, pub sa_mask: sigset_t, _restorer: *mut ::c_void, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct sigset_t { __size: [::c_ulong; 16], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, _pad: ::c_int, _pad2: [::c_long; 14], } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_uint, pub __seq: ::c_ushort, __pad1: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_frsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_files: ::fsblkcnt_t, pub f_ffree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, f_spare: [::c_long; 6], } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::size_t, pub msg_control: *mut ::c_void, pub msg_controllen: ::size_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::size_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], } pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub _f: [::c_char; 0], } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const SYS_gettid: ::c_long = 5178; // Valid for n64 cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } else { mod no_align; pub use self::no_align::*; } } libc/src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs0000644000175000017500000000021214661133735025210 0ustar jamespagejamespages! { // FIXME this is actually a union pub struct sem_t { __size: [::c_char; 32], __align: [::c_long; 0], } } libc/src/unix/linux_like/linux/uclibc/mips/mips64/align.rs0000644000175000017500000000040214661133735024515 0ustar jamespagejamespages! { // FIXME this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { __size: [::c_char; 32], } } libc/src/unix/linux_like/linux/mod.rs0000644000175000017500000060376214661133735020671 0ustar jamespagejamespage//! Linux-specific definitions for linux-like values pub type useconds_t = u32; pub type dev_t = u64; pub type socklen_t = u32; pub type mode_t = u32; pub type ino64_t = u64; pub type off64_t = i64; pub type blkcnt64_t = i64; pub type rlim64_t = u64; pub type mqd_t = ::c_int; pub type nfds_t = ::c_ulong; pub type nl_item = ::c_int; pub type idtype_t = ::c_uint; pub type loff_t = ::c_longlong; pub type pthread_key_t = ::c_uint; pub type pthread_once_t = ::c_int; pub type pthread_spinlock_t = ::c_int; pub type __u8 = ::c_uchar; pub type __u16 = ::c_ushort; pub type __s16 = ::c_short; pub type __u32 = ::c_uint; pub type __s32 = ::c_int; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type Elf64_Sxword = i64; pub type Elf32_Section = u16; pub type Elf64_Section = u16; // linux/can.h pub type canid_t = u32; // linux/can/j1939.h pub type can_err_mask_t = u32; pub type pgn_t = u32; pub type priority_t = u8; pub type name_t = u64; pub type iconv_t = *mut ::c_void; // linux/sctp.h pub type sctp_assoc_t = ::__s32; pub type eventfd_t = u64; missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME: fill this out with a struct } s! { pub struct glob_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct spwd { pub sp_namp: *mut ::c_char, pub sp_pwdp: *mut ::c_char, pub sp_lstchg: ::c_long, pub sp_min: ::c_long, pub sp_max: ::c_long, pub sp_warn: ::c_long, pub sp_inact: ::c_long, pub sp_expire: ::c_long, pub sp_flag: ::c_ulong, } pub struct dqblk { pub dqb_bhardlimit: u64, pub dqb_bsoftlimit: u64, pub dqb_curspace: u64, pub dqb_ihardlimit: u64, pub dqb_isoftlimit: u64, pub dqb_curinodes: u64, pub dqb_btime: u64, pub dqb_itime: u64, pub dqb_valid: u32, } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: u64, pub ssi_utime: u64, pub ssi_stime: u64, pub ssi_addr: u64, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } pub struct fsid_t { __val: [::c_int; 2], } pub struct packet_mreq { pub mr_ifindex: ::c_int, pub mr_type: ::c_ushort, pub mr_alen: ::c_ushort, pub mr_address: [::c_uchar; 8], } pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] bits: [u32; 32], #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] bits: [u64; 16], } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } // System V IPC pub struct msginfo { pub msgpool: ::c_int, pub msgmap: ::c_int, pub msgmax: ::c_int, pub msgmnb: ::c_int, pub msgmni: ::c_int, pub msgssz: ::c_int, pub msgtql: ::c_int, pub msgseg: ::c_ushort, } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct input_event { pub time: ::timeval, pub type_: ::__u16, pub code: ::__u16, pub value: ::__s32, } pub struct input_id { pub bustype: ::__u16, pub vendor: ::__u16, pub product: ::__u16, pub version: ::__u16, } pub struct input_absinfo { pub value: ::__s32, pub minimum: ::__s32, pub maximum: ::__s32, pub fuzz: ::__s32, pub flat: ::__s32, pub resolution: ::__s32, } pub struct input_keymap_entry { pub flags: ::__u8, pub len: ::__u8, pub index: ::__u16, pub keycode: ::__u32, pub scancode: [::__u8; 32], } pub struct input_mask { pub type_: ::__u32, pub codes_size: ::__u32, pub codes_ptr: ::__u64, } pub struct ff_replay { pub length: ::__u16, pub delay: ::__u16, } pub struct ff_trigger { pub button: ::__u16, pub interval: ::__u16, } pub struct ff_envelope { pub attack_length: ::__u16, pub attack_level: ::__u16, pub fade_length: ::__u16, pub fade_level: ::__u16, } pub struct ff_constant_effect { pub level: ::__s16, pub envelope: ff_envelope, } pub struct ff_ramp_effect { pub start_level: ::__s16, pub end_level: ::__s16, pub envelope: ff_envelope, } pub struct ff_condition_effect { pub right_saturation: ::__u16, pub left_saturation: ::__u16, pub right_coeff: ::__s16, pub left_coeff: ::__s16, pub deadband: ::__u16, pub center: ::__s16, } pub struct ff_periodic_effect { pub waveform: ::__u16, pub period: ::__u16, pub magnitude: ::__s16, pub offset: ::__s16, pub phase: ::__u16, pub envelope: ff_envelope, pub custom_len: ::__u32, pub custom_data: *mut ::__s16, } pub struct ff_rumble_effect { pub strong_magnitude: ::__u16, pub weak_magnitude: ::__u16, } pub struct ff_effect { pub type_: ::__u16, pub id: ::__s16, pub direction: ::__u16, pub trigger: ff_trigger, pub replay: ff_replay, // FIXME this is actually a union #[cfg(target_pointer_width = "64")] pub u: [u64; 4], #[cfg(target_pointer_width = "32")] pub u: [u32; 7], } pub struct uinput_ff_upload { pub request_id: ::__u32, pub retval: ::__s32, pub effect: ff_effect, pub old: ff_effect, } pub struct uinput_ff_erase { pub request_id: ::__u32, pub retval: ::__s32, pub effect_id: ::__u32, } pub struct uinput_abs_setup { pub code: ::__u16, pub absinfo: input_absinfo, } pub struct dl_phdr_info { #[cfg(target_pointer_width = "64")] pub dlpi_addr: Elf64_Addr, #[cfg(target_pointer_width = "32")] pub dlpi_addr: Elf32_Addr, pub dlpi_name: *const ::c_char, #[cfg(target_pointer_width = "64")] pub dlpi_phdr: *const Elf64_Phdr, #[cfg(target_pointer_width = "32")] pub dlpi_phdr: *const Elf32_Phdr, #[cfg(target_pointer_width = "64")] pub dlpi_phnum: Elf64_Half, #[cfg(target_pointer_width = "32")] pub dlpi_phnum: Elf32_Half, // As of uClibc 1.0.36, the following fields are // gated behind a "#if 0" block which always evaluates // to false. So I'm just removing these, and if uClibc changes // the #if block in the future to include the following fields, these // will probably need including here. tsidea, skrap #[cfg(not(target_env = "uclibc"))] pub dlpi_adds: ::c_ulonglong, #[cfg(not(target_env = "uclibc"))] pub dlpi_subs: ::c_ulonglong, #[cfg(not(target_env = "uclibc"))] pub dlpi_tls_modid: ::size_t, #[cfg(not(target_env = "uclibc"))] pub dlpi_tls_data: *mut ::c_void, } pub struct Elf32_Ehdr { pub e_ident: [::c_uchar; 16], pub e_type: Elf32_Half, pub e_machine: Elf32_Half, pub e_version: Elf32_Word, pub e_entry: Elf32_Addr, pub e_phoff: Elf32_Off, pub e_shoff: Elf32_Off, pub e_flags: Elf32_Word, pub e_ehsize: Elf32_Half, pub e_phentsize: Elf32_Half, pub e_phnum: Elf32_Half, pub e_shentsize: Elf32_Half, pub e_shnum: Elf32_Half, pub e_shstrndx: Elf32_Half, } pub struct Elf64_Ehdr { pub e_ident: [::c_uchar; 16], pub e_type: Elf64_Half, pub e_machine: Elf64_Half, pub e_version: Elf64_Word, pub e_entry: Elf64_Addr, pub e_phoff: Elf64_Off, pub e_shoff: Elf64_Off, pub e_flags: Elf64_Word, pub e_ehsize: Elf64_Half, pub e_phentsize: Elf64_Half, pub e_phnum: Elf64_Half, pub e_shentsize: Elf64_Half, pub e_shnum: Elf64_Half, pub e_shstrndx: Elf64_Half, } pub struct Elf32_Sym { pub st_name: Elf32_Word, pub st_value: Elf32_Addr, pub st_size: Elf32_Word, pub st_info: ::c_uchar, pub st_other: ::c_uchar, pub st_shndx: Elf32_Section, } pub struct Elf64_Sym { pub st_name: Elf64_Word, pub st_info: ::c_uchar, pub st_other: ::c_uchar, pub st_shndx: Elf64_Section, pub st_value: Elf64_Addr, pub st_size: Elf64_Xword, } pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct Elf32_Shdr { pub sh_name: Elf32_Word, pub sh_type: Elf32_Word, pub sh_flags: Elf32_Word, pub sh_addr: Elf32_Addr, pub sh_offset: Elf32_Off, pub sh_size: Elf32_Word, pub sh_link: Elf32_Word, pub sh_info: Elf32_Word, pub sh_addralign: Elf32_Word, pub sh_entsize: Elf32_Word, } pub struct Elf64_Shdr { pub sh_name: Elf64_Word, pub sh_type: Elf64_Word, pub sh_flags: Elf64_Xword, pub sh_addr: Elf64_Addr, pub sh_offset: Elf64_Off, pub sh_size: Elf64_Xword, pub sh_link: Elf64_Word, pub sh_info: Elf64_Word, pub sh_addralign: Elf64_Xword, pub sh_entsize: Elf64_Xword, } pub struct ucred { pub pid: ::pid_t, pub uid: ::uid_t, pub gid: ::gid_t, } pub struct mntent { pub mnt_fsname: *mut ::c_char, pub mnt_dir: *mut ::c_char, pub mnt_type: *mut ::c_char, pub mnt_opts: *mut ::c_char, pub mnt_freq: ::c_int, pub mnt_passno: ::c_int, } pub struct posix_spawn_file_actions_t { __allocated: ::c_int, __used: ::c_int, __actions: *mut ::c_int, __pad: [::c_int; 16], } pub struct posix_spawnattr_t { __flags: ::c_short, __pgrp: ::pid_t, __sd: ::sigset_t, __ss: ::sigset_t, #[cfg(any(target_env = "musl", target_env = "ohos"))] __prio: ::c_int, #[cfg(not(any(target_env = "musl", target_env = "ohos")))] __sp: ::sched_param, __policy: ::c_int, __pad: [::c_int; 16], } pub struct genlmsghdr { pub cmd: u8, pub version: u8, pub reserved: u16, } pub struct in6_pktinfo { pub ipi6_addr: ::in6_addr, pub ipi6_ifindex: ::c_uint, } pub struct arpd_request { pub req: ::c_ushort, pub ip: u32, pub dev: ::c_ulong, pub stamp: ::c_ulong, pub updated: ::c_ulong, pub ha: [::c_uchar; ::MAX_ADDR_LEN], } pub struct inotify_event { pub wd: ::c_int, pub mask: u32, pub cookie: u32, pub len: u32 } pub struct fanotify_response { pub fd: ::c_int, pub response: __u32, } pub struct sockaddr_vm { pub svm_family: ::sa_family_t, pub svm_reserved1: ::c_ushort, pub svm_port: ::c_uint, pub svm_cid: ::c_uint, pub svm_zero: [u8; 4] } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct sock_extended_err { pub ee_errno: u32, pub ee_origin: u8, pub ee_type: u8, pub ee_code: u8, pub ee_pad: u8, pub ee_info: u32, pub ee_data: u32, } // linux/can.h pub struct __c_anonymous_sockaddr_can_tp { pub rx_id: canid_t, pub tx_id: canid_t, } pub struct __c_anonymous_sockaddr_can_j1939 { pub name: u64, pub pgn: u32, pub addr: u8, } pub struct can_filter { pub can_id: canid_t, pub can_mask: canid_t, } // linux/can/j1939.h pub struct j1939_filter { pub name: name_t, pub name_mask: name_t, pub pgn: pgn_t, pub pgn_mask: pgn_t, pub addr: u8, pub addr_mask: u8, } // linux/filter.h pub struct sock_filter { pub code: ::__u16, pub jt: ::__u8, pub jf: ::__u8, pub k: ::__u32, } pub struct sock_fprog { pub len: ::c_ushort, pub filter: *mut sock_filter, } // linux/seccomp.h pub struct seccomp_data { pub nr: ::c_int, pub arch: ::__u32, pub instruction_pointer: ::__u64, pub args: [::__u64; 6], } pub struct seccomp_notif_sizes { pub seccomp_notif: ::__u16, pub seccomp_notif_resp: ::__u16, pub seccomp_data: ::__u16, } pub struct seccomp_notif { pub id: ::__u64, pub pid: ::__u32, pub flags: ::__u32, pub data: seccomp_data, } pub struct seccomp_notif_resp { pub id: ::__u64, pub val: ::__s64, pub error: ::__s32, pub flags: ::__u32, } pub struct seccomp_notif_addfd { pub id: ::__u64, pub flags: ::__u32, pub srcfd: ::__u32, pub newfd: ::__u32, pub newfd_flags: ::__u32, } pub struct nlmsghdr { pub nlmsg_len: u32, pub nlmsg_type: u16, pub nlmsg_flags: u16, pub nlmsg_seq: u32, pub nlmsg_pid: u32, } pub struct nlmsgerr { pub error: ::c_int, pub msg: nlmsghdr, } pub struct nlattr { pub nla_len: u16, pub nla_type: u16, } pub struct file_clone_range { pub src_fd: ::__s64, pub src_offset: ::__u64, pub src_length: ::__u64, pub dest_offset: ::__u64, } pub struct __c_anonymous_ifru_map { pub mem_start: ::c_ulong, pub mem_end: ::c_ulong, pub base_addr: ::c_ushort, pub irq: ::c_uchar, pub dma: ::c_uchar, pub port: ::c_uchar, } pub struct in6_ifreq { pub ifr6_addr: ::in6_addr, pub ifr6_prefixlen: u32, pub ifr6_ifindex: ::c_int, } pub struct option { pub name: *const ::c_char, pub has_arg: ::c_int, pub flag: *mut ::c_int, pub val: ::c_int, } // linux/sctp.h pub struct sctp_initmsg { pub sinit_num_ostreams: ::__u16, pub sinit_max_instreams: ::__u16, pub sinit_max_attempts: ::__u16, pub sinit_max_init_timeo: ::__u16, } pub struct sctp_sndrcvinfo { pub sinfo_stream: ::__u16, pub sinfo_ssn: ::__u16, pub sinfo_flags: ::__u16, pub sinfo_ppid: ::__u32, pub sinfo_context: ::__u32, pub sinfo_timetolive: ::__u32, pub sinfo_tsn: ::__u32, pub sinfo_cumtsn: ::__u32, pub sinfo_assoc_id: ::sctp_assoc_t, } pub struct sctp_sndinfo { pub snd_sid: ::__u16, pub snd_flags: ::__u16, pub snd_ppid: ::__u32, pub snd_context: ::__u32, pub snd_assoc_id: ::sctp_assoc_t, } pub struct sctp_rcvinfo { pub rcv_sid: ::__u16, pub rcv_ssn: ::__u16, pub rcv_flags: ::__u16, pub rcv_ppid: ::__u32, pub rcv_tsn: ::__u32, pub rcv_cumtsn: ::__u32, pub rcv_context: ::__u32, pub rcv_assoc_id: ::sctp_assoc_t, } pub struct sctp_nxtinfo { pub nxt_sid: ::__u16, pub nxt_flags: ::__u16, pub nxt_ppid: ::__u32, pub nxt_length: ::__u32, pub nxt_assoc_id: ::sctp_assoc_t, } pub struct sctp_prinfo { pub pr_policy: ::__u16, pub pr_value: ::__u32, } pub struct sctp_authinfo { pub auth_keynumber: ::__u16, } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } // linux/tls.h pub struct tls_crypto_info { pub version: ::__u16, pub cipher_type: ::__u16, } pub struct tls12_crypto_info_aes_gcm_128 { pub info: tls_crypto_info, pub iv: [::c_uchar; TLS_CIPHER_AES_GCM_128_IV_SIZE], pub key: [::c_uchar; TLS_CIPHER_AES_GCM_128_KEY_SIZE], pub salt: [::c_uchar; TLS_CIPHER_AES_GCM_128_SALT_SIZE], pub rec_seq: [::c_uchar; TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE], } pub struct tls12_crypto_info_aes_gcm_256 { pub info: tls_crypto_info, pub iv: [::c_uchar; TLS_CIPHER_AES_GCM_256_IV_SIZE], pub key: [::c_uchar; TLS_CIPHER_AES_GCM_256_KEY_SIZE], pub salt: [::c_uchar; TLS_CIPHER_AES_GCM_256_SALT_SIZE], pub rec_seq: [::c_uchar; TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE], } pub struct tls12_crypto_info_chacha20_poly1305 { pub info: tls_crypto_info, pub iv: [::c_uchar; TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE], pub key: [::c_uchar; TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE], pub salt: [::c_uchar; TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE], pub rec_seq: [::c_uchar; TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE], } } s_no_extra_traits! { pub struct sockaddr_nl { pub nl_family: ::sa_family_t, nl_pad: ::c_ushort, pub nl_pid: u32, pub nl_groups: u32 } pub struct dirent { pub d_ino: ::ino_t, pub d_off: ::off_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } pub struct sockaddr_alg { pub salg_family: ::sa_family_t, pub salg_type: [::c_uchar; 14], pub salg_feat: u32, pub salg_mask: u32, pub salg_name: [::c_uchar; 64], } pub struct uinput_setup { pub id: input_id, pub name: [::c_char; UINPUT_MAX_NAME_SIZE], pub ff_effects_max: ::__u32, } pub struct uinput_user_dev { pub name: [::c_char; UINPUT_MAX_NAME_SIZE], pub id: input_id, pub ff_effects_max: ::__u32, pub absmax: [::__s32; ABS_CNT], pub absmin: [::__s32; ABS_CNT], pub absfuzz: [::__s32; ABS_CNT], pub absflat: [::__s32; ABS_CNT], } /// WARNING: The `PartialEq`, `Eq` and `Hash` implementations of this /// type are unsound and will be removed in the future. #[deprecated( note = "this struct has unsafe trait implementations that will be \ removed in the future", since = "0.2.80" )] pub struct af_alg_iv { pub ivlen: u32, pub iv: [::c_uchar; 0], } // x32 compatibility // See https://sourceware.org/bugzilla/show_bug.cgi?id=21279 pub struct mq_attr { #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_flags: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_maxmsg: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_msgsize: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub mq_curmsgs: i64, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pad: [i64; 4], #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_flags: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_maxmsg: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_msgsize: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub mq_curmsgs: ::c_long, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pad: [::c_long; 4], } #[cfg(libc_union)] pub union __c_anonymous_ifr_ifru { pub ifru_addr: ::sockaddr, pub ifru_dstaddr: ::sockaddr, pub ifru_broadaddr: ::sockaddr, pub ifru_netmask: ::sockaddr, pub ifru_hwaddr: ::sockaddr, pub ifru_flags: ::c_short, pub ifru_ifindex: ::c_int, pub ifru_metric: ::c_int, pub ifru_mtu: ::c_int, pub ifru_map: __c_anonymous_ifru_map, pub ifru_slave: [::c_char; ::IFNAMSIZ], pub ifru_newname: [::c_char; ::IFNAMSIZ], pub ifru_data: *mut ::c_char, } pub struct ifreq { /// interface name, e.g. "en0" pub ifr_name: [::c_char; ::IFNAMSIZ], #[cfg(libc_union)] pub ifr_ifru: __c_anonymous_ifr_ifru, #[cfg(not(libc_union))] pub ifr_ifru: ::sockaddr, } #[cfg(libc_union)] pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut ::c_char, pub ifcu_req: *mut ::ifreq, } /* Structure used in SIOCGIFCONF request. Used to retrieve interface configuration for machine (useful for programs which must know all networks accessible). */ pub struct ifconf { pub ifc_len: ::c_int, /* Size of buffer. */ #[cfg(libc_union)] pub ifc_ifcu: __c_anonymous_ifc_ifcu, #[cfg(not(libc_union))] pub ifc_ifcu: *mut ::ifreq, } pub struct hwtstamp_config { pub flags: ::c_int, pub tx_type: ::c_int, pub rx_filter: ::c_int, } pub struct dirent64 { pub d_ino: ::ino64_t, pub d_off: ::off64_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } pub struct sched_attr { pub size: ::__u32, pub sched_policy: ::__u32, pub sched_flags: ::__u64, pub sched_nice: ::__s32, pub sched_priority: ::__u32, pub sched_runtime: ::__u64, pub sched_deadline: ::__u64, pub sched_period: ::__u64, } } s_no_extra_traits! { // linux/net_tstamp.h #[allow(missing_debug_implementations)] pub struct sock_txtime { pub clockid: ::clockid_t, pub flags: ::__u32, } } cfg_if! { if #[cfg(libc_union)] { s_no_extra_traits! { // linux/can.h #[allow(missing_debug_implementations)] pub union __c_anonymous_sockaddr_can_can_addr { pub tp: __c_anonymous_sockaddr_can_tp, pub j1939: __c_anonymous_sockaddr_can_j1939, } #[allow(missing_debug_implementations)] pub struct sockaddr_can { pub can_family: ::sa_family_t, pub can_ifindex: ::c_int, pub can_addr: __c_anonymous_sockaddr_can_can_addr, } } } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_nl { fn eq(&self, other: &sockaddr_nl) -> bool { self.nl_family == other.nl_family && self.nl_pid == other.nl_pid && self.nl_groups == other.nl_groups } } impl Eq for sockaddr_nl {} impl ::fmt::Debug for sockaddr_nl { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_nl") .field("nl_family", &self.nl_family) .field("nl_pid", &self.nl_pid) .field("nl_groups", &self.nl_groups) .finish() } } impl ::hash::Hash for sockaddr_nl { fn hash(&self, state: &mut H) { self.nl_family.hash(state); self.nl_pid.hash(state); self.nl_groups.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for dirent64 { fn eq(&self, other: &dirent64) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent64 {} impl ::fmt::Debug for dirent64 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent64") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent64 { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a,b)| a == b) } } impl Eq for pthread_cond_t {} impl ::fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_cond_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a,b)| a == b) } } impl Eq for pthread_mutex_t {} impl ::fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_mutex_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a,b)| a == b) } } impl Eq for pthread_rwlock_t {} impl ::fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_rwlock_t") // FIXME: .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for pthread_barrier_t { fn eq(&self, other: &pthread_barrier_t) -> bool { self.size.iter().zip(other.size.iter()).all(|(a,b)| a == b) } } impl Eq for pthread_barrier_t {} impl ::fmt::Debug for pthread_barrier_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_barrier_t") .field("size", &self.size) .finish() } } impl ::hash::Hash for pthread_barrier_t { fn hash(&self, state: &mut H) { self.size.hash(state); } } impl PartialEq for sockaddr_alg { fn eq(&self, other: &sockaddr_alg) -> bool { self.salg_family == other.salg_family && self .salg_type .iter() .zip(other.salg_type.iter()) .all(|(a, b)| a == b) && self.salg_feat == other.salg_feat && self.salg_mask == other.salg_mask && self .salg_name .iter() .zip(other.salg_name.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_alg {} impl ::fmt::Debug for sockaddr_alg { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_alg") .field("salg_family", &self.salg_family) .field("salg_type", &self.salg_type) .field("salg_feat", &self.salg_feat) .field("salg_mask", &self.salg_mask) .field("salg_name", &&self.salg_name[..]) .finish() } } impl ::hash::Hash for sockaddr_alg { fn hash(&self, state: &mut H) { self.salg_family.hash(state); self.salg_type.hash(state); self.salg_feat.hash(state); self.salg_mask.hash(state); self.salg_name.hash(state); } } impl PartialEq for uinput_setup { fn eq(&self, other: &uinput_setup) -> bool { self.id == other.id && self.name[..] == other.name[..] && self.ff_effects_max == other.ff_effects_max } } impl Eq for uinput_setup {} impl ::fmt::Debug for uinput_setup { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uinput_setup") .field("id", &self.id) .field("name", &&self.name[..]) .field("ff_effects_max", &self.ff_effects_max) .finish() } } impl ::hash::Hash for uinput_setup { fn hash(&self, state: &mut H) { self.id.hash(state); self.name.hash(state); self.ff_effects_max.hash(state); } } impl PartialEq for uinput_user_dev { fn eq(&self, other: &uinput_user_dev) -> bool { self.name[..] == other.name[..] && self.id == other.id && self.ff_effects_max == other.ff_effects_max && self.absmax[..] == other.absmax[..] && self.absmin[..] == other.absmin[..] && self.absfuzz[..] == other.absfuzz[..] && self.absflat[..] == other.absflat[..] } } impl Eq for uinput_user_dev {} impl ::fmt::Debug for uinput_user_dev { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uinput_setup") .field("name", &&self.name[..]) .field("id", &self.id) .field("ff_effects_max", &self.ff_effects_max) .field("absmax", &&self.absmax[..]) .field("absmin", &&self.absmin[..]) .field("absfuzz", &&self.absfuzz[..]) .field("absflat", &&self.absflat[..]) .finish() } } impl ::hash::Hash for uinput_user_dev { fn hash(&self, state: &mut H) { self.name.hash(state); self.id.hash(state); self.ff_effects_max.hash(state); self.absmax.hash(state); self.absmin.hash(state); self.absfuzz.hash(state); self.absflat.hash(state); } } #[allow(deprecated)] impl af_alg_iv { fn as_slice(&self) -> &[u8] { unsafe { ::core::slice::from_raw_parts( self.iv.as_ptr(), self.ivlen as usize ) } } } #[allow(deprecated)] impl PartialEq for af_alg_iv { fn eq(&self, other: &af_alg_iv) -> bool { *self.as_slice() == *other.as_slice() } } #[allow(deprecated)] impl Eq for af_alg_iv {} #[allow(deprecated)] impl ::fmt::Debug for af_alg_iv { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("af_alg_iv") .field("ivlen", &self.ivlen) .finish() } } #[allow(deprecated)] impl ::hash::Hash for af_alg_iv { fn hash(&self, state: &mut H) { self.as_slice().hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl ::fmt::Debug for mq_attr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl ::hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifr_ifru { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifr_ifru") .field("ifru_addr", unsafe { &self.ifru_addr }) .field("ifru_dstaddr", unsafe { &self.ifru_dstaddr }) .field("ifru_broadaddr", unsafe { &self.ifru_broadaddr }) .field("ifru_netmask", unsafe { &self.ifru_netmask }) .field("ifru_hwaddr", unsafe { &self.ifru_hwaddr }) .field("ifru_flags", unsafe { &self.ifru_flags }) .field("ifru_ifindex", unsafe { &self.ifru_ifindex }) .field("ifru_metric", unsafe { &self.ifru_metric }) .field("ifru_mtu", unsafe { &self.ifru_mtu }) .field("ifru_map", unsafe { &self.ifru_map }) .field("ifru_slave", unsafe { &self.ifru_slave }) .field("ifru_newname", unsafe { &self.ifru_newname }) .field("ifru_data", unsafe { &self.ifru_data }) .finish() } } impl ::fmt::Debug for ifreq { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifc_ifcu { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifr_ifru") .field("ifcu_buf", unsafe { &self.ifcu_buf }) .field("ifcu_req", unsafe { &self.ifcu_req }) .finish() } } impl ::fmt::Debug for ifconf { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifconf") .field("ifc_len", &self.ifc_len) .field("ifc_ifcu", &self.ifc_ifcu) .finish() } } impl ::fmt::Debug for hwtstamp_config { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("hwtstamp_config") .field("flags", &self.flags) .field("tx_type", &self.tx_type) .field("rx_filter", &self.rx_filter) .finish() } } impl PartialEq for hwtstamp_config { fn eq(&self, other: &hwtstamp_config) -> bool { self.flags == other.flags && self.tx_type == other.tx_type && self.rx_filter == other.rx_filter } } impl Eq for hwtstamp_config {} impl ::hash::Hash for hwtstamp_config { fn hash(&self, state: &mut H) { self.flags.hash(state); self.tx_type.hash(state); self.rx_filter.hash(state); } } impl ::fmt::Debug for sched_attr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sched_attr") .field("size", &self.size) .field("sched_policy", &self.sched_policy) .field("sched_flags", &self.sched_flags) .field("sched_nice", &self.sched_nice) .field("sched_priority", &self.sched_priority) .field("sched_runtime", &self.sched_runtime) .field("sched_deadline", &self.sched_deadline) .field("sched_period", &self.sched_period) .finish() } } impl PartialEq for sched_attr { fn eq(&self, other: &sched_attr) -> bool { self.size == other.size && self.sched_policy == other.sched_policy && self.sched_flags == other.sched_flags && self.sched_nice == other.sched_nice && self.sched_priority == other.sched_priority && self.sched_runtime == other.sched_runtime && self.sched_deadline == other.sched_deadline && self.sched_period == other.sched_period } } impl Eq for sched_attr {} impl ::hash::Hash for sched_attr { fn hash(&self, state: &mut H) { self.size.hash(state); self.sched_policy.hash(state); self.sched_flags.hash(state); self.sched_nice.hash(state); self.sched_priority.hash(state); self.sched_runtime.hash(state); self.sched_deadline.hash(state); self.sched_period.hash(state); } } } } cfg_if! { if #[cfg(any(target_env = "gnu", target_env = "musl", target_env = "ohos"))] { pub const ABDAY_1: ::nl_item = 0x20000; pub const ABDAY_2: ::nl_item = 0x20001; pub const ABDAY_3: ::nl_item = 0x20002; pub const ABDAY_4: ::nl_item = 0x20003; pub const ABDAY_5: ::nl_item = 0x20004; pub const ABDAY_6: ::nl_item = 0x20005; pub const ABDAY_7: ::nl_item = 0x20006; pub const DAY_1: ::nl_item = 0x20007; pub const DAY_2: ::nl_item = 0x20008; pub const DAY_3: ::nl_item = 0x20009; pub const DAY_4: ::nl_item = 0x2000A; pub const DAY_5: ::nl_item = 0x2000B; pub const DAY_6: ::nl_item = 0x2000C; pub const DAY_7: ::nl_item = 0x2000D; pub const ABMON_1: ::nl_item = 0x2000E; pub const ABMON_2: ::nl_item = 0x2000F; pub const ABMON_3: ::nl_item = 0x20010; pub const ABMON_4: ::nl_item = 0x20011; pub const ABMON_5: ::nl_item = 0x20012; pub const ABMON_6: ::nl_item = 0x20013; pub const ABMON_7: ::nl_item = 0x20014; pub const ABMON_8: ::nl_item = 0x20015; pub const ABMON_9: ::nl_item = 0x20016; pub const ABMON_10: ::nl_item = 0x20017; pub const ABMON_11: ::nl_item = 0x20018; pub const ABMON_12: ::nl_item = 0x20019; pub const MON_1: ::nl_item = 0x2001A; pub const MON_2: ::nl_item = 0x2001B; pub const MON_3: ::nl_item = 0x2001C; pub const MON_4: ::nl_item = 0x2001D; pub const MON_5: ::nl_item = 0x2001E; pub const MON_6: ::nl_item = 0x2001F; pub const MON_7: ::nl_item = 0x20020; pub const MON_8: ::nl_item = 0x20021; pub const MON_9: ::nl_item = 0x20022; pub const MON_10: ::nl_item = 0x20023; pub const MON_11: ::nl_item = 0x20024; pub const MON_12: ::nl_item = 0x20025; pub const AM_STR: ::nl_item = 0x20026; pub const PM_STR: ::nl_item = 0x20027; pub const D_T_FMT: ::nl_item = 0x20028; pub const D_FMT: ::nl_item = 0x20029; pub const T_FMT: ::nl_item = 0x2002A; pub const T_FMT_AMPM: ::nl_item = 0x2002B; pub const ERA: ::nl_item = 0x2002C; pub const ERA_D_FMT: ::nl_item = 0x2002E; pub const ALT_DIGITS: ::nl_item = 0x2002F; pub const ERA_D_T_FMT: ::nl_item = 0x20030; pub const ERA_T_FMT: ::nl_item = 0x20031; pub const CODESET: ::nl_item = 14; pub const CRNCYSTR: ::nl_item = 0x4000F; pub const RADIXCHAR: ::nl_item = 0x10000; pub const THOUSEP: ::nl_item = 0x10001; pub const YESEXPR: ::nl_item = 0x50000; pub const NOEXPR: ::nl_item = 0x50001; pub const YESSTR: ::nl_item = 0x50002; pub const NOSTR: ::nl_item = 0x50003; } } pub const RUSAGE_CHILDREN: ::c_int = -1; pub const L_tmpnam: ::c_uint = 20; pub const _PC_LINK_MAX: ::c_int = 0; pub const _PC_MAX_CANON: ::c_int = 1; pub const _PC_MAX_INPUT: ::c_int = 2; pub const _PC_NAME_MAX: ::c_int = 3; pub const _PC_PATH_MAX: ::c_int = 4; pub const _PC_PIPE_BUF: ::c_int = 5; pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_SYNC_IO: ::c_int = 9; pub const _PC_ASYNC_IO: ::c_int = 10; pub const _PC_PRIO_IO: ::c_int = 11; pub const _PC_SOCK_MAXBUF: ::c_int = 12; pub const _PC_FILESIZEBITS: ::c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; pub const _PC_REC_XFER_ALIGN: ::c_int = 17; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18; pub const _PC_SYMLINK_MAX: ::c_int = 19; pub const _PC_2_SYMLINKS: ::c_int = 20; pub const MS_NOUSER: ::c_ulong = 0xffffffff80000000; pub const _SC_ARG_MAX: ::c_int = 0; pub const _SC_CHILD_MAX: ::c_int = 1; pub const _SC_CLK_TCK: ::c_int = 2; pub const _SC_NGROUPS_MAX: ::c_int = 3; pub const _SC_OPEN_MAX: ::c_int = 4; pub const _SC_STREAM_MAX: ::c_int = 5; pub const _SC_TZNAME_MAX: ::c_int = 6; pub const _SC_JOB_CONTROL: ::c_int = 7; pub const _SC_SAVED_IDS: ::c_int = 8; pub const _SC_REALTIME_SIGNALS: ::c_int = 9; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 10; pub const _SC_TIMERS: ::c_int = 11; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 12; pub const _SC_PRIORITIZED_IO: ::c_int = 13; pub const _SC_SYNCHRONIZED_IO: ::c_int = 14; pub const _SC_FSYNC: ::c_int = 15; pub const _SC_MAPPED_FILES: ::c_int = 16; pub const _SC_MEMLOCK: ::c_int = 17; pub const _SC_MEMLOCK_RANGE: ::c_int = 18; pub const _SC_MEMORY_PROTECTION: ::c_int = 19; pub const _SC_MESSAGE_PASSING: ::c_int = 20; pub const _SC_SEMAPHORES: ::c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 22; pub const _SC_AIO_LISTIO_MAX: ::c_int = 23; pub const _SC_AIO_MAX: ::c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 25; pub const _SC_DELAYTIMER_MAX: ::c_int = 26; pub const _SC_MQ_OPEN_MAX: ::c_int = 27; pub const _SC_MQ_PRIO_MAX: ::c_int = 28; pub const _SC_VERSION: ::c_int = 29; pub const _SC_PAGESIZE: ::c_int = 30; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: ::c_int = 31; pub const _SC_SEM_NSEMS_MAX: ::c_int = 32; pub const _SC_SEM_VALUE_MAX: ::c_int = 33; pub const _SC_SIGQUEUE_MAX: ::c_int = 34; pub const _SC_TIMER_MAX: ::c_int = 35; pub const _SC_BC_BASE_MAX: ::c_int = 36; pub const _SC_BC_DIM_MAX: ::c_int = 37; pub const _SC_BC_SCALE_MAX: ::c_int = 38; pub const _SC_BC_STRING_MAX: ::c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 40; pub const _SC_EXPR_NEST_MAX: ::c_int = 42; pub const _SC_LINE_MAX: ::c_int = 43; pub const _SC_RE_DUP_MAX: ::c_int = 44; pub const _SC_2_VERSION: ::c_int = 46; pub const _SC_2_C_BIND: ::c_int = 47; pub const _SC_2_C_DEV: ::c_int = 48; pub const _SC_2_FORT_DEV: ::c_int = 49; pub const _SC_2_FORT_RUN: ::c_int = 50; pub const _SC_2_SW_DEV: ::c_int = 51; pub const _SC_2_LOCALEDEF: ::c_int = 52; pub const _SC_UIO_MAXIOV: ::c_int = 60; pub const _SC_IOV_MAX: ::c_int = 60; pub const _SC_THREADS: ::c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 70; pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; pub const _SC_TTY_NAME_MAX: ::c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 73; pub const _SC_THREAD_KEYS_MAX: ::c_int = 74; pub const _SC_THREAD_STACK_MIN: ::c_int = 75; pub const _SC_THREAD_THREADS_MAX: ::c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 82; pub const _SC_NPROCESSORS_CONF: ::c_int = 83; pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; pub const _SC_PHYS_PAGES: ::c_int = 85; pub const _SC_AVPHYS_PAGES: ::c_int = 86; pub const _SC_ATEXIT_MAX: ::c_int = 87; pub const _SC_PASS_MAX: ::c_int = 88; pub const _SC_XOPEN_VERSION: ::c_int = 89; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90; pub const _SC_XOPEN_UNIX: ::c_int = 91; pub const _SC_XOPEN_CRYPT: ::c_int = 92; pub const _SC_XOPEN_ENH_I18N: ::c_int = 93; pub const _SC_XOPEN_SHM: ::c_int = 94; pub const _SC_2_CHAR_TERM: ::c_int = 95; pub const _SC_2_UPE: ::c_int = 97; pub const _SC_XOPEN_XPG2: ::c_int = 98; pub const _SC_XOPEN_XPG3: ::c_int = 99; pub const _SC_XOPEN_XPG4: ::c_int = 100; pub const _SC_NZERO: ::c_int = 109; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126; pub const _SC_XBS5_LP64_OFF64: ::c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128; pub const _SC_XOPEN_LEGACY: ::c_int = 129; pub const _SC_XOPEN_REALTIME: ::c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131; pub const _SC_ADVISORY_INFO: ::c_int = 132; pub const _SC_BARRIERS: ::c_int = 133; pub const _SC_CLOCK_SELECTION: ::c_int = 137; pub const _SC_CPUTIME: ::c_int = 138; pub const _SC_THREAD_CPUTIME: ::c_int = 139; pub const _SC_MONOTONIC_CLOCK: ::c_int = 149; pub const _SC_READER_WRITER_LOCKS: ::c_int = 153; pub const _SC_SPIN_LOCKS: ::c_int = 154; pub const _SC_REGEXP: ::c_int = 155; pub const _SC_SHELL: ::c_int = 157; pub const _SC_SPAWN: ::c_int = 159; pub const _SC_SPORADIC_SERVER: ::c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 161; pub const _SC_TIMEOUTS: ::c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 165; pub const _SC_2_PBS: ::c_int = 168; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 169; pub const _SC_2_PBS_LOCATE: ::c_int = 170; pub const _SC_2_PBS_MESSAGE: ::c_int = 171; pub const _SC_2_PBS_TRACK: ::c_int = 172; pub const _SC_SYMLOOP_MAX: ::c_int = 173; pub const _SC_STREAMS: ::c_int = 174; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 175; pub const _SC_V6_ILP32_OFF32: ::c_int = 176; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 177; pub const _SC_V6_LP64_OFF64: ::c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 179; pub const _SC_HOST_NAME_MAX: ::c_int = 180; pub const _SC_TRACE: ::c_int = 181; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 182; pub const _SC_TRACE_INHERIT: ::c_int = 183; pub const _SC_TRACE_LOG: ::c_int = 184; pub const _SC_IPV6: ::c_int = 235; pub const _SC_RAW_SOCKETS: ::c_int = 236; pub const _SC_V7_ILP32_OFF32: ::c_int = 237; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 238; pub const _SC_V7_LP64_OFF64: ::c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 240; pub const _SC_SS_REPL_MAX: ::c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 242; pub const _SC_TRACE_NAME_MAX: ::c_int = 243; pub const _SC_TRACE_SYS_MAX: ::c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 245; pub const _SC_XOPEN_STREAMS: ::c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248; pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; // elf.h - Fields in the e_ident array. pub const EI_NIDENT: usize = 16; pub const EI_MAG0: usize = 0; pub const ELFMAG0: u8 = 0x7f; pub const EI_MAG1: usize = 1; pub const ELFMAG1: u8 = b'E'; pub const EI_MAG2: usize = 2; pub const ELFMAG2: u8 = b'L'; pub const EI_MAG3: usize = 3; pub const ELFMAG3: u8 = b'F'; pub const SELFMAG: usize = 4; pub const EI_CLASS: usize = 4; pub const ELFCLASSNONE: u8 = 0; pub const ELFCLASS32: u8 = 1; pub const ELFCLASS64: u8 = 2; pub const ELFCLASSNUM: usize = 3; pub const EI_DATA: usize = 5; pub const ELFDATANONE: u8 = 0; pub const ELFDATA2LSB: u8 = 1; pub const ELFDATA2MSB: u8 = 2; pub const ELFDATANUM: usize = 3; pub const EI_VERSION: usize = 6; pub const EI_OSABI: usize = 7; pub const ELFOSABI_NONE: u8 = 0; pub const ELFOSABI_SYSV: u8 = 0; pub const ELFOSABI_HPUX: u8 = 1; pub const ELFOSABI_NETBSD: u8 = 2; pub const ELFOSABI_GNU: u8 = 3; pub const ELFOSABI_LINUX: u8 = ELFOSABI_GNU; pub const ELFOSABI_SOLARIS: u8 = 6; pub const ELFOSABI_AIX: u8 = 7; pub const ELFOSABI_IRIX: u8 = 8; pub const ELFOSABI_FREEBSD: u8 = 9; pub const ELFOSABI_TRU64: u8 = 10; pub const ELFOSABI_MODESTO: u8 = 11; pub const ELFOSABI_OPENBSD: u8 = 12; pub const ELFOSABI_ARM: u8 = 97; pub const ELFOSABI_STANDALONE: u8 = 255; pub const EI_ABIVERSION: usize = 8; pub const EI_PAD: usize = 9; // elf.h - Legal values for e_type (object file type). pub const ET_NONE: u16 = 0; pub const ET_REL: u16 = 1; pub const ET_EXEC: u16 = 2; pub const ET_DYN: u16 = 3; pub const ET_CORE: u16 = 4; pub const ET_NUM: u16 = 5; pub const ET_LOOS: u16 = 0xfe00; pub const ET_HIOS: u16 = 0xfeff; pub const ET_LOPROC: u16 = 0xff00; pub const ET_HIPROC: u16 = 0xffff; // elf.h - Legal values for e_machine (architecture). pub const EM_NONE: u16 = 0; pub const EM_M32: u16 = 1; pub const EM_SPARC: u16 = 2; pub const EM_386: u16 = 3; pub const EM_68K: u16 = 4; pub const EM_88K: u16 = 5; pub const EM_860: u16 = 7; pub const EM_MIPS: u16 = 8; pub const EM_S370: u16 = 9; pub const EM_MIPS_RS3_LE: u16 = 10; pub const EM_PARISC: u16 = 15; pub const EM_VPP500: u16 = 17; pub const EM_SPARC32PLUS: u16 = 18; pub const EM_960: u16 = 19; pub const EM_PPC: u16 = 20; pub const EM_PPC64: u16 = 21; pub const EM_S390: u16 = 22; pub const EM_V800: u16 = 36; pub const EM_FR20: u16 = 37; pub const EM_RH32: u16 = 38; pub const EM_RCE: u16 = 39; pub const EM_ARM: u16 = 40; pub const EM_FAKE_ALPHA: u16 = 41; pub const EM_SH: u16 = 42; pub const EM_SPARCV9: u16 = 43; pub const EM_TRICORE: u16 = 44; pub const EM_ARC: u16 = 45; pub const EM_H8_300: u16 = 46; pub const EM_H8_300H: u16 = 47; pub const EM_H8S: u16 = 48; pub const EM_H8_500: u16 = 49; pub const EM_IA_64: u16 = 50; pub const EM_MIPS_X: u16 = 51; pub const EM_COLDFIRE: u16 = 52; pub const EM_68HC12: u16 = 53; pub const EM_MMA: u16 = 54; pub const EM_PCP: u16 = 55; pub const EM_NCPU: u16 = 56; pub const EM_NDR1: u16 = 57; pub const EM_STARCORE: u16 = 58; pub const EM_ME16: u16 = 59; pub const EM_ST100: u16 = 60; pub const EM_TINYJ: u16 = 61; pub const EM_X86_64: u16 = 62; pub const EM_PDSP: u16 = 63; pub const EM_FX66: u16 = 66; pub const EM_ST9PLUS: u16 = 67; pub const EM_ST7: u16 = 68; pub const EM_68HC16: u16 = 69; pub const EM_68HC11: u16 = 70; pub const EM_68HC08: u16 = 71; pub const EM_68HC05: u16 = 72; pub const EM_SVX: u16 = 73; pub const EM_ST19: u16 = 74; pub const EM_VAX: u16 = 75; pub const EM_CRIS: u16 = 76; pub const EM_JAVELIN: u16 = 77; pub const EM_FIREPATH: u16 = 78; pub const EM_ZSP: u16 = 79; pub const EM_MMIX: u16 = 80; pub const EM_HUANY: u16 = 81; pub const EM_PRISM: u16 = 82; pub const EM_AVR: u16 = 83; pub const EM_FR30: u16 = 84; pub const EM_D10V: u16 = 85; pub const EM_D30V: u16 = 86; pub const EM_V850: u16 = 87; pub const EM_M32R: u16 = 88; pub const EM_MN10300: u16 = 89; pub const EM_MN10200: u16 = 90; pub const EM_PJ: u16 = 91; pub const EM_OPENRISC: u16 = 92; pub const EM_ARC_A5: u16 = 93; pub const EM_XTENSA: u16 = 94; pub const EM_AARCH64: u16 = 183; pub const EM_TILEPRO: u16 = 188; pub const EM_TILEGX: u16 = 191; pub const EM_ALPHA: u16 = 0x9026; // elf.h - Legal values for e_version (version). pub const EV_NONE: u32 = 0; pub const EV_CURRENT: u32 = 1; pub const EV_NUM: u32 = 2; // elf.h - Legal values for p_type (segment type). pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_NUM: u32 = 8; pub const PT_LOOS: u32 = 0x60000000; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_STACK: u32 = 0x6474e551; pub const PT_GNU_RELRO: u32 = 0x6474e552; pub const PT_LOSUNW: u32 = 0x6ffffffa; pub const PT_SUNWBSS: u32 = 0x6ffffffa; pub const PT_SUNWSTACK: u32 = 0x6ffffffb; pub const PT_HISUNW: u32 = 0x6fffffff; pub const PT_HIOS: u32 = 0x6fffffff; pub const PT_LOPROC: u32 = 0x70000000; pub const PT_HIPROC: u32 = 0x7fffffff; // Legal values for p_flags (segment flags). pub const PF_X: u32 = 1 << 0; pub const PF_W: u32 = 1 << 1; pub const PF_R: u32 = 1 << 2; pub const PF_MASKOS: u32 = 0x0ff00000; pub const PF_MASKPROC: u32 = 0xf0000000; // elf.h - Legal values for a_type (entry type). pub const AT_NULL: ::c_ulong = 0; pub const AT_IGNORE: ::c_ulong = 1; pub const AT_EXECFD: ::c_ulong = 2; pub const AT_PHDR: ::c_ulong = 3; pub const AT_PHENT: ::c_ulong = 4; pub const AT_PHNUM: ::c_ulong = 5; pub const AT_PAGESZ: ::c_ulong = 6; pub const AT_BASE: ::c_ulong = 7; pub const AT_FLAGS: ::c_ulong = 8; pub const AT_ENTRY: ::c_ulong = 9; pub const AT_NOTELF: ::c_ulong = 10; pub const AT_UID: ::c_ulong = 11; pub const AT_EUID: ::c_ulong = 12; pub const AT_GID: ::c_ulong = 13; pub const AT_EGID: ::c_ulong = 14; pub const AT_PLATFORM: ::c_ulong = 15; pub const AT_HWCAP: ::c_ulong = 16; pub const AT_CLKTCK: ::c_ulong = 17; pub const AT_SECURE: ::c_ulong = 23; pub const AT_BASE_PLATFORM: ::c_ulong = 24; pub const AT_RANDOM: ::c_ulong = 25; pub const AT_HWCAP2: ::c_ulong = 26; pub const AT_EXECFN: ::c_ulong = 31; // defined in arch//include/uapi/asm/auxvec.h but has the same value // wherever it is defined. pub const AT_SYSINFO_EHDR: ::c_ulong = 33; pub const AT_MINSIGSTKSZ: ::c_ulong = 51; pub const GLOB_ERR: ::c_int = 1 << 0; pub const GLOB_MARK: ::c_int = 1 << 1; pub const GLOB_NOSORT: ::c_int = 1 << 2; pub const GLOB_DOOFFS: ::c_int = 1 << 3; pub const GLOB_NOCHECK: ::c_int = 1 << 4; pub const GLOB_APPEND: ::c_int = 1 << 5; pub const GLOB_NOESCAPE: ::c_int = 1 << 6; pub const GLOB_NOSPACE: ::c_int = 1; pub const GLOB_ABORTED: ::c_int = 2; pub const GLOB_NOMATCH: ::c_int = 3; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_SPAWN_USEVFORK: ::c_int = 64; pub const POSIX_SPAWN_SETSID: ::c_int = 128; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; pub const S_IREAD: mode_t = 256; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const F_SEAL_FUTURE_WRITE: ::c_int = 0x0010; pub const IFF_LOWER_UP: ::c_int = 0x10000; pub const IFF_DORMANT: ::c_int = 0x20000; pub const IFF_ECHO: ::c_int = 0x40000; // linux/if_addr.h pub const IFA_UNSPEC: ::c_ushort = 0; pub const IFA_ADDRESS: ::c_ushort = 1; pub const IFA_LOCAL: ::c_ushort = 2; pub const IFA_LABEL: ::c_ushort = 3; pub const IFA_BROADCAST: ::c_ushort = 4; pub const IFA_ANYCAST: ::c_ushort = 5; pub const IFA_CACHEINFO: ::c_ushort = 6; pub const IFA_MULTICAST: ::c_ushort = 7; pub const IFA_F_SECONDARY: u32 = 0x01; pub const IFA_F_TEMPORARY: u32 = 0x01; pub const IFA_F_NODAD: u32 = 0x02; pub const IFA_F_OPTIMISTIC: u32 = 0x04; pub const IFA_F_DADFAILED: u32 = 0x08; pub const IFA_F_HOMEADDRESS: u32 = 0x10; pub const IFA_F_DEPRECATED: u32 = 0x20; pub const IFA_F_TENTATIVE: u32 = 0x40; pub const IFA_F_PERMANENT: u32 = 0x80; // linux/if_link.h pub const IFLA_UNSPEC: ::c_ushort = 0; pub const IFLA_ADDRESS: ::c_ushort = 1; pub const IFLA_BROADCAST: ::c_ushort = 2; pub const IFLA_IFNAME: ::c_ushort = 3; pub const IFLA_MTU: ::c_ushort = 4; pub const IFLA_LINK: ::c_ushort = 5; pub const IFLA_QDISC: ::c_ushort = 6; pub const IFLA_STATS: ::c_ushort = 7; pub const IFLA_COST: ::c_ushort = 8; pub const IFLA_PRIORITY: ::c_ushort = 9; pub const IFLA_MASTER: ::c_ushort = 10; pub const IFLA_WIRELESS: ::c_ushort = 11; pub const IFLA_PROTINFO: ::c_ushort = 12; pub const IFLA_TXQLEN: ::c_ushort = 13; pub const IFLA_MAP: ::c_ushort = 14; pub const IFLA_WEIGHT: ::c_ushort = 15; pub const IFLA_OPERSTATE: ::c_ushort = 16; pub const IFLA_LINKMODE: ::c_ushort = 17; pub const IFLA_LINKINFO: ::c_ushort = 18; pub const IFLA_NET_NS_PID: ::c_ushort = 19; pub const IFLA_IFALIAS: ::c_ushort = 20; pub const IFLA_NUM_VF: ::c_ushort = 21; pub const IFLA_VFINFO_LIST: ::c_ushort = 22; pub const IFLA_STATS64: ::c_ushort = 23; pub const IFLA_VF_PORTS: ::c_ushort = 24; pub const IFLA_PORT_SELF: ::c_ushort = 25; pub const IFLA_AF_SPEC: ::c_ushort = 26; pub const IFLA_GROUP: ::c_ushort = 27; pub const IFLA_NET_NS_FD: ::c_ushort = 28; pub const IFLA_EXT_MASK: ::c_ushort = 29; pub const IFLA_PROMISCUITY: ::c_ushort = 30; pub const IFLA_NUM_TX_QUEUES: ::c_ushort = 31; pub const IFLA_NUM_RX_QUEUES: ::c_ushort = 32; pub const IFLA_CARRIER: ::c_ushort = 33; pub const IFLA_PHYS_PORT_ID: ::c_ushort = 34; pub const IFLA_CARRIER_CHANGES: ::c_ushort = 35; pub const IFLA_PHYS_SWITCH_ID: ::c_ushort = 36; pub const IFLA_LINK_NETNSID: ::c_ushort = 37; pub const IFLA_PHYS_PORT_NAME: ::c_ushort = 38; pub const IFLA_PROTO_DOWN: ::c_ushort = 39; pub const IFLA_GSO_MAX_SEGS: ::c_ushort = 40; pub const IFLA_GSO_MAX_SIZE: ::c_ushort = 41; pub const IFLA_PAD: ::c_ushort = 42; pub const IFLA_XDP: ::c_ushort = 43; pub const IFLA_EVENT: ::c_ushort = 44; pub const IFLA_NEW_NETNSID: ::c_ushort = 45; pub const IFLA_IF_NETNSID: ::c_ushort = 46; pub const IFLA_TARGET_NETNSID: ::c_ushort = IFLA_IF_NETNSID; pub const IFLA_CARRIER_UP_COUNT: ::c_ushort = 47; pub const IFLA_CARRIER_DOWN_COUNT: ::c_ushort = 48; pub const IFLA_NEW_IFINDEX: ::c_ushort = 49; pub const IFLA_MIN_MTU: ::c_ushort = 50; pub const IFLA_MAX_MTU: ::c_ushort = 51; pub const IFLA_PROP_LIST: ::c_ushort = 52; pub const IFLA_ALT_IFNAME: ::c_ushort = 53; pub const IFLA_PERM_ADDRESS: ::c_ushort = 54; pub const IFLA_PROTO_DOWN_REASON: ::c_ushort = 55; pub const IFLA_PARENT_DEV_NAME: ::c_ushort = 56; pub const IFLA_PARENT_DEV_BUS_NAME: ::c_ushort = 57; pub const IFLA_GRO_MAX_SIZE: ::c_ushort = 58; pub const IFLA_TSO_MAX_SIZE: ::c_ushort = 59; pub const IFLA_TSO_MAX_SEGS: ::c_ushort = 60; pub const IFLA_ALLMULTI: ::c_ushort = 61; pub const IFLA_INFO_UNSPEC: ::c_ushort = 0; pub const IFLA_INFO_KIND: ::c_ushort = 1; pub const IFLA_INFO_DATA: ::c_ushort = 2; pub const IFLA_INFO_XSTATS: ::c_ushort = 3; pub const IFLA_INFO_SLAVE_KIND: ::c_ushort = 4; pub const IFLA_INFO_SLAVE_DATA: ::c_ushort = 5; // linux/if_tun.h pub const IFF_TUN: ::c_int = 0x0001; pub const IFF_TAP: ::c_int = 0x0002; pub const IFF_NAPI: ::c_int = 0x0010; pub const IFF_NAPI_FRAGS: ::c_int = 0x0020; // Used in TUNSETIFF to bring up tun/tap without carrier pub const IFF_NO_CARRIER: ::c_int = 0x0040; pub const IFF_NO_PI: ::c_int = 0x1000; // Read queue size pub const TUN_READQ_SIZE: ::c_short = 500; // TUN device type flags: deprecated. Use IFF_TUN/IFF_TAP instead. pub const TUN_TUN_DEV: ::c_short = ::IFF_TUN as ::c_short; pub const TUN_TAP_DEV: ::c_short = ::IFF_TAP as ::c_short; pub const TUN_TYPE_MASK: ::c_short = 0x000f; // This flag has no real effect pub const IFF_ONE_QUEUE: ::c_int = 0x2000; pub const IFF_VNET_HDR: ::c_int = 0x4000; pub const IFF_TUN_EXCL: ::c_int = 0x8000; pub const IFF_MULTI_QUEUE: ::c_int = 0x0100; pub const IFF_ATTACH_QUEUE: ::c_int = 0x0200; pub const IFF_DETACH_QUEUE: ::c_int = 0x0400; // read-only flag pub const IFF_PERSIST: ::c_int = 0x0800; pub const IFF_NOFILTER: ::c_int = 0x1000; // Socket options pub const TUN_TX_TIMESTAMP: ::c_int = 1; // Features for GSO (TUNSETOFFLOAD) pub const TUN_F_CSUM: ::c_uint = 0x01; pub const TUN_F_TSO4: ::c_uint = 0x02; pub const TUN_F_TSO6: ::c_uint = 0x04; pub const TUN_F_TSO_ECN: ::c_uint = 0x08; pub const TUN_F_UFO: ::c_uint = 0x10; pub const TUN_F_USO4: ::c_uint = 0x20; pub const TUN_F_USO6: ::c_uint = 0x40; // Protocol info prepended to the packets (when IFF_NO_PI is not set) pub const TUN_PKT_STRIP: ::c_int = 0x0001; // Accept all multicast packets pub const TUN_FLT_ALLMULTI: ::c_int = 0x0001; // Since Linux 3.1 pub const SEEK_DATA: ::c_int = 3; pub const SEEK_HOLE: ::c_int = 4; pub const ST_RDONLY: ::c_ulong = 1; pub const ST_NOSUID: ::c_ulong = 2; pub const ST_NODEV: ::c_ulong = 4; pub const ST_NOEXEC: ::c_ulong = 8; pub const ST_SYNCHRONOUS: ::c_ulong = 16; pub const ST_MANDLOCK: ::c_ulong = 64; pub const ST_WRITE: ::c_ulong = 128; pub const ST_APPEND: ::c_ulong = 256; pub const ST_IMMUTABLE: ::c_ulong = 512; pub const ST_NOATIME: ::c_ulong = 1024; pub const ST_NODIRATIME: ::c_ulong = 2048; pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void; pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; pub const RTLD_NODELETE: ::c_int = 0x1000; pub const RTLD_NOW: ::c_int = 0x2; pub const AT_EACCESS: ::c_int = 0x200; // linux/mempolicy.h pub const MPOL_DEFAULT: ::c_int = 0; pub const MPOL_PREFERRED: ::c_int = 1; pub const MPOL_BIND: ::c_int = 2; pub const MPOL_INTERLEAVE: ::c_int = 3; pub const MPOL_LOCAL: ::c_int = 4; pub const MPOL_F_NUMA_BALANCING: ::c_int = 1 << 13; pub const MPOL_F_RELATIVE_NODES: ::c_int = 1 << 14; pub const MPOL_F_STATIC_NODES: ::c_int = 1 << 15; // linux/membarrier.h pub const MEMBARRIER_CMD_QUERY: ::c_int = 0; pub const MEMBARRIER_CMD_GLOBAL: ::c_int = 1 << 0; pub const MEMBARRIER_CMD_GLOBAL_EXPEDITED: ::c_int = 1 << 1; pub const MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED: ::c_int = 1 << 2; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED: ::c_int = 1 << 3; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED: ::c_int = 1 << 4; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE: ::c_int = 1 << 5; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE: ::c_int = 1 << 6; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ: ::c_int = 1 << 7; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ: ::c_int = 1 << 8; align_const! { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [0; __SIZEOF_PTHREAD_RWLOCK_T], }; } pub const PTHREAD_ONCE_INIT: pthread_once_t = 0; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_MUTEX_STALLED: ::c_int = 0; pub const PTHREAD_MUTEX_ROBUST: ::c_int = 1; pub const PTHREAD_PRIO_NONE: ::c_int = 0; pub const PTHREAD_PRIO_INHERIT: ::c_int = 1; pub const PTHREAD_PRIO_PROTECT: ::c_int = 2; pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const PTHREAD_INHERIT_SCHED: ::c_int = 0; pub const PTHREAD_EXPLICIT_SCHED: ::c_int = 1; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const RENAME_NOREPLACE: ::c_uint = 1; pub const RENAME_EXCHANGE: ::c_uint = 2; pub const RENAME_WHITEOUT: ::c_uint = 4; // netinet/in.h // NOTE: These are in addition to the constants defined in src/unix/mod.rs #[deprecated( since = "0.2.80", note = "This value was increased in the newer kernel \ and we'll change this following upstream in the future release. \ See #1896 for more info." )] pub const IPPROTO_MAX: ::c_int = 256; // System V IPC pub const IPC_PRIVATE: ::key_t = 0; pub const IPC_CREAT: ::c_int = 0o1000; pub const IPC_EXCL: ::c_int = 0o2000; pub const IPC_NOWAIT: ::c_int = 0o4000; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const IPC_INFO: ::c_int = 3; pub const MSG_STAT: ::c_int = 11; pub const MSG_INFO: ::c_int = 12; pub const MSG_NOTIFICATION: ::c_int = 0x8000; pub const MSG_NOERROR: ::c_int = 0o10000; pub const MSG_EXCEPT: ::c_int = 0o20000; pub const MSG_ZEROCOPY: ::c_int = 0x4000000; pub const SHM_R: ::c_int = 0o400; pub const SHM_W: ::c_int = 0o200; pub const SHM_RDONLY: ::c_int = 0o10000; pub const SHM_RND: ::c_int = 0o20000; pub const SHM_REMAP: ::c_int = 0o40000; pub const SHM_LOCK: ::c_int = 11; pub const SHM_UNLOCK: ::c_int = 12; pub const SHM_HUGETLB: ::c_int = 0o4000; #[cfg(not(all(target_env = "uclibc", target_arch = "mips")))] pub const SHM_NORESERVE: ::c_int = 0o10000; pub const QFMT_VFS_OLD: ::c_int = 1; pub const QFMT_VFS_V0: ::c_int = 2; pub const QFMT_VFS_V1: ::c_int = 4; pub const EFD_SEMAPHORE: ::c_int = 0x1; pub const LOG_NFACILITIES: ::c_int = 24; pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t; pub const RB_AUTOBOOT: ::c_int = 0x01234567u32 as i32; pub const RB_HALT_SYSTEM: ::c_int = 0xcdef0123u32 as i32; pub const RB_ENABLE_CAD: ::c_int = 0x89abcdefu32 as i32; pub const RB_DISABLE_CAD: ::c_int = 0x00000000u32 as i32; pub const RB_POWER_OFF: ::c_int = 0x4321fedcu32 as i32; pub const RB_SW_SUSPEND: ::c_int = 0xd000fce2u32 as i32; pub const RB_KEXEC: ::c_int = 0x45584543u32 as i32; pub const AI_PASSIVE: ::c_int = 0x0001; pub const AI_CANONNAME: ::c_int = 0x0002; pub const AI_NUMERICHOST: ::c_int = 0x0004; pub const AI_V4MAPPED: ::c_int = 0x0008; pub const AI_ALL: ::c_int = 0x0010; pub const AI_ADDRCONFIG: ::c_int = 0x0020; pub const AI_NUMERICSERV: ::c_int = 0x0400; pub const EAI_BADFLAGS: ::c_int = -1; pub const EAI_NONAME: ::c_int = -2; pub const EAI_AGAIN: ::c_int = -3; pub const EAI_FAIL: ::c_int = -4; pub const EAI_NODATA: ::c_int = -5; pub const EAI_FAMILY: ::c_int = -6; pub const EAI_SOCKTYPE: ::c_int = -7; pub const EAI_SERVICE: ::c_int = -8; pub const EAI_MEMORY: ::c_int = -10; pub const EAI_SYSTEM: ::c_int = -11; pub const EAI_OVERFLOW: ::c_int = -12; pub const NI_NUMERICHOST: ::c_int = 1; pub const NI_NUMERICSERV: ::c_int = 2; pub const NI_NOFQDN: ::c_int = 4; pub const NI_NAMEREQD: ::c_int = 8; pub const NI_DGRAM: ::c_int = 16; pub const NI_IDN: ::c_int = 32; pub const SYNC_FILE_RANGE_WAIT_BEFORE: ::c_uint = 1; pub const SYNC_FILE_RANGE_WRITE: ::c_uint = 2; pub const SYNC_FILE_RANGE_WAIT_AFTER: ::c_uint = 4; cfg_if! { if #[cfg(not(target_env = "uclibc"))] { pub const AIO_CANCELED: ::c_int = 0; pub const AIO_NOTCANCELED: ::c_int = 1; pub const AIO_ALLDONE: ::c_int = 2; pub const LIO_READ: ::c_int = 0; pub const LIO_WRITE: ::c_int = 1; pub const LIO_NOP: ::c_int = 2; pub const LIO_WAIT: ::c_int = 0; pub const LIO_NOWAIT: ::c_int = 1; pub const RUSAGE_THREAD: ::c_int = 1; pub const MSG_COPY: ::c_int = 0o40000; pub const SHM_EXEC: ::c_int = 0o100000; pub const IPV6_MULTICAST_ALL: ::c_int = 29; pub const IPV6_ROUTER_ALERT_ISOLATE: ::c_int = 30; pub const PACKET_MR_UNICAST: ::c_int = 3; pub const PTRACE_EVENT_STOP: ::c_int = 128; pub const UDP_SEGMENT: ::c_int = 103; pub const UDP_GRO: ::c_int = 104; } } pub const MREMAP_MAYMOVE: ::c_int = 1; pub const MREMAP_FIXED: ::c_int = 2; pub const MREMAP_DONTUNMAP: ::c_int = 4; pub const PR_SET_PDEATHSIG: ::c_int = 1; pub const PR_GET_PDEATHSIG: ::c_int = 2; pub const PR_GET_DUMPABLE: ::c_int = 3; pub const PR_SET_DUMPABLE: ::c_int = 4; pub const PR_GET_UNALIGN: ::c_int = 5; pub const PR_SET_UNALIGN: ::c_int = 6; pub const PR_UNALIGN_NOPRINT: ::c_int = 1; pub const PR_UNALIGN_SIGBUS: ::c_int = 2; pub const PR_GET_KEEPCAPS: ::c_int = 7; pub const PR_SET_KEEPCAPS: ::c_int = 8; pub const PR_GET_FPEMU: ::c_int = 9; pub const PR_SET_FPEMU: ::c_int = 10; pub const PR_FPEMU_NOPRINT: ::c_int = 1; pub const PR_FPEMU_SIGFPE: ::c_int = 2; pub const PR_GET_FPEXC: ::c_int = 11; pub const PR_SET_FPEXC: ::c_int = 12; pub const PR_FP_EXC_SW_ENABLE: ::c_int = 0x80; pub const PR_FP_EXC_DIV: ::c_int = 0x010000; pub const PR_FP_EXC_OVF: ::c_int = 0x020000; pub const PR_FP_EXC_UND: ::c_int = 0x040000; pub const PR_FP_EXC_RES: ::c_int = 0x080000; pub const PR_FP_EXC_INV: ::c_int = 0x100000; pub const PR_FP_EXC_DISABLED: ::c_int = 0; pub const PR_FP_EXC_NONRECOV: ::c_int = 1; pub const PR_FP_EXC_ASYNC: ::c_int = 2; pub const PR_FP_EXC_PRECISE: ::c_int = 3; pub const PR_GET_TIMING: ::c_int = 13; pub const PR_SET_TIMING: ::c_int = 14; pub const PR_TIMING_STATISTICAL: ::c_int = 0; pub const PR_TIMING_TIMESTAMP: ::c_int = 1; pub const PR_SET_NAME: ::c_int = 15; pub const PR_GET_NAME: ::c_int = 16; pub const PR_GET_ENDIAN: ::c_int = 19; pub const PR_SET_ENDIAN: ::c_int = 20; pub const PR_ENDIAN_BIG: ::c_int = 0; pub const PR_ENDIAN_LITTLE: ::c_int = 1; pub const PR_ENDIAN_PPC_LITTLE: ::c_int = 2; pub const PR_GET_SECCOMP: ::c_int = 21; pub const PR_SET_SECCOMP: ::c_int = 22; pub const PR_CAPBSET_READ: ::c_int = 23; pub const PR_CAPBSET_DROP: ::c_int = 24; pub const PR_GET_TSC: ::c_int = 25; pub const PR_SET_TSC: ::c_int = 26; pub const PR_TSC_ENABLE: ::c_int = 1; pub const PR_TSC_SIGSEGV: ::c_int = 2; pub const PR_GET_SECUREBITS: ::c_int = 27; pub const PR_SET_SECUREBITS: ::c_int = 28; pub const PR_SET_TIMERSLACK: ::c_int = 29; pub const PR_GET_TIMERSLACK: ::c_int = 30; pub const PR_TASK_PERF_EVENTS_DISABLE: ::c_int = 31; pub const PR_TASK_PERF_EVENTS_ENABLE: ::c_int = 32; pub const PR_MCE_KILL: ::c_int = 33; pub const PR_MCE_KILL_CLEAR: ::c_int = 0; pub const PR_MCE_KILL_SET: ::c_int = 1; pub const PR_MCE_KILL_LATE: ::c_int = 0; pub const PR_MCE_KILL_EARLY: ::c_int = 1; pub const PR_MCE_KILL_DEFAULT: ::c_int = 2; pub const PR_MCE_KILL_GET: ::c_int = 34; pub const PR_SET_MM: ::c_int = 35; pub const PR_SET_MM_START_CODE: ::c_int = 1; pub const PR_SET_MM_END_CODE: ::c_int = 2; pub const PR_SET_MM_START_DATA: ::c_int = 3; pub const PR_SET_MM_END_DATA: ::c_int = 4; pub const PR_SET_MM_START_STACK: ::c_int = 5; pub const PR_SET_MM_START_BRK: ::c_int = 6; pub const PR_SET_MM_BRK: ::c_int = 7; pub const PR_SET_MM_ARG_START: ::c_int = 8; pub const PR_SET_MM_ARG_END: ::c_int = 9; pub const PR_SET_MM_ENV_START: ::c_int = 10; pub const PR_SET_MM_ENV_END: ::c_int = 11; pub const PR_SET_MM_AUXV: ::c_int = 12; pub const PR_SET_MM_EXE_FILE: ::c_int = 13; pub const PR_SET_MM_MAP: ::c_int = 14; pub const PR_SET_MM_MAP_SIZE: ::c_int = 15; pub const PR_SET_PTRACER: ::c_int = 0x59616d61; pub const PR_SET_PTRACER_ANY: ::c_ulong = 0xffffffffffffffff; pub const PR_SET_CHILD_SUBREAPER: ::c_int = 36; pub const PR_GET_CHILD_SUBREAPER: ::c_int = 37; pub const PR_SET_NO_NEW_PRIVS: ::c_int = 38; pub const PR_GET_NO_NEW_PRIVS: ::c_int = 39; pub const PR_GET_TID_ADDRESS: ::c_int = 40; pub const PR_SET_THP_DISABLE: ::c_int = 41; pub const PR_GET_THP_DISABLE: ::c_int = 42; pub const PR_MPX_ENABLE_MANAGEMENT: ::c_int = 43; pub const PR_MPX_DISABLE_MANAGEMENT: ::c_int = 44; pub const PR_SET_FP_MODE: ::c_int = 45; pub const PR_GET_FP_MODE: ::c_int = 46; pub const PR_FP_MODE_FR: ::c_int = 1 << 0; pub const PR_FP_MODE_FRE: ::c_int = 1 << 1; pub const PR_CAP_AMBIENT: ::c_int = 47; pub const PR_CAP_AMBIENT_IS_SET: ::c_int = 1; pub const PR_CAP_AMBIENT_RAISE: ::c_int = 2; pub const PR_CAP_AMBIENT_LOWER: ::c_int = 3; pub const PR_CAP_AMBIENT_CLEAR_ALL: ::c_int = 4; pub const PR_SET_VMA: ::c_int = 0x53564d41; pub const PR_SET_VMA_ANON_NAME: ::c_int = 0; pub const PR_SCHED_CORE: ::c_int = 62; pub const PR_SCHED_CORE_GET: ::c_int = 0; pub const PR_SCHED_CORE_CREATE: ::c_int = 1; pub const PR_SCHED_CORE_SHARE_TO: ::c_int = 2; pub const PR_SCHED_CORE_SHARE_FROM: ::c_int = 3; pub const PR_SCHED_CORE_MAX: ::c_int = 4; pub const PR_SCHED_CORE_SCOPE_THREAD: ::c_int = 0; pub const PR_SCHED_CORE_SCOPE_THREAD_GROUP: ::c_int = 1; pub const PR_SCHED_CORE_SCOPE_PROCESS_GROUP: ::c_int = 2; pub const GRND_NONBLOCK: ::c_uint = 0x0001; pub const GRND_RANDOM: ::c_uint = 0x0002; pub const GRND_INSECURE: ::c_uint = 0x0004; // pub const SECCOMP_MODE_DISABLED: ::c_uint = 0; pub const SECCOMP_MODE_STRICT: ::c_uint = 1; pub const SECCOMP_MODE_FILTER: ::c_uint = 2; pub const SECCOMP_SET_MODE_STRICT: ::c_uint = 0; pub const SECCOMP_SET_MODE_FILTER: ::c_uint = 1; pub const SECCOMP_GET_ACTION_AVAIL: ::c_uint = 2; pub const SECCOMP_GET_NOTIF_SIZES: ::c_uint = 3; pub const SECCOMP_FILTER_FLAG_TSYNC: ::c_ulong = 1; pub const SECCOMP_FILTER_FLAG_LOG: ::c_ulong = 2; pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: ::c_ulong = 4; pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: ::c_ulong = 8; pub const SECCOMP_FILTER_FLAG_TSYNC_ESRCH: ::c_ulong = 16; pub const SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV: ::c_ulong = 32; pub const SECCOMP_RET_KILL_PROCESS: ::c_uint = 0x80000000; pub const SECCOMP_RET_KILL_THREAD: ::c_uint = 0x00000000; pub const SECCOMP_RET_KILL: ::c_uint = SECCOMP_RET_KILL_THREAD; pub const SECCOMP_RET_TRAP: ::c_uint = 0x00030000; pub const SECCOMP_RET_ERRNO: ::c_uint = 0x00050000; pub const SECCOMP_RET_TRACE: ::c_uint = 0x7ff00000; pub const SECCOMP_RET_LOG: ::c_uint = 0x7ffc0000; pub const SECCOMP_RET_ALLOW: ::c_uint = 0x7fff0000; pub const SECCOMP_RET_ACTION_FULL: ::c_uint = 0xffff0000; pub const SECCOMP_RET_ACTION: ::c_uint = 0x7fff0000; pub const SECCOMP_RET_DATA: ::c_uint = 0x0000ffff; pub const SECCOMP_USER_NOTIF_FLAG_CONTINUE: ::c_ulong = 1; pub const SECCOMP_ADDFD_FLAG_SETFD: ::c_ulong = 1; pub const SECCOMP_ADDFD_FLAG_SEND: ::c_ulong = 2; pub const ITIMER_REAL: ::c_int = 0; pub const ITIMER_VIRTUAL: ::c_int = 1; pub const ITIMER_PROF: ::c_int = 2; pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC; pub const TFD_NONBLOCK: ::c_int = O_NONBLOCK; pub const TFD_TIMER_ABSTIME: ::c_int = 1; pub const TFD_TIMER_CANCEL_ON_SET: ::c_int = 2; pub const _POSIX_VDISABLE: ::cc_t = 0; pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02; pub const FALLOC_FL_COLLAPSE_RANGE: ::c_int = 0x08; pub const FALLOC_FL_ZERO_RANGE: ::c_int = 0x10; pub const FALLOC_FL_INSERT_RANGE: ::c_int = 0x20; pub const FALLOC_FL_UNSHARE_RANGE: ::c_int = 0x40; #[deprecated( since = "0.2.55", note = "ENOATTR is not available on Linux; use ENODATA instead" )] pub const ENOATTR: ::c_int = ::ENODATA; pub const SO_ORIGINAL_DST: ::c_int = 80; pub const IP_RECVFRAGSIZE: ::c_int = 25; pub const IPV6_FLOWINFO: ::c_int = 11; pub const IPV6_FLOWLABEL_MGR: ::c_int = 32; pub const IPV6_FLOWINFO_SEND: ::c_int = 33; pub const IPV6_RECVFRAGSIZE: ::c_int = 77; pub const IPV6_FREEBIND: ::c_int = 78; pub const IPV6_FLOWINFO_FLOWLABEL: ::c_int = 0x000fffff; pub const IPV6_FLOWINFO_PRIORITY: ::c_int = 0x0ff00000; pub const IPV6_RTHDR_LOOSE: ::c_int = 0; pub const IPV6_RTHDR_STRICT: ::c_int = 1; // SO_MEMINFO offsets pub const SK_MEMINFO_RMEM_ALLOC: ::c_int = 0; pub const SK_MEMINFO_RCVBUF: ::c_int = 1; pub const SK_MEMINFO_WMEM_ALLOC: ::c_int = 2; pub const SK_MEMINFO_SNDBUF: ::c_int = 3; pub const SK_MEMINFO_FWD_ALLOC: ::c_int = 4; pub const SK_MEMINFO_WMEM_QUEUED: ::c_int = 5; pub const SK_MEMINFO_OPTMEM: ::c_int = 6; pub const SK_MEMINFO_BACKLOG: ::c_int = 7; pub const SK_MEMINFO_DROPS: ::c_int = 8; pub const IUTF8: ::tcflag_t = 0x00004000; #[cfg(not(all(target_env = "uclibc", target_arch = "mips")))] pub const CMSPAR: ::tcflag_t = 0o10000000000; pub const MFD_CLOEXEC: ::c_uint = 0x0001; pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002; pub const MFD_HUGETLB: ::c_uint = 0x0004; pub const MFD_NOEXEC_SEAL: ::c_uint = 0x0008; pub const MFD_EXEC: ::c_uint = 0x0010; pub const MFD_HUGE_64KB: ::c_uint = 0x40000000; pub const MFD_HUGE_512KB: ::c_uint = 0x4c000000; pub const MFD_HUGE_1MB: ::c_uint = 0x50000000; pub const MFD_HUGE_2MB: ::c_uint = 0x54000000; pub const MFD_HUGE_8MB: ::c_uint = 0x5c000000; pub const MFD_HUGE_16MB: ::c_uint = 0x60000000; pub const MFD_HUGE_32MB: ::c_uint = 0x64000000; pub const MFD_HUGE_256MB: ::c_uint = 0x70000000; pub const MFD_HUGE_512MB: ::c_uint = 0x74000000; pub const MFD_HUGE_1GB: ::c_uint = 0x78000000; pub const MFD_HUGE_2GB: ::c_uint = 0x7c000000; pub const MFD_HUGE_16GB: ::c_uint = 0x88000000; pub const MFD_HUGE_MASK: ::c_uint = 63; pub const MFD_HUGE_SHIFT: ::c_uint = 26; // linux/close_range.h pub const CLOSE_RANGE_UNSHARE: ::c_uint = 1 << 1; pub const CLOSE_RANGE_CLOEXEC: ::c_uint = 1 << 2; // linux/filter.h pub const SKF_AD_OFF: ::c_int = -0x1000; pub const SKF_AD_PROTOCOL: ::c_int = 0; pub const SKF_AD_PKTTYPE: ::c_int = 4; pub const SKF_AD_IFINDEX: ::c_int = 8; pub const SKF_AD_NLATTR: ::c_int = 12; pub const SKF_AD_NLATTR_NEST: ::c_int = 16; pub const SKF_AD_MARK: ::c_int = 20; pub const SKF_AD_QUEUE: ::c_int = 24; pub const SKF_AD_HATYPE: ::c_int = 28; pub const SKF_AD_RXHASH: ::c_int = 32; pub const SKF_AD_CPU: ::c_int = 36; pub const SKF_AD_ALU_XOR_X: ::c_int = 40; pub const SKF_AD_VLAN_TAG: ::c_int = 44; pub const SKF_AD_VLAN_TAG_PRESENT: ::c_int = 48; pub const SKF_AD_PAY_OFFSET: ::c_int = 52; pub const SKF_AD_RANDOM: ::c_int = 56; pub const SKF_AD_VLAN_TPID: ::c_int = 60; pub const SKF_AD_MAX: ::c_int = 64; pub const SKF_NET_OFF: ::c_int = -0x100000; pub const SKF_LL_OFF: ::c_int = -0x200000; pub const BPF_NET_OFF: ::c_int = SKF_NET_OFF; pub const BPF_LL_OFF: ::c_int = SKF_LL_OFF; pub const BPF_MEMWORDS: ::c_int = 16; pub const BPF_MAXINSNS: ::c_int = 4096; // linux/bpf_common.h pub const BPF_LD: ::__u32 = 0x00; pub const BPF_LDX: ::__u32 = 0x01; pub const BPF_ST: ::__u32 = 0x02; pub const BPF_STX: ::__u32 = 0x03; pub const BPF_ALU: ::__u32 = 0x04; pub const BPF_JMP: ::__u32 = 0x05; pub const BPF_RET: ::__u32 = 0x06; pub const BPF_MISC: ::__u32 = 0x07; pub const BPF_W: ::__u32 = 0x00; pub const BPF_H: ::__u32 = 0x08; pub const BPF_B: ::__u32 = 0x10; pub const BPF_IMM: ::__u32 = 0x00; pub const BPF_ABS: ::__u32 = 0x20; pub const BPF_IND: ::__u32 = 0x40; pub const BPF_MEM: ::__u32 = 0x60; pub const BPF_LEN: ::__u32 = 0x80; pub const BPF_MSH: ::__u32 = 0xa0; pub const BPF_ADD: ::__u32 = 0x00; pub const BPF_SUB: ::__u32 = 0x10; pub const BPF_MUL: ::__u32 = 0x20; pub const BPF_DIV: ::__u32 = 0x30; pub const BPF_OR: ::__u32 = 0x40; pub const BPF_AND: ::__u32 = 0x50; pub const BPF_LSH: ::__u32 = 0x60; pub const BPF_RSH: ::__u32 = 0x70; pub const BPF_NEG: ::__u32 = 0x80; pub const BPF_MOD: ::__u32 = 0x90; pub const BPF_XOR: ::__u32 = 0xa0; pub const BPF_JA: ::__u32 = 0x00; pub const BPF_JEQ: ::__u32 = 0x10; pub const BPF_JGT: ::__u32 = 0x20; pub const BPF_JGE: ::__u32 = 0x30; pub const BPF_JSET: ::__u32 = 0x40; pub const BPF_K: ::__u32 = 0x00; pub const BPF_X: ::__u32 = 0x08; // linux/openat2.h pub const RESOLVE_NO_XDEV: ::__u64 = 0x01; pub const RESOLVE_NO_MAGICLINKS: ::__u64 = 0x02; pub const RESOLVE_NO_SYMLINKS: ::__u64 = 0x04; pub const RESOLVE_BENEATH: ::__u64 = 0x08; pub const RESOLVE_IN_ROOT: ::__u64 = 0x10; pub const RESOLVE_CACHED: ::__u64 = 0x20; // linux/if_ether.h pub const ETH_ALEN: ::c_int = 6; pub const ETH_HLEN: ::c_int = 14; pub const ETH_ZLEN: ::c_int = 60; pub const ETH_DATA_LEN: ::c_int = 1500; pub const ETH_FRAME_LEN: ::c_int = 1514; pub const ETH_FCS_LEN: ::c_int = 4; // These are the defined Ethernet Protocol ID's. pub const ETH_P_LOOP: ::c_int = 0x0060; pub const ETH_P_PUP: ::c_int = 0x0200; pub const ETH_P_PUPAT: ::c_int = 0x0201; pub const ETH_P_IP: ::c_int = 0x0800; pub const ETH_P_X25: ::c_int = 0x0805; pub const ETH_P_ARP: ::c_int = 0x0806; pub const ETH_P_BPQ: ::c_int = 0x08FF; pub const ETH_P_IEEEPUP: ::c_int = 0x0a00; pub const ETH_P_IEEEPUPAT: ::c_int = 0x0a01; pub const ETH_P_BATMAN: ::c_int = 0x4305; pub const ETH_P_DEC: ::c_int = 0x6000; pub const ETH_P_DNA_DL: ::c_int = 0x6001; pub const ETH_P_DNA_RC: ::c_int = 0x6002; pub const ETH_P_DNA_RT: ::c_int = 0x6003; pub const ETH_P_LAT: ::c_int = 0x6004; pub const ETH_P_DIAG: ::c_int = 0x6005; pub const ETH_P_CUST: ::c_int = 0x6006; pub const ETH_P_SCA: ::c_int = 0x6007; pub const ETH_P_TEB: ::c_int = 0x6558; pub const ETH_P_RARP: ::c_int = 0x8035; pub const ETH_P_ATALK: ::c_int = 0x809B; pub const ETH_P_AARP: ::c_int = 0x80F3; pub const ETH_P_8021Q: ::c_int = 0x8100; pub const ETH_P_IPX: ::c_int = 0x8137; pub const ETH_P_IPV6: ::c_int = 0x86DD; pub const ETH_P_PAUSE: ::c_int = 0x8808; pub const ETH_P_SLOW: ::c_int = 0x8809; pub const ETH_P_WCCP: ::c_int = 0x883E; pub const ETH_P_MPLS_UC: ::c_int = 0x8847; pub const ETH_P_MPLS_MC: ::c_int = 0x8848; pub const ETH_P_ATMMPOA: ::c_int = 0x884c; pub const ETH_P_PPP_DISC: ::c_int = 0x8863; pub const ETH_P_PPP_SES: ::c_int = 0x8864; pub const ETH_P_LINK_CTL: ::c_int = 0x886c; pub const ETH_P_ATMFATE: ::c_int = 0x8884; pub const ETH_P_PAE: ::c_int = 0x888E; pub const ETH_P_AOE: ::c_int = 0x88A2; pub const ETH_P_8021AD: ::c_int = 0x88A8; pub const ETH_P_802_EX1: ::c_int = 0x88B5; pub const ETH_P_TIPC: ::c_int = 0x88CA; pub const ETH_P_MACSEC: ::c_int = 0x88E5; pub const ETH_P_8021AH: ::c_int = 0x88E7; pub const ETH_P_MVRP: ::c_int = 0x88F5; pub const ETH_P_1588: ::c_int = 0x88F7; pub const ETH_P_PRP: ::c_int = 0x88FB; pub const ETH_P_FCOE: ::c_int = 0x8906; pub const ETH_P_TDLS: ::c_int = 0x890D; pub const ETH_P_FIP: ::c_int = 0x8914; pub const ETH_P_80221: ::c_int = 0x8917; pub const ETH_P_LOOPBACK: ::c_int = 0x9000; pub const ETH_P_QINQ1: ::c_int = 0x9100; pub const ETH_P_QINQ2: ::c_int = 0x9200; pub const ETH_P_QINQ3: ::c_int = 0x9300; pub const ETH_P_EDSA: ::c_int = 0xDADA; pub const ETH_P_AF_IUCV: ::c_int = 0xFBFB; pub const ETH_P_802_3_MIN: ::c_int = 0x0600; // Non DIX types. Won't clash for 1500 types. pub const ETH_P_802_3: ::c_int = 0x0001; pub const ETH_P_AX25: ::c_int = 0x0002; pub const ETH_P_ALL: ::c_int = 0x0003; pub const ETH_P_802_2: ::c_int = 0x0004; pub const ETH_P_SNAP: ::c_int = 0x0005; pub const ETH_P_DDCMP: ::c_int = 0x0006; pub const ETH_P_WAN_PPP: ::c_int = 0x0007; pub const ETH_P_PPP_MP: ::c_int = 0x0008; pub const ETH_P_LOCALTALK: ::c_int = 0x0009; pub const ETH_P_CANFD: ::c_int = 0x000D; pub const ETH_P_PPPTALK: ::c_int = 0x0010; pub const ETH_P_TR_802_2: ::c_int = 0x0011; pub const ETH_P_MOBITEX: ::c_int = 0x0015; pub const ETH_P_CONTROL: ::c_int = 0x0016; pub const ETH_P_IRDA: ::c_int = 0x0017; pub const ETH_P_ECONET: ::c_int = 0x0018; pub const ETH_P_HDLC: ::c_int = 0x0019; pub const ETH_P_ARCNET: ::c_int = 0x001A; pub const ETH_P_DSA: ::c_int = 0x001B; pub const ETH_P_TRAILER: ::c_int = 0x001C; pub const ETH_P_PHONET: ::c_int = 0x00F5; pub const ETH_P_IEEE802154: ::c_int = 0x00F6; pub const ETH_P_CAIF: ::c_int = 0x00F7; pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x04; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x08; pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x10; pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x20; pub const NLMSG_NOOP: ::c_int = 0x1; pub const NLMSG_ERROR: ::c_int = 0x2; pub const NLMSG_DONE: ::c_int = 0x3; pub const NLMSG_OVERRUN: ::c_int = 0x4; pub const NLMSG_MIN_TYPE: ::c_int = 0x10; // linux/netfilter/nfnetlink.h pub const NFNLGRP_NONE: ::c_int = 0; pub const NFNLGRP_CONNTRACK_NEW: ::c_int = 1; pub const NFNLGRP_CONNTRACK_UPDATE: ::c_int = 2; pub const NFNLGRP_CONNTRACK_DESTROY: ::c_int = 3; pub const NFNLGRP_CONNTRACK_EXP_NEW: ::c_int = 4; pub const NFNLGRP_CONNTRACK_EXP_UPDATE: ::c_int = 5; pub const NFNLGRP_CONNTRACK_EXP_DESTROY: ::c_int = 6; pub const NFNLGRP_NFTABLES: ::c_int = 7; pub const NFNLGRP_ACCT_QUOTA: ::c_int = 8; pub const NFNLGRP_NFTRACE: ::c_int = 9; pub const NFNETLINK_V0: ::c_int = 0; pub const NFNL_SUBSYS_NONE: ::c_int = 0; pub const NFNL_SUBSYS_CTNETLINK: ::c_int = 1; pub const NFNL_SUBSYS_CTNETLINK_EXP: ::c_int = 2; pub const NFNL_SUBSYS_QUEUE: ::c_int = 3; pub const NFNL_SUBSYS_ULOG: ::c_int = 4; pub const NFNL_SUBSYS_OSF: ::c_int = 5; pub const NFNL_SUBSYS_IPSET: ::c_int = 6; pub const NFNL_SUBSYS_ACCT: ::c_int = 7; pub const NFNL_SUBSYS_CTNETLINK_TIMEOUT: ::c_int = 8; pub const NFNL_SUBSYS_CTHELPER: ::c_int = 9; pub const NFNL_SUBSYS_NFTABLES: ::c_int = 10; pub const NFNL_SUBSYS_NFT_COMPAT: ::c_int = 11; pub const NFNL_SUBSYS_HOOK: ::c_int = 12; pub const NFNL_SUBSYS_COUNT: ::c_int = 13; pub const NFNL_MSG_BATCH_BEGIN: ::c_int = NLMSG_MIN_TYPE; pub const NFNL_MSG_BATCH_END: ::c_int = NLMSG_MIN_TYPE + 1; pub const NFNL_BATCH_UNSPEC: ::c_int = 0; pub const NFNL_BATCH_GENID: ::c_int = 1; // linux/netfilter/nfnetlink_log.h pub const NFULNL_MSG_PACKET: ::c_int = 0; pub const NFULNL_MSG_CONFIG: ::c_int = 1; pub const NFULA_VLAN_UNSPEC: ::c_int = 0; pub const NFULA_VLAN_PROTO: ::c_int = 1; pub const NFULA_VLAN_TCI: ::c_int = 2; pub const NFULA_UNSPEC: ::c_int = 0; pub const NFULA_PACKET_HDR: ::c_int = 1; pub const NFULA_MARK: ::c_int = 2; pub const NFULA_TIMESTAMP: ::c_int = 3; pub const NFULA_IFINDEX_INDEV: ::c_int = 4; pub const NFULA_IFINDEX_OUTDEV: ::c_int = 5; pub const NFULA_IFINDEX_PHYSINDEV: ::c_int = 6; pub const NFULA_IFINDEX_PHYSOUTDEV: ::c_int = 7; pub const NFULA_HWADDR: ::c_int = 8; pub const NFULA_PAYLOAD: ::c_int = 9; pub const NFULA_PREFIX: ::c_int = 10; pub const NFULA_UID: ::c_int = 11; pub const NFULA_SEQ: ::c_int = 12; pub const NFULA_SEQ_GLOBAL: ::c_int = 13; pub const NFULA_GID: ::c_int = 14; pub const NFULA_HWTYPE: ::c_int = 15; pub const NFULA_HWHEADER: ::c_int = 16; pub const NFULA_HWLEN: ::c_int = 17; pub const NFULA_CT: ::c_int = 18; pub const NFULA_CT_INFO: ::c_int = 19; pub const NFULA_VLAN: ::c_int = 20; pub const NFULA_L2HDR: ::c_int = 21; pub const NFULNL_CFG_CMD_NONE: ::c_int = 0; pub const NFULNL_CFG_CMD_BIND: ::c_int = 1; pub const NFULNL_CFG_CMD_UNBIND: ::c_int = 2; pub const NFULNL_CFG_CMD_PF_BIND: ::c_int = 3; pub const NFULNL_CFG_CMD_PF_UNBIND: ::c_int = 4; pub const NFULA_CFG_UNSPEC: ::c_int = 0; pub const NFULA_CFG_CMD: ::c_int = 1; pub const NFULA_CFG_MODE: ::c_int = 2; pub const NFULA_CFG_NLBUFSIZ: ::c_int = 3; pub const NFULA_CFG_TIMEOUT: ::c_int = 4; pub const NFULA_CFG_QTHRESH: ::c_int = 5; pub const NFULA_CFG_FLAGS: ::c_int = 6; pub const NFULNL_COPY_NONE: ::c_int = 0x00; pub const NFULNL_COPY_META: ::c_int = 0x01; pub const NFULNL_COPY_PACKET: ::c_int = 0x02; pub const NFULNL_CFG_F_SEQ: ::c_int = 0x0001; pub const NFULNL_CFG_F_SEQ_GLOBAL: ::c_int = 0x0002; pub const NFULNL_CFG_F_CONNTRACK: ::c_int = 0x0004; // linux/netfilter/nfnetlink_queue.h pub const NFQNL_MSG_PACKET: ::c_int = 0; pub const NFQNL_MSG_VERDICT: ::c_int = 1; pub const NFQNL_MSG_CONFIG: ::c_int = 2; pub const NFQNL_MSG_VERDICT_BATCH: ::c_int = 3; pub const NFQA_UNSPEC: ::c_int = 0; pub const NFQA_PACKET_HDR: ::c_int = 1; pub const NFQA_VERDICT_HDR: ::c_int = 2; pub const NFQA_MARK: ::c_int = 3; pub const NFQA_TIMESTAMP: ::c_int = 4; pub const NFQA_IFINDEX_INDEV: ::c_int = 5; pub const NFQA_IFINDEX_OUTDEV: ::c_int = 6; pub const NFQA_IFINDEX_PHYSINDEV: ::c_int = 7; pub const NFQA_IFINDEX_PHYSOUTDEV: ::c_int = 8; pub const NFQA_HWADDR: ::c_int = 9; pub const NFQA_PAYLOAD: ::c_int = 10; pub const NFQA_CT: ::c_int = 11; pub const NFQA_CT_INFO: ::c_int = 12; pub const NFQA_CAP_LEN: ::c_int = 13; pub const NFQA_SKB_INFO: ::c_int = 14; pub const NFQA_EXP: ::c_int = 15; pub const NFQA_UID: ::c_int = 16; pub const NFQA_GID: ::c_int = 17; pub const NFQA_SECCTX: ::c_int = 18; pub const NFQA_VLAN: ::c_int = 19; pub const NFQA_L2HDR: ::c_int = 20; pub const NFQA_PRIORITY: ::c_int = 21; pub const NFQA_VLAN_UNSPEC: ::c_int = 0; pub const NFQA_VLAN_PROTO: ::c_int = 1; pub const NFQA_VLAN_TCI: ::c_int = 2; pub const NFQNL_CFG_CMD_NONE: ::c_int = 0; pub const NFQNL_CFG_CMD_BIND: ::c_int = 1; pub const NFQNL_CFG_CMD_UNBIND: ::c_int = 2; pub const NFQNL_CFG_CMD_PF_BIND: ::c_int = 3; pub const NFQNL_CFG_CMD_PF_UNBIND: ::c_int = 4; pub const NFQNL_COPY_NONE: ::c_int = 0; pub const NFQNL_COPY_META: ::c_int = 1; pub const NFQNL_COPY_PACKET: ::c_int = 2; pub const NFQA_CFG_UNSPEC: ::c_int = 0; pub const NFQA_CFG_CMD: ::c_int = 1; pub const NFQA_CFG_PARAMS: ::c_int = 2; pub const NFQA_CFG_QUEUE_MAXLEN: ::c_int = 3; pub const NFQA_CFG_MASK: ::c_int = 4; pub const NFQA_CFG_FLAGS: ::c_int = 5; pub const NFQA_CFG_F_FAIL_OPEN: ::c_int = 0x0001; pub const NFQA_CFG_F_CONNTRACK: ::c_int = 0x0002; pub const NFQA_CFG_F_GSO: ::c_int = 0x0004; pub const NFQA_CFG_F_UID_GID: ::c_int = 0x0008; pub const NFQA_CFG_F_SECCTX: ::c_int = 0x0010; pub const NFQA_CFG_F_MAX: ::c_int = 0x0020; pub const NFQA_SKB_CSUMNOTREADY: ::c_int = 0x0001; pub const NFQA_SKB_GSO: ::c_int = 0x0002; pub const NFQA_SKB_CSUM_NOTVERIFIED: ::c_int = 0x0004; // linux/genetlink.h pub const GENL_NAMSIZ: ::c_int = 16; pub const GENL_MIN_ID: ::c_int = NLMSG_MIN_TYPE; pub const GENL_MAX_ID: ::c_int = 1023; pub const GENL_ADMIN_PERM: ::c_int = 0x01; pub const GENL_CMD_CAP_DO: ::c_int = 0x02; pub const GENL_CMD_CAP_DUMP: ::c_int = 0x04; pub const GENL_CMD_CAP_HASPOL: ::c_int = 0x08; pub const GENL_ID_CTRL: ::c_int = NLMSG_MIN_TYPE; pub const CTRL_CMD_UNSPEC: ::c_int = 0; pub const CTRL_CMD_NEWFAMILY: ::c_int = 1; pub const CTRL_CMD_DELFAMILY: ::c_int = 2; pub const CTRL_CMD_GETFAMILY: ::c_int = 3; pub const CTRL_CMD_NEWOPS: ::c_int = 4; pub const CTRL_CMD_DELOPS: ::c_int = 5; pub const CTRL_CMD_GETOPS: ::c_int = 6; pub const CTRL_CMD_NEWMCAST_GRP: ::c_int = 7; pub const CTRL_CMD_DELMCAST_GRP: ::c_int = 8; pub const CTRL_CMD_GETMCAST_GRP: ::c_int = 9; pub const CTRL_ATTR_UNSPEC: ::c_int = 0; pub const CTRL_ATTR_FAMILY_ID: ::c_int = 1; pub const CTRL_ATTR_FAMILY_NAME: ::c_int = 2; pub const CTRL_ATTR_VERSION: ::c_int = 3; pub const CTRL_ATTR_HDRSIZE: ::c_int = 4; pub const CTRL_ATTR_MAXATTR: ::c_int = 5; pub const CTRL_ATTR_OPS: ::c_int = 6; pub const CTRL_ATTR_MCAST_GROUPS: ::c_int = 7; pub const CTRL_ATTR_OP_UNSPEC: ::c_int = 0; pub const CTRL_ATTR_OP_ID: ::c_int = 1; pub const CTRL_ATTR_OP_FLAGS: ::c_int = 2; pub const CTRL_ATTR_MCAST_GRP_UNSPEC: ::c_int = 0; pub const CTRL_ATTR_MCAST_GRP_NAME: ::c_int = 1; pub const CTRL_ATTR_MCAST_GRP_ID: ::c_int = 2; // linux/if_packet.h pub const PACKET_ADD_MEMBERSHIP: ::c_int = 1; pub const PACKET_DROP_MEMBERSHIP: ::c_int = 2; pub const PACKET_MR_MULTICAST: ::c_int = 0; pub const PACKET_MR_PROMISC: ::c_int = 1; pub const PACKET_MR_ALLMULTI: ::c_int = 2; // linux/netfilter.h pub const NF_DROP: ::c_int = 0; pub const NF_ACCEPT: ::c_int = 1; pub const NF_STOLEN: ::c_int = 2; pub const NF_QUEUE: ::c_int = 3; pub const NF_REPEAT: ::c_int = 4; pub const NF_STOP: ::c_int = 5; pub const NF_MAX_VERDICT: ::c_int = NF_STOP; pub const NF_VERDICT_MASK: ::c_int = 0x000000ff; pub const NF_VERDICT_FLAG_QUEUE_BYPASS: ::c_int = 0x00008000; pub const NF_VERDICT_QMASK: ::c_int = 0xffff0000; pub const NF_VERDICT_QBITS: ::c_int = 16; pub const NF_VERDICT_BITS: ::c_int = 16; pub const NF_INET_PRE_ROUTING: ::c_int = 0; pub const NF_INET_LOCAL_IN: ::c_int = 1; pub const NF_INET_FORWARD: ::c_int = 2; pub const NF_INET_LOCAL_OUT: ::c_int = 3; pub const NF_INET_POST_ROUTING: ::c_int = 4; pub const NF_INET_NUMHOOKS: ::c_int = 5; // Some NFPROTO are not compatible with musl and are defined in submodules. pub const NFPROTO_UNSPEC: ::c_int = 0; pub const NFPROTO_IPV4: ::c_int = 2; pub const NFPROTO_ARP: ::c_int = 3; pub const NFPROTO_BRIDGE: ::c_int = 7; pub const NFPROTO_IPV6: ::c_int = 10; pub const NFPROTO_DECNET: ::c_int = 12; pub const NFPROTO_NUMPROTO: ::c_int = 13; pub const NFPROTO_INET: ::c_int = 1; pub const NFPROTO_NETDEV: ::c_int = 5; pub const NF_NETDEV_INGRESS: ::c_int = 0; pub const NF_NETDEV_NUMHOOKS: ::c_int = 1; // linux/netfilter_ipv4.h pub const NF_IP_PRE_ROUTING: ::c_int = 0; pub const NF_IP_LOCAL_IN: ::c_int = 1; pub const NF_IP_FORWARD: ::c_int = 2; pub const NF_IP_LOCAL_OUT: ::c_int = 3; pub const NF_IP_POST_ROUTING: ::c_int = 4; pub const NF_IP_NUMHOOKS: ::c_int = 5; pub const NF_IP_PRI_FIRST: ::c_int = ::INT_MIN; pub const NF_IP_PRI_CONNTRACK_DEFRAG: ::c_int = -400; pub const NF_IP_PRI_RAW: ::c_int = -300; pub const NF_IP_PRI_SELINUX_FIRST: ::c_int = -225; pub const NF_IP_PRI_CONNTRACK: ::c_int = -200; pub const NF_IP_PRI_MANGLE: ::c_int = -150; pub const NF_IP_PRI_NAT_DST: ::c_int = -100; pub const NF_IP_PRI_FILTER: ::c_int = 0; pub const NF_IP_PRI_SECURITY: ::c_int = 50; pub const NF_IP_PRI_NAT_SRC: ::c_int = 100; pub const NF_IP_PRI_SELINUX_LAST: ::c_int = 225; pub const NF_IP_PRI_CONNTRACK_HELPER: ::c_int = 300; pub const NF_IP_PRI_CONNTRACK_CONFIRM: ::c_int = ::INT_MAX; pub const NF_IP_PRI_LAST: ::c_int = ::INT_MAX; // linux/netfilter_ipv6.h pub const NF_IP6_PRE_ROUTING: ::c_int = 0; pub const NF_IP6_LOCAL_IN: ::c_int = 1; pub const NF_IP6_FORWARD: ::c_int = 2; pub const NF_IP6_LOCAL_OUT: ::c_int = 3; pub const NF_IP6_POST_ROUTING: ::c_int = 4; pub const NF_IP6_NUMHOOKS: ::c_int = 5; pub const NF_IP6_PRI_FIRST: ::c_int = ::INT_MIN; pub const NF_IP6_PRI_CONNTRACK_DEFRAG: ::c_int = -400; pub const NF_IP6_PRI_RAW: ::c_int = -300; pub const NF_IP6_PRI_SELINUX_FIRST: ::c_int = -225; pub const NF_IP6_PRI_CONNTRACK: ::c_int = -200; pub const NF_IP6_PRI_MANGLE: ::c_int = -150; pub const NF_IP6_PRI_NAT_DST: ::c_int = -100; pub const NF_IP6_PRI_FILTER: ::c_int = 0; pub const NF_IP6_PRI_SECURITY: ::c_int = 50; pub const NF_IP6_PRI_NAT_SRC: ::c_int = 100; pub const NF_IP6_PRI_SELINUX_LAST: ::c_int = 225; pub const NF_IP6_PRI_CONNTRACK_HELPER: ::c_int = 300; pub const NF_IP6_PRI_LAST: ::c_int = ::INT_MAX; // linux/netfilter_ipv6/ip6_tables.h pub const IP6T_SO_ORIGINAL_DST: ::c_int = 80; pub const SIOCADDRT: ::c_ulong = 0x0000890B; pub const SIOCDELRT: ::c_ulong = 0x0000890C; pub const SIOCGIFNAME: ::c_ulong = 0x00008910; pub const SIOCSIFLINK: ::c_ulong = 0x00008911; pub const SIOCGIFCONF: ::c_ulong = 0x00008912; pub const SIOCGIFFLAGS: ::c_ulong = 0x00008913; pub const SIOCSIFFLAGS: ::c_ulong = 0x00008914; pub const SIOCGIFADDR: ::c_ulong = 0x00008915; pub const SIOCSIFADDR: ::c_ulong = 0x00008916; pub const SIOCGIFDSTADDR: ::c_ulong = 0x00008917; pub const SIOCSIFDSTADDR: ::c_ulong = 0x00008918; pub const SIOCGIFBRDADDR: ::c_ulong = 0x00008919; pub const SIOCSIFBRDADDR: ::c_ulong = 0x0000891A; pub const SIOCGIFNETMASK: ::c_ulong = 0x0000891B; pub const SIOCSIFNETMASK: ::c_ulong = 0x0000891C; pub const SIOCGIFMETRIC: ::c_ulong = 0x0000891D; pub const SIOCSIFMETRIC: ::c_ulong = 0x0000891E; pub const SIOCGIFMEM: ::c_ulong = 0x0000891F; pub const SIOCSIFMEM: ::c_ulong = 0x00008920; pub const SIOCGIFMTU: ::c_ulong = 0x00008921; pub const SIOCSIFMTU: ::c_ulong = 0x00008922; pub const SIOCSIFNAME: ::c_ulong = 0x00008923; pub const SIOCSIFHWADDR: ::c_ulong = 0x00008924; pub const SIOCGIFENCAP: ::c_ulong = 0x00008925; pub const SIOCSIFENCAP: ::c_ulong = 0x00008926; pub const SIOCGIFHWADDR: ::c_ulong = 0x00008927; pub const SIOCGIFSLAVE: ::c_ulong = 0x00008929; pub const SIOCSIFSLAVE: ::c_ulong = 0x00008930; pub const SIOCADDMULTI: ::c_ulong = 0x00008931; pub const SIOCDELMULTI: ::c_ulong = 0x00008932; pub const SIOCGIFINDEX: ::c_ulong = 0x00008933; pub const SIOGIFINDEX: ::c_ulong = SIOCGIFINDEX; pub const SIOCSIFPFLAGS: ::c_ulong = 0x00008934; pub const SIOCGIFPFLAGS: ::c_ulong = 0x00008935; pub const SIOCDIFADDR: ::c_ulong = 0x00008936; pub const SIOCSIFHWBROADCAST: ::c_ulong = 0x00008937; pub const SIOCGIFCOUNT: ::c_ulong = 0x00008938; pub const SIOCGIFBR: ::c_ulong = 0x00008940; pub const SIOCSIFBR: ::c_ulong = 0x00008941; pub const SIOCGIFTXQLEN: ::c_ulong = 0x00008942; pub const SIOCSIFTXQLEN: ::c_ulong = 0x00008943; pub const SIOCETHTOOL: ::c_ulong = 0x00008946; pub const SIOCGMIIPHY: ::c_ulong = 0x00008947; pub const SIOCGMIIREG: ::c_ulong = 0x00008948; pub const SIOCSMIIREG: ::c_ulong = 0x00008949; pub const SIOCWANDEV: ::c_ulong = 0x0000894A; pub const SIOCOUTQNSD: ::c_ulong = 0x0000894B; pub const SIOCGSKNS: ::c_ulong = 0x0000894C; pub const SIOCDARP: ::c_ulong = 0x00008953; pub const SIOCGARP: ::c_ulong = 0x00008954; pub const SIOCSARP: ::c_ulong = 0x00008955; pub const SIOCDRARP: ::c_ulong = 0x00008960; pub const SIOCGRARP: ::c_ulong = 0x00008961; pub const SIOCSRARP: ::c_ulong = 0x00008962; pub const SIOCGIFMAP: ::c_ulong = 0x00008970; pub const SIOCSIFMAP: ::c_ulong = 0x00008971; pub const SIOCSHWTSTAMP: ::c_ulong = 0x000089b0; pub const SIOCGHWTSTAMP: ::c_ulong = 0x000089b1; // wireless.h pub const WIRELESS_EXT: ::c_ulong = 0x16; pub const SIOCSIWCOMMIT: ::c_ulong = 0x8B00; pub const SIOCGIWNAME: ::c_ulong = 0x8B01; pub const SIOCSIWNWID: ::c_ulong = 0x8B02; pub const SIOCGIWNWID: ::c_ulong = 0x8B03; pub const SIOCSIWFREQ: ::c_ulong = 0x8B04; pub const SIOCGIWFREQ: ::c_ulong = 0x8B05; pub const SIOCSIWMODE: ::c_ulong = 0x8B06; pub const SIOCGIWMODE: ::c_ulong = 0x8B07; pub const SIOCSIWSENS: ::c_ulong = 0x8B08; pub const SIOCGIWSENS: ::c_ulong = 0x8B09; pub const SIOCSIWRANGE: ::c_ulong = 0x8B0A; pub const SIOCGIWRANGE: ::c_ulong = 0x8B0B; pub const SIOCSIWPRIV: ::c_ulong = 0x8B0C; pub const SIOCGIWPRIV: ::c_ulong = 0x8B0D; pub const SIOCSIWSTATS: ::c_ulong = 0x8B0E; pub const SIOCGIWSTATS: ::c_ulong = 0x8B0F; pub const SIOCSIWSPY: ::c_ulong = 0x8B10; pub const SIOCGIWSPY: ::c_ulong = 0x8B11; pub const SIOCSIWTHRSPY: ::c_ulong = 0x8B12; pub const SIOCGIWTHRSPY: ::c_ulong = 0x8B13; pub const SIOCSIWAP: ::c_ulong = 0x8B14; pub const SIOCGIWAP: ::c_ulong = 0x8B15; pub const SIOCGIWAPLIST: ::c_ulong = 0x8B17; pub const SIOCSIWSCAN: ::c_ulong = 0x8B18; pub const SIOCGIWSCAN: ::c_ulong = 0x8B19; pub const SIOCSIWESSID: ::c_ulong = 0x8B1A; pub const SIOCGIWESSID: ::c_ulong = 0x8B1B; pub const SIOCSIWNICKN: ::c_ulong = 0x8B1C; pub const SIOCGIWNICKN: ::c_ulong = 0x8B1D; pub const SIOCSIWRATE: ::c_ulong = 0x8B20; pub const SIOCGIWRATE: ::c_ulong = 0x8B21; pub const SIOCSIWRTS: ::c_ulong = 0x8B22; pub const SIOCGIWRTS: ::c_ulong = 0x8B23; pub const SIOCSIWFRAG: ::c_ulong = 0x8B24; pub const SIOCGIWFRAG: ::c_ulong = 0x8B25; pub const SIOCSIWTXPOW: ::c_ulong = 0x8B26; pub const SIOCGIWTXPOW: ::c_ulong = 0x8B27; pub const SIOCSIWRETRY: ::c_ulong = 0x8B28; pub const SIOCGIWRETRY: ::c_ulong = 0x8B29; pub const SIOCSIWENCODE: ::c_ulong = 0x8B2A; pub const SIOCGIWENCODE: ::c_ulong = 0x8B2B; pub const SIOCSIWPOWER: ::c_ulong = 0x8B2C; pub const SIOCGIWPOWER: ::c_ulong = 0x8B2D; pub const SIOCSIWGENIE: ::c_ulong = 0x8B30; pub const SIOCGIWGENIE: ::c_ulong = 0x8B31; pub const SIOCSIWMLME: ::c_ulong = 0x8B16; pub const SIOCSIWAUTH: ::c_ulong = 0x8B32; pub const SIOCGIWAUTH: ::c_ulong = 0x8B33; pub const SIOCSIWENCODEEXT: ::c_ulong = 0x8B34; pub const SIOCGIWENCODEEXT: ::c_ulong = 0x8B35; pub const SIOCSIWPMKSA: ::c_ulong = 0x8B36; pub const SIOCIWFIRSTPRIV: ::c_ulong = 0x8BE0; pub const SIOCIWLASTPRIV: ::c_ulong = 0x8BFF; pub const SIOCIWFIRST: ::c_ulong = 0x8B00; pub const SIOCIWLAST: ::c_ulong = SIOCIWLASTPRIV; pub const IWEVTXDROP: ::c_ulong = 0x8C00; pub const IWEVQUAL: ::c_ulong = 0x8C01; pub const IWEVCUSTOM: ::c_ulong = 0x8C02; pub const IWEVREGISTERED: ::c_ulong = 0x8C03; pub const IWEVEXPIRED: ::c_ulong = 0x8C04; pub const IWEVGENIE: ::c_ulong = 0x8C05; pub const IWEVMICHAELMICFAILURE: ::c_ulong = 0x8C06; pub const IWEVASSOCREQIE: ::c_ulong = 0x8C07; pub const IWEVASSOCRESPIE: ::c_ulong = 0x8C08; pub const IWEVPMKIDCAND: ::c_ulong = 0x8C09; pub const IWEVFIRST: ::c_ulong = 0x8C00; pub const IW_PRIV_TYPE_MASK: ::c_ulong = 0x7000; pub const IW_PRIV_TYPE_NONE: ::c_ulong = 0x0000; pub const IW_PRIV_TYPE_BYTE: ::c_ulong = 0x1000; pub const IW_PRIV_TYPE_CHAR: ::c_ulong = 0x2000; pub const IW_PRIV_TYPE_INT: ::c_ulong = 0x4000; pub const IW_PRIV_TYPE_FLOAT: ::c_ulong = 0x5000; pub const IW_PRIV_TYPE_ADDR: ::c_ulong = 0x6000; pub const IW_PRIV_SIZE_FIXED: ::c_ulong = 0x0800; pub const IW_PRIV_SIZE_MASK: ::c_ulong = 0x07FF; pub const IW_MAX_FREQUENCIES: usize = 32; pub const IW_MAX_BITRATES: usize = 32; pub const IW_MAX_TXPOWER: usize = 8; pub const IW_MAX_SPY: usize = 8; pub const IW_MAX_AP: usize = 64; pub const IW_ESSID_MAX_SIZE: usize = 32; pub const IW_MODE_AUTO: usize = 0; pub const IW_MODE_ADHOC: usize = 1; pub const IW_MODE_INFRA: usize = 2; pub const IW_MODE_MASTER: usize = 3; pub const IW_MODE_REPEAT: usize = 4; pub const IW_MODE_SECOND: usize = 5; pub const IW_MODE_MONITOR: usize = 6; pub const IW_MODE_MESH: usize = 7; pub const IW_QUAL_QUAL_UPDATED: ::c_ulong = 0x01; pub const IW_QUAL_LEVEL_UPDATED: ::c_ulong = 0x02; pub const IW_QUAL_NOISE_UPDATED: ::c_ulong = 0x04; pub const IW_QUAL_ALL_UPDATED: ::c_ulong = 0x07; pub const IW_QUAL_DBM: ::c_ulong = 0x08; pub const IW_QUAL_QUAL_INVALID: ::c_ulong = 0x10; pub const IW_QUAL_LEVEL_INVALID: ::c_ulong = 0x20; pub const IW_QUAL_NOISE_INVALID: ::c_ulong = 0x40; pub const IW_QUAL_RCPI: ::c_ulong = 0x80; pub const IW_QUAL_ALL_INVALID: ::c_ulong = 0x70; pub const IW_FREQ_AUTO: ::c_ulong = 0x00; pub const IW_FREQ_FIXED: ::c_ulong = 0x01; pub const IW_MAX_ENCODING_SIZES: usize = 8; pub const IW_ENCODING_TOKEN_MAX: usize = 64; pub const IW_ENCODE_INDEX: ::c_ulong = 0x00FF; pub const IW_ENCODE_FLAGS: ::c_ulong = 0xFF00; pub const IW_ENCODE_MODE: ::c_ulong = 0xF000; pub const IW_ENCODE_DISABLED: ::c_ulong = 0x8000; pub const IW_ENCODE_ENABLED: ::c_ulong = 0x0000; pub const IW_ENCODE_RESTRICTED: ::c_ulong = 0x4000; pub const IW_ENCODE_OPEN: ::c_ulong = 0x2000; pub const IW_ENCODE_NOKEY: ::c_ulong = 0x0800; pub const IW_ENCODE_TEMP: ::c_ulong = 0x0400; pub const IW_POWER_ON: ::c_ulong = 0x0000; pub const IW_POWER_TYPE: ::c_ulong = 0xF000; pub const IW_POWER_PERIOD: ::c_ulong = 0x1000; pub const IW_POWER_TIMEOUT: ::c_ulong = 0x2000; pub const IW_POWER_MODE: ::c_ulong = 0x0F00; pub const IW_POWER_UNICAST_R: ::c_ulong = 0x0100; pub const IW_POWER_MULTICAST_R: ::c_ulong = 0x0200; pub const IW_POWER_ALL_R: ::c_ulong = 0x0300; pub const IW_POWER_FORCE_S: ::c_ulong = 0x0400; pub const IW_POWER_REPEATER: ::c_ulong = 0x0800; pub const IW_POWER_MODIFIER: ::c_ulong = 0x000F; pub const IW_POWER_MIN: ::c_ulong = 0x0001; pub const IW_POWER_MAX: ::c_ulong = 0x0002; pub const IW_POWER_RELATIVE: ::c_ulong = 0x0004; pub const IW_TXPOW_TYPE: ::c_ulong = 0x00FF; pub const IW_TXPOW_DBM: ::c_ulong = 0x0000; pub const IW_TXPOW_MWATT: ::c_ulong = 0x0001; pub const IW_TXPOW_RELATIVE: ::c_ulong = 0x0002; pub const IW_TXPOW_RANGE: ::c_ulong = 0x1000; pub const IW_RETRY_ON: ::c_ulong = 0x0000; pub const IW_RETRY_TYPE: ::c_ulong = 0xF000; pub const IW_RETRY_LIMIT: ::c_ulong = 0x1000; pub const IW_RETRY_LIFETIME: ::c_ulong = 0x2000; pub const IW_RETRY_MODIFIER: ::c_ulong = 0x00FF; pub const IW_RETRY_MIN: ::c_ulong = 0x0001; pub const IW_RETRY_MAX: ::c_ulong = 0x0002; pub const IW_RETRY_RELATIVE: ::c_ulong = 0x0004; pub const IW_RETRY_SHORT: ::c_ulong = 0x0010; pub const IW_RETRY_LONG: ::c_ulong = 0x0020; pub const IW_SCAN_DEFAULT: ::c_ulong = 0x0000; pub const IW_SCAN_ALL_ESSID: ::c_ulong = 0x0001; pub const IW_SCAN_THIS_ESSID: ::c_ulong = 0x0002; pub const IW_SCAN_ALL_FREQ: ::c_ulong = 0x0004; pub const IW_SCAN_THIS_FREQ: ::c_ulong = 0x0008; pub const IW_SCAN_ALL_MODE: ::c_ulong = 0x0010; pub const IW_SCAN_THIS_MODE: ::c_ulong = 0x0020; pub const IW_SCAN_ALL_RATE: ::c_ulong = 0x0040; pub const IW_SCAN_THIS_RATE: ::c_ulong = 0x0080; pub const IW_SCAN_TYPE_ACTIVE: usize = 0; pub const IW_SCAN_TYPE_PASSIVE: usize = 1; pub const IW_SCAN_MAX_DATA: usize = 4096; pub const IW_SCAN_CAPA_NONE: ::c_ulong = 0x00; pub const IW_SCAN_CAPA_ESSID: ::c_ulong = 0x01; pub const IW_SCAN_CAPA_BSSID: ::c_ulong = 0x02; pub const IW_SCAN_CAPA_CHANNEL: ::c_ulong = 0x04; pub const IW_SCAN_CAPA_MODE: ::c_ulong = 0x08; pub const IW_SCAN_CAPA_RATE: ::c_ulong = 0x10; pub const IW_SCAN_CAPA_TYPE: ::c_ulong = 0x20; pub const IW_SCAN_CAPA_TIME: ::c_ulong = 0x40; pub const IW_CUSTOM_MAX: ::c_ulong = 256; pub const IW_GENERIC_IE_MAX: ::c_ulong = 1024; pub const IW_MLME_DEAUTH: ::c_ulong = 0; pub const IW_MLME_DISASSOC: ::c_ulong = 1; pub const IW_MLME_AUTH: ::c_ulong = 2; pub const IW_MLME_ASSOC: ::c_ulong = 3; pub const IW_AUTH_INDEX: ::c_ulong = 0x0FFF; pub const IW_AUTH_FLAGS: ::c_ulong = 0xF000; pub const IW_AUTH_WPA_VERSION: usize = 0; pub const IW_AUTH_CIPHER_PAIRWISE: usize = 1; pub const IW_AUTH_CIPHER_GROUP: usize = 2; pub const IW_AUTH_KEY_MGMT: usize = 3; pub const IW_AUTH_TKIP_COUNTERMEASURES: usize = 4; pub const IW_AUTH_DROP_UNENCRYPTED: usize = 5; pub const IW_AUTH_80211_AUTH_ALG: usize = 6; pub const IW_AUTH_WPA_ENABLED: usize = 7; pub const IW_AUTH_RX_UNENCRYPTED_EAPOL: usize = 8; pub const IW_AUTH_ROAMING_CONTROL: usize = 9; pub const IW_AUTH_PRIVACY_INVOKED: usize = 10; pub const IW_AUTH_CIPHER_GROUP_MGMT: usize = 11; pub const IW_AUTH_MFP: usize = 12; pub const IW_AUTH_WPA_VERSION_DISABLED: ::c_ulong = 0x00000001; pub const IW_AUTH_WPA_VERSION_WPA: ::c_ulong = 0x00000002; pub const IW_AUTH_WPA_VERSION_WPA2: ::c_ulong = 0x00000004; pub const IW_AUTH_CIPHER_NONE: ::c_ulong = 0x00000001; pub const IW_AUTH_CIPHER_WEP40: ::c_ulong = 0x00000002; pub const IW_AUTH_CIPHER_TKIP: ::c_ulong = 0x00000004; pub const IW_AUTH_CIPHER_CCMP: ::c_ulong = 0x00000008; pub const IW_AUTH_CIPHER_WEP104: ::c_ulong = 0x00000010; pub const IW_AUTH_CIPHER_AES_CMAC: ::c_ulong = 0x00000020; pub const IW_AUTH_KEY_MGMT_802_1X: usize = 1; pub const IW_AUTH_KEY_MGMT_PSK: usize = 2; pub const IW_AUTH_ALG_OPEN_SYSTEM: ::c_ulong = 0x00000001; pub const IW_AUTH_ALG_SHARED_KEY: ::c_ulong = 0x00000002; pub const IW_AUTH_ALG_LEAP: ::c_ulong = 0x00000004; pub const IW_AUTH_ROAMING_ENABLE: usize = 0; pub const IW_AUTH_ROAMING_DISABLE: usize = 1; pub const IW_AUTH_MFP_DISABLED: usize = 0; pub const IW_AUTH_MFP_OPTIONAL: usize = 1; pub const IW_AUTH_MFP_REQUIRED: usize = 2; pub const IW_ENCODE_SEQ_MAX_SIZE: usize = 8; pub const IW_ENCODE_ALG_NONE: usize = 0; pub const IW_ENCODE_ALG_WEP: usize = 1; pub const IW_ENCODE_ALG_TKIP: usize = 2; pub const IW_ENCODE_ALG_CCMP: usize = 3; pub const IW_ENCODE_ALG_PMK: usize = 4; pub const IW_ENCODE_ALG_AES_CMAC: usize = 5; pub const IW_ENCODE_EXT_TX_SEQ_VALID: ::c_ulong = 0x00000001; pub const IW_ENCODE_EXT_RX_SEQ_VALID: ::c_ulong = 0x00000002; pub const IW_ENCODE_EXT_GROUP_KEY: ::c_ulong = 0x00000004; pub const IW_ENCODE_EXT_SET_TX_KEY: ::c_ulong = 0x00000008; pub const IW_MICFAILURE_KEY_ID: ::c_ulong = 0x00000003; pub const IW_MICFAILURE_GROUP: ::c_ulong = 0x00000004; pub const IW_MICFAILURE_PAIRWISE: ::c_ulong = 0x00000008; pub const IW_MICFAILURE_STAKEY: ::c_ulong = 0x00000010; pub const IW_MICFAILURE_COUNT: ::c_ulong = 0x00000060; pub const IW_ENC_CAPA_WPA: ::c_ulong = 0x00000001; pub const IW_ENC_CAPA_WPA2: ::c_ulong = 0x00000002; pub const IW_ENC_CAPA_CIPHER_TKIP: ::c_ulong = 0x00000004; pub const IW_ENC_CAPA_CIPHER_CCMP: ::c_ulong = 0x00000008; pub const IW_ENC_CAPA_4WAY_HANDSHAKE: ::c_ulong = 0x00000010; pub const IW_PMKSA_ADD: usize = 1; pub const IW_PMKSA_REMOVE: usize = 2; pub const IW_PMKSA_FLUSH: usize = 3; pub const IW_PMKID_LEN: usize = 16; pub const IW_PMKID_CAND_PREAUTH: ::c_ulong = 0x00000001; pub const IW_EV_LCP_PK_LEN: usize = 4; pub const IW_EV_CHAR_PK_LEN: usize = IW_EV_LCP_PK_LEN + ::IFNAMSIZ; pub const IW_EV_POINT_PK_LEN: usize = IW_EV_LCP_PK_LEN + 4; pub const IPTOS_TOS_MASK: u8 = 0x1E; pub const IPTOS_PREC_MASK: u8 = 0xE0; pub const IPTOS_ECN_NOT_ECT: u8 = 0x00; pub const RTF_UP: ::c_ushort = 0x0001; pub const RTF_GATEWAY: ::c_ushort = 0x0002; pub const RTF_HOST: ::c_ushort = 0x0004; pub const RTF_REINSTATE: ::c_ushort = 0x0008; pub const RTF_DYNAMIC: ::c_ushort = 0x0010; pub const RTF_MODIFIED: ::c_ushort = 0x0020; pub const RTF_MTU: ::c_ushort = 0x0040; pub const RTF_MSS: ::c_ushort = RTF_MTU; pub const RTF_WINDOW: ::c_ushort = 0x0080; pub const RTF_IRTT: ::c_ushort = 0x0100; pub const RTF_REJECT: ::c_ushort = 0x0200; pub const RTF_STATIC: ::c_ushort = 0x0400; pub const RTF_XRESOLVE: ::c_ushort = 0x0800; pub const RTF_NOFORWARD: ::c_ushort = 0x1000; pub const RTF_THROW: ::c_ushort = 0x2000; pub const RTF_NOPMTUDISC: ::c_ushort = 0x4000; pub const RTF_DEFAULT: u32 = 0x00010000; pub const RTF_ALLONLINK: u32 = 0x00020000; pub const RTF_ADDRCONF: u32 = 0x00040000; pub const RTF_LINKRT: u32 = 0x00100000; pub const RTF_NONEXTHOP: u32 = 0x00200000; pub const RTF_CACHE: u32 = 0x01000000; pub const RTF_FLOW: u32 = 0x02000000; pub const RTF_POLICY: u32 = 0x04000000; pub const RTCF_VALVE: u32 = 0x00200000; pub const RTCF_MASQ: u32 = 0x00400000; pub const RTCF_NAT: u32 = 0x00800000; pub const RTCF_DOREDIRECT: u32 = 0x01000000; pub const RTCF_LOG: u32 = 0x02000000; pub const RTCF_DIRECTSRC: u32 = 0x04000000; pub const RTF_LOCAL: u32 = 0x80000000; pub const RTF_INTERFACE: u32 = 0x40000000; pub const RTF_MULTICAST: u32 = 0x20000000; pub const RTF_BROADCAST: u32 = 0x10000000; pub const RTF_NAT: u32 = 0x08000000; pub const RTF_ADDRCLASSMASK: u32 = 0xF8000000; pub const RT_CLASS_UNSPEC: u8 = 0; pub const RT_CLASS_DEFAULT: u8 = 253; pub const RT_CLASS_MAIN: u8 = 254; pub const RT_CLASS_LOCAL: u8 = 255; pub const RT_CLASS_MAX: u8 = 255; // linux/neighbor.h pub const NUD_NONE: u16 = 0x00; pub const NUD_INCOMPLETE: u16 = 0x01; pub const NUD_REACHABLE: u16 = 0x02; pub const NUD_STALE: u16 = 0x04; pub const NUD_DELAY: u16 = 0x08; pub const NUD_PROBE: u16 = 0x10; pub const NUD_FAILED: u16 = 0x20; pub const NUD_NOARP: u16 = 0x40; pub const NUD_PERMANENT: u16 = 0x80; pub const NTF_USE: u8 = 0x01; pub const NTF_SELF: u8 = 0x02; pub const NTF_MASTER: u8 = 0x04; pub const NTF_PROXY: u8 = 0x08; pub const NTF_ROUTER: u8 = 0x80; pub const NDA_UNSPEC: ::c_ushort = 0; pub const NDA_DST: ::c_ushort = 1; pub const NDA_LLADDR: ::c_ushort = 2; pub const NDA_CACHEINFO: ::c_ushort = 3; pub const NDA_PROBES: ::c_ushort = 4; pub const NDA_VLAN: ::c_ushort = 5; pub const NDA_PORT: ::c_ushort = 6; pub const NDA_VNI: ::c_ushort = 7; pub const NDA_IFINDEX: ::c_ushort = 8; // linux/netlink.h pub const NLA_ALIGNTO: ::c_int = 4; pub const NETLINK_ROUTE: ::c_int = 0; pub const NETLINK_UNUSED: ::c_int = 1; pub const NETLINK_USERSOCK: ::c_int = 2; pub const NETLINK_FIREWALL: ::c_int = 3; pub const NETLINK_SOCK_DIAG: ::c_int = 4; pub const NETLINK_NFLOG: ::c_int = 5; pub const NETLINK_XFRM: ::c_int = 6; pub const NETLINK_SELINUX: ::c_int = 7; pub const NETLINK_ISCSI: ::c_int = 8; pub const NETLINK_AUDIT: ::c_int = 9; pub const NETLINK_FIB_LOOKUP: ::c_int = 10; pub const NETLINK_CONNECTOR: ::c_int = 11; pub const NETLINK_NETFILTER: ::c_int = 12; pub const NETLINK_IP6_FW: ::c_int = 13; pub const NETLINK_DNRTMSG: ::c_int = 14; pub const NETLINK_KOBJECT_UEVENT: ::c_int = 15; pub const NETLINK_GENERIC: ::c_int = 16; pub const NETLINK_SCSITRANSPORT: ::c_int = 18; pub const NETLINK_ECRYPTFS: ::c_int = 19; pub const NETLINK_RDMA: ::c_int = 20; pub const NETLINK_CRYPTO: ::c_int = 21; pub const NETLINK_INET_DIAG: ::c_int = NETLINK_SOCK_DIAG; pub const NLM_F_REQUEST: ::c_int = 1; pub const NLM_F_MULTI: ::c_int = 2; pub const NLM_F_ACK: ::c_int = 4; pub const NLM_F_ECHO: ::c_int = 8; pub const NLM_F_DUMP_INTR: ::c_int = 16; pub const NLM_F_DUMP_FILTERED: ::c_int = 32; pub const NLM_F_ROOT: ::c_int = 0x100; pub const NLM_F_MATCH: ::c_int = 0x200; pub const NLM_F_ATOMIC: ::c_int = 0x400; pub const NLM_F_DUMP: ::c_int = NLM_F_ROOT | NLM_F_MATCH; pub const NLM_F_REPLACE: ::c_int = 0x100; pub const NLM_F_EXCL: ::c_int = 0x200; pub const NLM_F_CREATE: ::c_int = 0x400; pub const NLM_F_APPEND: ::c_int = 0x800; pub const NETLINK_ADD_MEMBERSHIP: ::c_int = 1; pub const NETLINK_DROP_MEMBERSHIP: ::c_int = 2; pub const NETLINK_PKTINFO: ::c_int = 3; pub const NETLINK_BROADCAST_ERROR: ::c_int = 4; pub const NETLINK_NO_ENOBUFS: ::c_int = 5; pub const NETLINK_RX_RING: ::c_int = 6; pub const NETLINK_TX_RING: ::c_int = 7; pub const NETLINK_LISTEN_ALL_NSID: ::c_int = 8; pub const NETLINK_LIST_MEMBERSHIPS: ::c_int = 9; pub const NETLINK_CAP_ACK: ::c_int = 10; pub const NETLINK_EXT_ACK: ::c_int = 11; pub const NETLINK_GET_STRICT_CHK: ::c_int = 12; pub const NLA_F_NESTED: ::c_int = 1 << 15; pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14; pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); // linux/rtnetlink.h pub const TCA_UNSPEC: ::c_ushort = 0; pub const TCA_KIND: ::c_ushort = 1; pub const TCA_OPTIONS: ::c_ushort = 2; pub const TCA_STATS: ::c_ushort = 3; pub const TCA_XSTATS: ::c_ushort = 4; pub const TCA_RATE: ::c_ushort = 5; pub const TCA_FCNT: ::c_ushort = 6; pub const TCA_STATS2: ::c_ushort = 7; pub const TCA_STAB: ::c_ushort = 8; pub const RTM_NEWLINK: u16 = 16; pub const RTM_DELLINK: u16 = 17; pub const RTM_GETLINK: u16 = 18; pub const RTM_SETLINK: u16 = 19; pub const RTM_NEWADDR: u16 = 20; pub const RTM_DELADDR: u16 = 21; pub const RTM_GETADDR: u16 = 22; pub const RTM_NEWROUTE: u16 = 24; pub const RTM_DELROUTE: u16 = 25; pub const RTM_GETROUTE: u16 = 26; pub const RTM_NEWNEIGH: u16 = 28; pub const RTM_DELNEIGH: u16 = 29; pub const RTM_GETNEIGH: u16 = 30; pub const RTM_NEWRULE: u16 = 32; pub const RTM_DELRULE: u16 = 33; pub const RTM_GETRULE: u16 = 34; pub const RTM_NEWQDISC: u16 = 36; pub const RTM_DELQDISC: u16 = 37; pub const RTM_GETQDISC: u16 = 38; pub const RTM_NEWTCLASS: u16 = 40; pub const RTM_DELTCLASS: u16 = 41; pub const RTM_GETTCLASS: u16 = 42; pub const RTM_NEWTFILTER: u16 = 44; pub const RTM_DELTFILTER: u16 = 45; pub const RTM_GETTFILTER: u16 = 46; pub const RTM_NEWACTION: u16 = 48; pub const RTM_DELACTION: u16 = 49; pub const RTM_GETACTION: u16 = 50; pub const RTM_NEWPREFIX: u16 = 52; pub const RTM_GETMULTICAST: u16 = 58; pub const RTM_GETANYCAST: u16 = 62; pub const RTM_NEWNEIGHTBL: u16 = 64; pub const RTM_GETNEIGHTBL: u16 = 66; pub const RTM_SETNEIGHTBL: u16 = 67; pub const RTM_NEWNDUSEROPT: u16 = 68; pub const RTM_NEWADDRLABEL: u16 = 72; pub const RTM_DELADDRLABEL: u16 = 73; pub const RTM_GETADDRLABEL: u16 = 74; pub const RTM_GETDCB: u16 = 78; pub const RTM_SETDCB: u16 = 79; pub const RTM_NEWNETCONF: u16 = 80; pub const RTM_GETNETCONF: u16 = 82; pub const RTM_NEWMDB: u16 = 84; pub const RTM_DELMDB: u16 = 85; pub const RTM_GETMDB: u16 = 86; pub const RTM_NEWNSID: u16 = 88; pub const RTM_DELNSID: u16 = 89; pub const RTM_GETNSID: u16 = 90; pub const RTM_F_NOTIFY: ::c_uint = 0x100; pub const RTM_F_CLONED: ::c_uint = 0x200; pub const RTM_F_EQUALIZE: ::c_uint = 0x400; pub const RTM_F_PREFIX: ::c_uint = 0x800; pub const RTA_UNSPEC: ::c_ushort = 0; pub const RTA_DST: ::c_ushort = 1; pub const RTA_SRC: ::c_ushort = 2; pub const RTA_IIF: ::c_ushort = 3; pub const RTA_OIF: ::c_ushort = 4; pub const RTA_GATEWAY: ::c_ushort = 5; pub const RTA_PRIORITY: ::c_ushort = 6; pub const RTA_PREFSRC: ::c_ushort = 7; pub const RTA_METRICS: ::c_ushort = 8; pub const RTA_MULTIPATH: ::c_ushort = 9; pub const RTA_PROTOINFO: ::c_ushort = 10; // No longer used pub const RTA_FLOW: ::c_ushort = 11; pub const RTA_CACHEINFO: ::c_ushort = 12; pub const RTA_SESSION: ::c_ushort = 13; // No longer used pub const RTA_MP_ALGO: ::c_ushort = 14; // No longer used pub const RTA_TABLE: ::c_ushort = 15; pub const RTA_MARK: ::c_ushort = 16; pub const RTA_MFC_STATS: ::c_ushort = 17; pub const RTN_UNSPEC: ::c_uchar = 0; pub const RTN_UNICAST: ::c_uchar = 1; pub const RTN_LOCAL: ::c_uchar = 2; pub const RTN_BROADCAST: ::c_uchar = 3; pub const RTN_ANYCAST: ::c_uchar = 4; pub const RTN_MULTICAST: ::c_uchar = 5; pub const RTN_BLACKHOLE: ::c_uchar = 6; pub const RTN_UNREACHABLE: ::c_uchar = 7; pub const RTN_PROHIBIT: ::c_uchar = 8; pub const RTN_THROW: ::c_uchar = 9; pub const RTN_NAT: ::c_uchar = 10; pub const RTN_XRESOLVE: ::c_uchar = 11; pub const RTPROT_UNSPEC: ::c_uchar = 0; pub const RTPROT_REDIRECT: ::c_uchar = 1; pub const RTPROT_KERNEL: ::c_uchar = 2; pub const RTPROT_BOOT: ::c_uchar = 3; pub const RTPROT_STATIC: ::c_uchar = 4; pub const RT_SCOPE_UNIVERSE: ::c_uchar = 0; pub const RT_SCOPE_SITE: ::c_uchar = 200; pub const RT_SCOPE_LINK: ::c_uchar = 253; pub const RT_SCOPE_HOST: ::c_uchar = 254; pub const RT_SCOPE_NOWHERE: ::c_uchar = 255; pub const RT_TABLE_UNSPEC: ::c_uchar = 0; pub const RT_TABLE_COMPAT: ::c_uchar = 252; pub const RT_TABLE_DEFAULT: ::c_uchar = 253; pub const RT_TABLE_MAIN: ::c_uchar = 254; pub const RT_TABLE_LOCAL: ::c_uchar = 255; pub const RTMSG_OVERRUN: u32 = ::NLMSG_OVERRUN as u32; pub const RTMSG_NEWDEVICE: u32 = 0x11; pub const RTMSG_DELDEVICE: u32 = 0x12; pub const RTMSG_NEWROUTE: u32 = 0x21; pub const RTMSG_DELROUTE: u32 = 0x22; pub const RTMSG_NEWRULE: u32 = 0x31; pub const RTMSG_DELRULE: u32 = 0x32; pub const RTMSG_CONTROL: u32 = 0x40; pub const RTMSG_AR_FAILED: u32 = 0x51; pub const MAX_ADDR_LEN: usize = 7; pub const ARPD_UPDATE: ::c_ushort = 0x01; pub const ARPD_LOOKUP: ::c_ushort = 0x02; pub const ARPD_FLUSH: ::c_ushort = 0x03; pub const ATF_MAGIC: ::c_int = 0x80; pub const RTEXT_FILTER_VF: ::c_int = 1 << 0; pub const RTEXT_FILTER_BRVLAN: ::c_int = 1 << 1; pub const RTEXT_FILTER_BRVLAN_COMPRESSED: ::c_int = 1 << 2; pub const RTEXT_FILTER_SKIP_STATS: ::c_int = 1 << 3; pub const RTEXT_FILTER_MRP: ::c_int = 1 << 4; pub const RTEXT_FILTER_CFM_CONFIG: ::c_int = 1 << 5; pub const RTEXT_FILTER_CFM_STATUS: ::c_int = 1 << 6; // userspace compat definitions for RTNLGRP_* pub const RTMGRP_LINK: ::c_int = 0x00001; pub const RTMGRP_NOTIFY: ::c_int = 0x00002; pub const RTMGRP_NEIGH: ::c_int = 0x00004; pub const RTMGRP_TC: ::c_int = 0x00008; pub const RTMGRP_IPV4_IFADDR: ::c_int = 0x00010; pub const RTMGRP_IPV4_MROUTE: ::c_int = 0x00020; pub const RTMGRP_IPV4_ROUTE: ::c_int = 0x00040; pub const RTMGRP_IPV4_RULE: ::c_int = 0x00080; pub const RTMGRP_IPV6_IFADDR: ::c_int = 0x00100; pub const RTMGRP_IPV6_MROUTE: ::c_int = 0x00200; pub const RTMGRP_IPV6_ROUTE: ::c_int = 0x00400; pub const RTMGRP_IPV6_IFINFO: ::c_int = 0x00800; pub const RTMGRP_DECnet_IFADDR: ::c_int = 0x01000; pub const RTMGRP_DECnet_ROUTE: ::c_int = 0x04000; pub const RTMGRP_IPV6_PREFIX: ::c_int = 0x20000; // enum rtnetlink_groups pub const RTNLGRP_NONE: ::c_uint = 0x00; pub const RTNLGRP_LINK: ::c_uint = 0x01; pub const RTNLGRP_NOTIFY: ::c_uint = 0x02; pub const RTNLGRP_NEIGH: ::c_uint = 0x03; pub const RTNLGRP_TC: ::c_uint = 0x04; pub const RTNLGRP_IPV4_IFADDR: ::c_uint = 0x05; pub const RTNLGRP_IPV4_MROUTE: ::c_uint = 0x06; pub const RTNLGRP_IPV4_ROUTE: ::c_uint = 0x07; pub const RTNLGRP_IPV4_RULE: ::c_uint = 0x08; pub const RTNLGRP_IPV6_IFADDR: ::c_uint = 0x09; pub const RTNLGRP_IPV6_MROUTE: ::c_uint = 0x0a; pub const RTNLGRP_IPV6_ROUTE: ::c_uint = 0x0b; pub const RTNLGRP_IPV6_IFINFO: ::c_uint = 0x0c; pub const RTNLGRP_DECnet_IFADDR: ::c_uint = 0x0d; pub const RTNLGRP_NOP2: ::c_uint = 0x0e; pub const RTNLGRP_DECnet_ROUTE: ::c_uint = 0x0f; pub const RTNLGRP_DECnet_RULE: ::c_uint = 0x10; pub const RTNLGRP_NOP4: ::c_uint = 0x11; pub const RTNLGRP_IPV6_PREFIX: ::c_uint = 0x12; pub const RTNLGRP_IPV6_RULE: ::c_uint = 0x13; pub const RTNLGRP_ND_USEROPT: ::c_uint = 0x14; pub const RTNLGRP_PHONET_IFADDR: ::c_uint = 0x15; pub const RTNLGRP_PHONET_ROUTE: ::c_uint = 0x16; pub const RTNLGRP_DCB: ::c_uint = 0x17; pub const RTNLGRP_IPV4_NETCONF: ::c_uint = 0x18; pub const RTNLGRP_IPV6_NETCONF: ::c_uint = 0x19; pub const RTNLGRP_MDB: ::c_uint = 0x1a; pub const RTNLGRP_MPLS_ROUTE: ::c_uint = 0x1b; pub const RTNLGRP_NSID: ::c_uint = 0x1c; pub const RTNLGRP_MPLS_NETCONF: ::c_uint = 0x1d; pub const RTNLGRP_IPV4_MROUTE_R: ::c_uint = 0x1e; pub const RTNLGRP_IPV6_MROUTE_R: ::c_uint = 0x1f; pub const RTNLGRP_NEXTHOP: ::c_uint = 0x20; pub const RTNLGRP_BRVLAN: ::c_uint = 0x21; pub const RTNLGRP_MCTP_IFADDR: ::c_uint = 0x22; pub const RTNLGRP_TUNNEL: ::c_uint = 0x23; pub const RTNLGRP_STATS: ::c_uint = 0x24; // linux/module.h pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001; pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002; // linux/net_tstamp.h pub const SOF_TIMESTAMPING_TX_HARDWARE: ::c_uint = 1 << 0; pub const SOF_TIMESTAMPING_TX_SOFTWARE: ::c_uint = 1 << 1; pub const SOF_TIMESTAMPING_RX_HARDWARE: ::c_uint = 1 << 2; pub const SOF_TIMESTAMPING_RX_SOFTWARE: ::c_uint = 1 << 3; pub const SOF_TIMESTAMPING_SOFTWARE: ::c_uint = 1 << 4; pub const SOF_TIMESTAMPING_SYS_HARDWARE: ::c_uint = 1 << 5; pub const SOF_TIMESTAMPING_RAW_HARDWARE: ::c_uint = 1 << 6; pub const SOF_TIMESTAMPING_OPT_ID: ::c_uint = 1 << 7; pub const SOF_TIMESTAMPING_TX_SCHED: ::c_uint = 1 << 8; pub const SOF_TIMESTAMPING_TX_ACK: ::c_uint = 1 << 9; pub const SOF_TIMESTAMPING_OPT_CMSG: ::c_uint = 1 << 10; pub const SOF_TIMESTAMPING_OPT_TSONLY: ::c_uint = 1 << 11; pub const SOF_TIMESTAMPING_OPT_STATS: ::c_uint = 1 << 12; pub const SOF_TIMESTAMPING_OPT_PKTINFO: ::c_uint = 1 << 13; pub const SOF_TIMESTAMPING_OPT_TX_SWHW: ::c_uint = 1 << 14; pub const SOF_TXTIME_DEADLINE_MODE: u32 = 1 << 0; pub const SOF_TXTIME_REPORT_ERRORS: u32 = 1 << 1; pub const HWTSTAMP_TX_OFF: ::c_uint = 0; pub const HWTSTAMP_TX_ON: ::c_uint = 1; pub const HWTSTAMP_TX_ONESTEP_SYNC: ::c_uint = 2; pub const HWTSTAMP_TX_ONESTEP_P2P: ::c_uint = 3; pub const HWTSTAMP_FILTER_NONE: ::c_uint = 0; pub const HWTSTAMP_FILTER_ALL: ::c_uint = 1; pub const HWTSTAMP_FILTER_SOME: ::c_uint = 2; pub const HWTSTAMP_FILTER_PTP_V1_L4_EVENT: ::c_uint = 3; pub const HWTSTAMP_FILTER_PTP_V1_L4_SYNC: ::c_uint = 4; pub const HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: ::c_uint = 5; pub const HWTSTAMP_FILTER_PTP_V2_L4_EVENT: ::c_uint = 6; pub const HWTSTAMP_FILTER_PTP_V2_L4_SYNC: ::c_uint = 7; pub const HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: ::c_uint = 8; pub const HWTSTAMP_FILTER_PTP_V2_L2_EVENT: ::c_uint = 9; pub const HWTSTAMP_FILTER_PTP_V2_L2_SYNC: ::c_uint = 10; pub const HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: ::c_uint = 11; pub const HWTSTAMP_FILTER_PTP_V2_EVENT: ::c_uint = 12; pub const HWTSTAMP_FILTER_PTP_V2_SYNC: ::c_uint = 13; pub const HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: ::c_uint = 14; pub const HWTSTAMP_FILTER_NTP_ALL: ::c_uint = 15; // linux/tls.h pub const TLS_TX: ::c_int = 1; pub const TLS_RX: ::c_int = 2; pub const TLS_1_2_VERSION_MAJOR: ::__u8 = 0x3; pub const TLS_1_2_VERSION_MINOR: ::__u8 = 0x3; pub const TLS_1_2_VERSION: ::__u16 = ((TLS_1_2_VERSION_MAJOR as ::__u16) << 8) | (TLS_1_2_VERSION_MINOR as ::__u16); pub const TLS_1_3_VERSION_MAJOR: ::__u8 = 0x3; pub const TLS_1_3_VERSION_MINOR: ::__u8 = 0x4; pub const TLS_1_3_VERSION: ::__u16 = ((TLS_1_3_VERSION_MAJOR as ::__u16) << 8) | (TLS_1_3_VERSION_MINOR as ::__u16); pub const TLS_CIPHER_AES_GCM_128: ::__u16 = 51; pub const TLS_CIPHER_AES_GCM_128_IV_SIZE: usize = 8; pub const TLS_CIPHER_AES_GCM_128_KEY_SIZE: usize = 16; pub const TLS_CIPHER_AES_GCM_128_SALT_SIZE: usize = 4; pub const TLS_CIPHER_AES_GCM_128_TAG_SIZE: usize = 16; pub const TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_AES_GCM_256: ::__u16 = 52; pub const TLS_CIPHER_AES_GCM_256_IV_SIZE: usize = 8; pub const TLS_CIPHER_AES_GCM_256_KEY_SIZE: usize = 32; pub const TLS_CIPHER_AES_GCM_256_SALT_SIZE: usize = 4; pub const TLS_CIPHER_AES_GCM_256_TAG_SIZE: usize = 16; pub const TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE: usize = 8; pub const TLS_CIPHER_CHACHA20_POLY1305: ::__u16 = 54; pub const TLS_CIPHER_CHACHA20_POLY1305_IV_SIZE: usize = 12; pub const TLS_CIPHER_CHACHA20_POLY1305_KEY_SIZE: usize = 32; pub const TLS_CIPHER_CHACHA20_POLY1305_SALT_SIZE: usize = 0; pub const TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE: usize = 16; pub const TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE: usize = 8; pub const TLS_SET_RECORD_TYPE: ::c_int = 1; pub const TLS_GET_RECORD_TYPE: ::c_int = 2; pub const SOL_TLS: ::c_int = 282; // linux/if_alg.h pub const ALG_SET_KEY: ::c_int = 1; pub const ALG_SET_IV: ::c_int = 2; pub const ALG_SET_OP: ::c_int = 3; pub const ALG_SET_AEAD_ASSOCLEN: ::c_int = 4; pub const ALG_SET_AEAD_AUTHSIZE: ::c_int = 5; pub const ALG_SET_DRBG_ENTROPY: ::c_int = 6; pub const ALG_SET_KEY_BY_KEY_SERIAL: ::c_int = 7; pub const ALG_OP_DECRYPT: ::c_int = 0; pub const ALG_OP_ENCRYPT: ::c_int = 1; // include/uapi/linux/if.h pub const IF_OPER_UNKNOWN: ::c_int = 0; pub const IF_OPER_NOTPRESENT: ::c_int = 1; pub const IF_OPER_DOWN: ::c_int = 2; pub const IF_OPER_LOWERLAYERDOWN: ::c_int = 3; pub const IF_OPER_TESTING: ::c_int = 4; pub const IF_OPER_DORMANT: ::c_int = 5; pub const IF_OPER_UP: ::c_int = 6; pub const IF_LINK_MODE_DEFAULT: ::c_int = 0; pub const IF_LINK_MODE_DORMANT: ::c_int = 1; pub const IF_LINK_MODE_TESTING: ::c_int = 2; // include/uapi/linux/udp.h pub const UDP_CORK: ::c_int = 1; pub const UDP_ENCAP: ::c_int = 100; pub const UDP_NO_CHECK6_TX: ::c_int = 101; pub const UDP_NO_CHECK6_RX: ::c_int = 102; // include/uapi/linux/mman.h pub const MAP_SHARED_VALIDATE: ::c_int = 0x3; // include/uapi/asm-generic/mman-common.h pub const MAP_FIXED_NOREPLACE: ::c_int = 0x100000; pub const MLOCK_ONFAULT: ::c_uint = 0x01; // uapi/linux/vm_sockets.h pub const VMADDR_CID_ANY: ::c_uint = 0xFFFFFFFF; pub const VMADDR_CID_HYPERVISOR: ::c_uint = 0; #[deprecated( since = "0.2.74", note = "VMADDR_CID_RESERVED is removed since Linux v5.6 and \ replaced with VMADDR_CID_LOCAL" )] pub const VMADDR_CID_RESERVED: ::c_uint = 1; pub const VMADDR_CID_LOCAL: ::c_uint = 1; pub const VMADDR_CID_HOST: ::c_uint = 2; pub const VMADDR_PORT_ANY: ::c_uint = 0xFFFFFFFF; // uapi/linux/inotify.h pub const IN_ACCESS: u32 = 0x0000_0001; pub const IN_MODIFY: u32 = 0x0000_0002; pub const IN_ATTRIB: u32 = 0x0000_0004; pub const IN_CLOSE_WRITE: u32 = 0x0000_0008; pub const IN_CLOSE_NOWRITE: u32 = 0x0000_0010; pub const IN_CLOSE: u32 = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE; pub const IN_OPEN: u32 = 0x0000_0020; pub const IN_MOVED_FROM: u32 = 0x0000_0040; pub const IN_MOVED_TO: u32 = 0x0000_0080; pub const IN_MOVE: u32 = IN_MOVED_FROM | IN_MOVED_TO; pub const IN_CREATE: u32 = 0x0000_0100; pub const IN_DELETE: u32 = 0x0000_0200; pub const IN_DELETE_SELF: u32 = 0x0000_0400; pub const IN_MOVE_SELF: u32 = 0x0000_0800; pub const IN_UNMOUNT: u32 = 0x0000_2000; pub const IN_Q_OVERFLOW: u32 = 0x0000_4000; pub const IN_IGNORED: u32 = 0x0000_8000; pub const IN_ONLYDIR: u32 = 0x0100_0000; pub const IN_DONT_FOLLOW: u32 = 0x0200_0000; pub const IN_EXCL_UNLINK: u32 = 0x0400_0000; // linux/keyctl.h pub const KEY_SPEC_THREAD_KEYRING: i32 = -1; pub const KEY_SPEC_PROCESS_KEYRING: i32 = -2; pub const KEY_SPEC_SESSION_KEYRING: i32 = -3; pub const KEY_SPEC_USER_KEYRING: i32 = -4; pub const KEY_SPEC_USER_SESSION_KEYRING: i32 = -5; pub const KEY_SPEC_GROUP_KEYRING: i32 = -6; pub const KEY_SPEC_REQKEY_AUTH_KEY: i32 = -7; pub const KEY_SPEC_REQUESTOR_KEYRING: i32 = -8; pub const KEY_REQKEY_DEFL_NO_CHANGE: i32 = -1; pub const KEY_REQKEY_DEFL_DEFAULT: i32 = 0; pub const KEY_REQKEY_DEFL_THREAD_KEYRING: i32 = 1; pub const KEY_REQKEY_DEFL_PROCESS_KEYRING: i32 = 2; pub const KEY_REQKEY_DEFL_SESSION_KEYRING: i32 = 3; pub const KEY_REQKEY_DEFL_USER_KEYRING: i32 = 4; pub const KEY_REQKEY_DEFL_USER_SESSION_KEYRING: i32 = 5; pub const KEY_REQKEY_DEFL_GROUP_KEYRING: i32 = 6; pub const KEY_REQKEY_DEFL_REQUESTOR_KEYRING: i32 = 7; pub const KEYCTL_GET_KEYRING_ID: u32 = 0; pub const KEYCTL_JOIN_SESSION_KEYRING: u32 = 1; pub const KEYCTL_UPDATE: u32 = 2; pub const KEYCTL_REVOKE: u32 = 3; pub const KEYCTL_CHOWN: u32 = 4; pub const KEYCTL_SETPERM: u32 = 5; pub const KEYCTL_DESCRIBE: u32 = 6; pub const KEYCTL_CLEAR: u32 = 7; pub const KEYCTL_LINK: u32 = 8; pub const KEYCTL_UNLINK: u32 = 9; pub const KEYCTL_SEARCH: u32 = 10; pub const KEYCTL_READ: u32 = 11; pub const KEYCTL_INSTANTIATE: u32 = 12; pub const KEYCTL_NEGATE: u32 = 13; pub const KEYCTL_SET_REQKEY_KEYRING: u32 = 14; pub const KEYCTL_SET_TIMEOUT: u32 = 15; pub const KEYCTL_ASSUME_AUTHORITY: u32 = 16; pub const KEYCTL_GET_SECURITY: u32 = 17; pub const KEYCTL_SESSION_TO_PARENT: u32 = 18; pub const KEYCTL_REJECT: u32 = 19; pub const KEYCTL_INSTANTIATE_IOV: u32 = 20; pub const KEYCTL_INVALIDATE: u32 = 21; pub const KEYCTL_GET_PERSISTENT: u32 = 22; pub const IN_MASK_CREATE: u32 = 0x1000_0000; pub const IN_MASK_ADD: u32 = 0x2000_0000; pub const IN_ISDIR: u32 = 0x4000_0000; pub const IN_ONESHOT: u32 = 0x8000_0000; pub const IN_ALL_EVENTS: u32 = IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF; pub const IN_CLOEXEC: ::c_int = O_CLOEXEC; pub const IN_NONBLOCK: ::c_int = O_NONBLOCK; // uapi/linux/mount.h pub const OPEN_TREE_CLONE: ::c_uint = 0x01; pub const OPEN_TREE_CLOEXEC: ::c_uint = O_CLOEXEC as ::c_uint; // uapi/linux/netfilter/nf_tables.h pub const NFT_TABLE_MAXNAMELEN: ::c_int = 256; pub const NFT_CHAIN_MAXNAMELEN: ::c_int = 256; pub const NFT_SET_MAXNAMELEN: ::c_int = 256; pub const NFT_OBJ_MAXNAMELEN: ::c_int = 256; pub const NFT_USERDATA_MAXLEN: ::c_int = 256; pub const NFT_REG_VERDICT: ::c_int = 0; pub const NFT_REG_1: ::c_int = 1; pub const NFT_REG_2: ::c_int = 2; pub const NFT_REG_3: ::c_int = 3; pub const NFT_REG_4: ::c_int = 4; pub const __NFT_REG_MAX: ::c_int = 5; pub const NFT_REG32_00: ::c_int = 8; pub const NFT_REG32_01: ::c_int = 9; pub const NFT_REG32_02: ::c_int = 10; pub const NFT_REG32_03: ::c_int = 11; pub const NFT_REG32_04: ::c_int = 12; pub const NFT_REG32_05: ::c_int = 13; pub const NFT_REG32_06: ::c_int = 14; pub const NFT_REG32_07: ::c_int = 15; pub const NFT_REG32_08: ::c_int = 16; pub const NFT_REG32_09: ::c_int = 17; pub const NFT_REG32_10: ::c_int = 18; pub const NFT_REG32_11: ::c_int = 19; pub const NFT_REG32_12: ::c_int = 20; pub const NFT_REG32_13: ::c_int = 21; pub const NFT_REG32_14: ::c_int = 22; pub const NFT_REG32_15: ::c_int = 23; pub const NFT_REG_SIZE: ::c_int = 16; pub const NFT_REG32_SIZE: ::c_int = 4; pub const NFT_CONTINUE: ::c_int = -1; pub const NFT_BREAK: ::c_int = -2; pub const NFT_JUMP: ::c_int = -3; pub const NFT_GOTO: ::c_int = -4; pub const NFT_RETURN: ::c_int = -5; pub const NFT_MSG_NEWTABLE: ::c_int = 0; pub const NFT_MSG_GETTABLE: ::c_int = 1; pub const NFT_MSG_DELTABLE: ::c_int = 2; pub const NFT_MSG_NEWCHAIN: ::c_int = 3; pub const NFT_MSG_GETCHAIN: ::c_int = 4; pub const NFT_MSG_DELCHAIN: ::c_int = 5; pub const NFT_MSG_NEWRULE: ::c_int = 6; pub const NFT_MSG_GETRULE: ::c_int = 7; pub const NFT_MSG_DELRULE: ::c_int = 8; pub const NFT_MSG_NEWSET: ::c_int = 9; pub const NFT_MSG_GETSET: ::c_int = 10; pub const NFT_MSG_DELSET: ::c_int = 11; pub const NFT_MSG_NEWSETELEM: ::c_int = 12; pub const NFT_MSG_GETSETELEM: ::c_int = 13; pub const NFT_MSG_DELSETELEM: ::c_int = 14; pub const NFT_MSG_NEWGEN: ::c_int = 15; pub const NFT_MSG_GETGEN: ::c_int = 16; pub const NFT_MSG_TRACE: ::c_int = 17; cfg_if! { if #[cfg(not(target_arch = "sparc64"))] { pub const NFT_MSG_NEWOBJ: ::c_int = 18; pub const NFT_MSG_GETOBJ: ::c_int = 19; pub const NFT_MSG_DELOBJ: ::c_int = 20; pub const NFT_MSG_GETOBJ_RESET: ::c_int = 21; } } pub const NFT_MSG_MAX: ::c_int = 25; pub const NFT_SET_ANONYMOUS: ::c_int = 0x1; pub const NFT_SET_CONSTANT: ::c_int = 0x2; pub const NFT_SET_INTERVAL: ::c_int = 0x4; pub const NFT_SET_MAP: ::c_int = 0x8; pub const NFT_SET_TIMEOUT: ::c_int = 0x10; pub const NFT_SET_EVAL: ::c_int = 0x20; pub const NFT_SET_POL_PERFORMANCE: ::c_int = 0; pub const NFT_SET_POL_MEMORY: ::c_int = 1; pub const NFT_SET_ELEM_INTERVAL_END: ::c_int = 0x1; pub const NFT_DATA_VALUE: ::c_uint = 0; pub const NFT_DATA_VERDICT: ::c_uint = 0xffffff00; pub const NFT_DATA_RESERVED_MASK: ::c_uint = 0xffffff00; pub const NFT_DATA_VALUE_MAXLEN: ::c_int = 64; pub const NFT_BYTEORDER_NTOH: ::c_int = 0; pub const NFT_BYTEORDER_HTON: ::c_int = 1; pub const NFT_CMP_EQ: ::c_int = 0; pub const NFT_CMP_NEQ: ::c_int = 1; pub const NFT_CMP_LT: ::c_int = 2; pub const NFT_CMP_LTE: ::c_int = 3; pub const NFT_CMP_GT: ::c_int = 4; pub const NFT_CMP_GTE: ::c_int = 5; pub const NFT_RANGE_EQ: ::c_int = 0; pub const NFT_RANGE_NEQ: ::c_int = 1; pub const NFT_LOOKUP_F_INV: ::c_int = 1 << 0; pub const NFT_DYNSET_OP_ADD: ::c_int = 0; pub const NFT_DYNSET_OP_UPDATE: ::c_int = 1; pub const NFT_DYNSET_F_INV: ::c_int = 1 << 0; pub const NFT_PAYLOAD_LL_HEADER: ::c_int = 0; pub const NFT_PAYLOAD_NETWORK_HEADER: ::c_int = 1; pub const NFT_PAYLOAD_TRANSPORT_HEADER: ::c_int = 2; pub const NFT_PAYLOAD_CSUM_NONE: ::c_int = 0; pub const NFT_PAYLOAD_CSUM_INET: ::c_int = 1; pub const NFT_META_LEN: ::c_int = 0; pub const NFT_META_PROTOCOL: ::c_int = 1; pub const NFT_META_PRIORITY: ::c_int = 2; pub const NFT_META_MARK: ::c_int = 3; pub const NFT_META_IIF: ::c_int = 4; pub const NFT_META_OIF: ::c_int = 5; pub const NFT_META_IIFNAME: ::c_int = 6; pub const NFT_META_OIFNAME: ::c_int = 7; pub const NFT_META_IIFTYPE: ::c_int = 8; pub const NFT_META_OIFTYPE: ::c_int = 9; pub const NFT_META_SKUID: ::c_int = 10; pub const NFT_META_SKGID: ::c_int = 11; pub const NFT_META_NFTRACE: ::c_int = 12; pub const NFT_META_RTCLASSID: ::c_int = 13; pub const NFT_META_SECMARK: ::c_int = 14; pub const NFT_META_NFPROTO: ::c_int = 15; pub const NFT_META_L4PROTO: ::c_int = 16; pub const NFT_META_BRI_IIFNAME: ::c_int = 17; pub const NFT_META_BRI_OIFNAME: ::c_int = 18; pub const NFT_META_PKTTYPE: ::c_int = 19; pub const NFT_META_CPU: ::c_int = 20; pub const NFT_META_IIFGROUP: ::c_int = 21; pub const NFT_META_OIFGROUP: ::c_int = 22; pub const NFT_META_CGROUP: ::c_int = 23; pub const NFT_META_PRANDOM: ::c_int = 24; pub const NFT_CT_STATE: ::c_int = 0; pub const NFT_CT_DIRECTION: ::c_int = 1; pub const NFT_CT_STATUS: ::c_int = 2; pub const NFT_CT_MARK: ::c_int = 3; pub const NFT_CT_SECMARK: ::c_int = 4; pub const NFT_CT_EXPIRATION: ::c_int = 5; pub const NFT_CT_HELPER: ::c_int = 6; pub const NFT_CT_L3PROTOCOL: ::c_int = 7; pub const NFT_CT_SRC: ::c_int = 8; pub const NFT_CT_DST: ::c_int = 9; pub const NFT_CT_PROTOCOL: ::c_int = 10; pub const NFT_CT_PROTO_SRC: ::c_int = 11; pub const NFT_CT_PROTO_DST: ::c_int = 12; pub const NFT_CT_LABELS: ::c_int = 13; pub const NFT_CT_PKTS: ::c_int = 14; pub const NFT_CT_BYTES: ::c_int = 15; pub const NFT_LIMIT_PKTS: ::c_int = 0; pub const NFT_LIMIT_PKT_BYTES: ::c_int = 1; pub const NFT_LIMIT_F_INV: ::c_int = 1 << 0; pub const NFT_QUEUE_FLAG_BYPASS: ::c_int = 0x01; pub const NFT_QUEUE_FLAG_CPU_FANOUT: ::c_int = 0x02; pub const NFT_QUEUE_FLAG_MASK: ::c_int = 0x03; pub const NFT_QUOTA_F_INV: ::c_int = 1 << 0; pub const NFT_REJECT_ICMP_UNREACH: ::c_int = 0; pub const NFT_REJECT_TCP_RST: ::c_int = 1; pub const NFT_REJECT_ICMPX_UNREACH: ::c_int = 2; pub const NFT_REJECT_ICMPX_NO_ROUTE: ::c_int = 0; pub const NFT_REJECT_ICMPX_PORT_UNREACH: ::c_int = 1; pub const NFT_REJECT_ICMPX_HOST_UNREACH: ::c_int = 2; pub const NFT_REJECT_ICMPX_ADMIN_PROHIBITED: ::c_int = 3; pub const NFT_NAT_SNAT: ::c_int = 0; pub const NFT_NAT_DNAT: ::c_int = 1; pub const NFT_TRACETYPE_UNSPEC: ::c_int = 0; pub const NFT_TRACETYPE_POLICY: ::c_int = 1; pub const NFT_TRACETYPE_RETURN: ::c_int = 2; pub const NFT_TRACETYPE_RULE: ::c_int = 3; pub const NFT_NG_INCREMENTAL: ::c_int = 0; pub const NFT_NG_RANDOM: ::c_int = 1; // linux/input.h pub const FF_MAX: ::__u16 = 0x7f; pub const FF_CNT: usize = FF_MAX as usize + 1; // linux/input-event-codes.h pub const INPUT_PROP_MAX: ::__u16 = 0x1f; pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1; pub const EV_MAX: ::__u16 = 0x1f; pub const EV_CNT: usize = EV_MAX as usize + 1; pub const SYN_MAX: ::__u16 = 0xf; pub const SYN_CNT: usize = SYN_MAX as usize + 1; pub const KEY_MAX: ::__u16 = 0x2ff; pub const KEY_CNT: usize = KEY_MAX as usize + 1; pub const REL_MAX: ::__u16 = 0x0f; pub const REL_CNT: usize = REL_MAX as usize + 1; pub const ABS_MAX: ::__u16 = 0x3f; pub const ABS_CNT: usize = ABS_MAX as usize + 1; pub const SW_MAX: ::__u16 = 0x10; pub const SW_CNT: usize = SW_MAX as usize + 1; pub const MSC_MAX: ::__u16 = 0x07; pub const MSC_CNT: usize = MSC_MAX as usize + 1; pub const LED_MAX: ::__u16 = 0x0f; pub const LED_CNT: usize = LED_MAX as usize + 1; pub const REP_MAX: ::__u16 = 0x01; pub const REP_CNT: usize = REP_MAX as usize + 1; pub const SND_MAX: ::__u16 = 0x07; pub const SND_CNT: usize = SND_MAX as usize + 1; // linux/uinput.h pub const UINPUT_VERSION: ::c_uint = 5; pub const UINPUT_MAX_NAME_SIZE: usize = 80; // uapi/linux/fanotify.h pub const FAN_ACCESS: u64 = 0x0000_0001; pub const FAN_MODIFY: u64 = 0x0000_0002; pub const FAN_ATTRIB: u64 = 0x0000_0004; pub const FAN_CLOSE_WRITE: u64 = 0x0000_0008; pub const FAN_CLOSE_NOWRITE: u64 = 0x0000_0010; pub const FAN_OPEN: u64 = 0x0000_0020; pub const FAN_MOVED_FROM: u64 = 0x0000_0040; pub const FAN_MOVED_TO: u64 = 0x0000_0080; pub const FAN_CREATE: u64 = 0x0000_0100; pub const FAN_DELETE: u64 = 0x0000_0200; pub const FAN_DELETE_SELF: u64 = 0x0000_0400; pub const FAN_MOVE_SELF: u64 = 0x0000_0800; pub const FAN_OPEN_EXEC: u64 = 0x0000_1000; pub const FAN_Q_OVERFLOW: u64 = 0x0000_4000; pub const FAN_FS_ERROR: u64 = 0x0000_8000; pub const FAN_OPEN_PERM: u64 = 0x0001_0000; pub const FAN_ACCESS_PERM: u64 = 0x0002_0000; pub const FAN_OPEN_EXEC_PERM: u64 = 0x0004_0000; pub const FAN_EVENT_ON_CHILD: u64 = 0x0800_0000; pub const FAN_RENAME: u64 = 0x1000_0000; pub const FAN_ONDIR: u64 = 0x4000_0000; pub const FAN_CLOSE: u64 = FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE; pub const FAN_MOVE: u64 = FAN_MOVED_FROM | FAN_MOVED_TO; pub const FAN_CLOEXEC: ::c_uint = 0x0000_0001; pub const FAN_NONBLOCK: ::c_uint = 0x0000_0002; pub const FAN_CLASS_NOTIF: ::c_uint = 0x0000_0000; pub const FAN_CLASS_CONTENT: ::c_uint = 0x0000_0004; pub const FAN_CLASS_PRE_CONTENT: ::c_uint = 0x0000_0008; pub const FAN_UNLIMITED_QUEUE: ::c_uint = 0x0000_0010; pub const FAN_UNLIMITED_MARKS: ::c_uint = 0x0000_0020; pub const FAN_ENABLE_AUDIT: ::c_uint = 0x0000_0040; pub const FAN_REPORT_PIDFD: ::c_uint = 0x0000_0080; pub const FAN_REPORT_TID: ::c_uint = 0x0000_0100; pub const FAN_REPORT_FID: ::c_uint = 0x0000_0200; pub const FAN_REPORT_DIR_FID: ::c_uint = 0x0000_0400; pub const FAN_REPORT_NAME: ::c_uint = 0x0000_0800; pub const FAN_REPORT_TARGET_FID: ::c_uint = 0x0000_1000; pub const FAN_REPORT_DFID_NAME: ::c_uint = FAN_REPORT_DIR_FID | FAN_REPORT_NAME; pub const FAN_REPORT_DFID_NAME_TARGET: ::c_uint = FAN_REPORT_DFID_NAME | FAN_REPORT_FID | FAN_REPORT_TARGET_FID; pub const FAN_MARK_ADD: ::c_uint = 0x0000_0001; pub const FAN_MARK_REMOVE: ::c_uint = 0x0000_0002; pub const FAN_MARK_DONT_FOLLOW: ::c_uint = 0x0000_0004; pub const FAN_MARK_ONLYDIR: ::c_uint = 0x0000_0008; pub const FAN_MARK_IGNORED_MASK: ::c_uint = 0x0000_0020; pub const FAN_MARK_IGNORED_SURV_MODIFY: ::c_uint = 0x0000_0040; pub const FAN_MARK_FLUSH: ::c_uint = 0x0000_0080; pub const FAN_MARK_EVICTABLE: ::c_uint = 0x0000_0200; pub const FAN_MARK_IGNORE: ::c_uint = 0x0000_0400; pub const FAN_MARK_INODE: ::c_uint = 0x0000_0000; pub const FAN_MARK_MOUNT: ::c_uint = 0x0000_0010; pub const FAN_MARK_FILESYSTEM: ::c_uint = 0x0000_0100; pub const FAN_MARK_IGNORE_SURV: ::c_uint = FAN_MARK_IGNORE | FAN_MARK_IGNORED_SURV_MODIFY; pub const FANOTIFY_METADATA_VERSION: u8 = 3; pub const FAN_EVENT_INFO_TYPE_FID: u8 = 1; pub const FAN_EVENT_INFO_TYPE_DFID_NAME: u8 = 2; pub const FAN_EVENT_INFO_TYPE_DFID: u8 = 3; pub const FAN_EVENT_INFO_TYPE_PIDFD: u8 = 4; pub const FAN_EVENT_INFO_TYPE_ERROR: u8 = 5; pub const FAN_EVENT_INFO_TYPE_OLD_DFID_NAME: u8 = 10; pub const FAN_EVENT_INFO_TYPE_NEW_DFID_NAME: u8 = 12; pub const FAN_RESPONSE_INFO_NONE: u8 = 0; pub const FAN_RESPONSE_INFO_AUDIT_RULE: u8 = 1; pub const FAN_ALLOW: u32 = 0x01; pub const FAN_DENY: u32 = 0x02; pub const FAN_AUDIT: u32 = 0x10; pub const FAN_INFO: u32 = 0x20; pub const FAN_NOFD: ::c_int = -1; pub const FAN_NOPIDFD: ::c_int = FAN_NOFD; pub const FAN_EPIDFD: ::c_int = -2; pub const FUTEX_WAIT: ::c_int = 0; pub const FUTEX_WAKE: ::c_int = 1; pub const FUTEX_FD: ::c_int = 2; pub const FUTEX_REQUEUE: ::c_int = 3; pub const FUTEX_CMP_REQUEUE: ::c_int = 4; pub const FUTEX_WAKE_OP: ::c_int = 5; pub const FUTEX_LOCK_PI: ::c_int = 6; pub const FUTEX_UNLOCK_PI: ::c_int = 7; pub const FUTEX_TRYLOCK_PI: ::c_int = 8; pub const FUTEX_WAIT_BITSET: ::c_int = 9; pub const FUTEX_WAKE_BITSET: ::c_int = 10; pub const FUTEX_WAIT_REQUEUE_PI: ::c_int = 11; pub const FUTEX_CMP_REQUEUE_PI: ::c_int = 12; pub const FUTEX_LOCK_PI2: ::c_int = 13; pub const FUTEX_PRIVATE_FLAG: ::c_int = 128; pub const FUTEX_CLOCK_REALTIME: ::c_int = 256; pub const FUTEX_CMD_MASK: ::c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); pub const FUTEX_BITSET_MATCH_ANY: ::c_int = 0xffffffff; pub const FUTEX_OP_SET: ::c_int = 0; pub const FUTEX_OP_ADD: ::c_int = 1; pub const FUTEX_OP_OR: ::c_int = 2; pub const FUTEX_OP_ANDN: ::c_int = 3; pub const FUTEX_OP_XOR: ::c_int = 4; pub const FUTEX_OP_OPARG_SHIFT: ::c_int = 8; pub const FUTEX_OP_CMP_EQ: ::c_int = 0; pub const FUTEX_OP_CMP_NE: ::c_int = 1; pub const FUTEX_OP_CMP_LT: ::c_int = 2; pub const FUTEX_OP_CMP_LE: ::c_int = 3; pub const FUTEX_OP_CMP_GT: ::c_int = 4; pub const FUTEX_OP_CMP_GE: ::c_int = 5; pub fn FUTEX_OP(op: ::c_int, oparg: ::c_int, cmp: ::c_int, cmparg: ::c_int) -> ::c_int { ((op & 0xf) << 28) | ((cmp & 0xf) << 24) | ((oparg & 0xfff) << 12) | (cmparg & 0xfff) } // linux/kexec.h pub const KEXEC_ON_CRASH: ::c_int = 0x00000001; pub const KEXEC_PRESERVE_CONTEXT: ::c_int = 0x00000002; pub const KEXEC_ARCH_MASK: ::c_int = 0xffff0000; pub const KEXEC_FILE_UNLOAD: ::c_int = 0x00000001; pub const KEXEC_FILE_ON_CRASH: ::c_int = 0x00000002; pub const KEXEC_FILE_NO_INITRAMFS: ::c_int = 0x00000004; // linux/reboot.h pub const LINUX_REBOOT_MAGIC1: ::c_int = 0xfee1dead; pub const LINUX_REBOOT_MAGIC2: ::c_int = 672274793; pub const LINUX_REBOOT_MAGIC2A: ::c_int = 85072278; pub const LINUX_REBOOT_MAGIC2B: ::c_int = 369367448; pub const LINUX_REBOOT_MAGIC2C: ::c_int = 537993216; pub const LINUX_REBOOT_CMD_RESTART: ::c_int = 0x01234567; pub const LINUX_REBOOT_CMD_HALT: ::c_int = 0xCDEF0123; pub const LINUX_REBOOT_CMD_CAD_ON: ::c_int = 0x89ABCDEF; pub const LINUX_REBOOT_CMD_CAD_OFF: ::c_int = 0x00000000; pub const LINUX_REBOOT_CMD_POWER_OFF: ::c_int = 0x4321FEDC; pub const LINUX_REBOOT_CMD_RESTART2: ::c_int = 0xA1B2C3D4; pub const LINUX_REBOOT_CMD_SW_SUSPEND: ::c_int = 0xD000FCE2; pub const LINUX_REBOOT_CMD_KEXEC: ::c_int = 0x45584543; pub const REG_EXTENDED: ::c_int = 1; pub const REG_ICASE: ::c_int = 2; pub const REG_NEWLINE: ::c_int = 4; pub const REG_NOSUB: ::c_int = 8; pub const REG_NOTBOL: ::c_int = 1; pub const REG_NOTEOL: ::c_int = 2; pub const REG_ENOSYS: ::c_int = -1; pub const REG_NOMATCH: ::c_int = 1; pub const REG_BADPAT: ::c_int = 2; pub const REG_ECOLLATE: ::c_int = 3; pub const REG_ECTYPE: ::c_int = 4; pub const REG_EESCAPE: ::c_int = 5; pub const REG_ESUBREG: ::c_int = 6; pub const REG_EBRACK: ::c_int = 7; pub const REG_EPAREN: ::c_int = 8; pub const REG_EBRACE: ::c_int = 9; pub const REG_BADBR: ::c_int = 10; pub const REG_ERANGE: ::c_int = 11; pub const REG_ESPACE: ::c_int = 12; pub const REG_BADRPT: ::c_int = 13; // linux/errqueue.h pub const SO_EE_ORIGIN_NONE: u8 = 0; pub const SO_EE_ORIGIN_LOCAL: u8 = 1; pub const SO_EE_ORIGIN_ICMP: u8 = 2; pub const SO_EE_ORIGIN_ICMP6: u8 = 3; pub const SO_EE_ORIGIN_TXSTATUS: u8 = 4; pub const SO_EE_ORIGIN_TIMESTAMPING: u8 = SO_EE_ORIGIN_TXSTATUS; // errno.h pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EWOULDBLOCK: ::c_int = EAGAIN; // linux/can.h pub const CAN_EFF_FLAG: canid_t = 0x80000000; pub const CAN_RTR_FLAG: canid_t = 0x40000000; pub const CAN_ERR_FLAG: canid_t = 0x20000000; pub const CAN_SFF_MASK: canid_t = 0x000007FF; pub const CAN_EFF_MASK: canid_t = 0x1FFFFFFF; pub const CAN_ERR_MASK: canid_t = 0x1FFFFFFF; pub const CANXL_PRIO_MASK: ::canid_t = CAN_SFF_MASK; pub const CAN_SFF_ID_BITS: ::c_int = 11; pub const CAN_EFF_ID_BITS: ::c_int = 29; pub const CANXL_PRIO_BITS: ::c_int = CAN_SFF_ID_BITS; pub const CAN_MAX_DLC: ::c_int = 8; pub const CAN_MAX_DLEN: usize = 8; pub const CANFD_MAX_DLC: ::c_int = 15; pub const CANFD_MAX_DLEN: usize = 64; pub const CANFD_BRS: ::c_int = 0x01; pub const CANFD_ESI: ::c_int = 0x02; pub const CANXL_MIN_DLC: ::c_int = 0; pub const CANXL_MAX_DLC: ::c_int = 2047; pub const CANXL_MAX_DLC_MASK: ::c_int = 0x07FF; pub const CANXL_MIN_DLEN: usize = 1; pub const CANXL_MAX_DLEN: usize = 2048; pub const CANXL_XLF: ::c_int = 0x80; pub const CANXL_SEC: ::c_int = 0x01; cfg_if! { if #[cfg(libc_align)] { pub const CAN_MTU: usize = ::mem::size_of::(); pub const CANFD_MTU: usize = ::mem::size_of::(); pub const CANXL_MTU: usize = ::mem::size_of::(); // FIXME: use `core::mem::offset_of!` once that is available // https://github.com/rust-lang/rfcs/pull/3308 // pub const CANXL_HDR_SIZE: usize = core::mem::offset_of!(canxl_frame, data); pub const CANXL_HDR_SIZE: usize = 12; pub const CANXL_MIN_MTU: usize = CANXL_HDR_SIZE + 64; pub const CANXL_MAX_MTU: usize = CANXL_MTU; } } pub const CAN_RAW: ::c_int = 1; pub const CAN_BCM: ::c_int = 2; pub const CAN_TP16: ::c_int = 3; pub const CAN_TP20: ::c_int = 4; pub const CAN_MCNET: ::c_int = 5; pub const CAN_ISOTP: ::c_int = 6; pub const CAN_J1939: ::c_int = 7; pub const CAN_NPROTO: ::c_int = 8; pub const SOL_CAN_BASE: ::c_int = 100; pub const CAN_INV_FILTER: canid_t = 0x20000000; pub const CAN_RAW_FILTER_MAX: ::c_int = 512; // linux/can/raw.h pub const SOL_CAN_RAW: ::c_int = SOL_CAN_BASE + CAN_RAW; pub const CAN_RAW_FILTER: ::c_int = 1; pub const CAN_RAW_ERR_FILTER: ::c_int = 2; pub const CAN_RAW_LOOPBACK: ::c_int = 3; pub const CAN_RAW_RECV_OWN_MSGS: ::c_int = 4; pub const CAN_RAW_FD_FRAMES: ::c_int = 5; pub const CAN_RAW_JOIN_FILTERS: ::c_int = 6; pub const CAN_RAW_XL_FRAMES: ::c_int = 7; // linux/can/j1939.h pub const SOL_CAN_J1939: ::c_int = SOL_CAN_BASE + CAN_J1939; pub const J1939_MAX_UNICAST_ADDR: ::c_uchar = 0xfd; pub const J1939_IDLE_ADDR: ::c_uchar = 0xfe; pub const J1939_NO_ADDR: ::c_uchar = 0xff; pub const J1939_NO_NAME: ::c_ulong = 0; pub const J1939_PGN_REQUEST: ::c_uint = 0x0ea00; pub const J1939_PGN_ADDRESS_CLAIMED: ::c_uint = 0x0ee00; pub const J1939_PGN_ADDRESS_COMMANDED: ::c_uint = 0x0fed8; pub const J1939_PGN_PDU1_MAX: ::c_uint = 0x3ff00; pub const J1939_PGN_MAX: ::c_uint = 0x3ffff; pub const J1939_NO_PGN: ::c_uint = 0x40000; pub const SO_J1939_FILTER: ::c_int = 1; pub const SO_J1939_PROMISC: ::c_int = 2; pub const SO_J1939_SEND_PRIO: ::c_int = 3; pub const SO_J1939_ERRQUEUE: ::c_int = 4; pub const SCM_J1939_DEST_ADDR: ::c_int = 1; pub const SCM_J1939_DEST_NAME: ::c_int = 2; pub const SCM_J1939_PRIO: ::c_int = 3; pub const SCM_J1939_ERRQUEUE: ::c_int = 4; pub const J1939_NLA_PAD: ::c_int = 0; pub const J1939_NLA_BYTES_ACKED: ::c_int = 1; pub const J1939_NLA_TOTAL_SIZE: ::c_int = 2; pub const J1939_NLA_PGN: ::c_int = 3; pub const J1939_NLA_SRC_NAME: ::c_int = 4; pub const J1939_NLA_DEST_NAME: ::c_int = 5; pub const J1939_NLA_SRC_ADDR: ::c_int = 6; pub const J1939_NLA_DEST_ADDR: ::c_int = 7; pub const J1939_EE_INFO_NONE: ::c_int = 0; pub const J1939_EE_INFO_TX_ABORT: ::c_int = 1; pub const J1939_EE_INFO_RX_RTS: ::c_int = 2; pub const J1939_EE_INFO_RX_DPO: ::c_int = 3; pub const J1939_EE_INFO_RX_ABORT: ::c_int = 4; pub const J1939_FILTER_MAX: ::c_int = 512; // linux/sctp.h pub const SCTP_FUTURE_ASSOC: ::c_int = 0; pub const SCTP_CURRENT_ASSOC: ::c_int = 1; pub const SCTP_ALL_ASSOC: ::c_int = 2; pub const SCTP_RTOINFO: ::c_int = 0; pub const SCTP_ASSOCINFO: ::c_int = 1; pub const SCTP_INITMSG: ::c_int = 2; pub const SCTP_NODELAY: ::c_int = 3; pub const SCTP_AUTOCLOSE: ::c_int = 4; pub const SCTP_SET_PEER_PRIMARY_ADDR: ::c_int = 5; pub const SCTP_PRIMARY_ADDR: ::c_int = 6; pub const SCTP_ADAPTATION_LAYER: ::c_int = 7; pub const SCTP_DISABLE_FRAGMENTS: ::c_int = 8; pub const SCTP_PEER_ADDR_PARAMS: ::c_int = 9; pub const SCTP_DEFAULT_SEND_PARAM: ::c_int = 10; pub const SCTP_EVENTS: ::c_int = 11; pub const SCTP_I_WANT_MAPPED_V4_ADDR: ::c_int = 12; pub const SCTP_MAXSEG: ::c_int = 13; pub const SCTP_STATUS: ::c_int = 14; pub const SCTP_GET_PEER_ADDR_INFO: ::c_int = 15; pub const SCTP_DELAYED_ACK_TIME: ::c_int = 16; pub const SCTP_DELAYED_ACK: ::c_int = SCTP_DELAYED_ACK_TIME; pub const SCTP_DELAYED_SACK: ::c_int = SCTP_DELAYED_ACK_TIME; pub const SCTP_CONTEXT: ::c_int = 17; pub const SCTP_FRAGMENT_INTERLEAVE: ::c_int = 18; pub const SCTP_PARTIAL_DELIVERY_POINT: ::c_int = 19; pub const SCTP_MAX_BURST: ::c_int = 20; pub const SCTP_AUTH_CHUNK: ::c_int = 21; pub const SCTP_HMAC_IDENT: ::c_int = 22; pub const SCTP_AUTH_KEY: ::c_int = 23; pub const SCTP_AUTH_ACTIVE_KEY: ::c_int = 24; pub const SCTP_AUTH_DELETE_KEY: ::c_int = 25; pub const SCTP_PEER_AUTH_CHUNKS: ::c_int = 26; pub const SCTP_LOCAL_AUTH_CHUNKS: ::c_int = 27; pub const SCTP_GET_ASSOC_NUMBER: ::c_int = 28; pub const SCTP_GET_ASSOC_ID_LIST: ::c_int = 29; pub const SCTP_AUTO_ASCONF: ::c_int = 30; pub const SCTP_PEER_ADDR_THLDS: ::c_int = 31; pub const SCTP_RECVRCVINFO: ::c_int = 32; pub const SCTP_RECVNXTINFO: ::c_int = 33; pub const SCTP_DEFAULT_SNDINFO: ::c_int = 34; pub const SCTP_AUTH_DEACTIVATE_KEY: ::c_int = 35; pub const SCTP_REUSE_PORT: ::c_int = 36; pub const SCTP_PEER_ADDR_THLDS_V2: ::c_int = 37; pub const SCTP_PR_SCTP_NONE: ::c_int = 0x0000; pub const SCTP_PR_SCTP_TTL: ::c_int = 0x0010; pub const SCTP_PR_SCTP_RTX: ::c_int = 0x0020; pub const SCTP_PR_SCTP_PRIO: ::c_int = 0x0030; pub const SCTP_PR_SCTP_MAX: ::c_int = SCTP_PR_SCTP_PRIO; pub const SCTP_PR_SCTP_MASK: ::c_int = 0x0030; pub const SCTP_ENABLE_RESET_STREAM_REQ: ::c_int = 0x01; pub const SCTP_ENABLE_RESET_ASSOC_REQ: ::c_int = 0x02; pub const SCTP_ENABLE_CHANGE_ASSOC_REQ: ::c_int = 0x04; pub const SCTP_ENABLE_STRRESET_MASK: ::c_int = 0x07; pub const SCTP_STREAM_RESET_INCOMING: ::c_int = 0x01; pub const SCTP_STREAM_RESET_OUTGOING: ::c_int = 0x02; pub const SCTP_INIT: ::c_int = 0; pub const SCTP_SNDRCV: ::c_int = 1; pub const SCTP_SNDINFO: ::c_int = 2; pub const SCTP_RCVINFO: ::c_int = 3; pub const SCTP_NXTINFO: ::c_int = 4; pub const SCTP_PRINFO: ::c_int = 5; pub const SCTP_AUTHINFO: ::c_int = 6; pub const SCTP_DSTADDRV4: ::c_int = 7; pub const SCTP_DSTADDRV6: ::c_int = 8; pub const SCTP_UNORDERED: ::c_int = 1 << 0; pub const SCTP_ADDR_OVER: ::c_int = 1 << 1; pub const SCTP_ABORT: ::c_int = 1 << 2; pub const SCTP_SACK_IMMEDIATELY: ::c_int = 1 << 3; pub const SCTP_SENDALL: ::c_int = 1 << 6; pub const SCTP_PR_SCTP_ALL: ::c_int = 1 << 7; pub const SCTP_NOTIFICATION: ::c_int = MSG_NOTIFICATION; pub const SCTP_EOF: ::c_int = ::MSG_FIN; /* DCCP socket options */ pub const DCCP_SOCKOPT_PACKET_SIZE: ::c_int = 1; pub const DCCP_SOCKOPT_SERVICE: ::c_int = 2; pub const DCCP_SOCKOPT_CHANGE_L: ::c_int = 3; pub const DCCP_SOCKOPT_CHANGE_R: ::c_int = 4; pub const DCCP_SOCKOPT_GET_CUR_MPS: ::c_int = 5; pub const DCCP_SOCKOPT_SERVER_TIMEWAIT: ::c_int = 6; pub const DCCP_SOCKOPT_SEND_CSCOV: ::c_int = 10; pub const DCCP_SOCKOPT_RECV_CSCOV: ::c_int = 11; pub const DCCP_SOCKOPT_AVAILABLE_CCIDS: ::c_int = 12; pub const DCCP_SOCKOPT_CCID: ::c_int = 13; pub const DCCP_SOCKOPT_TX_CCID: ::c_int = 14; pub const DCCP_SOCKOPT_RX_CCID: ::c_int = 15; pub const DCCP_SOCKOPT_QPOLICY_ID: ::c_int = 16; pub const DCCP_SOCKOPT_QPOLICY_TXQLEN: ::c_int = 17; pub const DCCP_SOCKOPT_CCID_RX_INFO: ::c_int = 128; pub const DCCP_SOCKOPT_CCID_TX_INFO: ::c_int = 192; /// maximum number of services provided on the same listening port pub const DCCP_SERVICE_LIST_MAX_LEN: ::c_int = 32; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_NET: ::c_int = 3; pub const CTL_FS: ::c_int = 5; pub const CTL_DEBUG: ::c_int = 6; pub const CTL_DEV: ::c_int = 7; pub const CTL_BUS: ::c_int = 8; pub const CTL_ABI: ::c_int = 9; pub const CTL_CPU: ::c_int = 10; pub const CTL_BUS_ISA: ::c_int = 1; pub const INOTIFY_MAX_USER_INSTANCES: ::c_int = 1; pub const INOTIFY_MAX_USER_WATCHES: ::c_int = 2; pub const INOTIFY_MAX_QUEUED_EVENTS: ::c_int = 3; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_VERSION: ::c_int = 4; pub const KERN_SECUREMASK: ::c_int = 5; pub const KERN_PROF: ::c_int = 6; pub const KERN_NODENAME: ::c_int = 7; pub const KERN_DOMAINNAME: ::c_int = 8; pub const KERN_PANIC: ::c_int = 15; pub const KERN_REALROOTDEV: ::c_int = 16; pub const KERN_SPARC_REBOOT: ::c_int = 21; pub const KERN_CTLALTDEL: ::c_int = 22; pub const KERN_PRINTK: ::c_int = 23; pub const KERN_NAMETRANS: ::c_int = 24; pub const KERN_PPC_HTABRECLAIM: ::c_int = 25; pub const KERN_PPC_ZEROPAGED: ::c_int = 26; pub const KERN_PPC_POWERSAVE_NAP: ::c_int = 27; pub const KERN_MODPROBE: ::c_int = 28; pub const KERN_SG_BIG_BUFF: ::c_int = 29; pub const KERN_ACCT: ::c_int = 30; pub const KERN_PPC_L2CR: ::c_int = 31; pub const KERN_RTSIGNR: ::c_int = 32; pub const KERN_RTSIGMAX: ::c_int = 33; pub const KERN_SHMMAX: ::c_int = 34; pub const KERN_MSGMAX: ::c_int = 35; pub const KERN_MSGMNB: ::c_int = 36; pub const KERN_MSGPOOL: ::c_int = 37; pub const KERN_SYSRQ: ::c_int = 38; pub const KERN_MAX_THREADS: ::c_int = 39; pub const KERN_RANDOM: ::c_int = 40; pub const KERN_SHMALL: ::c_int = 41; pub const KERN_MSGMNI: ::c_int = 42; pub const KERN_SEM: ::c_int = 43; pub const KERN_SPARC_STOP_A: ::c_int = 44; pub const KERN_SHMMNI: ::c_int = 45; pub const KERN_OVERFLOWUID: ::c_int = 46; pub const KERN_OVERFLOWGID: ::c_int = 47; pub const KERN_SHMPATH: ::c_int = 48; pub const KERN_HOTPLUG: ::c_int = 49; pub const KERN_IEEE_EMULATION_WARNINGS: ::c_int = 50; pub const KERN_S390_USER_DEBUG_LOGGING: ::c_int = 51; pub const KERN_CORE_USES_PID: ::c_int = 52; pub const KERN_TAINTED: ::c_int = 53; pub const KERN_CADPID: ::c_int = 54; pub const KERN_PIDMAX: ::c_int = 55; pub const KERN_CORE_PATTERN: ::c_int = 56; pub const KERN_PANIC_ON_OOPS: ::c_int = 57; pub const KERN_HPPA_PWRSW: ::c_int = 58; pub const KERN_HPPA_UNALIGNED: ::c_int = 59; pub const KERN_PRINTK_RATELIMIT: ::c_int = 60; pub const KERN_PRINTK_RATELIMIT_BURST: ::c_int = 61; pub const KERN_PTY: ::c_int = 62; pub const KERN_NGROUPS_MAX: ::c_int = 63; pub const KERN_SPARC_SCONS_PWROFF: ::c_int = 64; pub const KERN_HZ_TIMER: ::c_int = 65; pub const KERN_UNKNOWN_NMI_PANIC: ::c_int = 66; pub const KERN_BOOTLOADER_TYPE: ::c_int = 67; pub const KERN_RANDOMIZE: ::c_int = 68; pub const KERN_SETUID_DUMPABLE: ::c_int = 69; pub const KERN_SPIN_RETRY: ::c_int = 70; pub const KERN_ACPI_VIDEO_FLAGS: ::c_int = 71; pub const KERN_IA64_UNALIGNED: ::c_int = 72; pub const KERN_COMPAT_LOG: ::c_int = 73; pub const KERN_MAX_LOCK_DEPTH: ::c_int = 74; pub const KERN_NMI_WATCHDOG: ::c_int = 75; pub const KERN_PANIC_ON_NMI: ::c_int = 76; pub const VM_OVERCOMMIT_MEMORY: ::c_int = 5; pub const VM_PAGE_CLUSTER: ::c_int = 10; pub const VM_DIRTY_BACKGROUND: ::c_int = 11; pub const VM_DIRTY_RATIO: ::c_int = 12; pub const VM_DIRTY_WB_CS: ::c_int = 13; pub const VM_DIRTY_EXPIRE_CS: ::c_int = 14; pub const VM_NR_PDFLUSH_THREADS: ::c_int = 15; pub const VM_OVERCOMMIT_RATIO: ::c_int = 16; pub const VM_PAGEBUF: ::c_int = 17; pub const VM_HUGETLB_PAGES: ::c_int = 18; pub const VM_SWAPPINESS: ::c_int = 19; pub const VM_LOWMEM_RESERVE_RATIO: ::c_int = 20; pub const VM_MIN_FREE_KBYTES: ::c_int = 21; pub const VM_MAX_MAP_COUNT: ::c_int = 22; pub const VM_LAPTOP_MODE: ::c_int = 23; pub const VM_BLOCK_DUMP: ::c_int = 24; pub const VM_HUGETLB_GROUP: ::c_int = 25; pub const VM_VFS_CACHE_PRESSURE: ::c_int = 26; pub const VM_LEGACY_VA_LAYOUT: ::c_int = 27; pub const VM_SWAP_TOKEN_TIMEOUT: ::c_int = 28; pub const VM_DROP_PAGECACHE: ::c_int = 29; pub const VM_PERCPU_PAGELIST_FRACTION: ::c_int = 30; pub const VM_ZONE_RECLAIM_MODE: ::c_int = 31; pub const VM_MIN_UNMAPPED: ::c_int = 32; pub const VM_PANIC_ON_OOM: ::c_int = 33; pub const VM_VDSO_ENABLED: ::c_int = 34; pub const VM_MIN_SLAB: ::c_int = 35; pub const NET_CORE: ::c_int = 1; pub const NET_ETHER: ::c_int = 2; pub const NET_802: ::c_int = 3; pub const NET_UNIX: ::c_int = 4; pub const NET_IPV4: ::c_int = 5; pub const NET_IPX: ::c_int = 6; pub const NET_ATALK: ::c_int = 7; pub const NET_NETROM: ::c_int = 8; pub const NET_AX25: ::c_int = 9; pub const NET_BRIDGE: ::c_int = 10; pub const NET_ROSE: ::c_int = 11; pub const NET_IPV6: ::c_int = 12; pub const NET_X25: ::c_int = 13; pub const NET_TR: ::c_int = 14; pub const NET_DECNET: ::c_int = 15; pub const NET_ECONET: ::c_int = 16; pub const NET_SCTP: ::c_int = 17; pub const NET_LLC: ::c_int = 18; pub const NET_NETFILTER: ::c_int = 19; pub const NET_DCCP: ::c_int = 20; pub const NET_IRDA: ::c_int = 412; // include/linux/sched.h pub const PF_VCPU: ::c_int = 0x00000001; pub const PF_IDLE: ::c_int = 0x00000002; pub const PF_EXITING: ::c_int = 0x00000004; pub const PF_POSTCOREDUMP: ::c_int = 0x00000008; pub const PF_IO_WORKER: ::c_int = 0x00000010; pub const PF_WQ_WORKER: ::c_int = 0x00000020; pub const PF_FORKNOEXEC: ::c_int = 0x00000040; pub const PF_MCE_PROCESS: ::c_int = 0x00000080; pub const PF_SUPERPRIV: ::c_int = 0x00000100; pub const PF_DUMPCORE: ::c_int = 0x00000200; pub const PF_SIGNALED: ::c_int = 0x00000400; pub const PF_MEMALLOC: ::c_int = 0x00000800; pub const PF_NPROC_EXCEEDED: ::c_int = 0x00001000; pub const PF_USED_MATH: ::c_int = 0x00002000; pub const PF_USER_WORKER: ::c_int = 0x00004000; pub const PF_NOFREEZE: ::c_int = 0x00008000; pub const PF_KSWAPD: ::c_int = 0x00020000; pub const PF_MEMALLOC_NOFS: ::c_int = 0x00040000; pub const PF_MEMALLOC_NOIO: ::c_int = 0x00080000; pub const PF_LOCAL_THROTTLE: ::c_int = 0x00100000; pub const PF_KTHREAD: ::c_int = 0x00200000; pub const PF_RANDOMIZE: ::c_int = 0x00400000; pub const PF_NO_SETAFFINITY: ::c_int = 0x04000000; pub const PF_MCE_EARLY: ::c_int = 0x08000000; pub const PF_MEMALLOC_PIN: ::c_int = 0x10000000; pub const CSIGNAL: ::c_int = 0x000000ff; pub const SCHED_NORMAL: ::c_int = 0; pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const SCHED_BATCH: ::c_int = 3; pub const SCHED_IDLE: ::c_int = 5; pub const SCHED_DEADLINE: ::c_int = 6; pub const SCHED_RESET_ON_FORK: ::c_int = 0x40000000; pub const CLONE_PIDFD: ::c_int = 0x1000; pub const SCHED_FLAG_RESET_ON_FORK: ::c_int = 0x01; pub const SCHED_FLAG_RECLAIM: ::c_int = 0x02; pub const SCHED_FLAG_DL_OVERRUN: ::c_int = 0x04; pub const SCHED_FLAG_KEEP_POLICY: ::c_int = 0x08; pub const SCHED_FLAG_KEEP_PARAMS: ::c_int = 0x10; pub const SCHED_FLAG_UTIL_CLAMP_MIN: ::c_int = 0x20; pub const SCHED_FLAG_UTIL_CLAMP_MAX: ::c_int = 0x40; pub const SCHED_FLAG_KEEP_ALL: ::c_int = SCHED_FLAG_KEEP_POLICY | SCHED_FLAG_KEEP_PARAMS; pub const SCHED_FLAG_UTIL_CLAMP: ::c_int = SCHED_FLAG_UTIL_CLAMP_MIN | SCHED_FLAG_UTIL_CLAMP_MAX; pub const SCHED_FLAG_ALL: ::c_int = SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM | SCHED_FLAG_DL_OVERRUN | SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP; f! { pub fn NLA_ALIGN(len: ::c_int) -> ::c_int { return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1) } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as usize) < ::mem::size_of::() { return 0 as *mut cmsghdr; }; let next = (cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.wrapping_offset(1)) as usize > max || next as usize + super::CMSG_ALIGN((*next).cmsg_len as usize) > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ALLOC_SIZE(count: ::c_int) -> ::size_t { let _dummy: cpu_set_t = ::mem::zeroed(); let size_in_bits = 8 * ::mem::size_of_val(&_dummy.bits[0]); ((count as ::size_t + size_in_bits - 1) / 8) as ::size_t } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> ::c_int { let mut s: u32 = 0; let size_of_mask = ::mem::size_of_val(&cpuset.bits[0]); for i in cpuset.bits[..(size / size_of_mask)].iter() { s += i.count_ones(); }; s as ::c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> ::c_int { CPU_COUNT_S(::mem::size_of::(), cpuset) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn SCTP_PR_INDEX(policy: ::c_int) -> ::c_int { policy >> 4 - 1 } pub fn SCTP_PR_POLICY(policy: ::c_int) -> ::c_int { policy & SCTP_PR_SCTP_MASK } pub fn SCTP_PR_SET_POLICY(flags: &mut ::c_int, policy: ::c_int) -> () { *flags &= !SCTP_PR_SCTP_MASK; *flags |= policy; () } pub fn major(dev: ::dev_t) -> ::c_uint { let mut major = 0; major |= (dev & 0x00000000000fff00) >> 8; major |= (dev & 0xfffff00000000000) >> 32; major as ::c_uint } pub fn minor(dev: ::dev_t) -> ::c_uint { let mut minor = 0; minor |= (dev & 0x00000000000000ff) >> 0; minor |= (dev & 0x00000ffffff00000) >> 12; minor as ::c_uint } pub fn IPTOS_TOS(tos: u8) -> u8 { tos & IPTOS_TOS_MASK } pub fn IPTOS_PREC(tos: u8) -> u8 { tos & IPTOS_PREC_MASK } pub fn RT_TOS(tos: u8) -> u8 { tos & ::IPTOS_TOS_MASK } pub fn RT_ADDRCLASS(flags: u32) -> u32 { flags >> 23 } pub fn RT_LOCALADDR(flags: u32) -> bool { (flags & RTF_ADDRCLASSMASK) == (RTF_LOCAL | RTF_INTERFACE) } pub fn SO_EE_OFFENDER(ee: *const ::sock_extended_err) -> *mut ::sockaddr { ee.offset(1) as *mut ::sockaddr } pub fn BPF_RVAL(code: ::__u32) -> ::__u32 { code & 0x18 } pub fn BPF_MISCOP(code: ::__u32) -> ::__u32 { code & 0xf8 } pub fn BPF_STMT(code: ::__u16, k: ::__u32) -> sock_filter { sock_filter{code: code, jt: 0, jf: 0, k: k} } pub fn BPF_JUMP(code: ::__u16, k: ::__u32, jt: ::__u8, jf: ::__u8) -> sock_filter { sock_filter{code: code, jt: jt, jf: jf, k: k} } } safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= (major & 0x00000fff) << 8; dev |= (major & 0xfffff000) << 32; dev |= (minor & 0x000000ff) << 0; dev |= (minor & 0xffffff00) << 12; dev } pub {const} fn SCTP_PR_TTL_ENABLED(policy: ::c_int) -> bool { policy == SCTP_PR_SCTP_TTL } pub {const} fn SCTP_PR_RTX_ENABLED(policy: ::c_int) -> bool { policy == SCTP_PR_SCTP_RTX } pub {const} fn SCTP_PR_PRIO_ENABLED(policy: ::c_int) -> bool { policy == SCTP_PR_SCTP_PRIO } } cfg_if! { if #[cfg(all(not(target_env = "uclibc"), not(target_env = "ohos")))] { extern "C" { pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_error(aiocbp: *const aiocb) -> ::c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn lio_listio( mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut ::sigevent, ) -> ::c_int; } } } cfg_if! { if #[cfg(not(target_env = "uclibc"))] { extern "C" { pub fn pwritev( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t, ) -> ::ssize_t; pub fn preadv( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t, ) -> ::ssize_t; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn getloadavg( loadavg: *mut ::c_double, nelem: ::c_int ) -> ::c_int; pub fn process_vm_readv( pid: ::pid_t, local_iov: *const ::iovec, liovcnt: ::c_ulong, remote_iov: *const ::iovec, riovcnt: ::c_ulong, flags: ::c_ulong, ) -> isize; pub fn process_vm_writev( pid: ::pid_t, local_iov: *const ::iovec, liovcnt: ::c_ulong, remote_iov: *const ::iovec, riovcnt: ::c_ulong, flags: ::c_ulong, ) -> isize; pub fn futimes( fd: ::c_int, times: *const ::timeval ) -> ::c_int; } } } // These functions are not available on OpenHarmony cfg_if! { if #[cfg(not(target_env = "ohos"))] { extern "C" { // Only `getspnam_r` is implemented for musl, out of all of the reenterant // functions from `shadow.h`. // https://git.musl-libc.org/cgit/musl/tree/include/shadow.h pub fn getspnam_r( name: *const ::c_char, spbuf: *mut spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut spwd, ) -> ::c_int; pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, abs_timeout: *const ::timespec, ) -> ::ssize_t; pub fn mq_send( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_timedsend( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; pub fn mq_setattr( mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr ) -> ::c_int; pub fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; pub fn pthread_mutexattr_getrobust( attr: *const pthread_mutexattr_t, robustness: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setrobust( attr: *mut pthread_mutexattr_t, robustness: ::c_int, ) -> ::c_int; } } } extern "C" { #[cfg_attr( not(any(target_env = "musl", target_env = "ohos")), link_name = "__xpg_strerror_r" )] pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); pub fn drand48() -> ::c_double; pub fn erand48(xseed: *mut ::c_ushort) -> ::c_double; pub fn lrand48() -> ::c_long; pub fn nrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn mrand48() -> ::c_long; pub fn jrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn srand48(seed: ::c_long); pub fn seed48(xseed: *mut ::c_ushort) -> *mut ::c_ushort; pub fn lcong48(p: *mut ::c_ushort); pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut ::group; pub fn setspent(); pub fn endspent(); pub fn getspent() -> *mut spwd; pub fn getspnam(name: *const ::c_char) -> *mut spwd; // System V IPC pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn semget(key: ::key_t, nsems: ::c_int, semflag: ::c_int) -> ::c_int; pub fn semop(semid: ::c_int, sops: *mut ::sembuf, nsops: ::size_t) -> ::c_int; pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn msgsnd( msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, msgflg: ::c_int, ) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn __errno_location() -> *mut ::c_int; pub fn fallocate(fd: ::c_int, mode: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn readahead(fd: ::c_int, offset: ::off64_t, count: ::size_t) -> ::ssize_t; pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn lgetxattr( path: *const c_char, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn fgetxattr( filedes: ::c_int, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn lsetxattr( path: *const c_char, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn fsetxattr( filedes: ::c_int, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn llistxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn flistxattr(filedes: ::c_int, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int; pub fn lremovexattr(path: *const c_char, name: *const c_char) -> ::c_int; pub fn fremovexattr(filedes: ::c_int, name: *const c_char) -> ::c_int; pub fn signalfd(fd: ::c_int, mask: *const ::sigset_t, flags: ::c_int) -> ::c_int; pub fn timerfd_create(clockid: ::clockid_t, flags: ::c_int) -> ::c_int; pub fn timerfd_gettime(fd: ::c_int, curr_value: *mut itimerspec) -> ::c_int; pub fn timerfd_settime( fd: ::c_int, flags: ::c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> ::c_int; pub fn quotactl( cmd: ::c_int, special: *const ::c_char, id: ::c_int, data: *mut ::c_char, ) -> ::c_int; pub fn epoll_pwait( epfd: ::c_int, events: *mut ::epoll_event, maxevents: ::c_int, timeout: ::c_int, sigmask: *const ::sigset_t, ) -> ::c_int; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int, ) -> ::c_int; pub fn pthread_getaffinity_np( thread: ::pthread_t, cpusetsize: ::size_t, cpuset: *mut ::cpu_set_t, ) -> ::c_int; pub fn pthread_setaffinity_np( thread: ::pthread_t, cpusetsize: ::size_t, cpuset: *const ::cpu_set_t, ) -> ::c_int; pub fn pthread_setschedprio(native: ::pthread_t, priority: ::c_int) -> ::c_int; pub fn reboot(how_to: ::c_int) -> ::c_int; pub fn setfsgid(gid: ::gid_t) -> ::c_int; pub fn setfsuid(uid: ::uid_t) -> ::c_int; // Not available now on Android pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn sync_file_range( fd: ::c_int, offset: ::off64_t, nbytes: ::off64_t, flags: ::c_uint, ) -> ::c_int; pub fn mremap( addr: *mut ::c_void, len: ::size_t, new_len: ::size_t, flags: ::c_int, ... ) -> *mut ::c_void; pub fn glob( pattern: *const c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn remap_file_pages( addr: *mut ::c_void, size: ::size_t, prot: ::c_int, pgoff: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn vhangup() -> ::c_int; pub fn sync(); pub fn syncfs(fd: ::c_int) -> ::c_int; pub fn syscall(num: ::c_long, ...) -> ::c_long; pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) -> ::c_int; pub fn sched_setaffinity( pid: ::pid_t, cpusetsize: ::size_t, cpuset: *const cpu_set_t, ) -> ::c_int; pub fn epoll_create(size: ::c_int) -> ::c_int; pub fn epoll_create1(flags: ::c_int) -> ::c_int; pub fn epoll_wait( epfd: ::c_int, events: *mut ::epoll_event, maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut ::sched_param, ) -> ::c_int; pub fn unshare(flags: ::c_int) -> ::c_int; pub fn umount(target: *const ::c_char) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn tee(fd_in: ::c_int, fd_out: ::c_int, len: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn splice( fd_in: ::c_int, off_in: *mut ::loff_t, fd_out: ::c_int, off_out: *mut ::loff_t, len: ::size_t, flags: ::c_uint, ) -> ::ssize_t; pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; pub fn eventfd_read(fd: ::c_int, value: *mut eventfd_t) -> ::c_int; pub fn eventfd_write(fd: ::c_int, value: eventfd_t) -> ::c_int; pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn setns(fd: ::c_int, nstype: ::c_int) -> ::c_int; pub fn swapoff(path: *const ::c_char) -> ::c_int; pub fn vmsplice( fd: ::c_int, iov: *const ::iovec, nr_segs: ::size_t, flags: ::c_uint, ) -> ::ssize_t; pub fn mount( src: *const ::c_char, target: *const ::c_char, fstype: *const ::c_char, flags: ::c_ulong, data: *const ::c_void, ) -> ::c_int; pub fn personality(persona: ::c_ulong) -> ::c_int; pub fn prctl(option: ::c_int, ...) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int; pub fn ppoll( fds: *mut ::pollfd, nfds: nfds_t, timeout: *const ::timespec, sigmask: *const sigset_t, ) -> ::c_int; pub fn pthread_mutexattr_getprotocol( attr: *const pthread_mutexattr_t, protocol: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setprotocol( attr: *mut pthread_mutexattr_t, protocol: ::c_int, ) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_barrierattr_init(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_destroy(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_getpshared( attr: *const ::pthread_barrierattr_t, shared: *mut ::c_int, ) -> ::c_int; pub fn pthread_barrierattr_setpshared( attr: *mut ::pthread_barrierattr_t, shared: ::c_int, ) -> ::c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const ::pthread_barrierattr_t, count: ::c_uint, ) -> ::c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn clone( cb: extern "C" fn(*mut ::c_void) -> ::c_int, child_stack: *mut ::c_void, flags: ::c_int, arg: *mut ::c_void, ... ) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getinheritsched( attr: *const ::pthread_attr_t, inheritsched: *mut ::c_int, ) -> ::c_int; pub fn pthread_attr_setinheritsched( attr: *mut ::pthread_attr_t, inheritsched: ::c_int, ) -> ::c_int; pub fn pthread_attr_getschedpolicy( attr: *const ::pthread_attr_t, policy: *mut ::c_int, ) -> ::c_int; pub fn pthread_attr_setschedpolicy(attr: *mut ::pthread_attr_t, policy: ::c_int) -> ::c_int; pub fn pthread_attr_getschedparam( attr: *const ::pthread_attr_t, param: *mut ::sched_param, ) -> ::c_int; pub fn pthread_attr_setschedparam( attr: *mut ::pthread_attr_t, param: *const ::sched_param, ) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn sysinfo(info: *mut ::sysinfo) -> ::c_int; pub fn umount2(target: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn swapon(path: *const ::c_char, swapflags: ::c_int) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sendfile( out_fd: ::c_int, in_fd: ::c_int, offset: *mut off_t, count: ::size_t, ) -> ::ssize_t; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn getgrouplist( user: *const ::c_char, group: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut ::dl_phdr_info, size: ::size_t, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; pub fn setmntent(filename: *const ::c_char, ty: *const ::c_char) -> *mut ::FILE; pub fn getmntent(stream: *mut ::FILE) -> *mut ::mntent; pub fn addmntent(stream: *mut ::FILE, mnt: *const ::mntent) -> ::c_int; pub fn endmntent(streamp: *mut ::FILE) -> ::c_int; pub fn hasmntopt(mnt: *const ::mntent, opt: *const ::c_char) -> *mut ::c_char; pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, ) -> ::c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const ::sched_param, ) -> ::c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, newfd: ::c_int, ) -> ::c_int; pub fn fread_unlocked( buf: *mut ::c_void, size: ::size_t, nobj: ::size_t, stream: *mut ::FILE, ) -> ::size_t; pub fn inotify_rm_watch(fd: ::c_int, wd: ::c_int) -> ::c_int; pub fn inotify_init() -> ::c_int; pub fn inotify_init1(flags: ::c_int) -> ::c_int; pub fn inotify_add_watch(fd: ::c_int, path: *const ::c_char, mask: u32) -> ::c_int; pub fn fanotify_init(flags: ::c_uint, event_f_flags: ::c_uint) -> ::c_int; pub fn regcomp(preg: *mut ::regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regexec( preg: *const ::regex_t, input: *const ::c_char, nmatch: ::size_t, pmatch: *mut regmatch_t, eflags: ::c_int, ) -> ::c_int; pub fn regerror( errcode: ::c_int, preg: *const ::regex_t, errbuf: *mut ::c_char, errbuf_size: ::size_t, ) -> ::size_t; pub fn regfree(preg: *mut ::regex_t); pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, inbytesleft: *mut ::size_t, outbuf: *mut *mut ::c_char, outbytesleft: *mut ::size_t, ) -> ::size_t; pub fn iconv_close(cd: iconv_t) -> ::c_int; pub fn gettid() -> ::pid_t; pub fn timer_create( clockid: ::clockid_t, sevp: *mut ::sigevent, timerid: *mut ::timer_t, ) -> ::c_int; pub fn timer_delete(timerid: ::timer_t) -> ::c_int; pub fn timer_getoverrun(timerid: ::timer_t) -> ::c_int; pub fn timer_gettime(timerid: ::timer_t, curr_value: *mut ::itimerspec) -> ::c_int; pub fn timer_settime( timerid: ::timer_t, flags: ::c_int, new_value: *const ::itimerspec, old_value: *mut ::itimerspec, ) -> ::c_int; pub fn gethostid() -> ::c_long; pub fn pthread_getcpuclockid(thread: ::pthread_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; pub fn sched_getcpu() -> ::c_int; pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int; pub fn getopt_long( argc: ::c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut ::c_int, ) -> ::c_int; pub fn pthread_once(control: *mut pthread_once_t, routine: extern "C" fn()) -> ::c_int; pub fn copy_file_range( fd_in: ::c_int, off_in: *mut ::off64_t, fd_out: ::c_int, off_out: *mut ::off64_t, len: ::size_t, flags: ::c_uint, ) -> ::ssize_t; } // LFS64 extensions // // * musl has 64-bit versions only so aliases the LFS64 symbols to the standard ones cfg_if! { if #[cfg(not(target_env = "musl"))] { extern "C" { pub fn fallocate64( fd: ::c_int, mode: ::c_int, offset: ::off64_t, len: ::off64_t ) -> ::c_int; pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int; pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn freopen64( filename: *const c_char, mode: *const c_char, file: *mut ::FILE, ) -> *mut ::FILE; pub fn fseeko64(stream: *mut ::FILE, offset: ::off64_t, whence: ::c_int) -> ::c_int; pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int; pub fn ftello64(stream: *mut ::FILE) -> ::off64_t; pub fn posix_fallocate64(fd: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; pub fn sendfile64( out_fd: ::c_int, in_fd: ::c_int, offset: *mut off64_t, count: ::size_t, ) -> ::ssize_t; pub fn tmpfile64() -> *mut ::FILE; } } } cfg_if! { if #[cfg(target_env = "uclibc")] { mod uclibc; pub use self::uclibc::*; } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { mod musl; pub use self::musl::*; } else if #[cfg(target_env = "gnu")] { mod gnu; pub use self::gnu::*; } } mod arch; pub use self::arch::*; cfg_if! { if #[cfg(libc_align)] { #[macro_use] mod align; } else { #[macro_use] mod no_align; } } expand_align!(); cfg_if! { if #[cfg(libc_non_exhaustive)] { mod non_exhaustive; pub use self::non_exhaustive::*; } } libc/src/unix/linux_like/linux/gnu/0000775000175000017500000000000014661133735020321 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/0000775000175000017500000000000014661133735020707 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/powerpc.rs0000644000175000017500000007224714661133735022746 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = i32; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct ipc_perm { __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, __seq: u32, __pad1: u32, __glibc_reserved1: u64, __glibc_reserved2: u64, } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_ushort, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, __glibc_reserved1: ::c_uint, pub shm_atime: ::time_t, __glibc_reserved2: ::c_uint, pub shm_dtime: ::time_t, __glibc_reserved3: ::c_uint, pub shm_ctime: ::time_t, __glibc_reserved4: ::c_uint, pub shm_segsz: ::size_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __glibc_reserved5: ::c_ulong, __glibc_reserved6: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, __glibc_reserved1: ::c_uint, pub msg_stime: ::time_t, __glibc_reserved2: ::c_uint, pub msg_rtime: ::time_t, __glibc_reserved3: ::c_uint, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_DIRECT: ::c_int = 0x20000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_LARGEFILE: ::c_int = 0o200000; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_LOCKED: ::c_int = 0x00080; pub const MAP_NORESERVE: ::c_int = 0x00040; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 58; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const MCL_CURRENT: ::c_int = 0x2000; pub const MCL_FUTURE: ::c_int = 0x4000; pub const MCL_ONFAULT: ::c_int = 0x8000; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGSTKSZ: ::size_t = 0x4000; pub const MINSIGSTKSZ: ::size_t = 4096; pub const CBAUD: ::tcflag_t = 0xff; pub const TAB1: ::tcflag_t = 0x400; pub const TAB2: ::tcflag_t = 0x800; pub const TAB3: ::tcflag_t = 0xc00; pub const CR1: ::tcflag_t = 0x1000; pub const CR2: ::tcflag_t = 0x2000; pub const CR3: ::tcflag_t = 0x3000; pub const FF1: ::tcflag_t = 0x4000; pub const BS1: ::tcflag_t = 0x8000; pub const VT1: ::tcflag_t = 0x10000; pub const VWERASE: usize = 0xa; pub const VREPRINT: usize = 0xb; pub const VSUSP: usize = 0xc; pub const VSTART: usize = 0xd; pub const VSTOP: usize = 0xe; pub const VDISCARD: usize = 0x10; pub const VTIME: usize = 0x7; pub const IXON: ::tcflag_t = 0x200; pub const IXOFF: ::tcflag_t = 0x400; pub const ONLCR: ::tcflag_t = 0x2; pub const CSIZE: ::tcflag_t = 0x300; pub const CS6: ::tcflag_t = 0x100; pub const CS7: ::tcflag_t = 0x200; pub const CS8: ::tcflag_t = 0x300; pub const CSTOPB: ::tcflag_t = 0x400; pub const CREAD: ::tcflag_t = 0x800; pub const PARENB: ::tcflag_t = 0x1000; pub const PARODD: ::tcflag_t = 0x2000; pub const HUPCL: ::tcflag_t = 0x4000; pub const CLOCAL: ::tcflag_t = 0x8000; pub const ECHOKE: ::tcflag_t = 0x1; pub const ECHOE: ::tcflag_t = 0x2; pub const ECHOK: ::tcflag_t = 0x4; pub const ECHONL: ::tcflag_t = 0x10; pub const ECHOPRT: ::tcflag_t = 0x20; pub const ECHOCTL: ::tcflag_t = 0x40; pub const ISIG: ::tcflag_t = 0x80; pub const ICANON: ::tcflag_t = 0x100; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; pub const VSWTC: usize = 9; pub const OLCUC: ::tcflag_t = 0o000004; pub const NLDLY: ::tcflag_t = 0o001400; pub const CRDLY: ::tcflag_t = 0o030000; pub const TABDLY: ::tcflag_t = 0o006000; pub const BSDLY: ::tcflag_t = 0o100000; pub const FFDLY: ::tcflag_t = 0o040000; pub const VTDLY: ::tcflag_t = 0o200000; pub const XTABS: ::tcflag_t = 0o006000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const CBAUDEX: ::speed_t = 0o000020; pub const B57600: ::speed_t = 0o0020; pub const B115200: ::speed_t = 0o0021; pub const B230400: ::speed_t = 0o0022; pub const B460800: ::speed_t = 0o0023; pub const B500000: ::speed_t = 0o0024; pub const B576000: ::speed_t = 0o0025; pub const B921600: ::speed_t = 0o0026; pub const B1000000: ::speed_t = 0o0027; pub const B1152000: ::speed_t = 0o0030; pub const B1500000: ::speed_t = 0o0031; pub const B2000000: ::speed_t = 0o0032; pub const B2500000: ::speed_t = 0o0033; pub const B3000000: ::speed_t = 0o0034; pub const B3500000: ::speed_t = 0o0035; pub const B4000000: ::speed_t = 0o0036; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: ::tcflag_t = 0x400; pub const TOSTOP: ::tcflag_t = 0x400000; pub const FLUSHO: ::tcflag_t = 0x800000; pub const EXTPROC: ::tcflag_t = 0x10000000; pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_break: ::c_long = 17; pub const SYS_oldstat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_stime: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_oldfstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_stty: ::c_long = 31; pub const SYS_gtty: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_ftime: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_prof: ::c_long = 44; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_lock: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_mpx: ::c_long = 56; pub const SYS_setpgid: ::c_long = 57; pub const SYS_ulimit: ::c_long = 58; pub const SYS_oldolduname: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_oldlstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_profil: ::c_long = 98; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_ioperm: ::c_long = 101; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_olduname: ::c_long = 109; pub const SYS_iopl: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_vm86: ::c_long = 113; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_modify_ldt: ::c_long = 123; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; /* Syscall for Andrew File System */ pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_query_module: ::c_long = 166; pub const SYS_poll: ::c_long = 167; pub const SYS_nfsservctl: ::c_long = 168; pub const SYS_setresgid: ::c_long = 169; pub const SYS_getresgid: ::c_long = 170; pub const SYS_prctl: ::c_long = 171; pub const SYS_rt_sigreturn: ::c_long = 172; pub const SYS_rt_sigaction: ::c_long = 173; pub const SYS_rt_sigprocmask: ::c_long = 174; pub const SYS_rt_sigpending: ::c_long = 175; pub const SYS_rt_sigtimedwait: ::c_long = 176; pub const SYS_rt_sigqueueinfo: ::c_long = 177; pub const SYS_rt_sigsuspend: ::c_long = 178; pub const SYS_pread64: ::c_long = 179; pub const SYS_pwrite64: ::c_long = 180; pub const SYS_chown: ::c_long = 181; pub const SYS_getcwd: ::c_long = 182; pub const SYS_capget: ::c_long = 183; pub const SYS_capset: ::c_long = 184; pub const SYS_sigaltstack: ::c_long = 185; pub const SYS_sendfile: ::c_long = 186; pub const SYS_getpmsg: ::c_long = 187; /* some people actually want streams */ pub const SYS_putpmsg: ::c_long = 188; /* some people actually want streams */ pub const SYS_vfork: ::c_long = 189; pub const SYS_ugetrlimit: ::c_long = 190; /* SuS compliant getrlimit */ pub const SYS_readahead: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_pciconfig_read: ::c_long = 198; pub const SYS_pciconfig_write: ::c_long = 199; pub const SYS_pciconfig_iobase: ::c_long = 200; pub const SYS_multiplexer: ::c_long = 201; pub const SYS_getdents64: ::c_long = 202; pub const SYS_pivot_root: ::c_long = 203; pub const SYS_fcntl64: ::c_long = 204; pub const SYS_madvise: ::c_long = 205; pub const SYS_mincore: ::c_long = 206; pub const SYS_gettid: ::c_long = 207; pub const SYS_tkill: ::c_long = 208; pub const SYS_setxattr: ::c_long = 209; pub const SYS_lsetxattr: ::c_long = 210; pub const SYS_fsetxattr: ::c_long = 211; pub const SYS_getxattr: ::c_long = 212; pub const SYS_lgetxattr: ::c_long = 213; pub const SYS_fgetxattr: ::c_long = 214; pub const SYS_listxattr: ::c_long = 215; pub const SYS_llistxattr: ::c_long = 216; pub const SYS_flistxattr: ::c_long = 217; pub const SYS_removexattr: ::c_long = 218; pub const SYS_lremovexattr: ::c_long = 219; pub const SYS_fremovexattr: ::c_long = 220; pub const SYS_futex: ::c_long = 221; pub const SYS_sched_setaffinity: ::c_long = 222; pub const SYS_sched_getaffinity: ::c_long = 223; pub const SYS_tuxcall: ::c_long = 225; pub const SYS_sendfile64: ::c_long = 226; pub const SYS_io_setup: ::c_long = 227; pub const SYS_io_destroy: ::c_long = 228; pub const SYS_io_getevents: ::c_long = 229; pub const SYS_io_submit: ::c_long = 230; pub const SYS_io_cancel: ::c_long = 231; pub const SYS_set_tid_address: ::c_long = 232; pub const SYS_fadvise64: ::c_long = 233; pub const SYS_exit_group: ::c_long = 234; pub const SYS_lookup_dcookie: ::c_long = 235; pub const SYS_epoll_create: ::c_long = 236; pub const SYS_epoll_ctl: ::c_long = 237; pub const SYS_epoll_wait: ::c_long = 238; pub const SYS_remap_file_pages: ::c_long = 239; pub const SYS_timer_create: ::c_long = 240; pub const SYS_timer_settime: ::c_long = 241; pub const SYS_timer_gettime: ::c_long = 242; pub const SYS_timer_getoverrun: ::c_long = 243; pub const SYS_timer_delete: ::c_long = 244; pub const SYS_clock_settime: ::c_long = 245; pub const SYS_clock_gettime: ::c_long = 246; pub const SYS_clock_getres: ::c_long = 247; pub const SYS_clock_nanosleep: ::c_long = 248; pub const SYS_swapcontext: ::c_long = 249; pub const SYS_tgkill: ::c_long = 250; pub const SYS_utimes: ::c_long = 251; pub const SYS_statfs64: ::c_long = 252; pub const SYS_fstatfs64: ::c_long = 253; pub const SYS_fadvise64_64: ::c_long = 254; pub const SYS_rtas: ::c_long = 255; pub const SYS_sys_debug_setcontext: ::c_long = 256; pub const SYS_migrate_pages: ::c_long = 258; pub const SYS_mbind: ::c_long = 259; pub const SYS_get_mempolicy: ::c_long = 260; pub const SYS_set_mempolicy: ::c_long = 261; pub const SYS_mq_open: ::c_long = 262; pub const SYS_mq_unlink: ::c_long = 263; pub const SYS_mq_timedsend: ::c_long = 264; pub const SYS_mq_timedreceive: ::c_long = 265; pub const SYS_mq_notify: ::c_long = 266; pub const SYS_mq_getsetattr: ::c_long = 267; pub const SYS_kexec_load: ::c_long = 268; pub const SYS_add_key: ::c_long = 269; pub const SYS_request_key: ::c_long = 270; pub const SYS_keyctl: ::c_long = 271; pub const SYS_waitid: ::c_long = 272; pub const SYS_ioprio_set: ::c_long = 273; pub const SYS_ioprio_get: ::c_long = 274; pub const SYS_inotify_init: ::c_long = 275; pub const SYS_inotify_add_watch: ::c_long = 276; pub const SYS_inotify_rm_watch: ::c_long = 277; pub const SYS_spu_run: ::c_long = 278; pub const SYS_spu_create: ::c_long = 279; pub const SYS_pselect6: ::c_long = 280; pub const SYS_ppoll: ::c_long = 281; pub const SYS_unshare: ::c_long = 282; pub const SYS_splice: ::c_long = 283; pub const SYS_tee: ::c_long = 284; pub const SYS_vmsplice: ::c_long = 285; pub const SYS_openat: ::c_long = 286; pub const SYS_mkdirat: ::c_long = 287; pub const SYS_mknodat: ::c_long = 288; pub const SYS_fchownat: ::c_long = 289; pub const SYS_futimesat: ::c_long = 290; pub const SYS_fstatat64: ::c_long = 291; pub const SYS_unlinkat: ::c_long = 292; pub const SYS_renameat: ::c_long = 293; pub const SYS_linkat: ::c_long = 294; pub const SYS_symlinkat: ::c_long = 295; pub const SYS_readlinkat: ::c_long = 296; pub const SYS_fchmodat: ::c_long = 297; pub const SYS_faccessat: ::c_long = 298; pub const SYS_get_robust_list: ::c_long = 299; pub const SYS_set_robust_list: ::c_long = 300; pub const SYS_move_pages: ::c_long = 301; pub const SYS_getcpu: ::c_long = 302; pub const SYS_epoll_pwait: ::c_long = 303; pub const SYS_utimensat: ::c_long = 304; pub const SYS_signalfd: ::c_long = 305; pub const SYS_timerfd_create: ::c_long = 306; pub const SYS_eventfd: ::c_long = 307; pub const SYS_sync_file_range2: ::c_long = 308; pub const SYS_fallocate: ::c_long = 309; pub const SYS_subpage_prot: ::c_long = 310; pub const SYS_timerfd_settime: ::c_long = 311; pub const SYS_timerfd_gettime: ::c_long = 312; pub const SYS_signalfd4: ::c_long = 313; pub const SYS_eventfd2: ::c_long = 314; pub const SYS_epoll_create1: ::c_long = 315; pub const SYS_dup3: ::c_long = 316; pub const SYS_pipe2: ::c_long = 317; pub const SYS_inotify_init1: ::c_long = 318; pub const SYS_perf_event_open: ::c_long = 319; pub const SYS_preadv: ::c_long = 320; pub const SYS_pwritev: ::c_long = 321; pub const SYS_rt_tgsigqueueinfo: ::c_long = 322; pub const SYS_fanotify_init: ::c_long = 323; pub const SYS_fanotify_mark: ::c_long = 324; pub const SYS_prlimit64: ::c_long = 325; pub const SYS_socket: ::c_long = 326; pub const SYS_bind: ::c_long = 327; pub const SYS_connect: ::c_long = 328; pub const SYS_listen: ::c_long = 329; pub const SYS_accept: ::c_long = 330; pub const SYS_getsockname: ::c_long = 331; pub const SYS_getpeername: ::c_long = 332; pub const SYS_socketpair: ::c_long = 333; pub const SYS_send: ::c_long = 334; pub const SYS_sendto: ::c_long = 335; pub const SYS_recv: ::c_long = 336; pub const SYS_recvfrom: ::c_long = 337; pub const SYS_shutdown: ::c_long = 338; pub const SYS_setsockopt: ::c_long = 339; pub const SYS_getsockopt: ::c_long = 340; pub const SYS_sendmsg: ::c_long = 341; pub const SYS_recvmsg: ::c_long = 342; pub const SYS_recvmmsg: ::c_long = 343; pub const SYS_accept4: ::c_long = 344; pub const SYS_name_to_handle_at: ::c_long = 345; pub const SYS_open_by_handle_at: ::c_long = 346; pub const SYS_clock_adjtime: ::c_long = 347; pub const SYS_syncfs: ::c_long = 348; pub const SYS_sendmmsg: ::c_long = 349; pub const SYS_setns: ::c_long = 350; pub const SYS_process_vm_readv: ::c_long = 351; pub const SYS_process_vm_writev: ::c_long = 352; pub const SYS_finit_module: ::c_long = 353; pub const SYS_kcmp: ::c_long = 354; pub const SYS_sched_setattr: ::c_long = 355; pub const SYS_sched_getattr: ::c_long = 356; pub const SYS_renameat2: ::c_long = 357; pub const SYS_seccomp: ::c_long = 358; pub const SYS_getrandom: ::c_long = 359; pub const SYS_memfd_create: ::c_long = 360; pub const SYS_bpf: ::c_long = 361; pub const SYS_execveat: ::c_long = 362; pub const SYS_switch_endian: ::c_long = 363; pub const SYS_userfaultfd: ::c_long = 364; pub const SYS_membarrier: ::c_long = 365; pub const SYS_mlock2: ::c_long = 378; pub const SYS_copy_file_range: ::c_long = 379; pub const SYS_preadv2: ::c_long = 380; pub const SYS_pwritev2: ::c_long = 381; pub const SYS_kexec_file_load: ::c_long = 382; pub const SYS_statx: ::c_long = 383; pub const SYS_rseq: ::c_long = 387; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; libc/src/unix/linux_like/linux/gnu/b32/arm/0000775000175000017500000000000014661133735021466 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs0000644000175000017500000007401714661133735022622 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct stat64 { pub st_dev: ::dev_t, __pad1: ::c_uint, __st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_uint, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino64_t, } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_ulong, pub shm_dtime: ::time_t, __unused2: ::c_ulong, pub shm_ctime: ::time_t, __unused3: ::c_ulong, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __glibc_reserved1: ::c_ulong, pub msg_rtime: ::time_t, __glibc_reserved2: ::c_ulong, pub msg_ctime: ::time_t, __glibc_reserved3: ::c_ulong, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct mcontext_t { pub trap_no: ::c_ulong, pub error_code: ::c_ulong, pub oldmask: ::c_ulong, pub arm_r0: ::c_ulong, pub arm_r1: ::c_ulong, pub arm_r2: ::c_ulong, pub arm_r3: ::c_ulong, pub arm_r4: ::c_ulong, pub arm_r5: ::c_ulong, pub arm_r6: ::c_ulong, pub arm_r7: ::c_ulong, pub arm_r8: ::c_ulong, pub arm_r9: ::c_ulong, pub arm_r10: ::c_ulong, pub arm_fp: ::c_ulong, pub arm_ip: ::c_ulong, pub arm_sp: ::c_ulong, pub arm_lr: ::c_ulong, pub arm_pc: ::c_ulong, pub arm_cpsr: ::c_ulong, pub fault_address: ::c_ulong, } pub struct user_regs { pub arm_r0: ::c_ulong, pub arm_r1: ::c_ulong, pub arm_r2: ::c_ulong, pub arm_r3: ::c_ulong, pub arm_r4: ::c_ulong, pub arm_r5: ::c_ulong, pub arm_r6: ::c_ulong, pub arm_r7: ::c_ulong, pub arm_r8: ::c_ulong, pub arm_r9: ::c_ulong, pub arm_r10: ::c_ulong, pub arm_fp: ::c_ulong, pub arm_ip: ::c_ulong, pub arm_sp: ::c_ulong, pub arm_lr: ::c_ulong, pub arm_pc: ::c_ulong, pub arm_cpsr: ::c_ulong, pub arm_orig_r0: ::c_ulong, } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_LARGEFILE: ::c_int = 0o400000; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_ptrace: ::c_long = 26; pub const SYS_pause: ::c_long = 29; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_setpgid: ::c_long = 57; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_symlink: ::c_long = 83; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_vhangup: ::c_long = 111; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid: ::c_long = 170; pub const SYS_getresgid: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_chown: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_vfork: ::c_long = 190; pub const SYS_ugetrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_lchown32: ::c_long = 198; pub const SYS_getuid32: ::c_long = 199; pub const SYS_getgid32: ::c_long = 200; pub const SYS_geteuid32: ::c_long = 201; pub const SYS_getegid32: ::c_long = 202; pub const SYS_setreuid32: ::c_long = 203; pub const SYS_setregid32: ::c_long = 204; pub const SYS_getgroups32: ::c_long = 205; pub const SYS_setgroups32: ::c_long = 206; pub const SYS_fchown32: ::c_long = 207; pub const SYS_setresuid32: ::c_long = 208; pub const SYS_getresuid32: ::c_long = 209; pub const SYS_setresgid32: ::c_long = 210; pub const SYS_getresgid32: ::c_long = 211; pub const SYS_chown32: ::c_long = 212; pub const SYS_setuid32: ::c_long = 213; pub const SYS_setgid32: ::c_long = 214; pub const SYS_setfsuid32: ::c_long = 215; pub const SYS_setfsgid32: ::c_long = 216; pub const SYS_getdents64: ::c_long = 217; pub const SYS_pivot_root: ::c_long = 218; pub const SYS_mincore: ::c_long = 219; pub const SYS_madvise: ::c_long = 220; pub const SYS_fcntl64: ::c_long = 221; pub const SYS_gettid: ::c_long = 224; pub const SYS_readahead: ::c_long = 225; pub const SYS_setxattr: ::c_long = 226; pub const SYS_lsetxattr: ::c_long = 227; pub const SYS_fsetxattr: ::c_long = 228; pub const SYS_getxattr: ::c_long = 229; pub const SYS_lgetxattr: ::c_long = 230; pub const SYS_fgetxattr: ::c_long = 231; pub const SYS_listxattr: ::c_long = 232; pub const SYS_llistxattr: ::c_long = 233; pub const SYS_flistxattr: ::c_long = 234; pub const SYS_removexattr: ::c_long = 235; pub const SYS_lremovexattr: ::c_long = 236; pub const SYS_fremovexattr: ::c_long = 237; pub const SYS_tkill: ::c_long = 238; pub const SYS_sendfile64: ::c_long = 239; pub const SYS_futex: ::c_long = 240; pub const SYS_sched_setaffinity: ::c_long = 241; pub const SYS_sched_getaffinity: ::c_long = 242; pub const SYS_io_setup: ::c_long = 243; pub const SYS_io_destroy: ::c_long = 244; pub const SYS_io_getevents: ::c_long = 245; pub const SYS_io_submit: ::c_long = 246; pub const SYS_io_cancel: ::c_long = 247; pub const SYS_exit_group: ::c_long = 248; pub const SYS_lookup_dcookie: ::c_long = 249; pub const SYS_epoll_create: ::c_long = 250; pub const SYS_epoll_ctl: ::c_long = 251; pub const SYS_epoll_wait: ::c_long = 252; pub const SYS_remap_file_pages: ::c_long = 253; pub const SYS_set_tid_address: ::c_long = 256; pub const SYS_timer_create: ::c_long = 257; pub const SYS_timer_settime: ::c_long = 258; pub const SYS_timer_gettime: ::c_long = 259; pub const SYS_timer_getoverrun: ::c_long = 260; pub const SYS_timer_delete: ::c_long = 261; pub const SYS_clock_settime: ::c_long = 262; pub const SYS_clock_gettime: ::c_long = 263; pub const SYS_clock_getres: ::c_long = 264; pub const SYS_clock_nanosleep: ::c_long = 265; pub const SYS_statfs64: ::c_long = 266; pub const SYS_fstatfs64: ::c_long = 267; pub const SYS_tgkill: ::c_long = 268; pub const SYS_utimes: ::c_long = 269; pub const SYS_arm_fadvise64_64: ::c_long = 270; pub const SYS_pciconfig_iobase: ::c_long = 271; pub const SYS_pciconfig_read: ::c_long = 272; pub const SYS_pciconfig_write: ::c_long = 273; pub const SYS_mq_open: ::c_long = 274; pub const SYS_mq_unlink: ::c_long = 275; pub const SYS_mq_timedsend: ::c_long = 276; pub const SYS_mq_timedreceive: ::c_long = 277; pub const SYS_mq_notify: ::c_long = 278; pub const SYS_mq_getsetattr: ::c_long = 279; pub const SYS_waitid: ::c_long = 280; pub const SYS_socket: ::c_long = 281; pub const SYS_bind: ::c_long = 282; pub const SYS_connect: ::c_long = 283; pub const SYS_listen: ::c_long = 284; pub const SYS_accept: ::c_long = 285; pub const SYS_getsockname: ::c_long = 286; pub const SYS_getpeername: ::c_long = 287; pub const SYS_socketpair: ::c_long = 288; pub const SYS_send: ::c_long = 289; pub const SYS_sendto: ::c_long = 290; pub const SYS_recv: ::c_long = 291; pub const SYS_recvfrom: ::c_long = 292; pub const SYS_shutdown: ::c_long = 293; pub const SYS_setsockopt: ::c_long = 294; pub const SYS_getsockopt: ::c_long = 295; pub const SYS_sendmsg: ::c_long = 296; pub const SYS_recvmsg: ::c_long = 297; pub const SYS_semop: ::c_long = 298; pub const SYS_semget: ::c_long = 299; pub const SYS_semctl: ::c_long = 300; pub const SYS_msgsnd: ::c_long = 301; pub const SYS_msgrcv: ::c_long = 302; pub const SYS_msgget: ::c_long = 303; pub const SYS_msgctl: ::c_long = 304; pub const SYS_shmat: ::c_long = 305; pub const SYS_shmdt: ::c_long = 306; pub const SYS_shmget: ::c_long = 307; pub const SYS_shmctl: ::c_long = 308; pub const SYS_add_key: ::c_long = 309; pub const SYS_request_key: ::c_long = 310; pub const SYS_keyctl: ::c_long = 311; pub const SYS_semtimedop: ::c_long = 312; pub const SYS_vserver: ::c_long = 313; pub const SYS_ioprio_set: ::c_long = 314; pub const SYS_ioprio_get: ::c_long = 315; pub const SYS_inotify_init: ::c_long = 316; pub const SYS_inotify_add_watch: ::c_long = 317; pub const SYS_inotify_rm_watch: ::c_long = 318; pub const SYS_mbind: ::c_long = 319; pub const SYS_get_mempolicy: ::c_long = 320; pub const SYS_set_mempolicy: ::c_long = 321; pub const SYS_openat: ::c_long = 322; pub const SYS_mkdirat: ::c_long = 323; pub const SYS_mknodat: ::c_long = 324; pub const SYS_fchownat: ::c_long = 325; pub const SYS_futimesat: ::c_long = 326; pub const SYS_fstatat64: ::c_long = 327; pub const SYS_unlinkat: ::c_long = 328; pub const SYS_renameat: ::c_long = 329; pub const SYS_linkat: ::c_long = 330; pub const SYS_symlinkat: ::c_long = 331; pub const SYS_readlinkat: ::c_long = 332; pub const SYS_fchmodat: ::c_long = 333; pub const SYS_faccessat: ::c_long = 334; pub const SYS_pselect6: ::c_long = 335; pub const SYS_ppoll: ::c_long = 336; pub const SYS_unshare: ::c_long = 337; pub const SYS_set_robust_list: ::c_long = 338; pub const SYS_get_robust_list: ::c_long = 339; pub const SYS_splice: ::c_long = 340; pub const SYS_arm_sync_file_range: ::c_long = 341; pub const SYS_tee: ::c_long = 342; pub const SYS_vmsplice: ::c_long = 343; pub const SYS_move_pages: ::c_long = 344; pub const SYS_getcpu: ::c_long = 345; pub const SYS_epoll_pwait: ::c_long = 346; pub const SYS_kexec_load: ::c_long = 347; pub const SYS_utimensat: ::c_long = 348; pub const SYS_signalfd: ::c_long = 349; pub const SYS_timerfd_create: ::c_long = 350; pub const SYS_eventfd: ::c_long = 351; pub const SYS_fallocate: ::c_long = 352; pub const SYS_timerfd_settime: ::c_long = 353; pub const SYS_timerfd_gettime: ::c_long = 354; pub const SYS_signalfd4: ::c_long = 355; pub const SYS_eventfd2: ::c_long = 356; pub const SYS_epoll_create1: ::c_long = 357; pub const SYS_dup3: ::c_long = 358; pub const SYS_pipe2: ::c_long = 359; pub const SYS_inotify_init1: ::c_long = 360; pub const SYS_preadv: ::c_long = 361; pub const SYS_pwritev: ::c_long = 362; pub const SYS_rt_tgsigqueueinfo: ::c_long = 363; pub const SYS_perf_event_open: ::c_long = 364; pub const SYS_recvmmsg: ::c_long = 365; pub const SYS_accept4: ::c_long = 366; pub const SYS_fanotify_init: ::c_long = 367; pub const SYS_fanotify_mark: ::c_long = 368; pub const SYS_prlimit64: ::c_long = 369; pub const SYS_name_to_handle_at: ::c_long = 370; pub const SYS_open_by_handle_at: ::c_long = 371; pub const SYS_clock_adjtime: ::c_long = 372; pub const SYS_syncfs: ::c_long = 373; pub const SYS_sendmmsg: ::c_long = 374; pub const SYS_setns: ::c_long = 375; pub const SYS_process_vm_readv: ::c_long = 376; pub const SYS_process_vm_writev: ::c_long = 377; pub const SYS_kcmp: ::c_long = 378; pub const SYS_finit_module: ::c_long = 379; pub const SYS_sched_setattr: ::c_long = 380; pub const SYS_sched_getattr: ::c_long = 381; pub const SYS_renameat2: ::c_long = 382; pub const SYS_seccomp: ::c_long = 383; pub const SYS_getrandom: ::c_long = 384; pub const SYS_memfd_create: ::c_long = 385; pub const SYS_bpf: ::c_long = 386; pub const SYS_execveat: ::c_long = 387; pub const SYS_userfaultfd: ::c_long = 388; pub const SYS_membarrier: ::c_long = 389; pub const SYS_mlock2: ::c_long = 390; pub const SYS_copy_file_range: ::c_long = 391; pub const SYS_preadv2: ::c_long = 392; pub const SYS_pwritev2: ::c_long = 393; pub const SYS_pkey_mprotect: ::c_long = 394; pub const SYS_pkey_alloc: ::c_long = 395; pub const SYS_pkey_free: ::c_long = 396; pub const SYS_statx: ::c_long = 397; pub const SYS_rseq: ::c_long = 398; pub const SYS_kexec_file_load: ::c_long = 401; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b32/arm/align.rs0000644000175000017500000000341514661133735023127 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [i64; 2] } #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: ::mcontext_t, pub uc_sigmask: ::sigset_t, pub uc_regspace: [::c_ulong; 128], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_link) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); } } } } libc/src/unix/linux_like/linux/gnu/b32/csky/0000775000175000017500000000000014661133735021660 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/csky/mod.rs0000644000175000017500000006326414661133735023016 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct stat64 { pub st_dev: ::dev_t, __pad1: ::c_uint, __st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_uint, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino64_t, } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_ulong, pub shm_dtime: ::time_t, __unused2: ::c_ulong, pub shm_ctime: ::time_t, __unused3: ::c_ulong, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __glibc_reserved1: ::c_ulong, pub msg_rtime: ::time_t, __glibc_reserved2: ::c_ulong, pub msg_ctime: ::time_t, __glibc_reserved3: ::c_ulong, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_LARGEFILE: ::c_int = 0o100000; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; // Syscall table pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_close: ::c_long = 57; pub const SYS_fstat: ::c_long = 80; pub const SYS_lseek: ::c_long = 62; pub const SYS_mmap: ::c_long = 222; pub const SYS_mprotect: ::c_long = 226; pub const SYS_munmap: ::c_long = 215; pub const SYS_brk: ::c_long = 214; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_ioctl: ::c_long = 29; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_mremap: ::c_long = 216; pub const SYS_msync: ::c_long = 227; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmctl: ::c_long = 195; pub const SYS_dup: ::c_long = 23; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_getpid: ::c_long = 172; pub const SYS_sendfile: ::c_long = 71; pub const SYS_socket: ::c_long = 198; pub const SYS_connect: ::c_long = 203; pub const SYS_accept: ::c_long = 202; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_shutdown: ::c_long = 210; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_socketpair: ::c_long = 199; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_exit: ::c_long = 93; pub const SYS_wait4: ::c_long = 260; pub const SYS_kill: ::c_long = 129; pub const SYS_uname: ::c_long = 160; pub const SYS_semget: ::c_long = 190; pub const SYS_semop: ::c_long = 193; pub const SYS_semctl: ::c_long = 191; pub const SYS_shmdt: ::c_long = 197; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgctl: ::c_long = 187; pub const SYS_fcntl: ::c_long = 25; pub const SYS_flock: ::c_long = 32; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_getcwd: ::c_long = 17; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchown: ::c_long = 55; pub const SYS_umask: ::c_long = 166; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_getrusage: ::c_long = 165; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_times: ::c_long = 153; pub const SYS_ptrace: ::c_long = 117; pub const SYS_getuid: ::c_long = 174; pub const SYS_syslog: ::c_long = 116; pub const SYS_getgid: ::c_long = 176; pub const SYS_setuid: ::c_long = 146; pub const SYS_setgid: ::c_long = 144; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getegid: ::c_long = 177; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getppid: ::c_long = 173; pub const SYS_setsid: ::c_long = 157; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setregid: ::c_long = 143; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_getpgid: ::c_long = 155; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_getsid: ::c_long = 156; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_personality: ::c_long = 92; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_getpriority: ::c_long = 141; pub const SYS_setpriority: ::c_long = 140; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_prctl: ::c_long = 167; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_chroot: ::c_long = 51; pub const SYS_sync: ::c_long = 81; pub const SYS_acct: ::c_long = 89; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_mount: ::c_long = 40; pub const SYS_umount2: ::c_long = 39; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_reboot: ::c_long = 142; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_quotactl: ::c_long = 60; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_gettid: ::c_long = 178; pub const SYS_readahead: ::c_long = 213; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_tkill: ::c_long = 130; pub const SYS_futex: ::c_long = 98; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_getdents64: ::c_long = 61; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_fadvise64: ::c_long = 223; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_exit_group: ::c_long = 94; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_tgkill: ::c_long = 131; pub const SYS_mbind: ::c_long = 235; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_waitid: ::c_long = 95; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_openat: ::c_long = 56; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_mknodat: ::c_long = 33; pub const SYS_fchownat: ::c_long = 54; pub const SYS_newfstatat: ::c_long = 79; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_linkat: ::c_long = 37; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_faccessat: ::c_long = 48; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_unshare: ::c_long = 97; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_move_pages: ::c_long = 239; pub const SYS_utimensat: ::c_long = 88; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_fallocate: ::c_long = 47; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_accept4: ::c_long = 242; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_dup3: ::c_long = 24; pub const SYS_pipe2: ::c_long = 59; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_setns: ::c_long = 268; pub const SYS_getcpu: ::c_long = 168; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_rseq: ::c_long = 293; pub const SYS_syscall: ::c_long = 294; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b32/csky/align.rs0000644000175000017500000000022414661133735023314 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [i64; 2] } } libc/src/unix/linux_like/linux/gnu/b32/m68k/0000775000175000017500000000000014661133735021474 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs0000644000175000017500000007506414661133735022633 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, f_spare: [::__fsword_t; 4], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct ipc_perm { __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, __seq: ::c_ushort, __pad1: ::c_ushort, __glibc_reserved1: ::c_ulong, __glibc_reserved2: ::c_ulong, } pub struct stat64 { pub st_dev: ::dev_t, __pad1: ::c_ushort, pub __st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_ushort, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_ulong, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_ulong, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_ulong, pub st_ino: ::ino64_t, } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsblkcnt64_t, pub f_ffree: ::fsblkcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsblkcnt64_t, pub f_ffree: ::fsblkcnt64_t, pub f_favail: ::fsblkcnt64_t, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __glibc_reserved1: ::c_long, pub shm_dtime: ::time_t, __glibc_reserved2: ::c_long, pub shm_ctime: ::time_t, __glibc_reserved3: ::c_long, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __glibc_reserved5: ::c_ulong, __glibc_reserved6: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __glibc_reserved1: ::c_uint, pub msg_rtime: ::time_t, __glibc_reserved2: ::c_uint, pub msg_ctime: ::time_t, __glibc_reserved3: ::c_uint, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, _pad: [::c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_LARGEFILE: ::c_int = 0x20000; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_32BIT: ::c_int = 0x0040; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const PTRACE_SYSEMU: ::c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_uint = 32; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time32: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_chown16: ::c_long = 16; pub const SYS_stat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_oldumount: ::c_long = 22; pub const SYS_setuid16: ::c_long = 23; pub const SYS_getuid16: ::c_long = 24; pub const SYS_stime32: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_fstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime32: ::c_long = 30; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid16: ::c_long = 46; pub const SYS_getgid16: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid16: ::c_long = 49; pub const SYS_getegid16: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_setpgid: ::c_long = 57; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid16: ::c_long = 70; pub const SYS_setregid16: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_old_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups16: ::c_long = 80; pub const SYS_setgroups16: ::c_long = 81; pub const SYS_old_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_lstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_old_readdir: ::c_long = 89; pub const SYS_old_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown16: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_newstat: ::c_long = 106; pub const SYS_newlstat: ::c_long = 107; pub const SYS_newfstat: ::c_long = 108; pub const SYS_vhangup: ::c_long = 111; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_newuname: ::c_long = 122; pub const SYS_cacheflush: ::c_long = 123; pub const SYS_adjtimex_time32: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_setfsuid16: ::c_long = 138; pub const SYS_setfsgid16: ::c_long = 139; pub const SYS_llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS_select: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval_time32: ::c_long = 161; pub const SYS_nanosleep_time32: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid16: ::c_long = 164; pub const SYS_getresuid16: ::c_long = 165; pub const SYS_getpagesize: ::c_long = 166; pub const SYS_query_module: ::c_long = 167; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid16: ::c_long = 170; pub const SYS_getresgid16: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait_time32: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_lchown16: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_getpmsg: ::c_long = 188; pub const SYS_putpmsg: ::c_long = 189; pub const SYS_vfork: ::c_long = 190; pub const SYS_getrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_chown: ::c_long = 198; pub const SYS_getuid: ::c_long = 199; pub const SYS_getgid: ::c_long = 200; pub const SYS_geteuid: ::c_long = 201; pub const SYS_getegid: ::c_long = 202; pub const SYS_setreuid: ::c_long = 203; pub const SYS_setregid: ::c_long = 204; pub const SYS_getgroups: ::c_long = 205; pub const SYS_setgroups: ::c_long = 206; pub const SYS_fchown: ::c_long = 207; pub const SYS_setresuid: ::c_long = 208; pub const SYS_getresuid: ::c_long = 209; pub const SYS_setresgid: ::c_long = 210; pub const SYS_getresgid: ::c_long = 211; pub const SYS_lchown: ::c_long = 212; pub const SYS_setuid: ::c_long = 213; pub const SYS_setgid: ::c_long = 214; pub const SYS_setfsuid: ::c_long = 215; pub const SYS_setfsgid: ::c_long = 216; pub const SYS_pivot_root: ::c_long = 217; pub const SYS_getdents64: ::c_long = 220; pub const SYS_gettid: ::c_long = 221; pub const SYS_tkill: ::c_long = 222; pub const SYS_setxattr: ::c_long = 223; pub const SYS_lsetxattr: ::c_long = 224; pub const SYS_fsetxattr: ::c_long = 225; pub const SYS_getxattr: ::c_long = 226; pub const SYS_lgetxattr: ::c_long = 227; pub const SYS_fgetxattr: ::c_long = 228; pub const SYS_listxattr: ::c_long = 229; pub const SYS_llistxattr: ::c_long = 230; pub const SYS_flistxattr: ::c_long = 231; pub const SYS_removexattr: ::c_long = 232; pub const SYS_lremovexattr: ::c_long = 233; pub const SYS_fremovexattr: ::c_long = 234; pub const SYS_futex_time32: ::c_long = 235; pub const SYS_sendfile64: ::c_long = 236; pub const SYS_mincore: ::c_long = 237; pub const SYS_madvise: ::c_long = 238; pub const SYS_fcntl64: ::c_long = 239; pub const SYS_readahead: ::c_long = 240; pub const SYS_io_setup: ::c_long = 241; pub const SYS_io_destroy: ::c_long = 242; pub const SYS_io_getevents_time32: ::c_long = 243; pub const SYS_io_submit: ::c_long = 244; pub const SYS_io_cancel: ::c_long = 245; pub const SYS_fadvise64: ::c_long = 246; pub const SYS_exit_group: ::c_long = 247; pub const SYS_lookup_dcookie: ::c_long = 248; pub const SYS_epoll_create: ::c_long = 249; pub const SYS_epoll_ctl: ::c_long = 250; pub const SYS_epoll_wait: ::c_long = 251; pub const SYS_remap_file_pages: ::c_long = 252; pub const SYS_set_tid_address: ::c_long = 253; pub const SYS_timer_create: ::c_long = 254; pub const SYS_timer_settime32: ::c_long = 255; pub const SYS_timer_gettime32: ::c_long = 256; pub const SYS_timer_getoverrun: ::c_long = 257; pub const SYS_timer_delete: ::c_long = 258; pub const SYS_clock_settime32: ::c_long = 259; pub const SYS_clock_gettime32: ::c_long = 260; pub const SYS_clock_getres_time32: ::c_long = 261; pub const SYS_clock_nanosleep_time32: ::c_long = 262; pub const SYS_statfs64: ::c_long = 263; pub const SYS_fstatfs64: ::c_long = 264; pub const SYS_tgkill: ::c_long = 265; pub const SYS_utimes_time32: ::c_long = 266; pub const SYS_fadvise64_64: ::c_long = 267; pub const SYS_mbind: ::c_long = 268; pub const SYS_get_mempolicy: ::c_long = 269; pub const SYS_set_mempolicy: ::c_long = 270; pub const SYS_mq_open: ::c_long = 271; pub const SYS_mq_unlink: ::c_long = 272; pub const SYS_mq_timedsend_time32: ::c_long = 273; pub const SYS_mq_timedreceive_time32: ::c_long = 274; pub const SYS_mq_notify: ::c_long = 275; pub const SYS_mq_getsetattr: ::c_long = 276; pub const SYS_waitid: ::c_long = 277; pub const SYS_add_key: ::c_long = 279; pub const SYS_request_key: ::c_long = 280; pub const SYS_keyctl: ::c_long = 281; pub const SYS_ioprio_set: ::c_long = 282; pub const SYS_ioprio_get: ::c_long = 283; pub const SYS_inotify_init: ::c_long = 284; pub const SYS_inotify_add_watch: ::c_long = 285; pub const SYS_inotify_rm_watch: ::c_long = 286; pub const SYS_migrate_pages: ::c_long = 287; pub const SYS_openat: ::c_long = 288; pub const SYS_mkdirat: ::c_long = 289; pub const SYS_mknodat: ::c_long = 290; pub const SYS_fchownat: ::c_long = 291; pub const SYS_futimesat_time32: ::c_long = 292; pub const SYS_fstatat64: ::c_long = 293; pub const SYS_unlinkat: ::c_long = 294; pub const SYS_renameat: ::c_long = 295; pub const SYS_linkat: ::c_long = 296; pub const SYS_symlinkat: ::c_long = 297; pub const SYS_readlinkat: ::c_long = 298; pub const SYS_fchmodat: ::c_long = 299; pub const SYS_faccessat: ::c_long = 300; pub const SYS_pselect6_time32: ::c_long = 301; pub const SYS_ppoll_time32: ::c_long = 302; pub const SYS_unshare: ::c_long = 303; pub const SYS_set_robust_list: ::c_long = 304; pub const SYS_get_robust_list: ::c_long = 305; pub const SYS_splice: ::c_long = 306; pub const SYS_sync_file_range: ::c_long = 307; pub const SYS_tee: ::c_long = 308; pub const SYS_vmsplice: ::c_long = 309; pub const SYS_move_pages: ::c_long = 310; pub const SYS_sched_setaffinity: ::c_long = 311; pub const SYS_sched_getaffinity: ::c_long = 312; pub const SYS_kexec_load: ::c_long = 313; pub const SYS_getcpu: ::c_long = 314; pub const SYS_epoll_pwait: ::c_long = 315; pub const SYS_utimensat_time32: ::c_long = 316; pub const SYS_signalfd: ::c_long = 317; pub const SYS_timerfd_create: ::c_long = 318; pub const SYS_eventfd: ::c_long = 319; pub const SYS_fallocate: ::c_long = 320; pub const SYS_timerfd_settime32: ::c_long = 321; pub const SYS_timerfd_gettime32: ::c_long = 322; pub const SYS_signalfd4: ::c_long = 323; pub const SYS_eventfd2: ::c_long = 324; pub const SYS_epoll_create1: ::c_long = 325; pub const SYS_dup3: ::c_long = 326; pub const SYS_pipe2: ::c_long = 327; pub const SYS_inotify_init1: ::c_long = 328; pub const SYS_preadv: ::c_long = 329; pub const SYS_pwritev: ::c_long = 330; pub const SYS_rt_tgsigqueueinfo: ::c_long = 331; pub const SYS_perf_event_open: ::c_long = 332; pub const SYS_get_thread_area: ::c_long = 333; pub const SYS_set_thread_area: ::c_long = 334; pub const SYS_atomic_cmpxchg_32: ::c_long = 335; pub const SYS_atomic_barrier: ::c_long = 336; pub const SYS_fanotify_init: ::c_long = 337; pub const SYS_fanotify_mark: ::c_long = 338; pub const SYS_prlimit64: ::c_long = 339; pub const SYS_name_to_handle_at: ::c_long = 340; pub const SYS_open_by_handle_at: ::c_long = 341; pub const SYS_clock_adjtime32: ::c_long = 342; pub const SYS_syncfs: ::c_long = 343; pub const SYS_setns: ::c_long = 344; pub const SYS_process_vm_readv: ::c_long = 345; pub const SYS_process_vm_writev: ::c_long = 346; pub const SYS_kcmp: ::c_long = 347; pub const SYS_finit_module: ::c_long = 348; pub const SYS_sched_setattr: ::c_long = 349; pub const SYS_sched_getattr: ::c_long = 350; pub const SYS_renameat2: ::c_long = 351; pub const SYS_getrandom: ::c_long = 352; pub const SYS_memfd_create: ::c_long = 353; pub const SYS_bpf: ::c_long = 354; pub const SYS_execveat: ::c_long = 355; pub const SYS_socket: ::c_long = 356; pub const SYS_socketpair: ::c_long = 357; pub const SYS_bind: ::c_long = 358; pub const SYS_connect: ::c_long = 359; pub const SYS_listen: ::c_long = 360; pub const SYS_accept4: ::c_long = 361; pub const SYS_getsockopt: ::c_long = 362; pub const SYS_setsockopt: ::c_long = 363; pub const SYS_getsockname: ::c_long = 364; pub const SYS_getpeername: ::c_long = 365; pub const SYS_sendto: ::c_long = 366; pub const SYS_sendmsg: ::c_long = 367; pub const SYS_recvfrom: ::c_long = 368; pub const SYS_recvmsg: ::c_long = 369; pub const SYS_shutdown: ::c_long = 370; pub const SYS_recvmmsg_time32: ::c_long = 371; pub const SYS_sendmmsg: ::c_long = 372; pub const SYS_userfaultfd: ::c_long = 373; pub const SYS_membarrier: ::c_long = 374; pub const SYS_mlock2: ::c_long = 375; pub const SYS_copy_file_range: ::c_long = 376; pub const SYS_preadv2: ::c_long = 377; pub const SYS_pwritev2: ::c_long = 378; pub const SYS_statx: ::c_long = 379; pub const SYS_seccomp: ::c_long = 380; pub const SYS_pkey_mprotect: ::c_long = 381; pub const SYS_pkey_alloc: ::c_long = 382; pub const SYS_pkey_free: ::c_long = 383; pub const SYS_rseq: ::c_long = 384; pub const SYS_semget: ::c_long = 393; pub const SYS_semctl: ::c_long = 394; pub const SYS_shmget: ::c_long = 395; pub const SYS_shmctl: ::c_long = 396; pub const SYS_shmat: ::c_long = 397; pub const SYS_shmdt: ::c_long = 398; pub const SYS_msgget: ::c_long = 399; pub const SYS_msgsnd: ::c_long = 400; pub const SYS_msgrcv: ::c_long = 401; pub const SYS_msgctl: ::c_long = 402; pub const SYS_clock_gettime: ::c_long = 403; pub const SYS_clock_settime: ::c_long = 404; pub const SYS_clock_adjtime: ::c_long = 405; pub const SYS_clock_getres: ::c_long = 406; pub const SYS_clock_nanosleep: ::c_long = 407; pub const SYS_timer_gettime: ::c_long = 408; pub const SYS_timer_settime: ::c_long = 409; pub const SYS_timerfd_gettime: ::c_long = 410; pub const SYS_timerfd_settime: ::c_long = 411; pub const SYS_utimensat: ::c_long = 412; pub const SYS_pselect6: ::c_long = 413; pub const SYS_ppoll: ::c_long = 414; pub const SYS_io_pgetevents: ::c_long = 416; pub const SYS_recvmmsg: ::c_long = 417; pub const SYS_mq_timedsend: ::c_long = 418; pub const SYS_mq_timedreceive: ::c_long = 419; pub const SYS_semtimedop: ::c_long = 420; pub const SYS_rt_sigtimedwait: ::c_long = 421; pub const SYS_futex: ::c_long = 422; pub const SYS_sched_rr_get_interval: ::c_long = 423; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; libc/src/unix/linux_like/linux/gnu/b32/m68k/align.rs0000644000175000017500000000022414661133735023130 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(2))] pub struct max_align_t { priv_: [i8; 20] } } libc/src/unix/linux_like/linux/gnu/b32/sparc/0000775000175000017500000000000014661133735022017 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs0000644000175000017500000007265414661133735023160 0ustar jamespagejamespage//! SPARC-specific definitions for 32-bit linux-like values pub type c_char = i8; pub type wchar_t = i32; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, _pad: [::c_int; 29], _align: [usize; 0], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, __reserved: ::c_short, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_ushort, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 2], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_ushort, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __reserved: [::c_long; 2], } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, __pad1: ::c_ushort, pub mode: ::c_ushort, __pad2: ::c_ushort, pub __seq: ::c_ushort, __unused1: ::c_ulonglong, __unused2: ::c_ulonglong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, __pad1: ::c_uint, pub shm_atime: ::time_t, __pad2: ::c_uint, pub shm_dtime: ::time_t, __pad3: ::c_uint, pub shm_ctime: ::time_t, pub shm_segsz: ::size_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __reserved1: ::c_ulong, __reserved2: ::c_ulong, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, __pad1: ::c_uint, pub msg_stime: ::time_t, __pad2: ::c_uint, pub msg_rtime: ::time_t, __pad3: ::c_uint, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ushort, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved1: ::c_ulong, __glibc_reserved2: ::c_ulong, } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_APPEND: ::c_int = 0x8; pub const O_CREAT: ::c_int = 0x200; pub const O_EXCL: ::c_int = 0x800; pub const O_NOCTTY: ::c_int = 0x8000; pub const O_NONBLOCK: ::c_int = 0x4000; pub const O_SYNC: ::c_int = 0x802000; pub const O_RSYNC: ::c_int = 0x802000; pub const O_DSYNC: ::c_int = 0x2000; pub const O_FSYNC: ::c_int = 0x802000; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 0x0200; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLK: ::c_int = 78; pub const ENAMETOOLONG: ::c_int = 63; pub const ENOLCK: ::c_int = 79; pub const ENOSYS: ::c_int = 90; pub const ENOTEMPTY: ::c_int = 66; pub const ELOOP: ::c_int = 62; pub const ENOMSG: ::c_int = 75; pub const EIDRM: ::c_int = 77; pub const ECHRNG: ::c_int = 94; pub const EL2NSYNC: ::c_int = 95; pub const EL3HLT: ::c_int = 96; pub const EL3RST: ::c_int = 97; pub const ELNRNG: ::c_int = 98; pub const EUNATCH: ::c_int = 99; pub const ENOCSI: ::c_int = 100; pub const EL2HLT: ::c_int = 101; pub const EBADE: ::c_int = 102; pub const EBADR: ::c_int = 103; pub const EXFULL: ::c_int = 104; pub const ENOANO: ::c_int = 105; pub const EBADRQC: ::c_int = 106; pub const EBADSLT: ::c_int = 107; pub const EMULTIHOP: ::c_int = 87; pub const EOVERFLOW: ::c_int = 92; pub const ENOTUNIQ: ::c_int = 115; pub const EBADFD: ::c_int = 93; pub const EBADMSG: ::c_int = 76; pub const EREMCHG: ::c_int = 89; pub const ELIBACC: ::c_int = 114; pub const ELIBBAD: ::c_int = 112; pub const ELIBSCN: ::c_int = 124; pub const ELIBMAX: ::c_int = 123; pub const ELIBEXEC: ::c_int = 110; pub const EILSEQ: ::c_int = 122; pub const ERESTART: ::c_int = 116; pub const ESTRPIPE: ::c_int = 91; pub const EUSERS: ::c_int = 68; pub const ENOTSOCK: ::c_int = 38; pub const EDESTADDRREQ: ::c_int = 39; pub const EMSGSIZE: ::c_int = 40; pub const EPROTOTYPE: ::c_int = 41; pub const ENOPROTOOPT: ::c_int = 42; pub const EPROTONOSUPPORT: ::c_int = 43; pub const ESOCKTNOSUPPORT: ::c_int = 44; pub const EOPNOTSUPP: ::c_int = 45; pub const EPFNOSUPPORT: ::c_int = 46; pub const EAFNOSUPPORT: ::c_int = 47; pub const EADDRINUSE: ::c_int = 48; pub const EADDRNOTAVAIL: ::c_int = 49; pub const ENETDOWN: ::c_int = 50; pub const ENETUNREACH: ::c_int = 51; pub const ENETRESET: ::c_int = 52; pub const ECONNABORTED: ::c_int = 53; pub const ECONNRESET: ::c_int = 54; pub const ENOBUFS: ::c_int = 55; pub const EISCONN: ::c_int = 56; pub const ENOTCONN: ::c_int = 57; pub const ESHUTDOWN: ::c_int = 58; pub const ETOOMANYREFS: ::c_int = 59; pub const ETIMEDOUT: ::c_int = 60; pub const ECONNREFUSED: ::c_int = 61; pub const EHOSTDOWN: ::c_int = 64; pub const EHOSTUNREACH: ::c_int = 65; pub const EALREADY: ::c_int = 37; pub const EINPROGRESS: ::c_int = 36; pub const ESTALE: ::c_int = 70; pub const EDQUOT: ::c_int = 69; pub const ENOMEDIUM: ::c_int = 125; pub const EMEDIUMTYPE: ::c_int = 126; pub const ECANCELED: ::c_int = 127; pub const ENOKEY: ::c_int = 128; pub const EKEYEXPIRED: ::c_int = 129; pub const EKEYREVOKED: ::c_int = 130; pub const EKEYREJECTED: ::c_int = 131; pub const EOWNERDEAD: ::c_int = 132; pub const ENOTRECOVERABLE: ::c_int = 133; pub const EHWPOISON: ::c_int = 135; pub const ERFKILL: ::c_int = 134; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_SIGINFO: ::c_int = 0x200; pub const SA_NOCLDWAIT: ::c_int = 0x100; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 20; pub const SIGBUS: ::c_int = 10; pub const SIGUSR1: ::c_int = 30; pub const SIGUSR2: ::c_int = 31; pub const SIGCONT: ::c_int = 19; pub const SIGSTOP: ::c_int = 17; pub const SIGTSTP: ::c_int = 18; pub const SIGURG: ::c_int = 16; pub const SIGIO: ::c_int = 23; pub const SIGSYS: ::c_int = 12; pub const SIGPOLL: ::c_int = 23; pub const SIGPWR: ::c_int = 29; pub const SIG_SETMASK: ::c_int = 4; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const POLLWRNORM: ::c_short = 4; pub const POLLWRBAND: ::c_short = 0x100; pub const O_ASYNC: ::c_int = 0x40; pub const O_NDELAY: ::c_int = 0x4004; pub const EFD_NONBLOCK: ::c_int = 0x4000; pub const F_GETLK: ::c_int = 7; pub const F_GETOWN: ::c_int = 5; pub const F_SETOWN: ::c_int = 6; pub const SFD_NONBLOCK: ::c_int = 0x4000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const O_DIRECTORY: ::c_int = 0o200000; pub const O_NOFOLLOW: ::c_int = 0o400000; pub const O_LARGEFILE: ::c_int = 0x40000; pub const O_DIRECT: ::c_int = 0x100000; pub const MAP_LOCKED: ::c_int = 0x0100; pub const MAP_NORESERVE: ::c_int = 0x00040; pub const EDEADLOCK: ::c_int = 108; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const MCL_CURRENT: ::c_int = 0x2000; pub const MCL_FUTURE: ::c_int = 0x4000; pub const MCL_ONFAULT: ::c_int = 0x8000; pub const SIGSTKSZ: ::size_t = 16384; pub const MINSIGSTKSZ: ::size_t = 4096; pub const CBAUD: ::tcflag_t = 0x0000100f; pub const TAB1: ::tcflag_t = 0x800; pub const TAB2: ::tcflag_t = 0x1000; pub const TAB3: ::tcflag_t = 0x1800; pub const CR1: ::tcflag_t = 0x200; pub const CR2: ::tcflag_t = 0x400; pub const CR3: ::tcflag_t = 0x600; pub const FF1: ::tcflag_t = 0x8000; pub const BS1: ::tcflag_t = 0x2000; pub const VT1: ::tcflag_t = 0x4000; pub const VWERASE: usize = 0xe; pub const VREPRINT: usize = 0xc; pub const VSUSP: usize = 0xa; pub const VSTART: usize = 0x8; pub const VSTOP: usize = 0x9; pub const VDISCARD: usize = 0xd; pub const VTIME: usize = 0x5; pub const IXON: ::tcflag_t = 0x400; pub const IXOFF: ::tcflag_t = 0x1000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x30; pub const CS6: ::tcflag_t = 0x10; pub const CS7: ::tcflag_t = 0x20; pub const CS8: ::tcflag_t = 0x30; pub const CSTOPB: ::tcflag_t = 0x40; pub const CREAD: ::tcflag_t = 0x80; pub const PARENB: ::tcflag_t = 0x100; pub const PARODD: ::tcflag_t = 0x200; pub const HUPCL: ::tcflag_t = 0x400; pub const CLOCAL: ::tcflag_t = 0x800; pub const ECHOKE: ::tcflag_t = 0x800; pub const ECHOE: ::tcflag_t = 0x10; pub const ECHOK: ::tcflag_t = 0x20; pub const ECHONL: ::tcflag_t = 0x40; pub const ECHOPRT: ::tcflag_t = 0x400; pub const ECHOCTL: ::tcflag_t = 0x200; pub const ISIG: ::tcflag_t = 0x1; pub const ICANON: ::tcflag_t = 0x2; pub const PENDIN: ::tcflag_t = 0x4000; pub const NOFLSH: ::tcflag_t = 0x80; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0x00001000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0x1001; pub const B115200: ::speed_t = 0x1002; pub const B230400: ::speed_t = 0x1003; pub const B460800: ::speed_t = 0x1004; pub const B76800: ::speed_t = 0x1005; pub const B153600: ::speed_t = 0x1006; pub const B307200: ::speed_t = 0x1007; pub const B614400: ::speed_t = 0x1008; pub const B921600: ::speed_t = 0x1009; pub const B500000: ::speed_t = 0x100a; pub const B576000: ::speed_t = 0x100b; pub const B1000000: ::speed_t = 0x100c; pub const B1152000: ::speed_t = 0x100d; pub const B1500000: ::speed_t = 0x100e; pub const B2000000: ::speed_t = 0x100f; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: ::tcflag_t = 0x8000; pub const TOSTOP: ::tcflag_t = 0x100; pub const FLUSHO: ::tcflag_t = 0x1000; pub const EXTPROC: ::tcflag_t = 0x10000; pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_wait4: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execv: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_chown: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_brk: ::c_long = 17; pub const SYS_perfctr: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_capget: ::c_long = 21; pub const SYS_capset: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_vmsplice: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_sigaltstack: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_lchown32: ::c_long = 31; pub const SYS_fchown32: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_chown32: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_stat: ::c_long = 38; pub const SYS_sendfile: ::c_long = 39; pub const SYS_lstat: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_getuid32: ::c_long = 44; pub const SYS_umount2: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_getgid32: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_reboot: ::c_long = 55; pub const SYS_mmap2: ::c_long = 56; pub const SYS_symlink: ::c_long = 57; pub const SYS_readlink: ::c_long = 58; pub const SYS_execve: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_fstat: ::c_long = 62; pub const SYS_fstat64: ::c_long = 63; pub const SYS_getpagesize: ::c_long = 64; pub const SYS_msync: ::c_long = 65; pub const SYS_vfork: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_geteuid32: ::c_long = 69; pub const SYS_getegid32: ::c_long = 70; pub const SYS_mmap: ::c_long = 71; pub const SYS_setreuid32: ::c_long = 72; pub const SYS_munmap: ::c_long = 73; pub const SYS_mprotect: ::c_long = 74; pub const SYS_madvise: ::c_long = 75; pub const SYS_vhangup: ::c_long = 76; pub const SYS_truncate64: ::c_long = 77; pub const SYS_mincore: ::c_long = 78; pub const SYS_getgroups: ::c_long = 79; pub const SYS_setgroups: ::c_long = 80; pub const SYS_getpgrp: ::c_long = 81; pub const SYS_setgroups32: ::c_long = 82; pub const SYS_setitimer: ::c_long = 83; pub const SYS_ftruncate64: ::c_long = 84; pub const SYS_swapon: ::c_long = 85; pub const SYS_getitimer: ::c_long = 86; pub const SYS_setuid32: ::c_long = 87; pub const SYS_sethostname: ::c_long = 88; pub const SYS_setgid32: ::c_long = 89; pub const SYS_dup2: ::c_long = 90; pub const SYS_setfsuid32: ::c_long = 91; pub const SYS_fcntl: ::c_long = 92; pub const SYS_select: ::c_long = 93; pub const SYS_setfsgid32: ::c_long = 94; pub const SYS_fsync: ::c_long = 95; pub const SYS_setpriority: ::c_long = 96; pub const SYS_socket: ::c_long = 97; pub const SYS_connect: ::c_long = 98; pub const SYS_accept: ::c_long = 99; pub const SYS_getpriority: ::c_long = 100; pub const SYS_rt_sigreturn: ::c_long = 101; pub const SYS_rt_sigaction: ::c_long = 102; pub const SYS_rt_sigprocmask: ::c_long = 103; pub const SYS_rt_sigpending: ::c_long = 104; pub const SYS_rt_sigtimedwait: ::c_long = 105; pub const SYS_rt_sigqueueinfo: ::c_long = 106; pub const SYS_rt_sigsuspend: ::c_long = 107; pub const SYS_setresuid32: ::c_long = 108; pub const SYS_getresuid32: ::c_long = 109; pub const SYS_setresgid32: ::c_long = 110; pub const SYS_getresgid32: ::c_long = 111; pub const SYS_setregid32: ::c_long = 112; pub const SYS_recvmsg: ::c_long = 113; pub const SYS_sendmsg: ::c_long = 114; pub const SYS_getgroups32: ::c_long = 115; pub const SYS_gettimeofday: ::c_long = 116; pub const SYS_getrusage: ::c_long = 117; pub const SYS_getsockopt: ::c_long = 118; pub const SYS_getcwd: ::c_long = 119; pub const SYS_readv: ::c_long = 120; pub const SYS_writev: ::c_long = 121; pub const SYS_settimeofday: ::c_long = 122; pub const SYS_fchown: ::c_long = 123; pub const SYS_fchmod: ::c_long = 124; pub const SYS_recvfrom: ::c_long = 125; pub const SYS_setreuid: ::c_long = 126; pub const SYS_setregid: ::c_long = 127; pub const SYS_rename: ::c_long = 128; pub const SYS_truncate: ::c_long = 129; pub const SYS_ftruncate: ::c_long = 130; pub const SYS_flock: ::c_long = 131; pub const SYS_lstat64: ::c_long = 132; pub const SYS_sendto: ::c_long = 133; pub const SYS_shutdown: ::c_long = 134; pub const SYS_socketpair: ::c_long = 135; pub const SYS_mkdir: ::c_long = 136; pub const SYS_rmdir: ::c_long = 137; pub const SYS_utimes: ::c_long = 138; pub const SYS_stat64: ::c_long = 139; pub const SYS_sendfile64: ::c_long = 140; pub const SYS_getpeername: ::c_long = 141; pub const SYS_futex: ::c_long = 142; pub const SYS_gettid: ::c_long = 143; pub const SYS_getrlimit: ::c_long = 144; pub const SYS_setrlimit: ::c_long = 145; pub const SYS_pivot_root: ::c_long = 146; pub const SYS_prctl: ::c_long = 147; pub const SYS_pciconfig_read: ::c_long = 148; pub const SYS_pciconfig_write: ::c_long = 149; pub const SYS_getsockname: ::c_long = 150; pub const SYS_inotify_init: ::c_long = 151; pub const SYS_inotify_add_watch: ::c_long = 152; pub const SYS_poll: ::c_long = 153; pub const SYS_getdents64: ::c_long = 154; pub const SYS_fcntl64: ::c_long = 155; pub const SYS_inotify_rm_watch: ::c_long = 156; pub const SYS_statfs: ::c_long = 157; pub const SYS_fstatfs: ::c_long = 158; pub const SYS_umount: ::c_long = 159; pub const SYS_sched_set_affinity: ::c_long = 160; pub const SYS_sched_get_affinity: ::c_long = 161; pub const SYS_getdomainname: ::c_long = 162; pub const SYS_setdomainname: ::c_long = 163; pub const SYS_quotactl: ::c_long = 165; pub const SYS_set_tid_address: ::c_long = 166; pub const SYS_mount: ::c_long = 167; pub const SYS_ustat: ::c_long = 168; pub const SYS_setxattr: ::c_long = 169; pub const SYS_lsetxattr: ::c_long = 170; pub const SYS_fsetxattr: ::c_long = 171; pub const SYS_getxattr: ::c_long = 172; pub const SYS_lgetxattr: ::c_long = 173; pub const SYS_getdents: ::c_long = 174; pub const SYS_setsid: ::c_long = 175; pub const SYS_fchdir: ::c_long = 176; pub const SYS_fgetxattr: ::c_long = 177; pub const SYS_listxattr: ::c_long = 178; pub const SYS_llistxattr: ::c_long = 179; pub const SYS_flistxattr: ::c_long = 180; pub const SYS_removexattr: ::c_long = 181; pub const SYS_lremovexattr: ::c_long = 182; pub const SYS_sigpending: ::c_long = 183; pub const SYS_query_module: ::c_long = 184; pub const SYS_setpgid: ::c_long = 185; pub const SYS_fremovexattr: ::c_long = 186; pub const SYS_tkill: ::c_long = 187; pub const SYS_exit_group: ::c_long = 188; pub const SYS_uname: ::c_long = 189; pub const SYS_init_module: ::c_long = 190; pub const SYS_personality: ::c_long = 191; pub const SYS_remap_file_pages: ::c_long = 192; pub const SYS_epoll_create: ::c_long = 193; pub const SYS_epoll_ctl: ::c_long = 194; pub const SYS_epoll_wait: ::c_long = 195; pub const SYS_ioprio_set: ::c_long = 196; pub const SYS_getppid: ::c_long = 197; pub const SYS_sigaction: ::c_long = 198; pub const SYS_sgetmask: ::c_long = 199; pub const SYS_ssetmask: ::c_long = 200; pub const SYS_sigsuspend: ::c_long = 201; pub const SYS_oldlstat: ::c_long = 202; pub const SYS_uselib: ::c_long = 203; pub const SYS_readdir: ::c_long = 204; pub const SYS_readahead: ::c_long = 205; pub const SYS_socketcall: ::c_long = 206; pub const SYS_syslog: ::c_long = 207; pub const SYS_lookup_dcookie: ::c_long = 208; pub const SYS_fadvise64: ::c_long = 209; pub const SYS_fadvise64_64: ::c_long = 210; pub const SYS_tgkill: ::c_long = 211; pub const SYS_waitpid: ::c_long = 212; pub const SYS_swapoff: ::c_long = 213; pub const SYS_sysinfo: ::c_long = 214; pub const SYS_ipc: ::c_long = 215; pub const SYS_sigreturn: ::c_long = 216; pub const SYS_clone: ::c_long = 217; pub const SYS_ioprio_get: ::c_long = 218; pub const SYS_adjtimex: ::c_long = 219; pub const SYS_sigprocmask: ::c_long = 220; pub const SYS_create_module: ::c_long = 221; pub const SYS_delete_module: ::c_long = 222; pub const SYS_get_kernel_syms: ::c_long = 223; pub const SYS_getpgid: ::c_long = 224; pub const SYS_bdflush: ::c_long = 225; pub const SYS_sysfs: ::c_long = 226; pub const SYS_afs_syscall: ::c_long = 227; pub const SYS_setfsuid: ::c_long = 228; pub const SYS_setfsgid: ::c_long = 229; pub const SYS__newselect: ::c_long = 230; pub const SYS_time: ::c_long = 231; pub const SYS_splice: ::c_long = 232; pub const SYS_stime: ::c_long = 233; pub const SYS_statfs64: ::c_long = 234; pub const SYS_fstatfs64: ::c_long = 235; pub const SYS__llseek: ::c_long = 236; pub const SYS_mlock: ::c_long = 237; pub const SYS_munlock: ::c_long = 238; pub const SYS_mlockall: ::c_long = 239; pub const SYS_munlockall: ::c_long = 240; pub const SYS_sched_setparam: ::c_long = 241; pub const SYS_sched_getparam: ::c_long = 242; pub const SYS_sched_setscheduler: ::c_long = 243; pub const SYS_sched_getscheduler: ::c_long = 244; pub const SYS_sched_yield: ::c_long = 245; pub const SYS_sched_get_priority_max: ::c_long = 246; pub const SYS_sched_get_priority_min: ::c_long = 247; pub const SYS_sched_rr_get_interval: ::c_long = 248; pub const SYS_nanosleep: ::c_long = 249; pub const SYS_mremap: ::c_long = 250; pub const SYS__sysctl: ::c_long = 251; pub const SYS_getsid: ::c_long = 252; pub const SYS_fdatasync: ::c_long = 253; pub const SYS_nfsservctl: ::c_long = 254; pub const SYS_sync_file_range: ::c_long = 255; pub const SYS_clock_settime: ::c_long = 256; pub const SYS_clock_gettime: ::c_long = 257; pub const SYS_clock_getres: ::c_long = 258; pub const SYS_clock_nanosleep: ::c_long = 259; pub const SYS_sched_getaffinity: ::c_long = 260; pub const SYS_sched_setaffinity: ::c_long = 261; pub const SYS_timer_settime: ::c_long = 262; pub const SYS_timer_gettime: ::c_long = 263; pub const SYS_timer_getoverrun: ::c_long = 264; pub const SYS_timer_delete: ::c_long = 265; pub const SYS_timer_create: ::c_long = 266; pub const SYS_io_setup: ::c_long = 268; pub const SYS_io_destroy: ::c_long = 269; pub const SYS_io_submit: ::c_long = 270; pub const SYS_io_cancel: ::c_long = 271; pub const SYS_io_getevents: ::c_long = 272; pub const SYS_mq_open: ::c_long = 273; pub const SYS_mq_unlink: ::c_long = 274; pub const SYS_mq_timedsend: ::c_long = 275; pub const SYS_mq_timedreceive: ::c_long = 276; pub const SYS_mq_notify: ::c_long = 277; pub const SYS_mq_getsetattr: ::c_long = 278; pub const SYS_waitid: ::c_long = 279; pub const SYS_tee: ::c_long = 280; pub const SYS_add_key: ::c_long = 281; pub const SYS_request_key: ::c_long = 282; pub const SYS_keyctl: ::c_long = 283; pub const SYS_openat: ::c_long = 284; pub const SYS_mkdirat: ::c_long = 285; pub const SYS_mknodat: ::c_long = 286; pub const SYS_fchownat: ::c_long = 287; pub const SYS_futimesat: ::c_long = 288; pub const SYS_fstatat64: ::c_long = 289; pub const SYS_unlinkat: ::c_long = 290; pub const SYS_renameat: ::c_long = 291; pub const SYS_linkat: ::c_long = 292; pub const SYS_symlinkat: ::c_long = 293; pub const SYS_readlinkat: ::c_long = 294; pub const SYS_fchmodat: ::c_long = 295; pub const SYS_faccessat: ::c_long = 296; pub const SYS_pselect6: ::c_long = 297; pub const SYS_ppoll: ::c_long = 298; pub const SYS_unshare: ::c_long = 299; pub const SYS_set_robust_list: ::c_long = 300; pub const SYS_get_robust_list: ::c_long = 301; pub const SYS_migrate_pages: ::c_long = 302; pub const SYS_mbind: ::c_long = 303; pub const SYS_get_mempolicy: ::c_long = 304; pub const SYS_set_mempolicy: ::c_long = 305; pub const SYS_kexec_load: ::c_long = 306; pub const SYS_move_pages: ::c_long = 307; pub const SYS_getcpu: ::c_long = 308; pub const SYS_epoll_pwait: ::c_long = 309; pub const SYS_utimensat: ::c_long = 310; pub const SYS_signalfd: ::c_long = 311; pub const SYS_timerfd_create: ::c_long = 312; pub const SYS_eventfd: ::c_long = 313; pub const SYS_fallocate: ::c_long = 314; pub const SYS_timerfd_settime: ::c_long = 315; pub const SYS_timerfd_gettime: ::c_long = 316; pub const SYS_signalfd4: ::c_long = 317; pub const SYS_eventfd2: ::c_long = 318; pub const SYS_epoll_create1: ::c_long = 319; pub const SYS_dup3: ::c_long = 320; pub const SYS_pipe2: ::c_long = 321; pub const SYS_inotify_init1: ::c_long = 322; pub const SYS_accept4: ::c_long = 323; pub const SYS_preadv: ::c_long = 324; pub const SYS_pwritev: ::c_long = 325; pub const SYS_rt_tgsigqueueinfo: ::c_long = 326; pub const SYS_perf_event_open: ::c_long = 327; pub const SYS_recvmmsg: ::c_long = 328; pub const SYS_fanotify_init: ::c_long = 329; pub const SYS_fanotify_mark: ::c_long = 330; pub const SYS_prlimit64: ::c_long = 331; pub const SYS_name_to_handle_at: ::c_long = 332; pub const SYS_open_by_handle_at: ::c_long = 333; pub const SYS_clock_adjtime: ::c_long = 334; pub const SYS_syncfs: ::c_long = 335; pub const SYS_sendmmsg: ::c_long = 336; pub const SYS_setns: ::c_long = 337; pub const SYS_process_vm_readv: ::c_long = 338; pub const SYS_process_vm_writev: ::c_long = 339; pub const SYS_kern_features: ::c_long = 340; pub const SYS_kcmp: ::c_long = 341; pub const SYS_finit_module: ::c_long = 342; pub const SYS_sched_setattr: ::c_long = 343; pub const SYS_sched_getattr: ::c_long = 344; pub const SYS_renameat2: ::c_long = 345; pub const SYS_seccomp: ::c_long = 346; pub const SYS_getrandom: ::c_long = 347; pub const SYS_memfd_create: ::c_long = 348; pub const SYS_bpf: ::c_long = 349; pub const SYS_execveat: ::c_long = 350; pub const SYS_membarrier: ::c_long = 351; pub const SYS_userfaultfd: ::c_long = 352; pub const SYS_bind: ::c_long = 353; pub const SYS_listen: ::c_long = 354; pub const SYS_setsockopt: ::c_long = 355; pub const SYS_mlock2: ::c_long = 356; pub const SYS_copy_file_range: ::c_long = 357; pub const SYS_preadv2: ::c_long = 358; pub const SYS_pwritev2: ::c_long = 359; pub const SYS_statx: ::c_long = 360; pub const SYS_rseq: ::c_long = 365; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; // Reserved in the kernel, but not actually implemented yet pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b32/sparc/align.rs0000644000175000017500000000022414661133735023453 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [i64; 3] } } libc/src/unix/linux_like/linux/gnu/b32/riscv32/0000775000175000017500000000000014661133735022202 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs0000644000175000017500000006706014661133735023336 0ustar jamespagejamespage//! RISC-V-specific definitions for 32-bit linux-like values pub type c_char = u8; pub type wchar_t = ::c_int; s! { pub struct pthread_attr_t { __size: [::c_ulong; 7], } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2usize], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statfs64 { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_favail: ::fsfilcnt64_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused5: ::c_ulong, __unused6: ::c_ulong, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct user_regs_struct { pub pc: ::c_ulong, pub ra: ::c_ulong, pub sp: ::c_ulong, pub gp: ::c_ulong, pub tp: ::c_ulong, pub t0: ::c_ulong, pub t1: ::c_ulong, pub t2: ::c_ulong, pub s0: ::c_ulong, pub s1: ::c_ulong, pub a0: ::c_ulong, pub a1: ::c_ulong, pub a2: ::c_ulong, pub a3: ::c_ulong, pub a4: ::c_ulong, pub a5: ::c_ulong, pub a6: ::c_ulong, pub a7: ::c_ulong, pub s2: ::c_ulong, pub s3: ::c_ulong, pub s4: ::c_ulong, pub s5: ::c_ulong, pub s6: ::c_ulong, pub s7: ::c_ulong, pub s8: ::c_ulong, pub s9: ::c_ulong, pub s10: ::c_ulong, pub s11: ::c_ulong, pub t3: ::c_ulong, pub t4: ::c_ulong, pub t5: ::c_ulong, pub t6: ::c_ulong, } } pub const O_LARGEFILE: ::c_int = 0; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 1052672; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 256; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_SIGINFO: ::c_int = 4; pub const SA_NOCLDWAIT: ::c_int = 2; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const POLLWRNORM: ::c_short = 256; pub const POLLWRBAND: ::c_short = 512; pub const O_ASYNC: ::c_int = 8192; pub const O_NDELAY: ::c_int = 2048; pub const EFD_NONBLOCK: ::c_int = 2048; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const SFD_NONBLOCK: ::c_int = 2048; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const O_DIRECT: ::c_int = 16384; pub const O_DIRECTORY: ::c_int = 65536; pub const O_NOFOLLOW: ::c_int = 131072; pub const MAP_HUGETLB: ::c_int = 262144; pub const MAP_LOCKED: ::c_int = 8192; pub const MAP_NORESERVE: ::c_int = 16384; pub const MAP_ANON: ::c_int = 32; pub const MAP_ANONYMOUS: ::c_int = 32; pub const MAP_DENYWRITE: ::c_int = 2048; pub const MAP_EXECUTABLE: ::c_int = 4096; pub const MAP_POPULATE: ::c_int = 32768; pub const MAP_NONBLOCK: ::c_int = 65536; pub const MAP_STACK: ::c_int = 131072; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const MCL_CURRENT: ::c_int = 1; pub const MCL_FUTURE: ::c_int = 2; pub const MCL_ONFAULT: ::c_int = 4; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 4111; pub const TAB1: ::tcflag_t = 2048; pub const TAB2: ::tcflag_t = 4096; pub const TAB3: ::tcflag_t = 6144; pub const CR1: ::tcflag_t = 512; pub const CR2: ::tcflag_t = 1024; pub const CR3: ::tcflag_t = 1536; pub const FF1: ::tcflag_t = 32768; pub const BS1: ::tcflag_t = 8192; pub const VT1: ::tcflag_t = 16384; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 1024; pub const IXOFF: ::tcflag_t = 4096; pub const ONLCR: ::tcflag_t = 4; pub const CSIZE: ::tcflag_t = 48; pub const CS6: ::tcflag_t = 16; pub const CS7: ::tcflag_t = 32; pub const CS8: ::tcflag_t = 48; pub const CSTOPB: ::tcflag_t = 64; pub const CREAD: ::tcflag_t = 128; pub const PARENB: ::tcflag_t = 256; pub const PARODD: ::tcflag_t = 512; pub const HUPCL: ::tcflag_t = 1024; pub const CLOCAL: ::tcflag_t = 2048; pub const ECHOKE: ::tcflag_t = 2048; pub const ECHOE: ::tcflag_t = 16; pub const ECHOK: ::tcflag_t = 32; pub const ECHONL: ::tcflag_t = 64; pub const ECHOPRT: ::tcflag_t = 1024; pub const ECHOCTL: ::tcflag_t = 512; pub const ISIG: ::tcflag_t = 1; pub const ICANON: ::tcflag_t = 2; pub const PENDIN: ::tcflag_t = 16384; pub const NOFLSH: ::tcflag_t = 128; pub const CIBAUD: ::tcflag_t = 269418496; pub const CBAUDEX: ::tcflag_t = 4096; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 2; pub const NLDLY: ::tcflag_t = 256; pub const CRDLY: ::tcflag_t = 1536; pub const TABDLY: ::tcflag_t = 6144; pub const BSDLY: ::tcflag_t = 8192; pub const FFDLY: ::tcflag_t = 32768; pub const VTDLY: ::tcflag_t = 16384; pub const XTABS: ::tcflag_t = 6144; pub const B0: ::speed_t = 0; pub const B50: ::speed_t = 1; pub const B75: ::speed_t = 2; pub const B110: ::speed_t = 3; pub const B134: ::speed_t = 4; pub const B150: ::speed_t = 5; pub const B200: ::speed_t = 6; pub const B300: ::speed_t = 7; pub const B600: ::speed_t = 8; pub const B1200: ::speed_t = 9; pub const B1800: ::speed_t = 10; pub const B2400: ::speed_t = 11; pub const B4800: ::speed_t = 12; pub const B9600: ::speed_t = 13; pub const B19200: ::speed_t = 14; pub const B38400: ::speed_t = 15; pub const EXTA: ::speed_t = 14; pub const EXTB: ::speed_t = 15; pub const B57600: ::speed_t = 4097; pub const B115200: ::speed_t = 4098; pub const B230400: ::speed_t = 4099; pub const B460800: ::speed_t = 4100; pub const B500000: ::speed_t = 4101; pub const B576000: ::speed_t = 4102; pub const B921600: ::speed_t = 4103; pub const B1000000: ::speed_t = 4104; pub const B1152000: ::speed_t = 4105; pub const B1500000: ::speed_t = 4106; pub const B2000000: ::speed_t = 4107; pub const B2500000: ::speed_t = 4108; pub const B3000000: ::speed_t = 4109; pub const B3500000: ::speed_t = 4110; pub const B4000000: ::speed_t = 4111; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 32768; pub const TOSTOP: ::tcflag_t = 256; pub const FLUSHO: ::tcflag_t = 4096; pub const EXTPROC: ::tcflag_t = 65536; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const NGREG: usize = 32; pub const REG_PC: usize = 0; pub const REG_RA: usize = 1; pub const REG_SP: usize = 2; pub const REG_TP: usize = 4; pub const REG_S0: usize = 8; pub const REG_S1: usize = 9; pub const REG_A0: usize = 10; pub const REG_S2: usize = 18; pub const REG_NARGS: usize = 8; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_close: ::c_long = 57; pub const SYS_fstat: ::c_long = 80; pub const SYS_lseek: ::c_long = 62; pub const SYS_mmap: ::c_long = 222; pub const SYS_mprotect: ::c_long = 226; pub const SYS_munmap: ::c_long = 215; pub const SYS_brk: ::c_long = 214; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_ioctl: ::c_long = 29; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_mremap: ::c_long = 216; pub const SYS_msync: ::c_long = 227; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmctl: ::c_long = 195; pub const SYS_dup: ::c_long = 23; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_getpid: ::c_long = 172; pub const SYS_sendfile: ::c_long = 71; pub const SYS_socket: ::c_long = 198; pub const SYS_connect: ::c_long = 203; pub const SYS_accept: ::c_long = 202; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_shutdown: ::c_long = 210; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_socketpair: ::c_long = 199; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_exit: ::c_long = 93; pub const SYS_wait4: ::c_long = 260; pub const SYS_kill: ::c_long = 129; pub const SYS_uname: ::c_long = 160; pub const SYS_semget: ::c_long = 190; pub const SYS_semop: ::c_long = 193; pub const SYS_semctl: ::c_long = 191; pub const SYS_shmdt: ::c_long = 197; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgctl: ::c_long = 187; pub const SYS_fcntl: ::c_long = 25; pub const SYS_flock: ::c_long = 32; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_getcwd: ::c_long = 17; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchown: ::c_long = 55; pub const SYS_umask: ::c_long = 166; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_getrusage: ::c_long = 165; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_times: ::c_long = 153; pub const SYS_ptrace: ::c_long = 117; pub const SYS_getuid: ::c_long = 174; pub const SYS_syslog: ::c_long = 116; pub const SYS_getgid: ::c_long = 176; pub const SYS_setuid: ::c_long = 146; pub const SYS_setgid: ::c_long = 144; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getegid: ::c_long = 177; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getppid: ::c_long = 173; pub const SYS_setsid: ::c_long = 157; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setregid: ::c_long = 143; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_getpgid: ::c_long = 155; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_getsid: ::c_long = 156; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_personality: ::c_long = 92; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_getpriority: ::c_long = 141; pub const SYS_setpriority: ::c_long = 140; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_prctl: ::c_long = 167; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_chroot: ::c_long = 51; pub const SYS_sync: ::c_long = 81; pub const SYS_acct: ::c_long = 89; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_mount: ::c_long = 40; pub const SYS_umount2: ::c_long = 39; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_reboot: ::c_long = 142; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_quotactl: ::c_long = 60; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_gettid: ::c_long = 178; pub const SYS_readahead: ::c_long = 213; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_tkill: ::c_long = 130; pub const SYS_futex: ::c_long = 98; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_getdents64: ::c_long = 61; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_fadvise64: ::c_long = 223; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_exit_group: ::c_long = 94; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_tgkill: ::c_long = 131; pub const SYS_mbind: ::c_long = 235; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_waitid: ::c_long = 95; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_openat: ::c_long = 56; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_mknodat: ::c_long = 33; pub const SYS_fchownat: ::c_long = 54; pub const SYS_newfstatat: ::c_long = 79; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_linkat: ::c_long = 37; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_faccessat: ::c_long = 48; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_unshare: ::c_long = 97; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_move_pages: ::c_long = 239; pub const SYS_utimensat: ::c_long = 88; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_fallocate: ::c_long = 47; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_accept4: ::c_long = 242; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_dup3: ::c_long = 24; pub const SYS_pipe2: ::c_long = 59; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_setns: ::c_long = 268; pub const SYS_getcpu: ::c_long = 168; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_rseq: ::c_long = 293; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b32/riscv32/align.rs0000644000175000017500000000227514661133735023646 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub __uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct mcontext_t { pub __gregs: [::c_ulong; 32], pub __fpregs: __riscv_mc_fp_state, } #[allow(missing_debug_implementations)] pub union __riscv_mc_fp_state { pub __f: __riscv_mc_f_ext_state, pub __d: __riscv_mc_d_ext_state, pub __q: __riscv_mc_q_ext_state, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_f_ext_state { pub __f: [::c_uint; 32], pub __fcsr: ::c_uint, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_d_ext_state { pub __f: [::c_ulonglong; 32], pub __fcsr: ::c_uint, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct __riscv_mc_q_ext_state { pub __f: [::c_ulonglong; 64], pub __fcsr: ::c_uint, pub __glibc_reserved: [::c_uint; 3], } } libc/src/unix/linux_like/linux/gnu/b32/mod.rs0000644000175000017500000002675014661133735022044 0ustar jamespagejamespage//! 32-bit specific definitions for linux-like values use pthread_mutex_t; pub type c_long = i32; pub type c_ulong = u32; pub type clock_t = i32; pub type shmatt_t = ::c_ulong; pub type msgqnum_t = ::c_ulong; pub type msglen_t = ::c_ulong; pub type nlink_t = u32; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; pub type __fsword_t = i32; pub type fsblkcnt64_t = u64; pub type fsfilcnt64_t = u64; pub type __syscall_ulong_t = ::c_ulong; cfg_if! { if #[cfg(target_arch = "riscv32")] { pub type time_t = i64; pub type suseconds_t = i64; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type rlim_t = u64; pub type blksize_t = i64; } else { pub type time_t = i32; pub type suseconds_t = i32; pub type ino_t = u32; pub type off_t = i32; pub type blkcnt_t = i32; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type rlim_t = c_ulong; pub type blksize_t = i32; } } s! { pub struct stat { #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] pub st_dev: ::dev_t, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] pub st_dev: ::c_ulong, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] __pad1: ::c_short, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] st_pad1: [::c_long; 3], pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] pub st_rdev: ::dev_t, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] pub st_rdev: ::c_ulong, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] __pad2: ::c_short, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] st_pad2: [::c_long; 2], pub st_size: ::off_t, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] st_pad3: ::c_long, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] pub st_blksize: ::blksize_t, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] __unused4: ::c_long, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6")))] __unused5: ::c_long, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] pub st_blksize: ::blksize_t, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] pub st_blocks: ::blkcnt_t, #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] st_pad5: [::c_long; 14], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_attr_t { __size: [u32; 9] } pub struct sigset_t { __val: [::c_ulong; 32], } pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, #[deprecated( since = "0.2.58", note = "This padding field might become private in the future" )] pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub _f: [::c_char; 8], } pub struct semid_ds { pub sem_perm: ipc_perm, #[cfg(target_arch = "powerpc")] __reserved: ::__syscall_ulong_t, pub sem_otime: ::time_t, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc")))] __reserved: ::__syscall_ulong_t, #[cfg(target_arch = "powerpc")] __reserved2: ::__syscall_ulong_t, pub sem_ctime: ::time_t, #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc")))] __reserved2: ::__syscall_ulong_t, pub sem_nsems: ::__syscall_ulong_t, __glibc_reserved3: ::__syscall_ulong_t, __glibc_reserved4: ::__syscall_ulong_t, } } pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 24; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 32; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; cfg_if! { if #[cfg(target_arch = "sparc")] { pub const O_NOATIME: ::c_int = 0x200000; pub const O_PATH: ::c_int = 0x1000000; pub const O_TMPFILE: ::c_int = 0x2000000 | O_DIRECTORY; pub const SA_ONSTACK: ::c_int = 1; pub const PTRACE_DETACH: ::c_uint = 11; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const F_RDLCK: ::c_int = 1; pub const F_WRLCK: ::c_int = 2; pub const F_UNLCK: ::c_int = 3; pub const SFD_CLOEXEC: ::c_int = 0x400000; pub const NCCS: usize = 17; pub const O_TRUNC: ::c_int = 0x400; pub const O_CLOEXEC: ::c_int = 0x400000; pub const EBFONT: ::c_int = 109; pub const ENOSTR: ::c_int = 72; pub const ENODATA: ::c_int = 111; pub const ETIME: ::c_int = 73; pub const ENOSR: ::c_int = 74; pub const ENONET: ::c_int = 80; pub const ENOPKG: ::c_int = 113; pub const EREMOTE: ::c_int = 71; pub const ENOLINK: ::c_int = 82; pub const EADV: ::c_int = 83; pub const ESRMNT: ::c_int = 84; pub const ECOMM: ::c_int = 85; pub const EPROTO: ::c_int = 86; pub const EDOTDOT: ::c_int = 88; pub const SA_NODEFER: ::c_int = 0x20; pub const SA_RESETHAND: ::c_int = 0x4; pub const SA_RESTART: ::c_int = 0x2; pub const SA_NOCLDSTOP: ::c_int = 0x00000008; pub const EPOLL_CLOEXEC: ::c_int = 0x400000; pub const EFD_CLOEXEC: ::c_int = 0x400000; } else { pub const O_NOATIME: ::c_int = 0o1000000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const PTRACE_DETACH: ::c_uint = 17; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_CLOEXEC: ::c_int = 0x80000; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; } } align_const! { #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; pub const PTRACE_GETREGS: ::c_uint = 12; pub const PTRACE_SETREGS: ::c_uint = 13; extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; } cfg_if! { if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] { mod mips; pub use self::mips::*; } else if #[cfg(target_arch = "m68k")] { mod m68k; pub use self::m68k::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "sparc")] { mod sparc; pub use self::sparc::*; } else if #[cfg(target_arch = "riscv32")] { mod riscv32; pub use self::riscv32::*; } else if #[cfg(target_arch = "csky")] { mod csky; pub use self::csky::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/gnu/b32/x86/0000775000175000017500000000000014661133735021334 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs0000644000175000017500000011320114661133735022455 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type greg_t = i32; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct _libc_fpreg { pub significand: [u16; 4], pub exponent: u16, } pub struct _libc_fpstate { pub cw: ::c_ulong, pub sw: ::c_ulong, pub tag: ::c_ulong, pub ipoff: ::c_ulong, pub cssel: ::c_ulong, pub dataoff: ::c_ulong, pub datasel: ::c_ulong, pub _st: [_libc_fpreg; 8], pub status: ::c_ulong, } pub struct user_fpregs_struct { pub cwd: ::c_long, pub swd: ::c_long, pub twd: ::c_long, pub fip: ::c_long, pub fcs: ::c_long, pub foo: ::c_long, pub fos: ::c_long, pub st_space: [::c_long; 20], } pub struct user_regs_struct { pub ebx: ::c_long, pub ecx: ::c_long, pub edx: ::c_long, pub esi: ::c_long, pub edi: ::c_long, pub ebp: ::c_long, pub eax: ::c_long, pub xds: ::c_long, pub xes: ::c_long, pub xfs: ::c_long, pub xgs: ::c_long, pub orig_eax: ::c_long, pub eip: ::c_long, pub xcs: ::c_long, pub eflags: ::c_long, pub esp: ::c_long, pub xss: ::c_long, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: ::c_int, pub i387: user_fpregs_struct, pub u_tsize: ::c_ulong, pub u_dsize: ::c_ulong, pub u_ssize: ::c_ulong, pub start_code: ::c_ulong, pub start_stack: ::c_ulong, pub signal: ::c_long, __reserved: ::c_int, pub u_ar0: *mut user_regs_struct, pub u_fpstate: *mut user_fpregs_struct, pub magic: ::c_ulong, pub u_comm: [c_char; 32], pub u_debugreg: [::c_int; 8], } pub struct mcontext_t { pub gregs: [greg_t; 19], pub fpregs: *mut _libc_fpstate, pub oldmask: ::c_ulong, pub cr2: ::c_ulong, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct stat64 { pub st_dev: ::dev_t, __pad1: ::c_uint, __st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_uint, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ino: ::ino64_t, } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, __unused1: ::c_ulong, pub shm_dtime: ::time_t, __unused2: ::c_ulong, pub shm_ctime: ::time_t, __unused3: ::c_ulong, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, __glibc_reserved1: ::c_ulong, pub msg_rtime: ::time_t, __glibc_reserved2: ::c_ulong, pub msg_ctime: ::time_t, __glibc_reserved3: ::c_ulong, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } } s_no_extra_traits! { pub struct user_fpxregs_struct { pub cwd: ::c_ushort, pub swd: ::c_ushort, pub twd: ::c_ushort, pub fop: ::c_ushort, pub fip: ::c_long, pub fcs: ::c_long, pub foo: ::c_long, pub fos: ::c_long, pub mxcsr: ::c_long, __reserved: ::c_long, pub st_space: [::c_long; 32], pub xmm_space: [::c_long; 32], padding: [::c_long; 56], } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: ::sigset_t, __private: [u8; 112], __ssp: [::c_ulong; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpxregs_struct { fn eq(&self, other: &user_fpxregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.twd == other.twd && self.fop == other.fop && self.fip == other.fip && self.fcs == other.fcs && self.foo == other.foo && self.fos == other.fos && self.mxcsr == other.mxcsr // Ignore __reserved field && self.st_space == other.st_space && self.xmm_space == other.xmm_space // Ignore padding field } } impl Eq for user_fpxregs_struct {} impl ::fmt::Debug for user_fpxregs_struct { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("user_fpxregs_struct") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("twd", &self.twd) .field("fop", &self.fop) .field("fip", &self.fip) .field("fcs", &self.fcs) .field("foo", &self.foo) .field("fos", &self.fos) .field("mxcsr", &self.mxcsr) // Ignore __reserved field .field("st_space", &self.st_space) .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl ::hash::Hash for user_fpxregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.twd.hash(state); self.fop.hash(state); self.fip.hash(state); self.fcs.hash(state); self.foo.hash(state); self.fos.hash(state); self.mxcsr.hash(state); // Ignore __reserved field self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask // Ignore __private field } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); // Ignore __private field } } } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_LARGEFILE: ::c_int = 0o0100000; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_32BIT: ::c_int = 0x0040; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const PTRACE_SYSEMU: ::c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_uint = 32; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_break: ::c_long = 17; pub const SYS_oldstat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_stime: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_oldfstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_stty: ::c_long = 31; pub const SYS_gtty: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_ftime: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_prof: ::c_long = 44; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_lock: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_mpx: ::c_long = 56; pub const SYS_setpgid: ::c_long = 57; pub const SYS_ulimit: ::c_long = 58; pub const SYS_oldolduname: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_oldlstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_profil: ::c_long = 98; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_ioperm: ::c_long = 101; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_olduname: ::c_long = 109; pub const SYS_iopl: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_vm86old: ::c_long = 113; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_modify_ldt: ::c_long = 123; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_vm86: ::c_long = 166; pub const SYS_query_module: ::c_long = 167; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid: ::c_long = 170; pub const SYS_getresgid: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_chown: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_getpmsg: ::c_long = 188; pub const SYS_putpmsg: ::c_long = 189; pub const SYS_vfork: ::c_long = 190; pub const SYS_ugetrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_lchown32: ::c_long = 198; pub const SYS_getuid32: ::c_long = 199; pub const SYS_getgid32: ::c_long = 200; pub const SYS_geteuid32: ::c_long = 201; pub const SYS_getegid32: ::c_long = 202; pub const SYS_setreuid32: ::c_long = 203; pub const SYS_setregid32: ::c_long = 204; pub const SYS_getgroups32: ::c_long = 205; pub const SYS_setgroups32: ::c_long = 206; pub const SYS_fchown32: ::c_long = 207; pub const SYS_setresuid32: ::c_long = 208; pub const SYS_getresuid32: ::c_long = 209; pub const SYS_setresgid32: ::c_long = 210; pub const SYS_getresgid32: ::c_long = 211; pub const SYS_chown32: ::c_long = 212; pub const SYS_setuid32: ::c_long = 213; pub const SYS_setgid32: ::c_long = 214; pub const SYS_setfsuid32: ::c_long = 215; pub const SYS_setfsgid32: ::c_long = 216; pub const SYS_pivot_root: ::c_long = 217; pub const SYS_mincore: ::c_long = 218; pub const SYS_madvise: ::c_long = 219; pub const SYS_getdents64: ::c_long = 220; pub const SYS_fcntl64: ::c_long = 221; pub const SYS_gettid: ::c_long = 224; pub const SYS_readahead: ::c_long = 225; pub const SYS_setxattr: ::c_long = 226; pub const SYS_lsetxattr: ::c_long = 227; pub const SYS_fsetxattr: ::c_long = 228; pub const SYS_getxattr: ::c_long = 229; pub const SYS_lgetxattr: ::c_long = 230; pub const SYS_fgetxattr: ::c_long = 231; pub const SYS_listxattr: ::c_long = 232; pub const SYS_llistxattr: ::c_long = 233; pub const SYS_flistxattr: ::c_long = 234; pub const SYS_removexattr: ::c_long = 235; pub const SYS_lremovexattr: ::c_long = 236; pub const SYS_fremovexattr: ::c_long = 237; pub const SYS_tkill: ::c_long = 238; pub const SYS_sendfile64: ::c_long = 239; pub const SYS_futex: ::c_long = 240; pub const SYS_sched_setaffinity: ::c_long = 241; pub const SYS_sched_getaffinity: ::c_long = 242; pub const SYS_set_thread_area: ::c_long = 243; pub const SYS_get_thread_area: ::c_long = 244; pub const SYS_io_setup: ::c_long = 245; pub const SYS_io_destroy: ::c_long = 246; pub const SYS_io_getevents: ::c_long = 247; pub const SYS_io_submit: ::c_long = 248; pub const SYS_io_cancel: ::c_long = 249; pub const SYS_fadvise64: ::c_long = 250; pub const SYS_exit_group: ::c_long = 252; pub const SYS_lookup_dcookie: ::c_long = 253; pub const SYS_epoll_create: ::c_long = 254; pub const SYS_epoll_ctl: ::c_long = 255; pub const SYS_epoll_wait: ::c_long = 256; pub const SYS_remap_file_pages: ::c_long = 257; pub const SYS_set_tid_address: ::c_long = 258; pub const SYS_timer_create: ::c_long = 259; pub const SYS_timer_settime: ::c_long = 260; pub const SYS_timer_gettime: ::c_long = 261; pub const SYS_timer_getoverrun: ::c_long = 262; pub const SYS_timer_delete: ::c_long = 263; pub const SYS_clock_settime: ::c_long = 264; pub const SYS_clock_gettime: ::c_long = 265; pub const SYS_clock_getres: ::c_long = 266; pub const SYS_clock_nanosleep: ::c_long = 267; pub const SYS_statfs64: ::c_long = 268; pub const SYS_fstatfs64: ::c_long = 269; pub const SYS_tgkill: ::c_long = 270; pub const SYS_utimes: ::c_long = 271; pub const SYS_fadvise64_64: ::c_long = 272; pub const SYS_vserver: ::c_long = 273; pub const SYS_mbind: ::c_long = 274; pub const SYS_get_mempolicy: ::c_long = 275; pub const SYS_set_mempolicy: ::c_long = 276; pub const SYS_mq_open: ::c_long = 277; pub const SYS_mq_unlink: ::c_long = 278; pub const SYS_mq_timedsend: ::c_long = 279; pub const SYS_mq_timedreceive: ::c_long = 280; pub const SYS_mq_notify: ::c_long = 281; pub const SYS_mq_getsetattr: ::c_long = 282; pub const SYS_kexec_load: ::c_long = 283; pub const SYS_waitid: ::c_long = 284; pub const SYS_add_key: ::c_long = 286; pub const SYS_request_key: ::c_long = 287; pub const SYS_keyctl: ::c_long = 288; pub const SYS_ioprio_set: ::c_long = 289; pub const SYS_ioprio_get: ::c_long = 290; pub const SYS_inotify_init: ::c_long = 291; pub const SYS_inotify_add_watch: ::c_long = 292; pub const SYS_inotify_rm_watch: ::c_long = 293; pub const SYS_migrate_pages: ::c_long = 294; pub const SYS_openat: ::c_long = 295; pub const SYS_mkdirat: ::c_long = 296; pub const SYS_mknodat: ::c_long = 297; pub const SYS_fchownat: ::c_long = 298; pub const SYS_futimesat: ::c_long = 299; pub const SYS_fstatat64: ::c_long = 300; pub const SYS_unlinkat: ::c_long = 301; pub const SYS_renameat: ::c_long = 302; pub const SYS_linkat: ::c_long = 303; pub const SYS_symlinkat: ::c_long = 304; pub const SYS_readlinkat: ::c_long = 305; pub const SYS_fchmodat: ::c_long = 306; pub const SYS_faccessat: ::c_long = 307; pub const SYS_pselect6: ::c_long = 308; pub const SYS_ppoll: ::c_long = 309; pub const SYS_unshare: ::c_long = 310; pub const SYS_set_robust_list: ::c_long = 311; pub const SYS_get_robust_list: ::c_long = 312; pub const SYS_splice: ::c_long = 313; pub const SYS_sync_file_range: ::c_long = 314; pub const SYS_tee: ::c_long = 315; pub const SYS_vmsplice: ::c_long = 316; pub const SYS_move_pages: ::c_long = 317; pub const SYS_getcpu: ::c_long = 318; pub const SYS_epoll_pwait: ::c_long = 319; pub const SYS_utimensat: ::c_long = 320; pub const SYS_signalfd: ::c_long = 321; pub const SYS_timerfd_create: ::c_long = 322; pub const SYS_eventfd: ::c_long = 323; pub const SYS_fallocate: ::c_long = 324; pub const SYS_timerfd_settime: ::c_long = 325; pub const SYS_timerfd_gettime: ::c_long = 326; pub const SYS_signalfd4: ::c_long = 327; pub const SYS_eventfd2: ::c_long = 328; pub const SYS_epoll_create1: ::c_long = 329; pub const SYS_dup3: ::c_long = 330; pub const SYS_pipe2: ::c_long = 331; pub const SYS_inotify_init1: ::c_long = 332; pub const SYS_preadv: ::c_long = 333; pub const SYS_pwritev: ::c_long = 334; pub const SYS_rt_tgsigqueueinfo: ::c_long = 335; pub const SYS_perf_event_open: ::c_long = 336; pub const SYS_recvmmsg: ::c_long = 337; pub const SYS_fanotify_init: ::c_long = 338; pub const SYS_fanotify_mark: ::c_long = 339; pub const SYS_prlimit64: ::c_long = 340; pub const SYS_name_to_handle_at: ::c_long = 341; pub const SYS_open_by_handle_at: ::c_long = 342; pub const SYS_clock_adjtime: ::c_long = 343; pub const SYS_syncfs: ::c_long = 344; pub const SYS_sendmmsg: ::c_long = 345; pub const SYS_setns: ::c_long = 346; pub const SYS_process_vm_readv: ::c_long = 347; pub const SYS_process_vm_writev: ::c_long = 348; pub const SYS_kcmp: ::c_long = 349; pub const SYS_finit_module: ::c_long = 350; pub const SYS_sched_setattr: ::c_long = 351; pub const SYS_sched_getattr: ::c_long = 352; pub const SYS_renameat2: ::c_long = 353; pub const SYS_seccomp: ::c_long = 354; pub const SYS_getrandom: ::c_long = 355; pub const SYS_memfd_create: ::c_long = 356; pub const SYS_bpf: ::c_long = 357; pub const SYS_execveat: ::c_long = 358; pub const SYS_socket: ::c_long = 359; pub const SYS_socketpair: ::c_long = 360; pub const SYS_bind: ::c_long = 361; pub const SYS_connect: ::c_long = 362; pub const SYS_listen: ::c_long = 363; pub const SYS_accept4: ::c_long = 364; pub const SYS_getsockopt: ::c_long = 365; pub const SYS_setsockopt: ::c_long = 366; pub const SYS_getsockname: ::c_long = 367; pub const SYS_getpeername: ::c_long = 368; pub const SYS_sendto: ::c_long = 369; pub const SYS_sendmsg: ::c_long = 370; pub const SYS_recvfrom: ::c_long = 371; pub const SYS_recvmsg: ::c_long = 372; pub const SYS_shutdown: ::c_long = 373; pub const SYS_userfaultfd: ::c_long = 374; pub const SYS_membarrier: ::c_long = 375; pub const SYS_mlock2: ::c_long = 376; pub const SYS_copy_file_range: ::c_long = 377; pub const SYS_preadv2: ::c_long = 378; pub const SYS_pwritev2: ::c_long = 379; pub const SYS_pkey_mprotect: ::c_long = 380; pub const SYS_pkey_alloc: ::c_long = 381; pub const SYS_pkey_free: ::c_long = 382; pub const SYS_statx: ::c_long = 383; pub const SYS_rseq: ::c_long = 386; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; // offsets in user_regs_structs, from sys/reg.h pub const EBX: ::c_int = 0; pub const ECX: ::c_int = 1; pub const EDX: ::c_int = 2; pub const ESI: ::c_int = 3; pub const EDI: ::c_int = 4; pub const EBP: ::c_int = 5; pub const EAX: ::c_int = 6; pub const DS: ::c_int = 7; pub const ES: ::c_int = 8; pub const FS: ::c_int = 9; pub const GS: ::c_int = 10; pub const ORIG_EAX: ::c_int = 11; pub const EIP: ::c_int = 12; pub const CS: ::c_int = 13; pub const EFL: ::c_int = 14; pub const UESP: ::c_int = 15; pub const SS: ::c_int = 16; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_GS: ::c_int = 0; pub const REG_FS: ::c_int = 1; pub const REG_ES: ::c_int = 2; pub const REG_DS: ::c_int = 3; pub const REG_EDI: ::c_int = 4; pub const REG_ESI: ::c_int = 5; pub const REG_EBP: ::c_int = 6; pub const REG_ESP: ::c_int = 7; pub const REG_EBX: ::c_int = 8; pub const REG_EDX: ::c_int = 9; pub const REG_ECX: ::c_int = 10; pub const REG_EAX: ::c_int = 11; pub const REG_TRAPNO: ::c_int = 12; pub const REG_ERR: ::c_int = 13; pub const REG_EIP: ::c_int = 14; pub const REG_CS: ::c_int = 15; pub const REG_EFL: ::c_int = 16; pub const REG_UESP: ::c_int = 17; pub const REG_SS: ::c_int = 18; extern "C" { pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int; pub fn setcontext(ucp: *const ucontext_t) -> ::c_int; pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b32/x86/align.rs0000644000175000017500000000022514661133735022771 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 6] } } libc/src/unix/linux_like/linux/gnu/b32/mips/0000775000175000017500000000000014661133735021657 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs0000644000175000017500000007635714661133735023024 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; s! { pub struct stat64 { pub st_dev: ::c_ulong, st_pad1: [::c_long; 3], pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulong, st_pad2: [::c_long; 2], pub st_size: ::off64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, st_pad3: ::c_long, pub st_blocks: ::blkcnt64_t, st_pad5: [::c_long; 14], } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_frsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_files: ::fsblkcnt_t, pub f_ffree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, f_spare: [::c_long; 6], } pub struct statfs64 { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_frsize: ::c_long, pub f_blocks: u64, pub f_bfree: u64, pub f_files: u64, pub f_ffree: u64, pub f_bavail: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 5], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, __f_unused: ::c_int, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct sigaction { pub sa_flags: ::c_int, pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_restorer: ::Option, _resv: [::c_int; 1], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, pub _pad: [::c_int; 29], } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_uint, pub __seq: ::c_ushort, __pad1: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct msqid_ds { pub msg_perm: ::ipc_perm, #[cfg(target_endian = "big")] __glibc_reserved1: ::c_ulong, pub msg_stime: ::time_t, #[cfg(target_endian = "little")] __glibc_reserved1: ::c_ulong, #[cfg(target_endian = "big")] __glibc_reserved2: ::c_ulong, pub msg_rtime: ::time_t, #[cfg(target_endian = "little")] __glibc_reserved2: ::c_ulong, #[cfg(target_endian = "big")] __glibc_reserved3: ::c_ulong, pub msg_ctime: ::time_t, #[cfg(target_endian = "little")] __glibc_reserved3: ::c_ulong, __msg_cbytes: ::c_ulong, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: ::c_ulong, __glibc_reserved5: ::c_ulong, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_sysid: ::c_long, pub l_pid: ::pid_t, pad: [::c_long; 4], } } pub const O_LARGEFILE: ::c_int = 0x2000; pub const SYS_syscall: ::c_long = 4000 + 0; pub const SYS_exit: ::c_long = 4000 + 1; pub const SYS_fork: ::c_long = 4000 + 2; pub const SYS_read: ::c_long = 4000 + 3; pub const SYS_write: ::c_long = 4000 + 4; pub const SYS_open: ::c_long = 4000 + 5; pub const SYS_close: ::c_long = 4000 + 6; pub const SYS_waitpid: ::c_long = 4000 + 7; pub const SYS_creat: ::c_long = 4000 + 8; pub const SYS_link: ::c_long = 4000 + 9; pub const SYS_unlink: ::c_long = 4000 + 10; pub const SYS_execve: ::c_long = 4000 + 11; pub const SYS_chdir: ::c_long = 4000 + 12; pub const SYS_time: ::c_long = 4000 + 13; pub const SYS_mknod: ::c_long = 4000 + 14; pub const SYS_chmod: ::c_long = 4000 + 15; pub const SYS_lchown: ::c_long = 4000 + 16; pub const SYS_break: ::c_long = 4000 + 17; pub const SYS_lseek: ::c_long = 4000 + 19; pub const SYS_getpid: ::c_long = 4000 + 20; pub const SYS_mount: ::c_long = 4000 + 21; pub const SYS_umount: ::c_long = 4000 + 22; pub const SYS_setuid: ::c_long = 4000 + 23; pub const SYS_getuid: ::c_long = 4000 + 24; pub const SYS_stime: ::c_long = 4000 + 25; pub const SYS_ptrace: ::c_long = 4000 + 26; pub const SYS_alarm: ::c_long = 4000 + 27; pub const SYS_pause: ::c_long = 4000 + 29; pub const SYS_utime: ::c_long = 4000 + 30; pub const SYS_stty: ::c_long = 4000 + 31; pub const SYS_gtty: ::c_long = 4000 + 32; pub const SYS_access: ::c_long = 4000 + 33; pub const SYS_nice: ::c_long = 4000 + 34; pub const SYS_ftime: ::c_long = 4000 + 35; pub const SYS_sync: ::c_long = 4000 + 36; pub const SYS_kill: ::c_long = 4000 + 37; pub const SYS_rename: ::c_long = 4000 + 38; pub const SYS_mkdir: ::c_long = 4000 + 39; pub const SYS_rmdir: ::c_long = 4000 + 40; pub const SYS_dup: ::c_long = 4000 + 41; pub const SYS_pipe: ::c_long = 4000 + 42; pub const SYS_times: ::c_long = 4000 + 43; pub const SYS_prof: ::c_long = 4000 + 44; pub const SYS_brk: ::c_long = 4000 + 45; pub const SYS_setgid: ::c_long = 4000 + 46; pub const SYS_getgid: ::c_long = 4000 + 47; pub const SYS_signal: ::c_long = 4000 + 48; pub const SYS_geteuid: ::c_long = 4000 + 49; pub const SYS_getegid: ::c_long = 4000 + 50; pub const SYS_acct: ::c_long = 4000 + 51; pub const SYS_umount2: ::c_long = 4000 + 52; pub const SYS_lock: ::c_long = 4000 + 53; pub const SYS_ioctl: ::c_long = 4000 + 54; pub const SYS_fcntl: ::c_long = 4000 + 55; pub const SYS_mpx: ::c_long = 4000 + 56; pub const SYS_setpgid: ::c_long = 4000 + 57; pub const SYS_ulimit: ::c_long = 4000 + 58; pub const SYS_umask: ::c_long = 4000 + 60; pub const SYS_chroot: ::c_long = 4000 + 61; pub const SYS_ustat: ::c_long = 4000 + 62; pub const SYS_dup2: ::c_long = 4000 + 63; pub const SYS_getppid: ::c_long = 4000 + 64; pub const SYS_getpgrp: ::c_long = 4000 + 65; pub const SYS_setsid: ::c_long = 4000 + 66; pub const SYS_sigaction: ::c_long = 4000 + 67; pub const SYS_sgetmask: ::c_long = 4000 + 68; pub const SYS_ssetmask: ::c_long = 4000 + 69; pub const SYS_setreuid: ::c_long = 4000 + 70; pub const SYS_setregid: ::c_long = 4000 + 71; pub const SYS_sigsuspend: ::c_long = 4000 + 72; pub const SYS_sigpending: ::c_long = 4000 + 73; pub const SYS_sethostname: ::c_long = 4000 + 74; pub const SYS_setrlimit: ::c_long = 4000 + 75; pub const SYS_getrlimit: ::c_long = 4000 + 76; pub const SYS_getrusage: ::c_long = 4000 + 77; pub const SYS_gettimeofday: ::c_long = 4000 + 78; pub const SYS_settimeofday: ::c_long = 4000 + 79; pub const SYS_getgroups: ::c_long = 4000 + 80; pub const SYS_setgroups: ::c_long = 4000 + 81; pub const SYS_symlink: ::c_long = 4000 + 83; pub const SYS_readlink: ::c_long = 4000 + 85; pub const SYS_uselib: ::c_long = 4000 + 86; pub const SYS_swapon: ::c_long = 4000 + 87; pub const SYS_reboot: ::c_long = 4000 + 88; pub const SYS_readdir: ::c_long = 4000 + 89; pub const SYS_mmap: ::c_long = 4000 + 90; pub const SYS_munmap: ::c_long = 4000 + 91; pub const SYS_truncate: ::c_long = 4000 + 92; pub const SYS_ftruncate: ::c_long = 4000 + 93; pub const SYS_fchmod: ::c_long = 4000 + 94; pub const SYS_fchown: ::c_long = 4000 + 95; pub const SYS_getpriority: ::c_long = 4000 + 96; pub const SYS_setpriority: ::c_long = 4000 + 97; pub const SYS_profil: ::c_long = 4000 + 98; pub const SYS_statfs: ::c_long = 4000 + 99; pub const SYS_fstatfs: ::c_long = 4000 + 100; pub const SYS_ioperm: ::c_long = 4000 + 101; pub const SYS_socketcall: ::c_long = 4000 + 102; pub const SYS_syslog: ::c_long = 4000 + 103; pub const SYS_setitimer: ::c_long = 4000 + 104; pub const SYS_getitimer: ::c_long = 4000 + 105; pub const SYS_stat: ::c_long = 4000 + 106; pub const SYS_lstat: ::c_long = 4000 + 107; pub const SYS_fstat: ::c_long = 4000 + 108; pub const SYS_iopl: ::c_long = 4000 + 110; pub const SYS_vhangup: ::c_long = 4000 + 111; pub const SYS_idle: ::c_long = 4000 + 112; pub const SYS_vm86: ::c_long = 4000 + 113; pub const SYS_wait4: ::c_long = 4000 + 114; pub const SYS_swapoff: ::c_long = 4000 + 115; pub const SYS_sysinfo: ::c_long = 4000 + 116; pub const SYS_ipc: ::c_long = 4000 + 117; pub const SYS_fsync: ::c_long = 4000 + 118; pub const SYS_sigreturn: ::c_long = 4000 + 119; pub const SYS_clone: ::c_long = 4000 + 120; pub const SYS_setdomainname: ::c_long = 4000 + 121; pub const SYS_uname: ::c_long = 4000 + 122; pub const SYS_modify_ldt: ::c_long = 4000 + 123; pub const SYS_adjtimex: ::c_long = 4000 + 124; pub const SYS_mprotect: ::c_long = 4000 + 125; pub const SYS_sigprocmask: ::c_long = 4000 + 126; pub const SYS_create_module: ::c_long = 4000 + 127; pub const SYS_init_module: ::c_long = 4000 + 128; pub const SYS_delete_module: ::c_long = 4000 + 129; pub const SYS_get_kernel_syms: ::c_long = 4000 + 130; pub const SYS_quotactl: ::c_long = 4000 + 131; pub const SYS_getpgid: ::c_long = 4000 + 132; pub const SYS_fchdir: ::c_long = 4000 + 133; pub const SYS_bdflush: ::c_long = 4000 + 134; pub const SYS_sysfs: ::c_long = 4000 + 135; pub const SYS_personality: ::c_long = 4000 + 136; pub const SYS_afs_syscall: ::c_long = 4000 + 137; pub const SYS_setfsuid: ::c_long = 4000 + 138; pub const SYS_setfsgid: ::c_long = 4000 + 139; pub const SYS__llseek: ::c_long = 4000 + 140; pub const SYS_getdents: ::c_long = 4000 + 141; pub const SYS__newselect: ::c_long = 4000 + 142; pub const SYS_flock: ::c_long = 4000 + 143; pub const SYS_msync: ::c_long = 4000 + 144; pub const SYS_readv: ::c_long = 4000 + 145; pub const SYS_writev: ::c_long = 4000 + 146; pub const SYS_cacheflush: ::c_long = 4000 + 147; pub const SYS_cachectl: ::c_long = 4000 + 148; pub const SYS_sysmips: ::c_long = 4000 + 149; pub const SYS_getsid: ::c_long = 4000 + 151; pub const SYS_fdatasync: ::c_long = 4000 + 152; pub const SYS__sysctl: ::c_long = 4000 + 153; pub const SYS_mlock: ::c_long = 4000 + 154; pub const SYS_munlock: ::c_long = 4000 + 155; pub const SYS_mlockall: ::c_long = 4000 + 156; pub const SYS_munlockall: ::c_long = 4000 + 157; pub const SYS_sched_setparam: ::c_long = 4000 + 158; pub const SYS_sched_getparam: ::c_long = 4000 + 159; pub const SYS_sched_setscheduler: ::c_long = 4000 + 160; pub const SYS_sched_getscheduler: ::c_long = 4000 + 161; pub const SYS_sched_yield: ::c_long = 4000 + 162; pub const SYS_sched_get_priority_max: ::c_long = 4000 + 163; pub const SYS_sched_get_priority_min: ::c_long = 4000 + 164; pub const SYS_sched_rr_get_interval: ::c_long = 4000 + 165; pub const SYS_nanosleep: ::c_long = 4000 + 166; pub const SYS_mremap: ::c_long = 4000 + 167; pub const SYS_accept: ::c_long = 4000 + 168; pub const SYS_bind: ::c_long = 4000 + 169; pub const SYS_connect: ::c_long = 4000 + 170; pub const SYS_getpeername: ::c_long = 4000 + 171; pub const SYS_getsockname: ::c_long = 4000 + 172; pub const SYS_getsockopt: ::c_long = 4000 + 173; pub const SYS_listen: ::c_long = 4000 + 174; pub const SYS_recv: ::c_long = 4000 + 175; pub const SYS_recvfrom: ::c_long = 4000 + 176; pub const SYS_recvmsg: ::c_long = 4000 + 177; pub const SYS_send: ::c_long = 4000 + 178; pub const SYS_sendmsg: ::c_long = 4000 + 179; pub const SYS_sendto: ::c_long = 4000 + 180; pub const SYS_setsockopt: ::c_long = 4000 + 181; pub const SYS_shutdown: ::c_long = 4000 + 182; pub const SYS_socket: ::c_long = 4000 + 183; pub const SYS_socketpair: ::c_long = 4000 + 184; pub const SYS_setresuid: ::c_long = 4000 + 185; pub const SYS_getresuid: ::c_long = 4000 + 186; pub const SYS_query_module: ::c_long = 4000 + 187; pub const SYS_poll: ::c_long = 4000 + 188; pub const SYS_nfsservctl: ::c_long = 4000 + 189; pub const SYS_setresgid: ::c_long = 4000 + 190; pub const SYS_getresgid: ::c_long = 4000 + 191; pub const SYS_prctl: ::c_long = 4000 + 192; pub const SYS_rt_sigreturn: ::c_long = 4000 + 193; pub const SYS_rt_sigaction: ::c_long = 4000 + 194; pub const SYS_rt_sigprocmask: ::c_long = 4000 + 195; pub const SYS_rt_sigpending: ::c_long = 4000 + 196; pub const SYS_rt_sigtimedwait: ::c_long = 4000 + 197; pub const SYS_rt_sigqueueinfo: ::c_long = 4000 + 198; pub const SYS_rt_sigsuspend: ::c_long = 4000 + 199; pub const SYS_pread64: ::c_long = 4000 + 200; pub const SYS_pwrite64: ::c_long = 4000 + 201; pub const SYS_chown: ::c_long = 4000 + 202; pub const SYS_getcwd: ::c_long = 4000 + 203; pub const SYS_capget: ::c_long = 4000 + 204; pub const SYS_capset: ::c_long = 4000 + 205; pub const SYS_sigaltstack: ::c_long = 4000 + 206; pub const SYS_sendfile: ::c_long = 4000 + 207; pub const SYS_getpmsg: ::c_long = 4000 + 208; pub const SYS_putpmsg: ::c_long = 4000 + 209; pub const SYS_mmap2: ::c_long = 4000 + 210; pub const SYS_truncate64: ::c_long = 4000 + 211; pub const SYS_ftruncate64: ::c_long = 4000 + 212; pub const SYS_stat64: ::c_long = 4000 + 213; pub const SYS_lstat64: ::c_long = 4000 + 214; pub const SYS_fstat64: ::c_long = 4000 + 215; pub const SYS_pivot_root: ::c_long = 4000 + 216; pub const SYS_mincore: ::c_long = 4000 + 217; pub const SYS_madvise: ::c_long = 4000 + 218; pub const SYS_getdents64: ::c_long = 4000 + 219; pub const SYS_fcntl64: ::c_long = 4000 + 220; pub const SYS_gettid: ::c_long = 4000 + 222; pub const SYS_readahead: ::c_long = 4000 + 223; pub const SYS_setxattr: ::c_long = 4000 + 224; pub const SYS_lsetxattr: ::c_long = 4000 + 225; pub const SYS_fsetxattr: ::c_long = 4000 + 226; pub const SYS_getxattr: ::c_long = 4000 + 227; pub const SYS_lgetxattr: ::c_long = 4000 + 228; pub const SYS_fgetxattr: ::c_long = 4000 + 229; pub const SYS_listxattr: ::c_long = 4000 + 230; pub const SYS_llistxattr: ::c_long = 4000 + 231; pub const SYS_flistxattr: ::c_long = 4000 + 232; pub const SYS_removexattr: ::c_long = 4000 + 233; pub const SYS_lremovexattr: ::c_long = 4000 + 234; pub const SYS_fremovexattr: ::c_long = 4000 + 235; pub const SYS_tkill: ::c_long = 4000 + 236; pub const SYS_sendfile64: ::c_long = 4000 + 237; pub const SYS_futex: ::c_long = 4000 + 238; pub const SYS_sched_setaffinity: ::c_long = 4000 + 239; pub const SYS_sched_getaffinity: ::c_long = 4000 + 240; pub const SYS_io_setup: ::c_long = 4000 + 241; pub const SYS_io_destroy: ::c_long = 4000 + 242; pub const SYS_io_getevents: ::c_long = 4000 + 243; pub const SYS_io_submit: ::c_long = 4000 + 244; pub const SYS_io_cancel: ::c_long = 4000 + 245; pub const SYS_exit_group: ::c_long = 4000 + 246; pub const SYS_lookup_dcookie: ::c_long = 4000 + 247; pub const SYS_epoll_create: ::c_long = 4000 + 248; pub const SYS_epoll_ctl: ::c_long = 4000 + 249; pub const SYS_epoll_wait: ::c_long = 4000 + 250; pub const SYS_remap_file_pages: ::c_long = 4000 + 251; pub const SYS_set_tid_address: ::c_long = 4000 + 252; pub const SYS_restart_syscall: ::c_long = 4000 + 253; pub const SYS_fadvise64: ::c_long = 4000 + 254; pub const SYS_statfs64: ::c_long = 4000 + 255; pub const SYS_fstatfs64: ::c_long = 4000 + 256; pub const SYS_timer_create: ::c_long = 4000 + 257; pub const SYS_timer_settime: ::c_long = 4000 + 258; pub const SYS_timer_gettime: ::c_long = 4000 + 259; pub const SYS_timer_getoverrun: ::c_long = 4000 + 260; pub const SYS_timer_delete: ::c_long = 4000 + 261; pub const SYS_clock_settime: ::c_long = 4000 + 262; pub const SYS_clock_gettime: ::c_long = 4000 + 263; pub const SYS_clock_getres: ::c_long = 4000 + 264; pub const SYS_clock_nanosleep: ::c_long = 4000 + 265; pub const SYS_tgkill: ::c_long = 4000 + 266; pub const SYS_utimes: ::c_long = 4000 + 267; pub const SYS_mbind: ::c_long = 4000 + 268; pub const SYS_get_mempolicy: ::c_long = 4000 + 269; pub const SYS_set_mempolicy: ::c_long = 4000 + 270; pub const SYS_mq_open: ::c_long = 4000 + 271; pub const SYS_mq_unlink: ::c_long = 4000 + 272; pub const SYS_mq_timedsend: ::c_long = 4000 + 273; pub const SYS_mq_timedreceive: ::c_long = 4000 + 274; pub const SYS_mq_notify: ::c_long = 4000 + 275; pub const SYS_mq_getsetattr: ::c_long = 4000 + 276; pub const SYS_vserver: ::c_long = 4000 + 277; pub const SYS_waitid: ::c_long = 4000 + 278; /* pub const SYS_sys_setaltroot: ::c_long = 4000 + 279; */ pub const SYS_add_key: ::c_long = 4000 + 280; pub const SYS_request_key: ::c_long = 4000 + 281; pub const SYS_keyctl: ::c_long = 4000 + 282; pub const SYS_set_thread_area: ::c_long = 4000 + 283; pub const SYS_inotify_init: ::c_long = 4000 + 284; pub const SYS_inotify_add_watch: ::c_long = 4000 + 285; pub const SYS_inotify_rm_watch: ::c_long = 4000 + 286; pub const SYS_migrate_pages: ::c_long = 4000 + 287; pub const SYS_openat: ::c_long = 4000 + 288; pub const SYS_mkdirat: ::c_long = 4000 + 289; pub const SYS_mknodat: ::c_long = 4000 + 290; pub const SYS_fchownat: ::c_long = 4000 + 291; pub const SYS_futimesat: ::c_long = 4000 + 292; pub const SYS_fstatat64: ::c_long = 4000 + 293; pub const SYS_unlinkat: ::c_long = 4000 + 294; pub const SYS_renameat: ::c_long = 4000 + 295; pub const SYS_linkat: ::c_long = 4000 + 296; pub const SYS_symlinkat: ::c_long = 4000 + 297; pub const SYS_readlinkat: ::c_long = 4000 + 298; pub const SYS_fchmodat: ::c_long = 4000 + 299; pub const SYS_faccessat: ::c_long = 4000 + 300; pub const SYS_pselect6: ::c_long = 4000 + 301; pub const SYS_ppoll: ::c_long = 4000 + 302; pub const SYS_unshare: ::c_long = 4000 + 303; pub const SYS_splice: ::c_long = 4000 + 304; pub const SYS_sync_file_range: ::c_long = 4000 + 305; pub const SYS_tee: ::c_long = 4000 + 306; pub const SYS_vmsplice: ::c_long = 4000 + 307; pub const SYS_move_pages: ::c_long = 4000 + 308; pub const SYS_set_robust_list: ::c_long = 4000 + 309; pub const SYS_get_robust_list: ::c_long = 4000 + 310; pub const SYS_kexec_load: ::c_long = 4000 + 311; pub const SYS_getcpu: ::c_long = 4000 + 312; pub const SYS_epoll_pwait: ::c_long = 4000 + 313; pub const SYS_ioprio_set: ::c_long = 4000 + 314; pub const SYS_ioprio_get: ::c_long = 4000 + 315; pub const SYS_utimensat: ::c_long = 4000 + 316; pub const SYS_signalfd: ::c_long = 4000 + 317; pub const SYS_timerfd: ::c_long = 4000 + 318; pub const SYS_eventfd: ::c_long = 4000 + 319; pub const SYS_fallocate: ::c_long = 4000 + 320; pub const SYS_timerfd_create: ::c_long = 4000 + 321; pub const SYS_timerfd_gettime: ::c_long = 4000 + 322; pub const SYS_timerfd_settime: ::c_long = 4000 + 323; pub const SYS_signalfd4: ::c_long = 4000 + 324; pub const SYS_eventfd2: ::c_long = 4000 + 325; pub const SYS_epoll_create1: ::c_long = 4000 + 326; pub const SYS_dup3: ::c_long = 4000 + 327; pub const SYS_pipe2: ::c_long = 4000 + 328; pub const SYS_inotify_init1: ::c_long = 4000 + 329; pub const SYS_preadv: ::c_long = 4000 + 330; pub const SYS_pwritev: ::c_long = 4000 + 331; pub const SYS_rt_tgsigqueueinfo: ::c_long = 4000 + 332; pub const SYS_perf_event_open: ::c_long = 4000 + 333; pub const SYS_accept4: ::c_long = 4000 + 334; pub const SYS_recvmmsg: ::c_long = 4000 + 335; pub const SYS_fanotify_init: ::c_long = 4000 + 336; pub const SYS_fanotify_mark: ::c_long = 4000 + 337; pub const SYS_prlimit64: ::c_long = 4000 + 338; pub const SYS_name_to_handle_at: ::c_long = 4000 + 339; pub const SYS_open_by_handle_at: ::c_long = 4000 + 340; pub const SYS_clock_adjtime: ::c_long = 4000 + 341; pub const SYS_syncfs: ::c_long = 4000 + 342; pub const SYS_sendmmsg: ::c_long = 4000 + 343; pub const SYS_setns: ::c_long = 4000 + 344; pub const SYS_process_vm_readv: ::c_long = 4000 + 345; pub const SYS_process_vm_writev: ::c_long = 4000 + 346; pub const SYS_kcmp: ::c_long = 4000 + 347; pub const SYS_finit_module: ::c_long = 4000 + 348; pub const SYS_sched_setattr: ::c_long = 4000 + 349; pub const SYS_sched_getattr: ::c_long = 4000 + 350; pub const SYS_renameat2: ::c_long = 4000 + 351; pub const SYS_seccomp: ::c_long = 4000 + 352; pub const SYS_getrandom: ::c_long = 4000 + 353; pub const SYS_memfd_create: ::c_long = 4000 + 354; pub const SYS_bpf: ::c_long = 4000 + 355; pub const SYS_execveat: ::c_long = 4000 + 356; pub const SYS_userfaultfd: ::c_long = 4000 + 357; pub const SYS_membarrier: ::c_long = 4000 + 358; pub const SYS_mlock2: ::c_long = 4000 + 359; pub const SYS_copy_file_range: ::c_long = 4000 + 360; pub const SYS_preadv2: ::c_long = 4000 + 361; pub const SYS_pwritev2: ::c_long = 4000 + 362; pub const SYS_pkey_mprotect: ::c_long = 4000 + 363; pub const SYS_pkey_alloc: ::c_long = 4000 + 364; pub const SYS_pkey_free: ::c_long = 4000 + 365; pub const SYS_statx: ::c_long = 4000 + 366; pub const SYS_rseq: ::c_long = 4000 + 367; pub const SYS_pidfd_send_signal: ::c_long = 4000 + 424; pub const SYS_io_uring_setup: ::c_long = 4000 + 425; pub const SYS_io_uring_enter: ::c_long = 4000 + 426; pub const SYS_io_uring_register: ::c_long = 4000 + 427; pub const SYS_open_tree: ::c_long = 4000 + 428; pub const SYS_move_mount: ::c_long = 4000 + 429; pub const SYS_fsopen: ::c_long = 4000 + 430; pub const SYS_fsconfig: ::c_long = 4000 + 431; pub const SYS_fsmount: ::c_long = 4000 + 432; pub const SYS_fspick: ::c_long = 4000 + 433; pub const SYS_pidfd_open: ::c_long = 4000 + 434; pub const SYS_clone3: ::c_long = 4000 + 435; pub const SYS_close_range: ::c_long = 4000 + 436; pub const SYS_openat2: ::c_long = 4000 + 437; pub const SYS_pidfd_getfd: ::c_long = 4000 + 438; pub const SYS_faccessat2: ::c_long = 4000 + 439; pub const SYS_process_madvise: ::c_long = 4000 + 440; pub const SYS_epoll_pwait2: ::c_long = 4000 + 441; pub const SYS_mount_setattr: ::c_long = 4000 + 442; pub const SYS_quotactl_fd: ::c_long = 4000 + 443; pub const SYS_landlock_create_ruleset: ::c_long = 4000 + 444; pub const SYS_landlock_add_rule: ::c_long = 4000 + 445; pub const SYS_landlock_restrict_self: ::c_long = 4000 + 446; pub const SYS_memfd_secret: ::c_long = 4000 + 447; pub const SYS_process_mrelease: ::c_long = 4000 + 448; pub const SYS_futex_waitv: ::c_long = 4000 + 449; pub const SYS_set_mempolicy_home_node: ::c_long = 4000 + 450; pub const O_DIRECT: ::c_int = 0x8000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_APPEND: ::c_int = 8; pub const O_CREAT: ::c_int = 256; pub const O_EXCL: ::c_int = 1024; pub const O_NOCTTY: ::c_int = 2048; pub const O_NONBLOCK: ::c_int = 128; pub const O_SYNC: ::c_int = 0x4010; pub const O_RSYNC: ::c_int = 0x4010; pub const O_DSYNC: ::c_int = 0x10; pub const O_FSYNC: ::c_int = 0x4010; pub const O_ASYNC: ::c_int = 0x1000; pub const O_NDELAY: ::c_int = 0x80; pub const EDEADLK: ::c_int = 45; pub const ENAMETOOLONG: ::c_int = 78; pub const ENOLCK: ::c_int = 46; pub const ENOSYS: ::c_int = 89; pub const ENOTEMPTY: ::c_int = 93; pub const ELOOP: ::c_int = 90; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EBADE: ::c_int = 50; pub const EBADR: ::c_int = 51; pub const EXFULL: ::c_int = 52; pub const ENOANO: ::c_int = 53; pub const EBADRQC: ::c_int = 54; pub const EBADSLT: ::c_int = 55; pub const EDEADLOCK: ::c_int = 56; pub const EMULTIHOP: ::c_int = 74; pub const EOVERFLOW: ::c_int = 79; pub const ENOTUNIQ: ::c_int = 80; pub const EBADFD: ::c_int = 81; pub const EBADMSG: ::c_int = 77; pub const EREMCHG: ::c_int = 82; pub const ELIBACC: ::c_int = 83; pub const ELIBBAD: ::c_int = 84; pub const ELIBSCN: ::c_int = 85; pub const ELIBMAX: ::c_int = 86; pub const ELIBEXEC: ::c_int = 87; pub const EILSEQ: ::c_int = 88; pub const ERESTART: ::c_int = 91; pub const ESTRPIPE: ::c_int = 92; pub const EUSERS: ::c_int = 94; pub const ENOTSOCK: ::c_int = 95; pub const EDESTADDRREQ: ::c_int = 96; pub const EMSGSIZE: ::c_int = 97; pub const EPROTOTYPE: ::c_int = 98; pub const ENOPROTOOPT: ::c_int = 99; pub const EPROTONOSUPPORT: ::c_int = 120; pub const ESOCKTNOSUPPORT: ::c_int = 121; pub const EOPNOTSUPP: ::c_int = 122; pub const EPFNOSUPPORT: ::c_int = 123; pub const EAFNOSUPPORT: ::c_int = 124; pub const EADDRINUSE: ::c_int = 125; pub const EADDRNOTAVAIL: ::c_int = 126; pub const ENETDOWN: ::c_int = 127; pub const ENETUNREACH: ::c_int = 128; pub const ENETRESET: ::c_int = 129; pub const ECONNABORTED: ::c_int = 130; pub const ECONNRESET: ::c_int = 131; pub const ENOBUFS: ::c_int = 132; pub const EISCONN: ::c_int = 133; pub const ENOTCONN: ::c_int = 134; pub const ESHUTDOWN: ::c_int = 143; pub const ETOOMANYREFS: ::c_int = 144; pub const ETIMEDOUT: ::c_int = 145; pub const ECONNREFUSED: ::c_int = 146; pub const EHOSTDOWN: ::c_int = 147; pub const EHOSTUNREACH: ::c_int = 148; pub const EALREADY: ::c_int = 149; pub const EINPROGRESS: ::c_int = 150; pub const ESTALE: ::c_int = 151; pub const EUCLEAN: ::c_int = 135; pub const ENOTNAM: ::c_int = 137; pub const ENAVAIL: ::c_int = 138; pub const EISNAM: ::c_int = 139; pub const EREMOTEIO: ::c_int = 140; pub const EDQUOT: ::c_int = 1133; pub const ENOMEDIUM: ::c_int = 159; pub const EMEDIUMTYPE: ::c_int = 160; pub const ECANCELED: ::c_int = 158; pub const ENOKEY: ::c_int = 161; pub const EKEYEXPIRED: ::c_int = 162; pub const EKEYREVOKED: ::c_int = 163; pub const EKEYREJECTED: ::c_int = 164; pub const EOWNERDEAD: ::c_int = 165; pub const ENOTRECOVERABLE: ::c_int = 166; pub const ERFKILL: ::c_int = 167; pub const MAP_NORESERVE: ::c_int = 0x400; pub const MAP_ANON: ::c_int = 0x800; pub const MAP_ANONYMOUS: ::c_int = 0x800; pub const MAP_GROWSDOWN: ::c_int = 0x1000; pub const MAP_DENYWRITE: ::c_int = 0x2000; pub const MAP_EXECUTABLE: ::c_int = 0x4000; pub const MAP_LOCKED: ::c_int = 0x8000; pub const MAP_POPULATE: ::c_int = 0x10000; pub const MAP_NONBLOCK: ::c_int = 0x20000; pub const MAP_STACK: ::c_int = 0x40000; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; pub const SA_SIGINFO: ::c_int = 0x00000008; pub const SA_NOCLDWAIT: ::c_int = 0x00010000; pub const SIGCHLD: ::c_int = 18; pub const SIGBUS: ::c_int = 10; pub const SIGTTIN: ::c_int = 26; pub const SIGTTOU: ::c_int = 27; pub const SIGXCPU: ::c_int = 30; pub const SIGXFSZ: ::c_int = 31; pub const SIGVTALRM: ::c_int = 28; pub const SIGPROF: ::c_int = 29; pub const SIGWINCH: ::c_int = 20; pub const SIGUSR1: ::c_int = 16; pub const SIGUSR2: ::c_int = 17; pub const SIGCONT: ::c_int = 25; pub const SIGSTOP: ::c_int = 23; pub const SIGTSTP: ::c_int = 24; pub const SIGURG: ::c_int = 21; pub const SIGIO: ::c_int = 22; pub const SIGSYS: ::c_int = 12; pub const SIGPOLL: ::c_int = 22; pub const SIGPWR: ::c_int = 19; pub const SIG_SETMASK: ::c_int = 3; pub const SIG_BLOCK: ::c_int = 0x1; pub const SIG_UNBLOCK: ::c_int = 0x2; pub const POLLWRNORM: ::c_short = 0x004; pub const POLLWRBAND: ::c_short = 0x100; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: ::tcflag_t = 0x00000100; pub const TOSTOP: ::tcflag_t = 0x00008000; pub const FLUSHO: ::tcflag_t = 0x00002000; pub const EXTPROC: ::tcflag_t = 0o200000; pub const TCSANOW: ::c_int = 0x540e; pub const TCSADRAIN: ::c_int = 0x540f; pub const TCSAFLUSH: ::c_int = 0x5410; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const MAP_HUGETLB: ::c_int = 0x080000; pub const EFD_NONBLOCK: ::c_int = 0x80; pub const F_GETLK: ::c_int = 14; pub const F_GETOWN: ::c_int = 23; pub const F_SETOWN: ::c_int = 24; pub const SFD_NONBLOCK: ::c_int = 0x80; pub const RTLD_DEEPBIND: ::c_int = 0x10; pub const RTLD_GLOBAL: ::c_int = 0x4; pub const RTLD_NOLOAD: ::c_int = 0x8; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const EHWPOISON: ::c_int = 168; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b32/mips/align.rs0000644000175000017500000000022414661133735023313 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f32; 4] } } libc/src/unix/linux_like/linux/gnu/mod.rs0000644000175000017500000015102114661133735021444 0ustar jamespagejamespagepub type pthread_t = c_ulong; pub type __priority_which_t = ::c_uint; pub type __rlimit_resource_t = ::c_uint; pub type Lmid_t = ::c_long; pub type regoff_t = ::c_int; pub type __kernel_rwf_t = ::c_int; cfg_if! { if #[cfg(doc)] { // Used in `linux::arch` to define ioctl constants. pub(crate) type Ioctl = ::c_ulong; } else { #[doc(hidden)] pub type Ioctl = ::c_ulong; } } s! { pub struct statx { pub stx_mask: u32, pub stx_blksize: u32, pub stx_attributes: u64, pub stx_nlink: u32, pub stx_uid: u32, pub stx_gid: u32, pub stx_mode: u16, __statx_pad1: [u16; 1], pub stx_ino: u64, pub stx_size: u64, pub stx_blocks: u64, pub stx_attributes_mask: u64, pub stx_atime: ::statx_timestamp, pub stx_btime: ::statx_timestamp, pub stx_ctime: ::statx_timestamp, pub stx_mtime: ::statx_timestamp, pub stx_rdev_major: u32, pub stx_rdev_minor: u32, pub stx_dev_major: u32, pub stx_dev_minor: u32, pub stx_mnt_id: u64, pub stx_dio_mem_align: u32, pub stx_dio_offset_align: u32, __statx_pad3: [u64; 12], } pub struct statx_timestamp { pub tv_sec: i64, pub tv_nsec: u32, pub __statx_timestamp_pad1: [i32; 1], } pub struct aiocb { pub aio_fildes: ::c_int, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_sigevent: ::sigevent, __next_prio: *mut aiocb, __abs_prio: ::c_int, __policy: ::c_int, __error_code: ::c_int, __return_value: ::ssize_t, pub aio_offset: off_t, #[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))] __unused1: [::c_char; 4], __glibc_reserved: [::c_char; 32] } pub struct __exit_status { pub e_termination: ::c_short, pub e_exit: ::c_short, } pub struct __timeval { pub tv_sec: i32, pub tv_usec: i32, } pub struct glob64_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut ::c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::size_t, pub msg_control: *mut ::c_void, pub msg_controllen: ::size_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::size_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], #[cfg(not(any( target_arch = "sparc", target_arch = "sparc64", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6")))] pub c_ispeed: ::speed_t, #[cfg(not(any( target_arch = "sparc", target_arch = "sparc64", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6")))] pub c_ospeed: ::speed_t, } pub struct mallinfo { pub arena: ::c_int, pub ordblks: ::c_int, pub smblks: ::c_int, pub hblks: ::c_int, pub hblkhd: ::c_int, pub usmblks: ::c_int, pub fsmblks: ::c_int, pub uordblks: ::c_int, pub fordblks: ::c_int, pub keepcost: ::c_int, } pub struct mallinfo2 { pub arena: ::size_t, pub ordblks: ::size_t, pub smblks: ::size_t, pub hblks: ::size_t, pub hblkhd: ::size_t, pub usmblks: ::size_t, pub fsmblks: ::size_t, pub uordblks: ::size_t, pub fordblks: ::size_t, pub keepcost: ::size_t, } pub struct nl_pktinfo { pub group: u32, } pub struct nl_mmap_req { pub nm_block_size: ::c_uint, pub nm_block_nr: ::c_uint, pub nm_frame_size: ::c_uint, pub nm_frame_nr: ::c_uint, } pub struct nl_mmap_hdr { pub nm_status: ::c_uint, pub nm_len: ::c_uint, pub nm_group: u32, pub nm_pid: u32, pub nm_uid: u32, pub nm_gid: u32, } pub struct rtentry { pub rt_pad1: ::c_ulong, pub rt_dst: ::sockaddr, pub rt_gateway: ::sockaddr, pub rt_genmask: ::sockaddr, pub rt_flags: ::c_ushort, pub rt_pad2: ::c_short, pub rt_pad3: ::c_ulong, pub rt_tos: ::c_uchar, pub rt_class: ::c_uchar, #[cfg(target_pointer_width = "64")] pub rt_pad4: [::c_short; 3usize], #[cfg(not(target_pointer_width = "64"))] pub rt_pad4: ::c_short, pub rt_metric: ::c_short, pub rt_dev: *mut ::c_char, pub rt_mtu: ::c_ulong, pub rt_window: ::c_ulong, pub rt_irtt: ::c_ushort, } pub struct timex { pub modes: ::c_uint, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub offset: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub offset: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub freq: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub freq: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub maxerror: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub maxerror: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub esterror: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub esterror: ::c_long, pub status: ::c_int, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub constant: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub constant: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub precision: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub precision: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub tolerance: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub tolerance: ::c_long, pub time: ::timeval, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub tick: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub tick: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub ppsfreq: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub ppsfreq: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub jitter: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub jitter: ::c_long, pub shift: ::c_int, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub stabil: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub stabil: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub jitcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub jitcnt: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub calcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub calcnt: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub errcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub errcnt: ::c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub stbcnt: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub stbcnt: ::c_long, pub tai: ::c_int, pub __unused1: i32, pub __unused2: i32, pub __unused3: i32, pub __unused4: i32, pub __unused5: i32, pub __unused6: i32, pub __unused7: i32, pub __unused8: i32, pub __unused9: i32, pub __unused10: i32, pub __unused11: i32, } pub struct ntptimeval { pub time: ::timeval, pub maxerror: ::c_long, pub esterror: ::c_long, pub tai: ::c_long, pub __glibc_reserved1: ::c_long, pub __glibc_reserved2: ::c_long, pub __glibc_reserved3: ::c_long, pub __glibc_reserved4: ::c_long, } pub struct regex_t { __buffer: *mut ::c_void, __allocated: ::size_t, __used: ::size_t, __syntax: ::c_ulong, __fastmap: *mut ::c_char, __translate: *mut ::c_char, __re_nsub: ::size_t, __bitfield: u8, } pub struct Elf64_Chdr { pub ch_type: ::Elf64_Word, pub ch_reserved: ::Elf64_Word, pub ch_size: ::Elf64_Xword, pub ch_addralign: ::Elf64_Xword, } pub struct Elf32_Chdr { pub ch_type: ::Elf32_Word, pub ch_size: ::Elf32_Word, pub ch_addralign: ::Elf32_Word, } pub struct seminfo { pub semmap: ::c_int, pub semmni: ::c_int, pub semmns: ::c_int, pub semmnu: ::c_int, pub semmsl: ::c_int, pub semopm: ::c_int, pub semume: ::c_int, pub semusz: ::c_int, pub semvmx: ::c_int, pub semaem: ::c_int, } pub struct ptrace_peeksiginfo_args { pub off: ::__u64, pub flags: ::__u32, pub nr: ::__s32, } pub struct __c_anonymous_ptrace_syscall_info_entry { pub nr: ::__u64, pub args: [::__u64; 6], } pub struct __c_anonymous_ptrace_syscall_info_exit { pub sval: ::__s64, pub is_error: ::__u8, } pub struct __c_anonymous_ptrace_syscall_info_seccomp { pub nr: ::__u64, pub args: [::__u64; 6], pub ret_data: ::__u32, } pub struct ptrace_syscall_info { pub op: ::__u8, pub pad: [::__u8; 3], pub arch: ::__u32, pub instruction_pointer: ::__u64, pub stack_pointer: ::__u64, #[cfg(libc_union)] pub u: __c_anonymous_ptrace_syscall_info_data, } // linux/if_xdp.h pub struct sockaddr_xdp { pub sxdp_family: ::__u16, pub sxdp_flags: ::__u16, pub sxdp_ifindex: ::__u32, pub sxdp_queue_id: ::__u32, pub sxdp_shared_umem_fd: ::__u32, } pub struct xdp_ring_offset { pub producer: ::__u64, pub consumer: ::__u64, pub desc: ::__u64, pub flags: ::__u64, } pub struct xdp_mmap_offsets { pub rx: xdp_ring_offset, pub tx: xdp_ring_offset, pub fr: xdp_ring_offset, pub cr: xdp_ring_offset, } pub struct xdp_ring_offset_v1 { pub producer: ::__u64, pub consumer: ::__u64, pub desc: ::__u64, } pub struct xdp_mmap_offsets_v1 { pub rx: xdp_ring_offset_v1, pub tx: xdp_ring_offset_v1, pub fr: xdp_ring_offset_v1, pub cr: xdp_ring_offset_v1, } pub struct xdp_umem_reg { pub addr: ::__u64, pub len: ::__u64, pub chunk_size: ::__u32, pub headroom: ::__u32, pub flags: ::__u32, } pub struct xdp_umem_reg_v1 { pub addr: ::__u64, pub len: ::__u64, pub chunk_size: ::__u32, pub headroom: ::__u32, } pub struct xdp_statistics { pub rx_dropped: ::__u64, pub rx_invalid_descs: ::__u64, pub tx_invalid_descs: ::__u64, pub rx_ring_full: ::__u64, pub rx_fill_ring_empty_descs: ::__u64, pub tx_ring_empty_descs: ::__u64, } pub struct xdp_statistics_v1 { pub rx_dropped: ::__u64, pub rx_invalid_descs: ::__u64, pub tx_invalid_descs: ::__u64, } pub struct xdp_options { pub flags: ::__u32, } pub struct xdp_desc { pub addr: ::__u64, pub len: ::__u32, pub options: ::__u32, } pub struct iocb { pub aio_data: ::__u64, #[cfg(target_endian = "little")] pub aio_key: ::__u32, #[cfg(target_endian = "little")] pub aio_rw_flags: ::__kernel_rwf_t, #[cfg(target_endian = "big")] pub aio_rw_flags: ::__kernel_rwf_t, #[cfg(target_endian = "big")] pub aio_key: ::__u32, pub aio_lio_opcode: ::__u16, pub aio_reqprio: ::__s16, pub aio_fildes: ::__u32, pub aio_buf: ::__u64, pub aio_nbytes: ::__u64, pub aio_offset: ::__s64, aio_reserved2: ::__u64, pub aio_flags: ::__u32, pub aio_resfd: ::__u32, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, si_addr: *mut ::c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, _si_tid: ::c_int, _si_overrun: ::c_int, si_sigval: ::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).si_sigval } } cfg_if! { if #[cfg(libc_union)] { // Internal, for casts to access union fields #[repr(C)] struct sifields_sigchld { si_pid: ::pid_t, si_uid: ::uid_t, si_status: ::c_int, si_utime: ::c_long, si_stime: ::c_long, } impl ::Copy for sifields_sigchld {} impl ::Clone for sifields_sigchld { fn clone(&self) -> sifields_sigchld { *self } } // Internal, for casts to access union fields #[repr(C)] union sifields { _align_pointer: *mut ::c_void, sigchld: sifields_sigchld, } // Internal, for casts to access union fields. Note that some variants // of sifields start with a pointer, which makes the alignment of // sifields vary on 32-bit and 64-bit architectures. #[repr(C)] struct siginfo_f { _siginfo_base: [::c_int; 3], sifields: sifields, } impl siginfo_t { unsafe fn sifields(&self) -> &sifields { &(*(self as *const siginfo_t as *const siginfo_f)).sifields } pub unsafe fn si_pid(&self) -> ::pid_t { self.sifields().sigchld.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.sifields().sigchld.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.sifields().sigchld.si_status } pub unsafe fn si_utime(&self) -> ::c_long { self.sifields().sigchld.si_utime } pub unsafe fn si_stime(&self) -> ::c_long { self.sifields().sigchld.si_stime } } pub union __c_anonymous_ptrace_syscall_info_data { pub entry: __c_anonymous_ptrace_syscall_info_entry, pub exit: __c_anonymous_ptrace_syscall_info_exit, pub seccomp: __c_anonymous_ptrace_syscall_info_seccomp, } impl ::Copy for __c_anonymous_ptrace_syscall_info_data {} impl ::Clone for __c_anonymous_ptrace_syscall_info_data { fn clone(&self) -> __c_anonymous_ptrace_syscall_info_data { *self } } } } s_no_extra_traits! { pub struct utmpx { pub ut_type: ::c_short, pub ut_pid: ::pid_t, pub ut_line: [::c_char; __UT_LINESIZE], pub ut_id: [::c_char; 4], pub ut_user: [::c_char; __UT_NAMESIZE], pub ut_host: [::c_char; __UT_HOSTSIZE], pub ut_exit: __exit_status, #[cfg(any(target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64"))))] pub ut_session: ::c_long, #[cfg(any(target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64"))))] pub ut_tv: ::timeval, #[cfg(not(any(target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64")))))] pub ut_session: i32, #[cfg(not(any(target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64", all(target_pointer_width = "32", not(target_arch = "x86_64")))))] pub ut_tv: __timeval, pub ut_addr_v6: [i32; 4], __glibc_reserved: [::c_char; 20], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_user == other.ut_user && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.__glibc_reserved == other.__glibc_reserved } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) // FIXME: .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("__glibc_reserved", &self.__glibc_reserved) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.__glibc_reserved.hash(state); } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_ptrace_syscall_info_data { fn eq(&self, other: &__c_anonymous_ptrace_syscall_info_data) -> bool { unsafe { self.entry == other.entry || self.exit == other.exit || self.seccomp == other.seccomp } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ptrace_syscall_info_data {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ptrace_syscall_info_data { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("__c_anonymous_ptrace_syscall_info_data") .field("entry", &self.entry) .field("exit", &self.exit) .field("seccomp", &self.seccomp) .finish() } } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ptrace_syscall_info_data { fn hash(&self, state: &mut H) { unsafe { self.entry.hash(state); self.exit.hash(state); self.seccomp.hash(state); } } } } } // include/uapi/asm-generic/hugetlb_encode.h pub const HUGETLB_FLAG_ENCODE_SHIFT: ::c_int = 26; pub const HUGETLB_FLAG_ENCODE_MASK: ::c_int = 0x3f; pub const HUGETLB_FLAG_ENCODE_64KB: ::c_int = 16 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_512KB: ::c_int = 19 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_1MB: ::c_int = 20 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_2MB: ::c_int = 21 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_8MB: ::c_int = 23 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_16MB: ::c_int = 24 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_32MB: ::c_int = 25 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_256MB: ::c_int = 28 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_512MB: ::c_int = 29 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_1GB: ::c_int = 30 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_2GB: ::c_int = 31 << HUGETLB_FLAG_ENCODE_SHIFT; pub const HUGETLB_FLAG_ENCODE_16GB: ::c_int = 34 << HUGETLB_FLAG_ENCODE_SHIFT; // include/uapi/linux/mman.h /* * Huge page size encoding when MAP_HUGETLB is specified, and a huge page * size other than the default is desired. See hugetlb_encode.h. * All known huge page size encodings are provided here. It is the * responsibility of the application to know which sizes are supported on * the running system. See mmap(2) man page for details. */ pub const MAP_HUGE_SHIFT: ::c_int = HUGETLB_FLAG_ENCODE_SHIFT; pub const MAP_HUGE_MASK: ::c_int = HUGETLB_FLAG_ENCODE_MASK; pub const MAP_HUGE_64KB: ::c_int = HUGETLB_FLAG_ENCODE_64KB; pub const MAP_HUGE_512KB: ::c_int = HUGETLB_FLAG_ENCODE_512KB; pub const MAP_HUGE_1MB: ::c_int = HUGETLB_FLAG_ENCODE_1MB; pub const MAP_HUGE_2MB: ::c_int = HUGETLB_FLAG_ENCODE_2MB; pub const MAP_HUGE_8MB: ::c_int = HUGETLB_FLAG_ENCODE_8MB; pub const MAP_HUGE_16MB: ::c_int = HUGETLB_FLAG_ENCODE_16MB; pub const MAP_HUGE_32MB: ::c_int = HUGETLB_FLAG_ENCODE_32MB; pub const MAP_HUGE_256MB: ::c_int = HUGETLB_FLAG_ENCODE_256MB; pub const MAP_HUGE_512MB: ::c_int = HUGETLB_FLAG_ENCODE_512MB; pub const MAP_HUGE_1GB: ::c_int = HUGETLB_FLAG_ENCODE_1GB; pub const MAP_HUGE_2GB: ::c_int = HUGETLB_FLAG_ENCODE_2GB; pub const MAP_HUGE_16GB: ::c_int = HUGETLB_FLAG_ENCODE_16GB; pub const PRIO_PROCESS: ::__priority_which_t = 0; pub const PRIO_PGRP: ::__priority_which_t = 1; pub const PRIO_USER: ::__priority_which_t = 2; pub const MS_RMT_MASK: ::c_ulong = 0x02800051; pub const __UT_LINESIZE: usize = 32; pub const __UT_NAMESIZE: usize = 32; pub const __UT_HOSTSIZE: usize = 256; pub const EMPTY: ::c_short = 0; pub const RUN_LVL: ::c_short = 1; pub const BOOT_TIME: ::c_short = 2; pub const NEW_TIME: ::c_short = 3; pub const OLD_TIME: ::c_short = 4; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const USER_PROCESS: ::c_short = 7; pub const DEAD_PROCESS: ::c_short = 8; pub const ACCOUNTING: ::c_short = 9; // dlfcn.h pub const LM_ID_BASE: ::c_long = 0; pub const LM_ID_NEWLM: ::c_long = -1; pub const RTLD_DI_LMID: ::c_int = 1; pub const RTLD_DI_LINKMAP: ::c_int = 2; pub const RTLD_DI_CONFIGADDR: ::c_int = 3; pub const RTLD_DI_SERINFO: ::c_int = 4; pub const RTLD_DI_SERINFOSIZE: ::c_int = 5; pub const RTLD_DI_ORIGIN: ::c_int = 6; pub const RTLD_DI_PROFILENAME: ::c_int = 7; pub const RTLD_DI_PROFILEOUT: ::c_int = 8; pub const RTLD_DI_TLS_MODID: ::c_int = 9; pub const RTLD_DI_TLS_DATA: ::c_int = 10; pub const SOCK_NONBLOCK: ::c_int = O_NONBLOCK; pub const PIDFD_NONBLOCK: ::c_uint = O_NONBLOCK as ::c_uint; pub const SOL_RXRPC: ::c_int = 272; pub const SOL_PPPOL2TP: ::c_int = 273; pub const SOL_PNPIPE: ::c_int = 275; pub const SOL_RDS: ::c_int = 276; pub const SOL_IUCV: ::c_int = 277; pub const SOL_CAIF: ::c_int = 278; pub const SOL_NFC: ::c_int = 280; pub const SOL_XDP: ::c_int = 283; pub const MSG_TRYHARD: ::c_int = 4; pub const LC_PAPER: ::c_int = 7; pub const LC_NAME: ::c_int = 8; pub const LC_ADDRESS: ::c_int = 9; pub const LC_TELEPHONE: ::c_int = 10; pub const LC_MEASUREMENT: ::c_int = 11; pub const LC_IDENTIFICATION: ::c_int = 12; pub const LC_PAPER_MASK: ::c_int = 1 << LC_PAPER; pub const LC_NAME_MASK: ::c_int = 1 << LC_NAME; pub const LC_ADDRESS_MASK: ::c_int = 1 << LC_ADDRESS; pub const LC_TELEPHONE_MASK: ::c_int = 1 << LC_TELEPHONE; pub const LC_MEASUREMENT_MASK: ::c_int = 1 << LC_MEASUREMENT; pub const LC_IDENTIFICATION_MASK: ::c_int = 1 << LC_IDENTIFICATION; pub const LC_ALL_MASK: ::c_int = ::LC_CTYPE_MASK | ::LC_NUMERIC_MASK | ::LC_TIME_MASK | ::LC_COLLATE_MASK | ::LC_MONETARY_MASK | ::LC_MESSAGES_MASK | LC_PAPER_MASK | LC_NAME_MASK | LC_ADDRESS_MASK | LC_TELEPHONE_MASK | LC_MEASUREMENT_MASK | LC_IDENTIFICATION_MASK; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_DCCP: ::c_int = 6; pub const SOCK_PACKET: ::c_int = 10; pub const AF_IB: ::c_int = 27; pub const AF_MPLS: ::c_int = 28; pub const AF_NFC: ::c_int = 39; pub const AF_VSOCK: ::c_int = 40; pub const AF_XDP: ::c_int = 44; pub const PF_IB: ::c_int = AF_IB; pub const PF_MPLS: ::c_int = AF_MPLS; pub const PF_NFC: ::c_int = AF_NFC; pub const PF_VSOCK: ::c_int = AF_VSOCK; pub const PF_XDP: ::c_int = AF_XDP; pub const SIGEV_THREAD_ID: ::c_int = 4; pub const BUFSIZ: ::c_uint = 8192; pub const TMP_MAX: ::c_uint = 238328; pub const FOPEN_MAX: ::c_uint = 16; pub const FILENAME_MAX: ::c_uint = 4096; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const _SC_EQUIV_CLASS_MAX: ::c_int = 41; pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 45; pub const _SC_PII: ::c_int = 53; pub const _SC_PII_XTI: ::c_int = 54; pub const _SC_PII_SOCKET: ::c_int = 55; pub const _SC_PII_INTERNET: ::c_int = 56; pub const _SC_PII_OSI: ::c_int = 57; pub const _SC_POLL: ::c_int = 58; pub const _SC_SELECT: ::c_int = 59; pub const _SC_PII_INTERNET_STREAM: ::c_int = 61; pub const _SC_PII_INTERNET_DGRAM: ::c_int = 62; pub const _SC_PII_OSI_COTS: ::c_int = 63; pub const _SC_PII_OSI_CLTS: ::c_int = 64; pub const _SC_PII_OSI_M: ::c_int = 65; pub const _SC_T_IOV_MAX: ::c_int = 66; pub const _SC_2_C_VERSION: ::c_int = 96; pub const _SC_CHAR_BIT: ::c_int = 101; pub const _SC_CHAR_MAX: ::c_int = 102; pub const _SC_CHAR_MIN: ::c_int = 103; pub const _SC_INT_MAX: ::c_int = 104; pub const _SC_INT_MIN: ::c_int = 105; pub const _SC_LONG_BIT: ::c_int = 106; pub const _SC_WORD_BIT: ::c_int = 107; pub const _SC_MB_LEN_MAX: ::c_int = 108; pub const _SC_SSIZE_MAX: ::c_int = 110; pub const _SC_SCHAR_MAX: ::c_int = 111; pub const _SC_SCHAR_MIN: ::c_int = 112; pub const _SC_SHRT_MAX: ::c_int = 113; pub const _SC_SHRT_MIN: ::c_int = 114; pub const _SC_UCHAR_MAX: ::c_int = 115; pub const _SC_UINT_MAX: ::c_int = 116; pub const _SC_ULONG_MAX: ::c_int = 117; pub const _SC_USHRT_MAX: ::c_int = 118; pub const _SC_NL_ARGMAX: ::c_int = 119; pub const _SC_NL_LANGMAX: ::c_int = 120; pub const _SC_NL_MSGMAX: ::c_int = 121; pub const _SC_NL_NMAX: ::c_int = 122; pub const _SC_NL_SETMAX: ::c_int = 123; pub const _SC_NL_TEXTMAX: ::c_int = 124; pub const _SC_BASE: ::c_int = 134; pub const _SC_C_LANG_SUPPORT: ::c_int = 135; pub const _SC_C_LANG_SUPPORT_R: ::c_int = 136; pub const _SC_DEVICE_IO: ::c_int = 140; pub const _SC_DEVICE_SPECIFIC: ::c_int = 141; pub const _SC_DEVICE_SPECIFIC_R: ::c_int = 142; pub const _SC_FD_MGMT: ::c_int = 143; pub const _SC_FIFO: ::c_int = 144; pub const _SC_PIPE: ::c_int = 145; pub const _SC_FILE_ATTRIBUTES: ::c_int = 146; pub const _SC_FILE_LOCKING: ::c_int = 147; pub const _SC_FILE_SYSTEM: ::c_int = 148; pub const _SC_MULTI_PROCESS: ::c_int = 150; pub const _SC_SINGLE_PROCESS: ::c_int = 151; pub const _SC_NETWORKING: ::c_int = 152; pub const _SC_REGEX_VERSION: ::c_int = 156; pub const _SC_SIGNALS: ::c_int = 158; pub const _SC_SYSTEM_DATABASE: ::c_int = 162; pub const _SC_SYSTEM_DATABASE_R: ::c_int = 163; pub const _SC_USER_GROUPS: ::c_int = 166; pub const _SC_USER_GROUPS_R: ::c_int = 167; pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 185; pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 186; pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 187; pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 188; pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 189; pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 190; pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 191; pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 192; pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 193; pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 194; pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 195; pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 196; pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 197; pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 198; pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 199; pub const O_ACCMODE: ::c_int = 3; pub const ST_RELATIME: ::c_ulong = 4096; pub const NI_MAXHOST: ::socklen_t = 1025; // Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the // following are only available on newer Linux versions than the versions // currently used in CI in some configurations, so we define them here. cfg_if! { if #[cfg(not(target_arch = "s390x"))] { pub const BINDERFS_SUPER_MAGIC: ::c_long = 0x6c6f6f70; pub const XFS_SUPER_MAGIC: ::c_long = 0x58465342; } else if #[cfg(target_arch = "s390x")] { pub const BINDERFS_SUPER_MAGIC: ::c_uint = 0x6c6f6f70; pub const XFS_SUPER_MAGIC: ::c_uint = 0x58465342; } } pub const CPU_SETSIZE: ::c_int = 0x400; pub const PTRACE_TRACEME: ::c_uint = 0; pub const PTRACE_PEEKTEXT: ::c_uint = 1; pub const PTRACE_PEEKDATA: ::c_uint = 2; pub const PTRACE_PEEKUSER: ::c_uint = 3; pub const PTRACE_POKETEXT: ::c_uint = 4; pub const PTRACE_POKEDATA: ::c_uint = 5; pub const PTRACE_POKEUSER: ::c_uint = 6; pub const PTRACE_CONT: ::c_uint = 7; pub const PTRACE_KILL: ::c_uint = 8; pub const PTRACE_SINGLESTEP: ::c_uint = 9; pub const PTRACE_ATTACH: ::c_uint = 16; pub const PTRACE_SYSCALL: ::c_uint = 24; pub const PTRACE_SETOPTIONS: ::c_uint = 0x4200; pub const PTRACE_GETEVENTMSG: ::c_uint = 0x4201; pub const PTRACE_GETSIGINFO: ::c_uint = 0x4202; pub const PTRACE_SETSIGINFO: ::c_uint = 0x4203; pub const PTRACE_GETREGSET: ::c_uint = 0x4204; pub const PTRACE_SETREGSET: ::c_uint = 0x4205; pub const PTRACE_SEIZE: ::c_uint = 0x4206; pub const PTRACE_INTERRUPT: ::c_uint = 0x4207; pub const PTRACE_LISTEN: ::c_uint = 0x4208; pub const PTRACE_PEEKSIGINFO: ::c_uint = 0x4209; pub const PTRACE_GETSIGMASK: ::c_uint = 0x420a; pub const PTRACE_SETSIGMASK: ::c_uint = 0x420b; pub const PTRACE_GET_SYSCALL_INFO: ::c_uint = 0x420e; pub const PTRACE_SYSCALL_INFO_NONE: ::__u8 = 0; pub const PTRACE_SYSCALL_INFO_ENTRY: ::__u8 = 1; pub const PTRACE_SYSCALL_INFO_EXIT: ::__u8 = 2; pub const PTRACE_SYSCALL_INFO_SECCOMP: ::__u8 = 3; // linux/fs.h // Flags for preadv2/pwritev2 pub const RWF_HIPRI: ::c_int = 0x00000001; pub const RWF_DSYNC: ::c_int = 0x00000002; pub const RWF_SYNC: ::c_int = 0x00000004; pub const RWF_NOWAIT: ::c_int = 0x00000008; pub const RWF_APPEND: ::c_int = 0x00000010; // linux/rtnetlink.h pub const TCA_PAD: ::c_ushort = 9; pub const TCA_DUMP_INVISIBLE: ::c_ushort = 10; pub const TCA_CHAIN: ::c_ushort = 11; pub const TCA_HW_OFFLOAD: ::c_ushort = 12; pub const RTM_DELNETCONF: u16 = 81; pub const RTM_NEWSTATS: u16 = 92; pub const RTM_GETSTATS: u16 = 94; pub const RTM_NEWCACHEREPORT: u16 = 96; pub const RTM_F_LOOKUP_TABLE: ::c_uint = 0x1000; pub const RTM_F_FIB_MATCH: ::c_uint = 0x2000; pub const RTA_VIA: ::c_ushort = 18; pub const RTA_NEWDST: ::c_ushort = 19; pub const RTA_PREF: ::c_ushort = 20; pub const RTA_ENCAP_TYPE: ::c_ushort = 21; pub const RTA_ENCAP: ::c_ushort = 22; pub const RTA_EXPIRES: ::c_ushort = 23; pub const RTA_PAD: ::c_ushort = 24; pub const RTA_UID: ::c_ushort = 25; pub const RTA_TTL_PROPAGATE: ::c_ushort = 26; // linux/neighbor.h pub const NTF_EXT_LEARNED: u8 = 0x10; pub const NTF_OFFLOADED: u8 = 0x20; pub const NDA_MASTER: ::c_ushort = 9; pub const NDA_LINK_NETNSID: ::c_ushort = 10; pub const NDA_SRC_VNI: ::c_ushort = 11; // linux/personality.h pub const UNAME26: ::c_int = 0x0020000; pub const FDPIC_FUNCPTRS: ::c_int = 0x0080000; // linux/if_addr.h pub const IFA_FLAGS: ::c_ushort = 8; pub const IFA_F_MANAGETEMPADDR: u32 = 0x100; pub const IFA_F_NOPREFIXROUTE: u32 = 0x200; pub const IFA_F_MCAUTOJOIN: u32 = 0x400; pub const IFA_F_STABLE_PRIVACY: u32 = 0x800; pub const MAX_LINKS: ::c_int = 32; pub const GENL_UNS_ADMIN_PERM: ::c_int = 0x10; pub const GENL_ID_VFS_DQUOT: ::c_int = ::NLMSG_MIN_TYPE + 1; pub const GENL_ID_PMCRAID: ::c_int = ::NLMSG_MIN_TYPE + 2; // linux/if_xdp.h pub const XDP_SHARED_UMEM: ::__u16 = 1 << 0; pub const XDP_COPY: ::__u16 = 1 << 1; pub const XDP_ZEROCOPY: ::__u16 = 1 << 2; pub const XDP_USE_NEED_WAKEUP: ::__u16 = 1 << 3; pub const XDP_USE_SG: ::__u16 = 1 << 4; pub const XDP_UMEM_UNALIGNED_CHUNK_FLAG: ::__u32 = 1 << 0; pub const XDP_RING_NEED_WAKEUP: ::__u32 = 1 << 0; pub const XDP_MMAP_OFFSETS: ::c_int = 1; pub const XDP_RX_RING: ::c_int = 2; pub const XDP_TX_RING: ::c_int = 3; pub const XDP_UMEM_REG: ::c_int = 4; pub const XDP_UMEM_FILL_RING: ::c_int = 5; pub const XDP_UMEM_COMPLETION_RING: ::c_int = 6; pub const XDP_STATISTICS: ::c_int = 7; pub const XDP_OPTIONS: ::c_int = 8; pub const XDP_OPTIONS_ZEROCOPY: ::__u32 = 1 << 0; pub const XDP_PGOFF_RX_RING: ::off_t = 0; pub const XDP_PGOFF_TX_RING: ::off_t = 0x80000000; pub const XDP_UMEM_PGOFF_FILL_RING: ::c_ulonglong = 0x100000000; pub const XDP_UMEM_PGOFF_COMPLETION_RING: ::c_ulonglong = 0x180000000; pub const XSK_UNALIGNED_BUF_OFFSET_SHIFT: ::c_int = 48; pub const XSK_UNALIGNED_BUF_ADDR_MASK: ::c_ulonglong = (1 << XSK_UNALIGNED_BUF_OFFSET_SHIFT) - 1; pub const XDP_PKT_CONTD: ::__u32 = 1 << 0; // elf.h pub const NT_PRSTATUS: ::c_int = 1; pub const NT_PRFPREG: ::c_int = 2; pub const NT_FPREGSET: ::c_int = 2; pub const NT_PRPSINFO: ::c_int = 3; pub const NT_PRXREG: ::c_int = 4; pub const NT_TASKSTRUCT: ::c_int = 4; pub const NT_PLATFORM: ::c_int = 5; pub const NT_AUXV: ::c_int = 6; pub const NT_GWINDOWS: ::c_int = 7; pub const NT_ASRS: ::c_int = 8; pub const NT_PSTATUS: ::c_int = 10; pub const NT_PSINFO: ::c_int = 13; pub const NT_PRCRED: ::c_int = 14; pub const NT_UTSNAME: ::c_int = 15; pub const NT_LWPSTATUS: ::c_int = 16; pub const NT_LWPSINFO: ::c_int = 17; pub const NT_PRFPXREG: ::c_int = 20; pub const ELFOSABI_ARM_AEABI: u8 = 64; // linux/sched.h pub const CLONE_NEWTIME: ::c_int = 0x80; pub const CLONE_CLEAR_SIGHAND: ::c_int = 0x100000000; pub const CLONE_INTO_CGROUP: ::c_int = 0x200000000; // linux/keyctl.h pub const KEYCTL_DH_COMPUTE: u32 = 23; pub const KEYCTL_PKEY_QUERY: u32 = 24; pub const KEYCTL_PKEY_ENCRYPT: u32 = 25; pub const KEYCTL_PKEY_DECRYPT: u32 = 26; pub const KEYCTL_PKEY_SIGN: u32 = 27; pub const KEYCTL_PKEY_VERIFY: u32 = 28; pub const KEYCTL_RESTRICT_KEYRING: u32 = 29; pub const KEYCTL_SUPPORTS_ENCRYPT: u32 = 0x01; pub const KEYCTL_SUPPORTS_DECRYPT: u32 = 0x02; pub const KEYCTL_SUPPORTS_SIGN: u32 = 0x04; pub const KEYCTL_SUPPORTS_VERIFY: u32 = 0x08; cfg_if! { if #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6")))] { pub const KEYCTL_MOVE: u32 = 30; pub const KEYCTL_CAPABILITIES: u32 = 31; pub const KEYCTL_CAPS0_CAPABILITIES: u32 = 0x01; pub const KEYCTL_CAPS0_PERSISTENT_KEYRINGS: u32 = 0x02; pub const KEYCTL_CAPS0_DIFFIE_HELLMAN: u32 = 0x04; pub const KEYCTL_CAPS0_PUBLIC_KEY: u32 = 0x08; pub const KEYCTL_CAPS0_BIG_KEY: u32 = 0x10; pub const KEYCTL_CAPS0_INVALIDATE: u32 = 0x20; pub const KEYCTL_CAPS0_RESTRICT_KEYRING: u32 = 0x40; pub const KEYCTL_CAPS0_MOVE: u32 = 0x80; pub const KEYCTL_CAPS1_NS_KEYRING_NAME: u32 = 0x01; pub const KEYCTL_CAPS1_NS_KEY_TAG: u32 = 0x02; } } pub const M_MXFAST: ::c_int = 1; pub const M_NLBLKS: ::c_int = 2; pub const M_GRAIN: ::c_int = 3; pub const M_KEEP: ::c_int = 4; pub const M_TRIM_THRESHOLD: ::c_int = -1; pub const M_TOP_PAD: ::c_int = -2; pub const M_MMAP_THRESHOLD: ::c_int = -3; pub const M_MMAP_MAX: ::c_int = -4; pub const M_CHECK_ACTION: ::c_int = -5; pub const M_PERTURB: ::c_int = -6; pub const M_ARENA_TEST: ::c_int = -7; pub const M_ARENA_MAX: ::c_int = -8; pub const AT_STATX_SYNC_TYPE: ::c_int = 0x6000; pub const AT_STATX_SYNC_AS_STAT: ::c_int = 0x0000; pub const AT_STATX_FORCE_SYNC: ::c_int = 0x2000; pub const AT_STATX_DONT_SYNC: ::c_int = 0x4000; pub const STATX_TYPE: ::c_uint = 0x0001; pub const STATX_MODE: ::c_uint = 0x0002; pub const STATX_NLINK: ::c_uint = 0x0004; pub const STATX_UID: ::c_uint = 0x0008; pub const STATX_GID: ::c_uint = 0x0010; pub const STATX_ATIME: ::c_uint = 0x0020; pub const STATX_MTIME: ::c_uint = 0x0040; pub const STATX_CTIME: ::c_uint = 0x0080; pub const STATX_INO: ::c_uint = 0x0100; pub const STATX_SIZE: ::c_uint = 0x0200; pub const STATX_BLOCKS: ::c_uint = 0x0400; pub const STATX_BASIC_STATS: ::c_uint = 0x07ff; pub const STATX_BTIME: ::c_uint = 0x0800; pub const STATX_MNT_ID: ::c_uint = 0x1000; pub const STATX_DIOALIGN: ::c_uint = 0x2000; pub const STATX_ALL: ::c_uint = 0x0fff; pub const STATX__RESERVED: ::c_int = 0x80000000; pub const STATX_ATTR_COMPRESSED: ::c_int = 0x0004; pub const STATX_ATTR_IMMUTABLE: ::c_int = 0x0010; pub const STATX_ATTR_APPEND: ::c_int = 0x0020; pub const STATX_ATTR_NODUMP: ::c_int = 0x0040; pub const STATX_ATTR_ENCRYPTED: ::c_int = 0x0800; pub const STATX_ATTR_AUTOMOUNT: ::c_int = 0x1000; pub const STATX_ATTR_MOUNT_ROOT: ::c_int = 0x2000; pub const STATX_ATTR_VERITY: ::c_int = 0x00100000; pub const STATX_ATTR_DAX: ::c_int = 0x00200000; pub const SOMAXCONN: ::c_int = 4096; // linux/mount.h pub const MOVE_MOUNT_F_SYMLINKS: ::c_uint = 0x00000001; pub const MOVE_MOUNT_F_AUTOMOUNTS: ::c_uint = 0x00000002; pub const MOVE_MOUNT_F_EMPTY_PATH: ::c_uint = 0x00000004; pub const MOVE_MOUNT_T_SYMLINKS: ::c_uint = 0x00000010; pub const MOVE_MOUNT_T_AUTOMOUNTS: ::c_uint = 0x00000020; pub const MOVE_MOUNT_T_EMPTY_PATH: ::c_uint = 0x00000040; pub const MOVE_MOUNT_SET_GROUP: ::c_uint = 0x00000100; pub const MOVE_MOUNT_BENEATH: ::c_uint = 0x00000200; // sys/timex.h pub const ADJ_OFFSET: ::c_uint = 0x0001; pub const ADJ_FREQUENCY: ::c_uint = 0x0002; pub const ADJ_MAXERROR: ::c_uint = 0x0004; pub const ADJ_ESTERROR: ::c_uint = 0x0008; pub const ADJ_STATUS: ::c_uint = 0x0010; pub const ADJ_TIMECONST: ::c_uint = 0x0020; pub const ADJ_TAI: ::c_uint = 0x0080; pub const ADJ_SETOFFSET: ::c_uint = 0x0100; pub const ADJ_MICRO: ::c_uint = 0x1000; pub const ADJ_NANO: ::c_uint = 0x2000; pub const ADJ_TICK: ::c_uint = 0x4000; pub const ADJ_OFFSET_SINGLESHOT: ::c_uint = 0x8001; pub const ADJ_OFFSET_SS_READ: ::c_uint = 0xa001; pub const MOD_OFFSET: ::c_uint = ADJ_OFFSET; pub const MOD_FREQUENCY: ::c_uint = ADJ_FREQUENCY; pub const MOD_MAXERROR: ::c_uint = ADJ_MAXERROR; pub const MOD_ESTERROR: ::c_uint = ADJ_ESTERROR; pub const MOD_STATUS: ::c_uint = ADJ_STATUS; pub const MOD_TIMECONST: ::c_uint = ADJ_TIMECONST; pub const MOD_CLKB: ::c_uint = ADJ_TICK; pub const MOD_CLKA: ::c_uint = ADJ_OFFSET_SINGLESHOT; pub const MOD_TAI: ::c_uint = ADJ_TAI; pub const MOD_MICRO: ::c_uint = ADJ_MICRO; pub const MOD_NANO: ::c_uint = ADJ_NANO; pub const STA_PLL: ::c_int = 0x0001; pub const STA_PPSFREQ: ::c_int = 0x0002; pub const STA_PPSTIME: ::c_int = 0x0004; pub const STA_FLL: ::c_int = 0x0008; pub const STA_INS: ::c_int = 0x0010; pub const STA_DEL: ::c_int = 0x0020; pub const STA_UNSYNC: ::c_int = 0x0040; pub const STA_FREQHOLD: ::c_int = 0x0080; pub const STA_PPSSIGNAL: ::c_int = 0x0100; pub const STA_PPSJITTER: ::c_int = 0x0200; pub const STA_PPSWANDER: ::c_int = 0x0400; pub const STA_PPSERROR: ::c_int = 0x0800; pub const STA_CLOCKERR: ::c_int = 0x1000; pub const STA_NANO: ::c_int = 0x2000; pub const STA_MODE: ::c_int = 0x4000; pub const STA_CLK: ::c_int = 0x8000; pub const STA_RONLY: ::c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const NTP_API: ::c_int = 4; pub const TIME_OK: ::c_int = 0; pub const TIME_INS: ::c_int = 1; pub const TIME_DEL: ::c_int = 2; pub const TIME_OOP: ::c_int = 3; pub const TIME_WAIT: ::c_int = 4; pub const TIME_ERROR: ::c_int = 5; pub const TIME_BAD: ::c_int = TIME_ERROR; pub const MAXTC: ::c_long = 6; // Portable GLOB_* flags are defined at the `linux_like` level. // The following are GNU extensions. pub const GLOB_PERIOD: ::c_int = 1 << 7; pub const GLOB_ALTDIRFUNC: ::c_int = 1 << 9; pub const GLOB_BRACE: ::c_int = 1 << 10; pub const GLOB_NOMAGIC: ::c_int = 1 << 11; pub const GLOB_TILDE: ::c_int = 1 << 12; pub const GLOB_ONLYDIR: ::c_int = 1 << 13; pub const GLOB_TILDE_CHECK: ::c_int = 1 << 14; pub const MADV_COLLAPSE: ::c_int = 25; cfg_if! { if #[cfg(any( target_arch = "arm", target_arch = "x86", target_arch = "x86_64", target_arch = "s390x", target_arch = "riscv64", target_arch = "riscv32" ))] { pub const PTHREAD_STACK_MIN: ::size_t = 16384; } else if #[cfg(any( target_arch = "sparc", target_arch = "sparc64" ))] { pub const PTHREAD_STACK_MIN: ::size_t = 0x6000; } else { pub const PTHREAD_STACK_MIN: ::size_t = 131072; } } pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 3; pub const REG_STARTEND: ::c_int = 4; pub const REG_EEND: ::c_int = 14; pub const REG_ESIZE: ::c_int = 15; pub const REG_ERPAREN: ::c_int = 16; extern "C" { pub fn fgetspent_r( fp: *mut ::FILE, spbuf: *mut ::spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut ::spwd, ) -> ::c_int; pub fn sgetspent_r( s: *const ::c_char, spbuf: *mut ::spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut ::spwd, ) -> ::c_int; pub fn getspent_r( spbuf: *mut ::spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut ::spwd, ) -> ::c_int; pub fn qsort_r( base: *mut ::c_void, num: ::size_t, size: ::size_t, compar: ::Option< unsafe extern "C" fn(*const ::c_void, *const ::c_void, *mut ::c_void) -> ::c_int, >, arg: *mut ::c_void, ); pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, timeout: *mut ::timespec, ) -> ::c_int; pub fn getrlimit64(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit64) -> ::c_int; pub fn setrlimit64(resource: ::__rlimit_resource_t, rlim: *const ::rlimit64) -> ::c_int; pub fn getrlimit(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::__rlimit_resource_t, rlim: *const ::rlimit) -> ::c_int; pub fn prlimit( pid: ::pid_t, resource: ::__rlimit_resource_t, new_limit: *const ::rlimit, old_limit: *mut ::rlimit, ) -> ::c_int; pub fn prlimit64( pid: ::pid_t, resource: ::__rlimit_resource_t, new_limit: *const ::rlimit64, old_limit: *mut ::rlimit64, ) -> ::c_int; pub fn utmpname(file: *const ::c_char) -> ::c_int; pub fn utmpxname(file: *const ::c_char) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn getpt() -> ::c_int; pub fn mallopt(param: ::c_int, value: ::c_int) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn statx( dirfd: ::c_int, pathname: *const c_char, flags: ::c_int, mask: ::c_uint, statxbuf: *mut statx, ) -> ::c_int; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn getauxval(type_: ::c_ulong) -> ::c_ulong; pub fn adjtimex(buf: *mut timex) -> ::c_int; pub fn ntp_adjtime(buf: *mut timex) -> ::c_int; #[link_name = "ntp_gettimex"] pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int; pub fn clock_adjtime(clk_id: ::clockid_t, buf: *mut ::timex) -> ::c_int; pub fn fanotify_mark( fd: ::c_int, flags: ::c_uint, mask: u64, dirfd: ::c_int, path: *const ::c_char, ) -> ::c_int; pub fn preadv2( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t, flags: ::c_int, ) -> ::ssize_t; pub fn pwritev2( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t, flags: ::c_int, ) -> ::ssize_t; pub fn preadv64v2( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, flags: ::c_int, ) -> ::ssize_t; pub fn pwritev64v2( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, flags: ::c_int, ) -> ::ssize_t; pub fn renameat2( olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, flags: ::c_uint, ) -> ::c_int; // Added in `glibc` 2.25 pub fn explicit_bzero(s: *mut ::c_void, len: ::size_t); // Added in `glibc` 2.29 pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn ctermid(s: *mut ::c_char) -> *mut ::c_char; pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; pub fn backtrace(buf: *mut *mut ::c_void, sz: ::c_int) -> ::c_int; pub fn glob64( pattern: *const ::c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut glob64_t, ) -> ::c_int; pub fn globfree64(pglob: *mut glob64_t); pub fn ptrace(request: ::c_uint, ...) -> ::c_long; pub fn pthread_attr_getaffinity_np( attr: *const ::pthread_attr_t, cpusetsize: ::size_t, cpuset: *mut ::cpu_set_t, ) -> ::c_int; pub fn pthread_attr_setaffinity_np( attr: *mut ::pthread_attr_t, cpusetsize: ::size_t, cpuset: *const ::cpu_set_t, ) -> ::c_int; pub fn getpriority(which: ::__priority_which_t, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::__priority_which_t, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn pthread_rwlockattr_getkind_np( attr: *const ::pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setkind_np( attr: *mut ::pthread_rwlockattr_t, val: ::c_int, ) -> ::c_int; pub fn pthread_sigqueue(thread: ::pthread_t, sig: ::c_int, value: ::sigval) -> ::c_int; pub fn mallinfo() -> ::mallinfo; pub fn mallinfo2() -> ::mallinfo2; pub fn malloc_info(options: ::c_int, stream: *mut ::FILE) -> ::c_int; pub fn malloc_usable_size(ptr: *mut ::c_void) -> ::size_t; pub fn getpwent_r( pwd: *mut ::passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::passwd, ) -> ::c_int; pub fn getgrent_r( grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn fgetpwent_r( stream: *mut ::FILE, pwd: *mut ::passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::passwd, ) -> ::c_int; pub fn fgetgrent_r( stream: *mut ::FILE, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn putpwent(p: *const ::passwd, stream: *mut ::FILE) -> ::c_int; pub fn putgrent(grp: *const ::group, stream: *mut ::FILE) -> ::c_int; pub fn sethostid(hostid: ::c_long) -> ::c_int; pub fn memfd_create(name: *const ::c_char, flags: ::c_uint) -> ::c_int; pub fn mlock2(addr: *const ::c_void, len: ::size_t, flags: ::c_uint) -> ::c_int; pub fn euidaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int; pub fn eaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int; pub fn asctime_r(tm: *const ::tm, buf: *mut ::c_char) -> *mut ::c_char; pub fn ctime_r(timep: *const time_t, buf: *mut ::c_char) -> *mut ::c_char; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; /// POSIX version of `basename(3)`, defined in `libgen.h`. #[link_name = "__xpg_basename"] pub fn posix_basename(path: *mut ::c_char) -> *mut ::c_char; /// GNU version of `basename(3)`, defined in `string.h`. #[link_name = "basename"] pub fn gnu_basename(path: *const ::c_char) -> *mut ::c_char; pub fn dlmopen(lmid: Lmid_t, filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; pub fn dlinfo(handle: *mut ::c_void, request: ::c_int, info: *mut ::c_void) -> ::c_int; pub fn dladdr1( addr: *const ::c_void, info: *mut ::Dl_info, extra_info: *mut *mut ::c_void, flags: ::c_int, ) -> ::c_int; pub fn malloc_trim(__pad: ::size_t) -> ::c_int; pub fn gnu_get_libc_release() -> *const ::c_char; pub fn gnu_get_libc_version() -> *const ::c_char; // posix/spawn.h // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addchdir_np( actions: *mut ::posix_spawn_file_actions_t, path: *const ::c_char, ) -> ::c_int; // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addfchdir_np( actions: *mut ::posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; // Added in `glibc` 2.34 pub fn posix_spawn_file_actions_addclosefrom_np( actions: *mut ::posix_spawn_file_actions_t, from: ::c_int, ) -> ::c_int; // Added in `glibc` 2.35 pub fn posix_spawn_file_actions_addtcsetpgrp_np( actions: *mut ::posix_spawn_file_actions_t, tcfd: ::c_int, ) -> ::c_int; // mntent.h pub fn getmntent_r( stream: *mut ::FILE, mntbuf: *mut ::mntent, buf: *mut ::c_char, buflen: ::c_int, ) -> *mut ::mntent; pub fn execveat( dirfd: ::c_int, pathname: *const ::c_char, argv: *const *mut c_char, envp: *const *mut c_char, flags: ::c_int, ) -> ::c_int; // Added in `glibc` 2.34 pub fn close_range(first: ::c_uint, last: ::c_uint, flags: ::c_int) -> ::c_int; } cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "mips", target_arch = "mips32r6", target_arch = "powerpc", target_arch = "sparc", target_arch = "riscv32"))] { mod b32; pub use self::b32::*; } else if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "riscv64", target_arch = "loongarch64"))] { mod b64; pub use self::b64::*; } else { // Unknown target_arch } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } else { mod no_align; pub use self::no_align::*; } } libc/src/unix/linux_like/linux/gnu/b64/0000775000175000017500000000000014661133735020714 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/powerpc64/0000775000175000017500000000000014661133735022545 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs0000644000175000017500000010265514661133735023701 0ustar jamespagejamespage//! PowerPC64-specific definitions for 64-bit linux-like values use pthread_mutex_t; pub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = i64; pub type suseconds_t = i64; pub type __u64 = ::c_ulong; pub type __s64 = ::c_long; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: ::c_int, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __reserved: [::c_long; 3], } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_attr_t { __size: [u64; 7] } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: u32, __pad1: u32, __unused1: u64, __unused2: ::c_ulong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_segsz: ::size_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } } pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const VEOF: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const PTRACE_DETACH: ::c_uint = 17; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_CLOEXEC: ::c_int = 0x80000; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; align_const! { #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_DIRECT: ::c_int = 0x20000; pub const MAP_LOCKED: ::c_int = 0x00080; pub const MAP_NORESERVE: ::c_int = 0x00040; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 58; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const MCL_CURRENT: ::c_int = 0x2000; pub const MCL_FUTURE: ::c_int = 0x4000; pub const MCL_ONFAULT: ::c_int = 0x8000; pub const SIGSTKSZ: ::size_t = 0x4000; pub const MINSIGSTKSZ: ::size_t = 4096; pub const CBAUD: ::tcflag_t = 0xff; pub const TAB1: ::tcflag_t = 0x400; pub const TAB2: ::tcflag_t = 0x800; pub const TAB3: ::tcflag_t = 0xc00; pub const CR1: ::tcflag_t = 0x1000; pub const CR2: ::tcflag_t = 0x2000; pub const CR3: ::tcflag_t = 0x3000; pub const FF1: ::tcflag_t = 0x4000; pub const BS1: ::tcflag_t = 0x8000; pub const VT1: ::tcflag_t = 0x10000; pub const VWERASE: usize = 0xa; pub const VREPRINT: usize = 0xb; pub const VSUSP: usize = 0xc; pub const VSTART: usize = 0xd; pub const VSTOP: usize = 0xe; pub const VDISCARD: usize = 0x10; pub const VTIME: usize = 0x7; pub const IXON: ::tcflag_t = 0x200; pub const IXOFF: ::tcflag_t = 0x400; pub const ONLCR: ::tcflag_t = 0x2; pub const CSIZE: ::tcflag_t = 0x300; pub const CS6: ::tcflag_t = 0x100; pub const CS7: ::tcflag_t = 0x200; pub const CS8: ::tcflag_t = 0x300; pub const CSTOPB: ::tcflag_t = 0x400; pub const CREAD: ::tcflag_t = 0x800; pub const PARENB: ::tcflag_t = 0x1000; pub const PARODD: ::tcflag_t = 0x2000; pub const HUPCL: ::tcflag_t = 0x4000; pub const CLOCAL: ::tcflag_t = 0x8000; pub const ECHOKE: ::tcflag_t = 0x1; pub const ECHOE: ::tcflag_t = 0x2; pub const ECHOK: ::tcflag_t = 0x4; pub const ECHONL: ::tcflag_t = 0x10; pub const ECHOPRT: ::tcflag_t = 0x20; pub const ECHOCTL: ::tcflag_t = 0x40; pub const ISIG: ::tcflag_t = 0x80; pub const ICANON: ::tcflag_t = 0x100; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; pub const VSWTC: usize = 9; pub const OLCUC: ::tcflag_t = 0o000004; pub const NLDLY: ::tcflag_t = 0o001400; pub const CRDLY: ::tcflag_t = 0o030000; pub const TABDLY: ::tcflag_t = 0o006000; pub const BSDLY: ::tcflag_t = 0o100000; pub const FFDLY: ::tcflag_t = 0o040000; pub const VTDLY: ::tcflag_t = 0o200000; pub const XTABS: ::tcflag_t = 0o006000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const CBAUDEX: ::speed_t = 0o000020; pub const B57600: ::speed_t = 0o0020; pub const B115200: ::speed_t = 0o0021; pub const B230400: ::speed_t = 0o0022; pub const B460800: ::speed_t = 0o0023; pub const B500000: ::speed_t = 0o0024; pub const B576000: ::speed_t = 0o0025; pub const B921600: ::speed_t = 0o0026; pub const B1000000: ::speed_t = 0o0027; pub const B1152000: ::speed_t = 0o0030; pub const B1500000: ::speed_t = 0o0031; pub const B2000000: ::speed_t = 0o0032; pub const B2500000: ::speed_t = 0o0033; pub const B3000000: ::speed_t = 0o0034; pub const B3500000: ::speed_t = 0o0035; pub const B4000000: ::speed_t = 0o0036; pub const VEOL: usize = 6; pub const VEOL2: usize = 8; pub const VMIN: usize = 5; pub const IEXTEN: ::tcflag_t = 0x400; pub const TOSTOP: ::tcflag_t = 0x400000; pub const FLUSHO: ::tcflag_t = 0x800000; pub const EXTPROC: ::tcflag_t = 0x10000000; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_break: ::c_long = 17; pub const SYS_oldstat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_stime: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_oldfstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_stty: ::c_long = 31; pub const SYS_gtty: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_ftime: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_prof: ::c_long = 44; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_lock: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_mpx: ::c_long = 56; pub const SYS_setpgid: ::c_long = 57; pub const SYS_ulimit: ::c_long = 58; pub const SYS_oldolduname: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_oldlstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_profil: ::c_long = 98; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_ioperm: ::c_long = 101; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_olduname: ::c_long = 109; pub const SYS_iopl: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_vm86: ::c_long = 113; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_modify_ldt: ::c_long = 123; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; /* Syscall for Andrew File System */ pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_query_module: ::c_long = 166; pub const SYS_poll: ::c_long = 167; pub const SYS_nfsservctl: ::c_long = 168; pub const SYS_setresgid: ::c_long = 169; pub const SYS_getresgid: ::c_long = 170; pub const SYS_prctl: ::c_long = 171; pub const SYS_rt_sigreturn: ::c_long = 172; pub const SYS_rt_sigaction: ::c_long = 173; pub const SYS_rt_sigprocmask: ::c_long = 174; pub const SYS_rt_sigpending: ::c_long = 175; pub const SYS_rt_sigtimedwait: ::c_long = 176; pub const SYS_rt_sigqueueinfo: ::c_long = 177; pub const SYS_rt_sigsuspend: ::c_long = 178; pub const SYS_pread64: ::c_long = 179; pub const SYS_pwrite64: ::c_long = 180; pub const SYS_chown: ::c_long = 181; pub const SYS_getcwd: ::c_long = 182; pub const SYS_capget: ::c_long = 183; pub const SYS_capset: ::c_long = 184; pub const SYS_sigaltstack: ::c_long = 185; pub const SYS_sendfile: ::c_long = 186; pub const SYS_getpmsg: ::c_long = 187; /* some people actually want streams */ pub const SYS_putpmsg: ::c_long = 188; /* some people actually want streams */ pub const SYS_vfork: ::c_long = 189; pub const SYS_ugetrlimit: ::c_long = 190; /* SuS compliant getrlimit */ pub const SYS_readahead: ::c_long = 191; pub const SYS_pciconfig_read: ::c_long = 198; pub const SYS_pciconfig_write: ::c_long = 199; pub const SYS_pciconfig_iobase: ::c_long = 200; pub const SYS_multiplexer: ::c_long = 201; pub const SYS_getdents64: ::c_long = 202; pub const SYS_pivot_root: ::c_long = 203; pub const SYS_madvise: ::c_long = 205; pub const SYS_mincore: ::c_long = 206; pub const SYS_gettid: ::c_long = 207; pub const SYS_tkill: ::c_long = 208; pub const SYS_setxattr: ::c_long = 209; pub const SYS_lsetxattr: ::c_long = 210; pub const SYS_fsetxattr: ::c_long = 211; pub const SYS_getxattr: ::c_long = 212; pub const SYS_lgetxattr: ::c_long = 213; pub const SYS_fgetxattr: ::c_long = 214; pub const SYS_listxattr: ::c_long = 215; pub const SYS_llistxattr: ::c_long = 216; pub const SYS_flistxattr: ::c_long = 217; pub const SYS_removexattr: ::c_long = 218; pub const SYS_lremovexattr: ::c_long = 219; pub const SYS_fremovexattr: ::c_long = 220; pub const SYS_futex: ::c_long = 221; pub const SYS_sched_setaffinity: ::c_long = 222; pub const SYS_sched_getaffinity: ::c_long = 223; pub const SYS_tuxcall: ::c_long = 225; pub const SYS_io_setup: ::c_long = 227; pub const SYS_io_destroy: ::c_long = 228; pub const SYS_io_getevents: ::c_long = 229; pub const SYS_io_submit: ::c_long = 230; pub const SYS_io_cancel: ::c_long = 231; pub const SYS_set_tid_address: ::c_long = 232; pub const SYS_exit_group: ::c_long = 234; pub const SYS_lookup_dcookie: ::c_long = 235; pub const SYS_epoll_create: ::c_long = 236; pub const SYS_epoll_ctl: ::c_long = 237; pub const SYS_epoll_wait: ::c_long = 238; pub const SYS_remap_file_pages: ::c_long = 239; pub const SYS_timer_create: ::c_long = 240; pub const SYS_timer_settime: ::c_long = 241; pub const SYS_timer_gettime: ::c_long = 242; pub const SYS_timer_getoverrun: ::c_long = 243; pub const SYS_timer_delete: ::c_long = 244; pub const SYS_clock_settime: ::c_long = 245; pub const SYS_clock_gettime: ::c_long = 246; pub const SYS_clock_getres: ::c_long = 247; pub const SYS_clock_nanosleep: ::c_long = 248; pub const SYS_swapcontext: ::c_long = 249; pub const SYS_tgkill: ::c_long = 250; pub const SYS_utimes: ::c_long = 251; pub const SYS_statfs64: ::c_long = 252; pub const SYS_fstatfs64: ::c_long = 253; pub const SYS_rtas: ::c_long = 255; pub const SYS_sys_debug_setcontext: ::c_long = 256; pub const SYS_migrate_pages: ::c_long = 258; pub const SYS_mbind: ::c_long = 259; pub const SYS_get_mempolicy: ::c_long = 260; pub const SYS_set_mempolicy: ::c_long = 261; pub const SYS_mq_open: ::c_long = 262; pub const SYS_mq_unlink: ::c_long = 263; pub const SYS_mq_timedsend: ::c_long = 264; pub const SYS_mq_timedreceive: ::c_long = 265; pub const SYS_mq_notify: ::c_long = 266; pub const SYS_mq_getsetattr: ::c_long = 267; pub const SYS_kexec_load: ::c_long = 268; pub const SYS_add_key: ::c_long = 269; pub const SYS_request_key: ::c_long = 270; pub const SYS_keyctl: ::c_long = 271; pub const SYS_waitid: ::c_long = 272; pub const SYS_ioprio_set: ::c_long = 273; pub const SYS_ioprio_get: ::c_long = 274; pub const SYS_inotify_init: ::c_long = 275; pub const SYS_inotify_add_watch: ::c_long = 276; pub const SYS_inotify_rm_watch: ::c_long = 277; pub const SYS_spu_run: ::c_long = 278; pub const SYS_spu_create: ::c_long = 279; pub const SYS_pselect6: ::c_long = 280; pub const SYS_ppoll: ::c_long = 281; pub const SYS_unshare: ::c_long = 282; pub const SYS_splice: ::c_long = 283; pub const SYS_tee: ::c_long = 284; pub const SYS_vmsplice: ::c_long = 285; pub const SYS_openat: ::c_long = 286; pub const SYS_mkdirat: ::c_long = 287; pub const SYS_mknodat: ::c_long = 288; pub const SYS_fchownat: ::c_long = 289; pub const SYS_futimesat: ::c_long = 290; pub const SYS_newfstatat: ::c_long = 291; pub const SYS_unlinkat: ::c_long = 292; pub const SYS_renameat: ::c_long = 293; pub const SYS_linkat: ::c_long = 294; pub const SYS_symlinkat: ::c_long = 295; pub const SYS_readlinkat: ::c_long = 296; pub const SYS_fchmodat: ::c_long = 297; pub const SYS_faccessat: ::c_long = 298; pub const SYS_get_robust_list: ::c_long = 299; pub const SYS_set_robust_list: ::c_long = 300; pub const SYS_move_pages: ::c_long = 301; pub const SYS_getcpu: ::c_long = 302; pub const SYS_epoll_pwait: ::c_long = 303; pub const SYS_utimensat: ::c_long = 304; pub const SYS_signalfd: ::c_long = 305; pub const SYS_timerfd_create: ::c_long = 306; pub const SYS_eventfd: ::c_long = 307; pub const SYS_sync_file_range2: ::c_long = 308; pub const SYS_fallocate: ::c_long = 309; pub const SYS_subpage_prot: ::c_long = 310; pub const SYS_timerfd_settime: ::c_long = 311; pub const SYS_timerfd_gettime: ::c_long = 312; pub const SYS_signalfd4: ::c_long = 313; pub const SYS_eventfd2: ::c_long = 314; pub const SYS_epoll_create1: ::c_long = 315; pub const SYS_dup3: ::c_long = 316; pub const SYS_pipe2: ::c_long = 317; pub const SYS_inotify_init1: ::c_long = 318; pub const SYS_perf_event_open: ::c_long = 319; pub const SYS_preadv: ::c_long = 320; pub const SYS_pwritev: ::c_long = 321; pub const SYS_rt_tgsigqueueinfo: ::c_long = 322; pub const SYS_fanotify_init: ::c_long = 323; pub const SYS_fanotify_mark: ::c_long = 324; pub const SYS_prlimit64: ::c_long = 325; pub const SYS_socket: ::c_long = 326; pub const SYS_bind: ::c_long = 327; pub const SYS_connect: ::c_long = 328; pub const SYS_listen: ::c_long = 329; pub const SYS_accept: ::c_long = 330; pub const SYS_getsockname: ::c_long = 331; pub const SYS_getpeername: ::c_long = 332; pub const SYS_socketpair: ::c_long = 333; pub const SYS_send: ::c_long = 334; pub const SYS_sendto: ::c_long = 335; pub const SYS_recv: ::c_long = 336; pub const SYS_recvfrom: ::c_long = 337; pub const SYS_shutdown: ::c_long = 338; pub const SYS_setsockopt: ::c_long = 339; pub const SYS_getsockopt: ::c_long = 340; pub const SYS_sendmsg: ::c_long = 341; pub const SYS_recvmsg: ::c_long = 342; pub const SYS_recvmmsg: ::c_long = 343; pub const SYS_accept4: ::c_long = 344; pub const SYS_name_to_handle_at: ::c_long = 345; pub const SYS_open_by_handle_at: ::c_long = 346; pub const SYS_clock_adjtime: ::c_long = 347; pub const SYS_syncfs: ::c_long = 348; pub const SYS_sendmmsg: ::c_long = 349; pub const SYS_setns: ::c_long = 350; pub const SYS_process_vm_readv: ::c_long = 351; pub const SYS_process_vm_writev: ::c_long = 352; pub const SYS_finit_module: ::c_long = 353; pub const SYS_kcmp: ::c_long = 354; pub const SYS_sched_setattr: ::c_long = 355; pub const SYS_sched_getattr: ::c_long = 356; pub const SYS_renameat2: ::c_long = 357; pub const SYS_seccomp: ::c_long = 358; pub const SYS_getrandom: ::c_long = 359; pub const SYS_memfd_create: ::c_long = 360; pub const SYS_bpf: ::c_long = 361; pub const SYS_execveat: ::c_long = 362; pub const SYS_switch_endian: ::c_long = 363; pub const SYS_userfaultfd: ::c_long = 364; pub const SYS_membarrier: ::c_long = 365; pub const SYS_mlock2: ::c_long = 378; pub const SYS_copy_file_range: ::c_long = 379; pub const SYS_preadv2: ::c_long = 380; pub const SYS_pwritev2: ::c_long = 381; pub const SYS_kexec_file_load: ::c_long = 382; pub const SYS_statx: ::c_long = 383; pub const SYS_rseq: ::c_long = 387; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs0000644000175000017500000000022514661133735024202 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [i64; 4] } } libc/src/unix/linux_like/linux/gnu/b64/aarch64/0000775000175000017500000000000014661133735022144 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs0000644000175000017500000000436614661133735023452 0ustar jamespagejamespageuse pthread_mutex_t; pub type c_long = i32; pub type c_ulong = u32; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 48; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; align_const! { #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const SYS_sync_file_range2: ::c_long = 84; libc/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs0000644000175000017500000000021614661133735023534 0ustar jamespagejamespages! { pub struct user_fpsimd_struct { pub vregs: [::__uint128_t; 32], pub fpsr: u32, pub fpcr: u32, } } libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs0000644000175000017500000007645514661133735023310 0ustar jamespagejamespage//! AArch64-specific definitions for 64-bit linux-like values pub type c_char = u8; pub type wchar_t = u32; pub type nlink_t = u32; pub type blksize_t = i32; pub type suseconds_t = i64; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: ::c_int, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, __pad2: ::c_int, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_attr_t { __size: [usize; 8] } pub struct user_regs_struct { pub regs: [::c_ulonglong; 31], pub sp: ::c_ulonglong, pub pc: ::c_ulonglong, pub pstate: ::c_ulonglong, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_uint, pub __seq: ::c_ushort, __pad1: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } } pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const PTRACE_DETACH: ::c_uint = 17; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_CLOEXEC: ::c_int = 0x80000; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const SIGSTKSZ: ::size_t = 16384; pub const MINSIGSTKSZ: ::size_t = 5120; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; // sys/auxv.h pub const HWCAP_FP: ::c_ulong = 1 << 0; pub const HWCAP_ASIMD: ::c_ulong = 1 << 1; pub const HWCAP_EVTSTRM: ::c_ulong = 1 << 2; pub const HWCAP_AES: ::c_ulong = 1 << 3; pub const HWCAP_PMULL: ::c_ulong = 1 << 4; pub const HWCAP_SHA1: ::c_ulong = 1 << 5; pub const HWCAP_SHA2: ::c_ulong = 1 << 6; pub const HWCAP_CRC32: ::c_ulong = 1 << 7; pub const HWCAP_ATOMICS: ::c_ulong = 1 << 8; pub const HWCAP_FPHP: ::c_ulong = 1 << 9; pub const HWCAP_ASIMDHP: ::c_ulong = 1 << 10; pub const HWCAP_CPUID: ::c_ulong = 1 << 11; pub const HWCAP_ASIMDRDM: ::c_ulong = 1 << 12; pub const HWCAP_JSCVT: ::c_ulong = 1 << 13; pub const HWCAP_FCMA: ::c_ulong = 1 << 14; pub const HWCAP_LRCPC: ::c_ulong = 1 << 15; pub const HWCAP_DCPOP: ::c_ulong = 1 << 16; pub const HWCAP_SHA3: ::c_ulong = 1 << 17; pub const HWCAP_SM3: ::c_ulong = 1 << 18; pub const HWCAP_SM4: ::c_ulong = 1 << 19; pub const HWCAP_ASIMDDP: ::c_ulong = 1 << 20; pub const HWCAP_SHA512: ::c_ulong = 1 << 21; pub const HWCAP_SVE: ::c_ulong = 1 << 22; pub const HWCAP_ASIMDFHM: ::c_ulong = 1 << 23; pub const HWCAP_DIT: ::c_ulong = 1 << 24; pub const HWCAP_USCAT: ::c_ulong = 1 << 25; pub const HWCAP_ILRCPC: ::c_ulong = 1 << 26; pub const HWCAP_FLAGM: ::c_ulong = 1 << 27; pub const HWCAP_SSBS: ::c_ulong = 1 << 28; pub const HWCAP_SB: ::c_ulong = 1 << 29; pub const HWCAP_PACA: ::c_ulong = 1 << 30; pub const HWCAP_PACG: ::c_ulong = 1 << 31; // FIXME: enable these again once linux-api-headers are up to date enough on CI. // See discussion in https://github.com/rust-lang/libc/pull/1638 //pub const HWCAP2_DCPODP: ::c_ulong = 1 << 0; //pub const HWCAP2_SVE2: ::c_ulong = 1 << 1; //pub const HWCAP2_SVEAES: ::c_ulong = 1 << 2; //pub const HWCAP2_SVEPMULL: ::c_ulong = 1 << 3; //pub const HWCAP2_SVEBITPERM: ::c_ulong = 1 << 4; //pub const HWCAP2_SVESHA3: ::c_ulong = 1 << 5; //pub const HWCAP2_SVESM4: ::c_ulong = 1 << 6; //pub const HWCAP2_FLAGM2: ::c_ulong = 1 << 7; //pub const HWCAP2_FRINT: ::c_ulong = 1 << 8; //pub const HWCAP2_MTE: ::c_ulong = 1 << 18; // linux/prctl.h pub const PR_PAC_RESET_KEYS: ::c_int = 54; pub const PR_SET_TAGGED_ADDR_CTRL: ::c_int = 55; pub const PR_GET_TAGGED_ADDR_CTRL: ::c_int = 56; pub const PR_PAC_SET_ENABLED_KEYS: ::c_int = 60; pub const PR_PAC_GET_ENABLED_KEYS: ::c_int = 61; pub const PR_TAGGED_ADDR_ENABLE: ::c_ulong = 1; pub const PR_PAC_APIAKEY: ::c_ulong = 1 << 0; pub const PR_PAC_APIBKEY: ::c_ulong = 1 << 1; pub const PR_PAC_APDAKEY: ::c_ulong = 1 << 2; pub const PR_PAC_APDBKEY: ::c_ulong = 1 << 3; pub const PR_PAC_APGAKEY: ::c_ulong = 1 << 4; pub const PR_SME_SET_VL: ::c_int = 63; pub const PR_SME_GET_VL: ::c_int = 64; pub const PR_SME_VL_LEN_MAX: ::c_int = 0xffff; pub const PR_SME_SET_VL_INHERIT: ::c_ulong = 1 << 17; pub const PR_SME_SET_VL_ONE_EXEC: ::c_ulong = 1 << 18; // Syscall table pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_getcwd: ::c_long = 17; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_dup: ::c_long = 23; pub const SYS_dup3: ::c_long = 24; pub const SYS_fcntl: ::c_long = 25; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_ioctl: ::c_long = 29; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_flock: ::c_long = 32; pub const SYS_mknodat: ::c_long = 33; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_linkat: ::c_long = 37; // 38 is renameat only on LP64 pub const SYS_umount2: ::c_long = 39; pub const SYS_mount: ::c_long = 40; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_fallocate: ::c_long = 47; pub const SYS_faccessat: ::c_long = 48; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_chroot: ::c_long = 51; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_fchownat: ::c_long = 54; pub const SYS_fchown: ::c_long = 55; pub const SYS_openat: ::c_long = 56; pub const SYS_close: ::c_long = 57; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pipe2: ::c_long = 59; pub const SYS_quotactl: ::c_long = 60; pub const SYS_getdents64: ::c_long = 61; pub const SYS_lseek: ::c_long = 62; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_newfstatat: ::c_long = 79; pub const SYS_fstat: ::c_long = 80; pub const SYS_sync: ::c_long = 81; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; // 84 sync_file_range on LP64 and sync_file_range2 on ILP32 pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_utimensat: ::c_long = 88; pub const SYS_acct: ::c_long = 89; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_personality: ::c_long = 92; pub const SYS_exit: ::c_long = 93; pub const SYS_exit_group: ::c_long = 94; pub const SYS_waitid: ::c_long = 95; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_unshare: ::c_long = 97; pub const SYS_futex: ::c_long = 98; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_syslog: ::c_long = 116; pub const SYS_ptrace: ::c_long = 117; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_kill: ::c_long = 129; pub const SYS_tkill: ::c_long = 130; pub const SYS_tgkill: ::c_long = 131; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_setpriority: ::c_long = 140; pub const SYS_getpriority: ::c_long = 141; pub const SYS_reboot: ::c_long = 142; pub const SYS_setregid: ::c_long = 143; pub const SYS_setgid: ::c_long = 144; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setuid: ::c_long = 146; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_times: ::c_long = 153; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getpgid: ::c_long = 155; pub const SYS_getsid: ::c_long = 156; pub const SYS_setsid: ::c_long = 157; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_uname: ::c_long = 160; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; // 163 is getrlimit only on LP64 // 164 is setrlimit only on LP64 pub const SYS_getrusage: ::c_long = 165; pub const SYS_umask: ::c_long = 166; pub const SYS_prctl: ::c_long = 167; pub const SYS_getcpu: ::c_long = 168; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_getpid: ::c_long = 172; pub const SYS_getppid: ::c_long = 173; pub const SYS_getuid: ::c_long = 174; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getgid: ::c_long = 176; pub const SYS_getegid: ::c_long = 177; pub const SYS_gettid: ::c_long = 178; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgctl: ::c_long = 187; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_semget: ::c_long = 190; pub const SYS_semctl: ::c_long = 191; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_semop: ::c_long = 193; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmctl: ::c_long = 195; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmdt: ::c_long = 197; pub const SYS_socket: ::c_long = 198; pub const SYS_socketpair: ::c_long = 199; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_accept: ::c_long = 202; pub const SYS_connect: ::c_long = 203; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_shutdown: ::c_long = 210; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_readahead: ::c_long = 213; pub const SYS_brk: ::c_long = 214; pub const SYS_munmap: ::c_long = 215; pub const SYS_mremap: ::c_long = 216; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_mmap: ::c_long = 222; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_mprotect: ::c_long = 226; pub const SYS_msync: ::c_long = 227; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_mbind: ::c_long = 235; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_move_pages: ::c_long = 239; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_accept4: ::c_long = 242; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_wait4: ::c_long = 260; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_setns: ::c_long = 268; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_rseq: ::c_long = 293; pub const SYS_kexec_file_load: ::c_long = 294; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; pub const PROT_BTI: ::c_int = 0x10; pub const PROT_MTE: ::c_int = 0x20; extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod ilp32; pub use self::ilp32::*; } else { mod lp64; pub use self::lp64::*; } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } cfg_if! { if #[cfg(libc_int128)] { mod int128; pub use self::int128::*; } else if #[cfg(libc_align)] { mod fallback; pub use self::fallback::*; } } libc/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs0000644000175000017500000000535614661133735023306 0ustar jamespagejamespageuse pthread_mutex_t; pub type c_long = i64; pub type c_ulong = u64; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 48; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; align_const! { #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const SYS_renameat: ::c_long = 38; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_setrlimit: ::c_long = 164; libc/src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs0000644000175000017500000000024314661133735024246 0ustar jamespagejamespages! { #[repr(align(16))] pub struct user_fpsimd_struct { pub vregs: [[u64; 2]; 32], pub fpsr: ::c_uint, pub fpcr: ::c_uint, } } libc/src/unix/linux_like/linux/gnu/b64/aarch64/align.rs0000644000175000017500000000275414661133735023612 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8] } } s! { pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub fault_address: ::c_ulonglong, pub regs: [::c_ulonglong; 31], pub sp: ::c_ulonglong, pub pc: ::c_ulonglong, pub pstate: ::c_ulonglong, // nested arrays to get the right size/length while being able to // auto-derive traits like Debug __reserved: [[u64; 32]; 16], } #[repr(align(8))] pub struct clone_args { pub flags: ::c_ulonglong, pub pidfd: ::c_ulonglong, pub child_tid: ::c_ulonglong, pub parent_tid: ::c_ulonglong, pub exit_signal: ::c_ulonglong, pub stack: ::c_ulonglong, pub stack_size: ::c_ulonglong, pub tls: ::c_ulonglong, pub set_tid: ::c_ulonglong, pub set_tid_size: ::c_ulonglong, pub cgroup: ::c_ulonglong, } } extern "C" { pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int; pub fn setcontext(ucp: *const ucontext_t) -> ::c_int; pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; } libc/src/unix/linux_like/linux/gnu/b64/sparc64/0000775000175000017500000000000014661133735022176 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs0000644000175000017500000007676314661133735023344 0ustar jamespagejamespage//! SPARC64-specific definitions for 64-bit linux-like values use pthread_mutex_t; pub type c_long = i64; pub type c_ulong = u64; pub type c_char = i8; pub type wchar_t = i32; pub type nlink_t = u32; pub type blksize_t = i64; pub type suseconds_t = i32; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: ::c_int, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, __reserved: ::c_short, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct stat { pub st_dev: ::dev_t, __pad0: u64, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: u64, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 2], } pub struct stat64 { pub st_dev: ::dev_t, __pad0: u64, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad2: ::c_int, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __reserved: [::c_long; 2], } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_attr_t { __size: [u64; 7] } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, __pad0: u16, pub __seq: ::c_ushort, __unused1: ::c_ulonglong, __unused2: ::c_ulonglong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_segsz: ::size_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __reserved1: ::c_ulong, __reserved2: ::c_ulong } } pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const O_APPEND: ::c_int = 0x8; pub const O_CREAT: ::c_int = 0x200; pub const O_EXCL: ::c_int = 0x800; pub const O_NOCTTY: ::c_int = 0x8000; pub const O_NONBLOCK: ::c_int = 0x4000; pub const O_SYNC: ::c_int = 0x802000; pub const O_RSYNC: ::c_int = 0x802000; pub const O_DSYNC: ::c_int = 0x2000; pub const O_FSYNC: ::c_int = 0x802000; pub const O_NOATIME: ::c_int = 0x200000; pub const O_PATH: ::c_int = 0x1000000; pub const O_TMPFILE: ::c_int = 0x2000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 0x0200; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLK: ::c_int = 78; pub const ENAMETOOLONG: ::c_int = 63; pub const ENOLCK: ::c_int = 79; pub const ENOSYS: ::c_int = 90; pub const ENOTEMPTY: ::c_int = 66; pub const ELOOP: ::c_int = 62; pub const ENOMSG: ::c_int = 75; pub const EIDRM: ::c_int = 77; pub const ECHRNG: ::c_int = 94; pub const EL2NSYNC: ::c_int = 95; pub const EL3HLT: ::c_int = 96; pub const EL3RST: ::c_int = 97; pub const ELNRNG: ::c_int = 98; pub const EUNATCH: ::c_int = 99; pub const ENOCSI: ::c_int = 100; pub const EL2HLT: ::c_int = 101; pub const EBADE: ::c_int = 102; pub const EBADR: ::c_int = 103; pub const EXFULL: ::c_int = 104; pub const ENOANO: ::c_int = 105; pub const EBADRQC: ::c_int = 106; pub const EBADSLT: ::c_int = 107; pub const EMULTIHOP: ::c_int = 87; pub const EOVERFLOW: ::c_int = 92; pub const ENOTUNIQ: ::c_int = 115; pub const EBADFD: ::c_int = 93; pub const EBADMSG: ::c_int = 76; pub const EREMCHG: ::c_int = 89; pub const ELIBACC: ::c_int = 114; pub const ELIBBAD: ::c_int = 112; pub const ELIBSCN: ::c_int = 124; pub const ELIBMAX: ::c_int = 123; pub const ELIBEXEC: ::c_int = 110; pub const EILSEQ: ::c_int = 122; pub const ERESTART: ::c_int = 116; pub const ESTRPIPE: ::c_int = 91; pub const EUSERS: ::c_int = 68; pub const ENOTSOCK: ::c_int = 38; pub const EDESTADDRREQ: ::c_int = 39; pub const EMSGSIZE: ::c_int = 40; pub const EPROTOTYPE: ::c_int = 41; pub const ENOPROTOOPT: ::c_int = 42; pub const EPROTONOSUPPORT: ::c_int = 43; pub const ESOCKTNOSUPPORT: ::c_int = 44; pub const EOPNOTSUPP: ::c_int = 45; pub const EPFNOSUPPORT: ::c_int = 46; pub const EAFNOSUPPORT: ::c_int = 47; pub const EADDRINUSE: ::c_int = 48; pub const EADDRNOTAVAIL: ::c_int = 49; pub const ENETDOWN: ::c_int = 50; pub const ENETUNREACH: ::c_int = 51; pub const ENETRESET: ::c_int = 52; pub const ECONNABORTED: ::c_int = 53; pub const ECONNRESET: ::c_int = 54; pub const ENOBUFS: ::c_int = 55; pub const EISCONN: ::c_int = 56; pub const ENOTCONN: ::c_int = 57; pub const ESHUTDOWN: ::c_int = 58; pub const ETOOMANYREFS: ::c_int = 59; pub const ETIMEDOUT: ::c_int = 60; pub const ECONNREFUSED: ::c_int = 61; pub const EHOSTDOWN: ::c_int = 64; pub const EHOSTUNREACH: ::c_int = 65; pub const EALREADY: ::c_int = 37; pub const EINPROGRESS: ::c_int = 36; pub const ESTALE: ::c_int = 70; pub const EDQUOT: ::c_int = 69; pub const ENOMEDIUM: ::c_int = 125; pub const EMEDIUMTYPE: ::c_int = 126; pub const ECANCELED: ::c_int = 127; pub const ENOKEY: ::c_int = 128; pub const EKEYEXPIRED: ::c_int = 129; pub const EKEYREVOKED: ::c_int = 130; pub const EKEYREJECTED: ::c_int = 131; pub const EOWNERDEAD: ::c_int = 132; pub const ENOTRECOVERABLE: ::c_int = 133; pub const EHWPOISON: ::c_int = 135; pub const ERFKILL: ::c_int = 134; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 1; pub const SA_SIGINFO: ::c_int = 0x200; pub const SA_NOCLDWAIT: ::c_int = 0x100; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 20; pub const SIGBUS: ::c_int = 10; pub const SIGUSR1: ::c_int = 30; pub const SIGUSR2: ::c_int = 31; pub const SIGCONT: ::c_int = 19; pub const SIGSTOP: ::c_int = 17; pub const SIGTSTP: ::c_int = 18; pub const SIGURG: ::c_int = 16; pub const SIGIO: ::c_int = 23; pub const SIGSYS: ::c_int = 12; pub const SIGPOLL: ::c_int = 23; pub const SIGPWR: ::c_int = 29; pub const SIG_SETMASK: ::c_int = 4; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const POLLWRNORM: ::c_short = 4; pub const POLLWRBAND: ::c_short = 0x100; pub const O_ASYNC: ::c_int = 0x40; pub const O_NDELAY: ::c_int = 0x4004; pub const PTRACE_DETACH: ::c_uint = 17; pub const EFD_NONBLOCK: ::c_int = 0x4000; pub const F_GETLK: ::c_int = 7; pub const F_GETOWN: ::c_int = 5; pub const F_SETOWN: ::c_int = 6; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const F_RDLCK: ::c_int = 1; pub const F_WRLCK: ::c_int = 2; pub const F_UNLCK: ::c_int = 3; pub const SFD_NONBLOCK: ::c_int = 0x4000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const SFD_CLOEXEC: ::c_int = 0x400000; pub const NCCS: usize = 17; pub const O_TRUNC: ::c_int = 0x400; pub const O_CLOEXEC: ::c_int = 0x400000; pub const EBFONT: ::c_int = 109; pub const ENOSTR: ::c_int = 72; pub const ENODATA: ::c_int = 111; pub const ETIME: ::c_int = 73; pub const ENOSR: ::c_int = 74; pub const ENONET: ::c_int = 80; pub const ENOPKG: ::c_int = 113; pub const EREMOTE: ::c_int = 71; pub const ENOLINK: ::c_int = 82; pub const EADV: ::c_int = 83; pub const ESRMNT: ::c_int = 84; pub const ECOMM: ::c_int = 85; pub const EPROTO: ::c_int = 86; pub const EDOTDOT: ::c_int = 88; pub const SA_NODEFER: ::c_int = 0x20; pub const SA_RESETHAND: ::c_int = 0x4; pub const SA_RESTART: ::c_int = 0x2; pub const SA_NOCLDSTOP: ::c_int = 0x00000008; pub const EPOLL_CLOEXEC: ::c_int = 0x400000; pub const EFD_CLOEXEC: ::c_int = 0x400000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; align_const! { pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const O_DIRECTORY: ::c_int = 0o200000; pub const O_NOFOLLOW: ::c_int = 0o400000; pub const O_DIRECT: ::c_int = 0x100000; pub const MAP_LOCKED: ::c_int = 0x0100; pub const MAP_NORESERVE: ::c_int = 0x00040; pub const EDEADLOCK: ::c_int = 108; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const MCL_CURRENT: ::c_int = 0x2000; pub const MCL_FUTURE: ::c_int = 0x4000; pub const MCL_ONFAULT: ::c_int = 0x8000; pub const SIGSTKSZ: ::size_t = 16384; pub const MINSIGSTKSZ: ::size_t = 4096; pub const CBAUD: ::tcflag_t = 0x0000100f; pub const TAB1: ::tcflag_t = 0x800; pub const TAB2: ::tcflag_t = 0x1000; pub const TAB3: ::tcflag_t = 0x1800; pub const CR1: ::tcflag_t = 0x200; pub const CR2: ::tcflag_t = 0x400; pub const CR3: ::tcflag_t = 0x600; pub const FF1: ::tcflag_t = 0x8000; pub const BS1: ::tcflag_t = 0x2000; pub const VT1: ::tcflag_t = 0x4000; pub const VWERASE: usize = 0xe; pub const VREPRINT: usize = 0xc; pub const VSUSP: usize = 0xa; pub const VSTART: usize = 0x8; pub const VSTOP: usize = 0x9; pub const VDISCARD: usize = 0xd; pub const VTIME: usize = 0x5; pub const IXON: ::tcflag_t = 0x400; pub const IXOFF: ::tcflag_t = 0x1000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x30; pub const CS6: ::tcflag_t = 0x10; pub const CS7: ::tcflag_t = 0x20; pub const CS8: ::tcflag_t = 0x30; pub const CSTOPB: ::tcflag_t = 0x40; pub const CREAD: ::tcflag_t = 0x80; pub const PARENB: ::tcflag_t = 0x100; pub const PARODD: ::tcflag_t = 0x200; pub const HUPCL: ::tcflag_t = 0x400; pub const CLOCAL: ::tcflag_t = 0x800; pub const ECHOKE: ::tcflag_t = 0x800; pub const ECHOE: ::tcflag_t = 0x10; pub const ECHOK: ::tcflag_t = 0x20; pub const ECHONL: ::tcflag_t = 0x40; pub const ECHOPRT: ::tcflag_t = 0x400; pub const ECHOCTL: ::tcflag_t = 0x200; pub const ISIG: ::tcflag_t = 0x1; pub const ICANON: ::tcflag_t = 0x2; pub const PENDIN: ::tcflag_t = 0x4000; pub const NOFLSH: ::tcflag_t = 0x80; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0x00001000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0x1001; pub const B115200: ::speed_t = 0x1002; pub const B230400: ::speed_t = 0x1003; pub const B460800: ::speed_t = 0x1004; pub const B76800: ::speed_t = 0x1005; pub const B153600: ::speed_t = 0x1006; pub const B307200: ::speed_t = 0x1007; pub const B614400: ::speed_t = 0x1008; pub const B921600: ::speed_t = 0x1009; pub const B500000: ::speed_t = 0x100a; pub const B576000: ::speed_t = 0x100b; pub const B1000000: ::speed_t = 0x100c; pub const B1152000: ::speed_t = 0x100d; pub const B1500000: ::speed_t = 0x100e; pub const B2000000: ::speed_t = 0x100f; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: ::tcflag_t = 0x8000; pub const TOSTOP: ::tcflag_t = 0x100; pub const FLUSHO: ::tcflag_t = 0x1000; pub const EXTPROC: ::tcflag_t = 0x10000; pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_wait4: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execv: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_chown: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_brk: ::c_long = 17; pub const SYS_perfctr: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_capget: ::c_long = 21; pub const SYS_capset: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_vmsplice: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_sigaltstack: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_stat: ::c_long = 38; pub const SYS_sendfile: ::c_long = 39; pub const SYS_lstat: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_umount2: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_memory_ordering: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_reboot: ::c_long = 55; pub const SYS_symlink: ::c_long = 57; pub const SYS_readlink: ::c_long = 58; pub const SYS_execve: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_fstat: ::c_long = 62; pub const SYS_fstat64: ::c_long = 63; pub const SYS_getpagesize: ::c_long = 64; pub const SYS_msync: ::c_long = 65; pub const SYS_vfork: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_mmap: ::c_long = 71; pub const SYS_munmap: ::c_long = 73; pub const SYS_mprotect: ::c_long = 74; pub const SYS_madvise: ::c_long = 75; pub const SYS_vhangup: ::c_long = 76; pub const SYS_mincore: ::c_long = 78; pub const SYS_getgroups: ::c_long = 79; pub const SYS_setgroups: ::c_long = 80; pub const SYS_getpgrp: ::c_long = 81; pub const SYS_setitimer: ::c_long = 83; pub const SYS_swapon: ::c_long = 85; pub const SYS_getitimer: ::c_long = 86; pub const SYS_sethostname: ::c_long = 88; pub const SYS_dup2: ::c_long = 90; pub const SYS_fcntl: ::c_long = 92; pub const SYS_select: ::c_long = 93; pub const SYS_fsync: ::c_long = 95; pub const SYS_setpriority: ::c_long = 96; pub const SYS_socket: ::c_long = 97; pub const SYS_connect: ::c_long = 98; pub const SYS_accept: ::c_long = 99; pub const SYS_getpriority: ::c_long = 100; pub const SYS_rt_sigreturn: ::c_long = 101; pub const SYS_rt_sigaction: ::c_long = 102; pub const SYS_rt_sigprocmask: ::c_long = 103; pub const SYS_rt_sigpending: ::c_long = 104; pub const SYS_rt_sigtimedwait: ::c_long = 105; pub const SYS_rt_sigqueueinfo: ::c_long = 106; pub const SYS_rt_sigsuspend: ::c_long = 107; pub const SYS_setresuid: ::c_long = 108; pub const SYS_getresuid: ::c_long = 109; pub const SYS_setresgid: ::c_long = 110; pub const SYS_getresgid: ::c_long = 111; pub const SYS_recvmsg: ::c_long = 113; pub const SYS_sendmsg: ::c_long = 114; pub const SYS_gettimeofday: ::c_long = 116; pub const SYS_getrusage: ::c_long = 117; pub const SYS_getsockopt: ::c_long = 118; pub const SYS_getcwd: ::c_long = 119; pub const SYS_readv: ::c_long = 120; pub const SYS_writev: ::c_long = 121; pub const SYS_settimeofday: ::c_long = 122; pub const SYS_fchown: ::c_long = 123; pub const SYS_fchmod: ::c_long = 124; pub const SYS_recvfrom: ::c_long = 125; pub const SYS_setreuid: ::c_long = 126; pub const SYS_setregid: ::c_long = 127; pub const SYS_rename: ::c_long = 128; pub const SYS_truncate: ::c_long = 129; pub const SYS_ftruncate: ::c_long = 130; pub const SYS_flock: ::c_long = 131; pub const SYS_lstat64: ::c_long = 132; pub const SYS_sendto: ::c_long = 133; pub const SYS_shutdown: ::c_long = 134; pub const SYS_socketpair: ::c_long = 135; pub const SYS_mkdir: ::c_long = 136; pub const SYS_rmdir: ::c_long = 137; pub const SYS_utimes: ::c_long = 138; pub const SYS_stat64: ::c_long = 139; pub const SYS_sendfile64: ::c_long = 140; pub const SYS_getpeername: ::c_long = 141; pub const SYS_futex: ::c_long = 142; pub const SYS_gettid: ::c_long = 143; pub const SYS_getrlimit: ::c_long = 144; pub const SYS_setrlimit: ::c_long = 145; pub const SYS_pivot_root: ::c_long = 146; pub const SYS_prctl: ::c_long = 147; pub const SYS_pciconfig_read: ::c_long = 148; pub const SYS_pciconfig_write: ::c_long = 149; pub const SYS_getsockname: ::c_long = 150; pub const SYS_inotify_init: ::c_long = 151; pub const SYS_inotify_add_watch: ::c_long = 152; pub const SYS_poll: ::c_long = 153; pub const SYS_getdents64: ::c_long = 154; pub const SYS_inotify_rm_watch: ::c_long = 156; pub const SYS_statfs: ::c_long = 157; pub const SYS_fstatfs: ::c_long = 158; pub const SYS_umount: ::c_long = 159; pub const SYS_sched_set_affinity: ::c_long = 160; pub const SYS_sched_get_affinity: ::c_long = 161; pub const SYS_getdomainname: ::c_long = 162; pub const SYS_setdomainname: ::c_long = 163; pub const SYS_utrap_install: ::c_long = 164; pub const SYS_quotactl: ::c_long = 165; pub const SYS_set_tid_address: ::c_long = 166; pub const SYS_mount: ::c_long = 167; pub const SYS_ustat: ::c_long = 168; pub const SYS_setxattr: ::c_long = 169; pub const SYS_lsetxattr: ::c_long = 170; pub const SYS_fsetxattr: ::c_long = 171; pub const SYS_getxattr: ::c_long = 172; pub const SYS_lgetxattr: ::c_long = 173; pub const SYS_getdents: ::c_long = 174; pub const SYS_setsid: ::c_long = 175; pub const SYS_fchdir: ::c_long = 176; pub const SYS_fgetxattr: ::c_long = 177; pub const SYS_listxattr: ::c_long = 178; pub const SYS_llistxattr: ::c_long = 179; pub const SYS_flistxattr: ::c_long = 180; pub const SYS_removexattr: ::c_long = 181; pub const SYS_lremovexattr: ::c_long = 182; pub const SYS_sigpending: ::c_long = 183; pub const SYS_query_module: ::c_long = 184; pub const SYS_setpgid: ::c_long = 185; pub const SYS_fremovexattr: ::c_long = 186; pub const SYS_tkill: ::c_long = 187; pub const SYS_exit_group: ::c_long = 188; pub const SYS_uname: ::c_long = 189; pub const SYS_init_module: ::c_long = 190; pub const SYS_personality: ::c_long = 191; pub const SYS_remap_file_pages: ::c_long = 192; pub const SYS_epoll_create: ::c_long = 193; pub const SYS_epoll_ctl: ::c_long = 194; pub const SYS_epoll_wait: ::c_long = 195; pub const SYS_ioprio_set: ::c_long = 196; pub const SYS_getppid: ::c_long = 197; pub const SYS_sigaction: ::c_long = 198; pub const SYS_sgetmask: ::c_long = 199; pub const SYS_ssetmask: ::c_long = 200; pub const SYS_sigsuspend: ::c_long = 201; pub const SYS_oldlstat: ::c_long = 202; pub const SYS_uselib: ::c_long = 203; pub const SYS_readdir: ::c_long = 204; pub const SYS_readahead: ::c_long = 205; pub const SYS_socketcall: ::c_long = 206; pub const SYS_syslog: ::c_long = 207; pub const SYS_lookup_dcookie: ::c_long = 208; pub const SYS_fadvise64: ::c_long = 209; pub const SYS_fadvise64_64: ::c_long = 210; pub const SYS_tgkill: ::c_long = 211; pub const SYS_waitpid: ::c_long = 212; pub const SYS_swapoff: ::c_long = 213; pub const SYS_sysinfo: ::c_long = 214; pub const SYS_ipc: ::c_long = 215; pub const SYS_sigreturn: ::c_long = 216; pub const SYS_clone: ::c_long = 217; pub const SYS_ioprio_get: ::c_long = 218; pub const SYS_adjtimex: ::c_long = 219; pub const SYS_sigprocmask: ::c_long = 220; pub const SYS_create_module: ::c_long = 221; pub const SYS_delete_module: ::c_long = 222; pub const SYS_get_kernel_syms: ::c_long = 223; pub const SYS_getpgid: ::c_long = 224; pub const SYS_bdflush: ::c_long = 225; pub const SYS_sysfs: ::c_long = 226; pub const SYS_afs_syscall: ::c_long = 227; pub const SYS_setfsuid: ::c_long = 228; pub const SYS_setfsgid: ::c_long = 229; pub const SYS__newselect: ::c_long = 230; pub const SYS_splice: ::c_long = 232; pub const SYS_stime: ::c_long = 233; pub const SYS_statfs64: ::c_long = 234; pub const SYS_fstatfs64: ::c_long = 235; pub const SYS__llseek: ::c_long = 236; pub const SYS_mlock: ::c_long = 237; pub const SYS_munlock: ::c_long = 238; pub const SYS_mlockall: ::c_long = 239; pub const SYS_munlockall: ::c_long = 240; pub const SYS_sched_setparam: ::c_long = 241; pub const SYS_sched_getparam: ::c_long = 242; pub const SYS_sched_setscheduler: ::c_long = 243; pub const SYS_sched_getscheduler: ::c_long = 244; pub const SYS_sched_yield: ::c_long = 245; pub const SYS_sched_get_priority_max: ::c_long = 246; pub const SYS_sched_get_priority_min: ::c_long = 247; pub const SYS_sched_rr_get_interval: ::c_long = 248; pub const SYS_nanosleep: ::c_long = 249; pub const SYS_mremap: ::c_long = 250; pub const SYS__sysctl: ::c_long = 251; pub const SYS_getsid: ::c_long = 252; pub const SYS_fdatasync: ::c_long = 253; pub const SYS_nfsservctl: ::c_long = 254; pub const SYS_sync_file_range: ::c_long = 255; pub const SYS_clock_settime: ::c_long = 256; pub const SYS_clock_gettime: ::c_long = 257; pub const SYS_clock_getres: ::c_long = 258; pub const SYS_clock_nanosleep: ::c_long = 259; pub const SYS_sched_getaffinity: ::c_long = 260; pub const SYS_sched_setaffinity: ::c_long = 261; pub const SYS_timer_settime: ::c_long = 262; pub const SYS_timer_gettime: ::c_long = 263; pub const SYS_timer_getoverrun: ::c_long = 264; pub const SYS_timer_delete: ::c_long = 265; pub const SYS_timer_create: ::c_long = 266; pub const SYS_io_setup: ::c_long = 268; pub const SYS_io_destroy: ::c_long = 269; pub const SYS_io_submit: ::c_long = 270; pub const SYS_io_cancel: ::c_long = 271; pub const SYS_io_getevents: ::c_long = 272; pub const SYS_mq_open: ::c_long = 273; pub const SYS_mq_unlink: ::c_long = 274; pub const SYS_mq_timedsend: ::c_long = 275; pub const SYS_mq_timedreceive: ::c_long = 276; pub const SYS_mq_notify: ::c_long = 277; pub const SYS_mq_getsetattr: ::c_long = 278; pub const SYS_waitid: ::c_long = 279; pub const SYS_tee: ::c_long = 280; pub const SYS_add_key: ::c_long = 281; pub const SYS_request_key: ::c_long = 282; pub const SYS_keyctl: ::c_long = 283; pub const SYS_openat: ::c_long = 284; pub const SYS_mkdirat: ::c_long = 285; pub const SYS_mknodat: ::c_long = 286; pub const SYS_fchownat: ::c_long = 287; pub const SYS_futimesat: ::c_long = 288; pub const SYS_fstatat64: ::c_long = 289; pub const SYS_unlinkat: ::c_long = 290; pub const SYS_renameat: ::c_long = 291; pub const SYS_linkat: ::c_long = 292; pub const SYS_symlinkat: ::c_long = 293; pub const SYS_readlinkat: ::c_long = 294; pub const SYS_fchmodat: ::c_long = 295; pub const SYS_faccessat: ::c_long = 296; pub const SYS_pselect6: ::c_long = 297; pub const SYS_ppoll: ::c_long = 298; pub const SYS_unshare: ::c_long = 299; pub const SYS_set_robust_list: ::c_long = 300; pub const SYS_get_robust_list: ::c_long = 301; pub const SYS_migrate_pages: ::c_long = 302; pub const SYS_mbind: ::c_long = 303; pub const SYS_get_mempolicy: ::c_long = 304; pub const SYS_set_mempolicy: ::c_long = 305; pub const SYS_kexec_load: ::c_long = 306; pub const SYS_move_pages: ::c_long = 307; pub const SYS_getcpu: ::c_long = 308; pub const SYS_epoll_pwait: ::c_long = 309; pub const SYS_utimensat: ::c_long = 310; pub const SYS_signalfd: ::c_long = 311; pub const SYS_timerfd_create: ::c_long = 312; pub const SYS_eventfd: ::c_long = 313; pub const SYS_fallocate: ::c_long = 314; pub const SYS_timerfd_settime: ::c_long = 315; pub const SYS_timerfd_gettime: ::c_long = 316; pub const SYS_signalfd4: ::c_long = 317; pub const SYS_eventfd2: ::c_long = 318; pub const SYS_epoll_create1: ::c_long = 319; pub const SYS_dup3: ::c_long = 320; pub const SYS_pipe2: ::c_long = 321; pub const SYS_inotify_init1: ::c_long = 322; pub const SYS_accept4: ::c_long = 323; pub const SYS_preadv: ::c_long = 324; pub const SYS_pwritev: ::c_long = 325; pub const SYS_rt_tgsigqueueinfo: ::c_long = 326; pub const SYS_perf_event_open: ::c_long = 327; pub const SYS_recvmmsg: ::c_long = 328; pub const SYS_fanotify_init: ::c_long = 329; pub const SYS_fanotify_mark: ::c_long = 330; pub const SYS_prlimit64: ::c_long = 331; pub const SYS_name_to_handle_at: ::c_long = 332; pub const SYS_open_by_handle_at: ::c_long = 333; pub const SYS_clock_adjtime: ::c_long = 334; pub const SYS_syncfs: ::c_long = 335; pub const SYS_sendmmsg: ::c_long = 336; pub const SYS_setns: ::c_long = 337; pub const SYS_process_vm_readv: ::c_long = 338; pub const SYS_process_vm_writev: ::c_long = 339; pub const SYS_kern_features: ::c_long = 340; pub const SYS_kcmp: ::c_long = 341; pub const SYS_finit_module: ::c_long = 342; pub const SYS_sched_setattr: ::c_long = 343; pub const SYS_sched_getattr: ::c_long = 344; pub const SYS_renameat2: ::c_long = 345; pub const SYS_seccomp: ::c_long = 346; pub const SYS_getrandom: ::c_long = 347; pub const SYS_memfd_create: ::c_long = 348; pub const SYS_bpf: ::c_long = 349; pub const SYS_execveat: ::c_long = 350; pub const SYS_membarrier: ::c_long = 351; pub const SYS_userfaultfd: ::c_long = 352; pub const SYS_bind: ::c_long = 353; pub const SYS_listen: ::c_long = 354; pub const SYS_setsockopt: ::c_long = 355; pub const SYS_mlock2: ::c_long = 356; pub const SYS_copy_file_range: ::c_long = 357; pub const SYS_preadv2: ::c_long = 358; pub const SYS_pwritev2: ::c_long = 359; pub const SYS_statx: ::c_long = 360; pub const SYS_rseq: ::c_long = 365; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; // Reserved in the kernel, but not actually implemented yet pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b64/sparc64/align.rs0000644000175000017500000000022514661133735023633 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [i64; 4] } } libc/src/unix/linux_like/linux/gnu/b64/riscv64/0000775000175000017500000000000014661133735022214 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs0000644000175000017500000007265114661133735023352 0ustar jamespagejamespage//! RISC-V-specific definitions for 64-bit linux-like values pub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = ::c_int; pub type nlink_t = ::c_uint; pub type blksize_t = ::c_int; pub type fsblkcnt64_t = ::c_ulong; pub type fsfilcnt64_t = ::c_ulong; pub type suseconds_t = i64; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct pthread_attr_t { __size: [::c_ulong; 7], } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2usize], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statfs64 { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_frsize: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 4], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt64_t, pub f_bfree: ::fsblkcnt64_t, pub f_bavail: ::fsblkcnt64_t, pub f_files: ::fsfilcnt64_t, pub f_ffree: ::fsfilcnt64_t, pub f_favail: ::fsfilcnt64_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub __f_spare: [::c_int; 6], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused5: ::c_ulong, __unused6: ::c_ulong, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct user_regs_struct { pub pc: ::c_ulong, pub ra: ::c_ulong, pub sp: ::c_ulong, pub gp: ::c_ulong, pub tp: ::c_ulong, pub t0: ::c_ulong, pub t1: ::c_ulong, pub t2: ::c_ulong, pub s0: ::c_ulong, pub s1: ::c_ulong, pub a0: ::c_ulong, pub a1: ::c_ulong, pub a2: ::c_ulong, pub a3: ::c_ulong, pub a4: ::c_ulong, pub a5: ::c_ulong, pub a6: ::c_ulong, pub a7: ::c_ulong, pub s2: ::c_ulong, pub s3: ::c_ulong, pub s4: ::c_ulong, pub s5: ::c_ulong, pub s6: ::c_ulong, pub s7: ::c_ulong, pub s8: ::c_ulong, pub s9: ::c_ulong, pub s10: ::c_ulong, pub s11: ::c_ulong, pub t3: ::c_ulong, pub t4: ::c_ulong, pub t5: ::c_ulong, pub t6: ::c_ulong, } } pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 1052672; pub const O_NOATIME: ::c_int = 262144; pub const O_PATH: ::c_int = 2097152; pub const O_TMPFILE: ::c_int = 4259840; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 256; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 134217728; pub const SA_SIGINFO: ::c_int = 4; pub const SA_NOCLDWAIT: ::c_int = 2; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const POLLWRNORM: ::c_short = 256; pub const POLLWRBAND: ::c_short = 512; pub const O_ASYNC: ::c_int = 8192; pub const O_NDELAY: ::c_int = 2048; pub const PTRACE_DETACH: ::c_uint = 17; pub const EFD_NONBLOCK: ::c_int = 2048; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const SFD_NONBLOCK: ::c_int = 2048; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const SFD_CLOEXEC: ::c_int = 524288; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_CLOEXEC: ::c_int = 524288; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 1073741824; pub const SA_RESETHAND: ::c_int = -2147483648; pub const SA_RESTART: ::c_int = 268435456; pub const SA_NOCLDSTOP: ::c_int = 1; pub const EPOLL_CLOEXEC: ::c_int = 524288; pub const EFD_CLOEXEC: ::c_int = 524288; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const O_DIRECT: ::c_int = 16384; pub const O_DIRECTORY: ::c_int = 65536; pub const O_NOFOLLOW: ::c_int = 131072; pub const MAP_HUGETLB: ::c_int = 262144; pub const MAP_LOCKED: ::c_int = 8192; pub const MAP_NORESERVE: ::c_int = 16384; pub const MAP_ANON: ::c_int = 32; pub const MAP_ANONYMOUS: ::c_int = 32; pub const MAP_DENYWRITE: ::c_int = 2048; pub const MAP_EXECUTABLE: ::c_int = 4096; pub const MAP_POPULATE: ::c_int = 32768; pub const MAP_NONBLOCK: ::c_int = 65536; pub const MAP_STACK: ::c_int = 131072; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const PTRACE_GETREGS: ::c_uint = 12; pub const PTRACE_SETREGS: ::c_uint = 13; pub const MCL_CURRENT: ::c_int = 1; pub const MCL_FUTURE: ::c_int = 2; pub const MCL_ONFAULT: ::c_int = 4; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 4111; pub const TAB1: ::tcflag_t = 2048; pub const TAB2: ::tcflag_t = 4096; pub const TAB3: ::tcflag_t = 6144; pub const CR1: ::tcflag_t = 512; pub const CR2: ::tcflag_t = 1024; pub const CR3: ::tcflag_t = 1536; pub const FF1: ::tcflag_t = 32768; pub const BS1: ::tcflag_t = 8192; pub const VT1: ::tcflag_t = 16384; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 1024; pub const IXOFF: ::tcflag_t = 4096; pub const ONLCR: ::tcflag_t = 4; pub const CSIZE: ::tcflag_t = 48; pub const CS6: ::tcflag_t = 16; pub const CS7: ::tcflag_t = 32; pub const CS8: ::tcflag_t = 48; pub const CSTOPB: ::tcflag_t = 64; pub const CREAD: ::tcflag_t = 128; pub const PARENB: ::tcflag_t = 256; pub const PARODD: ::tcflag_t = 512; pub const HUPCL: ::tcflag_t = 1024; pub const CLOCAL: ::tcflag_t = 2048; pub const ECHOKE: ::tcflag_t = 2048; pub const ECHOE: ::tcflag_t = 16; pub const ECHOK: ::tcflag_t = 32; pub const ECHONL: ::tcflag_t = 64; pub const ECHOPRT: ::tcflag_t = 1024; pub const ECHOCTL: ::tcflag_t = 512; pub const ISIG: ::tcflag_t = 1; pub const ICANON: ::tcflag_t = 2; pub const PENDIN: ::tcflag_t = 16384; pub const NOFLSH: ::tcflag_t = 128; pub const CIBAUD: ::tcflag_t = 269418496; pub const CBAUDEX: ::tcflag_t = 4096; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 2; pub const NLDLY: ::tcflag_t = 256; pub const CRDLY: ::tcflag_t = 1536; pub const TABDLY: ::tcflag_t = 6144; pub const BSDLY: ::tcflag_t = 8192; pub const FFDLY: ::tcflag_t = 32768; pub const VTDLY: ::tcflag_t = 16384; pub const XTABS: ::tcflag_t = 6144; pub const B0: ::speed_t = 0; pub const B50: ::speed_t = 1; pub const B75: ::speed_t = 2; pub const B110: ::speed_t = 3; pub const B134: ::speed_t = 4; pub const B150: ::speed_t = 5; pub const B200: ::speed_t = 6; pub const B300: ::speed_t = 7; pub const B600: ::speed_t = 8; pub const B1200: ::speed_t = 9; pub const B1800: ::speed_t = 10; pub const B2400: ::speed_t = 11; pub const B4800: ::speed_t = 12; pub const B9600: ::speed_t = 13; pub const B19200: ::speed_t = 14; pub const B38400: ::speed_t = 15; pub const EXTA: ::speed_t = 14; pub const EXTB: ::speed_t = 15; pub const B57600: ::speed_t = 4097; pub const B115200: ::speed_t = 4098; pub const B230400: ::speed_t = 4099; pub const B460800: ::speed_t = 4100; pub const B500000: ::speed_t = 4101; pub const B576000: ::speed_t = 4102; pub const B921600: ::speed_t = 4103; pub const B1000000: ::speed_t = 4104; pub const B1152000: ::speed_t = 4105; pub const B1500000: ::speed_t = 4106; pub const B2000000: ::speed_t = 4107; pub const B2500000: ::speed_t = 4108; pub const B3000000: ::speed_t = 4109; pub const B3500000: ::speed_t = 4110; pub const B4000000: ::speed_t = 4111; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 32768; pub const TOSTOP: ::tcflag_t = 256; pub const FLUSHO: ::tcflag_t = 4096; pub const EXTPROC: ::tcflag_t = 65536; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; pub const NGREG: usize = 32; pub const REG_PC: usize = 0; pub const REG_RA: usize = 1; pub const REG_SP: usize = 2; pub const REG_TP: usize = 4; pub const REG_S0: usize = 8; pub const REG_S1: usize = 9; pub const REG_A0: usize = 10; pub const REG_S2: usize = 18; pub const REG_NARGS: usize = 8; pub const COMPAT_HWCAP_ISA_I: ::c_ulong = 1 << (b'I' - b'A'); pub const COMPAT_HWCAP_ISA_M: ::c_ulong = 1 << (b'M' - b'A'); pub const COMPAT_HWCAP_ISA_A: ::c_ulong = 1 << (b'A' - b'A'); pub const COMPAT_HWCAP_ISA_F: ::c_ulong = 1 << (b'F' - b'A'); pub const COMPAT_HWCAP_ISA_D: ::c_ulong = 1 << (b'D' - b'A'); pub const COMPAT_HWCAP_ISA_C: ::c_ulong = 1 << (b'C' - b'A'); pub const COMPAT_HWCAP_ISA_V: ::c_ulong = 1 << (b'V' - b'A'); pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_close: ::c_long = 57; pub const SYS_fstat: ::c_long = 80; pub const SYS_lseek: ::c_long = 62; pub const SYS_mmap: ::c_long = 222; pub const SYS_mprotect: ::c_long = 226; pub const SYS_munmap: ::c_long = 215; pub const SYS_brk: ::c_long = 214; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_ioctl: ::c_long = 29; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_mremap: ::c_long = 216; pub const SYS_msync: ::c_long = 227; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmctl: ::c_long = 195; pub const SYS_dup: ::c_long = 23; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_getpid: ::c_long = 172; pub const SYS_sendfile: ::c_long = 71; pub const SYS_socket: ::c_long = 198; pub const SYS_connect: ::c_long = 203; pub const SYS_accept: ::c_long = 202; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_shutdown: ::c_long = 210; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_socketpair: ::c_long = 199; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_exit: ::c_long = 93; pub const SYS_wait4: ::c_long = 260; pub const SYS_kill: ::c_long = 129; pub const SYS_uname: ::c_long = 160; pub const SYS_semget: ::c_long = 190; pub const SYS_semop: ::c_long = 193; pub const SYS_semctl: ::c_long = 191; pub const SYS_shmdt: ::c_long = 197; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgctl: ::c_long = 187; pub const SYS_fcntl: ::c_long = 25; pub const SYS_flock: ::c_long = 32; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_getcwd: ::c_long = 17; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchown: ::c_long = 55; pub const SYS_umask: ::c_long = 166; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_getrusage: ::c_long = 165; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_times: ::c_long = 153; pub const SYS_ptrace: ::c_long = 117; pub const SYS_getuid: ::c_long = 174; pub const SYS_syslog: ::c_long = 116; pub const SYS_getgid: ::c_long = 176; pub const SYS_setuid: ::c_long = 146; pub const SYS_setgid: ::c_long = 144; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getegid: ::c_long = 177; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getppid: ::c_long = 173; pub const SYS_setsid: ::c_long = 157; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setregid: ::c_long = 143; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_getpgid: ::c_long = 155; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_getsid: ::c_long = 156; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_personality: ::c_long = 92; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_getpriority: ::c_long = 141; pub const SYS_setpriority: ::c_long = 140; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_prctl: ::c_long = 167; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_chroot: ::c_long = 51; pub const SYS_sync: ::c_long = 81; pub const SYS_acct: ::c_long = 89; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_mount: ::c_long = 40; pub const SYS_umount2: ::c_long = 39; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_reboot: ::c_long = 142; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_quotactl: ::c_long = 60; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_gettid: ::c_long = 178; pub const SYS_readahead: ::c_long = 213; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_tkill: ::c_long = 130; pub const SYS_futex: ::c_long = 98; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_getdents64: ::c_long = 61; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_fadvise64: ::c_long = 223; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_exit_group: ::c_long = 94; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_tgkill: ::c_long = 131; pub const SYS_mbind: ::c_long = 235; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_waitid: ::c_long = 95; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_openat: ::c_long = 56; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_mknodat: ::c_long = 33; pub const SYS_fchownat: ::c_long = 54; pub const SYS_newfstatat: ::c_long = 79; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_linkat: ::c_long = 37; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_faccessat: ::c_long = 48; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_unshare: ::c_long = 97; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_move_pages: ::c_long = 239; pub const SYS_utimensat: ::c_long = 88; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_fallocate: ::c_long = 47; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_accept4: ::c_long = 242; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_dup3: ::c_long = 24; pub const SYS_pipe2: ::c_long = 59; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_setns: ::c_long = 268; pub const SYS_getcpu: ::c_long = 168; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_rseq: ::c_long = 293; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b64/riscv64/align.rs0000644000175000017500000000227514661133735023660 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct ucontext_t { pub __uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct mcontext_t { pub __gregs: [::c_ulong; 32], pub __fpregs: __riscv_mc_fp_state, } #[allow(missing_debug_implementations)] pub union __riscv_mc_fp_state { pub __f: __riscv_mc_f_ext_state, pub __d: __riscv_mc_d_ext_state, pub __q: __riscv_mc_q_ext_state, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_f_ext_state { pub __f: [::c_uint; 32], pub __fcsr: ::c_uint, } #[allow(missing_debug_implementations)] pub struct __riscv_mc_d_ext_state { pub __f: [::c_ulonglong; 32], pub __fcsr: ::c_uint, } #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct __riscv_mc_q_ext_state { pub __f: [::c_ulonglong; 64], pub __fcsr: ::c_uint, pub __glibc_reserved: [::c_uint; 3], } } libc/src/unix/linux_like/linux/gnu/b64/mod.rs0000644000175000017500000000727414661133735022051 0ustar jamespagejamespage//! 64-bit specific definitions for linux-like values pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = i64; pub type shmatt_t = u64; pub type msgqnum_t = u64; pub type msglen_t = u64; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type rlim_t = u64; #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub type __syscall_ulong_t = ::c_ulonglong; #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub type __syscall_ulong_t = ::c_ulong; cfg_if! { if #[cfg(all(target_arch = "aarch64", target_pointer_width = "32"))] { pub type clock_t = i32; pub type time_t = i32; pub type __fsword_t = i32; } else { pub type __fsword_t = i64; pub type clock_t = i64; pub type time_t = i64; } } s! { pub struct sigset_t { #[cfg(target_pointer_width = "32")] __val: [u32; 32], #[cfg(target_pointer_width = "64")] __val: [u64; 16], } pub struct sysinfo { pub uptime: i64, pub loads: [u64; 3], pub totalram: u64, pub freeram: u64, pub sharedram: u64, pub bufferram: u64, pub totalswap: u64, pub freeswap: u64, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: u64, pub freehigh: u64, pub mem_unit: ::c_uint, pub _f: [::c_char; 0], } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, __msg_cbytes: u64, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, __glibc_reserved4: u64, __glibc_reserved5: u64, } pub struct semid_ds { pub sem_perm: ipc_perm, pub sem_otime: ::time_t, #[cfg(not(any( target_arch = "aarch64", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "sparc64")))] __reserved: ::__syscall_ulong_t, pub sem_ctime: ::time_t, #[cfg(not(any( target_arch = "aarch64", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "sparc64")))] __reserved2: ::__syscall_ulong_t, pub sem_nsems: ::__syscall_ulong_t, __glibc_reserved3: ::__syscall_ulong_t, __glibc_reserved4: ::__syscall_ulong_t, } } pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const O_LARGEFILE: ::c_int = 0; cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(any(target_arch = "powerpc64"))] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(any(target_arch = "sparc64"))] { mod sparc64; pub use self::sparc64::*; } else if #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))] { mod mips64; pub use self::mips64::*; } else if #[cfg(any(target_arch = "s390x"))] { mod s390x; pub use self::s390x::*; } else if #[cfg(any(target_arch = "x86_64"))] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(any(target_arch = "riscv64"))] { mod riscv64; pub use self::riscv64::*; } else if #[cfg(any(target_arch = "loongarch64"))] { mod loongarch64; pub use self::loongarch64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/linux/gnu/b64/s390x.rs0000644000175000017500000010050114661133735022143 0ustar jamespagejamespage//! s390x use pthread_mutex_t; pub type blksize_t = i64; pub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type nlink_t = u64; pub type suseconds_t = i64; pub type wchar_t = i32; pub type greg_t = u64; pub type __u64 = u64; pub type __s64 = i64; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, __glibc_reserved0: ::c_int, pub sa_flags: ::c_int, pub sa_restorer: ::Option, pub sa_mask: ::sigset_t, } pub struct statfs { pub f_type: ::c_uint, pub f_bsize: ::c_uint, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_uint, pub f_frsize: ::c_uint, pub f_flags: ::c_uint, f_spare: [::c_uint; 4], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, _pad: ::c_int, _pad2: [::c_long; 14], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, st_pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, __glibc_reserved: [::c_long; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, st_pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, __glibc_reserved: [::c_long; 3], } pub struct pthread_attr_t { __size: [::c_ulong; 7] } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub __seq: ::c_ushort, __pad1: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct __psw_t { pub mask: u64, pub addr: u64, } pub struct fpregset_t { pub fpc: u32, __pad: u32, pub fprs: [fpreg_t; 16], } pub struct mcontext_t { pub psw: __psw_t, pub gregs: [u64; 16], pub aregs: [u32; 16], pub fpregs: fpregset_t, } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: ::sigset_t, } pub struct statfs64 { pub f_type: ::c_uint, pub f_bsize: ::c_uint, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::c_uint, pub f_frsize: ::c_uint, pub f_flags: ::c_uint, pub f_spare: [::c_uint; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } } s_no_extra_traits! { // FIXME: This is actually a union. pub struct fpreg_t { pub d: ::c_double, // f: ::c_float, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpreg_t { fn eq(&self, other: &fpreg_t) -> bool { self.d == other.d } } impl Eq for fpreg_t {} impl ::fmt::Debug for fpreg_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpreg_t") .field("d", &self.d) .finish() } } impl ::hash::Hash for fpreg_t { fn hash(&self, state: &mut H) { let d: u64 = unsafe { ::mem::transmute(self.d) }; d.hash(state); } } } } pub const POSIX_FADV_DONTNEED: ::c_int = 6; pub const POSIX_FADV_NOREUSE: ::c_int = 7; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_CLOEXEC: ::c_int = 0x80000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; align_const! { pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ECONNABORTED: ::c_int = 103; pub const ECONNREFUSED: ::c_int = 111; pub const ECONNRESET: ::c_int = 104; pub const EDEADLK: ::c_int = 35; pub const ENOSYS: ::c_int = 38; pub const ENOTCONN: ::c_int = 107; pub const ETIMEDOUT: ::c_int = 110; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NONBLOCK: ::c_int = 2048; pub const SA_NOCLDWAIT: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 4; pub const SIGBUS: ::c_int = 7; pub const SIGSTKSZ: ::size_t = 0x2000; pub const MINSIGSTKSZ: ::size_t = 2048; pub const SIG_SETMASK: ::c_int = 2; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const O_NOCTTY: ::c_int = 256; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const PTRACE_DETACH: ::c_uint = 17; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const VTIME: usize = 5; pub const VSWTC: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const OLCUC: ::tcflag_t = 0o000002; pub const ONLCR: ::tcflag_t = 0o000004; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const TABDLY: ::tcflag_t = 0o014000; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const BSDLY: ::tcflag_t = 0o020000; pub const BS1: ::tcflag_t = 0x00002000; pub const FFDLY: ::tcflag_t = 0o100000; pub const FF1: ::tcflag_t = 0x00008000; pub const VTDLY: ::tcflag_t = 0o040000; pub const VT1: ::tcflag_t = 0x00004000; pub const XTABS: ::tcflag_t = 0o014000; pub const CBAUD: ::speed_t = 0o010017; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const CSIZE: ::tcflag_t = 0o000060; pub const CS6: ::tcflag_t = 0o000020; pub const CS7: ::tcflag_t = 0o000040; pub const CS8: ::tcflag_t = 0o000060; pub const CSTOPB: ::tcflag_t = 0o000100; pub const CREAD: ::tcflag_t = 0o000200; pub const PARENB: ::tcflag_t = 0o000400; pub const PARODD: ::tcflag_t = 0o001000; pub const HUPCL: ::tcflag_t = 0o002000; pub const CLOCAL: ::tcflag_t = 0o004000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const ISIG: ::tcflag_t = 0o000001; pub const ICANON: ::tcflag_t = 0o000002; pub const XCASE: ::tcflag_t = 0o000004; pub const ECHOE: ::tcflag_t = 0o000020; pub const ECHOK: ::tcflag_t = 0o000040; pub const ECHONL: ::tcflag_t = 0o000100; pub const NOFLSH: ::tcflag_t = 0o000200; pub const ECHOCTL: ::tcflag_t = 0o001000; pub const ECHOPRT: ::tcflag_t = 0o002000; pub const ECHOKE: ::tcflag_t = 0o004000; pub const PENDIN: ::tcflag_t = 0o040000; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const IXON: ::tcflag_t = 0o002000; pub const IXOFF: ::tcflag_t = 0o010000; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_restart_syscall: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_brk: ::c_long = 45; pub const SYS_signal: ::c_long = 48; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_setpgid: ::c_long = 57; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_symlink: ::c_long = 83; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_lookup_dcookie: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; /* Syscall for Andrew File System */ pub const SYS_getdents: ::c_long = 141; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_query_module: ::c_long = 167; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_getpmsg: ::c_long = 188; pub const SYS_putpmsg: ::c_long = 189; pub const SYS_vfork: ::c_long = 190; pub const SYS_pivot_root: ::c_long = 217; pub const SYS_mincore: ::c_long = 218; pub const SYS_madvise: ::c_long = 219; pub const SYS_getdents64: ::c_long = 220; pub const SYS_readahead: ::c_long = 222; pub const SYS_setxattr: ::c_long = 224; pub const SYS_lsetxattr: ::c_long = 225; pub const SYS_fsetxattr: ::c_long = 226; pub const SYS_getxattr: ::c_long = 227; pub const SYS_lgetxattr: ::c_long = 228; pub const SYS_fgetxattr: ::c_long = 229; pub const SYS_listxattr: ::c_long = 230; pub const SYS_llistxattr: ::c_long = 231; pub const SYS_flistxattr: ::c_long = 232; pub const SYS_removexattr: ::c_long = 233; pub const SYS_lremovexattr: ::c_long = 234; pub const SYS_fremovexattr: ::c_long = 235; pub const SYS_gettid: ::c_long = 236; pub const SYS_tkill: ::c_long = 237; pub const SYS_futex: ::c_long = 238; pub const SYS_sched_setaffinity: ::c_long = 239; pub const SYS_sched_getaffinity: ::c_long = 240; pub const SYS_tgkill: ::c_long = 241; pub const SYS_io_setup: ::c_long = 243; pub const SYS_io_destroy: ::c_long = 244; pub const SYS_io_getevents: ::c_long = 245; pub const SYS_io_submit: ::c_long = 246; pub const SYS_io_cancel: ::c_long = 247; pub const SYS_exit_group: ::c_long = 248; pub const SYS_epoll_create: ::c_long = 249; pub const SYS_epoll_ctl: ::c_long = 250; pub const SYS_epoll_wait: ::c_long = 251; pub const SYS_set_tid_address: ::c_long = 252; pub const SYS_fadvise64: ::c_long = 253; pub const SYS_timer_create: ::c_long = 254; pub const SYS_timer_settime: ::c_long = 255; pub const SYS_timer_gettime: ::c_long = 256; pub const SYS_timer_getoverrun: ::c_long = 257; pub const SYS_timer_delete: ::c_long = 258; pub const SYS_clock_settime: ::c_long = 259; pub const SYS_clock_gettime: ::c_long = 260; pub const SYS_clock_getres: ::c_long = 261; pub const SYS_clock_nanosleep: ::c_long = 262; pub const SYS_statfs64: ::c_long = 265; pub const SYS_fstatfs64: ::c_long = 266; pub const SYS_remap_file_pages: ::c_long = 267; pub const SYS_mbind: ::c_long = 268; pub const SYS_get_mempolicy: ::c_long = 269; pub const SYS_set_mempolicy: ::c_long = 270; pub const SYS_mq_open: ::c_long = 271; pub const SYS_mq_unlink: ::c_long = 272; pub const SYS_mq_timedsend: ::c_long = 273; pub const SYS_mq_timedreceive: ::c_long = 274; pub const SYS_mq_notify: ::c_long = 275; pub const SYS_mq_getsetattr: ::c_long = 276; pub const SYS_kexec_load: ::c_long = 277; pub const SYS_add_key: ::c_long = 278; pub const SYS_request_key: ::c_long = 279; pub const SYS_keyctl: ::c_long = 280; pub const SYS_waitid: ::c_long = 281; pub const SYS_ioprio_set: ::c_long = 282; pub const SYS_ioprio_get: ::c_long = 283; pub const SYS_inotify_init: ::c_long = 284; pub const SYS_inotify_add_watch: ::c_long = 285; pub const SYS_inotify_rm_watch: ::c_long = 286; pub const SYS_migrate_pages: ::c_long = 287; pub const SYS_openat: ::c_long = 288; pub const SYS_mkdirat: ::c_long = 289; pub const SYS_mknodat: ::c_long = 290; pub const SYS_fchownat: ::c_long = 291; pub const SYS_futimesat: ::c_long = 292; pub const SYS_unlinkat: ::c_long = 294; pub const SYS_renameat: ::c_long = 295; pub const SYS_linkat: ::c_long = 296; pub const SYS_symlinkat: ::c_long = 297; pub const SYS_readlinkat: ::c_long = 298; pub const SYS_fchmodat: ::c_long = 299; pub const SYS_faccessat: ::c_long = 300; pub const SYS_pselect6: ::c_long = 301; pub const SYS_ppoll: ::c_long = 302; pub const SYS_unshare: ::c_long = 303; pub const SYS_set_robust_list: ::c_long = 304; pub const SYS_get_robust_list: ::c_long = 305; pub const SYS_splice: ::c_long = 306; pub const SYS_sync_file_range: ::c_long = 307; pub const SYS_tee: ::c_long = 308; pub const SYS_vmsplice: ::c_long = 309; pub const SYS_move_pages: ::c_long = 310; pub const SYS_getcpu: ::c_long = 311; pub const SYS_epoll_pwait: ::c_long = 312; pub const SYS_utimes: ::c_long = 313; pub const SYS_fallocate: ::c_long = 314; pub const SYS_utimensat: ::c_long = 315; pub const SYS_signalfd: ::c_long = 316; pub const SYS_timerfd: ::c_long = 317; pub const SYS_eventfd: ::c_long = 318; pub const SYS_timerfd_create: ::c_long = 319; pub const SYS_timerfd_settime: ::c_long = 320; pub const SYS_timerfd_gettime: ::c_long = 321; pub const SYS_signalfd4: ::c_long = 322; pub const SYS_eventfd2: ::c_long = 323; pub const SYS_inotify_init1: ::c_long = 324; pub const SYS_pipe2: ::c_long = 325; pub const SYS_dup3: ::c_long = 326; pub const SYS_epoll_create1: ::c_long = 327; pub const SYS_preadv: ::c_long = 328; pub const SYS_pwritev: ::c_long = 329; pub const SYS_rt_tgsigqueueinfo: ::c_long = 330; pub const SYS_perf_event_open: ::c_long = 331; pub const SYS_fanotify_init: ::c_long = 332; pub const SYS_fanotify_mark: ::c_long = 333; pub const SYS_prlimit64: ::c_long = 334; pub const SYS_name_to_handle_at: ::c_long = 335; pub const SYS_open_by_handle_at: ::c_long = 336; pub const SYS_clock_adjtime: ::c_long = 337; pub const SYS_syncfs: ::c_long = 338; pub const SYS_setns: ::c_long = 339; pub const SYS_process_vm_readv: ::c_long = 340; pub const SYS_process_vm_writev: ::c_long = 341; pub const SYS_s390_runtime_instr: ::c_long = 342; pub const SYS_kcmp: ::c_long = 343; pub const SYS_finit_module: ::c_long = 344; pub const SYS_sched_setattr: ::c_long = 345; pub const SYS_sched_getattr: ::c_long = 346; pub const SYS_renameat2: ::c_long = 347; pub const SYS_seccomp: ::c_long = 348; pub const SYS_getrandom: ::c_long = 349; pub const SYS_memfd_create: ::c_long = 350; pub const SYS_bpf: ::c_long = 351; pub const SYS_s390_pci_mmio_write: ::c_long = 352; pub const SYS_s390_pci_mmio_read: ::c_long = 353; pub const SYS_execveat: ::c_long = 354; pub const SYS_userfaultfd: ::c_long = 355; pub const SYS_membarrier: ::c_long = 356; pub const SYS_recvmmsg: ::c_long = 357; pub const SYS_sendmmsg: ::c_long = 358; pub const SYS_socket: ::c_long = 359; pub const SYS_socketpair: ::c_long = 360; pub const SYS_bind: ::c_long = 361; pub const SYS_connect: ::c_long = 362; pub const SYS_listen: ::c_long = 363; pub const SYS_accept4: ::c_long = 364; pub const SYS_getsockopt: ::c_long = 365; pub const SYS_setsockopt: ::c_long = 366; pub const SYS_getsockname: ::c_long = 367; pub const SYS_getpeername: ::c_long = 368; pub const SYS_sendto: ::c_long = 369; pub const SYS_sendmsg: ::c_long = 370; pub const SYS_recvfrom: ::c_long = 371; pub const SYS_recvmsg: ::c_long = 372; pub const SYS_shutdown: ::c_long = 373; pub const SYS_mlock2: ::c_long = 374; pub const SYS_copy_file_range: ::c_long = 375; pub const SYS_preadv2: ::c_long = 376; pub const SYS_pwritev2: ::c_long = 377; pub const SYS_lchown: ::c_long = 198; pub const SYS_setuid: ::c_long = 213; pub const SYS_getuid: ::c_long = 199; pub const SYS_setgid: ::c_long = 214; pub const SYS_getgid: ::c_long = 200; pub const SYS_geteuid: ::c_long = 201; pub const SYS_setreuid: ::c_long = 203; pub const SYS_setregid: ::c_long = 204; pub const SYS_getrlimit: ::c_long = 191; pub const SYS_getgroups: ::c_long = 205; pub const SYS_fchown: ::c_long = 207; pub const SYS_setresuid: ::c_long = 208; pub const SYS_setresgid: ::c_long = 210; pub const SYS_getresgid: ::c_long = 211; pub const SYS_select: ::c_long = 142; pub const SYS_getegid: ::c_long = 202; pub const SYS_setgroups: ::c_long = 206; pub const SYS_getresuid: ::c_long = 209; pub const SYS_chown: ::c_long = 212; pub const SYS_setfsuid: ::c_long = 215; pub const SYS_setfsgid: ::c_long = 216; pub const SYS_newfstatat: ::c_long = 293; pub const SYS_statx: ::c_long = 379; pub const SYS_rseq: ::c_long = 383; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn getcontext(ucp: *mut ::ucontext_t) -> ::c_int; pub fn setcontext(ucp: *const ::ucontext_t) -> ::c_int; pub fn makecontext(ucp: *mut ::ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); pub fn swapcontext(uocp: *mut ::ucontext_t, ucp: *const ::ucontext_t) -> ::c_int; } libc/src/unix/linux_like/linux/gnu/b64/loongarch64/0000775000175000017500000000000014661133735023042 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs0000644000175000017500000007653114661133735024201 0ustar jamespagejamespageuse pthread_mutex_t; pub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = i32; pub type blksize_t = i32; pub type nlink_t = u32; pub type suseconds_t = i64; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub __pad1: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::blksize_t, pub __pad2: ::c_int, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused: [::c_int; 2], } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_attr_t { __size: [::c_ulong; 7] } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [u64; 0], } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_uint, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } pub struct user_regs_struct { pub regs: [u64; 32], pub orig_a0: u64, pub csr_era: u64, pub csr_badv: u64, pub reserved: [u64; 10], } pub struct user_fp_struct { pub fpr: [u64; 32], pub fcc: u64, pub fcsr: u32, } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; align_const! { #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const HWCAP_LOONGARCH_CPUCFG: ::c_ulong = 1 << 0; pub const HWCAP_LOONGARCH_LAM: ::c_ulong = 1 << 1; pub const HWCAP_LOONGARCH_UAL: ::c_ulong = 1 << 2; pub const HWCAP_LOONGARCH_FPU: ::c_ulong = 1 << 3; pub const HWCAP_LOONGARCH_LSX: ::c_ulong = 1 << 4; pub const HWCAP_LOONGARCH_LASX: ::c_ulong = 1 << 5; pub const HWCAP_LOONGARCH_CRC32: ::c_ulong = 1 << 6; pub const HWCAP_LOONGARCH_COMPLEX: ::c_ulong = 1 << 7; pub const HWCAP_LOONGARCH_CRYPTO: ::c_ulong = 1 << 8; pub const HWCAP_LOONGARCH_LVZ: ::c_ulong = 1 << 9; pub const HWCAP_LOONGARCH_LBT_X86: ::c_ulong = 1 << 10; pub const HWCAP_LOONGARCH_LBT_ARM: ::c_ulong = 1 << 11; pub const HWCAP_LOONGARCH_LBT_MIPS: ::c_ulong = 1 << 12; pub const HWCAP_LOONGARCH_PTW: ::c_ulong = 1 << 13; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_getcwd: ::c_long = 17; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_dup: ::c_long = 23; pub const SYS_dup3: ::c_long = 24; pub const SYS_fcntl: ::c_long = 25; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_ioctl: ::c_long = 29; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_flock: ::c_long = 32; pub const SYS_mknodat: ::c_long = 33; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_linkat: ::c_long = 37; pub const SYS_umount2: ::c_long = 39; pub const SYS_mount: ::c_long = 40; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_statfs: ::c_long = 43; pub const SYS_fstatfs: ::c_long = 44; pub const SYS_truncate: ::c_long = 45; pub const SYS_ftruncate: ::c_long = 46; pub const SYS_fallocate: ::c_long = 47; pub const SYS_faccessat: ::c_long = 48; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_chroot: ::c_long = 51; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_fchownat: ::c_long = 54; pub const SYS_fchown: ::c_long = 55; pub const SYS_openat: ::c_long = 56; pub const SYS_close: ::c_long = 57; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pipe2: ::c_long = 59; pub const SYS_quotactl: ::c_long = 60; pub const SYS_getdents64: ::c_long = 61; pub const SYS_lseek: ::c_long = 62; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_sendfile: ::c_long = 71; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_sync: ::c_long = 81; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_utimensat: ::c_long = 88; pub const SYS_acct: ::c_long = 89; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_personality: ::c_long = 92; pub const SYS_exit: ::c_long = 93; pub const SYS_exit_group: ::c_long = 94; pub const SYS_waitid: ::c_long = 95; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_unshare: ::c_long = 97; pub const SYS_futex: ::c_long = 98; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_syslog: ::c_long = 116; pub const SYS_ptrace: ::c_long = 117; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_kill: ::c_long = 129; pub const SYS_tkill: ::c_long = 130; pub const SYS_tgkill: ::c_long = 131; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_setpriority: ::c_long = 140; pub const SYS_getpriority: ::c_long = 141; pub const SYS_reboot: ::c_long = 142; pub const SYS_setregid: ::c_long = 143; pub const SYS_setgid: ::c_long = 144; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setuid: ::c_long = 146; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_times: ::c_long = 153; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getpgid: ::c_long = 155; pub const SYS_getsid: ::c_long = 156; pub const SYS_setsid: ::c_long = 157; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_uname: ::c_long = 160; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_getrusage: ::c_long = 165; pub const SYS_umask: ::c_long = 166; pub const SYS_prctl: ::c_long = 167; pub const SYS_getcpu: ::c_long = 168; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_getpid: ::c_long = 172; pub const SYS_getppid: ::c_long = 173; pub const SYS_getuid: ::c_long = 174; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getgid: ::c_long = 176; pub const SYS_getegid: ::c_long = 177; pub const SYS_gettid: ::c_long = 178; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgctl: ::c_long = 187; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_semget: ::c_long = 190; pub const SYS_semctl: ::c_long = 191; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_semop: ::c_long = 193; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmctl: ::c_long = 195; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmdt: ::c_long = 197; pub const SYS_socket: ::c_long = 198; pub const SYS_socketpair: ::c_long = 199; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_accept: ::c_long = 202; pub const SYS_connect: ::c_long = 203; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_shutdown: ::c_long = 210; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_readahead: ::c_long = 213; pub const SYS_brk: ::c_long = 214; pub const SYS_munmap: ::c_long = 215; pub const SYS_mremap: ::c_long = 216; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_mmap: ::c_long = 222; pub const SYS_fadvise64: ::c_long = 223; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_mprotect: ::c_long = 226; pub const SYS_msync: ::c_long = 227; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_mbind: ::c_long = 235; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_move_pages: ::c_long = 239; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_accept4: ::c_long = 242; pub const SYS_recvmmsg: ::c_long = 243; //pub const SYS_arch_specific_syscall: ::c_long = 244; pub const SYS_wait4: ::c_long = 260; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_setns: ::c_long = 268; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_io_pgetevents: ::c_long = 292; pub const SYS_rseq: ::c_long = 293; pub const SYS_kexec_file_load: ::c_long = 294; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const O_DIRECT: ::c_int = 0o00040000; pub const O_DIRECTORY: ::c_int = 0o00200000; pub const O_NOFOLLOW: ::c_int = 0o00400000; pub const O_TRUNC: ::c_int = 0o00001000; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_CLOEXEC: ::c_int = 0o02000000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const O_APPEND: ::c_int = 0o00002000; pub const O_CREAT: ::c_int = 0o00000100; pub const O_EXCL: ::c_int = 0o00000200; pub const O_NOCTTY: ::c_int = 0o00000400; pub const O_NONBLOCK: ::c_int = 0o00004000; pub const FASYNC: ::c_int = 0o00020000; pub const O_SYNC: ::c_int = 0o04010000; pub const O_RSYNC: ::c_int = 0o04010000; pub const O_FSYNC: ::c_int = O_SYNC; pub const O_ASYNC: ::c_int = 0o00020000; pub const O_DSYNC: ::c_int = 0o00010000; pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const F_GETLK: ::c_int = 5; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_SETOWN: ::c_int = 8; pub const F_GETOWN: ::c_int = 9; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const EDEADLK: ::c_int = 35; pub const EDEADLOCK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const ERFKILL: ::c_int = 132; pub const EHWPOISON: ::c_int = 133; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_NORESERVE: ::c_int = 0x4000; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x1000; pub const MAP_LOCKED: ::c_int = 0x2000; pub const MAP_POPULATE: ::c_int = 0x8000; pub const MAP_NONBLOCK: ::c_int = 0x10000; pub const MAP_STACK: ::c_int = 0x20000; pub const MAP_HUGETLB: ::c_int = 0x40000; pub const MAP_SYNC: ::c_int = 0x080000; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SFD_NONBLOCK: ::c_int = 0x800; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const SIG_SETMASK: ::c_int = 2; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGSTKFLT: ::c_int = 16; pub const SIGCHLD: ::c_int = 17; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGURG: ::c_int = 23; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGIO: ::c_int = 29; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIGSYS: ::c_int = 31; pub const SIGUNUSED: ::c_int = 31; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; pub const PTRACE_DETACH: ::c_uint = 17; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const PTRACE_GETREGS: ::c_uint = 12; pub const PTRACE_SETREGS: ::c_uint = 13; pub const PTRACE_SYSEMU: ::c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_uint = 32; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const VEOF: usize = 4; pub const VTIME: usize = 5; pub const VMIN: usize = 6; pub const VSWTC: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VEOL: usize = 11; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const VEOL2: usize = 16; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const SIGSTKSZ: ::size_t = 16384; pub const MINSIGSTKSZ: ::size_t = 4096; pub const CBAUD: ::tcflag_t = 0o0010017; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const VT1: ::tcflag_t = 0x00004000; pub const ONLCR: ::tcflag_t = 0x4; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const XCASE: ::tcflag_t = 0x00000004; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const NCCS: usize = 32; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const EFD_NONBLOCK: ::c_int = 0x800; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs0000644000175000017500000000201514661133735024476 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } s! { pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub __pc: ::c_ulonglong, pub __gregs: [::c_ulonglong; 32], pub __flags: ::c_uint, pub __extcontext: [::c_ulonglong; 0], } #[repr(align(8))] pub struct clone_args { pub flags: ::c_ulonglong, pub pidfd: ::c_ulonglong, pub child_tid: ::c_ulonglong, pub parent_tid: ::c_ulonglong, pub exit_signal: ::c_ulonglong, pub stack: ::c_ulonglong, pub stack_size: ::c_ulonglong, pub tls: ::c_ulonglong, pub set_tid: ::c_ulonglong, pub set_tid_size: ::c_ulonglong, pub cgroup: ::c_ulonglong, } } libc/src/unix/linux_like/linux/gnu/b64/mips64/0000775000175000017500000000000014661133735022036 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs0000644000175000017500000010454414661133735023171 0ustar jamespagejamespageuse pthread_mutex_t; pub type blksize_t = i64; pub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; pub type nlink_t = u64; pub type suseconds_t = i64; pub type wchar_t = i32; pub type __u64 = ::c_ulong; pub type __s64 = ::c_long; s! { pub struct stat { pub st_dev: ::c_ulong, st_pad1: [::c_long; 2], pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulong, st_pad2: [::c_ulong; 1], pub st_size: ::off_t, st_pad3: ::c_long, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, st_pad4: ::c_long, pub st_blocks: ::blkcnt_t, st_pad5: [::c_long; 7], } pub struct statfs { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_frsize: ::c_long, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_files: ::fsblkcnt_t, pub f_ffree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, f_spare: [::c_long; 6], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct stat64 { pub st_dev: ::c_ulong, st_pad1: [::c_long; 2], pub st_ino: ::ino64_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulong, st_pad2: [::c_long; 2], pub st_size: ::off64_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, st_pad3: ::c_long, pub st_blocks: ::blkcnt64_t, st_pad5: [::c_long; 7], } pub struct statfs64 { pub f_type: ::c_long, pub f_bsize: ::c_long, pub f_frsize: ::c_long, pub f_blocks: u64, pub f_bfree: u64, pub f_files: u64, pub f_ffree: u64, pub f_bavail: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::c_long, pub f_flags: ::c_long, pub f_spare: [::c_long; 5], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_attr_t { __size: [::c_ulong; 7] } pub struct sigaction { pub sa_flags: ::c_int, pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_restorer: ::Option, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, _pad: ::c_int, _pad2: [::c_long; 14], } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_uint, pub __seq: ::c_ushort, __pad1: ::c_ushort, __unused1: ::c_ulong, __unused2: ::c_ulong } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: ::c_ulong, __unused5: ::c_ulong } } pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; align_const! { #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } pub const SYS_read: ::c_long = 5000 + 0; pub const SYS_write: ::c_long = 5000 + 1; pub const SYS_open: ::c_long = 5000 + 2; pub const SYS_close: ::c_long = 5000 + 3; pub const SYS_stat: ::c_long = 5000 + 4; pub const SYS_fstat: ::c_long = 5000 + 5; pub const SYS_lstat: ::c_long = 5000 + 6; pub const SYS_poll: ::c_long = 5000 + 7; pub const SYS_lseek: ::c_long = 5000 + 8; pub const SYS_mmap: ::c_long = 5000 + 9; pub const SYS_mprotect: ::c_long = 5000 + 10; pub const SYS_munmap: ::c_long = 5000 + 11; pub const SYS_brk: ::c_long = 5000 + 12; pub const SYS_rt_sigaction: ::c_long = 5000 + 13; pub const SYS_rt_sigprocmask: ::c_long = 5000 + 14; pub const SYS_ioctl: ::c_long = 5000 + 15; pub const SYS_pread64: ::c_long = 5000 + 16; pub const SYS_pwrite64: ::c_long = 5000 + 17; pub const SYS_readv: ::c_long = 5000 + 18; pub const SYS_writev: ::c_long = 5000 + 19; pub const SYS_access: ::c_long = 5000 + 20; pub const SYS_pipe: ::c_long = 5000 + 21; pub const SYS__newselect: ::c_long = 5000 + 22; pub const SYS_sched_yield: ::c_long = 5000 + 23; pub const SYS_mremap: ::c_long = 5000 + 24; pub const SYS_msync: ::c_long = 5000 + 25; pub const SYS_mincore: ::c_long = 5000 + 26; pub const SYS_madvise: ::c_long = 5000 + 27; pub const SYS_shmget: ::c_long = 5000 + 28; pub const SYS_shmat: ::c_long = 5000 + 29; pub const SYS_shmctl: ::c_long = 5000 + 30; pub const SYS_dup: ::c_long = 5000 + 31; pub const SYS_dup2: ::c_long = 5000 + 32; pub const SYS_pause: ::c_long = 5000 + 33; pub const SYS_nanosleep: ::c_long = 5000 + 34; pub const SYS_getitimer: ::c_long = 5000 + 35; pub const SYS_setitimer: ::c_long = 5000 + 36; pub const SYS_alarm: ::c_long = 5000 + 37; pub const SYS_getpid: ::c_long = 5000 + 38; pub const SYS_sendfile: ::c_long = 5000 + 39; pub const SYS_socket: ::c_long = 5000 + 40; pub const SYS_connect: ::c_long = 5000 + 41; pub const SYS_accept: ::c_long = 5000 + 42; pub const SYS_sendto: ::c_long = 5000 + 43; pub const SYS_recvfrom: ::c_long = 5000 + 44; pub const SYS_sendmsg: ::c_long = 5000 + 45; pub const SYS_recvmsg: ::c_long = 5000 + 46; pub const SYS_shutdown: ::c_long = 5000 + 47; pub const SYS_bind: ::c_long = 5000 + 48; pub const SYS_listen: ::c_long = 5000 + 49; pub const SYS_getsockname: ::c_long = 5000 + 50; pub const SYS_getpeername: ::c_long = 5000 + 51; pub const SYS_socketpair: ::c_long = 5000 + 52; pub const SYS_setsockopt: ::c_long = 5000 + 53; pub const SYS_getsockopt: ::c_long = 5000 + 54; pub const SYS_clone: ::c_long = 5000 + 55; pub const SYS_fork: ::c_long = 5000 + 56; pub const SYS_execve: ::c_long = 5000 + 57; pub const SYS_exit: ::c_long = 5000 + 58; pub const SYS_wait4: ::c_long = 5000 + 59; pub const SYS_kill: ::c_long = 5000 + 60; pub const SYS_uname: ::c_long = 5000 + 61; pub const SYS_semget: ::c_long = 5000 + 62; pub const SYS_semop: ::c_long = 5000 + 63; pub const SYS_semctl: ::c_long = 5000 + 64; pub const SYS_shmdt: ::c_long = 5000 + 65; pub const SYS_msgget: ::c_long = 5000 + 66; pub const SYS_msgsnd: ::c_long = 5000 + 67; pub const SYS_msgrcv: ::c_long = 5000 + 68; pub const SYS_msgctl: ::c_long = 5000 + 69; pub const SYS_fcntl: ::c_long = 5000 + 70; pub const SYS_flock: ::c_long = 5000 + 71; pub const SYS_fsync: ::c_long = 5000 + 72; pub const SYS_fdatasync: ::c_long = 5000 + 73; pub const SYS_truncate: ::c_long = 5000 + 74; pub const SYS_ftruncate: ::c_long = 5000 + 75; pub const SYS_getdents: ::c_long = 5000 + 76; pub const SYS_getcwd: ::c_long = 5000 + 77; pub const SYS_chdir: ::c_long = 5000 + 78; pub const SYS_fchdir: ::c_long = 5000 + 79; pub const SYS_rename: ::c_long = 5000 + 80; pub const SYS_mkdir: ::c_long = 5000 + 81; pub const SYS_rmdir: ::c_long = 5000 + 82; pub const SYS_creat: ::c_long = 5000 + 83; pub const SYS_link: ::c_long = 5000 + 84; pub const SYS_unlink: ::c_long = 5000 + 85; pub const SYS_symlink: ::c_long = 5000 + 86; pub const SYS_readlink: ::c_long = 5000 + 87; pub const SYS_chmod: ::c_long = 5000 + 88; pub const SYS_fchmod: ::c_long = 5000 + 89; pub const SYS_chown: ::c_long = 5000 + 90; pub const SYS_fchown: ::c_long = 5000 + 91; pub const SYS_lchown: ::c_long = 5000 + 92; pub const SYS_umask: ::c_long = 5000 + 93; pub const SYS_gettimeofday: ::c_long = 5000 + 94; pub const SYS_getrlimit: ::c_long = 5000 + 95; pub const SYS_getrusage: ::c_long = 5000 + 96; pub const SYS_sysinfo: ::c_long = 5000 + 97; pub const SYS_times: ::c_long = 5000 + 98; pub const SYS_ptrace: ::c_long = 5000 + 99; pub const SYS_getuid: ::c_long = 5000 + 100; pub const SYS_syslog: ::c_long = 5000 + 101; pub const SYS_getgid: ::c_long = 5000 + 102; pub const SYS_setuid: ::c_long = 5000 + 103; pub const SYS_setgid: ::c_long = 5000 + 104; pub const SYS_geteuid: ::c_long = 5000 + 105; pub const SYS_getegid: ::c_long = 5000 + 106; pub const SYS_setpgid: ::c_long = 5000 + 107; pub const SYS_getppid: ::c_long = 5000 + 108; pub const SYS_getpgrp: ::c_long = 5000 + 109; pub const SYS_setsid: ::c_long = 5000 + 110; pub const SYS_setreuid: ::c_long = 5000 + 111; pub const SYS_setregid: ::c_long = 5000 + 112; pub const SYS_getgroups: ::c_long = 5000 + 113; pub const SYS_setgroups: ::c_long = 5000 + 114; pub const SYS_setresuid: ::c_long = 5000 + 115; pub const SYS_getresuid: ::c_long = 5000 + 116; pub const SYS_setresgid: ::c_long = 5000 + 117; pub const SYS_getresgid: ::c_long = 5000 + 118; pub const SYS_getpgid: ::c_long = 5000 + 119; pub const SYS_setfsuid: ::c_long = 5000 + 120; pub const SYS_setfsgid: ::c_long = 5000 + 121; pub const SYS_getsid: ::c_long = 5000 + 122; pub const SYS_capget: ::c_long = 5000 + 123; pub const SYS_capset: ::c_long = 5000 + 124; pub const SYS_rt_sigpending: ::c_long = 5000 + 125; pub const SYS_rt_sigtimedwait: ::c_long = 5000 + 126; pub const SYS_rt_sigqueueinfo: ::c_long = 5000 + 127; pub const SYS_rt_sigsuspend: ::c_long = 5000 + 128; pub const SYS_sigaltstack: ::c_long = 5000 + 129; pub const SYS_utime: ::c_long = 5000 + 130; pub const SYS_mknod: ::c_long = 5000 + 131; pub const SYS_personality: ::c_long = 5000 + 132; pub const SYS_ustat: ::c_long = 5000 + 133; pub const SYS_statfs: ::c_long = 5000 + 134; pub const SYS_fstatfs: ::c_long = 5000 + 135; pub const SYS_sysfs: ::c_long = 5000 + 136; pub const SYS_getpriority: ::c_long = 5000 + 137; pub const SYS_setpriority: ::c_long = 5000 + 138; pub const SYS_sched_setparam: ::c_long = 5000 + 139; pub const SYS_sched_getparam: ::c_long = 5000 + 140; pub const SYS_sched_setscheduler: ::c_long = 5000 + 141; pub const SYS_sched_getscheduler: ::c_long = 5000 + 142; pub const SYS_sched_get_priority_max: ::c_long = 5000 + 143; pub const SYS_sched_get_priority_min: ::c_long = 5000 + 144; pub const SYS_sched_rr_get_interval: ::c_long = 5000 + 145; pub const SYS_mlock: ::c_long = 5000 + 146; pub const SYS_munlock: ::c_long = 5000 + 147; pub const SYS_mlockall: ::c_long = 5000 + 148; pub const SYS_munlockall: ::c_long = 5000 + 149; pub const SYS_vhangup: ::c_long = 5000 + 150; pub const SYS_pivot_root: ::c_long = 5000 + 151; pub const SYS__sysctl: ::c_long = 5000 + 152; pub const SYS_prctl: ::c_long = 5000 + 153; pub const SYS_adjtimex: ::c_long = 5000 + 154; pub const SYS_setrlimit: ::c_long = 5000 + 155; pub const SYS_chroot: ::c_long = 5000 + 156; pub const SYS_sync: ::c_long = 5000 + 157; pub const SYS_acct: ::c_long = 5000 + 158; pub const SYS_settimeofday: ::c_long = 5000 + 159; pub const SYS_mount: ::c_long = 5000 + 160; pub const SYS_umount2: ::c_long = 5000 + 161; pub const SYS_swapon: ::c_long = 5000 + 162; pub const SYS_swapoff: ::c_long = 5000 + 163; pub const SYS_reboot: ::c_long = 5000 + 164; pub const SYS_sethostname: ::c_long = 5000 + 165; pub const SYS_setdomainname: ::c_long = 5000 + 166; pub const SYS_create_module: ::c_long = 5000 + 167; pub const SYS_init_module: ::c_long = 5000 + 168; pub const SYS_delete_module: ::c_long = 5000 + 169; pub const SYS_get_kernel_syms: ::c_long = 5000 + 170; pub const SYS_query_module: ::c_long = 5000 + 171; pub const SYS_quotactl: ::c_long = 5000 + 172; pub const SYS_nfsservctl: ::c_long = 5000 + 173; pub const SYS_getpmsg: ::c_long = 5000 + 174; pub const SYS_putpmsg: ::c_long = 5000 + 175; pub const SYS_afs_syscall: ::c_long = 5000 + 176; pub const SYS_gettid: ::c_long = 5000 + 178; pub const SYS_readahead: ::c_long = 5000 + 179; pub const SYS_setxattr: ::c_long = 5000 + 180; pub const SYS_lsetxattr: ::c_long = 5000 + 181; pub const SYS_fsetxattr: ::c_long = 5000 + 182; pub const SYS_getxattr: ::c_long = 5000 + 183; pub const SYS_lgetxattr: ::c_long = 5000 + 184; pub const SYS_fgetxattr: ::c_long = 5000 + 185; pub const SYS_listxattr: ::c_long = 5000 + 186; pub const SYS_llistxattr: ::c_long = 5000 + 187; pub const SYS_flistxattr: ::c_long = 5000 + 188; pub const SYS_removexattr: ::c_long = 5000 + 189; pub const SYS_lremovexattr: ::c_long = 5000 + 190; pub const SYS_fremovexattr: ::c_long = 5000 + 191; pub const SYS_tkill: ::c_long = 5000 + 192; pub const SYS_futex: ::c_long = 5000 + 194; pub const SYS_sched_setaffinity: ::c_long = 5000 + 195; pub const SYS_sched_getaffinity: ::c_long = 5000 + 196; pub const SYS_cacheflush: ::c_long = 5000 + 197; pub const SYS_cachectl: ::c_long = 5000 + 198; pub const SYS_sysmips: ::c_long = 5000 + 199; pub const SYS_io_setup: ::c_long = 5000 + 200; pub const SYS_io_destroy: ::c_long = 5000 + 201; pub const SYS_io_getevents: ::c_long = 5000 + 202; pub const SYS_io_submit: ::c_long = 5000 + 203; pub const SYS_io_cancel: ::c_long = 5000 + 204; pub const SYS_exit_group: ::c_long = 5000 + 205; pub const SYS_lookup_dcookie: ::c_long = 5000 + 206; pub const SYS_epoll_create: ::c_long = 5000 + 207; pub const SYS_epoll_ctl: ::c_long = 5000 + 208; pub const SYS_epoll_wait: ::c_long = 5000 + 209; pub const SYS_remap_file_pages: ::c_long = 5000 + 210; pub const SYS_rt_sigreturn: ::c_long = 5000 + 211; pub const SYS_set_tid_address: ::c_long = 5000 + 212; pub const SYS_restart_syscall: ::c_long = 5000 + 213; pub const SYS_semtimedop: ::c_long = 5000 + 214; pub const SYS_fadvise64: ::c_long = 5000 + 215; pub const SYS_timer_create: ::c_long = 5000 + 216; pub const SYS_timer_settime: ::c_long = 5000 + 217; pub const SYS_timer_gettime: ::c_long = 5000 + 218; pub const SYS_timer_getoverrun: ::c_long = 5000 + 219; pub const SYS_timer_delete: ::c_long = 5000 + 220; pub const SYS_clock_settime: ::c_long = 5000 + 221; pub const SYS_clock_gettime: ::c_long = 5000 + 222; pub const SYS_clock_getres: ::c_long = 5000 + 223; pub const SYS_clock_nanosleep: ::c_long = 5000 + 224; pub const SYS_tgkill: ::c_long = 5000 + 225; pub const SYS_utimes: ::c_long = 5000 + 226; pub const SYS_mbind: ::c_long = 5000 + 227; pub const SYS_get_mempolicy: ::c_long = 5000 + 228; pub const SYS_set_mempolicy: ::c_long = 5000 + 229; pub const SYS_mq_open: ::c_long = 5000 + 230; pub const SYS_mq_unlink: ::c_long = 5000 + 231; pub const SYS_mq_timedsend: ::c_long = 5000 + 232; pub const SYS_mq_timedreceive: ::c_long = 5000 + 233; pub const SYS_mq_notify: ::c_long = 5000 + 234; pub const SYS_mq_getsetattr: ::c_long = 5000 + 235; pub const SYS_vserver: ::c_long = 5000 + 236; pub const SYS_waitid: ::c_long = 5000 + 237; /* pub const SYS_sys_setaltroot: ::c_long = 5000 + 238; */ pub const SYS_add_key: ::c_long = 5000 + 239; pub const SYS_request_key: ::c_long = 5000 + 240; pub const SYS_keyctl: ::c_long = 5000 + 241; pub const SYS_set_thread_area: ::c_long = 5000 + 242; pub const SYS_inotify_init: ::c_long = 5000 + 243; pub const SYS_inotify_add_watch: ::c_long = 5000 + 244; pub const SYS_inotify_rm_watch: ::c_long = 5000 + 245; pub const SYS_migrate_pages: ::c_long = 5000 + 246; pub const SYS_openat: ::c_long = 5000 + 247; pub const SYS_mkdirat: ::c_long = 5000 + 248; pub const SYS_mknodat: ::c_long = 5000 + 249; pub const SYS_fchownat: ::c_long = 5000 + 250; pub const SYS_futimesat: ::c_long = 5000 + 251; pub const SYS_newfstatat: ::c_long = 5000 + 252; pub const SYS_unlinkat: ::c_long = 5000 + 253; pub const SYS_renameat: ::c_long = 5000 + 254; pub const SYS_linkat: ::c_long = 5000 + 255; pub const SYS_symlinkat: ::c_long = 5000 + 256; pub const SYS_readlinkat: ::c_long = 5000 + 257; pub const SYS_fchmodat: ::c_long = 5000 + 258; pub const SYS_faccessat: ::c_long = 5000 + 259; pub const SYS_pselect6: ::c_long = 5000 + 260; pub const SYS_ppoll: ::c_long = 5000 + 261; pub const SYS_unshare: ::c_long = 5000 + 262; pub const SYS_splice: ::c_long = 5000 + 263; pub const SYS_sync_file_range: ::c_long = 5000 + 264; pub const SYS_tee: ::c_long = 5000 + 265; pub const SYS_vmsplice: ::c_long = 5000 + 266; pub const SYS_move_pages: ::c_long = 5000 + 267; pub const SYS_set_robust_list: ::c_long = 5000 + 268; pub const SYS_get_robust_list: ::c_long = 5000 + 269; pub const SYS_kexec_load: ::c_long = 5000 + 270; pub const SYS_getcpu: ::c_long = 5000 + 271; pub const SYS_epoll_pwait: ::c_long = 5000 + 272; pub const SYS_ioprio_set: ::c_long = 5000 + 273; pub const SYS_ioprio_get: ::c_long = 5000 + 274; pub const SYS_utimensat: ::c_long = 5000 + 275; pub const SYS_signalfd: ::c_long = 5000 + 276; pub const SYS_timerfd: ::c_long = 5000 + 277; pub const SYS_eventfd: ::c_long = 5000 + 278; pub const SYS_fallocate: ::c_long = 5000 + 279; pub const SYS_timerfd_create: ::c_long = 5000 + 280; pub const SYS_timerfd_gettime: ::c_long = 5000 + 281; pub const SYS_timerfd_settime: ::c_long = 5000 + 282; pub const SYS_signalfd4: ::c_long = 5000 + 283; pub const SYS_eventfd2: ::c_long = 5000 + 284; pub const SYS_epoll_create1: ::c_long = 5000 + 285; pub const SYS_dup3: ::c_long = 5000 + 286; pub const SYS_pipe2: ::c_long = 5000 + 287; pub const SYS_inotify_init1: ::c_long = 5000 + 288; pub const SYS_preadv: ::c_long = 5000 + 289; pub const SYS_pwritev: ::c_long = 5000 + 290; pub const SYS_rt_tgsigqueueinfo: ::c_long = 5000 + 291; pub const SYS_perf_event_open: ::c_long = 5000 + 292; pub const SYS_accept4: ::c_long = 5000 + 293; pub const SYS_recvmmsg: ::c_long = 5000 + 294; pub const SYS_fanotify_init: ::c_long = 5000 + 295; pub const SYS_fanotify_mark: ::c_long = 5000 + 296; pub const SYS_prlimit64: ::c_long = 5000 + 297; pub const SYS_name_to_handle_at: ::c_long = 5000 + 298; pub const SYS_open_by_handle_at: ::c_long = 5000 + 299; pub const SYS_clock_adjtime: ::c_long = 5000 + 300; pub const SYS_syncfs: ::c_long = 5000 + 301; pub const SYS_sendmmsg: ::c_long = 5000 + 302; pub const SYS_setns: ::c_long = 5000 + 303; pub const SYS_process_vm_readv: ::c_long = 5000 + 304; pub const SYS_process_vm_writev: ::c_long = 5000 + 305; pub const SYS_kcmp: ::c_long = 5000 + 306; pub const SYS_finit_module: ::c_long = 5000 + 307; pub const SYS_getdents64: ::c_long = 5000 + 308; pub const SYS_sched_setattr: ::c_long = 5000 + 309; pub const SYS_sched_getattr: ::c_long = 5000 + 310; pub const SYS_renameat2: ::c_long = 5000 + 311; pub const SYS_seccomp: ::c_long = 5000 + 312; pub const SYS_getrandom: ::c_long = 5000 + 313; pub const SYS_memfd_create: ::c_long = 5000 + 314; pub const SYS_bpf: ::c_long = 5000 + 315; pub const SYS_execveat: ::c_long = 5000 + 316; pub const SYS_userfaultfd: ::c_long = 5000 + 317; pub const SYS_membarrier: ::c_long = 5000 + 318; pub const SYS_mlock2: ::c_long = 5000 + 319; pub const SYS_copy_file_range: ::c_long = 5000 + 320; pub const SYS_preadv2: ::c_long = 5000 + 321; pub const SYS_pwritev2: ::c_long = 5000 + 322; pub const SYS_pkey_mprotect: ::c_long = 5000 + 323; pub const SYS_pkey_alloc: ::c_long = 5000 + 324; pub const SYS_pkey_free: ::c_long = 5000 + 325; pub const SYS_statx: ::c_long = 5000 + 326; pub const SYS_rseq: ::c_long = 5000 + 327; pub const SYS_pidfd_send_signal: ::c_long = 5000 + 424; pub const SYS_io_uring_setup: ::c_long = 5000 + 425; pub const SYS_io_uring_enter: ::c_long = 5000 + 426; pub const SYS_io_uring_register: ::c_long = 5000 + 427; pub const SYS_open_tree: ::c_long = 5000 + 428; pub const SYS_move_mount: ::c_long = 5000 + 429; pub const SYS_fsopen: ::c_long = 5000 + 430; pub const SYS_fsconfig: ::c_long = 5000 + 431; pub const SYS_fsmount: ::c_long = 5000 + 432; pub const SYS_fspick: ::c_long = 5000 + 433; pub const SYS_pidfd_open: ::c_long = 5000 + 434; pub const SYS_clone3: ::c_long = 5000 + 435; pub const SYS_close_range: ::c_long = 5000 + 436; pub const SYS_openat2: ::c_long = 5000 + 437; pub const SYS_pidfd_getfd: ::c_long = 5000 + 438; pub const SYS_faccessat2: ::c_long = 5000 + 439; pub const SYS_process_madvise: ::c_long = 5000 + 440; pub const SYS_epoll_pwait2: ::c_long = 5000 + 441; pub const SYS_mount_setattr: ::c_long = 5000 + 442; pub const SYS_quotactl_fd: ::c_long = 5000 + 443; pub const SYS_landlock_create_ruleset: ::c_long = 5000 + 444; pub const SYS_landlock_add_rule: ::c_long = 5000 + 445; pub const SYS_landlock_restrict_self: ::c_long = 5000 + 446; pub const SYS_memfd_secret: ::c_long = 5000 + 447; pub const SYS_process_mrelease: ::c_long = 5000 + 448; pub const SYS_futex_waitv: ::c_long = 5000 + 449; pub const SYS_set_mempolicy_home_node: ::c_long = 5000 + 450; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_CLOEXEC: ::c_int = 0x80000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const O_DIRECT: ::c_int = 0x8000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_APPEND: ::c_int = 8; pub const O_CREAT: ::c_int = 256; pub const O_EXCL: ::c_int = 1024; pub const O_NOCTTY: ::c_int = 2048; pub const O_NONBLOCK: ::c_int = 128; pub const O_SYNC: ::c_int = 0x4010; pub const O_RSYNC: ::c_int = 0x4010; pub const O_DSYNC: ::c_int = 0x10; pub const O_FSYNC: ::c_int = 0x4010; pub const O_ASYNC: ::c_int = 0x1000; pub const O_NDELAY: ::c_int = 0x80; pub const EDEADLK: ::c_int = 45; pub const ENAMETOOLONG: ::c_int = 78; pub const ENOLCK: ::c_int = 46; pub const ENOSYS: ::c_int = 89; pub const ENOTEMPTY: ::c_int = 93; pub const ELOOP: ::c_int = 90; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EBADE: ::c_int = 50; pub const EBADR: ::c_int = 51; pub const EXFULL: ::c_int = 52; pub const ENOANO: ::c_int = 53; pub const EBADRQC: ::c_int = 54; pub const EBADSLT: ::c_int = 55; pub const EDEADLOCK: ::c_int = 56; pub const EMULTIHOP: ::c_int = 74; pub const EOVERFLOW: ::c_int = 79; pub const ENOTUNIQ: ::c_int = 80; pub const EBADFD: ::c_int = 81; pub const EBADMSG: ::c_int = 77; pub const EREMCHG: ::c_int = 82; pub const ELIBACC: ::c_int = 83; pub const ELIBBAD: ::c_int = 84; pub const ELIBSCN: ::c_int = 85; pub const ELIBMAX: ::c_int = 86; pub const ELIBEXEC: ::c_int = 87; pub const EILSEQ: ::c_int = 88; pub const ERESTART: ::c_int = 91; pub const ESTRPIPE: ::c_int = 92; pub const EUSERS: ::c_int = 94; pub const ENOTSOCK: ::c_int = 95; pub const EDESTADDRREQ: ::c_int = 96; pub const EMSGSIZE: ::c_int = 97; pub const EPROTOTYPE: ::c_int = 98; pub const ENOPROTOOPT: ::c_int = 99; pub const EPROTONOSUPPORT: ::c_int = 120; pub const ESOCKTNOSUPPORT: ::c_int = 121; pub const EOPNOTSUPP: ::c_int = 122; pub const EPFNOSUPPORT: ::c_int = 123; pub const EAFNOSUPPORT: ::c_int = 124; pub const EADDRINUSE: ::c_int = 125; pub const EADDRNOTAVAIL: ::c_int = 126; pub const ENETDOWN: ::c_int = 127; pub const ENETUNREACH: ::c_int = 128; pub const ENETRESET: ::c_int = 129; pub const ECONNABORTED: ::c_int = 130; pub const ECONNRESET: ::c_int = 131; pub const ENOBUFS: ::c_int = 132; pub const EISCONN: ::c_int = 133; pub const ENOTCONN: ::c_int = 134; pub const ESHUTDOWN: ::c_int = 143; pub const ETOOMANYREFS: ::c_int = 144; pub const ETIMEDOUT: ::c_int = 145; pub const ECONNREFUSED: ::c_int = 146; pub const EHOSTDOWN: ::c_int = 147; pub const EHOSTUNREACH: ::c_int = 148; pub const EALREADY: ::c_int = 149; pub const EINPROGRESS: ::c_int = 150; pub const ESTALE: ::c_int = 151; pub const EUCLEAN: ::c_int = 135; pub const ENOTNAM: ::c_int = 137; pub const ENAVAIL: ::c_int = 138; pub const EISNAM: ::c_int = 139; pub const EREMOTEIO: ::c_int = 140; pub const EDQUOT: ::c_int = 1133; pub const ENOMEDIUM: ::c_int = 159; pub const EMEDIUMTYPE: ::c_int = 160; pub const ECANCELED: ::c_int = 158; pub const ENOKEY: ::c_int = 161; pub const EKEYEXPIRED: ::c_int = 162; pub const EKEYREVOKED: ::c_int = 163; pub const EKEYREJECTED: ::c_int = 164; pub const EOWNERDEAD: ::c_int = 165; pub const ENOTRECOVERABLE: ::c_int = 166; pub const ERFKILL: ::c_int = 167; pub const MAP_NORESERVE: ::c_int = 0x400; pub const MAP_ANON: ::c_int = 0x800; pub const MAP_ANONYMOUS: ::c_int = 0x800; pub const MAP_GROWSDOWN: ::c_int = 0x1000; pub const MAP_DENYWRITE: ::c_int = 0x2000; pub const MAP_EXECUTABLE: ::c_int = 0x4000; pub const MAP_LOCKED: ::c_int = 0x8000; pub const MAP_POPULATE: ::c_int = 0x10000; pub const MAP_NONBLOCK: ::c_int = 0x20000; pub const MAP_STACK: ::c_int = 0x40000; pub const MAP_HUGETLB: ::c_int = 0x080000; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_DGRAM: ::c_int = 1; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000008; pub const SA_NOCLDWAIT: ::c_int = 0x00010000; pub const SIGCHLD: ::c_int = 18; pub const SIGBUS: ::c_int = 10; pub const SIGTTIN: ::c_int = 26; pub const SIGTTOU: ::c_int = 27; pub const SIGXCPU: ::c_int = 30; pub const SIGXFSZ: ::c_int = 31; pub const SIGVTALRM: ::c_int = 28; pub const SIGPROF: ::c_int = 29; pub const SIGWINCH: ::c_int = 20; pub const SIGUSR1: ::c_int = 16; pub const SIGUSR2: ::c_int = 17; pub const SIGCONT: ::c_int = 25; pub const SIGSTOP: ::c_int = 23; pub const SIGTSTP: ::c_int = 24; pub const SIGURG: ::c_int = 21; pub const SIGIO: ::c_int = 22; pub const SIGSYS: ::c_int = 12; pub const SIGPOLL: ::c_int = 22; pub const SIGPWR: ::c_int = 19; pub const SIG_SETMASK: ::c_int = 3; pub const SIG_BLOCK: ::c_int = 0x1; pub const SIG_UNBLOCK: ::c_int = 0x2; pub const POLLWRNORM: ::c_short = 0x004; pub const POLLWRBAND: ::c_short = 0x100; pub const VEOF: usize = 16; pub const VEOL: usize = 17; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const IEXTEN: ::tcflag_t = 0x00000100; pub const TOSTOP: ::tcflag_t = 0x00008000; pub const FLUSHO: ::tcflag_t = 0x00002000; pub const EXTPROC: ::tcflag_t = 0o200000; pub const TCSANOW: ::c_int = 0x540e; pub const TCSADRAIN: ::c_int = 0x540f; pub const TCSAFLUSH: ::c_int = 0x5410; pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; pub const PTRACE_DETACH: ::c_uint = 17; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const PTRACE_GETREGS: ::c_uint = 12; pub const PTRACE_SETREGS: ::c_uint = 13; pub const EFD_NONBLOCK: ::c_int = 0x80; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const F_GETLK: ::c_int = 14; pub const F_GETOWN: ::c_int = 23; pub const F_SETOWN: ::c_int = 24; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const SFD_NONBLOCK: ::c_int = 0x80; pub const RTLD_DEEPBIND: ::c_int = 0x10; pub const RTLD_GLOBAL: ::c_int = 0x4; pub const RTLD_NOLOAD: ::c_int = 0x8; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const EHWPOISON: ::c_int = 168; extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b64/mips64/align.rs0000644000175000017500000000022514661133735023473 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } libc/src/unix/linux_like/linux/gnu/b64/x86_64/0000775000175000017500000000000014661133735021652 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs0000644000175000017500000005442414661133735022643 0ustar jamespagejamespageuse pthread_mutex_t; pub type c_long = i32; pub type c_ulong = u32; s! { pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } } pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 44; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 20; align_const! { pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } // Syscall table pub const __X32_SYSCALL_BIT: ::c_long = 0x40000000; pub const SYS_read: ::c_long = __X32_SYSCALL_BIT + 0; pub const SYS_write: ::c_long = __X32_SYSCALL_BIT + 1; pub const SYS_open: ::c_long = __X32_SYSCALL_BIT + 2; pub const SYS_close: ::c_long = __X32_SYSCALL_BIT + 3; pub const SYS_stat: ::c_long = __X32_SYSCALL_BIT + 4; pub const SYS_fstat: ::c_long = __X32_SYSCALL_BIT + 5; pub const SYS_lstat: ::c_long = __X32_SYSCALL_BIT + 6; pub const SYS_poll: ::c_long = __X32_SYSCALL_BIT + 7; pub const SYS_lseek: ::c_long = __X32_SYSCALL_BIT + 8; pub const SYS_mmap: ::c_long = __X32_SYSCALL_BIT + 9; pub const SYS_mprotect: ::c_long = __X32_SYSCALL_BIT + 10; pub const SYS_munmap: ::c_long = __X32_SYSCALL_BIT + 11; pub const SYS_brk: ::c_long = __X32_SYSCALL_BIT + 12; pub const SYS_rt_sigprocmask: ::c_long = __X32_SYSCALL_BIT + 14; pub const SYS_pread64: ::c_long = __X32_SYSCALL_BIT + 17; pub const SYS_pwrite64: ::c_long = __X32_SYSCALL_BIT + 18; pub const SYS_access: ::c_long = __X32_SYSCALL_BIT + 21; pub const SYS_pipe: ::c_long = __X32_SYSCALL_BIT + 22; pub const SYS_select: ::c_long = __X32_SYSCALL_BIT + 23; pub const SYS_sched_yield: ::c_long = __X32_SYSCALL_BIT + 24; pub const SYS_mremap: ::c_long = __X32_SYSCALL_BIT + 25; pub const SYS_msync: ::c_long = __X32_SYSCALL_BIT + 26; pub const SYS_mincore: ::c_long = __X32_SYSCALL_BIT + 27; pub const SYS_madvise: ::c_long = __X32_SYSCALL_BIT + 28; pub const SYS_shmget: ::c_long = __X32_SYSCALL_BIT + 29; pub const SYS_shmat: ::c_long = __X32_SYSCALL_BIT + 30; pub const SYS_shmctl: ::c_long = __X32_SYSCALL_BIT + 31; pub const SYS_dup: ::c_long = __X32_SYSCALL_BIT + 32; pub const SYS_dup2: ::c_long = __X32_SYSCALL_BIT + 33; pub const SYS_pause: ::c_long = __X32_SYSCALL_BIT + 34; pub const SYS_nanosleep: ::c_long = __X32_SYSCALL_BIT + 35; pub const SYS_getitimer: ::c_long = __X32_SYSCALL_BIT + 36; pub const SYS_alarm: ::c_long = __X32_SYSCALL_BIT + 37; pub const SYS_setitimer: ::c_long = __X32_SYSCALL_BIT + 38; pub const SYS_getpid: ::c_long = __X32_SYSCALL_BIT + 39; pub const SYS_sendfile: ::c_long = __X32_SYSCALL_BIT + 40; pub const SYS_socket: ::c_long = __X32_SYSCALL_BIT + 41; pub const SYS_connect: ::c_long = __X32_SYSCALL_BIT + 42; pub const SYS_accept: ::c_long = __X32_SYSCALL_BIT + 43; pub const SYS_sendto: ::c_long = __X32_SYSCALL_BIT + 44; pub const SYS_shutdown: ::c_long = __X32_SYSCALL_BIT + 48; pub const SYS_bind: ::c_long = __X32_SYSCALL_BIT + 49; pub const SYS_listen: ::c_long = __X32_SYSCALL_BIT + 50; pub const SYS_getsockname: ::c_long = __X32_SYSCALL_BIT + 51; pub const SYS_getpeername: ::c_long = __X32_SYSCALL_BIT + 52; pub const SYS_socketpair: ::c_long = __X32_SYSCALL_BIT + 53; pub const SYS_clone: ::c_long = __X32_SYSCALL_BIT + 56; pub const SYS_fork: ::c_long = __X32_SYSCALL_BIT + 57; pub const SYS_vfork: ::c_long = __X32_SYSCALL_BIT + 58; pub const SYS_exit: ::c_long = __X32_SYSCALL_BIT + 60; pub const SYS_wait4: ::c_long = __X32_SYSCALL_BIT + 61; pub const SYS_kill: ::c_long = __X32_SYSCALL_BIT + 62; pub const SYS_uname: ::c_long = __X32_SYSCALL_BIT + 63; pub const SYS_semget: ::c_long = __X32_SYSCALL_BIT + 64; pub const SYS_semop: ::c_long = __X32_SYSCALL_BIT + 65; pub const SYS_semctl: ::c_long = __X32_SYSCALL_BIT + 66; pub const SYS_shmdt: ::c_long = __X32_SYSCALL_BIT + 67; pub const SYS_msgget: ::c_long = __X32_SYSCALL_BIT + 68; pub const SYS_msgsnd: ::c_long = __X32_SYSCALL_BIT + 69; pub const SYS_msgrcv: ::c_long = __X32_SYSCALL_BIT + 70; pub const SYS_msgctl: ::c_long = __X32_SYSCALL_BIT + 71; pub const SYS_fcntl: ::c_long = __X32_SYSCALL_BIT + 72; pub const SYS_flock: ::c_long = __X32_SYSCALL_BIT + 73; pub const SYS_fsync: ::c_long = __X32_SYSCALL_BIT + 74; pub const SYS_fdatasync: ::c_long = __X32_SYSCALL_BIT + 75; pub const SYS_truncate: ::c_long = __X32_SYSCALL_BIT + 76; pub const SYS_ftruncate: ::c_long = __X32_SYSCALL_BIT + 77; pub const SYS_getdents: ::c_long = __X32_SYSCALL_BIT + 78; pub const SYS_getcwd: ::c_long = __X32_SYSCALL_BIT + 79; pub const SYS_chdir: ::c_long = __X32_SYSCALL_BIT + 80; pub const SYS_fchdir: ::c_long = __X32_SYSCALL_BIT + 81; pub const SYS_rename: ::c_long = __X32_SYSCALL_BIT + 82; pub const SYS_mkdir: ::c_long = __X32_SYSCALL_BIT + 83; pub const SYS_rmdir: ::c_long = __X32_SYSCALL_BIT + 84; pub const SYS_creat: ::c_long = __X32_SYSCALL_BIT + 85; pub const SYS_link: ::c_long = __X32_SYSCALL_BIT + 86; pub const SYS_unlink: ::c_long = __X32_SYSCALL_BIT + 87; pub const SYS_symlink: ::c_long = __X32_SYSCALL_BIT + 88; pub const SYS_readlink: ::c_long = __X32_SYSCALL_BIT + 89; pub const SYS_chmod: ::c_long = __X32_SYSCALL_BIT + 90; pub const SYS_fchmod: ::c_long = __X32_SYSCALL_BIT + 91; pub const SYS_chown: ::c_long = __X32_SYSCALL_BIT + 92; pub const SYS_fchown: ::c_long = __X32_SYSCALL_BIT + 93; pub const SYS_lchown: ::c_long = __X32_SYSCALL_BIT + 94; pub const SYS_umask: ::c_long = __X32_SYSCALL_BIT + 95; pub const SYS_gettimeofday: ::c_long = __X32_SYSCALL_BIT + 96; pub const SYS_getrlimit: ::c_long = __X32_SYSCALL_BIT + 97; pub const SYS_getrusage: ::c_long = __X32_SYSCALL_BIT + 98; pub const SYS_sysinfo: ::c_long = __X32_SYSCALL_BIT + 99; pub const SYS_times: ::c_long = __X32_SYSCALL_BIT + 100; pub const SYS_getuid: ::c_long = __X32_SYSCALL_BIT + 102; pub const SYS_syslog: ::c_long = __X32_SYSCALL_BIT + 103; pub const SYS_getgid: ::c_long = __X32_SYSCALL_BIT + 104; pub const SYS_setuid: ::c_long = __X32_SYSCALL_BIT + 105; pub const SYS_setgid: ::c_long = __X32_SYSCALL_BIT + 106; pub const SYS_geteuid: ::c_long = __X32_SYSCALL_BIT + 107; pub const SYS_getegid: ::c_long = __X32_SYSCALL_BIT + 108; pub const SYS_setpgid: ::c_long = __X32_SYSCALL_BIT + 109; pub const SYS_getppid: ::c_long = __X32_SYSCALL_BIT + 110; pub const SYS_getpgrp: ::c_long = __X32_SYSCALL_BIT + 111; pub const SYS_setsid: ::c_long = __X32_SYSCALL_BIT + 112; pub const SYS_setreuid: ::c_long = __X32_SYSCALL_BIT + 113; pub const SYS_setregid: ::c_long = __X32_SYSCALL_BIT + 114; pub const SYS_getgroups: ::c_long = __X32_SYSCALL_BIT + 115; pub const SYS_setgroups: ::c_long = __X32_SYSCALL_BIT + 116; pub const SYS_setresuid: ::c_long = __X32_SYSCALL_BIT + 117; pub const SYS_getresuid: ::c_long = __X32_SYSCALL_BIT + 118; pub const SYS_setresgid: ::c_long = __X32_SYSCALL_BIT + 119; pub const SYS_getresgid: ::c_long = __X32_SYSCALL_BIT + 120; pub const SYS_getpgid: ::c_long = __X32_SYSCALL_BIT + 121; pub const SYS_setfsuid: ::c_long = __X32_SYSCALL_BIT + 122; pub const SYS_setfsgid: ::c_long = __X32_SYSCALL_BIT + 123; pub const SYS_getsid: ::c_long = __X32_SYSCALL_BIT + 124; pub const SYS_capget: ::c_long = __X32_SYSCALL_BIT + 125; pub const SYS_capset: ::c_long = __X32_SYSCALL_BIT + 126; pub const SYS_rt_sigsuspend: ::c_long = __X32_SYSCALL_BIT + 130; pub const SYS_utime: ::c_long = __X32_SYSCALL_BIT + 132; pub const SYS_mknod: ::c_long = __X32_SYSCALL_BIT + 133; pub const SYS_personality: ::c_long = __X32_SYSCALL_BIT + 135; pub const SYS_ustat: ::c_long = __X32_SYSCALL_BIT + 136; pub const SYS_statfs: ::c_long = __X32_SYSCALL_BIT + 137; pub const SYS_fstatfs: ::c_long = __X32_SYSCALL_BIT + 138; pub const SYS_sysfs: ::c_long = __X32_SYSCALL_BIT + 139; pub const SYS_getpriority: ::c_long = __X32_SYSCALL_BIT + 140; pub const SYS_setpriority: ::c_long = __X32_SYSCALL_BIT + 141; pub const SYS_sched_setparam: ::c_long = __X32_SYSCALL_BIT + 142; pub const SYS_sched_getparam: ::c_long = __X32_SYSCALL_BIT + 143; pub const SYS_sched_setscheduler: ::c_long = __X32_SYSCALL_BIT + 144; pub const SYS_sched_getscheduler: ::c_long = __X32_SYSCALL_BIT + 145; pub const SYS_sched_get_priority_max: ::c_long = __X32_SYSCALL_BIT + 146; pub const SYS_sched_get_priority_min: ::c_long = __X32_SYSCALL_BIT + 147; pub const SYS_sched_rr_get_interval: ::c_long = __X32_SYSCALL_BIT + 148; pub const SYS_mlock: ::c_long = __X32_SYSCALL_BIT + 149; pub const SYS_munlock: ::c_long = __X32_SYSCALL_BIT + 150; pub const SYS_mlockall: ::c_long = __X32_SYSCALL_BIT + 151; pub const SYS_munlockall: ::c_long = __X32_SYSCALL_BIT + 152; pub const SYS_vhangup: ::c_long = __X32_SYSCALL_BIT + 153; pub const SYS_modify_ldt: ::c_long = __X32_SYSCALL_BIT + 154; pub const SYS_pivot_root: ::c_long = __X32_SYSCALL_BIT + 155; pub const SYS_prctl: ::c_long = __X32_SYSCALL_BIT + 157; pub const SYS_arch_prctl: ::c_long = __X32_SYSCALL_BIT + 158; pub const SYS_adjtimex: ::c_long = __X32_SYSCALL_BIT + 159; pub const SYS_setrlimit: ::c_long = __X32_SYSCALL_BIT + 160; pub const SYS_chroot: ::c_long = __X32_SYSCALL_BIT + 161; pub const SYS_sync: ::c_long = __X32_SYSCALL_BIT + 162; pub const SYS_acct: ::c_long = __X32_SYSCALL_BIT + 163; pub const SYS_settimeofday: ::c_long = __X32_SYSCALL_BIT + 164; pub const SYS_mount: ::c_long = __X32_SYSCALL_BIT + 165; pub const SYS_umount2: ::c_long = __X32_SYSCALL_BIT + 166; pub const SYS_swapon: ::c_long = __X32_SYSCALL_BIT + 167; pub const SYS_swapoff: ::c_long = __X32_SYSCALL_BIT + 168; pub const SYS_reboot: ::c_long = __X32_SYSCALL_BIT + 169; pub const SYS_sethostname: ::c_long = __X32_SYSCALL_BIT + 170; pub const SYS_setdomainname: ::c_long = __X32_SYSCALL_BIT + 171; pub const SYS_iopl: ::c_long = __X32_SYSCALL_BIT + 172; pub const SYS_ioperm: ::c_long = __X32_SYSCALL_BIT + 173; pub const SYS_init_module: ::c_long = __X32_SYSCALL_BIT + 175; pub const SYS_delete_module: ::c_long = __X32_SYSCALL_BIT + 176; pub const SYS_quotactl: ::c_long = __X32_SYSCALL_BIT + 179; pub const SYS_getpmsg: ::c_long = __X32_SYSCALL_BIT + 181; pub const SYS_putpmsg: ::c_long = __X32_SYSCALL_BIT + 182; pub const SYS_afs_syscall: ::c_long = __X32_SYSCALL_BIT + 183; pub const SYS_tuxcall: ::c_long = __X32_SYSCALL_BIT + 184; pub const SYS_security: ::c_long = __X32_SYSCALL_BIT + 185; pub const SYS_gettid: ::c_long = __X32_SYSCALL_BIT + 186; pub const SYS_readahead: ::c_long = __X32_SYSCALL_BIT + 187; pub const SYS_setxattr: ::c_long = __X32_SYSCALL_BIT + 188; pub const SYS_lsetxattr: ::c_long = __X32_SYSCALL_BIT + 189; pub const SYS_fsetxattr: ::c_long = __X32_SYSCALL_BIT + 190; pub const SYS_getxattr: ::c_long = __X32_SYSCALL_BIT + 191; pub const SYS_lgetxattr: ::c_long = __X32_SYSCALL_BIT + 192; pub const SYS_fgetxattr: ::c_long = __X32_SYSCALL_BIT + 193; pub const SYS_listxattr: ::c_long = __X32_SYSCALL_BIT + 194; pub const SYS_llistxattr: ::c_long = __X32_SYSCALL_BIT + 195; pub const SYS_flistxattr: ::c_long = __X32_SYSCALL_BIT + 196; pub const SYS_removexattr: ::c_long = __X32_SYSCALL_BIT + 197; pub const SYS_lremovexattr: ::c_long = __X32_SYSCALL_BIT + 198; pub const SYS_fremovexattr: ::c_long = __X32_SYSCALL_BIT + 199; pub const SYS_tkill: ::c_long = __X32_SYSCALL_BIT + 200; pub const SYS_time: ::c_long = __X32_SYSCALL_BIT + 201; pub const SYS_futex: ::c_long = __X32_SYSCALL_BIT + 202; pub const SYS_sched_setaffinity: ::c_long = __X32_SYSCALL_BIT + 203; pub const SYS_sched_getaffinity: ::c_long = __X32_SYSCALL_BIT + 204; pub const SYS_io_destroy: ::c_long = __X32_SYSCALL_BIT + 207; pub const SYS_io_getevents: ::c_long = __X32_SYSCALL_BIT + 208; pub const SYS_io_cancel: ::c_long = __X32_SYSCALL_BIT + 210; pub const SYS_lookup_dcookie: ::c_long = __X32_SYSCALL_BIT + 212; pub const SYS_epoll_create: ::c_long = __X32_SYSCALL_BIT + 213; pub const SYS_remap_file_pages: ::c_long = __X32_SYSCALL_BIT + 216; pub const SYS_getdents64: ::c_long = __X32_SYSCALL_BIT + 217; pub const SYS_set_tid_address: ::c_long = __X32_SYSCALL_BIT + 218; pub const SYS_restart_syscall: ::c_long = __X32_SYSCALL_BIT + 219; pub const SYS_semtimedop: ::c_long = __X32_SYSCALL_BIT + 220; pub const SYS_fadvise64: ::c_long = __X32_SYSCALL_BIT + 221; pub const SYS_timer_settime: ::c_long = __X32_SYSCALL_BIT + 223; pub const SYS_timer_gettime: ::c_long = __X32_SYSCALL_BIT + 224; pub const SYS_timer_getoverrun: ::c_long = __X32_SYSCALL_BIT + 225; pub const SYS_timer_delete: ::c_long = __X32_SYSCALL_BIT + 226; pub const SYS_clock_settime: ::c_long = __X32_SYSCALL_BIT + 227; pub const SYS_clock_gettime: ::c_long = __X32_SYSCALL_BIT + 228; pub const SYS_clock_getres: ::c_long = __X32_SYSCALL_BIT + 229; pub const SYS_clock_nanosleep: ::c_long = __X32_SYSCALL_BIT + 230; pub const SYS_exit_group: ::c_long = __X32_SYSCALL_BIT + 231; pub const SYS_epoll_wait: ::c_long = __X32_SYSCALL_BIT + 232; pub const SYS_epoll_ctl: ::c_long = __X32_SYSCALL_BIT + 233; pub const SYS_tgkill: ::c_long = __X32_SYSCALL_BIT + 234; pub const SYS_utimes: ::c_long = __X32_SYSCALL_BIT + 235; pub const SYS_mbind: ::c_long = __X32_SYSCALL_BIT + 237; pub const SYS_set_mempolicy: ::c_long = __X32_SYSCALL_BIT + 238; pub const SYS_get_mempolicy: ::c_long = __X32_SYSCALL_BIT + 239; pub const SYS_mq_open: ::c_long = __X32_SYSCALL_BIT + 240; pub const SYS_mq_unlink: ::c_long = __X32_SYSCALL_BIT + 241; pub const SYS_mq_timedsend: ::c_long = __X32_SYSCALL_BIT + 242; pub const SYS_mq_timedreceive: ::c_long = __X32_SYSCALL_BIT + 243; pub const SYS_mq_getsetattr: ::c_long = __X32_SYSCALL_BIT + 245; pub const SYS_add_key: ::c_long = __X32_SYSCALL_BIT + 248; pub const SYS_request_key: ::c_long = __X32_SYSCALL_BIT + 249; pub const SYS_keyctl: ::c_long = __X32_SYSCALL_BIT + 250; pub const SYS_ioprio_set: ::c_long = __X32_SYSCALL_BIT + 251; pub const SYS_ioprio_get: ::c_long = __X32_SYSCALL_BIT + 252; pub const SYS_inotify_init: ::c_long = __X32_SYSCALL_BIT + 253; pub const SYS_inotify_add_watch: ::c_long = __X32_SYSCALL_BIT + 254; pub const SYS_inotify_rm_watch: ::c_long = __X32_SYSCALL_BIT + 255; pub const SYS_migrate_pages: ::c_long = __X32_SYSCALL_BIT + 256; pub const SYS_openat: ::c_long = __X32_SYSCALL_BIT + 257; pub const SYS_mkdirat: ::c_long = __X32_SYSCALL_BIT + 258; pub const SYS_mknodat: ::c_long = __X32_SYSCALL_BIT + 259; pub const SYS_fchownat: ::c_long = __X32_SYSCALL_BIT + 260; pub const SYS_futimesat: ::c_long = __X32_SYSCALL_BIT + 261; pub const SYS_newfstatat: ::c_long = __X32_SYSCALL_BIT + 262; pub const SYS_unlinkat: ::c_long = __X32_SYSCALL_BIT + 263; pub const SYS_renameat: ::c_long = __X32_SYSCALL_BIT + 264; pub const SYS_linkat: ::c_long = __X32_SYSCALL_BIT + 265; pub const SYS_symlinkat: ::c_long = __X32_SYSCALL_BIT + 266; pub const SYS_readlinkat: ::c_long = __X32_SYSCALL_BIT + 267; pub const SYS_fchmodat: ::c_long = __X32_SYSCALL_BIT + 268; pub const SYS_faccessat: ::c_long = __X32_SYSCALL_BIT + 269; pub const SYS_pselect6: ::c_long = __X32_SYSCALL_BIT + 270; pub const SYS_ppoll: ::c_long = __X32_SYSCALL_BIT + 271; pub const SYS_unshare: ::c_long = __X32_SYSCALL_BIT + 272; pub const SYS_splice: ::c_long = __X32_SYSCALL_BIT + 275; pub const SYS_tee: ::c_long = __X32_SYSCALL_BIT + 276; pub const SYS_sync_file_range: ::c_long = __X32_SYSCALL_BIT + 277; pub const SYS_utimensat: ::c_long = __X32_SYSCALL_BIT + 280; pub const SYS_epoll_pwait: ::c_long = __X32_SYSCALL_BIT + 281; pub const SYS_signalfd: ::c_long = __X32_SYSCALL_BIT + 282; pub const SYS_timerfd_create: ::c_long = __X32_SYSCALL_BIT + 283; pub const SYS_eventfd: ::c_long = __X32_SYSCALL_BIT + 284; pub const SYS_fallocate: ::c_long = __X32_SYSCALL_BIT + 285; pub const SYS_timerfd_settime: ::c_long = __X32_SYSCALL_BIT + 286; pub const SYS_timerfd_gettime: ::c_long = __X32_SYSCALL_BIT + 287; pub const SYS_accept4: ::c_long = __X32_SYSCALL_BIT + 288; pub const SYS_signalfd4: ::c_long = __X32_SYSCALL_BIT + 289; pub const SYS_eventfd2: ::c_long = __X32_SYSCALL_BIT + 290; pub const SYS_epoll_create1: ::c_long = __X32_SYSCALL_BIT + 291; pub const SYS_dup3: ::c_long = __X32_SYSCALL_BIT + 292; pub const SYS_pipe2: ::c_long = __X32_SYSCALL_BIT + 293; pub const SYS_inotify_init1: ::c_long = __X32_SYSCALL_BIT + 294; pub const SYS_perf_event_open: ::c_long = __X32_SYSCALL_BIT + 298; pub const SYS_fanotify_init: ::c_long = __X32_SYSCALL_BIT + 300; pub const SYS_fanotify_mark: ::c_long = __X32_SYSCALL_BIT + 301; pub const SYS_prlimit64: ::c_long = __X32_SYSCALL_BIT + 302; pub const SYS_name_to_handle_at: ::c_long = __X32_SYSCALL_BIT + 303; pub const SYS_open_by_handle_at: ::c_long = __X32_SYSCALL_BIT + 304; pub const SYS_clock_adjtime: ::c_long = __X32_SYSCALL_BIT + 305; pub const SYS_syncfs: ::c_long = __X32_SYSCALL_BIT + 306; pub const SYS_setns: ::c_long = __X32_SYSCALL_BIT + 308; pub const SYS_getcpu: ::c_long = __X32_SYSCALL_BIT + 309; pub const SYS_kcmp: ::c_long = __X32_SYSCALL_BIT + 312; pub const SYS_finit_module: ::c_long = __X32_SYSCALL_BIT + 313; pub const SYS_sched_setattr: ::c_long = __X32_SYSCALL_BIT + 314; pub const SYS_sched_getattr: ::c_long = __X32_SYSCALL_BIT + 315; pub const SYS_renameat2: ::c_long = __X32_SYSCALL_BIT + 316; pub const SYS_seccomp: ::c_long = __X32_SYSCALL_BIT + 317; pub const SYS_getrandom: ::c_long = __X32_SYSCALL_BIT + 318; pub const SYS_memfd_create: ::c_long = __X32_SYSCALL_BIT + 319; pub const SYS_kexec_file_load: ::c_long = __X32_SYSCALL_BIT + 320; pub const SYS_bpf: ::c_long = __X32_SYSCALL_BIT + 321; pub const SYS_userfaultfd: ::c_long = __X32_SYSCALL_BIT + 323; pub const SYS_membarrier: ::c_long = __X32_SYSCALL_BIT + 324; pub const SYS_mlock2: ::c_long = __X32_SYSCALL_BIT + 325; pub const SYS_copy_file_range: ::c_long = __X32_SYSCALL_BIT + 326; pub const SYS_pkey_mprotect: ::c_long = __X32_SYSCALL_BIT + 329; pub const SYS_pkey_alloc: ::c_long = __X32_SYSCALL_BIT + 330; pub const SYS_pkey_free: ::c_long = __X32_SYSCALL_BIT + 331; pub const SYS_statx: ::c_long = __X32_SYSCALL_BIT + 332; pub const SYS_rseq: ::c_long = __X32_SYSCALL_BIT + 334; pub const SYS_pidfd_send_signal: ::c_long = __X32_SYSCALL_BIT + 424; pub const SYS_io_uring_setup: ::c_long = __X32_SYSCALL_BIT + 425; pub const SYS_io_uring_enter: ::c_long = __X32_SYSCALL_BIT + 426; pub const SYS_io_uring_register: ::c_long = __X32_SYSCALL_BIT + 427; pub const SYS_open_tree: ::c_long = __X32_SYSCALL_BIT + 428; pub const SYS_move_mount: ::c_long = __X32_SYSCALL_BIT + 429; pub const SYS_fsopen: ::c_long = __X32_SYSCALL_BIT + 430; pub const SYS_fsconfig: ::c_long = __X32_SYSCALL_BIT + 431; pub const SYS_fsmount: ::c_long = __X32_SYSCALL_BIT + 432; pub const SYS_fspick: ::c_long = __X32_SYSCALL_BIT + 433; pub const SYS_pidfd_open: ::c_long = __X32_SYSCALL_BIT + 434; pub const SYS_clone3: ::c_long = __X32_SYSCALL_BIT + 435; pub const SYS_close_range: ::c_long = __X32_SYSCALL_BIT + 436; pub const SYS_openat2: ::c_long = __X32_SYSCALL_BIT + 437; pub const SYS_pidfd_getfd: ::c_long = __X32_SYSCALL_BIT + 438; pub const SYS_faccessat2: ::c_long = __X32_SYSCALL_BIT + 439; pub const SYS_process_madvise: ::c_long = __X32_SYSCALL_BIT + 440; pub const SYS_epoll_pwait2: ::c_long = __X32_SYSCALL_BIT + 441; pub const SYS_mount_setattr: ::c_long = __X32_SYSCALL_BIT + 442; pub const SYS_quotactl_fd: ::c_long = __X32_SYSCALL_BIT + 443; pub const SYS_landlock_create_ruleset: ::c_long = __X32_SYSCALL_BIT + 444; pub const SYS_landlock_add_rule: ::c_long = __X32_SYSCALL_BIT + 445; pub const SYS_landlock_restrict_self: ::c_long = __X32_SYSCALL_BIT + 446; pub const SYS_memfd_secret: ::c_long = __X32_SYSCALL_BIT + 447; pub const SYS_process_mrelease: ::c_long = __X32_SYSCALL_BIT + 448; pub const SYS_futex_waitv: ::c_long = __X32_SYSCALL_BIT + 449; pub const SYS_set_mempolicy_home_node: ::c_long = __X32_SYSCALL_BIT + 450; pub const SYS_rt_sigaction: ::c_long = __X32_SYSCALL_BIT + 512; pub const SYS_rt_sigreturn: ::c_long = __X32_SYSCALL_BIT + 513; pub const SYS_ioctl: ::c_long = __X32_SYSCALL_BIT + 514; pub const SYS_readv: ::c_long = __X32_SYSCALL_BIT + 515; pub const SYS_writev: ::c_long = __X32_SYSCALL_BIT + 516; pub const SYS_recvfrom: ::c_long = __X32_SYSCALL_BIT + 517; pub const SYS_sendmsg: ::c_long = __X32_SYSCALL_BIT + 518; pub const SYS_recvmsg: ::c_long = __X32_SYSCALL_BIT + 519; pub const SYS_execve: ::c_long = __X32_SYSCALL_BIT + 520; pub const SYS_ptrace: ::c_long = __X32_SYSCALL_BIT + 521; pub const SYS_rt_sigpending: ::c_long = __X32_SYSCALL_BIT + 522; pub const SYS_rt_sigtimedwait: ::c_long = __X32_SYSCALL_BIT + 523; pub const SYS_rt_sigqueueinfo: ::c_long = __X32_SYSCALL_BIT + 524; pub const SYS_sigaltstack: ::c_long = __X32_SYSCALL_BIT + 525; pub const SYS_timer_create: ::c_long = __X32_SYSCALL_BIT + 526; pub const SYS_mq_notify: ::c_long = __X32_SYSCALL_BIT + 527; pub const SYS_kexec_load: ::c_long = __X32_SYSCALL_BIT + 528; pub const SYS_waitid: ::c_long = __X32_SYSCALL_BIT + 529; pub const SYS_set_robust_list: ::c_long = __X32_SYSCALL_BIT + 530; pub const SYS_get_robust_list: ::c_long = __X32_SYSCALL_BIT + 531; pub const SYS_vmsplice: ::c_long = __X32_SYSCALL_BIT + 532; pub const SYS_move_pages: ::c_long = __X32_SYSCALL_BIT + 533; pub const SYS_preadv: ::c_long = __X32_SYSCALL_BIT + 534; pub const SYS_pwritev: ::c_long = __X32_SYSCALL_BIT + 535; pub const SYS_rt_tgsigqueueinfo: ::c_long = __X32_SYSCALL_BIT + 536; pub const SYS_recvmmsg: ::c_long = __X32_SYSCALL_BIT + 537; pub const SYS_sendmmsg: ::c_long = __X32_SYSCALL_BIT + 538; pub const SYS_process_vm_readv: ::c_long = __X32_SYSCALL_BIT + 539; pub const SYS_process_vm_writev: ::c_long = __X32_SYSCALL_BIT + 540; pub const SYS_setsockopt: ::c_long = __X32_SYSCALL_BIT + 541; pub const SYS_getsockopt: ::c_long = __X32_SYSCALL_BIT + 542; pub const SYS_io_setup: ::c_long = __X32_SYSCALL_BIT + 543; pub const SYS_io_submit: ::c_long = __X32_SYSCALL_BIT + 544; pub const SYS_execveat: ::c_long = __X32_SYSCALL_BIT + 545; pub const SYS_preadv2: ::c_long = __X32_SYSCALL_BIT + 546; pub const SYS_pwritev2: ::c_long = __X32_SYSCALL_BIT + 547; libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs0000644000175000017500000004232514661133735023520 0ustar jamespagejamespageuse pthread_mutex_t; pub type c_long = i64; pub type c_ulong = u64; s! { pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } } pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; align_const! { #[cfg(target_endian = "little")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "little")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; #[cfg(target_endian = "big")] pub const PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP: ::pthread_mutex_t = pthread_mutex_t { size: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], }; } // Syscall table pub const SYS_read: ::c_long = 0; pub const SYS_write: ::c_long = 1; pub const SYS_open: ::c_long = 2; pub const SYS_close: ::c_long = 3; pub const SYS_stat: ::c_long = 4; pub const SYS_fstat: ::c_long = 5; pub const SYS_lstat: ::c_long = 6; pub const SYS_poll: ::c_long = 7; pub const SYS_lseek: ::c_long = 8; pub const SYS_mmap: ::c_long = 9; pub const SYS_mprotect: ::c_long = 10; pub const SYS_munmap: ::c_long = 11; pub const SYS_brk: ::c_long = 12; pub const SYS_rt_sigaction: ::c_long = 13; pub const SYS_rt_sigprocmask: ::c_long = 14; pub const SYS_rt_sigreturn: ::c_long = 15; pub const SYS_ioctl: ::c_long = 16; pub const SYS_pread64: ::c_long = 17; pub const SYS_pwrite64: ::c_long = 18; pub const SYS_readv: ::c_long = 19; pub const SYS_writev: ::c_long = 20; pub const SYS_access: ::c_long = 21; pub const SYS_pipe: ::c_long = 22; pub const SYS_select: ::c_long = 23; pub const SYS_sched_yield: ::c_long = 24; pub const SYS_mremap: ::c_long = 25; pub const SYS_msync: ::c_long = 26; pub const SYS_mincore: ::c_long = 27; pub const SYS_madvise: ::c_long = 28; pub const SYS_shmget: ::c_long = 29; pub const SYS_shmat: ::c_long = 30; pub const SYS_shmctl: ::c_long = 31; pub const SYS_dup: ::c_long = 32; pub const SYS_dup2: ::c_long = 33; pub const SYS_pause: ::c_long = 34; pub const SYS_nanosleep: ::c_long = 35; pub const SYS_getitimer: ::c_long = 36; pub const SYS_alarm: ::c_long = 37; pub const SYS_setitimer: ::c_long = 38; pub const SYS_getpid: ::c_long = 39; pub const SYS_sendfile: ::c_long = 40; pub const SYS_socket: ::c_long = 41; pub const SYS_connect: ::c_long = 42; pub const SYS_accept: ::c_long = 43; pub const SYS_sendto: ::c_long = 44; pub const SYS_recvfrom: ::c_long = 45; pub const SYS_sendmsg: ::c_long = 46; pub const SYS_recvmsg: ::c_long = 47; pub const SYS_shutdown: ::c_long = 48; pub const SYS_bind: ::c_long = 49; pub const SYS_listen: ::c_long = 50; pub const SYS_getsockname: ::c_long = 51; pub const SYS_getpeername: ::c_long = 52; pub const SYS_socketpair: ::c_long = 53; pub const SYS_setsockopt: ::c_long = 54; pub const SYS_getsockopt: ::c_long = 55; pub const SYS_clone: ::c_long = 56; pub const SYS_fork: ::c_long = 57; pub const SYS_vfork: ::c_long = 58; pub const SYS_execve: ::c_long = 59; pub const SYS_exit: ::c_long = 60; pub const SYS_wait4: ::c_long = 61; pub const SYS_kill: ::c_long = 62; pub const SYS_uname: ::c_long = 63; pub const SYS_semget: ::c_long = 64; pub const SYS_semop: ::c_long = 65; pub const SYS_semctl: ::c_long = 66; pub const SYS_shmdt: ::c_long = 67; pub const SYS_msgget: ::c_long = 68; pub const SYS_msgsnd: ::c_long = 69; pub const SYS_msgrcv: ::c_long = 70; pub const SYS_msgctl: ::c_long = 71; pub const SYS_fcntl: ::c_long = 72; pub const SYS_flock: ::c_long = 73; pub const SYS_fsync: ::c_long = 74; pub const SYS_fdatasync: ::c_long = 75; pub const SYS_truncate: ::c_long = 76; pub const SYS_ftruncate: ::c_long = 77; pub const SYS_getdents: ::c_long = 78; pub const SYS_getcwd: ::c_long = 79; pub const SYS_chdir: ::c_long = 80; pub const SYS_fchdir: ::c_long = 81; pub const SYS_rename: ::c_long = 82; pub const SYS_mkdir: ::c_long = 83; pub const SYS_rmdir: ::c_long = 84; pub const SYS_creat: ::c_long = 85; pub const SYS_link: ::c_long = 86; pub const SYS_unlink: ::c_long = 87; pub const SYS_symlink: ::c_long = 88; pub const SYS_readlink: ::c_long = 89; pub const SYS_chmod: ::c_long = 90; pub const SYS_fchmod: ::c_long = 91; pub const SYS_chown: ::c_long = 92; pub const SYS_fchown: ::c_long = 93; pub const SYS_lchown: ::c_long = 94; pub const SYS_umask: ::c_long = 95; pub const SYS_gettimeofday: ::c_long = 96; pub const SYS_getrlimit: ::c_long = 97; pub const SYS_getrusage: ::c_long = 98; pub const SYS_sysinfo: ::c_long = 99; pub const SYS_times: ::c_long = 100; pub const SYS_ptrace: ::c_long = 101; pub const SYS_getuid: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_getgid: ::c_long = 104; pub const SYS_setuid: ::c_long = 105; pub const SYS_setgid: ::c_long = 106; pub const SYS_geteuid: ::c_long = 107; pub const SYS_getegid: ::c_long = 108; pub const SYS_setpgid: ::c_long = 109; pub const SYS_getppid: ::c_long = 110; pub const SYS_getpgrp: ::c_long = 111; pub const SYS_setsid: ::c_long = 112; pub const SYS_setreuid: ::c_long = 113; pub const SYS_setregid: ::c_long = 114; pub const SYS_getgroups: ::c_long = 115; pub const SYS_setgroups: ::c_long = 116; pub const SYS_setresuid: ::c_long = 117; pub const SYS_getresuid: ::c_long = 118; pub const SYS_setresgid: ::c_long = 119; pub const SYS_getresgid: ::c_long = 120; pub const SYS_getpgid: ::c_long = 121; pub const SYS_setfsuid: ::c_long = 122; pub const SYS_setfsgid: ::c_long = 123; pub const SYS_getsid: ::c_long = 124; pub const SYS_capget: ::c_long = 125; pub const SYS_capset: ::c_long = 126; pub const SYS_rt_sigpending: ::c_long = 127; pub const SYS_rt_sigtimedwait: ::c_long = 128; pub const SYS_rt_sigqueueinfo: ::c_long = 129; pub const SYS_rt_sigsuspend: ::c_long = 130; pub const SYS_sigaltstack: ::c_long = 131; pub const SYS_utime: ::c_long = 132; pub const SYS_mknod: ::c_long = 133; pub const SYS_uselib: ::c_long = 134; pub const SYS_personality: ::c_long = 135; pub const SYS_ustat: ::c_long = 136; pub const SYS_statfs: ::c_long = 137; pub const SYS_fstatfs: ::c_long = 138; pub const SYS_sysfs: ::c_long = 139; pub const SYS_getpriority: ::c_long = 140; pub const SYS_setpriority: ::c_long = 141; pub const SYS_sched_setparam: ::c_long = 142; pub const SYS_sched_getparam: ::c_long = 143; pub const SYS_sched_setscheduler: ::c_long = 144; pub const SYS_sched_getscheduler: ::c_long = 145; pub const SYS_sched_get_priority_max: ::c_long = 146; pub const SYS_sched_get_priority_min: ::c_long = 147; pub const SYS_sched_rr_get_interval: ::c_long = 148; pub const SYS_mlock: ::c_long = 149; pub const SYS_munlock: ::c_long = 150; pub const SYS_mlockall: ::c_long = 151; pub const SYS_munlockall: ::c_long = 152; pub const SYS_vhangup: ::c_long = 153; pub const SYS_modify_ldt: ::c_long = 154; pub const SYS_pivot_root: ::c_long = 155; pub const SYS__sysctl: ::c_long = 156; pub const SYS_prctl: ::c_long = 157; pub const SYS_arch_prctl: ::c_long = 158; pub const SYS_adjtimex: ::c_long = 159; pub const SYS_setrlimit: ::c_long = 160; pub const SYS_chroot: ::c_long = 161; pub const SYS_sync: ::c_long = 162; pub const SYS_acct: ::c_long = 163; pub const SYS_settimeofday: ::c_long = 164; pub const SYS_mount: ::c_long = 165; pub const SYS_umount2: ::c_long = 166; pub const SYS_swapon: ::c_long = 167; pub const SYS_swapoff: ::c_long = 168; pub const SYS_reboot: ::c_long = 169; pub const SYS_sethostname: ::c_long = 170; pub const SYS_setdomainname: ::c_long = 171; pub const SYS_iopl: ::c_long = 172; pub const SYS_ioperm: ::c_long = 173; pub const SYS_create_module: ::c_long = 174; pub const SYS_init_module: ::c_long = 175; pub const SYS_delete_module: ::c_long = 176; pub const SYS_get_kernel_syms: ::c_long = 177; pub const SYS_query_module: ::c_long = 178; pub const SYS_quotactl: ::c_long = 179; pub const SYS_nfsservctl: ::c_long = 180; pub const SYS_getpmsg: ::c_long = 181; pub const SYS_putpmsg: ::c_long = 182; pub const SYS_afs_syscall: ::c_long = 183; pub const SYS_tuxcall: ::c_long = 184; pub const SYS_security: ::c_long = 185; pub const SYS_gettid: ::c_long = 186; pub const SYS_readahead: ::c_long = 187; pub const SYS_setxattr: ::c_long = 188; pub const SYS_lsetxattr: ::c_long = 189; pub const SYS_fsetxattr: ::c_long = 190; pub const SYS_getxattr: ::c_long = 191; pub const SYS_lgetxattr: ::c_long = 192; pub const SYS_fgetxattr: ::c_long = 193; pub const SYS_listxattr: ::c_long = 194; pub const SYS_llistxattr: ::c_long = 195; pub const SYS_flistxattr: ::c_long = 196; pub const SYS_removexattr: ::c_long = 197; pub const SYS_lremovexattr: ::c_long = 198; pub const SYS_fremovexattr: ::c_long = 199; pub const SYS_tkill: ::c_long = 200; pub const SYS_time: ::c_long = 201; pub const SYS_futex: ::c_long = 202; pub const SYS_sched_setaffinity: ::c_long = 203; pub const SYS_sched_getaffinity: ::c_long = 204; pub const SYS_set_thread_area: ::c_long = 205; pub const SYS_io_setup: ::c_long = 206; pub const SYS_io_destroy: ::c_long = 207; pub const SYS_io_getevents: ::c_long = 208; pub const SYS_io_submit: ::c_long = 209; pub const SYS_io_cancel: ::c_long = 210; pub const SYS_get_thread_area: ::c_long = 211; pub const SYS_lookup_dcookie: ::c_long = 212; pub const SYS_epoll_create: ::c_long = 213; pub const SYS_epoll_ctl_old: ::c_long = 214; pub const SYS_epoll_wait_old: ::c_long = 215; pub const SYS_remap_file_pages: ::c_long = 216; pub const SYS_getdents64: ::c_long = 217; pub const SYS_set_tid_address: ::c_long = 218; pub const SYS_restart_syscall: ::c_long = 219; pub const SYS_semtimedop: ::c_long = 220; pub const SYS_fadvise64: ::c_long = 221; pub const SYS_timer_create: ::c_long = 222; pub const SYS_timer_settime: ::c_long = 223; pub const SYS_timer_gettime: ::c_long = 224; pub const SYS_timer_getoverrun: ::c_long = 225; pub const SYS_timer_delete: ::c_long = 226; pub const SYS_clock_settime: ::c_long = 227; pub const SYS_clock_gettime: ::c_long = 228; pub const SYS_clock_getres: ::c_long = 229; pub const SYS_clock_nanosleep: ::c_long = 230; pub const SYS_exit_group: ::c_long = 231; pub const SYS_epoll_wait: ::c_long = 232; pub const SYS_epoll_ctl: ::c_long = 233; pub const SYS_tgkill: ::c_long = 234; pub const SYS_utimes: ::c_long = 235; pub const SYS_vserver: ::c_long = 236; pub const SYS_mbind: ::c_long = 237; pub const SYS_set_mempolicy: ::c_long = 238; pub const SYS_get_mempolicy: ::c_long = 239; pub const SYS_mq_open: ::c_long = 240; pub const SYS_mq_unlink: ::c_long = 241; pub const SYS_mq_timedsend: ::c_long = 242; pub const SYS_mq_timedreceive: ::c_long = 243; pub const SYS_mq_notify: ::c_long = 244; pub const SYS_mq_getsetattr: ::c_long = 245; pub const SYS_kexec_load: ::c_long = 246; pub const SYS_waitid: ::c_long = 247; pub const SYS_add_key: ::c_long = 248; pub const SYS_request_key: ::c_long = 249; pub const SYS_keyctl: ::c_long = 250; pub const SYS_ioprio_set: ::c_long = 251; pub const SYS_ioprio_get: ::c_long = 252; pub const SYS_inotify_init: ::c_long = 253; pub const SYS_inotify_add_watch: ::c_long = 254; pub const SYS_inotify_rm_watch: ::c_long = 255; pub const SYS_migrate_pages: ::c_long = 256; pub const SYS_openat: ::c_long = 257; pub const SYS_mkdirat: ::c_long = 258; pub const SYS_mknodat: ::c_long = 259; pub const SYS_fchownat: ::c_long = 260; pub const SYS_futimesat: ::c_long = 261; pub const SYS_newfstatat: ::c_long = 262; pub const SYS_unlinkat: ::c_long = 263; pub const SYS_renameat: ::c_long = 264; pub const SYS_linkat: ::c_long = 265; pub const SYS_symlinkat: ::c_long = 266; pub const SYS_readlinkat: ::c_long = 267; pub const SYS_fchmodat: ::c_long = 268; pub const SYS_faccessat: ::c_long = 269; pub const SYS_pselect6: ::c_long = 270; pub const SYS_ppoll: ::c_long = 271; pub const SYS_unshare: ::c_long = 272; pub const SYS_set_robust_list: ::c_long = 273; pub const SYS_get_robust_list: ::c_long = 274; pub const SYS_splice: ::c_long = 275; pub const SYS_tee: ::c_long = 276; pub const SYS_sync_file_range: ::c_long = 277; pub const SYS_vmsplice: ::c_long = 278; pub const SYS_move_pages: ::c_long = 279; pub const SYS_utimensat: ::c_long = 280; pub const SYS_epoll_pwait: ::c_long = 281; pub const SYS_signalfd: ::c_long = 282; pub const SYS_timerfd_create: ::c_long = 283; pub const SYS_eventfd: ::c_long = 284; pub const SYS_fallocate: ::c_long = 285; pub const SYS_timerfd_settime: ::c_long = 286; pub const SYS_timerfd_gettime: ::c_long = 287; pub const SYS_accept4: ::c_long = 288; pub const SYS_signalfd4: ::c_long = 289; pub const SYS_eventfd2: ::c_long = 290; pub const SYS_epoll_create1: ::c_long = 291; pub const SYS_dup3: ::c_long = 292; pub const SYS_pipe2: ::c_long = 293; pub const SYS_inotify_init1: ::c_long = 294; pub const SYS_preadv: ::c_long = 295; pub const SYS_pwritev: ::c_long = 296; pub const SYS_rt_tgsigqueueinfo: ::c_long = 297; pub const SYS_perf_event_open: ::c_long = 298; pub const SYS_recvmmsg: ::c_long = 299; pub const SYS_fanotify_init: ::c_long = 300; pub const SYS_fanotify_mark: ::c_long = 301; pub const SYS_prlimit64: ::c_long = 302; pub const SYS_name_to_handle_at: ::c_long = 303; pub const SYS_open_by_handle_at: ::c_long = 304; pub const SYS_clock_adjtime: ::c_long = 305; pub const SYS_syncfs: ::c_long = 306; pub const SYS_sendmmsg: ::c_long = 307; pub const SYS_setns: ::c_long = 308; pub const SYS_getcpu: ::c_long = 309; pub const SYS_process_vm_readv: ::c_long = 310; pub const SYS_process_vm_writev: ::c_long = 311; pub const SYS_kcmp: ::c_long = 312; pub const SYS_finit_module: ::c_long = 313; pub const SYS_sched_setattr: ::c_long = 314; pub const SYS_sched_getattr: ::c_long = 315; pub const SYS_renameat2: ::c_long = 316; pub const SYS_seccomp: ::c_long = 317; pub const SYS_getrandom: ::c_long = 318; pub const SYS_memfd_create: ::c_long = 319; pub const SYS_kexec_file_load: ::c_long = 320; pub const SYS_bpf: ::c_long = 321; pub const SYS_execveat: ::c_long = 322; pub const SYS_userfaultfd: ::c_long = 323; pub const SYS_membarrier: ::c_long = 324; pub const SYS_mlock2: ::c_long = 325; pub const SYS_copy_file_range: ::c_long = 326; pub const SYS_preadv2: ::c_long = 327; pub const SYS_pwritev2: ::c_long = 328; pub const SYS_pkey_mprotect: ::c_long = 329; pub const SYS_pkey_alloc: ::c_long = 330; pub const SYS_pkey_free: ::c_long = 331; pub const SYS_statx: ::c_long = 332; pub const SYS_rseq: ::c_long = 334; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_pidfd_open: ::c_long = 434; pub const SYS_clone3: ::c_long = 435; pub const SYS_close_range: ::c_long = 436; pub const SYS_openat2: ::c_long = 437; pub const SYS_pidfd_getfd: ::c_long = 438; pub const SYS_faccessat2: ::c_long = 439; pub const SYS_process_madvise: ::c_long = 440; pub const SYS_epoll_pwait2: ::c_long = 441; pub const SYS_mount_setattr: ::c_long = 442; pub const SYS_quotactl_fd: ::c_long = 443; pub const SYS_landlock_create_ruleset: ::c_long = 444; pub const SYS_landlock_add_rule: ::c_long = 445; pub const SYS_landlock_restrict_self: ::c_long = 446; pub const SYS_memfd_secret: ::c_long = 447; pub const SYS_process_mrelease: ::c_long = 448; pub const SYS_futex_waitv: ::c_long = 449; pub const SYS_set_mempolicy_home_node: ::c_long = 450; extern "C" { pub fn sysctl( name: *mut ::c_int, namelen: ::c_int, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; } libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs0000644000175000017500000006253614661133735023011 0ustar jamespagejamespage//! x86_64-specific definitions for 64-bit linux-like values pub type c_char = i8; pub type wchar_t = i32; pub type nlink_t = u64; pub type blksize_t = i64; pub type greg_t = i64; pub type suseconds_t = i64; pub type __u64 = ::c_ulonglong; pub type __s64 = ::c_longlong; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, #[cfg(target_arch = "sparc64")] __reserved0: ::c_int, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct statfs { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, f_spare: [::__fsword_t; 5], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off64_t, pub l_len: ::off64_t, pub l_pid: ::pid_t, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, #[doc(hidden)] #[deprecated( since="0.2.54", note="Please leave a comment on \ https://github.com/rust-lang/libc/pull/1316 if you're using \ this field" )] pub _pad: [::c_int; 29], _align: [u64; 0], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: i64, pub st_mtime: ::time_t, pub st_mtime_nsec: i64, pub st_ctime: ::time_t, pub st_ctime_nsec: i64, __unused: [i64; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino64_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, __pad0: ::c_int, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt64_t, pub st_atime: ::time_t, pub st_atime_nsec: i64, pub st_mtime: ::time_t, pub st_mtime_nsec: i64, pub st_ctime: ::time_t, pub st_ctime_nsec: i64, __reserved: [i64; 3], } pub struct statfs64 { pub f_type: ::__fsword_t, pub f_bsize: ::__fsword_t, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_namelen: ::__fsword_t, pub f_frsize: ::__fsword_t, pub f_flags: ::__fsword_t, pub f_spare: [::__fsword_t; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_attr_t { #[cfg(target_pointer_width = "32")] __size: [u32; 8], #[cfg(target_pointer_width = "64")] __size: [u64; 7] } pub struct _libc_fpxreg { pub significand: [u16; 4], pub exponent: u16, __private: [u16; 3], } pub struct _libc_xmmreg { pub element: [u32; 4], } pub struct _libc_fpstate { pub cwd: u16, pub swd: u16, pub ftw: u16, pub fop: u16, pub rip: u64, pub rdp: u64, pub mxcsr: u32, pub mxcr_mask: u32, pub _st: [_libc_fpxreg; 8], pub _xmm: [_libc_xmmreg; 16], __private: [u64; 12], } pub struct user_regs_struct { pub r15: ::c_ulonglong, pub r14: ::c_ulonglong, pub r13: ::c_ulonglong, pub r12: ::c_ulonglong, pub rbp: ::c_ulonglong, pub rbx: ::c_ulonglong, pub r11: ::c_ulonglong, pub r10: ::c_ulonglong, pub r9: ::c_ulonglong, pub r8: ::c_ulonglong, pub rax: ::c_ulonglong, pub rcx: ::c_ulonglong, pub rdx: ::c_ulonglong, pub rsi: ::c_ulonglong, pub rdi: ::c_ulonglong, pub orig_rax: ::c_ulonglong, pub rip: ::c_ulonglong, pub cs: ::c_ulonglong, pub eflags: ::c_ulonglong, pub rsp: ::c_ulonglong, pub ss: ::c_ulonglong, pub fs_base: ::c_ulonglong, pub gs_base: ::c_ulonglong, pub ds: ::c_ulonglong, pub es: ::c_ulonglong, pub fs: ::c_ulonglong, pub gs: ::c_ulonglong, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: ::c_int, pub i387: user_fpregs_struct, pub u_tsize: ::c_ulonglong, pub u_dsize: ::c_ulonglong, pub u_ssize: ::c_ulonglong, pub start_code: ::c_ulonglong, pub start_stack: ::c_ulonglong, pub signal: ::c_longlong, __reserved: ::c_int, #[cfg(target_pointer_width = "32")] __pad1: u32, pub u_ar0: *mut user_regs_struct, #[cfg(target_pointer_width = "32")] __pad2: u32, pub u_fpstate: *mut user_fpregs_struct, pub magic: ::c_ulonglong, pub u_comm: [::c_char; 32], pub u_debugreg: [::c_ulonglong; 8], } pub struct mcontext_t { pub gregs: [greg_t; 23], pub fpregs: *mut _libc_fpstate, __private: [u64; 8], } pub struct ipc_perm { pub __key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::c_ushort, __pad1: ::c_ushort, pub __seq: ::c_ushort, __pad2: ::c_ushort, __unused1: u64, __unused2: u64 } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_cpid: ::pid_t, pub shm_lpid: ::pid_t, pub shm_nattch: ::shmatt_t, __unused4: u64, __unused5: u64 } pub struct ptrace_rseq_configuration { pub rseq_abi_pointer: ::__u64, pub rseq_abi_size: ::__u32, pub signature: ::__u32, pub flags: ::__u32, pub pad: ::__u32, } } s_no_extra_traits! { pub struct user_fpregs_struct { pub cwd: ::c_ushort, pub swd: ::c_ushort, pub ftw: ::c_ushort, pub fop: ::c_ushort, pub rip: ::c_ulonglong, pub rdp: ::c_ulonglong, pub mxcsr: ::c_uint, pub mxcr_mask: ::c_uint, pub st_space: [::c_uint; 32], pub xmm_space: [::c_uint; 64], padding: [::c_uint; 24], } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask: ::sigset_t, __private: [u8; 512], // FIXME: the shadow stack field requires glibc >= 2.28. // Re-add once we drop compatibility with glibc versions older than // 2.28. // // __ssp: [::c_ulonglong; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for user_fpregs_struct { fn eq(&self, other: &user_fpregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self.st_space == other.st_space && self .xmm_space .iter() .zip(other.xmm_space.iter()) .all(|(a,b)| a == b) // Ignore padding field } } impl Eq for user_fpregs_struct {} impl ::fmt::Debug for user_fpregs_struct { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("user_fpregs_struct") .field("cwd", &self.cwd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("st_space", &self.st_space) // FIXME: .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl ::hash::Hash for user_fpregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask == other.uc_sigmask // Ignore __private field } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask", &self.uc_sigmask) // Ignore __private field .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask.hash(state); // Ignore __private field } } } } pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const VEOF: usize = 4; pub const RTLD_DEEPBIND: ::c_int = 0x8; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 1052672; pub const O_RSYNC: ::c_int = 1052672; pub const O_DSYNC: ::c_int = 4096; pub const O_FSYNC: ::c_int = 0x101000; pub const O_NOATIME: ::c_int = 0o1000000; pub const O_PATH: ::c_int = 0o10000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EBADMSG: ::c_int = 74; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const EHWPOISON: ::c_int = 133; pub const ERFKILL: ::c_int = 132; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const PTRACE_DETACH: ::c_uint = 17; pub const PTRACE_GET_RSEQ_CONFIGURATION: ::c_uint = 0x420f; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const SFD_NONBLOCK: ::c_int = 0x0800; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const SFD_CLOEXEC: ::c_int = 0x080000; pub const NCCS: usize = 32; pub const O_TRUNC: ::c_int = 512; pub const O_CLOEXEC: ::c_int = 0x80000; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_32BIT: ::c_int = 0x0040; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const MAP_SYNC: ::c_int = 0x080000; pub const EDEADLOCK: ::c_int = 35; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const PTRACE_GETFPREGS: ::c_uint = 14; pub const PTRACE_SETFPREGS: ::c_uint = 15; pub const PTRACE_GETFPXREGS: ::c_uint = 18; pub const PTRACE_SETFPXREGS: ::c_uint = 19; pub const PTRACE_GETREGS: ::c_uint = 12; pub const PTRACE_SETREGS: ::c_uint = 13; pub const PTRACE_PEEKSIGINFO_SHARED: ::c_uint = 1; pub const PTRACE_SYSEMU: ::c_uint = 31; pub const PTRACE_SYSEMU_SINGLESTEP: ::c_uint = 32; pub const PR_GET_SPECULATION_CTRL: ::c_int = 52; pub const PR_SET_SPECULATION_CTRL: ::c_int = 53; pub const PR_SPEC_NOT_AFFECTED: ::c_uint = 0; pub const PR_SPEC_PRCTL: ::c_uint = 1 << 0; pub const PR_SPEC_ENABLE: ::c_uint = 1 << 1; pub const PR_SPEC_DISABLE: ::c_uint = 1 << 2; pub const PR_SPEC_FORCE_DISABLE: ::c_uint = 1 << 3; pub const PR_SPEC_DISABLE_NOEXEC: ::c_uint = 1 << 4; pub const PR_SPEC_STORE_BYPASS: ::c_int = 0; pub const PR_SPEC_INDIRECT_BRANCH: ::c_int = 1; // FIXME: perharps for later //pub const PR_SPEC_L1D_FLUSH: ::c_int = 2; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0x00010000; // offsets in user_regs_structs, from sys/reg.h pub const R15: ::c_int = 0; pub const R14: ::c_int = 1; pub const R13: ::c_int = 2; pub const R12: ::c_int = 3; pub const RBP: ::c_int = 4; pub const RBX: ::c_int = 5; pub const R11: ::c_int = 6; pub const R10: ::c_int = 7; pub const R9: ::c_int = 8; pub const R8: ::c_int = 9; pub const RAX: ::c_int = 10; pub const RCX: ::c_int = 11; pub const RDX: ::c_int = 12; pub const RSI: ::c_int = 13; pub const RDI: ::c_int = 14; pub const ORIG_RAX: ::c_int = 15; pub const RIP: ::c_int = 16; pub const CS: ::c_int = 17; pub const EFLAGS: ::c_int = 18; pub const RSP: ::c_int = 19; pub const SS: ::c_int = 20; pub const FS_BASE: ::c_int = 21; pub const GS_BASE: ::c_int = 22; pub const DS: ::c_int = 23; pub const ES: ::c_int = 24; pub const FS: ::c_int = 25; pub const GS: ::c_int = 26; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_R8: ::c_int = 0; pub const REG_R9: ::c_int = 1; pub const REG_R10: ::c_int = 2; pub const REG_R11: ::c_int = 3; pub const REG_R12: ::c_int = 4; pub const REG_R13: ::c_int = 5; pub const REG_R14: ::c_int = 6; pub const REG_R15: ::c_int = 7; pub const REG_RDI: ::c_int = 8; pub const REG_RSI: ::c_int = 9; pub const REG_RBP: ::c_int = 10; pub const REG_RBX: ::c_int = 11; pub const REG_RDX: ::c_int = 12; pub const REG_RAX: ::c_int = 13; pub const REG_RCX: ::c_int = 14; pub const REG_RSP: ::c_int = 15; pub const REG_RIP: ::c_int = 16; pub const REG_EFL: ::c_int = 17; pub const REG_CSGSFS: ::c_int = 18; pub const REG_ERR: ::c_int = 19; pub const REG_TRAPNO: ::c_int = 20; pub const REG_OLDMASK: ::c_int = 21; pub const REG_CR2: ::c_int = 22; extern "C" { pub fn getcontext(ucp: *mut ucontext_t) -> ::c_int; pub fn setcontext(ucp: *const ucontext_t) -> ::c_int; pub fn makecontext(ucp: *mut ucontext_t, func: extern "C" fn(), argc: ::c_int, ...); pub fn swapcontext(uocp: *mut ucontext_t, ucp: *const ucontext_t) -> ::c_int; pub fn iopl(level: ::c_int) -> ::c_int; pub fn ioperm(from: ::c_ulong, num: ::c_ulong, turn_on: ::c_int) -> ::c_int; } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod x32; pub use self::x32::*; } else { mod not_x32; pub use self::not_x32::*; } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/linux/gnu/b64/x86_64/align.rs0000644000175000017500000000114714661133735023313 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } s! { #[repr(align(8))] pub struct clone_args { pub flags: ::c_ulonglong, pub pidfd: ::c_ulonglong, pub child_tid: ::c_ulonglong, pub parent_tid: ::c_ulonglong, pub exit_signal: ::c_ulonglong, pub stack: ::c_ulonglong, pub stack_size: ::c_ulonglong, pub tls: ::c_ulonglong, pub set_tid: ::c_ulonglong, pub set_tid_size: ::c_ulonglong, pub cgroup: ::c_ulonglong, } } libc/src/unix/linux_like/linux/gnu/no_align.rs0000644000175000017500000000040214661133735022447 0ustar jamespagejamespages! { // FIXME this is actually a union pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], __align: [::c_long; 0], } } libc/src/unix/linux_like/linux/gnu/align.rs0000644000175000017500000000057214661133735021763 0ustar jamespagejamespages! { // FIXME this is actually a union #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { #[cfg(target_pointer_width = "32")] __size: [::c_char; 16], #[cfg(target_pointer_width = "64")] __size: [::c_char; 32], } } libc/src/unix/linux_like/linux/non_exhaustive.rs0000644000175000017500000000025114661133735023131 0ustar jamespagejamespages! { // linux/openat2.h #[non_exhaustive] pub struct open_how { pub flags: ::__u64, pub mode: ::__u64, pub resolve: ::__u64, } } libc/src/unix/linux_like/linux/no_align.rs0000644000175000017500000001434214661133735021666 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { pub struct pthread_mutexattr_t { #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "riscv64", target_arch = "riscv32", target_arch = "loongarch64", all(target_arch = "aarch64", any(target_env = "musl", target_env = "ohos"))))] __align: [::c_int; 0], #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "riscv64", target_arch = "riscv32", target_arch = "loongarch64", all(target_arch = "aarch64", any(target_env = "musl", target_env = "ohos")))))] __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } pub struct pthread_rwlockattr_t { #[cfg(any(target_env = "musl", target_env = "ohos"))] __align: [::c_int; 0], #[cfg(not(any(target_env = "musl", target_env = "ohos")))] __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCKATTR_T], } pub struct pthread_condattr_t { __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } pub struct pthread_barrierattr_t { __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_BARRIERATTR_T], } pub struct fanotify_event_metadata { __align: [::c_long; 0], pub event_len: __u32, pub vers: __u8, pub reserved: __u8, pub metadata_len: __u16, pub mask: __u64, pub fd: ::c_int, pub pid: ::c_int, } } s_no_extra_traits! { pub struct pthread_cond_t { #[cfg(any(target_env = "musl", target_env = "ohos"))] __align: [*const ::c_void; 0], #[cfg(not(any(target_env = "musl", target_env = "ohos")))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_COND_T], } pub struct pthread_mutex_t { #[cfg(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", all(target_arch = "x86_64", target_pointer_width = "32")))] __align: [::c_long; 0], #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", all(target_arch = "x86_64", target_pointer_width = "32"))))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } pub struct pthread_rwlock_t { #[cfg(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", all(target_arch = "x86_64", target_pointer_width = "32")))] __align: [::c_long; 0], #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", all(target_arch = "x86_64", target_pointer_width = "32"))))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } pub struct pthread_barrier_t { #[cfg(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", all(target_arch = "x86_64", target_pointer_width = "32")))] __align: [::c_long; 0], #[cfg(not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", all(target_arch = "x86_64", target_pointer_width = "32"))))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_BARRIER_T], } } }; } libc/src/unix/linux_like/linux/align.rs0000644000175000017500000002125014661133735021166 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { #[cfg_attr(any(target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "aarch64", target_arch = "riscv64", target_arch = "riscv32", target_arch = "loongarch64"), repr(align(4)))] #[cfg_attr(not(any(target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "s390x", target_arch = "sparc64", target_arch = "aarch64", target_arch = "riscv64", target_arch = "riscv32", target_arch = "loongarch64")), repr(align(8)))] pub struct pthread_mutexattr_t { #[doc(hidden)] size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[cfg_attr(any(target_env = "musl", target_env = "ohos", target_pointer_width = "32"), repr(align(4)))] #[cfg_attr(all(not(target_env = "musl"), not(target_env = "ohos"), target_pointer_width = "64"), repr(align(8)))] pub struct pthread_rwlockattr_t { #[doc(hidden)] size: [u8; ::__SIZEOF_PTHREAD_RWLOCKATTR_T], } #[repr(align(4))] pub struct pthread_condattr_t { #[doc(hidden)] size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } #[repr(align(4))] pub struct pthread_barrierattr_t { #[doc(hidden)] size: [u8; ::__SIZEOF_PTHREAD_BARRIERATTR_T], } #[repr(align(8))] pub struct fanotify_event_metadata { pub event_len: __u32, pub vers: __u8, pub reserved: __u8, pub metadata_len: __u16, pub mask: __u64, pub fd: ::c_int, pub pid: ::c_int, } } s_no_extra_traits! { #[cfg_attr(all(any(target_env = "musl", target_env = "ohos"), target_pointer_width = "32"), repr(align(4)))] #[cfg_attr(all(any(target_env = "musl", target_env = "ohos"), target_pointer_width = "64"), repr(align(8)))] #[cfg_attr(all(not(any(target_env = "musl", target_env = "ohos")), target_arch = "x86"), repr(align(4)))] #[cfg_attr(all(not(any(target_env = "musl", target_env = "ohos")), not(target_arch = "x86")), repr(align(8)))] pub struct pthread_cond_t { #[doc(hidden)] size: [u8; ::__SIZEOF_PTHREAD_COND_T], } #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86")), repr(align(4)))] #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86"))), repr(align(8)))] pub struct pthread_mutex_t { #[doc(hidden)] size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86")), repr(align(4)))] #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86"))), repr(align(8)))] pub struct pthread_rwlock_t { size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86")), repr(align(4)))] #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "arm", target_arch = "hexagon", target_arch = "m68k", target_arch = "csky", target_arch = "powerpc", target_arch = "sparc", target_arch = "x86_64", target_arch = "x86"))), repr(align(8)))] pub struct pthread_barrier_t { size: [u8; ::__SIZEOF_PTHREAD_BARRIER_T], } // linux/can.h #[repr(align(8))] #[allow(missing_debug_implementations)] pub struct can_frame { pub can_id: canid_t, pub can_dlc: u8, __pad: u8, __res0: u8, __res1: u8, pub data: [u8; CAN_MAX_DLEN], } #[repr(align(8))] #[allow(missing_debug_implementations)] pub struct canfd_frame { pub can_id: canid_t, pub len: u8, pub flags: u8, __res0: u8, __res1: u8, pub data: [u8; CANFD_MAX_DLEN], } #[repr(align(8))] #[allow(missing_debug_implementations)] pub struct canxl_frame { pub prio: canid_t, pub flags: u8, pub sdt: u8, pub len: u16, pub af: u32, pub data: [u8; CANXL_MAX_DLEN], } } }; } libc/src/unix/linux_like/linux/arch/0000775000175000017500000000000014661133735020445 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/arch/generic/0000775000175000017500000000000014661133735022061 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/arch/generic/mod.rs0000644000175000017500000003162414661133735023212 0ustar jamespagejamespages! { pub struct termios2 { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; 19], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } } // include/uapi/asm-generic/socket.h // arch/alpha/include/uapi/asm/socket.h // tools/include/uapi/asm-generic/socket.h // arch/mips/include/uapi/asm/socket.h pub const SOL_SOCKET: ::c_int = 1; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: ::c_int = 1; pub const SO_REUSEADDR: ::c_int = 2; pub const SO_TYPE: ::c_int = 3; pub const SO_ERROR: ::c_int = 4; pub const SO_DONTROUTE: ::c_int = 5; pub const SO_BROADCAST: ::c_int = 6; pub const SO_SNDBUF: ::c_int = 7; pub const SO_RCVBUF: ::c_int = 8; pub const SO_KEEPALIVE: ::c_int = 9; pub const SO_OOBINLINE: ::c_int = 10; pub const SO_NO_CHECK: ::c_int = 11; pub const SO_PRIORITY: ::c_int = 12; pub const SO_LINGER: ::c_int = 13; pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_REUSEPORT: ::c_int = 15; pub const SO_PASSCRED: ::c_int = 16; pub const SO_PEERCRED: ::c_int = 17; pub const SO_RCVLOWAT: ::c_int = 18; pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; // pub const SO_RCVTIMEO_OLD: ::c_int = 20; // pub const SO_SNDTIMEO_OLD: ::c_int = 21; pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; pub const SO_BINDTODEVICE: ::c_int = 25; pub const SO_ATTACH_FILTER: ::c_int = 26; pub const SO_DETACH_FILTER: ::c_int = 27; pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: ::c_int = 28; pub const SO_TIMESTAMP: ::c_int = 29; // pub const SO_TIMESTAMP_OLD: ::c_int = 29; pub const SO_ACCEPTCONN: ::c_int = 30; pub const SO_PEERSEC: ::c_int = 31; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_PASSSEC: ::c_int = 34; pub const SO_TIMESTAMPNS: ::c_int = 35; // pub const SO_TIMESTAMPNS_OLD: ::c_int = 35; pub const SO_MARK: ::c_int = 36; pub const SO_TIMESTAMPING: ::c_int = 37; // pub const SO_TIMESTAMPING_OLD: ::c_int = 37; pub const SO_PROTOCOL: ::c_int = 38; pub const SO_DOMAIN: ::c_int = 39; pub const SO_RXQ_OVFL: ::c_int = 40; pub const SO_WIFI_STATUS: ::c_int = 41; pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: ::c_int = 42; pub const SO_NOFCS: ::c_int = 43; pub const SO_LOCK_FILTER: ::c_int = 44; pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; pub const SO_BUSY_POLL: ::c_int = 46; pub const SO_MAX_PACING_RATE: ::c_int = 47; pub const SO_BPF_EXTENSIONS: ::c_int = 48; pub const SO_INCOMING_CPU: ::c_int = 49; pub const SO_ATTACH_BPF: ::c_int = 50; pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; pub const SO_CNX_ADVICE: ::c_int = 53; pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; pub const SO_MEMINFO: ::c_int = 55; pub const SO_INCOMING_NAPI_ID: ::c_int = 56; pub const SO_COOKIE: ::c_int = 57; pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; pub const SO_PEERGROUPS: ::c_int = 59; pub const SO_ZEROCOPY: ::c_int = 60; pub const SO_TXTIME: ::c_int = 61; pub const SCM_TXTIME: ::c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: ::c_int = 62; cfg_if! { // Some of these platforms in CI already have these constants. // But they may still not have those _OLD ones. if #[cfg(all(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64", target_arch = "csky", target_arch = "loongarch64"), not(any(target_env = "musl", target_env = "ohos"))))] { pub const SO_TIMESTAMP_NEW: ::c_int = 63; pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; pub const SO_TIMESTAMPING_NEW: ::c_int = 65; pub const SO_RCVTIMEO_NEW: ::c_int = 66; pub const SO_SNDTIMEO_NEW: ::c_int = 67; pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; } } // pub const SO_PREFER_BUSY_POLL: ::c_int = 69; // pub const SO_BUSY_POLL_BUDGET: ::c_int = 70; cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", target_arch = "riscv64", target_arch = "s390x", target_arch = "csky", target_arch = "loongarch64"))] { pub const FICLONE: ::c_ulong = 0x40049409; pub const FICLONERANGE: ::c_ulong = 0x4020940D; } } // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; // Ioctl Constants pub const TCGETS: ::Ioctl = 0x5401; pub const TCSETS: ::Ioctl = 0x5402; pub const TCSETSW: ::Ioctl = 0x5403; pub const TCSETSF: ::Ioctl = 0x5404; pub const TCGETA: ::Ioctl = 0x5405; pub const TCSETA: ::Ioctl = 0x5406; pub const TCSETAW: ::Ioctl = 0x5407; pub const TCSETAF: ::Ioctl = 0x5408; pub const TCSBRK: ::Ioctl = 0x5409; pub const TCXONC: ::Ioctl = 0x540A; pub const TCFLSH: ::Ioctl = 0x540B; pub const TIOCEXCL: ::Ioctl = 0x540C; pub const TIOCNXCL: ::Ioctl = 0x540D; pub const TIOCSCTTY: ::Ioctl = 0x540E; pub const TIOCGPGRP: ::Ioctl = 0x540F; pub const TIOCSPGRP: ::Ioctl = 0x5410; pub const TIOCOUTQ: ::Ioctl = 0x5411; pub const TIOCSTI: ::Ioctl = 0x5412; pub const TIOCGWINSZ: ::Ioctl = 0x5413; pub const TIOCSWINSZ: ::Ioctl = 0x5414; pub const TIOCMGET: ::Ioctl = 0x5415; pub const TIOCMBIS: ::Ioctl = 0x5416; pub const TIOCMBIC: ::Ioctl = 0x5417; pub const TIOCMSET: ::Ioctl = 0x5418; pub const TIOCGSOFTCAR: ::Ioctl = 0x5419; pub const TIOCSSOFTCAR: ::Ioctl = 0x541A; pub const FIONREAD: ::Ioctl = 0x541B; pub const TIOCINQ: ::Ioctl = FIONREAD; pub const TIOCLINUX: ::Ioctl = 0x541C; pub const TIOCCONS: ::Ioctl = 0x541D; pub const TIOCGSERIAL: ::Ioctl = 0x541E; pub const TIOCSSERIAL: ::Ioctl = 0x541F; pub const TIOCPKT: ::Ioctl = 0x5420; pub const FIONBIO: ::Ioctl = 0x5421; pub const TIOCNOTTY: ::Ioctl = 0x5422; pub const TIOCSETD: ::Ioctl = 0x5423; pub const TIOCGETD: ::Ioctl = 0x5424; pub const TCSBRKP: ::Ioctl = 0x5425; pub const TIOCSBRK: ::Ioctl = 0x5427; pub const TIOCCBRK: ::Ioctl = 0x5428; pub const TIOCGSID: ::Ioctl = 0x5429; pub const TCGETS2: ::Ioctl = 0x802c542a; pub const TCSETS2: ::Ioctl = 0x402c542b; pub const TCSETSW2: ::Ioctl = 0x402c542c; pub const TCSETSF2: ::Ioctl = 0x402c542d; pub const TIOCGRS485: ::Ioctl = 0x542E; pub const TIOCSRS485: ::Ioctl = 0x542F; pub const TIOCGPTN: ::Ioctl = 0x80045430; pub const TIOCSPTLCK: ::Ioctl = 0x40045431; pub const TIOCGDEV: ::Ioctl = 0x80045432; pub const TCGETX: ::Ioctl = 0x5432; pub const TCSETX: ::Ioctl = 0x5433; pub const TCSETXF: ::Ioctl = 0x5434; pub const TCSETXW: ::Ioctl = 0x5435; pub const TIOCSIG: ::Ioctl = 0x40045436; pub const TIOCVHANGUP: ::Ioctl = 0x5437; pub const TIOCGPKT: ::Ioctl = 0x80045438; pub const TIOCGPTLCK: ::Ioctl = 0x80045439; pub const TIOCGEXCL: ::Ioctl = 0x80045440; pub const TIOCGPTPEER: ::Ioctl = 0x5441; // pub const TIOCGISO7816: ::Ioctl = 0x80285442; // pub const TIOCSISO7816: ::Ioctl = 0xc0285443; pub const FIONCLEX: ::Ioctl = 0x5450; pub const FIOCLEX: ::Ioctl = 0x5451; pub const FIOASYNC: ::Ioctl = 0x5452; pub const TIOCSERCONFIG: ::Ioctl = 0x5453; pub const TIOCSERGWILD: ::Ioctl = 0x5454; pub const TIOCSERSWILD: ::Ioctl = 0x5455; pub const TIOCGLCKTRMIOS: ::Ioctl = 0x5456; pub const TIOCSLCKTRMIOS: ::Ioctl = 0x5457; pub const TIOCSERGSTRUCT: ::Ioctl = 0x5458; pub const TIOCSERGETLSR: ::Ioctl = 0x5459; pub const TIOCSERGETMULTI: ::Ioctl = 0x545A; pub const TIOCSERSETMULTI: ::Ioctl = 0x545B; pub const TIOCMIWAIT: ::Ioctl = 0x545C; pub const TIOCGICOUNT: ::Ioctl = 0x545D; pub const BLKIOMIN: ::Ioctl = 0x1278; pub const BLKIOOPT: ::Ioctl = 0x1279; pub const BLKSSZGET: ::Ioctl = 0x1268; pub const BLKPBSZGET: ::Ioctl = 0x127B; cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "csky"))] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x80046601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x40046602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x80047601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x40047602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x80046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x40046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x80047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x40047602; } else if #[cfg(any(target_arch = "x86_64", target_arch = "riscv64", target_arch = "aarch64", target_arch = "s390x", target_arch = "loongarch64"))] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x80086601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x40086602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x80087601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x40087602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x80046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x40046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x80047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x40047602; } } cfg_if! { if #[cfg(any(target_arch = "arm", target_arch = "s390x"))] { pub const FIOQSIZE: ::Ioctl = 0x545E; } else { pub const FIOQSIZE: ::Ioctl = 0x5460; } } pub const TIOCM_LE: ::c_int = 0x001; pub const TIOCM_DTR: ::c_int = 0x002; pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_ST: ::c_int = 0x008; pub const TIOCM_SR: ::c_int = 0x010; pub const TIOCM_CTS: ::c_int = 0x020; pub const TIOCM_CAR: ::c_int = 0x040; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RNG: ::c_int = 0x080; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const TIOCM_DSR: ::c_int = 0x100; pub const BOTHER: ::speed_t = 0o010000; pub const IBSHIFT: ::tcflag_t = 16; // RLIMIT Constants cfg_if! { if #[cfg(any(target_env = "gnu", target_env = "uclibc"))] { pub const RLIMIT_CPU: ::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: ::__rlimit_resource_t = 1; pub const RLIMIT_DATA: ::__rlimit_resource_t = 2; pub const RLIMIT_STACK: ::__rlimit_resource_t = 3; pub const RLIMIT_CORE: ::__rlimit_resource_t = 4; pub const RLIMIT_RSS: ::__rlimit_resource_t = 5; pub const RLIMIT_NPROC: ::__rlimit_resource_t = 6; pub const RLIMIT_NOFILE: ::__rlimit_resource_t = 7; pub const RLIMIT_MEMLOCK: ::__rlimit_resource_t = 8; pub const RLIMIT_AS: ::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: ::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: ::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: ::__rlimit_resource_t = 12; pub const RLIMIT_NICE: ::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: ::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: ::__rlimit_resource_t = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::__rlimit_resource_t = RLIM_NLIMITS; } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_NPROC: ::c_int = 6; pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_MEMLOCK: ::c_int = 8; pub const RLIMIT_AS: ::c_int = 9; pub const RLIMIT_LOCKS: ::c_int = 10; pub const RLIMIT_SIGPENDING: ::c_int = 11; pub const RLIMIT_MSGQUEUE: ::c_int = 12; pub const RLIMIT_NICE: ::c_int = 13; pub const RLIMIT_RTPRIO: ::c_int = 14; pub const RLIMIT_RTTIME: ::c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::c_int = RLIM_NLIMITS; } } cfg_if! { if #[cfg(target_env = "gnu")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::__rlimit_resource_t = 16; } else if #[cfg(target_env = "uclibc")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::__rlimit_resource_t = 15; } } pub const RLIM_INFINITY: ::rlim_t = !0; libc/src/unix/linux_like/linux/arch/sparc/0000775000175000017500000000000014661133735021555 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/arch/sparc/mod.rs0000644000175000017500000002477414661133735022716 0ustar jamespagejamespages! { pub struct termios2 { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; 19], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } } // arch/sparc/include/uapi/asm/socket.h pub const SOL_SOCKET: ::c_int = 0xffff; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: ::c_int = 0x0001; pub const SO_PASSCRED: ::c_int = 0x0002; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_PEERCRED: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_BSDCOMPAT: ::c_int = 0x0400; pub const SO_RCVLOWAT: ::c_int = 0x0800; pub const SO_SNDLOWAT: ::c_int = 0x1000; pub const SO_RCVTIMEO: ::c_int = 0x2000; pub const SO_SNDTIMEO: ::c_int = 0x4000; // pub const SO_RCVTIMEO_OLD: ::c_int = 0x2000; // pub const SO_SNDTIMEO_OLD: ::c_int = 0x4000; pub const SO_ACCEPTCONN: ::c_int = 0x8000; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDBUFFORCE: ::c_int = 0x100a; pub const SO_RCVBUFFORCE: ::c_int = 0x100b; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; pub const SO_PROTOCOL: ::c_int = 0x1028; pub const SO_DOMAIN: ::c_int = 0x1029; pub const SO_NO_CHECK: ::c_int = 0x000b; pub const SO_PRIORITY: ::c_int = 0x000c; pub const SO_BINDTODEVICE: ::c_int = 0x000d; pub const SO_ATTACH_FILTER: ::c_int = 0x001a; pub const SO_DETACH_FILTER: ::c_int = 0x001b; pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: ::c_int = 0x001c; pub const SO_PEERSEC: ::c_int = 0x001e; pub const SO_PASSSEC: ::c_int = 0x001f; pub const SO_MARK: ::c_int = 0x0022; pub const SO_RXQ_OVFL: ::c_int = 0x0024; pub const SO_WIFI_STATUS: ::c_int = 0x0025; pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: ::c_int = 0x0026; pub const SO_NOFCS: ::c_int = 0x0027; pub const SO_LOCK_FILTER: ::c_int = 0x0028; pub const SO_SELECT_ERR_QUEUE: ::c_int = 0x0029; pub const SO_BUSY_POLL: ::c_int = 0x0030; pub const SO_MAX_PACING_RATE: ::c_int = 0x0031; pub const SO_BPF_EXTENSIONS: ::c_int = 0x0032; pub const SO_INCOMING_CPU: ::c_int = 0x0033; pub const SO_ATTACH_BPF: ::c_int = 0x0034; pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 0x0035; pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 0x0036; pub const SO_CNX_ADVICE: ::c_int = 0x0037; pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 0x0038; pub const SO_MEMINFO: ::c_int = 0x0039; pub const SO_INCOMING_NAPI_ID: ::c_int = 0x003a; pub const SO_COOKIE: ::c_int = 0x003b; pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 0x003c; pub const SO_PEERGROUPS: ::c_int = 0x003d; pub const SO_ZEROCOPY: ::c_int = 0x003e; pub const SO_TXTIME: ::c_int = 0x003f; pub const SCM_TXTIME: ::c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: ::c_int = 0x0041; pub const SO_SECURITY_AUTHENTICATION: ::c_int = 0x5001; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 0x5002; pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 0x5004; pub const SO_TIMESTAMP: ::c_int = 0x001d; pub const SO_TIMESTAMPNS: ::c_int = 0x0021; pub const SO_TIMESTAMPING: ::c_int = 0x0023; // pub const SO_TIMESTAMP_OLD: ::c_int = 0x001d; // pub const SO_TIMESTAMPNS_OLD: ::c_int = 0x0021; // pub const SO_TIMESTAMPING_OLD: ::c_int = 0x0023; // pub const SO_TIMESTAMP_NEW: ::c_int = 0x0046; // pub const SO_TIMESTAMPNS_NEW: ::c_int = 0x0042; // pub const SO_TIMESTAMPING_NEW: ::c_int = 0x0043; // pub const SO_RCVTIMEO_NEW: ::c_int = 0x0044; // pub const SO_SNDTIMEO_NEW: ::c_int = 0x0045; // pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 0x0047; // pub const SO_PREFER_BUSY_POLL: ::c_int = 0x0048; // pub const SO_BUSY_POLL_BUDGET: ::c_int = 0x0049; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; // Ioctl Constants pub const TCGETS: ::Ioctl = 0x40245408; pub const TCSETS: ::Ioctl = 0x80245409; pub const TCSETSW: ::Ioctl = 0x8024540a; pub const TCSETSF: ::Ioctl = 0x8024540b; pub const TCGETA: ::Ioctl = 0x40125401; pub const TCSETA: ::Ioctl = 0x80125402; pub const TCSETAW: ::Ioctl = 0x80125403; pub const TCSETAF: ::Ioctl = 0x80125404; pub const TCSBRK: ::Ioctl = 0x20005405; pub const TCXONC: ::Ioctl = 0x20005406; pub const TCFLSH: ::Ioctl = 0x20005407; pub const TIOCEXCL: ::Ioctl = 0x2000740d; pub const TIOCNXCL: ::Ioctl = 0x2000740e; pub const TIOCSCTTY: ::Ioctl = 0x20007484; pub const TIOCGPGRP: ::Ioctl = 0x40047483; pub const TIOCSPGRP: ::Ioctl = 0x80047482; pub const TIOCOUTQ: ::Ioctl = 0x40047473; pub const TIOCSTI: ::Ioctl = 0x80017472; pub const TIOCGWINSZ: ::Ioctl = 0x40087468; pub const TIOCSWINSZ: ::Ioctl = 0x80087467; pub const TIOCMGET: ::Ioctl = 0x4004746a; pub const TIOCMBIS: ::Ioctl = 0x8004746c; pub const TIOCMBIC: ::Ioctl = 0x8004746b; pub const TIOCMSET: ::Ioctl = 0x8004746d; pub const TIOCGSOFTCAR: ::Ioctl = 0x40047464; pub const TIOCSSOFTCAR: ::Ioctl = 0x80047465; pub const FIONREAD: ::Ioctl = 0x4004667f; pub const TIOCINQ: ::Ioctl = FIONREAD; pub const TIOCLINUX: ::Ioctl = 0x541C; pub const TIOCCONS: ::Ioctl = 0x20007424; pub const TIOCGSERIAL: ::Ioctl = 0x541E; pub const TIOCSSERIAL: ::Ioctl = 0x541F; pub const TIOCPKT: ::Ioctl = 0x80047470; pub const FIONBIO: ::Ioctl = 0x8004667e; pub const TIOCNOTTY: ::Ioctl = 0x20007471; pub const TIOCSETD: ::Ioctl = 0x80047401; pub const TIOCGETD: ::Ioctl = 0x40047400; pub const TCSBRKP: ::Ioctl = 0x5425; pub const TIOCSBRK: ::Ioctl = 0x2000747b; pub const TIOCCBRK: ::Ioctl = 0x2000747a; pub const TIOCGSID: ::Ioctl = 0x40047485; pub const TCGETS2: ::Ioctl = 0x402c540c; pub const TCSETS2: ::Ioctl = 0x802c540d; pub const TCSETSW2: ::Ioctl = 0x802c540e; pub const TCSETSF2: ::Ioctl = 0x802c540f; pub const TIOCGPTN: ::Ioctl = 0x40047486; pub const TIOCSPTLCK: ::Ioctl = 0x80047487; pub const TIOCGDEV: ::Ioctl = 0x40045432; pub const TIOCSIG: ::Ioctl = 0x80047488; pub const TIOCVHANGUP: ::Ioctl = 0x20005437; pub const TIOCGPKT: ::Ioctl = 0x40045438; pub const TIOCGPTLCK: ::Ioctl = 0x40045439; pub const TIOCGEXCL: ::Ioctl = 0x40045440; pub const TIOCGPTPEER: ::Ioctl = 0x20007489; pub const FIONCLEX: ::Ioctl = 0x20006602; pub const FIOCLEX: ::Ioctl = 0x20006601; pub const TIOCSERCONFIG: ::Ioctl = 0x5453; pub const TIOCSERGWILD: ::Ioctl = 0x5454; pub const TIOCSERSWILD: ::Ioctl = 0x5455; pub const TIOCGLCKTRMIOS: ::Ioctl = 0x5456; pub const TIOCSLCKTRMIOS: ::Ioctl = 0x5457; pub const TIOCSERGSTRUCT: ::Ioctl = 0x5458; pub const TIOCSERGETLSR: ::Ioctl = 0x5459; pub const TIOCSERGETMULTI: ::Ioctl = 0x545A; pub const TIOCSERSETMULTI: ::Ioctl = 0x545B; pub const TIOCMIWAIT: ::Ioctl = 0x545C; pub const TIOCGICOUNT: ::Ioctl = 0x545D; pub const TIOCSTART: ::Ioctl = 0x2000746e; pub const TIOCSTOP: ::Ioctl = 0x2000746f; pub const BLKIOMIN: ::Ioctl = 0x20001278; pub const BLKIOOPT: ::Ioctl = 0x20001279; pub const BLKSSZGET: ::Ioctl = 0x20001268; pub const BLKPBSZGET: ::Ioctl = 0x2000127B; //pub const FIOASYNC: ::Ioctl = 0x4004667d; //pub const FIOQSIZE: ::Ioctl = ; //pub const TIOCGISO7816: ::Ioctl = 0x40285443; //pub const TIOCSISO7816: ::Ioctl = 0xc0285444; //pub const TIOCGRS485: ::Ioctl = 0x40205441; //pub const TIOCSRS485: ::Ioctl = 0xc0205442; pub const TIOCM_LE: ::c_int = 0x001; pub const TIOCM_DTR: ::c_int = 0x002; pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_ST: ::c_int = 0x008; pub const TIOCM_SR: ::c_int = 0x010; pub const TIOCM_CTS: ::c_int = 0x020; pub const TIOCM_CAR: ::c_int = 0x040; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RNG: ::c_int = 0x080; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const TIOCM_DSR: ::c_int = 0x100; pub const BOTHER: ::speed_t = 0x1000; pub const IBSHIFT: ::tcflag_t = 16; // RLIMIT Constants pub const RLIMIT_CPU: ::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: ::__rlimit_resource_t = 1; pub const RLIMIT_DATA: ::__rlimit_resource_t = 2; pub const RLIMIT_STACK: ::__rlimit_resource_t = 3; pub const RLIMIT_CORE: ::__rlimit_resource_t = 4; pub const RLIMIT_RSS: ::__rlimit_resource_t = 5; pub const RLIMIT_NOFILE: ::__rlimit_resource_t = 6; pub const RLIMIT_NPROC: ::__rlimit_resource_t = 7; pub const RLIMIT_MEMLOCK: ::__rlimit_resource_t = 8; pub const RLIMIT_AS: ::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: ::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: ::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: ::__rlimit_resource_t = 12; pub const RLIMIT_NICE: ::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: ::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: ::__rlimit_resource_t = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::__rlimit_resource_t = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::__rlimit_resource_t = RLIM_NLIMITS; cfg_if! { if #[cfg(target_arch = "sparc64")] { pub const RLIM_INFINITY: ::rlim_t = !0; } else if #[cfg(target_arch = "sparc")] { pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff; } } cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(target_arch = "sparc")] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x80047602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x80047602; } else if #[cfg(target_arch = "sparc64")] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40086601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80086602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x40087601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x80087602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x80047602; } } libc/src/unix/linux_like/linux/arch/powerpc/0000775000175000017500000000000014661133735022124 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/arch/powerpc/mod.rs0000644000175000017500000002617514661133735023262 0ustar jamespagejamespage// arch/powerpc/include/uapi/asm/socket.h pub const SOL_SOCKET: ::c_int = 1; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: ::c_int = 1; pub const SO_REUSEADDR: ::c_int = 2; pub const SO_TYPE: ::c_int = 3; pub const SO_ERROR: ::c_int = 4; pub const SO_DONTROUTE: ::c_int = 5; pub const SO_BROADCAST: ::c_int = 6; pub const SO_SNDBUF: ::c_int = 7; pub const SO_RCVBUF: ::c_int = 8; pub const SO_KEEPALIVE: ::c_int = 9; pub const SO_OOBINLINE: ::c_int = 10; pub const SO_NO_CHECK: ::c_int = 11; pub const SO_PRIORITY: ::c_int = 12; pub const SO_LINGER: ::c_int = 13; pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_REUSEPORT: ::c_int = 15; // powerpc only differs in these pub const SO_RCVLOWAT: ::c_int = 16; pub const SO_SNDLOWAT: ::c_int = 17; pub const SO_RCVTIMEO: ::c_int = 18; pub const SO_SNDTIMEO: ::c_int = 19; // pub const SO_RCVTIMEO_OLD: ::c_int = 18; // pub const SO_SNDTIMEO_OLD: ::c_int = 19; pub const SO_PASSCRED: ::c_int = 20; pub const SO_PEERCRED: ::c_int = 21; // end pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; pub const SO_BINDTODEVICE: ::c_int = 25; pub const SO_ATTACH_FILTER: ::c_int = 26; pub const SO_DETACH_FILTER: ::c_int = 27; pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: ::c_int = 28; pub const SO_TIMESTAMP: ::c_int = 29; // pub const SO_TIMESTAMP_OLD: ::c_int = 29; pub const SO_ACCEPTCONN: ::c_int = 30; pub const SO_PEERSEC: ::c_int = 31; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_PASSSEC: ::c_int = 34; pub const SO_TIMESTAMPNS: ::c_int = 35; // pub const SO_TIMESTAMPNS_OLD: ::c_int = 35; pub const SO_MARK: ::c_int = 36; pub const SO_TIMESTAMPING: ::c_int = 37; // pub const SO_TIMESTAMPING_OLD: ::c_int = 37; pub const SO_PROTOCOL: ::c_int = 38; pub const SO_DOMAIN: ::c_int = 39; pub const SO_RXQ_OVFL: ::c_int = 40; pub const SO_WIFI_STATUS: ::c_int = 41; pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: ::c_int = 42; pub const SO_NOFCS: ::c_int = 43; pub const SO_LOCK_FILTER: ::c_int = 44; pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; pub const SO_BUSY_POLL: ::c_int = 46; pub const SO_MAX_PACING_RATE: ::c_int = 47; pub const SO_BPF_EXTENSIONS: ::c_int = 48; pub const SO_INCOMING_CPU: ::c_int = 49; pub const SO_ATTACH_BPF: ::c_int = 50; pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; pub const SO_CNX_ADVICE: ::c_int = 53; pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; pub const SO_MEMINFO: ::c_int = 55; pub const SO_INCOMING_NAPI_ID: ::c_int = 56; pub const SO_COOKIE: ::c_int = 57; pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; pub const SO_PEERGROUPS: ::c_int = 59; pub const SO_ZEROCOPY: ::c_int = 60; pub const SO_TXTIME: ::c_int = 61; pub const SCM_TXTIME: ::c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: ::c_int = 62; // pub const SO_TIMESTAMP_NEW: ::c_int = 63; // pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; // pub const SO_TIMESTAMPING_NEW: ::c_int = 65; // pub const SO_RCVTIMEO_NEW: ::c_int = 66; // pub const SO_SNDTIMEO_NEW: ::c_int = 67; // pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; // pub const SO_PREFER_BUSY_POLL: ::c_int = 69; // pub const SO_BUSY_POLL_BUDGET: ::c_int = 70; pub const FICLONE: ::c_ulong = 0x80049409; pub const FICLONERANGE: ::c_ulong = 0x8020940D; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; // Ioctl Constants cfg_if! { if #[cfg(target_env = "gnu")] { pub const TCGETS: ::Ioctl = 0x403c7413; pub const TCSETS: ::Ioctl = 0x803c7414; pub const TCSETSW: ::Ioctl = 0x803c7415; pub const TCSETSF: ::Ioctl = 0x803c7416; } else if #[cfg(target_env = "musl")] { pub const TCGETS: ::Ioctl = 0x402c7413; pub const TCSETS: ::Ioctl = 0x802c7414; pub const TCSETSW: ::Ioctl = 0x802c7415; pub const TCSETSF: ::Ioctl = 0x802c7416; } } pub const TCGETA: ::Ioctl = 0x40147417; pub const TCSETA: ::Ioctl = 0x80147418; pub const TCSETAW: ::Ioctl = 0x80147419; pub const TCSETAF: ::Ioctl = 0x8014741C; pub const TCSBRK: ::Ioctl = 0x2000741D; pub const TCXONC: ::Ioctl = 0x2000741E; pub const TCFLSH: ::Ioctl = 0x2000741F; pub const TIOCEXCL: ::Ioctl = 0x540C; pub const TIOCNXCL: ::Ioctl = 0x540D; pub const TIOCSCTTY: ::Ioctl = 0x540E; pub const TIOCGPGRP: ::Ioctl = 0x40047477; pub const TIOCSPGRP: ::Ioctl = 0x80047476; pub const TIOCOUTQ: ::Ioctl = 0x40047473; pub const TIOCSTI: ::Ioctl = 0x5412; pub const TIOCGWINSZ: ::Ioctl = 0x40087468; pub const TIOCSWINSZ: ::Ioctl = 0x80087467; pub const TIOCMGET: ::Ioctl = 0x5415; pub const TIOCMBIS: ::Ioctl = 0x5416; pub const TIOCMBIC: ::Ioctl = 0x5417; pub const TIOCMSET: ::Ioctl = 0x5418; pub const TIOCGSOFTCAR: ::Ioctl = 0x5419; pub const TIOCSSOFTCAR: ::Ioctl = 0x541A; pub const FIONREAD: ::Ioctl = 0x4004667F; pub const TIOCINQ: ::Ioctl = FIONREAD; pub const TIOCLINUX: ::Ioctl = 0x541C; pub const TIOCCONS: ::Ioctl = 0x541D; pub const TIOCGSERIAL: ::Ioctl = 0x541E; pub const TIOCSSERIAL: ::Ioctl = 0x541F; pub const TIOCPKT: ::Ioctl = 0x5420; pub const FIONBIO: ::Ioctl = 0x8004667e; pub const TIOCNOTTY: ::Ioctl = 0x5422; pub const TIOCSETD: ::Ioctl = 0x5423; pub const TIOCGETD: ::Ioctl = 0x5424; pub const TCSBRKP: ::Ioctl = 0x5425; pub const TIOCSBRK: ::Ioctl = 0x5427; pub const TIOCCBRK: ::Ioctl = 0x5428; pub const TIOCGSID: ::Ioctl = 0x5429; pub const TIOCGRS485: ::Ioctl = 0x542e; pub const TIOCSRS485: ::Ioctl = 0x542f; pub const TIOCGPTN: ::Ioctl = 0x40045430; pub const TIOCSPTLCK: ::Ioctl = 0x80045431; pub const TIOCGDEV: ::Ioctl = 0x40045432; pub const TIOCSIG: ::Ioctl = 0x80045436; pub const TIOCVHANGUP: ::Ioctl = 0x5437; pub const TIOCGPKT: ::Ioctl = 0x40045438; pub const TIOCGPTLCK: ::Ioctl = 0x40045439; pub const TIOCGEXCL: ::Ioctl = 0x40045440; pub const TIOCGPTPEER: ::Ioctl = 0x20005441; //pub const TIOCGISO7816: ::Ioctl = 0x40285442; //pub const TIOCSISO7816: ::Ioctl = 0xc0285443; pub const FIONCLEX: ::Ioctl = 0x20006602; pub const FIOCLEX: ::Ioctl = 0x20006601; pub const FIOASYNC: ::Ioctl = 0x8004667d; pub const TIOCSERCONFIG: ::Ioctl = 0x5453; pub const TIOCSERGWILD: ::Ioctl = 0x5454; pub const TIOCSERSWILD: ::Ioctl = 0x5455; pub const TIOCGLCKTRMIOS: ::Ioctl = 0x5456; pub const TIOCSLCKTRMIOS: ::Ioctl = 0x5457; pub const TIOCSERGSTRUCT: ::Ioctl = 0x5458; pub const TIOCSERGETLSR: ::Ioctl = 0x5459; pub const TIOCSERGETMULTI: ::Ioctl = 0x545A; pub const TIOCSERSETMULTI: ::Ioctl = 0x545B; pub const TIOCMIWAIT: ::Ioctl = 0x545C; pub const TIOCGICOUNT: ::Ioctl = 0x545D; pub const BLKIOMIN: ::Ioctl = 0x20001278; pub const BLKIOOPT: ::Ioctl = 0x20001279; pub const BLKSSZGET: ::Ioctl = 0x20001268; pub const BLKPBSZGET: ::Ioctl = 0x2000127B; //pub const FIOQSIZE: ::Ioctl = 0x40086680; cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(target_arch = "powerpc")] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x80047602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x80047602; } else if #[cfg(target_arch = "powerpc64")] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40086601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80086602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x40087601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x80087602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x80047602; } } pub const TIOCM_LE: ::c_int = 0x001; pub const TIOCM_DTR: ::c_int = 0x002; pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_ST: ::c_int = 0x008; pub const TIOCM_SR: ::c_int = 0x010; pub const TIOCM_CTS: ::c_int = 0x020; pub const TIOCM_CAR: ::c_int = 0x040; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RNG: ::c_int = 0x080; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const TIOCM_DSR: ::c_int = 0x100; pub const BOTHER: ::speed_t = 0o0037; pub const IBSHIFT: ::tcflag_t = 16; // RLIMIT Constants cfg_if! { if #[cfg(target_env = "gnu")] { pub const RLIMIT_CPU: ::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: ::__rlimit_resource_t = 1; pub const RLIMIT_DATA: ::__rlimit_resource_t = 2; pub const RLIMIT_STACK: ::__rlimit_resource_t = 3; pub const RLIMIT_CORE: ::__rlimit_resource_t = 4; pub const RLIMIT_RSS: ::__rlimit_resource_t = 5; pub const RLIMIT_NPROC: ::__rlimit_resource_t = 6; pub const RLIMIT_NOFILE: ::__rlimit_resource_t = 7; pub const RLIMIT_MEMLOCK: ::__rlimit_resource_t = 8; pub const RLIMIT_AS: ::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: ::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: ::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: ::__rlimit_resource_t = 12; pub const RLIMIT_NICE: ::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: ::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: ::__rlimit_resource_t = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::__rlimit_resource_t = 16; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::__rlimit_resource_t = RLIM_NLIMITS; } else if #[cfg(target_env = "musl")] { pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_NPROC: ::c_int = 6; pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_MEMLOCK: ::c_int = 8; pub const RLIMIT_AS: ::c_int = 9; pub const RLIMIT_LOCKS: ::c_int = 10; pub const RLIMIT_SIGPENDING: ::c_int = 11; pub const RLIMIT_MSGQUEUE: ::c_int = 12; pub const RLIMIT_NICE: ::c_int = 13; pub const RLIMIT_RTPRIO: ::c_int = 14; pub const RLIMIT_RTTIME: ::c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::c_int = RLIM_NLIMITS; } } pub const RLIM_INFINITY: ::rlim_t = !0; libc/src/unix/linux_like/linux/arch/mod.rs0000644000175000017500000000106714661133735021574 0ustar jamespagejamespagecfg_if! { if #[cfg(any(target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6"))] { mod mips; pub use self::mips::*; } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] { mod sparc; pub use self::sparc::*; } else { mod generic; pub use self::generic::*; } } libc/src/unix/linux_like/linux/arch/mips/0000775000175000017500000000000014661133735021415 5ustar jamespagejamespagelibc/src/unix/linux_like/linux/arch/mips/mod.rs0000644000175000017500000003112714661133735022544 0ustar jamespagejamespages! { pub struct termios2 { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; 23], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } } // arch/mips/include/uapi/asm/socket.h pub const SOL_SOCKET: ::c_int = 0xffff; // Defined in unix/linux_like/mod.rs // pub const SO_DEBUG: ::c_int = 0x0001; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_TYPE: ::c_int = 0x1008; // pub const SO_STYLE: ::c_int = SO_TYPE; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVLOWAT: ::c_int = 0x1004; // NOTE: These definitions are now being renamed with _OLD postfix, // but CI haven't support them yet. // Some related consts could be found in b32.rs and b64.rs pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_RCVTIMEO: ::c_int = 0x1006; // pub const SO_SNDTIMEO_OLD: ::c_int = 0x1005; // pub const SO_RCVTIMEO_OLD: ::c_int = 0x1006; pub const SO_ACCEPTCONN: ::c_int = 0x1009; pub const SO_PROTOCOL: ::c_int = 0x1028; pub const SO_DOMAIN: ::c_int = 0x1029; pub const SO_NO_CHECK: ::c_int = 11; pub const SO_PRIORITY: ::c_int = 12; pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_PASSCRED: ::c_int = 17; pub const SO_PEERCRED: ::c_int = 18; pub const SO_SECURITY_AUTHENTICATION: ::c_int = 22; pub const SO_SECURITY_ENCRYPTION_TRANSPORT: ::c_int = 23; pub const SO_SECURITY_ENCRYPTION_NETWORK: ::c_int = 24; pub const SO_BINDTODEVICE: ::c_int = 25; pub const SO_ATTACH_FILTER: ::c_int = 26; pub const SO_DETACH_FILTER: ::c_int = 27; pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; pub const SO_PEERNAME: ::c_int = 28; pub const SO_PEERSEC: ::c_int = 30; pub const SO_SNDBUFFORCE: ::c_int = 31; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_PASSSEC: ::c_int = 34; pub const SO_MARK: ::c_int = 36; pub const SO_RXQ_OVFL: ::c_int = 40; pub const SO_WIFI_STATUS: ::c_int = 41; pub const SCM_WIFI_STATUS: ::c_int = SO_WIFI_STATUS; pub const SO_PEEK_OFF: ::c_int = 42; pub const SO_NOFCS: ::c_int = 43; pub const SO_LOCK_FILTER: ::c_int = 44; pub const SO_SELECT_ERR_QUEUE: ::c_int = 45; pub const SO_BUSY_POLL: ::c_int = 46; pub const SO_MAX_PACING_RATE: ::c_int = 47; pub const SO_BPF_EXTENSIONS: ::c_int = 48; pub const SO_INCOMING_CPU: ::c_int = 49; pub const SO_ATTACH_BPF: ::c_int = 50; pub const SO_DETACH_BPF: ::c_int = SO_DETACH_FILTER; pub const SO_ATTACH_REUSEPORT_CBPF: ::c_int = 51; pub const SO_ATTACH_REUSEPORT_EBPF: ::c_int = 52; pub const SO_CNX_ADVICE: ::c_int = 53; pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; pub const SO_MEMINFO: ::c_int = 55; pub const SO_INCOMING_NAPI_ID: ::c_int = 56; pub const SO_COOKIE: ::c_int = 57; pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; pub const SO_PEERGROUPS: ::c_int = 59; pub const SO_ZEROCOPY: ::c_int = 60; pub const SO_TXTIME: ::c_int = 61; pub const SCM_TXTIME: ::c_int = SO_TXTIME; pub const SO_BINDTOIFINDEX: ::c_int = 62; // NOTE: These definitions are now being renamed with _OLD postfix, // but CI haven't support them yet. // Some related consts could be found in b32.rs and b64.rs pub const SO_TIMESTAMP: ::c_int = 29; pub const SO_TIMESTAMPNS: ::c_int = 35; pub const SO_TIMESTAMPING: ::c_int = 37; // pub const SO_TIMESTAMP_OLD: ::c_int = 29; // pub const SO_TIMESTAMPNS_OLD: ::c_int = 35; // pub const SO_TIMESTAMPING_OLD: ::c_int = 37; // pub const SO_TIMESTAMP_NEW: ::c_int = 63; // pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; // pub const SO_TIMESTAMPING_NEW: ::c_int = 65; // pub const SO_RCVTIMEO_NEW: ::c_int = 66; // pub const SO_SNDTIMEO_NEW: ::c_int = 67; // pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68; // pub const SO_PREFER_BUSY_POLL: ::c_int = 69; // pub const SO_BUSY_POLL_BUDGET: ::c_int = 70; pub const FICLONE: ::c_ulong = 0x80049409; pub const FICLONERANGE: ::c_ulong = 0x8020940D; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; // Ioctl Constants pub const TCGETS: ::Ioctl = 0x540d; pub const TCSETS: ::Ioctl = 0x540e; pub const TCSETSW: ::Ioctl = 0x540f; pub const TCSETSF: ::Ioctl = 0x5410; pub const TCGETA: ::Ioctl = 0x5401; pub const TCSETA: ::Ioctl = 0x5402; pub const TCSETAW: ::Ioctl = 0x5403; pub const TCSETAF: ::Ioctl = 0x5404; pub const TCSBRK: ::Ioctl = 0x5405; pub const TCXONC: ::Ioctl = 0x5406; pub const TCFLSH: ::Ioctl = 0x5407; pub const TIOCEXCL: ::Ioctl = 0x740d; pub const TIOCNXCL: ::Ioctl = 0x740e; pub const TIOCSCTTY: ::Ioctl = 0x5480; pub const TIOCGPGRP: ::Ioctl = 0x40047477; pub const TIOCSPGRP: ::Ioctl = 0x80047476; pub const TIOCOUTQ: ::Ioctl = 0x7472; pub const TIOCSTI: ::Ioctl = 0x5472; pub const TIOCGWINSZ: ::Ioctl = 0x40087468; pub const TIOCSWINSZ: ::Ioctl = 0x80087467; pub const TIOCMGET: ::Ioctl = 0x741d; pub const TIOCMBIS: ::Ioctl = 0x741b; pub const TIOCMBIC: ::Ioctl = 0x741c; pub const TIOCMSET: ::Ioctl = 0x741a; pub const TIOCGSOFTCAR: ::Ioctl = 0x5481; pub const TIOCSSOFTCAR: ::Ioctl = 0x5482; pub const FIONREAD: ::Ioctl = 0x467f; pub const TIOCINQ: ::Ioctl = FIONREAD; pub const TIOCLINUX: ::Ioctl = 0x5483; pub const TIOCCONS: ::Ioctl = 0x80047478; pub const TIOCGSERIAL: ::Ioctl = 0x5484; pub const TIOCSSERIAL: ::Ioctl = 0x5485; pub const TIOCPKT: ::Ioctl = 0x5470; pub const FIONBIO: ::Ioctl = 0x667e; pub const TIOCNOTTY: ::Ioctl = 0x5471; pub const TIOCSETD: ::Ioctl = 0x7401; pub const TIOCGETD: ::Ioctl = 0x7400; pub const TCSBRKP: ::Ioctl = 0x5486; pub const TIOCSBRK: ::Ioctl = 0x5427; pub const TIOCCBRK: ::Ioctl = 0x5428; pub const TIOCGSID: ::Ioctl = 0x7416; pub const TCGETS2: ::Ioctl = 0x4030542a; pub const TCSETS2: ::Ioctl = 0x8030542b; pub const TCSETSW2: ::Ioctl = 0x8030542c; pub const TCSETSF2: ::Ioctl = 0x8030542d; pub const TIOCGPTN: ::Ioctl = 0x40045430; pub const TIOCSPTLCK: ::Ioctl = 0x80045431; pub const TIOCGDEV: ::Ioctl = 0x40045432; pub const TIOCSIG: ::Ioctl = 0x80045436; pub const TIOCVHANGUP: ::Ioctl = 0x5437; pub const TIOCGPKT: ::Ioctl = 0x40045438; pub const TIOCGPTLCK: ::Ioctl = 0x40045439; pub const TIOCGEXCL: ::Ioctl = 0x40045440; pub const TIOCGPTPEER: ::Ioctl = 0x20005441; //pub const TIOCGISO7816: ::Ioctl = 0x40285442; //pub const TIOCSISO7816: ::Ioctl = 0xc0285443; pub const FIONCLEX: ::Ioctl = 0x6602; pub const FIOCLEX: ::Ioctl = 0x6601; pub const FIOASYNC: ::Ioctl = 0x667d; pub const TIOCSERCONFIG: ::Ioctl = 0x5488; pub const TIOCSERGWILD: ::Ioctl = 0x5489; pub const TIOCSERSWILD: ::Ioctl = 0x548a; pub const TIOCGLCKTRMIOS: ::Ioctl = 0x548b; pub const TIOCSLCKTRMIOS: ::Ioctl = 0x548c; pub const TIOCSERGSTRUCT: ::Ioctl = 0x548d; pub const TIOCSERGETLSR: ::Ioctl = 0x548e; pub const TIOCSERGETMULTI: ::Ioctl = 0x548f; pub const TIOCSERSETMULTI: ::Ioctl = 0x5490; pub const TIOCMIWAIT: ::Ioctl = 0x5491; pub const TIOCGICOUNT: ::Ioctl = 0x5492; pub const FIOQSIZE: ::Ioctl = 0x667f; pub const TIOCSLTC: ::Ioctl = 0x7475; pub const TIOCGETP: ::Ioctl = 0x7408; pub const TIOCSETP: ::Ioctl = 0x7409; pub const TIOCSETN: ::Ioctl = 0x740a; pub const BLKIOMIN: ::Ioctl = 0x20001278; pub const BLKIOOPT: ::Ioctl = 0x20001279; pub const BLKSSZGET: ::Ioctl = 0x20001268; pub const BLKPBSZGET: ::Ioctl = 0x2000127B; cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(any(target_arch = "mips", target_arch = "mips32r6"))] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x80047602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x80047602; } else if #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"))] { pub const FS_IOC_GETFLAGS: ::Ioctl = 0x40086601; pub const FS_IOC_SETFLAGS: ::Ioctl = 0x80086602; pub const FS_IOC_GETVERSION: ::Ioctl = 0x40087601; pub const FS_IOC_SETVERSION: ::Ioctl = 0x80087602; pub const FS_IOC32_GETFLAGS: ::Ioctl = 0x40046601; pub const FS_IOC32_SETFLAGS: ::Ioctl = 0x80046602; pub const FS_IOC32_GETVERSION: ::Ioctl = 0x40047601; pub const FS_IOC32_SETVERSION: ::Ioctl = 0x80047602; } } cfg_if! { if #[cfg(target_env = "musl")] { pub const TIOCGRS485: ::Ioctl = 0x4020542e; pub const TIOCSRS485: ::Ioctl = 0xc020542f; } } pub const TIOCM_LE: ::c_int = 0x001; pub const TIOCM_DTR: ::c_int = 0x002; pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_ST: ::c_int = 0x010; pub const TIOCM_SR: ::c_int = 0x020; pub const TIOCM_CTS: ::c_int = 0x040; pub const TIOCM_CAR: ::c_int = 0x100; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RNG: ::c_int = 0x200; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const TIOCM_DSR: ::c_int = 0x400; pub const BOTHER: ::speed_t = 0o010000; pub const IBSHIFT: ::tcflag_t = 16; // RLIMIT Constants cfg_if! { if #[cfg(any(target_env = "gnu", target_env = "uclibc"))] { pub const RLIMIT_CPU: ::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: ::__rlimit_resource_t = 1; pub const RLIMIT_DATA: ::__rlimit_resource_t = 2; pub const RLIMIT_STACK: ::__rlimit_resource_t = 3; pub const RLIMIT_CORE: ::__rlimit_resource_t = 4; pub const RLIMIT_NOFILE: ::__rlimit_resource_t = 5; pub const RLIMIT_AS: ::__rlimit_resource_t = 6; pub const RLIMIT_RSS: ::__rlimit_resource_t = 7; pub const RLIMIT_NPROC: ::__rlimit_resource_t = 8; pub const RLIMIT_MEMLOCK: ::__rlimit_resource_t = 9; pub const RLIMIT_LOCKS: ::__rlimit_resource_t = 10; pub const RLIMIT_SIGPENDING: ::__rlimit_resource_t = 11; pub const RLIMIT_MSGQUEUE: ::__rlimit_resource_t = 12; pub const RLIMIT_NICE: ::__rlimit_resource_t = 13; pub const RLIMIT_RTPRIO: ::__rlimit_resource_t = 14; pub const RLIMIT_RTTIME: ::__rlimit_resource_t = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::__rlimit_resource_t = RLIM_NLIMITS; } else if #[cfg(target_env = "musl")] { pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_NOFILE: ::c_int = 5; pub const RLIMIT_AS: ::c_int = 6; pub const RLIMIT_RSS: ::c_int = 7; pub const RLIMIT_NPROC: ::c_int = 8; pub const RLIMIT_MEMLOCK: ::c_int = 9; pub const RLIMIT_LOCKS: ::c_int = 10; pub const RLIMIT_SIGPENDING: ::c_int = 11; pub const RLIMIT_MSGQUEUE: ::c_int = 12; pub const RLIMIT_NICE: ::c_int = 13; pub const RLIMIT_RTPRIO: ::c_int = 14; pub const RLIMIT_RTTIME: ::c_int = 15; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 15; #[allow(deprecated)] #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIMIT_NLIMITS: ::c_int = RLIM_NLIMITS; pub const RLIM_INFINITY: ::rlim_t = !0; } } cfg_if! { if #[cfg(target_env = "gnu")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::__rlimit_resource_t = 16; } else if #[cfg(target_env = "uclibc")] { #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::__rlimit_resource_t = 15; } } cfg_if! { if #[cfg(any(target_arch = "mips64", target_arch = "mips64r6"), any(target_env = "gnu", target_env = "uclibc"))] { pub const RLIM_INFINITY: ::rlim_t = !0; } } cfg_if! { if #[cfg(any(target_arch = "mips", target_arch = "mips32r6"), any(target_env = "gnu", target_env = "uclibc"))] { pub const RLIM_INFINITY: ::rlim_t = 0x7fffffff; } } libc/src/unix/linux_like/mod.rs0000644000175000017500000020412614661133735017521 0ustar jamespagejamespagepub type sa_family_t = u16; pub type speed_t = ::c_uint; pub type tcflag_t = ::c_uint; pub type clockid_t = ::c_int; pub type timer_t = *mut ::c_void; pub type key_t = ::c_int; pub type id_t = ::c_uint; missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} } s! { pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, pub imr_sourceaddr: in_addr, } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } // The order of the `ai_addr` field in this struct is crucial // for converting between the Rust and C types. pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: socklen_t, #[cfg(any(target_os = "linux", target_os = "emscripten"))] pub ai_addr: *mut ::sockaddr, pub ai_canonname: *mut c_char, #[cfg(target_os = "android")] pub ai_addr: *mut ::sockaddr, pub ai_next: *mut addrinfo, } pub struct sockaddr_ll { pub sll_family: ::c_ushort, pub sll_protocol: ::c_ushort, pub sll_ifindex: ::c_int, pub sll_hatype: ::c_ushort, pub sll_pkttype: ::c_uchar, pub sll_halen: ::c_uchar, pub sll_addr: [::c_uchar; 8] } pub struct fd_set { fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE], } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, pub tm_gmtoff: ::c_long, pub tm_zone: *const ::c_char, } pub struct sched_param { pub sched_priority: ::c_int, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_low_priority: ::c_int, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_repl_period: ::timespec, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_init_budget: ::timespec, #[cfg(any(target_env = "musl", target_os = "emscripten", target_env = "ohos"))] pub sched_ss_max_repl: ::c_int, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct in_pktinfo { pub ipi_ifindex: ::c_int, pub ipi_spec_dst: ::in_addr, pub ipi_addr: ::in_addr, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: ::c_uint, pub ifa_addr: *mut ::sockaddr, pub ifa_netmask: *mut ::sockaddr, pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union pub ifa_data: *mut ::c_void } pub struct in6_rtmsg { rtmsg_dst: ::in6_addr, rtmsg_src: ::in6_addr, rtmsg_gateway: ::in6_addr, rtmsg_type: u32, rtmsg_dst_len: u16, rtmsg_src_len: u16, rtmsg_metric: u32, rtmsg_info: ::c_ulong, rtmsg_flags: u32, rtmsg_ifindex: ::c_int, } pub struct arpreq { pub arp_pa: ::sockaddr, pub arp_ha: ::sockaddr, pub arp_flags: ::c_int, pub arp_netmask: ::sockaddr, pub arp_dev: [::c_char; 16], } pub struct arpreq_old { pub arp_pa: ::sockaddr, pub arp_ha: ::sockaddr, pub arp_flags: ::c_int, pub arp_netmask: ::sockaddr, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct mmsghdr { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } } s_no_extra_traits! { #[cfg_attr( any( all( target_arch = "x86", not(target_env = "musl"), not(target_os = "android")), target_arch = "x86_64"), repr(packed))] pub struct epoll_event { pub events: u32, pub u64: u64, } pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [::c_char; 108] } pub struct sockaddr_storage { pub ss_family: sa_family_t, #[cfg(target_pointer_width = "32")] __ss_pad2: [u8; 128 - 2 - 4], #[cfg(target_pointer_width = "64")] __ss_pad2: [u8; 128 - 2 - 8], __ss_align: ::size_t, } pub struct utsname { pub sysname: [::c_char; 65], pub nodename: [::c_char; 65], pub release: [::c_char; 65], pub version: [::c_char; 65], pub machine: [::c_char; 65], pub domainname: [::c_char; 65] } pub struct sigevent { pub sigev_value: ::sigval, pub sigev_signo: ::c_int, pub sigev_notify: ::c_int, // Actually a union. We only expose sigev_notify_thread_id because it's // the most useful member pub sigev_notify_thread_id: ::c_int, #[cfg(target_pointer_width = "64")] __unused1: [::c_int; 11], #[cfg(target_pointer_width = "32")] __unused1: [::c_int; 12] } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for epoll_event { fn eq(&self, other: &epoll_event) -> bool { self.events == other.events && self.u64 == other.u64 } } impl Eq for epoll_event {} impl ::fmt::Debug for epoll_event { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let events = self.events; let u64 = self.u64; f.debug_struct("epoll_event") .field("events", &events) .field("u64", &u64) .finish() } } impl ::hash::Hash for epoll_event { fn hash(&self, state: &mut H) { let events = self.events; let u64 = self.u64; events.hash(state); u64.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl ::hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_align", &self.__ss_align) // FIXME: .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) && self .domainname .iter() .zip(other.domainname.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl ::fmt::Debug for utsname { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utsname") // FIXME: .field("sysname", &self.sysname) // FIXME: .field("nodename", &self.nodename) // FIXME: .field("release", &self.release) // FIXME: .field("version", &self.version) // FIXME: .field("machine", &self.machine) // FIXME: .field("domainname", &self.domainname) .finish() } } impl ::hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); self.domainname.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_value == other.sigev_value && self.sigev_signo == other.sigev_signo && self.sigev_notify == other.sigev_notify && self.sigev_notify_thread_id == other.sigev_notify_thread_id } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_value", &self.sigev_value) .field("sigev_signo", &self.sigev_signo) .field("sigev_notify", &self.sigev_notify) .field("sigev_notify_thread_id", &self.sigev_notify_thread_id) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_value.hash(state); self.sigev_signo.hash(state); self.sigev_notify.hash(state); self.sigev_notify_thread_id.hash(state); } } } } // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 2147483647; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 2; pub const _IOLBF: ::c_int = 1; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; // Linux-specific fcntls pub const F_SETLEASE: ::c_int = 1024; pub const F_GETLEASE: ::c_int = 1025; pub const F_NOTIFY: ::c_int = 1026; pub const F_CANCELLK: ::c_int = 1029; pub const F_DUPFD_CLOEXEC: ::c_int = 1030; pub const F_SETPIPE_SZ: ::c_int = 1031; pub const F_GETPIPE_SZ: ::c_int = 1032; pub const F_ADD_SEALS: ::c_int = 1033; pub const F_GET_SEALS: ::c_int = 1034; pub const F_SEAL_SEAL: ::c_int = 0x0001; pub const F_SEAL_SHRINK: ::c_int = 0x0002; pub const F_SEAL_GROW: ::c_int = 0x0004; pub const F_SEAL_WRITE: ::c_int = 0x0008; // FIXME(#235): Include file sealing fcntls once we have a way to verify them. pub const SIGTRAP: ::c_int = 5; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; pub const CLOCK_REALTIME: ::clockid_t = 0; pub const CLOCK_MONOTONIC: ::clockid_t = 1; pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3; pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4; pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5; pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6; pub const CLOCK_BOOTTIME: ::clockid_t = 7; pub const CLOCK_REALTIME_ALARM: ::clockid_t = 8; pub const CLOCK_BOOTTIME_ALARM: ::clockid_t = 9; pub const CLOCK_TAI: ::clockid_t = 11; pub const TIMER_ABSTIME: ::c_int = 1; pub const RUSAGE_SELF: ::c_int = 0; pub const O_RDONLY: ::c_int = 0; pub const O_WRONLY: ::c_int = 1; pub const O_RDWR: ::c_int = 2; pub const SOCK_CLOEXEC: ::c_int = O_CLOEXEC; pub const S_IFIFO: ::mode_t = 4096; pub const S_IFCHR: ::mode_t = 8192; pub const S_IFBLK: ::mode_t = 24576; pub const S_IFDIR: ::mode_t = 16384; pub const S_IFREG: ::mode_t = 32768; pub const S_IFLNK: ::mode_t = 40960; pub const S_IFSOCK: ::mode_t = 49152; pub const S_IFMT: ::mode_t = 61440; pub const S_IRWXU: ::mode_t = 448; pub const S_IXUSR: ::mode_t = 64; pub const S_IWUSR: ::mode_t = 128; pub const S_IRUSR: ::mode_t = 256; pub const S_IRWXG: ::mode_t = 56; pub const S_IXGRP: ::mode_t = 8; pub const S_IWGRP: ::mode_t = 16; pub const S_IRGRP: ::mode_t = 32; pub const S_IRWXO: ::mode_t = 7; pub const S_IXOTH: ::mode_t = 1; pub const S_IWOTH: ::mode_t = 2; pub const S_IROTH: ::mode_t = 4; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const XATTR_CREATE: ::c_int = 0x1; pub const XATTR_REPLACE: ::c_int = 0x2; cfg_if! { if #[cfg(target_os = "android")] { pub const RLIM64_INFINITY: ::c_ulonglong = !0; } else { pub const RLIM64_INFINITY: ::rlim64_t = !0; } } cfg_if! { if #[cfg(target_env = "ohos")] { pub const LC_CTYPE: ::c_int = 0; pub const LC_NUMERIC: ::c_int = 1; pub const LC_TIME: ::c_int = 2; pub const LC_COLLATE: ::c_int = 3; pub const LC_MONETARY: ::c_int = 4; pub const LC_MESSAGES: ::c_int = 5; pub const LC_PAPER: ::c_int = 6; pub const LC_NAME: ::c_int = 7; pub const LC_ADDRESS: ::c_int = 8; pub const LC_TELEPHONE: ::c_int = 9; pub const LC_MEASUREMENT: ::c_int = 10; pub const LC_IDENTIFICATION: ::c_int = 11; pub const LC_ALL: ::c_int = 12; } else if #[cfg(not(target_env = "uclibc"))] { pub const LC_CTYPE: ::c_int = 0; pub const LC_NUMERIC: ::c_int = 1; pub const LC_TIME: ::c_int = 2; pub const LC_COLLATE: ::c_int = 3; pub const LC_MONETARY: ::c_int = 4; pub const LC_MESSAGES: ::c_int = 5; pub const LC_ALL: ::c_int = 6; } } pub const LC_CTYPE_MASK: ::c_int = 1 << LC_CTYPE; pub const LC_NUMERIC_MASK: ::c_int = 1 << LC_NUMERIC; pub const LC_TIME_MASK: ::c_int = 1 << LC_TIME; pub const LC_COLLATE_MASK: ::c_int = 1 << LC_COLLATE; pub const LC_MONETARY_MASK: ::c_int = 1 << LC_MONETARY; pub const LC_MESSAGES_MASK: ::c_int = 1 << LC_MESSAGES; // LC_ALL_MASK defined per platform pub const MAP_FILE: ::c_int = 0x0000; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; // MS_ flags for msync(2) pub const MS_ASYNC: ::c_int = 0x0001; pub const MS_INVALIDATE: ::c_int = 0x0002; pub const MS_SYNC: ::c_int = 0x0004; // MS_ flags for mount(2) pub const MS_RDONLY: ::c_ulong = 0x01; pub const MS_NOSUID: ::c_ulong = 0x02; pub const MS_NODEV: ::c_ulong = 0x04; pub const MS_NOEXEC: ::c_ulong = 0x08; pub const MS_SYNCHRONOUS: ::c_ulong = 0x10; pub const MS_REMOUNT: ::c_ulong = 0x20; pub const MS_MANDLOCK: ::c_ulong = 0x40; pub const MS_DIRSYNC: ::c_ulong = 0x80; pub const MS_NOATIME: ::c_ulong = 0x0400; pub const MS_NODIRATIME: ::c_ulong = 0x0800; pub const MS_BIND: ::c_ulong = 0x1000; pub const MS_MOVE: ::c_ulong = 0x2000; pub const MS_REC: ::c_ulong = 0x4000; pub const MS_SILENT: ::c_ulong = 0x8000; pub const MS_POSIXACL: ::c_ulong = 0x010000; pub const MS_UNBINDABLE: ::c_ulong = 0x020000; pub const MS_PRIVATE: ::c_ulong = 0x040000; pub const MS_SLAVE: ::c_ulong = 0x080000; pub const MS_SHARED: ::c_ulong = 0x100000; pub const MS_RELATIME: ::c_ulong = 0x200000; pub const MS_KERNMOUNT: ::c_ulong = 0x400000; pub const MS_I_VERSION: ::c_ulong = 0x800000; pub const MS_STRICTATIME: ::c_ulong = 0x1000000; pub const MS_LAZYTIME: ::c_ulong = 0x2000000; pub const MS_ACTIVE: ::c_ulong = 0x40000000; pub const MS_MGC_VAL: ::c_ulong = 0xc0ed0000; pub const MS_MGC_MSK: ::c_ulong = 0xffff0000; pub const SCM_RIGHTS: ::c_int = 0x01; pub const SCM_CREDENTIALS: ::c_int = 0x02; pub const PROT_GROWSDOWN: ::c_int = 0x1000000; pub const PROT_GROWSUP: ::c_int = 0x2000000; pub const MAP_TYPE: ::c_int = 0x000f; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const MADV_FREE: ::c_int = 8; pub const MADV_REMOVE: ::c_int = 9; pub const MADV_DONTFORK: ::c_int = 10; pub const MADV_DOFORK: ::c_int = 11; pub const MADV_MERGEABLE: ::c_int = 12; pub const MADV_UNMERGEABLE: ::c_int = 13; pub const MADV_HUGEPAGE: ::c_int = 14; pub const MADV_NOHUGEPAGE: ::c_int = 15; pub const MADV_DONTDUMP: ::c_int = 16; pub const MADV_DODUMP: ::c_int = 17; pub const MADV_WIPEONFORK: ::c_int = 18; pub const MADV_KEEPONFORK: ::c_int = 19; pub const MADV_COLD: ::c_int = 20; pub const MADV_PAGEOUT: ::c_int = 21; pub const MADV_HWPOISON: ::c_int = 100; cfg_if! { if #[cfg(not(target_os = "emscripten"))] { pub const MADV_POPULATE_READ: ::c_int = 22; pub const MADV_POPULATE_WRITE: ::c_int = 23; pub const MADV_DONTNEED_LOCKED: ::c_int = 24; } } pub const IFF_UP: ::c_int = 0x1; pub const IFF_BROADCAST: ::c_int = 0x2; pub const IFF_DEBUG: ::c_int = 0x4; pub const IFF_LOOPBACK: ::c_int = 0x8; pub const IFF_POINTOPOINT: ::c_int = 0x10; pub const IFF_NOTRAILERS: ::c_int = 0x20; pub const IFF_RUNNING: ::c_int = 0x40; pub const IFF_NOARP: ::c_int = 0x80; pub const IFF_PROMISC: ::c_int = 0x100; pub const IFF_ALLMULTI: ::c_int = 0x200; pub const IFF_MASTER: ::c_int = 0x400; pub const IFF_SLAVE: ::c_int = 0x800; pub const IFF_MULTICAST: ::c_int = 0x1000; pub const IFF_PORTSEL: ::c_int = 0x2000; pub const IFF_AUTOMEDIA: ::c_int = 0x4000; pub const IFF_DYNAMIC: ::c_int = 0x8000; pub const SOL_IP: ::c_int = 0; pub const SOL_TCP: ::c_int = 6; pub const SOL_UDP: ::c_int = 17; pub const SOL_IPV6: ::c_int = 41; pub const SOL_ICMPV6: ::c_int = 58; pub const SOL_RAW: ::c_int = 255; pub const SOL_DECNET: ::c_int = 261; pub const SOL_X25: ::c_int = 262; pub const SOL_PACKET: ::c_int = 263; pub const SOL_ATM: ::c_int = 264; pub const SOL_AAL: ::c_int = 265; pub const SOL_IRDA: ::c_int = 266; pub const SOL_NETBEUI: ::c_int = 267; pub const SOL_LLC: ::c_int = 268; pub const SOL_DCCP: ::c_int = 269; pub const SOL_NETLINK: ::c_int = 270; pub const SOL_TIPC: ::c_int = 271; pub const SOL_BLUETOOTH: ::c_int = 274; pub const SOL_ALG: ::c_int = 279; pub const AF_UNSPEC: ::c_int = 0; pub const AF_UNIX: ::c_int = 1; pub const AF_LOCAL: ::c_int = 1; pub const AF_INET: ::c_int = 2; pub const AF_AX25: ::c_int = 3; pub const AF_IPX: ::c_int = 4; pub const AF_APPLETALK: ::c_int = 5; pub const AF_NETROM: ::c_int = 6; pub const AF_BRIDGE: ::c_int = 7; pub const AF_ATMPVC: ::c_int = 8; pub const AF_X25: ::c_int = 9; pub const AF_INET6: ::c_int = 10; pub const AF_ROSE: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_NETBEUI: ::c_int = 13; pub const AF_SECURITY: ::c_int = 14; pub const AF_KEY: ::c_int = 15; pub const AF_NETLINK: ::c_int = 16; pub const AF_ROUTE: ::c_int = AF_NETLINK; pub const AF_PACKET: ::c_int = 17; pub const AF_ASH: ::c_int = 18; pub const AF_ECONET: ::c_int = 19; pub const AF_ATMSVC: ::c_int = 20; pub const AF_RDS: ::c_int = 21; pub const AF_SNA: ::c_int = 22; pub const AF_IRDA: ::c_int = 23; pub const AF_PPPOX: ::c_int = 24; pub const AF_WANPIPE: ::c_int = 25; pub const AF_LLC: ::c_int = 26; pub const AF_CAN: ::c_int = 29; pub const AF_TIPC: ::c_int = 30; pub const AF_BLUETOOTH: ::c_int = 31; pub const AF_IUCV: ::c_int = 32; pub const AF_RXRPC: ::c_int = 33; pub const AF_ISDN: ::c_int = 34; pub const AF_PHONET: ::c_int = 35; pub const AF_IEEE802154: ::c_int = 36; pub const AF_CAIF: ::c_int = 37; pub const AF_ALG: ::c_int = 38; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_UNIX: ::c_int = AF_UNIX; pub const PF_LOCAL: ::c_int = AF_LOCAL; pub const PF_INET: ::c_int = AF_INET; pub const PF_AX25: ::c_int = AF_AX25; pub const PF_IPX: ::c_int = AF_IPX; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_NETROM: ::c_int = AF_NETROM; pub const PF_BRIDGE: ::c_int = AF_BRIDGE; pub const PF_ATMPVC: ::c_int = AF_ATMPVC; pub const PF_X25: ::c_int = AF_X25; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_ROSE: ::c_int = AF_ROSE; pub const PF_DECnet: ::c_int = AF_DECnet; pub const PF_NETBEUI: ::c_int = AF_NETBEUI; pub const PF_SECURITY: ::c_int = AF_SECURITY; pub const PF_KEY: ::c_int = AF_KEY; pub const PF_NETLINK: ::c_int = AF_NETLINK; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_PACKET: ::c_int = AF_PACKET; pub const PF_ASH: ::c_int = AF_ASH; pub const PF_ECONET: ::c_int = AF_ECONET; pub const PF_ATMSVC: ::c_int = AF_ATMSVC; pub const PF_RDS: ::c_int = AF_RDS; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_IRDA: ::c_int = AF_IRDA; pub const PF_PPPOX: ::c_int = AF_PPPOX; pub const PF_WANPIPE: ::c_int = AF_WANPIPE; pub const PF_LLC: ::c_int = AF_LLC; pub const PF_CAN: ::c_int = AF_CAN; pub const PF_TIPC: ::c_int = AF_TIPC; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const PF_IUCV: ::c_int = AF_IUCV; pub const PF_RXRPC: ::c_int = AF_RXRPC; pub const PF_ISDN: ::c_int = AF_ISDN; pub const PF_PHONET: ::c_int = AF_PHONET; pub const PF_IEEE802154: ::c_int = AF_IEEE802154; pub const PF_CAIF: ::c_int = AF_CAIF; pub const PF_ALG: ::c_int = AF_ALG; pub const MSG_OOB: ::c_int = 1; pub const MSG_PEEK: ::c_int = 2; pub const MSG_DONTROUTE: ::c_int = 4; pub const MSG_CTRUNC: ::c_int = 8; pub const MSG_TRUNC: ::c_int = 0x20; pub const MSG_DONTWAIT: ::c_int = 0x40; pub const MSG_EOR: ::c_int = 0x80; pub const MSG_WAITALL: ::c_int = 0x100; pub const MSG_FIN: ::c_int = 0x200; pub const MSG_SYN: ::c_int = 0x400; pub const MSG_CONFIRM: ::c_int = 0x800; pub const MSG_RST: ::c_int = 0x1000; pub const MSG_ERRQUEUE: ::c_int = 0x2000; pub const MSG_NOSIGNAL: ::c_int = 0x4000; pub const MSG_MORE: ::c_int = 0x8000; pub const MSG_WAITFORONE: ::c_int = 0x10000; pub const MSG_FASTOPEN: ::c_int = 0x20000000; pub const MSG_CMSG_CLOEXEC: ::c_int = 0x40000000; pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const IP_TOS: ::c_int = 1; pub const IP_TTL: ::c_int = 2; pub const IP_HDRINCL: ::c_int = 3; pub const IP_OPTIONS: ::c_int = 4; pub const IP_ROUTER_ALERT: ::c_int = 5; pub const IP_RECVOPTS: ::c_int = 6; pub const IP_RETOPTS: ::c_int = 7; pub const IP_PKTINFO: ::c_int = 8; pub const IP_PKTOPTIONS: ::c_int = 9; pub const IP_MTU_DISCOVER: ::c_int = 10; pub const IP_RECVERR: ::c_int = 11; pub const IP_RECVTTL: ::c_int = 12; pub const IP_RECVTOS: ::c_int = 13; pub const IP_MTU: ::c_int = 14; pub const IP_FREEBIND: ::c_int = 15; pub const IP_IPSEC_POLICY: ::c_int = 16; pub const IP_XFRM_POLICY: ::c_int = 17; pub const IP_PASSSEC: ::c_int = 18; pub const IP_TRANSPARENT: ::c_int = 19; pub const IP_ORIGDSTADDR: ::c_int = 20; pub const IP_RECVORIGDSTADDR: ::c_int = IP_ORIGDSTADDR; pub const IP_MINTTL: ::c_int = 21; pub const IP_NODEFRAG: ::c_int = 22; pub const IP_CHECKSUM: ::c_int = 23; pub const IP_BIND_ADDRESS_NO_PORT: ::c_int = 24; pub const IP_MULTICAST_IF: ::c_int = 32; pub const IP_MULTICAST_TTL: ::c_int = 33; pub const IP_MULTICAST_LOOP: ::c_int = 34; pub const IP_ADD_MEMBERSHIP: ::c_int = 35; pub const IP_DROP_MEMBERSHIP: ::c_int = 36; pub const IP_UNBLOCK_SOURCE: ::c_int = 37; pub const IP_BLOCK_SOURCE: ::c_int = 38; pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 39; pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 40; pub const IP_MSFILTER: ::c_int = 41; pub const IP_MULTICAST_ALL: ::c_int = 49; pub const IP_UNICAST_IF: ::c_int = 50; pub const IP_DEFAULT_MULTICAST_TTL: ::c_int = 1; pub const IP_DEFAULT_MULTICAST_LOOP: ::c_int = 1; pub const IP_PMTUDISC_DONT: ::c_int = 0; pub const IP_PMTUDISC_WANT: ::c_int = 1; pub const IP_PMTUDISC_DO: ::c_int = 2; pub const IP_PMTUDISC_PROBE: ::c_int = 3; pub const IP_PMTUDISC_INTERFACE: ::c_int = 4; pub const IP_PMTUDISC_OMIT: ::c_int = 5; // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: ::c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: ::c_int = 2; /// for compatibility pub const IPPROTO_IPIP: ::c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: ::c_int = 8; /// pup pub const IPPROTO_PUP: ::c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: ::c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: ::c_int = 29; /// DCCP pub const IPPROTO_DCCP: ::c_int = 33; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: ::c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: ::c_int = 44; /// resource reservation pub const IPPROTO_RSVP: ::c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: ::c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: ::c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: ::c_int = 51; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: ::c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: ::c_int = 60; pub const IPPROTO_MTP: ::c_int = 92; /// encapsulation header pub const IPPROTO_ENCAP: ::c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: ::c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_COMP: ::c_int = 108; /// SCTP pub const IPPROTO_SCTP: ::c_int = 132; pub const IPPROTO_MH: ::c_int = 135; pub const IPPROTO_UDPLITE: ::c_int = 136; /// raw IP packet pub const IPPROTO_RAW: ::c_int = 255; pub const IPPROTO_BEETPH: ::c_int = 94; pub const IPPROTO_MPLS: ::c_int = 137; /// Multipath TCP pub const IPPROTO_MPTCP: ::c_int = 262; /// Ethernet-within-IPv6 encapsulation. pub const IPPROTO_ETHERNET: ::c_int = 143; pub const MCAST_EXCLUDE: ::c_int = 0; pub const MCAST_INCLUDE: ::c_int = 1; pub const MCAST_JOIN_GROUP: ::c_int = 42; pub const MCAST_BLOCK_SOURCE: ::c_int = 43; pub const MCAST_UNBLOCK_SOURCE: ::c_int = 44; pub const MCAST_LEAVE_GROUP: ::c_int = 45; pub const MCAST_JOIN_SOURCE_GROUP: ::c_int = 46; pub const MCAST_LEAVE_SOURCE_GROUP: ::c_int = 47; pub const MCAST_MSFILTER: ::c_int = 48; pub const IPV6_ADDRFORM: ::c_int = 1; pub const IPV6_2292PKTINFO: ::c_int = 2; pub const IPV6_2292HOPOPTS: ::c_int = 3; pub const IPV6_2292DSTOPTS: ::c_int = 4; pub const IPV6_2292RTHDR: ::c_int = 5; pub const IPV6_2292PKTOPTIONS: ::c_int = 6; pub const IPV6_CHECKSUM: ::c_int = 7; pub const IPV6_2292HOPLIMIT: ::c_int = 8; pub const IPV6_NEXTHOP: ::c_int = 9; pub const IPV6_AUTHHDR: ::c_int = 10; pub const IPV6_UNICAST_HOPS: ::c_int = 16; pub const IPV6_MULTICAST_IF: ::c_int = 17; pub const IPV6_MULTICAST_HOPS: ::c_int = 18; pub const IPV6_MULTICAST_LOOP: ::c_int = 19; pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20; pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21; pub const IPV6_ROUTER_ALERT: ::c_int = 22; pub const IPV6_MTU_DISCOVER: ::c_int = 23; pub const IPV6_MTU: ::c_int = 24; pub const IPV6_RECVERR: ::c_int = 25; pub const IPV6_V6ONLY: ::c_int = 26; pub const IPV6_JOIN_ANYCAST: ::c_int = 27; pub const IPV6_LEAVE_ANYCAST: ::c_int = 28; pub const IPV6_IPSEC_POLICY: ::c_int = 34; pub const IPV6_XFRM_POLICY: ::c_int = 35; pub const IPV6_HDRINCL: ::c_int = 36; pub const IPV6_RECVPKTINFO: ::c_int = 49; pub const IPV6_PKTINFO: ::c_int = 50; pub const IPV6_RECVHOPLIMIT: ::c_int = 51; pub const IPV6_HOPLIMIT: ::c_int = 52; pub const IPV6_RECVHOPOPTS: ::c_int = 53; pub const IPV6_HOPOPTS: ::c_int = 54; pub const IPV6_RTHDRDSTOPTS: ::c_int = 55; pub const IPV6_RECVRTHDR: ::c_int = 56; pub const IPV6_RTHDR: ::c_int = 57; pub const IPV6_RECVDSTOPTS: ::c_int = 58; pub const IPV6_DSTOPTS: ::c_int = 59; pub const IPV6_RECVPATHMTU: ::c_int = 60; pub const IPV6_PATHMTU: ::c_int = 61; pub const IPV6_DONTFRAG: ::c_int = 62; pub const IPV6_RECVTCLASS: ::c_int = 66; pub const IPV6_TCLASS: ::c_int = 67; pub const IPV6_AUTOFLOWLABEL: ::c_int = 70; pub const IPV6_ADDR_PREFERENCES: ::c_int = 72; pub const IPV6_MINHOPCOUNT: ::c_int = 73; pub const IPV6_ORIGDSTADDR: ::c_int = 74; pub const IPV6_RECVORIGDSTADDR: ::c_int = IPV6_ORIGDSTADDR; pub const IPV6_TRANSPARENT: ::c_int = 75; pub const IPV6_UNICAST_IF: ::c_int = 76; pub const IPV6_PREFER_SRC_TMP: ::c_int = 0x0001; pub const IPV6_PREFER_SRC_PUBLIC: ::c_int = 0x0002; pub const IPV6_PREFER_SRC_PUBTMP_DEFAULT: ::c_int = 0x0100; pub const IPV6_PREFER_SRC_COA: ::c_int = 0x0004; pub const IPV6_PREFER_SRC_HOME: ::c_int = 0x0400; pub const IPV6_PREFER_SRC_CGA: ::c_int = 0x0008; pub const IPV6_PREFER_SRC_NONCGA: ::c_int = 0x0800; pub const IPV6_PMTUDISC_DONT: ::c_int = 0; pub const IPV6_PMTUDISC_WANT: ::c_int = 1; pub const IPV6_PMTUDISC_DO: ::c_int = 2; pub const IPV6_PMTUDISC_PROBE: ::c_int = 3; pub const IPV6_PMTUDISC_INTERFACE: ::c_int = 4; pub const IPV6_PMTUDISC_OMIT: ::c_int = 5; pub const TCP_NODELAY: ::c_int = 1; pub const TCP_MAXSEG: ::c_int = 2; pub const TCP_CORK: ::c_int = 3; pub const TCP_KEEPIDLE: ::c_int = 4; pub const TCP_KEEPINTVL: ::c_int = 5; pub const TCP_KEEPCNT: ::c_int = 6; pub const TCP_SYNCNT: ::c_int = 7; pub const TCP_LINGER2: ::c_int = 8; pub const TCP_DEFER_ACCEPT: ::c_int = 9; pub const TCP_WINDOW_CLAMP: ::c_int = 10; pub const TCP_INFO: ::c_int = 11; pub const TCP_QUICKACK: ::c_int = 12; pub const TCP_CONGESTION: ::c_int = 13; pub const TCP_MD5SIG: ::c_int = 14; cfg_if! { if #[cfg(all(target_os = "linux", any( target_env = "gnu", target_env = "musl", target_env = "ohos" )))] { // WARN: deprecated pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15; } } pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16; pub const TCP_THIN_DUPACK: ::c_int = 17; pub const TCP_USER_TIMEOUT: ::c_int = 18; pub const TCP_REPAIR: ::c_int = 19; pub const TCP_REPAIR_QUEUE: ::c_int = 20; pub const TCP_QUEUE_SEQ: ::c_int = 21; pub const TCP_REPAIR_OPTIONS: ::c_int = 22; pub const TCP_FASTOPEN: ::c_int = 23; pub const TCP_TIMESTAMP: ::c_int = 24; pub const TCP_NOTSENT_LOWAT: ::c_int = 25; pub const TCP_CC_INFO: ::c_int = 26; pub const TCP_SAVE_SYN: ::c_int = 27; pub const TCP_SAVED_SYN: ::c_int = 28; cfg_if! { if #[cfg(not(target_os = "emscripten"))] { // NOTE: emscripten doesn't support these options yet. pub const TCP_REPAIR_WINDOW: ::c_int = 29; pub const TCP_FASTOPEN_CONNECT: ::c_int = 30; pub const TCP_ULP: ::c_int = 31; pub const TCP_MD5SIG_EXT: ::c_int = 32; pub const TCP_FASTOPEN_KEY: ::c_int = 33; pub const TCP_FASTOPEN_NO_COOKIE: ::c_int = 34; pub const TCP_ZEROCOPY_RECEIVE: ::c_int = 35; pub const TCP_INQ: ::c_int = 36; pub const TCP_CM_INQ: ::c_int = TCP_INQ; // NOTE: Some CI images doesn't have this option yet. // pub const TCP_TX_DELAY: ::c_int = 37; pub const TCP_MD5SIG_MAXKEYLEN: usize = 80; } } pub const SO_DEBUG: ::c_int = 1; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 2; pub const PATH_MAX: ::c_int = 4096; pub const UIO_MAXIOV: ::c_int = 1024; pub const FD_SETSIZE: usize = 1024; pub const EPOLLIN: ::c_int = 0x1; pub const EPOLLPRI: ::c_int = 0x2; pub const EPOLLOUT: ::c_int = 0x4; pub const EPOLLERR: ::c_int = 0x8; pub const EPOLLHUP: ::c_int = 0x10; pub const EPOLLRDNORM: ::c_int = 0x40; pub const EPOLLRDBAND: ::c_int = 0x80; pub const EPOLLWRNORM: ::c_int = 0x100; pub const EPOLLWRBAND: ::c_int = 0x200; pub const EPOLLMSG: ::c_int = 0x400; pub const EPOLLRDHUP: ::c_int = 0x2000; pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; pub const EPOLLWAKEUP: ::c_int = 0x20000000; pub const EPOLLONESHOT: ::c_int = 0x40000000; pub const EPOLLET: ::c_int = 0x80000000; pub const EPOLL_CTL_ADD: ::c_int = 1; pub const EPOLL_CTL_MOD: ::c_int = 3; pub const EPOLL_CTL_DEL: ::c_int = 2; pub const MNT_FORCE: ::c_int = 0x1; pub const MNT_DETACH: ::c_int = 0x2; pub const MNT_EXPIRE: ::c_int = 0x4; pub const UMOUNT_NOFOLLOW: ::c_int = 0x8; pub const Q_GETFMT: ::c_int = 0x800004; pub const Q_GETINFO: ::c_int = 0x800005; pub const Q_SETINFO: ::c_int = 0x800006; pub const QIF_BLIMITS: u32 = 1; pub const QIF_SPACE: u32 = 2; pub const QIF_ILIMITS: u32 = 4; pub const QIF_INODES: u32 = 8; pub const QIF_BTIME: u32 = 16; pub const QIF_ITIME: u32 = 32; pub const QIF_LIMITS: u32 = 5; pub const QIF_USAGE: u32 = 10; pub const QIF_TIMES: u32 = 48; pub const QIF_ALL: u32 = 63; pub const Q_SYNC: ::c_int = 0x800001; pub const Q_QUOTAON: ::c_int = 0x800002; pub const Q_QUOTAOFF: ::c_int = 0x800003; pub const Q_GETQUOTA: ::c_int = 0x800007; pub const Q_SETQUOTA: ::c_int = 0x800008; pub const TCIOFF: ::c_int = 2; pub const TCION: ::c_int = 3; pub const TCOOFF: ::c_int = 0; pub const TCOON: ::c_int = 1; pub const TCIFLUSH: ::c_int = 0; pub const TCOFLUSH: ::c_int = 1; pub const TCIOFLUSH: ::c_int = 2; pub const NL0: ::tcflag_t = 0x00000000; pub const NL1: ::tcflag_t = 0x00000100; pub const TAB0: ::tcflag_t = 0x00000000; pub const CR0: ::tcflag_t = 0x00000000; pub const FF0: ::tcflag_t = 0x00000000; pub const BS0: ::tcflag_t = 0x00000000; pub const VT0: ::tcflag_t = 0x00000000; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VLNEXT: usize = 15; pub const IGNBRK: ::tcflag_t = 0x00000001; pub const BRKINT: ::tcflag_t = 0x00000002; pub const IGNPAR: ::tcflag_t = 0x00000004; pub const PARMRK: ::tcflag_t = 0x00000008; pub const INPCK: ::tcflag_t = 0x00000010; pub const ISTRIP: ::tcflag_t = 0x00000020; pub const INLCR: ::tcflag_t = 0x00000040; pub const IGNCR: ::tcflag_t = 0x00000080; pub const ICRNL: ::tcflag_t = 0x00000100; pub const IXANY: ::tcflag_t = 0x00000800; pub const IMAXBEL: ::tcflag_t = 0x00002000; pub const OPOST: ::tcflag_t = 0x1; pub const CS5: ::tcflag_t = 0x00000000; pub const CRTSCTS: ::tcflag_t = 0x80000000; pub const ECHO: ::tcflag_t = 0x00000008; pub const OCRNL: ::tcflag_t = 0o000010; pub const ONOCR: ::tcflag_t = 0o000020; pub const ONLRET: ::tcflag_t = 0o000040; pub const OFILL: ::tcflag_t = 0o000100; pub const OFDEL: ::tcflag_t = 0o000200; pub const CLONE_VM: ::c_int = 0x100; pub const CLONE_FS: ::c_int = 0x200; pub const CLONE_FILES: ::c_int = 0x400; pub const CLONE_SIGHAND: ::c_int = 0x800; pub const CLONE_PTRACE: ::c_int = 0x2000; pub const CLONE_VFORK: ::c_int = 0x4000; pub const CLONE_PARENT: ::c_int = 0x8000; pub const CLONE_THREAD: ::c_int = 0x10000; pub const CLONE_NEWNS: ::c_int = 0x20000; pub const CLONE_SYSVSEM: ::c_int = 0x40000; pub const CLONE_SETTLS: ::c_int = 0x80000; pub const CLONE_PARENT_SETTID: ::c_int = 0x100000; pub const CLONE_CHILD_CLEARTID: ::c_int = 0x200000; pub const CLONE_DETACHED: ::c_int = 0x400000; pub const CLONE_UNTRACED: ::c_int = 0x800000; pub const CLONE_CHILD_SETTID: ::c_int = 0x01000000; pub const CLONE_NEWCGROUP: ::c_int = 0x02000000; pub const CLONE_NEWUTS: ::c_int = 0x04000000; pub const CLONE_NEWIPC: ::c_int = 0x08000000; pub const CLONE_NEWUSER: ::c_int = 0x10000000; pub const CLONE_NEWPID: ::c_int = 0x20000000; pub const CLONE_NEWNET: ::c_int = 0x40000000; pub const CLONE_IO: ::c_int = 0x80000000; pub const WNOHANG: ::c_int = 0x00000001; pub const WUNTRACED: ::c_int = 0x00000002; pub const WSTOPPED: ::c_int = WUNTRACED; pub const WEXITED: ::c_int = 0x00000004; pub const WCONTINUED: ::c_int = 0x00000008; pub const WNOWAIT: ::c_int = 0x01000000; // Options for personality(2). pub const ADDR_NO_RANDOMIZE: ::c_int = 0x0040000; pub const MMAP_PAGE_ZERO: ::c_int = 0x0100000; pub const ADDR_COMPAT_LAYOUT: ::c_int = 0x0200000; pub const READ_IMPLIES_EXEC: ::c_int = 0x0400000; pub const ADDR_LIMIT_32BIT: ::c_int = 0x0800000; pub const SHORT_INODE: ::c_int = 0x1000000; pub const WHOLE_SECONDS: ::c_int = 0x2000000; pub const STICKY_TIMEOUTS: ::c_int = 0x4000000; pub const ADDR_LIMIT_3GB: ::c_int = 0x8000000; // Options set using PTRACE_SETOPTIONS. pub const PTRACE_O_TRACESYSGOOD: ::c_int = 0x00000001; pub const PTRACE_O_TRACEFORK: ::c_int = 0x00000002; pub const PTRACE_O_TRACEVFORK: ::c_int = 0x00000004; pub const PTRACE_O_TRACECLONE: ::c_int = 0x00000008; pub const PTRACE_O_TRACEEXEC: ::c_int = 0x00000010; pub const PTRACE_O_TRACEVFORKDONE: ::c_int = 0x00000020; pub const PTRACE_O_TRACEEXIT: ::c_int = 0x00000040; pub const PTRACE_O_TRACESECCOMP: ::c_int = 0x00000080; pub const PTRACE_O_SUSPEND_SECCOMP: ::c_int = 0x00200000; pub const PTRACE_O_EXITKILL: ::c_int = 0x00100000; pub const PTRACE_O_MASK: ::c_int = 0x003000ff; // Wait extended result codes for the above trace options. pub const PTRACE_EVENT_FORK: ::c_int = 1; pub const PTRACE_EVENT_VFORK: ::c_int = 2; pub const PTRACE_EVENT_CLONE: ::c_int = 3; pub const PTRACE_EVENT_EXEC: ::c_int = 4; pub const PTRACE_EVENT_VFORK_DONE: ::c_int = 5; pub const PTRACE_EVENT_EXIT: ::c_int = 6; pub const PTRACE_EVENT_SECCOMP: ::c_int = 7; pub const __WNOTHREAD: ::c_int = 0x20000000; pub const __WALL: ::c_int = 0x40000000; pub const __WCLONE: ::c_int = 0x80000000; pub const SPLICE_F_MOVE: ::c_uint = 0x01; pub const SPLICE_F_NONBLOCK: ::c_uint = 0x02; pub const SPLICE_F_MORE: ::c_uint = 0x04; pub const SPLICE_F_GIFT: ::c_uint = 0x08; pub const RTLD_LOCAL: ::c_int = 0; pub const RTLD_LAZY: ::c_int = 1; pub const POSIX_FADV_NORMAL: ::c_int = 0; pub const POSIX_FADV_RANDOM: ::c_int = 1; pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_FADV_WILLNEED: ::c_int = 3; pub const AT_FDCWD: ::c_int = -100; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x100; pub const AT_REMOVEDIR: ::c_int = 0x200; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; pub const AT_NO_AUTOMOUNT: ::c_int = 0x800; pub const AT_EMPTY_PATH: ::c_int = 0x1000; pub const AT_RECURSIVE: ::c_int = 0x8000; pub const LOG_CRON: ::c_int = 9 << 3; pub const LOG_AUTHPRIV: ::c_int = 10 << 3; pub const LOG_FTP: ::c_int = 11 << 3; pub const LOG_PERROR: ::c_int = 0x20; pub const PIPE_BUF: usize = 4096; pub const SI_LOAD_SHIFT: ::c_uint = 16; // si_code values for SIGBUS signal pub const BUS_ADRALN: ::c_int = 1; pub const BUS_ADRERR: ::c_int = 2; pub const BUS_OBJERR: ::c_int = 3; // Linux-specific si_code values for SIGBUS signal pub const BUS_MCEERR_AR: ::c_int = 4; pub const BUS_MCEERR_AO: ::c_int = 5; // si_code values for SIGCHLD signal pub const CLD_EXITED: ::c_int = 1; pub const CLD_KILLED: ::c_int = 2; pub const CLD_DUMPED: ::c_int = 3; pub const CLD_TRAPPED: ::c_int = 4; pub const CLD_STOPPED: ::c_int = 5; pub const CLD_CONTINUED: ::c_int = 6; pub const SIGEV_SIGNAL: ::c_int = 0; pub const SIGEV_NONE: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 2; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; cfg_if! { if #[cfg(not(target_os = "emscripten"))] { pub const P_PIDFD: idtype_t = 3; } } pub const UTIME_OMIT: c_long = 1073741822; pub const UTIME_NOW: c_long = 1073741823; pub const POLLIN: ::c_short = 0x1; pub const POLLPRI: ::c_short = 0x2; pub const POLLOUT: ::c_short = 0x4; pub const POLLERR: ::c_short = 0x8; pub const POLLHUP: ::c_short = 0x10; pub const POLLNVAL: ::c_short = 0x20; pub const POLLRDNORM: ::c_short = 0x040; pub const POLLRDBAND: ::c_short = 0x080; #[cfg(not(any(target_arch = "sparc", target_arch = "sparc64")))] pub const POLLRDHUP: ::c_short = 0x2000; #[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] pub const POLLRDHUP: ::c_short = 0x800; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; pub const IPTOS_RELIABILITY: u8 = 0x04; pub const IPTOS_MINCOST: u8 = 0x02; pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0; pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0; pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0; pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80; pub const IPTOS_PREC_FLASH: u8 = 0x60; pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40; pub const IPTOS_PREC_PRIORITY: u8 = 0x20; pub const IPTOS_PREC_ROUTINE: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const IPOPT_COPY: u8 = 0x80; pub const IPOPT_CLASS_MASK: u8 = 0x60; pub const IPOPT_NUMBER_MASK: u8 = 0x1f; pub const IPOPT_CONTROL: u8 = 0x00; pub const IPOPT_RESERVED1: u8 = 0x20; pub const IPOPT_MEASUREMENT: u8 = 0x40; pub const IPOPT_RESERVED2: u8 = 0x60; pub const IPOPT_END: u8 = 0 | IPOPT_CONTROL; pub const IPOPT_NOOP: u8 = 1 | IPOPT_CONTROL; pub const IPOPT_SEC: u8 = 2 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_LSRR: u8 = 3 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_TIMESTAMP: u8 = 4 | IPOPT_MEASUREMENT; pub const IPOPT_RR: u8 = 7 | IPOPT_CONTROL; pub const IPOPT_SID: u8 = 8 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_SSRR: u8 = 9 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_RA: u8 = 20 | IPOPT_CONTROL | IPOPT_COPY; pub const IPVERSION: u8 = 4; pub const MAXTTL: u8 = 255; pub const IPDEFTTL: u8 = 64; pub const IPOPT_OPTVAL: u8 = 0; pub const IPOPT_OLEN: u8 = 1; pub const IPOPT_OFFSET: u8 = 2; pub const IPOPT_MINOFF: u8 = 4; pub const MAX_IPOPTLEN: u8 = 40; pub const IPOPT_NOP: u8 = IPOPT_NOOP; pub const IPOPT_EOL: u8 = IPOPT_END; pub const IPOPT_TS: u8 = IPOPT_TIMESTAMP; pub const IPOPT_TS_TSONLY: u8 = 0; pub const IPOPT_TS_TSANDADDR: u8 = 1; pub const IPOPT_TS_PRESPEC: u8 = 3; pub const ARPOP_RREQUEST: u16 = 3; pub const ARPOP_RREPLY: u16 = 4; pub const ARPOP_InREQUEST: u16 = 8; pub const ARPOP_InREPLY: u16 = 9; pub const ARPOP_NAK: u16 = 10; pub const ATF_NETMASK: ::c_int = 0x20; pub const ATF_DONTPUB: ::c_int = 0x40; pub const ARPHRD_NETROM: u16 = 0; pub const ARPHRD_ETHER: u16 = 1; pub const ARPHRD_EETHER: u16 = 2; pub const ARPHRD_AX25: u16 = 3; pub const ARPHRD_PRONET: u16 = 4; pub const ARPHRD_CHAOS: u16 = 5; pub const ARPHRD_IEEE802: u16 = 6; pub const ARPHRD_ARCNET: u16 = 7; pub const ARPHRD_APPLETLK: u16 = 8; pub const ARPHRD_DLCI: u16 = 15; pub const ARPHRD_ATM: u16 = 19; pub const ARPHRD_METRICOM: u16 = 23; pub const ARPHRD_IEEE1394: u16 = 24; pub const ARPHRD_EUI64: u16 = 27; pub const ARPHRD_INFINIBAND: u16 = 32; pub const ARPHRD_SLIP: u16 = 256; pub const ARPHRD_CSLIP: u16 = 257; pub const ARPHRD_SLIP6: u16 = 258; pub const ARPHRD_CSLIP6: u16 = 259; pub const ARPHRD_RSRVD: u16 = 260; pub const ARPHRD_ADAPT: u16 = 264; pub const ARPHRD_ROSE: u16 = 270; pub const ARPHRD_X25: u16 = 271; pub const ARPHRD_HWX25: u16 = 272; pub const ARPHRD_CAN: u16 = 280; pub const ARPHRD_PPP: u16 = 512; pub const ARPHRD_CISCO: u16 = 513; pub const ARPHRD_HDLC: u16 = ARPHRD_CISCO; pub const ARPHRD_LAPB: u16 = 516; pub const ARPHRD_DDCMP: u16 = 517; pub const ARPHRD_RAWHDLC: u16 = 518; pub const ARPHRD_TUNNEL: u16 = 768; pub const ARPHRD_TUNNEL6: u16 = 769; pub const ARPHRD_FRAD: u16 = 770; pub const ARPHRD_SKIP: u16 = 771; pub const ARPHRD_LOOPBACK: u16 = 772; pub const ARPHRD_LOCALTLK: u16 = 773; pub const ARPHRD_FDDI: u16 = 774; pub const ARPHRD_BIF: u16 = 775; pub const ARPHRD_SIT: u16 = 776; pub const ARPHRD_IPDDP: u16 = 777; pub const ARPHRD_IPGRE: u16 = 778; pub const ARPHRD_PIMREG: u16 = 779; pub const ARPHRD_HIPPI: u16 = 780; pub const ARPHRD_ASH: u16 = 781; pub const ARPHRD_ECONET: u16 = 782; pub const ARPHRD_IRDA: u16 = 783; pub const ARPHRD_FCPP: u16 = 784; pub const ARPHRD_FCAL: u16 = 785; pub const ARPHRD_FCPL: u16 = 786; pub const ARPHRD_FCFABRIC: u16 = 787; pub const ARPHRD_IEEE802_TR: u16 = 800; pub const ARPHRD_IEEE80211: u16 = 801; pub const ARPHRD_IEEE80211_PRISM: u16 = 802; pub const ARPHRD_IEEE80211_RADIOTAP: u16 = 803; pub const ARPHRD_IEEE802154: u16 = 804; pub const ARPHRD_VOID: u16 = 0xFFFF; pub const ARPHRD_NONE: u16 = 0xFFFE; cfg_if! { if #[cfg(target_os = "emscripten")] { // Emscripten does not define any `*_SUPER_MAGIC` constants. } else if #[cfg(not(target_arch = "s390x"))] { pub const ADFS_SUPER_MAGIC: ::c_long = 0x0000adf5; pub const AFFS_SUPER_MAGIC: ::c_long = 0x0000adff; pub const AFS_SUPER_MAGIC: ::c_long = 0x5346414f; pub const AUTOFS_SUPER_MAGIC: ::c_long = 0x0187; pub const BPF_FS_MAGIC: ::c_long = 0xcafe4a11; pub const BTRFS_SUPER_MAGIC: ::c_long = 0x9123683e; pub const CGROUP2_SUPER_MAGIC: ::c_long = 0x63677270; pub const CGROUP_SUPER_MAGIC: ::c_long = 0x27e0eb; pub const CODA_SUPER_MAGIC: ::c_long = 0x73757245; pub const CRAMFS_MAGIC: ::c_long = 0x28cd3d45; pub const DEBUGFS_MAGIC: ::c_long = 0x64626720; pub const DEVPTS_SUPER_MAGIC: ::c_long = 0x1cd1; pub const ECRYPTFS_SUPER_MAGIC: ::c_long = 0xf15f; pub const EFS_SUPER_MAGIC: ::c_long = 0x00414a53; pub const EXT2_SUPER_MAGIC: ::c_long = 0x0000ef53; pub const EXT3_SUPER_MAGIC: ::c_long = 0x0000ef53; pub const EXT4_SUPER_MAGIC: ::c_long = 0x0000ef53; pub const F2FS_SUPER_MAGIC: ::c_long = 0xf2f52010; pub const FUSE_SUPER_MAGIC: ::c_long = 0x65735546; pub const FUTEXFS_SUPER_MAGIC: ::c_long = 0xbad1dea; pub const HOSTFS_SUPER_MAGIC: ::c_long = 0x00c0ffee; pub const HPFS_SUPER_MAGIC: ::c_long = 0xf995e849; pub const HUGETLBFS_MAGIC: ::c_long = 0x958458f6; pub const ISOFS_SUPER_MAGIC: ::c_long = 0x00009660; pub const JFFS2_SUPER_MAGIC: ::c_long = 0x000072b6; pub const MINIX2_SUPER_MAGIC2: ::c_long = 0x00002478; pub const MINIX2_SUPER_MAGIC: ::c_long = 0x00002468; pub const MINIX3_SUPER_MAGIC: ::c_long = 0x4d5a; pub const MINIX_SUPER_MAGIC2: ::c_long = 0x0000138f; pub const MINIX_SUPER_MAGIC: ::c_long = 0x0000137f; pub const MSDOS_SUPER_MAGIC: ::c_long = 0x00004d44; pub const NCP_SUPER_MAGIC: ::c_long = 0x0000564c; pub const NFS_SUPER_MAGIC: ::c_long = 0x00006969; pub const NILFS_SUPER_MAGIC: ::c_long = 0x3434; pub const OCFS2_SUPER_MAGIC: ::c_long = 0x7461636f; pub const OPENPROM_SUPER_MAGIC: ::c_long = 0x00009fa1; pub const OVERLAYFS_SUPER_MAGIC: ::c_long = 0x794c7630; pub const PROC_SUPER_MAGIC: ::c_long = 0x00009fa0; pub const QNX4_SUPER_MAGIC: ::c_long = 0x0000002f; pub const QNX6_SUPER_MAGIC: ::c_long = 0x68191122; pub const RDTGROUP_SUPER_MAGIC: ::c_long = 0x7655821; pub const REISERFS_SUPER_MAGIC: ::c_long = 0x52654973; pub const SECURITYFS_MAGIC: ::c_long = 0x73636673; pub const SELINUX_MAGIC: ::c_long = 0xf97cff8c; pub const SMACK_MAGIC: ::c_long = 0x43415d53; pub const SMB_SUPER_MAGIC: ::c_long = 0x0000517b; pub const SYSFS_MAGIC: ::c_long = 0x62656572; pub const TMPFS_MAGIC: ::c_long = 0x01021994; pub const TRACEFS_MAGIC: ::c_long = 0x74726163; pub const UDF_SUPER_MAGIC: ::c_long = 0x15013346; pub const USBDEVICE_SUPER_MAGIC: ::c_long = 0x00009fa2; pub const XENFS_SUPER_MAGIC: ::c_long = 0xabba1974; pub const NSFS_MAGIC: ::c_long = 0x6e736673; } else if #[cfg(target_arch = "s390x")] { pub const ADFS_SUPER_MAGIC: ::c_uint = 0x0000adf5; pub const AFFS_SUPER_MAGIC: ::c_uint = 0x0000adff; pub const AFS_SUPER_MAGIC: ::c_uint = 0x5346414f; pub const AUTOFS_SUPER_MAGIC: ::c_uint = 0x0187; pub const BPF_FS_MAGIC: ::c_uint = 0xcafe4a11; pub const BTRFS_SUPER_MAGIC: ::c_uint = 0x9123683e; pub const CGROUP2_SUPER_MAGIC: ::c_uint = 0x63677270; pub const CGROUP_SUPER_MAGIC: ::c_uint = 0x27e0eb; pub const CODA_SUPER_MAGIC: ::c_uint = 0x73757245; pub const CRAMFS_MAGIC: ::c_uint = 0x28cd3d45; pub const DEBUGFS_MAGIC: ::c_uint = 0x64626720; pub const DEVPTS_SUPER_MAGIC: ::c_uint = 0x1cd1; pub const ECRYPTFS_SUPER_MAGIC: ::c_uint = 0xf15f; pub const EFS_SUPER_MAGIC: ::c_uint = 0x00414a53; pub const EXT2_SUPER_MAGIC: ::c_uint = 0x0000ef53; pub const EXT3_SUPER_MAGIC: ::c_uint = 0x0000ef53; pub const EXT4_SUPER_MAGIC: ::c_uint = 0x0000ef53; pub const F2FS_SUPER_MAGIC: ::c_uint = 0xf2f52010; pub const FUSE_SUPER_MAGIC: ::c_uint = 0x65735546; pub const FUTEXFS_SUPER_MAGIC: ::c_uint = 0xbad1dea; pub const HOSTFS_SUPER_MAGIC: ::c_uint = 0x00c0ffee; pub const HPFS_SUPER_MAGIC: ::c_uint = 0xf995e849; pub const HUGETLBFS_MAGIC: ::c_uint = 0x958458f6; pub const ISOFS_SUPER_MAGIC: ::c_uint = 0x00009660; pub const JFFS2_SUPER_MAGIC: ::c_uint = 0x000072b6; pub const MINIX2_SUPER_MAGIC2: ::c_uint = 0x00002478; pub const MINIX2_SUPER_MAGIC: ::c_uint = 0x00002468; pub const MINIX3_SUPER_MAGIC: ::c_uint = 0x4d5a; pub const MINIX_SUPER_MAGIC2: ::c_uint = 0x0000138f; pub const MINIX_SUPER_MAGIC: ::c_uint = 0x0000137f; pub const MSDOS_SUPER_MAGIC: ::c_uint = 0x00004d44; pub const NCP_SUPER_MAGIC: ::c_uint = 0x0000564c; pub const NFS_SUPER_MAGIC: ::c_uint = 0x00006969; pub const NILFS_SUPER_MAGIC: ::c_uint = 0x3434; pub const OCFS2_SUPER_MAGIC: ::c_uint = 0x7461636f; pub const OPENPROM_SUPER_MAGIC: ::c_uint = 0x00009fa1; pub const OVERLAYFS_SUPER_MAGIC: ::c_uint = 0x794c7630; pub const PROC_SUPER_MAGIC: ::c_uint = 0x00009fa0; pub const QNX4_SUPER_MAGIC: ::c_uint = 0x0000002f; pub const QNX6_SUPER_MAGIC: ::c_uint = 0x68191122; pub const RDTGROUP_SUPER_MAGIC: ::c_uint = 0x7655821; pub const REISERFS_SUPER_MAGIC: ::c_uint = 0x52654973; pub const SECURITYFS_MAGIC: ::c_uint = 0x73636673; pub const SELINUX_MAGIC: ::c_uint = 0xf97cff8c; pub const SMACK_MAGIC: ::c_uint = 0x43415d53; pub const SMB_SUPER_MAGIC: ::c_uint = 0x0000517b; pub const SYSFS_MAGIC: ::c_uint = 0x62656572; pub const TMPFS_MAGIC: ::c_uint = 0x01021994; pub const TRACEFS_MAGIC: ::c_uint = 0x74726163; pub const UDF_SUPER_MAGIC: ::c_uint = 0x15013346; pub const USBDEVICE_SUPER_MAGIC: ::c_uint = 0x00009fa2; pub const XENFS_SUPER_MAGIC: ::c_uint = 0xabba1974; pub const NSFS_MAGIC: ::c_uint = 0x6e736673; } } const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + ::mem::size_of::() - 1 & !(::mem::size_of::() - 1) } } f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= ::mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut ::c_uchar { cmsg.offset(1) as *mut ::c_uchar } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(::mem::size_of::())) as ::c_uint } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { CMSG_ALIGN(::mem::size_of::()) as ::c_uint + length } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub fn SIGRTMAX() -> ::c_int { unsafe { __libc_current_sigrtmax() } } pub fn SIGRTMIN() -> ::c_int { unsafe { __libc_current_sigrtmin() } } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { status & 0x7f } pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0x80) != 0 } pub {const} fn W_EXITCODE(ret: ::c_int, sig: ::c_int) -> ::c_int { (ret << 8) | sig } pub {const} fn W_STOPCODE(sig: ::c_int) -> ::c_int { (sig << 8) | 0x7f } pub {const} fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int { (cmd << 8) | (type_ & 0x00ff) } pub {const} fn IPOPT_COPIED(o: u8) -> u8 { o & IPOPT_COPY } pub {const} fn IPOPT_CLASS(o: u8) -> u8 { o & IPOPT_CLASS_MASK } pub {const} fn IPOPT_NUMBER(o: u8) -> u8 { o & IPOPT_NUMBER_MASK } pub {const} fn IPTOS_ECN(x: u8) -> u8 { x & ::IPTOS_ECN_MASK } #[allow(ellipsis_inclusive_range_patterns)] pub {const} fn KERNEL_VERSION(a: u32, b: u32, c: u32) -> u32 { ((a << 16) + (b << 8)) + match c { 0 ... 255 => c, _ => 255, } } } extern "C" { #[doc(hidden)] pub fn __libc_current_sigrtmax() -> ::c_int; #[doc(hidden)] pub fn __libc_current_sigrtmin() -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn mincore(addr: *mut ::c_void, len: ::size_t, vec: *mut ::c_uchar) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn setgroups(ngroups: ::size_t, ptr: *const ::gid_t) -> ::c_int; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_mutexattr_setpshared( attr: *mut pthread_mutexattr_t, pshared: ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; pub fn clearenv() -> ::c_int; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, suid: *mut ::uid_t) -> ::c_int; pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, sgid: *mut ::gid_t) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; pub fn brk(addr: *mut ::c_void) -> ::c_int; pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; #[deprecated( since = "0.2.66", note = "causes memory corruption, see rust-lang/libc#1596" )] pub fn vfork() -> ::pid_t; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; pub fn wait4( pid: ::pid_t, status: *mut ::c_int, options: ::c_int, rusage: *mut ::rusage, ) -> ::pid_t; pub fn login_tty(fd: ::c_int) -> ::c_int; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn fexecve( fd: ::c_int, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn strchrnul(s: *const ::c_char, c: ::c_int) -> *mut ::c_char; pub fn strftime( s: *mut ::c_char, max: ::size_t, format: *const ::c_char, tm: *const ::tm, ) -> ::size_t; pub fn strftime_l( s: *mut ::c_char, max: ::size_t, format: *const ::c_char, tm: *const ::tm, locale: ::locale_t, ) -> ::size_t; pub fn strptime(s: *const ::c_char, format: *const ::c_char, tm: *mut ::tm) -> *mut ::c_char; } // LFS64 extensions // // * musl and Emscripten has 64-bit versions only so aliases the LFS64 symbols to the standard ones // * ulibc doesn't have preadv64/pwritev64 cfg_if! { if #[cfg(not(any(target_env = "musl", target_os = "emscripten")))] { extern "C" { pub fn fstatfs64(fd: ::c_int, buf: *mut statfs64) -> ::c_int; pub fn statvfs64(path: *const ::c_char, buf: *mut statvfs64) -> ::c_int; pub fn fstatvfs64(fd: ::c_int, buf: *mut statvfs64) -> ::c_int; pub fn statfs64(path: *const ::c_char, buf: *mut statfs64) -> ::c_int; pub fn creat64(path: *const c_char, mode: mode_t) -> ::c_int; pub fn fstat64(fildes: ::c_int, buf: *mut stat64) -> ::c_int; pub fn fstatat64( dirfd: ::c_int, pathname: *const c_char, buf: *mut stat64, flags: ::c_int, ) -> ::c_int; pub fn ftruncate64(fd: ::c_int, length: off64_t) -> ::c_int; pub fn lseek64(fd: ::c_int, offset: off64_t, whence: ::c_int) -> off64_t; pub fn lstat64(path: *const c_char, buf: *mut stat64) -> ::c_int; pub fn mmap64( addr: *mut ::c_void, len: ::size_t, prot: ::c_int, flags: ::c_int, fd: ::c_int, offset: off64_t, ) -> *mut ::c_void; pub fn open64(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; pub fn openat64(fd: ::c_int, path: *const c_char, oflag: ::c_int, ...) -> ::c_int; pub fn posix_fadvise64( fd: ::c_int, offset: ::off64_t, len: ::off64_t, advise: ::c_int, ) -> ::c_int; pub fn pread64( fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off64_t ) -> ::ssize_t; pub fn pwrite64( fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off64_t, ) -> ::ssize_t; pub fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64; pub fn readdir64_r( dirp: *mut ::DIR, entry: *mut ::dirent64, result: *mut *mut ::dirent64, ) -> ::c_int; pub fn stat64(path: *const c_char, buf: *mut stat64) -> ::c_int; pub fn truncate64(path: *const c_char, length: off64_t) -> ::c_int; } } } cfg_if! { if #[cfg(not(any(target_env = "uclibc", target_env = "musl", target_os = "emscripten")))] { extern "C" { pub fn preadv64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t; pub fn pwritev64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t; } } } cfg_if! { if #[cfg(not(target_env = "uclibc"))] { extern "C" { // uclibc has separate non-const version of this function pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *const termios, winp: *const ::winsize, ) -> ::pid_t; // uclibc has separate non-const version of this function pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *const termios, winp: *const ::winsize, ) -> ::c_int; } } } cfg_if! { if #[cfg(target_os = "emscripten")] { mod emscripten; pub use self::emscripten::*; } else if #[cfg(target_os = "linux")] { mod linux; pub use self::linux::*; } else if #[cfg(target_os = "l4re")] { mod linux; pub use self::linux::*; } else if #[cfg(target_os = "android")] { mod android; pub use self::android::*; } else { // Unknown target_os } } libc/src/unix/linux_like/android/0000775000175000017500000000000014661133735020011 5ustar jamespagejamespagelibc/src/unix/linux_like/android/b32/0000775000175000017500000000000014661133735020377 5ustar jamespagejamespagelibc/src/unix/linux_like/android/b32/arm.rs0000644000175000017500000005300314661133735021523 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type greg_t = i32; pub type mcontext_t = sigcontext; s! { pub struct sigcontext { pub trap_no: ::c_ulong, pub error_code: ::c_ulong, pub oldmask: ::c_ulong, pub arm_r0: ::c_ulong, pub arm_r1: ::c_ulong, pub arm_r2: ::c_ulong, pub arm_r3: ::c_ulong, pub arm_r4: ::c_ulong, pub arm_r5: ::c_ulong, pub arm_r6: ::c_ulong, pub arm_r7: ::c_ulong, pub arm_r8: ::c_ulong, pub arm_r9: ::c_ulong, pub arm_r10: ::c_ulong, pub arm_fp: ::c_ulong, pub arm_ip: ::c_ulong, pub arm_sp: ::c_ulong, pub arm_lr: ::c_ulong, pub arm_pc: ::c_ulong, pub arm_cpsr: ::c_ulong, pub fault_address: ::c_ulong, } } cfg_if! { if #[cfg(libc_union)] { s_no_extra_traits! { pub struct __c_anonymous_uc_sigmask_with_padding { pub uc_sigmask: ::sigset_t, /* Android has a wrong (smaller) sigset_t on x86. */ __padding_rt_sigset: u32, } pub union __c_anonymous_uc_sigmask { uc_sigmask: __c_anonymous_uc_sigmask_with_padding, uc_sigmask64: ::sigset64_t, } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask__c_anonymous_union: __c_anonymous_uc_sigmask, /* The kernel adds extra padding after uc_sigmask to match * glibc sigset_t on ARM. */ __padding: [c_char; 120], __align: [::c_longlong; 0], uc_regspace: [::c_ulong; 128], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous_uc_sigmask_with_padding { fn eq( &self, other: &__c_anonymous_uc_sigmask_with_padding ) -> bool { self.uc_sigmask == other.uc_sigmask // Ignore padding } } impl Eq for __c_anonymous_uc_sigmask_with_padding {} impl ::fmt::Debug for __c_anonymous_uc_sigmask_with_padding { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uc_sigmask_with_padding") .field("uc_sigmask_with_padding", &self.uc_sigmask) // Ignore padding .finish() } } impl ::hash::Hash for __c_anonymous_uc_sigmask_with_padding { fn hash(&self, state: &mut H) { self.uc_sigmask.hash(state) // Ignore padding } } impl PartialEq for __c_anonymous_uc_sigmask { fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool { unsafe { self.uc_sigmask == other.uc_sigmask } } } impl Eq for __c_anonymous_uc_sigmask {} impl ::fmt::Debug for __c_anonymous_uc_sigmask { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uc_sigmask") .field("uc_sigmask", unsafe { &self.uc_sigmask }) .finish() } } impl ::hash::Hash for __c_anonymous_uc_sigmask { fn hash(&self, state: &mut H) { unsafe { self.uc_sigmask.hash(state) } } } impl PartialEq for ucontext_t { fn eq(&self, other: &Self) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask__c_anonymous_union == other.uc_sigmask__c_anonymous_union && &self.uc_regspace[..] == &other.uc_regspace[..] // Ignore padding field } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field( "uc_sigmask__c_anonymous_union", &self.uc_sigmask__c_anonymous_union ) .field("uc_regspace", &&self.uc_regspace[..]) // Ignore padding field .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask__c_anonymous_union.hash(state); self.uc_regspace[..].hash(state); // Ignore padding field } } } } } } pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_LARGEFILE: ::c_int = 0o400000; pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_ptrace: ::c_long = 26; pub const SYS_pause: ::c_long = 29; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_setpgid: ::c_long = 57; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_symlink: ::c_long = 83; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_vhangup: ::c_long = 111; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; pub const SYS_getdents: ::c_long = 141; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid: ::c_long = 170; pub const SYS_getresgid: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_chown: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_vfork: ::c_long = 190; pub const SYS_ugetrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_lchown32: ::c_long = 198; pub const SYS_getuid32: ::c_long = 199; pub const SYS_getgid32: ::c_long = 200; pub const SYS_geteuid32: ::c_long = 201; pub const SYS_getegid32: ::c_long = 202; pub const SYS_setreuid32: ::c_long = 203; pub const SYS_setregid32: ::c_long = 204; pub const SYS_getgroups32: ::c_long = 205; pub const SYS_setgroups32: ::c_long = 206; pub const SYS_fchown32: ::c_long = 207; pub const SYS_setresuid32: ::c_long = 208; pub const SYS_getresuid32: ::c_long = 209; pub const SYS_setresgid32: ::c_long = 210; pub const SYS_getresgid32: ::c_long = 211; pub const SYS_chown32: ::c_long = 212; pub const SYS_setuid32: ::c_long = 213; pub const SYS_setgid32: ::c_long = 214; pub const SYS_setfsuid32: ::c_long = 215; pub const SYS_setfsgid32: ::c_long = 216; pub const SYS_getdents64: ::c_long = 217; pub const SYS_pivot_root: ::c_long = 218; pub const SYS_mincore: ::c_long = 219; pub const SYS_madvise: ::c_long = 220; pub const SYS_fcntl64: ::c_long = 221; pub const SYS_gettid: ::c_long = 224; pub const SYS_readahead: ::c_long = 225; pub const SYS_setxattr: ::c_long = 226; pub const SYS_lsetxattr: ::c_long = 227; pub const SYS_fsetxattr: ::c_long = 228; pub const SYS_getxattr: ::c_long = 229; pub const SYS_lgetxattr: ::c_long = 230; pub const SYS_fgetxattr: ::c_long = 231; pub const SYS_listxattr: ::c_long = 232; pub const SYS_llistxattr: ::c_long = 233; pub const SYS_flistxattr: ::c_long = 234; pub const SYS_removexattr: ::c_long = 235; pub const SYS_lremovexattr: ::c_long = 236; pub const SYS_fremovexattr: ::c_long = 237; pub const SYS_tkill: ::c_long = 238; pub const SYS_sendfile64: ::c_long = 239; pub const SYS_futex: ::c_long = 240; pub const SYS_sched_setaffinity: ::c_long = 241; pub const SYS_sched_getaffinity: ::c_long = 242; pub const SYS_io_setup: ::c_long = 243; pub const SYS_io_destroy: ::c_long = 244; pub const SYS_io_getevents: ::c_long = 245; pub const SYS_io_submit: ::c_long = 246; pub const SYS_io_cancel: ::c_long = 247; pub const SYS_exit_group: ::c_long = 248; pub const SYS_lookup_dcookie: ::c_long = 249; pub const SYS_epoll_create: ::c_long = 250; pub const SYS_epoll_ctl: ::c_long = 251; pub const SYS_epoll_wait: ::c_long = 252; pub const SYS_remap_file_pages: ::c_long = 253; pub const SYS_set_tid_address: ::c_long = 256; pub const SYS_timer_create: ::c_long = 257; pub const SYS_timer_settime: ::c_long = 258; pub const SYS_timer_gettime: ::c_long = 259; pub const SYS_timer_getoverrun: ::c_long = 260; pub const SYS_timer_delete: ::c_long = 261; pub const SYS_clock_settime: ::c_long = 262; pub const SYS_clock_gettime: ::c_long = 263; pub const SYS_clock_getres: ::c_long = 264; pub const SYS_clock_nanosleep: ::c_long = 265; pub const SYS_statfs64: ::c_long = 266; pub const SYS_fstatfs64: ::c_long = 267; pub const SYS_tgkill: ::c_long = 268; pub const SYS_utimes: ::c_long = 269; pub const SYS_arm_fadvise64_64: ::c_long = 270; pub const SYS_pciconfig_iobase: ::c_long = 271; pub const SYS_pciconfig_read: ::c_long = 272; pub const SYS_pciconfig_write: ::c_long = 273; pub const SYS_mq_open: ::c_long = 274; pub const SYS_mq_unlink: ::c_long = 275; pub const SYS_mq_timedsend: ::c_long = 276; pub const SYS_mq_timedreceive: ::c_long = 277; pub const SYS_mq_notify: ::c_long = 278; pub const SYS_mq_getsetattr: ::c_long = 279; pub const SYS_waitid: ::c_long = 280; pub const SYS_socket: ::c_long = 281; pub const SYS_bind: ::c_long = 282; pub const SYS_connect: ::c_long = 283; pub const SYS_listen: ::c_long = 284; pub const SYS_accept: ::c_long = 285; pub const SYS_getsockname: ::c_long = 286; pub const SYS_getpeername: ::c_long = 287; pub const SYS_socketpair: ::c_long = 288; pub const SYS_send: ::c_long = 289; pub const SYS_sendto: ::c_long = 290; pub const SYS_recv: ::c_long = 291; pub const SYS_recvfrom: ::c_long = 292; pub const SYS_shutdown: ::c_long = 293; pub const SYS_setsockopt: ::c_long = 294; pub const SYS_getsockopt: ::c_long = 295; pub const SYS_sendmsg: ::c_long = 296; pub const SYS_recvmsg: ::c_long = 297; pub const SYS_semop: ::c_long = 298; pub const SYS_semget: ::c_long = 299; pub const SYS_semctl: ::c_long = 300; pub const SYS_msgsnd: ::c_long = 301; pub const SYS_msgrcv: ::c_long = 302; pub const SYS_msgget: ::c_long = 303; pub const SYS_msgctl: ::c_long = 304; pub const SYS_shmat: ::c_long = 305; pub const SYS_shmdt: ::c_long = 306; pub const SYS_shmget: ::c_long = 307; pub const SYS_shmctl: ::c_long = 308; pub const SYS_add_key: ::c_long = 309; pub const SYS_request_key: ::c_long = 310; pub const SYS_keyctl: ::c_long = 311; pub const SYS_semtimedop: ::c_long = 312; pub const SYS_vserver: ::c_long = 313; pub const SYS_ioprio_set: ::c_long = 314; pub const SYS_ioprio_get: ::c_long = 315; pub const SYS_inotify_init: ::c_long = 316; pub const SYS_inotify_add_watch: ::c_long = 317; pub const SYS_inotify_rm_watch: ::c_long = 318; pub const SYS_mbind: ::c_long = 319; pub const SYS_get_mempolicy: ::c_long = 320; pub const SYS_set_mempolicy: ::c_long = 321; pub const SYS_openat: ::c_long = 322; pub const SYS_mkdirat: ::c_long = 323; pub const SYS_mknodat: ::c_long = 324; pub const SYS_fchownat: ::c_long = 325; pub const SYS_futimesat: ::c_long = 326; pub const SYS_fstatat64: ::c_long = 327; pub const SYS_unlinkat: ::c_long = 328; pub const SYS_renameat: ::c_long = 329; pub const SYS_linkat: ::c_long = 330; pub const SYS_symlinkat: ::c_long = 331; pub const SYS_readlinkat: ::c_long = 332; pub const SYS_fchmodat: ::c_long = 333; pub const SYS_faccessat: ::c_long = 334; pub const SYS_pselect6: ::c_long = 335; pub const SYS_ppoll: ::c_long = 336; pub const SYS_unshare: ::c_long = 337; pub const SYS_set_robust_list: ::c_long = 338; pub const SYS_get_robust_list: ::c_long = 339; pub const SYS_splice: ::c_long = 340; pub const SYS_arm_sync_file_range: ::c_long = 341; pub const SYS_tee: ::c_long = 342; pub const SYS_vmsplice: ::c_long = 343; pub const SYS_move_pages: ::c_long = 344; pub const SYS_getcpu: ::c_long = 345; pub const SYS_epoll_pwait: ::c_long = 346; pub const SYS_kexec_load: ::c_long = 347; pub const SYS_utimensat: ::c_long = 348; pub const SYS_signalfd: ::c_long = 349; pub const SYS_timerfd_create: ::c_long = 350; pub const SYS_eventfd: ::c_long = 351; pub const SYS_fallocate: ::c_long = 352; pub const SYS_timerfd_settime: ::c_long = 353; pub const SYS_timerfd_gettime: ::c_long = 354; pub const SYS_signalfd4: ::c_long = 355; pub const SYS_eventfd2: ::c_long = 356; pub const SYS_epoll_create1: ::c_long = 357; pub const SYS_dup3: ::c_long = 358; pub const SYS_pipe2: ::c_long = 359; pub const SYS_inotify_init1: ::c_long = 360; pub const SYS_preadv: ::c_long = 361; pub const SYS_pwritev: ::c_long = 362; pub const SYS_rt_tgsigqueueinfo: ::c_long = 363; pub const SYS_perf_event_open: ::c_long = 364; pub const SYS_recvmmsg: ::c_long = 365; pub const SYS_accept4: ::c_long = 366; pub const SYS_fanotify_init: ::c_long = 367; pub const SYS_fanotify_mark: ::c_long = 368; pub const SYS_prlimit64: ::c_long = 369; pub const SYS_name_to_handle_at: ::c_long = 370; pub const SYS_open_by_handle_at: ::c_long = 371; pub const SYS_clock_adjtime: ::c_long = 372; pub const SYS_syncfs: ::c_long = 373; pub const SYS_sendmmsg: ::c_long = 374; pub const SYS_setns: ::c_long = 375; pub const SYS_process_vm_readv: ::c_long = 376; pub const SYS_process_vm_writev: ::c_long = 377; pub const SYS_kcmp: ::c_long = 378; pub const SYS_finit_module: ::c_long = 379; pub const SYS_sched_setattr: ::c_long = 380; pub const SYS_sched_getattr: ::c_long = 381; pub const SYS_renameat2: ::c_long = 382; pub const SYS_seccomp: ::c_long = 383; pub const SYS_getrandom: ::c_long = 384; pub const SYS_memfd_create: ::c_long = 385; pub const SYS_bpf: ::c_long = 386; pub const SYS_execveat: ::c_long = 387; pub const SYS_userfaultfd: ::c_long = 388; pub const SYS_membarrier: ::c_long = 389; pub const SYS_mlock2: ::c_long = 390; pub const SYS_copy_file_range: ::c_long = 391; pub const SYS_preadv2: ::c_long = 392; pub const SYS_pwritev2: ::c_long = 393; pub const SYS_pkey_mprotect: ::c_long = 394; pub const SYS_pkey_alloc: ::c_long = 395; pub const SYS_pkey_free: ::c_long = 396; pub const SYS_statx: ::c_long = 397; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_R0: ::c_int = 0; pub const REG_R1: ::c_int = 1; pub const REG_R2: ::c_int = 2; pub const REG_R3: ::c_int = 3; pub const REG_R4: ::c_int = 4; pub const REG_R5: ::c_int = 5; pub const REG_R6: ::c_int = 6; pub const REG_R7: ::c_int = 7; pub const REG_R8: ::c_int = 8; pub const REG_R9: ::c_int = 9; pub const REG_R10: ::c_int = 10; pub const REG_R11: ::c_int = 11; pub const REG_R12: ::c_int = 12; pub const REG_R13: ::c_int = 13; pub const REG_R14: ::c_int = 14; pub const REG_R15: ::c_int = 15; pub const NGREG: ::c_int = 18; f! { // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not // exposed by the libc. As work-around, we implement it through `syscall` // directly. This workaround can be removed if the minimum version of // Android is bumped. When the workaround is removed, `accept4` can be // moved back to `linux_like/mod.rs` pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int ) -> ::c_int { ::syscall(SYS_accept4, fd, addr, len, flg) as ::c_int } } libc/src/unix/linux_like/android/b32/mod.rs0000644000175000017500000001467014661133735021532 0ustar jamespagejamespage// The following definitions are correct for arm and i686, // but may be wrong for mips pub type c_long = i32; pub type c_ulong = u32; pub type mode_t = u16; pub type off64_t = ::c_longlong; pub type sigset_t = ::c_ulong; pub type socklen_t = i32; pub type time64_t = i64; pub type __u64 = ::c_ulonglong; s! { pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, pub sa_restorer: ::Option, } pub struct rlimit64 { pub rlim_cur: u64, pub rlim_max: u64, } pub struct stat { pub st_dev: ::c_ulonglong, __pad0: [::c_uchar; 4], __st_ino: ::ino_t, pub st_mode: ::c_uint, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulonglong, __pad3: [::c_uchar; 4], pub st_size: ::c_longlong, pub st_blksize: ::blksize_t, pub st_blocks: ::c_ulonglong, pub st_atime: ::c_long, pub st_atime_nsec: ::c_long, pub st_mtime: ::c_long, pub st_mtime_nsec: ::c_long, pub st_ctime: ::c_long, pub st_ctime_nsec: ::c_long, pub st_ino: ::c_ulonglong, } pub struct stat64 { pub st_dev: ::c_ulonglong, __pad0: [::c_uchar; 4], __st_ino: ::ino_t, pub st_mode: ::c_uint, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::c_ulonglong, __pad3: [::c_uchar; 4], pub st_size: ::c_longlong, pub st_blksize: ::blksize_t, pub st_blocks: ::c_ulonglong, pub st_atime: ::c_long, pub st_atime_nsec: ::c_long, pub st_mtime: ::c_long, pub st_mtime_nsec: ::c_long, pub st_ctime: ::c_long, pub st_ctime_nsec: ::c_long, pub st_ino: ::c_ulonglong, } pub struct statfs64 { pub f_type: u32, pub f_bsize: u32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::__fsid_t, pub f_namelen: u32, pub f_frsize: u32, pub f_flags: u32, pub f_spare: [u32; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::c_ulong, pub f_bfree: ::c_ulong, pub f_bavail: ::c_ulong, pub f_files: ::c_ulong, pub f_ffree: ::c_ulong, pub f_favail: ::c_ulong, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, } pub struct pthread_attr_t { pub flags: u32, pub stack_base: *mut ::c_void, pub stack_size: ::size_t, pub guard_size: ::size_t, pub sched_policy: i32, pub sched_priority: i32, } pub struct pthread_mutex_t { value: ::c_int } pub struct pthread_cond_t { value: ::c_int } pub struct pthread_rwlock_t { lock: pthread_mutex_t, cond: pthread_cond_t, numLocks: ::c_int, writerThreadId: ::c_int, pendingReaders: ::c_int, pendingWriters: ::c_int, attr: i32, __reserved: [::c_char; 12], } pub struct pthread_barrier_t { __private: [i32; 8], } pub struct pthread_spinlock_t { __private: [i32; 2], } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct statfs { pub f_type: u32, pub f_bsize: u32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::__fsid_t, pub f_namelen: u32, pub f_frsize: u32, pub f_flags: u32, pub f_spare: [u32; 4], } pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub _f: [::c_char; 8], } } s_no_extra_traits! { pub struct sigset64_t { __bits: [::c_ulong; 2] } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl ::fmt::Debug for sigset64_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigset64_t") .field("__bits", &self.__bits) .finish() } } } } // These constants must be of the same type of sigaction.sa_flags pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const RTLD_GLOBAL: ::c_int = 2; pub const RTLD_NOW: ::c_int = 0; pub const RTLD_DEFAULT: *mut ::c_void = -1isize as *mut ::c_void; pub const PTRACE_GETFPREGS: ::c_int = 14; pub const PTRACE_SETFPREGS: ::c_int = 15; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { value: 0 }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { value: 0 }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { lock: PTHREAD_MUTEX_INITIALIZER, cond: PTHREAD_COND_INITIALIZER, numLocks: 0, writerThreadId: 0, pendingReaders: 0, pendingWriters: 0, attr: 0, __reserved: [0; 12], }; pub const PTHREAD_STACK_MIN: ::size_t = 4096 * 2; pub const CPU_SETSIZE: ::size_t = 32; pub const __CPU_BITS: ::size_t = 32; pub const UT_LINESIZE: usize = 8; pub const UT_NAMESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 16; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; extern "C" { pub fn timegm64(tm: *const ::tm) -> ::time64_t; } cfg_if! { if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/android/b32/x86/0000775000175000017500000000000014661133735021024 5ustar jamespagejamespagelibc/src/unix/linux_like/android/b32/x86/mod.rs0000644000175000017500000005722114661133735022156 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type greg_t = i32; s! { pub struct _libc_fpreg { pub significand: [u16; 4], pub exponent: u16, } pub struct _libc_fpstate { pub cw: ::c_ulong, pub sw: ::c_ulong, pub tag: ::c_ulong, pub ipoff: ::c_ulong, pub cssel: ::c_ulong, pub dataoff: ::c_ulong, pub datasel: ::c_ulong, pub _st: [_libc_fpreg; 8], pub status: ::c_ulong, } pub struct mcontext_t { pub gregs: [greg_t; 19], pub fpregs: *mut _libc_fpstate, pub oldmask: ::c_ulong, pub cr2: ::c_ulong, } } cfg_if! { if #[cfg(libc_union)] { s_no_extra_traits! { pub struct __c_anonymous_uc_sigmask_with_padding { pub uc_sigmask: ::sigset_t, /* Android has a wrong (smaller) sigset_t on x86. */ __padding_rt_sigset: u32, } pub union __c_anonymous_uc_sigmask { uc_sigmask: __c_anonymous_uc_sigmask_with_padding, uc_sigmask64: ::sigset64_t, } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask__c_anonymous_union: __c_anonymous_uc_sigmask, __padding_rt_sigset: u32, __fpregs_mem: _libc_fpstate, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous_uc_sigmask_with_padding { fn eq( &self, other: &__c_anonymous_uc_sigmask_with_padding ) -> bool { self.uc_sigmask == other.uc_sigmask // Ignore padding } } impl Eq for __c_anonymous_uc_sigmask_with_padding {} impl ::fmt::Debug for __c_anonymous_uc_sigmask_with_padding { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uc_sigmask_with_padding") .field("uc_sigmask_with_padding", &self.uc_sigmask) // Ignore padding .finish() } } impl ::hash::Hash for __c_anonymous_uc_sigmask_with_padding { fn hash(&self, state: &mut H) { self.uc_sigmask.hash(state) // Ignore padding } } impl PartialEq for __c_anonymous_uc_sigmask { fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool { unsafe { self.uc_sigmask == other.uc_sigmask } } } impl Eq for __c_anonymous_uc_sigmask {} impl ::fmt::Debug for __c_anonymous_uc_sigmask { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uc_sigmask") .field("uc_sigmask", unsafe { &self.uc_sigmask }) .finish() } } impl ::hash::Hash for __c_anonymous_uc_sigmask { fn hash(&self, state: &mut H) { unsafe { self.uc_sigmask.hash(state) } } } impl PartialEq for ucontext_t { fn eq(&self, other: &Self) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask__c_anonymous_union == other.uc_sigmask__c_anonymous_union // Ignore padding field } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field( "uc_sigmask__c_anonymous_union", &self.uc_sigmask__c_anonymous_union ) // Ignore padding field .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask__c_anonymous_union.hash(state); // Ignore padding field } } } } } } pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_LARGEFILE: ::c_int = 0o0100000; pub const MAP_32BIT: ::c_int = 0x40; // Syscall table pub const SYS_restart_syscall: ::c_long = 0; pub const SYS_exit: ::c_long = 1; pub const SYS_fork: ::c_long = 2; pub const SYS_read: ::c_long = 3; pub const SYS_write: ::c_long = 4; pub const SYS_open: ::c_long = 5; pub const SYS_close: ::c_long = 6; pub const SYS_waitpid: ::c_long = 7; pub const SYS_creat: ::c_long = 8; pub const SYS_link: ::c_long = 9; pub const SYS_unlink: ::c_long = 10; pub const SYS_execve: ::c_long = 11; pub const SYS_chdir: ::c_long = 12; pub const SYS_time: ::c_long = 13; pub const SYS_mknod: ::c_long = 14; pub const SYS_chmod: ::c_long = 15; pub const SYS_lchown: ::c_long = 16; pub const SYS_break: ::c_long = 17; pub const SYS_oldstat: ::c_long = 18; pub const SYS_lseek: ::c_long = 19; pub const SYS_getpid: ::c_long = 20; pub const SYS_mount: ::c_long = 21; pub const SYS_umount: ::c_long = 22; pub const SYS_setuid: ::c_long = 23; pub const SYS_getuid: ::c_long = 24; pub const SYS_stime: ::c_long = 25; pub const SYS_ptrace: ::c_long = 26; pub const SYS_alarm: ::c_long = 27; pub const SYS_oldfstat: ::c_long = 28; pub const SYS_pause: ::c_long = 29; pub const SYS_utime: ::c_long = 30; pub const SYS_stty: ::c_long = 31; pub const SYS_gtty: ::c_long = 32; pub const SYS_access: ::c_long = 33; pub const SYS_nice: ::c_long = 34; pub const SYS_ftime: ::c_long = 35; pub const SYS_sync: ::c_long = 36; pub const SYS_kill: ::c_long = 37; pub const SYS_rename: ::c_long = 38; pub const SYS_mkdir: ::c_long = 39; pub const SYS_rmdir: ::c_long = 40; pub const SYS_dup: ::c_long = 41; pub const SYS_pipe: ::c_long = 42; pub const SYS_times: ::c_long = 43; pub const SYS_prof: ::c_long = 44; pub const SYS_brk: ::c_long = 45; pub const SYS_setgid: ::c_long = 46; pub const SYS_getgid: ::c_long = 47; pub const SYS_signal: ::c_long = 48; pub const SYS_geteuid: ::c_long = 49; pub const SYS_getegid: ::c_long = 50; pub const SYS_acct: ::c_long = 51; pub const SYS_umount2: ::c_long = 52; pub const SYS_lock: ::c_long = 53; pub const SYS_ioctl: ::c_long = 54; pub const SYS_fcntl: ::c_long = 55; pub const SYS_mpx: ::c_long = 56; pub const SYS_setpgid: ::c_long = 57; pub const SYS_ulimit: ::c_long = 58; pub const SYS_oldolduname: ::c_long = 59; pub const SYS_umask: ::c_long = 60; pub const SYS_chroot: ::c_long = 61; pub const SYS_ustat: ::c_long = 62; pub const SYS_dup2: ::c_long = 63; pub const SYS_getppid: ::c_long = 64; pub const SYS_getpgrp: ::c_long = 65; pub const SYS_setsid: ::c_long = 66; pub const SYS_sigaction: ::c_long = 67; pub const SYS_sgetmask: ::c_long = 68; pub const SYS_ssetmask: ::c_long = 69; pub const SYS_setreuid: ::c_long = 70; pub const SYS_setregid: ::c_long = 71; pub const SYS_sigsuspend: ::c_long = 72; pub const SYS_sigpending: ::c_long = 73; pub const SYS_sethostname: ::c_long = 74; pub const SYS_setrlimit: ::c_long = 75; pub const SYS_getrlimit: ::c_long = 76; pub const SYS_getrusage: ::c_long = 77; pub const SYS_gettimeofday: ::c_long = 78; pub const SYS_settimeofday: ::c_long = 79; pub const SYS_getgroups: ::c_long = 80; pub const SYS_setgroups: ::c_long = 81; pub const SYS_select: ::c_long = 82; pub const SYS_symlink: ::c_long = 83; pub const SYS_oldlstat: ::c_long = 84; pub const SYS_readlink: ::c_long = 85; pub const SYS_uselib: ::c_long = 86; pub const SYS_swapon: ::c_long = 87; pub const SYS_reboot: ::c_long = 88; pub const SYS_readdir: ::c_long = 89; pub const SYS_mmap: ::c_long = 90; pub const SYS_munmap: ::c_long = 91; pub const SYS_truncate: ::c_long = 92; pub const SYS_ftruncate: ::c_long = 93; pub const SYS_fchmod: ::c_long = 94; pub const SYS_fchown: ::c_long = 95; pub const SYS_getpriority: ::c_long = 96; pub const SYS_setpriority: ::c_long = 97; pub const SYS_profil: ::c_long = 98; pub const SYS_statfs: ::c_long = 99; pub const SYS_fstatfs: ::c_long = 100; pub const SYS_ioperm: ::c_long = 101; pub const SYS_socketcall: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_setitimer: ::c_long = 104; pub const SYS_getitimer: ::c_long = 105; pub const SYS_stat: ::c_long = 106; pub const SYS_lstat: ::c_long = 107; pub const SYS_fstat: ::c_long = 108; pub const SYS_olduname: ::c_long = 109; pub const SYS_iopl: ::c_long = 110; pub const SYS_vhangup: ::c_long = 111; pub const SYS_idle: ::c_long = 112; pub const SYS_vm86old: ::c_long = 113; pub const SYS_wait4: ::c_long = 114; pub const SYS_swapoff: ::c_long = 115; pub const SYS_sysinfo: ::c_long = 116; pub const SYS_ipc: ::c_long = 117; pub const SYS_fsync: ::c_long = 118; pub const SYS_sigreturn: ::c_long = 119; pub const SYS_clone: ::c_long = 120; pub const SYS_setdomainname: ::c_long = 121; pub const SYS_uname: ::c_long = 122; pub const SYS_modify_ldt: ::c_long = 123; pub const SYS_adjtimex: ::c_long = 124; pub const SYS_mprotect: ::c_long = 125; pub const SYS_sigprocmask: ::c_long = 126; pub const SYS_create_module: ::c_long = 127; pub const SYS_init_module: ::c_long = 128; pub const SYS_delete_module: ::c_long = 129; pub const SYS_get_kernel_syms: ::c_long = 130; pub const SYS_quotactl: ::c_long = 131; pub const SYS_getpgid: ::c_long = 132; pub const SYS_fchdir: ::c_long = 133; pub const SYS_bdflush: ::c_long = 134; pub const SYS_sysfs: ::c_long = 135; pub const SYS_personality: ::c_long = 136; pub const SYS_afs_syscall: ::c_long = 137; pub const SYS_setfsuid: ::c_long = 138; pub const SYS_setfsgid: ::c_long = 139; // FIXME: SYS__llseek is in the NDK sources but for some reason is // not available in the tests // pub const SYS__llseek: ::c_long = 140; pub const SYS_getdents: ::c_long = 141; // FIXME: SYS__newselect is in the NDK sources but for some reason is // not available in the tests // pub const SYS__newselect: ::c_long = 142; pub const SYS_flock: ::c_long = 143; pub const SYS_msync: ::c_long = 144; pub const SYS_readv: ::c_long = 145; pub const SYS_writev: ::c_long = 146; pub const SYS_getsid: ::c_long = 147; pub const SYS_fdatasync: ::c_long = 148; // FIXME: SYS__llseek is in the NDK sources but for some reason is // not available in the tests // pub const SYS__sysctl: ::c_long = 149; pub const SYS_mlock: ::c_long = 150; pub const SYS_munlock: ::c_long = 151; pub const SYS_mlockall: ::c_long = 152; pub const SYS_munlockall: ::c_long = 153; pub const SYS_sched_setparam: ::c_long = 154; pub const SYS_sched_getparam: ::c_long = 155; pub const SYS_sched_setscheduler: ::c_long = 156; pub const SYS_sched_getscheduler: ::c_long = 157; pub const SYS_sched_yield: ::c_long = 158; pub const SYS_sched_get_priority_max: ::c_long = 159; pub const SYS_sched_get_priority_min: ::c_long = 160; pub const SYS_sched_rr_get_interval: ::c_long = 161; pub const SYS_nanosleep: ::c_long = 162; pub const SYS_mremap: ::c_long = 163; pub const SYS_setresuid: ::c_long = 164; pub const SYS_getresuid: ::c_long = 165; pub const SYS_vm86: ::c_long = 166; pub const SYS_query_module: ::c_long = 167; pub const SYS_poll: ::c_long = 168; pub const SYS_nfsservctl: ::c_long = 169; pub const SYS_setresgid: ::c_long = 170; pub const SYS_getresgid: ::c_long = 171; pub const SYS_prctl: ::c_long = 172; pub const SYS_rt_sigreturn: ::c_long = 173; pub const SYS_rt_sigaction: ::c_long = 174; pub const SYS_rt_sigprocmask: ::c_long = 175; pub const SYS_rt_sigpending: ::c_long = 176; pub const SYS_rt_sigtimedwait: ::c_long = 177; pub const SYS_rt_sigqueueinfo: ::c_long = 178; pub const SYS_rt_sigsuspend: ::c_long = 179; pub const SYS_pread64: ::c_long = 180; pub const SYS_pwrite64: ::c_long = 181; pub const SYS_chown: ::c_long = 182; pub const SYS_getcwd: ::c_long = 183; pub const SYS_capget: ::c_long = 184; pub const SYS_capset: ::c_long = 185; pub const SYS_sigaltstack: ::c_long = 186; pub const SYS_sendfile: ::c_long = 187; pub const SYS_getpmsg: ::c_long = 188; pub const SYS_putpmsg: ::c_long = 189; pub const SYS_vfork: ::c_long = 190; pub const SYS_ugetrlimit: ::c_long = 191; pub const SYS_mmap2: ::c_long = 192; pub const SYS_truncate64: ::c_long = 193; pub const SYS_ftruncate64: ::c_long = 194; pub const SYS_stat64: ::c_long = 195; pub const SYS_lstat64: ::c_long = 196; pub const SYS_fstat64: ::c_long = 197; pub const SYS_lchown32: ::c_long = 198; pub const SYS_getuid32: ::c_long = 199; pub const SYS_getgid32: ::c_long = 200; pub const SYS_geteuid32: ::c_long = 201; pub const SYS_getegid32: ::c_long = 202; pub const SYS_setreuid32: ::c_long = 203; pub const SYS_setregid32: ::c_long = 204; pub const SYS_getgroups32: ::c_long = 205; pub const SYS_setgroups32: ::c_long = 206; pub const SYS_fchown32: ::c_long = 207; pub const SYS_setresuid32: ::c_long = 208; pub const SYS_getresuid32: ::c_long = 209; pub const SYS_setresgid32: ::c_long = 210; pub const SYS_getresgid32: ::c_long = 211; pub const SYS_chown32: ::c_long = 212; pub const SYS_setuid32: ::c_long = 213; pub const SYS_setgid32: ::c_long = 214; pub const SYS_setfsuid32: ::c_long = 215; pub const SYS_setfsgid32: ::c_long = 216; pub const SYS_pivot_root: ::c_long = 217; pub const SYS_mincore: ::c_long = 218; pub const SYS_madvise: ::c_long = 219; pub const SYS_getdents64: ::c_long = 220; pub const SYS_fcntl64: ::c_long = 221; pub const SYS_gettid: ::c_long = 224; pub const SYS_readahead: ::c_long = 225; pub const SYS_setxattr: ::c_long = 226; pub const SYS_lsetxattr: ::c_long = 227; pub const SYS_fsetxattr: ::c_long = 228; pub const SYS_getxattr: ::c_long = 229; pub const SYS_lgetxattr: ::c_long = 230; pub const SYS_fgetxattr: ::c_long = 231; pub const SYS_listxattr: ::c_long = 232; pub const SYS_llistxattr: ::c_long = 233; pub const SYS_flistxattr: ::c_long = 234; pub const SYS_removexattr: ::c_long = 235; pub const SYS_lremovexattr: ::c_long = 236; pub const SYS_fremovexattr: ::c_long = 237; pub const SYS_tkill: ::c_long = 238; pub const SYS_sendfile64: ::c_long = 239; pub const SYS_futex: ::c_long = 240; pub const SYS_sched_setaffinity: ::c_long = 241; pub const SYS_sched_getaffinity: ::c_long = 242; pub const SYS_set_thread_area: ::c_long = 243; pub const SYS_get_thread_area: ::c_long = 244; pub const SYS_io_setup: ::c_long = 245; pub const SYS_io_destroy: ::c_long = 246; pub const SYS_io_getevents: ::c_long = 247; pub const SYS_io_submit: ::c_long = 248; pub const SYS_io_cancel: ::c_long = 249; pub const SYS_fadvise64: ::c_long = 250; pub const SYS_exit_group: ::c_long = 252; pub const SYS_lookup_dcookie: ::c_long = 253; pub const SYS_epoll_create: ::c_long = 254; pub const SYS_epoll_ctl: ::c_long = 255; pub const SYS_epoll_wait: ::c_long = 256; pub const SYS_remap_file_pages: ::c_long = 257; pub const SYS_set_tid_address: ::c_long = 258; pub const SYS_timer_create: ::c_long = 259; pub const SYS_timer_settime: ::c_long = 260; pub const SYS_timer_gettime: ::c_long = 261; pub const SYS_timer_getoverrun: ::c_long = 262; pub const SYS_timer_delete: ::c_long = 263; pub const SYS_clock_settime: ::c_long = 264; pub const SYS_clock_gettime: ::c_long = 265; pub const SYS_clock_getres: ::c_long = 266; pub const SYS_clock_nanosleep: ::c_long = 267; pub const SYS_statfs64: ::c_long = 268; pub const SYS_fstatfs64: ::c_long = 269; pub const SYS_tgkill: ::c_long = 270; pub const SYS_utimes: ::c_long = 271; pub const SYS_fadvise64_64: ::c_long = 272; pub const SYS_vserver: ::c_long = 273; pub const SYS_mbind: ::c_long = 274; pub const SYS_get_mempolicy: ::c_long = 275; pub const SYS_set_mempolicy: ::c_long = 276; pub const SYS_mq_open: ::c_long = 277; pub const SYS_mq_unlink: ::c_long = 278; pub const SYS_mq_timedsend: ::c_long = 279; pub const SYS_mq_timedreceive: ::c_long = 280; pub const SYS_mq_notify: ::c_long = 281; pub const SYS_mq_getsetattr: ::c_long = 282; pub const SYS_kexec_load: ::c_long = 283; pub const SYS_waitid: ::c_long = 284; pub const SYS_add_key: ::c_long = 286; pub const SYS_request_key: ::c_long = 287; pub const SYS_keyctl: ::c_long = 288; pub const SYS_ioprio_set: ::c_long = 289; pub const SYS_ioprio_get: ::c_long = 290; pub const SYS_inotify_init: ::c_long = 291; pub const SYS_inotify_add_watch: ::c_long = 292; pub const SYS_inotify_rm_watch: ::c_long = 293; pub const SYS_migrate_pages: ::c_long = 294; pub const SYS_openat: ::c_long = 295; pub const SYS_mkdirat: ::c_long = 296; pub const SYS_mknodat: ::c_long = 297; pub const SYS_fchownat: ::c_long = 298; pub const SYS_futimesat: ::c_long = 299; pub const SYS_fstatat64: ::c_long = 300; pub const SYS_unlinkat: ::c_long = 301; pub const SYS_renameat: ::c_long = 302; pub const SYS_linkat: ::c_long = 303; pub const SYS_symlinkat: ::c_long = 304; pub const SYS_readlinkat: ::c_long = 305; pub const SYS_fchmodat: ::c_long = 306; pub const SYS_faccessat: ::c_long = 307; pub const SYS_pselect6: ::c_long = 308; pub const SYS_ppoll: ::c_long = 309; pub const SYS_unshare: ::c_long = 310; pub const SYS_set_robust_list: ::c_long = 311; pub const SYS_get_robust_list: ::c_long = 312; pub const SYS_splice: ::c_long = 313; pub const SYS_sync_file_range: ::c_long = 314; pub const SYS_tee: ::c_long = 315; pub const SYS_vmsplice: ::c_long = 316; pub const SYS_move_pages: ::c_long = 317; pub const SYS_getcpu: ::c_long = 318; pub const SYS_epoll_pwait: ::c_long = 319; pub const SYS_utimensat: ::c_long = 320; pub const SYS_signalfd: ::c_long = 321; pub const SYS_timerfd_create: ::c_long = 322; pub const SYS_eventfd: ::c_long = 323; pub const SYS_fallocate: ::c_long = 324; pub const SYS_timerfd_settime: ::c_long = 325; pub const SYS_timerfd_gettime: ::c_long = 326; pub const SYS_signalfd4: ::c_long = 327; pub const SYS_eventfd2: ::c_long = 328; pub const SYS_epoll_create1: ::c_long = 329; pub const SYS_dup3: ::c_long = 330; pub const SYS_pipe2: ::c_long = 331; pub const SYS_inotify_init1: ::c_long = 332; pub const SYS_preadv: ::c_long = 333; pub const SYS_pwritev: ::c_long = 334; pub const SYS_rt_tgsigqueueinfo: ::c_long = 335; pub const SYS_perf_event_open: ::c_long = 336; pub const SYS_recvmmsg: ::c_long = 337; pub const SYS_fanotify_init: ::c_long = 338; pub const SYS_fanotify_mark: ::c_long = 339; pub const SYS_prlimit64: ::c_long = 340; pub const SYS_name_to_handle_at: ::c_long = 341; pub const SYS_open_by_handle_at: ::c_long = 342; pub const SYS_clock_adjtime: ::c_long = 343; pub const SYS_syncfs: ::c_long = 344; pub const SYS_sendmmsg: ::c_long = 345; pub const SYS_setns: ::c_long = 346; pub const SYS_process_vm_readv: ::c_long = 347; pub const SYS_process_vm_writev: ::c_long = 348; pub const SYS_kcmp: ::c_long = 349; pub const SYS_finit_module: ::c_long = 350; pub const SYS_sched_setattr: ::c_long = 351; pub const SYS_sched_getattr: ::c_long = 352; pub const SYS_renameat2: ::c_long = 353; pub const SYS_seccomp: ::c_long = 354; pub const SYS_getrandom: ::c_long = 355; pub const SYS_memfd_create: ::c_long = 356; pub const SYS_bpf: ::c_long = 357; pub const SYS_execveat: ::c_long = 358; pub const SYS_socket: ::c_long = 359; pub const SYS_socketpair: ::c_long = 360; pub const SYS_bind: ::c_long = 361; pub const SYS_connect: ::c_long = 362; pub const SYS_listen: ::c_long = 363; pub const SYS_accept4: ::c_long = 364; pub const SYS_getsockopt: ::c_long = 365; pub const SYS_setsockopt: ::c_long = 366; pub const SYS_getsockname: ::c_long = 367; pub const SYS_getpeername: ::c_long = 368; pub const SYS_sendto: ::c_long = 369; pub const SYS_sendmsg: ::c_long = 370; pub const SYS_recvfrom: ::c_long = 371; pub const SYS_recvmsg: ::c_long = 372; pub const SYS_shutdown: ::c_long = 373; pub const SYS_userfaultfd: ::c_long = 374; pub const SYS_membarrier: ::c_long = 375; pub const SYS_mlock2: ::c_long = 376; pub const SYS_copy_file_range: ::c_long = 377; pub const SYS_preadv2: ::c_long = 378; pub const SYS_pwritev2: ::c_long = 379; pub const SYS_pkey_mprotect: ::c_long = 380; pub const SYS_pkey_alloc: ::c_long = 381; pub const SYS_pkey_free: ::c_long = 382; pub const SYS_statx: ::c_long = 383; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; // offsets in user_regs_structs, from sys/reg.h pub const EBX: ::c_int = 0; pub const ECX: ::c_int = 1; pub const EDX: ::c_int = 2; pub const ESI: ::c_int = 3; pub const EDI: ::c_int = 4; pub const EBP: ::c_int = 5; pub const EAX: ::c_int = 6; pub const DS: ::c_int = 7; pub const ES: ::c_int = 8; pub const FS: ::c_int = 9; pub const GS: ::c_int = 10; pub const ORIG_EAX: ::c_int = 11; pub const EIP: ::c_int = 12; pub const CS: ::c_int = 13; pub const EFL: ::c_int = 14; pub const UESP: ::c_int = 15; pub const SS: ::c_int = 16; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_GS: ::c_int = 0; pub const REG_FS: ::c_int = 1; pub const REG_ES: ::c_int = 2; pub const REG_DS: ::c_int = 3; pub const REG_EDI: ::c_int = 4; pub const REG_ESI: ::c_int = 5; pub const REG_EBP: ::c_int = 6; pub const REG_ESP: ::c_int = 7; pub const REG_EBX: ::c_int = 8; pub const REG_EDX: ::c_int = 9; pub const REG_ECX: ::c_int = 10; pub const REG_EAX: ::c_int = 11; pub const REG_TRAPNO: ::c_int = 12; pub const REG_ERR: ::c_int = 13; pub const REG_EIP: ::c_int = 14; pub const REG_CS: ::c_int = 15; pub const REG_EFL: ::c_int = 16; pub const REG_UESP: ::c_int = 17; pub const REG_SS: ::c_int = 18; // socketcall values from linux/net.h (only the needed ones, and not public) const SYS_ACCEPT4: ::c_int = 18; f! { // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not // exposed by the libc. As work-around, we implement it as raw syscall. // Note that for x86, the `accept4` syscall is not available either, // and we must use the `socketcall` syscall instead. // This workaround can be removed if the minimum Android version is bumped. // When the workaround is removed, `accept4` can be moved back // to `linux_like/mod.rs` pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int ) -> ::c_int { // Arguments are passed as array of `long int` // (which is big enough on x86 for a pointer). let mut args = [ fd as ::c_long, addr as ::c_long, len as ::c_long, flg as ::c_long, ]; ::syscall(SYS_socketcall, SYS_ACCEPT4, args[..].as_mut_ptr()) } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/android/b32/x86/align.rs0000644000175000017500000000022414661133735022460 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(8))] pub struct max_align_t { priv_: [f64; 2] } } libc/src/unix/linux_like/android/mod.rs0000644000175000017500000044060514661133735021145 0ustar jamespagejamespage//! Android-specific definitions for linux-like values pub type clock_t = ::c_long; pub type time_t = ::c_long; pub type suseconds_t = ::c_long; pub type off_t = ::c_long; pub type blkcnt_t = ::c_ulong; pub type blksize_t = ::c_ulong; pub type nlink_t = u32; pub type useconds_t = u32; pub type pthread_t = ::c_long; pub type pthread_mutexattr_t = ::c_long; pub type pthread_rwlockattr_t = ::c_long; pub type pthread_barrierattr_t = ::c_int; pub type pthread_condattr_t = ::c_long; pub type pthread_key_t = ::c_int; pub type fsfilcnt_t = ::c_ulong; pub type fsblkcnt_t = ::c_ulong; pub type nfds_t = ::c_uint; pub type rlim_t = ::c_ulong; pub type dev_t = ::c_ulong; pub type ino_t = ::c_ulong; pub type ino64_t = u64; pub type __CPU_BITTYPE = ::c_ulong; pub type idtype_t = ::c_int; pub type loff_t = ::c_longlong; pub type __kernel_loff_t = ::c_longlong; pub type __kernel_pid_t = ::c_int; pub type __u8 = ::c_uchar; pub type __u16 = ::c_ushort; pub type __s16 = ::c_short; pub type __u32 = ::c_uint; pub type __s32 = ::c_int; // linux/elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Off = u32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Off = u64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type eventfd_t = u64; // these structs sit behind a heap allocation on Android pub type posix_spawn_file_actions_t = *mut ::c_void; pub type posix_spawnattr_t = *mut ::c_void; s! { pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: ::size_t } pub struct __fsid_t { __val: [::c_int; 2], } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::size_t, pub msg_control: *mut ::c_void, pub msg_controllen: ::size_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::size_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], } pub struct termios2 { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; 19], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } pub struct mallinfo { pub arena: ::size_t, pub ordblks: ::size_t, pub smblks: ::size_t, pub hblks: ::size_t, pub hblkhd: ::size_t, pub usmblks: ::size_t, pub fsmblks: ::size_t, pub uordblks: ::size_t, pub fordblks: ::size_t, pub keepcost: ::size_t, } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct flock64 { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::__kernel_loff_t, pub l_len: ::__kernel_loff_t, pub l_pid: ::__kernel_pid_t, } pub struct cpu_set_t { #[cfg(target_pointer_width = "64")] __bits: [__CPU_BITTYPE; 16], #[cfg(target_pointer_width = "32")] __bits: [__CPU_BITTYPE; 1], } pub struct sem_t { count: ::c_uint, #[cfg(target_pointer_width = "64")] __reserved: [::c_int; 3], } pub struct exit_status { pub e_termination: ::c_short, pub e_exit: ::c_short, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, #[cfg(target_pointer_width = "64")] __f_reserved: [u32; 6], } pub struct signalfd_siginfo { pub ssi_signo: u32, pub ssi_errno: i32, pub ssi_code: i32, pub ssi_pid: u32, pub ssi_uid: u32, pub ssi_fd: i32, pub ssi_tid: u32, pub ssi_band: u32, pub ssi_overrun: u32, pub ssi_trapno: u32, pub ssi_status: i32, pub ssi_int: i32, pub ssi_ptr: ::c_ulonglong, pub ssi_utime: ::c_ulonglong, pub ssi_stime: ::c_ulonglong, pub ssi_addr: ::c_ulonglong, pub ssi_addr_lsb: u16, _pad2: u16, pub ssi_syscall: i32, pub ssi_call_addr: u64, pub ssi_arch: u32, _pad: [u8; 28], } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } pub struct ucred { pub pid: ::pid_t, pub uid: ::uid_t, pub gid: ::gid_t, } pub struct genlmsghdr { pub cmd: u8, pub version: u8, pub reserved: u16, } pub struct nlmsghdr { pub nlmsg_len: u32, pub nlmsg_type: u16, pub nlmsg_flags: u16, pub nlmsg_seq: u32, pub nlmsg_pid: u32, } pub struct nlmsgerr { pub error: ::c_int, pub msg: nlmsghdr, } pub struct nl_pktinfo { pub group: u32, } pub struct nl_mmap_req { pub nm_block_size: ::c_uint, pub nm_block_nr: ::c_uint, pub nm_frame_size: ::c_uint, pub nm_frame_nr: ::c_uint, } pub struct nl_mmap_hdr { pub nm_status: ::c_uint, pub nm_len: ::c_uint, pub nm_group: u32, pub nm_pid: u32, pub nm_uid: u32, pub nm_gid: u32, } pub struct nlattr { pub nla_len: u16, pub nla_type: u16, } pub struct in6_pktinfo { pub ipi6_addr: ::in6_addr, pub ipi6_ifindex: ::c_int, } pub struct inotify_event { pub wd: ::c_int, pub mask: u32, pub cookie: u32, pub len: u32 } pub struct sock_extended_err { pub ee_errno: u32, pub ee_origin: u8, pub ee_type: u8, pub ee_code: u8, pub ee_pad: u8, pub ee_info: u32, pub ee_data: u32, } pub struct regex_t { re_magic: ::c_int, re_nsub: ::size_t, re_endp: *const ::c_char, re_guts: *mut ::c_void, } pub struct regmatch_t { pub rm_so: ::ssize_t, pub rm_eo: ::ssize_t, } pub struct sockaddr_vm { pub svm_family: ::sa_family_t, pub svm_reserved1: ::c_ushort, pub svm_port: ::c_uint, pub svm_cid: ::c_uint, pub svm_zero: [u8; 4] } // linux/elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } // link.h pub struct dl_phdr_info { #[cfg(target_pointer_width = "64")] pub dlpi_addr: Elf64_Addr, #[cfg(target_pointer_width = "32")] pub dlpi_addr: Elf32_Addr, pub dlpi_name: *const ::c_char, #[cfg(target_pointer_width = "64")] pub dlpi_phdr: *const Elf64_Phdr, #[cfg(target_pointer_width = "32")] pub dlpi_phdr: *const Elf32_Phdr, #[cfg(target_pointer_width = "64")] pub dlpi_phnum: Elf64_Half, #[cfg(target_pointer_width = "32")] pub dlpi_phnum: Elf32_Half, // These fields were added in Android R pub dlpi_adds: ::c_ulonglong, pub dlpi_subs: ::c_ulonglong, pub dlpi_tls_modid: ::size_t, pub dlpi_tls_data: *mut ::c_void, } // linux/filter.h pub struct sock_filter { pub code: ::__u16, pub jt: ::__u8, pub jf: ::__u8, pub k: ::__u32, } pub struct sock_fprog { pub len: ::c_ushort, pub filter: *mut sock_filter, } // linux/seccomp.h pub struct seccomp_data { pub nr: ::c_int, pub arch: ::__u32, pub instruction_pointer: ::__u64, pub args: [::__u64; 6], } pub struct seccomp_metadata { pub filter_off: ::__u64, pub flags: ::__u64, } pub struct ptrace_peeksiginfo_args { pub off: ::__u64, pub flags: ::__u32, pub nr: ::__s32, } // linux/input.h pub struct input_event { pub time: ::timeval, pub type_: ::__u16, pub code: ::__u16, pub value: ::__s32, } pub struct input_id { pub bustype: ::__u16, pub vendor: ::__u16, pub product: ::__u16, pub version: ::__u16, } pub struct input_absinfo { pub value: ::__s32, pub minimum: ::__s32, pub maximum: ::__s32, pub fuzz: ::__s32, pub flat: ::__s32, pub resolution: ::__s32, } pub struct input_keymap_entry { pub flags: ::__u8, pub len: ::__u8, pub index: ::__u16, pub keycode: ::__u32, pub scancode: [::__u8; 32], } pub struct input_mask { pub type_: ::__u32, pub codes_size: ::__u32, pub codes_ptr: ::__u64, } pub struct ff_replay { pub length: ::__u16, pub delay: ::__u16, } pub struct ff_trigger { pub button: ::__u16, pub interval: ::__u16, } pub struct ff_envelope { pub attack_length: ::__u16, pub attack_level: ::__u16, pub fade_length: ::__u16, pub fade_level: ::__u16, } pub struct ff_constant_effect { pub level: ::__s16, pub envelope: ff_envelope, } pub struct ff_ramp_effect { pub start_level: ::__s16, pub end_level: ::__s16, pub envelope: ff_envelope, } pub struct ff_condition_effect { pub right_saturation: ::__u16, pub left_saturation: ::__u16, pub right_coeff: ::__s16, pub left_coeff: ::__s16, pub deadband: ::__u16, pub center: ::__s16, } pub struct ff_periodic_effect { pub waveform: ::__u16, pub period: ::__u16, pub magnitude: ::__s16, pub offset: ::__s16, pub phase: ::__u16, pub envelope: ff_envelope, pub custom_len: ::__u32, pub custom_data: *mut ::__s16, } pub struct ff_rumble_effect { pub strong_magnitude: ::__u16, pub weak_magnitude: ::__u16, } pub struct ff_effect { pub type_: ::__u16, pub id: ::__s16, pub direction: ::__u16, pub trigger: ff_trigger, pub replay: ff_replay, // FIXME this is actually a union #[cfg(target_pointer_width = "64")] pub u: [u64; 4], #[cfg(target_pointer_width = "32")] pub u: [u32; 7], } // linux/uinput.h pub struct uinput_ff_upload { pub request_id: ::__u32, pub retval: ::__s32, pub effect: ff_effect, pub old: ff_effect, } pub struct uinput_ff_erase { pub request_id: ::__u32, pub retval: ::__s32, pub effect_id: ::__u32, } pub struct uinput_abs_setup { pub code: ::__u16, pub absinfo: input_absinfo, } pub struct option { pub name: *const ::c_char, pub has_arg: ::c_int, pub flag: *mut ::c_int, pub val: ::c_int, } pub struct __c_anonymous_ifru_map { pub mem_start: ::c_ulong, pub mem_end: ::c_ulong, pub base_addr: ::c_ushort, pub irq: ::c_uchar, pub dma: ::c_uchar, pub port: ::c_uchar, } pub struct in6_ifreq { pub ifr6_addr: ::in6_addr, pub ifr6_prefixlen: u32, pub ifr6_ifindex: ::c_int, } } s_no_extra_traits! { pub struct sockaddr_nl { pub nl_family: ::sa_family_t, nl_pad: ::c_ushort, pub nl_pid: u32, pub nl_groups: u32 } pub struct dirent { pub d_ino: u64, pub d_off: i64, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } pub struct dirent64 { pub d_ino: u64, pub d_off: i64, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub _pad: [::c_int; 29], _align: [usize; 0], } pub struct lastlog { ll_time: ::time_t, ll_line: [::c_char; UT_LINESIZE], ll_host: [::c_char; UT_HOSTSIZE], } pub struct utmp { pub ut_type: ::c_short, pub ut_pid: ::pid_t, pub ut_line: [::c_char; UT_LINESIZE], pub ut_id: [::c_char; 4], pub ut_user: [::c_char; UT_NAMESIZE], pub ut_host: [::c_char; UT_HOSTSIZE], pub ut_exit: exit_status, pub ut_session: ::c_long, pub ut_tv: ::timeval, pub ut_addr_v6: [i32; 4], unused: [::c_char; 20], } pub struct sockaddr_alg { pub salg_family: ::sa_family_t, pub salg_type: [::c_uchar; 14], pub salg_feat: u32, pub salg_mask: u32, pub salg_name: [::c_uchar; 64], } pub struct uinput_setup { pub id: input_id, pub name: [::c_char; UINPUT_MAX_NAME_SIZE], pub ff_effects_max: ::__u32, } pub struct uinput_user_dev { pub name: [::c_char; UINPUT_MAX_NAME_SIZE], pub id: input_id, pub ff_effects_max: ::__u32, pub absmax: [::__s32; ABS_CNT], pub absmin: [::__s32; ABS_CNT], pub absfuzz: [::__s32; ABS_CNT], pub absflat: [::__s32; ABS_CNT], } /// WARNING: The `PartialEq`, `Eq` and `Hash` implementations of this /// type are unsound and will be removed in the future. #[deprecated( note = "this struct has unsafe trait implementations that will be \ removed in the future", since = "0.2.80" )] pub struct af_alg_iv { pub ivlen: u32, pub iv: [::c_uchar; 0], } pub struct prop_info { __name: [::c_char; 32], __serial: ::c_uint, __value: [[::c_char; 4]; 23], } #[cfg(libc_union)] pub union __c_anonymous_ifr_ifru { pub ifru_addr: ::sockaddr, pub ifru_dstaddr: ::sockaddr, pub ifru_broadaddr: ::sockaddr, pub ifru_netmask: ::sockaddr, pub ifru_hwaddr: ::sockaddr, pub ifru_flags: ::c_short, pub ifru_ifindex: ::c_int, pub ifru_metric: ::c_int, pub ifru_mtu: ::c_int, pub ifru_map: __c_anonymous_ifru_map, pub ifru_slave: [::c_char; ::IFNAMSIZ], pub ifru_newname: [::c_char; ::IFNAMSIZ], pub ifru_data: *mut ::c_char, } pub struct ifreq { /// interface name, e.g. "en0" pub ifr_name: [::c_char; ::IFNAMSIZ], #[cfg(libc_union)] pub ifr_ifru: __c_anonymous_ifr_ifru, #[cfg(not(libc_union))] pub ifr_ifru: ::sockaddr, } #[cfg(libc_union)] pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut ::c_char, pub ifcu_req: *mut ::ifreq, } /* Structure used in SIOCGIFCONF request. Used to retrieve interface configuration for machine (useful for programs which must know all networks accessible). */ pub struct ifconf { pub ifc_len: ::c_int, /* Size of buffer. */ #[cfg(libc_union)] pub ifc_ifcu: __c_anonymous_ifc_ifcu, #[cfg(not(libc_union))] pub ifc_ifcu: *mut ::ifreq, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_nl { fn eq(&self, other: &sockaddr_nl) -> bool { self.nl_family == other.nl_family && self.nl_pid == other.nl_pid && self.nl_groups == other.nl_groups } } impl Eq for sockaddr_nl {} impl ::fmt::Debug for sockaddr_nl { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_nl") .field("nl_family", &self.nl_family) .field("nl_pid", &self.nl_pid) .field("nl_groups", &self.nl_groups) .finish() } } impl ::hash::Hash for sockaddr_nl { fn hash(&self, state: &mut H) { self.nl_family.hash(state); self.nl_pid.hash(state); self.nl_groups.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for dirent64 { fn eq(&self, other: &dirent64) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent64 {} impl ::fmt::Debug for dirent64 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent64") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent64 { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { self.si_signo == other.si_signo && self.si_errno == other.si_errno && self.si_code == other.si_code // Ignore _pad // Ignore _align } } impl Eq for siginfo_t {} impl ::fmt::Debug for siginfo_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_errno", &self.si_errno) .field("si_code", &self.si_code) // Ignore _pad // Ignore _align .finish() } } impl ::hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_errno.hash(state); self.si_code.hash(state); // Ignore _pad // Ignore _align } } impl PartialEq for lastlog { fn eq(&self, other: &lastlog) -> bool { self.ll_time == other.ll_time && self .ll_line .iter() .zip(other.ll_line.iter()) .all(|(a,b)| a == b) && self .ll_host .iter() .zip(other.ll_host.iter()) .all(|(a,b)| a == b) } } impl Eq for lastlog {} impl ::fmt::Debug for lastlog { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("lastlog") .field("ll_time", &self.ll_time) .field("ll_line", &self.ll_line) // FIXME: .field("ll_host", &self.ll_host) .finish() } } impl ::hash::Hash for lastlog { fn hash(&self, state: &mut H) { self.ll_time.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); } } impl PartialEq for utmp { fn eq(&self, other: &utmp) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self .ut_line .iter() .zip(other.ut_line.iter()) .all(|(a,b)| a == b) && self.ut_id == other.ut_id && self .ut_user .iter() .zip(other.ut_user.iter()) .all(|(a,b)| a == b) && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.unused == other.unused } } impl Eq for utmp {} impl ::fmt::Debug for utmp { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmp") .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) // FIXME: .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("unused", &self.unused) .finish() } } impl ::hash::Hash for utmp { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.unused.hash(state); } } impl PartialEq for sockaddr_alg { fn eq(&self, other: &sockaddr_alg) -> bool { self.salg_family == other.salg_family && self .salg_type .iter() .zip(other.salg_type.iter()) .all(|(a, b)| a == b) && self.salg_feat == other.salg_feat && self.salg_mask == other.salg_mask && self .salg_name .iter() .zip(other.salg_name.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_alg {} impl ::fmt::Debug for sockaddr_alg { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_alg") .field("salg_family", &self.salg_family) .field("salg_type", &self.salg_type) .field("salg_feat", &self.salg_feat) .field("salg_mask", &self.salg_mask) .field("salg_name", &&self.salg_name[..]) .finish() } } impl ::hash::Hash for sockaddr_alg { fn hash(&self, state: &mut H) { self.salg_family.hash(state); self.salg_type.hash(state); self.salg_feat.hash(state); self.salg_mask.hash(state); self.salg_name.hash(state); } } impl PartialEq for uinput_setup { fn eq(&self, other: &uinput_setup) -> bool { self.id == other.id && self.name[..] == other.name[..] && self.ff_effects_max == other.ff_effects_max } } impl Eq for uinput_setup {} impl ::fmt::Debug for uinput_setup { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uinput_setup") .field("id", &self.id) .field("name", &&self.name[..]) .field("ff_effects_max", &self.ff_effects_max) .finish() } } impl ::hash::Hash for uinput_setup { fn hash(&self, state: &mut H) { self.id.hash(state); self.name.hash(state); self.ff_effects_max.hash(state); } } impl PartialEq for uinput_user_dev { fn eq(&self, other: &uinput_user_dev) -> bool { self.name[..] == other.name[..] && self.id == other.id && self.ff_effects_max == other.ff_effects_max && self.absmax[..] == other.absmax[..] && self.absmin[..] == other.absmin[..] && self.absfuzz[..] == other.absfuzz[..] && self.absflat[..] == other.absflat[..] } } impl Eq for uinput_user_dev {} impl ::fmt::Debug for uinput_user_dev { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uinput_setup") .field("name", &&self.name[..]) .field("id", &self.id) .field("ff_effects_max", &self.ff_effects_max) .field("absmax", &&self.absmax[..]) .field("absmin", &&self.absmin[..]) .field("absfuzz", &&self.absfuzz[..]) .field("absflat", &&self.absflat[..]) .finish() } } impl ::hash::Hash for uinput_user_dev { fn hash(&self, state: &mut H) { self.name.hash(state); self.id.hash(state); self.ff_effects_max.hash(state); self.absmax.hash(state); self.absmin.hash(state); self.absfuzz.hash(state); self.absflat.hash(state); } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifr_ifru { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifr_ifru") .field("ifru_addr", unsafe { &self.ifru_addr }) .field("ifru_dstaddr", unsafe { &self.ifru_dstaddr }) .field("ifru_broadaddr", unsafe { &self.ifru_broadaddr }) .field("ifru_netmask", unsafe { &self.ifru_netmask }) .field("ifru_hwaddr", unsafe { &self.ifru_hwaddr }) .field("ifru_flags", unsafe { &self.ifru_flags }) .field("ifru_ifindex", unsafe { &self.ifru_ifindex }) .field("ifru_metric", unsafe { &self.ifru_metric }) .field("ifru_mtu", unsafe { &self.ifru_mtu }) .field("ifru_map", unsafe { &self.ifru_map }) .field("ifru_slave", unsafe { &self.ifru_slave }) .field("ifru_newname", unsafe { &self.ifru_newname }) .field("ifru_data", unsafe { &self.ifru_data }) .finish() } } impl ::fmt::Debug for ifreq { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifc_ifcu { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifr_ifru") .field("ifcu_buf", unsafe { &self.ifcu_buf }) .field("ifcu_req", unsafe { &self.ifcu_req }) .finish() } } impl ::fmt::Debug for ifconf { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifconf") .field("ifc_len", &self.ifc_len) .field("ifc_ifcu", &self.ifc_ifcu) .finish() } } #[allow(deprecated)] impl af_alg_iv { fn as_slice(&self) -> &[u8] { unsafe { ::core::slice::from_raw_parts( self.iv.as_ptr(), self.ivlen as usize ) } } } #[allow(deprecated)] impl PartialEq for af_alg_iv { fn eq(&self, other: &af_alg_iv) -> bool { *self.as_slice() == *other.as_slice() } } #[allow(deprecated)] impl Eq for af_alg_iv {} #[allow(deprecated)] impl ::fmt::Debug for af_alg_iv { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("af_alg_iv") .field("ivlen", &self.ivlen) .finish() } } #[allow(deprecated)] impl ::hash::Hash for af_alg_iv { fn hash(&self, state: &mut H) { self.as_slice().hash(state); } } impl PartialEq for prop_info { fn eq(&self, other: &prop_info) -> bool { self.__name == other.__name && self.__serial == other.__serial && self.__value == other.__value } } impl Eq for prop_info {} impl ::fmt::Debug for prop_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("prop_info") .field("__name", &self.__name) .field("__serial", &self.__serial) .field("__value", &self.__value) .finish() } } } } pub const MADV_SOFT_OFFLINE: ::c_int = 101; pub const MS_NOUSER: ::c_ulong = 0xffffffff80000000; pub const MS_RMT_MASK: ::c_ulong = 0x02800051; pub const O_TRUNC: ::c_int = 512; pub const O_CLOEXEC: ::c_int = 0x80000; pub const O_PATH: ::c_int = 0o10000000; pub const O_NOATIME: ::c_int = 0o1000000; pub const EBFONT: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EDOTDOT: ::c_int = 73; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; // sys/eventfd.h pub const EFD_SEMAPHORE: ::c_int = 0x1; pub const EFD_CLOEXEC: ::c_int = O_CLOEXEC; pub const EFD_NONBLOCK: ::c_int = O_NONBLOCK; // sys/timerfd.h pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC; pub const TFD_NONBLOCK: ::c_int = O_NONBLOCK; pub const TFD_TIMER_ABSTIME: ::c_int = 1; pub const TFD_TIMER_CANCEL_ON_SET: ::c_int = 2; pub const USER_PROCESS: ::c_short = 7; pub const _POSIX_VDISABLE: ::cc_t = 0; // linux/falloc.h pub const FALLOC_FL_KEEP_SIZE: ::c_int = 0x01; pub const FALLOC_FL_PUNCH_HOLE: ::c_int = 0x02; pub const FALLOC_FL_NO_HIDE_STALE: ::c_int = 0x04; pub const FALLOC_FL_COLLAPSE_RANGE: ::c_int = 0x08; pub const FALLOC_FL_ZERO_RANGE: ::c_int = 0x10; pub const FALLOC_FL_INSERT_RANGE: ::c_int = 0x20; pub const FALLOC_FL_UNSHARE_RANGE: ::c_int = 0x40; pub const BUFSIZ: ::c_uint = 1024; pub const FILENAME_MAX: ::c_uint = 4096; pub const FOPEN_MAX: ::c_uint = 20; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const L_tmpnam: ::c_uint = 4096; pub const TMP_MAX: ::c_uint = 308915776; pub const _PC_LINK_MAX: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_2_SYMLINKS: ::c_int = 7; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 8; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 9; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 10; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 11; pub const _PC_REC_XFER_ALIGN: ::c_int = 12; pub const _PC_SYMLINK_MAX: ::c_int = 13; pub const _PC_CHOWN_RESTRICTED: ::c_int = 14; pub const _PC_NO_TRUNC: ::c_int = 15; pub const _PC_VDISABLE: ::c_int = 16; pub const _PC_ASYNC_IO: ::c_int = 17; pub const _PC_PRIO_IO: ::c_int = 18; pub const _PC_SYNC_IO: ::c_int = 19; pub const FIONBIO: ::c_int = 0x5421; pub const _SC_ARG_MAX: ::c_int = 0x0000; pub const _SC_BC_BASE_MAX: ::c_int = 0x0001; pub const _SC_BC_DIM_MAX: ::c_int = 0x0002; pub const _SC_BC_SCALE_MAX: ::c_int = 0x0003; pub const _SC_BC_STRING_MAX: ::c_int = 0x0004; pub const _SC_CHILD_MAX: ::c_int = 0x0005; pub const _SC_CLK_TCK: ::c_int = 0x0006; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 0x0007; pub const _SC_EXPR_NEST_MAX: ::c_int = 0x0008; pub const _SC_LINE_MAX: ::c_int = 0x0009; pub const _SC_NGROUPS_MAX: ::c_int = 0x000a; pub const _SC_OPEN_MAX: ::c_int = 0x000b; pub const _SC_PASS_MAX: ::c_int = 0x000c; pub const _SC_2_C_BIND: ::c_int = 0x000d; pub const _SC_2_C_DEV: ::c_int = 0x000e; pub const _SC_2_C_VERSION: ::c_int = 0x000f; pub const _SC_2_CHAR_TERM: ::c_int = 0x0010; pub const _SC_2_FORT_DEV: ::c_int = 0x0011; pub const _SC_2_FORT_RUN: ::c_int = 0x0012; pub const _SC_2_LOCALEDEF: ::c_int = 0x0013; pub const _SC_2_SW_DEV: ::c_int = 0x0014; pub const _SC_2_UPE: ::c_int = 0x0015; pub const _SC_2_VERSION: ::c_int = 0x0016; pub const _SC_JOB_CONTROL: ::c_int = 0x0017; pub const _SC_SAVED_IDS: ::c_int = 0x0018; pub const _SC_VERSION: ::c_int = 0x0019; pub const _SC_RE_DUP_MAX: ::c_int = 0x001a; pub const _SC_STREAM_MAX: ::c_int = 0x001b; pub const _SC_TZNAME_MAX: ::c_int = 0x001c; pub const _SC_XOPEN_CRYPT: ::c_int = 0x001d; pub const _SC_XOPEN_ENH_I18N: ::c_int = 0x001e; pub const _SC_XOPEN_SHM: ::c_int = 0x001f; pub const _SC_XOPEN_VERSION: ::c_int = 0x0020; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 0x0021; pub const _SC_XOPEN_REALTIME: ::c_int = 0x0022; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 0x0023; pub const _SC_XOPEN_LEGACY: ::c_int = 0x0024; pub const _SC_ATEXIT_MAX: ::c_int = 0x0025; pub const _SC_IOV_MAX: ::c_int = 0x0026; pub const _SC_UIO_MAXIOV: ::c_int = _SC_IOV_MAX; pub const _SC_PAGESIZE: ::c_int = 0x0027; pub const _SC_PAGE_SIZE: ::c_int = 0x0028; pub const _SC_XOPEN_UNIX: ::c_int = 0x0029; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 0x002a; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 0x002b; pub const _SC_XBS5_LP64_OFF64: ::c_int = 0x002c; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 0x002d; pub const _SC_AIO_LISTIO_MAX: ::c_int = 0x002e; pub const _SC_AIO_MAX: ::c_int = 0x002f; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 0x0030; pub const _SC_DELAYTIMER_MAX: ::c_int = 0x0031; pub const _SC_MQ_OPEN_MAX: ::c_int = 0x0032; pub const _SC_MQ_PRIO_MAX: ::c_int = 0x0033; pub const _SC_RTSIG_MAX: ::c_int = 0x0034; pub const _SC_SEM_NSEMS_MAX: ::c_int = 0x0035; pub const _SC_SEM_VALUE_MAX: ::c_int = 0x0036; pub const _SC_SIGQUEUE_MAX: ::c_int = 0x0037; pub const _SC_TIMER_MAX: ::c_int = 0x0038; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 0x0039; pub const _SC_FSYNC: ::c_int = 0x003a; pub const _SC_MAPPED_FILES: ::c_int = 0x003b; pub const _SC_MEMLOCK: ::c_int = 0x003c; pub const _SC_MEMLOCK_RANGE: ::c_int = 0x003d; pub const _SC_MEMORY_PROTECTION: ::c_int = 0x003e; pub const _SC_MESSAGE_PASSING: ::c_int = 0x003f; pub const _SC_PRIORITIZED_IO: ::c_int = 0x0040; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 0x0041; pub const _SC_REALTIME_SIGNALS: ::c_int = 0x0042; pub const _SC_SEMAPHORES: ::c_int = 0x0043; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 0x0044; pub const _SC_SYNCHRONIZED_IO: ::c_int = 0x0045; pub const _SC_TIMERS: ::c_int = 0x0046; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 0x0047; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 0x0048; pub const _SC_LOGIN_NAME_MAX: ::c_int = 0x0049; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 0x004a; pub const _SC_THREAD_KEYS_MAX: ::c_int = 0x004b; pub const _SC_THREAD_STACK_MIN: ::c_int = 0x004c; pub const _SC_THREAD_THREADS_MAX: ::c_int = 0x004d; pub const _SC_TTY_NAME_MAX: ::c_int = 0x004e; pub const _SC_THREADS: ::c_int = 0x004f; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 0x0050; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 0x0051; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 0x0052; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 0x0053; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 0x0054; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 0x0055; pub const _SC_NPROCESSORS_CONF: ::c_int = 0x0060; pub const _SC_NPROCESSORS_ONLN: ::c_int = 0x0061; pub const _SC_PHYS_PAGES: ::c_int = 0x0062; pub const _SC_AVPHYS_PAGES: ::c_int = 0x0063; pub const _SC_MONOTONIC_CLOCK: ::c_int = 0x0064; pub const _SC_2_PBS: ::c_int = 0x0065; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 0x0066; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 0x0067; pub const _SC_2_PBS_LOCATE: ::c_int = 0x0068; pub const _SC_2_PBS_MESSAGE: ::c_int = 0x0069; pub const _SC_2_PBS_TRACK: ::c_int = 0x006a; pub const _SC_ADVISORY_INFO: ::c_int = 0x006b; pub const _SC_BARRIERS: ::c_int = 0x006c; pub const _SC_CLOCK_SELECTION: ::c_int = 0x006d; pub const _SC_CPUTIME: ::c_int = 0x006e; pub const _SC_HOST_NAME_MAX: ::c_int = 0x006f; pub const _SC_IPV6: ::c_int = 0x0070; pub const _SC_RAW_SOCKETS: ::c_int = 0x0071; pub const _SC_READER_WRITER_LOCKS: ::c_int = 0x0072; pub const _SC_REGEXP: ::c_int = 0x0073; pub const _SC_SHELL: ::c_int = 0x0074; pub const _SC_SPAWN: ::c_int = 0x0075; pub const _SC_SPIN_LOCKS: ::c_int = 0x0076; pub const _SC_SPORADIC_SERVER: ::c_int = 0x0077; pub const _SC_SS_REPL_MAX: ::c_int = 0x0078; pub const _SC_SYMLOOP_MAX: ::c_int = 0x0079; pub const _SC_THREAD_CPUTIME: ::c_int = 0x007a; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 0x007b; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 0x007c; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 0x007d; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 0x007e; pub const _SC_TIMEOUTS: ::c_int = 0x007f; pub const _SC_TRACE: ::c_int = 0x0080; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 0x0081; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 0x0082; pub const _SC_TRACE_INHERIT: ::c_int = 0x0083; pub const _SC_TRACE_LOG: ::c_int = 0x0084; pub const _SC_TRACE_NAME_MAX: ::c_int = 0x0085; pub const _SC_TRACE_SYS_MAX: ::c_int = 0x0086; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 0x0087; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 0x0088; pub const _SC_V7_ILP32_OFF32: ::c_int = 0x0089; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 0x008a; pub const _SC_V7_LP64_OFF64: ::c_int = 0x008b; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 0x008c; pub const _SC_XOPEN_STREAMS: ::c_int = 0x008d; pub const _SC_XOPEN_UUCP: ::c_int = 0x008e; pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 0x008f; pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 0x0090; pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 0x0091; pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 0x0092; pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 0x0093; pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 0x0094; pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 0x0095; pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 0x0096; pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 0x0097; pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 0x0098; pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 0x0099; pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 0x009a; pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 0x009b; pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 0x009c; pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 0x009d; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const F_SEAL_FUTURE_WRITE: ::c_int = 0x0010; pub const IFF_LOWER_UP: ::c_int = 0x10000; pub const IFF_DORMANT: ::c_int = 0x20000; pub const IFF_ECHO: ::c_int = 0x40000; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_EXPLICIT_SCHED: ::c_int = 0; pub const PTHREAD_INHERIT_SCHED: ::c_int = 1; // stdio.h pub const RENAME_NOREPLACE: ::c_int = 1; pub const RENAME_EXCHANGE: ::c_int = 2; pub const RENAME_WHITEOUT: ::c_int = 4; pub const FIOCLEX: ::c_int = 0x5451; pub const FIONCLEX: ::c_int = 0x5450; pub const SIGCHLD: ::c_int = 17; pub const SIGBUS: ::c_int = 7; pub const SIGUSR1: ::c_int = 10; pub const SIGUSR2: ::c_int = 12; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGURG: ::c_int = 23; pub const SIGIO: ::c_int = 29; pub const SIGSYS: ::c_int = 31; pub const SIGSTKFLT: ::c_int = 16; #[deprecated(since = "0.2.55", note = "Use SIGSYS instead")] pub const SIGUNUSED: ::c_int = 31; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGPOLL: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0x000000; pub const SIG_UNBLOCK: ::c_int = 0x01; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const LC_PAPER: ::c_int = 7; pub const LC_NAME: ::c_int = 8; pub const LC_ADDRESS: ::c_int = 9; pub const LC_TELEPHONE: ::c_int = 10; pub const LC_MEASUREMENT: ::c_int = 11; pub const LC_IDENTIFICATION: ::c_int = 12; pub const LC_PAPER_MASK: ::c_int = 1 << LC_PAPER; pub const LC_NAME_MASK: ::c_int = 1 << LC_NAME; pub const LC_ADDRESS_MASK: ::c_int = 1 << LC_ADDRESS; pub const LC_TELEPHONE_MASK: ::c_int = 1 << LC_TELEPHONE; pub const LC_MEASUREMENT_MASK: ::c_int = 1 << LC_MEASUREMENT; pub const LC_IDENTIFICATION_MASK: ::c_int = 1 << LC_IDENTIFICATION; pub const LC_ALL_MASK: ::c_int = ::LC_CTYPE_MASK | ::LC_NUMERIC_MASK | ::LC_TIME_MASK | ::LC_COLLATE_MASK | ::LC_MONETARY_MASK | ::LC_MESSAGES_MASK | LC_PAPER_MASK | LC_NAME_MASK | LC_ADDRESS_MASK | LC_TELEPHONE_MASK | LC_MEASUREMENT_MASK | LC_IDENTIFICATION_MASK; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = 0x0020; pub const MAP_GROWSDOWN: ::c_int = 0x0100; pub const MAP_DENYWRITE: ::c_int = 0x0800; pub const MAP_EXECUTABLE: ::c_int = 0x01000; pub const MAP_LOCKED: ::c_int = 0x02000; pub const MAP_NORESERVE: ::c_int = 0x04000; pub const MAP_POPULATE: ::c_int = 0x08000; pub const MAP_NONBLOCK: ::c_int = 0x010000; pub const MAP_STACK: ::c_int = 0x020000; pub const EDEADLK: ::c_int = 35; pub const ENAMETOOLONG: ::c_int = 36; pub const ENOLCK: ::c_int = 37; pub const ENOSYS: ::c_int = 38; pub const ENOTEMPTY: ::c_int = 39; pub const ELOOP: ::c_int = 40; pub const ENOMSG: ::c_int = 42; pub const EIDRM: ::c_int = 43; pub const ECHRNG: ::c_int = 44; pub const EL2NSYNC: ::c_int = 45; pub const EL3HLT: ::c_int = 46; pub const EL3RST: ::c_int = 47; pub const ELNRNG: ::c_int = 48; pub const EUNATCH: ::c_int = 49; pub const ENOCSI: ::c_int = 50; pub const EL2HLT: ::c_int = 51; pub const EBADE: ::c_int = 52; pub const EBADR: ::c_int = 53; pub const EXFULL: ::c_int = 54; pub const ENOANO: ::c_int = 55; pub const EBADRQC: ::c_int = 56; pub const EBADSLT: ::c_int = 57; pub const EMULTIHOP: ::c_int = 72; pub const EBADMSG: ::c_int = 74; pub const EOVERFLOW: ::c_int = 75; pub const ENOTUNIQ: ::c_int = 76; pub const EBADFD: ::c_int = 77; pub const EREMCHG: ::c_int = 78; pub const ELIBACC: ::c_int = 79; pub const ELIBBAD: ::c_int = 80; pub const ELIBSCN: ::c_int = 81; pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; pub const EUSERS: ::c_int = 87; pub const ENOTSOCK: ::c_int = 88; pub const EDESTADDRREQ: ::c_int = 89; pub const EMSGSIZE: ::c_int = 90; pub const EPROTOTYPE: ::c_int = 91; pub const ENOPROTOOPT: ::c_int = 92; pub const EPROTONOSUPPORT: ::c_int = 93; pub const ESOCKTNOSUPPORT: ::c_int = 94; pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; pub const EADDRNOTAVAIL: ::c_int = 99; pub const ENETDOWN: ::c_int = 100; pub const ENETUNREACH: ::c_int = 101; pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EISCONN: ::c_int = 106; pub const ENOTCONN: ::c_int = 107; pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; pub const ETIMEDOUT: ::c_int = 110; pub const ECONNREFUSED: ::c_int = 111; pub const EHOSTDOWN: ::c_int = 112; pub const EHOSTUNREACH: ::c_int = 113; pub const EALREADY: ::c_int = 114; pub const EINPROGRESS: ::c_int = 115; pub const ESTALE: ::c_int = 116; pub const EUCLEAN: ::c_int = 117; pub const ENOTNAM: ::c_int = 118; pub const ENAVAIL: ::c_int = 119; pub const EISNAM: ::c_int = 120; pub const EREMOTEIO: ::c_int = 121; pub const EDQUOT: ::c_int = 122; pub const ENOMEDIUM: ::c_int = 123; pub const EMEDIUMTYPE: ::c_int = 124; pub const ECANCELED: ::c_int = 125; pub const ENOKEY: ::c_int = 126; pub const EKEYEXPIRED: ::c_int = 127; pub const EKEYREVOKED: ::c_int = 128; pub const EKEYREJECTED: ::c_int = 129; pub const EOWNERDEAD: ::c_int = 130; pub const ENOTRECOVERABLE: ::c_int = 131; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_DCCP: ::c_int = 6; pub const SOCK_PACKET: ::c_int = 10; pub const IPPROTO_MAX: ::c_int = 256; pub const SOL_SOCKET: ::c_int = 1; pub const SOL_SCTP: ::c_int = 132; pub const SOL_IPX: ::c_int = 256; pub const SOL_AX25: ::c_int = 257; pub const SOL_ATALK: ::c_int = 258; pub const SOL_NETROM: ::c_int = 259; pub const SOL_ROSE: ::c_int = 260; /* DCCP socket options */ pub const DCCP_SOCKOPT_PACKET_SIZE: ::c_int = 1; pub const DCCP_SOCKOPT_SERVICE: ::c_int = 2; pub const DCCP_SOCKOPT_CHANGE_L: ::c_int = 3; pub const DCCP_SOCKOPT_CHANGE_R: ::c_int = 4; pub const DCCP_SOCKOPT_GET_CUR_MPS: ::c_int = 5; pub const DCCP_SOCKOPT_SERVER_TIMEWAIT: ::c_int = 6; pub const DCCP_SOCKOPT_SEND_CSCOV: ::c_int = 10; pub const DCCP_SOCKOPT_RECV_CSCOV: ::c_int = 11; pub const DCCP_SOCKOPT_AVAILABLE_CCIDS: ::c_int = 12; pub const DCCP_SOCKOPT_CCID: ::c_int = 13; pub const DCCP_SOCKOPT_TX_CCID: ::c_int = 14; pub const DCCP_SOCKOPT_RX_CCID: ::c_int = 15; pub const DCCP_SOCKOPT_QPOLICY_ID: ::c_int = 16; pub const DCCP_SOCKOPT_QPOLICY_TXQLEN: ::c_int = 17; pub const DCCP_SOCKOPT_CCID_RX_INFO: ::c_int = 128; pub const DCCP_SOCKOPT_CCID_TX_INFO: ::c_int = 192; /// maximum number of services provided on the same listening port pub const DCCP_SERVICE_LIST_MAX_LEN: ::c_int = 32; pub const SO_REUSEADDR: ::c_int = 2; pub const SO_TYPE: ::c_int = 3; pub const SO_ERROR: ::c_int = 4; pub const SO_DONTROUTE: ::c_int = 5; pub const SO_BROADCAST: ::c_int = 6; pub const SO_SNDBUF: ::c_int = 7; pub const SO_RCVBUF: ::c_int = 8; pub const SO_KEEPALIVE: ::c_int = 9; pub const SO_OOBINLINE: ::c_int = 10; pub const SO_PRIORITY: ::c_int = 12; pub const SO_LINGER: ::c_int = 13; pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_REUSEPORT: ::c_int = 15; pub const SO_PASSCRED: ::c_int = 16; pub const SO_PEERCRED: ::c_int = 17; pub const SO_RCVLOWAT: ::c_int = 18; pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; pub const SO_BINDTODEVICE: ::c_int = 25; pub const SO_ATTACH_FILTER: ::c_int = 26; pub const SO_DETACH_FILTER: ::c_int = 27; pub const SO_GET_FILTER: ::c_int = SO_ATTACH_FILTER; pub const SO_TIMESTAMP: ::c_int = 29; pub const SO_ACCEPTCONN: ::c_int = 30; pub const SO_PEERSEC: ::c_int = 31; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_PASSSEC: ::c_int = 34; pub const SO_TIMESTAMPNS: ::c_int = 35; // pub const SO_TIMESTAMPNS_OLD: ::c_int = 35; pub const SO_MARK: ::c_int = 36; pub const SO_TIMESTAMPING: ::c_int = 37; // pub const SO_TIMESTAMPING_OLD: ::c_int = 37; pub const SO_PROTOCOL: ::c_int = 38; pub const SO_DOMAIN: ::c_int = 39; pub const SO_RXQ_OVFL: ::c_int = 40; pub const SO_PEEK_OFF: ::c_int = 42; pub const SO_BUSY_POLL: ::c_int = 46; pub const SCM_TIMESTAMPING_OPT_STATS: ::c_int = 54; pub const SCM_TIMESTAMPING_PKTINFO: ::c_int = 58; pub const SO_TIMESTAMP_NEW: ::c_int = 63; pub const SO_TIMESTAMPNS_NEW: ::c_int = 64; pub const SO_TIMESTAMPING_NEW: ::c_int = 65; // Defined in unix/linux_like/mod.rs // pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const SCM_TIMESTAMPNS: ::c_int = SO_TIMESTAMPNS; pub const SCM_TIMESTAMPING: ::c_int = SO_TIMESTAMPING; pub const IPTOS_ECN_NOTECT: u8 = 0x00; pub const O_ACCMODE: ::c_int = 3; pub const O_APPEND: ::c_int = 1024; pub const O_CREAT: ::c_int = 64; pub const O_EXCL: ::c_int = 128; pub const O_NOCTTY: ::c_int = 256; pub const O_NONBLOCK: ::c_int = 2048; pub const O_SYNC: ::c_int = 0x101000; pub const O_ASYNC: ::c_int = 0x2000; pub const O_NDELAY: ::c_int = 0x800; pub const O_DSYNC: ::c_int = 4096; pub const O_RSYNC: ::c_int = O_SYNC; pub const NI_MAXHOST: ::size_t = 1025; pub const NI_MAXSERV: ::size_t = 32; pub const NI_NOFQDN: ::c_int = 0x00000001; pub const NI_NUMERICHOST: ::c_int = 0x00000002; pub const NI_NAMEREQD: ::c_int = 0x00000004; pub const NI_NUMERICSERV: ::c_int = 0x00000008; pub const NI_DGRAM: ::c_int = 0x00000010; pub const NCCS: usize = 19; pub const TCSBRKP: ::c_int = 0x5425; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 0x1; pub const TCSAFLUSH: ::c_int = 0x2; pub const VEOF: usize = 4; pub const VEOL: usize = 11; pub const VEOL2: usize = 16; pub const VMIN: usize = 6; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const FLUSHO: ::tcflag_t = 0x00001000; pub const EXTPROC: ::tcflag_t = 0o200000; pub const MAP_HUGETLB: ::c_int = 0x040000; pub const PTRACE_TRACEME: ::c_int = 0; pub const PTRACE_PEEKTEXT: ::c_int = 1; pub const PTRACE_PEEKDATA: ::c_int = 2; pub const PTRACE_PEEKUSER: ::c_int = 3; pub const PTRACE_POKETEXT: ::c_int = 4; pub const PTRACE_POKEDATA: ::c_int = 5; pub const PTRACE_POKEUSER: ::c_int = 6; pub const PTRACE_CONT: ::c_int = 7; pub const PTRACE_KILL: ::c_int = 8; pub const PTRACE_SINGLESTEP: ::c_int = 9; pub const PTRACE_GETREGS: ::c_int = 12; pub const PTRACE_SETREGS: ::c_int = 13; pub const PTRACE_ATTACH: ::c_int = 16; pub const PTRACE_DETACH: ::c_int = 17; pub const PTRACE_SYSCALL: ::c_int = 24; pub const PTRACE_SETOPTIONS: ::c_int = 0x4200; pub const PTRACE_GETEVENTMSG: ::c_int = 0x4201; pub const PTRACE_GETSIGINFO: ::c_int = 0x4202; pub const PTRACE_SETSIGINFO: ::c_int = 0x4203; pub const PTRACE_GETREGSET: ::c_int = 0x4204; pub const PTRACE_SETREGSET: ::c_int = 0x4205; pub const PTRACE_SECCOMP_GET_METADATA: ::c_int = 0x420d; pub const PTRACE_EVENT_STOP: ::c_int = 128; pub const F_GETLK: ::c_int = 5; pub const F_GETOWN: ::c_int = 9; pub const F_SETOWN: ::c_int = 8; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_RDLCK: ::c_int = 0; pub const F_WRLCK: ::c_int = 1; pub const F_UNLCK: ::c_int = 2; pub const F_OFD_GETLK: ::c_int = 36; pub const F_OFD_SETLK: ::c_int = 37; pub const F_OFD_SETLKW: ::c_int = 38; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_NPROC: ::c_int = 6; pub const RLIMIT_NOFILE: ::c_int = 7; pub const RLIMIT_MEMLOCK: ::c_int = 8; pub const RLIMIT_AS: ::c_int = 9; pub const RLIMIT_LOCKS: ::c_int = 10; pub const RLIMIT_SIGPENDING: ::c_int = 11; pub const RLIMIT_MSGQUEUE: ::c_int = 12; pub const RLIMIT_NICE: ::c_int = 13; pub const RLIMIT_RTPRIO: ::c_int = 14; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 16; pub const RLIM_INFINITY: ::rlim_t = !0; pub const TCGETS: ::c_int = 0x5401; pub const TCSETS: ::c_int = 0x5402; pub const TCSETSW: ::c_int = 0x5403; pub const TCSETSF: ::c_int = 0x5404; pub const TCGETS2: ::c_int = 0x802c542a; pub const TCSETS2: ::c_int = 0x402c542b; pub const TCSETSW2: ::c_int = 0x402c542c; pub const TCSETSF2: ::c_int = 0x402c542d; pub const TCGETA: ::c_int = 0x5405; pub const TCSETA: ::c_int = 0x5406; pub const TCSETAW: ::c_int = 0x5407; pub const TCSETAF: ::c_int = 0x5408; pub const TCSBRK: ::c_int = 0x5409; pub const TCXONC: ::c_int = 0x540A; pub const TCFLSH: ::c_int = 0x540B; pub const TIOCGSOFTCAR: ::c_int = 0x5419; pub const TIOCSSOFTCAR: ::c_int = 0x541A; pub const TIOCINQ: ::c_int = 0x541B; pub const TIOCLINUX: ::c_int = 0x541C; pub const TIOCGSERIAL: ::c_int = 0x541E; pub const TIOCEXCL: ::c_int = 0x540C; pub const TIOCNXCL: ::c_int = 0x540D; pub const TIOCSCTTY: ::c_int = 0x540E; pub const TIOCGPGRP: ::c_int = 0x540F; pub const TIOCSPGRP: ::c_int = 0x5410; pub const TIOCOUTQ: ::c_int = 0x5411; pub const TIOCSTI: ::c_int = 0x5412; pub const TIOCGWINSZ: ::c_int = 0x5413; pub const TIOCSWINSZ: ::c_int = 0x5414; pub const TIOCMGET: ::c_int = 0x5415; pub const TIOCMBIS: ::c_int = 0x5416; pub const TIOCMBIC: ::c_int = 0x5417; pub const TIOCMSET: ::c_int = 0x5418; pub const FIONREAD: ::c_int = 0x541B; pub const TIOCCONS: ::c_int = 0x541D; pub const TIOCSBRK: ::c_int = 0x5427; pub const TIOCCBRK: ::c_int = 0x5428; cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", target_arch = "riscv64", target_arch = "s390x"))] { pub const FICLONE: ::c_int = 0x40049409; pub const FICLONERANGE: ::c_int = 0x4020940D; } else if #[cfg(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64"))] { pub const FICLONE: ::c_int = 0x80049409; pub const FICLONERANGE: ::c_int = 0x8020940D; } } pub const ST_RDONLY: ::c_ulong = 1; pub const ST_NOSUID: ::c_ulong = 2; pub const ST_NODEV: ::c_ulong = 4; pub const ST_NOEXEC: ::c_ulong = 8; pub const ST_SYNCHRONOUS: ::c_ulong = 16; pub const ST_MANDLOCK: ::c_ulong = 64; pub const ST_NOATIME: ::c_ulong = 1024; pub const ST_NODIRATIME: ::c_ulong = 2048; pub const ST_RELATIME: ::c_ulong = 4096; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const AI_PASSIVE: ::c_int = 0x00000001; pub const AI_CANONNAME: ::c_int = 0x00000002; pub const AI_NUMERICHOST: ::c_int = 0x00000004; pub const AI_NUMERICSERV: ::c_int = 0x00000008; pub const AI_MASK: ::c_int = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG; pub const AI_ALL: ::c_int = 0x00000100; pub const AI_V4MAPPED_CFG: ::c_int = 0x00000200; pub const AI_ADDRCONFIG: ::c_int = 0x00000400; pub const AI_V4MAPPED: ::c_int = 0x00000800; pub const AI_DEFAULT: ::c_int = AI_V4MAPPED_CFG | AI_ADDRCONFIG; // linux/kexec.h pub const KEXEC_ON_CRASH: ::c_int = 0x00000001; pub const KEXEC_PRESERVE_CONTEXT: ::c_int = 0x00000002; pub const KEXEC_ARCH_MASK: ::c_int = 0xffff0000; pub const KEXEC_FILE_UNLOAD: ::c_int = 0x00000001; pub const KEXEC_FILE_ON_CRASH: ::c_int = 0x00000002; pub const KEXEC_FILE_NO_INITRAMFS: ::c_int = 0x00000004; pub const LINUX_REBOOT_MAGIC1: ::c_int = 0xfee1dead; pub const LINUX_REBOOT_MAGIC2: ::c_int = 672274793; pub const LINUX_REBOOT_MAGIC2A: ::c_int = 85072278; pub const LINUX_REBOOT_MAGIC2B: ::c_int = 369367448; pub const LINUX_REBOOT_MAGIC2C: ::c_int = 537993216; pub const LINUX_REBOOT_CMD_RESTART: ::c_int = 0x01234567; pub const LINUX_REBOOT_CMD_HALT: ::c_int = 0xCDEF0123; pub const LINUX_REBOOT_CMD_CAD_ON: ::c_int = 0x89ABCDEF; pub const LINUX_REBOOT_CMD_CAD_OFF: ::c_int = 0x00000000; pub const LINUX_REBOOT_CMD_POWER_OFF: ::c_int = 0x4321FEDC; pub const LINUX_REBOOT_CMD_RESTART2: ::c_int = 0xA1B2C3D4; pub const LINUX_REBOOT_CMD_SW_SUSPEND: ::c_int = 0xD000FCE2; pub const LINUX_REBOOT_CMD_KEXEC: ::c_int = 0x45584543; pub const REG_BASIC: ::c_int = 0; pub const REG_EXTENDED: ::c_int = 1; pub const REG_ICASE: ::c_int = 2; pub const REG_NOSUB: ::c_int = 4; pub const REG_NEWLINE: ::c_int = 8; pub const REG_NOSPEC: ::c_int = 16; pub const REG_PEND: ::c_int = 32; pub const REG_DUMP: ::c_int = 128; pub const REG_NOMATCH: ::c_int = 1; pub const REG_BADPAT: ::c_int = 2; pub const REG_ECOLLATE: ::c_int = 3; pub const REG_ECTYPE: ::c_int = 4; pub const REG_EESCAPE: ::c_int = 5; pub const REG_ESUBREG: ::c_int = 6; pub const REG_EBRACK: ::c_int = 7; pub const REG_EPAREN: ::c_int = 8; pub const REG_EBRACE: ::c_int = 9; pub const REG_BADBR: ::c_int = 10; pub const REG_ERANGE: ::c_int = 11; pub const REG_ESPACE: ::c_int = 12; pub const REG_BADRPT: ::c_int = 13; pub const REG_EMPTY: ::c_int = 14; pub const REG_ASSERT: ::c_int = 15; pub const REG_INVARG: ::c_int = 16; pub const REG_ATOI: ::c_int = 255; pub const REG_ITOA: ::c_int = 256; pub const REG_NOTBOL: ::c_int = 1; pub const REG_NOTEOL: ::c_int = 2; pub const REG_STARTEND: ::c_int = 4; pub const REG_TRACE: ::c_int = 256; pub const REG_LARGE: ::c_int = 512; pub const REG_BACKR: ::c_int = 1024; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MCL_ONFAULT: ::c_int = 0x0004; pub const CBAUD: ::tcflag_t = 0o0010017; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const FF1: ::tcflag_t = 0x00008000; pub const BS1: ::tcflag_t = 0x00002000; pub const VT1: ::tcflag_t = 0x00004000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 5; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x4; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x00000010; pub const CS7: ::tcflag_t = 0x00000020; pub const CS8: ::tcflag_t = 0x00000030; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOPRT: ::tcflag_t = 0x00000400; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const PENDIN: ::tcflag_t = 0x00004000; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const VSWTC: usize = 7; pub const OLCUC: ::tcflag_t = 0o000002; pub const NLDLY: ::tcflag_t = 0o000400; pub const CRDLY: ::tcflag_t = 0o003000; pub const TABDLY: ::tcflag_t = 0o014000; pub const BSDLY: ::tcflag_t = 0o020000; pub const FFDLY: ::tcflag_t = 0o100000; pub const VTDLY: ::tcflag_t = 0o040000; pub const XTABS: ::tcflag_t = 0o014000; pub const B0: ::speed_t = 0o000000; pub const B50: ::speed_t = 0o000001; pub const B75: ::speed_t = 0o000002; pub const B110: ::speed_t = 0o000003; pub const B134: ::speed_t = 0o000004; pub const B150: ::speed_t = 0o000005; pub const B200: ::speed_t = 0o000006; pub const B300: ::speed_t = 0o000007; pub const B600: ::speed_t = 0o000010; pub const B1200: ::speed_t = 0o000011; pub const B1800: ::speed_t = 0o000012; pub const B2400: ::speed_t = 0o000013; pub const B4800: ::speed_t = 0o000014; pub const B9600: ::speed_t = 0o000015; pub const B19200: ::speed_t = 0o000016; pub const B38400: ::speed_t = 0o000017; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const BOTHER: ::speed_t = 0o010000; pub const B57600: ::speed_t = 0o010001; pub const B115200: ::speed_t = 0o010002; pub const B230400: ::speed_t = 0o010003; pub const B460800: ::speed_t = 0o010004; pub const B500000: ::speed_t = 0o010005; pub const B576000: ::speed_t = 0o010006; pub const B921600: ::speed_t = 0o010007; pub const B1000000: ::speed_t = 0o010010; pub const B1152000: ::speed_t = 0o010011; pub const B1500000: ::speed_t = 0o010012; pub const B2000000: ::speed_t = 0o010013; pub const B2500000: ::speed_t = 0o010014; pub const B3000000: ::speed_t = 0o010015; pub const B3500000: ::speed_t = 0o010016; pub const B4000000: ::speed_t = 0o010017; pub const IBSHIFT: ::tcflag_t = 16; pub const BLKIOMIN: ::c_int = 0x1278; pub const BLKIOOPT: ::c_int = 0x1279; pub const BLKSSZGET: ::c_int = 0x1268; pub const BLKPBSZGET: ::c_int = 0x127B; cfg_if! { // Those type are constructed using the _IOC macro // DD-SS_SSSS_SSSS_SSSS-TTTT_TTTT-NNNN_NNNN // where D stands for direction (either None (00), Read (01) or Write (11)) // where S stands for size (int, long, struct...) // where T stands for type ('f','v','X'...) // where N stands for NR (NumbeR) if #[cfg(any(target_arch = "x86", target_arch = "arm"))] { pub const FS_IOC_GETFLAGS: ::c_int = 0x80046601; pub const FS_IOC_SETFLAGS: ::c_int = 0x40046602; pub const FS_IOC_GETVERSION: ::c_int = 0x80047601; pub const FS_IOC_SETVERSION: ::c_int = 0x40047602; pub const FS_IOC32_GETFLAGS: ::c_int = 0x80046601; pub const FS_IOC32_SETFLAGS: ::c_int = 0x40046602; pub const FS_IOC32_GETVERSION: ::c_int = 0x80047601; pub const FS_IOC32_SETVERSION: ::c_int = 0x40047602; } else if #[cfg(any(target_arch = "x86_64", target_arch = "riscv64", target_arch = "aarch64"))] { pub const FS_IOC_GETFLAGS: ::c_int = 0x80086601; pub const FS_IOC_SETFLAGS: ::c_int = 0x40086602; pub const FS_IOC_GETVERSION: ::c_int = 0x80087601; pub const FS_IOC_SETVERSION: ::c_int = 0x40087602; pub const FS_IOC32_GETFLAGS: ::c_int = 0x80046601; pub const FS_IOC32_SETFLAGS: ::c_int = 0x40046602; pub const FS_IOC32_GETVERSION: ::c_int = 0x80047601; pub const FS_IOC32_SETVERSION: ::c_int = 0x40047602; } } pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_NODATA: ::c_int = 7; pub const EAI_NONAME: ::c_int = 8; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 14; pub const NETLINK_ROUTE: ::c_int = 0; pub const NETLINK_UNUSED: ::c_int = 1; pub const NETLINK_USERSOCK: ::c_int = 2; pub const NETLINK_FIREWALL: ::c_int = 3; pub const NETLINK_SOCK_DIAG: ::c_int = 4; pub const NETLINK_NFLOG: ::c_int = 5; pub const NETLINK_XFRM: ::c_int = 6; pub const NETLINK_SELINUX: ::c_int = 7; pub const NETLINK_ISCSI: ::c_int = 8; pub const NETLINK_AUDIT: ::c_int = 9; pub const NETLINK_FIB_LOOKUP: ::c_int = 10; pub const NETLINK_CONNECTOR: ::c_int = 11; pub const NETLINK_NETFILTER: ::c_int = 12; pub const NETLINK_IP6_FW: ::c_int = 13; pub const NETLINK_DNRTMSG: ::c_int = 14; pub const NETLINK_KOBJECT_UEVENT: ::c_int = 15; pub const NETLINK_GENERIC: ::c_int = 16; pub const NETLINK_SCSITRANSPORT: ::c_int = 18; pub const NETLINK_ECRYPTFS: ::c_int = 19; pub const NETLINK_RDMA: ::c_int = 20; pub const NETLINK_CRYPTO: ::c_int = 21; pub const NETLINK_INET_DIAG: ::c_int = NETLINK_SOCK_DIAG; pub const MAX_LINKS: ::c_int = 32; pub const NLM_F_REQUEST: ::c_int = 1; pub const NLM_F_MULTI: ::c_int = 2; pub const NLM_F_ACK: ::c_int = 4; pub const NLM_F_ECHO: ::c_int = 8; pub const NLM_F_DUMP_INTR: ::c_int = 16; pub const NLM_F_DUMP_FILTERED: ::c_int = 32; pub const NLM_F_ROOT: ::c_int = 0x100; pub const NLM_F_MATCH: ::c_int = 0x200; pub const NLM_F_ATOMIC: ::c_int = 0x400; pub const NLM_F_DUMP: ::c_int = NLM_F_ROOT | NLM_F_MATCH; pub const NLM_F_REPLACE: ::c_int = 0x100; pub const NLM_F_EXCL: ::c_int = 0x200; pub const NLM_F_CREATE: ::c_int = 0x400; pub const NLM_F_APPEND: ::c_int = 0x800; pub const NLMSG_NOOP: ::c_int = 0x1; pub const NLMSG_ERROR: ::c_int = 0x2; pub const NLMSG_DONE: ::c_int = 0x3; pub const NLMSG_OVERRUN: ::c_int = 0x4; pub const NLMSG_MIN_TYPE: ::c_int = 0x10; // linux/netfilter/nfnetlink.h pub const NFNLGRP_NONE: ::c_int = 0; pub const NFNLGRP_CONNTRACK_NEW: ::c_int = 1; pub const NFNLGRP_CONNTRACK_UPDATE: ::c_int = 2; pub const NFNLGRP_CONNTRACK_DESTROY: ::c_int = 3; pub const NFNLGRP_CONNTRACK_EXP_NEW: ::c_int = 4; pub const NFNLGRP_CONNTRACK_EXP_UPDATE: ::c_int = 5; pub const NFNLGRP_CONNTRACK_EXP_DESTROY: ::c_int = 6; pub const NFNLGRP_NFTABLES: ::c_int = 7; pub const NFNLGRP_ACCT_QUOTA: ::c_int = 8; pub const NFNETLINK_V0: ::c_int = 0; pub const NFNL_SUBSYS_NONE: ::c_int = 0; pub const NFNL_SUBSYS_CTNETLINK: ::c_int = 1; pub const NFNL_SUBSYS_CTNETLINK_EXP: ::c_int = 2; pub const NFNL_SUBSYS_QUEUE: ::c_int = 3; pub const NFNL_SUBSYS_ULOG: ::c_int = 4; pub const NFNL_SUBSYS_OSF: ::c_int = 5; pub const NFNL_SUBSYS_IPSET: ::c_int = 6; pub const NFNL_SUBSYS_ACCT: ::c_int = 7; pub const NFNL_SUBSYS_CTNETLINK_TIMEOUT: ::c_int = 8; pub const NFNL_SUBSYS_CTHELPER: ::c_int = 9; pub const NFNL_SUBSYS_NFTABLES: ::c_int = 10; pub const NFNL_SUBSYS_NFT_COMPAT: ::c_int = 11; pub const NFNL_SUBSYS_COUNT: ::c_int = 12; pub const NFNL_MSG_BATCH_BEGIN: ::c_int = NLMSG_MIN_TYPE; pub const NFNL_MSG_BATCH_END: ::c_int = NLMSG_MIN_TYPE + 1; // linux/netfilter/nfnetlink_log.h pub const NFULNL_MSG_PACKET: ::c_int = 0; pub const NFULNL_MSG_CONFIG: ::c_int = 1; pub const NFULA_UNSPEC: ::c_int = 0; pub const NFULA_PACKET_HDR: ::c_int = 1; pub const NFULA_MARK: ::c_int = 2; pub const NFULA_TIMESTAMP: ::c_int = 3; pub const NFULA_IFINDEX_INDEV: ::c_int = 4; pub const NFULA_IFINDEX_OUTDEV: ::c_int = 5; pub const NFULA_IFINDEX_PHYSINDEV: ::c_int = 6; pub const NFULA_IFINDEX_PHYSOUTDEV: ::c_int = 7; pub const NFULA_HWADDR: ::c_int = 8; pub const NFULA_PAYLOAD: ::c_int = 9; pub const NFULA_PREFIX: ::c_int = 10; pub const NFULA_UID: ::c_int = 11; pub const NFULA_SEQ: ::c_int = 12; pub const NFULA_SEQ_GLOBAL: ::c_int = 13; pub const NFULA_GID: ::c_int = 14; pub const NFULA_HWTYPE: ::c_int = 15; pub const NFULA_HWHEADER: ::c_int = 16; pub const NFULA_HWLEN: ::c_int = 17; pub const NFULA_CT: ::c_int = 18; pub const NFULA_CT_INFO: ::c_int = 19; pub const NFULNL_CFG_CMD_NONE: ::c_int = 0; pub const NFULNL_CFG_CMD_BIND: ::c_int = 1; pub const NFULNL_CFG_CMD_UNBIND: ::c_int = 2; pub const NFULNL_CFG_CMD_PF_BIND: ::c_int = 3; pub const NFULNL_CFG_CMD_PF_UNBIND: ::c_int = 4; pub const NFULA_CFG_UNSPEC: ::c_int = 0; pub const NFULA_CFG_CMD: ::c_int = 1; pub const NFULA_CFG_MODE: ::c_int = 2; pub const NFULA_CFG_NLBUFSIZ: ::c_int = 3; pub const NFULA_CFG_TIMEOUT: ::c_int = 4; pub const NFULA_CFG_QTHRESH: ::c_int = 5; pub const NFULA_CFG_FLAGS: ::c_int = 6; pub const NFULNL_COPY_NONE: ::c_int = 0x00; pub const NFULNL_COPY_META: ::c_int = 0x01; pub const NFULNL_COPY_PACKET: ::c_int = 0x02; pub const NFULNL_CFG_F_SEQ: ::c_int = 0x0001; pub const NFULNL_CFG_F_SEQ_GLOBAL: ::c_int = 0x0002; pub const NFULNL_CFG_F_CONNTRACK: ::c_int = 0x0004; // linux/netfilter/nfnetlink_log.h pub const NFQNL_MSG_PACKET: ::c_int = 0; pub const NFQNL_MSG_VERDICT: ::c_int = 1; pub const NFQNL_MSG_CONFIG: ::c_int = 2; pub const NFQNL_MSG_VERDICT_BATCH: ::c_int = 3; pub const NFQA_UNSPEC: ::c_int = 0; pub const NFQA_PACKET_HDR: ::c_int = 1; pub const NFQA_VERDICT_HDR: ::c_int = 2; pub const NFQA_MARK: ::c_int = 3; pub const NFQA_TIMESTAMP: ::c_int = 4; pub const NFQA_IFINDEX_INDEV: ::c_int = 5; pub const NFQA_IFINDEX_OUTDEV: ::c_int = 6; pub const NFQA_IFINDEX_PHYSINDEV: ::c_int = 7; pub const NFQA_IFINDEX_PHYSOUTDEV: ::c_int = 8; pub const NFQA_HWADDR: ::c_int = 9; pub const NFQA_PAYLOAD: ::c_int = 10; pub const NFQA_CT: ::c_int = 11; pub const NFQA_CT_INFO: ::c_int = 12; pub const NFQA_CAP_LEN: ::c_int = 13; pub const NFQA_SKB_INFO: ::c_int = 14; pub const NFQA_EXP: ::c_int = 15; pub const NFQA_UID: ::c_int = 16; pub const NFQA_GID: ::c_int = 17; pub const NFQA_SECCTX: ::c_int = 18; /* FIXME: These are not yet available in musl sanitized kernel headers and make the tests fail. Enable them once musl has them. See https://github.com/rust-lang/libc/pull/1628 for more details. pub const NFQA_VLAN: ::c_int = 19; pub const NFQA_L2HDR: ::c_int = 20; pub const NFQA_VLAN_UNSPEC: ::c_int = 0; pub const NFQA_VLAN_PROTO: ::c_int = 1; pub const NFQA_VLAN_TCI: ::c_int = 2; */ pub const NFQNL_CFG_CMD_NONE: ::c_int = 0; pub const NFQNL_CFG_CMD_BIND: ::c_int = 1; pub const NFQNL_CFG_CMD_UNBIND: ::c_int = 2; pub const NFQNL_CFG_CMD_PF_BIND: ::c_int = 3; pub const NFQNL_CFG_CMD_PF_UNBIND: ::c_int = 4; pub const NFQNL_COPY_NONE: ::c_int = 0; pub const NFQNL_COPY_META: ::c_int = 1; pub const NFQNL_COPY_PACKET: ::c_int = 2; pub const NFQA_CFG_UNSPEC: ::c_int = 0; pub const NFQA_CFG_CMD: ::c_int = 1; pub const NFQA_CFG_PARAMS: ::c_int = 2; pub const NFQA_CFG_QUEUE_MAXLEN: ::c_int = 3; pub const NFQA_CFG_MASK: ::c_int = 4; pub const NFQA_CFG_FLAGS: ::c_int = 5; pub const NFQA_CFG_F_FAIL_OPEN: ::c_int = 0x0001; pub const NFQA_CFG_F_CONNTRACK: ::c_int = 0x0002; pub const NFQA_CFG_F_GSO: ::c_int = 0x0004; pub const NFQA_CFG_F_UID_GID: ::c_int = 0x0008; pub const NFQA_CFG_F_SECCTX: ::c_int = 0x0010; pub const NFQA_CFG_F_MAX: ::c_int = 0x0020; pub const NFQA_SKB_CSUMNOTREADY: ::c_int = 0x0001; pub const NFQA_SKB_GSO: ::c_int = 0x0002; pub const NFQA_SKB_CSUM_NOTVERIFIED: ::c_int = 0x0004; pub const GENL_NAMSIZ: ::c_int = 16; pub const GENL_MIN_ID: ::c_int = NLMSG_MIN_TYPE; pub const GENL_MAX_ID: ::c_int = 1023; pub const GENL_ADMIN_PERM: ::c_int = 0x01; pub const GENL_CMD_CAP_DO: ::c_int = 0x02; pub const GENL_CMD_CAP_DUMP: ::c_int = 0x04; pub const GENL_CMD_CAP_HASPOL: ::c_int = 0x08; pub const GENL_UNS_ADMIN_PERM: ::c_int = 0x10; pub const GENL_ID_CTRL: ::c_int = NLMSG_MIN_TYPE; pub const GENL_ID_VFS_DQUOT: ::c_int = NLMSG_MIN_TYPE + 1; pub const GENL_ID_PMCRAID: ::c_int = NLMSG_MIN_TYPE + 2; pub const CTRL_CMD_UNSPEC: ::c_int = 0; pub const CTRL_CMD_NEWFAMILY: ::c_int = 1; pub const CTRL_CMD_DELFAMILY: ::c_int = 2; pub const CTRL_CMD_GETFAMILY: ::c_int = 3; pub const CTRL_CMD_NEWOPS: ::c_int = 4; pub const CTRL_CMD_DELOPS: ::c_int = 5; pub const CTRL_CMD_GETOPS: ::c_int = 6; pub const CTRL_CMD_NEWMCAST_GRP: ::c_int = 7; pub const CTRL_CMD_DELMCAST_GRP: ::c_int = 8; pub const CTRL_CMD_GETMCAST_GRP: ::c_int = 9; pub const CTRL_ATTR_UNSPEC: ::c_int = 0; pub const CTRL_ATTR_FAMILY_ID: ::c_int = 1; pub const CTRL_ATTR_FAMILY_NAME: ::c_int = 2; pub const CTRL_ATTR_VERSION: ::c_int = 3; pub const CTRL_ATTR_HDRSIZE: ::c_int = 4; pub const CTRL_ATTR_MAXATTR: ::c_int = 5; pub const CTRL_ATTR_OPS: ::c_int = 6; pub const CTRL_ATTR_MCAST_GROUPS: ::c_int = 7; pub const CTRL_ATTR_OP_UNSPEC: ::c_int = 0; pub const CTRL_ATTR_OP_ID: ::c_int = 1; pub const CTRL_ATTR_OP_FLAGS: ::c_int = 2; pub const CTRL_ATTR_MCAST_GRP_UNSPEC: ::c_int = 0; pub const CTRL_ATTR_MCAST_GRP_NAME: ::c_int = 1; pub const CTRL_ATTR_MCAST_GRP_ID: ::c_int = 2; pub const NETLINK_ADD_MEMBERSHIP: ::c_int = 1; pub const NETLINK_DROP_MEMBERSHIP: ::c_int = 2; pub const NETLINK_PKTINFO: ::c_int = 3; pub const NETLINK_BROADCAST_ERROR: ::c_int = 4; pub const NETLINK_NO_ENOBUFS: ::c_int = 5; pub const NETLINK_RX_RING: ::c_int = 6; pub const NETLINK_TX_RING: ::c_int = 7; pub const NETLINK_LISTEN_ALL_NSID: ::c_int = 8; pub const NETLINK_LIST_MEMBERSHIPS: ::c_int = 9; pub const NETLINK_CAP_ACK: ::c_int = 10; pub const NETLINK_EXT_ACK: ::c_int = 11; pub const NETLINK_GET_STRICT_CHK: ::c_int = 12; pub const GRND_NONBLOCK: ::c_uint = 0x0001; pub const GRND_RANDOM: ::c_uint = 0x0002; pub const GRND_INSECURE: ::c_uint = 0x0004; pub const SECCOMP_MODE_DISABLED: ::c_uint = 0; pub const SECCOMP_MODE_STRICT: ::c_uint = 1; pub const SECCOMP_MODE_FILTER: ::c_uint = 2; pub const SECCOMP_FILTER_FLAG_TSYNC: ::c_ulong = 1; pub const SECCOMP_FILTER_FLAG_LOG: ::c_ulong = 2; pub const SECCOMP_FILTER_FLAG_SPEC_ALLOW: ::c_ulong = 4; pub const SECCOMP_FILTER_FLAG_NEW_LISTENER: ::c_ulong = 8; pub const SECCOMP_RET_ACTION_FULL: ::c_uint = 0xffff0000; pub const SECCOMP_RET_ACTION: ::c_uint = 0x7fff0000; pub const SECCOMP_RET_DATA: ::c_uint = 0x0000ffff; pub const SECCOMP_RET_KILL_PROCESS: ::c_uint = 0x80000000; pub const SECCOMP_RET_KILL_THREAD: ::c_uint = 0x00000000; pub const SECCOMP_RET_KILL: ::c_uint = SECCOMP_RET_KILL_THREAD; pub const SECCOMP_RET_TRAP: ::c_uint = 0x00030000; pub const SECCOMP_RET_ERRNO: ::c_uint = 0x00050000; pub const SECCOMP_RET_USER_NOTIF: ::c_uint = 0x7fc00000; pub const SECCOMP_RET_TRACE: ::c_uint = 0x7ff00000; pub const SECCOMP_RET_LOG: ::c_uint = 0x7ffc0000; pub const SECCOMP_RET_ALLOW: ::c_uint = 0x7fff0000; pub const NLA_F_NESTED: ::c_int = 1 << 15; pub const NLA_F_NET_BYTEORDER: ::c_int = 1 << 14; pub const NLA_TYPE_MASK: ::c_int = !(NLA_F_NESTED | NLA_F_NET_BYTEORDER); pub const NLA_ALIGNTO: ::c_int = 4; pub const SIGEV_THREAD_ID: ::c_int = 4; pub const CIBAUD: ::tcflag_t = 0o02003600000; pub const CBAUDEX: ::tcflag_t = 0o010000; pub const TIOCM_LE: ::c_int = 0x001; pub const TIOCM_DTR: ::c_int = 0x002; pub const TIOCM_RTS: ::c_int = 0x004; pub const TIOCM_ST: ::c_int = 0x008; pub const TIOCM_SR: ::c_int = 0x010; pub const TIOCM_CTS: ::c_int = 0x020; pub const TIOCM_CAR: ::c_int = 0x040; pub const TIOCM_RNG: ::c_int = 0x080; pub const TIOCM_DSR: ::c_int = 0x100; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; pub const SFD_CLOEXEC: ::c_int = O_CLOEXEC; pub const SFD_NONBLOCK: ::c_int = O_NONBLOCK; pub const SOCK_NONBLOCK: ::c_int = O_NONBLOCK; pub const SO_ORIGINAL_DST: ::c_int = 80; pub const IP_RECVFRAGSIZE: ::c_int = 25; pub const IPV6_FLOWINFO: ::c_int = 11; pub const IPV6_MULTICAST_ALL: ::c_int = 29; pub const IPV6_ROUTER_ALERT_ISOLATE: ::c_int = 30; pub const IPV6_FLOWLABEL_MGR: ::c_int = 32; pub const IPV6_FLOWINFO_SEND: ::c_int = 33; pub const IPV6_RECVFRAGSIZE: ::c_int = 77; pub const IPV6_FREEBIND: ::c_int = 78; pub const IPV6_FLOWINFO_FLOWLABEL: ::c_int = 0x000fffff; pub const IPV6_FLOWINFO_PRIORITY: ::c_int = 0x0ff00000; pub const IUTF8: ::tcflag_t = 0x00004000; pub const CMSPAR: ::tcflag_t = 0o10000000000; pub const O_TMPFILE: ::c_int = 0o20000000 | O_DIRECTORY; pub const MFD_CLOEXEC: ::c_uint = 0x0001; pub const MFD_ALLOW_SEALING: ::c_uint = 0x0002; pub const MFD_HUGETLB: ::c_uint = 0x0004; pub const MFD_NOEXEC_SEAL: ::c_uint = 0x0008; pub const MFD_EXEC: ::c_uint = 0x0010; pub const MFD_HUGE_64KB: ::c_uint = 0x40000000; pub const MFD_HUGE_512KB: ::c_uint = 0x4c000000; pub const MFD_HUGE_1MB: ::c_uint = 0x50000000; pub const MFD_HUGE_2MB: ::c_uint = 0x54000000; pub const MFD_HUGE_8MB: ::c_uint = 0x5c000000; pub const MFD_HUGE_16MB: ::c_uint = 0x60000000; pub const MFD_HUGE_32MB: ::c_uint = 0x64000000; pub const MFD_HUGE_256MB: ::c_uint = 0x70000000; pub const MFD_HUGE_512MB: ::c_uint = 0x74000000; pub const MFD_HUGE_1GB: ::c_uint = 0x78000000; pub const MFD_HUGE_2GB: ::c_uint = 0x7c000000; pub const MFD_HUGE_16GB: ::c_uint = 0x88000000; pub const MFD_HUGE_MASK: ::c_uint = 63; pub const MFD_HUGE_SHIFT: ::c_uint = 26; // these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has // the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32 // so we can use that type here to avoid having to cast. pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_LOOS: u32 = 0x60000000; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_STACK: u32 = 0x6474e551; pub const PT_GNU_RELRO: u32 = 0x6474e552; pub const PT_HIOS: u32 = 0x6fffffff; pub const PT_LOPROC: u32 = 0x70000000; pub const PT_HIPROC: u32 = 0x7fffffff; // uapi/linux/mount.h pub const OPEN_TREE_CLONE: ::c_uint = 0x01; pub const OPEN_TREE_CLOEXEC: ::c_uint = O_CLOEXEC as ::c_uint; // linux/netfilter.h pub const NF_DROP: ::c_int = 0; pub const NF_ACCEPT: ::c_int = 1; pub const NF_STOLEN: ::c_int = 2; pub const NF_QUEUE: ::c_int = 3; pub const NF_REPEAT: ::c_int = 4; pub const NF_STOP: ::c_int = 5; pub const NF_MAX_VERDICT: ::c_int = NF_STOP; pub const NF_VERDICT_MASK: ::c_int = 0x000000ff; pub const NF_VERDICT_FLAG_QUEUE_BYPASS: ::c_int = 0x00008000; pub const NF_VERDICT_QMASK: ::c_int = 0xffff0000; pub const NF_VERDICT_QBITS: ::c_int = 16; pub const NF_VERDICT_BITS: ::c_int = 16; pub const NF_INET_PRE_ROUTING: ::c_int = 0; pub const NF_INET_LOCAL_IN: ::c_int = 1; pub const NF_INET_FORWARD: ::c_int = 2; pub const NF_INET_LOCAL_OUT: ::c_int = 3; pub const NF_INET_POST_ROUTING: ::c_int = 4; pub const NF_INET_NUMHOOKS: ::c_int = 5; pub const NF_NETDEV_INGRESS: ::c_int = 0; pub const NF_NETDEV_NUMHOOKS: ::c_int = 1; pub const NFPROTO_UNSPEC: ::c_int = 0; pub const NFPROTO_INET: ::c_int = 1; pub const NFPROTO_IPV4: ::c_int = 2; pub const NFPROTO_ARP: ::c_int = 3; pub const NFPROTO_NETDEV: ::c_int = 5; pub const NFPROTO_BRIDGE: ::c_int = 7; pub const NFPROTO_IPV6: ::c_int = 10; pub const NFPROTO_DECNET: ::c_int = 12; pub const NFPROTO_NUMPROTO: ::c_int = 13; // linux/netfilter_ipv4.h pub const NF_IP_PRE_ROUTING: ::c_int = 0; pub const NF_IP_LOCAL_IN: ::c_int = 1; pub const NF_IP_FORWARD: ::c_int = 2; pub const NF_IP_LOCAL_OUT: ::c_int = 3; pub const NF_IP_POST_ROUTING: ::c_int = 4; pub const NF_IP_NUMHOOKS: ::c_int = 5; pub const NF_IP_PRI_FIRST: ::c_int = ::INT_MIN; pub const NF_IP_PRI_CONNTRACK_DEFRAG: ::c_int = -400; pub const NF_IP_PRI_RAW: ::c_int = -300; pub const NF_IP_PRI_SELINUX_FIRST: ::c_int = -225; pub const NF_IP_PRI_CONNTRACK: ::c_int = -200; pub const NF_IP_PRI_MANGLE: ::c_int = -150; pub const NF_IP_PRI_NAT_DST: ::c_int = -100; pub const NF_IP_PRI_FILTER: ::c_int = 0; pub const NF_IP_PRI_SECURITY: ::c_int = 50; pub const NF_IP_PRI_NAT_SRC: ::c_int = 100; pub const NF_IP_PRI_SELINUX_LAST: ::c_int = 225; pub const NF_IP_PRI_CONNTRACK_HELPER: ::c_int = 300; pub const NF_IP_PRI_CONNTRACK_CONFIRM: ::c_int = ::INT_MAX; pub const NF_IP_PRI_LAST: ::c_int = ::INT_MAX; // linux/netfilter_ipv6.h pub const NF_IP6_PRE_ROUTING: ::c_int = 0; pub const NF_IP6_LOCAL_IN: ::c_int = 1; pub const NF_IP6_FORWARD: ::c_int = 2; pub const NF_IP6_LOCAL_OUT: ::c_int = 3; pub const NF_IP6_POST_ROUTING: ::c_int = 4; pub const NF_IP6_NUMHOOKS: ::c_int = 5; pub const NF_IP6_PRI_FIRST: ::c_int = ::INT_MIN; pub const NF_IP6_PRI_CONNTRACK_DEFRAG: ::c_int = -400; pub const NF_IP6_PRI_RAW: ::c_int = -300; pub const NF_IP6_PRI_SELINUX_FIRST: ::c_int = -225; pub const NF_IP6_PRI_CONNTRACK: ::c_int = -200; pub const NF_IP6_PRI_MANGLE: ::c_int = -150; pub const NF_IP6_PRI_NAT_DST: ::c_int = -100; pub const NF_IP6_PRI_FILTER: ::c_int = 0; pub const NF_IP6_PRI_SECURITY: ::c_int = 50; pub const NF_IP6_PRI_NAT_SRC: ::c_int = 100; pub const NF_IP6_PRI_SELINUX_LAST: ::c_int = 225; pub const NF_IP6_PRI_CONNTRACK_HELPER: ::c_int = 300; pub const NF_IP6_PRI_LAST: ::c_int = ::INT_MAX; // linux/netfilter_ipv6/ip6_tables.h pub const IP6T_SO_ORIGINAL_DST: ::c_int = 80; // linux/netfilter/nf_tables.h pub const NFT_TABLE_MAXNAMELEN: ::c_int = 256; pub const NFT_CHAIN_MAXNAMELEN: ::c_int = 256; pub const NFT_SET_MAXNAMELEN: ::c_int = 256; pub const NFT_OBJ_MAXNAMELEN: ::c_int = 256; pub const NFT_USERDATA_MAXLEN: ::c_int = 256; pub const NFT_REG_VERDICT: ::c_int = 0; pub const NFT_REG_1: ::c_int = 1; pub const NFT_REG_2: ::c_int = 2; pub const NFT_REG_3: ::c_int = 3; pub const NFT_REG_4: ::c_int = 4; pub const __NFT_REG_MAX: ::c_int = 5; pub const NFT_REG32_00: ::c_int = 8; pub const NFT_REG32_01: ::c_int = 9; pub const NFT_REG32_02: ::c_int = 10; pub const NFT_REG32_03: ::c_int = 11; pub const NFT_REG32_04: ::c_int = 12; pub const NFT_REG32_05: ::c_int = 13; pub const NFT_REG32_06: ::c_int = 14; pub const NFT_REG32_07: ::c_int = 15; pub const NFT_REG32_08: ::c_int = 16; pub const NFT_REG32_09: ::c_int = 17; pub const NFT_REG32_10: ::c_int = 18; pub const NFT_REG32_11: ::c_int = 19; pub const NFT_REG32_12: ::c_int = 20; pub const NFT_REG32_13: ::c_int = 21; pub const NFT_REG32_14: ::c_int = 22; pub const NFT_REG32_15: ::c_int = 23; pub const NFT_REG_SIZE: ::c_int = 16; pub const NFT_REG32_SIZE: ::c_int = 4; pub const NFT_CONTINUE: ::c_int = -1; pub const NFT_BREAK: ::c_int = -2; pub const NFT_JUMP: ::c_int = -3; pub const NFT_GOTO: ::c_int = -4; pub const NFT_RETURN: ::c_int = -5; pub const NFT_MSG_NEWTABLE: ::c_int = 0; pub const NFT_MSG_GETTABLE: ::c_int = 1; pub const NFT_MSG_DELTABLE: ::c_int = 2; pub const NFT_MSG_NEWCHAIN: ::c_int = 3; pub const NFT_MSG_GETCHAIN: ::c_int = 4; pub const NFT_MSG_DELCHAIN: ::c_int = 5; pub const NFT_MSG_NEWRULE: ::c_int = 6; pub const NFT_MSG_GETRULE: ::c_int = 7; pub const NFT_MSG_DELRULE: ::c_int = 8; pub const NFT_MSG_NEWSET: ::c_int = 9; pub const NFT_MSG_GETSET: ::c_int = 10; pub const NFT_MSG_DELSET: ::c_int = 11; pub const NFT_MSG_NEWSETELEM: ::c_int = 12; pub const NFT_MSG_GETSETELEM: ::c_int = 13; pub const NFT_MSG_DELSETELEM: ::c_int = 14; pub const NFT_MSG_NEWGEN: ::c_int = 15; pub const NFT_MSG_GETGEN: ::c_int = 16; pub const NFT_MSG_TRACE: ::c_int = 17; pub const NFT_MSG_NEWOBJ: ::c_int = 18; pub const NFT_MSG_GETOBJ: ::c_int = 19; pub const NFT_MSG_DELOBJ: ::c_int = 20; pub const NFT_MSG_GETOBJ_RESET: ::c_int = 21; pub const NFT_MSG_MAX: ::c_int = 25; pub const NFT_SET_ANONYMOUS: ::c_int = 0x1; pub const NFT_SET_CONSTANT: ::c_int = 0x2; pub const NFT_SET_INTERVAL: ::c_int = 0x4; pub const NFT_SET_MAP: ::c_int = 0x8; pub const NFT_SET_TIMEOUT: ::c_int = 0x10; pub const NFT_SET_EVAL: ::c_int = 0x20; pub const NFT_SET_POL_PERFORMANCE: ::c_int = 0; pub const NFT_SET_POL_MEMORY: ::c_int = 1; pub const NFT_SET_ELEM_INTERVAL_END: ::c_int = 0x1; pub const NFT_DATA_VALUE: ::c_uint = 0; pub const NFT_DATA_VERDICT: ::c_uint = 0xffffff00; pub const NFT_DATA_RESERVED_MASK: ::c_uint = 0xffffff00; pub const NFT_DATA_VALUE_MAXLEN: ::c_int = 64; pub const NFT_BYTEORDER_NTOH: ::c_int = 0; pub const NFT_BYTEORDER_HTON: ::c_int = 1; pub const NFT_CMP_EQ: ::c_int = 0; pub const NFT_CMP_NEQ: ::c_int = 1; pub const NFT_CMP_LT: ::c_int = 2; pub const NFT_CMP_LTE: ::c_int = 3; pub const NFT_CMP_GT: ::c_int = 4; pub const NFT_CMP_GTE: ::c_int = 5; pub const NFT_RANGE_EQ: ::c_int = 0; pub const NFT_RANGE_NEQ: ::c_int = 1; pub const NFT_LOOKUP_F_INV: ::c_int = 1 << 0; pub const NFT_DYNSET_OP_ADD: ::c_int = 0; pub const NFT_DYNSET_OP_UPDATE: ::c_int = 1; pub const NFT_DYNSET_F_INV: ::c_int = 1 << 0; pub const NFT_PAYLOAD_LL_HEADER: ::c_int = 0; pub const NFT_PAYLOAD_NETWORK_HEADER: ::c_int = 1; pub const NFT_PAYLOAD_TRANSPORT_HEADER: ::c_int = 2; pub const NFT_PAYLOAD_CSUM_NONE: ::c_int = 0; pub const NFT_PAYLOAD_CSUM_INET: ::c_int = 1; pub const NFT_META_LEN: ::c_int = 0; pub const NFT_META_PROTOCOL: ::c_int = 1; pub const NFT_META_PRIORITY: ::c_int = 2; pub const NFT_META_MARK: ::c_int = 3; pub const NFT_META_IIF: ::c_int = 4; pub const NFT_META_OIF: ::c_int = 5; pub const NFT_META_IIFNAME: ::c_int = 6; pub const NFT_META_OIFNAME: ::c_int = 7; pub const NFT_META_IIFTYPE: ::c_int = 8; pub const NFT_META_OIFTYPE: ::c_int = 9; pub const NFT_META_SKUID: ::c_int = 10; pub const NFT_META_SKGID: ::c_int = 11; pub const NFT_META_NFTRACE: ::c_int = 12; pub const NFT_META_RTCLASSID: ::c_int = 13; pub const NFT_META_SECMARK: ::c_int = 14; pub const NFT_META_NFPROTO: ::c_int = 15; pub const NFT_META_L4PROTO: ::c_int = 16; pub const NFT_META_BRI_IIFNAME: ::c_int = 17; pub const NFT_META_BRI_OIFNAME: ::c_int = 18; pub const NFT_META_PKTTYPE: ::c_int = 19; pub const NFT_META_CPU: ::c_int = 20; pub const NFT_META_IIFGROUP: ::c_int = 21; pub const NFT_META_OIFGROUP: ::c_int = 22; pub const NFT_META_CGROUP: ::c_int = 23; pub const NFT_META_PRANDOM: ::c_int = 24; pub const NFT_CT_STATE: ::c_int = 0; pub const NFT_CT_DIRECTION: ::c_int = 1; pub const NFT_CT_STATUS: ::c_int = 2; pub const NFT_CT_MARK: ::c_int = 3; pub const NFT_CT_SECMARK: ::c_int = 4; pub const NFT_CT_EXPIRATION: ::c_int = 5; pub const NFT_CT_HELPER: ::c_int = 6; pub const NFT_CT_L3PROTOCOL: ::c_int = 7; pub const NFT_CT_SRC: ::c_int = 8; pub const NFT_CT_DST: ::c_int = 9; pub const NFT_CT_PROTOCOL: ::c_int = 10; pub const NFT_CT_PROTO_SRC: ::c_int = 11; pub const NFT_CT_PROTO_DST: ::c_int = 12; pub const NFT_CT_LABELS: ::c_int = 13; pub const NFT_CT_PKTS: ::c_int = 14; pub const NFT_CT_BYTES: ::c_int = 15; pub const NFT_LIMIT_PKTS: ::c_int = 0; pub const NFT_LIMIT_PKT_BYTES: ::c_int = 1; pub const NFT_LIMIT_F_INV: ::c_int = 1 << 0; pub const NFT_QUEUE_FLAG_BYPASS: ::c_int = 0x01; pub const NFT_QUEUE_FLAG_CPU_FANOUT: ::c_int = 0x02; pub const NFT_QUEUE_FLAG_MASK: ::c_int = 0x03; pub const NFT_QUOTA_F_INV: ::c_int = 1 << 0; pub const NFT_REJECT_ICMP_UNREACH: ::c_int = 0; pub const NFT_REJECT_TCP_RST: ::c_int = 1; pub const NFT_REJECT_ICMPX_UNREACH: ::c_int = 2; pub const NFT_REJECT_ICMPX_NO_ROUTE: ::c_int = 0; pub const NFT_REJECT_ICMPX_PORT_UNREACH: ::c_int = 1; pub const NFT_REJECT_ICMPX_HOST_UNREACH: ::c_int = 2; pub const NFT_REJECT_ICMPX_ADMIN_PROHIBITED: ::c_int = 3; pub const NFT_NAT_SNAT: ::c_int = 0; pub const NFT_NAT_DNAT: ::c_int = 1; pub const NFT_TRACETYPE_UNSPEC: ::c_int = 0; pub const NFT_TRACETYPE_POLICY: ::c_int = 1; pub const NFT_TRACETYPE_RETURN: ::c_int = 2; pub const NFT_TRACETYPE_RULE: ::c_int = 3; pub const NFT_NG_INCREMENTAL: ::c_int = 0; pub const NFT_NG_RANDOM: ::c_int = 1; // linux/input.h pub const FF_MAX: ::__u16 = 0x7f; pub const FF_CNT: usize = FF_MAX as usize + 1; // linux/input-event-codes.h pub const INPUT_PROP_MAX: ::__u16 = 0x1f; pub const INPUT_PROP_CNT: usize = INPUT_PROP_MAX as usize + 1; pub const EV_MAX: ::__u16 = 0x1f; pub const EV_CNT: usize = EV_MAX as usize + 1; pub const SYN_MAX: ::__u16 = 0xf; pub const SYN_CNT: usize = SYN_MAX as usize + 1; pub const KEY_MAX: ::__u16 = 0x2ff; pub const KEY_CNT: usize = KEY_MAX as usize + 1; pub const REL_MAX: ::__u16 = 0x0f; pub const REL_CNT: usize = REL_MAX as usize + 1; pub const ABS_MAX: ::__u16 = 0x3f; pub const ABS_CNT: usize = ABS_MAX as usize + 1; pub const SW_MAX: ::__u16 = 0x0f; pub const SW_CNT: usize = SW_MAX as usize + 1; pub const MSC_MAX: ::__u16 = 0x07; pub const MSC_CNT: usize = MSC_MAX as usize + 1; pub const LED_MAX: ::__u16 = 0x0f; pub const LED_CNT: usize = LED_MAX as usize + 1; pub const REP_MAX: ::__u16 = 0x01; pub const REP_CNT: usize = REP_MAX as usize + 1; pub const SND_MAX: ::__u16 = 0x07; pub const SND_CNT: usize = SND_MAX as usize + 1; // linux/uinput.h pub const UINPUT_VERSION: ::c_uint = 5; pub const UINPUT_MAX_NAME_SIZE: usize = 80; // bionic/libc/kernel/uapi/linux/if_tun.h pub const IFF_TUN: ::c_int = 0x0001; pub const IFF_TAP: ::c_int = 0x0002; pub const IFF_NAPI: ::c_int = 0x0010; pub const IFF_NAPI_FRAGS: ::c_int = 0x0020; pub const IFF_NO_CARRIER: ::c_int = 0x0040; pub const IFF_NO_PI: ::c_int = 0x1000; pub const IFF_ONE_QUEUE: ::c_int = 0x2000; pub const IFF_VNET_HDR: ::c_int = 0x4000; pub const IFF_TUN_EXCL: ::c_int = 0x8000; pub const IFF_MULTI_QUEUE: ::c_int = 0x0100; pub const IFF_ATTACH_QUEUE: ::c_int = 0x0200; pub const IFF_DETACH_QUEUE: ::c_int = 0x0400; pub const IFF_PERSIST: ::c_int = 0x0800; pub const IFF_NOFILTER: ::c_int = 0x1000; // Features for GSO (TUNSETOFFLOAD) pub const TUN_F_CSUM: ::c_uint = 0x01; pub const TUN_F_TSO4: ::c_uint = 0x02; pub const TUN_F_TSO6: ::c_uint = 0x04; pub const TUN_F_TSO_ECN: ::c_uint = 0x08; pub const TUN_F_UFO: ::c_uint = 0x10; pub const TUN_F_USO4: ::c_uint = 0x20; pub const TUN_F_USO6: ::c_uint = 0x40; // start android/platform/bionic/libc/kernel/uapi/linux/if_ether.h // from https://android.googlesource.com/platform/bionic/+/HEAD/libc/kernel/uapi/linux/if_ether.h pub const ETH_ALEN: ::c_int = 6; pub const ETH_HLEN: ::c_int = 14; pub const ETH_ZLEN: ::c_int = 60; pub const ETH_DATA_LEN: ::c_int = 1500; pub const ETH_FRAME_LEN: ::c_int = 1514; pub const ETH_FCS_LEN: ::c_int = 4; pub const ETH_MIN_MTU: ::c_int = 68; pub const ETH_MAX_MTU: ::c_int = 0xFFFF; pub const ETH_P_LOOP: ::c_int = 0x0060; pub const ETH_P_PUP: ::c_int = 0x0200; pub const ETH_P_PUPAT: ::c_int = 0x0201; pub const ETH_P_TSN: ::c_int = 0x22F0; pub const ETH_P_IP: ::c_int = 0x0800; pub const ETH_P_X25: ::c_int = 0x0805; pub const ETH_P_ARP: ::c_int = 0x0806; pub const ETH_P_BPQ: ::c_int = 0x08FF; pub const ETH_P_IEEEPUP: ::c_int = 0x0a00; pub const ETH_P_IEEEPUPAT: ::c_int = 0x0a01; pub const ETH_P_BATMAN: ::c_int = 0x4305; pub const ETH_P_DEC: ::c_int = 0x6000; pub const ETH_P_DNA_DL: ::c_int = 0x6001; pub const ETH_P_DNA_RC: ::c_int = 0x6002; pub const ETH_P_DNA_RT: ::c_int = 0x6003; pub const ETH_P_LAT: ::c_int = 0x6004; pub const ETH_P_DIAG: ::c_int = 0x6005; pub const ETH_P_CUST: ::c_int = 0x6006; pub const ETH_P_SCA: ::c_int = 0x6007; pub const ETH_P_TEB: ::c_int = 0x6558; pub const ETH_P_RARP: ::c_int = 0x8035; pub const ETH_P_ATALK: ::c_int = 0x809B; pub const ETH_P_AARP: ::c_int = 0x80F3; pub const ETH_P_8021Q: ::c_int = 0x8100; /* see rust-lang/libc#924 pub const ETH_P_ERSPAN: ::c_int = 0x88BE;*/ pub const ETH_P_IPX: ::c_int = 0x8137; pub const ETH_P_IPV6: ::c_int = 0x86DD; pub const ETH_P_PAUSE: ::c_int = 0x8808; pub const ETH_P_SLOW: ::c_int = 0x8809; pub const ETH_P_WCCP: ::c_int = 0x883E; pub const ETH_P_MPLS_UC: ::c_int = 0x8847; pub const ETH_P_MPLS_MC: ::c_int = 0x8848; pub const ETH_P_ATMMPOA: ::c_int = 0x884c; pub const ETH_P_PPP_DISC: ::c_int = 0x8863; pub const ETH_P_PPP_SES: ::c_int = 0x8864; pub const ETH_P_LINK_CTL: ::c_int = 0x886c; pub const ETH_P_ATMFATE: ::c_int = 0x8884; pub const ETH_P_PAE: ::c_int = 0x888E; pub const ETH_P_AOE: ::c_int = 0x88A2; pub const ETH_P_8021AD: ::c_int = 0x88A8; pub const ETH_P_802_EX1: ::c_int = 0x88B5; pub const ETH_P_TIPC: ::c_int = 0x88CA; pub const ETH_P_MACSEC: ::c_int = 0x88E5; pub const ETH_P_8021AH: ::c_int = 0x88E7; pub const ETH_P_MVRP: ::c_int = 0x88F5; pub const ETH_P_1588: ::c_int = 0x88F7; pub const ETH_P_NCSI: ::c_int = 0x88F8; pub const ETH_P_PRP: ::c_int = 0x88FB; pub const ETH_P_FCOE: ::c_int = 0x8906; /* see rust-lang/libc#924 pub const ETH_P_IBOE: ::c_int = 0x8915;*/ pub const ETH_P_TDLS: ::c_int = 0x890D; pub const ETH_P_FIP: ::c_int = 0x8914; pub const ETH_P_80221: ::c_int = 0x8917; pub const ETH_P_HSR: ::c_int = 0x892F; /* see rust-lang/libc#924 pub const ETH_P_NSH: ::c_int = 0x894F;*/ pub const ETH_P_LOOPBACK: ::c_int = 0x9000; pub const ETH_P_QINQ1: ::c_int = 0x9100; pub const ETH_P_QINQ2: ::c_int = 0x9200; pub const ETH_P_QINQ3: ::c_int = 0x9300; pub const ETH_P_EDSA: ::c_int = 0xDADA; /* see rust-lang/libc#924 pub const ETH_P_IFE: ::c_int = 0xED3E;*/ pub const ETH_P_AF_IUCV: ::c_int = 0xFBFB; pub const ETH_P_802_3_MIN: ::c_int = 0x0600; pub const ETH_P_802_3: ::c_int = 0x0001; pub const ETH_P_AX25: ::c_int = 0x0002; pub const ETH_P_ALL: ::c_int = 0x0003; pub const ETH_P_802_2: ::c_int = 0x0004; pub const ETH_P_SNAP: ::c_int = 0x0005; pub const ETH_P_DDCMP: ::c_int = 0x0006; pub const ETH_P_WAN_PPP: ::c_int = 0x0007; pub const ETH_P_PPP_MP: ::c_int = 0x0008; pub const ETH_P_LOCALTALK: ::c_int = 0x0009; pub const ETH_P_CAN: ::c_int = 0x000C; pub const ETH_P_CANFD: ::c_int = 0x000D; pub const ETH_P_PPPTALK: ::c_int = 0x0010; pub const ETH_P_TR_802_2: ::c_int = 0x0011; pub const ETH_P_MOBITEX: ::c_int = 0x0015; pub const ETH_P_CONTROL: ::c_int = 0x0016; pub const ETH_P_IRDA: ::c_int = 0x0017; pub const ETH_P_ECONET: ::c_int = 0x0018; pub const ETH_P_HDLC: ::c_int = 0x0019; pub const ETH_P_ARCNET: ::c_int = 0x001A; pub const ETH_P_DSA: ::c_int = 0x001B; pub const ETH_P_TRAILER: ::c_int = 0x001C; pub const ETH_P_PHONET: ::c_int = 0x00F5; pub const ETH_P_IEEE802154: ::c_int = 0x00F6; pub const ETH_P_CAIF: ::c_int = 0x00F7; pub const ETH_P_XDSA: ::c_int = 0x00F8; /* see rust-lang/libc#924 pub const ETH_P_MAP: ::c_int = 0x00F9;*/ // end android/platform/bionic/libc/kernel/uapi/linux/if_ether.h // start android/platform/bionic/libc/kernel/uapi/linux/neighbour.h pub const NDA_UNSPEC: ::c_ushort = 0; pub const NDA_DST: ::c_ushort = 1; pub const NDA_LLADDR: ::c_ushort = 2; pub const NDA_CACHEINFO: ::c_ushort = 3; pub const NDA_PROBES: ::c_ushort = 4; pub const NDA_VLAN: ::c_ushort = 5; pub const NDA_PORT: ::c_ushort = 6; pub const NDA_VNI: ::c_ushort = 7; pub const NDA_IFINDEX: ::c_ushort = 8; pub const NDA_MASTER: ::c_ushort = 9; pub const NDA_LINK_NETNSID: ::c_ushort = 10; pub const NDA_SRC_VNI: ::c_ushort = 11; pub const NDA_PROTOCOL: ::c_ushort = 12; pub const NDA_NH_ID: ::c_ushort = 13; pub const NDA_FDB_EXT_ATTRS: ::c_ushort = 14; pub const NDA_FLAGS_EXT: ::c_ushort = 15; pub const NDA_NDM_STATE_MASK: ::c_ushort = 16; pub const NDA_NDM_FLAGS_MASK: ::c_ushort = 17; pub const NTF_USE: u8 = 0x01; pub const NTF_SELF: u8 = 0x02; pub const NTF_MASTER: u8 = 0x04; pub const NTF_PROXY: u8 = 0x08; pub const NTF_EXT_LEARNED: u8 = 0x10; pub const NTF_OFFLOADED: u8 = 0x20; pub const NTF_STICKY: u8 = 0x40; pub const NTF_ROUTER: u8 = 0x80; pub const NTF_EXT_MANAGED: u8 = 0x01; pub const NTF_EXT_LOCKED: u8 = 0x02; pub const NUD_NONE: u16 = 0x00; pub const NUD_INCOMPLETE: u16 = 0x01; pub const NUD_REACHABLE: u16 = 0x02; pub const NUD_STALE: u16 = 0x04; pub const NUD_DELAY: u16 = 0x08; pub const NUD_PROBE: u16 = 0x10; pub const NUD_FAILED: u16 = 0x20; pub const NUD_NOARP: u16 = 0x40; pub const NUD_PERMANENT: u16 = 0x80; pub const NDTPA_UNSPEC: ::c_ushort = 0; pub const NDTPA_IFINDEX: ::c_ushort = 1; pub const NDTPA_REFCNT: ::c_ushort = 2; pub const NDTPA_REACHABLE_TIME: ::c_ushort = 3; pub const NDTPA_BASE_REACHABLE_TIME: ::c_ushort = 4; pub const NDTPA_RETRANS_TIME: ::c_ushort = 5; pub const NDTPA_GC_STALETIME: ::c_ushort = 6; pub const NDTPA_DELAY_PROBE_TIME: ::c_ushort = 7; pub const NDTPA_QUEUE_LEN: ::c_ushort = 8; pub const NDTPA_APP_PROBES: ::c_ushort = 9; pub const NDTPA_UCAST_PROBES: ::c_ushort = 10; pub const NDTPA_MCAST_PROBES: ::c_ushort = 11; pub const NDTPA_ANYCAST_DELAY: ::c_ushort = 12; pub const NDTPA_PROXY_DELAY: ::c_ushort = 13; pub const NDTPA_PROXY_QLEN: ::c_ushort = 14; pub const NDTPA_LOCKTIME: ::c_ushort = 15; pub const NDTPA_QUEUE_LENBYTES: ::c_ushort = 16; pub const NDTPA_MCAST_REPROBES: ::c_ushort = 17; pub const NDTPA_PAD: ::c_ushort = 18; pub const NDTPA_INTERVAL_PROBE_TIME_MS: ::c_ushort = 19; pub const NDTA_UNSPEC: ::c_ushort = 0; pub const NDTA_NAME: ::c_ushort = 1; pub const NDTA_THRESH1: ::c_ushort = 2; pub const NDTA_THRESH2: ::c_ushort = 3; pub const NDTA_THRESH3: ::c_ushort = 4; pub const NDTA_CONFIG: ::c_ushort = 5; pub const NDTA_PARMS: ::c_ushort = 6; pub const NDTA_STATS: ::c_ushort = 7; pub const NDTA_GC_INTERVAL: ::c_ushort = 8; pub const NDTA_PAD: ::c_ushort = 9; pub const FDB_NOTIFY_BIT: u16 = 0x01; pub const FDB_NOTIFY_INACTIVE_BIT: u16 = 0x02; pub const NFEA_UNSPEC: ::c_ushort = 0; pub const NFEA_ACTIVITY_NOTIFY: ::c_ushort = 1; pub const NFEA_DONT_REFRESH: ::c_ushort = 2; // end android/platform/bionic/libc/kernel/uapi/linux/neighbour.h pub const SIOCADDRT: ::c_ulong = 0x0000890B; pub const SIOCDELRT: ::c_ulong = 0x0000890C; pub const SIOCRTMSG: ::c_ulong = 0x0000890D; pub const SIOCGIFNAME: ::c_ulong = 0x00008910; pub const SIOCSIFLINK: ::c_ulong = 0x00008911; pub const SIOCGIFCONF: ::c_ulong = 0x00008912; pub const SIOCGIFFLAGS: ::c_ulong = 0x00008913; pub const SIOCSIFFLAGS: ::c_ulong = 0x00008914; pub const SIOCGIFADDR: ::c_ulong = 0x00008915; pub const SIOCSIFADDR: ::c_ulong = 0x00008916; pub const SIOCGIFDSTADDR: ::c_ulong = 0x00008917; pub const SIOCSIFDSTADDR: ::c_ulong = 0x00008918; pub const SIOCGIFBRDADDR: ::c_ulong = 0x00008919; pub const SIOCSIFBRDADDR: ::c_ulong = 0x0000891A; pub const SIOCGIFNETMASK: ::c_ulong = 0x0000891B; pub const SIOCSIFNETMASK: ::c_ulong = 0x0000891C; pub const SIOCGIFMETRIC: ::c_ulong = 0x0000891D; pub const SIOCSIFMETRIC: ::c_ulong = 0x0000891E; pub const SIOCGIFMEM: ::c_ulong = 0x0000891F; pub const SIOCSIFMEM: ::c_ulong = 0x00008920; pub const SIOCGIFMTU: ::c_ulong = 0x00008921; pub const SIOCSIFMTU: ::c_ulong = 0x00008922; pub const SIOCSIFNAME: ::c_ulong = 0x00008923; pub const SIOCSIFHWADDR: ::c_ulong = 0x00008924; pub const SIOCGIFENCAP: ::c_ulong = 0x00008925; pub const SIOCSIFENCAP: ::c_ulong = 0x00008926; pub const SIOCGIFHWADDR: ::c_ulong = 0x00008927; pub const SIOCGIFSLAVE: ::c_ulong = 0x00008929; pub const SIOCSIFSLAVE: ::c_ulong = 0x00008930; pub const SIOCADDMULTI: ::c_ulong = 0x00008931; pub const SIOCDELMULTI: ::c_ulong = 0x00008932; pub const SIOCGIFINDEX: ::c_ulong = 0x00008933; pub const SIOGIFINDEX: ::c_ulong = SIOCGIFINDEX; pub const SIOCSIFPFLAGS: ::c_ulong = 0x00008934; pub const SIOCGIFPFLAGS: ::c_ulong = 0x00008935; pub const SIOCDIFADDR: ::c_ulong = 0x00008936; pub const SIOCSIFHWBROADCAST: ::c_ulong = 0x00008937; pub const SIOCGIFCOUNT: ::c_ulong = 0x00008938; pub const SIOCGIFBR: ::c_ulong = 0x00008940; pub const SIOCSIFBR: ::c_ulong = 0x00008941; pub const SIOCGIFTXQLEN: ::c_ulong = 0x00008942; pub const SIOCSIFTXQLEN: ::c_ulong = 0x00008943; pub const SIOCETHTOOL: ::c_ulong = 0x00008946; pub const SIOCGMIIPHY: ::c_ulong = 0x00008947; pub const SIOCGMIIREG: ::c_ulong = 0x00008948; pub const SIOCSMIIREG: ::c_ulong = 0x00008949; pub const SIOCWANDEV: ::c_ulong = 0x0000894A; pub const SIOCOUTQNSD: ::c_ulong = 0x0000894B; pub const SIOCGSKNS: ::c_ulong = 0x0000894C; pub const SIOCDARP: ::c_ulong = 0x00008953; pub const SIOCGARP: ::c_ulong = 0x00008954; pub const SIOCSARP: ::c_ulong = 0x00008955; pub const SIOCDRARP: ::c_ulong = 0x00008960; pub const SIOCGRARP: ::c_ulong = 0x00008961; pub const SIOCSRARP: ::c_ulong = 0x00008962; pub const SIOCGIFMAP: ::c_ulong = 0x00008970; pub const SIOCSIFMAP: ::c_ulong = 0x00008971; pub const SIOCADDDLCI: ::c_ulong = 0x00008980; pub const SIOCDELDLCI: ::c_ulong = 0x00008981; pub const SIOCGIFVLAN: ::c_ulong = 0x00008982; pub const SIOCSIFVLAN: ::c_ulong = 0x00008983; pub const SIOCBONDENSLAVE: ::c_ulong = 0x00008990; pub const SIOCBONDRELEASE: ::c_ulong = 0x00008991; pub const SIOCBONDSETHWADDR: ::c_ulong = 0x00008992; pub const SIOCBONDSLAVEINFOQUERY: ::c_ulong = 0x00008993; pub const SIOCBONDINFOQUERY: ::c_ulong = 0x00008994; pub const SIOCBONDCHANGEACTIVE: ::c_ulong = 0x00008995; pub const SIOCBRADDBR: ::c_ulong = 0x000089a0; pub const SIOCBRDELBR: ::c_ulong = 0x000089a1; pub const SIOCBRADDIF: ::c_ulong = 0x000089a2; pub const SIOCBRDELIF: ::c_ulong = 0x000089a3; pub const SIOCSHWTSTAMP: ::c_ulong = 0x000089b0; pub const SIOCGHWTSTAMP: ::c_ulong = 0x000089b1; pub const SIOCDEVPRIVATE: ::c_ulong = 0x000089F0; pub const SIOCPROTOPRIVATE: ::c_ulong = 0x000089E0; // linux/module.h pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001; pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002; // linux/net_tstamp.h pub const SOF_TIMESTAMPING_TX_HARDWARE: ::c_uint = 1 << 0; pub const SOF_TIMESTAMPING_TX_SOFTWARE: ::c_uint = 1 << 1; pub const SOF_TIMESTAMPING_RX_HARDWARE: ::c_uint = 1 << 2; pub const SOF_TIMESTAMPING_RX_SOFTWARE: ::c_uint = 1 << 3; pub const SOF_TIMESTAMPING_SOFTWARE: ::c_uint = 1 << 4; pub const SOF_TIMESTAMPING_SYS_HARDWARE: ::c_uint = 1 << 5; pub const SOF_TIMESTAMPING_RAW_HARDWARE: ::c_uint = 1 << 6; pub const SOF_TIMESTAMPING_OPT_ID: ::c_uint = 1 << 7; pub const SOF_TIMESTAMPING_TX_SCHED: ::c_uint = 1 << 8; pub const SOF_TIMESTAMPING_TX_ACK: ::c_uint = 1 << 9; pub const SOF_TIMESTAMPING_OPT_CMSG: ::c_uint = 1 << 10; pub const SOF_TIMESTAMPING_OPT_TSONLY: ::c_uint = 1 << 11; pub const SOF_TIMESTAMPING_OPT_STATS: ::c_uint = 1 << 12; pub const SOF_TIMESTAMPING_OPT_PKTINFO: ::c_uint = 1 << 13; pub const SOF_TIMESTAMPING_OPT_TX_SWHW: ::c_uint = 1 << 14; #[deprecated( since = "0.2.55", note = "ENOATTR is not available on Android; use ENODATA instead" )] pub const ENOATTR: ::c_int = ::ENODATA; // linux/if_alg.h pub const ALG_SET_KEY: ::c_int = 1; pub const ALG_SET_IV: ::c_int = 2; pub const ALG_SET_OP: ::c_int = 3; pub const ALG_SET_AEAD_ASSOCLEN: ::c_int = 4; pub const ALG_SET_AEAD_AUTHSIZE: ::c_int = 5; pub const ALG_SET_DRBG_ENTROPY: ::c_int = 6; pub const ALG_OP_DECRYPT: ::c_int = 0; pub const ALG_OP_ENCRYPT: ::c_int = 1; // sys/mman.h pub const MLOCK_ONFAULT: ::c_int = 0x01; // uapi/linux/vm_sockets.h pub const VMADDR_CID_ANY: ::c_uint = 0xFFFFFFFF; pub const VMADDR_CID_HYPERVISOR: ::c_uint = 0; pub const VMADDR_CID_LOCAL: ::c_uint = 1; pub const VMADDR_CID_HOST: ::c_uint = 2; pub const VMADDR_PORT_ANY: ::c_uint = 0xFFFFFFFF; // uapi/linux/inotify.h pub const IN_ACCESS: u32 = 0x0000_0001; pub const IN_MODIFY: u32 = 0x0000_0002; pub const IN_ATTRIB: u32 = 0x0000_0004; pub const IN_CLOSE_WRITE: u32 = 0x0000_0008; pub const IN_CLOSE_NOWRITE: u32 = 0x0000_0010; pub const IN_CLOSE: u32 = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE; pub const IN_OPEN: u32 = 0x0000_0020; pub const IN_MOVED_FROM: u32 = 0x0000_0040; pub const IN_MOVED_TO: u32 = 0x0000_0080; pub const IN_MOVE: u32 = IN_MOVED_FROM | IN_MOVED_TO; pub const IN_CREATE: u32 = 0x0000_0100; pub const IN_DELETE: u32 = 0x0000_0200; pub const IN_DELETE_SELF: u32 = 0x0000_0400; pub const IN_MOVE_SELF: u32 = 0x0000_0800; pub const IN_UNMOUNT: u32 = 0x0000_2000; pub const IN_Q_OVERFLOW: u32 = 0x0000_4000; pub const IN_IGNORED: u32 = 0x0000_8000; pub const IN_ONLYDIR: u32 = 0x0100_0000; pub const IN_DONT_FOLLOW: u32 = 0x0200_0000; pub const IN_EXCL_UNLINK: u32 = 0x0400_0000; pub const IN_MASK_CREATE: u32 = 0x1000_0000; pub const IN_MASK_ADD: u32 = 0x2000_0000; pub const IN_ISDIR: u32 = 0x4000_0000; pub const IN_ONESHOT: u32 = 0x8000_0000; pub const IN_ALL_EVENTS: u32 = IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | IN_MOVE_SELF; pub const IN_CLOEXEC: ::c_int = O_CLOEXEC; pub const IN_NONBLOCK: ::c_int = O_NONBLOCK; pub const FUTEX_WAIT: ::c_int = 0; pub const FUTEX_WAKE: ::c_int = 1; pub const FUTEX_FD: ::c_int = 2; pub const FUTEX_REQUEUE: ::c_int = 3; pub const FUTEX_CMP_REQUEUE: ::c_int = 4; pub const FUTEX_WAKE_OP: ::c_int = 5; pub const FUTEX_LOCK_PI: ::c_int = 6; pub const FUTEX_UNLOCK_PI: ::c_int = 7; pub const FUTEX_TRYLOCK_PI: ::c_int = 8; pub const FUTEX_WAIT_BITSET: ::c_int = 9; pub const FUTEX_WAKE_BITSET: ::c_int = 10; pub const FUTEX_WAIT_REQUEUE_PI: ::c_int = 11; pub const FUTEX_CMP_REQUEUE_PI: ::c_int = 12; pub const FUTEX_LOCK_PI2: ::c_int = 13; pub const FUTEX_PRIVATE_FLAG: ::c_int = 128; pub const FUTEX_CLOCK_REALTIME: ::c_int = 256; pub const FUTEX_CMD_MASK: ::c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); // linux/errqueue.h pub const SO_EE_ORIGIN_NONE: u8 = 0; pub const SO_EE_ORIGIN_LOCAL: u8 = 1; pub const SO_EE_ORIGIN_ICMP: u8 = 2; pub const SO_EE_ORIGIN_ICMP6: u8 = 3; pub const SO_EE_ORIGIN_TXSTATUS: u8 = 4; pub const SO_EE_ORIGIN_TIMESTAMPING: u8 = SO_EE_ORIGIN_TXSTATUS; // errno.h pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EWOULDBLOCK: ::c_int = EAGAIN; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; // linux/sched.h pub const SCHED_NORMAL: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const SCHED_BATCH: ::c_int = 3; pub const SCHED_IDLE: ::c_int = 5; pub const SCHED_DEADLINE: ::c_int = 6; pub const SCHED_RESET_ON_FORK: ::c_int = 0x40000000; pub const CLONE_PIDFD: ::c_int = 0x1000; // linux/membarrier.h pub const MEMBARRIER_CMD_QUERY: ::c_int = 0; pub const MEMBARRIER_CMD_GLOBAL: ::c_int = 1 << 0; pub const MEMBARRIER_CMD_GLOBAL_EXPEDITED: ::c_int = 1 << 1; pub const MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED: ::c_int = 1 << 2; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED: ::c_int = 1 << 3; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED: ::c_int = 1 << 4; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE: ::c_int = 1 << 5; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE: ::c_int = 1 << 6; pub const MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ: ::c_int = 1 << 7; pub const MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ: ::c_int = 1 << 8; // linux/mempolicy.h pub const MPOL_DEFAULT: ::c_int = 0; pub const MPOL_PREFERRED: ::c_int = 1; pub const MPOL_BIND: ::c_int = 2; pub const MPOL_INTERLEAVE: ::c_int = 3; pub const MPOL_LOCAL: ::c_int = 4; pub const MPOL_F_NUMA_BALANCING: ::c_int = 1 << 13; pub const MPOL_F_RELATIVE_NODES: ::c_int = 1 << 14; pub const MPOL_F_STATIC_NODES: ::c_int = 1 << 15; // bits/seek_constants.h pub const SEEK_DATA: ::c_int = 3; pub const SEEK_HOLE: ::c_int = 4; // sys/socket.h pub const AF_NFC: ::c_int = 39; pub const AF_VSOCK: ::c_int = 40; pub const PF_NFC: ::c_int = AF_NFC; pub const PF_VSOCK: ::c_int = AF_VSOCK; pub const SOMAXCONN: ::c_int = 128; // sys/prctl.h pub const PR_SET_PDEATHSIG: ::c_int = 1; pub const PR_GET_PDEATHSIG: ::c_int = 2; pub const PR_GET_SECUREBITS: ::c_int = 27; pub const PR_SET_SECUREBITS: ::c_int = 28; // sys/system_properties.h pub const PROP_VALUE_MAX: ::c_int = 92; pub const PROP_NAME_MAX: ::c_int = 32; // sys/prctl.h pub const PR_SET_VMA: ::c_int = 0x53564d41; pub const PR_SET_VMA_ANON_NAME: ::c_int = 0; pub const PR_SET_NO_NEW_PRIVS: ::c_int = 38; pub const PR_GET_NO_NEW_PRIVS: ::c_int = 39; pub const PR_GET_SECCOMP: ::c_int = 21; pub const PR_SET_SECCOMP: ::c_int = 22; pub const PR_GET_TIMING: ::c_int = 13; pub const PR_SET_TIMING: ::c_int = 14; pub const PR_TIMING_STATISTICAL: ::c_int = 0; pub const PR_TIMING_TIMESTAMP: ::c_int = 1; // linux/if_addr.h pub const IFA_UNSPEC: ::c_ushort = 0; pub const IFA_ADDRESS: ::c_ushort = 1; pub const IFA_LOCAL: ::c_ushort = 2; pub const IFA_LABEL: ::c_ushort = 3; pub const IFA_BROADCAST: ::c_ushort = 4; pub const IFA_ANYCAST: ::c_ushort = 5; pub const IFA_CACHEINFO: ::c_ushort = 6; pub const IFA_MULTICAST: ::c_ushort = 7; pub const IFA_F_SECONDARY: u32 = 0x01; pub const IFA_F_TEMPORARY: u32 = 0x01; pub const IFA_F_NODAD: u32 = 0x02; pub const IFA_F_OPTIMISTIC: u32 = 0x04; pub const IFA_F_DADFAILED: u32 = 0x08; pub const IFA_F_HOMEADDRESS: u32 = 0x10; pub const IFA_F_DEPRECATED: u32 = 0x20; pub const IFA_F_TENTATIVE: u32 = 0x40; pub const IFA_F_PERMANENT: u32 = 0x80; // linux/if_link.h pub const IFLA_UNSPEC: ::c_ushort = 0; pub const IFLA_ADDRESS: ::c_ushort = 1; pub const IFLA_BROADCAST: ::c_ushort = 2; pub const IFLA_IFNAME: ::c_ushort = 3; pub const IFLA_MTU: ::c_ushort = 4; pub const IFLA_LINK: ::c_ushort = 5; pub const IFLA_QDISC: ::c_ushort = 6; pub const IFLA_STATS: ::c_ushort = 7; pub const IFLA_COST: ::c_ushort = 8; pub const IFLA_PRIORITY: ::c_ushort = 9; pub const IFLA_MASTER: ::c_ushort = 10; pub const IFLA_WIRELESS: ::c_ushort = 11; pub const IFLA_PROTINFO: ::c_ushort = 12; pub const IFLA_TXQLEN: ::c_ushort = 13; pub const IFLA_MAP: ::c_ushort = 14; pub const IFLA_WEIGHT: ::c_ushort = 15; pub const IFLA_OPERSTATE: ::c_ushort = 16; pub const IFLA_LINKMODE: ::c_ushort = 17; pub const IFLA_LINKINFO: ::c_ushort = 18; pub const IFLA_NET_NS_PID: ::c_ushort = 19; pub const IFLA_IFALIAS: ::c_ushort = 20; pub const IFLA_NUM_VF: ::c_ushort = 21; pub const IFLA_VFINFO_LIST: ::c_ushort = 22; pub const IFLA_STATS64: ::c_ushort = 23; pub const IFLA_VF_PORTS: ::c_ushort = 24; pub const IFLA_PORT_SELF: ::c_ushort = 25; pub const IFLA_AF_SPEC: ::c_ushort = 26; pub const IFLA_GROUP: ::c_ushort = 27; pub const IFLA_NET_NS_FD: ::c_ushort = 28; pub const IFLA_EXT_MASK: ::c_ushort = 29; pub const IFLA_PROMISCUITY: ::c_ushort = 30; pub const IFLA_NUM_TX_QUEUES: ::c_ushort = 31; pub const IFLA_NUM_RX_QUEUES: ::c_ushort = 32; pub const IFLA_CARRIER: ::c_ushort = 33; pub const IFLA_PHYS_PORT_ID: ::c_ushort = 34; pub const IFLA_CARRIER_CHANGES: ::c_ushort = 35; pub const IFLA_PHYS_SWITCH_ID: ::c_ushort = 36; pub const IFLA_LINK_NETNSID: ::c_ushort = 37; pub const IFLA_PHYS_PORT_NAME: ::c_ushort = 38; pub const IFLA_PROTO_DOWN: ::c_ushort = 39; pub const IFLA_GSO_MAX_SEGS: ::c_ushort = 40; pub const IFLA_GSO_MAX_SIZE: ::c_ushort = 41; pub const IFLA_PAD: ::c_ushort = 42; pub const IFLA_XDP: ::c_ushort = 43; pub const IFLA_EVENT: ::c_ushort = 44; pub const IFLA_NEW_NETNSID: ::c_ushort = 45; pub const IFLA_IF_NETNSID: ::c_ushort = 46; pub const IFLA_TARGET_NETNSID: ::c_ushort = IFLA_IF_NETNSID; pub const IFLA_CARRIER_UP_COUNT: ::c_ushort = 47; pub const IFLA_CARRIER_DOWN_COUNT: ::c_ushort = 48; pub const IFLA_NEW_IFINDEX: ::c_ushort = 49; pub const IFLA_MIN_MTU: ::c_ushort = 50; pub const IFLA_MAX_MTU: ::c_ushort = 51; pub const IFLA_PROP_LIST: ::c_ushort = 52; pub const IFLA_ALT_IFNAME: ::c_ushort = 53; pub const IFLA_PERM_ADDRESS: ::c_ushort = 54; pub const IFLA_PROTO_DOWN_REASON: ::c_ushort = 55; pub const IFLA_PARENT_DEV_NAME: ::c_ushort = 56; pub const IFLA_PARENT_DEV_BUS_NAME: ::c_ushort = 57; pub const IFLA_GRO_MAX_SIZE: ::c_ushort = 58; pub const IFLA_TSO_MAX_SIZE: ::c_ushort = 59; pub const IFLA_TSO_MAX_SEGS: ::c_ushort = 60; pub const IFLA_ALLMULTI: ::c_ushort = 61; pub const IFLA_DEVLINK_PORT: ::c_ushort = 62; pub const IFLA_GSO_IPV4_MAX_SIZE: ::c_ushort = 63; pub const IFLA_GRO_IPV4_MAX_SIZE: ::c_ushort = 64; pub const IFLA_INFO_UNSPEC: ::c_ushort = 0; pub const IFLA_INFO_KIND: ::c_ushort = 1; pub const IFLA_INFO_DATA: ::c_ushort = 2; pub const IFLA_INFO_XSTATS: ::c_ushort = 3; pub const IFLA_INFO_SLAVE_KIND: ::c_ushort = 4; pub const IFLA_INFO_SLAVE_DATA: ::c_ushort = 5; // linux/rtnetlink.h pub const TCA_UNSPEC: ::c_ushort = 0; pub const TCA_KIND: ::c_ushort = 1; pub const TCA_OPTIONS: ::c_ushort = 2; pub const TCA_STATS: ::c_ushort = 3; pub const TCA_XSTATS: ::c_ushort = 4; pub const TCA_RATE: ::c_ushort = 5; pub const TCA_FCNT: ::c_ushort = 6; pub const TCA_STATS2: ::c_ushort = 7; pub const TCA_STAB: ::c_ushort = 8; pub const RTM_NEWLINK: u16 = 16; pub const RTM_DELLINK: u16 = 17; pub const RTM_GETLINK: u16 = 18; pub const RTM_SETLINK: u16 = 19; pub const RTM_NEWADDR: u16 = 20; pub const RTM_DELADDR: u16 = 21; pub const RTM_GETADDR: u16 = 22; pub const RTM_NEWROUTE: u16 = 24; pub const RTM_DELROUTE: u16 = 25; pub const RTM_GETROUTE: u16 = 26; pub const RTM_NEWNEIGH: u16 = 28; pub const RTM_DELNEIGH: u16 = 29; pub const RTM_GETNEIGH: u16 = 30; pub const RTM_NEWRULE: u16 = 32; pub const RTM_DELRULE: u16 = 33; pub const RTM_GETRULE: u16 = 34; pub const RTM_NEWQDISC: u16 = 36; pub const RTM_DELQDISC: u16 = 37; pub const RTM_GETQDISC: u16 = 38; pub const RTM_NEWTCLASS: u16 = 40; pub const RTM_DELTCLASS: u16 = 41; pub const RTM_GETTCLASS: u16 = 42; pub const RTM_NEWTFILTER: u16 = 44; pub const RTM_DELTFILTER: u16 = 45; pub const RTM_GETTFILTER: u16 = 46; pub const RTM_NEWACTION: u16 = 48; pub const RTM_DELACTION: u16 = 49; pub const RTM_GETACTION: u16 = 50; pub const RTM_NEWPREFIX: u16 = 52; pub const RTM_GETMULTICAST: u16 = 58; pub const RTM_GETANYCAST: u16 = 62; pub const RTM_NEWNEIGHTBL: u16 = 64; pub const RTM_GETNEIGHTBL: u16 = 66; pub const RTM_SETNEIGHTBL: u16 = 67; pub const RTM_NEWNDUSEROPT: u16 = 68; pub const RTM_NEWADDRLABEL: u16 = 72; pub const RTM_DELADDRLABEL: u16 = 73; pub const RTM_GETADDRLABEL: u16 = 74; pub const RTM_GETDCB: u16 = 78; pub const RTM_SETDCB: u16 = 79; pub const RTM_NEWNETCONF: u16 = 80; pub const RTM_GETNETCONF: u16 = 82; pub const RTM_NEWMDB: u16 = 84; pub const RTM_DELMDB: u16 = 85; pub const RTM_GETMDB: u16 = 86; pub const RTM_NEWNSID: u16 = 88; pub const RTM_DELNSID: u16 = 89; pub const RTM_GETNSID: u16 = 90; pub const RTM_F_NOTIFY: ::c_uint = 0x100; pub const RTM_F_CLONED: ::c_uint = 0x200; pub const RTM_F_EQUALIZE: ::c_uint = 0x400; pub const RTM_F_PREFIX: ::c_uint = 0x800; pub const RTA_UNSPEC: ::c_ushort = 0; pub const RTA_DST: ::c_ushort = 1; pub const RTA_SRC: ::c_ushort = 2; pub const RTA_IIF: ::c_ushort = 3; pub const RTA_OIF: ::c_ushort = 4; pub const RTA_GATEWAY: ::c_ushort = 5; pub const RTA_PRIORITY: ::c_ushort = 6; pub const RTA_PREFSRC: ::c_ushort = 7; pub const RTA_METRICS: ::c_ushort = 8; pub const RTA_MULTIPATH: ::c_ushort = 9; pub const RTA_PROTOINFO: ::c_ushort = 10; // No longer used pub const RTA_FLOW: ::c_ushort = 11; pub const RTA_CACHEINFO: ::c_ushort = 12; pub const RTA_SESSION: ::c_ushort = 13; // No longer used pub const RTA_MP_ALGO: ::c_ushort = 14; // No longer used pub const RTA_TABLE: ::c_ushort = 15; pub const RTA_MARK: ::c_ushort = 16; pub const RTA_MFC_STATS: ::c_ushort = 17; pub const RTN_UNSPEC: ::c_uchar = 0; pub const RTN_UNICAST: ::c_uchar = 1; pub const RTN_LOCAL: ::c_uchar = 2; pub const RTN_BROADCAST: ::c_uchar = 3; pub const RTN_ANYCAST: ::c_uchar = 4; pub const RTN_MULTICAST: ::c_uchar = 5; pub const RTN_BLACKHOLE: ::c_uchar = 6; pub const RTN_UNREACHABLE: ::c_uchar = 7; pub const RTN_PROHIBIT: ::c_uchar = 8; pub const RTN_THROW: ::c_uchar = 9; pub const RTN_NAT: ::c_uchar = 10; pub const RTN_XRESOLVE: ::c_uchar = 11; pub const RTPROT_UNSPEC: ::c_uchar = 0; pub const RTPROT_REDIRECT: ::c_uchar = 1; pub const RTPROT_KERNEL: ::c_uchar = 2; pub const RTPROT_BOOT: ::c_uchar = 3; pub const RTPROT_STATIC: ::c_uchar = 4; pub const RT_SCOPE_UNIVERSE: ::c_uchar = 0; pub const RT_SCOPE_SITE: ::c_uchar = 200; pub const RT_SCOPE_LINK: ::c_uchar = 253; pub const RT_SCOPE_HOST: ::c_uchar = 254; pub const RT_SCOPE_NOWHERE: ::c_uchar = 255; pub const RT_TABLE_UNSPEC: ::c_uchar = 0; pub const RT_TABLE_COMPAT: ::c_uchar = 252; pub const RT_TABLE_DEFAULT: ::c_uchar = 253; pub const RT_TABLE_MAIN: ::c_uchar = 254; pub const RT_TABLE_LOCAL: ::c_uchar = 255; pub const RTMSG_NEWDEVICE: u32 = 0x11; pub const RTMSG_DELDEVICE: u32 = 0x12; pub const RTMSG_NEWROUTE: u32 = 0x21; pub const RTMSG_DELROUTE: u32 = 0x22; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_NET: ::c_int = 3; pub const CTL_FS: ::c_int = 5; pub const CTL_DEBUG: ::c_int = 6; pub const CTL_DEV: ::c_int = 7; pub const CTL_BUS: ::c_int = 8; pub const CTL_ABI: ::c_int = 9; pub const CTL_CPU: ::c_int = 10; pub const CTL_BUS_ISA: ::c_int = 1; pub const INOTIFY_MAX_USER_INSTANCES: ::c_int = 1; pub const INOTIFY_MAX_USER_WATCHES: ::c_int = 2; pub const INOTIFY_MAX_QUEUED_EVENTS: ::c_int = 3; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_VERSION: ::c_int = 4; pub const KERN_SECUREMASK: ::c_int = 5; pub const KERN_PROF: ::c_int = 6; pub const KERN_NODENAME: ::c_int = 7; pub const KERN_DOMAINNAME: ::c_int = 8; pub const KERN_PANIC: ::c_int = 15; pub const KERN_REALROOTDEV: ::c_int = 16; pub const KERN_SPARC_REBOOT: ::c_int = 21; pub const KERN_CTLALTDEL: ::c_int = 22; pub const KERN_PRINTK: ::c_int = 23; pub const KERN_NAMETRANS: ::c_int = 24; pub const KERN_PPC_HTABRECLAIM: ::c_int = 25; pub const KERN_PPC_ZEROPAGED: ::c_int = 26; pub const KERN_PPC_POWERSAVE_NAP: ::c_int = 27; pub const KERN_MODPROBE: ::c_int = 28; pub const KERN_SG_BIG_BUFF: ::c_int = 29; pub const KERN_ACCT: ::c_int = 30; pub const KERN_PPC_L2CR: ::c_int = 31; pub const KERN_RTSIGNR: ::c_int = 32; pub const KERN_RTSIGMAX: ::c_int = 33; pub const KERN_SHMMAX: ::c_int = 34; pub const KERN_MSGMAX: ::c_int = 35; pub const KERN_MSGMNB: ::c_int = 36; pub const KERN_MSGPOOL: ::c_int = 37; pub const KERN_SYSRQ: ::c_int = 38; pub const KERN_MAX_THREADS: ::c_int = 39; pub const KERN_RANDOM: ::c_int = 40; pub const KERN_SHMALL: ::c_int = 41; pub const KERN_MSGMNI: ::c_int = 42; pub const KERN_SEM: ::c_int = 43; pub const KERN_SPARC_STOP_A: ::c_int = 44; pub const KERN_SHMMNI: ::c_int = 45; pub const KERN_OVERFLOWUID: ::c_int = 46; pub const KERN_OVERFLOWGID: ::c_int = 47; pub const KERN_SHMPATH: ::c_int = 48; pub const KERN_HOTPLUG: ::c_int = 49; pub const KERN_IEEE_EMULATION_WARNINGS: ::c_int = 50; pub const KERN_S390_USER_DEBUG_LOGGING: ::c_int = 51; pub const KERN_CORE_USES_PID: ::c_int = 52; pub const KERN_TAINTED: ::c_int = 53; pub const KERN_CADPID: ::c_int = 54; pub const KERN_PIDMAX: ::c_int = 55; pub const KERN_CORE_PATTERN: ::c_int = 56; pub const KERN_PANIC_ON_OOPS: ::c_int = 57; pub const KERN_HPPA_PWRSW: ::c_int = 58; pub const KERN_HPPA_UNALIGNED: ::c_int = 59; pub const KERN_PRINTK_RATELIMIT: ::c_int = 60; pub const KERN_PRINTK_RATELIMIT_BURST: ::c_int = 61; pub const KERN_PTY: ::c_int = 62; pub const KERN_NGROUPS_MAX: ::c_int = 63; pub const KERN_SPARC_SCONS_PWROFF: ::c_int = 64; pub const KERN_HZ_TIMER: ::c_int = 65; pub const KERN_UNKNOWN_NMI_PANIC: ::c_int = 66; pub const KERN_BOOTLOADER_TYPE: ::c_int = 67; pub const KERN_RANDOMIZE: ::c_int = 68; pub const KERN_SETUID_DUMPABLE: ::c_int = 69; pub const KERN_SPIN_RETRY: ::c_int = 70; pub const KERN_ACPI_VIDEO_FLAGS: ::c_int = 71; pub const KERN_IA64_UNALIGNED: ::c_int = 72; pub const KERN_COMPAT_LOG: ::c_int = 73; pub const KERN_MAX_LOCK_DEPTH: ::c_int = 74; pub const VM_OVERCOMMIT_MEMORY: ::c_int = 5; pub const VM_PAGE_CLUSTER: ::c_int = 10; pub const VM_DIRTY_BACKGROUND: ::c_int = 11; pub const VM_DIRTY_RATIO: ::c_int = 12; pub const VM_DIRTY_WB_CS: ::c_int = 13; pub const VM_DIRTY_EXPIRE_CS: ::c_int = 14; pub const VM_NR_PDFLUSH_THREADS: ::c_int = 15; pub const VM_OVERCOMMIT_RATIO: ::c_int = 16; pub const VM_PAGEBUF: ::c_int = 17; pub const VM_HUGETLB_PAGES: ::c_int = 18; pub const VM_SWAPPINESS: ::c_int = 19; pub const VM_LOWMEM_RESERVE_RATIO: ::c_int = 20; pub const VM_MIN_FREE_KBYTES: ::c_int = 21; pub const VM_MAX_MAP_COUNT: ::c_int = 22; pub const VM_LAPTOP_MODE: ::c_int = 23; pub const VM_BLOCK_DUMP: ::c_int = 24; pub const VM_HUGETLB_GROUP: ::c_int = 25; pub const VM_VFS_CACHE_PRESSURE: ::c_int = 26; pub const VM_LEGACY_VA_LAYOUT: ::c_int = 27; pub const VM_SWAP_TOKEN_TIMEOUT: ::c_int = 28; pub const VM_DROP_PAGECACHE: ::c_int = 29; pub const VM_PERCPU_PAGELIST_FRACTION: ::c_int = 30; pub const VM_ZONE_RECLAIM_MODE: ::c_int = 31; pub const VM_MIN_UNMAPPED: ::c_int = 32; pub const VM_PANIC_ON_OOM: ::c_int = 33; pub const VM_VDSO_ENABLED: ::c_int = 34; pub const NET_CORE: ::c_int = 1; pub const NET_ETHER: ::c_int = 2; pub const NET_802: ::c_int = 3; pub const NET_UNIX: ::c_int = 4; pub const NET_IPV4: ::c_int = 5; pub const NET_IPX: ::c_int = 6; pub const NET_ATALK: ::c_int = 7; pub const NET_NETROM: ::c_int = 8; pub const NET_AX25: ::c_int = 9; pub const NET_BRIDGE: ::c_int = 10; pub const NET_ROSE: ::c_int = 11; pub const NET_IPV6: ::c_int = 12; pub const NET_X25: ::c_int = 13; pub const NET_TR: ::c_int = 14; pub const NET_DECNET: ::c_int = 15; pub const NET_ECONET: ::c_int = 16; pub const NET_SCTP: ::c_int = 17; pub const NET_LLC: ::c_int = 18; pub const NET_NETFILTER: ::c_int = 19; pub const NET_DCCP: ::c_int = 20; pub const HUGETLB_FLAG_ENCODE_SHIFT: ::c_int = 26; pub const MAP_HUGE_SHIFT: ::c_int = HUGETLB_FLAG_ENCODE_SHIFT; // include/linux/sched.h pub const PF_VCPU: ::c_int = 0x00000001; pub const PF_IDLE: ::c_int = 0x00000002; pub const PF_EXITING: ::c_int = 0x00000004; pub const PF_POSTCOREDUMP: ::c_int = 0x00000008; pub const PF_IO_WORKER: ::c_int = 0x00000010; pub const PF_WQ_WORKER: ::c_int = 0x00000020; pub const PF_FORKNOEXEC: ::c_int = 0x00000040; pub const PF_MCE_PROCESS: ::c_int = 0x00000080; pub const PF_SUPERPRIV: ::c_int = 0x00000100; pub const PF_DUMPCORE: ::c_int = 0x00000200; pub const PF_SIGNALED: ::c_int = 0x00000400; pub const PF_MEMALLOC: ::c_int = 0x00000800; pub const PF_NPROC_EXCEEDED: ::c_int = 0x00001000; pub const PF_USED_MATH: ::c_int = 0x00002000; pub const PF_USER_WORKER: ::c_int = 0x00004000; pub const PF_NOFREEZE: ::c_int = 0x00008000; pub const PF_KSWAPD: ::c_int = 0x00020000; pub const PF_MEMALLOC_NOFS: ::c_int = 0x00040000; pub const PF_MEMALLOC_NOIO: ::c_int = 0x00080000; pub const PF_LOCAL_THROTTLE: ::c_int = 0x00100000; pub const PF_KTHREAD: ::c_int = 0x00200000; pub const PF_RANDOMIZE: ::c_int = 0x00400000; pub const PF_NO_SETAFFINITY: ::c_int = 0x04000000; pub const PF_MCE_EARLY: ::c_int = 0x08000000; pub const PF_MEMALLOC_PIN: ::c_int = 0x10000000; pub const PF_SUSPEND_TASK: ::c_int = 0x80000000; // Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the // following are only available on newer Linux versions than the versions // currently used in CI in some configurations, so we define them here. cfg_if! { if #[cfg(not(target_arch = "s390x"))] { pub const XFS_SUPER_MAGIC: ::c_long = 0x58465342; } else if #[cfg(target_arch = "s390x")] { pub const XFS_SUPER_MAGIC: ::c_uint = 0x58465342; } } f! { pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { let next = (cmsg as usize + super::CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.offset(1)) as usize > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ALLOC_SIZE(count: ::c_int) -> ::size_t { let _dummy: cpu_set_t = ::mem::zeroed(); let size_in_bits = 8 * ::mem::size_of_val(&_dummy.__bits[0]); ((count as ::size_t + size_in_bits - 1) / 8) as ::size_t } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.__bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.__bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.__bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.__bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.__bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.__bits[idx] & (1 << offset)) } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> ::c_int { let mut s: u32 = 0; let size_of_mask = ::mem::size_of_val(&cpuset.__bits[0]); for i in cpuset.__bits[..(size / size_of_mask)].iter() { s += i.count_ones(); }; s as ::c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> ::c_int { CPU_COUNT_S(::mem::size_of::(), cpuset) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.__bits == set2.__bits } pub fn major(dev: ::dev_t) -> ::c_int { ((dev >> 8) & 0xfff) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { ((dev & 0xff) | ((dev >> 12) & 0xfff00)) as ::c_int } pub fn NLA_ALIGN(len: ::c_int) -> ::c_int { return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1) } pub fn SO_EE_OFFENDER(ee: *const ::sock_extended_err) -> *mut ::sockaddr { ee.offset(1) as *mut ::sockaddr } } safe_f! { pub {const} fn makedev(ma: ::c_uint, mi: ::c_uint) -> ::dev_t { let ma = ma as ::dev_t; let mi = mi as ::dev_t; ((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12) } } extern "C" { pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int; pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int; pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn prlimit( pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit, old_limit: *mut ::rlimit, ) -> ::c_int; pub fn prlimit64( pid: ::pid_t, resource: ::c_int, new_limit: *const ::rlimit64, old_limit: *mut ::rlimit64, ) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn mlock2(addr: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::size_t, serv: *mut ::c_char, servlen: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn preadv(fd: ::c_int, iov: *const ::iovec, count: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, count: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn process_vm_readv( pid: ::pid_t, local_iov: *const ::iovec, local_iov_count: ::c_ulong, remote_iov: *const ::iovec, remote_iov_count: ::c_ulong, flags: ::c_ulong, ) -> ::ssize_t; pub fn process_vm_writev( pid: ::pid_t, local_iov: *const ::iovec, local_iov_count: ::c_ulong, remote_iov: *const ::iovec, remote_iov_count: ::c_ulong, flags: ::c_ulong, ) -> ::ssize_t; pub fn ptrace(request: ::c_int, ...) -> ::c_long; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn __sched_cpualloc(count: ::size_t) -> *mut ::cpu_set_t; pub fn __sched_cpufree(set: *mut ::cpu_set_t); pub fn __sched_cpucount(setsize: ::size_t, set: *const cpu_set_t) -> ::c_int; pub fn sched_getcpu() -> ::c_int; pub fn mallinfo() -> ::mallinfo; // available from API 23 pub fn malloc_info(options: ::c_int, stream: *mut ::FILE) -> ::c_int; pub fn malloc_usable_size(ptr: *const ::c_void) -> ::size_t; pub fn utmpname(name: *const ::c_char) -> ::c_int; pub fn setutent(); pub fn getutent() -> *mut utmp; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn fallocate(fd: ::c_int, mode: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn fallocate64(fd: ::c_int, mode: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn posix_fallocate64(fd: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn lgetxattr( path: *const c_char, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn fgetxattr( filedes: ::c_int, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn lsetxattr( path: *const c_char, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn fsetxattr( filedes: ::c_int, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn llistxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn flistxattr(filedes: ::c_int, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int; pub fn lremovexattr(path: *const c_char, name: *const c_char) -> ::c_int; pub fn fremovexattr(filedes: ::c_int, name: *const c_char) -> ::c_int; pub fn signalfd(fd: ::c_int, mask: *const ::sigset_t, flags: ::c_int) -> ::c_int; pub fn timerfd_create(clock: ::clockid_t, flags: ::c_int) -> ::c_int; pub fn timerfd_gettime(fd: ::c_int, current_value: *mut itimerspec) -> ::c_int; pub fn timerfd_settime( fd: ::c_int, flags: ::c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> ::c_int; pub fn syscall(num: ::c_long, ...) -> ::c_long; pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, cpuset: *mut cpu_set_t) -> ::c_int; pub fn sched_setaffinity( pid: ::pid_t, cpusetsize: ::size_t, cpuset: *const cpu_set_t, ) -> ::c_int; pub fn epoll_create(size: ::c_int) -> ::c_int; pub fn epoll_create1(flags: ::c_int) -> ::c_int; pub fn epoll_wait( epfd: ::c_int, events: *mut ::epoll_event, maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut ::sched_param, ) -> ::c_int; pub fn unshare(flags: ::c_int) -> ::c_int; pub fn umount(target: *const ::c_char) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn tee(fd_in: ::c_int, fd_out: ::c_int, len: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn splice( fd_in: ::c_int, off_in: *mut ::loff_t, fd_out: ::c_int, off_out: *mut ::loff_t, len: ::size_t, flags: ::c_uint, ) -> ::ssize_t; pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; pub fn eventfd_read(fd: ::c_int, value: *mut eventfd_t) -> ::c_int; pub fn eventfd_write(fd: ::c_int, value: eventfd_t) -> ::c_int; pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn setns(fd: ::c_int, nstype: ::c_int) -> ::c_int; pub fn swapoff(puath: *const ::c_char) -> ::c_int; pub fn vmsplice( fd: ::c_int, iov: *const ::iovec, nr_segs: ::size_t, flags: ::c_uint, ) -> ::ssize_t; pub fn mount( src: *const ::c_char, target: *const ::c_char, fstype: *const ::c_char, flags: ::c_ulong, data: *const ::c_void, ) -> ::c_int; pub fn personality(persona: ::c_uint) -> ::c_int; pub fn prctl(option: ::c_int, ...) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int; pub fn ppoll( fds: *mut ::pollfd, nfds: nfds_t, timeout: *const ::timespec, sigmask: *const sigset_t, ) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_barrierattr_init(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_destroy(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_getpshared( attr: *const ::pthread_barrierattr_t, shared: *mut ::c_int, ) -> ::c_int; pub fn pthread_barrierattr_setpshared( attr: *mut ::pthread_barrierattr_t, shared: ::c_int, ) -> ::c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const ::pthread_barrierattr_t, count: ::c_uint, ) -> ::c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn clone( cb: extern "C" fn(*mut ::c_void) -> ::c_int, child_stack: *mut ::c_void, flags: ::c_int, arg: *mut ::c_void, ... ) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getinheritsched( attr: *const ::pthread_attr_t, flag: *mut ::c_int, ) -> ::c_int; pub fn pthread_attr_setinheritsched(attr: *mut ::pthread_attr_t, flag: ::c_int) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn sysinfo(info: *mut ::sysinfo) -> ::c_int; pub fn umount2(target: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn swapon(path: *const ::c_char, swapflags: ::c_int) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sendfile( out_fd: ::c_int, in_fd: ::c_int, offset: *mut ::off_t, count: ::size_t, ) -> ::ssize_t; pub fn sendfile64( out_fd: ::c_int, in_fd: ::c_int, offset: *mut ::off64_t, count: ::size_t, ) -> ::ssize_t; pub fn setfsgid(gid: ::gid_t) -> ::c_int; pub fn setfsuid(uid: ::uid_t) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn getgrouplist( user: *const ::c_char, group: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn __errno() -> *mut ::c_int; pub fn inotify_rm_watch(fd: ::c_int, wd: u32) -> ::c_int; pub fn sendmmsg( sockfd: ::c_int, msgvec: *const ::mmsghdr, vlen: ::c_uint, flags: ::c_int, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn inotify_init() -> ::c_int; pub fn inotify_init1(flags: ::c_int) -> ::c_int; pub fn inotify_add_watch(fd: ::c_int, path: *const ::c_char, mask: u32) -> ::c_int; pub fn regcomp(preg: *mut ::regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regexec( preg: *const ::regex_t, input: *const ::c_char, nmatch: ::size_t, pmatch: *mut regmatch_t, eflags: ::c_int, ) -> ::c_int; pub fn regerror( errcode: ::c_int, preg: *const ::regex_t, errbuf: *mut ::c_char, errbuf_size: ::size_t, ) -> ::size_t; pub fn regfree(preg: *mut ::regex_t); pub fn android_set_abort_message(msg: *const ::c_char); pub fn gettid() -> ::pid_t; /// Only available in API Version 28+ pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int; pub fn __system_property_set(__name: *const ::c_char, __value: *const ::c_char) -> ::c_int; pub fn __system_property_get(__name: *const ::c_char, __value: *mut ::c_char) -> ::c_int; pub fn __system_property_find(__name: *const ::c_char) -> *const prop_info; pub fn __system_property_find_nth(__n: ::c_uint) -> *const prop_info; pub fn __system_property_foreach( __callback: unsafe extern "C" fn(__pi: *const prop_info, __cookie: *mut ::c_void), __cookie: *mut ::c_void, ) -> ::c_int; // #include /// Only available in API Version 21+ pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut dl_phdr_info, size: usize, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; pub fn arc4random() -> u32; pub fn arc4random_uniform(__upper_bound: u32) -> u32; pub fn arc4random_buf(__buf: *mut ::c_void, __n: ::size_t); pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn pthread_getcpuclockid(thread: ::pthread_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn dirname(path: *const ::c_char) -> *mut ::c_char; pub fn basename(path: *const ::c_char) -> *mut ::c_char; pub fn getopt_long( argc: ::c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut ::c_int, ) -> ::c_int; pub fn sync(); pub fn syncfs(fd: ::c_int) -> ::c_int; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; pub fn fread_unlocked( buf: *mut ::c_void, size: ::size_t, nobj: ::size_t, stream: *mut ::FILE, ) -> ::size_t; pub fn fwrite_unlocked( buf: *const ::c_void, size: ::size_t, nobj: ::size_t, stream: *mut ::FILE, ) -> ::size_t; pub fn fflush_unlocked(stream: *mut ::FILE) -> ::c_int; pub fn fgets_unlocked(buf: *mut ::c_char, size: ::c_int, stream: *mut ::FILE) -> *mut ::c_char; } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod b32; pub use self::b32::*; } else if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { // Unknown target_pointer_width } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { #[repr(C)] struct siginfo_sigfault { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, si_addr: *mut ::c_void, } (*(self as *const siginfo_t as *const siginfo_sigfault)).si_addr } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, _si_tid: ::c_int, _si_overrun: ::c_int, si_sigval: ::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).si_sigval } } cfg_if! { if #[cfg(libc_union)] { // Internal, for casts to access union fields #[repr(C)] struct sifields_sigchld { si_pid: ::pid_t, si_uid: ::uid_t, si_status: ::c_int, si_utime: ::c_long, si_stime: ::c_long, } impl ::Copy for sifields_sigchld {} impl ::Clone for sifields_sigchld { fn clone(&self) -> sifields_sigchld { *self } } // Internal, for casts to access union fields #[repr(C)] union sifields { _align_pointer: *mut ::c_void, sigchld: sifields_sigchld, } // Internal, for casts to access union fields. Note that some variants // of sifields start with a pointer, which makes the alignment of // sifields vary on 32-bit and 64-bit architectures. #[repr(C)] struct siginfo_f { _siginfo_base: [::c_int; 3], sifields: sifields, } impl siginfo_t { unsafe fn sifields(&self) -> &sifields { &(*(self as *const siginfo_t as *const siginfo_f)).sifields } pub unsafe fn si_pid(&self) -> ::pid_t { self.sifields().sigchld.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.sifields().sigchld.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.sifields().sigchld.si_status } pub unsafe fn si_utime(&self) -> ::c_long { self.sifields().sigchld.si_utime } pub unsafe fn si_stime(&self) -> ::c_long { self.sifields().sigchld.si_stime } } } } libc/src/unix/linux_like/android/b64/0000775000175000017500000000000014661133735020404 5ustar jamespagejamespagelibc/src/unix/linux_like/android/b64/aarch64/0000775000175000017500000000000014661133735021634 5ustar jamespagejamespagelibc/src/unix/linux_like/android/b64/aarch64/int128.rs0000644000175000017500000000021614661133735023224 0ustar jamespagejamespages! { pub struct user_fpsimd_struct { pub vregs: [::__uint128_t; 32], pub fpsr: u32, pub fpcr: u32, } } libc/src/unix/linux_like/android/b64/aarch64/mod.rs0000644000175000017500000004010014661133735022752 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type __u64 = ::c_ulonglong; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::c_uint, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::c_ulong, pub st_size: ::off64_t, pub st_blksize: ::c_int, __pad2: ::c_int, pub st_blocks: ::c_long, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused4: ::c_uint, __unused5: ::c_uint, } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::c_uint, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::c_ulong, pub st_size: ::off64_t, pub st_blksize: ::c_int, __pad2: ::c_int, pub st_blocks: ::c_long, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused4: ::c_uint, __unused5: ::c_uint, } pub struct user_regs_struct { pub regs: [u64; 31], pub sp: u64, pub pc: u64, pub pstate: u64, } } pub const O_DIRECT: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x4000; pub const O_NOFOLLOW: ::c_int = 0x8000; pub const O_LARGEFILE: ::c_int = 0o400000; pub const SIGSTKSZ: ::size_t = 16384; pub const MINSIGSTKSZ: ::size_t = 5120; // From NDK's asm/hwcap.h pub const HWCAP_FP: ::c_ulong = 1 << 0; pub const HWCAP_ASIMD: ::c_ulong = 1 << 1; pub const HWCAP_EVTSTRM: ::c_ulong = 1 << 2; pub const HWCAP_AES: ::c_ulong = 1 << 3; pub const HWCAP_PMULL: ::c_ulong = 1 << 4; pub const HWCAP_SHA1: ::c_ulong = 1 << 5; pub const HWCAP_SHA2: ::c_ulong = 1 << 6; pub const HWCAP_CRC32: ::c_ulong = 1 << 7; pub const HWCAP_ATOMICS: ::c_ulong = 1 << 8; pub const HWCAP_FPHP: ::c_ulong = 1 << 9; pub const HWCAP_ASIMDHP: ::c_ulong = 1 << 10; pub const HWCAP_CPUID: ::c_ulong = 1 << 11; pub const HWCAP_ASIMDRDM: ::c_ulong = 1 << 12; pub const HWCAP_JSCVT: ::c_ulong = 1 << 13; pub const HWCAP_FCMA: ::c_ulong = 1 << 14; pub const HWCAP_LRCPC: ::c_ulong = 1 << 15; pub const HWCAP_DCPOP: ::c_ulong = 1 << 16; pub const HWCAP_SHA3: ::c_ulong = 1 << 17; pub const HWCAP_SM3: ::c_ulong = 1 << 18; pub const HWCAP_SM4: ::c_ulong = 1 << 19; pub const HWCAP_ASIMDDP: ::c_ulong = 1 << 20; pub const HWCAP_SHA512: ::c_ulong = 1 << 21; pub const HWCAP_SVE: ::c_ulong = 1 << 22; pub const HWCAP_ASIMDFHM: ::c_ulong = 1 << 23; pub const HWCAP_DIT: ::c_ulong = 1 << 24; pub const HWCAP_USCAT: ::c_ulong = 1 << 25; pub const HWCAP_ILRCPC: ::c_ulong = 1 << 26; pub const HWCAP_FLAGM: ::c_ulong = 1 << 27; pub const HWCAP_SSBS: ::c_ulong = 1 << 28; pub const HWCAP_SB: ::c_ulong = 1 << 29; pub const HWCAP_PACA: ::c_ulong = 1 << 30; pub const HWCAP_PACG: ::c_ulong = 1 << 31; pub const HWCAP2_DCPODP: ::c_ulong = 1 << 0; pub const HWCAP2_SVE2: ::c_ulong = 1 << 1; pub const HWCAP2_SVEAES: ::c_ulong = 1 << 2; pub const HWCAP2_SVEPMULL: ::c_ulong = 1 << 3; pub const HWCAP2_SVEBITPERM: ::c_ulong = 1 << 4; pub const HWCAP2_SVESHA3: ::c_ulong = 1 << 5; pub const HWCAP2_SVESM4: ::c_ulong = 1 << 6; pub const HWCAP2_FLAGM2: ::c_ulong = 1 << 7; pub const HWCAP2_FRINT: ::c_ulong = 1 << 8; pub const HWCAP2_SVEI8MM: ::c_ulong = 1 << 9; pub const HWCAP2_SVEF32MM: ::c_ulong = 1 << 10; pub const HWCAP2_SVEF64MM: ::c_ulong = 1 << 11; pub const HWCAP2_SVEBF16: ::c_ulong = 1 << 12; pub const HWCAP2_I8MM: ::c_ulong = 1 << 13; pub const HWCAP2_BF16: ::c_ulong = 1 << 14; pub const HWCAP2_DGH: ::c_ulong = 1 << 15; pub const HWCAP2_RNG: ::c_ulong = 1 << 16; pub const HWCAP2_BTI: ::c_ulong = 1 << 17; pub const HWCAP2_MTE: ::c_ulong = 1 << 18; pub const HWCAP2_ECV: ::c_ulong = 1 << 19; pub const HWCAP2_AFP: ::c_ulong = 1 << 20; pub const HWCAP2_RPRES: ::c_ulong = 1 << 21; pub const HWCAP2_MTE3: ::c_ulong = 1 << 22; pub const HWCAP2_SME: ::c_ulong = 1 << 23; pub const HWCAP2_SME_I16I64: ::c_ulong = 1 << 24; pub const HWCAP2_SME_F64F64: ::c_ulong = 1 << 25; pub const HWCAP2_SME_I8I32: ::c_ulong = 1 << 26; pub const HWCAP2_SME_F16F32: ::c_ulong = 1 << 27; pub const HWCAP2_SME_B16F32: ::c_ulong = 1 << 28; pub const HWCAP2_SME_F32F32: ::c_ulong = 1 << 29; pub const HWCAP2_SME_FA64: ::c_ulong = 1 << 30; pub const HWCAP2_WFXT: ::c_ulong = 1 << 31; pub const HWCAP2_EBF16: ::c_ulong = 1 << 32; pub const HWCAP2_SVE_EBF16: ::c_ulong = 1 << 33; pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_getcwd: ::c_long = 17; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_dup: ::c_long = 23; pub const SYS_dup3: ::c_long = 24; pub const SYS_fcntl: ::c_long = 25; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_ioctl: ::c_long = 29; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_flock: ::c_long = 32; pub const SYS_mknodat: ::c_long = 33; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_linkat: ::c_long = 37; pub const SYS_renameat: ::c_long = 38; pub const SYS_umount2: ::c_long = 39; pub const SYS_mount: ::c_long = 40; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_fallocate: ::c_long = 47; pub const SYS_faccessat: ::c_long = 48; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_chroot: ::c_long = 51; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_fchownat: ::c_long = 54; pub const SYS_fchown: ::c_long = 55; pub const SYS_openat: ::c_long = 56; pub const SYS_close: ::c_long = 57; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pipe2: ::c_long = 59; pub const SYS_quotactl: ::c_long = 60; pub const SYS_getdents64: ::c_long = 61; pub const SYS_lseek: ::c_long = 62; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_sync: ::c_long = 81; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_utimensat: ::c_long = 88; pub const SYS_acct: ::c_long = 89; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_personality: ::c_long = 92; pub const SYS_exit: ::c_long = 93; pub const SYS_exit_group: ::c_long = 94; pub const SYS_waitid: ::c_long = 95; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_unshare: ::c_long = 97; pub const SYS_futex: ::c_long = 98; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_syslog: ::c_long = 116; pub const SYS_ptrace: ::c_long = 117; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_kill: ::c_long = 129; pub const SYS_tkill: ::c_long = 130; pub const SYS_tgkill: ::c_long = 131; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_setpriority: ::c_long = 140; pub const SYS_getpriority: ::c_long = 141; pub const SYS_reboot: ::c_long = 142; pub const SYS_setregid: ::c_long = 143; pub const SYS_setgid: ::c_long = 144; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setuid: ::c_long = 146; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_times: ::c_long = 153; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getpgid: ::c_long = 155; pub const SYS_getsid: ::c_long = 156; pub const SYS_setsid: ::c_long = 157; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_uname: ::c_long = 160; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_getrusage: ::c_long = 165; pub const SYS_umask: ::c_long = 166; pub const SYS_prctl: ::c_long = 167; pub const SYS_getcpu: ::c_long = 168; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_getpid: ::c_long = 172; pub const SYS_getppid: ::c_long = 173; pub const SYS_getuid: ::c_long = 174; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getgid: ::c_long = 176; pub const SYS_getegid: ::c_long = 177; pub const SYS_gettid: ::c_long = 178; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgctl: ::c_long = 187; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_semget: ::c_long = 190; pub const SYS_semctl: ::c_long = 191; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_semop: ::c_long = 193; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmctl: ::c_long = 195; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmdt: ::c_long = 197; pub const SYS_socket: ::c_long = 198; pub const SYS_socketpair: ::c_long = 199; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_accept: ::c_long = 202; pub const SYS_connect: ::c_long = 203; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_shutdown: ::c_long = 210; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_readahead: ::c_long = 213; pub const SYS_brk: ::c_long = 214; pub const SYS_munmap: ::c_long = 215; pub const SYS_mremap: ::c_long = 216; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_mmap: ::c_long = 222; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_mprotect: ::c_long = 226; pub const SYS_msync: ::c_long = 227; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_mbind: ::c_long = 235; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_move_pages: ::c_long = 239; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_accept4: ::c_long = 242; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_arch_specific_syscall: ::c_long = 244; pub const SYS_wait4: ::c_long = 260; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_setns: ::c_long = 268; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_syscalls: ::c_long = 436; pub const PROT_BTI: ::c_int = 0x10; pub const PROT_MTE: ::c_int = 0x20; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } cfg_if! { if #[cfg(libc_int128)] { mod int128; pub use self::int128::*; } } libc/src/unix/linux_like/android/b64/aarch64/align.rs0000644000175000017500000000136414661133735023276 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8] } } s! { pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, } #[repr(align(16))] pub struct mcontext_t { pub fault_address: ::c_ulonglong, pub regs: [::c_ulonglong; 31], pub sp: ::c_ulonglong, pub pc: ::c_ulonglong, pub pstate: ::c_ulonglong, // nested arrays to get the right size/length while being able to // auto-derive traits like Debug __reserved: [[u64; 32]; 16], } } libc/src/unix/linux_like/android/b64/riscv64/0000775000175000017500000000000014661133735021704 5ustar jamespagejamespagelibc/src/unix/linux_like/android/b64/riscv64/mod.rs0000644000175000017500000003224214661133735023032 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = u32; pub type greg_t = i64; pub type __u64 = ::c_ulonglong; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::c_uint, pub st_nlink: ::c_uint, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::c_ulong, pub st_size: ::off64_t, pub st_blksize: ::c_int, __pad2: ::c_int, pub st_blocks: ::c_long, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused4: ::c_uint, __unused5: ::c_uint, } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::c_uint, pub st_nlink: ::c_uint, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, __pad1: ::c_ulong, pub st_size: ::off64_t, pub st_blksize: ::c_int, __pad2: ::c_int, pub st_blocks: ::c_long, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, __unused4: ::c_uint, __unused5: ::c_uint, } } pub const O_DIRECT: ::c_int = 0x40000; pub const O_DIRECTORY: ::c_int = 0x200000; pub const O_NOFOLLOW: ::c_int = 0x400000; pub const O_LARGEFILE: ::c_int = 0x100000; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; // From NDK's asm/hwcap.h pub const COMPAT_HWCAP_ISA_I: ::c_ulong = 1 << (b'I' - b'A'); pub const COMPAT_HWCAP_ISA_M: ::c_ulong = 1 << (b'M' - b'A'); pub const COMPAT_HWCAP_ISA_A: ::c_ulong = 1 << (b'A' - b'A'); pub const COMPAT_HWCAP_ISA_F: ::c_ulong = 1 << (b'F' - b'A'); pub const COMPAT_HWCAP_ISA_D: ::c_ulong = 1 << (b'D' - b'A'); pub const COMPAT_HWCAP_ISA_C: ::c_ulong = 1 << (b'C' - b'A'); pub const SYS_io_setup: ::c_long = 0; pub const SYS_io_destroy: ::c_long = 1; pub const SYS_io_submit: ::c_long = 2; pub const SYS_io_cancel: ::c_long = 3; pub const SYS_io_getevents: ::c_long = 4; pub const SYS_setxattr: ::c_long = 5; pub const SYS_lsetxattr: ::c_long = 6; pub const SYS_fsetxattr: ::c_long = 7; pub const SYS_getxattr: ::c_long = 8; pub const SYS_lgetxattr: ::c_long = 9; pub const SYS_fgetxattr: ::c_long = 10; pub const SYS_listxattr: ::c_long = 11; pub const SYS_llistxattr: ::c_long = 12; pub const SYS_flistxattr: ::c_long = 13; pub const SYS_removexattr: ::c_long = 14; pub const SYS_lremovexattr: ::c_long = 15; pub const SYS_fremovexattr: ::c_long = 16; pub const SYS_getcwd: ::c_long = 17; pub const SYS_lookup_dcookie: ::c_long = 18; pub const SYS_eventfd2: ::c_long = 19; pub const SYS_epoll_create1: ::c_long = 20; pub const SYS_epoll_ctl: ::c_long = 21; pub const SYS_epoll_pwait: ::c_long = 22; pub const SYS_dup: ::c_long = 23; pub const SYS_dup3: ::c_long = 24; pub const SYS_inotify_init1: ::c_long = 26; pub const SYS_inotify_add_watch: ::c_long = 27; pub const SYS_inotify_rm_watch: ::c_long = 28; pub const SYS_ioctl: ::c_long = 29; pub const SYS_ioprio_set: ::c_long = 30; pub const SYS_ioprio_get: ::c_long = 31; pub const SYS_flock: ::c_long = 32; pub const SYS_mknodat: ::c_long = 33; pub const SYS_mkdirat: ::c_long = 34; pub const SYS_unlinkat: ::c_long = 35; pub const SYS_symlinkat: ::c_long = 36; pub const SYS_linkat: ::c_long = 37; pub const SYS_renameat: ::c_long = 38; pub const SYS_umount2: ::c_long = 39; pub const SYS_mount: ::c_long = 40; pub const SYS_pivot_root: ::c_long = 41; pub const SYS_nfsservctl: ::c_long = 42; pub const SYS_fallocate: ::c_long = 47; pub const SYS_faccessat: ::c_long = 48; pub const SYS_chdir: ::c_long = 49; pub const SYS_fchdir: ::c_long = 50; pub const SYS_chroot: ::c_long = 51; pub const SYS_fchmod: ::c_long = 52; pub const SYS_fchmodat: ::c_long = 53; pub const SYS_fchownat: ::c_long = 54; pub const SYS_fchown: ::c_long = 55; pub const SYS_openat: ::c_long = 56; pub const SYS_close: ::c_long = 57; pub const SYS_vhangup: ::c_long = 58; pub const SYS_pipe2: ::c_long = 59; pub const SYS_quotactl: ::c_long = 60; pub const SYS_getdents64: ::c_long = 61; pub const SYS_read: ::c_long = 63; pub const SYS_write: ::c_long = 64; pub const SYS_readv: ::c_long = 65; pub const SYS_writev: ::c_long = 66; pub const SYS_pread64: ::c_long = 67; pub const SYS_pwrite64: ::c_long = 68; pub const SYS_preadv: ::c_long = 69; pub const SYS_pwritev: ::c_long = 70; pub const SYS_pselect6: ::c_long = 72; pub const SYS_ppoll: ::c_long = 73; pub const SYS_signalfd4: ::c_long = 74; pub const SYS_vmsplice: ::c_long = 75; pub const SYS_splice: ::c_long = 76; pub const SYS_tee: ::c_long = 77; pub const SYS_readlinkat: ::c_long = 78; pub const SYS_sync: ::c_long = 81; pub const SYS_fsync: ::c_long = 82; pub const SYS_fdatasync: ::c_long = 83; pub const SYS_sync_file_range: ::c_long = 84; pub const SYS_timerfd_create: ::c_long = 85; pub const SYS_timerfd_settime: ::c_long = 86; pub const SYS_timerfd_gettime: ::c_long = 87; pub const SYS_utimensat: ::c_long = 88; pub const SYS_acct: ::c_long = 89; pub const SYS_capget: ::c_long = 90; pub const SYS_capset: ::c_long = 91; pub const SYS_personality: ::c_long = 92; pub const SYS_exit: ::c_long = 93; pub const SYS_exit_group: ::c_long = 94; pub const SYS_waitid: ::c_long = 95; pub const SYS_set_tid_address: ::c_long = 96; pub const SYS_unshare: ::c_long = 97; pub const SYS_futex: ::c_long = 98; pub const SYS_set_robust_list: ::c_long = 99; pub const SYS_get_robust_list: ::c_long = 100; pub const SYS_nanosleep: ::c_long = 101; pub const SYS_getitimer: ::c_long = 102; pub const SYS_setitimer: ::c_long = 103; pub const SYS_kexec_load: ::c_long = 104; pub const SYS_init_module: ::c_long = 105; pub const SYS_delete_module: ::c_long = 106; pub const SYS_timer_create: ::c_long = 107; pub const SYS_timer_gettime: ::c_long = 108; pub const SYS_timer_getoverrun: ::c_long = 109; pub const SYS_timer_settime: ::c_long = 110; pub const SYS_timer_delete: ::c_long = 111; pub const SYS_clock_settime: ::c_long = 112; pub const SYS_clock_gettime: ::c_long = 113; pub const SYS_clock_getres: ::c_long = 114; pub const SYS_clock_nanosleep: ::c_long = 115; pub const SYS_syslog: ::c_long = 116; pub const SYS_ptrace: ::c_long = 117; pub const SYS_sched_setparam: ::c_long = 118; pub const SYS_sched_setscheduler: ::c_long = 119; pub const SYS_sched_getscheduler: ::c_long = 120; pub const SYS_sched_getparam: ::c_long = 121; pub const SYS_sched_setaffinity: ::c_long = 122; pub const SYS_sched_getaffinity: ::c_long = 123; pub const SYS_sched_yield: ::c_long = 124; pub const SYS_sched_get_priority_max: ::c_long = 125; pub const SYS_sched_get_priority_min: ::c_long = 126; pub const SYS_sched_rr_get_interval: ::c_long = 127; pub const SYS_restart_syscall: ::c_long = 128; pub const SYS_kill: ::c_long = 129; pub const SYS_tkill: ::c_long = 130; pub const SYS_tgkill: ::c_long = 131; pub const SYS_sigaltstack: ::c_long = 132; pub const SYS_rt_sigsuspend: ::c_long = 133; pub const SYS_rt_sigaction: ::c_long = 134; pub const SYS_rt_sigprocmask: ::c_long = 135; pub const SYS_rt_sigpending: ::c_long = 136; pub const SYS_rt_sigtimedwait: ::c_long = 137; pub const SYS_rt_sigqueueinfo: ::c_long = 138; pub const SYS_rt_sigreturn: ::c_long = 139; pub const SYS_setpriority: ::c_long = 140; pub const SYS_getpriority: ::c_long = 141; pub const SYS_reboot: ::c_long = 142; pub const SYS_setregid: ::c_long = 143; pub const SYS_setgid: ::c_long = 144; pub const SYS_setreuid: ::c_long = 145; pub const SYS_setuid: ::c_long = 146; pub const SYS_setresuid: ::c_long = 147; pub const SYS_getresuid: ::c_long = 148; pub const SYS_setresgid: ::c_long = 149; pub const SYS_getresgid: ::c_long = 150; pub const SYS_setfsuid: ::c_long = 151; pub const SYS_setfsgid: ::c_long = 152; pub const SYS_times: ::c_long = 153; pub const SYS_setpgid: ::c_long = 154; pub const SYS_getpgid: ::c_long = 155; pub const SYS_getsid: ::c_long = 156; pub const SYS_setsid: ::c_long = 157; pub const SYS_getgroups: ::c_long = 158; pub const SYS_setgroups: ::c_long = 159; pub const SYS_uname: ::c_long = 160; pub const SYS_sethostname: ::c_long = 161; pub const SYS_setdomainname: ::c_long = 162; pub const SYS_getrlimit: ::c_long = 163; pub const SYS_setrlimit: ::c_long = 164; pub const SYS_getrusage: ::c_long = 165; pub const SYS_umask: ::c_long = 166; pub const SYS_prctl: ::c_long = 167; pub const SYS_getcpu: ::c_long = 168; pub const SYS_gettimeofday: ::c_long = 169; pub const SYS_settimeofday: ::c_long = 170; pub const SYS_adjtimex: ::c_long = 171; pub const SYS_getpid: ::c_long = 172; pub const SYS_getppid: ::c_long = 173; pub const SYS_getuid: ::c_long = 174; pub const SYS_geteuid: ::c_long = 175; pub const SYS_getgid: ::c_long = 176; pub const SYS_getegid: ::c_long = 177; pub const SYS_gettid: ::c_long = 178; pub const SYS_sysinfo: ::c_long = 179; pub const SYS_mq_open: ::c_long = 180; pub const SYS_mq_unlink: ::c_long = 181; pub const SYS_mq_timedsend: ::c_long = 182; pub const SYS_mq_timedreceive: ::c_long = 183; pub const SYS_mq_notify: ::c_long = 184; pub const SYS_mq_getsetattr: ::c_long = 185; pub const SYS_msgget: ::c_long = 186; pub const SYS_msgctl: ::c_long = 187; pub const SYS_msgrcv: ::c_long = 188; pub const SYS_msgsnd: ::c_long = 189; pub const SYS_semget: ::c_long = 190; pub const SYS_semctl: ::c_long = 191; pub const SYS_semtimedop: ::c_long = 192; pub const SYS_semop: ::c_long = 193; pub const SYS_shmget: ::c_long = 194; pub const SYS_shmctl: ::c_long = 195; pub const SYS_shmat: ::c_long = 196; pub const SYS_shmdt: ::c_long = 197; pub const SYS_socket: ::c_long = 198; pub const SYS_socketpair: ::c_long = 199; pub const SYS_bind: ::c_long = 200; pub const SYS_listen: ::c_long = 201; pub const SYS_accept: ::c_long = 202; pub const SYS_connect: ::c_long = 203; pub const SYS_getsockname: ::c_long = 204; pub const SYS_getpeername: ::c_long = 205; pub const SYS_sendto: ::c_long = 206; pub const SYS_recvfrom: ::c_long = 207; pub const SYS_setsockopt: ::c_long = 208; pub const SYS_getsockopt: ::c_long = 209; pub const SYS_shutdown: ::c_long = 210; pub const SYS_sendmsg: ::c_long = 211; pub const SYS_recvmsg: ::c_long = 212; pub const SYS_readahead: ::c_long = 213; pub const SYS_brk: ::c_long = 214; pub const SYS_munmap: ::c_long = 215; pub const SYS_mremap: ::c_long = 216; pub const SYS_add_key: ::c_long = 217; pub const SYS_request_key: ::c_long = 218; pub const SYS_keyctl: ::c_long = 219; pub const SYS_clone: ::c_long = 220; pub const SYS_execve: ::c_long = 221; pub const SYS_swapon: ::c_long = 224; pub const SYS_swapoff: ::c_long = 225; pub const SYS_mprotect: ::c_long = 226; pub const SYS_msync: ::c_long = 227; pub const SYS_mlock: ::c_long = 228; pub const SYS_munlock: ::c_long = 229; pub const SYS_mlockall: ::c_long = 230; pub const SYS_munlockall: ::c_long = 231; pub const SYS_mincore: ::c_long = 232; pub const SYS_madvise: ::c_long = 233; pub const SYS_remap_file_pages: ::c_long = 234; pub const SYS_mbind: ::c_long = 235; pub const SYS_get_mempolicy: ::c_long = 236; pub const SYS_set_mempolicy: ::c_long = 237; pub const SYS_migrate_pages: ::c_long = 238; pub const SYS_move_pages: ::c_long = 239; pub const SYS_rt_tgsigqueueinfo: ::c_long = 240; pub const SYS_perf_event_open: ::c_long = 241; pub const SYS_accept4: ::c_long = 242; pub const SYS_recvmmsg: ::c_long = 243; pub const SYS_arch_specific_syscall: ::c_long = 244; pub const SYS_wait4: ::c_long = 260; pub const SYS_prlimit64: ::c_long = 261; pub const SYS_fanotify_init: ::c_long = 262; pub const SYS_fanotify_mark: ::c_long = 263; pub const SYS_name_to_handle_at: ::c_long = 264; pub const SYS_open_by_handle_at: ::c_long = 265; pub const SYS_clock_adjtime: ::c_long = 266; pub const SYS_syncfs: ::c_long = 267; pub const SYS_setns: ::c_long = 268; pub const SYS_sendmmsg: ::c_long = 269; pub const SYS_process_vm_readv: ::c_long = 270; pub const SYS_process_vm_writev: ::c_long = 271; pub const SYS_kcmp: ::c_long = 272; pub const SYS_finit_module: ::c_long = 273; pub const SYS_sched_setattr: ::c_long = 274; pub const SYS_sched_getattr: ::c_long = 275; pub const SYS_renameat2: ::c_long = 276; pub const SYS_seccomp: ::c_long = 277; pub const SYS_getrandom: ::c_long = 278; pub const SYS_memfd_create: ::c_long = 279; pub const SYS_bpf: ::c_long = 280; pub const SYS_execveat: ::c_long = 281; pub const SYS_userfaultfd: ::c_long = 282; pub const SYS_membarrier: ::c_long = 283; pub const SYS_mlock2: ::c_long = 284; pub const SYS_copy_file_range: ::c_long = 285; pub const SYS_preadv2: ::c_long = 286; pub const SYS_pwritev2: ::c_long = 287; pub const SYS_pkey_mprotect: ::c_long = 288; pub const SYS_pkey_alloc: ::c_long = 289; pub const SYS_pkey_free: ::c_long = 290; pub const SYS_statx: ::c_long = 291; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; pub const SYS_syscalls: ::c_long = 436; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/android/b64/riscv64/align.rs0000644000175000017500000000022514661133735023341 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f32; 8] } } libc/src/unix/linux_like/android/b64/mod.rs0000644000175000017500000002435714661133735021542 0ustar jamespagejamespage// The following definitions are correct for aarch64 and x86_64, // but may be wrong for mips64 pub type c_long = i64; pub type c_ulong = u64; pub type mode_t = u32; pub type off64_t = i64; pub type socklen_t = u32; s! { pub struct sigset_t { __val: [::c_ulong; 1], } pub struct sigaction { pub sa_flags: ::c_int, pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_restorer: ::Option, } pub struct rlimit64 { pub rlim_cur: ::c_ulonglong, pub rlim_max: ::c_ulonglong, } pub struct pthread_attr_t { pub flags: u32, pub stack_base: *mut ::c_void, pub stack_size: ::size_t, pub guard_size: ::size_t, pub sched_policy: i32, pub sched_priority: i32, __reserved: [::c_char; 16], } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct statfs { pub f_type: u64, pub f_bsize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::__fsid_t, pub f_namelen: u64, pub f_frsize: u64, pub f_flags: u64, pub f_spare: [u64; 4], } pub struct sysinfo { pub uptime: ::c_long, pub loads: [::c_ulong; 3], pub totalram: ::c_ulong, pub freeram: ::c_ulong, pub sharedram: ::c_ulong, pub bufferram: ::c_ulong, pub totalswap: ::c_ulong, pub freeswap: ::c_ulong, pub procs: ::c_ushort, pub pad: ::c_ushort, pub totalhigh: ::c_ulong, pub freehigh: ::c_ulong, pub mem_unit: ::c_uint, pub _f: [::c_char; 0], } pub struct statfs64 { pub f_type: u64, pub f_bsize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::__fsid_t, pub f_namelen: u64, pub f_frsize: u64, pub f_flags: u64, pub f_spare: [u64; 4], } pub struct statvfs64 { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_favail: u64, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, __f_spare: [::c_int; 6], } pub struct pthread_barrier_t { __private: [i64; 4], } pub struct pthread_spinlock_t { __private: i64, } } s_no_extra_traits! { pub struct pthread_mutex_t { value: ::c_int, __reserved: [::c_char; 36], } pub struct pthread_cond_t { value: ::c_int, __reserved: [::c_char; 44], } pub struct pthread_rwlock_t { numLocks: ::c_int, writerThreadId: ::c_int, pendingReaders: ::c_int, pendingWriters: ::c_int, attr: i32, __reserved: [::c_char; 36], } pub struct sigset64_t { __bits: [::c_ulong; 1] } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.value == other.value && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_mutex_t {} impl ::fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_mutex_t") .field("value", &self.value) // FIXME: .field("__reserved", &self.__reserved) .finish() } } impl ::hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.value.hash(state); self.__reserved.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.value == other.value && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_cond_t {} impl ::fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_cond_t") .field("value", &self.value) // FIXME: .field("__reserved", &self.__reserved) .finish() } } impl ::hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.value.hash(state); self.__reserved.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.numLocks == other.numLocks && self.writerThreadId == other.writerThreadId && self.pendingReaders == other.pendingReaders && self.pendingWriters == other.pendingWriters && self.attr == other.attr && self .__reserved .iter() .zip(other.__reserved.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_rwlock_t {} impl ::fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_rwlock_t") .field("numLocks", &self.numLocks) .field("writerThreadId", &self.writerThreadId) .field("pendingReaders", &self.pendingReaders) .field("pendingWriters", &self.pendingWriters) .field("attr", &self.attr) // FIXME: .field("__reserved", &self.__reserved) .finish() } } impl ::hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.numLocks.hash(state); self.writerThreadId.hash(state); self.pendingReaders.hash(state); self.pendingWriters.hash(state); self.attr.hash(state); self.__reserved.hash(state); } } impl ::fmt::Debug for sigset64_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigset64_t") .field("__bits", &self.__bits) .finish() } } } } // These constants must be of the same type of sigaction.sa_flags pub const SA_NOCLDSTOP: ::c_int = 0x00000001; pub const SA_NOCLDWAIT: ::c_int = 0x00000002; pub const SA_NODEFER: ::c_int = 0x40000000; pub const SA_ONSTACK: ::c_int = 0x08000000; pub const SA_RESETHAND: ::c_int = 0x80000000; pub const SA_RESTART: ::c_int = 0x10000000; pub const SA_SIGINFO: ::c_int = 0x00000004; pub const RTLD_GLOBAL: ::c_int = 0x00100; pub const RTLD_NOW: ::c_int = 2; pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; // From NDK's linux/auxvec.h pub const AT_NULL: ::c_ulong = 0; pub const AT_IGNORE: ::c_ulong = 1; pub const AT_EXECFD: ::c_ulong = 2; pub const AT_PHDR: ::c_ulong = 3; pub const AT_PHENT: ::c_ulong = 4; pub const AT_PHNUM: ::c_ulong = 5; pub const AT_PAGESZ: ::c_ulong = 6; pub const AT_BASE: ::c_ulong = 7; pub const AT_FLAGS: ::c_ulong = 8; pub const AT_ENTRY: ::c_ulong = 9; pub const AT_NOTELF: ::c_ulong = 10; pub const AT_UID: ::c_ulong = 11; pub const AT_EUID: ::c_ulong = 12; pub const AT_GID: ::c_ulong = 13; pub const AT_EGID: ::c_ulong = 14; pub const AT_PLATFORM: ::c_ulong = 15; pub const AT_HWCAP: ::c_ulong = 16; pub const AT_CLKTCK: ::c_ulong = 17; pub const AT_SECURE: ::c_ulong = 23; pub const AT_BASE_PLATFORM: ::c_ulong = 24; pub const AT_RANDOM: ::c_ulong = 25; pub const AT_HWCAP2: ::c_ulong = 26; pub const AT_EXECFN: ::c_ulong = 31; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { value: 0, __reserved: [0; 36], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { value: 0, __reserved: [0; 44], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { numLocks: 0, writerThreadId: 0, pendingReaders: 0, pendingWriters: 0, attr: 0, __reserved: [0; 36], }; pub const PTHREAD_STACK_MIN: ::size_t = 4096 * 4; pub const CPU_SETSIZE: ::size_t = 1024; pub const __CPU_BITS: ::size_t = 64; pub const UT_LINESIZE: usize = 32; pub const UT_NAMESIZE: usize = 32; pub const UT_HOSTSIZE: usize = 256; f! { // Sadly, Android before 5.0 (API level 21), the accept4 syscall is not // exposed by the libc. As work-around, we implement it through `syscall` // directly. This workaround can be removed if the minimum version of // Android is bumped. When the workaround is removed, `accept4` can be // moved back to `linux_like/mod.rs` pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int ) -> ::c_int { ::syscall(SYS_accept4, fd, addr, len, flg) as ::c_int } } extern "C" { pub fn getauxval(type_: ::c_ulong) -> ::c_ulong; pub fn __system_property_wait( pi: *const ::prop_info, __old_serial: u32, __new_serial_ptr: *mut u32, __relative_timeout: *const ::timespec, ) -> bool; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/unix/linux_like/android/b64/x86_64/0000775000175000017500000000000014661133735021342 5ustar jamespagejamespagelibc/src/unix/linux_like/android/b64/x86_64/mod.rs0000644000175000017500000007024714661133735022477 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type greg_t = i64; pub type __u64 = ::c_ulonglong; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::c_ulong, pub st_mode: ::c_uint, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::c_long, pub st_blocks: ::c_long, pub st_atime: ::c_long, pub st_atime_nsec: ::c_long, pub st_mtime: ::c_long, pub st_mtime_nsec: ::c_long, pub st_ctime: ::c_long, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 3], } pub struct stat64 { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::c_ulong, pub st_mode: ::c_uint, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off64_t, pub st_blksize: ::c_long, pub st_blocks: ::c_long, pub st_atime: ::c_long, pub st_atime_nsec: ::c_long, pub st_mtime: ::c_long, pub st_mtime_nsec: ::c_long, pub st_ctime: ::c_long, pub st_ctime_nsec: ::c_long, __unused: [::c_long; 3], } pub struct _libc_xmmreg { pub element: [u32; 4], } pub struct user_regs_struct { pub r15: ::c_ulong, pub r14: ::c_ulong, pub r13: ::c_ulong, pub r12: ::c_ulong, pub rbp: ::c_ulong, pub rbx: ::c_ulong, pub r11: ::c_ulong, pub r10: ::c_ulong, pub r9: ::c_ulong, pub r8: ::c_ulong, pub rax: ::c_ulong, pub rcx: ::c_ulong, pub rdx: ::c_ulong, pub rsi: ::c_ulong, pub rdi: ::c_ulong, pub orig_rax: ::c_ulong, pub rip: ::c_ulong, pub cs: ::c_ulong, pub eflags: ::c_ulong, pub rsp: ::c_ulong, pub ss: ::c_ulong, pub fs_base: ::c_ulong, pub gs_base: ::c_ulong, pub ds: ::c_ulong, pub es: ::c_ulong, pub fs: ::c_ulong, pub gs: ::c_ulong, } pub struct user { pub regs: user_regs_struct, pub u_fpvalid: ::c_int, pub i387: user_fpregs_struct, pub u_tsize: ::c_ulong, pub u_dsize: ::c_ulong, pub u_ssize: ::c_ulong, pub start_code: ::c_ulong, pub start_stack: ::c_ulong, pub signal: ::c_long, __reserved: ::c_int, #[cfg(target_pointer_width = "32")] __pad1: u32, pub u_ar0: *mut user_regs_struct, #[cfg(target_pointer_width = "32")] __pad2: u32, pub u_fpstate: *mut user_fpregs_struct, pub magic: ::c_ulong, pub u_comm: [::c_char; 32], pub u_debugreg: [::c_ulong; 8], pub error_code: ::c_ulong, pub fault_address: ::c_ulong, } } cfg_if! { if #[cfg(libc_union)] { s_no_extra_traits! { pub union __c_anonymous_uc_sigmask { uc_sigmask: ::sigset_t, uc_sigmask64: ::sigset64_t, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for __c_anonymous_uc_sigmask { fn eq(&self, other: &__c_anonymous_uc_sigmask) -> bool { unsafe { self.uc_sigmask == other.uc_sigmask } } } impl Eq for __c_anonymous_uc_sigmask {} impl ::fmt::Debug for __c_anonymous_uc_sigmask { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("uc_sigmask") .field("uc_sigmask", unsafe { &self.uc_sigmask }) .finish() } } impl ::hash::Hash for __c_anonymous_uc_sigmask { fn hash(&self, state: &mut H) { unsafe { self.uc_sigmask.hash(state) } } } } } } } s_no_extra_traits! { pub struct _libc_fpxreg { pub significand: [u16; 4], pub exponent: u16, __padding: [u16; 3], } pub struct _libc_fpstate { pub cwd: u16, pub swd: u16, pub ftw: u16, pub fop: u16, pub rip: u64, pub rdp: u64, pub mxcsr: u32, pub mxcr_mask: u32, pub _st: [_libc_fpxreg; 8], pub _xmm: [_libc_xmmreg; 16], __private: [u32; 24], } pub struct mcontext_t { pub gregs: [greg_t; 23], pub fpregs: *mut _libc_fpstate, __private: [u64; 8], } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_sigmask64: __c_anonymous_uc_sigmask, __fpregs_mem: _libc_fpstate, } pub struct user_fpregs_struct { pub cwd: ::c_ushort, pub swd: ::c_ushort, pub ftw: ::c_ushort, pub fop: ::c_ushort, pub rip: ::c_ulong, pub rdp: ::c_ulong, pub mxcsr: ::c_uint, pub mxcr_mask: ::c_uint, pub st_space: [::c_uint; 32], pub xmm_space: [::c_uint; 64], padding: [::c_uint; 24], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for _libc_fpxreg { fn eq(&self, other: &Self) -> bool { self.significand == other.significand && self.exponent == other.exponent // Ignore padding field } } impl Eq for _libc_fpxreg {} impl ::fmt::Debug for _libc_fpxreg { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("_libc_fpxreg") .field("significand", &self.significand) .field("exponent", &self.exponent) // Ignore padding field .finish() } } impl ::hash::Hash for _libc_fpxreg { fn hash(&self, state: &mut H) { self.significand.hash(state); self.exponent.hash(state); // Ignore padding field } } impl PartialEq for _libc_fpstate { fn eq(&self, other: &Self) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self._st == other._st && self._xmm == other._xmm // Ignore padding field } } impl Eq for _libc_fpstate {} impl ::fmt::Debug for _libc_fpstate { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("_libc_fpstate") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("_st", &self._st) .field("_xmm", &self._xmm) // Ignore padding field .finish() } } impl ::hash::Hash for _libc_fpstate { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self._st.hash(state); self._xmm.hash(state); // Ignore padding field } } impl PartialEq for mcontext_t { fn eq(&self, other: &Self) -> bool { self.gregs == other.gregs && self.fpregs == other.fpregs // Ignore padding field } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("gregs", &self.gregs) .field("fpregs", &self.fpregs) // Ignore padding field .finish() } } impl ::hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.gregs.hash(state); self.fpregs.hash(state); // Ignore padding field } } impl PartialEq for ucontext_t { fn eq(&self, other: &Self) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_sigmask64 == other.uc_sigmask64 // Ignore padding field } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_sigmask64", &self.uc_sigmask64) // Ignore padding field .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_flags.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); self.uc_sigmask64.hash(state); // Ignore padding field } } impl PartialEq for user_fpregs_struct { fn eq(&self, other: &user_fpregs_struct) -> bool { self.cwd == other.cwd && self.swd == other.swd && self.ftw == other.ftw && self.fop == other.fop && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mxcr_mask == other.mxcr_mask && self.st_space == other.st_space && self .xmm_space .iter() .zip(other.xmm_space.iter()) .all(|(a,b)| a == b) // Ignore padding field } } impl Eq for user_fpregs_struct {} impl ::fmt::Debug for user_fpregs_struct { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("user_fpregs_struct") .field("cwd", &self.cwd) .field("swd", &self.swd) .field("ftw", &self.ftw) .field("fop", &self.fop) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mxcr_mask", &self.mxcr_mask) .field("st_space", &self.st_space) // FIXME: .field("xmm_space", &self.xmm_space) // Ignore padding field .finish() } } impl ::hash::Hash for user_fpregs_struct { fn hash(&self, state: &mut H) { self.cwd.hash(state); self.swd.hash(state); self.ftw.hash(state); self.fop.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mxcr_mask.hash(state); self.st_space.hash(state); self.xmm_space.hash(state); // Ignore padding field } } } } pub const O_DIRECT: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x10000; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_LARGEFILE: ::c_int = 0o0100000; pub const SIGSTKSZ: ::size_t = 8192; pub const MINSIGSTKSZ: ::size_t = 2048; pub const MAP_32BIT: ::c_int = 0x40; // Syscall table pub const SYS_read: ::c_long = 0; pub const SYS_write: ::c_long = 1; pub const SYS_open: ::c_long = 2; pub const SYS_close: ::c_long = 3; pub const SYS_stat: ::c_long = 4; pub const SYS_fstat: ::c_long = 5; pub const SYS_lstat: ::c_long = 6; pub const SYS_poll: ::c_long = 7; pub const SYS_lseek: ::c_long = 8; pub const SYS_mmap: ::c_long = 9; pub const SYS_mprotect: ::c_long = 10; pub const SYS_munmap: ::c_long = 11; pub const SYS_brk: ::c_long = 12; pub const SYS_rt_sigaction: ::c_long = 13; pub const SYS_rt_sigprocmask: ::c_long = 14; pub const SYS_rt_sigreturn: ::c_long = 15; pub const SYS_ioctl: ::c_long = 16; pub const SYS_pread64: ::c_long = 17; pub const SYS_pwrite64: ::c_long = 18; pub const SYS_readv: ::c_long = 19; pub const SYS_writev: ::c_long = 20; pub const SYS_access: ::c_long = 21; pub const SYS_pipe: ::c_long = 22; pub const SYS_select: ::c_long = 23; pub const SYS_sched_yield: ::c_long = 24; pub const SYS_mremap: ::c_long = 25; pub const SYS_msync: ::c_long = 26; pub const SYS_mincore: ::c_long = 27; pub const SYS_madvise: ::c_long = 28; pub const SYS_shmget: ::c_long = 29; pub const SYS_shmat: ::c_long = 30; pub const SYS_shmctl: ::c_long = 31; pub const SYS_dup: ::c_long = 32; pub const SYS_dup2: ::c_long = 33; pub const SYS_pause: ::c_long = 34; pub const SYS_nanosleep: ::c_long = 35; pub const SYS_getitimer: ::c_long = 36; pub const SYS_alarm: ::c_long = 37; pub const SYS_setitimer: ::c_long = 38; pub const SYS_getpid: ::c_long = 39; pub const SYS_sendfile: ::c_long = 40; pub const SYS_socket: ::c_long = 41; pub const SYS_connect: ::c_long = 42; pub const SYS_accept: ::c_long = 43; pub const SYS_sendto: ::c_long = 44; pub const SYS_recvfrom: ::c_long = 45; pub const SYS_sendmsg: ::c_long = 46; pub const SYS_recvmsg: ::c_long = 47; pub const SYS_shutdown: ::c_long = 48; pub const SYS_bind: ::c_long = 49; pub const SYS_listen: ::c_long = 50; pub const SYS_getsockname: ::c_long = 51; pub const SYS_getpeername: ::c_long = 52; pub const SYS_socketpair: ::c_long = 53; pub const SYS_setsockopt: ::c_long = 54; pub const SYS_getsockopt: ::c_long = 55; pub const SYS_clone: ::c_long = 56; pub const SYS_fork: ::c_long = 57; pub const SYS_vfork: ::c_long = 58; pub const SYS_execve: ::c_long = 59; pub const SYS_exit: ::c_long = 60; pub const SYS_wait4: ::c_long = 61; pub const SYS_kill: ::c_long = 62; pub const SYS_uname: ::c_long = 63; pub const SYS_semget: ::c_long = 64; pub const SYS_semop: ::c_long = 65; pub const SYS_semctl: ::c_long = 66; pub const SYS_shmdt: ::c_long = 67; pub const SYS_msgget: ::c_long = 68; pub const SYS_msgsnd: ::c_long = 69; pub const SYS_msgrcv: ::c_long = 70; pub const SYS_msgctl: ::c_long = 71; pub const SYS_fcntl: ::c_long = 72; pub const SYS_flock: ::c_long = 73; pub const SYS_fsync: ::c_long = 74; pub const SYS_fdatasync: ::c_long = 75; pub const SYS_truncate: ::c_long = 76; pub const SYS_ftruncate: ::c_long = 77; pub const SYS_getdents: ::c_long = 78; pub const SYS_getcwd: ::c_long = 79; pub const SYS_chdir: ::c_long = 80; pub const SYS_fchdir: ::c_long = 81; pub const SYS_rename: ::c_long = 82; pub const SYS_mkdir: ::c_long = 83; pub const SYS_rmdir: ::c_long = 84; pub const SYS_creat: ::c_long = 85; pub const SYS_link: ::c_long = 86; pub const SYS_unlink: ::c_long = 87; pub const SYS_symlink: ::c_long = 88; pub const SYS_readlink: ::c_long = 89; pub const SYS_chmod: ::c_long = 90; pub const SYS_fchmod: ::c_long = 91; pub const SYS_chown: ::c_long = 92; pub const SYS_fchown: ::c_long = 93; pub const SYS_lchown: ::c_long = 94; pub const SYS_umask: ::c_long = 95; pub const SYS_gettimeofday: ::c_long = 96; pub const SYS_getrlimit: ::c_long = 97; pub const SYS_getrusage: ::c_long = 98; pub const SYS_sysinfo: ::c_long = 99; pub const SYS_times: ::c_long = 100; pub const SYS_ptrace: ::c_long = 101; pub const SYS_getuid: ::c_long = 102; pub const SYS_syslog: ::c_long = 103; pub const SYS_getgid: ::c_long = 104; pub const SYS_setuid: ::c_long = 105; pub const SYS_setgid: ::c_long = 106; pub const SYS_geteuid: ::c_long = 107; pub const SYS_getegid: ::c_long = 108; pub const SYS_setpgid: ::c_long = 109; pub const SYS_getppid: ::c_long = 110; pub const SYS_getpgrp: ::c_long = 111; pub const SYS_setsid: ::c_long = 112; pub const SYS_setreuid: ::c_long = 113; pub const SYS_setregid: ::c_long = 114; pub const SYS_getgroups: ::c_long = 115; pub const SYS_setgroups: ::c_long = 116; pub const SYS_setresuid: ::c_long = 117; pub const SYS_getresuid: ::c_long = 118; pub const SYS_setresgid: ::c_long = 119; pub const SYS_getresgid: ::c_long = 120; pub const SYS_getpgid: ::c_long = 121; pub const SYS_setfsuid: ::c_long = 122; pub const SYS_setfsgid: ::c_long = 123; pub const SYS_getsid: ::c_long = 124; pub const SYS_capget: ::c_long = 125; pub const SYS_capset: ::c_long = 126; pub const SYS_rt_sigpending: ::c_long = 127; pub const SYS_rt_sigtimedwait: ::c_long = 128; pub const SYS_rt_sigqueueinfo: ::c_long = 129; pub const SYS_rt_sigsuspend: ::c_long = 130; pub const SYS_sigaltstack: ::c_long = 131; pub const SYS_utime: ::c_long = 132; pub const SYS_mknod: ::c_long = 133; pub const SYS_uselib: ::c_long = 134; pub const SYS_personality: ::c_long = 135; pub const SYS_ustat: ::c_long = 136; pub const SYS_statfs: ::c_long = 137; pub const SYS_fstatfs: ::c_long = 138; pub const SYS_sysfs: ::c_long = 139; pub const SYS_getpriority: ::c_long = 140; pub const SYS_setpriority: ::c_long = 141; pub const SYS_sched_setparam: ::c_long = 142; pub const SYS_sched_getparam: ::c_long = 143; pub const SYS_sched_setscheduler: ::c_long = 144; pub const SYS_sched_getscheduler: ::c_long = 145; pub const SYS_sched_get_priority_max: ::c_long = 146; pub const SYS_sched_get_priority_min: ::c_long = 147; pub const SYS_sched_rr_get_interval: ::c_long = 148; pub const SYS_mlock: ::c_long = 149; pub const SYS_munlock: ::c_long = 150; pub const SYS_mlockall: ::c_long = 151; pub const SYS_munlockall: ::c_long = 152; pub const SYS_vhangup: ::c_long = 153; pub const SYS_modify_ldt: ::c_long = 154; pub const SYS_pivot_root: ::c_long = 155; // FIXME: SYS__sysctl is in the NDK sources but for some reason is // not available in the tests // pub const SYS__sysctl: ::c_long = 156; pub const SYS_prctl: ::c_long = 157; pub const SYS_arch_prctl: ::c_long = 158; pub const SYS_adjtimex: ::c_long = 159; pub const SYS_setrlimit: ::c_long = 160; pub const SYS_chroot: ::c_long = 161; pub const SYS_sync: ::c_long = 162; pub const SYS_acct: ::c_long = 163; pub const SYS_settimeofday: ::c_long = 164; pub const SYS_mount: ::c_long = 165; pub const SYS_umount2: ::c_long = 166; pub const SYS_swapon: ::c_long = 167; pub const SYS_swapoff: ::c_long = 168; pub const SYS_reboot: ::c_long = 169; pub const SYS_sethostname: ::c_long = 170; pub const SYS_setdomainname: ::c_long = 171; pub const SYS_iopl: ::c_long = 172; pub const SYS_ioperm: ::c_long = 173; pub const SYS_create_module: ::c_long = 174; pub const SYS_init_module: ::c_long = 175; pub const SYS_delete_module: ::c_long = 176; pub const SYS_get_kernel_syms: ::c_long = 177; pub const SYS_query_module: ::c_long = 178; pub const SYS_quotactl: ::c_long = 179; pub const SYS_nfsservctl: ::c_long = 180; pub const SYS_getpmsg: ::c_long = 181; pub const SYS_putpmsg: ::c_long = 182; pub const SYS_afs_syscall: ::c_long = 183; pub const SYS_tuxcall: ::c_long = 184; pub const SYS_security: ::c_long = 185; pub const SYS_gettid: ::c_long = 186; pub const SYS_readahead: ::c_long = 187; pub const SYS_setxattr: ::c_long = 188; pub const SYS_lsetxattr: ::c_long = 189; pub const SYS_fsetxattr: ::c_long = 190; pub const SYS_getxattr: ::c_long = 191; pub const SYS_lgetxattr: ::c_long = 192; pub const SYS_fgetxattr: ::c_long = 193; pub const SYS_listxattr: ::c_long = 194; pub const SYS_llistxattr: ::c_long = 195; pub const SYS_flistxattr: ::c_long = 196; pub const SYS_removexattr: ::c_long = 197; pub const SYS_lremovexattr: ::c_long = 198; pub const SYS_fremovexattr: ::c_long = 199; pub const SYS_tkill: ::c_long = 200; pub const SYS_time: ::c_long = 201; pub const SYS_futex: ::c_long = 202; pub const SYS_sched_setaffinity: ::c_long = 203; pub const SYS_sched_getaffinity: ::c_long = 204; pub const SYS_set_thread_area: ::c_long = 205; pub const SYS_io_setup: ::c_long = 206; pub const SYS_io_destroy: ::c_long = 207; pub const SYS_io_getevents: ::c_long = 208; pub const SYS_io_submit: ::c_long = 209; pub const SYS_io_cancel: ::c_long = 210; pub const SYS_get_thread_area: ::c_long = 211; pub const SYS_lookup_dcookie: ::c_long = 212; pub const SYS_epoll_create: ::c_long = 213; pub const SYS_epoll_ctl_old: ::c_long = 214; pub const SYS_epoll_wait_old: ::c_long = 215; pub const SYS_remap_file_pages: ::c_long = 216; pub const SYS_getdents64: ::c_long = 217; pub const SYS_set_tid_address: ::c_long = 218; pub const SYS_restart_syscall: ::c_long = 219; pub const SYS_semtimedop: ::c_long = 220; pub const SYS_fadvise64: ::c_long = 221; pub const SYS_timer_create: ::c_long = 222; pub const SYS_timer_settime: ::c_long = 223; pub const SYS_timer_gettime: ::c_long = 224; pub const SYS_timer_getoverrun: ::c_long = 225; pub const SYS_timer_delete: ::c_long = 226; pub const SYS_clock_settime: ::c_long = 227; pub const SYS_clock_gettime: ::c_long = 228; pub const SYS_clock_getres: ::c_long = 229; pub const SYS_clock_nanosleep: ::c_long = 230; pub const SYS_exit_group: ::c_long = 231; pub const SYS_epoll_wait: ::c_long = 232; pub const SYS_epoll_ctl: ::c_long = 233; pub const SYS_tgkill: ::c_long = 234; pub const SYS_utimes: ::c_long = 235; pub const SYS_vserver: ::c_long = 236; pub const SYS_mbind: ::c_long = 237; pub const SYS_set_mempolicy: ::c_long = 238; pub const SYS_get_mempolicy: ::c_long = 239; pub const SYS_mq_open: ::c_long = 240; pub const SYS_mq_unlink: ::c_long = 241; pub const SYS_mq_timedsend: ::c_long = 242; pub const SYS_mq_timedreceive: ::c_long = 243; pub const SYS_mq_notify: ::c_long = 244; pub const SYS_mq_getsetattr: ::c_long = 245; pub const SYS_kexec_load: ::c_long = 246; pub const SYS_waitid: ::c_long = 247; pub const SYS_add_key: ::c_long = 248; pub const SYS_request_key: ::c_long = 249; pub const SYS_keyctl: ::c_long = 250; pub const SYS_ioprio_set: ::c_long = 251; pub const SYS_ioprio_get: ::c_long = 252; pub const SYS_inotify_init: ::c_long = 253; pub const SYS_inotify_add_watch: ::c_long = 254; pub const SYS_inotify_rm_watch: ::c_long = 255; pub const SYS_migrate_pages: ::c_long = 256; pub const SYS_openat: ::c_long = 257; pub const SYS_mkdirat: ::c_long = 258; pub const SYS_mknodat: ::c_long = 259; pub const SYS_fchownat: ::c_long = 260; pub const SYS_futimesat: ::c_long = 261; pub const SYS_newfstatat: ::c_long = 262; pub const SYS_unlinkat: ::c_long = 263; pub const SYS_renameat: ::c_long = 264; pub const SYS_linkat: ::c_long = 265; pub const SYS_symlinkat: ::c_long = 266; pub const SYS_readlinkat: ::c_long = 267; pub const SYS_fchmodat: ::c_long = 268; pub const SYS_faccessat: ::c_long = 269; pub const SYS_pselect6: ::c_long = 270; pub const SYS_ppoll: ::c_long = 271; pub const SYS_unshare: ::c_long = 272; pub const SYS_set_robust_list: ::c_long = 273; pub const SYS_get_robust_list: ::c_long = 274; pub const SYS_splice: ::c_long = 275; pub const SYS_tee: ::c_long = 276; pub const SYS_sync_file_range: ::c_long = 277; pub const SYS_vmsplice: ::c_long = 278; pub const SYS_move_pages: ::c_long = 279; pub const SYS_utimensat: ::c_long = 280; pub const SYS_epoll_pwait: ::c_long = 281; pub const SYS_signalfd: ::c_long = 282; pub const SYS_timerfd_create: ::c_long = 283; pub const SYS_eventfd: ::c_long = 284; pub const SYS_fallocate: ::c_long = 285; pub const SYS_timerfd_settime: ::c_long = 286; pub const SYS_timerfd_gettime: ::c_long = 287; pub const SYS_accept4: ::c_long = 288; pub const SYS_signalfd4: ::c_long = 289; pub const SYS_eventfd2: ::c_long = 290; pub const SYS_epoll_create1: ::c_long = 291; pub const SYS_dup3: ::c_long = 292; pub const SYS_pipe2: ::c_long = 293; pub const SYS_inotify_init1: ::c_long = 294; pub const SYS_preadv: ::c_long = 295; pub const SYS_pwritev: ::c_long = 296; pub const SYS_rt_tgsigqueueinfo: ::c_long = 297; pub const SYS_perf_event_open: ::c_long = 298; pub const SYS_recvmmsg: ::c_long = 299; pub const SYS_fanotify_init: ::c_long = 300; pub const SYS_fanotify_mark: ::c_long = 301; pub const SYS_prlimit64: ::c_long = 302; pub const SYS_name_to_handle_at: ::c_long = 303; pub const SYS_open_by_handle_at: ::c_long = 304; pub const SYS_clock_adjtime: ::c_long = 305; pub const SYS_syncfs: ::c_long = 306; pub const SYS_sendmmsg: ::c_long = 307; pub const SYS_setns: ::c_long = 308; pub const SYS_getcpu: ::c_long = 309; pub const SYS_process_vm_readv: ::c_long = 310; pub const SYS_process_vm_writev: ::c_long = 311; pub const SYS_kcmp: ::c_long = 312; pub const SYS_finit_module: ::c_long = 313; pub const SYS_sched_setattr: ::c_long = 314; pub const SYS_sched_getattr: ::c_long = 315; pub const SYS_renameat2: ::c_long = 316; pub const SYS_seccomp: ::c_long = 317; pub const SYS_getrandom: ::c_long = 318; pub const SYS_memfd_create: ::c_long = 319; pub const SYS_kexec_file_load: ::c_long = 320; pub const SYS_bpf: ::c_long = 321; pub const SYS_execveat: ::c_long = 322; pub const SYS_userfaultfd: ::c_long = 323; pub const SYS_membarrier: ::c_long = 324; pub const SYS_mlock2: ::c_long = 325; pub const SYS_copy_file_range: ::c_long = 326; pub const SYS_preadv2: ::c_long = 327; pub const SYS_pwritev2: ::c_long = 328; pub const SYS_pkey_mprotect: ::c_long = 329; pub const SYS_pkey_alloc: ::c_long = 330; pub const SYS_pkey_free: ::c_long = 331; pub const SYS_statx: ::c_long = 332; pub const SYS_pidfd_send_signal: ::c_long = 424; pub const SYS_io_uring_setup: ::c_long = 425; pub const SYS_io_uring_enter: ::c_long = 426; pub const SYS_io_uring_register: ::c_long = 427; pub const SYS_open_tree: ::c_long = 428; pub const SYS_move_mount: ::c_long = 429; pub const SYS_fsopen: ::c_long = 430; pub const SYS_fsconfig: ::c_long = 431; pub const SYS_fsmount: ::c_long = 432; pub const SYS_fspick: ::c_long = 433; // offsets in user_regs_structs, from sys/reg.h pub const R15: ::c_int = 0; pub const R14: ::c_int = 1; pub const R13: ::c_int = 2; pub const R12: ::c_int = 3; pub const RBP: ::c_int = 4; pub const RBX: ::c_int = 5; pub const R11: ::c_int = 6; pub const R10: ::c_int = 7; pub const R9: ::c_int = 8; pub const R8: ::c_int = 9; pub const RAX: ::c_int = 10; pub const RCX: ::c_int = 11; pub const RDX: ::c_int = 12; pub const RSI: ::c_int = 13; pub const RDI: ::c_int = 14; pub const ORIG_RAX: ::c_int = 15; pub const RIP: ::c_int = 16; pub const CS: ::c_int = 17; pub const EFLAGS: ::c_int = 18; pub const RSP: ::c_int = 19; pub const SS: ::c_int = 20; pub const FS_BASE: ::c_int = 21; pub const GS_BASE: ::c_int = 22; pub const DS: ::c_int = 23; pub const ES: ::c_int = 24; pub const FS: ::c_int = 25; pub const GS: ::c_int = 26; // offsets in mcontext_t.gregs from sys/ucontext.h pub const REG_R8: ::c_int = 0; pub const REG_R9: ::c_int = 1; pub const REG_R10: ::c_int = 2; pub const REG_R11: ::c_int = 3; pub const REG_R12: ::c_int = 4; pub const REG_R13: ::c_int = 5; pub const REG_R14: ::c_int = 6; pub const REG_R15: ::c_int = 7; pub const REG_RDI: ::c_int = 8; pub const REG_RSI: ::c_int = 9; pub const REG_RBP: ::c_int = 10; pub const REG_RBX: ::c_int = 11; pub const REG_RDX: ::c_int = 12; pub const REG_RAX: ::c_int = 13; pub const REG_RCX: ::c_int = 14; pub const REG_RSP: ::c_int = 15; pub const REG_RIP: ::c_int = 16; pub const REG_EFL: ::c_int = 17; pub const REG_CSGSFS: ::c_int = 18; pub const REG_ERR: ::c_int = 19; pub const REG_TRAPNO: ::c_int = 20; pub const REG_OLDMASK: ::c_int = 21; pub const REG_CR2: ::c_int = 22; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/linux_like/android/b64/x86_64/align.rs0000644000175000017500000000022514661133735022777 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } } libc/src/unix/solarish/0000775000175000017500000000000014661133735016052 5ustar jamespagejamespagelibc/src/unix/solarish/x86.rs0000644000175000017500000000153314661133735017045 0ustar jamespagejamespagepub type Elf32_Addr = ::c_ulong; pub type Elf32_Half = ::c_ushort; pub type Elf32_Off = ::c_ulong; pub type Elf32_Sword = ::c_long; pub type Elf32_Word = ::c_ulong; pub type Elf32_Lword = ::c_ulonglong; pub type Elf32_Phdr = __c_anonymous_Elf32_Phdr; s! { pub struct __c_anonymous_Elf32_Phdr { pub p_type: ::Elf32_Word, pub p_offset: ::Elf32_Off, pub p_vaddr: ::Elf32_Addr, pub p_paddr: ::Elf32_Addr, pub p_filesz: ::Elf32_Word, pub p_memsz: ::Elf32_Word, pub p_flags: ::Elf32_Word, pub p_align: ::Elf32_Word, } pub struct dl_phdr_info { pub dlpi_addr: ::Elf32_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const ::Elf32_Phdr, pub dlpi_phnum: ::Elf32_Half, pub dlpi_adds: ::c_ulonglong, pub dlpi_subs: ::c_ulonglong, } } libc/src/unix/solarish/illumos.rs0000644000175000017500000000537614661133735020115 0ustar jamespagejamespages! { pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_amp: *mut ::c_void, pub shm_lkcnt: ::c_ushort, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_cnattch: ::c_ulong, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_pad4: [i64; 4], } pub struct fil_info { pub fi_flags: ::c_int, pub fi_pos: ::c_int, pub fi_name: [::c_char; ::FILNAME_MAX as usize], } } pub const AF_LOCAL: ::c_int = 1; // AF_UNIX pub const AF_FILE: ::c_int = 1; // AF_UNIX pub const EFD_SEMAPHORE: ::c_int = 0x1; pub const EFD_NONBLOCK: ::c_int = 0x800; pub const EFD_CLOEXEC: ::c_int = 0x80000; pub const TCP_KEEPIDLE: ::c_int = 34; pub const TCP_KEEPCNT: ::c_int = 35; pub const TCP_KEEPINTVL: ::c_int = 36; pub const TCP_CONGESTION: ::c_int = 37; // These constants are correct for 64-bit programs or 32-bit programs that are // not using large-file mode. If Rust ever supports anything other than 64-bit // compilation on illumos, this may require adjustment: pub const F_OFD_GETLK: ::c_int = 47; pub const F_OFD_SETLK: ::c_int = 48; pub const F_OFD_SETLKW: ::c_int = 49; pub const F_FLOCK: ::c_int = 53; pub const F_FLOCKW: ::c_int = 54; pub const F_DUPFD_CLOEXEC: ::c_int = 37; pub const F_DUP2FD_CLOEXEC: ::c_int = 36; pub const FIL_ATTACH: ::c_int = 0x1; pub const FIL_DETACH: ::c_int = 0x2; pub const FIL_LIST: ::c_int = 0x3; pub const FILNAME_MAX: ::c_int = 32; pub const FILF_PROG: ::c_int = 0x1; pub const FILF_AUTO: ::c_int = 0x2; pub const FILF_BYPASS: ::c_int = 0x4; pub const SOL_FILTER: ::c_int = 0xfffc; pub const MADV_PURGE: ::c_int = 9; pub const B1000000: ::speed_t = 24; pub const B1152000: ::speed_t = 25; pub const B1500000: ::speed_t = 26; pub const B2000000: ::speed_t = 27; pub const B2500000: ::speed_t = 28; pub const B3000000: ::speed_t = 29; pub const B3500000: ::speed_t = 30; pub const B4000000: ::speed_t = 31; // sys/systeminfo.h pub const SI_ADDRESS_WIDTH: ::c_int = 520; extern "C" { pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; pub fn mincore(addr: ::caddr_t, len: ::size_t, vec: *mut ::c_char) -> ::c_int; pub fn pset_bind_lwp( pset: ::psetid_t, id: ::id_t, pid: ::pid_t, opset: *mut ::psetid_t, ) -> ::c_int; pub fn pset_getloadavg(pset: ::psetid_t, load: *mut ::c_double, num: ::c_int) -> ::c_int; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn getpagesizes2(pagesize: *mut ::size_t, nelem: ::c_int) -> ::c_int; } libc/src/unix/solarish/x86_64.rs0000644000175000017500000001360714661133735017363 0ustar jamespagejamespagepub type greg_t = ::c_long; pub type Elf64_Addr = ::c_ulong; pub type Elf64_Half = ::c_ushort; pub type Elf64_Off = ::c_ulong; pub type Elf64_Sword = ::c_int; pub type Elf64_Sxword = ::c_long; pub type Elf64_Word = ::c_uint; pub type Elf64_Xword = ::c_ulong; pub type Elf64_Lword = ::c_ulong; pub type Elf64_Phdr = __c_anonymous_Elf64_Phdr; s! { pub struct __c_anonymous_fpchip_state { pub cw: u16, pub sw: u16, pub fctw: u8, pub __fx_rsvd: u8, pub fop: u16, pub rip: u64, pub rdp: u64, pub mxcsr: u32, pub mxcsr_mask: u32, pub st: [::upad128_t; 8], pub xmm: [::upad128_t; 16], pub __fx_ign: [::upad128_t; 6], pub status: u32, pub xstatus: u32, } pub struct __c_anonymous_Elf64_Phdr { pub p_type: ::Elf64_Word, pub p_flags: ::Elf64_Word, pub p_offset: ::Elf64_Off, pub p_vaddr: ::Elf64_Addr, pub p_paddr: ::Elf64_Addr, pub p_filesz: ::Elf64_Xword, pub p_memsz: ::Elf64_Xword, pub p_align: ::Elf64_Xword, } pub struct dl_phdr_info { pub dlpi_addr: ::Elf64_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const ::Elf64_Phdr, pub dlpi_phnum: ::Elf64_Half, pub dlpi_adds: ::c_ulonglong, pub dlpi_subs: ::c_ulonglong, } } s_no_extra_traits! { #[cfg(libc_union)] pub union __c_anonymous_fp_reg_set { pub fpchip_state: __c_anonymous_fpchip_state, pub f_fpregs: [[u32; 13]; 10], } pub struct fpregset_t { pub fp_reg_set: __c_anonymous_fp_reg_set, } pub struct mcontext_t { pub gregs: [::greg_t; 28], pub fpregs: fpregset_t, } pub struct ucontext_t { pub uc_flags: ::c_ulong, pub uc_link: *mut ucontext_t, pub uc_sigmask: ::sigset_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, pub uc_filler: [::c_long; 5], } } cfg_if! { if #[cfg(feature = "extra_traits")] { #[cfg(libc_union)] impl PartialEq for __c_anonymous_fp_reg_set { fn eq(&self, other: &__c_anonymous_fp_reg_set) -> bool { unsafe { self.fpchip_state == other.fpchip_state || self. f_fpregs. iter(). zip(other.f_fpregs.iter()). all(|(a, b)| a == b) } } } #[cfg(libc_union)] impl Eq for __c_anonymous_fp_reg_set {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_fp_reg_set { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("__c_anonymous_fp_reg_set") .field("fpchip_state", &{self.fpchip_state}) .field("f_fpregs", &{self.f_fpregs}) .finish() } } } impl PartialEq for fpregset_t { fn eq(&self, other: &fpregset_t) -> bool { self.fp_reg_set == other.fp_reg_set } } impl Eq for fpregset_t {} impl ::fmt::Debug for fpregset_t { fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpregset_t") .field("fp_reg_set", &self.fp_reg_set) .finish() } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.gregs == other.gregs && self.fpregs == other.fpregs } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("gregs", &self.gregs) .field("fpregs", &self.fpregs) .finish() } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_flags == other.uc_flags && self.uc_link == other.uc_link && self.uc_sigmask == other.uc_sigmask && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext && self.uc_filler == other.uc_filler } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f:&mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_flags", &self.uc_flags) .field("uc_link", &self.uc_link) .field("uc_sigmask", &self.uc_sigmask) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .field("uc_filler", &self.uc_filler) .finish() } } } } // sys/regset.h pub const REG_GSBASE: ::c_int = 27; pub const REG_FSBASE: ::c_int = 26; pub const REG_DS: ::c_int = 25; pub const REG_ES: ::c_int = 24; pub const REG_GS: ::c_int = 23; pub const REG_FS: ::c_int = 22; pub const REG_SS: ::c_int = 21; pub const REG_RSP: ::c_int = 20; pub const REG_RFL: ::c_int = 19; pub const REG_CS: ::c_int = 18; pub const REG_RIP: ::c_int = 17; pub const REG_ERR: ::c_int = 16; pub const REG_TRAPNO: ::c_int = 15; pub const REG_RAX: ::c_int = 14; pub const REG_RCX: ::c_int = 13; pub const REG_RDX: ::c_int = 12; pub const REG_RBX: ::c_int = 11; pub const REG_RBP: ::c_int = 10; pub const REG_RSI: ::c_int = 9; pub const REG_RDI: ::c_int = 8; pub const REG_R8: ::c_int = 7; pub const REG_R9: ::c_int = 6; pub const REG_R10: ::c_int = 5; pub const REG_R11: ::c_int = 4; pub const REG_R12: ::c_int = 3; pub const REG_R13: ::c_int = 2; pub const REG_R14: ::c_int = 1; pub const REG_R15: ::c_int = 0; libc/src/unix/solarish/solaris.rs0000644000175000017500000000567014661133735020102 0ustar jamespagejamespagepub type door_attr_t = ::c_uint; pub type door_id_t = ::c_ulonglong; s! { pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_flags: ::uintptr_t, pub shm_lkcnt: ::c_ushort, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_cnattch: ::c_ulong, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, pub shm_amp: *mut ::c_void, pub shm_gransize: u64, pub shm_allocated: u64, pub shm_pad4: [i64; 1], } pub struct door_desc_t__d_data__d_desc { pub d_descriptor: ::c_int, pub d_id: ::door_id_t } } s_no_extra_traits! { #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub union door_desc_t__d_data { pub d_desc: door_desc_t__d_data__d_desc, d_resv: [::c_int; 5], /* Check out /usr/include/sys/door.h */ } #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub struct door_desc_t { pub d_attributes: door_attr_t, pub d_data: door_desc_t__d_data, } #[cfg_attr(feature = "extra_traits", allow(missing_debug_implementations))] pub struct door_arg_t { pub data_ptr: *const ::c_char, pub data_size: ::size_t, pub desc_ptr: *const door_desc_t, pub dec_num: ::c_uint, pub rbuf: *const ::c_char, pub rsize: ::size_t, } } pub const PORT_SOURCE_POSTWAIT: ::c_int = 8; pub const PORT_SOURCE_SIGNAL: ::c_int = 9; pub const AF_LOCAL: ::c_int = 0; pub const AF_FILE: ::c_int = 0; pub const TCP_KEEPIDLE: ::c_int = 0x1d; pub const TCP_KEEPINTVL: ::c_int = 0x1e; pub const TCP_KEEPCNT: ::c_int = 0x1f; pub const F_DUPFD_CLOEXEC: ::c_int = 47; pub const F_DUPFD_CLOFORK: ::c_int = 49; pub const F_DUP2FD_CLOEXEC: ::c_int = 48; pub const F_DUP2FD_CLOFORK: ::c_int = 50; extern "C" { pub fn fexecve( fd: ::c_int, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn mincore(addr: *const ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; pub fn door_call(d: ::c_int, params: *const door_arg_t) -> ::c_int; pub fn door_return( data_ptr: *const ::c_char, data_size: ::size_t, desc_ptr: *const door_desc_t, num_desc: ::c_uint, ); pub fn door_create( server_procedure: extern "C" fn( cookie: *const ::c_void, argp: *const ::c_char, arg_size: ::size_t, dp: *const door_desc_t, n_desc: ::c_uint, ), cookie: *const ::c_void, attributes: door_attr_t, ) -> ::c_int; pub fn fattach(fildes: ::c_int, path: *const ::c_char) -> ::c_int; pub fn pthread_getattr_np(thread: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn euidaccess(path: *const ::c_char, amode: ::c_int) -> ::c_int; } libc/src/unix/solarish/compat.rs0000644000175000017500000001453414661133735017710 0ustar jamespagejamespage// Common functions that are unfortunately missing on illumos and // Solaris, but often needed by other crates. use core::cmp::min; use unix::solarish::*; const PTEM: &[u8] = b"ptem\0"; const LDTERM: &[u8] = b"ldterm\0"; pub unsafe fn cfmakeraw(termios: *mut ::termios) { (*termios).c_iflag &= !(IMAXBEL | IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); (*termios).c_oflag &= !OPOST; (*termios).c_lflag &= !(ECHO | ECHONL | ICANON | ISIG | IEXTEN); (*termios).c_cflag &= !(CSIZE | PARENB); (*termios).c_cflag |= CS8; // By default, most software expects a pending read to block until at // least one byte becomes available. As per termio(7I), this requires // setting the MIN and TIME parameters appropriately. // // As a somewhat unfortunate artefact of history, the MIN and TIME slots // in the control character array overlap with the EOF and EOL slots used // for canonical mode processing. Because the EOF character needs to be // the ASCII EOT value (aka Control-D), it has the byte value 4. When // switching to raw mode, this is interpreted as a MIN value of 4; i.e., // reads will block until at least four bytes have been input. // // Other platforms with a distinct MIN slot like Linux and FreeBSD appear // to default to a MIN value of 1, so we'll force that value here: (*termios).c_cc[VMIN] = 1; (*termios).c_cc[VTIME] = 0; } pub unsafe fn cfsetspeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int { // Neither of these functions on illumos or Solaris actually ever // return an error ::cfsetispeed(termios, speed); ::cfsetospeed(termios, speed); 0 } unsafe fn bail(fdm: ::c_int, fds: ::c_int) -> ::c_int { let e = *___errno(); if fds >= 0 { ::close(fds); } if fdm >= 0 { ::close(fdm); } *___errno() = e; return -1; } pub unsafe fn openpty( amain: *mut ::c_int, asubord: *mut ::c_int, name: *mut ::c_char, termp: *const termios, winp: *const ::winsize, ) -> ::c_int { // Open the main pseudo-terminal device, making sure not to set it as the // controlling terminal for this process: let fdm = ::posix_openpt(O_RDWR | O_NOCTTY); if fdm < 0 { return -1; } // Set permissions and ownership on the subordinate device and unlock it: if ::grantpt(fdm) < 0 || ::unlockpt(fdm) < 0 { return bail(fdm, -1); } // Get the path name of the subordinate device: let subordpath = ::ptsname(fdm); if subordpath.is_null() { return bail(fdm, -1); } // Open the subordinate device without setting it as the controlling // terminal for this process: let fds = ::open(subordpath, O_RDWR | O_NOCTTY); if fds < 0 { return bail(fdm, -1); } // Check if the STREAMS modules are already pushed: let setup = ::ioctl(fds, I_FIND, LDTERM.as_ptr()); if setup < 0 { return bail(fdm, fds); } else if setup == 0 { // The line discipline is not present, so push the appropriate STREAMS // modules for the subordinate device: if ::ioctl(fds, I_PUSH, PTEM.as_ptr()) < 0 || ::ioctl(fds, I_PUSH, LDTERM.as_ptr()) < 0 { return bail(fdm, fds); } } // If provided, set the terminal parameters: if !termp.is_null() && ::tcsetattr(fds, TCSAFLUSH, termp) != 0 { return bail(fdm, fds); } // If provided, set the window size: if !winp.is_null() && ::ioctl(fds, TIOCSWINSZ, winp) < 0 { return bail(fdm, fds); } // If the caller wants the name of the subordinate device, copy it out. // // Note that this is a terrible interface: there appears to be no standard // upper bound on the copy length for this pointer. Nobody should pass // anything but NULL here, preferring instead to use ptsname(3C) directly. if !name.is_null() { ::strcpy(name, subordpath); } *amain = fdm; *asubord = fds; 0 } pub unsafe fn forkpty( amain: *mut ::c_int, name: *mut ::c_char, termp: *const termios, winp: *const ::winsize, ) -> ::pid_t { let mut fds = -1; if openpty(amain, &mut fds, name, termp, winp) != 0 { return -1; } let pid = ::fork(); if pid < 0 { return bail(*amain, fds); } else if pid > 0 { // In the parent process, we close the subordinate device and return the // process ID of the new child: ::close(fds); return pid; } // The rest of this function executes in the child process. // Close the main side of the pseudo-terminal pair: ::close(*amain); // Use TIOCSCTTY to set the subordinate device as our controlling // terminal. This will fail (with ENOTTY) if we are not the leader in // our own session, so we call setsid() first. Finally, arrange for // the pseudo-terminal to occupy the standard I/O descriptors. if ::setsid() < 0 || ::ioctl(fds, TIOCSCTTY, 0) < 0 || ::dup2(fds, 0) < 0 || ::dup2(fds, 1) < 0 || ::dup2(fds, 2) < 0 { // At this stage there are no particularly good ways to handle failure. // Exit as abruptly as possible, using _exit() to avoid messing with any // state still shared with the parent process. ::_exit(EXIT_FAILURE); } // Close the inherited descriptor, taking care to avoid closing the standard // descriptors by mistake: if fds > 2 { ::close(fds); } 0 } pub unsafe fn getpwent_r( pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int { let old_errno = *::___errno(); *::___errno() = 0; *result = native_getpwent_r( pwd, buf, min(buflen, ::c_int::max_value() as ::size_t) as ::c_int, ); let ret = if (*result).is_null() { *::___errno() } else { 0 }; *::___errno() = old_errno; ret } pub unsafe fn getgrent_r( grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int { let old_errno = *::___errno(); *::___errno() = 0; *result = native_getgrent_r( grp, buf, min(buflen, ::c_int::max_value() as ::size_t) as ::c_int, ); let ret = if (*result).is_null() { *::___errno() } else { 0 }; *::___errno() = old_errno; ret } libc/src/unix/solarish/x86_common.rs0000644000175000017500000000523514661133735020420 0ustar jamespagejamespage// AT_SUN_HWCAP pub const AV_386_FPU: u32 = 0x00001; pub const AV_386_TSC: u32 = 0x00002; pub const AV_386_CX8: u32 = 0x00004; pub const AV_386_SEP: u32 = 0x00008; pub const AV_386_AMD_SYSC: u32 = 0x00010; pub const AV_386_CMOV: u32 = 0x00020; pub const AV_386_MMX: u32 = 0x00040; pub const AV_386_AMD_MMX: u32 = 0x00080; pub const AV_386_AMD_3DNow: u32 = 0x00100; pub const AV_386_AMD_3DNowx: u32 = 0x00200; pub const AV_386_FXSR: u32 = 0x00400; pub const AV_386_SSE: u32 = 0x00800; pub const AV_386_SSE2: u32 = 0x01000; pub const AV_386_CX16: u32 = 0x10000; pub const AV_386_AHF: u32 = 0x20000; pub const AV_386_TSCP: u32 = 0x40000; pub const AV_386_AMD_SSE4A: u32 = 0x80000; pub const AV_386_POPCNT: u32 = 0x100000; pub const AV_386_AMD_LZCNT: u32 = 0x200000; pub const AV_386_SSSE3: u32 = 0x400000; pub const AV_386_SSE4_1: u32 = 0x800000; pub const AV_386_SSE4_2: u32 = 0x1000000; pub const AV_386_MOVBE: u32 = 0x2000000; pub const AV_386_AES: u32 = 0x4000000; pub const AV_386_PCLMULQDQ: u32 = 0x8000000; pub const AV_386_XSAVE: u32 = 0x10000000; pub const AV_386_AVX: u32 = 0x20000000; pub const AV_386_VMX: u32 = 0x40000000; pub const AV_386_AMD_SVM: u32 = 0x80000000; // AT_SUN_HWCAP2 pub const AV_386_2_F16C: u32 = 0x00000001; pub const AV_386_2_RDRAND: u32 = 0x00000002; pub const AV_386_2_BMI1: u32 = 0x00000004; pub const AV_386_2_BMI2: u32 = 0x00000008; pub const AV_386_2_FMA: u32 = 0x00000010; pub const AV_386_2_AVX2: u32 = 0x00000020; pub const AV_386_2_ADX: u32 = 0x00000040; pub const AV_386_2_RDSEED: u32 = 0x00000080; pub const AV_386_2_AVX512F: u32 = 0x00000100; pub const AV_386_2_AVX512DQ: u32 = 0x00000200; pub const AV_386_2_AVX512IFMA: u32 = 0x00000400; pub const AV_386_2_AVX512PF: u32 = 0x00000800; pub const AV_386_2_AVX512ER: u32 = 0x00001000; pub const AV_386_2_AVX512CD: u32 = 0x00002000; pub const AV_386_2_AVX512BW: u32 = 0x00004000; pub const AV_386_2_AVX512VL: u32 = 0x00008000; pub const AV_386_2_AVX512VBMI: u32 = 0x00010000; pub const AV_386_2_AVX512VPOPCDQ: u32 = 0x00020000; pub const AV_386_2_AVX512_4NNIW: u32 = 0x00040000; pub const AV_386_2_AVX512_4FMAPS: u32 = 0x00080000; pub const AV_386_2_SHA: u32 = 0x00100000; pub const AV_386_2_FSGSBASE: u32 = 0x00200000; pub const AV_386_2_CLFLUSHOPT: u32 = 0x00400000; pub const AV_386_2_CLWB: u32 = 0x00800000; pub const AV_386_2_MONITORX: u32 = 0x01000000; pub const AV_386_2_CLZERO: u32 = 0x02000000; pub const AV_386_2_AVX512_VNNI: u32 = 0x04000000; pub const AV_386_2_VPCLMULQDQ: u32 = 0x08000000; pub const AV_386_2_VAES: u32 = 0x10000000; // AT_SUN_FPTYPE pub const AT_386_FPINFO_NONE: u32 = 0; pub const AT_386_FPINFO_FXSAVE: u32 = 1; pub const AT_386_FPINFO_XSAVE: u32 = 2; pub const AT_386_FPINFO_XSAVE_AMD: u32 = 3; libc/src/unix/solarish/mod.rs0000644000175000017500000033540614661133735017210 0ustar jamespagejamespagepub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; pub type caddr_t = *mut ::c_char; pub type clockid_t = ::c_int; pub type blkcnt_t = ::c_long; pub type clock_t = ::c_long; pub type daddr_t = ::c_long; pub type dev_t = ::c_ulong; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type ino_t = ::c_ulong; pub type key_t = ::c_int; pub type major_t = ::c_uint; pub type minor_t = ::c_uint; pub type mode_t = ::c_uint; pub type nlink_t = ::c_uint; pub type rlim_t = ::c_ulong; pub type speed_t = ::c_uint; pub type tcflag_t = ::c_uint; pub type time_t = ::c_long; pub type timer_t = ::c_int; pub type wchar_t = ::c_int; pub type nfds_t = ::c_ulong; pub type projid_t = ::c_int; pub type zoneid_t = ::c_int; pub type psetid_t = ::c_int; pub type processorid_t = ::c_int; pub type chipid_t = ::c_int; pub type ctid_t = ::id_t; pub type suseconds_t = ::c_long; pub type off_t = ::c_long; pub type useconds_t = ::c_uint; pub type socklen_t = ::c_uint; pub type sa_family_t = u16; pub type pthread_t = ::c_uint; pub type pthread_key_t = ::c_uint; pub type thread_t = ::c_uint; pub type blksize_t = ::c_int; pub type nl_item = ::c_int; pub type mqd_t = *mut ::c_void; pub type id_t = ::c_int; pub type idtype_t = ::c_uint; pub type shmatt_t = ::c_ulong; pub type lgrp_rsrc_t = ::c_int; pub type lgrp_affinity_t = ::c_int; pub type lgrp_id_t = ::id_t; pub type lgrp_mem_size_t = ::c_longlong; pub type lgrp_cookie_t = ::uintptr_t; pub type lgrp_content_t = ::c_uint; pub type lgrp_lat_between_t = ::c_uint; pub type lgrp_mem_size_flag_t = ::c_uint; pub type lgrp_view_t = ::c_uint; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum ucred_t {} impl ::Copy for ucred_t {} impl ::Clone for ucred_t { fn clone(&self) -> ucred_t { *self } } s! { pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct ipc_perm { pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub seq: ::c_uint, pub key: ::key_t, } pub struct sockaddr { pub sa_family: sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in { pub sin_family: sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [::c_char; 8] } pub struct sockaddr_in6 { pub sin6_family: sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, pub __sin6_src_id: u32 } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_age: *mut ::c_char, pub pw_comment: *mut ::c_char, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut ::c_char, pub ifa_flags: ::c_ulong, pub ifa_addr: *mut ::sockaddr, pub ifa_netmask: *mut ::sockaddr, pub ifa_dstaddr: *mut ::sockaddr, pub ifa_data: *mut ::c_void } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct pthread_attr_t { __pthread_attrp: *mut ::c_void } pub struct pthread_mutex_t { __pthread_mutex_flag1: u16, __pthread_mutex_flag2: u8, __pthread_mutex_ceiling: u8, __pthread_mutex_type: u16, __pthread_mutex_magic: u16, __pthread_mutex_lock: u64, __pthread_mutex_data: u64 } pub struct pthread_mutexattr_t { __pthread_mutexattrp: *mut ::c_void } pub struct pthread_cond_t { __pthread_cond_flag: [u8; 4], __pthread_cond_type: u16, __pthread_cond_magic: u16, __pthread_cond_data: u64 } pub struct pthread_condattr_t { __pthread_condattrp: *mut ::c_void, } pub struct pthread_rwlock_t { __pthread_rwlock_readers: i32, __pthread_rwlock_type: u16, __pthread_rwlock_magic: u16, __pthread_rwlock_mutex: ::pthread_mutex_t, __pthread_rwlock_readercv: ::pthread_cond_t, __pthread_rwlock_writercv: ::pthread_cond_t } pub struct pthread_rwlockattr_t { __pthread_rwlockattrp: *mut ::c_void, } pub struct dirent { pub d_ino: ::ino_t, pub d_off: ::off_t, pub d_reclen: u16, pub d_name: [::c_char; 3] } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut ::c_char, pub gl_offs: ::size_t, __unused1: *mut ::c_void, __unused2: ::c_int, __unused3: ::c_int, __unused4: ::c_int, __unused5: *mut ::c_void, __unused6: *mut ::c_void, __unused7: *mut ::c_void, __unused8: *mut ::c_void, __unused9: *mut ::c_void, __unused10: *mut ::c_void, } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, #[cfg(target_arch = "sparc64")] __sparcv9_pad: ::c_int, pub ai_addrlen: ::socklen_t, pub ai_canonname: *mut ::c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut addrinfo, } pub struct sigset_t { bits: [u32; 4], } pub struct sigaction { pub sa_flags: ::c_int, pub sa_sigaction: ::sighandler_t, pub sa_mask: sigset_t, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_basetype: [::c_char; 16], pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub f_fstr: [::c_char; 32] } pub struct sendfilevec_t { pub sfv_fd: ::c_int, pub sfv_flag: ::c_uint, pub sfv_off: ::off_t, pub sfv_len: ::size_t, } pub struct sched_param { pub sched_priority: ::c_int, sched_pad: [::c_int; 8] } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, __unused: [::c_char; 16] } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_cc: [::cc_t; ::NCCS] } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct sem_t { pub sem_count: u32, pub sem_type: u16, pub sem_magic: u16, pub sem_pad1: [u64; 3], pub sem_pad2: [u64; 2] } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_sysid: ::c_int, pub l_pid: ::pid_t, pub l_pad: [::c_long; 4] } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } pub struct mq_attr { pub mq_flags: ::c_long, pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, _pad: [::c_int; 12] } pub struct port_event { pub portev_events: ::c_int, pub portev_source: ::c_ushort, pub portev_pad: ::c_ushort, pub portev_object: ::uintptr_t, pub portev_user: *mut ::c_void, } pub struct port_notify { pub portnfy_port: ::c_int, pub portnfy_user: *mut ::c_void, } pub struct exit_status { e_termination: ::c_short, e_exit: ::c_short, } pub struct utmp { pub ut_user: [::c_char; 8], pub ut_id: [::c_char; 4], pub ut_line: [::c_char; 12], pub ut_pid: ::c_short, pub ut_type: ::c_short, pub ut_exit: exit_status, pub ut_time: ::time_t, } pub struct timex { pub modes: u32, pub offset: i32, pub freq: i32, pub maxerror: i32, pub esterror: i32, pub status: i32, pub constant: i32, pub precision: i32, pub tolerance: i32, pub ppsfreq: i32, pub jitter: i32, pub shift: i32, pub stabil: i32, pub jitcnt: i32, pub calcnt: i32, pub errcnt: i32, pub stbcnt: i32, } pub struct ntptimeval { pub time: ::timeval, pub maxerror: i32, pub esterror: i32, } pub struct mmapobj_result_t { pub mr_addr: ::caddr_t, pub mr_msize: ::size_t, pub mr_fsize: ::size_t, pub mr_offset: ::size_t, pub mr_prot: ::c_uint, pub mr_flags: ::c_uint, } pub struct lgrp_affinity_args { pub idtype: ::idtype_t, pub id: ::id_t, pub lgrp: ::lgrp_id_t, pub aff: ::lgrp_affinity_t, } pub struct processor_info_t { pub pi_state: ::c_int, pub pi_processor_type: [::c_char; PI_TYPELEN as usize], pub pi_fputypes: [::c_char; PI_FPUTYPE as usize], pub pi_clock: ::c_int, } pub struct option { pub name: *const ::c_char, pub has_arg: ::c_int, pub flag: *mut ::c_int, pub val: ::c_int, } } s_no_extra_traits! { #[cfg_attr(all( any(target_arch = "x86", target_arch = "x86_64"), libc_packedN ), repr(packed(4)))] #[cfg_attr(all( any(target_arch = "x86", target_arch = "x86_64"), not(libc_packedN) ), repr(packed))] pub struct epoll_event { pub events: u32, pub u64: u64, } pub struct utmpx { pub ut_user: [::c_char; _UTX_USERSIZE], pub ut_id: [::c_char; _UTX_IDSIZE], pub ut_line: [::c_char; _UTX_LINESIZE], pub ut_pid: ::pid_t, pub ut_type: ::c_short, pub ut_exit: exit_status, pub ut_tv: ::timeval, pub ut_session: ::c_int, pub ut_pad: [::c_int; _UTX_PADSIZE], pub ut_syslen: ::c_short, pub ut_host: [::c_char; _UTX_HOSTSIZE], } pub struct sockaddr_un { pub sun_family: sa_family_t, pub sun_path: [c_char; 108] } pub struct utsname { pub sysname: [::c_char; 257], pub nodename: [::c_char; 257], pub release: [::c_char; 257], pub version: [::c_char; 257], pub machine: [::c_char; 257], } pub struct fd_set { #[cfg(target_pointer_width = "64")] fds_bits: [i64; FD_SETSIZE / 64], #[cfg(target_pointer_width = "32")] fds_bits: [i32; FD_SETSIZE / 32], } pub struct sockaddr_storage { pub ss_family: ::sa_family_t, __ss_pad1: [u8; 6], __ss_align: i64, __ss_pad2: [u8; 240], } #[cfg_attr(all(target_pointer_width = "64", libc_align), repr(align(8)))] pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, #[cfg(target_pointer_width = "64")] pub si_pad: ::c_int, __data_pad: [::c_int; SIGINFO_DATA_SIZE], } pub struct sockaddr_dl { pub sdl_family: ::c_ushort, pub sdl_index: ::c_ushort, pub sdl_type: ::c_uchar, pub sdl_nlen: ::c_uchar, pub sdl_alen: ::c_uchar, pub sdl_slen: ::c_uchar, pub sdl_data: [::c_char; 244], } pub struct sigevent { pub sigev_notify: ::c_int, pub sigev_signo: ::c_int, pub sigev_value: ::sigval, pub ss_sp: *mut ::c_void, pub sigev_notify_attributes: *const ::pthread_attr_t, __sigev_pad2: ::c_int, } #[cfg(libc_union)] #[cfg_attr(libc_align, repr(align(16)))] pub union pad128_t { // pub _q in this structure would be a "long double", of 16 bytes pub _l: [i32; 4], } #[cfg(libc_union)] #[cfg_attr(libc_align, repr(align(16)))] pub union upad128_t { // pub _q in this structure would be a "long double", of 16 bytes pub _l: [u32; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_user == other.ut_user && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_syslen == other.ut_syslen && self.ut_pad == other.ut_pad && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_user", &self.ut_user) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) .field("ut_pid", &self.ut_pid) .field("ut_type", &self.ut_type) .field("ut_exit", &self.ut_exit) .field("ut_tv", &self.ut_tv) .field("ut_session", &self.ut_session) .field("ut_pad", &self.ut_pad) .field("ut_syslen", &self.ut_syslen) .field("ut_host", &&self.ut_host[..]) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_user.hash(state); self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_syslen.hash(state); self.ut_pad.hash(state); } } impl PartialEq for epoll_event { fn eq(&self, other: &epoll_event) -> bool { self.events == other.events && self.u64 == other.u64 } } impl Eq for epoll_event {} impl ::fmt::Debug for epoll_event { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let events = self.events; let u64 = self.u64; f.debug_struct("epoll_event") .field("events", &events) .field("u64", &u64) .finish() } } impl ::hash::Hash for epoll_event { fn hash(&self, state: &mut H) { let events = self.events; let u64 = self.u64; events.hash(state); u64.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_un {} impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl ::hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl ::fmt::Debug for utsname { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utsname") // FIXME: .field("sysname", &self.sysname) // FIXME: .field("nodename", &self.nodename) // FIXME: .field("release", &self.release) // FIXME: .field("version", &self.version) // FIXME: .field("machine", &self.machine) .finish() } } impl ::hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } impl PartialEq for fd_set { fn eq(&self, other: &fd_set) -> bool { self.fds_bits .iter() .zip(other.fds_bits.iter()) .all(|(a, b)| a == b) } } impl Eq for fd_set {} impl ::fmt::Debug for fd_set { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fd_set") // FIXME: .field("fds_bits", &self.fds_bits) .finish() } } impl ::hash::Hash for fd_set { fn hash(&self, state: &mut H) { self.fds_bits.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME: .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl siginfo_t { /// The siginfo_t will have differing contents based on the delivered signal. Based on /// `si_signo`, this determines how many of the `c_int` pad fields contain valid data /// exposed by the C unions. /// /// It is not yet exhausitive for the OS-defined types, and defaults to assuming the /// entire data pad area is "valid" for otherwise unrecognized signal numbers. fn data_field_count(&self) -> usize { match self.si_signo { ::SIGSEGV | ::SIGBUS | ::SIGILL | ::SIGTRAP | ::SIGFPE => { ::mem::size_of::() / ::mem::size_of::<::c_int>() } ::SIGCLD => ::mem::size_of::() / ::mem::size_of::<::c_int>(), ::SIGHUP | ::SIGINT | ::SIGQUIT | ::SIGABRT | ::SIGSYS | ::SIGPIPE | ::SIGALRM | ::SIGTERM | ::SIGUSR1 | ::SIGUSR2 | ::SIGPWR | ::SIGWINCH | ::SIGURG => ::mem::size_of::() / ::mem::size_of::<::c_int>(), _ => SIGINFO_DATA_SIZE, } } } impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { if self.si_signo == other.si_signo && self.si_code == other.si_code && self.si_errno == other.si_errno { // FIXME: The `si_pad` field in the 64-bit version of the struct is ignored // (for now) when doing comparisons. let field_count = self.data_field_count(); self.__data_pad[..field_count] .iter() .zip(other.__data_pad[..field_count].iter()) .all(|(a, b)| a == b) } else { false } } } impl Eq for siginfo_t {} impl ::fmt::Debug for siginfo_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_code", &self.si_code) .field("si_errno", &self.si_errno) // FIXME: .field("__pad", &self.__pad) .finish() } } impl ::hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_code.hash(state); self.si_errno.hash(state); // FIXME: The `si_pad` field in the 64-bit version of the struct is ignored // (for now) when doing hashing. let field_count = self.data_field_count(); self.__data_pad[..field_count].hash(state) } } impl PartialEq for sockaddr_dl { fn eq(&self, other: &sockaddr_dl) -> bool { self.sdl_family == other.sdl_family && self.sdl_index == other.sdl_index && self.sdl_type == other.sdl_type && self.sdl_nlen == other.sdl_nlen && self.sdl_alen == other.sdl_alen && self.sdl_slen == other.sdl_slen && self .sdl_data .iter() .zip(other.sdl_data.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_dl {} impl ::fmt::Debug for sockaddr_dl { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_dl") .field("sdl_family", &self.sdl_family) .field("sdl_index", &self.sdl_index) .field("sdl_type", &self.sdl_type) .field("sdl_nlen", &self.sdl_nlen) .field("sdl_alen", &self.sdl_alen) .field("sdl_slen", &self.sdl_slen) // FIXME: .field("sdl_data", &self.sdl_data) .finish() } } impl ::hash::Hash for sockaddr_dl { fn hash(&self, state: &mut H) { self.sdl_family.hash(state); self.sdl_index.hash(state); self.sdl_type.hash(state); self.sdl_nlen.hash(state); self.sdl_alen.hash(state); self.sdl_slen.hash(state); self.sdl_data.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.ss_sp == other.ss_sp && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("ss_sp", &self.ss_sp) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.ss_sp.hash(state); self.sigev_notify_attributes.hash(state); } } #[cfg(libc_union)] impl PartialEq for pad128_t { fn eq(&self, other: &pad128_t) -> bool { unsafe { // FIXME: self._q == other._q || self._l == other._l } } } #[cfg(libc_union)] impl Eq for pad128_t {} #[cfg(libc_union)] impl ::fmt::Debug for pad128_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("pad128_t") // FIXME: .field("_q", &{self._q}) .field("_l", &{self._l}) .finish() } } } #[cfg(libc_union)] impl ::hash::Hash for pad128_t { fn hash(&self, state: &mut H) { unsafe { // FIXME: state.write_i64(self._q as i64); self._l.hash(state); } } } #[cfg(libc_union)] impl PartialEq for upad128_t { fn eq(&self, other: &upad128_t) -> bool { unsafe { // FIXME: self._q == other._q || self._l == other._l } } } #[cfg(libc_union)] impl Eq for upad128_t {} #[cfg(libc_union)] impl ::fmt::Debug for upad128_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("upad128_t") // FIXME: .field("_q", &{self._q}) .field("_l", &{self._l}) .finish() } } } #[cfg(libc_union)] impl ::hash::Hash for upad128_t { fn hash(&self, state: &mut H) { unsafe { // FIXME: state.write_i64(self._q as i64); self._l.hash(state); } } } } } cfg_if! { if #[cfg(target_pointer_width = "64")] { const SIGINFO_DATA_SIZE: usize = 60; } else { const SIGINFO_DATA_SIZE: usize = 29; } } #[repr(C)] struct siginfo_fault { addr: *mut ::c_void, trapno: ::c_int, pc: *mut ::caddr_t, } impl ::Copy for siginfo_fault {} impl ::Clone for siginfo_fault { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_cldval { utime: ::clock_t, status: ::c_int, stime: ::clock_t, } impl ::Copy for siginfo_cldval {} impl ::Clone for siginfo_cldval { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_killval { uid: ::uid_t, value: ::sigval, // Pad out to match the SIGCLD value size _pad: *mut ::c_void, } impl ::Copy for siginfo_killval {} impl ::Clone for siginfo_killval { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_sigcld { pid: ::pid_t, val: siginfo_cldval, ctid: ::ctid_t, zoneid: ::zoneid_t, } impl ::Copy for siginfo_sigcld {} impl ::Clone for siginfo_sigcld { fn clone(&self) -> Self { *self } } #[repr(C)] struct siginfo_kill { pid: ::pid_t, val: siginfo_killval, ctid: ::ctid_t, zoneid: ::zoneid_t, } impl ::Copy for siginfo_kill {} impl ::Clone for siginfo_kill { fn clone(&self) -> Self { *self } } impl siginfo_t { unsafe fn sidata(&self) -> T { *((&self.__data_pad) as *const ::c_int as *const T) } pub unsafe fn si_addr(&self) -> *mut ::c_void { let sifault: siginfo_fault = self.sidata(); sifault.addr } pub unsafe fn si_uid(&self) -> ::uid_t { let kill: siginfo_kill = self.sidata(); kill.val.uid } pub unsafe fn si_value(&self) -> ::sigval { let kill: siginfo_kill = self.sidata(); kill.val.value } pub unsafe fn si_pid(&self) -> ::pid_t { let sigcld: siginfo_sigcld = self.sidata(); sigcld.pid } pub unsafe fn si_status(&self) -> ::c_int { let sigcld: siginfo_sigcld = self.sidata(); sigcld.val.status } pub unsafe fn si_utime(&self) -> ::c_long { let sigcld: siginfo_sigcld = self.sidata(); sigcld.val.utime } pub unsafe fn si_stime(&self) -> ::c_long { let sigcld: siginfo_sigcld = self.sidata(); sigcld.val.stime } } pub const LC_CTYPE: ::c_int = 0; pub const LC_NUMERIC: ::c_int = 1; pub const LC_TIME: ::c_int = 2; pub const LC_COLLATE: ::c_int = 3; pub const LC_MONETARY: ::c_int = 4; pub const LC_MESSAGES: ::c_int = 5; pub const LC_ALL: ::c_int = 6; pub const LC_CTYPE_MASK: ::c_int = 1 << LC_CTYPE; pub const LC_NUMERIC_MASK: ::c_int = 1 << LC_NUMERIC; pub const LC_TIME_MASK: ::c_int = 1 << LC_TIME; pub const LC_COLLATE_MASK: ::c_int = 1 << LC_COLLATE; pub const LC_MONETARY_MASK: ::c_int = 1 << LC_MONETARY; pub const LC_MESSAGES_MASK: ::c_int = 1 << LC_MESSAGES; pub const LC_ALL_MASK: ::c_int = LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK | LC_MONETARY_MASK | LC_MESSAGES_MASK; pub const DAY_1: ::nl_item = 1; pub const DAY_2: ::nl_item = 2; pub const DAY_3: ::nl_item = 3; pub const DAY_4: ::nl_item = 4; pub const DAY_5: ::nl_item = 5; pub const DAY_6: ::nl_item = 6; pub const DAY_7: ::nl_item = 7; pub const ABDAY_1: ::nl_item = 8; pub const ABDAY_2: ::nl_item = 9; pub const ABDAY_3: ::nl_item = 10; pub const ABDAY_4: ::nl_item = 11; pub const ABDAY_5: ::nl_item = 12; pub const ABDAY_6: ::nl_item = 13; pub const ABDAY_7: ::nl_item = 14; pub const MON_1: ::nl_item = 15; pub const MON_2: ::nl_item = 16; pub const MON_3: ::nl_item = 17; pub const MON_4: ::nl_item = 18; pub const MON_5: ::nl_item = 19; pub const MON_6: ::nl_item = 20; pub const MON_7: ::nl_item = 21; pub const MON_8: ::nl_item = 22; pub const MON_9: ::nl_item = 23; pub const MON_10: ::nl_item = 24; pub const MON_11: ::nl_item = 25; pub const MON_12: ::nl_item = 26; pub const ABMON_1: ::nl_item = 27; pub const ABMON_2: ::nl_item = 28; pub const ABMON_3: ::nl_item = 29; pub const ABMON_4: ::nl_item = 30; pub const ABMON_5: ::nl_item = 31; pub const ABMON_6: ::nl_item = 32; pub const ABMON_7: ::nl_item = 33; pub const ABMON_8: ::nl_item = 34; pub const ABMON_9: ::nl_item = 35; pub const ABMON_10: ::nl_item = 36; pub const ABMON_11: ::nl_item = 37; pub const ABMON_12: ::nl_item = 38; pub const RADIXCHAR: ::nl_item = 39; pub const THOUSEP: ::nl_item = 40; pub const YESSTR: ::nl_item = 41; pub const NOSTR: ::nl_item = 42; pub const CRNCYSTR: ::nl_item = 43; pub const D_T_FMT: ::nl_item = 44; pub const D_FMT: ::nl_item = 45; pub const T_FMT: ::nl_item = 46; pub const AM_STR: ::nl_item = 47; pub const PM_STR: ::nl_item = 48; pub const CODESET: ::nl_item = 49; pub const T_FMT_AMPM: ::nl_item = 50; pub const ERA: ::nl_item = 51; pub const ERA_D_FMT: ::nl_item = 52; pub const ERA_D_T_FMT: ::nl_item = 53; pub const ERA_T_FMT: ::nl_item = 54; pub const ALT_DIGITS: ::nl_item = 55; pub const YESEXPR: ::nl_item = 56; pub const NOEXPR: ::nl_item = 57; pub const _DATE_FMT: ::nl_item = 58; pub const MAXSTRMSG: ::nl_item = 58; pub const PATH_MAX: ::c_int = 1024; pub const SA_ONSTACK: ::c_int = 0x00000001; pub const SA_RESETHAND: ::c_int = 0x00000002; pub const SA_RESTART: ::c_int = 0x00000004; pub const SA_SIGINFO: ::c_int = 0x00000008; pub const SA_NODEFER: ::c_int = 0x00000010; pub const SA_NOCLDWAIT: ::c_int = 0x00010000; pub const SA_NOCLDSTOP: ::c_int = 0x00020000; pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 2; pub const FIOCLEX: ::c_int = 0x20006601; pub const FIONCLEX: ::c_int = 0x20006602; pub const FIONREAD: ::c_int = 0x4004667f; pub const FIONBIO: ::c_int = 0x8004667e; pub const FIOASYNC: ::c_int = 0x8004667d; pub const FIOSETOWN: ::c_int = 0x8004667c; pub const FIOGETOWN: ::c_int = 0x4004667b; pub const SIGCHLD: ::c_int = 18; pub const SIGCLD: ::c_int = ::SIGCHLD; pub const SIGBUS: ::c_int = 10; pub const SIGINFO: ::c_int = 41; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const SIG_SETMASK: ::c_int = 3; pub const SIGEV_NONE: ::c_int = 1; pub const SIGEV_SIGNAL: ::c_int = 2; pub const SIGEV_THREAD: ::c_int = 3; pub const CLD_EXITED: ::c_int = 1; pub const CLD_KILLED: ::c_int = 2; pub const CLD_DUMPED: ::c_int = 3; pub const CLD_TRAPPED: ::c_int = 4; pub const CLD_STOPPED: ::c_int = 5; pub const CLD_CONTINUED: ::c_int = 6; pub const IP_RECVDSTADDR: ::c_int = 0x7; pub const IP_SEC_OPT: ::c_int = 0x22; pub const IPV6_UNICAST_HOPS: ::c_int = 0x5; pub const IPV6_MULTICAST_IF: ::c_int = 0x6; pub const IPV6_MULTICAST_HOPS: ::c_int = 0x7; pub const IPV6_MULTICAST_LOOP: ::c_int = 0x8; pub const IPV6_RECVPKTINFO: ::c_int = 0x12; pub const IPV6_SEC_OPT: ::c_int = 0x22; pub const IPV6_V6ONLY: ::c_int = 0x27; cfg_if! { if #[cfg(target_pointer_width = "64")] { pub const FD_SETSIZE: usize = 65536; } else { pub const FD_SETSIZE: usize = 1024; } } pub const ST_RDONLY: ::c_ulong = 1; pub const ST_NOSUID: ::c_ulong = 2; pub const NI_MAXHOST: ::socklen_t = 1025; pub const NI_MAXSERV: ::socklen_t = 32; pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 32767; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const SEEK_DATA: ::c_int = 3; pub const SEEK_HOLE: ::c_int = 4; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 4; pub const _IOLBF: ::c_int = 64; pub const BUFSIZ: ::c_uint = 1024; pub const FOPEN_MAX: ::c_uint = 20; pub const FILENAME_MAX: ::c_uint = 1024; pub const L_tmpnam: ::c_uint = 25; pub const TMP_MAX: ::c_uint = 17576; pub const GRND_NONBLOCK: ::c_uint = 0x0001; pub const GRND_RANDOM: ::c_uint = 0x0002; pub const O_RDONLY: ::c_int = 0; pub const O_WRONLY: ::c_int = 1; pub const O_RDWR: ::c_int = 2; pub const O_NDELAY: ::c_int = 0x04; pub const O_APPEND: ::c_int = 8; pub const O_DSYNC: ::c_int = 0x40; pub const O_CREAT: ::c_int = 256; pub const O_EXCL: ::c_int = 1024; pub const O_NOCTTY: ::c_int = 2048; pub const O_TRUNC: ::c_int = 512; pub const O_NOFOLLOW: ::c_int = 0x20000; pub const O_SEARCH: ::c_int = 0x200000; pub const O_EXEC: ::c_int = 0x400000; pub const O_CLOEXEC: ::c_int = 0x800000; pub const O_ACCMODE: ::c_int = 0x600003; pub const O_XATTR: ::c_int = 0x4000; pub const O_DIRECTORY: ::c_int = 0x1000000; pub const O_DIRECT: ::c_int = 0x2000000; pub const S_IFIFO: mode_t = 4096; pub const S_IFCHR: mode_t = 8192; pub const S_IFBLK: mode_t = 24576; pub const S_IFDIR: mode_t = 16384; pub const S_IFREG: mode_t = 32768; pub const S_IFLNK: mode_t = 40960; pub const S_IFSOCK: mode_t = 49152; pub const S_IFMT: mode_t = 61440; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; pub const S_IREAD: mode_t = 256; pub const S_IRWXU: mode_t = 448; pub const S_IXUSR: mode_t = 64; pub const S_IWUSR: mode_t = 128; pub const S_IRUSR: mode_t = 256; pub const S_IRWXG: mode_t = 56; pub const S_IXGRP: mode_t = 8; pub const S_IWGRP: mode_t = 16; pub const S_IRGRP: mode_t = 32; pub const S_IRWXO: mode_t = 7; pub const S_IXOTH: mode_t = 1; pub const S_IWOTH: mode_t = 2; pub const S_IROTH: mode_t = 4; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_GETLK: ::c_int = 14; pub const F_ALLOCSP: ::c_int = 10; pub const F_FREESP: ::c_int = 11; pub const F_BLOCKS: ::c_int = 18; pub const F_BLKSIZE: ::c_int = 19; pub const F_SHARE: ::c_int = 40; pub const F_UNSHARE: ::c_int = 41; pub const F_ISSTREAM: ::c_int = 13; pub const F_PRIV: ::c_int = 15; pub const F_NPRIV: ::c_int = 16; pub const F_QUOTACTL: ::c_int = 17; pub const F_GETOWN: ::c_int = 23; pub const F_SETOWN: ::c_int = 24; pub const F_REVOKE: ::c_int = 25; pub const F_HASREMOTELOCKS: ::c_int = 26; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGSYS: ::c_int = 12; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const SIGUSR1: ::c_int = 16; pub const SIGUSR2: ::c_int = 17; pub const SIGPWR: ::c_int = 19; pub const SIGWINCH: ::c_int = 20; pub const SIGURG: ::c_int = 21; pub const SIGPOLL: ::c_int = 22; pub const SIGIO: ::c_int = SIGPOLL; pub const SIGSTOP: ::c_int = 23; pub const SIGTSTP: ::c_int = 24; pub const SIGCONT: ::c_int = 25; pub const SIGTTIN: ::c_int = 26; pub const SIGTTOU: ::c_int = 27; pub const SIGVTALRM: ::c_int = 28; pub const SIGPROF: ::c_int = 29; pub const SIGXCPU: ::c_int = 30; pub const SIGXFSZ: ::c_int = 31; pub const WNOHANG: ::c_int = 0x40; pub const WUNTRACED: ::c_int = 0x04; pub const WEXITED: ::c_int = 0x01; pub const WTRAPPED: ::c_int = 0x02; pub const WSTOPPED: ::c_int = WUNTRACED; pub const WCONTINUED: ::c_int = 0x08; pub const WNOWAIT: ::c_int = 0x80; pub const AT_FDCWD: ::c_int = 0xffd19553; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x1000; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x2000; pub const AT_REMOVEDIR: ::c_int = 0x1; pub const _AT_TRIGGER: ::c_int = 0x2; pub const AT_EACCESS: ::c_int = 0x4; pub const P_PID: idtype_t = 0; pub const P_PPID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const P_SID: idtype_t = 3; pub const P_CID: idtype_t = 4; pub const P_UID: idtype_t = 5; pub const P_GID: idtype_t = 6; pub const P_ALL: idtype_t = 7; pub const P_LWPID: idtype_t = 8; pub const P_TASKID: idtype_t = 9; pub const P_PROJID: idtype_t = 10; pub const P_POOLID: idtype_t = 11; pub const P_ZONEID: idtype_t = 12; pub const P_CTID: idtype_t = 13; pub const P_CPUID: idtype_t = 14; pub const P_PSETID: idtype_t = 15; pub const PBIND_NONE: ::processorid_t = -1; pub const PBIND_QUERY: ::processorid_t = -2; pub const PBIND_HARD: ::processorid_t = -3; pub const PBIND_SOFT: ::processorid_t = -4; pub const PS_NONE: ::c_int = -1; pub const PS_QUERY: ::c_int = -2; pub const PS_MYID: ::c_int = -3; pub const PS_SOFT: ::c_int = -4; pub const PS_HARD: ::c_int = -5; pub const PS_QUERY_TYPE: ::c_int = -6; pub const PS_SYSTEM: ::c_int = 1; pub const PS_PRIVATE: ::c_int = 2; pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const MAP_FILE: ::c_int = 0; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_NORESERVE: ::c_int = 0x40; pub const MAP_ANON: ::c_int = 0x0100; pub const MAP_ANONYMOUS: ::c_int = 0x0100; pub const MAP_RENAME: ::c_int = 0x20; pub const MAP_ALIGN: ::c_int = 0x200; pub const MAP_TEXT: ::c_int = 0x400; pub const MAP_INITDATA: ::c_int = 0x800; pub const MAP_32BIT: ::c_int = 0x80; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MS_SYNC: ::c_int = 0x0004; pub const MS_ASYNC: ::c_int = 0x0001; pub const MS_INVALIDATE: ::c_int = 0x0002; pub const MMOBJ_PADDING: ::c_uint = 0x10000; pub const MMOBJ_INTERPRET: ::c_uint = 0x20000; pub const MR_PADDING: ::c_uint = 0x1; pub const MR_HDR_ELF: ::c_uint = 0x2; pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EDEADLK: ::c_int = 45; pub const ENOLCK: ::c_int = 46; pub const ECANCELED: ::c_int = 47; pub const ENOTSUP: ::c_int = 48; pub const EDQUOT: ::c_int = 49; pub const EBADE: ::c_int = 50; pub const EBADR: ::c_int = 51; pub const EXFULL: ::c_int = 52; pub const ENOANO: ::c_int = 53; pub const EBADRQC: ::c_int = 54; pub const EBADSLT: ::c_int = 55; pub const EDEADLOCK: ::c_int = 56; pub const EBFONT: ::c_int = 57; pub const EOWNERDEAD: ::c_int = 58; pub const ENOTRECOVERABLE: ::c_int = 59; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const ELOCKUNMAPPED: ::c_int = 72; pub const ENOTACTIVE: ::c_int = 73; pub const EMULTIHOP: ::c_int = 74; pub const EADI: ::c_int = 75; pub const EBADMSG: ::c_int = 77; pub const ENAMETOOLONG: ::c_int = 78; pub const EOVERFLOW: ::c_int = 79; pub const ENOTUNIQ: ::c_int = 80; pub const EBADFD: ::c_int = 81; pub const EREMCHG: ::c_int = 82; pub const ELIBACC: ::c_int = 83; pub const ELIBBAD: ::c_int = 84; pub const ELIBSCN: ::c_int = 85; pub const ELIBMAX: ::c_int = 86; pub const ELIBEXEC: ::c_int = 87; pub const EILSEQ: ::c_int = 88; pub const ENOSYS: ::c_int = 89; pub const ELOOP: ::c_int = 90; pub const ERESTART: ::c_int = 91; pub const ESTRPIPE: ::c_int = 92; pub const ENOTEMPTY: ::c_int = 93; pub const EUSERS: ::c_int = 94; pub const ENOTSOCK: ::c_int = 95; pub const EDESTADDRREQ: ::c_int = 96; pub const EMSGSIZE: ::c_int = 97; pub const EPROTOTYPE: ::c_int = 98; pub const ENOPROTOOPT: ::c_int = 99; pub const EPROTONOSUPPORT: ::c_int = 120; pub const ESOCKTNOSUPPORT: ::c_int = 121; pub const EOPNOTSUPP: ::c_int = 122; pub const EPFNOSUPPORT: ::c_int = 123; pub const EAFNOSUPPORT: ::c_int = 124; pub const EADDRINUSE: ::c_int = 125; pub const EADDRNOTAVAIL: ::c_int = 126; pub const ENETDOWN: ::c_int = 127; pub const ENETUNREACH: ::c_int = 128; pub const ENETRESET: ::c_int = 129; pub const ECONNABORTED: ::c_int = 130; pub const ECONNRESET: ::c_int = 131; pub const ENOBUFS: ::c_int = 132; pub const EISCONN: ::c_int = 133; pub const ENOTCONN: ::c_int = 134; pub const ESHUTDOWN: ::c_int = 143; pub const ETOOMANYREFS: ::c_int = 144; pub const ETIMEDOUT: ::c_int = 145; pub const ECONNREFUSED: ::c_int = 146; pub const EHOSTDOWN: ::c_int = 147; pub const EHOSTUNREACH: ::c_int = 148; pub const EWOULDBLOCK: ::c_int = EAGAIN; pub const EALREADY: ::c_int = 149; pub const EINPROGRESS: ::c_int = 150; pub const ESTALE: ::c_int = 151; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_NODATA: ::c_int = 7; pub const EAI_NONAME: ::c_int = 8; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 12; pub const NI_NOFQDN: ::c_uint = 0x0001; pub const NI_NUMERICHOST: ::c_uint = 0x0002; pub const NI_NAMEREQD: ::c_uint = 0x0004; pub const NI_NUMERICSERV: ::c_uint = 0x0008; pub const NI_DGRAM: ::c_uint = 0x0010; pub const NI_WITHSCOPEID: ::c_uint = 0x0020; pub const NI_NUMERICSCOPE: ::c_uint = 0x0040; pub const F_DUPFD: ::c_int = 0; pub const F_DUP2FD: ::c_int = 9; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const F_GETXFL: ::c_int = 45; pub const SIGTRAP: ::c_int = 5; pub const GLOB_APPEND: ::c_int = 32; pub const GLOB_DOOFFS: ::c_int = 16; pub const GLOB_ERR: ::c_int = 1; pub const GLOB_MARK: ::c_int = 2; pub const GLOB_NOCHECK: ::c_int = 8; pub const GLOB_NOSORT: ::c_int = 4; pub const GLOB_NOESCAPE: ::c_int = 64; pub const GLOB_NOSPACE: ::c_int = -2; pub const GLOB_ABORTED: ::c_int = -1; pub const GLOB_NOMATCH: ::c_int = -3; pub const POLLIN: ::c_short = 0x1; pub const POLLPRI: ::c_short = 0x2; pub const POLLOUT: ::c_short = 0x4; pub const POLLERR: ::c_short = 0x8; pub const POLLHUP: ::c_short = 0x10; pub const POLLNVAL: ::c_short = 0x20; pub const POLLNORM: ::c_short = 0x0040; pub const POLLRDNORM: ::c_short = 0x0040; pub const POLLWRNORM: ::c_short = 0x4; /* POLLOUT */ pub const POLLRDBAND: ::c_short = 0x0080; pub const POLLWRBAND: ::c_short = 0x0100; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 0x40; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const PTHREAD_PROCESS_PRIVATE: ::c_ushort = 0; pub const PTHREAD_STACK_MIN: ::size_t = 4096; pub const SIGSTKSZ: ::size_t = 8192; // https://illumos.org/man/3c/clock_gettime // https://github.com/illumos/illumos-gate/ // blob/HEAD/usr/src/lib/libc/amd64/sys/__clock_gettime.s // clock_gettime(3c) doesn't seem to accept anything other than CLOCK_REALTIME // or __CLOCK_REALTIME0 // // https://github.com/illumos/illumos-gate/ // blob/HEAD/usr/src/uts/common/sys/time_impl.h // Confusing! CLOCK_HIGHRES==CLOCK_MONOTONIC==4 // __CLOCK_REALTIME0==0 is an obsoleted version of CLOCK_REALTIME==3 pub const CLOCK_REALTIME: ::clockid_t = 3; pub const CLOCK_MONOTONIC: ::clockid_t = 4; pub const TIMER_RELTIME: ::c_int = 0; pub const TIMER_ABSTIME: ::c_int = 1; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_NOFILE: ::c_int = 5; pub const RLIMIT_VMEM: ::c_int = 6; pub const RLIMIT_AS: ::c_int = RLIMIT_VMEM; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: rlim_t = 7; pub const RLIM_INFINITY: rlim_t = 0xfffffffffffffffd; pub const RUSAGE_SELF: ::c_int = 0; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const MADV_FREE: ::c_int = 5; pub const MADV_ACCESS_DEFAULT: ::c_int = 6; pub const MADV_ACCESS_LWP: ::c_int = 7; pub const MADV_ACCESS_MANY: ::c_int = 8; pub const AF_UNSPEC: ::c_int = 0; pub const AF_UNIX: ::c_int = 1; pub const AF_INET: ::c_int = 2; pub const AF_IMPLINK: ::c_int = 3; pub const AF_PUP: ::c_int = 4; pub const AF_CHAOS: ::c_int = 5; pub const AF_NS: ::c_int = 6; pub const AF_NBS: ::c_int = 7; pub const AF_ECMA: ::c_int = 8; pub const AF_DATAKIT: ::c_int = 9; pub const AF_CCITT: ::c_int = 10; pub const AF_SNA: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_DLI: ::c_int = 13; pub const AF_LAT: ::c_int = 14; pub const AF_HYLINK: ::c_int = 15; pub const AF_APPLETALK: ::c_int = 16; pub const AF_NIT: ::c_int = 17; pub const AF_802: ::c_int = 18; pub const AF_OSI: ::c_int = 19; pub const AF_X25: ::c_int = 20; pub const AF_OSINET: ::c_int = 21; pub const AF_GOSIP: ::c_int = 22; pub const AF_IPX: ::c_int = 23; pub const AF_ROUTE: ::c_int = 24; pub const AF_LINK: ::c_int = 25; pub const AF_INET6: ::c_int = 26; pub const AF_KEY: ::c_int = 27; pub const AF_NCA: ::c_int = 28; pub const AF_POLICY: ::c_int = 29; pub const AF_INET_OFFLOAD: ::c_int = 30; pub const AF_TRILL: ::c_int = 31; pub const AF_PACKET: ::c_int = 32; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_UNIX: ::c_int = AF_UNIX; pub const PF_LOCAL: ::c_int = PF_UNIX; pub const PF_FILE: ::c_int = PF_UNIX; pub const PF_INET: ::c_int = AF_INET; pub const PF_IMPLINK: ::c_int = AF_IMPLINK; pub const PF_PUP: ::c_int = AF_PUP; pub const PF_CHAOS: ::c_int = AF_CHAOS; pub const PF_NS: ::c_int = AF_NS; pub const PF_NBS: ::c_int = AF_NBS; pub const PF_ECMA: ::c_int = AF_ECMA; pub const PF_DATAKIT: ::c_int = AF_DATAKIT; pub const PF_CCITT: ::c_int = AF_CCITT; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_DECnet: ::c_int = AF_DECnet; pub const PF_DLI: ::c_int = AF_DLI; pub const PF_LAT: ::c_int = AF_LAT; pub const PF_HYLINK: ::c_int = AF_HYLINK; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_NIT: ::c_int = AF_NIT; pub const PF_802: ::c_int = AF_802; pub const PF_OSI: ::c_int = AF_OSI; pub const PF_X25: ::c_int = AF_X25; pub const PF_OSINET: ::c_int = AF_OSINET; pub const PF_GOSIP: ::c_int = AF_GOSIP; pub const PF_IPX: ::c_int = AF_IPX; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_LINK: ::c_int = AF_LINK; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_KEY: ::c_int = AF_KEY; pub const PF_NCA: ::c_int = AF_NCA; pub const PF_POLICY: ::c_int = AF_POLICY; pub const PF_INET_OFFLOAD: ::c_int = AF_INET_OFFLOAD; pub const PF_TRILL: ::c_int = AF_TRILL; pub const PF_PACKET: ::c_int = AF_PACKET; pub const SOCK_DGRAM: ::c_int = 1; pub const SOCK_STREAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 4; pub const SOCK_RDM: ::c_int = 5; pub const SOCK_SEQPACKET: ::c_int = 6; pub const IP_MULTICAST_IF: ::c_int = 16; pub const IP_MULTICAST_TTL: ::c_int = 17; pub const IP_MULTICAST_LOOP: ::c_int = 18; pub const IP_TTL: ::c_int = 4; pub const IP_HDRINCL: ::c_int = 2; pub const IP_ADD_MEMBERSHIP: ::c_int = 19; pub const IP_DROP_MEMBERSHIP: ::c_int = 20; pub const IPV6_JOIN_GROUP: ::c_int = 9; pub const IPV6_LEAVE_GROUP: ::c_int = 10; pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 23; pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 24; pub const IP_BLOCK_SOURCE: ::c_int = 21; pub const IP_UNBLOCK_SOURCE: ::c_int = 22; // These TCP socket options are common between illumos and Solaris, while higher // numbers have generally diverged: pub const TCP_NODELAY: ::c_int = 0x1; pub const TCP_MAXSEG: ::c_int = 0x2; pub const TCP_KEEPALIVE: ::c_int = 0x8; pub const TCP_NOTIFY_THRESHOLD: ::c_int = 0x10; pub const TCP_ABORT_THRESHOLD: ::c_int = 0x11; pub const TCP_CONN_NOTIFY_THRESHOLD: ::c_int = 0x12; pub const TCP_CONN_ABORT_THRESHOLD: ::c_int = 0x13; pub const TCP_RECVDSTADDR: ::c_int = 0x14; pub const TCP_INIT_CWND: ::c_int = 0x15; pub const TCP_KEEPALIVE_THRESHOLD: ::c_int = 0x16; pub const TCP_KEEPALIVE_ABORT_THRESHOLD: ::c_int = 0x17; pub const TCP_CORK: ::c_int = 0x18; pub const TCP_RTO_INITIAL: ::c_int = 0x19; pub const TCP_RTO_MIN: ::c_int = 0x1a; pub const TCP_RTO_MAX: ::c_int = 0x1b; pub const TCP_LINGER2: ::c_int = 0x1c; pub const UDP_NAT_T_ENDPOINT: ::c_int = 0x0103; pub const SOMAXCONN: ::c_int = 128; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x01; pub const SO_ACCEPTCONN: ::c_int = 0x0002; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVLOWAT: ::c_int = 0x1004; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; pub const SO_PROTOTYPE: ::c_int = 0x1009; pub const SO_DOMAIN: ::c_int = 0x100c; pub const SO_TIMESTAMP: ::c_int = 0x1013; pub const SO_EXCLBIND: ::c_int = 0x1015; pub const SCM_RIGHTS: ::c_int = 0x1010; pub const SCM_UCRED: ::c_int = 0x1012; pub const SCM_TIMESTAMP: ::c_int = SO_TIMESTAMP; pub const MSG_OOB: ::c_int = 0x1; pub const MSG_PEEK: ::c_int = 0x2; pub const MSG_DONTROUTE: ::c_int = 0x4; pub const MSG_EOR: ::c_int = 0x8; pub const MSG_CTRUNC: ::c_int = 0x10; pub const MSG_TRUNC: ::c_int = 0x20; pub const MSG_WAITALL: ::c_int = 0x40; pub const MSG_DONTWAIT: ::c_int = 0x80; pub const MSG_NOTIFICATION: ::c_int = 0x100; pub const MSG_NOSIGNAL: ::c_int = 0x200; pub const MSG_DUPCTRL: ::c_int = 0x800; pub const MSG_XPG4_2: ::c_int = 0x8000; pub const MSG_MAXIOVLEN: ::c_int = 16; pub const IF_NAMESIZE: ::size_t = 32; pub const IFNAMSIZ: ::size_t = 16; // https://docs.oracle.com/cd/E23824_01/html/821-1475/if-7p.html pub const IFF_UP: ::c_int = 0x0000000001; // Address is up pub const IFF_BROADCAST: ::c_int = 0x0000000002; // Broadcast address valid pub const IFF_DEBUG: ::c_int = 0x0000000004; // Turn on debugging pub const IFF_LOOPBACK: ::c_int = 0x0000000008; // Loopback net pub const IFF_POINTOPOINT: ::c_int = 0x0000000010; // Interface is p-to-p pub const IFF_NOTRAILERS: ::c_int = 0x0000000020; // Avoid use of trailers pub const IFF_RUNNING: ::c_int = 0x0000000040; // Resources allocated pub const IFF_NOARP: ::c_int = 0x0000000080; // No address res. protocol pub const IFF_PROMISC: ::c_int = 0x0000000100; // Receive all packets pub const IFF_ALLMULTI: ::c_int = 0x0000000200; // Receive all multicast pkts pub const IFF_INTELLIGENT: ::c_int = 0x0000000400; // Protocol code on board pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast // Multicast using broadcst. add. pub const IFF_MULTI_BCAST: ::c_int = 0x0000001000; pub const IFF_UNNUMBERED: ::c_int = 0x0000002000; // Non-unique address pub const IFF_DHCPRUNNING: ::c_int = 0x0000004000; // DHCP controls interface pub const IFF_PRIVATE: ::c_int = 0x0000008000; // Do not advertise pub const IFF_NOXMIT: ::c_int = 0x0000010000; // Do not transmit pkts // No address - just on-link subnet pub const IFF_NOLOCAL: ::c_int = 0x0000020000; pub const IFF_DEPRECATED: ::c_int = 0x0000040000; // Address is deprecated pub const IFF_ADDRCONF: ::c_int = 0x0000080000; // Addr. from stateless addrconf pub const IFF_ROUTER: ::c_int = 0x0000100000; // Router on interface pub const IFF_NONUD: ::c_int = 0x0000200000; // No NUD on interface pub const IFF_ANYCAST: ::c_int = 0x0000400000; // Anycast address pub const IFF_NORTEXCH: ::c_int = 0x0000800000; // Don't xchange rout. info pub const IFF_IPV4: ::c_int = 0x0001000000; // IPv4 interface pub const IFF_IPV6: ::c_int = 0x0002000000; // IPv6 interface pub const IFF_NOFAILOVER: ::c_int = 0x0008000000; // in.mpathd test address pub const IFF_FAILED: ::c_int = 0x0010000000; // Interface has failed pub const IFF_STANDBY: ::c_int = 0x0020000000; // Interface is a hot-spare pub const IFF_INACTIVE: ::c_int = 0x0040000000; // Functioning but not used pub const IFF_OFFLINE: ::c_int = 0x0080000000; // Interface is offline // If CoS marking is supported pub const IFF_COS_ENABLED: ::c_longlong = 0x0200000000; pub const IFF_PREFERRED: ::c_longlong = 0x0400000000; // Prefer as source addr. pub const IFF_TEMPORARY: ::c_longlong = 0x0800000000; // RFC3041 pub const IFF_FIXEDMTU: ::c_longlong = 0x1000000000; // MTU set with SIOCSLIFMTU pub const IFF_VIRTUAL: ::c_longlong = 0x2000000000; // Cannot send/receive pkts pub const IFF_DUPLICATE: ::c_longlong = 0x4000000000; // Local address in use pub const IFF_IPMP: ::c_longlong = 0x8000000000; // IPMP IP interface // sys/ipc.h: pub const IPC_ALLOC: ::c_int = 0x8000; pub const IPC_CREAT: ::c_int = 0x200; pub const IPC_EXCL: ::c_int = 0x400; pub const IPC_NOWAIT: ::c_int = 0x800; pub const IPC_PRIVATE: key_t = 0; pub const IPC_RMID: ::c_int = 10; pub const IPC_SET: ::c_int = 11; pub const IPC_SEAT: ::c_int = 12; // sys/shm.h pub const SHM_R: ::c_int = 0o400; pub const SHM_W: ::c_int = 0o200; pub const SHM_RDONLY: ::c_int = 0o10000; pub const SHM_RND: ::c_int = 0o20000; pub const SHM_SHARE_MMU: ::c_int = 0o40000; pub const SHM_PAGEABLE: ::c_int = 0o100000; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; pub const F_RDLCK: ::c_short = 1; pub const F_WRLCK: ::c_short = 2; pub const F_UNLCK: ::c_short = 3; pub const O_SYNC: ::c_int = 16; pub const O_NONBLOCK: ::c_int = 128; pub const IPPROTO_RAW: ::c_int = 255; pub const _PC_LINK_MAX: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_CHOWN_RESTRICTED: ::c_int = 9; pub const _PC_ASYNC_IO: ::c_int = 10; pub const _PC_PRIO_IO: ::c_int = 11; pub const _PC_SYNC_IO: ::c_int = 12; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; pub const _PC_REC_XFER_ALIGN: ::c_int = 17; pub const _PC_SYMLINK_MAX: ::c_int = 18; pub const _PC_2_SYMLINKS: ::c_int = 19; pub const _PC_ACL_ENABLED: ::c_int = 20; pub const _PC_MIN_HOLE_SIZE: ::c_int = 21; pub const _PC_CASE_BEHAVIOR: ::c_int = 22; pub const _PC_SATTR_ENABLED: ::c_int = 23; pub const _PC_SATTR_EXISTS: ::c_int = 24; pub const _PC_ACCESS_FILTERING: ::c_int = 25; pub const _PC_TIMESTAMP_RESOLUTION: ::c_int = 26; pub const _PC_FILESIZEBITS: ::c_int = 67; pub const _PC_XATTR_ENABLED: ::c_int = 100; pub const _PC_LAST: ::c_int = 101; pub const _PC_XATTR_EXISTS: ::c_int = 101; pub const _SC_ARG_MAX: ::c_int = 1; pub const _SC_CHILD_MAX: ::c_int = 2; pub const _SC_CLK_TCK: ::c_int = 3; pub const _SC_NGROUPS_MAX: ::c_int = 4; pub const _SC_OPEN_MAX: ::c_int = 5; pub const _SC_JOB_CONTROL: ::c_int = 6; pub const _SC_SAVED_IDS: ::c_int = 7; pub const _SC_VERSION: ::c_int = 8; pub const _SC_PASS_MAX: ::c_int = 9; pub const _SC_LOGNAME_MAX: ::c_int = 10; pub const _SC_PAGESIZE: ::c_int = 11; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_XOPEN_VERSION: ::c_int = 12; pub const _SC_NPROCESSORS_CONF: ::c_int = 14; pub const _SC_NPROCESSORS_ONLN: ::c_int = 15; pub const _SC_STREAM_MAX: ::c_int = 16; pub const _SC_TZNAME_MAX: ::c_int = 17; pub const _SC_AIO_LISTIO_MAX: ::c_int = 18; pub const _SC_AIO_MAX: ::c_int = 19; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 20; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 21; pub const _SC_DELAYTIMER_MAX: ::c_int = 22; pub const _SC_FSYNC: ::c_int = 23; pub const _SC_MAPPED_FILES: ::c_int = 24; pub const _SC_MEMLOCK: ::c_int = 25; pub const _SC_MEMLOCK_RANGE: ::c_int = 26; pub const _SC_MEMORY_PROTECTION: ::c_int = 27; pub const _SC_MESSAGE_PASSING: ::c_int = 28; pub const _SC_MQ_OPEN_MAX: ::c_int = 29; pub const _SC_MQ_PRIO_MAX: ::c_int = 30; pub const _SC_PRIORITIZED_IO: ::c_int = 31; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 32; pub const _SC_REALTIME_SIGNALS: ::c_int = 33; pub const _SC_RTSIG_MAX: ::c_int = 34; pub const _SC_SEMAPHORES: ::c_int = 35; pub const _SC_SEM_NSEMS_MAX: ::c_int = 36; pub const _SC_SEM_VALUE_MAX: ::c_int = 37; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 38; pub const _SC_SIGQUEUE_MAX: ::c_int = 39; pub const _SC_SIGRT_MIN: ::c_int = 40; pub const _SC_SIGRT_MAX: ::c_int = 41; pub const _SC_SYNCHRONIZED_IO: ::c_int = 42; pub const _SC_TIMERS: ::c_int = 43; pub const _SC_TIMER_MAX: ::c_int = 44; pub const _SC_2_C_BIND: ::c_int = 45; pub const _SC_2_C_DEV: ::c_int = 46; pub const _SC_2_C_VERSION: ::c_int = 47; pub const _SC_2_FORT_DEV: ::c_int = 48; pub const _SC_2_FORT_RUN: ::c_int = 49; pub const _SC_2_LOCALEDEF: ::c_int = 50; pub const _SC_2_SW_DEV: ::c_int = 51; pub const _SC_2_UPE: ::c_int = 52; pub const _SC_2_VERSION: ::c_int = 53; pub const _SC_BC_BASE_MAX: ::c_int = 54; pub const _SC_BC_DIM_MAX: ::c_int = 55; pub const _SC_BC_SCALE_MAX: ::c_int = 56; pub const _SC_BC_STRING_MAX: ::c_int = 57; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 58; pub const _SC_EXPR_NEST_MAX: ::c_int = 59; pub const _SC_LINE_MAX: ::c_int = 60; pub const _SC_RE_DUP_MAX: ::c_int = 61; pub const _SC_XOPEN_CRYPT: ::c_int = 62; pub const _SC_XOPEN_ENH_I18N: ::c_int = 63; pub const _SC_XOPEN_SHM: ::c_int = 64; pub const _SC_2_CHAR_TERM: ::c_int = 66; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 67; pub const _SC_ATEXIT_MAX: ::c_int = 76; pub const _SC_IOV_MAX: ::c_int = 77; pub const _SC_XOPEN_UNIX: ::c_int = 78; pub const _SC_T_IOV_MAX: ::c_int = 79; pub const _SC_PHYS_PAGES: ::c_int = 500; pub const _SC_AVPHYS_PAGES: ::c_int = 501; pub const _SC_COHER_BLKSZ: ::c_int = 503; pub const _SC_SPLIT_CACHE: ::c_int = 504; pub const _SC_ICACHE_SZ: ::c_int = 505; pub const _SC_DCACHE_SZ: ::c_int = 506; pub const _SC_ICACHE_LINESZ: ::c_int = 507; pub const _SC_DCACHE_LINESZ: ::c_int = 508; pub const _SC_ICACHE_BLKSZ: ::c_int = 509; pub const _SC_DCACHE_BLKSZ: ::c_int = 510; pub const _SC_DCACHE_TBLKSZ: ::c_int = 511; pub const _SC_ICACHE_ASSOC: ::c_int = 512; pub const _SC_DCACHE_ASSOC: ::c_int = 513; pub const _SC_MAXPID: ::c_int = 514; pub const _SC_STACK_PROT: ::c_int = 515; pub const _SC_NPROCESSORS_MAX: ::c_int = 516; pub const _SC_CPUID_MAX: ::c_int = 517; pub const _SC_EPHID_MAX: ::c_int = 518; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 568; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 569; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 570; pub const _SC_LOGIN_NAME_MAX: ::c_int = 571; pub const _SC_THREAD_KEYS_MAX: ::c_int = 572; pub const _SC_THREAD_STACK_MIN: ::c_int = 573; pub const _SC_THREAD_THREADS_MAX: ::c_int = 574; pub const _SC_TTY_NAME_MAX: ::c_int = 575; pub const _SC_THREADS: ::c_int = 576; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 577; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 578; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 579; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 580; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 581; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 582; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 583; pub const _SC_XOPEN_LEGACY: ::c_int = 717; pub const _SC_XOPEN_REALTIME: ::c_int = 718; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 719; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 720; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 721; pub const _SC_XBS5_LP64_OFF64: ::c_int = 722; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 723; pub const _SC_2_PBS: ::c_int = 724; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 725; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 726; pub const _SC_2_PBS_LOCATE: ::c_int = 728; pub const _SC_2_PBS_MESSAGE: ::c_int = 729; pub const _SC_2_PBS_TRACK: ::c_int = 730; pub const _SC_ADVISORY_INFO: ::c_int = 731; pub const _SC_BARRIERS: ::c_int = 732; pub const _SC_CLOCK_SELECTION: ::c_int = 733; pub const _SC_CPUTIME: ::c_int = 734; pub const _SC_HOST_NAME_MAX: ::c_int = 735; pub const _SC_MONOTONIC_CLOCK: ::c_int = 736; pub const _SC_READER_WRITER_LOCKS: ::c_int = 737; pub const _SC_REGEXP: ::c_int = 738; pub const _SC_SHELL: ::c_int = 739; pub const _SC_SPAWN: ::c_int = 740; pub const _SC_SPIN_LOCKS: ::c_int = 741; pub const _SC_SPORADIC_SERVER: ::c_int = 742; pub const _SC_SS_REPL_MAX: ::c_int = 743; pub const _SC_SYMLOOP_MAX: ::c_int = 744; pub const _SC_THREAD_CPUTIME: ::c_int = 745; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 746; pub const _SC_TIMEOUTS: ::c_int = 747; pub const _SC_TRACE: ::c_int = 748; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 749; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 750; pub const _SC_TRACE_INHERIT: ::c_int = 751; pub const _SC_TRACE_LOG: ::c_int = 752; pub const _SC_TRACE_NAME_MAX: ::c_int = 753; pub const _SC_TRACE_SYS_MAX: ::c_int = 754; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 755; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 756; pub const _SC_V6_ILP32_OFF32: ::c_int = 757; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 758; pub const _SC_V6_LP64_OFF64: ::c_int = 759; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 760; pub const _SC_XOPEN_STREAMS: ::c_int = 761; pub const _SC_IPV6: ::c_int = 762; pub const _SC_RAW_SOCKETS: ::c_int = 763; pub const _MUTEX_MAGIC: u16 = 0x4d58; // MX pub const _COND_MAGIC: u16 = 0x4356; // CV pub const _RWL_MAGIC: u16 = 0x5257; // RW pub const NCCS: usize = 19; pub const LOG_CRON: ::c_int = 15 << 3; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __pthread_mutex_flag1: 0, __pthread_mutex_flag2: 0, __pthread_mutex_ceiling: 0, __pthread_mutex_type: PTHREAD_PROCESS_PRIVATE, __pthread_mutex_magic: _MUTEX_MAGIC, __pthread_mutex_lock: 0, __pthread_mutex_data: 0, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __pthread_cond_flag: [0; 4], __pthread_cond_type: PTHREAD_PROCESS_PRIVATE, __pthread_cond_magic: _COND_MAGIC, __pthread_cond_data: 0, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __pthread_rwlock_readers: 0, __pthread_rwlock_type: PTHREAD_PROCESS_PRIVATE, __pthread_rwlock_magic: _RWL_MAGIC, __pthread_rwlock_mutex: PTHREAD_MUTEX_INITIALIZER, __pthread_rwlock_readercv: PTHREAD_COND_INITIALIZER, __pthread_rwlock_writercv: PTHREAD_COND_INITIALIZER, }; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 4; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const RTLD_NEXT: *mut ::c_void = -1isize as *mut ::c_void; pub const RTLD_DEFAULT: *mut ::c_void = -2isize as *mut ::c_void; pub const RTLD_SELF: *mut ::c_void = -3isize as *mut ::c_void; pub const RTLD_PROBE: *mut ::c_void = -4isize as *mut ::c_void; pub const RTLD_LAZY: ::c_int = 0x1; pub const RTLD_NOW: ::c_int = 0x2; pub const RTLD_NOLOAD: ::c_int = 0x4; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const RTLD_LOCAL: ::c_int = 0x0; pub const RTLD_PARENT: ::c_int = 0x200; pub const RTLD_GROUP: ::c_int = 0x400; pub const RTLD_WORLD: ::c_int = 0x800; pub const RTLD_NODELETE: ::c_int = 0x1000; pub const RTLD_FIRST: ::c_int = 0x2000; pub const RTLD_CONFGEN: ::c_int = 0x10000; pub const PORT_SOURCE_AIO: ::c_int = 1; pub const PORT_SOURCE_TIMER: ::c_int = 2; pub const PORT_SOURCE_USER: ::c_int = 3; pub const PORT_SOURCE_FD: ::c_int = 4; pub const PORT_SOURCE_ALERT: ::c_int = 5; pub const PORT_SOURCE_MQ: ::c_int = 6; pub const PORT_SOURCE_FILE: ::c_int = 7; pub const NONROOT_USR: ::c_short = 2; pub const _UTX_USERSIZE: usize = 32; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_PADSIZE: usize = 5; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 257; pub const EMPTY: ::c_short = 0; pub const RUN_LVL: ::c_short = 1; pub const BOOT_TIME: ::c_short = 2; pub const OLD_TIME: ::c_short = 3; pub const NEW_TIME: ::c_short = 4; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const USER_PROCESS: ::c_short = 7; pub const DEAD_PROCESS: ::c_short = 8; pub const ACCOUNTING: ::c_short = 9; pub const DOWN_TIME: ::c_short = 10; const _TIOC: ::c_int = ('T' as i32) << 8; const tIOC: ::c_int = ('t' as i32) << 8; pub const TCGETA: ::c_int = _TIOC | 1; pub const TCSETA: ::c_int = _TIOC | 2; pub const TCSETAW: ::c_int = _TIOC | 3; pub const TCSETAF: ::c_int = _TIOC | 4; pub const TCSBRK: ::c_int = _TIOC | 5; pub const TCXONC: ::c_int = _TIOC | 6; pub const TCFLSH: ::c_int = _TIOC | 7; pub const TCDSET: ::c_int = _TIOC | 32; pub const TCGETS: ::c_int = _TIOC | 13; pub const TCSETS: ::c_int = _TIOC | 14; pub const TCSANOW: ::c_int = _TIOC | 14; pub const TCSETSW: ::c_int = _TIOC | 15; pub const TCSADRAIN: ::c_int = _TIOC | 15; pub const TCSETSF: ::c_int = _TIOC | 16; pub const TCSAFLUSH: ::c_int = _TIOC | 16; pub const TCIFLUSH: ::c_int = 0; pub const TCOFLUSH: ::c_int = 1; pub const TCIOFLUSH: ::c_int = 2; pub const TCOOFF: ::c_int = 0; pub const TCOON: ::c_int = 1; pub const TCIOFF: ::c_int = 2; pub const TCION: ::c_int = 3; pub const TIOC: ::c_int = _TIOC; pub const TIOCKBON: ::c_int = _TIOC | 8; pub const TIOCKBOF: ::c_int = _TIOC | 9; pub const TIOCGWINSZ: ::c_int = _TIOC | 104; pub const TIOCSWINSZ: ::c_int = _TIOC | 103; pub const TIOCGSOFTCAR: ::c_int = _TIOC | 105; pub const TIOCSSOFTCAR: ::c_int = _TIOC | 106; pub const TIOCGPPS: ::c_int = _TIOC | 125; pub const TIOCSPPS: ::c_int = _TIOC | 126; pub const TIOCGPPSEV: ::c_int = _TIOC | 127; pub const TIOCGETD: ::c_int = tIOC | 0; pub const TIOCSETD: ::c_int = tIOC | 1; pub const TIOCHPCL: ::c_int = tIOC | 2; pub const TIOCGETP: ::c_int = tIOC | 8; pub const TIOCSETP: ::c_int = tIOC | 9; pub const TIOCSETN: ::c_int = tIOC | 10; pub const TIOCEXCL: ::c_int = tIOC | 13; pub const TIOCNXCL: ::c_int = tIOC | 14; pub const TIOCFLUSH: ::c_int = tIOC | 16; pub const TIOCSETC: ::c_int = tIOC | 17; pub const TIOCGETC: ::c_int = tIOC | 18; pub const TIOCLBIS: ::c_int = tIOC | 127; pub const TIOCLBIC: ::c_int = tIOC | 126; pub const TIOCLSET: ::c_int = tIOC | 125; pub const TIOCLGET: ::c_int = tIOC | 124; pub const TIOCSBRK: ::c_int = tIOC | 123; pub const TIOCCBRK: ::c_int = tIOC | 122; pub const TIOCSDTR: ::c_int = tIOC | 121; pub const TIOCCDTR: ::c_int = tIOC | 120; pub const TIOCSLTC: ::c_int = tIOC | 117; pub const TIOCGLTC: ::c_int = tIOC | 116; pub const TIOCOUTQ: ::c_int = tIOC | 115; pub const TIOCNOTTY: ::c_int = tIOC | 113; pub const TIOCSCTTY: ::c_int = tIOC | 132; pub const TIOCSTOP: ::c_int = tIOC | 111; pub const TIOCSTART: ::c_int = tIOC | 110; pub const TIOCSILOOP: ::c_int = tIOC | 109; pub const TIOCCILOOP: ::c_int = tIOC | 108; pub const TIOCGPGRP: ::c_int = tIOC | 20; pub const TIOCSPGRP: ::c_int = tIOC | 21; pub const TIOCGSID: ::c_int = tIOC | 22; pub const TIOCSTI: ::c_int = tIOC | 23; pub const TIOCMSET: ::c_int = tIOC | 26; pub const TIOCMBIS: ::c_int = tIOC | 27; pub const TIOCMBIC: ::c_int = tIOC | 28; pub const TIOCMGET: ::c_int = tIOC | 29; pub const TIOCREMOTE: ::c_int = tIOC | 30; pub const TIOCSIGNAL: ::c_int = tIOC | 31; pub const TIOCM_LE: ::c_int = 0o0001; pub const TIOCM_DTR: ::c_int = 0o0002; pub const TIOCM_RTS: ::c_int = 0o0004; pub const TIOCM_ST: ::c_int = 0o0010; pub const TIOCM_SR: ::c_int = 0o0020; pub const TIOCM_CTS: ::c_int = 0o0040; pub const TIOCM_CAR: ::c_int = 0o0100; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RNG: ::c_int = 0o0200; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const TIOCM_DSR: ::c_int = 0o0400; pub const EPOLLIN: ::c_int = 0x1; pub const EPOLLPRI: ::c_int = 0x2; pub const EPOLLOUT: ::c_int = 0x4; pub const EPOLLRDNORM: ::c_int = 0x40; pub const EPOLLRDBAND: ::c_int = 0x80; pub const EPOLLWRNORM: ::c_int = 0x100; pub const EPOLLWRBAND: ::c_int = 0x200; pub const EPOLLMSG: ::c_int = 0x400; pub const EPOLLERR: ::c_int = 0x8; pub const EPOLLHUP: ::c_int = 0x10; pub const EPOLLET: ::c_int = 0x80000000; pub const EPOLLRDHUP: ::c_int = 0x2000; pub const EPOLLONESHOT: ::c_int = 0x40000000; pub const EPOLLWAKEUP: ::c_int = 0x20000000; pub const EPOLLEXCLUSIVE: ::c_int = 0x10000000; pub const EPOLL_CLOEXEC: ::c_int = 0x80000; pub const EPOLL_CTL_ADD: ::c_int = 1; pub const EPOLL_CTL_MOD: ::c_int = 3; pub const EPOLL_CTL_DEL: ::c_int = 2; /* termios */ pub const B0: speed_t = 0; pub const B50: speed_t = 1; pub const B75: speed_t = 2; pub const B110: speed_t = 3; pub const B134: speed_t = 4; pub const B150: speed_t = 5; pub const B200: speed_t = 6; pub const B300: speed_t = 7; pub const B600: speed_t = 8; pub const B1200: speed_t = 9; pub const B1800: speed_t = 10; pub const B2400: speed_t = 11; pub const B4800: speed_t = 12; pub const B9600: speed_t = 13; pub const B19200: speed_t = 14; pub const B38400: speed_t = 15; pub const B57600: speed_t = 16; pub const B76800: speed_t = 17; pub const B115200: speed_t = 18; pub const B153600: speed_t = 19; pub const B230400: speed_t = 20; pub const B307200: speed_t = 21; pub const B460800: speed_t = 22; pub const B921600: speed_t = 23; pub const CSTART: ::tcflag_t = 0o21; pub const CSTOP: ::tcflag_t = 0o23; pub const CSWTCH: ::tcflag_t = 0o32; pub const CBAUD: ::tcflag_t = 0o17; pub const CIBAUD: ::tcflag_t = 0o3600000; pub const CBAUDEXT: ::tcflag_t = 0o10000000; pub const CIBAUDEXT: ::tcflag_t = 0o20000000; pub const CSIZE: ::tcflag_t = 0o000060; pub const CS5: ::tcflag_t = 0; pub const CS6: ::tcflag_t = 0o000020; pub const CS7: ::tcflag_t = 0o000040; pub const CS8: ::tcflag_t = 0o000060; pub const CSTOPB: ::tcflag_t = 0o000100; pub const ECHO: ::tcflag_t = 0o000010; pub const ECHOE: ::tcflag_t = 0o000020; pub const ECHOK: ::tcflag_t = 0o000040; pub const ECHONL: ::tcflag_t = 0o000100; pub const ECHOCTL: ::tcflag_t = 0o001000; pub const ECHOPRT: ::tcflag_t = 0o002000; pub const ECHOKE: ::tcflag_t = 0o004000; pub const EXTPROC: ::tcflag_t = 0o200000; pub const IGNBRK: ::tcflag_t = 0o000001; pub const BRKINT: ::tcflag_t = 0o000002; pub const IGNPAR: ::tcflag_t = 0o000004; pub const PARMRK: ::tcflag_t = 0o000010; pub const INPCK: ::tcflag_t = 0o000020; pub const ISTRIP: ::tcflag_t = 0o000040; pub const INLCR: ::tcflag_t = 0o000100; pub const IGNCR: ::tcflag_t = 0o000200; pub const ICRNL: ::tcflag_t = 0o000400; pub const IUCLC: ::tcflag_t = 0o001000; pub const IXON: ::tcflag_t = 0o002000; pub const IXOFF: ::tcflag_t = 0o010000; pub const IXANY: ::tcflag_t = 0o004000; pub const IMAXBEL: ::tcflag_t = 0o020000; pub const DOSMODE: ::tcflag_t = 0o100000; pub const OPOST: ::tcflag_t = 0o000001; pub const OLCUC: ::tcflag_t = 0o000002; pub const ONLCR: ::tcflag_t = 0o000004; pub const OCRNL: ::tcflag_t = 0o000010; pub const ONOCR: ::tcflag_t = 0o000020; pub const ONLRET: ::tcflag_t = 0o000040; pub const OFILL: ::tcflag_t = 0o0000100; pub const OFDEL: ::tcflag_t = 0o0000200; pub const CREAD: ::tcflag_t = 0o000200; pub const PARENB: ::tcflag_t = 0o000400; pub const PARODD: ::tcflag_t = 0o001000; pub const HUPCL: ::tcflag_t = 0o002000; pub const CLOCAL: ::tcflag_t = 0o004000; pub const CRTSXOFF: ::tcflag_t = 0o10000000000; pub const CRTSCTS: ::tcflag_t = 0o20000000000; pub const ISIG: ::tcflag_t = 0o000001; pub const ICANON: ::tcflag_t = 0o000002; pub const IEXTEN: ::tcflag_t = 0o100000; pub const TOSTOP: ::tcflag_t = 0o000400; pub const FLUSHO: ::tcflag_t = 0o020000; pub const PENDIN: ::tcflag_t = 0o040000; pub const NOFLSH: ::tcflag_t = 0o000200; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VEOF: usize = 4; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 4; pub const VTIME: usize = 5; pub const VSWTCH: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const VDSUSP: usize = 11; pub const VREPRINT: usize = 12; pub const VDISCARD: usize = 13; pub const VWERASE: usize = 14; pub const VLNEXT: usize = 15; pub const VSTATUS: usize = 16; pub const VERASE2: usize = 17; // const STR: ::c_int = (b'S' as ::c_int) << 8; pub const I_NREAD: ::c_int = STR | 0o1; pub const I_PUSH: ::c_int = STR | 0o2; pub const I_POP: ::c_int = STR | 0o3; pub const I_LOOK: ::c_int = STR | 0o4; pub const I_FLUSH: ::c_int = STR | 0o5; pub const I_SRDOPT: ::c_int = STR | 0o6; pub const I_GRDOPT: ::c_int = STR | 0o7; pub const I_STR: ::c_int = STR | 0o10; pub const I_SETSIG: ::c_int = STR | 0o11; pub const I_GETSIG: ::c_int = STR | 0o12; pub const I_FIND: ::c_int = STR | 0o13; pub const I_LINK: ::c_int = STR | 0o14; pub const I_UNLINK: ::c_int = STR | 0o15; pub const I_PEEK: ::c_int = STR | 0o17; pub const I_FDINSERT: ::c_int = STR | 0o20; pub const I_SENDFD: ::c_int = STR | 0o21; pub const I_RECVFD: ::c_int = STR | 0o16; pub const I_SWROPT: ::c_int = STR | 0o23; pub const I_GWROPT: ::c_int = STR | 0o24; pub const I_LIST: ::c_int = STR | 0o25; pub const I_PLINK: ::c_int = STR | 0o26; pub const I_PUNLINK: ::c_int = STR | 0o27; pub const I_ANCHOR: ::c_int = STR | 0o30; pub const I_FLUSHBAND: ::c_int = STR | 0o34; pub const I_CKBAND: ::c_int = STR | 0o35; pub const I_GETBAND: ::c_int = STR | 0o36; pub const I_ATMARK: ::c_int = STR | 0o37; pub const I_SETCLTIME: ::c_int = STR | 0o40; pub const I_GETCLTIME: ::c_int = STR | 0o41; pub const I_CANPUT: ::c_int = STR | 0o42; pub const I_SERROPT: ::c_int = STR | 0o43; pub const I_GERROPT: ::c_int = STR | 0o44; pub const I_ESETSIG: ::c_int = STR | 0o45; pub const I_EGETSIG: ::c_int = STR | 0o46; pub const __I_PUSH_NOCTTY: ::c_int = STR | 0o47; // 3SOCKET flags pub const SOCK_CLOEXEC: ::c_int = 0x080000; pub const SOCK_NONBLOCK: ::c_int = 0x100000; pub const SOCK_NDELAY: ::c_int = 0x200000; // pub const SCALE_KG: ::c_int = 1 << 6; pub const SCALE_KF: ::c_int = 1 << 16; pub const SCALE_KH: ::c_int = 1 << 2; pub const MAXTC: ::c_int = 1 << 6; pub const SCALE_PHASE: ::c_int = 1 << 22; pub const SCALE_USEC: ::c_int = 1 << 16; pub const SCALE_UPDATE: ::c_int = SCALE_KG * MAXTC; pub const FINEUSEC: ::c_int = 1 << 22; pub const MAXPHASE: ::c_int = 512000; pub const MAXFREQ: ::c_int = 512 * SCALE_USEC; pub const MAXTIME: ::c_int = 200 << PPS_AVG; pub const MINSEC: ::c_int = 16; pub const MAXSEC: ::c_int = 1200; pub const PPS_AVG: ::c_int = 2; pub const PPS_SHIFT: ::c_int = 2; pub const PPS_SHIFTMAX: ::c_int = 8; pub const PPS_VALID: ::c_int = 120; pub const MAXGLITCH: ::c_int = 30; pub const MOD_OFFSET: u32 = 0x0001; pub const MOD_FREQUENCY: u32 = 0x0002; pub const MOD_MAXERROR: u32 = 0x0004; pub const MOD_ESTERROR: u32 = 0x0008; pub const MOD_STATUS: u32 = 0x0010; pub const MOD_TIMECONST: u32 = 0x0020; pub const MOD_CLKB: u32 = 0x4000; pub const MOD_CLKA: u32 = 0x8000; pub const STA_PLL: u32 = 0x0001; pub const STA_PPSFREQ: i32 = 0x0002; pub const STA_PPSTIME: i32 = 0x0004; pub const STA_FLL: i32 = 0x0008; pub const STA_INS: i32 = 0x0010; pub const STA_DEL: i32 = 0x0020; pub const STA_UNSYNC: i32 = 0x0040; pub const STA_FREQHOLD: i32 = 0x0080; pub const STA_PPSSIGNAL: i32 = 0x0100; pub const STA_PPSJITTER: i32 = 0x0200; pub const STA_PPSWANDER: i32 = 0x0400; pub const STA_PPSERROR: i32 = 0x0800; pub const STA_CLOCKERR: i32 = 0x1000; pub const STA_RONLY: i32 = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR; pub const TIME_OK: i32 = 0; pub const TIME_INS: i32 = 1; pub const TIME_DEL: i32 = 2; pub const TIME_OOP: i32 = 3; pub const TIME_WAIT: i32 = 4; pub const TIME_ERROR: i32 = 5; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const SCHED_SYS: ::c_int = 3; pub const SCHED_IA: ::c_int = 4; pub const SCHED_FSS: ::c_int = 5; pub const SCHED_FX: ::c_int = 6; // sys/priv.h pub const PRIV_DEBUG: ::c_uint = 0x0001; pub const PRIV_AWARE: ::c_uint = 0x0002; pub const PRIV_AWARE_INHERIT: ::c_uint = 0x0004; pub const __PROC_PROTECT: ::c_uint = 0x0008; pub const NET_MAC_AWARE: ::c_uint = 0x0010; pub const NET_MAC_AWARE_INHERIT: ::c_uint = 0x0020; pub const PRIV_AWARE_RESET: ::c_uint = 0x0040; pub const PRIV_XPOLICY: ::c_uint = 0x0080; pub const PRIV_PFEXEC: ::c_uint = 0x0100; pub const PRIV_USER: ::c_uint = PRIV_DEBUG | NET_MAC_AWARE | NET_MAC_AWARE_INHERIT | PRIV_XPOLICY | PRIV_AWARE_RESET | PRIV_PFEXEC; // sys/systeminfo.h pub const SI_SYSNAME: ::c_int = 1; pub const SI_HOSTNAME: ::c_int = 2; pub const SI_RELEASE: ::c_int = 3; pub const SI_VERSION: ::c_int = 4; pub const SI_MACHINE: ::c_int = 5; pub const SI_ARCHITECTURE: ::c_int = 6; pub const SI_HW_SERIAL: ::c_int = 7; pub const SI_HW_PROVIDER: ::c_int = 8; pub const SI_SET_HOSTNAME: ::c_int = 258; pub const SI_SET_SRPC_DOMAIN: ::c_int = 265; pub const SI_PLATFORM: ::c_int = 513; pub const SI_ISALIST: ::c_int = 514; pub const SI_DHCP_CACHE: ::c_int = 515; pub const SI_ARCHITECTURE_32: ::c_int = 516; pub const SI_ARCHITECTURE_64: ::c_int = 517; pub const SI_ARCHITECTURE_K: ::c_int = 518; pub const SI_ARCHITECTURE_NATIVE: ::c_int = 519; // sys/lgrp_user.h pub const LGRP_COOKIE_NONE: ::lgrp_cookie_t = 0; pub const LGRP_AFF_NONE: ::lgrp_affinity_t = 0x0; pub const LGRP_AFF_WEAK: ::lgrp_affinity_t = 0x10; pub const LGRP_AFF_STRONG: ::lgrp_affinity_t = 0x100; pub const LGRP_RSRC_COUNT: ::lgrp_rsrc_t = 2; pub const LGRP_RSRC_CPU: ::lgrp_rsrc_t = 0; pub const LGRP_RSRC_MEM: ::lgrp_rsrc_t = 1; pub const LGRP_CONTENT_ALL: ::lgrp_content_t = 0; pub const LGRP_CONTENT_HIERARCHY: ::lgrp_content_t = LGRP_CONTENT_ALL; pub const LGRP_CONTENT_DIRECT: ::lgrp_content_t = 1; pub const LGRP_LAT_CPU_TO_MEM: ::lgrp_lat_between_t = 0; pub const LGRP_MEM_SZ_FREE: ::lgrp_mem_size_flag_t = 0; pub const LGRP_MEM_SZ_INSTALLED: ::lgrp_mem_size_flag_t = 1; pub const LGRP_VIEW_CALLER: ::lgrp_view_t = 0; pub const LGRP_VIEW_OS: ::lgrp_view_t = 1; // sys/processor.h pub const P_OFFLINE: ::c_int = 0x001; pub const P_ONLINE: ::c_int = 0x002; pub const P_STATUS: ::c_int = 0x003; pub const P_FAULTED: ::c_int = 0x004; pub const P_POWEROFF: ::c_int = 0x005; pub const P_NOINTR: ::c_int = 0x006; pub const P_SPARE: ::c_int = 0x007; pub const P_DISABLED: ::c_int = 0x008; pub const P_FORCED: ::c_int = 0x10000000; pub const PI_TYPELEN: ::c_int = 16; pub const PI_FPUTYPE: ::c_int = 32; // sys/auxv.h pub const AT_SUN_HWCAP: ::c_uint = 2009; pub const AT_SUN_HWCAP2: ::c_uint = 2023; pub const AT_SUN_FPTYPE: ::c_uint = 2027; // As per sys/socket.h, header alignment must be 8 bytes on SPARC // and 4 bytes everywhere else: #[cfg(target_arch = "sparc64")] const _CMSG_HDR_ALIGNMENT: usize = 8; #[cfg(not(target_arch = "sparc64"))] const _CMSG_HDR_ALIGNMENT: usize = 4; const _CMSG_DATA_ALIGNMENT: usize = ::mem::size_of::<::c_int>(); const NEWDEV: ::c_int = 1; // sys/sendfile.h pub const SFV_FD_SELF: ::c_int = -2; const_fn! { {const} fn _CMSG_HDR_ALIGN(p: usize) -> usize { (p + _CMSG_HDR_ALIGNMENT - 1) & !(_CMSG_HDR_ALIGNMENT - 1) } {const} fn _CMSG_DATA_ALIGN(p: usize) -> usize { (p + _CMSG_DATA_ALIGNMENT - 1) & !(_CMSG_DATA_ALIGNMENT - 1) } } f! { pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { _CMSG_DATA_ALIGN(cmsg.offset(1) as usize) as *mut ::c_uchar } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { _CMSG_DATA_ALIGN(::mem::size_of::<::cmsghdr>()) as ::c_uint + length } pub fn CMSG_FIRSTHDR(mhdr: *const ::msghdr) -> *mut ::cmsghdr { if ((*mhdr).msg_controllen as usize) < ::mem::size_of::<::cmsghdr>() { 0 as *mut ::cmsghdr } else { (*mhdr).msg_control as *mut ::cmsghdr } } pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr) -> *mut ::cmsghdr { if cmsg.is_null() { return ::CMSG_FIRSTHDR(mhdr); }; let next = _CMSG_HDR_ALIGN(cmsg as usize + (*cmsg).cmsg_len as usize + ::mem::size_of::<::cmsghdr>()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut ::cmsghdr } else { _CMSG_HDR_ALIGN(cmsg as usize + (*cmsg).cmsg_len as usize) as *mut ::cmsghdr } } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { _CMSG_HDR_ALIGN(::mem::size_of::<::cmsghdr>() as usize + length as usize) as ::c_uint } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0xFF) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { (status >> 8) & 0xFF } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { status & 0x7F } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { (status & 0xffff) == 0xffff } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status & 0xff00) >> 8 } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { ((status & 0xff) > 0) && (status & 0xff00 == 0) } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { ((status & 0xff) == 0x7f) && ((status & 0xff00) != 0) } pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0x80) != 0 } pub {const} fn MR_GET_TYPE(flags: ::c_uint) -> ::c_uint { flags & 0x0000ffff } } extern "C" { pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; pub fn getrandom(bbuf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn settimeofday(tp: *const ::timeval, tz: *const ::c_void) -> ::c_int; pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn stack_getbounds(sp: *mut ::stack_t) -> ::c_int; pub fn getgrouplist( name: *const ::c_char, basegid: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn ioctl(fildes: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn ___errno() -> *mut ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn getprogname() -> *const ::c_char; pub fn setprogname(name: *const ::c_char); pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::c_int) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) -> ::c_int; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_getname_np(tid: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_setname_np(tid: ::pthread_t, name: *const ::c_char) -> ::c_int; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; #[cfg_attr(target_os = "illumos", link_name = "_glob_ext")] pub fn glob( pattern: *const ::c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; #[cfg_attr(target_os = "illumos", link_name = "_globfree_ext")] pub fn globfree(pglob: *mut ::glob_t); pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmget(key: key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; pub fn futimesat(fd: ::c_int, path: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn futimens(dirfd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; #[cfg_attr(target_os = "illumos", link_name = "__xnet_bind")] pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; #[cfg_attr(target_os = "illumos", link_name = "__xnet_sendmsg")] pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; #[cfg_attr(target_os = "illumos", link_name = "__xnet_recvmsg")] pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn accept4( fd: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t, flags: ::c_int, ) -> ::c_int; pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, abs_timeout: *const ::timespec, ) -> ::ssize_t; pub fn mq_send( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_timedsend( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; pub fn port_create() -> ::c_int; pub fn port_associate( port: ::c_int, source: ::c_int, object: ::uintptr_t, events: ::c_int, user: *mut ::c_void, ) -> ::c_int; pub fn port_dissociate(port: ::c_int, source: ::c_int, object: ::uintptr_t) -> ::c_int; pub fn port_get(port: ::c_int, pe: *mut port_event, timeout: *mut ::timespec) -> ::c_int; pub fn port_getn( port: ::c_int, pe_list: *mut port_event, max: ::c_uint, nget: *mut ::c_uint, timeout: *mut ::timespec, ) -> ::c_int; pub fn port_send(port: ::c_int, events: ::c_int, user: *mut ::c_void) -> ::c_int; pub fn port_sendn( port_list: *mut ::c_int, error_list: *mut ::c_int, nent: ::c_uint, events: ::c_int, user: *mut ::c_void, ) -> ::c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getgrgid_r" )] pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; // The epoll functions are actually only present on illumos. However, // there are things using epoll on illumos (built using the // x86_64-pc-solaris target) which would break until the illumos target is // present in rustc. pub fn epoll_pwait( epfd: ::c_int, events: *mut ::epoll_event, maxevents: ::c_int, timeout: ::c_int, sigmask: *const ::sigset_t, ) -> ::c_int; pub fn epoll_create(size: ::c_int) -> ::c_int; pub fn epoll_create1(flags: ::c_int) -> ::c_int; pub fn epoll_wait( epfd: ::c_int, events: *mut ::epoll_event, maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) -> ::c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getgrnam_r" )] pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn thr_self() -> ::thread_t; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut sched_param) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const sched_param) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getpwnam_r" )] pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_getpwuid_r" )] pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "getpwent_r" )] fn native_getpwent_r(pwd: *mut passwd, buf: *mut ::c_char, buflen: ::c_int) -> *mut passwd; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "getgrent_r" )] fn native_getgrent_r(grp: *mut ::group, buf: *mut ::c_char, buflen: ::c_int) -> *mut ::group; #[cfg_attr( any(target_os = "solaris", target_os = "illumos"), link_name = "__posix_sigwait" )] pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut ::group; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn dup3(src: ::c_int, dst: ::c_int, flags: ::c_int) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn makeutx(ux: *const utmpx) -> *mut utmpx; pub fn modutx(ux: *const utmpx) -> *mut utmpx; pub fn updwtmpx(file: *const ::c_char, ut: *const utmpx) -> ::c_int; pub fn utmpxname(file: *const ::c_char) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn endutent(); pub fn getutent() -> *mut utmp; pub fn getutid(u: *const utmp) -> *mut utmp; pub fn getutline(u: *const utmp) -> *mut utmp; pub fn pututline(u: *const utmp) -> *mut utmp; pub fn setutent(); pub fn utmpname(file: *const ::c_char) -> ::c_int; pub fn getutmp(ux: *const utmpx, u: *mut utmp); pub fn getutmpx(u: *const utmp, ux: *mut utmpx); pub fn updwtmp(file: *const ::c_char, u: *mut utmp); pub fn ntp_adjtime(buf: *mut timex) -> ::c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int; pub fn timer_create(clock_id: clockid_t, evp: *mut sigevent, timerid: *mut timer_t) -> ::c_int; pub fn timer_delete(timerid: timer_t) -> ::c_int; pub fn timer_getoverrun(timerid: timer_t) -> ::c_int; pub fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> ::c_int; pub fn timer_settime( timerid: timer_t, flags: ::c_int, value: *const itimerspec, ovalue: *mut itimerspec, ) -> ::c_int; pub fn ucred_get(pid: ::pid_t) -> *mut ucred_t; pub fn getpeerucred(fd: ::c_int, ucred: *mut *mut ucred_t) -> ::c_int; pub fn ucred_free(ucred: *mut ucred_t); pub fn ucred_geteuid(ucred: *const ucred_t) -> ::uid_t; pub fn ucred_getruid(ucred: *const ucred_t) -> ::uid_t; pub fn ucred_getsuid(ucred: *const ucred_t) -> ::uid_t; pub fn ucred_getegid(ucred: *const ucred_t) -> ::gid_t; pub fn ucred_getrgid(ucred: *const ucred_t) -> ::gid_t; pub fn ucred_getsgid(ucred: *const ucred_t) -> ::gid_t; pub fn ucred_getgroups(ucred: *const ucred_t, groups: *mut *const ::gid_t) -> ::c_int; pub fn ucred_getpid(ucred: *const ucred_t) -> ::pid_t; pub fn ucred_getprojid(ucred: *const ucred_t) -> projid_t; pub fn ucred_getzoneid(ucred: *const ucred_t) -> zoneid_t; pub fn ucred_getpflags(ucred: *const ucred_t, flags: ::c_uint) -> ::c_uint; pub fn ucred_size() -> ::size_t; pub fn pset_create(newpset: *mut ::psetid_t) -> ::c_int; pub fn pset_destroy(pset: ::psetid_t) -> ::c_int; pub fn pset_assign(pset: ::psetid_t, cpu: ::processorid_t, opset: *mut psetid_t) -> ::c_int; pub fn pset_info( pset: ::psetid_t, tpe: *mut ::c_int, numcpus: *mut ::c_uint, cpulist: *mut processorid_t, ) -> ::c_int; pub fn pset_bind( pset: ::psetid_t, idtype: ::idtype_t, id: ::id_t, opset: *mut psetid_t, ) -> ::c_int; pub fn pset_list(pset: *mut psetid_t, numpsets: *mut ::c_uint) -> ::c_int; pub fn pset_setattr(pset: psetid_t, attr: ::c_uint) -> ::c_int; pub fn pset_getattr(pset: psetid_t, attr: *mut ::c_uint) -> ::c_int; pub fn processor_bind( idtype: ::idtype_t, id: ::id_t, new_binding: ::processorid_t, old_binding: *mut processorid_t, ) -> ::c_int; pub fn p_online(processorid: ::processorid_t, flag: ::c_int) -> ::c_int; pub fn processor_info(processorid: ::processorid_t, infop: *mut processor_info_t) -> ::c_int; pub fn getexecname() -> *const ::c_char; pub fn gethostid() -> ::c_long; pub fn getpflags(flags: ::c_uint) -> ::c_uint; pub fn setpflags(flags: ::c_uint, value: ::c_uint) -> ::c_int; pub fn sysinfo(command: ::c_int, buf: *mut ::c_char, count: ::c_long) -> ::c_int; pub fn faccessat(fd: ::c_int, path: *const ::c_char, amode: ::c_int, flag: ::c_int) -> ::c_int; // #include #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut dl_phdr_info, size: usize, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; pub fn getpagesize() -> ::c_int; pub fn getpagesizes(pagesize: *mut ::size_t, nelem: ::c_int) -> ::c_int; pub fn mmapobj( fd: ::c_int, flags: ::c_uint, storage: *mut mmapobj_result_t, elements: *mut ::c_uint, arg: *mut ::c_void, ) -> ::c_int; pub fn meminfo( inaddr: *const u64, addr_count: ::c_int, info_req: *const ::c_uint, info_count: ::c_int, outdata: *mut u64, validity: *mut ::c_uint, ) -> ::c_int; pub fn strcasecmp_l(s1: *const ::c_char, s2: *const ::c_char, loc: ::locale_t) -> ::c_int; pub fn strncasecmp_l( s1: *const ::c_char, s2: *const ::c_char, n: ::size_t, loc: ::locale_t, ) -> ::c_int; pub fn strsep(string: *mut *mut ::c_char, delim: *const ::c_char) -> *mut ::c_char; pub fn getisax(array: *mut u32, n: ::c_uint) -> ::c_uint; pub fn backtrace(buffer: *mut *mut ::c_void, size: ::c_int) -> ::c_int; pub fn backtrace_symbols(buffer: *const *mut ::c_void, size: ::c_int) -> *mut *mut ::c_char; pub fn backtrace_symbols_fd(buffer: *const *mut ::c_void, size: ::c_int, fd: ::c_int); pub fn getopt_long( argc: ::c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut ::c_int, ) -> ::c_int; pub fn sync(); pub fn __major(version: ::c_int, devnum: ::dev_t) -> ::major_t; pub fn __minor(version: ::c_int, devnum: ::dev_t) -> ::minor_t; pub fn __makedev(version: ::c_int, majdev: ::major_t, mindev: ::minor_t) -> ::dev_t; } #[link(name = "sendfile")] extern "C" { pub fn sendfile(out_fd: ::c_int, in_fd: ::c_int, off: *mut ::off_t, len: ::size_t) -> ::ssize_t; pub fn sendfilev( fildes: ::c_int, vec: *const sendfilevec_t, sfvcnt: ::c_int, xferred: *mut ::size_t, ) -> ::ssize_t; } #[link(name = "lgrp")] extern "C" { pub fn lgrp_init(view: lgrp_view_t) -> lgrp_cookie_t; pub fn lgrp_fini(cookie: lgrp_cookie_t) -> ::c_int; pub fn lgrp_affinity_get( idtype: ::idtype_t, id: ::id_t, lgrp: ::lgrp_id_t, ) -> ::lgrp_affinity_t; pub fn lgrp_affinity_set( idtype: ::idtype_t, id: ::id_t, lgrp: ::lgrp_id_t, aff: lgrp_affinity_t, ) -> ::lgrp_affinity_t; pub fn lgrp_cpus( cookie: ::lgrp_cookie_t, lgrp: ::lgrp_id_t, cpuids: *mut ::processorid_t, count: ::c_uint, content: ::lgrp_content_t, ) -> ::c_int; pub fn lgrp_mem_size( cookie: ::lgrp_cookie_t, lgrp: ::lgrp_id_t, tpe: ::lgrp_mem_size_flag_t, content: ::lgrp_content_t, ) -> ::lgrp_mem_size_t; pub fn lgrp_nlgrps(cookie: ::lgrp_cookie_t) -> ::c_int; pub fn lgrp_view(cookie: ::lgrp_cookie_t) -> ::lgrp_view_t; pub fn lgrp_home(idtype: ::idtype_t, id: ::id_t) -> ::lgrp_id_t; pub fn lgrp_version(version: ::c_int) -> ::c_int; pub fn lgrp_resources( cookie: ::lgrp_cookie_t, lgrp: ::lgrp_id_t, lgrps: *mut ::lgrp_id_t, count: ::c_uint, tpe: ::lgrp_rsrc_t, ) -> ::c_int; pub fn lgrp_root(cookie: ::lgrp_cookie_t) -> ::lgrp_id_t; } pub unsafe fn major(device: ::dev_t) -> ::major_t { __major(NEWDEV, device) } pub unsafe fn minor(device: ::dev_t) -> ::minor_t { __minor(NEWDEV, device) } pub unsafe fn makedev(maj: ::major_t, min: ::minor_t) -> ::dev_t { __makedev(NEWDEV, maj, min) } mod compat; pub use self::compat::*; cfg_if! { if #[cfg(target_os = "illumos")] { mod illumos; pub use self::illumos::*; } else if #[cfg(target_os = "solaris")] { mod solaris; pub use self::solaris::*; } else { // Unknown target_os } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; mod x86_common; pub use self::x86_64::*; pub use self::x86_common::*; } else if #[cfg(target_arch = "x86")] { mod x86; mod x86_common; pub use self::x86::*; pub use self::x86_common::*; } } libc/src/unix/nto/0000775000175000017500000000000014661133735015026 5ustar jamespagejamespagelibc/src/unix/nto/neutrino.rs0000644000175000017500000012233014661133735017236 0ustar jamespagejamespagepub type nto_job_t = ::sync_t; s! { pub struct syspage_entry_info { pub entry_off: u16, pub entry_size: u16, } pub struct syspage_array_info { entry_off: u16, entry_size: u16, element_size: u16, } pub struct intrspin { pub value: ::c_uint, // volatile } pub struct iov_t { pub iov_base: *mut ::c_void, // union pub iov_len: ::size_t, } pub struct _itimer { pub nsec: u64, pub interval_nsec: u64, } pub struct _msg_info64 { pub nd: u32, pub srcnd: u32, pub pid: ::pid_t, pub tid: i32, pub chid: i32, pub scoid: i32, pub coid: i32, pub priority: i16, pub flags: i16, pub msglen: isize, pub srcmsglen: isize, pub dstmsglen: isize, pub type_id: u32, reserved: u32, } pub struct _cred_info { pub ruid: ::uid_t, pub euid: ::uid_t, pub suid: ::uid_t, pub rgid: ::gid_t, pub egid: ::gid_t, pub sgid: ::gid_t, pub ngroups: u32, pub grouplist: [::gid_t; 8], } pub struct _client_info { pub nd: u32, pub pid: ::pid_t, pub sid: ::pid_t, pub flags: u32, pub cred: ::_cred_info, } pub struct _client_able { pub ability: u32, pub flags: u32, pub range_lo: u64, pub range_hi: u64, } pub struct nto_channel_config { pub event: ::sigevent, pub num_pulses: ::c_uint, pub rearm_threshold: ::c_uint, pub options: ::c_uint, reserved: [::c_uint; 3], } // TODO: The following structures are defined in a header file which doesn't // appear as part of the default headers found in a standard installation // of Neutrino 7.1 SDP. Commented out for now. //pub struct _asyncmsg_put_header { // pub err: ::c_int, // pub iov: *mut ::iov_t, // pub parts: ::c_int, // pub handle: ::c_uint, // pub cb: ::Option< // unsafe extern "C" fn( // err: ::c_int, // buf: *mut ::c_void, // handle: ::c_uint, // ) -> ::c_int>, // pub put_hdr_flags: ::c_uint, //} //pub struct _asyncmsg_connection_attr { // pub call_back: ::Option< // unsafe extern "C" fn( // err: ::c_int, // buff: *mut ::c_void, // handle: ::c_uint, // ) -> ::c_int>, // pub buffer_size: ::size_t, // pub max_num_buffer: ::c_uint, // pub trigger_num_msg: ::c_uint, // pub trigger_time: ::_itimer, // reserve: ::c_uint, //} //pub struct _asyncmsg_connection_descriptor { // pub flags: ::c_uint, // pub sendq_size: ::c_uint, // pub sendq_head: ::c_uint, // pub sendq_tail: ::c_uint, // pub sendq_free: ::c_uint, // pub err: ::c_int, // pub ev: ::sigevent, // pub num_curmsg: ::c_uint, // pub ttimer: ::timer_t, // pub block_con: ::pthread_cond_t, // pub mu: ::pthread_mutex_t, // reserved: ::c_uint, // pub attr: ::_asyncmsg_connection_attr, // pub reserves: [::c_uint; 3], // pub sendq: [::_asyncmsg_put_header; 1], // flexarray //} pub struct __c_anonymous_struct_ev { pub event: ::sigevent, pub coid: ::c_int, } pub struct _channel_connect_attr { // union pub ev: ::__c_anonymous_struct_ev, } pub struct _sighandler_info { pub siginfo: ::siginfo_t, pub handler: ::Option, pub context: *mut ::c_void, } pub struct __c_anonymous_struct_time { pub length: ::c_uint, pub scale: ::c_uint, } pub struct _idle_hook { pub hook_size: ::c_uint, pub cmd: ::c_uint, pub mode: ::c_uint, pub latency: ::c_uint, pub next_fire: u64, pub curr_time: u64, pub tod_adjust: u64, pub resp: ::c_uint, pub time: __c_anonymous_struct_time, pub trigger: ::sigevent, pub intrs: *mut ::c_uint, pub block_stack_size: ::c_uint, } pub struct _clockadjust { pub tick_count: u32, pub tick_nsec_inc: i32, } pub struct qtime_entry { pub cycles_per_sec: u64, pub nsec_tod_adjust: u64, // volatile pub nsec: u64, // volatile pub nsec_inc: u32, pub boot_time: u32, pub adjust: _clockadjust, pub timer_rate: u32, pub timer_scale: i32, pub timer_load: u32, pub intr: i32, pub epoch: u32, pub flags: u32, pub rr_interval_mul: u32, pub timer_load_hi: u32, pub nsec_stable: u64, // volatile pub timer_load_max: u64, pub timer_prog_time: u32, spare: [u32; 7], } pub struct _sched_info { pub priority_min: ::c_int, pub priority_max: ::c_int, pub interval: u64, pub priority_priv: ::c_int, reserved: [::c_int; 11], } pub struct _timer_info { pub itime: ::_itimer, pub otime: ::_itimer, pub flags: u32, pub tid: i32, pub notify: i32, pub clockid: ::clockid_t, pub overruns: u32, pub event: ::sigevent, // union } pub struct _clockperiod { pub nsec: u32, pub fract: i32, } } s_no_extra_traits! { #[repr(align(8))] pub struct syspage_entry { pub size: u16, pub total_size: u16, pub type_: u16, pub num_cpu: u16, pub system_private: syspage_entry_info, pub old_asinfo: syspage_entry_info, pub __mangle_name_to_cause_compilation_errs_meminfo: syspage_entry_info, pub hwinfo: syspage_entry_info, pub old_cpuinfo: syspage_entry_info, pub old_cacheattr: syspage_entry_info, pub qtime: syspage_entry_info, pub callout: syspage_entry_info, pub callin: syspage_entry_info, pub typed_strings: syspage_entry_info, pub strings: syspage_entry_info, pub old_intrinfo: syspage_entry_info, pub smp: syspage_entry_info, pub pminfo: syspage_entry_info, pub old_mdriver: syspage_entry_info, spare0: [u32; 1], __reserved: [u8; 160], // anonymous union with architecture dependent structs pub new_asinfo: syspage_array_info, pub new_cpuinfo: syspage_array_info, pub new_cacheattr: syspage_array_info, pub new_intrinfo: syspage_array_info, pub new_mdriver: syspage_array_info, } } pub const SYSMGR_PID: u32 = 1; pub const SYSMGR_CHID: u32 = 1; pub const SYSMGR_COID: u32 = _NTO_SIDE_CHANNEL; pub const SYSMGR_HANDLE: u32 = 0; pub const STATE_DEAD: ::c_int = 0x00; pub const STATE_RUNNING: ::c_int = 0x01; pub const STATE_READY: ::c_int = 0x02; pub const STATE_STOPPED: ::c_int = 0x03; pub const STATE_SEND: ::c_int = 0x04; pub const STATE_RECEIVE: ::c_int = 0x05; pub const STATE_REPLY: ::c_int = 0x06; pub const STATE_STACK: ::c_int = 0x07; pub const STATE_WAITTHREAD: ::c_int = 0x08; pub const STATE_WAITPAGE: ::c_int = 0x09; pub const STATE_SIGSUSPEND: ::c_int = 0x0a; pub const STATE_SIGWAITINFO: ::c_int = 0x0b; pub const STATE_NANOSLEEP: ::c_int = 0x0c; pub const STATE_MUTEX: ::c_int = 0x0d; pub const STATE_CONDVAR: ::c_int = 0x0e; pub const STATE_JOIN: ::c_int = 0x0f; pub const STATE_INTR: ::c_int = 0x10; pub const STATE_SEM: ::c_int = 0x11; pub const STATE_WAITCTX: ::c_int = 0x12; pub const STATE_NET_SEND: ::c_int = 0x13; pub const STATE_NET_REPLY: ::c_int = 0x14; pub const STATE_MAX: ::c_int = 0x18; pub const _NTO_TIMEOUT_RECEIVE: i32 = 1 << STATE_RECEIVE; pub const _NTO_TIMEOUT_SEND: i32 = 1 << STATE_SEND; pub const _NTO_TIMEOUT_REPLY: i32 = 1 << STATE_REPLY; pub const _NTO_TIMEOUT_SIGSUSPEND: i32 = 1 << STATE_SIGSUSPEND; pub const _NTO_TIMEOUT_SIGWAITINFO: i32 = 1 << STATE_SIGWAITINFO; pub const _NTO_TIMEOUT_NANOSLEEP: i32 = 1 << STATE_NANOSLEEP; pub const _NTO_TIMEOUT_MUTEX: i32 = 1 << STATE_MUTEX; pub const _NTO_TIMEOUT_CONDVAR: i32 = 1 << STATE_CONDVAR; pub const _NTO_TIMEOUT_JOIN: i32 = 1 << STATE_JOIN; pub const _NTO_TIMEOUT_INTR: i32 = 1 << STATE_INTR; pub const _NTO_TIMEOUT_SEM: i32 = 1 << STATE_SEM; pub const _NTO_MI_ENDIAN_BIG: u32 = 1; pub const _NTO_MI_ENDIAN_DIFF: u32 = 2; pub const _NTO_MI_UNBLOCK_REQ: u32 = 256; pub const _NTO_MI_NET_CRED_DIRTY: u32 = 512; pub const _NTO_MI_CONSTRAINED: u32 = 1024; pub const _NTO_MI_CHROOT: u32 = 2048; pub const _NTO_MI_BITS_64: u32 = 4096; pub const _NTO_MI_BITS_DIFF: u32 = 8192; pub const _NTO_MI_SANDBOX: u32 = 16384; pub const _NTO_CI_ENDIAN_BIG: u32 = 1; pub const _NTO_CI_BKGND_PGRP: u32 = 4; pub const _NTO_CI_ORPHAN_PGRP: u32 = 8; pub const _NTO_CI_STOPPED: u32 = 128; pub const _NTO_CI_UNABLE: u32 = 256; pub const _NTO_CI_TYPE_ID: u32 = 512; pub const _NTO_CI_CHROOT: u32 = 2048; pub const _NTO_CI_BITS_64: u32 = 4096; pub const _NTO_CI_SANDBOX: u32 = 16384; pub const _NTO_CI_LOADER: u32 = 32768; pub const _NTO_CI_FULL_GROUPS: u32 = 2147483648; pub const _NTO_TI_ACTIVE: u32 = 1; pub const _NTO_TI_ABSOLUTE: u32 = 2; pub const _NTO_TI_EXPIRED: u32 = 4; pub const _NTO_TI_TOD_BASED: u32 = 8; pub const _NTO_TI_TARGET_PROCESS: u32 = 16; pub const _NTO_TI_REPORT_TOLERANCE: u32 = 32; pub const _NTO_TI_PRECISE: u32 = 64; pub const _NTO_TI_TOLERANT: u32 = 128; pub const _NTO_TI_WAKEUP: u32 = 256; pub const _NTO_TI_PROCESS_TOLERANT: u32 = 512; pub const _NTO_TI_HIGH_RESOLUTION: u32 = 1024; pub const _PULSE_TYPE: u32 = 0; pub const _PULSE_SUBTYPE: u32 = 0; pub const _PULSE_CODE_UNBLOCK: i32 = -32; pub const _PULSE_CODE_DISCONNECT: i32 = -33; pub const _PULSE_CODE_THREADDEATH: i32 = -34; pub const _PULSE_CODE_COIDDEATH: i32 = -35; pub const _PULSE_CODE_NET_ACK: i32 = -36; pub const _PULSE_CODE_NET_UNBLOCK: i32 = -37; pub const _PULSE_CODE_NET_DETACH: i32 = -38; pub const _PULSE_CODE_RESTART: i32 = -39; pub const _PULSE_CODE_NORESTART: i32 = -40; pub const _PULSE_CODE_UNBLOCK_RESTART: i32 = -41; pub const _PULSE_CODE_UNBLOCK_TIMER: i32 = -42; pub const _PULSE_CODE_MINAVAIL: u32 = 0; pub const _PULSE_CODE_MAXAVAIL: u32 = 127; pub const _NTO_HARD_FLAGS_END: u32 = 1; pub const _NTO_PULSE_IF_UNIQUE: u32 = 4096; pub const _NTO_PULSE_REPLACE: u32 = 8192; pub const _NTO_PF_NOCLDSTOP: u32 = 1; pub const _NTO_PF_LOADING: u32 = 2; pub const _NTO_PF_TERMING: u32 = 4; pub const _NTO_PF_ZOMBIE: u32 = 8; pub const _NTO_PF_NOZOMBIE: u32 = 16; pub const _NTO_PF_FORKED: u32 = 32; pub const _NTO_PF_ORPHAN_PGRP: u32 = 64; pub const _NTO_PF_STOPPED: u32 = 128; pub const _NTO_PF_DEBUG_STOPPED: u32 = 256; pub const _NTO_PF_BKGND_PGRP: u32 = 512; pub const _NTO_PF_NOISYNC: u32 = 1024; pub const _NTO_PF_CONTINUED: u32 = 2048; pub const _NTO_PF_CHECK_INTR: u32 = 4096; pub const _NTO_PF_COREDUMP: u32 = 8192; pub const _NTO_PF_RING0: u32 = 32768; pub const _NTO_PF_SLEADER: u32 = 65536; pub const _NTO_PF_WAITINFO: u32 = 131072; pub const _NTO_PF_DESTROYALL: u32 = 524288; pub const _NTO_PF_NOCOREDUMP: u32 = 1048576; pub const _NTO_PF_WAITDONE: u32 = 4194304; pub const _NTO_PF_TERM_WAITING: u32 = 8388608; pub const _NTO_PF_ASLR: u32 = 16777216; pub const _NTO_PF_EXECED: u32 = 33554432; pub const _NTO_PF_APP_STOPPED: u32 = 67108864; pub const _NTO_PF_64BIT: u32 = 134217728; pub const _NTO_PF_NET: u32 = 268435456; pub const _NTO_PF_NOLAZYSTACK: u32 = 536870912; pub const _NTO_PF_NOEXEC_STACK: u32 = 1073741824; pub const _NTO_PF_LOADER_PERMS: u32 = 2147483648; pub const _NTO_TF_INTR_PENDING: u32 = 65536; pub const _NTO_TF_DETACHED: u32 = 131072; pub const _NTO_TF_SHR_MUTEX: u32 = 262144; pub const _NTO_TF_SHR_MUTEX_EUID: u32 = 524288; pub const _NTO_TF_THREADS_HOLD: u32 = 1048576; pub const _NTO_TF_UNBLOCK_REQ: u32 = 4194304; pub const _NTO_TF_ALIGN_FAULT: u32 = 16777216; pub const _NTO_TF_SSTEP: u32 = 33554432; pub const _NTO_TF_ALLOCED_STACK: u32 = 67108864; pub const _NTO_TF_NOMULTISIG: u32 = 134217728; pub const _NTO_TF_LOW_LATENCY: u32 = 268435456; pub const _NTO_TF_IOPRIV: u32 = 2147483648; pub const _NTO_TCTL_IO_PRIV: u32 = 1; pub const _NTO_TCTL_THREADS_HOLD: u32 = 2; pub const _NTO_TCTL_THREADS_CONT: u32 = 3; pub const _NTO_TCTL_RUNMASK: u32 = 4; pub const _NTO_TCTL_ALIGN_FAULT: u32 = 5; pub const _NTO_TCTL_RUNMASK_GET_AND_SET: u32 = 6; pub const _NTO_TCTL_PERFCOUNT: u32 = 7; pub const _NTO_TCTL_ONE_THREAD_HOLD: u32 = 8; pub const _NTO_TCTL_ONE_THREAD_CONT: u32 = 9; pub const _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT: u32 = 10; pub const _NTO_TCTL_NAME: u32 = 11; pub const _NTO_TCTL_RCM_GET_AND_SET: u32 = 12; pub const _NTO_TCTL_SHR_MUTEX: u32 = 13; pub const _NTO_TCTL_IO: u32 = 14; pub const _NTO_TCTL_NET_KIF_GET_AND_SET: u32 = 15; pub const _NTO_TCTL_LOW_LATENCY: u32 = 16; pub const _NTO_TCTL_ADD_EXIT_EVENT: u32 = 17; pub const _NTO_TCTL_DEL_EXIT_EVENT: u32 = 18; pub const _NTO_TCTL_IO_LEVEL: u32 = 19; pub const _NTO_TCTL_RESERVED: u32 = 2147483648; pub const _NTO_TCTL_IO_LEVEL_INHERIT: u32 = 1073741824; pub const _NTO_IO_LEVEL_NONE: u32 = 1; pub const _NTO_IO_LEVEL_1: u32 = 2; pub const _NTO_IO_LEVEL_2: u32 = 3; pub const _NTO_THREAD_NAME_MAX: u32 = 100; pub const _NTO_CHF_FIXED_PRIORITY: u32 = 1; pub const _NTO_CHF_UNBLOCK: u32 = 2; pub const _NTO_CHF_THREAD_DEATH: u32 = 4; pub const _NTO_CHF_DISCONNECT: u32 = 8; pub const _NTO_CHF_NET_MSG: u32 = 16; pub const _NTO_CHF_SENDER_LEN: u32 = 32; pub const _NTO_CHF_COID_DISCONNECT: u32 = 64; pub const _NTO_CHF_REPLY_LEN: u32 = 128; pub const _NTO_CHF_PULSE_POOL: u32 = 256; pub const _NTO_CHF_ASYNC_NONBLOCK: u32 = 512; pub const _NTO_CHF_ASYNC: u32 = 1024; pub const _NTO_CHF_GLOBAL: u32 = 2048; pub const _NTO_CHF_PRIVATE: u32 = 4096; pub const _NTO_CHF_MSG_PAUSING: u32 = 8192; pub const _NTO_CHF_INHERIT_RUNMASK: u32 = 16384; pub const _NTO_CHF_UNBLOCK_TIMER: u32 = 32768; pub const _NTO_CHO_CUSTOM_EVENT: u32 = 1; pub const _NTO_COF_CLOEXEC: u32 = 1; pub const _NTO_COF_DEAD: u32 = 2; pub const _NTO_COF_NOSHARE: u32 = 64; pub const _NTO_COF_NETCON: u32 = 128; pub const _NTO_COF_NONBLOCK: u32 = 256; pub const _NTO_COF_ASYNC: u32 = 512; pub const _NTO_COF_GLOBAL: u32 = 1024; pub const _NTO_COF_NOEVENT: u32 = 2048; pub const _NTO_COF_INSECURE: u32 = 4096; pub const _NTO_COF_REG_EVENTS: u32 = 8192; pub const _NTO_COF_UNREG_EVENTS: u32 = 16384; pub const _NTO_COF_MASK: u32 = 65535; pub const _NTO_SIDE_CHANNEL: u32 = 1073741824; pub const _NTO_CONNECTION_SCOID: u32 = 65536; pub const _NTO_GLOBAL_CHANNEL: u32 = 1073741824; pub const _NTO_TIMEOUT_MASK: u32 = (1 << STATE_MAX) - 1; pub const _NTO_TIMEOUT_ACTIVE: u32 = 1 << STATE_MAX; pub const _NTO_TIMEOUT_IMMEDIATE: u32 = 1 << (STATE_MAX + 1); pub const _NTO_IC_LATENCY: u32 = 0; pub const _NTO_INTR_FLAGS_END: u32 = 1; pub const _NTO_INTR_FLAGS_NO_UNMASK: u32 = 2; pub const _NTO_INTR_FLAGS_PROCESS: u32 = 4; pub const _NTO_INTR_FLAGS_TRK_MSK: u32 = 8; pub const _NTO_INTR_FLAGS_ARRAY: u32 = 16; pub const _NTO_INTR_FLAGS_EXCLUSIVE: u32 = 32; pub const _NTO_INTR_FLAGS_FPU: u32 = 64; pub const _NTO_INTR_CLASS_EXTERNAL: u32 = 0; pub const _NTO_INTR_CLASS_SYNTHETIC: u32 = 2147418112; pub const _NTO_INTR_SPARE: u32 = 2147483647; pub const _NTO_HOOK_IDLE: u32 = 2147418113; pub const _NTO_HOOK_OVERDRIVE: u32 = 2147418114; pub const _NTO_HOOK_LAST: u32 = 2147418114; pub const _NTO_HOOK_IDLE2_FLAG: u32 = 32768; pub const _NTO_IH_CMD_SLEEP_SETUP: u32 = 1; pub const _NTO_IH_CMD_SLEEP_BLOCK: u32 = 2; pub const _NTO_IH_CMD_SLEEP_WAKEUP: u32 = 4; pub const _NTO_IH_CMD_SLEEP_ONLINE: u32 = 8; pub const _NTO_IH_RESP_NEEDS_BLOCK: u32 = 1; pub const _NTO_IH_RESP_NEEDS_WAKEUP: u32 = 2; pub const _NTO_IH_RESP_NEEDS_ONLINE: u32 = 4; pub const _NTO_IH_RESP_SYNC_TIME: u32 = 16; pub const _NTO_IH_RESP_SYNC_TLB: u32 = 32; pub const _NTO_IH_RESP_SUGGEST_OFFLINE: u32 = 256; pub const _NTO_IH_RESP_SLEEP_MODE_REACHED: u32 = 512; pub const _NTO_IH_RESP_DELIVER_INTRS: u32 = 1024; pub const _NTO_READIOV_SEND: u32 = 0; pub const _NTO_READIOV_REPLY: u32 = 1; pub const _NTO_KEYDATA_VTID: u32 = 2147483648; pub const _NTO_KEYDATA_PATHSIGN: u32 = 32768; pub const _NTO_KEYDATA_OP_MASK: u32 = 255; pub const _NTO_KEYDATA_VERIFY: u32 = 0; pub const _NTO_KEYDATA_CALCULATE: u32 = 1; pub const _NTO_KEYDATA_CALCULATE_REUSE: u32 = 2; pub const _NTO_KEYDATA_PATHSIGN_VERIFY: u32 = 32768; pub const _NTO_KEYDATA_PATHSIGN_CALCULATE: u32 = 32769; pub const _NTO_KEYDATA_PATHSIGN_CALCULATE_REUSE: u32 = 32770; pub const _NTO_SCTL_SETPRIOCEILING: u32 = 1; pub const _NTO_SCTL_GETPRIOCEILING: u32 = 2; pub const _NTO_SCTL_SETEVENT: u32 = 3; pub const _NTO_SCTL_MUTEX_WAKEUP: u32 = 4; pub const _NTO_SCTL_MUTEX_CONSISTENT: u32 = 5; pub const _NTO_SCTL_SEM_VALUE: u32 = 6; pub const _NTO_CLIENTINFO_GETGROUPS: u32 = 1; pub const _NTO_CLIENTINFO_GETTYPEID: u32 = 2; extern "C" { pub fn ChannelCreate(__flags: ::c_uint) -> ::c_int; pub fn ChannelCreate_r(__flags: ::c_uint) -> ::c_int; pub fn ChannelCreatePulsePool( __flags: ::c_uint, __config: *const nto_channel_config, ) -> ::c_int; pub fn ChannelCreateExt( __flags: ::c_uint, __mode: ::mode_t, __bufsize: usize, __maxnumbuf: ::c_uint, __ev: *const ::sigevent, __cred: *mut _cred_info, ) -> ::c_int; pub fn ChannelDestroy(__chid: ::c_int) -> ::c_int; pub fn ChannelDestroy_r(__chid: ::c_int) -> ::c_int; pub fn ConnectAttach( __nd: u32, __pid: ::pid_t, __chid: ::c_int, __index: ::c_uint, __flags: ::c_int, ) -> ::c_int; pub fn ConnectAttach_r( __nd: u32, __pid: ::pid_t, __chid: ::c_int, __index: ::c_uint, __flags: ::c_int, ) -> ::c_int; // TODO: The following function uses a structure defined in a header file // which doesn't appear as part of the default headers found in a // standard installation of Neutrino 7.1 SDP. Commented out for now. //pub fn ConnectAttachExt( // __nd: u32, // __pid: ::pid_t, // __chid: ::c_int, // __index: ::c_uint, // __flags: ::c_int, // __cd: *mut _asyncmsg_connection_descriptor, //) -> ::c_int; pub fn ConnectDetach(__coid: ::c_int) -> ::c_int; pub fn ConnectDetach_r(__coid: ::c_int) -> ::c_int; pub fn ConnectServerInfo(__pid: ::pid_t, __coid: ::c_int, __info: *mut _msg_info64) -> ::c_int; pub fn ConnectServerInfo_r( __pid: ::pid_t, __coid: ::c_int, __info: *mut _msg_info64, ) -> ::c_int; pub fn ConnectClientInfoExtraArgs( __scoid: ::c_int, __info_pp: *mut _client_info, __ngroups: ::c_int, __abilities: *mut _client_able, __nable: ::c_int, __type_id: *mut ::c_uint, ) -> ::c_int; pub fn ConnectClientInfoExtraArgs_r( __scoid: ::c_int, __info_pp: *mut _client_info, __ngroups: ::c_int, __abilities: *mut _client_able, __nable: ::c_int, __type_id: *mut ::c_uint, ) -> ::c_int; pub fn ConnectClientInfo( __scoid: ::c_int, __info: *mut _client_info, __ngroups: ::c_int, ) -> ::c_int; pub fn ConnectClientInfo_r( __scoid: ::c_int, __info: *mut _client_info, __ngroups: ::c_int, ) -> ::c_int; pub fn ConnectClientInfoExt( __scoid: ::c_int, __info_pp: *mut *mut _client_info, flags: ::c_int, ) -> ::c_int; pub fn ClientInfoExtFree(__info_pp: *mut *mut _client_info) -> ::c_int; pub fn ConnectClientInfoAble( __scoid: ::c_int, __info_pp: *mut *mut _client_info, flags: ::c_int, abilities: *mut _client_able, nable: ::c_int, ) -> ::c_int; pub fn ConnectFlags( __pid: ::pid_t, __coid: ::c_int, __mask: ::c_uint, __bits: ::c_uint, ) -> ::c_int; pub fn ConnectFlags_r( __pid: ::pid_t, __coid: ::c_int, __mask: ::c_uint, __bits: ::c_uint, ) -> ::c_int; pub fn ChannelConnectAttr( __id: ::c_uint, __old_attr: *mut _channel_connect_attr, __new_attr: *mut _channel_connect_attr, __flags: ::c_uint, ) -> ::c_int; pub fn MsgSend( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSend_r( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSendnc( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSendnc_r( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSendsv( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgSendsv_r( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgSendsvnc( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgSendsvnc_r( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgSendvs( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSendvs_r( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSendvsnc( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSendvsnc_r( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __rmsg: *mut ::c_void, __rbytes: usize, ) -> ::c_long; pub fn MsgSendv( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgSendv_r( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgSendvnc( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgSendvnc_r( __coid: ::c_int, __siov: *const ::iovec, __sparts: usize, __riov: *const ::iovec, __rparts: usize, ) -> ::c_long; pub fn MsgReceive( __chid: ::c_int, __msg: *mut ::c_void, __bytes: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReceive_r( __chid: ::c_int, __msg: *mut ::c_void, __bytes: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReceivev( __chid: ::c_int, __iov: *const ::iovec, __parts: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReceivev_r( __chid: ::c_int, __iov: *const ::iovec, __parts: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReceivePulse( __chid: ::c_int, __pulse: *mut ::c_void, __bytes: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReceivePulse_r( __chid: ::c_int, __pulse: *mut ::c_void, __bytes: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReceivePulsev( __chid: ::c_int, __iov: *const ::iovec, __parts: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReceivePulsev_r( __chid: ::c_int, __iov: *const ::iovec, __parts: usize, __info: *mut _msg_info64, ) -> ::c_int; pub fn MsgReply( __rcvid: ::c_int, __status: ::c_long, __msg: *const ::c_void, __bytes: usize, ) -> ::c_int; pub fn MsgReply_r( __rcvid: ::c_int, __status: ::c_long, __msg: *const ::c_void, __bytes: usize, ) -> ::c_int; pub fn MsgReplyv( __rcvid: ::c_int, __status: ::c_long, __iov: *const ::iovec, __parts: usize, ) -> ::c_int; pub fn MsgReplyv_r( __rcvid: ::c_int, __status: ::c_long, __iov: *const ::iovec, __parts: usize, ) -> ::c_int; pub fn MsgReadiov( __rcvid: ::c_int, __iov: *const ::iovec, __parts: usize, __offset: usize, __flags: ::c_int, ) -> isize; pub fn MsgReadiov_r( __rcvid: ::c_int, __iov: *const ::iovec, __parts: usize, __offset: usize, __flags: ::c_int, ) -> isize; pub fn MsgRead( __rcvid: ::c_int, __msg: *mut ::c_void, __bytes: usize, __offset: usize, ) -> isize; pub fn MsgRead_r( __rcvid: ::c_int, __msg: *mut ::c_void, __bytes: usize, __offset: usize, ) -> isize; pub fn MsgReadv( __rcvid: ::c_int, __iov: *const ::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgReadv_r( __rcvid: ::c_int, __iov: *const ::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgWrite( __rcvid: ::c_int, __msg: *const ::c_void, __bytes: usize, __offset: usize, ) -> isize; pub fn MsgWrite_r( __rcvid: ::c_int, __msg: *const ::c_void, __bytes: usize, __offset: usize, ) -> isize; pub fn MsgWritev( __rcvid: ::c_int, __iov: *const ::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgWritev_r( __rcvid: ::c_int, __iov: *const ::iovec, __parts: usize, __offset: usize, ) -> isize; pub fn MsgSendPulse( __coid: ::c_int, __priority: ::c_int, __code: ::c_int, __value: ::c_int, ) -> ::c_int; pub fn MsgSendPulse_r( __coid: ::c_int, __priority: ::c_int, __code: ::c_int, __value: ::c_int, ) -> ::c_int; pub fn MsgSendPulsePtr( __coid: ::c_int, __priority: ::c_int, __code: ::c_int, __value: *mut ::c_void, ) -> ::c_int; pub fn MsgSendPulsePtr_r( __coid: ::c_int, __priority: ::c_int, __code: ::c_int, __value: *mut ::c_void, ) -> ::c_int; pub fn MsgDeliverEvent(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int; pub fn MsgDeliverEvent_r(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int; pub fn MsgVerifyEvent(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int; pub fn MsgVerifyEvent_r(__rcvid: ::c_int, __event: *const ::sigevent) -> ::c_int; pub fn MsgRegisterEvent(__event: *mut ::sigevent, __coid: ::c_int) -> ::c_int; pub fn MsgRegisterEvent_r(__event: *mut ::sigevent, __coid: ::c_int) -> ::c_int; pub fn MsgUnregisterEvent(__event: *const ::sigevent) -> ::c_int; pub fn MsgUnregisterEvent_r(__event: *const ::sigevent) -> ::c_int; pub fn MsgInfo(__rcvid: ::c_int, __info: *mut _msg_info64) -> ::c_int; pub fn MsgInfo_r(__rcvid: ::c_int, __info: *mut _msg_info64) -> ::c_int; pub fn MsgKeyData( __rcvid: ::c_int, __oper: ::c_int, __key: u32, __newkey: *mut u32, __iov: *const ::iovec, __parts: ::c_int, ) -> ::c_int; pub fn MsgKeyData_r( __rcvid: ::c_int, __oper: ::c_int, __key: u32, __newkey: *mut u32, __iov: *const ::iovec, __parts: ::c_int, ) -> ::c_int; pub fn MsgError(__rcvid: ::c_int, __err: ::c_int) -> ::c_int; pub fn MsgError_r(__rcvid: ::c_int, __err: ::c_int) -> ::c_int; pub fn MsgCurrent(__rcvid: ::c_int) -> ::c_int; pub fn MsgCurrent_r(__rcvid: ::c_int) -> ::c_int; pub fn MsgSendAsyncGbl( __coid: ::c_int, __smsg: *const ::c_void, __sbytes: usize, __msg_prio: ::c_uint, ) -> ::c_int; pub fn MsgSendAsync(__coid: ::c_int) -> ::c_int; pub fn MsgReceiveAsyncGbl( __chid: ::c_int, __rmsg: *mut ::c_void, __rbytes: usize, __info: *mut _msg_info64, __coid: ::c_int, ) -> ::c_int; pub fn MsgReceiveAsync(__chid: ::c_int, __iov: *const ::iovec, __parts: ::c_uint) -> ::c_int; pub fn MsgPause(__rcvid: ::c_int, __cookie: ::c_uint) -> ::c_int; pub fn MsgPause_r(__rcvid: ::c_int, __cookie: ::c_uint) -> ::c_int; pub fn SignalKill( __nd: u32, __pid: ::pid_t, __tid: ::c_int, __signo: ::c_int, __code: ::c_int, __value: ::c_int, ) -> ::c_int; pub fn SignalKill_r( __nd: u32, __pid: ::pid_t, __tid: ::c_int, __signo: ::c_int, __code: ::c_int, __value: ::c_int, ) -> ::c_int; pub fn SignalKillSigval( __nd: u32, __pid: ::pid_t, __tid: ::c_int, __signo: ::c_int, __code: ::c_int, __value: *const ::sigval, ) -> ::c_int; pub fn SignalKillSigval_r( __nd: u32, __pid: ::pid_t, __tid: ::c_int, __signo: ::c_int, __code: ::c_int, __value: *const ::sigval, ) -> ::c_int; pub fn SignalReturn(__info: *mut _sighandler_info) -> ::c_int; pub fn SignalFault(__sigcode: ::c_uint, __regs: *mut ::c_void, __refaddr: usize) -> ::c_int; pub fn SignalAction( __pid: ::pid_t, __sigstub: unsafe extern "C" fn(), __signo: ::c_int, __act: *const ::sigaction, __oact: *mut ::sigaction, ) -> ::c_int; pub fn SignalAction_r( __pid: ::pid_t, __sigstub: unsafe extern "C" fn(), __signo: ::c_int, __act: *const ::sigaction, __oact: *mut ::sigaction, ) -> ::c_int; pub fn SignalProcmask( __pid: ::pid_t, __tid: ::c_int, __how: ::c_int, __set: *const ::sigset_t, __oldset: *mut ::sigset_t, ) -> ::c_int; pub fn SignalProcmask_r( __pid: ::pid_t, __tid: ::c_int, __how: ::c_int, __set: *const ::sigset_t, __oldset: *mut ::sigset_t, ) -> ::c_int; pub fn SignalSuspend(__set: *const ::sigset_t) -> ::c_int; pub fn SignalSuspend_r(__set: *const ::sigset_t) -> ::c_int; pub fn SignalWaitinfo(__set: *const ::sigset_t, __info: *mut ::siginfo_t) -> ::c_int; pub fn SignalWaitinfo_r(__set: *const ::sigset_t, __info: *mut ::siginfo_t) -> ::c_int; pub fn SignalWaitinfoMask( __set: *const ::sigset_t, __info: *mut ::siginfo_t, __mask: *const ::sigset_t, ) -> ::c_int; pub fn SignalWaitinfoMask_r( __set: *const ::sigset_t, __info: *mut ::siginfo_t, __mask: *const ::sigset_t, ) -> ::c_int; pub fn ThreadCreate( __pid: ::pid_t, __func: unsafe extern "C" fn(__arg: *mut ::c_void) -> *mut ::c_void, __arg: *mut ::c_void, __attr: *const ::_thread_attr, ) -> ::c_int; pub fn ThreadCreate_r( __pid: ::pid_t, __func: unsafe extern "C" fn(__arg: *mut ::c_void) -> *mut ::c_void, __arg: *mut ::c_void, __attr: *const ::_thread_attr, ) -> ::c_int; pub fn ThreadDestroy(__tid: ::c_int, __priority: ::c_int, __status: *mut ::c_void) -> ::c_int; pub fn ThreadDestroy_r(__tid: ::c_int, __priority: ::c_int, __status: *mut ::c_void) -> ::c_int; pub fn ThreadDetach(__tid: ::c_int) -> ::c_int; pub fn ThreadDetach_r(__tid: ::c_int) -> ::c_int; pub fn ThreadJoin(__tid: ::c_int, __status: *mut *mut ::c_void) -> ::c_int; pub fn ThreadJoin_r(__tid: ::c_int, __status: *mut *mut ::c_void) -> ::c_int; pub fn ThreadCancel(__tid: ::c_int, __canstub: unsafe extern "C" fn()) -> ::c_int; pub fn ThreadCancel_r(__tid: ::c_int, __canstub: unsafe extern "C" fn()) -> ::c_int; pub fn ThreadCtl(__cmd: ::c_int, __data: *mut ::c_void) -> ::c_int; pub fn ThreadCtl_r(__cmd: ::c_int, __data: *mut ::c_void) -> ::c_int; pub fn ThreadCtlExt( __pid: ::pid_t, __tid: ::c_int, __cmd: ::c_int, __data: *mut ::c_void, ) -> ::c_int; pub fn ThreadCtlExt_r( __pid: ::pid_t, __tid: ::c_int, __cmd: ::c_int, __data: *mut ::c_void, ) -> ::c_int; pub fn InterruptHookTrace( __handler: ::Option *const ::sigevent>, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptHookIdle( __handler: ::Option, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptHookIdle2( __handler: ::Option< unsafe extern "C" fn(arg1: ::c_uint, arg2: *mut syspage_entry, arg3: *mut _idle_hook), >, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptHookOverdriveEvent(__event: *const ::sigevent, __flags: ::c_uint) -> ::c_int; pub fn InterruptAttachEvent( __intr: ::c_int, __event: *const ::sigevent, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptAttachEvent_r( __intr: ::c_int, __event: *const ::sigevent, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptAttach( __intr: ::c_int, __handler: ::Option< unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const ::sigevent, >, __area: *const ::c_void, __size: ::c_int, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptAttach_r( __intr: ::c_int, __handler: ::Option< unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const ::sigevent, >, __area: *const ::c_void, __size: ::c_int, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptAttachArray( __intr: ::c_int, __handler: ::Option< unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const *const ::sigevent, >, __area: *const ::c_void, __size: ::c_int, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptAttachArray_r( __intr: ::c_int, __handler: ::Option< unsafe extern "C" fn(__area: *mut ::c_void, __id: ::c_int) -> *const *const ::sigevent, >, __area: *const ::c_void, __size: ::c_int, __flags: ::c_uint, ) -> ::c_int; pub fn InterruptDetach(__id: ::c_int) -> ::c_int; pub fn InterruptDetach_r(__id: ::c_int) -> ::c_int; pub fn InterruptWait(__flags: ::c_int, __timeout: *const u64) -> ::c_int; pub fn InterruptWait_r(__flags: ::c_int, __timeout: *const u64) -> ::c_int; pub fn InterruptCharacteristic( __type: ::c_int, __id: ::c_int, __new: *mut ::c_uint, __old: *mut ::c_uint, ) -> ::c_int; pub fn InterruptCharacteristic_r( __type: ::c_int, __id: ::c_int, __new: *mut ::c_uint, __old: *mut ::c_uint, ) -> ::c_int; pub fn SchedGet(__pid: ::pid_t, __tid: ::c_int, __param: *mut ::sched_param) -> ::c_int; pub fn SchedGet_r(__pid: ::pid_t, __tid: ::c_int, __param: *mut ::sched_param) -> ::c_int; pub fn SchedGetCpuNum() -> ::c_uint; pub fn SchedSet( __pid: ::pid_t, __tid: ::c_int, __algorithm: ::c_int, __param: *const ::sched_param, ) -> ::c_int; pub fn SchedSet_r( __pid: ::pid_t, __tid: ::c_int, __algorithm: ::c_int, __param: *const ::sched_param, ) -> ::c_int; pub fn SchedInfo(__pid: ::pid_t, __algorithm: ::c_int, __info: *mut ::_sched_info) -> ::c_int; pub fn SchedInfo_r(__pid: ::pid_t, __algorithm: ::c_int, __info: *mut ::_sched_info) -> ::c_int; pub fn SchedYield() -> ::c_int; pub fn SchedYield_r() -> ::c_int; pub fn SchedCtl(__cmd: ::c_int, __data: *mut ::c_void, __length: usize) -> ::c_int; pub fn SchedCtl_r(__cmd: ::c_int, __data: *mut ::c_void, __length: usize) -> ::c_int; pub fn SchedJobCreate(__job: *mut nto_job_t) -> ::c_int; pub fn SchedJobCreate_r(__job: *mut nto_job_t) -> ::c_int; pub fn SchedJobDestroy(__job: *mut nto_job_t) -> ::c_int; pub fn SchedJobDestroy_r(__job: *mut nto_job_t) -> ::c_int; pub fn SchedWaypoint( __job: *mut nto_job_t, __new: *const i64, __max: *const i64, __old: *mut i64, ) -> ::c_int; pub fn SchedWaypoint_r( __job: *mut nto_job_t, __new: *const i64, __max: *const i64, __old: *mut i64, ) -> ::c_int; pub fn TimerCreate(__id: ::clockid_t, __notify: *const ::sigevent) -> ::c_int; pub fn TimerCreate_r(__id: ::clockid_t, __notify: *const ::sigevent) -> ::c_int; pub fn TimerDestroy(__id: ::timer_t) -> ::c_int; pub fn TimerDestroy_r(__id: ::timer_t) -> ::c_int; pub fn TimerSettime( __id: ::timer_t, __flags: ::c_int, __itime: *const ::_itimer, __oitime: *mut ::_itimer, ) -> ::c_int; pub fn TimerSettime_r( __id: ::timer_t, __flags: ::c_int, __itime: *const ::_itimer, __oitime: *mut ::_itimer, ) -> ::c_int; pub fn TimerInfo( __pid: ::pid_t, __id: ::timer_t, __flags: ::c_int, __info: *mut ::_timer_info, ) -> ::c_int; pub fn TimerInfo_r( __pid: ::pid_t, __id: ::timer_t, __flags: ::c_int, __info: *mut ::_timer_info, ) -> ::c_int; pub fn TimerAlarm( __id: ::clockid_t, __itime: *const ::_itimer, __otime: *mut ::_itimer, ) -> ::c_int; pub fn TimerAlarm_r( __id: ::clockid_t, __itime: *const ::_itimer, __otime: *mut ::_itimer, ) -> ::c_int; pub fn TimerTimeout( __id: ::clockid_t, __flags: ::c_int, __notify: *const ::sigevent, __ntime: *const u64, __otime: *mut u64, ) -> ::c_int; pub fn TimerTimeout_r( __id: ::clockid_t, __flags: ::c_int, __notify: *const ::sigevent, __ntime: *const u64, __otime: *mut u64, ) -> ::c_int; pub fn SyncTypeCreate( __type: ::c_uint, __sync: *mut ::sync_t, __attr: *const ::_sync_attr, ) -> ::c_int; pub fn SyncTypeCreate_r( __type: ::c_uint, __sync: *mut ::sync_t, __attr: *const ::_sync_attr, ) -> ::c_int; pub fn SyncDestroy(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncDestroy_r(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncCtl(__cmd: ::c_int, __sync: *mut ::sync_t, __data: *mut ::c_void) -> ::c_int; pub fn SyncCtl_r(__cmd: ::c_int, __sync: *mut ::sync_t, __data: *mut ::c_void) -> ::c_int; pub fn SyncMutexEvent(__sync: *mut ::sync_t, event: *const ::sigevent) -> ::c_int; pub fn SyncMutexEvent_r(__sync: *mut ::sync_t, event: *const ::sigevent) -> ::c_int; pub fn SyncMutexLock(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncMutexLock_r(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncMutexUnlock(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncMutexUnlock_r(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncMutexRevive(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncMutexRevive_r(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncCondvarWait(__sync: *mut ::sync_t, __mutex: *mut ::sync_t) -> ::c_int; pub fn SyncCondvarWait_r(__sync: *mut ::sync_t, __mutex: *mut ::sync_t) -> ::c_int; pub fn SyncCondvarSignal(__sync: *mut ::sync_t, __all: ::c_int) -> ::c_int; pub fn SyncCondvarSignal_r(__sync: *mut ::sync_t, __all: ::c_int) -> ::c_int; pub fn SyncSemPost(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncSemPost_r(__sync: *mut ::sync_t) -> ::c_int; pub fn SyncSemWait(__sync: *mut ::sync_t, __tryto: ::c_int) -> ::c_int; pub fn SyncSemWait_r(__sync: *mut ::sync_t, __tryto: ::c_int) -> ::c_int; pub fn ClockTime(__id: ::clockid_t, _new: *const u64, __old: *mut u64) -> ::c_int; pub fn ClockTime_r(__id: ::clockid_t, _new: *const u64, __old: *mut u64) -> ::c_int; pub fn ClockAdjust( __id: ::clockid_t, _new: *const ::_clockadjust, __old: *mut ::_clockadjust, ) -> ::c_int; pub fn ClockAdjust_r( __id: ::clockid_t, _new: *const ::_clockadjust, __old: *mut ::_clockadjust, ) -> ::c_int; pub fn ClockPeriod( __id: ::clockid_t, _new: *const ::_clockperiod, __old: *mut ::_clockperiod, __reserved: ::c_int, ) -> ::c_int; pub fn ClockPeriod_r( __id: ::clockid_t, _new: *const ::_clockperiod, __old: *mut ::_clockperiod, __reserved: ::c_int, ) -> ::c_int; pub fn ClockId(__pid: ::pid_t, __tid: ::c_int) -> ::c_int; pub fn ClockId_r(__pid: ::pid_t, __tid: ::c_int) -> ::c_int; // //TODO: The following commented out functions are implemented in assembly. // We can implmement them either via a C stub or rust's inline assembly. // //pub fn InterruptEnable(); //pub fn InterruptDisable(); pub fn InterruptMask(__intr: ::c_int, __id: ::c_int) -> ::c_int; pub fn InterruptUnmask(__intr: ::c_int, __id: ::c_int) -> ::c_int; //pub fn InterruptLock(__spin: *mut ::intrspin); //pub fn InterruptUnlock(__spin: *mut ::intrspin); //pub fn InterruptStatus() -> ::c_uint; } libc/src/unix/nto/x86_64.rs0000644000175000017500000000662714661133735016343 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = u32; pub type c_long = i64; pub type c_ulong = u64; pub type time_t = i64; s! { #[repr(align(8))] pub struct x86_64_cpu_registers { pub rdi: u64, pub rsi: u64, pub rdx: u64, pub r10: u64, pub r8: u64, pub r9: u64, pub rax: u64, pub rbx: u64, pub rbp: u64, pub rcx: u64, pub r11: u64, pub r12: u64, pub r13: u64, pub r14: u64, pub r15: u64, pub rip: u64, pub cs: u32, rsvd1: u32, pub rflags: u64, pub rsp: u64, pub ss: u32, rsvd2: u32, } #[repr(align(8))] pub struct mcontext_t { pub cpu: x86_64_cpu_registers, #[cfg(libc_union)] pub fpu: x86_64_fpu_registers, #[cfg(not(libc_union))] __reserved: [u8; 1024], } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct fsave_area_64 { pub fpu_control_word: u32, pub fpu_status_word: u32, pub fpu_tag_word: u32, pub fpu_ip: u32, pub fpu_cs: u32, pub fpu_op: u32, pub fpu_ds: u32, pub st_regs: [u8; 80], } pub struct fxsave_area_64 { pub fpu_control_word: u16, pub fpu_status_word: u16, pub fpu_tag_word: u16, pub fpu_operand: u16, pub fpu_rip: u64, pub fpu_rdp: u64, pub mxcsr: u32, pub mxcsr_mask: u32, pub st_regs: [u8; 128], pub xmm_regs: [u8; 128], reserved2: [u8; 224], } pub struct fpu_extention_savearea_64 { pub other: [u8; 512], pub xstate_bv: u64, pub xstate_undef: [u64; 7], pub xstate_info: [u8; 224], } } s_no_extra_traits! { #[cfg(libc_union)] pub union x86_64_fpu_registers { pub fsave_area: fsave_area_64, pub fxsave_area: fxsave_area_64, pub xsave_area: fpu_extention_savearea_64, pub data: [u8; 1024], } } cfg_if! { if #[cfg(feature = "extra_traits")] { #[cfg(libc_union)] impl Eq for x86_64_fpu_registers {} #[cfg(libc_union)] impl PartialEq for x86_64_fpu_registers { fn eq(&self, other: &x86_64_fpu_registers) -> bool { unsafe { self.fsave_area == other.fsave_area || self.fxsave_area == other.fxsave_area || self.xsave_area == other.xsave_area } } } #[cfg(libc_union)] impl ::fmt::Debug for x86_64_fpu_registers { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("x86_64_fpu_registers") .field("fsave_area", &self.fsave_area) .field("fxsave_area", &self.fxsave_area) .field("xsave_area", &self.xsave_area) .finish() } } } #[cfg(libc_union)] impl ::hash::Hash for x86_64_fpu_registers { fn hash(&self, state: &mut H) { unsafe { self.fsave_area.hash(state); self.fxsave_area.hash(state); self.xsave_area.hash(state); } } } } } libc/src/unix/nto/mod.rs0000644000175000017500000034455514661133735016171 0ustar jamespagejamespagepub type clock_t = u32; pub type sa_family_t = u8; pub type speed_t = ::c_uint; pub type tcflag_t = ::c_uint; pub type clockid_t = ::c_int; pub type timer_t = ::c_int; pub type key_t = ::c_uint; pub type id_t = ::c_int; pub type useconds_t = u32; pub type dev_t = u32; pub type socklen_t = u32; pub type mode_t = u32; pub type rlim64_t = u64; pub type mqd_t = ::c_int; pub type nfds_t = ::c_uint; pub type idtype_t = ::c_uint; pub type errno_t = ::c_int; pub type rsize_t = c_ulong; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf32_Lword = u64; pub type Elf32_Sword = i32; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type Elf64_Sxword = i64; pub type Elf64_Lword = u64; pub type Elf64_Sword = i32; pub type Elf32_Section = u16; pub type Elf64_Section = u16; pub type _Time32t = u32; pub type pthread_t = ::c_int; pub type regoff_t = ::ssize_t; pub type nlink_t = u32; pub type blksize_t = u32; pub type suseconds_t = i32; pub type ino_t = u64; pub type off_t = i64; pub type blkcnt_t = u64; pub type msgqnum_t = u64; pub type msglen_t = u64; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type rlim_t = u64; pub type posix_spawn_file_actions_t = *mut ::c_void; pub type posix_spawnattr_t = ::uintptr_t; pub type pthread_mutex_t = ::sync_t; pub type pthread_mutexattr_t = ::_sync_attr; pub type pthread_cond_t = ::sync_t; pub type pthread_condattr_t = ::_sync_attr; pub type pthread_rwlockattr_t = ::_sync_attr; pub type pthread_key_t = ::c_int; pub type pthread_spinlock_t = sync_t; pub type pthread_barrierattr_t = _sync_attr; pub type sem_t = sync_t; pub type nl_item = ::c_int; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } s! { pub struct dirent_extra { pub d_datalen: u16, pub d_type: u16, pub d_reserved: u32, } pub struct stat { pub st_ino: ::ino_t, pub st_size: ::off_t, pub st_dev: ::dev_t, pub st_rdev: ::dev_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub __old_st_mtime: ::_Time32t, pub __old_st_atime: ::_Time32t, pub __old_st_ctime: ::_Time32t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_blocksize: ::blksize_t, pub st_nblocks: i32, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_mtim: ::timespec, pub st_atim: ::timespec, pub st_ctim: ::timespec, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } #[repr(packed)] pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [i8; 8], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } // The order of the `ai_addr` field in this struct is crucial // for converting between the Rust and C types. pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut addrinfo, } pub struct fd_set { fds_bits: [::c_uint; 2 * FD_SETSIZE / ULONG_SIZE], } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, pub tm_gmtoff: ::c_long, pub tm_zone: *const ::c_char, } #[repr(align(8))] pub struct sched_param { pub sched_priority: ::c_int, pub sched_curpriority: ::c_int, pub reserved: [::c_int; 10], } #[repr(align(8))] pub struct __sched_param { pub __sched_priority: ::c_int, pub __sched_curpriority: ::c_int, pub reserved: [::c_int; 10], } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct lconv { pub currency_symbol: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub negative_sign: *mut ::c_char, pub positive_sign: *mut ::c_char, pub frac_digits: ::c_char, pub int_frac_digits: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub n_sign_posn: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub decimal_point: *mut ::c_char, pub grouping: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub _Frac_grouping: *mut ::c_char, pub _Frac_sep: *mut ::c_char, pub _False: *mut ::c_char, pub _True: *mut ::c_char, pub _No: *mut ::c_char, pub _Yes: *mut ::c_char, pub _Nostr: *mut ::c_char, pub _Yesstr: *mut ::c_char, pub _Reserved: [*mut ::c_char; 8], } pub struct in_pktinfo { pub ipi_addr: ::in_addr, pub ipi_ifindex: ::c_uint, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: ::c_uint, pub ifa_addr: *mut ::sockaddr, pub ifa_netmask: *mut ::sockaddr, pub ifa_dstaddr: *mut ::sockaddr, pub ifa_data: *mut ::c_void } pub struct arpreq { pub arp_pa: ::sockaddr, pub arp_ha: ::sockaddr, pub arp_flags: ::c_int, } #[repr(packed)] pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct mmsghdr { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } #[repr(align(8))] pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, __data: [u8; 36], // union } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_flags: ::c_int, pub sa_mask: ::sigset_t, } pub struct _sync { _union: ::c_uint, __owner: ::c_uint, } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_matchc: ::c_int, pub gl_pathv: *mut *mut c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, pub gl_errfunc: extern "C" fn(*const ::c_char, ::c_int) -> ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_age: *mut ::c_char, pub pw_comment: *mut ::c_char, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct Elf32_Ehdr { pub e_ident: [::c_uchar; 16], pub e_type: Elf32_Half, pub e_machine: Elf32_Half, pub e_version: Elf32_Word, pub e_entry: Elf32_Addr, pub e_phoff: Elf32_Off, pub e_shoff: Elf32_Off, pub e_flags: Elf32_Word, pub e_ehsize: Elf32_Half, pub e_phentsize: Elf32_Half, pub e_phnum: Elf32_Half, pub e_shentsize: Elf32_Half, pub e_shnum: Elf32_Half, pub e_shstrndx: Elf32_Half, } pub struct Elf64_Ehdr { pub e_ident: [::c_uchar; 16], pub e_type: Elf64_Half, pub e_machine: Elf64_Half, pub e_version: Elf64_Word, pub e_entry: Elf64_Addr, pub e_phoff: Elf64_Off, pub e_shoff: Elf64_Off, pub e_flags: Elf64_Word, pub e_ehsize: Elf64_Half, pub e_phentsize: Elf64_Half, pub e_phnum: Elf64_Half, pub e_shentsize: Elf64_Half, pub e_shnum: Elf64_Half, pub e_shstrndx: Elf64_Half, } pub struct Elf32_Sym { pub st_name: Elf32_Word, pub st_value: Elf32_Addr, pub st_size: Elf32_Word, pub st_info: ::c_uchar, pub st_other: ::c_uchar, pub st_shndx: Elf32_Section, } pub struct Elf64_Sym { pub st_name: Elf64_Word, pub st_info: ::c_uchar, pub st_other: ::c_uchar, pub st_shndx: Elf64_Section, pub st_value: Elf64_Addr, pub st_size: Elf64_Xword, } pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct Elf32_Shdr { pub sh_name: Elf32_Word, pub sh_type: Elf32_Word, pub sh_flags: Elf32_Word, pub sh_addr: Elf32_Addr, pub sh_offset: Elf32_Off, pub sh_size: Elf32_Word, pub sh_link: Elf32_Word, pub sh_info: Elf32_Word, pub sh_addralign: Elf32_Word, pub sh_entsize: Elf32_Word, } pub struct Elf64_Shdr { pub sh_name: Elf64_Word, pub sh_type: Elf64_Word, pub sh_flags: Elf64_Xword, pub sh_addr: Elf64_Addr, pub sh_offset: Elf64_Off, pub sh_size: Elf64_Xword, pub sh_link: Elf64_Word, pub sh_info: Elf64_Word, pub sh_addralign: Elf64_Xword, pub sh_entsize: Elf64_Xword, } pub struct in6_pktinfo { pub ipi6_addr: ::in6_addr, pub ipi6_ifindex: ::c_uint, } pub struct inotify_event { pub wd: ::c_int, pub mask: u32, pub cookie: u32, pub len: u32 } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_cc: [::cc_t; ::NCCS], __reserved: [::c_uint; 3], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } pub struct mallinfo { pub arena: ::c_int, pub ordblks: ::c_int, pub smblks: ::c_int, pub hblks: ::c_int, pub hblkhd: ::c_int, pub usmblks: ::c_int, pub fsmblks: ::c_int, pub uordblks: ::c_int, pub fordblks: ::c_int, pub keepcost: ::c_int, } pub struct flock { pub l_type: i16, pub l_whence: i16, pub l_zero1: i32, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, pub l_sysid: u32, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_basetype: [::c_char; 16], pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, f_filler: [::c_uint; 21], } pub struct aiocb { pub aio_fildes: ::c_int, pub aio_reqprio: ::c_int, pub aio_offset: off_t, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_sigevent: ::sigevent, pub aio_lio_opcode: ::c_int, pub _aio_lio_state: *mut ::c_void, _aio_pad: [::c_int; 3], pub _aio_next: *mut ::aiocb, pub _aio_flag: ::c_uint, pub _aio_iotype: ::c_uint, pub _aio_result: ::ssize_t, pub _aio_error: ::c_uint, pub _aio_suspend: *mut ::c_void, pub _aio_plist: *mut ::c_void, pub _aio_policy: ::c_int, pub _aio_param: ::__sched_param, } pub struct pthread_attr_t { __data1: ::c_long, __data2: [u8; 96] } pub struct ipc_perm { pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub seq: ::c_uint, pub key: ::key_t, _reserved: [::c_int; 4], } pub struct regex_t { re_magic: ::c_int, re_nsub: ::size_t, re_endp: *const ::c_char, re_g: *mut ::c_void, } pub struct _thread_attr { pub __flags: ::c_int, pub __stacksize: ::size_t, pub __stackaddr: *mut ::c_void, pub __exitfunc: ::Option, pub __policy: ::c_int, pub __param: ::__sched_param, pub __guardsize: ::c_uint, pub __prealloc: ::c_uint, __spare: [::c_int; 2], } pub struct _sync_attr { pub __protocol: ::c_int, pub __flags: ::c_int, pub __prioceiling: ::c_int, pub __clockid: ::c_int, pub __count: ::c_int, __reserved: [::c_int; 3], } pub struct sockcred { pub sc_uid: ::uid_t, pub sc_euid: ::uid_t, pub sc_gid: ::gid_t, pub sc_egid: ::gid_t, pub sc_ngroups: ::c_int, pub sc_groups: [::gid_t; 1], } pub struct bpf_program { pub bf_len: ::c_uint, pub bf_insns: *mut ::bpf_insn, } pub struct bpf_stat { pub bs_recv: u64, pub bs_drop: u64, pub bs_capt: u64, bs_padding: [u64; 13], } pub struct bpf_version { pub bv_major: ::c_ushort, pub bv_minor: ::c_ushort, } pub struct bpf_hdr { pub bh_tstamp: ::timeval, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: u16, } pub struct bpf_insn { pub code: u16, pub jt: ::c_uchar, pub jf: ::c_uchar, pub k: u32, } pub struct bpf_dltlist { pub bfl_len: ::c_uint, pub bfl_list: *mut ::c_uint, } pub struct unpcbid { pub unp_pid: ::pid_t, pub unp_euid: ::uid_t, pub unp_egid: ::gid_t, } pub struct dl_phdr_info { pub dlpi_addr: ::Elf64_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const ::Elf64_Phdr, pub dlpi_phnum: ::Elf64_Half, } #[repr(align(8))] pub struct ucontext_t { pub uc_link: *mut ucontext_t, pub uc_sigmask: ::sigset_t, pub uc_stack: stack_t, pub uc_mcontext: mcontext_t, } } s_no_extra_traits! { pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [::c_char; 104] } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, __ss_pad1: [::c_char; 6], __ss_align: i64, __ss_pad2: [::c_char; 112], } pub struct utsname { pub sysname: [::c_char; _SYSNAME_SIZE], pub nodename: [::c_char; _SYSNAME_SIZE], pub release: [::c_char; _SYSNAME_SIZE], pub version: [::c_char; _SYSNAME_SIZE], pub machine: [::c_char; _SYSNAME_SIZE], } pub struct sigevent { pub sigev_notify: ::c_int, pub __padding1: ::c_int, pub sigev_signo: ::c_int, // union pub __padding2: ::c_int, pub sigev_value: ::sigval, __sigev_un2: usize, // union } pub struct dirent { pub d_ino: ::ino_t, pub d_offset: ::off_t, pub d_reclen: ::c_short, pub d_namelen: ::c_short, pub d_name: [::c_char; 1], // flex array } pub struct sigset_t { __val: [u32; 2], } pub struct mq_attr { pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_flags: ::c_long, pub mq_curmsgs: ::c_long, pub mq_sendwait: ::c_long, pub mq_recvwait: ::c_long, } pub struct msg { pub msg_next: *mut ::msg, pub msg_type: ::c_long, pub msg_ts: ::c_ushort, pub msg_spot: ::c_short, _pad: [u8; 4], } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_first: *mut ::msg, pub msg_last: *mut ::msg, pub msg_cbytes: ::msglen_t, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, pub msg_stime: ::time_t, msg_pad1: ::c_long, pub msg_rtime: ::time_t, msg_pad2: ::c_long, pub msg_ctime: ::time_t, msg_pad3: ::c_long, msg_pad4: [::c_long; 4], } pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::sa_family_t, pub sdl_index: u16, pub sdl_type: ::c_uchar, pub sdl_nlen: ::c_uchar, pub sdl_alen: ::c_uchar, pub sdl_slen: ::c_uchar, pub sdl_data: [::c_char; 12], } pub struct sync_t { __u: ::c_uint, // union pub __owner: ::c_uint, } #[repr(align(4))] pub struct pthread_barrier_t { // union __pad: [u8; 28], // union } pub struct pthread_rwlock_t { pub __active: ::c_int, pub __blockedwriters: ::c_int, pub __blockedreaders: ::c_int, pub __heavy: ::c_int, pub __lock: ::pthread_mutex_t, // union pub __rcond: ::pthread_cond_t, // union pub __wcond: ::pthread_cond_t, // union pub __owner: ::c_uint, pub __spare: ::c_uint, } } cfg_if! { if #[cfg(feature = "extra_traits")] { // sigevent impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.__sigev_un2 == other.__sigev_un2 } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("__sigev_un2", &self.__sigev_un2) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.__sigev_un2.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_len == other.sun_len && self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_un {} impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl ::hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_len.hash(state); self.sun_family.hash(state); self.sun_path.hash(state); } } // sigset_t impl PartialEq for sigset_t { fn eq(&self, other: &sigset_t) -> bool { self.__val == other.__val } } impl Eq for sigset_t {} impl ::fmt::Debug for sigset_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigset_t") .field("__val", &self.__val) .finish() } } impl ::hash::Hash for sigset_t { fn hash(&self, state: &mut H) { self.__val.hash(state); } } // msg impl ::fmt::Debug for msg { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("msg") .field("msg_next", &self.msg_next) .field("msg_type", &self.msg_type) .field("msg_ts", &self.msg_ts) .field("msg_spot", &self.msg_spot) .finish() } } // msqid_ds impl ::fmt::Debug for msqid_ds { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("msqid_ds") .field("msg_perm", &self.msg_perm) .field("msg_first", &self.msg_first) .field("msg_cbytes", &self.msg_cbytes) .field("msg_qnum", &self.msg_qnum) .field("msg_qbytes", &self.msg_qbytes) .field("msg_lspid", &self.msg_lspid) .field("msg_lrpid", &self.msg_lrpid) .field("msg_stime", &self.msg_stime) .field("msg_rtime", &self.msg_rtime) .field("msg_ctime", &self.msg_ctime) .finish() } } // sockaddr_dl impl ::fmt::Debug for sockaddr_dl { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_dl") .field("sdl_len", &self.sdl_len) .field("sdl_family", &self.sdl_family) .field("sdl_index", &self.sdl_index) .field("sdl_type", &self.sdl_type) .field("sdl_nlen", &self.sdl_nlen) .field("sdl_alen", &self.sdl_alen) .field("sdl_slen", &self.sdl_slen) .field("sdl_data", &self.sdl_data) .finish() } } impl PartialEq for sockaddr_dl { fn eq(&self, other: &sockaddr_dl) -> bool { self.sdl_len == other.sdl_len && self.sdl_family == other.sdl_family && self.sdl_index == other.sdl_index && self.sdl_type == other.sdl_type && self.sdl_nlen == other.sdl_nlen && self.sdl_alen == other.sdl_alen && self.sdl_slen == other.sdl_slen && self .sdl_data .iter() .zip(other.sdl_data.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_dl {} impl ::hash::Hash for sockaddr_dl { fn hash(&self, state: &mut H) { self.sdl_len.hash(state); self.sdl_family.hash(state); self.sdl_index.hash(state); self.sdl_type.hash(state); self.sdl_nlen.hash(state); self.sdl_alen.hash(state); self.sdl_slen.hash(state); self.sdl_data.hash(state); } } // sync_t impl ::fmt::Debug for sync_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sync_t") .field("__owner", &self.__owner) .field("__u", &self.__u) .finish() } } // pthread_barrier_t impl ::fmt::Debug for pthread_barrier_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_barrier_t") .field("__pad", &self.__pad) .finish() } } // pthread_rwlock_t impl ::fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_rwlock_t") .field("__active", &self.__active) .field("__blockedwriters", &self.__blockedwriters) .field("__blockedreaders", &self.__blockedreaders) .field("__heavy", &self.__heavy) .field("__lock", &self.__lock) .field("__rcond", &self.__rcond) .field("__wcond", &self.__wcond) .field("__owner", &self.__owner) .field("__spare", &self.__spare) .finish() } } // syspage_entry impl ::fmt::Debug for syspage_entry { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("syspage_entry") .field("size", &self.size) .field("total_size", &self.total_size) .field("type_", &self.type_) .field("num_cpu", &self.num_cpu) .field("system_private", &self.system_private) .field("old_asinfo", &self.old_asinfo) .field("hwinfo", &self.hwinfo) .field("old_cpuinfo", &self.old_cpuinfo) .field("old_cacheattr", &self.old_cacheattr) .field("qtime", &self.qtime) .field("callout", &self.callout) .field("callin", &self.callin) .field("typed_strings", &self.typed_strings) .field("strings", &self.strings) .field("old_intrinfo", &self.old_intrinfo) .field("smp", &self.smp) .field("pminfo", &self.pminfo) .field("old_mdriver", &self.old_mdriver) .field("new_asinfo", &self.new_asinfo) .field("new_cpuinfo", &self.new_cpuinfo) .field("new_cacheattr", &self.new_cacheattr) .field("new_intrinfo", &self.new_intrinfo) .field("new_mdriver", &self.new_mdriver) .finish() } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a,b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a,b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a,b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a,b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a,b)| a == b) } } impl Eq for utsname {} impl ::fmt::Debug for utsname { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utsname") // FIXME: .field("sysname", &self.sysname) // FIXME: .field("nodename", &self.nodename) // FIXME: .field("release", &self.release) // FIXME: .field("version", &self.version) // FIXME: .field("machine", &self.machine) .finish() } } impl ::hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_flags == other.mq_flags && self.mq_curmsgs == other.mq_curmsgs && self.mq_msgsize == other.mq_msgsize && self.mq_sendwait == other.mq_sendwait && self.mq_recvwait == other.mq_recvwait } } impl Eq for mq_attr {} impl ::fmt::Debug for mq_attr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mq_attr") .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_flags", &self.mq_flags) .field("mq_curmsgs", &self.mq_curmsgs) .field("mq_msgsize", &self.mq_msgsize) .field("mq_sendwait", &self.mq_sendwait) .field("mq_recvwait", &self.mq_recvwait) .finish() } } impl ::hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_flags.hash(state); self.mq_curmsgs.hash(state); self.mq_sendwait.hash(state); self.mq_recvwait.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME: .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_offset == other.d_offset && self.d_reclen == other.d_reclen && self.d_namelen == other.d_namelen && self .d_name[..self.d_namelen as _] .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_offset", &self.d_offset) .field("d_reclen", &self.d_reclen) .field("d_namelen", &self.d_namelen) .field("d_name", &&self.d_name[..self.d_namelen as _]) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_offset.hash(state); self.d_reclen.hash(state); self.d_namelen.hash(state); self.d_name[..self.d_namelen as _].hash(state); } } } } pub const _SYSNAME_SIZE: usize = 256 + 1; pub const RLIM_INFINITY: ::rlim_t = 0xfffffffffffffffd; pub const O_LARGEFILE: ::c_int = 0o0100000; // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 32767; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 2; pub const _IOLBF: ::c_int = 1; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const F_DUPFD_CLOEXEC: ::c_int = 5; pub const SIGTRAP: ::c_int = 5; pub const CLOCK_REALTIME: ::clockid_t = 0; pub const CLOCK_MONOTONIC: ::clockid_t = 2; pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 3; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 4; pub const TIMER_ABSTIME: ::c_uint = 0x80000000; pub const RUSAGE_SELF: ::c_int = 0; pub const F_OK: ::c_int = 0; pub const X_OK: ::c_int = 1; pub const W_OK: ::c_int = 2; pub const R_OK: ::c_int = 4; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const PROT_NONE: ::c_int = 0x00000000; pub const PROT_READ: ::c_int = 0x00000100; pub const PROT_WRITE: ::c_int = 0x00000200; pub const PROT_EXEC: ::c_int = 0x00000400; pub const MAP_FILE: ::c_int = 0; pub const MAP_SHARED: ::c_int = 1; pub const MAP_PRIVATE: ::c_int = 2; pub const MAP_FIXED: ::c_int = 0x10; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const MS_ASYNC: ::c_int = 1; pub const MS_INVALIDATE: ::c_int = 4; pub const MS_SYNC: ::c_int = 2; pub const SCM_RIGHTS: ::c_int = 0x01; pub const SCM_TIMESTAMP: ::c_int = 0x02; pub const SCM_CREDS: ::c_int = 0x04; pub const MAP_TYPE: ::c_int = 0x3; pub const IFF_UP: ::c_int = 0x00000001; pub const IFF_BROADCAST: ::c_int = 0x00000002; pub const IFF_DEBUG: ::c_int = 0x00000004; pub const IFF_LOOPBACK: ::c_int = 0x00000008; pub const IFF_POINTOPOINT: ::c_int = 0x00000010; pub const IFF_NOTRAILERS: ::c_int = 0x00000020; pub const IFF_RUNNING: ::c_int = 0x00000040; pub const IFF_NOARP: ::c_int = 0x00000080; pub const IFF_PROMISC: ::c_int = 0x00000100; pub const IFF_ALLMULTI: ::c_int = 0x00000200; pub const IFF_MULTICAST: ::c_int = 0x00008000; pub const AF_UNSPEC: ::c_int = 0; pub const AF_UNIX: ::c_int = AF_LOCAL; pub const AF_LOCAL: ::c_int = 1; pub const AF_INET: ::c_int = 2; pub const AF_IPX: ::c_int = 23; pub const AF_APPLETALK: ::c_int = 16; pub const AF_INET6: ::c_int = 24; pub const AF_ROUTE: ::c_int = 17; pub const AF_SNA: ::c_int = 11; pub const AF_BLUETOOTH: ::c_int = 31; pub const AF_ISDN: ::c_int = 26; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_UNIX: ::c_int = PF_LOCAL; pub const PF_LOCAL: ::c_int = AF_LOCAL; pub const PF_INET: ::c_int = AF_INET; pub const PF_IPX: ::c_int = AF_IPX; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_INET6: ::c_int = AF_INET6; pub const pseudo_AF_KEY: ::c_int = 29; pub const PF_KEY: ::c_int = pseudo_AF_KEY; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const PF_ISDN: ::c_int = AF_ISDN; pub const SOMAXCONN: ::c_int = 128; pub const MSG_OOB: ::c_int = 0x0001; pub const MSG_PEEK: ::c_int = 0x0002; pub const MSG_DONTROUTE: ::c_int = 0x0004; pub const MSG_CTRUNC: ::c_int = 0x0020; pub const MSG_TRUNC: ::c_int = 0x0010; pub const MSG_DONTWAIT: ::c_int = 0x0080; pub const MSG_EOR: ::c_int = 0x0008; pub const MSG_WAITALL: ::c_int = 0x0040; pub const MSG_NOSIGNAL: ::c_int = 0x0800; pub const MSG_WAITFORONE: ::c_int = 0x2000; pub const IP_TOS: ::c_int = 3; pub const IP_TTL: ::c_int = 4; pub const IP_HDRINCL: ::c_int = 2; pub const IP_OPTIONS: ::c_int = 1; pub const IP_RECVOPTS: ::c_int = 5; pub const IP_RETOPTS: ::c_int = 8; pub const IP_PKTINFO: ::c_int = 25; pub const IP_IPSEC_POLICY_COMPAT: ::c_int = 22; pub const IP_MULTICAST_IF: ::c_int = 9; pub const IP_MULTICAST_TTL: ::c_int = 10; pub const IP_MULTICAST_LOOP: ::c_int = 11; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; pub const IP_DEFAULT_MULTICAST_TTL: ::c_int = 1; pub const IP_DEFAULT_MULTICAST_LOOP: ::c_int = 1; pub const IPPROTO_HOPOPTS: ::c_int = 0; pub const IPPROTO_IGMP: ::c_int = 2; pub const IPPROTO_IPIP: ::c_int = 4; pub const IPPROTO_EGP: ::c_int = 8; pub const IPPROTO_PUP: ::c_int = 12; pub const IPPROTO_IDP: ::c_int = 22; pub const IPPROTO_TP: ::c_int = 29; pub const IPPROTO_ROUTING: ::c_int = 43; pub const IPPROTO_FRAGMENT: ::c_int = 44; pub const IPPROTO_RSVP: ::c_int = 46; pub const IPPROTO_GRE: ::c_int = 47; pub const IPPROTO_ESP: ::c_int = 50; pub const IPPROTO_AH: ::c_int = 51; pub const IPPROTO_NONE: ::c_int = 59; pub const IPPROTO_DSTOPTS: ::c_int = 60; pub const IPPROTO_ENCAP: ::c_int = 98; pub const IPPROTO_PIM: ::c_int = 103; pub const IPPROTO_SCTP: ::c_int = 132; pub const IPPROTO_RAW: ::c_int = 255; pub const IPPROTO_MAX: ::c_int = 256; pub const IPPROTO_CARP: ::c_int = 112; pub const IPPROTO_DIVERT: ::c_int = 259; pub const IPPROTO_DONE: ::c_int = 257; pub const IPPROTO_EON: ::c_int = 80; pub const IPPROTO_ETHERIP: ::c_int = 97; pub const IPPROTO_GGP: ::c_int = 3; pub const IPPROTO_IPCOMP: ::c_int = 108; pub const IPPROTO_MOBILE: ::c_int = 55; pub const IPV6_RTHDR_LOOSE: ::c_int = 0; pub const IPV6_RTHDR_STRICT: ::c_int = 1; pub const IPV6_UNICAST_HOPS: ::c_int = 4; pub const IPV6_MULTICAST_IF: ::c_int = 9; pub const IPV6_MULTICAST_HOPS: ::c_int = 10; pub const IPV6_MULTICAST_LOOP: ::c_int = 11; pub const IPV6_JOIN_GROUP: ::c_int = 12; pub const IPV6_LEAVE_GROUP: ::c_int = 13; pub const IPV6_CHECKSUM: ::c_int = 26; pub const IPV6_V6ONLY: ::c_int = 27; pub const IPV6_IPSEC_POLICY_COMPAT: ::c_int = 28; pub const IPV6_RTHDRDSTOPTS: ::c_int = 35; pub const IPV6_RECVPKTINFO: ::c_int = 36; pub const IPV6_RECVHOPLIMIT: ::c_int = 37; pub const IPV6_RECVRTHDR: ::c_int = 38; pub const IPV6_RECVHOPOPTS: ::c_int = 39; pub const IPV6_RECVDSTOPTS: ::c_int = 40; pub const IPV6_RECVPATHMTU: ::c_int = 43; pub const IPV6_PATHMTU: ::c_int = 44; pub const IPV6_PKTINFO: ::c_int = 46; pub const IPV6_HOPLIMIT: ::c_int = 47; pub const IPV6_NEXTHOP: ::c_int = 48; pub const IPV6_HOPOPTS: ::c_int = 49; pub const IPV6_DSTOPTS: ::c_int = 50; pub const IPV6_RECVTCLASS: ::c_int = 57; pub const IPV6_TCLASS: ::c_int = 61; pub const IPV6_DONTFRAG: ::c_int = 62; pub const TCP_NODELAY: ::c_int = 0x01; pub const TCP_MAXSEG: ::c_int = 0x02; pub const TCP_MD5SIG: ::c_int = 0x10; pub const TCP_KEEPALIVE: ::c_int = 0x04; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const LOCK_SH: ::c_int = 0x1; pub const LOCK_EX: ::c_int = 0x2; pub const LOCK_NB: ::c_int = 0x4; pub const LOCK_UN: ::c_int = 0x8; pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 2; pub const PATH_MAX: ::c_int = 1024; pub const UIO_MAXIOV: ::c_int = 1024; pub const FD_SETSIZE: usize = 256; pub const TCIOFF: ::c_int = 0x0002; pub const TCION: ::c_int = 0x0003; pub const TCOOFF: ::c_int = 0x0000; pub const TCOON: ::c_int = 0x0001; pub const TCIFLUSH: ::c_int = 0; pub const TCOFLUSH: ::c_int = 1; pub const TCIOFLUSH: ::c_int = 2; pub const NL0: ::tcflag_t = 0x000; pub const NL1: ::tcflag_t = 0x100; pub const TAB0: ::tcflag_t = 0x0000; pub const CR0: ::tcflag_t = 0x000; pub const FF0: ::tcflag_t = 0x0000; pub const BS0: ::tcflag_t = 0x0000; pub const VT0: ::tcflag_t = 0x0000; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VLNEXT: usize = 15; pub const IGNBRK: ::tcflag_t = 0x00000001; pub const BRKINT: ::tcflag_t = 0x00000002; pub const IGNPAR: ::tcflag_t = 0x00000004; pub const PARMRK: ::tcflag_t = 0x00000008; pub const INPCK: ::tcflag_t = 0x00000010; pub const ISTRIP: ::tcflag_t = 0x00000020; pub const INLCR: ::tcflag_t = 0x00000040; pub const IGNCR: ::tcflag_t = 0x00000080; pub const ICRNL: ::tcflag_t = 0x00000100; pub const IXANY: ::tcflag_t = 0x00000800; pub const IMAXBEL: ::tcflag_t = 0x00002000; pub const OPOST: ::tcflag_t = 0x00000001; pub const CS5: ::tcflag_t = 0x00; pub const ECHO: ::tcflag_t = 0x00000008; pub const OCRNL: ::tcflag_t = 0x00000008; pub const ONOCR: ::tcflag_t = 0x00000010; pub const ONLRET: ::tcflag_t = 0x00000020; pub const OFILL: ::tcflag_t = 0x00000040; pub const OFDEL: ::tcflag_t = 0x00000080; pub const WNOHANG: ::c_int = 0x0040; pub const WUNTRACED: ::c_int = 0x0004; pub const WSTOPPED: ::c_int = WUNTRACED; pub const WEXITED: ::c_int = 0x0001; pub const WCONTINUED: ::c_int = 0x0008; pub const WNOWAIT: ::c_int = 0x0080; pub const WTRAPPED: ::c_int = 0x0002; pub const RTLD_LOCAL: ::c_int = 0x0200; pub const RTLD_LAZY: ::c_int = 0x0001; pub const POSIX_FADV_NORMAL: ::c_int = 0; pub const POSIX_FADV_RANDOM: ::c_int = 2; pub const POSIX_FADV_SEQUENTIAL: ::c_int = 1; pub const POSIX_FADV_WILLNEED: ::c_int = 3; pub const AT_FDCWD: ::c_int = -100; pub const AT_EACCESS: ::c_int = 0x0001; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x0002; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x0004; pub const AT_REMOVEDIR: ::c_int = 0x0008; pub const LOG_CRON: ::c_int = 9 << 3; pub const LOG_AUTHPRIV: ::c_int = 10 << 3; pub const LOG_FTP: ::c_int = 11 << 3; pub const LOG_PERROR: ::c_int = 0x20; pub const PIPE_BUF: usize = 5120; pub const CLD_EXITED: ::c_int = 1; pub const CLD_KILLED: ::c_int = 2; pub const CLD_DUMPED: ::c_int = 3; pub const CLD_TRAPPED: ::c_int = 4; pub const CLD_STOPPED: ::c_int = 5; pub const CLD_CONTINUED: ::c_int = 6; pub const UTIME_OMIT: c_long = 0x40000002; pub const UTIME_NOW: c_long = 0x40000001; pub const POLLIN: ::c_short = POLLRDNORM | POLLRDBAND; pub const POLLPRI: ::c_short = 0x0008; pub const POLLOUT: ::c_short = 0x0002; pub const POLLERR: ::c_short = 0x0020; pub const POLLHUP: ::c_short = 0x0040; pub const POLLNVAL: ::c_short = 0x1000; pub const POLLRDNORM: ::c_short = 0x0001; pub const POLLRDBAND: ::c_short = 0x0004; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; pub const IPTOS_RELIABILITY: u8 = 0x04; pub const IPTOS_MINCOST: u8 = 0x02; pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0; pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0; pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0; pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80; pub const IPTOS_PREC_FLASH: u8 = 0x60; pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40; pub const IPTOS_PREC_PRIORITY: u8 = 0x20; pub const IPTOS_PREC_ROUTINE: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const IPOPT_CONTROL: u8 = 0x00; pub const IPOPT_RESERVED1: u8 = 0x20; pub const IPOPT_RESERVED2: u8 = 0x60; pub const IPOPT_LSRR: u8 = 131; pub const IPOPT_RR: u8 = 7; pub const IPOPT_SSRR: u8 = 137; pub const IPDEFTTL: u8 = 64; pub const IPOPT_OPTVAL: u8 = 0; pub const IPOPT_OLEN: u8 = 1; pub const IPOPT_OFFSET: u8 = 2; pub const IPOPT_MINOFF: u8 = 4; pub const IPOPT_NOP: u8 = 1; pub const IPOPT_EOL: u8 = 0; pub const IPOPT_TS: u8 = 68; pub const IPOPT_TS_TSONLY: u8 = 0; pub const IPOPT_TS_TSANDADDR: u8 = 1; pub const IPOPT_TS_PRESPEC: u8 = 3; pub const MAX_IPOPTLEN: u8 = 40; pub const IPVERSION: u8 = 4; pub const MAXTTL: u8 = 255; pub const ARPHRD_ETHER: u16 = 1; pub const ARPHRD_IEEE802: u16 = 6; pub const ARPHRD_ARCNET: u16 = 7; pub const ARPHRD_IEEE1394: u16 = 24; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x0001; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_TYPE: ::c_int = 0x1008; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_RCVLOWAT: ::c_int = 0x1004; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_BINDTODEVICE: ::c_int = 0x0800; pub const SO_TIMESTAMP: ::c_int = 0x0400; pub const SO_ACCEPTCONN: ::c_int = 0x0002; pub const TIOCM_LE: ::c_int = 0x0100; pub const TIOCM_DTR: ::c_int = 0x0001; pub const TIOCM_RTS: ::c_int = 0x0002; pub const TIOCM_ST: ::c_int = 0x0200; pub const TIOCM_SR: ::c_int = 0x0400; pub const TIOCM_CTS: ::c_int = 0x1000; pub const TIOCM_CAR: ::c_int = TIOCM_CD; pub const TIOCM_CD: ::c_int = 0x8000; pub const TIOCM_RNG: ::c_int = TIOCM_RI; pub const TIOCM_RI: ::c_int = 0x4000; pub const TIOCM_DSR: ::c_int = 0x2000; pub const SCHED_OTHER: ::c_int = 3; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const IPC_PRIVATE: ::key_t = 0; pub const IPC_CREAT: ::c_int = 0o001000; pub const IPC_EXCL: ::c_int = 0o002000; pub const IPC_NOWAIT: ::c_int = 0o004000; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const MSG_NOERROR: ::c_int = 0o010000; pub const LOG_NFACILITIES: ::c_int = 24; pub const SEM_FAILED: *mut ::sem_t = 0xFFFFFFFFFFFFFFFF as *mut sem_t; pub const AI_PASSIVE: ::c_int = 0x00000001; pub const AI_CANONNAME: ::c_int = 0x00000002; pub const AI_NUMERICHOST: ::c_int = 0x00000004; pub const AI_NUMERICSERV: ::c_int = 0x00000008; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_NONAME: ::c_int = 8; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_FAIL: ::c_int = 4; pub const EAI_NODATA: ::c_int = 7; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 14; pub const NI_NUMERICHOST: ::c_int = 0x00000002; pub const NI_NUMERICSERV: ::c_int = 0x00000008; pub const NI_NOFQDN: ::c_int = 0x00000001; pub const NI_NAMEREQD: ::c_int = 0x00000004; pub const NI_DGRAM: ::c_int = 0x00000010; pub const AIO_CANCELED: ::c_int = 0; pub const AIO_NOTCANCELED: ::c_int = 2; pub const AIO_ALLDONE: ::c_int = 1; pub const LIO_READ: ::c_int = 1; pub const LIO_WRITE: ::c_int = 2; pub const LIO_NOP: ::c_int = 0; pub const LIO_WAIT: ::c_int = 1; pub const LIO_NOWAIT: ::c_int = 0; pub const ITIMER_REAL: ::c_int = 0; pub const ITIMER_VIRTUAL: ::c_int = 1; pub const ITIMER_PROF: ::c_int = 2; pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x00000010; pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x00000001; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x00000004; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x00000002; pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x00000400; pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x00000040; pub const IPTOS_ECN_NOT_ECT: u8 = 0x00; pub const RTF_UP: ::c_ushort = 0x0001; pub const RTF_GATEWAY: ::c_ushort = 0x0002; pub const RTF_HOST: ::c_ushort = 0x0004; pub const RTF_DYNAMIC: ::c_ushort = 0x0010; pub const RTF_MODIFIED: ::c_ushort = 0x0020; pub const RTF_REJECT: ::c_ushort = 0x0008; pub const RTF_STATIC: ::c_ushort = 0x0800; pub const RTF_XRESOLVE: ::c_ushort = 0x0200; pub const RTF_BROADCAST: u32 = 0x80000; pub const RTM_NEWADDR: u16 = 0xc; pub const RTM_DELADDR: u16 = 0xd; pub const RTA_DST: ::c_ushort = 0x1; pub const RTA_GATEWAY: ::c_ushort = 0x2; pub const UDP_ENCAP: ::c_int = 100; pub const IN_ACCESS: u32 = 0x00000001; pub const IN_MODIFY: u32 = 0x00000002; pub const IN_ATTRIB: u32 = 0x00000004; pub const IN_CLOSE_WRITE: u32 = 0x00000008; pub const IN_CLOSE_NOWRITE: u32 = 0x00000010; pub const IN_CLOSE: u32 = IN_CLOSE_WRITE | IN_CLOSE_NOWRITE; pub const IN_OPEN: u32 = 0x00000020; pub const IN_MOVED_FROM: u32 = 0x00000040; pub const IN_MOVED_TO: u32 = 0x00000080; pub const IN_MOVE: u32 = IN_MOVED_FROM | IN_MOVED_TO; pub const IN_CREATE: u32 = 0x00000100; pub const IN_DELETE: u32 = 0x00000200; pub const IN_DELETE_SELF: u32 = 0x00000400; pub const IN_MOVE_SELF: u32 = 0x00000800; pub const IN_UNMOUNT: u32 = 0x00002000; pub const IN_Q_OVERFLOW: u32 = 0x00004000; pub const IN_IGNORED: u32 = 0x00008000; pub const IN_ONLYDIR: u32 = 0x01000000; pub const IN_DONT_FOLLOW: u32 = 0x02000000; pub const IN_ISDIR: u32 = 0x40000000; pub const IN_ONESHOT: u32 = 0x80000000; pub const REG_EXTENDED: ::c_int = 0o0001; pub const REG_ICASE: ::c_int = 0o0002; pub const REG_NEWLINE: ::c_int = 0o0010; pub const REG_NOSUB: ::c_int = 0o0004; pub const REG_NOTBOL: ::c_int = 0o00001; pub const REG_NOTEOL: ::c_int = 0o00002; pub const REG_ENOSYS: ::c_int = 17; pub const REG_NOMATCH: ::c_int = 1; pub const REG_BADPAT: ::c_int = 2; pub const REG_ECOLLATE: ::c_int = 3; pub const REG_ECTYPE: ::c_int = 4; pub const REG_EESCAPE: ::c_int = 5; pub const REG_ESUBREG: ::c_int = 6; pub const REG_EBRACK: ::c_int = 7; pub const REG_EPAREN: ::c_int = 8; pub const REG_EBRACE: ::c_int = 9; pub const REG_BADBR: ::c_int = 10; pub const REG_ERANGE: ::c_int = 11; pub const REG_ESPACE: ::c_int = 12; pub const REG_BADRPT: ::c_int = 13; // errno.h pub const EOK: ::c_int = 0; pub const EWOULDBLOCK: ::c_int = EAGAIN; pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const ECHRNG: ::c_int = 37; pub const EL2NSYNC: ::c_int = 38; pub const EL3HLT: ::c_int = 39; pub const EL3RST: ::c_int = 40; pub const ELNRNG: ::c_int = 41; pub const EUNATCH: ::c_int = 42; pub const ENOCSI: ::c_int = 43; pub const EL2HLT: ::c_int = 44; pub const EDEADLK: ::c_int = 45; pub const ENOLCK: ::c_int = 46; pub const ECANCELED: ::c_int = 47; pub const EDQUOT: ::c_int = 49; pub const EBADE: ::c_int = 50; pub const EBADR: ::c_int = 51; pub const EXFULL: ::c_int = 52; pub const ENOANO: ::c_int = 53; pub const EBADRQC: ::c_int = 54; pub const EBADSLT: ::c_int = 55; pub const EDEADLOCK: ::c_int = 56; pub const EBFONT: ::c_int = 57; pub const EOWNERDEAD: ::c_int = 58; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENONET: ::c_int = 64; pub const ENOPKG: ::c_int = 65; pub const EREMOTE: ::c_int = 66; pub const ENOLINK: ::c_int = 67; pub const EADV: ::c_int = 68; pub const ESRMNT: ::c_int = 69; pub const ECOMM: ::c_int = 70; pub const EPROTO: ::c_int = 71; pub const EMULTIHOP: ::c_int = 74; pub const EBADMSG: ::c_int = 77; pub const ENAMETOOLONG: ::c_int = 78; pub const EOVERFLOW: ::c_int = 79; pub const ENOTUNIQ: ::c_int = 80; pub const EBADFD: ::c_int = 81; pub const EREMCHG: ::c_int = 82; pub const ELIBACC: ::c_int = 83; pub const ELIBBAD: ::c_int = 84; pub const ELIBSCN: ::c_int = 85; pub const ELIBMAX: ::c_int = 86; pub const ELIBEXEC: ::c_int = 87; pub const EILSEQ: ::c_int = 88; pub const ENOSYS: ::c_int = 89; pub const ELOOP: ::c_int = 90; pub const ERESTART: ::c_int = 91; pub const ESTRPIPE: ::c_int = 92; pub const ENOTEMPTY: ::c_int = 93; pub const EUSERS: ::c_int = 94; pub const ENOTRECOVERABLE: ::c_int = 95; pub const EOPNOTSUPP: ::c_int = 103; pub const EFPOS: ::c_int = 110; pub const ESTALE: ::c_int = 122; pub const EINPROGRESS: ::c_int = 236; pub const EALREADY: ::c_int = 237; pub const ENOTSOCK: ::c_int = 238; pub const EDESTADDRREQ: ::c_int = 239; pub const EMSGSIZE: ::c_int = 240; pub const EPROTOTYPE: ::c_int = 241; pub const ENOPROTOOPT: ::c_int = 242; pub const EPROTONOSUPPORT: ::c_int = 243; pub const ESOCKTNOSUPPORT: ::c_int = 244; pub const EPFNOSUPPORT: ::c_int = 246; pub const EAFNOSUPPORT: ::c_int = 247; pub const EADDRINUSE: ::c_int = 248; pub const EADDRNOTAVAIL: ::c_int = 249; pub const ENETDOWN: ::c_int = 250; pub const ENETUNREACH: ::c_int = 251; pub const ENETRESET: ::c_int = 252; pub const ECONNABORTED: ::c_int = 253; pub const ECONNRESET: ::c_int = 254; pub const ENOBUFS: ::c_int = 255; pub const EISCONN: ::c_int = 256; pub const ENOTCONN: ::c_int = 257; pub const ESHUTDOWN: ::c_int = 258; pub const ETOOMANYREFS: ::c_int = 259; pub const ETIMEDOUT: ::c_int = 260; pub const ECONNREFUSED: ::c_int = 261; pub const EHOSTDOWN: ::c_int = 264; pub const EHOSTUNREACH: ::c_int = 265; pub const EBADRPC: ::c_int = 272; pub const ERPCMISMATCH: ::c_int = 273; pub const EPROGUNAVAIL: ::c_int = 274; pub const EPROGMISMATCH: ::c_int = 275; pub const EPROCUNAVAIL: ::c_int = 276; pub const ENOREMOTE: ::c_int = 300; pub const ENONDP: ::c_int = 301; pub const EBADFSYS: ::c_int = 302; pub const EMORE: ::c_int = 309; pub const ECTRLTERM: ::c_int = 310; pub const ENOLIC: ::c_int = 311; pub const ESRVRFAULT: ::c_int = 312; pub const EENDIAN: ::c_int = 313; pub const ESECTYPEINVAL: ::c_int = 314; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const L_tmpnam: ::c_uint = 255; pub const _PC_LINK_MAX: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_CHOWN_RESTRICTED: ::c_int = 9; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_SYNC_IO: ::c_int = 14; pub const _PC_ASYNC_IO: ::c_int = 12; pub const _PC_PRIO_IO: ::c_int = 13; pub const _PC_SOCK_MAXBUF: ::c_int = 15; pub const _PC_FILESIZEBITS: ::c_int = 16; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 22; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 23; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 24; pub const _PC_REC_XFER_ALIGN: ::c_int = 25; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 21; pub const _PC_SYMLINK_MAX: ::c_int = 17; pub const _PC_2_SYMLINKS: ::c_int = 20; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_ARG_MAX: ::c_int = 1; pub const _SC_CHILD_MAX: ::c_int = 2; pub const _SC_CLK_TCK: ::c_int = 3; pub const _SC_NGROUPS_MAX: ::c_int = 4; pub const _SC_OPEN_MAX: ::c_int = 5; pub const _SC_JOB_CONTROL: ::c_int = 6; pub const _SC_SAVED_IDS: ::c_int = 7; pub const _SC_VERSION: ::c_int = 8; pub const _SC_PASS_MAX: ::c_int = 9; pub const _SC_PAGESIZE: ::c_int = 11; pub const _SC_XOPEN_VERSION: ::c_int = 12; pub const _SC_STREAM_MAX: ::c_int = 13; pub const _SC_TZNAME_MAX: ::c_int = 14; pub const _SC_AIO_LISTIO_MAX: ::c_int = 15; pub const _SC_AIO_MAX: ::c_int = 16; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 17; pub const _SC_DELAYTIMER_MAX: ::c_int = 18; pub const _SC_MQ_OPEN_MAX: ::c_int = 19; pub const _SC_MQ_PRIO_MAX: ::c_int = 20; pub const _SC_RTSIG_MAX: ::c_int = 21; pub const _SC_SEM_NSEMS_MAX: ::c_int = 22; pub const _SC_SEM_VALUE_MAX: ::c_int = 23; pub const _SC_SIGQUEUE_MAX: ::c_int = 24; pub const _SC_TIMER_MAX: ::c_int = 25; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 26; pub const _SC_FSYNC: ::c_int = 27; pub const _SC_MAPPED_FILES: ::c_int = 28; pub const _SC_MEMLOCK: ::c_int = 29; pub const _SC_MEMLOCK_RANGE: ::c_int = 30; pub const _SC_MEMORY_PROTECTION: ::c_int = 31; pub const _SC_MESSAGE_PASSING: ::c_int = 32; pub const _SC_PRIORITIZED_IO: ::c_int = 33; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 34; pub const _SC_REALTIME_SIGNALS: ::c_int = 35; pub const _SC_SEMAPHORES: ::c_int = 36; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 37; pub const _SC_SYNCHRONIZED_IO: ::c_int = 38; pub const _SC_TIMERS: ::c_int = 39; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 40; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 41; pub const _SC_LOGIN_NAME_MAX: ::c_int = 42; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 43; pub const _SC_THREAD_KEYS_MAX: ::c_int = 44; pub const _SC_THREAD_STACK_MIN: ::c_int = 45; pub const _SC_THREAD_THREADS_MAX: ::c_int = 46; pub const _SC_TTY_NAME_MAX: ::c_int = 47; pub const _SC_THREADS: ::c_int = 48; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 49; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 50; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 51; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 52; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 53; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 54; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 55; pub const _SC_2_CHAR_TERM: ::c_int = 56; pub const _SC_2_C_BIND: ::c_int = 57; pub const _SC_2_C_DEV: ::c_int = 58; pub const _SC_2_C_VERSION: ::c_int = 59; pub const _SC_2_FORT_DEV: ::c_int = 60; pub const _SC_2_FORT_RUN: ::c_int = 61; pub const _SC_2_LOCALEDEF: ::c_int = 62; pub const _SC_2_SW_DEV: ::c_int = 63; pub const _SC_2_UPE: ::c_int = 64; pub const _SC_2_VERSION: ::c_int = 65; pub const _SC_ATEXIT_MAX: ::c_int = 66; pub const _SC_AVPHYS_PAGES: ::c_int = 67; pub const _SC_BC_BASE_MAX: ::c_int = 68; pub const _SC_BC_DIM_MAX: ::c_int = 69; pub const _SC_BC_SCALE_MAX: ::c_int = 70; pub const _SC_BC_STRING_MAX: ::c_int = 71; pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 72; pub const _SC_CHAR_BIT: ::c_int = 73; pub const _SC_CHAR_MAX: ::c_int = 74; pub const _SC_CHAR_MIN: ::c_int = 75; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 76; pub const _SC_EQUIV_CLASS_MAX: ::c_int = 77; pub const _SC_EXPR_NEST_MAX: ::c_int = 78; pub const _SC_INT_MAX: ::c_int = 79; pub const _SC_INT_MIN: ::c_int = 80; pub const _SC_LINE_MAX: ::c_int = 81; pub const _SC_LONG_BIT: ::c_int = 82; pub const _SC_MB_LEN_MAX: ::c_int = 83; pub const _SC_NL_ARGMAX: ::c_int = 84; pub const _SC_NL_LANGMAX: ::c_int = 85; pub const _SC_NL_MSGMAX: ::c_int = 86; pub const _SC_NL_NMAX: ::c_int = 87; pub const _SC_NL_SETMAX: ::c_int = 88; pub const _SC_NL_TEXTMAX: ::c_int = 89; pub const _SC_NPROCESSORS_CONF: ::c_int = 90; pub const _SC_NPROCESSORS_ONLN: ::c_int = 91; pub const _SC_NZERO: ::c_int = 92; pub const _SC_PHYS_PAGES: ::c_int = 93; pub const _SC_PII: ::c_int = 94; pub const _SC_PII_INTERNET: ::c_int = 95; pub const _SC_PII_INTERNET_DGRAM: ::c_int = 96; pub const _SC_PII_INTERNET_STREAM: ::c_int = 97; pub const _SC_PII_OSI: ::c_int = 98; pub const _SC_PII_OSI_CLTS: ::c_int = 99; pub const _SC_PII_OSI_COTS: ::c_int = 100; pub const _SC_PII_OSI_M: ::c_int = 101; pub const _SC_PII_SOCKET: ::c_int = 102; pub const _SC_PII_XTI: ::c_int = 103; pub const _SC_POLL: ::c_int = 104; pub const _SC_RE_DUP_MAX: ::c_int = 105; pub const _SC_SCHAR_MAX: ::c_int = 106; pub const _SC_SCHAR_MIN: ::c_int = 107; pub const _SC_SELECT: ::c_int = 108; pub const _SC_SHRT_MAX: ::c_int = 109; pub const _SC_SHRT_MIN: ::c_int = 110; pub const _SC_SSIZE_MAX: ::c_int = 111; pub const _SC_T_IOV_MAX: ::c_int = 112; pub const _SC_UCHAR_MAX: ::c_int = 113; pub const _SC_UINT_MAX: ::c_int = 114; pub const _SC_UIO_MAXIOV: ::c_int = 115; pub const _SC_ULONG_MAX: ::c_int = 116; pub const _SC_USHRT_MAX: ::c_int = 117; pub const _SC_WORD_BIT: ::c_int = 118; pub const _SC_XOPEN_CRYPT: ::c_int = 119; pub const _SC_XOPEN_ENH_I18N: ::c_int = 120; pub const _SC_XOPEN_SHM: ::c_int = 121; pub const _SC_XOPEN_UNIX: ::c_int = 122; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 123; pub const _SC_XOPEN_XPG2: ::c_int = 124; pub const _SC_XOPEN_XPG3: ::c_int = 125; pub const _SC_XOPEN_XPG4: ::c_int = 126; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 127; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 128; pub const _SC_XBS5_LP64_OFF64: ::c_int = 129; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 130; pub const _SC_ADVISORY_INFO: ::c_int = 131; pub const _SC_CPUTIME: ::c_int = 132; pub const _SC_SPAWN: ::c_int = 133; pub const _SC_SPORADIC_SERVER: ::c_int = 134; pub const _SC_THREAD_CPUTIME: ::c_int = 135; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 136; pub const _SC_TIMEOUTS: ::c_int = 137; pub const _SC_BARRIERS: ::c_int = 138; pub const _SC_CLOCK_SELECTION: ::c_int = 139; pub const _SC_MONOTONIC_CLOCK: ::c_int = 140; pub const _SC_READER_WRITER_LOCKS: ::c_int = 141; pub const _SC_SPIN_LOCKS: ::c_int = 142; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 143; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 144; pub const _SC_TRACE: ::c_int = 145; pub const _SC_TRACE_INHERIT: ::c_int = 146; pub const _SC_TRACE_LOG: ::c_int = 147; pub const _SC_2_PBS: ::c_int = 148; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 149; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 150; pub const _SC_2_PBS_LOCATE: ::c_int = 151; pub const _SC_2_PBS_MESSAGE: ::c_int = 152; pub const _SC_2_PBS_TRACK: ::c_int = 153; pub const _SC_HOST_NAME_MAX: ::c_int = 154; pub const _SC_IOV_MAX: ::c_int = 155; pub const _SC_IPV6: ::c_int = 156; pub const _SC_RAW_SOCKETS: ::c_int = 157; pub const _SC_REGEXP: ::c_int = 158; pub const _SC_SHELL: ::c_int = 159; pub const _SC_SS_REPL_MAX: ::c_int = 160; pub const _SC_SYMLOOP_MAX: ::c_int = 161; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 162; pub const _SC_TRACE_NAME_MAX: ::c_int = 163; pub const _SC_TRACE_SYS_MAX: ::c_int = 164; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 165; pub const _SC_V6_ILP32_OFF32: ::c_int = 166; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 167; pub const _SC_V6_LP64_OFF64: ::c_int = 168; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 169; pub const _SC_XOPEN_REALTIME: ::c_int = 170; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 171; pub const _SC_XOPEN_LEGACY: ::c_int = 172; pub const _SC_XOPEN_STREAMS: ::c_int = 173; pub const _SC_V7_ILP32_OFF32: ::c_int = 176; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 177; pub const _SC_V7_LP64_OFF64: ::c_int = 178; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 179; pub const GLOB_ERR: ::c_int = 0x0001; pub const GLOB_MARK: ::c_int = 0x0002; pub const GLOB_NOSORT: ::c_int = 0x0004; pub const GLOB_DOOFFS: ::c_int = 0x0008; pub const GLOB_NOCHECK: ::c_int = 0x0010; pub const GLOB_APPEND: ::c_int = 0x0020; pub const GLOB_NOESCAPE: ::c_int = 0x0040; pub const GLOB_NOSPACE: ::c_int = 1; pub const GLOB_ABORTED: ::c_int = 2; pub const GLOB_NOMATCH: ::c_int = 3; pub const S_IEXEC: mode_t = ::S_IXUSR; pub const S_IWRITE: mode_t = ::S_IWUSR; pub const S_IREAD: mode_t = ::S_IRUSR; pub const S_IFIFO: ::mode_t = 0x1000; pub const S_IFCHR: ::mode_t = 0x2000; pub const S_IFDIR: ::mode_t = 0x4000; pub const S_IFBLK: ::mode_t = 0x6000; pub const S_IFREG: ::mode_t = 0x8000; pub const S_IFLNK: ::mode_t = 0xA000; pub const S_IFSOCK: ::mode_t = 0xC000; pub const S_IFMT: ::mode_t = 0xF000; pub const S_IXOTH: ::mode_t = 0o000001; pub const S_IWOTH: ::mode_t = 0o000002; pub const S_IROTH: ::mode_t = 0o000004; pub const S_IRWXO: ::mode_t = 0o000007; pub const S_IXGRP: ::mode_t = 0o000010; pub const S_IWGRP: ::mode_t = 0o000020; pub const S_IRGRP: ::mode_t = 0o000040; pub const S_IRWXG: ::mode_t = 0o000070; pub const S_IXUSR: ::mode_t = 0o000100; pub const S_IWUSR: ::mode_t = 0o000200; pub const S_IRUSR: ::mode_t = 0o000400; pub const S_IRWXU: ::mode_t = 0o000700; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const ST_RDONLY: ::c_ulong = 0x01; pub const ST_NOSUID: ::c_ulong = 0x04; pub const ST_NOEXEC: ::c_ulong = 0x02; pub const ST_NOATIME: ::c_ulong = 0x20; pub const RTLD_NEXT: *mut ::c_void = -3i64 as *mut ::c_void; pub const RTLD_DEFAULT: *mut ::c_void = -2i64 as *mut ::c_void; pub const RTLD_NODELETE: ::c_int = 0x1000; pub const RTLD_NOW: ::c_int = 0x0002; pub const EMPTY: ::c_short = 0; pub const RUN_LVL: ::c_short = 1; pub const BOOT_TIME: ::c_short = 2; pub const NEW_TIME: ::c_short = 4; pub const OLD_TIME: ::c_short = 3; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const USER_PROCESS: ::c_short = 7; pub const DEAD_PROCESS: ::c_short = 8; pub const ACCOUNTING: ::c_short = 9; pub const ENOTSUP: ::c_int = 48; pub const BUFSIZ: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 26 * 26 * 26; pub const FOPEN_MAX: ::c_uint = 16; pub const FILENAME_MAX: ::c_uint = 255; pub const NI_MAXHOST: ::socklen_t = 1025; pub const M_KEEP: ::c_int = 4; pub const REG_STARTEND: ::c_int = 0o00004; pub const VEOF: usize = 4; pub const RTLD_GLOBAL: ::c_int = 0x0100; pub const RTLD_NOLOAD: ::c_int = 0x0004; pub const O_RDONLY: ::c_int = 0o000000; pub const O_WRONLY: ::c_int = 0o000001; pub const O_RDWR: ::c_int = 0o000002; pub const O_EXEC: ::c_int = 0o00003; pub const O_ASYNC: ::c_int = 0o0200000; pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const O_TRUNC: ::c_int = 0o001000; pub const O_CLOEXEC: ::c_int = 0o020000; pub const O_DIRECTORY: ::c_int = 0o4000000; pub const O_ACCMODE: ::c_int = 0o000007; pub const O_APPEND: ::c_int = 0o000010; pub const O_CREAT: ::c_int = 0o000400; pub const O_EXCL: ::c_int = 0o002000; pub const O_NOCTTY: ::c_int = 0o004000; pub const O_NONBLOCK: ::c_int = 0o000200; pub const O_SYNC: ::c_int = 0o000040; pub const O_RSYNC: ::c_int = 0o000100; pub const O_DSYNC: ::c_int = 0o000020; pub const O_NOFOLLOW: ::c_int = 0o010000; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_CLOEXEC: ::c_int = 0x10000000; pub const SA_SIGINFO: ::c_int = 0x0002; pub const SA_NOCLDWAIT: ::c_int = 0x0020; pub const SA_NODEFER: ::c_int = 0x0010; pub const SA_RESETHAND: ::c_int = 0x0004; pub const SA_NOCLDSTOP: ::c_int = 0x0001; pub const SIGTTIN: ::c_int = 26; pub const SIGTTOU: ::c_int = 27; pub const SIGXCPU: ::c_int = 30; pub const SIGXFSZ: ::c_int = 31; pub const SIGVTALRM: ::c_int = 28; pub const SIGPROF: ::c_int = 29; pub const SIGWINCH: ::c_int = 20; pub const SIGCHLD: ::c_int = 18; pub const SIGBUS: ::c_int = 10; pub const SIGUSR1: ::c_int = 16; pub const SIGUSR2: ::c_int = 17; pub const SIGCONT: ::c_int = 25; pub const SIGSTOP: ::c_int = 23; pub const SIGTSTP: ::c_int = 24; pub const SIGURG: ::c_int = 21; pub const SIGIO: ::c_int = SIGPOLL; pub const SIGSYS: ::c_int = 12; pub const SIGPOLL: ::c_int = 22; pub const SIGPWR: ::c_int = 19; pub const SIG_SETMASK: ::c_int = 2; pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const POLLWRNORM: ::c_short = ::POLLOUT; pub const POLLWRBAND: ::c_short = 0x0010; pub const F_SETLK: ::c_int = 106; pub const F_SETLKW: ::c_int = 107; pub const F_ALLOCSP: ::c_int = 110; pub const F_FREESP: ::c_int = 111; pub const F_GETLK: ::c_int = 114; pub const F_RDLCK: ::c_int = 1; pub const F_WRLCK: ::c_int = 2; pub const F_UNLCK: ::c_int = 3; pub const NCCS: usize = 40; pub const MAP_ANON: ::c_int = MAP_ANONYMOUS; pub const MAP_ANONYMOUS: ::c_int = 0x00080000; pub const MCL_CURRENT: ::c_int = 0x000000001; pub const MCL_FUTURE: ::c_int = 0x000000002; pub const _TIO_CBAUD: ::tcflag_t = 15; pub const CBAUD: ::tcflag_t = _TIO_CBAUD; pub const TAB1: ::tcflag_t = 0x0800; pub const TAB2: ::tcflag_t = 0x1000; pub const TAB3: ::tcflag_t = 0x1800; pub const CR1: ::tcflag_t = 0x200; pub const CR2: ::tcflag_t = 0x400; pub const CR3: ::tcflag_t = 0x600; pub const FF1: ::tcflag_t = 0x8000; pub const BS1: ::tcflag_t = 0x2000; pub const VT1: ::tcflag_t = 0x4000; pub const VWERASE: usize = 14; pub const VREPRINT: usize = 12; pub const VSUSP: usize = 10; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VDISCARD: usize = 13; pub const VTIME: usize = 17; pub const IXON: ::tcflag_t = 0x00000400; pub const IXOFF: ::tcflag_t = 0x00001000; pub const ONLCR: ::tcflag_t = 0x00000004; pub const CSIZE: ::tcflag_t = 0x00000030; pub const CS6: ::tcflag_t = 0x10; pub const CS7: ::tcflag_t = 0x20; pub const CS8: ::tcflag_t = 0x30; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00000800; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const ECHOCTL: ::tcflag_t = 0x00000200; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const OLCUC: ::tcflag_t = 0x00000002; pub const NLDLY: ::tcflag_t = 0x00000100; pub const CRDLY: ::tcflag_t = 0x00000600; pub const TABDLY: ::tcflag_t = 0x00001800; pub const BSDLY: ::tcflag_t = 0x00002000; pub const FFDLY: ::tcflag_t = 0x00008000; pub const VTDLY: ::tcflag_t = 0x00004000; pub const XTABS: ::tcflag_t = 0x1800; pub const B0: ::speed_t = 0; pub const B50: ::speed_t = 1; pub const B75: ::speed_t = 2; pub const B110: ::speed_t = 3; pub const B134: ::speed_t = 4; pub const B150: ::speed_t = 5; pub const B200: ::speed_t = 6; pub const B300: ::speed_t = 7; pub const B600: ::speed_t = 8; pub const B1200: ::speed_t = 9; pub const B1800: ::speed_t = 10; pub const B2400: ::speed_t = 11; pub const B4800: ::speed_t = 12; pub const B9600: ::speed_t = 13; pub const B19200: ::speed_t = 14; pub const B38400: ::speed_t = 15; pub const EXTA: ::speed_t = 14; pub const EXTB: ::speed_t = 15; pub const B57600: ::speed_t = 57600; pub const B115200: ::speed_t = 115200; pub const VEOL: usize = 5; pub const VEOL2: usize = 6; pub const VMIN: usize = 16; pub const IEXTEN: ::tcflag_t = 0x00008000; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const TCSANOW: ::c_int = 0x0001; pub const TCSADRAIN: ::c_int = 0x0002; pub const TCSAFLUSH: ::c_int = 0x0004; pub const HW_MACHINE: ::c_int = 1; pub const HW_MODEL: ::c_int = 2; pub const HW_NCPU: ::c_int = 3; pub const HW_BYTEORDER: ::c_int = 4; pub const HW_PHYSMEM: ::c_int = 5; pub const HW_USERMEM: ::c_int = 6; pub const HW_PAGESIZE: ::c_int = 7; pub const HW_DISKNAMES: ::c_int = 8; pub const HW_IOSTATS: ::c_int = 9; pub const HW_MACHINE_ARCH: ::c_int = 10; pub const HW_ALIGNBYTES: ::c_int = 11; pub const HW_CNMAGIC: ::c_int = 12; pub const HW_PHYSMEM64: ::c_int = 13; pub const HW_USERMEM64: ::c_int = 14; pub const HW_IOSTATNAMES: ::c_int = 15; pub const HW_MAXID: ::c_int = 15; pub const CTL_UNSPEC: ::c_int = 0; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_VFS: ::c_int = 3; pub const CTL_NET: ::c_int = 4; pub const CTL_DEBUG: ::c_int = 5; pub const CTL_HW: ::c_int = 6; pub const CTL_MACHDEP: ::c_int = 7; pub const CTL_USER: ::c_int = 8; pub const CTL_QNX: ::c_int = 9; pub const CTL_PROC: ::c_int = 10; pub const CTL_VENDOR: ::c_int = 11; pub const CTL_EMUL: ::c_int = 12; pub const CTL_SECURITY: ::c_int = 13; pub const CTL_MAXID: ::c_int = 14; pub const DAY_1: ::nl_item = 8; pub const DAY_2: ::nl_item = 9; pub const DAY_3: ::nl_item = 10; pub const DAY_4: ::nl_item = 11; pub const DAY_5: ::nl_item = 12; pub const DAY_6: ::nl_item = 13; pub const DAY_7: ::nl_item = 14; pub const MON_1: ::nl_item = 22; pub const MON_2: ::nl_item = 23; pub const MON_3: ::nl_item = 24; pub const MON_4: ::nl_item = 25; pub const MON_5: ::nl_item = 26; pub const MON_6: ::nl_item = 27; pub const MON_7: ::nl_item = 28; pub const MON_8: ::nl_item = 29; pub const MON_9: ::nl_item = 30; pub const MON_10: ::nl_item = 31; pub const MON_11: ::nl_item = 32; pub const MON_12: ::nl_item = 33; pub const ABDAY_1: ::nl_item = 15; pub const ABDAY_2: ::nl_item = 16; pub const ABDAY_3: ::nl_item = 17; pub const ABDAY_4: ::nl_item = 18; pub const ABDAY_5: ::nl_item = 19; pub const ABDAY_6: ::nl_item = 20; pub const ABDAY_7: ::nl_item = 21; pub const ABMON_1: ::nl_item = 34; pub const ABMON_2: ::nl_item = 35; pub const ABMON_3: ::nl_item = 36; pub const ABMON_4: ::nl_item = 37; pub const ABMON_5: ::nl_item = 38; pub const ABMON_6: ::nl_item = 39; pub const ABMON_7: ::nl_item = 40; pub const ABMON_8: ::nl_item = 41; pub const ABMON_9: ::nl_item = 42; pub const ABMON_10: ::nl_item = 43; pub const ABMON_11: ::nl_item = 44; pub const ABMON_12: ::nl_item = 45; pub const AF_ARP: ::c_int = 28; pub const AF_CCITT: ::c_int = 10; pub const AF_CHAOS: ::c_int = 5; pub const AF_CNT: ::c_int = 21; pub const AF_COIP: ::c_int = 20; pub const AF_DATAKIT: ::c_int = 9; pub const AF_DECnet: ::c_int = 12; pub const AF_DLI: ::c_int = 13; pub const AF_E164: ::c_int = 26; pub const AF_ECMA: ::c_int = 8; pub const AF_HYLINK: ::c_int = 15; pub const AF_IEEE80211: ::c_int = 32; pub const AF_IMPLINK: ::c_int = 3; pub const AF_ISO: ::c_int = 7; pub const AF_LAT: ::c_int = 14; pub const AF_LINK: ::c_int = 18; pub const AF_NATM: ::c_int = 27; pub const AF_NS: ::c_int = 6; pub const AF_OSI: ::c_int = 7; pub const AF_PUP: ::c_int = 4; pub const ALT_DIGITS: ::nl_item = 50; pub const AM_STR: ::nl_item = 6; pub const B76800: ::speed_t = 76800; pub const BIOCFLUSH: ::c_int = 17000; pub const BIOCGBLEN: ::c_int = 1074020966; pub const BIOCGDLT: ::c_int = 1074020970; pub const BIOCGDLTLIST: ::c_int = -1072676233; pub const BIOCGETIF: ::c_int = 1083196011; pub const BIOCGHDRCMPLT: ::c_int = 1074020980; pub const BIOCGRTIMEOUT: ::c_int = 1074807406; pub const BIOCGSEESENT: ::c_int = 1074020984; pub const BIOCGSTATS: ::c_int = 1082147439; pub const BIOCIMMEDIATE: ::c_int = -2147204496; pub const BIOCPROMISC: ::c_int = 17001; pub const BIOCSBLEN: ::c_int = -1073462682; pub const BIOCSDLT: ::c_int = -2147204490; pub const BIOCSETF: ::c_int = -2146418073; pub const BIOCSETIF: ::c_int = -2138029460; pub const BIOCSHDRCMPLT: ::c_int = -2147204491; pub const BIOCSRTIMEOUT: ::c_int = -2146418067; pub const BIOCSSEESENT: ::c_int = -2147204487; pub const BIOCVERSION: ::c_int = 1074020977; pub const BPF_ALIGNMENT: usize = ::mem::size_of::<::c_long>(); pub const CHAR_BIT: usize = 8; pub const CODESET: ::nl_item = 1; pub const CRNCYSTR: ::nl_item = 55; pub const D_FLAG_FILTER: ::c_int = 0x00000001; pub const D_FLAG_STAT: ::c_int = 0x00000002; pub const D_FLAG_STAT_FORM_MASK: ::c_int = 0x000000f0; pub const D_FLAG_STAT_FORM_T32_2001: ::c_int = 0x00000010; pub const D_FLAG_STAT_FORM_T32_2008: ::c_int = 0x00000020; pub const D_FLAG_STAT_FORM_T64_2008: ::c_int = 0x00000030; pub const D_FLAG_STAT_FORM_UNSET: ::c_int = 0x00000000; pub const D_FMT: ::nl_item = 3; pub const D_GETFLAG: ::c_int = 1; pub const D_SETFLAG: ::c_int = 2; pub const D_T_FMT: ::nl_item = 2; pub const ERA: ::nl_item = 46; pub const ERA_D_FMT: ::nl_item = 47; pub const ERA_D_T_FMT: ::nl_item = 48; pub const ERA_T_FMT: ::nl_item = 49; pub const RADIXCHAR: ::nl_item = 51; pub const THOUSEP: ::nl_item = 52; pub const YESEXPR: ::nl_item = 53; pub const NOEXPR: ::nl_item = 54; pub const F_GETOWN: ::c_int = 35; pub const FIONBIO: ::c_int = -2147195266; pub const FIOASYNC: ::c_int = -2147195267; pub const FIOCLEX: ::c_int = 26113; pub const FIOGETOWN: ::c_int = 1074030203; pub const FIONCLEX: ::c_int = 26114; pub const FIONREAD: ::c_int = 1074030207; pub const FIONSPACE: ::c_int = 1074030200; pub const FIONWRITE: ::c_int = 1074030201; pub const FIOSETOWN: ::c_int = -2147195268; pub const F_SETOWN: ::c_int = 36; pub const IFF_ACCEPTRTADV: ::c_int = 0x40000000; pub const IFF_IP6FORWARDING: ::c_int = 0x20000000; pub const IFF_LINK0: ::c_int = 0x00001000; pub const IFF_LINK1: ::c_int = 0x00002000; pub const IFF_LINK2: ::c_int = 0x00004000; pub const IFF_OACTIVE: ::c_int = 0x00000400; pub const IFF_SHIM: ::c_int = 0x80000000; pub const IFF_SIMPLEX: ::c_int = 0x00000800; pub const IHFLOW: tcflag_t = 0x00000001; pub const IIDLE: tcflag_t = 0x00000008; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_RECVIF: ::c_int = 20; pub const IPTOS_ECN_NOTECT: u8 = 0x00; pub const IUCLC: tcflag_t = 0x00000200; pub const IUTF8: tcflag_t = 0x0004000; pub const KERN_ARGMAX: ::c_int = 8; pub const KERN_ARND: ::c_int = 81; pub const KERN_BOOTTIME: ::c_int = 21; pub const KERN_CLOCKRATE: ::c_int = 12; pub const KERN_FILE: ::c_int = 15; pub const KERN_HOSTID: ::c_int = 11; pub const KERN_HOSTNAME: ::c_int = 10; pub const KERN_IOV_MAX: ::c_int = 38; pub const KERN_JOB_CONTROL: ::c_int = 19; pub const KERN_LOGSIGEXIT: ::c_int = 46; pub const KERN_MAXFILES: ::c_int = 7; pub const KERN_MAXID: ::c_int = 83; pub const KERN_MAXPROC: ::c_int = 6; pub const KERN_MAXVNODES: ::c_int = 5; pub const KERN_NGROUPS: ::c_int = 18; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_POSIX1: ::c_int = 17; pub const KERN_PROC: ::c_int = 14; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_ARGS: ::c_int = 48; pub const KERN_PROC_ENV: ::c_int = 3; pub const KERN_PROC_GID: ::c_int = 7; pub const KERN_PROC_PGRP: ::c_int = 2; pub const KERN_PROC_PID: ::c_int = 1; pub const KERN_PROC_RGID: ::c_int = 8; pub const KERN_PROC_RUID: ::c_int = 6; pub const KERN_PROC_SESSION: ::c_int = 3; pub const KERN_PROC_TTY: ::c_int = 4; pub const KERN_PROC_UID: ::c_int = 5; pub const KERN_PROF: ::c_int = 16; pub const KERN_SAVED_IDS: ::c_int = 20; pub const KERN_SECURELVL: ::c_int = 9; pub const KERN_VERSION: ::c_int = 4; pub const KERN_VNODE: ::c_int = 13; pub const LC_ALL: ::c_int = 63; pub const LC_COLLATE: ::c_int = 1; pub const LC_CTYPE: ::c_int = 2; pub const LC_MESSAGES: ::c_int = 32; pub const LC_MONETARY: ::c_int = 4; pub const LC_NUMERIC: ::c_int = 8; pub const LC_TIME: ::c_int = 16; pub const LOCAL_CONNWAIT: ::c_int = 0x0002; pub const LOCAL_CREDS: ::c_int = 0x0001; pub const LOCAL_PEEREID: ::c_int = 0x0003; pub const MAP_STACK: ::c_int = 0x00001000; pub const MNT_NOEXEC: ::c_int = 0x02; pub const MNT_NOSUID: ::c_int = 0x04; pub const MNT_RDONLY: ::c_int = 0x01; pub const MSG_NOTIFICATION: ::c_int = 0x0400; pub const NET_RT_DUMP: ::c_int = 1; pub const NET_RT_FLAGS: ::c_int = 2; pub const NET_RT_IFLIST: ::c_int = 4; pub const NI_NUMERICSCOPE: ::c_int = 0x00000040; pub const OHFLOW: tcflag_t = 0x00000002; pub const P_ALL: idtype_t = 0; pub const PARSTK: tcflag_t = 0x00000004; pub const PF_ARP: ::c_int = 28; pub const PF_CCITT: ::c_int = 10; pub const PF_CHAOS: ::c_int = 5; pub const PF_CNT: ::c_int = 21; pub const PF_COIP: ::c_int = 20; pub const PF_DATAKIT: ::c_int = 9; pub const PF_DECnet: ::c_int = 12; pub const PF_DLI: ::c_int = 13; pub const PF_ECMA: ::c_int = 8; pub const PF_HYLINK: ::c_int = 15; pub const PF_IMPLINK: ::c_int = 3; pub const PF_ISO: ::c_int = 7; pub const PF_LAT: ::c_int = 14; pub const PF_LINK: ::c_int = 18; pub const PF_NATM: ::c_int = 27; pub const PF_OSI: ::c_int = 7; pub const PF_PIP: ::c_int = 25; pub const PF_PUP: ::c_int = 4; pub const PF_RTIP: ::c_int = 22; pub const PF_XTP: ::c_int = 19; pub const PM_STR: ::nl_item = 7; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 2; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 1; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const _POSIX_VDISABLE: ::c_int = 0; pub const P_PGID: idtype_t = 2; pub const P_PID: idtype_t = 1; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_USER: ::c_int = 2; pub const pseudo_AF_HDRCMPLT: ::c_int = 30; pub const pseudo_AF_PIP: ::c_int = 25; pub const pseudo_AF_RTIP: ::c_int = 22; pub const pseudo_AF_XTP: ::c_int = 19; pub const REG_ASSERT: ::c_int = 15; pub const REG_ATOI: ::c_int = 255; pub const REG_BACKR: ::c_int = 0x400; pub const REG_BASIC: ::c_int = 0x00; pub const REG_DUMP: ::c_int = 0x80; pub const REG_EMPTY: ::c_int = 14; pub const REG_INVARG: ::c_int = 16; pub const REG_ITOA: ::c_int = 0o400; pub const REG_LARGE: ::c_int = 0x200; pub const REG_NOSPEC: ::c_int = 0x10; pub const REG_OK: ::c_int = 0; pub const REG_PEND: ::c_int = 0x20; pub const REG_TRACE: ::c_int = 0x100; pub const RLIMIT_AS: ::c_int = 6; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_MEMLOCK: ::c_int = 7; pub const RLIMIT_NOFILE: ::c_int = 5; pub const RLIMIT_NPROC: ::c_int = 8; pub const RLIMIT_RSS: ::c_int = 6; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_VMEM: ::c_int = 6; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 14; pub const SCHED_ADJTOHEAD: ::c_int = 5; pub const SCHED_ADJTOTAIL: ::c_int = 6; pub const SCHED_MAXPOLICY: ::c_int = 7; pub const SCHED_SETPRIO: ::c_int = 7; pub const SCHED_SPORADIC: ::c_int = 4; pub const SHM_ANON: *mut ::c_char = -1isize as *mut ::c_char; pub const SIGCLD: ::c_int = SIGCHLD; pub const SIGDEADLK: ::c_int = 7; pub const SIGEMT: ::c_int = 7; pub const SIGEV_NONE: ::c_int = 0; pub const SIGEV_SIGNAL: ::c_int = 129; pub const SIGEV_THREAD: ::c_int = 135; pub const SIOCGIFADDR: ::c_int = -1064277727; pub const SO_FIB: ::c_int = 0x100a; pub const SO_OVERFLOWED: ::c_int = 0x1009; pub const SO_SETFIB: ::c_int = 0x100a; pub const SO_TXPRIO: ::c_int = 0x100b; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_VLANPRIO: ::c_int = 0x100c; pub const _SS_ALIGNSIZE: usize = ::mem::size_of::(); pub const _SS_MAXSIZE: usize = 128; pub const _SS_PAD1SIZE: usize = _SS_ALIGNSIZE - 2; pub const _SS_PAD2SIZE: usize = _SS_MAXSIZE - 2 - _SS_PAD1SIZE - _SS_ALIGNSIZE; pub const TC_CPOSIX: tcflag_t = CLOCAL | CREAD | CSIZE | CSTOPB | HUPCL | PARENB | PARODD; pub const TCGETS: ::c_int = 0x404c540d; pub const TC_IPOSIX: tcflag_t = BRKINT | ICRNL | IGNBRK | IGNPAR | INLCR | INPCK | ISTRIP | IXOFF | IXON | PARMRK; pub const TC_LPOSIX: tcflag_t = ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN | ISIG | NOFLSH | TOSTOP; pub const TC_OPOSIX: tcflag_t = OPOST; pub const T_FMT_AMPM: ::nl_item = 5; pub const TIOCCBRK: ::c_int = 29818; pub const TIOCCDTR: ::c_int = 29816; pub const TIOCDRAIN: ::c_int = 29790; pub const TIOCEXCL: ::c_int = 29709; pub const TIOCFLUSH: ::c_int = -2147191792; pub const TIOCGETA: ::c_int = 1078752275; pub const TIOCGPGRP: ::c_int = 1074033783; pub const TIOCGWINSZ: ::c_int = 1074295912; pub const TIOCMBIC: ::c_int = -2147191701; pub const TIOCMBIS: ::c_int = -2147191700; pub const TIOCMGET: ::c_int = 1074033770; pub const TIOCMSET: ::c_int = -2147191699; pub const TIOCNOTTY: ::c_int = 29809; pub const TIOCNXCL: ::c_int = 29710; pub const TIOCOUTQ: ::c_int = 1074033779; pub const TIOCPKT: ::c_int = -2147191696; pub const TIOCPKT_DATA: ::c_int = 0x00; pub const TIOCPKT_DOSTOP: ::c_int = 0x20; pub const TIOCPKT_FLUSHREAD: ::c_int = 0x01; pub const TIOCPKT_FLUSHWRITE: ::c_int = 0x02; pub const TIOCPKT_IOCTL: ::c_int = 0x40; pub const TIOCPKT_NOSTOP: ::c_int = 0x10; pub const TIOCPKT_START: ::c_int = 0x08; pub const TIOCPKT_STOP: ::c_int = 0x04; pub const TIOCSBRK: ::c_int = 29819; pub const TIOCSCTTY: ::c_int = 29793; pub const TIOCSDTR: ::c_int = 29817; pub const TIOCSETA: ::c_int = -2142473196; pub const TIOCSETAF: ::c_int = -2142473194; pub const TIOCSETAW: ::c_int = -2142473195; pub const TIOCSPGRP: ::c_int = -2147191690; pub const TIOCSTART: ::c_int = 29806; pub const TIOCSTI: ::c_int = -2147388302; pub const TIOCSTOP: ::c_int = 29807; pub const TIOCSWINSZ: ::c_int = -2146929561; pub const USER_CS_PATH: ::c_int = 1; pub const USER_BC_BASE_MAX: ::c_int = 2; pub const USER_BC_DIM_MAX: ::c_int = 3; pub const USER_BC_SCALE_MAX: ::c_int = 4; pub const USER_BC_STRING_MAX: ::c_int = 5; pub const USER_COLL_WEIGHTS_MAX: ::c_int = 6; pub const USER_EXPR_NEST_MAX: ::c_int = 7; pub const USER_LINE_MAX: ::c_int = 8; pub const USER_RE_DUP_MAX: ::c_int = 9; pub const USER_POSIX2_VERSION: ::c_int = 10; pub const USER_POSIX2_C_BIND: ::c_int = 11; pub const USER_POSIX2_C_DEV: ::c_int = 12; pub const USER_POSIX2_CHAR_TERM: ::c_int = 13; pub const USER_POSIX2_FORT_DEV: ::c_int = 14; pub const USER_POSIX2_FORT_RUN: ::c_int = 15; pub const USER_POSIX2_LOCALEDEF: ::c_int = 16; pub const USER_POSIX2_SW_DEV: ::c_int = 17; pub const USER_POSIX2_UPE: ::c_int = 18; pub const USER_STREAM_MAX: ::c_int = 19; pub const USER_TZNAME_MAX: ::c_int = 20; pub const USER_ATEXIT_MAX: ::c_int = 21; pub const USER_MAXID: ::c_int = 22; pub const VDOWN: usize = 31; pub const VINS: usize = 32; pub const VDEL: usize = 33; pub const VRUB: usize = 34; pub const VCAN: usize = 35; pub const VHOME: usize = 36; pub const VEND: usize = 37; pub const VSPARE3: usize = 38; pub const VSPARE4: usize = 39; pub const VSWTCH: usize = 7; pub const VDSUSP: usize = 11; pub const VFWD: usize = 18; pub const VLOGIN: usize = 19; pub const VPREFIX: usize = 20; pub const VSUFFIX: usize = 24; pub const VLEFT: usize = 28; pub const VRIGHT: usize = 29; pub const VUP: usize = 30; pub const XCASE: tcflag_t = 0x00000004; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0x00; pub const PTHREAD_CREATE_DETACHED: ::c_int = 0x01; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 3; pub const PTHREAD_STACK_MIN: ::size_t = 256; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = 0; pub const PTHREAD_MUTEX_STALLED: ::c_int = 0x00; pub const PTHREAD_MUTEX_ROBUST: ::c_int = 0x10; pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0x00; pub const PTHREAD_PROCESS_SHARED: ::c_int = 0x01; pub const PTHREAD_KEYS_MAX: usize = 128; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __u: 0x80000000, __owner: 0xffffffff, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __u: CLOCK_REALTIME as u32, __owner: 0xfffffffb, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __active: 0, __blockedwriters: 0, __blockedreaders: 0, __heavy: 0, __lock: PTHREAD_MUTEX_INITIALIZER, __rcond: PTHREAD_COND_INITIALIZER, __wcond: PTHREAD_COND_INITIALIZER, __owner: -2i32 as ::c_uint, __spare: 0, }; const_fn! { {const} fn _CMSG_ALIGN(len: usize) -> usize { len + ::mem::size_of::() - 1 & !(::mem::size_of::() - 1) } {const} fn _ALIGN(p: usize, b: usize) -> usize { (p + b - 1) & !(b-1) } } f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= ::mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr) -> *mut ::cmsghdr { let msg = _CMSG_ALIGN((*cmsg).cmsg_len as usize); let next = cmsg as usize + msg + _CMSG_ALIGN(::mem::size_of::<::cmsghdr>()); if next > (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize { 0 as *mut ::cmsghdr } else { (cmsg as usize + msg) as *mut ::cmsghdr } } pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(_CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { _CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as ::c_uint + length } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_CMSG_ALIGN(::mem::size_of::()) + _CMSG_ALIGN(length as usize) ) as ::c_uint } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } pub fn _DEXTRA_FIRST(_d: *const dirent) -> *mut ::dirent_extra { let _f = &((*(_d)).d_name) as *const _; let _s = _d as usize; _ALIGN(_s + _f as usize - _s + (*_d).d_namelen as usize + 1, 8) as *mut ::dirent_extra } pub fn _DEXTRA_VALID(_x: *const ::dirent_extra, _d: *const dirent) -> bool { let sz = _x as usize - _d as usize + ::mem::size_of::<::dirent_extra>(); let rsz = (*_d).d_reclen as usize; if sz > rsz || sz + (*_x).d_datalen as usize > rsz { false } else { true } } pub fn _DEXTRA_NEXT(_x: *const ::dirent_extra) -> *mut ::dirent_extra { _ALIGN( _x as usize + ::mem::size_of::<::dirent_extra>() + (*_x).d_datalen as usize, 8 ) as *mut ::dirent_extra } pub fn SOCKCREDSIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; ::mem::size_of::() + ::mem::size_of::<::gid_t>() * ngrps } pub fn major(dev: ::dev_t) -> ::c_uint { ((dev as ::c_uint) >> 10) & 0x3f } pub fn minor(dev: ::dev_t) -> ::c_uint { (dev as ::c_uint) & 0x3ff } } safe_f! { pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { status & 0x7f } pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0x80) != 0 } pub {const} fn IPTOS_ECN(x: u8) -> u8 { x & ::IPTOS_ECN_MASK } pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { ((major << 10) | (minor)) as ::dev_t } } // Network related functions are provided by libsocket and regex // functions are provided by libregex. #[link(name = "socket")] #[link(name = "regex")] extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn mknodat( __fd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: ::dev_t, ) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_mutexattr_setpshared( attr: *mut pthread_mutexattr_t, pshared: ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> *mut ::c_char; pub fn clearenv() -> ::c_int; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; pub fn wait4( pid: ::pid_t, status: *mut ::c_int, options: ::c_int, rusage: *mut ::rusage, ) -> ::pid_t; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::c_int; pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::pid_t; pub fn login_tty(fd: ::c_int) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn getpeereid(socket: ::c_int, euid: *mut ::uid_t, egid: *mut ::gid_t) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut ::group; pub fn setspent(); pub fn endspent(); pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn pthread_setschedprio(native: ::pthread_t, priority: ::c_int) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn glob( pattern: *const c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn sync(); pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut ::sched_param, ) -> ::c_int; pub fn umount(target: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn settimeofday(tv: *const ::timeval, tz: *const ::c_void) -> ::c_int; pub fn sched_rr_get_interval(pid: ::pid_t, tp: *mut ::timespec) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn mount( special_device: *const ::c_char, mount_directory: *const ::c_char, flags: ::c_int, mount_type: *const ::c_char, mount_data: *const ::c_void, mount_datalen: ::c_int, ) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int; pub fn pthread_mutex_consistent(mutex: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_barrierattr_init(__attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_destroy(__attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_getpshared( __attr: *const ::pthread_barrierattr_t, __pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_barrierattr_setpshared( __attr: *mut ::pthread_barrierattr_t, __pshared: ::c_int, ) -> ::c_int; pub fn pthread_barrier_init( __barrier: *mut ::pthread_barrier_t, __attr: *const ::pthread_barrierattr_t, __count: ::c_uint, ) -> ::c_int; pub fn pthread_barrier_destroy(__barrier: *mut ::pthread_barrier_t) -> ::c_int; pub fn pthread_barrier_wait(__barrier: *mut ::pthread_barrier_t) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn getgrouplist( user: *const ::c_char, group: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_getrobust( attr: *const pthread_mutexattr_t, robustness: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setrobust( attr: *mut pthread_mutexattr_t, robustness: ::c_int, ) -> ::c_int; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn getitimer(which: ::c_int, curr_value: *mut ::itimerval) -> ::c_int; pub fn setitimer( which: ::c_int, value: *const ::itimerval, ovalue: *mut ::itimerval, ) -> ::c_int; pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, ) -> ::c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const ::sched_param, ) -> ::c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, newfd: ::c_int, ) -> ::c_int; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn inotify_rm_watch(fd: ::c_int, wd: ::c_int) -> ::c_int; pub fn inotify_init() -> ::c_int; pub fn inotify_add_watch(fd: ::c_int, path: *const ::c_char, mask: u32) -> ::c_int; pub fn gettid() -> ::pid_t; pub fn pthread_getcpuclockid(thread: ::pthread_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_uint, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_uint, timeout: *mut ::timespec, ) -> ::c_int; pub fn mallopt(param: ::c_int, value: i64) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn ctermid(s: *mut ::c_char) -> *mut ::c_char; pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; pub fn mallinfo() -> ::mallinfo; pub fn getpwent_r( pwd: *mut ::passwd, buf: *mut ::c_char, __bufsize: ::c_int, __result: *mut *mut ::passwd, ) -> ::c_int; pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::c_int) -> ::c_int; pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int; pub fn sysctl( _: *const ::c_int, _: ::c_uint, _: *mut ::c_void, _: *mut ::size_t, _: *const ::c_void, _: ::size_t, ) -> ::c_int; pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlp: *const ::rlimit) -> ::c_int; pub fn lio_listio( __mode: ::c_int, __list: *const *mut aiocb, __nent: ::c_int, __sig: *mut sigevent, ) -> ::c_int; pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *const dl_phdr_info, size: ::size_t, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; pub fn memset_s(s: *mut ::c_void, smax: ::size_t, c: ::c_int, n: ::size_t) -> ::c_int; pub fn regcomp( __preg: *mut ::regex_t, __pattern: *const ::c_char, __cflags: ::c_int, ) -> ::c_int; pub fn regexec( __preg: *const ::regex_t, __str: *const ::c_char, __nmatch: ::size_t, __pmatch: *mut ::regmatch_t, __eflags: ::c_int, ) -> ::c_int; pub fn regerror( __errcode: ::c_int, __preg: *const ::regex_t, __errbuf: *mut ::c_char, __errbuf_size: ::size_t, ) -> ::size_t; pub fn regfree(__preg: *mut ::regex_t); pub fn dirfd(__dirp: *mut ::DIR) -> ::c_int; pub fn dircntl(dir: *mut ::DIR, cmd: ::c_int, ...) -> ::c_int; pub fn aio_cancel(__fd: ::c_int, __aiocbp: *mut ::aiocb) -> ::c_int; pub fn aio_error(__aiocbp: *const ::aiocb) -> ::c_int; pub fn aio_fsync(__operation: ::c_int, __aiocbp: *mut ::aiocb) -> ::c_int; pub fn aio_read(__aiocbp: *mut ::aiocb) -> ::c_int; pub fn aio_return(__aiocpb: *mut ::aiocb) -> ::ssize_t; pub fn aio_suspend( __list: *const *const ::aiocb, __nent: ::c_int, __timeout: *const ::timespec, ) -> ::c_int; pub fn aio_write(__aiocpb: *mut ::aiocb) -> ::c_int; pub fn mq_close(__mqdes: ::mqd_t) -> ::c_int; pub fn mq_getattr(__mqdes: ::mqd_t, __mqstat: *mut ::mq_attr) -> ::c_int; pub fn mq_notify(__mqdes: ::mqd_t, __notification: *const ::sigevent) -> ::c_int; pub fn mq_open(__name: *const ::c_char, __oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_receive( __mqdes: ::mqd_t, __msg_ptr: *mut ::c_char, __msg_len: ::size_t, __msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_send( __mqdes: ::mqd_t, __msg_ptr: *const ::c_char, __msg_len: ::size_t, __msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_setattr( __mqdes: ::mqd_t, __mqstat: *const mq_attr, __omqstat: *mut mq_attr, ) -> ::c_int; pub fn mq_timedreceive( __mqdes: ::mqd_t, __msg_ptr: *mut ::c_char, __msg_len: ::size_t, __msg_prio: *mut ::c_uint, __abs_timeout: *const ::timespec, ) -> ::ssize_t; pub fn mq_timedsend( __mqdes: ::mqd_t, __msg_ptr: *const ::c_char, __msg_len: ::size_t, __msg_prio: ::c_uint, __abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_unlink(__name: *const ::c_char) -> ::c_int; pub fn __get_errno_ptr() -> *mut ::c_int; // System page, see https://www.qnx.com/developers/docs/7.1#com.qnx.doc.neutrino.building/topic/syspage/syspage_about.html pub static mut _syspage_ptr: *mut syspage_entry; // Function on the stack after a call to pthread_create(). This is used // as a sentinel to work around an infitnite loop in the unwinding code. pub fn __my_thread_exit(value_ptr: *mut *const ::c_void); } // Models the implementation in stdlib.h. Ctest will fail if trying to use the // default symbol from libc pub unsafe fn atexit(cb: extern "C" fn()) -> ::c_int { extern "C" { static __dso_handle: *mut ::c_void; pub fn __cxa_atexit( cb: extern "C" fn(), __arg: *mut ::c_void, __dso: *mut ::c_void, ) -> ::c_int; } __cxa_atexit(cb, 0 as *mut ::c_void, __dso_handle) } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { #[repr(C)] struct siginfo_si_addr { _pad: [u8; 32], si_addr: *mut ::c_void, } (*(self as *const siginfo_t as *const siginfo_si_addr)).si_addr } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_si_value { _pad: [u8; 32], si_value: ::sigval, } (*(self as *const siginfo_t as *const siginfo_si_value)).si_value } pub unsafe fn si_pid(&self) -> ::pid_t { #[repr(C)] struct siginfo_si_pid { _pad: [u8; 16], si_pid: ::pid_t, } (*(self as *const siginfo_t as *const siginfo_si_pid)).si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { #[repr(C)] struct siginfo_si_uid { _pad: [u8; 24], si_uid: ::uid_t, } (*(self as *const siginfo_t as *const siginfo_si_uid)).si_uid } pub unsafe fn si_status(&self) -> ::c_int { #[repr(C)] struct siginfo_si_status { _pad: [u8; 28], si_status: ::c_int, } (*(self as *const siginfo_t as *const siginfo_si_status)).si_status } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else { panic!("Unsupported arch"); } } mod neutrino; pub use self::neutrino::*; libc/src/unix/nto/aarch64.rs0000644000175000017500000000133214661133735016621 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type c_long = i64; pub type c_ulong = u64; pub type time_t = i64; s! { pub struct aarch64_qreg_t { pub qlo: u64, pub qhi: u64, } pub struct aarch64_fpu_registers { pub reg: [::aarch64_qreg_t; 32], pub fpsr: u32, pub fpcr: u32, } pub struct aarch64_cpu_registers { pub gpr: [u64; 32], pub elr: u64, pub pstate: u64, } #[repr(align(16))] pub struct mcontext_t { pub cpu: ::aarch64_cpu_registers, pub fpu: ::aarch64_fpu_registers, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } } libc/src/unix/mod.rs0000644000175000017500000017013014661133735015353 0ustar jamespagejamespage//! Definitions found commonly among almost all Unix derivatives //! //! More functions and definitions can be found in the more specific modules //! according to the platform in question. pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type pid_t = i32; pub type in_addr_t = u32; pub type in_port_t = u16; pub type sighandler_t = ::size_t; pub type cc_t = ::c_uchar; cfg_if! { if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))] { pub type uid_t = ::c_ushort; pub type gid_t = ::c_ushort; } else if #[cfg(target_os = "nto")] { pub type uid_t = i32; pub type gid_t = i32; } else { pub type uid_t = u32; pub type gid_t = u32; } } missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} } pub type locale_t = *mut ::c_void; s! { pub struct group { pub gr_name: *mut ::c_char, pub gr_passwd: *mut ::c_char, pub gr_gid: ::gid_t, pub gr_mem: *mut *mut ::c_char, } pub struct utimbuf { pub actime: time_t, pub modtime: time_t, } pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } // linux x32 compatibility // See https://sourceware.org/bugzilla/show_bug.cgi?id=16437 pub struct timespec { pub tv_sec: time_t, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] pub tv_nsec: i64, #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] pub tv_nsec: ::c_long, } pub struct rlimit { pub rlim_cur: rlim_t, pub rlim_max: rlim_t, } pub struct rusage { pub ru_utime: timeval, pub ru_stime: timeval, pub ru_maxrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad1: u32, pub ru_ixrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad2: u32, pub ru_idrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad3: u32, pub ru_isrss: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad4: u32, pub ru_minflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad5: u32, pub ru_majflt: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad6: u32, pub ru_nswap: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad7: u32, pub ru_inblock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad8: u32, pub ru_oublock: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad9: u32, pub ru_msgsnd: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad10: u32, pub ru_msgrcv: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad11: u32, pub ru_nsignals: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad12: u32, pub ru_nvcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad13: u32, pub ru_nivcsw: c_long, #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] __pad14: u32, #[cfg(any(target_env = "musl", target_env = "ohos", target_os = "emscripten"))] __reserved: [c_long; 16], } pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, #[cfg(target_os = "android")] pub ipv6mr_interface: ::c_int, #[cfg(not(target_os = "android"))] pub ipv6mr_interface: ::c_uint, } pub struct hostent { pub h_name: *mut ::c_char, pub h_aliases: *mut *mut ::c_char, pub h_addrtype: ::c_int, pub h_length: ::c_int, pub h_addr_list: *mut *mut ::c_char, } pub struct iovec { pub iov_base: *mut ::c_void, pub iov_len: ::size_t, } pub struct pollfd { pub fd: ::c_int, pub events: ::c_short, pub revents: ::c_short, } pub struct winsize { pub ws_row: ::c_ushort, pub ws_col: ::c_ushort, pub ws_xpixel: ::c_ushort, pub ws_ypixel: ::c_ushort, } pub struct linger { pub l_onoff: ::c_int, pub l_linger: ::c_int, } pub struct sigval { // Actually a union of an int and a void* pub sival_ptr: *mut ::c_void } // pub struct itimerval { pub it_interval: ::timeval, pub it_value: ::timeval, } // pub struct tms { pub tms_utime: ::clock_t, pub tms_stime: ::clock_t, pub tms_cutime: ::clock_t, pub tms_cstime: ::clock_t, } pub struct servent { pub s_name: *mut ::c_char, pub s_aliases: *mut *mut ::c_char, pub s_port: ::c_int, pub s_proto: *mut ::c_char, } pub struct protoent { pub p_name: *mut ::c_char, pub p_aliases: *mut *mut ::c_char, pub p_proto: ::c_int, } } pub const INT_MIN: c_int = -2147483648; pub const INT_MAX: c_int = 2147483647; pub const SIG_DFL: sighandler_t = 0 as sighandler_t; pub const SIG_IGN: sighandler_t = 1 as sighandler_t; pub const SIG_ERR: sighandler_t = !0 as sighandler_t; cfg_if! { if #[cfg(not(target_os = "nto"))] { pub const DT_UNKNOWN: u8 = 0; pub const DT_FIFO: u8 = 1; pub const DT_CHR: u8 = 2; pub const DT_DIR: u8 = 4; pub const DT_BLK: u8 = 6; pub const DT_REG: u8 = 8; pub const DT_LNK: u8 = 10; pub const DT_SOCK: u8 = 12; } } cfg_if! { if #[cfg(not(target_os = "redox"))] { pub const FD_CLOEXEC: ::c_int = 0x1; } } cfg_if! { if #[cfg(not(target_os = "nto"))] { pub const USRQUOTA: ::c_int = 0; pub const GRPQUOTA: ::c_int = 1; } } pub const SIGIOT: ::c_int = 6; pub const S_ISUID: ::mode_t = 0x800; pub const S_ISGID: ::mode_t = 0x400; pub const S_ISVTX: ::mode_t = 0x200; cfg_if! { if #[cfg(not(any(target_os = "haiku", target_os = "illumos", target_os = "solaris")))] { pub const IF_NAMESIZE: ::size_t = 16; pub const IFNAMSIZ: ::size_t = IF_NAMESIZE; } } pub const LOG_EMERG: ::c_int = 0; pub const LOG_ALERT: ::c_int = 1; pub const LOG_CRIT: ::c_int = 2; pub const LOG_ERR: ::c_int = 3; pub const LOG_WARNING: ::c_int = 4; pub const LOG_NOTICE: ::c_int = 5; pub const LOG_INFO: ::c_int = 6; pub const LOG_DEBUG: ::c_int = 7; pub const LOG_KERN: ::c_int = 0; pub const LOG_USER: ::c_int = 1 << 3; pub const LOG_MAIL: ::c_int = 2 << 3; pub const LOG_DAEMON: ::c_int = 3 << 3; pub const LOG_AUTH: ::c_int = 4 << 3; pub const LOG_SYSLOG: ::c_int = 5 << 3; pub const LOG_LPR: ::c_int = 6 << 3; pub const LOG_NEWS: ::c_int = 7 << 3; pub const LOG_UUCP: ::c_int = 8 << 3; pub const LOG_LOCAL0: ::c_int = 16 << 3; pub const LOG_LOCAL1: ::c_int = 17 << 3; pub const LOG_LOCAL2: ::c_int = 18 << 3; pub const LOG_LOCAL3: ::c_int = 19 << 3; pub const LOG_LOCAL4: ::c_int = 20 << 3; pub const LOG_LOCAL5: ::c_int = 21 << 3; pub const LOG_LOCAL6: ::c_int = 22 << 3; pub const LOG_LOCAL7: ::c_int = 23 << 3; cfg_if! { if #[cfg(not(target_os = "haiku"))] { pub const LOG_PID: ::c_int = 0x01; pub const LOG_CONS: ::c_int = 0x02; pub const LOG_ODELAY: ::c_int = 0x04; pub const LOG_NDELAY: ::c_int = 0x08; pub const LOG_NOWAIT: ::c_int = 0x10; } } pub const LOG_PRIMASK: ::c_int = 7; pub const LOG_FACMASK: ::c_int = 0x3f8; cfg_if! { if #[cfg(not(target_os = "nto"))] { pub const PRIO_MIN: ::c_int = -20; pub const PRIO_MAX: ::c_int = 20; } } pub const IPPROTO_ICMP: ::c_int = 1; pub const IPPROTO_ICMPV6: ::c_int = 58; pub const IPPROTO_TCP: ::c_int = 6; pub const IPPROTO_UDP: ::c_int = 17; pub const IPPROTO_IP: ::c_int = 0; pub const IPPROTO_IPV6: ::c_int = 41; pub const INADDR_LOOPBACK: in_addr_t = 2130706433; pub const INADDR_ANY: in_addr_t = 0; pub const INADDR_BROADCAST: in_addr_t = 4294967295; pub const INADDR_NONE: in_addr_t = 4294967295; pub const ARPOP_REQUEST: u16 = 1; pub const ARPOP_REPLY: u16 = 2; pub const ATF_COM: ::c_int = 0x02; pub const ATF_PERM: ::c_int = 0x04; pub const ATF_PUBL: ::c_int = 0x08; pub const ATF_USETRAILERS: ::c_int = 0x10; cfg_if! { if #[cfg(any(target_os = "l4re", target_os = "espidf"))] { // required libraries for L4Re and the ESP-IDF framework are linked externally, ATM } else if #[cfg(feature = "std")] { // cargo build, don't pull in anything extra as the std dep // already pulls in all libs. } else if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"), feature = "rustc-dep-of-std"))] { #[link(name = "util", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "rt", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "pthread", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "m", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "dl", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "gcc", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "util", cfg(not(target_feature = "crt-static")))] #[link(name = "rt", cfg(not(target_feature = "crt-static")))] #[link(name = "pthread", cfg(not(target_feature = "crt-static")))] #[link(name = "m", cfg(not(target_feature = "crt-static")))] #[link(name = "dl", cfg(not(target_feature = "crt-static")))] #[link(name = "c", cfg(not(target_feature = "crt-static")))] extern {} } else if #[cfg(any(target_env = "musl", target_env = "ohos"))] { #[cfg_attr(feature = "rustc-dep-of-std", link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static")))] #[cfg_attr(feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))))] extern {} } else if #[cfg(target_os = "emscripten")] { #[link(name = "c")] extern {} } else if #[cfg(all(target_os = "android", feature = "rustc-dep-of-std"))] { #[link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "m", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] #[link(name = "m", cfg(not(target_feature = "crt-static")))] #[link(name = "c", cfg(not(target_feature = "crt-static")))] extern {} } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "android", target_os = "openbsd", target_os = "nto", ))] { #[link(name = "c")] #[link(name = "m")] extern {} } else if #[cfg(target_os = "haiku")] { #[link(name = "root")] #[link(name = "network")] extern {} } else if #[cfg(target_env = "newlib")] { #[link(name = "c")] #[link(name = "m")] extern {} } else if #[cfg(target_env = "illumos")] { #[link(name = "c")] #[link(name = "m")] extern {} } else if #[cfg(target_os = "redox")] { #[cfg_attr(feature = "rustc-dep-of-std", link(name = "c", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static")))] #[cfg_attr(feature = "rustc-dep-of-std", link(name = "c", cfg(not(target_feature = "crt-static"))))] extern {} } else if #[cfg(target_env = "aix")] { #[link(name = "c")] #[link(name = "m")] #[link(name = "bsd")] #[link(name = "pthread")] extern {} } else { #[link(name = "c")] #[link(name = "m")] #[link(name = "rt")] #[link(name = "pthread")] extern {} } } missing! { #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME: fill this out with a struct } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn qsort( base: *mut c_void, num: size_t, size: size_t, compar: ::Option c_int>, ); pub fn bsearch( key: *const c_void, base: *const c_void, num: size_t, size: size_t, compar: ::Option c_int>, ) -> *mut c_void; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fopen$UNIX2003" )] pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "freopen$UNIX2003" )] pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fputs$UNIX2003" )] pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fwrite$UNIX2003" )] pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); #[cfg_attr(target_os = "netbsd", link_name = "__fgetpos50")] pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__fsetpos50")] pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn clearerr(stream: *mut FILE); pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "strtod$UNIX2003" )] pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn _exit(status: c_int) -> !; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "system$UNIX2003" )] pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn stpcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strndup(cs: *const c_char, n: size_t) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "strerror$UNIX2003" )] pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strtok_r(s: *mut c_char, t: *const c_char, p: *mut *mut c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn strsignal(sig: c_int) -> *mut c_char; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; } extern "C" { #[cfg_attr(target_os = "netbsd", link_name = "__getpwnam50")] pub fn getpwnam(name: *const ::c_char) -> *mut passwd; #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid50")] pub fn getpwuid(uid: ::uid_t) -> *mut passwd; pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_fscanf" )] pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_scanf" )] pub fn scanf(format: *const ::c_char, ...) -> ::c_int; #[cfg_attr( all(target_os = "linux", not(target_env = "uclibc")), link_name = "__isoc99_sscanf" )] pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr(target_os = "netbsd", link_name = "__socket30")] #[cfg_attr(target_os = "illumos", link_name = "__xnet_socket")] #[cfg_attr(target_os = "espidf", link_name = "lwip_socket")] pub fn socket(domain: ::c_int, ty: ::c_int, protocol: ::c_int) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "connect$UNIX2003" )] #[cfg_attr(target_os = "illumos", link_name = "__xnet_connect")] #[cfg_attr(target_os = "espidf", link_name = "lwip_connect")] pub fn connect(socket: ::c_int, address: *const sockaddr, len: socklen_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "listen$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_listen")] pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "accept$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_accept")] pub fn accept(socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getpeername$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_getpeername")] pub fn getpeername( socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t, ) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getsockname$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_getsockname")] pub fn getsockname( socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t, ) -> ::c_int; #[cfg_attr(target_os = "espidf", link_name = "lwip_setsockopt")] pub fn setsockopt( socket: ::c_int, level: ::c_int, name: ::c_int, value: *const ::c_void, option_len: socklen_t, ) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "socketpair$UNIX2003" )] #[cfg_attr(target_os = "illumos", link_name = "__xnet_socketpair")] pub fn socketpair( domain: ::c_int, type_: ::c_int, protocol: ::c_int, socket_vector: *mut ::c_int, ) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sendto$UNIX2003" )] #[cfg_attr(target_os = "illumos", link_name = "__xnet_sendto")] #[cfg_attr(target_os = "espidf", link_name = "lwip_sendto")] pub fn sendto( socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int, addr: *const sockaddr, addrlen: socklen_t, ) -> ::ssize_t; #[cfg_attr(target_os = "espidf", link_name = "lwip_shutdown")] pub fn shutdown(socket: ::c_int, how: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "chmod$UNIX2003" )] pub fn chmod(path: *const c_char, mode: mode_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fchmod$UNIX2003" )] pub fn fchmod(fd: ::c_int, mode: mode_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "fstat$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__fstat50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "fstat@FBSD_1.0" )] pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; pub fn mkdir(path: *const c_char, mode: mode_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "stat$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__stat50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "stat@FBSD_1.0" )] pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn pclose(stream: *mut ::FILE) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fdopen$UNIX2003" )] pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE; pub fn fileno(stream: *mut ::FILE) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "open$UNIX2003" )] pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "creat$UNIX2003" )] pub fn creat(path: *const c_char, mode: mode_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fcntl$UNIX2003" )] pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "opendir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "opendir$INODE64$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__opendir30")] pub fn opendir(dirname: *const c_char) -> *mut ::DIR; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "readdir$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__readdir30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "readdir@FBSD_1.0" )] pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "closedir$UNIX2003" )] pub fn closedir(dirp: *mut ::DIR) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "rewinddir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "rewinddir$INODE64$UNIX2003" )] pub fn rewinddir(dirp: *mut ::DIR); pub fn fchmodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, flags: ::c_int, ) -> ::c_int; pub fn fchown(fd: ::c_int, owner: ::uid_t, group: ::gid_t) -> ::c_int; pub fn fchownat( dirfd: ::c_int, pathname: *const ::c_char, owner: ::uid_t, group: ::gid_t, flags: ::c_int, ) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "fstatat$INODE64" )] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "fstatat@FBSD_1.1" )] pub fn fstatat( dirfd: ::c_int, pathname: *const ::c_char, buf: *mut stat, flags: ::c_int, ) -> ::c_int; pub fn linkat( olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, flags: ::c_int, ) -> ::c_int; pub fn renameat( olddirfd: ::c_int, oldpath: *const ::c_char, newdirfd: ::c_int, newpath: *const ::c_char, ) -> ::c_int; pub fn symlinkat( target: *const ::c_char, newdirfd: ::c_int, linkpath: *const ::c_char, ) -> ::c_int; pub fn unlinkat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; pub fn alarm(seconds: ::c_uint) -> ::c_uint; pub fn chdir(dir: *const c_char) -> ::c_int; pub fn fchdir(dirfd: ::c_int) -> ::c_int; pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "lchown$UNIX2003" )] pub fn lchown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "close$NOCANCEL$UNIX2003" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "close$NOCANCEL" )] pub fn close(fd: ::c_int) -> ::c_int; pub fn dup(fd: ::c_int) -> ::c_int; pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; pub fn execl(path: *const c_char, arg0: *const c_char, ...) -> ::c_int; pub fn execle(path: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; pub fn execlp(file: *const ::c_char, arg0: *const ::c_char, ...) -> ::c_int; pub fn execv(prog: *const c_char, argv: *const *const c_char) -> ::c_int; pub fn execve( prog: *const c_char, argv: *const *const c_char, envp: *const *const c_char, ) -> ::c_int; pub fn execvp(c: *const c_char, argv: *const *const c_char) -> ::c_int; pub fn fork() -> pid_t; pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long; pub fn getcwd(buf: *mut c_char, size: ::size_t) -> *mut c_char; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; pub fn getgid() -> gid_t; pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t) -> ::c_int; #[cfg_attr(target_os = "illumos", link_name = "getloginx")] pub fn getlogin() -> *mut c_char; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getopt$UNIX2003" )] pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn getpgid(pid: pid_t) -> pid_t; pub fn getpgrp() -> pid_t; pub fn getpid() -> pid_t; pub fn getppid() -> pid_t; pub fn getuid() -> uid_t; pub fn isatty(fd: ::c_int) -> ::c_int; pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int; pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; pub fn pipe(fds: *mut ::c_int) -> ::c_int; pub fn posix_memalign(memptr: *mut *mut ::c_void, align: ::size_t, size: ::size_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "read$UNIX2003" )] pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; pub fn rmdir(path: *const c_char) -> ::c_int; pub fn seteuid(uid: uid_t) -> ::c_int; pub fn setegid(gid: gid_t) -> ::c_int; pub fn setgid(gid: gid_t) -> ::c_int; pub fn setpgid(pid: pid_t, pgid: pid_t) -> ::c_int; pub fn setsid() -> pid_t; pub fn setuid(uid: uid_t) -> ::c_int; pub fn setreuid(ruid: uid_t, euid: uid_t) -> ::c_int; pub fn setregid(rgid: gid_t, egid: gid_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sleep$UNIX2003" )] pub fn sleep(secs: ::c_uint) -> ::c_uint; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "nanosleep$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__nanosleep50")] pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> ::c_int; pub fn tcgetpgrp(fd: ::c_int) -> pid_t; pub fn tcsetpgrp(fd: ::c_int, pgrp: ::pid_t) -> ::c_int; pub fn ttyname(fd: ::c_int) -> *mut c_char; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "ttyname_r$UNIX2003" )] #[cfg_attr(target_os = "illumos", link_name = "__posix_ttyname_r")] pub fn ttyname_r(fd: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn unlink(c: *const c_char) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "wait$UNIX2003" )] pub fn wait(status: *mut ::c_int) -> pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "waitpid$UNIX2003" )] pub fn waitpid(pid: pid_t, status: *mut ::c_int, options: ::c_int) -> pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "write$UNIX2003" )] pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pread$UNIX2003" )] pub fn pread(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pwrite$UNIX2003" )] pub fn pwrite(fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off_t) -> ::ssize_t; pub fn umask(mask: mode_t) -> mode_t; #[cfg_attr(target_os = "netbsd", link_name = "__utime50")] pub fn utime(file: *const c_char, buf: *const utimbuf) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "kill$UNIX2003" )] pub fn kill(pid: pid_t, sig: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "killpg$UNIX2003" )] pub fn killpg(pgrp: pid_t, sig: ::c_int) -> ::c_int; pub fn mlock(addr: *const ::c_void, len: ::size_t) -> ::c_int; pub fn munlock(addr: *const ::c_void, len: ::size_t) -> ::c_int; pub fn mlockall(flags: ::c_int) -> ::c_int; pub fn munlockall() -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "mmap$UNIX2003" )] pub fn mmap( addr: *mut ::c_void, len: ::size_t, prot: ::c_int, flags: ::c_int, fd: ::c_int, offset: off_t, ) -> *mut ::c_void; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "munmap$UNIX2003" )] pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int; pub fn if_nametoindex(ifname: *const c_char) -> ::c_uint; pub fn if_indextoname(ifindex: ::c_uint, ifname: *mut ::c_char) -> *mut ::c_char; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "lstat$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__lstat50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "lstat@FBSD_1.0" )] pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "fsync$UNIX2003" )] pub fn fsync(fd: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "setenv$UNIX2003" )] pub fn setenv(name: *const c_char, val: *const c_char, overwrite: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "unsetenv$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__unsetenv13")] pub fn unsetenv(name: *const c_char) -> ::c_int; pub fn symlink(path1: *const c_char, path2: *const c_char) -> ::c_int; pub fn truncate(path: *const c_char, length: off_t) -> ::c_int; pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; pub fn signal(signum: ::c_int, handler: sighandler_t) -> sighandler_t; #[cfg_attr(target_os = "netbsd", link_name = "__getrusage50")] pub fn getrusage(resource: ::c_int, usage: *mut rusage) -> ::c_int; #[cfg_attr( any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos" ), link_name = "realpath$DARWIN_EXTSN" )] pub fn realpath(pathname: *const ::c_char, resolved: *mut ::c_char) -> *mut ::c_char; pub fn flock(fd: ::c_int, operation: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__times13")] pub fn times(buf: *mut ::tms) -> ::clock_t; pub fn pthread_self() -> ::pthread_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_join$UNIX2003" )] pub fn pthread_join(native: ::pthread_t, value: *mut *mut ::c_void) -> ::c_int; pub fn pthread_exit(value: *mut ::c_void) -> !; pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_destroy(attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getstacksize( attr: *const ::pthread_attr_t, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setstacksize(attr: *mut ::pthread_attr_t, stack_size: ::size_t) -> ::c_int; pub fn pthread_attr_setdetachstate(attr: *mut ::pthread_attr_t, state: ::c_int) -> ::c_int; pub fn pthread_detach(thread: ::pthread_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__libc_thr_yield")] pub fn sched_yield() -> ::c_int; pub fn pthread_key_create( key: *mut pthread_key_t, dtor: ::Option, ) -> ::c_int; pub fn pthread_key_delete(key: pthread_key_t) -> ::c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut ::c_void; pub fn pthread_setspecific(key: pthread_key_t, value: *const ::c_void) -> ::c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> ::c_int; pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> ::c_int; pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_mutexattr_destroy$UNIX2003" )] pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> ::c_int; pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_init$UNIX2003" )] pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_wait$UNIX2003" )] pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cond_timedwait$UNIX2003" )] pub fn pthread_cond_timedwait( cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> ::c_int; pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> ::c_int; pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> ::c_int; pub fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> ::c_int; pub fn pthread_condattr_destroy(attr: *mut pthread_condattr_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_init$UNIX2003" )] pub fn pthread_rwlock_init( lock: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t, ) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_destroy$UNIX2003" )] pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_rdlock$UNIX2003" )] pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_tryrdlock$UNIX2003" )] pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_wrlock$UNIX2003" )] pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_trywrlock$UNIX2003" )] pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_rwlock_unlock$UNIX2003" )] pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> ::c_int; pub fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> ::c_int; pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> ::c_int; #[cfg_attr(target_os = "illumos", link_name = "__xnet_getsockopt")] #[cfg_attr(target_os = "espidf", link_name = "lwip_getsockopt")] pub fn getsockopt( sockfd: ::c_int, level: ::c_int, optname: ::c_int, optval: *mut ::c_void, optlen: *mut ::socklen_t, ) -> ::c_int; pub fn raise(signum: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__utimes50")] pub fn utimes(filename: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn dlopen(filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; pub fn dlerror() -> *mut ::c_char; pub fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void; pub fn dlclose(handle: *mut ::c_void) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr(target_os = "illumos", link_name = "__xnet_getaddrinfo")] #[cfg_attr(target_os = "espidf", link_name = "lwip_getaddrinfo")] pub fn getaddrinfo( node: *const c_char, service: *const c_char, hints: *const addrinfo, res: *mut *mut addrinfo, ) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr(target_os = "espidf", link_name = "lwip_freeaddrinfo")] pub fn freeaddrinfo(res: *mut addrinfo); pub fn hstrerror(errcode: ::c_int) -> *const ::c_char; pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char; #[cfg_attr( any( all( target_os = "linux", not(any(target_env = "musl", target_env = "ohos")) ), target_os = "freebsd", target_os = "dragonfly", target_os = "haiku" ), link_name = "__res_init" )] #[cfg_attr( any( target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos" ), link_name = "res_9_init" )] pub fn res_init() -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__gmtime_r50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__localtime_r50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "mktime$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__mktime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn mktime(tm: *mut tm) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__time50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn time(time: *mut time_t) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__gmtime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn gmtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__locatime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn localtime(time_p: *const time_t) -> *mut tm; #[cfg_attr(target_os = "netbsd", link_name = "__difftime50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn difftime(time1: time_t, time0: time_t) -> ::c_double; #[cfg_attr(target_os = "netbsd", link_name = "__timegm50")] #[cfg_attr(any(target_env = "musl", target_env = "ohos"), allow(deprecated))] // FIXME: for `time_t` pub fn timegm(tm: *mut ::tm) -> time_t; #[cfg_attr(target_os = "netbsd", link_name = "__mknod50")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "mknod@FBSD_1.0" )] pub fn mknod(pathname: *const ::c_char, mode: ::mode_t, dev: ::dev_t) -> ::c_int; pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn endservent(); pub fn getservbyname(name: *const ::c_char, proto: *const ::c_char) -> *mut servent; pub fn getservbyport(port: ::c_int, proto: *const ::c_char) -> *mut servent; pub fn getservent() -> *mut servent; pub fn setservent(stayopen: ::c_int); pub fn getprotobyname(name: *const ::c_char) -> *mut protoent; pub fn getprotobynumber(proto: ::c_int) -> *mut protoent; pub fn chroot(name: *const ::c_char) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "usleep$UNIX2003" )] pub fn usleep(secs: ::c_uint) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "send$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_send")] pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recv$UNIX2003" )] #[cfg_attr(target_os = "espidf", link_name = "lwip_recv")] pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "putenv$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__putenv50")] pub fn putenv(string: *mut c_char) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "poll$UNIX2003" )] pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "select$1050" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "select$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__select50")] pub fn select( nfds: ::c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *mut timeval, ) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__setlocale50")] pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; pub fn localeconv() -> *mut lconv; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sem_wait$UNIX2003" )] pub fn sem_wait(sem: *mut sem_t) -> ::c_int; pub fn sem_trywait(sem: *mut sem_t) -> ::c_int; pub fn sem_post(sem: *mut sem_t) -> ::c_int; pub fn statvfs(path: *const c_char, buf: *mut statvfs) -> ::c_int; pub fn fstatvfs(fd: ::c_int, buf: *mut statvfs) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] pub fn sigemptyset(set: *mut sigset_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] pub fn sigaddset(set: *mut sigset_t, signum: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigfillset14")] pub fn sigfillset(set: *mut sigset_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigdelset14")] pub fn sigdelset(set: *mut sigset_t, signum: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigismember14")] pub fn sigismember(set: *const sigset_t, signum: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigprocmask14")] pub fn sigprocmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigpending14")] pub fn sigpending(set: *mut sigset_t) -> ::c_int; pub fn sysconf(name: ::c_int) -> ::c_long; pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int; pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "tcdrain$UNIX2003" )] pub fn tcdrain(fd: ::c_int) -> ::c_int; pub fn cfgetispeed(termios: *const ::termios) -> ::speed_t; pub fn cfgetospeed(termios: *const ::termios) -> ::speed_t; pub fn cfsetispeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn cfsetospeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; pub fn tcgetattr(fd: ::c_int, termios: *mut ::termios) -> ::c_int; pub fn tcsetattr(fd: ::c_int, optional_actions: ::c_int, termios: *const ::termios) -> ::c_int; pub fn tcflow(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcflush(fd: ::c_int, action: ::c_int) -> ::c_int; pub fn tcgetsid(fd: ::c_int) -> ::pid_t; pub fn tcsendbreak(fd: ::c_int, duration: ::c_int) -> ::c_int; pub fn mkstemp(template: *mut ::c_char) -> ::c_int; pub fn mkdtemp(template: *mut ::c_char) -> *mut ::c_char; pub fn tmpnam(ptr: *mut ::c_char) -> *mut ::c_char; pub fn openlog(ident: *const ::c_char, logopt: ::c_int, facility: ::c_int); pub fn closelog(); pub fn setlogmask(maskpri: ::c_int) -> ::c_int; #[cfg_attr(target_os = "macos", link_name = "syslog$DARWIN_EXTSN")] pub fn syslog(priority: ::c_int, message: *const ::c_char, ...); #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "nice$UNIX2003" )] pub fn nice(incr: ::c_int) -> ::c_int; pub fn grantpt(fd: ::c_int) -> ::c_int; pub fn posix_openpt(flags: ::c_int) -> ::c_int; pub fn ptsname(fd: ::c_int) -> *mut ::c_char; pub fn unlockpt(fd: ::c_int) -> ::c_int; pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; pub fn lockf(fd: ::c_int, cmd: ::c_int, len: ::off_t) -> ::c_int; } cfg_if! { if #[cfg(not(any(target_os = "emscripten", target_os = "android", target_os = "haiku", target_os = "nto")))] { extern "C" { pub fn adjtime(delta: *const timeval, olddelta: *mut timeval) -> ::c_int; } } } cfg_if! { if #[cfg(not(any(target_os = "emscripten", target_os = "android", target_os = "nto")))] { extern "C" { pub fn stpncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; } } } cfg_if! { if #[cfg(not(target_os = "aix"))] { extern "C" { pub fn dladdr(addr: *const ::c_void, info: *mut Dl_info) -> ::c_int; } } } cfg_if! { if #[cfg(not(any(target_env = "uclibc", target_os = "nto")))] { extern "C" { pub fn open_wmemstream( ptr: *mut *mut wchar_t, sizeloc: *mut size_t, ) -> *mut FILE; } } } cfg_if! { if #[cfg(not(target_os = "redox"))] { extern { pub fn getsid(pid: pid_t) -> pid_t; #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "pause$UNIX2003")] pub fn pause() -> ::c_int; pub fn mkdirat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn openat(dirfd: ::c_int, pathname: *const ::c_char, flags: ::c_int, ...) -> ::c_int; #[cfg_attr(all(target_os = "macos", target_arch = "x86_64"), link_name = "fdopendir$INODE64")] #[cfg_attr(all(target_os = "macos", target_arch = "x86"), link_name = "fdopendir$INODE64$UNIX2003")] pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; #[cfg_attr(all(target_os = "macos", not(target_arch = "aarch64")), link_name = "readdir_r$INODE64")] #[cfg_attr(target_os = "netbsd", link_name = "__readdir_r30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "readdir_r@FBSD_1.0" )] #[allow(non_autolinks)] // FIXME: `<>` breaks line length limit. /// The 64-bit libc on Solaris and illumos only has readdir_r. If a /// 32-bit Solaris or illumos target is ever created, it should use /// __posix_readdir_r. See libc(3LIB) on Solaris or illumos: /// https://illumos.org/man/3lib/libc /// https://docs.oracle.com/cd/E36784_01/html/E36873/libc-3lib.html /// https://www.unix.com/man-page/opensolaris/3LIB/libc/ pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) -> ::c_int; } } } cfg_if! { if #[cfg(target_os = "nto")] { extern { pub fn readlinkat(dirfd: ::c_int, pathname: *const ::c_char, buf: *mut ::c_char, bufsiz: ::size_t) -> ::c_int; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::c_int; pub fn pselect( nfds: ::c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *mut timespec, sigmask: *const sigset_t, ) -> ::c_int; pub fn sigaction( signum: ::c_int, act: *const sigaction, oldact: *mut sigaction ) -> ::c_int; } } else { extern { pub fn readlinkat(dirfd: ::c_int, pathname: *const ::c_char, buf: *mut ::c_char, bufsiz: ::size_t) -> ::ssize_t; pub fn fmemopen(buf: *mut c_void, size: size_t, mode: *const c_char) -> *mut FILE; pub fn open_memstream(ptr: *mut *mut c_char, sizeloc: *mut size_t) -> *mut FILE; pub fn atexit(cb: extern "C" fn()) -> c_int; #[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")] pub fn sigaction( signum: ::c_int, act: *const sigaction, oldact: *mut sigaction ) -> ::c_int; pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: ::size_t) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "pselect$1050" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pselect$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__pselect50")] pub fn pselect( nfds: ::c_int, readfds: *mut fd_set, writefds: *mut fd_set, errorfds: *mut fd_set, timeout: *const timespec, sigmask: *const sigset_t, ) -> ::c_int; } } } cfg_if! { if #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto", )))] { extern { pub fn cfmakeraw(termios: *mut ::termios); pub fn cfsetspeed(termios: *mut ::termios, speed: ::speed_t) -> ::c_int; } } } cfg_if! { if #[cfg(target_env = "newlib")] { mod newlib; pub use self::newlib::*; } else if #[cfg(any(target_os = "linux", target_os = "l4re", target_os = "android", target_os = "emscripten"))] { mod linux_like; pub use self::linux_like::*; } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd"))] { mod bsd; pub use self::bsd::*; } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] { mod solarish; pub use self::solarish::*; } else if #[cfg(target_os = "haiku")] { mod haiku; pub use self::haiku::*; } else if #[cfg(target_os = "redox")] { mod redox; pub use self::redox::*; } else if #[cfg(target_os = "nto")] { mod nto; pub use self::nto::*; } else if #[cfg(target_os = "aix")] { mod aix; pub use self::aix::*; } else if #[cfg(target_os = "hurd")] { mod hurd; pub use self::hurd::*; } else { // Unknown target_os } } cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } else { mod no_align; pub use self::no_align::*; } } libc/src/unix/hurd/0000775000175000017500000000000014661133735015170 5ustar jamespagejamespagelibc/src/unix/hurd/b32.rs0000644000175000017500000000504114661133735016122 0ustar jamespagejamespagepub type c_long = i32; pub type c_ulong = u32; pub type __int64_t = ::c_longlong; pub type __uint64_t = ::c_ulonglong; pub type int_fast16_t = ::c_int; pub type int_fast32_t = ::c_int; pub type int_fast64_t = ::c_longlong; pub type uint_fast16_t = ::c_uint; pub type uint_fast32_t = ::c_uint; pub type uint_fast64_t = ::c_ulonglong; pub type __quad_t = ::c_longlong; pub type __u_quad_t = ::c_ulonglong; pub type __intmax_t = ::c_longlong; pub type __uintmax_t = ::c_ulonglong; pub type __squad_type = ::__int64_t; pub type __uquad_type = ::__uint64_t; pub type __sword_type = ::c_int; pub type __uword_type = ::c_uint; pub type __slong32_type = ::c_long; pub type __ulong32_type = ::c_ulong; pub type __s64_type = ::__int64_t; pub type __u64_type = ::__uint64_t; pub type __ipc_pid_t = ::c_ushort; pub type Elf32_Half = u16; pub type Elf32_Word = u32; pub type Elf32_Off = u32; pub type Elf32_Addr = u32; pub type Elf32_Section = u16; pub type Elf_Addr = ::Elf32_Addr; pub type Elf_Half = ::Elf32_Half; pub type Elf_Ehdr = ::Elf32_Ehdr; pub type Elf_Phdr = ::Elf32_Phdr; pub type Elf_Shdr = ::Elf32_Shdr; pub type Elf_Sym = ::Elf32_Sym; s! { pub struct Elf32_Ehdr { pub e_ident: [::c_uchar; 16], pub e_type: Elf32_Half, pub e_machine: Elf32_Half, pub e_version: Elf32_Word, pub e_entry: Elf32_Addr, pub e_phoff: Elf32_Off, pub e_shoff: Elf32_Off, pub e_flags: Elf32_Word, pub e_ehsize: Elf32_Half, pub e_phentsize: Elf32_Half, pub e_phnum: Elf32_Half, pub e_shentsize: Elf32_Half, pub e_shnum: Elf32_Half, pub e_shstrndx: Elf32_Half, } pub struct Elf32_Shdr { pub sh_name: Elf32_Word, pub sh_type: Elf32_Word, pub sh_flags: Elf32_Word, pub sh_addr: Elf32_Addr, pub sh_offset: Elf32_Off, pub sh_size: Elf32_Word, pub sh_link: Elf32_Word, pub sh_info: Elf32_Word, pub sh_addralign: Elf32_Word, pub sh_entsize: Elf32_Word, } pub struct Elf32_Sym { pub st_name: Elf32_Word, pub st_value: Elf32_Addr, pub st_size: Elf32_Word, pub st_info: ::c_uchar, pub st_other: ::c_uchar, pub st_shndx: Elf32_Section, } pub struct Elf32_Phdr { pub p_type: ::Elf32_Word, pub p_offset: ::Elf32_Off, pub p_vaddr: ::Elf32_Addr, pub p_paddr: ::Elf32_Addr, pub p_filesz: ::Elf32_Word, pub p_memsz: ::Elf32_Word, pub p_flags: ::Elf32_Word, pub p_align: ::Elf32_Word, } } libc/src/unix/hurd/mod.rs0000644000175000017500000046306714661133735016333 0ustar jamespagejamespage#![allow(dead_code)] // types pub type c_char = i8; pub type __s16_type = ::c_short; pub type __u16_type = ::c_ushort; pub type __s32_type = ::c_int; pub type __u32_type = ::c_uint; pub type __slongword_type = ::c_long; pub type __ulongword_type = ::c_ulong; pub type __u_char = ::c_uchar; pub type __u_short = ::c_ushort; pub type __u_int = ::c_uint; pub type __u_long = ::c_ulong; pub type __int8_t = ::c_schar; pub type __uint8_t = ::c_uchar; pub type __int16_t = ::c_short; pub type __uint16_t = ::c_ushort; pub type __int32_t = ::c_int; pub type __uint32_t = ::c_uint; pub type __int_least8_t = __int8_t; pub type __uint_least8_t = __uint8_t; pub type __int_least16_t = __int16_t; pub type __uint_least16_t = __uint16_t; pub type __int_least32_t = __int32_t; pub type __uint_least32_t = __uint32_t; pub type __int_least64_t = __int64_t; pub type __uint_least64_t = __uint64_t; pub type __dev_t = __uword_type; pub type __uid_t = __u32_type; pub type __gid_t = __u32_type; pub type __ino_t = __ulongword_type; pub type __ino64_t = __uquad_type; pub type __mode_t = __u32_type; pub type __nlink_t = __uword_type; pub type __off_t = __slongword_type; pub type __off64_t = __squad_type; pub type __pid_t = __s32_type; pub type __rlim_t = __ulongword_type; pub type __rlim64_t = __uquad_type; pub type __blkcnt_t = __slongword_type; pub type __blkcnt64_t = __squad_type; pub type __fsblkcnt_t = __ulongword_type; pub type __fsblkcnt64_t = __uquad_type; pub type __fsfilcnt_t = __ulongword_type; pub type __fsfilcnt64_t = __uquad_type; pub type __fsword_t = __sword_type; pub type __id_t = __u32_type; pub type __clock_t = __slongword_type; pub type __time_t = __slongword_type; pub type __useconds_t = __u32_type; pub type __suseconds_t = __slongword_type; pub type __suseconds64_t = __squad_type; pub type __daddr_t = __s32_type; pub type __key_t = __s32_type; pub type __clockid_t = __s32_type; pub type __timer_t = __uword_type; pub type __blksize_t = __slongword_type; pub type __fsid_t = __uquad_type; pub type __ssize_t = __sword_type; pub type __syscall_slong_t = __slongword_type; pub type __syscall_ulong_t = __ulongword_type; pub type __cpu_mask = __ulongword_type; pub type __loff_t = __off64_t; pub type __caddr_t = *mut ::c_char; pub type __intptr_t = __sword_type; pub type __ptrdiff_t = __sword_type; pub type __socklen_t = __u32_type; pub type __sig_atomic_t = ::c_int; pub type __time64_t = __int64_t; pub type ssize_t = __ssize_t; pub type size_t = ::c_ulong; pub type wchar_t = ::c_int; pub type wint_t = ::c_uint; pub type gid_t = __gid_t; pub type uid_t = __uid_t; pub type off_t = __off_t; pub type off64_t = __off64_t; pub type useconds_t = __useconds_t; pub type pid_t = __pid_t; pub type socklen_t = __socklen_t; pub type in_addr_t = u32; pub type _Float32 = f32; pub type _Float64 = f64; pub type _Float32x = f64; pub type _Float64x = f64; pub type __locale_t = *mut __locale_struct; pub type locale_t = __locale_t; pub type u_char = __u_char; pub type u_short = __u_short; pub type u_int = __u_int; pub type u_long = __u_long; pub type quad_t = __quad_t; pub type u_quad_t = __u_quad_t; pub type fsid_t = __fsid_t; pub type loff_t = __loff_t; pub type ino_t = __ino_t; pub type ino64_t = __ino64_t; pub type dev_t = __dev_t; pub type mode_t = __mode_t; pub type nlink_t = __nlink_t; pub type id_t = __id_t; pub type daddr_t = __daddr_t; pub type caddr_t = __caddr_t; pub type key_t = __key_t; pub type clock_t = __clock_t; pub type clockid_t = __clockid_t; pub type time_t = __time_t; pub type timer_t = __timer_t; pub type suseconds_t = __suseconds_t; pub type ulong = ::c_ulong; pub type ushort = ::c_ushort; pub type uint = ::c_uint; pub type u_int8_t = __uint8_t; pub type u_int16_t = __uint16_t; pub type u_int32_t = __uint32_t; pub type u_int64_t = __uint64_t; pub type register_t = ::c_int; pub type __sigset_t = ::c_ulong; pub type sigset_t = __sigset_t; pub type __fd_mask = ::c_long; pub type fd_mask = __fd_mask; pub type blksize_t = __blksize_t; pub type blkcnt_t = __blkcnt_t; pub type fsblkcnt_t = __fsblkcnt_t; pub type fsfilcnt_t = __fsfilcnt_t; pub type blkcnt64_t = __blkcnt64_t; pub type fsblkcnt64_t = __fsblkcnt64_t; pub type fsfilcnt64_t = __fsfilcnt64_t; pub type __pthread_spinlock_t = ::c_int; pub type __tss_t = ::c_int; pub type __thrd_t = ::c_long; pub type __pthread_t = ::c_long; pub type pthread_t = __pthread_t; pub type __pthread_process_shared = ::c_uint; pub type __pthread_inheritsched = ::c_uint; pub type __pthread_contentionscope = ::c_uint; pub type __pthread_detachstate = ::c_uint; pub type pthread_attr_t = __pthread_attr; pub type __pthread_mutex_protocol = ::c_uint; pub type __pthread_mutex_type = ::c_uint; pub type __pthread_mutex_robustness = ::c_uint; pub type pthread_mutexattr_t = __pthread_mutexattr; pub type pthread_mutex_t = __pthread_mutex; pub type pthread_condattr_t = __pthread_condattr; pub type pthread_cond_t = __pthread_cond; pub type pthread_spinlock_t = __pthread_spinlock_t; pub type pthread_rwlockattr_t = __pthread_rwlockattr; pub type pthread_rwlock_t = __pthread_rwlock; pub type pthread_barrierattr_t = __pthread_barrierattr; pub type pthread_barrier_t = __pthread_barrier; pub type __pthread_key = ::c_int; pub type pthread_key_t = __pthread_key; pub type pthread_once_t = __pthread_once; pub type __rlimit_resource = ::c_uint; pub type __rlimit_resource_t = __rlimit_resource; pub type rlim_t = __rlim_t; pub type rlim64_t = __rlim64_t; pub type __rusage_who = ::c_int; pub type __priority_which = ::c_uint; pub type sa_family_t = ::c_uchar; pub type in_port_t = u16; pub type __sigval_t = ::sigval; pub type sigevent_t = sigevent; pub type nfds_t = ::c_ulong; pub type tcflag_t = ::c_uint; pub type cc_t = ::c_uchar; pub type speed_t = ::c_int; pub type sigval_t = ::sigval; pub type greg_t = ::c_int; pub type gregset_t = [greg_t; 19usize]; pub type __ioctl_dir = ::c_uint; pub type __ioctl_datum = ::c_uint; pub type __error_t_codes = ::c_int; pub type int_least8_t = __int_least8_t; pub type int_least16_t = __int_least16_t; pub type int_least32_t = __int_least32_t; pub type int_least64_t = __int_least64_t; pub type uint_least8_t = __uint_least8_t; pub type uint_least16_t = __uint_least16_t; pub type uint_least32_t = __uint_least32_t; pub type uint_least64_t = __uint_least64_t; pub type int_fast8_t = ::c_schar; pub type uint_fast8_t = ::c_uchar; pub type intmax_t = __intmax_t; pub type uintmax_t = __uintmax_t; pub type tcp_seq = u32; pub type tcp_ca_state = ::c_uint; pub type idtype_t = ::c_uint; pub type mqd_t = ::c_int; pub type Lmid_t = ::c_long; pub type regoff_t = ::c_int; pub type nl_item = ::c_int; pub type iconv_t = *mut ::c_void; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos64_t {} // FIXME: fill this out with a struct impl ::Copy for fpos64_t {} impl ::Clone for fpos64_t { fn clone(&self) -> fpos64_t { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } // structs s! { pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, pub imr_sourceaddr: in_addr, } pub struct sockaddr { pub sa_len: ::c_uchar, pub sa_family: sa_family_t, pub sa_data: [::c_char; 14usize], } pub struct in_addr { pub s_addr: in_addr_t, } pub struct sockaddr_in { pub sin_len: ::c_uchar, pub sin_family: sa_family_t, pub sin_port: in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [::c_uchar; 8usize], } pub struct sockaddr_in6 { pub sin6_len: ::c_uchar, pub sin6_family: sa_family_t, pub sin6_port: in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_un { pub sun_len: ::c_uchar, pub sun_family: sa_family_t, pub sun_path: [::c_char; 108usize], } pub struct sockaddr_storage { pub ss_len: ::c_uchar, pub ss_family: sa_family_t, pub __ss_padding: [::c_char; 122usize], pub __ss_align: __uint32_t, } pub struct sockaddr_at { pub _address: u8, } pub struct sockaddr_ax25 { pub _address: u8, } pub struct sockaddr_x25 { pub _address: u8, } pub struct sockaddr_dl { pub _address: u8, } pub struct sockaddr_eon { pub _address: u8, } pub struct sockaddr_inarp { pub _address: u8, } pub struct sockaddr_ipx { pub _address: u8, } pub struct sockaddr_iso { pub _address: u8, } pub struct sockaddr_ns { pub _address: u8, } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: socklen_t, pub ai_addr: *mut sockaddr, pub ai_canonname: *mut ::c_char, pub ai_next: *mut addrinfo, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct dirent { pub d_ino: __ino_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_namlen: ::c_uchar, pub d_name: [::c_char; 1usize], } pub struct dirent64 { pub d_ino: __ino64_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_namlen: ::c_uchar, pub d_name: [::c_char; 1usize], } pub struct fd_set { pub fds_bits: [__fd_mask; 8usize], } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_cc: [::cc_t; 20usize], pub __ispeed: ::speed_t, pub __ospeed: ::speed_t, } pub struct mallinfo { pub arena: ::c_int, pub ordblks: ::c_int, pub smblks: ::c_int, pub hblks: ::c_int, pub hblkhd: ::c_int, pub usmblks: ::c_int, pub fsmblks: ::c_int, pub uordblks: ::c_int, pub fordblks: ::c_int, pub keepcost: ::c_int, } pub struct mallinfo2 { pub arena: ::size_t, pub ordblks: ::size_t, pub smblks: ::size_t, pub hblks: ::size_t, pub hblkhd: ::size_t, pub usmblks: ::size_t, pub fsmblks: ::size_t, pub uordblks: ::size_t, pub fordblks: ::size_t, pub keepcost: ::size_t, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: __sigset_t, pub sa_flags: ::c_int, } pub struct sigevent { pub sigev_value: ::sigval, pub sigev_signo: ::c_int, pub sigev_notify: ::c_int, __unused1: *mut ::c_void, //actually a function pointer pub sigev_notify_attributes: *mut pthread_attr_t, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub si_pid: __pid_t, pub si_uid: __uid_t, pub si_addr: *mut ::c_void, pub si_status: ::c_int, pub si_band: ::c_long, pub si_value: ::sigval, } pub struct timespec { pub tv_sec: __time_t, pub tv_nsec: __syscall_slong_t, } pub struct __locale_data { pub _address: u8, } pub struct stat { pub st_fstype: ::c_int, pub st_dev: __fsid_t, /* Actually st_fsid */ pub st_ino: __ino_t, pub st_gen: ::c_uint, pub st_rdev: __dev_t, pub st_mode: __mode_t, pub st_nlink: __nlink_t, pub st_uid: __uid_t, pub st_gid: __gid_t, pub st_size: __off_t, pub st_atim: ::timespec, pub st_mtim: ::timespec, pub st_ctim: ::timespec, pub st_blksize: __blksize_t, pub st_blocks: __blkcnt_t, pub st_author: __uid_t, pub st_flags: ::c_uint, pub st_spare: [::c_int; 11usize], } pub struct stat64 { pub st_fstype: ::c_int, pub st_fsid: __fsid_t, pub st_ino: __ino64_t, pub st_gen: ::c_uint, pub st_rdev: __dev_t, pub st_mode: __mode_t, pub st_nlink: __nlink_t, pub st_uid: __uid_t, pub st_gid: __gid_t, pub st_size: __off64_t, pub st_atim: ::timespec, pub st_mtim: ::timespec, pub st_ctim: ::timespec, pub st_blksize: __blksize_t, pub st_blocks: __blkcnt64_t, pub st_author: __uid_t, pub st_flags: ::c_uint, pub st_spare: [::c_int; 8usize], } pub struct statx { pub stx_mask: u32, pub stx_blksize: u32, pub stx_attributes: u64, pub stx_nlink: u32, pub stx_uid: u32, pub stx_gid: u32, pub stx_mode: u16, __statx_pad1: [u16; 1], pub stx_ino: u64, pub stx_size: u64, pub stx_blocks: u64, pub stx_attributes_mask: u64, pub stx_atime: ::statx_timestamp, pub stx_btime: ::statx_timestamp, pub stx_ctime: ::statx_timestamp, pub stx_mtime: ::statx_timestamp, pub stx_rdev_major: u32, pub stx_rdev_minor: u32, pub stx_dev_major: u32, pub stx_dev_minor: u32, __statx_pad2: [u64; 14], } pub struct statx_timestamp { pub tv_sec: i64, pub tv_nsec: u32, pub __statx_timestamp_pad1: [i32; 1], } pub struct statfs { pub f_type: ::c_uint, pub f_bsize: ::c_ulong, pub f_blocks: __fsblkcnt_t, pub f_bfree: __fsblkcnt_t, pub f_bavail: __fsblkcnt_t, pub f_files: __fsblkcnt_t, pub f_ffree: __fsblkcnt_t, pub f_fsid: __fsid_t, pub f_namelen: ::c_ulong, pub f_favail: __fsfilcnt_t, pub f_frsize: ::c_ulong, pub f_flag: ::c_ulong, pub f_spare: [::c_uint; 3usize], } pub struct statfs64 { pub f_type: ::c_uint, pub f_bsize: ::c_ulong, pub f_blocks: __fsblkcnt64_t, pub f_bfree: __fsblkcnt64_t, pub f_bavail: __fsblkcnt64_t, pub f_files: __fsblkcnt64_t, pub f_ffree: __fsblkcnt64_t, pub f_fsid: __fsid_t, pub f_namelen: ::c_ulong, pub f_favail: __fsfilcnt64_t, pub f_frsize: ::c_ulong, pub f_flag: ::c_ulong, pub f_spare: [::c_uint ; 3usize], } pub struct statvfs { pub __f_type: ::c_uint, pub f_bsize: ::c_ulong, pub f_blocks: __fsblkcnt_t, pub f_bfree: __fsblkcnt_t, pub f_bavail: __fsblkcnt_t, pub f_files: __fsfilcnt_t, pub f_ffree: __fsfilcnt_t, pub f_fsid: __fsid_t, pub f_namemax: ::c_ulong, pub f_favail: __fsfilcnt_t, pub f_frsize: ::c_ulong, pub f_flag: ::c_ulong, pub f_spare: [::c_uint; 3usize], } pub struct statvfs64 { pub __f_type: ::c_uint, pub f_bsize: ::c_ulong, pub f_blocks: __fsblkcnt64_t, pub f_bfree: __fsblkcnt64_t, pub f_bavail: __fsblkcnt64_t, pub f_files: __fsfilcnt64_t, pub f_ffree: __fsfilcnt64_t, pub f_fsid: __fsid_t, pub f_namemax: ::c_ulong, pub f_favail: __fsfilcnt64_t, pub f_frsize: ::c_ulong, pub f_flag: ::c_ulong, pub f_spare: [::c_uint; 3usize], } pub struct aiocb { pub aio_fildes: ::c_int, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_sigevent: ::sigevent, __next_prio: *mut aiocb, __abs_prio: ::c_int, __policy: ::c_int, __error_code: ::c_int, __return_value: ::ssize_t, pub aio_offset: off_t, #[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))] __unused1: [::c_char; 4], __glibc_reserved: [::c_char; 32] } pub struct mq_attr { pub mq_flags: ::c_long, pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, } pub struct __exit_status { pub e_termination: ::c_short, pub e_exit: ::c_short, } #[cfg_attr(target_pointer_width = "32", repr(align(4)))] #[cfg_attr(target_pointer_width = "64", repr(align(8)))] pub struct sem_t { __size: [::c_char; 20usize], } pub struct __pthread { pub _address: u8, } pub struct __pthread_mutexattr { pub __prioceiling: ::c_int, pub __protocol: __pthread_mutex_protocol, pub __pshared: __pthread_process_shared, pub __mutex_type: __pthread_mutex_type, } pub struct __pthread_mutex { pub __lock: ::c_uint, pub __owner_id: ::c_uint, pub __cnt: ::c_uint, pub __shpid: ::c_int, pub __type: ::c_int, pub __flags: ::c_int, pub __reserved1: ::c_uint, pub __reserved2: ::c_uint, } pub struct __pthread_condattr { pub __pshared: __pthread_process_shared, pub __clock: __clockid_t, } pub struct __pthread_rwlockattr { pub __pshared: __pthread_process_shared, } pub struct __pthread_barrierattr { pub __pshared: __pthread_process_shared, } pub struct __pthread_once { pub __run: ::c_int, pub __lock: __pthread_spinlock_t, } pub struct __pthread_cond { pub __lock: __pthread_spinlock_t, pub __queue: *mut __pthread, pub __attr: *mut __pthread_condattr, pub __wrefs: ::c_uint, pub __data: *mut ::c_void, } pub struct __pthread_attr { pub __schedparam: sched_param, pub __stackaddr: *mut ::c_void, pub __stacksize: size_t, pub __guardsize: size_t, pub __detachstate: __pthread_detachstate, pub __inheritsched: __pthread_inheritsched, pub __contentionscope: __pthread_contentionscope, pub __schedpolicy: ::c_int, } pub struct __pthread_rwlock { pub __held: __pthread_spinlock_t, pub __lock: __pthread_spinlock_t, pub __readers: ::c_int, pub __readerqueue: *mut __pthread, pub __writerqueue: *mut __pthread, pub __attr: *mut __pthread_rwlockattr, pub __data: *mut ::c_void, } pub struct __pthread_barrier { pub __lock: __pthread_spinlock_t, pub __queue: *mut __pthread, pub __pending: ::c_uint, pub __count: ::c_uint, pub __attr: *mut __pthread_barrierattr, pub __data: *mut ::c_void, } pub struct seminfo { pub semmap: ::c_int, pub semmni: ::c_int, pub semmns: ::c_int, pub semmnu: ::c_int, pub semmsl: ::c_int, pub semopm: ::c_int, pub semume: ::c_int, pub semusz: ::c_int, pub semvmx: ::c_int, pub semaem: ::c_int, } pub struct _IO_FILE { _unused: [u8; 0], } pub struct sched_param { pub sched_priority: ::c_int, } pub struct iovec { pub iov_base: *mut ::c_void, pub iov_len: size_t, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: __uid_t, pub pw_gid: __gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct spwd { pub sp_namp: *mut ::c_char, pub sp_pwdp: *mut ::c_char, pub sp_lstchg: ::c_long, pub sp_min: ::c_long, pub sp_max: ::c_long, pub sp_warn: ::c_long, pub sp_inact: ::c_long, pub sp_expire: ::c_long, pub sp_flag: ::c_ulong, } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, pub tm_gmtoff: ::c_long, pub tm_zone: *const ::c_char, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut c_char, pub ifa_flags: ::c_uint, pub ifa_addr: *mut ::sockaddr, pub ifa_netmask: *mut ::sockaddr, pub ifa_ifu: *mut ::sockaddr, // FIXME This should be a union pub ifa_data: *mut ::c_void } pub struct arpreq { pub arp_pa: ::sockaddr, pub arp_ha: ::sockaddr, pub arp_flags: ::c_int, pub arp_netmask: ::sockaddr, pub arp_dev: [::c_char; 16], } pub struct arpreq_old { pub arp_pa: ::sockaddr, pub arp_ha: ::sockaddr, pub arp_flags: ::c_int, pub arp_netmask: ::sockaddr, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct arpd_request { pub req: ::c_ushort, pub ip: u32, pub dev: ::c_ulong, pub stamp: ::c_ulong, pub updated: ::c_ulong, pub ha: [::c_uchar; ::MAX_ADDR_LEN], } pub struct mmsghdr { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } pub struct ifreq { /// interface name, e.g. "en0" pub ifr_name: [::c_char; ::IFNAMSIZ], pub ifr_ifru: ::sockaddr, } pub struct __locale_struct { pub __locales: [*mut __locale_data; 13usize], pub __ctype_b: *const ::c_ushort, pub __ctype_tolower: *const ::c_int, pub __ctype_toupper: *const ::c_int, pub __names: [*const ::c_char; 13usize], } pub struct utsname { pub sysname: [::c_char; 65], pub nodename: [::c_char; 65], pub release: [::c_char; 65], pub version: [::c_char; 65], pub machine: [::c_char; 65], pub domainname: [::c_char; 65] } pub struct rlimit64 { pub rlim_cur: rlim64_t, pub rlim_max: rlim64_t, } pub struct stack_t { pub ss_sp: * mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, pub dlpi_adds: ::c_ulonglong, pub dlpi_subs: ::c_ulonglong, pub dlpi_tls_modid: ::size_t, pub dlpi_tls_data: *mut ::c_void, } pub struct flock { #[cfg(target_pointer_width = "32")] pub l_type : ::c_int, #[cfg(target_pointer_width = "32")] pub l_whence : ::c_int, #[cfg(target_pointer_width = "64")] pub l_type : ::c_short, #[cfg(target_pointer_width = "64")] pub l_whence : ::c_short, pub l_start : __off_t, pub l_len : __off_t, pub l_pid : __pid_t, } pub struct flock64 { #[cfg(target_pointer_width = "32")] pub l_type : ::c_int, #[cfg(target_pointer_width = "32")] pub l_whence : ::c_int, #[cfg(target_pointer_width = "64")] pub l_type : ::c_short, #[cfg(target_pointer_width = "64")] pub l_whence : ::c_short, pub l_start : __off_t, pub l_len : __off64_t, pub l_pid : __pid_t, } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct glob64_t { pub gl_pathc: ::size_t, pub gl_pathv: *mut *mut ::c_char, pub gl_offs: ::size_t, pub gl_flags: ::c_int, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, } pub struct regex_t { __buffer: *mut ::c_void, __allocated: ::size_t, __used: ::size_t, __syntax: ::c_ulong, __fastmap: *mut ::c_char, __translate: *mut ::c_char, __re_nsub: ::size_t, __bitfield: u8, } pub struct cpu_set_t { #[cfg(all(target_pointer_width = "32", not(target_arch = "x86_64")))] bits: [u32; 32], #[cfg(not(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] bits: [u64; 16], } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } // System V IPC pub struct msginfo { pub msgpool: ::c_int, pub msgmap: ::c_int, pub msgmax: ::c_int, pub msgmnb: ::c_int, pub msgmni: ::c_int, pub msgssz: ::c_int, pub msgtql: ::c_int, pub msgseg: ::c_ushort, } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct mntent { pub mnt_fsname: *mut ::c_char, pub mnt_dir: *mut ::c_char, pub mnt_type: *mut ::c_char, pub mnt_opts: *mut ::c_char, pub mnt_freq: ::c_int, pub mnt_passno: ::c_int, } pub struct posix_spawn_file_actions_t { __allocated: ::c_int, __used: ::c_int, __actions: *mut ::c_int, __pad: [::c_int; 16], } pub struct posix_spawnattr_t { __flags: ::c_short, __pgrp: ::pid_t, __sd: ::sigset_t, __ss: ::sigset_t, __sp: ::sched_param, __policy: ::c_int, __pad: [::c_int; 16], } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct option { pub name: *const ::c_char, pub has_arg: ::c_int, pub flag: *mut ::c_int, pub val: ::c_int, } } s_no_extra_traits! { pub struct utmpx { pub ut_type: ::c_short, pub ut_pid: ::pid_t, pub ut_line: [::c_char; __UT_LINESIZE], pub ut_id: [::c_char; 4], pub ut_user: [::c_char; __UT_NAMESIZE], pub ut_host: [::c_char; __UT_HOSTSIZE], pub ut_exit: __exit_status, #[cfg(any( all(target_pointer_width = "32", not(target_arch = "x86_64"))))] pub ut_session: ::c_long, #[cfg(any(all(target_pointer_width = "32", not(target_arch = "x86_64"))))] pub ut_tv: ::timeval, #[cfg(not(any(all(target_pointer_width = "32", not(target_arch = "x86_64")))))] pub ut_session: i32, #[cfg(not(any(all(target_pointer_width = "32", not(target_arch = "x86_64")))))] pub ut_tv: __timeval, pub ut_addr_v6: [i32; 4], __glibc_reserved: [::c_char; 20], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_user == other.ut_user && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_addr_v6 == other.ut_addr_v6 && self.__glibc_reserved == other.__glibc_reserved } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_line", &self.ut_line) .field("ut_id", &self.ut_id) .field("ut_user", &self.ut_user) // FIXME: .field("ut_host", &self.ut_host) .field("ut_exit", &self.ut_exit) .field("ut_session", &self.ut_session) .field("ut_tv", &self.ut_tv) .field("ut_addr_v6", &self.ut_addr_v6) .field("__glibc_reserved", &self.__glibc_reserved) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_user.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_addr_v6.hash(state); self.__glibc_reserved.hash(state); } } } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { self.si_addr } pub unsafe fn si_value(&self) -> ::sigval { self.si_value } pub unsafe fn si_pid(&self) -> ::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.si_status } } // const // aio.h pub const AIO_CANCELED: ::c_int = 0; pub const AIO_NOTCANCELED: ::c_int = 1; pub const AIO_ALLDONE: ::c_int = 2; pub const LIO_READ: ::c_int = 0; pub const LIO_WRITE: ::c_int = 1; pub const LIO_NOP: ::c_int = 2; pub const LIO_WAIT: ::c_int = 0; pub const LIO_NOWAIT: ::c_int = 1; // glob.h pub const GLOB_ERR: ::c_int = 1 << 0; pub const GLOB_MARK: ::c_int = 1 << 1; pub const GLOB_NOSORT: ::c_int = 1 << 2; pub const GLOB_DOOFFS: ::c_int = 1 << 3; pub const GLOB_NOCHECK: ::c_int = 1 << 4; pub const GLOB_APPEND: ::c_int = 1 << 5; pub const GLOB_NOESCAPE: ::c_int = 1 << 6; pub const GLOB_NOSPACE: ::c_int = 1; pub const GLOB_ABORTED: ::c_int = 2; pub const GLOB_NOMATCH: ::c_int = 3; pub const GLOB_PERIOD: ::c_int = 1 << 7; pub const GLOB_ALTDIRFUNC: ::c_int = 1 << 9; pub const GLOB_BRACE: ::c_int = 1 << 10; pub const GLOB_NOMAGIC: ::c_int = 1 << 11; pub const GLOB_TILDE: ::c_int = 1 << 12; pub const GLOB_ONLYDIR: ::c_int = 1 << 13; pub const GLOB_TILDE_CHECK: ::c_int = 1 << 14; // ipc.h pub const IPC_PRIVATE: ::key_t = 0; pub const IPC_CREAT: ::c_int = 0o1000; pub const IPC_EXCL: ::c_int = 0o2000; pub const IPC_NOWAIT: ::c_int = 0o4000; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const IPC_INFO: ::c_int = 3; pub const MSG_STAT: ::c_int = 11; pub const MSG_INFO: ::c_int = 12; pub const MSG_NOERROR: ::c_int = 0o10000; pub const MSG_EXCEPT: ::c_int = 0o20000; // shm.h pub const SHM_R: ::c_int = 0o400; pub const SHM_W: ::c_int = 0o200; pub const SHM_RDONLY: ::c_int = 0o10000; pub const SHM_RND: ::c_int = 0o20000; pub const SHM_REMAP: ::c_int = 0o40000; pub const SHM_LOCK: ::c_int = 11; pub const SHM_UNLOCK: ::c_int = 12; // unistd.h pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const __FD_SETSIZE: usize = 256; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const F_OK: ::c_int = 0; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const SEEK_DATA: ::c_int = 3; pub const SEEK_HOLE: ::c_int = 4; pub const L_SET: ::c_int = 0; pub const L_INCR: ::c_int = 1; pub const L_XTND: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const F_LOCK: ::c_int = 1; pub const F_TLOCK: ::c_int = 2; pub const F_TEST: ::c_int = 3; pub const CLOSE_RANGE_CLOEXEC: ::c_int = 4; // stdio.h pub const EOF: ::c_int = -1; // stdlib.h pub const WNOHANG: ::c_int = 1; pub const WUNTRACED: ::c_int = 2; pub const WSTOPPED: ::c_int = 2; pub const WCONTINUED: ::c_int = 4; pub const WNOWAIT: ::c_int = 8; pub const WEXITED: ::c_int = 16; pub const __W_CONTINUED: ::c_int = 65535; pub const __WCOREFLAG: ::c_int = 128; pub const RAND_MAX: ::c_int = 2147483647; pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const __LITTLE_ENDIAN: usize = 1234; pub const __BIG_ENDIAN: usize = 4321; pub const __PDP_ENDIAN: usize = 3412; pub const __BYTE_ORDER: usize = 1234; pub const __FLOAT_WORD_ORDER: usize = 1234; pub const LITTLE_ENDIAN: usize = 1234; pub const BIG_ENDIAN: usize = 4321; pub const PDP_ENDIAN: usize = 3412; pub const BYTE_ORDER: usize = 1234; // sys/select.h pub const FD_SETSIZE: usize = 256; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 32; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 32; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 28; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 24; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 16; pub const __SIZEOF_PTHREAD_COND_T: usize = 20; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_ONCE_T: usize = 8; pub const __PTHREAD_SPIN_LOCK_INITIALIZER: ::c_int = 0; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; // sys/resource.h pub const RLIM_INFINITY: ::rlim_t = 2147483647; pub const RLIM64_INFINITY: ::rlim64_t = 9223372036854775807; pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY; pub const PRIO_MIN: ::c_int = -20; pub const PRIO_MAX: ::c_int = 20; // pwd.h pub const NSS_BUFLEN_PASSWD: usize = 1024; // sys/socket.h pub const SOCK_TYPE_MASK: usize = 15; pub const PF_UNSPEC: ::c_int = 0; pub const PF_LOCAL: ::c_int = 1; pub const PF_UNIX: ::c_int = 1; pub const PF_FILE: ::c_int = 1; pub const PF_INET: ::c_int = 2; pub const PF_IMPLINK: ::c_int = 3; pub const PF_PUP: ::c_int = 4; pub const PF_CHAOS: ::c_int = 5; pub const PF_NS: ::c_int = 6; pub const PF_ISO: ::c_int = 7; pub const PF_OSI: ::c_int = 7; pub const PF_ECMA: ::c_int = 8; pub const PF_DATAKIT: ::c_int = 9; pub const PF_CCITT: ::c_int = 10; pub const PF_SNA: ::c_int = 11; pub const PF_DECnet: ::c_int = 12; pub const PF_DLI: ::c_int = 13; pub const PF_LAT: ::c_int = 14; pub const PF_HYLINK: ::c_int = 15; pub const PF_APPLETALK: ::c_int = 16; pub const PF_ROUTE: ::c_int = 17; pub const PF_XTP: ::c_int = 19; pub const PF_COIP: ::c_int = 20; pub const PF_CNT: ::c_int = 21; pub const PF_RTIP: ::c_int = 22; pub const PF_IPX: ::c_int = 23; pub const PF_SIP: ::c_int = 24; pub const PF_PIP: ::c_int = 25; pub const PF_INET6: ::c_int = 26; pub const PF_MAX: ::c_int = 27; pub const AF_UNSPEC: ::c_int = 0; pub const AF_LOCAL: ::c_int = 1; pub const AF_UNIX: ::c_int = 1; pub const AF_FILE: ::c_int = 1; pub const AF_INET: ::c_int = 2; pub const AF_IMPLINK: ::c_int = 3; pub const AF_PUP: ::c_int = 4; pub const AF_CHAOS: ::c_int = 5; pub const AF_NS: ::c_int = 6; pub const AF_ISO: ::c_int = 7; pub const AF_OSI: ::c_int = 7; pub const AF_ECMA: ::c_int = 8; pub const AF_DATAKIT: ::c_int = 9; pub const AF_CCITT: ::c_int = 10; pub const AF_SNA: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_DLI: ::c_int = 13; pub const AF_LAT: ::c_int = 14; pub const AF_HYLINK: ::c_int = 15; pub const AF_APPLETALK: ::c_int = 16; pub const AF_ROUTE: ::c_int = 17; pub const pseudo_AF_XTP: ::c_int = 19; pub const AF_COIP: ::c_int = 20; pub const AF_CNT: ::c_int = 21; pub const pseudo_AF_RTIP: ::c_int = 22; pub const AF_IPX: ::c_int = 23; pub const AF_SIP: ::c_int = 24; pub const pseudo_AF_PIP: ::c_int = 25; pub const AF_INET6: ::c_int = 26; pub const AF_MAX: ::c_int = 27; pub const SOMAXCONN: ::c_int = 4096; pub const _SS_SIZE: usize = 128; pub const CMGROUP_MAX: usize = 16; pub const SOL_SOCKET: ::c_int = 65535; // sys/time.h pub const ITIMER_REAL: ::c_int = 0; pub const ITIMER_VIRTUAL: ::c_int = 1; pub const ITIMER_PROF: ::c_int = 2; // netinet/in.h pub const SOL_IP: ::c_int = 0; pub const SOL_TCP: ::c_int = 6; pub const SOL_UDP: ::c_int = 17; pub const SOL_IPV6: ::c_int = 41; pub const SOL_ICMPV6: ::c_int = 58; pub const IP_OPTIONS: ::c_int = 1; pub const IP_HDRINCL: ::c_int = 2; pub const IP_TOS: ::c_int = 3; pub const IP_TTL: ::c_int = 4; pub const IP_RECVOPTS: ::c_int = 5; pub const IP_RECVRETOPTS: ::c_int = 6; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_RETOPTS: ::c_int = 8; pub const IP_MULTICAST_IF: ::c_int = 9; pub const IP_MULTICAST_TTL: ::c_int = 10; pub const IP_MULTICAST_LOOP: ::c_int = 11; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; pub const IPV6_ADDRFORM: ::c_int = 1; pub const IPV6_2292PKTINFO: ::c_int = 2; pub const IPV6_2292HOPOPTS: ::c_int = 3; pub const IPV6_2292DSTOPTS: ::c_int = 4; pub const IPV6_2292RTHDR: ::c_int = 5; pub const IPV6_2292PKTOPTIONS: ::c_int = 6; pub const IPV6_CHECKSUM: ::c_int = 7; pub const IPV6_2292HOPLIMIT: ::c_int = 8; pub const IPV6_RXINFO: ::c_int = 2; pub const IPV6_TXINFO: ::c_int = 2; pub const SCM_SRCINFO: ::c_int = 2; pub const IPV6_UNICAST_HOPS: ::c_int = 16; pub const IPV6_MULTICAST_IF: ::c_int = 17; pub const IPV6_MULTICAST_HOPS: ::c_int = 18; pub const IPV6_MULTICAST_LOOP: ::c_int = 19; pub const IPV6_JOIN_GROUP: ::c_int = 20; pub const IPV6_LEAVE_GROUP: ::c_int = 21; pub const IPV6_ROUTER_ALERT: ::c_int = 22; pub const IPV6_MTU_DISCOVER: ::c_int = 23; pub const IPV6_MTU: ::c_int = 24; pub const IPV6_RECVERR: ::c_int = 25; pub const IPV6_V6ONLY: ::c_int = 26; pub const IPV6_JOIN_ANYCAST: ::c_int = 27; pub const IPV6_LEAVE_ANYCAST: ::c_int = 28; pub const IPV6_RECVPKTINFO: ::c_int = 49; pub const IPV6_PKTINFO: ::c_int = 50; pub const IPV6_RECVHOPLIMIT: ::c_int = 51; pub const IPV6_HOPLIMIT: ::c_int = 52; pub const IPV6_RECVHOPOPTS: ::c_int = 53; pub const IPV6_HOPOPTS: ::c_int = 54; pub const IPV6_RTHDRDSTOPTS: ::c_int = 55; pub const IPV6_RECVRTHDR: ::c_int = 56; pub const IPV6_RTHDR: ::c_int = 57; pub const IPV6_RECVDSTOPTS: ::c_int = 58; pub const IPV6_DSTOPTS: ::c_int = 59; pub const IPV6_RECVPATHMTU: ::c_int = 60; pub const IPV6_PATHMTU: ::c_int = 61; pub const IPV6_DONTFRAG: ::c_int = 62; pub const IPV6_RECVTCLASS: ::c_int = 66; pub const IPV6_TCLASS: ::c_int = 67; pub const IPV6_ADDR_PREFERENCES: ::c_int = 72; pub const IPV6_MINHOPCOUNT: ::c_int = 73; pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20; pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21; pub const IPV6_RXHOPOPTS: ::c_int = 3; pub const IPV6_RXDSTOPTS: ::c_int = 4; pub const IPV6_RTHDR_LOOSE: ::c_int = 0; pub const IPV6_RTHDR_STRICT: ::c_int = 1; pub const IPV6_RTHDR_TYPE_0: ::c_int = 0; pub const IN_CLASSA_NET: u32 = 4278190080; pub const IN_CLASSA_NSHIFT: usize = 24; pub const IN_CLASSA_HOST: u32 = 16777215; pub const IN_CLASSA_MAX: u32 = 128; pub const IN_CLASSB_NET: u32 = 4294901760; pub const IN_CLASSB_NSHIFT: usize = 16; pub const IN_CLASSB_HOST: u32 = 65535; pub const IN_CLASSB_MAX: u32 = 65536; pub const IN_CLASSC_NET: u32 = 4294967040; pub const IN_CLASSC_NSHIFT: usize = 8; pub const IN_CLASSC_HOST: u32 = 255; pub const IN_LOOPBACKNET: u32 = 127; pub const INET_ADDRSTRLEN: usize = 16; pub const INET6_ADDRSTRLEN: usize = 46; // netinet/ip.h pub const IPTOS_TOS_MASK: u8 = 0x1E; pub const IPTOS_PREC_MASK: u8 = 0xE0; pub const IPTOS_ECN_NOT_ECT: u8 = 0x00; pub const IPTOS_LOWDELAY: u8 = 0x10; pub const IPTOS_THROUGHPUT: u8 = 0x08; pub const IPTOS_RELIABILITY: u8 = 0x04; pub const IPTOS_MINCOST: u8 = 0x02; pub const IPTOS_PREC_NETCONTROL: u8 = 0xe0; pub const IPTOS_PREC_INTERNETCONTROL: u8 = 0xc0; pub const IPTOS_PREC_CRITIC_ECP: u8 = 0xa0; pub const IPTOS_PREC_FLASHOVERRIDE: u8 = 0x80; pub const IPTOS_PREC_FLASH: u8 = 0x60; pub const IPTOS_PREC_IMMEDIATE: u8 = 0x40; pub const IPTOS_PREC_PRIORITY: u8 = 0x20; pub const IPTOS_PREC_ROUTINE: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const IPOPT_COPY: u8 = 0x80; pub const IPOPT_CLASS_MASK: u8 = 0x60; pub const IPOPT_NUMBER_MASK: u8 = 0x1f; pub const IPOPT_CONTROL: u8 = 0x00; pub const IPOPT_RESERVED1: u8 = 0x20; pub const IPOPT_MEASUREMENT: u8 = 0x40; pub const IPOPT_RESERVED2: u8 = 0x60; pub const IPOPT_END: u8 = 0 | IPOPT_CONTROL; pub const IPOPT_NOOP: u8 = 1 | IPOPT_CONTROL; pub const IPOPT_SEC: u8 = 2 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_LSRR: u8 = 3 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_TIMESTAMP: u8 = 4 | IPOPT_MEASUREMENT; pub const IPOPT_RR: u8 = 7 | IPOPT_CONTROL; pub const IPOPT_SID: u8 = 8 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_SSRR: u8 = 9 | IPOPT_CONTROL | IPOPT_COPY; pub const IPOPT_RA: u8 = 20 | IPOPT_CONTROL | IPOPT_COPY; pub const IPVERSION: u8 = 4; pub const MAXTTL: u8 = 255; pub const IPDEFTTL: u8 = 64; pub const IPOPT_OPTVAL: u8 = 0; pub const IPOPT_OLEN: u8 = 1; pub const IPOPT_OFFSET: u8 = 2; pub const IPOPT_MINOFF: u8 = 4; pub const MAX_IPOPTLEN: u8 = 40; pub const IPOPT_NOP: u8 = IPOPT_NOOP; pub const IPOPT_EOL: u8 = IPOPT_END; pub const IPOPT_TS: u8 = IPOPT_TIMESTAMP; pub const IPOPT_TS_TSONLY: u8 = 0; pub const IPOPT_TS_TSANDADDR: u8 = 1; pub const IPOPT_TS_PRESPEC: u8 = 3; // net/if_arp.h pub const ARPOP_REQUEST: u16 = 1; pub const ARPOP_REPLY: u16 = 2; pub const ARPOP_RREQUEST: u16 = 3; pub const ARPOP_RREPLY: u16 = 4; pub const ARPOP_InREQUEST: u16 = 8; pub const ARPOP_InREPLY: u16 = 9; pub const ARPOP_NAK: u16 = 10; pub const MAX_ADDR_LEN: usize = 7; pub const ARPD_UPDATE: ::c_ushort = 0x01; pub const ARPD_LOOKUP: ::c_ushort = 0x02; pub const ARPD_FLUSH: ::c_ushort = 0x03; pub const ATF_MAGIC: ::c_int = 0x80; pub const ATF_NETMASK: ::c_int = 0x20; pub const ATF_DONTPUB: ::c_int = 0x40; pub const ARPHRD_NETROM: u16 = 0; pub const ARPHRD_ETHER: u16 = 1; pub const ARPHRD_EETHER: u16 = 2; pub const ARPHRD_AX25: u16 = 3; pub const ARPHRD_PRONET: u16 = 4; pub const ARPHRD_CHAOS: u16 = 5; pub const ARPHRD_IEEE802: u16 = 6; pub const ARPHRD_ARCNET: u16 = 7; pub const ARPHRD_APPLETLK: u16 = 8; pub const ARPHRD_DLCI: u16 = 15; pub const ARPHRD_ATM: u16 = 19; pub const ARPHRD_METRICOM: u16 = 23; pub const ARPHRD_IEEE1394: u16 = 24; pub const ARPHRD_EUI64: u16 = 27; pub const ARPHRD_INFINIBAND: u16 = 32; pub const ARPHRD_SLIP: u16 = 256; pub const ARPHRD_CSLIP: u16 = 257; pub const ARPHRD_SLIP6: u16 = 258; pub const ARPHRD_CSLIP6: u16 = 259; pub const ARPHRD_RSRVD: u16 = 260; pub const ARPHRD_ADAPT: u16 = 264; pub const ARPHRD_ROSE: u16 = 270; pub const ARPHRD_X25: u16 = 271; pub const ARPHRD_HWX25: u16 = 272; pub const ARPHRD_CAN: u16 = 280; pub const ARPHRD_PPP: u16 = 512; pub const ARPHRD_CISCO: u16 = 513; pub const ARPHRD_HDLC: u16 = ARPHRD_CISCO; pub const ARPHRD_LAPB: u16 = 516; pub const ARPHRD_DDCMP: u16 = 517; pub const ARPHRD_RAWHDLC: u16 = 518; pub const ARPHRD_TUNNEL: u16 = 768; pub const ARPHRD_TUNNEL6: u16 = 769; pub const ARPHRD_FRAD: u16 = 770; pub const ARPHRD_SKIP: u16 = 771; pub const ARPHRD_LOOPBACK: u16 = 772; pub const ARPHRD_LOCALTLK: u16 = 773; pub const ARPHRD_FDDI: u16 = 774; pub const ARPHRD_BIF: u16 = 775; pub const ARPHRD_SIT: u16 = 776; pub const ARPHRD_IPDDP: u16 = 777; pub const ARPHRD_IPGRE: u16 = 778; pub const ARPHRD_PIMREG: u16 = 779; pub const ARPHRD_HIPPI: u16 = 780; pub const ARPHRD_ASH: u16 = 781; pub const ARPHRD_ECONET: u16 = 782; pub const ARPHRD_IRDA: u16 = 783; pub const ARPHRD_FCPP: u16 = 784; pub const ARPHRD_FCAL: u16 = 785; pub const ARPHRD_FCPL: u16 = 786; pub const ARPHRD_FCFABRIC: u16 = 787; pub const ARPHRD_IEEE802_TR: u16 = 800; pub const ARPHRD_IEEE80211: u16 = 801; pub const ARPHRD_IEEE80211_PRISM: u16 = 802; pub const ARPHRD_IEEE80211_RADIOTAP: u16 = 803; pub const ARPHRD_IEEE802154: u16 = 804; pub const ARPHRD_VOID: u16 = 0xFFFF; pub const ARPHRD_NONE: u16 = 0xFFFE; // bits/posix1_lim.h pub const _POSIX_AIO_LISTIO_MAX: usize = 2; pub const _POSIX_AIO_MAX: usize = 1; pub const _POSIX_ARG_MAX: usize = 4096; pub const _POSIX_CHILD_MAX: usize = 25; pub const _POSIX_DELAYTIMER_MAX: usize = 32; pub const _POSIX_HOST_NAME_MAX: usize = 255; pub const _POSIX_LINK_MAX: usize = 8; pub const _POSIX_LOGIN_NAME_MAX: usize = 9; pub const _POSIX_MAX_CANON: usize = 255; pub const _POSIX_MAX_INPUT: usize = 255; pub const _POSIX_MQ_OPEN_MAX: usize = 8; pub const _POSIX_MQ_PRIO_MAX: usize = 32; pub const _POSIX_NAME_MAX: usize = 14; pub const _POSIX_NGROUPS_MAX: usize = 8; pub const _POSIX_OPEN_MAX: usize = 20; pub const _POSIX_FD_SETSIZE: usize = 20; pub const _POSIX_PATH_MAX: usize = 256; pub const _POSIX_PIPE_BUF: usize = 512; pub const _POSIX_RE_DUP_MAX: usize = 255; pub const _POSIX_RTSIG_MAX: usize = 8; pub const _POSIX_SEM_NSEMS_MAX: usize = 256; pub const _POSIX_SEM_VALUE_MAX: usize = 32767; pub const _POSIX_SIGQUEUE_MAX: usize = 32; pub const _POSIX_SSIZE_MAX: usize = 32767; pub const _POSIX_STREAM_MAX: usize = 8; pub const _POSIX_SYMLINK_MAX: usize = 255; pub const _POSIX_SYMLOOP_MAX: usize = 8; pub const _POSIX_TIMER_MAX: usize = 32; pub const _POSIX_TTY_NAME_MAX: usize = 9; pub const _POSIX_TZNAME_MAX: usize = 6; pub const _POSIX_QLIMIT: usize = 1; pub const _POSIX_HIWAT: usize = 512; pub const _POSIX_UIO_MAXIOV: usize = 16; pub const _POSIX_CLOCKRES_MIN: usize = 20000000; pub const NAME_MAX: usize = 255; pub const NGROUPS_MAX: usize = 256; pub const _POSIX_THREAD_KEYS_MAX: usize = 128; pub const _POSIX_THREAD_DESTRUCTOR_ITERATIONS: usize = 4; pub const _POSIX_THREAD_THREADS_MAX: usize = 64; pub const SEM_VALUE_MAX: ::c_int = 2147483647; pub const MAXNAMLEN: usize = 255; // netdb.h pub const _PATH_HEQUIV: &'static [u8; 17usize] = b"/etc/hosts.equiv\0"; pub const _PATH_HOSTS: &'static [u8; 11usize] = b"/etc/hosts\0"; pub const _PATH_NETWORKS: &'static [u8; 14usize] = b"/etc/networks\0"; pub const _PATH_NSSWITCH_CONF: &'static [u8; 19usize] = b"/etc/nsswitch.conf\0"; pub const _PATH_PROTOCOLS: &'static [u8; 15usize] = b"/etc/protocols\0"; pub const _PATH_SERVICES: &'static [u8; 14usize] = b"/etc/services\0"; pub const HOST_NOT_FOUND: ::c_int = 1; pub const TRY_AGAIN: ::c_int = 2; pub const NO_RECOVERY: ::c_int = 3; pub const NO_DATA: ::c_int = 4; pub const NETDB_INTERNAL: ::c_int = -1; pub const NETDB_SUCCESS: ::c_int = 0; pub const NO_ADDRESS: ::c_int = 4; pub const IPPORT_RESERVED: ::c_int = 1024; pub const SCOPE_DELIMITER: u8 = 37u8; pub const GAI_WAIT: ::c_int = 0; pub const GAI_NOWAIT: ::c_int = 1; pub const AI_PASSIVE: ::c_int = 1; pub const AI_CANONNAME: ::c_int = 2; pub const AI_NUMERICHOST: ::c_int = 4; pub const AI_V4MAPPED: ::c_int = 8; pub const AI_ALL: ::c_int = 16; pub const AI_ADDRCONFIG: ::c_int = 32; pub const AI_IDN: ::c_int = 64; pub const AI_CANONIDN: ::c_int = 128; pub const AI_NUMERICSERV: ::c_int = 1024; pub const EAI_BADFLAGS: ::c_int = -1; pub const EAI_NONAME: ::c_int = -2; pub const EAI_AGAIN: ::c_int = -3; pub const EAI_FAIL: ::c_int = -4; pub const EAI_FAMILY: ::c_int = -6; pub const EAI_SOCKTYPE: ::c_int = -7; pub const EAI_SERVICE: ::c_int = -8; pub const EAI_MEMORY: ::c_int = -10; pub const EAI_SYSTEM: ::c_int = -11; pub const EAI_OVERFLOW: ::c_int = -12; pub const EAI_NODATA: ::c_int = -5; pub const EAI_ADDRFAMILY: ::c_int = -9; pub const EAI_INPROGRESS: ::c_int = -100; pub const EAI_CANCELED: ::c_int = -101; pub const EAI_NOTCANCELED: ::c_int = -102; pub const EAI_ALLDONE: ::c_int = -103; pub const EAI_INTR: ::c_int = -104; pub const EAI_IDN_ENCODE: ::c_int = -105; pub const NI_MAXHOST: usize = 1025; pub const NI_MAXSERV: usize = 32; pub const NI_NUMERICHOST: ::c_int = 1; pub const NI_NUMERICSERV: ::c_int = 2; pub const NI_NOFQDN: ::c_int = 4; pub const NI_NAMEREQD: ::c_int = 8; pub const NI_DGRAM: ::c_int = 16; pub const NI_IDN: ::c_int = 32; // time.h pub const CLOCK_REALTIME: ::clockid_t = 0; pub const CLOCK_MONOTONIC: ::clockid_t = 1; pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 3; pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4; pub const CLOCK_REALTIME_COARSE: ::clockid_t = 5; pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = 6; pub const TIMER_ABSTIME: ::c_int = 1; pub const TIME_UTC: ::c_int = 1; // sys/poll.h pub const POLLIN: i16 = 1; pub const POLLPRI: i16 = 2; pub const POLLOUT: i16 = 4; pub const POLLRDNORM: i16 = 1; pub const POLLRDBAND: i16 = 2; pub const POLLWRNORM: i16 = 4; pub const POLLWRBAND: i16 = 4; pub const POLLERR: i16 = 8; pub const POLLHUP: i16 = 16; pub const POLLNVAL: i16 = 32; // locale.h pub const __LC_CTYPE: usize = 0; pub const __LC_NUMERIC: usize = 1; pub const __LC_TIME: usize = 2; pub const __LC_COLLATE: usize = 3; pub const __LC_MONETARY: usize = 4; pub const __LC_MESSAGES: usize = 5; pub const __LC_ALL: usize = 6; pub const __LC_PAPER: usize = 7; pub const __LC_NAME: usize = 8; pub const __LC_ADDRESS: usize = 9; pub const __LC_TELEPHONE: usize = 10; pub const __LC_MEASUREMENT: usize = 11; pub const __LC_IDENTIFICATION: usize = 12; pub const LC_CTYPE: ::c_int = 0; pub const LC_NUMERIC: ::c_int = 1; pub const LC_TIME: ::c_int = 2; pub const LC_COLLATE: ::c_int = 3; pub const LC_MONETARY: ::c_int = 4; pub const LC_MESSAGES: ::c_int = 5; pub const LC_ALL: ::c_int = 6; pub const LC_PAPER: ::c_int = 7; pub const LC_NAME: ::c_int = 8; pub const LC_ADDRESS: ::c_int = 9; pub const LC_TELEPHONE: ::c_int = 10; pub const LC_MEASUREMENT: ::c_int = 11; pub const LC_IDENTIFICATION: ::c_int = 12; pub const LC_CTYPE_MASK: ::c_int = 1; pub const LC_NUMERIC_MASK: ::c_int = 2; pub const LC_TIME_MASK: ::c_int = 4; pub const LC_COLLATE_MASK: ::c_int = 8; pub const LC_MONETARY_MASK: ::c_int = 16; pub const LC_MESSAGES_MASK: ::c_int = 32; pub const LC_PAPER_MASK: ::c_int = 128; pub const LC_NAME_MASK: ::c_int = 256; pub const LC_ADDRESS_MASK: ::c_int = 512; pub const LC_TELEPHONE_MASK: ::c_int = 1024; pub const LC_MEASUREMENT_MASK: ::c_int = 2048; pub const LC_IDENTIFICATION_MASK: ::c_int = 4096; pub const LC_ALL_MASK: ::c_int = 8127; pub const ABDAY_1: ::nl_item = 0x20000; pub const ABDAY_2: ::nl_item = 0x20001; pub const ABDAY_3: ::nl_item = 0x20002; pub const ABDAY_4: ::nl_item = 0x20003; pub const ABDAY_5: ::nl_item = 0x20004; pub const ABDAY_6: ::nl_item = 0x20005; pub const ABDAY_7: ::nl_item = 0x20006; pub const DAY_1: ::nl_item = 0x20007; pub const DAY_2: ::nl_item = 0x20008; pub const DAY_3: ::nl_item = 0x20009; pub const DAY_4: ::nl_item = 0x2000A; pub const DAY_5: ::nl_item = 0x2000B; pub const DAY_6: ::nl_item = 0x2000C; pub const DAY_7: ::nl_item = 0x2000D; pub const ABMON_1: ::nl_item = 0x2000E; pub const ABMON_2: ::nl_item = 0x2000F; pub const ABMON_3: ::nl_item = 0x20010; pub const ABMON_4: ::nl_item = 0x20011; pub const ABMON_5: ::nl_item = 0x20012; pub const ABMON_6: ::nl_item = 0x20013; pub const ABMON_7: ::nl_item = 0x20014; pub const ABMON_8: ::nl_item = 0x20015; pub const ABMON_9: ::nl_item = 0x20016; pub const ABMON_10: ::nl_item = 0x20017; pub const ABMON_11: ::nl_item = 0x20018; pub const ABMON_12: ::nl_item = 0x20019; pub const MON_1: ::nl_item = 0x2001A; pub const MON_2: ::nl_item = 0x2001B; pub const MON_3: ::nl_item = 0x2001C; pub const MON_4: ::nl_item = 0x2001D; pub const MON_5: ::nl_item = 0x2001E; pub const MON_6: ::nl_item = 0x2001F; pub const MON_7: ::nl_item = 0x20020; pub const MON_8: ::nl_item = 0x20021; pub const MON_9: ::nl_item = 0x20022; pub const MON_10: ::nl_item = 0x20023; pub const MON_11: ::nl_item = 0x20024; pub const MON_12: ::nl_item = 0x20025; pub const AM_STR: ::nl_item = 0x20026; pub const PM_STR: ::nl_item = 0x20027; pub const D_T_FMT: ::nl_item = 0x20028; pub const D_FMT: ::nl_item = 0x20029; pub const T_FMT: ::nl_item = 0x2002A; pub const T_FMT_AMPM: ::nl_item = 0x2002B; pub const ERA: ::nl_item = 0x2002C; pub const ERA_D_FMT: ::nl_item = 0x2002E; pub const ALT_DIGITS: ::nl_item = 0x2002F; pub const ERA_D_T_FMT: ::nl_item = 0x20030; pub const ERA_T_FMT: ::nl_item = 0x20031; pub const CODESET: ::nl_item = 14; pub const CRNCYSTR: ::nl_item = 0x4000F; pub const RADIXCHAR: ::nl_item = 0x10000; pub const THOUSEP: ::nl_item = 0x10001; pub const YESEXPR: ::nl_item = 0x50000; pub const NOEXPR: ::nl_item = 0x50001; pub const YESSTR: ::nl_item = 0x50002; pub const NOSTR: ::nl_item = 0x50003; // reboot.h pub const RB_AUTOBOOT: ::c_int = 0x0; pub const RB_ASKNAME: ::c_int = 0x1; pub const RB_SINGLE: ::c_int = 0x2; pub const RB_KBD: ::c_int = 0x4; pub const RB_HALT: ::c_int = 0x8; pub const RB_INITNAME: ::c_int = 0x10; pub const RB_DFLTROOT: ::c_int = 0x20; pub const RB_NOBOOTRC: ::c_int = 0x20; pub const RB_ALTBOOT: ::c_int = 0x40; pub const RB_UNIPROC: ::c_int = 0x80; pub const RB_DEBUGGER: ::c_int = 0x1000; // semaphore.h pub const __SIZEOF_SEM_T: usize = 20; pub const SEM_FAILED: *mut ::sem_t = 0 as *mut sem_t; // termios.h pub const IGNBRK: ::tcflag_t = 1; pub const BRKINT: ::tcflag_t = 2; pub const IGNPAR: ::tcflag_t = 4; pub const PARMRK: ::tcflag_t = 8; pub const INPCK: ::tcflag_t = 16; pub const ISTRIP: ::tcflag_t = 32; pub const INLCR: ::tcflag_t = 64; pub const IGNCR: ::tcflag_t = 128; pub const ICRNL: ::tcflag_t = 256; pub const IXON: ::tcflag_t = 512; pub const IXOFF: ::tcflag_t = 1024; pub const IXANY: ::tcflag_t = 2048; pub const IMAXBEL: ::tcflag_t = 8192; pub const IUCLC: ::tcflag_t = 16384; pub const OPOST: ::tcflag_t = 1; pub const ONLCR: ::tcflag_t = 2; pub const ONOEOT: ::tcflag_t = 8; pub const OCRNL: ::tcflag_t = 16; pub const ONOCR: ::tcflag_t = 32; pub const ONLRET: ::tcflag_t = 64; pub const NLDLY: ::tcflag_t = 768; pub const NL0: ::tcflag_t = 0; pub const NL1: ::tcflag_t = 256; pub const TABDLY: ::tcflag_t = 3076; pub const TAB0: ::tcflag_t = 0; pub const TAB1: ::tcflag_t = 1024; pub const TAB2: ::tcflag_t = 2048; pub const TAB3: ::tcflag_t = 4; pub const CRDLY: ::tcflag_t = 12288; pub const CR0: ::tcflag_t = 0; pub const CR1: ::tcflag_t = 4096; pub const CR2: ::tcflag_t = 8192; pub const CR3: ::tcflag_t = 12288; pub const FFDLY: ::tcflag_t = 16384; pub const FF0: ::tcflag_t = 0; pub const FF1: ::tcflag_t = 16384; pub const BSDLY: ::tcflag_t = 32768; pub const BS0: ::tcflag_t = 0; pub const BS1: ::tcflag_t = 32768; pub const VTDLY: ::tcflag_t = 65536; pub const VT0: ::tcflag_t = 0; pub const VT1: ::tcflag_t = 65536; pub const OLCUC: ::tcflag_t = 131072; pub const OFILL: ::tcflag_t = 262144; pub const OFDEL: ::tcflag_t = 524288; pub const CIGNORE: ::tcflag_t = 1; pub const CSIZE: ::tcflag_t = 768; pub const CS5: ::tcflag_t = 0; pub const CS6: ::tcflag_t = 256; pub const CS7: ::tcflag_t = 512; pub const CS8: ::tcflag_t = 768; pub const CSTOPB: ::tcflag_t = 1024; pub const CREAD: ::tcflag_t = 2048; pub const PARENB: ::tcflag_t = 4096; pub const PARODD: ::tcflag_t = 8192; pub const HUPCL: ::tcflag_t = 16384; pub const CLOCAL: ::tcflag_t = 32768; pub const CRTSCTS: ::tcflag_t = 65536; pub const CRTS_IFLOW: ::tcflag_t = 65536; pub const CCTS_OFLOW: ::tcflag_t = 65536; pub const CDTRCTS: ::tcflag_t = 131072; pub const MDMBUF: ::tcflag_t = 1048576; pub const CHWFLOW: ::tcflag_t = 1245184; pub const ECHOKE: ::tcflag_t = 1; pub const _ECHOE: ::tcflag_t = 2; pub const ECHOE: ::tcflag_t = 2; pub const _ECHOK: ::tcflag_t = 4; pub const ECHOK: ::tcflag_t = 4; pub const _ECHO: ::tcflag_t = 8; pub const ECHO: ::tcflag_t = 8; pub const _ECHONL: ::tcflag_t = 16; pub const ECHONL: ::tcflag_t = 16; pub const ECHOPRT: ::tcflag_t = 32; pub const ECHOCTL: ::tcflag_t = 64; pub const _ISIG: ::tcflag_t = 128; pub const ISIG: ::tcflag_t = 128; pub const _ICANON: ::tcflag_t = 256; pub const ICANON: ::tcflag_t = 256; pub const ALTWERASE: ::tcflag_t = 512; pub const _IEXTEN: ::tcflag_t = 1024; pub const IEXTEN: ::tcflag_t = 1024; pub const EXTPROC: ::tcflag_t = 2048; pub const _TOSTOP: ::tcflag_t = 4194304; pub const TOSTOP: ::tcflag_t = 4194304; pub const FLUSHO: ::tcflag_t = 8388608; pub const NOKERNINFO: ::tcflag_t = 33554432; pub const PENDIN: ::tcflag_t = 536870912; pub const _NOFLSH: ::tcflag_t = 2147483648; pub const NOFLSH: ::tcflag_t = 2147483648; pub const VEOF: usize = 0; pub const VEOL: usize = 1; pub const VEOL2: usize = 2; pub const VERASE: usize = 3; pub const VWERASE: usize = 4; pub const VKILL: usize = 5; pub const VREPRINT: usize = 6; pub const VINTR: usize = 8; pub const VQUIT: usize = 9; pub const VSUSP: usize = 10; pub const VDSUSP: usize = 11; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VLNEXT: usize = 14; pub const VDISCARD: usize = 15; pub const VMIN: usize = 16; pub const VTIME: usize = 17; pub const VSTATUS: usize = 18; pub const NCCS: usize = 20; pub const B0: ::speed_t = 0; pub const B50: ::speed_t = 50; pub const B75: ::speed_t = 75; pub const B110: ::speed_t = 110; pub const B134: ::speed_t = 134; pub const B150: ::speed_t = 150; pub const B200: ::speed_t = 200; pub const B300: ::speed_t = 300; pub const B600: ::speed_t = 600; pub const B1200: ::speed_t = 1200; pub const B1800: ::speed_t = 1800; pub const B2400: ::speed_t = 2400; pub const B4800: ::speed_t = 4800; pub const B9600: ::speed_t = 9600; pub const B7200: ::speed_t = 7200; pub const B14400: ::speed_t = 14400; pub const B19200: ::speed_t = 19200; pub const B28800: ::speed_t = 28800; pub const B38400: ::speed_t = 38400; pub const EXTA: ::speed_t = B19200; pub const EXTB: ::speed_t = B38400; pub const B57600: ::speed_t = 57600; pub const B76800: ::speed_t = 76800; pub const B115200: ::speed_t = 115200; pub const B230400: ::speed_t = 230400; pub const B460800: ::speed_t = 460800; pub const B500000: ::speed_t = 500000; pub const B576000: ::speed_t = 576000; pub const B921600: ::speed_t = 921600; pub const B1000000: ::speed_t = 1000000; pub const B1152000: ::speed_t = 1152000; pub const B1500000: ::speed_t = 1500000; pub const B2000000: ::speed_t = 2000000; pub const B2500000: ::speed_t = 2500000; pub const B3000000: ::speed_t = 3000000; pub const B3500000: ::speed_t = 3500000; pub const B4000000: ::speed_t = 4000000; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const TCSASOFT: ::c_int = 16; pub const TCIFLUSH: ::c_int = 1; pub const TCOFLUSH: ::c_int = 2; pub const TCIOFLUSH: ::c_int = 3; pub const TCOOFF: ::c_int = 1; pub const TCOON: ::c_int = 2; pub const TCIOFF: ::c_int = 3; pub const TCION: ::c_int = 4; pub const TTYDEF_IFLAG: ::tcflag_t = 11042; pub const TTYDEF_LFLAG: ::tcflag_t = 1483; pub const TTYDEF_CFLAG: ::tcflag_t = 23040; pub const TTYDEF_SPEED: ::tcflag_t = 9600; pub const CEOL: u8 = 0u8; pub const CERASE: u8 = 127; pub const CMIN: u8 = 1; pub const CQUIT: u8 = 28; pub const CTIME: u8 = 0; pub const CBRK: u8 = 0u8; // dlfcn.h pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; pub const RTLD_NEXT: *mut ::c_void = -1i64 as *mut ::c_void; pub const RTLD_LAZY: ::c_int = 1; pub const RTLD_NOW: ::c_int = 2; pub const RTLD_BINDING_MASK: ::c_int = 3; pub const RTLD_NOLOAD: ::c_int = 4; pub const RTLD_DEEPBIND: ::c_int = 8; pub const RTLD_GLOBAL: ::c_int = 256; pub const RTLD_LOCAL: ::c_int = 0; pub const RTLD_NODELETE: ::c_int = 4096; pub const DLFO_STRUCT_HAS_EH_DBASE: usize = 1; pub const DLFO_STRUCT_HAS_EH_COUNT: usize = 0; pub const LM_ID_BASE: c_long = 0; pub const LM_ID_NEWLM: c_long = -1; // bits/signum_generic.h pub const SIGINT: ::c_int = 2; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGFPE: ::c_int = 8; pub const SIGSEGV: ::c_int = 11; pub const SIGTERM: ::c_int = 15; pub const SIGHUP: ::c_int = 1; pub const SIGQUIT: ::c_int = 3; pub const SIGTRAP: ::c_int = 5; pub const SIGKILL: ::c_int = 9; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGIOT: ::c_int = 6; pub const SIGBUS: ::c_int = 10; pub const SIGSYS: ::c_int = 12; pub const SIGEMT: ::c_int = 7; pub const SIGINFO: ::c_int = 29; pub const SIGLOST: ::c_int = 32; pub const SIGURG: ::c_int = 16; pub const SIGSTOP: ::c_int = 17; pub const SIGTSTP: ::c_int = 18; pub const SIGCONT: ::c_int = 19; pub const SIGCHLD: ::c_int = 20; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGPOLL: ::c_int = 23; pub const SIGXCPU: ::c_int = 24; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGXFSZ: ::c_int = 25; pub const SIGUSR1: ::c_int = 30; pub const SIGUSR2: ::c_int = 31; pub const SIGWINCH: ::c_int = 28; pub const SIGIO: ::c_int = 23; pub const SIGCLD: ::c_int = 20; pub const __SIGRTMIN: usize = 32; pub const __SIGRTMAX: usize = 32; pub const _NSIG: usize = 33; pub const NSIG: usize = 33; // bits/sigaction.h pub const SA_ONSTACK: ::c_int = 1; pub const SA_RESTART: ::c_int = 2; pub const SA_NODEFER: ::c_int = 16; pub const SA_RESETHAND: ::c_int = 4; pub const SA_NOCLDSTOP: ::c_int = 8; pub const SA_SIGINFO: ::c_int = 64; pub const SA_INTERRUPT: ::c_int = 0; pub const SA_NOMASK: ::c_int = 16; pub const SA_ONESHOT: ::c_int = 4; pub const SA_STACK: ::c_int = 1; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const SIG_SETMASK: ::c_int = 3; // bits/sigcontext.h pub const FPC_IE: u16 = 1; pub const FPC_IM: u16 = 1; pub const FPC_DE: u16 = 2; pub const FPC_DM: u16 = 2; pub const FPC_ZE: u16 = 4; pub const FPC_ZM: u16 = 4; pub const FPC_OE: u16 = 8; pub const FPC_OM: u16 = 8; pub const FPC_UE: u16 = 16; pub const FPC_PE: u16 = 32; pub const FPC_PC: u16 = 768; pub const FPC_PC_24: u16 = 0; pub const FPC_PC_53: u16 = 512; pub const FPC_PC_64: u16 = 768; pub const FPC_RC: u16 = 3072; pub const FPC_RC_RN: u16 = 0; pub const FPC_RC_RD: u16 = 1024; pub const FPC_RC_RU: u16 = 2048; pub const FPC_RC_CHOP: u16 = 3072; pub const FPC_IC: u16 = 4096; pub const FPC_IC_PROJ: u16 = 0; pub const FPC_IC_AFF: u16 = 4096; pub const FPS_IE: u16 = 1; pub const FPS_DE: u16 = 2; pub const FPS_ZE: u16 = 4; pub const FPS_OE: u16 = 8; pub const FPS_UE: u16 = 16; pub const FPS_PE: u16 = 32; pub const FPS_SF: u16 = 64; pub const FPS_ES: u16 = 128; pub const FPS_C0: u16 = 256; pub const FPS_C1: u16 = 512; pub const FPS_C2: u16 = 1024; pub const FPS_TOS: u16 = 14336; pub const FPS_TOS_SHIFT: u16 = 11; pub const FPS_C3: u16 = 16384; pub const FPS_BUSY: u16 = 32768; pub const FPE_INTOVF_TRAP: ::c_int = 1; pub const FPE_INTDIV_FAULT: ::c_int = 2; pub const FPE_FLTOVF_FAULT: ::c_int = 3; pub const FPE_FLTDIV_FAULT: ::c_int = 4; pub const FPE_FLTUND_FAULT: ::c_int = 5; pub const FPE_SUBRNG_FAULT: ::c_int = 7; pub const FPE_FLTDNR_FAULT: ::c_int = 8; pub const FPE_FLTINX_FAULT: ::c_int = 9; pub const FPE_EMERR_FAULT: ::c_int = 10; pub const FPE_EMBND_FAULT: ::c_int = 11; pub const ILL_INVOPR_FAULT: ::c_int = 1; pub const ILL_STACK_FAULT: ::c_int = 2; pub const ILL_FPEOPR_FAULT: ::c_int = 3; pub const DBG_SINGLE_TRAP: ::c_int = 1; pub const DBG_BRKPNT_FAULT: ::c_int = 2; pub const __NGREG: usize = 19; pub const NGREG: usize = 19; // bits/sigstack.h pub const MINSIGSTKSZ: usize = 8192; pub const SIGSTKSZ: usize = 40960; // sys/stat.h pub const __S_IFMT: mode_t = 61440; pub const __S_IFDIR: mode_t = 16384; pub const __S_IFCHR: mode_t = 8192; pub const __S_IFBLK: mode_t = 24576; pub const __S_IFREG: mode_t = 32768; pub const __S_IFLNK: mode_t = 40960; pub const __S_IFSOCK: mode_t = 49152; pub const __S_IFIFO: mode_t = 4096; pub const __S_ISUID: mode_t = 2048; pub const __S_ISGID: mode_t = 1024; pub const __S_ISVTX: mode_t = 512; pub const __S_IREAD: mode_t = 256; pub const __S_IWRITE: mode_t = 128; pub const __S_IEXEC: mode_t = 64; pub const S_INOCACHE: mode_t = 65536; pub const S_IUSEUNK: mode_t = 131072; pub const S_IUNKNOWN: mode_t = 1835008; pub const S_IUNKSHIFT: mode_t = 12; pub const S_IPTRANS: mode_t = 2097152; pub const S_IATRANS: mode_t = 4194304; pub const S_IROOT: mode_t = 8388608; pub const S_ITRANS: mode_t = 14680064; pub const S_IMMAP0: mode_t = 16777216; pub const CMASK: mode_t = 18; pub const UF_SETTABLE: ::c_uint = 65535; pub const UF_NODUMP: ::c_uint = 1; pub const UF_IMMUTABLE: ::c_uint = 2; pub const UF_APPEND: ::c_uint = 4; pub const UF_OPAQUE: ::c_uint = 8; pub const UF_NOUNLINK: ::c_uint = 16; pub const SF_SETTABLE: ::c_uint = 4294901760; pub const SF_ARCHIVED: ::c_uint = 65536; pub const SF_IMMUTABLE: ::c_uint = 131072; pub const SF_APPEND: ::c_uint = 262144; pub const SF_NOUNLINK: ::c_uint = 1048576; pub const SF_SNAPSHOT: ::c_uint = 2097152; pub const UTIME_NOW: ::c_long = -1; pub const UTIME_OMIT: ::c_long = -2; pub const S_IFMT: ::mode_t = 61440; pub const S_IFDIR: ::mode_t = 16384; pub const S_IFCHR: ::mode_t = 8192; pub const S_IFBLK: ::mode_t = 24576; pub const S_IFREG: ::mode_t = 32768; pub const S_IFIFO: ::mode_t = 4096; pub const S_IFLNK: ::mode_t = 40960; pub const S_IFSOCK: ::mode_t = 49152; pub const S_ISUID: ::mode_t = 2048; pub const S_ISGID: ::mode_t = 1024; pub const S_ISVTX: ::mode_t = 512; pub const S_IRUSR: ::mode_t = 256; pub const S_IWUSR: ::mode_t = 128; pub const S_IXUSR: ::mode_t = 64; pub const S_IRWXU: ::mode_t = 448; pub const S_IREAD: ::mode_t = 256; pub const S_IWRITE: ::mode_t = 128; pub const S_IEXEC: ::mode_t = 64; pub const S_IRGRP: ::mode_t = 32; pub const S_IWGRP: ::mode_t = 16; pub const S_IXGRP: ::mode_t = 8; pub const S_IRWXG: ::mode_t = 56; pub const S_IROTH: ::mode_t = 4; pub const S_IWOTH: ::mode_t = 2; pub const S_IXOTH: ::mode_t = 1; pub const S_IRWXO: ::mode_t = 7; pub const ACCESSPERMS: ::mode_t = 511; pub const ALLPERMS: ::mode_t = 4095; pub const DEFFILEMODE: ::mode_t = 438; pub const S_BLKSIZE: usize = 512; pub const STATX_TYPE: ::c_uint = 1; pub const STATX_MODE: ::c_uint = 2; pub const STATX_NLINK: ::c_uint = 4; pub const STATX_UID: ::c_uint = 8; pub const STATX_GID: ::c_uint = 16; pub const STATX_ATIME: ::c_uint = 32; pub const STATX_MTIME: ::c_uint = 64; pub const STATX_CTIME: ::c_uint = 128; pub const STATX_INO: ::c_uint = 256; pub const STATX_SIZE: ::c_uint = 512; pub const STATX_BLOCKS: ::c_uint = 1024; pub const STATX_BASIC_STATS: ::c_uint = 2047; pub const STATX_ALL: ::c_uint = 4095; pub const STATX_BTIME: ::c_uint = 2048; pub const STATX_MNT_ID: ::c_uint = 4096; pub const STATX_DIOALIGN: ::c_uint = 8192; pub const STATX__RESERVED: ::c_uint = 2147483648; pub const STATX_ATTR_COMPRESSED: ::c_uint = 4; pub const STATX_ATTR_IMMUTABLE: ::c_uint = 16; pub const STATX_ATTR_APPEND: ::c_uint = 32; pub const STATX_ATTR_NODUMP: ::c_uint = 64; pub const STATX_ATTR_ENCRYPTED: ::c_uint = 2048; pub const STATX_ATTR_AUTOMOUNT: ::c_uint = 4096; pub const STATX_ATTR_MOUNT_ROOT: ::c_uint = 8192; pub const STATX_ATTR_VERITY: ::c_uint = 1048576; pub const STATX_ATTR_DAX: ::c_uint = 2097152; // sys/ioctl.h pub const TIOCM_LE: ::c_int = 1; pub const TIOCM_DTR: ::c_int = 2; pub const TIOCM_RTS: ::c_int = 4; pub const TIOCM_ST: ::c_int = 8; pub const TIOCM_SR: ::c_int = 16; pub const TIOCM_CTS: ::c_int = 32; pub const TIOCM_CAR: ::c_int = 64; pub const TIOCM_CD: ::c_int = 64; pub const TIOCM_RNG: ::c_int = 128; pub const TIOCM_RI: ::c_int = 128; pub const TIOCM_DSR: ::c_int = 256; pub const TIOCPKT_DATA: ::c_int = 0; pub const TIOCPKT_FLUSHREAD: ::c_int = 1; pub const TIOCPKT_FLUSHWRITE: ::c_int = 2; pub const TIOCPKT_STOP: ::c_int = 4; pub const TIOCPKT_START: ::c_int = 8; pub const TIOCPKT_NOSTOP: ::c_int = 16; pub const TIOCPKT_DOSTOP: ::c_int = 32; pub const TIOCPKT_IOCTL: ::c_int = 64; pub const TTYDISC: ::c_int = 0; pub const TABLDISC: ::c_int = 3; pub const SLIPDISC: ::c_int = 4; pub const TANDEM: ::tcflag_t = 1; pub const CBREAK: ::tcflag_t = 2; pub const LCASE: ::tcflag_t = 4; pub const CRMOD: ::tcflag_t = 16; pub const RAW: ::tcflag_t = 32; pub const ODDP: ::tcflag_t = 64; pub const EVENP: ::tcflag_t = 128; pub const ANYP: ::tcflag_t = 192; pub const NLDELAY: ::tcflag_t = 768; pub const NL2: ::tcflag_t = 512; pub const NL3: ::tcflag_t = 768; pub const TBDELAY: ::tcflag_t = 3072; pub const XTABS: ::tcflag_t = 3072; pub const CRDELAY: ::tcflag_t = 12288; pub const VTDELAY: ::tcflag_t = 16384; pub const BSDELAY: ::tcflag_t = 32768; pub const ALLDELAY: ::tcflag_t = 65280; pub const CRTBS: ::tcflag_t = 65536; pub const PRTERA: ::tcflag_t = 131072; pub const CRTERA: ::tcflag_t = 262144; pub const TILDE: ::tcflag_t = 524288; pub const LITOUT: ::tcflag_t = 2097152; pub const NOHANG: ::tcflag_t = 16777216; pub const L001000: ::tcflag_t = 33554432; pub const CRTKIL: ::tcflag_t = 67108864; pub const PASS8: ::tcflag_t = 134217728; pub const CTLECH: ::tcflag_t = 268435456; pub const DECCTQ: ::tcflag_t = 1073741824; pub const FIONBIO: ::c_ulong = 0xa008007e; pub const FIONREAD: ::c_ulong = 0x6008007f; pub const TIOCSWINSZ: ::c_ulong = 0x90200767; pub const TIOCGWINSZ: ::c_ulong = 0x50200768; pub const TIOCEXCL: ::c_ulong = 0x70d; pub const TIOCNXCL: ::c_ulong = 0x70e; pub const TIOCSCTTY: ::c_ulong = 0x761; pub const FIOCLEX: ::c_ulong = 1; // fcntl.h pub const O_EXEC: ::c_int = 4; pub const O_NORW: ::c_int = 0; pub const O_RDONLY: ::c_int = 1; pub const O_WRONLY: ::c_int = 2; pub const O_RDWR: ::c_int = 3; pub const O_ACCMODE: ::c_int = 3; pub const O_LARGEFILE: ::c_int = 0; pub const O_CREAT: ::c_int = 16; pub const O_EXCL: ::c_int = 32; pub const O_NOLINK: ::c_int = 64; pub const O_NOTRANS: ::c_int = 128; pub const O_NOFOLLOW: ::c_int = 1048576; pub const O_DIRECTORY: ::c_int = 2097152; pub const O_APPEND: ::c_int = 256; pub const O_ASYNC: ::c_int = 512; pub const O_FSYNC: ::c_int = 1024; pub const O_SYNC: ::c_int = 1024; pub const O_NOATIME: ::c_int = 2048; pub const O_SHLOCK: ::c_int = 131072; pub const O_EXLOCK: ::c_int = 262144; pub const O_DSYNC: ::c_int = 1024; pub const O_RSYNC: ::c_int = 1024; pub const O_NONBLOCK: ::c_int = 8; pub const O_NDELAY: ::c_int = 8; pub const O_HURD: ::c_int = 458751; pub const O_TRUNC: ::c_int = 65536; pub const O_CLOEXEC: ::c_int = 4194304; pub const O_IGNORE_CTTY: ::c_int = 524288; pub const O_TMPFILE: ::c_int = 8388608; pub const O_NOCTTY: ::c_int = 0; pub const FREAD: ::c_int = 1; pub const FWRITE: ::c_int = 2; pub const FASYNC: ::c_int = 512; pub const FCREAT: ::c_int = 16; pub const FEXCL: ::c_int = 32; pub const FTRUNC: ::c_int = 65536; pub const FNOCTTY: ::c_int = 0; pub const FFSYNC: ::c_int = 1024; pub const FSYNC: ::c_int = 1024; pub const FAPPEND: ::c_int = 256; pub const FNONBLOCK: ::c_int = 8; pub const FNDELAY: ::c_int = 8; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const F_GETOWN: ::c_int = 5; pub const F_SETOWN: ::c_int = 6; pub const F_GETLK: ::c_int = 7; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const F_GETLK64: ::c_int = 10; pub const F_SETLK64: ::c_int = 11; pub const F_SETLKW64: ::c_int = 12; pub const F_DUPFD_CLOEXEC: ::c_int = 1030; pub const FD_CLOEXEC: ::c_int = 1; pub const F_RDLCK: ::c_int = 1; pub const F_WRLCK: ::c_int = 2; pub const F_UNLCK: ::c_int = 3; pub const POSIX_FADV_NORMAL: ::c_int = 0; pub const POSIX_FADV_RANDOM: ::c_int = 1; pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_FADV_WILLNEED: ::c_int = 3; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const AT_FDCWD: ::c_int = -100; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 256; pub const AT_REMOVEDIR: ::c_int = 512; pub const AT_SYMLINK_FOLLOW: ::c_int = 1024; pub const AT_NO_AUTOMOUNT: ::c_int = 2048; pub const AT_EMPTY_PATH: ::c_int = 4096; pub const AT_STATX_SYNC_TYPE: ::c_int = 24576; pub const AT_STATX_SYNC_AS_STAT: ::c_int = 0; pub const AT_STATX_FORCE_SYNC: ::c_int = 8192; pub const AT_STATX_DONT_SYNC: ::c_int = 16384; pub const AT_RECURSIVE: ::c_int = 32768; pub const AT_EACCESS: ::c_int = 512; // sys/uio.h pub const RWF_HIPRI: ::c_int = 1; pub const RWF_DSYNC: ::c_int = 2; pub const RWF_SYNC: ::c_int = 4; pub const RWF_NOWAIT: ::c_int = 8; pub const RWF_APPEND: ::c_int = 16; // errno.h pub const EPERM: ::c_int = 1073741825; pub const ENOENT: ::c_int = 1073741826; pub const ESRCH: ::c_int = 1073741827; pub const EINTR: ::c_int = 1073741828; pub const EIO: ::c_int = 1073741829; pub const ENXIO: ::c_int = 1073741830; pub const E2BIG: ::c_int = 1073741831; pub const ENOEXEC: ::c_int = 1073741832; pub const EBADF: ::c_int = 1073741833; pub const ECHILD: ::c_int = 1073741834; pub const EDEADLK: ::c_int = 1073741835; pub const ENOMEM: ::c_int = 1073741836; pub const EACCES: ::c_int = 1073741837; pub const EFAULT: ::c_int = 1073741838; pub const ENOTBLK: ::c_int = 1073741839; pub const EBUSY: ::c_int = 1073741840; pub const EEXIST: ::c_int = 1073741841; pub const EXDEV: ::c_int = 1073741842; pub const ENODEV: ::c_int = 1073741843; pub const ENOTDIR: ::c_int = 1073741844; pub const EISDIR: ::c_int = 1073741845; pub const EINVAL: ::c_int = 1073741846; pub const EMFILE: ::c_int = 1073741848; pub const ENFILE: ::c_int = 1073741847; pub const ENOTTY: ::c_int = 1073741849; pub const ETXTBSY: ::c_int = 1073741850; pub const EFBIG: ::c_int = 1073741851; pub const ENOSPC: ::c_int = 1073741852; pub const ESPIPE: ::c_int = 1073741853; pub const EROFS: ::c_int = 1073741854; pub const EMLINK: ::c_int = 1073741855; pub const EPIPE: ::c_int = 1073741856; pub const EDOM: ::c_int = 1073741857; pub const ERANGE: ::c_int = 1073741858; pub const EAGAIN: ::c_int = 1073741859; pub const EWOULDBLOCK: ::c_int = 1073741859; pub const EINPROGRESS: ::c_int = 1073741860; pub const EALREADY: ::c_int = 1073741861; pub const ENOTSOCK: ::c_int = 1073741862; pub const EMSGSIZE: ::c_int = 1073741864; pub const EPROTOTYPE: ::c_int = 1073741865; pub const ENOPROTOOPT: ::c_int = 1073741866; pub const EPROTONOSUPPORT: ::c_int = 1073741867; pub const ESOCKTNOSUPPORT: ::c_int = 1073741868; pub const EOPNOTSUPP: ::c_int = 1073741869; pub const EPFNOSUPPORT: ::c_int = 1073741870; pub const EAFNOSUPPORT: ::c_int = 1073741871; pub const EADDRINUSE: ::c_int = 1073741872; pub const EADDRNOTAVAIL: ::c_int = 1073741873; pub const ENETDOWN: ::c_int = 1073741874; pub const ENETUNREACH: ::c_int = 1073741875; pub const ENETRESET: ::c_int = 1073741876; pub const ECONNABORTED: ::c_int = 1073741877; pub const ECONNRESET: ::c_int = 1073741878; pub const ENOBUFS: ::c_int = 1073741879; pub const EISCONN: ::c_int = 1073741880; pub const ENOTCONN: ::c_int = 1073741881; pub const EDESTADDRREQ: ::c_int = 1073741863; pub const ESHUTDOWN: ::c_int = 1073741882; pub const ETOOMANYREFS: ::c_int = 1073741883; pub const ETIMEDOUT: ::c_int = 1073741884; pub const ECONNREFUSED: ::c_int = 1073741885; pub const ELOOP: ::c_int = 1073741886; pub const ENAMETOOLONG: ::c_int = 1073741887; pub const EHOSTDOWN: ::c_int = 1073741888; pub const EHOSTUNREACH: ::c_int = 1073741889; pub const ENOTEMPTY: ::c_int = 1073741890; pub const EPROCLIM: ::c_int = 1073741891; pub const EUSERS: ::c_int = 1073741892; pub const EDQUOT: ::c_int = 1073741893; pub const ESTALE: ::c_int = 1073741894; pub const EREMOTE: ::c_int = 1073741895; pub const EBADRPC: ::c_int = 1073741896; pub const ERPCMISMATCH: ::c_int = 1073741897; pub const EPROGUNAVAIL: ::c_int = 1073741898; pub const EPROGMISMATCH: ::c_int = 1073741899; pub const EPROCUNAVAIL: ::c_int = 1073741900; pub const ENOLCK: ::c_int = 1073741901; pub const EFTYPE: ::c_int = 1073741903; pub const EAUTH: ::c_int = 1073741904; pub const ENEEDAUTH: ::c_int = 1073741905; pub const ENOSYS: ::c_int = 1073741902; pub const ELIBEXEC: ::c_int = 1073741907; pub const ENOTSUP: ::c_int = 1073741942; pub const EILSEQ: ::c_int = 1073741930; pub const EBACKGROUND: ::c_int = 1073741924; pub const EDIED: ::c_int = 1073741925; pub const EGREGIOUS: ::c_int = 1073741927; pub const EIEIO: ::c_int = 1073741928; pub const EGRATUITOUS: ::c_int = 1073741929; pub const EBADMSG: ::c_int = 1073741931; pub const EIDRM: ::c_int = 1073741932; pub const EMULTIHOP: ::c_int = 1073741933; pub const ENODATA: ::c_int = 1073741934; pub const ENOLINK: ::c_int = 1073741935; pub const ENOMSG: ::c_int = 1073741936; pub const ENOSR: ::c_int = 1073741937; pub const ENOSTR: ::c_int = 1073741938; pub const EOVERFLOW: ::c_int = 1073741939; pub const EPROTO: ::c_int = 1073741940; pub const ETIME: ::c_int = 1073741941; pub const ECANCELED: ::c_int = 1073741943; pub const EOWNERDEAD: ::c_int = 1073741944; pub const ENOTRECOVERABLE: ::c_int = 1073741945; pub const EMACH_SEND_IN_PROGRESS: ::c_int = 268435457; pub const EMACH_SEND_INVALID_DATA: ::c_int = 268435458; pub const EMACH_SEND_INVALID_DEST: ::c_int = 268435459; pub const EMACH_SEND_TIMED_OUT: ::c_int = 268435460; pub const EMACH_SEND_WILL_NOTIFY: ::c_int = 268435461; pub const EMACH_SEND_NOTIFY_IN_PROGRESS: ::c_int = 268435462; pub const EMACH_SEND_INTERRUPTED: ::c_int = 268435463; pub const EMACH_SEND_MSG_TOO_SMALL: ::c_int = 268435464; pub const EMACH_SEND_INVALID_REPLY: ::c_int = 268435465; pub const EMACH_SEND_INVALID_RIGHT: ::c_int = 268435466; pub const EMACH_SEND_INVALID_NOTIFY: ::c_int = 268435467; pub const EMACH_SEND_INVALID_MEMORY: ::c_int = 268435468; pub const EMACH_SEND_NO_BUFFER: ::c_int = 268435469; pub const EMACH_SEND_NO_NOTIFY: ::c_int = 268435470; pub const EMACH_SEND_INVALID_TYPE: ::c_int = 268435471; pub const EMACH_SEND_INVALID_HEADER: ::c_int = 268435472; pub const EMACH_RCV_IN_PROGRESS: ::c_int = 268451841; pub const EMACH_RCV_INVALID_NAME: ::c_int = 268451842; pub const EMACH_RCV_TIMED_OUT: ::c_int = 268451843; pub const EMACH_RCV_TOO_LARGE: ::c_int = 268451844; pub const EMACH_RCV_INTERRUPTED: ::c_int = 268451845; pub const EMACH_RCV_PORT_CHANGED: ::c_int = 268451846; pub const EMACH_RCV_INVALID_NOTIFY: ::c_int = 268451847; pub const EMACH_RCV_INVALID_DATA: ::c_int = 268451848; pub const EMACH_RCV_PORT_DIED: ::c_int = 268451849; pub const EMACH_RCV_IN_SET: ::c_int = 268451850; pub const EMACH_RCV_HEADER_ERROR: ::c_int = 268451851; pub const EMACH_RCV_BODY_ERROR: ::c_int = 268451852; pub const EKERN_INVALID_ADDRESS: ::c_int = 1; pub const EKERN_PROTECTION_FAILURE: ::c_int = 2; pub const EKERN_NO_SPACE: ::c_int = 3; pub const EKERN_INVALID_ARGUMENT: ::c_int = 4; pub const EKERN_FAILURE: ::c_int = 5; pub const EKERN_RESOURCE_SHORTAGE: ::c_int = 6; pub const EKERN_NOT_RECEIVER: ::c_int = 7; pub const EKERN_NO_ACCESS: ::c_int = 8; pub const EKERN_MEMORY_FAILURE: ::c_int = 9; pub const EKERN_MEMORY_ERROR: ::c_int = 10; pub const EKERN_NOT_IN_SET: ::c_int = 12; pub const EKERN_NAME_EXISTS: ::c_int = 13; pub const EKERN_ABORTED: ::c_int = 14; pub const EKERN_INVALID_NAME: ::c_int = 15; pub const EKERN_INVALID_TASK: ::c_int = 16; pub const EKERN_INVALID_RIGHT: ::c_int = 17; pub const EKERN_INVALID_VALUE: ::c_int = 18; pub const EKERN_UREFS_OVERFLOW: ::c_int = 19; pub const EKERN_INVALID_CAPABILITY: ::c_int = 20; pub const EKERN_RIGHT_EXISTS: ::c_int = 21; pub const EKERN_INVALID_HOST: ::c_int = 22; pub const EKERN_MEMORY_PRESENT: ::c_int = 23; pub const EKERN_WRITE_PROTECTION_FAILURE: ::c_int = 24; pub const EKERN_TERMINATED: ::c_int = 26; pub const EKERN_TIMEDOUT: ::c_int = 27; pub const EKERN_INTERRUPTED: ::c_int = 28; pub const EMIG_TYPE_ERROR: ::c_int = -300; pub const EMIG_REPLY_MISMATCH: ::c_int = -301; pub const EMIG_REMOTE_ERROR: ::c_int = -302; pub const EMIG_BAD_ID: ::c_int = -303; pub const EMIG_BAD_ARGUMENTS: ::c_int = -304; pub const EMIG_NO_REPLY: ::c_int = -305; pub const EMIG_EXCEPTION: ::c_int = -306; pub const EMIG_ARRAY_TOO_LARGE: ::c_int = -307; pub const EMIG_SERVER_DIED: ::c_int = -308; pub const EMIG_DESTROY_REQUEST: ::c_int = -309; pub const ED_IO_ERROR: ::c_int = 2500; pub const ED_WOULD_BLOCK: ::c_int = 2501; pub const ED_NO_SUCH_DEVICE: ::c_int = 2502; pub const ED_ALREADY_OPEN: ::c_int = 2503; pub const ED_DEVICE_DOWN: ::c_int = 2504; pub const ED_INVALID_OPERATION: ::c_int = 2505; pub const ED_INVALID_RECNUM: ::c_int = 2506; pub const ED_INVALID_SIZE: ::c_int = 2507; pub const ED_NO_MEMORY: ::c_int = 2508; pub const ED_READ_ONLY: ::c_int = 2509; pub const _HURD_ERRNOS: usize = 122; // sched.h pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const _BITS_TYPES_STRUCT_SCHED_PARAM: usize = 1; pub const __CPU_SETSIZE: usize = 1024; pub const CPU_SETSIZE: usize = 1024; // pthread.h pub const PTHREAD_SPINLOCK_INITIALIZER: ::c_int = 0; pub const PTHREAD_CANCEL_DISABLE: ::c_int = 0; pub const PTHREAD_CANCEL_ENABLE: ::c_int = 1; pub const PTHREAD_CANCEL_DEFERRED: ::c_int = 0; pub const PTHREAD_CANCEL_ASYNCHRONOUS: ::c_int = 1; pub const PTHREAD_BARRIER_SERIAL_THREAD: ::c_int = -1; // netinet/tcp.h pub const TCP_NODELAY: ::c_int = 1; pub const TCP_MAXSEG: ::c_int = 2; pub const TCP_CORK: ::c_int = 3; pub const TCP_KEEPIDLE: ::c_int = 4; pub const TCP_KEEPINTVL: ::c_int = 5; pub const TCP_KEEPCNT: ::c_int = 6; pub const TCP_SYNCNT: ::c_int = 7; pub const TCP_LINGER2: ::c_int = 8; pub const TCP_DEFER_ACCEPT: ::c_int = 9; pub const TCP_WINDOW_CLAMP: ::c_int = 10; pub const TCP_INFO: ::c_int = 11; pub const TCP_QUICKACK: ::c_int = 12; pub const TCP_CONGESTION: ::c_int = 13; pub const TCP_MD5SIG: ::c_int = 14; pub const TCP_COOKIE_TRANSACTIONS: ::c_int = 15; pub const TCP_THIN_LINEAR_TIMEOUTS: ::c_int = 16; pub const TCP_THIN_DUPACK: ::c_int = 17; pub const TCP_USER_TIMEOUT: ::c_int = 18; pub const TCP_REPAIR: ::c_int = 19; pub const TCP_REPAIR_QUEUE: ::c_int = 20; pub const TCP_QUEUE_SEQ: ::c_int = 21; pub const TCP_REPAIR_OPTIONS: ::c_int = 22; pub const TCP_FASTOPEN: ::c_int = 23; pub const TCP_TIMESTAMP: ::c_int = 24; pub const TCP_NOTSENT_LOWAT: ::c_int = 25; pub const TCP_CC_INFO: ::c_int = 26; pub const TCP_SAVE_SYN: ::c_int = 27; pub const TCP_SAVED_SYN: ::c_int = 28; pub const TCP_REPAIR_WINDOW: ::c_int = 29; pub const TCP_FASTOPEN_CONNECT: ::c_int = 30; pub const TCP_ULP: ::c_int = 31; pub const TCP_MD5SIG_EXT: ::c_int = 32; pub const TCP_FASTOPEN_KEY: ::c_int = 33; pub const TCP_FASTOPEN_NO_COOKIE: ::c_int = 34; pub const TCP_ZEROCOPY_RECEIVE: ::c_int = 35; pub const TCP_INQ: ::c_int = 36; pub const TCP_CM_INQ: ::c_int = 36; pub const TCP_TX_DELAY: ::c_int = 37; pub const TCP_REPAIR_ON: ::c_int = 1; pub const TCP_REPAIR_OFF: ::c_int = 0; pub const TCP_REPAIR_OFF_NO_WP: ::c_int = -1; // stdint.h pub const INT8_MIN: i8 = -128; pub const INT16_MIN: i16 = -32768; pub const INT32_MIN: i32 = -2147483648; pub const INT8_MAX: i8 = 127; pub const INT16_MAX: i16 = 32767; pub const INT32_MAX: i32 = 2147483647; pub const UINT8_MAX: u8 = 255; pub const UINT16_MAX: u16 = 65535; pub const UINT32_MAX: u32 = 4294967295; pub const INT_LEAST8_MIN: int_least8_t = -128; pub const INT_LEAST16_MIN: int_least16_t = -32768; pub const INT_LEAST32_MIN: int_least32_t = -2147483648; pub const INT_LEAST8_MAX: int_least8_t = 127; pub const INT_LEAST16_MAX: int_least16_t = 32767; pub const INT_LEAST32_MAX: int_least32_t = 2147483647; pub const UINT_LEAST8_MAX: uint_least8_t = 255; pub const UINT_LEAST16_MAX: uint_least16_t = 65535; pub const UINT_LEAST32_MAX: uint_least32_t = 4294967295; pub const INT_FAST8_MIN: int_fast8_t = -128; pub const INT_FAST16_MIN: int_fast16_t = -2147483648; pub const INT_FAST32_MIN: int_fast32_t = -2147483648; pub const INT_FAST8_MAX: int_fast8_t = 127; pub const INT_FAST16_MAX: int_fast16_t = 2147483647; pub const INT_FAST32_MAX: int_fast32_t = 2147483647; pub const UINT_FAST8_MAX: uint_fast8_t = 255; pub const UINT_FAST16_MAX: uint_fast16_t = 4294967295; pub const UINT_FAST32_MAX: uint_fast32_t = 4294967295; pub const INTPTR_MIN: __intptr_t = -2147483648; pub const INTPTR_MAX: __intptr_t = 2147483647; pub const UINTPTR_MAX: usize = 4294967295; pub const PTRDIFF_MIN: __ptrdiff_t = -2147483648; pub const PTRDIFF_MAX: __ptrdiff_t = 2147483647; pub const SIG_ATOMIC_MIN: __sig_atomic_t = -2147483648; pub const SIG_ATOMIC_MAX: __sig_atomic_t = 2147483647; pub const SIZE_MAX: usize = 4294967295; pub const WINT_MIN: wint_t = 0; pub const WINT_MAX: wint_t = 4294967295; pub const INT8_WIDTH: usize = 8; pub const UINT8_WIDTH: usize = 8; pub const INT16_WIDTH: usize = 16; pub const UINT16_WIDTH: usize = 16; pub const INT32_WIDTH: usize = 32; pub const UINT32_WIDTH: usize = 32; pub const INT64_WIDTH: usize = 64; pub const UINT64_WIDTH: usize = 64; pub const INT_LEAST8_WIDTH: usize = 8; pub const UINT_LEAST8_WIDTH: usize = 8; pub const INT_LEAST16_WIDTH: usize = 16; pub const UINT_LEAST16_WIDTH: usize = 16; pub const INT_LEAST32_WIDTH: usize = 32; pub const UINT_LEAST32_WIDTH: usize = 32; pub const INT_LEAST64_WIDTH: usize = 64; pub const UINT_LEAST64_WIDTH: usize = 64; pub const INT_FAST8_WIDTH: usize = 8; pub const UINT_FAST8_WIDTH: usize = 8; pub const INT_FAST16_WIDTH: usize = 32; pub const UINT_FAST16_WIDTH: usize = 32; pub const INT_FAST32_WIDTH: usize = 32; pub const UINT_FAST32_WIDTH: usize = 32; pub const INT_FAST64_WIDTH: usize = 64; pub const UINT_FAST64_WIDTH: usize = 64; pub const INTPTR_WIDTH: usize = 32; pub const UINTPTR_WIDTH: usize = 32; pub const INTMAX_WIDTH: usize = 64; pub const UINTMAX_WIDTH: usize = 64; pub const PTRDIFF_WIDTH: usize = 32; pub const SIG_ATOMIC_WIDTH: usize = 32; pub const SIZE_WIDTH: usize = 32; pub const WCHAR_WIDTH: usize = 32; pub const WINT_WIDTH: usize = 32; pub const TH_FIN: u8 = 1; pub const TH_SYN: u8 = 2; pub const TH_RST: u8 = 4; pub const TH_PUSH: u8 = 8; pub const TH_ACK: u8 = 16; pub const TH_URG: u8 = 32; pub const TCPOPT_EOL: u8 = 0; pub const TCPOPT_NOP: u8 = 1; pub const TCPOPT_MAXSEG: u8 = 2; pub const TCPOLEN_MAXSEG: u8 = 4; pub const TCPOPT_WINDOW: u8 = 3; pub const TCPOLEN_WINDOW: u8 = 3; pub const TCPOPT_SACK_PERMITTED: u8 = 4; pub const TCPOLEN_SACK_PERMITTED: u8 = 2; pub const TCPOPT_SACK: u8 = 5; pub const TCPOPT_TIMESTAMP: u8 = 8; pub const TCPOLEN_TIMESTAMP: u8 = 10; pub const TCPOLEN_TSTAMP_APPA: u8 = 12; pub const TCPOPT_TSTAMP_HDR: u32 = 16844810; pub const TCP_MSS: usize = 512; pub const TCP_MAXWIN: usize = 65535; pub const TCP_MAX_WINSHIFT: usize = 14; pub const TCPI_OPT_TIMESTAMPS: u8 = 1; pub const TCPI_OPT_SACK: u8 = 2; pub const TCPI_OPT_WSCALE: u8 = 4; pub const TCPI_OPT_ECN: u8 = 8; pub const TCPI_OPT_ECN_SEEN: u8 = 16; pub const TCPI_OPT_SYN_DATA: u8 = 32; pub const TCP_MD5SIG_MAXKEYLEN: usize = 80; pub const TCP_MD5SIG_FLAG_PREFIX: usize = 1; pub const TCP_COOKIE_MIN: usize = 8; pub const TCP_COOKIE_MAX: usize = 16; pub const TCP_COOKIE_PAIR_SIZE: usize = 32; pub const TCP_COOKIE_IN_ALWAYS: ::c_int = 1; pub const TCP_COOKIE_OUT_NEVER: ::c_int = 2; pub const TCP_S_DATA_IN: ::c_int = 4; pub const TCP_S_DATA_OUT: ::c_int = 8; pub const TCP_MSS_DEFAULT: usize = 536; pub const TCP_MSS_DESIRED: usize = 1220; // sys/wait.h pub const WCOREFLAG: ::c_int = 128; pub const WAIT_ANY: pid_t = -1; pub const WAIT_MYPGRP: pid_t = 0; // sys/file.h pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_UN: ::c_int = 8; pub const LOCK_NB: ::c_int = 4; // sys/mman.h pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 4; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 1; pub const MAP_FILE: ::c_int = 1; pub const MAP_ANON: ::c_int = 2; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const MAP_TYPE: ::c_int = 15; pub const MAP_COPY: ::c_int = 32; pub const MAP_SHARED: ::c_int = 16; pub const MAP_PRIVATE: ::c_int = 0; pub const MAP_FIXED: ::c_int = 256; pub const MAP_NOEXTEND: ::c_int = 512; pub const MAP_HASSEMPHORE: ::c_int = 1024; pub const MAP_INHERIT: ::c_int = 2048; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_MADV_WONTNEED: ::c_int = 4; pub const MS_ASYNC: ::c_int = 1; pub const MS_SYNC: ::c_int = 0; pub const MS_INVALIDATE: ::c_int = 2; pub const MREMAP_MAYMOVE: ::c_int = 1; pub const MREMAP_FIXED: ::c_int = 2; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; // spawn.h pub const POSIX_SPAWN_USEVFORK: ::c_int = 64; pub const POSIX_SPAWN_SETSID: ::c_int = 128; // sys/syslog.h pub const LOG_CRON: ::c_int = 9 << 3; pub const LOG_AUTHPRIV: ::c_int = 10 << 3; pub const LOG_FTP: ::c_int = 11 << 3; pub const LOG_PERROR: ::c_int = 0x20; // net/if.h pub const IFF_UP: ::c_int = 0x1; pub const IFF_BROADCAST: ::c_int = 0x2; pub const IFF_DEBUG: ::c_int = 0x4; pub const IFF_LOOPBACK: ::c_int = 0x8; pub const IFF_POINTOPOINT: ::c_int = 0x10; pub const IFF_NOTRAILERS: ::c_int = 0x20; pub const IFF_RUNNING: ::c_int = 0x40; pub const IFF_NOARP: ::c_int = 0x80; pub const IFF_PROMISC: ::c_int = 0x100; pub const IFF_ALLMULTI: ::c_int = 0x200; pub const IFF_MASTER: ::c_int = 0x400; pub const IFF_SLAVE: ::c_int = 0x800; pub const IFF_MULTICAST: ::c_int = 0x1000; pub const IFF_PORTSEL: ::c_int = 0x2000; pub const IFF_AUTOMEDIA: ::c_int = 0x4000; pub const IFF_DYNAMIC: ::c_int = 0x8000; // random.h pub const GRND_NONBLOCK: ::c_uint = 1; pub const GRND_RANDOM: ::c_uint = 2; pub const GRND_INSECURE: ::c_uint = 4; pub const _PC_LINK_MAX: ::c_int = 0; pub const _PC_MAX_CANON: ::c_int = 1; pub const _PC_MAX_INPUT: ::c_int = 2; pub const _PC_NAME_MAX: ::c_int = 3; pub const _PC_PATH_MAX: ::c_int = 4; pub const _PC_PIPE_BUF: ::c_int = 5; pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_SYNC_IO: ::c_int = 9; pub const _PC_ASYNC_IO: ::c_int = 10; pub const _PC_PRIO_IO: ::c_int = 11; pub const _PC_SOCK_MAXBUF: ::c_int = 12; pub const _PC_FILESIZEBITS: ::c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; pub const _PC_REC_XFER_ALIGN: ::c_int = 17; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18; pub const _PC_SYMLINK_MAX: ::c_int = 19; pub const _PC_2_SYMLINKS: ::c_int = 20; pub const _SC_ARG_MAX: ::c_int = 0; pub const _SC_CHILD_MAX: ::c_int = 1; pub const _SC_CLK_TCK: ::c_int = 2; pub const _SC_NGROUPS_MAX: ::c_int = 3; pub const _SC_OPEN_MAX: ::c_int = 4; pub const _SC_STREAM_MAX: ::c_int = 5; pub const _SC_TZNAME_MAX: ::c_int = 6; pub const _SC_JOB_CONTROL: ::c_int = 7; pub const _SC_SAVED_IDS: ::c_int = 8; pub const _SC_REALTIME_SIGNALS: ::c_int = 9; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 10; pub const _SC_TIMERS: ::c_int = 11; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 12; pub const _SC_PRIORITIZED_IO: ::c_int = 13; pub const _SC_SYNCHRONIZED_IO: ::c_int = 14; pub const _SC_FSYNC: ::c_int = 15; pub const _SC_MAPPED_FILES: ::c_int = 16; pub const _SC_MEMLOCK: ::c_int = 17; pub const _SC_MEMLOCK_RANGE: ::c_int = 18; pub const _SC_MEMORY_PROTECTION: ::c_int = 19; pub const _SC_MESSAGE_PASSING: ::c_int = 20; pub const _SC_SEMAPHORES: ::c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 22; pub const _SC_AIO_LISTIO_MAX: ::c_int = 23; pub const _SC_AIO_MAX: ::c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 25; pub const _SC_DELAYTIMER_MAX: ::c_int = 26; pub const _SC_MQ_OPEN_MAX: ::c_int = 27; pub const _SC_MQ_PRIO_MAX: ::c_int = 28; pub const _SC_VERSION: ::c_int = 29; pub const _SC_PAGESIZE: ::c_int = 30; pub const _SC_PAGE_SIZE: ::c_int = 30; pub const _SC_RTSIG_MAX: ::c_int = 31; pub const _SC_SEM_NSEMS_MAX: ::c_int = 32; pub const _SC_SEM_VALUE_MAX: ::c_int = 33; pub const _SC_SIGQUEUE_MAX: ::c_int = 34; pub const _SC_TIMER_MAX: ::c_int = 35; pub const _SC_BC_BASE_MAX: ::c_int = 36; pub const _SC_BC_DIM_MAX: ::c_int = 37; pub const _SC_BC_SCALE_MAX: ::c_int = 38; pub const _SC_BC_STRING_MAX: ::c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 40; pub const _SC_EQUIV_CLASS_MAX: ::c_int = 41; pub const _SC_EXPR_NEST_MAX: ::c_int = 42; pub const _SC_LINE_MAX: ::c_int = 43; pub const _SC_RE_DUP_MAX: ::c_int = 44; pub const _SC_CHARCLASS_NAME_MAX: ::c_int = 45; pub const _SC_2_VERSION: ::c_int = 46; pub const _SC_2_C_BIND: ::c_int = 47; pub const _SC_2_C_DEV: ::c_int = 48; pub const _SC_2_FORT_DEV: ::c_int = 49; pub const _SC_2_FORT_RUN: ::c_int = 50; pub const _SC_2_SW_DEV: ::c_int = 51; pub const _SC_2_LOCALEDEF: ::c_int = 52; pub const _SC_PII: ::c_int = 53; pub const _SC_PII_XTI: ::c_int = 54; pub const _SC_PII_SOCKET: ::c_int = 55; pub const _SC_PII_INTERNET: ::c_int = 56; pub const _SC_PII_OSI: ::c_int = 57; pub const _SC_POLL: ::c_int = 58; pub const _SC_SELECT: ::c_int = 59; pub const _SC_UIO_MAXIOV: ::c_int = 60; pub const _SC_IOV_MAX: ::c_int = 60; pub const _SC_PII_INTERNET_STREAM: ::c_int = 61; pub const _SC_PII_INTERNET_DGRAM: ::c_int = 62; pub const _SC_PII_OSI_COTS: ::c_int = 63; pub const _SC_PII_OSI_CLTS: ::c_int = 64; pub const _SC_PII_OSI_M: ::c_int = 65; pub const _SC_T_IOV_MAX: ::c_int = 66; pub const _SC_THREADS: ::c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 70; pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; pub const _SC_TTY_NAME_MAX: ::c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 73; pub const _SC_THREAD_KEYS_MAX: ::c_int = 74; pub const _SC_THREAD_STACK_MIN: ::c_int = 75; pub const _SC_THREAD_THREADS_MAX: ::c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 82; pub const _SC_NPROCESSORS_CONF: ::c_int = 83; pub const _SC_NPROCESSORS_ONLN: ::c_int = 84; pub const _SC_PHYS_PAGES: ::c_int = 85; pub const _SC_AVPHYS_PAGES: ::c_int = 86; pub const _SC_ATEXIT_MAX: ::c_int = 87; pub const _SC_PASS_MAX: ::c_int = 88; pub const _SC_XOPEN_VERSION: ::c_int = 89; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 90; pub const _SC_XOPEN_UNIX: ::c_int = 91; pub const _SC_XOPEN_CRYPT: ::c_int = 92; pub const _SC_XOPEN_ENH_I18N: ::c_int = 93; pub const _SC_XOPEN_SHM: ::c_int = 94; pub const _SC_2_CHAR_TERM: ::c_int = 95; pub const _SC_2_C_VERSION: ::c_int = 96; pub const _SC_2_UPE: ::c_int = 97; pub const _SC_XOPEN_XPG2: ::c_int = 98; pub const _SC_XOPEN_XPG3: ::c_int = 99; pub const _SC_XOPEN_XPG4: ::c_int = 100; pub const _SC_CHAR_BIT: ::c_int = 101; pub const _SC_CHAR_MAX: ::c_int = 102; pub const _SC_CHAR_MIN: ::c_int = 103; pub const _SC_INT_MAX: ::c_int = 104; pub const _SC_INT_MIN: ::c_int = 105; pub const _SC_LONG_BIT: ::c_int = 106; pub const _SC_WORD_BIT: ::c_int = 107; pub const _SC_MB_LEN_MAX: ::c_int = 108; pub const _SC_NZERO: ::c_int = 109; pub const _SC_SSIZE_MAX: ::c_int = 110; pub const _SC_SCHAR_MAX: ::c_int = 111; pub const _SC_SCHAR_MIN: ::c_int = 112; pub const _SC_SHRT_MAX: ::c_int = 113; pub const _SC_SHRT_MIN: ::c_int = 114; pub const _SC_UCHAR_MAX: ::c_int = 115; pub const _SC_UINT_MAX: ::c_int = 116; pub const _SC_ULONG_MAX: ::c_int = 117; pub const _SC_USHRT_MAX: ::c_int = 118; pub const _SC_NL_ARGMAX: ::c_int = 119; pub const _SC_NL_LANGMAX: ::c_int = 120; pub const _SC_NL_MSGMAX: ::c_int = 121; pub const _SC_NL_NMAX: ::c_int = 122; pub const _SC_NL_SETMAX: ::c_int = 123; pub const _SC_NL_TEXTMAX: ::c_int = 124; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 126; pub const _SC_XBS5_LP64_OFF64: ::c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 128; pub const _SC_XOPEN_LEGACY: ::c_int = 129; pub const _SC_XOPEN_REALTIME: ::c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 131; pub const _SC_ADVISORY_INFO: ::c_int = 132; pub const _SC_BARRIERS: ::c_int = 133; pub const _SC_BASE: ::c_int = 134; pub const _SC_C_LANG_SUPPORT: ::c_int = 135; pub const _SC_C_LANG_SUPPORT_R: ::c_int = 136; pub const _SC_CLOCK_SELECTION: ::c_int = 137; pub const _SC_CPUTIME: ::c_int = 138; pub const _SC_THREAD_CPUTIME: ::c_int = 139; pub const _SC_DEVICE_IO: ::c_int = 140; pub const _SC_DEVICE_SPECIFIC: ::c_int = 141; pub const _SC_DEVICE_SPECIFIC_R: ::c_int = 142; pub const _SC_FD_MGMT: ::c_int = 143; pub const _SC_FIFO: ::c_int = 144; pub const _SC_PIPE: ::c_int = 145; pub const _SC_FILE_ATTRIBUTES: ::c_int = 146; pub const _SC_FILE_LOCKING: ::c_int = 147; pub const _SC_FILE_SYSTEM: ::c_int = 148; pub const _SC_MONOTONIC_CLOCK: ::c_int = 149; pub const _SC_MULTI_PROCESS: ::c_int = 150; pub const _SC_SINGLE_PROCESS: ::c_int = 151; pub const _SC_NETWORKING: ::c_int = 152; pub const _SC_READER_WRITER_LOCKS: ::c_int = 153; pub const _SC_SPIN_LOCKS: ::c_int = 154; pub const _SC_REGEXP: ::c_int = 155; pub const _SC_REGEX_VERSION: ::c_int = 156; pub const _SC_SHELL: ::c_int = 157; pub const _SC_SIGNALS: ::c_int = 158; pub const _SC_SPAWN: ::c_int = 159; pub const _SC_SPORADIC_SERVER: ::c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 161; pub const _SC_SYSTEM_DATABASE: ::c_int = 162; pub const _SC_SYSTEM_DATABASE_R: ::c_int = 163; pub const _SC_TIMEOUTS: ::c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 165; pub const _SC_USER_GROUPS: ::c_int = 166; pub const _SC_USER_GROUPS_R: ::c_int = 167; pub const _SC_2_PBS: ::c_int = 168; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 169; pub const _SC_2_PBS_LOCATE: ::c_int = 170; pub const _SC_2_PBS_MESSAGE: ::c_int = 171; pub const _SC_2_PBS_TRACK: ::c_int = 172; pub const _SC_SYMLOOP_MAX: ::c_int = 173; pub const _SC_STREAMS: ::c_int = 174; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 175; pub const _SC_V6_ILP32_OFF32: ::c_int = 176; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 177; pub const _SC_V6_LP64_OFF64: ::c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 179; pub const _SC_HOST_NAME_MAX: ::c_int = 180; pub const _SC_TRACE: ::c_int = 181; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 182; pub const _SC_TRACE_INHERIT: ::c_int = 183; pub const _SC_TRACE_LOG: ::c_int = 184; pub const _SC_LEVEL1_ICACHE_SIZE: ::c_int = 185; pub const _SC_LEVEL1_ICACHE_ASSOC: ::c_int = 186; pub const _SC_LEVEL1_ICACHE_LINESIZE: ::c_int = 187; pub const _SC_LEVEL1_DCACHE_SIZE: ::c_int = 188; pub const _SC_LEVEL1_DCACHE_ASSOC: ::c_int = 189; pub const _SC_LEVEL1_DCACHE_LINESIZE: ::c_int = 190; pub const _SC_LEVEL2_CACHE_SIZE: ::c_int = 191; pub const _SC_LEVEL2_CACHE_ASSOC: ::c_int = 192; pub const _SC_LEVEL2_CACHE_LINESIZE: ::c_int = 193; pub const _SC_LEVEL3_CACHE_SIZE: ::c_int = 194; pub const _SC_LEVEL3_CACHE_ASSOC: ::c_int = 195; pub const _SC_LEVEL3_CACHE_LINESIZE: ::c_int = 196; pub const _SC_LEVEL4_CACHE_SIZE: ::c_int = 197; pub const _SC_LEVEL4_CACHE_ASSOC: ::c_int = 198; pub const _SC_LEVEL4_CACHE_LINESIZE: ::c_int = 199; pub const _SC_IPV6: ::c_int = 235; pub const _SC_RAW_SOCKETS: ::c_int = 236; pub const _SC_V7_ILP32_OFF32: ::c_int = 237; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 238; pub const _SC_V7_LP64_OFF64: ::c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 240; pub const _SC_SS_REPL_MAX: ::c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 242; pub const _SC_TRACE_NAME_MAX: ::c_int = 243; pub const _SC_TRACE_SYS_MAX: ::c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 245; pub const _SC_XOPEN_STREAMS: ::c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248; pub const _SC_MINSIGSTKSZ: ::c_int = 249; pub const _SC_SIGSTKSZ: ::c_int = 250; pub const _CS_PATH: ::c_int = 0; pub const _CS_V6_WIDTH_RESTRICTED_ENVS: ::c_int = 1; pub const _CS_GNU_LIBC_VERSION: ::c_int = 2; pub const _CS_GNU_LIBPTHREAD_VERSION: ::c_int = 3; pub const _CS_V5_WIDTH_RESTRICTED_ENVS: ::c_int = 4; pub const _CS_V7_WIDTH_RESTRICTED_ENVS: ::c_int = 5; pub const _CS_LFS_CFLAGS: ::c_int = 1000; pub const _CS_LFS_LDFLAGS: ::c_int = 1001; pub const _CS_LFS_LIBS: ::c_int = 1002; pub const _CS_LFS_LINTFLAGS: ::c_int = 1003; pub const _CS_LFS64_CFLAGS: ::c_int = 1004; pub const _CS_LFS64_LDFLAGS: ::c_int = 1005; pub const _CS_LFS64_LIBS: ::c_int = 1006; pub const _CS_LFS64_LINTFLAGS: ::c_int = 1007; pub const _CS_XBS5_ILP32_OFF32_CFLAGS: ::c_int = 1100; pub const _CS_XBS5_ILP32_OFF32_LDFLAGS: ::c_int = 1101; pub const _CS_XBS5_ILP32_OFF32_LIBS: ::c_int = 1102; pub const _CS_XBS5_ILP32_OFF32_LINTFLAGS: ::c_int = 1103; pub const _CS_XBS5_ILP32_OFFBIG_CFLAGS: ::c_int = 1104; pub const _CS_XBS5_ILP32_OFFBIG_LDFLAGS: ::c_int = 1105; pub const _CS_XBS5_ILP32_OFFBIG_LIBS: ::c_int = 1106; pub const _CS_XBS5_ILP32_OFFBIG_LINTFLAGS: ::c_int = 1107; pub const _CS_XBS5_LP64_OFF64_CFLAGS: ::c_int = 1108; pub const _CS_XBS5_LP64_OFF64_LDFLAGS: ::c_int = 1109; pub const _CS_XBS5_LP64_OFF64_LIBS: ::c_int = 1110; pub const _CS_XBS5_LP64_OFF64_LINTFLAGS: ::c_int = 1111; pub const _CS_XBS5_LPBIG_OFFBIG_CFLAGS: ::c_int = 1112; pub const _CS_XBS5_LPBIG_OFFBIG_LDFLAGS: ::c_int = 1113; pub const _CS_XBS5_LPBIG_OFFBIG_LIBS: ::c_int = 1114; pub const _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS: ::c_int = 1115; pub const _CS_POSIX_V6_ILP32_OFF32_CFLAGS: ::c_int = 1116; pub const _CS_POSIX_V6_ILP32_OFF32_LDFLAGS: ::c_int = 1117; pub const _CS_POSIX_V6_ILP32_OFF32_LIBS: ::c_int = 1118; pub const _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS: ::c_int = 1119; pub const _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS: ::c_int = 1120; pub const _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS: ::c_int = 1121; pub const _CS_POSIX_V6_ILP32_OFFBIG_LIBS: ::c_int = 1122; pub const _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS: ::c_int = 1123; pub const _CS_POSIX_V6_LP64_OFF64_CFLAGS: ::c_int = 1124; pub const _CS_POSIX_V6_LP64_OFF64_LDFLAGS: ::c_int = 1125; pub const _CS_POSIX_V6_LP64_OFF64_LIBS: ::c_int = 1126; pub const _CS_POSIX_V6_LP64_OFF64_LINTFLAGS: ::c_int = 1127; pub const _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS: ::c_int = 1128; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS: ::c_int = 1129; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LIBS: ::c_int = 1130; pub const _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS: ::c_int = 1131; pub const _CS_POSIX_V7_ILP32_OFF32_CFLAGS: ::c_int = 1132; pub const _CS_POSIX_V7_ILP32_OFF32_LDFLAGS: ::c_int = 1133; pub const _CS_POSIX_V7_ILP32_OFF32_LIBS: ::c_int = 1134; pub const _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS: ::c_int = 1135; pub const _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS: ::c_int = 1136; pub const _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS: ::c_int = 1137; pub const _CS_POSIX_V7_ILP32_OFFBIG_LIBS: ::c_int = 1138; pub const _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS: ::c_int = 1139; pub const _CS_POSIX_V7_LP64_OFF64_CFLAGS: ::c_int = 1140; pub const _CS_POSIX_V7_LP64_OFF64_LDFLAGS: ::c_int = 1141; pub const _CS_POSIX_V7_LP64_OFF64_LIBS: ::c_int = 1142; pub const _CS_POSIX_V7_LP64_OFF64_LINTFLAGS: ::c_int = 1143; pub const _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS: ::c_int = 1144; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS: ::c_int = 1145; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LIBS: ::c_int = 1146; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS: ::c_int = 1147; pub const _CS_V6_ENV: ::c_int = 1148; pub const _CS_V7_ENV: ::c_int = 1149; pub const PTHREAD_PROCESS_PRIVATE: __pthread_process_shared = 0; pub const PTHREAD_PROCESS_SHARED: __pthread_process_shared = 1; pub const PTHREAD_EXPLICIT_SCHED: __pthread_inheritsched = 0; pub const PTHREAD_INHERIT_SCHED: __pthread_inheritsched = 1; pub const PTHREAD_SCOPE_SYSTEM: __pthread_contentionscope = 0; pub const PTHREAD_SCOPE_PROCESS: __pthread_contentionscope = 1; pub const PTHREAD_CREATE_JOINABLE: __pthread_detachstate = 0; pub const PTHREAD_CREATE_DETACHED: __pthread_detachstate = 1; pub const PTHREAD_PRIO_NONE: __pthread_mutex_protocol = 0; pub const PTHREAD_PRIO_INHERIT: __pthread_mutex_protocol = 1; pub const PTHREAD_PRIO_PROTECT: __pthread_mutex_protocol = 2; pub const PTHREAD_MUTEX_TIMED: __pthread_mutex_type = 0; pub const PTHREAD_MUTEX_ERRORCHECK: __pthread_mutex_type = 1; pub const PTHREAD_MUTEX_RECURSIVE: __pthread_mutex_type = 2; pub const PTHREAD_MUTEX_STALLED: __pthread_mutex_robustness = 0; pub const PTHREAD_MUTEX_ROBUST: __pthread_mutex_robustness = 256; pub const RLIMIT_CPU: ::__rlimit_resource_t = 0; pub const RLIMIT_FSIZE: ::__rlimit_resource_t = 1; pub const RLIMIT_DATA: ::__rlimit_resource_t = 2; pub const RLIMIT_STACK: ::__rlimit_resource_t = 3; pub const RLIMIT_CORE: ::__rlimit_resource_t = 4; pub const RLIMIT_RSS: ::__rlimit_resource_t = 5; pub const RLIMIT_MEMLOCK: ::__rlimit_resource_t = 6; pub const RLIMIT_NPROC: ::__rlimit_resource_t = 7; pub const RLIMIT_OFILE: ::__rlimit_resource_t = 8; pub const RLIMIT_NOFILE: ::__rlimit_resource_t = 8; pub const RLIMIT_SBSIZE: ::__rlimit_resource_t = 9; pub const RLIMIT_AS: ::__rlimit_resource_t = 10; pub const RLIMIT_VMEM: ::__rlimit_resource_t = 10; pub const RLIMIT_NLIMITS: ::__rlimit_resource_t = 11; pub const RLIM_NLIMITS: ::__rlimit_resource_t = 11; pub const RUSAGE_SELF: __rusage_who = 0; pub const RUSAGE_CHILDREN: __rusage_who = -1; pub const PRIO_PROCESS: __priority_which = 0; pub const PRIO_PGRP: __priority_which = 1; pub const PRIO_USER: __priority_which = 2; pub const __UT_LINESIZE: usize = 32; pub const __UT_NAMESIZE: usize = 32; pub const __UT_HOSTSIZE: usize = 256; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_CLOEXEC: ::c_int = 4194304; pub const SOCK_NONBLOCK: ::c_int = 2048; pub const MSG_OOB: ::c_int = 1; pub const MSG_PEEK: ::c_int = 2; pub const MSG_DONTROUTE: ::c_int = 4; pub const MSG_EOR: ::c_int = 8; pub const MSG_TRUNC: ::c_int = 16; pub const MSG_CTRUNC: ::c_int = 32; pub const MSG_WAITALL: ::c_int = 64; pub const MSG_DONTWAIT: ::c_int = 128; pub const MSG_NOSIGNAL: ::c_int = 1024; pub const MSG_CMSG_CLOEXEC: ::c_int = 0x40000000; pub const SCM_RIGHTS: ::c_int = 1; pub const SCM_TIMESTAMP: ::c_int = 2; pub const SCM_CREDS: ::c_int = 3; pub const SO_DEBUG: ::c_int = 1; pub const SO_ACCEPTCONN: ::c_int = 2; pub const SO_REUSEADDR: ::c_int = 4; pub const SO_KEEPALIVE: ::c_int = 8; pub const SO_DONTROUTE: ::c_int = 16; pub const SO_BROADCAST: ::c_int = 32; pub const SO_USELOOPBACK: ::c_int = 64; pub const SO_LINGER: ::c_int = 128; pub const SO_OOBINLINE: ::c_int = 256; pub const SO_REUSEPORT: ::c_int = 512; pub const SO_SNDBUF: ::c_int = 4097; pub const SO_RCVBUF: ::c_int = 4098; pub const SO_SNDLOWAT: ::c_int = 4099; pub const SO_RCVLOWAT: ::c_int = 4100; pub const SO_SNDTIMEO: ::c_int = 4101; pub const SO_RCVTIMEO: ::c_int = 4102; pub const SO_ERROR: ::c_int = 4103; pub const SO_STYLE: ::c_int = 4104; pub const SO_TYPE: ::c_int = 4104; pub const IPPROTO_IP: ::c_int = 0; pub const IPPROTO_ICMP: ::c_int = 1; pub const IPPROTO_IGMP: ::c_int = 2; pub const IPPROTO_IPIP: ::c_int = 4; pub const IPPROTO_TCP: ::c_int = 6; pub const IPPROTO_EGP: ::c_int = 8; pub const IPPROTO_PUP: ::c_int = 12; pub const IPPROTO_UDP: ::c_int = 17; pub const IPPROTO_IDP: ::c_int = 22; pub const IPPROTO_TP: ::c_int = 29; pub const IPPROTO_DCCP: ::c_int = 33; pub const IPPROTO_IPV6: ::c_int = 41; pub const IPPROTO_RSVP: ::c_int = 46; pub const IPPROTO_GRE: ::c_int = 47; pub const IPPROTO_ESP: ::c_int = 50; pub const IPPROTO_AH: ::c_int = 51; pub const IPPROTO_MTP: ::c_int = 92; pub const IPPROTO_BEETPH: ::c_int = 94; pub const IPPROTO_ENCAP: ::c_int = 98; pub const IPPROTO_PIM: ::c_int = 103; pub const IPPROTO_COMP: ::c_int = 108; pub const IPPROTO_L2TP: ::c_int = 115; pub const IPPROTO_SCTP: ::c_int = 132; pub const IPPROTO_UDPLITE: ::c_int = 136; pub const IPPROTO_MPLS: ::c_int = 137; pub const IPPROTO_ETHERNET: ::c_int = 143; pub const IPPROTO_RAW: ::c_int = 255; pub const IPPROTO_MPTCP: ::c_int = 262; pub const IPPROTO_MAX: ::c_int = 263; pub const IPPROTO_HOPOPTS: ::c_int = 0; pub const IPPROTO_ROUTING: ::c_int = 43; pub const IPPROTO_FRAGMENT: ::c_int = 44; pub const IPPROTO_ICMPV6: ::c_int = 58; pub const IPPROTO_NONE: ::c_int = 59; pub const IPPROTO_DSTOPTS: ::c_int = 60; pub const IPPROTO_MH: ::c_int = 135; pub const IPPORT_ECHO: in_port_t = 7; pub const IPPORT_DISCARD: in_port_t = 9; pub const IPPORT_SYSTAT: in_port_t = 11; pub const IPPORT_DAYTIME: in_port_t = 13; pub const IPPORT_NETSTAT: in_port_t = 15; pub const IPPORT_FTP: in_port_t = 21; pub const IPPORT_TELNET: in_port_t = 23; pub const IPPORT_SMTP: in_port_t = 25; pub const IPPORT_TIMESERVER: in_port_t = 37; pub const IPPORT_NAMESERVER: in_port_t = 42; pub const IPPORT_WHOIS: in_port_t = 43; pub const IPPORT_MTP: in_port_t = 57; pub const IPPORT_TFTP: in_port_t = 69; pub const IPPORT_RJE: in_port_t = 77; pub const IPPORT_FINGER: in_port_t = 79; pub const IPPORT_TTYLINK: in_port_t = 87; pub const IPPORT_SUPDUP: in_port_t = 95; pub const IPPORT_EXECSERVER: in_port_t = 512; pub const IPPORT_LOGINSERVER: in_port_t = 513; pub const IPPORT_CMDSERVER: in_port_t = 514; pub const IPPORT_EFSSERVER: in_port_t = 520; pub const IPPORT_BIFFUDP: in_port_t = 512; pub const IPPORT_WHOSERVER: in_port_t = 513; pub const IPPORT_ROUTESERVER: in_port_t = 520; pub const IPPORT_USERRESERVED: in_port_t = 5000; pub const DT_UNKNOWN: ::c_uchar = 0; pub const DT_FIFO: ::c_uchar = 1; pub const DT_CHR: ::c_uchar = 2; pub const DT_DIR: ::c_uchar = 4; pub const DT_BLK: ::c_uchar = 6; pub const DT_REG: ::c_uchar = 8; pub const DT_LNK: ::c_uchar = 10; pub const DT_SOCK: ::c_uchar = 12; pub const DT_WHT: ::c_uchar = 14; pub const ST_RDONLY: ::c_ulong = 1; pub const ST_NOSUID: ::c_ulong = 2; pub const ST_NOEXEC: ::c_ulong = 8; pub const ST_SYNCHRONOUS: ::c_ulong = 16; pub const ST_NOATIME: ::c_ulong = 32; pub const ST_RELATIME: ::c_ulong = 64; pub const RTLD_DI_LMID: ::c_int = 1; pub const RTLD_DI_LINKMAP: ::c_int = 2; pub const RTLD_DI_CONFIGADDR: ::c_int = 3; pub const RTLD_DI_SERINFO: ::c_int = 4; pub const RTLD_DI_SERINFOSIZE: ::c_int = 5; pub const RTLD_DI_ORIGIN: ::c_int = 6; pub const RTLD_DI_PROFILENAME: ::c_int = 7; pub const RTLD_DI_PROFILEOUT: ::c_int = 8; pub const RTLD_DI_TLS_MODID: ::c_int = 9; pub const RTLD_DI_TLS_DATA: ::c_int = 10; pub const RTLD_DI_PHDR: ::c_int = 11; pub const RTLD_DI_MAX: ::c_int = 11; pub const SI_ASYNCIO: ::c_int = -4; pub const SI_MESGQ: ::c_int = -3; pub const SI_TIMER: ::c_int = -2; pub const SI_QUEUE: ::c_int = -1; pub const SI_USER: ::c_int = 0; pub const ILL_ILLOPC: ::c_int = 1; pub const ILL_ILLOPN: ::c_int = 2; pub const ILL_ILLADR: ::c_int = 3; pub const ILL_ILLTRP: ::c_int = 4; pub const ILL_PRVOPC: ::c_int = 5; pub const ILL_PRVREG: ::c_int = 6; pub const ILL_COPROC: ::c_int = 7; pub const ILL_BADSTK: ::c_int = 8; pub const FPE_INTDIV: ::c_int = 1; pub const FPE_INTOVF: ::c_int = 2; pub const FPE_FLTDIV: ::c_int = 3; pub const FPE_FLTOVF: ::c_int = 4; pub const FPE_FLTUND: ::c_int = 5; pub const FPE_FLTRES: ::c_int = 6; pub const FPE_FLTINV: ::c_int = 7; pub const FPE_FLTSUB: ::c_int = 8; pub const SEGV_MAPERR: ::c_int = 1; pub const SEGV_ACCERR: ::c_int = 2; pub const BUS_ADRALN: ::c_int = 1; pub const BUS_ADRERR: ::c_int = 2; pub const BUS_OBJERR: ::c_int = 3; pub const TRAP_BRKPT: ::c_int = 1; pub const TRAP_TRACE: ::c_int = 2; pub const CLD_EXITED: ::c_int = 1; pub const CLD_KILLED: ::c_int = 2; pub const CLD_DUMPED: ::c_int = 3; pub const CLD_TRAPPED: ::c_int = 4; pub const CLD_STOPPED: ::c_int = 5; pub const CLD_CONTINUED: ::c_int = 6; pub const POLL_IN: ::c_int = 1; pub const POLL_OUT: ::c_int = 2; pub const POLL_MSG: ::c_int = 3; pub const POLL_ERR: ::c_int = 4; pub const POLL_PRI: ::c_int = 5; pub const POLL_HUP: ::c_int = 6; pub const SIGEV_SIGNAL: ::c_int = 0; pub const SIGEV_NONE: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 2; pub const REG_GS: ::c_uint = 0; pub const REG_FS: ::c_uint = 1; pub const REG_ES: ::c_uint = 2; pub const REG_DS: ::c_uint = 3; pub const REG_EDI: ::c_uint = 4; pub const REG_ESI: ::c_uint = 5; pub const REG_EBP: ::c_uint = 6; pub const REG_ESP: ::c_uint = 7; pub const REG_EBX: ::c_uint = 8; pub const REG_EDX: ::c_uint = 9; pub const REG_ECX: ::c_uint = 10; pub const REG_EAX: ::c_uint = 11; pub const REG_TRAPNO: ::c_uint = 12; pub const REG_ERR: ::c_uint = 13; pub const REG_EIP: ::c_uint = 14; pub const REG_CS: ::c_uint = 15; pub const REG_EFL: ::c_uint = 16; pub const REG_UESP: ::c_uint = 17; pub const REG_SS: ::c_uint = 18; pub const IOC_VOID: __ioctl_dir = 0; pub const IOC_OUT: __ioctl_dir = 1; pub const IOC_IN: __ioctl_dir = 2; pub const IOC_INOUT: __ioctl_dir = 3; pub const IOC_8: __ioctl_datum = 0; pub const IOC_16: __ioctl_datum = 1; pub const IOC_32: __ioctl_datum = 2; pub const IOC_64: __ioctl_datum = 3; pub const TCP_ESTABLISHED: ::c_uint = 1; pub const TCP_SYN_SENT: ::c_uint = 2; pub const TCP_SYN_RECV: ::c_uint = 3; pub const TCP_FIN_WAIT1: ::c_uint = 4; pub const TCP_FIN_WAIT2: ::c_uint = 5; pub const TCP_TIME_WAIT: ::c_uint = 6; pub const TCP_CLOSE: ::c_uint = 7; pub const TCP_CLOSE_WAIT: ::c_uint = 8; pub const TCP_LAST_ACK: ::c_uint = 9; pub const TCP_LISTEN: ::c_uint = 10; pub const TCP_CLOSING: ::c_uint = 11; pub const TCP_CA_Open: tcp_ca_state = 0; pub const TCP_CA_Disorder: tcp_ca_state = 1; pub const TCP_CA_CWR: tcp_ca_state = 2; pub const TCP_CA_Recovery: tcp_ca_state = 3; pub const TCP_CA_Loss: tcp_ca_state = 4; pub const TCP_NO_QUEUE: ::c_uint = 0; pub const TCP_RECV_QUEUE: ::c_uint = 1; pub const TCP_SEND_QUEUE: ::c_uint = 2; pub const TCP_QUEUES_NR: ::c_uint = 3; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 4; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __lock: 0, __owner_id: 0, __cnt: 0, __shpid: 0, __type: PTHREAD_MUTEX_TIMED as ::c_int, __flags: 0, __reserved1: 0, __reserved2: 0, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __lock: __PTHREAD_SPIN_LOCK_INITIALIZER, __queue: 0i64 as *mut __pthread, __attr: 0i64 as *mut __pthread_condattr, __wrefs: 0, __data: 0i64 as *mut ::c_void, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __held: __PTHREAD_SPIN_LOCK_INITIALIZER, __lock: __PTHREAD_SPIN_LOCK_INITIALIZER, __readers: 0, __readerqueue: 0i64 as *mut __pthread, __writerqueue: 0i64 as *mut __pthread, __attr: 0i64 as *mut __pthread_rwlockattr, __data: 0i64 as *mut ::c_void, }; pub const PTHREAD_STACK_MIN: ::size_t = 0; const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + ::mem::size_of::() - 1 & !(::mem::size_of::() - 1) } } // functions f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= ::mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut ::c_uchar { cmsg.offset(1) as *mut ::c_uchar } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(::mem::size_of::())) as ::c_uint } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { CMSG_ALIGN(::mem::size_of::()) as ::c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if ((*cmsg).cmsg_len as usize) < ::mem::size_of::() { return 0 as *mut cmsghdr; }; let next = (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut cmsghdr; let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if (next.offset(1)) as usize > max || next as usize + CMSG_ALIGN((*next).cmsg_len as usize) > max { 0 as *mut cmsghdr } else { next as *mut cmsghdr } } pub fn CPU_ALLOC_SIZE(count: ::c_int) -> ::size_t { let _dummy: cpu_set_t = ::mem::zeroed(); let size_in_bits = 8 * ::mem::size_of_val(&_dummy.bits[0]); ((count as ::size_t + size_in_bits - 1) / 8) as ::size_t } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.bits.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); // 32, 64 etc let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); cpuset.bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let size_in_bits = 8 * ::mem::size_of_val(&cpuset.bits[0]); let (idx, offset) = (cpu / size_in_bits, cpu % size_in_bits); 0 != (cpuset.bits[idx] & (1 << offset)) } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> ::c_int { let mut s: u32 = 0; let size_of_mask = ::mem::size_of_val(&cpuset.bits[0]); for i in cpuset.bits[..(size / size_of_mask)].iter() { s += i.count_ones(); }; s as ::c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> ::c_int { CPU_COUNT_S(::mem::size_of::(), cpuset) } pub fn CPU_EQUAL(set1: &cpu_set_t, set2: &cpu_set_t) -> bool { set1.bits == set2.bits } pub fn major(dev: ::dev_t) -> ::c_uint { ((dev >> 8) & 0xff) as ::c_uint } pub fn minor(dev: ::dev_t) -> ::c_uint { (dev & 0xffff00ff) as ::c_uint } pub fn IPTOS_TOS(tos: u8) -> u8 { tos & IPTOS_TOS_MASK } pub fn IPTOS_PREC(tos: u8) -> u8 { tos & IPTOS_PREC_MASK } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } extern "C" { pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int; pub fn futimens(__fd: ::c_int, __times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn mkfifoat(__fd: ::c_int, __path: *const ::c_char, __mode: __mode_t) -> ::c_int; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn __libc_current_sigrtmin() -> ::c_int; pub fn __libc_current_sigrtmax() -> ::c_int; pub fn wait4( pid: ::pid_t, status: *mut ::c_int, options: ::c_int, rusage: *mut ::rusage, ) -> ::pid_t; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; pub fn sigwait(__set: *const sigset_t, __sig: *mut ::c_int) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn ioctl(__fd: ::c_int, __request: ::c_ulong, ...) -> ::c_int; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn dup3(oldfd: ::c_int, newfd: ::c_int, flags: ::c_int) -> ::c_int; pub fn pread64(fd: ::c_int, buf: *mut ::c_void, count: ::size_t, offset: off64_t) -> ::ssize_t; pub fn pwrite64( fd: ::c_int, buf: *const ::c_void, count: ::size_t, offset: off64_t, ) -> ::ssize_t; pub fn readv(__fd: ::c_int, __iovec: *const ::iovec, __count: ::c_int) -> ::ssize_t; pub fn writev(__fd: ::c_int, __iovec: *const ::iovec, __count: ::c_int) -> ::ssize_t; pub fn preadv( __fd: ::c_int, __iovec: *const ::iovec, __count: ::c_int, __offset: __off_t, ) -> ssize_t; pub fn pwritev( __fd: ::c_int, __iovec: *const ::iovec, __count: ::c_int, __offset: __off_t, ) -> ssize_t; pub fn preadv64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t; pub fn pwritev64( fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off64_t, ) -> ::ssize_t; pub fn fread_unlocked( buf: *mut ::c_void, size: ::size_t, nobj: ::size_t, stream: *mut ::FILE, ) -> ::size_t; pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_error(aiocbp: *const aiocb) -> ::c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn lio_listio( mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut ::sigevent, ) -> ::c_int; pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, abs_timeout: *const ::timespec, ) -> ::ssize_t; pub fn mq_send( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_timedsend( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; pub fn lseek64(__fd: ::c_int, __offset: __off64_t, __whence: ::c_int) -> __off64_t; pub fn lseek(__fd: ::c_int, __offset: __off_t, __whence: ::c_int) -> __off_t; pub fn fgetpos64(stream: *mut ::FILE, ptr: *mut fpos64_t) -> ::c_int; pub fn fseeko64(stream: *mut ::FILE, offset: ::off64_t, whence: ::c_int) -> ::c_int; pub fn fsetpos64(stream: *mut ::FILE, ptr: *const fpos64_t) -> ::c_int; pub fn ftello64(stream: *mut ::FILE) -> ::off64_t; pub fn bind(__fd: ::c_int, __addr: *const sockaddr, __len: socklen_t) -> ::c_int; pub fn accept4( fd: ::c_int, addr: *mut ::sockaddr, len: *mut ::socklen_t, flg: ::c_int, ) -> ::c_int; pub fn ppoll( fds: *mut ::pollfd, nfds: nfds_t, timeout: *const ::timespec, sigmask: *const sigset_t, ) -> ::c_int; pub fn recvmsg(__fd: ::c_int, __message: *mut msghdr, __flags: ::c_int) -> ::ssize_t; pub fn sendmsg(__fd: ::c_int, __message: *const msghdr, __flags: ::c_int) -> ssize_t; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn sendfile( out_fd: ::c_int, in_fd: ::c_int, offset: *mut off_t, count: ::size_t, ) -> ::ssize_t; pub fn sendfile64( out_fd: ::c_int, in_fd: ::c_int, offset: *mut off64_t, count: ::size_t, ) -> ::ssize_t; pub fn shutdown(__fd: ::c_int, __how: ::c_int) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn gethostid() -> ::c_long; pub fn sethostid(hostid: ::c_long) -> ::c_int; pub fn setpwent(); pub fn endpwent(); pub fn getpwent() -> *mut passwd; pub fn setgrent(); pub fn endgrent(); pub fn getgrent() -> *mut ::group; pub fn setspent(); pub fn endspent(); pub fn getspent() -> *mut spwd; pub fn getspnam(name: *const ::c_char) -> *mut spwd; pub fn getpwent_r( pwd: *mut ::passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::passwd, ) -> ::c_int; pub fn getgrent_r( grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn fgetpwent_r( stream: *mut ::FILE, pwd: *mut ::passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::passwd, ) -> ::c_int; pub fn fgetgrent_r( stream: *mut ::FILE, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn putpwent(p: *const ::passwd, stream: *mut ::FILE) -> ::c_int; pub fn putgrent(grp: *const ::group, stream: *mut ::FILE) -> ::c_int; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn fgetspent_r( fp: *mut ::FILE, spbuf: *mut ::spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut ::spwd, ) -> ::c_int; pub fn sgetspent_r( s: *const ::c_char, spbuf: *mut ::spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut ::spwd, ) -> ::c_int; pub fn getspent_r( spbuf: *mut ::spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut ::spwd, ) -> ::c_int; pub fn getspnam_r( name: *const ::c_char, spbuf: *mut spwd, buf: *mut ::c_char, buflen: ::size_t, spbufp: *mut *mut spwd, ) -> ::c_int; // mntent.h pub fn getmntent_r( stream: *mut ::FILE, mntbuf: *mut ::mntent, buf: *mut ::c_char, buflen: ::c_int, ) -> *mut ::mntent; pub fn utmpname(file: *const ::c_char) -> ::c_int; pub fn utmpxname(file: *const ::c_char) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, suid: *mut ::uid_t) -> ::c_int; pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, sgid: *mut ::gid_t) -> ::c_int; pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; pub fn initgroups(user: *const ::c_char, group: ::gid_t) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getgrouplist( user: *const ::c_char, group: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn setgroups(ngroups: ::size_t, ptr: *const ::gid_t) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; pub fn setmntent(filename: *const ::c_char, ty: *const ::c_char) -> *mut ::FILE; pub fn getmntent(stream: *mut ::FILE) -> *mut ::mntent; pub fn addmntent(stream: *mut ::FILE, mnt: *const ::mntent) -> ::c_int; pub fn endmntent(streamp: *mut ::FILE) -> ::c_int; pub fn hasmntopt(mnt: *const ::mntent, opt: *const ::c_char) -> *mut ::c_char; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn pthread_kill(__threadid: ::pthread_t, __signo: ::c_int) -> ::c_int; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; pub fn __pthread_equal(__t1: __pthread_t, __t2: __pthread_t) -> ::c_int; pub fn pthread_getattr_np(__thr: ::pthread_t, __attr: *mut pthread_attr_t) -> ::c_int; pub fn pthread_attr_getguardsize( __attr: *const pthread_attr_t, __guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getstack( __attr: *const pthread_attr_t, __stackaddr: *mut *mut ::c_void, __stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setpshared( attr: *mut pthread_mutexattr_t, pshared: ::c_int, ) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( __attr: *mut pthread_condattr_t, __clock_id: __clockid_t, ) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_once(control: *mut pthread_once_t, routine: extern "C" fn()) -> ::c_int; pub fn pthread_barrierattr_init(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_destroy(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_getpshared( attr: *const ::pthread_barrierattr_t, shared: *mut ::c_int, ) -> ::c_int; pub fn pthread_barrierattr_setpshared( attr: *mut ::pthread_barrierattr_t, shared: ::c_int, ) -> ::c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const ::pthread_barrierattr_t, count: ::c_uint, ) -> ::c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn pthread_sigmask( __how: ::c_int, __newmask: *const __sigset_t, __oldmask: *mut __sigset_t, ) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut ::sched_param, ) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn pthread_getcpuclockid(thread: ::pthread_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn clock_getres(__clock_id: clockid_t, __res: *mut ::timespec) -> ::c_int; pub fn clock_gettime(__clock_id: clockid_t, __tp: *mut ::timespec) -> ::c_int; pub fn clock_settime(__clock_id: clockid_t, __tp: *const ::timespec) -> ::c_int; pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn asctime_r(tm: *const ::tm, buf: *mut ::c_char) -> *mut ::c_char; pub fn ctime_r(timep: *const time_t, buf: *mut ::c_char) -> *mut ::c_char; pub fn strftime( s: *mut ::c_char, max: ::size_t, format: *const ::c_char, tm: *const ::tm, ) -> ::size_t; pub fn strptime(s: *const ::c_char, format: *const ::c_char, tm: *mut ::tm) -> *mut ::c_char; pub fn timer_create( clockid: ::clockid_t, sevp: *mut ::sigevent, timerid: *mut ::timer_t, ) -> ::c_int; pub fn timer_delete(timerid: ::timer_t) -> ::c_int; pub fn timer_getoverrun(timerid: ::timer_t) -> ::c_int; pub fn timer_gettime(timerid: ::timer_t, curr_value: *mut ::itimerspec) -> ::c_int; pub fn timer_settime( timerid: ::timer_t, flags: ::c_int, new_value: *const ::itimerspec, old_value: *mut ::itimerspec, ) -> ::c_int; pub fn fstat(__fd: ::c_int, __buf: *mut stat) -> ::c_int; pub fn fstat64(__fd: ::c_int, __buf: *mut stat64) -> ::c_int; pub fn fstatat( __fd: ::c_int, __file: *const ::c_char, __buf: *mut stat, __flag: ::c_int, ) -> ::c_int; pub fn fstatat64( __fd: ::c_int, __file: *const ::c_char, __buf: *mut stat64, __flag: ::c_int, ) -> ::c_int; pub fn statx( dirfd: ::c_int, pathname: *const c_char, flags: ::c_int, mask: ::c_uint, statxbuf: *mut statx, ) -> ::c_int; pub fn ftruncate(__fd: ::c_int, __length: __off_t) -> ::c_int; pub fn ftruncate64(__fd: ::c_int, __length: __off64_t) -> ::c_int; pub fn truncate64(__file: *const ::c_char, __length: __off64_t) -> ::c_int; pub fn lstat(__file: *const ::c_char, __buf: *mut stat) -> ::c_int; pub fn lstat64(__file: *const ::c_char, __buf: *mut stat64) -> ::c_int; pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; pub fn statfs64(__file: *const ::c_char, __buf: *mut statfs64) -> ::c_int; pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn fstatfs64(__fildes: ::c_int, __buf: *mut statfs64) -> ::c_int; pub fn statvfs(__file: *const ::c_char, __buf: *mut statvfs) -> ::c_int; pub fn statvfs64(__file: *const ::c_char, __buf: *mut statvfs64) -> ::c_int; pub fn fstatvfs(__fildes: ::c_int, __buf: *mut statvfs) -> ::c_int; pub fn fstatvfs64(__fildes: ::c_int, __buf: *mut statvfs64) -> ::c_int; pub fn open(__file: *const ::c_char, __oflag: ::c_int, ...) -> ::c_int; pub fn open64(__file: *const ::c_char, __oflag: ::c_int, ...) -> ::c_int; pub fn openat(__fd: ::c_int, __file: *const ::c_char, __oflag: ::c_int, ...) -> ::c_int; pub fn openat64(__fd: ::c_int, __file: *const ::c_char, __oflag: ::c_int, ...) -> ::c_int; pub fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn freopen64( filename: *const c_char, mode: *const c_char, file: *mut ::FILE, ) -> *mut ::FILE; pub fn creat64(path: *const c_char, mode: mode_t) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; pub fn tmpfile64() -> *mut ::FILE; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn getdtablesize() -> ::c_int; // Added in `glibc` 2.34 pub fn close_range(first: ::c_uint, last: ::c_uint, flags: ::c_int) -> ::c_int; pub fn openpty( __amaster: *mut ::c_int, __aslave: *mut ::c_int, __name: *mut ::c_char, __termp: *const termios, __winp: *const ::winsize, ) -> ::c_int; pub fn forkpty( __amaster: *mut ::c_int, __name: *mut ::c_char, __termp: *const termios, __winp: *const ::winsize, ) -> ::pid_t; pub fn getpt() -> ::c_int; pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; pub fn login_tty(fd: ::c_int) -> ::c_int; pub fn ctermid(s: *mut ::c_char) -> *mut ::c_char; pub fn clearenv() -> ::c_int; pub fn execveat( dirfd: ::c_int, pathname: *const ::c_char, argv: *const *mut c_char, envp: *const *mut c_char, flags: ::c_int, ) -> ::c_int; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn fexecve( fd: ::c_int, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; // posix/spawn.h pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, ) -> ::c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const ::sched_param, ) -> ::c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, newfd: ::c_int, ) -> ::c_int; // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addchdir_np( actions: *mut ::posix_spawn_file_actions_t, path: *const ::c_char, ) -> ::c_int; // Added in `glibc` 2.29 pub fn posix_spawn_file_actions_addfchdir_np( actions: *mut ::posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; // Added in `glibc` 2.34 pub fn posix_spawn_file_actions_addclosefrom_np( actions: *mut ::posix_spawn_file_actions_t, from: ::c_int, ) -> ::c_int; // Added in `glibc` 2.35 pub fn posix_spawn_file_actions_addtcsetpgrp_np( actions: *mut ::posix_spawn_file_actions_t, tcfd: ::c_int, ) -> ::c_int; pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn euidaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int; pub fn eaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn stat(__file: *const ::c_char, __buf: *mut stat) -> ::c_int; pub fn stat64(__file: *const ::c_char, __buf: *mut stat64) -> ::c_int; pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent; pub fn readdir64(dirp: *mut ::DIR) -> *mut ::dirent64; pub fn readdir_r(dirp: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) -> ::c_int; pub fn readdir64_r( dirp: *mut ::DIR, entry: *mut ::dirent64, result: *mut *mut ::dirent64, ) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; #[link_name = "__xpg_strerror_r"] pub fn strerror_r(__errnum: ::c_int, __buf: *mut ::c_char, __buflen: ::size_t) -> ::c_int; pub fn __errno_location() -> *mut ::c_int; pub fn mmap64( __addr: *mut ::c_void, __len: size_t, __prot: ::c_int, __flags: ::c_int, __fd: ::c_int, __offset: __off64_t, ) -> *mut ::c_void; pub fn mremap( addr: *mut ::c_void, len: ::size_t, new_len: ::size_t, flags: ::c_int, ... ) -> *mut ::c_void; pub fn mprotect(__addr: *mut ::c_void, __len: ::size_t, __prot: ::c_int) -> ::c_int; pub fn msync(__addr: *mut ::c_void, __len: ::size_t, __flags: ::c_int) -> ::c_int; pub fn sync(); pub fn syncfs(fd: ::c_int) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn fallocate64(fd: ::c_int, mode: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn posix_fallocate64(fd: ::c_int, offset: ::off64_t, len: ::off64_t) -> ::c_int; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn posix_fadvise64( fd: ::c_int, offset: ::off64_t, len: ::off64_t, advise: ::c_int, ) -> ::c_int; pub fn madvise(__addr: *mut ::c_void, __len: ::size_t, __advice: ::c_int) -> ::c_int; pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn getrlimit(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit) -> ::c_int; pub fn getrlimit64(resource: ::__rlimit_resource_t, rlim: *mut ::rlimit64) -> ::c_int; pub fn setrlimit(resource: ::__rlimit_resource_t, rlim: *const ::rlimit) -> ::c_int; pub fn setrlimit64(resource: ::__rlimit_resource_t, rlim: *const ::rlimit64) -> ::c_int; pub fn getpriority(which: ::__priority_which, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::__priority_which, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn getrandom(__buffer: *mut ::c_void, __length: ::size_t, __flags: ::c_uint) -> ::ssize_t; pub fn getentropy(__buffer: *mut ::c_void, __length: ::size_t) -> ::c_int; pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; pub fn strchrnul(s: *const ::c_char, c: ::c_int) -> *mut ::c_char; pub fn abs(i: ::c_int) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); pub fn drand48() -> ::c_double; pub fn erand48(xseed: *mut ::c_ushort) -> ::c_double; pub fn lrand48() -> ::c_long; pub fn nrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn mrand48() -> ::c_long; pub fn jrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn srand48(seed: ::c_long); pub fn seed48(xseed: *mut ::c_ushort) -> *mut ::c_ushort; pub fn lcong48(p: *mut ::c_ushort); pub fn qsort_r( base: *mut ::c_void, num: ::size_t, size: ::size_t, compar: ::Option< unsafe extern "C" fn(*const ::c_void, *const ::c_void, *mut ::c_void) -> ::c_int, >, arg: *mut ::c_void, ); pub fn brk(addr: *mut ::c_void) -> ::c_int; pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn mallopt(param: ::c_int, value: ::c_int) -> ::c_int; pub fn mallinfo() -> ::mallinfo; pub fn mallinfo2() -> ::mallinfo2; pub fn malloc_info(options: ::c_int, stream: *mut ::FILE) -> ::c_int; pub fn malloc_usable_size(ptr: *mut ::c_void) -> ::size_t; pub fn malloc_trim(__pad: ::size_t) -> ::c_int; pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, inbytesleft: *mut ::size_t, outbuf: *mut *mut ::c_char, outbytesleft: *mut ::size_t, ) -> ::size_t; pub fn iconv_close(cd: iconv_t) -> ::c_int; pub fn getopt_long( argc: ::c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut ::c_int, ) -> ::c_int; pub fn backtrace(buf: *mut *mut ::c_void, sz: ::c_int) -> ::c_int; pub fn reboot(how_to: ::c_int) -> ::c_int; pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; pub fn regexec( preg: *const ::regex_t, input: *const ::c_char, nmatch: ::size_t, pmatch: *mut regmatch_t, eflags: ::c_int, ) -> ::c_int; pub fn regerror( errcode: ::c_int, preg: *const ::regex_t, errbuf: *mut ::c_char, errbuf_size: ::size_t, ) -> ::size_t; pub fn regfree(preg: *mut ::regex_t); pub fn glob( pattern: *const c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn glob64( pattern: *const ::c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut glob64_t, ) -> ::c_int; pub fn globfree64(pglob: *mut glob64_t); pub fn getxattr( path: *const c_char, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn lgetxattr( path: *const c_char, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn fgetxattr( filedes: ::c_int, name: *const c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn setxattr( path: *const c_char, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn lsetxattr( path: *const c_char, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn fsetxattr( filedes: ::c_int, name: *const c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn listxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn llistxattr(path: *const c_char, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn flistxattr(filedes: ::c_int, list: *mut c_char, size: ::size_t) -> ::ssize_t; pub fn removexattr(path: *const c_char, name: *const c_char) -> ::c_int; pub fn lremovexattr(path: *const c_char, name: *const c_char) -> ::c_int; pub fn fremovexattr(filedes: ::c_int, name: *const c_char) -> ::c_int; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; /// POSIX version of `basename(3)`, defined in `libgen.h`. #[link_name = "__xpg_basename"] pub fn posix_basename(path: *mut ::c_char) -> *mut ::c_char; /// GNU version of `basename(3)`, defined in `string.h`. #[link_name = "basename"] pub fn gnu_basename(path: *const ::c_char) -> *mut ::c_char; pub fn dlmopen(lmid: Lmid_t, filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; pub fn dlinfo(handle: *mut ::c_void, request: ::c_int, info: *mut ::c_void) -> ::c_int; pub fn dladdr1( addr: *const ::c_void, info: *mut ::Dl_info, extra_info: *mut *mut ::c_void, flags: ::c_int, ) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut ::dl_phdr_info, size: ::size_t, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; pub fn gnu_get_libc_release() -> *const ::c_char; pub fn gnu_get_libc_version() -> *const ::c_char; } safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= major << 8; dev |= minor; dev } pub fn SIGRTMAX() -> ::c_int { unsafe { __libc_current_sigrtmax() } } pub fn SIGRTMIN() -> ::c_int { unsafe { __libc_current_sigrtmin() } } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { status & 0x7f } pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0x80) != 0 } pub {const} fn W_EXITCODE(ret: ::c_int, sig: ::c_int) -> ::c_int { (ret << 8) | sig } pub {const} fn W_STOPCODE(sig: ::c_int) -> ::c_int { (sig << 8) | 0x7f } pub {const} fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int { (cmd << 8) | (type_ & 0x00ff) } pub {const} fn IPOPT_COPIED(o: u8) -> u8 { o & IPOPT_COPY } pub {const} fn IPOPT_CLASS(o: u8) -> u8 { o & IPOPT_CLASS_MASK } pub {const} fn IPOPT_NUMBER(o: u8) -> u8 { o & IPOPT_NUMBER_MASK } pub {const} fn IPTOS_ECN(x: u8) -> u8 { x & ::IPTOS_ECN_MASK } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } else { mod no_align; pub use self::no_align::*; } } cfg_if! { if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { mod b32; pub use self::b32::*; } } libc/src/unix/hurd/b64.rs0000644000175000017500000000506714661133735016137 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type __int64_t = ::c_long; pub type __uint64_t = ::c_ulong; pub type int_fast16_t = ::c_long; pub type int_fast32_t = ::c_long; pub type int_fast64_t = ::c_long; pub type uint_fast16_t = ::c_ulong; pub type uint_fast32_t = ::c_ulong; pub type uint_fast64_t = ::c_ulong; pub type __quad_t = ::c_long; pub type __u_quad_t = ::c_ulong; pub type __intmax_t = ::c_long; pub type __uintmax_t = ::c_ulong; pub type __squad_type = ::c_long; pub type __uquad_type = ::c_ulong; pub type __sword_type = ::c_long; pub type __uword_type = ::c_ulong; pub type __slong32_type = ::c_int; pub type __ulong32_type = ::c_uint; pub type __s64_type = ::c_long; pub type __u64_type = ::c_ulong; pub type __ipc_pid_t = ::c_int; pub type Elf64_Half = u16; pub type Elf64_Word = u32; pub type Elf64_Off = u64; pub type Elf64_Addr = u64; pub type Elf64_Xword = u64; pub type Elf64_Sxword = i64; pub type Elf64_Section = u16; pub type Elf_Addr = ::Elf64_Addr; pub type Elf_Half = ::Elf64_Half; pub type Elf_Ehdr = ::Elf64_Ehdr; pub type Elf_Phdr = ::Elf64_Phdr; pub type Elf_Shdr = ::Elf64_Shdr; pub type Elf_Sym = ::Elf64_Sym; s! { pub struct Elf64_Ehdr { pub e_ident: [::c_uchar; 16], pub e_type: Elf64_Half, pub e_machine: Elf64_Half, pub e_version: Elf64_Word, pub e_entry: Elf64_Addr, pub e_phoff: Elf64_Off, pub e_shoff: Elf64_Off, pub e_flags: Elf64_Word, pub e_ehsize: Elf64_Half, pub e_phentsize: Elf64_Half, pub e_phnum: Elf64_Half, pub e_shentsize: Elf64_Half, pub e_shnum: Elf64_Half, pub e_shstrndx: Elf64_Half, } pub struct Elf64_Shdr { pub sh_name: Elf64_Word, pub sh_type: Elf64_Word, pub sh_flags: Elf64_Xword, pub sh_addr: Elf64_Addr, pub sh_offset: Elf64_Off, pub sh_size: Elf64_Xword, pub sh_link: Elf64_Word, pub sh_info: Elf64_Word, pub sh_addralign: Elf64_Xword, pub sh_entsize: Elf64_Xword, } pub struct Elf64_Sym { pub st_name: Elf64_Word, pub st_info: ::c_uchar, pub st_other: ::c_uchar, pub st_shndx: Elf64_Section, pub st_value: Elf64_Addr, pub st_size: Elf64_Xword, } pub struct Elf64_Phdr { pub p_type: ::Elf64_Word, pub p_flags: ::Elf64_Word, pub p_offset: ::Elf64_Off, pub p_vaddr: ::Elf64_Addr, pub p_paddr: ::Elf64_Addr, pub p_filesz: ::Elf64_Xword, pub p_memsz: ::Elf64_Xword, pub p_align: ::Elf64_Xword, } } libc/src/unix/hurd/no_align.rs0000644000175000017500000000002414661133735017316 0ustar jamespagejamespage// Placeholder file libc/src/unix/hurd/align.rs0000644000175000017500000000002414661133735016622 0ustar jamespagejamespage// Placeholder file libc/src/unix/haiku/0000775000175000017500000000000014661133735015327 5ustar jamespagejamespagelibc/src/unix/haiku/b32.rs0000644000175000017500000000075714661133735016272 0ustar jamespagejamespagepub type c_long = i32; pub type c_ulong = u32; pub type time_t = i32; pub type Elf_Addr = ::Elf32_Addr; pub type Elf_Half = ::Elf32_Half; pub type Elf_Phdr = ::Elf32_Phdr; s! { pub struct Elf32_Phdr { pub p_type: ::Elf32_Word, pub p_offset: ::Elf32_Off, pub p_vaddr: ::Elf32_Addr, pub p_paddr: ::Elf32_Addr, pub p_filesz: ::Elf32_Word, pub p_memsz: ::Elf32_Word, pub p_flags: ::Elf32_Word, pub p_align: ::Elf32_Word, } } libc/src/unix/haiku/x86_64.rs0000644000175000017500000002313014661133735016630 0ustar jamespagejamespages_no_extra_traits! { pub struct fpu_state { pub control: ::c_ushort, pub status: ::c_ushort, pub tag: ::c_ushort, pub opcode: ::c_ushort, pub rip: ::c_ulong, pub rdp: ::c_ulong, pub mxcsr: ::c_uint, pub mscsr_mask: ::c_uint, pub _fpreg: [[::c_uchar; 8]; 16], pub _xmm: [[::c_uchar; 16]; 16], pub _reserved_416_511: [::c_uchar; 96], } pub struct xstate_hdr { pub bv: ::c_ulong, pub xcomp_bv: ::c_ulong, pub _reserved: [::c_uchar; 48], } pub struct savefpu { pub fp_fxsave: fpu_state, pub fp_xstate: xstate_hdr, pub _fp_ymm: [[::c_uchar; 16]; 16], } pub struct mcontext_t { pub rax: ::c_ulong, pub rbx: ::c_ulong, pub rcx: ::c_ulong, pub rdx: ::c_ulong, pub rdi: ::c_ulong, pub rsi: ::c_ulong, pub rbp: ::c_ulong, pub r8: ::c_ulong, pub r9: ::c_ulong, pub r10: ::c_ulong, pub r11: ::c_ulong, pub r12: ::c_ulong, pub r13: ::c_ulong, pub r14: ::c_ulong, pub r15: ::c_ulong, pub rsp: ::c_ulong, pub rip: ::c_ulong, pub rflags: ::c_ulong, pub fpu: savefpu, } pub struct ucontext_t { pub uc_link: *mut ucontext_t, pub uc_sigmask: ::sigset_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpu_state { fn eq(&self, other: &fpu_state) -> bool { self.control == other.control && self.status == other.status && self.tag == other.tag && self.opcode == other.opcode && self.rip == other.rip && self.rdp == other.rdp && self.mxcsr == other.mxcsr && self.mscsr_mask == other.mscsr_mask && self._fpreg.iter().zip(other._fpreg.iter()).all(|(a, b)| a == b) && self._xmm.iter().zip(other._xmm.iter()).all(|(a, b)| a == b) && self._reserved_416_511. iter(). zip(other._reserved_416_511.iter()). all(|(a, b)| a == b) } } impl Eq for fpu_state {} impl ::fmt::Debug for fpu_state { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpu_state") .field("control", &self.control) .field("status", &self.status) .field("tag", &self.tag) .field("opcode", &self.opcode) .field("rip", &self.rip) .field("rdp", &self.rdp) .field("mxcsr", &self.mxcsr) .field("mscsr_mask", &self.mscsr_mask) // FIXME: .field("_fpreg", &self._fpreg) // FIXME: .field("_xmm", &self._xmm) // FIXME: .field("_reserved_416_511", &self._reserved_416_511) .finish() } } impl ::hash::Hash for fpu_state { fn hash(&self, state: &mut H) { self.control.hash(state); self.status.hash(state); self.tag.hash(state); self.opcode.hash(state); self.rip.hash(state); self.rdp.hash(state); self.mxcsr.hash(state); self.mscsr_mask.hash(state); self._fpreg.hash(state); self._xmm.hash(state); self._reserved_416_511.hash(state); } } impl PartialEq for xstate_hdr { fn eq(&self, other: &xstate_hdr) -> bool { self.bv == other.bv && self.xcomp_bv == other.xcomp_bv && self._reserved.iter().zip(other._reserved.iter()).all(|(a, b)| a == b) } } impl Eq for xstate_hdr {} impl ::fmt::Debug for xstate_hdr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("xstate_hdr") .field("bv", &self.bv) .field("xcomp_bv", &self.xcomp_bv) // FIXME: .field("_reserved", &field._reserved) .finish() } } impl ::hash::Hash for xstate_hdr { fn hash(&self, state: &mut H) { self.bv.hash(state); self.xcomp_bv.hash(state); self._reserved.hash(state); } } impl PartialEq for savefpu { fn eq(&self, other: &savefpu) -> bool { self.fp_fxsave == other.fp_fxsave && self.fp_xstate == other.fp_xstate && self._fp_ymm.iter().zip(other._fp_ymm.iter()).all(|(a, b)| a == b) } } impl Eq for savefpu {} impl ::fmt::Debug for savefpu { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("savefpu") .field("fp_fxsave", &self.fp_fxsave) .field("fp_xstate", &self.fp_xstate) // FIXME: .field("_fp_ymm", &field._fp_ymm) .finish() } } impl ::hash::Hash for savefpu { fn hash(&self, state: &mut H) { self.fp_fxsave.hash(state); self.fp_xstate.hash(state); self._fp_ymm.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.rax == other.rax && self.rbx == other.rbx && self.rbx == other.rbx && self.rcx == other.rcx && self.rdx == other.rdx && self.rdi == other.rdi && self.rsi == other.rsi && self.r8 == other.r8 && self.r9 == other.r9 && self.r10 == other.r10 && self.r11 == other.r11 && self.r12 == other.r12 && self.r13 == other.r13 && self.r14 == other.r14 && self.r15 == other.r15 && self.rsp == other.rsp && self.rip == other.rip && self.rflags == other.rflags && self.fpu == other.fpu } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("rax", &self.rax) .field("rbx", &self.rbx) .field("rcx", &self.rcx) .field("rdx", &self.rdx) .field("rdi", &self.rdi) .field("rsi", &self.rsi) .field("rbp", &self.rbp) .field("r8", &self.r8) .field("r9", &self.r9) .field("r10", &self.r10) .field("r11", &self.r11) .field("r12", &self.r12) .field("r13", &self.r13) .field("r14", &self.r14) .field("r15", &self.r15) .field("rsp", &self.rsp) .field("rip", &self.rip) .field("rflags", &self.rflags) .field("fpu", &self.fpu) .finish() } } impl ::hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.rax.hash(state); self.rbx.hash(state); self.rcx.hash(state); self.rdx.hash(state); self.rdi.hash(state); self.rsi.hash(state); self.rbp.hash(state); self.r8.hash(state); self.r9.hash(state); self.r10.hash(state); self.r11.hash(state); self.r12.hash(state); self.r13.hash(state); self.r14.hash(state); self.r15.hash(state); self.rsp.hash(state); self.rip.hash(state); self.rflags.hash(state); self.fpu.hash(state); } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_link == other.uc_link && self.uc_sigmask == other.uc_sigmask && self.uc_stack == other.uc_stack && self.uc_mcontext == other.uc_mcontext } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_link", &self.uc_link) .field("uc_sigmask", &self.uc_sigmask) .field("uc_stack", &self.uc_stack) .field("uc_mcontext", &self.uc_mcontext) .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_link.hash(state); self.uc_sigmask.hash(state); self.uc_stack.hash(state); self.uc_mcontext.hash(state); } } } } libc/src/unix/haiku/mod.rs0000644000175000017500000021577114661133735016467 0ustar jamespagejamespagepub type rlim_t = ::uintptr_t; pub type sa_family_t = u8; pub type pthread_key_t = ::c_int; pub type nfds_t = ::c_ulong; pub type tcflag_t = ::c_uint; pub type speed_t = ::c_uchar; pub type c_char = i8; pub type clock_t = i32; pub type clockid_t = i32; pub type suseconds_t = i32; pub type wchar_t = i32; pub type off_t = i64; pub type ino_t = i64; pub type blkcnt_t = i64; pub type blksize_t = i32; pub type dev_t = i32; pub type mode_t = u32; pub type nlink_t = i32; pub type useconds_t = u32; pub type socklen_t = u32; pub type pthread_t = ::uintptr_t; pub type pthread_condattr_t = ::uintptr_t; pub type pthread_mutexattr_t = ::uintptr_t; pub type pthread_rwlockattr_t = ::uintptr_t; pub type sigset_t = u64; pub type fsblkcnt_t = i64; pub type fsfilcnt_t = i64; pub type pthread_attr_t = *mut ::c_void; pub type nl_item = ::c_int; pub type id_t = i32; pub type idtype_t = ::c_int; pub type fd_mask = u32; pub type regoff_t = ::c_int; pub type key_t = i32; pub type msgqnum_t = u32; pub type msglen_t = u32; pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type ENTRY = entry; pub type ACTION = ::c_int; pub type posix_spawnattr_t = *mut ::c_void; pub type posix_spawn_file_actions_t = *mut ::c_void; pub type StringList = _stringlist; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { self.si_addr } pub unsafe fn si_pid(&self) -> ::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.si_status } } s! { pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [u8; 30], } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [i8; 24], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: u8, pub sin6_port: u16, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: socklen_t, pub ai_canonname: *mut c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut addrinfo, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *const ::c_char, pub ifa_flags: ::c_uint, pub ifa_addr: *mut ::sockaddr, pub ifa_netmask: *mut ::sockaddr, pub ifa_dstaddr: *mut ::sockaddr, pub ifa_data: *mut ::c_void, } pub struct fd_set { // size for 1024 bits, and a fd_mask with size u32 fds_bits: [fd_mask; 32], } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, pub tm_gmtoff: ::c_int, pub tm_zone: *mut ::c_char, } pub struct utsname { pub sysname: [::c_char; 32], pub nodename: [::c_char; 32], pub release: [::c_char; 32], pub version: [::c_char; 32], pub machine: [::c_char; 32], } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::c_char, pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, pub c_cc: [::cc_t; ::NCCS], } pub struct flock { pub l_type: ::c_short, pub l_whence: ::c_short, pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, } pub struct stat { pub st_dev: dev_t, pub st_ino: ino_t, pub st_mode: mode_t, pub st_nlink: nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_size: off_t, pub st_rdev: dev_t, pub st_blksize: blksize_t, pub st_atime: time_t, pub st_atime_nsec: c_long, pub st_mtime: time_t, pub st_mtime_nsec: c_long, pub st_ctime: time_t, pub st_ctime_nsec: c_long, pub st_crtime: time_t, pub st_crtime_nsec: c_long, pub st_type: u32, pub st_blocks: blkcnt_t, } pub struct glob_t { pub gl_pathc: ::size_t, __unused1: ::size_t, pub gl_offs: ::size_t, __unused2: ::size_t, pub gl_pathv: *mut *mut c_char, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, __unused6: *mut ::c_void, __unused7: *mut ::c_void, __unused8: *mut ::c_void, } pub struct pthread_mutex_t { flags: u32, lock: i32, unused: i32, owner: i32, owner_count: i32, } pub struct pthread_cond_t { flags: u32, unused: i32, mutex: *mut ::c_void, waiter_count: i32, lock: i32, } pub struct pthread_rwlock_t { flags: u32, owner: i32, lock_sem: i32, // this is actually a union lock_count: i32, reader_count: i32, writer_count: i32, waiters: [*mut ::c_void; 2], } pub struct pthread_spinlock_t { lock: u32, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, pub pw_gecos: *mut ::c_char, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, pub si_pid: ::pid_t, pub si_uid: ::uid_t, pub si_addr: *mut ::c_void, pub si_status: ::c_int, pub si_band: c_long, pub sigval: *mut ::c_void, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, //actually a union with sa_handler pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, sa_userdata: *mut ::c_void, } pub struct sem_t { pub type_: i32, pub named_sem_id: i32, // actually a union with unnamed_sem (i32) pub padding: [i32; 2], } pub struct ucred { pub pid: ::pid_t, pub uid: ::uid_t, pub gid: ::gid_t, } pub struct sockaddr_dl { pub sdl_len: u8, pub sdl_family: u8, pub sdl_e_type: u16, pub sdl_index: u32, pub sdl_type: u8, pub sdl_nlen: u8, pub sdl_alen: u8, pub sdl_slen: u8, pub sdl_data: [u8; 46], } pub struct spwd { pub sp_namp: *mut ::c_char, pub sp_pwdp: *mut ::c_char, pub sp_lstchg: ::c_int, pub sp_min: ::c_int, pub sp_max: ::c_int, pub sp_warn: ::c_int, pub sp_inact: ::c_int, pub sp_expire: ::c_int, pub sp_flag: ::c_int, } pub struct regex_t { __buffer: *mut ::c_void, __allocated: ::size_t, __used: ::size_t, __syntax: ::c_ulong, __fastmap: *mut ::c_char, __translate: *mut ::c_char, __re_nsub: ::size_t, __bitfield: u8, } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, } pub struct ipc_perm { pub key: ::key_t, pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct entry { pub key: *mut ::c_char, pub data: *mut ::c_void, } pub struct option { pub name: *const ::c_char, pub has_arg: ::c_int, pub flag: *mut ::c_int, pub val: ::c_int, } pub struct _stringlist { pub sl_str: *mut *mut ::c_char, pub sl_max: ::size_t, pub sl_cur: ::size_t, } pub struct dl_phdr_info { pub dlpi_addr: ::Elf_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const ::Elf_Phdr, pub dlpi_phnum: ::Elf_Half, } } s_no_extra_traits! { pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [::c_char; 126] } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: sa_family_t, __ss_pad1: [u8; 6], __ss_pad2: u64, __ss_pad3: [u8; 112], } pub struct dirent { pub d_dev: dev_t, pub d_pdev: dev_t, pub d_ino: ino_t, pub d_pino: i64, pub d_reclen: ::c_ushort, pub d_name: [::c_char; 1024], // Max length is _POSIX_PATH_MAX } pub struct sigevent { pub sigev_notify: ::c_int, pub sigev_signo: ::c_int, pub sigev_value: ::sigval, __unused1: *mut ::c_void, // actually a function pointer pub sigev_notify_attributes: *mut ::pthread_attr_t, } pub struct utmpx { pub ut_type: ::c_short, pub ut_tv: ::timeval, pub ut_id: [::c_char; 8], pub ut_pid: ::pid_t, pub ut_user: [::c_char; 32], pub ut_line: [::c_char; 16], pub ut_host: [::c_char; 128], __ut_reserved: [::c_char; 64], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_tv == other.ut_tv && self.ut_id == other.ut_id && self.ut_pid == other.ut_pid && self.ut_user == other.ut_user && self.ut_line == other.ut_line && self.ut_host.iter().zip(other.ut_host.iter()).all(|(a,b)| a == b) && self.__ut_reserved == other.__ut_reserved } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_tv", &self.ut_tv) .field("ut_id", &self.ut_id) .field("ut_pid", &self.ut_pid) .field("ut_user", &self.ut_user) .field("ut_line", &self.ut_line) .field("ut_host", &self.ut_host) .field("__ut_reserved", &self.__ut_reserved) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_tv.hash(state); self.ut_id.hash(state); self.ut_pid.hash(state); self.ut_user.hash(state); self.ut_line.hash(state); self.ut_host.hash(state); self.__ut_reserved.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_len == other.sun_len && self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_un {} impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl ::hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_len.hash(state); self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self .__ss_pad1 .iter() .zip(other.__ss_pad1.iter()) .all(|(a, b)| a == b) && self.__ss_pad2 == other.__ss_pad2 && self .__ss_pad3 .iter() .zip(other.__ss_pad3.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_pad2", &self.__ss_pad2) // FIXME: .field("__ss_pad3", &self.__ss_pad3) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_pad2.hash(state); self.__ss_pad3.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_dev == other.d_dev && self.d_pdev == other.d_pdev && self.d_ino == other.d_ino && self.d_pino == other.d_pino && self.d_reclen == other.d_reclen && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_dev", &self.d_dev) .field("d_pdev", &self.d_pdev) .field("d_ino", &self.d_ino) .field("d_pino", &self.d_pino) .field("d_reclen", &self.d_reclen) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_dev.hash(state); self.d_pdev.hash(state); self.d_ino.hash(state); self.d_pino.hash(state); self.d_reclen.hash(state); self.d_name.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_attributes.hash(state); } } } } pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 2147483647; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const L_SET: ::c_int = SEEK_SET; pub const L_INCR: ::c_int = SEEK_CUR; pub const L_XTND: ::c_int = SEEK_END; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 2; pub const _IOLBF: ::c_int = 1; pub const F_DUPFD: ::c_int = 0x0001; pub const F_GETFD: ::c_int = 0x0002; pub const F_SETFD: ::c_int = 0x0004; pub const F_GETFL: ::c_int = 0x0008; pub const F_SETFL: ::c_int = 0x0010; pub const F_GETLK: ::c_int = 0x0020; pub const F_SETLK: ::c_int = 0x0080; pub const F_SETLKW: ::c_int = 0x0100; pub const F_DUPFD_CLOEXEC: ::c_int = 0x0200; pub const F_RDLCK: ::c_int = 0x0040; pub const F_UNLCK: ::c_int = 0x0200; pub const F_WRLCK: ::c_int = 0x0400; pub const AT_FDCWD: ::c_int = -100; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x01; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x02; pub const AT_REMOVEDIR: ::c_int = 0x04; pub const AT_EACCESS: ::c_int = 0x08; pub const POLLIN: ::c_short = 0x0001; pub const POLLOUT: ::c_short = 0x0002; pub const POLLRDNORM: ::c_short = POLLIN; pub const POLLWRNORM: ::c_short = POLLOUT; pub const POLLRDBAND: ::c_short = 0x0008; pub const POLLWRBAND: ::c_short = 0x0010; pub const POLLPRI: ::c_short = 0x0020; pub const POLLERR: ::c_short = 0x0004; pub const POLLHUP: ::c_short = 0x0080; pub const POLLNVAL: ::c_short = 0x1000; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; pub const CLOCK_REALTIME: ::c_int = -1; pub const CLOCK_MONOTONIC: ::c_int = 0; pub const CLOCK_PROCESS_CPUTIME_ID: ::c_int = -2; pub const CLOCK_THREAD_CPUTIME_ID: ::c_int = -3; pub const RLIMIT_CORE: ::c_int = 0; pub const RLIMIT_CPU: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_FSIZE: ::c_int = 3; pub const RLIMIT_NOFILE: ::c_int = 4; pub const RLIMIT_STACK: ::c_int = 5; pub const RLIMIT_AS: ::c_int = 6; pub const RLIM_INFINITY: ::rlim_t = 0xffffffff; // Haiku specific pub const RLIMIT_NOVMON: ::c_int = 7; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 8; pub const RUSAGE_SELF: ::c_int = 0; pub const RTLD_LAZY: ::c_int = 0; pub const NCCS: usize = 11; pub const O_RDONLY: ::c_int = 0x0000; pub const O_WRONLY: ::c_int = 0x0001; pub const O_RDWR: ::c_int = 0x0002; pub const O_ACCMODE: ::c_int = 0x0003; pub const O_EXCL: ::c_int = 0x0100; pub const O_CREAT: ::c_int = 0x0200; pub const O_TRUNC: ::c_int = 0x0400; pub const O_NOCTTY: ::c_int = 0x1000; pub const O_NOTRAVERSE: ::c_int = 0x2000; pub const O_CLOEXEC: ::c_int = 0x00000040; pub const O_NONBLOCK: ::c_int = 0x00000080; pub const O_APPEND: ::c_int = 0x00000800; pub const O_SYNC: ::c_int = 0x00010000; pub const O_RSYNC: ::c_int = 0x00020000; pub const O_DSYNC: ::c_int = 0x00040000; pub const O_NOFOLLOW: ::c_int = 0x00080000; pub const O_NOCACHE: ::c_int = 0x00100000; pub const O_DIRECTORY: ::c_int = 0x00200000; pub const S_IFIFO: ::mode_t = 4096; pub const S_IFCHR: ::mode_t = 8192; pub const S_IFBLK: ::mode_t = 24576; pub const S_IFDIR: ::mode_t = 16384; pub const S_IFREG: ::mode_t = 32768; pub const S_IFLNK: ::mode_t = 40960; pub const S_IFSOCK: ::mode_t = 49152; pub const S_IFMT: ::mode_t = 61440; pub const S_IRWXU: ::mode_t = 0o00700; pub const S_IRUSR: ::mode_t = 0o00400; pub const S_IWUSR: ::mode_t = 0o00200; pub const S_IXUSR: ::mode_t = 0o00100; pub const S_IRWXG: ::mode_t = 0o00070; pub const S_IRGRP: ::mode_t = 0o00040; pub const S_IWGRP: ::mode_t = 0o00020; pub const S_IXGRP: ::mode_t = 0o00010; pub const S_IRWXO: ::mode_t = 0o00007; pub const S_IROTH: ::mode_t = 0o00004; pub const S_IWOTH: ::mode_t = 0o00002; pub const S_IXOTH: ::mode_t = 0o00001; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGCHLD: ::c_int = 5; pub const SIGABRT: ::c_int = 6; pub const SIGPIPE: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSTOP: ::c_int = 10; pub const SIGSEGV: ::c_int = 11; pub const SIGCONT: ::c_int = 12; pub const SIGTSTP: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const SIGTTIN: ::c_int = 16; pub const SIGTTOU: ::c_int = 17; pub const SIGUSR1: ::c_int = 18; pub const SIGUSR2: ::c_int = 19; pub const SIGWINCH: ::c_int = 20; pub const SIGKILLTHR: ::c_int = 21; pub const SIGTRAP: ::c_int = 22; pub const SIGPOLL: ::c_int = 23; pub const SIGPROF: ::c_int = 24; pub const SIGSYS: ::c_int = 25; pub const SIGURG: ::c_int = 26; pub const SIGVTALRM: ::c_int = 27; pub const SIGXCPU: ::c_int = 28; pub const SIGXFSZ: ::c_int = 29; pub const SIGBUS: ::c_int = 30; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const SIG_SETMASK: ::c_int = 3; pub const SIGEV_NONE: ::c_int = 0; pub const SIGEV_SIGNAL: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 2; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_NODATA: ::c_int = 7; pub const EAI_NONAME: ::c_int = 8; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 14; pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const LC_ALL: ::c_int = 0; pub const LC_COLLATE: ::c_int = 1; pub const LC_CTYPE: ::c_int = 2; pub const LC_MONETARY: ::c_int = 3; pub const LC_NUMERIC: ::c_int = 4; pub const LC_TIME: ::c_int = 5; pub const LC_MESSAGES: ::c_int = 6; // FIXME: Haiku does not have MAP_FILE, but library/std/os.rs requires it pub const MAP_FILE: ::c_int = 0x00; pub const MAP_SHARED: ::c_int = 0x01; pub const MAP_PRIVATE: ::c_int = 0x02; pub const MAP_FIXED: ::c_int = 0x04; pub const MAP_ANONYMOUS: ::c_int = 0x08; pub const MAP_NORESERVE: ::c_int = 0x10; pub const MAP_ANON: ::c_int = MAP_ANONYMOUS; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const MS_ASYNC: ::c_int = 0x01; pub const MS_INVALIDATE: ::c_int = 0x04; pub const MS_SYNC: ::c_int = 0x02; pub const E2BIG: ::c_int = -2147454975; pub const ECHILD: ::c_int = -2147454974; pub const EDEADLK: ::c_int = -2147454973; pub const EFBIG: ::c_int = -2147454972; pub const EMLINK: ::c_int = -2147454971; pub const ENFILE: ::c_int = -2147454970; pub const ENODEV: ::c_int = -2147454969; pub const ENOLCK: ::c_int = -2147454968; pub const ENOSYS: ::c_int = -2147454967; pub const ENOTTY: ::c_int = -2147454966; pub const ENXIO: ::c_int = -2147454965; pub const ESPIPE: ::c_int = -2147454964; pub const ESRCH: ::c_int = -2147454963; pub const EFPOS: ::c_int = -2147454962; pub const ESIGPARM: ::c_int = -2147454961; pub const EDOM: ::c_int = -2147454960; pub const ERANGE: ::c_int = -2147454959; pub const EPROTOTYPE: ::c_int = -2147454958; pub const EPROTONOSUPPORT: ::c_int = -2147454957; pub const EPFNOSUPPORT: ::c_int = -2147454956; pub const EAFNOSUPPORT: ::c_int = -2147454955; pub const EADDRINUSE: ::c_int = -2147454954; pub const EADDRNOTAVAIL: ::c_int = -2147454953; pub const ENETDOWN: ::c_int = -2147454952; pub const ENETUNREACH: ::c_int = -2147454951; pub const ENETRESET: ::c_int = -2147454950; pub const ECONNABORTED: ::c_int = -2147454949; pub const ECONNRESET: ::c_int = -2147454948; pub const EISCONN: ::c_int = -2147454947; pub const ENOTCONN: ::c_int = -2147454946; pub const ESHUTDOWN: ::c_int = -2147454945; pub const ECONNREFUSED: ::c_int = -2147454944; pub const EHOSTUNREACH: ::c_int = -2147454943; pub const ENOPROTOOPT: ::c_int = -2147454942; pub const ENOBUFS: ::c_int = -2147454941; pub const EINPROGRESS: ::c_int = -2147454940; pub const EALREADY: ::c_int = -2147454939; pub const EILSEQ: ::c_int = -2147454938; pub const ENOMSG: ::c_int = -2147454937; pub const ESTALE: ::c_int = -2147454936; pub const EOVERFLOW: ::c_int = -2147454935; pub const EMSGSIZE: ::c_int = -2147454934; pub const EOPNOTSUPP: ::c_int = -2147454933; pub const ENOTSOCK: ::c_int = -2147454932; pub const EHOSTDOWN: ::c_int = -2147454931; pub const EBADMSG: ::c_int = -2147454930; pub const ECANCELED: ::c_int = -2147454929; pub const EDESTADDRREQ: ::c_int = -2147454928; pub const EDQUOT: ::c_int = -2147454927; pub const EIDRM: ::c_int = -2147454926; pub const EMULTIHOP: ::c_int = -2147454925; pub const ENODATA: ::c_int = -2147454924; pub const ENOLINK: ::c_int = -2147454923; pub const ENOSR: ::c_int = -2147454922; pub const ENOSTR: ::c_int = -2147454921; pub const ENOTSUP: ::c_int = -2147454920; pub const EPROTO: ::c_int = -2147454919; pub const ETIME: ::c_int = -2147454918; pub const ETXTBSY: ::c_int = -2147454917; pub const ENOATTR: ::c_int = -2147454916; // INT_MIN pub const ENOMEM: ::c_int = -2147483648; // POSIX errors that can be mapped to BeOS error codes pub const EACCES: ::c_int = -2147483646; pub const EINTR: ::c_int = -2147483638; pub const EIO: ::c_int = -2147483647; pub const EBUSY: ::c_int = -2147483634; pub const EFAULT: ::c_int = -2147478783; pub const ETIMEDOUT: ::c_int = -2147483639; pub const EAGAIN: ::c_int = -2147483637; pub const EWOULDBLOCK: ::c_int = -2147483637; pub const EBADF: ::c_int = -2147459072; pub const EEXIST: ::c_int = -2147459070; pub const EINVAL: ::c_int = -2147483643; pub const ENAMETOOLONG: ::c_int = -2147459068; pub const ENOENT: ::c_int = -2147459069; pub const EPERM: ::c_int = -2147483633; pub const ENOTDIR: ::c_int = -2147459067; pub const EISDIR: ::c_int = -2147459063; pub const ENOTEMPTY: ::c_int = -2147459066; pub const ENOSPC: ::c_int = -2147459065; pub const EROFS: ::c_int = -2147459064; pub const EMFILE: ::c_int = -2147459062; pub const EXDEV: ::c_int = -2147459061; pub const ELOOP: ::c_int = -2147459060; pub const ENOEXEC: ::c_int = -2147478782; pub const EPIPE: ::c_int = -2147459059; pub const IPPROTO_RAW: ::c_int = 255; // These are prefixed with POSIX_ on Haiku pub const MADV_NORMAL: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_RANDOM: ::c_int = 3; pub const MADV_WILLNEED: ::c_int = 4; pub const MADV_DONTNEED: ::c_int = 5; pub const MADV_FREE: ::c_int = 6; // https://github.com/haiku/haiku/blob/HEAD/headers/posix/net/if.h#L80 pub const IFF_UP: ::c_int = 0x0001; pub const IFF_BROADCAST: ::c_int = 0x0002; // valid broadcast address pub const IFF_LOOPBACK: ::c_int = 0x0008; pub const IFF_POINTOPOINT: ::c_int = 0x0010; // point-to-point link pub const IFF_NOARP: ::c_int = 0x0040; // no address resolution pub const IFF_AUTOUP: ::c_int = 0x0080; // auto dial pub const IFF_PROMISC: ::c_int = 0x0100; // receive all packets pub const IFF_ALLMULTI: ::c_int = 0x0200; // receive all multicast packets pub const IFF_SIMPLEX: ::c_int = 0x0800; // doesn't receive own transmissions pub const IFF_LINK: ::c_int = 0x1000; // has link pub const IFF_AUTO_CONFIGURED: ::c_int = 0x2000; pub const IFF_CONFIGURING: ::c_int = 0x4000; pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast pub const AF_UNSPEC: ::c_int = 0; pub const AF_INET: ::c_int = 1; pub const AF_APPLETALK: ::c_int = 2; pub const AF_ROUTE: ::c_int = 3; pub const AF_LINK: ::c_int = 4; pub const AF_INET6: ::c_int = 5; pub const AF_DLI: ::c_int = 6; pub const AF_IPX: ::c_int = 7; pub const AF_NOTIFY: ::c_int = 8; pub const AF_LOCAL: ::c_int = 9; pub const AF_UNIX: ::c_int = AF_LOCAL; pub const AF_BLUETOOTH: ::c_int = 10; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_INET: ::c_int = AF_INET; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_LINK: ::c_int = AF_LINK; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_LOCAL: ::c_int = AF_LOCAL; pub const PF_UNIX: ::c_int = AF_UNIX; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const IP_OPTIONS: ::c_int = 1; pub const IP_HDRINCL: ::c_int = 2; pub const IP_TOS: ::c_int = 3; pub const IP_TTL: ::c_int = 4; pub const IP_RECVOPTS: ::c_int = 5; pub const IP_RECVRETOPTS: ::c_int = 6; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_RETOPTS: ::c_int = 8; pub const IP_MULTICAST_IF: ::c_int = 9; pub const IP_MULTICAST_TTL: ::c_int = 10; pub const IP_MULTICAST_LOOP: ::c_int = 11; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; pub const IP_BLOCK_SOURCE: ::c_int = 14; pub const IP_UNBLOCK_SOURCE: ::c_int = 15; pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 16; pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 17; pub const TCP_NODELAY: ::c_int = 0x01; pub const TCP_MAXSEG: ::c_int = 0x02; pub const TCP_NOPUSH: ::c_int = 0x04; pub const TCP_NOOPT: ::c_int = 0x08; pub const IF_NAMESIZE: ::size_t = 32; pub const IFNAMSIZ: ::size_t = IF_NAMESIZE; pub const IPV6_MULTICAST_IF: ::c_int = 24; pub const IPV6_MULTICAST_HOPS: ::c_int = 25; pub const IPV6_MULTICAST_LOOP: ::c_int = 26; pub const IPV6_UNICAST_HOPS: ::c_int = 27; pub const IPV6_JOIN_GROUP: ::c_int = 28; pub const IPV6_LEAVE_GROUP: ::c_int = 29; pub const IPV6_V6ONLY: ::c_int = 30; pub const IPV6_PKTINFO: ::c_int = 31; pub const IPV6_RECVPKTINFO: ::c_int = 32; pub const IPV6_HOPLIMIT: ::c_int = 33; pub const IPV6_RECVHOPLIMIT: ::c_int = 34; pub const IPV6_HOPOPTS: ::c_int = 35; pub const IPV6_DSTOPTS: ::c_int = 36; pub const IPV6_RTHDR: ::c_int = 37; pub const MSG_OOB: ::c_int = 0x0001; pub const MSG_PEEK: ::c_int = 0x0002; pub const MSG_DONTROUTE: ::c_int = 0x0004; pub const MSG_EOR: ::c_int = 0x0008; pub const MSG_TRUNC: ::c_int = 0x0010; pub const MSG_CTRUNC: ::c_int = 0x0020; pub const MSG_WAITALL: ::c_int = 0x0040; pub const MSG_DONTWAIT: ::c_int = 0x0080; pub const MSG_BCAST: ::c_int = 0x0100; pub const MSG_MCAST: ::c_int = 0x0200; pub const MSG_EOF: ::c_int = 0x0400; pub const MSG_NOSIGNAL: ::c_int = 0x0800; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const LOCK_SH: ::c_int = 0x01; pub const LOCK_EX: ::c_int = 0x02; pub const LOCK_NB: ::c_int = 0x04; pub const LOCK_UN: ::c_int = 0x08; pub const MINSIGSTKSZ: ::size_t = 8192; pub const SIGSTKSZ: ::size_t = 16384; pub const IOV_MAX: ::c_int = 1024; pub const PATH_MAX: ::c_int = 1024; pub const SA_NOCLDSTOP: ::c_int = 0x01; pub const SA_NOCLDWAIT: ::c_int = 0x02; pub const SA_RESETHAND: ::c_int = 0x04; pub const SA_NODEFER: ::c_int = 0x08; pub const SA_RESTART: ::c_int = 0x10; pub const SA_ONSTACK: ::c_int = 0x20; pub const SA_SIGINFO: ::c_int = 0x40; pub const SA_NOMASK: ::c_int = SA_NODEFER; pub const SA_STACK: ::c_int = SA_ONSTACK; pub const SA_ONESHOT: ::c_int = SA_RESETHAND; pub const SS_ONSTACK: ::c_int = 0x1; pub const SS_DISABLE: ::c_int = 0x2; pub const FD_SETSIZE: usize = 1024; pub const RTLD_LOCAL: ::c_int = 0x0; pub const RTLD_NOW: ::c_int = 0x1; pub const RTLD_GLOBAL: ::c_int = 0x2; pub const RTLD_DEFAULT: *mut ::c_void = 0isize as *mut ::c_void; pub const BUFSIZ: ::c_uint = 8192; pub const FILENAME_MAX: ::c_uint = 256; pub const FOPEN_MAX: ::c_uint = 128; pub const L_tmpnam: ::c_uint = 512; pub const TMP_MAX: ::c_uint = 32768; pub const _PC_CHOWN_RESTRICTED: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_NO_TRUNC: ::c_int = 5; pub const _PC_PATH_MAX: ::c_int = 6; pub const _PC_PIPE_BUF: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_LINK_MAX: ::c_int = 25; pub const _PC_SYNC_IO: ::c_int = 26; pub const _PC_ASYNC_IO: ::c_int = 27; pub const _PC_PRIO_IO: ::c_int = 28; pub const _PC_SOCK_MAXBUF: ::c_int = 29; pub const _PC_FILESIZEBITS: ::c_int = 30; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 31; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 32; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 33; pub const _PC_REC_XFER_ALIGN: ::c_int = 34; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 35; pub const _PC_SYMLINK_MAX: ::c_int = 36; pub const _PC_2_SYMLINKS: ::c_int = 37; pub const _PC_XATTR_EXISTS: ::c_int = 38; pub const _PC_XATTR_ENABLED: ::c_int = 39; pub const FIONBIO: ::c_ulong = 0xbe000000; pub const FIONREAD: ::c_ulong = 0xbe000001; pub const FIOSEEKDATA: ::c_ulong = 0xbe000002; pub const FIOSEEKHOLE: ::c_ulong = 0xbe000003; pub const _SC_ARG_MAX: ::c_int = 15; pub const _SC_CHILD_MAX: ::c_int = 16; pub const _SC_CLK_TCK: ::c_int = 17; pub const _SC_JOB_CONTROL: ::c_int = 18; pub const _SC_NGROUPS_MAX: ::c_int = 19; pub const _SC_OPEN_MAX: ::c_int = 20; pub const _SC_SAVED_IDS: ::c_int = 21; pub const _SC_STREAM_MAX: ::c_int = 22; pub const _SC_TZNAME_MAX: ::c_int = 23; pub const _SC_VERSION: ::c_int = 24; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 25; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 26; pub const _SC_PAGESIZE: ::c_int = 27; pub const _SC_PAGE_SIZE: ::c_int = 27; pub const _SC_SEM_NSEMS_MAX: ::c_int = 28; pub const _SC_SEM_VALUE_MAX: ::c_int = 29; pub const _SC_SEMAPHORES: ::c_int = 30; pub const _SC_THREADS: ::c_int = 31; pub const _SC_IOV_MAX: ::c_int = 32; pub const _SC_UIO_MAXIOV: ::c_int = 32; pub const _SC_NPROCESSORS_CONF: ::c_int = 34; pub const _SC_NPROCESSORS_ONLN: ::c_int = 35; pub const _SC_ATEXIT_MAX: ::c_int = 37; pub const _SC_PASS_MAX: ::c_int = 39; pub const _SC_PHYS_PAGES: ::c_int = 40; pub const _SC_AVPHYS_PAGES: ::c_int = 41; pub const _SC_PIPE: ::c_int = 42; pub const _SC_SELECT: ::c_int = 43; pub const _SC_POLL: ::c_int = 44; pub const _SC_MAPPED_FILES: ::c_int = 45; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 46; pub const _SC_THREAD_STACK_MIN: ::c_int = 47; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 48; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 49; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 50; pub const _SC_REALTIME_SIGNALS: ::c_int = 51; pub const _SC_MEMORY_PROTECTION: ::c_int = 52; pub const _SC_SIGQUEUE_MAX: ::c_int = 53; pub const _SC_RTSIG_MAX: ::c_int = 54; pub const _SC_MONOTONIC_CLOCK: ::c_int = 55; pub const _SC_DELAYTIMER_MAX: ::c_int = 56; pub const _SC_TIMER_MAX: ::c_int = 57; pub const _SC_TIMERS: ::c_int = 58; pub const _SC_CPUTIME: ::c_int = 59; pub const _SC_THREAD_CPUTIME: ::c_int = 60; pub const _SC_HOST_NAME_MAX: ::c_int = 61; pub const _SC_REGEXP: ::c_int = 62; pub const _SC_SYMLOOP_MAX: ::c_int = 63; pub const _SC_SHELL: ::c_int = 64; pub const _SC_TTY_NAME_MAX: ::c_int = 65; pub const _SC_ADVISORY_INFO: ::c_int = 66; pub const _SC_BARRIERS: ::c_int = 67; pub const _SC_CLOCK_SELECTION: ::c_int = 68; pub const _SC_FSYNC: ::c_int = 69; pub const _SC_IPV6: ::c_int = 70; pub const _SC_MEMLOCK: ::c_int = 71; pub const _SC_MEMLOCK_RANGE: ::c_int = 72; pub const _SC_MESSAGE_PASSING: ::c_int = 73; pub const _SC_PRIORITIZED_IO: ::c_int = 74; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 75; pub const _SC_READER_WRITER_LOCKS: ::c_int = 76; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 77; pub const _SC_SPAWN: ::c_int = 78; pub const _SC_SPIN_LOCKS: ::c_int = 79; pub const _SC_SPORADIC_SERVER: ::c_int = 80; pub const _SC_SYNCHRONIZED_IO: ::c_int = 81; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 82; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 83; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 84; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 85; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 86; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 87; pub const _SC_TIMEOUTS: ::c_int = 88; pub const _SC_TRACE: ::c_int = 89; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 90; pub const _SC_TRACE_INHERIT: ::c_int = 91; pub const _SC_TRACE_LOG: ::c_int = 92; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 93; pub const _SC_V6_ILP32_OFF32: ::c_int = 94; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 95; pub const _SC_V6_LP64_OFF64: ::c_int = 96; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 97; pub const _SC_V7_ILP32_OFF32: ::c_int = 98; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 99; pub const _SC_V7_LP64_OFF64: ::c_int = 100; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 101; pub const _SC_2_C_BIND: ::c_int = 102; pub const _SC_2_C_DEV: ::c_int = 103; pub const _SC_2_CHAR_TERM: ::c_int = 104; pub const _SC_2_FORT_DEV: ::c_int = 105; pub const _SC_2_FORT_RUN: ::c_int = 106; pub const _SC_2_LOCALEDEF: ::c_int = 107; pub const _SC_2_PBS: ::c_int = 108; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 109; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 110; pub const _SC_2_PBS_LOCATE: ::c_int = 111; pub const _SC_2_PBS_MESSAGE: ::c_int = 112; pub const _SC_2_PBS_TRACK: ::c_int = 113; pub const _SC_2_SW_DEV: ::c_int = 114; pub const _SC_2_UPE: ::c_int = 115; pub const _SC_2_VERSION: ::c_int = 116; pub const _SC_XOPEN_CRYPT: ::c_int = 117; pub const _SC_XOPEN_ENH_I18N: ::c_int = 118; pub const _SC_XOPEN_REALTIME: ::c_int = 119; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 120; pub const _SC_XOPEN_SHM: ::c_int = 121; pub const _SC_XOPEN_STREAMS: ::c_int = 122; pub const _SC_XOPEN_UNIX: ::c_int = 123; pub const _SC_XOPEN_UUCP: ::c_int = 124; pub const _SC_XOPEN_VERSION: ::c_int = 125; pub const _SC_BC_BASE_MAX: ::c_int = 129; pub const _SC_BC_DIM_MAX: ::c_int = 130; pub const _SC_BC_SCALE_MAX: ::c_int = 131; pub const _SC_BC_STRING_MAX: ::c_int = 132; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 133; pub const _SC_EXPR_NEST_MAX: ::c_int = 134; pub const _SC_LINE_MAX: ::c_int = 135; pub const _SC_LOGIN_NAME_MAX: ::c_int = 136; pub const _SC_MQ_OPEN_MAX: ::c_int = 137; pub const _SC_MQ_PRIO_MAX: ::c_int = 138; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 139; pub const _SC_THREAD_KEYS_MAX: ::c_int = 140; pub const _SC_THREAD_THREADS_MAX: ::c_int = 141; pub const _SC_RE_DUP_MAX: ::c_int = 142; pub const PTHREAD_STACK_MIN: ::size_t = 8192; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { flags: 0, lock: 0, unused: -42, owner: -1, owner_count: 0, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { flags: 0, unused: -42, mutex: 0 as *mut _, waiter_count: 0, lock: 0, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { flags: 0, owner: -1, lock_sem: 0, lock_count: 0, reader_count: 0, writer_count: 0, waiters: [0 as *mut _; 2], }; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = 0; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 3; pub const FIOCLEX: c_ulong = 0; // FIXME: does not exist on Haiku! pub const RUSAGE_CHILDREN: ::c_int = -1; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOL_SOCKET: ::c_int = -1; pub const SO_ACCEPTCONN: ::c_int = 0x00000001; pub const SO_BROADCAST: ::c_int = 0x00000002; pub const SO_DEBUG: ::c_int = 0x00000004; pub const SO_DONTROUTE: ::c_int = 0x00000008; pub const SO_KEEPALIVE: ::c_int = 0x00000010; pub const SO_OOBINLINE: ::c_int = 0x00000020; pub const SO_REUSEADDR: ::c_int = 0x00000040; pub const SO_REUSEPORT: ::c_int = 0x00000080; pub const SO_USELOOPBACK: ::c_int = 0x00000100; pub const SO_LINGER: ::c_int = 0x00000200; pub const SO_SNDBUF: ::c_int = 0x40000001; pub const SO_SNDLOWAT: ::c_int = 0x40000002; pub const SO_SNDTIMEO: ::c_int = 0x40000003; pub const SO_RCVBUF: ::c_int = 0x40000004; pub const SO_RCVLOWAT: ::c_int = 0x40000005; pub const SO_RCVTIMEO: ::c_int = 0x40000006; pub const SO_ERROR: ::c_int = 0x40000007; pub const SO_TYPE: ::c_int = 0x40000008; pub const SO_NONBLOCK: ::c_int = 0x40000009; pub const SO_BINDTODEVICE: ::c_int = 0x4000000a; pub const SO_PEERCRED: ::c_int = 0x4000000b; pub const SCM_RIGHTS: ::c_int = 0x01; pub const SOMAXCONN: ::c_int = 32; pub const NI_MAXHOST: ::size_t = 1025; pub const WNOHANG: ::c_int = 0x01; pub const WUNTRACED: ::c_int = 0x02; pub const WCONTINUED: ::c_int = 0x04; pub const WEXITED: ::c_int = 0x08; pub const WSTOPPED: ::c_int = 0x10; pub const WNOWAIT: ::c_int = 0x20; // si_code values for SIGBUS signal pub const BUS_ADRALN: ::c_int = 40; pub const BUS_ADRERR: ::c_int = 41; pub const BUS_OBJERR: ::c_int = 42; // si_code values for SIGCHLD signal pub const CLD_EXITED: ::c_int = 60; pub const CLD_KILLED: ::c_int = 61; pub const CLD_DUMPED: ::c_int = 62; pub const CLD_TRAPPED: ::c_int = 63; pub const CLD_STOPPED: ::c_int = 64; pub const CLD_CONTINUED: ::c_int = 65; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const UTIME_OMIT: c_long = 1000000001; pub const UTIME_NOW: c_long = 1000000000; pub const VINTR: usize = 0; pub const VQUIT: usize = 1; pub const VERASE: usize = 2; pub const VKILL: usize = 3; pub const VEOF: usize = 4; pub const VEOL: usize = 5; pub const VMIN: usize = 4; pub const VTIME: usize = 5; pub const VEOL2: usize = 6; pub const VSWTCH: usize = 7; pub const VSTART: usize = 8; pub const VSTOP: usize = 9; pub const VSUSP: usize = 10; pub const IGNBRK: ::tcflag_t = 0x01; pub const BRKINT: ::tcflag_t = 0x02; pub const IGNPAR: ::tcflag_t = 0x04; pub const PARMRK: ::tcflag_t = 0x08; pub const INPCK: ::tcflag_t = 0x10; pub const ISTRIP: ::tcflag_t = 0x20; pub const INLCR: ::tcflag_t = 0x40; pub const IGNCR: ::tcflag_t = 0x80; pub const ICRNL: ::tcflag_t = 0x100; pub const IUCLC: ::tcflag_t = 0x200; pub const IXON: ::tcflag_t = 0x400; pub const IXANY: ::tcflag_t = 0x800; pub const IXOFF: ::tcflag_t = 0x1000; pub const OPOST: ::tcflag_t = 0x00000001; pub const OLCUC: ::tcflag_t = 0x00000002; pub const ONLCR: ::tcflag_t = 0x00000004; pub const OCRNL: ::tcflag_t = 0x00000008; pub const ONOCR: ::tcflag_t = 0x00000010; pub const ONLRET: ::tcflag_t = 0x00000020; pub const OFILL: ::tcflag_t = 0x00000040; pub const OFDEL: ::tcflag_t = 0x00000080; pub const NLDLY: ::tcflag_t = 0x00000100; pub const NL0: ::tcflag_t = 0x00000000; pub const NL1: ::tcflag_t = 0x00000100; pub const CRDLY: ::tcflag_t = 0x00000600; pub const CR0: ::tcflag_t = 0x00000000; pub const CR1: ::tcflag_t = 0x00000200; pub const CR2: ::tcflag_t = 0x00000400; pub const CR3: ::tcflag_t = 0x00000600; pub const TABDLY: ::tcflag_t = 0x00001800; pub const TAB0: ::tcflag_t = 0x00000000; pub const TAB1: ::tcflag_t = 0x00000800; pub const TAB2: ::tcflag_t = 0x00001000; pub const TAB3: ::tcflag_t = 0x00001800; pub const BSDLY: ::tcflag_t = 0x00002000; pub const BS0: ::tcflag_t = 0x00000000; pub const BS1: ::tcflag_t = 0x00002000; pub const VTDLY: ::tcflag_t = 0x00004000; pub const VT0: ::tcflag_t = 0x00000000; pub const VT1: ::tcflag_t = 0x00004000; pub const FFDLY: ::tcflag_t = 0x00008000; pub const FF0: ::tcflag_t = 0x00000000; pub const FF1: ::tcflag_t = 0x00008000; pub const CSIZE: ::tcflag_t = 0x00000020; pub const CS5: ::tcflag_t = 0x00000000; pub const CS6: ::tcflag_t = 0x00000000; pub const CS7: ::tcflag_t = 0x00000000; pub const CS8: ::tcflag_t = 0x00000020; pub const CSTOPB: ::tcflag_t = 0x00000040; pub const CREAD: ::tcflag_t = 0x00000080; pub const PARENB: ::tcflag_t = 0x00000100; pub const PARODD: ::tcflag_t = 0x00000200; pub const HUPCL: ::tcflag_t = 0x00000400; pub const CLOCAL: ::tcflag_t = 0x00000800; pub const XLOBLK: ::tcflag_t = 0x00001000; pub const CTSFLOW: ::tcflag_t = 0x00002000; pub const RTSFLOW: ::tcflag_t = 0x00004000; pub const CRTSCTS: ::tcflag_t = RTSFLOW | CTSFLOW; pub const ISIG: ::tcflag_t = 0x00000001; pub const ICANON: ::tcflag_t = 0x00000002; pub const XCASE: ::tcflag_t = 0x00000004; pub const ECHO: ::tcflag_t = 0x00000008; pub const ECHOE: ::tcflag_t = 0x00000010; pub const ECHOK: ::tcflag_t = 0x00000020; pub const ECHONL: ::tcflag_t = 0x00000040; pub const NOFLSH: ::tcflag_t = 0x00000080; pub const TOSTOP: ::tcflag_t = 0x00000100; pub const IEXTEN: ::tcflag_t = 0x00000200; pub const ECHOCTL: ::tcflag_t = 0x00000400; pub const ECHOPRT: ::tcflag_t = 0x00000800; pub const ECHOKE: ::tcflag_t = 0x00001000; pub const FLUSHO: ::tcflag_t = 0x00002000; pub const PENDIN: ::tcflag_t = 0x00004000; pub const TCGB_CTS: ::c_int = 0x01; pub const TCGB_DSR: ::c_int = 0x02; pub const TCGB_RI: ::c_int = 0x04; pub const TCGB_DCD: ::c_int = 0x08; pub const TIOCM_CTS: ::c_int = TCGB_CTS; pub const TIOCM_CD: ::c_int = TCGB_DCD; pub const TIOCM_CAR: ::c_int = TCGB_DCD; pub const TIOCM_RI: ::c_int = TCGB_RI; pub const TIOCM_RNG: ::c_int = TCGB_RI; pub const TIOCM_DSR: ::c_int = TCGB_DSR; pub const TIOCM_DTR: ::c_int = 0x10; pub const TIOCM_RTS: ::c_int = 0x20; pub const B0: speed_t = 0x00; pub const B50: speed_t = 0x01; pub const B75: speed_t = 0x02; pub const B110: speed_t = 0x03; pub const B134: speed_t = 0x04; pub const B150: speed_t = 0x05; pub const B200: speed_t = 0x06; pub const B300: speed_t = 0x07; pub const B600: speed_t = 0x08; pub const B1200: speed_t = 0x09; pub const B1800: speed_t = 0x0A; pub const B2400: speed_t = 0x0B; pub const B4800: speed_t = 0x0C; pub const B9600: speed_t = 0x0D; pub const B19200: speed_t = 0x0E; pub const B38400: speed_t = 0x0F; pub const B57600: speed_t = 0x10; pub const B115200: speed_t = 0x11; pub const B230400: speed_t = 0x12; pub const B31250: speed_t = 0x13; pub const TCSANOW: ::c_int = 0x01; pub const TCSADRAIN: ::c_int = 0x02; pub const TCSAFLUSH: ::c_int = 0x04; pub const TCOOFF: ::c_int = 0x01; pub const TCOON: ::c_int = 0x02; pub const TCIOFF: ::c_int = 0x04; pub const TCION: ::c_int = 0x08; pub const TCIFLUSH: ::c_int = 0x01; pub const TCOFLUSH: ::c_int = 0x02; pub const TCIOFLUSH: ::c_int = 0x03; pub const TCGETA: ::c_ulong = 0x8000; pub const TCSETA: ::c_ulong = TCGETA + 1; pub const TCSETAF: ::c_ulong = TCGETA + 2; pub const TCSETAW: ::c_ulong = TCGETA + 3; pub const TCSBRK: ::c_ulong = TCGETA + 5; pub const TCFLSH: ::c_ulong = TCGETA + 6; pub const TCXONC: ::c_ulong = TCGETA + 7; pub const TCGETBITS: ::c_ulong = TCGETA + 9; pub const TCSETDTR: ::c_ulong = TCGETA + 10; pub const TCSETRTS: ::c_ulong = TCGETA + 11; pub const TIOCGWINSZ: ::c_ulong = TCGETA + 12; pub const TIOCSWINSZ: ::c_ulong = TCGETA + 13; pub const TIOCGPGRP: ::c_ulong = TCGETA + 15; pub const TIOCSPGRP: ::c_ulong = TCGETA + 16; pub const TIOCSCTTY: ::c_ulong = TCGETA + 17; pub const TIOCMGET: ::c_ulong = TCGETA + 18; pub const TIOCMSET: ::c_ulong = TCGETA + 19; pub const TIOCSBRK: ::c_ulong = TCGETA + 20; pub const TIOCCBRK: ::c_ulong = TCGETA + 21; pub const TIOCMBIS: ::c_ulong = TCGETA + 22; pub const TIOCMBIC: ::c_ulong = TCGETA + 23; pub const TIOCGSID: ::c_ulong = TCGETA + 24; pub const TIOCOUTQ: ::c_ulong = TCGETA + 25; pub const TIOCEXCL: ::c_ulong = TCGETA + 26; pub const TIOCNXCL: ::c_ulong = TCGETA + 27; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; // utmpx entry types pub const EMPTY: ::c_short = 0; pub const BOOT_TIME: ::c_short = 1; pub const OLD_TIME: ::c_short = 2; pub const NEW_TIME: ::c_short = 3; pub const USER_PROCESS: ::c_short = 4; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const DEAD_PROCESS: ::c_short = 7; pub const LOG_PID: ::c_int = 1 << 12; pub const LOG_CONS: ::c_int = 2 << 12; pub const LOG_ODELAY: ::c_int = 4 << 12; pub const LOG_NDELAY: ::c_int = 8 << 12; pub const LOG_SERIAL: ::c_int = 16 << 12; pub const LOG_PERROR: ::c_int = 32 << 12; pub const LOG_NOWAIT: ::c_int = 64 << 12; // spawn.h pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x10; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x20; pub const POSIX_SPAWN_SETSID: ::c_int = 0x40; const_fn! { {const} fn CMSG_ALIGN(len: usize) -> usize { len + ::mem::size_of::() - 1 & !(::mem::size_of::() - 1) } } f! { pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize >= ::mem::size_of::() { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(::mem::size_of::())) as ::c_uint } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { CMSG_ALIGN(::mem::size_of::()) as ::c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { if cmsg.is_null() { return ::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize) + CMSG_ALIGN(::mem::size_of::<::cmsghdr>()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut ::cmsghdr } else { (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut ::cmsghdr } } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & !0xff) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { status & 0xff } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { ((status >> 8) & 0xff) != 0 } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { ((status >> 16) & 0xff) != 0 } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status >> 16) & 0xff } // actually WIFCORED, but this is used everywhere else pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0x10000) != 0 } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { (status & 0x20000) != 0 } } extern "C" { pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn getpriority(which: ::c_int, who: id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: id_t, priority: ::c_int) -> ::c_int; pub fn endusershell(); pub fn getpass(prompt: *const ::c_char) -> *mut ::c_char; pub fn getusershell() -> *mut ::c_char; pub fn issetugid() -> ::c_int; pub fn setusershell(); pub fn utimensat( fd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn _errnop() -> *mut ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn ppoll( fds: *mut ::pollfd, numfds: ::nfds_t, timeout: *const ::timespec, sigMask: *const sigset_t, ) -> ::c_int; pub fn getspent() -> *mut spwd; pub fn getspent_r( pwd: *mut spwd, buf: *mut ::c_char, bufferSize: ::size_t, res: *mut *mut spwd, ) -> ::c_int; pub fn setspent(); pub fn endspent(); pub fn getspnam(name: *const ::c_char) -> *mut spwd; pub fn getspnam_r( name: *const ::c_char, spwd: *mut spwd, buffer: *mut ::c_char, bufferSize: ::size_t, res: *mut *mut spwd, ) -> ::c_int; pub fn sgetspent(line: *const ::c_char) -> *mut spwd; pub fn sgetspent_r( line: *const ::c_char, spwd: *mut spwd, buffer: *mut ::c_char, bufferSize: ::size_t, res: *mut *mut spwd, ) -> ::c_int; pub fn fgetspent(file: *mut ::FILE) -> *mut spwd; pub fn fgetspent_r( file: *mut ::FILE, spwd: *mut spwd, buffer: *mut ::c_char, bufferSize: ::size_t, res: *mut *mut spwd, ) -> ::c_int; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn pthread_create( thread: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn valloc(numBytes: ::size_t) -> *mut ::c_void; pub fn malloc_usable_size(ptr: *mut ::c_void) -> ::size_t; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_spin_init(lock: *mut ::pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut ::pthread_spinlock_t) -> ::c_int; pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; pub fn glob( pattern: *const ::c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; pub fn globfree(pglob: *mut ::glob_t); pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advice: ::c_int) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, count: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, count: ::c_int) -> ::ssize_t; pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, environment: *const *const ::c_char, ) -> ::c_int; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getgrouplist( user: *const ::c_char, basegroup: ::gid_t, grouplist: *mut ::gid_t, groupcount: *mut ::c_int, ) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwent() -> *mut passwd; pub fn setpwent(); pub fn endpwent(); pub fn endgrent(); pub fn getgrent() -> *mut ::group; pub fn setgrent(); pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn getitimer(which: ::c_int, curr_value: *mut ::itimerval) -> ::c_int; pub fn setitimer( which: ::c_int, new_value: *const ::itimerval, old_value: *mut ::itimerval, ) -> ::c_int; pub fn regcomp(preg: *mut regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regexec( preg: *const regex_t, input: *const ::c_char, nmatch: ::size_t, pmatch: *mut regmatch_t, eflags: ::c_int, ) -> ::c_int; pub fn regerror( errcode: ::c_int, preg: *const regex_t, errbuf: *mut ::c_char, errbuf_size: ::size_t, ) -> ::size_t; pub fn regfree(preg: *mut regex_t); pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtype: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn msgsnd( msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, msgflg: ::c_int, ) -> ::c_int; pub fn semget(key: ::key_t, nsems: ::c_int, semflg: ::c_int) -> ::c_int; pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn semop(semid: ::c_int, sops: *mut sembuf, nsops: ::size_t) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn lsearch( key: *const ::c_void, base: *mut ::c_void, nelp: *mut ::size_t, width: ::size_t, compar: ::Option ::c_int>, ) -> *mut ::c_void; pub fn lfind( key: *const ::c_void, base: *const ::c_void, nelp: *mut ::size_t, width: ::size_t, compar: ::Option ::c_int>, ) -> *mut ::c_void; pub fn hcreate(nelt: ::size_t) -> ::c_int; pub fn hdestroy(); pub fn hsearch(entry: ::ENTRY, action: ::ACTION) -> *mut ::ENTRY; pub fn drand48() -> ::c_double; pub fn erand48(xseed: *mut ::c_ushort) -> ::c_double; pub fn lrand48() -> ::c_long; pub fn nrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn mrand48() -> ::c_long; pub fn jrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn srand48(seed: ::c_long); pub fn seed48(xseed: *mut ::c_ushort) -> *mut ::c_ushort; pub fn lcong48(p: *mut ::c_ushort); pub fn clearenv() -> ::c_int; pub fn ctermid(s: *mut ::c_char) -> *mut ::c_char; pub fn sync(); pub fn getpagesize() -> ::c_int; pub fn brk(addr: *mut ::c_void) -> ::c_int; pub fn sbrk(increment: ::intptr_t) -> *mut ::c_void; pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawn_file_actions_init(file_actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_destroy( file_actions: *mut posix_spawn_file_actions_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addopen( file_actions: *mut posix_spawn_file_actions_t, fildes: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( file_actions: *mut posix_spawn_file_actions_t, fildes: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( file_actions: *mut posix_spawn_file_actions_t, fildes: ::c_int, newfildes: ::c_int, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, _flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, _pgroup: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, pgroup: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, sigdefault: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, sigdefault: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, _sigmask: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, sigmask: *const ::sigset_t, ) -> ::c_int; pub fn getopt_long( argc: ::c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut ::c_int, ) -> ::c_int; pub fn strcasecmp_l( string1: *const ::c_char, string2: *const ::c_char, locale: ::locale_t, ) -> ::c_int; pub fn strncasecmp_l( string1: *const ::c_char, string2: *const ::c_char, length: ::size_t, locale: ::locale_t, ) -> ::c_int; } #[link(name = "bsd")] extern "C" { pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::pid_t; pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::c_int; pub fn strsep(string: *mut *mut ::c_char, delimiters: *const ::c_char) -> *mut ::c_char; pub fn explicit_bzero(buf: *mut ::c_void, len: ::size_t); pub fn login_tty(_fd: ::c_int) -> ::c_int; pub fn sl_init() -> *mut StringList; pub fn sl_add(sl: *mut StringList, n: *mut ::c_char) -> ::c_int; pub fn sl_free(sl: *mut StringList, i: ::c_int); pub fn sl_find(sl: *mut StringList, n: *mut ::c_char) -> *mut ::c_char; pub fn getprogname() -> *const ::c_char; pub fn setprogname(progname: *const ::c_char); pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut dl_phdr_info, size: usize, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; } #[link(name = "gnu")] extern "C" { pub fn memmem( source: *const ::c_void, sourceLength: ::size_t, search: *const ::c_void, searchLength: ::size_t, ) -> *mut ::c_void; pub fn pthread_getattr_np(thread: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_getname_np( thread: ::pthread_t, buffer: *mut ::c_char, length: ::size_t, ) -> ::c_int; pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int; } cfg_if! { if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { mod b32; pub use self::b32::*; } } cfg_if! { if #[cfg(target_arch = "x86")] { // TODO // mod x86; // pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { // TODO // mod aarch64; // pub use self::aarch64::*; } } mod native; pub use self::native::*; libc/src/unix/haiku/b64.rs0000644000175000017500000000076214661133735016273 0ustar jamespagejamespagepub type c_ulong = u64; pub type c_long = i64; pub type time_t = i64; pub type Elf_Addr = ::Elf64_Addr; pub type Elf_Half = ::Elf64_Half; pub type Elf_Phdr = ::Elf64_Phdr; s! { pub struct Elf64_Phdr { pub p_type: ::Elf64_Word, pub p_flags: ::Elf64_Word, pub p_offset: ::Elf64_Off, pub p_vaddr: ::Elf64_Addr, pub p_paddr: ::Elf64_Addr, pub p_filesz: ::Elf64_Xword, pub p_memsz: ::Elf64_Xword, pub p_align: ::Elf64_Xword, } } libc/src/unix/haiku/native.rs0000644000175000017500000015071214661133735017167 0ustar jamespagejamespage// This module contains bindings to the native Haiku API. The Haiku API // originates from BeOS, and it was the original way to perform low level // system and IO operations. The POSIX API was in that era was like a // compatibility layer. In current Haiku development, both the POSIX API and // the Haiku API are considered to be co-equal status. However, they are not // integrated like they are on other UNIX platforms, which means that for many // low level concepts there are two versions, like processes (POSIX) and // teams (Haiku), or pthreads and native threads. // // Both the POSIX API and the Haiku API live in libroot.so, the library that is // linked to any binary by default. // // This file follows the Haiku API for Haiku R1 beta 2. It is organized by the // C/C++ header files in which the concepts can be found, while adhering to the // style guide for this crate. // Helper macro to generate u32 constants. The Haiku API uses (non-standard) // multi-character constants (like 'UPDA' or 'MSGM') to represent 32 bit // integer constants. macro_rules! haiku_constant { ($a:tt, $b:tt, $c:tt, $d:tt) => { (($a as u32) << 24) + (($b as u32) << 16) + (($c as u32) << 8) + ($d as u32) }; } // support/SupportDefs.h pub type status_t = i32; pub type bigtime_t = i64; pub type nanotime_t = i64; pub type type_code = u32; pub type perform_code = u32; // kernel/OS.h pub type area_id = i32; pub type port_id = i32; pub type sem_id = i32; pub type team_id = i32; pub type thread_id = i32; pub type thread_func = extern "C" fn(*mut ::c_void) -> status_t; // kernel/image.h pub type image_id = i32; e! { // kernel/OS.h pub enum thread_state { B_THREAD_RUNNING = 1, B_THREAD_READY, B_THREAD_RECEIVING, B_THREAD_ASLEEP, B_THREAD_SUSPENDED, B_THREAD_WAITING } // kernel/image.h pub enum image_type { B_APP_IMAGE = 1, B_LIBRARY_IMAGE, B_ADD_ON_IMAGE, B_SYSTEM_IMAGE } // kernel/scheduler.h pub enum be_task_flags { B_DEFAULT_MEDIA_PRIORITY = 0x000, B_OFFLINE_PROCESSING = 0x001, B_STATUS_RENDERING = 0x002, B_USER_INPUT_HANDLING = 0x004, B_LIVE_VIDEO_MANIPULATION = 0x008, B_VIDEO_PLAYBACK = 0x010, B_VIDEO_RECORDING = 0x020, B_LIVE_AUDIO_MANIPULATION = 0x040, B_AUDIO_PLAYBACK = 0x080, B_AUDIO_RECORDING = 0x100, B_LIVE_3D_RENDERING = 0x200, B_NUMBER_CRUNCHING = 0x400, B_MIDI_PROCESSING = 0x800, } pub enum schduler_mode { SCHEDULER_MODE_LOW_LATENCY, SCHEDULER_MODE_POWER_SAVING, } // FindDirectory.h pub enum path_base_directory { B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY, B_FIND_PATH_ADD_ONS_DIRECTORY, B_FIND_PATH_APPS_DIRECTORY, B_FIND_PATH_BIN_DIRECTORY, B_FIND_PATH_BOOT_DIRECTORY, B_FIND_PATH_CACHE_DIRECTORY, B_FIND_PATH_DATA_DIRECTORY, B_FIND_PATH_DEVELOP_DIRECTORY, B_FIND_PATH_DEVELOP_LIB_DIRECTORY, B_FIND_PATH_DOCUMENTATION_DIRECTORY, B_FIND_PATH_ETC_DIRECTORY, B_FIND_PATH_FONTS_DIRECTORY, B_FIND_PATH_HEADERS_DIRECTORY, B_FIND_PATH_LIB_DIRECTORY, B_FIND_PATH_LOG_DIRECTORY, B_FIND_PATH_MEDIA_NODES_DIRECTORY, B_FIND_PATH_PACKAGES_DIRECTORY, B_FIND_PATH_PREFERENCES_DIRECTORY, B_FIND_PATH_SERVERS_DIRECTORY, B_FIND_PATH_SETTINGS_DIRECTORY, B_FIND_PATH_SOUNDS_DIRECTORY, B_FIND_PATH_SPOOL_DIRECTORY, B_FIND_PATH_TRANSLATORS_DIRECTORY, B_FIND_PATH_VAR_DIRECTORY, B_FIND_PATH_IMAGE_PATH = 1000, B_FIND_PATH_PACKAGE_PATH, } pub enum directory_which { B_DESKTOP_DIRECTORY = 0, B_TRASH_DIRECTORY, B_SYSTEM_DIRECTORY = 1000, B_SYSTEM_ADDONS_DIRECTORY = 1002, B_SYSTEM_BOOT_DIRECTORY, B_SYSTEM_FONTS_DIRECTORY, B_SYSTEM_LIB_DIRECTORY, B_SYSTEM_SERVERS_DIRECTORY, B_SYSTEM_APPS_DIRECTORY, B_SYSTEM_BIN_DIRECTORY, B_SYSTEM_DOCUMENTATION_DIRECTORY = 1010, B_SYSTEM_PREFERENCES_DIRECTORY, B_SYSTEM_TRANSLATORS_DIRECTORY, B_SYSTEM_MEDIA_NODES_DIRECTORY, B_SYSTEM_SOUNDS_DIRECTORY, B_SYSTEM_DATA_DIRECTORY, B_SYSTEM_DEVELOP_DIRECTORY, B_SYSTEM_PACKAGES_DIRECTORY, B_SYSTEM_HEADERS_DIRECTORY, B_SYSTEM_ETC_DIRECTORY = 2008, B_SYSTEM_SETTINGS_DIRECTORY = 2010, B_SYSTEM_LOG_DIRECTORY = 2012, B_SYSTEM_SPOOL_DIRECTORY, B_SYSTEM_TEMP_DIRECTORY, B_SYSTEM_VAR_DIRECTORY, B_SYSTEM_CACHE_DIRECTORY = 2020, B_SYSTEM_NONPACKAGED_DIRECTORY = 2023, B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY, B_SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY, B_SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY, B_SYSTEM_NONPACKAGED_BIN_DIRECTORY, B_SYSTEM_NONPACKAGED_DATA_DIRECTORY, B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY, B_SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY, B_SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY, B_SYSTEM_NONPACKAGED_LIB_DIRECTORY, B_SYSTEM_NONPACKAGED_HEADERS_DIRECTORY, B_SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY, B_USER_DIRECTORY = 3000, B_USER_CONFIG_DIRECTORY, B_USER_ADDONS_DIRECTORY, B_USER_BOOT_DIRECTORY, B_USER_FONTS_DIRECTORY, B_USER_LIB_DIRECTORY, B_USER_SETTINGS_DIRECTORY, B_USER_DESKBAR_DIRECTORY, B_USER_PRINTERS_DIRECTORY, B_USER_TRANSLATORS_DIRECTORY, B_USER_MEDIA_NODES_DIRECTORY, B_USER_SOUNDS_DIRECTORY, B_USER_DATA_DIRECTORY, B_USER_CACHE_DIRECTORY, B_USER_PACKAGES_DIRECTORY, B_USER_HEADERS_DIRECTORY, B_USER_NONPACKAGED_DIRECTORY, B_USER_NONPACKAGED_ADDONS_DIRECTORY, B_USER_NONPACKAGED_TRANSLATORS_DIRECTORY, B_USER_NONPACKAGED_MEDIA_NODES_DIRECTORY, B_USER_NONPACKAGED_BIN_DIRECTORY, B_USER_NONPACKAGED_DATA_DIRECTORY, B_USER_NONPACKAGED_FONTS_DIRECTORY, B_USER_NONPACKAGED_SOUNDS_DIRECTORY, B_USER_NONPACKAGED_DOCUMENTATION_DIRECTORY, B_USER_NONPACKAGED_LIB_DIRECTORY, B_USER_NONPACKAGED_HEADERS_DIRECTORY, B_USER_NONPACKAGED_DEVELOP_DIRECTORY, B_USER_DEVELOP_DIRECTORY, B_USER_DOCUMENTATION_DIRECTORY, B_USER_SERVERS_DIRECTORY, B_USER_APPS_DIRECTORY, B_USER_BIN_DIRECTORY, B_USER_PREFERENCES_DIRECTORY, B_USER_ETC_DIRECTORY, B_USER_LOG_DIRECTORY, B_USER_SPOOL_DIRECTORY, B_USER_VAR_DIRECTORY, B_APPS_DIRECTORY = 4000, B_PREFERENCES_DIRECTORY, B_UTILITIES_DIRECTORY, B_PACKAGE_LINKS_DIRECTORY, } // kernel/OS.h pub enum topology_level_type { B_TOPOLOGY_UNKNOWN, B_TOPOLOGY_ROOT, B_TOPOLOGY_SMT, B_TOPOLOGY_CORE, B_TOPOLOGY_PACKAGE, } pub enum cpu_platform { B_CPU_UNKNOWN, B_CPU_x86, B_CPU_x86_64, B_CPU_PPC, B_CPU_PPC_64, B_CPU_M68K, B_CPU_ARM, B_CPU_ARM_64, B_CPU_ALPHA, B_CPU_MIPS, B_CPU_SH, B_CPU_SPARC, B_CPU_RISC_V } pub enum cpu_vendor { B_CPU_VENDOR_UNKNOWN, B_CPU_VENDOR_AMD, B_CPU_VENDOR_CYRIX, B_CPU_VENDOR_IDT, B_CPU_VENDOR_INTEL, B_CPU_VENDOR_NATIONAL_SEMICONDUCTOR, B_CPU_VENDOR_RISE, B_CPU_VENDOR_TRANSMETA, B_CPU_VENDOR_VIA, B_CPU_VENDOR_IBM, B_CPU_VENDOR_MOTOROLA, B_CPU_VENDOR_NEC, B_CPU_VENDOR_HYGON, B_CPU_VENDOR_SUN, B_CPU_VENDOR_FUJITSU } } s! { // kernel/OS.h pub struct area_info { pub area: area_id, pub name: [::c_char; B_OS_NAME_LENGTH], pub size: usize, pub lock: u32, pub protection: u32, pub team: team_id, pub ram_size: u32, pub copy_count: u32, pub in_count: u32, pub out_count: u32, pub address: *mut ::c_void } pub struct port_info { pub port: port_id, pub team: team_id, pub name: [::c_char; B_OS_NAME_LENGTH], pub capacity: i32, pub queue_count: i32, pub total_count: i32, } pub struct port_message_info { pub size: ::size_t, pub sender: ::uid_t, pub sender_group: ::gid_t, pub sender_team: ::team_id } pub struct team_info { pub team: team_id, pub thread_count: i32, pub image_count: i32, pub area_count: i32, pub debugger_nub_thread: thread_id, pub debugger_nub_port: port_id, pub argc: i32, pub args: [::c_char; 64], pub uid: ::uid_t, pub gid: ::gid_t } pub struct sem_info { pub sem: sem_id, pub team: team_id, pub name: [::c_char; B_OS_NAME_LENGTH], pub count: i32, pub latest_holder: thread_id } pub struct team_usage_info { pub user_time: bigtime_t, pub kernel_time: bigtime_t } pub struct thread_info { pub thread: thread_id, pub team: team_id, pub name: [::c_char; B_OS_NAME_LENGTH], pub state: thread_state, pub priority: i32, pub sem: sem_id, pub user_time: bigtime_t, pub kernel_time: bigtime_t, pub stack_base: *mut ::c_void, pub stack_end: *mut ::c_void } pub struct cpu_info { pub active_time: bigtime_t, pub enabled: bool, pub current_frequency: u64 } pub struct system_info { pub boot_time: bigtime_t, pub cpu_count: u32, pub max_pages: u64, pub used_pages: u64, pub cached_pages: u64, pub block_cache_pages: u64, pub ignored_pages: u64, pub needed_memory: u64, pub free_memory: u64, pub max_swap_pages: u64, pub free_swap_pages: u64, pub page_faults: u32, pub max_sems: u32, pub used_sems: u32, pub max_ports: u32, pub used_ports: u32, pub max_threads: u32, pub used_threads: u32, pub max_teams: u32, pub used_teams: u32, pub kernel_name: [::c_char; B_FILE_NAME_LENGTH], pub kernel_build_date: [::c_char; B_OS_NAME_LENGTH], pub kernel_build_time: [::c_char; B_OS_NAME_LENGTH], pub kernel_version: i64, pub abi: u32 } pub struct object_wait_info { pub object: i32, pub type_: u16, pub events: u16 } pub struct cpu_topology_root_info { pub platform: cpu_platform, } pub struct cpu_topology_package_info { pub vendor: cpu_vendor, pub cache_line_size: u32, } pub struct cpu_topology_core_info { pub model: u32, pub default_frequency: u64, } // kernel/fs_attr.h pub struct attr_info { pub type_: u32, pub size: ::off_t } // kernel/fs_index.h pub struct index_info { pub type_: u32, pub size: ::off_t, pub modification_time: ::time_t, pub creation_time: ::time_t, pub uid: ::uid_t, pub gid: ::gid_t } //kernel/fs_info.h pub struct fs_info { pub dev: ::dev_t, pub root: ::ino_t, pub flags: u32, pub block_size: ::off_t, pub io_size: ::off_t, pub total_blocks: ::off_t, pub free_blocks: ::off_t, pub total_nodes: ::off_t, pub free_nodes: ::off_t, pub device_name: [::c_char; 128], pub volume_name: [::c_char; B_FILE_NAME_LENGTH], pub fsh_name: [::c_char; B_OS_NAME_LENGTH] } // kernel/image.h pub struct image_info { pub id: image_id, pub image_type: ::c_int, pub sequence: i32, pub init_order: i32, pub init_routine: extern "C" fn(), pub term_routine: extern "C" fn(), pub device: ::dev_t, pub node: ::ino_t, pub name: [::c_char; ::PATH_MAX as usize], pub text: *mut ::c_void, pub data: *mut ::c_void, pub text_size: i32, pub data_size: i32, pub api_version: i32, pub abi: i32 } pub struct __c_anonymous_eax_0 { pub max_eax: u32, pub vendor_id: [::c_char; 12], } pub struct __c_anonymous_eax_1 { pub stepping: u32, pub model: u32, pub family: u32, pub tpe: u32, __reserved_0: u32, pub extended_model: u32, pub extended_family: u32, __reserved_1: u32, pub brand_index: u32, pub clflush: u32, pub logical_cpus: u32, pub apic_id: u32, pub features: u32, pub extended_features: u32, } pub struct __c_anonymous_eax_2 { pub call_num: u8, pub cache_descriptors: [u8; 15], } pub struct __c_anonymous_eax_3 { __reserved: [u32; 2], pub serial_number_high: u32, pub serial_number_low: u32, } pub struct __c_anonymous_regs { pub eax: u32, pub ebx: u32, pub edx: u32, pub ecx: u32, } } s_no_extra_traits! { #[cfg(libc_union)] pub union cpuid_info { pub eax_0: __c_anonymous_eax_0, pub eax_1: __c_anonymous_eax_1, pub eax_2: __c_anonymous_eax_2, pub eax_3: __c_anonymous_eax_3, pub as_chars: [::c_char; 16], pub regs: __c_anonymous_regs, } #[cfg(libc_union)] pub union __c_anonymous_cpu_topology_info_data { pub root: cpu_topology_root_info, pub package: cpu_topology_package_info, pub core: cpu_topology_core_info, } pub struct cpu_topology_node_info { pub id: u32, pub type_: topology_level_type, pub level: u32, #[cfg(libc_union)] pub data: __c_anonymous_cpu_topology_info_data, #[cfg(not(libc_union))] pub data: cpu_topology_core_info, } } cfg_if! { if #[cfg(feature = "extra_traits")] { #[cfg(libc_union)] impl PartialEq for cpuid_info { fn eq(&self, other: &cpuid_info) -> bool { unsafe { self.eax_0 == other.eax_0 || self.eax_1 == other.eax_1 || self.eax_2 == other.eax_2 || self.eax_3 == other.eax_3 || self.as_chars == other.as_chars || self.regs == other.regs } } } #[cfg(libc_union)] impl Eq for cpuid_info {} #[cfg(libc_union)] impl ::fmt::Debug for cpuid_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("cpuid_info") .field("eax_0", &self.eax_0) .field("eax_1", &self.eax_1) .field("eax_2", &self.eax_2) .field("eax_3", &self.eax_3) .field("as_chars", &self.as_chars) .field("regs", &self.regs) .finish() } } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_cpu_topology_info_data { fn eq(&self, other: &__c_anonymous_cpu_topology_info_data) -> bool { unsafe { self.root == other.root || self.package == other.package || self.core == other.core } } } #[cfg(libc_union)] impl Eq for __c_anonymous_cpu_topology_info_data {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_cpu_topology_info_data { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("__c_anonymous_cpu_topology_info_data") .field("root", &self.root) .field("package", &self.package) .field("core", &self.core) .finish() } } } impl PartialEq for cpu_topology_node_info { fn eq(&self, other: &cpu_topology_node_info) -> bool { self.id == other.id && self.type_ == other.type_ && self.level == other.level } } impl Eq for cpu_topology_node_info {} impl ::fmt::Debug for cpu_topology_node_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("cpu_topology_node_info") .field("id", &self.id) .field("type", &self.type_) .field("level", &self.level) .finish() } } } } // kernel/OS.h pub const B_OS_NAME_LENGTH: usize = 32; pub const B_PAGE_SIZE: usize = 4096; pub const B_INFINITE_TIMEOUT: usize = 9223372036854775807; pub const B_RELATIVE_TIMEOUT: u32 = 0x8; pub const B_ABSOLUTE_TIMEOUT: u32 = 0x10; pub const B_TIMEOUT_REAL_TIME_BASE: u32 = 0x40; pub const B_ABSOLUTE_REAL_TIME_TIMEOUT: u32 = B_ABSOLUTE_TIMEOUT | B_TIMEOUT_REAL_TIME_BASE; pub const B_NO_LOCK: u32 = 0; pub const B_LAZY_LOCK: u32 = 1; pub const B_FULL_LOCK: u32 = 2; pub const B_CONTIGUOUS: u32 = 3; pub const B_LOMEM: u32 = 4; pub const B_32_BIT_FULL_LOCK: u32 = 5; pub const B_32_BIT_CONTIGUOUS: u32 = 6; pub const B_ANY_ADDRESS: u32 = 0; pub const B_EXACT_ADDRESS: u32 = 1; pub const B_BASE_ADDRESS: u32 = 2; pub const B_CLONE_ADDRESS: u32 = 3; pub const B_ANY_KERNEL_ADDRESS: u32 = 4; pub const B_RANDOMIZED_ANY_ADDRESS: u32 = 6; pub const B_RANDOMIZED_BASE_ADDRESS: u32 = 7; pub const B_READ_AREA: u32 = 1 << 0; pub const B_WRITE_AREA: u32 = 1 << 1; pub const B_EXECUTE_AREA: u32 = 1 << 2; pub const B_STACK_AREA: u32 = 1 << 3; pub const B_CLONEABLE_AREA: u32 = 1 << 8; pub const B_CAN_INTERRUPT: u32 = 0x01; pub const B_CHECK_PERMISSION: u32 = 0x04; pub const B_KILL_CAN_INTERRUPT: u32 = 0x20; pub const B_DO_NOT_RESCHEDULE: u32 = 0x02; pub const B_RELEASE_ALL: u32 = 0x08; pub const B_RELEASE_IF_WAITING_ONLY: u32 = 0x10; pub const B_CURRENT_TEAM: team_id = 0; pub const B_SYSTEM_TEAM: team_id = 1; pub const B_TEAM_USAGE_SELF: i32 = 0; pub const B_TEAM_USAGE_CHILDREN: i32 = -1; pub const B_IDLE_PRIORITY: i32 = 0; pub const B_LOWEST_ACTIVE_PRIORITY: i32 = 1; pub const B_LOW_PRIORITY: i32 = 5; pub const B_NORMAL_PRIORITY: i32 = 10; pub const B_DISPLAY_PRIORITY: i32 = 15; pub const B_URGENT_DISPLAY_PRIORITY: i32 = 20; pub const B_REAL_TIME_DISPLAY_PRIORITY: i32 = 100; pub const B_URGENT_PRIORITY: i32 = 110; pub const B_REAL_TIME_PRIORITY: i32 = 120; pub const B_SYSTEM_TIMEBASE: i32 = 0; pub const B_FIRST_REAL_TIME_PRIORITY: i32 = B_REAL_TIME_DISPLAY_PRIORITY; pub const B_ONE_SHOT_ABSOLUTE_ALARM: u32 = 1; pub const B_ONE_SHOT_RELATIVE_ALARM: u32 = 2; pub const B_PERIODIC_ALARM: u32 = 3; pub const B_OBJECT_TYPE_FD: u16 = 0; pub const B_OBJECT_TYPE_SEMAPHORE: u16 = 1; pub const B_OBJECT_TYPE_PORT: u16 = 2; pub const B_OBJECT_TYPE_THREAD: u16 = 3; pub const B_EVENT_READ: u16 = 0x0001; pub const B_EVENT_WRITE: u16 = 0x0002; pub const B_EVENT_ERROR: u16 = 0x0004; pub const B_EVENT_PRIORITY_READ: u16 = 0x0008; pub const B_EVENT_PRIORITY_WRITE: u16 = 0x0010; pub const B_EVENT_HIGH_PRIORITY_READ: u16 = 0x0020; pub const B_EVENT_HIGH_PRIORITY_WRITE: u16 = 0x0040; pub const B_EVENT_DISCONNECTED: u16 = 0x0080; pub const B_EVENT_ACQUIRE_SEMAPHORE: u16 = 0x0001; pub const B_EVENT_INVALID: u16 = 0x1000; // kernel/fs_info.h pub const B_FS_IS_READONLY: u32 = 0x00000001; pub const B_FS_IS_REMOVABLE: u32 = 0x00000002; pub const B_FS_IS_PERSISTENT: u32 = 0x00000004; pub const B_FS_IS_SHARED: u32 = 0x00000008; pub const B_FS_HAS_MIME: u32 = 0x00010000; pub const B_FS_HAS_ATTR: u32 = 0x00020000; pub const B_FS_HAS_QUERY: u32 = 0x00040000; pub const B_FS_HAS_SELF_HEALING_LINKS: u32 = 0x00080000; pub const B_FS_HAS_ALIASES: u32 = 0x00100000; pub const B_FS_SUPPORTS_NODE_MONITORING: u32 = 0x00200000; pub const B_FS_SUPPORTS_MONITOR_CHILDREN: u32 = 0x00400000; // kernel/fs_query.h pub const B_LIVE_QUERY: u32 = 0x00000001; pub const B_QUERY_NON_INDEXED: u32 = 0x00000002; // kernel/fs_volume.h pub const B_MOUNT_READ_ONLY: u32 = 1; pub const B_MOUNT_VIRTUAL_DEVICE: u32 = 2; pub const B_FORCE_UNMOUNT: u32 = 1; // kernel/image.h pub const B_FLUSH_DCACHE: u32 = 0x0001; pub const B_FLUSH_ICACHE: u32 = 0x0004; pub const B_INVALIDATE_DCACHE: u32 = 0x0002; pub const B_INVALIDATE_ICACHE: u32 = 0x0008; pub const B_SYMBOL_TYPE_DATA: i32 = 0x1; pub const B_SYMBOL_TYPE_TEXT: i32 = 0x2; pub const B_SYMBOL_TYPE_ANY: i32 = 0x5; // storage/StorageDefs.h pub const B_DEV_NAME_LENGTH: usize = 128; pub const B_FILE_NAME_LENGTH: usize = ::FILENAME_MAX as usize; pub const B_PATH_NAME_LENGTH: usize = ::PATH_MAX as usize; pub const B_ATTR_NAME_LENGTH: usize = B_FILE_NAME_LENGTH - 1; pub const B_MIME_TYPE_LENGTH: usize = B_ATTR_NAME_LENGTH - 15; pub const B_MAX_SYMLINKS: usize = 16; // Haiku open modes in BFile are passed as u32 pub const B_READ_ONLY: u32 = ::O_RDONLY as u32; pub const B_WRITE_ONLY: u32 = ::O_WRONLY as u32; pub const B_READ_WRITE: u32 = ::O_RDWR as u32; pub const B_FAIL_IF_EXISTS: u32 = ::O_EXCL as u32; pub const B_CREATE_FILE: u32 = ::O_CREAT as u32; pub const B_ERASE_FILE: u32 = ::O_TRUNC as u32; pub const B_OPEN_AT_END: u32 = ::O_APPEND as u32; pub const B_FILE_NODE: u32 = 0x01; pub const B_SYMLINK_NODE: u32 = 0x02; pub const B_DIRECTORY_NODE: u32 = 0x04; pub const B_ANY_NODE: u32 = 0x07; // support/Errors.h pub const B_GENERAL_ERROR_BASE: status_t = core::i32::MIN; pub const B_OS_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x1000; pub const B_APP_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x2000; pub const B_INTERFACE_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x3000; pub const B_MEDIA_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x4000; pub const B_TRANSLATION_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x4800; pub const B_MIDI_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x5000; pub const B_STORAGE_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x6000; pub const B_POSIX_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x7000; pub const B_MAIL_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x8000; pub const B_PRINT_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0x9000; pub const B_DEVICE_ERROR_BASE: status_t = B_GENERAL_ERROR_BASE + 0xa000; pub const B_ERRORS_END: status_t = B_GENERAL_ERROR_BASE + 0xffff; // General errors pub const B_NO_MEMORY: status_t = B_GENERAL_ERROR_BASE + 0; pub const B_IO_ERROR: status_t = B_GENERAL_ERROR_BASE + 1; pub const B_PERMISSION_DENIED: status_t = B_GENERAL_ERROR_BASE + 2; pub const B_BAD_INDEX: status_t = B_GENERAL_ERROR_BASE + 3; pub const B_BAD_TYPE: status_t = B_GENERAL_ERROR_BASE + 4; pub const B_BAD_VALUE: status_t = B_GENERAL_ERROR_BASE + 5; pub const B_MISMATCHED_VALUES: status_t = B_GENERAL_ERROR_BASE + 6; pub const B_NAME_NOT_FOUND: status_t = B_GENERAL_ERROR_BASE + 7; pub const B_NAME_IN_USE: status_t = B_GENERAL_ERROR_BASE + 8; pub const B_TIMED_OUT: status_t = B_GENERAL_ERROR_BASE + 9; pub const B_INTERRUPTED: status_t = B_GENERAL_ERROR_BASE + 10; pub const B_WOULD_BLOCK: status_t = B_GENERAL_ERROR_BASE + 11; pub const B_CANCELED: status_t = B_GENERAL_ERROR_BASE + 12; pub const B_NO_INIT: status_t = B_GENERAL_ERROR_BASE + 13; pub const B_NOT_INITIALIZED: status_t = B_GENERAL_ERROR_BASE + 13; pub const B_BUSY: status_t = B_GENERAL_ERROR_BASE + 14; pub const B_NOT_ALLOWED: status_t = B_GENERAL_ERROR_BASE + 15; pub const B_BAD_DATA: status_t = B_GENERAL_ERROR_BASE + 16; pub const B_DONT_DO_THAT: status_t = B_GENERAL_ERROR_BASE + 17; pub const B_ERROR: status_t = -1; pub const B_OK: status_t = 0; pub const B_NO_ERROR: status_t = 0; // Kernel kit errors pub const B_BAD_SEM_ID: status_t = B_OS_ERROR_BASE + 0; pub const B_NO_MORE_SEMS: status_t = B_OS_ERROR_BASE + 1; pub const B_BAD_THREAD_ID: status_t = B_OS_ERROR_BASE + 0x100; pub const B_NO_MORE_THREADS: status_t = B_OS_ERROR_BASE + 0x101; pub const B_BAD_THREAD_STATE: status_t = B_OS_ERROR_BASE + 0x102; pub const B_BAD_TEAM_ID: status_t = B_OS_ERROR_BASE + 0x103; pub const B_NO_MORE_TEAMS: status_t = B_OS_ERROR_BASE + 0x104; pub const B_BAD_PORT_ID: status_t = B_OS_ERROR_BASE + 0x200; pub const B_NO_MORE_PORTS: status_t = B_OS_ERROR_BASE + 0x201; pub const B_BAD_IMAGE_ID: status_t = B_OS_ERROR_BASE + 0x300; pub const B_BAD_ADDRESS: status_t = B_OS_ERROR_BASE + 0x301; pub const B_NOT_AN_EXECUTABLE: status_t = B_OS_ERROR_BASE + 0x302; pub const B_MISSING_LIBRARY: status_t = B_OS_ERROR_BASE + 0x303; pub const B_MISSING_SYMBOL: status_t = B_OS_ERROR_BASE + 0x304; pub const B_UNKNOWN_EXECUTABLE: status_t = B_OS_ERROR_BASE + 0x305; pub const B_LEGACY_EXECUTABLE: status_t = B_OS_ERROR_BASE + 0x306; pub const B_DEBUGGER_ALREADY_INSTALLED: status_t = B_OS_ERROR_BASE + 0x400; // Application kit errors pub const B_BAD_REPLY: status_t = B_APP_ERROR_BASE + 0; pub const B_DUPLICATE_REPLY: status_t = B_APP_ERROR_BASE + 1; pub const B_MESSAGE_TO_SELF: status_t = B_APP_ERROR_BASE + 2; pub const B_BAD_HANDLER: status_t = B_APP_ERROR_BASE + 3; pub const B_ALREADY_RUNNING: status_t = B_APP_ERROR_BASE + 4; pub const B_LAUNCH_FAILED: status_t = B_APP_ERROR_BASE + 5; pub const B_AMBIGUOUS_APP_LAUNCH: status_t = B_APP_ERROR_BASE + 6; pub const B_UNKNOWN_MIME_TYPE: status_t = B_APP_ERROR_BASE + 7; pub const B_BAD_SCRIPT_SYNTAX: status_t = B_APP_ERROR_BASE + 8; pub const B_LAUNCH_FAILED_NO_RESOLVE_LINK: status_t = B_APP_ERROR_BASE + 9; pub const B_LAUNCH_FAILED_EXECUTABLE: status_t = B_APP_ERROR_BASE + 10; pub const B_LAUNCH_FAILED_APP_NOT_FOUND: status_t = B_APP_ERROR_BASE + 11; pub const B_LAUNCH_FAILED_APP_IN_TRASH: status_t = B_APP_ERROR_BASE + 12; pub const B_LAUNCH_FAILED_NO_PREFERRED_APP: status_t = B_APP_ERROR_BASE + 13; pub const B_LAUNCH_FAILED_FILES_APP_NOT_FOUND: status_t = B_APP_ERROR_BASE + 14; pub const B_BAD_MIME_SNIFFER_RULE: status_t = B_APP_ERROR_BASE + 15; pub const B_NOT_A_MESSAGE: status_t = B_APP_ERROR_BASE + 16; pub const B_SHUTDOWN_CANCELLED: status_t = B_APP_ERROR_BASE + 17; pub const B_SHUTTING_DOWN: status_t = B_APP_ERROR_BASE + 18; // Storage kit errors pub const B_FILE_ERROR: status_t = B_STORAGE_ERROR_BASE + 0; pub const B_FILE_EXISTS: status_t = B_STORAGE_ERROR_BASE + 2; pub const B_ENTRY_NOT_FOUND: status_t = B_STORAGE_ERROR_BASE + 3; pub const B_NAME_TOO_LONG: status_t = B_STORAGE_ERROR_BASE + 4; pub const B_NOT_A_DIRECTORY: status_t = B_STORAGE_ERROR_BASE + 5; pub const B_DIRECTORY_NOT_EMPTY: status_t = B_STORAGE_ERROR_BASE + 6; pub const B_DEVICE_FULL: status_t = B_STORAGE_ERROR_BASE + 7; pub const B_READ_ONLY_DEVICE: status_t = B_STORAGE_ERROR_BASE + 8; pub const B_IS_A_DIRECTORY: status_t = B_STORAGE_ERROR_BASE + 9; pub const B_NO_MORE_FDS: status_t = B_STORAGE_ERROR_BASE + 10; pub const B_CROSS_DEVICE_LINK: status_t = B_STORAGE_ERROR_BASE + 11; pub const B_LINK_LIMIT: status_t = B_STORAGE_ERROR_BASE + 12; pub const B_BUSTED_PIPE: status_t = B_STORAGE_ERROR_BASE + 13; pub const B_UNSUPPORTED: status_t = B_STORAGE_ERROR_BASE + 14; pub const B_PARTITION_TOO_SMALL: status_t = B_STORAGE_ERROR_BASE + 15; pub const B_PARTIAL_READ: status_t = B_STORAGE_ERROR_BASE + 16; pub const B_PARTIAL_WRITE: status_t = B_STORAGE_ERROR_BASE + 17; // Mapped posix errors pub const B_BUFFER_OVERFLOW: status_t = ::EOVERFLOW; pub const B_TOO_MANY_ARGS: status_t = ::E2BIG; pub const B_FILE_TOO_LARGE: status_t = ::EFBIG; pub const B_RESULT_NOT_REPRESENTABLE: status_t = ::ERANGE; pub const B_DEVICE_NOT_FOUND: status_t = ::ENODEV; pub const B_NOT_SUPPORTED: status_t = ::EOPNOTSUPP; // Media kit errors pub const B_STREAM_NOT_FOUND: status_t = B_MEDIA_ERROR_BASE + 0; pub const B_SERVER_NOT_FOUND: status_t = B_MEDIA_ERROR_BASE + 1; pub const B_RESOURCE_NOT_FOUND: status_t = B_MEDIA_ERROR_BASE + 2; pub const B_RESOURCE_UNAVAILABLE: status_t = B_MEDIA_ERROR_BASE + 3; pub const B_BAD_SUBSCRIBER: status_t = B_MEDIA_ERROR_BASE + 4; pub const B_SUBSCRIBER_NOT_ENTERED: status_t = B_MEDIA_ERROR_BASE + 5; pub const B_BUFFER_NOT_AVAILABLE: status_t = B_MEDIA_ERROR_BASE + 6; pub const B_LAST_BUFFER_ERROR: status_t = B_MEDIA_ERROR_BASE + 7; pub const B_MEDIA_SYSTEM_FAILURE: status_t = B_MEDIA_ERROR_BASE + 100; pub const B_MEDIA_BAD_NODE: status_t = B_MEDIA_ERROR_BASE + 101; pub const B_MEDIA_NODE_BUSY: status_t = B_MEDIA_ERROR_BASE + 102; pub const B_MEDIA_BAD_FORMAT: status_t = B_MEDIA_ERROR_BASE + 103; pub const B_MEDIA_BAD_BUFFER: status_t = B_MEDIA_ERROR_BASE + 104; pub const B_MEDIA_TOO_MANY_NODES: status_t = B_MEDIA_ERROR_BASE + 105; pub const B_MEDIA_TOO_MANY_BUFFERS: status_t = B_MEDIA_ERROR_BASE + 106; pub const B_MEDIA_NODE_ALREADY_EXISTS: status_t = B_MEDIA_ERROR_BASE + 107; pub const B_MEDIA_BUFFER_ALREADY_EXISTS: status_t = B_MEDIA_ERROR_BASE + 108; pub const B_MEDIA_CANNOT_SEEK: status_t = B_MEDIA_ERROR_BASE + 109; pub const B_MEDIA_CANNOT_CHANGE_RUN_MODE: status_t = B_MEDIA_ERROR_BASE + 110; pub const B_MEDIA_APP_ALREADY_REGISTERED: status_t = B_MEDIA_ERROR_BASE + 111; pub const B_MEDIA_APP_NOT_REGISTERED: status_t = B_MEDIA_ERROR_BASE + 112; pub const B_MEDIA_CANNOT_RECLAIM_BUFFERS: status_t = B_MEDIA_ERROR_BASE + 113; pub const B_MEDIA_BUFFERS_NOT_RECLAIMED: status_t = B_MEDIA_ERROR_BASE + 114; pub const B_MEDIA_TIME_SOURCE_STOPPED: status_t = B_MEDIA_ERROR_BASE + 115; pub const B_MEDIA_TIME_SOURCE_BUSY: status_t = B_MEDIA_ERROR_BASE + 116; pub const B_MEDIA_BAD_SOURCE: status_t = B_MEDIA_ERROR_BASE + 117; pub const B_MEDIA_BAD_DESTINATION: status_t = B_MEDIA_ERROR_BASE + 118; pub const B_MEDIA_ALREADY_CONNECTED: status_t = B_MEDIA_ERROR_BASE + 119; pub const B_MEDIA_NOT_CONNECTED: status_t = B_MEDIA_ERROR_BASE + 120; pub const B_MEDIA_BAD_CLIP_FORMAT: status_t = B_MEDIA_ERROR_BASE + 121; pub const B_MEDIA_ADDON_FAILED: status_t = B_MEDIA_ERROR_BASE + 122; pub const B_MEDIA_ADDON_DISABLED: status_t = B_MEDIA_ERROR_BASE + 123; pub const B_MEDIA_CHANGE_IN_PROGRESS: status_t = B_MEDIA_ERROR_BASE + 124; pub const B_MEDIA_STALE_CHANGE_COUNT: status_t = B_MEDIA_ERROR_BASE + 125; pub const B_MEDIA_ADDON_RESTRICTED: status_t = B_MEDIA_ERROR_BASE + 126; pub const B_MEDIA_NO_HANDLER: status_t = B_MEDIA_ERROR_BASE + 127; pub const B_MEDIA_DUPLICATE_FORMAT: status_t = B_MEDIA_ERROR_BASE + 128; pub const B_MEDIA_REALTIME_DISABLED: status_t = B_MEDIA_ERROR_BASE + 129; pub const B_MEDIA_REALTIME_UNAVAILABLE: status_t = B_MEDIA_ERROR_BASE + 130; // Mail kit errors pub const B_MAIL_NO_DAEMON: status_t = B_MAIL_ERROR_BASE + 0; pub const B_MAIL_UNKNOWN_USER: status_t = B_MAIL_ERROR_BASE + 1; pub const B_MAIL_WRONG_PASSWORD: status_t = B_MAIL_ERROR_BASE + 2; pub const B_MAIL_UNKNOWN_HOST: status_t = B_MAIL_ERROR_BASE + 3; pub const B_MAIL_ACCESS_ERROR: status_t = B_MAIL_ERROR_BASE + 4; pub const B_MAIL_UNKNOWN_FIELD: status_t = B_MAIL_ERROR_BASE + 5; pub const B_MAIL_NO_RECIPIENT: status_t = B_MAIL_ERROR_BASE + 6; pub const B_MAIL_INVALID_MAIL: status_t = B_MAIL_ERROR_BASE + 7; // Print kit errors pub const B_NO_PRINT_SERVER: status_t = B_PRINT_ERROR_BASE + 0; // Device kit errors pub const B_DEV_INVALID_IOCTL: status_t = B_DEVICE_ERROR_BASE + 0; pub const B_DEV_NO_MEMORY: status_t = B_DEVICE_ERROR_BASE + 1; pub const B_DEV_BAD_DRIVE_NUM: status_t = B_DEVICE_ERROR_BASE + 2; pub const B_DEV_NO_MEDIA: status_t = B_DEVICE_ERROR_BASE + 3; pub const B_DEV_UNREADABLE: status_t = B_DEVICE_ERROR_BASE + 4; pub const B_DEV_FORMAT_ERROR: status_t = B_DEVICE_ERROR_BASE + 5; pub const B_DEV_TIMEOUT: status_t = B_DEVICE_ERROR_BASE + 6; pub const B_DEV_RECALIBRATE_ERROR: status_t = B_DEVICE_ERROR_BASE + 7; pub const B_DEV_SEEK_ERROR: status_t = B_DEVICE_ERROR_BASE + 8; pub const B_DEV_ID_ERROR: status_t = B_DEVICE_ERROR_BASE + 9; pub const B_DEV_READ_ERROR: status_t = B_DEVICE_ERROR_BASE + 10; pub const B_DEV_WRITE_ERROR: status_t = B_DEVICE_ERROR_BASE + 11; pub const B_DEV_NOT_READY: status_t = B_DEVICE_ERROR_BASE + 12; pub const B_DEV_MEDIA_CHANGED: status_t = B_DEVICE_ERROR_BASE + 13; pub const B_DEV_MEDIA_CHANGE_REQUESTED: status_t = B_DEVICE_ERROR_BASE + 14; pub const B_DEV_RESOURCE_CONFLICT: status_t = B_DEVICE_ERROR_BASE + 15; pub const B_DEV_CONFIGURATION_ERROR: status_t = B_DEVICE_ERROR_BASE + 16; pub const B_DEV_DISABLED_BY_USER: status_t = B_DEVICE_ERROR_BASE + 17; pub const B_DEV_DOOR_OPEN: status_t = B_DEVICE_ERROR_BASE + 18; pub const B_DEV_INVALID_PIPE: status_t = B_DEVICE_ERROR_BASE + 19; pub const B_DEV_CRC_ERROR: status_t = B_DEVICE_ERROR_BASE + 20; pub const B_DEV_STALLED: status_t = B_DEVICE_ERROR_BASE + 21; pub const B_DEV_BAD_PID: status_t = B_DEVICE_ERROR_BASE + 22; pub const B_DEV_UNEXPECTED_PID: status_t = B_DEVICE_ERROR_BASE + 23; pub const B_DEV_DATA_OVERRUN: status_t = B_DEVICE_ERROR_BASE + 24; pub const B_DEV_DATA_UNDERRUN: status_t = B_DEVICE_ERROR_BASE + 25; pub const B_DEV_FIFO_OVERRUN: status_t = B_DEVICE_ERROR_BASE + 26; pub const B_DEV_FIFO_UNDERRUN: status_t = B_DEVICE_ERROR_BASE + 27; pub const B_DEV_PENDING: status_t = B_DEVICE_ERROR_BASE + 28; pub const B_DEV_MULTIPLE_ERRORS: status_t = B_DEVICE_ERROR_BASE + 29; pub const B_DEV_TOO_LATE: status_t = B_DEVICE_ERROR_BASE + 30; // translation kit errors pub const B_TRANSLATION_BASE_ERROR: status_t = B_TRANSLATION_ERROR_BASE + 0; pub const B_NO_TRANSLATOR: status_t = B_TRANSLATION_ERROR_BASE + 1; pub const B_ILLEGAL_DATA: status_t = B_TRANSLATION_ERROR_BASE + 2; // support/TypeConstants.h pub const B_AFFINE_TRANSFORM_TYPE: u32 = haiku_constant!('A', 'M', 'T', 'X'); pub const B_ALIGNMENT_TYPE: u32 = haiku_constant!('A', 'L', 'G', 'N'); pub const B_ANY_TYPE: u32 = haiku_constant!('A', 'N', 'Y', 'T'); pub const B_ATOM_TYPE: u32 = haiku_constant!('A', 'T', 'O', 'M'); pub const B_ATOMREF_TYPE: u32 = haiku_constant!('A', 'T', 'M', 'R'); pub const B_BOOL_TYPE: u32 = haiku_constant!('B', 'O', 'O', 'L'); pub const B_CHAR_TYPE: u32 = haiku_constant!('C', 'H', 'A', 'R'); pub const B_COLOR_8_BIT_TYPE: u32 = haiku_constant!('C', 'L', 'R', 'B'); pub const B_DOUBLE_TYPE: u32 = haiku_constant!('D', 'B', 'L', 'E'); pub const B_FLOAT_TYPE: u32 = haiku_constant!('F', 'L', 'O', 'T'); pub const B_GRAYSCALE_8_BIT_TYPE: u32 = haiku_constant!('G', 'R', 'Y', 'B'); pub const B_INT16_TYPE: u32 = haiku_constant!('S', 'H', 'R', 'T'); pub const B_INT32_TYPE: u32 = haiku_constant!('L', 'O', 'N', 'G'); pub const B_INT64_TYPE: u32 = haiku_constant!('L', 'L', 'N', 'G'); pub const B_INT8_TYPE: u32 = haiku_constant!('B', 'Y', 'T', 'E'); pub const B_LARGE_ICON_TYPE: u32 = haiku_constant!('I', 'C', 'O', 'N'); pub const B_MEDIA_PARAMETER_GROUP_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'G'); pub const B_MEDIA_PARAMETER_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'T'); pub const B_MEDIA_PARAMETER_WEB_TYPE: u32 = haiku_constant!('B', 'M', 'C', 'W'); pub const B_MESSAGE_TYPE: u32 = haiku_constant!('M', 'S', 'G', 'G'); pub const B_MESSENGER_TYPE: u32 = haiku_constant!('M', 'S', 'N', 'G'); pub const B_MIME_TYPE: u32 = haiku_constant!('M', 'I', 'M', 'E'); pub const B_MINI_ICON_TYPE: u32 = haiku_constant!('M', 'I', 'C', 'N'); pub const B_MONOCHROME_1_BIT_TYPE: u32 = haiku_constant!('M', 'N', 'O', 'B'); pub const B_OBJECT_TYPE: u32 = haiku_constant!('O', 'P', 'T', 'R'); pub const B_OFF_T_TYPE: u32 = haiku_constant!('O', 'F', 'F', 'T'); pub const B_PATTERN_TYPE: u32 = haiku_constant!('P', 'A', 'T', 'N'); pub const B_POINTER_TYPE: u32 = haiku_constant!('P', 'N', 'T', 'R'); pub const B_POINT_TYPE: u32 = haiku_constant!('B', 'P', 'N', 'T'); pub const B_PROPERTY_INFO_TYPE: u32 = haiku_constant!('S', 'C', 'T', 'D'); pub const B_RAW_TYPE: u32 = haiku_constant!('R', 'A', 'W', 'T'); pub const B_RECT_TYPE: u32 = haiku_constant!('R', 'E', 'C', 'T'); pub const B_REF_TYPE: u32 = haiku_constant!('R', 'R', 'E', 'F'); pub const B_RGB_32_BIT_TYPE: u32 = haiku_constant!('R', 'G', 'B', 'B'); pub const B_RGB_COLOR_TYPE: u32 = haiku_constant!('R', 'G', 'B', 'C'); pub const B_SIZE_TYPE: u32 = haiku_constant!('S', 'I', 'Z', 'E'); pub const B_SIZE_T_TYPE: u32 = haiku_constant!('S', 'I', 'Z', 'T'); pub const B_SSIZE_T_TYPE: u32 = haiku_constant!('S', 'S', 'Z', 'T'); pub const B_STRING_TYPE: u32 = haiku_constant!('C', 'S', 'T', 'R'); pub const B_STRING_LIST_TYPE: u32 = haiku_constant!('S', 'T', 'R', 'L'); pub const B_TIME_TYPE: u32 = haiku_constant!('T', 'I', 'M', 'E'); pub const B_UINT16_TYPE: u32 = haiku_constant!('U', 'S', 'H', 'T'); pub const B_UINT32_TYPE: u32 = haiku_constant!('U', 'L', 'N', 'G'); pub const B_UINT64_TYPE: u32 = haiku_constant!('U', 'L', 'L', 'G'); pub const B_UINT8_TYPE: u32 = haiku_constant!('U', 'B', 'Y', 'T'); pub const B_VECTOR_ICON_TYPE: u32 = haiku_constant!('V', 'I', 'C', 'N'); pub const B_XATTR_TYPE: u32 = haiku_constant!('X', 'A', 'T', 'R'); pub const B_NETWORK_ADDRESS_TYPE: u32 = haiku_constant!('N', 'W', 'A', 'D'); pub const B_MIME_STRING_TYPE: u32 = haiku_constant!('M', 'I', 'M', 'S'); pub const B_ASCII_TYPE: u32 = haiku_constant!('T', 'E', 'X', 'T'); extern "C" { // kernel/OS.h pub fn create_area( name: *const ::c_char, startAddress: *mut *mut ::c_void, addressSpec: u32, size: usize, lock: u32, protection: u32, ) -> area_id; pub fn clone_area( name: *const ::c_char, destAddress: *mut *mut ::c_void, addressSpec: u32, protection: u32, source: area_id, ) -> area_id; pub fn find_area(name: *const ::c_char) -> area_id; pub fn area_for(address: *mut ::c_void) -> area_id; pub fn delete_area(id: area_id) -> status_t; pub fn resize_area(id: area_id, newSize: usize) -> status_t; pub fn set_area_protection(id: area_id, newProtection: u32) -> status_t; pub fn _get_area_info(id: area_id, areaInfo: *mut area_info, size: usize) -> status_t; pub fn _get_next_area_info( team: team_id, cookie: *mut isize, areaInfo: *mut area_info, size: usize, ) -> status_t; pub fn create_port(capacity: i32, name: *const ::c_char) -> port_id; pub fn find_port(name: *const ::c_char) -> port_id; pub fn read_port( port: port_id, code: *mut i32, buffer: *mut ::c_void, bufferSize: ::size_t, ) -> ::ssize_t; pub fn read_port_etc( port: port_id, code: *mut i32, buffer: *mut ::c_void, bufferSize: ::size_t, flags: u32, timeout: bigtime_t, ) -> ::ssize_t; pub fn write_port( port: port_id, code: i32, buffer: *const ::c_void, bufferSize: ::size_t, ) -> status_t; pub fn write_port_etc( port: port_id, code: i32, buffer: *const ::c_void, bufferSize: ::size_t, flags: u32, timeout: bigtime_t, ) -> status_t; pub fn close_port(port: port_id) -> status_t; pub fn delete_port(port: port_id) -> status_t; pub fn port_buffer_size(port: port_id) -> ::ssize_t; pub fn port_buffer_size_etc(port: port_id, flags: u32, timeout: bigtime_t) -> ::ssize_t; pub fn port_count(port: port_id) -> ::ssize_t; pub fn set_port_owner(port: port_id, team: team_id) -> status_t; pub fn _get_port_info(port: port_id, buf: *mut port_info, portInfoSize: ::size_t) -> status_t; pub fn _get_next_port_info( port: port_id, cookie: *mut i32, portInfo: *mut port_info, portInfoSize: ::size_t, ) -> status_t; pub fn _get_port_message_info_etc( port: port_id, info: *mut port_message_info, infoSize: ::size_t, flags: u32, timeout: bigtime_t, ) -> status_t; pub fn create_sem(count: i32, name: *const ::c_char) -> sem_id; pub fn delete_sem(id: sem_id) -> status_t; pub fn acquire_sem(id: sem_id) -> status_t; pub fn acquire_sem_etc(id: sem_id, count: i32, flags: u32, timeout: bigtime_t) -> status_t; pub fn release_sem(id: sem_id) -> status_t; pub fn release_sem_etc(id: sem_id, count: i32, flags: u32) -> status_t; pub fn switch_sem(semToBeReleased: sem_id, id: sem_id) -> status_t; pub fn switch_sem_etc( semToBeReleased: sem_id, id: sem_id, count: i32, flags: u32, timeout: bigtime_t, ) -> status_t; pub fn get_sem_count(id: sem_id, threadCount: *mut i32) -> status_t; pub fn set_sem_owner(id: sem_id, team: team_id) -> status_t; pub fn _get_sem_info(id: sem_id, info: *mut sem_info, infoSize: ::size_t) -> status_t; pub fn _get_next_sem_info( team: team_id, cookie: *mut i32, info: *mut sem_info, infoSize: ::size_t, ) -> status_t; pub fn kill_team(team: team_id) -> status_t; pub fn _get_team_info(team: team_id, info: *mut team_info, size: ::size_t) -> status_t; pub fn _get_next_team_info(cookie: *mut i32, info: *mut team_info, size: ::size_t) -> status_t; pub fn spawn_thread( func: thread_func, name: *const ::c_char, priority: i32, data: *mut ::c_void, ) -> thread_id; pub fn kill_thread(thread: thread_id) -> status_t; pub fn resume_thread(thread: thread_id) -> status_t; pub fn suspend_thread(thread: thread_id) -> status_t; pub fn rename_thread(thread: thread_id, newName: *const ::c_char) -> status_t; pub fn set_thread_priority(thread: thread_id, newPriority: i32) -> status_t; pub fn suggest_thread_priority( what: u32, period: i32, jitter: ::bigtime_t, length: ::bigtime_t, ) -> i32; pub fn estimate_max_scheduling_latency(th: ::thread_id) -> ::bigtime_t; pub fn exit_thread(status: status_t); pub fn wait_for_thread(thread: thread_id, returnValue: *mut status_t) -> status_t; pub fn on_exit_thread(callback: extern "C" fn(*mut ::c_void), data: *mut ::c_void) -> status_t; pub fn find_thread(name: *const ::c_char) -> thread_id; pub fn get_scheduler_mode() -> i32; pub fn set_scheduler_mode(mode: i32) -> status_t; pub fn send_data( thread: thread_id, code: i32, buffer: *const ::c_void, bufferSize: ::size_t, ) -> status_t; pub fn receive_data(sender: *mut thread_id, buffer: *mut ::c_void, bufferSize: ::size_t) -> i32; pub fn has_data(thread: thread_id) -> bool; pub fn snooze(amount: bigtime_t) -> status_t; pub fn snooze_etc(amount: bigtime_t, timeBase: ::c_int, flags: u32) -> status_t; pub fn snooze_until(time: bigtime_t, timeBase: ::c_int) -> status_t; pub fn _get_thread_info(id: thread_id, info: *mut thread_info, size: ::size_t) -> status_t; pub fn _get_next_thread_info( team: team_id, cookie: *mut i32, info: *mut thread_info, size: ::size_t, ) -> status_t; pub fn get_pthread_thread_id(thread: ::pthread_t) -> thread_id; pub fn _get_team_usage_info( team: team_id, who: i32, info: *mut team_usage_info, size: ::size_t, ) -> status_t; pub fn real_time_clock() -> ::c_ulong; pub fn set_real_time_clock(secsSinceJan1st1970: ::c_ulong); pub fn real_time_clock_usecs() -> bigtime_t; pub fn system_time() -> bigtime_t; pub fn system_time_nsecs() -> nanotime_t; // set_timezone() is deprecated and a no-op pub fn set_alarm(when: bigtime_t, flags: u32) -> bigtime_t; pub fn debugger(message: *const ::c_char); pub fn disable_debugger(state: ::c_int) -> ::c_int; pub fn get_system_info(info: *mut system_info) -> status_t; pub fn _get_cpu_info_etc( firstCPU: u32, cpuCount: u32, info: *mut cpu_info, size: ::size_t, ) -> status_t; pub fn get_cpu_topology_info( topologyInfos: *mut cpu_topology_node_info, topologyInfoCount: *mut u32, ) -> status_t; pub fn is_computer_on() -> i32; pub fn is_computer_on_fire() -> ::c_double; pub fn send_signal(threadID: thread_id, signal: ::c_uint) -> ::c_int; pub fn set_signal_stack(base: *mut ::c_void, size: ::size_t); pub fn wait_for_objects(infos: *mut object_wait_info, numInfos: ::c_int) -> ::ssize_t; pub fn wait_for_objects_etc( infos: *mut object_wait_info, numInfos: ::c_int, flags: u32, timeout: bigtime_t, ) -> ::ssize_t; // kernel/fs_attr.h pub fn fs_read_attr( fd: ::c_int, attribute: *const ::c_char, type_: u32, pos: ::off_t, buffer: *mut ::c_void, readBytes: ::size_t, ) -> ::ssize_t; pub fn fs_write_attr( fd: ::c_int, attribute: *const ::c_char, type_: u32, pos: ::off_t, buffer: *const ::c_void, writeBytes: ::size_t, ) -> ::ssize_t; pub fn fs_remove_attr(fd: ::c_int, attribute: *const ::c_char) -> ::c_int; pub fn fs_stat_attr( fd: ::c_int, attribute: *const ::c_char, attrInfo: *mut attr_info, ) -> ::c_int; pub fn fs_open_attr( path: *const ::c_char, attribute: *const ::c_char, type_: u32, openMode: ::c_int, ) -> ::c_int; pub fn fs_fopen_attr( fd: ::c_int, attribute: *const ::c_char, type_: u32, openMode: ::c_int, ) -> ::c_int; pub fn fs_close_attr(fd: ::c_int) -> ::c_int; pub fn fs_open_attr_dir(path: *const ::c_char) -> *mut ::DIR; pub fn fs_lopen_attr_dir(path: *const ::c_char) -> *mut ::DIR; pub fn fs_fopen_attr_dir(fd: ::c_int) -> *mut ::DIR; pub fn fs_close_attr_dir(dir: *mut ::DIR) -> ::c_int; pub fn fs_read_attr_dir(dir: *mut ::DIR) -> *mut ::dirent; pub fn fs_rewind_attr_dir(dir: *mut ::DIR); // kernel/fs_image.h pub fn fs_create_index( device: ::dev_t, name: *const ::c_char, type_: u32, flags: u32, ) -> ::c_int; pub fn fs_remove_index(device: ::dev_t, name: *const ::c_char) -> ::c_int; pub fn fs_stat_index( device: ::dev_t, name: *const ::c_char, indexInfo: *mut index_info, ) -> ::c_int; pub fn fs_open_index_dir(device: ::dev_t) -> *mut ::DIR; pub fn fs_close_index_dir(indexDirectory: *mut ::DIR) -> ::c_int; pub fn fs_read_index_dir(indexDirectory: *mut ::DIR) -> *mut ::dirent; pub fn fs_rewind_index_dir(indexDirectory: *mut ::DIR); // kernel/fs_info.h pub fn dev_for_path(path: *const ::c_char) -> ::dev_t; pub fn next_dev(pos: *mut i32) -> ::dev_t; pub fn fs_stat_dev(dev: ::dev_t, info: *mut fs_info) -> ::c_int; // kernel/fs_query.h pub fn fs_open_query(device: ::dev_t, query: *const ::c_char, flags: u32) -> *mut ::DIR; pub fn fs_open_live_query( device: ::dev_t, query: *const ::c_char, flags: u32, port: port_id, token: i32, ) -> *mut ::DIR; pub fn fs_close_query(d: *mut ::DIR) -> ::c_int; pub fn fs_read_query(d: *mut ::DIR) -> *mut ::dirent; pub fn get_path_for_dirent(dent: *mut ::dirent, buf: *mut ::c_char, len: ::size_t) -> status_t; // kernel/fs_volume.h pub fn fs_mount_volume( where_: *const ::c_char, device: *const ::c_char, filesystem: *const ::c_char, flags: u32, parameters: *const ::c_char, ) -> ::dev_t; pub fn fs_unmount_volume(path: *const ::c_char, flags: u32) -> status_t; // kernel/image.h pub fn load_image( argc: i32, argv: *mut *const ::c_char, environ: *mut *const ::c_char, ) -> thread_id; pub fn load_add_on(path: *const ::c_char) -> image_id; pub fn unload_add_on(image: image_id) -> status_t; pub fn get_image_symbol( image: image_id, name: *const ::c_char, symbolType: i32, symbolLocation: *mut *mut ::c_void, ) -> status_t; pub fn get_nth_image_symbol( image: image_id, n: i32, nameBuffer: *mut ::c_char, nameLength: *mut i32, symbolType: *mut i32, symbolLocation: *mut *mut ::c_void, ) -> status_t; pub fn clear_caches(address: *mut ::c_void, length: ::size_t, flags: u32); pub fn _get_image_info(image: image_id, info: *mut image_info, size: ::size_t) -> status_t; pub fn _get_next_image_info( team: team_id, cookie: *mut i32, info: *mut image_info, size: ::size_t, ) -> status_t; pub fn find_path( codePointer: *const ::c_void, baseDirectory: path_base_directory, subPath: *const ::c_char, pathBuffer: *mut ::c_char, bufferSize: usize, ) -> status_t; pub fn find_path_etc( codePointer: *const ::c_void, dependency: *const ::c_char, architecture: *const ::c_char, baseDirectory: path_base_directory, subPath: *const ::c_char, flags: u32, pathBuffer: *mut ::c_char, bufferSize: ::size_t, ) -> status_t; pub fn find_path_for_path( path: *const ::c_char, baseDirectory: path_base_directory, subPath: *const ::c_char, pathBuffer: *mut ::c_char, bufferSize: ::size_t, ) -> status_t; pub fn find_path_for_path_etc( path: *const ::c_char, dependency: *const ::c_char, architectur: *const ::c_char, baseDirectory: path_base_directory, subPath: *const ::c_char, flags: u32, pathBuffer: *mut ::c_char, bufferSize: ::size_t, ) -> status_t; pub fn find_paths( baseDirectory: path_base_directory, subPath: *const ::c_char, _paths: *mut *mut *mut ::c_char, pathCount: *mut ::size_t, ) -> status_t; pub fn find_paths_etc( architecture: *const ::c_char, baseDirectory: path_base_directory, subPath: *const ::c_char, flags: u32, _paths: *mut *mut *mut ::c_char, pathCount: *mut ::size_t, ) -> status_t; pub fn find_directory( which: directory_which, volume: ::dev_t, createIt: bool, pathString: *mut ::c_char, length: i32, ) -> status_t; } cfg_if! { if #[cfg(libc_union)] { extern "C" { pub fn get_cpuid(info: *mut cpuid_info, eaxRegister: u32, cpuNum: u32) -> status_t; } } } // The following functions are defined as macros in C/C++ #[inline] pub unsafe fn get_cpu_info(firstCPU: u32, cpuCount: u32, info: *mut cpu_info) -> status_t { _get_cpu_info_etc( firstCPU, cpuCount, info, core::mem::size_of::() as ::size_t, ) } #[inline] pub unsafe fn get_area_info(id: area_id, info: *mut area_info) -> status_t { _get_area_info(id, info, core::mem::size_of::() as usize) } #[inline] pub unsafe fn get_next_area_info( team: team_id, cookie: *mut isize, info: *mut area_info, ) -> status_t { _get_next_area_info( team, cookie, info, core::mem::size_of::() as usize, ) } #[inline] pub unsafe fn get_port_info(port: port_id, buf: *mut port_info) -> status_t { _get_port_info(port, buf, core::mem::size_of::() as ::size_t) } #[inline] pub unsafe fn get_next_port_info( port: port_id, cookie: *mut i32, portInfo: *mut port_info, ) -> status_t { _get_next_port_info( port, cookie, portInfo, core::mem::size_of::() as ::size_t, ) } #[inline] pub unsafe fn get_port_message_info_etc( port: port_id, info: *mut port_message_info, flags: u32, timeout: bigtime_t, ) -> status_t { _get_port_message_info_etc( port, info, core::mem::size_of::() as ::size_t, flags, timeout, ) } #[inline] pub unsafe fn get_sem_info(id: sem_id, info: *mut sem_info) -> status_t { _get_sem_info(id, info, core::mem::size_of::() as ::size_t) } #[inline] pub unsafe fn get_next_sem_info(team: team_id, cookie: *mut i32, info: *mut sem_info) -> status_t { _get_next_sem_info( team, cookie, info, core::mem::size_of::() as ::size_t, ) } #[inline] pub unsafe fn get_team_info(team: team_id, info: *mut team_info) -> status_t { _get_team_info(team, info, core::mem::size_of::() as ::size_t) } #[inline] pub unsafe fn get_next_team_info(cookie: *mut i32, info: *mut team_info) -> status_t { _get_next_team_info(cookie, info, core::mem::size_of::() as ::size_t) } #[inline] pub unsafe fn get_team_usage_info(team: team_id, who: i32, info: *mut team_usage_info) -> status_t { _get_team_usage_info( team, who, info, core::mem::size_of::() as ::size_t, ) } #[inline] pub unsafe fn get_thread_info(id: thread_id, info: *mut thread_info) -> status_t { _get_thread_info(id, info, core::mem::size_of::() as ::size_t) } #[inline] pub unsafe fn get_next_thread_info( team: team_id, cookie: *mut i32, info: *mut thread_info, ) -> status_t { _get_next_thread_info( team, cookie, info, core::mem::size_of::() as ::size_t, ) } // kernel/image.h #[inline] pub unsafe fn get_image_info(image: image_id, info: *mut image_info) -> status_t { _get_image_info(image, info, core::mem::size_of::() as ::size_t) } #[inline] pub unsafe fn get_next_image_info( team: team_id, cookie: *mut i32, info: *mut image_info, ) -> status_t { _get_next_image_info( team, cookie, info, core::mem::size_of::() as ::size_t, ) } libc/src/unix/redox/0000775000175000017500000000000014661133735015347 5ustar jamespagejamespagelibc/src/unix/redox/mod.rs0000644000175000017500000013471714661133735016507 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; cfg_if! { if #[cfg(target_pointer_width = "32")] { pub type c_long = i32; pub type c_ulong = u32; } } cfg_if! { if #[cfg(target_pointer_width = "64")] { pub type c_long = i64; pub type c_ulong = u64; } } pub type blkcnt_t = ::c_ulong; pub type blksize_t = ::c_long; pub type clock_t = ::c_long; pub type clockid_t = ::c_int; pub type dev_t = ::c_long; pub type fsblkcnt_t = ::c_ulong; pub type fsfilcnt_t = ::c_ulong; pub type ino_t = ::c_ulong; pub type mode_t = ::c_int; pub type nfds_t = ::c_ulong; pub type nlink_t = ::c_ulong; pub type off_t = ::c_longlong; pub type pthread_t = *mut ::c_void; // Must be usize due to library/std/sys_common/thread_local.rs, // should technically be *mut ::c_void pub type pthread_key_t = usize; pub type rlim_t = ::c_ulonglong; pub type sa_family_t = u16; pub type sem_t = *mut ::c_void; pub type sigset_t = ::c_ulonglong; pub type socklen_t = u32; pub type speed_t = u32; pub type suseconds_t = ::c_int; pub type tcflag_t = u32; pub type time_t = ::c_longlong; pub type id_t = ::c_uint; pub type pid_t = usize; pub type uid_t = u32; pub type gid_t = u32; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } s_no_extra_traits! { #[repr(C)] pub struct utsname { pub sysname: [::c_char; UTSLENGTH], pub nodename: [::c_char; UTSLENGTH], pub release: [::c_char; UTSLENGTH], pub version: [::c_char; UTSLENGTH], pub machine: [::c_char; UTSLENGTH], pub domainname: [::c_char; UTSLENGTH], } pub struct dirent { pub d_ino: ::ino_t, pub d_off: ::off_t, pub d_reclen: ::c_ushort, pub d_type: ::c_uchar, pub d_name: [::c_char; 256], } pub struct sockaddr_un { pub sun_family: ::sa_family_t, pub sun_path: [::c_char; 108] } pub struct sockaddr_storage { pub ss_family: ::sa_family_t, __ss_padding: [ u8; 128 - ::core::mem::size_of::() - ::core::mem::size_of::() ], __ss_align: ::c_ulong, } } s! { pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: ::size_t, pub ai_canonname: *mut ::c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut ::addrinfo, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct epoll_event { pub events: u32, pub u64: u64, pub _pad: u64, } pub struct fd_set { fds_bits: [::c_ulong; ::FD_SETSIZE / ULONG_SIZE], } pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: ::in_addr, pub imr_interface: ::in_addr, } pub struct lconv { pub currency_symbol: *const ::c_char, pub decimal_point: *const ::c_char, pub frac_digits: ::c_char, pub grouping: *const ::c_char, pub int_curr_symbol: *const ::c_char, pub int_frac_digits: ::c_char, pub mon_decimal_point: *const ::c_char, pub mon_grouping: *const ::c_char, pub mon_thousands_sep: *const ::c_char, pub negative_sign: *const ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub n_sign_posn: ::c_char, pub positive_sign: *const ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub thousands_sep: *const ::c_char, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_flags: ::c_ulong, pub sa_restorer: ::Option, pub sa_mask: ::sigset_t, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, _pad: [::c_int; 29], _align: [usize; 0], } pub struct sockaddr { pub sa_family: ::sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in { pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [::c_char; 8], } pub struct sockaddr_in6 { pub sin6_family: ::sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, _pad: [::c_char; 24], } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, pub tm_gmtoff: ::c_long, pub tm_zone: *const ::c_char, } pub struct ucred { pub pid: pid_t, pub uid: uid_t, pub gid: gid_t, } #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] pub struct pthread_attr_t { bytes: [u8; _PTHREAD_ATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_barrier_t { bytes: [u8; _PTHREAD_BARRIER_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_barrierattr_t { bytes: [u8; _PTHREAD_BARRIERATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_mutex_t { bytes: [u8; _PTHREAD_MUTEX_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_rwlock_t { bytes: [u8; _PTHREAD_RWLOCK_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_mutexattr_t { bytes: [u8; _PTHREAD_MUTEXATTR_SIZE], } #[repr(C)] #[repr(align(1))] pub struct pthread_rwlockattr_t { bytes: [u8; _PTHREAD_RWLOCKATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_cond_t { bytes: [u8; _PTHREAD_COND_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_condattr_t { bytes: [u8; _PTHREAD_CONDATTR_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_once_t { bytes: [u8; _PTHREAD_ONCE_SIZE], } #[repr(C)] #[repr(align(4))] pub struct pthread_spinlock_t { bytes: [u8; _PTHREAD_SPINLOCK_SIZE], } } const _PTHREAD_ATTR_SIZE: usize = 32; const _PTHREAD_RWLOCKATTR_SIZE: usize = 1; const _PTHREAD_RWLOCK_SIZE: usize = 4; const _PTHREAD_BARRIER_SIZE: usize = 24; const _PTHREAD_BARRIERATTR_SIZE: usize = 4; const _PTHREAD_CONDATTR_SIZE: usize = 8; const _PTHREAD_COND_SIZE: usize = 8; const _PTHREAD_MUTEX_SIZE: usize = 12; const _PTHREAD_MUTEXATTR_SIZE: usize = 20; const _PTHREAD_ONCE_SIZE: usize = 4; const _PTHREAD_SPINLOCK_SIZE: usize = 4; pub const UTSLENGTH: usize = 65; // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { const ULONG_SIZE: usize = 32; } else if #[cfg(target_pointer_width = "64")] { const ULONG_SIZE: usize = 64; } else { // Unknown target_pointer_width } } // limits.h pub const PATH_MAX: ::c_int = 4096; // fcntl.h pub const F_GETLK: ::c_int = 5; pub const F_SETLK: ::c_int = 6; pub const F_SETLKW: ::c_int = 7; pub const F_ULOCK: ::c_int = 0; pub const F_LOCK: ::c_int = 1; pub const F_TLOCK: ::c_int = 2; pub const F_TEST: ::c_int = 3; // FIXME: relibc { pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; // } // dlfcn.h pub const RTLD_LAZY: ::c_int = 0x0001; pub const RTLD_NOW: ::c_int = 0x0002; pub const RTLD_GLOBAL: ::c_int = 0x0100; pub const RTLD_LOCAL: ::c_int = 0x0000; // errno.h pub const EPERM: ::c_int = 1; /* Operation not permitted */ pub const ENOENT: ::c_int = 2; /* No such file or directory */ pub const ESRCH: ::c_int = 3; /* No such process */ pub const EINTR: ::c_int = 4; /* Interrupted system call */ pub const EIO: ::c_int = 5; /* I/O error */ pub const ENXIO: ::c_int = 6; /* No such device or address */ pub const E2BIG: ::c_int = 7; /* Argument list too long */ pub const ENOEXEC: ::c_int = 8; /* Exec format error */ pub const EBADF: ::c_int = 9; /* Bad file number */ pub const ECHILD: ::c_int = 10; /* No child processes */ pub const EAGAIN: ::c_int = 11; /* Try again */ pub const ENOMEM: ::c_int = 12; /* Out of memory */ pub const EACCES: ::c_int = 13; /* Permission denied */ pub const EFAULT: ::c_int = 14; /* Bad address */ pub const ENOTBLK: ::c_int = 15; /* Block device required */ pub const EBUSY: ::c_int = 16; /* Device or resource busy */ pub const EEXIST: ::c_int = 17; /* File exists */ pub const EXDEV: ::c_int = 18; /* Cross-device link */ pub const ENODEV: ::c_int = 19; /* No such device */ pub const ENOTDIR: ::c_int = 20; /* Not a directory */ pub const EISDIR: ::c_int = 21; /* Is a directory */ pub const EINVAL: ::c_int = 22; /* Invalid argument */ pub const ENFILE: ::c_int = 23; /* File table overflow */ pub const EMFILE: ::c_int = 24; /* Too many open files */ pub const ENOTTY: ::c_int = 25; /* Not a typewriter */ pub const ETXTBSY: ::c_int = 26; /* Text file busy */ pub const EFBIG: ::c_int = 27; /* File too large */ pub const ENOSPC: ::c_int = 28; /* No space left on device */ pub const ESPIPE: ::c_int = 29; /* Illegal seek */ pub const EROFS: ::c_int = 30; /* Read-only file system */ pub const EMLINK: ::c_int = 31; /* Too many links */ pub const EPIPE: ::c_int = 32; /* Broken pipe */ pub const EDOM: ::c_int = 33; /* Math argument out of domain of func */ pub const ERANGE: ::c_int = 34; /* Math result not representable */ pub const EDEADLK: ::c_int = 35; /* Resource deadlock would occur */ pub const ENAMETOOLONG: ::c_int = 36; /* File name too long */ pub const ENOLCK: ::c_int = 37; /* No record locks available */ pub const ENOSYS: ::c_int = 38; /* Function not implemented */ pub const ENOTEMPTY: ::c_int = 39; /* Directory not empty */ pub const ELOOP: ::c_int = 40; /* Too many symbolic links encountered */ pub const EWOULDBLOCK: ::c_int = 41; /* Operation would block */ pub const ENOMSG: ::c_int = 42; /* No message of desired type */ pub const EIDRM: ::c_int = 43; /* Identifier removed */ pub const ECHRNG: ::c_int = 44; /* Channel number out of range */ pub const EL2NSYNC: ::c_int = 45; /* Level 2 not synchronized */ pub const EL3HLT: ::c_int = 46; /* Level 3 halted */ pub const EL3RST: ::c_int = 47; /* Level 3 reset */ pub const ELNRNG: ::c_int = 48; /* Link number out of range */ pub const EUNATCH: ::c_int = 49; /* Protocol driver not attached */ pub const ENOCSI: ::c_int = 50; /* No CSI structure available */ pub const EL2HLT: ::c_int = 51; /* Level 2 halted */ pub const EBADE: ::c_int = 52; /* Invalid exchange */ pub const EBADR: ::c_int = 53; /* Invalid request descriptor */ pub const EXFULL: ::c_int = 54; /* Exchange full */ pub const ENOANO: ::c_int = 55; /* No anode */ pub const EBADRQC: ::c_int = 56; /* Invalid request code */ pub const EBADSLT: ::c_int = 57; /* Invalid slot */ pub const EDEADLOCK: ::c_int = 58; /* Resource deadlock would occur */ pub const EBFONT: ::c_int = 59; /* Bad font file format */ pub const ENOSTR: ::c_int = 60; /* Device not a stream */ pub const ENODATA: ::c_int = 61; /* No data available */ pub const ETIME: ::c_int = 62; /* Timer expired */ pub const ENOSR: ::c_int = 63; /* Out of streams resources */ pub const ENONET: ::c_int = 64; /* Machine is not on the network */ pub const ENOPKG: ::c_int = 65; /* Package not installed */ pub const EREMOTE: ::c_int = 66; /* Object is remote */ pub const ENOLINK: ::c_int = 67; /* Link has been severed */ pub const EADV: ::c_int = 68; /* Advertise error */ pub const ESRMNT: ::c_int = 69; /* Srmount error */ pub const ECOMM: ::c_int = 70; /* Communication error on send */ pub const EPROTO: ::c_int = 71; /* Protocol error */ pub const EMULTIHOP: ::c_int = 72; /* Multihop attempted */ pub const EDOTDOT: ::c_int = 73; /* RFS specific error */ pub const EBADMSG: ::c_int = 74; /* Not a data message */ pub const EOVERFLOW: ::c_int = 75; /* Value too large for defined data type */ pub const ENOTUNIQ: ::c_int = 76; /* Name not unique on network */ pub const EBADFD: ::c_int = 77; /* File descriptor in bad state */ pub const EREMCHG: ::c_int = 78; /* Remote address changed */ pub const ELIBACC: ::c_int = 79; /* Can not access a needed shared library */ pub const ELIBBAD: ::c_int = 80; /* Accessing a corrupted shared library */ pub const ELIBSCN: ::c_int = 81; /* .lib section in a.out corrupted */ /* Attempting to link in too many shared libraries */ pub const ELIBMAX: ::c_int = 82; pub const ELIBEXEC: ::c_int = 83; /* Cannot exec a shared library directly */ pub const EILSEQ: ::c_int = 84; /* Illegal byte sequence */ /* Interrupted system call should be restarted */ pub const ERESTART: ::c_int = 85; pub const ESTRPIPE: ::c_int = 86; /* Streams pipe error */ pub const EUSERS: ::c_int = 87; /* Too many users */ pub const ENOTSOCK: ::c_int = 88; /* Socket operation on non-socket */ pub const EDESTADDRREQ: ::c_int = 89; /* Destination address required */ pub const EMSGSIZE: ::c_int = 90; /* Message too long */ pub const EPROTOTYPE: ::c_int = 91; /* Protocol wrong type for socket */ pub const ENOPROTOOPT: ::c_int = 92; /* Protocol not available */ pub const EPROTONOSUPPORT: ::c_int = 93; /* Protocol not supported */ pub const ESOCKTNOSUPPORT: ::c_int = 94; /* Socket type not supported */ /* Operation not supported on transport endpoint */ pub const EOPNOTSUPP: ::c_int = 95; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 96; /* Protocol family not supported */ /* Address family not supported by protocol */ pub const EAFNOSUPPORT: ::c_int = 97; pub const EADDRINUSE: ::c_int = 98; /* Address already in use */ pub const EADDRNOTAVAIL: ::c_int = 99; /* Cannot assign requested address */ pub const ENETDOWN: ::c_int = 100; /* Network is down */ pub const ENETUNREACH: ::c_int = 101; /* Network is unreachable */ /* Network dropped connection because of reset */ pub const ENETRESET: ::c_int = 102; pub const ECONNABORTED: ::c_int = 103; /* Software caused connection abort */ pub const ECONNRESET: ::c_int = 104; /* Connection reset by peer */ pub const ENOBUFS: ::c_int = 105; /* No buffer space available */ pub const EISCONN: ::c_int = 106; /* Transport endpoint is already connected */ pub const ENOTCONN: ::c_int = 107; /* Transport endpoint is not connected */ /* Cannot send after transport endpoint shutdown */ pub const ESHUTDOWN: ::c_int = 108; pub const ETOOMANYREFS: ::c_int = 109; /* Too many references: cannot splice */ pub const ETIMEDOUT: ::c_int = 110; /* Connection timed out */ pub const ECONNREFUSED: ::c_int = 111; /* Connection refused */ pub const EHOSTDOWN: ::c_int = 112; /* Host is down */ pub const EHOSTUNREACH: ::c_int = 113; /* No route to host */ pub const EALREADY: ::c_int = 114; /* Operation already in progress */ pub const EINPROGRESS: ::c_int = 115; /* Operation now in progress */ pub const ESTALE: ::c_int = 116; /* Stale NFS file handle */ pub const EUCLEAN: ::c_int = 117; /* Structure needs cleaning */ pub const ENOTNAM: ::c_int = 118; /* Not a XENIX named type file */ pub const ENAVAIL: ::c_int = 119; /* No XENIX semaphores available */ pub const EISNAM: ::c_int = 120; /* Is a named type file */ pub const EREMOTEIO: ::c_int = 121; /* Remote I/O error */ pub const EDQUOT: ::c_int = 122; /* Quota exceeded */ pub const ENOMEDIUM: ::c_int = 123; /* No medium found */ pub const EMEDIUMTYPE: ::c_int = 124; /* Wrong medium type */ pub const ECANCELED: ::c_int = 125; /* Operation Canceled */ pub const ENOKEY: ::c_int = 126; /* Required key not available */ pub const EKEYEXPIRED: ::c_int = 127; /* Key has expired */ pub const EKEYREVOKED: ::c_int = 128; /* Key has been revoked */ pub const EKEYREJECTED: ::c_int = 129; /* Key was rejected by service */ pub const EOWNERDEAD: ::c_int = 130; /* Owner died */ pub const ENOTRECOVERABLE: ::c_int = 131; /* State not recoverable */ // fcntl.h pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; // FIXME: relibc { pub const F_DUPFD_CLOEXEC: ::c_int = ::F_DUPFD; // } pub const FD_CLOEXEC: ::c_int = 0x0100_0000; pub const O_RDONLY: ::c_int = 0x0001_0000; pub const O_WRONLY: ::c_int = 0x0002_0000; pub const O_RDWR: ::c_int = 0x0003_0000; pub const O_ACCMODE: ::c_int = 0x0003_0000; pub const O_NONBLOCK: ::c_int = 0x0004_0000; pub const O_APPEND: ::c_int = 0x0008_0000; pub const O_SHLOCK: ::c_int = 0x0010_0000; pub const O_EXLOCK: ::c_int = 0x0020_0000; pub const O_ASYNC: ::c_int = 0x0040_0000; pub const O_FSYNC: ::c_int = 0x0080_0000; pub const O_CLOEXEC: ::c_int = 0x0100_0000; pub const O_CREAT: ::c_int = 0x0200_0000; pub const O_TRUNC: ::c_int = 0x0400_0000; pub const O_EXCL: ::c_int = 0x0800_0000; pub const O_DIRECTORY: ::c_int = 0x1000_0000; pub const O_PATH: ::c_int = 0x2000_0000; pub const O_SYMLINK: ::c_int = 0x4000_0000; // Negative to allow it to be used as int // FIXME: Fix negative values missing from includes pub const O_NOFOLLOW: ::c_int = -0x8000_0000; // locale.h pub const LC_ALL: ::c_int = 0; pub const LC_COLLATE: ::c_int = 1; pub const LC_CTYPE: ::c_int = 2; pub const LC_MESSAGES: ::c_int = 3; pub const LC_MONETARY: ::c_int = 4; pub const LC_NUMERIC: ::c_int = 5; pub const LC_TIME: ::c_int = 6; // netdb.h pub const AI_PASSIVE: ::c_int = 0x0001; pub const AI_CANONNAME: ::c_int = 0x0002; pub const AI_NUMERICHOST: ::c_int = 0x0004; pub const AI_V4MAPPED: ::c_int = 0x0008; pub const AI_ALL: ::c_int = 0x0010; pub const AI_ADDRCONFIG: ::c_int = 0x0020; pub const AI_NUMERICSERV: ::c_int = 0x0400; pub const EAI_BADFLAGS: ::c_int = -1; pub const EAI_NONAME: ::c_int = -2; pub const EAI_AGAIN: ::c_int = -3; pub const EAI_FAIL: ::c_int = -4; pub const EAI_NODATA: ::c_int = -5; pub const EAI_FAMILY: ::c_int = -6; pub const EAI_SOCKTYPE: ::c_int = -7; pub const EAI_SERVICE: ::c_int = -8; pub const EAI_ADDRFAMILY: ::c_int = -9; pub const EAI_MEMORY: ::c_int = -10; pub const EAI_SYSTEM: ::c_int = -11; pub const EAI_OVERFLOW: ::c_int = -12; pub const NI_MAXHOST: ::c_int = 1025; pub const NI_MAXSERV: ::c_int = 32; pub const NI_NUMERICHOST: ::c_int = 0x0001; pub const NI_NUMERICSERV: ::c_int = 0x0002; pub const NI_NOFQDN: ::c_int = 0x0004; pub const NI_NAMEREQD: ::c_int = 0x0008; pub const NI_DGRAM: ::c_int = 0x0010; // netinet/in.h // FIXME: relibc { pub const IP_TTL: ::c_int = 2; pub const IPV6_UNICAST_HOPS: ::c_int = 16; pub const IPV6_MULTICAST_IF: ::c_int = 17; pub const IPV6_MULTICAST_HOPS: ::c_int = 18; pub const IPV6_MULTICAST_LOOP: ::c_int = 19; pub const IPV6_ADD_MEMBERSHIP: ::c_int = 20; pub const IPV6_DROP_MEMBERSHIP: ::c_int = 21; pub const IPV6_V6ONLY: ::c_int = 26; pub const IP_MULTICAST_IF: ::c_int = 32; pub const IP_MULTICAST_TTL: ::c_int = 33; pub const IP_MULTICAST_LOOP: ::c_int = 34; pub const IP_ADD_MEMBERSHIP: ::c_int = 35; pub const IP_DROP_MEMBERSHIP: ::c_int = 36; pub const IPPROTO_RAW: ::c_int = 255; // } // netinet/tcp.h pub const TCP_NODELAY: ::c_int = 1; // FIXME: relibc { pub const TCP_KEEPIDLE: ::c_int = 1; // } // poll.h pub const POLLIN: ::c_short = 0x001; pub const POLLPRI: ::c_short = 0x002; pub const POLLOUT: ::c_short = 0x004; pub const POLLERR: ::c_short = 0x008; pub const POLLHUP: ::c_short = 0x010; pub const POLLNVAL: ::c_short = 0x020; pub const POLLRDNORM: ::c_short = 0x040; pub const POLLRDBAND: ::c_short = 0x080; pub const POLLWRNORM: ::c_short = 0x100; pub const POLLWRBAND: ::c_short = 0x200; // pthread.h pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_INITIALIZER: ::pthread_mutex_t = ::pthread_mutex_t { bytes: [0; _PTHREAD_MUTEX_SIZE], }; pub const PTHREAD_COND_INITIALIZER: ::pthread_cond_t = ::pthread_cond_t { bytes: [0; _PTHREAD_COND_SIZE], }; pub const PTHREAD_RWLOCK_INITIALIZER: ::pthread_rwlock_t = ::pthread_rwlock_t { bytes: [0; _PTHREAD_RWLOCK_SIZE], }; pub const PTHREAD_STACK_MIN: ::size_t = 4096; // signal.h pub const SIG_BLOCK: ::c_int = 0; pub const SIG_UNBLOCK: ::c_int = 1; pub const SIG_SETMASK: ::c_int = 2; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGTRAP: ::c_int = 5; pub const SIGABRT: ::c_int = 6; pub const SIGBUS: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGUSR1: ::c_int = 10; pub const SIGSEGV: ::c_int = 11; pub const SIGUSR2: ::c_int = 12; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const SIGSTKFLT: ::c_int = 16; pub const SIGCHLD: ::c_int = 17; pub const SIGCONT: ::c_int = 18; pub const SIGSTOP: ::c_int = 19; pub const SIGTSTP: ::c_int = 20; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGURG: ::c_int = 23; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGIO: ::c_int = 29; pub const SIGPWR: ::c_int = 30; pub const SIGSYS: ::c_int = 31; pub const NSIG: ::c_int = 32; pub const SA_NOCLDSTOP: ::c_ulong = 0x00000001; pub const SA_NOCLDWAIT: ::c_ulong = 0x00000002; pub const SA_SIGINFO: ::c_ulong = 0x00000004; pub const SA_RESTORER: ::c_ulong = 0x04000000; pub const SA_ONSTACK: ::c_ulong = 0x08000000; pub const SA_RESTART: ::c_ulong = 0x10000000; pub const SA_NODEFER: ::c_ulong = 0x40000000; pub const SA_RESETHAND: ::c_ulong = 0x80000000; // sys/file.h pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; // sys/epoll.h pub const EPOLL_CLOEXEC: ::c_int = 0x0100_0000; pub const EPOLL_CTL_ADD: ::c_int = 1; pub const EPOLL_CTL_DEL: ::c_int = 2; pub const EPOLL_CTL_MOD: ::c_int = 3; pub const EPOLLIN: ::c_int = 0x001; pub const EPOLLPRI: ::c_int = 0x002; pub const EPOLLOUT: ::c_int = 0x004; pub const EPOLLERR: ::c_int = 0x008; pub const EPOLLHUP: ::c_int = 0x010; pub const EPOLLNVAL: ::c_int = 0x020; pub const EPOLLRDNORM: ::c_int = 0x040; pub const EPOLLRDBAND: ::c_int = 0x080; pub const EPOLLWRNORM: ::c_int = 0x100; pub const EPOLLWRBAND: ::c_int = 0x200; pub const EPOLLMSG: ::c_int = 0x400; pub const EPOLLRDHUP: ::c_int = 0x2000; pub const EPOLLEXCLUSIVE: ::c_int = 1 << 28; pub const EPOLLWAKEUP: ::c_int = 1 << 29; pub const EPOLLONESHOT: ::c_int = 1 << 30; pub const EPOLLET: ::c_int = 1 << 31; // sys/stat.h pub const S_IFMT: ::c_int = 0o0_170_000; pub const S_IFDIR: ::c_int = 0o040_000; pub const S_IFCHR: ::c_int = 0o020_000; pub const S_IFBLK: ::c_int = 0o060_000; pub const S_IFREG: ::c_int = 0o100_000; pub const S_IFIFO: ::c_int = 0o010_000; pub const S_IFLNK: ::c_int = 0o120_000; pub const S_IFSOCK: ::c_int = 0o140_000; pub const S_IRWXU: ::c_int = 0o0_700; pub const S_IRUSR: ::c_int = 0o0_400; pub const S_IWUSR: ::c_int = 0o0_200; pub const S_IXUSR: ::c_int = 0o0_100; pub const S_IRWXG: ::c_int = 0o0_070; pub const S_IRGRP: ::c_int = 0o0_040; pub const S_IWGRP: ::c_int = 0o0_020; pub const S_IXGRP: ::c_int = 0o0_010; pub const S_IRWXO: ::c_int = 0o0_007; pub const S_IROTH: ::c_int = 0o0_004; pub const S_IWOTH: ::c_int = 0o0_002; pub const S_IXOTH: ::c_int = 0o0_001; // stdlib.h pub const EXIT_SUCCESS: ::c_int = 0; pub const EXIT_FAILURE: ::c_int = 1; // sys/ioctl.h // FIXME: relibc { pub const FIONREAD: ::c_ulong = 0x541B; pub const FIONBIO: ::c_ulong = 0x5421; pub const FIOCLEX: ::c_ulong = 0x5451; // } pub const TCGETS: ::c_ulong = 0x5401; pub const TCSETS: ::c_ulong = 0x5402; pub const TCFLSH: ::c_ulong = 0x540B; pub const TIOCSCTTY: ::c_ulong = 0x540E; pub const TIOCGPGRP: ::c_ulong = 0x540F; pub const TIOCSPGRP: ::c_ulong = 0x5410; pub const TIOCGWINSZ: ::c_ulong = 0x5413; pub const TIOCSWINSZ: ::c_ulong = 0x5414; // sys/mman.h pub const PROT_NONE: ::c_int = 0x0000; pub const PROT_READ: ::c_int = 0x0004; pub const PROT_WRITE: ::c_int = 0x0002; pub const PROT_EXEC: ::c_int = 0x0001; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_ANON: ::c_int = 0x0020; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_FAILED: *mut ::c_void = !0 as _; pub const MS_ASYNC: ::c_int = 0x0001; pub const MS_INVALIDATE: ::c_int = 0x0002; pub const MS_SYNC: ::c_int = 0x0004; // sys/select.h pub const FD_SETSIZE: usize = 1024; // sys/socket.h pub const AF_INET: ::c_int = 2; pub const AF_INET6: ::c_int = 10; pub const AF_UNIX: ::c_int = 1; pub const AF_UNSPEC: ::c_int = 0; pub const PF_INET: ::c_int = 2; pub const PF_INET6: ::c_int = 10; pub const PF_UNIX: ::c_int = 1; pub const PF_UNSPEC: ::c_int = 0; pub const MSG_CTRUNC: ::c_int = 8; pub const MSG_DONTROUTE: ::c_int = 4; pub const MSG_EOR: ::c_int = 128; pub const MSG_OOB: ::c_int = 1; pub const MSG_PEEK: ::c_int = 2; pub const MSG_TRUNC: ::c_int = 32; pub const MSG_DONTWAIT: ::c_int = 64; pub const MSG_WAITALL: ::c_int = 256; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const SO_DEBUG: ::c_int = 1; pub const SO_REUSEADDR: ::c_int = 2; pub const SO_TYPE: ::c_int = 3; pub const SO_ERROR: ::c_int = 4; pub const SO_DONTROUTE: ::c_int = 5; pub const SO_BROADCAST: ::c_int = 6; pub const SO_SNDBUF: ::c_int = 7; pub const SO_RCVBUF: ::c_int = 8; pub const SO_KEEPALIVE: ::c_int = 9; pub const SO_OOBINLINE: ::c_int = 10; pub const SO_NO_CHECK: ::c_int = 11; pub const SO_PRIORITY: ::c_int = 12; pub const SO_LINGER: ::c_int = 13; pub const SO_BSDCOMPAT: ::c_int = 14; pub const SO_REUSEPORT: ::c_int = 15; pub const SO_PASSCRED: ::c_int = 16; pub const SO_PEERCRED: ::c_int = 17; pub const SO_RCVLOWAT: ::c_int = 18; pub const SO_SNDLOWAT: ::c_int = 19; pub const SO_RCVTIMEO: ::c_int = 20; pub const SO_SNDTIMEO: ::c_int = 21; pub const SO_ACCEPTCONN: ::c_int = 30; pub const SO_PEERSEC: ::c_int = 31; pub const SO_SNDBUFFORCE: ::c_int = 32; pub const SO_RCVBUFFORCE: ::c_int = 33; pub const SO_PROTOCOL: ::c_int = 38; pub const SO_DOMAIN: ::c_int = 39; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_NONBLOCK: ::c_int = 0o4_000; pub const SOCK_CLOEXEC: ::c_int = 0o2_000_000; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOL_SOCKET: ::c_int = 1; pub const SOMAXCONN: ::c_int = 128; // sys/termios.h pub const VEOF: usize = 0; pub const VEOL: usize = 1; pub const VEOL2: usize = 2; pub const VERASE: usize = 3; pub const VWERASE: usize = 4; pub const VKILL: usize = 5; pub const VREPRINT: usize = 6; pub const VSWTC: usize = 7; pub const VINTR: usize = 8; pub const VQUIT: usize = 9; pub const VSUSP: usize = 10; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VLNEXT: usize = 14; pub const VDISCARD: usize = 15; pub const VMIN: usize = 16; pub const VTIME: usize = 17; pub const NCCS: usize = 32; pub const IGNBRK: ::tcflag_t = 0o000_001; pub const BRKINT: ::tcflag_t = 0o000_002; pub const IGNPAR: ::tcflag_t = 0o000_004; pub const PARMRK: ::tcflag_t = 0o000_010; pub const INPCK: ::tcflag_t = 0o000_020; pub const ISTRIP: ::tcflag_t = 0o000_040; pub const INLCR: ::tcflag_t = 0o000_100; pub const IGNCR: ::tcflag_t = 0o000_200; pub const ICRNL: ::tcflag_t = 0o000_400; pub const IXON: ::tcflag_t = 0o001_000; pub const IXOFF: ::tcflag_t = 0o002_000; pub const OPOST: ::tcflag_t = 0o000_001; pub const ONLCR: ::tcflag_t = 0o000_002; pub const OLCUC: ::tcflag_t = 0o000_004; pub const OCRNL: ::tcflag_t = 0o000_010; pub const ONOCR: ::tcflag_t = 0o000_020; pub const ONLRET: ::tcflag_t = 0o000_040; pub const OFILL: ::tcflag_t = 0o0000_100; pub const OFDEL: ::tcflag_t = 0o0000_200; pub const B0: speed_t = 0o000_000; pub const B50: speed_t = 0o000_001; pub const B75: speed_t = 0o000_002; pub const B110: speed_t = 0o000_003; pub const B134: speed_t = 0o000_004; pub const B150: speed_t = 0o000_005; pub const B200: speed_t = 0o000_006; pub const B300: speed_t = 0o000_007; pub const B600: speed_t = 0o000_010; pub const B1200: speed_t = 0o000_011; pub const B1800: speed_t = 0o000_012; pub const B2400: speed_t = 0o000_013; pub const B4800: speed_t = 0o000_014; pub const B9600: speed_t = 0o000_015; pub const B19200: speed_t = 0o000_016; pub const B38400: speed_t = 0o000_017; pub const B57600: speed_t = 0o0_020; pub const B115200: speed_t = 0o0_021; pub const B230400: speed_t = 0o0_022; pub const B460800: speed_t = 0o0_023; pub const B500000: speed_t = 0o0_024; pub const B576000: speed_t = 0o0_025; pub const B921600: speed_t = 0o0_026; pub const B1000000: speed_t = 0o0_027; pub const B1152000: speed_t = 0o0_030; pub const B1500000: speed_t = 0o0_031; pub const B2000000: speed_t = 0o0_032; pub const B2500000: speed_t = 0o0_033; pub const B3000000: speed_t = 0o0_034; pub const B3500000: speed_t = 0o0_035; pub const B4000000: speed_t = 0o0_036; pub const CSIZE: ::tcflag_t = 0o001_400; pub const CS5: ::tcflag_t = 0o000_000; pub const CS6: ::tcflag_t = 0o000_400; pub const CS7: ::tcflag_t = 0o001_000; pub const CS8: ::tcflag_t = 0o001_400; pub const CSTOPB: ::tcflag_t = 0o002_000; pub const CREAD: ::tcflag_t = 0o004_000; pub const PARENB: ::tcflag_t = 0o010_000; pub const PARODD: ::tcflag_t = 0o020_000; pub const HUPCL: ::tcflag_t = 0o040_000; pub const CLOCAL: ::tcflag_t = 0o0100000; pub const ISIG: ::tcflag_t = 0x0000_0080; pub const ICANON: ::tcflag_t = 0x0000_0100; pub const ECHO: ::tcflag_t = 0x0000_0008; pub const ECHOE: ::tcflag_t = 0x0000_0002; pub const ECHOK: ::tcflag_t = 0x0000_0004; pub const ECHONL: ::tcflag_t = 0x0000_0010; pub const NOFLSH: ::tcflag_t = 0x8000_0000; pub const TOSTOP: ::tcflag_t = 0x0040_0000; pub const IEXTEN: ::tcflag_t = 0x0000_0400; pub const TCOOFF: ::c_int = 0; pub const TCOON: ::c_int = 1; pub const TCIOFF: ::c_int = 2; pub const TCION: ::c_int = 3; pub const TCIFLUSH: ::c_int = 0; pub const TCOFLUSH: ::c_int = 1; pub const TCIOFLUSH: ::c_int = 2; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; // sys/wait.h pub const WNOHANG: ::c_int = 1; pub const WUNTRACED: ::c_int = 2; pub const WSTOPPED: ::c_int = 2; pub const WEXITED: ::c_int = 4; pub const WCONTINUED: ::c_int = 8; pub const WNOWAIT: ::c_int = 0x0100_0000; pub const __WNOTHREAD: ::c_int = 0x2000_0000; pub const __WALL: ::c_int = 0x4000_0000; #[allow(overflowing_literals)] pub const __WCLONE: ::c_int = 0x8000_0000; // time.h pub const CLOCK_REALTIME: ::c_int = 1; pub const CLOCK_MONOTONIC: ::c_int = 4; pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2; pub const CLOCKS_PER_SEC: ::clock_t = 1_000_000; // unistd.h // POSIX.1 { pub const _SC_ARG_MAX: ::c_int = 0; pub const _SC_CHILD_MAX: ::c_int = 1; pub const _SC_CLK_TCK: ::c_int = 2; pub const _SC_NGROUPS_MAX: ::c_int = 3; pub const _SC_OPEN_MAX: ::c_int = 4; pub const _SC_STREAM_MAX: ::c_int = 5; pub const _SC_TZNAME_MAX: ::c_int = 6; // ... pub const _SC_VERSION: ::c_int = 29; pub const _SC_PAGESIZE: ::c_int = 30; pub const _SC_PAGE_SIZE: ::c_int = 30; // ... pub const _SC_RE_DUP_MAX: ::c_int = 44; // ... pub const _SC_LOGIN_NAME_MAX: ::c_int = 71; pub const _SC_TTY_NAME_MAX: ::c_int = 72; // ... pub const _SC_SYMLOOP_MAX: ::c_int = 173; // ... pub const _SC_HOST_NAME_MAX: ::c_int = 180; // } POSIX.1 pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const _PC_LINK_MAX: ::c_int = 0; pub const _PC_MAX_CANON: ::c_int = 1; pub const _PC_MAX_INPUT: ::c_int = 2; pub const _PC_NAME_MAX: ::c_int = 3; pub const _PC_PATH_MAX: ::c_int = 4; pub const _PC_PIPE_BUF: ::c_int = 5; pub const _PC_CHOWN_RESTRICTED: ::c_int = 6; pub const _PC_NO_TRUNC: ::c_int = 7; pub const _PC_VDISABLE: ::c_int = 8; pub const _PC_SYNC_IO: ::c_int = 9; pub const _PC_ASYNC_IO: ::c_int = 10; pub const _PC_PRIO_IO: ::c_int = 11; pub const _PC_SOCK_MAXBUF: ::c_int = 12; pub const _PC_FILESIZEBITS: ::c_int = 13; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; pub const _PC_REC_XFER_ALIGN: ::c_int = 17; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 18; pub const _PC_SYMLINK_MAX: ::c_int = 19; pub const _PC_2_SYMLINKS: ::c_int = 20; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; // wait.h f! { pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] &= !(1 << (fd % size)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; return ((*set).fds_bits[fd / size] & (1 << (fd % size))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let fd = fd as usize; let size = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; (*set).fds_bits[fd / size] |= 1 << (fd % size); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0xff) == 0x7f } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { status == 0xffff } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { ((status & 0x7f) + 1) as i8 >= 2 } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { status & 0x7f } pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0x7f) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { (status >> 8) & 0xff } pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0x80) != 0 } } extern "C" { // errno.h pub fn __errno_location() -> *mut ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; // unistd.h pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn getdtablesize() -> ::c_int; // grp.h pub fn getgrent() -> *mut ::group; pub fn setgrent(); pub fn endgrent(); pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getgrouplist( user: *const ::c_char, group: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; // malloc.h pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; // netdb.h pub fn getnameinfo( addr: *const ::sockaddr, addrlen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; // pthread.h pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn pthread_create( tid: *mut ::pthread_t, attr: *const ::pthread_attr_t, start: extern "C" fn(*mut ::c_void) -> *mut ::c_void, arg: *mut ::c_void, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; //pty.h pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *const termios, winp: *const ::winsize, ) -> ::c_int; // pwd.h pub fn getpwent() -> *mut passwd; pub fn setpwent(); pub fn endpwent(); pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; // signal.h pub fn pthread_sigmask( how: ::c_int, set: *const ::sigset_t, oldset: *mut ::sigset_t, ) -> ::c_int; pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, sig: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; // stdlib.h pub fn getsubopt( optionp: *mut *mut c_char, tokens: *const *mut c_char, valuep: *mut *mut c_char, ) -> ::c_int; pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void; // string.h pub fn explicit_bzero(p: *mut ::c_void, len: ::size_t); pub fn strlcat(dst: *mut ::c_char, src: *const ::c_char, siz: ::size_t) -> ::size_t; pub fn strlcpy(dst: *mut ::c_char, src: *const ::c_char, siz: ::size_t) -> ::size_t; // sys/epoll.h pub fn epoll_create(size: ::c_int) -> ::c_int; pub fn epoll_create1(flags: ::c_int) -> ::c_int; pub fn epoll_wait( epfd: ::c_int, events: *mut ::epoll_event, maxevents: ::c_int, timeout: ::c_int, ) -> ::c_int; pub fn epoll_ctl(epfd: ::c_int, op: ::c_int, fd: ::c_int, event: *mut ::epoll_event) -> ::c_int; // sys/ioctl.h pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; // sys/mman.h pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn shm_open(name: *const c_char, oflag: ::c_int, mode: mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; // sys/resource.h pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; // sys/socket.h pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; // sys/stat.h pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; // sys/uio.h pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; // sys/utsname.h pub fn uname(utsname: *mut utsname) -> ::c_int; // time.h pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; // utmp.h pub fn login_tty(fd: ::c_int) -> ::c_int; } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_un {} impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl ::hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_family == other.ss_family && self.__ss_align == self.__ss_align && self .__ss_padding .iter() .zip(other.__ss_padding.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_family", &self.ss_family) .field("__ss_align", &self.__ss_align) // FIXME: .field("__ss_padding", &self.__ss_padding) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_family.hash(state); self.__ss_padding.hash(state); self.__ss_align.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a, b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a, b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a, b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a, b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a, b)| a == b) && self .domainname .iter() .zip(other.domainname.iter()) .all(|(a, b)| a == b) } } impl Eq for utsname {} impl ::fmt::Debug for utsname { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utsname") // FIXME: .field("sysname", &self.sysname) // FIXME: .field("nodename", &self.nodename) // FIXME: .field("release", &self.release) // FIXME: .field("version", &self.version) // FIXME: .field("machine", &self.machine) // FIXME: .field("domainname", &self.domainname) .finish() } } impl ::hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); self.domainname.hash(state); } } } } libc/src/unix/bsd/0000775000175000017500000000000014661133735014776 5ustar jamespagejamespagelibc/src/unix/bsd/netbsdlike/0000775000175000017500000000000014661133735017122 5ustar jamespagejamespagelibc/src/unix/bsd/netbsdlike/mod.rs0000644000175000017500000007057614661133735020264 0ustar jamespagejamespagepub type wchar_t = i32; pub type time_t = i64; pub type mode_t = u32; pub type nlink_t = u32; pub type ino_t = u64; pub type pthread_key_t = ::c_int; pub type rlim_t = u64; pub type speed_t = ::c_uint; pub type tcflag_t = ::c_uint; pub type nl_item = c_long; pub type clockid_t = ::c_int; pub type id_t = u32; pub type sem_t = *mut sem; pub type key_t = c_long; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum sem {} impl ::Copy for sem {} impl ::Clone for sem { fn clone(&self) -> sem { *self } } s! { pub struct sched_param { pub sched_priority: ::c_int, } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_mask: ::sigset_t, pub sa_flags: ::c_int, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct in6_pktinfo { pub ipi6_addr: ::in6_addr, pub ipi6_ifindex: ::c_uint, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_cc: [::cc_t; ::NCCS], pub c_ispeed: ::c_int, pub c_ospeed: ::c_int, } pub struct flock { pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, pub l_type: ::c_short, pub l_whence: ::c_short, } pub struct ipc_perm { pub cuid: ::uid_t, pub cgid: ::gid_t, pub uid: ::uid_t, pub gid: ::gid_t, pub mode: ::mode_t, #[cfg(target_os = "openbsd")] pub seq: ::c_ushort, #[cfg(target_os = "netbsd")] pub _seq: ::c_ushort, #[cfg(target_os = "openbsd")] pub key: ::key_t, #[cfg(target_os = "netbsd")] pub _key: ::key_t, } pub struct ptrace_io_desc { pub piod_op: ::c_int, pub piod_offs: *mut ::c_void, pub piod_addr: *mut ::c_void, pub piod_len: ::size_t, } } pub const D_T_FMT: ::nl_item = 0; pub const D_FMT: ::nl_item = 1; pub const T_FMT: ::nl_item = 2; pub const T_FMT_AMPM: ::nl_item = 3; pub const AM_STR: ::nl_item = 4; pub const PM_STR: ::nl_item = 5; pub const DAY_1: ::nl_item = 6; pub const DAY_2: ::nl_item = 7; pub const DAY_3: ::nl_item = 8; pub const DAY_4: ::nl_item = 9; pub const DAY_5: ::nl_item = 10; pub const DAY_6: ::nl_item = 11; pub const DAY_7: ::nl_item = 12; pub const ABDAY_1: ::nl_item = 13; pub const ABDAY_2: ::nl_item = 14; pub const ABDAY_3: ::nl_item = 15; pub const ABDAY_4: ::nl_item = 16; pub const ABDAY_5: ::nl_item = 17; pub const ABDAY_6: ::nl_item = 18; pub const ABDAY_7: ::nl_item = 19; pub const MON_1: ::nl_item = 20; pub const MON_2: ::nl_item = 21; pub const MON_3: ::nl_item = 22; pub const MON_4: ::nl_item = 23; pub const MON_5: ::nl_item = 24; pub const MON_6: ::nl_item = 25; pub const MON_7: ::nl_item = 26; pub const MON_8: ::nl_item = 27; pub const MON_9: ::nl_item = 28; pub const MON_10: ::nl_item = 29; pub const MON_11: ::nl_item = 30; pub const MON_12: ::nl_item = 31; pub const ABMON_1: ::nl_item = 32; pub const ABMON_2: ::nl_item = 33; pub const ABMON_3: ::nl_item = 34; pub const ABMON_4: ::nl_item = 35; pub const ABMON_5: ::nl_item = 36; pub const ABMON_6: ::nl_item = 37; pub const ABMON_7: ::nl_item = 38; pub const ABMON_8: ::nl_item = 39; pub const ABMON_9: ::nl_item = 40; pub const ABMON_10: ::nl_item = 41; pub const ABMON_11: ::nl_item = 42; pub const ABMON_12: ::nl_item = 43; pub const RADIXCHAR: ::nl_item = 44; pub const THOUSEP: ::nl_item = 45; pub const YESSTR: ::nl_item = 46; pub const YESEXPR: ::nl_item = 47; pub const NOSTR: ::nl_item = 48; pub const NOEXPR: ::nl_item = 49; pub const CRNCYSTR: ::nl_item = 50; pub const CODESET: ::nl_item = 51; pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 2147483647; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 2; pub const _IOLBF: ::c_int = 1; pub const BUFSIZ: ::c_uint = 1024; pub const FOPEN_MAX: ::c_uint = 20; pub const FILENAME_MAX: ::c_uint = 1024; pub const L_tmpnam: ::c_uint = 1024; pub const O_NOCTTY: ::c_int = 32768; pub const S_IFIFO: mode_t = 4096; pub const S_IFCHR: mode_t = 8192; pub const S_IFBLK: mode_t = 24576; pub const S_IFDIR: mode_t = 16384; pub const S_IFREG: mode_t = 32768; pub const S_IFLNK: mode_t = 40960; pub const S_IFSOCK: mode_t = 49152; pub const S_IFMT: mode_t = 61440; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; pub const S_IREAD: mode_t = 256; pub const S_IRWXU: mode_t = 448; pub const S_IXUSR: mode_t = 64; pub const S_IWUSR: mode_t = 128; pub const S_IRUSR: mode_t = 256; pub const S_IRWXG: mode_t = 56; pub const S_IXGRP: mode_t = 8; pub const S_IWGRP: mode_t = 16; pub const S_IRGRP: mode_t = 32; pub const S_IRWXO: mode_t = 7; pub const S_IXOTH: mode_t = 1; pub const S_IWOTH: mode_t = 2; pub const S_IROTH: mode_t = 4; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const F_GETLK: ::c_int = 7; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const MAP_FILE: ::c_int = 0x0000; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_ANON: ::c_int = 0x1000; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const IPC_CREAT: ::c_int = 0o001000; pub const IPC_EXCL: ::c_int = 0o002000; pub const IPC_NOWAIT: ::c_int = 0o004000; pub const IPC_PRIVATE: ::key_t = 0; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const IPC_R: ::c_int = 0o000400; pub const IPC_W: ::c_int = 0o000200; pub const IPC_M: ::c_int = 0o010000; pub const SHM_R: ::c_int = IPC_R; pub const SHM_W: ::c_int = IPC_W; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MS_ASYNC: ::c_int = 0x0001; pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EDEADLK: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EAGAIN: ::c_int = 35; pub const EWOULDBLOCK: ::c_int = 35; pub const EINPROGRESS: ::c_int = 36; pub const EALREADY: ::c_int = 37; pub const ENOTSOCK: ::c_int = 38; pub const EDESTADDRREQ: ::c_int = 39; pub const EMSGSIZE: ::c_int = 40; pub const EPROTOTYPE: ::c_int = 41; pub const ENOPROTOOPT: ::c_int = 42; pub const EPROTONOSUPPORT: ::c_int = 43; pub const ESOCKTNOSUPPORT: ::c_int = 44; pub const EOPNOTSUPP: ::c_int = 45; pub const EPFNOSUPPORT: ::c_int = 46; pub const EAFNOSUPPORT: ::c_int = 47; pub const EADDRINUSE: ::c_int = 48; pub const EADDRNOTAVAIL: ::c_int = 49; pub const ENETDOWN: ::c_int = 50; pub const ENETUNREACH: ::c_int = 51; pub const ENETRESET: ::c_int = 52; pub const ECONNABORTED: ::c_int = 53; pub const ECONNRESET: ::c_int = 54; pub const ENOBUFS: ::c_int = 55; pub const EISCONN: ::c_int = 56; pub const ENOTCONN: ::c_int = 57; pub const ESHUTDOWN: ::c_int = 58; pub const ETOOMANYREFS: ::c_int = 59; pub const ETIMEDOUT: ::c_int = 60; pub const ECONNREFUSED: ::c_int = 61; pub const ELOOP: ::c_int = 62; pub const ENAMETOOLONG: ::c_int = 63; pub const EHOSTDOWN: ::c_int = 64; pub const EHOSTUNREACH: ::c_int = 65; pub const ENOTEMPTY: ::c_int = 66; pub const EPROCLIM: ::c_int = 67; pub const EUSERS: ::c_int = 68; pub const EDQUOT: ::c_int = 69; pub const ESTALE: ::c_int = 70; pub const EREMOTE: ::c_int = 71; pub const EBADRPC: ::c_int = 72; pub const ERPCMISMATCH: ::c_int = 73; pub const EPROGUNAVAIL: ::c_int = 74; pub const EPROGMISMATCH: ::c_int = 75; pub const EPROCUNAVAIL: ::c_int = 76; pub const ENOLCK: ::c_int = 77; pub const ENOSYS: ::c_int = 78; pub const EFTYPE: ::c_int = 79; pub const EAUTH: ::c_int = 80; pub const ENEEDAUTH: ::c_int = 81; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const SIGTRAP: ::c_int = 5; pub const GLOB_APPEND: ::c_int = 0x0001; pub const GLOB_DOOFFS: ::c_int = 0x0002; pub const GLOB_ERR: ::c_int = 0x0004; pub const GLOB_MARK: ::c_int = 0x0008; pub const GLOB_NOCHECK: ::c_int = 0x0010; pub const GLOB_NOSORT: ::c_int = 0x0020; pub const GLOB_NOESCAPE: ::c_int = 0x1000; pub const GLOB_NOSPACE: ::c_int = -1; pub const GLOB_ABORTED: ::c_int = -2; pub const GLOB_NOMATCH: ::c_int = -3; pub const GLOB_NOSYS: ::c_int = -4; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02; pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x04; pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x08; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x10; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x20; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; pub const PIOD_READ_D: ::c_int = 1; pub const PIOD_WRITE_D: ::c_int = 2; pub const PIOD_READ_I: ::c_int = 3; pub const PIOD_WRITE_I: ::c_int = 4; pub const PIOD_READ_AUXV: ::c_int = 5; pub const PT_TRACE_ME: ::c_int = 0; pub const PT_READ_I: ::c_int = 1; pub const PT_READ_D: ::c_int = 2; pub const PT_WRITE_I: ::c_int = 4; pub const PT_WRITE_D: ::c_int = 5; pub const PT_CONTINUE: ::c_int = 7; pub const PT_KILL: ::c_int = 8; pub const PT_ATTACH: ::c_int = 9; pub const PT_DETACH: ::c_int = 10; pub const PT_IO: ::c_int = 11; // http://man.openbsd.org/OpenBSD-current/man2/clock_getres.2 // The man page says clock_gettime(3) can accept various values as clockid_t but // http://fxr.watson.org/fxr/source/kern/kern_time.c?v=OPENBSD;im=excerpts#L161 // the implementation rejects anything other than the below two // // http://netbsd.gw.com/cgi-bin/man-cgi?clock_gettime // https://github.com/jsonn/src/blob/HEAD/sys/kern/subr_time.c#L222 // Basically the same goes for NetBSD pub const CLOCK_REALTIME: ::clockid_t = 0; pub const CLOCK_MONOTONIC: ::clockid_t = 3; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_MEMLOCK: ::c_int = 6; pub const RLIMIT_NPROC: ::c_int = 7; pub const RLIMIT_NOFILE: ::c_int = 8; pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY; pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY; pub const RUSAGE_SELF: ::c_int = 0; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const MADV_FREE: ::c_int = 6; // sys/fstypes.h in NetBSD, or sys/mount.h in OpenBSD pub const MNT_NODEV: ::c_int = 0x00000010; pub const MNT_LOCAL: ::c_int = 0x00001000; pub const MNT_QUOTA: ::c_int = 0x00002000; pub const AF_UNSPEC: ::c_int = 0; pub const AF_LOCAL: ::c_int = 1; pub const AF_UNIX: ::c_int = AF_LOCAL; pub const AF_INET: ::c_int = 2; pub const AF_IMPLINK: ::c_int = 3; pub const AF_PUP: ::c_int = 4; pub const AF_CHAOS: ::c_int = 5; pub const AF_NS: ::c_int = 6; pub const AF_ISO: ::c_int = 7; pub const AF_OSI: ::c_int = AF_ISO; pub const AF_DATAKIT: ::c_int = 9; pub const AF_CCITT: ::c_int = 10; pub const AF_SNA: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_DLI: ::c_int = 13; pub const AF_LAT: ::c_int = 14; pub const AF_HYLINK: ::c_int = 15; pub const AF_APPLETALK: ::c_int = 16; pub const AF_LINK: ::c_int = 18; pub const pseudo_AF_XTP: ::c_int = 19; pub const AF_COIP: ::c_int = 20; pub const AF_CNT: ::c_int = 21; pub const pseudo_AF_RTIP: ::c_int = 22; pub const AF_IPX: ::c_int = 23; pub const AF_INET6: ::c_int = 24; pub const pseudo_AF_PIP: ::c_int = 25; pub const AF_ISDN: ::c_int = 26; pub const AF_E164: ::c_int = AF_ISDN; pub const AF_NATM: ::c_int = 27; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_LOCAL: ::c_int = AF_LOCAL; pub const PF_UNIX: ::c_int = PF_LOCAL; pub const PF_INET: ::c_int = AF_INET; pub const PF_IMPLINK: ::c_int = AF_IMPLINK; pub const PF_PUP: ::c_int = AF_PUP; pub const PF_CHAOS: ::c_int = AF_CHAOS; pub const PF_NS: ::c_int = AF_NS; pub const PF_ISO: ::c_int = AF_ISO; pub const PF_OSI: ::c_int = AF_ISO; pub const PF_DATAKIT: ::c_int = AF_DATAKIT; pub const PF_CCITT: ::c_int = AF_CCITT; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_DECnet: ::c_int = AF_DECnet; pub const PF_DLI: ::c_int = AF_DLI; pub const PF_LAT: ::c_int = AF_LAT; pub const PF_HYLINK: ::c_int = AF_HYLINK; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_LINK: ::c_int = AF_LINK; pub const PF_XTP: ::c_int = pseudo_AF_XTP; pub const PF_COIP: ::c_int = AF_COIP; pub const PF_CNT: ::c_int = AF_CNT; pub const PF_IPX: ::c_int = AF_IPX; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_RTIP: ::c_int = pseudo_AF_RTIP; pub const PF_PIP: ::c_int = pseudo_AF_PIP; pub const PF_ISDN: ::c_int = AF_ISDN; pub const PF_NATM: ::c_int = AF_NATM; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const IP_TTL: ::c_int = 4; pub const IP_HDRINCL: ::c_int = 2; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; pub const IPV6_RECVPKTINFO: ::c_int = 36; pub const IPV6_PKTINFO: ::c_int = 46; pub const IPV6_RECVTCLASS: ::c_int = 57; pub const IPV6_TCLASS: ::c_int = 61; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x01; pub const SO_ACCEPTCONN: ::c_int = 0x0002; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVLOWAT: ::c_int = 0x1004; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; pub const SOMAXCONN: ::c_int = 128; pub const MSG_OOB: ::c_int = 0x1; pub const MSG_PEEK: ::c_int = 0x2; pub const MSG_DONTROUTE: ::c_int = 0x4; pub const MSG_EOR: ::c_int = 0x8; pub const MSG_TRUNC: ::c_int = 0x10; pub const MSG_CTRUNC: ::c_int = 0x20; pub const MSG_WAITALL: ::c_int = 0x40; pub const MSG_DONTWAIT: ::c_int = 0x80; pub const MSG_BCAST: ::c_int = 0x100; pub const MSG_MCAST: ::c_int = 0x200; pub const MSG_NOSIGNAL: ::c_int = 0x400; pub const MSG_CMSG_CLOEXEC: ::c_int = 0x800; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; pub const IPPROTO_RAW: ::c_int = 255; pub const _SC_ARG_MAX: ::c_int = 1; pub const _SC_CHILD_MAX: ::c_int = 2; pub const _SC_NGROUPS_MAX: ::c_int = 4; pub const _SC_OPEN_MAX: ::c_int = 5; pub const _SC_JOB_CONTROL: ::c_int = 6; pub const _SC_SAVED_IDS: ::c_int = 7; pub const _SC_VERSION: ::c_int = 8; pub const _SC_BC_BASE_MAX: ::c_int = 9; pub const _SC_BC_DIM_MAX: ::c_int = 10; pub const _SC_BC_SCALE_MAX: ::c_int = 11; pub const _SC_BC_STRING_MAX: ::c_int = 12; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 13; pub const _SC_EXPR_NEST_MAX: ::c_int = 14; pub const _SC_LINE_MAX: ::c_int = 15; pub const _SC_RE_DUP_MAX: ::c_int = 16; pub const _SC_2_VERSION: ::c_int = 17; pub const _SC_2_C_BIND: ::c_int = 18; pub const _SC_2_C_DEV: ::c_int = 19; pub const _SC_2_CHAR_TERM: ::c_int = 20; pub const _SC_2_FORT_DEV: ::c_int = 21; pub const _SC_2_FORT_RUN: ::c_int = 22; pub const _SC_2_LOCALEDEF: ::c_int = 23; pub const _SC_2_SW_DEV: ::c_int = 24; pub const _SC_2_UPE: ::c_int = 25; pub const _SC_STREAM_MAX: ::c_int = 26; pub const _SC_TZNAME_MAX: ::c_int = 27; pub const _SC_PAGESIZE: ::c_int = 28; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_FSYNC: ::c_int = 29; pub const _SC_XOPEN_SHM: ::c_int = 30; pub const Q_GETQUOTA: ::c_int = 0x300; pub const Q_SETQUOTA: ::c_int = 0x400; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const LOG_NFACILITIES: ::c_int = 24; pub const HW_NCPU: ::c_int = 3; pub const B0: speed_t = 0; pub const B50: speed_t = 50; pub const B75: speed_t = 75; pub const B110: speed_t = 110; pub const B134: speed_t = 134; pub const B150: speed_t = 150; pub const B200: speed_t = 200; pub const B300: speed_t = 300; pub const B600: speed_t = 600; pub const B1200: speed_t = 1200; pub const B1800: speed_t = 1800; pub const B2400: speed_t = 2400; pub const B4800: speed_t = 4800; pub const B9600: speed_t = 9600; pub const B19200: speed_t = 19200; pub const B38400: speed_t = 38400; pub const B7200: speed_t = 7200; pub const B14400: speed_t = 14400; pub const B28800: speed_t = 28800; pub const B57600: speed_t = 57600; pub const B76800: speed_t = 76800; pub const B115200: speed_t = 115200; pub const B230400: speed_t = 230400; pub const EXTA: speed_t = 19200; pub const EXTB: speed_t = 38400; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const CRTSCTS: ::tcflag_t = 0x00010000; pub const CRTS_IFLOW: ::tcflag_t = CRTSCTS; pub const CCTS_OFLOW: ::tcflag_t = CRTSCTS; pub const OCRNL: ::tcflag_t = 0x10; pub const TIOCEXCL: ::c_ulong = 0x2000740d; pub const TIOCNXCL: ::c_ulong = 0x2000740e; pub const TIOCFLUSH: ::c_ulong = 0x80047410; pub const TIOCGETA: ::c_ulong = 0x402c7413; pub const TIOCSETA: ::c_ulong = 0x802c7414; pub const TIOCSETAW: ::c_ulong = 0x802c7415; pub const TIOCSETAF: ::c_ulong = 0x802c7416; pub const TIOCGETD: ::c_ulong = 0x4004741a; pub const TIOCSETD: ::c_ulong = 0x8004741b; pub const TIOCMGET: ::c_ulong = 0x4004746a; pub const TIOCMBIC: ::c_ulong = 0x8004746b; pub const TIOCMBIS: ::c_ulong = 0x8004746c; pub const TIOCMSET: ::c_ulong = 0x8004746d; pub const TIOCSTART: ::c_ulong = 0x2000746e; pub const TIOCSTOP: ::c_ulong = 0x2000746f; pub const TIOCSCTTY: ::c_ulong = 0x20007461; pub const TIOCGWINSZ: ::c_ulong = 0x40087468; pub const TIOCSWINSZ: ::c_ulong = 0x80087467; pub const TIOCM_LE: ::c_int = 0o0001; pub const TIOCM_DTR: ::c_int = 0o0002; pub const TIOCM_RTS: ::c_int = 0o0004; pub const TIOCM_ST: ::c_int = 0o0010; pub const TIOCM_SR: ::c_int = 0o0020; pub const TIOCM_CTS: ::c_int = 0o0040; pub const TIOCM_CAR: ::c_int = 0o0100; pub const TIOCM_RNG: ::c_int = 0o0200; pub const TIOCM_DSR: ::c_int = 0o0400; pub const TIOCM_CD: ::c_int = TIOCM_CAR; pub const TIOCM_RI: ::c_int = TIOCM_RNG; pub const TIMER_ABSTIME: ::c_int = 1; // sys/reboot.h pub const RB_AUTOBOOT: ::c_int = 0; pub const TCP_INFO: ::c_int = 9; #[link(name = "util")] extern "C" { pub fn setgrent(); pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn accept4( s: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn mincore(addr: *mut ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_getres50")] pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_gettime50")] pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__clock_settime50")] pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn __errno() -> *mut ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn login_tty(fd: ::c_int) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const sched_param, ) -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut sched_param, ) -> ::c_int; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn getgrouplist( name: *const ::c_char, basegid: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::size_t) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn execvpe( file: *const ::c_char, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn waitid( idtype: idtype_t, id: ::id_t, infop: *mut ::siginfo_t, options: ::c_int, ) -> ::c_int; pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, ) -> ::c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const ::sched_param, ) -> ::c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, newfd: ::c_int, ) -> ::c_int; } extern "C" { pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn gethostid() -> ::c_long; pub fn sethostid(hostid: ::c_long) -> ::c_int; pub fn ftok(path: *const ::c_char, id: ::c_int) -> ::key_t; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; } cfg_if! { if #[cfg(target_os = "netbsd")] { mod netbsd; pub use self::netbsd::*; } else if #[cfg(target_os = "openbsd")] { mod openbsd; pub use self::openbsd::*; } else { // Unknown target_os } } libc/src/unix/bsd/netbsdlike/openbsd/0000775000175000017500000000000014661133735020554 5ustar jamespagejamespagelibc/src/unix/bsd/netbsdlike/openbsd/riscv64.rs0000644000175000017500000000155414661133735022425 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; pub type ucontext_t = sigcontext; s! { pub struct sigcontext { __sc_unused: ::c_int, pub sc_mask: ::c_int, pub sc_ra: ::c_long, pub sc_sp: ::c_long, pub sc_gp: ::c_long, pub sc_tp: ::c_long, pub sc_t: [::c_long; 7], pub sc_s: [::c_long; 12], pub sc_a: [::c_long; 8], pub sc_sepc: ::c_long, pub sc_f: [::c_long; 32], pub sc_fcsr: ::c_long, pub sc_cookie: ::c_long, } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/powerpc.rs0000644000175000017500000000061514661133735022601 0ustar jamespagejamespagepub type c_long = i32; pub type c_ulong = u32; pub type c_char = u8; // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_double>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/mips64.rs0000644000175000017500000000023514661133735022242 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type c_char = i8; #[doc(hidden)] pub const _ALIGNBYTES: usize = 7; pub const _MAX_PAGE_SHIFT: u32 = 14; libc/src/unix/bsd/netbsdlike/openbsd/arm.rs0000644000175000017500000000061514661133735021701 0ustar jamespagejamespagepub type c_long = i32; pub type c_ulong = u32; pub type c_char = u8; // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_double>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/x86.rs0000644000175000017500000000061214661133735021544 0ustar jamespagejamespagepub type c_long = i32; pub type c_ulong = u32; pub type c_char = i8; // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_int>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 4 - 1; } } pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/sparc64.rs0000644000175000017500000000023714661133735022404 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type c_char = i8; #[doc(hidden)] pub const _ALIGNBYTES: usize = 0xf; pub const _MAX_PAGE_SHIFT: u32 = 13; libc/src/unix/bsd/netbsdlike/openbsd/x86_64.rs0000644000175000017500000001046314661133735022062 0ustar jamespagejamespageuse PT_FIRSTMACH; pub type c_long = i64; pub type c_ulong = u64; pub type c_char = i8; pub type ucontext_t = sigcontext; s! { pub struct sigcontext { pub sc_rdi: ::c_long, pub sc_rsi: ::c_long, pub sc_rdx: ::c_long, pub sc_rcx: ::c_long, pub sc_r8: ::c_long, pub sc_r9: ::c_long, pub sc_r10: ::c_long, pub sc_r11: ::c_long, pub sc_r12: ::c_long, pub sc_r13: ::c_long, pub sc_r14: ::c_long, pub sc_r15: ::c_long, pub sc_rbp: ::c_long, pub sc_rbx: ::c_long, pub sc_rax: ::c_long, pub sc_gs: ::c_long, pub sc_fs: ::c_long, pub sc_es: ::c_long, pub sc_ds: ::c_long, pub sc_trapno: ::c_long, pub sc_err: ::c_long, pub sc_rip: ::c_long, pub sc_cs: ::c_long, pub sc_rflags: ::c_long, pub sc_rsp: ::c_long, pub sc_ss: ::c_long, pub sc_fpstate: *mut fxsave64, __sc_unused: ::c_int, pub sc_mask: ::c_int, pub sc_cookie: ::c_long, } } s_no_extra_traits! { #[repr(packed)] pub struct fxsave64 { pub fx_fcw: u16, pub fx_fsw: u16, pub fx_ftw: u8, __fx_unused1: u8, pub fx_fop: u16, pub fx_rip: u64, pub fx_rdp: u64, pub fx_mxcsr: u32, pub fx_mxcsr_mask: u32, pub fx_st: [[u64; 2]; 8], pub fx_xmm: [[u64; 2]; 16], __fx_unused3: [u8; 96], } } cfg_if! { if #[cfg(feature = "extra_traits")] { // `fxsave64` is packed, so field access is unaligned. // use {x} to create temporary storage, copy field to it, and do aligned access. impl PartialEq for fxsave64 { fn eq(&self, other: &fxsave64) -> bool { return {self.fx_fcw} == {other.fx_fcw} && {self.fx_fsw} == {other.fx_fsw} && {self.fx_ftw} == {other.fx_ftw} && {self.fx_fop} == {other.fx_fop} && {self.fx_rip} == {other.fx_rip} && {self.fx_rdp} == {other.fx_rdp} && {self.fx_mxcsr} == {other.fx_mxcsr} && {self.fx_mxcsr_mask} == {other.fx_mxcsr_mask} && {self.fx_st}.iter().zip({other.fx_st}.iter()).all(|(a,b)| a == b) && {self.fx_xmm}.iter().zip({other.fx_xmm}.iter()).all(|(a,b)| a == b) } } impl Eq for fxsave64 {} impl ::fmt::Debug for fxsave64 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fxsave64") .field("fx_fcw", &{self.fx_fcw}) .field("fx_fsw", &{self.fx_fsw}) .field("fx_ftw", &{self.fx_ftw}) .field("fx_fop", &{self.fx_fop}) .field("fx_rip", &{self.fx_rip}) .field("fx_rdp", &{self.fx_rdp}) .field("fx_mxcsr", &{self.fx_mxcsr}) .field("fx_mxcsr_mask", &{self.fx_mxcsr_mask}) // FIXME: .field("fx_st", &{self.fx_st}) // FIXME: .field("fx_xmm", &{self.fx_xmm}) .finish() } } impl ::hash::Hash for fxsave64 { fn hash(&self, state: &mut H) { {self.fx_fcw}.hash(state); {self.fx_fsw}.hash(state); {self.fx_ftw}.hash(state); {self.fx_fop}.hash(state); {self.fx_rip}.hash(state); {self.fx_rdp}.hash(state); {self.fx_mxcsr}.hash(state); {self.fx_mxcsr_mask}.hash(state); {self.fx_st}.hash(state); {self.fx_xmm}.hash(state); } } } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const _MAX_PAGE_SHIFT: u32 = 12; pub const PT_STEP: ::c_int = PT_FIRSTMACH + 0; pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 4; libc/src/unix/bsd/netbsdlike/openbsd/mod.rs0000644000175000017500000022277314661133735021714 0ustar jamespagejamespageuse unix::bsd::O_SYNC; pub type clock_t = i64; pub type suseconds_t = ::c_long; pub type dev_t = i32; pub type sigset_t = ::c_uint; pub type blksize_t = i32; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = ::c_uint; pub type pthread_attr_t = *mut ::c_void; pub type pthread_mutex_t = *mut ::c_void; pub type pthread_mutexattr_t = *mut ::c_void; pub type pthread_cond_t = *mut ::c_void; pub type pthread_condattr_t = *mut ::c_void; pub type pthread_rwlock_t = *mut ::c_void; pub type pthread_rwlockattr_t = *mut ::c_void; pub type pthread_spinlock_t = ::uintptr_t; pub type caddr_t = *mut ::c_char; // elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Lword = u64; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Lword = u64; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; // search.h pub type ENTRY = entry; pub type ACTION = ::c_uint; // spawn.h pub type posix_spawnattr_t = *mut ::c_void; pub type posix_spawn_file_actions_t = *mut ::c_void; cfg_if! { if #[cfg(target_pointer_width = "64")] { type Elf_Addr = Elf64_Addr; type Elf_Half = Elf64_Half; type Elf_Phdr = Elf64_Phdr; } else if #[cfg(target_pointer_width = "32")] { type Elf_Addr = Elf32_Addr; type Elf_Half = Elf32_Half; type Elf_Phdr = Elf32_Phdr; } } s! { pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::c_int, } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_matchc: ::size_t, pub gl_offs: ::size_t, pub gl_flags: ::c_int, pub gl_pathv: *mut *mut ::c_char, __unused1: *mut ::c_void, __unused2: *mut ::c_void, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, __unused6: *mut ::c_void, __unused7: *mut ::c_void, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct ufs_args { pub fspec: *mut ::c_char, pub export_info: export_args, } pub struct mfs_args { pub fspec: *mut ::c_char, pub export_info: export_args, // https://github.com/openbsd/src/blob/HEAD/sys/sys/types.h#L134 pub base: *mut ::c_char, pub size: ::c_ulong, } pub struct iso_args { pub fspec: *mut ::c_char, pub export_info: export_args, pub flags: ::c_int, pub sess: ::c_int, } pub struct nfs_args { pub version: ::c_int, pub addr: *mut ::sockaddr, pub addrlen: ::c_int, pub sotype: ::c_int, pub proto: ::c_int, pub fh: *mut ::c_uchar, pub fhsize: ::c_int, pub flags: ::c_int, pub wsize: ::c_int, pub rsize: ::c_int, pub readdirsize: ::c_int, pub timeo: ::c_int, pub retrans: ::c_int, pub maxgrouplist: ::c_int, pub readahead: ::c_int, pub leaseterm: ::c_int, pub deadthresh: ::c_int, pub hostname: *mut ::c_char, pub acregmin: ::c_int, pub acregmax: ::c_int, pub acdirmin: ::c_int, pub acdirmax: ::c_int, } pub struct msdosfs_args { pub fspec: *mut ::c_char, pub export_info: export_args, pub uid: ::uid_t, pub gid: ::gid_t, pub mask: ::mode_t, pub flags: ::c_int, } pub struct ntfs_args { pub fspec: *mut ::c_char, pub export_info: export_args, pub uid: ::uid_t, pub gid: ::gid_t, pub mode: ::mode_t, pub flag: ::c_ulong, } pub struct udf_args { pub fspec: *mut ::c_char, pub lastblock: u32, } pub struct tmpfs_args { pub ta_version: ::c_int, pub ta_nodes_max: ::ino_t, pub ta_size_max: ::off_t, pub ta_root_uid: ::uid_t, pub ta_root_gid: ::gid_t, pub ta_root_mode: ::mode_t, } pub struct fusefs_args { pub name: *mut ::c_char, pub fd: ::c_int, pub max_read: ::c_int, pub allow_other: ::c_int, } pub struct xucred { pub cr_uid: ::uid_t, pub cr_gid: ::gid_t, pub cr_ngroups: ::c_short, //https://github.com/openbsd/src/blob/HEAD/sys/sys/syslimits.h#L44 pub cr_groups: [::gid_t; 16], } pub struct export_args { pub ex_flags: ::c_int, pub ex_root: ::uid_t, pub ex_anon: xucred, pub ex_addr: *mut ::sockaddr, pub ex_addrlen: ::c_int, pub ex_mask: *mut ::sockaddr, pub ex_masklen: ::c_int, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [i8; 8], } pub struct splice { pub sp_fd: ::c_int, pub sp_max: ::off_t, pub sp_idle: ::timeval, } pub struct kevent { pub ident: ::uintptr_t, pub filter: ::c_short, pub flags: ::c_ushort, pub fflags: ::c_uint, pub data: i64, pub udata: *mut ::c_void, } pub struct stat { pub st_mode: ::mode_t, pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: u32, pub st_gen: u32, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: ::socklen_t, pub ai_addr: *mut ::sockaddr, pub ai_canonname: *mut ::c_char, pub ai_next: *mut ::addrinfo, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct if_data { pub ifi_type: ::c_uchar, pub ifi_addrlen: ::c_uchar, pub ifi_hdrlen: ::c_uchar, pub ifi_link_state: ::c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_rdomain: u32, pub ifi_baudrate: u64, pub ifi_ipackets: u64, pub ifi_ierrors: u64, pub ifi_opackets: u64, pub ifi_oerrors: u64, pub ifi_collisions: u64, pub ifi_ibytes: u64, pub ifi_obytes: u64, pub ifi_imcasts: u64, pub ifi_omcasts: u64, pub ifi_iqdrops: u64, pub ifi_oqdrops: u64, pub ifi_noproto: u64, pub ifi_capabilities: u32, pub ifi_lastchange: ::timeval, } pub struct if_msghdr { pub ifm_msglen: ::c_ushort, pub ifm_version: ::c_uchar, pub ifm_type: ::c_uchar, pub ifm_hdrlen: ::c_ushort, pub ifm_index: ::c_ushort, pub ifm_tableid: ::c_ushort, pub ifm_pad1: ::c_uchar, pub ifm_pad2: ::c_uchar, pub ifm_addrs: ::c_int, pub ifm_flags: ::c_int, pub ifm_xflags: ::c_int, pub ifm_data: if_data, } pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, pub sdl_index: ::c_ushort, pub sdl_type: ::c_uchar, pub sdl_nlen: ::c_uchar, pub sdl_alen: ::c_uchar, pub sdl_slen: ::c_uchar, pub sdl_data: [::c_char; 24], } pub struct sockpeercred { pub uid: ::uid_t, pub gid: ::gid_t, pub pid: ::pid_t, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::c_int, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::c_short, pub shm_atime: ::time_t, __shm_atimensec: c_long, pub shm_dtime: ::time_t, __shm_dtimensec: c_long, pub shm_ctime: ::time_t, __shm_ctimensec: c_long, pub shm_internal: *mut ::c_void, } // elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } // link.h pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, } // sys/sysctl.h pub struct kinfo_proc { pub p_forw: u64, pub p_back: u64, pub p_paddr: u64, pub p_addr: u64, pub p_fd: u64, pub p_stats: u64, pub p_limit: u64, pub p_vmspace: u64, pub p_sigacts: u64, pub p_sess: u64, pub p_tsess: u64, pub p_ru: u64, pub p_eflag: i32, pub p_exitsig: i32, pub p_flag: i32, pub p_pid: i32, pub p_ppid: i32, pub p_sid: i32, pub p__pgid: i32, pub p_tpgid: i32, pub p_uid: u32, pub p_ruid: u32, pub p_gid: u32, pub p_rgid: u32, pub p_groups: [u32; KI_NGROUPS as usize], pub p_ngroups: i16, pub p_jobc: i16, pub p_tdev: u32, pub p_estcpu: u32, pub p_rtime_sec: u32, pub p_rtime_usec: u32, pub p_cpticks: i32, pub p_pctcpu: u32, pub p_swtime: u32, pub p_slptime: u32, pub p_schedflags: i32, pub p_uticks: u64, pub p_sticks: u64, pub p_iticks: u64, pub p_tracep: u64, pub p_traceflag: i32, pub p_holdcnt: i32, pub p_siglist: i32, pub p_sigmask: u32, pub p_sigignore: u32, pub p_sigcatch: u32, pub p_stat: i8, pub p_priority: u8, pub p_usrpri: u8, pub p_nice: u8, pub p_xstat: u16, pub p_spare: u16, pub p_comm: [::c_char; KI_MAXCOMLEN as usize], pub p_wmesg: [::c_char; KI_WMESGLEN as usize], pub p_wchan: u64, pub p_login: [::c_char; KI_MAXLOGNAME as usize], pub p_vm_rssize: i32, pub p_vm_tsize: i32, pub p_vm_dsize: i32, pub p_vm_ssize: i32, pub p_uvalid: i64, pub p_ustart_sec: u64, pub p_ustart_usec: u32, pub p_uutime_sec: u32, pub p_uutime_usec: u32, pub p_ustime_sec: u32, pub p_ustime_usec: u32, pub p_uru_maxrss: u64, pub p_uru_ixrss: u64, pub p_uru_idrss: u64, pub p_uru_isrss: u64, pub p_uru_minflt: u64, pub p_uru_majflt: u64, pub p_uru_nswap: u64, pub p_uru_inblock: u64, pub p_uru_oublock: u64, pub p_uru_msgsnd: u64, pub p_uru_msgrcv: u64, pub p_uru_nsignals: u64, pub p_uru_nvcsw: u64, pub p_uru_nivcsw: u64, pub p_uctime_sec: u32, pub p_uctime_usec: u32, pub p_psflags: u32, pub p_acflag: u32, pub p_svuid: u32, pub p_svgid: u32, pub p_emul: [::c_char; KI_EMULNAMELEN as usize], pub p_rlim_rss_cur: u64, pub p_cpuid: u64, pub p_vm_map_size: u64, pub p_tid: i32, pub p_rtableid: u32, pub p_pledge: u64, pub p_name: [::c_char; KI_MAXCOMLEN as usize], } pub struct kinfo_vmentry { pub kve_start: ::c_ulong, pub kve_end: ::c_ulong, pub kve_guard: ::c_ulong, pub kve_fspace: ::c_ulong, pub kve_fspace_augment: ::c_ulong, pub kve_offset: u64, pub kve_wired_count: ::c_int, pub kve_etype: ::c_int, pub kve_protection: ::c_int, pub kve_max_protection: ::c_int, pub kve_advice: ::c_int, pub kve_inheritance: ::c_int, pub kve_flags: u8, } pub struct ptrace_state { pub pe_report_event: ::c_int, pub pe_other_pid: ::pid_t, pub pe_tid: ::pid_t, } pub struct ptrace_thread_state { pub pts_tid: ::pid_t, } // search.h pub struct entry { pub key: *mut ::c_char, pub data: *mut ::c_void, } pub struct ifreq { pub ifr_name: [::c_char; ::IFNAMSIZ], #[cfg(libc_union)] pub ifr_ifru: __c_anonymous_ifr_ifru, #[cfg(not(libc_union))] pub ifr_ifru: ::sockaddr, } pub struct tcp_info { pub tcpi_state: u8, pub __tcpi_ca_state: u8, pub __tcpi_retransmits: u8, pub __tcpi_probes: u8, pub __tcpi_backoff: u8, pub tcpi_options: u8, pub tcpi_snd_wscale: u8, pub tcpi_rcv_wscale: u8, pub tcpi_rto: u32, pub __tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub __tcpi_unacked: u32, pub __tcpi_sacked: u32, pub __tcpi_lost: u32, pub __tcpi_retrans: u32, pub __tcpi_fackets: u32, pub tcpi_last_data_sent: u32, pub tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub tcpi_last_ack_recv: u32, pub __tcpi_pmtu: u32, pub __tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub __tcpi_advmss: u32, pub __tcpi_reordering: u32, pub __tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_nxt: u32, pub tcpi_rcv_nxt: u32, pub tcpi_toe_tid: u32, pub tcpi_snd_rexmitpack: u32, pub tcpi_rcv_ooopack: u32, pub tcpi_snd_zerowin: u32, pub tcpi_rttmin: u32, pub tcpi_max_sndwnd: u32, pub tcpi_rcv_adv: u32, pub tcpi_rcv_up: u32, pub tcpi_snd_una: u32, pub tcpi_snd_up: u32, pub tcpi_snd_wl1: u32, pub tcpi_snd_wl2: u32, pub tcpi_snd_max: u32, pub tcpi_ts_recent: u32, pub tcpi_ts_recent_age: u32, pub tcpi_rfbuf_cnt: u32, pub tcpi_rfbuf_ts: u32, pub tcpi_so_rcv_sb_cc: u32, pub tcpi_so_rcv_sb_hiwat: u32, pub tcpi_so_rcv_sb_lowat: u32, pub tcpi_so_rcv_sb_wat: u32, pub tcpi_so_snd_sb_cc: u32, pub tcpi_so_snd_sb_hiwat: u32, pub tcpi_so_snd_sb_lowat: u32, pub tcpi_so_snd_sb_wat: u32, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_char { self.si_addr } pub unsafe fn si_code(&self) -> ::c_int { self.si_code } pub unsafe fn si_errno(&self) -> ::c_int { self.si_errno } pub unsafe fn si_pid(&self) -> ::pid_t { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_code: ::c_int, _si_errno: ::c_int, _pad: [::c_int; SI_PAD], _pid: ::pid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._pid } pub unsafe fn si_uid(&self) -> ::uid_t { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_code: ::c_int, _si_errno: ::c_int, _pad: [::c_int; SI_PAD], _pid: ::pid_t, _uid: ::uid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._uid } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_code: ::c_int, _si_errno: ::c_int, _pad: [::c_int; SI_PAD], _pid: ::pid_t, _uid: ::uid_t, value: ::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).value } } s_no_extra_traits! { pub struct dirent { pub d_fileno: ::ino_t, pub d_off: ::off_t, pub d_reclen: u16, pub d_type: u8, pub d_namlen: u8, __d_padding: [u8; 4], pub d_name: [::c_char; 256], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: ::sa_family_t, __ss_pad1: [u8; 6], __ss_pad2: i64, __ss_pad3: [u8; 240], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, pub si_addr: *mut ::c_char, #[cfg(target_pointer_width = "32")] __pad: [u8; 112], #[cfg(target_pointer_width = "64")] __pad: [u8; 108], } pub struct lastlog { ll_time: ::time_t, ll_line: [::c_char; UT_LINESIZE], ll_host: [::c_char; UT_HOSTSIZE], } pub struct utmp { pub ut_line: [::c_char; UT_LINESIZE], pub ut_name: [::c_char; UT_NAMESIZE], pub ut_host: [::c_char; UT_HOSTSIZE], pub ut_time: ::time_t, } pub union mount_info { pub ufs_args: ufs_args, pub mfs_args: mfs_args, pub nfs_args: nfs_args, pub iso_args: iso_args, pub msdosfs_args: msdosfs_args, pub ntfs_args: ntfs_args, pub tmpfs_args: tmpfs_args, align: [::c_char; 160], } #[cfg(libc_union)] pub union __c_anonymous_ifr_ifru { pub ifru_addr: ::sockaddr, pub ifru_dstaddr: ::sockaddr, pub ifru_broadaddr: ::sockaddr, pub ifru_flags: ::c_short, pub ifru_metric: ::c_int, pub ifru_vnetid: i64, pub ifru_media: u64, pub ifru_data: ::caddr_t, pub ifru_index: ::c_uint, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); } } impl PartialEq for siginfo_t { fn eq(&self, other: &siginfo_t) -> bool { self.si_signo == other.si_signo && self.si_code == other.si_code && self.si_errno == other.si_errno && self.si_addr == other.si_addr } } impl Eq for siginfo_t {} impl ::fmt::Debug for siginfo_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("siginfo_t") .field("si_signo", &self.si_signo) .field("si_code", &self.si_code) .field("si_errno", &self.si_errno) .field("si_addr", &self.si_addr) .finish() } } impl ::hash::Hash for siginfo_t { fn hash(&self, state: &mut H) { self.si_signo.hash(state); self.si_code.hash(state); self.si_errno.hash(state); self.si_addr.hash(state); } } impl PartialEq for lastlog { fn eq(&self, other: &lastlog) -> bool { self.ll_time == other.ll_time && self .ll_line .iter() .zip(other.ll_line.iter()) .all(|(a,b)| a == b) && self .ll_host .iter() .zip(other.ll_host.iter()) .all(|(a,b)| a == b) } } impl Eq for lastlog {} impl ::fmt::Debug for lastlog { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("lastlog") .field("ll_time", &self.ll_time) // FIXME: .field("ll_line", &self.ll_line) // FIXME: .field("ll_host", &self.ll_host) .finish() } } impl ::hash::Hash for lastlog { fn hash(&self, state: &mut H) { self.ll_time.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); } } impl PartialEq for utmp { fn eq(&self, other: &utmp) -> bool { self.ut_time == other.ut_time && self .ut_line .iter() .zip(other.ut_line.iter()) .all(|(a,b)| a == b) && self .ut_name .iter() .zip(other.ut_name.iter()) .all(|(a,b)| a == b) && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) } } impl Eq for utmp {} impl ::fmt::Debug for utmp { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmp") // FIXME: .field("ut_line", &self.ut_line) // FIXME: .field("ut_name", &self.ut_name) // FIXME: .field("ut_host", &self.ut_host) .field("ut_time", &self.ut_time) .finish() } } impl ::hash::Hash for utmp { fn hash(&self, state: &mut H) { self.ut_line.hash(state); self.ut_name.hash(state); self.ut_host.hash(state); self.ut_time.hash(state); } } impl PartialEq for mount_info { fn eq(&self, other: &mount_info) -> bool { unsafe { self.align .iter() .zip(other.align.iter()) .all(|(a,b)| a == b) } } } impl Eq for mount_info { } impl ::fmt::Debug for mount_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mount_info") // FIXME: .field("align", &self.align) .finish() } } impl ::hash::Hash for mount_info { fn hash(&self, state: &mut H) { unsafe { self.align.hash(state) }; } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifr_ifru { fn eq(&self, other: &__c_anonymous_ifr_ifru) -> bool { unsafe { self.ifru_addr == other.ifru_addr && self.ifru_dstaddr == other.ifru_dstaddr && self.ifru_broadaddr == other.ifru_broadaddr && self.ifru_flags == other.ifru_flags && self.ifru_metric == other.ifru_metric && self.ifru_vnetid == other.ifru_vnetid && self.ifru_media == other.ifru_media && self.ifru_data == other.ifru_data && self.ifru_index == other.ifru_index } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifr_ifru {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifr_ifru { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__c_anonymous_ifr_ifru") .field("ifru_addr", unsafe { &self.ifru_addr }) .field("ifru_dstaddr", unsafe { &self.ifru_dstaddr }) .field("ifru_broadaddr", unsafe { &self.ifru_broadaddr }) .field("ifru_flags", unsafe { &self.ifru_flags }) .field("ifru_metric", unsafe { &self.ifru_metric }) .field("ifru_vnetid", unsafe { &self.ifru_vnetid }) .field("ifru_media", unsafe { &self.ifru_media }) .field("ifru_data", unsafe { &self.ifru_data }) .field("ifru_index", unsafe { &self.ifru_index }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifr_ifru { fn hash(&self, state: &mut H) { unsafe { self.ifru_addr.hash(state); self.ifru_dstaddr.hash(state); self.ifru_broadaddr.hash(state); self.ifru_flags.hash(state); self.ifru_metric.hash(state); self.ifru_vnetid.hash(state); self.ifru_media.hash(state); self.ifru_data.hash(state); self.ifru_index.hash(state); } } } } } cfg_if! { if #[cfg(libc_union)] { s_no_extra_traits! { // This type uses the union mount_info: pub struct statfs { pub f_flags: u32, pub f_bsize: u32, pub f_iosize: u32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: u64, pub f_favail: i64, pub f_syncwrites: u64, pub f_syncreads: u64, pub f_asyncwrites: u64, pub f_asyncreads: u64, pub f_fsid: ::fsid_t, pub f_namemax: u32, pub f_owner: ::uid_t, pub f_ctime: u64, pub f_fstypename: [::c_char; 16], pub f_mntonname: [::c_char; 90], pub f_mntfromname: [::c_char; 90], pub f_mntfromspec: [::c_char; 90], pub mount_info: mount_info, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_favail == other.f_favail && self.f_syncwrites == other.f_syncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncwrites == other.f_asyncwrites && self.f_asyncreads == other.f_asyncreads && self.f_fsid == other.f_fsid && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_ctime == other.f_ctime && self.f_fstypename .iter() .zip(other.f_fstypename.iter()) .all(|(a,b)| a == b) && self.f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) && self.f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) && self.f_mntfromspec .iter() .zip(other.f_mntfromspec.iter()) .all(|(a,b)| a == b) && self.mount_info == other.mount_info } } impl Eq for statfs { } impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_flags", &self.f_flags) .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_favail", &self.f_favail) .field("f_syncwrites", &self.f_syncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_asyncreads", &self.f_asyncreads) .field("f_fsid", &self.f_fsid) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_ctime", &self.f_ctime) // FIXME: .field("f_fstypename", &self.f_fstypename) // FIXME: .field("f_mntonname", &self.f_mntonname) // FIXME: .field("f_mntfromname", &self.f_mntfromname) // FIXME: .field("f_mntfromspec", &self.f_mntfromspec) .field("mount_info", &self.mount_info) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_favail.hash(state); self.f_syncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncwrites.hash(state); self.f_asyncreads.hash(state); self.f_fsid.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_ctime.hash(state); self.f_fstypename.hash(state); self.f_mntonname.hash(state); self.f_mntfromname.hash(state); self.f_mntfromspec.hash(state); self.mount_info.hash(state); } } } } } } pub const UT_NAMESIZE: usize = 32; pub const UT_LINESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 256; pub const O_CLOEXEC: ::c_int = 0x10000; pub const O_DIRECTORY: ::c_int = 0x20000; pub const O_RSYNC: ::c_int = O_SYNC; pub const MS_SYNC: ::c_int = 0x0002; pub const MS_INVALIDATE: ::c_int = 0x0004; pub const POLLNORM: ::c_short = ::POLLRDNORM; pub const ENOATTR: ::c_int = 83; pub const EILSEQ: ::c_int = 84; pub const EOVERFLOW: ::c_int = 87; pub const ECANCELED: ::c_int = 88; pub const EIDRM: ::c_int = 89; pub const ENOMSG: ::c_int = 90; pub const ENOTSUP: ::c_int = 91; pub const EBADMSG: ::c_int = 92; pub const ENOTRECOVERABLE: ::c_int = 93; pub const EOWNERDEAD: ::c_int = 94; pub const EPROTO: ::c_int = 95; pub const ELAST: ::c_int = 95; pub const F_DUPFD_CLOEXEC: ::c_int = 10; pub const UTIME_OMIT: c_long = -1; pub const UTIME_NOW: c_long = -2; pub const AT_FDCWD: ::c_int = -100; pub const AT_EACCESS: ::c_int = 0x01; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x02; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x04; pub const AT_REMOVEDIR: ::c_int = 0x08; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 9; pub const SO_TIMESTAMP: ::c_int = 0x0800; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_BINDANY: ::c_int = 0x1000; pub const SO_NETPROC: ::c_int = 0x1020; pub const SO_RTABLE: ::c_int = 0x1021; pub const SO_PEERCRED: ::c_int = 0x1022; pub const SO_SPLICE: ::c_int = 0x1023; pub const SO_DOMAIN: ::c_int = 0x1024; pub const SO_PROTOCOL: ::c_int = 0x1025; // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: ::c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: ::c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: ::c_int = 3; /// for compatibility pub const IPPROTO_IPIP: ::c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: ::c_int = 8; /// pup pub const IPPROTO_PUP: ::c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: ::c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: ::c_int = 29; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: ::c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: ::c_int = 44; /// resource reservation pub const IPPROTO_RSVP: ::c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: ::c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: ::c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: ::c_int = 51; /// IP Mobility RFC 2004 pub const IPPROTO_MOBILE: ::c_int = 55; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: ::c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: ::c_int = 60; /// ISO cnlp pub const IPPROTO_EON: ::c_int = 80; /// Ethernet-in-IP pub const IPPROTO_ETHERIP: ::c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: ::c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: ::c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_IPCOMP: ::c_int = 108; /// CARP pub const IPPROTO_CARP: ::c_int = 112; /// unicast MPLS packet pub const IPPROTO_MPLS: ::c_int = 137; /// PFSYNC pub const IPPROTO_PFSYNC: ::c_int = 240; pub const IPPROTO_MAX: ::c_int = 256; // Only used internally, so it can be outside the range of valid IP protocols pub const IPPROTO_DIVERT: ::c_int = 258; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_SENDSRCADDR: ::c_int = IP_RECVDSTADDR; pub const IP_RECVIF: ::c_int = 30; // sys/netinet/in.h pub const TCP_MD5SIG: ::c_int = 0x04; pub const TCP_NOPUSH: ::c_int = 0x10; pub const MSG_WAITFORONE: ::c_int = 0x1000; pub const AF_ECMA: ::c_int = 8; pub const AF_ROUTE: ::c_int = 17; pub const AF_ENCAP: ::c_int = 28; pub const AF_SIP: ::c_int = 29; pub const AF_KEY: ::c_int = 30; pub const pseudo_AF_HDRCMPLT: ::c_int = 31; pub const AF_BLUETOOTH: ::c_int = 32; pub const AF_MPLS: ::c_int = 33; pub const pseudo_AF_PFLOW: ::c_int = 34; pub const pseudo_AF_PIPEX: ::c_int = 35; pub const NET_RT_DUMP: ::c_int = 1; pub const NET_RT_FLAGS: ::c_int = 2; pub const NET_RT_IFLIST: ::c_int = 3; pub const NET_RT_STATS: ::c_int = 4; pub const NET_RT_TABLE: ::c_int = 5; pub const NET_RT_IFNAMES: ::c_int = 6; #[doc(hidden)] #[deprecated( since = "0.2.95", note = "Possibly increasing over the releases and might not be so used in the field" )] pub const NET_RT_MAXID: ::c_int = 7; pub const IPV6_JOIN_GROUP: ::c_int = 12; pub const IPV6_LEAVE_GROUP: ::c_int = 13; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_ECMA: ::c_int = AF_ECMA; pub const PF_ENCAP: ::c_int = AF_ENCAP; pub const PF_SIP: ::c_int = AF_SIP; pub const PF_KEY: ::c_int = AF_KEY; pub const PF_BPF: ::c_int = pseudo_AF_HDRCMPLT; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const PF_MPLS: ::c_int = AF_MPLS; pub const PF_PFLOW: ::c_int = pseudo_AF_PFLOW; pub const PF_PIPEX: ::c_int = pseudo_AF_PIPEX; pub const SCM_TIMESTAMP: ::c_int = 0x04; pub const O_DSYNC: ::c_int = 128; pub const MAP_RENAME: ::c_int = 0x0000; pub const MAP_NORESERVE: ::c_int = 0x0000; pub const MAP_HASSEMAPHORE: ::c_int = 0x0000; pub const MAP_TRYFIXED: ::c_int = 0; pub const EIPSEC: ::c_int = 82; pub const ENOMEDIUM: ::c_int = 85; pub const EMEDIUMTYPE: ::c_int = 86; pub const EAI_BADFLAGS: ::c_int = -1; pub const EAI_NONAME: ::c_int = -2; pub const EAI_AGAIN: ::c_int = -3; pub const EAI_FAIL: ::c_int = -4; pub const EAI_NODATA: ::c_int = -5; pub const EAI_FAMILY: ::c_int = -6; pub const EAI_SOCKTYPE: ::c_int = -7; pub const EAI_SERVICE: ::c_int = -8; pub const EAI_MEMORY: ::c_int = -10; pub const EAI_SYSTEM: ::c_int = -11; pub const EAI_OVERFLOW: ::c_int = -14; pub const RUSAGE_THREAD: ::c_int = 1; pub const MAP_COPY: ::c_int = 0x0002; pub const MAP_NOEXTEND: ::c_int = 0x0000; pub const _PC_LINK_MAX: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_CHOWN_RESTRICTED: ::c_int = 7; pub const _PC_NO_TRUNC: ::c_int = 8; pub const _PC_VDISABLE: ::c_int = 9; pub const _PC_2_SYMLINKS: ::c_int = 10; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 11; pub const _PC_ASYNC_IO: ::c_int = 12; pub const _PC_FILESIZEBITS: ::c_int = 13; pub const _PC_PRIO_IO: ::c_int = 14; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 16; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 17; pub const _PC_REC_XFER_ALIGN: ::c_int = 18; pub const _PC_SYMLINK_MAX: ::c_int = 19; pub const _PC_SYNC_IO: ::c_int = 20; pub const _PC_TIMESTAMP_RESOLUTION: ::c_int = 21; pub const _SC_CLK_TCK: ::c_int = 3; pub const _SC_SEM_NSEMS_MAX: ::c_int = 31; pub const _SC_SEM_VALUE_MAX: ::c_int = 32; pub const _SC_HOST_NAME_MAX: ::c_int = 33; pub const _SC_MONOTONIC_CLOCK: ::c_int = 34; pub const _SC_2_PBS: ::c_int = 35; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 36; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 37; pub const _SC_2_PBS_LOCATE: ::c_int = 38; pub const _SC_2_PBS_MESSAGE: ::c_int = 39; pub const _SC_2_PBS_TRACK: ::c_int = 40; pub const _SC_ADVISORY_INFO: ::c_int = 41; pub const _SC_AIO_LISTIO_MAX: ::c_int = 42; pub const _SC_AIO_MAX: ::c_int = 43; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 44; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 45; pub const _SC_ATEXIT_MAX: ::c_int = 46; pub const _SC_BARRIERS: ::c_int = 47; pub const _SC_CLOCK_SELECTION: ::c_int = 48; pub const _SC_CPUTIME: ::c_int = 49; pub const _SC_DELAYTIMER_MAX: ::c_int = 50; pub const _SC_IOV_MAX: ::c_int = 51; pub const _SC_IPV6: ::c_int = 52; pub const _SC_MAPPED_FILES: ::c_int = 53; pub const _SC_MEMLOCK: ::c_int = 54; pub const _SC_MEMLOCK_RANGE: ::c_int = 55; pub const _SC_MEMORY_PROTECTION: ::c_int = 56; pub const _SC_MESSAGE_PASSING: ::c_int = 57; pub const _SC_MQ_OPEN_MAX: ::c_int = 58; pub const _SC_MQ_PRIO_MAX: ::c_int = 59; pub const _SC_PRIORITIZED_IO: ::c_int = 60; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 61; pub const _SC_RAW_SOCKETS: ::c_int = 62; pub const _SC_READER_WRITER_LOCKS: ::c_int = 63; pub const _SC_REALTIME_SIGNALS: ::c_int = 64; pub const _SC_REGEXP: ::c_int = 65; pub const _SC_RTSIG_MAX: ::c_int = 66; pub const _SC_SEMAPHORES: ::c_int = 67; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 68; pub const _SC_SHELL: ::c_int = 69; pub const _SC_SIGQUEUE_MAX: ::c_int = 70; pub const _SC_SPAWN: ::c_int = 71; pub const _SC_SPIN_LOCKS: ::c_int = 72; pub const _SC_SPORADIC_SERVER: ::c_int = 73; pub const _SC_SS_REPL_MAX: ::c_int = 74; pub const _SC_SYNCHRONIZED_IO: ::c_int = 75; pub const _SC_SYMLOOP_MAX: ::c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 78; pub const _SC_THREAD_CPUTIME: ::c_int = 79; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 80; pub const _SC_THREAD_KEYS_MAX: ::c_int = 81; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 82; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 83; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 84; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 85; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 86; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 87; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 88; pub const _SC_THREAD_STACK_MIN: ::c_int = 89; pub const _SC_THREAD_THREADS_MAX: ::c_int = 90; pub const _SC_THREADS: ::c_int = 91; pub const _SC_TIMEOUTS: ::c_int = 92; pub const _SC_TIMER_MAX: ::c_int = 93; pub const _SC_TIMERS: ::c_int = 94; pub const _SC_TRACE: ::c_int = 95; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 96; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 97; pub const _SC_TRACE_INHERIT: ::c_int = 98; pub const _SC_TRACE_LOG: ::c_int = 99; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 100; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 101; pub const _SC_LOGIN_NAME_MAX: ::c_int = 102; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 103; pub const _SC_TRACE_NAME_MAX: ::c_int = 104; pub const _SC_TRACE_SYS_MAX: ::c_int = 105; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 106; pub const _SC_TTY_NAME_MAX: ::c_int = 107; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 108; pub const _SC_V6_ILP32_OFF32: ::c_int = 109; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 110; pub const _SC_V6_LP64_OFF64: ::c_int = 111; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 112; pub const _SC_V7_ILP32_OFF32: ::c_int = 113; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 114; pub const _SC_V7_LP64_OFF64: ::c_int = 115; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 116; pub const _SC_XOPEN_CRYPT: ::c_int = 117; pub const _SC_XOPEN_ENH_I18N: ::c_int = 118; pub const _SC_XOPEN_LEGACY: ::c_int = 119; pub const _SC_XOPEN_REALTIME: ::c_int = 120; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 121; pub const _SC_XOPEN_STREAMS: ::c_int = 122; pub const _SC_XOPEN_UNIX: ::c_int = 123; pub const _SC_XOPEN_UUCP: ::c_int = 124; pub const _SC_XOPEN_VERSION: ::c_int = 125; pub const _SC_PHYS_PAGES: ::c_int = 500; pub const _SC_AVPHYS_PAGES: ::c_int = 501; pub const _SC_NPROCESSORS_CONF: ::c_int = 502; pub const _SC_NPROCESSORS_ONLN: ::c_int = 503; pub const FD_SETSIZE: usize = 1024; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_OTHER: ::c_int = 2; pub const SCHED_RR: ::c_int = 3; pub const ST_NOSUID: ::c_ulong = 2; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 0 as *mut _; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 0 as *mut _; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 0 as *mut _; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 3; pub const PTHREAD_MUTEX_STRICT_NP: ::c_int = 4; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_STRICT_NP; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_DEVICE: i16 = -8; pub const EVFILT_EXCEPT: i16 = -9; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_FLAG1: u16 = 0x2000; pub const EV_ERROR: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; #[deprecated(since = "0.2.113", note = "Not stable across OS versions")] pub const EV_SYSFLAGS: u16 = 0xf800; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_EOF: u32 = 0x00000002; pub const NOTE_OOB: u32 = 0x00000004; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_TRUNCATE: u32 = 0x00000080; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const NOTE_CHANGE: u32 = 0x00000001; pub const TMP_MAX: ::c_uint = 0x7fffffff; pub const AI_PASSIVE: ::c_int = 1; pub const AI_CANONNAME: ::c_int = 2; pub const AI_NUMERICHOST: ::c_int = 4; pub const AI_EXT: ::c_int = 8; pub const AI_NUMERICSERV: ::c_int = 16; pub const AI_FQDN: ::c_int = 32; pub const AI_ADDRCONFIG: ::c_int = 64; pub const NI_NUMERICHOST: ::c_int = 1; pub const NI_NUMERICSERV: ::c_int = 2; pub const NI_NOFQDN: ::c_int = 4; pub const NI_NAMEREQD: ::c_int = 8; pub const NI_DGRAM: ::c_int = 16; pub const NI_MAXHOST: ::size_t = 256; pub const RTLD_LOCAL: ::c_int = 0; pub const CTL_MAXNAME: ::c_int = 12; pub const CTLTYPE_NODE: ::c_int = 1; pub const CTLTYPE_INT: ::c_int = 2; pub const CTLTYPE_STRING: ::c_int = 3; pub const CTLTYPE_QUAD: ::c_int = 4; pub const CTLTYPE_STRUCT: ::c_int = 5; pub const CTL_UNSPEC: ::c_int = 0; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_FS: ::c_int = 3; pub const CTL_NET: ::c_int = 4; pub const CTL_DEBUG: ::c_int = 5; pub const CTL_HW: ::c_int = 6; pub const CTL_MACHDEP: ::c_int = 7; pub const CTL_DDB: ::c_int = 9; pub const CTL_VFS: ::c_int = 10; pub const CTL_MAXID: ::c_int = 11; pub const HW_NCPUONLINE: ::c_int = 25; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_VERSION: ::c_int = 4; pub const KERN_MAXVNODES: ::c_int = 5; pub const KERN_MAXPROC: ::c_int = 6; pub const KERN_MAXFILES: ::c_int = 7; pub const KERN_ARGMAX: ::c_int = 8; pub const KERN_SECURELVL: ::c_int = 9; pub const KERN_HOSTNAME: ::c_int = 10; pub const KERN_HOSTID: ::c_int = 11; pub const KERN_CLOCKRATE: ::c_int = 12; pub const KERN_PROF: ::c_int = 16; pub const KERN_POSIX1: ::c_int = 17; pub const KERN_NGROUPS: ::c_int = 18; pub const KERN_JOB_CONTROL: ::c_int = 19; pub const KERN_SAVED_IDS: ::c_int = 20; pub const KERN_BOOTTIME: ::c_int = 21; pub const KERN_DOMAINNAME: ::c_int = 22; pub const KERN_MAXPARTITIONS: ::c_int = 23; pub const KERN_RAWPARTITION: ::c_int = 24; pub const KERN_MAXTHREAD: ::c_int = 25; pub const KERN_NTHREADS: ::c_int = 26; pub const KERN_OSVERSION: ::c_int = 27; pub const KERN_SOMAXCONN: ::c_int = 28; pub const KERN_SOMINCONN: ::c_int = 29; #[deprecated(since = "0.2.71", note = "Removed in OpenBSD 6.0")] pub const KERN_USERMOUNT: ::c_int = 30; pub const KERN_NOSUIDCOREDUMP: ::c_int = 32; pub const KERN_FSYNC: ::c_int = 33; pub const KERN_SYSVMSG: ::c_int = 34; pub const KERN_SYSVSEM: ::c_int = 35; pub const KERN_SYSVSHM: ::c_int = 36; #[deprecated(since = "0.2.71", note = "Removed in OpenBSD 6.0")] pub const KERN_ARND: ::c_int = 37; pub const KERN_MSGBUFSIZE: ::c_int = 38; pub const KERN_MALLOCSTATS: ::c_int = 39; pub const KERN_CPTIME: ::c_int = 40; pub const KERN_NCHSTATS: ::c_int = 41; pub const KERN_FORKSTAT: ::c_int = 42; pub const KERN_NSELCOLL: ::c_int = 43; pub const KERN_TTY: ::c_int = 44; pub const KERN_CCPU: ::c_int = 45; pub const KERN_FSCALE: ::c_int = 46; pub const KERN_NPROCS: ::c_int = 47; pub const KERN_MSGBUF: ::c_int = 48; pub const KERN_POOL: ::c_int = 49; pub const KERN_STACKGAPRANDOM: ::c_int = 50; pub const KERN_SYSVIPC_INFO: ::c_int = 51; pub const KERN_SPLASSERT: ::c_int = 54; pub const KERN_PROC_ARGS: ::c_int = 55; pub const KERN_NFILES: ::c_int = 56; pub const KERN_TTYCOUNT: ::c_int = 57; pub const KERN_NUMVNODES: ::c_int = 58; pub const KERN_MBSTAT: ::c_int = 59; pub const KERN_SEMINFO: ::c_int = 61; pub const KERN_SHMINFO: ::c_int = 62; pub const KERN_INTRCNT: ::c_int = 63; pub const KERN_WATCHDOG: ::c_int = 64; pub const KERN_PROC: ::c_int = 66; pub const KERN_MAXCLUSTERS: ::c_int = 67; pub const KERN_EVCOUNT: ::c_int = 68; pub const KERN_TIMECOUNTER: ::c_int = 69; pub const KERN_MAXLOCKSPERUID: ::c_int = 70; pub const KERN_CPTIME2: ::c_int = 71; pub const KERN_CACHEPCT: ::c_int = 72; pub const KERN_FILE: ::c_int = 73; pub const KERN_CONSDEV: ::c_int = 75; pub const KERN_NETLIVELOCKS: ::c_int = 76; pub const KERN_POOL_DEBUG: ::c_int = 77; pub const KERN_PROC_CWD: ::c_int = 78; pub const KERN_PROC_NOBROADCASTKILL: ::c_int = 79; pub const KERN_PROC_VMMAP: ::c_int = 80; pub const KERN_GLOBAL_PTRACE: ::c_int = 81; pub const KERN_CONSBUFSIZE: ::c_int = 82; pub const KERN_CONSBUF: ::c_int = 83; pub const KERN_AUDIO: ::c_int = 84; pub const KERN_CPUSTATS: ::c_int = 85; pub const KERN_PFSTATUS: ::c_int = 86; pub const KERN_TIMEOUT_STATS: ::c_int = 87; #[deprecated( since = "0.2.95", note = "Possibly increasing over the releases and might not be so used in the field" )] pub const KERN_MAXID: ::c_int = 88; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_PID: ::c_int = 1; pub const KERN_PROC_PGRP: ::c_int = 2; pub const KERN_PROC_SESSION: ::c_int = 3; pub const KERN_PROC_TTY: ::c_int = 4; pub const KERN_PROC_UID: ::c_int = 5; pub const KERN_PROC_RUID: ::c_int = 6; pub const KERN_PROC_KTHREAD: ::c_int = 7; pub const KERN_PROC_SHOW_THREADS: ::c_int = 0x40000000; pub const KERN_SYSVIPC_MSG_INFO: ::c_int = 1; pub const KERN_SYSVIPC_SEM_INFO: ::c_int = 2; pub const KERN_SYSVIPC_SHM_INFO: ::c_int = 3; pub const KERN_PROC_ARGV: ::c_int = 1; pub const KERN_PROC_NARGV: ::c_int = 2; pub const KERN_PROC_ENV: ::c_int = 3; pub const KERN_PROC_NENV: ::c_int = 4; pub const KI_NGROUPS: ::c_int = 16; pub const KI_MAXCOMLEN: ::c_int = 24; pub const KI_WMESGLEN: ::c_int = 8; pub const KI_MAXLOGNAME: ::c_int = 32; pub const KI_EMULNAMELEN: ::c_int = 8; pub const KVE_ET_OBJ: ::c_int = 0x00000001; pub const KVE_ET_SUBMAP: ::c_int = 0x00000002; pub const KVE_ET_COPYONWRITE: ::c_int = 0x00000004; pub const KVE_ET_NEEDSCOPY: ::c_int = 0x00000008; pub const KVE_ET_HOLE: ::c_int = 0x00000010; pub const KVE_ET_NOFAULT: ::c_int = 0x00000020; pub const KVE_ET_STACK: ::c_int = 0x00000040; pub const KVE_ET_WC: ::c_int = 0x000000080; pub const KVE_ET_CONCEAL: ::c_int = 0x000000100; pub const KVE_ET_SYSCALL: ::c_int = 0x000000200; pub const KVE_ET_FREEMAPPED: ::c_int = 0x000000800; pub const KVE_PROT_NONE: ::c_int = 0x00000000; pub const KVE_PROT_READ: ::c_int = 0x00000001; pub const KVE_PROT_WRITE: ::c_int = 0x00000002; pub const KVE_PROT_EXEC: ::c_int = 0x00000004; pub const KVE_ADV_NORMAL: ::c_int = 0x00000000; pub const KVE_ADV_RANDOM: ::c_int = 0x00000001; pub const KVE_ADV_SEQUENTIAL: ::c_int = 0x00000002; pub const KVE_INH_SHARE: ::c_int = 0x00000000; pub const KVE_INH_COPY: ::c_int = 0x00000010; pub const KVE_INH_NONE: ::c_int = 0x00000020; pub const KVE_INH_ZERO: ::c_int = 0x00000030; pub const KVE_F_STATIC: ::c_int = 0x1; pub const KVE_F_KMEM: ::c_int = 0x2; pub const CHWFLOW: ::tcflag_t = ::MDMBUF | ::CRTSCTS; pub const OLCUC: ::tcflag_t = 0x20; pub const ONOCR: ::tcflag_t = 0x40; pub const ONLRET: ::tcflag_t = 0x80; //https://github.com/openbsd/src/blob/HEAD/sys/sys/mount.h pub const ISOFSMNT_NORRIP: ::c_int = 0x1; // disable Rock Ridge Ext pub const ISOFSMNT_GENS: ::c_int = 0x2; // enable generation numbers pub const ISOFSMNT_EXTATT: ::c_int = 0x4; // enable extended attr pub const ISOFSMNT_NOJOLIET: ::c_int = 0x8; // disable Joliet Ext pub const ISOFSMNT_SESS: ::c_int = 0x10; // use iso_args.sess pub const NFS_ARGSVERSION: ::c_int = 4; // change when nfs_args changes pub const NFSMNT_RESVPORT: ::c_int = 0; // always use reserved ports pub const NFSMNT_SOFT: ::c_int = 0x1; // soft mount (hard is default) pub const NFSMNT_WSIZE: ::c_int = 0x2; // set write size pub const NFSMNT_RSIZE: ::c_int = 0x4; // set read size pub const NFSMNT_TIMEO: ::c_int = 0x8; // set initial timeout pub const NFSMNT_RETRANS: ::c_int = 0x10; // set number of request retries pub const NFSMNT_MAXGRPS: ::c_int = 0x20; // set maximum grouplist size pub const NFSMNT_INT: ::c_int = 0x40; // allow interrupts on hard mount pub const NFSMNT_NOCONN: ::c_int = 0x80; // Don't Connect the socket pub const NFSMNT_NQNFS: ::c_int = 0x100; // Use Nqnfs protocol pub const NFSMNT_NFSV3: ::c_int = 0x200; // Use NFS Version 3 protocol pub const NFSMNT_KERB: ::c_int = 0x400; // Use Kerberos authentication pub const NFSMNT_DUMBTIMR: ::c_int = 0x800; // Don't estimate rtt dynamically pub const NFSMNT_LEASETERM: ::c_int = 0x1000; // set lease term (nqnfs) pub const NFSMNT_READAHEAD: ::c_int = 0x2000; // set read ahead pub const NFSMNT_DEADTHRESH: ::c_int = 0x4000; // set dead server retry thresh pub const NFSMNT_NOAC: ::c_int = 0x8000; // disable attribute cache pub const NFSMNT_RDIRPLUS: ::c_int = 0x10000; // Use Readdirplus for V3 pub const NFSMNT_READDIRSIZE: ::c_int = 0x20000; // Set readdir size /* Flags valid only in mount syscall arguments */ pub const NFSMNT_ACREGMIN: ::c_int = 0x40000; // acregmin field valid pub const NFSMNT_ACREGMAX: ::c_int = 0x80000; // acregmax field valid pub const NFSMNT_ACDIRMIN: ::c_int = 0x100000; // acdirmin field valid pub const NFSMNT_ACDIRMAX: ::c_int = 0x200000; // acdirmax field valid /* Flags valid only in kernel */ pub const NFSMNT_INTERNAL: ::c_int = 0xfffc0000; // Bits set internally pub const NFSMNT_HASWRITEVERF: ::c_int = 0x40000; // Has write verifier for V3 pub const NFSMNT_GOTPATHCONF: ::c_int = 0x80000; // Got the V3 pathconf info pub const NFSMNT_GOTFSINFO: ::c_int = 0x100000; // Got the V3 fsinfo pub const NFSMNT_MNTD: ::c_int = 0x200000; // Mnt server for mnt point pub const NFSMNT_DISMINPROG: ::c_int = 0x400000; // Dismount in progress pub const NFSMNT_DISMNT: ::c_int = 0x800000; // Dismounted pub const NFSMNT_SNDLOCK: ::c_int = 0x1000000; // Send socket lock pub const NFSMNT_WANTSND: ::c_int = 0x2000000; // Want above pub const NFSMNT_RCVLOCK: ::c_int = 0x4000000; // Rcv socket lock pub const NFSMNT_WANTRCV: ::c_int = 0x8000000; // Want above pub const NFSMNT_WAITAUTH: ::c_int = 0x10000000; // Wait for authentication pub const NFSMNT_HASAUTH: ::c_int = 0x20000000; // Has authenticator pub const NFSMNT_WANTAUTH: ::c_int = 0x40000000; // Wants an authenticator pub const NFSMNT_AUTHERR: ::c_int = 0x80000000; // Authentication error pub const MSDOSFSMNT_SHORTNAME: ::c_int = 0x1; // Force old DOS short names only pub const MSDOSFSMNT_LONGNAME: ::c_int = 0x2; // Force Win'95 long names pub const MSDOSFSMNT_NOWIN95: ::c_int = 0x4; // Completely ignore Win95 entries pub const NTFS_MFLAG_CASEINS: ::c_int = 0x1; pub const NTFS_MFLAG_ALLNAMES: ::c_int = 0x2; pub const TMPFS_ARGS_VERSION: ::c_int = 1; const SI_MAXSZ: ::size_t = 128; const SI_PAD: ::size_t = (SI_MAXSZ / ::mem::size_of::<::c_int>()) - 3; pub const MAP_STACK: ::c_int = 0x4000; pub const MAP_CONCEAL: ::c_int = 0x8000; // https://github.com/openbsd/src/blob/HEAD/sys/net/if.h#L187 pub const IFF_UP: ::c_int = 0x1; // interface is up pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link pub const IFF_STATICARP: ::c_int = 0x20; // only static ARP pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE: ::c_int = 0x400; // transmission in progress pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast pub const PTHREAD_STACK_MIN: ::size_t = 1_usize << _MAX_PAGE_SHIFT; pub const MINSIGSTKSZ: ::size_t = 3_usize << _MAX_PAGE_SHIFT; pub const SIGSTKSZ: ::size_t = MINSIGSTKSZ + (1_usize << _MAX_PAGE_SHIFT) * 4; pub const PT_SET_EVENT_MASK: ::c_int = 12; pub const PT_GET_EVENT_MASK: ::c_int = 13; pub const PT_GET_PROCESS_STATE: ::c_int = 14; pub const PT_GET_THREAD_FIRST: ::c_int = 15; pub const PT_GET_THREAD_NEXT: ::c_int = 16; pub const PT_FIRSTMACH: ::c_int = 32; pub const SOCK_CLOEXEC: ::c_int = 0x8000; pub const SOCK_NONBLOCK: ::c_int = 0x4000; pub const SOCK_DNS: ::c_int = 0x1000; pub const BIOCGRSIG: ::c_ulong = 0x40044273; pub const BIOCSRSIG: ::c_ulong = 0x80044272; pub const BIOCSDLT: ::c_ulong = 0x8004427a; pub const PTRACE_FORK: ::c_int = 0x0002; pub const WCONTINUED: ::c_int = 0x08; pub const WEXITED: ::c_int = 0x04; pub const WSTOPPED: ::c_int = 0x02; // same as WUNTRACED pub const WNOWAIT: ::c_int = 0x10; pub const WTRAPPED: ::c_int = 0x20; pub const P_ALL: ::idtype_t = 0; pub const P_PGID: ::idtype_t = 1; pub const P_PID: ::idtype_t = 2; // search.h pub const FIND: ::ACTION = 0; pub const ENTER: ::ACTION = 1; // futex.h pub const FUTEX_WAIT: ::c_int = 1; pub const FUTEX_WAKE: ::c_int = 2; pub const FUTEX_REQUEUE: ::c_int = 3; pub const FUTEX_PRIVATE_FLAG: ::c_int = 128; // sysctl.h, kinfo_proc p_eflag constants pub const EPROC_CTTY: i32 = 0x01; // controlling tty vnode active pub const EPROC_SLEADER: i32 = 0x02; // session leader pub const EPROC_UNVEIL: i32 = 0x04; // has unveil settings pub const EPROC_LKUNVEIL: i32 = 0x08; // unveil is locked // Flags for chflags(2) pub const UF_SETTABLE: ::c_uint = 0x0000ffff; pub const UF_NODUMP: ::c_uint = 0x00000001; pub const UF_IMMUTABLE: ::c_uint = 0x00000002; pub const UF_APPEND: ::c_uint = 0x00000004; pub const UF_OPAQUE: ::c_uint = 0x00000008; pub const SF_SETTABLE: ::c_uint = 0xffff0000; pub const SF_ARCHIVED: ::c_uint = 0x00010000; pub const SF_IMMUTABLE: ::c_uint = 0x00020000; pub const SF_APPEND: ::c_uint = 0x00040000; // sys/exec_elf.h - Legal values for p_type (segment type). pub const PT_NULL: u32 = 0; pub const PT_LOAD: u32 = 1; pub const PT_DYNAMIC: u32 = 2; pub const PT_INTERP: u32 = 3; pub const PT_NOTE: u32 = 4; pub const PT_SHLIB: u32 = 5; pub const PT_PHDR: u32 = 6; pub const PT_TLS: u32 = 7; pub const PT_LOOS: u32 = 0x60000000; pub const PT_HIOS: u32 = 0x6fffffff; pub const PT_LOPROC: u32 = 0x70000000; pub const PT_HIPROC: u32 = 0x7fffffff; pub const PT_GNU_EH_FRAME: u32 = 0x6474e550; pub const PT_GNU_RELRO: u32 = 0x6474e552; // sys/exec_elf.h - Legal values for p_flags (segment flags). pub const PF_X: u32 = 0x1; pub const PF_W: u32 = 0x2; pub const PF_R: u32 = 0x4; pub const PF_MASKOS: u32 = 0x0ff00000; pub const PF_MASKPROC: u32 = 0xf0000000; // sys/mount.h pub const MNT_NOPERM: ::c_int = 0x00000020; pub const MNT_WXALLOWED: ::c_int = 0x00000800; pub const MNT_EXRDONLY: ::c_int = 0x00000080; pub const MNT_DEFEXPORTED: ::c_int = 0x00000200; pub const MNT_EXPORTANON: ::c_int = 0x00000400; pub const MNT_ROOTFS: ::c_int = 0x00004000; pub const MNT_NOATIME: ::c_int = 0x00008000; pub const MNT_DELEXPORT: ::c_int = 0x00020000; pub const MNT_STALLED: ::c_int = 0x00100000; pub const MNT_SWAPPABLE: ::c_int = 0x00200000; pub const MNT_WANTRDWR: ::c_int = 0x02000000; pub const MNT_SOFTDEP: ::c_int = 0x04000000; pub const MNT_DOOMED: ::c_int = 0x08000000; // For use with vfs_fsync and getfsstat pub const MNT_WAIT: ::c_int = 1; pub const MNT_NOWAIT: ::c_int = 2; pub const MNT_LAZY: ::c_int = 3; // sys/_time.h pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 2; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 4; pub const CLOCK_UPTIME: ::clockid_t = 5; pub const CLOCK_BOOTTIME: ::clockid_t = 6; pub const LC_COLLATE_MASK: ::c_int = 1 << ::LC_COLLATE; pub const LC_CTYPE_MASK: ::c_int = 1 << ::LC_CTYPE; pub const LC_MONETARY_MASK: ::c_int = 1 << ::LC_MONETARY; pub const LC_NUMERIC_MASK: ::c_int = 1 << ::LC_NUMERIC; pub const LC_TIME_MASK: ::c_int = 1 << ::LC_TIME; pub const LC_MESSAGES_MASK: ::c_int = 1 << ::LC_MESSAGES; const _LC_LAST: ::c_int = 7; pub const LC_ALL_MASK: ::c_int = (1 << _LC_LAST) - 2; pub const LC_GLOBAL_LOCALE: ::locale_t = -1isize as ::locale_t; // sys/reboot.h pub const RB_ASKNAME: ::c_int = 0x00001; pub const RB_SINGLE: ::c_int = 0x00002; pub const RB_NOSYNC: ::c_int = 0x00004; pub const RB_HALT: ::c_int = 0x00008; pub const RB_INITNAME: ::c_int = 0x00010; pub const RB_KDB: ::c_int = 0x00040; pub const RB_RDONLY: ::c_int = 0x00080; pub const RB_DUMP: ::c_int = 0x00100; pub const RB_MINIROOT: ::c_int = 0x00200; pub const RB_CONFIG: ::c_int = 0x00400; pub const RB_TIMEBAD: ::c_int = 0x00800; pub const RB_POWERDOWN: ::c_int = 0x01000; pub const RB_SERCONS: ::c_int = 0x02000; pub const RB_USERREQ: ::c_int = 0x04000; pub const RB_RESET: ::c_int = 0x08000; pub const RB_GOODRANDOM: ::c_int = 0x10000; pub const RB_UNHIBERNATE: ::c_int = 0x20000; const_fn! { {const} fn _ALIGN(p: usize) -> usize { (p + _ALIGNBYTES) & !_ALIGNBYTES } } f! { pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { _ALIGN(::mem::size_of::<::cmsghdr>()) as ::c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr) -> *mut ::cmsghdr { if cmsg.is_null() { return ::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize) + _ALIGN(::mem::size_of::<::cmsghdr>()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut ::cmsghdr } else { (cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize)) as *mut ::cmsghdr } } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_ALIGN(::mem::size_of::<::cmsghdr>()) + _ALIGN(length as usize)) as ::c_uint } pub fn major(dev: ::dev_t) -> ::c_uint{ ((dev as ::c_uint) >> 8) & 0xff } pub fn minor(dev: ::dev_t) -> ::c_uint { let dev = dev as ::c_uint; let mut res = 0; res |= (dev) & 0xff; res |= ((dev) & 0xffff0000) >> 8; res } } safe_f! { pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { status >> 8 } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0xff) == 0o177 } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { (status & 0o177777) == 0o177777 } pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= (major & 0xff) << 8; dev |= minor & 0xff; dev |= (minor & 0xffff00) << 8; dev } } extern "C" { pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn settimeofday(tp: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn pledge(promises: *const ::c_char, execpromises: *const ::c_char) -> ::c_int; pub fn unveil(path: *const ::c_char, permissions: *const ::c_char) -> ::c_int; pub fn strtonum( nptr: *const ::c_char, minval: ::c_longlong, maxval: ::c_longlong, errstr: *mut *const ::c_char, ) -> ::c_longlong; pub fn dup3(src: ::c_int, dst: ::c_int, flags: ::c_int) -> ::c_int; pub fn chflags(path: *const ::c_char, flags: ::c_uint) -> ::c_int; pub fn fchflags(fd: ::c_int, flags: ::c_uint) -> ::c_int; pub fn chflagsat( fd: ::c_int, path: *const ::c_char, flags: ::c_uint, atflag: ::c_int, ) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::size_t, serv: *mut ::c_char, servlen: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, sgid: *mut ::gid_t) -> ::c_int; pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, suid: *mut ::uid_t) -> ::c_int; pub fn kevent( kq: ::c_int, changelist: *const ::kevent, nchanges: ::c_int, eventlist: *mut ::kevent, nevents: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn getthrid() -> ::pid_t; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_main_np() -> ::c_int; pub fn pthread_get_name_np(tid: ::pthread_t, name: *mut ::c_char, len: ::size_t); pub fn pthread_set_name_np(tid: ::pthread_t, name: *const ::c_char); pub fn pthread_stackseg_np(thread: ::pthread_t, sinfo: *mut ::stack_t) -> ::c_int; pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *const ::termios, winp: *const ::winsize, ) -> ::c_int; pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *const ::termios, winp: *const ::winsize, ) -> ::pid_t; pub fn sysctl( name: *const ::c_int, namelen: ::c_uint, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: caddr_t, data: ::c_int) -> ::c_int; pub fn utrace(label: *const ::c_char, addr: *const ::c_void, len: ::size_t) -> ::c_int; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; // #include pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut dl_phdr_info, size: usize, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn duplocale(base: ::locale_t) -> ::locale_t; // Added in `OpenBSD` 5.5 pub fn explicit_bzero(s: *mut ::c_void, len: ::size_t); pub fn setproctitle(fmt: *const ::c_char, ...); pub fn freezero(ptr: *mut ::c_void, size: ::size_t); pub fn malloc_conceal(size: ::size_t) -> *mut ::c_void; pub fn calloc_conceal(nmemb: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn srand48_deterministic(seed: ::c_long); pub fn seed48_deterministic(xseed: *mut ::c_ushort) -> *mut ::c_ushort; pub fn lcong48_deterministic(p: *mut ::c_ushort); pub fn lsearch( key: *const ::c_void, base: *mut ::c_void, nelp: *mut ::size_t, width: ::size_t, compar: ::Option ::c_int>, ) -> *mut ::c_void; pub fn lfind( key: *const ::c_void, base: *const ::c_void, nelp: *mut ::size_t, width: ::size_t, compar: ::Option ::c_int>, ) -> *mut ::c_void; pub fn hcreate(nelt: ::size_t) -> ::c_int; pub fn hdestroy(); pub fn hsearch(entry: ::ENTRY, action: ::ACTION) -> *mut ::ENTRY; // futex.h pub fn futex( uaddr: *mut u32, op: ::c_int, val: ::c_int, timeout: *const ::timespec, uaddr2: *mut u32, ) -> ::c_int; pub fn mimmutable(addr: *mut ::c_void, len: ::size_t) -> ::c_int; pub fn reboot(mode: ::c_int) -> ::c_int; } #[link(name = "execinfo")] extern "C" { pub fn backtrace(addrlist: *mut *mut ::c_void, len: ::size_t) -> ::size_t; pub fn backtrace_symbols(addrlist: *const *mut ::c_void, len: ::size_t) -> *mut *mut ::c_char; pub fn backtrace_symbols_fd( addrlist: *const *mut ::c_void, len: ::size_t, fd: ::c_int, ) -> ::c_int; pub fn backtrace_symbols_fmt( addrlist: *const *mut ::c_void, len: ::size_t, fmt: *const ::c_char, ) -> *mut *mut ::c_char; } cfg_if! { if #[cfg(libc_union)] { extern { // these functions use statfs which uses the union mount_info: pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn getmntinfo(mntbufp: *mut *mut ::statfs, flags: ::c_int) -> ::c_int; pub fn getfsstat(buf: *mut statfs, bufsize: ::size_t, flags: ::c_int) -> ::c_int; } } } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "mips64")] { mod mips64; pub use self::mips64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else if #[cfg(target_arch = "sparc64")] { mod sparc64; pub use self::sparc64::*; } else if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/netbsdlike/openbsd/aarch64.rs0000644000175000017500000000132214661133735022346 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; pub type ucontext_t = sigcontext; s! { pub struct sigcontext { __sc_unused: ::c_int, pub sc_mask: ::c_int, pub sc_sp: ::c_ulong, pub sc_lr: ::c_ulong, pub sc_elr: ::c_ulong, pub sc_spsr: ::c_ulong, pub sc_x: [::c_ulong; 30], pub sc_cookie: ::c_long, } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs0000644000175000017500000000061314661133735022751 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const _MAX_PAGE_SHIFT: u32 = 12; libc/src/unix/bsd/netbsdlike/netbsd/0000775000175000017500000000000014661133735020401 5ustar jamespagejamespagelibc/src/unix/bsd/netbsdlike/netbsd/riscv64.rs0000644000175000017500000000107114661133735022244 0ustar jamespagejamespageuse PT_FIRSTMACH; pub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; pub type __cpu_simple_lock_nv_t = ::c_int; cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 0; pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 1; pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 2; pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 3; libc/src/unix/bsd/netbsdlike/netbsd/powerpc.rs0000644000175000017500000000107114661133735022423 0ustar jamespagejamespageuse PT_FIRSTMACH; pub type c_long = i32; pub type c_ulong = u32; pub type c_char = u8; pub type __cpu_simple_lock_nv_t = ::c_int; // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_double>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const PT_STEP: ::c_int = PT_FIRSTMACH + 0; pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 2; libc/src/unix/bsd/netbsdlike/netbsd/arm.rs0000644000175000017500000000477414661133735021540 0ustar jamespagejamespageuse PT_FIRSTMACH; pub type c_long = i32; pub type c_ulong = u32; pub type c_char = u8; pub type __cpu_simple_lock_nv_t = ::c_int; // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_longlong>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 4; pub const _REG_R0: ::c_int = 0; pub const _REG_R1: ::c_int = 1; pub const _REG_R2: ::c_int = 2; pub const _REG_R3: ::c_int = 3; pub const _REG_R4: ::c_int = 4; pub const _REG_R5: ::c_int = 5; pub const _REG_R6: ::c_int = 6; pub const _REG_R7: ::c_int = 7; pub const _REG_R8: ::c_int = 8; pub const _REG_R9: ::c_int = 9; pub const _REG_R10: ::c_int = 10; pub const _REG_R11: ::c_int = 11; pub const _REG_R12: ::c_int = 12; pub const _REG_R13: ::c_int = 13; pub const _REG_R14: ::c_int = 14; pub const _REG_R15: ::c_int = 15; pub const _REG_CPSR: ::c_int = 16; pub const _REG_X0: ::c_int = 0; pub const _REG_X1: ::c_int = 1; pub const _REG_X2: ::c_int = 2; pub const _REG_X3: ::c_int = 3; pub const _REG_X4: ::c_int = 4; pub const _REG_X5: ::c_int = 5; pub const _REG_X6: ::c_int = 6; pub const _REG_X7: ::c_int = 7; pub const _REG_X8: ::c_int = 8; pub const _REG_X9: ::c_int = 9; pub const _REG_X10: ::c_int = 10; pub const _REG_X11: ::c_int = 11; pub const _REG_X12: ::c_int = 12; pub const _REG_X13: ::c_int = 13; pub const _REG_X14: ::c_int = 14; pub const _REG_X15: ::c_int = 15; pub const _REG_X16: ::c_int = 16; pub const _REG_X17: ::c_int = 17; pub const _REG_X18: ::c_int = 18; pub const _REG_X19: ::c_int = 19; pub const _REG_X20: ::c_int = 20; pub const _REG_X21: ::c_int = 21; pub const _REG_X22: ::c_int = 22; pub const _REG_X23: ::c_int = 23; pub const _REG_X24: ::c_int = 24; pub const _REG_X25: ::c_int = 25; pub const _REG_X26: ::c_int = 26; pub const _REG_X27: ::c_int = 27; pub const _REG_X28: ::c_int = 28; pub const _REG_X29: ::c_int = 29; pub const _REG_X30: ::c_int = 30; pub const _REG_X31: ::c_int = 31; pub const _REG_ELR: ::c_int = 32; pub const _REG_SPSR: ::c_int = 33; pub const _REG_TIPDR: ::c_int = 34; pub const _REG_RV: ::c_int = _REG_R0; pub const _REG_FP: ::c_int = _REG_R11; pub const _REG_LR: ::c_int = _REG_R13; pub const _REG_SP: ::c_int = _REG_R14; pub const _REG_PC: ::c_int = _REG_R15; libc/src/unix/bsd/netbsdlike/netbsd/x86.rs0000644000175000017500000000062114661133735021371 0ustar jamespagejamespagepub type c_long = i32; pub type c_ulong = u32; pub type c_char = i8; pub type __cpu_simple_lock_nv_t = ::c_uchar; // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_int>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 4 - 1; } } libc/src/unix/bsd/netbsdlike/netbsd/sparc64.rs0000644000175000017500000000033514661133735022230 0ustar jamespagejamespagepub type c_long = i64; pub type c_ulong = u64; pub type c_char = i8; pub type __cpu_simple_lock_nv_t = ::c_uchar; // should be pub(crate), but that requires Rust 1.18.0 #[doc(hidden)] pub const _ALIGNBYTES: usize = 0xf; libc/src/unix/bsd/netbsdlike/netbsd/x86_64.rs0000644000175000017500000000363514661133735021712 0ustar jamespagejamespageuse PT_FIRSTMACH; pub type c_long = i64; pub type c_ulong = u64; pub type c_char = i8; pub type c___greg_t = u64; pub type __cpu_simple_lock_nv_t = ::c_uchar; s! { pub struct mcontext_t { pub __gregs: [c___greg_t; 26], pub _mc_tlsbase: c___greg_t, pub __fpregs: [[::c_char;32]; 16], } pub struct ucontext_t { pub uc_flags: ::c_uint, pub uc_link: *mut ::ucontext_t, pub uc_sigmask: ::sigset_t, pub uc_stack: ::stack_t, pub uc_mcontext: ::mcontext_t, } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const PT_STEP: ::c_int = PT_FIRSTMACH + 0; pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 4; pub const _REG_RDI: ::c_int = 0; pub const _REG_RSI: ::c_int = 1; pub const _REG_RDX: ::c_int = 2; pub const _REG_RCX: ::c_int = 3; pub const _REG_R8: ::c_int = 4; pub const _REG_R9: ::c_int = 5; pub const _REG_R10: ::c_int = 6; pub const _REG_R11: ::c_int = 7; pub const _REG_R12: ::c_int = 8; pub const _REG_R13: ::c_int = 9; pub const _REG_R14: ::c_int = 10; pub const _REG_R15: ::c_int = 11; pub const _REG_RBP: ::c_int = 12; pub const _REG_RBX: ::c_int = 13; pub const _REG_RAX: ::c_int = 14; pub const _REG_GS: ::c_int = 15; pub const _REG_FS: ::c_int = 16; pub const _REG_ES: ::c_int = 17; pub const _REG_DS: ::c_int = 18; pub const _REG_TRAPNO: ::c_int = 19; pub const _REG_ERR: ::c_int = 20; pub const _REG_RIP: ::c_int = 21; pub const _REG_CS: ::c_int = 22; pub const _REG_RFLAGS: ::c_int = 23; pub const _REG_RSP: ::c_int = 24; pub const _REG_SS: ::c_int = 25; libc/src/unix/bsd/netbsdlike/netbsd/mips.rs0000644000175000017500000000110114661133735021706 0ustar jamespagejamespageuse PT_FIRSTMACH; pub type c_long = i32; pub type c_ulong = u32; pub type c_char = i8; pub type __cpu_simple_lock_nv_t = ::c_int; cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_longlong>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 1; pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 2; pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 3; pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 4; libc/src/unix/bsd/netbsdlike/netbsd/mod.rs0000644000175000017500000031317314661133735021534 0ustar jamespagejamespagepub type clock_t = ::c_uint; pub type suseconds_t = ::c_int; pub type dev_t = u64; pub type blksize_t = i32; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = ::c_int; pub type mqd_t = ::c_int; type __pthread_spin_t = __cpu_simple_lock_nv_t; pub type vm_size_t = ::uintptr_t; // FIXME: deprecated since long time pub type lwpid_t = ::c_uint; pub type shmatt_t = ::c_uint; pub type cpuid_t = ::c_ulong; pub type cpuset_t = _cpuset; pub type pthread_spin_t = ::c_uchar; pub type timer_t = ::c_int; // elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Lword = u64; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Lword = u64; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type iconv_t = *mut ::c_void; e! { pub enum fae_action { FAE_OPEN, FAE_DUP2, FAE_CLOSE, } } cfg_if! { if #[cfg(target_pointer_width = "64")] { type Elf_Addr = Elf64_Addr; type Elf_Half = Elf64_Half; type Elf_Phdr = Elf64_Phdr; } else if #[cfg(target_pointer_width = "32")] { type Elf_Addr = Elf32_Addr; type Elf_Half = Elf32_Half; type Elf_Phdr = Elf32_Phdr; } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { self.si_addr } pub unsafe fn si_code(&self) -> ::c_int { self.si_code } pub unsafe fn si_errno(&self) -> ::c_int { self.si_errno } pub unsafe fn si_pid(&self) -> ::pid_t { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, __pad1: ::c_int, _pid: ::pid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._pid } pub unsafe fn si_uid(&self) -> ::uid_t { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, __pad1: ::c_int, _pid: ::pid_t, _uid: ::uid_t, } (*(self as *const siginfo_t as *const siginfo_timer))._uid } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, __pad1: ::c_int, _pid: ::pid_t, _uid: ::uid_t, value: ::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).value } pub unsafe fn si_status(&self) -> ::c_int { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, __pad1: ::c_int, _pid: ::pid_t, _uid: ::uid_t, _value: ::sigval, _cpid: ::pid_t, _cuid: ::uid_t, status: ::c_int, } (*(self as *const siginfo_t as *const siginfo_timer)).status } } s! { pub struct aiocb { pub aio_offset: ::off_t, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_fildes: ::c_int, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, pub aio_sigevent: ::sigevent, _state: ::c_int, _errno: ::c_int, _retval: ::ssize_t } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_matchc: ::size_t, pub gl_offs: ::size_t, pub gl_flags: ::c_int, pub gl_pathv: *mut *mut ::c_char, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, __unused6: *mut ::c_void, __unused7: *mut ::c_void, __unused8: *mut ::c_void, } pub struct mq_attr { pub mq_flags: ::c_long, pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } pub struct sigset_t { __bits: [u32; 4], } pub struct stat { pub st_dev: ::dev_t, pub st_mode: ::mode_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atimensec: ::c_long, pub st_mtime: ::time_t, pub st_mtimensec: ::c_long, pub st_ctime: ::time_t, pub st_ctimensec: ::c_long, pub st_birthtime: ::time_t, pub st_birthtimensec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: u32, pub st_gen: u32, pub st_spare: [u32; 2], } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: ::socklen_t, pub ai_canonname: *mut ::c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut ::addrinfo, } pub struct siginfo_t { pub si_signo: ::c_int, pub si_code: ::c_int, pub si_errno: ::c_int, __pad1: ::c_int, pub si_addr: *mut ::c_void, __pad2: [u64; 13], } pub struct pthread_attr_t { pta_magic: ::c_uint, pta_flags: ::c_int, pta_private: *mut ::c_void, } pub struct pthread_mutex_t { ptm_magic: ::c_uint, ptm_errorcheck: __pthread_spin_t, #[cfg(any(target_arch = "sparc", target_arch = "sparc64", target_arch = "x86", target_arch = "x86_64"))] ptm_pad1: [u8; 3], // actually a union with a non-unused, 0-initialized field ptm_unused: __pthread_spin_t, #[cfg(any(target_arch = "sparc", target_arch = "sparc64", target_arch = "x86", target_arch = "x86_64"))] ptm_pad2: [u8; 3], ptm_owner: ::pthread_t, ptm_waiters: *mut u8, ptm_recursed: ::c_uint, ptm_spare2: *mut ::c_void, } pub struct pthread_mutexattr_t { ptma_magic: ::c_uint, ptma_private: *mut ::c_void, } pub struct pthread_rwlockattr_t { ptra_magic: ::c_uint, ptra_private: *mut ::c_void, } pub struct pthread_cond_t { ptc_magic: ::c_uint, ptc_lock: __pthread_spin_t, ptc_waiters_first: *mut u8, ptc_waiters_last: *mut u8, ptc_mutex: *mut ::pthread_mutex_t, ptc_private: *mut ::c_void, } pub struct pthread_condattr_t { ptca_magic: ::c_uint, ptca_private: *mut ::c_void, } pub struct pthread_rwlock_t { ptr_magic: ::c_uint, ptr_interlock: __pthread_spin_t, ptr_rblocked_first: *mut u8, ptr_rblocked_last: *mut u8, ptr_wblocked_first: *mut u8, ptr_wblocked_last: *mut u8, ptr_nreaders: ::c_uint, ptr_owner: ::pthread_t, ptr_private: *mut ::c_void, } pub struct pthread_spinlock_t { pts_magic: ::c_uint, pts_spin: ::pthread_spin_t, pts_flags: ::c_int, } pub struct kevent { pub ident: ::uintptr_t, pub filter: u32, pub flags: u32, pub fflags: u32, pub data: i64, pub udata: ::intptr_t, /* FIXME: NetBSD 10.0 will finally have same layout as other BSD */ } pub struct dqblk { pub dqb_bhardlimit: u32, pub dqb_bsoftlimit: u32, pub dqb_curblocks: u32, pub dqb_ihardlimit: u32, pub dqb_isoftlimit: u32, pub dqb_curinodes: u32, pub dqb_btime: i32, pub dqb_itime: i32, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *const ::c_void, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct if_data { pub ifi_type: ::c_uchar, pub ifi_addrlen: ::c_uchar, pub ifi_hdrlen: ::c_uchar, pub ifi_link_state: ::c_int, pub ifi_mtu: u64, pub ifi_metric: u64, pub ifi_baudrate: u64, pub ifi_ipackets: u64, pub ifi_ierrors: u64, pub ifi_opackets: u64, pub ifi_oerrors: u64, pub ifi_collisions: u64, pub ifi_ibytes: u64, pub ifi_obytes: u64, pub ifi_imcasts: u64, pub ifi_omcasts: u64, pub ifi_iqdrops: u64, pub ifi_noproto: u64, pub ifi_lastchange: ::timespec, } pub struct if_msghdr { pub ifm_msglen: ::c_ushort, pub ifm_version: ::c_uchar, pub ifm_type: ::c_uchar, pub ifm_addrs: ::c_int, pub ifm_flags: ::c_int, pub ifm_index: ::c_ushort, pub ifm_data: if_data, } pub struct sockcred { pub sc_pid: ::pid_t, pub sc_uid: ::uid_t, pub sc_euid: ::uid_t, pub sc_gid: ::gid_t, pub sc_egid: ::gid_t, pub sc_ngroups: ::c_int, pub sc_groups: [::gid_t; 1], } pub struct uucred { pub cr_unused: ::c_ushort, pub cr_uid: ::uid_t, pub cr_gid: ::gid_t, pub cr_ngroups: ::c_int, pub cr_groups: [::gid_t; NGROUPS_MAX as usize], } pub struct unpcbid { pub unp_pid: ::pid_t, pub unp_euid: ::uid_t, pub unp_egid: ::gid_t, } pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, pub sdl_index: ::c_ushort, pub sdl_type: u8, pub sdl_nlen: u8, pub sdl_alen: u8, pub sdl_slen: u8, pub sdl_data: [::c_char; 12], } pub struct mmsghdr { pub msg_hdr: ::msghdr, pub msg_len: ::c_uint, } pub struct __exit_status { pub e_termination: u16, pub e_exit: u16, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, _shm_internal: *mut ::c_void, } pub struct utmp { pub ut_line: [::c_char; UT_LINESIZE], pub ut_name: [::c_char; UT_NAMESIZE], pub ut_host: [::c_char; UT_HOSTSIZE], pub ut_time: ::time_t } pub struct lastlog { pub ll_line: [::c_char; UT_LINESIZE], pub ll_host: [::c_char; UT_HOSTSIZE], pub ll_time: ::time_t } pub struct timex { pub modes: ::c_uint, pub offset: ::c_long, pub freq: ::c_long, pub maxerror: ::c_long, pub esterror: ::c_long, pub status: ::c_int, pub constant: ::c_long, pub precision: ::c_long, pub tolerance: ::c_long, pub ppsfreq: ::c_long, pub jitter: ::c_long, pub shift: ::c_int, pub stabil: ::c_long, pub jitcnt: ::c_long, pub calcnt: ::c_long, pub errcnt: ::c_long, pub stbcnt: ::c_long, } pub struct ntptimeval { pub time: ::timespec, pub maxerror: ::c_long, pub esterror: ::c_long, pub tai: ::c_long, pub time_state: ::c_int, } // elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } pub struct Aux32Info { pub a_type: Elf32_Word, pub a_v: Elf32_Word, } pub struct Aux64Info { pub a_type: Elf64_Word, pub a_v: Elf64_Xword, } // link.h pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, pub dlpi_adds: ::c_ulonglong, pub dlpi_subs: ::c_ulonglong, pub dlpi_tls_modid: usize, pub dlpi_tls_data: *mut ::c_void, } pub struct _cpuset { bits: [u32; 0] } pub struct accept_filter_arg { pub af_name: [::c_char; 16], af_arg: [[::c_char; 10]; 24], } pub struct ki_sigset_t { pub __bits: [u32; 4], } pub struct kinfo_proc2 { pub p_forw: u64, pub p_back: u64, pub p_paddr: u64, pub p_addr: u64, pub p_fd: u64, pub p_cwdi: u64, pub p_stats: u64, pub p_limit: u64, pub p_vmspace: u64, pub p_sigacts: u64, pub p_sess: u64, pub p_tsess: u64, pub p_ru: u64, pub p_eflag: i32, pub p_exitsig: i32, pub p_flag: i32, pub p_pid: i32, pub p_ppid: i32, pub p_sid: i32, pub p__pgid: i32, pub p_tpgid: i32, pub p_uid: u32, pub p_ruid: u32, pub p_gid: u32, pub p_rgid: u32, pub p_groups: [u32; KI_NGROUPS as usize], pub p_ngroups: i16, pub p_jobc: i16, pub p_tdev: u32, pub p_estcpu: u32, pub p_rtime_sec: u32, pub p_rtime_usec: u32, pub p_cpticks: i32, pub p_pctcpu: u32, pub p_swtime: u32, pub p_slptime: u32, pub p_schedflags: i32, pub p_uticks: u64, pub p_sticks: u64, pub p_iticks: u64, pub p_tracep: u64, pub p_traceflag: i32, pub p_holdcnt: i32, pub p_siglist: ki_sigset_t, pub p_sigmask: ki_sigset_t, pub p_sigignore: ki_sigset_t, pub p_sigcatch: ki_sigset_t, pub p_stat: i8, pub p_priority: u8, pub p_usrpri: u8, pub p_nice: u8, pub p_xstat: u16, pub p_acflag: u16, pub p_comm: [::c_char; KI_MAXCOMLEN as usize], pub p_wmesg: [::c_char; KI_WMESGLEN as usize], pub p_wchan: u64, pub p_login: [::c_char; KI_MAXLOGNAME as usize], pub p_vm_rssize: i32, pub p_vm_tsize: i32, pub p_vm_dsize: i32, pub p_vm_ssize: i32, pub p_uvalid: i64, pub p_ustart_sec: u32, pub p_ustart_usec: u32, pub p_uutime_sec: u32, pub p_uutime_usec: u32, pub p_ustime_sec: u32, pub p_ustime_usec: u32, pub p_uru_maxrss: u64, pub p_uru_ixrss: u64, pub p_uru_idrss: u64, pub p_uru_isrss: u64, pub p_uru_minflt: u64, pub p_uru_majflt: u64, pub p_uru_nswap: u64, pub p_uru_inblock: u64, pub p_uru_oublock: u64, pub p_uru_msgsnd: u64, pub p_uru_msgrcv: u64, pub p_uru_nsignals: u64, pub p_uru_nvcsw: u64, pub p_uru_nivcsw: u64, pub p_uctime_sec: u32, pub p_uctime_usec: u32, pub p_cpuid: u64, pub p_realflag: u64, pub p_nlwps: u64, pub p_nrlwps: u64, pub p_realstat: u64, pub p_svuid: u32, pub p_svgid: u32, pub p_ename: [::c_char; KI_MAXEMULLEN as usize], pub p_vm_vsize: i64, pub p_vm_msize: i64, } pub struct kinfo_lwp { pub l_forw: u64, pub l_back: u64, pub l_laddr: u64, pub l_addr: u64, pub l_lid: i32, pub l_flag: i32, pub l_swtime: u32, pub l_slptime: u32, pub l_schedflags: i32, pub l_holdcnt: i32, pub l_priority: u8, pub l_usrpri: u8, pub l_stat: i8, l_pad1: i8, l_pad2: i32, pub l_wmesg: [::c_char; KI_WMESGLEN as usize], pub l_wchan: u64, pub l_cpuid: u64, pub l_rtime_sec: u32, pub l_rtime_usec: u32, pub l_cpticks: u32, pub l_pctcpu: u32, pub l_pid: u32, pub l_name: [::c_char; KI_LNAMELEN as usize], } pub struct kinfo_vmentry { pub kve_start: u64, pub kve_end: u64, pub kve_offset: u64, pub kve_type: u32, pub kve_flags: u32, pub kve_count: u32, pub kve_wired_count: u32, pub kve_advice: u32, pub kve_attributes: u32, pub kve_protection: u32, pub kve_max_protection: u32, pub kve_ref_count: u32, pub kve_inheritance: u32, pub kve_vn_fileid: u64, pub kve_vn_size: u64, pub kve_vn_fsid: u64, pub kve_vn_rdev: u64, pub kve_vn_type: u32, pub kve_vn_mode: u32, pub kve_path: [[::c_char; 32]; 32], } pub struct __c_anonymous_posix_spawn_fae_open { pub path: *mut ::c_char, pub oflag: ::c_int, pub mode: ::mode_t, } pub struct __c_anonymous_posix_spawn_fae_dup2 { pub newfildes: ::c_int, } pub struct posix_spawnattr_t { pub sa_flags: ::c_short, pub sa_pgroup: ::pid_t, pub sa_schedparam: ::sched_param, pub sa_schedpolicy: ::c_int, pub sa_sigdefault: sigset_t, pub sa_sigmask: sigset_t, } pub struct posix_spawn_file_actions_entry_t { pub fae_action: fae_action, pub fae_fildes: ::c_int, #[cfg(libc_union)] pub fae_data: __c_anonymous_posix_spawn_fae, } pub struct posix_spawn_file_actions_t { pub size: ::c_uint, pub len: ::c_uint, #[cfg(libc_union)] pub fae: *mut posix_spawn_file_actions_entry_t, } pub struct ptrace_lwpinfo { pub pl_lwpid: lwpid_t, pub pl_event: ::c_int, } pub struct ptrace_lwpstatus { pub pl_lwpid: lwpid_t, pub pl_sigpend: sigset_t, pub pl_sigmask: sigset_t, pub pl_name: [::c_char; 20], pub pl_private: *mut ::c_void, } pub struct ptrace_siginfo { pub psi_siginfo: siginfo_t, pub psi_lwpid: lwpid_t, } pub struct ptrace_event { pub pe_set_event: ::c_int, } pub struct sysctldesc { pub descr_num: i32, pub descr_ver: u32, pub descr_len: u32, pub descr_str: [::c_char; 1], } pub struct ifreq { pub _priv: [[::c_char; 6]; 24], } pub struct ifconf { pub ifc_len: ::c_int, #[cfg(libc_union)] pub ifc_ifcu: __c_anonymous_ifc_ifcu, } pub struct tcp_info { pub tcpi_state: u8, pub __tcpi_ca_state: u8, pub __tcpi_retransmits: u8, pub __tcpi_probes: u8, pub __tcpi_backoff: u8, pub tcpi_options: u8, pub tcp_snd_wscale: u8, pub tcp_rcv_wscale: u8, pub tcpi_rto: u32, pub __tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub __tcpi_unacked: u32, pub __tcpi_sacked: u32, pub __tcpi_lost: u32, pub __tcpi_retrans: u32, pub __tcpi_fackets: u32, pub __tcpi_last_data_sent: u32, pub __tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub __tcpi_last_ack_recv: u32, pub __tcpi_pmtu: u32, pub __tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub __tcpi_advmss: u32, pub __tcpi_reordering: u32, pub __tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_bwnd: u32, pub tcpi_snd_nxt: u32, pub tcpi_rcv_nxt: u32, pub tcpi_toe_tid: u32, pub tcpi_snd_rexmitpack: u32, pub tcpi_rcv_ooopack: u32, pub tcpi_snd_zerowin: u32, pub __tcpi_pad: [u32; 26], } } s_no_extra_traits! { pub struct utmpx { pub ut_name: [::c_char; _UTX_USERSIZE], pub ut_id: [::c_char; _UTX_IDSIZE], pub ut_line: [::c_char; _UTX_LINESIZE], pub ut_host: [::c_char; _UTX_HOSTSIZE], pub ut_session: u16, pub ut_type: u16, pub ut_pid: ::pid_t, pub ut_exit: __exit_status, // FIXME: when anonymous struct are supported pub ut_ss: sockaddr_storage, pub ut_tv: ::timeval, pub ut_pad: [u8; _UTX_PADSIZE], } pub struct lastlogx { pub ll_tv: ::timeval, pub ll_line: [::c_char; _UTX_LINESIZE], pub ll_host: [::c_char; _UTX_HOSTSIZE], pub ll_ss: sockaddr_storage, } pub struct in_pktinfo { pub ipi_addr: ::in_addr, pub ipi_ifindex: ::c_uint, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [i8; 8], } pub struct dirent { pub d_fileno: ::ino_t, pub d_reclen: u16, pub d_namlen: u16, pub d_type: u8, pub d_name: [::c_char; 512], } pub struct statvfs { pub f_flag: ::c_ulong, pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_iosize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_bresvd: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fresvd: ::fsfilcnt_t, pub f_syncreads: u64, pub f_syncwrites: u64, pub f_asyncreads: u64, pub f_asyncwrites: u64, pub f_fsidx: ::fsid_t, pub f_fsid: ::c_ulong, pub f_namemax: ::c_ulong, pub f_owner: ::uid_t, pub f_spare: [u32; 4], pub f_fstypename: [::c_char; 32], pub f_mntonname: [::c_char; 1024], pub f_mntfromname: [::c_char; 1024], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: ::sa_family_t, __ss_pad1: [u8; 6], __ss_pad2: i64, __ss_pad3: [u8; 112], } pub struct sigevent { pub sigev_notify: ::c_int, pub sigev_signo: ::c_int, pub sigev_value: ::sigval, __unused1: *mut ::c_void, //actually a function pointer pub sigev_notify_attributes: *mut ::c_void } #[cfg(libc_union)] pub union __c_anonymous_posix_spawn_fae { pub open: __c_anonymous_posix_spawn_fae_open, pub dup2: __c_anonymous_posix_spawn_fae_dup2, } #[cfg(libc_union)] pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut ::c_void, pub ifcu_req: *mut ifreq, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_name == other.ut_name && self.ut_line == other.ut_line && self.ut_id == other.ut_id && self.ut_exit == other.ut_exit && self.ut_session == other.ut_session && self.ut_tv == other.ut_tv && self.ut_ss == other.ut_ss && self .ut_pad .iter() .zip(other.ut_pad.iter()) .all(|(a,b)| a == b) && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_name", &self.ut_name) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) // FIXME .field("ut_host", &self.ut_host) .field("ut_session", &self.ut_session) .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_exit", &self.ut_exit) .field("ut_ss", &self.ut_ss) .field("ut_tv", &self.ut_tv) // FIXME .field("ut_pad", &self.ut_pad) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_name.hash(state); self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_line.hash(state); self.ut_id.hash(state); self.ut_host.hash(state); self.ut_exit.hash(state); self.ut_session.hash(state); self.ut_tv.hash(state); self.ut_ss.hash(state); self.ut_pad.hash(state); } } impl PartialEq for lastlogx { fn eq(&self, other: &lastlogx) -> bool { self.ll_tv == other.ll_tv && self.ll_line == other.ll_line && self.ll_ss == other.ll_ss && self .ll_host .iter() .zip(other.ll_host.iter()) .all(|(a,b)| a == b) } } impl Eq for lastlogx {} impl ::fmt::Debug for lastlogx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("lastlogx") .field("ll_tv", &self.ll_tv) .field("ll_line", &self.ll_line) // FIXME.field("ll_host", &self.ll_host) .field("ll_ss", &self.ll_ss) .finish() } } impl ::hash::Hash for lastlogx { fn hash(&self, state: &mut H) { self.ll_tv.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); self.ll_ss.hash(state); } } impl PartialEq for in_pktinfo { fn eq(&self, other: &in_pktinfo) -> bool { self.ipi_addr == other.ipi_addr && self.ipi_ifindex == other.ipi_ifindex } } impl Eq for in_pktinfo {} impl ::fmt::Debug for in_pktinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("in_pktinfo") .field("ipi_addr", &self.ipi_addr) .field("ipi_ifindex", &self.ipi_ifindex) .finish() } } impl ::hash::Hash for in_pktinfo { fn hash(&self, state: &mut H) { self.ipi_addr.hash(state); self.ipi_ifindex.hash(state); } } impl PartialEq for arphdr { fn eq(&self, other: &arphdr) -> bool { self.ar_hrd == other.ar_hrd && self.ar_pro == other.ar_pro && self.ar_hln == other.ar_hln && self.ar_pln == other.ar_pln && self.ar_op == other.ar_op } } impl Eq for arphdr {} impl ::fmt::Debug for arphdr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let ar_hrd = self.ar_hrd; let ar_pro = self.ar_pro; let ar_op = self.ar_op; f.debug_struct("arphdr") .field("ar_hrd", &ar_hrd) .field("ar_pro", &ar_pro) .field("ar_hln", &self.ar_hln) .field("ar_pln", &self.ar_pln) .field("ar_op", &ar_op) .finish() } } impl ::hash::Hash for arphdr { fn hash(&self, state: &mut H) { let ar_hrd = self.ar_hrd; let ar_pro = self.ar_pro; let ar_op = self.ar_op; ar_hrd.hash(state); ar_pro.hash(state); self.ar_hln.hash(state); self.ar_pln.hash(state); ar_op.hash(state); } } impl PartialEq for in_addr { fn eq(&self, other: &in_addr) -> bool { self.s_addr == other.s_addr } } impl Eq for in_addr {} impl ::fmt::Debug for in_addr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let s_addr = self.s_addr; f.debug_struct("in_addr") .field("s_addr", &s_addr) .finish() } } impl ::hash::Hash for in_addr { fn hash(&self, state: &mut H) { let s_addr = self.s_addr; s_addr.hash(state); } } impl PartialEq for ip_mreq { fn eq(&self, other: &ip_mreq) -> bool { self.imr_multiaddr == other.imr_multiaddr && self.imr_interface == other.imr_interface } } impl Eq for ip_mreq {} impl ::fmt::Debug for ip_mreq { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ip_mreq") .field("imr_multiaddr", &self.imr_multiaddr) .field("imr_interface", &self.imr_interface) .finish() } } impl ::hash::Hash for ip_mreq { fn hash(&self, state: &mut H) { self.imr_multiaddr.hash(state); self.imr_interface.hash(state); } } impl PartialEq for sockaddr_in { fn eq(&self, other: &sockaddr_in) -> bool { self.sin_len == other.sin_len && self.sin_family == other.sin_family && self.sin_port == other.sin_port && self.sin_addr == other.sin_addr && self.sin_zero == other.sin_zero } } impl Eq for sockaddr_in {} impl ::fmt::Debug for sockaddr_in { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_in") .field("sin_len", &self.sin_len) .field("sin_family", &self.sin_family) .field("sin_port", &self.sin_port) .field("sin_addr", &self.sin_addr) .field("sin_zero", &self.sin_zero) .finish() } } impl ::hash::Hash for sockaddr_in { fn hash(&self, state: &mut H) { self.sin_len.hash(state); self.sin_family.hash(state); self.sin_port.hash(state); self.sin_addr.hash(state); self.sin_zero.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_reclen == other.d_reclen && self.d_namlen == other.d_namlen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_reclen", &self.d_reclen) .field("d_namlen", &self.d_namlen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_reclen.hash(state); self.d_namlen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for statvfs { fn eq(&self, other: &statvfs) -> bool { self.f_flag == other.f_flag && self.f_bsize == other.f_bsize && self.f_frsize == other.f_frsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_bresvd == other.f_bresvd && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_favail == other.f_favail && self.f_fresvd == other.f_fresvd && self.f_syncreads == other.f_syncreads && self.f_syncwrites == other.f_syncwrites && self.f_asyncreads == other.f_asyncreads && self.f_asyncwrites == other.f_asyncwrites && self.f_fsidx == other.f_fsidx && self.f_fsid == other.f_fsid && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_spare == other.f_spare && self.f_fstypename == other.f_fstypename && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) } } impl Eq for statvfs {} impl ::fmt::Debug for statvfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statvfs") .field("f_flag", &self.f_flag) .field("f_bsize", &self.f_bsize) .field("f_frsize", &self.f_frsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_bresvd", &self.f_bresvd) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_favail", &self.f_favail) .field("f_fresvd", &self.f_fresvd) .field("f_syncreads", &self.f_syncreads) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncreads", &self.f_asyncreads) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_fsidx", &self.f_fsidx) .field("f_fsid", &self.f_fsid) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_spare", &self.f_spare) .field("f_fstypename", &self.f_fstypename) // FIXME: .field("f_mntonname", &self.f_mntonname) // FIXME: .field("f_mntfromname", &self.f_mntfromname) .finish() } } impl ::hash::Hash for statvfs { fn hash(&self, state: &mut H) { self.f_flag.hash(state); self.f_bsize.hash(state); self.f_frsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_bresvd.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_favail.hash(state); self.f_fresvd.hash(state); self.f_syncreads.hash(state); self.f_syncwrites.hash(state); self.f_asyncreads.hash(state); self.f_asyncwrites.hash(state); self.f_fsidx.hash(state); self.f_fsid.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_spare.hash(state); self.f_fstypename.hash(state); self.f_mntonname.hash(state); self.f_mntfromname.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_pad2 == other.__ss_pad2 && self .__ss_pad3 .iter() .zip(other.__ss_pad3.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_pad2", &self.__ss_pad2) // FIXME: .field("__ss_pad3", &self.__ss_pad3) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_pad2.hash(state); self.__ss_pad3.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_attributes.hash(state); } } #[cfg(libc_union)] impl Eq for __c_anonymous_posix_spawn_fae {} #[cfg(libc_union)] impl PartialEq for __c_anonymous_posix_spawn_fae { fn eq(&self, other: &__c_anonymous_posix_spawn_fae) -> bool { unsafe { self.open == other.open || self.dup2 == other.dup2 } } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_posix_spawn_fae { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("__c_anonymous_posix_fae") .field("open", &self.open) .field("dup2", &self.dup2) .finish() } } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_posix_spawn_fae { fn hash(&self, state: &mut H) { unsafe { self.open.hash(state); self.dup2.hash(state); } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifc_ifcu {} #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifc_ifcu { fn eq(&self, other: &__c_anonymous_ifc_ifcu) -> bool { unsafe { self.ifcu_buf == other.ifcu_buf || self.ifcu_req == other.ifcu_req } } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifc_ifcu { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("__c_anonymous_ifc_ifcu") .field("ifcu_buf", &self.ifcu_buf) .field("ifcu_req", &self.ifcu_req) .finish() } } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifc_ifcu { fn hash(&self, state: &mut H) { unsafe { self.ifcu_buf.hash(state); self.ifcu_req.hash(state); } } } } } pub const AT_FDCWD: ::c_int = -100; pub const AT_EACCESS: ::c_int = 0x100; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x200; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; pub const AT_REMOVEDIR: ::c_int = 0x800; pub const AT_NULL: ::c_int = 0; pub const AT_IGNORE: ::c_int = 1; pub const AT_EXECFD: ::c_int = 2; pub const AT_PHDR: ::c_int = 3; pub const AT_PHENT: ::c_int = 4; pub const AT_PHNUM: ::c_int = 5; pub const AT_PAGESZ: ::c_int = 6; pub const AT_BASE: ::c_int = 7; pub const AT_FLAGS: ::c_int = 8; pub const AT_ENTRY: ::c_int = 9; pub const AT_DCACHEBSIZE: ::c_int = 10; pub const AT_ICACHEBSIZE: ::c_int = 11; pub const AT_UCACHEBSIZE: ::c_int = 12; pub const AT_STACKBASE: ::c_int = 13; pub const AT_EUID: ::c_int = 2000; pub const AT_RUID: ::c_int = 2001; pub const AT_EGID: ::c_int = 2002; pub const AT_RGID: ::c_int = 2003; pub const AT_SUN_LDELF: ::c_int = 2004; pub const AT_SUN_LDSHDR: ::c_int = 2005; pub const AT_SUN_LDNAME: ::c_int = 2006; pub const AT_SUN_LDPGSIZE: ::c_int = 2007; pub const AT_SUN_PLATFORM: ::c_int = 2008; pub const AT_SUN_HWCAP: ::c_int = 2009; pub const AT_SUN_IFLUSH: ::c_int = 2010; pub const AT_SUN_CPU: ::c_int = 2011; pub const AT_SUN_EMUL_ENTRY: ::c_int = 2012; pub const AT_SUN_EMUL_EXECFD: ::c_int = 2013; pub const AT_SUN_EXECNAME: ::c_int = 2014; pub const EXTATTR_NAMESPACE_USER: ::c_int = 1; pub const EXTATTR_NAMESPACE_SYSTEM: ::c_int = 2; pub const LC_COLLATE_MASK: ::c_int = 1 << ::LC_COLLATE; pub const LC_CTYPE_MASK: ::c_int = 1 << ::LC_CTYPE; pub const LC_MONETARY_MASK: ::c_int = 1 << ::LC_MONETARY; pub const LC_NUMERIC_MASK: ::c_int = 1 << ::LC_NUMERIC; pub const LC_TIME_MASK: ::c_int = 1 << ::LC_TIME; pub const LC_MESSAGES_MASK: ::c_int = 1 << ::LC_MESSAGES; pub const LC_ALL_MASK: ::c_int = !0; pub const ERA: ::nl_item = 52; pub const ERA_D_FMT: ::nl_item = 53; pub const ERA_D_T_FMT: ::nl_item = 54; pub const ERA_T_FMT: ::nl_item = 55; pub const ALT_DIGITS: ::nl_item = 56; pub const O_CLOEXEC: ::c_int = 0x400000; pub const O_ALT_IO: ::c_int = 0x40000; pub const O_NOSIGPIPE: ::c_int = 0x1000000; pub const O_SEARCH: ::c_int = 0x800000; pub const O_DIRECTORY: ::c_int = 0x200000; pub const O_DIRECT: ::c_int = 0x00080000; pub const O_RSYNC: ::c_int = 0x00020000; pub const MS_SYNC: ::c_int = 0x4; pub const MS_INVALIDATE: ::c_int = 0x2; // Here because they are not present on OpenBSD // (https://github.com/openbsd/src/blob/HEAD/sys/sys/resource.h) pub const RLIMIT_SBSIZE: ::c_int = 9; pub const RLIMIT_AS: ::c_int = 10; pub const RLIMIT_NTHR: ::c_int = 11; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 12; pub const EIDRM: ::c_int = 82; pub const ENOMSG: ::c_int = 83; pub const EOVERFLOW: ::c_int = 84; pub const EILSEQ: ::c_int = 85; pub const ENOTSUP: ::c_int = 86; pub const ECANCELED: ::c_int = 87; pub const EBADMSG: ::c_int = 88; pub const ENODATA: ::c_int = 89; pub const ENOSR: ::c_int = 90; pub const ENOSTR: ::c_int = 91; pub const ETIME: ::c_int = 92; pub const ENOATTR: ::c_int = 93; pub const EMULTIHOP: ::c_int = 94; pub const ENOLINK: ::c_int = 95; pub const EPROTO: ::c_int = 96; pub const EOWNERDEAD: ::c_int = 97; pub const ENOTRECOVERABLE: ::c_int = 98; #[deprecated( since = "0.2.143", note = "This value will always match the highest defined error number \ and thus is not stable. \ See #3040 for more info." )] pub const ELAST: ::c_int = 98; pub const F_DUPFD_CLOEXEC: ::c_int = 12; pub const F_CLOSEM: ::c_int = 10; pub const F_GETNOSIGPIPE: ::c_int = 13; pub const F_SETNOSIGPIPE: ::c_int = 14; pub const F_MAXFD: ::c_int = 11; pub const F_GETPATH: ::c_int = 15; pub const FUTEX_WAIT: ::c_int = 0; pub const FUTEX_WAKE: ::c_int = 1; pub const FUTEX_FD: ::c_int = 2; pub const FUTEX_REQUEUE: ::c_int = 3; pub const FUTEX_CMP_REQUEUE: ::c_int = 4; pub const FUTEX_WAKE_OP: ::c_int = 5; pub const FUTEX_LOCK_PI: ::c_int = 6; pub const FUTEX_UNLOCK_PI: ::c_int = 7; pub const FUTEX_TRYLOCK_PI: ::c_int = 8; pub const FUTEX_WAIT_BITSET: ::c_int = 9; pub const FUTEX_WAKE_BITSET: ::c_int = 10; pub const FUTEX_WAIT_REQUEUE_PI: ::c_int = 11; pub const FUTEX_CMP_REQUEUE_PI: ::c_int = 12; pub const FUTEX_PRIVATE_FLAG: ::c_int = 1 << 7; pub const FUTEX_CLOCK_REALTIME: ::c_int = 1 << 8; pub const FUTEX_CMD_MASK: ::c_int = !(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME); pub const FUTEX_WAITERS: u32 = 1 << 31; pub const FUTEX_OWNER_DIED: u32 = 1 << 30; pub const FUTEX_SYNCOBJ_1: u32 = 1 << 29; pub const FUTEX_SYNCOBJ_0: u32 = 1 << 28; pub const FUTEX_TID_MASK: u32 = (1 << 28) - 1; pub const FUTEX_BITSET_MATCH_ANY: u32 = !0; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_SENDSRCADDR: ::c_int = IP_RECVDSTADDR; pub const IP_RECVIF: ::c_int = 20; pub const IP_PKTINFO: ::c_int = 25; pub const IP_RECVPKTINFO: ::c_int = 26; pub const IPV6_JOIN_GROUP: ::c_int = 12; pub const IPV6_LEAVE_GROUP: ::c_int = 13; pub const TCP_KEEPIDLE: ::c_int = 3; pub const TCP_KEEPINTVL: ::c_int = 5; pub const TCP_KEEPCNT: ::c_int = 6; pub const TCP_KEEPINIT: ::c_int = 7; pub const TCP_MD5SIG: ::c_int = 0x10; pub const TCP_CONGCTL: ::c_int = 0x20; pub const SOCK_CONN_DGRAM: ::c_int = 6; pub const SOCK_DCCP: ::c_int = SOCK_CONN_DGRAM; pub const SOCK_NOSIGPIPE: ::c_int = 0x40000000; pub const SOCK_FLAGS_MASK: ::c_int = 0xf0000000; pub const SO_SNDTIMEO: ::c_int = 0x100b; pub const SO_RCVTIMEO: ::c_int = 0x100c; pub const SO_NOSIGPIPE: ::c_int = 0x0800; pub const SO_ACCEPTFILTER: ::c_int = 0x1000; pub const SO_TIMESTAMP: ::c_int = 0x2000; pub const SO_OVERFLOWED: ::c_int = 0x1009; pub const SO_NOHEADER: ::c_int = 0x100a; // http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/un.h?annotate pub const LOCAL_OCREDS: ::c_int = 0x0001; // pass credentials to receiver pub const LOCAL_CONNWAIT: ::c_int = 0x0002; // connects block until accepted pub const LOCAL_PEEREID: ::c_int = 0x0003; // get peer identification pub const LOCAL_CREDS: ::c_int = 0x0004; // pass credentials to receiver // https://github.com/NetBSD/src/blob/trunk/sys/net/if.h#L373 pub const IFF_UP: ::c_int = 0x0001; // interface is up pub const IFF_BROADCAST: ::c_int = 0x0002; // broadcast address valid pub const IFF_DEBUG: ::c_int = 0x0004; // turn on debugging pub const IFF_LOOPBACK: ::c_int = 0x0008; // is a loopback net pub const IFF_POINTOPOINT: ::c_int = 0x0010; // interface is point-to-point link pub const IFF_NOTRAILERS: ::c_int = 0x0020; // avoid use of trailers pub const IFF_RUNNING: ::c_int = 0x0040; // resources allocated pub const IFF_NOARP: ::c_int = 0x0080; // no address resolution protocol pub const IFF_PROMISC: ::c_int = 0x0100; // receive all packets pub const IFF_ALLMULTI: ::c_int = 0x0200; // receive all multicast packets pub const IFF_OACTIVE: ::c_int = 0x0400; // transmission in progress pub const IFF_SIMPLEX: ::c_int = 0x0800; // can't hear own transmissions pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// Hop-by-hop option header pub const IPPROTO_HOPOPTS: ::c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: ::c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: ::c_int = 3; /// for compatibility pub const IPPROTO_IPIP: ::c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// exterior gateway protocol pub const IPPROTO_EGP: ::c_int = 8; /// pup pub const IPPROTO_PUP: ::c_int = 12; // IPPROTO_UDP defined in src/unix/mod.rs /// xns idp pub const IPPROTO_IDP: ::c_int = 22; /// tp-4 w/ class negotiation pub const IPPROTO_TP: ::c_int = 29; /// DCCP pub const IPPROTO_DCCP: ::c_int = 33; // IPPROTO_IPV6 defined in src/unix/mod.rs /// IP6 routing header pub const IPPROTO_ROUTING: ::c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: ::c_int = 44; /// resource reservation pub const IPPROTO_RSVP: ::c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: ::c_int = 47; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: ::c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: ::c_int = 51; /// IP Mobility RFC 2004 pub const IPPROTO_MOBILE: ::c_int = 55; /// IPv6 ICMP pub const IPPROTO_IPV6_ICMP: ::c_int = 58; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: ::c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: ::c_int = 60; /// ISO cnlp pub const IPPROTO_EON: ::c_int = 80; /// Ethernet-in-IP pub const IPPROTO_ETHERIP: ::c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: ::c_int = 98; /// Protocol indep. multicast pub const IPPROTO_PIM: ::c_int = 103; /// IP Payload Comp. Protocol pub const IPPROTO_IPCOMP: ::c_int = 108; /// VRRP RFC 2338 pub const IPPROTO_VRRP: ::c_int = 112; /// Common Address Resolution Protocol pub const IPPROTO_CARP: ::c_int = 112; /// L2TPv3 pub const IPPROTO_L2TP: ::c_int = 115; /// SCTP pub const IPPROTO_SCTP: ::c_int = 132; /// PFSYNC pub const IPPROTO_PFSYNC: ::c_int = 240; pub const IPPROTO_MAX: ::c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: ::c_int = 257; /// sysctl placeholder for (FAST_)IPSEC pub const CTL_IPPROTO_IPSEC: ::c_int = 258; pub const AF_OROUTE: ::c_int = 17; pub const AF_ARP: ::c_int = 28; pub const pseudo_AF_KEY: ::c_int = 29; pub const pseudo_AF_HDRCMPLT: ::c_int = 30; pub const AF_BLUETOOTH: ::c_int = 31; pub const AF_IEEE80211: ::c_int = 32; pub const AF_MPLS: ::c_int = 33; pub const AF_ROUTE: ::c_int = 34; pub const NET_RT_DUMP: ::c_int = 1; pub const NET_RT_FLAGS: ::c_int = 2; pub const NET_RT_OOOIFLIST: ::c_int = 3; pub const NET_RT_OOIFLIST: ::c_int = 4; pub const NET_RT_OIFLIST: ::c_int = 5; pub const NET_RT_IFLIST: ::c_int = 6; pub const NET_RT_MAXID: ::c_int = 7; pub const PF_OROUTE: ::c_int = AF_OROUTE; pub const PF_ARP: ::c_int = AF_ARP; pub const PF_KEY: ::c_int = pseudo_AF_KEY; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const PF_MPLS: ::c_int = AF_MPLS; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const MSG_NBIO: ::c_int = 0x1000; pub const MSG_WAITFORONE: ::c_int = 0x2000; pub const MSG_NOTIFICATION: ::c_int = 0x4000; pub const SCM_TIMESTAMP: ::c_int = 0x08; pub const SCM_CREDS: ::c_int = 0x10; pub const O_DSYNC: ::c_int = 0x10000; pub const MAP_RENAME: ::c_int = 0x20; pub const MAP_NORESERVE: ::c_int = 0x40; pub const MAP_HASSEMAPHORE: ::c_int = 0x200; pub const MAP_TRYFIXED: ::c_int = 0x400; pub const MAP_WIRED: ::c_int = 0x800; pub const MAP_STACK: ::c_int = 0x2000; // map alignment aliases for MAP_ALIGNED pub const MAP_ALIGNMENT_SHIFT: ::c_int = 24; pub const MAP_ALIGNMENT_MASK: ::c_int = 0xff << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_64KB: ::c_int = 16 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_16MB: ::c_int = 24 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_4GB: ::c_int = 32 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_1TB: ::c_int = 40 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_256TB: ::c_int = 48 << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNMENT_64PB: ::c_int = 56 << MAP_ALIGNMENT_SHIFT; // mremap flag pub const MAP_REMAPDUP: ::c_int = 0x004; pub const DCCP_TYPE_REQUEST: ::c_int = 0; pub const DCCP_TYPE_RESPONSE: ::c_int = 1; pub const DCCP_TYPE_DATA: ::c_int = 2; pub const DCCP_TYPE_ACK: ::c_int = 3; pub const DCCP_TYPE_DATAACK: ::c_int = 4; pub const DCCP_TYPE_CLOSEREQ: ::c_int = 5; pub const DCCP_TYPE_CLOSE: ::c_int = 6; pub const DCCP_TYPE_RESET: ::c_int = 7; pub const DCCP_TYPE_MOVE: ::c_int = 8; pub const DCCP_FEATURE_CC: ::c_int = 1; pub const DCCP_FEATURE_ECN: ::c_int = 2; pub const DCCP_FEATURE_ACKRATIO: ::c_int = 3; pub const DCCP_FEATURE_ACKVECTOR: ::c_int = 4; pub const DCCP_FEATURE_MOBILITY: ::c_int = 5; pub const DCCP_FEATURE_LOSSWINDOW: ::c_int = 6; pub const DCCP_FEATURE_CONN_NONCE: ::c_int = 8; pub const DCCP_FEATURE_IDENTREG: ::c_int = 7; pub const DCCP_OPT_PADDING: ::c_int = 0; pub const DCCP_OPT_DATA_DISCARD: ::c_int = 1; pub const DCCP_OPT_SLOW_RECV: ::c_int = 2; pub const DCCP_OPT_BUF_CLOSED: ::c_int = 3; pub const DCCP_OPT_CHANGE_L: ::c_int = 32; pub const DCCP_OPT_CONFIRM_L: ::c_int = 33; pub const DCCP_OPT_CHANGE_R: ::c_int = 34; pub const DCCP_OPT_CONFIRM_R: ::c_int = 35; pub const DCCP_OPT_INIT_COOKIE: ::c_int = 36; pub const DCCP_OPT_NDP_COUNT: ::c_int = 37; pub const DCCP_OPT_ACK_VECTOR0: ::c_int = 38; pub const DCCP_OPT_ACK_VECTOR1: ::c_int = 39; pub const DCCP_OPT_RECV_BUF_DROPS: ::c_int = 40; pub const DCCP_OPT_TIMESTAMP: ::c_int = 41; pub const DCCP_OPT_TIMESTAMP_ECHO: ::c_int = 42; pub const DCCP_OPT_ELAPSEDTIME: ::c_int = 43; pub const DCCP_OPT_DATACHECKSUM: ::c_int = 44; pub const DCCP_REASON_UNSPEC: ::c_int = 0; pub const DCCP_REASON_CLOSED: ::c_int = 1; pub const DCCP_REASON_INVALID: ::c_int = 2; pub const DCCP_REASON_OPTION_ERR: ::c_int = 3; pub const DCCP_REASON_FEA_ERR: ::c_int = 4; pub const DCCP_REASON_CONN_REF: ::c_int = 5; pub const DCCP_REASON_BAD_SNAME: ::c_int = 6; pub const DCCP_REASON_BAD_COOKIE: ::c_int = 7; pub const DCCP_REASON_INV_MOVE: ::c_int = 8; pub const DCCP_REASON_UNANSW_CH: ::c_int = 10; pub const DCCP_REASON_FRUITLESS_NEG: ::c_int = 11; pub const DCCP_CCID: ::c_int = 1; pub const DCCP_CSLEN: ::c_int = 2; pub const DCCP_MAXSEG: ::c_int = 4; pub const DCCP_SERVICE: ::c_int = 8; pub const DCCP_NDP_LIMIT: ::c_int = 16; pub const DCCP_SEQ_NUM_LIMIT: ::c_int = 16777216; pub const DCCP_MAX_OPTIONS: ::c_int = 32; pub const DCCP_MAX_PKTS: ::c_int = 100; pub const _PC_LINK_MAX: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_CHOWN_RESTRICTED: ::c_int = 7; pub const _PC_NO_TRUNC: ::c_int = 8; pub const _PC_VDISABLE: ::c_int = 9; pub const _PC_SYNC_IO: ::c_int = 10; pub const _PC_FILESIZEBITS: ::c_int = 11; pub const _PC_SYMLINK_MAX: ::c_int = 12; pub const _PC_2_SYMLINKS: ::c_int = 13; pub const _PC_ACL_EXTENDED: ::c_int = 14; pub const _PC_MIN_HOLE_SIZE: ::c_int = 15; pub const _SC_SYNCHRONIZED_IO: ::c_int = 31; pub const _SC_IOV_MAX: ::c_int = 32; pub const _SC_MAPPED_FILES: ::c_int = 33; pub const _SC_MEMLOCK: ::c_int = 34; pub const _SC_MEMLOCK_RANGE: ::c_int = 35; pub const _SC_MEMORY_PROTECTION: ::c_int = 36; pub const _SC_LOGIN_NAME_MAX: ::c_int = 37; pub const _SC_MONOTONIC_CLOCK: ::c_int = 38; pub const _SC_CLK_TCK: ::c_int = 39; pub const _SC_ATEXIT_MAX: ::c_int = 40; pub const _SC_THREADS: ::c_int = 41; pub const _SC_SEMAPHORES: ::c_int = 42; pub const _SC_BARRIERS: ::c_int = 43; pub const _SC_TIMERS: ::c_int = 44; pub const _SC_SPIN_LOCKS: ::c_int = 45; pub const _SC_READER_WRITER_LOCKS: ::c_int = 46; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 47; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 48; pub const _SC_CLOCK_SELECTION: ::c_int = 49; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 50; pub const _SC_AIO_LISTIO_MAX: ::c_int = 51; pub const _SC_AIO_MAX: ::c_int = 52; pub const _SC_MESSAGE_PASSING: ::c_int = 53; pub const _SC_MQ_OPEN_MAX: ::c_int = 54; pub const _SC_MQ_PRIO_MAX: ::c_int = 55; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 56; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 57; pub const _SC_THREAD_KEYS_MAX: ::c_int = 58; pub const _SC_THREAD_STACK_MIN: ::c_int = 59; pub const _SC_THREAD_THREADS_MAX: ::c_int = 60; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 61; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 62; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 63; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 64; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 65; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 66; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 67; pub const _SC_TTY_NAME_MAX: ::c_int = 68; pub const _SC_HOST_NAME_MAX: ::c_int = 69; pub const _SC_PASS_MAX: ::c_int = 70; pub const _SC_REGEXP: ::c_int = 71; pub const _SC_SHELL: ::c_int = 72; pub const _SC_SYMLOOP_MAX: ::c_int = 73; pub const _SC_V6_ILP32_OFF32: ::c_int = 74; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 75; pub const _SC_V6_LP64_OFF64: ::c_int = 76; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 77; pub const _SC_2_PBS: ::c_int = 80; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 81; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 82; pub const _SC_2_PBS_LOCATE: ::c_int = 83; pub const _SC_2_PBS_MESSAGE: ::c_int = 84; pub const _SC_2_PBS_TRACK: ::c_int = 85; pub const _SC_SPAWN: ::c_int = 86; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 87; pub const _SC_TIMER_MAX: ::c_int = 88; pub const _SC_SEM_NSEMS_MAX: ::c_int = 89; pub const _SC_CPUTIME: ::c_int = 90; pub const _SC_THREAD_CPUTIME: ::c_int = 91; pub const _SC_DELAYTIMER_MAX: ::c_int = 92; // These two variables will be supported in NetBSD 8.0 // pub const _SC_SIGQUEUE_MAX : ::c_int = 93; // pub const _SC_REALTIME_SIGNALS : ::c_int = 94; pub const _SC_PHYS_PAGES: ::c_int = 121; pub const _SC_NPROCESSORS_CONF: ::c_int = 1001; pub const _SC_NPROCESSORS_ONLN: ::c_int = 1002; pub const _SC_SCHED_RT_TS: ::c_int = 2001; pub const _SC_SCHED_PRI_MIN: ::c_int = 2002; pub const _SC_SCHED_PRI_MAX: ::c_int = 2003; pub const FD_SETSIZE: usize = 0x100; pub const ST_NOSUID: ::c_ulong = 8; pub const BIOCGRSIG: ::c_ulong = 0x40044272; pub const BIOCSRSIG: ::c_ulong = 0x80044273; pub const BIOCSDLT: ::c_ulong = 0x80044278; pub const BIOCGSEESENT: ::c_ulong = 0x40044276; pub const BIOCSSEESENT: ::c_ulong = 0x80044277; // pub const MNT_UNION: ::c_int = 0x00000020; pub const MNT_NOCOREDUMP: ::c_int = 0x00008000; pub const MNT_RELATIME: ::c_int = 0x00020000; pub const MNT_IGNORE: ::c_int = 0x00100000; pub const MNT_NFS4ACLS: ::c_int = 0x00200000; pub const MNT_DISCARD: ::c_int = 0x00800000; pub const MNT_EXTATTR: ::c_int = 0x01000000; pub const MNT_LOG: ::c_int = 0x02000000; pub const MNT_NOATIME: ::c_int = 0x04000000; pub const MNT_AUTOMOUNTED: ::c_int = 0x10000000; pub const MNT_SYMPERM: ::c_int = 0x20000000; pub const MNT_NODEVMTIME: ::c_int = 0x40000000; pub const MNT_SOFTDEP: ::c_int = 0x80000000; pub const MNT_POSIX1EACLS: ::c_int = 0x00000800; pub const MNT_ACLS: ::c_int = MNT_POSIX1EACLS; pub const MNT_WAIT: ::c_int = 1; pub const MNT_NOWAIT: ::c_int = 2; pub const MNT_LAZY: ::c_int = 3; // pub const NTP_API: ::c_int = 4; pub const MAXPHASE: ::c_long = 500000000; pub const MAXFREQ: ::c_long = 500000; pub const MINSEC: ::c_int = 256; pub const MAXSEC: ::c_int = 2048; pub const NANOSECOND: ::c_long = 1000000000; pub const SCALE_PPM: ::c_int = 65; pub const MAXTC: ::c_int = 10; pub const MOD_OFFSET: ::c_uint = 0x0001; pub const MOD_FREQUENCY: ::c_uint = 0x0002; pub const MOD_MAXERROR: ::c_uint = 0x0004; pub const MOD_ESTERROR: ::c_uint = 0x0008; pub const MOD_STATUS: ::c_uint = 0x0010; pub const MOD_TIMECONST: ::c_uint = 0x0020; pub const MOD_PPSMAX: ::c_uint = 0x0040; pub const MOD_TAI: ::c_uint = 0x0080; pub const MOD_MICRO: ::c_uint = 0x1000; pub const MOD_NANO: ::c_uint = 0x2000; pub const MOD_CLKB: ::c_uint = 0x4000; pub const MOD_CLKA: ::c_uint = 0x8000; pub const STA_PLL: ::c_int = 0x0001; pub const STA_PPSFREQ: ::c_int = 0x0002; pub const STA_PPSTIME: ::c_int = 0x0004; pub const STA_FLL: ::c_int = 0x0008; pub const STA_INS: ::c_int = 0x0010; pub const STA_DEL: ::c_int = 0x0020; pub const STA_UNSYNC: ::c_int = 0x0040; pub const STA_FREQHOLD: ::c_int = 0x0080; pub const STA_PPSSIGNAL: ::c_int = 0x0100; pub const STA_PPSJITTER: ::c_int = 0x0200; pub const STA_PPSWANDER: ::c_int = 0x0400; pub const STA_PPSERROR: ::c_int = 0x0800; pub const STA_CLOCKERR: ::c_int = 0x1000; pub const STA_NANO: ::c_int = 0x2000; pub const STA_MODE: ::c_int = 0x4000; pub const STA_CLK: ::c_int = 0x8000; pub const STA_RONLY: ::c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: ::c_int = 0; pub const TIME_INS: ::c_int = 1; pub const TIME_DEL: ::c_int = 2; pub const TIME_OOP: ::c_int = 3; pub const TIME_WAIT: ::c_int = 4; pub const TIME_ERROR: ::c_int = 5; pub const LITTLE_ENDIAN: ::c_int = 1234; pub const BIG_ENDIAN: ::c_int = 4321; pub const PL_EVENT_NONE: ::c_int = 0; pub const PL_EVENT_SIGNAL: ::c_int = 1; pub const PL_EVENT_SUSPENDED: ::c_int = 2; cfg_if! { if #[cfg(any(target_arch = "sparc", target_arch = "sparc64", target_arch = "x86", target_arch = "x86_64"))] { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { ptm_magic: 0x33330003, ptm_errorcheck: 0, ptm_pad1: [0; 3], ptm_unused: 0, ptm_pad2: [0; 3], ptm_waiters: 0 as *mut _, ptm_owner: 0, ptm_recursed: 0, ptm_spare2: 0 as *mut _, }; } else { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { ptm_magic: 0x33330003, ptm_errorcheck: 0, ptm_unused: 0, ptm_waiters: 0 as *mut _, ptm_owner: 0, ptm_recursed: 0, ptm_spare2: 0 as *mut _, }; } } pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { ptc_magic: 0x55550005, ptc_lock: 0, ptc_waiters_first: 0 as *mut _, ptc_waiters_last: 0 as *mut _, ptc_mutex: 0 as *mut _, ptc_private: 0 as *mut _, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { ptr_magic: 0x99990009, ptr_interlock: 0, ptr_rblocked_first: 0 as *mut _, ptr_rblocked_last: 0 as *mut _, ptr_wblocked_first: 0 as *mut _, ptr_wblocked_last: 0 as *mut _, ptr_nreaders: 0, ptr_owner: 0, ptr_private: 0 as *mut _, }; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const SCHED_NONE: ::c_int = -1; pub const SCHED_OTHER: ::c_int = 0; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; pub const EVFILT_AIO: u32 = 2; pub const EVFILT_PROC: u32 = 4; pub const EVFILT_READ: u32 = 0; pub const EVFILT_SIGNAL: u32 = 5; pub const EVFILT_TIMER: u32 = 6; pub const EVFILT_VNODE: u32 = 3; pub const EVFILT_WRITE: u32 = 1; pub const EVFILT_FS: u32 = 7; pub const EVFILT_USER: u32 = 8; pub const EVFILT_EMPTY: u32 = 9; pub const EV_ADD: u32 = 0x1; pub const EV_DELETE: u32 = 0x2; pub const EV_ENABLE: u32 = 0x4; pub const EV_DISABLE: u32 = 0x8; pub const EV_ONESHOT: u32 = 0x10; pub const EV_CLEAR: u32 = 0x20; pub const EV_RECEIPT: u32 = 0x40; pub const EV_DISPATCH: u32 = 0x80; pub const EV_FLAG1: u32 = 0x2000; pub const EV_ERROR: u32 = 0x4000; pub const EV_EOF: u32 = 0x8000; pub const EV_SYSFLAGS: u32 = 0xf000; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const NOTE_MSECONDS: u32 = 0x00000000; pub const NOTE_SECONDS: u32 = 0x00000001; pub const NOTE_USECONDS: u32 = 0x00000002; pub const NOTE_NSECONDS: u32 = 0x00000003; pub const NOTE_ABSTIME: u32 = 0x000000010; pub const TMP_MAX: ::c_uint = 308915776; pub const AI_PASSIVE: ::c_int = 0x00000001; pub const AI_CANONNAME: ::c_int = 0x00000002; pub const AI_NUMERICHOST: ::c_int = 0x00000004; pub const AI_NUMERICSERV: ::c_int = 0x00000008; pub const AI_ADDRCONFIG: ::c_int = 0x00000400; pub const AI_SRV: ::c_int = 0x00000800; pub const NI_MAXHOST: ::socklen_t = 1025; pub const NI_MAXSERV: ::socklen_t = 32; pub const NI_NOFQDN: ::c_int = 0x00000001; pub const NI_NUMERICHOST: ::c_int = 0x000000002; pub const NI_NAMEREQD: ::c_int = 0x000000004; pub const NI_NUMERICSERV: ::c_int = 0x000000008; pub const NI_DGRAM: ::c_int = 0x00000010; pub const NI_WITHSCOPEID: ::c_int = 0x00000020; pub const NI_NUMERICSCOPE: ::c_int = 0x00000040; pub const RTLD_NOLOAD: ::c_int = 0x2000; pub const RTLD_LOCAL: ::c_int = 0x200; pub const CTL_MAXNAME: ::c_int = 12; pub const SYSCTL_NAMELEN: ::c_int = 32; pub const SYSCTL_DEFSIZE: ::c_int = 8; pub const CTLTYPE_NODE: ::c_int = 1; pub const CTLTYPE_INT: ::c_int = 2; pub const CTLTYPE_STRING: ::c_int = 3; pub const CTLTYPE_QUAD: ::c_int = 4; pub const CTLTYPE_STRUCT: ::c_int = 5; pub const CTLTYPE_BOOL: ::c_int = 6; pub const CTLFLAG_READONLY: ::c_int = 0x00000000; pub const CTLFLAG_READWRITE: ::c_int = 0x00000070; pub const CTLFLAG_ANYWRITE: ::c_int = 0x00000080; pub const CTLFLAG_PRIVATE: ::c_int = 0x00000100; pub const CTLFLAG_PERMANENT: ::c_int = 0x00000200; pub const CTLFLAG_OWNDATA: ::c_int = 0x00000400; pub const CTLFLAG_IMMEDIATE: ::c_int = 0x00000800; pub const CTLFLAG_HEX: ::c_int = 0x00001000; pub const CTLFLAG_ROOT: ::c_int = 0x00002000; pub const CTLFLAG_ANYNUMBER: ::c_int = 0x00004000; pub const CTLFLAG_HIDDEN: ::c_int = 0x00008000; pub const CTLFLAG_ALIAS: ::c_int = 0x00010000; pub const CTLFLAG_MMAP: ::c_int = 0x00020000; pub const CTLFLAG_OWNDESC: ::c_int = 0x00040000; pub const CTLFLAG_UNSIGNED: ::c_int = 0x00080000; pub const SYSCTL_VERS_MASK: ::c_int = 0xff000000; pub const SYSCTL_VERS_0: ::c_int = 0x00000000; pub const SYSCTL_VERS_1: ::c_int = 0x01000000; pub const SYSCTL_VERSION: ::c_int = SYSCTL_VERS_1; pub const CTL_EOL: ::c_int = -1; pub const CTL_QUERY: ::c_int = -2; pub const CTL_CREATE: ::c_int = -3; pub const CTL_CREATESYM: ::c_int = -4; pub const CTL_DESTROY: ::c_int = -5; pub const CTL_MMAP: ::c_int = -6; pub const CTL_DESCRIBE: ::c_int = -7; pub const CTL_UNSPEC: ::c_int = 0; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_VFS: ::c_int = 3; pub const CTL_NET: ::c_int = 4; pub const CTL_DEBUG: ::c_int = 5; pub const CTL_HW: ::c_int = 6; pub const CTL_MACHDEP: ::c_int = 7; pub const CTL_USER: ::c_int = 8; pub const CTL_DDB: ::c_int = 9; pub const CTL_PROC: ::c_int = 10; pub const CTL_VENDOR: ::c_int = 11; pub const CTL_EMUL: ::c_int = 12; pub const CTL_SECURITY: ::c_int = 13; pub const CTL_MAXID: ::c_int = 14; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_VERSION: ::c_int = 4; pub const KERN_MAXVNODES: ::c_int = 5; pub const KERN_MAXPROC: ::c_int = 6; pub const KERN_MAXFILES: ::c_int = 7; pub const KERN_ARGMAX: ::c_int = 8; pub const KERN_SECURELVL: ::c_int = 9; pub const KERN_HOSTNAME: ::c_int = 10; pub const KERN_HOSTID: ::c_int = 11; pub const KERN_CLOCKRATE: ::c_int = 12; pub const KERN_VNODE: ::c_int = 13; pub const KERN_PROC: ::c_int = 14; pub const KERN_FILE: ::c_int = 15; pub const KERN_PROF: ::c_int = 16; pub const KERN_POSIX1: ::c_int = 17; pub const KERN_NGROUPS: ::c_int = 18; pub const KERN_JOB_CONTROL: ::c_int = 19; pub const KERN_SAVED_IDS: ::c_int = 20; pub const KERN_OBOOTTIME: ::c_int = 21; pub const KERN_DOMAINNAME: ::c_int = 22; pub const KERN_MAXPARTITIONS: ::c_int = 23; pub const KERN_RAWPARTITION: ::c_int = 24; pub const KERN_NTPTIME: ::c_int = 25; pub const KERN_TIMEX: ::c_int = 26; pub const KERN_AUTONICETIME: ::c_int = 27; pub const KERN_AUTONICEVAL: ::c_int = 28; pub const KERN_RTC_OFFSET: ::c_int = 29; pub const KERN_ROOT_DEVICE: ::c_int = 30; pub const KERN_MSGBUFSIZE: ::c_int = 31; pub const KERN_FSYNC: ::c_int = 32; pub const KERN_OLDSYSVMSG: ::c_int = 33; pub const KERN_OLDSYSVSEM: ::c_int = 34; pub const KERN_OLDSYSVSHM: ::c_int = 35; pub const KERN_OLDSHORTCORENAME: ::c_int = 36; pub const KERN_SYNCHRONIZED_IO: ::c_int = 37; pub const KERN_IOV_MAX: ::c_int = 38; pub const KERN_MBUF: ::c_int = 39; pub const KERN_MAPPED_FILES: ::c_int = 40; pub const KERN_MEMLOCK: ::c_int = 41; pub const KERN_MEMLOCK_RANGE: ::c_int = 42; pub const KERN_MEMORY_PROTECTION: ::c_int = 43; pub const KERN_LOGIN_NAME_MAX: ::c_int = 44; pub const KERN_DEFCORENAME: ::c_int = 45; pub const KERN_LOGSIGEXIT: ::c_int = 46; pub const KERN_PROC2: ::c_int = 47; pub const KERN_PROC_ARGS: ::c_int = 48; pub const KERN_FSCALE: ::c_int = 49; pub const KERN_CCPU: ::c_int = 50; pub const KERN_CP_TIME: ::c_int = 51; pub const KERN_OLDSYSVIPC_INFO: ::c_int = 52; pub const KERN_MSGBUF: ::c_int = 53; pub const KERN_CONSDEV: ::c_int = 54; pub const KERN_MAXPTYS: ::c_int = 55; pub const KERN_PIPE: ::c_int = 56; pub const KERN_MAXPHYS: ::c_int = 57; pub const KERN_SBMAX: ::c_int = 58; pub const KERN_TKSTAT: ::c_int = 59; pub const KERN_MONOTONIC_CLOCK: ::c_int = 60; pub const KERN_URND: ::c_int = 61; pub const KERN_LABELSECTOR: ::c_int = 62; pub const KERN_LABELOFFSET: ::c_int = 63; pub const KERN_LWP: ::c_int = 64; pub const KERN_FORKFSLEEP: ::c_int = 65; pub const KERN_POSIX_THREADS: ::c_int = 66; pub const KERN_POSIX_SEMAPHORES: ::c_int = 67; pub const KERN_POSIX_BARRIERS: ::c_int = 68; pub const KERN_POSIX_TIMERS: ::c_int = 69; pub const KERN_POSIX_SPIN_LOCKS: ::c_int = 70; pub const KERN_POSIX_READER_WRITER_LOCKS: ::c_int = 71; pub const KERN_DUMP_ON_PANIC: ::c_int = 72; pub const KERN_SOMAXKVA: ::c_int = 73; pub const KERN_ROOT_PARTITION: ::c_int = 74; pub const KERN_DRIVERS: ::c_int = 75; pub const KERN_BUF: ::c_int = 76; pub const KERN_FILE2: ::c_int = 77; pub const KERN_VERIEXEC: ::c_int = 78; pub const KERN_CP_ID: ::c_int = 79; pub const KERN_HARDCLOCK_TICKS: ::c_int = 80; pub const KERN_ARND: ::c_int = 81; pub const KERN_SYSVIPC: ::c_int = 82; pub const KERN_BOOTTIME: ::c_int = 83; pub const KERN_EVCNT: ::c_int = 84; pub const KERN_MAXID: ::c_int = 85; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_PID: ::c_int = 1; pub const KERN_PROC_PGRP: ::c_int = 2; pub const KERN_PROC_SESSION: ::c_int = 3; pub const KERN_PROC_TTY: ::c_int = 4; pub const KERN_PROC_UID: ::c_int = 5; pub const KERN_PROC_RUID: ::c_int = 6; pub const KERN_PROC_GID: ::c_int = 7; pub const KERN_PROC_RGID: ::c_int = 8; pub const KERN_PROC_ARGV: ::c_int = 1; pub const KERN_PROC_NARGV: ::c_int = 2; pub const KERN_PROC_ENV: ::c_int = 3; pub const KERN_PROC_NENV: ::c_int = 4; pub const KERN_PROC_PATHNAME: ::c_int = 5; pub const VM_PROC: ::c_int = 16; pub const VM_PROC_MAP: ::c_int = 1; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_NODATA: ::c_int = 7; pub const EAI_NONAME: ::c_int = 8; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 14; pub const AIO_CANCELED: ::c_int = 1; pub const AIO_NOTCANCELED: ::c_int = 2; pub const AIO_ALLDONE: ::c_int = 3; pub const LIO_NOP: ::c_int = 0; pub const LIO_WRITE: ::c_int = 1; pub const LIO_READ: ::c_int = 2; pub const LIO_WAIT: ::c_int = 1; pub const LIO_NOWAIT: ::c_int = 0; pub const SIGEV_NONE: ::c_int = 0; pub const SIGEV_SIGNAL: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 2; pub const WSTOPPED: ::c_int = 0x00000002; // same as WUNTRACED pub const WCONTINUED: ::c_int = 0x00000010; pub const WEXITED: ::c_int = 0x000000020; pub const WNOWAIT: ::c_int = 0x00010000; pub const WALTSIG: ::c_int = 0x00000004; pub const WALLSIG: ::c_int = 0x00000008; pub const WTRAPPED: ::c_int = 0x00000040; pub const WNOZOMBIE: ::c_int = 0x00020000; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 4; pub const UTIME_OMIT: c_long = 1073741822; pub const UTIME_NOW: c_long = 1073741823; pub const B460800: ::speed_t = 460800; pub const B921600: ::speed_t = 921600; pub const ONOCR: ::tcflag_t = 0x20; pub const ONLRET: ::tcflag_t = 0x40; pub const CDTRCTS: ::tcflag_t = 0x00020000; pub const CHWFLOW: ::tcflag_t = ::MDMBUF | ::CRTSCTS | ::CDTRCTS; // pub const _PATH_UTMPX: &[::c_char; 14] = b"/var/run/utmpx"; // pub const _PATH_WTMPX: &[::c_char; 14] = b"/var/log/wtmpx"; // pub const _PATH_LASTLOGX: &[::c_char; 17] = b"/var/log/lastlogx"; // pub const _PATH_UTMP_UPDATE: &[::c_char; 24] = b"/usr/libexec/utmp_update"; pub const UT_NAMESIZE: usize = 8; pub const UT_LINESIZE: usize = 8; pub const UT_HOSTSIZE: usize = 16; pub const _UTX_USERSIZE: usize = 32; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_PADSIZE: usize = 40; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 256; pub const EMPTY: u16 = 0; pub const RUN_LVL: u16 = 1; pub const BOOT_TIME: u16 = 2; pub const OLD_TIME: u16 = 3; pub const NEW_TIME: u16 = 4; pub const INIT_PROCESS: u16 = 5; pub const LOGIN_PROCESS: u16 = 6; pub const USER_PROCESS: u16 = 7; pub const DEAD_PROCESS: u16 = 8; pub const ACCOUNTING: u16 = 9; pub const SIGNATURE: u16 = 10; pub const DOWN_TIME: u16 = 11; pub const SOCK_CLOEXEC: ::c_int = 0x10000000; pub const SOCK_NONBLOCK: ::c_int = 0x20000000; // Uncomment on next NetBSD release // pub const FIOSEEKDATA: ::c_ulong = 0xc0086661; // pub const FIOSEEKHOLE: ::c_ulong = 0xc0086662; pub const OFIOGETBMAP: ::c_ulong = 0xc004667a; pub const FIOGETBMAP: ::c_ulong = 0xc008667a; pub const FIONWRITE: ::c_ulong = 0x40046679; pub const FIONSPACE: ::c_ulong = 0x40046678; pub const FIBMAP: ::c_ulong = 0xc008667a; pub const SIGSTKSZ: ::size_t = 40960; pub const REG_ENOSYS: ::c_int = 17; pub const PT_DUMPCORE: ::c_int = 12; pub const PT_LWPINFO: ::c_int = 13; pub const PT_SYSCALL: ::c_int = 14; pub const PT_SYSCALLEMU: ::c_int = 15; pub const PT_SET_EVENT_MASK: ::c_int = 16; pub const PT_GET_EVENT_MASK: ::c_int = 17; pub const PT_GET_PROCESS_STATE: ::c_int = 18; pub const PT_SET_SIGINFO: ::c_int = 19; pub const PT_GET_SIGINFO: ::c_int = 20; pub const PT_RESUME: ::c_int = 21; pub const PT_SUSPEND: ::c_int = 23; pub const PT_STOP: ::c_int = 23; pub const PT_LWPSTATUS: ::c_int = 24; pub const PT_LWPNEXT: ::c_int = 25; pub const PT_SET_SIGPASS: ::c_int = 26; pub const PT_GET_SIGPASS: ::c_int = 27; pub const PT_FIRSTMACH: ::c_int = 32; pub const POSIX_SPAWN_RETURNERROR: ::c_int = 0x40; // Flags for chflags(2) pub const SF_APPEND: ::c_ulong = 0x00040000; pub const SF_ARCHIVED: ::c_ulong = 0x00010000; pub const SF_IMMUTABLE: ::c_ulong = 0x00020000; pub const SF_LOG: ::c_ulong = 0x00400000; pub const SF_SETTABLE: ::c_ulong = 0xffff0000; pub const SF_SNAPINVAL: ::c_ulong = 0x00800000; pub const SF_SNAPSHOT: ::c_ulong = 0x00200000; pub const UF_APPEND: ::c_ulong = 0x00000004; pub const UF_IMMUTABLE: ::c_ulong = 0x00000002; pub const UF_NODUMP: ::c_ulong = 0x00000001; pub const UF_OPAQUE: ::c_ulong = 0x00000008; pub const UF_SETTABLE: ::c_ulong = 0x0000ffff; // sys/sysctl.h pub const KVME_PROT_READ: ::c_int = 0x00000001; pub const KVME_PROT_WRITE: ::c_int = 0x00000002; pub const KVME_PROT_EXEC: ::c_int = 0x00000004; pub const KVME_FLAG_COW: ::c_int = 0x00000001; pub const KVME_FLAG_NEEDS_COPY: ::c_int = 0x00000002; pub const KVME_FLAG_NOCOREDUMP: ::c_int = 0x000000004; pub const KVME_FLAG_PAGEABLE: ::c_int = 0x000000008; pub const KVME_FLAG_GROWS_UP: ::c_int = 0x000000010; pub const KVME_FLAG_GROWS_DOWN: ::c_int = 0x000000020; pub const NGROUPS_MAX: ::c_int = 16; pub const KI_NGROUPS: ::c_int = 16; pub const KI_MAXCOMLEN: ::c_int = 24; pub const KI_WMESGLEN: ::c_int = 8; pub const KI_MAXLOGNAME: ::c_int = 24; pub const KI_MAXEMULLEN: ::c_int = 16; pub const KI_LNAMELEN: ::c_int = 20; // sys/lwp.h pub const LSIDL: ::c_int = 1; pub const LSRUN: ::c_int = 2; pub const LSSLEEP: ::c_int = 3; pub const LSSTOP: ::c_int = 4; pub const LSZOMB: ::c_int = 5; pub const LSONPROC: ::c_int = 7; pub const LSSUSPENDED: ::c_int = 8; // sys/xattr.h pub const XATTR_CREATE: ::c_int = 0x01; pub const XATTR_REPLACE: ::c_int = 0x02; // sys/extattr.h pub const EXTATTR_NAMESPACE_EMPTY: ::c_int = 0; // For getrandom() pub const GRND_NONBLOCK: ::c_uint = 0x1; pub const GRND_RANDOM: ::c_uint = 0x2; pub const GRND_INSECURE: ::c_uint = 0x4; // sys/reboot.h pub const RB_ASKNAME: ::c_int = 0x000000001; pub const RB_SINGLE: ::c_int = 0x000000002; pub const RB_NOSYNC: ::c_int = 0x000000004; pub const RB_HALT: ::c_int = 0x000000008; pub const RB_INITNAME: ::c_int = 0x000000010; pub const RB_KDB: ::c_int = 0x000000040; pub const RB_RDONLY: ::c_int = 0x000000080; pub const RB_DUMP: ::c_int = 0x000000100; pub const RB_MINIROOT: ::c_int = 0x000000200; pub const RB_STRING: ::c_int = 0x000000400; pub const RB_POWERDOWN: ::c_int = RB_HALT | 0x000000800; pub const RB_USERCONF: ::c_int = 0x000001000; cfg_if! { if #[cfg(libc_const_extern_fn)] { pub const fn MAP_ALIGNED(alignment: ::c_int) -> ::c_int { alignment << MAP_ALIGNMENT_SHIFT } } else { pub fn MAP_ALIGNED(alignment: ::c_int) -> ::c_int { alignment << MAP_ALIGNMENT_SHIFT } } } const_fn! { {const} fn _ALIGN(p: usize) -> usize { (p + _ALIGNBYTES) & !_ALIGNBYTES } } f! { pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { _ALIGN(::mem::size_of::<::cmsghdr>()) as ::c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr) -> *mut ::cmsghdr { if cmsg.is_null() { return ::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize) + _ALIGN(::mem::size_of::<::cmsghdr>()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut ::cmsghdr } else { (cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize)) as *mut ::cmsghdr } } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_ALIGN(::mem::size_of::<::cmsghdr>()) + _ALIGN(length as usize)) as ::c_uint } // dirfd() is a macro on netbsd to access // the first field of the struct where dirp points to: // http://cvsweb.netbsd.org/bsdweb.cgi/src/include/dirent.h?rev=1.36 pub fn dirfd(dirp: *mut ::DIR) -> ::c_int { *(dirp as *const ::c_int) } pub fn SOCKCREDSIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; ::mem::size_of::() + ::mem::size_of::<::gid_t>() * ngrps } pub fn PROT_MPROTECT(x: ::c_int) -> ::c_int { x << 3 } pub fn PROT_MPROTECT_EXTRACT(x: ::c_int) -> ::c_int { (x >> 3) & 0x7 } pub fn major(dev: ::dev_t) -> ::c_int { (((dev as u32) & 0x000fff00) >> 8) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { let mut res = 0; res |= ((dev as u32) & 0xfff00000) >> 12; res |= (dev as u32) & 0x000000ff; res as ::c_int } } safe_f! { pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { status >> 8 } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0o177) == 0o177 } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { status == 0xffff } pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= (major << 8) & 0x000ff00; dev |= (minor << 12) & 0xfff00000; dev |= minor & 0xff; dev } } extern "C" { pub fn ntp_adjtime(buf: *mut timex) -> ::c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn reallocarr(ptr: *mut ::c_void, number: ::size_t, size: ::size_t) -> ::c_int; pub fn chflags(path: *const ::c_char, flags: ::c_ulong) -> ::c_int; pub fn fchflags(fd: ::c_int, flags: ::c_ulong) -> ::c_int; pub fn lchflags(path: *const ::c_char, flags: ::c_ulong) -> ::c_int; pub fn extattr_list_fd( fd: ::c_int, attrnamespace: ::c_int, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_list_file( path: *const ::c_char, attrnamespace: ::c_int, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_list_link( path: *const ::c_char, attrnamespace: ::c_int, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_delete_fd( fd: ::c_int, attrnamespace: ::c_int, attrname: *const ::c_char, ) -> ::c_int; pub fn extattr_delete_file( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, ) -> ::c_int; pub fn extattr_delete_link( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, ) -> ::c_int; pub fn extattr_get_fd( fd: ::c_int, attrnamespace: ::c_int, attrname: *const ::c_char, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_get_file( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_get_link( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_namespace_to_string( attrnamespace: ::c_int, string: *mut *mut ::c_char, ) -> ::c_int; pub fn extattr_set_fd( fd: ::c_int, attrnamespace: ::c_int, attrname: *const ::c_char, data: *const ::c_void, nbytes: ::size_t, ) -> ::c_int; pub fn extattr_set_file( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *const ::c_void, nbytes: ::size_t, ) -> ::c_int; pub fn extattr_set_link( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *const ::c_void, nbytes: ::size_t, ) -> ::c_int; pub fn extattr_string_to_namespace( string: *const ::c_char, attrnamespace: *mut ::c_int, ) -> ::c_int; pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *mut ::termios, winp: *mut ::winsize, ) -> ::c_int; pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *mut ::termios, winp: *mut ::winsize, ) -> ::pid_t; #[link_name = "__lutimes50"] pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; #[link_name = "__gettimeofday50"] pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn sysctl( name: *const ::c_int, namelen: ::c_uint, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *const ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn sysctlbyname( name: *const ::c_char, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *const ::c_void, newlen: ::size_t, ) -> ::c_int; #[link_name = "__kevent50"] pub fn kevent( kq: ::c_int, changelist: *const ::kevent, nchanges: ::size_t, eventlist: *mut ::kevent, nevents: ::size_t, timeout: *const ::timespec, ) -> ::c_int; #[link_name = "__mount50"] pub fn mount( src: *const ::c_char, target: *const ::c_char, flags: ::c_int, data: *mut ::c_void, size: ::size_t, ) -> ::c_int; pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) -> ::c_int; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_send( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; #[link_name = "__mq_timedreceive50"] pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, abs_timeout: *const ::timespec, ) -> ::ssize_t; #[link_name = "__mq_timedsend50"] pub fn mq_timedsend( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: *mut ::c_void, data: ::c_int) -> ::c_int; pub fn utrace(label: *const ::c_char, addr: *mut ::c_void, len: ::size_t) -> ::c_int; pub fn pthread_getname_np(t: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_setname_np( t: ::pthread_t, name: *const ::c_char, arg: *const ::c_void, ) -> ::c_int; pub fn pthread_attr_get_np(thread: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_getattr_np(native: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_getaffinity_np( thread: ::pthread_t, size: ::size_t, set: *mut cpuset_t, ) -> ::c_int; pub fn pthread_setaffinity_np( thread: ::pthread_t, size: ::size_t, set: *mut cpuset_t, ) -> ::c_int; pub fn _cpuset_create() -> *mut cpuset_t; pub fn _cpuset_destroy(set: *mut cpuset_t); pub fn _cpuset_clr(cpu: cpuid_t, set: *mut cpuset_t) -> ::c_int; pub fn _cpuset_set(cpu: cpuid_t, set: *mut cpuset_t) -> ::c_int; pub fn _cpuset_isset(cpu: cpuid_t, set: *const cpuset_t) -> ::c_int; pub fn _cpuset_size(set: *const cpuset_t) -> ::size_t; pub fn _cpuset_zero(set: *mut cpuset_t); #[link_name = "__sigtimedwait50"] pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t); pub fn localeconv_l(loc: ::locale_t) -> *mut lconv; pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; #[link_name = "__settimeofday50"] pub fn settimeofday(tv: *const ::timeval, tz: *const ::c_void) -> ::c_int; pub fn dup3(src: ::c_int, dst: ::c_int, flags: ::c_int) -> ::c_int; pub fn kqueue1(flags: ::c_int) -> ::c_int; pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, ) -> ::c_int; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::c_uint, flags: ::c_int, timeout: *mut ::timespec, ) -> ::c_int; pub fn _lwp_self() -> lwpid_t; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; // link.h pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut dl_phdr_info, size: usize, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; // dlfcn.h pub fn _dlauxinfo() -> *mut ::c_void; pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, inbytesleft: *mut ::size_t, outbuf: *mut *mut ::c_char, outbytesleft: *mut ::size_t, ) -> ::size_t; pub fn iconv_close(cd: iconv_t) -> ::c_int; pub fn timer_create( clockid: ::clockid_t, sevp: *mut ::sigevent, timerid: *mut ::timer_t, ) -> ::c_int; pub fn timer_delete(timerid: ::timer_t) -> ::c_int; pub fn timer_getoverrun(timerid: ::timer_t) -> ::c_int; pub fn timer_gettime(timerid: ::timer_t, curr_value: *mut ::itimerspec) -> ::c_int; pub fn timer_settime( timerid: ::timer_t, flags: ::c_int, new_value: *const ::itimerspec, old_value: *mut ::itimerspec, ) -> ::c_int; // Added in `NetBSD` 7.0 pub fn explicit_memset(b: *mut ::c_void, c: ::c_int, len: ::size_t); pub fn consttime_memequal(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int; pub fn setproctitle(fmt: *const ::c_char, ...); pub fn mremap( oldp: *mut ::c_void, oldsize: ::size_t, newp: *mut ::c_void, newsize: ::size_t, flags: ::c_int, ) -> *mut ::c_void; pub fn sched_rr_get_interval(pid: ::pid_t, t: *mut ::timespec) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const ::sched_param) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut ::sched_param) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; #[link_name = "__pollts50"] pub fn pollts( fds: *mut ::pollfd, nfds: ::nfds_t, ts: *const ::timespec, sigmask: *const ::sigset_t, ) -> ::c_int; pub fn ppoll( fds: *mut ::pollfd, nfds: ::nfds_t, ts: *const ::timespec, sigmask: *const ::sigset_t, ) -> ::c_int; pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn reboot(mode: ::c_int, bootstr: *mut ::c_char) -> ::c_int; } #[link(name = "rt")] extern "C" { pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_error(aiocbp: *const aiocb) -> ::c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t; #[link_name = "__aio_suspend50"] pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn lio_listio( mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent, ) -> ::c_int; } #[link(name = "util")] extern "C" { #[cfg_attr(target_os = "netbsd", link_name = "__getpwent_r50")] pub fn getpwent_r( pwd: *mut ::passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::passwd, ) -> ::c_int; pub fn getgrent_r( grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn updwtmpx(file: *const ::c_char, ut: *const utmpx) -> ::c_int; pub fn getlastlogx(fname: *const ::c_char, uid: ::uid_t, ll: *mut lastlogx) -> *mut lastlogx; pub fn updlastlogx(fname: *const ::c_char, uid: ::uid_t, ll: *mut lastlogx) -> ::c_int; pub fn utmpxname(file: *const ::c_char) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn getutmp(ux: *const utmpx, u: *mut utmp); pub fn getutmpx(u: *const utmp, ux: *mut utmpx); pub fn utpname(file: *const ::c_char) -> ::c_int; pub fn setutent(); pub fn endutent(); pub fn getutent() -> *mut utmp; pub fn efopen(p: *const ::c_char, m: *const ::c_char) -> ::FILE; pub fn emalloc(n: ::size_t) -> *mut ::c_void; pub fn ecalloc(n: ::size_t, c: ::size_t) -> *mut ::c_void; pub fn erealloc(p: *mut ::c_void, n: ::size_t) -> *mut ::c_void; pub fn ereallocarr(p: *mut ::c_void, n: ::size_t, s: ::size_t); pub fn estrdup(s: *const ::c_char) -> *mut ::c_char; pub fn estrndup(s: *const ::c_char, len: ::size_t) -> *mut ::c_char; pub fn estrlcpy(dst: *mut ::c_char, src: *const ::c_char, len: ::size_t) -> ::size_t; pub fn estrlcat(dst: *mut ::c_char, src: *const ::c_char, len: ::size_t) -> ::size_t; pub fn estrtoi( nptr: *const ::c_char, base: ::c_int, lo: ::intmax_t, hi: ::intmax_t, ) -> ::intmax_t; pub fn estrtou( nptr: *const ::c_char, base: ::c_int, lo: ::uintmax_t, hi: ::uintmax_t, ) -> ::uintmax_t; pub fn easprintf(string: *mut *mut ::c_char, fmt: *const ::c_char, ...) -> ::c_int; pub fn evasprintf(string: *mut *mut ::c_char, fmt: *const ::c_char, ...) -> ::c_int; pub fn esetfunc( cb: ::Option, ) -> ::Option; pub fn secure_path(path: *const ::c_char) -> ::c_int; pub fn snprintb( buf: *mut ::c_char, buflen: ::size_t, fmt: *const ::c_char, val: u64, ) -> ::c_int; pub fn snprintb_m( buf: *mut ::c_char, buflen: ::size_t, fmt: *const ::c_char, val: u64, max: ::size_t, ) -> ::c_int; pub fn getbootfile() -> *const ::c_char; pub fn getbyteorder() -> ::c_int; pub fn getdiskrawname( buf: *mut ::c_char, buflen: ::size_t, name: *const ::c_char, ) -> *const ::c_char; pub fn getdiskcookedname( buf: *mut ::c_char, buflen: ::size_t, name: *const ::c_char, ) -> *const ::c_char; pub fn getfsspecname( buf: *mut ::c_char, buflen: ::size_t, spec: *const ::c_char, ) -> *const ::c_char; pub fn strpct( buf: *mut ::c_char, bufsiz: ::size_t, numerator: ::uintmax_t, denominator: ::uintmax_t, precision: ::size_t, ) -> *mut ::c_char; pub fn strspct( buf: *mut ::c_char, bufsiz: ::size_t, numerator: ::intmax_t, denominator: ::intmax_t, precision: ::size_t, ) -> *mut ::c_char; #[link_name = "__login50"] pub fn login(ut: *const utmp); #[link_name = "__loginx50"] pub fn loginx(ut: *const utmpx); pub fn logout(line: *const ::c_char); pub fn logoutx(line: *const ::c_char, status: ::c_int, tpe: ::c_int); pub fn logwtmp(line: *const ::c_char, name: *const ::c_char, host: *const ::c_char); pub fn logwtmpx( line: *const ::c_char, name: *const ::c_char, host: *const ::c_char, status: ::c_int, tpe: ::c_int, ); pub fn getxattr( path: *const ::c_char, name: *const ::c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn lgetxattr( path: *const ::c_char, name: *const ::c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn fgetxattr( filedes: ::c_int, name: *const ::c_char, value: *mut ::c_void, size: ::size_t, ) -> ::ssize_t; pub fn setxattr( path: *const ::c_char, name: *const ::c_char, value: *const ::c_void, size: ::size_t, ) -> ::c_int; pub fn lsetxattr( path: *const ::c_char, name: *const ::c_char, value: *const ::c_void, size: ::size_t, ) -> ::c_int; pub fn fsetxattr( filedes: ::c_int, name: *const ::c_char, value: *const ::c_void, size: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn listxattr(path: *const ::c_char, list: *mut ::c_char, size: ::size_t) -> ::ssize_t; pub fn llistxattr(path: *const ::c_char, list: *mut ::c_char, size: ::size_t) -> ::ssize_t; pub fn flistxattr(filedes: ::c_int, list: *mut ::c_char, size: ::size_t) -> ::ssize_t; pub fn removexattr(path: *const ::c_char, name: *const ::c_char) -> ::c_int; pub fn lremovexattr(path: *const ::c_char, name: *const ::c_char) -> ::c_int; pub fn fremovexattr(fd: ::c_int, path: *const ::c_char, name: *const ::c_char) -> ::c_int; pub fn string_to_flags( string_p: *mut *mut ::c_char, setp: *mut ::c_ulong, clrp: *mut ::c_ulong, ) -> ::c_int; pub fn flags_to_string(flags: ::c_ulong, def: *const ::c_char) -> ::c_int; pub fn kinfo_getvmmap(pid: ::pid_t, cntp: *mut ::size_t) -> *mut kinfo_vmentry; } #[link(name = "execinfo")] extern "C" { pub fn backtrace(addrlist: *mut *mut ::c_void, len: ::size_t) -> ::size_t; pub fn backtrace_symbols(addrlist: *const *mut ::c_void, len: ::size_t) -> *mut *mut ::c_char; pub fn backtrace_symbols_fd( addrlist: *const *mut ::c_void, len: ::size_t, fd: ::c_int, ) -> ::c_int; pub fn backtrace_symbols_fmt( addrlist: *const *mut ::c_void, len: ::size_t, fmt: *const ::c_char, ) -> *mut *mut ::c_char; pub fn backtrace_symbols_fd_fmt( addrlist: *const *mut ::c_void, len: ::size_t, fd: ::c_int, fmt: *const ::c_char, ) -> ::c_int; } cfg_if! { if #[cfg(libc_union)] { extern { // these functions use statvfs: pub fn getmntinfo(mntbufp: *mut *mut ::statvfs, flags: ::c_int) -> ::c_int; pub fn getvfsstat(buf: *mut statvfs, bufsize: ::size_t, flags: ::c_int) -> ::c_int; } } } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "sparc64")] { mod sparc64; pub use self::sparc64::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "mips")] { mod mips; pub use self::mips::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/netbsdlike/netbsd/aarch64.rs0000644000175000017500000001141614661133735022200 0ustar jamespagejamespageuse PT_FIRSTMACH; pub type c_long = i64; pub type c_ulong = u64; pub type c_char = u8; pub type greg_t = u64; pub type __cpu_simple_lock_nv_t = ::c_uchar; s! { pub struct __fregset { #[cfg(libc_union)] pub __qregs: [__c_anonymous__freg; 32], pub __fpcr: u32, pub __fpsr: u32, } pub struct mcontext_t { pub __gregs: [::greg_t; 32], pub __fregs: __fregset, __spare: [::greg_t; 8], } pub struct ucontext_t { pub uc_flags: ::c_uint, pub uc_link: *mut ucontext_t, pub uc_sigmask: ::sigset_t, pub uc_stack: ::stack_t, pub uc_mcontext: mcontext_t, } } s_no_extra_traits! { #[cfg(libc_union)] #[repr(align(16))] pub union __c_anonymous__freg { pub __b8: [u8; 16], pub __h16: [u16; 8], pub __s32: [u32; 4], pub __d64: [u64; 2], pub __q128: [u128; 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { #[cfg(libc_union)] impl PartialEq for __c_anonymous__freg { fn eq(&self, other: &__c_anonymous__freg) -> bool { unsafe { self.__b8 == other.__b8 || self.__h16 == other.__h16 || self.__s32 == other.__s32 || self.__d64 == other.__d64 || self.__q128 == other.__q128 } } } #[cfg(libc_union)] impl Eq for __c_anonymous__freg {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous__freg { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { f.debug_struct("__c_anonymous__freg") .field("__b8", &self.__b8) .field("__h16", &self.__h16) .field("__s32", &self.__s32) .field("__d64", &self.__d64) .field("__q128", &self.__q128) .finish() } } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous__freg { fn hash(&self, state: &mut H) { unsafe { self.__b8.hash(state); self.__h16.hash(state); self.__s32.hash(state); self.__d64.hash(state); self.__q128.hash(state); } } } } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_int>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 4 - 1; } } pub const PT_GETREGS: ::c_int = PT_FIRSTMACH + 0; pub const PT_SETREGS: ::c_int = PT_FIRSTMACH + 1; pub const PT_GETFPREGS: ::c_int = PT_FIRSTMACH + 2; pub const PT_SETFPREGS: ::c_int = PT_FIRSTMACH + 3; pub const _REG_R0: ::c_int = 0; pub const _REG_R1: ::c_int = 1; pub const _REG_R2: ::c_int = 2; pub const _REG_R3: ::c_int = 3; pub const _REG_R4: ::c_int = 4; pub const _REG_R5: ::c_int = 5; pub const _REG_R6: ::c_int = 6; pub const _REG_R7: ::c_int = 7; pub const _REG_R8: ::c_int = 8; pub const _REG_R9: ::c_int = 9; pub const _REG_R10: ::c_int = 10; pub const _REG_R11: ::c_int = 11; pub const _REG_R12: ::c_int = 12; pub const _REG_R13: ::c_int = 13; pub const _REG_R14: ::c_int = 14; pub const _REG_R15: ::c_int = 15; pub const _REG_CPSR: ::c_int = 16; pub const _REG_X0: ::c_int = 0; pub const _REG_X1: ::c_int = 1; pub const _REG_X2: ::c_int = 2; pub const _REG_X3: ::c_int = 3; pub const _REG_X4: ::c_int = 4; pub const _REG_X5: ::c_int = 5; pub const _REG_X6: ::c_int = 6; pub const _REG_X7: ::c_int = 7; pub const _REG_X8: ::c_int = 8; pub const _REG_X9: ::c_int = 9; pub const _REG_X10: ::c_int = 10; pub const _REG_X11: ::c_int = 11; pub const _REG_X12: ::c_int = 12; pub const _REG_X13: ::c_int = 13; pub const _REG_X14: ::c_int = 14; pub const _REG_X15: ::c_int = 15; pub const _REG_X16: ::c_int = 16; pub const _REG_X17: ::c_int = 17; pub const _REG_X18: ::c_int = 18; pub const _REG_X19: ::c_int = 19; pub const _REG_X20: ::c_int = 20; pub const _REG_X21: ::c_int = 21; pub const _REG_X22: ::c_int = 22; pub const _REG_X23: ::c_int = 23; pub const _REG_X24: ::c_int = 24; pub const _REG_X25: ::c_int = 25; pub const _REG_X26: ::c_int = 26; pub const _REG_X27: ::c_int = 27; pub const _REG_X28: ::c_int = 28; pub const _REG_X29: ::c_int = 29; pub const _REG_X30: ::c_int = 30; pub const _REG_X31: ::c_int = 31; pub const _REG_ELR: ::c_int = 32; pub const _REG_SPSR: ::c_int = 33; pub const _REG_TIPDR: ::c_int = 34; pub const _REG_RV: ::c_int = _REG_X0; pub const _REG_FP: ::c_int = _REG_X29; pub const _REG_LR: ::c_int = _REG_X30; pub const _REG_SP: ::c_int = _REG_X31; pub const _REG_PC: ::c_int = _REG_ELR; libc/src/unix/bsd/apple/0000775000175000017500000000000014661133735016077 5ustar jamespagejamespagelibc/src/unix/bsd/apple/long_array.rs0000644000175000017500000000022714661133735020601 0ustar jamespagejamespages! { pub struct ctl_info { pub ctl_id: u32, pub ctl_name: [::c_char; MAX_KCTL_NAME], } } pub const MAX_KCTL_NAME: usize = 96; libc/src/unix/bsd/apple/b32/0000775000175000017500000000000014661133735016465 5ustar jamespagejamespagelibc/src/unix/bsd/apple/b32/mod.rs0000644000175000017500000000637714661133735017625 0ustar jamespagejamespage//! 32-bit specific Apple (ios/darwin) definitions pub type c_long = i32; pub type c_ulong = u32; pub type boolean_t = ::c_int; s! { pub struct if_data { pub ifi_type: ::c_uchar, pub ifi_typelen: ::c_uchar, pub ifi_physical: ::c_uchar, pub ifi_addrlen: ::c_uchar, pub ifi_hdrlen: ::c_uchar, pub ifi_recvquota: ::c_uchar, pub ifi_xmitquota: ::c_uchar, pub ifi_unused1: ::c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_baudrate: u32, pub ifi_ipackets: u32, pub ifi_ierrors: u32, pub ifi_opackets: u32, pub ifi_oerrors: u32, pub ifi_collisions: u32, pub ifi_ibytes: u32, pub ifi_obytes: u32, pub ifi_imcasts: u32, pub ifi_omcasts: u32, pub ifi_iqdrops: u32, pub ifi_noproto: u32, pub ifi_recvtiming: u32, pub ifi_xmittiming: u32, pub ifi_lastchange: ::timeval, pub ifi_unused2: u32, pub ifi_hwassist: u32, pub ifi_reserved1: u32, pub ifi_reserved2: u32, } pub struct bpf_hdr { pub bh_tstamp: ::timeval, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: ::c_ushort, } pub struct malloc_zone_t { __private: [::uintptr_t; 18], // FIXME: keeping private for now } } s_no_extra_traits! { pub struct pthread_attr_t { __sig: c_long, __opaque: [::c_char; 36] } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_attr_t { fn eq(&self, other: &pthread_attr_t) -> bool { self.__sig == other.__sig && self.__opaque .iter() .zip(other.__opaque.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_attr_t {} impl ::fmt::Debug for pthread_attr_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_attr_t") .field("__sig", &self.__sig) // FIXME: .field("__opaque", &self.__opaque) .finish() } } impl ::hash::Hash for pthread_attr_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } } } #[doc(hidden)] #[deprecated(since = "0.2.55")] pub const NET_RT_MAXID: ::c_int = 10; pub const __PTHREAD_MUTEX_SIZE__: usize = 40; pub const __PTHREAD_COND_SIZE__: usize = 24; pub const __PTHREAD_CONDATTR_SIZE__: usize = 4; pub const __PTHREAD_RWLOCK_SIZE__: usize = 124; pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 12; pub const TIOCTIMESTAMP: ::c_ulong = 0x40087459; pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40087458; pub const BIOCSETF: ::c_ulong = 0x80084267; pub const BIOCSRTIMEOUT: ::c_ulong = 0x8008426d; pub const BIOCGRTIMEOUT: ::c_ulong = 0x4008426e; pub const BIOCSETFNR: ::c_ulong = 0x8008427e; extern "C" { pub fn exchangedata( path1: *const ::c_char, path2: *const ::c_char, options: ::c_ulong, ) -> ::c_int; } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/bsd/apple/b32/align.rs0000644000175000017500000000022514661133735020122 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 2] } } libc/src/unix/bsd/apple/mod.rs0000644000175000017500000073114514661133735017235 0ustar jamespagejamespage//! Apple (ios/darwin)-specific definitions //! //! This covers *-apple-* triples currently pub type c_char = i8; pub type wchar_t = i32; pub type clock_t = c_ulong; pub type time_t = c_long; pub type suseconds_t = i32; pub type dev_t = i32; pub type ino_t = u64; pub type mode_t = u16; pub type nlink_t = u16; pub type blksize_t = i32; pub type rlim_t = u64; pub type pthread_key_t = c_ulong; pub type sigset_t = u32; pub type clockid_t = ::c_uint; pub type fsblkcnt_t = ::c_uint; pub type fsfilcnt_t = ::c_uint; pub type speed_t = ::c_ulong; pub type tcflag_t = ::c_ulong; pub type nl_item = ::c_int; pub type id_t = ::c_uint; pub type sem_t = ::c_int; pub type idtype_t = ::c_uint; pub type integer_t = ::c_int; pub type cpu_type_t = integer_t; pub type cpu_subtype_t = integer_t; pub type natural_t = u32; pub type mach_msg_type_number_t = natural_t; pub type kern_return_t = ::c_int; pub type uuid_t = [u8; 16]; pub type task_info_t = *mut integer_t; pub type host_info_t = *mut integer_t; pub type task_flavor_t = natural_t; pub type rusage_info_t = *mut ::c_void; pub type vm_offset_t = ::uintptr_t; pub type vm_size_t = ::uintptr_t; pub type vm_address_t = vm_offset_t; pub type posix_spawnattr_t = *mut ::c_void; pub type posix_spawn_file_actions_t = *mut ::c_void; pub type key_t = ::c_int; pub type shmatt_t = ::c_ushort; pub type sae_associd_t = u32; pub type sae_connid_t = u32; pub type mach_port_t = ::c_uint; pub type host_t = ::c_uint; pub type host_flavor_t = integer_t; pub type host_info64_t = *mut integer_t; pub type processor_flavor_t = ::c_int; pub type thread_flavor_t = natural_t; pub type thread_inspect_t = ::mach_port_t; pub type thread_act_t = ::mach_port_t; pub type thread_act_array_t = *mut ::thread_act_t; pub type policy_t = ::c_int; pub type mach_vm_address_t = u64; pub type mach_vm_offset_t = u64; pub type mach_vm_size_t = u64; pub type vm_map_t = ::mach_port_t; pub type mem_entry_name_port_t = ::mach_port_t; pub type memory_object_t = ::mach_port_t; pub type memory_object_offset_t = ::c_ulonglong; pub type vm_inherit_t = ::c_uint; pub type vm_prot_t = ::c_int; pub type ledger_t = ::mach_port_t; pub type ledger_array_t = *mut ::ledger_t; pub type iconv_t = *mut ::c_void; pub type processor_cpu_load_info_t = *mut processor_cpu_load_info; pub type processor_cpu_load_info_data_t = processor_cpu_load_info; pub type processor_basic_info_t = *mut processor_basic_info; pub type processor_basic_info_data_t = processor_basic_info; pub type processor_set_basic_info_data_t = processor_set_basic_info; pub type processor_set_basic_info_t = *mut processor_set_basic_info; pub type processor_set_load_info_data_t = processor_set_load_info; pub type processor_set_load_info_t = *mut processor_set_load_info; pub type processor_info_t = *mut integer_t; pub type processor_info_array_t = *mut integer_t; pub type mach_task_basic_info_data_t = mach_task_basic_info; pub type mach_task_basic_info_t = *mut mach_task_basic_info; pub type task_thread_times_info_data_t = task_thread_times_info; pub type task_thread_times_info_t = *mut task_thread_times_info; pub type thread_info_t = *mut integer_t; pub type thread_basic_info_t = *mut thread_basic_info; pub type thread_basic_info_data_t = thread_basic_info; pub type thread_identifier_info_t = *mut thread_identifier_info; pub type thread_identifier_info_data_t = thread_identifier_info; pub type thread_extended_info_t = *mut thread_extended_info; pub type thread_extended_info_data_t = thread_extended_info; pub type thread_t = ::mach_port_t; pub type thread_policy_flavor_t = natural_t; pub type thread_policy_t = *mut integer_t; pub type thread_latency_qos_t = integer_t; pub type thread_throughput_qos_t = integer_t; pub type thread_standard_policy_data_t = thread_standard_policy; pub type thread_standard_policy_t = *mut thread_standard_policy; pub type thread_extended_policy_data_t = thread_extended_policy; pub type thread_extended_policy_t = *mut thread_extended_policy; pub type thread_time_constraint_policy_data_t = thread_time_constraint_policy; pub type thread_time_constraint_policy_t = *mut thread_time_constraint_policy; pub type thread_precedence_policy_data_t = thread_precedence_policy; pub type thread_precedence_policy_t = *mut thread_precedence_policy; pub type thread_affinity_policy_data_t = thread_affinity_policy; pub type thread_affinity_policy_t = *mut thread_affinity_policy; pub type thread_background_policy_data_t = thread_background_policy; pub type thread_background_policy_t = *mut thread_background_policy; pub type thread_latency_qos_policy_data_t = thread_latency_qos_policy; pub type thread_latency_qos_policy_t = *mut thread_latency_qos_policy; pub type thread_throughput_qos_policy_data_t = thread_throughput_qos_policy; pub type thread_throughput_qos_policy_t = *mut thread_throughput_qos_policy; pub type pthread_introspection_hook_t = extern "C" fn(event: ::c_uint, thread: ::pthread_t, addr: *mut ::c_void, size: ::size_t); pub type pthread_jit_write_callback_t = ::Option ::c_int>; pub type os_unfair_lock = os_unfair_lock_s; pub type os_unfair_lock_t = *mut os_unfair_lock; pub type os_log_t = *mut ::c_void; pub type os_log_type_t = u8; pub type os_signpost_id_t = u64; pub type os_signpost_type_t = u8; pub type vm_statistics_t = *mut vm_statistics; pub type vm_statistics_data_t = vm_statistics; pub type vm_statistics64_t = *mut vm_statistics64; pub type vm_statistics64_data_t = vm_statistics64; pub type task_t = ::mach_port_t; pub type task_inspect_t = ::mach_port_t; pub type sysdir_search_path_enumeration_state = ::c_uint; pub type CCStatus = i32; pub type CCCryptorStatus = i32; pub type CCRNGStatus = ::CCCryptorStatus; pub type copyfile_state_t = *mut ::c_void; pub type copyfile_flags_t = u32; pub type copyfile_callback_t = ::Option< extern "C" fn( ::c_int, ::c_int, copyfile_state_t, *const ::c_char, *const ::c_char, *mut ::c_void, ) -> ::c_int, >; pub type attrgroup_t = u32; pub type vol_capabilities_set_t = [u32; 4]; deprecated_mach! { pub type mach_timebase_info_data_t = mach_timebase_info; } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum qos_class_t { QOS_CLASS_USER_INTERACTIVE = 0x21, QOS_CLASS_USER_INITIATED = 0x19, QOS_CLASS_DEFAULT = 0x15, QOS_CLASS_UTILITY = 0x11, QOS_CLASS_BACKGROUND = 0x09, QOS_CLASS_UNSPECIFIED = 0x00, } impl ::Copy for qos_class_t {} impl ::Clone for qos_class_t { fn clone(&self) -> qos_class_t { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum sysdir_search_path_directory_t { SYSDIR_DIRECTORY_APPLICATION = 1, SYSDIR_DIRECTORY_DEMO_APPLICATION = 2, SYSDIR_DIRECTORY_DEVELOPER_APPLICATION = 3, SYSDIR_DIRECTORY_ADMIN_APPLICATION = 4, SYSDIR_DIRECTORY_LIBRARY = 5, SYSDIR_DIRECTORY_DEVELOPER = 6, SYSDIR_DIRECTORY_USER = 7, SYSDIR_DIRECTORY_DOCUMENTATION = 8, SYSDIR_DIRECTORY_DOCUMENT = 9, SYSDIR_DIRECTORY_CORESERVICE = 10, SYSDIR_DIRECTORY_AUTOSAVED_INFORMATION = 11, SYSDIR_DIRECTORY_DESKTOP = 12, SYSDIR_DIRECTORY_CACHES = 13, SYSDIR_DIRECTORY_APPLICATION_SUPPORT = 14, SYSDIR_DIRECTORY_DOWNLOADS = 15, SYSDIR_DIRECTORY_INPUT_METHODS = 16, SYSDIR_DIRECTORY_MOVIES = 17, SYSDIR_DIRECTORY_MUSIC = 18, SYSDIR_DIRECTORY_PICTURES = 19, SYSDIR_DIRECTORY_PRINTER_DESCRIPTION = 20, SYSDIR_DIRECTORY_SHARED_PUBLIC = 21, SYSDIR_DIRECTORY_PREFERENCE_PANES = 22, SYSDIR_DIRECTORY_ALL_APPLICATIONS = 100, SYSDIR_DIRECTORY_ALL_LIBRARIES = 101, } impl ::Copy for sysdir_search_path_directory_t {} impl ::Clone for sysdir_search_path_directory_t { fn clone(&self) -> sysdir_search_path_directory_t { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum sysdir_search_path_domain_mask_t { SYSDIR_DOMAIN_MASK_USER = (1 << 0), SYSDIR_DOMAIN_MASK_LOCAL = (1 << 1), SYSDIR_DOMAIN_MASK_NETWORK = (1 << 2), SYSDIR_DOMAIN_MASK_SYSTEM = (1 << 3), SYSDIR_DOMAIN_MASK_ALL = 0x0ffff, } impl ::Copy for sysdir_search_path_domain_mask_t {} impl ::Clone for sysdir_search_path_domain_mask_t { fn clone(&self) -> sysdir_search_path_domain_mask_t { *self } } s! { pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct aiocb { pub aio_fildes: ::c_int, pub aio_offset: ::off_t, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_reqprio: ::c_int, pub aio_sigevent: sigevent, pub aio_lio_opcode: ::c_int } pub struct glob_t { pub gl_pathc: ::size_t, __unused1: ::c_int, pub gl_offs: ::size_t, __unused2: ::c_int, pub gl_pathv: *mut *mut ::c_char, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, __unused6: *mut ::c_void, __unused7: *mut ::c_void, __unused8: *mut ::c_void, } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: ::socklen_t, pub ai_canonname: *mut ::c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut addrinfo, } #[deprecated( since = "0.2.55", note = "Use the `mach2` crate instead", )] pub struct mach_timebase_info { pub numer: u32, pub denom: u32, } pub struct stat { pub st_dev: dev_t, pub st_mode: mode_t, pub st_nlink: nlink_t, pub st_ino: ino_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: dev_t, pub st_atime: time_t, pub st_atime_nsec: c_long, pub st_mtime: time_t, pub st_mtime_nsec: c_long, pub st_ctime: time_t, pub st_ctime_nsec: c_long, pub st_birthtime: time_t, pub st_birthtime_nsec: c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: blksize_t, pub st_flags: u32, pub st_gen: u32, pub st_lspare: i32, pub st_qspare: [i64; 2], } pub struct pthread_mutexattr_t { __sig: ::c_long, __opaque: [u8; 8], } pub struct pthread_condattr_t { __sig: ::c_long, __opaque: [u8; __PTHREAD_CONDATTR_SIZE__], } pub struct pthread_rwlockattr_t { __sig: ::c_long, __opaque: [u8; __PTHREAD_RWLOCKATTR_SIZE__], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub si_pid: ::pid_t, pub si_uid: ::uid_t, pub si_status: ::c_int, pub si_addr: *mut ::c_void, //Requires it to be union for tests //pub si_value: ::sigval, _pad: [usize; 9], } pub struct sigaction { // FIXME: this field is actually a union pub sa_sigaction: ::sighandler_t, pub sa_mask: sigset_t, pub sa_flags: ::c_int, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct fstore_t { pub fst_flags: ::c_uint, pub fst_posmode: ::c_int, pub fst_offset: ::off_t, pub fst_length: ::off_t, pub fst_bytesalloc: ::off_t, } pub struct fpunchhole_t { pub fp_flags: ::c_uint, /* unused */ pub reserved: ::c_uint, /* (to maintain 8-byte alignment) */ pub fp_offset: ::off_t, /* IN: start of the region */ pub fp_length: ::off_t, /* IN: size of the region */ } pub struct ftrimactivefile_t { pub fta_offset: ::off_t, pub fta_length: ::off_t, } pub struct fspecread_t { pub fsr_flags: ::c_uint, pub reserved: ::c_uint, pub fsr_offset: ::off_t, pub fsr_length: ::off_t, } pub struct radvisory { pub ra_offset: ::off_t, pub ra_count: ::c_int, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [::c_char; 8], } pub struct kevent64_s { pub ident: u64, pub filter: i16, pub flags: u16, pub fflags: u32, pub data: i64, pub udata: u64, pub ext: [u64; 2], } pub struct dqblk { pub dqb_bhardlimit: u64, pub dqb_bsoftlimit: u64, pub dqb_curbytes: u64, pub dqb_ihardlimit: u32, pub dqb_isoftlimit: u32, pub dqb_curinodes: u32, pub dqb_btime: u32, pub dqb_itime: u32, pub dqb_id: u32, pub dqb_spare: [u32; 4], } pub struct if_msghdr { pub ifm_msglen: ::c_ushort, pub ifm_version: ::c_uchar, pub ifm_type: ::c_uchar, pub ifm_addrs: ::c_int, pub ifm_flags: ::c_int, pub ifm_index: ::c_ushort, pub ifm_data: if_data, } pub struct ifa_msghdr { pub ifam_msglen: ::c_ushort, pub ifam_version: ::c_uchar, pub ifam_type: ::c_uchar, pub ifam_addrs: ::c_int, pub ifam_flags: ::c_int, pub ifam_index: ::c_ushort, pub ifam_metric: ::c_int, } pub struct ifma_msghdr { pub ifmam_msglen: ::c_ushort, pub ifmam_version: ::c_uchar, pub ifmam_type: ::c_uchar, pub ifmam_addrs: ::c_int, pub ifmam_flags: ::c_int, pub ifmam_index: ::c_ushort, } pub struct ifma_msghdr2 { pub ifmam_msglen: ::c_ushort, pub ifmam_version: ::c_uchar, pub ifmam_type: ::c_uchar, pub ifmam_addrs: ::c_int, pub ifmam_flags: ::c_int, pub ifmam_index: ::c_ushort, pub ifmam_refcount: i32, } pub struct rt_metrics { pub rmx_locks: u32, pub rmx_mtu: u32, pub rmx_hopcount: u32, pub rmx_expire: i32, pub rmx_recvpipe: u32, pub rmx_sendpipe: u32, pub rmx_ssthresh: u32, pub rmx_rtt: u32, pub rmx_rttvar: u32, pub rmx_pksent: u32, pub rmx_state: u32, pub rmx_filler: [u32; 3], } pub struct rt_msghdr { pub rtm_msglen: ::c_ushort, pub rtm_version: ::c_uchar, pub rtm_type: ::c_uchar, pub rtm_index: ::c_ushort, pub rtm_flags: ::c_int, pub rtm_addrs: ::c_int, pub rtm_pid: ::pid_t, pub rtm_seq: ::c_int, pub rtm_errno: ::c_int, pub rtm_use: ::c_int, pub rtm_inits: u32, pub rtm_rmx: rt_metrics, } pub struct rt_msghdr2 { pub rtm_msglen: ::c_ushort, pub rtm_version: ::c_uchar, pub rtm_type: ::c_uchar, pub rtm_index: ::c_ushort, pub rtm_flags: ::c_int, pub rtm_addrs: ::c_int, pub rtm_refcnt: i32, pub rtm_parentflags: ::c_int, pub rtm_reserved: ::c_int, pub rtm_use: ::c_int, pub rtm_inits: u32, pub rtm_rmx: rt_metrics, } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_cc: [::cc_t; ::NCCS], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } pub struct flock { pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, pub l_type: ::c_short, pub l_whence: ::c_short, } pub struct sf_hdtr { pub headers: *mut ::iovec, pub hdr_cnt: ::c_int, pub trailers: *mut ::iovec, pub trl_cnt: ::c_int, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct proc_taskinfo { pub pti_virtual_size: u64, pub pti_resident_size: u64, pub pti_total_user: u64, pub pti_total_system: u64, pub pti_threads_user: u64, pub pti_threads_system: u64, pub pti_policy: i32, pub pti_faults: i32, pub pti_pageins: i32, pub pti_cow_faults: i32, pub pti_messages_sent: i32, pub pti_messages_received: i32, pub pti_syscalls_mach: i32, pub pti_syscalls_unix: i32, pub pti_csw: i32, pub pti_threadnum: i32, pub pti_numrunning: i32, pub pti_priority: i32, } pub struct proc_bsdinfo { pub pbi_flags: u32, pub pbi_status: u32, pub pbi_xstatus: u32, pub pbi_pid: u32, pub pbi_ppid: u32, pub pbi_uid: ::uid_t, pub pbi_gid: ::gid_t, pub pbi_ruid: ::uid_t, pub pbi_rgid: ::gid_t, pub pbi_svuid: ::uid_t, pub pbi_svgid: ::gid_t, pub rfu_1: u32, pub pbi_comm: [::c_char; MAXCOMLEN], pub pbi_name: [::c_char; 32], // MAXCOMLEN * 2, but macro isn't happy... pub pbi_nfiles: u32, pub pbi_pgid: u32, pub pbi_pjobc: u32, pub e_tdev: u32, pub e_tpgid: u32, pub pbi_nice: i32, pub pbi_start_tvsec: u64, pub pbi_start_tvusec: u64, } pub struct proc_taskallinfo { pub pbsd: proc_bsdinfo, pub ptinfo: proc_taskinfo, } pub struct xsw_usage { pub xsu_total: u64, pub xsu_avail: u64, pub xsu_used: u64, pub xsu_pagesize: u32, pub xsu_encrypted: ::boolean_t, } pub struct xucred { pub cr_version: ::c_uint, pub cr_uid: ::uid_t, pub cr_ngroups: ::c_short, pub cr_groups: [::gid_t;16] } #[deprecated( since = "0.2.55", note = "Use the `mach2` crate instead", )] pub struct mach_header { pub magic: u32, pub cputype: cpu_type_t, pub cpusubtype: cpu_subtype_t, pub filetype: u32, pub ncmds: u32, pub sizeofcmds: u32, pub flags: u32, } #[deprecated( since = "0.2.55", note = "Use the `mach2` crate instead", )] pub struct mach_header_64 { pub magic: u32, pub cputype: cpu_type_t, pub cpusubtype: cpu_subtype_t, pub filetype: u32, pub ncmds: u32, pub sizeofcmds: u32, pub flags: u32, pub reserved: u32, } pub struct segment_command { pub cmd: u32, pub cmdsize: u32, pub segname: [::c_char; 16], pub vmaddr: u32, pub vmsize: u32, pub fileoff: u32, pub filesize: u32, pub maxprot: vm_prot_t, pub initprot: vm_prot_t, pub nsects: u32, pub flags: u32, } pub struct segment_command_64 { pub cmd: u32, pub cmdsize: u32, pub segname: [::c_char; 16], pub vmaddr: u64, pub vmsize: u64, pub fileoff: u64, pub filesize: u64, pub maxprot: vm_prot_t, pub initprot: vm_prot_t, pub nsects: u32, pub flags: u32, } pub struct load_command { pub cmd: u32, pub cmdsize: u32, } pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, pub sdl_index: ::c_ushort, pub sdl_type: ::c_uchar, pub sdl_nlen: ::c_uchar, pub sdl_alen: ::c_uchar, pub sdl_slen: ::c_uchar, pub sdl_data: [::c_char; 12], } pub struct sockaddr_inarp { pub sin_len: ::c_uchar, pub sin_family: ::c_uchar, pub sin_port: ::c_ushort, pub sin_addr: ::in_addr, pub sin_srcaddr: ::in_addr, pub sin_tos: ::c_ushort, pub sin_other: ::c_ushort, } pub struct sockaddr_ctl { pub sc_len: ::c_uchar, pub sc_family: ::c_uchar, pub ss_sysaddr: u16, pub sc_id: u32, pub sc_unit: u32, pub sc_reserved: [u32; 5], } pub struct in_pktinfo { pub ipi_ifindex: ::c_uint, pub ipi_spec_dst: ::in_addr, pub ipi_addr: ::in_addr, } pub struct in6_pktinfo { pub ipi6_addr: ::in6_addr, pub ipi6_ifindex: ::c_uint, } // sys/ipc.h: pub struct ipc_perm { pub uid: ::uid_t, pub gid: ::gid_t, pub cuid: ::uid_t, pub cgid: ::gid_t, pub mode: ::mode_t, pub _seq: ::c_ushort, pub _key: ::key_t, } // sys/sem.h pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } // sys/shm.h pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct in_addr { pub s_addr: ::in_addr_t, } // net/ndrv.h pub struct sockaddr_ndrv { pub snd_len: ::c_uchar, pub snd_family: ::c_uchar, pub snd_name: [::c_uchar; ::IFNAMSIZ], } // sys/socket.h pub struct sa_endpoints_t { pub sae_srcif: ::c_uint, // optional source interface pub sae_srcaddr: *const ::sockaddr, // optional source address pub sae_srcaddrlen: ::socklen_t, // size of source address pub sae_dstaddr: *const ::sockaddr, // destination address pub sae_dstaddrlen: ::socklen_t, // size of destination address } pub struct timex { pub modes: ::c_uint, pub offset: ::c_long, pub freq: ::c_long, pub maxerror: ::c_long, pub esterror: ::c_long, pub status: ::c_int, pub constant: ::c_long, pub precision: ::c_long, pub tolerance: ::c_long, pub ppsfreq: ::c_long, pub jitter: ::c_long, pub shift: ::c_int, pub stabil: ::c_long, pub jitcnt: ::c_long, pub calcnt: ::c_long, pub errcnt: ::c_long, pub stbcnt: ::c_long, } pub struct ntptimeval { pub time: ::timespec, pub maxerror: ::c_long, pub esterror: ::c_long, pub tai: ::c_long, pub time_state: ::c_int, } pub struct thread_standard_policy { pub no_data: natural_t, } pub struct thread_extended_policy { pub timeshare: boolean_t, } pub struct thread_time_constraint_policy { pub period: u32, pub computation: u32, pub constraint: u32, pub preemptible: boolean_t, } pub struct thread_precedence_policy { pub importance: integer_t, } pub struct thread_affinity_policy { pub affinity_tag: integer_t, } pub struct thread_background_policy { pub priority: integer_t, } pub struct thread_latency_qos_policy { pub thread_latency_qos_tier: thread_latency_qos_t, } pub struct thread_throughput_qos_policy { pub thread_throughput_qos_tier: thread_throughput_qos_t, } // malloc/malloc.h pub struct malloc_statistics_t { pub blocks_in_use: ::c_uint, pub size_in_use: ::size_t, pub max_size_in_use: ::size_t, pub size_allocated: ::size_t, } pub struct mstats { pub bytes_total: ::size_t, pub chunks_used: ::size_t, pub bytes_used: ::size_t, pub chunks_free: ::size_t, pub bytes_free: ::size_t, } pub struct vm_range_t { pub address: ::vm_address_t, pub size: ::vm_size_t, } // sched.h pub struct sched_param { pub sched_priority: ::c_int, __opaque: [::c_char; 4], } pub struct vinfo_stat { pub vst_dev: u32, pub vst_mode: u16, pub vst_nlink: u16, pub vst_ino: u64, pub vst_uid: ::uid_t, pub vst_gid: ::gid_t, pub vst_atime: i64, pub vst_atimensec: i64, pub vst_mtime: i64, pub vst_mtimensec: i64, pub vst_ctime: i64, pub vst_ctimensec: i64, pub vst_birthtime: i64, pub vst_birthtimensec: i64, pub vst_size: ::off_t, pub vst_blocks: i64, pub vst_blksize: i32, pub vst_flags: u32, pub vst_gen: u32, pub vst_rdev: u32, pub vst_qspare: [i64; 2], } pub struct vnode_info { pub vi_stat: vinfo_stat, pub vi_type: ::c_int, pub vi_pad: ::c_int, pub vi_fsid: ::fsid_t, } pub struct vnode_info_path { pub vip_vi: vnode_info, // Normally it's `vip_path: [::c_char; MAXPATHLEN]` but because libc supports an old rustc // version, we go around this limitation like this. pub vip_path: [[::c_char; 32]; 32], } pub struct proc_vnodepathinfo { pub pvi_cdir: vnode_info_path, pub pvi_rdir: vnode_info_path, } pub struct vm_statistics { pub free_count: natural_t, pub active_count: natural_t, pub inactive_count: natural_t, pub wire_count: natural_t, pub zero_fill_count: natural_t, pub reactivations: natural_t, pub pageins: natural_t, pub pageouts: natural_t, pub faults: natural_t, pub cow_faults: natural_t, pub lookups: natural_t, pub hits: natural_t, pub purgeable_count: natural_t, pub purges: natural_t, pub speculative_count: natural_t, } pub struct task_thread_times_info { pub user_time: time_value_t, pub system_time: time_value_t, } pub struct rusage_info_v0 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, } pub struct rusage_info_v1 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, } pub struct rusage_info_v2 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, pub ri_diskio_bytesread: u64, pub ri_diskio_byteswritten: u64, } pub struct rusage_info_v3 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, pub ri_diskio_bytesread: u64, pub ri_diskio_byteswritten: u64, pub ri_cpu_time_qos_default: u64, pub ri_cpu_time_qos_maintenance: u64, pub ri_cpu_time_qos_background: u64, pub ri_cpu_time_qos_utility: u64, pub ri_cpu_time_qos_legacy: u64, pub ri_cpu_time_qos_user_initiated: u64, pub ri_cpu_time_qos_user_interactive: u64, pub ri_billed_system_time: u64, pub ri_serviced_system_time: u64, } pub struct rusage_info_v4 { pub ri_uuid: [u8; 16], pub ri_user_time: u64, pub ri_system_time: u64, pub ri_pkg_idle_wkups: u64, pub ri_interrupt_wkups: u64, pub ri_pageins: u64, pub ri_wired_size: u64, pub ri_resident_size: u64, pub ri_phys_footprint: u64, pub ri_proc_start_abstime: u64, pub ri_proc_exit_abstime: u64, pub ri_child_user_time: u64, pub ri_child_system_time: u64, pub ri_child_pkg_idle_wkups: u64, pub ri_child_interrupt_wkups: u64, pub ri_child_pageins: u64, pub ri_child_elapsed_abstime: u64, pub ri_diskio_bytesread: u64, pub ri_diskio_byteswritten: u64, pub ri_cpu_time_qos_default: u64, pub ri_cpu_time_qos_maintenance: u64, pub ri_cpu_time_qos_background: u64, pub ri_cpu_time_qos_utility: u64, pub ri_cpu_time_qos_legacy: u64, pub ri_cpu_time_qos_user_initiated: u64, pub ri_cpu_time_qos_user_interactive: u64, pub ri_billed_system_time: u64, pub ri_serviced_system_time: u64, pub ri_logical_writes: u64, pub ri_lifetime_max_phys_footprint: u64, pub ri_instructions: u64, pub ri_cycles: u64, pub ri_billed_energy: u64, pub ri_serviced_energy: u64, pub ri_interval_max_phys_footprint: u64, pub ri_runnable_time: u64, } pub struct image_offset { pub uuid: ::uuid_t, pub offset: u32, } pub struct attrlist { pub bitmapcount: ::c_ushort, pub reserved: u16, pub commonattr: attrgroup_t, pub volattr: attrgroup_t, pub dirattr: attrgroup_t, pub fileattr: attrgroup_t, pub forkattr: attrgroup_t, } pub struct attrreference_t { pub attr_dataoffset: i32, pub attr_length: u32, } pub struct vol_capabilities_attr_t { pub capabilities: vol_capabilities_set_t, pub valid: vol_capabilities_set_t, } pub struct attribute_set_t { pub commonattr: attrgroup_t, pub volattr: attrgroup_t, pub dirattr: attrgroup_t, pub fileattr: attrgroup_t, pub forkattr: attrgroup_t, } pub struct vol_attributes_attr_t { pub validattr: attribute_set_t, pub nativeattr: attribute_set_t, } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct ifconf { pub ifc_len: ::c_int, #[cfg(libc_union)] pub ifc_ifcu: __c_anonymous_ifc_ifcu, #[cfg(not(libc_union))] pub ifc_ifcu: *mut ifreq, } #[cfg_attr(libc_align, repr(align(8)))] pub struct tcp_connection_info { pub tcpi_state: u8, pub tcpi_snd_wscale: u8, pub tcpi_rcv_wscale: u8, __pad1: u8, pub tcpi_options: u32, pub tcpi_flags: u32, pub tcpi_rto: u32, pub tcpi_maxseg: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_sbbytes: u32, pub tcpi_rcv_wnd: u32, pub tcpi_rttcur: u32, pub tcpi_srtt: u32, pub tcpi_rttvar: u32, pub tcpi_tfo_cookie_req: u32, pub tcpi_tfo_cookie_rcv: u32, pub tcpi_tfo_syn_loss: u32, pub tcpi_tfo_syn_data_sent: u32, pub tcpi_tfo_syn_data_acked: u32, pub tcpi_tfo_syn_data_rcv: u32, pub tcpi_tfo_cookie_req_rcv: u32, pub tcpi_tfo_cookie_sent: u32, pub tcpi_tfo_cookie_invalid: u32, pub tcpi_tfo_cookie_wrong: u32, pub tcpi_tfo_no_cookie_rcv: u32, pub tcpi_tfo_heuristics_disable: u32, pub tcpi_tfo_send_blackhole: u32, pub tcpi_tfo_recv_blackhole: u32, pub tcpi_tfo_onebyte_proxy: u32, __pad2: u32, pub tcpi_txpackets: u64, pub tcpi_txbytes: u64, pub tcpi_txretransmitbytes: u64, pub tcpi_rxpackets: u64, pub tcpi_rxbytes: u64, pub tcpi_rxoutoforderbytes: u64, pub tcpi_rxretransmitpackets: u64, } } s_no_extra_traits! { #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct kevent { pub ident: ::uintptr_t, pub filter: i16, pub flags: u16, pub fflags: u32, pub data: ::intptr_t, pub udata: *mut ::c_void, } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct semid_ds { // Note the manpage shows different types than the system header. pub sem_perm: ipc_perm, pub sem_base: i32, pub sem_nsems: ::c_ushort, pub sem_otime: ::time_t, pub sem_pad1: i32, pub sem_ctime: ::time_t, pub sem_pad2: i32, pub sem_pad3: [i32; 4], } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct shmid_ds { pub shm_perm: ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_atime: ::time_t, // FIXME: 64-bit wrong align => wrong offset pub shm_dtime: ::time_t, // FIXME: 64-bit wrong align => wrong offset pub shm_ctime: ::time_t, // FIXME: 64-bit wrong align => wrong offset // FIXME: 64-bit wrong align => wrong offset: pub shm_internal: *mut ::c_void, } pub struct proc_threadinfo { pub pth_user_time: u64, pub pth_system_time: u64, pub pth_cpu_usage: i32, pub pth_policy: i32, pub pth_run_state: i32, pub pth_flags: i32, pub pth_sleep_time: i32, pub pth_curpri: i32, pub pth_priority: i32, pub pth_maxpriority: i32, pub pth_name: [::c_char; MAXTHREADNAMESIZE], } pub struct statfs { pub f_bsize: u32, pub f_iosize: i32, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: u64, pub f_files: u64, pub f_ffree: u64, pub f_fsid: ::fsid_t, pub f_owner: ::uid_t, pub f_type: u32, pub f_flags: u32, pub f_fssubtype: u32, pub f_fstypename: [::c_char; 16], pub f_mntonname: [::c_char; 1024], pub f_mntfromname: [::c_char; 1024], pub f_flags_ext: u32, pub f_reserved: [u32; 7], } pub struct dirent { pub d_ino: u64, pub d_seekoff: u64, pub d_reclen: u16, pub d_namlen: u16, pub d_type: u8, pub d_name: [::c_char; 1024], } pub struct pthread_rwlock_t { __sig: ::c_long, __opaque: [u8; __PTHREAD_RWLOCK_SIZE__], } pub struct pthread_mutex_t { __sig: ::c_long, __opaque: [u8; __PTHREAD_MUTEX_SIZE__], } pub struct pthread_cond_t { __sig: ::c_long, __opaque: [u8; __PTHREAD_COND_SIZE__], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: ::sa_family_t, __ss_pad1: [u8; 6], __ss_align: i64, __ss_pad2: [u8; 112], } pub struct utmpx { pub ut_user: [::c_char; _UTX_USERSIZE], pub ut_id: [::c_char; _UTX_IDSIZE], pub ut_line: [::c_char; _UTX_LINESIZE], pub ut_pid: ::pid_t, pub ut_type: ::c_short, pub ut_tv: ::timeval, pub ut_host: [::c_char; _UTX_HOSTSIZE], ut_pad: [u32; 16], } pub struct sigevent { pub sigev_notify: ::c_int, pub sigev_signo: ::c_int, pub sigev_value: ::sigval, __unused1: *mut ::c_void, //actually a function pointer pub sigev_notify_attributes: *mut ::pthread_attr_t } pub struct processor_cpu_load_info { pub cpu_ticks: [::c_uint; CPU_STATE_MAX as usize], } pub struct processor_basic_info { pub cpu_type: cpu_type_t, pub cpu_subtype: cpu_subtype_t, pub running: ::boolean_t, pub slot_num: ::c_int, pub is_master: ::boolean_t, } pub struct processor_set_basic_info { pub processor_count: ::c_int, pub default_policy: ::c_int, } pub struct processor_set_load_info { pub task_count: ::c_int, pub thread_count: ::c_int, pub load_average: integer_t, pub mach_factor: integer_t, } pub struct time_value_t { pub seconds: integer_t, pub microseconds: integer_t, } pub struct thread_basic_info { pub user_time: time_value_t, pub system_time: time_value_t, pub cpu_usage: ::integer_t, pub policy: ::policy_t, pub run_state: ::integer_t, pub flags: ::integer_t, pub suspend_count: ::integer_t, pub sleep_time: ::integer_t, } pub struct thread_identifier_info { pub thread_id: u64, pub thread_handle: u64, pub dispatch_qaddr: u64, } pub struct thread_extended_info { pub pth_user_time: u64, pub pth_system_time: u64, pub pth_cpu_usage: i32, pub pth_policy: i32, pub pth_run_state: i32, pub pth_flags: i32, pub pth_sleep_time: i32, pub pth_curpri: i32, pub pth_priority: i32, pub pth_maxpriority: i32, pub pth_name: [::c_char; MAXTHREADNAMESIZE], } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct if_data64 { pub ifi_type: ::c_uchar, pub ifi_typelen: ::c_uchar, pub ifi_physical: ::c_uchar, pub ifi_addrlen: ::c_uchar, pub ifi_hdrlen: ::c_uchar, pub ifi_recvquota: ::c_uchar, pub ifi_xmitquota: ::c_uchar, pub ifi_unused1: ::c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_baudrate: u64, pub ifi_ipackets: u64, pub ifi_ierrors: u64, pub ifi_opackets: u64, pub ifi_oerrors: u64, pub ifi_collisions: u64, pub ifi_ibytes: u64, pub ifi_obytes: u64, pub ifi_imcasts: u64, pub ifi_omcasts: u64, pub ifi_iqdrops: u64, pub ifi_noproto: u64, pub ifi_recvtiming: u32, pub ifi_xmittiming: u32, #[cfg(target_pointer_width = "32")] pub ifi_lastchange: ::timeval, #[cfg(not(target_pointer_width = "32"))] pub ifi_lastchange: timeval32, } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct if_msghdr2 { pub ifm_msglen: ::c_ushort, pub ifm_version: ::c_uchar, pub ifm_type: ::c_uchar, pub ifm_addrs: ::c_int, pub ifm_flags: ::c_int, pub ifm_index: ::c_ushort, pub ifm_snd_len: ::c_int, pub ifm_snd_maxlen: ::c_int, pub ifm_snd_drops: ::c_int, pub ifm_timer: ::c_int, pub ifm_data: if_data64, } #[cfg_attr(libc_packedN, repr(packed(8)))] pub struct vm_statistics64 { pub free_count: natural_t, pub active_count: natural_t, pub inactive_count: natural_t, pub wire_count: natural_t, pub zero_fill_count: u64, pub reactivations: u64, pub pageins: u64, pub pageouts: u64, pub faults: u64, pub cow_faults: u64, pub lookups: u64, pub hits: u64, pub purges: u64, pub purgeable_count: natural_t, pub speculative_count: natural_t, pub decompressions: u64, pub compressions: u64, pub swapins: u64, pub swapouts: u64, pub compressor_page_count: natural_t, pub throttled_count: natural_t, pub external_page_count: natural_t, pub internal_page_count: natural_t, pub total_uncompressed_pages_in_compressor: u64, } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct mach_task_basic_info { pub virtual_size: mach_vm_size_t, pub resident_size: mach_vm_size_t, pub resident_size_max: mach_vm_size_t, pub user_time: time_value_t, pub system_time: time_value_t, pub policy: ::policy_t, pub suspend_count: integer_t, } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct log2phys { pub l2p_flags: ::c_uint, pub l2p_contigbytes: ::off_t, pub l2p_devoffset: ::off_t, } pub struct os_unfair_lock_s { _os_unfair_lock_opaque: u32, } #[cfg_attr(libc_packedN, repr(packed(1)))] pub struct sockaddr_vm { pub svm_len: ::c_uchar, pub svm_family: ::sa_family_t, pub svm_reserved1: ::c_ushort, pub svm_port: ::c_uint, pub svm_cid: ::c_uint, } pub struct ifdevmtu { pub ifdm_current: ::c_int, pub ifdm_min: ::c_int, pub ifdm_max: ::c_int, } #[cfg(libc_union)] pub union __c_anonymous_ifk_data { pub ifk_ptr: *mut ::c_void, pub ifk_value: ::c_int, } #[cfg_attr(libc_packedN, repr(packed(4)))] pub struct ifkpi { pub ifk_module_id: ::c_uint, pub ifk_type: ::c_uint, #[cfg(libc_union)] pub ifk_data: __c_anonymous_ifk_data, } #[cfg(libc_union)] pub union __c_anonymous_ifr_ifru { pub ifru_addr: ::sockaddr, pub ifru_dstaddr: ::sockaddr, pub ifru_broadaddr: ::sockaddr, pub ifru_flags: ::c_short, pub ifru_metrics: ::c_int, pub ifru_mtu: ::c_int, pub ifru_phys: ::c_int, pub ifru_media: ::c_int, pub ifru_intval: ::c_int, pub ifru_data: *mut ::c_char, pub ifru_devmtu: ifdevmtu, pub ifru_kpi: ifkpi, pub ifru_wake_flags: u32, pub ifru_route_refcnt: u32, pub ifru_cap: [::c_int; 2], pub ifru_functional_type: u32, } pub struct ifreq { pub ifr_name: [::c_char; ::IFNAMSIZ], #[cfg(libc_union)] pub ifr_ifru: __c_anonymous_ifr_ifru, #[cfg(not(libc_union))] pub ifr_ifru: ::sockaddr, } #[cfg(libc_union)] pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: *mut ::c_char, pub ifcu_req: *mut ifreq, } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { self.si_addr } pub unsafe fn si_value(&self) -> ::sigval { #[repr(C)] struct siginfo_timer { _si_signo: ::c_int, _si_errno: ::c_int, _si_code: ::c_int, _si_pid: ::pid_t, _si_uid: ::uid_t, _si_status: ::c_int, _si_addr: *mut ::c_void, si_value: ::sigval, } (*(self as *const siginfo_t as *const siginfo_timer)).si_value } pub unsafe fn si_pid(&self) -> ::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.si_status } } cfg_if! { if #[cfg(libc_union)] { s_no_extra_traits! { pub union semun { pub val: ::c_int, pub buf: *mut semid_ds, pub array: *mut ::c_ushort, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for semun { fn eq(&self, other: &semun) -> bool { unsafe { self.val == other.val } } } impl Eq for semun {} impl ::fmt::Debug for semun { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("semun") .field("val", unsafe { &self.val }) .finish() } } impl ::hash::Hash for semun { fn hash(&self, state: &mut H) { unsafe { self.val.hash(state) }; } } } } } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for kevent { fn eq(&self, other: &kevent) -> bool { self.ident == other.ident && self.filter == other.filter && self.flags == other.flags && self.fflags == other.fflags && self.data == other.data && self.udata == other.udata } } impl Eq for kevent {} impl ::fmt::Debug for kevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let ident = self.ident; let filter = self.filter; let flags = self.flags; let fflags = self.fflags; let data = self.data; let udata = self.udata; f.debug_struct("kevent") .field("ident", &ident) .field("filter", &filter) .field("flags", &flags) .field("fflags", &fflags) .field("data", &data) .field("udata", &udata) .finish() } } impl ::hash::Hash for kevent { fn hash(&self, state: &mut H) { let ident = self.ident; let filter = self.filter; let flags = self.flags; let fflags = self.fflags; let data = self.data; let udata = self.udata; ident.hash(state); filter.hash(state); flags.hash(state); fflags.hash(state); data.hash(state); udata.hash(state); } } impl PartialEq for semid_ds { fn eq(&self, other: &semid_ds) -> bool { let sem_perm = self.sem_perm; let sem_pad3 = self.sem_pad3; let other_sem_perm = other.sem_perm; let other_sem_pad3 = other.sem_pad3; sem_perm == other_sem_perm && self.sem_base == other.sem_base && self.sem_nsems == other.sem_nsems && self.sem_otime == other.sem_otime && self.sem_pad1 == other.sem_pad1 && self.sem_ctime == other.sem_ctime && self.sem_pad2 == other.sem_pad2 && sem_pad3 == other_sem_pad3 } } impl Eq for semid_ds {} impl ::fmt::Debug for semid_ds { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let sem_perm = self.sem_perm; let sem_base = self.sem_base; let sem_nsems = self.sem_nsems; let sem_otime = self.sem_otime; let sem_pad1 = self.sem_pad1; let sem_ctime = self.sem_ctime; let sem_pad2 = self.sem_pad2; let sem_pad3 = self.sem_pad3; f.debug_struct("semid_ds") .field("sem_perm", &sem_perm) .field("sem_base", &sem_base) .field("sem_nsems", &sem_nsems) .field("sem_otime", &sem_otime) .field("sem_pad1", &sem_pad1) .field("sem_ctime", &sem_ctime) .field("sem_pad2", &sem_pad2) .field("sem_pad3", &sem_pad3) .finish() } } impl ::hash::Hash for semid_ds { fn hash(&self, state: &mut H) { let sem_perm = self.sem_perm; let sem_base = self.sem_base; let sem_nsems = self.sem_nsems; let sem_otime = self.sem_otime; let sem_pad1 = self.sem_pad1; let sem_ctime = self.sem_ctime; let sem_pad2 = self.sem_pad2; let sem_pad3 = self.sem_pad3; sem_perm.hash(state); sem_base.hash(state); sem_nsems.hash(state); sem_otime.hash(state); sem_pad1.hash(state); sem_ctime.hash(state); sem_pad2.hash(state); sem_pad3.hash(state); } } impl PartialEq for shmid_ds { fn eq(&self, other: &shmid_ds) -> bool { let shm_perm = self.shm_perm; let other_shm_perm = other.shm_perm; shm_perm == other_shm_perm && self.shm_segsz == other.shm_segsz && self.shm_lpid == other.shm_lpid && self.shm_cpid == other.shm_cpid && self.shm_nattch == other.shm_nattch && self.shm_atime == other.shm_atime && self.shm_dtime == other.shm_dtime && self.shm_ctime == other.shm_ctime && self.shm_internal == other.shm_internal } } impl Eq for shmid_ds {} impl ::fmt::Debug for shmid_ds { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let shm_perm = self.shm_perm; let shm_segsz = self.shm_segsz; let shm_lpid = self.shm_lpid; let shm_cpid = self.shm_cpid; let shm_nattch = self.shm_nattch; let shm_atime = self.shm_atime; let shm_dtime = self.shm_dtime; let shm_ctime = self.shm_ctime; let shm_internal = self.shm_internal; f.debug_struct("shmid_ds") .field("shm_perm", &shm_perm) .field("shm_segsz", &shm_segsz) .field("shm_lpid", &shm_lpid) .field("shm_cpid", &shm_cpid) .field("shm_nattch", &shm_nattch) .field("shm_atime", &shm_atime) .field("shm_dtime", &shm_dtime) .field("shm_ctime", &shm_ctime) .field("shm_internal", &shm_internal) .finish() } } impl ::hash::Hash for shmid_ds { fn hash(&self, state: &mut H) { let shm_perm = self.shm_perm; let shm_segsz = self.shm_segsz; let shm_lpid = self.shm_lpid; let shm_cpid = self.shm_cpid; let shm_nattch = self.shm_nattch; let shm_atime = self.shm_atime; let shm_dtime = self.shm_dtime; let shm_ctime = self.shm_ctime; let shm_internal = self.shm_internal; shm_perm.hash(state); shm_segsz.hash(state); shm_lpid.hash(state); shm_cpid.hash(state); shm_nattch.hash(state); shm_atime.hash(state); shm_dtime.hash(state); shm_ctime.hash(state); shm_internal.hash(state); } } impl PartialEq for proc_threadinfo { fn eq(&self, other: &proc_threadinfo) -> bool { self.pth_user_time == other.pth_user_time && self.pth_system_time == other.pth_system_time && self.pth_cpu_usage == other.pth_cpu_usage && self.pth_policy == other.pth_policy && self.pth_run_state == other.pth_run_state && self.pth_flags == other.pth_flags && self.pth_sleep_time == other.pth_sleep_time && self.pth_curpri == other.pth_curpri && self.pth_priority == other.pth_priority && self.pth_maxpriority == other.pth_maxpriority && self.pth_name .iter() .zip(other.pth_name.iter()) .all(|(a,b)| a == b) } } impl Eq for proc_threadinfo {} impl ::fmt::Debug for proc_threadinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("proc_threadinfo") .field("pth_user_time", &self.pth_user_time) .field("pth_system_time", &self.pth_system_time) .field("pth_cpu_usage", &self.pth_cpu_usage) .field("pth_policy", &self.pth_policy) .field("pth_run_state", &self.pth_run_state) .field("pth_flags", &self.pth_flags) .field("pth_sleep_time", &self.pth_sleep_time) .field("pth_curpri", &self.pth_curpri) .field("pth_priority", &self.pth_priority) .field("pth_maxpriority", &self.pth_maxpriority) // FIXME: .field("pth_name", &self.pth_name) .finish() } } impl ::hash::Hash for proc_threadinfo { fn hash(&self, state: &mut H) { self.pth_user_time.hash(state); self.pth_system_time.hash(state); self.pth_cpu_usage.hash(state); self.pth_policy.hash(state); self.pth_run_state.hash(state); self.pth_flags.hash(state); self.pth_sleep_time.hash(state); self.pth_curpri.hash(state); self.pth_priority.hash(state); self.pth_maxpriority.hash(state); self.pth_name.hash(state); } } impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_fsid == other.f_fsid && self.f_owner == other.f_owner && self.f_flags == other.f_flags && self.f_fssubtype == other.f_fssubtype && self.f_fstypename == other.f_fstypename && self.f_type == other.f_type && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) && self.f_reserved == other.f_reserved } } impl Eq for statfs {} impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_fsid", &self.f_fsid) .field("f_owner", &self.f_owner) .field("f_flags", &self.f_flags) .field("f_fssubtype", &self.f_fssubtype) .field("f_fstypename", &self.f_fstypename) .field("f_type", &self.f_type) // FIXME: .field("f_mntonname", &self.f_mntonname) // FIXME: .field("f_mntfromname", &self.f_mntfromname) .field("f_reserved", &self.f_reserved) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_fsid.hash(state); self.f_owner.hash(state); self.f_flags.hash(state); self.f_fssubtype.hash(state); self.f_fstypename.hash(state); self.f_type.hash(state); self.f_mntonname.hash(state); self.f_mntfromname.hash(state); self.f_reserved.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_ino == other.d_ino && self.d_seekoff == other.d_seekoff && self.d_reclen == other.d_reclen && self.d_namlen == other.d_namlen && self.d_type == other.d_type && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_seekoff", &self.d_seekoff) .field("d_reclen", &self.d_reclen) .field("d_namlen", &self.d_namlen) .field("d_type", &self.d_type) // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_ino.hash(state); self.d_seekoff.hash(state); self.d_reclen.hash(state); self.d_namlen.hash(state); self.d_type.hash(state); self.d_name.hash(state); } } impl PartialEq for pthread_rwlock_t { fn eq(&self, other: &pthread_rwlock_t) -> bool { self.__sig == other.__sig && self. __opaque .iter() .zip(other.__opaque.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_rwlock_t {} impl ::fmt::Debug for pthread_rwlock_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_rwlock_t") .field("__sig", &self.__sig) // FIXME: .field("__opaque", &self.__opaque) .finish() } } impl ::hash::Hash for pthread_rwlock_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for pthread_mutex_t { fn eq(&self, other: &pthread_mutex_t) -> bool { self.__sig == other.__sig && self. __opaque .iter() .zip(other.__opaque.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_mutex_t {} impl ::fmt::Debug for pthread_mutex_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_mutex_t") .field("__sig", &self.__sig) // FIXME: .field("__opaque", &self.__opaque) .finish() } } impl ::hash::Hash for pthread_mutex_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for pthread_cond_t { fn eq(&self, other: &pthread_cond_t) -> bool { self.__sig == other.__sig && self. __opaque .iter() .zip(other.__opaque.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_cond_t {} impl ::fmt::Debug for pthread_cond_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_cond_t") .field("__sig", &self.__sig) // FIXME: .field("__opaque", &self.__opaque) .finish() } } impl ::hash::Hash for pthread_cond_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self .__ss_pad1 .iter() .zip(other.__ss_pad1.iter()) .all(|(a, b)| a == b) && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME: .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_user .iter() .zip(other.ut_user.iter()) .all(|(a,b)| a == b) && self.ut_id == other.ut_id && self.ut_line == other.ut_line && self.ut_pid == other.ut_pid && self.ut_type == other.ut_type && self.ut_tv == other.ut_tv && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self.ut_pad == other.ut_pad } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") // FIXME: .field("ut_user", &self.ut_user) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) .field("ut_pid", &self.ut_pid) .field("ut_type", &self.ut_type) .field("ut_tv", &self.ut_tv) // FIXME: .field("ut_host", &self.ut_host) .field("ut_pad", &self.ut_pad) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_user.hash(state); self.ut_id.hash(state); self.ut_line.hash(state); self.ut_pid.hash(state); self.ut_type.hash(state); self.ut_tv.hash(state); self.ut_host.hash(state); self.ut_pad.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_attributes == other.sigev_notify_attributes } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_attributes", &self.sigev_notify_attributes) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_attributes.hash(state); } } impl PartialEq for processor_cpu_load_info { fn eq(&self, other: &processor_cpu_load_info) -> bool { self.cpu_ticks == other.cpu_ticks } } impl Eq for processor_cpu_load_info {} impl ::fmt::Debug for processor_cpu_load_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("processor_cpu_load_info") .field("cpu_ticks", &self.cpu_ticks) .finish() } } impl ::hash::Hash for processor_cpu_load_info { fn hash(&self, state: &mut H) { self.cpu_ticks.hash(state); } } impl PartialEq for processor_basic_info { fn eq(&self, other: &processor_basic_info) -> bool { self.cpu_type == other.cpu_type && self.cpu_subtype == other.cpu_subtype && self.running == other.running && self.slot_num == other.slot_num && self.is_master == other.is_master } } impl Eq for processor_basic_info {} impl ::fmt::Debug for processor_basic_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("processor_basic_info") .field("cpu_type", &self.cpu_type) .field("cpu_subtype", &self.cpu_subtype) .field("running", &self.running) .field("slot_num", &self.slot_num) .field("is_master", &self.is_master) .finish() } } impl ::hash::Hash for processor_basic_info { fn hash(&self, state: &mut H) { self.cpu_type.hash(state); self.cpu_subtype.hash(state); self.running.hash(state); self.slot_num.hash(state); self.is_master.hash(state); } } impl PartialEq for processor_set_basic_info { fn eq(&self, other: &processor_set_basic_info) -> bool { self.processor_count == other.processor_count && self.default_policy == other.default_policy } } impl Eq for processor_set_basic_info {} impl ::fmt::Debug for processor_set_basic_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("processor_set_basic_info") .field("processor_count", &self.processor_count) .field("default_policy", &self.default_policy) .finish() } } impl ::hash::Hash for processor_set_basic_info { fn hash(&self, state: &mut H) { self.processor_count.hash(state); self.default_policy.hash(state); } } impl PartialEq for processor_set_load_info { fn eq(&self, other: &processor_set_load_info) -> bool { self.task_count == other.task_count && self.thread_count == other.thread_count && self.load_average == other.load_average && self.mach_factor == other.mach_factor } } impl Eq for processor_set_load_info {} impl ::fmt::Debug for processor_set_load_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("processor_set_load_info") .field("task_count", &self.task_count) .field("thread_count", &self.thread_count) .field("load_average", &self.load_average) .field("mach_factor", &self.mach_factor) .finish() } } impl ::hash::Hash for processor_set_load_info { fn hash(&self, state: &mut H) { self.task_count.hash(state); self.thread_count.hash(state); self.load_average.hash(state); self.mach_factor.hash(state); } } impl PartialEq for time_value_t { fn eq(&self, other: &time_value_t) -> bool { self.seconds == other.seconds && self.microseconds == other.microseconds } } impl Eq for time_value_t {} impl ::fmt::Debug for time_value_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("time_value_t") .field("seconds", &self.seconds) .field("microseconds", &self.microseconds) .finish() } } impl ::hash::Hash for time_value_t { fn hash(&self, state: &mut H) { self.seconds.hash(state); self.microseconds.hash(state); } } impl PartialEq for thread_basic_info { fn eq(&self, other: &thread_basic_info) -> bool { self.user_time == other.user_time && self.system_time == other.system_time && self.cpu_usage == other.cpu_usage && self.policy == other.policy && self.run_state == other.run_state && self.flags == other.flags && self.suspend_count == other.suspend_count && self.sleep_time == other.sleep_time } } impl Eq for thread_basic_info {} impl ::fmt::Debug for thread_basic_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("thread_basic_info") .field("user_time", &self.user_time) .field("system_time", &self.system_time) .field("cpu_usage", &self.cpu_usage) .field("policy", &self.policy) .field("run_state", &self.run_state) .field("flags", &self.flags) .field("suspend_count", &self.suspend_count) .field("sleep_time", &self.sleep_time) .finish() } } impl ::hash::Hash for thread_basic_info { fn hash(&self, state: &mut H) { self.user_time.hash(state); self.system_time.hash(state); self.cpu_usage.hash(state); self.policy.hash(state); self.run_state.hash(state); self.flags.hash(state); self.suspend_count.hash(state); self.sleep_time.hash(state); } } impl PartialEq for thread_extended_info { fn eq(&self, other: &thread_extended_info) -> bool { self.pth_user_time == other.pth_user_time && self.pth_system_time == other.pth_system_time && self.pth_cpu_usage == other.pth_cpu_usage && self.pth_policy == other.pth_policy && self.pth_run_state == other.pth_run_state && self.pth_flags == other.pth_flags && self.pth_sleep_time == other.pth_sleep_time && self.pth_curpri == other.pth_curpri && self.pth_priority == other.pth_priority && self.pth_maxpriority == other.pth_maxpriority && self.pth_name .iter() .zip(other.pth_name.iter()) .all(|(a,b)| a == b) } } impl Eq for thread_extended_info {} impl ::fmt::Debug for thread_extended_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("proc_threadinfo") .field("pth_user_time", &self.pth_user_time) .field("pth_system_time", &self.pth_system_time) .field("pth_cpu_usage", &self.pth_cpu_usage) .field("pth_policy", &self.pth_policy) .field("pth_run_state", &self.pth_run_state) .field("pth_flags", &self.pth_flags) .field("pth_sleep_time", &self.pth_sleep_time) .field("pth_curpri", &self.pth_curpri) .field("pth_priority", &self.pth_priority) .field("pth_maxpriority", &self.pth_maxpriority) // FIXME: .field("pth_name", &self.pth_name) .finish() } } impl ::hash::Hash for thread_extended_info { fn hash(&self, state: &mut H) { self.pth_user_time.hash(state); self.pth_system_time.hash(state); self.pth_cpu_usage.hash(state); self.pth_policy.hash(state); self.pth_run_state.hash(state); self.pth_flags.hash(state); self.pth_sleep_time.hash(state); self.pth_curpri.hash(state); self.pth_priority.hash(state); self.pth_maxpriority.hash(state); self.pth_name.hash(state); } } impl PartialEq for thread_identifier_info { fn eq(&self, other: &thread_identifier_info) -> bool { self.thread_id == other.thread_id && self.thread_handle == other.thread_handle && self.dispatch_qaddr == other.dispatch_qaddr } } impl Eq for thread_identifier_info {} impl ::fmt::Debug for thread_identifier_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("thread_identifier_info") .field("thread_id", &self.thread_id) .field("thread_handle", &self.thread_handle) .field("dispatch_qaddr", &self.dispatch_qaddr) .finish() } } impl ::hash::Hash for thread_identifier_info { fn hash(&self, state: &mut H) { self.thread_id.hash(state); self.thread_handle.hash(state); self.dispatch_qaddr.hash(state); } } impl PartialEq for if_data64 { fn eq(&self, other: &if_data64) -> bool { self.ifi_type == other.ifi_type && self.ifi_typelen == other.ifi_typelen && self.ifi_physical == other.ifi_physical && self.ifi_addrlen == other.ifi_addrlen && self.ifi_hdrlen == other.ifi_hdrlen && self.ifi_recvquota == other.ifi_recvquota && self.ifi_xmitquota == other.ifi_xmitquota && self.ifi_unused1 == other.ifi_unused1 && self.ifi_mtu == other.ifi_mtu && self.ifi_metric == other.ifi_metric && self.ifi_baudrate == other.ifi_baudrate && self.ifi_ipackets == other.ifi_ipackets && self.ifi_ierrors == other.ifi_ierrors && self.ifi_opackets == other.ifi_opackets && self.ifi_oerrors == other.ifi_oerrors && self.ifi_collisions == other.ifi_collisions && self.ifi_ibytes == other.ifi_ibytes && self.ifi_obytes == other.ifi_obytes && self.ifi_imcasts == other.ifi_imcasts && self.ifi_omcasts == other.ifi_omcasts && self.ifi_iqdrops == other.ifi_iqdrops && self.ifi_noproto == other.ifi_noproto && self.ifi_recvtiming == other.ifi_recvtiming && self.ifi_xmittiming == other.ifi_xmittiming && self.ifi_lastchange == other.ifi_lastchange } } impl Eq for if_data64 {} impl ::fmt::Debug for if_data64 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let ifi_type = self.ifi_type; let ifi_typelen = self.ifi_typelen; let ifi_physical = self.ifi_physical; let ifi_addrlen = self.ifi_addrlen; let ifi_hdrlen = self.ifi_hdrlen; let ifi_recvquota = self.ifi_recvquota; let ifi_xmitquota = self.ifi_xmitquota; let ifi_unused1 = self.ifi_unused1; let ifi_mtu = self.ifi_mtu; let ifi_metric = self.ifi_metric; let ifi_baudrate = self.ifi_baudrate; let ifi_ipackets = self.ifi_ipackets; let ifi_ierrors = self.ifi_ierrors; let ifi_opackets = self.ifi_opackets; let ifi_oerrors = self.ifi_oerrors; let ifi_collisions = self.ifi_collisions; let ifi_ibytes = self.ifi_ibytes; let ifi_obytes = self.ifi_obytes; let ifi_imcasts = self.ifi_imcasts; let ifi_omcasts = self.ifi_omcasts; let ifi_iqdrops = self.ifi_iqdrops; let ifi_noproto = self.ifi_noproto; let ifi_recvtiming = self.ifi_recvtiming; let ifi_xmittiming = self.ifi_xmittiming; let ifi_lastchange = self.ifi_lastchange; f.debug_struct("if_data64") .field("ifi_type", &ifi_type) .field("ifi_typelen", &ifi_typelen) .field("ifi_physical", &ifi_physical) .field("ifi_addrlen", &ifi_addrlen) .field("ifi_hdrlen", &ifi_hdrlen) .field("ifi_recvquota", &ifi_recvquota) .field("ifi_xmitquota", &ifi_xmitquota) .field("ifi_unused1", &ifi_unused1) .field("ifi_mtu", &ifi_mtu) .field("ifi_metric", &ifi_metric) .field("ifi_baudrate", &ifi_baudrate) .field("ifi_ipackets", &ifi_ipackets) .field("ifi_ierrors", &ifi_ierrors) .field("ifi_opackets", &ifi_opackets) .field("ifi_oerrors", &ifi_oerrors) .field("ifi_collisions", &ifi_collisions) .field("ifi_ibytes", &ifi_ibytes) .field("ifi_obytes", &ifi_obytes) .field("ifi_imcasts", &ifi_imcasts) .field("ifi_omcasts", &ifi_omcasts) .field("ifi_iqdrops", &ifi_iqdrops) .field("ifi_noproto", &ifi_noproto) .field("ifi_recvtiming", &ifi_recvtiming) .field("ifi_xmittiming", &ifi_xmittiming) .field("ifi_lastchange", &ifi_lastchange) .finish() } } impl ::hash::Hash for if_data64 { fn hash(&self, state: &mut H) { let ifi_type = self.ifi_type; let ifi_typelen = self.ifi_typelen; let ifi_physical = self.ifi_physical; let ifi_addrlen = self.ifi_addrlen; let ifi_hdrlen = self.ifi_hdrlen; let ifi_recvquota = self.ifi_recvquota; let ifi_xmitquota = self.ifi_xmitquota; let ifi_unused1 = self.ifi_unused1; let ifi_mtu = self.ifi_mtu; let ifi_metric = self.ifi_metric; let ifi_baudrate = self.ifi_baudrate; let ifi_ipackets = self.ifi_ipackets; let ifi_ierrors = self.ifi_ierrors; let ifi_opackets = self.ifi_opackets; let ifi_oerrors = self.ifi_oerrors; let ifi_collisions = self.ifi_collisions; let ifi_ibytes = self.ifi_ibytes; let ifi_obytes = self.ifi_obytes; let ifi_imcasts = self.ifi_imcasts; let ifi_omcasts = self.ifi_omcasts; let ifi_iqdrops = self.ifi_iqdrops; let ifi_noproto = self.ifi_noproto; let ifi_recvtiming = self.ifi_recvtiming; let ifi_xmittiming = self.ifi_xmittiming; let ifi_lastchange = self.ifi_lastchange; ifi_type.hash(state); ifi_typelen.hash(state); ifi_physical.hash(state); ifi_addrlen.hash(state); ifi_hdrlen.hash(state); ifi_recvquota.hash(state); ifi_xmitquota.hash(state); ifi_unused1.hash(state); ifi_mtu.hash(state); ifi_metric.hash(state); ifi_baudrate.hash(state); ifi_ipackets.hash(state); ifi_ierrors.hash(state); ifi_opackets.hash(state); ifi_oerrors.hash(state); ifi_collisions.hash(state); ifi_ibytes.hash(state); ifi_obytes.hash(state); ifi_imcasts.hash(state); ifi_omcasts.hash(state); ifi_iqdrops.hash(state); ifi_noproto.hash(state); ifi_recvtiming.hash(state); ifi_xmittiming.hash(state); ifi_lastchange.hash(state); } } impl PartialEq for if_msghdr2 { fn eq(&self, other: &if_msghdr2) -> bool { self.ifm_msglen == other.ifm_msglen && self.ifm_version == other.ifm_version && self.ifm_type == other.ifm_type && self.ifm_addrs == other.ifm_addrs && self.ifm_flags == other.ifm_flags && self.ifm_index == other.ifm_index && self.ifm_snd_len == other.ifm_snd_len && self.ifm_snd_maxlen == other.ifm_snd_maxlen && self.ifm_snd_drops == other.ifm_snd_drops && self.ifm_timer == other.ifm_timer && self.ifm_data == other.ifm_data } } impl Eq for if_msghdr2 {} impl ::fmt::Debug for if_msghdr2 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let ifm_msglen = self.ifm_msglen; let ifm_version = self.ifm_version; let ifm_type = self.ifm_type; let ifm_addrs = self.ifm_addrs; let ifm_flags = self.ifm_flags; let ifm_index = self.ifm_index; let ifm_snd_len = self.ifm_snd_len; let ifm_snd_maxlen = self.ifm_snd_maxlen; let ifm_snd_drops = self.ifm_snd_drops; let ifm_timer = self.ifm_timer; let ifm_data = self.ifm_data; f.debug_struct("if_msghdr2") .field("ifm_msglen", &ifm_msglen) .field("ifm_version", &ifm_version) .field("ifm_type", &ifm_type) .field("ifm_addrs", &ifm_addrs) .field("ifm_flags", &ifm_flags) .field("ifm_index", &ifm_index) .field("ifm_snd_len", &ifm_snd_len) .field("ifm_snd_maxlen", &ifm_snd_maxlen) .field("ifm_snd_drops", &ifm_snd_drops) .field("ifm_timer", &ifm_timer) .field("ifm_data", &ifm_data) .finish() } } impl ::hash::Hash for if_msghdr2 { fn hash(&self, state: &mut H) { let ifm_msglen = self.ifm_msglen; let ifm_version = self.ifm_version; let ifm_type = self.ifm_type; let ifm_addrs = self.ifm_addrs; let ifm_flags = self.ifm_flags; let ifm_index = self.ifm_index; let ifm_snd_len = self.ifm_snd_len; let ifm_snd_maxlen = self.ifm_snd_maxlen; let ifm_snd_drops = self.ifm_snd_drops; let ifm_timer = self.ifm_timer; let ifm_data = self.ifm_data; ifm_msglen.hash(state); ifm_version.hash(state); ifm_type.hash(state); ifm_addrs.hash(state); ifm_flags.hash(state); ifm_index.hash(state); ifm_snd_len.hash(state); ifm_snd_maxlen.hash(state); ifm_snd_drops.hash(state); ifm_timer.hash(state); ifm_data.hash(state); } } impl PartialEq for vm_statistics64 { fn eq(&self, other: &vm_statistics64) -> bool { // Otherwise rustfmt crashes... let total_uncompressed = self.total_uncompressed_pages_in_compressor; self.free_count == other.free_count && self.active_count == other.active_count && self.inactive_count == other.inactive_count && self.wire_count == other.wire_count && self.zero_fill_count == other.zero_fill_count && self.reactivations == other.reactivations && self.pageins == other.pageins && self.pageouts == other.pageouts && self.faults == other.faults && self.cow_faults == other.cow_faults && self.lookups == other.lookups && self.hits == other.hits && self.purges == other.purges && self.purgeable_count == other.purgeable_count && self.speculative_count == other.speculative_count && self.decompressions == other.decompressions && self.compressions == other.compressions && self.swapins == other.swapins && self.swapouts == other.swapouts && self.compressor_page_count == other.compressor_page_count && self.throttled_count == other.throttled_count && self.external_page_count == other.external_page_count && self.internal_page_count == other.internal_page_count && total_uncompressed == other.total_uncompressed_pages_in_compressor } } impl Eq for vm_statistics64 {} impl ::fmt::Debug for vm_statistics64 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let free_count = self.free_count; let active_count = self.active_count; let inactive_count = self.inactive_count; let wire_count = self.wire_count; let zero_fill_count = self.zero_fill_count; let reactivations = self.reactivations; let pageins = self.pageins; let pageouts = self.pageouts; let faults = self.faults; let cow_faults = self.cow_faults; let lookups = self.lookups; let hits = self.hits; let purges = self.purges; let purgeable_count = self.purgeable_count; let speculative_count = self.speculative_count; let decompressions = self.decompressions; let compressions = self.compressions; let swapins = self.swapins; let swapouts = self.swapouts; let compressor_page_count = self.compressor_page_count; let throttled_count = self.throttled_count; let external_page_count = self.external_page_count; let internal_page_count = self.internal_page_count; // Otherwise rustfmt crashes... let total_uncompressed = self.total_uncompressed_pages_in_compressor; f.debug_struct("vm_statistics64") .field("free_count", &free_count) .field("active_count", &active_count) .field("inactive_count", &inactive_count) .field("wire_count", &wire_count) .field("zero_fill_count", &zero_fill_count) .field("reactivations", &reactivations) .field("pageins", &pageins) .field("pageouts", &pageouts) .field("faults", &faults) .field("cow_faults", &cow_faults) .field("lookups", &lookups) .field("hits", &hits) .field("purges", &purges) .field("purgeable_count", &purgeable_count) .field("speculative_count", &speculative_count) .field("decompressions", &decompressions) .field("compressions", &compressions) .field("swapins", &swapins) .field("swapouts", &swapouts) .field("compressor_page_count", &compressor_page_count) .field("throttled_count", &throttled_count) .field("external_page_count", &external_page_count) .field("internal_page_count", &internal_page_count) .field("total_uncompressed_pages_in_compressor", &total_uncompressed) .finish() } } impl ::hash::Hash for vm_statistics64 { fn hash(&self, state: &mut H) { let free_count = self.free_count; let active_count = self.active_count; let inactive_count = self.inactive_count; let wire_count = self.wire_count; let zero_fill_count = self.zero_fill_count; let reactivations = self.reactivations; let pageins = self.pageins; let pageouts = self.pageouts; let faults = self.faults; let cow_faults = self.cow_faults; let lookups = self.lookups; let hits = self.hits; let purges = self.purges; let purgeable_count = self.purgeable_count; let speculative_count = self.speculative_count; let decompressions = self.decompressions; let compressions = self.compressions; let swapins = self.swapins; let swapouts = self.swapouts; let compressor_page_count = self.compressor_page_count; let throttled_count = self.throttled_count; let external_page_count = self.external_page_count; let internal_page_count = self.internal_page_count; // Otherwise rustfmt crashes... let total_uncompressed = self.total_uncompressed_pages_in_compressor; free_count.hash(state); active_count.hash(state); inactive_count.hash(state); wire_count.hash(state); zero_fill_count.hash(state); reactivations.hash(state); pageins.hash(state); pageouts.hash(state); faults.hash(state); cow_faults.hash(state); lookups.hash(state); hits.hash(state); purges.hash(state); purgeable_count.hash(state); speculative_count.hash(state); decompressions.hash(state); compressions.hash(state); swapins.hash(state); swapouts.hash(state); compressor_page_count.hash(state); throttled_count.hash(state); external_page_count.hash(state); internal_page_count.hash(state); total_uncompressed.hash(state); } } impl PartialEq for mach_task_basic_info { fn eq(&self, other: &mach_task_basic_info) -> bool { self.virtual_size == other.virtual_size && self.resident_size == other.resident_size && self.resident_size_max == other.resident_size_max && self.user_time == other.user_time && self.system_time == other.system_time && self.policy == other.policy && self.suspend_count == other.suspend_count } } impl Eq for mach_task_basic_info {} impl ::fmt::Debug for mach_task_basic_info { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let virtual_size = self.virtual_size; let resident_size = self.resident_size; let resident_size_max = self.resident_size_max; let user_time = self.user_time; let system_time = self.system_time; let policy = self.policy; let suspend_count = self.suspend_count; f.debug_struct("mach_task_basic_info") .field("virtual_size", &virtual_size) .field("resident_size", &resident_size) .field("resident_size_max", &resident_size_max) .field("user_time", &user_time) .field("system_time", &system_time) .field("policy", &policy) .field("suspend_count", &suspend_count) .finish() } } impl ::hash::Hash for mach_task_basic_info { fn hash(&self, state: &mut H) { let virtual_size = self.virtual_size; let resident_size = self.resident_size; let resident_size_max = self.resident_size_max; let user_time = self.user_time; let system_time = self.system_time; let policy = self.policy; let suspend_count = self.suspend_count; virtual_size.hash(state); resident_size.hash(state); resident_size_max.hash(state); user_time.hash(state); system_time.hash(state); policy.hash(state); suspend_count.hash(state); } } impl PartialEq for log2phys { fn eq(&self, other: &log2phys) -> bool { self.l2p_flags == other.l2p_flags && self.l2p_contigbytes == other.l2p_contigbytes && self.l2p_devoffset == other.l2p_devoffset } } impl Eq for log2phys {} impl ::fmt::Debug for log2phys { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let l2p_flags = self.l2p_flags; let l2p_contigbytes = self.l2p_contigbytes; let l2p_devoffset = self.l2p_devoffset; f.debug_struct("log2phys") .field("l2p_flags", &l2p_flags) .field("l2p_contigbytes", &l2p_contigbytes) .field("l2p_devoffset", &l2p_devoffset) .finish() } } impl ::hash::Hash for log2phys { fn hash(&self, state: &mut H) { let l2p_flags = self.l2p_flags; let l2p_contigbytes = self.l2p_contigbytes; let l2p_devoffset = self.l2p_devoffset; l2p_flags.hash(state); l2p_contigbytes.hash(state); l2p_devoffset.hash(state); } } impl PartialEq for os_unfair_lock { fn eq(&self, other: &os_unfair_lock) -> bool { self._os_unfair_lock_opaque == other._os_unfair_lock_opaque } } impl Eq for os_unfair_lock {} impl ::fmt::Debug for os_unfair_lock { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("os_unfair_lock") .field("_os_unfair_lock_opaque", &self._os_unfair_lock_opaque) .finish() } } impl ::hash::Hash for os_unfair_lock { fn hash(&self, state: &mut H) { self._os_unfair_lock_opaque.hash(state); } } impl PartialEq for sockaddr_vm { fn eq(&self, other: &sockaddr_vm) -> bool { self.svm_len == other.svm_len && self.svm_family == other.svm_family && self.svm_reserved1 == other.svm_reserved1 && self.svm_port == other.svm_port && self.svm_cid == other.svm_cid } } impl Eq for sockaddr_vm {} impl ::fmt::Debug for sockaddr_vm { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let svm_len = self.svm_len; let svm_family = self.svm_family; let svm_reserved1 = self.svm_reserved1; let svm_port = self.svm_port; let svm_cid = self.svm_cid; f.debug_struct("sockaddr_vm") .field("svm_len",&svm_len) .field("svm_family",&svm_family) .field("svm_reserved1",&svm_reserved1) .field("svm_port",&svm_port) .field("svm_cid",&svm_cid) .finish() } } impl ::hash::Hash for sockaddr_vm { fn hash(&self, state: &mut H) { let svm_len = self.svm_len; let svm_family = self.svm_family; let svm_reserved1 = self.svm_reserved1; let svm_port = self.svm_port; let svm_cid = self.svm_cid; svm_len.hash(state); svm_family.hash(state); svm_reserved1.hash(state); svm_port.hash(state); svm_cid.hash(state); } } impl PartialEq for ifdevmtu { fn eq(&self, other: &ifdevmtu) -> bool { self.ifdm_current == other.ifdm_current && self.ifdm_min == other.ifdm_min && self.ifdm_max == other.ifdm_max } } impl Eq for ifdevmtu {} impl ::fmt::Debug for ifdevmtu { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifdevmtu") .field("ifdm_current", &self.ifdm_current) .field("ifdm_min", &self.ifdm_min) .field("ifdm_max", &self.ifdm_max) .finish() } } impl ::hash::Hash for ifdevmtu { fn hash(&self, state: &mut H) { self.ifdm_current.hash(state); self.ifdm_min.hash(state); self.ifdm_max.hash(state); } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifk_data { fn eq(&self, other: &__c_anonymous_ifk_data) -> bool { unsafe { self.ifk_ptr == other.ifk_ptr && self.ifk_value == other.ifk_value } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifk_data {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifk_data { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__c_anonymous_ifk_data") .field("ifk_ptr", unsafe { &self.ifk_ptr }) .field("ifk_value", unsafe { &self.ifk_value }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifk_data { fn hash(&self, state: &mut H) { unsafe { self.ifk_ptr.hash(state); self.ifk_value.hash(state); } } } impl PartialEq for ifkpi { fn eq(&self, other: &ifkpi) -> bool { self.ifk_module_id == other.ifk_module_id && self.ifk_type == other.ifk_type } } impl Eq for ifkpi {} impl ::fmt::Debug for ifkpi { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifkpi") .field("ifk_module_id", &self.ifk_module_id) .field("ifk_type", &self.ifk_type) .finish() } } impl ::hash::Hash for ifkpi { fn hash(&self, state: &mut H) { self.ifk_module_id.hash(state); self.ifk_type.hash(state); } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifr_ifru { fn eq(&self, other: &__c_anonymous_ifr_ifru) -> bool { unsafe { self.ifru_addr == other.ifru_addr && self.ifru_dstaddr == other.ifru_dstaddr && self.ifru_broadaddr == other.ifru_broadaddr && self.ifru_flags == other.ifru_flags && self.ifru_metrics == other.ifru_metrics && self.ifru_mtu == other.ifru_mtu && self.ifru_phys == other.ifru_phys && self.ifru_media == other.ifru_media && self.ifru_intval == other.ifru_intval && self.ifru_data == other.ifru_data && self.ifru_devmtu == other.ifru_devmtu && self.ifru_kpi == other.ifru_kpi && self.ifru_wake_flags == other.ifru_wake_flags && self.ifru_route_refcnt == other.ifru_route_refcnt && self.ifru_cap.iter().zip(other.ifru_cap.iter()).all(|(a,b)| a == b) && self.ifru_functional_type == other.ifru_functional_type } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifr_ifru {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifr_ifru { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__c_anonymous_ifr_ifru") .field("ifru_addr", unsafe { &self.ifru_addr }) .field("ifru_dstaddr", unsafe { &self.ifru_dstaddr }) .field("ifru_broadaddr", unsafe { &self.ifru_broadaddr }) .field("ifru_flags", unsafe { &self.ifru_flags }) .field("ifru_metrics", unsafe { &self.ifru_metrics }) .field("ifru_mtu", unsafe { &self.ifru_mtu }) .field("ifru_phys", unsafe { &self.ifru_phys }) .field("ifru_media", unsafe { &self.ifru_media }) .field("ifru_intval", unsafe { &self.ifru_intval }) .field("ifru_data", unsafe { &self.ifru_data }) .field("ifru_devmtu", unsafe { &self.ifru_devmtu }) .field("ifru_kpi", unsafe { &self.ifru_kpi }) .field("ifru_wake_flags", unsafe { &self.ifru_wake_flags }) .field("ifru_route_refcnt", unsafe { &self.ifru_route_refcnt }) .field("ifru_cap", unsafe { &self.ifru_cap }) .field("ifru_functional_type", unsafe { &self.ifru_functional_type }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifr_ifru { fn hash(&self, state: &mut H) { unsafe { self.ifru_addr.hash(state); self.ifru_dstaddr.hash(state); self.ifru_broadaddr.hash(state); self.ifru_flags.hash(state); self.ifru_metrics.hash(state); self.ifru_mtu.hash(state); self.ifru_phys.hash(state); self.ifru_media.hash(state); self.ifru_intval.hash(state); self.ifru_data.hash(state); self.ifru_devmtu.hash(state); self.ifru_kpi.hash(state); self.ifru_wake_flags.hash(state); self.ifru_route_refcnt.hash(state); self.ifru_cap.hash(state); self.ifru_functional_type.hash(state); } } } impl PartialEq for ifreq { fn eq(&self, other: &ifreq) -> bool { self.ifr_name == other.ifr_name && self.ifr_ifru == other.ifr_ifru } } impl Eq for ifreq {} impl ::fmt::Debug for ifreq { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } impl ::hash::Hash for ifreq { fn hash(&self, state: &mut H) { self.ifr_name.hash(state); self.ifr_ifru.hash(state); } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifc_ifcu {} #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifc_ifcu { fn eq(&self, other: &__c_anonymous_ifc_ifcu) -> bool { unsafe { self.ifcu_buf == other.ifcu_buf && self.ifcu_req == other.ifcu_req } } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifc_ifcu { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifc_ifcu") .field("ifcu_buf", unsafe { &self.ifcu_buf }) .field("ifcu_req", unsafe { &self.ifcu_req }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifc_ifcu { fn hash(&self, state: &mut H) { unsafe { self.ifcu_buf.hash(state) }; unsafe { self.ifcu_req.hash(state) }; } } } } pub const _UTX_USERSIZE: usize = 256; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 256; pub const EMPTY: ::c_short = 0; pub const RUN_LVL: ::c_short = 1; pub const BOOT_TIME: ::c_short = 2; pub const OLD_TIME: ::c_short = 3; pub const NEW_TIME: ::c_short = 4; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const USER_PROCESS: ::c_short = 7; pub const DEAD_PROCESS: ::c_short = 8; pub const ACCOUNTING: ::c_short = 9; pub const SIGNATURE: ::c_short = 10; pub const SHUTDOWN_TIME: ::c_short = 11; pub const LC_COLLATE_MASK: ::c_int = 1 << 0; pub const LC_CTYPE_MASK: ::c_int = 1 << 1; pub const LC_MESSAGES_MASK: ::c_int = 1 << 2; pub const LC_MONETARY_MASK: ::c_int = 1 << 3; pub const LC_NUMERIC_MASK: ::c_int = 1 << 4; pub const LC_TIME_MASK: ::c_int = 1 << 5; pub const LC_ALL_MASK: ::c_int = LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK; pub const CODESET: ::nl_item = 0; pub const D_T_FMT: ::nl_item = 1; pub const D_FMT: ::nl_item = 2; pub const T_FMT: ::nl_item = 3; pub const T_FMT_AMPM: ::nl_item = 4; pub const AM_STR: ::nl_item = 5; pub const PM_STR: ::nl_item = 6; pub const DAY_1: ::nl_item = 7; pub const DAY_2: ::nl_item = 8; pub const DAY_3: ::nl_item = 9; pub const DAY_4: ::nl_item = 10; pub const DAY_5: ::nl_item = 11; pub const DAY_6: ::nl_item = 12; pub const DAY_7: ::nl_item = 13; pub const ABDAY_1: ::nl_item = 14; pub const ABDAY_2: ::nl_item = 15; pub const ABDAY_3: ::nl_item = 16; pub const ABDAY_4: ::nl_item = 17; pub const ABDAY_5: ::nl_item = 18; pub const ABDAY_6: ::nl_item = 19; pub const ABDAY_7: ::nl_item = 20; pub const MON_1: ::nl_item = 21; pub const MON_2: ::nl_item = 22; pub const MON_3: ::nl_item = 23; pub const MON_4: ::nl_item = 24; pub const MON_5: ::nl_item = 25; pub const MON_6: ::nl_item = 26; pub const MON_7: ::nl_item = 27; pub const MON_8: ::nl_item = 28; pub const MON_9: ::nl_item = 29; pub const MON_10: ::nl_item = 30; pub const MON_11: ::nl_item = 31; pub const MON_12: ::nl_item = 32; pub const ABMON_1: ::nl_item = 33; pub const ABMON_2: ::nl_item = 34; pub const ABMON_3: ::nl_item = 35; pub const ABMON_4: ::nl_item = 36; pub const ABMON_5: ::nl_item = 37; pub const ABMON_6: ::nl_item = 38; pub const ABMON_7: ::nl_item = 39; pub const ABMON_8: ::nl_item = 40; pub const ABMON_9: ::nl_item = 41; pub const ABMON_10: ::nl_item = 42; pub const ABMON_11: ::nl_item = 43; pub const ABMON_12: ::nl_item = 44; pub const CLOCK_REALTIME: ::clockid_t = 0; pub const CLOCK_MONOTONIC_RAW: ::clockid_t = 4; pub const CLOCK_MONOTONIC_RAW_APPROX: ::clockid_t = 5; pub const CLOCK_MONOTONIC: ::clockid_t = 6; pub const CLOCK_UPTIME_RAW: ::clockid_t = 8; pub const CLOCK_UPTIME_RAW_APPROX: ::clockid_t = 9; pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 12; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 16; pub const ERA: ::nl_item = 45; pub const ERA_D_FMT: ::nl_item = 46; pub const ERA_D_T_FMT: ::nl_item = 47; pub const ERA_T_FMT: ::nl_item = 48; pub const ALT_DIGITS: ::nl_item = 49; pub const RADIXCHAR: ::nl_item = 50; pub const THOUSEP: ::nl_item = 51; pub const YESEXPR: ::nl_item = 52; pub const NOEXPR: ::nl_item = 53; pub const YESSTR: ::nl_item = 54; pub const NOSTR: ::nl_item = 55; pub const CRNCYSTR: ::nl_item = 56; pub const D_MD_ORDER: ::nl_item = 57; pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const RAND_MAX: ::c_int = 2147483647; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const SEEK_HOLE: ::c_int = 3; pub const SEEK_DATA: ::c_int = 4; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 2; pub const _IOLBF: ::c_int = 1; pub const BUFSIZ: ::c_uint = 1024; pub const FOPEN_MAX: ::c_uint = 20; pub const FILENAME_MAX: ::c_uint = 1024; pub const L_tmpnam: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 308915776; pub const _PC_LINK_MAX: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_CHOWN_RESTRICTED: ::c_int = 7; pub const _PC_NO_TRUNC: ::c_int = 8; pub const _PC_VDISABLE: ::c_int = 9; pub const _PC_NAME_CHARS_MAX: ::c_int = 10; pub const _PC_CASE_SENSITIVE: ::c_int = 11; pub const _PC_CASE_PRESERVING: ::c_int = 12; pub const _PC_EXTENDED_SECURITY_NP: ::c_int = 13; pub const _PC_AUTH_OPAQUE_NP: ::c_int = 14; pub const _PC_2_SYMLINKS: ::c_int = 15; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 16; pub const _PC_ASYNC_IO: ::c_int = 17; pub const _PC_FILESIZEBITS: ::c_int = 18; pub const _PC_PRIO_IO: ::c_int = 19; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 20; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 21; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 22; pub const _PC_REC_XFER_ALIGN: ::c_int = 23; pub const _PC_SYMLINK_MAX: ::c_int = 24; pub const _PC_SYNC_IO: ::c_int = 25; pub const _PC_XATTR_SIZE_BITS: ::c_int = 26; pub const _PC_MIN_HOLE_SIZE: ::c_int = 27; pub const O_EVTONLY: ::c_int = 0x00008000; pub const O_NOCTTY: ::c_int = 0x00020000; pub const O_DIRECTORY: ::c_int = 0x00100000; pub const O_SYMLINK: ::c_int = 0x00200000; pub const O_DSYNC: ::c_int = 0x00400000; pub const O_CLOEXEC: ::c_int = 0x01000000; pub const O_NOFOLLOW_ANY: ::c_int = 0x20000000; pub const O_EXEC: ::c_int = 0x40000000; pub const O_SEARCH: ::c_int = O_EXEC | O_DIRECTORY; pub const S_IFIFO: mode_t = 4096; pub const S_IFCHR: mode_t = 8192; pub const S_IFBLK: mode_t = 24576; pub const S_IFDIR: mode_t = 16384; pub const S_IFREG: mode_t = 32768; pub const S_IFLNK: mode_t = 40960; pub const S_IFSOCK: mode_t = 49152; pub const S_IFMT: mode_t = 61440; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; pub const S_IREAD: mode_t = 256; pub const S_IRWXU: mode_t = 448; pub const S_IXUSR: mode_t = 64; pub const S_IWUSR: mode_t = 128; pub const S_IRUSR: mode_t = 256; pub const S_IRWXG: mode_t = 56; pub const S_IXGRP: mode_t = 8; pub const S_IWGRP: mode_t = 16; pub const S_IRGRP: mode_t = 32; pub const S_IRWXO: mode_t = 7; pub const S_IXOTH: mode_t = 1; pub const S_IWOTH: mode_t = 2; pub const S_IROTH: mode_t = 4; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const F_GETLK: ::c_int = 7; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const PT_TRACE_ME: ::c_int = 0; pub const PT_READ_I: ::c_int = 1; pub const PT_READ_D: ::c_int = 2; pub const PT_READ_U: ::c_int = 3; pub const PT_WRITE_I: ::c_int = 4; pub const PT_WRITE_D: ::c_int = 5; pub const PT_WRITE_U: ::c_int = 6; pub const PT_CONTINUE: ::c_int = 7; pub const PT_KILL: ::c_int = 8; pub const PT_STEP: ::c_int = 9; pub const PT_ATTACH: ::c_int = 10; pub const PT_DETACH: ::c_int = 11; pub const PT_SIGEXC: ::c_int = 12; pub const PT_THUPDATE: ::c_int = 13; pub const PT_ATTACHEXC: ::c_int = 14; pub const PT_FORCEQUOTA: ::c_int = 30; pub const PT_DENY_ATTACH: ::c_int = 31; pub const PT_FIRSTMACH: ::c_int = 32; pub const MAP_FILE: ::c_int = 0x0000; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_ANON: ::c_int = 0x1000; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const CPU_STATE_USER: ::c_int = 0; pub const CPU_STATE_SYSTEM: ::c_int = 1; pub const CPU_STATE_IDLE: ::c_int = 2; pub const CPU_STATE_NICE: ::c_int = 3; pub const CPU_STATE_MAX: ::c_int = 4; pub const PROCESSOR_BASIC_INFO: ::c_int = 1; pub const PROCESSOR_CPU_LOAD_INFO: ::c_int = 2; pub const PROCESSOR_PM_REGS_INFO: ::c_int = 0x10000001; pub const PROCESSOR_TEMPERATURE: ::c_int = 0x10000002; pub const PROCESSOR_SET_LOAD_INFO: ::c_int = 4; pub const PROCESSOR_SET_BASIC_INFO: ::c_int = 5; deprecated_mach! { pub const VM_FLAGS_FIXED: ::c_int = 0x0000; pub const VM_FLAGS_ANYWHERE: ::c_int = 0x0001; pub const VM_FLAGS_PURGABLE: ::c_int = 0x0002; pub const VM_FLAGS_RANDOM_ADDR: ::c_int = 0x0008; pub const VM_FLAGS_NO_CACHE: ::c_int = 0x0010; pub const VM_FLAGS_RESILIENT_CODESIGN: ::c_int = 0x0020; pub const VM_FLAGS_RESILIENT_MEDIA: ::c_int = 0x0040; pub const VM_FLAGS_OVERWRITE: ::c_int = 0x4000; pub const VM_FLAGS_SUPERPAGE_MASK: ::c_int = 0x70000; pub const VM_FLAGS_RETURN_DATA_ADDR: ::c_int = 0x100000; pub const VM_FLAGS_RETURN_4K_DATA_ADDR: ::c_int = 0x800000; pub const VM_FLAGS_ALIAS_MASK: ::c_int = 0xFF000000; pub const VM_FLAGS_USER_ALLOCATE: ::c_int = 0xff07401f; pub const VM_FLAGS_USER_MAP: ::c_int = 0xff97401f; pub const VM_FLAGS_USER_REMAP: ::c_int = VM_FLAGS_FIXED | VM_FLAGS_ANYWHERE | VM_FLAGS_RANDOM_ADDR | VM_FLAGS_OVERWRITE | VM_FLAGS_RETURN_DATA_ADDR | VM_FLAGS_RESILIENT_CODESIGN; pub const VM_FLAGS_SUPERPAGE_SHIFT: ::c_int = 16; pub const SUPERPAGE_NONE: ::c_int = 0; pub const SUPERPAGE_SIZE_ANY: ::c_int = 1; pub const VM_FLAGS_SUPERPAGE_NONE: ::c_int = SUPERPAGE_NONE << VM_FLAGS_SUPERPAGE_SHIFT; pub const VM_FLAGS_SUPERPAGE_SIZE_ANY: ::c_int = SUPERPAGE_SIZE_ANY << VM_FLAGS_SUPERPAGE_SHIFT; pub const SUPERPAGE_SIZE_2MB: ::c_int = 2; pub const VM_FLAGS_SUPERPAGE_SIZE_2MB: ::c_int = SUPERPAGE_SIZE_2MB << VM_FLAGS_SUPERPAGE_SHIFT; pub const VM_MEMORY_MALLOC: ::c_int = 1; pub const VM_MEMORY_MALLOC_SMALL: ::c_int = 2; pub const VM_MEMORY_MALLOC_LARGE: ::c_int = 3; pub const VM_MEMORY_MALLOC_HUGE: ::c_int = 4; pub const VM_MEMORY_SBRK: ::c_int = 5; pub const VM_MEMORY_REALLOC: ::c_int = 6; pub const VM_MEMORY_MALLOC_TINY: ::c_int = 7; pub const VM_MEMORY_MALLOC_LARGE_REUSABLE: ::c_int = 8; pub const VM_MEMORY_MALLOC_LARGE_REUSED: ::c_int = 9; pub const VM_MEMORY_ANALYSIS_TOOL: ::c_int = 10; pub const VM_MEMORY_MALLOC_NANO: ::c_int = 11; pub const VM_MEMORY_MACH_MSG: ::c_int = 20; pub const VM_MEMORY_IOKIT: ::c_int = 21; pub const VM_MEMORY_STACK: ::c_int = 30; pub const VM_MEMORY_GUARD: ::c_int = 31; pub const VM_MEMORY_SHARED_PMAP: ::c_int = 32; pub const VM_MEMORY_DYLIB: ::c_int = 33; pub const VM_MEMORY_OBJC_DISPATCHERS: ::c_int = 34; pub const VM_MEMORY_UNSHARED_PMAP: ::c_int = 35; pub const VM_MEMORY_APPKIT: ::c_int = 40; pub const VM_MEMORY_FOUNDATION: ::c_int = 41; pub const VM_MEMORY_COREGRAPHICS: ::c_int = 42; pub const VM_MEMORY_CORESERVICES: ::c_int = 43; pub const VM_MEMORY_CARBON: ::c_int = VM_MEMORY_CORESERVICES; pub const VM_MEMORY_JAVA: ::c_int = 44; pub const VM_MEMORY_COREDATA: ::c_int = 45; pub const VM_MEMORY_COREDATA_OBJECTIDS: ::c_int = 46; pub const VM_MEMORY_ATS: ::c_int = 50; pub const VM_MEMORY_LAYERKIT: ::c_int = 51; pub const VM_MEMORY_CGIMAGE: ::c_int = 52; pub const VM_MEMORY_TCMALLOC: ::c_int = 53; pub const VM_MEMORY_COREGRAPHICS_DATA: ::c_int = 54; pub const VM_MEMORY_COREGRAPHICS_SHARED: ::c_int = 55; pub const VM_MEMORY_COREGRAPHICS_FRAMEBUFFERS: ::c_int = 56; pub const VM_MEMORY_COREGRAPHICS_BACKINGSTORES: ::c_int = 57; pub const VM_MEMORY_COREGRAPHICS_XALLOC: ::c_int = 58; pub const VM_MEMORY_COREGRAPHICS_MISC: ::c_int = VM_MEMORY_COREGRAPHICS; pub const VM_MEMORY_DYLD: ::c_int = 60; pub const VM_MEMORY_DYLD_MALLOC: ::c_int = 61; pub const VM_MEMORY_SQLITE: ::c_int = 62; pub const VM_MEMORY_JAVASCRIPT_CORE: ::c_int = 63; pub const VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR: ::c_int = 64; pub const VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE: ::c_int = 65; pub const VM_MEMORY_GLSL: ::c_int = 66; pub const VM_MEMORY_OPENCL: ::c_int = 67; pub const VM_MEMORY_COREIMAGE: ::c_int = 68; pub const VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS: ::c_int = 69; pub const VM_MEMORY_IMAGEIO: ::c_int = 70; pub const VM_MEMORY_COREPROFILE: ::c_int = 71; pub const VM_MEMORY_ASSETSD: ::c_int = 72; pub const VM_MEMORY_OS_ALLOC_ONCE: ::c_int = 73; pub const VM_MEMORY_LIBDISPATCH: ::c_int = 74; pub const VM_MEMORY_ACCELERATE: ::c_int = 75; pub const VM_MEMORY_COREUI: ::c_int = 76; pub const VM_MEMORY_COREUIFILE: ::c_int = 77; pub const VM_MEMORY_GENEALOGY: ::c_int = 78; pub const VM_MEMORY_RAWCAMERA: ::c_int = 79; pub const VM_MEMORY_CORPSEINFO: ::c_int = 80; pub const VM_MEMORY_ASL: ::c_int = 81; pub const VM_MEMORY_SWIFT_RUNTIME: ::c_int = 82; pub const VM_MEMORY_SWIFT_METADATA: ::c_int = 83; pub const VM_MEMORY_DHMM: ::c_int = 84; pub const VM_MEMORY_SCENEKIT: ::c_int = 86; pub const VM_MEMORY_SKYWALK: ::c_int = 87; pub const VM_MEMORY_APPLICATION_SPECIFIC_1: ::c_int = 240; pub const VM_MEMORY_APPLICATION_SPECIFIC_16: ::c_int = 255; } pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MS_ASYNC: ::c_int = 0x0001; pub const MS_INVALIDATE: ::c_int = 0x0002; pub const MS_SYNC: ::c_int = 0x0010; pub const MS_KILLPAGES: ::c_int = 0x0004; pub const MS_DEACTIVATE: ::c_int = 0x0008; pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EDEADLK: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EAGAIN: ::c_int = 35; pub const EWOULDBLOCK: ::c_int = EAGAIN; pub const EINPROGRESS: ::c_int = 36; pub const EALREADY: ::c_int = 37; pub const ENOTSOCK: ::c_int = 38; pub const EDESTADDRREQ: ::c_int = 39; pub const EMSGSIZE: ::c_int = 40; pub const EPROTOTYPE: ::c_int = 41; pub const ENOPROTOOPT: ::c_int = 42; pub const EPROTONOSUPPORT: ::c_int = 43; pub const ESOCKTNOSUPPORT: ::c_int = 44; pub const ENOTSUP: ::c_int = 45; pub const EPFNOSUPPORT: ::c_int = 46; pub const EAFNOSUPPORT: ::c_int = 47; pub const EADDRINUSE: ::c_int = 48; pub const EADDRNOTAVAIL: ::c_int = 49; pub const ENETDOWN: ::c_int = 50; pub const ENETUNREACH: ::c_int = 51; pub const ENETRESET: ::c_int = 52; pub const ECONNABORTED: ::c_int = 53; pub const ECONNRESET: ::c_int = 54; pub const ENOBUFS: ::c_int = 55; pub const EISCONN: ::c_int = 56; pub const ENOTCONN: ::c_int = 57; pub const ESHUTDOWN: ::c_int = 58; pub const ETOOMANYREFS: ::c_int = 59; pub const ETIMEDOUT: ::c_int = 60; pub const ECONNREFUSED: ::c_int = 61; pub const ELOOP: ::c_int = 62; pub const ENAMETOOLONG: ::c_int = 63; pub const EHOSTDOWN: ::c_int = 64; pub const EHOSTUNREACH: ::c_int = 65; pub const ENOTEMPTY: ::c_int = 66; pub const EPROCLIM: ::c_int = 67; pub const EUSERS: ::c_int = 68; pub const EDQUOT: ::c_int = 69; pub const ESTALE: ::c_int = 70; pub const EREMOTE: ::c_int = 71; pub const EBADRPC: ::c_int = 72; pub const ERPCMISMATCH: ::c_int = 73; pub const EPROGUNAVAIL: ::c_int = 74; pub const EPROGMISMATCH: ::c_int = 75; pub const EPROCUNAVAIL: ::c_int = 76; pub const ENOLCK: ::c_int = 77; pub const ENOSYS: ::c_int = 78; pub const EFTYPE: ::c_int = 79; pub const EAUTH: ::c_int = 80; pub const ENEEDAUTH: ::c_int = 81; pub const EPWROFF: ::c_int = 82; pub const EDEVERR: ::c_int = 83; pub const EOVERFLOW: ::c_int = 84; pub const EBADEXEC: ::c_int = 85; pub const EBADARCH: ::c_int = 86; pub const ESHLIBVERS: ::c_int = 87; pub const EBADMACHO: ::c_int = 88; pub const ECANCELED: ::c_int = 89; pub const EIDRM: ::c_int = 90; pub const ENOMSG: ::c_int = 91; pub const EILSEQ: ::c_int = 92; pub const ENOATTR: ::c_int = 93; pub const EBADMSG: ::c_int = 94; pub const EMULTIHOP: ::c_int = 95; pub const ENODATA: ::c_int = 96; pub const ENOLINK: ::c_int = 97; pub const ENOSR: ::c_int = 98; pub const ENOSTR: ::c_int = 99; pub const EPROTO: ::c_int = 100; pub const ETIME: ::c_int = 101; pub const EOPNOTSUPP: ::c_int = 102; pub const ENOPOLICY: ::c_int = 103; pub const ENOTRECOVERABLE: ::c_int = 104; pub const EOWNERDEAD: ::c_int = 105; pub const EQFULL: ::c_int = 106; pub const ELAST: ::c_int = 106; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_NODATA: ::c_int = 7; pub const EAI_NONAME: ::c_int = 8; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 14; pub const F_DUPFD: ::c_int = 0; pub const F_DUPFD_CLOEXEC: ::c_int = 67; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const F_PREALLOCATE: ::c_int = 42; pub const F_RDADVISE: ::c_int = 44; pub const F_RDAHEAD: ::c_int = 45; pub const F_NOCACHE: ::c_int = 48; pub const F_LOG2PHYS: ::c_int = 49; pub const F_GETPATH: ::c_int = 50; pub const F_FULLFSYNC: ::c_int = 51; pub const F_FREEZE_FS: ::c_int = 53; pub const F_THAW_FS: ::c_int = 54; pub const F_GLOBAL_NOCACHE: ::c_int = 55; pub const F_NODIRECT: ::c_int = 62; pub const F_LOG2PHYS_EXT: ::c_int = 65; pub const F_BARRIERFSYNC: ::c_int = 85; pub const F_PUNCHHOLE: ::c_int = 99; pub const F_TRIM_ACTIVE_FILE: ::c_int = 100; pub const F_SPECULATIVE_READ: ::c_int = 101; pub const F_GETPATH_NOFIRMLINK: ::c_int = 102; pub const F_ALLOCATECONTIG: ::c_uint = 0x02; pub const F_ALLOCATEALL: ::c_uint = 0x04; pub const F_PEOFPOSMODE: ::c_int = 3; pub const F_VOLPOSMODE: ::c_int = 4; pub const AT_FDCWD: ::c_int = -2; pub const AT_EACCESS: ::c_int = 0x0010; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x0020; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x0040; pub const AT_REMOVEDIR: ::c_int = 0x0080; pub const PTHREAD_INTROSPECTION_THREAD_CREATE: ::c_uint = 1; pub const PTHREAD_INTROSPECTION_THREAD_START: ::c_uint = 2; pub const PTHREAD_INTROSPECTION_THREAD_TERMINATE: ::c_uint = 3; pub const PTHREAD_INTROSPECTION_THREAD_DESTROY: ::c_uint = 4; pub const TIOCMODG: ::c_ulong = 0x40047403; pub const TIOCMODS: ::c_ulong = 0x80047404; pub const TIOCM_LE: ::c_int = 0x1; pub const TIOCM_DTR: ::c_int = 0x2; pub const TIOCM_RTS: ::c_int = 0x4; pub const TIOCM_ST: ::c_int = 0x8; pub const TIOCM_SR: ::c_int = 0x10; pub const TIOCM_CTS: ::c_int = 0x20; pub const TIOCM_CAR: ::c_int = 0x40; pub const TIOCM_CD: ::c_int = 0x40; pub const TIOCM_RNG: ::c_int = 0x80; pub const TIOCM_RI: ::c_int = 0x80; pub const TIOCM_DSR: ::c_int = 0x100; pub const TIOCEXCL: ::c_int = 0x2000740d; pub const TIOCNXCL: ::c_int = 0x2000740e; pub const TIOCFLUSH: ::c_ulong = 0x80047410; pub const TIOCGETD: ::c_ulong = 0x4004741a; pub const TIOCSETD: ::c_ulong = 0x8004741b; pub const TIOCIXON: ::c_uint = 0x20007481; pub const TIOCIXOFF: ::c_uint = 0x20007480; pub const TIOCSDTR: ::c_uint = 0x20007479; pub const TIOCCDTR: ::c_uint = 0x20007478; pub const TIOCGPGRP: ::c_ulong = 0x40047477; pub const TIOCSPGRP: ::c_ulong = 0x80047476; pub const TIOCOUTQ: ::c_ulong = 0x40047473; pub const TIOCSTI: ::c_ulong = 0x80017472; pub const TIOCNOTTY: ::c_uint = 0x20007471; pub const TIOCPKT: ::c_ulong = 0x80047470; pub const TIOCPKT_DATA: ::c_int = 0x0; pub const TIOCPKT_FLUSHREAD: ::c_int = 0x1; pub const TIOCPKT_FLUSHWRITE: ::c_int = 0x2; pub const TIOCPKT_STOP: ::c_int = 0x4; pub const TIOCPKT_START: ::c_int = 0x8; pub const TIOCPKT_NOSTOP: ::c_int = 0x10; pub const TIOCPKT_DOSTOP: ::c_int = 0x20; pub const TIOCPKT_IOCTL: ::c_int = 0x40; pub const TIOCSTOP: ::c_uint = 0x2000746f; pub const TIOCSTART: ::c_uint = 0x2000746e; pub const TIOCMSET: ::c_ulong = 0x8004746d; pub const TIOCMBIS: ::c_ulong = 0x8004746c; pub const TIOCMBIC: ::c_ulong = 0x8004746b; pub const TIOCMGET: ::c_ulong = 0x4004746a; pub const TIOCREMOTE: ::c_ulong = 0x80047469; pub const TIOCGWINSZ: ::c_ulong = 0x40087468; pub const TIOCSWINSZ: ::c_ulong = 0x80087467; pub const TIOCUCNTL: ::c_ulong = 0x80047466; pub const TIOCSTAT: ::c_uint = 0x20007465; pub const TIOCSCONS: ::c_uint = 0x20007463; pub const TIOCCONS: ::c_ulong = 0x80047462; pub const TIOCSCTTY: ::c_uint = 0x20007461; pub const TIOCEXT: ::c_ulong = 0x80047460; pub const TIOCSIG: ::c_uint = 0x2000745f; pub const TIOCDRAIN: ::c_uint = 0x2000745e; pub const TIOCMSDTRWAIT: ::c_ulong = 0x8004745b; pub const TIOCMGDTRWAIT: ::c_ulong = 0x4004745a; pub const TIOCSDRAINWAIT: ::c_ulong = 0x80047457; pub const TIOCGDRAINWAIT: ::c_ulong = 0x40047456; pub const TIOCDSIMICROCODE: ::c_uint = 0x20007455; pub const TIOCPTYGRANT: ::c_uint = 0x20007454; pub const TIOCPTYGNAME: ::c_uint = 0x40807453; pub const TIOCPTYUNLK: ::c_uint = 0x20007452; pub const BIOCGRSIG: ::c_ulong = 0x40044272; pub const BIOCSRSIG: ::c_ulong = 0x80044273; pub const BIOCSDLT: ::c_ulong = 0x80044278; pub const BIOCGSEESENT: ::c_ulong = 0x40044276; pub const BIOCSSEESENT: ::c_ulong = 0x80044277; pub const BIOCGDLTLIST: ::c_ulong = 0xc00c4279; pub const FIODTYPE: ::c_ulong = 0x4004667a; pub const B0: speed_t = 0; pub const B50: speed_t = 50; pub const B75: speed_t = 75; pub const B110: speed_t = 110; pub const B134: speed_t = 134; pub const B150: speed_t = 150; pub const B200: speed_t = 200; pub const B300: speed_t = 300; pub const B600: speed_t = 600; pub const B1200: speed_t = 1200; pub const B1800: speed_t = 1800; pub const B2400: speed_t = 2400; pub const B4800: speed_t = 4800; pub const B9600: speed_t = 9600; pub const B19200: speed_t = 19200; pub const B38400: speed_t = 38400; pub const B7200: speed_t = 7200; pub const B14400: speed_t = 14400; pub const B28800: speed_t = 28800; pub const B57600: speed_t = 57600; pub const B76800: speed_t = 76800; pub const B115200: speed_t = 115200; pub const B230400: speed_t = 230400; pub const EXTA: speed_t = 19200; pub const EXTB: speed_t = 38400; pub const SIGTRAP: ::c_int = 5; pub const GLOB_APPEND: ::c_int = 0x0001; pub const GLOB_DOOFFS: ::c_int = 0x0002; pub const GLOB_ERR: ::c_int = 0x0004; pub const GLOB_MARK: ::c_int = 0x0008; pub const GLOB_NOCHECK: ::c_int = 0x0010; pub const GLOB_NOSORT: ::c_int = 0x0020; pub const GLOB_NOESCAPE: ::c_int = 0x2000; pub const GLOB_NOSPACE: ::c_int = -1; pub const GLOB_ABORTED: ::c_int = -2; pub const GLOB_NOMATCH: ::c_int = -3; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const _SC_IOV_MAX: ::c_int = 56; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 70; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 71; pub const _SC_LOGIN_NAME_MAX: ::c_int = 73; pub const _SC_MQ_PRIO_MAX: ::c_int = 75; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 82; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 83; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 85; pub const _SC_THREAD_KEYS_MAX: ::c_int = 86; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 87; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 88; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 89; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 90; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 91; pub const _SC_THREAD_STACK_MIN: ::c_int = 93; pub const _SC_THREAD_THREADS_MAX: ::c_int = 94; pub const _SC_THREADS: ::c_int = 96; pub const _SC_TTY_NAME_MAX: ::c_int = 101; pub const _SC_ATEXIT_MAX: ::c_int = 107; pub const _SC_XOPEN_CRYPT: ::c_int = 108; pub const _SC_XOPEN_ENH_I18N: ::c_int = 109; pub const _SC_XOPEN_LEGACY: ::c_int = 110; pub const _SC_XOPEN_REALTIME: ::c_int = 111; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 112; pub const _SC_XOPEN_SHM: ::c_int = 113; pub const _SC_XOPEN_UNIX: ::c_int = 115; pub const _SC_XOPEN_VERSION: ::c_int = 116; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 121; pub const _SC_PHYS_PAGES: ::c_int = 200; pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 2; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 1; pub const PTHREAD_CREATE_DETACHED: ::c_int = 2; #[cfg(target_arch = "aarch64")] pub const PTHREAD_STACK_MIN: ::size_t = 16384; #[cfg(not(target_arch = "aarch64"))] pub const PTHREAD_STACK_MIN: ::size_t = 8192; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_AS: ::c_int = 5; pub const RLIMIT_RSS: ::c_int = RLIMIT_AS; pub const RLIMIT_MEMLOCK: ::c_int = 6; pub const RLIMIT_NPROC: ::c_int = 7; pub const RLIMIT_NOFILE: ::c_int = 8; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::c_int = 9; pub const _RLIMIT_POSIX_FLAG: ::c_int = 0x1000; pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; pub const RUSAGE_SELF: ::c_int = 0; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const MADV_FREE: ::c_int = 5; pub const MADV_ZERO_WIRED_PAGES: ::c_int = 6; pub const MADV_FREE_REUSABLE: ::c_int = 7; pub const MADV_FREE_REUSE: ::c_int = 8; pub const MADV_CAN_REUSE: ::c_int = 9; pub const MINCORE_INCORE: ::c_int = 0x1; pub const MINCORE_REFERENCED: ::c_int = 0x2; pub const MINCORE_MODIFIED: ::c_int = 0x4; pub const MINCORE_REFERENCED_OTHER: ::c_int = 0x8; pub const MINCORE_MODIFIED_OTHER: ::c_int = 0x10; pub const CTLIOCGINFO: c_ulong = 0xc0644e03; // // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// IP6 hop-by-hop options pub const IPPROTO_HOPOPTS: ::c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: ::c_int = 2; /// gateway2 (deprecated) pub const IPPROTO_GGP: ::c_int = 3; /// for compatibility pub const IPPROTO_IPIP: ::c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// Stream protocol II. pub const IPPROTO_ST: ::c_int = 7; /// exterior gateway protocol pub const IPPROTO_EGP: ::c_int = 8; /// private interior gateway pub const IPPROTO_PIGP: ::c_int = 9; /// BBN RCC Monitoring pub const IPPROTO_RCCMON: ::c_int = 10; /// network voice protocol pub const IPPROTO_NVPII: ::c_int = 11; /// pup pub const IPPROTO_PUP: ::c_int = 12; /// Argus pub const IPPROTO_ARGUS: ::c_int = 13; /// EMCON pub const IPPROTO_EMCON: ::c_int = 14; /// Cross Net Debugger pub const IPPROTO_XNET: ::c_int = 15; /// Chaos pub const IPPROTO_CHAOS: ::c_int = 16; // IPPROTO_UDP defined in src/unix/mod.rs /// Multiplexing pub const IPPROTO_MUX: ::c_int = 18; /// DCN Measurement Subsystems pub const IPPROTO_MEAS: ::c_int = 19; /// Host Monitoring pub const IPPROTO_HMP: ::c_int = 20; /// Packet Radio Measurement pub const IPPROTO_PRM: ::c_int = 21; /// xns idp pub const IPPROTO_IDP: ::c_int = 22; /// Trunk-1 pub const IPPROTO_TRUNK1: ::c_int = 23; /// Trunk-2 pub const IPPROTO_TRUNK2: ::c_int = 24; /// Leaf-1 pub const IPPROTO_LEAF1: ::c_int = 25; /// Leaf-2 pub const IPPROTO_LEAF2: ::c_int = 26; /// Reliable Data pub const IPPROTO_RDP: ::c_int = 27; /// Reliable Transaction pub const IPPROTO_IRTP: ::c_int = 28; /// tp-4 w/ class negotiation pub const IPPROTO_TP: ::c_int = 29; /// Bulk Data Transfer pub const IPPROTO_BLT: ::c_int = 30; /// Network Services pub const IPPROTO_NSP: ::c_int = 31; /// Merit Internodal pub const IPPROTO_INP: ::c_int = 32; /// Sequential Exchange pub const IPPROTO_SEP: ::c_int = 33; /// Third Party Connect pub const IPPROTO_3PC: ::c_int = 34; /// InterDomain Policy Routing pub const IPPROTO_IDPR: ::c_int = 35; /// XTP pub const IPPROTO_XTP: ::c_int = 36; /// Datagram Delivery pub const IPPROTO_DDP: ::c_int = 37; /// Control Message Transport pub const IPPROTO_CMTP: ::c_int = 38; /// TP++ Transport pub const IPPROTO_TPXX: ::c_int = 39; /// IL transport protocol pub const IPPROTO_IL: ::c_int = 40; // IPPROTO_IPV6 defined in src/unix/mod.rs /// Source Demand Routing pub const IPPROTO_SDRP: ::c_int = 42; /// IP6 routing header pub const IPPROTO_ROUTING: ::c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: ::c_int = 44; /// InterDomain Routing pub const IPPROTO_IDRP: ::c_int = 45; /// resource reservation pub const IPPROTO_RSVP: ::c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: ::c_int = 47; /// Mobile Host Routing pub const IPPROTO_MHRP: ::c_int = 48; /// BHA pub const IPPROTO_BHA: ::c_int = 49; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: ::c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: ::c_int = 51; /// Integ. Net Layer Security pub const IPPROTO_INLSP: ::c_int = 52; /// IP with encryption pub const IPPROTO_SWIPE: ::c_int = 53; /// Next Hop Resolution pub const IPPROTO_NHRP: ::c_int = 54; /* 55-57: Unassigned */ // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: ::c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: ::c_int = 60; /// any host internal protocol pub const IPPROTO_AHIP: ::c_int = 61; /// CFTP pub const IPPROTO_CFTP: ::c_int = 62; /// "hello" routing protocol pub const IPPROTO_HELLO: ::c_int = 63; /// SATNET/Backroom EXPAK pub const IPPROTO_SATEXPAK: ::c_int = 64; /// Kryptolan pub const IPPROTO_KRYPTOLAN: ::c_int = 65; /// Remote Virtual Disk pub const IPPROTO_RVD: ::c_int = 66; /// Pluribus Packet Core pub const IPPROTO_IPPC: ::c_int = 67; /// Any distributed FS pub const IPPROTO_ADFS: ::c_int = 68; /// Satnet Monitoring pub const IPPROTO_SATMON: ::c_int = 69; /// VISA Protocol pub const IPPROTO_VISA: ::c_int = 70; /// Packet Core Utility pub const IPPROTO_IPCV: ::c_int = 71; /// Comp. Prot. Net. Executive pub const IPPROTO_CPNX: ::c_int = 72; /// Comp. Prot. HeartBeat pub const IPPROTO_CPHB: ::c_int = 73; /// Wang Span Network pub const IPPROTO_WSN: ::c_int = 74; /// Packet Video Protocol pub const IPPROTO_PVP: ::c_int = 75; /// BackRoom SATNET Monitoring pub const IPPROTO_BRSATMON: ::c_int = 76; /// Sun net disk proto (temp.) pub const IPPROTO_ND: ::c_int = 77; /// WIDEBAND Monitoring pub const IPPROTO_WBMON: ::c_int = 78; /// WIDEBAND EXPAK pub const IPPROTO_WBEXPAK: ::c_int = 79; /// ISO cnlp pub const IPPROTO_EON: ::c_int = 80; /// VMTP pub const IPPROTO_VMTP: ::c_int = 81; /// Secure VMTP pub const IPPROTO_SVMTP: ::c_int = 82; /// Banyon VINES pub const IPPROTO_VINES: ::c_int = 83; /// TTP pub const IPPROTO_TTP: ::c_int = 84; /// NSFNET-IGP pub const IPPROTO_IGP: ::c_int = 85; /// dissimilar gateway prot. pub const IPPROTO_DGP: ::c_int = 86; /// TCF pub const IPPROTO_TCF: ::c_int = 87; /// Cisco/GXS IGRP pub const IPPROTO_IGRP: ::c_int = 88; /// OSPFIGP pub const IPPROTO_OSPFIGP: ::c_int = 89; /// Strite RPC protocol pub const IPPROTO_SRPC: ::c_int = 90; /// Locus Address Resoloution pub const IPPROTO_LARP: ::c_int = 91; /// Multicast Transport pub const IPPROTO_MTP: ::c_int = 92; /// AX.25 Frames pub const IPPROTO_AX25: ::c_int = 93; /// IP encapsulated in IP pub const IPPROTO_IPEIP: ::c_int = 94; /// Mobile Int.ing control pub const IPPROTO_MICP: ::c_int = 95; /// Semaphore Comm. security pub const IPPROTO_SCCSP: ::c_int = 96; /// Ethernet IP encapsulation pub const IPPROTO_ETHERIP: ::c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: ::c_int = 98; /// any private encr. scheme pub const IPPROTO_APES: ::c_int = 99; /// GMTP pub const IPPROTO_GMTP: ::c_int = 100; /* 101-254: Partly Unassigned */ /// Protocol Independent Mcast pub const IPPROTO_PIM: ::c_int = 103; /// payload compression (IPComp) pub const IPPROTO_IPCOMP: ::c_int = 108; /// PGM pub const IPPROTO_PGM: ::c_int = 113; /// SCTP pub const IPPROTO_SCTP: ::c_int = 132; /* 255: Reserved */ /* BSD Private, local use, namespace incursion */ /// divert pseudo-protocol pub const IPPROTO_DIVERT: ::c_int = 254; /// raw IP packet pub const IPPROTO_RAW: ::c_int = 255; pub const IPPROTO_MAX: ::c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: ::c_int = 257; pub const AF_UNSPEC: ::c_int = 0; pub const AF_LOCAL: ::c_int = 1; pub const AF_UNIX: ::c_int = AF_LOCAL; pub const AF_INET: ::c_int = 2; pub const AF_IMPLINK: ::c_int = 3; pub const AF_PUP: ::c_int = 4; pub const AF_CHAOS: ::c_int = 5; pub const AF_NS: ::c_int = 6; pub const AF_ISO: ::c_int = 7; pub const AF_OSI: ::c_int = AF_ISO; pub const AF_ECMA: ::c_int = 8; pub const AF_DATAKIT: ::c_int = 9; pub const AF_CCITT: ::c_int = 10; pub const AF_SNA: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_DLI: ::c_int = 13; pub const AF_LAT: ::c_int = 14; pub const AF_HYLINK: ::c_int = 15; pub const AF_APPLETALK: ::c_int = 16; pub const AF_ROUTE: ::c_int = 17; pub const AF_LINK: ::c_int = 18; pub const pseudo_AF_XTP: ::c_int = 19; pub const AF_COIP: ::c_int = 20; pub const AF_CNT: ::c_int = 21; pub const pseudo_AF_RTIP: ::c_int = 22; pub const AF_IPX: ::c_int = 23; pub const AF_SIP: ::c_int = 24; pub const pseudo_AF_PIP: ::c_int = 25; pub const AF_NDRV: ::c_int = 27; pub const AF_ISDN: ::c_int = 28; pub const AF_E164: ::c_int = AF_ISDN; pub const pseudo_AF_KEY: ::c_int = 29; pub const AF_INET6: ::c_int = 30; pub const AF_NATM: ::c_int = 31; pub const AF_SYSTEM: ::c_int = 32; pub const AF_NETBIOS: ::c_int = 33; pub const AF_PPP: ::c_int = 34; pub const pseudo_AF_HDRCMPLT: ::c_int = 35; pub const AF_IEEE80211: ::c_int = 37; pub const AF_UTUN: ::c_int = 38; pub const AF_VSOCK: ::c_int = 40; pub const AF_SYS_CONTROL: ::c_int = 2; pub const SYSPROTO_EVENT: ::c_int = 1; pub const SYSPROTO_CONTROL: ::c_int = 2; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_LOCAL: ::c_int = AF_LOCAL; pub const PF_UNIX: ::c_int = PF_LOCAL; pub const PF_INET: ::c_int = AF_INET; pub const PF_IMPLINK: ::c_int = AF_IMPLINK; pub const PF_PUP: ::c_int = AF_PUP; pub const PF_CHAOS: ::c_int = AF_CHAOS; pub const PF_NS: ::c_int = AF_NS; pub const PF_ISO: ::c_int = AF_ISO; pub const PF_OSI: ::c_int = AF_ISO; pub const PF_ECMA: ::c_int = AF_ECMA; pub const PF_DATAKIT: ::c_int = AF_DATAKIT; pub const PF_CCITT: ::c_int = AF_CCITT; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_DECnet: ::c_int = AF_DECnet; pub const PF_DLI: ::c_int = AF_DLI; pub const PF_LAT: ::c_int = AF_LAT; pub const PF_HYLINK: ::c_int = AF_HYLINK; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_LINK: ::c_int = AF_LINK; pub const PF_XTP: ::c_int = pseudo_AF_XTP; pub const PF_COIP: ::c_int = AF_COIP; pub const PF_CNT: ::c_int = AF_CNT; pub const PF_SIP: ::c_int = AF_SIP; pub const PF_IPX: ::c_int = AF_IPX; pub const PF_RTIP: ::c_int = pseudo_AF_RTIP; pub const PF_PIP: ::c_int = pseudo_AF_PIP; pub const PF_NDRV: ::c_int = AF_NDRV; pub const PF_ISDN: ::c_int = AF_ISDN; pub const PF_KEY: ::c_int = pseudo_AF_KEY; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_NATM: ::c_int = AF_NATM; pub const PF_SYSTEM: ::c_int = AF_SYSTEM; pub const PF_NETBIOS: ::c_int = AF_NETBIOS; pub const PF_PPP: ::c_int = AF_PPP; pub const PF_VSOCK: ::c_int = AF_VSOCK; pub const NET_RT_DUMP: ::c_int = 1; pub const NET_RT_FLAGS: ::c_int = 2; pub const NET_RT_IFLIST: ::c_int = 3; pub const SOMAXCONN: ::c_int = 128; pub const SOCK_MAXADDRLEN: ::c_int = 255; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const IP_TTL: ::c_int = 4; pub const IP_HDRINCL: ::c_int = 2; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; pub const IP_RECVIF: ::c_int = 20; pub const IP_RECVTTL: ::c_int = 24; pub const IP_BOUND_IF: ::c_int = 25; pub const IP_PKTINFO: ::c_int = 26; pub const IP_RECVTOS: ::c_int = 27; pub const IP_DONTFRAG: ::c_int = 28; pub const IPV6_JOIN_GROUP: ::c_int = 12; pub const IPV6_LEAVE_GROUP: ::c_int = 13; pub const IPV6_CHECKSUM: ::c_int = 26; pub const IPV6_RECVTCLASS: ::c_int = 35; pub const IPV6_TCLASS: ::c_int = 36; pub const IPV6_RECVHOPLIMIT: ::c_int = 37; pub const IPV6_PKTINFO: ::c_int = 46; pub const IPV6_HOPLIMIT: ::c_int = 47; pub const IPV6_RECVPKTINFO: ::c_int = 61; pub const IPV6_DONTFRAG: ::c_int = 62; pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 70; pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 71; pub const IP_BLOCK_SOURCE: ::c_int = 72; pub const IP_UNBLOCK_SOURCE: ::c_int = 73; pub const IPV6_BOUND_IF: ::c_int = 125; pub const TCP_NOPUSH: ::c_int = 4; pub const TCP_NOOPT: ::c_int = 8; pub const TCP_KEEPALIVE: ::c_int = 0x10; pub const TCP_KEEPINTVL: ::c_int = 0x101; pub const TCP_KEEPCNT: ::c_int = 0x102; /// Enable/Disable TCP Fastopen on this socket pub const TCP_FASTOPEN: ::c_int = 0x105; pub const TCP_CONNECTION_INFO: ::c_int = 0x106; pub const SOL_LOCAL: ::c_int = 0; pub const LOCAL_PEERCRED: ::c_int = 0x001; pub const LOCAL_PEERPID: ::c_int = 0x002; pub const LOCAL_PEEREPID: ::c_int = 0x003; pub const LOCAL_PEERUUID: ::c_int = 0x004; pub const LOCAL_PEEREUUID: ::c_int = 0x005; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x01; pub const SO_ACCEPTCONN: ::c_int = 0x0002; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_TIMESTAMP: ::c_int = 0x0400; pub const SO_TIMESTAMP_MONOTONIC: ::c_int = 0x0800; pub const SO_DONTTRUNC: ::c_int = 0x2000; pub const SO_WANTMORE: ::c_int = 0x4000; pub const SO_WANTOOBFLAG: ::c_int = 0x8000; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVLOWAT: ::c_int = 0x1004; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; pub const SO_LABEL: ::c_int = 0x1010; pub const SO_PEERLABEL: ::c_int = 0x1011; pub const SO_NREAD: ::c_int = 0x1020; pub const SO_NKE: ::c_int = 0x1021; pub const SO_NOSIGPIPE: ::c_int = 0x1022; pub const SO_NOADDRERR: ::c_int = 0x1023; pub const SO_NWRITE: ::c_int = 0x1024; pub const SO_REUSESHAREUID: ::c_int = 0x1025; pub const SO_NOTIFYCONFLICT: ::c_int = 0x1026; pub const SO_LINGER_SEC: ::c_int = 0x1080; pub const SO_RANDOMPORT: ::c_int = 0x1082; pub const SO_NP_EXTENSIONS: ::c_int = 0x1083; pub const MSG_OOB: ::c_int = 0x1; pub const MSG_PEEK: ::c_int = 0x2; pub const MSG_DONTROUTE: ::c_int = 0x4; pub const MSG_EOR: ::c_int = 0x8; pub const MSG_TRUNC: ::c_int = 0x10; pub const MSG_CTRUNC: ::c_int = 0x20; pub const MSG_WAITALL: ::c_int = 0x40; pub const MSG_DONTWAIT: ::c_int = 0x80; pub const MSG_EOF: ::c_int = 0x100; pub const MSG_FLUSH: ::c_int = 0x400; pub const MSG_HOLD: ::c_int = 0x800; pub const MSG_SEND: ::c_int = 0x1000; pub const MSG_HAVEMORE: ::c_int = 0x2000; pub const MSG_RCVMORE: ::c_int = 0x4000; pub const MSG_NEEDSA: ::c_int = 0x10000; pub const MSG_NOSIGNAL: ::c_int = 0x80000; pub const SCM_TIMESTAMP: ::c_int = 0x02; pub const SCM_CREDS: ::c_int = 0x03; // https://github.com/aosm/xnu/blob/HEAD/bsd/net/if.h#L140-L156 pub const IFF_UP: ::c_int = 0x1; // interface is up pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link pub const IFF_NOTRAILERS: ::c_int = 0x20; // obsolete: avoid use of trailers pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE: ::c_int = 0x400; // transmission in progress pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit pub const IFF_ALTPHYS: ::c_int = IFF_LINK2; // use alternate physical connection pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const SAE_ASSOCID_ANY: ::sae_associd_t = 0; /// ((sae_associd_t)(-1ULL)) pub const SAE_ASSOCID_ALL: ::sae_associd_t = 0xffffffff; pub const SAE_CONNID_ANY: ::sae_connid_t = 0; /// ((sae_connid_t)(-1ULL)) pub const SAE_CONNID_ALL: ::sae_connid_t = 0xffffffff; // connectx() flag parameters /// resume connect() on read/write pub const CONNECT_RESUME_ON_READ_WRITE: ::c_uint = 0x1; /// data is idempotent pub const CONNECT_DATA_IDEMPOTENT: ::c_uint = 0x2; /// data includes security that replaces the TFO-cookie pub const CONNECT_DATA_AUTHENTICATED: ::c_uint = 0x4; pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; pub const MAP_COPY: ::c_int = 0x0002; pub const MAP_RENAME: ::c_int = 0x0020; pub const MAP_NORESERVE: ::c_int = 0x0040; pub const MAP_NOEXTEND: ::c_int = 0x0100; pub const MAP_HASSEMAPHORE: ::c_int = 0x0200; pub const MAP_NOCACHE: ::c_int = 0x0400; pub const MAP_JIT: ::c_int = 0x0800; pub const _SC_ARG_MAX: ::c_int = 1; pub const _SC_CHILD_MAX: ::c_int = 2; pub const _SC_CLK_TCK: ::c_int = 3; pub const _SC_NGROUPS_MAX: ::c_int = 4; pub const _SC_OPEN_MAX: ::c_int = 5; pub const _SC_JOB_CONTROL: ::c_int = 6; pub const _SC_SAVED_IDS: ::c_int = 7; pub const _SC_VERSION: ::c_int = 8; pub const _SC_BC_BASE_MAX: ::c_int = 9; pub const _SC_BC_DIM_MAX: ::c_int = 10; pub const _SC_BC_SCALE_MAX: ::c_int = 11; pub const _SC_BC_STRING_MAX: ::c_int = 12; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 13; pub const _SC_EXPR_NEST_MAX: ::c_int = 14; pub const _SC_LINE_MAX: ::c_int = 15; pub const _SC_RE_DUP_MAX: ::c_int = 16; pub const _SC_2_VERSION: ::c_int = 17; pub const _SC_2_C_BIND: ::c_int = 18; pub const _SC_2_C_DEV: ::c_int = 19; pub const _SC_2_CHAR_TERM: ::c_int = 20; pub const _SC_2_FORT_DEV: ::c_int = 21; pub const _SC_2_FORT_RUN: ::c_int = 22; pub const _SC_2_LOCALEDEF: ::c_int = 23; pub const _SC_2_SW_DEV: ::c_int = 24; pub const _SC_2_UPE: ::c_int = 25; pub const _SC_STREAM_MAX: ::c_int = 26; pub const _SC_TZNAME_MAX: ::c_int = 27; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 28; pub const _SC_PAGESIZE: ::c_int = 29; pub const _SC_MEMLOCK: ::c_int = 30; pub const _SC_MEMLOCK_RANGE: ::c_int = 31; pub const _SC_MEMORY_PROTECTION: ::c_int = 32; pub const _SC_MESSAGE_PASSING: ::c_int = 33; pub const _SC_PRIORITIZED_IO: ::c_int = 34; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 35; pub const _SC_REALTIME_SIGNALS: ::c_int = 36; pub const _SC_SEMAPHORES: ::c_int = 37; pub const _SC_FSYNC: ::c_int = 38; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 39; pub const _SC_SYNCHRONIZED_IO: ::c_int = 40; pub const _SC_TIMERS: ::c_int = 41; pub const _SC_AIO_LISTIO_MAX: ::c_int = 42; pub const _SC_AIO_MAX: ::c_int = 43; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 44; pub const _SC_DELAYTIMER_MAX: ::c_int = 45; pub const _SC_MQ_OPEN_MAX: ::c_int = 46; pub const _SC_MAPPED_FILES: ::c_int = 47; pub const _SC_RTSIG_MAX: ::c_int = 48; pub const _SC_SEM_NSEMS_MAX: ::c_int = 49; pub const _SC_SEM_VALUE_MAX: ::c_int = 50; pub const _SC_SIGQUEUE_MAX: ::c_int = 51; pub const _SC_TIMER_MAX: ::c_int = 52; pub const _SC_NPROCESSORS_CONF: ::c_int = 57; pub const _SC_NPROCESSORS_ONLN: ::c_int = 58; pub const _SC_2_PBS: ::c_int = 59; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 60; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 61; pub const _SC_2_PBS_LOCATE: ::c_int = 62; pub const _SC_2_PBS_MESSAGE: ::c_int = 63; pub const _SC_2_PBS_TRACK: ::c_int = 64; pub const _SC_ADVISORY_INFO: ::c_int = 65; pub const _SC_BARRIERS: ::c_int = 66; pub const _SC_CLOCK_SELECTION: ::c_int = 67; pub const _SC_CPUTIME: ::c_int = 68; pub const _SC_FILE_LOCKING: ::c_int = 69; pub const _SC_HOST_NAME_MAX: ::c_int = 72; pub const _SC_MONOTONIC_CLOCK: ::c_int = 74; pub const _SC_READER_WRITER_LOCKS: ::c_int = 76; pub const _SC_REGEXP: ::c_int = 77; pub const _SC_SHELL: ::c_int = 78; pub const _SC_SPAWN: ::c_int = 79; pub const _SC_SPIN_LOCKS: ::c_int = 80; pub const _SC_SPORADIC_SERVER: ::c_int = 81; pub const _SC_THREAD_CPUTIME: ::c_int = 84; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 92; pub const _SC_TIMEOUTS: ::c_int = 95; pub const _SC_TRACE: ::c_int = 97; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 98; pub const _SC_TRACE_INHERIT: ::c_int = 99; pub const _SC_TRACE_LOG: ::c_int = 100; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 102; pub const _SC_V6_ILP32_OFF32: ::c_int = 103; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 104; pub const _SC_V6_LP64_OFF64: ::c_int = 105; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 106; pub const _SC_IPV6: ::c_int = 118; pub const _SC_RAW_SOCKETS: ::c_int = 119; pub const _SC_SYMLOOP_MAX: ::c_int = 120; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_XOPEN_STREAMS: ::c_int = 114; pub const _SC_XBS5_ILP32_OFF32: ::c_int = 122; pub const _SC_XBS5_ILP32_OFFBIG: ::c_int = 123; pub const _SC_XBS5_LP64_OFF64: ::c_int = 124; pub const _SC_XBS5_LPBIG_OFFBIG: ::c_int = 125; pub const _SC_SS_REPL_MAX: ::c_int = 126; pub const _SC_TRACE_EVENT_NAME_MAX: ::c_int = 127; pub const _SC_TRACE_NAME_MAX: ::c_int = 128; pub const _SC_TRACE_SYS_MAX: ::c_int = 129; pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 130; pub const _SC_PASS_MAX: ::c_int = 131; // `confstr` keys (only the values guaranteed by `man confstr`). pub const _CS_PATH: ::c_int = 1; pub const _CS_DARWIN_USER_DIR: ::c_int = 65536; pub const _CS_DARWIN_USER_TEMP_DIR: ::c_int = 65537; pub const _CS_DARWIN_USER_CACHE_DIR: ::c_int = 65538; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const _PTHREAD_MUTEX_SIG_init: ::c_long = 0x32AAABA7; pub const _PTHREAD_COND_SIG_init: ::c_long = 0x3CB0B1BB; pub const _PTHREAD_RWLOCK_SIG_init: ::c_long = 0x2DA8B3B4; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __sig: _PTHREAD_MUTEX_SIG_init, __opaque: [0; __PTHREAD_MUTEX_SIZE__], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __sig: _PTHREAD_COND_SIG_init, __opaque: [0; __PTHREAD_COND_SIZE__], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __sig: _PTHREAD_RWLOCK_SIG_init, __opaque: [0; __PTHREAD_RWLOCK_SIZE__], }; pub const OS_UNFAIR_LOCK_INIT: os_unfair_lock = os_unfair_lock { _os_unfair_lock_opaque: 0, }; pub const OS_LOG_TYPE_DEFAULT: ::os_log_type_t = 0x00; pub const OS_LOG_TYPE_INFO: ::os_log_type_t = 0x01; pub const OS_LOG_TYPE_DEBUG: ::os_log_type_t = 0x02; pub const OS_LOG_TYPE_ERROR: ::os_log_type_t = 0x10; pub const OS_LOG_TYPE_FAULT: ::os_log_type_t = 0x11; pub const OS_SIGNPOST_EVENT: ::os_signpost_type_t = 0x00; pub const OS_SIGNPOST_INTERVAL_BEGIN: ::os_signpost_type_t = 0x01; pub const OS_SIGNPOST_INTERVAL_END: ::os_signpost_type_t = 0x02; pub const MINSIGSTKSZ: ::size_t = 32768; pub const SIGSTKSZ: ::size_t = 131072; pub const FD_SETSIZE: usize = 1024; pub const ST_NOSUID: ::c_ulong = 2; pub const SCHED_OTHER: ::c_int = 1; pub const SCHED_FIFO: ::c_int = 4; pub const SCHED_RR: ::c_int = 2; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_MACHPORT: i16 = -8; pub const EVFILT_FS: i16 = -9; pub const EVFILT_USER: i16 = -10; pub const EVFILT_VM: i16 = -12; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_FLAG0: u16 = 0x1000; pub const EV_POLL: u16 = 0x1000; pub const EV_FLAG1: u16 = 0x2000; pub const EV_OOBAND: u16 = 0x2000; pub const EV_ERROR: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; pub const EV_SYSFLAGS: u16 = 0xf000; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_NONE: u32 = 0x00000080; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated since MacOSX 10.9")] pub const NOTE_REAP: u32 = 0x10000000; pub const NOTE_SIGNAL: u32 = 0x08000000; pub const NOTE_EXITSTATUS: u32 = 0x04000000; pub const NOTE_EXIT_DETAIL: u32 = 0x02000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xfff00000; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated since MacOSX 10.9")] pub const NOTE_EXIT_REPARENTED: u32 = 0x00080000; pub const NOTE_EXIT_DETAIL_MASK: u32 = 0x00070000; pub const NOTE_EXIT_DECRYPTFAIL: u32 = 0x00010000; pub const NOTE_EXIT_MEMORY: u32 = 0x00020000; pub const NOTE_EXIT_CSERROR: u32 = 0x00040000; pub const NOTE_VM_PRESSURE: u32 = 0x80000000; pub const NOTE_VM_PRESSURE_TERMINATE: u32 = 0x40000000; pub const NOTE_VM_PRESSURE_SUDDEN_TERMINATE: u32 = 0x20000000; pub const NOTE_VM_ERROR: u32 = 0x10000000; pub const NOTE_SECONDS: u32 = 0x00000001; pub const NOTE_USECONDS: u32 = 0x00000002; pub const NOTE_NSECONDS: u32 = 0x00000004; pub const NOTE_ABSOLUTE: u32 = 0x00000008; pub const NOTE_LEEWAY: u32 = 0x00000010; pub const NOTE_CRITICAL: u32 = 0x00000020; pub const NOTE_BACKGROUND: u32 = 0x00000040; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const OCRNL: ::tcflag_t = 0x00000010; pub const ONOCR: ::tcflag_t = 0x00000020; pub const ONLRET: ::tcflag_t = 0x00000040; pub const OFILL: ::tcflag_t = 0x00000080; pub const NLDLY: ::tcflag_t = 0x00000300; pub const TABDLY: ::tcflag_t = 0x00000c04; pub const CRDLY: ::tcflag_t = 0x00003000; pub const FFDLY: ::tcflag_t = 0x00004000; pub const BSDLY: ::tcflag_t = 0x00008000; pub const VTDLY: ::tcflag_t = 0x00010000; pub const OFDEL: ::tcflag_t = 0x00020000; pub const NL0: ::tcflag_t = 0x00000000; pub const NL1: ::tcflag_t = 0x00000100; pub const TAB0: ::tcflag_t = 0x00000000; pub const TAB1: ::tcflag_t = 0x00000400; pub const TAB2: ::tcflag_t = 0x00000800; pub const CR0: ::tcflag_t = 0x00000000; pub const CR1: ::tcflag_t = 0x00001000; pub const CR2: ::tcflag_t = 0x00002000; pub const CR3: ::tcflag_t = 0x00003000; pub const FF0: ::tcflag_t = 0x00000000; pub const FF1: ::tcflag_t = 0x00004000; pub const BS0: ::tcflag_t = 0x00000000; pub const BS1: ::tcflag_t = 0x00008000; pub const TAB3: ::tcflag_t = 0x00000004; pub const VT0: ::tcflag_t = 0x00000000; pub const VT1: ::tcflag_t = 0x00010000; pub const IUTF8: ::tcflag_t = 0x00004000; pub const CRTSCTS: ::tcflag_t = 0x00030000; pub const NI_MAXHOST: ::socklen_t = 1025; pub const NI_MAXSERV: ::socklen_t = 32; pub const NI_NOFQDN: ::c_int = 0x00000001; pub const NI_NUMERICHOST: ::c_int = 0x00000002; pub const NI_NAMEREQD: ::c_int = 0x00000004; pub const NI_NUMERICSERV: ::c_int = 0x00000008; pub const NI_NUMERICSCOPE: ::c_int = 0x00000100; pub const NI_DGRAM: ::c_int = 0x00000010; pub const Q_GETQUOTA: ::c_int = 0x300; pub const Q_SETQUOTA: ::c_int = 0x400; pub const RENAME_SWAP: ::c_uint = 0x00000002; pub const RENAME_EXCL: ::c_uint = 0x00000004; pub const RTLD_LOCAL: ::c_int = 0x4; pub const RTLD_FIRST: ::c_int = 0x100; pub const RTLD_NODELETE: ::c_int = 0x80; pub const RTLD_NOLOAD: ::c_int = 0x10; pub const RTLD_GLOBAL: ::c_int = 0x8; pub const RTLD_MAIN_ONLY: *mut ::c_void = -5isize as *mut ::c_void; pub const _WSTOPPED: ::c_int = 0o177; pub const LOG_NETINFO: ::c_int = 12 << 3; pub const LOG_REMOTEAUTH: ::c_int = 13 << 3; pub const LOG_INSTALL: ::c_int = 14 << 3; pub const LOG_RAS: ::c_int = 15 << 3; pub const LOG_LAUNCHD: ::c_int = 24 << 3; pub const LOG_NFACILITIES: ::c_int = 25; pub const CTLTYPE: ::c_int = 0xf; pub const CTLTYPE_NODE: ::c_int = 1; pub const CTLTYPE_INT: ::c_int = 2; pub const CTLTYPE_STRING: ::c_int = 3; pub const CTLTYPE_QUAD: ::c_int = 4; pub const CTLTYPE_OPAQUE: ::c_int = 5; pub const CTLTYPE_STRUCT: ::c_int = CTLTYPE_OPAQUE; pub const CTLFLAG_RD: ::c_int = 0x80000000; pub const CTLFLAG_WR: ::c_int = 0x40000000; pub const CTLFLAG_RW: ::c_int = CTLFLAG_RD | CTLFLAG_WR; pub const CTLFLAG_NOLOCK: ::c_int = 0x20000000; pub const CTLFLAG_ANYBODY: ::c_int = 0x10000000; pub const CTLFLAG_SECURE: ::c_int = 0x08000000; pub const CTLFLAG_MASKED: ::c_int = 0x04000000; pub const CTLFLAG_NOAUTO: ::c_int = 0x02000000; pub const CTLFLAG_KERN: ::c_int = 0x01000000; pub const CTLFLAG_LOCKED: ::c_int = 0x00800000; pub const CTLFLAG_OID2: ::c_int = 0x00400000; pub const CTL_UNSPEC: ::c_int = 0; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_VFS: ::c_int = 3; pub const CTL_NET: ::c_int = 4; pub const CTL_DEBUG: ::c_int = 5; pub const CTL_HW: ::c_int = 6; pub const CTL_MACHDEP: ::c_int = 7; pub const CTL_USER: ::c_int = 8; pub const CTL_MAXID: ::c_int = 9; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_VERSION: ::c_int = 4; pub const KERN_MAXVNODES: ::c_int = 5; pub const KERN_MAXPROC: ::c_int = 6; pub const KERN_MAXFILES: ::c_int = 7; pub const KERN_ARGMAX: ::c_int = 8; pub const KERN_SECURELVL: ::c_int = 9; pub const KERN_HOSTNAME: ::c_int = 10; pub const KERN_HOSTID: ::c_int = 11; pub const KERN_CLOCKRATE: ::c_int = 12; pub const KERN_VNODE: ::c_int = 13; pub const KERN_PROC: ::c_int = 14; pub const KERN_FILE: ::c_int = 15; pub const KERN_PROF: ::c_int = 16; pub const KERN_POSIX1: ::c_int = 17; pub const KERN_NGROUPS: ::c_int = 18; pub const KERN_JOB_CONTROL: ::c_int = 19; pub const KERN_SAVED_IDS: ::c_int = 20; pub const KERN_BOOTTIME: ::c_int = 21; pub const KERN_NISDOMAINNAME: ::c_int = 22; pub const KERN_DOMAINNAME: ::c_int = KERN_NISDOMAINNAME; pub const KERN_MAXPARTITIONS: ::c_int = 23; pub const KERN_KDEBUG: ::c_int = 24; pub const KERN_UPDATEINTERVAL: ::c_int = 25; pub const KERN_OSRELDATE: ::c_int = 26; pub const KERN_NTP_PLL: ::c_int = 27; pub const KERN_BOOTFILE: ::c_int = 28; pub const KERN_MAXFILESPERPROC: ::c_int = 29; pub const KERN_MAXPROCPERUID: ::c_int = 30; pub const KERN_DUMPDEV: ::c_int = 31; pub const KERN_IPC: ::c_int = 32; pub const KERN_DUMMY: ::c_int = 33; pub const KERN_PS_STRINGS: ::c_int = 34; pub const KERN_USRSTACK32: ::c_int = 35; pub const KERN_LOGSIGEXIT: ::c_int = 36; pub const KERN_SYMFILE: ::c_int = 37; pub const KERN_PROCARGS: ::c_int = 38; pub const KERN_NETBOOT: ::c_int = 40; pub const KERN_SYSV: ::c_int = 42; pub const KERN_AFFINITY: ::c_int = 43; pub const KERN_TRANSLATE: ::c_int = 44; pub const KERN_CLASSIC: ::c_int = KERN_TRANSLATE; pub const KERN_EXEC: ::c_int = 45; pub const KERN_CLASSICHANDLER: ::c_int = KERN_EXEC; pub const KERN_AIOMAX: ::c_int = 46; pub const KERN_AIOPROCMAX: ::c_int = 47; pub const KERN_AIOTHREADS: ::c_int = 48; pub const KERN_COREFILE: ::c_int = 50; pub const KERN_COREDUMP: ::c_int = 51; pub const KERN_SUGID_COREDUMP: ::c_int = 52; pub const KERN_PROCDELAYTERM: ::c_int = 53; pub const KERN_SHREG_PRIVATIZABLE: ::c_int = 54; pub const KERN_LOW_PRI_WINDOW: ::c_int = 56; pub const KERN_LOW_PRI_DELAY: ::c_int = 57; pub const KERN_POSIX: ::c_int = 58; pub const KERN_USRSTACK64: ::c_int = 59; pub const KERN_NX_PROTECTION: ::c_int = 60; pub const KERN_TFP: ::c_int = 61; pub const KERN_PROCNAME: ::c_int = 62; pub const KERN_THALTSTACK: ::c_int = 63; pub const KERN_SPECULATIVE_READS: ::c_int = 64; pub const KERN_OSVERSION: ::c_int = 65; pub const KERN_SAFEBOOT: ::c_int = 66; pub const KERN_RAGEVNODE: ::c_int = 68; pub const KERN_TTY: ::c_int = 69; pub const KERN_CHECKOPENEVT: ::c_int = 70; pub const KERN_THREADNAME: ::c_int = 71; pub const KERN_MAXID: ::c_int = 72; pub const KERN_RAGE_PROC: ::c_int = 1; pub const KERN_RAGE_THREAD: ::c_int = 2; pub const KERN_UNRAGE_PROC: ::c_int = 3; pub const KERN_UNRAGE_THREAD: ::c_int = 4; pub const KERN_OPENEVT_PROC: ::c_int = 1; pub const KERN_UNOPENEVT_PROC: ::c_int = 2; pub const KERN_TFP_POLICY: ::c_int = 1; pub const KERN_TFP_POLICY_DENY: ::c_int = 0; pub const KERN_TFP_POLICY_DEFAULT: ::c_int = 2; pub const KERN_KDEFLAGS: ::c_int = 1; pub const KERN_KDDFLAGS: ::c_int = 2; pub const KERN_KDENABLE: ::c_int = 3; pub const KERN_KDSETBUF: ::c_int = 4; pub const KERN_KDGETBUF: ::c_int = 5; pub const KERN_KDSETUP: ::c_int = 6; pub const KERN_KDREMOVE: ::c_int = 7; pub const KERN_KDSETREG: ::c_int = 8; pub const KERN_KDGETREG: ::c_int = 9; pub const KERN_KDREADTR: ::c_int = 10; pub const KERN_KDPIDTR: ::c_int = 11; pub const KERN_KDTHRMAP: ::c_int = 12; pub const KERN_KDPIDEX: ::c_int = 14; pub const KERN_KDSETRTCDEC: ::c_int = 15; pub const KERN_KDGETENTROPY: ::c_int = 16; pub const KERN_KDWRITETR: ::c_int = 17; pub const KERN_KDWRITEMAP: ::c_int = 18; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Removed in MacOSX 10.12")] pub const KERN_KDENABLE_BG_TRACE: ::c_int = 19; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Removed in MacOSX 10.12")] pub const KERN_KDDISABLE_BG_TRACE: ::c_int = 20; pub const KERN_KDREADCURTHRMAP: ::c_int = 21; pub const KERN_KDSET_TYPEFILTER: ::c_int = 22; pub const KERN_KDBUFWAIT: ::c_int = 23; pub const KERN_KDCPUMAP: ::c_int = 24; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_PID: ::c_int = 1; pub const KERN_PROC_PGRP: ::c_int = 2; pub const KERN_PROC_SESSION: ::c_int = 3; pub const KERN_PROC_TTY: ::c_int = 4; pub const KERN_PROC_UID: ::c_int = 5; pub const KERN_PROC_RUID: ::c_int = 6; pub const KERN_PROC_LCID: ::c_int = 7; pub const KERN_SUCCESS: ::c_int = 0; pub const KERN_INVALID_ADDRESS: ::c_int = 1; pub const KERN_PROTECTION_FAILURE: ::c_int = 2; pub const KERN_NO_SPACE: ::c_int = 3; pub const KERN_INVALID_ARGUMENT: ::c_int = 4; pub const KERN_FAILURE: ::c_int = 5; pub const KERN_RESOURCE_SHORTAGE: ::c_int = 6; pub const KERN_NOT_RECEIVER: ::c_int = 7; pub const KERN_NO_ACCESS: ::c_int = 8; pub const KERN_MEMORY_FAILURE: ::c_int = 9; pub const KERN_MEMORY_ERROR: ::c_int = 10; pub const KERN_ALREADY_IN_SET: ::c_int = 11; pub const KERN_NOT_IN_SET: ::c_int = 12; pub const KERN_NAME_EXISTS: ::c_int = 13; pub const KERN_ABORTED: ::c_int = 14; pub const KERN_INVALID_NAME: ::c_int = 15; pub const KERN_INVALID_TASK: ::c_int = 16; pub const KERN_INVALID_RIGHT: ::c_int = 17; pub const KERN_INVALID_VALUE: ::c_int = 18; pub const KERN_UREFS_OVERFLOW: ::c_int = 19; pub const KERN_INVALID_CAPABILITY: ::c_int = 20; pub const KERN_RIGHT_EXISTS: ::c_int = 21; pub const KERN_INVALID_HOST: ::c_int = 22; pub const KERN_MEMORY_PRESENT: ::c_int = 23; pub const KERN_MEMORY_DATA_MOVED: ::c_int = 24; pub const KERN_MEMORY_RESTART_COPY: ::c_int = 25; pub const KERN_INVALID_PROCESSOR_SET: ::c_int = 26; pub const KERN_POLICY_LIMIT: ::c_int = 27; pub const KERN_INVALID_POLICY: ::c_int = 28; pub const KERN_INVALID_OBJECT: ::c_int = 29; pub const KERN_ALREADY_WAITING: ::c_int = 30; pub const KERN_DEFAULT_SET: ::c_int = 31; pub const KERN_EXCEPTION_PROTECTED: ::c_int = 32; pub const KERN_INVALID_LEDGER: ::c_int = 33; pub const KERN_INVALID_MEMORY_CONTROL: ::c_int = 34; pub const KERN_INVALID_SECURITY: ::c_int = 35; pub const KERN_NOT_DEPRESSED: ::c_int = 36; pub const KERN_TERMINATED: ::c_int = 37; pub const KERN_LOCK_SET_DESTROYED: ::c_int = 38; pub const KERN_LOCK_UNSTABLE: ::c_int = 39; pub const KERN_LOCK_OWNED: ::c_int = 40; pub const KERN_LOCK_OWNED_SELF: ::c_int = 41; pub const KERN_SEMAPHORE_DESTROYED: ::c_int = 42; pub const KERN_RPC_SERVER_TERMINATED: ::c_int = 43; pub const KERN_RPC_TERMINATE_ORPHAN: ::c_int = 44; pub const KERN_RPC_CONTINUE_ORPHAN: ::c_int = 45; pub const KERN_NOT_SUPPORTED: ::c_int = 46; pub const KERN_NODE_DOWN: ::c_int = 47; pub const KERN_NOT_WAITING: ::c_int = 48; pub const KERN_OPERATION_TIMED_OUT: ::c_int = 49; pub const KERN_CODESIGN_ERROR: ::c_int = 50; pub const KERN_POLICY_STATIC: ::c_int = 51; pub const KERN_INSUFFICIENT_BUFFER_SIZE: ::c_int = 52; pub const KIPC_MAXSOCKBUF: ::c_int = 1; pub const KIPC_SOCKBUF_WASTE: ::c_int = 2; pub const KIPC_SOMAXCONN: ::c_int = 3; pub const KIPC_MAX_LINKHDR: ::c_int = 4; pub const KIPC_MAX_PROTOHDR: ::c_int = 5; pub const KIPC_MAX_HDR: ::c_int = 6; pub const KIPC_MAX_DATALEN: ::c_int = 7; pub const KIPC_MBSTAT: ::c_int = 8; pub const KIPC_NMBCLUSTERS: ::c_int = 9; pub const KIPC_SOQLIMITCOMPAT: ::c_int = 10; pub const VM_METER: ::c_int = 1; pub const VM_LOADAVG: ::c_int = 2; pub const VM_MACHFACTOR: ::c_int = 4; pub const VM_SWAPUSAGE: ::c_int = 5; pub const VM_MAXID: ::c_int = 6; pub const VM_PROT_NONE: ::vm_prot_t = 0x00; pub const VM_PROT_READ: ::vm_prot_t = 0x01; pub const VM_PROT_WRITE: ::vm_prot_t = 0x02; pub const VM_PROT_EXECUTE: ::vm_prot_t = 0x04; pub const MEMORY_OBJECT_NULL: ::memory_object_t = 0; pub const HW_MACHINE: ::c_int = 1; pub const HW_MODEL: ::c_int = 2; pub const HW_NCPU: ::c_int = 3; pub const HW_BYTEORDER: ::c_int = 4; pub const HW_PHYSMEM: ::c_int = 5; pub const HW_USERMEM: ::c_int = 6; pub const HW_PAGESIZE: ::c_int = 7; pub const HW_DISKNAMES: ::c_int = 8; pub const HW_DISKSTATS: ::c_int = 9; pub const HW_EPOCH: ::c_int = 10; pub const HW_FLOATINGPT: ::c_int = 11; pub const HW_MACHINE_ARCH: ::c_int = 12; pub const HW_VECTORUNIT: ::c_int = 13; pub const HW_BUS_FREQ: ::c_int = 14; pub const HW_CPU_FREQ: ::c_int = 15; pub const HW_CACHELINE: ::c_int = 16; pub const HW_L1ICACHESIZE: ::c_int = 17; pub const HW_L1DCACHESIZE: ::c_int = 18; pub const HW_L2SETTINGS: ::c_int = 19; pub const HW_L2CACHESIZE: ::c_int = 20; pub const HW_L3SETTINGS: ::c_int = 21; pub const HW_L3CACHESIZE: ::c_int = 22; pub const HW_TB_FREQ: ::c_int = 23; pub const HW_MEMSIZE: ::c_int = 24; pub const HW_AVAILCPU: ::c_int = 25; pub const HW_TARGET: ::c_int = 26; pub const HW_PRODUCT: ::c_int = 27; pub const HW_MAXID: ::c_int = 28; pub const USER_CS_PATH: ::c_int = 1; pub const USER_BC_BASE_MAX: ::c_int = 2; pub const USER_BC_DIM_MAX: ::c_int = 3; pub const USER_BC_SCALE_MAX: ::c_int = 4; pub const USER_BC_STRING_MAX: ::c_int = 5; pub const USER_COLL_WEIGHTS_MAX: ::c_int = 6; pub const USER_EXPR_NEST_MAX: ::c_int = 7; pub const USER_LINE_MAX: ::c_int = 8; pub const USER_RE_DUP_MAX: ::c_int = 9; pub const USER_POSIX2_VERSION: ::c_int = 10; pub const USER_POSIX2_C_BIND: ::c_int = 11; pub const USER_POSIX2_C_DEV: ::c_int = 12; pub const USER_POSIX2_CHAR_TERM: ::c_int = 13; pub const USER_POSIX2_FORT_DEV: ::c_int = 14; pub const USER_POSIX2_FORT_RUN: ::c_int = 15; pub const USER_POSIX2_LOCALEDEF: ::c_int = 16; pub const USER_POSIX2_SW_DEV: ::c_int = 17; pub const USER_POSIX2_UPE: ::c_int = 18; pub const USER_STREAM_MAX: ::c_int = 19; pub const USER_TZNAME_MAX: ::c_int = 20; pub const USER_MAXID: ::c_int = 21; pub const CTL_DEBUG_NAME: ::c_int = 0; pub const CTL_DEBUG_VALUE: ::c_int = 1; pub const CTL_DEBUG_MAXID: ::c_int = 20; pub const PRIO_DARWIN_THREAD: ::c_int = 3; pub const PRIO_DARWIN_PROCESS: ::c_int = 4; pub const PRIO_DARWIN_BG: ::c_int = 0x1000; pub const PRIO_DARWIN_NONUI: ::c_int = 0x1001; pub const SEM_FAILED: *mut sem_t = -1isize as *mut ::sem_t; pub const AI_PASSIVE: ::c_int = 0x00000001; pub const AI_CANONNAME: ::c_int = 0x00000002; pub const AI_NUMERICHOST: ::c_int = 0x00000004; pub const AI_NUMERICSERV: ::c_int = 0x00001000; pub const AI_MASK: ::c_int = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG; pub const AI_ALL: ::c_int = 0x00000100; pub const AI_V4MAPPED_CFG: ::c_int = 0x00000200; pub const AI_ADDRCONFIG: ::c_int = 0x00000400; pub const AI_V4MAPPED: ::c_int = 0x00000800; pub const AI_DEFAULT: ::c_int = AI_V4MAPPED_CFG | AI_ADDRCONFIG; pub const AI_UNUSABLE: ::c_int = 0x10000000; pub const SIGEV_NONE: ::c_int = 0; pub const SIGEV_SIGNAL: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 3; pub const AIO_CANCELED: ::c_int = 2; pub const AIO_NOTCANCELED: ::c_int = 4; pub const AIO_ALLDONE: ::c_int = 1; #[deprecated( since = "0.2.64", note = "Can vary at runtime. Use sysconf(3) instead" )] pub const AIO_LISTIO_MAX: ::c_int = 16; pub const LIO_NOP: ::c_int = 0; pub const LIO_WRITE: ::c_int = 2; pub const LIO_READ: ::c_int = 1; pub const LIO_WAIT: ::c_int = 2; pub const LIO_NOWAIT: ::c_int = 1; pub const WEXITED: ::c_int = 0x00000004; pub const WSTOPPED: ::c_int = 0x00000008; pub const WCONTINUED: ::c_int = 0x00000010; pub const WNOWAIT: ::c_int = 0x00000020; pub const P_ALL: idtype_t = 0; pub const P_PID: idtype_t = 1; pub const P_PGID: idtype_t = 2; pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const XATTR_NOFOLLOW: ::c_int = 0x0001; pub const XATTR_CREATE: ::c_int = 0x0002; pub const XATTR_REPLACE: ::c_int = 0x0004; pub const XATTR_NOSECURITY: ::c_int = 0x0008; pub const XATTR_NODEFAULT: ::c_int = 0x0010; pub const XATTR_SHOWCOMPRESSION: ::c_int = 0x0020; pub const NET_RT_IFLIST2: ::c_int = 0x0006; // net/route.h pub const RTF_UP: ::c_int = 0x1; pub const RTF_GATEWAY: ::c_int = 0x2; pub const RTF_HOST: ::c_int = 0x4; pub const RTF_REJECT: ::c_int = 0x8; pub const RTF_DYNAMIC: ::c_int = 0x10; pub const RTF_MODIFIED: ::c_int = 0x20; pub const RTF_DONE: ::c_int = 0x40; pub const RTF_DELCLONE: ::c_int = 0x80; pub const RTF_CLONING: ::c_int = 0x100; pub const RTF_XRESOLVE: ::c_int = 0x200; pub const RTF_LLINFO: ::c_int = 0x400; pub const RTF_STATIC: ::c_int = 0x800; pub const RTF_BLACKHOLE: ::c_int = 0x1000; pub const RTF_NOIFREF: ::c_int = 0x2000; pub const RTF_PROTO2: ::c_int = 0x4000; pub const RTF_PROTO1: ::c_int = 0x8000; pub const RTF_PRCLONING: ::c_int = 0x10000; pub const RTF_WASCLONED: ::c_int = 0x20000; pub const RTF_PROTO3: ::c_int = 0x40000; pub const RTF_PINNED: ::c_int = 0x100000; pub const RTF_LOCAL: ::c_int = 0x200000; pub const RTF_BROADCAST: ::c_int = 0x400000; pub const RTF_MULTICAST: ::c_int = 0x800000; pub const RTF_IFSCOPE: ::c_int = 0x1000000; pub const RTF_CONDEMNED: ::c_int = 0x2000000; pub const RTF_IFREF: ::c_int = 0x4000000; pub const RTF_PROXY: ::c_int = 0x8000000; pub const RTF_ROUTER: ::c_int = 0x10000000; pub const RTF_DEAD: ::c_int = 0x20000000; pub const RTF_GLOBAL: ::c_int = 0x40000000; pub const RTM_VERSION: ::c_int = 5; // Message types pub const RTM_ADD: ::c_int = 0x1; pub const RTM_DELETE: ::c_int = 0x2; pub const RTM_CHANGE: ::c_int = 0x3; pub const RTM_GET: ::c_int = 0x4; pub const RTM_LOSING: ::c_int = 0x5; pub const RTM_REDIRECT: ::c_int = 0x6; pub const RTM_MISS: ::c_int = 0x7; pub const RTM_LOCK: ::c_int = 0x8; pub const RTM_OLDADD: ::c_int = 0x9; pub const RTM_OLDDEL: ::c_int = 0xa; pub const RTM_RESOLVE: ::c_int = 0xb; pub const RTM_NEWADDR: ::c_int = 0xc; pub const RTM_DELADDR: ::c_int = 0xd; pub const RTM_IFINFO: ::c_int = 0xe; pub const RTM_NEWMADDR: ::c_int = 0xf; pub const RTM_DELMADDR: ::c_int = 0x10; pub const RTM_IFINFO2: ::c_int = 0x12; pub const RTM_NEWMADDR2: ::c_int = 0x13; pub const RTM_GET2: ::c_int = 0x14; // Bitmask values for rtm_inits and rmx_locks. pub const RTV_MTU: ::c_int = 0x1; pub const RTV_HOPCOUNT: ::c_int = 0x2; pub const RTV_EXPIRE: ::c_int = 0x4; pub const RTV_RPIPE: ::c_int = 0x8; pub const RTV_SPIPE: ::c_int = 0x10; pub const RTV_SSTHRESH: ::c_int = 0x20; pub const RTV_RTT: ::c_int = 0x40; pub const RTV_RTTVAR: ::c_int = 0x80; // Bitmask values for rtm_addrs. pub const RTA_DST: ::c_int = 0x1; pub const RTA_GATEWAY: ::c_int = 0x2; pub const RTA_NETMASK: ::c_int = 0x4; pub const RTA_GENMASK: ::c_int = 0x8; pub const RTA_IFP: ::c_int = 0x10; pub const RTA_IFA: ::c_int = 0x20; pub const RTA_AUTHOR: ::c_int = 0x40; pub const RTA_BRD: ::c_int = 0x80; // Index offsets for sockaddr array for alternate internal encoding. pub const RTAX_DST: ::c_int = 0; pub const RTAX_GATEWAY: ::c_int = 1; pub const RTAX_NETMASK: ::c_int = 2; pub const RTAX_GENMASK: ::c_int = 3; pub const RTAX_IFP: ::c_int = 4; pub const RTAX_IFA: ::c_int = 5; pub const RTAX_AUTHOR: ::c_int = 6; pub const RTAX_BRD: ::c_int = 7; pub const RTAX_MAX: ::c_int = 8; pub const KERN_PROCARGS2: ::c_int = 49; pub const PROC_PIDTASKALLINFO: ::c_int = 2; pub const PROC_PIDTBSDINFO: ::c_int = 3; pub const PROC_PIDTASKINFO: ::c_int = 4; pub const PROC_PIDTHREADINFO: ::c_int = 5; pub const PROC_PIDVNODEPATHINFO: ::c_int = 9; pub const PROC_PIDPATHINFO_MAXSIZE: ::c_int = 4096; pub const PROC_CSM_ALL: ::c_uint = 0x0001; pub const PROC_CSM_NOSMT: ::c_uint = 0x0002; pub const PROC_CSM_TECS: ::c_uint = 0x0004; pub const MAXCOMLEN: usize = 16; pub const MAXTHREADNAMESIZE: usize = 64; pub const XUCRED_VERSION: ::c_uint = 0; pub const LC_SEGMENT: u32 = 0x1; pub const LC_SEGMENT_64: u32 = 0x19; pub const MH_MAGIC: u32 = 0xfeedface; pub const MH_MAGIC_64: u32 = 0xfeedfacf; // net/if_utun.h pub const UTUN_OPT_FLAGS: ::c_int = 1; pub const UTUN_OPT_IFNAME: ::c_int = 2; // net/bpf.h pub const DLT_NULL: ::c_uint = 0; // no link-layer encapsulation pub const DLT_EN10MB: ::c_uint = 1; // Ethernet (10Mb) pub const DLT_EN3MB: ::c_uint = 2; // Experimental Ethernet (3Mb) pub const DLT_AX25: ::c_uint = 3; // Amateur Radio AX.25 pub const DLT_PRONET: ::c_uint = 4; // Proteon ProNET Token Ring pub const DLT_CHAOS: ::c_uint = 5; // Chaos pub const DLT_IEEE802: ::c_uint = 6; // IEEE 802 Networks pub const DLT_ARCNET: ::c_uint = 7; // ARCNET pub const DLT_SLIP: ::c_uint = 8; // Serial Line IP pub const DLT_PPP: ::c_uint = 9; // Point-to-point Protocol pub const DLT_FDDI: ::c_uint = 10; // FDDI pub const DLT_ATM_RFC1483: ::c_uint = 11; // LLC/SNAP encapsulated atm pub const DLT_RAW: ::c_uint = 12; // raw IP pub const DLT_LOOP: ::c_uint = 108; // https://github.com/apple/darwin-xnu/blob/HEAD/bsd/net/bpf.h#L100 // sizeof(i32) pub const BPF_ALIGNMENT: ::c_int = 4; // sys/mount.h pub const MNT_NODEV: ::c_int = 0x00000010; pub const MNT_UNION: ::c_int = 0x00000020; pub const MNT_CPROTECT: ::c_int = 0x00000080; // MAC labeled / "quarantined" flag pub const MNT_QUARANTINE: ::c_int = 0x00000400; // Flags set by internal operations. pub const MNT_LOCAL: ::c_int = 0x00001000; pub const MNT_QUOTA: ::c_int = 0x00002000; pub const MNT_ROOTFS: ::c_int = 0x00004000; pub const MNT_DOVOLFS: ::c_int = 0x00008000; pub const MNT_DONTBROWSE: ::c_int = 0x00100000; pub const MNT_IGNORE_OWNERSHIP: ::c_int = 0x00200000; pub const MNT_AUTOMOUNTED: ::c_int = 0x00400000; pub const MNT_JOURNALED: ::c_int = 0x00800000; pub const MNT_NOUSERXATTR: ::c_int = 0x01000000; pub const MNT_DEFWRITE: ::c_int = 0x02000000; pub const MNT_MULTILABEL: ::c_int = 0x04000000; pub const MNT_NOATIME: ::c_int = 0x10000000; pub const MNT_SNAPSHOT: ::c_int = 0x40000000; // External filesystem command modifier flags. pub const MNT_NOBLOCK: ::c_int = 0x00020000; // sys/spawn.h: pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x0001; pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x0002; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x0004; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x0008; pub const POSIX_SPAWN_SETEXEC: ::c_int = 0x0040; pub const POSIX_SPAWN_START_SUSPENDED: ::c_int = 0x0080; pub const POSIX_SPAWN_CLOEXEC_DEFAULT: ::c_int = 0x4000; // sys/ipc.h: pub const IPC_CREAT: ::c_int = 0x200; pub const IPC_EXCL: ::c_int = 0x400; pub const IPC_NOWAIT: ::c_int = 0x800; pub const IPC_PRIVATE: key_t = 0; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const IPC_R: ::c_int = 0x100; pub const IPC_W: ::c_int = 0x80; pub const IPC_M: ::c_int = 0x1000; // sys/sem.h pub const SEM_UNDO: ::c_int = 0o10000; pub const GETNCNT: ::c_int = 3; pub const GETPID: ::c_int = 4; pub const GETVAL: ::c_int = 5; pub const GETALL: ::c_int = 6; pub const GETZCNT: ::c_int = 7; pub const SETVAL: ::c_int = 8; pub const SETALL: ::c_int = 9; // sys/shm.h pub const SHM_RDONLY: ::c_int = 0x1000; pub const SHM_RND: ::c_int = 0x2000; #[cfg(target_arch = "aarch64")] pub const SHMLBA: ::c_int = 16 * 1024; #[cfg(not(target_arch = "aarch64"))] pub const SHMLBA: ::c_int = 4096; pub const SHM_R: ::c_int = IPC_R; pub const SHM_W: ::c_int = IPC_W; // Flags for chflags(2) pub const UF_SETTABLE: ::c_uint = 0x0000ffff; pub const UF_NODUMP: ::c_uint = 0x00000001; pub const UF_IMMUTABLE: ::c_uint = 0x00000002; pub const UF_APPEND: ::c_uint = 0x00000004; pub const UF_OPAQUE: ::c_uint = 0x00000008; pub const UF_COMPRESSED: ::c_uint = 0x00000020; pub const UF_TRACKED: ::c_uint = 0x00000040; pub const SF_SETTABLE: ::c_uint = 0xffff0000; pub const SF_ARCHIVED: ::c_uint = 0x00010000; pub const SF_IMMUTABLE: ::c_uint = 0x00020000; pub const SF_APPEND: ::c_uint = 0x00040000; pub const UF_HIDDEN: ::c_uint = 0x00008000; // pub const NTP_API: ::c_int = 4; pub const MAXPHASE: ::c_long = 500000000; pub const MAXFREQ: ::c_long = 500000; pub const MINSEC: ::c_int = 256; pub const MAXSEC: ::c_int = 2048; pub const NANOSECOND: ::c_long = 1000000000; pub const SCALE_PPM: ::c_int = 65; pub const MAXTC: ::c_int = 10; pub const MOD_OFFSET: ::c_uint = 0x0001; pub const MOD_FREQUENCY: ::c_uint = 0x0002; pub const MOD_MAXERROR: ::c_uint = 0x0004; pub const MOD_ESTERROR: ::c_uint = 0x0008; pub const MOD_STATUS: ::c_uint = 0x0010; pub const MOD_TIMECONST: ::c_uint = 0x0020; pub const MOD_PPSMAX: ::c_uint = 0x0040; pub const MOD_TAI: ::c_uint = 0x0080; pub const MOD_MICRO: ::c_uint = 0x1000; pub const MOD_NANO: ::c_uint = 0x2000; pub const MOD_CLKB: ::c_uint = 0x4000; pub const MOD_CLKA: ::c_uint = 0x8000; pub const STA_PLL: ::c_int = 0x0001; pub const STA_PPSFREQ: ::c_int = 0x0002; pub const STA_PPSTIME: ::c_int = 0x0004; pub const STA_FLL: ::c_int = 0x0008; pub const STA_INS: ::c_int = 0x0010; pub const STA_DEL: ::c_int = 0x0020; pub const STA_UNSYNC: ::c_int = 0x0040; pub const STA_FREQHOLD: ::c_int = 0x0080; pub const STA_PPSSIGNAL: ::c_int = 0x0100; pub const STA_PPSJITTER: ::c_int = 0x0200; pub const STA_PPSWANDER: ::c_int = 0x0400; pub const STA_PPSERROR: ::c_int = 0x0800; pub const STA_CLOCKERR: ::c_int = 0x1000; pub const STA_NANO: ::c_int = 0x2000; pub const STA_MODE: ::c_int = 0x4000; pub const STA_CLK: ::c_int = 0x8000; pub const STA_RONLY: ::c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: ::c_int = 0; pub const TIME_INS: ::c_int = 1; pub const TIME_DEL: ::c_int = 2; pub const TIME_OOP: ::c_int = 3; pub const TIME_WAIT: ::c_int = 4; pub const TIME_ERROR: ::c_int = 5; // pub const MNT_WAIT: ::c_int = 1; pub const MNT_NOWAIT: ::c_int = 2; // pub const THREAD_STANDARD_POLICY: ::c_int = 1; pub const THREAD_STANDARD_POLICY_COUNT: ::c_int = 0; pub const THREAD_EXTENDED_POLICY: ::c_int = 1; pub const THREAD_TIME_CONSTRAINT_POLICY: ::c_int = 2; pub const THREAD_PRECEDENCE_POLICY: ::c_int = 3; pub const THREAD_AFFINITY_POLICY: ::c_int = 4; pub const THREAD_AFFINITY_TAG_NULL: ::c_int = 0; pub const THREAD_BACKGROUND_POLICY: ::c_int = 5; pub const THREAD_BACKGROUND_POLICY_DARWIN_BG: ::c_int = 0x1000; pub const THREAD_LATENCY_QOS_POLICY: ::c_int = 7; pub const THREAD_THROUGHPUT_QOS_POLICY: ::c_int = 8; // pub const TH_STATE_RUNNING: ::c_int = 1; pub const TH_STATE_STOPPED: ::c_int = 2; pub const TH_STATE_WAITING: ::c_int = 3; pub const TH_STATE_UNINTERRUPTIBLE: ::c_int = 4; pub const TH_STATE_HALTED: ::c_int = 5; pub const TH_FLAGS_SWAPPED: ::c_int = 0x1; pub const TH_FLAGS_IDLE: ::c_int = 0x2; pub const TH_FLAGS_GLOBAL_FORCED_IDLE: ::c_int = 0x4; pub const THREAD_BASIC_INFO: ::c_int = 3; pub const THREAD_IDENTIFIER_INFO: ::c_int = 4; pub const THREAD_EXTENDED_INFO: ::c_int = 5; // CommonCrypto/CommonCryptoError.h pub const kCCSuccess: i32 = 0; pub const kCCParamError: i32 = -4300; pub const kCCBufferTooSmall: i32 = -4301; pub const kCCMemoryFailure: i32 = -4302; pub const kCCAlignmentError: i32 = -4303; pub const kCCDecodeError: i32 = -4304; pub const kCCUnimplemented: i32 = -4305; pub const kCCOverflow: i32 = -4306; pub const kCCRNGFailure: i32 = -4307; pub const kCCUnspecifiedError: i32 = -4308; pub const kCCCallSequenceError: i32 = -4309; pub const kCCKeySizeError: i32 = -4310; pub const kCCInvalidKey: i32 = -4311; // mach/host_info.h pub const HOST_LOAD_INFO: i32 = 1; pub const HOST_VM_INFO: i32 = 2; pub const HOST_CPU_LOAD_INFO: i32 = 3; pub const HOST_VM_INFO64: i32 = 4; pub const HOST_EXTMOD_INFO64: i32 = 5; pub const HOST_EXPIRED_TASK_INFO: i32 = 6; // mach/vm_statistics.h pub const VM_PAGE_QUERY_PAGE_PRESENT: i32 = 0x1; pub const VM_PAGE_QUERY_PAGE_FICTITIOUS: i32 = 0x2; pub const VM_PAGE_QUERY_PAGE_REF: i32 = 0x4; pub const VM_PAGE_QUERY_PAGE_DIRTY: i32 = 0x8; pub const VM_PAGE_QUERY_PAGE_PAGED_OUT: i32 = 0x10; pub const VM_PAGE_QUERY_PAGE_COPIED: i32 = 0x20; pub const VM_PAGE_QUERY_PAGE_SPECULATIVE: i32 = 0x40; pub const VM_PAGE_QUERY_PAGE_EXTERNAL: i32 = 0x80; pub const VM_PAGE_QUERY_PAGE_CS_VALIDATED: i32 = 0x100; pub const VM_PAGE_QUERY_PAGE_CS_TAINTED: i32 = 0x200; pub const VM_PAGE_QUERY_PAGE_CS_NX: i32 = 0x400; // mach/task_info.h pub const TASK_THREAD_TIMES_INFO: u32 = 3; pub const HOST_CPU_LOAD_INFO_COUNT: u32 = 4; pub const MACH_TASK_BASIC_INFO: u32 = 20; pub const MACH_PORT_NULL: i32 = 0; pub const RUSAGE_INFO_V0: ::c_int = 0; pub const RUSAGE_INFO_V1: ::c_int = 1; pub const RUSAGE_INFO_V2: ::c_int = 2; pub const RUSAGE_INFO_V3: ::c_int = 3; pub const RUSAGE_INFO_V4: ::c_int = 4; // copyfile.h pub const COPYFILE_ACL: ::copyfile_flags_t = 1 << 0; pub const COPYFILE_STAT: ::copyfile_flags_t = 1 << 1; pub const COPYFILE_XATTR: ::copyfile_flags_t = 1 << 2; pub const COPYFILE_DATA: ::copyfile_flags_t = 1 << 3; pub const COPYFILE_SECURITY: ::copyfile_flags_t = COPYFILE_STAT | COPYFILE_ACL; pub const COPYFILE_METADATA: ::copyfile_flags_t = COPYFILE_SECURITY | COPYFILE_XATTR; pub const COPYFILE_RECURSIVE: ::copyfile_flags_t = 1 << 15; pub const COPYFILE_CHECK: ::copyfile_flags_t = 1 << 16; pub const COPYFILE_EXCL: ::copyfile_flags_t = 1 << 17; pub const COPYFILE_NOFOLLOW_SRC: ::copyfile_flags_t = 1 << 18; pub const COPYFILE_NOFOLLOW_DST: ::copyfile_flags_t = 1 << 19; pub const COPYFILE_MOVE: ::copyfile_flags_t = 1 << 20; pub const COPYFILE_UNLINK: ::copyfile_flags_t = 1 << 21; pub const COPYFILE_NOFOLLOW: ::copyfile_flags_t = COPYFILE_NOFOLLOW_SRC | COPYFILE_NOFOLLOW_DST; pub const COPYFILE_PACK: ::copyfile_flags_t = 1 << 22; pub const COPYFILE_UNPACK: ::copyfile_flags_t = 1 << 23; pub const COPYFILE_CLONE: ::copyfile_flags_t = 1 << 24; pub const COPYFILE_CLONE_FORCE: ::copyfile_flags_t = 1 << 25; pub const COPYFILE_RUN_IN_PLACE: ::copyfile_flags_t = 1 << 26; pub const COPYFILE_DATA_SPARSE: ::copyfile_flags_t = 1 << 27; pub const COPYFILE_PRESERVE_DST_TRACKED: ::copyfile_flags_t = 1 << 28; pub const COPYFILE_VERBOSE: ::copyfile_flags_t = 1 << 30; pub const COPYFILE_RECURSE_ERROR: ::c_int = 0; pub const COPYFILE_RECURSE_FILE: ::c_int = 1; pub const COPYFILE_RECURSE_DIR: ::c_int = 2; pub const COPYFILE_RECURSE_DIR_CLEANUP: ::c_int = 3; pub const COPYFILE_COPY_DATA: ::c_int = 4; pub const COPYFILE_COPY_XATTR: ::c_int = 5; pub const COPYFILE_START: ::c_int = 1; pub const COPYFILE_FINISH: ::c_int = 2; pub const COPYFILE_ERR: ::c_int = 3; pub const COPYFILE_PROGRESS: ::c_int = 4; pub const COPYFILE_CONTINUE: ::c_int = 0; pub const COPYFILE_SKIP: ::c_int = 1; pub const COPYFILE_QUIT: ::c_int = 2; pub const COPYFILE_STATE_SRC_FD: ::c_int = 1; pub const COPYFILE_STATE_SRC_FILENAME: ::c_int = 2; pub const COPYFILE_STATE_DST_FD: ::c_int = 3; pub const COPYFILE_STATE_DST_FILENAME: ::c_int = 4; pub const COPYFILE_STATE_QUARANTINE: ::c_int = 5; pub const COPYFILE_STATE_STATUS_CB: ::c_int = 6; pub const COPYFILE_STATE_STATUS_CTX: ::c_int = 7; pub const COPYFILE_STATE_COPIED: ::c_int = 8; pub const COPYFILE_STATE_XATTRNAME: ::c_int = 9; pub const COPYFILE_STATE_WAS_CLONED: ::c_int = 10; pub const COPYFILE_STATE_SRC_BSIZE: ::c_int = 11; pub const COPYFILE_STATE_DST_BSIZE: ::c_int = 12; pub const COPYFILE_STATE_BSIZE: ::c_int = 13; // pub const ATTR_BIT_MAP_COUNT: ::c_ushort = 5; pub const FSOPT_NOFOLLOW: u32 = 0x1; pub const FSOPT_NOFOLLOW_ANY: u32 = 0x800; pub const FSOPT_REPORT_FULLSIZE: u32 = 0x4; pub const FSOPT_PACK_INVAL_ATTRS: u32 = 0x8; pub const FSOPT_ATTR_CMN_EXTENDED: u32 = 0x20; pub const FSOPT_RETURN_REALDEV: u32 = 0x200; pub const ATTR_CMN_NAME: attrgroup_t = 0x00000001; pub const ATTR_CMN_DEVID: attrgroup_t = 0x00000002; pub const ATTR_CMN_FSID: attrgroup_t = 0x00000004; pub const ATTR_CMN_OBJTYPE: attrgroup_t = 0x00000008; pub const ATTR_CMN_OBJTAG: attrgroup_t = 0x00000010; pub const ATTR_CMN_OBJID: attrgroup_t = 0x00000020; pub const ATTR_CMN_OBJPERMANENTID: attrgroup_t = 0x00000040; pub const ATTR_CMN_PAROBJID: attrgroup_t = 0x00000080; pub const ATTR_CMN_SCRIPT: attrgroup_t = 0x00000100; pub const ATTR_CMN_CRTIME: attrgroup_t = 0x00000200; pub const ATTR_CMN_MODTIME: attrgroup_t = 0x00000400; pub const ATTR_CMN_CHGTIME: attrgroup_t = 0x00000800; pub const ATTR_CMN_ACCTIME: attrgroup_t = 0x00001000; pub const ATTR_CMN_BKUPTIME: attrgroup_t = 0x00002000; pub const ATTR_CMN_FNDRINFO: attrgroup_t = 0x00004000; pub const ATTR_CMN_OWNERID: attrgroup_t = 0x00008000; pub const ATTR_CMN_GRPID: attrgroup_t = 0x00010000; pub const ATTR_CMN_ACCESSMASK: attrgroup_t = 0x00020000; pub const ATTR_CMN_FLAGS: attrgroup_t = 0x00040000; pub const ATTR_CMN_GEN_COUNT: attrgroup_t = 0x00080000; pub const ATTR_CMN_DOCUMENT_ID: attrgroup_t = 0x00100000; pub const ATTR_CMN_USERACCESS: attrgroup_t = 0x00200000; pub const ATTR_CMN_EXTENDED_SECURITY: attrgroup_t = 0x00400000; pub const ATTR_CMN_UUID: attrgroup_t = 0x00800000; pub const ATTR_CMN_GRPUUID: attrgroup_t = 0x01000000; pub const ATTR_CMN_FILEID: attrgroup_t = 0x02000000; pub const ATTR_CMN_PARENTID: attrgroup_t = 0x04000000; pub const ATTR_CMN_FULLPATH: attrgroup_t = 0x08000000; pub const ATTR_CMN_ADDEDTIME: attrgroup_t = 0x10000000; pub const ATTR_CMN_DATA_PROTECT_FLAGS: attrgroup_t = 0x40000000; pub const ATTR_CMN_RETURNED_ATTRS: attrgroup_t = 0x80000000; pub const ATTR_VOL_FSTYPE: attrgroup_t = 0x00000001; pub const ATTR_VOL_SIGNATURE: attrgroup_t = 0x00000002; pub const ATTR_VOL_SIZE: attrgroup_t = 0x00000004; pub const ATTR_VOL_SPACEFREE: attrgroup_t = 0x00000008; pub const ATTR_VOL_SPACEAVAIL: attrgroup_t = 0x00000010; pub const ATTR_VOL_MINALLOCATION: attrgroup_t = 0x00000020; pub const ATTR_VOL_ALLOCATIONCLUMP: attrgroup_t = 0x00000040; pub const ATTR_VOL_IOBLOCKSIZE: attrgroup_t = 0x00000080; pub const ATTR_VOL_OBJCOUNT: attrgroup_t = 0x00000100; pub const ATTR_VOL_FILECOUNT: attrgroup_t = 0x00000200; pub const ATTR_VOL_DIRCOUNT: attrgroup_t = 0x00000400; pub const ATTR_VOL_MAXOBJCOUNT: attrgroup_t = 0x00000800; pub const ATTR_VOL_MOUNTPOINT: attrgroup_t = 0x00001000; pub const ATTR_VOL_NAME: attrgroup_t = 0x00002000; pub const ATTR_VOL_MOUNTFLAGS: attrgroup_t = 0x00004000; pub const ATTR_VOL_MOUNTEDDEVICE: attrgroup_t = 0x00008000; pub const ATTR_VOL_ENCODINGSUSED: attrgroup_t = 0x00010000; pub const ATTR_VOL_CAPABILITIES: attrgroup_t = 0x00020000; pub const ATTR_VOL_UUID: attrgroup_t = 0x00040000; pub const ATTR_VOL_SPACEUSED: attrgroup_t = 0x00800000; pub const ATTR_VOL_QUOTA_SIZE: attrgroup_t = 0x10000000; pub const ATTR_VOL_RESERVED_SIZE: attrgroup_t = 0x20000000; pub const ATTR_VOL_ATTRIBUTES: attrgroup_t = 0x40000000; pub const ATTR_VOL_INFO: attrgroup_t = 0x80000000; pub const ATTR_DIR_LINKCOUNT: attrgroup_t = 0x00000001; pub const ATTR_DIR_ENTRYCOUNT: attrgroup_t = 0x00000002; pub const ATTR_DIR_MOUNTSTATUS: attrgroup_t = 0x00000004; pub const ATTR_DIR_ALLOCSIZE: attrgroup_t = 0x00000008; pub const ATTR_DIR_IOBLOCKSIZE: attrgroup_t = 0x00000010; pub const ATTR_DIR_DATALENGTH: attrgroup_t = 0x00000020; pub const ATTR_FILE_LINKCOUNT: attrgroup_t = 0x00000001; pub const ATTR_FILE_TOTALSIZE: attrgroup_t = 0x00000002; pub const ATTR_FILE_ALLOCSIZE: attrgroup_t = 0x00000004; pub const ATTR_FILE_IOBLOCKSIZE: attrgroup_t = 0x00000008; pub const ATTR_FILE_DEVTYPE: attrgroup_t = 0x00000020; pub const ATTR_FILE_FORKCOUNT: attrgroup_t = 0x00000080; pub const ATTR_FILE_FORKLIST: attrgroup_t = 0x00000100; pub const ATTR_FILE_DATALENGTH: attrgroup_t = 0x00000200; pub const ATTR_FILE_DATAALLOCSIZE: attrgroup_t = 0x00000400; pub const ATTR_FILE_RSRCLENGTH: attrgroup_t = 0x00001000; pub const ATTR_FILE_RSRCALLOCSIZE: attrgroup_t = 0x00002000; pub const ATTR_CMNEXT_RELPATH: attrgroup_t = 0x00000004; pub const ATTR_CMNEXT_PRIVATESIZE: attrgroup_t = 0x00000008; pub const ATTR_CMNEXT_LINKID: attrgroup_t = 0x00000010; pub const ATTR_CMNEXT_NOFIRMLINKPATH: attrgroup_t = 0x00000020; pub const ATTR_CMNEXT_REALDEVID: attrgroup_t = 0x00000040; pub const ATTR_CMNEXT_REALFSID: attrgroup_t = 0x00000080; pub const ATTR_CMNEXT_CLONEID: attrgroup_t = 0x00000100; pub const ATTR_CMNEXT_EXT_FLAGS: attrgroup_t = 0x00000200; pub const ATTR_CMNEXT_RECURSIVE_GENCOUNT: attrgroup_t = 0x00000400; pub const DIR_MNTSTATUS_MNTPOINT: u32 = 0x1; pub const VOL_CAPABILITIES_FORMAT: usize = 0; pub const VOL_CAPABILITIES_INTERFACES: usize = 1; pub const VOL_CAP_FMT_PERSISTENTOBJECTIDS: attrgroup_t = 0x00000001; pub const VOL_CAP_FMT_SYMBOLICLINKS: attrgroup_t = 0x00000002; pub const VOL_CAP_FMT_HARDLINKS: attrgroup_t = 0x00000004; pub const VOL_CAP_FMT_JOURNAL: attrgroup_t = 0x00000008; pub const VOL_CAP_FMT_JOURNAL_ACTIVE: attrgroup_t = 0x00000010; pub const VOL_CAP_FMT_NO_ROOT_TIMES: attrgroup_t = 0x00000020; pub const VOL_CAP_FMT_SPARSE_FILES: attrgroup_t = 0x00000040; pub const VOL_CAP_FMT_ZERO_RUNS: attrgroup_t = 0x00000080; pub const VOL_CAP_FMT_CASE_SENSITIVE: attrgroup_t = 0x00000100; pub const VOL_CAP_FMT_CASE_PRESERVING: attrgroup_t = 0x00000200; pub const VOL_CAP_FMT_FAST_STATFS: attrgroup_t = 0x00000400; pub const VOL_CAP_FMT_2TB_FILESIZE: attrgroup_t = 0x00000800; pub const VOL_CAP_FMT_OPENDENYMODES: attrgroup_t = 0x00001000; pub const VOL_CAP_FMT_HIDDEN_FILES: attrgroup_t = 0x00002000; pub const VOL_CAP_FMT_PATH_FROM_ID: attrgroup_t = 0x00004000; pub const VOL_CAP_FMT_NO_VOLUME_SIZES: attrgroup_t = 0x00008000; pub const VOL_CAP_FMT_DECMPFS_COMPRESSION: attrgroup_t = 0x00010000; pub const VOL_CAP_FMT_64BIT_OBJECT_IDS: attrgroup_t = 0x00020000; pub const VOL_CAP_FMT_DIR_HARDLINKS: attrgroup_t = 0x00040000; pub const VOL_CAP_FMT_DOCUMENT_ID: attrgroup_t = 0x00080000; pub const VOL_CAP_FMT_WRITE_GENERATION_COUNT: attrgroup_t = 0x00100000; pub const VOL_CAP_FMT_NO_IMMUTABLE_FILES: attrgroup_t = 0x00200000; pub const VOL_CAP_FMT_NO_PERMISSIONS: attrgroup_t = 0x00400000; pub const VOL_CAP_FMT_SHARED_SPACE: attrgroup_t = 0x00800000; pub const VOL_CAP_FMT_VOL_GROUPS: attrgroup_t = 0x01000000; pub const VOL_CAP_FMT_SEALED: attrgroup_t = 0x02000000; pub const VOL_CAP_INT_SEARCHFS: attrgroup_t = 0x00000001; pub const VOL_CAP_INT_ATTRLIST: attrgroup_t = 0x00000002; pub const VOL_CAP_INT_NFSEXPORT: attrgroup_t = 0x00000004; pub const VOL_CAP_INT_READDIRATTR: attrgroup_t = 0x00000008; pub const VOL_CAP_INT_EXCHANGEDATA: attrgroup_t = 0x00000010; pub const VOL_CAP_INT_COPYFILE: attrgroup_t = 0x00000020; pub const VOL_CAP_INT_ALLOCATE: attrgroup_t = 0x00000040; pub const VOL_CAP_INT_VOL_RENAME: attrgroup_t = 0x00000080; pub const VOL_CAP_INT_ADVLOCK: attrgroup_t = 0x00000100; pub const VOL_CAP_INT_FLOCK: attrgroup_t = 0x00000200; pub const VOL_CAP_INT_EXTENDED_SECURITY: attrgroup_t = 0x00000400; pub const VOL_CAP_INT_USERACCESS: attrgroup_t = 0x00000800; pub const VOL_CAP_INT_MANLOCK: attrgroup_t = 0x00001000; pub const VOL_CAP_INT_NAMEDSTREAMS: attrgroup_t = 0x00002000; pub const VOL_CAP_INT_EXTENDED_ATTR: attrgroup_t = 0x00004000; pub const VOL_CAP_INT_CLONE: attrgroup_t = 0x00010000; pub const VOL_CAP_INT_SNAPSHOT: attrgroup_t = 0x00020000; pub const VOL_CAP_INT_RENAME_SWAP: attrgroup_t = 0x00040000; pub const VOL_CAP_INT_RENAME_EXCL: attrgroup_t = 0x00080000; pub const VOL_CAP_INT_RENAME_OPENFAIL: attrgroup_t = 0x00100000; // /// Process being created by fork. pub const SIDL: u32 = 1; /// Currently runnable. pub const SRUN: u32 = 2; /// Sleeping on an address. pub const SSLEEP: u32 = 3; /// Process debugging or suspension. pub const SSTOP: u32 = 4; /// Awaiting collection by parent. pub const SZOMB: u32 = 5; // sys/vsock.h pub const VMADDR_CID_ANY: ::c_uint = 0xFFFFFFFF; pub const VMADDR_CID_HYPERVISOR: ::c_uint = 0; pub const VMADDR_CID_RESERVED: ::c_uint = 1; pub const VMADDR_CID_HOST: ::c_uint = 2; pub const VMADDR_PORT_ANY: ::c_uint = 0xFFFFFFFF; cfg_if! { if #[cfg(libc_const_extern_fn)] { const fn __DARWIN_ALIGN32(p: usize) -> usize { const __DARWIN_ALIGNBYTES32: usize = ::mem::size_of::() - 1; p + __DARWIN_ALIGNBYTES32 & !__DARWIN_ALIGNBYTES32 } } else if #[cfg(libc_const_size_of)] { fn __DARWIN_ALIGN32(p: usize) -> usize { const __DARWIN_ALIGNBYTES32: usize = ::mem::size_of::() - 1; p + __DARWIN_ALIGNBYTES32 & !__DARWIN_ALIGNBYTES32 } } else { fn __DARWIN_ALIGN32(p: usize) -> usize { let __DARWIN_ALIGNBYTES32: usize = ::mem::size_of::() - 1; p + __DARWIN_ALIGNBYTES32 & !__DARWIN_ALIGNBYTES32 } } } cfg_if! { if #[cfg(libc_const_size_of)] { pub const THREAD_EXTENDED_POLICY_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_TIME_CONSTRAINT_POLICY_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_PRECEDENCE_POLICY_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_AFFINITY_POLICY_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_BACKGROUND_POLICY_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_LATENCY_QOS_POLICY_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_THROUGHPUT_QOS_POLICY_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_BASIC_INFO_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_IDENTIFIER_INFO_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const THREAD_EXTENDED_INFO_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; pub const TASK_THREAD_TIMES_INFO_COUNT: u32 = (::mem::size_of::() / ::mem::size_of::()) as u32; pub const MACH_TASK_BASIC_INFO_COUNT: u32 = (::mem::size_of::() / ::mem::size_of::()) as u32; pub const HOST_VM_INFO64_COUNT: mach_msg_type_number_t = (::mem::size_of::() / ::mem::size_of::()) as mach_msg_type_number_t; } else { pub const THREAD_EXTENDED_POLICY_COUNT: mach_msg_type_number_t = 1; pub const THREAD_TIME_CONSTRAINT_POLICY_COUNT: mach_msg_type_number_t = 4; pub const THREAD_PRECEDENCE_POLICY_COUNT: mach_msg_type_number_t = 1; pub const THREAD_AFFINITY_POLICY_COUNT: mach_msg_type_number_t = 1; pub const THREAD_BACKGROUND_POLICY_COUNT: mach_msg_type_number_t = 1; pub const THREAD_LATENCY_QOS_POLICY_COUNT: mach_msg_type_number_t = 1; pub const THREAD_THROUGHPUT_QOS_POLICY_COUNT: mach_msg_type_number_t = 1; pub const THREAD_BASIC_INFO_COUNT: mach_msg_type_number_t = 10; pub const THREAD_IDENTIFIER_INFO_COUNT: mach_msg_type_number_t = 6; pub const THREAD_EXTENDED_INFO_COUNT: mach_msg_type_number_t = 28; pub const TASK_THREAD_TIMES_INFO_COUNT: u32 = 4; pub const MACH_TASK_BASIC_INFO_COUNT: u32 = 12; pub const HOST_VM_INFO64_COUNT: mach_msg_type_number_t = 38; } } f! { pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr) -> *mut ::cmsghdr { if cmsg.is_null() { return ::CMSG_FIRSTHDR(mhdr); }; let cmsg_len = (*cmsg).cmsg_len as usize; let next = cmsg as usize + __DARWIN_ALIGN32(cmsg_len as usize); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next + __DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) > max { 0 as *mut ::cmsghdr } else { next as *mut ::cmsghdr } } pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(__DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (__DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) + __DARWIN_ALIGN32(length as usize)) as ::c_uint } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { (__DARWIN_ALIGN32(::mem::size_of::<::cmsghdr>()) + length as usize) as ::c_uint } pub {const} fn VM_MAKE_TAG(id: u8) -> u32 { (id as u32) << 24u32 } pub fn major(dev: dev_t) -> i32 { (dev >> 24) & 0xff } pub fn minor(dev: dev_t) -> i32 { dev & 0xffffff } pub fn makedev(major: i32, minor: i32) -> dev_t { (major << 24) | minor } } safe_f! { pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { status >> 8 } pub {const} fn _WSTATUS(status: ::c_int) -> ::c_int { status & 0x7f } pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { _WSTATUS(status) == _WSTOPPED && WSTOPSIG(status) == 0x13 } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { _WSTATUS(status) != _WSTOPPED && _WSTATUS(status) != 0 } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { _WSTATUS(status) == _WSTOPPED && WSTOPSIG(status) != 0x13 } } extern "C" { pub fn setgrent(); #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated in MacOSX 10.5")] #[cfg_attr(not(target_arch = "aarch64"), link_name = "daemon$1050")] pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated in MacOSX 10.10")] pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; #[doc(hidden)] #[deprecated(since = "0.2.49", note = "Deprecated in MacOSX 10.10")] pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_error(aiocbp: *const aiocb) -> ::c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "aio_suspend$UNIX2003" )] pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn chflags(path: *const ::c_char, flags: ::c_uint) -> ::c_int; pub fn fchflags(fd: ::c_int, flags: ::c_uint) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "confstr$UNIX2003" )] pub fn confstr(name: ::c_int, buf: *mut ::c_char, len: ::size_t) -> ::size_t; pub fn lio_listio( mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent, ) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn setutxent(); pub fn endutxent(); pub fn utmpxname(file: *const ::c_char) -> ::c_int; pub fn asctime(tm: *const ::tm) -> *mut ::c_char; pub fn ctime(clock: *const time_t) -> *mut ::c_char; pub fn getdate(datestr: *const ::c_char) -> *mut ::tm; pub fn strptime( buf: *const ::c_char, format: *const ::c_char, timeptr: *mut ::tm, ) -> *mut ::c_char; pub fn asctime_r(tm: *const ::tm, result: *mut ::c_char) -> *mut ::c_char; pub fn ctime_r(clock: *const time_t, result: *mut ::c_char) -> *mut ::c_char; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::socklen_t, serv: *mut ::c_char, servlen: ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn mincore(addr: *const ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; pub fn sysctlnametomib( name: *const ::c_char, mibp: *mut ::c_int, sizep: *mut ::size_t, ) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "mprotect$UNIX2003" )] pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn semget(key: key_t, nsems: ::c_int, semflg: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "semctl$UNIX2003" )] pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn semop(semid: ::c_int, sops: *mut sembuf, nsops: ::size_t) -> ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::c_int; pub fn ftok(pathname: *const c_char, proj_id: ::c_int) -> key_t; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "shmctl$UNIX2003" )] pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn shmget(key: key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn sysctl( name: *mut ::c_int, namelen: ::c_uint, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn sysctlbyname( name: *const ::c_char, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn mach_absolute_time() -> u64; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] #[allow(deprecated)] pub fn mach_timebase_info(info: *mut ::mach_timebase_info) -> ::c_int; pub fn mach_host_self() -> mach_port_t; pub fn mach_thread_self() -> mach_port_t; pub fn pthread_setname_np(name: *const ::c_char) -> ::c_int; pub fn pthread_getname_np(thread: ::pthread_t, name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn pthread_mach_thread_np(thread: ::pthread_t) -> ::mach_port_t; pub fn pthread_from_mach_thread_np(port: ::mach_port_t) -> ::pthread_t; pub fn pthread_create_from_mach_thread( thread: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn pthread_stack_frame_decode_np( frame_addr: ::uintptr_t, return_addr: *mut ::uintptr_t, ) -> ::uintptr_t; pub fn pthread_get_stackaddr_np(thread: ::pthread_t) -> *mut ::c_void; pub fn pthread_get_stacksize_np(thread: ::pthread_t) -> ::size_t; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_main_np() -> ::c_int; pub fn pthread_mutexattr_setpshared( attr: *mut pthread_mutexattr_t, pshared: ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; pub fn pthread_threadid_np(thread: ::pthread_t, thread_id: *mut u64) -> ::c_int; pub fn pthread_attr_set_qos_class_np( attr: *mut pthread_attr_t, class: qos_class_t, priority: ::c_int, ) -> ::c_int; pub fn pthread_attr_get_qos_class_np( attr: *mut pthread_attr_t, class: *mut qos_class_t, priority: *mut ::c_int, ) -> ::c_int; pub fn pthread_set_qos_class_self_np(class: qos_class_t, priority: ::c_int) -> ::c_int; pub fn pthread_get_qos_class_np( thread: ::pthread_t, class: *mut qos_class_t, priority: *mut ::c_int, ) -> ::c_int; pub fn pthread_attr_getschedparam( attr: *const ::pthread_attr_t, param: *mut sched_param, ) -> ::c_int; pub fn pthread_attr_setschedparam( attr: *mut ::pthread_attr_t, param: *const sched_param, ) -> ::c_int; pub fn pthread_getschedparam( thread: ::pthread_t, policy: *mut ::c_int, param: *mut sched_param, ) -> ::c_int; pub fn pthread_setschedparam( thread: ::pthread_t, policy: ::c_int, param: *const sched_param, ) -> ::c_int; // Available from Big Sur pub fn pthread_introspection_hook_install( hook: ::pthread_introspection_hook_t, ) -> ::pthread_introspection_hook_t; pub fn pthread_introspection_setspecific_np( thread: ::pthread_t, key: ::pthread_key_t, value: *const ::c_void, ) -> ::c_int; pub fn pthread_introspection_getspecific_np( thread: ::pthread_t, key: ::pthread_key_t, ) -> *mut ::c_void; pub fn pthread_jit_write_protect_np(enabled: ::c_int); pub fn pthread_jit_write_protect_supported_np() -> ::c_int; // An array of pthread_jit_write_with_callback_np must declare // the list of callbacks e.g. // #[link_section = "__DATA_CONST,__pth_jit_func"] // static callbacks: [libc::pthread_jit_write_callback_t; 2] = [native_jit_write_cb, // std::mem::transmute::(std::ptr::null())]; // (a handy PTHREAD_JIT_WRITE_CALLBACK_NP macro for other languages). pub fn pthread_jit_write_with_callback_np( callback: ::pthread_jit_write_callback_t, ctx: *mut ::c_void, ) -> ::c_int; pub fn pthread_jit_write_freeze_callbacks_np(); pub fn pthread_cpu_number_np(cpu_number_out: *mut ::size_t) -> ::c_int; pub fn os_unfair_lock_lock(lock: os_unfair_lock_t); pub fn os_unfair_lock_trylock(lock: os_unfair_lock_t) -> bool; pub fn os_unfair_lock_unlock(lock: os_unfair_lock_t); pub fn os_unfair_lock_assert_owner(lock: os_unfair_lock_t); pub fn os_unfair_lock_assert_not_owner(lock: os_unfair_lock_t); pub fn os_log_create(subsystem: *const ::c_char, category: *const ::c_char) -> ::os_log_t; pub fn os_log_type_enabled(oslog: ::os_log_t, tpe: ::os_log_type_t) -> bool; pub fn os_signpost_id_make_with_pointer( log: ::os_log_t, ptr: *const ::c_void, ) -> ::os_signpost_id_t; pub fn os_signpost_id_generate(log: ::os_log_t) -> ::os_signpost_id_t; pub fn os_signpost_enabled(log: ::os_log_t) -> bool; pub fn thread_policy_set( thread: thread_t, flavor: thread_policy_flavor_t, policy_info: thread_policy_t, count: mach_msg_type_number_t, ) -> kern_return_t; pub fn thread_policy_get( thread: thread_t, flavor: thread_policy_flavor_t, policy_info: thread_policy_t, count: *mut mach_msg_type_number_t, get_default: *mut boolean_t, ) -> kern_return_t; pub fn thread_info( target_act: thread_inspect_t, flavor: thread_flavor_t, thread_info_out: thread_info_t, thread_info_outCnt: *mut mach_msg_type_number_t, ) -> kern_return_t; #[cfg_attr(doc, doc(alias = "__errno_location"))] #[cfg_attr(doc, doc(alias = "errno"))] pub fn __error() -> *mut ::c_int; pub fn backtrace(buf: *mut *mut ::c_void, sz: ::c_int) -> ::c_int; pub fn backtrace_symbols(addrs: *const *mut ::c_void, sz: ::c_int) -> *mut *mut ::c_char; pub fn backtrace_symbols_fd(addrs: *const *mut ::c_void, sz: ::c_int, fd: ::c_int); pub fn backtrace_from_fp( startfp: *mut ::c_void, array: *mut *mut ::c_void, size: ::c_int, ) -> ::c_int; pub fn backtrace_image_offsets( array: *const *mut ::c_void, image_offsets: *mut image_offset, size: ::c_int, ); pub fn backtrace_async( array: *mut *mut ::c_void, length: ::size_t, task_id: *mut u32, ) -> ::size_t; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "statfs$INODE64" )] pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "fstatfs$INODE64" )] pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn kevent( kq: ::c_int, changelist: *const ::kevent, nchanges: ::c_int, eventlist: *mut ::kevent, nevents: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn kevent64( kq: ::c_int, changelist: *const ::kevent64_s, nchanges: ::c_int, eventlist: *mut ::kevent64_s, nevents: ::c_int, flags: ::c_uint, timeout: *const ::timespec, ) -> ::c_int; pub fn mount( src: *const ::c_char, target: *const ::c_char, flags: ::c_int, data: *mut ::c_void, ) -> ::c_int; pub fn fmount( src: *const ::c_char, fd: ::c_int, flags: ::c_int, data: *mut ::c_void, ) -> ::c_int; pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: *mut ::c_char, data: ::c_int) -> ::c_int; pub fn quotactl( special: *const ::c_char, cmd: ::c_int, id: ::c_int, data: *mut ::c_char, ) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn sendfile( fd: ::c_int, s: ::c_int, offset: ::off_t, len: *mut ::off_t, hdtr: *mut ::sf_hdtr, flags: ::c_int, ) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::c_int; pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::pid_t; pub fn login_tty(fd: ::c_int) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn freelocale(loc: ::locale_t) -> ::c_int; pub fn localeconv_l(loc: ::locale_t) -> *mut lconv; pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn querylocale(mask: ::c_int, loc: ::locale_t) -> *const ::c_char; pub fn getpriority(which: ::c_int, who: ::id_t) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::id_t, prio: ::c_int) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::c_int) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn getxattr( path: *const ::c_char, name: *const ::c_char, value: *mut ::c_void, size: ::size_t, position: u32, flags: ::c_int, ) -> ::ssize_t; pub fn fgetxattr( filedes: ::c_int, name: *const ::c_char, value: *mut ::c_void, size: ::size_t, position: u32, flags: ::c_int, ) -> ::ssize_t; pub fn setxattr( path: *const ::c_char, name: *const ::c_char, value: *const ::c_void, size: ::size_t, position: u32, flags: ::c_int, ) -> ::c_int; pub fn fsetxattr( filedes: ::c_int, name: *const ::c_char, value: *const ::c_void, size: ::size_t, position: u32, flags: ::c_int, ) -> ::c_int; pub fn listxattr( path: *const ::c_char, list: *mut ::c_char, size: ::size_t, flags: ::c_int, ) -> ::ssize_t; pub fn flistxattr( filedes: ::c_int, list: *mut ::c_char, size: ::size_t, flags: ::c_int, ) -> ::ssize_t; pub fn removexattr(path: *const ::c_char, name: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn renamex_np(from: *const ::c_char, to: *const ::c_char, flags: ::c_uint) -> ::c_int; pub fn renameatx_np( fromfd: ::c_int, from: *const ::c_char, tofd: ::c_int, to: *const ::c_char, flags: ::c_uint, ) -> ::c_int; pub fn fremovexattr(filedes: ::c_int, name: *const ::c_char, flags: ::c_int) -> ::c_int; pub fn getgrouplist( name: *const ::c_char, basegid: ::c_int, groups: *mut ::c_int, ngroups: *mut ::c_int, ) -> ::c_int; pub fn initgroups(user: *const ::c_char, basegroup: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "waitid$UNIX2003" )] pub fn waitid(idtype: idtype_t, id: id_t, infop: *mut ::siginfo_t, options: ::c_int) -> ::c_int; pub fn brk(addr: *const ::c_void) -> *mut ::c_void; pub fn sbrk(increment: ::c_int) -> *mut ::c_void; pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn _dyld_image_count() -> u32; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] #[allow(deprecated)] pub fn _dyld_get_image_header(image_index: u32) -> *const mach_header; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn _dyld_get_image_vmaddr_slide(image_index: u32) -> ::intptr_t; #[deprecated(since = "0.2.55", note = "Use the `mach2` crate instead")] pub fn _dyld_get_image_name(image_index: u32) -> *const ::c_char; pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_setarchpref_np( attr: *mut posix_spawnattr_t, count: ::size_t, pref: *mut ::cpu_type_t, subpref: *mut ::cpu_subtype_t, ocount: *mut ::size_t, ) -> ::c_int; pub fn posix_spawnattr_getarchpref_np( attr: *const posix_spawnattr_t, count: ::size_t, pref: *mut ::cpu_type_t, subpref: *mut ::cpu_subtype_t, ocount: *mut ::size_t, ) -> ::c_int; pub fn posix_spawnattr_getbinpref_np( attr: *const posix_spawnattr_t, count: ::size_t, pref: *mut ::cpu_type_t, ocount: *mut ::size_t, ) -> ::c_int; pub fn posix_spawnattr_setbinpref_np( attr: *mut posix_spawnattr_t, count: ::size_t, pref: *mut ::cpu_type_t, ocount: *mut ::size_t, ) -> ::c_int; pub fn posix_spawnattr_set_qos_class_np( attr: *mut posix_spawnattr_t, qos_class: ::qos_class_t, ) -> ::c_int; pub fn posix_spawnattr_get_qos_class_np( attr: *const posix_spawnattr_t, qos_class: *mut ::qos_class_t, ) -> ::c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, newfd: ::c_int, ) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn connectx( socket: ::c_int, endpoints: *const sa_endpoints_t, associd: sae_associd_t, flags: ::c_uint, iov: *const ::iovec, iovcnt: ::c_uint, len: *mut ::size_t, connid: *mut sae_connid_t, ) -> ::c_int; pub fn disconnectx(socket: ::c_int, associd: sae_associd_t, connid: sae_connid_t) -> ::c_int; pub fn ntp_adjtime(buf: *mut timex) -> ::c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "getmntinfo$INODE64" )] pub fn getmntinfo(mntbufp: *mut *mut statfs, flags: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "getfsstat$INODE64" )] pub fn getfsstat(mntbufp: *mut statfs, bufsize: ::c_int, flags: ::c_int) -> ::c_int; // Copy-on-write functions. // According to the man page `flags` is an `int` but in the header // this is a `uint32_t`. pub fn clonefile(src: *const ::c_char, dst: *const ::c_char, flags: u32) -> ::c_int; pub fn clonefileat( src_dirfd: ::c_int, src: *const ::c_char, dst_dirfd: ::c_int, dst: *const ::c_char, flags: u32, ) -> ::c_int; pub fn fclonefileat( srcfd: ::c_int, dst_dirfd: ::c_int, dst: *const ::c_char, flags: u32, ) -> ::c_int; pub fn copyfile( from: *const ::c_char, to: *const ::c_char, state: copyfile_state_t, flags: copyfile_flags_t, ) -> ::c_int; pub fn fcopyfile( from: ::c_int, to: ::c_int, state: copyfile_state_t, flags: copyfile_flags_t, ) -> ::c_int; pub fn copyfile_state_free(s: copyfile_state_t) -> ::c_int; pub fn copyfile_state_alloc() -> copyfile_state_t; pub fn copyfile_state_get(s: copyfile_state_t, flags: u32, dst: *mut ::c_void) -> ::c_int; pub fn copyfile_state_set(s: copyfile_state_t, flags: u32, src: *const ::c_void) -> ::c_int; // Added in macOS 10.13 // ISO/IEC 9899:2011 ("ISO C11") K.3.7.4.1 pub fn memset_s(s: *mut ::c_void, smax: ::size_t, c: ::c_int, n: ::size_t) -> ::c_int; // Added in macOS 10.5 pub fn memset_pattern4(b: *mut ::c_void, pattern4: *const ::c_void, len: ::size_t); pub fn memset_pattern8(b: *mut ::c_void, pattern8: *const ::c_void, len: ::size_t); pub fn memset_pattern16(b: *mut ::c_void, pattern16: *const ::c_void, len: ::size_t); // Inherited from BSD but available from Big Sur only pub fn strtonum( __numstr: *const ::c_char, __minval: ::c_longlong, __maxval: ::c_longlong, errstrp: *mut *const ::c_char, ) -> ::c_longlong; pub fn mstats() -> mstats; pub fn malloc_printf(format: *const ::c_char, ...); pub fn malloc_zone_check(zone: *mut ::malloc_zone_t) -> ::boolean_t; pub fn malloc_zone_print(zone: *mut ::malloc_zone_t, verbose: ::boolean_t); pub fn malloc_zone_statistics(zone: *mut ::malloc_zone_t, stats: *mut malloc_statistics_t); pub fn malloc_zone_log(zone: *mut ::malloc_zone_t, address: *mut ::c_void); pub fn malloc_zone_print_ptr_info(ptr: *mut ::c_void); pub fn malloc_default_zone() -> *mut ::malloc_zone_t; pub fn malloc_zone_from_ptr(ptr: *const ::c_void) -> *mut ::malloc_zone_t; pub fn malloc_zone_malloc(zone: *mut ::malloc_zone_t, size: ::size_t) -> *mut ::c_void; pub fn malloc_zone_valloc(zone: *mut ::malloc_zone_t, size: ::size_t) -> *mut ::c_void; pub fn malloc_zone_calloc( zone: *mut ::malloc_zone_t, num_items: ::size_t, size: ::size_t, ) -> *mut ::c_void; pub fn malloc_zone_realloc( zone: *mut ::malloc_zone_t, ptr: *mut ::c_void, size: ::size_t, ) -> *mut ::c_void; pub fn malloc_zone_free(zone: *mut ::malloc_zone_t, ptr: *mut ::c_void); pub fn proc_listpids( t: u32, typeinfo: u32, buffer: *mut ::c_void, buffersize: ::c_int, ) -> ::c_int; pub fn proc_listallpids(buffer: *mut ::c_void, buffersize: ::c_int) -> ::c_int; pub fn proc_listpgrppids( pgrpid: ::pid_t, buffer: *mut ::c_void, buffersize: ::c_int, ) -> ::c_int; pub fn proc_listchildpids(ppid: ::pid_t, buffer: *mut ::c_void, buffersize: ::c_int) -> ::c_int; pub fn proc_pidinfo( pid: ::c_int, flavor: ::c_int, arg: u64, buffer: *mut ::c_void, buffersize: ::c_int, ) -> ::c_int; pub fn proc_pidfdinfo( pid: ::c_int, fd: ::c_int, flavor: ::c_int, buffer: *mut ::c_void, buffersize: ::c_int, ) -> ::c_int; pub fn proc_pidfileportinfo( pid: ::c_int, fileport: u32, flavor: ::c_int, buffer: *mut ::c_void, buffersize: ::c_int, ) -> ::c_int; pub fn proc_pidpath(pid: ::c_int, buffer: *mut ::c_void, buffersize: u32) -> ::c_int; pub fn proc_name(pid: ::c_int, buffer: *mut ::c_void, buffersize: u32) -> ::c_int; pub fn proc_regionfilename( pid: ::c_int, address: u64, buffer: *mut ::c_void, buffersize: u32, ) -> ::c_int; pub fn proc_kmsgbuf(buffer: *mut ::c_void, buffersize: u32) -> ::c_int; pub fn proc_libversion(major: *mut ::c_int, minor: *mut ::c_int) -> ::c_int; pub fn proc_pid_rusage(pid: ::c_int, flavor: ::c_int, buffer: *mut rusage_info_t) -> ::c_int; // Available from Big Sur pub fn proc_set_no_smt() -> ::c_int; pub fn proc_setthread_no_smt() -> ::c_int; pub fn proc_set_csm(flags: u32) -> ::c_int; pub fn proc_setthread_csm(flags: u32) -> ::c_int; /// # Notes /// /// `id` is of type [`uuid_t`]. pub fn gethostuuid(id: *mut u8, timeout: *const ::timespec) -> ::c_int; pub fn gethostid() -> ::c_long; pub fn sethostid(hostid: ::c_long); pub fn CCRandomGenerateBytes(bytes: *mut ::c_void, size: ::size_t) -> ::CCRNGStatus; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; pub fn _NSGetExecutablePath(buf: *mut ::c_char, bufsize: *mut u32) -> ::c_int; pub fn _NSGetEnviron() -> *mut *mut *mut ::c_char; pub fn mach_vm_map( target_task: ::vm_map_t, address: *mut ::mach_vm_address_t, size: ::mach_vm_size_t, mask: ::mach_vm_offset_t, flags: ::c_int, object: ::mem_entry_name_port_t, offset: ::memory_object_offset_t, copy: ::boolean_t, cur_protection: ::vm_prot_t, max_protection: ::vm_prot_t, inheritance: ::vm_inherit_t, ) -> ::kern_return_t; pub fn vm_allocate( target_task: vm_map_t, address: *mut vm_address_t, size: vm_size_t, flags: ::c_int, ) -> ::kern_return_t; pub fn vm_deallocate( target_task: vm_map_t, address: vm_address_t, size: vm_size_t, ) -> ::kern_return_t; pub fn host_statistics64( host_priv: host_t, flavor: host_flavor_t, host_info64_out: host_info64_t, host_info64_outCnt: *mut mach_msg_type_number_t, ) -> ::kern_return_t; pub fn host_processor_info( host: host_t, flavor: processor_flavor_t, out_processor_count: *mut natural_t, out_processor_info: *mut processor_info_array_t, out_processor_infoCnt: *mut mach_msg_type_number_t, ) -> ::kern_return_t; pub static mut mach_task_self_: ::mach_port_t; pub fn task_for_pid( host: ::mach_port_t, pid: ::pid_t, task: *mut ::mach_port_t, ) -> ::kern_return_t; pub fn task_info( host: ::mach_port_t, flavor: task_flavor_t, task_info_out: task_info_t, task_info_count: *mut mach_msg_type_number_t, ) -> ::kern_return_t; pub fn task_create( target_task: ::task_t, ledgers: ::ledger_array_t, ledgersCnt: ::mach_msg_type_number_t, inherit_memory: ::boolean_t, child_task: *mut ::task_t, ) -> ::kern_return_t; pub fn task_terminate(target_task: ::task_t) -> ::kern_return_t; pub fn task_threads( target_task: ::task_inspect_t, act_list: *mut ::thread_act_array_t, act_listCnt: *mut ::mach_msg_type_number_t, ) -> ::kern_return_t; pub fn host_statistics( host_priv: host_t, flavor: host_flavor_t, host_info_out: host_info_t, host_info_outCnt: *mut mach_msg_type_number_t, ) -> ::kern_return_t; // sysdir.h pub fn sysdir_start_search_path_enumeration( dir: sysdir_search_path_directory_t, domainMask: sysdir_search_path_domain_mask_t, ) -> ::sysdir_search_path_enumeration_state; pub fn sysdir_get_next_search_path_enumeration( state: ::sysdir_search_path_enumeration_state, path: *mut ::c_char, ) -> ::sysdir_search_path_enumeration_state; pub static vm_page_size: vm_size_t; pub fn getattrlist( path: *const ::c_char, attrList: *mut ::c_void, attrBuf: *mut ::c_void, attrBufSize: ::size_t, options: u32, ) -> ::c_int; pub fn fgetattrlist( fd: ::c_int, attrList: *mut ::c_void, attrBuf: *mut ::c_void, attrBufSize: ::size_t, options: u32, ) -> ::c_int; pub fn getattrlistat( fd: ::c_int, path: *const ::c_char, attrList: *mut ::c_void, attrBuf: *mut ::c_void, attrBufSize: ::size_t, options: ::c_ulong, ) -> ::c_int; pub fn setattrlist( path: *const ::c_char, attrList: *mut ::c_void, attrBuf: *mut ::c_void, attrBufSize: ::size_t, options: u32, ) -> ::c_int; pub fn fsetattrlist( fd: ::c_int, attrList: *mut ::c_void, attrBuf: *mut ::c_void, attrBufSize: ::size_t, options: u32, ) -> ::c_int; pub fn setattrlistat( dir_fd: ::c_int, path: *const ::c_char, attrList: *mut ::c_void, attrBuf: *mut ::c_void, attrBufSize: ::size_t, options: u32, ) -> ::c_int; pub fn getattrlistbulk( dirfd: ::c_int, attrList: *mut ::c_void, attrBuf: *mut ::c_void, attrBufSize: ::size_t, options: u64, ) -> ::c_int; pub fn malloc_size(ptr: *const ::c_void) -> ::size_t; pub fn malloc_good_size(size: ::size_t) -> ::size_t; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn freadlink(fd: ::c_int, buf: *mut ::c_char, size: ::size_t) -> ::c_int; pub fn execvP( file: *const ::c_char, search_path: *const ::c_char, argv: *const *mut ::c_char, ) -> ::c_int; } pub unsafe fn mach_task_self() -> ::mach_port_t { mach_task_self_ } cfg_if! { if #[cfg(target_os = "macos")] { extern "C" { pub fn clock_settime(clock_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; } } } cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "visionos"))] { extern "C" { pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; pub fn task_set_info(target_task: ::task_t, flavor: ::task_flavor_t, task_info_in: ::task_info_t, task_info_inCnt: ::mach_msg_type_number_t ) -> ::kern_return_t; } } } // These require a dependency on `libiconv`, and including this when built as // part of `std` means every Rust program gets it. Ideally we would have a link // modifier to only include these if they are used, but we do not. #[cfg_attr(not(feature = "rustc-dep-of-std"), link(name = "iconv"))] extern "C" { pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, inbytesleft: *mut ::size_t, outbuf: *mut *mut ::c_char, outbytesleft: *mut ::size_t, ) -> ::size_t; pub fn iconv_close(cd: iconv_t) -> ::c_int; } cfg_if! { if #[cfg(target_pointer_width = "32")] { mod b32; pub use self::b32::*; } else if #[cfg(target_pointer_width = "64")] { mod b64; pub use self::b64::*; } else { // Unknown target_arch } } cfg_if! { if #[cfg(libc_long_array)] { mod long_array; pub use self::long_array::*; } } libc/src/unix/bsd/apple/b64/0000775000175000017500000000000014661133735016472 5ustar jamespagejamespagelibc/src/unix/bsd/apple/b64/aarch64/0000775000175000017500000000000014661133735017722 5ustar jamespagejamespagelibc/src/unix/bsd/apple/b64/aarch64/mod.rs0000644000175000017500000000037714661133735021054 0ustar jamespagejamespagepub type boolean_t = ::c_int; s! { pub struct malloc_zone_t { __private: [::uintptr_t; 18], // FIXME: needs arm64 auth pointers support } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/bsd/apple/b64/aarch64/align.rs0000644000175000017500000000270614661133735021365 0ustar jamespagejamespagepub type mcontext_t = *mut __darwin_mcontext64; s_no_extra_traits! { #[allow(missing_debug_implementations)] pub struct max_align_t { priv_: f64 } } s! { pub struct ucontext_t { pub uc_onstack: ::c_int, pub uc_sigmask: ::sigset_t, pub uc_stack: ::stack_t, pub uc_link: *mut ::ucontext_t, pub uc_mcsize: usize, pub uc_mcontext: mcontext_t, } pub struct __darwin_mcontext64 { pub __es: __darwin_arm_exception_state64, pub __ss: __darwin_arm_thread_state64, pub __ns: __darwin_arm_neon_state64, } pub struct __darwin_arm_exception_state64 { pub __far: u64, pub __esr: u32, pub __exception: u32, } pub struct __darwin_arm_thread_state64 { pub __x: [u64; 29], pub __fp: u64, pub __lr: u64, pub __sp: u64, pub __pc: u64, pub __cpsr: u32, pub __pad: u32, } // This type natively uses a uint128, but for a while we hacked // it in with repr(align) and `[u64; 2]`. uint128 isn't available // all the way back to our earliest supported versions so we // preserver the old shim. #[cfg_attr(not(libc_int128), repr(align(16)))] pub struct __darwin_arm_neon_state64 { #[cfg(libc_int128)] pub __v: [::__uint128_t; 32], #[cfg(not(libc_int128))] pub __v: [[u64; 2]; 32], pub __fpsr: u32, pub __fpcr: u32, } } libc/src/unix/bsd/apple/b64/mod.rs0000644000175000017500000000655214661133735017625 0ustar jamespagejamespage//! 64-bit specific Apple (ios/darwin) definitions pub type c_long = i64; pub type c_ulong = u64; s! { pub struct timeval32 { pub tv_sec: i32, pub tv_usec: i32, } pub struct if_data { pub ifi_type: ::c_uchar, pub ifi_typelen: ::c_uchar, pub ifi_physical: ::c_uchar, pub ifi_addrlen: ::c_uchar, pub ifi_hdrlen: ::c_uchar, pub ifi_recvquota: ::c_uchar, pub ifi_xmitquota: ::c_uchar, pub ifi_unused1: ::c_uchar, pub ifi_mtu: u32, pub ifi_metric: u32, pub ifi_baudrate: u32, pub ifi_ipackets: u32, pub ifi_ierrors: u32, pub ifi_opackets: u32, pub ifi_oerrors: u32, pub ifi_collisions: u32, pub ifi_ibytes: u32, pub ifi_obytes: u32, pub ifi_imcasts: u32, pub ifi_omcasts: u32, pub ifi_iqdrops: u32, pub ifi_noproto: u32, pub ifi_recvtiming: u32, pub ifi_xmittiming: u32, pub ifi_lastchange: timeval32, pub ifi_unused2: u32, pub ifi_hwassist: u32, pub ifi_reserved1: u32, pub ifi_reserved2: u32, } pub struct bpf_hdr { pub bh_tstamp: ::timeval32, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: ::c_ushort, } } s_no_extra_traits! { pub struct pthread_attr_t { __sig: c_long, __opaque: [::c_char; 56] } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for pthread_attr_t { fn eq(&self, other: &pthread_attr_t) -> bool { self.__sig == other.__sig && self.__opaque .iter() .zip(other.__opaque.iter()) .all(|(a,b)| a == b) } } impl Eq for pthread_attr_t {} impl ::fmt::Debug for pthread_attr_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("pthread_attr_t") .field("__sig", &self.__sig) // FIXME: .field("__opaque", &self.__opaque) .finish() } } impl ::hash::Hash for pthread_attr_t { fn hash(&self, state: &mut H) { self.__sig.hash(state); self.__opaque.hash(state); } } } } #[doc(hidden)] #[deprecated(since = "0.2.55")] pub const NET_RT_MAXID: ::c_int = 11; pub const __PTHREAD_MUTEX_SIZE__: usize = 56; pub const __PTHREAD_COND_SIZE__: usize = 40; pub const __PTHREAD_CONDATTR_SIZE__: usize = 8; pub const __PTHREAD_RWLOCK_SIZE__: usize = 192; pub const __PTHREAD_RWLOCKATTR_SIZE__: usize = 16; pub const TIOCTIMESTAMP: ::c_ulong = 0x40107459; pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40107458; pub const BIOCSETF: ::c_ulong = 0x80104267; pub const BIOCSRTIMEOUT: ::c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: ::c_ulong = 0x4010426e; pub const BIOCSETFNR: ::c_ulong = 0x8010427e; extern "C" { pub fn exchangedata( path1: *const ::c_char, path2: *const ::c_char, options: ::c_uint, ) -> ::c_int; } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/apple/b64/align.rs0000644000175000017500000000022514661133735020127 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 2] } } libc/src/unix/bsd/apple/b64/x86_64/0000775000175000017500000000000014661133735017430 5ustar jamespagejamespagelibc/src/unix/bsd/apple/b64/x86_64/mod.rs0000644000175000017500000001312514661133735020555 0ustar jamespagejamespagepub type boolean_t = ::c_uint; pub type mcontext_t = *mut __darwin_mcontext64; s! { pub struct ucontext_t { pub uc_onstack: ::c_int, pub uc_sigmask: ::sigset_t, pub uc_stack: ::stack_t, pub uc_link: *mut ::ucontext_t, pub uc_mcsize: usize, pub uc_mcontext: mcontext_t, } pub struct __darwin_mcontext64 { pub __es: __darwin_x86_exception_state64, pub __ss: __darwin_x86_thread_state64, pub __fs: __darwin_x86_float_state64, } pub struct __darwin_x86_exception_state64 { pub __trapno: u16, pub __cpu: u16, pub __err: u32, pub __faultvaddr: u64, } pub struct __darwin_x86_thread_state64 { pub __rax: u64, pub __rbx: u64, pub __rcx: u64, pub __rdx: u64, pub __rdi: u64, pub __rsi: u64, pub __rbp: u64, pub __rsp: u64, pub __r8: u64, pub __r9: u64, pub __r10: u64, pub __r11: u64, pub __r12: u64, pub __r13: u64, pub __r14: u64, pub __r15: u64, pub __rip: u64, pub __rflags: u64, pub __cs: u64, pub __fs: u64, pub __gs: u64, } pub struct __darwin_x86_float_state64 { pub __fpu_reserved: [::c_int; 2], __fpu_fcw: ::c_short, __fpu_fsw: ::c_short, pub __fpu_ftw: u8, pub __fpu_rsrv1: u8, pub __fpu_fop: u16, pub __fpu_ip: u32, pub __fpu_cs: u16, pub __fpu_rsrv2: u16, pub __fpu_dp: u32, pub __fpu_ds: u16, pub __fpu_rsrv3: u16, pub __fpu_mxcsr: u32, pub __fpu_mxcsrmask: u32, pub __fpu_stmm0: __darwin_mmst_reg, pub __fpu_stmm1: __darwin_mmst_reg, pub __fpu_stmm2: __darwin_mmst_reg, pub __fpu_stmm3: __darwin_mmst_reg, pub __fpu_stmm4: __darwin_mmst_reg, pub __fpu_stmm5: __darwin_mmst_reg, pub __fpu_stmm6: __darwin_mmst_reg, pub __fpu_stmm7: __darwin_mmst_reg, pub __fpu_xmm0: __darwin_xmm_reg, pub __fpu_xmm1: __darwin_xmm_reg, pub __fpu_xmm2: __darwin_xmm_reg, pub __fpu_xmm3: __darwin_xmm_reg, pub __fpu_xmm4: __darwin_xmm_reg, pub __fpu_xmm5: __darwin_xmm_reg, pub __fpu_xmm6: __darwin_xmm_reg, pub __fpu_xmm7: __darwin_xmm_reg, pub __fpu_xmm8: __darwin_xmm_reg, pub __fpu_xmm9: __darwin_xmm_reg, pub __fpu_xmm10: __darwin_xmm_reg, pub __fpu_xmm11: __darwin_xmm_reg, pub __fpu_xmm12: __darwin_xmm_reg, pub __fpu_xmm13: __darwin_xmm_reg, pub __fpu_xmm14: __darwin_xmm_reg, pub __fpu_xmm15: __darwin_xmm_reg, // this field is actually [u8; 96], but defining it with a bigger type // allows us to auto-implement traits for it since the length of the // array is less than 32 __fpu_rsrv4: [u32; 24], pub __fpu_reserved1: ::c_int, } pub struct __darwin_mmst_reg { pub __mmst_reg: [::c_char; 10], pub __mmst_rsrv: [::c_char; 6], } pub struct __darwin_xmm_reg { pub __xmm_reg: [::c_char; 16], } pub struct malloc_introspection_t { _private: [::uintptr_t; 16], // FIXME: keeping private for now } pub struct malloc_zone_t { _reserved1: *mut ::c_void, _reserved2: *mut ::c_void, pub size: ::Option ::size_t>, pub malloc: ::Option *mut ::c_void>, pub calloc: ::Option *mut ::c_void>, pub valloc: ::Option *mut ::c_void>, pub free: ::Option, pub realloc: ::Option *mut ::c_void>, pub destroy: ::Option, pub zone_name: *const ::c_char, pub batch_malloc: ::Option ::c_uint>, pub batch_free: ::Option, pub introspect: *mut malloc_introspection_t, pub version: ::c_uint, pub memalign: ::Option *mut ::c_void>, pub free_definite_size: ::Option, pub pressure_relief: ::Option ::size_t>, pub claimed_address: ::Option ::boolean_t>, } } cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/bsd/apple/b64/x86_64/align.rs0000644000175000017500000000022514661133735021065 0ustar jamespagejamespages_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 2] } } libc/src/unix/bsd/mod.rs0000644000175000017500000007331114661133735016126 0ustar jamespagejamespagepub type off_t = i64; pub type useconds_t = u32; pub type blkcnt_t = i64; pub type socklen_t = u32; pub type sa_family_t = u8; pub type pthread_t = ::uintptr_t; pub type nfds_t = ::c_uint; pub type regoff_t = off_t; s! { pub struct sockaddr { pub sa_len: u8, pub sa_family: sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct passwd { pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_change: ::time_t, pub pw_class: *mut ::c_char, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, pub pw_expire: ::time_t, #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos", target_os = "netbsd", target_os = "openbsd")))] pub pw_fields: ::c_int, } pub struct ifaddrs { pub ifa_next: *mut ifaddrs, pub ifa_name: *mut ::c_char, pub ifa_flags: ::c_uint, pub ifa_addr: *mut ::sockaddr, pub ifa_netmask: *mut ::sockaddr, pub ifa_dstaddr: *mut ::sockaddr, pub ifa_data: *mut ::c_void, #[cfg(target_os = "netbsd")] pub ifa_addrflags: ::c_uint } pub struct fd_set { #[cfg(all(target_pointer_width = "64", any(target_os = "freebsd", target_os = "dragonfly")))] fds_bits: [i64; FD_SETSIZE / 64], #[cfg(not(all(target_pointer_width = "64", any(target_os = "freebsd", target_os = "dragonfly"))))] fds_bits: [i32; FD_SETSIZE / 32], } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, pub tm_gmtoff: ::c_long, pub tm_zone: *mut ::c_char, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct fsid_t { __fsid_val: [i32; 2], } pub struct if_nameindex { pub if_index: ::c_uint, pub if_name: *mut ::c_char, } pub struct regex_t { __re_magic: ::c_int, __re_nsub: ::size_t, __re_endp: *const ::c_char, __re_g: *mut ::c_void, } pub struct regmatch_t { pub rm_so: regoff_t, pub rm_eo: regoff_t, } pub struct option { pub name: *const ::c_char, pub has_arg: ::c_int, pub flag: *mut ::c_int, pub val: ::c_int, } } s_no_extra_traits! { pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [c_char; 104] } pub struct utsname { #[cfg(not(target_os = "dragonfly"))] pub sysname: [::c_char; 256], #[cfg(target_os = "dragonfly")] pub sysname: [::c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub nodename: [::c_char; 256], #[cfg(target_os = "dragonfly")] pub nodename: [::c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub release: [::c_char; 256], #[cfg(target_os = "dragonfly")] pub release: [::c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub version: [::c_char; 256], #[cfg(target_os = "dragonfly")] pub version: [::c_char; 32], #[cfg(not(target_os = "dragonfly"))] pub machine: [::c_char; 256], #[cfg(target_os = "dragonfly")] pub machine: [::c_char; 32], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_un { fn eq(&self, other: &sockaddr_un) -> bool { self.sun_len == other.sun_len && self.sun_family == other.sun_family && self .sun_path .iter() .zip(other.sun_path.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_un {} impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) // FIXME: .field("sun_path", &self.sun_path) .finish() } } impl ::hash::Hash for sockaddr_un { fn hash(&self, state: &mut H) { self.sun_len.hash(state); self.sun_family.hash(state); self.sun_path.hash(state); } } impl PartialEq for utsname { fn eq(&self, other: &utsname) -> bool { self.sysname .iter() .zip(other.sysname.iter()) .all(|(a,b)| a == b) && self .nodename .iter() .zip(other.nodename.iter()) .all(|(a,b)| a == b) && self .release .iter() .zip(other.release.iter()) .all(|(a,b)| a == b) && self .version .iter() .zip(other.version.iter()) .all(|(a,b)| a == b) && self .machine .iter() .zip(other.machine.iter()) .all(|(a,b)| a == b) } } impl Eq for utsname {} impl ::fmt::Debug for utsname { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utsname") // FIXME: .field("sysname", &self.sysname) // FIXME: .field("nodename", &self.nodename) // FIXME: .field("release", &self.release) // FIXME: .field("version", &self.version) // FIXME: .field("machine", &self.machine) .finish() } } impl ::hash::Hash for utsname { fn hash(&self, state: &mut H) { self.sysname.hash(state); self.nodename.hash(state); self.release.hash(state); self.version.hash(state); self.machine.hash(state); } } } } pub const LC_ALL: ::c_int = 0; pub const LC_COLLATE: ::c_int = 1; pub const LC_CTYPE: ::c_int = 2; pub const LC_MONETARY: ::c_int = 3; pub const LC_NUMERIC: ::c_int = 4; pub const LC_TIME: ::c_int = 5; pub const LC_MESSAGES: ::c_int = 6; pub const FIOCLEX: ::c_ulong = 0x20006601; pub const FIONCLEX: ::c_ulong = 0x20006602; pub const FIONREAD: ::c_ulong = 0x4004667f; pub const FIONBIO: ::c_ulong = 0x8004667e; pub const FIOASYNC: ::c_ulong = 0x8004667d; pub const FIOSETOWN: ::c_ulong = 0x8004667c; pub const FIOGETOWN: ::c_ulong = 0x4004667b; pub const PATH_MAX: ::c_int = 1024; pub const MAXPATHLEN: ::c_int = PATH_MAX; pub const IOV_MAX: ::c_int = 1024; pub const SA_ONSTACK: ::c_int = 0x0001; pub const SA_SIGINFO: ::c_int = 0x0040; pub const SA_RESTART: ::c_int = 0x0002; pub const SA_RESETHAND: ::c_int = 0x0004; pub const SA_NOCLDSTOP: ::c_int = 0x0008; pub const SA_NODEFER: ::c_int = 0x0010; pub const SA_NOCLDWAIT: ::c_int = 0x0020; pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 4; pub const SIGCHLD: ::c_int = 20; pub const SIGBUS: ::c_int = 10; pub const SIGUSR1: ::c_int = 30; pub const SIGUSR2: ::c_int = 31; pub const SIGCONT: ::c_int = 19; pub const SIGSTOP: ::c_int = 17; pub const SIGTSTP: ::c_int = 18; pub const SIGURG: ::c_int = 16; pub const SIGIO: ::c_int = 23; pub const SIGSYS: ::c_int = 12; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGINFO: ::c_int = 29; pub const SIG_SETMASK: ::c_int = 3; pub const SIG_BLOCK: ::c_int = 0x1; pub const SIG_UNBLOCK: ::c_int = 0x2; pub const IP_TOS: ::c_int = 3; pub const IP_MULTICAST_IF: ::c_int = 9; pub const IP_MULTICAST_TTL: ::c_int = 10; pub const IP_MULTICAST_LOOP: ::c_int = 11; pub const IPV6_UNICAST_HOPS: ::c_int = 4; pub const IPV6_MULTICAST_IF: ::c_int = 9; pub const IPV6_MULTICAST_HOPS: ::c_int = 10; pub const IPV6_MULTICAST_LOOP: ::c_int = 11; pub const IPV6_V6ONLY: ::c_int = 27; pub const IPTOS_ECN_NOTECT: u8 = 0x00; pub const IPTOS_ECN_MASK: u8 = 0x03; pub const IPTOS_ECN_ECT1: u8 = 0x01; pub const IPTOS_ECN_ECT0: u8 = 0x02; pub const IPTOS_ECN_CE: u8 = 0x03; pub const ST_RDONLY: ::c_ulong = 1; pub const SCM_RIGHTS: ::c_int = 0x01; pub const NCCS: usize = 20; pub const O_ACCMODE: ::c_int = 0x3; pub const O_RDONLY: ::c_int = 0; pub const O_WRONLY: ::c_int = 1; pub const O_RDWR: ::c_int = 2; pub const O_APPEND: ::c_int = 8; pub const O_CREAT: ::c_int = 512; pub const O_TRUNC: ::c_int = 1024; pub const O_EXCL: ::c_int = 2048; pub const O_ASYNC: ::c_int = 0x40; pub const O_SYNC: ::c_int = 0x80; pub const O_NONBLOCK: ::c_int = 0x4; pub const O_NOFOLLOW: ::c_int = 0x100; pub const O_SHLOCK: ::c_int = 0x10; pub const O_EXLOCK: ::c_int = 0x20; pub const O_FSYNC: ::c_int = O_SYNC; pub const O_NDELAY: ::c_int = O_NONBLOCK; pub const F_GETOWN: ::c_int = 5; pub const F_SETOWN: ::c_int = 6; pub const F_RDLCK: ::c_short = 1; pub const F_UNLCK: ::c_short = 2; pub const F_WRLCK: ::c_short = 3; pub const MNT_RDONLY: ::c_int = 0x00000001; pub const MNT_SYNCHRONOUS: ::c_int = 0x00000002; pub const MNT_NOEXEC: ::c_int = 0x00000004; pub const MNT_NOSUID: ::c_int = 0x00000008; pub const MNT_ASYNC: ::c_int = 0x00000040; pub const MNT_EXPORTED: ::c_int = 0x00000100; pub const MNT_UPDATE: ::c_int = 0x00010000; pub const MNT_RELOAD: ::c_int = 0x00040000; pub const MNT_FORCE: ::c_int = 0x00080000; pub const Q_SYNC: ::c_int = 0x600; pub const Q_QUOTAON: ::c_int = 0x100; pub const Q_QUOTAOFF: ::c_int = 0x200; pub const TCIOFF: ::c_int = 3; pub const TCION: ::c_int = 4; pub const TCOOFF: ::c_int = 1; pub const TCOON: ::c_int = 2; pub const TCIFLUSH: ::c_int = 1; pub const TCOFLUSH: ::c_int = 2; pub const TCIOFLUSH: ::c_int = 3; pub const TCSANOW: ::c_int = 0; pub const TCSADRAIN: ::c_int = 1; pub const TCSAFLUSH: ::c_int = 2; pub const VEOF: usize = 0; pub const VEOL: usize = 1; pub const VEOL2: usize = 2; pub const VERASE: usize = 3; pub const VWERASE: usize = 4; pub const VKILL: usize = 5; pub const VREPRINT: usize = 6; pub const VINTR: usize = 8; pub const VQUIT: usize = 9; pub const VSUSP: usize = 10; pub const VDSUSP: usize = 11; pub const VSTART: usize = 12; pub const VSTOP: usize = 13; pub const VLNEXT: usize = 14; pub const VDISCARD: usize = 15; pub const VMIN: usize = 16; pub const VTIME: usize = 17; pub const VSTATUS: usize = 18; pub const _POSIX_VDISABLE: ::cc_t = 0xff; pub const IGNBRK: ::tcflag_t = 0x00000001; pub const BRKINT: ::tcflag_t = 0x00000002; pub const IGNPAR: ::tcflag_t = 0x00000004; pub const PARMRK: ::tcflag_t = 0x00000008; pub const INPCK: ::tcflag_t = 0x00000010; pub const ISTRIP: ::tcflag_t = 0x00000020; pub const INLCR: ::tcflag_t = 0x00000040; pub const IGNCR: ::tcflag_t = 0x00000080; pub const ICRNL: ::tcflag_t = 0x00000100; pub const IXON: ::tcflag_t = 0x00000200; pub const IXOFF: ::tcflag_t = 0x00000400; pub const IXANY: ::tcflag_t = 0x00000800; pub const IMAXBEL: ::tcflag_t = 0x00002000; pub const OPOST: ::tcflag_t = 0x1; pub const ONLCR: ::tcflag_t = 0x2; pub const OXTABS: ::tcflag_t = 0x4; pub const ONOEOT: ::tcflag_t = 0x8; pub const CIGNORE: ::tcflag_t = 0x00000001; pub const CSIZE: ::tcflag_t = 0x00000300; pub const CS5: ::tcflag_t = 0x00000000; pub const CS6: ::tcflag_t = 0x00000100; pub const CS7: ::tcflag_t = 0x00000200; pub const CS8: ::tcflag_t = 0x00000300; pub const CSTOPB: ::tcflag_t = 0x00000400; pub const CREAD: ::tcflag_t = 0x00000800; pub const PARENB: ::tcflag_t = 0x00001000; pub const PARODD: ::tcflag_t = 0x00002000; pub const HUPCL: ::tcflag_t = 0x00004000; pub const CLOCAL: ::tcflag_t = 0x00008000; pub const ECHOKE: ::tcflag_t = 0x00000001; pub const ECHOE: ::tcflag_t = 0x00000002; pub const ECHOK: ::tcflag_t = 0x00000004; pub const ECHO: ::tcflag_t = 0x00000008; pub const ECHONL: ::tcflag_t = 0x00000010; pub const ECHOPRT: ::tcflag_t = 0x00000020; pub const ECHOCTL: ::tcflag_t = 0x00000040; pub const ISIG: ::tcflag_t = 0x00000080; pub const ICANON: ::tcflag_t = 0x00000100; pub const ALTWERASE: ::tcflag_t = 0x00000200; pub const IEXTEN: ::tcflag_t = 0x00000400; pub const EXTPROC: ::tcflag_t = 0x00000800; pub const TOSTOP: ::tcflag_t = 0x00400000; pub const FLUSHO: ::tcflag_t = 0x00800000; pub const NOKERNINFO: ::tcflag_t = 0x02000000; pub const PENDIN: ::tcflag_t = 0x20000000; pub const NOFLSH: ::tcflag_t = 0x80000000; pub const MDMBUF: ::tcflag_t = 0x00100000; pub const WNOHANG: ::c_int = 0x00000001; pub const WUNTRACED: ::c_int = 0x00000002; pub const RTLD_LAZY: ::c_int = 0x1; pub const RTLD_NOW: ::c_int = 0x2; pub const RTLD_NEXT: *mut ::c_void = -1isize as *mut ::c_void; pub const RTLD_DEFAULT: *mut ::c_void = -2isize as *mut ::c_void; pub const RTLD_SELF: *mut ::c_void = -3isize as *mut ::c_void; pub const LOG_CRON: ::c_int = 9 << 3; pub const LOG_AUTHPRIV: ::c_int = 10 << 3; pub const LOG_FTP: ::c_int = 11 << 3; pub const LOG_PERROR: ::c_int = 0x20; pub const TCP_NODELAY: ::c_int = 1; pub const TCP_MAXSEG: ::c_int = 2; pub const PIPE_BUF: usize = 512; // si_code values for SIGBUS signal pub const BUS_ADRALN: ::c_int = 1; pub const BUS_ADRERR: ::c_int = 2; pub const BUS_OBJERR: ::c_int = 3; // si_code values for SIGCHLD signal pub const CLD_EXITED: ::c_int = 1; pub const CLD_KILLED: ::c_int = 2; pub const CLD_DUMPED: ::c_int = 3; pub const CLD_TRAPPED: ::c_int = 4; pub const CLD_STOPPED: ::c_int = 5; pub const CLD_CONTINUED: ::c_int = 6; pub const POLLIN: ::c_short = 0x1; pub const POLLPRI: ::c_short = 0x2; pub const POLLOUT: ::c_short = 0x4; pub const POLLERR: ::c_short = 0x8; pub const POLLHUP: ::c_short = 0x10; pub const POLLNVAL: ::c_short = 0x20; pub const POLLRDNORM: ::c_short = 0x040; pub const POLLWRNORM: ::c_short = 0x004; pub const POLLRDBAND: ::c_short = 0x080; pub const POLLWRBAND: ::c_short = 0x100; pub const BIOCGBLEN: ::c_ulong = 0x40044266; pub const BIOCSBLEN: ::c_ulong = 0xc0044266; pub const BIOCFLUSH: ::c_uint = 0x20004268; pub const BIOCPROMISC: ::c_uint = 0x20004269; pub const BIOCGDLT: ::c_ulong = 0x4004426a; pub const BIOCGETIF: ::c_ulong = 0x4020426b; pub const BIOCSETIF: ::c_ulong = 0x8020426c; pub const BIOCGSTATS: ::c_ulong = 0x4008426f; pub const BIOCIMMEDIATE: ::c_ulong = 0x80044270; pub const BIOCVERSION: ::c_ulong = 0x40044271; pub const BIOCGHDRCMPLT: ::c_ulong = 0x40044274; pub const BIOCSHDRCMPLT: ::c_ulong = 0x80044275; pub const SIOCGIFADDR: ::c_ulong = 0xc0206921; pub const REG_BASIC: ::c_int = 0o0000; pub const REG_EXTENDED: ::c_int = 0o0001; pub const REG_ICASE: ::c_int = 0o0002; pub const REG_NOSUB: ::c_int = 0o0004; pub const REG_NEWLINE: ::c_int = 0o0010; pub const REG_NOSPEC: ::c_int = 0o0020; pub const REG_PEND: ::c_int = 0o0040; pub const REG_DUMP: ::c_int = 0o0200; pub const REG_NOMATCH: ::c_int = 1; pub const REG_BADPAT: ::c_int = 2; pub const REG_ECOLLATE: ::c_int = 3; pub const REG_ECTYPE: ::c_int = 4; pub const REG_EESCAPE: ::c_int = 5; pub const REG_ESUBREG: ::c_int = 6; pub const REG_EBRACK: ::c_int = 7; pub const REG_EPAREN: ::c_int = 8; pub const REG_EBRACE: ::c_int = 9; pub const REG_BADBR: ::c_int = 10; pub const REG_ERANGE: ::c_int = 11; pub const REG_ESPACE: ::c_int = 12; pub const REG_BADRPT: ::c_int = 13; pub const REG_EMPTY: ::c_int = 14; pub const REG_ASSERT: ::c_int = 15; pub const REG_INVARG: ::c_int = 16; pub const REG_ATOI: ::c_int = 255; pub const REG_ITOA: ::c_int = 0o0400; pub const REG_NOTBOL: ::c_int = 0o00001; pub const REG_NOTEOL: ::c_int = 0o00002; pub const REG_STARTEND: ::c_int = 0o00004; pub const REG_TRACE: ::c_int = 0o00400; pub const REG_LARGE: ::c_int = 0o01000; pub const REG_BACKR: ::c_int = 0o02000; pub const TIOCCBRK: ::c_uint = 0x2000747a; pub const TIOCSBRK: ::c_uint = 0x2000747b; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; pub const ITIMER_REAL: ::c_int = 0; pub const ITIMER_VIRTUAL: ::c_int = 1; pub const ITIMER_PROF: ::c_int = 2; f! { pub fn CMSG_FIRSTHDR(mhdr: *const ::msghdr) -> *mut ::cmsghdr { if (*mhdr).msg_controllen as usize >= ::mem::size_of::<::cmsghdr>() { (*mhdr).msg_control as *mut ::cmsghdr } else { 0 as *mut ::cmsghdr } } pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } safe_f! { pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { status & 0o177 } pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0o177) == 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { status >> 8 } pub {const} fn WCOREDUMP(status: ::c_int) -> bool { (status & 0o200) != 0 } pub {const} fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int { (cmd << 8) | (type_ & 0x00ff) } } extern "C" { #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getrlimit$UNIX2003" )] pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "setrlimit$UNIX2003" )] pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; #[cfg_attr( all(target_os = "freebsd", any(freebsd12, freebsd11, freebsd10)), link_name = "rand@FBSD_1.0" )] pub fn rand() -> ::c_int; #[cfg_attr( all(target_os = "freebsd", any(freebsd12, freebsd11, freebsd10)), link_name = "srand@FBSD_1.0" )] pub fn srand(seed: ::c_uint); pub fn getifaddrs(ifap: *mut *mut ::ifaddrs) -> ::c_int; pub fn freeifaddrs(ifa: *mut ::ifaddrs); pub fn setgroups(ngroups: ::c_int, ptr: *const ::gid_t) -> ::c_int; pub fn setlogin(name: *const ::c_char) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; pub fn kqueue() -> ::c_int; pub fn unmount(target: *const ::c_char, arg: ::c_int) -> ::c_int; pub fn syscall(num: ::c_int, ...) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__getpwent50")] pub fn getpwent() -> *mut passwd; pub fn setpwent(); pub fn endpwent(); pub fn endgrent(); pub fn getgrent() -> *mut ::group; pub fn getprogname() -> *const ::c_char; pub fn setprogname(name: *const ::c_char); pub fn getloadavg(loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; pub fn if_nameindex() -> *mut if_nameindex; pub fn if_freenameindex(ptr: *mut if_nameindex); pub fn getpeereid(socket: ::c_int, euid: *mut ::uid_t, egid: *mut ::gid_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", not(target_arch = "aarch64")), link_name = "glob$INODE64" )] #[cfg_attr(target_os = "netbsd", link_name = "__glob30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "glob@FBSD_1.0" )] pub fn glob( pattern: *const ::c_char, flags: ::c_int, errfunc: ::Option ::c_int>, pglob: *mut ::glob_t, ) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__globfree30")] #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "globfree@FBSD_1.0" )] pub fn globfree(pglob: *mut ::glob_t); pub fn posix_madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "seekdir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "seekdir$INODE64$UNIX2003" )] pub fn seekdir(dirp: *mut ::DIR, loc: ::c_long); #[cfg_attr( all(target_os = "macos", target_arch = "x86_64"), link_name = "telldir$INODE64" )] #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "telldir$INODE64$UNIX2003" )] pub fn telldir(dirp: *mut ::DIR) -> ::c_long; pub fn madvise(addr: *mut ::c_void, len: ::size_t, advice: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "msync$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__msync13")] pub fn msync(addr: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recvfrom$UNIX2003" )] pub fn recvfrom( socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, ) -> ::ssize_t; pub fn mkstemps(template: *mut ::c_char, suffixlen: ::c_int) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__futimes50")] pub fn futimes(fd: ::c_int, times: *const ::timeval) -> ::c_int; pub fn nl_langinfo(item: ::nl_item) -> *mut ::c_char; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "bind$UNIX2003" )] pub fn bind(socket: ::c_int, address: *const ::sockaddr, address_len: ::socklen_t) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "writev$UNIX2003" )] pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "readv$UNIX2003" )] pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sendmsg$UNIX2003" )] pub fn sendmsg(fd: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "recvmsg$UNIX2003" )] pub fn recvmsg(fd: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn sync(); pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sigaltstack$UNIX2003" )] #[cfg_attr(target_os = "netbsd", link_name = "__sigaltstack14")] pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sigsuspend(mask: *const ::sigset_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_sigmask$UNIX2003" )] pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "pthread_cancel$UNIX2003" )] pub fn pthread_cancel(thread: ::pthread_t) -> ::c_int; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sched_get_priority_min(policy: ::c_int) -> ::c_int; pub fn sched_get_priority_max(policy: ::c_int) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__getpwnam_r50")] pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid_r50")] pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "sigwait$UNIX2003" )] pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "popen$UNIX2003" )] pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn faccessat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn acct(filename: *const ::c_char) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "wait4$UNIX2003" )] #[cfg_attr( all(target_os = "freebsd", any(freebsd12, freebsd11, freebsd10)), link_name = "wait4@FBSD_1.0" )] pub fn wait4( pid: ::pid_t, status: *mut ::c_int, options: ::c_int, rusage: *mut ::rusage, ) -> ::pid_t; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "getitimer$UNIX2003" )] pub fn getitimer(which: ::c_int, curr_value: *mut ::itimerval) -> ::c_int; #[cfg_attr( all(target_os = "macos", target_arch = "x86"), link_name = "setitimer$UNIX2003" )] pub fn setitimer( which: ::c_int, new_value: *const ::itimerval, old_value: *mut ::itimerval, ) -> ::c_int; pub fn regcomp(preg: *mut regex_t, pattern: *const ::c_char, cflags: ::c_int) -> ::c_int; pub fn regexec( preg: *const regex_t, input: *const ::c_char, nmatch: ::size_t, pmatch: *mut regmatch_t, eflags: ::c_int, ) -> ::c_int; pub fn regerror( errcode: ::c_int, preg: *const regex_t, errbuf: *mut ::c_char, errbuf_size: ::size_t, ) -> ::size_t; pub fn regfree(preg: *mut regex_t); pub fn arc4random() -> u32; pub fn arc4random_buf(buf: *mut ::c_void, size: ::size_t); pub fn arc4random_uniform(l: u32) -> u32; pub fn drand48() -> ::c_double; pub fn erand48(xseed: *mut ::c_ushort) -> ::c_double; pub fn lrand48() -> ::c_long; pub fn nrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn mrand48() -> ::c_long; pub fn jrand48(xseed: *mut ::c_ushort) -> ::c_long; pub fn srand48(seed: ::c_long); pub fn seed48(xseed: *mut ::c_ushort) -> *mut ::c_ushort; pub fn lcong48(p: *mut ::c_ushort); pub fn getopt_long( argc: ::c_int, argv: *const *mut c_char, optstring: *const c_char, longopts: *const option, longindex: *mut ::c_int, ) -> ::c_int; pub fn strftime( buf: *mut ::c_char, maxsize: ::size_t, format: *const ::c_char, timeptr: *const ::tm, ) -> ::size_t; pub fn strftime_l( buf: *mut ::c_char, maxsize: ::size_t, format: *const ::c_char, timeptr: *const ::tm, locale: ::locale_t, ) -> ::size_t; } cfg_if! { if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] { mod apple; pub use self::apple::*; } else if #[cfg(any(target_os = "openbsd", target_os = "netbsd"))] { mod netbsdlike; pub use self::netbsdlike::*; } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] { mod freebsdlike; pub use self::freebsdlike::*; } else { // Unknown target_os } } libc/src/unix/bsd/freebsdlike/0000775000175000017500000000000014661133735017255 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/dragonfly/0000775000175000017500000000000014661133735021242 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/dragonfly/errno.rs0000644000175000017500000000057114661133735022736 0ustar jamespagejamespage// DragonFlyBSD's __error function is declared with "static inline", so it must // be implemented in the libc crate, as a pointer to a static thread_local. f! { #[deprecated(since = "0.2.77", note = "Use `__errno_location()` instead")] pub fn __error() -> *mut ::c_int { &mut errno } } extern "C" { #[thread_local] pub static mut errno: ::c_int; } libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs0000644000175000017500000016364414661133735022403 0ustar jamespagejamespagepub type dev_t = u32; pub type c_char = i8; pub type wchar_t = i32; pub type clock_t = u64; pub type ino_t = u64; pub type lwpid_t = i32; pub type nlink_t = u32; pub type blksize_t = i64; pub type clockid_t = ::c_ulong; pub type c_long = i64; pub type c_ulong = u64; pub type time_t = i64; pub type suseconds_t = i64; pub type uuid_t = ::uuid; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = ::c_uint; pub type shmatt_t = ::c_uint; pub type mqd_t = ::c_int; pub type sem_t = *mut sem; pub type cpuset_t = cpumask_t; pub type cpu_set_t = cpumask_t; pub type register_t = ::c_long; pub type umtx_t = ::c_int; pub type pthread_barrierattr_t = ::c_int; pub type pthread_barrier_t = ::uintptr_t; pub type pthread_spinlock_t = ::uintptr_t; pub type segsz_t = usize; pub type vm_prot_t = u8; pub type vm_maptype_t = u8; pub type vm_inherit_t = i8; pub type vm_subsys_t = ::c_int; pub type vm_eflags_t = ::c_uint; pub type vm_map_t = *mut __c_anonymous_vm_map; pub type vm_map_entry_t = *mut vm_map_entry; pub type pmap = __c_anonymous_pmap; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum sem {} impl ::Copy for sem {} impl ::Clone for sem { fn clone(&self) -> sem { *self } } e! { #[repr(u32)] pub enum lwpstat { LSRUN = 1, LSSTOP = 2, LSSLEEP = 3, } #[repr(u32)] pub enum procstat { SIDL = 1, SACTIVE = 2, SSTOP = 3, SZOMB = 4, SCORE = 5, } } s! { pub struct kevent { pub ident: ::uintptr_t, pub filter: ::c_short, pub flags: ::c_ushort, pub fflags: ::c_uint, pub data: ::intptr_t, pub udata: *mut ::c_void, } pub struct exit_status { pub e_termination: u16, pub e_exit: u16 } pub struct aiocb { pub aio_fildes: ::c_int, pub aio_offset: ::off_t, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, pub aio_sigevent: sigevent, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, _aio_val: ::c_int, _aio_err: ::c_int } pub struct uuid { pub time_low: u32, pub time_mid: u16, pub time_hi_and_version: u16, pub clock_seq_hi_and_reserved: u8, pub clock_seq_low: u8, pub node: [u8; 6], } pub struct mq_attr { pub mq_flags: ::c_long, pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_bavail: ::fsblkcnt_t, pub f_files: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_favail: ::fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, pub f_owner: ::uid_t, pub f_type: ::c_uint, pub f_syncreads: u64, pub f_syncwrites: u64, pub f_asyncreads: u64, pub f_asyncwrites: u64, pub f_fsid_uuid: ::uuid_t, pub f_uid_uuid: ::uuid_t, } pub struct stat { pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_dev: ::dev_t, pub st_mode: ::mode_t, pub st_padding1: u16, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: i64, pub __old_st_blksize: u32, pub st_flags: u32, pub st_gen: u32, pub st_lspare: i32, pub st_blksize: i64, pub st_qspare2: i64, } pub struct if_data { pub ifi_type: ::c_uchar, pub ifi_physical: ::c_uchar, pub ifi_addrlen: ::c_uchar, pub ifi_hdrlen: ::c_uchar, pub ifi_recvquota: ::c_uchar, pub ifi_xmitquota: ::c_uchar, pub ifi_mtu: ::c_ulong, pub ifi_metric: ::c_ulong, pub ifi_link_state: ::c_ulong, pub ifi_baudrate: u64, pub ifi_ipackets: ::c_ulong, pub ifi_ierrors: ::c_ulong, pub ifi_opackets: ::c_ulong, pub ifi_oerrors: ::c_ulong, pub ifi_collisions: ::c_ulong, pub ifi_ibytes: ::c_ulong, pub ifi_obytes: ::c_ulong, pub ifi_imcasts: ::c_ulong, pub ifi_omcasts: ::c_ulong, pub ifi_iqdrops: ::c_ulong, pub ifi_noproto: ::c_ulong, pub ifi_hwassist: ::c_ulong, pub ifi_oqdrops: ::c_ulong, pub ifi_lastchange: ::timeval, } pub struct if_msghdr { pub ifm_msglen: ::c_ushort, pub ifm_version: ::c_uchar, pub ifm_type: ::c_uchar, pub ifm_addrs: ::c_int, pub ifm_flags: ::c_int, pub ifm_index: ::c_ushort, pub ifm_data: if_data, } pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, pub sdl_index: ::c_ushort, pub sdl_type: ::c_uchar, pub sdl_nlen: ::c_uchar, pub sdl_alen: ::c_uchar, pub sdl_slen: ::c_uchar, pub sdl_data: [::c_char; 12], pub sdl_rcf: ::c_ushort, pub sdl_route: [::c_ushort; 16], } pub struct xucred { pub cr_version: ::c_uint, pub cr_uid: ::uid_t, pub cr_ngroups: ::c_short, pub cr_groups: [::gid_t; 16], __cr_unused1: *mut ::c_void, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct cpumask_t { ary: [u64; 4], } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, shm_internal: *mut ::c_void, } pub struct kinfo_file { pub f_size: ::size_t, pub f_pid: ::pid_t, pub f_uid: ::uid_t, pub f_fd: ::c_int, pub f_file: *mut ::c_void, pub f_type: ::c_short, pub f_count: ::c_int, pub f_msgcount: ::c_int, pub f_offset: ::off_t, pub f_data: *mut ::c_void, pub f_flag: ::c_uint, } pub struct kinfo_cputime { pub cp_user: u64, pub cp_nice: u64, pub cp_sys: u64, pub cp_intr: u64, pub cp_idel: u64, cp_unused01: u64, cp_unused02: u64, pub cp_sample_pc: u64, pub cp_sample_sp: u64, pub cp_msg: [::c_char; 32], } pub struct kinfo_lwp { pub kl_pid: ::pid_t, pub kl_tid: ::lwpid_t, pub kl_flags: ::c_int, pub kl_stat: ::lwpstat, pub kl_lock: ::c_int, pub kl_tdflags: ::c_int, pub kl_mpcount: ::c_int, pub kl_prio: ::c_int, pub kl_tdprio: ::c_int, pub kl_rtprio: ::rtprio, pub kl_uticks: u64, pub kl_sticks: u64, pub kl_iticks: u64, pub kl_cpticks: u64, pub kl_pctcpu: ::c_uint, pub kl_slptime: ::c_uint, pub kl_origcpu: ::c_int, pub kl_estcpu: ::c_int, pub kl_cpuid: ::c_int, pub kl_ru: ::rusage, pub kl_siglist: ::sigset_t, pub kl_sigmask: ::sigset_t, pub kl_wchan: ::uintptr_t, pub kl_wmesg: [::c_char; 9], pub kl_comm: [::c_char; MAXCOMLEN+1], } pub struct kinfo_proc { pub kp_paddr: ::uintptr_t, pub kp_flags: ::c_int, pub kp_stat: ::procstat, pub kp_lock: ::c_int, pub kp_acflag: ::c_int, pub kp_traceflag: ::c_int, pub kp_fd: ::uintptr_t, pub kp_siglist: ::sigset_t, pub kp_sigignore: ::sigset_t, pub kp_sigcatch: ::sigset_t, pub kp_sigflag: ::c_int, pub kp_start: ::timeval, pub kp_comm: [::c_char; MAXCOMLEN+1], pub kp_uid: ::uid_t, pub kp_ngroups: ::c_short, pub kp_groups: [::gid_t; NGROUPS], pub kp_ruid: ::uid_t, pub kp_svuid: ::uid_t, pub kp_rgid: ::gid_t, pub kp_svgid: ::gid_t, pub kp_pid: ::pid_t, pub kp_ppid: ::pid_t, pub kp_pgid: ::pid_t, pub kp_jobc: ::c_int, pub kp_sid: ::pid_t, pub kp_login: [::c_char; 40], // MAXNAMELEN rounded up to the nearest sizeof(long) pub kp_tdev: ::dev_t, pub kp_tpgid: ::pid_t, pub kp_tsid: ::pid_t, pub kp_exitstat: ::c_ushort, pub kp_nthreads: ::c_int, pub kp_nice: ::c_int, pub kp_swtime: ::c_uint, pub kp_vm_map_size: ::size_t, pub kp_vm_rssize: ::segsz_t, pub kp_vm_swrss: ::segsz_t, pub kp_vm_tsize: ::segsz_t, pub kp_vm_dsize: ::segsz_t, pub kp_vm_ssize: ::segsz_t, pub kp_vm_prssize: ::c_uint, pub kp_jailid: ::c_int, pub kp_ru: ::rusage, pub kp_cru: ::rusage, pub kp_auxflags: ::c_int, pub kp_lwp: ::kinfo_lwp, pub kp_ktaddr: ::uintptr_t, kp_spare: [::c_int; 2], } pub struct __c_anonymous_vm_map { _priv: [::uintptr_t; 36], } pub struct vm_map_entry { _priv: [::uintptr_t; 15], pub eflags: ::vm_eflags_t, pub maptype: ::vm_maptype_t, pub protection: ::vm_prot_t, pub max_protection: ::vm_prot_t, pub inheritance: ::vm_inherit_t, pub wired_count: ::c_int, pub id: ::vm_subsys_t, } pub struct __c_anonymous_pmap { _priv1: [::uintptr_t; 32], _priv2: [::uintptr_t; 32], _priv3: [::uintptr_t; 32], _priv4: [::uintptr_t; 32], _priv5: [::uintptr_t; 8], } pub struct vmspace { vm_map: __c_anonymous_vm_map, vm_pmap: __c_anonymous_pmap, pub vm_flags: ::c_int, pub vm_shm: *mut ::c_char, pub vm_rssize: ::segsz_t, pub vm_swrss: ::segsz_t, pub vm_tsize: ::segsz_t, pub vm_dsize: ::segsz_t, pub vm_ssize: ::segsz_t, pub vm_taddr: *mut ::c_char, pub vm_daddr: *mut ::c_char, pub vm_maxsaddr: *mut ::c_char, pub vm_minsaddr: *mut ::c_char, _unused1: ::c_int, _unused2: ::c_int, pub vm_pagesupply: ::c_int, pub vm_holdcnt: ::c_uint, pub vm_refcnt: ::c_uint, } pub struct cpuctl_msr_args_t { pub msr: ::c_int, pub data: u64, } pub struct cpuctl_cpuid_args_t { pub level: ::c_int, pub data: [u32; 4], } pub struct cpuctl_cpuid_count_args_t { pub level: ::c_int, pub level_type: ::c_int, pub data: [u32; 4], } pub struct cpuctl_update_args_t { pub data: *mut ::c_void, pub size: ::size_t, } } s_no_extra_traits! { pub struct utmpx { pub ut_name: [::c_char; 32], pub ut_id: [::c_char; 4], pub ut_line: [::c_char; 32], pub ut_host: [::c_char; 256], pub ut_unused: [u8; 16], pub ut_session: u16, pub ut_type: u16, pub ut_pid: ::pid_t, ut_exit: exit_status, ut_ss: ::sockaddr_storage, pub ut_tv: ::timeval, pub ut_unused2: [u8; 16], } pub struct lastlogx { pub ll_tv: ::timeval, pub ll_line: [::c_char; _UTX_LINESIZE], pub ll_host: [::c_char; _UTX_HOSTSIZE], pub ll_ss: ::sockaddr_storage, } pub struct dirent { pub d_fileno: ::ino_t, pub d_namlen: u16, pub d_type: u8, __unused1: u8, __unused2: u32, pub d_name: [::c_char; 256], } pub struct statfs { __spare2: ::c_long, pub f_bsize: ::c_long, pub f_iosize: ::c_long, pub f_blocks: ::c_long, pub f_bfree: ::c_long, pub f_bavail: ::c_long, pub f_files: ::c_long, pub f_ffree: ::c_long, pub f_fsid: ::fsid_t, pub f_owner: ::uid_t, pub f_type: ::c_int, pub f_flags: ::c_int, pub f_syncwrites: ::c_long, pub f_asyncwrites: ::c_long, pub f_fstypename: [::c_char; 16], pub f_mntonname: [::c_char; 80], pub f_syncreads: ::c_long, pub f_asyncreads: ::c_long, __spares1: ::c_short, pub f_mntfromname: [::c_char; 80], __spares2: ::c_short, __spare: [::c_long; 2], } pub struct sigevent { pub sigev_notify: ::c_int, // The union is 8-byte in size, so it is aligned at a 8-byte offset. #[cfg(target_pointer_width = "64")] __unused1: ::c_int, pub sigev_signo: ::c_int, //actually a union // pad the union #[cfg(target_pointer_width = "64")] __unused2: ::c_int, pub sigev_value: ::sigval, __unused3: *mut ::c_void //actually a function pointer } pub struct mcontext_t { pub mc_onstack: register_t, pub mc_rdi: register_t, pub mc_rsi: register_t, pub mc_rdx: register_t, pub mc_rcx: register_t, pub mc_r8: register_t, pub mc_r9: register_t, pub mc_rax: register_t, pub mc_rbx: register_t, pub mc_rbp: register_t, pub mc_r10: register_t, pub mc_r11: register_t, pub mc_r12: register_t, pub mc_r13: register_t, pub mc_r14: register_t, pub mc_r15: register_t, pub mc_xflags: register_t, pub mc_trapno: register_t, pub mc_addr: register_t, pub mc_flags: register_t, pub mc_err: register_t, pub mc_rip: register_t, pub mc_cs: register_t, pub mc_rflags: register_t, pub mc_rsp: register_t, pub mc_ss: register_t, pub mc_len: ::c_uint, pub mc_fpformat: ::c_uint, pub mc_ownedfp: ::c_uint, __reserved: ::c_uint, __unused: [::c_uint; 8], pub mc_fpregs: [[::c_uint; 8]; 32], } pub struct ucontext_t { pub uc_sigmask: ::sigset_t, pub uc_mcontext: mcontext_t, pub uc_link: *mut ucontext_t, pub uc_stack: stack_t, pub uc_cofunc: ::Option, pub uc_arg: *mut ::c_void, __pad: [::c_int; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_name == other.ut_name && self.ut_id == other.ut_id && self.ut_line == other.ut_line && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self.ut_unused == other.ut_unused && self.ut_session == other.ut_session && self.ut_type == other.ut_type && self.ut_pid == other.ut_pid && self.ut_exit == other.ut_exit && self.ut_ss == other.ut_ss && self.ut_tv == other.ut_tv && self.ut_unused2 == other.ut_unused2 } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_name", &self.ut_name) .field("ut_id", &self.ut_id) .field("ut_line", &self.ut_line) // FIXME: .field("ut_host", &self.ut_host) .field("ut_unused", &self.ut_unused) .field("ut_session", &self.ut_session) .field("ut_type", &self.ut_type) .field("ut_pid", &self.ut_pid) .field("ut_exit", &self.ut_exit) .field("ut_ss", &self.ut_ss) .field("ut_tv", &self.ut_tv) .field("ut_unused2", &self.ut_unused2) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_name.hash(state); self.ut_id.hash(state); self.ut_line.hash(state); self.ut_host.hash(state); self.ut_unused.hash(state); self.ut_session.hash(state); self.ut_type.hash(state); self.ut_pid.hash(state); self.ut_exit.hash(state); self.ut_ss.hash(state); self.ut_tv.hash(state); self.ut_unused2.hash(state); } } impl PartialEq for lastlogx { fn eq(&self, other: &lastlogx) -> bool { self.ll_tv == other.ll_tv && self.ll_line == other.ll_line && self.ll_host == other.ll_host && self.ll_ss == other.ll_ss } } impl Eq for lastlogx {} impl ::fmt::Debug for lastlogx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("lastlogx") .field("ll_tv", &self.ll_tv) .field("ll_line", &self.ll_line) .field("ll_host", &self.ll_host) .field("ll_ss", &self.ll_ss) .finish() } } impl ::hash::Hash for lastlogx { fn hash(&self, state: &mut H) { self.ll_tv.hash(state); self.ll_line.hash(state); self.ll_host.hash(state); self.ll_ss.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_namlen == other.d_namlen && self.d_type == other.d_type // Ignore __unused1 // Ignore __unused2 && self .d_name .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_namlen", &self.d_namlen) .field("d_type", &self.d_type) // Ignore __unused1 // Ignore __unused2 // FIXME: .field("d_name", &self.d_name) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_namlen.hash(state); self.d_type.hash(state); // Ignore __unused1 // Ignore __unused2 self.d_name.hash(state); } } impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_fsid == other.f_fsid && self.f_owner == other.f_owner && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_fstypename == other.f_fstypename && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) } } impl Eq for statfs {} impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_fsid", &self.f_fsid) .field("f_owner", &self.f_owner) .field("f_type", &self.f_type) .field("f_flags", &self.f_flags) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) // FIXME: .field("f_mntonname", &self.f_mntonname) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) // FIXME: .field("f_mntfromname", &self.f_mntfromname) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_fsid.hash(state); self.f_owner.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_fstypename.hash(state); self.f_mntonname.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_mntfromname.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_onstack == other.mc_onstack && self.mc_rdi == other.mc_rdi && self.mc_rsi == other.mc_rsi && self.mc_rdx == other.mc_rdx && self.mc_rcx == other.mc_rcx && self.mc_r8 == other.mc_r8 && self.mc_r9 == other.mc_r9 && self.mc_rax == other.mc_rax && self.mc_rbx == other.mc_rbx && self.mc_rbp == other.mc_rbp && self.mc_r10 == other.mc_r10 && self.mc_r11 == other.mc_r11 && self.mc_r12 == other.mc_r12 && self.mc_r13 == other.mc_r13 && self.mc_r14 == other.mc_r14 && self.mc_r15 == other.mc_r15 && self.mc_xflags == other.mc_xflags && self.mc_trapno == other.mc_trapno && self.mc_addr == other.mc_addr && self.mc_flags == other.mc_flags && self.mc_err == other.mc_err && self.mc_rip == other.mc_rip && self.mc_cs == other.mc_cs && self.mc_rflags == other.mc_rflags && self.mc_rsp == other.mc_rsp && self.mc_ss == other.mc_ss && self.mc_len == other.mc_len && self.mc_fpformat == other.mc_fpformat && self.mc_ownedfp == other.mc_ownedfp && self.mc_fpregs.iter().zip(other.mc_fpregs.iter()). all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("mc_onstack", &self.mc_onstack) .field("mc_rdi", &self.mc_rdi) .field("mc_rsi", &self.mc_rsi) .field("mc_rdx", &self.mc_rdx) .field("mc_rcx", &self.mc_rcx) .field("mc_r8", &self.mc_r8) .field("mc_r9", &self.mc_r9) .field("mc_rax", &self.mc_rax) .field("mc_rbx", &self.mc_rbx) .field("mc_rbp", &self.mc_rbp) .field("mc_r10", &self.mc_r10) .field("mc_r11", &self.mc_r11) .field("mc_r12", &self.mc_r12) .field("mc_r13", &self.mc_r13) .field("mc_r14", &self.mc_r14) .field("mc_r15", &self.mc_r15) .field("mc_xflags", &self.mc_xflags) .field("mc_trapno", &self.mc_trapno) .field("mc_addr", &self.mc_addr) .field("mc_flags", &self.mc_flags) .field("mc_err", &self.mc_err) .field("mc_rip", &self.mc_rip) .field("mc_cs", &self.mc_cs) .field("mc_rflags", &self.mc_rflags) .field("mc_rsp", &self.mc_rsp) .field("mc_ss", &self.mc_ss) .field("mc_len", &self.mc_len) .field("mc_fpformat", &self.mc_fpformat) .field("mc_ownedfp", &self.mc_ownedfp) .field("mc_fpregs", &self.mc_fpregs) .finish() } } impl ::hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_onstack.hash(state); self.mc_rdi.hash(state); self.mc_rsi.hash(state); self.mc_rdx.hash(state); self.mc_rcx.hash(state); self.mc_r8.hash(state); self.mc_r9.hash(state); self.mc_rax.hash(state); self.mc_rbx.hash(state); self.mc_rbp.hash(state); self.mc_r10.hash(state); self.mc_r11.hash(state); self.mc_r10.hash(state); self.mc_r11.hash(state); self.mc_r12.hash(state); self.mc_r13.hash(state); self.mc_r14.hash(state); self.mc_r15.hash(state); self.mc_xflags.hash(state); self.mc_trapno.hash(state); self.mc_addr.hash(state); self.mc_flags.hash(state); self.mc_err.hash(state); self.mc_rip.hash(state); self.mc_cs.hash(state); self.mc_rflags.hash(state); self.mc_rsp.hash(state); self.mc_ss.hash(state); self.mc_len.hash(state); self.mc_fpformat.hash(state); self.mc_ownedfp.hash(state); self.mc_fpregs.hash(state); } } impl PartialEq for ucontext_t { fn eq(&self, other: &ucontext_t) -> bool { self.uc_sigmask == other.uc_sigmask && self.uc_mcontext == other.uc_mcontext && self.uc_link == other.uc_link && self.uc_stack == other.uc_stack && self.uc_cofunc == other.uc_cofunc && self.uc_arg == other.uc_arg } } impl Eq for ucontext_t {} impl ::fmt::Debug for ucontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ucontext_t") .field("uc_sigmask", &self.uc_sigmask) .field("uc_mcontext", &self.uc_mcontext) .field("uc_link", &self.uc_link) .field("uc_stack", &self.uc_stack) .field("uc_cofunc", &self.uc_cofunc) .field("uc_arg", &self.uc_arg) .finish() } } impl ::hash::Hash for ucontext_t { fn hash(&self, state: &mut H) { self.uc_sigmask.hash(state); self.uc_mcontext.hash(state); self.uc_link.hash(state); self.uc_stack.hash(state); self.uc_cofunc.hash(state); self.uc_arg.hash(state); } } } } pub const RAND_MAX: ::c_int = 0x7fff_ffff; pub const PTHREAD_STACK_MIN: ::size_t = 16384; pub const SIGSTKSZ: ::size_t = 40960; pub const SIGCKPT: ::c_int = 33; pub const SIGCKPTEXIT: ::c_int = 34; pub const CKPT_FREEZE: ::c_int = 0x1; pub const CKPT_THAW: ::c_int = 0x2; pub const MADV_INVAL: ::c_int = 10; pub const MADV_SETMAP: ::c_int = 11; pub const O_CLOEXEC: ::c_int = 0x00020000; pub const O_DIRECTORY: ::c_int = 0x08000000; pub const F_GETLK: ::c_int = 7; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const F_GETPATH: ::c_int = 19; pub const ENOMEDIUM: ::c_int = 93; pub const ENOTRECOVERABLE: ::c_int = 94; pub const EOWNERDEAD: ::c_int = 95; pub const EASYNC: ::c_int = 99; pub const ELAST: ::c_int = 99; pub const RLIMIT_POSIXLOCKS: ::c_int = 11; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::rlim_t = 12; pub const Q_GETQUOTA: ::c_int = 0x300; pub const Q_SETQUOTA: ::c_int = 0x400; pub const CTL_UNSPEC: ::c_int = 0; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_VFS: ::c_int = 3; pub const CTL_NET: ::c_int = 4; pub const CTL_DEBUG: ::c_int = 5; pub const CTL_HW: ::c_int = 6; pub const CTL_MACHDEP: ::c_int = 7; pub const CTL_USER: ::c_int = 8; pub const CTL_P1003_1B: ::c_int = 9; pub const CTL_LWKT: ::c_int = 10; pub const CTL_MAXID: ::c_int = 11; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_VERSION: ::c_int = 4; pub const KERN_MAXVNODES: ::c_int = 5; pub const KERN_MAXPROC: ::c_int = 6; pub const KERN_MAXFILES: ::c_int = 7; pub const KERN_ARGMAX: ::c_int = 8; pub const KERN_SECURELVL: ::c_int = 9; pub const KERN_HOSTNAME: ::c_int = 10; pub const KERN_HOSTID: ::c_int = 11; pub const KERN_CLOCKRATE: ::c_int = 12; pub const KERN_VNODE: ::c_int = 13; pub const KERN_PROC: ::c_int = 14; pub const KERN_FILE: ::c_int = 15; pub const KERN_PROF: ::c_int = 16; pub const KERN_POSIX1: ::c_int = 17; pub const KERN_NGROUPS: ::c_int = 18; pub const KERN_JOB_CONTROL: ::c_int = 19; pub const KERN_SAVED_IDS: ::c_int = 20; pub const KERN_BOOTTIME: ::c_int = 21; pub const KERN_NISDOMAINNAME: ::c_int = 22; pub const KERN_UPDATEINTERVAL: ::c_int = 23; pub const KERN_OSRELDATE: ::c_int = 24; pub const KERN_NTP_PLL: ::c_int = 25; pub const KERN_BOOTFILE: ::c_int = 26; pub const KERN_MAXFILESPERPROC: ::c_int = 27; pub const KERN_MAXPROCPERUID: ::c_int = 28; pub const KERN_DUMPDEV: ::c_int = 29; pub const KERN_IPC: ::c_int = 30; pub const KERN_DUMMY: ::c_int = 31; pub const KERN_PS_STRINGS: ::c_int = 32; pub const KERN_USRSTACK: ::c_int = 33; pub const KERN_LOGSIGEXIT: ::c_int = 34; pub const KERN_IOV_MAX: ::c_int = 35; pub const KERN_MAXPOSIXLOCKSPERUID: ::c_int = 36; pub const KERN_MAXID: ::c_int = 37; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_PID: ::c_int = 1; pub const KERN_PROC_PGRP: ::c_int = 2; pub const KERN_PROC_SESSION: ::c_int = 3; pub const KERN_PROC_TTY: ::c_int = 4; pub const KERN_PROC_UID: ::c_int = 5; pub const KERN_PROC_RUID: ::c_int = 6; pub const KERN_PROC_ARGS: ::c_int = 7; pub const KERN_PROC_CWD: ::c_int = 8; pub const KERN_PROC_PATHNAME: ::c_int = 9; pub const KERN_PROC_FLAGMASK: ::c_int = 0x10; pub const KERN_PROC_FLAG_LWP: ::c_int = 0x10; pub const KIPC_MAXSOCKBUF: ::c_int = 1; pub const KIPC_SOCKBUF_WASTE: ::c_int = 2; pub const KIPC_SOMAXCONN: ::c_int = 3; pub const KIPC_MAX_LINKHDR: ::c_int = 4; pub const KIPC_MAX_PROTOHDR: ::c_int = 5; pub const KIPC_MAX_HDR: ::c_int = 6; pub const KIPC_MAX_DATALEN: ::c_int = 7; pub const KIPC_MBSTAT: ::c_int = 8; pub const KIPC_NMBCLUSTERS: ::c_int = 9; pub const HW_MACHINE: ::c_int = 1; pub const HW_MODEL: ::c_int = 2; pub const HW_NCPU: ::c_int = 3; pub const HW_BYTEORDER: ::c_int = 4; pub const HW_PHYSMEM: ::c_int = 5; pub const HW_USERMEM: ::c_int = 6; pub const HW_PAGESIZE: ::c_int = 7; pub const HW_DISKNAMES: ::c_int = 8; pub const HW_DISKSTATS: ::c_int = 9; pub const HW_FLOATINGPT: ::c_int = 10; pub const HW_MACHINE_ARCH: ::c_int = 11; pub const HW_MACHINE_PLATFORM: ::c_int = 12; pub const HW_SENSORS: ::c_int = 13; pub const HW_MAXID: ::c_int = 14; pub const USER_CS_PATH: ::c_int = 1; pub const USER_BC_BASE_MAX: ::c_int = 2; pub const USER_BC_DIM_MAX: ::c_int = 3; pub const USER_BC_SCALE_MAX: ::c_int = 4; pub const USER_BC_STRING_MAX: ::c_int = 5; pub const USER_COLL_WEIGHTS_MAX: ::c_int = 6; pub const USER_EXPR_NEST_MAX: ::c_int = 7; pub const USER_LINE_MAX: ::c_int = 8; pub const USER_RE_DUP_MAX: ::c_int = 9; pub const USER_POSIX2_VERSION: ::c_int = 10; pub const USER_POSIX2_C_BIND: ::c_int = 11; pub const USER_POSIX2_C_DEV: ::c_int = 12; pub const USER_POSIX2_CHAR_TERM: ::c_int = 13; pub const USER_POSIX2_FORT_DEV: ::c_int = 14; pub const USER_POSIX2_FORT_RUN: ::c_int = 15; pub const USER_POSIX2_LOCALEDEF: ::c_int = 16; pub const USER_POSIX2_SW_DEV: ::c_int = 17; pub const USER_POSIX2_UPE: ::c_int = 18; pub const USER_STREAM_MAX: ::c_int = 19; pub const USER_TZNAME_MAX: ::c_int = 20; pub const USER_MAXID: ::c_int = 21; pub const CTL_P1003_1B_ASYNCHRONOUS_IO: ::c_int = 1; pub const CTL_P1003_1B_MAPPED_FILES: ::c_int = 2; pub const CTL_P1003_1B_MEMLOCK: ::c_int = 3; pub const CTL_P1003_1B_MEMLOCK_RANGE: ::c_int = 4; pub const CTL_P1003_1B_MEMORY_PROTECTION: ::c_int = 5; pub const CTL_P1003_1B_MESSAGE_PASSING: ::c_int = 6; pub const CTL_P1003_1B_PRIORITIZED_IO: ::c_int = 7; pub const CTL_P1003_1B_PRIORITY_SCHEDULING: ::c_int = 8; pub const CTL_P1003_1B_REALTIME_SIGNALS: ::c_int = 9; pub const CTL_P1003_1B_SEMAPHORES: ::c_int = 10; pub const CTL_P1003_1B_FSYNC: ::c_int = 11; pub const CTL_P1003_1B_SHARED_MEMORY_OBJECTS: ::c_int = 12; pub const CTL_P1003_1B_SYNCHRONIZED_IO: ::c_int = 13; pub const CTL_P1003_1B_TIMERS: ::c_int = 14; pub const CTL_P1003_1B_AIO_LISTIO_MAX: ::c_int = 15; pub const CTL_P1003_1B_AIO_MAX: ::c_int = 16; pub const CTL_P1003_1B_AIO_PRIO_DELTA_MAX: ::c_int = 17; pub const CTL_P1003_1B_DELAYTIMER_MAX: ::c_int = 18; pub const CTL_P1003_1B_UNUSED1: ::c_int = 19; pub const CTL_P1003_1B_PAGESIZE: ::c_int = 20; pub const CTL_P1003_1B_RTSIG_MAX: ::c_int = 21; pub const CTL_P1003_1B_SEM_NSEMS_MAX: ::c_int = 22; pub const CTL_P1003_1B_SEM_VALUE_MAX: ::c_int = 23; pub const CTL_P1003_1B_SIGQUEUE_MAX: ::c_int = 24; pub const CTL_P1003_1B_TIMER_MAX: ::c_int = 25; pub const CTL_P1003_1B_MAXID: ::c_int = 26; pub const CPUCTL_RSMSR: ::c_int = 0xc0106301; pub const CPUCTL_WRMSR: ::c_int = 0xc0106302; pub const CPUCTL_CPUID: ::c_int = 0xc0106303; pub const CPUCTL_UPDATE: ::c_int = 0xc0106304; pub const CPUCTL_MSRSBIT: ::c_int = 0xc0106305; pub const CPUCTL_MSRCBIT: ::c_int = 0xc0106306; pub const CPUCTL_CPUID_COUNT: ::c_int = 0xc0106307; pub const CPU_SETSIZE: ::size_t = ::mem::size_of::<::cpumask_t>() * 8; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_EXCEPT: i16 = -8; pub const EVFILT_USER: i16 = -9; pub const EVFILT_FS: i16 = -10; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_NODATA: u16 = 0x1000; pub const EV_FLAG1: u16 = 0x2000; pub const EV_ERROR: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; pub const EV_HUP: u16 = 0x8000; pub const EV_SYSFLAGS: u16 = 0xf000; pub const FIODNAME: ::c_ulong = 0x80106678; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_OOB: u32 = 0x00000002; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const SO_SNDSPACE: ::c_int = 0x100a; pub const SO_CPUHINT: ::c_int = 0x1030; pub const SO_PASSCRED: ::c_int = 0x4000; pub const PT_FIRSTMACH: ::c_int = 32; pub const PROC_REAP_ACQUIRE: ::c_int = 0x0001; pub const PROC_REAP_RELEASE: ::c_int = 0x0002; pub const PROC_REAP_STATUS: ::c_int = 0x0003; pub const PROC_PDEATHSIG_CTL: ::c_int = 0x0004; pub const PROC_PDEATHSIG_STATUS: ::c_int = 0x0005; // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/HEAD/sys/net/if.h#L101 pub const IFF_UP: ::c_int = 0x1; // interface is up pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link pub const IFF_SMART: ::c_int = 0x20; // interface manages own routes pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE_COMPAT: ::c_int = 0x400; // was transmission in progress pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit pub const IFF_ALTPHYS: ::c_int = IFF_LINK2; // use alternate physical connection pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast // was interface is in polling mode pub const IFF_POLLING_COMPAT: ::c_int = 0x10000; pub const IFF_PPROMISC: ::c_int = 0x20000; // user-requested promisc mode pub const IFF_MONITOR: ::c_int = 0x40000; // user-requested monitor mode pub const IFF_STATICARP: ::c_int = 0x80000; // static ARP pub const IFF_NPOLLING: ::c_int = 0x100000; // interface is in polling mode pub const IFF_IDIRECT: ::c_int = 0x200000; // direct input // // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// IP6 hop-by-hop options pub const IPPROTO_HOPOPTS: ::c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: ::c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: ::c_int = 3; /// for compatibility pub const IPPROTO_IPIP: ::c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// Stream protocol II. pub const IPPROTO_ST: ::c_int = 7; /// exterior gateway protocol pub const IPPROTO_EGP: ::c_int = 8; /// private interior gateway pub const IPPROTO_PIGP: ::c_int = 9; /// BBN RCC Monitoring pub const IPPROTO_RCCMON: ::c_int = 10; /// network voice protocol pub const IPPROTO_NVPII: ::c_int = 11; /// pup pub const IPPROTO_PUP: ::c_int = 12; /// Argus pub const IPPROTO_ARGUS: ::c_int = 13; /// EMCON pub const IPPROTO_EMCON: ::c_int = 14; /// Cross Net Debugger pub const IPPROTO_XNET: ::c_int = 15; /// Chaos pub const IPPROTO_CHAOS: ::c_int = 16; // IPPROTO_UDP defined in src/unix/mod.rs /// Multiplexing pub const IPPROTO_MUX: ::c_int = 18; /// DCN Measurement Subsystems pub const IPPROTO_MEAS: ::c_int = 19; /// Host Monitoring pub const IPPROTO_HMP: ::c_int = 20; /// Packet Radio Measurement pub const IPPROTO_PRM: ::c_int = 21; /// xns idp pub const IPPROTO_IDP: ::c_int = 22; /// Trunk-1 pub const IPPROTO_TRUNK1: ::c_int = 23; /// Trunk-2 pub const IPPROTO_TRUNK2: ::c_int = 24; /// Leaf-1 pub const IPPROTO_LEAF1: ::c_int = 25; /// Leaf-2 pub const IPPROTO_LEAF2: ::c_int = 26; /// Reliable Data pub const IPPROTO_RDP: ::c_int = 27; /// Reliable Transaction pub const IPPROTO_IRTP: ::c_int = 28; /// tp-4 w/ class negotiation pub const IPPROTO_TP: ::c_int = 29; /// Bulk Data Transfer pub const IPPROTO_BLT: ::c_int = 30; /// Network Services pub const IPPROTO_NSP: ::c_int = 31; /// Merit Internodal pub const IPPROTO_INP: ::c_int = 32; /// Sequential Exchange pub const IPPROTO_SEP: ::c_int = 33; /// Third Party Connect pub const IPPROTO_3PC: ::c_int = 34; /// InterDomain Policy Routing pub const IPPROTO_IDPR: ::c_int = 35; /// XTP pub const IPPROTO_XTP: ::c_int = 36; /// Datagram Delivery pub const IPPROTO_DDP: ::c_int = 37; /// Control Message Transport pub const IPPROTO_CMTP: ::c_int = 38; /// TP++ Transport pub const IPPROTO_TPXX: ::c_int = 39; /// IL transport protocol pub const IPPROTO_IL: ::c_int = 40; // IPPROTO_IPV6 defined in src/unix/mod.rs /// Source Demand Routing pub const IPPROTO_SDRP: ::c_int = 42; /// IP6 routing header pub const IPPROTO_ROUTING: ::c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: ::c_int = 44; /// InterDomain Routing pub const IPPROTO_IDRP: ::c_int = 45; /// resource reservation pub const IPPROTO_RSVP: ::c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: ::c_int = 47; /// Mobile Host Routing pub const IPPROTO_MHRP: ::c_int = 48; /// BHA pub const IPPROTO_BHA: ::c_int = 49; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: ::c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: ::c_int = 51; /// Integ. Net Layer Security pub const IPPROTO_INLSP: ::c_int = 52; /// IP with encryption pub const IPPROTO_SWIPE: ::c_int = 53; /// Next Hop Resolution pub const IPPROTO_NHRP: ::c_int = 54; /// IP Mobility pub const IPPROTO_MOBILE: ::c_int = 55; /// Transport Layer Security pub const IPPROTO_TLSP: ::c_int = 56; /// SKIP pub const IPPROTO_SKIP: ::c_int = 57; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: ::c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: ::c_int = 60; /// any host internal protocol pub const IPPROTO_AHIP: ::c_int = 61; /// CFTP pub const IPPROTO_CFTP: ::c_int = 62; /// "hello" routing protocol pub const IPPROTO_HELLO: ::c_int = 63; /// SATNET/Backroom EXPAK pub const IPPROTO_SATEXPAK: ::c_int = 64; /// Kryptolan pub const IPPROTO_KRYPTOLAN: ::c_int = 65; /// Remote Virtual Disk pub const IPPROTO_RVD: ::c_int = 66; /// Pluribus Packet Core pub const IPPROTO_IPPC: ::c_int = 67; /// Any distributed FS pub const IPPROTO_ADFS: ::c_int = 68; /// Satnet Monitoring pub const IPPROTO_SATMON: ::c_int = 69; /// VISA Protocol pub const IPPROTO_VISA: ::c_int = 70; /// Packet Core Utility pub const IPPROTO_IPCV: ::c_int = 71; /// Comp. Prot. Net. Executive pub const IPPROTO_CPNX: ::c_int = 72; /// Comp. Prot. HeartBeat pub const IPPROTO_CPHB: ::c_int = 73; /// Wang Span Network pub const IPPROTO_WSN: ::c_int = 74; /// Packet Video Protocol pub const IPPROTO_PVP: ::c_int = 75; /// BackRoom SATNET Monitoring pub const IPPROTO_BRSATMON: ::c_int = 76; /// Sun net disk proto (temp.) pub const IPPROTO_ND: ::c_int = 77; /// WIDEBAND Monitoring pub const IPPROTO_WBMON: ::c_int = 78; /// WIDEBAND EXPAK pub const IPPROTO_WBEXPAK: ::c_int = 79; /// ISO cnlp pub const IPPROTO_EON: ::c_int = 80; /// VMTP pub const IPPROTO_VMTP: ::c_int = 81; /// Secure VMTP pub const IPPROTO_SVMTP: ::c_int = 82; /// Banyon VINES pub const IPPROTO_VINES: ::c_int = 83; /// TTP pub const IPPROTO_TTP: ::c_int = 84; /// NSFNET-IGP pub const IPPROTO_IGP: ::c_int = 85; /// dissimilar gateway prot. pub const IPPROTO_DGP: ::c_int = 86; /// TCF pub const IPPROTO_TCF: ::c_int = 87; /// Cisco/GXS IGRP pub const IPPROTO_IGRP: ::c_int = 88; /// OSPFIGP pub const IPPROTO_OSPFIGP: ::c_int = 89; /// Strite RPC protocol pub const IPPROTO_SRPC: ::c_int = 90; /// Locus Address Resoloution pub const IPPROTO_LARP: ::c_int = 91; /// Multicast Transport pub const IPPROTO_MTP: ::c_int = 92; /// AX.25 Frames pub const IPPROTO_AX25: ::c_int = 93; /// IP encapsulated in IP pub const IPPROTO_IPEIP: ::c_int = 94; /// Mobile Int.ing control pub const IPPROTO_MICP: ::c_int = 95; /// Semaphore Comm. security pub const IPPROTO_SCCSP: ::c_int = 96; /// Ethernet IP encapsulation pub const IPPROTO_ETHERIP: ::c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: ::c_int = 98; /// any private encr. scheme pub const IPPROTO_APES: ::c_int = 99; /// GMTP pub const IPPROTO_GMTP: ::c_int = 100; /// payload compression (IPComp) pub const IPPROTO_IPCOMP: ::c_int = 108; /* 101-254: Partly Unassigned */ /// Protocol Independent Mcast pub const IPPROTO_PIM: ::c_int = 103; /// CARP pub const IPPROTO_CARP: ::c_int = 112; /// PGM pub const IPPROTO_PGM: ::c_int = 113; /// PFSYNC pub const IPPROTO_PFSYNC: ::c_int = 240; /* 255: Reserved */ /* BSD Private, local use, namespace incursion, no longer used */ /// divert pseudo-protocol pub const IPPROTO_DIVERT: ::c_int = 254; pub const IPPROTO_MAX: ::c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: ::c_int = 257; /// Used by RSS: the layer3 protocol is unknown pub const IPPROTO_UNKNOWN: ::c_int = 258; // sys/netinet/tcp.h pub const TCP_SIGNATURE_ENABLE: ::c_int = 16; pub const TCP_KEEPINIT: ::c_int = 32; pub const TCP_FASTKEEP: ::c_int = 128; pub const AF_BLUETOOTH: ::c_int = 33; pub const AF_MPLS: ::c_int = 34; pub const AF_IEEE80211: ::c_int = 35; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const NET_RT_DUMP: ::c_int = 1; pub const NET_RT_FLAGS: ::c_int = 2; pub const NET_RT_IFLIST: ::c_int = 3; pub const NET_RT_MAXID: ::c_int = 4; pub const SOMAXOPT_SIZE: ::c_int = 65536; pub const MSG_UNUSED09: ::c_int = 0x00000200; pub const MSG_NOSIGNAL: ::c_int = 0x00000400; pub const MSG_SYNC: ::c_int = 0x00000800; pub const MSG_CMSG_CLOEXEC: ::c_int = 0x00001000; pub const MSG_FBLOCKING: ::c_int = 0x00010000; pub const MSG_FNONBLOCKING: ::c_int = 0x00020000; pub const MSG_FMASK: ::c_int = 0xFFFF0000; // sys/mount.h pub const MNT_NODEV: ::c_int = 0x00000010; pub const MNT_AUTOMOUNTED: ::c_int = 0x00000020; pub const MNT_TRIM: ::c_int = 0x01000000; pub const MNT_LOCAL: ::c_int = 0x00001000; pub const MNT_QUOTA: ::c_int = 0x00002000; pub const MNT_ROOTFS: ::c_int = 0x00004000; pub const MNT_USER: ::c_int = 0x00008000; pub const MNT_IGNORE: ::c_int = 0x00800000; // utmpx entry types pub const EMPTY: ::c_short = 0; pub const RUN_LVL: ::c_short = 1; pub const BOOT_TIME: ::c_short = 2; pub const OLD_TIME: ::c_short = 3; pub const NEW_TIME: ::c_short = 4; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const USER_PROCESS: ::c_short = 7; pub const DEAD_PROCESS: ::c_short = 8; pub const ACCOUNTING: ::c_short = 9; pub const SIGNATURE: ::c_short = 10; pub const DOWNTIME: ::c_short = 11; // utmpx database types pub const UTX_DB_UTMPX: ::c_uint = 0; pub const UTX_DB_WTMPX: ::c_uint = 1; pub const UTX_DB_LASTLOG: ::c_uint = 2; pub const _UTX_LINESIZE: usize = 32; pub const _UTX_USERSIZE: usize = 32; pub const _UTX_IDSIZE: usize = 4; pub const _UTX_HOSTSIZE: usize = 256; pub const LC_COLLATE_MASK: ::c_int = 1 << 0; pub const LC_CTYPE_MASK: ::c_int = 1 << 1; pub const LC_MONETARY_MASK: ::c_int = 1 << 2; pub const LC_NUMERIC_MASK: ::c_int = 1 << 3; pub const LC_TIME_MASK: ::c_int = 1 << 4; pub const LC_MESSAGES_MASK: ::c_int = 1 << 5; pub const LC_ALL_MASK: ::c_int = LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK; pub const TIOCSIG: ::c_ulong = 0x2000745f; pub const BTUARTDISC: ::c_int = 0x7; pub const TIOCDCDTIMESTAMP: ::c_ulong = 0x40107458; pub const TIOCISPTMASTER: ::c_ulong = 0x20007455; pub const TIOCMODG: ::c_ulong = 0x40047403; pub const TIOCMODS: ::c_ulong = 0x80047404; pub const TIOCREMOTE: ::c_ulong = 0x80047469; // Constants used by "at" family of system calls. pub const AT_FDCWD: ::c_int = 0xFFFAFDCD; // invalid file descriptor pub const AT_SYMLINK_NOFOLLOW: ::c_int = 1; pub const AT_REMOVEDIR: ::c_int = 2; pub const AT_EACCESS: ::c_int = 4; pub const AT_SYMLINK_FOLLOW: ::c_int = 8; pub const VCHECKPT: usize = 19; pub const _PC_2_SYMLINKS: ::c_int = 22; pub const _PC_TIMESTAMP_RESOLUTION: ::c_int = 23; pub const _SC_V7_ILP32_OFF32: ::c_int = 122; pub const _SC_V7_ILP32_OFFBIG: ::c_int = 123; pub const _SC_V7_LP64_OFF64: ::c_int = 124; pub const _SC_V7_LPBIG_OFFBIG: ::c_int = 125; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: ::c_int = 126; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 127; pub const WCONTINUED: ::c_int = 0x4; pub const WSTOPPED: ::c_int = 0x2; pub const WNOWAIT: ::c_int = 0x8; pub const WEXITED: ::c_int = 0x10; pub const WTRAPPED: ::c_int = 0x20; // Similar to FreeBSD, only the standardized ones are exposed. // There are more. pub const P_PID: idtype_t = 0; pub const P_PGID: idtype_t = 2; pub const P_ALL: idtype_t = 7; // Values for struct rtprio (type_ field) pub const RTP_PRIO_REALTIME: ::c_ushort = 0; pub const RTP_PRIO_NORMAL: ::c_ushort = 1; pub const RTP_PRIO_IDLE: ::c_ushort = 2; pub const RTP_PRIO_THREAD: ::c_ushort = 3; // Flags for chflags(2) pub const UF_NOHISTORY: ::c_ulong = 0x00000040; pub const UF_CACHE: ::c_ulong = 0x00000080; pub const UF_XLINK: ::c_ulong = 0x00000100; pub const SF_NOHISTORY: ::c_ulong = 0x00400000; pub const SF_CACHE: ::c_ulong = 0x00800000; pub const SF_XLINK: ::c_ulong = 0x01000000; // timespec constants pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const MINCORE_SUPER: ::c_int = 0x20; // kinfo_proc constants pub const MAXCOMLEN: usize = 16; pub const MAXLOGNAME: usize = 33; pub const NGROUPS: usize = 16; pub const RB_PAUSE: ::c_int = 0x40000; pub const RB_VIDEO: ::c_int = 0x20000000; const_fn! { {const} fn _CMSG_ALIGN(n: usize) -> usize { (n + (::mem::size_of::<::c_long>() - 1)) & !(::mem::size_of::<::c_long>() - 1) } } f! { pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(_CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { (_CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) + length as usize) as ::c_uint } pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr) -> *mut ::cmsghdr { let next = cmsg as usize + _CMSG_ALIGN((*cmsg).cmsg_len as usize) + _CMSG_ALIGN(::mem::size_of::<::cmsghdr>()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next <= max { (cmsg as usize + _CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut ::cmsghdr } else { 0 as *mut ::cmsghdr } } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) + _CMSG_ALIGN(length as usize)) as ::c_uint } pub fn CPU_ZERO(cpuset: &mut cpu_set_t) -> () { for slot in cpuset.ary.iter_mut() { *slot = 0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpu_set_t) -> () { let (idx, offset) = ((cpu >> 6) & 3, cpu & 63); cpuset.ary[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpu_set_t) -> () { let (idx, offset) = ((cpu >> 6) & 3, cpu & 63); cpuset.ary[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpu_set_t) -> bool { let (idx, offset) = ((cpu >> 6) & 3, cpu & 63); 0 != cpuset.ary[idx] & (1 << offset) } pub fn major(dev: ::dev_t) -> ::c_int { ((dev >> 8) & 0xff) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { (dev & 0xffff00ff) as ::c_int } } safe_f! { pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 } pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= major << 8; dev |= minor; dev } } extern "C" { pub fn __errno_location() -> *mut ::c_int; pub fn setgrent(); pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn setutxdb(_type: ::c_uint, file: *mut ::c_char) -> ::c_int; pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, timeout: *mut ::timespec) -> ::c_int; pub fn devname_r( dev: ::dev_t, mode: ::mode_t, buf: *mut ::c_char, len: ::size_t, ) -> *mut ::c_char; pub fn waitid( idtype: idtype_t, id: ::id_t, infop: *mut ::siginfo_t, options: ::c_int, ) -> ::c_int; pub fn freelocale(loc: ::locale_t); pub fn lwp_rtprio( function: ::c_int, pid: ::pid_t, lwpid: lwpid_t, rtp: *mut super::rtprio, ) -> ::c_int; pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn sched_getaffinity(pid: ::pid_t, cpusetsize: ::size_t, mask: *mut cpu_set_t) -> ::c_int; pub fn sched_setaffinity(pid: ::pid_t, cpusetsize: ::size_t, mask: *const cpu_set_t) -> ::c_int; pub fn sched_getcpu() -> ::c_int; pub fn setproctitle(fmt: *const ::c_char, ...); pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn procctl(idtype: ::idtype_t, id: ::id_t, cmd: ::c_int, data: *mut ::c_void) -> ::c_int; pub fn updwtmpx(file: *const ::c_char, ut: *const utmpx) -> ::c_int; pub fn getlastlogx(fname: *const ::c_char, uid: ::uid_t, ll: *mut lastlogx) -> *mut lastlogx; pub fn updlastlogx(fname: *const ::c_char, uid: ::uid_t, ll: *mut lastlogx) -> ::c_int; pub fn getutxuser(name: *const ::c_char) -> utmpx; pub fn utmpxname(file: *const ::c_char) -> ::c_int; pub fn sys_checkpoint(tpe: ::c_int, fd: ::c_int, pid: ::pid_t, retval: ::c_int) -> ::c_int; pub fn umtx_sleep(ptr: *const ::c_int, value: ::c_int, timeout: ::c_int) -> ::c_int; pub fn umtx_wakeup(ptr: *const ::c_int, count: ::c_int) -> ::c_int; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; pub fn getmntinfo(mntbufp: *mut *mut ::statfs, flags: ::c_int) -> ::c_int; pub fn getmntvinfo( mntbufp: *mut *mut ::statfs, mntvbufp: *mut *mut ::statvfs, flags: ::c_int, ) -> ::c_int; } #[link(name = "rt")] extern "C" { pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_error(aiocbp: *const aiocb) -> ::c_int; pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; pub fn lio_listio( mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent, ) -> ::c_int; pub fn reallocf(ptr: *mut ::c_void, size: ::size_t) -> *mut ::c_void; pub fn freezero(ptr: *mut ::c_void, size: ::size_t); } #[link(name = "kvm")] extern "C" { pub fn kvm_vm_map_entry_first( kvm: *mut ::kvm_t, map: vm_map_t, entry: vm_map_entry_t, ) -> vm_map_entry_t; pub fn kvm_vm_map_entry_next( kvm: *mut ::kvm_t, map: vm_map_entry_t, entry: vm_map_entry_t, ) -> vm_map_entry_t; } cfg_if! { if #[cfg(libc_thread_local)] { mod errno; pub use self::errno::*; } } libc/src/unix/bsd/freebsdlike/freebsd/0000775000175000017500000000000014661133735020667 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/freebsd/freebsd15/0000775000175000017500000000000014661133735022447 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs0000644000175000017500000000123214661133735023747 0ustar jamespagejamespagepub const PROC_KPTI_CTL: ::c_int = ::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: ::c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: ::c_int = 2; pub const PROC_KPTI_STATUS: ::c_int = ::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: ::c_int = 0x80000000; pub const PROC_LA_CTL: ::c_int = ::PROC_PROCCTL_MD_MIN + 2; pub const PROC_LA_STATUS: ::c_int = ::PROC_PROCCTL_MD_MIN + 3; pub const PROC_LA_CTL_LA48_ON_EXEC: ::c_int = 1; pub const PROC_LA_CTL_LA57_ON_EXEC: ::c_int = 2; pub const PROC_LA_CTL_DEFAULT_ON_EXEC: ::c_int = 3; pub const PROC_LA_STATUS_LA48: ::c_int = 0x01000000; pub const PROC_LA_STATUS_LA57: ::c_int = 0x02000000; libc/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs0000644000175000017500000004460714661133735023605 0ustar jamespagejamespage// APIs in FreeBSD 15 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = ::c_ulong; pub type shmatt_t = ::c_uint; pub type kpaddr_t = u64; pub type kssize_t = i64; pub type domainset_t = __c_anonymous_domainset; s! { pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, } pub struct kevent { pub ident: ::uintptr_t, pub filter: ::c_short, pub flags: ::c_ushort, pub fflags: ::c_uint, pub data: i64, pub udata: *mut ::c_void, pub ext: [u64; 4], } pub struct kvm_page { pub kp_version: ::u_int, pub kp_paddr: ::kpaddr_t, pub kp_kmap_vaddr: ::kvaddr_t, pub kp_dmap_vaddr: ::kvaddr_t, pub kp_prot: ::vm_prot_t, pub kp_offset: ::off_t, pub kp_len: ::size_t, } pub struct __c_anonymous_domainset { _priv: [::uintptr_t; 4], } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: ::c_int, /// Reserved: layout identifier. pub ki_layout: ::c_int, /// Address of command arguments. pub ki_args: *mut ::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut ::c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut ::c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut ::c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut ::c_void, // This is normally "struct filedesc". /// Pointer to open file info. pub ki_fd: *mut ::c_void, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut ::c_void, /// Sleep address. pub ki_wchan: *const ::c_void, /// Process identifier. pub ki_pid: ::pid_t, /// Parent process ID. pub ki_ppid: ::pid_t, /// Process group ID. pub ki_pgid: ::pid_t, /// tty process group ID. pub ki_tpgid: ::pid_t, /// Process session ID. pub ki_sid: ::pid_t, /// Terminal session ID. pub ki_tsid: ::pid_t, /// Job control counter. pub ki_jobc: ::c_short, /// Unused (just here for alignment). pub ki_spare_short1: ::c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: ::sigset_t, /// Current signal mask. pub ki_sigmask: ::sigset_t, /// Signals being ignored. pub ki_sigignore: ::sigset_t, /// Signals being caught by user. pub ki_sigcatch: ::sigset_t, /// Effective user ID. pub ki_uid: ::uid_t, /// Real user ID. pub ki_ruid: ::uid_t, /// Saved effective user ID. pub ki_svuid: ::uid_t, /// Real group ID. pub ki_rgid: ::gid_t, /// Saved effective group ID. pub ki_svgid: ::gid_t, /// Number of groups. pub ki_ngroups: ::c_short, /// Unused (just here for alignment). pub ki_spare_short2: ::c_short, /// Groups. pub ki_groups: [::gid_t; ::KI_NGROUPS], /// Virtual size. pub ki_size: ::vm_size_t, /// Current resident set size in pages. pub ki_rssize: ::segsz_t, /// Resident set size before last swap. pub ki_swrss: ::segsz_t, /// Text size (pages) XXX. pub ki_tsize: ::segsz_t, /// Data size (pages) XXX. pub ki_dsize: ::segsz_t, /// Stack size (pages). pub ki_ssize: ::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: ::u_short, /// Accounting flags. pub ki_acflag: ::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: ::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: ::u_int, /// Time since last blocked. pub ki_slptime: ::u_int, /// Time swapped in or out. pub ki_swtime: ::u_int, /// Number of copy-on-write faults. pub ki_cow: ::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: ::timeval, /// Time used by process children. pub ki_childtime: ::timeval, /// P_* flags. pub ki_flag: ::c_long, /// KI_* flags (below). pub ki_kiflag: ::c_long, /// Kernel trace points. pub ki_traceflag: ::c_int, /// S* process status. pub ki_stat: ::c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: ::c_char, /// Run queue index. pub ki_rqindex: ::c_char, /// Which cpu we are on. pub ki_oncpu_old: ::c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: ::c_uchar, /// Thread name. pub ki_tdname: [::c_char; ::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [::c_char; ::WMESGLEN + 1], /// Setlogin name. pub ki_login: [::c_char; ::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [::c_char; ::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [::c_char; ::COMMLEN + 1], /// Emulation name. pub ki_emul: [::c_char; ::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [::c_char; ::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [::c_char; ::MAXCOMLEN - ::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[::c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [::c_int; ::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: u64, /// Which cpu we are on. pub ki_oncpu: ::c_int, /// Last cpu we were on. pub ki_lastcpu: ::c_int, /// PID of tracing process. pub ki_tracer: ::c_int, /// P2_* flags. pub ki_flag2: ::c_int, /// Default FIB number. pub ki_fibnum: ::c_int, /// Credential flags. pub ki_cr_flags: ::u_int, /// Process jail ID. pub ki_jid: ::c_int, /// Number of threads in total. pub ki_numthreads: ::c_int, /// Thread ID. pub ki_tid: ::lwpid_t, /// Process priority. pub ki_pri: ::priority, /// Process rusage statistics. pub ki_rusage: ::rusage, /// rusage of children processes. pub ki_rusage_ch: ::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut ::c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut ::c_void, /// User convenience pointer. pub ki_udata: *mut ::c_void, // This is normally "struct thread". pub ki_tdaddr: *mut ::c_void, // This is normally "struct pwddesc". /// Pointer to process paths info. pub ki_pd: *mut ::c_void, pub ki_spareptrs: [*mut ::c_void; ::KI_NSPARE_PTR], pub ki_sparelongs: [::c_long; ::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: ::c_long, /// kthread flag. pub ki_tdflags: ::c_long, } } s_no_extra_traits! { pub struct dirent { pub d_fileno: ::ino_t, pub d_off: ::off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [::c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: ::uid_t, pub f_fsid: ::fsid_t, f_charspare: [::c_char; 80], pub f_fstypename: [::c_char; 16], pub f_mntfromname: [::c_char; 1024], pub f_mntonname: [::c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut ::c_char, pub vn_type: ::c_int, pub vn_mode: u16, pub vn_devname: [::c_char; ::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) } } impl Eq for statfs {} impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self .d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[::c_char] = &self.vn_devname; let other_vn_devname: &[::c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl ::fmt::Debug for vnstat { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let self_vn_devname: &[::c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl ::hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[::c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: ::c_int = 0x7fff_ffff; pub const ELAST: ::c_int = 97; pub const KF_TYPE_EVENTFD: ::c_int = 13; /// max length of devicename pub const SPECNAMELEN: ::c_int = 255; pub const KI_NSPARE_PTR: usize = 5; /// domainset policies pub const DOMAINSET_POLICY_INVALID: ::c_int = 0; pub const DOMAINSET_POLICY_ROUNDROBIN: ::c_int = 1; pub const DOMAINSET_POLICY_FIRSTTOUCH: ::c_int = 2; pub const DOMAINSET_POLICY_PREFER: ::c_int = 3; pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4; pub const MINCORE_SUPER: ::c_int = 0x60; safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } } f! { pub fn major(dev: ::dev_t) -> ::c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as ::c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn freelocale(loc: ::locale_t); pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn cpuset_getdomain( level: ::cpulevel_t, which: ::cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *mut ::domainset_t, policy: *mut ::c_int, ) -> ::c_int; pub fn cpuset_setdomain( level: ::cpulevel_t, which: ::cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *const ::domainset_t, policy: ::c_int, ) -> ::c_int; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_kerndisp(kd: *mut ::kvm_t) -> ::kssize_t; } cfg_if! { if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))] { mod b64; pub use self::b64::*; } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs0000644000175000017500000000153414661133735023411 0ustar jamespagejamespage#[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, st_padding0: i16, pub st_uid: ::uid_t, pub st_gid: ::gid_t, st_padding1: i32, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u64, pub st_spare: [u64; 10], } impl ::Copy for ::stat {} impl ::Clone for ::stat { fn clone(&self) -> ::stat { *self } } libc/src/unix/bsd/freebsdlike/freebsd/riscv64.rs0000644000175000017500000001253514661133735022541 0ustar jamespagejamespagepub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = ::c_int; pub type time_t = i64; pub type suseconds_t = ::c_long; pub type register_t = i64; s_no_extra_traits! { pub struct gpregs { pub gp_ra: ::register_t, pub gp_sp: ::register_t, pub gp_gp: ::register_t, pub gp_tp: ::register_t, pub gp_t: [::register_t; 7], pub gp_s: [::register_t; 12], pub gp_a: [::register_t; 8], pub gp_sepc: ::register_t, pub gp_sstatus: ::register_t, } pub struct fpregs { pub fp_x: [[::register_t; 2]; 32], pub fp_fcsr: ::register_t, pub fp_flags: ::c_int, pub fp_pad: ::c_int, } pub struct mcontext_t { pub mc_gpregs: gpregs, pub mc_fpregs: fpregs, pub mc_flags: ::c_int, pub mc_pad: ::c_int, pub mc_spare: [u64; 8], } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_longlong>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for gpregs { fn eq(&self, other: &gpregs) -> bool { self.gp_ra == other.gp_ra && self.gp_sp == other.gp_sp && self.gp_gp == other.gp_gp && self.gp_tp == other.gp_tp && self.gp_t.iter().zip(other.gp_t.iter()).all(|(a, b)| a == b) && self.gp_s.iter().zip(other.gp_s.iter()).all(|(a, b)| a == b) && self.gp_a.iter().zip(other.gp_a.iter()).all(|(a, b)| a == b) && self.gp_sepc == other.gp_sepc && self.gp_sstatus == other.gp_sstatus } } impl Eq for gpregs {} impl ::fmt::Debug for gpregs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("gpregs") .field("gp_ra", &self.gp_ra) .field("gp_sp", &self.gp_sp) .field("gp_gp", &self.gp_gp) .field("gp_tp", &self.gp_tp) .field("gp_t", &self.gp_t) .field("gp_s", &self.gp_s) .field("gp_a", &self.gp_a) .field("gp_sepc", &self.gp_sepc) .field("gp_sstatus", &self.gp_sstatus) .finish() } } impl ::hash::Hash for gpregs { fn hash(&self, state: &mut H) { self.gp_ra.hash(state); self.gp_sp.hash(state); self.gp_gp.hash(state); self.gp_tp.hash(state); self.gp_t.hash(state); self.gp_s.hash(state); self.gp_a.hash(state); self.gp_sepc.hash(state); self.gp_sstatus.hash(state); } } impl PartialEq for fpregs { fn eq(&self, other: &fpregs) -> bool { self.fp_x == other.fp_x && self.fp_fcsr == other.fp_fcsr && self.fp_flags == other.fp_flags && self.fp_pad == other.fp_pad } } impl Eq for fpregs {} impl ::fmt::Debug for fpregs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpregs") .field("fp_x", &self.fp_x) .field("fp_fcsr", &self.fp_fcsr) .field("fp_flags", &self.fp_flags) .field("fp_pad", &self.fp_pad) .finish() } } impl ::hash::Hash for fpregs { fn hash(&self, state: &mut H) { self.fp_x.hash(state); self.fp_fcsr.hash(state); self.fp_flags.hash(state); self.fp_pad.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_gpregs == other.mc_gpregs && self.mc_fpregs == other.mc_fpregs && self.mc_flags == other.mc_flags && self.mc_pad == other.mc_pad && self.mc_spare.iter().zip(other.mc_spare.iter()).all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("mc_gpregs", &self.mc_gpregs) .field("mc_fpregs", &self.mc_fpregs) .field("mc_flags", &self.mc_flags) .field("mc_pad", &self.mc_pad) .field("mc_spare", &self.mc_spare) .finish() } } impl ::hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_gpregs.hash(state); self.mc_fpregs.hash(state); self.mc_flags.hash(state); self.mc_pad.hash(state); self.mc_spare.hash(state); } } } } pub const MAP_32BIT: ::c_int = 0x00080000; pub const MINSIGSTKSZ: ::size_t = 4096; // 1024 * 4 libc/src/unix/bsd/freebsdlike/freebsd/powerpc.rs0000644000175000017500000000237014661133735022714 0ustar jamespagejamespagepub type c_char = u8; pub type c_long = i32; pub type c_ulong = u32; pub type wchar_t = i32; pub type time_t = i64; pub type suseconds_t = i32; pub type register_t = i32; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u32, pub st_lspare: i32, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_int>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 4 - 1; } } pub const MAP_32BIT: ::c_int = 0x00080000; pub const MINSIGSTKSZ: ::size_t = 2048; // 512 * 4 libc/src/unix/bsd/freebsdlike/freebsd/arm.rs0000644000175000017500000000261414661133735022015 0ustar jamespagejamespagepub type c_char = u8; pub type c_long = i32; pub type c_ulong = u32; pub type wchar_t = u32; pub type time_t = i64; pub type suseconds_t = i32; pub type register_t = i32; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_atime_pad: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_mtime_pad: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_ctime_pad: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u32, pub st_lspare: i32, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, pub st_birthtime_pad: ::c_long, } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_int>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 4 - 1; } } pub const MAP_32BIT: ::c_int = 0x00080000; pub const MINSIGSTKSZ: ::size_t = 4096; // 1024 * 4 libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/0000775000175000017500000000000014661133735022446 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs0000644000175000017500000000123214661133735023746 0ustar jamespagejamespagepub const PROC_KPTI_CTL: ::c_int = ::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: ::c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: ::c_int = 2; pub const PROC_KPTI_STATUS: ::c_int = ::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: ::c_int = 0x80000000; pub const PROC_LA_CTL: ::c_int = ::PROC_PROCCTL_MD_MIN + 2; pub const PROC_LA_STATUS: ::c_int = ::PROC_PROCCTL_MD_MIN + 3; pub const PROC_LA_CTL_LA48_ON_EXEC: ::c_int = 1; pub const PROC_LA_CTL_LA57_ON_EXEC: ::c_int = 2; pub const PROC_LA_CTL_DEFAULT_ON_EXEC: ::c_int = 3; pub const PROC_LA_STATUS_LA48: ::c_int = 0x01000000; pub const PROC_LA_STATUS_LA57: ::c_int = 0x02000000; libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs0000644000175000017500000004460714661133735023604 0ustar jamespagejamespage// APIs in FreeBSD 14 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = ::c_ulong; pub type shmatt_t = ::c_uint; pub type kpaddr_t = u64; pub type kssize_t = i64; pub type domainset_t = __c_anonymous_domainset; s! { pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, } pub struct kevent { pub ident: ::uintptr_t, pub filter: ::c_short, pub flags: ::c_ushort, pub fflags: ::c_uint, pub data: i64, pub udata: *mut ::c_void, pub ext: [u64; 4], } pub struct kvm_page { pub kp_version: ::u_int, pub kp_paddr: ::kpaddr_t, pub kp_kmap_vaddr: ::kvaddr_t, pub kp_dmap_vaddr: ::kvaddr_t, pub kp_prot: ::vm_prot_t, pub kp_offset: ::off_t, pub kp_len: ::size_t, } pub struct __c_anonymous_domainset { _priv: [::uintptr_t; 4], } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: ::c_int, /// Reserved: layout identifier. pub ki_layout: ::c_int, /// Address of command arguments. pub ki_args: *mut ::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut ::c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut ::c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut ::c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut ::c_void, // This is normally "struct filedesc". /// Pointer to open file info. pub ki_fd: *mut ::c_void, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut ::c_void, /// Sleep address. pub ki_wchan: *const ::c_void, /// Process identifier. pub ki_pid: ::pid_t, /// Parent process ID. pub ki_ppid: ::pid_t, /// Process group ID. pub ki_pgid: ::pid_t, /// tty process group ID. pub ki_tpgid: ::pid_t, /// Process session ID. pub ki_sid: ::pid_t, /// Terminal session ID. pub ki_tsid: ::pid_t, /// Job control counter. pub ki_jobc: ::c_short, /// Unused (just here for alignment). pub ki_spare_short1: ::c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: ::sigset_t, /// Current signal mask. pub ki_sigmask: ::sigset_t, /// Signals being ignored. pub ki_sigignore: ::sigset_t, /// Signals being caught by user. pub ki_sigcatch: ::sigset_t, /// Effective user ID. pub ki_uid: ::uid_t, /// Real user ID. pub ki_ruid: ::uid_t, /// Saved effective user ID. pub ki_svuid: ::uid_t, /// Real group ID. pub ki_rgid: ::gid_t, /// Saved effective group ID. pub ki_svgid: ::gid_t, /// Number of groups. pub ki_ngroups: ::c_short, /// Unused (just here for alignment). pub ki_spare_short2: ::c_short, /// Groups. pub ki_groups: [::gid_t; ::KI_NGROUPS], /// Virtual size. pub ki_size: ::vm_size_t, /// Current resident set size in pages. pub ki_rssize: ::segsz_t, /// Resident set size before last swap. pub ki_swrss: ::segsz_t, /// Text size (pages) XXX. pub ki_tsize: ::segsz_t, /// Data size (pages) XXX. pub ki_dsize: ::segsz_t, /// Stack size (pages). pub ki_ssize: ::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: ::u_short, /// Accounting flags. pub ki_acflag: ::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: ::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: ::u_int, /// Time since last blocked. pub ki_slptime: ::u_int, /// Time swapped in or out. pub ki_swtime: ::u_int, /// Number of copy-on-write faults. pub ki_cow: ::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: ::timeval, /// Time used by process children. pub ki_childtime: ::timeval, /// P_* flags. pub ki_flag: ::c_long, /// KI_* flags (below). pub ki_kiflag: ::c_long, /// Kernel trace points. pub ki_traceflag: ::c_int, /// S* process status. pub ki_stat: ::c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: ::c_char, /// Run queue index. pub ki_rqindex: ::c_char, /// Which cpu we are on. pub ki_oncpu_old: ::c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: ::c_uchar, /// Thread name. pub ki_tdname: [::c_char; ::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [::c_char; ::WMESGLEN + 1], /// Setlogin name. pub ki_login: [::c_char; ::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [::c_char; ::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [::c_char; ::COMMLEN + 1], /// Emulation name. pub ki_emul: [::c_char; ::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [::c_char; ::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [::c_char; ::MAXCOMLEN - ::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[::c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [::c_int; ::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: u64, /// Which cpu we are on. pub ki_oncpu: ::c_int, /// Last cpu we were on. pub ki_lastcpu: ::c_int, /// PID of tracing process. pub ki_tracer: ::c_int, /// P2_* flags. pub ki_flag2: ::c_int, /// Default FIB number. pub ki_fibnum: ::c_int, /// Credential flags. pub ki_cr_flags: ::u_int, /// Process jail ID. pub ki_jid: ::c_int, /// Number of threads in total. pub ki_numthreads: ::c_int, /// Thread ID. pub ki_tid: ::lwpid_t, /// Process priority. pub ki_pri: ::priority, /// Process rusage statistics. pub ki_rusage: ::rusage, /// rusage of children processes. pub ki_rusage_ch: ::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut ::c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut ::c_void, /// User convenience pointer. pub ki_udata: *mut ::c_void, // This is normally "struct thread". pub ki_tdaddr: *mut ::c_void, // This is normally "struct pwddesc". /// Pointer to process paths info. pub ki_pd: *mut ::c_void, pub ki_spareptrs: [*mut ::c_void; ::KI_NSPARE_PTR], pub ki_sparelongs: [::c_long; ::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: ::c_long, /// kthread flag. pub ki_tdflags: ::c_long, } } s_no_extra_traits! { pub struct dirent { pub d_fileno: ::ino_t, pub d_off: ::off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [::c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: ::uid_t, pub f_fsid: ::fsid_t, f_charspare: [::c_char; 80], pub f_fstypename: [::c_char; 16], pub f_mntfromname: [::c_char; 1024], pub f_mntonname: [::c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut ::c_char, pub vn_type: ::c_int, pub vn_mode: u16, pub vn_devname: [::c_char; ::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) } } impl Eq for statfs {} impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self .d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[::c_char] = &self.vn_devname; let other_vn_devname: &[::c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl ::fmt::Debug for vnstat { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let self_vn_devname: &[::c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl ::hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[::c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: ::c_int = 0x7fff_ffff; pub const ELAST: ::c_int = 97; pub const KF_TYPE_EVENTFD: ::c_int = 13; /// max length of devicename pub const SPECNAMELEN: ::c_int = 255; pub const KI_NSPARE_PTR: usize = 5; /// domainset policies pub const DOMAINSET_POLICY_INVALID: ::c_int = 0; pub const DOMAINSET_POLICY_ROUNDROBIN: ::c_int = 1; pub const DOMAINSET_POLICY_FIRSTTOUCH: ::c_int = 2; pub const DOMAINSET_POLICY_PREFER: ::c_int = 3; pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4; pub const MINCORE_SUPER: ::c_int = 0x60; safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } } f! { pub fn major(dev: ::dev_t) -> ::c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as ::c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn freelocale(loc: ::locale_t); pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn cpuset_getdomain( level: ::cpulevel_t, which: ::cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *mut ::domainset_t, policy: *mut ::c_int, ) -> ::c_int; pub fn cpuset_setdomain( level: ::cpulevel_t, which: ::cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *const ::domainset_t, policy: ::c_int, ) -> ::c_int; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_kerndisp(kd: *mut ::kvm_t) -> ::kssize_t; } cfg_if! { if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))] { mod b64; pub use self::b64::*; } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs0000644000175000017500000000153414661133735023410 0ustar jamespagejamespage#[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, st_padding0: i16, pub st_uid: ::uid_t, pub st_gid: ::gid_t, st_padding1: i32, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u64, pub st_spare: [u64; 10], } impl ::Copy for ::stat {} impl ::Clone for ::stat { fn clone(&self) -> ::stat { *self } } libc/src/unix/bsd/freebsdlike/freebsd/x86.rs0000644000175000017500000001664114661133735021670 0ustar jamespagejamespagepub type c_char = i8; pub type c_long = i32; pub type c_ulong = u32; pub type wchar_t = i32; pub type time_t = i32; pub type suseconds_t = i32; pub type register_t = i32; s_no_extra_traits! { pub struct mcontext_t { pub mc_onstack: register_t, pub mc_gs: register_t, pub mc_fs: register_t, pub mc_es: register_t, pub mc_ds: register_t, pub mc_edi: register_t, pub mc_esi: register_t, pub mc_ebp: register_t, pub mc_isp: register_t, pub mc_ebx: register_t, pub mc_edx: register_t, pub mc_ecx: register_t, pub mc_eax: register_t, pub mc_trapno: register_t, pub mc_err: register_t, pub mc_eip: register_t, pub mc_cs: register_t, pub mc_eflags: register_t, pub mc_esp: register_t, pub mc_ss: register_t, pub mc_len: ::c_int, pub mc_fpformat: ::c_int, pub mc_ownedfp: ::c_int, pub mc_flags: register_t, pub mc_fpstate: [[::c_int; 32]; 4], pub mc_fsbase: register_t, pub mc_gsbase: register_t, pub mc_xfpustate: register_t, pub mc_xfpustate_len: register_t, pub mc_spare2: [::c_int; 4], } } s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u32, pub st_lspare: i32, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, __unused: [u8; 8], } pub struct ucontext_t { pub uc_sigmask: ::sigset_t, pub uc_mcontext: ::mcontext_t, pub uc_link: *mut ::ucontext_t, pub uc_stack: ::stack_t, pub uc_flags: ::c_int, __spare__: [::c_int; 4], } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 4 - 1; } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_onstack == other.mc_onstack && self.mc_gs == other.mc_gs && self.mc_fs == other.mc_fs && self.mc_es == other.mc_es && self.mc_ds == other.mc_ds && self.mc_edi == other.mc_edi && self.mc_esi == other.mc_esi && self.mc_ebp == other.mc_ebp && self.mc_isp == other.mc_isp && self.mc_ebx == other.mc_ebx && self.mc_edx == other.mc_edx && self.mc_ecx == other.mc_ecx && self.mc_eax == other.mc_eax && self.mc_trapno == other.mc_trapno && self.mc_err == other.mc_err && self.mc_eip == other.mc_eip && self.mc_cs == other.mc_cs && self.mc_eflags == other.mc_eflags && self.mc_esp == other.mc_esp && self.mc_ss == other.mc_ss && self.mc_len == other.mc_len && self.mc_fpformat == other.mc_fpformat && self.mc_ownedfp == other.mc_ownedfp && self.mc_flags == other.mc_flags && self.mc_fpstate.iter().zip(other.mc_fpstate.iter()).all(|(a, b)| a == b) && self.mc_fsbase == other.mc_fsbase && self.mc_gsbase == other.mc_gsbase && self.mc_xfpustate == other.mc_xfpustate && self.mc_xfpustate_len == other.mc_xfpustate_len && self.mc_spare2.iter().zip(other.mc_spare2.iter()).all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("mc_onstack", &self.mc_onstack) .field("mc_gs", &self.mc_gs) .field("mc_fs", &self.mc_fs) .field("mc_es", &self.mc_es) .field("mc_ds", &self.mc_ds) .field("mc_edi", &self.mc_edi) .field("mc_esi", &self.mc_esi) .field("mc_ebp", &self.mc_ebp) .field("mc_isp", &self.mc_isp) .field("mc_ebx", &self.mc_ebx) .field("mc_edx", &self.mc_edx) .field("mc_ecx", &self.mc_ecx) .field("mc_eax", &self.mc_eax) .field("mc_trapno", &self.mc_trapno) .field("mc_err", &self.mc_err) .field("mc_eip", &self.mc_eip) .field("mc_cs", &self.mc_cs) .field("mc_eflags", &self.mc_eflags) .field("mc_esp", &self.mc_esp) .field("mc_ss", &self.mc_ss) .field("mc_len", &self.mc_len) .field("mc_fpformat", &self.mc_fpformat) .field("mc_ownedfp", &self.mc_ownedfp) .field("mc_flags", &self.mc_flags) .field("mc_fpstate", &self.mc_fpstate) .field("mc_fsbase", &self.mc_fsbase) .field("mc_gsbase", &self.mc_gsbase) .field("mc_xfpustate", &self.mc_xfpustate) .field("mc_xfpustate_len", &self.mc_xfpustate_len) .field("mc_spare2", &self.mc_spare2) .finish() } } impl ::hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_onstack.hash(state); self.mc_gs.hash(state); self.mc_fs.hash(state); self.mc_es.hash(state); self.mc_ds.hash(state); self.mc_edi.hash(state); self.mc_esi.hash(state); self.mc_ebp.hash(state); self.mc_isp.hash(state); self.mc_ebx.hash(state); self.mc_edx.hash(state); self.mc_ecx.hash(state); self.mc_eax.hash(state); self.mc_trapno.hash(state); self.mc_err.hash(state); self.mc_eip.hash(state); self.mc_cs.hash(state); self.mc_eflags.hash(state); self.mc_esp.hash(state); self.mc_ss.hash(state); self.mc_len.hash(state); self.mc_fpformat.hash(state); self.mc_ownedfp.hash(state); self.mc_flags.hash(state); self.mc_fpstate.hash(state); self.mc_fsbase.hash(state); self.mc_gsbase.hash(state); self.mc_xfpustate.hash(state); self.mc_xfpustate_len.hash(state); self.mc_spare2.hash(state); } } } } pub const MINSIGSTKSZ: ::size_t = 2048; // 512 * 4 libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/0000775000175000017500000000000014661133735022443 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs0000644000175000017500000004215414661133735023574 0ustar jamespagejamespage// APIs that were changed after FreeBSD 11 // The type of `nlink_t` changed from `u16` to `u64` in FreeBSD 12: pub type nlink_t = u16; // Type of `dev_t` changed from `u32` to `u64` in FreeBSD 12: pub type dev_t = u32; // Type of `ino_t` changed from `unsigned int` to `unsigned long` in FreeBSD 12: pub type ino_t = u32; s! { pub struct kevent { pub ident: ::uintptr_t, pub filter: ::c_short, pub flags: ::c_ushort, pub fflags: ::c_uint, pub data: ::intptr_t, pub udata: *mut ::c_void, } pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, // Type of shm_nattc changed from `int` to `shmatt_t` (aka `unsigned // int`) in FreeBSD 12: pub shm_nattch: ::c_int, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: ::c_int, /// Reserved: layout identifier. pub ki_layout: ::c_int, /// Address of command arguments. pub ki_args: *mut ::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut ::c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut ::c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut ::c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut ::c_void, // This is normally "struct filedesc". /// Pointer to open file info. pub ki_fd: *mut ::c_void, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut ::c_void, /// Sleep address. pub ki_wchan: *mut ::c_void, /// Process identifier. pub ki_pid: ::pid_t, /// Parent process ID. pub ki_ppid: ::pid_t, /// Process group ID. pub ki_pgid: ::pid_t, /// tty process group ID. pub ki_tpgid: ::pid_t, /// Process session ID. pub ki_sid: ::pid_t, /// Terminal session ID. pub ki_tsid: ::pid_t, /// Job control counter. pub ki_jobc: ::c_short, /// Unused (just here for alignment). pub ki_spare_short1: ::c_short, /// Controlling tty dev. pub ki_tdev: ::dev_t, /// Signals arrived but not delivered. pub ki_siglist: ::sigset_t, /// Current signal mask. pub ki_sigmask: ::sigset_t, /// Signals being ignored. pub ki_sigignore: ::sigset_t, /// Signals being caught by user. pub ki_sigcatch: ::sigset_t, /// Effective user ID. pub ki_uid: ::uid_t, /// Real user ID. pub ki_ruid: ::uid_t, /// Saved effective user ID. pub ki_svuid: ::uid_t, /// Real group ID. pub ki_rgid: ::gid_t, /// Saved effective group ID. pub ki_svgid: ::gid_t, /// Number of groups. pub ki_ngroups: ::c_short, /// Unused (just here for alignment). pub ki_spare_short2: ::c_short, /// Groups. pub ki_groups: [::gid_t; ::KI_NGROUPS], /// Virtual size. pub ki_size: ::vm_size_t, /// Current resident set size in pages. pub ki_rssize: ::segsz_t, /// Resident set size before last swap. pub ki_swrss: ::segsz_t, /// Text size (pages) XXX. pub ki_tsize: ::segsz_t, /// Data size (pages) XXX. pub ki_dsize: ::segsz_t, /// Stack size (pages). pub ki_ssize: ::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: ::u_short, /// Accounting flags. pub ki_acflag: ::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: ::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: ::u_int, /// Time since last blocked. pub ki_slptime: ::u_int, /// Time swapped in or out. pub ki_swtime: ::u_int, /// Number of copy-on-write faults. pub ki_cow: ::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: ::timeval, /// Time used by process children. pub ki_childtime: ::timeval, /// P_* flags. pub ki_flag: ::c_long, /// KI_* flags (below). pub ki_kiflag: ::c_long, /// Kernel trace points. pub ki_traceflag: ::c_int, /// S* process status. pub ki_stat: ::c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: ::c_char, /// Run queue index. pub ki_rqindex: ::c_char, /// Which cpu we are on. pub ki_oncpu_old: ::c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: ::c_uchar, /// Thread name. pub ki_tdname: [::c_char; ::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [::c_char; ::WMESGLEN + 1], /// Setlogin name. pub ki_login: [::c_char; ::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [::c_char; ::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [::c_char; ::COMMLEN + 1], /// Emulation name. pub ki_emul: [::c_char; ::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [::c_char; ::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [::c_char; ::MAXCOMLEN - ::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[::c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [::c_int; ::KI_NSPARE_INT], /// Which cpu we are on. pub ki_oncpu: ::c_int, /// Last cpu we were on. pub ki_lastcpu: ::c_int, /// PID of tracing process. pub ki_tracer: ::c_int, /// P2_* flags. pub ki_flag2: ::c_int, /// Default FIB number. pub ki_fibnum: ::c_int, /// Credential flags. pub ki_cr_flags: ::u_int, /// Process jail ID. pub ki_jid: ::c_int, /// Number of threads in total. pub ki_numthreads: ::c_int, /// Thread ID. pub ki_tid: ::lwpid_t, /// Process priority. pub ki_pri: ::priority, /// Process rusage statistics. pub ki_rusage: ::rusage, /// rusage of children processes. pub ki_rusage_ch: ::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut ::c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut ::c_void, /// User convenience pointer. pub ki_udata: *mut ::c_void, // This is normally "struct thread". pub ki_tdaddr: *mut ::c_void, pub ki_spareptrs: [*mut ::c_void; ::KI_NSPARE_PTR], pub ki_sparelongs: [::c_long; ::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: ::c_long, /// kthread flag. pub ki_tdflags: ::c_long, } } s_no_extra_traits! { pub struct dirent { pub d_fileno: ::ino_t, pub d_reclen: u16, pub d_type: u8, // Type of `d_namlen` changed from `char` to `u16` in FreeBSD 12: pub d_namlen: u8, pub d_name: [::c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: ::uid_t, pub f_fsid: ::fsid_t, f_charspare: [::c_char; 80], pub f_fstypename: [::c_char; 16], // Array length changed from 88 to 1024 in FreeBSD 12: pub f_mntfromname: [::c_char; 88], // Array length changed from 88 to 1024 in FreeBSD 12: pub f_mntonname: [::c_char; 88], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_mntdir: *mut ::c_char, pub vn_dev: u32, pub vn_fsid: u32, pub vn_type: ::c_int, pub vn_mode: u16, pub vn_devname: [::c_char; ::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) } } impl Eq for statfs {} impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self .d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[::c_char] = &self.vn_devname; let other_vn_devname: &[::c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_mntdir == other.vn_mntdir && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl ::fmt::Debug for vnstat { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let self_vn_devname: &[::c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_mntdir", &self.vn_mntdir) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl ::hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[::c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_mntdir.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const ELAST: ::c_int = 96; pub const RAND_MAX: ::c_int = 0x7fff_fffd; pub const KI_NSPARE_PTR: usize = 6; pub const MINCORE_SUPER: ::c_int = 0x20; /// max length of devicename pub const SPECNAMELEN: ::c_int = 63; safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; (major << 8) | minor } } f! { pub fn major(dev: ::dev_t) -> ::c_int { ((dev >> 8) & 0xff) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { (dev & 0xffff00ff) as ::c_int } } extern "C" { // Return type ::c_int was removed in FreeBSD 12 pub fn setgrent() -> ::c_int; // Type of `addr` argument changed from `const void*` to `void*` // in FreeBSD 12 pub fn mprotect(addr: *const ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; // Return type ::c_int was removed in FreeBSD 12 pub fn freelocale(loc: ::locale_t) -> ::c_int; // Return type ::c_int changed to ::ssize_t in FreeBSD 12: pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::c_int; // Type of `path` argument changed from `const void*` to `void*` // in FreeBSD 12 pub fn dirname(path: *const ::c_char) -> *mut ::c_char; pub fn basename(path: *const ::c_char) -> *mut ::c_char; } cfg_if! { if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))] { mod b64; pub use self::b64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs0000644000175000017500000000145314661133735023405 0ustar jamespagejamespage#[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u32, pub st_lspare: i32, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, } impl ::Copy for ::stat {} impl ::Clone for ::stat { fn clone(&self) -> ::stat { *self } } libc/src/unix/bsd/freebsdlike/freebsd/mod.rs0000644000175000017500000060270414661133735022023 0ustar jamespagejamespagepub type fflags_t = u32; pub type clock_t = i32; pub type vm_prot_t = u_char; pub type kvaddr_t = u64; pub type segsz_t = isize; pub type __fixpt_t = u32; pub type fixpt_t = __fixpt_t; pub type __lwpid_t = i32; pub type lwpid_t = __lwpid_t; pub type blksize_t = i32; pub type clockid_t = ::c_int; pub type sem_t = _sem; pub type timer_t = *mut __c_anonymous__timer; pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u64; pub type idtype_t = ::c_uint; pub type msglen_t = ::c_ulong; pub type msgqnum_t = ::c_ulong; pub type cpulevel_t = ::c_int; pub type cpuwhich_t = ::c_int; pub type mqd_t = *mut ::c_void; pub type posix_spawnattr_t = *mut ::c_void; pub type posix_spawn_file_actions_t = *mut ::c_void; pub type pthread_spinlock_t = *mut __c_anonymous_pthread_spinlock; pub type pthread_barrierattr_t = *mut __c_anonymous_pthread_barrierattr; pub type pthread_barrier_t = *mut __c_anonymous_pthread_barrier; pub type uuid_t = ::uuid; pub type u_int = ::c_uint; pub type u_char = ::c_uchar; pub type u_long = ::c_ulong; pub type u_short = ::c_ushort; pub type caddr_t = *mut ::c_char; pub type fhandle_t = fhandle; pub type au_id_t = ::uid_t; pub type au_asid_t = ::pid_t; pub type cpusetid_t = ::c_int; pub type sctp_assoc_t = u32; pub type eventfd_t = u64; #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_support_flags { DEVSTAT_ALL_SUPPORTED = 0x00, DEVSTAT_NO_BLOCKSIZE = 0x01, DEVSTAT_NO_ORDERED_TAGS = 0x02, DEVSTAT_BS_UNAVAILABLE = 0x04, } impl ::Copy for devstat_support_flags {} impl ::Clone for devstat_support_flags { fn clone(&self) -> devstat_support_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_trans_flags { DEVSTAT_NO_DATA = 0x00, DEVSTAT_READ = 0x01, DEVSTAT_WRITE = 0x02, DEVSTAT_FREE = 0x03, } impl ::Copy for devstat_trans_flags {} impl ::Clone for devstat_trans_flags { fn clone(&self) -> devstat_trans_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_tag_type { DEVSTAT_TAG_SIMPLE = 0x00, DEVSTAT_TAG_HEAD = 0x01, DEVSTAT_TAG_ORDERED = 0x02, DEVSTAT_TAG_NONE = 0x03, } impl ::Copy for devstat_tag_type {} impl ::Clone for devstat_tag_type { fn clone(&self) -> devstat_tag_type { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_match_flags { DEVSTAT_MATCH_NONE = 0x00, DEVSTAT_MATCH_TYPE = 0x01, DEVSTAT_MATCH_IF = 0x02, DEVSTAT_MATCH_PASS = 0x04, } impl ::Copy for devstat_match_flags {} impl ::Clone for devstat_match_flags { fn clone(&self) -> devstat_match_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_priority { DEVSTAT_PRIORITY_MIN = 0x000, DEVSTAT_PRIORITY_OTHER = 0x020, DEVSTAT_PRIORITY_PASS = 0x030, DEVSTAT_PRIORITY_FD = 0x040, DEVSTAT_PRIORITY_WFD = 0x050, DEVSTAT_PRIORITY_TAPE = 0x060, DEVSTAT_PRIORITY_CD = 0x090, DEVSTAT_PRIORITY_DISK = 0x110, DEVSTAT_PRIORITY_ARRAY = 0x120, DEVSTAT_PRIORITY_MAX = 0xfff, } impl ::Copy for devstat_priority {} impl ::Clone for devstat_priority { fn clone(&self) -> devstat_priority { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_type_flags { DEVSTAT_TYPE_DIRECT = 0x000, DEVSTAT_TYPE_SEQUENTIAL = 0x001, DEVSTAT_TYPE_PRINTER = 0x002, DEVSTAT_TYPE_PROCESSOR = 0x003, DEVSTAT_TYPE_WORM = 0x004, DEVSTAT_TYPE_CDROM = 0x005, DEVSTAT_TYPE_SCANNER = 0x006, DEVSTAT_TYPE_OPTICAL = 0x007, DEVSTAT_TYPE_CHANGER = 0x008, DEVSTAT_TYPE_COMM = 0x009, DEVSTAT_TYPE_ASC0 = 0x00a, DEVSTAT_TYPE_ASC1 = 0x00b, DEVSTAT_TYPE_STORARRAY = 0x00c, DEVSTAT_TYPE_ENCLOSURE = 0x00d, DEVSTAT_TYPE_FLOPPY = 0x00e, DEVSTAT_TYPE_MASK = 0x00f, DEVSTAT_TYPE_IF_SCSI = 0x010, DEVSTAT_TYPE_IF_IDE = 0x020, DEVSTAT_TYPE_IF_OTHER = 0x030, DEVSTAT_TYPE_IF_MASK = 0x0f0, DEVSTAT_TYPE_PASS = 0x100, } impl ::Copy for devstat_type_flags {} impl ::Clone for devstat_type_flags { fn clone(&self) -> devstat_type_flags { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_metric { DSM_NONE, DSM_TOTAL_BYTES, DSM_TOTAL_BYTES_READ, DSM_TOTAL_BYTES_WRITE, DSM_TOTAL_TRANSFERS, DSM_TOTAL_TRANSFERS_READ, DSM_TOTAL_TRANSFERS_WRITE, DSM_TOTAL_TRANSFERS_OTHER, DSM_TOTAL_BLOCKS, DSM_TOTAL_BLOCKS_READ, DSM_TOTAL_BLOCKS_WRITE, DSM_KB_PER_TRANSFER, DSM_KB_PER_TRANSFER_READ, DSM_KB_PER_TRANSFER_WRITE, DSM_TRANSFERS_PER_SECOND, DSM_TRANSFERS_PER_SECOND_READ, DSM_TRANSFERS_PER_SECOND_WRITE, DSM_TRANSFERS_PER_SECOND_OTHER, DSM_MB_PER_SECOND, DSM_MB_PER_SECOND_READ, DSM_MB_PER_SECOND_WRITE, DSM_BLOCKS_PER_SECOND, DSM_BLOCKS_PER_SECOND_READ, DSM_BLOCKS_PER_SECOND_WRITE, DSM_MS_PER_TRANSACTION, DSM_MS_PER_TRANSACTION_READ, DSM_MS_PER_TRANSACTION_WRITE, DSM_SKIP, DSM_TOTAL_BYTES_FREE, DSM_TOTAL_TRANSFERS_FREE, DSM_TOTAL_BLOCKS_FREE, DSM_KB_PER_TRANSFER_FREE, DSM_MB_PER_SECOND_FREE, DSM_TRANSFERS_PER_SECOND_FREE, DSM_BLOCKS_PER_SECOND_FREE, DSM_MS_PER_TRANSACTION_OTHER, DSM_MS_PER_TRANSACTION_FREE, DSM_BUSY_PCT, DSM_QUEUE_LENGTH, DSM_TOTAL_DURATION, DSM_TOTAL_DURATION_READ, DSM_TOTAL_DURATION_WRITE, DSM_TOTAL_DURATION_FREE, DSM_TOTAL_DURATION_OTHER, DSM_TOTAL_BUSY_TIME, DSM_MAX, } impl ::Copy for devstat_metric {} impl ::Clone for devstat_metric { fn clone(&self) -> devstat_metric { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))] #[repr(u32)] pub enum devstat_select_mode { DS_SELECT_ADD, DS_SELECT_ONLY, DS_SELECT_REMOVE, DS_SELECT_ADDONLY, } impl ::Copy for devstat_select_mode {} impl ::Clone for devstat_select_mode { fn clone(&self) -> devstat_select_mode { *self } } s! { pub struct aiocb { pub aio_fildes: ::c_int, pub aio_offset: ::off_t, pub aio_buf: *mut ::c_void, pub aio_nbytes: ::size_t, __unused1: [::c_int; 2], __unused2: *mut ::c_void, pub aio_lio_opcode: ::c_int, pub aio_reqprio: ::c_int, // unused 3 through 5 are the __aiocb_private structure __unused3: ::c_long, __unused4: ::c_long, __unused5: *mut ::c_void, pub aio_sigevent: sigevent } pub struct jail { pub version: u32, pub path: *mut ::c_char, pub hostname: *mut ::c_char, pub jailname: *mut ::c_char, pub ip4s: ::c_uint, pub ip6s: ::c_uint, pub ip4: *mut ::in_addr, pub ip6: *mut ::in6_addr, } pub struct statvfs { pub f_bavail: ::fsblkcnt_t, pub f_bfree: ::fsblkcnt_t, pub f_blocks: ::fsblkcnt_t, pub f_favail: ::fsfilcnt_t, pub f_ffree: ::fsfilcnt_t, pub f_files: ::fsfilcnt_t, pub f_bsize: ::c_ulong, pub f_flag: ::c_ulong, pub f_frsize: ::c_ulong, pub f_fsid: ::c_ulong, pub f_namemax: ::c_ulong, } // internal structure has changed over time pub struct _sem { data: [u32; 4], } pub struct sembuf { pub sem_num: ::c_ushort, pub sem_op: ::c_short, pub sem_flg: ::c_short, } pub struct msqid_ds { pub msg_perm: ::ipc_perm, __unused1: *mut ::c_void, __unused2: *mut ::c_void, pub msg_cbytes: ::msglen_t, pub msg_qnum: ::msgqnum_t, pub msg_qbytes: ::msglen_t, pub msg_lspid: ::pid_t, pub msg_lrpid: ::pid_t, pub msg_stime: ::time_t, pub msg_rtime: ::time_t, pub msg_ctime: ::time_t, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_size: ::size_t, pub ss_flags: ::c_int, } pub struct mmsghdr { pub msg_hdr: ::msghdr, pub msg_len: ::ssize_t, } pub struct sockcred { pub sc_uid: ::uid_t, pub sc_euid: ::uid_t, pub sc_gid: ::gid_t, pub sc_egid: ::gid_t, pub sc_ngroups: ::c_int, pub sc_groups: [::gid_t; 1], } pub struct ptrace_vm_entry { pub pve_entry: ::c_int, pub pve_timestamp: ::c_int, pub pve_start: ::c_ulong, pub pve_end: ::c_ulong, pub pve_offset: ::c_ulong, pub pve_prot: ::c_uint, pub pve_pathlen: ::c_uint, pub pve_fileid: ::c_long, pub pve_fsid: u32, pub pve_path: *mut ::c_char, } pub struct ptrace_lwpinfo { pub pl_lwpid: lwpid_t, pub pl_event: ::c_int, pub pl_flags: ::c_int, pub pl_sigmask: ::sigset_t, pub pl_siglist: ::sigset_t, pub pl_siginfo: ::siginfo_t, pub pl_tdname: [::c_char; ::MAXCOMLEN as usize + 1], pub pl_child_pid: ::pid_t, pub pl_syscall_code: ::c_uint, pub pl_syscall_narg: ::c_uint, } pub struct ptrace_sc_ret { pub sr_retval: [::register_t; 2], pub sr_error: ::c_int, } pub struct ptrace_coredump { pub pc_fd: ::c_int, pub pc_flags: u32, pub pc_limit: ::off_t, } pub struct ptrace_sc_remote { pub pscr_ret: ptrace_sc_ret, pub pscr_syscall: ::c_uint, pub pscr_nargs: ::c_uint, pub pscr_args: *mut ::register_t, } pub struct cpuset_t { #[cfg(all(any(freebsd15, freebsd14), target_pointer_width = "64"))] __bits: [::c_long; 16], #[cfg(all(any(freebsd15, freebsd14), target_pointer_width = "32"))] __bits: [::c_long; 32], #[cfg(all(not(any(freebsd15, freebsd14)), target_pointer_width = "64"))] __bits: [::c_long; 4], #[cfg(all(not(any(freebsd15, freebsd14)), target_pointer_width = "32"))] __bits: [::c_long; 8], } pub struct cap_rights_t { cr_rights: [u64; 2], } pub struct umutex { m_owner: ::lwpid_t, m_flags: u32, m_ceilings: [u32; 2], m_rb_link: ::uintptr_t, #[cfg(target_pointer_width = "32")] m_pad: u32, m_spare: [u32; 2], } pub struct ucond { c_has_waiters: u32, c_flags: u32, c_clockid: u32, c_spare: [u32; 1], } pub struct uuid { pub time_low: u32, pub time_mid: u16, pub time_hi_and_version: u16, pub clock_seq_hi_and_reserved: u8, pub clock_seq_low: u8, pub node: [u8; _UUID_NODE_LEN], } pub struct __c_anonymous_pthread_spinlock { s_clock: umutex, } pub struct __c_anonymous_pthread_barrierattr { pshared: ::c_int, } pub struct __c_anonymous_pthread_barrier { b_lock: umutex, b_cv: ucond, b_cycle: i64, b_count: ::c_int, b_waiters: ::c_int, b_refcount: ::c_int, b_destroying: ::c_int, } pub struct kinfo_vmentry { pub kve_structsize: ::c_int, pub kve_type: ::c_int, pub kve_start: u64, pub kve_end: u64, pub kve_offset: u64, pub kve_vn_fileid: u64, #[cfg(not(freebsd11))] pub kve_vn_fsid_freebsd11: u32, #[cfg(freebsd11)] pub kve_vn_fsid: u32, pub kve_flags: ::c_int, pub kve_resident: ::c_int, pub kve_private_resident: ::c_int, pub kve_protection: ::c_int, pub kve_ref_count: ::c_int, pub kve_shadow_count: ::c_int, pub kve_vn_type: ::c_int, pub kve_vn_size: u64, #[cfg(not(freebsd11))] pub kve_vn_rdev_freebsd11: u32, #[cfg(freebsd11)] pub kve_vn_rdev: u32, pub kve_vn_mode: u16, pub kve_status: u16, #[cfg(not(freebsd11))] pub kve_vn_fsid: u64, #[cfg(not(freebsd11))] pub kve_vn_rdev: u64, #[cfg(not(freebsd11))] _kve_is_spare: [::c_int; 8], #[cfg(freebsd11)] _kve_is_spare: [::c_int; 12], pub kve_path: [[::c_char; 32]; 32], } pub struct __c_anonymous_filestat { pub stqe_next: *mut filestat, } pub struct filestat { pub fs_type: ::c_int, pub fs_flags: ::c_int, pub fs_fflags: ::c_int, pub fs_uflags: ::c_int, pub fs_fd: ::c_int, pub fs_ref_count: ::c_int, pub fs_offset: ::off_t, pub fs_typedep: *mut ::c_void, pub fs_path: *mut ::c_char, pub next: __c_anonymous_filestat, pub fs_cap_rights: cap_rights_t, } pub struct filestat_list { pub stqh_first: *mut filestat, pub stqh_last: *mut *mut filestat, } pub struct procstat { pub tpe: ::c_int, pub kd: ::uintptr_t, pub vmentries: *mut ::c_void, pub files: *mut ::c_void, pub argv: *mut ::c_void, pub envv: *mut ::c_void, pub core: ::uintptr_t, } pub struct itimerspec { pub it_interval: ::timespec, pub it_value: ::timespec, } pub struct __c_anonymous__timer { _priv: [::c_int; 3], } /// Used to hold a copy of the command line, if it had a sane length. pub struct pargs { /// Reference count. pub ar_ref: u_int, /// Length. pub ar_length: u_int, /// Arguments. pub ar_args: [::c_uchar; 1], } pub struct priority { /// Scheduling class. pub pri_class: u_char, /// Normal priority level. pub pri_level: u_char, /// Priority before propagation. pub pri_native: u_char, /// User priority based on p_cpu and p_nice. pub pri_user: u_char, } pub struct kvm_swap { pub ksw_devname: [::c_char; 32], pub ksw_used: u_int, pub ksw_total: u_int, pub ksw_flags: ::c_int, pub ksw_reserved1: u_int, pub ksw_reserved2: u_int, } pub struct nlist { /// symbol name (in memory) pub n_name: *const ::c_char, /// type defines pub n_type: ::c_uchar, /// "type" and binding information pub n_other: ::c_char, /// used by stab entries pub n_desc: ::c_short, pub n_value: ::c_ulong, } pub struct kvm_nlist { pub n_name: *const ::c_char, pub n_type: ::c_uchar, pub n_value: ::kvaddr_t, } pub struct __c_anonymous_sem { _priv: ::uintptr_t, } pub struct semid_ds { pub sem_perm: ::ipc_perm, pub __sem_base: *mut __c_anonymous_sem, pub sem_nsems: ::c_ushort, pub sem_otime: ::time_t, pub sem_ctime: ::time_t, } pub struct vmtotal { pub t_vm: u64, pub t_avm: u64, pub t_rm: u64, pub t_arm: u64, pub t_vmshr: u64, pub t_avmshr: u64, pub t_rmshr: u64, pub t_armshr: u64, pub t_free: u64, pub t_rq: i16, pub t_dw: i16, pub t_pw: i16, pub t_sl: i16, pub t_sw: i16, pub t_pad: [u16; 3], } pub struct sockstat { pub inp_ppcb: u64, pub so_addr: u64, pub so_pcb: u64, pub unp_conn: u64, pub dom_family: ::c_int, pub proto: ::c_int, pub so_rcv_sb_state: ::c_int, pub so_snd_sb_state: ::c_int, /// Socket address. pub sa_local: ::sockaddr_storage, /// Peer address. pub sa_peer: ::sockaddr_storage, pub type_: ::c_int, pub dname: [::c_char; 32], #[cfg(any(freebsd12, freebsd13, freebsd14, freebsd15))] pub sendq: ::c_uint, #[cfg(any(freebsd12, freebsd13, freebsd14, freebsd15))] pub recvq: ::c_uint, } pub struct shmstat { pub size: u64, pub mode: u16, } pub struct spacectl_range { pub r_offset: ::off_t, pub r_len: ::off_t } pub struct rusage_ext { pub rux_runtime: u64, pub rux_uticks: u64, pub rux_sticks: u64, pub rux_iticks: u64, pub rux_uu: u64, pub rux_su: u64, pub rux_tu: u64, } pub struct if_clonereq { pub ifcr_total: ::c_int, pub ifcr_count: ::c_int, pub ifcr_buffer: *mut ::c_char, } pub struct if_msghdr { /// to skip over non-understood messages pub ifm_msglen: ::c_ushort, /// future binary compatibility pub ifm_version: ::c_uchar, /// message type pub ifm_type: ::c_uchar, /// like rtm_addrs pub ifm_addrs: ::c_int, /// value of if_flags pub ifm_flags: ::c_int, /// index for associated ifp pub ifm_index: ::c_ushort, pub _ifm_spare1: ::c_ushort, /// statistics and other data about if pub ifm_data: if_data, } pub struct if_msghdrl { /// to skip over non-understood messages pub ifm_msglen: ::c_ushort, /// future binary compatibility pub ifm_version: ::c_uchar, /// message type pub ifm_type: ::c_uchar, /// like rtm_addrs pub ifm_addrs: ::c_int, /// value of if_flags pub ifm_flags: ::c_int, /// index for associated ifp pub ifm_index: ::c_ushort, /// spare space to grow if_index, see if_var.h pub _ifm_spare1: ::c_ushort, /// length of if_msghdrl incl. if_data pub ifm_len: ::c_ushort, /// offset of if_data from beginning pub ifm_data_off: ::c_ushort, pub _ifm_spare2: ::c_int, /// statistics and other data about if pub ifm_data: if_data, } pub struct ifa_msghdr { /// to skip over non-understood messages pub ifam_msglen: ::c_ushort, /// future binary compatibility pub ifam_version: ::c_uchar, /// message type pub ifam_type: ::c_uchar, /// like rtm_addrs pub ifam_addrs: ::c_int, /// value of ifa_flags pub ifam_flags: ::c_int, /// index for associated ifp pub ifam_index: ::c_ushort, pub _ifam_spare1: ::c_ushort, /// value of ifa_ifp->if_metric pub ifam_metric: ::c_int, } pub struct ifa_msghdrl { /// to skip over non-understood messages pub ifam_msglen: ::c_ushort, /// future binary compatibility pub ifam_version: ::c_uchar, /// message type pub ifam_type: ::c_uchar, /// like rtm_addrs pub ifam_addrs: ::c_int, /// value of ifa_flags pub ifam_flags: ::c_int, /// index for associated ifp pub ifam_index: ::c_ushort, /// spare space to grow if_index, see if_var.h pub _ifam_spare1: ::c_ushort, /// length of ifa_msghdrl incl. if_data pub ifam_len: ::c_ushort, /// offset of if_data from beginning pub ifam_data_off: ::c_ushort, /// value of ifa_ifp->if_metric pub ifam_metric: ::c_int, /// statistics and other data about if or address pub ifam_data: if_data, } pub struct ifma_msghdr { /// to skip over non-understood messages pub ifmam_msglen: ::c_ushort, /// future binary compatibility pub ifmam_version: ::c_uchar, /// message type pub ifmam_type: ::c_uchar, /// like rtm_addrs pub ifmam_addrs: ::c_int, /// value of ifa_flags pub ifmam_flags: ::c_int, /// index for associated ifp pub ifmam_index: ::c_ushort, pub _ifmam_spare1: ::c_ushort, } pub struct if_announcemsghdr { /// to skip over non-understood messages pub ifan_msglen: ::c_ushort, /// future binary compatibility pub ifan_version: ::c_uchar, /// message type pub ifan_type: ::c_uchar, /// index for associated ifp pub ifan_index: ::c_ushort, /// if name, e.g. "en0" pub ifan_name: [::c_char; ::IFNAMSIZ as usize], /// what type of announcement pub ifan_what: ::c_ushort, } pub struct ifreq_buffer { pub length: ::size_t, pub buffer: *mut ::c_void, } pub struct ifaliasreq { /// if name, e.g. "en0" pub ifra_name: [::c_char; ::IFNAMSIZ as usize], pub ifra_addr: ::sockaddr, pub ifra_broadaddr: ::sockaddr, pub ifra_mask: ::sockaddr, pub ifra_vhid: ::c_int, } /// 9.x compat pub struct oifaliasreq { /// if name, e.g. "en0" pub ifra_name: [::c_char; ::IFNAMSIZ as usize], pub ifra_addr: ::sockaddr, pub ifra_broadaddr: ::sockaddr, pub ifra_mask: ::sockaddr, } pub struct ifmediareq { /// if name, e.g. "en0" pub ifm_name: [::c_char; ::IFNAMSIZ as usize], /// current media options pub ifm_current: ::c_int, /// don't care mask pub ifm_mask: ::c_int, /// media status pub ifm_status: ::c_int, /// active options pub ifm_active: ::c_int, /// # entries in ifm_ulist array pub ifm_count: ::c_int, /// media words pub ifm_ulist: *mut ::c_int, } pub struct ifdrv { /// if name, e.g. "en0" pub ifd_name: [::c_char; ::IFNAMSIZ as usize], pub ifd_cmd: ::c_ulong, pub ifd_len: ::size_t, pub ifd_data: *mut ::c_void, } pub struct ifi2creq { /// i2c address (0xA0, 0xA2) pub dev_addr: u8, /// read offset pub offset: u8, /// read length pub len: u8, pub spare0: u8, pub spare1: u32, /// read buffer pub data: [u8; 8], } pub struct ifrsshash { /// if name, e.g. "en0" pub ifrh_name: [::c_char; ::IFNAMSIZ as usize], /// RSS_FUNC_ pub ifrh_func: u8, pub ifrh_spare0: u8, pub ifrh_spare1: u16, /// RSS_TYPE_ pub ifrh_types: u32, } pub struct ifmibdata { /// name of interface pub ifmd_name: [::c_char; ::IFNAMSIZ as usize], /// number of promiscuous listeners pub ifmd_pcount: ::c_int, /// interface flags pub ifmd_flags: ::c_int, /// instantaneous length of send queue pub ifmd_snd_len: ::c_int, /// maximum length of send queue pub ifmd_snd_maxlen: ::c_int, /// number of drops in send queue pub ifmd_snd_drops: ::c_int, /// for future expansion pub ifmd_filler: [::c_int; 4], /// generic information and statistics pub ifmd_data: if_data, } pub struct ifmib_iso_8802_3 { pub dot3StatsAlignmentErrors: u32, pub dot3StatsFCSErrors: u32, pub dot3StatsSingleCollisionFrames: u32, pub dot3StatsMultipleCollisionFrames: u32, pub dot3StatsSQETestErrors: u32, pub dot3StatsDeferredTransmissions: u32, pub dot3StatsLateCollisions: u32, pub dot3StatsExcessiveCollisions: u32, pub dot3StatsInternalMacTransmitErrors: u32, pub dot3StatsCarrierSenseErrors: u32, pub dot3StatsFrameTooLongs: u32, pub dot3StatsInternalMacReceiveErrors: u32, pub dot3StatsEtherChipSet: u32, pub dot3StatsMissedFrames: u32, pub dot3StatsCollFrequencies: [u32; 16], pub dot3Compliance: u32, } pub struct __c_anonymous_ph { pub ph1: u64, pub ph2: u64, } pub struct fid { pub fid_len: ::c_ushort, pub fid_data0: ::c_ushort, pub fid_data: [::c_char; ::MAXFIDSZ as usize], } pub struct fhandle { pub fh_fsid: ::fsid_t, pub fh_fid: fid, } pub struct bintime { pub sec: ::time_t, pub frac: u64, } pub struct clockinfo { /// clock frequency pub hz: ::c_int, /// micro-seconds per hz tick pub tick: ::c_int, pub spare: ::c_int, /// statistics clock frequency pub stathz: ::c_int, /// profiling clock frequency pub profhz: ::c_int, } pub struct __c_anonymous_stailq_entry_devstat { pub stqe_next: *mut devstat, } pub struct devstat { /// Update sequence pub sequence0: ::u_int, /// Allocated entry pub allocated: ::c_int, /// started ops pub start_count: ::u_int, /// completed ops pub end_count: ::u_int, /// busy time unaccounted for since this time pub busy_from: bintime, pub dev_links: __c_anonymous_stailq_entry_devstat, /// Devstat device number. pub device_number: u32, pub device_name: [::c_char; DEVSTAT_NAME_LEN as usize], pub unit_number: ::c_int, pub bytes: [u64; DEVSTAT_N_TRANS_FLAGS as usize], pub operations: [u64; DEVSTAT_N_TRANS_FLAGS as usize], pub duration: [bintime; DEVSTAT_N_TRANS_FLAGS as usize], pub busy_time: bintime, /// Time the device was created. pub creation_time: bintime, /// Block size, bytes pub block_size: u32, /// The number of simple, ordered, and head of queue tags sent. pub tag_types: [u64; 3], /// Which statistics are supported by a given device. pub flags: devstat_support_flags, /// Device type pub device_type: devstat_type_flags, /// Controls list pos. pub priority: devstat_priority, /// Identification for GEOM nodes pub id: *const ::c_void, /// Update sequence pub sequence1: ::u_int, } pub struct devstat_match { pub match_fields: devstat_match_flags, pub device_type: devstat_type_flags, pub num_match_categories: ::c_int, } pub struct devstat_match_table { pub match_str: *const ::c_char, pub type_: devstat_type_flags, pub match_field: devstat_match_flags, } pub struct device_selection { pub device_number: u32, pub device_name: [::c_char; DEVSTAT_NAME_LEN as usize], pub unit_number: ::c_int, pub selected: ::c_int, pub bytes: u64, pub position: ::c_int, } pub struct devinfo { pub devices: *mut devstat, pub mem_ptr: *mut u8, pub generation: ::c_long, pub numdevs: ::c_int, } pub struct sockcred2 { pub sc_version: ::c_int, pub sc_pid: ::pid_t, pub sc_uid: ::uid_t, pub sc_euid: ::uid_t, pub sc_gid: ::gid_t, pub sc_egid: ::gid_t, pub sc_ngroups: ::c_int, pub sc_groups: [::gid_t; 1], } pub struct ifconf { pub ifc_len: ::c_int, #[cfg(libc_union)] pub ifc_ifcu: __c_anonymous_ifc_ifcu, #[cfg(not(libc_union))] pub ifc_ifcu: *mut ifreq, } pub struct au_mask_t { pub am_success: ::c_uint, pub am_failure: ::c_uint, } pub struct au_tid_t { pub port: u32, pub machine: u32, } pub struct auditinfo_t { pub ai_auid: ::au_id_t, pub ai_mask: ::au_mask_t, pub ai_termid: au_tid_t, pub ai_asid: ::au_asid_t, } pub struct tcp_fastopen { pub enable: ::c_int, pub psk: [u8; ::TCP_FASTOPEN_PSK_LEN as usize], } pub struct tcp_function_set { pub function_set_name: [::c_char; ::TCP_FUNCTION_NAME_LEN_MAX as usize], pub pcbcnt: u32, } // Note: this structure will change in a backwards-incompatible way in // FreeBSD 15. pub struct tcp_info { pub tcpi_state: u8, pub __tcpi_ca_state: u8, pub __tcpi_retransmits: u8, pub __tcpi_probes: u8, pub __tcpi_backoff: u8, pub tcpi_options: u8, pub tcp_snd_wscale: u8, pub tcp_rcv_wscale: u8, pub tcpi_rto: u32, pub __tcpi_ato: u32, pub tcpi_snd_mss: u32, pub tcpi_rcv_mss: u32, pub __tcpi_unacked: u32, pub __tcpi_sacked: u32, pub __tcpi_lost: u32, pub __tcpi_retrans: u32, pub __tcpi_fackets: u32, pub __tcpi_last_data_sent: u32, pub __tcpi_last_ack_sent: u32, pub tcpi_last_data_recv: u32, pub __tcpi_last_ack_recv: u32, pub __tcpi_pmtu: u32, pub __tcpi_rcv_ssthresh: u32, pub tcpi_rtt: u32, pub tcpi_rttvar: u32, pub tcpi_snd_ssthresh: u32, pub tcpi_snd_cwnd: u32, pub __tcpi_advmss: u32, pub __tcpi_reordering: u32, pub __tcpi_rcv_rtt: u32, pub tcpi_rcv_space: u32, pub tcpi_snd_wnd: u32, pub tcpi_snd_bwnd: u32, pub tcpi_snd_nxt: u32, pub tcpi_rcv_nxt: u32, pub tcpi_toe_tid: u32, pub tcpi_snd_rexmitpack: u32, pub tcpi_rcv_ooopack: u32, pub tcpi_snd_zerowin: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_delivered_ce: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_received_ce: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_delivered_e1_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_delivered_e0_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_delivered_ce_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_received_e1_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_received_e0_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub __tcpi_received_ce_bytes: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_total_tlp: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_total_tlp_bytes: u64, #[cfg(any(freebsd15, freebsd14))] pub tcpi_snd_una: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_snd_max: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_rcv_numsacks: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_rcv_adv: u32, #[cfg(any(freebsd15, freebsd14))] pub tcpi_dupacks: u32, #[cfg(freebsd14)] pub __tcpi_pad: [u32; 10], #[cfg(freebsd15)] pub __tcpi_pad: [u32; 14], #[cfg(not(any(freebsd15, freebsd14)))] pub __tcpi_pad: [u32; 26], } pub struct _umtx_time { pub _timeout: ::timespec, pub _flags: u32, pub _clockid: u32, } pub struct shm_largepage_conf { pub psind: ::c_int, pub alloc_policy: ::c_int, __pad: [::c_int; 10], } pub struct memory_type { __priva: [::uintptr_t; 32], __privb: [::uintptr_t; 26], } pub struct memory_type_list { __priv: [::uintptr_t; 2], } pub struct pidfh { __priva: [[::uintptr_t; 32]; 8], __privb: [::uintptr_t; 2], } pub struct sctp_event { pub se_assoc_id: ::sctp_assoc_t, pub se_type: u16, pub se_on: u8, } pub struct sctp_event_subscribe { pub sctp_data_io_event: u8, pub sctp_association_event: u8, pub sctp_address_event: u8, pub sctp_send_failure_event: u8, pub sctp_peer_error_event: u8, pub sctp_shutdown_event: u8, pub sctp_partial_delivery_event: u8, pub sctp_adaptation_layer_event: u8, pub sctp_authentication_event: u8, pub sctp_sender_dry_event: u8, pub sctp_stream_reset_event: u8, } pub struct sctp_initmsg { pub sinit_num_ostreams: u16, pub sinit_max_instreams: u16, pub sinit_max_attempts: u16, pub sinit_max_init_timeo: u16, } pub struct sctp_sndrcvinfo { pub sinfo_stream: u16, pub sinfo_ssn: u16, pub sinfo_flags: u16, pub sinfo_ppid: u32, pub sinfo_context: u32, pub sinfo_timetolive: u32, pub sinfo_tsn: u32, pub sinfo_cumtsn: u32, pub sinfo_assoc_id: ::sctp_assoc_t, pub sinfo_keynumber: u16, pub sinfo_keynumber_valid: u16, pub __reserve_pad: [[u8; 23]; 4], } pub struct sctp_extrcvinfo { pub sinfo_stream: u16, pub sinfo_ssn: u16, pub sinfo_flags: u16, pub sinfo_ppid: u32, pub sinfo_context: u32, pub sinfo_timetolive: u32, pub sinfo_tsn: u32, pub sinfo_cumtsn: u32, pub sinfo_assoc_id: ::sctp_assoc_t, pub serinfo_next_flags: u16, pub serinfo_next_stream: u16, pub serinfo_next_aid: u32, pub serinfo_next_length: u32, pub serinfo_next_ppid: u32, pub sinfo_keynumber: u16, pub sinfo_keynumber_valid: u16, pub __reserve_pad: [[u8; 19]; 4], } pub struct sctp_sndinfo { pub snd_sid: u16, pub snd_flags: u16, pub snd_ppid: u32, pub snd_context: u32, pub snd_assoc_id: ::sctp_assoc_t, } pub struct sctp_prinfo { pub pr_policy: u16, pub pr_value: u32, } pub struct sctp_default_prinfo { pub pr_policy: u16, pub pr_value: u32, pub pr_assoc_id: ::sctp_assoc_t, } pub struct sctp_authinfo { pub auth_keynumber: u16, } pub struct sctp_rcvinfo { pub rcv_sid: u16, pub rcv_ssn: u16, pub rcv_flags: u16, pub rcv_ppid: u32, pub rcv_tsn: u32, pub rcv_cumtsn: u32, pub rcv_context: u32, pub rcv_assoc_id: ::sctp_assoc_t, } pub struct sctp_nxtinfo { pub nxt_sid: u16, pub nxt_flags: u16, pub nxt_ppid: u32, pub nxt_length: u32, pub nxt_assoc_id: ::sctp_assoc_t, } pub struct sctp_recvv_rn { pub recvv_rcvinfo: sctp_rcvinfo, pub recvv_nxtinfo: sctp_nxtinfo, } pub struct sctp_sendv_spa { pub sendv_flags: u32, pub sendv_sndinfo: sctp_sndinfo, pub sendv_prinfo: sctp_prinfo, pub sendv_authinfo: sctp_authinfo, } pub struct sctp_snd_all_completes { pub sall_stream: u16, pub sall_flags: u16, pub sall_ppid: u32, pub sall_context: u32, pub sall_num_sent: u32, pub sall_num_failed: u32, } pub struct sctp_pcbinfo { pub ep_count: u32, pub asoc_count: u32, pub laddr_count: u32, pub raddr_count: u32, pub chk_count: u32, pub readq_count: u32, pub free_chunks: u32, pub stream_oque: u32, } pub struct sctp_sockstat { pub ss_assoc_id: ::sctp_assoc_t, pub ss_total_sndbuf: u32, pub ss_total_recv_buf: u32, } pub struct sctp_assoc_change { pub sac_type: u16, pub sac_flags: u16, pub sac_length: u32, pub sac_state: u16, pub sac_error: u16, pub sac_outbound_streams: u16, pub sac_inbound_streams: u16, pub sac_assoc_id: ::sctp_assoc_t, pub sac_info: [u8; 0], } pub struct sctp_paddr_change { pub spc_type: u16, pub spc_flags: u16, pub spc_length: u32, pub spc_aaddr: ::sockaddr_storage, pub spc_state: u32, pub spc_error: u32, pub spc_assoc_id: ::sctp_assoc_t, } pub struct sctp_remote_error { pub sre_type: u16, pub sre_flags: u16, pub sre_length: u32, pub sre_error: u16, pub sre_assoc_id: ::sctp_assoc_t, pub sre_data: [u8; 0], } pub struct sctp_send_failed_event { pub ssfe_type: u16, pub ssfe_flags: u16, pub ssfe_length: u32, pub ssfe_error: u32, pub ssfe_info: sctp_sndinfo, pub ssfe_assoc_id: ::sctp_assoc_t, pub ssfe_data: [u8; 0], } pub struct sctp_shutdown_event { pub sse_type: u16, pub sse_flags: u16, pub sse_length: u32, pub sse_assoc_id: ::sctp_assoc_t, } pub struct sctp_adaptation_event { pub sai_type: u16, pub sai_flags: u16, pub sai_length: u32, pub sai_adaptation_ind: u32, pub sai_assoc_id: ::sctp_assoc_t, } pub struct sctp_setadaptation { pub ssb_adaptation_ind: u32, } pub struct sctp_pdapi_event { pub pdapi_type: u16, pub pdapi_flags: u16, pub pdapi_length: u32, pub pdapi_indication: u32, pub pdapi_stream: u16, pub pdapi_seq: u16, pub pdapi_assoc_id: ::sctp_assoc_t, } pub struct sctp_sender_dry_event { pub sender_dry_type: u16, pub sender_dry_flags: u16, pub sender_dry_length: u32, pub sender_dry_assoc_id: ::sctp_assoc_t, } pub struct sctp_stream_reset_event { pub strreset_type: u16, pub strreset_flags: u16, pub strreset_length: u32, pub strreset_assoc_id: ::sctp_assoc_t, pub strreset_stream_list: [u16; 0], } pub struct sctp_stream_change_event { pub strchange_type: u16, pub strchange_flags: u16, pub strchange_length: u32, pub strchange_assoc_id: ::sctp_assoc_t, pub strchange_instrms: u16, pub strchange_outstrms: u16, } } s_no_extra_traits! { pub struct utmpx { pub ut_type: ::c_short, pub ut_tv: ::timeval, pub ut_id: [::c_char; 8], pub ut_pid: ::pid_t, pub ut_user: [::c_char; 32], pub ut_line: [::c_char; 16], pub ut_host: [::c_char; 128], pub __ut_spare: [::c_char; 64], } #[cfg(libc_union)] pub union __c_anonymous_cr_pid { __cr_unused: *mut ::c_void, pub cr_pid: ::pid_t, } pub struct xucred { pub cr_version: ::c_uint, pub cr_uid: ::uid_t, pub cr_ngroups: ::c_short, pub cr_groups: [::gid_t; 16], #[cfg(libc_union)] pub cr_pid__c_anonymous_union: __c_anonymous_cr_pid, #[cfg(not(libc_union))] __cr_unused1: *mut ::c_void, } pub struct sockaddr_dl { pub sdl_len: ::c_uchar, pub sdl_family: ::c_uchar, pub sdl_index: ::c_ushort, pub sdl_type: ::c_uchar, pub sdl_nlen: ::c_uchar, pub sdl_alen: ::c_uchar, pub sdl_slen: ::c_uchar, pub sdl_data: [::c_char; 46], } pub struct mq_attr { pub mq_flags: ::c_long, pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_curmsgs: ::c_long, __reserved: [::c_long; 4] } pub struct sigevent { pub sigev_notify: ::c_int, pub sigev_signo: ::c_int, pub sigev_value: ::sigval, //The rest of the structure is actually a union. We expose only //sigev_notify_thread_id because it's the most useful union member. pub sigev_notify_thread_id: ::lwpid_t, #[cfg(target_pointer_width = "64")] __unused1: ::c_int, __unused2: [::c_long; 7] } pub struct ptsstat { #[cfg(any(freebsd12, freebsd13, freebsd14, freebsd15))] pub dev: u64, #[cfg(not(any(freebsd12, freebsd13, freebsd14, freebsd15)))] pub dev: u32, pub devname: [::c_char; SPECNAMELEN as usize + 1], } #[cfg(libc_union)] pub union __c_anonymous_elf32_auxv_union { pub a_val: ::c_int, } pub struct Elf32_Auxinfo { pub a_type: ::c_int, #[cfg(libc_union)] pub a_un: __c_anonymous_elf32_auxv_union, } #[cfg(libc_union)] pub union __c_anonymous_ifi_epoch { pub tt: ::time_t, pub ph: u64, } #[cfg(libc_union)] pub union __c_anonymous_ifi_lastchange { pub tv: ::timeval, pub ph: __c_anonymous_ph, } pub struct if_data { /// ethernet, tokenring, etc pub ifi_type: u8, /// e.g., AUI, Thinnet, 10base-T, etc pub ifi_physical: u8, /// media address length pub ifi_addrlen: u8, /// media header length pub ifi_hdrlen: u8, /// current link state pub ifi_link_state: u8, /// carp vhid pub ifi_vhid: u8, /// length of this data struct pub ifi_datalen: u16, /// maximum transmission unit pub ifi_mtu: u32, /// routing metric (external only) pub ifi_metric: u32, /// linespeed pub ifi_baudrate: u64, /// packets received on interface pub ifi_ipackets: u64, /// input errors on interface pub ifi_ierrors: u64, /// packets sent on interface pub ifi_opackets: u64, /// output errors on interface pub ifi_oerrors: u64, /// collisions on csma interfaces pub ifi_collisions: u64, /// total number of octets received pub ifi_ibytes: u64, /// total number of octets sent pub ifi_obytes: u64, /// packets received via multicast pub ifi_imcasts: u64, /// packets sent via multicast pub ifi_omcasts: u64, /// dropped on input pub ifi_iqdrops: u64, /// dropped on output pub ifi_oqdrops: u64, /// destined for unsupported protocol pub ifi_noproto: u64, /// HW offload capabilities, see IFCAP pub ifi_hwassist: u64, /// uptime at attach or stat reset #[cfg(libc_union)] pub __ifi_epoch: __c_anonymous_ifi_epoch, /// uptime at attach or stat reset #[cfg(not(libc_union))] pub __ifi_epoch: u64, /// time of last administrative change #[cfg(libc_union)] pub __ifi_lastchange: __c_anonymous_ifi_lastchange, /// time of last administrative change #[cfg(not(libc_union))] pub __ifi_lastchange: ::timeval, } #[cfg(libc_union)] pub union __c_anonymous_ifr_ifru { pub ifru_addr: ::sockaddr, pub ifru_dstaddr: ::sockaddr, pub ifru_broadaddr: ::sockaddr, pub ifru_buffer: ifreq_buffer, pub ifru_flags: [::c_short; 2], pub ifru_index: ::c_short, pub ifru_jid: ::c_int, pub ifru_metric: ::c_int, pub ifru_mtu: ::c_int, pub ifru_phys: ::c_int, pub ifru_media: ::c_int, pub ifru_data: ::caddr_t, pub ifru_cap: [::c_int; 2], pub ifru_fib: ::c_uint, pub ifru_vlan_pcp: ::c_uchar, } pub struct ifreq { /// if name, e.g. "en0" pub ifr_name: [::c_char; ::IFNAMSIZ], #[cfg(libc_union)] pub ifr_ifru: __c_anonymous_ifr_ifru, #[cfg(not(libc_union))] pub ifr_ifru: ::sockaddr, } #[cfg(libc_union)] pub union __c_anonymous_ifc_ifcu { pub ifcu_buf: ::caddr_t, pub ifcu_req: *mut ifreq, } pub struct ifstat { /// if name, e.g. "en0" pub ifs_name: [::c_char; ::IFNAMSIZ as usize], pub ascii: [::c_char; ::IFSTATMAX as usize + 1], } pub struct ifrsskey { /// if name, e.g. "en0" pub ifrk_name: [::c_char; ::IFNAMSIZ as usize], /// RSS_FUNC_ pub ifrk_func: u8, pub ifrk_spare0: u8, pub ifrk_keylen: u16, pub ifrk_key: [u8; ::RSS_KEYLEN as usize], } pub struct ifdownreason { pub ifdr_name: [::c_char; ::IFNAMSIZ as usize], pub ifdr_reason: u32, pub ifdr_vendor: u32, pub ifdr_msg: [::c_char; ::IFDR_MSG_SIZE as usize], } #[repr(packed)] pub struct sctphdr { pub src_port: u16, pub dest_port: u16, pub v_tag: u32, pub checksum: u32, } #[repr(packed)] pub struct sctp_chunkhdr { pub chunk_type: u8, pub chunk_flags: u8, pub chunk_length: u16, } #[repr(packed)] pub struct sctp_paramhdr { pub param_type: u16, pub param_length: u16, } #[repr(packed)] pub struct sctp_gen_error_cause { pub code: u16, pub length: u16, pub info: [u8; 0], } #[repr(packed)] pub struct sctp_error_cause { pub code: u16, pub length: u16, } #[repr(packed)] pub struct sctp_error_invalid_stream { pub cause: sctp_error_cause, pub stream_id: u16, __reserved: u16, } #[repr(packed)] pub struct sctp_error_missing_param { pub cause: sctp_error_cause, pub num_missing_params: u32, pub tpe: [u8; 0], } #[repr(packed)] pub struct sctp_error_stale_cookie { pub cause: sctp_error_cause, pub stale_time: u32, } #[repr(packed)] pub struct sctp_error_out_of_resource { pub cause: sctp_error_cause, } #[repr(packed)] pub struct sctp_error_unresolv_addr { pub cause: sctp_error_cause, } #[repr(packed)] pub struct sctp_error_unrecognized_chunk { pub cause: sctp_error_cause, pub ch: sctp_chunkhdr, } #[repr(packed)] pub struct sctp_error_no_user_data { pub cause: sctp_error_cause, pub tsn: u32, } #[repr(packed)] pub struct sctp_error_auth_invalid_hmac { pub cause: sctp_error_cause, pub hmac_id: u16, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for utmpx { fn eq(&self, other: &utmpx) -> bool { self.ut_type == other.ut_type && self.ut_tv == other.ut_tv && self.ut_id == other.ut_id && self.ut_pid == other.ut_pid && self.ut_user == other.ut_user && self.ut_line == other.ut_line && self .ut_host .iter() .zip(other.ut_host.iter()) .all(|(a,b)| a == b) && self .__ut_spare .iter() .zip(other.__ut_spare.iter()) .all(|(a,b)| a == b) } } impl Eq for utmpx {} impl ::fmt::Debug for utmpx { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("utmpx") .field("ut_type", &self.ut_type) .field("ut_tv", &self.ut_tv) .field("ut_id", &self.ut_id) .field("ut_pid", &self.ut_pid) .field("ut_user", &self.ut_user) .field("ut_line", &self.ut_line) // FIXME: .field("ut_host", &self.ut_host) // FIXME: .field("__ut_spare", &self.__ut_spare) .finish() } } impl ::hash::Hash for utmpx { fn hash(&self, state: &mut H) { self.ut_type.hash(state); self.ut_tv.hash(state); self.ut_id.hash(state); self.ut_pid.hash(state); self.ut_user.hash(state); self.ut_line.hash(state); self.ut_host.hash(state); self.__ut_spare.hash(state); } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_cr_pid { fn eq(&self, other: &__c_anonymous_cr_pid) -> bool { unsafe { self.cr_pid == other.cr_pid} } } #[cfg(libc_union)] impl Eq for __c_anonymous_cr_pid {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_cr_pid { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("cr_pid") .field("cr_pid", unsafe { &self.cr_pid }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_cr_pid { fn hash(&self, state: &mut H) { unsafe { self.cr_pid.hash(state) }; } } impl PartialEq for xucred { fn eq(&self, other: &xucred) -> bool { #[cfg(libc_union)] let equal_cr_pid = self.cr_pid__c_anonymous_union == other.cr_pid__c_anonymous_union; #[cfg(not(libc_union))] let equal_cr_pid = self.__cr_unused1 == other.__cr_unused1; self.cr_version == other.cr_version && self.cr_uid == other.cr_uid && self.cr_ngroups == other.cr_ngroups && self.cr_groups == other.cr_groups && equal_cr_pid } } impl Eq for xucred {} impl ::fmt::Debug for xucred { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let mut struct_formatter = f.debug_struct("xucred"); struct_formatter.field("cr_version", &self.cr_version); struct_formatter.field("cr_uid", &self.cr_uid); struct_formatter.field("cr_ngroups", &self.cr_ngroups); struct_formatter.field("cr_groups", &self.cr_groups); #[cfg(libc_union)] struct_formatter.field( "cr_pid__c_anonymous_union", &self.cr_pid__c_anonymous_union ); struct_formatter.finish() } } impl ::hash::Hash for xucred { fn hash(&self, state: &mut H) { self.cr_version.hash(state); self.cr_uid.hash(state); self.cr_ngroups.hash(state); self.cr_groups.hash(state); #[cfg(libc_union)] self.cr_pid__c_anonymous_union.hash(state); #[cfg(not(libc_union))] self.__cr_unused1.hash(state); } } impl PartialEq for sockaddr_dl { fn eq(&self, other: &sockaddr_dl) -> bool { self.sdl_len == other.sdl_len && self.sdl_family == other.sdl_family && self.sdl_index == other.sdl_index && self.sdl_type == other.sdl_type && self.sdl_nlen == other.sdl_nlen && self.sdl_alen == other.sdl_alen && self.sdl_slen == other.sdl_slen && self .sdl_data .iter() .zip(other.sdl_data.iter()) .all(|(a,b)| a == b) } } impl Eq for sockaddr_dl {} impl ::fmt::Debug for sockaddr_dl { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_dl") .field("sdl_len", &self.sdl_len) .field("sdl_family", &self.sdl_family) .field("sdl_index", &self.sdl_index) .field("sdl_type", &self.sdl_type) .field("sdl_nlen", &self.sdl_nlen) .field("sdl_alen", &self.sdl_alen) .field("sdl_slen", &self.sdl_slen) // FIXME: .field("sdl_data", &self.sdl_data) .finish() } } impl ::hash::Hash for sockaddr_dl { fn hash(&self, state: &mut H) { self.sdl_len.hash(state); self.sdl_family.hash(state); self.sdl_index.hash(state); self.sdl_type.hash(state); self.sdl_nlen.hash(state); self.sdl_alen.hash(state); self.sdl_slen.hash(state); self.sdl_data.hash(state); } } impl PartialEq for mq_attr { fn eq(&self, other: &mq_attr) -> bool { self.mq_flags == other.mq_flags && self.mq_maxmsg == other.mq_maxmsg && self.mq_msgsize == other.mq_msgsize && self.mq_curmsgs == other.mq_curmsgs } } impl Eq for mq_attr {} impl ::fmt::Debug for mq_attr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mq_attr") .field("mq_flags", &self.mq_flags) .field("mq_maxmsg", &self.mq_maxmsg) .field("mq_msgsize", &self.mq_msgsize) .field("mq_curmsgs", &self.mq_curmsgs) .finish() } } impl ::hash::Hash for mq_attr { fn hash(&self, state: &mut H) { self.mq_flags.hash(state); self.mq_maxmsg.hash(state); self.mq_msgsize.hash(state); self.mq_curmsgs.hash(state); } } impl PartialEq for sigevent { fn eq(&self, other: &sigevent) -> bool { self.sigev_notify == other.sigev_notify && self.sigev_signo == other.sigev_signo && self.sigev_value == other.sigev_value && self.sigev_notify_thread_id == other.sigev_notify_thread_id } } impl Eq for sigevent {} impl ::fmt::Debug for sigevent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigevent") .field("sigev_notify", &self.sigev_notify) .field("sigev_signo", &self.sigev_signo) .field("sigev_value", &self.sigev_value) .field("sigev_notify_thread_id", &self.sigev_notify_thread_id) .finish() } } impl ::hash::Hash for sigevent { fn hash(&self, state: &mut H) { self.sigev_notify.hash(state); self.sigev_signo.hash(state); self.sigev_value.hash(state); self.sigev_notify_thread_id.hash(state); } } impl PartialEq for ptsstat { fn eq(&self, other: &ptsstat) -> bool { let self_devname: &[::c_char] = &self.devname; let other_devname: &[::c_char] = &other.devname; self.dev == other.dev && self_devname == other_devname } } impl Eq for ptsstat {} impl ::fmt::Debug for ptsstat { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let self_devname: &[::c_char] = &self.devname; f.debug_struct("ptsstat") .field("dev", &self.dev) .field("devname", &self_devname) .finish() } } impl ::hash::Hash for ptsstat { fn hash(&self, state: &mut H) { let self_devname: &[::c_char] = &self.devname; self.dev.hash(state); self_devname.hash(state); } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_elf32_auxv_union { fn eq(&self, other: &__c_anonymous_elf32_auxv_union) -> bool { unsafe { self.a_val == other.a_val} } } #[cfg(libc_union)] impl Eq for __c_anonymous_elf32_auxv_union {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_elf32_auxv_union { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("a_val") .field("a_val", unsafe { &self.a_val }) .finish() } } #[cfg(not(libc_union))] impl PartialEq for Elf32_Auxinfo { fn eq(&self, other: &Elf32_Auxinfo) -> bool { self.a_type == other.a_type } } #[cfg(libc_union)] impl PartialEq for Elf32_Auxinfo { fn eq(&self, other: &Elf32_Auxinfo) -> bool { self.a_type == other.a_type && self.a_un == other.a_un } } impl Eq for Elf32_Auxinfo {} #[cfg(not(libc_union))] impl ::fmt::Debug for Elf32_Auxinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("Elf32_Auxinfo") .field("a_type", &self.a_type) .finish() } } #[cfg(libc_union)] impl ::fmt::Debug for Elf32_Auxinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("Elf32_Auxinfo") .field("a_type", &self.a_type) .field("a_un", &self.a_un) .finish() } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifr_ifru { fn eq(&self, other: &__c_anonymous_ifr_ifru) -> bool { unsafe { self.ifru_addr == other.ifru_addr && self.ifru_dstaddr == other.ifru_dstaddr && self.ifru_broadaddr == other.ifru_broadaddr && self.ifru_buffer == other.ifru_buffer && self.ifru_flags == other.ifru_flags && self.ifru_index == other.ifru_index && self.ifru_jid == other.ifru_jid && self.ifru_metric == other.ifru_metric && self.ifru_mtu == other.ifru_mtu && self.ifru_phys == other.ifru_phys && self.ifru_media == other.ifru_media && self.ifru_data == other.ifru_data && self.ifru_cap == other.ifru_cap && self.ifru_fib == other.ifru_fib && self.ifru_vlan_pcp == other.ifru_vlan_pcp } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifr_ifru {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifr_ifru { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifr_ifru") .field("ifru_addr", unsafe { &self.ifru_addr }) .field("ifru_dstaddr", unsafe { &self.ifru_dstaddr }) .field("ifru_broadaddr", unsafe { &self.ifru_broadaddr }) .field("ifru_buffer", unsafe { &self.ifru_buffer }) .field("ifru_flags", unsafe { &self.ifru_flags }) .field("ifru_index", unsafe { &self.ifru_index }) .field("ifru_jid", unsafe { &self.ifru_jid }) .field("ifru_metric", unsafe { &self.ifru_metric }) .field("ifru_mtu", unsafe { &self.ifru_mtu }) .field("ifru_phys", unsafe { &self.ifru_phys }) .field("ifru_media", unsafe { &self.ifru_media }) .field("ifru_data", unsafe { &self.ifru_data }) .field("ifru_cap", unsafe { &self.ifru_cap }) .field("ifru_fib", unsafe { &self.ifru_fib }) .field("ifru_vlan_pcp", unsafe { &self.ifru_vlan_pcp }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifr_ifru { fn hash(&self, state: &mut H) { unsafe { self.ifru_addr.hash(state) }; unsafe { self.ifru_dstaddr.hash(state) }; unsafe { self.ifru_broadaddr.hash(state) }; unsafe { self.ifru_buffer.hash(state) }; unsafe { self.ifru_flags.hash(state) }; unsafe { self.ifru_index.hash(state) }; unsafe { self.ifru_jid.hash(state) }; unsafe { self.ifru_metric.hash(state) }; unsafe { self.ifru_mtu.hash(state) }; unsafe { self.ifru_phys.hash(state) }; unsafe { self.ifru_media.hash(state) }; unsafe { self.ifru_data.hash(state) }; unsafe { self.ifru_cap.hash(state) }; unsafe { self.ifru_fib.hash(state) }; unsafe { self.ifru_vlan_pcp.hash(state) }; } } impl PartialEq for ifreq { fn eq(&self, other: &ifreq) -> bool { self.ifr_name == other.ifr_name && self.ifr_ifru == other.ifr_ifru } } impl Eq for ifreq {} impl ::fmt::Debug for ifreq { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifreq") .field("ifr_name", &self.ifr_name) .field("ifr_ifru", &self.ifr_ifru) .finish() } } impl ::hash::Hash for ifreq { fn hash(&self, state: &mut H) { self.ifr_name.hash(state); self.ifr_ifru.hash(state); } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifc_ifcu {} #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifc_ifcu { fn eq(&self, other: &__c_anonymous_ifc_ifcu) -> bool { unsafe { self.ifcu_buf == other.ifcu_buf && self.ifcu_req == other.ifcu_req } } } #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifc_ifcu { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("ifc_ifcu") .field("ifcu_buf", unsafe { &self.ifcu_buf }) .field("ifcu_req", unsafe { &self.ifcu_req }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifc_ifcu { fn hash(&self, state: &mut H) { unsafe { self.ifcu_buf.hash(state) }; unsafe { self.ifcu_req.hash(state) }; } } impl PartialEq for ifstat { fn eq(&self, other: &ifstat) -> bool { let self_ascii: &[::c_char] = &self.ascii; let other_ascii: &[::c_char] = &other.ascii; self.ifs_name == other.ifs_name && self_ascii == other_ascii } } impl Eq for ifstat {} impl ::fmt::Debug for ifstat { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let ascii: &[::c_char] = &self.ascii; f.debug_struct("ifstat") .field("ifs_name", &self.ifs_name) .field("ascii", &ascii) .finish() } } impl ::hash::Hash for ifstat { fn hash(&self, state: &mut H) { self.ifs_name.hash(state); self.ascii.hash(state); } } impl PartialEq for ifrsskey { fn eq(&self, other: &ifrsskey) -> bool { let self_ifrk_key: &[u8] = &self.ifrk_key; let other_ifrk_key: &[u8] = &other.ifrk_key; self.ifrk_name == other.ifrk_name && self.ifrk_func == other.ifrk_func && self.ifrk_spare0 == other.ifrk_spare0 && self.ifrk_keylen == other.ifrk_keylen && self_ifrk_key == other_ifrk_key } } impl Eq for ifrsskey {} impl ::fmt::Debug for ifrsskey { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let ifrk_key: &[u8] = &self.ifrk_key; f.debug_struct("ifrsskey") .field("ifrk_name", &self.ifrk_name) .field("ifrk_func", &self.ifrk_func) .field("ifrk_spare0", &self.ifrk_spare0) .field("ifrk_keylen", &self.ifrk_keylen) .field("ifrk_key", &ifrk_key) .finish() } } impl ::hash::Hash for ifrsskey { fn hash(&self, state: &mut H) { self.ifrk_name.hash(state); self.ifrk_func.hash(state); self.ifrk_spare0.hash(state); self.ifrk_keylen.hash(state); self.ifrk_key.hash(state); } } impl PartialEq for ifdownreason { fn eq(&self, other: &ifdownreason) -> bool { let self_ifdr_msg: &[::c_char] = &self.ifdr_msg; let other_ifdr_msg: &[::c_char] = &other.ifdr_msg; self.ifdr_name == other.ifdr_name && self.ifdr_reason == other.ifdr_reason && self.ifdr_vendor == other.ifdr_vendor && self_ifdr_msg == other_ifdr_msg } } impl Eq for ifdownreason {} impl ::fmt::Debug for ifdownreason { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let ifdr_msg: &[::c_char] = &self.ifdr_msg; f.debug_struct("ifdownreason") .field("ifdr_name", &self.ifdr_name) .field("ifdr_reason", &self.ifdr_reason) .field("ifdr_vendor", &self.ifdr_vendor) .field("ifdr_msg", &ifdr_msg) .finish() } } impl ::hash::Hash for ifdownreason { fn hash(&self, state: &mut H) { self.ifdr_name.hash(state); self.ifdr_reason.hash(state); self.ifdr_vendor.hash(state); self.ifdr_msg.hash(state); } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifi_epoch { fn eq(&self, other: &__c_anonymous_ifi_epoch) -> bool { unsafe { self.tt == other.tt && self.ph == other.ph } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifi_epoch {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifi_epoch { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__c_anonymous_ifi_epoch") .field("tt", unsafe { &self.tt }) .field("ph", unsafe { &self.ph }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifi_epoch { fn hash(&self, state: &mut H) { unsafe { self.tt.hash(state); self.ph.hash(state); } } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_ifi_lastchange { fn eq(&self, other: &__c_anonymous_ifi_lastchange) -> bool { unsafe { self.tv == other.tv && self.ph == other.ph } } } #[cfg(libc_union)] impl Eq for __c_anonymous_ifi_lastchange {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_ifi_lastchange { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("__c_anonymous_ifi_lastchange") .field("tv", unsafe { &self.tv }) .field("ph", unsafe { &self.ph }) .finish() } } #[cfg(libc_union)] impl ::hash::Hash for __c_anonymous_ifi_lastchange { fn hash(&self, state: &mut H) { unsafe { self.tv.hash(state); self.ph.hash(state); } } } impl PartialEq for if_data { fn eq(&self, other: &if_data) -> bool { self.ifi_type == other.ifi_type && self.ifi_physical == other.ifi_physical && self.ifi_addrlen == other.ifi_addrlen && self.ifi_hdrlen == other.ifi_hdrlen && self.ifi_link_state == other.ifi_link_state && self.ifi_vhid == other.ifi_vhid && self.ifi_datalen == other.ifi_datalen && self.ifi_mtu == other.ifi_mtu && self.ifi_metric == other.ifi_metric && self.ifi_baudrate == other.ifi_baudrate && self.ifi_ipackets == other.ifi_ipackets && self.ifi_ierrors == other.ifi_ierrors && self.ifi_opackets == other.ifi_opackets && self.ifi_oerrors == other.ifi_oerrors && self.ifi_collisions == other.ifi_collisions && self.ifi_ibytes == other.ifi_ibytes && self.ifi_obytes == other.ifi_obytes && self.ifi_imcasts == other.ifi_imcasts && self.ifi_omcasts == other.ifi_omcasts && self.ifi_iqdrops == other.ifi_iqdrops && self.ifi_oqdrops == other.ifi_oqdrops && self.ifi_noproto == other.ifi_noproto && self.ifi_hwassist == other.ifi_hwassist && self.__ifi_epoch == other.__ifi_epoch && self.__ifi_lastchange == other.__ifi_lastchange } } impl Eq for if_data {} impl ::fmt::Debug for if_data { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("if_data") .field("ifi_type", &self.ifi_type) .field("ifi_physical", &self.ifi_physical) .field("ifi_addrlen", &self.ifi_addrlen) .field("ifi_hdrlen", &self.ifi_hdrlen) .field("ifi_link_state", &self.ifi_link_state) .field("ifi_vhid", &self.ifi_vhid) .field("ifi_datalen", &self.ifi_datalen) .field("ifi_mtu", &self.ifi_mtu) .field("ifi_metric", &self.ifi_metric) .field("ifi_baudrate", &self.ifi_baudrate) .field("ifi_ipackets", &self.ifi_ipackets) .field("ifi_ierrors", &self.ifi_ierrors) .field("ifi_opackets", &self.ifi_opackets) .field("ifi_oerrors", &self.ifi_oerrors) .field("ifi_collisions", &self.ifi_collisions) .field("ifi_ibytes", &self.ifi_ibytes) .field("ifi_obytes", &self.ifi_obytes) .field("ifi_imcasts", &self.ifi_imcasts) .field("ifi_omcasts", &self.ifi_omcasts) .field("ifi_iqdrops", &self.ifi_iqdrops) .field("ifi_oqdrops", &self.ifi_oqdrops) .field("ifi_noproto", &self.ifi_noproto) .field("ifi_hwassist", &self.ifi_hwassist) .field("__ifi_epoch", &self.__ifi_epoch) .field("__ifi_lastchange", &self.__ifi_lastchange) .finish() } } impl ::hash::Hash for if_data { fn hash(&self, state: &mut H) { self.ifi_type.hash(state); self.ifi_physical.hash(state); self.ifi_addrlen.hash(state); self.ifi_hdrlen.hash(state); self.ifi_link_state.hash(state); self.ifi_vhid.hash(state); self.ifi_datalen.hash(state); self.ifi_mtu.hash(state); self.ifi_metric.hash(state); self.ifi_baudrate.hash(state); self.ifi_ipackets.hash(state); self.ifi_ierrors.hash(state); self.ifi_opackets.hash(state); self.ifi_oerrors.hash(state); self.ifi_collisions.hash(state); self.ifi_ibytes.hash(state); self.ifi_obytes.hash(state); self.ifi_imcasts.hash(state); self.ifi_omcasts.hash(state); self.ifi_iqdrops.hash(state); self.ifi_oqdrops.hash(state); self.ifi_noproto.hash(state); self.ifi_hwassist.hash(state); self.__ifi_epoch.hash(state); self.__ifi_lastchange.hash(state); } } impl PartialEq for sctphdr { fn eq(&self, other: &sctphdr) -> bool { return {self.src_port} == {other.src_port} && {self.dest_port} == {other.dest_port} && {self.v_tag} == {other.v_tag} && {self.checksum} == {other.checksum} } } impl Eq for sctphdr {} impl ::fmt::Debug for sctphdr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctphdr") .field("src_port", &{self.src_port}) .field("dest_port", &{self.dest_port}) .field("v_tag", &{self.v_tag}) .field("checksum", &{self.checksum}) .finish() } } impl ::hash::Hash for sctphdr { fn hash(&self, state: &mut H) { {self.src_port}.hash(state); {self.dest_port}.hash(state); {self.v_tag}.hash(state); {self.checksum}.hash(state); } } impl PartialEq for sctp_chunkhdr { fn eq(&self, other: &sctp_chunkhdr) -> bool { return {self.chunk_type} == {other.chunk_type} && {self.chunk_flags} == {other.chunk_flags} && {self.chunk_length} == {other.chunk_length} } } impl Eq for sctp_chunkhdr {} impl ::fmt::Debug for sctp_chunkhdr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_chunkhdr") .field("chunk_type", &{self.chunk_type}) .field("chunk_flags", &{self.chunk_flags}) .field("chunk_length", &{self.chunk_length}) .finish() } } impl ::hash::Hash for sctp_chunkhdr { fn hash(&self, state: &mut H) { {self.chunk_type}.hash(state); {self.chunk_flags}.hash(state); {self.chunk_length}.hash(state); } } impl PartialEq for sctp_paramhdr { fn eq(&self, other: &sctp_paramhdr) -> bool { return {self.param_type} == {other.param_type} && {self.param_length} == {other.param_length} } } impl Eq for sctp_paramhdr {} impl ::fmt::Debug for sctp_paramhdr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_paramhdr") .field("param_type", &{self.param_type}) .field("param_length", &{self.param_length}) .finish() } } impl ::hash::Hash for sctp_paramhdr { fn hash(&self, state: &mut H) { {self.param_type}.hash(state); {self.param_length}.hash(state); } } impl PartialEq for sctp_gen_error_cause { fn eq(&self, other: &sctp_gen_error_cause) -> bool { return {self.code} == {other.code} && {self.length} == {other.length} && {self.info}.iter().zip({other.info}.iter()).all(|(a,b)| a == b) } } impl Eq for sctp_gen_error_cause {} impl ::fmt::Debug for sctp_gen_error_cause { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_gen_error_cause") .field("code", &{self.code}) .field("length", &{self.length}) // FIXME: .field("info", &{self.info}) .finish() } } impl ::hash::Hash for sctp_gen_error_cause { fn hash(&self, state: &mut H) { {self.code}.hash(state); {self.length}.hash(state); {self.info}.hash(state); } } impl PartialEq for sctp_error_cause { fn eq(&self, other: &sctp_error_cause) -> bool { return {self.code} == {other.code} && {self.length} == {other.length} } } impl Eq for sctp_error_cause {} impl ::fmt::Debug for sctp_error_cause { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_cause") .field("code", &{self.code}) .field("length", &{self.length}) .finish() } } impl ::hash::Hash for sctp_error_cause { fn hash(&self, state: &mut H) { {self.code}.hash(state); {self.length}.hash(state); } } impl PartialEq for sctp_error_invalid_stream { fn eq(&self, other: &sctp_error_invalid_stream) -> bool { return {self.cause} == {other.cause} && {self.stream_id} == {other.stream_id} } } impl Eq for sctp_error_invalid_stream {} impl ::fmt::Debug for sctp_error_invalid_stream { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_invalid_stream") .field("cause", &{self.cause}) .field("stream_id", &{self.stream_id}) .finish() } } impl ::hash::Hash for sctp_error_invalid_stream { fn hash(&self, state: &mut H) { {self.cause}.hash(state); {self.stream_id}.hash(state); } } impl PartialEq for sctp_error_missing_param { fn eq(&self, other: &sctp_error_missing_param) -> bool { return {self.cause} == {other.cause} && {self.num_missing_params} == {other.num_missing_params} && {self.tpe}.iter().zip({other.tpe}.iter()).all(|(a,b)| a == b) } } impl Eq for sctp_error_missing_param {} impl ::fmt::Debug for sctp_error_missing_param { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_missing_param") .field("cause", &{self.cause}) .field("num_missing_params", &{self.num_missing_params}) // FIXME: .field("tpe", &{self.tpe}) .finish() } } impl ::hash::Hash for sctp_error_missing_param { fn hash(&self, state: &mut H) { {self.cause}.hash(state); {self.num_missing_params}.hash(state); {self.tpe}.hash(state); } } impl PartialEq for sctp_error_stale_cookie { fn eq(&self, other: &sctp_error_stale_cookie) -> bool { return {self.cause} == {other.cause} && {self.stale_time} == {other.stale_time} } } impl Eq for sctp_error_stale_cookie {} impl ::fmt::Debug for sctp_error_stale_cookie { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_stale_cookie") .field("cause", &{self.cause}) .field("stale_time", &{self.stale_time}) .finish() } } impl ::hash::Hash for sctp_error_stale_cookie { fn hash(&self, state: &mut H) { {self.cause}.hash(state); {self.stale_time}.hash(state); } } impl PartialEq for sctp_error_out_of_resource { fn eq(&self, other: &sctp_error_out_of_resource) -> bool { return {self.cause} == {other.cause} } } impl Eq for sctp_error_out_of_resource {} impl ::fmt::Debug for sctp_error_out_of_resource { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_out_of_resource") .field("cause", &{self.cause}) .finish() } } impl ::hash::Hash for sctp_error_out_of_resource { fn hash(&self, state: &mut H) { {self.cause}.hash(state); } } impl PartialEq for sctp_error_unresolv_addr { fn eq(&self, other: &sctp_error_unresolv_addr) -> bool { return {self.cause} == {other.cause} } } impl Eq for sctp_error_unresolv_addr {} impl ::fmt::Debug for sctp_error_unresolv_addr { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_unresolv_addr") .field("cause", &{self.cause}) .finish() } } impl ::hash::Hash for sctp_error_unresolv_addr { fn hash(&self, state: &mut H) { {self.cause}.hash(state); } } impl PartialEq for sctp_error_unrecognized_chunk { fn eq(&self, other: &sctp_error_unrecognized_chunk) -> bool { return {self.cause} == {other.cause} && {self.ch} == {other.ch} } } impl Eq for sctp_error_unrecognized_chunk {} impl ::fmt::Debug for sctp_error_unrecognized_chunk { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_unrecognized_chunk") .field("cause", &{self.cause}) .field("ch", &{self.ch}) .finish() } } impl ::hash::Hash for sctp_error_unrecognized_chunk { fn hash(&self, state: &mut H) { {self.cause}.hash(state); {self.ch}.hash(state); } } impl PartialEq for sctp_error_no_user_data { fn eq(&self, other: &sctp_error_no_user_data) -> bool { return {self.cause} == {other.cause} && {self.tsn} == {other.tsn} } } impl Eq for sctp_error_no_user_data {} impl ::fmt::Debug for sctp_error_no_user_data { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_no_user_data") .field("cause", &{self.cause}) .field("tsn", &{self.tsn}) .finish() } } impl ::hash::Hash for sctp_error_no_user_data { fn hash(&self, state: &mut H) { {self.cause}.hash(state); {self.tsn}.hash(state); } } impl PartialEq for sctp_error_auth_invalid_hmac { fn eq(&self, other: &sctp_error_auth_invalid_hmac) -> bool { return {self.cause} == {other.cause} && {self.hmac_id} == {other.hmac_id} } } impl Eq for sctp_error_auth_invalid_hmac {} impl ::fmt::Debug for sctp_error_auth_invalid_hmac { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sctp_error_invalid_hmac") .field("cause", &{self.cause}) .field("hmac_id", &{self.hmac_id}) .finish() } } impl ::hash::Hash for sctp_error_auth_invalid_hmac { fn hash(&self, state: &mut H) { {self.cause}.hash(state); {self.hmac_id}.hash(state); } } } } #[cfg_attr(feature = "extra_traits", derive(Debug))] #[repr(u32)] pub enum dot3Vendors { dot3VendorAMD = 1, dot3VendorIntel = 2, dot3VendorNational = 4, dot3VendorFujitsu = 5, dot3VendorDigital = 6, dot3VendorWesternDigital = 7, } impl ::Copy for dot3Vendors {} impl ::Clone for dot3Vendors { fn clone(&self) -> dot3Vendors { *self } } // aio.h pub const LIO_VECTORED: ::c_int = 4; pub const LIO_WRITEV: ::c_int = 5; pub const LIO_READV: ::c_int = 6; // sys/devicestat.h pub const DEVSTAT_N_TRANS_FLAGS: ::c_int = 4; pub const DEVSTAT_NAME_LEN: ::c_int = 16; // sys/cpuset.h cfg_if! { if #[cfg(any(freebsd15, freebsd14))] { pub const CPU_SETSIZE: ::c_int = 1024; } else { pub const CPU_SETSIZE: ::c_int = 256; } } pub const SIGEV_THREAD_ID: ::c_int = 4; pub const EXTATTR_NAMESPACE_EMPTY: ::c_int = 0; pub const EXTATTR_NAMESPACE_USER: ::c_int = 1; pub const EXTATTR_NAMESPACE_SYSTEM: ::c_int = 2; pub const PTHREAD_STACK_MIN: ::size_t = MINSIGSTKSZ; pub const PTHREAD_MUTEX_ADAPTIVE_NP: ::c_int = 4; pub const PTHREAD_MUTEX_STALLED: ::c_int = 0; pub const PTHREAD_MUTEX_ROBUST: ::c_int = 1; pub const SIGSTKSZ: ::size_t = MINSIGSTKSZ + 32768; pub const SF_NODISKIO: ::c_int = 0x00000001; pub const SF_MNOWAIT: ::c_int = 0x00000002; pub const SF_SYNC: ::c_int = 0x00000004; pub const SF_USER_READAHEAD: ::c_int = 0x00000008; pub const SF_NOCACHE: ::c_int = 0x00000010; pub const O_CLOEXEC: ::c_int = 0x00100000; pub const O_DIRECTORY: ::c_int = 0x00020000; pub const O_DSYNC: ::c_int = 0x01000000; pub const O_EMPTY_PATH: ::c_int = 0x02000000; pub const O_EXEC: ::c_int = 0x00040000; pub const O_PATH: ::c_int = 0x00400000; pub const O_RESOLVE_BENEATH: ::c_int = 0x00800000; pub const O_SEARCH: ::c_int = O_EXEC; pub const O_TTY_INIT: ::c_int = 0x00080000; pub const O_VERIFY: ::c_int = 0x00200000; pub const F_GETLK: ::c_int = 11; pub const F_SETLK: ::c_int = 12; pub const F_SETLKW: ::c_int = 13; pub const ENOTCAPABLE: ::c_int = 93; pub const ECAPMODE: ::c_int = 94; pub const ENOTRECOVERABLE: ::c_int = 95; pub const EOWNERDEAD: ::c_int = 96; pub const EINTEGRITY: ::c_int = 97; pub const RLIMIT_NPTS: ::c_int = 11; pub const RLIMIT_SWAP: ::c_int = 12; pub const RLIMIT_KQUEUES: ::c_int = 13; pub const RLIMIT_UMTXP: ::c_int = 14; #[deprecated(since = "0.2.64", note = "Not stable across OS versions")] pub const RLIM_NLIMITS: ::rlim_t = 15; pub const RLIM_SAVED_MAX: ::rlim_t = ::RLIM_INFINITY; pub const RLIM_SAVED_CUR: ::rlim_t = ::RLIM_INFINITY; pub const CP_USER: ::c_int = 0; pub const CP_NICE: ::c_int = 1; pub const CP_SYS: ::c_int = 2; pub const CP_INTR: ::c_int = 3; pub const CP_IDLE: ::c_int = 4; pub const CPUSTATES: ::c_int = 5; pub const NI_NOFQDN: ::c_int = 0x00000001; pub const NI_NUMERICHOST: ::c_int = 0x00000002; pub const NI_NAMEREQD: ::c_int = 0x00000004; pub const NI_NUMERICSERV: ::c_int = 0x00000008; pub const NI_DGRAM: ::c_int = 0x00000010; pub const NI_NUMERICSCOPE: ::c_int = 0x00000020; pub const XU_NGROUPS: ::c_int = 16; pub const Q_GETQUOTA: ::c_int = 0x700; pub const Q_SETQUOTA: ::c_int = 0x800; pub const MAP_GUARD: ::c_int = 0x00002000; pub const MAP_EXCL: ::c_int = 0x00004000; pub const MAP_PREFAULT_READ: ::c_int = 0x00040000; pub const MAP_ALIGNMENT_SHIFT: ::c_int = 24; pub const MAP_ALIGNMENT_MASK: ::c_int = 0xff << MAP_ALIGNMENT_SHIFT; pub const MAP_ALIGNED_SUPER: ::c_int = 1 << MAP_ALIGNMENT_SHIFT; pub const POSIX_FADV_NORMAL: ::c_int = 0; pub const POSIX_FADV_RANDOM: ::c_int = 1; pub const POSIX_FADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_FADV_WILLNEED: ::c_int = 3; pub const POSIX_FADV_DONTNEED: ::c_int = 4; pub const POSIX_FADV_NOREUSE: ::c_int = 5; pub const POLLINIGNEOF: ::c_short = 0x2000; pub const EVFILT_READ: i16 = -1; pub const EVFILT_WRITE: i16 = -2; pub const EVFILT_AIO: i16 = -3; pub const EVFILT_VNODE: i16 = -4; pub const EVFILT_PROC: i16 = -5; pub const EVFILT_SIGNAL: i16 = -6; pub const EVFILT_TIMER: i16 = -7; pub const EVFILT_PROCDESC: i16 = -8; pub const EVFILT_FS: i16 = -9; pub const EVFILT_LIO: i16 = -10; pub const EVFILT_USER: i16 = -11; pub const EVFILT_SENDFILE: i16 = -12; pub const EVFILT_EMPTY: i16 = -13; pub const EV_ADD: u16 = 0x1; pub const EV_DELETE: u16 = 0x2; pub const EV_ENABLE: u16 = 0x4; pub const EV_DISABLE: u16 = 0x8; pub const EV_FORCEONESHOT: u16 = 0x100; pub const EV_KEEPUDATA: u16 = 0x200; pub const EV_ONESHOT: u16 = 0x10; pub const EV_CLEAR: u16 = 0x20; pub const EV_RECEIPT: u16 = 0x40; pub const EV_DISPATCH: u16 = 0x80; pub const EV_SYSFLAGS: u16 = 0xf000; pub const EV_DROP: u16 = 0x1000; pub const EV_FLAG1: u16 = 0x2000; pub const EV_FLAG2: u16 = 0x4000; pub const EV_EOF: u16 = 0x8000; pub const EV_ERROR: u16 = 0x4000; pub const NOTE_TRIGGER: u32 = 0x01000000; pub const NOTE_FFNOP: u32 = 0x00000000; pub const NOTE_FFAND: u32 = 0x40000000; pub const NOTE_FFOR: u32 = 0x80000000; pub const NOTE_FFCOPY: u32 = 0xc0000000; pub const NOTE_FFCTRLMASK: u32 = 0xc0000000; pub const NOTE_FFLAGSMASK: u32 = 0x00ffffff; pub const NOTE_LOWAT: u32 = 0x00000001; pub const NOTE_FILE_POLL: u32 = 0x00000002; pub const NOTE_DELETE: u32 = 0x00000001; pub const NOTE_WRITE: u32 = 0x00000002; pub const NOTE_EXTEND: u32 = 0x00000004; pub const NOTE_ATTRIB: u32 = 0x00000008; pub const NOTE_LINK: u32 = 0x00000010; pub const NOTE_RENAME: u32 = 0x00000020; pub const NOTE_REVOKE: u32 = 0x00000040; pub const NOTE_OPEN: u32 = 0x00000080; pub const NOTE_CLOSE: u32 = 0x00000100; pub const NOTE_CLOSE_WRITE: u32 = 0x00000200; pub const NOTE_READ: u32 = 0x00000400; pub const NOTE_EXIT: u32 = 0x80000000; pub const NOTE_FORK: u32 = 0x40000000; pub const NOTE_EXEC: u32 = 0x20000000; pub const NOTE_PDATAMASK: u32 = 0x000fffff; pub const NOTE_PCTRLMASK: u32 = 0xf0000000; pub const NOTE_TRACK: u32 = 0x00000001; pub const NOTE_TRACKERR: u32 = 0x00000002; pub const NOTE_CHILD: u32 = 0x00000004; pub const NOTE_SECONDS: u32 = 0x00000001; pub const NOTE_MSECONDS: u32 = 0x00000002; pub const NOTE_USECONDS: u32 = 0x00000004; pub const NOTE_NSECONDS: u32 = 0x00000008; pub const NOTE_ABSTIME: u32 = 0x00000010; pub const MADV_PROTECT: ::c_int = 10; #[doc(hidden)] #[deprecated( since = "0.2.72", note = "CTL_UNSPEC is deprecated. Use CTL_SYSCTL instead" )] pub const CTL_UNSPEC: ::c_int = 0; pub const CTL_SYSCTL: ::c_int = 0; pub const CTL_KERN: ::c_int = 1; pub const CTL_VM: ::c_int = 2; pub const CTL_VFS: ::c_int = 3; pub const CTL_NET: ::c_int = 4; pub const CTL_DEBUG: ::c_int = 5; pub const CTL_HW: ::c_int = 6; pub const CTL_MACHDEP: ::c_int = 7; pub const CTL_USER: ::c_int = 8; pub const CTL_P1003_1B: ::c_int = 9; // sys/sysctl.h pub const CTL_MAXNAME: ::c_int = 24; pub const CTLTYPE: ::c_int = 0xf; pub const CTLTYPE_NODE: ::c_int = 1; pub const CTLTYPE_INT: ::c_int = 2; pub const CTLTYPE_STRING: ::c_int = 3; pub const CTLTYPE_S64: ::c_int = 4; pub const CTLTYPE_OPAQUE: ::c_int = 5; pub const CTLTYPE_STRUCT: ::c_int = CTLTYPE_OPAQUE; pub const CTLTYPE_UINT: ::c_int = 6; pub const CTLTYPE_LONG: ::c_int = 7; pub const CTLTYPE_ULONG: ::c_int = 8; pub const CTLTYPE_U64: ::c_int = 9; pub const CTLTYPE_U8: ::c_int = 0xa; pub const CTLTYPE_U16: ::c_int = 0xb; pub const CTLTYPE_S8: ::c_int = 0xc; pub const CTLTYPE_S16: ::c_int = 0xd; pub const CTLTYPE_S32: ::c_int = 0xe; pub const CTLTYPE_U32: ::c_int = 0xf; pub const CTLFLAG_RD: ::c_int = 0x80000000; pub const CTLFLAG_WR: ::c_int = 0x40000000; pub const CTLFLAG_RW: ::c_int = CTLFLAG_RD | CTLFLAG_WR; pub const CTLFLAG_DORMANT: ::c_int = 0x20000000; pub const CTLFLAG_ANYBODY: ::c_int = 0x10000000; pub const CTLFLAG_SECURE: ::c_int = 0x08000000; pub const CTLFLAG_PRISON: ::c_int = 0x04000000; pub const CTLFLAG_DYN: ::c_int = 0x02000000; pub const CTLFLAG_SKIP: ::c_int = 0x01000000; pub const CTLMASK_SECURE: ::c_int = 0x00F00000; pub const CTLFLAG_TUN: ::c_int = 0x00080000; pub const CTLFLAG_RDTUN: ::c_int = CTLFLAG_RD | CTLFLAG_TUN; pub const CTLFLAG_RWTUN: ::c_int = CTLFLAG_RW | CTLFLAG_TUN; pub const CTLFLAG_MPSAFE: ::c_int = 0x00040000; pub const CTLFLAG_VNET: ::c_int = 0x00020000; pub const CTLFLAG_DYING: ::c_int = 0x00010000; pub const CTLFLAG_CAPRD: ::c_int = 0x00008000; pub const CTLFLAG_CAPWR: ::c_int = 0x00004000; pub const CTLFLAG_STATS: ::c_int = 0x00002000; pub const CTLFLAG_NOFETCH: ::c_int = 0x00001000; pub const CTLFLAG_CAPRW: ::c_int = CTLFLAG_CAPRD | CTLFLAG_CAPWR; pub const CTLFLAG_NEEDGIANT: ::c_int = 0x00000800; pub const CTLSHIFT_SECURE: ::c_int = 20; pub const CTLFLAG_SECURE1: ::c_int = CTLFLAG_SECURE | (0 << CTLSHIFT_SECURE); pub const CTLFLAG_SECURE2: ::c_int = CTLFLAG_SECURE | (1 << CTLSHIFT_SECURE); pub const CTLFLAG_SECURE3: ::c_int = CTLFLAG_SECURE | (2 << CTLSHIFT_SECURE); pub const OID_AUTO: ::c_int = -1; pub const CTL_SYSCTL_DEBUG: ::c_int = 0; pub const CTL_SYSCTL_NAME: ::c_int = 1; pub const CTL_SYSCTL_NEXT: ::c_int = 2; pub const CTL_SYSCTL_NAME2OID: ::c_int = 3; pub const CTL_SYSCTL_OIDFMT: ::c_int = 4; pub const CTL_SYSCTL_OIDDESCR: ::c_int = 5; pub const CTL_SYSCTL_OIDLABEL: ::c_int = 6; pub const CTL_SYSCTL_NEXTNOSKIP: ::c_int = 7; pub const KERN_OSTYPE: ::c_int = 1; pub const KERN_OSRELEASE: ::c_int = 2; pub const KERN_OSREV: ::c_int = 3; pub const KERN_VERSION: ::c_int = 4; pub const KERN_MAXVNODES: ::c_int = 5; pub const KERN_MAXPROC: ::c_int = 6; pub const KERN_MAXFILES: ::c_int = 7; pub const KERN_ARGMAX: ::c_int = 8; pub const KERN_SECURELVL: ::c_int = 9; pub const KERN_HOSTNAME: ::c_int = 10; pub const KERN_HOSTID: ::c_int = 11; pub const KERN_CLOCKRATE: ::c_int = 12; pub const KERN_VNODE: ::c_int = 13; pub const KERN_PROC: ::c_int = 14; pub const KERN_FILE: ::c_int = 15; pub const KERN_PROF: ::c_int = 16; pub const KERN_POSIX1: ::c_int = 17; pub const KERN_NGROUPS: ::c_int = 18; pub const KERN_JOB_CONTROL: ::c_int = 19; pub const KERN_SAVED_IDS: ::c_int = 20; pub const KERN_BOOTTIME: ::c_int = 21; pub const KERN_NISDOMAINNAME: ::c_int = 22; pub const KERN_UPDATEINTERVAL: ::c_int = 23; pub const KERN_OSRELDATE: ::c_int = 24; pub const KERN_NTP_PLL: ::c_int = 25; pub const KERN_BOOTFILE: ::c_int = 26; pub const KERN_MAXFILESPERPROC: ::c_int = 27; pub const KERN_MAXPROCPERUID: ::c_int = 28; pub const KERN_DUMPDEV: ::c_int = 29; pub const KERN_IPC: ::c_int = 30; pub const KERN_DUMMY: ::c_int = 31; pub const KERN_PS_STRINGS: ::c_int = 32; pub const KERN_USRSTACK: ::c_int = 33; pub const KERN_LOGSIGEXIT: ::c_int = 34; pub const KERN_IOV_MAX: ::c_int = 35; pub const KERN_HOSTUUID: ::c_int = 36; pub const KERN_ARND: ::c_int = 37; pub const KERN_MAXPHYS: ::c_int = 38; pub const KERN_PROC_ALL: ::c_int = 0; pub const KERN_PROC_PID: ::c_int = 1; pub const KERN_PROC_PGRP: ::c_int = 2; pub const KERN_PROC_SESSION: ::c_int = 3; pub const KERN_PROC_TTY: ::c_int = 4; pub const KERN_PROC_UID: ::c_int = 5; pub const KERN_PROC_RUID: ::c_int = 6; pub const KERN_PROC_ARGS: ::c_int = 7; pub const KERN_PROC_PROC: ::c_int = 8; pub const KERN_PROC_SV_NAME: ::c_int = 9; pub const KERN_PROC_RGID: ::c_int = 10; pub const KERN_PROC_GID: ::c_int = 11; pub const KERN_PROC_PATHNAME: ::c_int = 12; pub const KERN_PROC_OVMMAP: ::c_int = 13; pub const KERN_PROC_OFILEDESC: ::c_int = 14; pub const KERN_PROC_KSTACK: ::c_int = 15; pub const KERN_PROC_INC_THREAD: ::c_int = 0x10; pub const KERN_PROC_VMMAP: ::c_int = 32; pub const KERN_PROC_FILEDESC: ::c_int = 33; pub const KERN_PROC_GROUPS: ::c_int = 34; pub const KERN_PROC_ENV: ::c_int = 35; pub const KERN_PROC_AUXV: ::c_int = 36; pub const KERN_PROC_RLIMIT: ::c_int = 37; pub const KERN_PROC_PS_STRINGS: ::c_int = 38; pub const KERN_PROC_UMASK: ::c_int = 39; pub const KERN_PROC_OSREL: ::c_int = 40; pub const KERN_PROC_SIGTRAMP: ::c_int = 41; pub const KERN_PROC_CWD: ::c_int = 42; pub const KERN_PROC_NFDS: ::c_int = 43; pub const KERN_PROC_SIGFASTBLK: ::c_int = 44; pub const KIPC_MAXSOCKBUF: ::c_int = 1; pub const KIPC_SOCKBUF_WASTE: ::c_int = 2; pub const KIPC_SOMAXCONN: ::c_int = 3; pub const KIPC_MAX_LINKHDR: ::c_int = 4; pub const KIPC_MAX_PROTOHDR: ::c_int = 5; pub const KIPC_MAX_HDR: ::c_int = 6; pub const KIPC_MAX_DATALEN: ::c_int = 7; pub const HW_MACHINE: ::c_int = 1; pub const HW_MODEL: ::c_int = 2; pub const HW_NCPU: ::c_int = 3; pub const HW_BYTEORDER: ::c_int = 4; pub const HW_PHYSMEM: ::c_int = 5; pub const HW_USERMEM: ::c_int = 6; pub const HW_PAGESIZE: ::c_int = 7; pub const HW_DISKNAMES: ::c_int = 8; pub const HW_DISKSTATS: ::c_int = 9; pub const HW_FLOATINGPT: ::c_int = 10; pub const HW_MACHINE_ARCH: ::c_int = 11; pub const HW_REALMEM: ::c_int = 12; pub const USER_CS_PATH: ::c_int = 1; pub const USER_BC_BASE_MAX: ::c_int = 2; pub const USER_BC_DIM_MAX: ::c_int = 3; pub const USER_BC_SCALE_MAX: ::c_int = 4; pub const USER_BC_STRING_MAX: ::c_int = 5; pub const USER_COLL_WEIGHTS_MAX: ::c_int = 6; pub const USER_EXPR_NEST_MAX: ::c_int = 7; pub const USER_LINE_MAX: ::c_int = 8; pub const USER_RE_DUP_MAX: ::c_int = 9; pub const USER_POSIX2_VERSION: ::c_int = 10; pub const USER_POSIX2_C_BIND: ::c_int = 11; pub const USER_POSIX2_C_DEV: ::c_int = 12; pub const USER_POSIX2_CHAR_TERM: ::c_int = 13; pub const USER_POSIX2_FORT_DEV: ::c_int = 14; pub const USER_POSIX2_FORT_RUN: ::c_int = 15; pub const USER_POSIX2_LOCALEDEF: ::c_int = 16; pub const USER_POSIX2_SW_DEV: ::c_int = 17; pub const USER_POSIX2_UPE: ::c_int = 18; pub const USER_STREAM_MAX: ::c_int = 19; pub const USER_TZNAME_MAX: ::c_int = 20; pub const USER_LOCALBASE: ::c_int = 21; pub const CTL_P1003_1B_ASYNCHRONOUS_IO: ::c_int = 1; pub const CTL_P1003_1B_MAPPED_FILES: ::c_int = 2; pub const CTL_P1003_1B_MEMLOCK: ::c_int = 3; pub const CTL_P1003_1B_MEMLOCK_RANGE: ::c_int = 4; pub const CTL_P1003_1B_MEMORY_PROTECTION: ::c_int = 5; pub const CTL_P1003_1B_MESSAGE_PASSING: ::c_int = 6; pub const CTL_P1003_1B_PRIORITIZED_IO: ::c_int = 7; pub const CTL_P1003_1B_PRIORITY_SCHEDULING: ::c_int = 8; pub const CTL_P1003_1B_REALTIME_SIGNALS: ::c_int = 9; pub const CTL_P1003_1B_SEMAPHORES: ::c_int = 10; pub const CTL_P1003_1B_FSYNC: ::c_int = 11; pub const CTL_P1003_1B_SHARED_MEMORY_OBJECTS: ::c_int = 12; pub const CTL_P1003_1B_SYNCHRONIZED_IO: ::c_int = 13; pub const CTL_P1003_1B_TIMERS: ::c_int = 14; pub const CTL_P1003_1B_AIO_LISTIO_MAX: ::c_int = 15; pub const CTL_P1003_1B_AIO_MAX: ::c_int = 16; pub const CTL_P1003_1B_AIO_PRIO_DELTA_MAX: ::c_int = 17; pub const CTL_P1003_1B_DELAYTIMER_MAX: ::c_int = 18; pub const CTL_P1003_1B_MQ_OPEN_MAX: ::c_int = 19; pub const CTL_P1003_1B_PAGESIZE: ::c_int = 20; pub const CTL_P1003_1B_RTSIG_MAX: ::c_int = 21; pub const CTL_P1003_1B_SEM_NSEMS_MAX: ::c_int = 22; pub const CTL_P1003_1B_SEM_VALUE_MAX: ::c_int = 23; pub const CTL_P1003_1B_SIGQUEUE_MAX: ::c_int = 24; pub const CTL_P1003_1B_TIMER_MAX: ::c_int = 25; pub const TIOCGPTN: ::c_ulong = 0x4004740f; pub const TIOCPTMASTER: ::c_ulong = 0x2000741c; pub const TIOCSIG: ::c_ulong = 0x2004745f; pub const TIOCM_DCD: ::c_int = 0x40; pub const H4DISC: ::c_int = 0x7; pub const VM_TOTAL: ::c_int = 1; pub const BIOCSETFNR: ::c_ulong = 0x80104282; pub const FIODGNAME: ::c_ulong = 0x80106678; pub const FIONWRITE: ::c_ulong = 0x40046677; pub const FIONSPACE: ::c_ulong = 0x40046676; pub const FIOSEEKDATA: ::c_ulong = 0xc0086661; pub const FIOSEEKHOLE: ::c_ulong = 0xc0086662; pub const FIOSSHMLPGCNF: ::c_ulong = 0x80306664; pub const JAIL_API_VERSION: u32 = 2; pub const JAIL_CREATE: ::c_int = 0x01; pub const JAIL_UPDATE: ::c_int = 0x02; pub const JAIL_ATTACH: ::c_int = 0x04; pub const JAIL_DYING: ::c_int = 0x08; pub const JAIL_SET_MASK: ::c_int = 0x0f; pub const JAIL_GET_MASK: ::c_int = 0x08; pub const JAIL_SYS_DISABLE: ::c_int = 0; pub const JAIL_SYS_NEW: ::c_int = 1; pub const JAIL_SYS_INHERIT: ::c_int = 2; pub const MNT_ACLS: ::c_int = 0x08000000; pub const MNT_BYFSID: ::c_int = 0x08000000; pub const MNT_GJOURNAL: ::c_int = 0x02000000; pub const MNT_MULTILABEL: ::c_int = 0x04000000; pub const MNT_NFS4ACLS: ::c_int = 0x00000010; pub const MNT_SNAPSHOT: ::c_int = 0x01000000; pub const MNT_UNION: ::c_int = 0x00000020; pub const MNT_NONBUSY: ::c_int = 0x04000000; pub const SCM_BINTIME: ::c_int = 0x04; pub const SCM_REALTIME: ::c_int = 0x05; pub const SCM_MONOTONIC: ::c_int = 0x06; pub const SCM_TIME_INFO: ::c_int = 0x07; pub const SCM_CREDS2: ::c_int = 0x08; pub const SO_BINTIME: ::c_int = 0x2000; pub const SO_NO_OFFLOAD: ::c_int = 0x4000; pub const SO_NO_DDP: ::c_int = 0x8000; pub const SO_REUSEPORT_LB: ::c_int = 0x10000; pub const SO_LABEL: ::c_int = 0x1009; pub const SO_PEERLABEL: ::c_int = 0x1010; pub const SO_LISTENQLIMIT: ::c_int = 0x1011; pub const SO_LISTENQLEN: ::c_int = 0x1012; pub const SO_LISTENINCQLEN: ::c_int = 0x1013; pub const SO_SETFIB: ::c_int = 0x1014; pub const SO_USER_COOKIE: ::c_int = 0x1015; pub const SO_PROTOCOL: ::c_int = 0x1016; pub const SO_PROTOTYPE: ::c_int = SO_PROTOCOL; pub const SO_TS_CLOCK: ::c_int = 0x1017; pub const SO_DOMAIN: ::c_int = 0x1019; pub const SO_VENDOR: ::c_int = 0x80000000; pub const SO_TS_REALTIME_MICRO: ::c_int = 0; pub const SO_TS_BINTIME: ::c_int = 1; pub const SO_TS_REALTIME: ::c_int = 2; pub const SO_TS_MONOTONIC: ::c_int = 3; pub const SO_TS_DEFAULT: ::c_int = SO_TS_REALTIME_MICRO; pub const SO_TS_CLOCK_MAX: ::c_int = SO_TS_MONOTONIC; pub const LOCAL_CREDS: ::c_int = 2; pub const LOCAL_CREDS_PERSISTENT: ::c_int = 3; pub const LOCAL_CONNWAIT: ::c_int = 4; pub const LOCAL_VENDOR: ::c_int = SO_VENDOR; pub const PL_EVENT_NONE: ::c_int = 0; pub const PL_EVENT_SIGNAL: ::c_int = 1; pub const PL_FLAG_SA: ::c_int = 0x01; pub const PL_FLAG_BOUND: ::c_int = 0x02; pub const PL_FLAG_SCE: ::c_int = 0x04; pub const PL_FLAG_SCX: ::c_int = 0x08; pub const PL_FLAG_EXEC: ::c_int = 0x10; pub const PL_FLAG_SI: ::c_int = 0x20; pub const PL_FLAG_FORKED: ::c_int = 0x40; pub const PL_FLAG_CHILD: ::c_int = 0x80; pub const PL_FLAG_BORN: ::c_int = 0x100; pub const PL_FLAG_EXITED: ::c_int = 0x200; pub const PL_FLAG_VFORKED: ::c_int = 0x400; pub const PL_FLAG_VFORK_DONE: ::c_int = 0x800; pub const PT_LWPINFO: ::c_int = 13; pub const PT_GETNUMLWPS: ::c_int = 14; pub const PT_GETLWPLIST: ::c_int = 15; pub const PT_CLEARSTEP: ::c_int = 16; pub const PT_SETSTEP: ::c_int = 17; pub const PT_SUSPEND: ::c_int = 18; pub const PT_RESUME: ::c_int = 19; pub const PT_TO_SCE: ::c_int = 20; pub const PT_TO_SCX: ::c_int = 21; pub const PT_SYSCALL: ::c_int = 22; pub const PT_FOLLOW_FORK: ::c_int = 23; pub const PT_LWP_EVENTS: ::c_int = 24; pub const PT_GET_EVENT_MASK: ::c_int = 25; pub const PT_SET_EVENT_MASK: ::c_int = 26; pub const PT_GET_SC_ARGS: ::c_int = 27; pub const PT_GET_SC_RET: ::c_int = 28; pub const PT_COREDUMP: ::c_int = 29; pub const PT_GETREGS: ::c_int = 33; pub const PT_SETREGS: ::c_int = 34; pub const PT_GETFPREGS: ::c_int = 35; pub const PT_SETFPREGS: ::c_int = 36; pub const PT_GETDBREGS: ::c_int = 37; pub const PT_SETDBREGS: ::c_int = 38; pub const PT_VM_TIMESTAMP: ::c_int = 40; pub const PT_VM_ENTRY: ::c_int = 41; pub const PT_GETREGSET: ::c_int = 42; pub const PT_SETREGSET: ::c_int = 43; pub const PT_SC_REMOTE: ::c_int = 44; pub const PT_FIRSTMACH: ::c_int = 64; pub const PTRACE_EXEC: ::c_int = 0x0001; pub const PTRACE_SCE: ::c_int = 0x0002; pub const PTRACE_SCX: ::c_int = 0x0004; pub const PTRACE_SYSCALL: ::c_int = PTRACE_SCE | PTRACE_SCX; pub const PTRACE_FORK: ::c_int = 0x0008; pub const PTRACE_LWP: ::c_int = 0x0010; pub const PTRACE_VFORK: ::c_int = 0x0020; pub const PTRACE_DEFAULT: ::c_int = PTRACE_EXEC; pub const PC_COMPRESS: u32 = 0x00000001; pub const PC_ALL: u32 = 0x00000002; pub const PROC_SPROTECT: ::c_int = 1; pub const PROC_REAP_ACQUIRE: ::c_int = 2; pub const PROC_REAP_RELEASE: ::c_int = 3; pub const PROC_REAP_STATUS: ::c_int = 4; pub const PROC_REAP_GETPIDS: ::c_int = 5; pub const PROC_REAP_KILL: ::c_int = 6; pub const PROC_TRACE_CTL: ::c_int = 7; pub const PROC_TRACE_STATUS: ::c_int = 8; pub const PROC_TRAPCAP_CTL: ::c_int = 9; pub const PROC_TRAPCAP_STATUS: ::c_int = 10; pub const PROC_PDEATHSIG_CTL: ::c_int = 11; pub const PROC_PDEATHSIG_STATUS: ::c_int = 12; pub const PROC_ASLR_CTL: ::c_int = 13; pub const PROC_ASLR_STATUS: ::c_int = 14; pub const PROC_PROTMAX_CTL: ::c_int = 15; pub const PROC_PROTMAX_STATUS: ::c_int = 16; pub const PROC_STACKGAP_CTL: ::c_int = 17; pub const PROC_STACKGAP_STATUS: ::c_int = 18; pub const PROC_NO_NEW_PRIVS_CTL: ::c_int = 19; pub const PROC_NO_NEW_PRIVS_STATUS: ::c_int = 20; pub const PROC_WXMAP_CTL: ::c_int = 21; pub const PROC_WXMAP_STATUS: ::c_int = 22; pub const PROC_PROCCTL_MD_MIN: ::c_int = 0x10000000; pub const PPROT_SET: ::c_int = 1; pub const PPROT_CLEAR: ::c_int = 2; pub const PPROT_DESCEND: ::c_int = 0x10; pub const PPROT_INHERIT: ::c_int = 0x20; pub const PROC_TRACE_CTL_ENABLE: ::c_int = 1; pub const PROC_TRACE_CTL_DISABLE: ::c_int = 2; pub const PROC_TRACE_CTL_DISABLE_EXEC: ::c_int = 3; pub const PROC_TRAPCAP_CTL_ENABLE: ::c_int = 1; pub const PROC_TRAPCAP_CTL_DISABLE: ::c_int = 2; pub const PROC_ASLR_FORCE_ENABLE: ::c_int = 1; pub const PROC_ASLR_FORCE_DISABLE: ::c_int = 2; pub const PROC_ASLR_NOFORCE: ::c_int = 3; pub const PROC_ASLR_ACTIVE: ::c_int = 0x80000000; pub const PROC_PROTMAX_FORCE_ENABLE: ::c_int = 1; pub const PROC_PROTMAX_FORCE_DISABLE: ::c_int = 2; pub const PROC_PROTMAX_NOFORCE: ::c_int = 3; pub const PROC_PROTMAX_ACTIVE: ::c_int = 0x80000000; pub const PROC_STACKGAP_ENABLE: ::c_int = 0x0001; pub const PROC_STACKGAP_DISABLE: ::c_int = 0x0002; pub const PROC_STACKGAP_ENABLE_EXEC: ::c_int = 0x0004; pub const PROC_STACKGAP_DISABLE_EXEC: ::c_int = 0x0008; pub const PROC_NO_NEW_PRIVS_ENABLE: ::c_int = 1; pub const PROC_NO_NEW_PRIVS_DISABLE: ::c_int = 2; pub const PROC_WX_MAPPINGS_PERMIT: ::c_int = 0x0001; pub const PROC_WX_MAPPINGS_DISALLOW_EXEC: ::c_int = 0x0002; pub const PROC_WXORX_ENFORCE: ::c_int = 0x80000000; pub const AF_SLOW: ::c_int = 33; pub const AF_SCLUSTER: ::c_int = 34; pub const AF_ARP: ::c_int = 35; pub const AF_BLUETOOTH: ::c_int = 36; pub const AF_IEEE80211: ::c_int = 37; pub const AF_INET_SDP: ::c_int = 40; pub const AF_INET6_SDP: ::c_int = 42; // sys/net/if.h pub const IF_MAXUNIT: ::c_int = 0x7fff; /// (n) interface is up pub const IFF_UP: ::c_int = 0x1; /// (i) broadcast address valid pub const IFF_BROADCAST: ::c_int = 0x2; /// (n) turn on debugging pub const IFF_DEBUG: ::c_int = 0x4; /// (i) is a loopback net pub const IFF_LOOPBACK: ::c_int = 0x8; /// (i) is a point-to-point link pub const IFF_POINTOPOINT: ::c_int = 0x10; /// (i) calls if_input in net epoch #[deprecated(since = "0.2.149", note = "Removed in FreeBSD 14")] pub const IFF_KNOWSEPOCH: ::c_int = 0x20; /// (d) resources allocated pub const IFF_RUNNING: ::c_int = 0x40; #[doc(hidden)] #[deprecated( since = "0.2.54", note = "IFF_DRV_RUNNING is deprecated. Use the portable IFF_RUNNING instead" )] /// (d) resources allocate pub const IFF_DRV_RUNNING: ::c_int = 0x40; /// (n) no address resolution protocol pub const IFF_NOARP: ::c_int = 0x80; /// (n) receive all packets pub const IFF_PROMISC: ::c_int = 0x100; /// (n) receive all multicast packets pub const IFF_ALLMULTI: ::c_int = 0x200; /// (d) tx hardware queue is full pub const IFF_OACTIVE: ::c_int = 0x400; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Use the portable `IFF_OACTIVE` instead")] /// (d) tx hardware queue is full pub const IFF_DRV_OACTIVE: ::c_int = 0x400; /// (i) can't hear own transmissions pub const IFF_SIMPLEX: ::c_int = 0x800; /// per link layer defined bit pub const IFF_LINK0: ::c_int = 0x1000; /// per link layer defined bit pub const IFF_LINK1: ::c_int = 0x2000; /// per link layer defined bit pub const IFF_LINK2: ::c_int = 0x4000; /// use alternate physical connection pub const IFF_ALTPHYS: ::c_int = IFF_LINK2; /// (i) supports multicast pub const IFF_MULTICAST: ::c_int = 0x8000; /// (i) unconfigurable using ioctl(2) pub const IFF_CANTCONFIG: ::c_int = 0x10000; /// (n) user-requested promisc mode pub const IFF_PPROMISC: ::c_int = 0x20000; /// (n) user-requested monitor mode pub const IFF_MONITOR: ::c_int = 0x40000; /// (n) static ARP pub const IFF_STATICARP: ::c_int = 0x80000; /// (n) interface is winding down pub const IFF_DYING: ::c_int = 0x200000; /// (n) interface is being renamed pub const IFF_RENAMING: ::c_int = 0x400000; /// interface is not part of any groups #[deprecated(since = "0.2.149", note = "Removed in FreeBSD 14")] pub const IFF_NOGROUP: ::c_int = 0x800000; /// link invalid/unknown pub const LINK_STATE_UNKNOWN: ::c_int = 0; /// link is down pub const LINK_STATE_DOWN: ::c_int = 1; /// link is up pub const LINK_STATE_UP: ::c_int = 2; /// can offload checksum on RX pub const IFCAP_RXCSUM: ::c_int = 0x00001; /// can offload checksum on TX pub const IFCAP_TXCSUM: ::c_int = 0x00002; /// can be a network console pub const IFCAP_NETCONS: ::c_int = 0x00004; /// VLAN-compatible MTU pub const IFCAP_VLAN_MTU: ::c_int = 0x00008; /// hardware VLAN tag support pub const IFCAP_VLAN_HWTAGGING: ::c_int = 0x00010; /// 9000 byte MTU supported pub const IFCAP_JUMBO_MTU: ::c_int = 0x00020; /// driver supports polling pub const IFCAP_POLLING: ::c_int = 0x00040; /// can do IFCAP_HWCSUM on VLANs pub const IFCAP_VLAN_HWCSUM: ::c_int = 0x00080; /// can do TCP Segmentation Offload pub const IFCAP_TSO4: ::c_int = 0x00100; /// can do TCP6 Segmentation Offload pub const IFCAP_TSO6: ::c_int = 0x00200; /// can do Large Receive Offload pub const IFCAP_LRO: ::c_int = 0x00400; /// wake on any unicast frame pub const IFCAP_WOL_UCAST: ::c_int = 0x00800; /// wake on any multicast frame pub const IFCAP_WOL_MCAST: ::c_int = 0x01000; /// wake on any Magic Packet pub const IFCAP_WOL_MAGIC: ::c_int = 0x02000; /// interface can offload TCP pub const IFCAP_TOE4: ::c_int = 0x04000; /// interface can offload TCP6 pub const IFCAP_TOE6: ::c_int = 0x08000; /// interface hw can filter vlan tag pub const IFCAP_VLAN_HWFILTER: ::c_int = 0x10000; /// can do SIOCGIFCAPNV/SIOCSIFCAPNV pub const IFCAP_NV: ::c_int = 0x20000; /// can do IFCAP_TSO on VLANs pub const IFCAP_VLAN_HWTSO: ::c_int = 0x40000; /// the runtime link state is dynamic pub const IFCAP_LINKSTATE: ::c_int = 0x80000; /// netmap mode supported/enabled pub const IFCAP_NETMAP: ::c_int = 0x100000; /// can offload checksum on IPv6 RX pub const IFCAP_RXCSUM_IPV6: ::c_int = 0x200000; /// can offload checksum on IPv6 TX pub const IFCAP_TXCSUM_IPV6: ::c_int = 0x400000; /// manages counters internally pub const IFCAP_HWSTATS: ::c_int = 0x800000; /// hardware supports TX rate limiting pub const IFCAP_TXRTLMT: ::c_int = 0x1000000; /// hardware rx timestamping pub const IFCAP_HWRXTSTMP: ::c_int = 0x2000000; /// understands M_EXTPG mbufs pub const IFCAP_MEXTPG: ::c_int = 0x4000000; /// can do TLS encryption and segmentation for TCP pub const IFCAP_TXTLS4: ::c_int = 0x8000000; /// can do TLS encryption and segmentation for TCP6 pub const IFCAP_TXTLS6: ::c_int = 0x10000000; /// can do IFCAN_HWCSUM on VXLANs pub const IFCAP_VXLAN_HWCSUM: ::c_int = 0x20000000; /// can do IFCAP_TSO on VXLANs pub const IFCAP_VXLAN_HWTSO: ::c_int = 0x40000000; /// can do TLS with rate limiting pub const IFCAP_TXTLS_RTLMT: ::c_int = 0x80000000; pub const IFCAP_HWCSUM_IPV6: ::c_int = IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6; pub const IFCAP_HWCSUM: ::c_int = IFCAP_RXCSUM | IFCAP_TXCSUM; pub const IFCAP_TSO: ::c_int = IFCAP_TSO4 | IFCAP_TSO6; pub const IFCAP_WOL: ::c_int = IFCAP_WOL_UCAST | IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC; pub const IFCAP_TOE: ::c_int = IFCAP_TOE4 | IFCAP_TOE6; pub const IFCAP_TXTLS: ::c_int = IFCAP_TXTLS4 | IFCAP_TXTLS6; pub const IFCAP_CANTCHANGE: ::c_int = IFCAP_NETMAP | IFCAP_NV; pub const IFQ_MAXLEN: ::c_int = 50; pub const IFNET_SLOWHZ: ::c_int = 1; pub const IFAN_ARRIVAL: ::c_int = 0; pub const IFAN_DEPARTURE: ::c_int = 1; pub const IFSTATMAX: ::c_int = 800; pub const RSS_FUNC_NONE: ::c_int = 0; pub const RSS_FUNC_PRIVATE: ::c_int = 1; pub const RSS_FUNC_TOEPLITZ: ::c_int = 2; pub const RSS_TYPE_IPV4: ::c_int = 0x00000001; pub const RSS_TYPE_TCP_IPV4: ::c_int = 0x00000002; pub const RSS_TYPE_IPV6: ::c_int = 0x00000004; pub const RSS_TYPE_IPV6_EX: ::c_int = 0x00000008; pub const RSS_TYPE_TCP_IPV6: ::c_int = 0x00000010; pub const RSS_TYPE_TCP_IPV6_EX: ::c_int = 0x00000020; pub const RSS_TYPE_UDP_IPV4: ::c_int = 0x00000040; pub const RSS_TYPE_UDP_IPV6: ::c_int = 0x00000080; pub const RSS_TYPE_UDP_IPV6_EX: ::c_int = 0x00000100; pub const RSS_KEYLEN: ::c_int = 128; pub const IFNET_PCP_NONE: ::c_int = 0xff; pub const IFDR_MSG_SIZE: ::c_int = 64; pub const IFDR_REASON_MSG: ::c_int = 1; pub const IFDR_REASON_VENDOR: ::c_int = 2; // sys/net/if_mib.h /// non-interface-specific pub const IFMIB_SYSTEM: ::c_int = 1; /// per-interface data table pub const IFMIB_IFDATA: ::c_int = 2; /// generic stats for all kinds of ifaces pub const IFDATA_GENERAL: ::c_int = 1; /// specific to the type of interface pub const IFDATA_LINKSPECIFIC: ::c_int = 2; /// driver name and unit pub const IFDATA_DRIVERNAME: ::c_int = 3; /// number of interfaces configured pub const IFMIB_IFCOUNT: ::c_int = 1; /// functions not specific to a type of iface pub const NETLINK_GENERIC: ::c_int = 0; pub const DOT3COMPLIANCE_STATS: ::c_int = 1; pub const DOT3COMPLIANCE_COLLS: ::c_int = 2; pub const dot3ChipSetAMD7990: ::c_int = 1; pub const dot3ChipSetAMD79900: ::c_int = 2; pub const dot3ChipSetAMD79C940: ::c_int = 3; pub const dot3ChipSetIntel82586: ::c_int = 1; pub const dot3ChipSetIntel82596: ::c_int = 2; pub const dot3ChipSetIntel82557: ::c_int = 3; pub const dot3ChipSetNational8390: ::c_int = 1; pub const dot3ChipSetNationalSonic: ::c_int = 2; pub const dot3ChipSetFujitsu86950: ::c_int = 1; pub const dot3ChipSetDigitalDC21040: ::c_int = 1; pub const dot3ChipSetDigitalDC21140: ::c_int = 2; pub const dot3ChipSetDigitalDC21041: ::c_int = 3; pub const dot3ChipSetDigitalDC21140A: ::c_int = 4; pub const dot3ChipSetDigitalDC21142: ::c_int = 5; pub const dot3ChipSetWesternDigital83C690: ::c_int = 1; pub const dot3ChipSetWesternDigital83C790: ::c_int = 2; // sys/netinet/in.h // Protocols (RFC 1700) // NOTE: These are in addition to the constants defined in src/unix/mod.rs // IPPROTO_IP defined in src/unix/mod.rs /// IP6 hop-by-hop options pub const IPPROTO_HOPOPTS: ::c_int = 0; // IPPROTO_ICMP defined in src/unix/mod.rs /// group mgmt protocol pub const IPPROTO_IGMP: ::c_int = 2; /// gateway^2 (deprecated) pub const IPPROTO_GGP: ::c_int = 3; /// for compatibility pub const IPPROTO_IPIP: ::c_int = 4; // IPPROTO_TCP defined in src/unix/mod.rs /// Stream protocol II. pub const IPPROTO_ST: ::c_int = 7; /// exterior gateway protocol pub const IPPROTO_EGP: ::c_int = 8; /// private interior gateway pub const IPPROTO_PIGP: ::c_int = 9; /// BBN RCC Monitoring pub const IPPROTO_RCCMON: ::c_int = 10; /// network voice protocol pub const IPPROTO_NVPII: ::c_int = 11; /// pup pub const IPPROTO_PUP: ::c_int = 12; /// Argus pub const IPPROTO_ARGUS: ::c_int = 13; /// EMCON pub const IPPROTO_EMCON: ::c_int = 14; /// Cross Net Debugger pub const IPPROTO_XNET: ::c_int = 15; /// Chaos pub const IPPROTO_CHAOS: ::c_int = 16; // IPPROTO_UDP defined in src/unix/mod.rs /// Multiplexing pub const IPPROTO_MUX: ::c_int = 18; /// DCN Measurement Subsystems pub const IPPROTO_MEAS: ::c_int = 19; /// Host Monitoring pub const IPPROTO_HMP: ::c_int = 20; /// Packet Radio Measurement pub const IPPROTO_PRM: ::c_int = 21; /// xns idp pub const IPPROTO_IDP: ::c_int = 22; /// Trunk-1 pub const IPPROTO_TRUNK1: ::c_int = 23; /// Trunk-2 pub const IPPROTO_TRUNK2: ::c_int = 24; /// Leaf-1 pub const IPPROTO_LEAF1: ::c_int = 25; /// Leaf-2 pub const IPPROTO_LEAF2: ::c_int = 26; /// Reliable Data pub const IPPROTO_RDP: ::c_int = 27; /// Reliable Transaction pub const IPPROTO_IRTP: ::c_int = 28; /// tp-4 w/ class negotiation pub const IPPROTO_TP: ::c_int = 29; /// Bulk Data Transfer pub const IPPROTO_BLT: ::c_int = 30; /// Network Services pub const IPPROTO_NSP: ::c_int = 31; /// Merit Internodal pub const IPPROTO_INP: ::c_int = 32; #[doc(hidden)] #[deprecated( since = "0.2.72", note = "IPPROTO_SEP is deprecated. Use IPPROTO_DCCP instead" )] pub const IPPROTO_SEP: ::c_int = 33; /// Datagram Congestion Control Protocol pub const IPPROTO_DCCP: ::c_int = 33; /// Third Party Connect pub const IPPROTO_3PC: ::c_int = 34; /// InterDomain Policy Routing pub const IPPROTO_IDPR: ::c_int = 35; /// XTP pub const IPPROTO_XTP: ::c_int = 36; /// Datagram Delivery pub const IPPROTO_DDP: ::c_int = 37; /// Control Message Transport pub const IPPROTO_CMTP: ::c_int = 38; /// TP++ Transport pub const IPPROTO_TPXX: ::c_int = 39; /// IL transport protocol pub const IPPROTO_IL: ::c_int = 40; // IPPROTO_IPV6 defined in src/unix/mod.rs /// Source Demand Routing pub const IPPROTO_SDRP: ::c_int = 42; /// IP6 routing header pub const IPPROTO_ROUTING: ::c_int = 43; /// IP6 fragmentation header pub const IPPROTO_FRAGMENT: ::c_int = 44; /// InterDomain Routing pub const IPPROTO_IDRP: ::c_int = 45; /// resource reservation pub const IPPROTO_RSVP: ::c_int = 46; /// General Routing Encap. pub const IPPROTO_GRE: ::c_int = 47; /// Mobile Host Routing pub const IPPROTO_MHRP: ::c_int = 48; /// BHA pub const IPPROTO_BHA: ::c_int = 49; /// IP6 Encap Sec. Payload pub const IPPROTO_ESP: ::c_int = 50; /// IP6 Auth Header pub const IPPROTO_AH: ::c_int = 51; /// Integ. Net Layer Security pub const IPPROTO_INLSP: ::c_int = 52; /// IP with encryption pub const IPPROTO_SWIPE: ::c_int = 53; /// Next Hop Resolution pub const IPPROTO_NHRP: ::c_int = 54; /// IP Mobility pub const IPPROTO_MOBILE: ::c_int = 55; /// Transport Layer Security pub const IPPROTO_TLSP: ::c_int = 56; /// SKIP pub const IPPROTO_SKIP: ::c_int = 57; // IPPROTO_ICMPV6 defined in src/unix/mod.rs /// IP6 no next header pub const IPPROTO_NONE: ::c_int = 59; /// IP6 destination option pub const IPPROTO_DSTOPTS: ::c_int = 60; /// any host internal protocol pub const IPPROTO_AHIP: ::c_int = 61; /// CFTP pub const IPPROTO_CFTP: ::c_int = 62; /// "hello" routing protocol pub const IPPROTO_HELLO: ::c_int = 63; /// SATNET/Backroom EXPAK pub const IPPROTO_SATEXPAK: ::c_int = 64; /// Kryptolan pub const IPPROTO_KRYPTOLAN: ::c_int = 65; /// Remote Virtual Disk pub const IPPROTO_RVD: ::c_int = 66; /// Pluribus Packet Core pub const IPPROTO_IPPC: ::c_int = 67; /// Any distributed FS pub const IPPROTO_ADFS: ::c_int = 68; /// Satnet Monitoring pub const IPPROTO_SATMON: ::c_int = 69; /// VISA Protocol pub const IPPROTO_VISA: ::c_int = 70; /// Packet Core Utility pub const IPPROTO_IPCV: ::c_int = 71; /// Comp. Prot. Net. Executive pub const IPPROTO_CPNX: ::c_int = 72; /// Comp. Prot. HeartBeat pub const IPPROTO_CPHB: ::c_int = 73; /// Wang Span Network pub const IPPROTO_WSN: ::c_int = 74; /// Packet Video Protocol pub const IPPROTO_PVP: ::c_int = 75; /// BackRoom SATNET Monitoring pub const IPPROTO_BRSATMON: ::c_int = 76; /// Sun net disk proto (temp.) pub const IPPROTO_ND: ::c_int = 77; /// WIDEBAND Monitoring pub const IPPROTO_WBMON: ::c_int = 78; /// WIDEBAND EXPAK pub const IPPROTO_WBEXPAK: ::c_int = 79; /// ISO cnlp pub const IPPROTO_EON: ::c_int = 80; /// VMTP pub const IPPROTO_VMTP: ::c_int = 81; /// Secure VMTP pub const IPPROTO_SVMTP: ::c_int = 82; /// Banyon VINES pub const IPPROTO_VINES: ::c_int = 83; /// TTP pub const IPPROTO_TTP: ::c_int = 84; /// NSFNET-IGP pub const IPPROTO_IGP: ::c_int = 85; /// dissimilar gateway prot. pub const IPPROTO_DGP: ::c_int = 86; /// TCF pub const IPPROTO_TCF: ::c_int = 87; /// Cisco/GXS IGRP pub const IPPROTO_IGRP: ::c_int = 88; /// OSPFIGP pub const IPPROTO_OSPFIGP: ::c_int = 89; /// Strite RPC protocol pub const IPPROTO_SRPC: ::c_int = 90; /// Locus Address Resoloution pub const IPPROTO_LARP: ::c_int = 91; /// Multicast Transport pub const IPPROTO_MTP: ::c_int = 92; /// AX.25 Frames pub const IPPROTO_AX25: ::c_int = 93; /// IP encapsulated in IP pub const IPPROTO_IPEIP: ::c_int = 94; /// Mobile Int.ing control pub const IPPROTO_MICP: ::c_int = 95; /// Semaphore Comm. security pub const IPPROTO_SCCSP: ::c_int = 96; /// Ethernet IP encapsulation pub const IPPROTO_ETHERIP: ::c_int = 97; /// encapsulation header pub const IPPROTO_ENCAP: ::c_int = 98; /// any private encr. scheme pub const IPPROTO_APES: ::c_int = 99; /// GMTP pub const IPPROTO_GMTP: ::c_int = 100; /// payload compression (IPComp) pub const IPPROTO_IPCOMP: ::c_int = 108; /// SCTP pub const IPPROTO_SCTP: ::c_int = 132; /// IPv6 Mobility Header pub const IPPROTO_MH: ::c_int = 135; /// UDP-Lite pub const IPPROTO_UDPLITE: ::c_int = 136; /// IP6 Host Identity Protocol pub const IPPROTO_HIP: ::c_int = 139; /// IP6 Shim6 Protocol pub const IPPROTO_SHIM6: ::c_int = 140; /* 101-254: Partly Unassigned */ /// Protocol Independent Mcast pub const IPPROTO_PIM: ::c_int = 103; /// CARP pub const IPPROTO_CARP: ::c_int = 112; /// PGM pub const IPPROTO_PGM: ::c_int = 113; /// MPLS-in-IP pub const IPPROTO_MPLS: ::c_int = 137; /// PFSYNC pub const IPPROTO_PFSYNC: ::c_int = 240; /* 255: Reserved */ /* BSD Private, local use, namespace incursion, no longer used */ /// OLD divert pseudo-proto pub const IPPROTO_OLD_DIVERT: ::c_int = 254; pub const IPPROTO_MAX: ::c_int = 256; /// last return value of *_input(), meaning "all job for this pkt is done". pub const IPPROTO_DONE: ::c_int = 257; /* Only used internally, so can be outside the range of valid IP protocols. */ /// divert pseudo-protocol pub const IPPROTO_DIVERT: ::c_int = 258; /// SeND pseudo-protocol pub const IPPROTO_SEND: ::c_int = 259; // sys/netinet/TCP.h pub const TCP_MD5SIG: ::c_int = 16; pub const TCP_INFO: ::c_int = 32; pub const TCP_CONGESTION: ::c_int = 64; pub const TCP_CCALGOOPT: ::c_int = 65; pub const TCP_MAXUNACKTIME: ::c_int = 68; pub const TCP_MAXPEAKRATE: ::c_int = 69; pub const TCP_IDLE_REDUCE: ::c_int = 70; pub const TCP_REMOTE_UDP_ENCAPS_PORT: ::c_int = 71; pub const TCP_DELACK: ::c_int = 72; pub const TCP_FIN_IS_RST: ::c_int = 73; pub const TCP_LOG_LIMIT: ::c_int = 74; pub const TCP_SHARED_CWND_ALLOWED: ::c_int = 75; pub const TCP_PROC_ACCOUNTING: ::c_int = 76; pub const TCP_USE_CMP_ACKS: ::c_int = 77; pub const TCP_PERF_INFO: ::c_int = 78; pub const TCP_LRD: ::c_int = 79; pub const TCP_KEEPINIT: ::c_int = 128; pub const TCP_FASTOPEN: ::c_int = 1025; pub const TCP_PCAP_OUT: ::c_int = 2048; pub const TCP_PCAP_IN: ::c_int = 4096; pub const TCP_FASTOPEN_PSK_LEN: ::c_int = 16; pub const TCP_FUNCTION_NAME_LEN_MAX: ::c_int = 32; pub const IP_BINDANY: ::c_int = 24; pub const IP_BINDMULTI: ::c_int = 25; pub const IP_RSS_LISTEN_BUCKET: ::c_int = 26; pub const IP_ORIGDSTADDR: ::c_int = 27; pub const IP_RECVORIGDSTADDR: ::c_int = IP_ORIGDSTADDR; pub const IP_DONTFRAG: ::c_int = 67; pub const IP_RECVTOS: ::c_int = 68; pub const IPV6_BINDANY: ::c_int = 64; pub const IPV6_ORIGDSTADDR: ::c_int = 72; pub const IPV6_RECVORIGDSTADDR: ::c_int = IPV6_ORIGDSTADDR; pub const PF_SLOW: ::c_int = AF_SLOW; pub const PF_SCLUSTER: ::c_int = AF_SCLUSTER; pub const PF_ARP: ::c_int = AF_ARP; pub const PF_BLUETOOTH: ::c_int = AF_BLUETOOTH; pub const PF_IEEE80211: ::c_int = AF_IEEE80211; pub const PF_INET_SDP: ::c_int = AF_INET_SDP; pub const PF_INET6_SDP: ::c_int = AF_INET6_SDP; pub const NET_RT_DUMP: ::c_int = 1; pub const NET_RT_FLAGS: ::c_int = 2; pub const NET_RT_IFLIST: ::c_int = 3; pub const NET_RT_IFMALIST: ::c_int = 4; pub const NET_RT_IFLISTL: ::c_int = 5; // System V IPC pub const IPC_INFO: ::c_int = 3; pub const MSG_NOERROR: ::c_int = 0o10000; pub const SHM_LOCK: ::c_int = 11; pub const SHM_UNLOCK: ::c_int = 12; pub const SHM_STAT: ::c_int = 13; pub const SHM_INFO: ::c_int = 14; pub const SHM_ANON: *mut ::c_char = 1 as *mut ::c_char; // The *_MAXID constants never should've been used outside of the // FreeBSD base system. And with the exception of CTL_P1003_1B_MAXID, // they were all removed in svn r262489. They remain here for backwards // compatibility only, and are scheduled to be removed in libc 1.0.0. #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const CTL_MAXID: ::c_int = 10; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const KERN_MAXID: ::c_int = 38; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const HW_MAXID: ::c_int = 13; #[doc(hidden)] #[deprecated(since = "0.2.54", note = "Removed in FreeBSD 11")] pub const USER_MAXID: ::c_int = 21; #[doc(hidden)] #[deprecated(since = "0.2.74", note = "Removed in FreeBSD 13")] pub const CTL_P1003_1B_MAXID: ::c_int = 26; pub const MSG_NOTIFICATION: ::c_int = 0x00002000; pub const MSG_NBIO: ::c_int = 0x00004000; pub const MSG_COMPAT: ::c_int = 0x00008000; pub const MSG_CMSG_CLOEXEC: ::c_int = 0x00040000; pub const MSG_NOSIGNAL: ::c_int = 0x20000; pub const MSG_WAITFORONE: ::c_int = 0x00080000; // utmpx entry types pub const EMPTY: ::c_short = 0; pub const BOOT_TIME: ::c_short = 1; pub const OLD_TIME: ::c_short = 2; pub const NEW_TIME: ::c_short = 3; pub const USER_PROCESS: ::c_short = 4; pub const INIT_PROCESS: ::c_short = 5; pub const LOGIN_PROCESS: ::c_short = 6; pub const DEAD_PROCESS: ::c_short = 7; pub const SHUTDOWN_TIME: ::c_short = 8; // utmp database types pub const UTXDB_ACTIVE: ::c_int = 0; pub const UTXDB_LASTLOGIN: ::c_int = 1; pub const UTXDB_LOG: ::c_int = 2; pub const LC_COLLATE_MASK: ::c_int = 1 << 0; pub const LC_CTYPE_MASK: ::c_int = 1 << 1; pub const LC_MONETARY_MASK: ::c_int = 1 << 2; pub const LC_NUMERIC_MASK: ::c_int = 1 << 3; pub const LC_TIME_MASK: ::c_int = 1 << 4; pub const LC_MESSAGES_MASK: ::c_int = 1 << 5; pub const LC_ALL_MASK: ::c_int = LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK; pub const WSTOPPED: ::c_int = 2; // same as WUNTRACED pub const WCONTINUED: ::c_int = 4; pub const WNOWAIT: ::c_int = 8; pub const WEXITED: ::c_int = 16; pub const WTRAPPED: ::c_int = 32; // FreeBSD defines a great many more of these, we only expose the // standardized ones. pub const P_PID: idtype_t = 0; pub const P_PGID: idtype_t = 2; pub const P_ALL: idtype_t = 7; pub const UTIME_OMIT: c_long = -2; pub const UTIME_NOW: c_long = -1; pub const B460800: ::speed_t = 460800; pub const B921600: ::speed_t = 921600; pub const AT_FDCWD: ::c_int = -100; pub const AT_EACCESS: ::c_int = 0x100; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 0x200; pub const AT_SYMLINK_FOLLOW: ::c_int = 0x400; pub const AT_REMOVEDIR: ::c_int = 0x800; pub const AT_RESOLVE_BENEATH: ::c_int = 0x2000; pub const AT_EMPTY_PATH: ::c_int = 0x4000; pub const AT_NULL: ::c_int = 0; pub const AT_IGNORE: ::c_int = 1; pub const AT_EXECFD: ::c_int = 2; pub const AT_PHDR: ::c_int = 3; pub const AT_PHENT: ::c_int = 4; pub const AT_PHNUM: ::c_int = 5; pub const AT_PAGESZ: ::c_int = 6; pub const AT_BASE: ::c_int = 7; pub const AT_FLAGS: ::c_int = 8; pub const AT_ENTRY: ::c_int = 9; pub const AT_NOTELF: ::c_int = 10; pub const AT_UID: ::c_int = 11; pub const AT_EUID: ::c_int = 12; pub const AT_GID: ::c_int = 13; pub const AT_EGID: ::c_int = 14; pub const AT_EXECPATH: ::c_int = 15; pub const AT_CANARY: ::c_int = 16; pub const AT_OSRELDATE: ::c_int = 18; pub const AT_NCPUS: ::c_int = 19; pub const AT_PAGESIZES: ::c_int = 20; pub const AT_TIMEKEEP: ::c_int = 22; pub const AT_HWCAP: ::c_int = 25; pub const AT_HWCAP2: ::c_int = 26; pub const AT_USRSTACKBASE: ::c_int = 35; pub const AT_USRSTACKLIM: ::c_int = 36; pub const TABDLY: ::tcflag_t = 0x00000004; pub const TAB0: ::tcflag_t = 0x00000000; pub const TAB3: ::tcflag_t = 0x00000004; pub const _PC_ACL_NFS4: ::c_int = 64; pub const _SC_CPUSET_SIZE: ::c_int = 122; pub const _UUID_NODE_LEN: usize = 6; // Flags which can be passed to pdfork(2) pub const PD_DAEMON: ::c_int = 0x00000001; pub const PD_CLOEXEC: ::c_int = 0x00000002; pub const PD_ALLOWED_AT_FORK: ::c_int = PD_DAEMON | PD_CLOEXEC; // Values for struct rtprio (type_ field) pub const RTP_PRIO_REALTIME: ::c_ushort = 2; pub const RTP_PRIO_NORMAL: ::c_ushort = 3; pub const RTP_PRIO_IDLE: ::c_ushort = 4; pub const POSIX_SPAWN_RESETIDS: ::c_int = 0x01; pub const POSIX_SPAWN_SETPGROUP: ::c_int = 0x02; pub const POSIX_SPAWN_SETSCHEDPARAM: ::c_int = 0x04; pub const POSIX_SPAWN_SETSCHEDULER: ::c_int = 0x08; pub const POSIX_SPAWN_SETSIGDEF: ::c_int = 0x10; pub const POSIX_SPAWN_SETSIGMASK: ::c_int = 0x20; // Flags for chflags(2) pub const UF_SYSTEM: ::c_ulong = 0x00000080; pub const UF_SPARSE: ::c_ulong = 0x00000100; pub const UF_OFFLINE: ::c_ulong = 0x00000200; pub const UF_REPARSE: ::c_ulong = 0x00000400; pub const UF_ARCHIVE: ::c_ulong = 0x00000800; pub const UF_READONLY: ::c_ulong = 0x00001000; pub const UF_HIDDEN: ::c_ulong = 0x00008000; pub const SF_SNAPSHOT: ::c_ulong = 0x00200000; // fcntl commands pub const F_ADD_SEALS: ::c_int = 19; pub const F_GET_SEALS: ::c_int = 20; pub const F_OGETLK: ::c_int = 7; pub const F_OSETLK: ::c_int = 8; pub const F_OSETLKW: ::c_int = 9; pub const F_RDAHEAD: ::c_int = 16; pub const F_READAHEAD: ::c_int = 15; pub const F_SETLK_REMOTE: ::c_int = 14; pub const F_KINFO: ::c_int = 22; // for use with F_ADD_SEALS pub const F_SEAL_GROW: ::c_int = 4; pub const F_SEAL_SEAL: ::c_int = 1; pub const F_SEAL_SHRINK: ::c_int = 2; pub const F_SEAL_WRITE: ::c_int = 8; // for use with fspacectl pub const SPACECTL_DEALLOC: ::c_int = 1; // For realhostname* api pub const HOSTNAME_FOUND: ::c_int = 0; pub const HOSTNAME_INCORRECTNAME: ::c_int = 1; pub const HOSTNAME_INVALIDADDR: ::c_int = 2; pub const HOSTNAME_INVALIDNAME: ::c_int = 3; // For rfork pub const RFFDG: ::c_int = 4; pub const RFPROC: ::c_int = 16; pub const RFMEM: ::c_int = 32; pub const RFNOWAIT: ::c_int = 64; pub const RFCFDG: ::c_int = 4096; pub const RFTHREAD: ::c_int = 8192; pub const RFSIGSHARE: ::c_int = 16384; pub const RFLINUXTHPN: ::c_int = 65536; pub const RFTSIGZMB: ::c_int = 524288; pub const RFSPAWN: ::c_int = 2147483648; // For eventfd pub const EFD_SEMAPHORE: ::c_int = 0x1; pub const EFD_NONBLOCK: ::c_int = 0x4; pub const EFD_CLOEXEC: ::c_int = 0x100000; pub const MALLOCX_ZERO: ::c_int = 0x40; /// size of returned wchan message pub const WMESGLEN: usize = 8; /// size of returned lock name pub const LOCKNAMELEN: usize = 8; /// size of returned thread name pub const TDNAMLEN: usize = 16; /// size of returned ki_comm name pub const COMMLEN: usize = 19; /// size of returned ki_emul pub const KI_EMULNAMELEN: usize = 16; /// number of groups in ki_groups pub const KI_NGROUPS: usize = 16; cfg_if! { if #[cfg(freebsd11)] { pub const KI_NSPARE_INT: usize = 4; } else { pub const KI_NSPARE_INT: usize = 2; } } pub const KI_NSPARE_LONG: usize = 12; /// Flags for the process credential. pub const KI_CRF_CAPABILITY_MODE: usize = 0x00000001; /// Steal a bit from ki_cr_flags to indicate that the cred had more than /// KI_NGROUPS groups. pub const KI_CRF_GRP_OVERFLOW: usize = 0x80000000; /// controlling tty vnode active pub const KI_CTTY: usize = 0x00000001; /// session leader pub const KI_SLEADER: usize = 0x00000002; /// proc blocked on lock ki_lockname pub const KI_LOCKBLOCK: usize = 0x00000004; /// size of returned ki_login pub const LOGNAMELEN: usize = 17; /// size of returned ki_loginclass pub const LOGINCLASSLEN: usize = 17; pub const KF_ATTR_VALID: ::c_int = 0x0001; pub const KF_TYPE_NONE: ::c_int = 0; pub const KF_TYPE_VNODE: ::c_int = 1; pub const KF_TYPE_SOCKET: ::c_int = 2; pub const KF_TYPE_PIPE: ::c_int = 3; pub const KF_TYPE_FIFO: ::c_int = 4; pub const KF_TYPE_KQUEUE: ::c_int = 5; pub const KF_TYPE_MQUEUE: ::c_int = 7; pub const KF_TYPE_SHM: ::c_int = 8; pub const KF_TYPE_SEM: ::c_int = 9; pub const KF_TYPE_PTS: ::c_int = 10; pub const KF_TYPE_PROCDESC: ::c_int = 11; pub const KF_TYPE_DEV: ::c_int = 12; pub const KF_TYPE_UNKNOWN: ::c_int = 255; pub const KF_VTYPE_VNON: ::c_int = 0; pub const KF_VTYPE_VREG: ::c_int = 1; pub const KF_VTYPE_VDIR: ::c_int = 2; pub const KF_VTYPE_VBLK: ::c_int = 3; pub const KF_VTYPE_VCHR: ::c_int = 4; pub const KF_VTYPE_VLNK: ::c_int = 5; pub const KF_VTYPE_VSOCK: ::c_int = 6; pub const KF_VTYPE_VFIFO: ::c_int = 7; pub const KF_VTYPE_VBAD: ::c_int = 8; pub const KF_VTYPE_UNKNOWN: ::c_int = 255; /// Current working directory pub const KF_FD_TYPE_CWD: ::c_int = -1; /// Root directory pub const KF_FD_TYPE_ROOT: ::c_int = -2; /// Jail directory pub const KF_FD_TYPE_JAIL: ::c_int = -3; /// Ktrace vnode pub const KF_FD_TYPE_TRACE: ::c_int = -4; pub const KF_FD_TYPE_TEXT: ::c_int = -5; /// Controlling terminal pub const KF_FD_TYPE_CTTY: ::c_int = -6; pub const KF_FLAG_READ: ::c_int = 0x00000001; pub const KF_FLAG_WRITE: ::c_int = 0x00000002; pub const KF_FLAG_APPEND: ::c_int = 0x00000004; pub const KF_FLAG_ASYNC: ::c_int = 0x00000008; pub const KF_FLAG_FSYNC: ::c_int = 0x00000010; pub const KF_FLAG_NONBLOCK: ::c_int = 0x00000020; pub const KF_FLAG_DIRECT: ::c_int = 0x00000040; pub const KF_FLAG_HASLOCK: ::c_int = 0x00000080; pub const KF_FLAG_SHLOCK: ::c_int = 0x00000100; pub const KF_FLAG_EXLOCK: ::c_int = 0x00000200; pub const KF_FLAG_NOFOLLOW: ::c_int = 0x00000400; pub const KF_FLAG_CREAT: ::c_int = 0x00000800; pub const KF_FLAG_TRUNC: ::c_int = 0x00001000; pub const KF_FLAG_EXCL: ::c_int = 0x00002000; pub const KF_FLAG_EXEC: ::c_int = 0x00004000; pub const KVME_TYPE_NONE: ::c_int = 0; pub const KVME_TYPE_DEFAULT: ::c_int = 1; pub const KVME_TYPE_VNODE: ::c_int = 2; pub const KVME_TYPE_SWAP: ::c_int = 3; pub const KVME_TYPE_DEVICE: ::c_int = 4; pub const KVME_TYPE_PHYS: ::c_int = 5; pub const KVME_TYPE_DEAD: ::c_int = 6; pub const KVME_TYPE_SG: ::c_int = 7; pub const KVME_TYPE_MGTDEVICE: ::c_int = 8; // Present in `sys/user.h` but is undefined for whatever reason... // pub const KVME_TYPE_GUARD: ::c_int = 9; pub const KVME_TYPE_UNKNOWN: ::c_int = 255; pub const KVME_PROT_READ: ::c_int = 0x00000001; pub const KVME_PROT_WRITE: ::c_int = 0x00000002; pub const KVME_PROT_EXEC: ::c_int = 0x00000004; pub const KVME_FLAG_COW: ::c_int = 0x00000001; pub const KVME_FLAG_NEEDS_COPY: ::c_int = 0x00000002; pub const KVME_FLAG_NOCOREDUMP: ::c_int = 0x00000004; pub const KVME_FLAG_SUPER: ::c_int = 0x00000008; pub const KVME_FLAG_GROWS_UP: ::c_int = 0x00000010; pub const KVME_FLAG_GROWS_DOWN: ::c_int = 0x00000020; pub const KVME_FLAG_USER_WIRED: ::c_int = 0x00000040; pub const KKST_MAXLEN: ::c_int = 1024; /// Stack is valid. pub const KKST_STATE_STACKOK: ::c_int = 0; /// Stack swapped out. pub const KKST_STATE_SWAPPED: ::c_int = 1; pub const KKST_STATE_RUNNING: ::c_int = 2; // Constants about priority. pub const PRI_MIN: ::c_int = 0; pub const PRI_MAX: ::c_int = 255; pub const PRI_MIN_ITHD: ::c_int = PRI_MIN; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRI_MAX_ITHD: ::c_int = PRI_MIN_REALTIME - 1; pub const PI_REALTIME: ::c_int = PRI_MIN_ITHD + 0; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_AV: ::c_int = PRI_MIN_ITHD + 4; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_NET: ::c_int = PRI_MIN_ITHD + 8; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_DISK: ::c_int = PRI_MIN_ITHD + 12; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_TTY: ::c_int = PRI_MIN_ITHD + 16; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_DULL: ::c_int = PRI_MIN_ITHD + 20; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PI_SOFT: ::c_int = PRI_MIN_ITHD + 24; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PRI_MIN_REALTIME: ::c_int = 48; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRI_MAX_REALTIME: ::c_int = PRI_MIN_KERN - 1; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PRI_MIN_KERN: ::c_int = 80; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRI_MAX_KERN: ::c_int = PRI_MIN_TIMESHARE - 1; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PSWP: ::c_int = PRI_MIN_KERN + 0; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PVM: ::c_int = PRI_MIN_KERN + 4; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PINOD: ::c_int = PRI_MIN_KERN + 8; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PRIBIO: ::c_int = PRI_MIN_KERN + 12; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PVFS: ::c_int = PRI_MIN_KERN + 16; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PZERO: ::c_int = PRI_MIN_KERN + 20; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PSOCK: ::c_int = PRI_MIN_KERN + 24; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PWAIT: ::c_int = PRI_MIN_KERN + 28; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PLOCK: ::c_int = PRI_MIN_KERN + 32; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PPAUSE: ::c_int = PRI_MIN_KERN + 36; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const PRI_MIN_TIMESHARE: ::c_int = 120; pub const PRI_MAX_TIMESHARE: ::c_int = PRI_MIN_IDLE - 1; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] #[allow(deprecated)] pub const PUSER: ::c_int = PRI_MIN_TIMESHARE; pub const PRI_MIN_IDLE: ::c_int = 224; pub const PRI_MAX_IDLE: ::c_int = PRI_MAX; pub const NZERO: ::c_int = 0; // Resource utilization information. pub const RUSAGE_THREAD: ::c_int = 1; cfg_if! { if #[cfg(any(freebsd11, target_pointer_width = "32"))] { pub const ARG_MAX: ::c_int = 256 * 1024; } else { pub const ARG_MAX: ::c_int = 2 * 256 * 1024; } } pub const CHILD_MAX: ::c_int = 40; /// max command name remembered pub const MAXCOMLEN: usize = 19; /// max interpreter file name length pub const MAXINTERP: ::c_int = ::PATH_MAX; /// max login name length (incl. NUL) pub const MAXLOGNAME: ::c_int = 33; /// max simultaneous processes pub const MAXUPRC: ::c_int = CHILD_MAX; /// max bytes for an exec function pub const NCARGS: ::c_int = ARG_MAX; /// /* max number groups pub const NGROUPS: ::c_int = NGROUPS_MAX + 1; /// max open files per process pub const NOFILE: ::c_int = OPEN_MAX; /// marker for empty group set member pub const NOGROUP: ::c_int = 65535; /// max hostname size pub const MAXHOSTNAMELEN: ::c_int = 256; /// max bytes in term canon input line pub const MAX_CANON: ::c_int = 255; /// max bytes in terminal input pub const MAX_INPUT: ::c_int = 255; /// max bytes in a file name pub const NAME_MAX: ::c_int = 255; pub const MAXSYMLINKS: ::c_int = 32; /// max supplemental group id's pub const NGROUPS_MAX: ::c_int = 1023; /// max open files per process pub const OPEN_MAX: ::c_int = 64; pub const _POSIX_ARG_MAX: ::c_int = 4096; pub const _POSIX_LINK_MAX: ::c_int = 8; pub const _POSIX_MAX_CANON: ::c_int = 255; pub const _POSIX_MAX_INPUT: ::c_int = 255; pub const _POSIX_NAME_MAX: ::c_int = 14; pub const _POSIX_PIPE_BUF: ::c_int = 512; pub const _POSIX_SSIZE_MAX: ::c_int = 32767; pub const _POSIX_STREAM_MAX: ::c_int = 8; /// max ibase/obase values in bc(1) pub const BC_BASE_MAX: ::c_int = 99; /// max array elements in bc(1) pub const BC_DIM_MAX: ::c_int = 2048; /// max scale value in bc(1) pub const BC_SCALE_MAX: ::c_int = 99; /// max const string length in bc(1) pub const BC_STRING_MAX: ::c_int = 1000; /// max character class name size pub const CHARCLASS_NAME_MAX: ::c_int = 14; /// max weights for order keyword pub const COLL_WEIGHTS_MAX: ::c_int = 10; /// max expressions nested in expr(1) pub const EXPR_NEST_MAX: ::c_int = 32; /// max bytes in an input line pub const LINE_MAX: ::c_int = 2048; /// max RE's in interval notation pub const RE_DUP_MAX: ::c_int = 255; pub const _POSIX2_BC_BASE_MAX: ::c_int = 99; pub const _POSIX2_BC_DIM_MAX: ::c_int = 2048; pub const _POSIX2_BC_SCALE_MAX: ::c_int = 99; pub const _POSIX2_BC_STRING_MAX: ::c_int = 1000; pub const _POSIX2_CHARCLASS_NAME_MAX: ::c_int = 14; pub const _POSIX2_COLL_WEIGHTS_MAX: ::c_int = 2; pub const _POSIX2_EQUIV_CLASS_MAX: ::c_int = 2; pub const _POSIX2_EXPR_NEST_MAX: ::c_int = 32; pub const _POSIX2_LINE_MAX: ::c_int = 2048; pub const _POSIX2_RE_DUP_MAX: ::c_int = 255; // sys/proc.h pub const TDF_BORROWING: ::c_int = 0x00000001; pub const TDF_INPANIC: ::c_int = 0x00000002; pub const TDF_INMEM: ::c_int = 0x00000004; pub const TDF_SINTR: ::c_int = 0x00000008; pub const TDF_TIMEOUT: ::c_int = 0x00000010; pub const TDF_IDLETD: ::c_int = 0x00000020; pub const TDF_CANSWAP: ::c_int = 0x00000040; pub const TDF_KTH_SUSP: ::c_int = 0x00000100; pub const TDF_ALLPROCSUSP: ::c_int = 0x00000200; pub const TDF_BOUNDARY: ::c_int = 0x00000400; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_ASTPENDING: ::c_int = 0x00000800; pub const TDF_SBDRY: ::c_int = 0x00002000; pub const TDF_UPIBLOCKED: ::c_int = 0x00004000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_NEEDSUSPCHK: ::c_int = 0x00008000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_NEEDRESCHED: ::c_int = 0x00010000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_NEEDSIGCHK: ::c_int = 0x00020000; pub const TDF_NOLOAD: ::c_int = 0x00040000; pub const TDF_SERESTART: ::c_int = 0x00080000; pub const TDF_THRWAKEUP: ::c_int = 0x00100000; pub const TDF_SEINTR: ::c_int = 0x00200000; pub const TDF_SWAPINREQ: ::c_int = 0x00400000; #[deprecated(since = "0.2.133", note = "Removed in FreeBSD 14")] pub const TDF_UNUSED23: ::c_int = 0x00800000; pub const TDF_SCHED0: ::c_int = 0x01000000; pub const TDF_SCHED1: ::c_int = 0x02000000; pub const TDF_SCHED2: ::c_int = 0x04000000; pub const TDF_SCHED3: ::c_int = 0x08000000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_ALRMPEND: ::c_int = 0x10000000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_PROFPEND: ::c_int = 0x20000000; #[deprecated(since = "0.2.133", note = "Not stable across OS versions")] pub const TDF_MACPEND: ::c_int = 0x40000000; pub const TDB_SUSPEND: ::c_int = 0x00000001; pub const TDB_XSIG: ::c_int = 0x00000002; pub const TDB_USERWR: ::c_int = 0x00000004; pub const TDB_SCE: ::c_int = 0x00000008; pub const TDB_SCX: ::c_int = 0x00000010; pub const TDB_EXEC: ::c_int = 0x00000020; pub const TDB_FORK: ::c_int = 0x00000040; pub const TDB_STOPATFORK: ::c_int = 0x00000080; pub const TDB_CHILD: ::c_int = 0x00000100; pub const TDB_BORN: ::c_int = 0x00000200; pub const TDB_EXIT: ::c_int = 0x00000400; pub const TDB_VFORK: ::c_int = 0x00000800; pub const TDB_FSTP: ::c_int = 0x00001000; pub const TDB_STEP: ::c_int = 0x00002000; pub const TDP_OLDMASK: ::c_int = 0x00000001; pub const TDP_INKTR: ::c_int = 0x00000002; pub const TDP_INKTRACE: ::c_int = 0x00000004; pub const TDP_BUFNEED: ::c_int = 0x00000008; pub const TDP_COWINPROGRESS: ::c_int = 0x00000010; pub const TDP_ALTSTACK: ::c_int = 0x00000020; pub const TDP_DEADLKTREAT: ::c_int = 0x00000040; pub const TDP_NOFAULTING: ::c_int = 0x00000080; pub const TDP_OWEUPC: ::c_int = 0x00000200; pub const TDP_ITHREAD: ::c_int = 0x00000400; pub const TDP_SYNCIO: ::c_int = 0x00000800; pub const TDP_SCHED1: ::c_int = 0x00001000; pub const TDP_SCHED2: ::c_int = 0x00002000; pub const TDP_SCHED3: ::c_int = 0x00004000; pub const TDP_SCHED4: ::c_int = 0x00008000; pub const TDP_GEOM: ::c_int = 0x00010000; pub const TDP_SOFTDEP: ::c_int = 0x00020000; pub const TDP_NORUNNINGBUF: ::c_int = 0x00040000; pub const TDP_WAKEUP: ::c_int = 0x00080000; pub const TDP_INBDFLUSH: ::c_int = 0x00100000; pub const TDP_KTHREAD: ::c_int = 0x00200000; pub const TDP_CALLCHAIN: ::c_int = 0x00400000; pub const TDP_IGNSUSP: ::c_int = 0x00800000; pub const TDP_AUDITREC: ::c_int = 0x01000000; pub const TDP_RFPPWAIT: ::c_int = 0x02000000; pub const TDP_RESETSPUR: ::c_int = 0x04000000; pub const TDP_NERRNO: ::c_int = 0x08000000; pub const TDP_EXECVMSPC: ::c_int = 0x40000000; pub const TDI_SUSPENDED: ::c_int = 0x0001; pub const TDI_SLEEPING: ::c_int = 0x0002; pub const TDI_SWAPPED: ::c_int = 0x0004; pub const TDI_LOCK: ::c_int = 0x0008; pub const TDI_IWAIT: ::c_int = 0x0010; pub const P_ADVLOCK: ::c_int = 0x00000001; pub const P_CONTROLT: ::c_int = 0x00000002; pub const P_KPROC: ::c_int = 0x00000004; pub const P_UNUSED3: ::c_int = 0x00000008; pub const P_PPWAIT: ::c_int = 0x00000010; pub const P_PROFIL: ::c_int = 0x00000020; pub const P_STOPPROF: ::c_int = 0x00000040; pub const P_HADTHREADS: ::c_int = 0x00000080; pub const P_SUGID: ::c_int = 0x00000100; pub const P_SYSTEM: ::c_int = 0x00000200; pub const P_SINGLE_EXIT: ::c_int = 0x00000400; pub const P_TRACED: ::c_int = 0x00000800; pub const P_WAITED: ::c_int = 0x00001000; pub const P_WEXIT: ::c_int = 0x00002000; pub const P_EXEC: ::c_int = 0x00004000; pub const P_WKILLED: ::c_int = 0x00008000; pub const P_CONTINUED: ::c_int = 0x00010000; pub const P_STOPPED_SIG: ::c_int = 0x00020000; pub const P_STOPPED_TRACE: ::c_int = 0x00040000; pub const P_STOPPED_SINGLE: ::c_int = 0x00080000; pub const P_PROTECTED: ::c_int = 0x00100000; pub const P_SIGEVENT: ::c_int = 0x00200000; pub const P_SINGLE_BOUNDARY: ::c_int = 0x00400000; pub const P_HWPMC: ::c_int = 0x00800000; pub const P_JAILED: ::c_int = 0x01000000; pub const P_TOTAL_STOP: ::c_int = 0x02000000; pub const P_INEXEC: ::c_int = 0x04000000; pub const P_STATCHILD: ::c_int = 0x08000000; pub const P_INMEM: ::c_int = 0x10000000; pub const P_SWAPPINGOUT: ::c_int = 0x20000000; pub const P_SWAPPINGIN: ::c_int = 0x40000000; pub const P_PPTRACE: ::c_int = 0x80000000; pub const P_STOPPED: ::c_int = P_STOPPED_SIG | P_STOPPED_SINGLE | P_STOPPED_TRACE; pub const P2_INHERIT_PROTECTED: ::c_int = 0x00000001; pub const P2_NOTRACE: ::c_int = 0x00000002; pub const P2_NOTRACE_EXEC: ::c_int = 0x00000004; pub const P2_AST_SU: ::c_int = 0x00000008; pub const P2_PTRACE_FSTP: ::c_int = 0x00000010; pub const P2_TRAPCAP: ::c_int = 0x00000020; pub const P2_STKGAP_DISABLE: ::c_int = 0x00000800; pub const P2_STKGAP_DISABLE_EXEC: ::c_int = 0x00001000; pub const P_TREE_ORPHANED: ::c_int = 0x00000001; pub const P_TREE_FIRST_ORPHAN: ::c_int = 0x00000002; pub const P_TREE_REAPER: ::c_int = 0x00000004; pub const SIDL: ::c_char = 1; pub const SRUN: ::c_char = 2; pub const SSLEEP: ::c_char = 3; pub const SSTOP: ::c_char = 4; pub const SZOMB: ::c_char = 5; pub const SWAIT: ::c_char = 6; pub const SLOCK: ::c_char = 7; pub const P_MAGIC: ::c_int = 0xbeefface; pub const TDP_SIGFASTBLOCK: ::c_int = 0x00000100; pub const TDP_UIOHELD: ::c_int = 0x10000000; pub const TDP_SIGFASTPENDING: ::c_int = 0x80000000; pub const TDP2_COMPAT32RB: ::c_int = 0x00000002; pub const P2_PROTMAX_ENABLE: ::c_int = 0x00000200; pub const P2_PROTMAX_DISABLE: ::c_int = 0x00000400; pub const TDP2_SBPAGES: ::c_int = 0x00000001; pub const P2_ASLR_ENABLE: ::c_int = 0x00000040; pub const P2_ASLR_DISABLE: ::c_int = 0x00000080; pub const P2_ASLR_IGNSTART: ::c_int = 0x00000100; pub const P_TREE_GRPEXITED: ::c_int = 0x00000008; // libprocstat.h pub const PS_FST_VTYPE_VNON: ::c_int = 1; pub const PS_FST_VTYPE_VREG: ::c_int = 2; pub const PS_FST_VTYPE_VDIR: ::c_int = 3; pub const PS_FST_VTYPE_VBLK: ::c_int = 4; pub const PS_FST_VTYPE_VCHR: ::c_int = 5; pub const PS_FST_VTYPE_VLNK: ::c_int = 6; pub const PS_FST_VTYPE_VSOCK: ::c_int = 7; pub const PS_FST_VTYPE_VFIFO: ::c_int = 8; pub const PS_FST_VTYPE_VBAD: ::c_int = 9; pub const PS_FST_VTYPE_UNKNOWN: ::c_int = 255; pub const PS_FST_TYPE_VNODE: ::c_int = 1; pub const PS_FST_TYPE_FIFO: ::c_int = 2; pub const PS_FST_TYPE_SOCKET: ::c_int = 3; pub const PS_FST_TYPE_PIPE: ::c_int = 4; pub const PS_FST_TYPE_PTS: ::c_int = 5; pub const PS_FST_TYPE_KQUEUE: ::c_int = 6; pub const PS_FST_TYPE_MQUEUE: ::c_int = 8; pub const PS_FST_TYPE_SHM: ::c_int = 9; pub const PS_FST_TYPE_SEM: ::c_int = 10; pub const PS_FST_TYPE_UNKNOWN: ::c_int = 11; pub const PS_FST_TYPE_NONE: ::c_int = 12; pub const PS_FST_TYPE_PROCDESC: ::c_int = 13; pub const PS_FST_TYPE_DEV: ::c_int = 14; pub const PS_FST_TYPE_EVENTFD: ::c_int = 15; pub const PS_FST_UFLAG_RDIR: ::c_int = 0x0001; pub const PS_FST_UFLAG_CDIR: ::c_int = 0x0002; pub const PS_FST_UFLAG_JAIL: ::c_int = 0x0004; pub const PS_FST_UFLAG_TRACE: ::c_int = 0x0008; pub const PS_FST_UFLAG_TEXT: ::c_int = 0x0010; pub const PS_FST_UFLAG_MMAP: ::c_int = 0x0020; pub const PS_FST_UFLAG_CTTY: ::c_int = 0x0040; pub const PS_FST_FFLAG_READ: ::c_int = 0x0001; pub const PS_FST_FFLAG_WRITE: ::c_int = 0x0002; pub const PS_FST_FFLAG_NONBLOCK: ::c_int = 0x0004; pub const PS_FST_FFLAG_APPEND: ::c_int = 0x0008; pub const PS_FST_FFLAG_SHLOCK: ::c_int = 0x0010; pub const PS_FST_FFLAG_EXLOCK: ::c_int = 0x0020; pub const PS_FST_FFLAG_ASYNC: ::c_int = 0x0040; pub const PS_FST_FFLAG_SYNC: ::c_int = 0x0080; pub const PS_FST_FFLAG_NOFOLLOW: ::c_int = 0x0100; pub const PS_FST_FFLAG_CREAT: ::c_int = 0x0200; pub const PS_FST_FFLAG_TRUNC: ::c_int = 0x0400; pub const PS_FST_FFLAG_EXCL: ::c_int = 0x0800; pub const PS_FST_FFLAG_DIRECT: ::c_int = 0x1000; pub const PS_FST_FFLAG_EXEC: ::c_int = 0x2000; pub const PS_FST_FFLAG_HASLOCK: ::c_int = 0x4000; // sys/mount.h /// File identifier. /// These are unique per filesystem on a single machine. /// /// Note that the offset of fid_data is 4 bytes, so care must be taken to avoid /// undefined behavior accessing unaligned fields within an embedded struct. pub const MAXFIDSZ: ::c_int = 16; /// Length of type name including null. pub const MFSNAMELEN: ::c_int = 16; cfg_if! { if #[cfg(any(freebsd10, freebsd11))] { /// Size of on/from name bufs. pub const MNAMELEN: ::c_int = 88; } else { /// Size of on/from name bufs. pub const MNAMELEN: ::c_int = 1024; } } /// Using journaled soft updates. pub const MNT_SUJ: u64 = 0x100000000; /// Mounted by automountd(8). pub const MNT_AUTOMOUNTED: u64 = 0x200000000; /// Filesys metadata untrusted. pub const MNT_UNTRUSTED: u64 = 0x800000000; /// Require TLS. pub const MNT_EXTLS: u64 = 0x4000000000; /// Require TLS with client cert. pub const MNT_EXTLSCERT: u64 = 0x8000000000; /// Require TLS with user cert. pub const MNT_EXTLSCERTUSER: u64 = 0x10000000000; /// Filesystem is stored locally. pub const MNT_LOCAL: u64 = 0x000001000; /// Quotas are enabled on fs. pub const MNT_QUOTA: u64 = 0x000002000; /// Identifies the root fs. pub const MNT_ROOTFS: u64 = 0x000004000; /// Mounted by a user. pub const MNT_USER: u64 = 0x000008000; /// Do not show entry in df. pub const MNT_IGNORE: u64 = 0x000800000; /// Filesystem is verified. pub const MNT_VERIFIED: u64 = 0x400000000; /// Do not cover a mount point. pub const MNT_NOCOVER: u64 = 0x001000000000; /// Only mount on empty dir. pub const MNT_EMPTYDIR: u64 = 0x002000000000; /// Recursively unmount uppers. pub const MNT_RECURSE: u64 = 0x100000000000; /// Unmount in async context. pub const MNT_DEFERRED: u64 = 0x200000000000; /// Get configured filesystems. pub const VFS_VFSCONF: ::c_int = 0; /// Generic filesystem information. pub const VFS_GENERIC: ::c_int = 0; /// int: highest defined filesystem type. pub const VFS_MAXTYPENUM: ::c_int = 1; /// struct: vfsconf for filesystem given as next argument. pub const VFS_CONF: ::c_int = 2; /// Synchronously wait for I/O to complete. pub const MNT_WAIT: ::c_int = 1; /// Start all I/O, but do not wait for it. pub const MNT_NOWAIT: ::c_int = 2; /// Push data not written by filesystem syncer. pub const MNT_LAZY: ::c_int = 3; /// Suspend file system after sync. pub const MNT_SUSPEND: ::c_int = 4; pub const MAXSECFLAVORS: ::c_int = 5; /// Statically compiled into kernel. pub const VFCF_STATIC: ::c_int = 0x00010000; /// May get data over the network. pub const VFCF_NETWORK: ::c_int = 0x00020000; /// Writes are not implemented. pub const VFCF_READONLY: ::c_int = 0x00040000; /// Data does not represent real files. pub const VFCF_SYNTHETIC: ::c_int = 0x00080000; /// Aliases some other mounted FS. pub const VFCF_LOOPBACK: ::c_int = 0x00100000; /// Stores file names as Unicode. pub const VFCF_UNICODE: ::c_int = 0x00200000; /// Can be mounted from within a jail. pub const VFCF_JAIL: ::c_int = 0x00400000; /// Supports delegated administration. pub const VFCF_DELEGADMIN: ::c_int = 0x00800000; /// Stop at Boundary: defer stop requests to kernel->user (AST) transition. pub const VFCF_SBDRY: ::c_int = 0x01000000; // time.h /// not on dst pub const DST_NONE: ::c_int = 0; /// USA style dst pub const DST_USA: ::c_int = 1; /// Australian style dst pub const DST_AUST: ::c_int = 2; /// Western European dst pub const DST_WET: ::c_int = 3; /// Middle European dst pub const DST_MET: ::c_int = 4; /// Eastern European dst pub const DST_EET: ::c_int = 5; /// Canada pub const DST_CAN: ::c_int = 6; pub const CPUCLOCK_WHICH_PID: ::c_int = 0; pub const CPUCLOCK_WHICH_TID: ::c_int = 1; pub const MFD_CLOEXEC: ::c_uint = 0x00000001; pub const MFD_ALLOW_SEALING: ::c_uint = 0x00000002; pub const MFD_HUGETLB: ::c_uint = 0x00000004; pub const MFD_HUGE_MASK: ::c_uint = 0xFC000000; pub const MFD_HUGE_64KB: ::c_uint = 16 << 26; pub const MFD_HUGE_512KB: ::c_uint = 19 << 26; pub const MFD_HUGE_1MB: ::c_uint = 20 << 26; pub const MFD_HUGE_2MB: ::c_uint = 21 << 26; pub const MFD_HUGE_8MB: ::c_uint = 23 << 26; pub const MFD_HUGE_16MB: ::c_uint = 24 << 26; pub const MFD_HUGE_32MB: ::c_uint = 25 << 26; pub const MFD_HUGE_256MB: ::c_uint = 28 << 26; pub const MFD_HUGE_512MB: ::c_uint = 29 << 26; pub const MFD_HUGE_1GB: ::c_uint = 30 << 26; pub const MFD_HUGE_2GB: ::c_uint = 31 << 26; pub const MFD_HUGE_16GB: ::c_uint = 34 << 26; pub const SHM_LARGEPAGE_ALLOC_DEFAULT: ::c_int = 0; pub const SHM_LARGEPAGE_ALLOC_NOWAIT: ::c_int = 1; pub const SHM_LARGEPAGE_ALLOC_HARD: ::c_int = 2; pub const SHM_RENAME_NOREPLACE: ::c_int = 1 << 0; pub const SHM_RENAME_EXCHANGE: ::c_int = 1 << 1; // sys/umtx.h pub const UMTX_OP_WAIT: ::c_int = 2; pub const UMTX_OP_WAKE: ::c_int = 3; pub const UMTX_OP_MUTEX_TRYLOCK: ::c_int = 4; pub const UMTX_OP_MUTEX_LOCK: ::c_int = 5; pub const UMTX_OP_MUTEX_UNLOCK: ::c_int = 6; pub const UMTX_OP_SET_CEILING: ::c_int = 7; pub const UMTX_OP_CV_WAIT: ::c_int = 8; pub const UMTX_OP_CV_SIGNAL: ::c_int = 9; pub const UMTX_OP_CV_BROADCAST: ::c_int = 10; pub const UMTX_OP_WAIT_UINT: ::c_int = 11; pub const UMTX_OP_RW_RDLOCK: ::c_int = 12; pub const UMTX_OP_RW_WRLOCK: ::c_int = 13; pub const UMTX_OP_RW_UNLOCK: ::c_int = 14; pub const UMTX_OP_WAIT_UINT_PRIVATE: ::c_int = 15; pub const UMTX_OP_WAKE_PRIVATE: ::c_int = 16; pub const UMTX_OP_MUTEX_WAIT: ::c_int = 17; pub const UMTX_OP_NWAKE_PRIVATE: ::c_int = 21; pub const UMTX_OP_MUTEX_WAKE2: ::c_int = 22; pub const UMTX_OP_SEM2_WAIT: ::c_int = 23; pub const UMTX_OP_SEM2_WAKE: ::c_int = 24; pub const UMTX_OP_SHM: ::c_int = 25; pub const UMTX_OP_ROBUST_LISTS: ::c_int = 26; pub const UMTX_ABSTIME: u32 = 1; pub const CPU_LEVEL_ROOT: ::c_int = 1; pub const CPU_LEVEL_CPUSET: ::c_int = 2; pub const CPU_LEVEL_WHICH: ::c_int = 3; pub const CPU_WHICH_TID: ::c_int = 1; pub const CPU_WHICH_PID: ::c_int = 2; pub const CPU_WHICH_CPUSET: ::c_int = 3; pub const CPU_WHICH_IRQ: ::c_int = 4; pub const CPU_WHICH_JAIL: ::c_int = 5; // sys/signal.h pub const SIGTHR: ::c_int = 32; pub const SIGLWP: ::c_int = SIGTHR; pub const SIGLIBRT: ::c_int = 33; // netinet/sctp.h pub const SCTP_FUTURE_ASSOC: ::c_int = 0; pub const SCTP_CURRENT_ASSOC: ::c_int = 1; pub const SCTP_ALL_ASSOC: ::c_int = 2; pub const SCTP_NO_NEXT_MSG: ::c_int = 0x0000; pub const SCTP_NEXT_MSG_AVAIL: ::c_int = 0x0001; pub const SCTP_NEXT_MSG_ISCOMPLETE: ::c_int = 0x0002; pub const SCTP_NEXT_MSG_IS_UNORDERED: ::c_int = 0x0004; pub const SCTP_NEXT_MSG_IS_NOTIFICATION: ::c_int = 0x0008; pub const SCTP_RECVV_NOINFO: ::c_int = 0; pub const SCTP_RECVV_RCVINFO: ::c_int = 1; pub const SCTP_RECVV_NXTINFO: ::c_int = 2; pub const SCTP_RECVV_RN: ::c_int = 3; pub const SCTP_SENDV_NOINFO: ::c_int = 0; pub const SCTP_SENDV_SNDINFO: ::c_int = 1; pub const SCTP_SENDV_PRINFO: ::c_int = 2; pub const SCTP_SENDV_AUTHINFO: ::c_int = 3; pub const SCTP_SENDV_SPA: ::c_int = 4; pub const SCTP_SEND_SNDINFO_VALID: ::c_int = 0x00000001; pub const SCTP_SEND_PRINFO_VALID: ::c_int = 0x00000002; pub const SCTP_SEND_AUTHINFO_VALID: ::c_int = 0x00000004; pub const SCTP_NOTIFICATION: ::c_int = 0x0010; pub const SCTP_COMPLETE: ::c_int = 0x0020; pub const SCTP_EOF: ::c_int = 0x0100; pub const SCTP_ABORT: ::c_int = 0x0200; pub const SCTP_UNORDERED: ::c_int = 0x0400; pub const SCTP_ADDR_OVER: ::c_int = 0x0800; pub const SCTP_SENDALL: ::c_int = 0x1000; pub const SCTP_EOR: ::c_int = 0x2000; pub const SCTP_SACK_IMMEDIATELY: ::c_int = 0x4000; pub const SCTP_PR_SCTP_NONE: ::c_int = 0x0000; pub const SCTP_PR_SCTP_TTL: ::c_int = 0x0001; pub const SCTP_PR_SCTP_PRIO: ::c_int = 0x0002; pub const SCTP_PR_SCTP_BUF: ::c_int = SCTP_PR_SCTP_PRIO; pub const SCTP_PR_SCTP_RTX: ::c_int = 0x0003; pub const SCTP_PR_SCTP_MAX: ::c_int = SCTP_PR_SCTP_RTX; pub const SCTP_PR_SCTP_ALL: ::c_int = 0x000f; pub const SCTP_INIT: ::c_int = 0x0001; pub const SCTP_SNDRCV: ::c_int = 0x0002; pub const SCTP_EXTRCV: ::c_int = 0x0003; pub const SCTP_SNDINFO: ::c_int = 0x0004; pub const SCTP_RCVINFO: ::c_int = 0x0005; pub const SCTP_NXTINFO: ::c_int = 0x0006; pub const SCTP_PRINFO: ::c_int = 0x0007; pub const SCTP_AUTHINFO: ::c_int = 0x0008; pub const SCTP_DSTADDRV4: ::c_int = 0x0009; pub const SCTP_DSTADDRV6: ::c_int = 0x000a; pub const SCTP_RTOINFO: ::c_int = 0x00000001; pub const SCTP_ASSOCINFO: ::c_int = 0x00000002; pub const SCTP_INITMSG: ::c_int = 0x00000003; pub const SCTP_NODELAY: ::c_int = 0x00000004; pub const SCTP_AUTOCLOSE: ::c_int = 0x00000005; pub const SCTP_SET_PEER_PRIMARY_ADDR: ::c_int = 0x00000006; pub const SCTP_PRIMARY_ADDR: ::c_int = 0x00000007; pub const SCTP_ADAPTATION_LAYER: ::c_int = 0x00000008; pub const SCTP_ADAPTION_LAYER: ::c_int = 0x00000008; pub const SCTP_DISABLE_FRAGMENTS: ::c_int = 0x00000009; pub const SCTP_PEER_ADDR_PARAMS: ::c_int = 0x0000000a; pub const SCTP_DEFAULT_SEND_PARAM: ::c_int = 0x0000000b; pub const SCTP_EVENTS: ::c_int = 0x0000000c; pub const SCTP_I_WANT_MAPPED_V4_ADDR: ::c_int = 0x0000000d; pub const SCTP_MAXSEG: ::c_int = 0x0000000e; pub const SCTP_DELAYED_SACK: ::c_int = 0x0000000f; pub const SCTP_FRAGMENT_INTERLEAVE: ::c_int = 0x00000010; pub const SCTP_PARTIAL_DELIVERY_POINT: ::c_int = 0x00000011; pub const SCTP_AUTH_CHUNK: ::c_int = 0x00000012; pub const SCTP_AUTH_KEY: ::c_int = 0x00000013; pub const SCTP_HMAC_IDENT: ::c_int = 0x00000014; pub const SCTP_AUTH_ACTIVE_KEY: ::c_int = 0x00000015; pub const SCTP_AUTH_DELETE_KEY: ::c_int = 0x00000016; pub const SCTP_USE_EXT_RCVINFO: ::c_int = 0x00000017; pub const SCTP_AUTO_ASCONF: ::c_int = 0x00000018; pub const SCTP_MAXBURST: ::c_int = 0x00000019; pub const SCTP_MAX_BURST: ::c_int = 0x00000019; pub const SCTP_CONTEXT: ::c_int = 0x0000001a; pub const SCTP_EXPLICIT_EOR: ::c_int = 0x00000001b; pub const SCTP_REUSE_PORT: ::c_int = 0x00000001c; pub const SCTP_AUTH_DEACTIVATE_KEY: ::c_int = 0x00000001d; pub const SCTP_EVENT: ::c_int = 0x0000001e; pub const SCTP_RECVRCVINFO: ::c_int = 0x0000001f; pub const SCTP_RECVNXTINFO: ::c_int = 0x00000020; pub const SCTP_DEFAULT_SNDINFO: ::c_int = 0x00000021; pub const SCTP_DEFAULT_PRINFO: ::c_int = 0x00000022; pub const SCTP_PEER_ADDR_THLDS: ::c_int = 0x00000023; pub const SCTP_REMOTE_UDP_ENCAPS_PORT: ::c_int = 0x00000024; pub const SCTP_ECN_SUPPORTED: ::c_int = 0x00000025; pub const SCTP_AUTH_SUPPORTED: ::c_int = 0x00000027; pub const SCTP_ASCONF_SUPPORTED: ::c_int = 0x00000028; pub const SCTP_RECONFIG_SUPPORTED: ::c_int = 0x00000029; pub const SCTP_NRSACK_SUPPORTED: ::c_int = 0x00000030; pub const SCTP_PKTDROP_SUPPORTED: ::c_int = 0x00000031; pub const SCTP_MAX_CWND: ::c_int = 0x00000032; pub const SCTP_STATUS: ::c_int = 0x00000100; pub const SCTP_GET_PEER_ADDR_INFO: ::c_int = 0x00000101; pub const SCTP_PEER_AUTH_CHUNKS: ::c_int = 0x00000102; pub const SCTP_LOCAL_AUTH_CHUNKS: ::c_int = 0x00000103; pub const SCTP_GET_ASSOC_NUMBER: ::c_int = 0x00000104; pub const SCTP_GET_ASSOC_ID_LIST: ::c_int = 0x00000105; pub const SCTP_TIMEOUTS: ::c_int = 0x00000106; pub const SCTP_PR_STREAM_STATUS: ::c_int = 0x00000107; pub const SCTP_PR_ASSOC_STATUS: ::c_int = 0x00000108; pub const SCTP_COMM_UP: ::c_int = 0x0001; pub const SCTP_COMM_LOST: ::c_int = 0x0002; pub const SCTP_RESTART: ::c_int = 0x0003; pub const SCTP_SHUTDOWN_COMP: ::c_int = 0x0004; pub const SCTP_CANT_STR_ASSOC: ::c_int = 0x0005; pub const SCTP_ASSOC_SUPPORTS_PR: ::c_int = 0x01; pub const SCTP_ASSOC_SUPPORTS_AUTH: ::c_int = 0x02; pub const SCTP_ASSOC_SUPPORTS_ASCONF: ::c_int = 0x03; pub const SCTP_ASSOC_SUPPORTS_MULTIBUF: ::c_int = 0x04; pub const SCTP_ASSOC_SUPPORTS_RE_CONFIG: ::c_int = 0x05; pub const SCTP_ASSOC_SUPPORTS_INTERLEAVING: ::c_int = 0x06; pub const SCTP_ASSOC_SUPPORTS_MAX: ::c_int = 0x06; pub const SCTP_ADDR_AVAILABLE: ::c_int = 0x0001; pub const SCTP_ADDR_UNREACHABLE: ::c_int = 0x0002; pub const SCTP_ADDR_REMOVED: ::c_int = 0x0003; pub const SCTP_ADDR_ADDED: ::c_int = 0x0004; pub const SCTP_ADDR_MADE_PRIM: ::c_int = 0x0005; pub const SCTP_ADDR_CONFIRMED: ::c_int = 0x0006; pub const SCTP_ACTIVE: ::c_int = 0x0001; pub const SCTP_INACTIVE: ::c_int = 0x0002; pub const SCTP_UNCONFIRMED: ::c_int = 0x0200; pub const SCTP_DATA_UNSENT: ::c_int = 0x0001; pub const SCTP_DATA_SENT: ::c_int = 0x0002; pub const SCTP_PARTIAL_DELIVERY_ABORTED: ::c_int = 0x0001; pub const SCTP_AUTH_NEW_KEY: ::c_int = 0x0001; pub const SCTP_AUTH_NEWKEY: ::c_int = SCTP_AUTH_NEW_KEY; pub const SCTP_AUTH_NO_AUTH: ::c_int = 0x0002; pub const SCTP_AUTH_FREE_KEY: ::c_int = 0x0003; pub const SCTP_STREAM_RESET_INCOMING_SSN: ::c_int = 0x0001; pub const SCTP_STREAM_RESET_OUTGOING_SSN: ::c_int = 0x0002; pub const SCTP_STREAM_RESET_DENIED: ::c_int = 0x0004; pub const SCTP_STREAM_RESET_FAILED: ::c_int = 0x0008; pub const SCTP_ASSOC_RESET_DENIED: ::c_int = 0x0004; pub const SCTP_ASSOC_RESET_FAILED: ::c_int = 0x0008; pub const SCTP_STREAM_CHANGE_DENIED: ::c_int = 0x0004; pub const SCTP_STREAM_CHANGE_FAILED: ::c_int = 0x0008; pub const KENV_DUMP_LOADER: ::c_int = 4; pub const KENV_DUMP_STATIC: ::c_int = 5; pub const RB_PAUSE: ::c_int = 0x100000; pub const RB_REROOT: ::c_int = 0x200000; pub const RB_POWERCYCLE: ::c_int = 0x400000; pub const RB_PROBE: ::c_int = 0x10000000; pub const RB_MULTIPLE: ::c_int = 0x20000000; // sys/time.h pub const CLOCK_BOOTTIME: ::clockid_t = ::CLOCK_UPTIME; pub const CLOCK_REALTIME_COARSE: ::clockid_t = ::CLOCK_REALTIME_FAST; pub const CLOCK_MONOTONIC_COARSE: ::clockid_t = ::CLOCK_MONOTONIC_FAST; // sys/timerfd.h pub const TFD_NONBLOCK: ::c_int = ::O_NONBLOCK; pub const TFD_CLOEXEC: ::c_int = O_CLOEXEC; pub const TFD_TIMER_ABSTIME: ::c_int = 0x01; pub const TFD_TIMER_CANCEL_ON_SET: ::c_int = 0x02; cfg_if! { if #[cfg(libc_const_extern_fn)] { pub const fn MAP_ALIGNED(a: ::c_int) -> ::c_int { a << 24 } } else { pub fn MAP_ALIGNED(a: ::c_int) -> ::c_int { a << 24 } } } const_fn! { {const} fn _ALIGN(p: usize) -> usize { (p + _ALIGNBYTES) & !_ALIGNBYTES } } f! { pub fn CMSG_DATA(cmsg: *const ::cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { _ALIGN(::mem::size_of::<::cmsghdr>()) as ::c_uint + length } pub fn CMSG_NXTHDR(mhdr: *const ::msghdr, cmsg: *const ::cmsghdr) -> *mut ::cmsghdr { if cmsg.is_null() { return ::CMSG_FIRSTHDR(mhdr); }; let next = cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize) + _ALIGN(::mem::size_of::<::cmsghdr>()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next > max { 0 as *mut ::cmsghdr } else { (cmsg as usize + _ALIGN((*cmsg).cmsg_len as usize)) as *mut ::cmsghdr } } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (_ALIGN(::mem::size_of::<::cmsghdr>()) + _ALIGN(length as usize)) as ::c_uint } pub fn MALLOCX_ALIGN(lg: ::c_uint) -> ::c_int { ffsl(lg as ::c_long - 1) } pub {const} fn MALLOCX_TCACHE(tc: ::c_int) -> ::c_int { (tc + 2) << 8 as ::c_int } pub {const} fn MALLOCX_ARENA(a: ::c_int) -> ::c_int { (a + 1) << 20 as ::c_int } pub fn SOCKCREDSIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; ::mem::size_of::() + ::mem::size_of::<::gid_t>() * ngrps } pub fn uname(buf: *mut ::utsname) -> ::c_int { __xuname(256, buf as *mut ::c_void) } pub fn CPU_ZERO(cpuset: &mut cpuset_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = 0; } } pub fn CPU_FILL(cpuset: &mut cpuset_t) -> () { for slot in cpuset.__bits.iter_mut() { *slot = !0; } } pub fn CPU_SET(cpu: usize, cpuset: &mut cpuset_t) -> () { let bitset_bits = 8 * ::mem::size_of::<::c_long>(); let (idx, offset) = (cpu / bitset_bits, cpu % bitset_bits); cpuset.__bits[idx] |= 1 << offset; () } pub fn CPU_CLR(cpu: usize, cpuset: &mut cpuset_t) -> () { let bitset_bits = 8 * ::mem::size_of::<::c_long>(); let (idx, offset) = (cpu / bitset_bits, cpu % bitset_bits); cpuset.__bits[idx] &= !(1 << offset); () } pub fn CPU_ISSET(cpu: usize, cpuset: &cpuset_t) -> bool { let bitset_bits = 8 * ::mem::size_of::<::c_long>(); let (idx, offset) = (cpu / bitset_bits, cpu % bitset_bits); 0 != cpuset.__bits[idx] & (1 << offset) } pub fn CPU_COUNT(cpuset: &cpuset_t) -> ::c_int { let mut s: u32 = 0; let cpuset_size = ::mem::size_of::(); let bitset_size = ::mem::size_of::<::c_long>(); for i in cpuset.__bits[..(cpuset_size / bitset_size)].iter() { s += i.count_ones(); }; s as ::c_int } pub fn SOCKCRED2SIZE(ngrps: usize) -> usize { let ngrps = if ngrps > 0 { ngrps - 1 } else { 0 }; ::mem::size_of::() + ::mem::size_of::<::gid_t>() * ngrps } pub fn PROT_MAX(x: ::c_int) -> ::c_int { x << 16 } pub fn PROT_MAX_EXTRACT(x: ::c_int) -> ::c_int { (x >> 16) & (::PROT_READ | ::PROT_WRITE | ::PROT_EXEC) } } safe_f! { pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { (status & 0o177) != 0o177 && (status & 0o177) != 0 && status != 0x13 } pub {const} fn INVALID_SINFO_FLAG(x: ::c_int) -> bool { (x) & 0xfffffff0 & !(SCTP_EOF | SCTP_ABORT | SCTP_UNORDERED | SCTP_ADDR_OVER | SCTP_SENDALL | SCTP_EOR | SCTP_SACK_IMMEDIATELY) != 0 } pub {const} fn PR_SCTP_POLICY(x: ::c_int) -> ::c_int { x & 0x0f } pub {const} fn PR_SCTP_ENABLED(x: ::c_int) -> bool { PR_SCTP_POLICY(x) != SCTP_PR_SCTP_NONE && PR_SCTP_POLICY(x) != SCTP_PR_SCTP_ALL } pub {const} fn PR_SCTP_TTL_ENABLED(x: ::c_int) -> bool { PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL } pub {const} fn PR_SCTP_BUF_ENABLED(x: ::c_int) -> bool { PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF } pub {const} fn PR_SCTP_RTX_ENABLED(x: ::c_int) -> bool { PR_SCTP_POLICY(x) == SCTP_PR_SCTP_RTX } pub {const} fn PR_SCTP_INVALID_POLICY(x: ::c_int) -> bool { PR_SCTP_POLICY(x) > SCTP_PR_SCTP_MAX } pub {const} fn PR_SCTP_VALID_POLICY(x: ::c_int) -> bool { PR_SCTP_POLICY(x) <= SCTP_PR_SCTP_MAX } } cfg_if! { if #[cfg(not(any(freebsd10, freebsd11)))] { extern "C" { pub fn fhlink(fhp: *mut fhandle_t, to: *const ::c_char) -> ::c_int; pub fn fhlinkat(fhp: *mut fhandle_t, tofd: ::c_int, to: *const ::c_char) -> ::c_int; pub fn fhreadlink( fhp: *mut fhandle_t, buf: *mut ::c_char, bufsize: ::size_t, ) -> ::c_int; pub fn getfhat( fd: ::c_int, path: *mut ::c_char, fhp: *mut fhandle, flag: ::c_int, ) -> ::c_int; } } } extern "C" { #[cfg_attr(doc, doc(alias = "__errno_location"))] #[cfg_attr(doc, doc(alias = "errno"))] pub fn __error() -> *mut ::c_int; pub fn aio_cancel(fd: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_error(aiocbp: *const aiocb) -> ::c_int; pub fn aio_fsync(op: ::c_int, aiocbp: *mut aiocb) -> ::c_int; pub fn aio_read(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_readv(aiocbp: *mut ::aiocb) -> ::c_int; pub fn aio_return(aiocbp: *mut aiocb) -> ::ssize_t; pub fn aio_suspend( aiocb_list: *const *const aiocb, nitems: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn aio_write(aiocbp: *mut aiocb) -> ::c_int; pub fn aio_writev(aiocbp: *mut ::aiocb) -> ::c_int; pub fn copy_file_range( infd: ::c_int, inoffp: *mut ::off_t, outfd: ::c_int, outoffp: *mut ::off_t, len: ::size_t, flags: ::c_uint, ) -> ::ssize_t; pub fn devname_r( dev: ::dev_t, mode: ::mode_t, buf: *mut ::c_char, len: ::c_int, ) -> *mut ::c_char; pub fn extattr_delete_fd( fd: ::c_int, attrnamespace: ::c_int, attrname: *const ::c_char, ) -> ::c_int; pub fn extattr_delete_file( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, ) -> ::c_int; pub fn extattr_delete_link( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, ) -> ::c_int; pub fn extattr_get_fd( fd: ::c_int, attrnamespace: ::c_int, attrname: *const ::c_char, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_get_file( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_get_link( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_list_fd( fd: ::c_int, attrnamespace: ::c_int, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_list_file( path: *const ::c_char, attrnamespace: ::c_int, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_list_link( path: *const ::c_char, attrnamespace: ::c_int, data: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_set_fd( fd: ::c_int, attrnamespace: ::c_int, attrname: *const ::c_char, data: *const ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_set_file( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *const ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn extattr_set_link( path: *const ::c_char, attrnamespace: ::c_int, attrname: *const ::c_char, data: *const ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn fspacectl( fd: ::c_int, cmd: ::c_int, rqsr: *const spacectl_range, flags: ::c_int, rmsr: *mut spacectl_range, ) -> ::c_int; pub fn jail(jail: *mut ::jail) -> ::c_int; pub fn jail_attach(jid: ::c_int) -> ::c_int; pub fn jail_remove(jid: ::c_int) -> ::c_int; pub fn jail_get(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int) -> ::c_int; pub fn jail_set(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int) -> ::c_int; pub fn lio_listio( mode: ::c_int, aiocb_list: *const *mut aiocb, nitems: ::c_int, sevp: *mut sigevent, ) -> ::c_int; pub fn mkostemp(template: *mut ::c_char, flags: ::c_int) -> ::c_int; pub fn mkostemps(template: *mut ::c_char, suffixlen: ::c_int, flags: ::c_int) -> ::c_int; pub fn getutxuser(user: *const ::c_char) -> *mut utmpx; pub fn setutxdb(_type: ::c_int, file: *const ::c_char) -> ::c_int; pub fn aio_waitcomplete(iocbp: *mut *mut aiocb, timeout: *mut ::timespec) -> ::ssize_t; pub fn mq_getfd_np(mqd: ::mqd_t) -> ::c_int; pub fn waitid( idtype: idtype_t, id: ::id_t, infop: *mut ::siginfo_t, options: ::c_int, ) -> ::c_int; pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int; pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t; pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int; pub fn shmat(shmid: ::c_int, shmaddr: *const ::c_void, shmflg: ::c_int) -> *mut ::c_void; pub fn shmdt(shmaddr: *const ::c_void) -> ::c_int; pub fn shmctl(shmid: ::c_int, cmd: ::c_int, buf: *mut ::shmid_ds) -> ::c_int; pub fn semget(key: ::key_t, nsems: ::c_int, semflg: ::c_int) -> ::c_int; pub fn semctl(semid: ::c_int, semnum: ::c_int, cmd: ::c_int, ...) -> ::c_int; pub fn semop(semid: ::c_int, sops: *mut sembuf, nsops: ::size_t) -> ::c_int; pub fn msgctl(msqid: ::c_int, cmd: ::c_int, buf: *mut ::msqid_ds) -> ::c_int; pub fn msgget(key: ::key_t, msgflg: ::c_int) -> ::c_int; pub fn msgsnd( msqid: ::c_int, msgp: *const ::c_void, msgsz: ::size_t, msgflg: ::c_int, ) -> ::c_int; pub fn cfmakesane(termios: *mut ::termios); pub fn pdfork(fdp: *mut ::c_int, flags: ::c_int) -> ::pid_t; pub fn pdgetpid(fd: ::c_int, pidp: *mut ::pid_t) -> ::c_int; pub fn pdkill(fd: ::c_int, signum: ::c_int) -> ::c_int; pub fn rtprio_thread(function: ::c_int, lwpid: ::lwpid_t, rtp: *mut super::rtprio) -> ::c_int; pub fn posix_spawn( pid: *mut ::pid_t, path: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnp( pid: *mut ::pid_t, file: *const ::c_char, file_actions: *const ::posix_spawn_file_actions_t, attrp: *const ::posix_spawnattr_t, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> ::c_int; pub fn posix_spawnattr_getsigdefault( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigdefault( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getsigmask( attr: *const posix_spawnattr_t, default: *mut ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_setsigmask( attr: *mut posix_spawnattr_t, default: *const ::sigset_t, ) -> ::c_int; pub fn posix_spawnattr_getflags( attr: *const posix_spawnattr_t, flags: *mut ::c_short, ) -> ::c_int; pub fn posix_spawnattr_setflags(attr: *mut posix_spawnattr_t, flags: ::c_short) -> ::c_int; pub fn posix_spawnattr_getpgroup( attr: *const posix_spawnattr_t, flags: *mut ::pid_t, ) -> ::c_int; pub fn posix_spawnattr_setpgroup(attr: *mut posix_spawnattr_t, flags: ::pid_t) -> ::c_int; pub fn posix_spawnattr_getschedpolicy( attr: *const posix_spawnattr_t, flags: *mut ::c_int, ) -> ::c_int; pub fn posix_spawnattr_setschedpolicy(attr: *mut posix_spawnattr_t, flags: ::c_int) -> ::c_int; pub fn posix_spawnattr_getschedparam( attr: *const posix_spawnattr_t, param: *mut ::sched_param, ) -> ::c_int; pub fn posix_spawnattr_setschedparam( attr: *mut posix_spawnattr_t, param: *const ::sched_param, ) -> ::c_int; pub fn posix_spawn_file_actions_init(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_destroy(actions: *mut posix_spawn_file_actions_t) -> ::c_int; pub fn posix_spawn_file_actions_addopen( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, path: *const ::c_char, oflag: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn posix_spawn_file_actions_addclose( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, ) -> ::c_int; pub fn posix_spawn_file_actions_adddup2( actions: *mut posix_spawn_file_actions_t, fd: ::c_int, newfd: ::c_int, ) -> ::c_int; pub fn uuidgen(store: *mut uuid, count: ::c_int) -> ::c_int; pub fn thr_kill(id: ::c_long, sig: ::c_int) -> ::c_int; pub fn thr_kill2(pid: ::pid_t, id: ::c_long, sig: ::c_int) -> ::c_int; pub fn thr_self(tid: *mut ::c_long) -> ::c_int; pub fn pthread_getthreadid_np() -> ::c_int; pub fn pthread_getaffinity_np( td: ::pthread_t, cpusetsize: ::size_t, cpusetp: *mut cpuset_t, ) -> ::c_int; pub fn pthread_setaffinity_np( td: ::pthread_t, cpusetsize: ::size_t, cpusetp: *const cpuset_t, ) -> ::c_int; // sched.h linux compatibility api pub fn sched_getaffinity(pid: ::pid_t, cpusetsz: ::size_t, cpuset: *mut ::cpuset_t) -> ::c_int; pub fn sched_setaffinity( pid: ::pid_t, cpusetsz: ::size_t, cpuset: *const ::cpuset_t, ) -> ::c_int; pub fn sched_getcpu() -> ::c_int; pub fn pthread_mutex_consistent(mutex: *mut ::pthread_mutex_t) -> ::c_int; pub fn pthread_mutexattr_getrobust( attr: *mut ::pthread_mutexattr_t, robust: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setrobust( attr: *mut ::pthread_mutexattr_t, robust: ::c_int, ) -> ::c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: ::c_int) -> ::c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> ::c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> ::c_int; #[cfg_attr(all(target_os = "freebsd", freebsd11), link_name = "statfs@FBSD_1.0")] pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int; #[cfg_attr(all(target_os = "freebsd", freebsd11), link_name = "fstatfs@FBSD_1.0")] pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int; pub fn dup3(src: ::c_int, dst: ::c_int, flags: ::c_int) -> ::c_int; pub fn __xuname(nmln: ::c_int, buf: *mut ::c_void) -> ::c_int; pub fn sendmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::size_t, flags: ::c_int, ) -> ::ssize_t; pub fn recvmmsg( sockfd: ::c_int, msgvec: *mut ::mmsghdr, vlen: ::size_t, flags: ::c_int, timeout: *const ::timespec, ) -> ::ssize_t; pub fn memmem( haystack: *const ::c_void, haystacklen: ::size_t, needle: *const ::c_void, needlelen: ::size_t, ) -> *mut ::c_void; pub fn fhopen(fhp: *const fhandle_t, flags: ::c_int) -> ::c_int; pub fn fhstat(fhp: *const fhandle, buf: *mut ::stat) -> ::c_int; pub fn fhstatfs(fhp: *const fhandle_t, buf: *mut ::statfs) -> ::c_int; pub fn getfh(path: *const ::c_char, fhp: *mut fhandle_t) -> ::c_int; pub fn lgetfh(path: *const ::c_char, fhp: *mut fhandle_t) -> ::c_int; pub fn getfsstat(buf: *mut ::statfs, bufsize: ::c_long, mode: ::c_int) -> ::c_int; #[cfg_attr( all(target_os = "freebsd", freebsd11), link_name = "getmntinfo@FBSD_1.0" )] pub fn getmntinfo(mntbufp: *mut *mut ::statfs, mode: ::c_int) -> ::c_int; pub fn mount( type_: *const ::c_char, dir: *const ::c_char, flags: ::c_int, data: *mut ::c_void, ) -> ::c_int; pub fn nmount(iov: *mut ::iovec, niov: ::c_uint, flags: ::c_int) -> ::c_int; pub fn setproctitle(fmt: *const ::c_char, ...); pub fn rfork(flags: ::c_int) -> ::c_int; pub fn cpuset_getaffinity( level: cpulevel_t, which: cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *mut cpuset_t, ) -> ::c_int; pub fn cpuset_setaffinity( level: cpulevel_t, which: cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *const cpuset_t, ) -> ::c_int; pub fn cpuset(setid: *mut ::cpusetid_t) -> ::c_int; pub fn cpuset_getid( level: cpulevel_t, which: cpuwhich_t, id: ::id_t, setid: *mut ::cpusetid_t, ) -> ::c_int; pub fn cpuset_setid(which: cpuwhich_t, id: ::id_t, setid: ::cpusetid_t) -> ::c_int; pub fn cap_enter() -> ::c_int; pub fn cap_getmode(modep: *mut ::c_uint) -> ::c_int; pub fn cap_fcntls_get(fd: ::c_int, fcntlrightsp: *mut u32) -> ::c_int; pub fn cap_fcntls_limit(fd: ::c_int, fcntlrights: u32) -> ::c_int; pub fn cap_ioctls_get(fd: ::c_int, cmds: *mut u_long, maxcmds: usize) -> isize; pub fn cap_ioctls_limit(fd: ::c_int, cmds: *const u_long, ncmds: usize) -> ::c_int; pub fn __cap_rights_init(version: ::c_int, rights: *mut cap_rights_t, ...) -> *mut cap_rights_t; pub fn __cap_rights_get(version: ::c_int, fd: ::c_int, rightsp: *mut cap_rights_t) -> ::c_int; pub fn __cap_rights_set(rights: *mut cap_rights_t, ...) -> *mut cap_rights_t; pub fn __cap_rights_clear(rights: *mut cap_rights_t, ...) -> *mut cap_rights_t; pub fn __cap_rights_is_set(rights: *const cap_rights_t, ...) -> bool; pub fn cap_rights_is_valid(rights: *const cap_rights_t) -> bool; pub fn cap_rights_limit(fd: ::c_int, rights: *const cap_rights_t) -> ::c_int; pub fn cap_rights_merge(dst: *mut cap_rights_t, src: *const cap_rights_t) -> *mut cap_rights_t; pub fn cap_rights_remove(dst: *mut cap_rights_t, src: *const cap_rights_t) -> *mut cap_rights_t; pub fn cap_rights_contains(big: *const cap_rights_t, little: *const cap_rights_t) -> bool; pub fn cap_sandboxed() -> bool; pub fn reallocarray(ptr: *mut ::c_void, nmemb: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn ffs(value: ::c_int) -> ::c_int; pub fn ffsl(value: ::c_long) -> ::c_int; pub fn ffsll(value: ::c_longlong) -> ::c_int; pub fn fls(value: ::c_int) -> ::c_int; pub fn flsl(value: ::c_long) -> ::c_int; pub fn flsll(value: ::c_longlong) -> ::c_int; pub fn malloc_stats_print( write_cb: unsafe extern "C" fn(*mut ::c_void, *const ::c_char), cbopaque: *mut ::c_void, opt: *const ::c_char, ); pub fn mallctl( name: *const ::c_char, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn mallctlnametomib( name: *const ::c_char, mibp: *mut ::size_t, miplen: *mut ::size_t, ) -> ::c_int; pub fn mallctlbymib( mib: *const ::size_t, mible: ::size_t, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *mut ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn mallocx(size: ::size_t, flags: ::c_int) -> *mut ::c_void; pub fn rallocx(ptr: *mut ::c_void, size: ::size_t, flags: ::c_int) -> *mut ::c_void; pub fn xallocx(ptr: *mut ::c_void, size: ::size_t, extra: ::size_t, flags: ::c_int) -> ::size_t; pub fn sallocx(ptr: *const ::c_void, flags: ::c_int) -> ::size_t; pub fn dallocx(ptr: *mut ::c_void, flags: ::c_int); pub fn sdallocx(ptr: *mut ::c_void, size: ::size_t, flags: ::c_int); pub fn nallocx(size: ::size_t, flags: ::c_int) -> ::size_t; pub fn procctl(idtype: ::idtype_t, id: ::id_t, cmd: ::c_int, data: *mut ::c_void) -> ::c_int; pub fn getpagesize() -> ::c_int; pub fn getpagesizes(pagesize: *mut ::size_t, nelem: ::c_int) -> ::c_int; pub fn clock_getcpuclockid2(arg1: ::id_t, arg2: ::c_int, arg3: *mut clockid_t) -> ::c_int; pub fn strchrnul(s: *const ::c_char, c: ::c_int) -> *mut ::c_char; pub fn shm_create_largepage( path: *const ::c_char, flags: ::c_int, psind: ::c_int, alloc_policy: ::c_int, mode: ::mode_t, ) -> ::c_int; pub fn shm_rename( path_from: *const ::c_char, path_to: *const ::c_char, flags: ::c_int, ) -> ::c_int; pub fn memfd_create(name: *const ::c_char, flags: ::c_uint) -> ::c_int; pub fn setaudit(auditinfo: *const auditinfo_t) -> ::c_int; pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int; pub fn eventfd_read(fd: ::c_int, value: *mut eventfd_t) -> ::c_int; pub fn eventfd_write(fd: ::c_int, value: eventfd_t) -> ::c_int; pub fn fdatasync(fd: ::c_int) -> ::c_int; pub fn elf_aux_info(aux: ::c_int, buf: *mut ::c_void, buflen: ::c_int) -> ::c_int; pub fn setproctitle_fast(fmt: *const ::c_char, ...); pub fn timingsafe_bcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int; pub fn timingsafe_memcmp(a: *const ::c_void, b: *const ::c_void, len: ::size_t) -> ::c_int; pub fn _umtx_op( obj: *mut ::c_void, op: ::c_int, val: ::c_ulong, uaddr: *mut ::c_void, uaddr2: *mut ::c_void, ) -> ::c_int; pub fn sctp_peeloff(s: ::c_int, id: ::sctp_assoc_t) -> ::c_int; pub fn sctp_bindx(s: ::c_int, addrs: *mut ::sockaddr, num: ::c_int, tpe: ::c_int) -> ::c_int; pub fn sctp_connectx( s: ::c_int, addrs: *const ::sockaddr, addrcnt: ::c_int, id: *mut ::sctp_assoc_t, ) -> ::c_int; pub fn sctp_getaddrlen(family: ::sa_family_t) -> ::c_int; pub fn sctp_getpaddrs( s: ::c_int, asocid: ::sctp_assoc_t, addrs: *mut *mut ::sockaddr, ) -> ::c_int; pub fn sctp_freepaddrs(addrs: *mut ::sockaddr); pub fn sctp_getladdrs( s: ::c_int, asocid: ::sctp_assoc_t, addrs: *mut *mut ::sockaddr, ) -> ::c_int; pub fn sctp_freeladdrs(addrs: *mut ::sockaddr); pub fn sctp_opt_info( s: ::c_int, id: ::sctp_assoc_t, opt: ::c_int, arg: *mut ::c_void, size: *mut ::socklen_t, ) -> ::c_int; pub fn sctp_sendv( sd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, addrs: *mut ::sockaddr, addrcnt: ::c_int, info: *mut ::c_void, infolen: ::socklen_t, infotype: ::c_uint, flags: ::c_int, ) -> ::ssize_t; pub fn sctp_recvv( sd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, from: *mut ::sockaddr, fromlen: *mut ::socklen_t, info: *mut ::c_void, infolen: *mut ::socklen_t, infotype: *mut ::c_uint, flags: *mut ::c_int, ) -> ::ssize_t; pub fn timerfd_create(clockid: ::c_int, flags: ::c_int) -> ::c_int; pub fn timerfd_gettime(fd: ::c_int, curr_value: *mut itimerspec) -> ::c_int; pub fn timerfd_settime( fd: ::c_int, flags: ::c_int, new_value: *const itimerspec, old_value: *mut itimerspec, ) -> ::c_int; pub fn closefrom(lowfd: ::c_int); pub fn close_range(lowfd: ::c_uint, highfd: ::c_uint, flags: ::c_int) -> ::c_int; } #[link(name = "memstat")] extern "C" { pub fn memstat_strerror(error: ::c_int) -> *const ::c_char; pub fn memstat_mtl_alloc() -> *mut memory_type_list; pub fn memstat_mtl_first(list: *mut memory_type_list) -> *mut memory_type; pub fn memstat_mtl_next(mtp: *mut memory_type) -> *mut memory_type; pub fn memstat_mtl_find( list: *mut memory_type_list, allocator: ::c_int, name: *const ::c_char, ) -> *mut memory_type; pub fn memstat_mtl_free(list: *mut memory_type_list); pub fn memstat_mtl_geterror(list: *mut memory_type_list) -> ::c_int; pub fn memstat_get_name(mtp: *const memory_type) -> *const ::c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_dpcpu_setcpu(kd: *mut ::kvm_t, cpu: ::c_uint) -> ::c_int; pub fn kvm_getargv(kd: *mut ::kvm_t, p: *const kinfo_proc, nchr: ::c_int) -> *mut *mut ::c_char; pub fn kvm_getcptime(kd: *mut ::kvm_t, cp_time: *mut ::c_long) -> ::c_int; pub fn kvm_getenvv(kd: *mut ::kvm_t, p: *const kinfo_proc, nchr: ::c_int) -> *mut *mut ::c_char; pub fn kvm_geterr(kd: *mut ::kvm_t) -> *mut ::c_char; pub fn kvm_getmaxcpu(kd: *mut ::kvm_t) -> ::c_int; pub fn kvm_getncpus(kd: *mut ::kvm_t) -> ::c_int; pub fn kvm_getpcpu(kd: *mut ::kvm_t, cpu: ::c_int) -> *mut ::c_void; pub fn kvm_counter_u64_fetch(kd: *mut ::kvm_t, base: ::c_ulong) -> u64; pub fn kvm_getswapinfo( kd: *mut ::kvm_t, info: *mut kvm_swap, maxswap: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn kvm_native(kd: *mut ::kvm_t) -> ::c_int; pub fn kvm_nlist(kd: *mut ::kvm_t, nl: *mut nlist) -> ::c_int; pub fn kvm_nlist2(kd: *mut ::kvm_t, nl: *mut kvm_nlist) -> ::c_int; pub fn kvm_read_zpcpu( kd: *mut ::kvm_t, base: ::c_ulong, buf: *mut ::c_void, size: ::size_t, cpu: ::c_int, ) -> ::ssize_t; pub fn kvm_read2( kd: *mut ::kvm_t, addr: kvaddr_t, buf: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; } #[link(name = "util")] extern "C" { pub fn extattr_namespace_to_string( attrnamespace: ::c_int, string: *mut *mut ::c_char, ) -> ::c_int; pub fn extattr_string_to_namespace( string: *const ::c_char, attrnamespace: *mut ::c_int, ) -> ::c_int; pub fn realhostname(host: *mut ::c_char, hsize: ::size_t, ip: *const ::in_addr) -> ::c_int; pub fn realhostname_sa( host: *mut ::c_char, hsize: ::size_t, addr: *mut ::sockaddr, addrlen: ::c_int, ) -> ::c_int; pub fn kld_isloaded(name: *const ::c_char) -> ::c_int; pub fn kld_load(name: *const ::c_char) -> ::c_int; pub fn kinfo_getvmmap(pid: ::pid_t, cntp: *mut ::c_int) -> *mut kinfo_vmentry; pub fn hexdump(ptr: *const ::c_void, length: ::c_int, hdr: *const ::c_char, flags: ::c_int); pub fn humanize_number( buf: *mut ::c_char, len: ::size_t, number: i64, suffix: *const ::c_char, scale: ::c_int, flags: ::c_int, ) -> ::c_int; pub fn flopen(path: *const ::c_char, flags: ::c_int, ...) -> ::c_int; pub fn flopenat(fd: ::c_int, path: *const ::c_char, flags: ::c_int, ...) -> ::c_int; pub fn getlocalbase() -> *const ::c_char; pub fn pidfile_open( path: *const ::c_char, mode: ::mode_t, pidptr: *mut ::pid_t, ) -> *mut ::pidfh; pub fn pidfile_write(path: *mut ::pidfh) -> ::c_int; pub fn pidfile_close(path: *mut ::pidfh) -> ::c_int; pub fn pidfile_remove(path: *mut ::pidfh) -> ::c_int; pub fn pidfile_fileno(path: *const ::pidfh) -> ::c_int; // FIXME: pidfile_signal in due time (both manpage present and updated image snapshot) } #[link(name = "procstat")] extern "C" { pub fn procstat_open_sysctl() -> *mut procstat; pub fn procstat_getfiles( procstat: *mut procstat, kp: *mut kinfo_proc, mmapped: ::c_int, ) -> *mut filestat_list; pub fn procstat_freefiles(procstat: *mut procstat, head: *mut filestat_list); pub fn procstat_getprocs( procstat: *mut procstat, what: ::c_int, arg: ::c_int, count: *mut ::c_uint, ) -> *mut kinfo_proc; pub fn procstat_freeprocs(procstat: *mut procstat, p: *mut kinfo_proc); pub fn procstat_getvmmap( procstat: *mut procstat, kp: *mut kinfo_proc, count: *mut ::c_uint, ) -> *mut kinfo_vmentry; pub fn procstat_freevmmap(procstat: *mut procstat, vmmap: *mut kinfo_vmentry); pub fn procstat_close(procstat: *mut procstat); pub fn procstat_freeargv(procstat: *mut procstat); pub fn procstat_freeenvv(procstat: *mut procstat); pub fn procstat_freegroups(procstat: *mut procstat, groups: *mut ::gid_t); pub fn procstat_freeptlwpinfo(procstat: *mut procstat, pl: *mut ptrace_lwpinfo); pub fn procstat_getargv( procstat: *mut procstat, kp: *mut kinfo_proc, nchr: ::size_t, ) -> *mut *mut ::c_char; pub fn procstat_getenvv( procstat: *mut procstat, kp: *mut kinfo_proc, nchr: ::size_t, ) -> *mut *mut ::c_char; pub fn procstat_getgroups( procstat: *mut procstat, kp: *mut kinfo_proc, count: *mut ::c_uint, ) -> *mut ::gid_t; pub fn procstat_getosrel( procstat: *mut procstat, kp: *mut kinfo_proc, osrelp: *mut ::c_int, ) -> ::c_int; pub fn procstat_getpathname( procstat: *mut procstat, kp: *mut kinfo_proc, pathname: *mut ::c_char, maxlen: ::size_t, ) -> ::c_int; pub fn procstat_getrlimit( procstat: *mut procstat, kp: *mut kinfo_proc, which: ::c_int, rlimit: *mut ::rlimit, ) -> ::c_int; pub fn procstat_getumask( procstat: *mut procstat, kp: *mut kinfo_proc, maskp: *mut ::c_ushort, ) -> ::c_int; pub fn procstat_open_core(filename: *const ::c_char) -> *mut procstat; pub fn procstat_open_kvm(nlistf: *const ::c_char, memf: *const ::c_char) -> *mut procstat; pub fn procstat_get_socket_info( proc_: *mut procstat, fst: *mut filestat, sock: *mut sockstat, errbuf: *mut ::c_char, ) -> ::c_int; pub fn procstat_get_vnode_info( proc_: *mut procstat, fst: *mut filestat, vn: *mut vnstat, errbuf: *mut ::c_char, ) -> ::c_int; pub fn procstat_get_pts_info( proc_: *mut procstat, fst: *mut filestat, pts: *mut ptsstat, errbuf: *mut ::c_char, ) -> ::c_int; pub fn procstat_get_shm_info( proc_: *mut procstat, fst: *mut filestat, shm: *mut shmstat, errbuf: *mut ::c_char, ) -> ::c_int; } #[link(name = "rt")] extern "C" { pub fn timer_create(clock_id: clockid_t, evp: *mut sigevent, timerid: *mut timer_t) -> ::c_int; pub fn timer_delete(timerid: timer_t) -> ::c_int; pub fn timer_getoverrun(timerid: timer_t) -> ::c_int; pub fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> ::c_int; pub fn timer_settime( timerid: timer_t, flags: ::c_int, value: *const itimerspec, ovalue: *mut itimerspec, ) -> ::c_int; } #[link(name = "devstat")] extern "C" { pub fn devstat_getnumdevs(kd: *mut ::kvm_t) -> ::c_int; pub fn devstat_getgeneration(kd: *mut ::kvm_t) -> ::c_long; pub fn devstat_getversion(kd: *mut ::kvm_t) -> ::c_int; pub fn devstat_checkversion(kd: *mut ::kvm_t) -> ::c_int; pub fn devstat_selectdevs( dev_select: *mut *mut device_selection, num_selected: *mut ::c_int, num_selections: *mut ::c_int, select_generation: *mut ::c_long, current_generation: ::c_long, devices: *mut devstat, numdevs: ::c_int, matches: *mut devstat_match, num_matches: ::c_int, dev_selections: *mut *mut ::c_char, num_dev_selections: ::c_int, select_mode: devstat_select_mode, maxshowdevs: ::c_int, perf_select: ::c_int, ) -> ::c_int; pub fn devstat_buildmatch( match_str: *mut ::c_char, matches: *mut *mut devstat_match, num_matches: *mut ::c_int, ) -> ::c_int; } cfg_if! { if #[cfg(freebsd15)] { mod freebsd15; pub use self::freebsd15::*; } else if #[cfg(freebsd14)] { mod freebsd14; pub use self::freebsd14::*; } else if #[cfg(freebsd13)] { mod freebsd13; pub use self::freebsd13::*; } else if #[cfg(freebsd12)] { mod freebsd12; pub use self::freebsd12::*; } else if #[cfg(any(freebsd10, freebsd11))] { mod freebsd11; pub use self::freebsd11::*; } else { // Unknown freebsd version } } cfg_if! { if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "riscv64")] { mod riscv64; pub use self::riscv64::*; } else { // Unknown target_arch } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/0000775000175000017500000000000014661133735022445 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs0000644000175000017500000000043714661133735023753 0ustar jamespagejamespagepub const PROC_KPTI_CTL: ::c_int = ::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: ::c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: ::c_int = 2; pub const PROC_KPTI_STATUS: ::c_int = ::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: ::c_int = 0x80000000; libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs0000644000175000017500000004460714661133735023603 0ustar jamespagejamespage// APIs in FreeBSD 13 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = ::c_ulong; pub type shmatt_t = ::c_uint; pub type kpaddr_t = u64; pub type kssize_t = i64; pub type domainset_t = __c_anonymous_domainset; s! { pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, } pub struct kevent { pub ident: ::uintptr_t, pub filter: ::c_short, pub flags: ::c_ushort, pub fflags: ::c_uint, pub data: i64, pub udata: *mut ::c_void, pub ext: [u64; 4], } pub struct kvm_page { pub kp_version: ::u_int, pub kp_paddr: ::kpaddr_t, pub kp_kmap_vaddr: ::kvaddr_t, pub kp_dmap_vaddr: ::kvaddr_t, pub kp_prot: ::vm_prot_t, pub kp_offset: ::off_t, pub kp_len: ::size_t, } pub struct __c_anonymous_domainset { _priv: [::uintptr_t; 4], } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: ::c_int, /// Reserved: layout identifier. pub ki_layout: ::c_int, /// Address of command arguments. pub ki_args: *mut ::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut ::c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut ::c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut ::c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut ::c_void, // This is normally "struct filedesc". /// Pointer to open file info. pub ki_fd: *mut ::c_void, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut ::c_void, /// Sleep address. pub ki_wchan: *const ::c_void, /// Process identifier. pub ki_pid: ::pid_t, /// Parent process ID. pub ki_ppid: ::pid_t, /// Process group ID. pub ki_pgid: ::pid_t, /// tty process group ID. pub ki_tpgid: ::pid_t, /// Process session ID. pub ki_sid: ::pid_t, /// Terminal session ID. pub ki_tsid: ::pid_t, /// Job control counter. pub ki_jobc: ::c_short, /// Unused (just here for alignment). pub ki_spare_short1: ::c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: ::sigset_t, /// Current signal mask. pub ki_sigmask: ::sigset_t, /// Signals being ignored. pub ki_sigignore: ::sigset_t, /// Signals being caught by user. pub ki_sigcatch: ::sigset_t, /// Effective user ID. pub ki_uid: ::uid_t, /// Real user ID. pub ki_ruid: ::uid_t, /// Saved effective user ID. pub ki_svuid: ::uid_t, /// Real group ID. pub ki_rgid: ::gid_t, /// Saved effective group ID. pub ki_svgid: ::gid_t, /// Number of groups. pub ki_ngroups: ::c_short, /// Unused (just here for alignment). pub ki_spare_short2: ::c_short, /// Groups. pub ki_groups: [::gid_t; ::KI_NGROUPS], /// Virtual size. pub ki_size: ::vm_size_t, /// Current resident set size in pages. pub ki_rssize: ::segsz_t, /// Resident set size before last swap. pub ki_swrss: ::segsz_t, /// Text size (pages) XXX. pub ki_tsize: ::segsz_t, /// Data size (pages) XXX. pub ki_dsize: ::segsz_t, /// Stack size (pages). pub ki_ssize: ::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: ::u_short, /// Accounting flags. pub ki_acflag: ::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: ::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: ::u_int, /// Time since last blocked. pub ki_slptime: ::u_int, /// Time swapped in or out. pub ki_swtime: ::u_int, /// Number of copy-on-write faults. pub ki_cow: ::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: ::timeval, /// Time used by process children. pub ki_childtime: ::timeval, /// P_* flags. pub ki_flag: ::c_long, /// KI_* flags (below). pub ki_kiflag: ::c_long, /// Kernel trace points. pub ki_traceflag: ::c_int, /// S* process status. pub ki_stat: ::c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: ::c_char, /// Run queue index. pub ki_rqindex: ::c_char, /// Which cpu we are on. pub ki_oncpu_old: ::c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: ::c_uchar, /// Thread name. pub ki_tdname: [::c_char; ::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [::c_char; ::WMESGLEN + 1], /// Setlogin name. pub ki_login: [::c_char; ::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [::c_char; ::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [::c_char; ::COMMLEN + 1], /// Emulation name. pub ki_emul: [::c_char; ::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [::c_char; ::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [::c_char; ::MAXCOMLEN - ::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[::c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [::c_int; ::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: u64, /// Which cpu we are on. pub ki_oncpu: ::c_int, /// Last cpu we were on. pub ki_lastcpu: ::c_int, /// PID of tracing process. pub ki_tracer: ::c_int, /// P2_* flags. pub ki_flag2: ::c_int, /// Default FIB number. pub ki_fibnum: ::c_int, /// Credential flags. pub ki_cr_flags: ::u_int, /// Process jail ID. pub ki_jid: ::c_int, /// Number of threads in total. pub ki_numthreads: ::c_int, /// Thread ID. pub ki_tid: ::lwpid_t, /// Process priority. pub ki_pri: ::priority, /// Process rusage statistics. pub ki_rusage: ::rusage, /// rusage of children processes. pub ki_rusage_ch: ::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut ::c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut ::c_void, /// User convenience pointer. pub ki_udata: *mut ::c_void, // This is normally "struct thread". pub ki_tdaddr: *mut ::c_void, // This is normally "struct pwddesc". /// Pointer to process paths info. pub ki_pd: *mut ::c_void, pub ki_spareptrs: [*mut ::c_void; ::KI_NSPARE_PTR], pub ki_sparelongs: [::c_long; ::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: ::c_long, /// kthread flag. pub ki_tdflags: ::c_long, } } s_no_extra_traits! { pub struct dirent { pub d_fileno: ::ino_t, pub d_off: ::off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [::c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: ::uid_t, pub f_fsid: ::fsid_t, f_charspare: [::c_char; 80], pub f_fstypename: [::c_char; 16], pub f_mntfromname: [::c_char; 1024], pub f_mntonname: [::c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut ::c_char, pub vn_type: ::c_int, pub vn_mode: u16, pub vn_devname: [::c_char; ::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) } } impl Eq for statfs {} impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self .d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[::c_char] = &self.vn_devname; let other_vn_devname: &[::c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl ::fmt::Debug for vnstat { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let self_vn_devname: &[::c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl ::hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[::c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: ::c_int = 0x7fff_ffff; pub const ELAST: ::c_int = 97; pub const KF_TYPE_EVENTFD: ::c_int = 13; /// max length of devicename pub const SPECNAMELEN: ::c_int = 255; pub const KI_NSPARE_PTR: usize = 5; /// domainset policies pub const DOMAINSET_POLICY_INVALID: ::c_int = 0; pub const DOMAINSET_POLICY_ROUNDROBIN: ::c_int = 1; pub const DOMAINSET_POLICY_FIRSTTOUCH: ::c_int = 2; pub const DOMAINSET_POLICY_PREFER: ::c_int = 3; pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4; pub const MINCORE_SUPER: ::c_int = 0x20; safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } } f! { pub fn major(dev: ::dev_t) -> ::c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as ::c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn freelocale(loc: ::locale_t); pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn cpuset_getdomain( level: ::cpulevel_t, which: ::cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *mut ::domainset_t, policy: *mut ::c_int, ) -> ::c_int; pub fn cpuset_setdomain( level: ::cpulevel_t, which: ::cpuwhich_t, id: ::id_t, setsize: ::size_t, mask: *const ::domainset_t, policy: ::c_int, ) -> ::c_int; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; } #[link(name = "kvm")] extern "C" { pub fn kvm_kerndisp(kd: *mut ::kvm_t) -> ::kssize_t; } cfg_if! { if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))] { mod b64; pub use self::b64::*; } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs0000644000175000017500000000153414661133735023407 0ustar jamespagejamespage#[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, st_padding0: i16, pub st_uid: ::uid_t, pub st_gid: ::gid_t, st_padding1: i32, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u64, pub st_spare: [u64; 10], } impl ::Copy for ::stat {} impl ::Clone for ::stat { fn clone(&self) -> ::stat { *self } } libc/src/unix/bsd/freebsdlike/freebsd/aarch64.rs0000644000175000017500000001155514661133735022472 0ustar jamespagejamespagepub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = u32; pub type time_t = i64; pub type suseconds_t = i64; pub type register_t = i64; s_no_extra_traits! { pub struct gpregs { pub gp_x: [::register_t; 30], pub gp_lr: ::register_t, pub gp_sp: ::register_t, pub gp_elr: ::register_t, pub gp_spsr: u32, pub gp_pad: ::c_int, } pub struct fpregs { pub fp_q: u128, pub fp_sr: u32, pub fp_cr: u32, pub fp_flags: ::c_int, pub fp_pad: ::c_int, } pub struct mcontext_t { pub mc_gpregs: gpregs, pub mc_fpregs: fpregs, pub mc_flags: ::c_int, pub mc_pad: ::c_int, pub mc_spare: [u64; 8], } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_longlong>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for gpregs { fn eq(&self, other: &gpregs) -> bool { self.gp_x.iter().zip(other.gp_x.iter()).all(|(a, b)| a == b) && self.gp_lr == other.gp_lr && self.gp_sp == other.gp_sp && self.gp_elr == other.gp_elr && self.gp_spsr == other.gp_spsr && self.gp_pad == other.gp_pad } } impl Eq for gpregs {} impl ::fmt::Debug for gpregs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("gpregs") .field("gp_x", &self.gp_x) .field("gp_lr", &self.gp_lr) .field("gp_sp", &self.gp_sp) .field("gp_elr", &self.gp_elr) .field("gp_spsr", &self.gp_spsr) .field("gp_pad", &self.gp_pad) .finish() } } impl ::hash::Hash for gpregs { fn hash(&self, state: &mut H) { self.gp_x.hash(state); self.gp_lr.hash(state); self.gp_sp.hash(state); self.gp_elr.hash(state); self.gp_spsr.hash(state); self.gp_pad.hash(state); } } impl PartialEq for fpregs { fn eq(&self, other: &fpregs) -> bool { self.fp_q == other.fp_q && self.fp_sr == other.fp_sr && self.fp_cr == other.fp_cr && self.fp_flags == other.fp_flags && self.fp_pad == other.fp_pad } } impl Eq for fpregs {} impl ::fmt::Debug for fpregs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpregs") .field("fp_q", &self.fp_q) .field("fp_sr", &self.fp_sr) .field("fp_cr", &self.fp_cr) .field("fp_flags", &self.fp_flags) .field("fp_pad", &self.fp_pad) .finish() } } impl ::hash::Hash for fpregs { fn hash(&self, state: &mut H) { self.fp_q.hash(state); self.fp_sr.hash(state); self.fp_cr.hash(state); self.fp_flags.hash(state); self.fp_pad.hash(state); } } impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_gpregs == other.mc_gpregs && self.mc_fpregs == other.mc_fpregs && self.mc_flags == other.mc_flags && self.mc_pad == other.mc_pad && self.mc_spare.iter().zip(other.mc_spare.iter()).all(|(a, b)| a == b) } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("mc_gpregs", &self.mc_gpregs) .field("mc_fpregs", &self.mc_fpregs) .field("mc_flags", &self.mc_flags) .field("mc_pad", &self.mc_pad) .field("mc_spare", &self.mc_spare) .finish() } } impl ::hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_gpregs.hash(state); self.mc_fpregs.hash(state); self.mc_flags.hash(state); self.mc_pad.hash(state); self.mc_spare.hash(state); } } } } pub const MAP_32BIT: ::c_int = 0x00080000; pub const MINSIGSTKSZ: ::size_t = 4096; // 1024 * 4 libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/0000775000175000017500000000000014661133735022444 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs0000644000175000017500000000043714661133735023752 0ustar jamespagejamespagepub const PROC_KPTI_CTL: ::c_int = ::PROC_PROCCTL_MD_MIN; pub const PROC_KPTI_CTL_ENABLE_ON_EXEC: ::c_int = 1; pub const PROC_KPTI_CTL_DISABLE_ON_EXEC: ::c_int = 2; pub const PROC_KPTI_STATUS: ::c_int = ::PROC_PROCCTL_MD_MIN + 1; pub const PROC_KPTI_STATUS_ACTIVE: ::c_int = 0x80000000; libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs0000644000175000017500000004237014661133735023575 0ustar jamespagejamespage// APIs in FreeBSD 12 that have changed since 11. pub type nlink_t = u64; pub type dev_t = u64; pub type ino_t = ::c_ulong; pub type shmatt_t = ::c_uint; s! { pub struct shmid_ds { pub shm_perm: ::ipc_perm, pub shm_segsz: ::size_t, pub shm_lpid: ::pid_t, pub shm_cpid: ::pid_t, pub shm_nattch: ::shmatt_t, pub shm_atime: ::time_t, pub shm_dtime: ::time_t, pub shm_ctime: ::time_t, } pub struct kevent { pub ident: ::uintptr_t, pub filter: ::c_short, pub flags: ::c_ushort, pub fflags: ::c_uint, pub data: i64, pub udata: *mut ::c_void, pub ext: [u64; 4], } pub struct kvm_page { pub version: ::c_uint, pub paddr: ::c_ulong, pub kmap_vaddr: ::c_ulong, pub dmap_vaddr: ::c_ulong, pub prot: ::vm_prot_t, pub offset: ::u_long, pub len: ::size_t, } pub struct kinfo_proc { /// Size of this structure. pub ki_structsize: ::c_int, /// Reserved: layout identifier. pub ki_layout: ::c_int, /// Address of command arguments. pub ki_args: *mut ::pargs, // This is normally "struct proc". /// Address of proc. pub ki_paddr: *mut ::c_void, // This is normally "struct user". /// Kernel virtual address of u-area. pub ki_addr: *mut ::c_void, // This is normally "struct vnode". /// Pointer to trace file. pub ki_tracep: *mut ::c_void, // This is normally "struct vnode". /// Pointer to executable file. pub ki_textvp: *mut ::c_void, // This is normally "struct filedesc". /// Pointer to open file info. pub ki_fd: *mut ::c_void, // This is normally "struct vmspace". /// Pointer to kernel vmspace struct. pub ki_vmspace: *mut ::c_void, /// Sleep address. pub ki_wchan: *mut ::c_void, /// Process identifier. pub ki_pid: ::pid_t, /// Parent process ID. pub ki_ppid: ::pid_t, /// Process group ID. pub ki_pgid: ::pid_t, /// tty process group ID. pub ki_tpgid: ::pid_t, /// Process session ID. pub ki_sid: ::pid_t, /// Terminal session ID. pub ki_tsid: ::pid_t, /// Job control counter. pub ki_jobc: ::c_short, /// Unused (just here for alignment). pub ki_spare_short1: ::c_short, /// Controlling tty dev. pub ki_tdev_freebsd11: u32, /// Signals arrived but not delivered. pub ki_siglist: ::sigset_t, /// Current signal mask. pub ki_sigmask: ::sigset_t, /// Signals being ignored. pub ki_sigignore: ::sigset_t, /// Signals being caught by user. pub ki_sigcatch: ::sigset_t, /// Effective user ID. pub ki_uid: ::uid_t, /// Real user ID. pub ki_ruid: ::uid_t, /// Saved effective user ID. pub ki_svuid: ::uid_t, /// Real group ID. pub ki_rgid: ::gid_t, /// Saved effective group ID. pub ki_svgid: ::gid_t, /// Number of groups. pub ki_ngroups: ::c_short, /// Unused (just here for alignment). pub ki_spare_short2: ::c_short, /// Groups. pub ki_groups: [::gid_t; ::KI_NGROUPS], /// Virtual size. pub ki_size: ::vm_size_t, /// Current resident set size in pages. pub ki_rssize: ::segsz_t, /// Resident set size before last swap. pub ki_swrss: ::segsz_t, /// Text size (pages) XXX. pub ki_tsize: ::segsz_t, /// Data size (pages) XXX. pub ki_dsize: ::segsz_t, /// Stack size (pages). pub ki_ssize: ::segsz_t, /// Exit status for wait & stop signal. pub ki_xstat: ::u_short, /// Accounting flags. pub ki_acflag: ::u_short, /// %cpu for process during `ki_swtime`. pub ki_pctcpu: ::fixpt_t, /// Time averaged value of `ki_cpticks`. pub ki_estcpu: ::u_int, /// Time since last blocked. pub ki_slptime: ::u_int, /// Time swapped in or out. pub ki_swtime: ::u_int, /// Number of copy-on-write faults. pub ki_cow: ::u_int, /// Real time in microsec. pub ki_runtime: u64, /// Starting time. pub ki_start: ::timeval, /// Time used by process children. pub ki_childtime: ::timeval, /// P_* flags. pub ki_flag: ::c_long, /// KI_* flags (below). pub ki_kiflag: ::c_long, /// Kernel trace points. pub ki_traceflag: ::c_int, /// S* process status. pub ki_stat: ::c_char, /// Process "nice" value. pub ki_nice: i8, // signed char /// Process lock (prevent swap) count. pub ki_lock: ::c_char, /// Run queue index. pub ki_rqindex: ::c_char, /// Which cpu we are on. pub ki_oncpu_old: ::c_uchar, /// Last cpu we were on. pub ki_lastcpu_old: ::c_uchar, /// Thread name. pub ki_tdname: [::c_char; ::TDNAMLEN + 1], /// Wchan message. pub ki_wmesg: [::c_char; ::WMESGLEN + 1], /// Setlogin name. pub ki_login: [::c_char; ::LOGNAMELEN + 1], /// Lock name. pub ki_lockname: [::c_char; ::LOCKNAMELEN + 1], /// Command name. pub ki_comm: [::c_char; ::COMMLEN + 1], /// Emulation name. pub ki_emul: [::c_char; ::KI_EMULNAMELEN + 1], /// Login class. pub ki_loginclass: [::c_char; ::LOGINCLASSLEN + 1], /// More thread name. pub ki_moretdname: [::c_char; ::MAXCOMLEN - ::TDNAMLEN + 1], /// Spare string space. pub ki_sparestrings: [[::c_char; 23]; 2], // little hack to allow PartialEq /// Spare room for growth. pub ki_spareints: [::c_int; ::KI_NSPARE_INT], /// Controlling tty dev. pub ki_tdev: ::dev_t, /// Which cpu we are on. pub ki_oncpu: ::c_int, /// Last cpu we were on. pub ki_lastcpu: ::c_int, /// PID of tracing process. pub ki_tracer: ::c_int, /// P2_* flags. pub ki_flag2: ::c_int, /// Default FIB number. pub ki_fibnum: ::c_int, /// Credential flags. pub ki_cr_flags: ::u_int, /// Process jail ID. pub ki_jid: ::c_int, /// Number of threads in total. pub ki_numthreads: ::c_int, /// Thread ID. pub ki_tid: ::lwpid_t, /// Process priority. pub ki_pri: ::priority, /// Process rusage statistics. pub ki_rusage: ::rusage, /// rusage of children processes. pub ki_rusage_ch: ::rusage, // This is normally "struct pcb". /// Kernel virtual addr of pcb. pub ki_pcb: *mut ::c_void, /// Kernel virtual addr of stack. pub ki_kstack: *mut ::c_void, /// User convenience pointer. pub ki_udata: *mut ::c_void, // This is normally "struct thread". pub ki_tdaddr: *mut ::c_void, pub ki_spareptrs: [*mut ::c_void; ::KI_NSPARE_PTR], pub ki_sparelongs: [::c_long; ::KI_NSPARE_LONG], /// PS_* flags. pub ki_sflag: ::c_long, /// kthread flag. pub ki_tdflags: ::c_long, } } s_no_extra_traits! { pub struct dirent { pub d_fileno: ::ino_t, pub d_off: ::off_t, pub d_reclen: u16, pub d_type: u8, d_pad0: u8, pub d_namlen: u16, d_pad1: u16, pub d_name: [::c_char; 256], } pub struct statfs { pub f_version: u32, pub f_type: u32, pub f_flags: u64, pub f_bsize: u64, pub f_iosize: u64, pub f_blocks: u64, pub f_bfree: u64, pub f_bavail: i64, pub f_files: u64, pub f_ffree: i64, pub f_syncwrites: u64, pub f_asyncwrites: u64, pub f_syncreads: u64, pub f_asyncreads: u64, f_spare: [u64; 10], pub f_namemax: u32, pub f_owner: ::uid_t, pub f_fsid: ::fsid_t, f_charspare: [::c_char; 80], pub f_fstypename: [::c_char; 16], pub f_mntfromname: [::c_char; 1024], pub f_mntonname: [::c_char; 1024], } pub struct vnstat { pub vn_fileid: u64, pub vn_size: u64, pub vn_dev: u64, pub vn_fsid: u64, pub vn_mntdir: *mut ::c_char, pub vn_type: ::c_int, pub vn_mode: u16, pub vn_devname: [::c_char; ::SPECNAMELEN as usize + 1], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for statfs { fn eq(&self, other: &statfs) -> bool { self.f_version == other.f_version && self.f_type == other.f_type && self.f_flags == other.f_flags && self.f_bsize == other.f_bsize && self.f_iosize == other.f_iosize && self.f_blocks == other.f_blocks && self.f_bfree == other.f_bfree && self.f_bavail == other.f_bavail && self.f_files == other.f_files && self.f_ffree == other.f_ffree && self.f_syncwrites == other.f_syncwrites && self.f_asyncwrites == other.f_asyncwrites && self.f_syncreads == other.f_syncreads && self.f_asyncreads == other.f_asyncreads && self.f_namemax == other.f_namemax && self.f_owner == other.f_owner && self.f_fsid == other.f_fsid && self.f_fstypename == other.f_fstypename && self .f_mntfromname .iter() .zip(other.f_mntfromname.iter()) .all(|(a,b)| a == b) && self .f_mntonname .iter() .zip(other.f_mntonname.iter()) .all(|(a,b)| a == b) } } impl Eq for statfs {} impl ::fmt::Debug for statfs { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("statfs") .field("f_bsize", &self.f_bsize) .field("f_iosize", &self.f_iosize) .field("f_blocks", &self.f_blocks) .field("f_bfree", &self.f_bfree) .field("f_bavail", &self.f_bavail) .field("f_files", &self.f_files) .field("f_ffree", &self.f_ffree) .field("f_syncwrites", &self.f_syncwrites) .field("f_asyncwrites", &self.f_asyncwrites) .field("f_syncreads", &self.f_syncreads) .field("f_asyncreads", &self.f_asyncreads) .field("f_namemax", &self.f_namemax) .field("f_owner", &self.f_owner) .field("f_fsid", &self.f_fsid) .field("f_fstypename", &self.f_fstypename) .field("f_mntfromname", &&self.f_mntfromname[..]) .field("f_mntonname", &&self.f_mntonname[..]) .finish() } } impl ::hash::Hash for statfs { fn hash(&self, state: &mut H) { self.f_version.hash(state); self.f_type.hash(state); self.f_flags.hash(state); self.f_bsize.hash(state); self.f_iosize.hash(state); self.f_blocks.hash(state); self.f_bfree.hash(state); self.f_bavail.hash(state); self.f_files.hash(state); self.f_ffree.hash(state); self.f_syncwrites.hash(state); self.f_asyncwrites.hash(state); self.f_syncreads.hash(state); self.f_asyncreads.hash(state); self.f_namemax.hash(state); self.f_owner.hash(state); self.f_fsid.hash(state); self.f_charspare.hash(state); self.f_fstypename.hash(state); self.f_mntfromname.hash(state); self.f_mntonname.hash(state); } } impl PartialEq for dirent { fn eq(&self, other: &dirent) -> bool { self.d_fileno == other.d_fileno && self.d_off == other.d_off && self.d_reclen == other.d_reclen && self.d_type == other.d_type && self.d_namlen == other.d_namlen && self .d_name[..self.d_namlen as _] .iter() .zip(other.d_name.iter()) .all(|(a,b)| a == b) } } impl Eq for dirent {} impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_fileno", &self.d_fileno) .field("d_off", &self.d_off) .field("d_reclen", &self.d_reclen) .field("d_type", &self.d_type) .field("d_namlen", &self.d_namlen) .field("d_name", &&self.d_name[..self.d_namlen as _]) .finish() } } impl ::hash::Hash for dirent { fn hash(&self, state: &mut H) { self.d_fileno.hash(state); self.d_off.hash(state); self.d_reclen.hash(state); self.d_type.hash(state); self.d_namlen.hash(state); self.d_name[..self.d_namlen as _].hash(state); } } impl PartialEq for vnstat { fn eq(&self, other: &vnstat) -> bool { let self_vn_devname: &[::c_char] = &self.vn_devname; let other_vn_devname: &[::c_char] = &other.vn_devname; self.vn_fileid == other.vn_fileid && self.vn_size == other.vn_size && self.vn_dev == other.vn_dev && self.vn_fsid == other.vn_fsid && self.vn_mntdir == other.vn_mntdir && self.vn_type == other.vn_type && self.vn_mode == other.vn_mode && self_vn_devname == other_vn_devname } } impl Eq for vnstat {} impl ::fmt::Debug for vnstat { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { let self_vn_devname: &[::c_char] = &self.vn_devname; f.debug_struct("vnstat") .field("vn_fileid", &self.vn_fileid) .field("vn_size", &self.vn_size) .field("vn_dev", &self.vn_dev) .field("vn_fsid", &self.vn_fsid) .field("vn_mntdir", &self.vn_mntdir) .field("vn_type", &self.vn_type) .field("vn_mode", &self.vn_mode) .field("vn_devname", &self_vn_devname) .finish() } } impl ::hash::Hash for vnstat { fn hash(&self, state: &mut H) { let self_vn_devname: &[::c_char] = &self.vn_devname; self.vn_fileid.hash(state); self.vn_size.hash(state); self.vn_dev.hash(state); self.vn_fsid.hash(state); self.vn_mntdir.hash(state); self.vn_type.hash(state); self.vn_mode.hash(state); self_vn_devname.hash(state); } } } } pub const RAND_MAX: ::c_int = 0x7fff_fffd; pub const ELAST: ::c_int = 97; /// max length of devicename pub const SPECNAMELEN: ::c_int = 63; pub const KI_NSPARE_PTR: usize = 6; pub const MINCORE_SUPER: ::c_int = 0x20; safe_f! { pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t { let major = major as ::dev_t; let minor = minor as ::dev_t; let mut dev = 0; dev |= ((major & 0xffffff00) as dev_t) << 32; dev |= ((major & 0x000000ff) as dev_t) << 8; dev |= ((minor & 0x0000ff00) as dev_t) << 24; dev |= ((minor & 0xffff00ff) as dev_t) << 0; dev } } f! { pub fn major(dev: ::dev_t) -> ::c_int { (((dev >> 32) & 0xffffff00) | ((dev >> 8) & 0xff)) as ::c_int } pub fn minor(dev: ::dev_t) -> ::c_int { (((dev >> 24) & 0xff00) | (dev & 0xffff00ff)) as ::c_int } } extern "C" { pub fn setgrent(); pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int; pub fn freelocale(loc: ::locale_t); pub fn msgrcv( msqid: ::c_int, msgp: *mut ::c_void, msgsz: ::size_t, msgtyp: ::c_long, msgflg: ::c_int, ) -> ::ssize_t; pub fn dirname(path: *mut ::c_char) -> *mut ::c_char; pub fn basename(path: *mut ::c_char) -> *mut ::c_char; } cfg_if! { if #[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))] { mod b64; pub use self::b64::*; } } cfg_if! { if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } } libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs0000644000175000017500000000153414661133735023406 0ustar jamespagejamespage#[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_nlink: ::nlink_t, pub st_mode: ::mode_t, st_padding0: i16, pub st_uid: ::uid_t, pub st_gid: ::gid_t, st_padding1: i32, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u64, pub st_spare: [u64; 10], } impl ::Copy for ::stat {} impl ::Clone for ::stat { fn clone(&self) -> ::stat { *self } } libc/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs0000644000175000017500000000237114661133735023067 0ustar jamespagejamespagepub type c_char = u8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = i32; pub type time_t = i64; pub type suseconds_t = i64; pub type register_t = i64; s! { pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_atime: ::time_t, pub st_atime_nsec: ::c_long, pub st_mtime: ::time_t, pub st_mtime_nsec: ::c_long, pub st_ctime: ::time_t, pub st_ctime_nsec: ::c_long, pub st_size: ::off_t, pub st_blocks: ::blkcnt_t, pub st_blksize: ::blksize_t, pub st_flags: ::fflags_t, pub st_gen: u32, pub st_lspare: i32, pub st_birthtime: ::time_t, pub st_birthtime_nsec: ::c_long, } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const MAP_32BIT: ::c_int = 0x00080000; pub const MINSIGSTKSZ: ::size_t = 2048; // 512 * 4 libc/src/unix/bsd/freebsdlike/freebsd/x86_64/0000775000175000017500000000000014661133735021625 5ustar jamespagejamespagelibc/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs0000644000175000017500000002531114661133735022752 0ustar jamespagejamespagepub type c_char = i8; pub type c_long = i64; pub type c_ulong = u64; pub type wchar_t = i32; pub type time_t = i64; pub type suseconds_t = i64; pub type register_t = i64; s! { pub struct reg32 { pub r_fs: u32, pub r_es: u32, pub r_ds: u32, pub r_edi: u32, pub r_esi: u32, pub r_ebp: u32, pub r_isp: u32, pub r_ebx: u32, pub r_edx: u32, pub r_ecx: u32, pub r_eax: u32, pub r_trapno: u32, pub r_err: u32, pub r_eip: u32, pub r_cs: u32, pub r_eflags: u32, pub r_esp: u32, pub r_ss: u32, pub r_gs: u32, } pub struct reg { pub r_r15: i64, pub r_r14: i64, pub r_r13: i64, pub r_r12: i64, pub r_r11: i64, pub r_r10: i64, pub r_r9: i64, pub r_r8: i64, pub r_rdi: i64, pub r_rsi: i64, pub r_rbp: i64, pub r_rbx: i64, pub r_rdx: i64, pub r_rcx: i64, pub r_rax: i64, pub r_trapno: u32, pub r_fs: u16, pub r_gs: u16, pub r_err: u32, pub r_es: u16, pub r_ds: u16, pub r_rip: i64, pub r_cs: i64, pub r_rflags: i64, pub r_rsp: i64, pub r_ss: i64, } } s_no_extra_traits! { pub struct fpreg32 { pub fpr_env: [u32; 7], pub fpr_acc: [[u8; 10]; 8], pub fpr_ex_sw: u32, pub fpr_pad: [u8; 64], } pub struct fpreg { pub fpr_env: [u64; 4], pub fpr_acc: [[u8; 16]; 8], pub fpr_xacc: [[u8; 16]; 16], pub fpr_spare: [u64; 12], } pub struct xmmreg { pub xmm_env: [u32; 8], pub xmm_acc: [[u8; 16]; 8], pub xmm_reg: [[u8; 16]; 8], pub xmm_pad: [u8; 224], } #[cfg(libc_union)] pub union __c_anonymous_elf64_auxv_union { pub a_val: ::c_long, pub a_ptr: *mut ::c_void, pub a_fcn: extern "C" fn(), } pub struct Elf64_Auxinfo { pub a_type: ::c_long, #[cfg(libc_union)] pub a_un: __c_anonymous_elf64_auxv_union, } pub struct kinfo_file { pub kf_structsize: ::c_int, pub kf_type: ::c_int, pub kf_fd: ::c_int, pub kf_ref_count: ::c_int, pub kf_flags: ::c_int, _kf_pad0: ::c_int, pub kf_offset: i64, _priv: [::uintptr_t; 38], // FIXME if needed pub kf_status: u16, _kf_pad1: u16, _kf_ispare0: ::c_int, pub kf_cap_rights: ::cap_rights_t, _kf_cap_spare: u64, pub kf_path: [::c_char; ::PATH_MAX as usize], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for fpreg32 { fn eq(&self, other: &fpreg32) -> bool { self.fpr_env == other.fpr_env && self.fpr_acc == other.fpr_acc && self.fpr_ex_sw == other.fpr_ex_sw && self.fpr_pad .iter() .zip(other.fpr_pad.iter()) .all(|(a,b)| a == b) } } impl Eq for fpreg32 {} impl ::fmt::Debug for fpreg32 { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpreg32") .field("fpr_env", &&self.fpr_env[..]) .field("fpr_acc", &self.fpr_acc) .field("fpr_ex_sw", &self.fpr_ex_sw) .field("fpr_pad", &&self.fpr_pad[..]) .finish() } } impl ::hash::Hash for fpreg32 { fn hash(&self, state: &mut H) { self.fpr_env.hash(state); self.fpr_acc.hash(state); self.fpr_ex_sw.hash(state); self.fpr_pad.hash(state); } } impl PartialEq for fpreg { fn eq(&self, other: &fpreg) -> bool { self.fpr_env == other.fpr_env && self.fpr_acc == other.fpr_acc && self.fpr_xacc == other.fpr_xacc && self.fpr_spare == other.fpr_spare } } impl Eq for fpreg {} impl ::fmt::Debug for fpreg { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("fpreg") .field("fpr_env", &self.fpr_env) .field("fpr_acc", &self.fpr_acc) .field("fpr_xacc", &self.fpr_xacc) .field("fpr_spare", &self.fpr_spare) .finish() } } impl ::hash::Hash for fpreg { fn hash(&self, state: &mut H) { self.fpr_env.hash(state); self.fpr_acc.hash(state); self.fpr_xacc.hash(state); self.fpr_spare.hash(state); } } impl PartialEq for xmmreg { fn eq(&self, other: &xmmreg) -> bool { self.xmm_env == other.xmm_env && self.xmm_acc == other.xmm_acc && self.xmm_reg == other.xmm_reg && self.xmm_pad .iter() .zip(other.xmm_pad.iter()) .all(|(a,b)| a == b) } } impl Eq for xmmreg {} impl ::fmt::Debug for xmmreg { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("xmmreg") .field("xmm_env", &self.xmm_env) .field("xmm_acc", &self.xmm_acc) .field("xmm_reg", &self.xmm_reg) .field("xmm_pad", &&self.xmm_pad[..]) .finish() } } impl ::hash::Hash for xmmreg { fn hash(&self, state: &mut H) { self.xmm_env.hash(state); self.xmm_acc.hash(state); self.xmm_reg.hash(state); self.xmm_pad.hash(state); } } #[cfg(libc_union)] impl PartialEq for __c_anonymous_elf64_auxv_union { fn eq(&self, other: &__c_anonymous_elf64_auxv_union) -> bool { unsafe { self.a_val == other.a_val || self.a_ptr == other.a_ptr || self.a_fcn == other.a_fcn } } } #[cfg(libc_union)] impl Eq for __c_anonymous_elf64_auxv_union {} #[cfg(libc_union)] impl ::fmt::Debug for __c_anonymous_elf64_auxv_union { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("a_val") .field("a_val", unsafe { &self.a_val }) .finish() } } #[cfg(not(libc_union))] impl PartialEq for Elf64_Auxinfo { fn eq(&self, other: &Elf64_Auxinfo) -> bool { self.a_type == other.a_type } } #[cfg(libc_union)] impl PartialEq for Elf64_Auxinfo { fn eq(&self, other: &Elf64_Auxinfo) -> bool { self.a_type == other.a_type && self.a_un == other.a_un } } impl Eq for Elf64_Auxinfo {} #[cfg(not(libc_union))] impl ::fmt::Debug for Elf64_Auxinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("Elf64_Auxinfo") .field("a_type", &self.a_type) .finish() } } #[cfg(libc_union)] impl ::fmt::Debug for Elf64_Auxinfo { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("Elf64_Auxinfo") .field("a_type", &self.a_type) .field("a_un", &self.a_un) .finish() } } impl PartialEq for kinfo_file { fn eq(&self, other: &kinfo_file) -> bool { self.kf_structsize == other.kf_structsize && self.kf_type == other.kf_type && self.kf_fd == other.kf_fd && self.kf_ref_count == other.kf_ref_count && self.kf_flags == other.kf_flags && self.kf_offset == other.kf_offset && self.kf_status == other.kf_status && self.kf_cap_rights == other.kf_cap_rights && self.kf_path .iter() .zip(other.kf_path.iter()) .all(|(a,b)| a == b) } } impl Eq for kinfo_file {} impl ::fmt::Debug for kinfo_file { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("kinfo_file") .field("kf_structsize", &self.kf_structsize) .field("kf_type", &self.kf_type) .field("kf_fd", &self.kf_fd) .field("kf_ref_count", &self.kf_ref_count) .field("kf_flags", &self.kf_flags) .field("kf_offset", &self.kf_offset) .field("kf_status", &self.kf_status) .field("kf_cap_rights", &self.kf_cap_rights) .field("kf_path", &&self.kf_path[..]) .finish() } } impl ::hash::Hash for kinfo_file { fn hash(&self, state: &mut H) { self.kf_structsize.hash(state); self.kf_type.hash(state); self.kf_fd.hash(state); self.kf_ref_count.hash(state); self.kf_flags.hash(state); self.kf_offset.hash(state); self.kf_status.hash(state); self.kf_cap_rights.hash(state); self.kf_path.hash(state); } } } } // should be pub(crate), but that requires Rust 1.18.0 cfg_if! { if #[cfg(libc_const_size_of)] { #[doc(hidden)] pub const _ALIGNBYTES: usize = ::mem::size_of::<::c_long>() - 1; } else { #[doc(hidden)] pub const _ALIGNBYTES: usize = 8 - 1; } } pub const MAP_32BIT: ::c_int = 0x00080000; pub const MINSIGSTKSZ: ::size_t = 2048; // 512 * 4 pub const _MC_HASSEGS: u32 = 0x1; pub const _MC_HASBASES: u32 = 0x2; pub const _MC_HASFPXSTATE: u32 = 0x4; pub const _MC_FLAG_MASK: u32 = _MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE; pub const _MC_FPFMT_NODEV: c_long = 0x10000; pub const _MC_FPFMT_XMM: c_long = 0x10002; pub const _MC_FPOWNED_NONE: c_long = 0x20000; pub const _MC_FPOWNED_FPU: c_long = 0x20001; pub const _MC_FPOWNED_PCB: c_long = 0x20002; cfg_if! { if #[cfg(libc_align)] { mod align; pub use self::align::*; } } libc/src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs0000644000175000017500000001717514661133735023276 0ustar jamespagejamespageuse {c_long, register_t}; s_no_extra_traits! { #[allow(missing_debug_implementations)] #[repr(align(16))] pub struct max_align_t { priv_: [f64; 4] } #[repr(align(16))] pub struct mcontext_t { pub mc_onstack: register_t, pub mc_rdi: register_t, pub mc_rsi: register_t, pub mc_rdx: register_t, pub mc_rcx: register_t, pub mc_r8: register_t, pub mc_r9: register_t, pub mc_rax: register_t, pub mc_rbx: register_t, pub mc_rbp: register_t, pub mc_r10: register_t, pub mc_r11: register_t, pub mc_r12: register_t, pub mc_r13: register_t, pub mc_r14: register_t, pub mc_r15: register_t, pub mc_trapno: u32, pub mc_fs: u16, pub mc_gs: u16, pub mc_addr: register_t, pub mc_flags: u32, pub mc_es: u16, pub mc_ds: u16, pub mc_err: register_t, pub mc_rip: register_t, pub mc_cs: register_t, pub mc_rflags: register_t, pub mc_rsp: register_t, pub mc_ss: register_t, pub mc_len: c_long, pub mc_fpformat: c_long, pub mc_ownedfp: c_long, pub mc_fpstate: [c_long; 64], pub mc_fsbase: register_t, pub mc_gsbase: register_t, pub mc_xfpustate: register_t, pub mc_xfpustate_len: register_t, pub mc_spare: [c_long; 4], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for mcontext_t { fn eq(&self, other: &mcontext_t) -> bool { self.mc_onstack == other.mc_onstack && self.mc_rdi == other.mc_rdi && self.mc_rsi == other.mc_rsi && self.mc_rdx == other.mc_rdx && self.mc_rcx == other.mc_rcx && self.mc_r8 == other.mc_r8 && self.mc_r9 == other.mc_r9 && self.mc_rax == other.mc_rax && self.mc_rbx == other.mc_rbx && self.mc_rbp == other.mc_rbp && self.mc_r10 == other.mc_r10 && self.mc_r11 == other.mc_r11 && self.mc_r12 == other.mc_r12 && self.mc_r13 == other.mc_r13 && self.mc_r14 == other.mc_r14 && self.mc_r15 == other.mc_r15 && self.mc_trapno == other.mc_trapno && self.mc_fs == other.mc_fs && self.mc_gs == other.mc_gs && self.mc_addr == other.mc_addr && self.mc_flags == other.mc_flags && self.mc_es == other.mc_es && self.mc_ds == other.mc_ds && self.mc_err == other.mc_err && self.mc_rip == other.mc_rip && self.mc_cs == other.mc_cs && self.mc_rflags == other.mc_rflags && self.mc_rsp == other.mc_rsp && self.mc_ss == other.mc_ss && self.mc_len == other.mc_len && self.mc_fpformat == other.mc_fpformat && self.mc_ownedfp == other.mc_ownedfp && self.mc_fpstate.iter().zip(other.mc_fpstate.iter()) .all(|(a, b)| a == b) && self.mc_fsbase == other.mc_fsbase && self.mc_gsbase == other.mc_gsbase && self.mc_xfpustate == other.mc_xfpustate && self.mc_xfpustate_len == other.mc_xfpustate_len && self.mc_spare == other.mc_spare } } impl Eq for mcontext_t {} impl ::fmt::Debug for mcontext_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("mcontext_t") .field("mc_onstack", &self.mc_onstack) .field("mc_rdi", &self.mc_rdi) .field("mc_rsi", &self.mc_rsi) .field("mc_rdx", &self.mc_rdx) .field("mc_rcx", &self.mc_rcx) .field("mc_r8", &self.mc_r8) .field("mc_r9", &self.mc_r9) .field("mc_rax", &self.mc_rax) .field("mc_rbx", &self.mc_rbx) .field("mc_rbp", &self.mc_rbp) .field("mc_r10", &self.mc_r10) .field("mc_r11", &self.mc_r11) .field("mc_r12", &self.mc_r12) .field("mc_r13", &self.mc_r13) .field("mc_r14", &self.mc_r14) .field("mc_r15", &self.mc_r15) .field("mc_trapno", &self.mc_trapno) .field("mc_fs", &self.mc_fs) .field("mc_gs", &self.mc_gs) .field("mc_addr", &self.mc_addr) .field("mc_flags", &self.mc_flags) .field("mc_es", &self.mc_es) .field("mc_ds", &self.mc_ds) .field("mc_err", &self.mc_err) .field("mc_rip", &self.mc_rip) .field("mc_cs", &self.mc_cs) .field("mc_rflags", &self.mc_rflags) .field("mc_rsp", &self.mc_rsp) .field("mc_ss", &self.mc_ss) .field("mc_len", &self.mc_len) .field("mc_fpformat", &self.mc_fpformat) .field("mc_ownedfp", &self.mc_ownedfp) // FIXME: .field("mc_fpstate", &self.mc_fpstate) .field("mc_fsbase", &self.mc_fsbase) .field("mc_gsbase", &self.mc_gsbase) .field("mc_xfpustate", &self.mc_xfpustate) .field("mc_xfpustate_len", &self.mc_xfpustate_len) .field("mc_spare", &self.mc_spare) .finish() } } impl ::hash::Hash for mcontext_t { fn hash(&self, state: &mut H) { self.mc_onstack.hash(state); self.mc_rdi.hash(state); self.mc_rsi.hash(state); self.mc_rdx.hash(state); self.mc_rcx.hash(state); self.mc_r8.hash(state); self.mc_r9.hash(state); self.mc_rax.hash(state); self.mc_rbx.hash(state); self.mc_rbp.hash(state); self.mc_r10.hash(state); self.mc_r11.hash(state); self.mc_r12.hash(state); self.mc_r13.hash(state); self.mc_r14.hash(state); self.mc_r15.hash(state); self.mc_trapno.hash(state); self.mc_fs.hash(state); self.mc_gs.hash(state); self.mc_addr.hash(state); self.mc_flags.hash(state); self.mc_es.hash(state); self.mc_ds.hash(state); self.mc_err.hash(state); self.mc_rip.hash(state); self.mc_cs.hash(state); self.mc_rflags.hash(state); self.mc_rsp.hash(state); self.mc_ss.hash(state); self.mc_len.hash(state); self.mc_fpformat.hash(state); self.mc_ownedfp.hash(state); self.mc_fpstate.hash(state); self.mc_fsbase.hash(state); self.mc_gsbase.hash(state); self.mc_xfpustate.hash(state); self.mc_xfpustate_len.hash(state); self.mc_spare.hash(state); } } } } s! { pub struct ucontext_t { pub uc_sigmask: ::sigset_t, pub uc_mcontext: ::mcontext_t, pub uc_link: *mut ::ucontext_t, pub uc_stack: ::stack_t, pub uc_flags: ::c_int, __spare__: [::c_int; 4], } } libc/src/unix/bsd/freebsdlike/mod.rs0000644000175000017500000017451614661133735020416 0ustar jamespagejamespagepub type mode_t = u16; pub type pthread_attr_t = *mut ::c_void; pub type rlim_t = i64; pub type pthread_mutex_t = *mut ::c_void; pub type pthread_mutexattr_t = *mut ::c_void; pub type pthread_cond_t = *mut ::c_void; pub type pthread_condattr_t = *mut ::c_void; pub type pthread_rwlock_t = *mut ::c_void; pub type pthread_rwlockattr_t = *mut ::c_void; pub type pthread_key_t = ::c_int; pub type tcflag_t = ::c_uint; pub type speed_t = ::c_uint; pub type nl_item = ::c_int; pub type id_t = i64; pub type vm_size_t = ::uintptr_t; pub type key_t = ::c_long; // elf.h pub type Elf32_Addr = u32; pub type Elf32_Half = u16; pub type Elf32_Lword = u64; pub type Elf32_Off = u32; pub type Elf32_Sword = i32; pub type Elf32_Word = u32; pub type Elf64_Addr = u64; pub type Elf64_Half = u16; pub type Elf64_Lword = u64; pub type Elf64_Off = u64; pub type Elf64_Sword = i32; pub type Elf64_Sxword = i64; pub type Elf64_Word = u32; pub type Elf64_Xword = u64; pub type iconv_t = *mut ::c_void; // It's an alias over "struct __kvm_t". However, its fields aren't supposed to be used directly, // making the type definition system dependent. Better not bind it exactly. pub type kvm_t = ::c_void; cfg_if! { if #[cfg(target_pointer_width = "64")] { type Elf_Addr = Elf64_Addr; type Elf_Half = Elf64_Half; type Elf_Phdr = Elf64_Phdr; } else if #[cfg(target_pointer_width = "32")] { type Elf_Addr = Elf32_Addr; type Elf_Half = Elf32_Half; type Elf_Phdr = Elf32_Phdr; } } // link.h #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum timezone {} impl ::Copy for timezone {} impl ::Clone for timezone { fn clone(&self) -> timezone { *self } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { self.si_addr } pub unsafe fn si_value(&self) -> ::sigval { self.si_value } pub unsafe fn si_pid(&self) -> ::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.si_status } } s! { pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct ip_mreqn { pub imr_multiaddr: in_addr, pub imr_address: in_addr, pub imr_ifindex: ::c_int, } pub struct ip_mreq_source { pub imr_multiaddr: in_addr, pub imr_sourceaddr: in_addr, pub imr_interface: in_addr, } pub struct glob_t { pub gl_pathc: ::size_t, pub gl_matchc: ::size_t, pub gl_offs: ::size_t, pub gl_flags: ::c_int, pub gl_pathv: *mut *mut ::c_char, __unused3: *mut ::c_void, __unused4: *mut ::c_void, __unused5: *mut ::c_void, __unused6: *mut ::c_void, __unused7: *mut ::c_void, __unused8: *mut ::c_void, } pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: ::socklen_t, pub ai_canonname: *mut ::c_char, pub ai_addr: *mut ::sockaddr, pub ai_next: *mut addrinfo, } pub struct sigset_t { bits: [u32; 4], } pub struct siginfo_t { pub si_signo: ::c_int, pub si_errno: ::c_int, pub si_code: ::c_int, pub si_pid: ::pid_t, pub si_uid: ::uid_t, pub si_status: ::c_int, pub si_addr: *mut ::c_void, pub si_value: ::sigval, _pad1: ::c_long, _pad2: [::c_int; 7], } pub struct sigaction { pub sa_sigaction: ::sighandler_t, pub sa_flags: ::c_int, pub sa_mask: sigset_t, } pub struct sched_param { pub sched_priority: ::c_int, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [::c_char; 8], } pub struct termios { pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_cc: [::cc_t; ::NCCS], pub c_ispeed: ::speed_t, pub c_ospeed: ::speed_t, } pub struct flock { pub l_start: ::off_t, pub l_len: ::off_t, pub l_pid: ::pid_t, pub l_type: ::c_short, pub l_whence: ::c_short, #[cfg(not(target_os = "dragonfly"))] pub l_sysid: ::c_int, } pub struct sf_hdtr { pub headers: *mut ::iovec, pub hdr_cnt: ::c_int, pub trailers: *mut ::iovec, pub trl_cnt: ::c_int, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, pub int_n_sign_posn: ::c_char, } pub struct cmsgcred { pub cmcred_pid: ::pid_t, pub cmcred_uid: ::uid_t, pub cmcred_euid: ::uid_t, pub cmcred_gid: ::gid_t, pub cmcred_ngroups: ::c_short, pub cmcred_groups: [::gid_t; CMGROUP_MAX], } pub struct rtprio { pub type_: ::c_ushort, pub prio: ::c_ushort, } pub struct in6_pktinfo { pub ipi6_addr: ::in6_addr, pub ipi6_ifindex: ::c_uint, } pub struct arphdr { pub ar_hrd: u16, pub ar_pro: u16, pub ar_hln: u8, pub ar_pln: u8, pub ar_op: u16, } pub struct timex { pub modes: ::c_uint, pub offset: ::c_long, pub freq: ::c_long, pub maxerror: ::c_long, pub esterror: ::c_long, pub status: ::c_int, pub constant: ::c_long, pub precision: ::c_long, pub tolerance: ::c_long, pub ppsfreq: ::c_long, pub jitter: ::c_long, pub shift: ::c_int, pub stabil: ::c_long, pub jitcnt: ::c_long, pub calcnt: ::c_long, pub errcnt: ::c_long, pub stbcnt: ::c_long, } pub struct ntptimeval { pub time: ::timespec, pub maxerror: ::c_long, pub esterror: ::c_long, pub tai: ::c_long, pub time_state: ::c_int, } pub struct accept_filter_arg { pub af_name: [::c_char; 16], af_arg: [[::c_char; 10]; 24], } pub struct ptrace_io_desc { pub piod_op: ::c_int, pub piod_offs: *mut ::c_void, pub piod_addr: *mut ::c_void, pub piod_len: ::size_t, } // bpf.h pub struct bpf_program { pub bf_len: ::c_uint, pub bf_insns: *mut bpf_insn, } pub struct bpf_stat { pub bs_recv: ::c_uint, pub bs_drop: ::c_uint, } pub struct bpf_version { pub bv_major: ::c_ushort, pub bv_minor: ::c_ushort, } pub struct bpf_hdr { pub bh_tstamp: ::timeval, pub bh_caplen: u32, pub bh_datalen: u32, pub bh_hdrlen: ::c_ushort, } pub struct bpf_insn { pub code: ::c_ushort, pub jt: ::c_uchar, pub jf: ::c_uchar, pub k: u32, } pub struct bpf_dltlist { bfl_len: ::c_uint, bfl_list: *mut ::c_uint, } // elf.h pub struct Elf32_Phdr { pub p_type: Elf32_Word, pub p_offset: Elf32_Off, pub p_vaddr: Elf32_Addr, pub p_paddr: Elf32_Addr, pub p_filesz: Elf32_Word, pub p_memsz: Elf32_Word, pub p_flags: Elf32_Word, pub p_align: Elf32_Word, } pub struct Elf64_Phdr { pub p_type: Elf64_Word, pub p_flags: Elf64_Word, pub p_offset: Elf64_Off, pub p_vaddr: Elf64_Addr, pub p_paddr: Elf64_Addr, pub p_filesz: Elf64_Xword, pub p_memsz: Elf64_Xword, pub p_align: Elf64_Xword, } // link.h pub struct dl_phdr_info { pub dlpi_addr: Elf_Addr, pub dlpi_name: *const ::c_char, pub dlpi_phdr: *const Elf_Phdr, pub dlpi_phnum: Elf_Half, pub dlpi_adds: ::c_ulonglong, pub dlpi_subs: ::c_ulonglong, pub dlpi_tls_modid: usize, pub dlpi_tls_data: *mut ::c_void, } pub struct ipc_perm { pub cuid: ::uid_t, pub cgid: ::gid_t, pub uid: ::uid_t, pub gid: ::gid_t, pub mode: ::mode_t, pub seq: ::c_ushort, pub key: ::key_t, } pub struct eui64 { pub octet: [u8; EUI64_LEN], } } s_no_extra_traits! { pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: ::sa_family_t, __ss_pad1: [u8; 6], __ss_align: i64, __ss_pad2: [u8; 112], } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl PartialEq for sockaddr_storage { fn eq(&self, other: &sockaddr_storage) -> bool { self.ss_len == other.ss_len && self.ss_family == other.ss_family && self.__ss_pad1 == other.__ss_pad1 && self.__ss_align == other.__ss_align && self .__ss_pad2 .iter() .zip(other.__ss_pad2.iter()) .all(|(a, b)| a == b) } } impl Eq for sockaddr_storage {} impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &self.__ss_pad1) .field("__ss_align", &self.__ss_align) // FIXME: .field("__ss_pad2", &self.__ss_pad2) .finish() } } impl ::hash::Hash for sockaddr_storage { fn hash(&self, state: &mut H) { self.ss_len.hash(state); self.ss_family.hash(state); self.__ss_pad1.hash(state); self.__ss_align.hash(state); self.__ss_pad2.hash(state); } } } } // Non-public helper constant cfg_if! { if #[cfg(all(not(libc_const_size_of), target_pointer_width = "32"))] { const SIZEOF_LONG: usize = 4; } else if #[cfg(all(not(libc_const_size_of), target_pointer_width = "64"))] { const SIZEOF_LONG: usize = 8; } else if #[cfg(libc_const_size_of)] { const SIZEOF_LONG: usize = ::mem::size_of::<::c_long>(); } } #[deprecated( since = "0.2.64", note = "Can vary at runtime. Use sysconf(3) instead" )] pub const AIO_LISTIO_MAX: ::c_int = 16; pub const AIO_CANCELED: ::c_int = 1; pub const AIO_NOTCANCELED: ::c_int = 2; pub const AIO_ALLDONE: ::c_int = 3; pub const LIO_NOP: ::c_int = 0; pub const LIO_WRITE: ::c_int = 1; pub const LIO_READ: ::c_int = 2; pub const LIO_WAIT: ::c_int = 1; pub const LIO_NOWAIT: ::c_int = 0; pub const SIGEV_NONE: ::c_int = 0; pub const SIGEV_SIGNAL: ::c_int = 1; pub const SIGEV_THREAD: ::c_int = 2; pub const SIGEV_KEVENT: ::c_int = 3; pub const CODESET: ::nl_item = 0; pub const D_T_FMT: ::nl_item = 1; pub const D_FMT: ::nl_item = 2; pub const T_FMT: ::nl_item = 3; pub const T_FMT_AMPM: ::nl_item = 4; pub const AM_STR: ::nl_item = 5; pub const PM_STR: ::nl_item = 6; pub const DAY_1: ::nl_item = 7; pub const DAY_2: ::nl_item = 8; pub const DAY_3: ::nl_item = 9; pub const DAY_4: ::nl_item = 10; pub const DAY_5: ::nl_item = 11; pub const DAY_6: ::nl_item = 12; pub const DAY_7: ::nl_item = 13; pub const ABDAY_1: ::nl_item = 14; pub const ABDAY_2: ::nl_item = 15; pub const ABDAY_3: ::nl_item = 16; pub const ABDAY_4: ::nl_item = 17; pub const ABDAY_5: ::nl_item = 18; pub const ABDAY_6: ::nl_item = 19; pub const ABDAY_7: ::nl_item = 20; pub const MON_1: ::nl_item = 21; pub const MON_2: ::nl_item = 22; pub const MON_3: ::nl_item = 23; pub const MON_4: ::nl_item = 24; pub const MON_5: ::nl_item = 25; pub const MON_6: ::nl_item = 26; pub const MON_7: ::nl_item = 27; pub const MON_8: ::nl_item = 28; pub const MON_9: ::nl_item = 29; pub const MON_10: ::nl_item = 30; pub const MON_11: ::nl_item = 31; pub const MON_12: ::nl_item = 32; pub const ABMON_1: ::nl_item = 33; pub const ABMON_2: ::nl_item = 34; pub const ABMON_3: ::nl_item = 35; pub const ABMON_4: ::nl_item = 36; pub const ABMON_5: ::nl_item = 37; pub const ABMON_6: ::nl_item = 38; pub const ABMON_7: ::nl_item = 39; pub const ABMON_8: ::nl_item = 40; pub const ABMON_9: ::nl_item = 41; pub const ABMON_10: ::nl_item = 42; pub const ABMON_11: ::nl_item = 43; pub const ABMON_12: ::nl_item = 44; pub const ERA: ::nl_item = 45; pub const ERA_D_FMT: ::nl_item = 46; pub const ERA_D_T_FMT: ::nl_item = 47; pub const ERA_T_FMT: ::nl_item = 48; pub const ALT_DIGITS: ::nl_item = 49; pub const RADIXCHAR: ::nl_item = 50; pub const THOUSEP: ::nl_item = 51; pub const YESEXPR: ::nl_item = 52; pub const NOEXPR: ::nl_item = 53; pub const YESSTR: ::nl_item = 54; pub const NOSTR: ::nl_item = 55; pub const CRNCYSTR: ::nl_item = 56; pub const D_MD_ORDER: ::nl_item = 57; pub const ALTMON_1: ::nl_item = 58; pub const ALTMON_2: ::nl_item = 59; pub const ALTMON_3: ::nl_item = 60; pub const ALTMON_4: ::nl_item = 61; pub const ALTMON_5: ::nl_item = 62; pub const ALTMON_6: ::nl_item = 63; pub const ALTMON_7: ::nl_item = 64; pub const ALTMON_8: ::nl_item = 65; pub const ALTMON_9: ::nl_item = 66; pub const ALTMON_10: ::nl_item = 67; pub const ALTMON_11: ::nl_item = 68; pub const ALTMON_12: ::nl_item = 69; pub const EXIT_FAILURE: ::c_int = 1; pub const EXIT_SUCCESS: ::c_int = 0; pub const EOF: ::c_int = -1; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const SEEK_DATA: ::c_int = 3; pub const SEEK_HOLE: ::c_int = 4; pub const _IOFBF: ::c_int = 0; pub const _IONBF: ::c_int = 2; pub const _IOLBF: ::c_int = 1; pub const BUFSIZ: ::c_uint = 1024; pub const FOPEN_MAX: ::c_uint = 20; pub const FILENAME_MAX: ::c_uint = 1024; pub const L_tmpnam: ::c_uint = 1024; pub const TMP_MAX: ::c_uint = 308915776; pub const O_NOCTTY: ::c_int = 32768; pub const O_DIRECT: ::c_int = 0x00010000; pub const S_IFIFO: mode_t = 4096; pub const S_IFCHR: mode_t = 8192; pub const S_IFBLK: mode_t = 24576; pub const S_IFDIR: mode_t = 16384; pub const S_IFREG: mode_t = 32768; pub const S_IFLNK: mode_t = 40960; pub const S_IFSOCK: mode_t = 49152; pub const S_IFMT: mode_t = 61440; pub const S_IEXEC: mode_t = 64; pub const S_IWRITE: mode_t = 128; pub const S_IREAD: mode_t = 256; pub const S_IRWXU: mode_t = 448; pub const S_IXUSR: mode_t = 64; pub const S_IWUSR: mode_t = 128; pub const S_IRUSR: mode_t = 256; pub const S_IRWXG: mode_t = 56; pub const S_IXGRP: mode_t = 8; pub const S_IWGRP: mode_t = 16; pub const S_IRGRP: mode_t = 32; pub const S_IRWXO: mode_t = 7; pub const S_IXOTH: mode_t = 1; pub const S_IWOTH: mode_t = 2; pub const S_IROTH: mode_t = 4; pub const F_OK: ::c_int = 0; pub const R_OK: ::c_int = 4; pub const W_OK: ::c_int = 2; pub const X_OK: ::c_int = 1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const F_LOCK: ::c_int = 1; pub const F_TEST: ::c_int = 3; pub const F_TLOCK: ::c_int = 2; pub const F_ULOCK: ::c_int = 0; pub const F_DUPFD_CLOEXEC: ::c_int = 17; pub const F_DUP2FD: ::c_int = 10; pub const F_DUP2FD_CLOEXEC: ::c_int = 18; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGSEGV: ::c_int = 11; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const PROT_NONE: ::c_int = 0; pub const PROT_READ: ::c_int = 1; pub const PROT_WRITE: ::c_int = 2; pub const PROT_EXEC: ::c_int = 4; pub const MAP_FILE: ::c_int = 0x0000; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_ANON: ::c_int = 0x1000; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; pub const MCL_CURRENT: ::c_int = 0x0001; pub const MCL_FUTURE: ::c_int = 0x0002; pub const MNT_EXPUBLIC: ::c_int = 0x20000000; pub const MNT_NOATIME: ::c_int = 0x10000000; pub const MNT_NOCLUSTERR: ::c_int = 0x40000000; pub const MNT_NOCLUSTERW: ::c_int = 0x80000000; pub const MNT_NOSYMFOLLOW: ::c_int = 0x00400000; pub const MNT_SOFTDEP: ::c_int = 0x00200000; pub const MNT_SUIDDIR: ::c_int = 0x00100000; pub const MNT_EXRDONLY: ::c_int = 0x00000080; pub const MNT_DEFEXPORTED: ::c_int = 0x00000200; pub const MNT_EXPORTANON: ::c_int = 0x00000400; pub const MNT_EXKERB: ::c_int = 0x00000800; pub const MNT_DELEXPORT: ::c_int = 0x00020000; pub const MS_SYNC: ::c_int = 0x0000; pub const MS_ASYNC: ::c_int = 0x0001; pub const MS_INVALIDATE: ::c_int = 0x0002; pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EDEADLK: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const ENOTBLK: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const EAGAIN: ::c_int = 35; pub const EWOULDBLOCK: ::c_int = 35; pub const EINPROGRESS: ::c_int = 36; pub const EALREADY: ::c_int = 37; pub const ENOTSOCK: ::c_int = 38; pub const EDESTADDRREQ: ::c_int = 39; pub const EMSGSIZE: ::c_int = 40; pub const EPROTOTYPE: ::c_int = 41; pub const ENOPROTOOPT: ::c_int = 42; pub const EPROTONOSUPPORT: ::c_int = 43; pub const ESOCKTNOSUPPORT: ::c_int = 44; pub const EOPNOTSUPP: ::c_int = 45; pub const ENOTSUP: ::c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: ::c_int = 46; pub const EAFNOSUPPORT: ::c_int = 47; pub const EADDRINUSE: ::c_int = 48; pub const EADDRNOTAVAIL: ::c_int = 49; pub const ENETDOWN: ::c_int = 50; pub const ENETUNREACH: ::c_int = 51; pub const ENETRESET: ::c_int = 52; pub const ECONNABORTED: ::c_int = 53; pub const ECONNRESET: ::c_int = 54; pub const ENOBUFS: ::c_int = 55; pub const EISCONN: ::c_int = 56; pub const ENOTCONN: ::c_int = 57; pub const ESHUTDOWN: ::c_int = 58; pub const ETOOMANYREFS: ::c_int = 59; pub const ETIMEDOUT: ::c_int = 60; pub const ECONNREFUSED: ::c_int = 61; pub const ELOOP: ::c_int = 62; pub const ENAMETOOLONG: ::c_int = 63; pub const EHOSTDOWN: ::c_int = 64; pub const EHOSTUNREACH: ::c_int = 65; pub const ENOTEMPTY: ::c_int = 66; pub const EPROCLIM: ::c_int = 67; pub const EUSERS: ::c_int = 68; pub const EDQUOT: ::c_int = 69; pub const ESTALE: ::c_int = 70; pub const EREMOTE: ::c_int = 71; pub const EBADRPC: ::c_int = 72; pub const ERPCMISMATCH: ::c_int = 73; pub const EPROGUNAVAIL: ::c_int = 74; pub const EPROGMISMATCH: ::c_int = 75; pub const EPROCUNAVAIL: ::c_int = 76; pub const ENOLCK: ::c_int = 77; pub const ENOSYS: ::c_int = 78; pub const EFTYPE: ::c_int = 79; pub const EAUTH: ::c_int = 80; pub const ENEEDAUTH: ::c_int = 81; pub const EIDRM: ::c_int = 82; pub const ENOMSG: ::c_int = 83; pub const EOVERFLOW: ::c_int = 84; pub const ECANCELED: ::c_int = 85; pub const EILSEQ: ::c_int = 86; pub const ENOATTR: ::c_int = 87; pub const EDOOFUS: ::c_int = 88; pub const EBADMSG: ::c_int = 89; pub const EMULTIHOP: ::c_int = 90; pub const ENOLINK: ::c_int = 91; pub const EPROTO: ::c_int = 92; pub const POLLSTANDARD: ::c_short = ::POLLIN | ::POLLPRI | ::POLLOUT | ::POLLRDNORM | ::POLLRDBAND | ::POLLWRBAND | ::POLLERR | ::POLLHUP | ::POLLNVAL; pub const AI_PASSIVE: ::c_int = 0x00000001; pub const AI_CANONNAME: ::c_int = 0x00000002; pub const AI_NUMERICHOST: ::c_int = 0x00000004; pub const AI_NUMERICSERV: ::c_int = 0x00000008; pub const AI_ALL: ::c_int = 0x00000100; pub const AI_ADDRCONFIG: ::c_int = 0x00000400; pub const AI_V4MAPPED: ::c_int = 0x00000800; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_FAMILY: ::c_int = 5; pub const EAI_MEMORY: ::c_int = 6; pub const EAI_NONAME: ::c_int = 8; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_OVERFLOW: ::c_int = 14; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const SIGTRAP: ::c_int = 5; pub const GLOB_APPEND: ::c_int = 0x0001; pub const GLOB_DOOFFS: ::c_int = 0x0002; pub const GLOB_ERR: ::c_int = 0x0004; pub const GLOB_MARK: ::c_int = 0x0008; pub const GLOB_NOCHECK: ::c_int = 0x0010; pub const GLOB_NOSORT: ::c_int = 0x0020; pub const GLOB_NOESCAPE: ::c_int = 0x2000; pub const GLOB_NOSPACE: ::c_int = -1; pub const GLOB_ABORTED: ::c_int = -2; pub const GLOB_NOMATCH: ::c_int = -3; pub const POSIX_MADV_NORMAL: ::c_int = 0; pub const POSIX_MADV_RANDOM: ::c_int = 1; pub const POSIX_MADV_SEQUENTIAL: ::c_int = 2; pub const POSIX_MADV_WILLNEED: ::c_int = 3; pub const POSIX_MADV_DONTNEED: ::c_int = 4; pub const PTHREAD_PROCESS_PRIVATE: ::c_int = 0; pub const PTHREAD_PROCESS_SHARED: ::c_int = 1; pub const PTHREAD_CREATE_JOINABLE: ::c_int = 0; pub const PTHREAD_CREATE_DETACHED: ::c_int = 1; pub const RLIMIT_CPU: ::c_int = 0; pub const RLIMIT_FSIZE: ::c_int = 1; pub const RLIMIT_DATA: ::c_int = 2; pub const RLIMIT_STACK: ::c_int = 3; pub const RLIMIT_CORE: ::c_int = 4; pub const RLIMIT_RSS: ::c_int = 5; pub const RLIMIT_MEMLOCK: ::c_int = 6; pub const RLIMIT_NPROC: ::c_int = 7; pub const RLIMIT_NOFILE: ::c_int = 8; pub const RLIMIT_SBSIZE: ::c_int = 9; pub const RLIMIT_VMEM: ::c_int = 10; pub const RLIMIT_AS: ::c_int = RLIMIT_VMEM; pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff; pub const RUSAGE_SELF: ::c_int = 0; pub const RUSAGE_CHILDREN: ::c_int = -1; pub const CLOCK_REALTIME: ::clockid_t = 0; pub const CLOCK_VIRTUAL: ::clockid_t = 1; pub const CLOCK_PROF: ::clockid_t = 2; pub const CLOCK_MONOTONIC: ::clockid_t = 4; pub const CLOCK_UPTIME: ::clockid_t = 5; pub const CLOCK_UPTIME_PRECISE: ::clockid_t = 7; pub const CLOCK_UPTIME_FAST: ::clockid_t = 8; pub const CLOCK_REALTIME_PRECISE: ::clockid_t = 9; pub const CLOCK_REALTIME_FAST: ::clockid_t = 10; pub const CLOCK_MONOTONIC_PRECISE: ::clockid_t = 11; pub const CLOCK_MONOTONIC_FAST: ::clockid_t = 12; pub const CLOCK_SECOND: ::clockid_t = 13; pub const CLOCK_THREAD_CPUTIME_ID: ::clockid_t = 14; pub const CLOCK_PROCESS_CPUTIME_ID: ::clockid_t = 15; pub const MADV_NORMAL: ::c_int = 0; pub const MADV_RANDOM: ::c_int = 1; pub const MADV_SEQUENTIAL: ::c_int = 2; pub const MADV_WILLNEED: ::c_int = 3; pub const MADV_DONTNEED: ::c_int = 4; pub const MADV_FREE: ::c_int = 5; pub const MADV_NOSYNC: ::c_int = 6; pub const MADV_AUTOSYNC: ::c_int = 7; pub const MADV_NOCORE: ::c_int = 8; pub const MADV_CORE: ::c_int = 9; pub const MINCORE_INCORE: ::c_int = 0x1; pub const MINCORE_REFERENCED: ::c_int = 0x2; pub const MINCORE_MODIFIED: ::c_int = 0x4; pub const MINCORE_REFERENCED_OTHER: ::c_int = 0x8; pub const MINCORE_MODIFIED_OTHER: ::c_int = 0x10; pub const AF_UNSPEC: ::c_int = 0; pub const AF_LOCAL: ::c_int = 1; pub const AF_UNIX: ::c_int = AF_LOCAL; pub const AF_INET: ::c_int = 2; pub const AF_IMPLINK: ::c_int = 3; pub const AF_PUP: ::c_int = 4; pub const AF_CHAOS: ::c_int = 5; pub const AF_NETBIOS: ::c_int = 6; pub const AF_ISO: ::c_int = 7; pub const AF_OSI: ::c_int = AF_ISO; pub const AF_ECMA: ::c_int = 8; pub const AF_DATAKIT: ::c_int = 9; pub const AF_CCITT: ::c_int = 10; pub const AF_SNA: ::c_int = 11; pub const AF_DECnet: ::c_int = 12; pub const AF_DLI: ::c_int = 13; pub const AF_LAT: ::c_int = 14; pub const AF_HYLINK: ::c_int = 15; pub const AF_APPLETALK: ::c_int = 16; pub const AF_ROUTE: ::c_int = 17; pub const AF_LINK: ::c_int = 18; pub const pseudo_AF_XTP: ::c_int = 19; pub const AF_COIP: ::c_int = 20; pub const AF_CNT: ::c_int = 21; pub const pseudo_AF_RTIP: ::c_int = 22; pub const AF_IPX: ::c_int = 23; pub const AF_SIP: ::c_int = 24; pub const pseudo_AF_PIP: ::c_int = 25; pub const AF_ISDN: ::c_int = 26; pub const AF_E164: ::c_int = AF_ISDN; pub const pseudo_AF_KEY: ::c_int = 27; pub const AF_INET6: ::c_int = 28; pub const AF_NATM: ::c_int = 29; pub const AF_ATM: ::c_int = 30; pub const pseudo_AF_HDRCMPLT: ::c_int = 31; pub const AF_NETGRAPH: ::c_int = 32; pub const PF_UNSPEC: ::c_int = AF_UNSPEC; pub const PF_LOCAL: ::c_int = AF_LOCAL; pub const PF_UNIX: ::c_int = PF_LOCAL; pub const PF_INET: ::c_int = AF_INET; pub const PF_IMPLINK: ::c_int = AF_IMPLINK; pub const PF_PUP: ::c_int = AF_PUP; pub const PF_CHAOS: ::c_int = AF_CHAOS; pub const PF_NETBIOS: ::c_int = AF_NETBIOS; pub const PF_ISO: ::c_int = AF_ISO; pub const PF_OSI: ::c_int = AF_ISO; pub const PF_ECMA: ::c_int = AF_ECMA; pub const PF_DATAKIT: ::c_int = AF_DATAKIT; pub const PF_CCITT: ::c_int = AF_CCITT; pub const PF_SNA: ::c_int = AF_SNA; pub const PF_DECnet: ::c_int = AF_DECnet; pub const PF_DLI: ::c_int = AF_DLI; pub const PF_LAT: ::c_int = AF_LAT; pub const PF_HYLINK: ::c_int = AF_HYLINK; pub const PF_APPLETALK: ::c_int = AF_APPLETALK; pub const PF_ROUTE: ::c_int = AF_ROUTE; pub const PF_LINK: ::c_int = AF_LINK; pub const PF_XTP: ::c_int = pseudo_AF_XTP; pub const PF_COIP: ::c_int = AF_COIP; pub const PF_CNT: ::c_int = AF_CNT; pub const PF_SIP: ::c_int = AF_SIP; pub const PF_IPX: ::c_int = AF_IPX; pub const PF_RTIP: ::c_int = pseudo_AF_RTIP; pub const PF_PIP: ::c_int = pseudo_AF_PIP; pub const PF_ISDN: ::c_int = AF_ISDN; pub const PF_KEY: ::c_int = pseudo_AF_KEY; pub const PF_INET6: ::c_int = AF_INET6; pub const PF_NATM: ::c_int = AF_NATM; pub const PF_ATM: ::c_int = AF_ATM; pub const PF_NETGRAPH: ::c_int = AF_NETGRAPH; pub const PIOD_READ_D: ::c_int = 1; pub const PIOD_WRITE_D: ::c_int = 2; pub const PIOD_READ_I: ::c_int = 3; pub const PIOD_WRITE_I: ::c_int = 4; pub const PT_TRACE_ME: ::c_int = 0; pub const PT_READ_I: ::c_int = 1; pub const PT_READ_D: ::c_int = 2; pub const PT_WRITE_I: ::c_int = 4; pub const PT_WRITE_D: ::c_int = 5; pub const PT_CONTINUE: ::c_int = 7; pub const PT_KILL: ::c_int = 8; pub const PT_STEP: ::c_int = 9; pub const PT_ATTACH: ::c_int = 10; pub const PT_DETACH: ::c_int = 11; pub const PT_IO: ::c_int = 12; pub const SOMAXCONN: ::c_int = 128; pub const MSG_OOB: ::c_int = 0x00000001; pub const MSG_PEEK: ::c_int = 0x00000002; pub const MSG_DONTROUTE: ::c_int = 0x00000004; pub const MSG_EOR: ::c_int = 0x00000008; pub const MSG_TRUNC: ::c_int = 0x00000010; pub const MSG_CTRUNC: ::c_int = 0x00000020; pub const MSG_WAITALL: ::c_int = 0x00000040; pub const MSG_DONTWAIT: ::c_int = 0x00000080; pub const MSG_EOF: ::c_int = 0x00000100; pub const SCM_TIMESTAMP: ::c_int = 0x02; pub const SCM_CREDS: ::c_int = 0x03; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_CLOEXEC: ::c_int = 0x10000000; pub const SOCK_NONBLOCK: ::c_int = 0x20000000; pub const SOCK_MAXADDRLEN: ::c_int = 255; pub const IP_TTL: ::c_int = 4; pub const IP_HDRINCL: ::c_int = 2; pub const IP_RECVDSTADDR: ::c_int = 7; pub const IP_SENDSRCADDR: ::c_int = IP_RECVDSTADDR; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; pub const IP_RECVIF: ::c_int = 20; pub const IPV6_JOIN_GROUP: ::c_int = 12; pub const IPV6_LEAVE_GROUP: ::c_int = 13; pub const IPV6_CHECKSUM: ::c_int = 26; pub const IPV6_RECVPKTINFO: ::c_int = 36; pub const IPV6_PKTINFO: ::c_int = 46; pub const IPV6_HOPLIMIT: ::c_int = 47; pub const IPV6_RECVTCLASS: ::c_int = 57; pub const IPV6_TCLASS: ::c_int = 61; pub const IPV6_DONTFRAG: ::c_int = 62; pub const IP_ADD_SOURCE_MEMBERSHIP: ::c_int = 70; pub const IP_DROP_SOURCE_MEMBERSHIP: ::c_int = 71; pub const IP_BLOCK_SOURCE: ::c_int = 72; pub const IP_UNBLOCK_SOURCE: ::c_int = 73; pub const TCP_NOPUSH: ::c_int = 4; pub const TCP_NOOPT: ::c_int = 8; pub const TCP_KEEPIDLE: ::c_int = 256; pub const TCP_KEEPINTVL: ::c_int = 512; pub const TCP_KEEPCNT: ::c_int = 1024; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x01; pub const SO_ACCEPTCONN: ::c_int = 0x0002; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_TIMESTAMP: ::c_int = 0x0400; pub const SO_NOSIGPIPE: ::c_int = 0x0800; pub const SO_ACCEPTFILTER: ::c_int = 0x1000; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVLOWAT: ::c_int = 0x1004; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; pub const LOCAL_PEERCRED: ::c_int = 1; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const LOCK_SH: ::c_int = 1; pub const LOCK_EX: ::c_int = 2; pub const LOCK_NB: ::c_int = 4; pub const LOCK_UN: ::c_int = 8; pub const MAP_COPY: ::c_int = 0x0002; #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Removed in FreeBSD 11, unused in DragonFlyBSD" )] pub const MAP_RENAME: ::c_int = 0x0020; #[doc(hidden)] #[deprecated( since = "0.2.54", note = "Removed in FreeBSD 11, unused in DragonFlyBSD" )] pub const MAP_NORESERVE: ::c_int = 0x0040; pub const MAP_HASSEMAPHORE: ::c_int = 0x0200; pub const MAP_STACK: ::c_int = 0x0400; pub const MAP_NOSYNC: ::c_int = 0x0800; pub const MAP_NOCORE: ::c_int = 0x020000; pub const IPPROTO_RAW: ::c_int = 255; pub const _PC_LINK_MAX: ::c_int = 1; pub const _PC_MAX_CANON: ::c_int = 2; pub const _PC_MAX_INPUT: ::c_int = 3; pub const _PC_NAME_MAX: ::c_int = 4; pub const _PC_PATH_MAX: ::c_int = 5; pub const _PC_PIPE_BUF: ::c_int = 6; pub const _PC_CHOWN_RESTRICTED: ::c_int = 7; pub const _PC_NO_TRUNC: ::c_int = 8; pub const _PC_VDISABLE: ::c_int = 9; pub const _PC_ALLOC_SIZE_MIN: ::c_int = 10; pub const _PC_FILESIZEBITS: ::c_int = 12; pub const _PC_REC_INCR_XFER_SIZE: ::c_int = 14; pub const _PC_REC_MAX_XFER_SIZE: ::c_int = 15; pub const _PC_REC_MIN_XFER_SIZE: ::c_int = 16; pub const _PC_REC_XFER_ALIGN: ::c_int = 17; pub const _PC_SYMLINK_MAX: ::c_int = 18; pub const _PC_MIN_HOLE_SIZE: ::c_int = 21; pub const _PC_ASYNC_IO: ::c_int = 53; pub const _PC_PRIO_IO: ::c_int = 54; pub const _PC_SYNC_IO: ::c_int = 55; pub const _PC_ACL_EXTENDED: ::c_int = 59; pub const _PC_ACL_PATH_MAX: ::c_int = 60; pub const _PC_CAP_PRESENT: ::c_int = 61; pub const _PC_INF_PRESENT: ::c_int = 62; pub const _PC_MAC_PRESENT: ::c_int = 63; pub const _SC_ARG_MAX: ::c_int = 1; pub const _SC_CHILD_MAX: ::c_int = 2; pub const _SC_CLK_TCK: ::c_int = 3; pub const _SC_NGROUPS_MAX: ::c_int = 4; pub const _SC_OPEN_MAX: ::c_int = 5; pub const _SC_JOB_CONTROL: ::c_int = 6; pub const _SC_SAVED_IDS: ::c_int = 7; pub const _SC_VERSION: ::c_int = 8; pub const _SC_BC_BASE_MAX: ::c_int = 9; pub const _SC_BC_DIM_MAX: ::c_int = 10; pub const _SC_BC_SCALE_MAX: ::c_int = 11; pub const _SC_BC_STRING_MAX: ::c_int = 12; pub const _SC_COLL_WEIGHTS_MAX: ::c_int = 13; pub const _SC_EXPR_NEST_MAX: ::c_int = 14; pub const _SC_LINE_MAX: ::c_int = 15; pub const _SC_RE_DUP_MAX: ::c_int = 16; pub const _SC_2_VERSION: ::c_int = 17; pub const _SC_2_C_BIND: ::c_int = 18; pub const _SC_2_C_DEV: ::c_int = 19; pub const _SC_2_CHAR_TERM: ::c_int = 20; pub const _SC_2_FORT_DEV: ::c_int = 21; pub const _SC_2_FORT_RUN: ::c_int = 22; pub const _SC_2_LOCALEDEF: ::c_int = 23; pub const _SC_2_SW_DEV: ::c_int = 24; pub const _SC_2_UPE: ::c_int = 25; pub const _SC_STREAM_MAX: ::c_int = 26; pub const _SC_TZNAME_MAX: ::c_int = 27; pub const _SC_ASYNCHRONOUS_IO: ::c_int = 28; pub const _SC_MAPPED_FILES: ::c_int = 29; pub const _SC_MEMLOCK: ::c_int = 30; pub const _SC_MEMLOCK_RANGE: ::c_int = 31; pub const _SC_MEMORY_PROTECTION: ::c_int = 32; pub const _SC_MESSAGE_PASSING: ::c_int = 33; pub const _SC_PRIORITIZED_IO: ::c_int = 34; pub const _SC_PRIORITY_SCHEDULING: ::c_int = 35; pub const _SC_REALTIME_SIGNALS: ::c_int = 36; pub const _SC_SEMAPHORES: ::c_int = 37; pub const _SC_FSYNC: ::c_int = 38; pub const _SC_SHARED_MEMORY_OBJECTS: ::c_int = 39; pub const _SC_SYNCHRONIZED_IO: ::c_int = 40; pub const _SC_TIMERS: ::c_int = 41; pub const _SC_AIO_LISTIO_MAX: ::c_int = 42; pub const _SC_AIO_MAX: ::c_int = 43; pub const _SC_AIO_PRIO_DELTA_MAX: ::c_int = 44; pub const _SC_DELAYTIMER_MAX: ::c_int = 45; pub const _SC_MQ_OPEN_MAX: ::c_int = 46; pub const _SC_PAGESIZE: ::c_int = 47; pub const _SC_PAGE_SIZE: ::c_int = _SC_PAGESIZE; pub const _SC_RTSIG_MAX: ::c_int = 48; pub const _SC_SEM_NSEMS_MAX: ::c_int = 49; pub const _SC_SEM_VALUE_MAX: ::c_int = 50; pub const _SC_SIGQUEUE_MAX: ::c_int = 51; pub const _SC_TIMER_MAX: ::c_int = 52; pub const _SC_IOV_MAX: ::c_int = 56; pub const _SC_NPROCESSORS_CONF: ::c_int = 57; pub const _SC_2_PBS: ::c_int = 59; pub const _SC_2_PBS_ACCOUNTING: ::c_int = 60; pub const _SC_2_PBS_CHECKPOINT: ::c_int = 61; pub const _SC_2_PBS_LOCATE: ::c_int = 62; pub const _SC_2_PBS_MESSAGE: ::c_int = 63; pub const _SC_2_PBS_TRACK: ::c_int = 64; pub const _SC_ADVISORY_INFO: ::c_int = 65; pub const _SC_BARRIERS: ::c_int = 66; pub const _SC_CLOCK_SELECTION: ::c_int = 67; pub const _SC_CPUTIME: ::c_int = 68; pub const _SC_FILE_LOCKING: ::c_int = 69; pub const _SC_NPROCESSORS_ONLN: ::c_int = 58; pub const _SC_GETGR_R_SIZE_MAX: ::c_int = 70; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 71; pub const _SC_HOST_NAME_MAX: ::c_int = 72; pub const _SC_LOGIN_NAME_MAX: ::c_int = 73; pub const _SC_MONOTONIC_CLOCK: ::c_int = 74; pub const _SC_MQ_PRIO_MAX: ::c_int = 75; pub const _SC_READER_WRITER_LOCKS: ::c_int = 76; pub const _SC_REGEXP: ::c_int = 77; pub const _SC_SHELL: ::c_int = 78; pub const _SC_SPAWN: ::c_int = 79; pub const _SC_SPIN_LOCKS: ::c_int = 80; pub const _SC_SPORADIC_SERVER: ::c_int = 81; pub const _SC_THREAD_ATTR_STACKADDR: ::c_int = 82; pub const _SC_THREAD_ATTR_STACKSIZE: ::c_int = 83; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: ::c_int = 85; pub const _SC_THREAD_KEYS_MAX: ::c_int = 86; pub const _SC_THREAD_PRIO_INHERIT: ::c_int = 87; pub const _SC_THREAD_PRIO_PROTECT: ::c_int = 88; pub const _SC_THREAD_PRIORITY_SCHEDULING: ::c_int = 89; pub const _SC_THREAD_PROCESS_SHARED: ::c_int = 90; pub const _SC_THREAD_SAFE_FUNCTIONS: ::c_int = 91; pub const _SC_THREAD_SPORADIC_SERVER: ::c_int = 92; pub const _SC_THREAD_STACK_MIN: ::c_int = 93; pub const _SC_THREAD_THREADS_MAX: ::c_int = 94; pub const _SC_TIMEOUTS: ::c_int = 95; pub const _SC_THREADS: ::c_int = 96; pub const _SC_TRACE: ::c_int = 97; pub const _SC_TRACE_EVENT_FILTER: ::c_int = 98; pub const _SC_TRACE_INHERIT: ::c_int = 99; pub const _SC_TRACE_LOG: ::c_int = 100; pub const _SC_TTY_NAME_MAX: ::c_int = 101; pub const _SC_TYPED_MEMORY_OBJECTS: ::c_int = 102; pub const _SC_V6_ILP32_OFF32: ::c_int = 103; pub const _SC_V6_ILP32_OFFBIG: ::c_int = 104; pub const _SC_V6_LP64_OFF64: ::c_int = 105; pub const _SC_V6_LPBIG_OFFBIG: ::c_int = 106; pub const _SC_ATEXIT_MAX: ::c_int = 107; pub const _SC_XOPEN_CRYPT: ::c_int = 108; pub const _SC_XOPEN_ENH_I18N: ::c_int = 109; pub const _SC_XOPEN_LEGACY: ::c_int = 110; pub const _SC_XOPEN_REALTIME: ::c_int = 111; pub const _SC_XOPEN_REALTIME_THREADS: ::c_int = 112; pub const _SC_XOPEN_SHM: ::c_int = 113; pub const _SC_XOPEN_STREAMS: ::c_int = 114; pub const _SC_XOPEN_UNIX: ::c_int = 115; pub const _SC_XOPEN_VERSION: ::c_int = 116; pub const _SC_XOPEN_XCU_VERSION: ::c_int = 117; pub const _SC_IPV6: ::c_int = 118; pub const _SC_RAW_SOCKETS: ::c_int = 119; pub const _SC_SYMLOOP_MAX: ::c_int = 120; pub const _SC_PHYS_PAGES: ::c_int = 121; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 0 as *mut _; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 0 as *mut _; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 0 as *mut _; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 3; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_ERRORCHECK; pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_OTHER: ::c_int = 2; pub const SCHED_RR: ::c_int = 3; pub const FD_SETSIZE: usize = 1024; pub const ST_NOSUID: ::c_ulong = 2; pub const NI_MAXHOST: ::size_t = 1025; pub const XUCRED_VERSION: ::c_uint = 0; pub const RTLD_LOCAL: ::c_int = 0; pub const RTLD_NODELETE: ::c_int = 0x1000; pub const RTLD_NOLOAD: ::c_int = 0x2000; pub const RTLD_GLOBAL: ::c_int = 0x100; pub const LOG_NTP: ::c_int = 12 << 3; pub const LOG_SECURITY: ::c_int = 13 << 3; pub const LOG_CONSOLE: ::c_int = 14 << 3; pub const LOG_NFACILITIES: ::c_int = 24; pub const TIOCEXCL: ::c_ulong = 0x2000740d; pub const TIOCNXCL: ::c_ulong = 0x2000740e; pub const TIOCFLUSH: ::c_ulong = 0x80047410; pub const TIOCGETA: ::c_ulong = 0x402c7413; pub const TIOCSETA: ::c_ulong = 0x802c7414; pub const TIOCSETAW: ::c_ulong = 0x802c7415; pub const TIOCSETAF: ::c_ulong = 0x802c7416; pub const TIOCGETD: ::c_ulong = 0x4004741a; pub const TIOCSETD: ::c_ulong = 0x8004741b; pub const TIOCGDRAINWAIT: ::c_ulong = 0x40047456; pub const TIOCSDRAINWAIT: ::c_ulong = 0x80047457; pub const TIOCTIMESTAMP: ::c_ulong = 0x40107459; pub const TIOCMGDTRWAIT: ::c_ulong = 0x4004745a; pub const TIOCMSDTRWAIT: ::c_ulong = 0x8004745b; pub const TIOCDRAIN: ::c_ulong = 0x2000745e; pub const TIOCEXT: ::c_ulong = 0x80047460; pub const TIOCSCTTY: ::c_ulong = 0x20007461; pub const TIOCCONS: ::c_ulong = 0x80047462; pub const TIOCGSID: ::c_ulong = 0x40047463; pub const TIOCSTAT: ::c_ulong = 0x20007465; pub const TIOCUCNTL: ::c_ulong = 0x80047466; pub const TIOCSWINSZ: ::c_ulong = 0x80087467; pub const TIOCGWINSZ: ::c_ulong = 0x40087468; pub const TIOCMGET: ::c_ulong = 0x4004746a; pub const TIOCM_LE: ::c_int = 0x1; pub const TIOCM_DTR: ::c_int = 0x2; pub const TIOCM_RTS: ::c_int = 0x4; pub const TIOCM_ST: ::c_int = 0x8; pub const TIOCM_SR: ::c_int = 0x10; pub const TIOCM_CTS: ::c_int = 0x20; pub const TIOCM_RI: ::c_int = 0x80; pub const TIOCM_DSR: ::c_int = 0x100; pub const TIOCM_CD: ::c_int = 0x40; pub const TIOCM_CAR: ::c_int = 0x40; pub const TIOCM_RNG: ::c_int = 0x80; pub const TIOCMBIC: ::c_ulong = 0x8004746b; pub const TIOCMBIS: ::c_ulong = 0x8004746c; pub const TIOCMSET: ::c_ulong = 0x8004746d; pub const TIOCSTART: ::c_ulong = 0x2000746e; pub const TIOCSTOP: ::c_ulong = 0x2000746f; pub const TIOCPKT: ::c_ulong = 0x80047470; pub const TIOCPKT_DATA: ::c_int = 0x0; pub const TIOCPKT_FLUSHREAD: ::c_int = 0x1; pub const TIOCPKT_FLUSHWRITE: ::c_int = 0x2; pub const TIOCPKT_STOP: ::c_int = 0x4; pub const TIOCPKT_START: ::c_int = 0x8; pub const TIOCPKT_NOSTOP: ::c_int = 0x10; pub const TIOCPKT_DOSTOP: ::c_int = 0x20; pub const TIOCPKT_IOCTL: ::c_int = 0x40; pub const TIOCNOTTY: ::c_ulong = 0x20007471; pub const TIOCSTI: ::c_ulong = 0x80017472; pub const TIOCOUTQ: ::c_ulong = 0x40047473; pub const TIOCSPGRP: ::c_ulong = 0x80047476; pub const TIOCGPGRP: ::c_ulong = 0x40047477; pub const TIOCCDTR: ::c_ulong = 0x20007478; pub const TIOCSDTR: ::c_ulong = 0x20007479; pub const TTYDISC: ::c_int = 0x0; pub const SLIPDISC: ::c_int = 0x4; pub const PPPDISC: ::c_int = 0x5; pub const NETGRAPHDISC: ::c_int = 0x6; pub const BIOCGRSIG: ::c_ulong = 0x40044272; pub const BIOCSRSIG: ::c_ulong = 0x80044273; pub const BIOCSDLT: ::c_ulong = 0x80044278; pub const BIOCGSEESENT: ::c_ulong = 0x40044276; pub const BIOCSSEESENT: ::c_ulong = 0x80044277; pub const BIOCSETF: ::c_ulong = 0x80104267; pub const BIOCGDLTLIST: ::c_ulong = 0xc0104279; pub const BIOCSRTIMEOUT: ::c_ulong = 0x8010426d; pub const BIOCGRTIMEOUT: ::c_ulong = 0x4010426e; pub const FIODTYPE: ::c_ulong = 0x4004667a; pub const FIOGETLBA: ::c_ulong = 0x40046679; pub const B0: speed_t = 0; pub const B50: speed_t = 50; pub const B75: speed_t = 75; pub const B110: speed_t = 110; pub const B134: speed_t = 134; pub const B150: speed_t = 150; pub const B200: speed_t = 200; pub const B300: speed_t = 300; pub const B600: speed_t = 600; pub const B1200: speed_t = 1200; pub const B1800: speed_t = 1800; pub const B2400: speed_t = 2400; pub const B4800: speed_t = 4800; pub const B9600: speed_t = 9600; pub const B19200: speed_t = 19200; pub const B38400: speed_t = 38400; pub const B7200: speed_t = 7200; pub const B14400: speed_t = 14400; pub const B28800: speed_t = 28800; pub const B57600: speed_t = 57600; pub const B76800: speed_t = 76800; pub const B115200: speed_t = 115200; pub const B230400: speed_t = 230400; pub const EXTA: speed_t = 19200; pub const EXTB: speed_t = 38400; pub const SEM_FAILED: *mut sem_t = 0 as *mut sem_t; pub const CRTSCTS: ::tcflag_t = 0x00030000; pub const CCTS_OFLOW: ::tcflag_t = 0x00010000; pub const CRTS_IFLOW: ::tcflag_t = 0x00020000; pub const CDTR_IFLOW: ::tcflag_t = 0x00040000; pub const CDSR_OFLOW: ::tcflag_t = 0x00080000; pub const CCAR_OFLOW: ::tcflag_t = 0x00100000; pub const VERASE2: usize = 7; pub const OCRNL: ::tcflag_t = 0x10; pub const ONOCR: ::tcflag_t = 0x20; pub const ONLRET: ::tcflag_t = 0x40; pub const CMGROUP_MAX: usize = 16; pub const EUI64_LEN: usize = 8; // https://github.com/freebsd/freebsd/blob/HEAD/sys/net/bpf.h pub const BPF_ALIGNMENT: usize = SIZEOF_LONG; // Values for rtprio struct (prio field) and syscall (function argument) pub const RTP_PRIO_MIN: ::c_ushort = 0; pub const RTP_PRIO_MAX: ::c_ushort = 31; pub const RTP_LOOKUP: ::c_int = 0; pub const RTP_SET: ::c_int = 1; // Flags for chflags(2) pub const UF_SETTABLE: ::c_ulong = 0x0000ffff; pub const UF_NODUMP: ::c_ulong = 0x00000001; pub const UF_IMMUTABLE: ::c_ulong = 0x00000002; pub const UF_APPEND: ::c_ulong = 0x00000004; pub const UF_OPAQUE: ::c_ulong = 0x00000008; pub const UF_NOUNLINK: ::c_ulong = 0x00000010; pub const SF_SETTABLE: ::c_ulong = 0xffff0000; pub const SF_ARCHIVED: ::c_ulong = 0x00010000; pub const SF_IMMUTABLE: ::c_ulong = 0x00020000; pub const SF_APPEND: ::c_ulong = 0x00040000; pub const SF_NOUNLINK: ::c_ulong = 0x00100000; pub const TIMER_ABSTIME: ::c_int = 1; // pub const NTP_API: ::c_int = 4; pub const MAXPHASE: ::c_long = 500000000; pub const MAXFREQ: ::c_long = 500000; pub const MINSEC: ::c_int = 256; pub const MAXSEC: ::c_int = 2048; pub const NANOSECOND: ::c_long = 1000000000; pub const SCALE_PPM: ::c_int = 65; pub const MAXTC: ::c_int = 10; pub const MOD_OFFSET: ::c_uint = 0x0001; pub const MOD_FREQUENCY: ::c_uint = 0x0002; pub const MOD_MAXERROR: ::c_uint = 0x0004; pub const MOD_ESTERROR: ::c_uint = 0x0008; pub const MOD_STATUS: ::c_uint = 0x0010; pub const MOD_TIMECONST: ::c_uint = 0x0020; pub const MOD_PPSMAX: ::c_uint = 0x0040; pub const MOD_TAI: ::c_uint = 0x0080; pub const MOD_MICRO: ::c_uint = 0x1000; pub const MOD_NANO: ::c_uint = 0x2000; pub const MOD_CLKB: ::c_uint = 0x4000; pub const MOD_CLKA: ::c_uint = 0x8000; pub const STA_PLL: ::c_int = 0x0001; pub const STA_PPSFREQ: ::c_int = 0x0002; pub const STA_PPSTIME: ::c_int = 0x0004; pub const STA_FLL: ::c_int = 0x0008; pub const STA_INS: ::c_int = 0x0010; pub const STA_DEL: ::c_int = 0x0020; pub const STA_UNSYNC: ::c_int = 0x0040; pub const STA_FREQHOLD: ::c_int = 0x0080; pub const STA_PPSSIGNAL: ::c_int = 0x0100; pub const STA_PPSJITTER: ::c_int = 0x0200; pub const STA_PPSWANDER: ::c_int = 0x0400; pub const STA_PPSERROR: ::c_int = 0x0800; pub const STA_CLOCKERR: ::c_int = 0x1000; pub const STA_NANO: ::c_int = 0x2000; pub const STA_MODE: ::c_int = 0x4000; pub const STA_CLK: ::c_int = 0x8000; pub const STA_RONLY: ::c_int = STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK; pub const TIME_OK: ::c_int = 0; pub const TIME_INS: ::c_int = 1; pub const TIME_DEL: ::c_int = 2; pub const TIME_OOP: ::c_int = 3; pub const TIME_WAIT: ::c_int = 4; pub const TIME_ERROR: ::c_int = 5; pub const REG_ENOSYS: ::c_int = -1; pub const REG_ILLSEQ: ::c_int = 17; pub const IPC_PRIVATE: ::key_t = 0; pub const IPC_CREAT: ::c_int = 0o1000; pub const IPC_EXCL: ::c_int = 0o2000; pub const IPC_NOWAIT: ::c_int = 0o4000; pub const IPC_RMID: ::c_int = 0; pub const IPC_SET: ::c_int = 1; pub const IPC_STAT: ::c_int = 2; pub const IPC_R: ::c_int = 0o400; pub const IPC_W: ::c_int = 0o200; pub const IPC_M: ::c_int = 0o10000; pub const SHM_RDONLY: ::c_int = 0o10000; pub const SHM_RND: ::c_int = 0o20000; pub const SHM_R: ::c_int = 0o400; pub const SHM_W: ::c_int = 0o200; pub const KENV_GET: ::c_int = 0; pub const KENV_SET: ::c_int = 1; pub const KENV_UNSET: ::c_int = 2; pub const KENV_DUMP: ::c_int = 3; pub const KENV_MNAMELEN: ::c_int = 128; pub const KENV_MVALLEN: ::c_int = 128; pub const RB_ASKNAME: ::c_int = 0x001; pub const RB_SINGLE: ::c_int = 0x002; pub const RB_NOSYNC: ::c_int = 0x004; pub const RB_HALT: ::c_int = 0x008; pub const RB_INITNAME: ::c_int = 0x010; pub const RB_DFLTROOT: ::c_int = 0x020; pub const RB_KDB: ::c_int = 0x040; pub const RB_RDONLY: ::c_int = 0x080; pub const RB_DUMP: ::c_int = 0x100; pub const RB_MINIROOT: ::c_int = 0x200; pub const RB_VERBOSE: ::c_int = 0x800; pub const RB_SERIAL: ::c_int = 0x1000; pub const RB_CDROM: ::c_int = 0x2000; pub const RB_POWEROFF: ::c_int = 0x4000; pub const RB_GDB: ::c_int = 0x8000; pub const RB_MUTE: ::c_int = 0x10000; pub const RB_SELFTEST: ::c_int = 0x20000; // For getrandom() pub const GRND_NONBLOCK: ::c_uint = 0x1; pub const GRND_RANDOM: ::c_uint = 0x2; pub const GRND_INSECURE: ::c_uint = 0x4; safe_f! { pub {const} fn WIFCONTINUED(status: ::c_int) -> bool { status == 0x13 } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { status >> 8 } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0o177) == 0o177 } } extern "C" { pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::timezone) -> ::c_int; pub fn accept4( s: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t, flags: ::c_int, ) -> ::c_int; pub fn chflags(path: *const ::c_char, flags: ::c_ulong) -> ::c_int; pub fn chflagsat( fd: ::c_int, path: *const ::c_char, flags: ::c_ulong, atflag: ::c_int, ) -> ::c_int; pub fn clock_nanosleep( clk_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; pub fn clock_getres(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_gettime(clk_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_settime(clk_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn clock_getcpuclockid(pid: ::pid_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn pthread_getcpuclockid(thread: ::pthread_t, clk_id: *mut ::clockid_t) -> ::c_int; pub fn dirfd(dirp: *mut ::DIR) -> ::c_int; pub fn duplocale(base: ::locale_t) -> ::locale_t; pub fn endutxent(); pub fn fchflags(fd: ::c_int, flags: ::c_ulong) -> ::c_int; pub fn fexecve( fd: ::c_int, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn getdomainname(name: *mut ::c_char, len: ::c_int) -> ::c_int; pub fn getgrent_r( grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn getpwent_r( pwd: *mut ::passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::passwd, ) -> ::c_int; pub fn getgrouplist( name: *const ::c_char, basegid: ::gid_t, groups: *mut ::gid_t, ngroups: *mut ::c_int, ) -> ::c_int; pub fn getnameinfo( sa: *const ::sockaddr, salen: ::socklen_t, host: *mut ::c_char, hostlen: ::size_t, serv: *mut ::c_char, servlen: ::size_t, flags: ::c_int, ) -> ::c_int; pub fn getpriority(which: ::c_int, who: ::c_int) -> ::c_int; pub fn getresgid(rgid: *mut ::gid_t, egid: *mut ::gid_t, sgid: *mut ::gid_t) -> ::c_int; pub fn getresuid(ruid: *mut ::uid_t, euid: *mut ::uid_t, suid: *mut ::uid_t) -> ::c_int; pub fn getutxent() -> *mut utmpx; pub fn getutxid(ut: *const utmpx) -> *mut utmpx; pub fn getutxline(ut: *const utmpx) -> *mut utmpx; pub fn initgroups(name: *const ::c_char, basegid: ::gid_t) -> ::c_int; #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "kevent@FBSD_1.0" )] pub fn kevent( kq: ::c_int, changelist: *const ::kevent, nchanges: ::c_int, eventlist: *mut ::kevent, nevents: ::c_int, timeout: *const ::timespec, ) -> ::c_int; pub fn lchflags(path: *const ::c_char, flags: ::c_ulong) -> ::c_int; pub fn lutimes(file: *const ::c_char, times: *const ::timeval) -> ::c_int; pub fn memrchr(cx: *const ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void; pub fn mkfifoat(dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t) -> ::c_int; #[cfg_attr( all(target_os = "freebsd", any(freebsd11, freebsd10)), link_name = "mknodat@FBSD_1.1" )] pub fn mknodat( dirfd: ::c_int, pathname: *const ::c_char, mode: ::mode_t, dev: dev_t, ) -> ::c_int; pub fn malloc_usable_size(ptr: *const ::c_void) -> ::size_t; pub fn mincore(addr: *const ::c_void, len: ::size_t, vec: *mut ::c_char) -> ::c_int; pub fn newlocale(mask: ::c_int, locale: *const ::c_char, base: ::locale_t) -> ::locale_t; pub fn nl_langinfo_l(item: ::nl_item, locale: ::locale_t) -> *mut ::c_char; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; pub fn posix_fallocate(fd: ::c_int, offset: ::off_t, len: ::off_t) -> ::c_int; pub fn posix_fadvise(fd: ::c_int, offset: ::off_t, len: ::off_t, advise: ::c_int) -> ::c_int; pub fn ppoll( fds: *mut ::pollfd, nfds: ::nfds_t, timeout: *const ::timespec, sigmask: *const sigset_t, ) -> ::c_int; pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn pthread_attr_get_np(tid: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int; pub fn pthread_attr_getguardsize( attr: *const ::pthread_attr_t, guardsize: *mut ::size_t, ) -> ::c_int; pub fn pthread_attr_setguardsize(attr: *mut ::pthread_attr_t, guardsize: ::size_t) -> ::c_int; pub fn pthread_attr_getstack( attr: *const ::pthread_attr_t, stackaddr: *mut *mut ::c_void, stacksize: *mut ::size_t, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const pthread_condattr_t, clock_id: *mut clockid_t, ) -> ::c_int; pub fn pthread_condattr_getpshared( attr: *const pthread_condattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, pshared: ::c_int) -> ::c_int; pub fn pthread_main_np() -> ::c_int; pub fn pthread_mutex_timedlock( lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_mutexattr_getpshared( attr: *const pthread_mutexattr_t, pshared: *mut ::c_int, ) -> ::c_int; pub fn pthread_mutexattr_setpshared( attr: *mut pthread_mutexattr_t, pshared: ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_getpshared( attr: *const pthread_rwlockattr_t, val: *mut ::c_int, ) -> ::c_int; pub fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, val: ::c_int) -> ::c_int; pub fn pthread_barrierattr_init(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_destroy(attr: *mut ::pthread_barrierattr_t) -> ::c_int; pub fn pthread_barrierattr_getpshared( attr: *const ::pthread_barrierattr_t, shared: *mut ::c_int, ) -> ::c_int; pub fn pthread_barrierattr_setpshared( attr: *mut ::pthread_barrierattr_t, shared: ::c_int, ) -> ::c_int; pub fn pthread_barrier_init( barrier: *mut pthread_barrier_t, attr: *const ::pthread_barrierattr_t, count: ::c_uint, ) -> ::c_int; pub fn pthread_barrier_destroy(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_barrier_wait(barrier: *mut pthread_barrier_t) -> ::c_int; pub fn pthread_get_name_np(tid: ::pthread_t, name: *mut ::c_char, len: ::size_t); pub fn pthread_set_name_np(tid: ::pthread_t, name: *const ::c_char); pub fn pthread_getname_np( thread: ::pthread_t, buffer: *mut ::c_char, length: ::size_t, ) -> ::c_int; pub fn pthread_setname_np(thread: ::pthread_t, name: *const ::c_char) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const sched_param, ) -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut sched_param, ) -> ::c_int; pub fn ptrace(request: ::c_int, pid: ::pid_t, addr: *mut ::c_char, data: ::c_int) -> ::c_int; pub fn utrace(addr: *const ::c_void, len: ::size_t) -> ::c_int; pub fn pututxline(ut: *const utmpx) -> *mut utmpx; pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t; pub fn querylocale(mask: ::c_int, loc: ::locale_t) -> *const ::c_char; pub fn rtprio(function: ::c_int, pid: ::pid_t, rtp: *mut rtprio) -> ::c_int; pub fn sched_rr_get_interval(pid: ::pid_t, t: *mut ::timespec) -> ::c_int; pub fn sched_getparam(pid: ::pid_t, param: *mut sched_param) -> ::c_int; pub fn sched_setparam(pid: ::pid_t, param: *const sched_param) -> ::c_int; pub fn sched_getscheduler(pid: ::pid_t) -> ::c_int; pub fn sched_setscheduler( pid: ::pid_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn sem_getvalue(sem: *mut sem_t, sval: *mut ::c_int) -> ::c_int; pub fn sem_timedwait(sem: *mut sem_t, abstime: *const ::timespec) -> ::c_int; pub fn sendfile( fd: ::c_int, s: ::c_int, offset: ::off_t, nbytes: ::size_t, hdtr: *mut ::sf_hdtr, sbytes: *mut ::off_t, flags: ::c_int, ) -> ::c_int; pub fn setdomainname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn sethostname(name: *const ::c_char, len: ::c_int) -> ::c_int; pub fn setpriority(which: ::c_int, who: ::c_int, prio: ::c_int) -> ::c_int; pub fn setresgid(rgid: ::gid_t, egid: ::gid_t, sgid: ::gid_t) -> ::c_int; pub fn setresuid(ruid: ::uid_t, euid: ::uid_t, suid: ::uid_t) -> ::c_int; pub fn settimeofday(tv: *const ::timeval, tz: *const ::timezone) -> ::c_int; pub fn setutxent(); pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn sigtimedwait( set: *const sigset_t, info: *mut siginfo_t, timeout: *const ::timespec, ) -> ::c_int; pub fn sigwaitinfo(set: *const sigset_t, info: *mut siginfo_t) -> ::c_int; pub fn sysctl( name: *const ::c_int, namelen: ::c_uint, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *const ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn sysctlbyname( name: *const ::c_char, oldp: *mut ::c_void, oldlenp: *mut ::size_t, newp: *const ::c_void, newlen: ::size_t, ) -> ::c_int; pub fn sysctlnametomib( name: *const ::c_char, mibp: *mut ::c_int, sizep: *mut ::size_t, ) -> ::c_int; pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn utimensat( dirfd: ::c_int, path: *const ::c_char, times: *const ::timespec, flag: ::c_int, ) -> ::c_int; pub fn ntp_adjtime(buf: *mut timex) -> ::c_int; pub fn ntp_gettime(buf: *mut ntptimeval) -> ::c_int; // #include pub fn dl_iterate_phdr( callback: ::Option< unsafe extern "C" fn( info: *mut dl_phdr_info, size: usize, data: *mut ::c_void, ) -> ::c_int, >, data: *mut ::c_void, ) -> ::c_int; pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t; pub fn iconv( cd: iconv_t, inbuf: *mut *mut ::c_char, inbytesleft: *mut ::size_t, outbuf: *mut *mut ::c_char, outbytesleft: *mut ::size_t, ) -> ::size_t; pub fn iconv_close(cd: iconv_t) -> ::c_int; // Added in `FreeBSD` 11.0 // Added in `DragonFly BSD` 5.4 pub fn explicit_bzero(s: *mut ::c_void, len: ::size_t); // ISO/IEC 9899:2011 ("ISO C11") K.3.7.4.1 pub fn memset_s(s: *mut ::c_void, smax: ::size_t, c: ::c_int, n: ::size_t) -> ::c_int; pub fn gethostid() -> ::c_long; pub fn sethostid(hostid: ::c_long); pub fn eui64_aton(a: *const ::c_char, e: *mut eui64) -> ::c_int; pub fn eui64_ntoa(id: *const eui64, a: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn eui64_ntohost(hostname: *mut ::c_char, len: ::size_t, id: *const eui64) -> ::c_int; pub fn eui64_hostton(hostname: *const ::c_char, id: *mut eui64) -> ::c_int; pub fn eaccess(path: *const ::c_char, mode: ::c_int) -> ::c_int; pub fn kenv( action: ::c_int, name: *const ::c_char, value: *mut ::c_char, len: ::c_int, ) -> ::c_int; pub fn reboot(howto: ::c_int) -> ::c_int; pub fn exect( path: *const ::c_char, argv: *const *mut ::c_char, envp: *const *mut ::c_char, ) -> ::c_int; pub fn execvP( file: *const ::c_char, search_path: *const ::c_char, argv: *const *mut ::c_char, ) -> ::c_int; } #[link(name = "rt")] extern "C" { pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; pub fn mq_notify(mqd: ::mqd_t, notification: *const ::sigevent) -> ::c_int; pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_send( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, abs_timeout: *const ::timespec, ) -> ::ssize_t; pub fn mq_timedsend( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; } #[link(name = "util")] extern "C" { pub fn openpty( amaster: *mut ::c_int, aslave: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::c_int; pub fn forkpty( amaster: *mut ::c_int, name: *mut ::c_char, termp: *mut termios, winp: *mut ::winsize, ) -> ::pid_t; pub fn login_tty(fd: ::c_int) -> ::c_int; pub fn fparseln( stream: *mut ::FILE, len: *mut ::size_t, lineno: *mut ::size_t, delim: *const ::c_char, flags: ::c_int, ) -> *mut ::c_char; } #[link(name = "execinfo")] extern "C" { pub fn backtrace(addrlist: *mut *mut ::c_void, len: ::size_t) -> ::size_t; pub fn backtrace_symbols(addrlist: *const *mut ::c_void, len: ::size_t) -> *mut *mut ::c_char; pub fn backtrace_symbols_fd( addrlist: *const *mut ::c_void, len: ::size_t, fd: ::c_int, ) -> ::c_int; } #[link(name = "kvm")] extern "C" { pub fn kvm_open( execfile: *const ::c_char, corefile: *const ::c_char, swapfile: *const ::c_char, flags: ::c_int, errstr: *const ::c_char, ) -> *mut ::kvm_t; pub fn kvm_close(kd: *mut ::kvm_t) -> ::c_int; pub fn kvm_getprocs( kd: *mut ::kvm_t, op: ::c_int, arg: ::c_int, cnt: *mut ::c_int, ) -> *mut ::kinfo_proc; pub fn kvm_getloadavg(kd: *mut kvm_t, loadavg: *mut ::c_double, nelem: ::c_int) -> ::c_int; pub fn kvm_openfiles( execfile: *const ::c_char, corefile: *const ::c_char, swapfile: *const ::c_char, flags: ::c_int, errbuf: *mut ::c_char, ) -> *mut ::kvm_t; pub fn kvm_read( kd: *mut ::kvm_t, addr: ::c_ulong, buf: *mut ::c_void, nbytes: ::size_t, ) -> ::ssize_t; pub fn kvm_write( kd: *mut ::kvm_t, addr: ::c_ulong, buf: *const ::c_void, nbytes: ::size_t, ) -> ::ssize_t; } cfg_if! { if #[cfg(target_os = "freebsd")] { mod freebsd; pub use self::freebsd::*; } else if #[cfg(target_os = "dragonfly")] { mod dragonfly; pub use self::dragonfly::*; } else { // ... } } libc/src/unix/newlib/0000775000175000017500000000000014661133735015506 5ustar jamespagejamespagelibc/src/unix/newlib/espidf/0000775000175000017500000000000014661133735016760 5ustar jamespagejamespagelibc/src/unix/newlib/espidf/mod.rs0000644000175000017500000000643514661133735020113 0ustar jamespagejamespagepub type clock_t = ::c_ulong; pub type c_char = i8; pub type wchar_t = u32; pub type c_long = i32; pub type c_ulong = u32; s! { pub struct cmsghdr { pub cmsg_len: ::socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct sockaddr_un { pub sun_family: ::sa_family_t, pub sun_path: [::c_char; 108], } pub struct sockaddr { pub sa_len: u8, pub sa_family: ::sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: ::sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [::c_char; 8], } pub struct sockaddr_storage { pub s2_len: u8, pub ss_family: ::sa_family_t, pub s2_data1: [::c_char; 2], pub s2_data2: [u32; 3], pub s2_data3: [u32; 3], } } pub const AF_UNIX: ::c_int = 1; pub const AF_INET6: ::c_int = 10; pub const FIONBIO: ::c_ulong = 2147772030; pub const POLLIN: ::c_short = 1 << 0; pub const POLLRDNORM: ::c_short = 1 << 1; pub const POLLRDBAND: ::c_short = 1 << 2; pub const POLLPRI: ::c_short = POLLRDBAND; pub const POLLOUT: ::c_short = 1 << 3; pub const POLLWRNORM: ::c_short = POLLOUT; pub const POLLWRBAND: ::c_short = 1 << 4; pub const POLLERR: ::c_short = 1 << 5; pub const POLLHUP: ::c_short = 1 << 6; pub const SOL_SOCKET: ::c_int = 0xfff; pub const MSG_OOB: ::c_int = 0x04; pub const MSG_PEEK: ::c_int = 0x01; pub const MSG_DONTWAIT: ::c_int = 0x08; pub const MSG_DONTROUTE: ::c_int = 0x4; pub const MSG_WAITALL: ::c_int = 0x02; pub const MSG_MORE: ::c_int = 0x10; pub const MSG_NOSIGNAL: ::c_int = 0x20; pub const MSG_TRUNC: ::c_int = 0x04; pub const MSG_CTRUNC: ::c_int = 0x08; pub const MSG_EOR: ::c_int = 0x08; pub const PTHREAD_STACK_MIN: ::size_t = 768; pub const SIGABRT: ::size_t = 1; pub const SIGFPE: ::size_t = 1; pub const SIGILL: ::size_t = 1; pub const SIGINT: ::size_t = 1; pub const SIGSEGV: ::size_t = 1; pub const SIGTERM: ::size_t = 1; pub const SIGHUP: ::size_t = 1; pub const SIGQUIT: ::size_t = 1; pub const NSIG: ::size_t = 2; extern "C" { pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; #[link_name = "lwip_sendmsg"] pub fn sendmsg(s: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; #[link_name = "lwip_recvmsg"] pub fn recvmsg(s: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn eventfd(initval: ::c_uint, flags: ::c_int) -> ::c_int; } pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; libc/src/unix/newlib/vita/0000775000175000017500000000000014661133735016451 5ustar jamespagejamespagelibc/src/unix/newlib/vita/mod.rs0000644000175000017500000001472214661133735017602 0ustar jamespagejamespagepub type clock_t = ::c_long; pub type c_char = i8; pub type wchar_t = u32; pub type c_long = i32; pub type c_ulong = u32; pub type sigset_t = ::c_ulong; s! { pub struct msghdr { pub msg_name: *mut ::c_void, pub msg_namelen: ::socklen_t, pub msg_iov: *mut ::iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut ::c_void, pub msg_controllen: ::socklen_t, pub msg_flags: ::c_int, } pub struct sockaddr { pub sa_len: u8, pub sa_family: ::sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: ::sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_vport: ::in_port_t, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_vport: ::in_port_t, pub sin_zero: [u8; 6], } pub struct sockaddr_un { pub ss_len: u8, pub sun_family: ::sa_family_t, pub sun_path: [::c_char; 108usize], } pub struct sockaddr_storage { pub ss_len: u8, pub ss_family: ::sa_family_t, pub __ss_pad1: [u8; 2], pub __ss_align: i64, pub __ss_pad2: [u8; 116], } pub struct sched_param { pub sched_priority: ::c_int, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atime: ::time_t, pub st_mtime: ::time_t, pub st_ctime: ::time_t, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_spare4: [::c_long; 2usize], } #[repr(align(8))] pub struct dirent { __offset: [u8; 88], pub d_name: [::c_char; 256usize], __pad: [u8; 8], } } pub const AF_UNIX: ::c_int = 1; pub const AF_INET6: ::c_int = 24; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOMAXCONN: ::c_int = 128; pub const FIONBIO: ::c_ulong = 1; pub const POLLIN: ::c_short = 0x0001; pub const POLLPRI: ::c_short = POLLIN; pub const POLLOUT: ::c_short = 0x0004; pub const POLLRDNORM: ::c_short = POLLIN; pub const POLLRDBAND: ::c_short = POLLIN; pub const POLLWRNORM: ::c_short = POLLOUT; pub const POLLWRBAND: ::c_short = POLLOUT; pub const POLLERR: ::c_short = 0x0008; pub const POLLHUP: ::c_short = 0x0010; pub const POLLNVAL: ::c_short = 0x0020; pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void; pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_NONBLOCK: ::c_int = 0x1100; pub const MSG_OOB: ::c_int = 0x1; pub const MSG_PEEK: ::c_int = 0x2; pub const MSG_DONTROUTE: ::c_int = 0x4; pub const MSG_EOR: ::c_int = 0x8; pub const MSG_TRUNC: ::c_int = 0x10; pub const MSG_CTRUNC: ::c_int = 0x20; pub const MSG_WAITALL: ::c_int = 0x40; pub const MSG_DONTWAIT: ::c_int = 0x80; pub const MSG_BCAST: ::c_int = 0x100; pub const MSG_MCAST: ::c_int = 0x200; pub const UTIME_OMIT: c_long = -1; pub const AT_FDCWD: ::c_int = -2; pub const O_DIRECTORY: ::c_int = 0x200000; pub const O_NOFOLLOW: ::c_int = 0x100000; pub const AT_EACCESS: ::c_int = 1; pub const AT_SYMLINK_NOFOLLOW: ::c_int = 2; pub const AT_SYMLINK_FOLLOW: ::c_int = 4; pub const AT_REMOVEDIR: ::c_int = 8; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGTRAP: ::c_int = 5; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGBUS: ::c_int = 10; pub const SIGSEGV: ::c_int = 11; pub const SIGSYS: ::c_int = 12; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const EAI_BADFLAGS: ::c_int = -1; pub const EAI_NONAME: ::c_int = -2; pub const EAI_AGAIN: ::c_int = -3; pub const EAI_FAIL: ::c_int = -4; pub const EAI_NODATA: ::c_int = -5; pub const EAI_FAMILY: ::c_int = -6; pub const EAI_SOCKTYPE: ::c_int = -7; pub const EAI_SERVICE: ::c_int = -8; pub const EAI_ADDRFAMILY: ::c_int = -9; pub const EAI_MEMORY: ::c_int = -10; pub const EAI_SYSTEM: ::c_int = -11; pub const EAI_OVERFLOW: ::c_int = -12; pub const _SC_PAGESIZE: ::c_int = 8; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51; pub const PTHREAD_STACK_MIN: ::size_t = 32 * 1024; pub const IP_HDRINCL: ::c_int = 2; extern "C" { pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn sendmsg(s: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn recvmsg(s: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn pthread_attr_getschedparam( attr: *const ::pthread_attr_t, param: *mut sched_param, ) -> ::c_int; pub fn pthread_attr_setschedparam( attr: *mut ::pthread_attr_t, param: *const sched_param, ) -> ::c_int; pub fn pthread_attr_getprocessorid_np( attr: *const ::pthread_attr_t, processor_id: *mut ::c_int, ) -> ::c_int; pub fn pthread_attr_setprocessorid_np( attr: *mut ::pthread_attr_t, processor_id: ::c_int, ) -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut ::sched_param, ) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const ::pthread_condattr_t, clock_id: *mut ::clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut ::pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn pthread_getprocessorid_np() -> ::c_int; pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; pub fn pipe2(fds: *mut ::c_int, flags: ::c_int) -> ::c_int; } libc/src/unix/newlib/arm/0000775000175000017500000000000014661133735016265 5ustar jamespagejamespagelibc/src/unix/newlib/arm/mod.rs0000644000175000017500000000254414661133735017415 0ustar jamespagejamespagepub type clock_t = ::c_long; pub type c_char = u8; pub type wchar_t = u32; pub type c_long = i32; pub type c_ulong = u32; s! { pub struct sockaddr { pub sa_family: ::sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in6 { pub sin6_family: ::sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [u8; 8], } pub struct sockaddr_storage { pub ss_family: ::sa_family_t, pub __ss_padding: [u8; 26], } } pub const AF_INET6: ::c_int = 23; pub const FIONBIO: ::c_ulong = 1; pub const POLLIN: ::c_short = 0x1; pub const POLLPRI: ::c_short = 0x2; pub const POLLHUP: ::c_short = 0x4; pub const POLLERR: ::c_short = 0x8; pub const POLLOUT: ::c_short = 0x10; pub const POLLNVAL: ::c_short = 0x20; pub const SOL_SOCKET: ::c_int = 65535; pub const MSG_OOB: ::c_int = 1; pub const MSG_PEEK: ::c_int = 2; pub const MSG_DONTWAIT: ::c_int = 4; pub const MSG_DONTROUTE: ::c_int = 0; pub const MSG_WAITALL: ::c_int = 0; pub const MSG_MORE: ::c_int = 0; pub const MSG_NOSIGNAL: ::c_int = 0; pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; libc/src/unix/newlib/powerpc/0000775000175000017500000000000014661133735017165 5ustar jamespagejamespagelibc/src/unix/newlib/powerpc/mod.rs0000644000175000017500000000054114661133735020310 0ustar jamespagejamespagepub type clock_t = ::c_ulong; pub type c_char = u8; pub type wchar_t = ::c_int; pub type c_long = i32; pub type c_ulong = u32; pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; // the newlib shipped with devkitPPC does not support the following components: // - sockaddr // - AF_INET6 // - FIONBIO // - POLL* // - SOL_SOCKET // - MSG_* libc/src/unix/newlib/aarch64/0000775000175000017500000000000014661133735016736 5ustar jamespagejamespagelibc/src/unix/newlib/aarch64/mod.rs0000644000175000017500000000250214661133735020060 0ustar jamespagejamespagepub type clock_t = ::c_long; pub type c_char = u8; pub type wchar_t = u32; pub type c_long = i64; pub type c_ulong = u64; s! { pub struct sockaddr { pub sa_len: u8, pub sa_family: ::sa_family_t, pub sa_data: [::c_char; 14], } pub struct sockaddr_in6 { pub sin6_len: u8, pub sin6_family: ::sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_in { pub sin_len: u8, pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, pub sin_zero: [::c_char; 8], } } pub const AF_INET6: ::c_int = 23; pub const FIONBIO: ::c_ulong = 1; pub const POLLIN: ::c_short = 0x1; pub const POLLPRI: ::c_short = 0x2; pub const POLLOUT: ::c_short = 0x4; pub const POLLERR: ::c_short = 0x8; pub const POLLHUP: ::c_short = 0x10; pub const POLLNVAL: ::c_short = 0x20; pub const SOL_SOCKET: ::c_int = 65535; pub const MSG_OOB: ::c_int = 1; pub const MSG_PEEK: ::c_int = 2; pub const MSG_DONTWAIT: ::c_int = 4; pub const MSG_DONTROUTE: ::c_int = 0; pub const MSG_WAITALL: ::c_int = 0; pub const MSG_MORE: ::c_int = 0; pub const MSG_NOSIGNAL: ::c_int = 0; pub use crate::unix::newlib::generic::{dirent, sigset_t, stat}; libc/src/unix/newlib/mod.rs0000644000175000017500000006205714661133735016643 0ustar jamespagejamespagepub type blkcnt_t = i32; pub type blksize_t = i32; pub type clockid_t = ::c_ulong; cfg_if! { if #[cfg(any(target_os = "espidf"))] { pub type dev_t = ::c_short; pub type ino_t = ::c_ushort; pub type off_t = ::c_long; } else if #[cfg(any(target_os = "vita"))] { pub type dev_t = ::c_short; pub type ino_t = ::c_ushort; pub type off_t = ::c_int; } else { pub type dev_t = u32; pub type ino_t = u32; pub type off_t = i64; } } pub type fsblkcnt_t = u64; pub type fsfilcnt_t = u32; pub type id_t = u32; pub type key_t = ::c_int; pub type loff_t = ::c_longlong; pub type mode_t = ::c_uint; pub type nfds_t = u32; pub type nlink_t = ::c_ushort; pub type pthread_t = ::c_ulong; pub type pthread_key_t = ::c_uint; pub type rlim_t = u32; cfg_if! { if #[cfg(target_os = "horizon")] { pub type sa_family_t = u16; } else { pub type sa_family_t = u8; } } pub type socklen_t = u32; pub type speed_t = u32; pub type suseconds_t = i32; pub type tcflag_t = ::c_uint; pub type useconds_t = u32; cfg_if! { if #[cfg(any(target_os = "horizon", all(target_os = "espidf", espidf_time64)))] { pub type time_t = ::c_longlong; } else { pub type time_t = i32; } } s! { // The order of the `ai_addr` field in this struct is crucial // for converting between the Rust and C types. pub struct addrinfo { pub ai_flags: ::c_int, pub ai_family: ::c_int, pub ai_socktype: ::c_int, pub ai_protocol: ::c_int, pub ai_addrlen: socklen_t, #[cfg(target_os = "espidf")] pub ai_addr: *mut sockaddr, pub ai_canonname: *mut ::c_char, #[cfg(not(any( target_os = "espidf", all(libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo"))))] pub ai_addr: *mut sockaddr, pub ai_next: *mut addrinfo, } pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } pub struct linger { pub l_onoff: ::c_int, pub l_linger: ::c_int, } pub struct in_addr { pub s_addr: ::in_addr_t, } pub struct hostent { pub h_name: *mut ::c_char, pub h_aliases: *mut *mut ::c_char, pub h_addrtype: ::c_int, pub h_length: ::c_int, pub h_addr_list: *mut *mut ::c_char, pub h_addr: *mut ::c_char, } pub struct pollfd { pub fd: ::c_int, pub events: ::c_int, pub revents: ::c_int, } pub struct lconv { pub decimal_point: *mut ::c_char, pub thousands_sep: *mut ::c_char, pub grouping: *mut ::c_char, pub int_curr_symbol: *mut ::c_char, pub currency_symbol: *mut ::c_char, pub mon_decimal_point: *mut ::c_char, pub mon_thousands_sep: *mut ::c_char, pub mon_grouping: *mut ::c_char, pub positive_sign: *mut ::c_char, pub negative_sign: *mut ::c_char, pub int_frac_digits: ::c_char, pub frac_digits: ::c_char, pub p_cs_precedes: ::c_char, pub p_sep_by_space: ::c_char, pub n_cs_precedes: ::c_char, pub n_sep_by_space: ::c_char, pub p_sign_posn: ::c_char, pub n_sign_posn: ::c_char, pub int_n_cs_precedes: ::c_char, pub int_n_sep_by_space: ::c_char, pub int_n_sign_posn: ::c_char, pub int_p_cs_precedes: ::c_char, pub int_p_sep_by_space: ::c_char, pub int_p_sign_posn: ::c_char, } pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, } pub struct statvfs { pub f_bsize: ::c_ulong, pub f_frsize: ::c_ulong, pub f_blocks: fsblkcnt_t, pub f_bfree: fsblkcnt_t, pub f_bavail: fsblkcnt_t, pub f_files: fsfilcnt_t, pub f_ffree: fsfilcnt_t, pub f_favail: fsfilcnt_t, pub f_fsid: ::c_ulong, pub f_flag: ::c_ulong, pub f_namemax: ::c_ulong, } pub struct sigaction { pub sa_handler: extern fn(arg1: ::c_int), pub sa_mask: sigset_t, pub sa_flags: ::c_int, } pub struct stack_t { pub ss_sp: *mut ::c_void, pub ss_flags: ::c_int, pub ss_size: usize, } pub struct fd_set { // Unverified fds_bits: [::c_ulong; FD_SETSIZE / ULONG_SIZE], } pub struct passwd { // Unverified pub pw_name: *mut ::c_char, pub pw_passwd: *mut ::c_char, pub pw_uid: ::uid_t, pub pw_gid: ::gid_t, pub pw_gecos: *mut ::c_char, pub pw_dir: *mut ::c_char, pub pw_shell: *mut ::c_char, } pub struct termios { // Unverified pub c_iflag: ::tcflag_t, pub c_oflag: ::tcflag_t, pub c_cflag: ::tcflag_t, pub c_lflag: ::tcflag_t, pub c_line: ::cc_t, pub c_cc: [::cc_t; ::NCCS], } pub struct sem_t { // Unverified __size: [::c_char; 16], } pub struct Dl_info { // Unverified pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct utsname { // Unverified pub sysname: [::c_char; 65], pub nodename: [::c_char; 65], pub release: [::c_char; 65], pub version: [::c_char; 65], pub machine: [::c_char; 65], pub domainname: [::c_char; 65] } pub struct cpu_set_t { // Unverified bits: [u32; 32], } pub struct pthread_attr_t { // Unverified __size: [u8; __SIZEOF_PTHREAD_ATTR_T] } pub struct pthread_rwlockattr_t { // Unverified __size: [u8; __SIZEOF_PTHREAD_RWLOCKATTR_T] } } // unverified constants align_const! { pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_RWLOCK_T], }; } pub const NCCS: usize = 32; cfg_if! { if #[cfg(target_os = "espidf")] { const __PTHREAD_INITIALIZER_BYTE: u8 = 0xff; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 32; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 12; pub const __SIZEOF_PTHREAD_COND_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 12; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; } else if #[cfg(target_os = "vita")] { const __PTHREAD_INITIALIZER_BYTE: u8 = 0xff; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 4; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_COND_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 4; } else { const __PTHREAD_INITIALIZER_BYTE: u8 = 0; pub const __SIZEOF_PTHREAD_ATTR_T: usize = 56; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56; pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8; pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32; } } pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4; pub const __PTHREAD_MUTEX_HAVE_PREV: usize = 1; pub const __PTHREAD_RWLOCK_INT_FLAGS_SHARED: usize = 1; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 2; cfg_if! { if #[cfg(any(target_os = "horizon", target_os = "espidf"))] { pub const FD_SETSIZE: usize = 64; } else if #[cfg(target_os = "vita")] { pub const FD_SETSIZE: usize = 256; } else { pub const FD_SETSIZE: usize = 1024; } } // intentionally not public, only used for fd_set const ULONG_SIZE: usize = 32; // Other constants pub const EPERM: ::c_int = 1; pub const ENOENT: ::c_int = 2; pub const ESRCH: ::c_int = 3; pub const EINTR: ::c_int = 4; pub const EIO: ::c_int = 5; pub const ENXIO: ::c_int = 6; pub const E2BIG: ::c_int = 7; pub const ENOEXEC: ::c_int = 8; pub const EBADF: ::c_int = 9; pub const ECHILD: ::c_int = 10; pub const EAGAIN: ::c_int = 11; pub const ENOMEM: ::c_int = 12; pub const EACCES: ::c_int = 13; pub const EFAULT: ::c_int = 14; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENFILE: ::c_int = 23; pub const EMFILE: ::c_int = 24; pub const ENOTTY: ::c_int = 25; pub const ETXTBSY: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDOM: ::c_int = 33; pub const ERANGE: ::c_int = 34; pub const ENOMSG: ::c_int = 35; pub const EIDRM: ::c_int = 36; pub const EDEADLK: ::c_int = 45; pub const ENOLCK: ::c_int = 46; pub const ENOSTR: ::c_int = 60; pub const ENODATA: ::c_int = 61; pub const ETIME: ::c_int = 62; pub const ENOSR: ::c_int = 63; pub const ENOLINK: ::c_int = 67; pub const EPROTO: ::c_int = 71; pub const EMULTIHOP: ::c_int = 74; pub const EBADMSG: ::c_int = 77; pub const EFTYPE: ::c_int = 79; pub const ENOSYS: ::c_int = 88; pub const ENOTEMPTY: ::c_int = 90; pub const ENAMETOOLONG: ::c_int = 91; pub const ELOOP: ::c_int = 92; pub const EOPNOTSUPP: ::c_int = 95; pub const EPFNOSUPPORT: ::c_int = 96; pub const ECONNRESET: ::c_int = 104; pub const ENOBUFS: ::c_int = 105; pub const EAFNOSUPPORT: ::c_int = 106; pub const EPROTOTYPE: ::c_int = 107; pub const ENOTSOCK: ::c_int = 108; pub const ENOPROTOOPT: ::c_int = 109; pub const ECONNREFUSED: ::c_int = 111; pub const EADDRINUSE: ::c_int = 112; pub const ECONNABORTED: ::c_int = 113; pub const ENETUNREACH: ::c_int = 114; pub const ENETDOWN: ::c_int = 115; pub const ETIMEDOUT: ::c_int = 116; pub const EHOSTDOWN: ::c_int = 117; pub const EHOSTUNREACH: ::c_int = 118; pub const EINPROGRESS: ::c_int = 119; pub const EALREADY: ::c_int = 120; pub const EDESTADDRREQ: ::c_int = 121; pub const EMSGSIZE: ::c_int = 122; pub const EPROTONOSUPPORT: ::c_int = 123; pub const EADDRNOTAVAIL: ::c_int = 125; pub const ENETRESET: ::c_int = 126; pub const EISCONN: ::c_int = 127; pub const ENOTCONN: ::c_int = 128; pub const ETOOMANYREFS: ::c_int = 129; pub const EDQUOT: ::c_int = 132; pub const ESTALE: ::c_int = 133; pub const ENOTSUP: ::c_int = 134; pub const EILSEQ: ::c_int = 138; pub const EOVERFLOW: ::c_int = 139; pub const ECANCELED: ::c_int = 140; pub const ENOTRECOVERABLE: ::c_int = 141; pub const EOWNERDEAD: ::c_int = 142; pub const EWOULDBLOCK: ::c_int = 11; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const F_GETOWN: ::c_int = 5; pub const F_SETOWN: ::c_int = 6; pub const F_GETLK: ::c_int = 7; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const F_RGETLK: ::c_int = 10; pub const F_RSETLK: ::c_int = 11; pub const F_CNVT: ::c_int = 12; pub const F_RSETLKW: ::c_int = 13; pub const F_DUPFD_CLOEXEC: ::c_int = 14; pub const O_RDONLY: ::c_int = 0; pub const O_WRONLY: ::c_int = 1; pub const O_RDWR: ::c_int = 2; pub const O_APPEND: ::c_int = 8; pub const O_CREAT: ::c_int = 512; pub const O_TRUNC: ::c_int = 1024; pub const O_EXCL: ::c_int = 2048; pub const O_SYNC: ::c_int = 8192; pub const O_NONBLOCK: ::c_int = 16384; pub const O_ACCMODE: ::c_int = 3; pub const O_CLOEXEC: ::c_int = 0x80000; pub const RTLD_LAZY: ::c_int = 0x1; pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; pub const FIOCLEX: ::c_ulong = 0x20006601; pub const FIONCLEX: ::c_ulong = 0x20006602; pub const S_BLKSIZE: ::mode_t = 1024; pub const S_IREAD: ::mode_t = 256; pub const S_IWRITE: ::mode_t = 128; pub const S_IEXEC: ::mode_t = 64; pub const S_ENFMT: ::mode_t = 1024; pub const S_IFMT: ::mode_t = 61440; pub const S_IFDIR: ::mode_t = 16384; pub const S_IFCHR: ::mode_t = 8192; pub const S_IFBLK: ::mode_t = 24576; pub const S_IFREG: ::mode_t = 32768; pub const S_IFLNK: ::mode_t = 40960; pub const S_IFSOCK: ::mode_t = 49152; pub const S_IFIFO: ::mode_t = 4096; pub const S_IRUSR: ::mode_t = 256; pub const S_IWUSR: ::mode_t = 128; pub const S_IXUSR: ::mode_t = 64; pub const S_IRGRP: ::mode_t = 32; pub const S_IWGRP: ::mode_t = 16; pub const S_IXGRP: ::mode_t = 8; pub const S_IROTH: ::mode_t = 4; pub const S_IWOTH: ::mode_t = 2; pub const S_IXOTH: ::mode_t = 1; pub const SOL_TCP: ::c_int = 6; pub const PF_UNSPEC: ::c_int = 0; pub const PF_INET: ::c_int = 2; pub const PF_INET6: ::c_int = 23; pub const AF_UNSPEC: ::c_int = 0; pub const AF_INET: ::c_int = 2; pub const CLOCK_REALTIME: ::clockid_t = 1; pub const CLOCK_MONOTONIC: ::clockid_t = 4; pub const CLOCK_BOOTTIME: ::clockid_t = 4; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const SO_BINTIME: ::c_int = 0x2000; pub const SO_NO_OFFLOAD: ::c_int = 0x4000; pub const SO_NO_DDP: ::c_int = 0x8000; pub const SO_REUSEPORT_LB: ::c_int = 0x10000; pub const SO_LABEL: ::c_int = 0x1009; pub const SO_PEERLABEL: ::c_int = 0x1010; pub const SO_LISTENQLIMIT: ::c_int = 0x1011; pub const SO_LISTENQLEN: ::c_int = 0x1012; pub const SO_LISTENINCQLEN: ::c_int = 0x1013; pub const SO_SETFIB: ::c_int = 0x1014; pub const SO_USER_COOKIE: ::c_int = 0x1015; pub const SO_PROTOCOL: ::c_int = 0x1016; pub const SO_PROTOTYPE: ::c_int = SO_PROTOCOL; pub const SO_VENDOR: ::c_int = 0x80000000; pub const SO_DEBUG: ::c_int = 0x01; pub const SO_ACCEPTCONN: ::c_int = 0x0002; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_OOBINLINE: ::c_int = 0x0100; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_TIMESTAMP: ::c_int = 0x0400; pub const SO_NOSIGPIPE: ::c_int = 0x0800; pub const SO_ACCEPTFILTER: ::c_int = 0x1000; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_SNDLOWAT: ::c_int = 0x1003; pub const SO_RCVLOWAT: ::c_int = 0x1004; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_RCVTIMEO: ::c_int = 0x1006; cfg_if! { if #[cfg(target_os = "horizon")] { pub const SO_ERROR: ::c_int = 0x1009; } else { pub const SO_ERROR: ::c_int = 0x1007; } } pub const SO_TYPE: ::c_int = 0x1008; pub const SOCK_CLOEXEC: ::c_int = O_CLOEXEC; pub const INET_ADDRSTRLEN: ::c_int = 16; // https://github.com/bminor/newlib/blob/HEAD/newlib/libc/sys/linux/include/net/if.h#L121 pub const IFF_UP: ::c_int = 0x1; // interface is up pub const IFF_BROADCAST: ::c_int = 0x2; // broadcast address valid pub const IFF_DEBUG: ::c_int = 0x4; // turn on debugging pub const IFF_LOOPBACK: ::c_int = 0x8; // is a loopback net pub const IFF_POINTOPOINT: ::c_int = 0x10; // interface is point-to-point link pub const IFF_NOTRAILERS: ::c_int = 0x20; // avoid use of trailers pub const IFF_RUNNING: ::c_int = 0x40; // resources allocated pub const IFF_NOARP: ::c_int = 0x80; // no address resolution protocol pub const IFF_PROMISC: ::c_int = 0x100; // receive all packets pub const IFF_ALLMULTI: ::c_int = 0x200; // receive all multicast packets pub const IFF_OACTIVE: ::c_int = 0x400; // transmission in progress pub const IFF_SIMPLEX: ::c_int = 0x800; // can't hear own transmissions pub const IFF_LINK0: ::c_int = 0x1000; // per link layer defined bit pub const IFF_LINK1: ::c_int = 0x2000; // per link layer defined bit pub const IFF_LINK2: ::c_int = 0x4000; // per link layer defined bit pub const IFF_ALTPHYS: ::c_int = IFF_LINK2; // use alternate physical connection pub const IFF_MULTICAST: ::c_int = 0x8000; // supports multicast cfg_if! { if #[cfg(target_os = "vita")] { pub const TCP_NODELAY: ::c_int = 1; pub const TCP_MAXSEG: ::c_int = 2; } else { pub const TCP_NODELAY: ::c_int = 8193; pub const TCP_MAXSEG: ::c_int = 8194; } } pub const TCP_NOPUSH: ::c_int = 4; pub const TCP_NOOPT: ::c_int = 8; pub const TCP_KEEPIDLE: ::c_int = 256; pub const TCP_KEEPINTVL: ::c_int = 512; pub const TCP_KEEPCNT: ::c_int = 1024; cfg_if! { if #[cfg(target_os = "horizon")] { pub const IP_TOS: ::c_int = 7; } else { pub const IP_TOS: ::c_int = 3; } } cfg_if! { if #[cfg(target_os = "vita")] { pub const IP_TTL: ::c_int = 4; } else { pub const IP_TTL: ::c_int = 8; } } pub const IP_MULTICAST_IF: ::c_int = 9; pub const IP_MULTICAST_TTL: ::c_int = 10; pub const IP_MULTICAST_LOOP: ::c_int = 11; cfg_if! { if #[cfg(target_os = "vita")] { pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; } else { pub const IP_ADD_MEMBERSHIP: ::c_int = 11; pub const IP_DROP_MEMBERSHIP: ::c_int = 12; } } pub const IPV6_UNICAST_HOPS: ::c_int = 4; pub const IPV6_MULTICAST_IF: ::c_int = 9; pub const IPV6_MULTICAST_HOPS: ::c_int = 10; pub const IPV6_MULTICAST_LOOP: ::c_int = 11; pub const IPV6_V6ONLY: ::c_int = 27; pub const IPV6_JOIN_GROUP: ::c_int = 12; pub const IPV6_LEAVE_GROUP: ::c_int = 13; pub const IPV6_ADD_MEMBERSHIP: ::c_int = 12; pub const IPV6_DROP_MEMBERSHIP: ::c_int = 13; pub const HOST_NOT_FOUND: ::c_int = 1; pub const NO_DATA: ::c_int = 2; pub const NO_ADDRESS: ::c_int = 2; pub const NO_RECOVERY: ::c_int = 3; pub const TRY_AGAIN: ::c_int = 4; pub const AI_PASSIVE: ::c_int = 1; pub const AI_CANONNAME: ::c_int = 2; pub const AI_NUMERICHOST: ::c_int = 4; pub const AI_NUMERICSERV: ::c_int = 0; pub const AI_ADDRCONFIG: ::c_int = 0; pub const NI_MAXHOST: ::c_int = 1025; pub const NI_MAXSERV: ::c_int = 32; pub const NI_NOFQDN: ::c_int = 1; pub const NI_NUMERICHOST: ::c_int = 2; pub const NI_NAMEREQD: ::c_int = 4; pub const NI_NUMERICSERV: ::c_int = 0; pub const NI_DGRAM: ::c_int = 0; cfg_if! { // Defined in vita/mod.rs for "vita" if #[cfg(not(target_os = "vita"))] { pub const EAI_FAMILY: ::c_int = -303; pub const EAI_MEMORY: ::c_int = -304; pub const EAI_NONAME: ::c_int = -305; pub const EAI_SOCKTYPE: ::c_int = -307; } } pub const EXIT_SUCCESS: ::c_int = 0; pub const EXIT_FAILURE: ::c_int = 1; pub const PRIO_PROCESS: ::c_int = 0; pub const PRIO_PGRP: ::c_int = 1; pub const PRIO_USER: ::c_int = 2; f! { pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] &= !(1 << (fd % bits)); return } pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; return ((*set).fds_bits[fd / bits] & (1 << (fd % bits))) != 0 } pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> () { let bits = ::mem::size_of_val(&(*set).fds_bits[0]) * 8; let fd = fd as usize; (*set).fds_bits[fd / bits] |= 1 << (fd % bits); return } pub fn FD_ZERO(set: *mut fd_set) -> () { for slot in (*set).fds_bits.iter_mut() { *slot = 0; } } } extern "C" { pub fn getrlimit(resource: ::c_int, rlim: *mut ::rlimit) -> ::c_int; pub fn setrlimit(resource: ::c_int, rlim: *const ::rlimit) -> ::c_int; #[cfg_attr(target_os = "linux", link_name = "__xpg_strerror_r")] pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn sem_destroy(sem: *mut sem_t) -> ::c_int; pub fn sem_init(sem: *mut sem_t, pshared: ::c_int, value: ::c_uint) -> ::c_int; pub fn abs(i: ::c_int) -> ::c_int; pub fn labs(i: ::c_long) -> ::c_long; pub fn rand() -> ::c_int; pub fn srand(seed: ::c_uint); #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr(target_os = "espidf", link_name = "lwip_bind")] pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) -> ::c_int; pub fn clock_settime(clock_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; pub fn clock_gettime(clock_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; pub fn clock_getres(clock_id: ::clockid_t, res: *mut ::timespec) -> ::c_int; #[cfg_attr(target_os = "espidf", link_name = "lwip_close")] pub fn closesocket(sockfd: ::c_int) -> ::c_int; pub fn ioctl(fd: ::c_int, request: ::c_ulong, ...) -> ::c_int; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] #[cfg_attr(target_os = "espidf", link_name = "lwip_recvfrom")] pub fn recvfrom( fd: ::c_int, buf: *mut ::c_void, n: usize, flags: ::c_int, addr: *mut sockaddr, addr_len: *mut socklen_t, ) -> isize; #[cfg(not(all( libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo" )))] pub fn getnameinfo( sa: *const sockaddr, salen: socklen_t, host: *mut ::c_char, hostlen: socklen_t, serv: *mut ::c_char, servlen: socklen_t, flags: ::c_int, ) -> ::c_int; pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void; pub fn fexecve( fd: ::c_int, argv: *const *const ::c_char, envp: *const *const ::c_char, ) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn getgrgid_r( gid: ::gid_t, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn sigaltstack(ss: *const stack_t, oss: *mut stack_t) -> ::c_int; pub fn sem_close(sem: *mut sem_t) -> ::c_int; pub fn getdtablesize() -> ::c_int; pub fn getgrnam_r( name: *const ::c_char, grp: *mut ::group, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut ::group, ) -> ::c_int; pub fn pthread_sigmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sem_open(name: *const ::c_char, oflag: ::c_int, ...) -> *mut sem_t; pub fn getgrnam(name: *const ::c_char) -> *mut ::group; pub fn pthread_kill(thread: ::pthread_t, sig: ::c_int) -> ::c_int; pub fn sem_unlink(name: *const ::c_char) -> ::c_int; pub fn daemon(nochdir: ::c_int, noclose: ::c_int) -> ::c_int; pub fn getpwnam_r( name: *const ::c_char, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn getpwuid_r( uid: ::uid_t, pwd: *mut passwd, buf: *mut ::c_char, buflen: ::size_t, result: *mut *mut passwd, ) -> ::c_int; pub fn sigwait(set: *const sigset_t, sig: *mut ::c_int) -> ::c_int; pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; pub fn getgrgid(gid: ::gid_t) -> *mut ::group; pub fn popen(command: *const c_char, mode: *const c_char) -> *mut ::FILE; pub fn uname(buf: *mut ::utsname) -> ::c_int; } mod generic; cfg_if! { if #[cfg(target_os = "espidf")] { mod espidf; pub use self::espidf::*; } else if #[cfg(target_os = "horizon")] { mod horizon; pub use self::horizon::*; } else if #[cfg(target_os = "vita")] { mod vita; pub use self::vita::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else { // Only tested on ARM so far. Other platforms might have different // definitions for types and constants. pub use target_arch_not_implemented; } } cfg_if! { if #[cfg(libc_align)] { #[macro_use] mod align; } else { #[macro_use] mod no_align; } } expand_align!(); libc/src/unix/newlib/horizon/0000775000175000017500000000000014661133735017176 5ustar jamespagejamespagelibc/src/unix/newlib/horizon/mod.rs0000644000175000017500000001627414661133735020333 0ustar jamespagejamespage//! ARMv6K Nintendo 3DS C Newlib definitions pub type c_char = u8; pub type c_long = i32; pub type c_ulong = u32; pub type wchar_t = ::c_uint; pub type u_register_t = ::c_uint; pub type u_char = ::c_uchar; pub type u_short = ::c_ushort; pub type u_int = ::c_uint; pub type u_long = c_ulong; pub type ushort = ::c_ushort; pub type uint = ::c_uint; pub type ulong = c_ulong; pub type clock_t = c_ulong; pub type daddr_t = c_long; pub type caddr_t = *mut c_char; pub type sbintime_t = ::c_longlong; pub type sigset_t = ::c_ulong; s! { pub struct sockaddr { pub sa_family: ::sa_family_t, pub sa_data: [::c_char; 26usize], } pub struct sockaddr_storage { pub ss_family: ::sa_family_t, pub __ss_padding: [::c_char; 26usize], } pub struct sockaddr_in { pub sin_family: ::sa_family_t, pub sin_port: ::in_port_t, pub sin_addr: ::in_addr, } pub struct sockaddr_in6 { pub sin6_family: ::sa_family_t, pub sin6_port: ::in_port_t, pub sin6_flowinfo: u32, pub sin6_addr: ::in6_addr, pub sin6_scope_id: u32, } pub struct sockaddr_un { pub sun_len: ::c_uchar, pub sun_family: ::sa_family_t, pub sun_path: [::c_char; 104usize], } pub struct sched_param { pub sched_priority: ::c_int, } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atim: ::timespec, pub st_mtim: ::timespec, pub st_ctim: ::timespec, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_spare4: [::c_long; 2usize], } } pub const SIGEV_NONE: ::c_int = 1; pub const SIGEV_SIGNAL: ::c_int = 2; pub const SIGEV_THREAD: ::c_int = 3; pub const SA_NOCLDSTOP: ::c_int = 1; pub const MINSIGSTKSZ: ::c_int = 2048; pub const SIGSTKSZ: ::c_int = 8192; pub const SS_ONSTACK: ::c_int = 1; pub const SS_DISABLE: ::c_int = 2; pub const SIG_SETMASK: ::c_int = 0; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGTRAP: ::c_int = 5; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGBUS: ::c_int = 10; pub const SIGSEGV: ::c_int = 11; pub const SIGSYS: ::c_int = 12; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const SIGURG: ::c_int = 16; pub const SIGSTOP: ::c_int = 17; pub const SIGTSTP: ::c_int = 18; pub const SIGCONT: ::c_int = 19; pub const SIGCHLD: ::c_int = 20; pub const SIGCLD: ::c_int = 20; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIGIO: ::c_int = 23; pub const SIGPOLL: ::c_int = 23; pub const SIGXCPU: ::c_int = 24; pub const SIGXFSZ: ::c_int = 25; pub const SIGVTALRM: ::c_int = 26; pub const SIGPROF: ::c_int = 27; pub const SIGWINCH: ::c_int = 28; pub const SIGLOST: ::c_int = 29; pub const SIGUSR1: ::c_int = 30; pub const SIGUSR2: ::c_int = 31; pub const NSIG: ::c_int = 32; pub const CLOCK_ENABLED: ::c_uint = 1; pub const CLOCK_DISABLED: ::c_uint = 0; pub const CLOCK_ALLOWED: ::c_uint = 1; pub const CLOCK_DISALLOWED: ::c_uint = 0; pub const TIMER_ABSTIME: ::c_uint = 4; pub const SOL_SOCKET: ::c_int = 65535; pub const MSG_OOB: ::c_int = 1; pub const MSG_PEEK: ::c_int = 2; pub const MSG_DONTWAIT: ::c_int = 4; pub const MSG_DONTROUTE: ::c_int = 0; pub const MSG_WAITALL: ::c_int = 0; pub const MSG_MORE: ::c_int = 0; pub const MSG_NOSIGNAL: ::c_int = 0; pub const SOL_CONFIG: ::c_uint = 65534; pub const _SC_PAGESIZE: ::c_int = 8; pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 51; pub const PTHREAD_STACK_MIN: ::size_t = 4096; pub const WNOHANG: ::c_int = 1; pub const POLLIN: ::c_short = 0x0001; pub const POLLPRI: ::c_short = 0x0002; pub const POLLOUT: ::c_short = 0x0004; pub const POLLRDNORM: ::c_short = 0x0040; pub const POLLWRNORM: ::c_short = POLLOUT; pub const POLLRDBAND: ::c_short = 0x0080; pub const POLLWRBAND: ::c_short = 0x0100; pub const POLLERR: ::c_short = 0x0008; pub const POLLHUP: ::c_short = 0x0010; pub const POLLNVAL: ::c_short = 0x0020; pub const EAI_AGAIN: ::c_int = 2; pub const EAI_BADFLAGS: ::c_int = 3; pub const EAI_FAIL: ::c_int = 4; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SYSTEM: ::c_int = 11; pub const EAI_BADHINTS: ::c_int = 12; pub const EAI_PROTOCOL: ::c_int = 13; pub const EAI_OVERFLOW: ::c_int = 14; pub const EAI_MAX: ::c_int = 15; pub const AF_UNIX: ::c_int = 1; pub const AF_INET6: ::c_int = 23; pub const FIONBIO: ::c_ulong = 1; pub const RTLD_DEFAULT: *mut ::c_void = 0 as *mut ::c_void; // For pthread get/setschedparam pub const SCHED_FIFO: ::c_int = 1; pub const SCHED_RR: ::c_int = 2; // For getrandom() pub const GRND_NONBLOCK: ::c_uint = 0x1; pub const GRND_RANDOM: ::c_uint = 0x2; // Horizon OS works doesn't or can't hold any of this information safe_f! { pub {const} fn WIFSTOPPED(_status: ::c_int) -> bool { false } pub {const} fn WSTOPSIG(_status: ::c_int) -> ::c_int { 0 } pub {const} fn WIFCONTINUED(_status: ::c_int) -> bool { true } pub {const} fn WIFSIGNALED(_status: ::c_int) -> bool { false } pub {const} fn WTERMSIG(_status: ::c_int) -> ::c_int { 0 } pub {const} fn WIFEXITED(_status: ::c_int) -> bool { true } pub {const} fn WEXITSTATUS(_status: ::c_int) -> ::c_int { 0 } pub {const} fn WCOREDUMP(_status: ::c_int) -> bool { false } } extern "C" { pub fn pthread_create( native: *mut ::pthread_t, attr: *const ::pthread_attr_t, f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; pub fn pthread_attr_getschedparam( attr: *const ::pthread_attr_t, param: *mut sched_param, ) -> ::c_int; pub fn pthread_attr_setschedparam( attr: *mut ::pthread_attr_t, param: *const sched_param, ) -> ::c_int; pub fn pthread_attr_getprocessorid_np( attr: *const ::pthread_attr_t, processor_id: *mut ::c_int, ) -> ::c_int; pub fn pthread_attr_setprocessorid_np( attr: *mut ::pthread_attr_t, processor_id: ::c_int, ) -> ::c_int; pub fn pthread_getschedparam( native: ::pthread_t, policy: *mut ::c_int, param: *mut ::sched_param, ) -> ::c_int; pub fn pthread_setschedparam( native: ::pthread_t, policy: ::c_int, param: *const ::sched_param, ) -> ::c_int; pub fn pthread_condattr_getclock( attr: *const ::pthread_condattr_t, clock_id: *mut ::clockid_t, ) -> ::c_int; pub fn pthread_condattr_setclock( attr: *mut ::pthread_condattr_t, clock_id: ::clockid_t, ) -> ::c_int; pub fn pthread_getprocessorid_np() -> ::c_int; pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t; pub fn gethostid() -> ::c_long; } pub use crate::unix::newlib::generic::dirent; libc/src/unix/newlib/no_align.rs0000644000175000017500000000404214661133735017640 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { pub struct pthread_mutex_t { // Unverified #[cfg(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc"))] __align: [::c_long; 0], #[cfg(not(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } pub struct pthread_rwlock_t { // Unverified #[cfg(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc"))] __align: [::c_long; 0], #[cfg(not(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc")))] __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } pub struct pthread_mutexattr_t { // Unverified #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64"))] __align: [::c_int; 0], #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")))] __align: [::c_long; 0], size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } pub struct pthread_cond_t { // Unverified __align: [::c_longlong; 0], size: [u8; ::__SIZEOF_PTHREAD_COND_T], } pub struct pthread_condattr_t { // Unverified __align: [::c_int; 0], size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } }; } libc/src/unix/newlib/align.rs0000644000175000017500000000501414661133735017144 0ustar jamespagejamespagemacro_rules! expand_align { () => { s! { #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc")), repr(align(4)))] #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc"))), repr(align(8)))] pub struct pthread_mutex_t { // Unverified size: [u8; ::__SIZEOF_PTHREAD_MUTEX_T], } #[cfg_attr(all(target_pointer_width = "32", any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc")), repr(align(4)))] #[cfg_attr(any(target_pointer_width = "64", not(any(target_arch = "mips", target_arch = "arm", target_arch = "powerpc"))), repr(align(8)))] pub struct pthread_rwlock_t { // Unverified size: [u8; ::__SIZEOF_PTHREAD_RWLOCK_T], } #[cfg_attr(any(target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64"), repr(align(4)))] #[cfg_attr(not(any(target_pointer_width = "32", target_arch = "x86_64", target_arch = "powerpc64", target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64")), repr(align(8)))] pub struct pthread_mutexattr_t { // Unverified size: [u8; ::__SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(8))] pub struct pthread_cond_t { // Unverified size: [u8; ::__SIZEOF_PTHREAD_COND_T], } #[repr(align(4))] pub struct pthread_condattr_t { // Unverified size: [u8; ::__SIZEOF_PTHREAD_CONDATTR_T], } } }; } libc/src/unix/newlib/generic.rs0000644000175000017500000000147614661133735017476 0ustar jamespagejamespage//! Common types used by most newlib platforms s! { pub struct sigset_t { __val: [::c_ulong; 16], } pub struct stat { pub st_dev: ::dev_t, pub st_ino: ::ino_t, pub st_mode: ::mode_t, pub st_nlink: ::nlink_t, pub st_uid: ::uid_t, pub st_gid: ::gid_t, pub st_rdev: ::dev_t, pub st_size: ::off_t, pub st_atime: ::time_t, pub st_spare1: ::c_long, pub st_mtime: ::time_t, pub st_spare2: ::c_long, pub st_ctime: ::time_t, pub st_spare3: ::c_long, pub st_blksize: ::blksize_t, pub st_blocks: ::blkcnt_t, pub st_spare4: [::c_long; 2usize], } pub struct dirent { pub d_ino: ::ino_t, pub d_type: ::c_uchar, pub d_name: [::c_char; 256usize], } } libc/src/unix/no_align.rs0000644000175000017500000000014114661133735016354 0ustar jamespagejamespages! { pub struct in6_addr { pub s6_addr: [u8; 16], __align: [u32; 0], } } libc/src/unix/align.rs0000644000175000017500000000013414661133735015662 0ustar jamespagejamespages! { #[repr(align(4))] pub struct in6_addr { pub s6_addr: [u8; 16], } } libc/src/teeos/0000775000175000017500000000000014661133735014362 5ustar jamespagejamespagelibc/src/teeos/mod.rs0000644000175000017500000007320514661133735015514 0ustar jamespagejamespage//! Libc bindings for teeos //! //! Apparently the loader just dynamically links it anyway, but fails //! when linking is explicitly requested. #![allow(non_camel_case_types)] #![allow(non_snake_case)] // only supported on Rust > 1.59, so we can directly reexport c_void from core. pub use core::ffi::c_void; use Option; pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_bool = i32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type size_t = usize; pub type ptrdiff_t = isize; pub type intptr_t = isize; pub type uintptr_t = usize; pub type ssize_t = isize; pub type pid_t = c_int; // aarch64 specifc pub type c_char = u8; pub type wchar_t = u32; pub type c_long = i64; pub type c_ulong = u64; #[repr(align(16))] pub struct _CLongDouble(pub u128); // long double in C means A float point value, which has 128bit length. // but some bit maybe not used, so the really length of long double could be 80(x86) or 128(power pc/IEEE) // this is different from f128(not stable and not included default) in Rust, so we use u128 for FFI(Rust to C). // this is unstable and will couse to memfault/data abort. pub type c_longdouble = _CLongDouble; pub type pthread_t = c_ulong; pub type pthread_key_t = c_uint; pub type pthread_spinlock_t = c_int; pub type off_t = i64; pub type time_t = c_long; pub type clock_t = c_long; pub type clockid_t = c_int; pub type suseconds_t = c_long; pub type once_fn = extern "C" fn() -> c_void; pub type pthread_once_t = c_int; pub type va_list = *mut c_char; pub type wint_t = c_uint; pub type wctype_t = c_ulong; pub type cmpfunc = extern "C" fn(x: *const c_void, y: *const c_void) -> c_int; #[repr(align(8))] #[repr(C)] pub struct pthread_cond_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_COND_T], } #[repr(align(8))] #[repr(C)] pub struct pthread_mutex_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } #[repr(align(4))] #[repr(C)] pub struct pthread_mutexattr_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_MUTEXATTR_T], } #[repr(align(4))] #[repr(C)] pub struct pthread_condattr_t { #[doc(hidden)] size: [u8; __SIZEOF_PTHREAD_CONDATTR_T], } #[repr(C)] pub struct pthread_attr_t { __size: [u64; 7], } #[repr(C)] pub struct cpu_set_t { bits: [c_ulong; 128 / core::mem::size_of::()], } #[repr(C)] pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } #[repr(C)] pub struct timeval { pub tv_sec: time_t, pub tv_usec: suseconds_t, } #[repr(C)] pub struct tm { pub tm_sec: c_int, pub tm_min: c_int, pub tm_hour: c_int, pub tm_mday: c_int, pub tm_mon: c_int, pub tm_year: c_int, pub tm_wday: c_int, pub tm_yday: c_int, pub tm_isdst: c_int, pub __tm_gmtoff: c_long, pub __tm_zone: *const c_char, } #[repr(C)] pub struct mbstate_t { pub __opaque1: c_uint, pub __opaque2: c_uint, } #[repr(C)] pub struct sem_t { pub __val: [c_int; 4 * core::mem::size_of::() / core::mem::size_of::()], } #[repr(C)] pub struct div_t { pub quot: c_int, pub rem: c_int, } // fcntl pub const O_CREAT: u32 = 0100; pub const O_EXCL: u32 = 0200; pub const O_NOCTTY: u32 = 0400; pub const O_TRUNC: u32 = 01000; pub const O_APPEND: u32 = 02000; pub const O_NONBLOCK: u32 = 04000; pub const O_DSYNC: u32 = 010000; pub const O_SYNC: u32 = 04010000; pub const O_RSYNC: u32 = 04010000; pub const O_DIRECTORY: u32 = 0200000; pub const O_NOFOLLOW: u32 = 0400000; pub const O_CLOEXEC: u32 = 02000000; pub const O_ASYNC: u32 = 020000; pub const O_DIRECT: u32 = 040000; pub const O_LARGEFILE: u32 = 0100000; pub const O_NOATIME: u32 = 01000000; pub const O_PATH: u32 = 010000000; pub const O_TMPFILE: u32 = 020200000; pub const O_NDELAY: u32 = O_NONBLOCK; pub const F_DUPFD: u32 = 0; pub const F_GETFD: u32 = 1; pub const F_SETFD: u32 = 2; pub const F_GETFL: u32 = 3; pub const F_SETFL: u32 = 4; pub const F_SETOWN: u32 = 8; pub const F_GETOWN: u32 = 9; pub const F_SETSIG: u32 = 10; pub const F_GETSIG: u32 = 11; pub const F_GETLK: u32 = 12; pub const F_SETLK: u32 = 13; pub const F_SETLKW: u32 = 14; pub const F_SETOWN_EX: u32 = 15; pub const F_GETOWN_EX: u32 = 16; pub const F_GETOWNER_UIDS: u32 = 17; // mman pub const MAP_FAILED: u64 = 0xffffffffffffffff; pub const MAP_FIXED_NOREPLACE: u32 = 0x100000; pub const MAP_SHARED_VALIDATE: u32 = 0x03; pub const MAP_SHARED: u32 = 0x01; pub const MAP_PRIVATE: u32 = 0x02; pub const MAP_TYPE: u32 = 0x0f; pub const MAP_FIXED: u32 = 0x10; pub const MAP_ANON: u32 = 0x20; pub const MAP_ANONYMOUS: u32 = MAP_ANON; pub const MAP_NORESERVE: u32 = 0x4000; pub const MAP_GROWSDOWN: u32 = 0x0100; pub const MAP_DENYWRITE: u32 = 0x0800; pub const MAP_EXECUTABLE: u32 = 0x1000; pub const MAP_LOCKED: u32 = 0x2000; pub const MAP_POPULATE: u32 = 0x8000; pub const MAP_NONBLOCK: u32 = 0x10000; pub const MAP_STACK: u32 = 0x20000; pub const MAP_HUGETLB: u32 = 0x40000; pub const MAP_SYNC: u32 = 0x80000; pub const MAP_FILE: u32 = 0; pub const MAP_HUGE_SHIFT: u32 = 26; pub const MAP_HUGE_MASK: u32 = 0x3f; pub const MAP_HUGE_16KB: u32 = 14 << 26; pub const MAP_HUGE_64KB: u32 = 16 << 26; pub const MAP_HUGE_512KB: u32 = 19 << 26; pub const MAP_HUGE_1MB: u32 = 20 << 26; pub const MAP_HUGE_2MB: u32 = 21 << 26; pub const MAP_HUGE_8MB: u32 = 23 << 26; pub const MAP_HUGE_16MB: u32 = 24 << 26; pub const MAP_HUGE_32MB: u32 = 25 << 26; pub const MAP_HUGE_256MB: u32 = 28 << 26; pub const MAP_HUGE_512MB: u32 = 29 << 26; pub const MAP_HUGE_1GB: u32 = 30 << 26; pub const MAP_HUGE_2GB: u32 = 31 << 26; pub const MAP_HUGE_16GB: u32 = 34u32 << 26; pub const PROT_NONE: u32 = 0; pub const PROT_READ: u32 = 1; pub const PROT_WRITE: u32 = 2; pub const PROT_EXEC: u32 = 4; pub const PROT_GROWSDOWN: u32 = 0x01000000; pub const PROT_GROWSUP: u32 = 0x02000000; pub const MS_ASYNC: u32 = 1; pub const MS_INVALIDATE: u32 = 2; pub const MS_SYNC: u32 = 4; pub const MCL_CURRENT: u32 = 1; pub const MCL_FUTURE: u32 = 2; pub const MCL_ONFAULT: u32 = 4; pub const POSIX_MADV_NORMAL: u32 = 0; pub const POSIX_MADV_RANDOM: u32 = 1; pub const POSIX_MADV_SEQUENTIAL: u32 = 2; pub const POSIX_MADV_WILLNEED: u32 = 3; pub const POSIX_MADV_DONTNEED: u32 = 4; // wctype pub const WCTYPE_ALNUM: u64 = 1; pub const WCTYPE_ALPHA: u64 = 2; pub const WCTYPE_BLANK: u64 = 3; pub const WCTYPE_CNTRL: u64 = 4; pub const WCTYPE_DIGIT: u64 = 5; pub const WCTYPE_GRAPH: u64 = 6; pub const WCTYPE_LOWER: u64 = 7; pub const WCTYPE_PRINT: u64 = 8; pub const WCTYPE_PUNCT: u64 = 9; pub const WCTYPE_SPACE: u64 = 10; pub const WCTYPE_UPPER: u64 = 11; pub const WCTYPE_XDIGIT: u64 = 12; // locale pub const LC_CTYPE: i32 = 0; pub const LC_NUMERIC: i32 = 1; pub const LC_TIME: i32 = 2; pub const LC_COLLATE: i32 = 3; pub const LC_MONETARY: i32 = 4; pub const LC_MESSAGES: i32 = 5; pub const LC_ALL: i32 = 6; // pthread pub const __SIZEOF_PTHREAD_COND_T: usize = 48; pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40; pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4; pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4; // errno.h pub const EPERM: c_int = 1; pub const ENOENT: c_int = 2; pub const ESRCH: c_int = 3; pub const EINTR: c_int = 4; pub const EIO: c_int = 5; pub const ENXIO: c_int = 6; pub const E2BIG: c_int = 7; pub const ENOEXEC: c_int = 8; pub const EBADF: c_int = 9; pub const ECHILD: c_int = 10; pub const EAGAIN: c_int = 11; pub const ENOMEM: c_int = 12; pub const EACCES: c_int = 13; pub const EFAULT: c_int = 14; pub const ENOTBLK: c_int = 15; pub const EBUSY: c_int = 16; pub const EEXIST: c_int = 17; pub const EXDEV: c_int = 18; pub const ENODEV: c_int = 19; pub const ENOTDIR: c_int = 20; pub const EISDIR: c_int = 21; pub const EINVAL: c_int = 22; pub const ENFILE: c_int = 23; pub const EMFILE: c_int = 24; pub const ENOTTY: c_int = 25; pub const ETXTBSY: c_int = 26; pub const EFBIG: c_int = 27; pub const ENOSPC: c_int = 28; pub const ESPIPE: c_int = 29; pub const EROFS: c_int = 30; pub const EMLINK: c_int = 31; pub const EPIPE: c_int = 32; pub const EDOM: c_int = 33; pub const ERANGE: c_int = 34; pub const EDEADLK: c_int = 35; pub const ENAMETOOLONG: c_int = 36; pub const ENOLCK: c_int = 37; pub const ENOSYS: c_int = 38; pub const ENOTEMPTY: c_int = 39; pub const ELOOP: c_int = 40; pub const EWOULDBLOCK: c_int = EAGAIN; pub const ENOMSG: c_int = 42; pub const EIDRM: c_int = 43; pub const ECHRNG: c_int = 44; pub const EL2NSYNC: c_int = 45; pub const EL3HLT: c_int = 46; pub const EL3RST: c_int = 47; pub const ELNRNG: c_int = 48; pub const EUNATCH: c_int = 49; pub const ENOCSI: c_int = 50; pub const EL2HLT: c_int = 51; pub const EBADE: c_int = 52; pub const EBADR: c_int = 53; pub const EXFULL: c_int = 54; pub const ENOANO: c_int = 55; pub const EBADRQC: c_int = 56; pub const EBADSLT: c_int = 57; pub const EDEADLOCK: c_int = EDEADLK; pub const EBFONT: c_int = 59; pub const ENOSTR: c_int = 60; pub const ENODATA: c_int = 61; pub const ETIME: c_int = 62; pub const ENOSR: c_int = 63; pub const ENONET: c_int = 64; pub const ENOPKG: c_int = 65; pub const EREMOTE: c_int = 66; pub const ENOLINK: c_int = 67; pub const EADV: c_int = 68; pub const ESRMNT: c_int = 69; pub const ECOMM: c_int = 70; pub const EPROTO: c_int = 71; pub const EMULTIHOP: c_int = 72; pub const EDOTDOT: c_int = 73; pub const EBADMSG: c_int = 74; pub const EOVERFLOW: c_int = 75; pub const ENOTUNIQ: c_int = 76; pub const EBADFD: c_int = 77; pub const EREMCHG: c_int = 78; pub const ELIBACC: c_int = 79; pub const ELIBBAD: c_int = 80; pub const ELIBSCN: c_int = 81; pub const ELIBMAX: c_int = 82; pub const ELIBEXEC: c_int = 83; pub const EILSEQ: c_int = 84; pub const ERESTART: c_int = 85; pub const ESTRPIPE: c_int = 86; pub const EUSERS: c_int = 87; pub const ENOTSOCK: c_int = 88; pub const EDESTADDRREQ: c_int = 89; pub const EMSGSIZE: c_int = 90; pub const EPROTOTYPE: c_int = 91; pub const ENOPROTOOPT: c_int = 92; pub const EPROTONOSUPPOR: c_int = 93; pub const ESOCKTNOSUPPOR: c_int = 94; pub const EOPNOTSUPP: c_int = 95; pub const ENOTSUP: c_int = EOPNOTSUPP; pub const EPFNOSUPPORT: c_int = 96; pub const EAFNOSUPPORT: c_int = 97; pub const EADDRINUSE: c_int = 98; pub const EADDRNOTAVAIL: c_int = 99; pub const ENETDOWN: c_int = 100; pub const ENETUNREACH: c_int = 101; pub const ENETRESET: c_int = 102; pub const ECONNABORTED: c_int = 103; pub const ECONNRESET: c_int = 104; pub const ENOBUFS: c_int = 105; pub const EISCONN: c_int = 106; pub const ENOTCONN: c_int = 107; pub const ESHUTDOWN: c_int = 108; pub const ETOOMANYREFS: c_int = 109; pub const ETIMEDOUT: c_int = 110; pub const ECONNREFUSED: c_int = 111; pub const EHOSTDOWN: c_int = 112; pub const EHOSTUNREACH: c_int = 113; pub const EALREADY: c_int = 114; pub const EINPROGRESS: c_int = 115; pub const ESTALE: c_int = 116; pub const EUCLEAN: c_int = 117; pub const ENOTNAM: c_int = 118; pub const ENAVAIL: c_int = 119; pub const EISNAM: c_int = 120; pub const EREMOTEIO: c_int = 121; pub const EDQUOT: c_int = 122; pub const ENOMEDIUM: c_int = 123; pub const EMEDIUMTYPE: c_int = 124; pub const ECANCELED: c_int = 125; pub const ENOKEY: c_int = 126; pub const EKEYEXPIRED: c_int = 127; pub const EKEYREVOKED: c_int = 128; pub const EKEYREJECTED: c_int = 129; pub const EOWNERDEAD: c_int = 130; pub const ENOTRECOVERABLE: c_int = 131; pub const ERFKILL: c_int = 132; pub const EHWPOISON: c_int = 133; // pthread_attr.h pub const TEESMP_THREAD_ATTR_CA_WILDCARD: c_int = 0; pub const TEESMP_THREAD_ATTR_CA_INHERIT: c_int = -1; pub const TEESMP_THREAD_ATTR_TASK_ID_INHERIT: c_int = -1; pub const TEESMP_THREAD_ATTR_HAS_SHADOW: c_int = 0x1; pub const TEESMP_THREAD_ATTR_NO_SHADOW: c_int = 0x0; // unistd.h pub const _SC_ARG_MAX: c_int = 0; pub const _SC_CHILD_MAX: c_int = 1; pub const _SC_CLK_TCK: c_int = 2; pub const _SC_NGROUPS_MAX: c_int = 3; pub const _SC_OPEN_MAX: c_int = 4; pub const _SC_STREAM_MAX: c_int = 5; pub const _SC_TZNAME_MAX: c_int = 6; pub const _SC_JOB_CONTROL: c_int = 7; pub const _SC_SAVED_IDS: c_int = 8; pub const _SC_REALTIME_SIGNALS: c_int = 9; pub const _SC_PRIORITY_SCHEDULING: c_int = 10; pub const _SC_TIMERS: c_int = 11; pub const _SC_ASYNCHRONOUS_IO: c_int = 12; pub const _SC_PRIORITIZED_IO: c_int = 13; pub const _SC_SYNCHRONIZED_IO: c_int = 14; pub const _SC_FSYNC: c_int = 15; pub const _SC_MAPPED_FILES: c_int = 16; pub const _SC_MEMLOCK: c_int = 17; pub const _SC_MEMLOCK_RANGE: c_int = 18; pub const _SC_MEMORY_PROTECTION: c_int = 19; pub const _SC_MESSAGE_PASSING: c_int = 20; pub const _SC_SEMAPHORES: c_int = 21; pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22; pub const _SC_AIO_LISTIO_MAX: c_int = 23; pub const _SC_AIO_MAX: c_int = 24; pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25; pub const _SC_DELAYTIMER_MAX: c_int = 26; pub const _SC_MQ_OPEN_MAX: c_int = 27; pub const _SC_MQ_PRIO_MAX: c_int = 28; pub const _SC_VERSION: c_int = 29; pub const _SC_PAGE_SIZE: c_int = 30; pub const _SC_PAGESIZE: c_int = 30; /* !! */ pub const _SC_RTSIG_MAX: c_int = 31; pub const _SC_SEM_NSEMS_MAX: c_int = 32; pub const _SC_SEM_VALUE_MAX: c_int = 33; pub const _SC_SIGQUEUE_MAX: c_int = 34; pub const _SC_TIMER_MAX: c_int = 35; pub const _SC_BC_BASE_MAX: c_int = 36; pub const _SC_BC_DIM_MAX: c_int = 37; pub const _SC_BC_SCALE_MAX: c_int = 38; pub const _SC_BC_STRING_MAX: c_int = 39; pub const _SC_COLL_WEIGHTS_MAX: c_int = 40; pub const _SC_EXPR_NEST_MAX: c_int = 42; pub const _SC_LINE_MAX: c_int = 43; pub const _SC_RE_DUP_MAX: c_int = 44; pub const _SC_2_VERSION: c_int = 46; pub const _SC_2_C_BIND: c_int = 47; pub const _SC_2_C_DEV: c_int = 48; pub const _SC_2_FORT_DEV: c_int = 49; pub const _SC_2_FORT_RUN: c_int = 50; pub const _SC_2_SW_DEV: c_int = 51; pub const _SC_2_LOCALEDEF: c_int = 52; pub const _SC_UIO_MAXIOV: c_int = 60; /* !! */ pub const _SC_IOV_MAX: c_int = 60; pub const _SC_THREADS: c_int = 67; pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68; pub const _SC_GETGR_R_SIZE_MAX: c_int = 69; pub const _SC_GETPW_R_SIZE_MAX: c_int = 70; pub const _SC_LOGIN_NAME_MAX: c_int = 71; pub const _SC_TTY_NAME_MAX: c_int = 72; pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73; pub const _SC_THREAD_KEYS_MAX: c_int = 74; pub const _SC_THREAD_STACK_MIN: c_int = 75; pub const _SC_THREAD_THREADS_MAX: c_int = 76; pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77; pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78; pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79; pub const _SC_THREAD_PRIO_INHERIT: c_int = 80; pub const _SC_THREAD_PRIO_PROTECT: c_int = 81; pub const _SC_THREAD_PROCESS_SHARED: c_int = 82; pub const _SC_NPROCESSORS_CONF: c_int = 83; pub const _SC_NPROCESSORS_ONLN: c_int = 84; pub const _SC_PHYS_PAGES: c_int = 85; pub const _SC_AVPHYS_PAGES: c_int = 86; pub const _SC_ATEXIT_MAX: c_int = 87; pub const _SC_PASS_MAX: c_int = 88; pub const _SC_XOPEN_VERSION: c_int = 89; pub const _SC_XOPEN_XCU_VERSION: c_int = 90; pub const _SC_XOPEN_UNIX: c_int = 91; pub const _SC_XOPEN_CRYPT: c_int = 92; pub const _SC_XOPEN_ENH_I18N: c_int = 93; pub const _SC_XOPEN_SHM: c_int = 94; pub const _SC_2_CHAR_TERM: c_int = 95; pub const _SC_2_UPE: c_int = 97; pub const _SC_XOPEN_XPG2: c_int = 98; pub const _SC_XOPEN_XPG3: c_int = 99; pub const _SC_XOPEN_XPG4: c_int = 100; pub const _SC_NZERO: c_int = 109; pub const _SC_XBS5_ILP32_OFF32: c_int = 125; pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126; pub const _SC_XBS5_LP64_OFF64: c_int = 127; pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128; pub const _SC_XOPEN_LEGACY: c_int = 129; pub const _SC_XOPEN_REALTIME: c_int = 130; pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131; pub const _SC_ADVISORY_INFO: c_int = 132; pub const _SC_BARRIERS: c_int = 133; pub const _SC_CLOCK_SELECTION: c_int = 137; pub const _SC_CPUTIME: c_int = 138; pub const _SC_THREAD_CPUTIME: c_int = 139; pub const _SC_MONOTONIC_CLOCK: c_int = 149; pub const _SC_READER_WRITER_LOCKS: c_int = 153; pub const _SC_SPIN_LOCKS: c_int = 154; pub const _SC_REGEXP: c_int = 155; pub const _SC_SHELL: c_int = 157; pub const _SC_SPAWN: c_int = 159; pub const _SC_SPORADIC_SERVER: c_int = 160; pub const _SC_THREAD_SPORADIC_SERVER: c_int = 161; pub const _SC_TIMEOUTS: c_int = 164; pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 165; pub const _SC_2_PBS: c_int = 168; pub const _SC_2_PBS_ACCOUNTING: c_int = 169; pub const _SC_2_PBS_LOCATE: c_int = 170; pub const _SC_2_PBS_MESSAGE: c_int = 171; pub const _SC_2_PBS_TRACK: c_int = 172; pub const _SC_SYMLOOP_MAX: c_int = 173; pub const _SC_STREAMS: c_int = 174; pub const _SC_2_PBS_CHECKPOINT: c_int = 175; pub const _SC_V6_ILP32_OFF32: c_int = 176; pub const _SC_V6_ILP32_OFFBIG: c_int = 177; pub const _SC_V6_LP64_OFF64: c_int = 178; pub const _SC_V6_LPBIG_OFFBIG: c_int = 179; pub const _SC_HOST_NAME_MAX: c_int = 180; pub const _SC_TRACE: c_int = 181; pub const _SC_TRACE_EVENT_FILTER: c_int = 182; pub const _SC_TRACE_INHERIT: c_int = 183; pub const _SC_TRACE_LOG: c_int = 184; pub const _SC_IPV6: c_int = 235; pub const _SC_RAW_SOCKETS: c_int = 236; pub const _SC_V7_ILP32_OFF32: c_int = 237; pub const _SC_V7_ILP32_OFFBIG: c_int = 238; pub const _SC_V7_LP64_OFF64: c_int = 239; pub const _SC_V7_LPBIG_OFFBIG: c_int = 240; pub const _SC_SS_REPL_MAX: c_int = 241; pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 242; pub const _SC_TRACE_NAME_MAX: c_int = 243; pub const _SC_TRACE_SYS_MAX: c_int = 244; pub const _SC_TRACE_USER_EVENT_MAX: c_int = 245; pub const _SC_XOPEN_STREAMS: c_int = 246; pub const _SC_THREAD_ROBUST_PRIO_INHERIT: c_int = 247; pub const _SC_THREAD_ROBUST_PRIO_PROTECT: c_int = 248; // limits.h pub const PTHREAD_KEYS_MAX: c_int = 128; pub const PTHREAD_STACK_MIN: c_int = 2048; pub const PTHREAD_DESTRUCTOR_ITERATIONS: c_int = 4; pub const SEM_VALUE_MAX: c_int = 0x7fffffff; pub const SEM_NSEMS_MAX: c_int = 256; pub const DELAYTIMER_MAX: c_int = 0x7fffffff; pub const MQ_PRIO_MAX: c_int = 32768; pub const LOGIN_NAME_MAX: c_int = 256; // time.h pub const CLOCK_REALTIME: clockid_t = 0; pub const CLOCK_MONOTONIC: clockid_t = 1; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_MUTEX_NORMAL: c_int = 0; pub const PTHREAD_MUTEX_RECURSIVE: c_int = 1; pub const PTHREAD_MUTEX_ERRORCHECK: c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_MUTEX_STALLED: c_int = 0; pub const PTHREAD_MUTEX_ROBUST: c_int = 1; extern "C" { // ---- ALLOC ----------------------------------------------------------------------------- pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn aligned_alloc(align: size_t, len: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn posix_memalign(memptr: *mut *mut c_void, align: size_t, size: size_t) -> c_int; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; // ----- PTHREAD --------------------------------------------------------------------------- pub fn pthread_self() -> pthread_t; pub fn pthread_join(native: pthread_t, value: *mut *mut c_void) -> c_int; // detach or pthread_attr_setdetachstate must not be called! //pub fn pthread_detach(thread: pthread_t) -> c_int; pub fn pthread_exit(value: *mut c_void) -> !; pub fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int; pub fn pthread_attr_destroy(attr: *mut pthread_attr_t) -> c_int; pub fn pthread_attr_getstack( attr: *const pthread_attr_t, stackaddr: *mut *mut c_void, stacksize: *mut size_t, ) -> c_int; pub fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, stack_size: size_t) -> c_int; pub fn pthread_attr_getstacksize(attr: *const pthread_attr_t, size: *mut size_t) -> c_int; pub fn pthread_attr_settee( attr: *mut pthread_attr_t, ca: c_int, task_id: c_int, shadow: c_int, ) -> c_int; // C-TA API do not include this interface, but TA can use. pub fn sched_yield() -> c_int; pub fn pthread_key_create( key: *mut pthread_key_t, dtor: Option, ) -> c_int; pub fn pthread_key_delete(key: pthread_key_t) -> c_int; pub fn pthread_getspecific(key: pthread_key_t) -> *mut c_void; pub fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int; pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_init( lock: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> c_int; pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> c_int; pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int; pub fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, _type: c_int) -> c_int; pub fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, pshared: c_int) -> c_int; pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int; pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int; pub fn pthread_cond_wait(cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t) -> c_int; pub fn pthread_cond_timedwait( cond: *mut pthread_cond_t, lock: *mut pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; pub fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robustness: c_int) -> c_int; pub fn pthread_create( native: *mut pthread_t, attr: *const pthread_attr_t, f: extern "C" fn(*mut c_void) -> *mut c_void, value: *mut c_void, ) -> c_int; pub fn pthread_spin_init(lock: *mut pthread_spinlock_t, pshared: c_int) -> c_int; pub fn pthread_spin_destroy(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_lock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_trylock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_spin_unlock(lock: *mut pthread_spinlock_t) -> c_int; pub fn pthread_setschedprio(native: pthread_t, priority: c_int) -> c_int; pub fn pthread_once(pot: *mut pthread_once_t, f: Option) -> c_int; pub fn pthread_equal(p1: pthread_t, p2: pthread_t) -> c_int; pub fn pthread_mutexattr_setprotocol(a: *mut pthread_mutexattr_t, protocol: c_int) -> c_int; pub fn pthread_attr_setstack( attr: *mut pthread_attr_t, stack: *mut c_void, size: size_t, ) -> c_int; pub fn pthread_setaffinity_np(td: pthread_t, size: size_t, set: *const cpu_set_t) -> c_int; pub fn pthread_getaffinity_np(td: pthread_t, size: size_t, set: *mut cpu_set_t) -> c_int; // stdio.h pub fn printf(fmt: *const c_char, ...) -> c_int; pub fn scanf(fmt: *const c_char, ...) -> c_int; pub fn snprintf(s: *mut c_char, n: size_t, fmt: *const c_char, ...) -> c_int; pub fn sprintf(s: *mut c_char, fmt: *const c_char, ...) -> c_int; pub fn vsnprintf(s: *mut c_char, n: size_t, fmt: *const c_char, ap: va_list) -> c_int; pub fn vsprintf(s: *mut c_char, fmt: *const c_char, ap: va_list) -> c_int; // Not available. //pub fn pthread_setname_np(thread: pthread_t, name: *const c_char) -> c_int; pub fn abort() -> !; // Not available. //pub fn prctl(op: c_int, ...) -> c_int; pub fn sched_getaffinity(pid: pid_t, cpusetsize: size_t, cpuset: *mut cpu_set_t) -> c_int; pub fn sched_setaffinity(pid: pid_t, cpusetsize: size_t, cpuset: *const cpu_set_t) -> c_int; // sysconf is currently only implemented as a stub. pub fn sysconf(name: c_int) -> c_long; // mman.h pub fn mmap( addr: *mut c_void, len: size_t, prot: c_int, flags: c_int, fd: c_int, offset: off_t, ) -> *mut c_void; pub fn munmap(addr: *mut c_void, len: size_t) -> c_int; // errno.h pub fn __errno_location() -> *mut c_int; pub fn strerror(e: c_int) -> *mut c_char; // time.h pub fn clock_gettime(clock_id: clockid_t, tp: *mut timespec) -> c_int; // unistd pub fn getpid() -> pid_t; // time pub fn gettimeofday(tv: *mut timeval, tz: *mut c_void) -> c_int; pub fn strftime( restrict: *mut c_char, sz: size_t, _restrict: *const c_char, __restrict: *const tm, ) -> size_t; pub fn time(t: *mut time_t) -> time_t; // sem pub fn sem_close(sem: *mut sem_t) -> c_int; pub fn sem_destroy(sem: *mut sem_t) -> c_int; pub fn sem_getvalue(sem: *mut sem_t, valp: *mut c_int) -> c_int; pub fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int; pub fn sem_open(name: *const c_char, flags: c_int, ...) -> *mut sem_t; pub fn sem_post(sem: *mut sem_t) -> c_int; pub fn sem_unlink(name: *const c_char) -> c_int; pub fn sem_wait(sem: *mut sem_t) -> c_int; // locale pub fn setlocale(cat: c_int, name: *const c_char) -> *mut c_char; pub fn strcoll(l: *const c_char, r: *const c_char) -> c_int; pub fn strxfrm(dest: *mut c_char, src: *const c_char, n: size_t) -> size_t; pub fn strtod(s: *const c_char, p: *mut *mut c_char) -> c_double; // multibyte pub fn mbrtowc(wc: *mut wchar_t, src: *const c_char, n: size_t, st: *mut mbstate_t) -> size_t; pub fn wcrtomb(s: *mut c_char, wc: wchar_t, st: *mut mbstate_t) -> size_t; pub fn wctob(c: wint_t) -> c_int; // prng pub fn srandom(seed: c_uint); pub fn initstate(seed: c_uint, state: *mut c_char, size: size_t) -> *mut c_char; pub fn setstate(state: *mut c_char) -> *mut c_char; pub fn random() -> c_long; // string pub fn strchr(s: *const c_char, c: c_int) -> *mut c_char; pub fn strlen(cs: *const c_char) -> size_t; pub fn strcmp(l: *const c_char, r: *const c_char) -> c_int; pub fn strcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncmp(_l: *const c_char, r: *const c_char, n: size_t) -> c_int; pub fn strncpy(dest: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strnlen(cs: *const c_char, n: size_t) -> size_t; pub fn strrchr(s: *const c_char, c: c_int) -> *mut c_char; pub fn strstr(h: *const c_char, n: *const c_char) -> *mut c_char; pub fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t; pub fn wcslen(s: *const wchar_t) -> size_t; // ctype pub fn isalpha(c: c_int) -> c_int; pub fn isascii(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn iswctype(wc: wint_t, ttype: wctype_t) -> c_int; pub fn iswdigit(wc: wint_t) -> c_int; pub fn iswlower(wc: wint_t) -> c_int; pub fn iswspace(wc: wint_t) -> c_int; pub fn iswupper(wc: wint_t) -> c_int; pub fn towupper(wc: wint_t) -> wint_t; pub fn towlower(wc: wint_t) -> wint_t; // cmath pub fn atan(x: c_double) -> c_double; pub fn ceil(x: c_double) -> c_double; pub fn ceilf(x: c_float) -> c_float; pub fn exp(x: c_double) -> c_double; pub fn fabs(x: c_double) -> c_double; pub fn floor(x: c_double) -> c_double; pub fn frexp(x: c_double, e: *mut c_int) -> c_double; pub fn log(x: c_double) -> c_double; pub fn log2(x: c_double) -> c_double; pub fn pow(x: c_double, y: c_double) -> c_double; pub fn roundf(x: c_float) -> c_float; pub fn scalbn(x: c_double, n: c_int) -> c_double; pub fn sqrt(x: c_double) -> c_double; // stdlib pub fn abs(x: c_int) -> c_int; pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn bsearch( key: *const c_void, base: *const c_void, nel: size_t, width: size_t, cmp: cmpfunc, ) -> *mut c_void; pub fn div(num: c_int, den: c_int) -> div_t; pub fn ecvt(x: c_double, n: c_int, dp: *mut c_int, sign: *mut c_int) -> *mut c_char; pub fn imaxabs(a: intmax_t) -> intmax_t; pub fn llabs(a: c_longlong) -> c_longlong; pub fn qsort(base: *mut c_void, nel: size_t, width: size_t, cmp: cmpfunc); pub fn strtoul(s: *const c_char, p: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtol(s: *const c_char, p: *mut *mut c_char, base: c_int) -> c_long; pub fn wcstod(s: *const wchar_t, p: *mut *mut wchar_t) -> c_double; } pub fn errno() -> c_int { unsafe { *__errno_location() } } pub fn CPU_COUNT_S(size: usize, cpuset: &cpu_set_t) -> c_int { let mut s: u32 = 0; let size_of_mask = core::mem::size_of_val(&cpuset.bits[0]); for i in cpuset.bits[..(size / size_of_mask)].iter() { s += i.count_ones(); } s as c_int } pub fn CPU_COUNT(cpuset: &cpu_set_t) -> c_int { CPU_COUNT_S(core::mem::size_of::(), cpuset) } libc/src/vxworks/0000775000175000017500000000000014661133735014766 5ustar jamespagejamespagelibc/src/vxworks/powerpc.rs0000644000175000017500000000013514661133735017010 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type c_long = i32; pub type c_ulong = u32; libc/src/vxworks/arm.rs0000644000175000017500000000013514661133735016110 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type c_long = i32; pub type c_ulong = u32; libc/src/vxworks/x86.rs0000644000175000017500000000013514661133735015756 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type c_long = i32; pub type c_ulong = u32; libc/src/vxworks/x86_64.rs0000644000175000017500000000013514661133735016267 0ustar jamespagejamespagepub type c_char = i8; pub type wchar_t = i32; pub type c_long = i64; pub type c_ulong = u64; libc/src/vxworks/mod.rs0000644000175000017500000017263214661133735016124 0ustar jamespagejamespage//! Interface to VxWorks C library use core::mem::size_of; use core::ptr::null_mut; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} impl ::Copy for DIR {} impl ::Clone for DIR { fn clone(&self) -> DIR { *self } } pub type c_schar = i8; pub type c_uchar = u8; pub type c_short = i16; pub type c_ushort = u16; pub type c_int = i32; pub type c_uint = u32; pub type c_float = f32; pub type c_double = f64; pub type c_longlong = i64; pub type c_ulonglong = u64; pub type intmax_t = i64; pub type uintmax_t = u64; pub type uintptr_t = usize; pub type intptr_t = isize; pub type ptrdiff_t = isize; pub type size_t = ::uintptr_t; pub type ssize_t = ::intptr_t; pub type pid_t = ::c_int; pub type in_addr_t = u32; pub type sighandler_t = ::size_t; pub type cpuset_t = u32; pub type blkcnt_t = ::c_long; pub type blksize_t = ::c_long; pub type ino_t = ::c_ulong; pub type rlim_t = ::c_ulong; pub type suseconds_t = ::c_long; pub type time_t = ::c_long; pub type errno_t = ::c_int; pub type useconds_t = ::c_ulong; pub type socklen_t = ::c_uint; pub type pthread_t = ::c_ulong; pub type clockid_t = ::c_int; //defined for the structs pub type dev_t = ::c_ulong; pub type mode_t = ::c_int; pub type nlink_t = ::c_ulong; pub type uid_t = ::c_ushort; pub type gid_t = ::c_ushort; pub type sigset_t = ::c_ulonglong; pub type key_t = ::c_long; pub type nfds_t = ::c_uint; pub type stat64 = ::stat; pub type pthread_key_t = ::c_ulong; // From b_off_t.h pub type off_t = ::c_longlong; pub type off64_t = off_t; // From b_BOOL.h pub type BOOL = ::c_int; // From vxWind.h .. pub type _Vx_OBJ_HANDLE = ::c_int; pub type _Vx_TASK_ID = ::_Vx_OBJ_HANDLE; pub type _Vx_MSG_Q_ID = ::_Vx_OBJ_HANDLE; pub type _Vx_SEM_ID_KERNEL = ::_Vx_OBJ_HANDLE; pub type _Vx_RTP_ID = ::_Vx_OBJ_HANDLE; pub type _Vx_SD_ID = ::_Vx_OBJ_HANDLE; pub type _Vx_CONDVAR_ID = ::_Vx_OBJ_HANDLE; pub type _Vx_SEM_ID = *mut ::_Vx_semaphore; pub type OBJ_HANDLE = ::_Vx_OBJ_HANDLE; pub type TASK_ID = ::OBJ_HANDLE; pub type MSG_Q_ID = ::OBJ_HANDLE; pub type SEM_ID_KERNEL = ::OBJ_HANDLE; pub type RTP_ID = ::OBJ_HANDLE; pub type SD_ID = ::OBJ_HANDLE; pub type CONDVAR_ID = ::OBJ_HANDLE; // From vxTypes.h pub type _Vx_usr_arg_t = isize; pub type _Vx_exit_code_t = isize; pub type _Vx_ticks_t = ::c_uint; pub type _Vx_ticks64_t = ::c_ulonglong; pub type sa_family_t = ::c_uchar; // mqueue.h pub type mqd_t = ::c_int; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum _Vx_semaphore {} impl ::Copy for _Vx_semaphore {} impl ::Clone for _Vx_semaphore { fn clone(&self) -> _Vx_semaphore { *self } } impl siginfo_t { pub unsafe fn si_addr(&self) -> *mut ::c_void { self.si_addr } pub unsafe fn si_value(&self) -> ::sigval { self.si_value } pub unsafe fn si_pid(&self) -> ::pid_t { self.si_pid } pub unsafe fn si_uid(&self) -> ::uid_t { self.si_uid } pub unsafe fn si_status(&self) -> ::c_int { self.si_status } } s! { // b_pthread_condattr_t.h pub struct pthread_condattr_t { pub condAttrStatus: ::c_int, pub condAttrPshared: ::c_int, pub condAttrClockId: ::clockid_t, } // b_pthread_cond_t.h pub struct pthread_cond_t{ pub condSemId: ::_Vx_SEM_ID, pub condValid: ::c_int, pub condInitted: ::c_int, pub condRefCount: ::c_int, pub condMutex: *mut ::pthread_mutex_t, pub condAttr: ::pthread_condattr_t, pub condSemName: [::c_char; _PTHREAD_SHARED_SEM_NAME_MAX] } // b_pthread_rwlockattr_t.h pub struct pthread_rwlockattr_t { pub rwlockAttrStatus: ::c_int, pub rwlockAttrPshared: ::c_int, pub rwlockAttrMaxReaders: ::c_uint, pub rwlockAttrConformOpt: ::c_uint, } // b_pthread_rwlock_t.h pub struct pthread_rwlock_t { pub rwlockSemId: :: _Vx_SEM_ID, pub rwlockReadersRefCount: ::c_uint, pub rwlockValid: ::c_int, pub rwlockInitted: ::c_int, pub rwlockAttr: ::pthread_rwlockattr_t, pub rwlockSemName: [::c_char; _PTHREAD_SHARED_SEM_NAME_MAX] } // b_struct_timeval.h pub struct timeval { pub tv_sec: ::time_t, pub tv_usec: ::suseconds_t, } // socket.h pub struct linger { pub l_onoff: ::c_int, pub l_linger: ::c_int, } pub struct sockaddr { pub sa_len : ::c_uchar, pub sa_family : sa_family_t, pub sa_data : [::c_char; 14], } pub struct iovec { pub iov_base: *mut ::c_void, pub iov_len: ::size_t, } pub struct msghdr { pub msg_name: *mut c_void, pub msg_namelen: socklen_t, pub msg_iov: *mut iovec, pub msg_iovlen: ::c_int, pub msg_control: *mut c_void, pub msg_controllen: socklen_t, pub msg_flags: ::c_int, } pub struct cmsghdr { pub cmsg_len: socklen_t, pub cmsg_level: ::c_int, pub cmsg_type: ::c_int, } // poll.h pub struct pollfd { pub fd : ::c_int, pub events : ::c_short, pub revents : ::c_short, } // resource.h pub struct rlimit { pub rlim_cur : ::rlim_t, pub rlim_max : ::rlim_t, } // stat.h pub struct stat { pub st_dev : ::dev_t, pub st_ino : ::ino_t, pub st_mode : ::mode_t, pub st_nlink : ::nlink_t, pub st_uid : ::uid_t, pub st_gid : ::gid_t, pub st_rdev : ::dev_t, pub st_size : ::off_t, pub st_atime : ::time_t, pub st_mtime : ::time_t, pub st_ctime : ::time_t, pub st_blksize : ::blksize_t, pub st_blocks : ::blkcnt_t, pub st_attrib : ::c_uchar, pub st_reserved1 : ::c_int, pub st_reserved2 : ::c_int, pub st_reserved3 : ::c_int, pub st_reserved4 : ::c_int, } //b_struct__Timespec.h pub struct _Timespec { pub tv_sec : ::time_t, pub tv_nsec : ::c_long, } // b_struct__Sched_param.h pub struct _Sched_param { pub sched_priority: ::c_int, /* scheduling priority */ pub sched_ss_low_priority: ::c_int, /* low scheduling priority */ pub sched_ss_repl_period: ::_Timespec, /* replenishment period */ pub sched_ss_init_budget: ::_Timespec, /* initial budget */ pub sched_ss_max_repl: ::c_int, /* max pending replenishment */ } // b_pthread_attr_t.h pub struct pthread_attr_t { pub threadAttrStatus : ::c_int, pub threadAttrStacksize : ::size_t, pub threadAttrStackaddr : *mut ::c_void, pub threadAttrGuardsize : ::size_t, pub threadAttrDetachstate : ::c_int, pub threadAttrContentionscope : ::c_int, pub threadAttrInheritsched : ::c_int, pub threadAttrSchedpolicy : ::c_int, pub threadAttrName : *mut ::c_char, pub threadAttrOptions : ::c_int, pub threadAttrSchedparam : ::_Sched_param, } // signal.h pub struct sigaction { pub sa_u : ::sa_u_t, pub sa_mask : ::sigset_t, pub sa_flags : ::c_int, } // b_stack_t.h pub struct stack_t { pub ss_sp : *mut ::c_void, pub ss_size : ::size_t, pub ss_flags : ::c_int, } // signal.h pub struct siginfo_t { pub si_signo : ::c_int, pub si_code : ::c_int, pub si_value : ::sigval, pub si_errno : ::c_int, pub si_status: ::c_int, pub si_addr: *mut ::c_void, pub si_uid: ::uid_t, pub si_pid: ::pid_t, } // pthread.h (krnl) // b_pthread_mutexattr_t.h (usr) pub struct pthread_mutexattr_t { mutexAttrStatus : ::c_int, mutexAttrPshared : ::c_int, mutexAttrProtocol : ::c_int, mutexAttrPrioceiling : ::c_int, mutexAttrType : ::c_int, } // pthread.h (krnl) // b_pthread_mutex_t.h (usr) pub struct pthread_mutex_t { pub mutexSemId: ::_Vx_SEM_ID, /*_Vx_SEM_ID ..*/ pub mutexValid: ::c_int, pub mutexInitted: ::c_int, pub mutexCondRefCount: ::c_int, pub mutexSavPriority: ::c_int, pub mutexAttr: ::pthread_mutexattr_t, pub mutexSemName: [::c_char; _PTHREAD_SHARED_SEM_NAME_MAX], } // b_struct_timespec.h pub struct timespec { pub tv_sec: ::time_t, pub tv_nsec: ::c_long, } // time.h pub struct tm { pub tm_sec: ::c_int, pub tm_min: ::c_int, pub tm_hour: ::c_int, pub tm_mday: ::c_int, pub tm_mon: ::c_int, pub tm_year: ::c_int, pub tm_wday: ::c_int, pub tm_yday: ::c_int, pub tm_isdst: ::c_int, } // in.h pub struct in_addr { pub s_addr: in_addr_t, } // in.h pub struct ip_mreq { pub imr_multiaddr: in_addr, pub imr_interface: in_addr, } // in6.h #[repr(align(4))] pub struct in6_addr { pub s6_addr: [u8; 16], } // in6.h pub struct ipv6_mreq { pub ipv6mr_multiaddr: in6_addr, pub ipv6mr_interface: ::c_uint, } // netdb.h pub struct addrinfo { pub ai_flags : ::c_int, pub ai_family : ::c_int, pub ai_socktype : ::c_int, pub ai_protocol : ::c_int, pub ai_addrlen : ::size_t, pub ai_canonname: *mut ::c_char, pub ai_addr : *mut ::sockaddr, pub ai_next : *mut ::addrinfo, } // in.h pub struct sockaddr_in { pub sin_len : u8, pub sin_family: u8, pub sin_port : u16, pub sin_addr : ::in_addr, pub sin_zero : [::c_char; 8], } // in6.h pub struct sockaddr_in6 { pub sin6_len : u8, pub sin6_family : u8, pub sin6_port : u16, pub sin6_flowinfo: u32, pub sin6_addr : ::in6_addr, pub sin6_scope_id: u32, } pub struct Dl_info { pub dli_fname: *const ::c_char, pub dli_fbase: *mut ::c_void, pub dli_sname: *const ::c_char, pub dli_saddr: *mut ::c_void, } pub struct mq_attr { pub mq_maxmsg: ::c_long, pub mq_msgsize: ::c_long, pub mq_flags: ::c_long, pub mq_curmsgs: ::c_long, } } s_no_extra_traits! { // dirent.h pub struct dirent { pub d_ino : ::ino_t, pub d_name : [::c_char; _PARM_NAME_MAX as usize + 1], } pub struct sockaddr_un { pub sun_len: u8, pub sun_family: sa_family_t, pub sun_path: [::c_char; 104] } // rtpLibCommon.h pub struct RTP_DESC { pub status : ::c_int, pub options : u32, pub entrAddr : *mut ::c_void, pub initTaskId: ::TASK_ID, pub parentId : ::RTP_ID, pub pathName : [::c_char; VX_RTP_NAME_LENGTH as usize + 1], pub taskCnt : ::c_int, pub textStart : *mut ::c_void, pub textEnd : *mut ::c_void, } // socket.h pub struct sockaddr_storage { pub ss_len : ::c_uchar, pub ss_family : ::sa_family_t, pub __ss_pad1 : [::c_char; _SS_PAD1SIZE], pub __ss_align : i32, pub __ss_pad2 : [::c_char; _SS_PAD2SIZE], } pub union sa_u_t { pub sa_handler : ::Option !>, pub sa_sigaction: ::Option !>, } pub union sigval { pub sival_int : ::c_int, pub sival_ptr : *mut ::c_void, } } cfg_if! { if #[cfg(feature = "extra_traits")] { impl ::fmt::Debug for dirent { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("dirent") .field("d_ino", &self.d_ino) .field("d_name", &&self.d_name[..]) .finish() } } impl ::fmt::Debug for sockaddr_un { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_un") .field("sun_len", &self.sun_len) .field("sun_family", &self.sun_family) .field("sun_path", &&self.sun_path[..]) .finish() } } impl ::fmt::Debug for RTP_DESC { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("RTP_DESC") .field("status", &self.status) .field("options", &self.options) .field("entrAddr", &self.entrAddr) .field("initTaskId", &self.initTaskId) .field("parentId", &self.parentId) .field("pathName", &&self.pathName[..]) .field("taskCnt", &self.taskCnt) .field("textStart", &self.textStart) .field("textEnd", &self.textEnd) .finish() } } impl ::fmt::Debug for sockaddr_storage { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sockaddr_storage") .field("ss_len", &self.ss_len) .field("ss_family", &self.ss_family) .field("__ss_pad1", &&self.__ss_pad1[..]) .field("__ss_align", &self.__ss_align) .field("__ss_pad2", &&self.__ss_pad2[..]) .finish() } } impl PartialEq for sa_u_t { fn eq(&self, other: &sa_u_t) -> bool { unsafe { let h1 = match self.sa_handler { Some(handler) => handler as usize, None => 0 as usize, }; let h2 = match other.sa_handler { Some(handler) => handler as usize, None => 0 as usize, }; h1 == h2 } } } impl Eq for sa_u_t {} impl ::fmt::Debug for sa_u_t { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { unsafe { let h = match self.sa_handler { Some(handler) => handler as usize, None => 0 as usize, }; f.debug_struct("sa_u_t") .field("sa_handler", &h) .finish() } } } impl ::hash::Hash for sa_u_t { fn hash(&self, state: &mut H) { unsafe { let h = match self.sa_handler { Some(handler) => handler as usize, None => 0 as usize, }; h.hash(state) } } } impl PartialEq for sigval { fn eq(&self, other: &sigval) -> bool { unsafe { self.sival_ptr as usize == other.sival_ptr as usize } } } impl Eq for sigval {} impl ::fmt::Debug for sigval { fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { f.debug_struct("sigval") .field("sival_ptr", unsafe { &(self.sival_ptr as usize) }) .finish() } } impl ::hash::Hash for sigval { fn hash(&self, state: &mut H) { unsafe { (self.sival_ptr as usize).hash(state) }; } } } } pub const STDIN_FILENO: ::c_int = 0; pub const STDOUT_FILENO: ::c_int = 1; pub const STDERR_FILENO: ::c_int = 2; pub const EXIT_SUCCESS: ::c_int = 0; pub const EXIT_FAILURE: ::c_int = 1; pub const EAI_SERVICE: ::c_int = 9; pub const EAI_SOCKTYPE: ::c_int = 10; pub const EAI_SYSTEM: ::c_int = 11; // FIXME: This is not defined in vxWorks, but we have to define it here // to make the building pass for getrandom and std pub const RTLD_DEFAULT: *mut ::c_void = 0i64 as *mut ::c_void; //Clock Lib Stuff pub const CLOCK_REALTIME: ::c_int = 0x0; pub const CLOCK_MONOTONIC: ::c_int = 0x1; pub const CLOCK_PROCESS_CPUTIME_ID: ::c_int = 0x2; pub const CLOCK_THREAD_CPUTIME_ID: ::c_int = 0x3; pub const TIMER_ABSTIME: ::c_int = 0x1; pub const TIMER_RELTIME: ::c_int = 0x0; // PTHREAD STUFF pub const PTHREAD_INITIALIZED_OBJ: ::c_int = 0xF70990EF; pub const PTHREAD_DESTROYED_OBJ: ::c_int = -1; pub const PTHREAD_VALID_OBJ: ::c_int = 0xEC542A37; pub const PTHREAD_INVALID_OBJ: ::c_int = -1; pub const PTHREAD_UNUSED_YET_OBJ: ::c_int = -1; pub const PTHREAD_PRIO_NONE: ::c_int = 0; pub const PTHREAD_PRIO_INHERIT: ::c_int = 1; pub const PTHREAD_PRIO_PROTECT: ::c_int = 2; pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0; pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1; pub const PTHREAD_MUTEX_RECURSIVE: ::c_int = 2; pub const PTHREAD_MUTEX_DEFAULT: ::c_int = PTHREAD_MUTEX_NORMAL; pub const PTHREAD_STACK_MIN: usize = 4096; pub const _PTHREAD_SHARED_SEM_NAME_MAX: usize = 30; // ERRNO STUFF pub const OK: ::c_int = 0; pub const EPERM: ::c_int = 1; /* Not owner */ pub const ENOENT: ::c_int = 2; /* No such file or directory */ pub const ESRCH: ::c_int = 3; /* No such process */ pub const EINTR: ::c_int = 4; /* Interrupted system call */ pub const EIO: ::c_int = 5; /* I/O error */ pub const ENXIO: ::c_int = 6; /* No such device or address */ pub const E2BIG: ::c_int = 7; /* Arg list too long */ pub const ENOEXEC: ::c_int = 8; /* Exec format error */ pub const EBADF: ::c_int = 9; /* Bad file number */ pub const ECHILD: ::c_int = 10; /* No children */ pub const EAGAIN: ::c_int = 11; /* No more processes */ pub const ENOMEM: ::c_int = 12; /* Not enough core */ pub const EACCES: ::c_int = 13; /* Permission denied */ pub const EFAULT: ::c_int = 14; pub const ENOTEMPTY: ::c_int = 15; pub const EBUSY: ::c_int = 16; pub const EEXIST: ::c_int = 17; pub const EXDEV: ::c_int = 18; pub const ENODEV: ::c_int = 19; pub const ENOTDIR: ::c_int = 20; pub const EISDIR: ::c_int = 21; pub const EINVAL: ::c_int = 22; pub const ENAMETOOLONG: ::c_int = 26; pub const EFBIG: ::c_int = 27; pub const ENOSPC: ::c_int = 28; pub const ESPIPE: ::c_int = 29; pub const EROFS: ::c_int = 30; pub const EMLINK: ::c_int = 31; pub const EPIPE: ::c_int = 32; pub const EDEADLK: ::c_int = 33; pub const ERANGE: ::c_int = 38; pub const EDESTADDRREQ: ::c_int = 40; pub const EPROTOTYPE: ::c_int = 41; pub const ENOPROTOOPT: ::c_int = 42; pub const EPROTONOSUPPORT: ::c_int = 43; pub const ESOCKTNOSUPPORT: ::c_int = 44; pub const EOPNOTSUPP: ::c_int = 45; pub const EPFNOSUPPORT: ::c_int = 46; pub const EAFNOSUPPORT: ::c_int = 47; pub const EADDRINUSE: ::c_int = 48; pub const EADDRNOTAVAIL: ::c_int = 49; pub const ENOTSOCK: ::c_int = 50; pub const ENETUNREACH: ::c_int = 51; pub const ENETRESET: ::c_int = 52; pub const ECONNABORTED: ::c_int = 53; pub const ECONNRESET: ::c_int = 54; pub const ENOBUFS: ::c_int = 55; pub const EISCONN: ::c_int = 56; pub const ENOTCONN: ::c_int = 57; pub const ESHUTDOWN: ::c_int = 58; pub const ETOOMANYREFS: ::c_int = 59; pub const ETIMEDOUT: ::c_int = 60; pub const ECONNREFUSED: ::c_int = 61; pub const ENETDOWN: ::c_int = 62; pub const ETXTBSY: ::c_int = 63; pub const ELOOP: ::c_int = 64; pub const EHOSTUNREACH: ::c_int = 65; pub const EINPROGRESS: ::c_int = 68; pub const EALREADY: ::c_int = 69; pub const EWOULDBLOCK: ::c_int = 70; pub const ENOSYS: ::c_int = 71; pub const EDQUOT: ::c_int = 83; pub const ESTALE: ::c_int = 88; // NFS errnos: Refer to pkgs_v2/storage/fs/nfs/h/nfs/nfsCommon.h const M_nfsStat: ::c_int = 48 << 16; enum nfsstat { NFSERR_REMOTE = 71, NFSERR_WFLUSH = 99, NFSERR_BADHANDLE = 10001, NFSERR_NOT_SYNC = 10002, NFSERR_BAD_COOKIE = 10003, NFSERR_TOOSMALL = 10005, NFSERR_BADTYPE = 10007, NFSERR_JUKEBOX = 10008, } pub const S_nfsLib_NFS_OK: ::c_int = OK; pub const S_nfsLib_NFSERR_PERM: ::c_int = EPERM; pub const S_nfsLib_NFSERR_NOENT: ::c_int = ENOENT; pub const S_nfsLib_NFSERR_IO: ::c_int = EIO; pub const S_nfsLib_NFSERR_NXIO: ::c_int = ENXIO; pub const S_nfsLib_NFSERR_ACCESS: ::c_int = EACCES; pub const S_nfsLib_NFSERR_EXIST: ::c_int = EEXIST; pub const S_nfsLib_NFSERR_ENODEV: ::c_int = ENODEV; pub const S_nfsLib_NFSERR_NOTDIR: ::c_int = ENOTDIR; pub const S_nfsLib_NFSERR_ISDIR: ::c_int = EISDIR; pub const S_nfsLib_NFSERR_INVAL: ::c_int = EINVAL; pub const S_nfsLib_NFSERR_FBIG: ::c_int = EFBIG; pub const S_nfsLib_NFSERR_NOSPC: ::c_int = ENOSPC; pub const S_nfsLib_NFSERR_ROFS: ::c_int = EROFS; pub const S_nfsLib_NFSERR_NAMETOOLONG: ::c_int = ENAMETOOLONG; pub const S_nfsLib_NFSERR_NOTEMPTY: ::c_int = ENOTEMPTY; pub const S_nfsLib_NFSERR_DQUOT: ::c_int = EDQUOT; pub const S_nfsLib_NFSERR_STALE: ::c_int = ESTALE; pub const S_nfsLib_NFSERR_WFLUSH: ::c_int = M_nfsStat | nfsstat::NFSERR_WFLUSH as ::c_int; pub const S_nfsLib_NFSERR_REMOTE: ::c_int = M_nfsStat | nfsstat::NFSERR_REMOTE as ::c_int; pub const S_nfsLib_NFSERR_BADHANDLE: ::c_int = M_nfsStat | nfsstat::NFSERR_BADHANDLE as ::c_int; pub const S_nfsLib_NFSERR_NOT_SYNC: ::c_int = M_nfsStat | nfsstat::NFSERR_NOT_SYNC as ::c_int; pub const S_nfsLib_NFSERR_BAD_COOKIE: ::c_int = M_nfsStat | nfsstat::NFSERR_BAD_COOKIE as ::c_int; pub const S_nfsLib_NFSERR_NOTSUPP: ::c_int = EOPNOTSUPP; pub const S_nfsLib_NFSERR_TOOSMALL: ::c_int = M_nfsStat | nfsstat::NFSERR_TOOSMALL as ::c_int; pub const S_nfsLib_NFSERR_SERVERFAULT: ::c_int = EIO; pub const S_nfsLib_NFSERR_BADTYPE: ::c_int = M_nfsStat | nfsstat::NFSERR_BADTYPE as ::c_int; pub const S_nfsLib_NFSERR_JUKEBOX: ::c_int = M_nfsStat | nfsstat::NFSERR_JUKEBOX as ::c_int; // in.h pub const IPPROTO_IP: ::c_int = 0; pub const IPPROTO_IPV6: ::c_int = 41; pub const IP_TTL: ::c_int = 4; pub const IP_MULTICAST_IF: ::c_int = 9; pub const IP_MULTICAST_TTL: ::c_int = 10; pub const IP_MULTICAST_LOOP: ::c_int = 11; pub const IP_ADD_MEMBERSHIP: ::c_int = 12; pub const IP_DROP_MEMBERSHIP: ::c_int = 13; // in6.h pub const IPV6_V6ONLY: ::c_int = 1; pub const IPV6_UNICAST_HOPS: ::c_int = 4; pub const IPV6_MULTICAST_IF: ::c_int = 9; pub const IPV6_MULTICAST_HOPS: ::c_int = 10; pub const IPV6_MULTICAST_LOOP: ::c_int = 11; pub const IPV6_ADD_MEMBERSHIP: ::c_int = 12; pub const IPV6_DROP_MEMBERSHIP: ::c_int = 13; // STAT Stuff pub const S_IFMT: ::c_int = 0xf000; pub const S_IFIFO: ::c_int = 0x1000; pub const S_IFCHR: ::c_int = 0x2000; pub const S_IFDIR: ::c_int = 0x4000; pub const S_IFBLK: ::c_int = 0x6000; pub const S_IFREG: ::c_int = 0x8000; pub const S_IFLNK: ::c_int = 0xa000; pub const S_IFSHM: ::c_int = 0xb000; pub const S_IFSOCK: ::c_int = 0xc000; pub const S_ISUID: ::c_int = 0x0800; pub const S_ISGID: ::c_int = 0x0400; pub const S_ISTXT: ::c_int = 0x0200; pub const S_IRUSR: ::c_int = 0x0100; pub const S_IWUSR: ::c_int = 0x0080; pub const S_IXUSR: ::c_int = 0x0040; pub const S_IRWXU: ::c_int = 0x01c0; pub const S_IRGRP: ::c_int = 0x0020; pub const S_IWGRP: ::c_int = 0x0010; pub const S_IXGRP: ::c_int = 0x0008; pub const S_IRWXG: ::c_int = 0x0038; pub const S_IROTH: ::c_int = 0x0004; pub const S_IWOTH: ::c_int = 0x0002; pub const S_IXOTH: ::c_int = 0x0001; pub const S_IRWXO: ::c_int = 0x0007; // socket.h pub const SOL_SOCKET: ::c_int = 0xffff; pub const SO_DEBUG: ::c_int = 0x0001; pub const SO_REUSEADDR: ::c_int = 0x0004; pub const SO_KEEPALIVE: ::c_int = 0x0008; pub const SO_DONTROUTE: ::c_int = 0x0010; pub const SO_RCVLOWAT: ::c_int = 0x0012; pub const SO_SNDLOWAT: ::c_int = 0x0013; pub const SO_SNDTIMEO: ::c_int = 0x1005; pub const SO_ACCEPTCONN: ::c_int = 0x001e; pub const SO_BROADCAST: ::c_int = 0x0020; pub const SO_USELOOPBACK: ::c_int = 0x0040; pub const SO_LINGER: ::c_int = 0x0080; pub const SO_REUSEPORT: ::c_int = 0x0200; pub const SO_VLAN: ::c_int = 0x8000; pub const SO_SNDBUF: ::c_int = 0x1001; pub const SO_RCVBUF: ::c_int = 0x1002; pub const SO_RCVTIMEO: ::c_int = 0x1006; pub const SO_ERROR: ::c_int = 0x1007; pub const SO_TYPE: ::c_int = 0x1008; pub const SO_BINDTODEVICE: ::c_int = 0x1010; pub const SO_OOBINLINE: ::c_int = 0x1011; pub const SO_CONNTIMEO: ::c_int = 0x100a; pub const SOCK_STREAM: ::c_int = 1; pub const SOCK_DGRAM: ::c_int = 2; pub const SOCK_RAW: ::c_int = 3; pub const SOCK_RDM: ::c_int = 4; pub const SOCK_SEQPACKET: ::c_int = 5; pub const SOCK_PACKET: ::c_int = 10; pub const _SS_MAXSIZE: usize = 128; pub const _SS_ALIGNSIZE: usize = size_of::(); pub const _SS_PAD1SIZE: usize = _SS_ALIGNSIZE - size_of::<::c_uchar>() - size_of::<::sa_family_t>(); pub const _SS_PAD2SIZE: usize = _SS_MAXSIZE - size_of::<::c_uchar>() - size_of::<::sa_family_t>() - _SS_PAD1SIZE - _SS_ALIGNSIZE; pub const MSG_OOB: ::c_int = 0x0001; pub const MSG_PEEK: ::c_int = 0x0002; pub const MSG_DONTROUTE: ::c_int = 0x0004; pub const MSG_EOR: ::c_int = 0x0008; pub const MSG_TRUNC: ::c_int = 0x0010; pub const MSG_CTRUNC: ::c_int = 0x0020; pub const MSG_WAITALL: ::c_int = 0x0040; pub const MSG_DONTWAIT: ::c_int = 0x0080; pub const MSG_EOF: ::c_int = 0x0100; pub const MSG_EXP: ::c_int = 0x0200; pub const MSG_MBUF: ::c_int = 0x0400; pub const MSG_NOTIFICATION: ::c_int = 0x0800; pub const MSG_COMPAT: ::c_int = 0x8000; pub const AF_UNSPEC: ::c_int = 0; pub const AF_LOCAL: ::c_int = 1; pub const AF_UNIX: ::c_int = AF_LOCAL; pub const AF_INET: ::c_int = 2; pub const AF_NETLINK: ::c_int = 16; pub const AF_ROUTE: ::c_int = 17; pub const AF_LINK: ::c_int = 18; pub const AF_PACKET: ::c_int = 19; pub const pseudo_AF_KEY: ::c_int = 27; pub const AF_KEY: ::c_int = pseudo_AF_KEY; pub const AF_INET6: ::c_int = 28; pub const AF_SOCKDEV: ::c_int = 31; pub const AF_TIPC: ::c_int = 33; pub const AF_MIPC: ::c_int = 34; pub const AF_MIPC_SAFE: ::c_int = 35; pub const AF_MAX: ::c_int = 37; pub const SHUT_RD: ::c_int = 0; pub const SHUT_WR: ::c_int = 1; pub const SHUT_RDWR: ::c_int = 2; pub const IPPROTO_TCP: ::c_int = 6; pub const TCP_NODELAY: ::c_int = 1; pub const TCP_MAXSEG: ::c_int = 2; pub const TCP_NOPUSH: ::c_int = 3; pub const TCP_KEEPIDLE: ::c_int = 4; pub const TCP_KEEPINTVL: ::c_int = 5; pub const TCP_KEEPCNT: ::c_int = 6; // ioLib.h pub const FIONREAD: ::c_int = 0x40040001; pub const FIOFLUSH: ::c_int = 2; pub const FIOOPTIONS: ::c_int = 3; pub const FIOBAUDRATE: ::c_int = 4; pub const FIODISKFORMAT: ::c_int = 5; pub const FIODISKINIT: ::c_int = 6; pub const FIOSEEK: ::c_int = 7; pub const FIOWHERE: ::c_int = 8; pub const FIODIRENTRY: ::c_int = 9; pub const FIORENAME: ::c_int = 10; pub const FIOREADYCHANGE: ::c_int = 11; pub const FIODISKCHANGE: ::c_int = 13; pub const FIOCANCEL: ::c_int = 14; pub const FIOSQUEEZE: ::c_int = 15; pub const FIOGETNAME: ::c_int = 18; pub const FIONBIO: ::c_int = 0x90040010; // limits.h pub const PATH_MAX: ::c_int = _PARM_PATH_MAX; pub const _POSIX_PATH_MAX: ::c_int = 256; // Some poll stuff pub const POLLIN: ::c_short = 0x0001; pub const POLLPRI: ::c_short = 0x0002; pub const POLLOUT: ::c_short = 0x0004; pub const POLLRDNORM: ::c_short = 0x0040; pub const POLLWRNORM: ::c_short = POLLOUT; pub const POLLRDBAND: ::c_short = 0x0080; pub const POLLWRBAND: ::c_short = 0x0100; pub const POLLERR: ::c_short = 0x0008; pub const POLLHUP: ::c_short = 0x0010; pub const POLLNVAL: ::c_short = 0x0020; // fnctlcom.h pub const FD_CLOEXEC: ::c_int = 1; pub const F_DUPFD: ::c_int = 0; pub const F_GETFD: ::c_int = 1; pub const F_SETFD: ::c_int = 2; pub const F_GETFL: ::c_int = 3; pub const F_SETFL: ::c_int = 4; pub const F_GETOWN: ::c_int = 5; pub const F_SETOWN: ::c_int = 6; pub const F_GETLK: ::c_int = 7; pub const F_SETLK: ::c_int = 8; pub const F_SETLKW: ::c_int = 9; pub const F_DUPFD_CLOEXEC: ::c_int = 14; // signal.h pub const SIG_DFL: sighandler_t = 0 as sighandler_t; pub const SIG_IGN: sighandler_t = 1 as sighandler_t; pub const SIG_ERR: sighandler_t = -1 as isize as sighandler_t; pub const SIGHUP: ::c_int = 1; pub const SIGINT: ::c_int = 2; pub const SIGQUIT: ::c_int = 3; pub const SIGILL: ::c_int = 4; pub const SIGTRAP: ::c_int = 5; pub const SIGABRT: ::c_int = 6; pub const SIGEMT: ::c_int = 7; pub const SIGFPE: ::c_int = 8; pub const SIGKILL: ::c_int = 9; pub const SIGBUS: ::c_int = 10; pub const SIGSEGV: ::c_int = 11; pub const SIGFMT: ::c_int = 12; pub const SIGPIPE: ::c_int = 13; pub const SIGALRM: ::c_int = 14; pub const SIGTERM: ::c_int = 15; pub const SIGCNCL: ::c_int = 16; pub const SIGSTOP: ::c_int = 17; pub const SIGTSTP: ::c_int = 18; pub const SIGCONT: ::c_int = 19; pub const SIGCHLD: ::c_int = 20; pub const SIGTTIN: ::c_int = 21; pub const SIGTTOU: ::c_int = 22; pub const SIG_BLOCK: ::c_int = 1; pub const SIG_UNBLOCK: ::c_int = 2; pub const SIG_SETMASK: ::c_int = 3; pub const SI_SYNC: ::c_int = 0; pub const SI_USER: ::c_int = -1; pub const SI_QUEUE: ::c_int = -2; pub const SI_TIMER: ::c_int = -3; pub const SI_ASYNCIO: ::c_int = -4; pub const SI_MESGQ: ::c_int = -5; pub const SI_CHILD: ::c_int = -6; pub const SI_KILL: ::c_int = SI_USER; // vxParams.h definitions pub const _PARM_NAME_MAX: ::c_int = 255; pub const _PARM_PATH_MAX: ::c_int = 1024; // WAIT STUFF pub const WNOHANG: ::c_int = 0x01; pub const WUNTRACED: ::c_int = 0x02; const PTHREAD_MUTEXATTR_INITIALIZER: pthread_mutexattr_t = pthread_mutexattr_t { mutexAttrStatus: PTHREAD_INITIALIZED_OBJ, mutexAttrProtocol: PTHREAD_PRIO_NONE, mutexAttrPrioceiling: 0, mutexAttrType: PTHREAD_MUTEX_DEFAULT, mutexAttrPshared: 1, }; pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { mutexSemId: null_mut(), mutexValid: PTHREAD_VALID_OBJ, mutexInitted: PTHREAD_UNUSED_YET_OBJ, mutexCondRefCount: 0, mutexSavPriority: -1, mutexAttr: PTHREAD_MUTEXATTR_INITIALIZER, mutexSemName: [0; _PTHREAD_SHARED_SEM_NAME_MAX], }; const PTHREAD_CONDATTR_INITIALIZER: pthread_condattr_t = pthread_condattr_t { condAttrStatus: 0xf70990ef, condAttrPshared: 1, condAttrClockId: CLOCK_REALTIME, }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { condSemId: null_mut(), condValid: PTHREAD_VALID_OBJ, condInitted: PTHREAD_UNUSED_YET_OBJ, condRefCount: 0, condMutex: null_mut(), condAttr: PTHREAD_CONDATTR_INITIALIZER, condSemName: [0; _PTHREAD_SHARED_SEM_NAME_MAX], }; const PTHREAD_RWLOCKATTR_INITIALIZER: pthread_rwlockattr_t = pthread_rwlockattr_t { rwlockAttrStatus: PTHREAD_INITIALIZED_OBJ, rwlockAttrPshared: 1, rwlockAttrMaxReaders: 0, rwlockAttrConformOpt: 1, }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { rwlockSemId: null_mut(), rwlockReadersRefCount: 0, rwlockValid: PTHREAD_VALID_OBJ, rwlockInitted: PTHREAD_UNUSED_YET_OBJ, rwlockAttr: PTHREAD_RWLOCKATTR_INITIALIZER, rwlockSemName: [0; _PTHREAD_SHARED_SEM_NAME_MAX], }; pub const SEEK_SET: ::c_int = 0; pub const SEEK_CUR: ::c_int = 1; pub const SEEK_END: ::c_int = 2; // rtpLibCommon.h pub const VX_RTP_NAME_LENGTH: ::c_int = 255; pub const RTP_ID_ERROR: ::RTP_ID = -1; // h/public/unistd.h pub const _SC_GETPW_R_SIZE_MAX: ::c_int = 21; // Via unistd.h pub const _SC_PAGESIZE: ::c_int = 39; pub const O_ACCMODE: ::c_int = 3; pub const O_CLOEXEC: ::c_int = 0x100000; // fcntlcom pub const O_EXCL: ::c_int = 0x0800; pub const O_CREAT: ::c_int = 0x0200; pub const O_TRUNC: ::c_int = 0x0400; pub const O_APPEND: ::c_int = 0x0008; pub const O_RDWR: ::c_int = 0x0002; pub const O_WRONLY: ::c_int = 0x0001; pub const O_RDONLY: ::c_int = 0; pub const O_NONBLOCK: ::c_int = 0x4000; // mman.h pub const PROT_NONE: ::c_int = 0x0000; pub const PROT_READ: ::c_int = 0x0001; pub const PROT_WRITE: ::c_int = 0x0002; pub const PROT_EXEC: ::c_int = 0x0004; pub const MAP_SHARED: ::c_int = 0x0001; pub const MAP_PRIVATE: ::c_int = 0x0002; pub const MAP_ANON: ::c_int = 0x0004; pub const MAP_ANONYMOUS: ::c_int = MAP_ANON; pub const MAP_FIXED: ::c_int = 0x0010; pub const MAP_CONTIG: ::c_int = 0x0020; pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void; #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} impl ::Copy for FILE {} impl ::Clone for FILE { fn clone(&self) -> FILE { *self } } #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum fpos_t {} // FIXME: fill this out with a struct impl ::Copy for fpos_t {} impl ::Clone for fpos_t { fn clone(&self) -> fpos_t { *self } } f! { pub {const} fn CMSG_ALIGN(len: usize) -> usize { len + ::mem::size_of::() - 1 & !(::mem::size_of::() - 1) } pub fn CMSG_NXTHDR(mhdr: *const msghdr, cmsg: *const cmsghdr) -> *mut cmsghdr { let next = cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize) + CMSG_ALIGN(::mem::size_of::<::cmsghdr>()); let max = (*mhdr).msg_control as usize + (*mhdr).msg_controllen as usize; if next <= max { (cmsg as usize + CMSG_ALIGN((*cmsg).cmsg_len as usize)) as *mut ::cmsghdr } else { 0 as *mut ::cmsghdr } } pub fn CMSG_FIRSTHDR(mhdr: *const msghdr) -> *mut cmsghdr { if (*mhdr).msg_controllen as usize > 0 { (*mhdr).msg_control as *mut cmsghdr } else { 0 as *mut cmsghdr } } pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut ::c_uchar { (cmsg as *mut ::c_uchar) .offset(CMSG_ALIGN(::mem::size_of::<::cmsghdr>()) as isize) } pub {const} fn CMSG_SPACE(length: ::c_uint) -> ::c_uint { (CMSG_ALIGN(length as usize) + CMSG_ALIGN(::mem::size_of::())) as ::c_uint } pub {const} fn CMSG_LEN(length: ::c_uint) -> ::c_uint { CMSG_ALIGN(::mem::size_of::()) as ::c_uint + length } } extern "C" { pub fn isalnum(c: c_int) -> c_int; pub fn isalpha(c: c_int) -> c_int; pub fn iscntrl(c: c_int) -> c_int; pub fn isdigit(c: c_int) -> c_int; pub fn isgraph(c: c_int) -> c_int; pub fn islower(c: c_int) -> c_int; pub fn isprint(c: c_int) -> c_int; pub fn ispunct(c: c_int) -> c_int; pub fn isspace(c: c_int) -> c_int; pub fn isupper(c: c_int) -> c_int; pub fn isxdigit(c: c_int) -> c_int; pub fn isblank(c: c_int) -> c_int; pub fn tolower(c: c_int) -> c_int; pub fn toupper(c: c_int) -> c_int; pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE; pub fn freopen(filename: *const c_char, mode: *const c_char, file: *mut FILE) -> *mut FILE; pub fn fflush(file: *mut FILE) -> c_int; pub fn fclose(file: *mut FILE) -> c_int; pub fn remove(filename: *const c_char) -> c_int; pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int; pub fn tmpfile() -> *mut FILE; pub fn setvbuf(stream: *mut FILE, buffer: *mut c_char, mode: c_int, size: size_t) -> c_int; pub fn setbuf(stream: *mut FILE, buf: *mut c_char); pub fn getchar() -> c_int; pub fn putchar(c: c_int) -> c_int; pub fn fgetc(stream: *mut FILE) -> c_int; pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char; pub fn fputc(c: c_int, stream: *mut FILE) -> c_int; pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int; pub fn puts(s: *const c_char) -> c_int; pub fn ungetc(c: c_int, stream: *mut FILE) -> c_int; pub fn fread(ptr: *mut c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fwrite(ptr: *const c_void, size: size_t, nobj: size_t, stream: *mut FILE) -> size_t; pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int; pub fn ftell(stream: *mut FILE) -> c_long; pub fn rewind(stream: *mut FILE); pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int; pub fn fsetpos(stream: *mut FILE, ptr: *const fpos_t) -> c_int; pub fn feof(stream: *mut FILE) -> c_int; pub fn ferror(stream: *mut FILE) -> c_int; pub fn perror(s: *const c_char); pub fn atof(s: *const c_char) -> c_double; pub fn atoi(s: *const c_char) -> c_int; pub fn atol(s: *const c_char) -> c_long; pub fn atoll(s: *const c_char) -> c_longlong; pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; pub fn strtof(s: *const c_char, endp: *mut *mut c_char) -> c_float; pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long; pub fn strtoll(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_longlong; pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong; pub fn strtoull(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulonglong; pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void; pub fn malloc(size: size_t) -> *mut c_void; pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void; pub fn free(p: *mut c_void); pub fn abort() -> !; pub fn exit(status: c_int) -> !; pub fn atexit(cb: extern "C" fn()) -> c_int; pub fn system(s: *const c_char) -> c_int; pub fn getenv(s: *const c_char) -> *mut c_char; pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char; pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char; pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; pub fn strdup(cs: *const c_char) -> *mut c_char; pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; pub fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int; pub fn strlen(cs: *const c_char) -> size_t; pub fn strerror(n: c_int) -> *mut c_char; pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; pub fn wcslen(buf: *const wchar_t) -> size_t; pub fn wcstombs(dest: *mut c_char, src: *const wchar_t, n: size_t) -> ::size_t; pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; pub fn wmemchr(cx: *const wchar_t, c: wchar_t, n: size_t) -> *mut wchar_t; pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; pub fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; } extern "C" { pub fn fprintf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn printf(format: *const ::c_char, ...) -> ::c_int; pub fn snprintf(s: *mut ::c_char, n: ::size_t, format: *const ::c_char, ...) -> ::c_int; pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn fscanf(stream: *mut ::FILE, format: *const ::c_char, ...) -> ::c_int; pub fn scanf(format: *const ::c_char, ...) -> ::c_int; pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) -> ::c_int; pub fn getchar_unlocked() -> ::c_int; pub fn putchar_unlocked(c: ::c_int) -> ::c_int; pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE; pub fn fileno(stream: *mut ::FILE) -> ::c_int; pub fn creat(path: *const c_char, mode: mode_t) -> ::c_int; pub fn rewinddir(dirp: *mut ::DIR); pub fn fchown(fd: ::c_int, owner: ::uid_t, group: ::gid_t) -> ::c_int; pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; pub fn alarm(seconds: ::c_uint) -> ::c_uint; pub fn fchdir(dirfd: ::c_int) -> ::c_int; pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> ::c_int; pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long; pub fn getegid() -> gid_t; pub fn geteuid() -> uid_t; pub fn getgroups(ngroups_max: ::c_int, groups: *mut gid_t) -> ::c_int; pub fn getlogin() -> *mut c_char; pub fn getopt(argc: ::c_int, argv: *const *mut c_char, optstr: *const c_char) -> ::c_int; pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; pub fn pause() -> ::c_int; pub fn seteuid(uid: uid_t) -> ::c_int; pub fn setegid(gid: gid_t) -> ::c_int; pub fn sleep(secs: ::c_uint) -> ::c_uint; pub fn ttyname(fd: ::c_int) -> *mut c_char; pub fn wait(status: *mut ::c_int) -> pid_t; pub fn umask(mask: mode_t) -> mode_t; pub fn mlock(addr: *const ::c_void, len: ::size_t) -> ::c_int; pub fn mlockall(flags: ::c_int) -> ::c_int; pub fn munlockall() -> ::c_int; pub fn mmap( addr: *mut ::c_void, len: ::size_t, prot: ::c_int, flags: ::c_int, fd: ::c_int, offset: off_t, ) -> *mut ::c_void; pub fn munmap(addr: *mut ::c_void, len: ::size_t) -> ::c_int; pub fn truncate(path: *const c_char, length: off_t) -> ::c_int; pub fn shm_open(name: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int; pub fn shm_unlink(name: *const ::c_char) -> ::c_int; pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; pub fn pthread_exit(value: *mut ::c_void) -> !; pub fn pthread_attr_setdetachstate(attr: *mut ::pthread_attr_t, state: ::c_int) -> ::c_int; pub fn strerror_r(errnum: ::c_int, buf: *mut c_char, buflen: ::size_t) -> ::c_int; pub fn sigaddset(set: *mut sigset_t, signum: ::c_int) -> ::c_int; pub fn sigaction(signum: ::c_int, act: *const sigaction, oldact: *mut sigaction) -> ::c_int; pub fn utimes(filename: *const ::c_char, times: *const ::timeval) -> ::c_int; #[link_name = "_rtld_dlopen"] pub fn dlopen(filename: *const ::c_char, flag: ::c_int) -> *mut ::c_void; #[link_name = "_rtld_dlerror"] pub fn dlerror() -> *mut ::c_char; #[link_name = "_rtld_dlsym"] pub fn dlsym(handle: *mut ::c_void, symbol: *const ::c_char) -> *mut ::c_void; #[link_name = "_rtld_dlclose"] pub fn dlclose(handle: *mut ::c_void) -> ::c_int; #[link_name = "_rtld_dladdr"] pub fn dladdr(addr: *mut ::c_void, info: *mut Dl_info) -> ::c_int; // time.h pub fn gmtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn localtime_r(time_p: *const time_t, result: *mut tm) -> *mut tm; pub fn mktime(tm: *mut tm) -> time_t; pub fn time(time: *mut time_t) -> time_t; pub fn gmtime(time_p: *const time_t) -> *mut tm; pub fn localtime(time_p: *const time_t) -> *mut tm; pub fn timegm(tm: *mut tm) -> time_t; pub fn difftime(time1: time_t, time0: time_t) -> ::c_double; pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int; pub fn usleep(secs: ::useconds_t) -> ::c_int; pub fn putenv(string: *mut c_char) -> ::c_int; pub fn setlocale(category: ::c_int, locale: *const ::c_char) -> *mut ::c_char; pub fn sigprocmask(how: ::c_int, set: *const sigset_t, oldset: *mut sigset_t) -> ::c_int; pub fn sigpending(set: *mut sigset_t) -> ::c_int; pub fn mkfifo(path: *const c_char, mode: mode_t) -> ::c_int; pub fn fseeko(stream: *mut ::FILE, offset: ::off_t, whence: ::c_int) -> ::c_int; pub fn ftello(stream: *mut ::FILE) -> ::off_t; pub fn mkstemp(template: *mut ::c_char) -> ::c_int; pub fn tmpnam(ptr: *mut ::c_char) -> *mut ::c_char; pub fn openlog(ident: *const ::c_char, logopt: ::c_int, facility: ::c_int); pub fn closelog(); pub fn setlogmask(maskpri: ::c_int) -> ::c_int; pub fn syslog(priority: ::c_int, message: *const ::c_char, ...); pub fn getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t; } extern "C" { // stdlib.h pub fn memalign(block_size: ::size_t, size_arg: ::size_t) -> *mut ::c_void; // ioLib.h pub fn getcwd(buf: *mut ::c_char, size: ::size_t) -> *mut ::c_char; // ioLib.h pub fn chdir(attr: *const ::c_char) -> ::c_int; // pthread.h pub fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> ::c_int; // pthread.h pub fn pthread_mutexattr_destroy(attr: *mut pthread_mutexattr_t) -> ::c_int; // pthread.h pub fn pthread_mutexattr_settype(pAttr: *mut ::pthread_mutexattr_t, pType: ::c_int) -> ::c_int; // pthread.h pub fn pthread_mutex_init( mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t, ) -> ::c_int; // pthread.h pub fn pthread_mutex_destroy(mutex: *mut pthread_mutex_t) -> ::c_int; // pthread.h pub fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> ::c_int; // pthread.h pub fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> ::c_int; // pthread.h pub fn pthread_mutex_timedlock(attr: *mut pthread_mutex_t, spec: *const timespec) -> ::c_int; // pthread.h pub fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> ::c_int; // pthread.h pub fn pthread_attr_setname(pAttr: *mut ::pthread_attr_t, name: *mut ::c_char) -> ::c_int; // pthread.h pub fn pthread_attr_setstacksize(attr: *mut ::pthread_attr_t, stacksize: ::size_t) -> ::c_int; // pthread.h pub fn pthread_attr_getstacksize(attr: *const ::pthread_attr_t, size: *mut ::size_t) -> ::c_int; // pthread.h pub fn pthread_attr_init(attr: *mut ::pthread_attr_t) -> ::c_int; // pthread.h pub fn pthread_create( pThread: *mut ::pthread_t, pAttr: *const ::pthread_attr_t, start_routine: extern "C" fn(*mut ::c_void) -> *mut ::c_void, value: *mut ::c_void, ) -> ::c_int; // pthread.h pub fn pthread_attr_destroy(thread: *mut ::pthread_attr_t) -> ::c_int; // pthread.h pub fn pthread_detach(thread: ::pthread_t) -> ::c_int; // int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); pub fn pthread_atfork( prepare: ::Option, parent: ::Option, child: ::Option, ) -> ::c_int; // stat.h pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; // stat.h pub fn lstat(path: *const ::c_char, buf: *mut stat) -> ::c_int; // unistd.h pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; // dirent.h pub fn readdir_r(pDir: *mut ::DIR, entry: *mut ::dirent, result: *mut *mut ::dirent) -> ::c_int; // dirent.h pub fn readdir(pDir: *mut ::DIR) -> *mut ::dirent; // fcntl.h or // ioLib.h pub fn open(path: *const ::c_char, oflag: ::c_int, ...) -> ::c_int; // poll.h pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; // pthread.h pub fn pthread_condattr_init(attr: *mut ::pthread_condattr_t) -> ::c_int; // pthread.h pub fn pthread_condattr_destroy(attr: *mut ::pthread_condattr_t) -> ::c_int; // pthread.h pub fn pthread_condattr_getclock( pAttr: *const ::pthread_condattr_t, pClockId: *mut ::clockid_t, ) -> ::c_int; // pthread.h pub fn pthread_condattr_setclock( pAttr: *mut ::pthread_condattr_t, clockId: ::clockid_t, ) -> ::c_int; // pthread.h pub fn pthread_cond_init( cond: *mut ::pthread_cond_t, attr: *const ::pthread_condattr_t, ) -> ::c_int; // pthread.h pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> ::c_int; // pthread.h pub fn pthread_cond_signal(cond: *mut ::pthread_cond_t) -> ::c_int; // pthread.h pub fn pthread_cond_broadcast(cond: *mut ::pthread_cond_t) -> ::c_int; // pthread.h pub fn pthread_cond_wait(cond: *mut ::pthread_cond_t, mutex: *mut ::pthread_mutex_t) -> ::c_int; // pthread.h pub fn pthread_rwlockattr_init(attr: *mut ::pthread_rwlockattr_t) -> ::c_int; // pthread.h pub fn pthread_rwlockattr_destroy(attr: *mut ::pthread_rwlockattr_t) -> ::c_int; // pthread.h pub fn pthread_rwlockattr_setmaxreaders( attr: *mut ::pthread_rwlockattr_t, attr2: ::c_uint, ) -> ::c_int; // pthread.h pub fn pthread_rwlock_init( attr: *mut ::pthread_rwlock_t, host: *const ::pthread_rwlockattr_t, ) -> ::c_int; // pthread.h pub fn pthread_rwlock_destroy(attr: *mut ::pthread_rwlock_t) -> ::c_int; // pthread.h pub fn pthread_rwlock_rdlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; // pthread.h pub fn pthread_rwlock_tryrdlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; // pthread.h pub fn pthread_rwlock_timedrdlock( attr: *mut ::pthread_rwlock_t, host: *const ::timespec, ) -> ::c_int; // pthread.h pub fn pthread_rwlock_wrlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; // pthread.h pub fn pthread_rwlock_trywrlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; // pthread.h pub fn pthread_rwlock_timedwrlock( attr: *mut ::pthread_rwlock_t, host: *const ::timespec, ) -> ::c_int; // pthread.h pub fn pthread_rwlock_unlock(attr: *mut ::pthread_rwlock_t) -> ::c_int; // pthread.h pub fn pthread_key_create( key: *mut ::pthread_key_t, dtor: ::Option, ) -> ::c_int; // pthread.h pub fn pthread_key_delete(key: ::pthread_key_t) -> ::c_int; // pthread.h pub fn pthread_setspecific(key: ::pthread_key_t, value: *const ::c_void) -> ::c_int; // pthread.h pub fn pthread_getspecific(key: ::pthread_key_t) -> *mut ::c_void; // pthread.h pub fn pthread_cond_timedwait( cond: *mut ::pthread_cond_t, mutex: *mut ::pthread_mutex_t, abstime: *const ::timespec, ) -> ::c_int; // pthread.h pub fn pthread_attr_getname(attr: *mut ::pthread_attr_t, name: *mut *mut ::c_char) -> ::c_int; // pthread.h pub fn pthread_join(thread: ::pthread_t, status: *mut *mut ::c_void) -> ::c_int; // pthread.h pub fn pthread_self() -> ::pthread_t; // clockLib.h pub fn clock_gettime(clock_id: ::clockid_t, tp: *mut ::timespec) -> ::c_int; // clockLib.h pub fn clock_settime(clock_id: ::clockid_t, tp: *const ::timespec) -> ::c_int; // clockLib.h pub fn clock_getres(clock_id: ::clockid_t, res: *mut ::timespec) -> ::c_int; // clockLib.h pub fn clock_nanosleep( clock_id: ::clockid_t, flags: ::c_int, rqtp: *const ::timespec, rmtp: *mut ::timespec, ) -> ::c_int; // timerLib.h pub fn nanosleep(rqtp: *const ::timespec, rmtp: *mut ::timespec) -> ::c_int; // socket.h pub fn accept(s: ::c_int, addr: *mut ::sockaddr, addrlen: *mut ::socklen_t) -> ::c_int; // socket.h pub fn bind(fd: ::c_int, addr: *const sockaddr, len: socklen_t) -> ::c_int; // socket.h pub fn connect(s: ::c_int, name: *const ::sockaddr, namelen: ::socklen_t) -> ::c_int; // socket.h pub fn getpeername(s: ::c_int, name: *mut ::sockaddr, namelen: *mut ::socklen_t) -> ::c_int; // socket.h pub fn getsockname( socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t, ) -> ::c_int; // socket.h pub fn getsockopt( sockfd: ::c_int, level: ::c_int, optname: ::c_int, optval: *mut ::c_void, optlen: *mut ::socklen_t, ) -> ::c_int; // socket.h pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int; // socket.h pub fn recv(s: ::c_int, buf: *mut ::c_void, bufLen: ::size_t, flags: ::c_int) -> ::ssize_t; // socket.h pub fn recvfrom( s: ::c_int, buf: *mut ::c_void, bufLen: ::size_t, flags: ::c_int, from: *mut ::sockaddr, pFromLen: *mut ::socklen_t, ) -> ::ssize_t; pub fn recvmsg(socket: ::c_int, mp: *mut ::msghdr, flags: ::c_int) -> ::ssize_t; // socket.h pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t; pub fn sendmsg(socket: ::c_int, mp: *const ::msghdr, flags: ::c_int) -> ::ssize_t; // socket.h pub fn sendto( socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int, addr: *const sockaddr, addrlen: socklen_t, ) -> ::ssize_t; // socket.h pub fn setsockopt( socket: ::c_int, level: ::c_int, name: ::c_int, value: *const ::c_void, option_len: socklen_t, ) -> ::c_int; // socket.h pub fn shutdown(s: ::c_int, how: ::c_int) -> ::c_int; // socket.h pub fn socket(domain: ::c_int, _type: ::c_int, protocol: ::c_int) -> ::c_int; // icotl.h pub fn ioctl(fd: ::c_int, request: ::c_int, ...) -> ::c_int; // fcntl.h pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int; // ntp_rfc2553.h for kernel // netdb.h for user pub fn gai_strerror(errcode: ::c_int) -> *mut ::c_char; // ioLib.h or // unistd.h pub fn close(fd: ::c_int) -> ::c_int; // ioLib.h or // unistd.h pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t) -> ::ssize_t; // ioLib.h or // unistd.h pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t) -> ::ssize_t; // ioLib.h or // unistd.h pub fn isatty(fd: ::c_int) -> ::c_int; // ioLib.h or // unistd.h pub fn dup(src: ::c_int) -> ::c_int; // ioLib.h or // unistd.h pub fn dup2(src: ::c_int, dst: ::c_int) -> ::c_int; // ioLib.h or // unistd.h pub fn pipe(fds: *mut ::c_int) -> ::c_int; // ioLib.h or // unistd.h pub fn unlink(pathname: *const ::c_char) -> ::c_int; // unistd.h and // ioLib.h pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; // netdb.h pub fn getaddrinfo( node: *const ::c_char, service: *const ::c_char, hints: *const addrinfo, res: *mut *mut addrinfo, ) -> ::c_int; // netdb.h pub fn freeaddrinfo(res: *mut addrinfo); // signal.h pub fn signal(signum: ::c_int, handler: sighandler_t) -> sighandler_t; // unistd.h pub fn getpid() -> pid_t; // unistd.h pub fn getppid() -> pid_t; // wait.h pub fn waitpid(pid: pid_t, status: *mut ::c_int, optons: ::c_int) -> pid_t; // unistd.h pub fn sysconf(attr: ::c_int) -> ::c_long; // stdlib.h pub fn setenv( // setenv.c envVarName: *const ::c_char, envVarValue: *const ::c_char, overwrite: ::c_int, ) -> ::c_int; // stdlib.h pub fn unsetenv( // setenv.c envVarName: *const ::c_char, ) -> ::c_int; // stdlib.h pub fn realpath(fileName: *const ::c_char, resolvedName: *mut ::c_char) -> *mut ::c_char; // unistd.h pub fn link(src: *const ::c_char, dst: *const ::c_char) -> ::c_int; // unistd.h pub fn readlink(path: *const ::c_char, buf: *mut ::c_char, bufsize: ::size_t) -> ::ssize_t; // unistd.h pub fn symlink(path1: *const ::c_char, path2: *const ::c_char) -> ::c_int; // dirent.h pub fn opendir(name: *const ::c_char) -> *mut ::DIR; // unistd.h pub fn rmdir(path: *const ::c_char) -> ::c_int; // stat.h pub fn mkdir(dirName: *const ::c_char, mode: ::mode_t) -> ::c_int; // stat.h pub fn chmod(path: *const ::c_char, mode: ::mode_t) -> ::c_int; // stat.h pub fn fchmod(attr1: ::c_int, attr2: ::mode_t) -> ::c_int; // unistd.h pub fn fsync(fd: ::c_int) -> ::c_int; // dirent.h pub fn closedir(ptr: *mut ::DIR) -> ::c_int; // sched.h pub fn sched_yield() -> ::c_int; // errnoLib.h pub fn errnoSet(err: ::c_int) -> ::c_int; // errnoLib.h pub fn errnoGet() -> ::c_int; // unistd.h pub fn _exit(status: ::c_int) -> !; // unistd.h pub fn setgid(gid: ::gid_t) -> ::c_int; // unistd.h pub fn getgid() -> ::gid_t; // unistd.h pub fn setuid(uid: ::uid_t) -> ::c_int; // unistd.h pub fn getuid() -> ::uid_t; // signal.h pub fn sigemptyset(__set: *mut sigset_t) -> ::c_int; // pthread.h for kernel // signal.h for user pub fn pthread_sigmask( __how: ::c_int, __set: *const sigset_t, __oset: *mut sigset_t, ) -> ::c_int; // signal.h for user pub fn kill(__pid: pid_t, __signo: ::c_int) -> ::c_int; // signal.h for user pub fn sigqueue(__pid: pid_t, __signo: ::c_int, __value: ::sigval) -> ::c_int; // signal.h for user pub fn _sigqueue( rtpId: ::RTP_ID, signo: ::c_int, pValue: *const ::sigval, sigCode: ::c_int, ) -> ::c_int; // signal.h pub fn taskKill(taskId: ::TASK_ID, signo: ::c_int) -> ::c_int; // signal.h pub fn raise(__signo: ::c_int) -> ::c_int; // taskLibCommon.h pub fn taskIdSelf() -> ::TASK_ID; pub fn taskDelay(ticks: ::_Vx_ticks_t) -> ::c_int; // rtpLibCommon.h pub fn rtpInfoGet(rtpId: ::RTP_ID, rtpStruct: *mut ::RTP_DESC) -> ::c_int; pub fn rtpSpawn( pubrtpFileName: *const ::c_char, argv: *mut *const ::c_char, envp: *mut *const ::c_char, priority: ::c_int, uStackSize: ::size_t, options: ::c_int, taskOptions: ::c_int, ) -> RTP_ID; // ioLib.h pub fn _realpath(fileName: *const ::c_char, resolvedName: *mut ::c_char) -> *mut ::c_char; // pathLib.h pub fn _pathIsAbsolute(filepath: *const ::c_char, pNameTail: *mut *const ::c_char) -> BOOL; pub fn writev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t; // randomNumGen.h pub fn randBytes(buf: *mut c_uchar, length: c_int) -> c_int; pub fn randABytes(buf: *mut c_uchar, length: c_int) -> c_int; pub fn randUBytes(buf: *mut c_uchar, length: c_int) -> c_int; pub fn randSecure() -> c_int; // mqueue.h pub fn mq_open(name: *const ::c_char, oflag: ::c_int, ...) -> ::mqd_t; pub fn mq_close(mqd: ::mqd_t) -> ::c_int; pub fn mq_unlink(name: *const ::c_char) -> ::c_int; pub fn mq_receive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, ) -> ::ssize_t; pub fn mq_timedreceive( mqd: ::mqd_t, msg_ptr: *mut ::c_char, msg_len: ::size_t, msg_prio: *mut ::c_uint, abs_timeout: *const ::timespec, ) -> ::ssize_t; pub fn mq_send( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, ) -> ::c_int; pub fn mq_timedsend( mqd: ::mqd_t, msg_ptr: *const ::c_char, msg_len: ::size_t, msg_prio: ::c_uint, abs_timeout: *const ::timespec, ) -> ::c_int; pub fn mq_getattr(mqd: ::mqd_t, attr: *mut ::mq_attr) -> ::c_int; pub fn mq_setattr(mqd: ::mqd_t, newattr: *const ::mq_attr, oldattr: *mut ::mq_attr) -> ::c_int; } //Dummy functions, these don't really exist in VxWorks. // wait.h macros safe_f! { pub {const} fn WIFEXITED(status: ::c_int) -> bool { (status & 0xFF00) == 0 } pub {const} fn WIFSIGNALED(status: ::c_int) -> bool { (status & 0xFF00) != 0 } pub {const} fn WIFSTOPPED(status: ::c_int) -> bool { (status & 0xFF0000) != 0 } pub {const} fn WEXITSTATUS(status: ::c_int) -> ::c_int { status & 0xFF } pub {const} fn WTERMSIG(status: ::c_int) -> ::c_int { (status >> 8) & 0xFF } pub {const} fn WSTOPSIG(status: ::c_int) -> ::c_int { (status >> 16) & 0xFF } } pub fn pread(_fd: ::c_int, _buf: *mut ::c_void, _count: ::size_t, _offset: off64_t) -> ::ssize_t { -1 } pub fn pwrite( _fd: ::c_int, _buf: *const ::c_void, _count: ::size_t, _offset: off64_t, ) -> ::ssize_t { -1 } pub fn posix_memalign(memptr: *mut *mut ::c_void, align: ::size_t, size: ::size_t) -> ::c_int { // check to see if align is a power of 2 and if align is a multiple // of sizeof(void *) if (align & align - 1 != 0) || (align as usize % size_of::<::size_t>() != 0) { return ::EINVAL; } unsafe { // posix_memalign should not set errno let e = ::errnoGet(); let temp = memalign(align, size); ::errnoSet(e as ::c_int); if temp.is_null() { ::ENOMEM } else { *memptr = temp; 0 } } } cfg_if! { if #[cfg(libc_core_cvoid)] { pub use ::ffi::c_void; } else { // Use repr(u8) as LLVM expects `void*` to be the same as `i8*` to help // enable more optimization opportunities around it recognizing things // like malloc/free. #[repr(u8)] #[allow(missing_copy_implementations)] #[allow(missing_debug_implementations)] pub enum c_void { // Two dummy variants so the #[repr] attribute can be used. #[doc(hidden)] __variant1, #[doc(hidden)] __variant2, } } } cfg_if! { if #[cfg(target_arch = "aarch64")] { mod aarch64; pub use self::aarch64::*; } else if #[cfg(target_arch = "arm")] { mod arm; pub use self::arm::*; } else if #[cfg(target_arch = "x86")] { mod x86; pub use self::x86::*; } else if #[cfg(target_arch = "x86_64")] { mod x86_64; pub use self::x86_64::*; } else if #[cfg(target_arch = "powerpc")] { mod powerpc; pub use self::powerpc::*; } else if #[cfg(target_arch = "powerpc64")] { mod powerpc64; pub use self::powerpc64::*; } else { // Unknown target_arch } } libc/src/vxworks/aarch64.rs0000644000175000017500000000013514661133735016561 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type c_long = i64; pub type c_ulong = u64; libc/src/vxworks/powerpc64.rs0000644000175000017500000000013514661133735017162 0ustar jamespagejamespagepub type c_char = u8; pub type wchar_t = u32; pub type c_long = i64; pub type c_ulong = u64; libc/src/macros.rs0000644000175000017500000002516614661133735015105 0ustar jamespagejamespage/// A macro for defining #[cfg] if-else statements. /// /// This is similar to the `if/elif` C preprocessor macro by allowing definition /// of a cascade of `#[cfg]` cases, emitting the implementation which matches /// first. /// /// This allows you to conveniently provide a long list #[cfg]'d blocks of code /// without having to rewrite each clause multiple times. macro_rules! cfg_if { // match if/else chains with a final `else` ($( if #[cfg($($meta:meta),*)] { $($it:item)* } ) else * else { $($it2:item)* }) => { cfg_if! { @__items () ; $( ( ($($meta),*) ($($it)*) ), )* ( () ($($it2)*) ), } }; // match if/else chains lacking a final `else` ( if #[cfg($($i_met:meta),*)] { $($i_it:item)* } $( else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } )* ) => { cfg_if! { @__items () ; ( ($($i_met),*) ($($i_it)*) ), $( ( ($($e_met),*) ($($e_it)*) ), )* ( () () ), } }; // Internal and recursive macro to emit all the items // // Collects all the negated `cfg`s in a list at the beginning and after the // semicolon is all the remaining items (@__items ($($not:meta,)*) ; ) => {}; (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { // Emit all items within one block, applying an appropriate #[cfg]. The // #[cfg] will require all `$m` matchers specified and must also negate // all previous matchers. cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } // Recurse to emit all other items in `$rest`, and when we do so add all // our `$m` matchers to the list of `$not` matchers as future emissions // will have to negate everything we just matched as well. cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } }; // Internal macro to Apply a cfg attribute to a list of items (@__apply $m:meta, $($it:item)*) => { $(#[$m] $it)* }; } macro_rules! s { ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($( s!(it: $(#[$attr])* pub $t $i { $($field)* }); )*); (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => ( compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead"); ); (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => ( __item! { #[repr(C)] #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] #[allow(deprecated)] $(#[$attr])* pub struct $i { $($field)* } } #[allow(deprecated)] impl ::Copy for $i {} #[allow(deprecated)] impl ::Clone for $i { fn clone(&self) -> $i { *self } } ); } macro_rules! s_no_extra_traits { ($($(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($( s_no_extra_traits!(it: $(#[$attr])* pub $t $i { $($field)* }); )*); (it: $(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => ( cfg_if! { if #[cfg(libc_union)] { __item! { #[repr(C)] $(#[$attr])* pub union $i { $($field)* } } impl ::Copy for $i {} impl ::Clone for $i { fn clone(&self) -> $i { *self } } } } ); (it: $(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => ( __item! { #[repr(C)] $(#[$attr])* pub struct $i { $($field)* } } #[allow(deprecated)] impl ::Copy for $i {} #[allow(deprecated)] impl ::Clone for $i { fn clone(&self) -> $i { *self } } ); } macro_rules! missing { ($($(#[$attr:meta])* pub enum $i:ident {})*) => ($( $(#[$attr])* #[allow(missing_copy_implementations)] pub enum $i { } )*); } macro_rules! e { ($($(#[$attr:meta])* pub enum $i:ident { $($field:tt)* })*) => ($( __item! { #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] $(#[$attr])* pub enum $i { $($field)* } } impl ::Copy for $i {} impl ::Clone for $i { fn clone(&self) -> $i { *self } } )*); } macro_rules! s_paren { ($($(#[$attr:meta])* pub struct $i:ident ( $($field:tt)* ); )* ) => ($( __item! { #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))] $(#[$attr])* pub struct $i ( $($field)* ); } impl ::Copy for $i {} impl ::Clone for $i { fn clone(&self) -> $i { *self } } )*); } // This is a pretty horrible hack to allow us to conditionally mark // some functions as 'const', without requiring users of this macro // to care about the "const-extern-fn" feature. // // When 'const-extern-fn' is enabled, we emit the captured 'const' keyword // in the expanded function. // // When 'const-extern-fn' is disabled, we always emit a plain 'pub unsafe extern fn'. // Note that the expression matched by the macro is exactly the same - this allows // users of this macro to work whether or not 'const-extern-fn' is enabled // // Unfortunately, we need to duplicate most of this macro between the 'cfg_if' blocks. // This is because 'const unsafe extern fn' won't even parse on older compilers, // so we need to avoid emitting it at all of 'const-extern-fn'. // // Specifically, moving the 'cfg_if' into the macro body will *not* work. // Doing so would cause the '#[cfg(feature = "const-extern-fn")]' to be emitted // into user code. The 'cfg' gate will not stop Rust from trying to parse the // 'pub const unsafe extern fn', so users would get a compiler error even when // the 'const-extern-fn' feature is disabled // // Note that users of this macro need to place 'const' in a weird position // (after the closing ')' for the arguments, but before the return type). // This was the only way I could satisfy the following two requirements: // 1. Avoid ambiguity errors from 'macro_rules!' (which happen when writing '$foo:ident fn' // 2. Allow users of this macro to mix 'pub fn foo' and 'pub const fn bar' within the same // 'f!' block cfg_if! { if #[cfg(libc_const_extern_fn)] { macro_rules! f { ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident( $($arg:ident: $argty:ty),* ) -> $ret:ty { $($body:stmt);* })*) => ($( #[inline] $(#[$attr])* pub $($constness)* unsafe extern fn $i($($arg: $argty),* ) -> $ret { $($body);* } )*) } macro_rules! safe_f { ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident( $($arg:ident: $argty:ty),* ) -> $ret:ty { $($body:stmt);* })*) => ($( #[inline] $(#[$attr])* pub $($constness)* extern fn $i($($arg: $argty),* ) -> $ret { $($body);* } )*) } macro_rules! const_fn { ($($(#[$attr:meta])* $({$constness:ident})* fn $i:ident( $($arg:ident: $argty:ty),* ) -> $ret:ty { $($body:stmt);* })*) => ($( #[inline] $(#[$attr])* $($constness)* fn $i($($arg: $argty),* ) -> $ret { $($body);* } )*) } } else { macro_rules! f { ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident( $($arg:ident: $argty:ty),* ) -> $ret:ty { $($body:stmt);* })*) => ($( #[inline] $(#[$attr])* pub unsafe extern fn $i($($arg: $argty),* ) -> $ret { $($body);* } )*) } macro_rules! safe_f { ($($(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident( $($arg:ident: $argty:ty),* ) -> $ret:ty { $($body:stmt);* })*) => ($( #[inline] $(#[$attr])* pub extern fn $i($($arg: $argty),* ) -> $ret { $($body);* } )*) } macro_rules! const_fn { ($($(#[$attr:meta])* $({$constness:ident})* fn $i:ident( $($arg:ident: $argty:ty),* ) -> $ret:ty { $($body:stmt);* })*) => ($( #[inline] $(#[$attr])* fn $i($($arg: $argty),* ) -> $ret { $($body);* } )*) } } } macro_rules! __item { ($i:item) => { $i }; } macro_rules! align_const { ($($(#[$attr:meta])* pub const $name:ident : $t1:ty = $t2:ident { $($field:tt)* };)*) => ($( #[cfg(libc_align)] $(#[$attr])* pub const $name : $t1 = $t2 { $($field)* }; #[cfg(not(libc_align))] $(#[$attr])* pub const $name : $t1 = $t2 { $($field)* __align: [], }; )*) } // This macro is used to deprecate items that should be accessed via the mach2 crate macro_rules! deprecated_mach { (pub const $id:ident: $ty:ty = $expr:expr;) => { #[deprecated( since = "0.2.55", note = "Use the `mach2` crate instead", )] #[allow(deprecated)] pub const $id: $ty = $expr; }; ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => { $( deprecated_mach!( pub const $id: $ty = $expr; ); )* }; (pub type $id:ident = $ty:ty;) => { #[deprecated( since = "0.2.55", note = "Use the `mach2` crate instead", )] #[allow(deprecated)] pub type $id = $ty; }; ($(pub type $id:ident = $ty:ty;)*) => { $( deprecated_mach!( pub type $id = $ty; ); )* } } #[cfg(not(libc_ptr_addr_of))] macro_rules! ptr_addr_of { ($place:expr) => { &$place }; } #[cfg(libc_ptr_addr_of)] macro_rules! ptr_addr_of { ($place:expr) => { ::core::ptr::addr_of!($place) }; } libc/CONTRIBUTING.md0000644000175000017500000001127014661133735014704 0ustar jamespagejamespage# Contributing to `libc` Welcome! If you are reading this document, it means you are interested in contributing to the `libc` crate. ## v0.2 changes If you want to add your changes to v0.2, please submit them to the `libc-0.2` branch. If you want to add any breaking changes, it should be submitted to the main branch, which has changes for v0.3. We will support and make a new release for v0.2 until we make the first release of v0.3. ## Adding an API Want to use an API which currently isn't bound in `libc`? It's quite easy to add one! The internal structure of this crate is designed to minimize the number of `#[cfg]` attributes in order to easily be able to add new items which apply to all platforms in the future. As a result, the crate is organized hierarchically based on platform. Each module has a number of `#[cfg]`'d children, but only one is ever actually compiled. Each module then reexports all the contents of its children. This means that for each platform that libc supports, the path from a leaf module to the root will contain all bindings for the platform in question. Consequently, this indicates where an API should be added! Adding an API at a particular level in the hierarchy means that it is supported on all the child platforms of that level. For example, when adding a Unix API it should be added to `src/unix/mod.rs`, but when adding a Linux-only API it should be added to `src/unix/linux_like/linux/mod.rs`. If you're not 100% sure at what level of the hierarchy an API should be added at, fear not! This crate has CI support which tests any binding against all platforms supported, so you'll see failures if an API is added at the wrong level or has different signatures across platforms. New symbol(s) (i.e. functions, constants etc.) should also be added to the symbols list(s) found in the `libc-test/semver` directory. These lists keep track of what symbols are public in the libc crate and ensures they remain available between changes to the crate. If the new symbol(s) are available on all supported Unixes it should be added to `unix.txt` list1, otherwise they should be added to the OS specific list(s). With that in mind, the steps for adding a new API are: 1. Determine where in the module hierarchy your API should be added. 2. Add the API, including adding new symbol(s) to the semver lists. 3. Send a PR to this repo. 4. Wait for CI to pass, fixing errors. 5. Wait for a merge! 1: Note that this list has nothing to do with any Unix or Posix standard, it's just a list shared between all OSs that declare `#[cfg(unix)]`. ## Test before you commit We have two automated tests running on [GitHub Actions](https://github.com/rust-lang/libc/actions): 1. [`libc-test`](https://github.com/gnzlbg/ctest) - `cd libc-test && cargo test` - Use the `skip_*()` functions in `build.rs` if you really need a workaround. 2. Style checker - [`sh ci/style.sh`](https://github.com/rust-lang/libc/blob/main/ci/style.sh) ## Breaking change policy Sometimes an upstream adds a breaking change to their API e.g. removing outdated items, changing the type signature, etc. And we probably should follow that change to build the `libc` crate successfully. It's annoying to do the equivalent of semver-major versioning for each such change. Instead, we mark the item as deprecated and do the actual change after a certain period. The steps are: 1. Add `#[deprecated(since = "", note="")]` attribute to the item. - The `since` field should have a next version of `libc` (e.g., if the current version is `0.2.1`, it should be `0.2.2`). - The `note` field should have a reason to deprecate and a tracking issue to call for comments (e.g., "We consider removing this as the upstream removed it. If you're using it, please comment on #XXX"). 2. If we don't see any concerns for a while, do the change actually. ## Supported target policy When Rust removes a support for a target, the libc crate also may remove the support anytime. ## Releasing your change to crates.io Now that you've done the amazing job of landing your new API or your new platform in this crate, the next step is to get that sweet, sweet usage from crates.io! The only next step is to bump the version of libc and then publish it. If you'd like to get a release out ASAP you can follow these steps: 1. Increment the patch version number in `Cargo.toml` and `libc-test/Cargo.toml`. 1. Send a PR to this repository. It should [look like this][example-pr], but it'd also be nice to fill out the description with a small rationale for the release (any rationale is ok though!). 1. Once merged, the release will be tagged and published by one of the libc crate maintainers. [example-pr]: https://github.com/rust-lang/libc/pull/2120 libc/.cargo-checksum.json0000664000175000017500000006273414661133735016334 0ustar jamespagejamespage{"files":{"CONTRIBUTING.md":"a93fcda0a76e1975fcfb0aa2ba00c9b1864f9ae6062704a294d81a3688898e10","Cargo.toml":"a4fd0b57f9e9365869b9c6030ffa4ca30d84c43deda5883aa5a58d8775877ff9","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"4da2919bb509f3f06163778478494f780ca6627cb79ccab5d2c828c8d88dc133","build.rs":"c26a84b1e50468025002c5e7201b9c104e7e7aec167def54f811b68c0e94a644","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"893fcec48142d273063ffd814dca33fbec92205fd39ada97075f85201d803996","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"07410f511835da540e5bdc55f7384c71cd7836fe63bbca6be547de825f823c03","src/fuchsia/no_align.rs":"303f3f1b255e0088b5715094353cf00476131d8e94e6aebb3f469557771c8b8a","src/fuchsia/riscv64.rs":"617cd75e79e0e20f664db764a4dc2a396d9fd11a4d95371acd91ed4811293b11","src/fuchsia/x86_64.rs":"93a3632b5cf67d2a6bcb7dc0a558605252d5fe689e0f38d8aa2ec5852255ac87","src/hermit/aarch64.rs":"86048676e335944c37a63d0083d0f368ae10ceccefeed9debb3bbe08777fc682","src/hermit/mod.rs":"2d04cfa0d55dc0a2e36fdc4a45819b9d3722af19bb1932778b44feb4c2f81036","src/hermit/x86_64.rs":"ab832b7524e5fb15c49ff7431165ab1a37dc4667ae0b58e8306f4c539bfa110c","src/lib.rs":"9d7030ba3e21064a0f3a8e79927c70d5a95a0026be61be084f3ab021e243e503","src/macros.rs":"5f985b3de7b18833f866bf832b8ffb0430f0f70aa9a468b6a2c855c1bf9d33e4","src/psp.rs":"0a7d5121a8cc2903009f586c00e4ae2d6126d24eb90531dafaba6f59823aa6b2","src/sgx.rs":"16a95cdefc81c5ee00d8353a60db363c4cc3e0f75abcd5d0144723f2a306ed1b","src/solid/aarch64.rs":"a726e47f324adf73a4a0b67a2c183408d0cad105ae66acf36db37a42ab7f8707","src/solid/arm.rs":"e39a4f74ebbef3b97b8c95758ad741123d84ed3eb48d9cf4f1f4872097fc27fe","src/solid/mod.rs":"5f4151dca5132e4b4e4c23ab9737e12856dddbdc0ca3f7dbc004328ef3c8acde","src/switch.rs":"9da3dd39b3de45a7928789926e8572d00e1e11a39e6f7289a1349aadce90edba","src/teeos/mod.rs":"eb664b3e94bcd44d8c8147b56c2187139d01bf8402ee0bb81967a5a50a3e927f","src/unix/aix/mod.rs":"a1ed0ae0164eb783297e185908f6c61c67d5ac82d4f6ab9c559c4d7e0fea51c3","src/unix/aix/powerpc64.rs":"cf374d81139d45f9d77c6a764f640bfbf7e0a5903689652c8296f8e10d55169b","src/unix/align.rs":"2cdc7c826ef7ae61f5171c5ae8c445a743d86f1a7f2d9d7e4ceeec56d6874f65","src/unix/bsd/apple/b32/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b32/mod.rs":"2546ad3eb6aecb95f916648bc63264117c92b4b4859532b34cb011e4c75a5a72","src/unix/bsd/apple/b64/aarch64/align.rs":"2eaf0f561a32bdcbf4e0477c8895d5e7bcb5cdebd5fef7b4df2ca8e38e144d94","src/unix/bsd/apple/b64/aarch64/mod.rs":"44c217a4f263afe7a97435de9323d20a96c37836f899ca0925306d4b7e073c27","src/unix/bsd/apple/b64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/mod.rs":"f5e278a1af7fb358891d1c9be4eb7e815aaca0c5cb738d0c3604ba2208a856f7","src/unix/bsd/apple/b64/x86_64/align.rs":"ec833a747866fe19ca2d9b4d3c9ff0385faba5edf4bd0d15fa68884c40b0e26c","src/unix/bsd/apple/b64/x86_64/mod.rs":"8c87c5855038aae5d433c8f5eb3b29b0a175879a0245342b3bfd83bdf4cfd936","src/unix/bsd/apple/long_array.rs":"3cf1f19b812e6d093c819dc65ce55b13491963e0780eda0d0bd1577603e81948","src/unix/bsd/apple/mod.rs":"e8ed82a15cc3a21337894a123bf8d3cbc9b176224a6709bf6b602a266ff97651","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"2777f94909a798df1b8030fb86d02e2118d0ac3e49e9a542df54a569ca5ae2f9","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"6c8e216385f53a4bf5f171749b57602fc34a4e4b160a44ca31c058cb0c8a2126","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"e243ae0e89623d4fa9f85afe14369cc5fd5f2028ea715773dbec722ba80dac1f","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"bef9fae288a4f29e941ea369be1cd20b170040e60665a4d49a4a9e79009b72d8","src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs":"88be47524b28b6635ccb1e85ea511bf17337be0af7e9baa740c341ac9e83a6f7","src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs":"6ddc6abf6d5ccaea0d8cccf521e8ca6457efcad3086af4155628d5d06d672346","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs":"93115c1a9faa43ebf58b7dee3582aed5a54291b284764e370e7f649b2e6a9565","src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs":"e7b5863e222d6cc416b6b0fbe71690fad909e899b4c4ae810bbca117e4fcb650","src/unix/bsd/freebsdlike/freebsd/mod.rs":"9fb4dd76676d9a91cf1e10e48dad2f010c03bb40ee3c1da863a98b7a2245d4cb","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"fa4bed4c58cad24ba3395941c7fa6b11e089551a04714f9561078e400f5b2b62","src/unix/bsd/freebsdlike/freebsd/x86.rs":"6766e2ce85e187b306cd3b0b8d7e15b8f4042c5cff81d89b3af69ecc99c70ab0","src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs":"0e1f69a88fca1c32874b1daf5db3d446fefbe518dca497f096cc9168c39dde70","src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs":"51e4dd0c8ae247bb652feda5adad9333ea3bb30c750c3a3935e0b0e47d7803eb","src/unix/bsd/freebsdlike/mod.rs":"dca41da072ffb96ba9fd96cefdf629937284a850dd933949cb7f7c5930f3ac54","src/unix/bsd/mod.rs":"1cd730c416c4a00457e5e159ef7d3631966ac5326e15c7a853e03c7d66a90307","src/unix/bsd/netbsdlike/mod.rs":"ea60540aa4edd4e43136749d5df497b1dc072b9912b6030dd1ab794a6d1c3c3c","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"057ee877db7193ba0dc10801b9a6563ac6dbdb78376d6851a84cb12b30841759","src/unix/bsd/netbsdlike/netbsd/arm.rs":"949b55e4dee1c8c511f4f061a6a57ac876a6c0eabfaf5cc20e9ab40d8f41b2e0","src/unix/bsd/netbsdlike/netbsd/mips.rs":"88be18ac43ba224c77e78e4179b6761debc5e6c30a258fac56263809c7af4fbc","src/unix/bsd/netbsdlike/netbsd/mod.rs":"b8d6f089fc8eb2cb59e45335a26c9ce871b846216c9859b553c6b91982f8de33","src/unix/bsd/netbsdlike/netbsd/powerpc.rs":"ee7ff5d89d0ed22f531237b5059aa669df93a3b5c489fa641465ace8d405bf41","src/unix/bsd/netbsdlike/netbsd/riscv64.rs":"1cbe2e5ed681cb1054b699da37daaf6c714267df7d332c90fc2a589b11579625","src/unix/bsd/netbsdlike/netbsd/sparc64.rs":"9489f4b3e4566f43bb12dfb92238960613dac7f6a45cc13068a8d152b902d7d9","src/unix/bsd/netbsdlike/netbsd/x86.rs":"20692320e36bfe028d1a34d16fe12ca77aa909cb02bda167376f98f1a09aefe7","src/unix/bsd/netbsdlike/netbsd/x86_64.rs":"532b76199d6c71ff996eade9f906c55a72c9aff489595d25a21e21878cfd740b","src/unix/bsd/netbsdlike/openbsd/aarch64.rs":"dd91931d373b7ecaf6e2de25adadee10d16fa9b12c2cbacdff3eb291e1ba36af","src/unix/bsd/netbsdlike/openbsd/arm.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/mips64.rs":"8532a189ae10c7d668d9d4065da8b05d124e09bd39442c9f74a7f231c43eca48","src/unix/bsd/netbsdlike/openbsd/mod.rs":"7b93b5b24b3c72a79b2de19b47ac2f56b29d87e9fc8f4c721a63d1e87ec83fcc","src/unix/bsd/netbsdlike/openbsd/powerpc.rs":"01580d261bc6447bb327a0d982181b7bdabfa066cee65a30373d3ced729ad307","src/unix/bsd/netbsdlike/openbsd/powerpc64.rs":"1dd5449dd1fd3d51e30ffdeeaece91d0aaf05c710e0ac699fecc5461cfa2c28e","src/unix/bsd/netbsdlike/openbsd/riscv64.rs":"1fe3332dc705a13e6242219970f5449d6d7a73e2e6c8537ab8e421d8a6f2e3ff","src/unix/bsd/netbsdlike/openbsd/sparc64.rs":"d04fd287afbaa2c5df9d48c94e8374a532a3ba491b424ddf018270c7312f4085","src/unix/bsd/netbsdlike/openbsd/x86.rs":"6f7f5c4fde2a2259eb547890cbd86570cea04ef85347d7569e94e679448bec87","src/unix/bsd/netbsdlike/openbsd/x86_64.rs":"d31db31630289c85af3339dbe357998a21ca584cbae31607448fe2cf7675a4e1","src/unix/haiku/b32.rs":"a2efdbf7158a6da341e1db9176b0ab193ba88b449616239ed95dced11f54d87b","src/unix/haiku/b64.rs":"ff8115367d3d7d354f792d6176dfaaa26353f57056197b563bf4681f91ff7985","src/unix/haiku/mod.rs":"a97c51465d706e0dea8a7e2850d927c4ed78a7aa6603468d8b8df59ae1f2d296","src/unix/haiku/native.rs":"3bbf42c3e3e437e8b626be67c72b6adcec60646eb5dd4bf8471a603cbbb5e5a4","src/unix/haiku/x86_64.rs":"3ec3aeeb7ed208b8916f3e32d42bfd085ff5e16936a1a35d9a52789f043b7237","src/unix/hurd/align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/hurd/b32.rs":"2ba90ed973f90366c36a6387833a3df42abfee9622d4a0352635937d4a89eaf4","src/unix/hurd/b64.rs":"d919b4aec9b3080ad24c125c57b2c8b2e483d72045f1554c429d14560355846f","src/unix/hurd/mod.rs":"6a2f0db80a3cd34b55ef82e357da4d453d5d190a2dd4501bfa5d0bb9bca0de4f","src/unix/hurd/no_align.rs":"03c79b2cd8270ebd0cf93cb475a8f1ff85b28175ea0de007ede17cad94a89b03","src/unix/linux_like/android/b32/arm.rs":"ce582de7e983a33d3bfad13075c53aac9016cee35f06ad8653ee9072c3ec2564","src/unix/linux_like/android/b32/mod.rs":"7c173e0375119bf06a3081652faede95e5bcd6858e7576b7533d037978737c8f","src/unix/linux_like/android/b32/x86/align.rs":"812914e4241df82e32b12375ca3374615dc3a4bdd4cf31f0423c5815320c0dab","src/unix/linux_like/android/b32/x86/mod.rs":"e6d107efbcd37b5b85dfa18f683300cbf768ffa0237997a9fa52b184a53323ac","src/unix/linux_like/android/b64/aarch64/align.rs":"2179c3b1608fa4bf68840482bfc2b2fa3ee2faf6fcae3770f9e505cddca35c7b","src/unix/linux_like/android/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/android/b64/aarch64/mod.rs":"873af67c4a9757ead56bc797d04efcecd311ecbf0084ebdd198fb690463ef299","src/unix/linux_like/android/b64/mod.rs":"71e4fcbe952bfa4a5f9022f3972e906917b38f729b9d8ef57cd5d179104894ac","src/unix/linux_like/android/b64/riscv64/align.rs":"0bf138f84e5327d8339bcd4adf071a6832b516445e597552c82bbd881095e3a8","src/unix/linux_like/android/b64/riscv64/mod.rs":"19d4bf2237c47127eba9144e0b82e995bc079315e719179a91813b0ae7b0e49d","src/unix/linux_like/android/b64/x86_64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/android/b64/x86_64/mod.rs":"4ec2de11a9b65c4325b7b991f0b99a414975e0e61ba8668caca5d921e9b314d1","src/unix/linux_like/android/mod.rs":"d68feed235b945ff6e32a8d5c8b659b04966f42a7a77722b454dce2b54561cbd","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/lfs64.rs":"3776af30a758d765a88920ec4fde442ab89040da13d3b3625c7fbcb8a958559f","src/unix/linux_like/emscripten/mod.rs":"70d4591730a731ee32788a9d8d2de379592844ec36b7d1723514179605587713","src/unix/linux_like/emscripten/no_align.rs":"0128e4aa721a9902754828b61b5ec7d8a86619983ed1e0544a85d35b1051fad6","src/unix/linux_like/linux/align.rs":"bc5abcd38e2320171e0981e773c9c5fe3e0d5a66fdff049228f6a1acad80ef8b","src/unix/linux_like/linux/arch/generic/mod.rs":"3ab533349696d24505adb6bb9183d73fd5e3b17e2f90dd21478af2a47b4d6fa8","src/unix/linux_like/linux/arch/mips/mod.rs":"ca3db0e3ae852abf18f3588e40d5d64707fcc1829e08ddc5da1080e1a92c8851","src/unix/linux_like/linux/arch/mod.rs":"5bd5361f8a6ab4e18bbba6da9f92c164ae252b15a0ed10064812544aa1fdf198","src/unix/linux_like/linux/arch/powerpc/mod.rs":"0bc2d2667a00eca81f4abeb6d613a90848a947f51224103f83268928b8197629","src/unix/linux_like/linux/arch/sparc/mod.rs":"5e6777863e74a9e2aa9dc487f1059783dd211babc2b32d6bf676f311e49c55d6","src/unix/linux_like/linux/gnu/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/gnu/b32/arm/align.rs":"6ec0eb3ee93f7ae99fd714b4deabfb5e97fbcefd8c26f5a45fb8e7150899cdeb","src/unix/linux_like/linux/gnu/b32/arm/mod.rs":"f68ec59b6407f9d4e326f3e71a41ec21f19ecfc703edf9a93e496f661fed5506","src/unix/linux_like/linux/gnu/b32/csky/align.rs":"3fed009dc9af3cc81be7087da9d2d7d1f39845e4497e290259c5cdbae25f039d","src/unix/linux_like/linux/gnu/b32/csky/mod.rs":"8729b68e433e94c2128e51a7db4fd555938e4be4dc64584c352b24a20d9c8e91","src/unix/linux_like/linux/gnu/b32/m68k/align.rs":"8faa92f77a9232c035418d45331774e64a9a841d99c91791570a203bf2b45bcb","src/unix/linux_like/linux/gnu/b32/m68k/mod.rs":"80956d3fef163ecf248828a6f38782dd8ae856d86b1bb5aac2de36032dbd8ea0","src/unix/linux_like/linux/gnu/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/gnu/b32/mips/mod.rs":"96e22350d5d132d917c743d6560464500652c67b52c3d0e8474494487df3365d","src/unix/linux_like/linux/gnu/b32/mod.rs":"b56625dd20dd48a8699034d349ef089c540c0ddcbf8a3481d598d101f8b40b78","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"20fc3cc4fe1ef6617b63b61b897f782ceb9c2842fc718f504a1840537229bf47","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"887288a0a1cfff319d0e15edcdc4fcb31fd643ff41715ec5244c8f2413624169","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"cc4342b949e4d796f304acd9dfe3f721a1c2f37fec16b42d3bb27dc94723af37","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"06d4db4ee8352f62a0a5ead0c4d6ea0a78feff522f19b9bc5772f6dd920ffd80","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"fdf1c72375a2167699157e0dd825422690bb6719f7bc69515a2e5846d0431d7c","src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs":"832e7487249c1c0bb6e9911ce3f7d32ca22378e42392ab83c56915cbc59d8be3","src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs":"bf4611b737813deef6787babf6c01698605f3b75482269b8546318667bc68e29","src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs":"11a950697fdda0258c6e37c6b13993348c8de4134105ed4faa79358e53175072","src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs":"8202614484da36c388d2ffdd2554c56bb4f9db8e5bd621f8c36114cdcfeec644","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"10f025edecebc6e0ed8fdae4736ebe7564189741d5b910433f07c21fc12a94d8","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"73532be4b5775acf9524c77feeefe1f6d1936ceffef908d01dd2586986520f2d","src/unix/linux_like/linux/gnu/b64/mod.rs":"6a160ef25439c4fecdb0e3bd0b818742263c791364da874d4febd3aa644ec8e2","src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs":"a90c2641616c620e9d1fea87695ce046e14f9da2282bb93f761eeb4077c74741","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"dec86883731f7b8419bff35b125b40eefc927090c1510f6daf931726f7965c0b","src/unix/linux_like/linux/gnu/b64/s390x.rs":"1ea9e39432ce6bf68779d33546dacd7d39477a9f8fc3da4f4f339e4538cb74c3","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"bed381c44cec2a5b50125f7e548ab487d4c829006c971d152a611b7141760052","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"332846e4a5920d7e6b05df0448a2333c5dd00fb27cb33654648f507ee89dbec5","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"38f74ce15d9662ce4818815a2b87be1618d5e45f190f7e4db84ff3285b4421fb","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"b20218a11364a6dec87f96d6c0d8b19e660697ab09ad5ee0e9b3a9dafedaaebb","src/unix/linux_like/linux/gnu/mod.rs":"78ce3d4fe6dcb9dc90210526023a1421502e341a7c39d769fd385001c1eb3b8d","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"efdc36b0e95a87b45093756e766cded003bac6fbd9493cd1af158f7476b2d3e2","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"af10147d7c3661751750a58ffad089d5d18d180cd18303c653aef126c07ccd91","src/unix/linux_like/linux/musl/b32/hexagon.rs":"d079cab42529f7dab699334d43168c74ff4aa0282f11040a8b7d274b65767a7a","src/unix/linux_like/linux/musl/b32/mips/align.rs":"429fb5e005cb7143602d430098b6ebfb7d360685b194f333dfd587472ae954ee","src/unix/linux_like/linux/musl/b32/mips/mod.rs":"e44043766f7cd26de7ffa4232654afb6feb03e58dbd5890717970887bd003151","src/unix/linux_like/linux/musl/b32/mod.rs":"31677597fd9544c4b1ec1477628288f6273fabbc06e38f33da862ad55f019ce1","src/unix/linux_like/linux/musl/b32/powerpc.rs":"3dae56a4e7789bcc5314e419fea5e4b2495367b4f1a49d1c9477c60225d65eef","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"3ee845d272f91a1908d5f421d7c353e1f14681bbdfef64410e408f4c14365a91","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"f2b53ae0034c833244b7cdb8c670349bf8272a03abf04152eba65cf62810484d","src/unix/linux_like/linux/musl/b64/aarch64/align.rs":"6ba32725d24d7d8e6aa111f3b57aafa318f83b606abe96561329151829821133","src/unix/linux_like/linux/musl/b64/aarch64/int128.rs":"1735f6f5c56770d20dd426442f09724d9b2052b46a7cd82f23f3288a4a7276de","src/unix/linux_like/linux/musl/b64/aarch64/mod.rs":"45ce6897afcc960267bb7505702b639daf94dc69428a213bf1aefd367ca32adc","src/unix/linux_like/linux/musl/b64/loongarch64/align.rs":"060aa33cc737966c691aab8511c5c5729e551458ce18d0e284e0d45f39beeb60","src/unix/linux_like/linux/musl/b64/loongarch64/mod.rs":"3d9ef92e682a1789544a2bd20cad5a5623db9d7d9f5d0a3692bb0230af034165","src/unix/linux_like/linux/musl/b64/mips64.rs":"a968ef9c54fa22293085f318c8472c1754482df92cc500568dc33bd807d71ea6","src/unix/linux_like/linux/musl/b64/mod.rs":"20ceaf90a03c24a2eb154a5dffbfc9a538348404db5b554a3d8126021ba45509","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"140e579800a67315f4cb8a42b22aa8157eae34ffe626e77e421b43c53c23b34d","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"c5944526d7e19cd43e9d14d119a1d98f8780db7ecbcc79e69d7b9348e596b520","src/unix/linux_like/linux/musl/b64/s390x.rs":"8557b3477ca8cefef7fce764a3c25441929a54e50ead4091f6f7823c427cd728","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"a91c4f18027c9958037f78ae48f6352d23cb4e6f2995b2cc8de7dce0e5759470","src/unix/linux_like/linux/musl/lfs64.rs":"3e4fb381f3a0756520bde0f1692d4fa45e4ae8133bf7d7c64b0e3fdd512f235f","src/unix/linux_like/linux/musl/mod.rs":"ac8ccdb25116ecdfa44eacaffefb21329aa286713c44a12dbe2c1614f2a2748a","src/unix/linux_like/linux/no_align.rs":"62cdca0e011937aaf09a51ca86d9f0ee0fdb05f61ec3c058e6a5d5fa6357d784","src/unix/linux_like/linux/non_exhaustive.rs":"181a05bf94fdb911db83ce793b993bd6548a4115b306a7ef3c10f745a8fea3e9","src/unix/linux_like/linux/uclibc/align.rs":"9ed16138d8e439bd90930845a65eafa7ebd67366e6bf633936d44014f6e4c959","src/unix/linux_like/linux/uclibc/arm/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/arm/mod.rs":"50288ff9e411ab0966da24838f2c2a5618021bc19c422a04f577b2979ef4081e","src/unix/linux_like/linux/uclibc/arm/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips32/align.rs":"e4a3c27fe20a57b8d612c34cb05bc70646edb5cec7251957315afa53a7b9f936","src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs":"d0c4434e2bf813372c418a8f516c706cdccc9f7be2f0921b2207b0afdb66fe81","src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/uclibc/mips/mips64/align.rs":"a7bdcb18a37a2d91e64d5fad83ea3edc78f5412adb28f77ab077dbb26dd08b2d","src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs":"3f38ee6a4690b9d7594be20d216467a34d955f7653c2c8ce1e6147daeb53f1e0","src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs":"4a18e3875698c85229599225ac3401a2a40da87e77b2ad4ef47c6fcd5a24ed30","src/unix/linux_like/linux/uclibc/mips/mod.rs":"a048fce1c2d9b1ad57305642e8ad05ca0f0c7e4753267a2e2d6b4fee5db3b072","src/unix/linux_like/linux/uclibc/mod.rs":"193a03fa4aa5345394e39d2115c9427e806c9f28b0fde685719119e1c90ca08a","src/unix/linux_like/linux/uclibc/no_align.rs":"3f28637046524618adaa1012e26cb7ffe94b9396e6b518cccdc69d59f274d709","src/unix/linux_like/linux/uclibc/x86_64/l4re.rs":"8485b9182b7c67f7344fab377e7cc2a72afefd9ab63837c860514abba9728d76","src/unix/linux_like/linux/uclibc/x86_64/mod.rs":"196d03affbefb85716937c15904831e731eb222ee906e05e42102d639a8152ea","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"863f628cbaa864911ffebc58e9fb788b6c6a9651955fc401ac1f40f20eb62505","src/unix/mod.rs":"e3a98b62b83a1e42675e968c05b2281d612a66cdc09c4e3b4c16921c31a9e254","src/unix/newlib/aarch64/mod.rs":"964c096288da836b53c0c71d7f3a97048d177da220a69314c5ce93ba330d72af","src/unix/newlib/align.rs":"28aaf87fafbc6b312622719d472d8cf65f9e5467d15339df5f73e66d8502b28a","src/unix/newlib/arm/mod.rs":"cf754f8b1197489fca01e881a4b4b146e814998e4b365f116fa1a102c00e6a4e","src/unix/newlib/espidf/mod.rs":"689e29a9fff5a263e5ab8410d0a8919f77fa64aa12f4d71f71085a6f07f19f67","src/unix/newlib/generic.rs":"5f0b5d07ddb5a5d60580f9561fdb05e9218d9751d4068c4aadad2ba6b950aabf","src/unix/newlib/horizon/mod.rs":"3a521d22bf932fc01c1d26d1f9bff20f11b1855b03c8236a8eb18310f6cab5a8","src/unix/newlib/mod.rs":"e5d5faf27a6336b9f1c02b8726427801d906a14dae766852b4e85c1a92df06c8","src/unix/newlib/no_align.rs":"e0743b2179495a9514bc3a4d1781e492878c4ec834ee0085d0891dd1712e82fb","src/unix/newlib/powerpc/mod.rs":"cc9e188711b9bf614323ad6c48e0d2e1a1ecc5d3bc64961ba451f29c6c22d2d8","src/unix/newlib/vita/mod.rs":"ff1caf74bb0696fe15d60dbac598db4520cd538aa0f5989713d97d008eee6ad8","src/unix/no_align.rs":"c06e95373b9088266e0b14bba0954eef95f93fb2b01d951855e382d22de78e53","src/unix/nto/aarch64.rs":"4709c9afdc8d583be876598e7c238499ee3e8da5bd2baa614d9c7dd414851555","src/unix/nto/mod.rs":"07268897fc8810f2fed22ab56f87757f71c73ba401abd848bccca6b183a13b02","src/unix/nto/neutrino.rs":"799bff4ab01a6424db6c5a2b76aa5679826d41495f9d13c63485bf13bc80026b","src/unix/nto/x86_64.rs":"a3e18e93c2999da1cd7a6f748a4b60c07aefb73d8ea2aafec19a84cfb040bc8e","src/unix/redox/mod.rs":"e75a319975472fe9e0873244fb07c5d2004672b7a4cf7a3cb01532d6d394cb8a","src/unix/solarish/compat.rs":"00f1ee3faec9da69204e42f025f6735dd13d894071a154425dcc43ecbdd06e7f","src/unix/solarish/illumos.rs":"cd93c2d84722bbf9933a92842a8998eb0b2afc962f50bc2546ad127b82809fa7","src/unix/solarish/mod.rs":"3e550d95419169febf094c425451ca86b12821fa17839b4b0ba7520b145a5820","src/unix/solarish/solaris.rs":"41b350a89ddf01cd12a10f93640f92be53be0b0d976021cdc08da17bf3e72edf","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"ec2b01f194eb8a6a27133c57681da195a949e03098f3ea1e847227a9c09ef5fc","src/unix/solarish/x86_common.rs":"ac869d9c3c95645c22460468391eb1982023c3a8e02b9e06a72e3aef3d5f1eac","src/vxworks/aarch64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/arm.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/mod.rs":"4105a2e6a6c9908fc1f2a770ede052bb0d6a5d9d49e32d815f557081efc49860","src/vxworks/powerpc.rs":"acb7968ce99fe3f4abdf39d98f8133d21a4fba435b8ef7084777cb181d788e88","src/vxworks/powerpc64.rs":"98f0afdc511cd02557e506c21fed6737585490a1dce7a9d4941d08c437762b99","src/vxworks/x86.rs":"552f007f38317620b23889cb7c49d1d115841252439060122f52f434fbc6e5ba","src/vxworks/x86_64.rs":"018d92be3ad628a129eff9f2f5dfbc0883d8b8e5f2fa917b900a7f98ed6b514a","src/wasi.rs":"d4147353537d7556076ff1a1c4cb96cc2dae9416a5d176ba8a077ad55ab7ec18","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"9fdc5e1c62c441abef7bc62a7343efb2041edc24db9ac0efc0f74df55b69e249","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","src/xous.rs":"eb0675f25ba01f73072d2b70907fb8abb1148facefe5a20756c49250f3d65fae","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"}memoffset/0000775000175000017500000000000014661133735013530 5ustar jamespagejamespagememoffset/build.rs0000644000175000017500000000142014661133735015170 0ustar jamespagejamespageextern crate autocfg; fn main() { let ac = autocfg::new(); // Check for a minimum version for a few features if ac.probe_rustc_version(1, 20) { println!("cargo:rustc-cfg=tuple_ty"); } if ac.probe_rustc_version(1, 31) { println!("cargo:rustc-cfg=allow_clippy"); } if ac.probe_rustc_version(1, 36) { println!("cargo:rustc-cfg=maybe_uninit"); } if ac.probe_rustc_version(1, 40) { println!("cargo:rustc-cfg=doctests"); } if ac.probe_rustc_version(1, 51) { println!("cargo:rustc-cfg=raw_ref_macros"); } if ac.probe_rustc_version(1, 65) { println!("cargo:rustc-cfg=stable_const"); } if ac.probe_rustc_version(1, 77) { println!("cargo:rustc-cfg=stable_offset_of"); } } memoffset/README.md0000644000175000017500000000324214661133735015006 0ustar jamespagejamespage# memoffset # [![](https://img.shields.io/crates/v/memoffset.svg)](https://crates.io/crates/memoffset) C-Like `offset_of` functionality for Rust structs. Introduces the following macros: * `offset_of!` for obtaining the offset of a member of a struct. * `offset_of_tuple!` for obtaining the offset of a member of a tuple. (Requires Rust 1.20+) * `offset_of_union!` for obtaining the offset of a member of a union. * `span_of!` for obtaining the range that a field, or fields, span. `memoffset` works under `no_std` environments. If you're using a rustc version greater or equal to 1.77, this crate's `offset_of!()` macro simply forwards to `core::mem::offset_of!()`. ## Usage ## Add the following dependency to your `Cargo.toml`: ```toml [dependencies] memoffset = "0.9" ``` These versions will compile fine with rustc versions greater or equal to 1.19. ## Examples ## ```rust use memoffset::{offset_of, span_of}; #[repr(C, packed)] struct Foo { a: u32, b: u32, c: [u8; 5], d: u32, } fn main() { assert_eq!(offset_of!(Foo, b), 4); assert_eq!(offset_of!(Foo, d), 4+4+5); assert_eq!(span_of!(Foo, a), 0..4); assert_eq!(span_of!(Foo, a .. c), 0..8); assert_eq!(span_of!(Foo, a ..= c), 0..13); assert_eq!(span_of!(Foo, ..= d), 0..17); assert_eq!(span_of!(Foo, b ..), 4..17); } ``` ## Usage in constants ## `memoffset` has support for compile-time `offset_of!` on rust>=1.65. On versions below 1.77, this is an incomplete implementation with one caveat: Due to dependence on [`#![feature(const_refs_to_cell)]`](https://github.com/rust-lang/rust/issues/80384), you cannot get the offset of a `Cell` field in a const-context. memoffset/Cargo.toml0000644000175000017500000000171214661133735015457 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] name = "memoffset" version = "0.9.1" authors = ["Gilad Naaman "] description = "offset_of functionality for Rust structs." readme = "README.md" keywords = [ "mem", "offset", "offset_of", "offsetof", ] categories = ["no-std"] license = "MIT" repository = "https://github.com/Gilnaa/memoffset" [dev-dependencies.doc-comment] version = "0.3" [build-dependencies.autocfg] version = "1" [features] default = [] unstable_const = [] unstable_offset_of = [] memoffset/src/0000775000175000017500000000000014661133735014317 5ustar jamespagejamespagememoffset/src/offset_of.rs0000644000175000017500000002774014661133735016647 0ustar jamespagejamespage// Copyright (c) 2017 Gilad Naaman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /// Macro to create a local `base_ptr` raw pointer of the given type, avoiding UB as /// much as is possible currently. #[cfg(maybe_uninit)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__let_base_ptr { ($name:ident, $type:ty) => { // No UB here, and the pointer does not dangle, either. // But we have to make sure that `uninit` lives long enough, // so it has to be in the same scope as `$name`. That's why // `let_base_ptr` declares a variable (several, actually) // instead of returning one. let uninit = $crate::__priv::mem::MaybeUninit::<$type>::uninit(); let $name: *const $type = uninit.as_ptr(); }; } #[cfg(not(maybe_uninit))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__let_base_ptr { ($name:ident, $type:ty) => { // No UB right here, but we will later dereference this pointer to // offset into a field, and that is UB because the pointer is dangling. let $name = $crate::__priv::mem::align_of::<$type>() as *const $type; }; } /// Macro to compute the distance between two pointers. #[cfg(stable_const)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset_offset_from_unsafe { ($field:expr, $base:expr) => {{ let field = $field; // evaluate $field outside the `unsafe` block let base = $base; // evaluate $base outside the `unsafe` block // Compute offset, with unstable `offset_from` for const-compatibility. // (Requires the pointers to not dangle, but we already need that for `raw_field!` anyway.) unsafe { (field as *const u8).offset_from(base as *const u8) as usize } }}; } #[cfg(not(stable_const))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset_offset_from_unsafe { ($field:expr, $base:expr) => { // Compute offset. ($field as usize) - ($base as usize) }; } #[cfg(not(stable_offset_of))] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_impl { ($parent:path, $field:tt) => {{ // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). _memoffset__let_base_ptr!(base_ptr, $parent); // Get field pointer. let field_ptr = raw_field!(base_ptr, $parent, $field); // Compute offset. _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } #[cfg(stable_offset_of)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__offset_of_impl { ($parent:path, $field:tt) => {{ $crate::__priv::mem::offset_of!($parent, $field) }}; } /// Calculates the offset of the specified field from the start of the named struct. /// /// ## Examples /// ``` /// use memoffset::offset_of; /// /// #[repr(C, packed)] /// struct Foo { /// a: u32, /// b: u64, /// c: [u8; 5] /// } /// /// assert_eq!(offset_of!(Foo, a), 0); /// assert_eq!(offset_of!(Foo, b), 4); /// ``` /// /// ## Notes /// Rust's ABI is unstable, and [type layout can be changed with each /// compilation](https://doc.rust-lang.org/reference/type-layout.html). /// /// Using `offset_of!` with a `repr(Rust)` struct will return the correct offset of the /// specified `field` for a particular compilation, but the exact value may change /// based on the compiler version, concrete struct type, time of day, or rustc's mood. /// /// As a result, the value should not be retained and used between different compilations. #[macro_export(local_inner_macros)] macro_rules! offset_of { ($parent:path, $field:tt) => { // Macro implementation is delegated to another macro to have a // single top-level macro to attach documentation to. _memoffset__offset_of_impl!($parent, $field) }; } #[cfg(tuple_ty)] #[cfg(not(stable_offset_of))] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_tuple_impl { ($parent:ty, $field:tt) => {{ // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). _memoffset__let_base_ptr!(base_ptr, $parent); // Get field pointer. let field_ptr = raw_field_tuple!(base_ptr, $parent, $field); // Compute offset. _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } #[cfg(tuple_ty)] #[cfg(stable_offset_of)] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_tuple_impl { ($parent:ty, $field:tt) => {{ $crate::__priv::mem::offset_of!($parent, $field) }}; } /// Calculates the offset of the specified field from the start of the tuple. /// /// ## Examples /// ``` /// use memoffset::offset_of_tuple; /// /// assert!(offset_of_tuple!((u8, u32), 1) >= 0, "Tuples do not have a defined layout"); /// ``` #[cfg(tuple_ty)] #[macro_export(local_inner_macros)] macro_rules! offset_of_tuple { ($parent:ty, $field:tt) => {{ // Macro implementation is delegated to another macro to have a // single top-level macro to attach documentation to. _memoffset__offset_of_tuple_impl!($parent, $field) }}; } #[cfg(not(stable_offset_of))] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_union_impl { ($parent:path, $field:tt) => {{ // Get a base pointer (non-dangling if rustc supports `MaybeUninit`). _memoffset__let_base_ptr!(base_ptr, $parent); // Get field pointer. let field_ptr = raw_field_union!(base_ptr, $parent, $field); // Compute offset. _memoffset_offset_from_unsafe!(field_ptr, base_ptr) }}; } #[cfg(stable_offset_of)] #[macro_export(local_inner_macros)] #[doc(hidden)] macro_rules! _memoffset__offset_of_union_impl { ($parent:path, $field:tt) => {{ $crate::__priv::mem::offset_of!($parent, $field) }}; } /// Calculates the offset of the specified union member from the start of the union. /// /// ## Examples /// ``` /// use memoffset::offset_of_union; /// /// #[repr(C, packed)] /// union Foo { /// foo32: i32, /// foo64: i64, /// } /// /// assert!(offset_of_union!(Foo, foo64) == 0); /// ``` /// /// ## Note /// Due to `macro_rules!` limitations, this macro will accept structs with a single field as well as unions. /// This is not a stable guarantee, and future versions of this crate might fail /// on any use of this macro with a struct, without a semver bump. #[macro_export(local_inner_macros)] macro_rules! offset_of_union { ($parent:path, $field:tt) => {{ // Macro implementation is delegated to another macro to have a // single top-level macro to attach documentation to. _memoffset__offset_of_union_impl!($parent, $field) }}; } #[cfg(test)] mod tests { #![cfg_attr(allow_clippy, allow(clippy::identity_op))] // For `... + 0` constructs below. #[test] fn offset_simple() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(offset_of!(Foo, a), 0); assert_eq!(offset_of!(Foo, b), 4); assert_eq!(offset_of!(Foo, c), 8); } #[test] fn offset_simple_packed() { #[repr(C, packed)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(offset_of!(Foo, a), 0); assert_eq!(offset_of!(Foo, b), 4); assert_eq!(offset_of!(Foo, c), 6); } #[test] fn tuple_struct() { #[repr(C)] struct Tup(i32, i32); assert_eq!(offset_of!(Tup, 0), 0); assert_eq!(offset_of!(Tup, 1), 4); } #[test] fn offset_union() { // Since we're specifying repr(C), all fields are supposed to be at offset 0 #[repr(C)] union Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(offset_of_union!(Foo, a), 0); assert_eq!(offset_of_union!(Foo, b), 0); assert_eq!(offset_of_union!(Foo, c), 0); } #[test] fn path() { mod sub { #[repr(C)] pub struct Foo { pub x: u32, } } assert_eq!(offset_of!(sub::Foo, x), 0); } #[test] fn inside_generic_method() { struct Pair(T, U); fn foo(_: Pair) -> usize { offset_of!(Pair, 1) } assert_eq!(foo(Pair(0, 0)), 4); } #[cfg(tuple_ty)] #[test] fn test_tuple_offset() { let f = (0i32, 0.0f32, 0u8); let f_ptr = &f as *const _; let f1_ptr = &f.1 as *const _; assert_eq!( f1_ptr as usize - f_ptr as usize, offset_of_tuple!((i32, f32, u8), 1) ); } #[test] fn test_raw_field() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } let f: Foo = Foo { a: 0, b: [0, 0], c: 0, }; let f_ptr = &f as *const _; assert_eq!(f_ptr as usize + 0, raw_field!(f_ptr, Foo, a) as usize); assert_eq!(f_ptr as usize + 4, raw_field!(f_ptr, Foo, b) as usize); assert_eq!(f_ptr as usize + 8, raw_field!(f_ptr, Foo, c) as usize); } #[cfg(tuple_ty)] #[test] fn test_raw_field_tuple() { let t = (0u32, 0u8, false); let t_ptr = &t as *const _; let t_addr = t_ptr as usize; assert_eq!( &t.0 as *const _ as usize - t_addr, raw_field_tuple!(t_ptr, (u32, u8, bool), 0) as usize - t_addr ); assert_eq!( &t.1 as *const _ as usize - t_addr, raw_field_tuple!(t_ptr, (u32, u8, bool), 1) as usize - t_addr ); assert_eq!( &t.2 as *const _ as usize - t_addr, raw_field_tuple!(t_ptr, (u32, u8, bool), 2) as usize - t_addr ); } #[test] fn test_raw_field_union() { #[repr(C)] union Foo { a: u32, b: [u8; 2], c: i64, } let f = Foo { a: 0 }; let f_ptr = &f as *const _; assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, a) as usize); assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, b) as usize); assert_eq!(f_ptr as usize + 0, raw_field_union!(f_ptr, Foo, c) as usize); } #[cfg(any(stable_offset_of, stable_const))] #[test] fn const_offset() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!([0; offset_of!(Foo, b)].len(), 4); } #[cfg(stable_offset_of)] #[test] fn const_offset_interior_mutable() { #[repr(C)] struct Foo { a: u32, b: core::cell::Cell, } assert_eq!([0; offset_of!(Foo, b)].len(), 4); } #[cfg(any(stable_offset_of, stable_const))] #[test] fn const_fn_offset() { const fn test_fn() -> usize { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } offset_of!(Foo, b) } assert_eq!([0; test_fn()].len(), 4); } } memoffset/src/lib.rs0000644000175000017500000000533114661133735015433 0ustar jamespagejamespage// Copyright (c) 2017 Gilad Naaman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. //! A crate used for calculating offsets of struct members and their spans. //! //! This functionality currently can not be used in compile time code such as `const` or `const fn` definitions. //! //! ## Examples //! ``` //! use memoffset::{offset_of, span_of}; //! //! #[repr(C, packed)] //! struct HelpMeIAmTrappedInAStructFactory { //! help_me_before_they_: [u8; 15], //! a: u32 //! } //! //! assert_eq!(offset_of!(HelpMeIAmTrappedInAStructFactory, a), 15); //! assert_eq!(span_of!(HelpMeIAmTrappedInAStructFactory, a), 15..19); //! assert_eq!(span_of!(HelpMeIAmTrappedInAStructFactory, help_me_before_they_ .. a), 0..15); //! ``` //! //! This functionality can be useful, for example, for checksum calculations: //! //! ```ignore //! #[repr(C, packed)] //! struct Message { //! header: MessageHeader, //! fragment_index: u32, //! fragment_count: u32, //! payload: [u8; 1024], //! checksum: u16 //! } //! //! let checksum_range = &raw[span_of!(Message, header..checksum)]; //! let checksum = crc16(checksum_range); //! ``` #![no_std] #[macro_use] #[cfg(doctests)] #[cfg(doctest)] extern crate doc_comment; #[cfg(doctests)] #[cfg(doctest)] doctest!("../README.md"); /// Hidden module for things the macros need to access. #[doc(hidden)] pub mod __priv { #[doc(hidden)] pub use core::mem; #[doc(hidden)] pub use core::ptr; /// Use type inference to obtain the size of the pointee (without actually using the pointer). #[doc(hidden)] pub fn size_of_pointee(_ptr: *const T) -> usize { mem::size_of::() } } #[macro_use] mod raw_field; #[macro_use] mod offset_of; #[macro_use] mod span_of; memoffset/src/span_of.rs0000644000175000017500000002064014661133735016312 0ustar jamespagejamespage// Copyright (c) 2017 Gilad Naaman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /// Reexport for `local_inner_macros`; see /// . #[doc(hidden)] #[macro_export] macro_rules! _memoffset__compile_error { ($($inner:tt)*) => { compile_error! { $($inner)* } } } /// Produces a range instance representing the sub-slice containing the specified member. /// /// This macro provides 2 forms of differing functionalities. /// /// The first form is identical to the appearance of the `offset_of!` macro. /// /// ```ignore /// span_of!(Struct, member) /// ``` /// /// The second form of `span_of!` returns a sub-slice which starts at one field, and ends at another. /// The general pattern of this form is: /// /// ```ignore /// // Exclusive /// span_of!(Struct, member_a .. member_b) /// // Inclusive /// span_of!(Struct, member_a ..= member_b) /// /// // Open-ended ranges /// span_of!(Struct, .. end) /// span_of!(Struct, start ..) /// ``` /// /// ### Note /// This macro uses recursion in order to resolve the range expressions, so there is a limit to /// the complexity of the expression. /// In order to raise the limit, the compiler's recursion limit should be lifted. /// /// ### Safety /// The inter-field form mentioned above assumes that the first field is positioned before the /// second. /// This is only guaranteed for `repr(C)` structs. /// Usage with `repr(Rust)` structs may yield unexpected results, like downward-going ranges, /// spans that include unexpected fields, empty spans, or spans that include *unexpected* padding bytes. /// /// ## Examples /// ``` /// use memoffset::span_of; /// /// #[repr(C)] /// struct Florp { /// a: u32 /// } /// /// #[repr(C)] /// struct Blarg { /// x: [u32; 2], /// y: [u8; 56], /// z: Florp, /// egg: [[u8; 4]; 4] /// } /// /// assert_eq!(0..84, span_of!(Blarg, ..)); /// assert_eq!(0..8, span_of!(Blarg, .. y)); /// assert_eq!(0..64, span_of!(Blarg, ..= y)); /// assert_eq!(0..8, span_of!(Blarg, x)); /// assert_eq!(8..84, span_of!(Blarg, y ..)); /// assert_eq!(0..8, span_of!(Blarg, x .. y)); /// assert_eq!(0..64, span_of!(Blarg, x ..= y)); /// ``` #[macro_export(local_inner_macros)] macro_rules! span_of { (@helper $root:ident, [] ..=) => { _memoffset__compile_error!("Expected a range, found '..='") }; (@helper $root:ident, [] ..) => { _memoffset__compile_error!("Expected a range, found '..'") }; // No explicit begin for range. (@helper $root:ident, $parent:path, [] ..) => {{ ($root as usize, $root as usize + $crate::__priv::size_of_pointee($root)) }}; (@helper $root:ident, $parent:path, [] ..= $end:tt) => {{ let end = raw_field!($root, $parent, $end); ($root as usize, end as usize + $crate::__priv::size_of_pointee(end)) }}; (@helper $root:ident, $parent:path, [] .. $end:tt) => {{ ($root as usize, raw_field!($root, $parent, $end) as usize) }}; // Explicit begin and end for range. (@helper $root:ident, $parent:path, # $begin:tt [] ..= $end:tt) => {{ let begin = raw_field!($root, $parent, $begin); let end = raw_field!($root, $parent, $end); (begin as usize, end as usize + $crate::__priv::size_of_pointee(end)) }}; (@helper $root:ident, $parent:path, # $begin:tt [] .. $end:tt) => {{ (raw_field!($root, $parent, $begin) as usize, raw_field!($root, $parent, $end) as usize) }}; // No explicit end for range. (@helper $root:ident, $parent:path, # $begin:tt [] ..) => {{ (raw_field!($root, $parent, $begin) as usize, $root as usize + $crate::__priv::size_of_pointee($root)) }}; (@helper $root:ident, $parent:path, # $begin:tt [] ..=) => {{ _memoffset__compile_error!( "Found inclusive range to the end of a struct. Did you mean '..' instead of '..='?") }}; // Just one field. (@helper $root:ident, $parent:path, # $field:tt []) => {{ let field = raw_field!($root, $parent, $field); (field as usize, field as usize + $crate::__priv::size_of_pointee(field)) }}; // Parsing. (@helper $root:ident, $parent:path, $(# $begin:tt)+ [] $tt:tt $($rest:tt)*) => {{ span_of!(@helper $root, $parent, $(#$begin)* #$tt [] $($rest)*) }}; (@helper $root:ident, $parent:path, [] $tt:tt $($rest:tt)*) => {{ span_of!(@helper $root, $parent, #$tt [] $($rest)*) }}; // Entry point. ($sty:path, $($exp:tt)+) => ({ // Get a base pointer. _memoffset__let_base_ptr!(root, $sty); let base = root as usize; let (begin, end) = span_of!(@helper root, $sty, [] $($exp)*); begin-base..end-base }); } #[cfg(test)] mod tests { use core::mem; #[test] fn span_simple() { #[repr(C)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(span_of!(Foo, a), 0..4); assert_eq!(span_of!(Foo, b), 4..6); assert_eq!(span_of!(Foo, c), 8..8 + 8); } #[test] #[cfg_attr(miri, ignore)] // this creates unaligned references fn span_simple_packed() { #[repr(C, packed)] struct Foo { a: u32, b: [u8; 2], c: i64, } assert_eq!(span_of!(Foo, a), 0..4); assert_eq!(span_of!(Foo, b), 4..6); assert_eq!(span_of!(Foo, c), 6..6 + 8); } #[test] fn span_forms() { #[repr(C)] struct Florp { a: u32, } #[repr(C)] struct Blarg { x: u64, y: [u8; 56], z: Florp, egg: [[u8; 4]; 5], } // Love me some brute force assert_eq!(0..8, span_of!(Blarg, x)); assert_eq!(64..68, span_of!(Blarg, z)); assert_eq!(68..mem::size_of::(), span_of!(Blarg, egg)); assert_eq!(8..64, span_of!(Blarg, y..z)); assert_eq!(0..64, span_of!(Blarg, x..=y)); } #[test] fn ig_test() { #[repr(C)] struct Member { foo: u32, } #[repr(C)] struct Test { x: u64, y: [u8; 56], z: Member, egg: [[u8; 4]; 4], } assert_eq!(span_of!(Test, ..x), 0..0); assert_eq!(span_of!(Test, ..=x), 0..8); assert_eq!(span_of!(Test, ..y), 0..8); assert_eq!(span_of!(Test, ..=y), 0..64); assert_eq!(span_of!(Test, ..z), 0..64); assert_eq!(span_of!(Test, ..=z), 0..68); assert_eq!(span_of!(Test, ..egg), 0..68); assert_eq!(span_of!(Test, ..=egg), 0..84); assert_eq!(span_of!(Test, ..), 0..mem::size_of::()); assert_eq!( span_of!(Test, x..), offset_of!(Test, x)..mem::size_of::() ); assert_eq!( span_of!(Test, y..), offset_of!(Test, y)..mem::size_of::() ); assert_eq!( span_of!(Test, z..), offset_of!(Test, z)..mem::size_of::() ); assert_eq!( span_of!(Test, egg..), offset_of!(Test, egg)..mem::size_of::() ); assert_eq!( span_of!(Test, x..y), offset_of!(Test, x)..offset_of!(Test, y) ); assert_eq!( span_of!(Test, x..=y), offset_of!(Test, x)..offset_of!(Test, y) + mem::size_of::<[u8; 56]>() ); } } memoffset/src/raw_field.rs0000644000175000017500000001702314661133735016622 0ustar jamespagejamespage// Copyright (c) 2020 Gilad Naaman, Ralf Jung // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. /// `addr_of!`, or just ref-then-cast when that is not available. #[cfg(raw_ref_macros)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__addr_of { ($path:expr) => {{ $crate::__priv::ptr::addr_of!($path) }}; } #[cfg(not(raw_ref_macros))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__addr_of { ($path:expr) => {{ // This is UB because we create an intermediate reference to uninitialized memory. // Nothing we can do about that without `addr_of!` though. &$path as *const _ }}; } /// Deref-coercion protection macro. /// /// Prevents compilation if the specified field name is not a part of the /// struct definition. /// /// ```compile_fail /// use memoffset::_memoffset__field_check; /// /// struct Foo { /// foo: i32, /// } /// /// type BoxedFoo = Box; /// /// _memoffset__field_check!(BoxedFoo, foo); /// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. #[allow(clippy::unneeded_field_pattern)] let $type { $field: _, .. }; }; } #[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. let $type { $field: _, .. }; }; } /// Deref-coercion protection macro. /// /// Prevents compilation if the specified type is not a tuple. /// /// ```compile_fail /// use memoffset::_memoffset__field_check_tuple; /// /// _memoffset__field_check_tuple!(i32, 0); /// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_tuple { ($type:ty, $field:tt) => { // Make sure the type argument is a tuple #[allow(clippy::unneeded_wildcard_pattern)] let (_, ..): $type; }; } #[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_tuple { ($type:ty, $field:tt) => { // Make sure the type argument is a tuple let (_, ..): $type; }; } /// Deref-coercion protection macro for unions. /// Unfortunately accepts single-field structs as well, which is not ideal, /// but ultimately pretty harmless. /// /// ```compile_fail /// use memoffset::_memoffset__field_check_union; /// /// union Foo { /// variant_a: i32, /// } /// /// type BoxedFoo = Box; /// /// _memoffset__field_check_union!(BoxedFoo, variant_a); /// ``` #[cfg(allow_clippy)] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_union { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. #[allow(clippy::unneeded_wildcard_pattern)] // rustc1.19 requires unsafe here for the pattern; not needed in newer versions #[allow(unused_unsafe)] unsafe { let $type { $field: _ }; } }; } #[cfg(not(allow_clippy))] #[macro_export] #[doc(hidden)] macro_rules! _memoffset__field_check_union { ($type:path, $field:tt) => { // Make sure the field actually exists. This line ensures that a // compile-time error is generated if $field is accessed through a // Deref impl. // rustc1.19 requires unsafe here for the pattern; not needed in newer versions #[allow(unused_unsafe)] unsafe { let $type { $field: _ }; } }; } /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent type. /// /// The `base` pointer *must not* be dangling, but it *may* point to /// uninitialized memory. #[macro_export(local_inner_macros)] macro_rules! raw_field { ($base:expr, $parent:path, $field:tt) => {{ _memoffset__field_check!($parent, $field); let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent tuple type. /// /// The `base` pointer *must not* be dangling, but it *may* point to /// uninitialized memory. #[cfg(tuple_ty)] #[macro_export(local_inner_macros)] macro_rules! raw_field_tuple { ($base:expr, $parent:ty, $field:tt) => {{ _memoffset__field_check_tuple!($parent, $field); let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } /// Computes a const raw pointer to the given field of the given base pointer /// to the given parent tuple type. /// /// The `base` pointer *must not* be dangling, but it *may* point to /// uninitialized memory. /// /// ## Note /// This macro is the same as `raw_field`, except for a different Deref-coercion check that /// supports unions. /// Due to `macro_rules!` limitations, this check will accept structs with a single field as well as unions. /// This is not a stable guarantee, and future versions of this crate might fail /// on any use of this macro with a struct, without a semver bump. #[macro_export(local_inner_macros)] macro_rules! raw_field_union { ($base:expr, $parent:path, $field:tt) => {{ _memoffset__field_check_union!($parent, $field); let base = $base; // evaluate $base outside the `unsafe` block // Get the field address. // Crucially, we know that this will not trigger a deref coercion because // of the field check we did above. #[allow(unused_unsafe)] // for when the macro is used in an unsafe block unsafe { _memoffset__addr_of!((*(base as *const $parent)).$field) } }}; } memoffset/CHANGELOG.md0000644000175000017500000000134614661133735015343 0ustar jamespagejamespage# Changelog ## Unreleased ## v0.9.1 (26/03/2024) ### Added - Added changelog ### Changed - Clarify documentation about macro indirection - Turn the crate into a thin stdlib wrapper on rustc>=1.77 - Turn `unstable_offset_of` and `unstable_const` into NOPs; they are not needed any more on recent nightlies ## v0.9.0 (18/05/2023) ### Added - Cargo feature `unstable_offset_of` which turns the crate into a stdlib polyfill ## v0.8.0 (15/12/2022) ### Changed - Constant-evaluation is automatically enabled ## v0.7.1 (17/10/2022) ### Changed - Version in `README.md` ## v0.7.0 (17/10/2022) ### Added - `offset_of_union!` ## v0.6.5 (03/12/2021) ### Removed - [nightly] `#![feature(const_raw_ptr_deref, const_maybe_uninit_as_ptr)]` memoffset/LICENSE0000644000175000017500000000203714661133735014535 0ustar jamespagejamespageCopyright (c) 2017 Gilad Naaman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.memoffset/.cargo-checksum.json0000664000175000017500000000146414661133735017401 0ustar jamespagejamespage{"files":{"CHANGELOG.md":"badae1c4dc22e994d6e29d892bd925083d948d941f11ee7b767a535bd4ff5f9a","Cargo.toml":"772e523da630871e710cc229f36282205713bba853d4d3f78e5a5d099bb3a814","LICENSE":"3234ac55816264ee7b6c7ee27efd61cf0a1fe775806870e3d9b4c41ea73c5cb1","README.md":"c04d939e7dc8bc21010cae6d22bf7f16e019960c0adbae4f894f47c24c54e109","build.rs":"0ddaae191a4091fe1318177d12244ff0dbabc17a18f25a54059f4badc9a20876","src/lib.rs":"c4034868e7f7b5c03848a735589081bc763f62f6fe8eb4175873c97db1f855a3","src/offset_of.rs":"fdd36253329210293cc867d7fb0a5bca2ec7f12befa9a30c88b85932ead4cd34","src/raw_field.rs":"95a17510c77b11ecb68b170f724ca1c71517ff1476024bcba48c70ca712c21cc","src/span_of.rs":"268505154f4ae3df1a961da047fef50200339f4d75d8e4d6b9340ee14028943a"},"package":"488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"}once_cell/0000775000175000017500000000000014661133735013466 5ustar jamespagejamespageonce_cell/README.md0000644000175000017500000000421714661133735014747 0ustar jamespagejamespage

once_cell

[![Build Status](https://github.com/matklad/once_cell/actions/workflows/ci.yaml/badge.svg)](https://github.com/matklad/once_cell/actions) [![Crates.io](https://img.shields.io/crates/v/once_cell.svg)](https://crates.io/crates/once_cell) [![API reference](https://docs.rs/once_cell/badge.svg)](https://docs.rs/once_cell/) # Overview `once_cell` provides two new cell-like types, `unsync::OnceCell` and `sync::OnceCell`. `OnceCell` might store arbitrary non-`Copy` types, can be assigned to at most once and provide direct access to the stored contents. In a nutshell, API looks *roughly* like this: ```rust impl OnceCell { fn new() -> OnceCell { ... } fn set(&self, value: T) -> Result<(), T> { ... } fn get(&self) -> Option<&T> { ... } } ``` Note that, like with `RefCell` and `Mutex`, the `set` method requires only a shared reference. Because of the single assignment restriction `get` can return an `&T` instead of `Ref` or `MutexGuard`. `once_cell` also has a `Lazy` type, build on top of `OnceCell` which provides the same API as the `lazy_static!` macro, but without using any macros: ```rust use std::{sync::Mutex, collections::HashMap}; use once_cell::sync::Lazy; static GLOBAL_DATA: Lazy>> = Lazy::new(|| { let mut m = HashMap::new(); m.insert(13, "Spica".to_string()); m.insert(74, "Hoyten".to_string()); Mutex::new(m) }); fn main() { println!("{:?}", GLOBAL_DATA.lock().unwrap()); } ``` More patterns and use-cases are in the [docs](https://docs.rs/once_cell/)! # Related crates * [double-checked-cell](https://github.com/niklasf/double-checked-cell) * [lazy-init](https://crates.io/crates/lazy-init) * [lazycell](https://crates.io/crates/lazycell) * [mitochondria](https://crates.io/crates/mitochondria) * [lazy_static](https://crates.io/crates/lazy_static) * [async_once_cell](https://crates.io/crates/async_once_cell) * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring your own mutex) Parts of `once_cell` API are included into `std` [as of Rust 1.70.0](https://github.com/rust-lang/rust/pull/105587). once_cell/examples/0000775000175000017500000000000014661133735015304 5ustar jamespagejamespageonce_cell/examples/regex.rs0000644000175000017500000000317714661133735016772 0ustar jamespagejamespageuse std::{str::FromStr, time::Instant}; use regex::Regex; macro_rules! regex { ($re:literal $(,)?) => {{ static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); RE.get_or_init(|| regex::Regex::new($re).unwrap()) }}; } fn slow() { let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##; let mut total = 0; for _ in 0..1000 { let re = Regex::new( r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##, ) .unwrap(); let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap(); total += size; } println!("{}", total); } fn fast() { let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##; let mut total = 0; for _ in 0..1000 { let re: &Regex = regex!( r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##, ); let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap(); total += size; } println!("{}", total); } fn main() { let t = Instant::now(); slow(); println!("slow: {:?}", t.elapsed()); let t = Instant::now(); fast(); println!("fast: {:?}", t.elapsed()); } once_cell/examples/test_synchronization.rs0000644000175000017500000000231114661133735022145 0ustar jamespagejamespage//! Test if the OnceCell properly synchronizes. //! Needs to be run in release mode. //! //! We create a `Vec` with `N_ROUNDS` of `OnceCell`s. All threads will walk the `Vec`, and race to //! be the first one to initialize a cell. //! Every thread adds the results of the cells it sees to an accumulator, which is compared at the //! end. //! All threads should end up with the same result. use once_cell::sync::OnceCell; const N_THREADS: usize = 32; const N_ROUNDS: usize = 1_000_000; static CELLS: OnceCell>> = OnceCell::new(); static RESULT: OnceCell = OnceCell::new(); fn main() { let start = std::time::Instant::now(); CELLS.get_or_init(|| vec![OnceCell::new(); N_ROUNDS]); let threads = (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::>(); for thread in threads { thread.join().unwrap(); } println!("{:?}", start.elapsed()); println!("No races detected"); } fn thread_main(i: usize) { let cells = CELLS.get().unwrap(); let mut accum = 0; for cell in cells.iter() { let &value = cell.get_or_init(|| i); accum += value; } assert_eq!(RESULT.get_or_init(|| accum), &accum); } once_cell/examples/bench_acquire.rs0000644000175000017500000000250014661133735020435 0ustar jamespagejamespage//! Benchmark the overhead that the synchronization of `OnceCell::get` causes. //! We do some other operations that write to memory to get an imprecise but somewhat realistic //! measurement. use once_cell::sync::OnceCell; use std::sync::atomic::{AtomicUsize, Ordering}; const N_THREADS: usize = 16; const N_ROUNDS: usize = 1_000_000; static CELL: OnceCell = OnceCell::new(); static OTHER: AtomicUsize = AtomicUsize::new(0); fn main() { let start = std::time::Instant::now(); let threads = (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::>(); for thread in threads { thread.join().unwrap(); } println!("{:?}", start.elapsed()); println!("{:?}", OTHER.load(Ordering::Relaxed)); } #[inline(never)] fn thread_main(i: usize) { // The operations we do here don't really matter, as long as we do multiple writes, and // everything is messy enough to prevent the compiler from optimizing the loop away. let mut data = [i; 128]; let mut accum = 0usize; for _ in 0..N_ROUNDS { let _value = CELL.get_or_init(|| i + 1); let k = OTHER.fetch_add(data[accum & 0x7F] as usize, Ordering::Relaxed); for j in data.iter_mut() { *j = (*j).wrapping_add(accum); accum = accum.wrapping_add(k); } } } once_cell/examples/bench.rs0000644000175000017500000000147714661133735016740 0ustar jamespagejamespageuse std::mem::size_of; use once_cell::sync::OnceCell; const N_THREADS: usize = 32; const N_ROUNDS: usize = 100_000_000; static CELL: OnceCell = OnceCell::new(); fn main() { let start = std::time::Instant::now(); let threads = (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::>(); for thread in threads { thread.join().unwrap(); } println!("{:?}", start.elapsed()); println!("size_of::>() = {:?}", size_of::>()); println!("size_of::>() = {:?}", size_of::>()); println!("size_of::>() = {:?}", size_of::>()); } fn thread_main(i: usize) { for _ in 0..N_ROUNDS { let &value = CELL.get_or_init(|| i); assert!(value < N_THREADS) } } once_cell/examples/reentrant_init_deadlocks.rs0000644000175000017500000000053714661133735022713 0ustar jamespagejamespagefn main() { let cell = once_cell::sync::OnceCell::::new(); cell.get_or_init(|| { cell.get_or_init(|| 1); 2 }); } /// Dummy test to make it seem hang when compiled as `--test` /// See https://github.com/matklad/once_cell/issues/79 #[test] fn dummy_test() { std::thread::sleep(std::time::Duration::from_secs(4)); } once_cell/examples/lazy_static.rs0000644000175000017500000000201414661133735020173 0ustar jamespagejamespageextern crate once_cell; use once_cell::sync::{Lazy, OnceCell}; use std::collections::HashMap; static HASHMAP: Lazy> = Lazy::new(|| { let mut m = HashMap::new(); m.insert(0, "foo"); m.insert(1, "bar"); m.insert(2, "baz"); m }); // Same, but completely without macros fn hashmap() -> &'static HashMap { static INSTANCE: OnceCell> = OnceCell::new(); INSTANCE.get_or_init(|| { let mut m = HashMap::new(); m.insert(0, "foo"); m.insert(1, "bar"); m.insert(2, "baz"); m }) } fn main() { // First access to `HASHMAP` initializes it println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap()); // Any further access to `HASHMAP` just returns the computed value println!("The entry for `1` is \"{}\".", HASHMAP.get(&1).unwrap()); // The same works for function-style: assert_eq!(hashmap().get(&0), Some(&"foo")); assert_eq!(hashmap().get(&1), Some(&"bar")); } once_cell/LICENSE-APACHE0000644000175000017500000002513714661133735015420 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. once_cell/Cargo.toml0000644000175000017500000000401114661133735015410 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.60" name = "once_cell" version = "1.19.0" authors = ["Aleksey Kladov "] exclude = [ "*.png", "*.svg", "/Cargo.lock.msrv", "rustfmt.toml", ] description = "Single assignment cells and lazy values." documentation = "https://docs.rs/once_cell" readme = "README.md" keywords = [ "lazy", "static", ] categories = [ "rust-patterns", "memory-management", ] license = "MIT OR Apache-2.0" repository = "https://github.com/matklad/once_cell" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--generate-link-to-definition"] [[example]] name = "bench" required-features = ["std"] [[example]] name = "bench_acquire" required-features = ["std"] [[example]] name = "lazy_static" required-features = ["std"] [[example]] name = "reentrant_init_deadlocks" required-features = ["std"] [[example]] name = "regex" required-features = ["std"] [[example]] name = "test_synchronization" required-features = ["std"] [dependencies.critical-section] version = "1" optional = true [dependencies.parking_lot_core] version = "0.9.3" optional = true default_features = false [dependencies.portable-atomic] version = "1" optional = true [dev-dependencies.critical-section] version = "1.1.1" features = ["std"] [dev-dependencies.regex] version = "1.2.0" [features] alloc = ["race"] atomic-polyfill = ["critical-section"] critical-section = [ "dep:critical-section", "portable-atomic", ] default = ["std"] parking_lot = ["dep:parking_lot_core"] race = [] std = ["alloc"] unstable = [] once_cell/tests/0000775000175000017500000000000014661133735014630 5ustar jamespagejamespageonce_cell/tests/it/0000775000175000017500000000000014661133735015244 5ustar jamespagejamespageonce_cell/tests/it/sync_lazy.rs0000644000175000017500000000714514661133735017632 0ustar jamespagejamespageuse std::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering::SeqCst}, thread::scope, }; use once_cell::sync::{Lazy, OnceCell}; #[test] fn lazy_new() { let called = AtomicUsize::new(0); let x = Lazy::new(|| { called.fetch_add(1, SeqCst); 92 }); assert_eq!(called.load(SeqCst), 0); scope(|s| { s.spawn(|| { let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.load(SeqCst), 1); }); }); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.load(SeqCst), 1); } #[test] fn lazy_deref_mut() { let called = AtomicUsize::new(0); let mut x = Lazy::new(|| { called.fetch_add(1, SeqCst); 92 }); assert_eq!(called.load(SeqCst), 0); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.load(SeqCst), 1); *x /= 2; assert_eq!(*x, 46); assert_eq!(called.load(SeqCst), 1); } #[test] fn lazy_force_mut() { let called = Cell::new(0); let mut x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let v = Lazy::force_mut(&mut x); assert_eq!(called.get(), 1); *v /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_get_mut() { let called = Cell::new(0); let mut x: Lazy = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); assert_eq!(*x, 92); let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap(); assert_eq!(called.get(), 1); *mut_ref /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_default() { static CALLED: AtomicUsize = AtomicUsize::new(0); struct Foo(u8); impl Default for Foo { fn default() -> Self { CALLED.fetch_add(1, SeqCst); Foo(42) } } let lazy: Lazy> = <_>::default(); assert_eq!(CALLED.load(SeqCst), 0); assert_eq!(lazy.lock().unwrap().0, 42); assert_eq!(CALLED.load(SeqCst), 1); lazy.lock().unwrap().0 = 21; assert_eq!(lazy.lock().unwrap().0, 21); assert_eq!(CALLED.load(SeqCst), 1); } #[test] fn static_lazy() { static XS: Lazy> = Lazy::new(|| { let mut xs = Vec::new(); xs.push(1); xs.push(2); xs.push(3); xs }); scope(|s| { s.spawn(|| { assert_eq!(&*XS, &vec![1, 2, 3]); }); }); assert_eq!(&*XS, &vec![1, 2, 3]); } #[test] fn static_lazy_via_fn() { fn xs() -> &'static Vec { static XS: OnceCell> = OnceCell::new(); XS.get_or_init(|| { let mut xs = Vec::new(); xs.push(1); xs.push(2); xs.push(3); xs }) } assert_eq!(xs(), &vec![1, 2, 3]); } #[test] fn lazy_into_value() { let l: Lazy = Lazy::new(|| panic!()); assert!(matches!(Lazy::into_value(l), Err(_))); let l = Lazy::new(|| -> i32 { 92 }); Lazy::force(&l); assert!(matches!(Lazy::into_value(l), Ok(92))); } #[test] fn lazy_poisoning() { let x: Lazy = Lazy::new(|| panic!("kaboom")); for _ in 0..2 { let res = std::panic::catch_unwind(|| x.len()); assert!(res.is_err()); } } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let lazy: Lazy<&String, _>; { let s = String::new(); lazy = Lazy::new(|| &s); _ = *lazy; } } #[test] fn lazy_is_sync_send() { fn assert_traits() {} assert_traits::>(); } once_cell/tests/it/unsync_lazy.rs0000644000175000017500000000531514661133735020172 0ustar jamespagejamespageuse core::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; use once_cell::unsync::Lazy; #[test] fn lazy_new() { let called = Cell::new(0); let x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.get(), 1); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.get(), 1); } #[test] fn lazy_deref_mut() { let called = Cell::new(0); let mut x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let y = *x - 30; assert_eq!(y, 62); assert_eq!(called.get(), 1); *x /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_force_mut() { let called = Cell::new(0); let mut x = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); let v = Lazy::force_mut(&mut x); assert_eq!(called.get(), 1); *v /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_get_mut() { let called = Cell::new(0); let mut x: Lazy = Lazy::new(|| { called.set(called.get() + 1); 92 }); assert_eq!(called.get(), 0); assert_eq!(*x, 92); let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap(); assert_eq!(called.get(), 1); *mut_ref /= 2; assert_eq!(*x, 46); assert_eq!(called.get(), 1); } #[test] fn lazy_default() { static CALLED: AtomicUsize = AtomicUsize::new(0); struct Foo(u8); impl Default for Foo { fn default() -> Self { CALLED.fetch_add(1, SeqCst); Foo(42) } } let lazy: Lazy> = <_>::default(); assert_eq!(CALLED.load(SeqCst), 0); assert_eq!(lazy.lock().unwrap().0, 42); assert_eq!(CALLED.load(SeqCst), 1); lazy.lock().unwrap().0 = 21; assert_eq!(lazy.lock().unwrap().0, 21); assert_eq!(CALLED.load(SeqCst), 1); } #[test] fn lazy_into_value() { let l: Lazy = Lazy::new(|| panic!()); assert!(matches!(Lazy::into_value(l), Err(_))); let l = Lazy::new(|| -> i32 { 92 }); Lazy::force(&l); assert!(matches!(Lazy::into_value(l), Ok(92))); } #[test] #[cfg(feature = "std")] fn lazy_poisoning() { let x: Lazy = Lazy::new(|| panic!("kaboom")); for _ in 0..2 { let res = std::panic::catch_unwind(|| x.len()); assert!(res.is_err()); } } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let lazy: Lazy<&String, _>; { let s = String::new(); lazy = Lazy::new(|| &s); _ = *lazy; } } once_cell/tests/it/unsync_once_cell.rs0000644000175000017500000000741514661133735021141 0ustar jamespagejamespageuse core::{ cell::Cell, sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; use once_cell::unsync::OnceCell; #[test] fn once_cell() { let c = OnceCell::new(); assert!(c.get().is_none()); c.get_or_init(|| 92); assert_eq!(c.get(), Some(&92)); c.get_or_init(|| panic!("Kabom!")); assert_eq!(c.get(), Some(&92)); } #[test] fn once_cell_with_value() { const CELL: OnceCell = OnceCell::with_value(12); let cell = CELL; assert_eq!(cell.get(), Some(&12)); } #[test] fn once_cell_get_mut() { let mut c = OnceCell::new(); assert!(c.get_mut().is_none()); c.set(90).unwrap(); *c.get_mut().unwrap() += 2; assert_eq!(c.get_mut(), Some(&mut 92)); } #[test] fn once_cell_drop() { static DROP_CNT: AtomicUsize = AtomicUsize::new(0); struct Dropper; impl Drop for Dropper { fn drop(&mut self) { DROP_CNT.fetch_add(1, SeqCst); } } let x = OnceCell::new(); x.get_or_init(|| Dropper); assert_eq!(DROP_CNT.load(SeqCst), 0); drop(x); assert_eq!(DROP_CNT.load(SeqCst), 1); } #[test] fn once_cell_drop_empty() { let x = OnceCell::::new(); drop(x); } #[test] fn clone() { let s = OnceCell::new(); let c = s.clone(); assert!(c.get().is_none()); s.set("hello".to_string()).unwrap(); let c = s.clone(); assert_eq!(c.get().map(String::as_str), Some("hello")); } #[test] fn get_or_try_init() { let cell: OnceCell = OnceCell::new(); assert!(cell.get().is_none()); let res = std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); assert!(res.is_err()); assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); assert_eq!(cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), Ok(&"hello".to_string())); assert_eq!(cell.get(), Some(&"hello".to_string())); } #[test] fn from_impl() { assert_eq!(OnceCell::from("value").get(), Some(&"value")); assert_ne!(OnceCell::from("foo").get(), Some(&"bar")); } #[test] fn partialeq_impl() { assert!(OnceCell::from("value") == OnceCell::from("value")); assert!(OnceCell::from("foo") != OnceCell::from("bar")); assert!(OnceCell::::new() == OnceCell::new()); assert!(OnceCell::::new() != OnceCell::from("value".to_owned())); } #[test] fn into_inner() { let cell: OnceCell = OnceCell::new(); assert_eq!(cell.into_inner(), None); let cell = OnceCell::new(); cell.set("hello".to_string()).unwrap(); assert_eq!(cell.into_inner(), Some("hello".to_string())); } #[test] fn debug_impl() { let cell = OnceCell::new(); assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)"); cell.set(vec!["hello", "world"]).unwrap(); assert_eq!( format!("{:#?}", cell), r#"OnceCell( [ "hello", "world", ], )"# ); } #[test] #[should_panic(expected = "reentrant init")] fn reentrant_init() { let x: OnceCell> = OnceCell::new(); let dangling_ref: Cell> = Cell::new(None); x.get_or_init(|| { let r = x.get_or_init(|| Box::new(92)); dangling_ref.set(Some(r)); Box::new(62) }); eprintln!("use after free: {:?}", dangling_ref.get().unwrap()); } #[test] fn aliasing_in_get() { let x = OnceCell::new(); x.set(42).unwrap(); let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option` --+ let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option` | println!("{}", at_x); // <------- up until here ---------------------------+ } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let cell = OnceCell::new(); { let s = String::new(); cell.set(&s).unwrap(); } } once_cell/tests/it/main.rs0000644000175000017500000000045114661133735016534 0ustar jamespagejamespagemod unsync_once_cell; #[cfg(any(feature = "std", feature = "critical-section"))] mod sync_once_cell; mod unsync_lazy; #[cfg(any(feature = "std", feature = "critical-section"))] mod sync_lazy; #[cfg(feature = "race")] mod race; #[cfg(all(feature = "race", feature = "alloc"))] mod race_once_box; once_cell/tests/it/race.rs0000644000175000017500000000575714661133735016540 0ustar jamespagejamespage#[cfg(feature = "std")] use std::sync::Barrier; use std::{ num::NonZeroUsize, sync::atomic::{AtomicUsize, Ordering::SeqCst}, thread::scope, }; use once_cell::race::{OnceBool, OnceNonZeroUsize}; #[test] fn once_non_zero_usize_smoke_test() { let cnt = AtomicUsize::new(0); let cell = OnceNonZeroUsize::new(); let val = NonZeroUsize::new(92).unwrap(); scope(|s| { s.spawn(|| { assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); val }), val ); assert_eq!(cnt.load(SeqCst), 1); assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); val }), val ); assert_eq!(cnt.load(SeqCst), 1); }); }); assert_eq!(cell.get(), Some(val)); assert_eq!(cnt.load(SeqCst), 1); } #[test] fn once_non_zero_usize_set() { let val1 = NonZeroUsize::new(92).unwrap(); let val2 = NonZeroUsize::new(62).unwrap(); let cell = OnceNonZeroUsize::new(); assert!(cell.set(val1).is_ok()); assert_eq!(cell.get(), Some(val1)); assert!(cell.set(val2).is_err()); assert_eq!(cell.get(), Some(val1)); } #[cfg(feature = "std")] #[test] fn once_non_zero_usize_first_wins() { let val1 = NonZeroUsize::new(92).unwrap(); let val2 = NonZeroUsize::new(62).unwrap(); let cell = OnceNonZeroUsize::new(); let b1 = Barrier::new(2); let b2 = Barrier::new(2); let b3 = Barrier::new(2); scope(|s| { s.spawn(|| { let r1 = cell.get_or_init(|| { b1.wait(); b2.wait(); val1 }); assert_eq!(r1, val1); b3.wait(); }); b1.wait(); s.spawn(|| { let r2 = cell.get_or_init(|| { b2.wait(); b3.wait(); val2 }); assert_eq!(r2, val1); }); }); assert_eq!(cell.get(), Some(val1)); } #[test] fn once_bool_smoke_test() { let cnt = AtomicUsize::new(0); let cell = OnceBool::new(); scope(|s| { s.spawn(|| { assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); false }), false ); assert_eq!(cnt.load(SeqCst), 1); assert_eq!( cell.get_or_init(|| { cnt.fetch_add(1, SeqCst); false }), false ); assert_eq!(cnt.load(SeqCst), 1); }); }); assert_eq!(cell.get(), Some(false)); assert_eq!(cnt.load(SeqCst), 1); } #[test] fn once_bool_set() { let cell = OnceBool::new(); assert!(cell.set(false).is_ok()); assert_eq!(cell.get(), Some(false)); assert!(cell.set(true).is_err()); assert_eq!(cell.get(), Some(false)); } once_cell/tests/it/sync_once_cell.rs0000644000175000017500000001675714661133735020607 0ustar jamespagejamespageuse std::{ sync::atomic::{AtomicUsize, Ordering::SeqCst}, thread::scope, }; #[cfg(feature = "std")] use std::sync::Barrier; #[cfg(not(feature = "std"))] use core::cell::Cell; use once_cell::sync::{Lazy, OnceCell}; #[test] fn once_cell() { let c = OnceCell::new(); assert!(c.get().is_none()); scope(|s| { s.spawn(|| { c.get_or_init(|| 92); assert_eq!(c.get(), Some(&92)); }); }); c.get_or_init(|| panic!("Kabom!")); assert_eq!(c.get(), Some(&92)); } #[test] fn once_cell_with_value() { static CELL: OnceCell = OnceCell::with_value(12); assert_eq!(CELL.get(), Some(&12)); } #[test] fn once_cell_get_mut() { let mut c = OnceCell::new(); assert!(c.get_mut().is_none()); c.set(90).unwrap(); *c.get_mut().unwrap() += 2; assert_eq!(c.get_mut(), Some(&mut 92)); } #[test] fn once_cell_get_unchecked() { let c = OnceCell::new(); c.set(92).unwrap(); unsafe { assert_eq!(c.get_unchecked(), &92); } } #[test] fn once_cell_drop() { static DROP_CNT: AtomicUsize = AtomicUsize::new(0); struct Dropper; impl Drop for Dropper { fn drop(&mut self) { DROP_CNT.fetch_add(1, SeqCst); } } let x = OnceCell::new(); scope(|s| { s.spawn(|| { x.get_or_init(|| Dropper); assert_eq!(DROP_CNT.load(SeqCst), 0); drop(x); }); }); assert_eq!(DROP_CNT.load(SeqCst), 1); } #[test] fn once_cell_drop_empty() { let x = OnceCell::::new(); drop(x); } #[test] fn clone() { let s = OnceCell::new(); let c = s.clone(); assert!(c.get().is_none()); s.set("hello".to_string()).unwrap(); let c = s.clone(); assert_eq!(c.get().map(String::as_str), Some("hello")); } #[test] fn get_or_try_init() { let cell: OnceCell = OnceCell::new(); assert!(cell.get().is_none()); let res = std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); assert!(res.is_err()); assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); assert_eq!(cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), Ok(&"hello".to_string())); assert_eq!(cell.get(), Some(&"hello".to_string())); } #[cfg(feature = "std")] #[test] fn wait() { let cell: OnceCell = OnceCell::new(); scope(|s| { s.spawn(|| cell.set("hello".to_string())); let greeting = cell.wait(); assert_eq!(greeting, "hello") }); } #[cfg(feature = "std")] #[test] fn get_or_init_stress() { let n_threads = if cfg!(miri) { 30 } else { 1_000 }; let n_cells = if cfg!(miri) { 30 } else { 1_000 }; let cells: Vec<_> = std::iter::repeat_with(|| (Barrier::new(n_threads), OnceCell::new())) .take(n_cells) .collect(); scope(|s| { for t in 0..n_threads { let cells = &cells; s.spawn(move || { for (i, (b, s)) in cells.iter().enumerate() { b.wait(); let j = if t % 2 == 0 { s.wait() } else { s.get_or_init(|| i) }; assert_eq!(*j, i); } }); } }); } #[test] fn from_impl() { assert_eq!(OnceCell::from("value").get(), Some(&"value")); assert_ne!(OnceCell::from("foo").get(), Some(&"bar")); } #[test] fn partialeq_impl() { assert!(OnceCell::from("value") == OnceCell::from("value")); assert!(OnceCell::from("foo") != OnceCell::from("bar")); assert!(OnceCell::::new() == OnceCell::new()); assert!(OnceCell::::new() != OnceCell::from("value".to_owned())); } #[test] fn into_inner() { let cell: OnceCell = OnceCell::new(); assert_eq!(cell.into_inner(), None); let cell = OnceCell::new(); cell.set("hello".to_string()).unwrap(); assert_eq!(cell.into_inner(), Some("hello".to_string())); } #[test] fn debug_impl() { let cell = OnceCell::new(); assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)"); cell.set(vec!["hello", "world"]).unwrap(); assert_eq!( format!("{:#?}", cell), r#"OnceCell( [ "hello", "world", ], )"# ); } #[test] #[cfg_attr(miri, ignore)] // miri doesn't support processes #[cfg(feature = "std")] fn reentrant_init() { let examples_dir = { let mut exe = std::env::current_exe().unwrap(); exe.pop(); exe.pop(); exe.push("examples"); exe }; let bin = examples_dir .join("reentrant_init_deadlocks") .with_extension(std::env::consts::EXE_EXTENSION); let mut guard = Guard { child: std::process::Command::new(bin).spawn().unwrap() }; std::thread::sleep(std::time::Duration::from_secs(2)); let status = guard.child.try_wait().unwrap(); assert!(status.is_none()); struct Guard { child: std::process::Child, } impl Drop for Guard { fn drop(&mut self) { let _ = self.child.kill(); } } } #[cfg(not(feature = "std"))] #[test] #[should_panic(expected = "reentrant init")] fn reentrant_init() { let x: OnceCell> = OnceCell::new(); let dangling_ref: Cell> = Cell::new(None); x.get_or_init(|| { let r = x.get_or_init(|| Box::new(92)); dangling_ref.set(Some(r)); Box::new(62) }); eprintln!("use after free: {:?}", dangling_ref.get().unwrap()); } #[test] fn eval_once_macro() { macro_rules! eval_once { (|| -> $ty:ty { $($body:tt)* }) => {{ static ONCE_CELL: OnceCell<$ty> = OnceCell::new(); fn init() -> $ty { $($body)* } ONCE_CELL.get_or_init(init) }}; } let fib: &'static Vec = eval_once! { || -> Vec { let mut res = vec![1, 1]; for i in 0..10 { let next = res[i] + res[i + 1]; res.push(next); } res } }; assert_eq!(fib[5], 8) } #[test] fn once_cell_does_not_leak_partially_constructed_boxes() { let n_tries = if cfg!(miri) { 10 } else { 100 }; let n_readers = 10; let n_writers = 3; const MSG: &str = "Hello, World"; for _ in 0..n_tries { let cell: OnceCell = OnceCell::new(); scope(|scope| { for _ in 0..n_readers { scope.spawn(|| loop { if let Some(msg) = cell.get() { assert_eq!(msg, MSG); break; } }); } for _ in 0..n_writers { let _ = scope.spawn(|| cell.set(MSG.to_owned())); } }); } } #[cfg(feature = "std")] #[test] fn get_does_not_block() { let cell = OnceCell::new(); let barrier = Barrier::new(2); scope(|scope| { scope.spawn(|| { cell.get_or_init(|| { barrier.wait(); barrier.wait(); "hello".to_string() }); }); barrier.wait(); assert_eq!(cell.get(), None); barrier.wait(); }); assert_eq!(cell.get(), Some(&"hello".to_string())); } #[test] // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669 fn arrrrrrrrrrrrrrrrrrrrrr() { let cell = OnceCell::new(); { let s = String::new(); cell.set(&s).unwrap(); } } #[test] fn once_cell_is_sync_send() { fn assert_traits() {} assert_traits::>(); assert_traits::>(); } once_cell/tests/it/race_once_box.rs0000644000175000017500000000647514661133735020412 0ustar jamespagejamespage#[cfg(feature = "std")] use std::sync::Barrier; use std::sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, Arc, }; use once_cell::race::OnceBox; #[derive(Default)] struct Heap { total: Arc, } #[derive(Debug)] struct Pebble { val: T, total: Arc, } impl Drop for Pebble { fn drop(&mut self) { self.total.fetch_sub(1, SeqCst); } } impl Heap { fn total(&self) -> usize { self.total.load(SeqCst) } fn new_pebble(&self, val: T) -> Pebble { self.total.fetch_add(1, SeqCst); Pebble { val, total: Arc::clone(&self.total) } } } #[cfg(feature = "std")] #[test] fn once_box_smoke_test() { use std::thread::scope; let heap = Heap::default(); let global_cnt = AtomicUsize::new(0); let cell = OnceBox::new(); let b = Barrier::new(128); scope(|s| { for _ in 0..128 { s.spawn(|| { let local_cnt = AtomicUsize::new(0); cell.get_or_init(|| { global_cnt.fetch_add(1, SeqCst); local_cnt.fetch_add(1, SeqCst); b.wait(); Box::new(heap.new_pebble(())) }); assert_eq!(local_cnt.load(SeqCst), 1); cell.get_or_init(|| { global_cnt.fetch_add(1, SeqCst); local_cnt.fetch_add(1, SeqCst); Box::new(heap.new_pebble(())) }); assert_eq!(local_cnt.load(SeqCst), 1); }); } }); assert!(cell.get().is_some()); assert!(global_cnt.load(SeqCst) > 10); assert_eq!(heap.total(), 1); drop(cell); assert_eq!(heap.total(), 0); } #[test] fn once_box_set() { let heap = Heap::default(); let cell = OnceBox::new(); assert!(cell.get().is_none()); assert!(cell.set(Box::new(heap.new_pebble("hello"))).is_ok()); assert_eq!(cell.get().unwrap().val, "hello"); assert_eq!(heap.total(), 1); assert!(cell.set(Box::new(heap.new_pebble("world"))).is_err()); assert_eq!(cell.get().unwrap().val, "hello"); assert_eq!(heap.total(), 1); drop(cell); assert_eq!(heap.total(), 0); } #[cfg(feature = "std")] #[test] fn once_box_first_wins() { use std::thread::scope; let cell = OnceBox::new(); let val1 = 92; let val2 = 62; let b1 = Barrier::new(2); let b2 = Barrier::new(2); let b3 = Barrier::new(2); scope(|s| { s.spawn(|| { let r1 = cell.get_or_init(|| { b1.wait(); b2.wait(); Box::new(val1) }); assert_eq!(*r1, val1); b3.wait(); }); b1.wait(); s.spawn(|| { let r2 = cell.get_or_init(|| { b2.wait(); b3.wait(); Box::new(val2) }); assert_eq!(*r2, val1); }); }); assert_eq!(cell.get(), Some(&val1)); } #[test] fn once_box_reentrant() { let cell = OnceBox::new(); let res = cell.get_or_init(|| { cell.get_or_init(|| Box::new("hello".to_string())); Box::new("world".to_string()) }); assert_eq!(res, "hello"); } #[test] fn once_box_default() { struct Foo; let cell: OnceBox = Default::default(); assert!(cell.get().is_none()); } once_cell/LICENSE-MIT0000644000175000017500000000177714661133735015134 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. once_cell/src/0000775000175000017500000000000014661133735014255 5ustar jamespagejamespageonce_cell/src/imp_cs.rs0000644000175000017500000000466514661133735016106 0ustar jamespagejamespageuse core::panic::{RefUnwindSafe, UnwindSafe}; use portable_atomic::{AtomicBool, Ordering}; use critical_section::{CriticalSection, Mutex}; use crate::unsync; pub(crate) struct OnceCell { initialized: AtomicBool, // Use `unsync::OnceCell` internally since `Mutex` does not provide // interior mutability and to be able to re-use `get_or_try_init`. value: Mutex>, } // Why do we need `T: Send`? // Thread A creates a `OnceCell` and shares it with // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. unsafe impl Sync for OnceCell {} unsafe impl Send for OnceCell {} impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl OnceCell { pub(crate) const fn new() -> OnceCell { OnceCell { initialized: AtomicBool::new(false), value: Mutex::new(unsync::OnceCell::new()) } } pub(crate) const fn with_value(value: T) -> OnceCell { OnceCell { initialized: AtomicBool::new(true), value: Mutex::new(unsync::OnceCell::with_value(value)), } } #[inline] pub(crate) fn is_initialized(&self) -> bool { self.initialized.load(Ordering::Acquire) } #[cold] pub(crate) fn initialize(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result, { critical_section::with(|cs| { let cell = self.value.borrow(cs); cell.get_or_try_init(f).map(|_| { self.initialized.store(true, Ordering::Release); }) }) } /// Get the reference to the underlying value, without checking if the cell /// is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); // SAFETY: The caller ensures that the value is initialized and access synchronized. self.value.borrow(CriticalSection::new()).get().unwrap_unchecked() } #[inline] pub(crate) fn get_mut(&mut self) -> Option<&mut T> { self.value.get_mut().get_mut() } #[inline] pub(crate) fn into_inner(self) -> Option { self.value.into_inner().into_inner() } } once_cell/src/lib.rs0000644000175000017500000013354514661133735015402 0ustar jamespagejamespage//! # Overview //! //! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and //! [`sync::OnceCell`]. A `OnceCell` might store arbitrary non-`Copy` types, can //! be assigned to at most once and provides direct access to the stored //! contents. The core API looks *roughly* like this (and there's much more //! inside, read on!): //! //! ```rust,ignore //! impl OnceCell { //! const fn new() -> OnceCell { ... } //! fn set(&self, value: T) -> Result<(), T> { ... } //! fn get(&self) -> Option<&T> { ... } //! } //! ``` //! //! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires //! only a shared reference. Because of the single assignment restriction `get` //! can return a `&T` instead of `Ref` or `MutexGuard`. //! //! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait), //! while the `unsync` one is not. //! //! [`unsync::OnceCell`]: unsync/struct.OnceCell.html //! [`sync::OnceCell`]: sync/struct.OnceCell.html //! [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html //! [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html //! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html //! //! # Recipes //! //! `OnceCell` might be useful for a variety of patterns. //! //! ## Safe Initialization of Global Data //! //! ```rust //! use std::{env, io}; //! //! use once_cell::sync::OnceCell; //! //! #[derive(Debug)] //! pub struct Logger { //! // ... //! } //! static INSTANCE: OnceCell = OnceCell::new(); //! //! impl Logger { //! pub fn global() -> &'static Logger { //! INSTANCE.get().expect("logger is not initialized") //! } //! //! fn from_cli(args: env::Args) -> Result { //! // ... //! # Ok(Logger {}) //! } //! } //! //! fn main() { //! let logger = Logger::from_cli(env::args()).unwrap(); //! INSTANCE.set(logger).unwrap(); //! // use `Logger::global()` from now on //! } //! ``` //! //! ## Lazy Initialized Global Data //! //! This is essentially the `lazy_static!` macro, but without a macro. //! //! ```rust //! use std::{sync::Mutex, collections::HashMap}; //! //! use once_cell::sync::OnceCell; //! //! fn global_data() -> &'static Mutex> { //! static INSTANCE: OnceCell>> = OnceCell::new(); //! INSTANCE.get_or_init(|| { //! let mut m = HashMap::new(); //! m.insert(13, "Spica".to_string()); //! m.insert(74, "Hoyten".to_string()); //! Mutex::new(m) //! }) //! } //! ``` //! //! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to //! streamline this pattern: //! //! ```rust //! use std::{sync::Mutex, collections::HashMap}; //! use once_cell::sync::Lazy; //! //! static GLOBAL_DATA: Lazy>> = Lazy::new(|| { //! let mut m = HashMap::new(); //! m.insert(13, "Spica".to_string()); //! m.insert(74, "Hoyten".to_string()); //! Mutex::new(m) //! }); //! //! fn main() { //! println!("{:?}", GLOBAL_DATA.lock().unwrap()); //! } //! ``` //! //! Note that the variable that holds `Lazy` is declared as `static`, *not* //! `const`. This is important: using `const` instead compiles, but works wrong. //! //! [`sync::Lazy`]: sync/struct.Lazy.html //! [`unsync::Lazy`]: unsync/struct.Lazy.html //! //! ## General purpose lazy evaluation //! //! Unlike `lazy_static!`, `Lazy` works with local variables. //! //! ```rust //! use once_cell::unsync::Lazy; //! //! fn main() { //! let ctx = vec![1, 2, 3]; //! let thunk = Lazy::new(|| { //! ctx.iter().sum::() //! }); //! assert_eq!(*thunk, 6); //! } //! ``` //! //! If you need a lazy field in a struct, you probably should use `OnceCell` //! directly, because that will allow you to access `self` during //! initialization. //! //! ```rust //! use std::{fs, path::PathBuf}; //! //! use once_cell::unsync::OnceCell; //! //! struct Ctx { //! config_path: PathBuf, //! config: OnceCell, //! } //! //! impl Ctx { //! pub fn get_config(&self) -> Result<&str, std::io::Error> { //! let cfg = self.config.get_or_try_init(|| { //! fs::read_to_string(&self.config_path) //! })?; //! Ok(cfg.as_str()) //! } //! } //! ``` //! //! ## Lazily Compiled Regex //! //! This is a `regex!` macro which takes a string literal and returns an //! *expression* that evaluates to a `&'static Regex`: //! //! ``` //! macro_rules! regex { //! ($re:literal $(,)?) => {{ //! static RE: once_cell::sync::OnceCell = once_cell::sync::OnceCell::new(); //! RE.get_or_init(|| regex::Regex::new($re).unwrap()) //! }}; //! } //! ``` //! //! This macro can be useful to avoid the "compile regex on every loop //! iteration" problem. //! //! ## Runtime `include_bytes!` //! //! The `include_bytes` macro is useful to include test resources, but it slows //! down test compilation a lot. An alternative is to load the resources at //! runtime: //! //! ``` //! use std::path::Path; //! //! use once_cell::sync::OnceCell; //! //! pub struct TestResource { //! path: &'static str, //! cell: OnceCell>, //! } //! //! impl TestResource { //! pub const fn new(path: &'static str) -> TestResource { //! TestResource { path, cell: OnceCell::new() } //! } //! pub fn bytes(&self) -> &[u8] { //! self.cell.get_or_init(|| { //! let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); //! let path = Path::new(dir.as_str()).join(self.path); //! std::fs::read(&path).unwrap_or_else(|_err| { //! panic!("failed to load test resource: {}", path.display()) //! }) //! }).as_slice() //! } //! } //! //! static TEST_IMAGE: TestResource = TestResource::new("test_data/lena.png"); //! //! #[test] //! fn test_sobel_filter() { //! let rgb: &[u8] = TEST_IMAGE.bytes(); //! // ... //! # drop(rgb); //! } //! ``` //! //! ## `lateinit` //! //! `LateInit` type for delayed initialization. It is reminiscent of Kotlin's //! `lateinit` keyword and allows construction of cyclic data structures: //! //! //! ``` //! use once_cell::sync::OnceCell; //! //! pub struct LateInit { cell: OnceCell } //! //! impl LateInit { //! pub fn init(&self, value: T) { //! assert!(self.cell.set(value).is_ok()) //! } //! } //! //! impl Default for LateInit { //! fn default() -> Self { LateInit { cell: OnceCell::default() } } //! } //! //! impl std::ops::Deref for LateInit { //! type Target = T; //! fn deref(&self) -> &T { //! self.cell.get().unwrap() //! } //! } //! //! #[derive(Default)] //! struct A<'a> { //! b: LateInit<&'a B<'a>>, //! } //! //! #[derive(Default)] //! struct B<'a> { //! a: LateInit<&'a A<'a>> //! } //! //! //! fn build_cycle() { //! let a = A::default(); //! let b = B::default(); //! a.b.init(&b); //! b.a.init(&a); //! //! let _a = &a.b.a.b.a; //! } //! ``` //! //! # Comparison with std //! //! |`!Sync` types | Access Mode | Drawbacks | //! |----------------------|------------------------|-----------------------------------------------| //! |`Cell` | `T` | requires `T: Copy` for `get` | //! |`RefCell` | `RefMut` / `Ref` | may panic at runtime | //! |`unsync::OnceCell` | `&T` | assignable only once | //! //! |`Sync` types | Access Mode | Drawbacks | //! |----------------------|------------------------|-----------------------------------------------| //! |`AtomicT` | `T` | works only with certain `Copy` types | //! |`Mutex` | `MutexGuard` | may deadlock at runtime, may block the thread | //! |`sync::OnceCell` | `&T` | assignable only once, may block the thread | //! //! Technically, calling `get_or_init` will also cause a panic or a deadlock if //! it recursively calls itself. However, because the assignment can happen only //! once, such cases should be more rare than equivalents with `RefCell` and //! `Mutex`. //! //! # Minimum Supported `rustc` Version //! //! If only the `std`, `alloc`, or `race` features are enabled, MSRV will be //! updated conservatively, supporting at least latest 8 versions of the compiler. //! When using other features, like `parking_lot`, MSRV might be updated more //! frequently, up to the latest stable. In both cases, increasing MSRV is *not* //! considered a semver-breaking change and requires only a minor version bump. //! //! # Implementation details //! //! The implementation is based on the //! [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) and //! [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and //! [`std::sync::Once`]. In some sense, `once_cell` just streamlines and unifies //! those APIs. //! //! To implement a sync flavor of `OnceCell`, this crates uses either a custom //! re-implementation of `std::sync::Once` or `parking_lot::Mutex`. This is //! controlled by the `parking_lot` feature (disabled by default). Performance //! is the same for both cases, but the `parking_lot` based `OnceCell` is //! smaller by up to 16 bytes. //! //! This crate uses `unsafe`. //! //! [`std::sync::Once`]: https://doc.rust-lang.org/std/sync/struct.Once.html //! //! # F.A.Q. //! //! **Should I use the sync or unsync flavor?** //! //! Because Rust compiler checks thread safety for you, it's impossible to //! accidentally use `unsync` where `sync` is required. So, use `unsync` in //! single-threaded code and `sync` in multi-threaded. It's easy to switch //! between the two if code becomes multi-threaded later. //! //! At the moment, `unsync` has an additional benefit that reentrant //! initialization causes a panic, which might be easier to debug than a //! deadlock. //! //! **Does this crate support async?** //! //! No, but you can use //! [`async_once_cell`](https://crates.io/crates/async_once_cell) instead. //! //! **Does this crate support `no_std`?** //! //! Yes, but with caveats. `OnceCell` is a synchronization primitive which //! _semantically_ relies on blocking. `OnceCell` guarantees that at most one //! `f` will be called to compute the value. If two threads of execution call //! `get_or_init` concurrently, one of them has to wait. //! //! Waiting fundamentally requires OS support. Execution environment needs to //! understand who waits on whom to prevent deadlocks due to priority inversion. //! You _could_ make code to compile by blindly using pure spinlocks, but the //! runtime behavior would be subtly wrong. //! //! Given these constraints, `once_cell` provides the following options: //! //! - The `race` module provides similar, but distinct synchronization primitive //! which is compatible with `no_std`. With `race`, the `f` function can be //! called multiple times by different threads, but only one thread will win //! to install the value. //! - `critical-section` feature (with a `-`, not `_`) uses `critical_section` //! to implement blocking. //! //! **Can I bring my own mutex?** //! //! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to //! allow just that. //! //! **Should I use `std::cell::OnceCell`, `once_cell`, or `lazy_static`?** //! //! If you can use `std` version (your MSRV is at least 1.70, and you don't need //! extra features `once_cell` provides), use `std`. Otherwise, use `once_cell`. //! Don't use `lazy_static`. //! //! # Related crates //! //! * Most of this crate's functionality is available in `std` starting with //! Rust 1.70. See `std::cell::OnceCell` and `std::sync::OnceLock`. //! * [double-checked-cell](https://github.com/niklasf/double-checked-cell) //! * [lazy-init](https://crates.io/crates/lazy-init) //! * [lazycell](https://crates.io/crates/lazycell) //! * [mitochondria](https://crates.io/crates/mitochondria) //! * [lazy_static](https://crates.io/crates/lazy_static) //! * [async_once_cell](https://crates.io/crates/async_once_cell) //! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring //! your own mutex) #![cfg_attr(not(feature = "std"), no_std)] #[cfg(feature = "alloc")] extern crate alloc; #[cfg(all(feature = "critical-section", not(feature = "std")))] #[path = "imp_cs.rs"] mod imp; #[cfg(all(feature = "std", feature = "parking_lot"))] #[path = "imp_pl.rs"] mod imp; #[cfg(all(feature = "std", not(feature = "parking_lot")))] #[path = "imp_std.rs"] mod imp; /// Single-threaded version of `OnceCell`. pub mod unsync { use core::{ cell::{Cell, UnsafeCell}, fmt, mem, ops::{Deref, DerefMut}, panic::{RefUnwindSafe, UnwindSafe}, }; /// A cell which can be written to only once. It is not thread safe. /// /// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&` /// references to the contents. /// /// [`std::cell::RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// let value: &String = cell.get_or_init(|| { /// "Hello, World!".to_string() /// }); /// assert_eq!(value, "Hello, World!"); /// assert!(cell.get().is_some()); /// ``` pub struct OnceCell { // Invariant: written to at most once. inner: UnsafeCell>, } // Similarly to a `Sync` bound on `sync::OnceCell`, we can use // `&unsync::OnceCell` to sneak a `T` through `catch_unwind`, // by initializing the cell in closure and extracting the value in the // `Drop`. impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl Default for OnceCell { fn default() -> Self { Self::new() } } impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { Some(v) => f.debug_tuple("OnceCell").field(v).finish(), None => f.write_str("OnceCell(Uninit)"), } } } impl Clone for OnceCell { fn clone(&self) -> OnceCell { match self.get() { Some(value) => OnceCell::with_value(value.clone()), None => OnceCell::new(), } } fn clone_from(&mut self, source: &Self) { match (self.get_mut(), source.get()) { (Some(this), Some(source)) => this.clone_from(source), _ => *self = source.clone(), } } } impl PartialEq for OnceCell { fn eq(&self, other: &Self) -> bool { self.get() == other.get() } } impl Eq for OnceCell {} impl From for OnceCell { fn from(value: T) -> Self { OnceCell::with_value(value) } } impl OnceCell { /// Creates a new empty cell. pub const fn new() -> OnceCell { OnceCell { inner: UnsafeCell::new(None) } } /// Creates a new initialized cell. pub const fn with_value(value: T) -> OnceCell { OnceCell { inner: UnsafeCell::new(Some(value)) } } /// Gets a reference to the underlying value. /// /// Returns `None` if the cell is empty. #[inline] pub fn get(&self) -> Option<&T> { // Safe due to `inner`'s invariant of being written to at most once. // Had multiple writes to `inner` been allowed, a reference to the // value we return now would become dangling by a write of a // different value later. unsafe { &*self.inner.get() }.as_ref() } /// Gets a mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// *cell.get_mut().unwrap() = 93; /// assert_eq!(cell.get(), Some(&93)); /// ``` #[inline] pub fn get_mut(&mut self) -> Option<&mut T> { // Safe because we have unique access unsafe { &mut *self.inner.get() }.as_mut() } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// assert_eq!(cell.set(92), Ok(())); /// assert_eq!(cell.set(62), Err(62)); /// /// assert!(cell.get().is_some()); /// ``` pub fn set(&self, value: T) -> Result<(), T> { match self.try_insert(value) { Ok(_) => Ok(()), Err((_, value)) => Err(value), } } /// Like [`set`](Self::set), but also returns a reference to the final cell value. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// assert_eq!(cell.try_insert(92), Ok(&92)); /// assert_eq!(cell.try_insert(62), Err((&92, 62))); /// /// assert!(cell.get().is_some()); /// ``` pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { if let Some(old) = self.get() { return Err((old, value)); } let slot = unsafe { &mut *self.inner.get() }; // This is the only place where we set the slot, no races // due to reentrancy/concurrency are possible, and we've // checked that slot is currently `None`, so this write // maintains the `inner`'s invariant. *slot = Some(value); Ok(unsafe { slot.as_ref().unwrap_unchecked() }) } /// Gets the contents of the cell, initializing it with `f` /// if the cell was empty. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. Doing /// so results in a panic. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// let value = cell.get_or_init(|| 92); /// assert_eq!(value, &92); /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { enum Void {} match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. Doing /// so results in a panic. /// /// # Example /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); /// assert!(cell.get().is_none()); /// let value = cell.get_or_try_init(|| -> Result { /// Ok(92) /// }); /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { if let Some(val) = self.get() { return Ok(val); } let val = f()?; // Note that *some* forms of reentrant initialization might lead to // UB (see `reentrant_init` test). I believe that just removing this // `assert`, while keeping `set/get` would be sound, but it seems // better to panic, rather than to silently use an old value. assert!(self.set(val).is_ok(), "reentrant init"); Ok(unsafe { self.get().unwrap_unchecked() }) } /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. /// /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. /// /// # Examples /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.take(), None); /// /// let mut cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// cell = OnceCell::new(); /// ``` pub fn take(&mut self) -> Option { mem::take(self).into_inner() } /// Consumes the `OnceCell`, returning the wrapped value. /// /// Returns `None` if the cell was empty. /// /// # Examples /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.into_inner(), None); /// /// let cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` pub fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option`. self.inner.into_inner() } } /// A value which is initialized on the first access. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let lazy: Lazy = Lazy::new(|| { /// println!("initializing"); /// 92 /// }); /// println!("ready"); /// println!("{}", *lazy); /// println!("{}", *lazy); /// /// // Prints: /// // ready /// // initializing /// // 92 /// // 92 /// ``` pub struct Lazy T> { cell: OnceCell, init: Cell>, } impl RefUnwindSafe for Lazy where OnceCell: RefUnwindSafe {} impl fmt::Debug for Lazy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() } } impl Lazy { /// Creates a new lazy value with the given initializing function. /// /// # Example /// ``` /// # fn main() { /// use once_cell::unsync::Lazy; /// /// let hello = "Hello, World!".to_string(); /// /// let lazy = Lazy::new(|| hello.to_uppercase()); /// /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// # } /// ``` pub const fn new(init: F) -> Lazy { Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) } } /// Consumes this `Lazy` returning the stored value. /// /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. pub fn into_value(this: Lazy) -> Result { let cell = this.cell; let init = this.init; cell.into_inner().ok_or_else(|| { init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) }) } } impl T> Lazy { /// Forces the evaluation of this lazy value and returns a reference to /// the result. /// /// This is equivalent to the `Deref` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` pub fn force(this: &Lazy) -> &T { this.cell.get_or_init(|| match this.init.take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }) } /// Forces the evaluation of this lazy value and returns a mutable reference to /// the result. /// /// This is equivalent to the `DerefMut` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force_mut(&mut lazy), &92); /// assert_eq!(*lazy, 92); /// ``` pub fn force_mut(this: &mut Lazy) -> &mut T { if this.cell.get_mut().is_none() { let value = match this.init.get_mut().take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }; this.cell = OnceCell::with_value(value); } this.cell.get_mut().unwrap_or_else(|| unreachable!()) } /// Gets the reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get(&lazy), None); /// assert_eq!(&*lazy, &92); /// assert_eq!(Lazy::get(&lazy), Some(&92)); /// ``` pub fn get(this: &Lazy) -> Option<&T> { this.cell.get() } /// Gets the mutable reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::unsync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get_mut(&mut lazy), None); /// assert_eq!(*lazy, 92); /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92)); /// ``` pub fn get_mut(this: &mut Lazy) -> Option<&mut T> { this.cell.get_mut() } } impl T> Deref for Lazy { type Target = T; fn deref(&self) -> &T { Lazy::force(self) } } impl T> DerefMut for Lazy { fn deref_mut(&mut self) -> &mut T { Lazy::force_mut(self) } } impl Default for Lazy { /// Creates a new lazy value using `Default` as the initializing function. fn default() -> Lazy { Lazy::new(T::default) } } } /// Thread-safe, blocking version of `OnceCell`. #[cfg(any(feature = "std", feature = "critical-section"))] pub mod sync { use core::{ cell::Cell, fmt, mem, ops::{Deref, DerefMut}, panic::RefUnwindSafe, }; use super::imp::OnceCell as Imp; /// A thread-safe cell which can be written to only once. /// /// `OnceCell` provides `&` references to the contents without RAII guards. /// /// Reading a non-`None` value out of `OnceCell` establishes a /// happens-before relationship with a corresponding write. For example, if /// thread A initializes the cell with `get_or_init(f)`, and thread B /// subsequently reads the result of this call, B also observes all the side /// effects of `f`. /// /// # Example /// ``` /// use once_cell::sync::OnceCell; /// /// static CELL: OnceCell = OnceCell::new(); /// assert!(CELL.get().is_none()); /// /// std::thread::spawn(|| { /// let value: &String = CELL.get_or_init(|| { /// "Hello, World!".to_string() /// }); /// assert_eq!(value, "Hello, World!"); /// }).join().unwrap(); /// /// let value: Option<&String> = CELL.get(); /// assert!(value.is_some()); /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); /// ``` pub struct OnceCell(Imp); impl Default for OnceCell { fn default() -> OnceCell { OnceCell::new() } } impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { Some(v) => f.debug_tuple("OnceCell").field(v).finish(), None => f.write_str("OnceCell(Uninit)"), } } } impl Clone for OnceCell { fn clone(&self) -> OnceCell { match self.get() { Some(value) => Self::with_value(value.clone()), None => Self::new(), } } fn clone_from(&mut self, source: &Self) { match (self.get_mut(), source.get()) { (Some(this), Some(source)) => this.clone_from(source), _ => *self = source.clone(), } } } impl From for OnceCell { fn from(value: T) -> Self { Self::with_value(value) } } impl PartialEq for OnceCell { fn eq(&self, other: &OnceCell) -> bool { self.get() == other.get() } } impl Eq for OnceCell {} impl OnceCell { /// Creates a new empty cell. pub const fn new() -> OnceCell { OnceCell(Imp::new()) } /// Creates a new initialized cell. pub const fn with_value(value: T) -> OnceCell { OnceCell(Imp::with_value(value)) } /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. pub fn get(&self) -> Option<&T> { if self.0.is_initialized() { // Safe b/c value is initialized. Some(unsafe { self.get_unchecked() }) } else { None } } /// Gets the reference to the underlying value, blocking the current /// thread until it is set. /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell = std::sync::Arc::new(OnceCell::new()); /// let t = std::thread::spawn({ /// let cell = std::sync::Arc::clone(&cell); /// move || cell.set(92).unwrap() /// }); /// /// // Returns immediately, but might return None. /// let _value_or_none = cell.get(); /// /// // Will return 92, but might block until the other thread does `.set`. /// let value: &u32 = cell.wait(); /// assert_eq!(*value, 92); /// t.join().unwrap(); /// ``` #[cfg(feature = "std")] pub fn wait(&self) -> &T { if !self.0.is_initialized() { self.0.wait() } debug_assert!(self.0.is_initialized()); // Safe b/c of the wait call above and the fact that we didn't // relinquish our borrow. unsafe { self.get_unchecked() } } /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// cell = OnceCell::new(); /// ``` #[inline] pub fn get_mut(&mut self) -> Option<&mut T> { self.0.get_mut() } /// Get the reference to the underlying value, without checking if the /// cell is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. #[inline] pub unsafe fn get_unchecked(&self) -> &T { self.0.get_unchecked() } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. /// /// # Example /// /// ``` /// use once_cell::sync::OnceCell; /// /// static CELL: OnceCell = OnceCell::new(); /// /// fn main() { /// assert!(CELL.get().is_none()); /// /// std::thread::spawn(|| { /// assert_eq!(CELL.set(92), Ok(())); /// }).join().unwrap(); /// /// assert_eq!(CELL.set(62), Err(62)); /// assert_eq!(CELL.get(), Some(&92)); /// } /// ``` pub fn set(&self, value: T) -> Result<(), T> { match self.try_insert(value) { Ok(_) => Ok(()), Err((_, value)) => Err(value), } } /// Like [`set`](Self::set), but also returns a reference to the final cell value. /// /// # Example /// /// ``` /// use once_cell::unsync::OnceCell; /// /// let cell = OnceCell::new(); /// assert!(cell.get().is_none()); /// /// assert_eq!(cell.try_insert(92), Ok(&92)); /// assert_eq!(cell.try_insert(62), Err((&92, 62))); /// /// assert!(cell.get().is_some()); /// ``` pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { let mut value = Some(value); let res = self.get_or_init(|| unsafe { value.take().unwrap_unchecked() }); match value { None => Ok(res), Some(value) => Err((res, value)), } } /// Gets the contents of the cell, initializing it with `f` if the cell /// was empty. /// /// Many threads may call `get_or_init` concurrently with different /// initializing functions, but it is guaranteed that only one function /// will be executed. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and the cell /// remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. The /// exact outcome is unspecified. Current implementation deadlocks, but /// this may be changed to a panic in the future. /// /// # Example /// ``` /// use once_cell::sync::OnceCell; /// /// let cell = OnceCell::new(); /// let value = cell.get_or_init(|| 92); /// assert_eq!(value, &92); /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { enum Void {} match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// # Panics /// /// If `f` panics, the panic is propagated to the caller, and /// the cell remains uninitialized. /// /// It is an error to reentrantly initialize the cell from `f`. /// The exact outcome is unspecified. Current implementation /// deadlocks, but this may be changed to a panic in the future. /// /// # Example /// ``` /// use once_cell::sync::OnceCell; /// /// let cell = OnceCell::new(); /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); /// assert!(cell.get().is_none()); /// let value = cell.get_or_try_init(|| -> Result { /// Ok(92) /// }); /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { // Fast path check if let Some(value) = self.get() { return Ok(value); } self.0.initialize(f)?; // Safe b/c value is initialized. debug_assert!(self.0.is_initialized()); Ok(unsafe { self.get_unchecked() }) } /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state. /// /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized. /// /// # Examples /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.take(), None); /// /// let mut cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` /// /// This method is allowed to violate the invariant of writing to a `OnceCell` /// at most once because it requires `&mut` access to `self`. As with all /// interior mutability, `&mut` access permits arbitrary modification: /// /// ``` /// use once_cell::sync::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); /// cell.set(92).unwrap(); /// cell = OnceCell::new(); /// ``` pub fn take(&mut self) -> Option { mem::take(self).into_inner() } /// Consumes the `OnceCell`, returning the wrapped value. Returns /// `None` if the cell was empty. /// /// # Examples /// /// ``` /// use once_cell::sync::OnceCell; /// /// let cell: OnceCell = OnceCell::new(); /// assert_eq!(cell.into_inner(), None); /// /// let cell = OnceCell::new(); /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] pub fn into_inner(self) -> Option { self.0.into_inner() } } /// A value which is initialized on the first access. /// /// This type is thread-safe and can be used in statics. /// /// # Example /// /// ``` /// use std::collections::HashMap; /// /// use once_cell::sync::Lazy; /// /// static HASHMAP: Lazy> = Lazy::new(|| { /// println!("initializing"); /// let mut m = HashMap::new(); /// m.insert(13, "Spica".to_string()); /// m.insert(74, "Hoyten".to_string()); /// m /// }); /// /// fn main() { /// println!("ready"); /// std::thread::spawn(|| { /// println!("{:?}", HASHMAP.get(&13)); /// }).join().unwrap(); /// println!("{:?}", HASHMAP.get(&74)); /// /// // Prints: /// // ready /// // initializing /// // Some("Spica") /// // Some("Hoyten") /// } /// ``` pub struct Lazy T> { cell: OnceCell, init: Cell>, } impl fmt::Debug for Lazy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish() } } // We never create a `&F` from a `&Lazy` so it is fine to not impl // `Sync` for `F`. We do create a `&mut Option` in `force`, but this is // properly synchronized, so it only happens once so it also does not // contribute to this impl. unsafe impl Sync for Lazy where OnceCell: Sync {} // auto-derived `Send` impl is OK. impl RefUnwindSafe for Lazy where OnceCell: RefUnwindSafe {} impl Lazy { /// Creates a new lazy value with the given initializing /// function. pub const fn new(f: F) -> Lazy { Lazy { cell: OnceCell::new(), init: Cell::new(Some(f)) } } /// Consumes this `Lazy` returning the stored value. /// /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise. pub fn into_value(this: Lazy) -> Result { let cell = this.cell; let init = this.init; cell.into_inner().ok_or_else(|| { init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned")) }) } } impl T> Lazy { /// Forces the evaluation of this lazy value and /// returns a reference to the result. This is equivalent /// to the `Deref` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` pub fn force(this: &Lazy) -> &T { this.cell.get_or_init(|| match this.init.take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }) } /// Forces the evaluation of this lazy value and /// returns a mutable reference to the result. This is equivalent /// to the `Deref` impl, but is explicit. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92); /// ``` pub fn force_mut(this: &mut Lazy) -> &mut T { if this.cell.get_mut().is_none() { let value = match this.init.get_mut().take() { Some(f) => f(), None => panic!("Lazy instance has previously been poisoned"), }; this.cell = OnceCell::with_value(value); } this.cell.get_mut().unwrap_or_else(|| unreachable!()) } /// Gets the reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get(&lazy), None); /// assert_eq!(&*lazy, &92); /// assert_eq!(Lazy::get(&lazy), Some(&92)); /// ``` pub fn get(this: &Lazy) -> Option<&T> { this.cell.get() } /// Gets the reference to the result of this lazy value if /// it was initialized, otherwise returns `None`. /// /// # Example /// ``` /// use once_cell::sync::Lazy; /// /// let mut lazy = Lazy::new(|| 92); /// /// assert_eq!(Lazy::get_mut(&mut lazy), None); /// assert_eq!(&*lazy, &92); /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92)); /// ``` pub fn get_mut(this: &mut Lazy) -> Option<&mut T> { this.cell.get_mut() } } impl T> Deref for Lazy { type Target = T; fn deref(&self) -> &T { Lazy::force(self) } } impl T> DerefMut for Lazy { fn deref_mut(&mut self) -> &mut T { Lazy::force_mut(self) } } impl Default for Lazy { /// Creates a new lazy value using `Default` as the initializing function. fn default() -> Lazy { Lazy::new(T::default) } } /// ```compile_fail /// struct S(*mut ()); /// unsafe impl Sync for S {} /// /// fn share(_: &T) {} /// share(&once_cell::sync::OnceCell::::new()); /// ``` /// /// ```compile_fail /// struct S(*mut ()); /// unsafe impl Sync for S {} /// /// fn share(_: &T) {} /// share(&once_cell::sync::Lazy::::new(|| unimplemented!())); /// ``` fn _dummy() {} } #[cfg(feature = "race")] pub mod race; once_cell/src/imp_pl.rs0000644000175000017500000001325314661133735016105 0ustar jamespagejamespageuse std::{ cell::UnsafeCell, panic::{RefUnwindSafe, UnwindSafe}, sync::atomic::{AtomicU8, Ordering}, }; pub(crate) struct OnceCell { state: AtomicU8, value: UnsafeCell>, } const INCOMPLETE: u8 = 0x0; const RUNNING: u8 = 0x1; const COMPLETE: u8 = 0x2; // Why do we need `T: Send`? // Thread A creates a `OnceCell` and shares it with // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. unsafe impl Sync for OnceCell {} unsafe impl Send for OnceCell {} impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl OnceCell { pub(crate) const fn new() -> OnceCell { OnceCell { state: AtomicU8::new(INCOMPLETE), value: UnsafeCell::new(None) } } pub(crate) const fn with_value(value: T) -> OnceCell { OnceCell { state: AtomicU8::new(COMPLETE), value: UnsafeCell::new(Some(value)) } } /// Safety: synchronizes with store to value via Release/Acquire. #[inline] pub(crate) fn is_initialized(&self) -> bool { self.state.load(Ordering::Acquire) == COMPLETE } /// Safety: synchronizes with store to value via `is_initialized` or mutex /// lock/unlock, writes value only once because of the mutex. #[cold] pub(crate) fn initialize(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result, { let mut f = Some(f); let mut res: Result<(), E> = Ok(()); let slot: *mut Option = self.value.get(); initialize_inner(&self.state, &mut || { // We are calling user-supplied function and need to be careful. // - if it returns Err, we unlock mutex and return without touching anything // - if it panics, we unlock mutex and propagate panic without touching anything // - if it calls `set` or `get_or_try_init` re-entrantly, we get a deadlock on // mutex, which is important for safety. We *could* detect this and panic, // but that is more complicated // - finally, if it returns Ok, we store the value and store the flag with // `Release`, which synchronizes with `Acquire`s. let f = unsafe { f.take().unwrap_unchecked() }; match f() { Ok(value) => unsafe { // Safe b/c we have a unique access and no panic may happen // until the cell is marked as initialized. debug_assert!((*slot).is_none()); *slot = Some(value); true }, Err(err) => { res = Err(err); false } } }); res } #[cold] pub(crate) fn wait(&self) { let key = &self.state as *const _ as usize; unsafe { parking_lot_core::park( key, || self.state.load(Ordering::Acquire) != COMPLETE, || (), |_, _| (), parking_lot_core::DEFAULT_PARK_TOKEN, None, ); } } /// Get the reference to the underlying value, without checking if the cell /// is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); let slot = &*self.value.get(); slot.as_ref().unwrap_unchecked() } /// Gets the mutable reference to the underlying value. /// Returns `None` if the cell is empty. pub(crate) fn get_mut(&mut self) -> Option<&mut T> { // Safe b/c we have an exclusive access let slot: &mut Option = unsafe { &mut *self.value.get() }; slot.as_mut() } /// Consumes this `OnceCell`, returning the wrapped value. /// Returns `None` if the cell was empty. pub(crate) fn into_inner(self) -> Option { self.value.into_inner() } } struct Guard<'a> { state: &'a AtomicU8, new_state: u8, } impl<'a> Drop for Guard<'a> { fn drop(&mut self) { self.state.store(self.new_state, Ordering::Release); unsafe { let key = self.state as *const AtomicU8 as usize; parking_lot_core::unpark_all(key, parking_lot_core::DEFAULT_UNPARK_TOKEN); } } } // Note: this is intentionally monomorphic #[inline(never)] fn initialize_inner(state: &AtomicU8, init: &mut dyn FnMut() -> bool) { loop { let exchange = state.compare_exchange_weak(INCOMPLETE, RUNNING, Ordering::Acquire, Ordering::Acquire); match exchange { Ok(_) => { let mut guard = Guard { state, new_state: INCOMPLETE }; if init() { guard.new_state = COMPLETE; } return; } Err(COMPLETE) => return, Err(RUNNING) => unsafe { let key = state as *const AtomicU8 as usize; parking_lot_core::park( key, || state.load(Ordering::Relaxed) == RUNNING, || (), |_, _| (), parking_lot_core::DEFAULT_PARK_TOKEN, None, ); }, Err(INCOMPLETE) => (), Err(_) => debug_assert!(false), } } } #[test] fn test_size() { use std::mem::size_of; assert_eq!(size_of::>(), 1 * size_of::() + size_of::()); } once_cell/src/imp_std.rs0000644000175000017500000003070714661133735016267 0ustar jamespagejamespage// There's a lot of scary concurrent code in this module, but it is copied from // `std::sync::Once` with two changes: // * no poisoning // * init function can fail use std::{ cell::{Cell, UnsafeCell}, panic::{RefUnwindSafe, UnwindSafe}, sync::atomic::{AtomicBool, AtomicPtr, Ordering}, thread::{self, Thread}, }; #[derive(Debug)] pub(crate) struct OnceCell { // This `queue` field is the core of the implementation. It encodes two // pieces of information: // // * The current state of the cell (`INCOMPLETE`, `RUNNING`, `COMPLETE`) // * Linked list of threads waiting for the current cell. // // State is encoded in two low bits. Only `INCOMPLETE` and `RUNNING` states // allow waiters. queue: AtomicPtr, value: UnsafeCell>, } // Why do we need `T: Send`? // Thread A creates a `OnceCell` and shares it with // scoped thread B, which fills the cell, which is // then destroyed by A. That is, destructor observes // a sent value. unsafe impl Sync for OnceCell {} unsafe impl Send for OnceCell {} impl RefUnwindSafe for OnceCell {} impl UnwindSafe for OnceCell {} impl OnceCell { pub(crate) const fn new() -> OnceCell { OnceCell { queue: AtomicPtr::new(INCOMPLETE_PTR), value: UnsafeCell::new(None) } } pub(crate) const fn with_value(value: T) -> OnceCell { OnceCell { queue: AtomicPtr::new(COMPLETE_PTR), value: UnsafeCell::new(Some(value)) } } /// Safety: synchronizes with store to value via Release/(Acquire|SeqCst). #[inline] pub(crate) fn is_initialized(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization // operations visible to us, and, this being a fast path, weaker // ordering helps with performance. This `Acquire` synchronizes with // `SeqCst` operations on the slow path. self.queue.load(Ordering::Acquire) == COMPLETE_PTR } /// Safety: synchronizes with store to value via SeqCst read from state, /// writes value only once because we never get to INCOMPLETE state after a /// successful write. #[cold] pub(crate) fn initialize(&self, f: F) -> Result<(), E> where F: FnOnce() -> Result, { let mut f = Some(f); let mut res: Result<(), E> = Ok(()); let slot: *mut Option = self.value.get(); initialize_or_wait( &self.queue, Some(&mut || { let f = unsafe { f.take().unwrap_unchecked() }; match f() { Ok(value) => { unsafe { *slot = Some(value) }; true } Err(err) => { res = Err(err); false } } }), ); res } #[cold] pub(crate) fn wait(&self) { initialize_or_wait(&self.queue, None); } /// Get the reference to the underlying value, without checking if the cell /// is initialized. /// /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub(crate) unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); let slot = &*self.value.get(); slot.as_ref().unwrap_unchecked() } /// Gets the mutable reference to the underlying value. /// Returns `None` if the cell is empty. pub(crate) fn get_mut(&mut self) -> Option<&mut T> { // Safe b/c we have a unique access. unsafe { &mut *self.value.get() }.as_mut() } /// Consumes this `OnceCell`, returning the wrapped value. /// Returns `None` if the cell was empty. #[inline] pub(crate) fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically // verifies that it is not currently borrowed. // So, it is safe to move out `Option`. self.value.into_inner() } } // Three states that a OnceCell can be in, encoded into the lower bits of `queue` in // the OnceCell structure. const INCOMPLETE: usize = 0x0; const RUNNING: usize = 0x1; const COMPLETE: usize = 0x2; const INCOMPLETE_PTR: *mut Waiter = INCOMPLETE as *mut Waiter; const COMPLETE_PTR: *mut Waiter = COMPLETE as *mut Waiter; // Mask to learn about the state. All other bits are the queue of waiters if // this is in the RUNNING state. const STATE_MASK: usize = 0x3; /// Representation of a node in the linked list of waiters in the RUNNING state. /// A waiters is stored on the stack of the waiting threads. #[repr(align(4))] // Ensure the two lower bits are free to use as state bits. struct Waiter { thread: Cell>, signaled: AtomicBool, next: *mut Waiter, } /// Drains and notifies the queue of waiters on drop. struct Guard<'a> { queue: &'a AtomicPtr, new_queue: *mut Waiter, } impl Drop for Guard<'_> { fn drop(&mut self) { let queue = self.queue.swap(self.new_queue, Ordering::AcqRel); let state = strict::addr(queue) & STATE_MASK; assert_eq!(state, RUNNING); unsafe { let mut waiter = strict::map_addr(queue, |q| q & !STATE_MASK); while !waiter.is_null() { let next = (*waiter).next; let thread = (*waiter).thread.take().unwrap(); (*waiter).signaled.store(true, Ordering::Release); waiter = next; thread.unpark(); } } } } // Corresponds to `std::sync::Once::call_inner`. // // Originally copied from std, but since modified to remove poisoning and to // support wait. // // Note: this is intentionally monomorphic #[inline(never)] fn initialize_or_wait(queue: &AtomicPtr, mut init: Option<&mut dyn FnMut() -> bool>) { let mut curr_queue = queue.load(Ordering::Acquire); loop { let curr_state = strict::addr(curr_queue) & STATE_MASK; match (curr_state, &mut init) { (COMPLETE, _) => return, (INCOMPLETE, Some(init)) => { let exchange = queue.compare_exchange( curr_queue, strict::map_addr(curr_queue, |q| (q & !STATE_MASK) | RUNNING), Ordering::Acquire, Ordering::Acquire, ); if let Err(new_queue) = exchange { curr_queue = new_queue; continue; } let mut guard = Guard { queue, new_queue: INCOMPLETE_PTR }; if init() { guard.new_queue = COMPLETE_PTR; } return; } (INCOMPLETE, None) | (RUNNING, _) => { wait(queue, curr_queue); curr_queue = queue.load(Ordering::Acquire); } _ => debug_assert!(false), } } } fn wait(queue: &AtomicPtr, mut curr_queue: *mut Waiter) { let curr_state = strict::addr(curr_queue) & STATE_MASK; loop { let node = Waiter { thread: Cell::new(Some(thread::current())), signaled: AtomicBool::new(false), next: strict::map_addr(curr_queue, |q| q & !STATE_MASK), }; let me = &node as *const Waiter as *mut Waiter; let exchange = queue.compare_exchange( curr_queue, strict::map_addr(me, |q| q | curr_state), Ordering::Release, Ordering::Relaxed, ); if let Err(new_queue) = exchange { if strict::addr(new_queue) & STATE_MASK != curr_state { return; } curr_queue = new_queue; continue; } while !node.signaled.load(Ordering::Acquire) { thread::park(); } break; } } // Polyfill of strict provenance from https://crates.io/crates/sptr. // // Use free-standing function rather than a trait to keep things simple and // avoid any potential conflicts with future stabile std API. mod strict { #[must_use] #[inline] pub(crate) fn addr(ptr: *mut T) -> usize where T: Sized, { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the // provenance). unsafe { core::mem::transmute(ptr) } } #[must_use] #[inline] pub(crate) fn with_addr(ptr: *mut T, addr: usize) -> *mut T where T: Sized, { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. // // In the mean-time, this operation is defined to be "as if" it was // a wrapping_offset, so we can emulate it as such. This should properly // restore pointer provenance even under today's compiler. let self_addr = self::addr(ptr) as isize; let dest_addr = addr as isize; let offset = dest_addr.wrapping_sub(self_addr); // This is the canonical desugarring of this operation, // but `pointer::cast` was only stabilized in 1.38. // self.cast::().wrapping_offset(offset).cast::() (ptr as *mut u8).wrapping_offset(offset) as *mut T } #[must_use] #[inline] pub(crate) fn map_addr(ptr: *mut T, f: impl FnOnce(usize) -> usize) -> *mut T where T: Sized, { self::with_addr(ptr, f(addr(ptr))) } } // These test are snatched from std as well. #[cfg(test)] mod tests { use std::panic; use std::{sync::mpsc::channel, thread}; use super::OnceCell; impl OnceCell { fn init(&self, f: impl FnOnce() -> T) { enum Void {} let _ = self.initialize(|| Ok::(f())); } } #[test] fn smoke_once() { static O: OnceCell<()> = OnceCell::new(); let mut a = 0; O.init(|| a += 1); assert_eq!(a, 1); O.init(|| a += 1); assert_eq!(a, 1); } #[test] fn stampede_once() { static O: OnceCell<()> = OnceCell::new(); static mut RUN: bool = false; let (tx, rx) = channel(); for _ in 0..10 { let tx = tx.clone(); thread::spawn(move || { for _ in 0..4 { thread::yield_now() } unsafe { O.init(|| { assert!(!RUN); RUN = true; }); assert!(RUN); } tx.send(()).unwrap(); }); } unsafe { O.init(|| { assert!(!RUN); RUN = true; }); assert!(RUN); } for _ in 0..10 { rx.recv().unwrap(); } } #[test] fn poison_bad() { static O: OnceCell<()> = OnceCell::new(); // poison the once let t = panic::catch_unwind(|| { O.init(|| panic!()); }); assert!(t.is_err()); // we can subvert poisoning, however let mut called = false; O.init(|| { called = true; }); assert!(called); // once any success happens, we stop propagating the poison O.init(|| {}); } #[test] fn wait_for_force_to_finish() { static O: OnceCell<()> = OnceCell::new(); // poison the once let t = panic::catch_unwind(|| { O.init(|| panic!()); }); assert!(t.is_err()); // make sure someone's waiting inside the once via a force let (tx1, rx1) = channel(); let (tx2, rx2) = channel(); let t1 = thread::spawn(move || { O.init(|| { tx1.send(()).unwrap(); rx2.recv().unwrap(); }); }); rx1.recv().unwrap(); // put another waiter on the once let t2 = thread::spawn(|| { let mut called = false; O.init(|| { called = true; }); assert!(!called); }); tx2.send(()).unwrap(); assert!(t1.join().is_ok()); assert!(t2.join().is_ok()); } #[test] #[cfg(target_pointer_width = "64")] fn test_size() { use std::mem::size_of; assert_eq!(size_of::>(), 4 * size_of::()); } } once_cell/src/race.rs0000644000175000017500000003173714661133735015546 0ustar jamespagejamespage//! Thread-safe, non-blocking, "first one wins" flavor of `OnceCell`. //! //! If two threads race to initialize a type from the `race` module, they //! don't block, execute initialization function together, but only one of //! them stores the result. //! //! This module does not require `std` feature. //! //! # Atomic orderings //! //! All types in this module use `Acquire` and `Release` //! [atomic orderings](Ordering) for all their operations. While this is not //! strictly necessary for types other than `OnceBox`, it is useful for users as //! it allows them to be certain that after `get` or `get_or_init` returns on //! one thread, any side-effects caused by the setter thread prior to them //! calling `set` or `get_or_init` will be made visible to that thread; without //! it, it's possible for it to appear as if they haven't happened yet from the //! getter thread's perspective. This is an acceptable tradeoff to make since //! `Acquire` and `Release` have very little performance overhead on most //! architectures versus `Relaxed`. #[cfg(feature = "critical-section")] use portable_atomic as atomic; #[cfg(not(feature = "critical-section"))] use core::sync::atomic; use atomic::{AtomicPtr, AtomicUsize, Ordering}; use core::cell::UnsafeCell; use core::marker::PhantomData; use core::num::NonZeroUsize; use core::ptr; /// A thread-safe cell which can be written to only once. #[derive(Default, Debug)] pub struct OnceNonZeroUsize { inner: AtomicUsize, } impl OnceNonZeroUsize { /// Creates a new empty cell. #[inline] pub const fn new() -> OnceNonZeroUsize { OnceNonZeroUsize { inner: AtomicUsize::new(0) } } /// Gets the underlying value. #[inline] pub fn get(&self) -> Option { let val = self.inner.load(Ordering::Acquire); NonZeroUsize::new(val) } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(())` if it was /// full. #[inline] pub fn set(&self, value: NonZeroUsize) -> Result<(), ()> { let exchange = self.inner.compare_exchange(0, value.get(), Ordering::AcqRel, Ordering::Acquire); match exchange { Ok(_) => Ok(()), Err(_) => Err(()), } } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> NonZeroUsize where F: FnOnce() -> NonZeroUsize, { enum Void {} match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result where F: FnOnce() -> Result, { let val = self.inner.load(Ordering::Acquire); let res = match NonZeroUsize::new(val) { Some(it) => it, None => { let mut val = f()?.get(); let exchange = self.inner.compare_exchange(0, val, Ordering::AcqRel, Ordering::Acquire); if let Err(old) = exchange { val = old; } unsafe { NonZeroUsize::new_unchecked(val) } } }; Ok(res) } } /// A thread-safe cell which can be written to only once. #[derive(Default, Debug)] pub struct OnceBool { inner: OnceNonZeroUsize, } impl OnceBool { /// Creates a new empty cell. #[inline] pub const fn new() -> OnceBool { OnceBool { inner: OnceNonZeroUsize::new() } } /// Gets the underlying value. #[inline] pub fn get(&self) -> Option { self.inner.get().map(OnceBool::from_usize) } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(())` if it was /// full. #[inline] pub fn set(&self, value: bool) -> Result<(), ()> { self.inner.set(OnceBool::to_usize(value)) } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> bool where F: FnOnce() -> bool, { OnceBool::from_usize(self.inner.get_or_init(|| OnceBool::to_usize(f()))) } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result where F: FnOnce() -> Result, { self.inner.get_or_try_init(|| f().map(OnceBool::to_usize)).map(OnceBool::from_usize) } #[inline] fn from_usize(value: NonZeroUsize) -> bool { value.get() == 1 } #[inline] fn to_usize(value: bool) -> NonZeroUsize { unsafe { NonZeroUsize::new_unchecked(if value { 1 } else { 2 }) } } } /// A thread-safe cell which can be written to only once. pub struct OnceRef<'a, T> { inner: AtomicPtr, ghost: PhantomData>, } // TODO: Replace UnsafeCell with SyncUnsafeCell once stabilized unsafe impl<'a, T: Sync> Sync for OnceRef<'a, T> {} impl<'a, T> core::fmt::Debug for OnceRef<'a, T> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "OnceRef({:?})", self.inner) } } impl<'a, T> Default for OnceRef<'a, T> { fn default() -> Self { Self::new() } } impl<'a, T> OnceRef<'a, T> { /// Creates a new empty cell. pub const fn new() -> OnceRef<'a, T> { OnceRef { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData } } /// Gets a reference to the underlying value. pub fn get(&self) -> Option<&'a T> { let ptr = self.inner.load(Ordering::Acquire); unsafe { ptr.as_ref() } } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. pub fn set(&self, value: &'a T) -> Result<(), ()> { let ptr = value as *const T as *mut T; let exchange = self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire); match exchange { Ok(_) => Ok(()), Err(_) => Err(()), } } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> &'a T where F: FnOnce() -> &'a T, { enum Void {} match self.get_or_try_init(|| Ok::<&'a T, Void>(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result<&'a T, E> where F: FnOnce() -> Result<&'a T, E>, { let mut ptr = self.inner.load(Ordering::Acquire); if ptr.is_null() { // TODO replace with `cast_mut` when MSRV reaches 1.65.0 (also in `set`) ptr = f()? as *const T as *mut T; let exchange = self.inner.compare_exchange( ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire, ); if let Err(old) = exchange { ptr = old; } } Ok(unsafe { &*ptr }) } /// ```compile_fail /// use once_cell::race::OnceRef; /// /// let mut l = OnceRef::new(); /// /// { /// let y = 2; /// let mut r = OnceRef::new(); /// r.set(&y).unwrap(); /// core::mem::swap(&mut l, &mut r); /// } /// /// // l now contains a dangling reference to y /// eprintln!("uaf: {}", l.get().unwrap()); /// ``` fn _dummy() {} } #[cfg(feature = "alloc")] pub use self::once_box::OnceBox; #[cfg(feature = "alloc")] mod once_box { use super::atomic::{AtomicPtr, Ordering}; use core::{marker::PhantomData, ptr}; use alloc::boxed::Box; /// A thread-safe cell which can be written to only once. pub struct OnceBox { inner: AtomicPtr, ghost: PhantomData>>, } impl core::fmt::Debug for OnceBox { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "OnceBox({:?})", self.inner.load(Ordering::Relaxed)) } } impl Default for OnceBox { fn default() -> Self { Self::new() } } impl Drop for OnceBox { fn drop(&mut self) { let ptr = *self.inner.get_mut(); if !ptr.is_null() { drop(unsafe { Box::from_raw(ptr) }) } } } impl OnceBox { /// Creates a new empty cell. pub const fn new() -> OnceBox { OnceBox { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData } } /// Gets a reference to the underlying value. pub fn get(&self) -> Option<&T> { let ptr = self.inner.load(Ordering::Acquire); if ptr.is_null() { return None; } Some(unsafe { &*ptr }) } /// Sets the contents of this cell to `value`. /// /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was /// full. pub fn set(&self, value: Box) -> Result<(), Box> { let ptr = Box::into_raw(value); let exchange = self.inner.compare_exchange( ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire, ); if exchange.is_err() { let value = unsafe { Box::from_raw(ptr) }; return Err(value); } Ok(()) } /// Gets the contents of the cell, initializing it with `f` if the cell was /// empty. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> Box, { enum Void {} match self.get_or_try_init(|| Ok::, Void>(f())) { Ok(val) => val, Err(void) => match void {}, } } /// Gets the contents of the cell, initializing it with `f` if /// the cell was empty. If the cell was empty and `f` failed, an /// error is returned. /// /// If several threads concurrently run `get_or_init`, more than one `f` can /// be called. However, all threads will return the same value, produced by /// some `f`. pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, E>, { let mut ptr = self.inner.load(Ordering::Acquire); if ptr.is_null() { let val = f()?; ptr = Box::into_raw(val); let exchange = self.inner.compare_exchange( ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire, ); if let Err(old) = exchange { drop(unsafe { Box::from_raw(ptr) }); ptr = old; } }; Ok(unsafe { &*ptr }) } } unsafe impl Sync for OnceBox {} /// ```compile_fail /// struct S(*mut ()); /// unsafe impl Sync for S {} /// /// fn share(_: &T) {} /// share(&once_cell::race::OnceBox::::new()); /// ``` fn _dummy() {} } once_cell/CHANGELOG.md0000644000175000017500000001401514661133735015276 0ustar jamespagejamespage# Changelog ## Unreleased - ## 1.19.0 - Use `portable-atomic` instead of `atomic-polyfill`, [#251](https://github.com/matklad/once_cell/pull/251). ## 1.18.0 - `MSRV` is updated to 1.60.0 to take advantage of `dep:` syntax for cargo features, removing "implementation details" from publicly visible surface. ## 1.17.2 - Avoid unnecessary synchronization in `Lazy::{force,deref}_mut()`, [#231](https://github.com/matklad/once_cell/pull/231). ## 1.17.1 - Make `OnceRef` implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228). ## 1.17.0 - Add `race::OnceRef` for storing a `&'a T`. ## 1.16.0 - Add `no_std` implementation based on `critical-section`, [#195](https://github.com/matklad/once_cell/pull/195). - Deprecate `atomic-polyfill` feature (use the new `critical-section` instead) ## 1.15.0 - Increase minimal supported Rust version to 1.56.0. - Implement `UnwindSafe` even if the `std` feature is disabled. ## 1.14.0 - Add extension to `unsync` and `sync` `Lazy` mut API: - `force_mut` - `get_mut` ## 1.13.1 - Make implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228). - Upgrade `atomic-polyfill` to `1.0` ## 1.13.0 - Add `Lazy::get`, similar to `OnceCell::get`. ## 1.12.1 - Remove incorrect `debug_assert`. ## 1.12.0 - Add `OnceCell::wait`, a blocking variant of `get`. ## 1.11.0 - Add `OnceCell::with_value` to create initialized `OnceCell` in `const` context. - Improve `Clone` implementation for `OnceCell`. - Rewrite `parking_lot` version on top of `parking_lot_core`, for even smaller cells! ## 1.10.0 - upgrade `parking_lot` to `0.12.0` (note that this bumps MSRV with `parking_lot` feature enabled to `1.49.0`). ## 1.9.0 - Added an `atomic-polyfill` optional dependency to compile `race` on platforms without atomics ## 1.8.0 - Add `try_insert` API -- a version of `set` that returns a reference. ## 1.7.2 - Improve code size when using parking_lot feature. ## 1.7.1 - Fix `race::OnceBox` to also impl `Default` even if `T` doesn't impl `Default`. ## 1.7.0 - Hide the `race` module behind (default) `race` feature. Turns out that adding `race` by default was a breaking change on some platforms without atomics. In this release, we make the module opt-out. Technically, this is a breaking change for those who use `race` with `no_default_features`. Given that the `race` module itself only several days old, the breakage is deemed acceptable. ## 1.6.0 - Add `Lazy::into_value` - Stabilize `once_cell::race` module for "first one wins" no_std-compatible initialization flavor. - Migrate from deprecated `compare_and_swap` to `compare_exchange`. ## 1.5.2 - `OnceBox` API uses `Box`. This a breaking change to unstable API. ## 1.5.1 - MSRV is increased to `1.36.0`. - document `once_cell::race` module. - introduce `alloc` feature for `OnceBox`. - fix `OnceBox::set`. ## 1.5.0 - add new `once_cell::race` module for "first one wins" no_std-compatible initialization flavor. The API is provisional, subject to change and is gated by the `unstable` cargo feature. ## 1.4.1 - upgrade `parking_lot` to `0.11.0` - make `sync::OnceCell` pass https://doc.rust-lang.org/nomicon/dropck.html#an-escape-hatch[dropck] with `parking_lot` feature enabled. This fixes a (minor) semver-incompatible changed introduced in `1.4.0` ## 1.4.0 - upgrade `parking_lot` to `0.10` (note that this bumps MSRV with `parking_lot` feature enabled to `1.36.0`). - add `OnceCell::take`. - upgrade crossbeam utils (private dependency) to `0.7`. ## 1.3.1 - remove unnecessary `F: fmt::Debug` bound from `impl fmt::Debug for Lazy`. ## 1.3.0 - `Lazy` now implements `DerefMut`. - update implementation according to the latest changes in `std`. ## 1.2.0 - add `sync::OnceCell::get_unchecked`. ## 1.1.0 - implement `Default` for `Lazy`: it creates an empty `Lazy` which is initialized with `T::default` on first access. - add `OnceCell::get_mut`. ## 1.0.2 - actually add `#![no_std]` attribute if std feature is not enabled. ## 1.0.1 - fix unsoundness in `Lazy` if the initializing function panics. Thanks [@xfix](https://github.com/xfix)! - implement `RefUnwindSafe` for `Lazy`. - share more code between `std` and `parking_lot` implementations. - add F.A.Q section to the docs. ## 1.0.0 - remove `parking_lot` from the list of default features. - add `std` default feature. Without `std`, only `unsync` module is supported. - implement `Eq` for `OnceCell`. - fix wrong `Sync` bound on `sync::Lazy`. - run the whole test suite with miri. ## 0.2.7 - New implementation of `sync::OnceCell` if `parking_lot` feature is disabled. It now employs a hand-rolled variant of `std::sync::Once`. - `sync::OnceCell::get_or_try_init` works without `parking_lot` as well! - document the effects of `parking_lot` feature: same performance but smaller types. ## 0.2.6 - Updated `Lazy`'s `Deref` impl to requires only `FnOnce` instead of `Fn` ## 0.2.5 - `Lazy` requires only `FnOnce` instead of `Fn` ## 0.2.4 - nicer `fmt::Debug` implementation ## 0.2.3 - update `parking_lot` to `0.9.0` - fix stacked borrows violation in `unsync::OnceCell::get` - implement `Clone` for `sync::OnceCell where T: Clone` ## 0.2.2 - add `OnceCell::into_inner` which consumes a cell and returns an option ## 0.2.1 - implement `sync::OnceCell::get_or_try_init` if `parking_lot` feature is enabled - switch internal `unsafe` implementation of `sync::OnceCell` from `Once` to `Mutex` - `sync::OnceCell::get_or_init` is twice as fast if cell is already initialized - implement `std::panic::RefUnwindSafe` and `std::panic::UnwindSafe` for `OnceCell` - better document behavior around panics ## 0.2.0 - MSRV is now 1.31.1 - `Lazy::new` and `OnceCell::new` are now const-fns - `unsync_lazy` and `sync_lazy` macros are removed ## 0.1.8 - update crossbeam-utils to 0.6 - enable bors-ng ## 0.1.7 - cells implement `PartialEq` and `From` - MSRV is down to 1.24.1 - update `parking_lot` to `0.7.1` ## 0.1.6 - `unsync::OnceCell` is `Clone` if `T` is `Clone`. ## 0.1.5 - No changelog until this point :( once_cell/.cargo-checksum.json0000664000175000017500000000434714661133735017342 0ustar jamespagejamespage{"files":{"CHANGELOG.md":"cc4e490ceb3a92be753f3ffee297921a341faf67b304e1e0e63833aba4c3d529","Cargo.lock":"57fb641115940cc1870a3460ebb53ca921461c38894a68e62bf0fc4438825fa8","Cargo.toml":"b0c4dcab027bb78093c9cd0e643b778303bb113fed7f3ab251252141d2b6735d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"2331182c8b5a6971fd0d04a0ca711d5839e93b3de6b2003108940a8c93850aaf","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/lazy_static.rs":"8bca1b264da21eceb1ccaf30477fc941bc71bedd030f1c6982ed3a7804abfb4f","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_cs.rs":"32ee2c252d176726e62cf1f81a270d3738cb06784c47d4064e62350d9f7672cd","src/imp_pl.rs":"6a97f60a91ab44192dcaf028e987f6be0328b5d4d69216dcdaec93bc39401f68","src/imp_std.rs":"1c130f83be5c1360dfd379911f97797c1e4c730b845f465c8c2630467ca317d2","src/lib.rs":"60fe685113e11203ec32876b5dad9c8e1eb705da5854eff8f044d3f4651a7d0f","src/race.rs":"e8400987cc44b3e4b1a321d1e0506df07be7034a7d1c16be641dc75b44fee05c","tests/it/main.rs":"e6e9987e053af84b9d76052602995b1e777efb5bc06cd5f49009e6f03b18626c","tests/it/race.rs":"8dfe38563b6d0be890ab076be1fc1122d41a7c7792354cd7f60bc4454666b968","tests/it/race_once_box.rs":"1c2fe9e2988ec38d60c93c797fceb4c7a65d1b2e48a6a1e78db78ab91388e844","tests/it/sync_lazy.rs":"a36c5d66340b3d6d20aad331a499858a2125dfdfd624c5bf3b4b06a0b157c75c","tests/it/sync_once_cell.rs":"0d04beeb394eb53dd3fc0309fcfc382d56350e72b89d22356e0047d6c7bfef58","tests/it/unsync_lazy.rs":"51a1ffd411770d1e32399ec23feb5f61be362bbed34e100eb7509f8496224e1a","tests/it/unsync_once_cell.rs":"82b72936d7bd4090db25cfc543c01ef3206d6917ac56f09d17d4110a65deb30a"},"package":"3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"}once_cell/Cargo.lock0000644000175000017500000001135414661133735015375 0ustar jamespagejamespage# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" dependencies = [ "memchr", ] [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "critical-section" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" [[package]] name = "libc" version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "once_cell" version = "1.19.0" dependencies = [ "critical-section", "parking_lot_core", "portable-atomic", "regex", ] [[package]] name = "parking_lot_core" version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-sys", ] [[package]] name = "portable-atomic" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "redox_syscall" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "windows-sys" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" once_cell/bors.toml0000644000175000017500000000006214661133735015324 0ustar jamespagejamespagestatus = [ "Rust" ] delete_merged_branches = true portable-atomic/0000775000175000017500000000000014661133735014625 5ustar jamespagejamespageportable-atomic/no_atomic.rs0000644000175000017500000000444314661133735017146 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // This file is @generated by no_atomic.sh. // It is not intended for manual editing. // Note: This is the list as of nightly-2022-02-10. We don't refer to this in // nightly-2022-02-11+ because feature(cfg_target_has_atomic) stabilized. #[rustfmt::skip] static NO_ATOMIC_CAS: &[&str] = &[ "avr-unknown-gnu-atmega328", "bpfeb-unknown-none", "bpfel-unknown-none", "msp430-none-elf", "riscv32i-unknown-none-elf", "riscv32imc-unknown-none-elf", "thumbv4t-none-eabi", "thumbv6m-none-eabi", ]; // Note: This is the list as of nightly-2022-02-10. We don't refer to this in // nightly-2022-02-11+ because feature(cfg_target_has_atomic) stabilized. #[rustfmt::skip] static NO_ATOMIC_64: &[&str] = &[ "arm-linux-androideabi", "armebv7r-none-eabi", "armebv7r-none-eabihf", "armv4t-unknown-linux-gnueabi", "armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-musleabi", "armv5te-unknown-linux-uclibceabi", "armv6k-nintendo-3ds", "armv7r-none-eabi", "armv7r-none-eabihf", "avr-unknown-gnu-atmega328", "hexagon-unknown-linux-musl", "m68k-unknown-linux-gnu", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips-unknown-linux-uclibc", "mipsel-sony-psp", "mipsel-unknown-linux-gnu", "mipsel-unknown-linux-musl", "mipsel-unknown-linux-uclibc", "mipsel-unknown-none", "mipsisa32r6-unknown-linux-gnu", "mipsisa32r6el-unknown-linux-gnu", "msp430-none-elf", "powerpc-unknown-freebsd", "powerpc-unknown-linux-gnu", "powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-musl", "powerpc-unknown-netbsd", "powerpc-unknown-openbsd", "powerpc-wrs-vxworks", "powerpc-wrs-vxworks-spe", "riscv32gc-unknown-linux-gnu", "riscv32gc-unknown-linux-musl", "riscv32i-unknown-none-elf", "riscv32imac-unknown-none-elf", "riscv32imc-esp-espidf", "riscv32imc-unknown-none-elf", "thumbv4t-none-eabi", "thumbv6m-none-eabi", "thumbv7em-none-eabi", "thumbv7em-none-eabihf", "thumbv7m-none-eabi", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", ]; #[rustfmt::skip] static NO_ATOMIC: &[&str] = &[ "bpfeb-unknown-none", "bpfel-unknown-none", "mipsel-sony-psx", ]; portable-atomic/build.rs0000644000175000017500000005416114661133735016277 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // The rustc-cfg emitted by the build script are *not* public API. #![allow(clippy::match_same_arms, clippy::needless_pass_by_value)] #[path = "version.rs"] mod version; use version::{rustc_version, Version}; use std::{env, str}; include!("no_atomic.rs"); fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=no_atomic.rs"); println!("cargo:rerun-if-changed=version.rs"); #[cfg(feature = "unsafe-assume-single-core")] println!("cargo:rustc-cfg=portable_atomic_unsafe_assume_single_core"); #[cfg(feature = "s-mode")] println!("cargo:rustc-cfg=portable_atomic_s_mode"); #[cfg(feature = "force-amo")] println!("cargo:rustc-cfg=portable_atomic_force_amo"); #[cfg(feature = "disable-fiq")] println!("cargo:rustc-cfg=portable_atomic_disable_fiq"); let target = &*env::var("TARGET").expect("TARGET not set"); let target_arch = &*env::var("CARGO_CFG_TARGET_ARCH").expect("CARGO_CFG_TARGET_ARCH not set"); let target_os = &*env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS not set"); // HACK: If --target is specified, rustflags is not applied to the build // script itself, so the build script will not be rerun when these are changed. // // Ideally, the build script should be rebuilt when CARGO_ENCODED_RUSTFLAGS // is changed, but since it is an environment variable set by cargo, // as of 1.62.0-nightly, specifying it as rerun-if-env-changed does not work. println!("cargo:rerun-if-env-changed=CARGO_ENCODED_RUSTFLAGS"); println!("cargo:rerun-if-env-changed=RUSTFLAGS"); println!("cargo:rerun-if-env-changed=CARGO_BUILD_RUSTFLAGS"); let mut target_upper = target.replace(|c: char| c == '-' || c == '.', "_"); target_upper.make_ascii_uppercase(); println!("cargo:rerun-if-env-changed=CARGO_TARGET_{}_RUSTFLAGS", target_upper); let version = match rustc_version() { Some(version) => version, None => { println!( "cargo:warning={}: unable to determine rustc version; assuming latest stable rustc (1.{})", env!("CARGO_PKG_NAME"), Version::LATEST.minor ); Version::LATEST } }; // Note that this is `no_`*, not `has_*`. This allows treating as the latest // stable rustc is used when the build script doesn't run. This is useful // for non-cargo build systems that don't run the build script. // atomic_min_max stabilized in Rust 1.45 (nightly-2020-05-30): https://github.com/rust-lang/rust/pull/72324 if !version.probe(45, 2020, 5, 29) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_min_max"); } // track_caller stabilized in Rust 1.46 (nightly-2020-07-02): https://github.com/rust-lang/rust/pull/72445 if !version.probe(46, 2020, 7, 1) { println!("cargo:rustc-cfg=portable_atomic_no_track_caller"); } // unsafe_op_in_unsafe_fn stabilized in Rust 1.52 (nightly-2021-03-11): https://github.com/rust-lang/rust/pull/79208 if !version.probe(52, 2021, 3, 10) { println!("cargo:rustc-cfg=portable_atomic_no_unsafe_op_in_unsafe_fn"); } // https://github.com/rust-lang/rust/pull/84662 merged in Rust 1.56 (nightly-2021-08-02). if !version.probe(56, 2021, 8, 1) { println!("cargo:rustc-cfg=portable_atomic_no_core_unwind_safe"); } // const_raw_ptr_deref stabilized in Rust 1.58 (nightly-2021-11-15): https://github.com/rust-lang/rust/pull/89551 if !version.probe(58, 2021, 11, 14) { println!("cargo:rustc-cfg=portable_atomic_no_const_raw_ptr_deref"); } // https://github.com/rust-lang/rust/pull/98383 merged in Rust 1.64 (nightly-2022-07-19). if !version.probe(64, 2022, 7, 18) { println!("cargo:rustc-cfg=portable_atomic_no_stronger_failure_ordering"); } // https://github.com/rust-lang/rust/pull/114790 merged in nightly-2023-08-24 if !version.probe(74, 2023, 8, 23) { println!("cargo:rustc-cfg=portable_atomic_no_asm_maybe_uninit"); } // asm stabilized in Rust 1.59 (nightly-2021-12-16): https://github.com/rust-lang/rust/pull/91728 let no_asm = !version.probe(59, 2021, 12, 15); if no_asm { if version.nightly && version.probe(46, 2020, 6, 20) && ((target_arch != "x86" && target_arch != "x86_64") || version.llvm >= 10) && is_allowed_feature("asm") { // This feature was added in Rust 1.45 (nightly-2020-05-20), but // concat! in asm! requires Rust 1.46 (nightly-2020-06-21). // x86 intel syntax requires LLVM 10 (since Rust 1.53, the minimum // external LLVM version is 10+: https://github.com/rust-lang/rust/pull/83387). // The part of this feature we use has not been changed since nightly-2020-06-21 // until it was stabilized in nightly-2021-12-16, so it can be safely enabled in // nightly, which is older than nightly-2021-12-16. println!("cargo:rustc-cfg=portable_atomic_unstable_asm"); } println!("cargo:rustc-cfg=portable_atomic_no_asm"); } // feature(cfg_target_has_atomic) stabilized in Rust 1.60 (nightly-2022-02-11): https://github.com/rust-lang/rust/pull/93824 if !version.probe(60, 2022, 2, 10) { if version.nightly && version.probe(40, 2019, 10, 13) && is_allowed_feature("cfg_target_has_atomic") { // This feature has not been changed since the change in Rust 1.40 (nightly-2019-10-14) // until it was stabilized in nightly-2022-02-11, so it can be safely enabled in // nightly, which is older than nightly-2022-02-11. println!("cargo:rustc-cfg=portable_atomic_unstable_cfg_target_has_atomic"); } else { println!("cargo:rustc-cfg=portable_atomic_no_cfg_target_has_atomic"); let target = &*convert_custom_linux_target(target); if NO_ATOMIC_CAS.contains(&target) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_cas"); } if NO_ATOMIC_64.contains(&target) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_64"); } else { // Otherwise, assuming `"max-atomic-width" == 64` or `"max-atomic-width" == 128`. } } } // We don't need to use convert_custom_linux_target here because all linux targets have atomics. if NO_ATOMIC.contains(&target) { println!("cargo:rustc-cfg=portable_atomic_no_atomic_load_store"); } if version.llvm >= 16 { println!("cargo:rustc-cfg=portable_atomic_llvm_16"); } if version.nightly { // `cfg(sanitize = "..")` is not stabilized. let sanitize = env::var("CARGO_CFG_SANITIZE").unwrap_or_default(); if sanitize.contains("thread") { // Most kinds of sanitizers are not compatible with asm // (https://github.com/google/sanitizers/issues/192), // but it seems that ThreadSanitizer is the only one that can cause // false positives in our code. println!("cargo:rustc-cfg=portable_atomic_sanitize_thread"); } // https://github.com/rust-lang/rust/pull/93868 merged in Rust 1.60 (nightly-2022-02-13). // https://github.com/rust-lang/rust/pull/111331 merged in Rust 1.71 (nightly-2023-05-09). if !no_asm && (target_arch == "powerpc64" && version.probe(60, 2022, 2, 12) || target_arch == "s390x" && version.probe(71, 2023, 5, 8)) && is_allowed_feature("asm_experimental_arch") { println!("cargo:rustc-cfg=portable_atomic_unstable_asm_experimental_arch"); } } let is_macos = target_os == "macos"; let is_apple = is_macos || target_os == "ios" || target_os == "tvos" || target_os == "watchos"; match target_arch { "x86_64" => { // cmpxchg16b_target_feature stabilized in Rust 1.69 (nightly-2023-03-01): https://github.com/rust-lang/rust/pull/106774 if !version.probe(69, 2023, 2, 28) { if version.nightly && is_allowed_feature("cmpxchg16b_target_feature") { // This feature has not been changed since 1.33 // (https://github.com/rust-lang/rust/commit/fbb56bcf44d28e65a9495decf091b6d0386e540c) // until it was stabilized in nightly-2023-03-01, so it can be safely enabled in // nightly, which is older than nightly-2023-03-01. println!("cargo:rustc-cfg=portable_atomic_unstable_cmpxchg16b_target_feature"); } else { println!("cargo:rustc-cfg=portable_atomic_no_cmpxchg16b_target_feature"); } } // For Miri and ThreadSanitizer. // https://github.com/rust-lang/rust/pull/109359 (includes https://github.com/rust-lang/stdarch/pull/1358) merged in Rust 1.70 (nightly-2023-03-24). if version.nightly && !version.probe(70, 2023, 3, 23) { println!("cargo:rustc-cfg=portable_atomic_unstable_cmpxchg16b_intrinsic"); } // x86_64 Apple targets always support CMPXCHG16B: // https://github.com/rust-lang/rust/blob/1.70.0/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs#L8 // https://github.com/rust-lang/rust/blob/1.70.0/compiler/rustc_target/src/spec/apple_base.rs#L69-L70 // Script to get targets that support cmpxchg16b by default: // $ (for target in $(rustc --print target-list); do [[ "${target}" == "x86_64"* ]] && rustc --print cfg --target "${target}" | grep -q cmpxchg16b && echo "${target}"; done) let has_cmpxchg16b = is_apple; // LLVM recognizes this also as cx16 target feature: https://godbolt.org/z/r8zWGcMhd // However, it is unlikely that rustc will support that name, so we ignore it. // cmpxchg16b_target_feature stabilized in Rust 1.69. target_feature_if("cmpxchg16b", has_cmpxchg16b, &version, Stable(69)); } "aarch64" => { // For Miri and ThreadSanitizer. // https://github.com/rust-lang/rust/pull/97423 merged in Rust 1.64 (nightly-2022-06-30). if version.nightly && version.probe(64, 2022, 6, 29) { println!("cargo:rustc-cfg=portable_atomic_new_atomic_intrinsics"); } // aarch64 macOS always supports FEAT_LSE and FEAT_LSE2 because it is armv8.5-a: // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/include/llvm/TargetParser/AArch64TargetParser.h#L494 let mut has_lse = is_macos; // FEAT_LSE2 doesn't imply FEAT_LSE. FEAT_LSE128 implies FEAT_LSE but not FEAT_LSE2. // As of rustc 1.70, target_feature "lse2"/"lse128"/"rcpc3" is not available on rustc side: // https://github.com/rust-lang/rust/blob/1.70.0/compiler/rustc_codegen_ssa/src/target_features.rs#L58 target_feature_if("lse2", is_macos, &version, Unavailable); // LLVM supports FEAT_LRCPC3 and FEAT_LSE128 on LLVM 16+: // https://github.com/llvm/llvm-project/commit/a6aaa969f7caec58a994142f8d855861cf3a1463 // https://github.com/llvm/llvm-project/commit/7fea6f2e0e606e5339c3359568f680eaf64aa306 has_lse |= target_feature_if("lse128", false, &version, Unavailable); target_feature_if("rcpc3", false, &version, Unavailable); // aarch64_target_feature stabilized in Rust 1.61. target_feature_if("lse", has_lse, &version, Stable(61)); // As of Apple M1/M1 Pro, on Apple hardware, CAS loop-based RMW is much slower than LL/SC // loop-based RMW: https://github.com/taiki-e/portable-atomic/pull/89 if is_apple || target_cpu().map_or(false, |cpu| cpu.starts_with("apple-")) { println!("cargo:rustc-cfg=portable_atomic_ll_sc_rmw"); } } "arm" => { // For non-Linux/Android pre-v6 ARM (tier 3) with unsafe_assume_single_core enabled. // feature(isa_attribute) stabilized in Rust 1.67 (nightly-2022-11-06): https://github.com/rust-lang/rust/pull/102458 if version.nightly && !version.probe(67, 2022, 11, 5) { println!("cargo:rustc-cfg=portable_atomic_unstable_isa_attribute"); } // #[cfg(target_feature = "v7")] and others don't work on stable. // armv7-unknown-linux-gnueabihf // ^^ let mut subarch = strip_prefix(target, "arm").or_else(|| strip_prefix(target, "thumb")).unwrap(); subarch = strip_prefix(subarch, "eb").unwrap_or(subarch); // ignore endianness subarch = subarch.split('-').next().unwrap(); // ignore vender/os/env subarch = subarch.split('.').next().unwrap(); // ignore .base/.main suffix let mut known = true; // See https://github.com/taiki-e/atomic-maybe-uninit/blob/HEAD/build.rs for details let mut is_mclass = false; match subarch { "v7" | "v7a" | "v7neon" | "v7s" | "v7k" | "v8a" | "v9a" => {} // aclass "v6m" | "v7em" | "v7m" | "v8m" => is_mclass = true, "v7r" | "v8r" => {} // rclass // arm-linux-androideabi is v5te // https://github.com/rust-lang/rust/blob/1.70.0/compiler/rustc_target/src/spec/arm_linux_androideabi.rs#L11-L12 _ if target == "arm-linux-androideabi" => subarch = "v5te", // armeb-unknown-linux-gnueabi is v8 & aclass // https://github.com/rust-lang/rust/blob/1.70.0/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs#L12 _ if target == "armeb-unknown-linux-gnueabi" => subarch = "v8", // v6 targets other than v6m don't have *class target feature. "" | "v6" | "v6k" => subarch = "v6", // Other targets don't have *class target feature. "v4t" | "v5te" => {} _ => { known = false; println!( "cargo:warning={}: unrecognized arm subarch: {}", env!("CARGO_PKG_NAME"), target ); } } target_feature_if("mclass", is_mclass, &version, Nightly); let v6 = known && (subarch.starts_with("v6") || subarch.starts_with("v7") || subarch.starts_with("v8") || subarch.starts_with("v9")); target_feature_if("v6", v6, &version, Nightly); } "powerpc64" => { // For Miri and ThreadSanitizer. if version.nightly && version.llvm >= 15 { println!("cargo:rustc-cfg=portable_atomic_llvm_15"); } let target_endian = env::var("CARGO_CFG_TARGET_ENDIAN").expect("CARGO_CFG_TARGET_ENDIAN not set"); // powerpc64le is pwr8+ by default // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/PowerPC/PPC.td#L663 // See also https://github.com/rust-lang/rust/issues/59932 let mut has_pwr8_features = target_endian == "little"; // https://github.com/llvm/llvm-project/commit/549e118e93c666914a1045fde38a2cac33e1e445 if let Some(cpu) = &target_cpu() { if let Some(mut cpu_version) = strip_prefix(cpu, "pwr") { cpu_version = strip_suffix(cpu_version, "x").unwrap_or(cpu_version); // for pwr5x and pwr6x if let Ok(cpu_version) = cpu_version.parse::() { has_pwr8_features = cpu_version >= 8; } } else { // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/PowerPC/PPC.td#L663 // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/PowerPC/PPC.td#L445-L447 has_pwr8_features = cpu == "ppc64le" || cpu == "future"; } } // Note: As of rustc 1.70, target_feature "quadword-atomics" is not available on rustc side: // https://github.com/rust-lang/rust/blob/1.70.0/compiler/rustc_codegen_ssa/src/target_features.rs#L226 // lqarx and stqcx. target_feature_if("quadword-atomics", has_pwr8_features, &version, Unavailable); } "s390x" => { // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/SystemZ/SystemZFeatures.td let mut arch9_features = false; // z196+ let mut arch13_features = false; // z15+ if let Some(cpu) = target_cpu() { // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/SystemZ/SystemZProcessors.td match &*cpu { "arch9" | "z196" | "arch10" | "zEC12" | "arch11" | "z13" | "arch12" | "z14" => { arch9_features = true; } "arch13" | "z15" | "arch14" | "z16" => { arch9_features = true; arch13_features = true; } _ => {} } } // Note: As of rustc 1.70, target_feature "fast-serialization"/"load-store-on-cond"/"distinct-ops"/"miscellaneous-extensions-3" is not available on rustc side: // https://github.com/rust-lang/rust/blob/1.70.0/compiler/rustc_codegen_ssa/src/target_features.rs // bcr 14,0 target_feature_if("fast-serialization", arch9_features, &version, Unavailable); // {l,st}oc{,g}{,r} target_feature_if("load-store-on-cond", arch9_features, &version, Unavailable); // {al,sl,n,o,x}{,g}rk target_feature_if("distinct-ops", arch9_features, &version, Unavailable); // nand (nnr{,g}k), select (sel{,g}r), etc. target_feature_if("miscellaneous-extensions-3", arch13_features, &version, Unavailable); } _ => {} } } enum Availability { Stable(u32), Nightly, Unavailable, } use Availability::{Nightly, Stable, Unavailable}; fn target_feature_if( name: &str, mut has_target_feature: bool, version: &Version, availability: Availability, ) -> bool { // HACK: Currently, it seems that the only way to handle unstable target // features on the stable is to parse the `-C target-feature` in RUSTFLAGS. // // - #[cfg(target_feature = "unstable_target_feature")] doesn't work on stable. // - CARGO_CFG_TARGET_FEATURE excludes unstable target features on stable. // // As mentioned in the [RFC2045], unstable target features are also passed to LLVM // (e.g., https://godbolt.org/z/TfaEx95jc), so this hack works properly on stable. // // [RFC2045]: https://rust-lang.github.io/rfcs/2045-target-feature.html#backend-compilation-options match availability { // In these cases, cfg(target_feature = "...") would work, so skip emitting our own target_feature cfg. Availability::Stable(stabilized) if version.nightly || version.minor >= stabilized => { return false } Availability::Nightly if version.nightly => return false, _ => {} } if let Some(rustflags) = env::var_os("CARGO_ENCODED_RUSTFLAGS") { for mut flag in rustflags.to_string_lossy().split('\x1f') { flag = strip_prefix(flag, "-C").unwrap_or(flag); if let Some(flag) = strip_prefix(flag, "target-feature=") { for s in flag.split(',') { // TODO: Handles cases where a specific target feature // implicitly enables another target feature. match (s.as_bytes().first(), s.as_bytes().get(1..)) { (Some(b'+'), Some(f)) if f == name.as_bytes() => has_target_feature = true, (Some(b'-'), Some(f)) if f == name.as_bytes() => has_target_feature = false, _ => {} } } } } } if has_target_feature { println!("cargo:rustc-cfg=portable_atomic_target_feature=\"{}\"", name); } has_target_feature } fn target_cpu() -> Option { let rustflags = env::var_os("CARGO_ENCODED_RUSTFLAGS")?; let rustflags = rustflags.to_string_lossy(); let mut cpu = None; for mut flag in rustflags.split('\x1f') { flag = strip_prefix(flag, "-C").unwrap_or(flag); if let Some(flag) = strip_prefix(flag, "target-cpu=") { cpu = Some(flag); } } cpu.map(str::to_owned) } fn is_allowed_feature(name: &str) -> bool { // allowed by default let mut allowed = true; if let Some(rustflags) = env::var_os("CARGO_ENCODED_RUSTFLAGS") { for mut flag in rustflags.to_string_lossy().split('\x1f') { flag = strip_prefix(flag, "-Z").unwrap_or(flag); if let Some(flag) = strip_prefix(flag, "allow-features=") { // If it is specified multiple times, the last value will be preferred. allowed = flag.split(',').any(|allowed| allowed == name); } } } allowed } // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.14/build-common.rs. // // The target triplets have the form of 'arch-vendor-system'. // // When building for Linux (e.g. the 'system' part is // 'linux-something'), replace the vendor with 'unknown' // so that mapping to rust standard targets happens correctly. fn convert_custom_linux_target(target: &str) -> String { let mut parts: Vec<&str> = target.split('-').collect(); let system = parts.get(2); if system == Some(&"linux") { parts[1] = "unknown"; } parts.join("-") } // str::strip_prefix requires Rust 1.45 #[must_use] fn strip_prefix<'a>(s: &'a str, pat: &str) -> Option<&'a str> { if s.starts_with(pat) { Some(&s[pat.len()..]) } else { None } } // str::strip_suffix requires Rust 1.45 #[must_use] fn strip_suffix<'a>(s: &'a str, pat: &str) -> Option<&'a str> { if s.ends_with(pat) { Some(&s[..s.len() - pat.len()]) } else { None } } portable-atomic/README.md0000644000175000017500000003333014661133735016104 0ustar jamespagejamespage# portable-atomic [![crates.io](https://img.shields.io/crates/v/portable-atomic?style=flat-square&logo=rust)](https://crates.io/crates/portable-atomic) [![docs.rs](https://img.shields.io/badge/docs.rs-portable--atomic-blue?style=flat-square&logo=docs.rs)](https://docs.rs/portable-atomic) [![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue?style=flat-square)](#license) [![rustc](https://img.shields.io/badge/rustc-1.34+-blue?style=flat-square&logo=rust)](https://www.rust-lang.org) [![build status](https://img.shields.io/github/actions/workflow/status/taiki-e/portable-atomic/ci.yml?branch=main&style=flat-square&logo=github)](https://github.com/taiki-e/portable-atomic/actions) [![build status](https://img.shields.io/cirrus/github/taiki-e/portable-atomic/main?style=flat-square&logo=cirrusci)](https://cirrus-ci.com/github/taiki-e/portable-atomic) Portable atomic types including support for 128-bit atomics, atomic float, etc. - Provide all atomic integer types (`Atomic{I,U}{8,16,32,64}`) for all targets that can use atomic CAS. (i.e., all targets that can use `std`, and most no-std targets) - Provide `AtomicI128` and `AtomicU128`. - Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float)) - Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR) - Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise) - Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485). - Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), [`from_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.from_ptr) and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+. - Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc. ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] portable-atomic = "1" ``` The default features are mainly for users who use atomics larger than the pointer width. If you don't need them, disabling the default features may reduce code size and compile time slightly. ```toml [dependencies] portable-atomic = { version = "1", default-features = false } ``` If your crate supports no-std environment and requires atomic CAS, enabling the `require-cas` feature will allow the `portable-atomic` to display helpful error messages to users on targets requiring additional action on the user side to provide atomic CAS. ```toml [dependencies] portable-atomic = { version = "1.3", default-features = false, features = ["require-cas"] } ``` *Compiler support: requires rustc 1.34+* ## 128-bit atomics support Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), aarch64 (Rust 1.59+), powerpc64 (nightly only), and s390x (nightly only), otherwise the fallback implementation is used. On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg. They are usually implemented using inline assembly, and when using Miri or ThreadSanitizer that do not support inline assembly, core intrinsics are used instead of inline assembly if possible. See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md) for details. ## Optional features - **`fallback`** *(enabled by default)*
Enable fallback implementations. Disabling this allows only atomic types for which the platform natively supports atomic operations. - **`float`**
Provide `AtomicF{32,64}`. Note that most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. ([GPU targets have atomic instructions for float, so we plan to use these instructions for GPU targets in the future.](https://github.com/taiki-e/portable-atomic/issues/34)) - **`std`**
Use `std`. - **`require-cas`**
Emit compile error if atomic CAS is not available. See [Usage](#usage) section and [#100](https://github.com/taiki-e/portable-atomic/pull/100) for more. - **`serde`**
Implement `serde::{Serialize,Deserialize}` for atomic types. Note: - The MSRV when this feature is enabled depends on the MSRV of [serde]. - **`critical-section`**
When this feature is enabled, this crate uses [critical-section] to provide atomic CAS for targets where it is not natively available. When enabling it, you should provide a suitable critical section implementation for the current target, see the [critical-section] documentation for details on how to do so. `critical-section` support is useful to get atomic CAS when the [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) can't be used, such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts needs extra care due to e.g. real-time requirements. Note that with the `critical-section` feature, critical sections are taken for all atomic operations, while with [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) some operations don't require disabling interrupts (loads and stores, but additionally on MSP430 `add`, `sub`, `and`, `or`, `xor`, `not`). Therefore, for better performance, if all the `critical-section` implementation for your target does is disable interrupts, prefer using `unsafe-assume-single-core` feature instead. Note: - The MSRV when this feature is enabled depends on the MSRV of [critical-section]. - It is usually *not* recommended to always enable this feature in dependencies of the library. Enabling this feature will prevent the end user from having the chance to take advantage of other (potentially) efficient implementations ([Implementations provided by `unsafe-assume-single-core` feature, default implementations on MSP430 and AVR](#optional-features-unsafe-assume-single-core), implementation proposed in [#60], etc. Other systems may also be supported in the future). The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where other implementations are known not to work.) As an example, the end-user's `Cargo.toml` that uses a crate that provides a critical-section implementation and a crate that depends on portable-atomic as an option would be expected to look like this: ```toml [dependencies] portable-atomic = { version = "1", default-features = false, features = ["critical-section"] } crate-provides-critical-section-impl = "..." crate-uses-portable-atomic-as-feature = { version = "...", features = ["portable-atomic"] } ``` - **`unsafe-assume-single-core`**
Assume that the target is single-core. When this feature is enabled, this crate provides atomic CAS for targets where atomic CAS is not available in the standard library by disabling interrupts. This feature is `unsafe`, and note the following safety requirements: - Enabling this feature for multi-core systems is always **unsound**. - This uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode. Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent. The following are known cases: - On pre-v6 ARM, this disables only IRQs by default. For many systems (e.g., GBA) this is enough. If the system need to disable both IRQs and FIQs, you need to enable the `disable-fiq` feature together. - On RISC-V without A-extension, this generates code for machine-mode (M-mode) by default. If you enable the `s-mode` together, this generates code for supervisor-mode (S-mode). In particular, `qemu-system-riscv*` uses [OpenSBI](https://github.com/riscv-software-src/opensbi) as the default firmware. See also [the `interrupt` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md). Consider using the [`critical-section` feature](#optional-features-critical-section) for systems that cannot use this feature. It is **very strongly discouraged** to enable this feature in libraries that depend on `portable-atomic`. The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer targeting a single-core chip.) ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa are currently supported. Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this feature. Enabling this feature for targets that have atomic CAS will result in a compile error. Feel free to submit an issue if your target is not supported yet. ## Optional cfg One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags): ```toml # .cargo/config.toml [target.] rustflags = ["--cfg", "portable_atomic_no_outline_atomics"] ``` Or set environment variable: ```sh RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... ``` - **`--cfg portable_atomic_unsafe_assume_single_core`**
Since 1.4.0, this cfg is an alias of [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core). Originally, we were providing these as cfgs instead of features, but based on a strong request from the embedded ecosystem, we have agreed to provide them as features as well. See [#94](https://github.com/taiki-e/portable-atomic/pull/94) for more. - **`--cfg portable_atomic_no_outline_atomics`**
Disable dynamic dispatching by run-time CPU feature detection. If dynamic dispatching by run-time CPU feature detection is enabled, it allows maintaining support for older CPUs while using features that are not supported on older CPUs, such as CMPXCHG16B (x86_64) and FEAT_LSE (aarch64). Note: - Dynamic detection is currently only enabled in Rust 1.59+ for aarch64, in Rust 1.59+ (AVX) or 1.69+ (CMPXCHG16B) for x86_64, nightly only for powerpc64 (disabled by default), otherwise it works the same as when this cfg is set. - If the required target features are enabled at compile-time, the atomic operations are inlined. - This is compatible with no-std (as with all features except `std`). - On some targets, run-time detection is disabled by default mainly for compatibility with older versions of operating systems or incomplete build environments, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.) - Some aarch64 targets enable LLVM's `outline-atomics` target feature by default, so if you set this cfg, you may want to disable that as well. (portable-atomic's outline-atomics does not depend on the compiler-rt symbols, so even if you need to disable LLVM's outline-atomics, you may not need to disable portable-atomic's outline-atomics.) See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md). ## Related Projects - [atomic-maybe-uninit]: Atomic operations on potentially uninitialized integers. - [atomic-memcpy]: Byte-wise atomic memcpy. [#60]: https://github.com/taiki-e/portable-atomic/issues/60 [atomic-maybe-uninit]: https://github.com/taiki-e/atomic-maybe-uninit [atomic-memcpy]: https://github.com/taiki-e/atomic-memcpy [critical-section]: https://github.com/rust-embedded/critical-section [rust-lang/rust#100650]: https://github.com/rust-lang/rust/issues/100650 [serde]: https://github.com/serde-rs/serde ## License Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or [MIT license](LICENSE-MIT) at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. portable-atomic/LICENSE-APACHE0000644000175000017500000002367614661133735016565 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS portable-atomic/Cargo.toml0000644000175000017500000000617014661133735016557 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.34" name = "portable-atomic" version = "1.6.0" exclude = [ "/.*", "/tools", "/target-specs", "/DEVELOPMENT.md", ] description = """ Portable atomic types including support for 128-bit atomics, atomic float, etc. """ readme = "README.md" keywords = ["atomic"] categories = [ "concurrency", "embedded", "hardware-support", "no-std", "no-std::no-alloc", ] license = "Apache-2.0 OR MIT" repository = "https://github.com/taiki-e/portable-atomic" [package.metadata.cargo_check_external_types] allowed_external_types = ["serde::*"] [package.metadata.docs.rs] features = [ "float", "std", "serde", "critical-section", ] rustdoc-args = [ "--cfg", "portable_atomic_doc_cfg", ] targets = ["x86_64-unknown-linux-gnu"] [lib] doc-scrape-examples = false [dependencies.critical-section] version = "1" optional = true [dependencies.serde] version = "1.0.103" optional = true default-features = false [dev-dependencies.build-context] version = "0.1" [dev-dependencies.crossbeam-utils] version = "0.8" [dev-dependencies.fastrand] version = "2" [dev-dependencies.paste] version = "1" [dev-dependencies.sptr] version = "0.3" [dev-dependencies.static_assertions] version = "1" [features] default = ["fallback"] disable-fiq = [] fallback = [] float = [] force-amo = [] require-cas = [] s-mode = [] std = [] unsafe-assume-single-core = [] [lints.clippy] all = "warn" as_ptr_cast_mut = "warn" default_union_representation = "warn" inline_asm_x86_att_syntax = "warn" pedantic = "warn" trailing_empty_array = "warn" transmute_undefined_repr = "warn" undocumented_unsafe_blocks = "warn" [lints.clippy.borrow_as_ptr] level = "allow" priority = 1 [lints.clippy.doc_markdown] level = "allow" priority = 1 [lints.clippy.float_cmp] level = "allow" priority = 1 [lints.clippy.manual_assert] level = "allow" priority = 1 [lints.clippy.manual_range_contains] level = "allow" priority = 1 [lints.clippy.missing_errors_doc] level = "allow" priority = 1 [lints.clippy.module_name_repetitions] level = "allow" priority = 1 [lints.clippy.similar_names] level = "allow" priority = 1 [lints.clippy.single_match] level = "allow" priority = 1 [lints.clippy.single_match_else] level = "allow" priority = 1 [lints.clippy.struct_excessive_bools] level = "allow" priority = 1 [lints.clippy.too_many_arguments] level = "allow" priority = 1 [lints.clippy.too_many_lines] level = "allow" priority = 1 [lints.clippy.type_complexity] level = "allow" priority = 1 [lints.rust] improper_ctypes = "warn" improper_ctypes_definitions = "warn" non_ascii_idents = "warn" rust_2018_idioms = "warn" single_use_lifetimes = "warn" unreachable_pub = "warn" portable-atomic/LICENSE-MIT0000644000175000017500000000177714661133735016273 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. portable-atomic/src/0000775000175000017500000000000014661133735015414 5ustar jamespagejamespageportable-atomic/src/imp/0000775000175000017500000000000014661133735016201 5ustar jamespagejamespageportable-atomic/src/imp/core_atomic.rs0000644000175000017500000005007214661133735021035 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Wrap the standard library's atomic types in newtype. // // This is not a reexport, because we want to backport changes like // https://github.com/rust-lang/rust/pull/98383 to old compilers. use core::{cell::UnsafeCell, marker::PhantomData, sync::atomic::Ordering}; // core::panic::RefUnwindSafe is only available on Rust 1.56+, so on pre-1.56 // Rust, we implement RefUnwindSafe when "std" feature is enabled. // However, on pre-1.56 Rust, the standard library's atomic types implement // RefUnwindSafe when "linked to std", and that's behavior that our other atomic // implementations can't emulate, so use PhantomData to match // conditions where our other atomic implementations implement RefUnwindSafe. // If we do not do this, for example, downstream that is only tested on x86_64 // may incorrectly assume that AtomicU64 always implements RefUnwindSafe even on // older rustc, and may be broken on platforms where std AtomicU64 is not available. struct NotRefUnwindSafe(UnsafeCell<()>); // SAFETY: this is a marker type and we'll never access the value. unsafe impl Sync for NotRefUnwindSafe {} #[repr(transparent)] pub(crate) struct AtomicPtr { inner: core::sync::atomic::AtomicPtr, // Prevent RefUnwindSafe from being propagated from the std atomic type. See NotRefUnwindSafe for more. _not_ref_unwind_safe: PhantomData, } impl AtomicPtr { #[inline] pub(crate) const fn new(v: *mut T) -> Self { Self { inner: core::sync::atomic::AtomicPtr::new(v), _not_ref_unwind_safe: PhantomData } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::is_always_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { true } #[inline] pub(crate) fn get_mut(&mut self) -> &mut *mut T { self.inner.get_mut() } #[inline] pub(crate) fn into_inner(self) -> *mut T { self.inner.into_inner() } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> *mut T { crate::utils::assert_load_ordering(order); // for track_caller (compiler can omit double check) self.inner.load(order) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, ptr: *mut T, order: Ordering) { crate::utils::assert_store_ordering(order); // for track_caller (compiler can omit double check) self.inner.store(ptr, order); } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; #[inline] pub(crate) const fn as_ptr(&self) -> *mut *mut T { // SAFETY: Self is #[repr(C)] and internally UnsafeCell<*mut T>. // See also https://github.com/rust-lang/rust/pull/66705 and // https://github.com/rust-lang/rust/issues/66136#issuecomment-557867116. unsafe { (*(self as *const Self as *const UnsafeCell<*mut T>)).get() } } } } #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl AtomicPtr { #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange(current, new, success, failure) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange_weak(current, new, success, failure) } } impl core::ops::Deref for AtomicPtr { type Target = core::sync::atomic::AtomicPtr; #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn deref(&self) -> &Self::Target { &self.inner } } macro_rules! atomic_int { ($atomic_type:ident, $int_type:ident) => { #[repr(transparent)] pub(crate) struct $atomic_type { inner: core::sync::atomic::$atomic_type, // Prevent RefUnwindSafe from being propagated from the std atomic type. See NotRefUnwindSafe for more. _not_ref_unwind_safe: PhantomData, } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)) )] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl_default_no_fetch_ops!($atomic_type, $int_type); #[cfg(not(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), )))] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)) )] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { inner: core::sync::atomic::$atomic_type::new(v), _not_ref_unwind_safe: PhantomData, } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::is_always_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { // ESP-IDF targets' 64-bit atomics are not lock-free. // https://github.com/rust-lang/rust/pull/115577#issuecomment-1732259297 cfg!(not(all( any(target_arch = "riscv32", target_arch = "xtensa"), target_os = "espidf", ))) | (core::mem::size_of::<$int_type>() < 8) } #[inline] pub(crate) fn get_mut(&mut self) -> &mut $int_type { self.inner.get_mut() } #[inline] pub(crate) fn into_inner(self) -> $int_type { self.inner.into_inner() } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); // for track_caller (compiler can omit double check) self.inner.load(order) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); // for track_caller (compiler can omit double check) self.inner.store(val, order); } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { // SAFETY: Self is #[repr(C)] and internally UnsafeCell<$int_type>. // See also https://github.com/rust-lang/rust/pull/66705 and // https://github.com/rust-lang/rust/issues/66136#issuecomment-557867116. unsafe { (*(self as *const Self as *const UnsafeCell<$int_type>)).get() } } } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)) )] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] impl $atomic_type { #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange(current, new, success, failure) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // for track_caller (compiler can omit double check) #[cfg(portable_atomic_no_stronger_failure_ordering)] let success = crate::utils::upgrade_success_ordering(success, failure); self.inner.compare_exchange_weak(current, new, success, failure) } #[allow(dead_code)] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn fetch_update_(&self, order: Ordering, mut f: F) -> $int_type where F: FnMut($int_type) -> $int_type, { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = self.load(Ordering::Relaxed); loop { let next = f(prev); match self.compare_exchange_weak(prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(next_prev) => prev = next_prev, } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { #[cfg(not(portable_atomic_no_atomic_min_max))] { #[cfg(any( all( target_arch = "aarch64", any(target_feature = "lse", portable_atomic_target_feature = "lse"), ), all( target_arch = "arm", not(any( target_feature = "v6", portable_atomic_target_feature = "v6", )), ), target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc", target_arch = "powerpc64", ))] { // HACK: the following operations are currently broken (at least on qemu-user): // - aarch64's `AtomicI{8,16}::fetch_{max,min}` (release mode + lse) // - armv5te's `Atomic{I,U}{8,16}::fetch_{max,min}` // - mips's `AtomicI8::fetch_{max,min}` (release mode) // - mipsel's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - mips64's `AtomicI8::fetch_{max,min}` (release mode) // - mips64el's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc's `AtomicI{8,16}::fetch_{max,min}` // - powerpc64's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc64le's `AtomicU{8,16}::fetch_{max,min}` (release mode + fat LTO) // See also: // https://github.com/llvm/llvm-project/issues/61880 // https://github.com/llvm/llvm-project/issues/61881 // https://github.com/llvm/llvm-project/issues/61882 // https://github.com/taiki-e/portable-atomic/issues/2 // https://github.com/rust-lang/rust/issues/100650 if core::mem::size_of::<$int_type>() <= 2 { return self.fetch_update_(order, |x| core::cmp::max(x, val)); } } self.inner.fetch_max(val, order) } #[cfg(portable_atomic_no_atomic_min_max)] { self.fetch_update_(order, |x| core::cmp::max(x, val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { #[cfg(not(portable_atomic_no_atomic_min_max))] { #[cfg(any( all( target_arch = "aarch64", any(target_feature = "lse", portable_atomic_target_feature = "lse"), ), all( target_arch = "arm", not(any( target_feature = "v6", portable_atomic_target_feature = "v6", )), ), target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "powerpc", target_arch = "powerpc64", ))] { // HACK: the following operations are currently broken (at least on qemu-user): // - aarch64's `AtomicI{8,16}::fetch_{max,min}` (release mode + lse) // - armv5te's `Atomic{I,U}{8,16}::fetch_{max,min}` // - mips's `AtomicI8::fetch_{max,min}` (release mode) // - mipsel's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - mips64's `AtomicI8::fetch_{max,min}` (release mode) // - mips64el's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc's `AtomicI{8,16}::fetch_{max,min}` // - powerpc64's `AtomicI{8,16}::fetch_{max,min}` (debug mode, at least) // - powerpc64le's `AtomicU{8,16}::fetch_{max,min}` (release mode + fat LTO) // See also: // https://github.com/llvm/llvm-project/issues/61880 // https://github.com/llvm/llvm-project/issues/61881 // https://github.com/llvm/llvm-project/issues/61882 // https://github.com/taiki-e/portable-atomic/issues/2 // https://github.com/rust-lang/rust/issues/100650 if core::mem::size_of::<$int_type>() <= 2 { return self.fetch_update_(order, |x| core::cmp::min(x, val)); } } self.inner.fetch_min(val, order) } #[cfg(portable_atomic_no_atomic_min_max)] { self.fetch_update_(order, |x| core::cmp::min(x, val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { self.fetch_xor(!0, order) } #[cfg(not(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_neg(&self, order: Ordering) -> $int_type { self.fetch_update_(order, $int_type::wrapping_neg) } #[cfg(not(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), )))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } impl core::ops::Deref for $atomic_type { type Target = core::sync::atomic::$atomic_type; #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn deref(&self) -> &Self::Target { &self.inner } } }; } atomic_int!(AtomicIsize, isize); atomic_int!(AtomicUsize, usize); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicI8, i8); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicU8, u8); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicI16, i16); #[cfg(not(portable_atomic_no_atomic_load_store))] atomic_int!(AtomicU16, u16); #[cfg(not(portable_atomic_no_atomic_load_store))] #[cfg(not(target_pointer_width = "16"))] atomic_int!(AtomicI32, i32); #[cfg(not(portable_atomic_no_atomic_load_store))] #[cfg(not(target_pointer_width = "16"))] atomic_int!(AtomicU32, u32); #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_64)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] atomic_int!(AtomicI64, i64); #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_64)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] atomic_int!(AtomicU64, u64); portable-atomic/src/imp/float.rs0000644000175000017500000002015714661133735017657 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // AtomicF{32,64} implementation based on AtomicU{32,64}. // // This module provides atomic float implementations using atomic integer. // // Note that most of `fetch_*` operations of atomic floats are implemented using // CAS loops, which can be slower than equivalent operations of atomic integers. // // GPU targets have atomic instructions for float, so GPU targets will use // architecture-specific implementations instead of this implementation in the // future: https://github.com/taiki-e/portable-atomic/issues/34 #![cfg_attr( all(target_pointer_width = "16", not(feature = "fallback")), allow(unused_imports, unused_macros) )] use core::{cell::UnsafeCell, sync::atomic::Ordering}; macro_rules! atomic_float { ( $atomic_type:ident, $float_type:ident, $atomic_int_type:ident, $int_type:ident, $align:literal ) => { #[repr(C, align($align))] pub(crate) struct $atomic_type { v: UnsafeCell<$float_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by atomic operations. unsafe impl Sync for $atomic_type {} impl $atomic_type { #[inline] pub(crate) const fn new(v: $float_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { crate::$atomic_int_type::is_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { crate::$atomic_int_type::is_always_lock_free() } #[inline] pub(crate) fn get_mut(&mut self) -> &mut $float_type { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.v.get() } } #[inline] pub(crate) fn into_inner(self) -> $float_type { self.v.into_inner() } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> $float_type { $float_type::from_bits(self.as_bits().load(order)) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, val: $float_type, order: Ordering) { self.as_bits().store(val.to_bits(), order) } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; #[inline] pub(crate) const fn as_bits(&self) -> &crate::$atomic_int_type { // SAFETY: $atomic_type and $atomic_int_type have the same layout, // and there is no concurrent access to the value that does not go through this method. unsafe { &*(self as *const Self as *const crate::$atomic_int_type) } } } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $float_type { self.v.get() } } cfg_has_atomic_cas! { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn swap(&self, val: $float_type, order: Ordering) -> $float_type { $float_type::from_bits(self.as_bits().swap(val.to_bits(), order)) } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { match self.as_bits().compare_exchange( current.to_bits(), new.to_bits(), success, failure, ) { Ok(v) => Ok($float_type::from_bits(v)), Err(v) => Err($float_type::from_bits(v)), } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { match self.as_bits().compare_exchange_weak( current.to_bits(), new.to_bits(), success, failure, ) { Ok(v) => Ok($float_type::from_bits(v)), Err(v) => Err($float_type::from_bits(v)), } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_add(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x + val) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_sub(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x - val) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn fetch_update_(&self, order: Ordering, mut f: F) -> $float_type where F: FnMut($float_type) -> $float_type, { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = self.load(Ordering::Relaxed); loop { let next = f(prev); match self.compare_exchange_weak(prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(next_prev) => prev = next_prev, } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_max(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x.max(val)) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_min(&self, val: $float_type, order: Ordering) -> $float_type { self.fetch_update_(order, |x| x.min(val)) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_neg(&self, order: Ordering) -> $float_type { const NEG_MASK: $int_type = !0 / 2 + 1; $float_type::from_bits(self.as_bits().fetch_xor(NEG_MASK, order)) } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_abs(&self, order: Ordering) -> $float_type { const ABS_MASK: $int_type = !0 / 2; $float_type::from_bits(self.as_bits().fetch_and(ABS_MASK, order)) } } } // cfg_has_atomic_cas! }; } cfg_has_atomic_32! { atomic_float!(AtomicF32, f32, AtomicU32, u32, 4); } cfg_has_atomic_64! { atomic_float!(AtomicF64, f64, AtomicU64, u64, 8); } portable-atomic/src/imp/x86.rs0000644000175000017500000002120414661133735017171 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic operations implementation on x86/x86_64. // // This module provides atomic operations not supported by LLVM or optimizes // cases where LLVM code generation is not optimal. // // Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use // this module and use CAS loop instead. // // Refs: // - x86 and amd64 instruction reference https://www.felixcloutier.com/x86 // // Generated asm: // - x86_64 https://godbolt.org/z/d17eTs5Ec use core::{arch::asm, sync::atomic::Ordering}; use super::core_atomic::{ AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64, AtomicU8, AtomicUsize, }; #[cfg(target_pointer_width = "32")] macro_rules! ptr_modifier { () => { ":e" }; } #[cfg(target_pointer_width = "64")] macro_rules! ptr_modifier { () => { "" }; } macro_rules! atomic_int { ($atomic_type:ident, $ptr_size:tt) => { impl $atomic_type { #[inline] pub(crate) fn not(&self, _order: Ordering) { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // // https://www.felixcloutier.com/x86/not unsafe { // atomic RMW is always SeqCst. asm!( concat!("lock not ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"), dst = in(reg) dst, options(nostack, preserves_flags), ); } } #[inline] pub(crate) fn neg(&self, _order: Ordering) { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // // https://www.felixcloutier.com/x86/neg unsafe { // atomic RMW is always SeqCst. asm!( concat!("lock neg ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"), dst = in(reg) dst, // Do not use `preserves_flags` because NEG modifies the CF, OF, SF, ZF, AF, and PF flag. options(nostack), ); } } } }; } atomic_int!(AtomicI8, "byte"); atomic_int!(AtomicU8, "byte"); atomic_int!(AtomicI16, "word"); atomic_int!(AtomicU16, "word"); atomic_int!(AtomicI32, "dword"); atomic_int!(AtomicU32, "dword"); #[cfg(target_arch = "x86_64")] atomic_int!(AtomicI64, "qword"); #[cfg(target_arch = "x86_64")] atomic_int!(AtomicU64, "qword"); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicIsize, "dword"); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicUsize, "dword"); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicIsize, "qword"); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicUsize, "qword"); #[cfg(target_arch = "x86")] impl AtomicI64 { #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } #[cfg(target_arch = "x86")] impl AtomicU64 { #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } macro_rules! atomic_bit_opts { ($atomic_type:ident, $int_type:ident, $val_modifier:tt, $ptr_size:tt) => { // LLVM 14 and older don't support generating `lock bt{s,r,c}`. // LLVM 15 only supports generating `lock bt{s,r,c}` for immediate bit offsets. // LLVM 16+ can generate `lock bt{s,r,c}` for both immediate and register bit offsets. // https://godbolt.org/z/TGhr5z4ds // So, use fetch_* based implementations on LLVM 16+, otherwise use asm based implementations. #[cfg(portable_atomic_llvm_16)] impl_default_bit_opts!($atomic_type, $int_type); #[cfg(not(portable_atomic_llvm_16))] impl $atomic_type { #[inline] pub(crate) fn bit_set(&self, bit: u32, _order: Ordering) -> bool { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // the masking by the bit size of the type ensures that we do not shift // out of bounds. // // https://www.felixcloutier.com/x86/bts unsafe { let r: u8; // atomic RMW is always SeqCst. asm!( concat!("lock bts ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"), "setb {r}", dst = in(reg) dst, bit = in(reg) (bit & ($int_type::BITS - 1)) as $int_type, r = out(reg_byte) r, // Do not use `preserves_flags` because BTS modifies the CF flag. options(nostack), ); r != 0 } } #[inline] pub(crate) fn bit_clear(&self, bit: u32, _order: Ordering) -> bool { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // the masking by the bit size of the type ensures that we do not shift // out of bounds. // // https://www.felixcloutier.com/x86/btr unsafe { let r: u8; // atomic RMW is always SeqCst. asm!( concat!("lock btr ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"), "setb {r}", dst = in(reg) dst, bit = in(reg) (bit & ($int_type::BITS - 1)) as $int_type, r = out(reg_byte) r, // Do not use `preserves_flags` because BTR modifies the CF flag. options(nostack), ); r != 0 } } #[inline] pub(crate) fn bit_toggle(&self, bit: u32, _order: Ordering) -> bool { let dst = self.as_ptr(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. // the masking by the bit size of the type ensures that we do not shift // out of bounds. // // https://www.felixcloutier.com/x86/btc unsafe { let r: u8; // atomic RMW is always SeqCst. asm!( concat!("lock btc ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"), "setb {r}", dst = in(reg) dst, bit = in(reg) (bit & ($int_type::BITS - 1)) as $int_type, r = out(reg_byte) r, // Do not use `preserves_flags` because BTC modifies the CF flag. options(nostack), ); r != 0 } } } }; } impl_default_bit_opts!(AtomicI8, i8); impl_default_bit_opts!(AtomicU8, u8); atomic_bit_opts!(AtomicI16, i16, ":x", "word"); atomic_bit_opts!(AtomicU16, u16, ":x", "word"); atomic_bit_opts!(AtomicI32, i32, ":e", "dword"); atomic_bit_opts!(AtomicU32, u32, ":e", "dword"); #[cfg(target_arch = "x86_64")] atomic_bit_opts!(AtomicI64, i64, "", "qword"); #[cfg(target_arch = "x86_64")] atomic_bit_opts!(AtomicU64, u64, "", "qword"); #[cfg(target_arch = "x86")] impl_default_bit_opts!(AtomicI64, i64); #[cfg(target_arch = "x86")] impl_default_bit_opts!(AtomicU64, u64); #[cfg(target_pointer_width = "32")] atomic_bit_opts!(AtomicIsize, isize, ":e", "dword"); #[cfg(target_pointer_width = "32")] atomic_bit_opts!(AtomicUsize, usize, ":e", "dword"); #[cfg(target_pointer_width = "64")] atomic_bit_opts!(AtomicIsize, isize, "", "qword"); #[cfg(target_pointer_width = "64")] atomic_bit_opts!(AtomicUsize, usize, "", "qword"); portable-atomic/src/imp/msp430.rs0000644000175000017500000003060314661133735017575 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic load/store implementation on MSP430. // // Adapted from https://github.com/pftbest/msp430-atomic. // Including https://github.com/pftbest/msp430-atomic/pull/4 for a compile error fix. // Including https://github.com/pftbest/msp430-atomic/pull/5 for a soundness bug fix. // // Operations not supported here are provided by disabling interrupts. // See also src/imp/interrupt/msp430.rs. // // Note: Ordering is always SeqCst. // // Refs: https://www.ti.com/lit/ug/slau208q/slau208q.pdf #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; #[cfg(any(test, not(feature = "critical-section")))] use core::cell::UnsafeCell; use core::sync::atomic::Ordering; /// An atomic fence. /// /// # Panics /// /// Panics if `order` is [`Relaxed`](Ordering::Relaxed). #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub fn fence(order: Ordering) { match order { Ordering::Relaxed => panic!("there is no such thing as a relaxed fence"), // MSP430 is single-core and a compiler fence works as an atomic fence. _ => compiler_fence(order), } } /// A compiler memory fence. /// /// # Panics /// /// Panics if `order` is [`Relaxed`](Ordering::Relaxed). #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub fn compiler_fence(order: Ordering) { match order { Ordering::Relaxed => panic!("there is no such thing as a relaxed compiler fence"), _ => {} } // SAFETY: using an empty asm is safe. unsafe { // Do not use `nomem` and `readonly` because prevent preceding and subsequent memory accesses from being reordered. #[cfg(not(portable_atomic_no_asm))] asm!("", options(nostack, preserves_flags)); #[cfg(portable_atomic_no_asm)] llvm_asm!("" ::: "memory" : "volatile"); } } macro_rules! atomic { (load_store, $([$($generics:tt)*])? $atomic_type:ident, $value_type:ty, $asm_suffix:tt) => { #[cfg(any(test, not(feature = "critical-section")))] #[repr(transparent)] pub(crate) struct $atomic_type $(<$($generics)*>)? { v: UnsafeCell<$value_type>, } #[cfg(any(test, not(feature = "critical-section")))] // Send is implicitly implemented for atomic integers, but not for atomic pointers. // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Send for $atomic_type $(<$($generics)*>)? {} #[cfg(any(test, not(feature = "critical-section")))] // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Sync for $atomic_type $(<$($generics)*>)? {} #[cfg(any(test, not(feature = "critical-section")))] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[cfg(test)] #[inline] pub(crate) const fn new(v: $value_type) -> Self { Self { v: UnsafeCell::new(v) } } #[cfg(test)] #[inline] pub(crate) fn is_lock_free() -> bool { Self::is_always_lock_free() } #[cfg(test)] #[inline] pub(crate) const fn is_always_lock_free() -> bool { true } #[cfg(test)] #[inline] pub(crate) fn get_mut(&mut self) -> &mut $value_type { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.v.get() } } #[cfg(test)] #[inline] pub(crate) fn into_inner(self) -> $value_type { self.v.into_inner() } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $value_type { crate::utils::assert_load_ordering(order); let src = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { let out; #[cfg(not(portable_atomic_no_asm))] asm!( concat!("mov", $asm_suffix, " @{src}, {out}"), src = in(reg) src, out = lateout(reg) out, options(nostack, preserves_flags), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("mov", $asm_suffix, " $1, $0") : "=r"(out) : "*m"(src) : "memory" : "volatile" ); out } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $value_type, order: Ordering) { crate::utils::assert_store_ordering(order); let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("mov", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) dst, val = in(reg) val, options(nostack, preserves_flags), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("mov", $asm_suffix, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } } }; ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty, $asm_suffix:tt) => { atomic!(load_store, $([$($generics)*])? $atomic_type, $value_type, $asm_suffix); #[cfg(any(test, not(feature = "critical-section")))] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) fn add(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("add", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) dst, val = in(reg) val, // Do not use `preserves_flags` because ADD modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("add", $asm_suffix, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn sub(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("sub", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) dst, val = in(reg) val, // Do not use `preserves_flags` because SUB modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("sub", $asm_suffix, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn and(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("and", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) dst, val = in(reg) val, // Do not use `preserves_flags` because AND modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("and", $asm_suffix, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn or(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("bis", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) dst, val = in(reg) val, options(nostack, preserves_flags), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("bis", $asm_suffix, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn xor(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("xor", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) dst, val = in(reg) val, // Do not use `preserves_flags` because XOR modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("xor", $asm_suffix, " $1, $0") :: "*m"(dst), "ir"(val) : "memory" : "volatile" ); } } #[inline] pub(crate) fn not(&self, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { #[cfg(not(portable_atomic_no_asm))] asm!( concat!("inv", $asm_suffix, " 0({dst})"), dst = in(reg) dst, // Do not use `preserves_flags` because INV modifies the V, N, Z, and C bits of the status register. options(nostack), ); #[cfg(portable_atomic_no_asm)] llvm_asm!( concat!("inv", $asm_suffix, " $0") :: "*m"(dst) : "memory" : "volatile" ); } } } } } atomic!(AtomicI8, i8, ".b"); atomic!(AtomicU8, u8, ".b"); atomic!(AtomicI16, i16, ".w"); atomic!(AtomicU16, u16, ".w"); atomic!(AtomicIsize, isize, ".w"); atomic!(AtomicUsize, usize, ".w"); atomic!(load_store, [T] AtomicPtr, *mut T, ".w"); portable-atomic/src/imp/atomic128/0000775000175000017500000000000014661133735017710 5ustar jamespagejamespageportable-atomic/src/imp/atomic128/README.md0000644000175000017500000001326614661133735021175 0ustar jamespagejamespage# Implementation of 128-bit atomics ## 128-bit atomics instructions Here is the table of targets that support 128-bit atomics and the instructions used: | target_arch | load | store | CAS | RMW | note | | ----------- | ---- | ----- | --- | --- | ---- | | x86_64 | cmpxchg16b or vmovdqa | cmpxchg16b or vmovdqa | cmpxchg16b | cmpxchg16b | cmpxchg16b target feature required. vmovdqa requires Intel or AMD CPU with AVX.
Both compile-time and run-time detection are supported for cmpxchg16b. vmovdqa is currently run-time detection only.
Requires rustc 1.59+ when cmpxchg16b target feature is enabled at compile-time, otherwise requires rustc 1.69+ | | aarch64 | ldxp/stxp or casp or ldp/ldiapp | ldxp/stxp or casp or stp/stilp/swpp | ldxp/stxp or casp | ldxp/stxp or casp/swpp/ldclrp/ldsetp | casp requires lse target feature, ldp/stp requires lse2 target feature, ldiapp/stilp requires lse2 and rcpc3 target features, swpp/ldclrp/ldsetp requires lse128 target feature.
Both compile-time and run-time detection are supported for lse and lse2. Others are currently compile-time detection only.
Requires rustc 1.59+ | | powerpc64 | lq | stq | lqarx/stqcx. | lqarx/stqcx. | Requires target-cpu pwr8+ (powerpc64le is pwr8 by default). Both compile-time and run-time detection are supported (run-time detection is currently disabled by default).
Requires nightly | | s390x | lpq | stpq | cdsg | cdsg | Requires nightly | On compiler versions or platforms where these are not supported, the fallback implementation is used. See [aarch64.rs](aarch64.rs) module-level comments for more details on the instructions used on aarch64. ## Comparison with core::intrinsics::atomic_\* (core::sync::atomic::Atomic{I,U}128) This directory has target-specific implementations with inline assembly ([aarch64.rs](aarch64.rs), [x86_64.rs](x86_64.rs), [powerpc64.rs](powerpc64.rs), [s390x.rs](s390x.rs)) and an implementation without inline assembly ([intrinsics.rs](intrinsics.rs)). The latter currently always needs nightly compilers and is only used for Miri and ThreadSanitizer, which do not support inline assembly. Implementations with inline assembly generate assemblies almost equivalent to the `core::intrinsics::atomic_*` (used in `core::sync::atomic::Atomic{I,U}128`) for many operations, but some operations may or may not generate more efficient code. For example: - On x86_64, implementation with inline assembly contains additional optimizations (e.g., [#16](https://github.com/taiki-e/portable-atomic/pull/16)) and is much faster for some operations. - On aarch64, implementation with inline assembly supports outline-atomics on more operating systems, and may be faster in environments where outline-atomics can improve performance. - On powerpc64 and s390x, LLVM does not support generating some 128-bit atomic operations (see [intrinsics.rs](intrinsics.rs) module-level comments), and we use CAS loop to implement them, so implementation with inline assembly may be faster for those operations. - In implementations without inline assembly, the compiler may reuse condition flags that have changed as a result of the operation, or use immediate values instead of registers, depending on the situation. As 128-bit atomics-related APIs stabilize in the standard library, implementations with inline assembly are planned to be updated to get the benefits of both. ## Run-time feature detection [detect](detect) module has run-time feature detection implementations. Here is the table of targets that support run-time feature detection and the instruction or API used: | target_arch | target_os/target_env | instruction/API | features | note | | ----------- | -------------------- | --------------- | -------- | ---- | | x86_64 | all (except for sgx) | cpuid | all | Enabled by default | | aarch64 | linux | getauxval | all | Only enabled by default on `*-linux-gnu*`, and `*-linux-musl*"` (default is static linking)/`*-linux-ohos*` (default is dynamic linking) with dynamic linking enabled. | | aarch64 | android | getauxval | all | Enabled by default | | aarch64 | freebsd | elf_aux_info | lse, lse2 | Enabled by default | | aarch64 | netbsd | sysctl | all | Enabled by default | | aarch64 | openbsd | sysctl | lse | Enabled by default | | aarch64 | macos | sysctl | all | Currently only used in tests because FEAT_LSE and FEAT_LSE2 are always available at compile-time. | | aarch64 | windows | IsProcessorFeaturePresent | lse | Enabled by default | | aarch64 | fuchsia | zx_system_get_features | lse | Enabled by default | | powerpc64 | linux | getauxval | all | Disabled by default | | powerpc64 | freebsd | elf_aux_info | all | Disabled by default | Run-time detection is enabled by default on most targets and can be disabled with `--cfg portable_atomic_no_outline_atomics`. On some targets, run-time detection is disabled by default mainly for compatibility with older versions of operating systems or incomplete build environments, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.) For targets not included in the above table, run-time detection is always disabled and works the same as when `--cfg portable_atomic_no_outline_atomics` is set. See [detect/auxv.rs](detect/auxv.rs) module-level comments for more details on Linux/Android/FreeBSD. See also [docs on `portable_atomic_no_outline_atomics`](https://github.com/taiki-e/portable-atomic/blob/HEAD/README.md#optional-cfg-no-outline-atomics) in the top-level readme. portable-atomic/src/imp/atomic128/x86_64.rs0000644000175000017500000007630614661133735021226 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic{I,U}128 implementation on x86_64 using CMPXCHG16B (DWCAS). // // Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use // this module and use intrinsics.rs instead. // // Refs: // - x86 and amd64 instruction reference https://www.felixcloutier.com/x86 // - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit // // Generated asm: // - x86_64 (+cmpxchg16b) https://godbolt.org/z/55n54WeKr include!("macros.rs"); #[cfg(not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")))] #[path = "../fallback/outline_atomics.rs"] mod fallback; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(not(target_env = "sgx"))] #[path = "detect/x86_64.rs"] mod detect; #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::sync::atomic::Ordering; use crate::utils::{Pair, U128}; // Asserts that the function is called in the correct context. macro_rules! debug_assert_cmpxchg16b { () => { #[cfg(not(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )))] { debug_assert!(detect::detect().has_cmpxchg16b()); } }; } #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] macro_rules! debug_assert_vmovdqa_atomic { () => {{ debug_assert_cmpxchg16b!(); debug_assert!(detect::detect().has_vmovdqa_atomic()); }}; } #[allow(unused_macros)] #[cfg(target_pointer_width = "32")] macro_rules! ptr_modifier { () => { ":e" }; } #[allow(unused_macros)] #[cfg(target_pointer_width = "64")] macro_rules! ptr_modifier { () => { "" }; } #[cfg_attr( not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn cmpxchg16b(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned (required by CMPXCHG16B), that there are no // concurrent non-atomic operations, and that the CPU supports CMPXCHG16B. // // If the value at `dst` (destination operand) and rdx:rax are equal, the // 128-bit value in rcx:rbx is stored in the `dst`, otherwise the value at // `dst` is loaded to rdx:rax. // // The ZF flag is set if the value at `dst` and rdx:rax are equal, // otherwise it is cleared. Other flags are unaffected. // // Refs: https://www.felixcloutier.com/x86/cmpxchg8b:cmpxchg16b unsafe { // cmpxchg16b is always SeqCst. let r: u8; let old = U128 { whole: old }; let new = U128 { whole: new }; let (prev_lo, prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( // rbx is reserved by LLVM "xchg {rbx_tmp}, rbx", concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "sete r8b", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = inout(reg) new.pair.lo => _, in("rcx") new.pair.hi, inout("rax") old.pair.lo => prev_lo, inout("rdx") old.pair.hi => prev_hi, in($rdi) dst, out("r8b") r, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); (U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole, r != 0) } } // VMOVDQA is atomic on Intel and AMD CPUs with AVX. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 for details. // // Refs: https://www.felixcloutier.com/x86/movdqa:vmovdqa32:vmovdqa64 // // Do not use vector registers on targets such as x86_64-unknown-none unless SSE is explicitly enabled. // https://doc.rust-lang.org/nightly/rustc/platform-support/x86_64-unknown-none.html #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] #[target_feature(enable = "avx")] #[inline] unsafe fn atomic_load_vmovdqa(src: *mut u128) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_vmovdqa_atomic!(); // SAFETY: the caller must uphold the safety contract. // // atomic load by vmovdqa is always SeqCst. unsafe { let out: core::arch::x86_64::__m128; asm!( concat!("vmovdqa {out}, xmmword ptr [{src", ptr_modifier!(), "}]"), src = in(reg) src, out = out(xmm_reg) out, options(nostack, preserves_flags), ); core::mem::transmute(out) } } #[cfg(not(any(portable_atomic_no_outline_atomics, target_env = "sgx")))] #[cfg(target_feature = "sse")] #[target_feature(enable = "avx")] #[inline] unsafe fn atomic_store_vmovdqa(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); debug_assert_vmovdqa_atomic!(); // SAFETY: the caller must uphold the safety contract. unsafe { let val: core::arch::x86_64::__m128 = core::mem::transmute(val); match order { // Relaxed and Release stores are equivalent. Ordering::Relaxed | Ordering::Release => { asm!( concat!("vmovdqa xmmword ptr [{dst", ptr_modifier!(), "}], {val}"), dst = in(reg) dst, val = in(xmm_reg) val, options(nostack, preserves_flags), ); } Ordering::SeqCst => { asm!( concat!("vmovdqa xmmword ptr [{dst", ptr_modifier!(), "}], {val}"), "mfence", dst = in(reg) dst, val = in(xmm_reg) val, options(nostack, preserves_flags), ); } _ => unreachable!("{:?}", order), } } } #[cfg(not(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), )))] macro_rules! load_store_detect { ( vmovdqa = $vmovdqa:ident cmpxchg16b = $cmpxchg16b:ident fallback = $fallback:ident ) => {{ let cpuid = detect::detect(); #[cfg(not(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )))] { // Check CMPXCHG16B first to prevent mixing atomic and non-atomic access. if cpuid.has_cmpxchg16b() { // We do not use vector registers on targets such as x86_64-unknown-none unless SSE is explicitly enabled. #[cfg(target_feature = "sse")] { if cpuid.has_vmovdqa_atomic() { $vmovdqa } else { $cmpxchg16b } } #[cfg(not(target_feature = "sse"))] { $cmpxchg16b } } else { fallback::$fallback } } #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] { if cpuid.has_vmovdqa_atomic() { $vmovdqa } else { $cmpxchg16b } } }}; } #[inline] unsafe fn atomic_load(src: *mut u128, _order: Ordering) -> u128 { // Do not use vector registers on targets such as x86_64-unknown-none unless SSE is explicitly enabled. // https://doc.rust-lang.org/nightly/rustc/platform-support/x86_64-unknown-none.html // SGX doesn't support CPUID. #[cfg(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that CMPXCHG16B is available at compile-time. unsafe { // cmpxchg16b is always SeqCst. atomic_load_cmpxchg16b(src) } #[cfg(not(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), )))] // SAFETY: the caller must uphold the safety contract. unsafe { ifunc!(unsafe fn(src: *mut u128) -> u128 { load_store_detect! { vmovdqa = atomic_load_vmovdqa cmpxchg16b = atomic_load_cmpxchg16b // Use SeqCst because cmpxchg16b and atomic load by vmovdqa is always SeqCst. fallback = atomic_load_seqcst } }) } } #[cfg_attr( not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn atomic_load_cmpxchg16b(src: *mut u128) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `src` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. // // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing of condition flags and avoid use of xchg to handle rbx. unsafe { // cmpxchg16b is always SeqCst. let (out_lo, out_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( // rbx is reserved by LLVM "mov {rbx_tmp}, rbx", "xor rbx, rbx", // zeroed rbx concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "mov rbx, {rbx_tmp}", // restore rbx // set old/new args of cmpxchg16b to 0 (rbx is zeroed after saved to rbx_tmp, to avoid xchg) rbx_tmp = out(reg) _, in("rcx") 0_u64, inout("rax") 0_u64 => out_lo, inout("rdx") 0_u64 => out_hi, in($rdi) src, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { // Do not use vector registers on targets such as x86_64-unknown-none unless SSE is explicitly enabled. // https://doc.rust-lang.org/nightly/rustc/platform-support/x86_64-unknown-none.html // SGX doesn't support CPUID. #[cfg(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that CMPXCHG16B is available at compile-time. unsafe { // cmpxchg16b is always SeqCst. let _ = order; atomic_store_cmpxchg16b(dst, val); } #[cfg(not(all( any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), any(portable_atomic_no_outline_atomics, target_env = "sgx", not(target_feature = "sse")), )))] // SAFETY: the caller must uphold the safety contract. unsafe { #[cfg(target_feature = "sse")] fn_alias! { #[target_feature(enable = "avx")] unsafe fn(dst: *mut u128, val: u128); // atomic store by vmovdqa has at least release semantics. atomic_store_vmovdqa_non_seqcst = atomic_store_vmovdqa(Ordering::Release); atomic_store_vmovdqa_seqcst = atomic_store_vmovdqa(Ordering::SeqCst); } match order { // Relaxed and Release stores are equivalent in all implementations // that may be called here (vmovdqa, asm-based cmpxchg16b, and fallback). // core::arch's cmpxchg16b will never called here. Ordering::Relaxed | Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { load_store_detect! { vmovdqa = atomic_store_vmovdqa_non_seqcst cmpxchg16b = atomic_store_cmpxchg16b fallback = atomic_store_non_seqcst } }); } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { load_store_detect! { vmovdqa = atomic_store_vmovdqa_seqcst cmpxchg16b = atomic_store_cmpxchg16b fallback = atomic_store_seqcst } }); } _ => unreachable!("{:?}", order), } } } #[cfg_attr( not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")), target_feature(enable = "cmpxchg16b") )] unsafe fn atomic_store_cmpxchg16b(dst: *mut u128, val: u128) { // SAFETY: the caller must uphold the safety contract. unsafe { // cmpxchg16b is always SeqCst. atomic_swap_cmpxchg16b(dst, val, Ordering::SeqCst); } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, _success: Ordering, _failure: Ordering, ) -> Result { #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and cfg guarantees that CMPXCHG16B is available at compile-time. let (prev, ok) = unsafe { cmpxchg16b(dst, old, new) }; #[cfg(not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")))] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no different kinds of concurrent accesses. let (prev, ok) = unsafe { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> (u128, bool) { if detect::detect().has_cmpxchg16b() { cmpxchg16b } else { // Use SeqCst because cmpxchg16b is always SeqCst. fallback::atomic_compare_exchange_seqcst } }) }; if ok { Ok(prev) } else { Err(prev) } } // cmpxchg16b is always strong. use atomic_compare_exchange as atomic_compare_exchange_weak; #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] use atomic_swap_cmpxchg16b as atomic_swap; #[cfg_attr( not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn atomic_swap_cmpxchg16b(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. // // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing/comparing of condition flags and reducing uses of xchg/mov to handle rbx. // // Do not use atomic_rmw_cas_3 because it needs extra MOV to implement swap. unsafe { // cmpxchg16b is always SeqCst. let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( // rbx is reserved by LLVM "xchg {rbx_tmp}, rbx", // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // This is based on the code generated for the first load in DW RMWs by LLVM. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement this. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). concat!("mov rax, qword ptr [", $rdi, "]"), concat!("mov rdx, qword ptr [", $rdi, " + 8]"), "2:", concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "jne 2b", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = inout(reg) val.pair.lo => _, in("rcx") val.pair.hi, out("rax") prev_lo, out("rdx") prev_hi, in($rdi) dst, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } /// Atomic RMW by CAS loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - rsi/r8 pair: val argument (read-only for `$op`) /// - rax/rdx pair: previous value loaded (read-only for `$op`) /// - rbx/rcx pair: new value that will be stored // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing/comparing of condition flags and reducing uses of xchg/mov to handle rbx. macro_rules! atomic_rmw_cas_3 { ($name:ident as $reexport_name:ident, $($op:tt)*) => { #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] use $name as $reexport_name; #[cfg_attr( not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn $name(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. unsafe { // cmpxchg16b is always SeqCst. let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( // rbx is reserved by LLVM "mov {rbx_tmp}, rbx", // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // This is based on the code generated for the first load in DW RMWs by LLVM. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement this. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). concat!("mov rax, qword ptr [", $rdi, "]"), concat!("mov rdx, qword ptr [", $rdi, " + 8]"), "2:", $($op)* concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "jne 2b", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = out(reg) _, out("rcx") _, out("rax") prev_lo, out("rdx") prev_hi, in($rdi) dst, in("rsi") val.pair.lo, in("r8") val.pair.hi, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by CAS loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - rax/rdx pair: previous value loaded (read-only for `$op`) /// - rbx/rcx pair: new value that will be stored // We could use CAS loop by atomic_compare_exchange here, but using an inline assembly allows // omitting the storing of condition flags and avoid use of xchg to handle rbx. macro_rules! atomic_rmw_cas_2 { ($name:ident as $reexport_name:ident, $($op:tt)*) => { #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] use $name as $reexport_name; #[cfg_attr( not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")), target_feature(enable = "cmpxchg16b") )] #[inline] unsafe fn $name(dst: *mut u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_cmpxchg16b!(); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // cfg guarantees that the CPU supports CMPXCHG16B. // // See cmpxchg16b function for more. unsafe { // cmpxchg16b is always SeqCst. let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg16b { ($rdi:tt) => { asm!( // rbx is reserved by LLVM "mov {rbx_tmp}, rbx", // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // This is based on the code generated for the first load in DW RMWs by LLVM. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement this. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). concat!("mov rax, qword ptr [", $rdi, "]"), concat!("mov rdx, qword ptr [", $rdi, " + 8]"), "2:", $($op)* concat!("lock cmpxchg16b xmmword ptr [", $rdi, "]"), "jne 2b", "mov rbx, {rbx_tmp}", // restore rbx rbx_tmp = out(reg) _, out("rcx") _, out("rax") prev_lo, out("rdx") prev_hi, in($rdi) dst, // Do not use `preserves_flags` because CMPXCHG16B modifies the ZF flag. options(nostack), ) }; } #[cfg(target_pointer_width = "32")] cmpxchg16b!("edi"); #[cfg(target_pointer_width = "64")] cmpxchg16b!("rdi"); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } atomic_rmw_cas_3! { atomic_add_cmpxchg16b as atomic_add, "mov rbx, rax", "add rbx, rsi", "mov rcx, rdx", "adc rcx, r8", } atomic_rmw_cas_3! { atomic_sub_cmpxchg16b as atomic_sub, "mov rbx, rax", "sub rbx, rsi", "mov rcx, rdx", "sbb rcx, r8", } atomic_rmw_cas_3! { atomic_and_cmpxchg16b as atomic_and, "mov rbx, rax", "and rbx, rsi", "mov rcx, rdx", "and rcx, r8", } atomic_rmw_cas_3! { atomic_nand_cmpxchg16b as atomic_nand, "mov rbx, rax", "and rbx, rsi", "not rbx", "mov rcx, rdx", "and rcx, r8", "not rcx", } atomic_rmw_cas_3! { atomic_or_cmpxchg16b as atomic_or, "mov rbx, rax", "or rbx, rsi", "mov rcx, rdx", "or rcx, r8", } atomic_rmw_cas_3! { atomic_xor_cmpxchg16b as atomic_xor, "mov rbx, rax", "xor rbx, rsi", "mov rcx, rdx", "xor rcx, r8", } atomic_rmw_cas_2! { atomic_not_cmpxchg16b as atomic_not, "mov rbx, rax", "not rbx", "mov rcx, rdx", "not rcx", } atomic_rmw_cas_2! { atomic_neg_cmpxchg16b as atomic_neg, "mov rbx, rax", "neg rbx", "mov rcx, 0", "sbb rcx, rdx", } atomic_rmw_cas_3! { atomic_max_cmpxchg16b as atomic_max, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovl rcx, rdx", "mov rbx, rsi", "cmovl rbx, rax", } atomic_rmw_cas_3! { atomic_umax_cmpxchg16b as atomic_umax, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovb rcx, rdx", "mov rbx, rsi", "cmovb rbx, rax", } atomic_rmw_cas_3! { atomic_min_cmpxchg16b as atomic_min, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovge rcx, rdx", "mov rbx, rsi", "cmovge rbx, rax", } atomic_rmw_cas_3! { atomic_umin_cmpxchg16b as atomic_umin, "cmp rsi, rax", "mov rcx, r8", "sbb rcx, rdx", "mov rcx, r8", "cmovae rcx, rdx", "mov rbx, rsi", "cmovae rbx, rax", } macro_rules! atomic_rmw_with_ifunc { ( unsafe fn $name:ident($($arg:tt)*) $(-> $ret_ty:ty)?; cmpxchg16b = $cmpxchg16b_fn:ident; fallback = $seqcst_fallback_fn:ident; ) => { #[cfg(not(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )))] #[inline] unsafe fn $name($($arg)*, _order: Ordering) $(-> $ret_ty)? { fn_alias! { #[cfg_attr( not(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )), target_feature(enable = "cmpxchg16b") )] unsafe fn($($arg)*) $(-> $ret_ty)?; // cmpxchg16b is always SeqCst. cmpxchg16b_seqcst_fn = $cmpxchg16b_fn(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls cmpxchg16b_fn if cmpxchg16b is available. unsafe { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_cmpxchg16b() { cmpxchg16b_seqcst_fn } else { // Use SeqCst because cmpxchg16b is always SeqCst. fallback::$seqcst_fallback_fn } }) } } }; } atomic_rmw_with_ifunc! { unsafe fn atomic_swap(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_swap_cmpxchg16b; fallback = atomic_swap_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_add(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_add_cmpxchg16b; fallback = atomic_add_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_sub(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_sub_cmpxchg16b; fallback = atomic_sub_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_and(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_and_cmpxchg16b; fallback = atomic_and_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_nand(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_nand_cmpxchg16b; fallback = atomic_nand_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_or(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_or_cmpxchg16b; fallback = atomic_or_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_xor(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_xor_cmpxchg16b; fallback = atomic_xor_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_max(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_max_cmpxchg16b; fallback = atomic_max_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_umax(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_umax_cmpxchg16b; fallback = atomic_umax_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_min(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_min_cmpxchg16b; fallback = atomic_min_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_umin(dst: *mut u128, val: u128) -> u128; cmpxchg16b = atomic_umin_cmpxchg16b; fallback = atomic_umin_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_not(dst: *mut u128) -> u128; cmpxchg16b = atomic_not_cmpxchg16b; fallback = atomic_not_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_neg(dst: *mut u128) -> u128; cmpxchg16b = atomic_neg_cmpxchg16b; fallback = atomic_neg_seqcst; } #[inline] fn is_lock_free() -> bool { #[cfg(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"))] { // CMPXCHG16B is available at compile-time. true } #[cfg(not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")))] { detect::detect().has_cmpxchg16b() } } const IS_ALWAYS_LOCK_FREE: bool = cfg!(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")); atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[allow(clippy::undocumented_unsafe_blocks, clippy::wildcard_imports)] #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/intrinsics.rs0000644000175000017500000005200514661133735022443 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic{I,U}128 implementation without inline assembly. // // Note: This module is currently only enabled on Miri and ThreadSanitizer which // do not support inline assembly. // // This uses `core::arch::x86_64::cmpxchg16b` on x86_64 and // `core::intrinsics::atomic_*` on aarch64, powerpc64, and s390x. // // See README.md of this directory for performance comparison with the // implementation with inline assembly. // // Note: // - This currently needs Rust 1.70 on x86_64, otherwise nightly compilers. // - On powerpc64, this requires LLVM 15+ and pwr8+ (quadword-atomics LLVM target feature): // https://github.com/llvm/llvm-project/commit/549e118e93c666914a1045fde38a2cac33e1e445 // - On aarch64 big-endian, LLVM (as of 17) generates broken code. (wrong result in stress test) // (on cfg(miri)/cfg(sanitize) it may be fine though) // - On s390x, LLVM (as of 17) generates libcalls for operations other than load/store/cmpxchg: // https://godbolt.org/z/5a5T4hxMh // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/test/CodeGen/SystemZ/atomicrmw-ops-i128.ll // https://reviews.llvm.org/D146425 // - On powerpc64, LLVM (as of 17) doesn't support 128-bit atomic min/max: // https://github.com/llvm/llvm-project/issues/68390 // - On powerpc64le, LLVM (as of 17) generates broken code. (wrong result from fetch_add) // // Refs: https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs include!("macros.rs"); #[allow(dead_code)] // we only use compare_exchange. #[cfg(target_arch = "x86_64")] #[cfg(not(target_feature = "cmpxchg16b"))] #[path = "../fallback/outline_atomics.rs"] mod fallback; #[cfg(target_arch = "x86_64")] #[cfg(not(target_feature = "cmpxchg16b"))] #[path = "detect/x86_64.rs"] mod detect; use core::sync::atomic::Ordering; #[cfg(not(target_arch = "x86_64"))] use core::{ intrinsics, sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst}, }; // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L3128 #[cfg(target_arch = "x86_64")] #[inline] fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Ordering::Release | Ordering::Relaxed => Ordering::Relaxed, Ordering::SeqCst => Ordering::SeqCst, Ordering::Acquire | Ordering::AcqRel => Ordering::Acquire, _ => unreachable!("{:?}", order), } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { #[cfg(target_arch = "x86_64")] // SAFETY: the caller must uphold the safety contract. unsafe { let fail_order = strongest_failure_ordering(order); match atomic_compare_exchange(src, 0, 0, order, fail_order) { Ok(v) | Err(v) => v, } } #[cfg(not(target_arch = "x86_64"))] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_load_acquire(src), Relaxed => intrinsics::atomic_load_relaxed(src), SeqCst => intrinsics::atomic_load_seqcst(src), _ => unreachable!("{:?}", order), } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { #[cfg(target_arch = "x86_64")] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_swap(dst, val, order); } #[cfg(not(target_arch = "x86_64"))] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Release => intrinsics::atomic_store_release(dst, val), Relaxed => intrinsics::atomic_store_relaxed(dst, val), SeqCst => intrinsics::atomic_store_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { #[cfg(target_arch = "x86_64")] let (val, ok) = { #[cfg_attr(not(target_feature = "cmpxchg16b"), target_feature(enable = "cmpxchg16b"))] #[cfg_attr(target_feature = "cmpxchg16b", inline)] #[cfg_attr(not(target_feature = "cmpxchg16b"), inline(never))] unsafe fn cmpxchg16b( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); #[cfg(not(target_feature = "cmpxchg16b"))] { debug_assert!(detect::detect().has_cmpxchg16b()); } // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned (required by CMPXCHG16B), that there are no // concurrent non-atomic operations, and that the CPU supports CMPXCHG16B. let prev = unsafe { core::arch::x86_64::cmpxchg16b(dst, old, new, success, failure) }; (prev, prev == old) } // The stronger failure ordering in cmpxchg16b_intrinsic is actually supported // before stabilization, but we do not have a specific cfg for it. #[cfg(portable_atomic_unstable_cmpxchg16b_intrinsic)] let success = crate::utils::upgrade_success_ordering(success, failure); #[cfg(target_feature = "cmpxchg16b")] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and cfg guarantees that CMPXCHG16B is available at compile-time. unsafe { cmpxchg16b(dst, old, new, success, failure) } #[cfg(not(target_feature = "cmpxchg16b"))] // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no different kinds of concurrent accesses. unsafe { ifunc!(unsafe fn( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering ) -> (u128, bool) { if detect::detect().has_cmpxchg16b() { cmpxchg16b } else { fallback::atomic_compare_exchange } }) } }; #[cfg(not(target_arch = "x86_64"))] // SAFETY: the caller must uphold the safety contract. let (val, ok) = unsafe { match (success, failure) { (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed_relaxed(dst, old, new), (Relaxed, Acquire) => intrinsics::atomic_cxchg_relaxed_acquire(dst, old, new), (Relaxed, SeqCst) => intrinsics::atomic_cxchg_relaxed_seqcst(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchg_acquire_relaxed(dst, old, new), (Acquire, Acquire) => intrinsics::atomic_cxchg_acquire_acquire(dst, old, new), (Acquire, SeqCst) => intrinsics::atomic_cxchg_acquire_seqcst(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchg_release_relaxed(dst, old, new), (Release, Acquire) => intrinsics::atomic_cxchg_release_acquire(dst, old, new), (Release, SeqCst) => intrinsics::atomic_cxchg_release_seqcst(dst, old, new), (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_relaxed(dst, old, new), (AcqRel, Acquire) => intrinsics::atomic_cxchg_acqrel_acquire(dst, old, new), (AcqRel, SeqCst) => intrinsics::atomic_cxchg_acqrel_seqcst(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchg_seqcst_relaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchg_seqcst_acquire(dst, old, new), (SeqCst, SeqCst) => intrinsics::atomic_cxchg_seqcst_seqcst(dst, old, new), _ => unreachable!("{:?}, {:?}", success, failure), } }; if ok { Ok(val) } else { Err(val) } } #[cfg(target_arch = "x86_64")] use atomic_compare_exchange as atomic_compare_exchange_weak; #[cfg(not(target_arch = "x86_64"))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_compare_exchange_weak( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { // SAFETY: the caller must uphold the safety contract. let (val, ok) = unsafe { match (success, failure) { (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed_relaxed(dst, old, new), (Relaxed, Acquire) => intrinsics::atomic_cxchgweak_relaxed_acquire(dst, old, new), (Relaxed, SeqCst) => intrinsics::atomic_cxchgweak_relaxed_seqcst(dst, old, new), (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acquire_relaxed(dst, old, new), (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acquire_acquire(dst, old, new), (Acquire, SeqCst) => intrinsics::atomic_cxchgweak_acquire_seqcst(dst, old, new), (Release, Relaxed) => intrinsics::atomic_cxchgweak_release_relaxed(dst, old, new), (Release, Acquire) => intrinsics::atomic_cxchgweak_release_acquire(dst, old, new), (Release, SeqCst) => intrinsics::atomic_cxchgweak_release_seqcst(dst, old, new), (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_relaxed(dst, old, new), (AcqRel, Acquire) => intrinsics::atomic_cxchgweak_acqrel_acquire(dst, old, new), (AcqRel, SeqCst) => intrinsics::atomic_cxchgweak_acqrel_seqcst(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_seqcst_relaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_seqcst_acquire(dst, old, new), (SeqCst, SeqCst) => intrinsics::atomic_cxchgweak_seqcst_seqcst(dst, old, new), _ => unreachable!("{:?}, {:?}", success, failure), } }; if ok { Ok(val) } else { Err(val) } } #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_update(dst: *mut u128, order: Ordering, mut f: F) -> u128 where F: FnMut(u128) -> u128, { // SAFETY: the caller must uphold the safety contract. unsafe { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = atomic_load(dst, Ordering::Relaxed); loop { let next = f(prev); match atomic_compare_exchange_weak(dst, prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(x) => prev = x, } } } } // On x86_64, we use core::arch::x86_64::cmpxchg16b instead of core::intrinsics. // On s390x, LLVM generates libcalls for operations other than load/store/cmpxchg (see also module-level comment). #[cfg(any(target_arch = "x86_64", target_arch = "s390x"))] atomic_rmw_by_atomic_update!(); // On powerpc64, LLVM doesn't support 128-bit atomic min/max (see also module-level comment). #[cfg(target_arch = "powerpc64")] atomic_rmw_by_atomic_update!(cmp); #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_swap(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xchg_acquire(dst, val), Release => intrinsics::atomic_xchg_release(dst, val), AcqRel => intrinsics::atomic_xchg_acqrel(dst, val), Relaxed => intrinsics::atomic_xchg_relaxed(dst, val), SeqCst => intrinsics::atomic_xchg_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_add(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xadd_acquire(dst, val), Release => intrinsics::atomic_xadd_release(dst, val), AcqRel => intrinsics::atomic_xadd_acqrel(dst, val), Relaxed => intrinsics::atomic_xadd_relaxed(dst, val), SeqCst => intrinsics::atomic_xadd_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_sub(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xsub_acquire(dst, val), Release => intrinsics::atomic_xsub_release(dst, val), AcqRel => intrinsics::atomic_xsub_acqrel(dst, val), Relaxed => intrinsics::atomic_xsub_relaxed(dst, val), SeqCst => intrinsics::atomic_xsub_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_and(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_and_acquire(dst, val), Release => intrinsics::atomic_and_release(dst, val), AcqRel => intrinsics::atomic_and_acqrel(dst, val), Relaxed => intrinsics::atomic_and_relaxed(dst, val), SeqCst => intrinsics::atomic_and_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_nand(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_nand_acquire(dst, val), Release => intrinsics::atomic_nand_release(dst, val), AcqRel => intrinsics::atomic_nand_acqrel(dst, val), Relaxed => intrinsics::atomic_nand_relaxed(dst, val), SeqCst => intrinsics::atomic_nand_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_or(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_or_acquire(dst, val), Release => intrinsics::atomic_or_release(dst, val), AcqRel => intrinsics::atomic_or_acqrel(dst, val), Relaxed => intrinsics::atomic_or_relaxed(dst, val), SeqCst => intrinsics::atomic_or_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_xor(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_xor_acquire(dst, val), Release => intrinsics::atomic_xor_release(dst, val), AcqRel => intrinsics::atomic_xor_acqrel(dst, val), Relaxed => intrinsics::atomic_xor_relaxed(dst, val), SeqCst => intrinsics::atomic_xor_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_max(dst: *mut u128, val: u128, order: Ordering) -> i128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_max_acquire(dst.cast::(), val as i128), Release => intrinsics::atomic_max_release(dst.cast::(), val as i128), AcqRel => intrinsics::atomic_max_acqrel(dst.cast::(), val as i128), Relaxed => intrinsics::atomic_max_relaxed(dst.cast::(), val as i128), SeqCst => intrinsics::atomic_max_seqcst(dst.cast::(), val as i128), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_min(dst: *mut u128, val: u128, order: Ordering) -> i128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_min_acquire(dst.cast::(), val as i128), Release => intrinsics::atomic_min_release(dst.cast::(), val as i128), AcqRel => intrinsics::atomic_min_acqrel(dst.cast::(), val as i128), Relaxed => intrinsics::atomic_min_relaxed(dst.cast::(), val as i128), SeqCst => intrinsics::atomic_min_seqcst(dst.cast::(), val as i128), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umax(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_umax_acquire(dst, val), Release => intrinsics::atomic_umax_release(dst, val), AcqRel => intrinsics::atomic_umax_acqrel(dst, val), Relaxed => intrinsics::atomic_umax_relaxed(dst, val), SeqCst => intrinsics::atomic_umax_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umin(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { match order { Acquire => intrinsics::atomic_umin_acquire(dst, val), Release => intrinsics::atomic_umin_release(dst, val), AcqRel => intrinsics::atomic_umin_acqrel(dst, val), Relaxed => intrinsics::atomic_umin_relaxed(dst, val), SeqCst => intrinsics::atomic_umin_seqcst(dst, val), _ => unreachable!("{:?}", order), } } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_not(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_xor(dst, !0, order) } } #[cfg(not(any(target_arch = "x86_64", target_arch = "s390x")))] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_neg(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, u128::wrapping_neg) } } #[cfg(not(target_arch = "x86_64"))] #[inline] const fn is_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } #[cfg(not(target_arch = "x86_64"))] const IS_ALWAYS_LOCK_FREE: bool = true; #[cfg(target_arch = "x86_64")] #[inline] fn is_lock_free() -> bool { #[cfg(target_feature = "cmpxchg16b")] { // CMPXCHG16B is available at compile-time. true } #[cfg(not(target_feature = "cmpxchg16b"))] { detect::detect().has_cmpxchg16b() } } #[cfg(target_arch = "x86_64")] const IS_ALWAYS_LOCK_FREE: bool = cfg!(target_feature = "cmpxchg16b"); atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/aarch64.rs0000644000175000017500000021430514661133735021511 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic{I,U}128 implementation on AArch64. // // There are a few ways to implement 128-bit atomic operations in AArch64. // // - LDXP/STXP loop (DW LL/SC) // - CASP (DWCAS) added as FEAT_LSE (mandatory from armv8.1-a) // - LDP/STP (DW load/store) if FEAT_LSE2 (optional from armv8.2-a, mandatory from armv8.4-a) is available // - LDIAPP/STILP (DW acquire-load/release-store) added as FEAT_LRCPC3 (optional from armv8.9-a/armv9.4-a) (if FEAT_LSE2 is also available) // - LDCLRP/LDSETP/SWPP (DW RMW) added as FEAT_LSE128 (optional from armv9.4-a) // // If outline-atomics is not enabled and FEAT_LSE is not available at // compile-time, we use LDXP/STXP loop. // If outline-atomics is enabled and FEAT_LSE is not available at // compile-time, we use CASP for CAS if FEAT_LSE is available // at run-time, otherwise, use LDXP/STXP loop. // If FEAT_LSE is available at compile-time, we use CASP for load/store/CAS/RMW. // However, when portable_atomic_ll_sc_rmw cfg is set, use LDXP/STXP loop instead of CASP // loop for RMW (by default, it is set on Apple hardware; see build script for details). // If FEAT_LSE2 is available at compile-time, we use LDP/STP for load/store. // If FEAT_LSE128 is available at compile-time, we use LDCLRP/LDSETP/SWPP for fetch_and/fetch_or/swap/{release,seqcst}-store. // If FEAT_LSE2 and FEAT_LRCPC3 are available at compile-time, we use LDIAPP/STILP for acquire-load/release-store. // // Note: FEAT_LSE2 doesn't imply FEAT_LSE. FEAT_LSE128 implies FEAT_LSE but not FEAT_LSE2. // // Note that we do not separate LL and SC into separate functions, but handle // them within a single asm block. This is because it is theoretically possible // for the compiler to insert operations that might clear the reservation between // LL and SC. Considering the type of operations we are providing and the fact // that [progress64](https://github.com/ARM-software/progress64) uses such code, // this is probably not a problem for aarch64, but it seems that aarch64 doesn't // guarantee it and hexagon is the only architecture with hardware guarantees // that such code works. See also: // // - https://yarchive.net/comp/linux/cmpxchg_ll_sc_portability.html // - https://lists.llvm.org/pipermail/llvm-dev/2016-May/099490.html // - https://lists.llvm.org/pipermail/llvm-dev/2018-June/123993.html // // Also, even when using a CAS loop to implement atomic RMW, include the loop itself // in the asm block because it is more efficient for some codegen backends. // https://github.com/rust-lang/compiler-builtins/issues/339#issuecomment-1191260474 // // Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use // this module and use intrinsics.rs instead. // // Refs: // - ARM Compiler armasm User Guide // https://developer.arm.com/documentation/dui0801/latest // - Arm A-profile A64 Instruction Set Architecture // https://developer.arm.com/documentation/ddi0602/latest // - Arm Architecture Reference Manual for A-profile architecture // https://developer.arm.com/documentation/ddi0487/latest // - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit // // Generated asm: // - aarch64 https://godbolt.org/z/5Mz1E33vz // - aarch64 msvc https://godbolt.org/z/P53d1MsGY // - aarch64 (+lse) https://godbolt.org/z/qvaE8n79K // - aarch64 msvc (+lse) https://godbolt.org/z/dj4aYerfr // - aarch64 (+lse,+lse2) https://godbolt.org/z/1E15jjxah // - aarch64 (+lse,+lse2,+rcpc3) https://godbolt.org/z/YreM4n84o // - aarch64 (+lse2,+lse128) https://godbolt.org/z/Kfeqs54ox // - aarch64 (+lse2,+lse128,+rcpc3) https://godbolt.org/z/n6zhjE77s include!("macros.rs"); // On musl with static linking, it seems that getauxval is not always available. // See detect/auxv.rs for more. #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( test, not(all( any(target_feature = "lse2", portable_atomic_target_feature = "lse2"), any(target_feature = "lse", portable_atomic_target_feature = "lse"), )), ))] #[cfg(any( all( target_os = "linux", any( target_env = "gnu", all(any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static")), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ))] #[path = "detect/auxv.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg_attr( target_os = "netbsd", cfg(any( test, not(all( any(target_feature = "lse2", portable_atomic_target_feature = "lse2"), any(target_feature = "lse", portable_atomic_target_feature = "lse"), )), )) )] #[cfg_attr( target_os = "openbsd", cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))) )] #[cfg(any(target_os = "netbsd", target_os = "openbsd"))] #[path = "detect/aarch64_aa64reg.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[cfg(target_os = "fuchsia")] #[path = "detect/aarch64_fuchsia.rs"] mod detect; #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[cfg(target_os = "windows")] #[path = "detect/aarch64_windows.rs"] mod detect; // test only #[cfg(test)] #[cfg(not(qemu))] #[cfg(not(valgrind))] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))] #[path = "detect/aarch64_aa64reg.rs"] mod detect_aa64reg; #[cfg(test)] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(target_os = "macos")] #[path = "detect/aarch64_macos.rs"] mod detect_macos; #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::sync::atomic::Ordering; use crate::utils::{Pair, U128}; #[cfg(any( target_feature = "lse", portable_atomic_target_feature = "lse", not(portable_atomic_no_outline_atomics), ))] macro_rules! debug_assert_lse { () => { #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", target_os = "fuchsia", target_os = "windows", ), ))] #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] { debug_assert!(detect::detect().has_lse()); } }; } #[rustfmt::skip] #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] macro_rules! debug_assert_lse2 { () => { #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", // These don't support detection of FEAT_LSE2. // target_os = "openbsd", // target_os = "fuchsia", // target_os = "windows", ), ))] #[cfg(not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")))] { debug_assert!(detect::detect().has_lse2()); } }; } // Refs: https://developer.arm.com/documentation/100067/0612/armclang-Integrated-Assembler/AArch32-Target-selection-directives?lang=en // // This is similar to #[target_feature(enable = "lse")], except that there are // no compiler guarantees regarding (un)inlining, and the scope is within an asm // block rather than a function. We use this directive to support outline-atomics // on pre-1.61 rustc (aarch64_target_feature stabilized in Rust 1.61). // // The .arch_extension directive is effective until the end of the assembly block and // is not propagated to subsequent code, so the end_lse macro is unneeded. // https://godbolt.org/z/4oMEW8vWc // https://github.com/torvalds/linux/commit/e0d5896bd356cd577f9710a02d7a474cdf58426b // https://github.com/torvalds/linux/commit/dd1f6308b28edf0452dd5dc7877992903ec61e69 // (It seems GCC effectively ignores this directive and always allow FEAT_LSE instructions: https://godbolt.org/z/W9W6rensG) // // The .arch directive has a similar effect, but we don't use it due to the following issue: // https://github.com/torvalds/linux/commit/dd1f6308b28edf0452dd5dc7877992903ec61e69 // // This is also needed for compatibility with rustc_codegen_cranelift: // https://github.com/rust-lang/rustc_codegen_cranelift/issues/1400#issuecomment-1774599775 // // Note: If FEAT_LSE is not available at compile-time, we must guarantee that // the function that uses it is not inlined into a function where it is not // clear whether FEAT_LSE is available. Otherwise, (even if we checked whether // FEAT_LSE is available at run-time) optimizations that reorder its // instructions across the if condition might introduce undefined behavior. // (see also https://rust-lang.github.io/rfcs/2045-target-feature.html#safely-inlining-target_feature-functions-on-more-contexts) // However, our code uses the ifunc helper macro that works with function pointers, // so we don't have to worry about this unless calling without helper macro. #[cfg(any( target_feature = "lse", portable_atomic_target_feature = "lse", not(portable_atomic_no_outline_atomics), ))] macro_rules! start_lse { () => { ".arch_extension lse" }; } #[cfg(target_endian = "little")] macro_rules! select_le_or_be { ($le:expr, $be:expr) => { $le }; } #[cfg(target_endian = "big")] macro_rules! select_le_or_be { ($le:expr, $be:expr) => { $be }; } macro_rules! atomic_rmw { ($op:ident, $order:ident) => { atomic_rmw!($op, $order, write = $order) }; ($op:ident, $order:ident, write = $write:ident) => { match $order { Ordering::Relaxed => $op!("", "", ""), Ordering::Acquire => $op!("a", "", ""), Ordering::Release => $op!("", "l", ""), Ordering::AcqRel => $op!("a", "l", ""), // In MSVC environments, SeqCst stores/writes needs fences after writes. // https://reviews.llvm.org/D141748 #[cfg(target_env = "msvc")] Ordering::SeqCst if $write == Ordering::SeqCst => $op!("a", "l", "dmb ish"), // AcqRel and SeqCst RMWs are equivalent in non-MSVC environments. Ordering::SeqCst => $op!("a", "l", ""), _ => unreachable!("{:?}", $order), } }; } // cfg guarantee that the CPU supports FEAT_LSE2. #[cfg(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))] use _atomic_load_ldp as atomic_load; #[cfg(not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")))] #[inline] unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { #[inline] unsafe fn atomic_load_no_lse2(src: *mut u128, order: Ordering) -> u128 { #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { _atomic_load_casp(src, order) } #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] // SAFETY: the caller must uphold the safety contract. unsafe { _atomic_load_ldxp_stxp(src, order) } } #[cfg(not(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", // These don't support detection of FEAT_LSE2. // target_os = "openbsd", // target_os = "fuchsia", // target_os = "windows", ), )))] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_load_no_lse2(src, order) } #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", // These don't support detection of FEAT_LSE2. // target_os = "openbsd", // target_os = "fuchsia", // target_os = "windows", ), ))] { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(src: *mut u128) -> u128; atomic_load_lse2_relaxed = _atomic_load_ldp(Ordering::Relaxed); atomic_load_lse2_acquire = _atomic_load_ldp(Ordering::Acquire); atomic_load_lse2_seqcst = _atomic_load_ldp(Ordering::SeqCst); } fn_alias! { unsafe fn(src: *mut u128) -> u128; atomic_load_no_lse2_relaxed = atomic_load_no_lse2(Ordering::Relaxed); atomic_load_no_lse2_acquire = atomic_load_no_lse2(Ordering::Acquire); atomic_load_no_lse2_seqcst = atomic_load_no_lse2(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // and we've checked if FEAT_LSE2 is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(src: *mut u128) -> u128 { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { atomic_load_lse2_relaxed } else { atomic_load_no_lse2_relaxed } }) } Ordering::Acquire => { ifunc!(unsafe fn(src: *mut u128) -> u128 { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { atomic_load_lse2_acquire } else { atomic_load_no_lse2_acquire } }) } Ordering::SeqCst => { ifunc!(unsafe fn(src: *mut u128) -> u128 { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { atomic_load_lse2_seqcst } else { atomic_load_no_lse2_seqcst } }) } _ => unreachable!("{:?}", order), } } } } // If CPU supports FEAT_LSE2, LDP/LDIAPP is single-copy atomic reads, // otherwise it is two single-copy atomic reads. // Refs: B2.2.1 of the Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] #[inline] unsafe fn _atomic_load_ldp(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_lse2!(); // SAFETY: the caller must guarantee that `dst` is valid for reads, // 16-byte aligned, that there are no concurrent non-atomic operations. // // Refs: // - LDP: https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/LDP--A64- unsafe { let (out_lo, out_hi); macro_rules! atomic_load_relaxed { ($acquire:tt $(, $readonly:tt)?) => { asm!( "ldp {out_lo}, {out_hi}, [{src}]", $acquire, src = in(reg) ptr_reg!(src), out_hi = lateout(reg) out_hi, out_lo = lateout(reg) out_lo, options(nostack, preserves_flags $(, $readonly)?), ) }; } match order { Ordering::Relaxed => atomic_load_relaxed!("", readonly), #[cfg(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3"))] Ordering::Acquire => { // SAFETY: cfg guarantee that the CPU supports FEAT_LRCPC3. // Refs: https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDIAPP--Load-Acquire-RCpc-ordered-Pair-of-registers- asm!( "ldiapp {out_lo}, {out_hi}, [{src}]", src = in(reg) ptr_reg!(src), out_hi = lateout(reg) out_hi, out_lo = lateout(reg) out_lo, options(nostack, preserves_flags), ); } #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] Ordering::Acquire => atomic_load_relaxed!("dmb ishld"), Ordering::SeqCst => { asm!( // ldar (or dmb ishld) is required to prevent reordering with preceding stlxp. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108891 for details. "ldar {tmp}, [{src}]", "ldp {out_lo}, {out_hi}, [{src}]", "dmb ishld", src = in(reg) ptr_reg!(src), out_hi = lateout(reg) out_hi, out_lo = lateout(reg) out_lo, tmp = out(reg) _, options(nostack, preserves_flags), ); } _ => unreachable!("{:?}", order), } U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } // Do not use _atomic_compare_exchange_casp because it needs extra MOV to implement load. #[cfg(any(test, not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn _atomic_load_casp(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let (out_lo, out_hi); macro_rules! atomic_load { ($acquire:tt, $release:tt) => { asm!( start_lse!(), concat!("casp", $acquire, $release, " x2, x3, x2, x3, [{src}]"), src = in(reg) ptr_reg!(src), // must be allocated to even/odd register pair inout("x2") 0_u64 => out_lo, inout("x3") 0_u64 => out_hi, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_load!("", ""), Ordering::Acquire => atomic_load!("a", ""), Ordering::SeqCst => atomic_load!("a", "l"), _ => unreachable!("{:?}", order), } U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } #[cfg(any( test, all( not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), not(any(target_feature = "lse", portable_atomic_target_feature = "lse")), ), ))] #[inline] unsafe fn _atomic_load_ldxp_stxp(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let (mut out_lo, mut out_hi); macro_rules! atomic_load { ($acquire:tt, $release:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {out_lo}, {out_hi}, [{src}]"), concat!("st", $release, "xp {r:w}, {out_lo}, {out_hi}, [{src}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", src = in(reg) ptr_reg!(src), out_lo = out(reg) out_lo, out_hi = out(reg) out_hi, r = out(reg) _, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_load!("", ""), Ordering::Acquire => atomic_load!("a", ""), Ordering::SeqCst => atomic_load!("a", "l"), _ => unreachable!("{:?}", order), } U128 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } // cfg guarantee that the CPU supports FEAT_LSE2. #[cfg(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))] use _atomic_store_stp as atomic_store; #[cfg(not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")))] #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { #[inline] unsafe fn atomic_store_no_lse2(dst: *mut u128, val: u128, order: Ordering) { // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW. #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { _atomic_swap_casp(dst, val, order); } #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] // SAFETY: the caller must uphold the safety contract. unsafe { _atomic_store_ldxp_stxp(dst, val, order); } } #[cfg(not(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", // These don't support detection of FEAT_LSE2. // target_os = "openbsd", // target_os = "fuchsia", // target_os = "windows", ), )))] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_store_no_lse2(dst, val, order); } #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", // These don't support detection of FEAT_LSE2. // target_os = "openbsd", // target_os = "fuchsia", // target_os = "windows", ), ))] { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, val: u128); atomic_store_lse2_relaxed = _atomic_store_stp(Ordering::Relaxed); atomic_store_lse2_release = _atomic_store_stp(Ordering::Release); atomic_store_lse2_seqcst = _atomic_store_stp(Ordering::SeqCst); } fn_alias! { unsafe fn(dst: *mut u128, val: u128); atomic_store_no_lse2_relaxed = atomic_store_no_lse2(Ordering::Relaxed); atomic_store_no_lse2_release = atomic_store_no_lse2(Ordering::Release); atomic_store_no_lse2_seqcst = atomic_store_no_lse2(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // and we've checked if FEAT_LSE2 is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { atomic_store_lse2_relaxed } else { atomic_store_no_lse2_relaxed } }); } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { atomic_store_lse2_release } else { atomic_store_no_lse2_release } }); } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { let cpuinfo = detect::detect(); if cpuinfo.has_lse2() { atomic_store_lse2_seqcst } else { atomic_store_no_lse2_seqcst } }); } _ => unreachable!("{:?}", order), } } } } // If CPU supports FEAT_LSE2, STP/STILP is single-copy atomic writes, // otherwise it is two single-copy atomic writes. // Refs: B2.2.1 of the Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile #[cfg(any( target_feature = "lse2", portable_atomic_target_feature = "lse2", not(portable_atomic_no_outline_atomics), ))] #[inline] unsafe fn _atomic_store_stp(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); debug_assert_lse2!(); // SAFETY: the caller must guarantee that `dst` is valid for writes, // 16-byte aligned, that there are no concurrent non-atomic operations. // // Refs: // - STP: https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/STP--A64- unsafe { #[rustfmt::skip] macro_rules! atomic_store { ($acquire:tt, $release:tt) => {{ let val = U128 { whole: val }; asm!( $release, "stp {val_lo}, {val_hi}, [{dst}]", $acquire, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, options(nostack, preserves_flags), ); }}; } match order { Ordering::Relaxed => atomic_store!("", ""), #[cfg(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3"))] Ordering::Release => { let val = U128 { whole: val }; // SAFETY: cfg guarantee that the CPU supports FEAT_LRCPC3. // Refs: https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/STILP--Store-Release-ordered-Pair-of-registers- asm!( "stilp {val_lo}, {val_hi}, [{dst}]", dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, options(nostack, preserves_flags), ); } #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] Ordering::Release => { // Use swpp if stp requires fences. // https://reviews.llvm.org/D143506 // SAFETY: cfg guarantee that the CPU supports FEAT_LSE128. _atomic_swap_swpp(dst, val, order); } #[cfg(not(any(target_feature = "rcpc3", portable_atomic_target_feature = "rcpc3")))] #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] Ordering::Release => atomic_store!("", "dmb ish"), #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] Ordering::SeqCst => { // Use swpp if stp requires fences. // https://reviews.llvm.org/D143506 // SAFETY: cfg guarantee that the CPU supports FEAT_LSE128. _atomic_swap_swpp(dst, val, order); } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] Ordering::SeqCst => atomic_store!("dmb ish", "dmb ish"), _ => unreachable!("{:?}", order), } } } // Do not use _atomic_swap_ldxp_stxp because it needs extra registers to implement store. #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn _atomic_store_ldxp_stxp(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; macro_rules! store { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp xzr, {tmp}, [{dst}]"), concat!("st", $release, "xp {tmp:w}, {val_lo}, {val_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {tmp:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, tmp = out(reg) _, options(nostack, preserves_flags), ) }; } atomic_rmw!(store, order); } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. let prev = unsafe { _atomic_compare_exchange_casp(dst, old, new, success, failure) }; #[cfg(not(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", target_os = "fuchsia", target_os = "windows", ), )))] #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] // SAFETY: the caller must uphold the safety contract. let prev = unsafe { _atomic_compare_exchange_ldxp_stxp(dst, old, new, success, failure) }; #[cfg(all( not(portable_atomic_no_outline_atomics), any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd", target_os = "fuchsia", target_os = "windows", ), ))] #[cfg(not(any(target_feature = "lse", portable_atomic_target_feature = "lse")))] let prev = { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128; atomic_compare_exchange_casp_relaxed = _atomic_compare_exchange_casp(Ordering::Relaxed, Ordering::Relaxed); atomic_compare_exchange_casp_acquire = _atomic_compare_exchange_casp(Ordering::Acquire, Ordering::Acquire); atomic_compare_exchange_casp_release = _atomic_compare_exchange_casp(Ordering::Release, Ordering::Relaxed); atomic_compare_exchange_casp_acqrel = _atomic_compare_exchange_casp(Ordering::AcqRel, Ordering::Acquire); // AcqRel and SeqCst RMWs are equivalent in non-MSVC environments. #[cfg(target_env = "msvc")] atomic_compare_exchange_casp_seqcst = _atomic_compare_exchange_casp(Ordering::SeqCst, Ordering::SeqCst); } fn_alias! { unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128; atomic_compare_exchange_ldxp_stxp_relaxed = _atomic_compare_exchange_ldxp_stxp(Ordering::Relaxed, Ordering::Relaxed); atomic_compare_exchange_ldxp_stxp_acquire = _atomic_compare_exchange_ldxp_stxp(Ordering::Acquire, Ordering::Acquire); atomic_compare_exchange_ldxp_stxp_release = _atomic_compare_exchange_ldxp_stxp(Ordering::Release, Ordering::Relaxed); atomic_compare_exchange_ldxp_stxp_acqrel = _atomic_compare_exchange_ldxp_stxp(Ordering::AcqRel, Ordering::Acquire); // AcqRel and SeqCst RMWs are equivalent in non-MSVC environments. #[cfg(target_env = "msvc")] atomic_compare_exchange_ldxp_stxp_seqcst = _atomic_compare_exchange_ldxp_stxp(Ordering::SeqCst, Ordering::SeqCst); } // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and we've checked if FEAT_LSE is available. unsafe { let success = crate::utils::upgrade_success_ordering(success, failure); match success { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { atomic_compare_exchange_casp_relaxed } else { atomic_compare_exchange_ldxp_stxp_relaxed } }) } Ordering::Acquire => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { atomic_compare_exchange_casp_acquire } else { atomic_compare_exchange_ldxp_stxp_acquire } }) } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { atomic_compare_exchange_casp_release } else { atomic_compare_exchange_ldxp_stxp_release } }) } // AcqRel and SeqCst RMWs are equivalent in both implementations in non-MSVC environments. #[cfg(not(target_env = "msvc"))] Ordering::AcqRel | Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { atomic_compare_exchange_casp_acqrel } else { atomic_compare_exchange_ldxp_stxp_acqrel } }) } #[cfg(target_env = "msvc")] Ordering::AcqRel => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { atomic_compare_exchange_casp_acqrel } else { atomic_compare_exchange_ldxp_stxp_acqrel } }) } #[cfg(target_env = "msvc")] Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, old: u128, new: u128) -> u128 { if detect::detect().has_lse() { atomic_compare_exchange_casp_seqcst } else { atomic_compare_exchange_ldxp_stxp_seqcst } }) } _ => unreachable!("{:?}", success), } } }; if prev == old { Ok(prev) } else { Err(prev) } } #[cfg(any( target_feature = "lse", portable_atomic_target_feature = "lse", not(portable_atomic_no_outline_atomics), ))] #[inline] unsafe fn _atomic_compare_exchange_casp( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); let order = crate::utils::upgrade_success_ordering(success, failure); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE. // // Refs: // - https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/CASPA--CASPAL--CASP--CASPL--CASPAL--CASP--CASPL--A64- // - https://developer.arm.com/documentation/ddi0602/2023-06/Base-Instructions/CASP--CASPA--CASPAL--CASPL--Compare-and-Swap-Pair-of-words-or-doublewords-in-memory- unsafe { let old = U128 { whole: old }; let new = U128 { whole: new }; let (prev_lo, prev_hi); macro_rules! cmpxchg { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), concat!("casp", $acquire, $release, " x6, x7, x4, x5, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), // must be allocated to even/odd register pair inout("x6") old.pair.lo => prev_lo, inout("x7") old.pair.hi => prev_hi, // must be allocated to even/odd register pair in("x4") new.pair.lo, in("x5") new.pair.hi, options(nostack, preserves_flags), ) }; } atomic_rmw!(cmpxchg, order, write = success); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[inline] unsafe fn _atomic_compare_exchange_ldxp_stxp( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> u128 { debug_assert!(dst as usize % 16 == 0); let order = crate::utils::upgrade_success_ordering(success, failure); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, and that there are no concurrent non-atomic operations. // // Refs: // - LDXP: https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/LDXP--A64- // - LDAXP: https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/LDAXP--A64- // - STXP: https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/STXP--A64- // - STLXP: https://developer.arm.com/documentation/dui0801/l/A64-Data-Transfer-Instructions/STLXP--A64- // // Note: Load-Exclusive pair (by itself) does not guarantee atomicity; to complete an atomic // operation (even load/store), a corresponding Store-Exclusive pair must succeed. // See Arm Architecture Reference Manual for A-profile architecture // Section B2.2.1 "Requirements for single-copy atomicity", and // Section B2.9 "Synchronization and semaphores" for more. unsafe { let old = U128 { whole: old }; let new = U128 { whole: new }; let (mut prev_lo, mut prev_hi); macro_rules! cmpxchg { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), "cmp {prev_lo}, {old_lo}", "cset {r:w}, ne", "cmp {prev_hi}, {old_hi}", "cinc {r:w}, {r:w}, ne", "cbz {r:w}, 3f", concat!("st", $release, "xp {r:w}, {prev_lo}, {prev_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", "b 4f", "3:", concat!("st", $release, "xp {r:w}, {new_lo}, {new_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", "4:", $fence, dst = in(reg) ptr_reg!(dst), old_lo = in(reg) old.pair.lo, old_hi = in(reg) old.pair.hi, new_lo = in(reg) new.pair.lo, new_hi = in(reg) new.pair.hi, prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, r = out(reg) _, // Do not use `preserves_flags` because CMP modifies the condition flags. options(nostack), ) }; } atomic_rmw!(cmpxchg, order, write = success); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } // casp is always strong, and ldxp requires a corresponding (succeed) stxp for // its atomicity (see code comment in _atomic_compare_exchange_ldxp_stxp). // (i.e., aarch64 doesn't have 128-bit weak CAS) use self::atomic_compare_exchange as atomic_compare_exchange_weak; // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW. #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] use _atomic_swap_casp as atomic_swap; #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] use _atomic_swap_ldxp_stxp as atomic_swap; #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] use _atomic_swap_swpp as atomic_swap; #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] #[inline] unsafe fn _atomic_swap_swpp(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE128. // // Refs: // - https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/SWPP--SWPPA--SWPPAL--SWPPL--Swap-quadword-in-memory-?lang=en unsafe { let val = U128 { whole: val }; let (prev_lo, prev_hi); macro_rules! swap { ($acquire:tt, $release:tt, $fence:tt) => { asm!( concat!("swpp", $acquire, $release, " {val_lo}, {val_hi}, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), val_lo = inout(reg) val.pair.lo => prev_lo, val_hi = inout(reg) val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } atomic_rmw!(swap, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } // Do not use atomic_rmw_cas_3 because it needs extra MOV to implement swap. #[cfg(any(test, not(portable_atomic_ll_sc_rmw)))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn _atomic_swap_casp(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! swap { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), // If FEAT_LSE2 is not supported, this works like byte-wise atomic. // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. "ldp x4, x5, [{dst}]", "2:", // casp writes the current value to the first register pair, // so copy the `out`'s value for later comparison. "mov {tmp_lo}, x4", "mov {tmp_hi}, x5", concat!("casp", $acquire, $release, " x4, x5, x2, x3, [{dst}]"), "cmp {tmp_hi}, x5", "ccmp {tmp_lo}, x4, #0, eq", "b.ne 2b", $fence, dst = in(reg) ptr_reg!(dst), tmp_lo = out(reg) _, tmp_hi = out(reg) _, // must be allocated to even/odd register pair out("x4") prev_lo, out("x5") prev_hi, // must be allocated to even/odd register pair in("x2") val.pair.lo, in("x3") val.pair.hi, // Do not use `preserves_flags` because CMP and CCMP modify the condition flags. options(nostack), ) }; } atomic_rmw!(swap, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } // Do not use atomic_rmw_ll_sc_3 because it needs extra MOV to implement swap. #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn _atomic_swap_ldxp_stxp(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! swap { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), concat!("st", $release, "xp {r:w}, {val_lo}, {val_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, r = out(reg) _, options(nostack, preserves_flags), ) }; } atomic_rmw!(swap, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } /// Atomic RMW by LL/SC loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - val_lo/val_hi pair: val argument (read-only for `$op`) /// - prev_lo/prev_hi pair: previous value loaded by ll (read-only for `$op`) /// - new_lo/new_hi pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_3 { ($name:ident as $reexport_name:ident $(($preserves_flags:tt))?, $($op:tt)*) => { // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW generated by atomic_rmw_cas_3! macro instead. #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] use $name as $reexport_name; #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn $name(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), $($op)* concat!("st", $release, "xp {r:w}, {new_lo}, {new_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, new_lo = out(reg) _, new_hi = out(reg) _, r = out(reg) _, options(nostack $(, $preserves_flags)?), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by CAS loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - val_lo/val_hi pair: val argument (read-only for `$op`) /// - x6/x7 pair: previous value loaded (read-only for `$op`) /// - x4/x5 pair: new value that will be stored macro_rules! atomic_rmw_cas_3 { ($name:ident as $reexport_name:ident, $($op:tt)*) => { // If FEAT_LSE is not available at compile-time or portable_atomic_ll_sc_rmw cfg is set, // we use LL/SC-based atomic RMW generated by atomic_rmw_ll_sc_3! macro instead. #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] use $name as $reexport_name; #[cfg(any(test, not(portable_atomic_ll_sc_rmw)))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn $name(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let val = U128 { whole: val }; let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), // If FEAT_LSE2 is not supported, this works like byte-wise atomic. // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. "ldp x6, x7, [{dst}]", "2:", // casp writes the current value to the first register pair, // so copy the `out`'s value for later comparison. "mov {tmp_lo}, x6", "mov {tmp_hi}, x7", $($op)* concat!("casp", $acquire, $release, " x6, x7, x4, x5, [{dst}]"), "cmp {tmp_hi}, x7", "ccmp {tmp_lo}, x6, #0, eq", "b.ne 2b", $fence, dst = in(reg) ptr_reg!(dst), val_lo = in(reg) val.pair.lo, val_hi = in(reg) val.pair.hi, tmp_lo = out(reg) _, tmp_hi = out(reg) _, // must be allocated to even/odd register pair out("x6") prev_lo, out("x7") prev_hi, // must be allocated to even/odd register pair out("x4") _, out("x5") _, // Do not use `preserves_flags` because CMP and CCMP modify the condition flags. options(nostack), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by LL/SC loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - prev_lo/prev_hi pair: previous value loaded by ll (read-only for `$op`) /// - new_lo/new_hi pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_2 { ($name:ident as $reexport_name:ident $(($preserves_flags:tt))?, $($op:tt)*) => { // If FEAT_LSE is available at compile-time and portable_atomic_ll_sc_rmw cfg is not set, // we use CAS-based atomic RMW generated by atomic_rmw_cas_2! macro instead. #[cfg(not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )))] use $name as $reexport_name; #[cfg(any( test, not(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), )) ))] #[inline] unsafe fn $name(dst: *mut u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( "2:", concat!("ld", $acquire, "xp {prev_lo}, {prev_hi}, [{dst}]"), $($op)* concat!("st", $release, "xp {r:w}, {new_lo}, {new_hi}, [{dst}]"), // 0 if the store was successful, 1 if no store was performed "cbnz {r:w}, 2b", $fence, dst = in(reg) ptr_reg!(dst), prev_lo = out(reg) prev_lo, prev_hi = out(reg) prev_hi, new_lo = out(reg) _, new_hi = out(reg) _, r = out(reg) _, options(nostack $(, $preserves_flags)?), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } /// Atomic RMW by CAS loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - x6/x7 pair: previous value loaded (read-only for `$op`) /// - x4/x5 pair: new value that will be stored macro_rules! atomic_rmw_cas_2 { ($name:ident as $reexport_name:ident, $($op:tt)*) => { // If FEAT_LSE is not available at compile-time or portable_atomic_ll_sc_rmw cfg is set, // we use LL/SC-based atomic RMW generated by atomic_rmw_ll_sc_3! macro instead. #[cfg(all( any(target_feature = "lse", portable_atomic_target_feature = "lse"), not(portable_atomic_ll_sc_rmw), ))] use $name as $reexport_name; #[cfg(any(test, not(portable_atomic_ll_sc_rmw)))] #[cfg(any(target_feature = "lse", portable_atomic_target_feature = "lse"))] #[inline] unsafe fn $name(dst: *mut u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_lse!(); // SAFETY: the caller must uphold the safety contract. // cfg guarantee that the CPU supports FEAT_LSE. unsafe { let (mut prev_lo, mut prev_hi); macro_rules! op { ($acquire:tt, $release:tt, $fence:tt) => { asm!( start_lse!(), // If FEAT_LSE2 is not supported, this works like byte-wise atomic. // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. "ldp x6, x7, [{dst}]", "2:", // casp writes the current value to the first register pair, // so copy the `out`'s value for later comparison. "mov {tmp_lo}, x6", "mov {tmp_hi}, x7", $($op)* concat!("casp", $acquire, $release, " x6, x7, x4, x5, [{dst}]"), "cmp {tmp_hi}, x7", "ccmp {tmp_lo}, x6, #0, eq", "b.ne 2b", $fence, dst = in(reg) ptr_reg!(dst), tmp_lo = out(reg) _, tmp_hi = out(reg) _, // must be allocated to even/odd register pair out("x6") prev_lo, out("x7") prev_hi, // must be allocated to even/odd register pair out("x4") _, out("x5") _, // Do not use `preserves_flags` because CMP and CCMP modify the condition flags. options(nostack), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } }; } // Do not use `preserves_flags` because ADDS modifies the condition flags. atomic_rmw_ll_sc_3! { _atomic_add_ldxp_stxp as atomic_add, select_le_or_be!("adds {new_lo}, {prev_lo}, {val_lo}", "adds {new_hi}, {prev_hi}, {val_hi}"), select_le_or_be!("adc {new_hi}, {prev_hi}, {val_hi}", "adc {new_lo}, {prev_lo}, {val_lo}"), } atomic_rmw_cas_3! { _atomic_add_casp as atomic_add, select_le_or_be!("adds x4, x6, {val_lo}", "adds x5, x7, {val_hi}"), select_le_or_be!("adc x5, x7, {val_hi}", "adc x4, x6, {val_lo}"), } // Do not use `preserves_flags` because SUBS modifies the condition flags. atomic_rmw_ll_sc_3! { _atomic_sub_ldxp_stxp as atomic_sub, select_le_or_be!("subs {new_lo}, {prev_lo}, {val_lo}", "subs {new_hi}, {prev_hi}, {val_hi}"), select_le_or_be!("sbc {new_hi}, {prev_hi}, {val_hi}", "sbc {new_lo}, {prev_lo}, {val_lo}"), } atomic_rmw_cas_3! { _atomic_sub_casp as atomic_sub, select_le_or_be!("subs x4, x6, {val_lo}", "subs x5, x7, {val_hi}"), select_le_or_be!("sbc x5, x7, {val_hi}", "sbc x4, x6, {val_lo}"), } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_ll_sc_3! { _atomic_and_ldxp_stxp as atomic_and (preserves_flags), "and {new_lo}, {prev_lo}, {val_lo}", "and {new_hi}, {prev_hi}, {val_hi}", } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_cas_3! { _atomic_and_casp as atomic_and, "and x4, x6, {val_lo}", "and x5, x7, {val_hi}", } #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] #[inline] unsafe fn atomic_and(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE128. // // Refs: // - https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDCLRP--LDCLRPA--LDCLRPAL--LDCLRPL--Atomic-bit-clear-on-quadword-in-memory-?lang=en unsafe { let val = U128 { whole: !val }; let (prev_lo, prev_hi); macro_rules! and { ($acquire:tt, $release:tt, $fence:tt) => { asm!( concat!("ldclrp", $acquire, $release, " {val_lo}, {val_hi}, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), val_lo = inout(reg) val.pair.lo => prev_lo, val_hi = inout(reg) val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } atomic_rmw!(and, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } atomic_rmw_ll_sc_3! { _atomic_nand_ldxp_stxp as atomic_nand (preserves_flags), "and {new_lo}, {prev_lo}, {val_lo}", "mvn {new_lo}, {new_lo}", "and {new_hi}, {prev_hi}, {val_hi}", "mvn {new_hi}, {new_hi}", } atomic_rmw_cas_3! { _atomic_nand_casp as atomic_nand, "and x4, x6, {val_lo}", "mvn x4, x4", "and x5, x7, {val_hi}", "mvn x5, x5", } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_ll_sc_3! { _atomic_or_ldxp_stxp as atomic_or (preserves_flags), "orr {new_lo}, {prev_lo}, {val_lo}", "orr {new_hi}, {prev_hi}, {val_hi}", } #[cfg(not(any(target_feature = "lse128", portable_atomic_target_feature = "lse128")))] atomic_rmw_cas_3! { _atomic_or_casp as atomic_or, "orr x4, x6, {val_lo}", "orr x5, x7, {val_hi}", } #[cfg(any(target_feature = "lse128", portable_atomic_target_feature = "lse128"))] #[inline] unsafe fn atomic_or(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must guarantee that `dst` is valid for both writes and // reads, 16-byte aligned, that there are no concurrent non-atomic operations, // and the CPU supports FEAT_LSE128. // // Refs: // - https://developer.arm.com/documentation/ddi0602/2023-03/Base-Instructions/LDSETP--LDSETPA--LDSETPAL--LDSETPL--Atomic-bit-set-on-quadword-in-memory-?lang=en unsafe { let val = U128 { whole: val }; let (prev_lo, prev_hi); macro_rules! or { ($acquire:tt, $release:tt, $fence:tt) => { asm!( concat!("ldsetp", $acquire, $release, " {val_lo}, {val_hi}, [{dst}]"), $fence, dst = in(reg) ptr_reg!(dst), val_lo = inout(reg) val.pair.lo => prev_lo, val_hi = inout(reg) val.pair.hi => prev_hi, options(nostack, preserves_flags), ) }; } atomic_rmw!(or, order); U128 { pair: Pair { lo: prev_lo, hi: prev_hi } }.whole } } atomic_rmw_ll_sc_3! { _atomic_xor_ldxp_stxp as atomic_xor (preserves_flags), "eor {new_lo}, {prev_lo}, {val_lo}", "eor {new_hi}, {prev_hi}, {val_hi}", } atomic_rmw_cas_3! { _atomic_xor_casp as atomic_xor, "eor x4, x6, {val_lo}", "eor x5, x7, {val_hi}", } atomic_rmw_ll_sc_2! { _atomic_not_ldxp_stxp as atomic_not (preserves_flags), "mvn {new_lo}, {prev_lo}", "mvn {new_hi}, {prev_hi}", } atomic_rmw_cas_2! { _atomic_not_casp as atomic_not, "mvn x4, x6", "mvn x5, x7", } // Do not use `preserves_flags` because NEGS modifies the condition flags. atomic_rmw_ll_sc_2! { _atomic_neg_ldxp_stxp as atomic_neg, select_le_or_be!("negs {new_lo}, {prev_lo}", "negs {new_hi}, {prev_hi}"), select_le_or_be!("ngc {new_hi}, {prev_hi}", "ngc {new_lo}, {prev_lo}"), } atomic_rmw_cas_2! { _atomic_neg_casp as atomic_neg, select_le_or_be!("negs x4, x6", "negs x5, x7"), select_le_or_be!("ngc x5, x7", "ngc x4, x6"), } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_max_ldxp_stxp as atomic_max, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, lt", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, lt", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_max_casp as atomic_max, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, lt", // select hi 64-bit "csel x4, x6, {val_lo}, lt", // select lo 64-bit } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_umax_ldxp_stxp as atomic_umax, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, lo", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, lo", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_umax_casp as atomic_umax, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, lo", // select hi 64-bit "csel x4, x6, {val_lo}, lo", // select lo 64-bit } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_min_ldxp_stxp as atomic_min, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, ge", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, ge", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_min_casp as atomic_min, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, ge", // select hi 64-bit "csel x4, x6, {val_lo}, ge", // select lo 64-bit } // Do not use `preserves_flags` because CMP and SBCS modify the condition flags. atomic_rmw_ll_sc_3! { _atomic_umin_ldxp_stxp as atomic_umin, select_le_or_be!("cmp {val_lo}, {prev_lo}", "cmp {val_hi}, {prev_hi}"), select_le_or_be!("sbcs xzr, {val_hi}, {prev_hi}", "sbcs xzr, {val_lo}, {prev_lo}"), "csel {new_hi}, {prev_hi}, {val_hi}, hs", // select hi 64-bit "csel {new_lo}, {prev_lo}, {val_lo}, hs", // select lo 64-bit } atomic_rmw_cas_3! { _atomic_umin_casp as atomic_umin, select_le_or_be!("cmp {val_lo}, x6", "cmp {val_hi}, x7"), select_le_or_be!("sbcs xzr, {val_hi}, x7", "sbcs xzr, {val_lo}, x6"), "csel x5, x7, {val_hi}, hs", // select hi 64-bit "csel x4, x6, {val_lo}, hs", // select lo 64-bit } #[inline] const fn is_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } const IS_ALWAYS_LOCK_FREE: bool = true; atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/s390x.rs0000644000175000017500000003653314661133735021154 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic{I,U}128 implementation on s390x. // // s390x supports 128-bit atomic load/store/cmpxchg: // https://github.com/llvm/llvm-project/commit/a11f63a952664f700f076fd754476a2b9eb158cc // // LLVM's minimal supported architecture level is z10: // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/SystemZ/SystemZProcessors.td) // This does not appear to have changed since the current s390x backend was added in LLVM 3.3: // https://github.com/llvm/llvm-project/commit/5f613dfd1f7edb0ae95d521b7107b582d9df5103#diff-cbaef692b3958312e80fd5507a7e2aff071f1acb086f10e8a96bc06a7bb289db // // Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use // this module and use intrinsics.rs instead. // // Refs: // - z/Architecture Principles of Operation https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf // - z/Architecture Reference Summary https://www.ibm.com/support/pages/zarchitecture-reference-summary // - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit // // Generated asm: // - s390x https://godbolt.org/z/b11znnEh4 // - s390x (z196) https://godbolt.org/z/s5n9PGcv6 // - s390x (z15) https://godbolt.org/z/Wf49h7bPf include!("macros.rs"); use core::{arch::asm, sync::atomic::Ordering}; use crate::utils::{Pair, U128}; // Use distinct operands on z196 or later, otherwise split to lgr and $op. #[cfg(any(target_feature = "distinct-ops", portable_atomic_target_feature = "distinct-ops"))] macro_rules! distinct_op { ($op:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!($op, "k ", $a0, ", ", $a1, ", ", $a2) }; } #[cfg(not(any(target_feature = "distinct-ops", portable_atomic_target_feature = "distinct-ops")))] macro_rules! distinct_op { ($op:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!("lgr ", $a0, ", ", $a1, "\n", $op, " ", $a0, ", ", $a2) }; } // Use selgr$cond on z15 or later, otherwise split to locgr$cond and $op. #[cfg(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", ))] #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] macro_rules! select_op { ($cond:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!("selgr", $cond, " ", $a0, ", ", $a1, ", ", $a2) }; } #[cfg(not(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", )))] #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] macro_rules! select_op { ($cond:tt, $a0:tt, $a1:tt, $a2:tt) => { concat!("lgr ", $a0, ", ", $a2, "\n", "locgr", $cond, " ", $a0, ", ", $a1) }; } #[inline] unsafe fn atomic_load(src: *mut u128, _order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { // atomic load is always SeqCst. let (out_hi, out_lo); asm!( "lpq %r0, 0({src})", src = in(reg) ptr_reg!(src), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") out_hi, out("r1") out_lo, options(nostack, preserves_flags), ); U128 { pair: Pair { hi: out_hi, lo: out_lo } }.whole } } #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; macro_rules! atomic_store { ($fence:tt) => { asm!( "stpq %r0, 0({dst})", $fence, dst = in(reg) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. in("r0") val.pair.hi, in("r1") val.pair.lo, options(nostack, preserves_flags), ) }; } match order { // Relaxed and Release stores are equivalent. Ordering::Relaxed | Ordering::Release => atomic_store!(""), // bcr 14,0 (fast-BCR-serialization) requires z196 or later. #[cfg(any( target_feature = "fast-serialization", portable_atomic_target_feature = "fast-serialization", ))] Ordering::SeqCst => atomic_store!("bcr 14, 0"), #[cfg(not(any( target_feature = "fast-serialization", portable_atomic_target_feature = "fast-serialization", )))] Ordering::SeqCst => atomic_store!("bcr 15, 0"), _ => unreachable!("{:?}", order), } } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, _success: Ordering, _failure: Ordering, ) -> Result { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. let prev = unsafe { // atomic CAS is always SeqCst. let old = U128 { whole: old }; let new = U128 { whole: new }; let (prev_hi, prev_lo); asm!( "cdsg %r0, %r12, 0({dst})", dst = in(reg) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. inout("r0") old.pair.hi => prev_hi, inout("r1") old.pair.lo => prev_lo, in("r12") new.pair.hi, in("r13") new.pair.lo, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole }; if prev == old { Ok(prev) } else { Err(prev) } } // cdsg is always strong. use atomic_compare_exchange as atomic_compare_exchange_weak; #[cfg(not(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", )))] #[inline(always)] unsafe fn atomic_update(dst: *mut u128, order: Ordering, mut f: F) -> u128 where F: FnMut(u128) -> u128, { // SAFETY: the caller must uphold the safety contract. unsafe { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = atomic_load(dst, Ordering::Relaxed); loop { let next = f(prev); match atomic_compare_exchange_weak(dst, prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(x) => prev = x, } } } } #[inline] unsafe fn atomic_swap(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. // // We could use atomic_update here, but using an inline assembly allows omitting // the comparison of results and the storing/comparing of condition flags. // // Do not use atomic_rmw_cas_3 because it needs extra LGR to implement swap. unsafe { // atomic swap is always SeqCst. let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); asm!( "lpq %r0, 0({dst})", "2:", "cdsg %r0, %r12, 0({dst})", "jl 2b", dst = in(reg) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") prev_hi, out("r1") prev_lo, in("r12") val.pair.hi, in("r13") val.pair.lo, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } /// Atomic RMW by CAS loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - val_hi/val_lo pair: val argument (read-only for `$op`) /// - r0/r1 pair: previous value loaded (read-only for `$op`) /// - r12/r13 pair: new value that will be stored // We could use atomic_update here, but using an inline assembly allows omitting // the comparison of results and the storing/comparing of condition flags. macro_rules! atomic_rmw_cas_3 { ($name:ident, [$($reg:tt)*], $($op:tt)*) => { #[inline] unsafe fn $name(dst: *mut u128, val: u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { // atomic RMW is always SeqCst. let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); asm!( "lpq %r0, 0({dst})", "2:", $($op)* "cdsg %r0, %r12, 0({dst})", "jl 2b", dst = in(reg) ptr_reg!(dst), val_hi = in(reg) val.pair.hi, val_lo = in(reg) val.pair.lo, $($reg)* // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") prev_hi, out("r1") prev_lo, out("r12") _, out("r13") _, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } /// Atomic RMW by CAS loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// `$op` can use the following registers: /// - r0/r1 pair: previous value loaded (read-only for `$op`) /// - r12/r13 pair: new value that will be stored // We could use atomic_update here, but using an inline assembly allows omitting // the comparison of results and the storing/comparing of condition flags. macro_rules! atomic_rmw_cas_2 { ($name:ident, $($op:tt)*) => { #[inline] unsafe fn $name(dst: *mut u128, _order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); // SAFETY: the caller must uphold the safety contract. unsafe { // atomic RMW is always SeqCst. let (mut prev_hi, mut prev_lo); asm!( "lpq %r0, 0({dst})", "2:", $($op)* "cdsg %r0, %r12, 0({dst})", "jl 2b", dst = in(reg) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. out("r0") prev_hi, out("r1") prev_lo, out("r12") _, out("r13") _, // Do not use `preserves_flags` because CDSG modifies the condition code. options(nostack), ); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } atomic_rmw_cas_3! { atomic_add, [], distinct_op!("algr", "%r13", "%r1", "{val_lo}"), "lgr %r12, %r0", "alcgr %r12, {val_hi}", } atomic_rmw_cas_3! { atomic_sub, [], distinct_op!("slgr", "%r13", "%r1", "{val_lo}"), "lgr %r12, %r0", "slbgr %r12, {val_hi}", } atomic_rmw_cas_3! { atomic_and, [], distinct_op!("ngr", "%r13", "%r1", "{val_lo}"), distinct_op!("ngr", "%r12", "%r0", "{val_hi}"), } // Use nngrk on z15 or later. #[cfg(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", ))] atomic_rmw_cas_3! { atomic_nand, [], "nngrk %r13, %r1, {val_lo}", "nngrk %r12, %r0, {val_hi}", } #[cfg(not(any( target_feature = "miscellaneous-extensions-3", portable_atomic_target_feature = "miscellaneous-extensions-3", )))] atomic_rmw_cas_3! { atomic_nand, [], distinct_op!("ngr", "%r13", "%r1", "{val_lo}"), "xihf %r13, 4294967295", "xilf %r13, 4294967295", distinct_op!("ngr", "%r12", "%r0", "{val_hi}"), "xihf %r12, 4294967295", "xilf %r12, 4294967295", } atomic_rmw_cas_3! { atomic_or, [], distinct_op!("ogr", "%r13", "%r1", "{val_lo}"), distinct_op!("ogr", "%r12", "%r0", "{val_hi}"), } atomic_rmw_cas_3! { atomic_xor, [], distinct_op!("xgr", "%r13", "%r1", "{val_lo}"), distinct_op!("xgr", "%r12", "%r0", "{val_hi}"), } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_max, [], "clgr %r1, {val_lo}", select_op!("h", "%r12", "%r1", "{val_lo}"), "cgr %r0, {val_hi}", select_op!("h", "%r13", "%r1", "{val_lo}"), "locgre %r13, %r12", select_op!("h", "%r12", "%r0", "{val_hi}"), } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_umax, [tmp = out(reg) _,], "clgr %r1, {val_lo}", select_op!("h", "{tmp}", "%r1", "{val_lo}"), "clgr %r0, {val_hi}", select_op!("h", "%r12", "%r0", "{val_hi}"), select_op!("h", "%r13", "%r1", "{val_lo}"), "cgr %r0, {val_hi}", "locgre %r13, {tmp}", } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_min, [], "clgr %r1, {val_lo}", select_op!("l", "%r12", "%r1", "{val_lo}"), "cgr %r0, {val_hi}", select_op!("l", "%r13", "%r1", "{val_lo}"), "locgre %r13, %r12", select_op!("l", "%r12", "%r0", "{val_hi}"), } #[cfg(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", ))] atomic_rmw_cas_3! { atomic_umin, [tmp = out(reg) _,], "clgr %r1, {val_lo}", select_op!("l", "{tmp}", "%r1", "{val_lo}"), "clgr %r0, {val_hi}", select_op!("l", "%r12", "%r0", "{val_hi}"), select_op!("l", "%r13", "%r1", "{val_lo}"), "cgr %r0, {val_hi}", "locgre %r13, {tmp}", } // We use atomic_update for atomic min/max on pre-z196 because // z10 doesn't seem to have a good way to implement 128-bit min/max. // loc{,g}r requires z196 or later. // https://godbolt.org/z/j8KG9q5oq #[cfg(not(any( target_feature = "load-store-on-cond", portable_atomic_target_feature = "load-store-on-cond", )))] atomic_rmw_by_atomic_update!(cmp); atomic_rmw_cas_2! { atomic_not, "lgr %r13, %r1", "xihf %r13, 4294967295", "xilf %r13, 4294967295", "lgr %r12, %r0", "xihf %r12, 4294967295", "xilf %r12, 4294967295", } atomic_rmw_cas_2! { atomic_neg, "lghi %r13, 0", "slgr %r13, %r1", "lghi %r12, 0", "slbgr %r12, %r0", } #[inline] const fn is_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } const IS_ALWAYS_LOCK_FREE: bool = true; atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/powerpc64.rs0000644000175000017500000010644614661133735022120 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic{I,U}128 implementation on PowerPC64. // // powerpc64 on pwr8+ support 128-bit atomics: // https://github.com/llvm/llvm-project/commit/549e118e93c666914a1045fde38a2cac33e1e445 // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/test/CodeGen/PowerPC/atomics-i128-ldst.ll // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/test/CodeGen/PowerPC/atomics-i128.ll // // powerpc64le is pwr8+ by default https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/PowerPC/PPC.td#L663 // See also https://github.com/rust-lang/rust/issues/59932 // // Note that we do not separate LL and SC into separate functions, but handle // them within a single asm block. This is because it is theoretically possible // for the compiler to insert operations that might clear the reservation between // LL and SC. See aarch64.rs for details. // // Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use // this module and use intrinsics.rs instead. // // Refs: // - Power ISA https://openpowerfoundation.org/specifications/isa // - AIX Assembler language reference https://www.ibm.com/docs/en/aix/7.3?topic=aix-assembler-language-reference // - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit // // Generated asm: // - powerpc64 (pwr8) https://godbolt.org/z/nG5dGa38a // - powerpc64le https://godbolt.org/z/6c99s75e4 include!("macros.rs"); #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[path = "../fallback/outline_atomics.rs"] mod fallback; // On musl with static linking, it seems that getauxval is not always available. // See detect/auxv.rs for more. #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any(test, portable_atomic_outline_atomics))] // TODO(powerpc64): currently disabled by default #[cfg(any( test, not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )), ))] #[cfg(any( all( target_os = "linux", any( target_env = "gnu", all(any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static")), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ))] #[path = "detect/auxv.rs"] mod detect; use core::{arch::asm, sync::atomic::Ordering}; use crate::utils::{Pair, U128}; macro_rules! debug_assert_pwr8 { () => { #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] { debug_assert!(detect::detect().has_quadword_atomics()); } }; } // Refs: https://www.ibm.com/docs/en/aix/7.3?topic=ops-machine-pseudo-op // // This is similar to #[target_feature(enable = "quadword-atomics")], except that there are // no compiler guarantees regarding (un)inlining, and the scope is within an asm // block rather than a function. We use this directive because #[target_feature(enable = "quadword-atomics")] // is not supported as of Rust 1.70-nightly. // // start_pwr8 and end_pwr8 must be used in pairs. // // Note: If power8 instructions are not available at compile-time, we must guarantee that // the function that uses it is not inlined into a function where it is not // clear whether power8 instructions are available. Otherwise, (even if we checked whether // power8 instructions are available at run-time) optimizations that reorder its // instructions across the if condition might introduce undefined behavior. // (see also https://rust-lang.github.io/rfcs/2045-target-feature.html#safely-inlining-target_feature-functions-on-more-contexts) // However, our code uses the ifunc helper macro that works with function pointers, // so we don't have to worry about this unless calling without helper macro. macro_rules! start_pwr8 { () => { ".machine push\n.machine power8" }; } macro_rules! end_pwr8 { () => { ".machine pop" }; } macro_rules! atomic_rmw { ($op:ident, $order:ident) => { match $order { Ordering::Relaxed => $op!("", ""), Ordering::Acquire => $op!("lwsync", ""), Ordering::Release => $op!("", "lwsync"), Ordering::AcqRel => $op!("lwsync", "lwsync"), Ordering::SeqCst => $op!("lwsync", "sync"), _ => unreachable!("{:?}", $order), } }; } // Extracts and checks the EQ bit of cr0. #[inline] fn extract_cr0(r: u64) -> bool { r & 0x20000000 != 0 } #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use atomic_load_pwr8 as atomic_load; #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[inline] unsafe fn atomic_load(src: *mut u128, order: Ordering) -> u128 { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(src: *mut u128) -> u128; atomic_load_pwr8_relaxed = atomic_load_pwr8(Ordering::Relaxed); atomic_load_pwr8_acquire = atomic_load_pwr8(Ordering::Acquire); atomic_load_pwr8_seqcst = atomic_load_pwr8(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls atomic_load_pwr8 if quadword-atomics is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_quadword_atomics() { atomic_load_pwr8_relaxed } else { fallback::atomic_load_non_seqcst } }) } Ordering::Acquire => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_quadword_atomics() { atomic_load_pwr8_acquire } else { fallback::atomic_load_non_seqcst } }) } Ordering::SeqCst => { ifunc!(unsafe fn(src: *mut u128) -> u128 { if detect::detect().has_quadword_atomics() { atomic_load_pwr8_seqcst } else { fallback::atomic_load_seqcst } }) } _ => unreachable!("{:?}", order), } } } #[inline] unsafe fn atomic_load_pwr8(src: *mut u128, order: Ordering) -> u128 { debug_assert!(src as usize % 16 == 0); debug_assert_pwr8!(); // SAFETY: the caller must uphold the safety contract. // // Refs: "3.3.4 Fixed Point Load and Store Quadword Instructions" of Power ISA unsafe { let (out_hi, out_lo); macro_rules! atomic_load_acquire { ($release:tt) => { asm!( start_pwr8!(), $release, "lq %r4, 0({src})", // Lightweight acquire sync // Refs: https://github.com/boostorg/atomic/blob/boost-1.79.0/include/boost/atomic/detail/core_arch_ops_gcc_ppc.hpp#L47-L62 "cmpd %cr7, %r4, %r4", "bne- %cr7, 2f", "2:", "isync", end_pwr8!(), src = in(reg_nonzero) ptr_reg!(src), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r4") out_hi, out("r5") out_lo, out("cr7") _, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => { asm!( start_pwr8!(), "lq %r4, 0({src})", end_pwr8!(), src = in(reg_nonzero) ptr_reg!(src), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r4") out_hi, out("r5") out_lo, options(nostack, preserves_flags, readonly), ); } Ordering::Acquire => atomic_load_acquire!(""), Ordering::SeqCst => atomic_load_acquire!("sync"), _ => unreachable!("{:?}", order), } U128 { pair: Pair { hi: out_hi, lo: out_lo } }.whole } } #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use atomic_store_pwr8 as atomic_store; #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[inline] unsafe fn atomic_store(dst: *mut u128, val: u128, order: Ordering) { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn(dst: *mut u128, val: u128); atomic_store_pwr8_relaxed = atomic_store_pwr8(Ordering::Relaxed); atomic_store_pwr8_release = atomic_store_pwr8(Ordering::Release); atomic_store_pwr8_seqcst = atomic_store_pwr8(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls atomic_store_pwr8 if quadword-atomics is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { if detect::detect().has_quadword_atomics() { atomic_store_pwr8_relaxed } else { fallback::atomic_store_non_seqcst } }); } Ordering::Release => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { if detect::detect().has_quadword_atomics() { atomic_store_pwr8_release } else { fallback::atomic_store_non_seqcst } }); } Ordering::SeqCst => { ifunc!(unsafe fn(dst: *mut u128, val: u128) { if detect::detect().has_quadword_atomics() { atomic_store_pwr8_seqcst } else { fallback::atomic_store_seqcst } }); } _ => unreachable!("{:?}", order), } } } #[inline] unsafe fn atomic_store_pwr8(dst: *mut u128, val: u128, order: Ordering) { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); // SAFETY: the caller must uphold the safety contract. // // Refs: "3.3.4 Fixed Point Load and Store Quadword Instructions" of Power ISA unsafe { let val = U128 { whole: val }; macro_rules! atomic_store { ($release:tt) => { asm!( start_pwr8!(), $release, "stq %r4, 0({dst})", end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. in("r4") val.pair.hi, in("r5") val.pair.lo, options(nostack, preserves_flags), ) }; } match order { Ordering::Relaxed => atomic_store!(""), Ordering::Release => atomic_store!("lwsync"), Ordering::SeqCst => atomic_store!("sync"), _ => unreachable!("{:?}", order), } } } #[inline] unsafe fn atomic_compare_exchange( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { let success = crate::utils::upgrade_success_ordering(success, failure); #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] // SAFETY: the caller must uphold the safety contract. // cfg guarantees that quadword atomics instructions are available at compile-time. let (prev, ok) = unsafe { atomic_compare_exchange_pwr8(dst, old, new, success) }; #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] // SAFETY: the caller must uphold the safety contract. let (prev, ok) = unsafe { atomic_compare_exchange_ifunc(dst, old, new, success) }; if ok { Ok(prev) } else { Err(prev) } } #[inline] unsafe fn atomic_compare_exchange_pwr8( dst: *mut u128, old: u128, new: u128, order: Ordering, ) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); // SAFETY: the caller must uphold the safety contract. // // Refs: "4.6.2.2 128-bit Load And Reserve and Store Conditional Instructions" of Power ISA unsafe { let old = U128 { whole: old }; let new = U128 { whole: new }; let (mut prev_hi, mut prev_lo); let mut r; macro_rules! cmpxchg { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, "2:", "lqarx %r8, 0, {dst}", "xor {tmp_lo}, %r9, {old_lo}", "xor {tmp_hi}, %r8, {old_hi}", "or. {tmp_lo}, {tmp_lo}, {tmp_hi}", "bne %cr0, 3f", // jump if compare failed "stqcx. %r6, 0, {dst}", "bne %cr0, 2b", // continue loop if store failed "3:", // if compare failed EQ bit is cleared, if stqcx succeeds EQ bit is set. "mfcr {tmp_lo}", $acquire, end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), old_hi = in(reg) old.pair.hi, old_lo = in(reg) old.pair.lo, tmp_hi = out(reg) _, tmp_lo = out(reg) r, // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. in("r6") new.pair.hi, in("r7") new.pair.lo, out("r8") prev_hi, out("r9") prev_lo, out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(cmpxchg, order); (U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole, extract_cr0(r)) } } // Always use strong CAS for outline-atomics. #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] use atomic_compare_exchange as atomic_compare_exchange_weak; #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] #[inline] unsafe fn atomic_compare_exchange_weak( dst: *mut u128, old: u128, new: u128, success: Ordering, failure: Ordering, ) -> Result { let success = crate::utils::upgrade_success_ordering(success, failure); // SAFETY: the caller must uphold the safety contract. // cfg guarantees that quadword atomics instructions are available at compile-time. let (prev, ok) = unsafe { atomic_compare_exchange_weak_pwr8(dst, old, new, success) }; if ok { Ok(prev) } else { Err(prev) } } #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] #[inline] unsafe fn atomic_compare_exchange_weak_pwr8( dst: *mut u128, old: u128, new: u128, order: Ordering, ) -> (u128, bool) { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); // SAFETY: the caller must uphold the safety contract. // // Refs: "4.6.2.2 128-bit Load And Reserve and Store Conditional Instructions" of Power ISA unsafe { let old = U128 { whole: old }; let new = U128 { whole: new }; let (mut prev_hi, mut prev_lo); let mut r; macro_rules! cmpxchg_weak { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, "lqarx %r8, 0, {dst}", "xor {tmp_lo}, %r9, {old_lo}", "xor {tmp_hi}, %r8, {old_hi}", "or. {tmp_lo}, {tmp_lo}, {tmp_hi}", "bne %cr0, 3f", // jump if compare failed "stqcx. %r6, 0, {dst}", "3:", // if compare or stqcx failed EQ bit is cleared, if stqcx succeeds EQ bit is set. "mfcr {tmp_lo}", $acquire, end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), old_hi = in(reg) old.pair.hi, old_lo = in(reg) old.pair.lo, tmp_hi = out(reg) _, tmp_lo = out(reg) r, // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. in("r6") new.pair.hi, in("r7") new.pair.lo, out("r8") prev_hi, out("r9") prev_lo, out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(cmpxchg_weak, order); (U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole, extract_cr0(r)) } } #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use atomic_swap_pwr8 as atomic_swap; // Do not use atomic_rmw_ll_sc_3 because it needs extra MR to implement swap. #[inline] unsafe fn atomic_swap_pwr8(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); macro_rules! swap { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, "2:", "lqarx %r6, 0, {dst}", "stqcx. %r8, 0, {dst}", "bne %cr0, 2b", $acquire, end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r6") prev_hi, out("r7") prev_lo, in("r8") val.pair.hi, in("r9") val.pair.lo, out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(swap, order); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } /// Atomic RMW by LL/SC loop (3 arguments) /// `unsafe fn(dst: *mut u128, val: u128, order: Ordering) -> u128;` /// /// $op can use the following registers: /// - val_hi/val_lo pair: val argument (read-only for `$op`) /// - r6/r7 pair: previous value loaded by ll (read-only for `$op`) /// - r8/r9 pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_3 { ($name:ident as $reexport_name:ident, [$($reg:tt)*], $($op:tt)*) => { #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use $name as $reexport_name; #[inline] unsafe fn $name(dst: *mut u128, val: u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); // SAFETY: the caller must uphold the safety contract. unsafe { let val = U128 { whole: val }; let (mut prev_hi, mut prev_lo); macro_rules! op { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, "2:", "lqarx %r6, 0, {dst}", $($op)* "stqcx. %r8, 0, {dst}", "bne %cr0, 2b", $acquire, end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), val_hi = in(reg) val.pair.hi, val_lo = in(reg) val.pair.lo, $($reg)* // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r6") prev_hi, out("r7") prev_lo, out("r8") _, // new (hi) out("r9") _, // new (lo) out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } /// Atomic RMW by LL/SC loop (2 arguments) /// `unsafe fn(dst: *mut u128, order: Ordering) -> u128;` /// /// $op can use the following registers: /// - r6/r7 pair: previous value loaded by ll (read-only for `$op`) /// - r8/r9 pair: new value that will be stored by sc macro_rules! atomic_rmw_ll_sc_2 { ($name:ident as $reexport_name:ident, [$($reg:tt)*], $($op:tt)*) => { #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use $name as $reexport_name; #[inline] unsafe fn $name(dst: *mut u128, order: Ordering) -> u128 { debug_assert!(dst as usize % 16 == 0); debug_assert_pwr8!(); // SAFETY: the caller must uphold the safety contract. unsafe { let (mut prev_hi, mut prev_lo); macro_rules! op { ($acquire:tt, $release:tt) => { asm!( start_pwr8!(), $release, "2:", "lqarx %r6, 0, {dst}", $($op)* "stqcx. %r8, 0, {dst}", "bne %cr0, 2b", $acquire, end_pwr8!(), dst = in(reg_nonzero) ptr_reg!(dst), $($reg)* // Quadword atomic instructions work with even/odd pair of specified register and subsequent register. // We cannot use r1 (sp) and r2 (system reserved), so start with r4 or grater. out("r6") prev_hi, out("r7") prev_lo, out("r8") _, // new (hi) out("r9") _, // new (lo) out("cr0") _, options(nostack, preserves_flags), ) }; } atomic_rmw!(op, order); U128 { pair: Pair { hi: prev_hi, lo: prev_lo } }.whole } } }; } atomic_rmw_ll_sc_3! { atomic_add_pwr8 as atomic_add, [out("xer") _,], "addc %r9, {val_lo}, %r7", "adde %r8, {val_hi}, %r6", } atomic_rmw_ll_sc_3! { atomic_sub_pwr8 as atomic_sub, [out("xer") _,], "subc %r9, %r7, {val_lo}", "subfe %r8, {val_hi}, %r6", } atomic_rmw_ll_sc_3! { atomic_and_pwr8 as atomic_and, [], "and %r9, {val_lo}, %r7", "and %r8, {val_hi}, %r6", } atomic_rmw_ll_sc_3! { atomic_nand_pwr8 as atomic_nand, [], "nand %r9, {val_lo}, %r7", "nand %r8, {val_hi}, %r6", } atomic_rmw_ll_sc_3! { atomic_or_pwr8 as atomic_or, [], "or %r9, {val_lo}, %r7", "or %r8, {val_hi}, %r6", } atomic_rmw_ll_sc_3! { atomic_xor_pwr8 as atomic_xor, [], "xor %r9, {val_lo}, %r7", "xor %r8, {val_hi}, %r6", } atomic_rmw_ll_sc_3! { atomic_max_pwr8 as atomic_max, [out("cr1") _,], "cmpld %r7, {val_lo}", // (unsigned) compare lo 64-bit, store result to cr0 "iselgt %r9, %r7, {val_lo}", // select lo 64-bit based on GT bit in cr0 "cmpd %cr1, %r6, {val_hi}", // (signed) compare hi 64-bit, store result to cr1 "isel %r8, %r7, {val_lo}, 5", // select lo 64-bit based on GT bit in cr1 "cmpld %r6, {val_hi}", // (unsigned) compare hi 64-bit, store result to cr0 "iseleq %r9, %r9, %r8", // select lo 64-bit based on EQ bit in cr0 "isel %r8, %r6, {val_hi}, 5", // select hi 64-bit based on GT bit in cr1 } atomic_rmw_ll_sc_3! { atomic_umax_pwr8 as atomic_umax, [], "cmpld %r7, {val_lo}", // compare lo 64-bit, store result to cr0 "iselgt %r9, %r7, {val_lo}", // select lo 64-bit based on GT bit in cr0 "cmpld %r6, {val_hi}", // compare hi 64-bit, store result to cr0 "iselgt %r8, %r7, {val_lo}", // select lo 64-bit based on GT bit in cr0 "iseleq %r9, %r9, %r8", // select lo 64-bit based on EQ bit in cr0 "iselgt %r8, %r6, {val_hi}", // select hi 64-bit based on GT bit in cr0 } atomic_rmw_ll_sc_3! { atomic_min_pwr8 as atomic_min, [out("cr1") _,], "cmpld %r7, {val_lo}", // (unsigned) compare lo 64-bit, store result to cr0 "isellt %r9, %r7, {val_lo}", // select lo 64-bit based on LT bit in cr0 "cmpd %cr1, %r6, {val_hi}", // (signed) compare hi 64-bit, store result to cr1 "isel %r8, %r7, {val_lo}, 4", // select lo 64-bit based on LT bit in cr1 "cmpld %r6, {val_hi}", // (unsigned) compare hi 64-bit, store result to cr0 "iseleq %r9, %r9, %r8", // select lo 64-bit based on EQ bit in cr0 "isel %r8, %r6, {val_hi}, 4", // select hi 64-bit based on LT bit in cr1 } atomic_rmw_ll_sc_3! { atomic_umin_pwr8 as atomic_umin, [], "cmpld %r7, {val_lo}", // compare lo 64-bit, store result to cr0 "isellt %r9, %r7, {val_lo}", // select lo 64-bit based on LT bit in cr0 "cmpld %r6, {val_hi}", // compare hi 64-bit, store result to cr0 "isellt %r8, %r7, {val_lo}", // select lo 64-bit based on LT bit in cr0 "iseleq %r9, %r9, %r8", // select lo 64-bit based on EQ bit in cr0 "isellt %r8, %r6, {val_hi}", // select hi 64-bit based on LT bit in cr0 } #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] use atomic_not_pwr8 as atomic_not; #[inline] unsafe fn atomic_not_pwr8(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_xor_pwr8(dst, !0, order) } } #[cfg(portable_atomic_llvm_16)] atomic_rmw_ll_sc_2! { atomic_neg_pwr8 as atomic_neg, [out("xer") _,], "subfic %r9, %r7, 0", "subfze %r8, %r6", } // LLVM 15 miscompiles subfic. #[cfg(not(portable_atomic_llvm_16))] atomic_rmw_ll_sc_2! { atomic_neg_pwr8 as atomic_neg, [zero = in(reg) 0_u64, out("xer") _,], "subc %r9, {zero}, %r7", "subfze %r8, %r6", } macro_rules! atomic_rmw_with_ifunc { ( unsafe fn $name:ident($($arg:tt)*) $(-> $ret_ty:ty)?; pwr8 = $pwr8_fn:ident; non_seqcst_fallback = $non_seqcst_fallback_fn:ident; seqcst_fallback = $seqcst_fallback_fn:ident; ) => { #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] #[inline] unsafe fn $name($($arg)*, order: Ordering) $(-> $ret_ty)? { fn_alias! { // inline(never) is just a hint and also not strictly necessary // because we use ifunc helper macro, but used for clarity. #[inline(never)] unsafe fn($($arg)*) $(-> $ret_ty)?; pwr8_relaxed_fn = $pwr8_fn(Ordering::Relaxed); pwr8_acquire_fn = $pwr8_fn(Ordering::Acquire); pwr8_release_fn = $pwr8_fn(Ordering::Release); pwr8_acqrel_fn = $pwr8_fn(Ordering::AcqRel); pwr8_seqcst_fn = $pwr8_fn(Ordering::SeqCst); } // SAFETY: the caller must uphold the safety contract. // we only calls pwr8_fn if quadword-atomics is available. unsafe { match order { Ordering::Relaxed => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_relaxed_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Acquire => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_acquire_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::Release => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_release_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::AcqRel => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_acqrel_fn } else { fallback::$non_seqcst_fallback_fn } }) } Ordering::SeqCst => { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if detect::detect().has_quadword_atomics() { pwr8_seqcst_fn } else { fallback::$seqcst_fallback_fn } }) } _ => unreachable!("{:?}", order), } } } }; } atomic_rmw_with_ifunc! { unsafe fn atomic_compare_exchange_ifunc(dst: *mut u128, old: u128, new: u128) -> (u128, bool); pwr8 = atomic_compare_exchange_pwr8; non_seqcst_fallback = atomic_compare_exchange_non_seqcst; seqcst_fallback = atomic_compare_exchange_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_swap(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_swap_pwr8; non_seqcst_fallback = atomic_swap_non_seqcst; seqcst_fallback = atomic_swap_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_add(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_add_pwr8; non_seqcst_fallback = atomic_add_non_seqcst; seqcst_fallback = atomic_add_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_sub(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_sub_pwr8; non_seqcst_fallback = atomic_sub_non_seqcst; seqcst_fallback = atomic_sub_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_and(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_and_pwr8; non_seqcst_fallback = atomic_and_non_seqcst; seqcst_fallback = atomic_and_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_nand(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_nand_pwr8; non_seqcst_fallback = atomic_nand_non_seqcst; seqcst_fallback = atomic_nand_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_or(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_or_pwr8; non_seqcst_fallback = atomic_or_non_seqcst; seqcst_fallback = atomic_or_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_xor(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_xor_pwr8; non_seqcst_fallback = atomic_xor_non_seqcst; seqcst_fallback = atomic_xor_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_max(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_max_pwr8; non_seqcst_fallback = atomic_max_non_seqcst; seqcst_fallback = atomic_max_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_umax(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_umax_pwr8; non_seqcst_fallback = atomic_umax_non_seqcst; seqcst_fallback = atomic_umax_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_min(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_min_pwr8; non_seqcst_fallback = atomic_min_non_seqcst; seqcst_fallback = atomic_min_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_umin(dst: *mut u128, val: u128) -> u128; pwr8 = atomic_umin_pwr8; non_seqcst_fallback = atomic_umin_non_seqcst; seqcst_fallback = atomic_umin_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_not(dst: *mut u128) -> u128; pwr8 = atomic_not_pwr8; non_seqcst_fallback = atomic_not_non_seqcst; seqcst_fallback = atomic_not_seqcst; } atomic_rmw_with_ifunc! { unsafe fn atomic_neg(dst: *mut u128) -> u128; pwr8 = atomic_neg_pwr8; non_seqcst_fallback = atomic_neg_non_seqcst; seqcst_fallback = atomic_neg_seqcst; } #[inline] fn is_lock_free() -> bool { #[cfg(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ))] { // lqarx and stqcx. instructions are statically available. true } #[cfg(not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )))] { detect::detect().has_quadword_atomics() } } const IS_ALWAYS_LOCK_FREE: bool = cfg!(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )); atomic128!(AtomicI128, i128, atomic_max, atomic_min); atomic128!(AtomicU128, u128, atomic_umax, atomic_umin); #[cfg(test)] mod tests { use super::*; test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u128); } portable-atomic/src/imp/atomic128/macros.rs0000644000175000017500000003676114661133735021555 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT macro_rules! atomic128 { ($atomic_type:ident, $int_type:ident, $atomic_max:ident, $atomic_min:ident) => { #[repr(C, align(16))] pub(crate) struct $atomic_type { v: core::cell::UnsafeCell<$int_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by atomic intrinsics. unsafe impl Sync for $atomic_type {} impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: core::cell::UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { is_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } #[inline] pub(crate) fn get_mut(&mut self) -> &mut $int_type { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.v.get() } } #[inline] pub(crate) fn into_inner(self) -> $int_type { self.v.into_inner() } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_load(self.v.get().cast::(), order) as $int_type } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_store(self.v.get().cast::(), val as u128, order) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn swap(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_swap(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { match atomic_compare_exchange( self.v.get().cast::(), current as u128, new as u128, success, failure, ) { Ok(v) => Ok(v as $int_type), Err(v) => Err(v as $int_type), } } } #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { match atomic_compare_exchange_weak( self.v.get().cast::(), current as u128, new as u128, success, failure, ) { Ok(v) => Ok(v as $int_type), Err(v) => Err(v as $int_type), } } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_add(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_sub(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_and(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_nand(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_or(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_xor(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { $atomic_max(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { $atomic_min(self.v.get().cast::(), val as u128, order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_not(self.v.get().cast::(), order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn fetch_neg(&self, order: Ordering) -> $int_type { // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_neg(self.v.get().cast::(), order) as $int_type } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; } #[cfg(any(target_arch = "powerpc64", target_arch = "s390x", target_arch = "x86_64"))] #[allow(unused_macros)] // also used by intrinsics.rs macro_rules! atomic_rmw_by_atomic_update { () => { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_swap(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |_| val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_add(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x.wrapping_add(val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_sub(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x.wrapping_sub(val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_and(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x & val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_nand(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| !(x & val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_or(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x | val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_xor(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| x ^ val) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_not(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| !x) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_neg(dst: *mut u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, u128::wrapping_neg) } } atomic_rmw_by_atomic_update!(cmp); }; (cmp) => { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_max(dst: *mut u128, val: u128, order: Ordering) -> u128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::max(x as i128, val as i128) as u128) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umax(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::max(x, val)) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_min(dst: *mut u128, val: u128, order: Ordering) -> u128 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::min(x as i128, val as i128) as u128) } } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn atomic_umin(dst: *mut u128, val: u128, order: Ordering) -> u128 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update(dst, order, |x| core::cmp::min(x, val)) } } }; } portable-atomic/src/imp/atomic128/detect/0000775000175000017500000000000014661133735021160 5ustar jamespagejamespageportable-atomic/src/imp/atomic128/detect/common.rs0000644000175000017500000003434314661133735023023 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT #[derive(Clone, Copy)] pub(crate) struct CpuInfo(u32); impl CpuInfo { const INIT: u32 = 0; #[inline] fn set(&mut self, bit: u32) { self.0 = set(self.0, bit); } #[inline] fn test(self, bit: u32) -> bool { test(self.0, bit) } } #[inline] fn set(x: u32, bit: u32) -> u32 { x | 1 << bit } #[inline] fn test(x: u32, bit: u32) -> bool { x & (1 << bit) != 0 } #[inline] pub(crate) fn detect() -> CpuInfo { use core::sync::atomic::{AtomicU32, Ordering}; static CACHE: AtomicU32 = AtomicU32::new(0); let mut info = CpuInfo(CACHE.load(Ordering::Relaxed)); if info.0 != 0 { return info; } info.set(CpuInfo::INIT); // Note: detect_false cfg is intended to make it easy for portable-atomic developers to // test cases such as has_cmpxchg16b == false, has_lse == false, // __kuser_helper_version < 5, etc., and is not a public API. if !cfg!(portable_atomic_test_outline_atomics_detect_false) { _detect(&mut info); } CACHE.store(info.0, Ordering::Relaxed); info } #[cfg(target_arch = "aarch64")] impl CpuInfo { /// Whether FEAT_LSE is available const HAS_LSE: u32 = 1; /// Whether FEAT_LSE2 is available #[cfg_attr(not(test), allow(dead_code))] const HAS_LSE2: u32 = 2; /// Whether FEAT_LSE128 is available // This is currently only used in tests. #[cfg(test)] const HAS_LSE128: u32 = 3; /// Whether FEAT_LRCPC3 is available // This is currently only used in tests. #[cfg(test)] const HAS_RCPC3: u32 = 4; #[cfg(any(test, not(any(target_feature = "lse", portable_atomic_target_feature = "lse"))))] #[inline] pub(crate) fn has_lse(self) -> bool { self.test(CpuInfo::HAS_LSE) } #[cfg_attr(not(test), allow(dead_code))] #[cfg(any(test, not(any(target_feature = "lse2", portable_atomic_target_feature = "lse2"))))] #[inline] pub(crate) fn has_lse2(self) -> bool { self.test(CpuInfo::HAS_LSE2) } #[cfg(test)] #[inline] pub(crate) fn has_lse128(self) -> bool { self.test(CpuInfo::HAS_LSE128) } #[cfg(test)] #[inline] pub(crate) fn has_rcpc3(self) -> bool { self.test(CpuInfo::HAS_RCPC3) } } #[cfg(target_arch = "x86_64")] impl CpuInfo { /// Whether CMPXCHG16B is available const HAS_CMPXCHG16B: u32 = 1; /// Whether VMOVDQA is atomic const HAS_VMOVDQA_ATOMIC: u32 = 2; #[cfg(any( test, not(any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b")), ))] #[inline] pub(crate) fn has_cmpxchg16b(self) -> bool { self.test(CpuInfo::HAS_CMPXCHG16B) } #[inline] pub(crate) fn has_vmovdqa_atomic(self) -> bool { self.test(CpuInfo::HAS_VMOVDQA_ATOMIC) } } #[cfg(target_arch = "powerpc64")] impl CpuInfo { /// Whether lqarx and stqcx. instructions are available const HAS_QUADWORD_ATOMICS: u32 = 1; #[cfg(any( test, not(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )), ))] #[inline] pub(crate) fn has_quadword_atomics(self) -> bool { self.test(CpuInfo::HAS_QUADWORD_ATOMICS) } } // core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 #[cfg(any(target_arch = "aarch64", target_arch = "powerpc64"))] #[cfg(not(windows))] #[allow(dead_code, non_camel_case_types)] mod c_types { pub(crate) type c_void = core::ffi::c_void; // c_{,u}int is {i,u}32 on non-16-bit architectures // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/ffi/mod.rs#L160 // (16-bit architectures currently don't use this module) pub(crate) type c_int = i32; pub(crate) type c_uint = u32; // c_{,u}long is {i,u}64 on non-Windows 64-bit targets, otherwise is {i,u}32 // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/ffi/mod.rs#L176 // (Windows currently doesn't use this module - this module is cfg(not(windows))) #[cfg(target_pointer_width = "64")] pub(crate) type c_long = i64; #[cfg(not(target_pointer_width = "64"))] pub(crate) type c_long = i32; #[cfg(target_pointer_width = "64")] pub(crate) type c_ulong = u64; #[cfg(not(target_pointer_width = "64"))] pub(crate) type c_ulong = u32; // c_size_t is currently always usize // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/ffi/mod.rs#L88 pub(crate) type c_size_t = usize; // c_char is u8 by default on most non-Apple/non-Windows ARM/PowerPC/RISC-V/s390x/Hexagon targets // (Linux/Android/FreeBSD/NetBSD/OpenBSD/VxWorks/Fuchsia/QNX Neutrino/Horizon/AIX/z/OS) // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/ffi/mod.rs#L104 // https://github.com/llvm/llvm-project/blob/9734b2256d89cb4c61a4dbf4a3c3f3f942fe9b8c/lldb/source/Utility/ArchSpec.cpp#L712 // RISC-V https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/HEAD/riscv-cc.adoc#cc-type-representations // Hexagon https://lists.llvm.org/pipermail/llvm-dev/attachments/20190916/21516a52/attachment-0001.pdf // AIX https://www.ibm.com/docs/en/xl-c-aix/13.1.2?topic=descriptions-qchars // z/OS https://www.ibm.com/docs/en/zos/2.5.0?topic=specifiers-character-types // (macOS is currently the only Apple target that uses this module, and Windows currently doesn't use this module) #[cfg(not(target_os = "macos"))] pub(crate) type c_char = u8; // c_char is i8 on all Apple targets #[cfg(target_os = "macos")] pub(crate) type c_char = i8; // Static assertions for C type definitions. #[cfg(test)] const _: fn() = || { use test_helper::{libc, sys}; let _: c_int = 0 as std::os::raw::c_int; let _: c_uint = 0 as std::os::raw::c_uint; let _: c_long = 0 as std::os::raw::c_long; let _: c_ulong = 0 as std::os::raw::c_ulong; let _: c_size_t = 0 as libc::size_t; // std::os::raw::c_size_t is unstable let _: c_char = 0 as std::os::raw::c_char; let _: c_char = 0 as sys::c_char; }; } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests_common { use super::*; #[test] fn test_bit_flags() { let mut x = CpuInfo(0); #[cfg(target_arch = "aarch64")] { assert!(!x.test(CpuInfo::INIT)); assert!(!x.test(CpuInfo::HAS_LSE)); assert!(!x.test(CpuInfo::HAS_LSE2)); assert!(!x.test(CpuInfo::HAS_LSE128)); assert!(!x.test(CpuInfo::HAS_RCPC3)); x.set(CpuInfo::INIT); assert!(x.test(CpuInfo::INIT)); assert!(!x.test(CpuInfo::HAS_LSE)); assert!(!x.test(CpuInfo::HAS_LSE2)); assert!(!x.test(CpuInfo::HAS_LSE128)); assert!(!x.test(CpuInfo::HAS_RCPC3)); x.set(CpuInfo::HAS_LSE); assert!(x.test(CpuInfo::INIT)); assert!(x.test(CpuInfo::HAS_LSE)); assert!(!x.test(CpuInfo::HAS_LSE2)); assert!(!x.test(CpuInfo::HAS_LSE128)); assert!(!x.test(CpuInfo::HAS_RCPC3)); x.set(CpuInfo::HAS_LSE2); assert!(x.test(CpuInfo::INIT)); assert!(x.test(CpuInfo::HAS_LSE)); assert!(x.test(CpuInfo::HAS_LSE2)); assert!(!x.test(CpuInfo::HAS_LSE128)); assert!(!x.test(CpuInfo::HAS_RCPC3)); x.set(CpuInfo::HAS_LSE128); assert!(x.test(CpuInfo::INIT)); assert!(x.test(CpuInfo::HAS_LSE)); assert!(x.test(CpuInfo::HAS_LSE2)); assert!(x.test(CpuInfo::HAS_LSE128)); assert!(!x.test(CpuInfo::HAS_RCPC3)); x.set(CpuInfo::HAS_RCPC3); assert!(x.test(CpuInfo::INIT)); assert!(x.test(CpuInfo::HAS_LSE)); assert!(x.test(CpuInfo::HAS_LSE2)); assert!(x.test(CpuInfo::HAS_LSE128)); assert!(x.test(CpuInfo::HAS_RCPC3)); } #[cfg(target_arch = "x86_64")] { assert!(!x.test(CpuInfo::INIT)); assert!(!x.test(CpuInfo::HAS_CMPXCHG16B)); assert!(!x.test(CpuInfo::HAS_VMOVDQA_ATOMIC)); x.set(CpuInfo::INIT); assert!(x.test(CpuInfo::INIT)); assert!(!x.test(CpuInfo::HAS_CMPXCHG16B)); assert!(!x.test(CpuInfo::HAS_VMOVDQA_ATOMIC)); x.set(CpuInfo::HAS_CMPXCHG16B); assert!(x.test(CpuInfo::INIT)); assert!(x.test(CpuInfo::HAS_CMPXCHG16B)); assert!(!x.test(CpuInfo::HAS_VMOVDQA_ATOMIC)); x.set(CpuInfo::HAS_VMOVDQA_ATOMIC); assert!(x.test(CpuInfo::INIT)); assert!(x.test(CpuInfo::HAS_CMPXCHG16B)); assert!(x.test(CpuInfo::HAS_VMOVDQA_ATOMIC)); } #[cfg(target_arch = "powerpc64")] { assert!(!x.test(CpuInfo::INIT)); assert!(!x.test(CpuInfo::HAS_QUADWORD_ATOMICS)); x.set(CpuInfo::INIT); assert!(x.test(CpuInfo::INIT)); assert!(!x.test(CpuInfo::HAS_QUADWORD_ATOMICS)); x.set(CpuInfo::HAS_QUADWORD_ATOMICS); assert!(x.test(CpuInfo::INIT)); assert!(x.test(CpuInfo::HAS_QUADWORD_ATOMICS)); } } #[test] fn print_features() { use std::{fmt::Write as _, io::Write, string::String}; let mut features = String::new(); macro_rules! print_feature { ($name:expr, $enabled:expr $(,)?) => {{ let _ = writeln!(features, " {}: {}", $name, $enabled); }}; } #[cfg(target_arch = "aarch64")] { features.push_str("run-time:\n"); print_feature!("lse", detect().test(CpuInfo::HAS_LSE)); print_feature!("lse2", detect().test(CpuInfo::HAS_LSE2)); print_feature!("lse128", detect().test(CpuInfo::HAS_LSE128)); print_feature!("rcpc3", detect().test(CpuInfo::HAS_RCPC3)); features.push_str("compile-time:\n"); print_feature!( "lse", cfg!(any(target_feature = "lse", portable_atomic_target_feature = "lse")), ); print_feature!( "lse2", cfg!(any(target_feature = "lse2", portable_atomic_target_feature = "lse2")), ); } #[cfg(target_arch = "x86_64")] { features.push_str("run-time:\n"); print_feature!("cmpxchg16b", detect().test(CpuInfo::HAS_CMPXCHG16B)); print_feature!("vmovdqa-atomic", detect().test(CpuInfo::HAS_VMOVDQA_ATOMIC)); features.push_str("compile-time:\n"); print_feature!( "cmpxchg16b", cfg!(any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", )), ); } #[cfg(target_arch = "powerpc64")] { features.push_str("run-time:\n"); print_feature!("quadword-atomics", detect().test(CpuInfo::HAS_QUADWORD_ATOMICS)); features.push_str("compile-time:\n"); print_feature!( "quadword-atomics", cfg!(any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", )), ); } let stdout = std::io::stderr(); let mut stdout = stdout.lock(); let _ = stdout.write_all(features.as_bytes()); } #[cfg(target_arch = "x86_64")] #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_detect() { if detect().has_cmpxchg16b() { assert!(detect().test(CpuInfo::HAS_CMPXCHG16B)); } else { assert!(!detect().test(CpuInfo::HAS_CMPXCHG16B)); } if detect().has_vmovdqa_atomic() { assert!(detect().test(CpuInfo::HAS_VMOVDQA_ATOMIC)); } else { assert!(!detect().test(CpuInfo::HAS_VMOVDQA_ATOMIC)); } } #[cfg(target_arch = "aarch64")] #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_detect() { let proc_cpuinfo = test_helper::cpuinfo::ProcCpuinfo::new(); if detect().has_lse() { assert!(detect().test(CpuInfo::HAS_LSE)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(proc_cpuinfo.lse); } } else { assert!(!detect().test(CpuInfo::HAS_LSE)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(!proc_cpuinfo.lse); } } if detect().has_lse2() { assert!(detect().test(CpuInfo::HAS_LSE)); assert!(detect().test(CpuInfo::HAS_LSE2)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { lse2: Some(lse2), .. }) = proc_cpuinfo { assert!(lse2); } } else { assert!(!detect().test(CpuInfo::HAS_LSE2)); if let Ok(test_helper::cpuinfo::ProcCpuinfo { lse2: Some(lse2), .. }) = proc_cpuinfo { assert!(!lse2); } } if detect().has_lse128() { assert!(detect().test(CpuInfo::HAS_LSE)); assert!(detect().test(CpuInfo::HAS_LSE2)); assert!(detect().test(CpuInfo::HAS_LSE128)); } else { assert!(!detect().test(CpuInfo::HAS_LSE128)); } if detect().has_rcpc3() { assert!(detect().test(CpuInfo::HAS_RCPC3)); } else { assert!(!detect().test(CpuInfo::HAS_RCPC3)); } } #[cfg(target_arch = "powerpc64")] #[test] #[cfg_attr(portable_atomic_test_outline_atomics_detect_false, ignore)] fn test_detect() { let proc_cpuinfo = test_helper::cpuinfo::ProcCpuinfo::new(); if detect().has_quadword_atomics() { assert!(detect().test(CpuInfo::HAS_QUADWORD_ATOMICS)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(proc_cpuinfo.power8); } } else { assert!(!detect().test(CpuInfo::HAS_QUADWORD_ATOMICS)); if let Ok(proc_cpuinfo) = proc_cpuinfo { assert!(!proc_cpuinfo.power8); } } } } portable-atomic/src/imp/atomic128/detect/aarch64_aa64reg.rs0000644000175000017500000006057414661133735024301 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Run-time feature detection on aarch64 Linux/FreeBSD/NetBSD/OpenBSD by parsing system registers. // // As of nightly-2023-01-23, is_aarch64_feature_detected doesn't support run-time detection on NetBSD/OpenBSD. // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/mod.rs // https://github.com/rust-lang/stdarch/pull/1374 // // Refs: // - https://developer.arm.com/documentation/ddi0601/latest/AArch64-Registers // - https://www.kernel.org/doc/Documentation/arm64/cpu-feature-registers.txt // - https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/aarch64.rs // // Supported platforms: // - Linux 4.11+ (emulate mrs instruction) // https://github.com/torvalds/linux/commit/77c97b4ee21290f5f083173d957843b615abbff2 // - FreeBSD 12.0+ (emulate mrs instruction) // https://github.com/freebsd/freebsd-src/commit/398810619cb32abf349f8de23f29510b2ee0839b // - NetBSD 9.0+ (through sysctl) // https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb // - OpenBSD 7.1+ (through sysctl) // https://github.com/openbsd/src/commit/d335af936b9d7dd9cf655cae1ce19560c45de6c8 // // For now, this module is only used on NetBSD/OpenBSD. // On Linux/FreeBSD, this module is test-only: // - On Linux, this approach requires a higher kernel version than Rust supports, // and also does not work with qemu-user (as of QEMU 7.2) and Valgrind. // (Looking into HWCAP_CPUID in auxvec, it appears that Valgrind is setting it // to false correctly, but qemu-user is setting it to true.) // - On FreeBSD, this approach does not work on FreeBSD 12 on QEMU (confirmed on // FreeBSD 12.{2,3,4}), and we got SIGILL (worked on FreeBSD 13 and 14). include!("common.rs"); #[cfg_attr(test, derive(Debug, PartialEq))] struct AA64Reg { aa64isar0: u64, #[cfg(test)] aa64isar1: u64, // OpenBSD has an API to get this, but currently always returns 0. // https://github.com/openbsd/src/blob/6a233889798dc3ecb18acc52dce1e57862af2957/sys/arch/arm64/arm64/machdep.c#L371-L377 #[cfg_attr(target_os = "openbsd", cfg(test))] aa64mmfr2: u64, } #[cold] fn _detect(info: &mut CpuInfo) { let AA64Reg { aa64isar0, #[cfg(test)] aa64isar1, #[cfg_attr(target_os = "openbsd", cfg(test))] aa64mmfr2, } = imp::aa64reg(); // ID_AA64ISAR0_EL1, Instruction Set Attribute Register 0 // https://developer.arm.com/documentation/ddi0601/2023-06/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0?lang=en let atomic = extract(aa64isar0, 23, 20); if atomic >= 2 { info.set(CpuInfo::HAS_LSE); // we currently only use FEAT_LSE and FEAT_LSE2 in outline-atomics. #[cfg(test)] { if atomic >= 3 { info.set(CpuInfo::HAS_LSE128); } } } // we currently only use FEAT_LSE and FEAT_LSE2 in outline-atomics. #[cfg(test)] { // ID_AA64ISAR1_EL1, Instruction Set Attribute Register 1 // https://developer.arm.com/documentation/ddi0601/2023-06/AArch64-Registers/ID-AA64ISAR1-EL1--AArch64-Instruction-Set-Attribute-Register-1?lang=en if extract(aa64isar1, 23, 20) >= 3 { info.set(CpuInfo::HAS_RCPC3); } } // OpenBSD has an API to get this, but currently always returns 0. // https://github.com/openbsd/src/blob/6a233889798dc3ecb18acc52dce1e57862af2957/sys/arch/arm64/arm64/machdep.c#L371-L377 #[cfg_attr(target_os = "openbsd", cfg(test))] { // ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2 // https://developer.arm.com/documentation/ddi0601/2023-06/AArch64-Registers/ID-AA64MMFR2-EL1--AArch64-Memory-Model-Feature-Register-2?lang=en if extract(aa64mmfr2, 35, 32) >= 1 { info.set(CpuInfo::HAS_LSE2); } } } fn extract(x: u64, high: usize, low: usize) -> u64 { (x >> low) & ((1 << (high - low + 1)) - 1) } #[cfg(not(any(target_os = "netbsd", target_os = "openbsd")))] mod imp { // This module is test-only. See parent module docs for details. #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use super::AA64Reg; pub(super) fn aa64reg() -> AA64Reg { // SAFETY: This is safe on FreeBSD 12.0+. FreeBSD 11 was EoL on 2021-09-30. // Note that stdarch has been doing the same thing since before FreeBSD 11 was EoL. // https://github.com/rust-lang/stdarch/pull/611 unsafe { let aa64isar0: u64; asm!( "mrs {0}, ID_AA64ISAR0_EL1", out(reg) aa64isar0, options(pure, nomem, nostack, preserves_flags) ); #[cfg(test)] let aa64isar1: u64; #[cfg(test)] { asm!( "mrs {0}, ID_AA64ISAR1_EL1", out(reg) aa64isar1, options(pure, nomem, nostack, preserves_flags) ); } let aa64mmfr2: u64; asm!( "mrs {0}, ID_AA64MMFR2_EL1", out(reg) aa64mmfr2, options(pure, nomem, nostack, preserves_flags) ); AA64Reg { aa64isar0, #[cfg(test)] aa64isar1, aa64mmfr2, } } } } #[cfg(target_os = "netbsd")] mod imp { // NetBSD doesn't trap the mrs instruction, but exposes the system registers through sysctl. // https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb // https://github.com/golang/sys/commit/ef9fd89ba245e184bdd308f7f2b4f3c551fa5b0f use core::ptr; use super::AA64Reg; // core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 #[allow(non_camel_case_types)] pub(super) mod ffi { pub(crate) use super::super::c_types::{c_char, c_int, c_size_t, c_void}; extern "C" { // Defined in sys/sysctl.h. // https://man.netbsd.org/sysctl.3 // https://github.com/NetBSD/src/blob/167403557cf60bed09a63fc84d941a1a4bd7d52e/sys/sys/sysctl.h // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/bsd/netbsdlike/netbsd/mod.rs#L2582 pub(crate) fn sysctlbyname( name: *const c_char, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> c_int; } // Defined in aarch64/armreg.h. // https://github.com/NetBSD/src/blob/167403557cf60bed09a63fc84d941a1a4bd7d52e/sys/arch/aarch64/include/armreg.h#L1626 #[derive(Clone, Copy)] #[repr(C)] pub(crate) struct aarch64_sysctl_cpu_id { // NetBSD 9.0+ // https://github.com/NetBSD/src/commit/0e9d25528729f7fea53e78275d1bc5039dfe8ffb pub(crate) midr: u64, pub(crate) revidr: u64, pub(crate) mpidr: u64, pub(crate) aa64dfr0: u64, pub(crate) aa64dfr1: u64, pub(crate) aa64isar0: u64, pub(crate) aa64isar1: u64, pub(crate) aa64mmfr0: u64, pub(crate) aa64mmfr1: u64, pub(crate) aa64mmfr2: u64, pub(crate) aa64pfr0: u64, pub(crate) aa64pfr1: u64, pub(crate) aa64zfr0: u64, pub(crate) mvfr0: u32, pub(crate) mvfr1: u32, pub(crate) mvfr2: u32, // NetBSD 10.0+ // https://github.com/NetBSD/src/commit/0c7bdc13f0e332cccec56e307f023b4888638973 pub(crate) pad: u32, pub(crate) clidr: u64, pub(crate) ctr: u64, } } pub(super) unsafe fn sysctl_cpu_id(name: &[u8]) -> Option { const OUT_LEN: ffi::c_size_t = core::mem::size_of::() as ffi::c_size_t; debug_assert_eq!(name.last(), Some(&0), "{:?}", name); debug_assert_eq!(name.iter().filter(|&&v| v == 0).count(), 1, "{:?}", name); // SAFETY: all fields of aarch64_sysctl_cpu_id are zero-able and we use // the result when machdep.cpuN.cpu_id sysctl was successful. let mut buf: ffi::aarch64_sysctl_cpu_id = unsafe { core::mem::zeroed() }; let mut out_len = OUT_LEN; // SAFETY: // - the caller must guarantee that `name` is ` machdep.cpuN.cpu_id` in a C string. // - `out_len` does not exceed the size of the value at `buf`. // - `sysctlbyname` is thread-safe. let res = unsafe { ffi::sysctlbyname( name.as_ptr().cast::(), (&mut buf as *mut ffi::aarch64_sysctl_cpu_id).cast::(), &mut out_len, ptr::null_mut(), 0, ) }; if res != 0 { return None; } Some(AA64Reg { aa64isar0: buf.aa64isar0, #[cfg(test)] aa64isar1: buf.aa64isar1, aa64mmfr2: buf.aa64mmfr2, }) } pub(super) fn aa64reg() -> AA64Reg { // Get system registers for cpu0. // If failed, returns default because machdep.cpuN.cpu_id sysctl is not available. // machdep.cpuN.cpu_id sysctl was added on NetBSD 9.0 so it is not available on older versions. // SAFETY: we passed a valid name in a C string. // It is ok to check only cpu0, even if there are more CPUs. // https://github.com/NetBSD/src/commit/bd9707e06ea7d21b5c24df6dfc14cb37c2819416 // https://github.com/golang/sys/commit/ef9fd89ba245e184bdd308f7f2b4f3c551fa5b0f match unsafe { sysctl_cpu_id(b"machdep.cpu0.cpu_id\0") } { Some(cpu_id) => cpu_id, None => AA64Reg { aa64isar0: 0, #[cfg(test)] aa64isar1: 0, aa64mmfr2: 0, }, } } } #[cfg(target_os = "openbsd")] mod imp { // OpenBSD doesn't trap the mrs instruction, but exposes the system registers through sysctl. // https://github.com/openbsd/src/commit/d335af936b9d7dd9cf655cae1ce19560c45de6c8 // https://github.com/golang/go/commit/cd54ef1f61945459486e9eea2f016d99ef1da925 use core::ptr; use super::AA64Reg; // core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 #[allow(non_camel_case_types)] pub(super) mod ffi { pub(crate) use super::super::c_types::{c_int, c_size_t, c_uint, c_void}; // Defined in sys/sysctl.h. // https://github.com/openbsd/src/blob/72ccc03bd11da614f31f7ff76e3f6fce99bc1c79/sys/sys/sysctl.h#L82 pub(crate) const CTL_MACHDEP: c_int = 7; // Defined in machine/cpu.h. // https://github.com/openbsd/src/blob/72ccc03bd11da614f31f7ff76e3f6fce99bc1c79/sys/arch/arm64/include/cpu.h#L25-L40 pub(crate) const CPU_ID_AA64ISAR0: c_int = 2; #[cfg(test)] pub(crate) const CPU_ID_AA64ISAR1: c_int = 3; // OpenBSD has an API to get this, but currently always returns 0. // https://github.com/openbsd/src/blob/6a233889798dc3ecb18acc52dce1e57862af2957/sys/arch/arm64/arm64/machdep.c#L371-L377 #[cfg(test)] pub(crate) const CPU_ID_AA64MMFR2: c_int = 7; extern "C" { // Defined in sys/sysctl.h. // https://man.openbsd.org/sysctl.2 // https://github.com/openbsd/src/blob/72ccc03bd11da614f31f7ff76e3f6fce99bc1c79/sys/sys/sysctl.h // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/bsd/netbsdlike/openbsd/mod.rs#L1817-L1824 pub(crate) fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *mut c_void, new_len: c_size_t, ) -> c_int; } } // ID_AA64ISAR0_EL1 and ID_AA64ISAR1_EL1 are supported on OpenBSD 7.1+. // https://github.com/openbsd/src/commit/d335af936b9d7dd9cf655cae1ce19560c45de6c8 // Others are supported on OpenBSD 7.3+. // https://github.com/openbsd/src/commit/c7654cd65262d532212f65123ee3905ba200365c // sysctl returns an unsupported error if operation is not supported, // so we can safely use this function on older versions of OpenBSD. pub(super) fn aa64reg() -> AA64Reg { let aa64isar0 = sysctl64(&[ffi::CTL_MACHDEP, ffi::CPU_ID_AA64ISAR0]).unwrap_or(0); #[cfg(test)] let aa64isar1 = sysctl64(&[ffi::CTL_MACHDEP, ffi::CPU_ID_AA64ISAR1]).unwrap_or(0); #[cfg(test)] let aa64mmfr2 = sysctl64(&[ffi::CTL_MACHDEP, ffi::CPU_ID_AA64MMFR2]).unwrap_or(0); AA64Reg { aa64isar0, #[cfg(test)] aa64isar1, #[cfg(test)] aa64mmfr2, } } fn sysctl64(mib: &[ffi::c_int]) -> Option { const OUT_LEN: ffi::c_size_t = core::mem::size_of::() as ffi::c_size_t; let mut out = 0_u64; let mut out_len = OUT_LEN; #[allow(clippy::cast_possible_truncation)] // SAFETY: // - `mib.len()` does not exceed the size of `mib`. // - `out_len` does not exceed the size of `out`. // - `sysctl` is thread-safe. let res = unsafe { ffi::sysctl( mib.as_ptr(), mib.len() as ffi::c_uint, (&mut out as *mut u64).cast::(), &mut out_len, ptr::null_mut(), 0, ) }; if res == -1 { return None; } debug_assert_eq!(out_len, OUT_LEN); Some(out) } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use std::{ process::Command, string::{String, ToString}, }; use super::*; #[test] fn test_aa64reg() { let AA64Reg { aa64isar0, aa64isar1, aa64mmfr2 } = imp::aa64reg(); std::eprintln!("aa64isar0={}", aa64isar0); std::eprintln!("aa64isar1={}", aa64isar1); std::eprintln!("aa64mmfr2={}", aa64mmfr2); if cfg!(target_os = "openbsd") { let output = Command::new("sysctl").arg("machdep").output().unwrap(); assert!(output.status.success()); let stdout = String::from_utf8(output.stdout).unwrap(); // OpenBSD 7.1+ assert_eq!( stdout.lines().find_map(|s| s.strip_prefix("machdep.id_aa64isar0=")).unwrap_or("0"), aa64isar0.to_string(), ); assert_eq!( stdout.lines().find_map(|s| s.strip_prefix("machdep.id_aa64isar1=")).unwrap_or("0"), aa64isar1.to_string(), ); // OpenBSD 7.3+ assert_eq!( stdout.lines().find_map(|s| s.strip_prefix("machdep.id_aa64mmfr2=")).unwrap_or("0"), aa64mmfr2.to_string(), ); } if detect().test(CpuInfo::HAS_LSE) { let atomic = extract(aa64isar0, 23, 20); if detect().test(CpuInfo::HAS_LSE128) { assert_eq!(atomic, 3); } else { assert_eq!(atomic, 2); } } if detect().test(CpuInfo::HAS_LSE2) { assert_eq!(extract(aa64mmfr2, 35, 32), 1); } if detect().test(CpuInfo::HAS_RCPC3) { assert_eq!(extract(aa64isar1, 23, 20), 3); } } #[allow(clippy::cast_possible_wrap)] #[cfg(target_os = "netbsd")] #[test] fn test_netbsd() { use c_types::*; use core::{arch::asm, mem, ptr}; use imp::ffi; use test_helper::sys; // Call syscall using asm instead of libc. // Note that NetBSD does not guarantee the stability of raw syscall as // much as Linux does (It may actually be stable enough, though: https://lists.llvm.org/pipermail/llvm-dev/2019-June/133393.html). // // This is currently used only for testing. unsafe fn sysctl_cpu_id_asm_syscall(name: &[&[u8]]) -> Result { // https://github.com/golang/go/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/src/syscall/asm_netbsd_arm64.s #[inline] unsafe fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> Result { #[allow(clippy::cast_possible_truncation)] // SAFETY: the caller must uphold the safety contract. unsafe { let mut n = sys::SYS___sysctl as u64; let r: i64; asm!( "svc 0", "b.cc 2f", "mov x17, x0", "mov x0, #-1", "2:", inout("x17") n, inout("x0") ptr_reg!(name) => r, inout("x1") name_len as u64 => _, in("x2") ptr_reg!(old_p), in("x3") ptr_reg!(old_len_p), in("x4") ptr_reg!(new_p), in("x5") new_len as u64, options(nostack), ); if r as c_int == -1 { Err(n as c_int) } else { Ok(r as c_int) } } } // https://github.com/golang/sys/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/cpu/cpu_netbsd_arm64.go. use std::{vec, vec::Vec}; fn sysctl_nodes(mib: &mut Vec) -> Result, i32> { mib.push(sys::CTL_QUERY); let mut q_node = sys::sysctlnode { sysctl_flags: sys::SYSCTL_VERS_1, ..unsafe { mem::zeroed() } }; let qp = (&mut q_node as *mut sys::sysctlnode).cast::(); let sz = mem::size_of::(); let mut olen = 0; #[allow(clippy::cast_possible_truncation)] unsafe { sysctl(mib.as_ptr(), mib.len() as c_uint, ptr::null_mut(), &mut olen, qp, sz)?; } let mut nodes = Vec::::with_capacity(olen / sz); let np = nodes.as_mut_ptr().cast::(); #[allow(clippy::cast_possible_truncation)] unsafe { sysctl(mib.as_ptr(), mib.len() as c_uint, np, &mut olen, qp, sz)?; nodes.set_len(olen / sz); } mib.pop(); // pop CTL_QUERY Ok(nodes) } fn name_to_mib(parts: &[&[u8]]) -> Result, i32> { let mut mib = vec![]; for (part_no, &part) in parts.iter().enumerate() { let nodes = sysctl_nodes(&mut mib)?; for node in nodes { let mut n = vec![]; for b in node.sysctl_name { if b != 0 { n.push(b); } } if n == part { mib.push(node.sysctl_num); break; } } if mib.len() != part_no + 1 { return Err(0); } } Ok(mib) } const OUT_LEN: ffi::c_size_t = core::mem::size_of::() as ffi::c_size_t; let mib = name_to_mib(name)?; let mut buf: ffi::aarch64_sysctl_cpu_id = unsafe { core::mem::zeroed() }; let mut out_len = OUT_LEN; #[allow(clippy::cast_possible_truncation)] unsafe { sysctl( mib.as_ptr(), mib.len() as c_uint, (&mut buf as *mut ffi::aarch64_sysctl_cpu_id).cast::(), &mut out_len, ptr::null_mut(), 0, )?; } Ok(AA64Reg { aa64isar0: buf.aa64isar0, #[cfg(test)] aa64isar1: buf.aa64isar1, #[cfg(test)] aa64mmfr2: buf.aa64mmfr2, }) } unsafe { assert_eq!( imp::sysctl_cpu_id(b"machdep.cpu0.cpu_id\0").unwrap(), sysctl_cpu_id_asm_syscall(&[b"machdep", b"cpu0", b"cpu_id"]).unwrap() ); } } // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate, FFI bindings defined // in libc, and FFI bindings generated for the platform's latest header file // using bindgen have compatible signatures (or the same values if constants). // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[cfg(target_os = "netbsd")] #[allow( clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::no_effect_underscore_binding, clippy::used_underscore_binding )] const _: fn() = || { use core::mem::size_of; use imp::ffi; use test_helper::{libc, sys}; let mut _sysctlbyname: unsafe extern "C" fn( *const ffi::c_char, *mut ffi::c_void, *mut ffi::c_size_t, *const ffi::c_void, ffi::c_size_t, ) -> ffi::c_int = ffi::sysctlbyname; _sysctlbyname = libc::sysctlbyname; _sysctlbyname = sys::sysctlbyname; // libc doesn't have this // static_assert!( // size_of::() == size_of::() // ); static_assert!( size_of::() == size_of::() ); let ffi: ffi::aarch64_sysctl_cpu_id = unsafe { core::mem::zeroed() }; let _ = sys::aarch64_sysctl_cpu_id { ac_midr: ffi.midr, ac_revidr: ffi.revidr, ac_mpidr: ffi.mpidr, ac_aa64dfr0: ffi.aa64dfr0, ac_aa64dfr1: ffi.aa64dfr1, ac_aa64isar0: ffi.aa64isar0, ac_aa64isar1: ffi.aa64isar1, ac_aa64mmfr0: ffi.aa64mmfr0, ac_aa64mmfr1: ffi.aa64mmfr1, ac_aa64mmfr2: ffi.aa64mmfr2, ac_aa64pfr0: ffi.aa64pfr0, ac_aa64pfr1: ffi.aa64pfr1, ac_aa64zfr0: ffi.aa64zfr0, ac_mvfr0: ffi.mvfr0, ac_mvfr1: ffi.mvfr1, ac_mvfr2: ffi.mvfr2, ac_pad: ffi.pad, ac_clidr: ffi.clidr, ac_ctr: ffi.ctr, }; }; #[cfg(target_os = "openbsd")] #[allow( clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::no_effect_underscore_binding )] const _: fn() = || { use imp::ffi; use test_helper::{libc, sys}; let mut _sysctl: unsafe extern "C" fn( *const ffi::c_int, ffi::c_uint, *mut ffi::c_void, *mut ffi::c_size_t, *mut ffi::c_void, ffi::c_size_t, ) -> ffi::c_int = ffi::sysctl; _sysctl = libc::sysctl; _sysctl = sys::sysctl; static_assert!(ffi::CTL_MACHDEP == libc::CTL_MACHDEP); static_assert!(ffi::CTL_MACHDEP == sys::CTL_MACHDEP as ffi::c_int); // static_assert!(ffi::CPU_ID_AA64ISAR0 == libc::CPU_ID_AA64ISAR0); // libc doesn't have this static_assert!(ffi::CPU_ID_AA64ISAR0 == sys::CPU_ID_AA64ISAR0 as ffi::c_int); // static_assert!(ffi::CPU_ID_AA64ISAR1 == libc::CPU_ID_AA64ISAR1); // libc doesn't have this static_assert!(ffi::CPU_ID_AA64ISAR1 == sys::CPU_ID_AA64ISAR1 as ffi::c_int); // static_assert!(ffi::CPU_ID_AA64MMFR2 == libc::CPU_ID_AA64MMFR2); // libc doesn't have this static_assert!(ffi::CPU_ID_AA64MMFR2 == sys::CPU_ID_AA64MMFR2 as ffi::c_int); }; } portable-atomic/src/imp/atomic128/detect/auxv.rs0000644000175000017500000007713314661133735022522 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Run-time feature detection on aarch64/powerpc64 Linux/Android/FreeBSD by parsing ELF auxiliary vectors. // // # Linux/Android // // As of nightly-2023-01-23, is_aarch64_feature_detected always uses dlsym by default // on aarch64 Linux/Android, but on the following platforms, so we can safely assume // getauxval is linked to the binary. // // - On glibc (*-linux-gnu*), [aarch64 support is available on glibc 2.17+](https://sourceware.org/legacy-ml/libc-announce/2012/msg00001.html) // and is newer than [glibc 2.16 that added getauxval](https://sourceware.org/legacy-ml/libc-announce/2012/msg00000.html). // - On musl (*-linux-musl*, *-linux-ohos*), [aarch64 support is available on musl 1.1.7+](https://git.musl-libc.org/cgit/musl/tree/WHATSNEW?h=v1.1.7#n1422) // and is newer than [musl 1.1.0 that added getauxval](https://git.musl-libc.org/cgit/musl/tree/WHATSNEW?h=v1.1.0#n1197). // https://github.com/rust-lang/rust/commit/9a04ae4997493e9260352064163285cddc43de3c // - On bionic (*-android*), [64-bit architecture support is available on Android 5.0+ (API level 21+)](https://android-developers.googleblog.com/2014/10/whats-new-in-android-50-lollipop.html) // and is newer than [Android 4.3 (API level 18) that added getauxval](https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h#L49). // // However, on musl with static linking, it seems that getauxval is not always available, independent of version requirements: https://github.com/rust-lang/rust/issues/89626 // (That problem may have been fixed in https://github.com/rust-lang/rust/commit/9a04ae4997493e9260352064163285cddc43de3c, // but even in the version containing that patch, [there is report](https://github.com/rust-lang/rust/issues/89626#issuecomment-1242636038) // of the same error.) // // On other Linux targets, we cannot assume that getauxval is always available, so we don't enable // outline-atomics by default (can be enabled by `--cfg portable_atomic_outline_atomics`). // // - On musl with static linking. See the above for more. // Also, in this case, dlsym(getauxval) always returns null. // - On uClibc-ng (*-linux-uclibc*, *-l4re-uclibc*), [uClibc-ng 1.0.43 (released in 2023-04-05) added getauxval](https://github.com/wbx-github/uclibc-ng/commit/d869bb1600942c01a77539128f9ba5b5b55ad647). // - On Picolibc, [Picolibc 1.4.6 added getauxval stub](https://github.com/picolibc/picolibc#picolibc-version-146). // // See also https://github.com/rust-lang/stdarch/pull/1375 // // See tests::test_linux_like and aarch64_aa64reg.rs for (test-only) alternative implementations. // // # FreeBSD // // As of nightly-2023-01-23, is_aarch64_feature_detected always uses mrs on // aarch64 FreeBSD. However, they do not work on FreeBSD 12 on QEMU (confirmed // on FreeBSD 12.{2,3,4}), and we got SIGILL (worked on FreeBSD 13 and 14). // // So use elf_aux_info instead of mrs like compiler-rt does. // https://man.freebsd.org/elf_aux_info(3) // https://reviews.llvm.org/D109330 // // elf_aux_info is available on FreeBSD 12.0+ and 11.4+: // https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470 // https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h // On FreeBSD, [aarch64 support is available on FreeBSD 11.0+](https://www.freebsd.org/releases/11.0R/relnotes/#hardware-arm), // but FreeBSD 11 (11.4) was EoL on 2021-09-30, and FreeBSD 11.3 was EoL on 2020-09-30: // https://www.freebsd.org/security/unsupported // See also https://github.com/rust-lang/stdarch/pull/611#issuecomment-445464613 // // See tests::test_freebsd and aarch64_aa64reg.rs for (test-only) alternative implementations. // // # PowerPC64 // // On PowerPC64, outline-atomics is currently disabled by default mainly for // compatibility with older versions of operating systems // (can be enabled by `--cfg portable_atomic_outline_atomics`). include!("common.rs"); use os::ffi; #[cfg(any(target_os = "linux", target_os = "android"))] mod os { // core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 #[cfg_attr(test, allow(dead_code))] pub(super) mod ffi { pub(crate) use super::super::c_types::c_ulong; #[cfg(all(target_arch = "aarch64", target_os = "android"))] pub(crate) use super::super::c_types::{c_char, c_int}; extern "C" { // https://man7.org/linux/man-pages/man3/getauxval.3.html // https://github.com/bminor/glibc/blob/801af9fafd4689337ebf27260aa115335a0cb2bc/misc/sys/auxv.h // https://github.com/bminor/musl/blob/7d756e1c04de6eb3f2b3d3e1141a218bb329fcfb/include/sys/auxv.h // https://github.com/wbx-github/uclibc-ng/blob/cdb07d2cd52af39feb425e6d36c02b30916b9f0a/include/sys/auxv.h // https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/auxv.h // https://github.com/picolibc/picolibc/blob/7a8a58aeaa5946cb662577a518051091b691af3a/newlib/libc/picolib/getauxval.c // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/linux/gnu/mod.rs#L1201 // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/linux/musl/mod.rs#L744 // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/android/b64/mod.rs#L333 pub(crate) fn getauxval(type_: c_ulong) -> c_ulong; // Defined in sys/system_properties.h. // https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/system_properties.h // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/linux_like/android/mod.rs#L3471 #[cfg(all(target_arch = "aarch64", target_os = "android"))] pub(crate) fn __system_property_get(name: *const c_char, value: *mut c_char) -> c_int; } // https://github.com/torvalds/linux/blob/v6.1/include/uapi/linux/auxvec.h #[cfg(any(test, target_arch = "aarch64"))] pub(crate) const AT_HWCAP: c_ulong = 16; #[cfg(any(test, target_arch = "powerpc64"))] pub(crate) const AT_HWCAP2: c_ulong = 26; // Defined in sys/system_properties.h. // https://github.com/aosp-mirror/platform_bionic/blob/d3ebc2f7c49a9893b114124d4a6b315f3a328764/libc/include/sys/system_properties.h #[cfg(all(target_arch = "aarch64", target_os = "android"))] pub(crate) const PROP_VALUE_MAX: c_int = 92; } pub(super) fn getauxval(type_: ffi::c_ulong) -> ffi::c_ulong { #[cfg(all(target_arch = "aarch64", target_os = "android"))] { // Samsung Exynos 9810 has a bug that big and little cores have different // ISAs. And on older Android (pre-9), the kernel incorrectly reports // that features available only on some cores are available on all cores. // https://reviews.llvm.org/D114523 let mut arch = [0_u8; ffi::PROP_VALUE_MAX as usize]; // SAFETY: we've passed a valid C string and a buffer with max length. let len = unsafe { ffi::__system_property_get( b"ro.arch\0".as_ptr().cast::(), arch.as_mut_ptr().cast::(), ) }; // On Exynos, ro.arch is not available on Android 12+, but it is fine // because Android 9+ includes the fix. if len > 0 && arch.starts_with(b"exynos9810") { return 0; } } // SAFETY: `getauxval` is thread-safe. See also the module level docs. unsafe { ffi::getauxval(type_) } } } #[cfg(target_os = "freebsd")] mod os { // core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 #[cfg_attr(test, allow(dead_code))] pub(super) mod ffi { pub(crate) use super::super::c_types::{c_int, c_ulong, c_void}; extern "C" { // Defined in sys/auxv.h. // https://man.freebsd.org/elf_aux_info(3) // https://github.com/freebsd/freebsd-src/blob/deb63adf945d446ed91a9d84124c71f15ae571d1/sys/sys/auxv.h pub(crate) fn elf_aux_info(aux: c_int, buf: *mut c_void, buf_len: c_int) -> c_int; } // Defined in sys/elf_common.h. // https://github.com/freebsd/freebsd-src/blob/deb63adf945d446ed91a9d84124c71f15ae571d1/sys/sys/elf_common.h #[cfg(any(test, target_arch = "aarch64"))] pub(crate) const AT_HWCAP: c_int = 25; #[cfg(any(test, target_arch = "powerpc64"))] pub(crate) const AT_HWCAP2: c_int = 26; } pub(super) fn getauxval(aux: ffi::c_int) -> ffi::c_ulong { #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] const OUT_LEN: ffi::c_int = core::mem::size_of::() as ffi::c_int; let mut out: ffi::c_ulong = 0; // SAFETY: // - the pointer is valid because we got it from a reference. // - `OUT_LEN` is the same as the size of `out`. // - `elf_aux_info` is thread-safe. unsafe { let res = ffi::elf_aux_info( aux, (&mut out as *mut ffi::c_ulong).cast::(), OUT_LEN, ); // If elf_aux_info fails, `out` will be left at zero (which is the proper default value). debug_assert!(res == 0 || out == 0); } out } } // Basically, Linux and FreeBSD use the same hwcap values. // FreeBSD supports a subset of the hwcap values supported by Linux. use arch::_detect; #[cfg(target_arch = "aarch64")] mod arch { use super::{ffi, os, CpuInfo}; // Linux // https://github.com/torvalds/linux/blob/1c41041124bd14dd6610da256a3da4e5b74ce6b1/arch/arm64/include/uapi/asm/hwcap.h // FreeBSD // Defined in machine/elf.h. // https://github.com/freebsd/freebsd-src/blob/deb63adf945d446ed91a9d84124c71f15ae571d1/sys/arm64/include/elf.h // available on FreeBSD 13.0+ and 12.2+ // https://github.com/freebsd/freebsd-src/blob/release/13.0.0/sys/arm64/include/elf.h // https://github.com/freebsd/freebsd-src/blob/release/12.2.0/sys/arm64/include/elf.h pub(super) const HWCAP_ATOMICS: ffi::c_ulong = 1 << 8; pub(super) const HWCAP_USCAT: ffi::c_ulong = 1 << 25; #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_pointer_width = "64")] #[cfg(test)] pub(super) const HWCAP2_LRCPC3: ffi::c_ulong = 1 << 46; #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_pointer_width = "64")] #[cfg(test)] pub(super) const HWCAP2_LSE128: ffi::c_ulong = 1 << 47; #[cold] pub(super) fn _detect(info: &mut CpuInfo) { let hwcap = os::getauxval(ffi::AT_HWCAP); if hwcap & HWCAP_ATOMICS != 0 { info.set(CpuInfo::HAS_LSE); } if hwcap & HWCAP_USCAT != 0 { info.set(CpuInfo::HAS_LSE2); } #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_pointer_width = "64")] #[cfg(test)] { let hwcap2 = os::getauxval(ffi::AT_HWCAP2); if hwcap2 & HWCAP2_LRCPC3 != 0 { info.set(CpuInfo::HAS_RCPC3); } if hwcap2 & HWCAP2_LSE128 != 0 { info.set(CpuInfo::HAS_LSE128); } } } } #[cfg(target_arch = "powerpc64")] mod arch { use super::{ffi, os, CpuInfo}; // Linux // https://github.com/torvalds/linux/blob/v6.1/arch/powerpc/include/uapi/asm/cputable.h // FreeBSD // Defined in machine/cpu.h. // https://github.com/freebsd/freebsd-src/blob/deb63adf945d446ed91a9d84124c71f15ae571d1/sys/powerpc/include/cpu.h // available on FreeBSD 11.0+ // https://github.com/freebsd/freebsd-src/commit/b0bf7fcd298133457991b27625bbed766e612730 pub(super) const PPC_FEATURE2_ARCH_2_07: ffi::c_ulong = 0x80000000; #[cold] pub(super) fn _detect(info: &mut CpuInfo) { let hwcap2 = os::getauxval(ffi::AT_HWCAP2); // power8 if hwcap2 & PPC_FEATURE2_ARCH_2_07 != 0 { info.set(CpuInfo::HAS_QUADWORD_ATOMICS); } } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_pointer_width = "64")] #[test] fn test_linux_like() { use c_types::*; use core::{arch::asm, mem}; use std::vec; use test_helper::{libc, sys}; // Linux kernel 6.4 has added a way to read auxv without depending on either libc or mrs trap. // https://github.com/torvalds/linux/commit/ddc65971bb677aa9f6a4c21f76d3133e106f88eb // // This is currently used only for testing. fn getauxval_pr_get_auxv(type_: ffi::c_ulong) -> Result { #[cfg(target_arch = "aarch64")] unsafe fn prctl_get_auxv(out: *mut c_void, len: usize) -> Result { let r: i64; unsafe { asm!( "svc 0", in("x8") sys::__NR_prctl as u64, inout("x0") sys::PR_GET_AUXV as u64 => r, in("x1") ptr_reg!(out), in("x2") len as u64, // arg4 and arg5 must be zero. in("x3") 0_u64, in("x4") 0_u64, options(nostack, preserves_flags) ); } #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] if (r as c_int) < 0 { Err(r as c_int) } else { Ok(r as usize) } } #[cfg(target_arch = "powerpc64")] unsafe fn prctl_get_auxv(out: *mut c_void, len: usize) -> Result { let r: i64; unsafe { asm!( "sc", "bns+ 2f", "neg %r3, %r3", "2:", inout("r0") sys::__NR_prctl as u64 => _, inout("r3") sys::PR_GET_AUXV as u64 => r, inout("r4") ptr_reg!(out) => _, inout("r5") len as u64 => _, // arg4 and arg5 must be zero. inout("r6") 0_u64 => _, inout("r7") 0_u64 => _, out("r8") _, out("r9") _, out("r10") _, out("r11") _, out("r12") _, out("cr0") _, options(nostack, preserves_flags) ); } #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)] if (r as c_int) < 0 { Err(r as c_int) } else { Ok(r as usize) } } let mut auxv = vec![unsafe { mem::zeroed::() }; 38]; let old_len = auxv.len() * mem::size_of::(); // SAFETY: // - `out_len` does not exceed the size of `auxv`. let _len = unsafe { prctl_get_auxv(auxv.as_mut_ptr().cast::(), old_len)? }; for aux in &auxv { if aux.a_type == type_ { // SAFETY: aux.a_un is #[repr(C)] union and all fields have // the same size and can be safely transmuted to integers. return Ok(unsafe { aux.a_un.a_val }); } } Err(0) } unsafe { let mut u = mem::zeroed(); assert_eq!(libc::uname(&mut u), 0); let release = std::ffi::CStr::from_ptr(u.release.as_ptr()); let release = core::str::from_utf8(release.to_bytes()).unwrap(); let mut digits = release.split('.'); let major = digits.next().unwrap().parse::().unwrap(); let minor = digits.next().unwrap().parse::().unwrap(); if (major, minor) < (6, 4) { std::eprintln!("kernel version: {major}.{minor} (no pr_get_auxv)"); assert_eq!(getauxval_pr_get_auxv(ffi::AT_HWCAP).unwrap_err(), -22); assert_eq!(getauxval_pr_get_auxv(ffi::AT_HWCAP2).unwrap_err(), -22); } else { std::eprintln!("kernel version: {major}.{minor} (has pr_get_auxv)"); assert_eq!( os::getauxval(ffi::AT_HWCAP), getauxval_pr_get_auxv(ffi::AT_HWCAP).unwrap() ); assert_eq!( os::getauxval(ffi::AT_HWCAP2), getauxval_pr_get_auxv(ffi::AT_HWCAP2).unwrap() ); } } } #[allow(clippy::cast_sign_loss)] #[cfg(all(target_arch = "aarch64", target_os = "android"))] #[test] fn test_android() { unsafe { let mut arch = [1; ffi::PROP_VALUE_MAX as usize]; let len = ffi::__system_property_get( b"ro.arch\0".as_ptr().cast::(), arch.as_mut_ptr().cast::(), ); assert!(len >= 0); std::eprintln!("len={}", len); std::eprintln!("arch={:?}", arch); std::eprintln!( "arch={:?}", core::str::from_utf8(core::slice::from_raw_parts(arch.as_ptr(), len as usize)) .unwrap() ); } } #[allow(clippy::cast_possible_wrap)] #[cfg(target_os = "freebsd")] #[test] fn test_freebsd() { use c_types::*; use core::{arch::asm, mem, ptr}; use test_helper::sys; // This is almost equivalent to what elf_aux_info does. // https://man.freebsd.org/elf_aux_info(3) // On FreeBSD, [aarch64 support is available on FreeBSD 11.0+](https://www.freebsd.org/releases/11.0R/relnotes/#hardware-arm), // but elf_aux_info is available on FreeBSD 12.0+ and 11.4+: // https://github.com/freebsd/freebsd-src/commit/0b08ae2120cdd08c20a2b806e2fcef4d0a36c470 // https://github.com/freebsd/freebsd-src/blob/release/11.4.0/sys/sys/auxv.h // so use sysctl instead of elf_aux_info. // Note that FreeBSD 11 (11.4) was EoL on 2021-09-30, and FreeBSD 11.3 was EoL on 2020-09-30: // https://www.freebsd.org/security/unsupported // // std_detect uses this way, but it appears to be somewhat incorrect // (the type of arg4 of sysctl, auxv is smaller than AT_COUNT, etc.). // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/freebsd/auxvec.rs#L52 // // This is currently used only for testing. // If you want us to use this implementation for compatibility with the older FreeBSD // version that came to EoL a few years ago, please open an issue. fn getauxval_sysctl_libc(type_: ffi::c_int) -> ffi::c_ulong { let mut auxv: [sys::Elf64_Auxinfo; sys::AT_COUNT as usize] = unsafe { mem::zeroed() }; let mut len = core::mem::size_of_val(&auxv) as c_size_t; // SAFETY: calling getpid is safe. let pid = unsafe { sys::getpid() }; let mib = [ sys::CTL_KERN as c_int, sys::KERN_PROC as c_int, sys::KERN_PROC_AUXV as c_int, pid, ]; #[allow(clippy::cast_possible_truncation)] // SAFETY: // - `mib.len()` does not exceed the size of `mib`. // - `len` does not exceed the size of `auxv`. // - `sysctl` is thread-safe. let res = unsafe { sys::sysctl( mib.as_ptr(), mib.len() as c_uint, auxv.as_mut_ptr().cast::(), &mut len, ptr::null_mut(), 0, ) }; if res != -1 { for aux in &auxv { if aux.a_type == type_ as c_long { // SAFETY: aux.a_un is #[repr(C)] union and all fields have // the same size and can be safely transmuted to integers. return unsafe { aux.a_un.a_val as c_ulong }; } } } 0 } // Similar to the above, but call syscall using asm instead of libc. // Note that FreeBSD does not guarantee the stability of raw syscall as // much as Linux does (It may actually be stable enough, though: // https://lists.llvm.org/pipermail/llvm-dev/2019-June/133393.html, // https://github.com/ziglang/zig/issues/16590). // // This is currently used only for testing. fn getauxval_sysctl_asm_syscall(type_: ffi::c_int) -> Result { #[allow(non_camel_case_types)] type pid_t = c_int; // https://github.com/freebsd/freebsd-src/blob/9888a79adad22ba06b5aff17d05abac0029c537a/lib/libc/aarch64/SYS.h // https://github.com/golang/go/blob/4badad8d477ffd7a6b762c35bc69aed82faface7/src/syscall/asm_freebsd_arm64.s #[cfg(target_arch = "aarch64")] #[inline] fn getpid() -> pid_t { #[allow(clippy::cast_possible_truncation)] // SAFETY: calling getpid is safe. unsafe { let n = sys::SYS_getpid; let r: i64; asm!( "svc 0", in("x8") n as u64, out("x0") r, options(nostack, readonly), ); r as pid_t } } #[cfg(target_arch = "aarch64")] #[inline] unsafe fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> Result { #[allow(clippy::cast_possible_truncation)] // SAFETY: the caller must uphold the safety contract. unsafe { let mut n = sys::SYS___sysctl as u64; let r: i64; asm!( "svc 0", "b.cc 2f", "mov x8, x0", "mov x0, #-1", "2:", inout("x8") n, inout("x0") ptr_reg!(name) => r, inout("x1") name_len as u64 => _, in("x2") ptr_reg!(old_p), in("x3") ptr_reg!(old_len_p), in("x4") ptr_reg!(new_p), in("x5") new_len as u64, options(nostack), ); if r as c_int == -1 { Err(n as c_int) } else { Ok(r as c_int) } } } // https://github.com/freebsd/freebsd-src/blob/9888a79adad22ba06b5aff17d05abac0029c537a/lib/libc/powerpc64/SYS.h #[cfg(target_arch = "powerpc64")] #[inline] fn getpid() -> pid_t { #[allow(clippy::cast_possible_truncation)] // SAFETY: calling getpid is safe. unsafe { let n = sys::SYS_getpid; let r: i64; asm!( "sc", inout("r0") n as u64 => _, out("r3") r, out("r4") _, out("r5") _, out("r6") _, out("r7") _, out("r8") _, out("r9") _, out("r10") _, out("r11") _, out("r12") _, out("cr0") _, options(nostack, preserves_flags, readonly), ); r as pid_t } } #[cfg(target_arch = "powerpc64")] #[inline] unsafe fn sysctl( name: *const c_int, name_len: c_uint, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *const c_void, new_len: c_size_t, ) -> Result { #[allow(clippy::cast_possible_truncation)] // SAFETY: the caller must uphold the safety contract. unsafe { let mut n = sys::SYS___sysctl as u64; let r: i64; asm!( "sc", "bns+ 2f", "mr %r0, %r3", "li %r3, -1", "2:", inout("r0") n, inout("r3") ptr_reg!(name) => r, inout("r4") name_len as u64 => _, inout("r5") ptr_reg!(old_p) => _, inout("r6") ptr_reg!(old_len_p) => _, inout("r7") ptr_reg!(new_p) => _, inout("r8") new_len as u64 => _, out("r9") _, out("r10") _, out("r11") _, out("r12") _, out("cr0") _, options(nostack, preserves_flags) ); if r as c_int == -1 { Err(n as c_int) } else { Ok(r as c_int) } } } let mut auxv: [sys::Elf64_Auxinfo; sys::AT_COUNT as usize] = unsafe { mem::zeroed() }; let mut len = core::mem::size_of_val(&auxv) as c_size_t; let pid = getpid(); let mib = [ sys::CTL_KERN as c_int, sys::KERN_PROC as c_int, sys::KERN_PROC_AUXV as c_int, pid, ]; #[allow(clippy::cast_possible_truncation)] // SAFETY: // - `mib.len()` does not exceed the size of `mib`. // - `len` does not exceed the size of `auxv`. // - `sysctl` is thread-safe. unsafe { sysctl( mib.as_ptr(), mib.len() as c_uint, auxv.as_mut_ptr().cast::(), &mut len, ptr::null_mut(), 0, )?; } for aux in &auxv { if aux.a_type == type_ as c_long { // SAFETY: aux.a_un is #[repr(C)] union and all fields have // the same size and can be safely transmuted to integers. return Ok(unsafe { aux.a_un.a_val as c_ulong }); } } Err(0) } assert_eq!(os::getauxval(ffi::AT_HWCAP), getauxval_sysctl_libc(ffi::AT_HWCAP)); assert_eq!(os::getauxval(ffi::AT_HWCAP2), getauxval_sysctl_libc(ffi::AT_HWCAP2)); assert_eq!( os::getauxval(ffi::AT_HWCAP), getauxval_sysctl_asm_syscall(ffi::AT_HWCAP).unwrap() ); assert_eq!( os::getauxval(ffi::AT_HWCAP2), // AT_HWCAP2 is only available on FreeBSD 13+, at least for aarch64. getauxval_sysctl_asm_syscall(ffi::AT_HWCAP2).unwrap_or(0) ); } // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate, FFI bindings defined // in libc, and FFI bindings generated for the platform's latest header file // using bindgen have compatible signatures (or the same values if constants). // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[allow( clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation, clippy::no_effect_underscore_binding )] const _: fn() = || { use test_helper::{libc, sys}; #[cfg(not(target_os = "freebsd"))] type AtType = ffi::c_ulong; #[cfg(target_os = "freebsd")] type AtType = ffi::c_int; #[cfg(any(target_os = "linux", target_os = "android"))] { let mut _getauxval: unsafe extern "C" fn(ffi::c_ulong) -> ffi::c_ulong = ffi::getauxval; _getauxval = libc::getauxval; _getauxval = sys::getauxval; } #[cfg(all(target_arch = "aarch64", target_os = "android"))] { let mut ___system_property_get: unsafe extern "C" fn( *const ffi::c_char, *mut ffi::c_char, ) -> ffi::c_int = ffi::__system_property_get; ___system_property_get = libc::__system_property_get; ___system_property_get = sys::__system_property_get; static_assert!(ffi::PROP_VALUE_MAX == libc::PROP_VALUE_MAX); static_assert!(ffi::PROP_VALUE_MAX == sys::PROP_VALUE_MAX as ffi::c_int); } #[cfg(target_os = "freebsd")] { let mut _elf_aux_info: unsafe extern "C" fn( ffi::c_int, *mut ffi::c_void, ffi::c_int, ) -> ffi::c_int = ffi::elf_aux_info; _elf_aux_info = libc::elf_aux_info; _elf_aux_info = sys::elf_aux_info; } #[cfg(not(target_os = "freebsd"))] // libc doesn't have this on FreeBSD static_assert!(ffi::AT_HWCAP == libc::AT_HWCAP); static_assert!(ffi::AT_HWCAP == sys::AT_HWCAP as AtType); #[cfg(not(target_os = "freebsd"))] // libc doesn't have this on FreeBSD static_assert!(ffi::AT_HWCAP2 == libc::AT_HWCAP2); static_assert!(ffi::AT_HWCAP2 == sys::AT_HWCAP2 as AtType); #[cfg(target_arch = "aarch64")] { // static_assert!(arch::HWCAP_ATOMICS == libc::HWCAP_ATOMICS); // libc doesn't have this static_assert!(arch::HWCAP_ATOMICS == sys::HWCAP_ATOMICS as ffi::c_ulong); // static_assert!(HWCAP_USCAT == libc::HWCAP_USCAT); // libc doesn't have this static_assert!(arch::HWCAP_USCAT == sys::HWCAP_USCAT as ffi::c_ulong); #[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(target_pointer_width = "64")] { // static_assert!(HWCAP2_LRCPC3 == libc::HWCAP2_LRCPC3); // libc doesn't have this static_assert!(arch::HWCAP2_LRCPC3 == sys::HWCAP2_LRCPC3 as ffi::c_ulong); // static_assert!(HWCAP2_LSE128 == libc::HWCAP2_LSE128); // libc doesn't have this static_assert!(arch::HWCAP2_LSE128 == sys::HWCAP2_LSE128 as ffi::c_ulong); } } #[cfg(target_arch = "powerpc64")] { // static_assert!(arch::PPC_FEATURE2_ARCH_2_07 == libc::PPC_FEATURE2_ARCH_2_07); // libc doesn't have this static_assert!( arch::PPC_FEATURE2_ARCH_2_07 == sys::PPC_FEATURE2_ARCH_2_07 as ffi::c_ulong ); } }; } portable-atomic/src/imp/atomic128/detect/aarch64_fuchsia.rs0000644000175000017500000000650714661133735024466 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Run-time feature detection on aarch64 Fuchsia by using zx_system_get_features. // // As of nightly-2023-01-23, is_aarch64_feature_detected doesn't support run-time detection on Fuchsia. // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/mod.rs // // Refs: // - https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features // - https://github.com/llvm/llvm-project/commit/4e731abc55681751b5d736b613f7720e50eb1ad4 include!("common.rs"); #[allow(non_camel_case_types)] mod ffi { // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/types.h pub(crate) type zx_status_t = i32; // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/errors.h pub(crate) const ZX_OK: zx_status_t = 0; // https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/zircon/system/public/zircon/features.h pub(crate) const ZX_FEATURE_KIND_CPU: u32 = 0; pub(crate) const ZX_ARM64_FEATURE_ISA_ATOMICS: u32 = 1 << 8; #[link(name = "zircon")] extern "C" { // https://fuchsia.dev/fuchsia-src/reference/syscalls/system_get_features pub(crate) fn zx_system_get_features(kind: u32, features: *mut u32) -> zx_status_t; } } fn zx_system_get_features(kind: u32) -> u32 { let mut out = 0_u32; // SAFETY: the pointer is valid because we got it from a reference. let res = unsafe { ffi::zx_system_get_features(kind, &mut out) }; if res != ffi::ZX_OK { return 0; } out } #[cold] fn _detect(info: &mut CpuInfo) { let features = zx_system_get_features(ffi::ZX_FEATURE_KIND_CPU); if features & ffi::ZX_ARM64_FEATURE_ISA_ATOMICS != 0 { info.set(CpuInfo::HAS_LSE); } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; #[test] fn test_fuchsia() { let features = zx_system_get_features(ffi::ZX_FEATURE_KIND_CPU); assert_ne!(features, 0); std::eprintln!("features: {:b}", features); } // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings // generated for the platform's latest header file using bindgen have // compatible signatures (or the same values if constants). // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[allow( clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation, clippy::no_effect_underscore_binding )] const _: fn() = || { use test_helper::sys; // TODO(codegen): zx_system_get_features let _: ffi::zx_status_t = 0 as sys::zx_status_t; static_assert!(ffi::ZX_OK == sys::ZX_OK as ffi::zx_status_t); static_assert!(ffi::ZX_FEATURE_KIND_CPU == sys::ZX_FEATURE_KIND_CPU); static_assert!(ffi::ZX_ARM64_FEATURE_ISA_ATOMICS == sys::ZX_ARM64_FEATURE_ISA_ATOMICS); }; } portable-atomic/src/imp/atomic128/detect/x86_64.rs0000644000175000017500000001075514661133735022472 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/rust-lang/stdarch. #![cfg_attr(any(not(target_feature = "sse"), portable_atomic_sanitize_thread), allow(dead_code))] // Miri doesn't support inline assembly used in __cpuid: https://github.com/rust-lang/miri/issues/932 // SGX doesn't support CPUID: https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/core_arch/src/x86/cpuid.rs#L102-L105 #[cfg(any(target_env = "sgx", miri))] compile_error!("internal error: this module is not supported on this environment"); include!("common.rs"); #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::arch::x86_64::{CpuidResult, _xgetbv}; // Workaround for https://github.com/rust-lang/rust/issues/101346 // It is not clear if our use cases are affected, but we implement this just in case. // // Refs: // - https://www.felixcloutier.com/x86/cpuid // - https://en.wikipedia.org/wiki/CPUID // - https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/core_arch/src/x86/cpuid.rs unsafe fn __cpuid(leaf: u32) -> CpuidResult { let eax; let mut ebx; let ecx; let edx; // SAFETY: the caller must guarantee that CPU supports `cpuid`. unsafe { asm!( // rbx is reserved by LLVM "mov {ebx_tmp:r}, rbx", "cpuid", "xchg {ebx_tmp:r}, rbx", // restore rbx ebx_tmp = out(reg) ebx, inout("eax") leaf => eax, inout("ecx") 0 => ecx, out("edx") edx, options(nostack, preserves_flags), ); } CpuidResult { eax, ebx, ecx, edx } } // https://en.wikipedia.org/wiki/CPUID const VENDOR_ID_INTEL: [u8; 12] = *b"GenuineIntel"; const VENDOR_ID_AMD: [u8; 12] = *b"AuthenticAMD"; unsafe fn _vendor_id() -> [u8; 12] { // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L40-L59 // SAFETY: the caller must guarantee that CPU supports `cpuid`. let CpuidResult { ebx, ecx, edx, .. } = unsafe { __cpuid(0) }; let vendor_id: [[u8; 4]; 3] = [ebx.to_ne_bytes(), edx.to_ne_bytes(), ecx.to_ne_bytes()]; // SAFETY: transmute is safe because `[u8; 12]` and `[[u8; 4]; 3]` has the same layout. unsafe { core::mem::transmute(vendor_id) } } #[cold] fn _detect(info: &mut CpuInfo) { // SAFETY: Calling `_vendor_id`` is safe because the CPU has `cpuid` support. let vendor_id = unsafe { _vendor_id() }; // SAFETY: Calling `__cpuid`` is safe because the CPU has `cpuid` support. let proc_info_ecx = unsafe { __cpuid(0x0000_0001_u32).ecx }; // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L111 if test(proc_info_ecx, 13) { info.set(CpuInfo::HAS_CMPXCHG16B); } // VMOVDQA is atomic on Intel and AMD CPUs with AVX. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104688 for details. if vendor_id == VENDOR_ID_INTEL || vendor_id == VENDOR_ID_AMD { // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/x86.rs#L131-L224 let cpu_xsave = test(proc_info_ecx, 26); if cpu_xsave { let cpu_osxsave = test(proc_info_ecx, 27); if cpu_osxsave { // SAFETY: Calling `_xgetbv`` is safe because the CPU has `xsave` support // and OS has set `osxsave`. let xcr0 = unsafe { _xgetbv(0) }; let os_avx_support = xcr0 & 6 == 6; if os_avx_support && test(proc_info_ecx, 28) { info.set(CpuInfo::HAS_VMOVDQA_ATOMIC); } } } } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { #[cfg(not(portable_atomic_test_outline_atomics_detect_false))] use super::*; #[cfg(not(portable_atomic_test_outline_atomics_detect_false))] #[test] fn test_cpuid() { assert_eq!(std::is_x86_feature_detected!("cmpxchg16b"), detect().has_cmpxchg16b()); let vendor_id = unsafe { _vendor_id() }; if vendor_id == VENDOR_ID_INTEL || vendor_id == VENDOR_ID_AMD { assert_eq!(std::is_x86_feature_detected!("avx"), detect().has_vmovdqa_atomic()); } else { assert!(!detect().has_vmovdqa_atomic()); } } } portable-atomic/src/imp/atomic128/detect/aarch64_macos.rs0000644000175000017500000001354714661133735024150 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Run-time feature detection on aarch64 macOS by using sysctl. // // This module is currently only enabled on tests because aarch64 macOS always supports FEAT_LSE and FEAT_LSE2. // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/include/llvm/TargetParser/AArch64TargetParser.h#L494 // // If macOS supporting Armv9.4-a becomes popular in the future, this module will // be used to support outline-atomics for FEAT_LSE128/FEAT_LRCPC3. // // Refs: https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics // // Note that iOS doesn't support sysctl: // - https://developer.apple.com/forums/thread/9440 // - https://nabla-c0d3.github.io/blog/2015/06/16/ios9-security-privacy include!("common.rs"); use core::ptr; // core::ffi::c_* (except c_void) requires Rust 1.64, libc will soon require Rust 1.47 #[allow(non_camel_case_types)] mod ffi { pub(crate) use super::c_types::{c_char, c_int, c_size_t, c_void}; extern "C" { // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname // https://github.com/apple-oss-distributions/xnu/blob/5c2921b07a2480ab43ec66f5b9e41cb872bc554f/bsd/sys/sysctl.h // https://github.com/rust-lang/libc/blob/0.2.139/src/unix/bsd/apple/mod.rs#L5167-L5173 pub(crate) fn sysctlbyname( name: *const c_char, old_p: *mut c_void, old_len_p: *mut c_size_t, new_p: *mut c_void, new_len: c_size_t, ) -> c_int; } } unsafe fn sysctlbyname32(name: &[u8]) -> Option { const OUT_LEN: ffi::c_size_t = core::mem::size_of::() as ffi::c_size_t; debug_assert_eq!(name.last(), Some(&0), "{:?}", name); debug_assert_eq!(name.iter().filter(|&&v| v == 0).count(), 1, "{:?}", name); let mut out = 0_u32; let mut out_len = OUT_LEN; // SAFETY: // - the caller must guarantee that `name` a valid C string. // - `out_len` does not exceed the size of `out`. // - `sysctlbyname` is thread-safe. let res = unsafe { ffi::sysctlbyname( name.as_ptr().cast::(), (&mut out as *mut u32).cast::(), &mut out_len, ptr::null_mut(), 0, ) }; if res != 0 { return None; } debug_assert_eq!(out_len, OUT_LEN); Some(out) } #[cold] fn _detect(info: &mut CpuInfo) { // hw.optional.armv8_1_atomics is available on macOS 11+ (note: aarch64 support was added on macOS 11), // hw.optional.arm.FEAT_* are only available on macOS 12+. // Query both names in case future versions of macOS remove the old name. // https://github.com/golang/go/commit/c15593197453b8bf90fc3a9080ba2afeaf7934ea // https://github.com/google/boringssl/commit/91e0b11eba517d83b910b20fe3740eeb39ecb37e // SAFETY: we passed a valid C string. if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE\0").unwrap_or(0) != 0 || sysctlbyname32(b"hw.optional.armv8_1_atomics\0").unwrap_or(0) != 0 } { info.set(CpuInfo::HAS_LSE); } // SAFETY: we passed a valid C string. if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE2\0").unwrap_or(0) != 0 } { info.set(CpuInfo::HAS_LSE2); } // we currently only use FEAT_LSE and FEAT_LSE2 in outline-atomics. #[cfg(test)] { // SAFETY: we passed a valid C string. if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE128\0").unwrap_or(0) != 0 } { info.set(CpuInfo::HAS_LSE128); } // SAFETY: we passed a valid C string. if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC3\0").unwrap_or(0) != 0 } { info.set(CpuInfo::HAS_RCPC3); } } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; #[test] fn test_macos() { unsafe { assert_eq!(sysctlbyname32(b"hw.optional.armv8_1_atomics\0"), Some(1)); assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LSE\0"), Some(1)); assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LSE2\0"), Some(1)); assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LSE128\0"), None); assert_eq!(std::io::Error::last_os_error().kind(), std::io::ErrorKind::NotFound); assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC\0"), Some(1)); assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC2\0"), Some(1)); assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC3\0"), None); assert_eq!(std::io::Error::last_os_error().kind(), std::io::ErrorKind::NotFound); } } // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate, FFI bindings defined // in libc, and FFI bindings generated for the platform's latest header file // using bindgen have compatible signatures (or the same values if constants). // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // See also tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[allow( clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::no_effect_underscore_binding )] const _: fn() = || { use test_helper::{libc, sys}; let mut _sysctlbyname: unsafe extern "C" fn( *const ffi::c_char, *mut ffi::c_void, *mut ffi::c_size_t, *mut ffi::c_void, ffi::c_size_t, ) -> ffi::c_int = ffi::sysctlbyname; _sysctlbyname = libc::sysctlbyname; _sysctlbyname = sys::sysctlbyname; }; } portable-atomic/src/imp/atomic128/detect/aarch64_windows.rs0000644000175000017500000000636614661133735024541 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Run-time feature detection on aarch64 Windows by using IsProcessorFeaturePresent. // // As of nightly-2023-01-23, is_aarch64_feature_detected doesn't support run-time detection of FEAT_LSE on Windows. // https://github.com/rust-lang/stdarch/blob/a0c30f3e3c75adcd6ee7efc94014ebcead61c507/crates/std_detect/src/detect/os/windows/aarch64.rs // https://github.com/rust-lang/stdarch/pull/1373 // // Refs: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent include!("common.rs"); // windows-sys requires Rust 1.56 #[allow(clippy::upper_case_acronyms)] mod ffi { pub(crate) type DWORD = u32; pub(crate) type BOOL = i32; pub(crate) const FALSE: BOOL = 0; // Defined in winnt.h of Windows SDK. pub(crate) const PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE: DWORD = 34; extern "system" { // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent pub(crate) fn IsProcessorFeaturePresent(ProcessorFeature: DWORD) -> BOOL; } } #[cold] fn _detect(info: &mut CpuInfo) { // SAFETY: calling IsProcessorFeaturePresent is safe, and FALSE is also // returned if the HAL does not support detection of the specified feature. if unsafe { ffi::IsProcessorFeaturePresent(ffi::PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) != ffi::FALSE } { info.set(CpuInfo::HAS_LSE); } } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; // Static assertions for FFI bindings. // This checks that FFI bindings defined in this crate and FFI bindings defined // in windows-sys have compatible signatures (or the same values if constants). // Since this is static assertion, we can detect problems with // `cargo check --tests --target ` run in CI (via TESTS=1 build.sh) // without actually running tests on these platforms. // (Unlike libc, windows-sys programmatically generates bindings from Windows // API metadata, so it should be enough to check compatibility with the // windows-sys' signatures/values.) // See also tools/codegen/src/ffi.rs. // TODO(codegen): auto-generate this test #[allow( clippy::cast_possible_wrap, clippy::cast_sign_loss, clippy::cast_possible_truncation, clippy::no_effect_underscore_binding )] const _: fn() = || { use test_helper::windows_sys; let _: ffi::DWORD = 0 as windows_sys::Win32::System::Threading::PROCESSOR_FEATURE_ID; let _: ffi::BOOL = 0 as windows_sys::Win32::Foundation::BOOL; let mut _sysctl: unsafe extern "system" fn(ffi::DWORD) -> ffi::BOOL = ffi::IsProcessorFeaturePresent; _sysctl = windows_sys::Win32::System::Threading::IsProcessorFeaturePresent; static_assert!(ffi::FALSE == windows_sys::Win32::Foundation::FALSE); static_assert!( ffi::PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE == windows_sys::Win32::System::Threading::PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE ); }; } portable-atomic/src/imp/interrupt/0000775000175000017500000000000014661133735020235 5ustar jamespagejamespageportable-atomic/src/imp/interrupt/xtensa.rs0000644000175000017500000000334014661133735022103 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Refs: // - Xtensa Instruction Set Architecture (ISA) Reference Manual https://0x04.net/~mwk/doc/xtensa.pdf // - Linux kernel's Xtensa atomic implementation https://github.com/torvalds/linux/blob/v6.1/arch/xtensa/include/asm/atomic.h use core::arch::asm; pub(super) use core::sync::atomic; pub(super) type State = u32; /// Disables interrupts and returns the previous interrupt state. #[inline] pub(super) fn disable() -> State { let r: State; // SAFETY: reading the PS special register and disabling all interrupts is safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. // Interrupt level 15 to disable all interrupts. // SYNC after RSIL is not required. asm!("rsil {0}, 15", out(reg) r, options(nostack)); } r } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline] pub(super) unsafe fn restore(r: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // and we've checked that interrupts were enabled before disabling interrupts. unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. // SYNC after WSR is required to guarantee that subsequent RSIL read the written value. asm!( "wsr.ps {0}", "rsync", in(reg) r, options(nostack), ); } } portable-atomic/src/imp/interrupt/README.md0000644000175000017500000000532114661133735021513 0ustar jamespagejamespage# Implementation of disabling interrupts This module is used to provide atomic CAS for targets where atomic CAS is not available in the standard library. - On MSP430 and AVR, they are always single-core, so this module is always used. - On ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa, they could be multi-core, so this module is used when the `unsafe-assume-single-core` feature is enabled. The implementation uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode. Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent. Consider using the [`critical-section` feature](../../../README.md#optional-features-critical-section) for systems that cannot use the `unsafe-assume-single-core` feature. For some targets, the implementation can be changed by explicitly enabling features. - On ARMv6-M, this disables interrupts by modifying the PRIMASK register. - On pre-v6 ARM, this disables interrupts by modifying the I (IRQ mask) bit of the CPSR. - On pre-v6 ARM with the `disable-fiq` feature, this disables interrupts by modifying the I (IRQ mask) bit and F (FIQ mask) bit of the CPSR. - On RISC-V (without A-extension), this disables interrupts by modifying the MIE (Machine Interrupt Enable) bit of the `mstatus` register. - On RISC-V (without A-extension) with the `s-mode` feature, this disables interrupts by modifying the SIE (Supervisor Interrupt Enable) bit of the `sstatus` register. - On RISC-V (without A-extension) with the `force-amo` feature, this uses AMO instructions for RMWs that have corresponding AMO instructions even if A-extension is disabled. For other RMWs, this disables interrupts as usual. - On MSP430, this disables interrupts by modifying the GIE (Global Interrupt Enable) bit of the status register (SR). - On AVR, this disables interrupts by modifying the I (Global Interrupt Enable) bit of the status register (SREG). - On Xtensa, this disables interrupts by modifying the PS special register. Some operations don't require disabling interrupts (loads and stores on targets except for AVR, but additionally on MSP430 {8,16}-bit `add,sub,and,or,xor,not`, on RISC-V with the `force-amo` feature 32-bit(RV32)/{32,64}-bit(RV64) `swap,fetch_{add,sub,and,or,xor,not,max,min},add,sub,and,or,xor,not` and {8,16}-bit `fetch_{and,or,xor,not},and,or,xor,not`). However, when the `critical-section` feature is enabled, critical sections are taken for all atomic operations. Feel free to submit an issue if your target is not supported yet. portable-atomic/src/imp/interrupt/msp430.rs0000644000175000017500000000474114661133735021635 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/rust-embedded/msp430. // // See also src/imp/msp430.rs. // // Refs: https://www.ti.com/lit/ug/slau208q/slau208q.pdf #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; pub(super) use super::super::msp430 as atomic; pub(super) type State = u16; /// Disables interrupts and returns the previous interrupt state. #[inline] pub(super) fn disable() -> State { let r: State; // SAFETY: reading the status register and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. // Do not use `preserves_flags` because DINT modifies the GIE (global interrupt enable) bit of the status register. #[cfg(not(portable_atomic_no_asm))] asm!( "mov R2, {0}", "dint {{ nop", out(reg) r, options(nostack), ); #[cfg(portable_atomic_no_asm)] { llvm_asm!("mov R2, $0" : "=r"(r) ::: "volatile"); llvm_asm!("dint { nop" ::: "memory" : "volatile"); } } r } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline] pub(super) unsafe fn restore(r: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, unsafe { // This clobbers the entire status register, but we never explicitly modify // flags within a critical session, and the only flags that may be changed // within a critical session are the arithmetic flags that are changed as // a side effect of arithmetic operations, etc., which LLVM recognizes, // so it is safe to clobber them here. // See also the discussion at https://github.com/taiki-e/portable-atomic/pull/40. // // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. // Do not use `preserves_flags` because MOV modifies the status register. #[cfg(not(portable_atomic_no_asm))] asm!("nop {{ mov {0}, R2 {{ nop", in(reg) r, options(nostack)); #[cfg(portable_atomic_no_asm)] llvm_asm!("nop { mov $0, R2 { nop" :: "r"(r) : "memory" : "volatile"); } } portable-atomic/src/imp/interrupt/armv6m.rs0000644000175000017500000000303614661133735022013 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/rust-embedded/cortex-m. // // Generated asm: // - armv6-m https://godbolt.org/z/YxME38xcM #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; pub(super) use core::sync::atomic; pub(super) type State = u32; /// Disables interrupts and returns the previous interrupt state. #[inline] pub(super) fn disable() -> State { let r: State; // SAFETY: reading the priority mask register and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. asm!( "mrs {0}, PRIMASK", "cpsid i", out(reg) r, options(nostack, preserves_flags), ); } r } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline] pub(super) unsafe fn restore(r: State) { if r & 0x1 == 0 { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // and we've checked that interrupts were enabled before disabling interrupts. unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. asm!("cpsie i", options(nostack, preserves_flags)); } } } portable-atomic/src/imp/interrupt/mod.rs0000644000175000017500000010716714661133735021374 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Critical section based fallback implementations // // This module supports two different critical section implementations: // - Built-in "disable all interrupts". // - Call into the `critical-section` crate (which allows the user to plug any implementation). // // The `critical-section`-based fallback is enabled when the user asks for it with the `critical-section` // Cargo feature. // // The "disable interrupts" fallback is not sound on multi-core systems. // Also, this uses privileged instructions to disable interrupts, so it usually // doesn't work on unprivileged mode. Using this fallback in an environment where privileged // instructions are not available is also usually considered **unsound**, // although the details are system-dependent. // // Therefore, this implementation will only be enabled in one of the following cases: // // - When the user explicitly declares that the system is single-core and that // privileged instructions are available using an unsafe cfg. // - When we can safely assume that the system is single-core and that // privileged instructions are available on the system. // // AVR, which is single core[^avr1] and LLVM also generates code that disables // interrupts [^avr2] in atomic ops by default, is considered the latter. // MSP430 as well. // // See also README.md of this directory. // // [^avr1]: https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp#L1074 // [^avr2]: https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/test/CodeGen/AVR/atomics/load16.ll#L5 // On some platforms, atomic load/store can be implemented in a more efficient // way than disabling interrupts. On MSP430, some RMWs that do not return the // previous value can also be optimized. // // Note: On single-core systems, it is okay to use critical session-based // CAS together with atomic load/store. The load/store will not be // called while interrupts are disabled, and since the load/store is // atomic, it is not affected by interrupts even if interrupts are enabled. #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] use arch::atomic; #[cfg(not(feature = "critical-section"))] #[cfg_attr( all( target_arch = "arm", any(target_feature = "mclass", portable_atomic_target_feature = "mclass"), ), path = "armv6m.rs" )] #[cfg_attr( all( target_arch = "arm", not(any(target_feature = "mclass", portable_atomic_target_feature = "mclass")), ), path = "armv4t.rs" )] #[cfg_attr(target_arch = "avr", path = "avr.rs")] #[cfg_attr(target_arch = "msp430", path = "msp430.rs")] #[cfg_attr(any(target_arch = "riscv32", target_arch = "riscv64"), path = "riscv.rs")] #[cfg_attr(target_arch = "xtensa", path = "xtensa.rs")] mod arch; use core::{cell::UnsafeCell, sync::atomic::Ordering}; // Critical section implementations might use locks internally. #[cfg(feature = "critical-section")] const IS_ALWAYS_LOCK_FREE: bool = false; // Consider atomic operations based on disabling interrupts on single-core // systems are lock-free. (We consider the pre-v6 ARM Linux's atomic operations // provided in a similar way by the Linux kernel to be lock-free.) #[cfg(not(feature = "critical-section"))] const IS_ALWAYS_LOCK_FREE: bool = true; #[cfg(feature = "critical-section")] #[inline] fn with(f: F) -> R where F: FnOnce() -> R, { critical_section::with(|_| f()) } #[cfg(not(feature = "critical-section"))] #[inline] fn with(f: F) -> R where F: FnOnce() -> R, { // Get current interrupt state and disable interrupts let state = arch::disable(); let r = f(); // Restore interrupt state // SAFETY: the state was retrieved by the previous `disable`. unsafe { arch::restore(state) } r } #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] #[cfg_attr(target_pointer_width = "128", repr(C, align(16)))] pub(crate) struct AtomicPtr { p: UnsafeCell<*mut T>, } // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Send for AtomicPtr {} // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Sync for AtomicPtr {} impl AtomicPtr { #[inline] pub(crate) const fn new(p: *mut T) -> Self { Self { p: UnsafeCell::new(p) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::is_always_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } #[inline] pub(crate) fn get_mut(&mut self) -> &mut *mut T { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.p.get() } } #[inline] pub(crate) fn into_inner(self) -> *mut T { self.p.into_inner() } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> *mut T { crate::utils::assert_load_ordering(order); #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] { self.as_native().load(order) } #[cfg(any(target_arch = "avr", feature = "critical-section"))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.p.get().read() }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, ptr: *mut T, order: Ordering) { crate::utils::assert_store_ordering(order); #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] { self.as_native().store(ptr, order); } #[cfg(any(target_arch = "avr", feature = "critical-section"))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.p.get().write(ptr) }); } #[inline] pub(crate) fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { let _ = order; #[cfg(portable_atomic_force_amo)] { self.as_native().swap(ptr, order) } #[cfg(not(portable_atomic_force_amo))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.p.get().read(); self.p.get().write(ptr); prev }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.p.get().read(); if prev == current { self.p.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) const fn as_ptr(&self) -> *mut *mut T { self.p.get() } #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] #[inline] fn as_native(&self) -> &atomic::AtomicPtr { // SAFETY: AtomicPtr and atomic::AtomicPtr have the same layout and // guarantee atomicity in a compatible way. (see module-level comments) unsafe { &*(self as *const Self as *const atomic::AtomicPtr) } } } macro_rules! atomic_int { (base, $atomic_type:ident, $int_type:ident, $align:literal) => { #[repr(C, align($align))] pub(crate) struct $atomic_type { v: UnsafeCell<$int_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Sync for $atomic_type {} impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::is_always_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { IS_ALWAYS_LOCK_FREE } #[inline] pub(crate) fn get_mut(&mut self) -> &mut $int_type { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.v.get() } } #[inline] pub(crate) fn into_inner(self) -> $int_type { self.v.into_inner() } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; (load_store_atomic $([$kind:ident])?, $atomic_type:ident, $int_type:ident, $align:literal) => { atomic_int!(base, $atomic_type, $int_type, $align); #[cfg(not(portable_atomic_force_amo))] atomic_int!(cas[emulate], $atomic_type, $int_type); #[cfg(portable_atomic_force_amo)] atomic_int!(cas $([$kind])?, $atomic_type, $int_type); impl $atomic_type { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] { self.as_native().load(order) } #[cfg(any(target_arch = "avr", feature = "critical-section"))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().read() }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] { self.as_native().store(val, order); } #[cfg(any(target_arch = "avr", feature = "critical-section"))] // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().write(val) }); } #[cfg(not(any(target_arch = "avr", feature = "critical-section")))] #[inline] fn as_native(&self) -> &atomic::$atomic_type { // SAFETY: $atomic_type and atomic::$atomic_type have the same layout and // guarantee atomicity in a compatible way. (see module-level comments) unsafe { &*(self as *const Self as *const atomic::$atomic_type) } } } #[cfg(not(all(target_arch = "msp430", not(feature = "critical-section"))))] impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); #[cfg(not(all(target_arch = "msp430", not(feature = "critical-section"))))] impl $atomic_type { #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } } #[cfg(all(target_arch = "msp430", not(feature = "critical-section")))] impl $atomic_type { #[inline] pub(crate) fn add(&self, val: $int_type, order: Ordering) { self.as_native().add(val, order); } #[inline] pub(crate) fn sub(&self, val: $int_type, order: Ordering) { self.as_native().sub(val, order); } #[inline] pub(crate) fn and(&self, val: $int_type, order: Ordering) { self.as_native().and(val, order); } #[inline] pub(crate) fn or(&self, val: $int_type, order: Ordering) { self.as_native().or(val, order); } #[inline] pub(crate) fn xor(&self, val: $int_type, order: Ordering) { self.as_native().xor(val, order); } #[inline] pub(crate) fn not(&self, order: Ordering) { self.as_native().not(order); } } }; (load_store_critical_session, $atomic_type:ident, $int_type:ident, $align:literal) => { atomic_int!(base, $atomic_type, $int_type, $align); atomic_int!(cas[emulate], $atomic_type, $int_type); impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().read() }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { self.v.get().write(val) }); } #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } } }; (cas[emulate], $atomic_type:ident, $int_type:ident) => { impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(val); prev }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); if prev == current { self.v.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_add(val)); prev }) } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_sub(val)); prev }) } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev & val); prev }) } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!(prev & val)); prev }) } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev | val); prev }) } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev ^ val); prev }) } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::max(prev, val)); prev }) } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::min(prev, val)); prev }) } #[inline] pub(crate) fn fetch_not(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!prev); prev }) } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_neg()); prev }) } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } }; // cfg(portable_atomic_force_amo) 32-bit(RV32)/{32,64}-bit(RV64) RMW (cas, $atomic_type:ident, $int_type:ident) => { impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().swap(val, order) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); if prev == current { self.v.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_add(val, order) } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_sub(val, order) } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_and(val, order) } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!(prev & val)); prev }) } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_or(val, order) } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_xor(val, order) } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_max(val, order) } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_min(val, order) } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { self.as_native().fetch_not(order) } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_neg()); prev }) } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } }; // cfg(portable_atomic_force_amo) {8,16}-bit RMW (cas[sub_word], $atomic_type:ident, $int_type:ident) => { impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(val); prev }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); if prev == current { self.v.get().write(new); Ok(prev) } else { Err(prev) } }) } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_add(val)); prev }) } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_sub(val)); prev }) } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_and(val, order) } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(!(prev & val)); prev }) } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_or(val, order) } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { self.as_native().fetch_xor(val, order) } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::max(prev, val)); prev }) } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(core::cmp::min(prev, val)); prev }) } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $int_type { self.as_native().fetch_not(order) } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by disabling interrupts (see // module-level comments) and the raw pointer is valid because we got it // from a reference. with(|| unsafe { let prev = self.v.get().read(); self.v.get().write(prev.wrapping_neg()); prev }) } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } } }; } #[cfg(target_pointer_width = "16")] atomic_int!(load_store_atomic, AtomicIsize, isize, 2); #[cfg(target_pointer_width = "16")] atomic_int!(load_store_atomic, AtomicUsize, usize, 2); #[cfg(target_pointer_width = "32")] atomic_int!(load_store_atomic, AtomicIsize, isize, 4); #[cfg(target_pointer_width = "32")] atomic_int!(load_store_atomic, AtomicUsize, usize, 4); #[cfg(target_pointer_width = "64")] atomic_int!(load_store_atomic, AtomicIsize, isize, 8); #[cfg(target_pointer_width = "64")] atomic_int!(load_store_atomic, AtomicUsize, usize, 8); #[cfg(target_pointer_width = "128")] atomic_int!(load_store_atomic, AtomicIsize, isize, 16); #[cfg(target_pointer_width = "128")] atomic_int!(load_store_atomic, AtomicUsize, usize, 16); atomic_int!(load_store_atomic[sub_word], AtomicI8, i8, 1); atomic_int!(load_store_atomic[sub_word], AtomicU8, u8, 1); atomic_int!(load_store_atomic[sub_word], AtomicI16, i16, 2); atomic_int!(load_store_atomic[sub_word], AtomicU16, u16, 2); #[cfg(not(target_pointer_width = "16"))] atomic_int!(load_store_atomic, AtomicI32, i32, 4); #[cfg(not(target_pointer_width = "16"))] atomic_int!(load_store_atomic, AtomicU32, u32, 4); #[cfg(target_pointer_width = "16")] #[cfg(any(test, feature = "fallback"))] atomic_int!(load_store_critical_session, AtomicI32, i32, 4); #[cfg(target_pointer_width = "16")] #[cfg(any(test, feature = "fallback"))] atomic_int!(load_store_critical_session, AtomicU32, u32, 4); #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] atomic_int!(load_store_atomic, AtomicI64, i64, 8); #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] atomic_int!(load_store_atomic, AtomicU64, u64, 8); #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] #[cfg(any(test, feature = "fallback"))] atomic_int!(load_store_critical_session, AtomicI64, i64, 8); #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] #[cfg(any(test, feature = "fallback"))] atomic_int!(load_store_critical_session, AtomicU64, u64, 8); #[cfg(any(test, feature = "fallback"))] atomic_int!(load_store_critical_session, AtomicI128, i128, 16); #[cfg(any(test, feature = "fallback"))] atomic_int!(load_store_critical_session, AtomicU128, u128, 16); #[cfg(test)] mod tests { use super::*; test_atomic_ptr_single_thread!(); test_atomic_int_single_thread!(i8); test_atomic_int_single_thread!(u8); test_atomic_int_single_thread!(i16); test_atomic_int_single_thread!(u16); test_atomic_int_single_thread!(i32); test_atomic_int_single_thread!(u32); test_atomic_int_single_thread!(i64); test_atomic_int_single_thread!(u64); test_atomic_int_single_thread!(i128); test_atomic_int_single_thread!(u128); test_atomic_int_single_thread!(isize); test_atomic_int_single_thread!(usize); } portable-atomic/src/imp/interrupt/riscv.rs0000644000175000017500000000453014661133735021731 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Refs: // - https://five-embeddev.com/riscv-isa-manual/latest/machine.html#machine-status-registers-mstatus-and-mstatush // - https://five-embeddev.com/riscv-isa-manual/latest/supervisor.html#sstatus // // Generated asm: // - riscv64gc https://godbolt.org/z/osbzsT679 #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; pub(super) use super::super::riscv as atomic; // Status register #[cfg(not(portable_atomic_s_mode))] macro_rules! status { () => { "mstatus" }; } #[cfg(portable_atomic_s_mode)] macro_rules! status { () => { "sstatus" }; } // MIE (Machine Interrupt Enable) bit (1 << 3) #[cfg(not(portable_atomic_s_mode))] const MASK: State = 0x8; #[cfg(not(portable_atomic_s_mode))] macro_rules! mask { () => { "0x8" }; } // SIE (Supervisor Interrupt Enable) bit (1 << 1) #[cfg(portable_atomic_s_mode)] const MASK: State = 0x2; #[cfg(portable_atomic_s_mode)] macro_rules! mask { () => { "0x2" }; } #[cfg(target_arch = "riscv32")] pub(super) type State = u32; #[cfg(target_arch = "riscv64")] pub(super) type State = u64; /// Disables interrupts and returns the previous interrupt state. #[inline] pub(super) fn disable() -> State { let r: State; // SAFETY: reading mstatus and disabling interrupts is safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. asm!(concat!("csrrci {0}, ", status!(), ", ", mask!()), out(reg) r, options(nostack, preserves_flags)); } r } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline] pub(super) unsafe fn restore(r: State) { if r & MASK != 0 { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // and we've checked that interrupts were enabled before disabling interrupts. unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. asm!(concat!("csrsi ", status!(), ", ", mask!()), options(nostack, preserves_flags)); } } } portable-atomic/src/imp/interrupt/armv4t.rs0000644000175000017500000001476214661133735022030 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Refs: https://developer.arm.com/documentation/ddi0406/cb/System-Level-Architecture/The-System-Level-Programmers--Model/ARM-processor-modes-and-ARM-core-registers/Program-Status-Registers--PSRs-?lang=en // // Generated asm: // - armv5te https://godbolt.org/z/Teh7WajMs #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; // - 0x80 - I (IRQ mask) bit (1 << 7) // - 0x40 - F (FIQ mask) bit (1 << 6) // We disable only IRQs by default. See also https://github.com/taiki-e/portable-atomic/pull/28#issuecomment-1214146912. #[cfg(not(portable_atomic_disable_fiq))] macro_rules! mask { () => { "0x80" }; } #[cfg(portable_atomic_disable_fiq)] macro_rules! mask { () => { "0xC0" // 0x80 | 0x40 }; } pub(super) type State = u32; /// Disables interrupts and returns the previous interrupt state. #[inline] #[instruction_set(arm::a32)] pub(super) fn disable() -> State { let cpsr: State; // SAFETY: reading CPSR and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { asm!( "mrs {prev}, cpsr", concat!("orr {new}, {prev}, ", mask!()), "msr cpsr_c, {new}", prev = out(reg) cpsr, new = out(reg) _, // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. options(nostack, preserves_flags), ); } cpsr } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline] #[instruction_set(arm::a32)] pub(super) unsafe fn restore(cpsr: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, // // This clobbers the control field mask byte of CPSR. See msp430.rs to safety on this. // (preserves_flags is fine because we only clobber the I, F, T, and M bits of CPSR.) // // Refs: https://developer.arm.com/documentation/dui0473/m/arm-and-thumb-instructions/msr--general-purpose-register-to-psr- unsafe { // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. asm!("msr cpsr_c, {0}", in(reg) cpsr, options(nostack, preserves_flags)); } } // On pre-v6 ARM, we cannot use core::sync::atomic here because they call the // `__sync_*` builtins for non-relaxed load/store (because pre-v6 ARM doesn't // have Data Memory Barrier). // // Generated asm: // - armv5te https://godbolt.org/z/bMxK7M8Ta pub(crate) mod atomic { #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::{cell::UnsafeCell, sync::atomic::Ordering}; macro_rules! atomic { ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty, $asm_suffix:tt) => { #[repr(transparent)] pub(crate) struct $atomic_type $(<$($generics)*>)? { v: UnsafeCell<$value_type>, } // Send is implicitly implemented for atomic integers, but not for atomic pointers. // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Send for $atomic_type $(<$($generics)*>)? {} // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Sync for $atomic_type $(<$($generics)*>)? {} impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) fn load(&self, order: Ordering) -> $value_type { let src = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { let out; match order { Ordering::Relaxed => { asm!( concat!("ldr", $asm_suffix, " {out}, [{src}]"), src = in(reg) src, out = lateout(reg) out, options(nostack, preserves_flags, readonly), ); } Ordering::Acquire | Ordering::SeqCst => { // inline asm without nomem/readonly implies compiler fence. // And compiler fence is fine because the user explicitly declares that // the system is single-core by using an unsafe cfg. asm!( concat!("ldr", $asm_suffix, " {out}, [{src}]"), src = in(reg) src, out = lateout(reg) out, options(nostack, preserves_flags), ); } _ => unreachable!("{:?}", order), } out } } #[inline] pub(crate) fn store(&self, val: $value_type, _order: Ordering) { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { // inline asm without nomem/readonly implies compiler fence. // And compiler fence is fine because the user explicitly declares that // the system is single-core by using an unsafe cfg. asm!( concat!("str", $asm_suffix, " {val}, [{dst}]"), dst = in(reg) dst, val = in(reg) val, options(nostack, preserves_flags), ); } } } }; } atomic!(AtomicI8, i8, "b"); atomic!(AtomicU8, u8, "b"); atomic!(AtomicI16, i16, "h"); atomic!(AtomicU16, u16, "h"); atomic!(AtomicI32, i32, ""); atomic!(AtomicU32, u32, ""); atomic!(AtomicIsize, isize, ""); atomic!(AtomicUsize, usize, ""); atomic!([T] AtomicPtr, *mut T, ""); } portable-atomic/src/imp/interrupt/avr.rs0000644000175000017500000000426514661133735021400 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/Rahix/avr-device. // // Refs: // - AVR Instruction Set Manual https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; pub(super) type State = u8; /// Disables interrupts and returns the previous interrupt state. #[inline] pub(super) fn disable() -> State { let sreg: State; // SAFETY: reading the status register (SREG) and disabling interrupts are safe. // (see module-level comments of interrupt/mod.rs on the safety of using privileged instructions) unsafe { // Do not use `nomem` and `readonly` because prevent subsequent memory accesses from being reordered before interrupts are disabled. // Do not use `preserves_flags` because CLI modifies the I bit of the status register (SREG). // Refs: https://ww1.microchip.com/downloads/en/DeviceDoc/AVR-InstructionSet-Manual-DS40002198.pdf#page=58 #[cfg(not(portable_atomic_no_asm))] asm!( "in {0}, 0x3F", "cli", out(reg) sreg, options(nostack), ); #[cfg(portable_atomic_no_asm)] { llvm_asm!("in $0, 0x3F" : "=r"(sreg) ::: "volatile"); llvm_asm!("cli" ::: "memory" : "volatile"); } } sreg } /// Restores the previous interrupt state. /// /// # Safety /// /// The state must be the one retrieved by the previous `disable`. #[inline] pub(super) unsafe fn restore(sreg: State) { // SAFETY: the caller must guarantee that the state was retrieved by the previous `disable`, unsafe { // This clobbers the entire status register. See msp430.rs to safety on this. // // Do not use `nomem` and `readonly` because prevent preceding memory accesses from being reordered after interrupts are enabled. // Do not use `preserves_flags` because OUT modifies the status register (SREG). #[cfg(not(portable_atomic_no_asm))] asm!("out 0x3F, {0}", in(reg) sreg, options(nostack)); #[cfg(portable_atomic_no_asm)] llvm_asm!("out 0x3F, $0" :: "r"(sreg) : "memory" : "volatile"); } } portable-atomic/src/imp/arm_linux.rs0000644000175000017500000004477514661133735020564 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // 64-bit atomic implementation using kuser_cmpxchg64 on pre-v6 ARM Linux/Android. // // Refs: // - https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt // - https://github.com/rust-lang/compiler-builtins/blob/0.1.88/src/arm_linux.rs // // Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use // this module and use fallback implementation instead. // TODO: Since Rust 1.64, the Linux kernel requirement for Rust when using std is 3.2+, so it should // be possible to omit the dynamic kernel version check if the std feature is enabled on Rust 1.64+. // https://blog.rust-lang.org/2022/08/01/Increasing-glibc-kernel-requirements.html #[path = "fallback/outline_atomics.rs"] mod fallback; use core::{arch::asm, cell::UnsafeCell, mem, sync::atomic::Ordering}; use crate::utils::{Pair, U64}; // https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt const KUSER_HELPER_VERSION: usize = 0xFFFF0FFC; // __kuser_helper_version >= 5 (kernel version 3.1+) const KUSER_CMPXCHG64: usize = 0xFFFF0F60; #[inline] fn __kuser_helper_version() -> i32 { use core::sync::atomic::AtomicI32; static CACHE: AtomicI32 = AtomicI32::new(0); let mut v = CACHE.load(Ordering::Relaxed); if v != 0 { return v; } // SAFETY: core assumes that at least __kuser_memory_barrier (__kuser_helper_version >= 3) is // available on this platform. __kuser_helper_version is always available on such a platform. v = unsafe { (KUSER_HELPER_VERSION as *const i32).read() }; CACHE.store(v, Ordering::Relaxed); v } #[inline] fn has_kuser_cmpxchg64() -> bool { // Note: detect_false cfg is intended to make it easy for portable-atomic developers to // test cases such as has_cmpxchg16b == false, has_lse == false, // __kuser_helper_version < 5, etc., and is not a public API. if cfg!(portable_atomic_test_outline_atomics_detect_false) { return false; } __kuser_helper_version() >= 5 } #[inline] unsafe fn __kuser_cmpxchg64(old_val: *const u64, new_val: *const u64, ptr: *mut u64) -> bool { // SAFETY: the caller must uphold the safety contract. unsafe { let f: extern "C" fn(*const u64, *const u64, *mut u64) -> u32 = mem::transmute(KUSER_CMPXCHG64 as *const ()); f(old_val, new_val, ptr) == 0 } } // 64-bit atomic load by two 32-bit atomic loads. #[inline] unsafe fn byte_wise_atomic_load(src: *const u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { let (out_lo, out_hi); asm!( "ldr {out_lo}, [{src}]", "ldr {out_hi}, [{src}, #4]", src = in(reg) src, out_lo = out(reg) out_lo, out_hi = out(reg) out_hi, options(pure, nostack, preserves_flags, readonly), ); U64 { pair: Pair { lo: out_lo, hi: out_hi } }.whole } } #[inline(always)] unsafe fn atomic_update_kuser_cmpxchg64(dst: *mut u64, mut f: F) -> u64 where F: FnMut(u64) -> u64, { debug_assert!(dst as usize % 8 == 0); debug_assert!(has_kuser_cmpxchg64()); // SAFETY: the caller must uphold the safety contract. unsafe { loop { // This is not single-copy atomic reads, but this is ok because subsequent // CAS will check for consistency. // // Note that the C++20 memory model does not allow mixed-sized atomic access, // so we must use inline assembly to implement byte_wise_atomic_load. // (i.e., byte-wise atomic based on the standard library's atomic types // cannot be used here). let prev = byte_wise_atomic_load(dst); let next = f(prev); if __kuser_cmpxchg64(&prev, &next, dst) { return prev; } } } } macro_rules! atomic_with_ifunc { ( unsafe fn $name:ident($($arg:tt)*) $(-> $ret_ty:ty)? { $($kuser_cmpxchg64_fn_body:tt)* } fallback = $seqcst_fallback_fn:ident ) => { #[inline] unsafe fn $name($($arg)*) $(-> $ret_ty)? { unsafe fn kuser_cmpxchg64_fn($($arg)*) $(-> $ret_ty)? { $($kuser_cmpxchg64_fn_body)* } // SAFETY: the caller must uphold the safety contract. // we only calls __kuser_cmpxchg64 if it is available. unsafe { ifunc!(unsafe fn($($arg)*) $(-> $ret_ty)? { if has_kuser_cmpxchg64() { kuser_cmpxchg64_fn } else { // Use SeqCst because __kuser_cmpxchg64 is always SeqCst. // https://github.com/torvalds/linux/blob/v6.1/arch/arm/kernel/entry-armv.S#L918-L925 fallback::$seqcst_fallback_fn } }) } } }; } atomic_with_ifunc! { unsafe fn atomic_load(src: *mut u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(src, |old| old) } } fallback = atomic_load_seqcst } atomic_with_ifunc! { unsafe fn atomic_store(dst: *mut u64, val: u64) { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |_| val); } } fallback = atomic_store_seqcst } atomic_with_ifunc! { unsafe fn atomic_swap(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |_| val) } } fallback = atomic_swap_seqcst } atomic_with_ifunc! { unsafe fn atomic_compare_exchange(dst: *mut u64, old: u64, new: u64) -> (u64, bool) { // SAFETY: the caller must uphold the safety contract. let prev = unsafe { atomic_update_kuser_cmpxchg64(dst, |v| if v == old { new } else { v }) }; (prev, prev == old) } fallback = atomic_compare_exchange_seqcst } atomic_with_ifunc! { unsafe fn atomic_add(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| x.wrapping_add(val)) } } fallback = atomic_add_seqcst } atomic_with_ifunc! { unsafe fn atomic_sub(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| x.wrapping_sub(val)) } } fallback = atomic_sub_seqcst } atomic_with_ifunc! { unsafe fn atomic_and(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| x & val) } } fallback = atomic_and_seqcst } atomic_with_ifunc! { unsafe fn atomic_nand(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| !(x & val)) } } fallback = atomic_nand_seqcst } atomic_with_ifunc! { unsafe fn atomic_or(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| x | val) } } fallback = atomic_or_seqcst } atomic_with_ifunc! { unsafe fn atomic_xor(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| x ^ val) } } fallback = atomic_xor_seqcst } atomic_with_ifunc! { unsafe fn atomic_max(dst: *mut u64, val: u64) -> u64 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| core::cmp::max(x as i64, val as i64) as u64) } } fallback = atomic_max_seqcst } atomic_with_ifunc! { unsafe fn atomic_umax(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| core::cmp::max(x, val)) } } fallback = atomic_umax_seqcst } atomic_with_ifunc! { unsafe fn atomic_min(dst: *mut u64, val: u64) -> u64 { #[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)] // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| core::cmp::min(x as i64, val as i64) as u64) } } fallback = atomic_min_seqcst } atomic_with_ifunc! { unsafe fn atomic_umin(dst: *mut u64, val: u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| core::cmp::min(x, val)) } } fallback = atomic_umin_seqcst } atomic_with_ifunc! { unsafe fn atomic_not(dst: *mut u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, |x| !x) } } fallback = atomic_not_seqcst } atomic_with_ifunc! { unsafe fn atomic_neg(dst: *mut u64) -> u64 { // SAFETY: the caller must uphold the safety contract. unsafe { atomic_update_kuser_cmpxchg64(dst, u64::wrapping_neg) } } fallback = atomic_neg_seqcst } macro_rules! atomic64 { ($atomic_type:ident, $int_type:ident, $atomic_max:ident, $atomic_min:ident) => { #[repr(C, align(8))] pub(crate) struct $atomic_type { v: UnsafeCell<$int_type>, } // Send is implicitly implemented. // SAFETY: any data races are prevented by the kernel user helper or the lock. unsafe impl Sync for $atomic_type {} impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { has_kuser_cmpxchg64() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { false } #[inline] pub(crate) fn get_mut(&mut self) -> &mut $int_type { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.v.get() } } #[inline] pub(crate) fn into_inner(self) -> $int_type { self.v.into_inner() } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_load(self.v.get().cast::()) as $int_type } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_store(self.v.get().cast::(), val as u64) } } #[inline] pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_swap(self.v.get().cast::(), val as u64) as $int_type } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { let (prev, ok) = atomic_compare_exchange( self.v.get().cast::(), current as u64, new as u64, ); if ok { Ok(prev as $int_type) } else { Err(prev as $int_type) } } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_add(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_sub(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_and(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_nand(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_or(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_xor(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { $atomic_max(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { $atomic_min(self.v.get().cast::(), val as u64) as $int_type } } #[inline] pub(crate) fn fetch_not(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_not(self.v.get().cast::()) as $int_type } } #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { // SAFETY: any data races are prevented by the kernel user helper or the lock // and the raw pointer passed in is valid because we got it from a reference. unsafe { atomic_neg(self.v.get().cast::()) as $int_type } } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; } atomic64!(AtomicI64, i64, atomic_max, atomic_min); atomic64!(AtomicU64, u64, atomic_umax, atomic_umin); #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[cfg(test)] mod tests { use super::*; #[test] fn kuser_helper_version() { let version = __kuser_helper_version(); assert!(version >= 5, "{:?}", version); assert_eq!(version, unsafe { (KUSER_HELPER_VERSION as *const i32).read() }); } test_atomic_int!(i64); test_atomic_int!(u64); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. stress_test!(u64); } portable-atomic/src/imp/mod.rs0000644000175000017500000004020414661133735017324 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // ----------------------------------------------------------------------------- // Lock-free implementations #[cfg(not(any( all( portable_atomic_no_atomic_load_store, not(all(target_arch = "bpf", not(feature = "critical-section"))), ), portable_atomic_unsafe_assume_single_core, target_arch = "avr", target_arch = "msp430", )))] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(all( any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"), portable_atomic_no_atomic_cas, ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(all( any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"), not(target_has_atomic = "ptr"), ))) )] mod core_atomic; // aarch64 128-bit atomics #[cfg(all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr( all(any(miri, portable_atomic_sanitize_thread), portable_atomic_new_atomic_intrinsics), path = "atomic128/intrinsics.rs" )] #[cfg_attr( not(all(any(miri, portable_atomic_sanitize_thread), portable_atomic_new_atomic_intrinsics)), path = "atomic128/aarch64.rs" )] mod aarch64; // x86_64 128-bit atomics #[cfg(all( target_arch = "x86_64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_cmpxchg16b_target_feature), not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "atomic128/intrinsics.rs")] #[cfg_attr(not(any(miri, portable_atomic_sanitize_thread)), path = "atomic128/x86_64.rs")] mod x86_64; // powerpc64 128-bit atomics #[cfg(all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), any(test, portable_atomic_outline_atomics), // TODO(powerpc64): currently disabled by default any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr( all(any(miri, portable_atomic_sanitize_thread), portable_atomic_llvm_15), path = "atomic128/intrinsics.rs" )] #[cfg_attr( not(all(any(miri, portable_atomic_sanitize_thread), portable_atomic_llvm_15)), path = "atomic128/powerpc64.rs" )] mod powerpc64; // s390x 128-bit atomics #[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))] // Use intrinsics.rs on Miri and Sanitizer that do not support inline assembly. #[cfg_attr(any(miri, portable_atomic_sanitize_thread), path = "atomic128/intrinsics.rs")] #[cfg_attr(not(any(miri, portable_atomic_sanitize_thread)), path = "atomic128/s390x.rs")] mod s390x; // pre-v6 ARM Linux 64-bit atomics #[cfg(feature = "fallback")] // Miri and Sanitizer do not support inline assembly. #[cfg(all( target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))] mod arm_linux; // MSP430 atomics #[cfg(target_arch = "msp430")] pub(crate) mod msp430; // atomic load/store for RISC-V without A-extension #[cfg(any(test, not(feature = "critical-section")))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any(test, not(target_has_atomic = "ptr"))) )] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] mod riscv; // x86-specific optimizations // Miri and Sanitizer do not support inline assembly. #[cfg(all( any(target_arch = "x86", target_arch = "x86_64"), not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), ))] mod x86; // ----------------------------------------------------------------------------- // Lock-based fallback implementations #[cfg(feature = "fallback")] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] #[cfg(any( test, not(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all( target_arch = "x86_64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ), ), all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch), )) ))] mod fallback; // ----------------------------------------------------------------------------- // Critical section based fallback implementations // On AVR, we always use critical section based fallback implementation. // AVR can be safely assumed to be single-core, so this is sound. // https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp#L1074 // MSP430 as well. #[cfg(any( all(test, target_os = "none"), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_cas)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any(test, not(target_has_atomic = "ptr"))) )] #[cfg(any( target_arch = "arm", target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", target_arch = "xtensa", feature = "critical-section", ))] mod interrupt; // ----------------------------------------------------------------------------- // Atomic float implementations #[cfg(feature = "float")] pub(crate) mod float; // ----------------------------------------------------------------------------- #[cfg(not(any( portable_atomic_no_atomic_load_store, portable_atomic_unsafe_assume_single_core, target_arch = "avr", target_arch = "msp430", )))] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(all( any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"), portable_atomic_no_atomic_cas, ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(all( any(target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section"), not(target_has_atomic = "ptr"), ))) )] items! { pub(crate) use self::core_atomic::{ AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, }; #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( not(portable_atomic_no_atomic_64), not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] pub(crate) use self::core_atomic::{AtomicI64, AtomicU64}; } // bpf #[cfg(all( target_arch = "bpf", portable_atomic_no_atomic_load_store, not(feature = "critical-section"), ))] pub(crate) use self::core_atomic::{AtomicI64, AtomicIsize, AtomicPtr, AtomicU64, AtomicUsize}; // RISC-V without A-extension & !(assume single core | critical section) #[cfg(not(any(portable_atomic_unsafe_assume_single_core, feature = "critical-section")))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))] #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] items! { pub(crate) use self::riscv::{ AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU32, AtomicU8, AtomicUsize, }; #[cfg(target_arch = "riscv64")] pub(crate) use self::riscv::{AtomicI64, AtomicU64}; } // no core atomic CAS & (assume single core | critical section) => critical section based fallback #[cfg(any( portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_cas))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "ptr")))] items! { pub(crate) use self::interrupt::{ AtomicI16, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16, AtomicU8, AtomicUsize, }; #[cfg(any(not(target_pointer_width = "16"), feature = "fallback"))] pub(crate) use self::interrupt::{AtomicI32, AtomicU32}; #[cfg(any( not(any(target_pointer_width = "16", target_pointer_width = "32")), feature = "fallback", ))] pub(crate) use self::interrupt::{AtomicI64, AtomicU64}; #[cfg(feature = "fallback")] pub(crate) use self::interrupt::{AtomicI128, AtomicU128}; } // no core (64-bit | 128-bit) atomic & has CAS => use lock-base fallback #[cfg(feature = "fallback")] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(not(portable_atomic_no_atomic_cas)))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(target_has_atomic = "ptr"))] items! { #[cfg(not(all( target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), )))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))] pub(crate) use self::fallback::{AtomicI64, AtomicU64}; #[cfg(not(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all( target_arch = "x86_64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_cmpxchg16b_target_feature), not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), portable_atomic_outline_atomics, // TODO(powerpc64): currently disabled by default any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ), all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch), )))] pub(crate) use self::fallback::{AtomicI128, AtomicU128}; } // 64-bit atomics (platform-specific) // pre-v6 ARM Linux #[cfg(feature = "fallback")] #[cfg(all( target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), ))] #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(portable_atomic_no_atomic_64))] #[cfg_attr(not(portable_atomic_no_cfg_target_has_atomic), cfg(not(target_has_atomic = "64")))] pub(crate) use self::arm_linux::{AtomicI64, AtomicU64}; // 128-bit atomics (platform-specific) // aarch64 #[cfg(all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ))] pub(crate) use self::aarch64::{AtomicI128, AtomicU128}; // x86_64 & (cmpxchg16b | outline-atomics) #[cfg(all( target_arch = "x86_64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_cmpxchg16b_target_feature), not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ))] pub(crate) use self::x86_64::{AtomicI128, AtomicU128}; // powerpc64 & (pwr8 | outline-atomics) #[cfg(all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), portable_atomic_outline_atomics, // TODO(powerpc64): currently disabled by default any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ))] pub(crate) use self::powerpc64::{AtomicI128, AtomicU128}; // s390x #[cfg(all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch))] pub(crate) use self::s390x::{AtomicI128, AtomicU128}; portable-atomic/src/imp/riscv.rs0000644000175000017500000010151314661133735017674 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Atomic load/store implementation on RISC-V. // // This is for RISC-V targets without atomic CAS. (rustc doesn't provide atomics // at all on such targets. https://github.com/rust-lang/rust/pull/114499) // // Also, optionally provides RMW implementation when force-amo is enabled. // // Refs: // - RISC-V Instruction Set Manual Volume I: Unprivileged ISA // https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf // - RISC-V Atomics ABI Specification // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/HEAD/riscv-atomic.adoc // - "Mappings from C/C++ primitives to RISC-V primitives." table in RISC-V Instruction Set Manual: // https://five-embeddev.com/riscv-isa-manual/latest/memory.html#sec:memory:porting // - atomic-maybe-uninit https://github.com/taiki-e/atomic-maybe-uninit // // Generated asm: // - riscv64gc https://godbolt.org/z/EETebx7TE // - riscv32imac https://godbolt.org/z/8zzv73bKh #[cfg(not(portable_atomic_no_asm))] use core::arch::asm; use core::{cell::UnsafeCell, sync::atomic::Ordering}; #[cfg(any(test, portable_atomic_force_amo))] macro_rules! atomic_rmw_amo_order { ($op:ident, $order:ident) => { match $order { Ordering::Relaxed => $op!(""), Ordering::Acquire => $op!(".aq"), Ordering::Release => $op!(".rl"), // AcqRel and SeqCst RMWs are equivalent. Ordering::AcqRel | Ordering::SeqCst => $op!(".aqrl"), _ => unreachable!("{:?}", $order), } }; } #[cfg(any(test, portable_atomic_force_amo))] macro_rules! atomic_rmw_amo { ($op:ident, $dst:ident, $val:ident, $order:ident, $asm_suffix:tt) => {{ let out; macro_rules! op { ($asm_order:tt) => { // SAFETY: The user guaranteed that the AMO instruction is available in this // system by setting the portable_atomic_force_amo and // portable_atomic_unsafe_assume_single_core. // The caller of this macro must guarantee the validity of the pointer. asm!( ".option push", // https://github.com/riscv-non-isa/riscv-asm-manual/blob/HEAD/riscv-asm.md#arch ".option arch, +a", concat!("amo", stringify!($op), ".", $asm_suffix, $asm_order, " {out}, {val}, 0({dst})"), ".option pop", dst = in(reg) ptr_reg!($dst), val = in(reg) $val, out = lateout(reg) out, options(nostack, preserves_flags), ) }; } atomic_rmw_amo_order!(op, $order); out }}; } // 32-bit val.wrapping_shl(shift) but no extra `& (u32::BITS - 1)` #[cfg(any(test, portable_atomic_force_amo))] #[inline] fn sllw(val: u32, shift: u32) -> u32 { // SAFETY: Calling sll{,w} is safe. unsafe { let out; #[cfg(target_arch = "riscv32")] asm!("sll {out}, {val}, {shift}", out = lateout(reg) out, val = in(reg) val, shift = in(reg) shift, options(pure, nomem, nostack, preserves_flags)); #[cfg(target_arch = "riscv64")] asm!("sllw {out}, {val}, {shift}", out = lateout(reg) out, val = in(reg) val, shift = in(reg) shift, options(pure, nomem, nostack, preserves_flags)); out } } // 32-bit val.wrapping_shr(shift) but no extra `& (u32::BITS - 1)` #[cfg(any(test, portable_atomic_force_amo))] #[inline] fn srlw(val: u32, shift: u32) -> u32 { // SAFETY: Calling srl{,w} is safe. unsafe { let out; #[cfg(target_arch = "riscv32")] asm!("srl {out}, {val}, {shift}", out = lateout(reg) out, val = in(reg) val, shift = in(reg) shift, options(pure, nomem, nostack, preserves_flags)); #[cfg(target_arch = "riscv64")] asm!("srlw {out}, {val}, {shift}", out = lateout(reg) out, val = in(reg) val, shift = in(reg) shift, options(pure, nomem, nostack, preserves_flags)); out } } macro_rules! atomic_load_store { ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty, $asm_suffix:tt) => { #[repr(transparent)] pub(crate) struct $atomic_type $(<$($generics)*>)? { v: UnsafeCell<$value_type>, } // Send is implicitly implemented for atomic integers, but not for atomic pointers. // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Send for $atomic_type $(<$($generics)*>)? {} // SAFETY: any data races are prevented by atomic operations. unsafe impl $(<$($generics)*>)? Sync for $atomic_type $(<$($generics)*>)? {} #[cfg(any(test, not(portable_atomic_unsafe_assume_single_core)))] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) const fn new(v: $value_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::is_always_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { true } #[inline] pub(crate) fn get_mut(&mut self) -> &mut $value_type { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.v.get() } } #[inline] pub(crate) fn into_inner(self) -> $value_type { self.v.into_inner() } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $value_type { self.v.get() } } impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $value_type { crate::utils::assert_load_ordering(order); let src = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { let out; match order { Ordering::Relaxed => { asm!( concat!("l", $asm_suffix, " {out}, 0({src})"), src = in(reg) ptr_reg!(src), out = lateout(reg) out, options(nostack, preserves_flags, readonly), ); } Ordering::Acquire => { asm!( concat!("l", $asm_suffix, " {out}, 0({src})"), "fence r, rw", src = in(reg) ptr_reg!(src), out = lateout(reg) out, options(nostack, preserves_flags), ); } Ordering::SeqCst => { asm!( "fence rw, rw", concat!("l", $asm_suffix, " {out}, 0({src})"), "fence r, rw", src = in(reg) ptr_reg!(src), out = lateout(reg) out, options(nostack, preserves_flags), ); } _ => unreachable!("{:?}", order), } out } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $value_type, order: Ordering) { crate::utils::assert_store_ordering(order); let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { match order { Ordering::Relaxed => { asm!( concat!("s", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) ptr_reg!(dst), val = in(reg) val, options(nostack, preserves_flags), ); } // Release and SeqCst stores are equivalent. Ordering::Release | Ordering::SeqCst => { asm!( "fence rw, w", concat!("s", $asm_suffix, " {val}, 0({dst})"), dst = in(reg) ptr_reg!(dst), val = in(reg) val, options(nostack, preserves_flags), ); } _ => unreachable!("{:?}", order), } } } } }; } macro_rules! atomic_ptr { ($([$($generics:tt)*])? $atomic_type:ident, $value_type:ty, $asm_suffix:tt) => { atomic_load_store!($([$($generics)*])? $atomic_type, $value_type, $asm_suffix); #[cfg(portable_atomic_force_amo)] impl $(<$($generics)*>)? $atomic_type $(<$($generics)*>)? { #[inline] pub(crate) fn swap(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(swap, dst, val, order, $asm_suffix) } } } }; } macro_rules! atomic { ($atomic_type:ident, $value_type:ty, $asm_suffix:tt, $max:tt, $min:tt) => { atomic_load_store!($atomic_type, $value_type, $asm_suffix); // There is no amo{sub,nand,neg}. #[cfg(any(test, portable_atomic_force_amo))] impl $atomic_type { #[inline] pub(crate) fn swap(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(swap, dst, val, order, $asm_suffix) } } #[inline] pub(crate) fn fetch_add(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(add, dst, val, order, $asm_suffix) } } #[inline] pub(crate) fn fetch_sub(&self, val: $value_type, order: Ordering) -> $value_type { self.fetch_add(val.wrapping_neg(), order) } #[inline] pub(crate) fn fetch_and(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(and, dst, val, order, $asm_suffix) } } #[inline] pub(crate) fn fetch_or(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(or, dst, val, order, $asm_suffix) } } #[inline] pub(crate) fn fetch_xor(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!(xor, dst, val, order, $asm_suffix) } } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $value_type { self.fetch_xor(!0, order) } #[inline] pub(crate) fn fetch_max(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!($max, dst, val, order, $asm_suffix) } } #[inline] pub(crate) fn fetch_min(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. unsafe { atomic_rmw_amo!($min, dst, val, order, $asm_suffix) } } } }; } macro_rules! atomic_sub_word { ($atomic_type:ident, $value_type:ty, $unsigned_type:ty, $asm_suffix:tt) => { atomic_load_store!($atomic_type, $value_type, $asm_suffix); #[cfg(any(test, portable_atomic_force_amo))] impl $atomic_type { #[inline] pub(crate) fn fetch_and(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); let (dst, shift, mask) = crate::utils::create_sub_word_mask_values(dst); let mask = !sllw(mask as u32, shift as u32); // TODO: use zero_extend helper instead of cast for val. let val = sllw(val as $unsigned_type as u32, shift as u32); let val = val | mask; // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. let out: u32 = unsafe { atomic_rmw_amo!(and, dst, val, order, "w") }; srlw(out, shift as u32) as $unsigned_type as $value_type } #[inline] pub(crate) fn fetch_or(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); let (dst, shift, _mask) = crate::utils::create_sub_word_mask_values(dst); // TODO: use zero_extend helper instead of cast for val. let val = sllw(val as $unsigned_type as u32, shift as u32); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. let out: u32 = unsafe { atomic_rmw_amo!(or, dst, val, order, "w") }; srlw(out, shift as u32) as $unsigned_type as $value_type } #[inline] pub(crate) fn fetch_xor(&self, val: $value_type, order: Ordering) -> $value_type { let dst = self.v.get(); let (dst, shift, _mask) = crate::utils::create_sub_word_mask_values(dst); // TODO: use zero_extend helper instead of cast for val. let val = sllw(val as $unsigned_type as u32, shift as u32); // SAFETY: any data races are prevented by atomic intrinsics and the raw // pointer passed in is valid because we got it from a reference. let out: u32 = unsafe { atomic_rmw_amo!(xor, dst, val, order, "w") }; srlw(out, shift as u32) as $unsigned_type as $value_type } #[inline] pub(crate) fn fetch_not(&self, order: Ordering) -> $value_type { self.fetch_xor(!0, order) } } }; } atomic_sub_word!(AtomicI8, i8, u8, "b"); atomic_sub_word!(AtomicU8, u8, u8, "b"); atomic_sub_word!(AtomicI16, i16, u16, "h"); atomic_sub_word!(AtomicU16, u16, u16, "h"); atomic!(AtomicI32, i32, "w", max, min); atomic!(AtomicU32, u32, "w", maxu, minu); #[cfg(target_arch = "riscv64")] atomic!(AtomicI64, i64, "d", max, min); #[cfg(target_arch = "riscv64")] atomic!(AtomicU64, u64, "d", maxu, minu); #[cfg(target_pointer_width = "32")] atomic!(AtomicIsize, isize, "w", max, min); #[cfg(target_pointer_width = "32")] atomic!(AtomicUsize, usize, "w", maxu, minu); #[cfg(target_pointer_width = "32")] atomic_ptr!([T] AtomicPtr, *mut T, "w"); #[cfg(target_pointer_width = "64")] atomic!(AtomicIsize, isize, "d", max, min); #[cfg(target_pointer_width = "64")] atomic!(AtomicUsize, usize, "d", maxu, minu); #[cfg(target_pointer_width = "64")] atomic_ptr!([T] AtomicPtr, *mut T, "d"); #[cfg(test)] mod tests { use super::*; test_atomic_ptr_load_store!(); test_atomic_int_load_store!(i8); test_atomic_int_load_store!(u8); test_atomic_int_load_store!(i16); test_atomic_int_load_store!(u16); test_atomic_int_load_store!(i32); test_atomic_int_load_store!(u32); #[cfg(target_arch = "riscv64")] test_atomic_int_load_store!(i64); #[cfg(target_arch = "riscv64")] test_atomic_int_load_store!(u64); test_atomic_int_load_store!(isize); test_atomic_int_load_store!(usize); macro_rules! test_atomic_int_amo { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; test_atomic_int_amo!([], $int_type); } } }; ($atomic_type:ty, $int_type:ident) => { ::quickcheck::quickcheck! { fn quickcheck_swap(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.swap(y, order), x); assert_eq!(a.swap(x, order), y); } true } fn quickcheck_fetch_add(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_add(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_add(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_add(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_add(x)); } true } fn quickcheck_fetch_sub(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_sub(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_sub(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_sub(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_sub(x)); } true } fn quickcheck_fetch_and(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_and(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x & y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_and(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y & x); } true } fn quickcheck_fetch_or(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_or(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x | y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_or(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y | x); } true } fn quickcheck_fetch_xor(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_xor(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x ^ y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_xor(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y ^ x); } true } fn quickcheck_fetch_max(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_max(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_max(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(y, x)); } true } fn quickcheck_fetch_min(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_min(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_min(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(y, x)); } true } fn quickcheck_fetch_not(x: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_not(order), x); assert_eq!(a.load(Ordering::Relaxed), !x); assert_eq!(a.fetch_not(order), !x); assert_eq!(a.load(Ordering::Relaxed), x); } true } } }; } macro_rules! test_atomic_int_amo_sub_word { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; test_atomic_int_amo_sub_word!([], $int_type); } } }; ($atomic_type:ty, $int_type:ident) => { use crate::tests::helper::*; ::quickcheck::quickcheck! { fn quickcheck_fetch_and(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_and(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x & y); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } arr.0[a_idx] = <$atomic_type>::new(y); let a = &arr.0[a_idx]; assert_eq!(a.fetch_and(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y & x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } fn quickcheck_fetch_or(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_or(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x | y); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } arr.0[a_idx] = <$atomic_type>::new(y); let a = &arr.0[a_idx]; assert_eq!(a.fetch_or(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y | x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } fn quickcheck_fetch_xor(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_xor(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x ^ y); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } arr.0[a_idx] = <$atomic_type>::new(y); let a = &arr.0[a_idx]; assert_eq!(a.fetch_xor(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y ^ x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } fn quickcheck_fetch_not(x: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { for base in [0, !0] { let mut arr = Align16([ <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), <$atomic_type>::new(base), ]); let a_idx = fastrand::usize(3..=6); arr.0[a_idx] = <$atomic_type>::new(x); let a = &arr.0[a_idx]; assert_eq!(a.fetch_not(order), x); assert_eq!(a.load(Ordering::Relaxed), !x); assert_eq!(a.fetch_not(order), !x); assert_eq!(a.load(Ordering::Relaxed), x); for i in 0..a_idx { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } for i in a_idx + 1..arr.0.len() { assert_eq!(arr.0[i].load(Ordering::Relaxed), base, "invalid value written"); } } } true } } }; } test_atomic_int_amo_sub_word!(i8); test_atomic_int_amo_sub_word!(u8); test_atomic_int_amo_sub_word!(i16); test_atomic_int_amo_sub_word!(u16); test_atomic_int_amo!(i32); test_atomic_int_amo!(u32); #[cfg(target_arch = "riscv64")] test_atomic_int_amo!(i64); #[cfg(target_arch = "riscv64")] test_atomic_int_amo!(u64); test_atomic_int_amo!(isize); test_atomic_int_amo!(usize); } portable-atomic/src/imp/fallback/0000775000175000017500000000000014661133735017740 5ustar jamespagejamespageportable-atomic/src/imp/fallback/seq_lock_wide.rs0000644000175000017500000001425714661133735023125 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/seq_lock_wide.rs. use core::{ mem::ManuallyDrop, sync::atomic::{self, AtomicUsize, Ordering}, }; use super::utils::Backoff; // See mod.rs for details. pub(super) type AtomicChunk = AtomicUsize; pub(super) type Chunk = usize; /// A simple stamped lock. /// /// The state is represented as two `AtomicUsize`: `state_hi` for high bits and `state_lo` for low /// bits. pub(super) struct SeqLock { /// The high bits of the current state of the lock. state_hi: AtomicUsize, /// The low bits of the current state of the lock. /// /// All bits except the least significant one hold the current stamp. When locked, the state_lo /// equals 1 and doesn't contain a valid stamp. state_lo: AtomicUsize, } impl SeqLock { #[inline] pub(super) const fn new() -> Self { Self { state_hi: AtomicUsize::new(0), state_lo: AtomicUsize::new(0) } } /// If not locked, returns the current stamp. /// /// This method should be called before optimistic reads. #[inline] pub(super) fn optimistic_read(&self) -> Option<(usize, usize)> { // The acquire loads from `state_hi` and `state_lo` synchronize with the release stores in // `SeqLockWriteGuard::drop` and `SeqLockWriteGuard::abort`. // // As a consequence, we can make sure that (1) all writes within the era of `state_hi - 1` // happens before now; and therefore, (2) if `state_lo` is even, all writes within the // critical section of (`state_hi`, `state_lo`) happens before now. let state_hi = self.state_hi.load(Ordering::Acquire); let state_lo = self.state_lo.load(Ordering::Acquire); if state_lo == 1 { None } else { Some((state_hi, state_lo)) } } /// Returns `true` if the current stamp is equal to `stamp`. /// /// This method should be called after optimistic reads to check whether they are valid. The /// argument `stamp` should correspond to the one returned by method `optimistic_read`. #[inline] pub(super) fn validate_read(&self, stamp: (usize, usize)) -> bool { // Thanks to the fence, if we're noticing any modification to the data at the critical // section of `(stamp.0, stamp.1)`, then the critical section's write of 1 to state_lo should be // visible. atomic::fence(Ordering::Acquire); // So if `state_lo` coincides with `stamp.1`, then either (1) we're noticing no modification // to the data after the critical section of `(stamp.0, stamp.1)`, or (2) `state_lo` wrapped // around. // // If (2) is the case, the acquire ordering ensures we see the new value of `state_hi`. let state_lo = self.state_lo.load(Ordering::Acquire); // If (2) is the case and `state_hi` coincides with `stamp.0`, then `state_hi` also wrapped // around, which we give up to correctly validate the read. let state_hi = self.state_hi.load(Ordering::Relaxed); // Except for the case that both `state_hi` and `state_lo` wrapped around, the following // condition implies that we're noticing no modification to the data after the critical // section of `(stamp.0, stamp.1)`. (state_hi, state_lo) == stamp } /// Grabs the lock for writing. #[inline] pub(super) fn write(&self) -> SeqLockWriteGuard<'_> { let mut backoff = Backoff::new(); loop { let previous = self.state_lo.swap(1, Ordering::Acquire); if previous != 1 { // To synchronize with the acquire fence in `validate_read` via any modification to // the data at the critical section of `(state_hi, previous)`. atomic::fence(Ordering::Release); return SeqLockWriteGuard { lock: self, state_lo: previous }; } while self.state_lo.load(Ordering::Relaxed) == 1 { backoff.snooze(); } } } } /// An RAII guard that releases the lock and increments the stamp when dropped. #[must_use] pub(super) struct SeqLockWriteGuard<'a> { /// The parent lock. lock: &'a SeqLock, /// The stamp before locking. state_lo: usize, } impl SeqLockWriteGuard<'_> { /// Releases the lock without incrementing the stamp. #[inline] pub(super) fn abort(self) { // We specifically don't want to call drop(), since that's // what increments the stamp. let this = ManuallyDrop::new(self); // Restore the stamp. // // Release ordering for synchronizing with `optimistic_read`. this.lock.state_lo.store(this.state_lo, Ordering::Release); } } impl Drop for SeqLockWriteGuard<'_> { #[inline] fn drop(&mut self) { let state_lo = self.state_lo.wrapping_add(2); // Increase the high bits if the low bits wrap around. // // Release ordering for synchronizing with `optimistic_read`. if state_lo == 0 { let state_hi = self.lock.state_hi.load(Ordering::Relaxed); self.lock.state_hi.store(state_hi.wrapping_add(1), Ordering::Release); } // Release the lock and increment the stamp. // // Release ordering for synchronizing with `optimistic_read`. self.lock.state_lo.store(state_lo, Ordering::Release); } } #[cfg(test)] mod tests { use super::SeqLock; #[test] fn smoke() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); assert!(lock.validate_read(before)); { let _guard = lock.write(); } assert!(!lock.validate_read(before)); let after = lock.optimistic_read().unwrap(); assert_ne!(before, after); } #[test] fn test_abort() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); { let guard = lock.write(); guard.abort(); } let after = lock.optimistic_read().unwrap(); assert_eq!(before, after, "aborted write does not update the stamp"); } } portable-atomic/src/imp/fallback/utils.rs0000644000175000017500000001223414661133735021446 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT use core::ops; // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/9384f1eb2b356364e201ad38545e03c837d55f3a/crossbeam-utils/src/cache_padded.rs. /// Pads and aligns a value to the length of a cache line. // Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache // lines at a time, so we have to align to 128 bytes rather than 64. // // Sources: // - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf // - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107 // // ARM's big.LITTLE architecture has asymmetric cores and "big" cores have 128-byte cache line size. // // Sources: // - https://www.mono-project.com/news/2016/09/12/arm64-icache/ // // powerpc64 has 128-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/powerpc/include/asm/cache.h#L26 #[cfg_attr( any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64"), repr(align(128)) )] // arm, mips, mips64, sparc, and hexagon have 32-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L17 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/hexagon/include/asm/cache.h#L12 #[cfg_attr( any( target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "sparc", target_arch = "hexagon", ), repr(align(32)) )] // m68k has 16-byte cache line size. // // Sources: // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/m68k/include/asm/cache.h#L9 #[cfg_attr(target_arch = "m68k", repr(align(16)))] // s390x has 256-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/s390/include/asm/cache.h#L13 #[cfg_attr(target_arch = "s390x", repr(align(256)))] // x86, wasm, riscv, and sparc64 have 64-byte cache line size. // // Sources: // - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/riscv/include/asm/cache.h#L10 // - https://github.com/torvalds/linux/blob/3516bd729358a2a9b090c1905bd2a3fa926e24c6/arch/sparc/include/asm/cache.h#L19 // // All others are assumed to have 64-byte cache line size. #[cfg_attr( not(any( target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64", target_arch = "arm", target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6", target_arch = "sparc", target_arch = "hexagon", target_arch = "m68k", target_arch = "s390x", )), repr(align(64)) )] pub(crate) struct CachePadded { value: T, } impl CachePadded { #[inline] pub(crate) const fn new(value: T) -> Self { Self { value } } } impl ops::Deref for CachePadded { type Target = T; #[inline] fn deref(&self) -> &Self::Target { &self.value } } // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/backoff.rs. // Adjusted to reduce spinning. /// Performs exponential backoff in spin loops. pub(crate) struct Backoff { step: u32, } // https://github.com/oneapi-src/oneTBB/blob/v2021.5.0/include/oneapi/tbb/detail/_utils.h#L46-L48 const SPIN_LIMIT: u32 = 4; impl Backoff { #[inline] pub(crate) const fn new() -> Self { Self { step: 0 } } #[inline] pub(crate) fn snooze(&mut self) { if self.step <= SPIN_LIMIT { for _ in 0..1 << self.step { #[allow(deprecated)] core::sync::atomic::spin_loop_hint(); } self.step += 1; } else { #[cfg(not(feature = "std"))] for _ in 0..1 << self.step { #[allow(deprecated)] core::sync::atomic::spin_loop_hint(); } #[cfg(feature = "std")] std::thread::yield_now(); } } } portable-atomic/src/imp/fallback/outline_atomics.rs0000644000175000017500000001472314661133735023511 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Helper for outline-atomics. // // On architectures where DW atomics are not supported on older CPUs, we use // fallback implementation when DW atomic instructions are not supported and // outline-atomics is enabled. // // This module provides helpers to implement them. use core::sync::atomic::Ordering; #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))] pub(crate) type Udw = u128; #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))] pub(crate) type AtomicUdw = super::super::fallback::AtomicU128; #[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))] pub(crate) type AtomicIdw = super::super::fallback::AtomicI128; #[cfg(target_arch = "arm")] pub(crate) type Udw = u64; #[cfg(target_arch = "arm")] pub(crate) type AtomicUdw = super::super::fallback::AtomicU64; #[cfg(target_arch = "arm")] pub(crate) type AtomicIdw = super::super::fallback::AtomicI64; // Asserts that the function is called in the correct context. macro_rules! debug_assert_outline_atomics { () => { #[cfg(target_arch = "x86_64")] { debug_assert!(!super::detect::detect().has_cmpxchg16b()); } #[cfg(target_arch = "powerpc64")] { debug_assert!(!super::detect::detect().has_quadword_atomics()); } #[cfg(target_arch = "arm")] { debug_assert!(!super::has_kuser_cmpxchg64()); } }; } #[cold] pub(crate) unsafe fn atomic_load(src: *mut Udw, order: Ordering) -> Udw { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { (*(src as *const AtomicUdw)).load(order) } } fn_alias! { #[cold] pub(crate) unsafe fn(src: *mut Udw) -> Udw; // fallback's atomic load has at least acquire semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] atomic_load_non_seqcst = atomic_load(Ordering::Acquire); atomic_load_seqcst = atomic_load(Ordering::SeqCst); } #[cold] pub(crate) unsafe fn atomic_store(dst: *mut Udw, val: Udw, order: Ordering) { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { (*(dst as *const AtomicUdw)).store(val, order); } } fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw, val: Udw); // fallback's atomic store has at least release semantics. #[cfg(not(target_arch = "arm"))] atomic_store_non_seqcst = atomic_store(Ordering::Release); atomic_store_seqcst = atomic_store(Ordering::SeqCst); } #[cold] pub(crate) unsafe fn atomic_compare_exchange( dst: *mut Udw, old: Udw, new: Udw, success: Ordering, failure: Ordering, ) -> (Udw, bool) { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { match (*(dst as *const AtomicUdw)).compare_exchange(old, new, success, failure) { Ok(v) => (v, true), Err(v) => (v, false), } } } fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw, old: Udw, new: Udw) -> (Udw, bool); // fallback's atomic CAS has at least AcqRel semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] atomic_compare_exchange_non_seqcst = atomic_compare_exchange(Ordering::AcqRel, Ordering::Acquire); atomic_compare_exchange_seqcst = atomic_compare_exchange(Ordering::SeqCst, Ordering::SeqCst); } macro_rules! atomic_rmw_3 { ( $name:ident($atomic_type:ident::$method_name:ident), $non_seqcst_alias:ident, $seqcst_alias:ident ) => { #[cold] pub(crate) unsafe fn $name(dst: *mut Udw, val: Udw, order: Ordering) -> Udw { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { (*(dst as *const $atomic_type)).$method_name(val as _, order) as Udw } } fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw, val: Udw) -> Udw; // fallback's atomic RMW has at least AcqRel semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] $non_seqcst_alias = $name(Ordering::AcqRel); $seqcst_alias = $name(Ordering::SeqCst); } }; } macro_rules! atomic_rmw_2 { ( $name:ident($atomic_type:ident::$method_name:ident), $non_seqcst_alias:ident, $seqcst_alias:ident ) => { #[cold] pub(crate) unsafe fn $name(dst: *mut Udw, order: Ordering) -> Udw { debug_assert_outline_atomics!(); #[allow(clippy::cast_ptr_alignment)] // SAFETY: the caller must uphold the safety contract. unsafe { (*(dst as *const $atomic_type)).$method_name(order) as Udw } } fn_alias! { #[cold] pub(crate) unsafe fn(dst: *mut Udw) -> Udw; // fallback's atomic RMW has at least AcqRel semantics. #[cfg(not(any(target_arch = "arm", target_arch = "x86_64")))] $non_seqcst_alias = $name(Ordering::AcqRel); $seqcst_alias = $name(Ordering::SeqCst); } }; } atomic_rmw_3!(atomic_swap(AtomicUdw::swap), atomic_swap_non_seqcst, atomic_swap_seqcst); atomic_rmw_3!(atomic_add(AtomicUdw::fetch_add), atomic_add_non_seqcst, atomic_add_seqcst); atomic_rmw_3!(atomic_sub(AtomicUdw::fetch_sub), atomic_sub_non_seqcst, atomic_sub_seqcst); atomic_rmw_3!(atomic_and(AtomicUdw::fetch_and), atomic_and_non_seqcst, atomic_and_seqcst); atomic_rmw_3!(atomic_nand(AtomicUdw::fetch_nand), atomic_nand_non_seqcst, atomic_nand_seqcst); atomic_rmw_3!(atomic_or(AtomicUdw::fetch_or), atomic_or_non_seqcst, atomic_or_seqcst); atomic_rmw_3!(atomic_xor(AtomicUdw::fetch_xor), atomic_xor_non_seqcst, atomic_xor_seqcst); atomic_rmw_3!(atomic_max(AtomicIdw::fetch_max), atomic_max_non_seqcst, atomic_max_seqcst); atomic_rmw_3!(atomic_umax(AtomicUdw::fetch_max), atomic_umax_non_seqcst, atomic_umax_seqcst); atomic_rmw_3!(atomic_min(AtomicIdw::fetch_min), atomic_min_non_seqcst, atomic_min_seqcst); atomic_rmw_3!(atomic_umin(AtomicUdw::fetch_min), atomic_umin_non_seqcst, atomic_umin_seqcst); atomic_rmw_2!(atomic_not(AtomicUdw::fetch_not), atomic_not_non_seqcst, atomic_not_seqcst); atomic_rmw_2!(atomic_neg(AtomicUdw::fetch_neg), atomic_neg_non_seqcst, atomic_neg_seqcst); portable-atomic/src/imp/fallback/mod.rs0000644000175000017500000004000214661133735021057 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Fallback implementation using global locks. // // This implementation uses seqlock for global locks. // // This is basically based on global locks in crossbeam-utils's `AtomicCell`, // but seqlock is implemented in a way that does not depend on UB // (see comments in optimistic_read method in atomic! macro for details). // // Note that we cannot use a lock per atomic type, since the in-memory representation of the atomic // type and the value type must be the same. #![cfg_attr( any( all( target_arch = "x86_64", not(portable_atomic_no_cmpxchg16b_target_feature), not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), all( target_arch = "powerpc64", feature = "fallback", not(portable_atomic_no_outline_atomics), portable_atomic_outline_atomics, // TODO(powerpc64): currently disabled by default any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ), not(any(miri, portable_atomic_sanitize_thread)), ), all( target_arch = "arm", not(portable_atomic_no_asm), any(target_os = "linux", target_os = "android"), not(portable_atomic_no_outline_atomics), ), ), allow(dead_code) )] #[macro_use] pub(crate) mod utils; // Use "wide" sequence lock if the pointer width <= 32 for preventing its counter against wrap // around. // // In narrow architectures (pointer width <= 16), the counter is still <= 32-bit and may be // vulnerable to wrap around. But it's mostly okay, since in such a primitive hardware, the // counter will not be increased that fast. // // Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI, // aarch64 ILP32 ABI, mips64 N32 ABI). On those targets, AtomicU64 is available and fast, // so use it to implement normal sequence lock. cfg_has_fast_atomic_64! { mod seq_lock; } cfg_no_fast_atomic_64! { #[path = "seq_lock_wide.rs"] mod seq_lock; } use core::{cell::UnsafeCell, mem, sync::atomic::Ordering}; use seq_lock::{SeqLock, SeqLockWriteGuard}; use utils::CachePadded; // Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI, // aarch64 ILP32 ABI, mips64 N32 ABI). On those targets, AtomicU64 is fast, // so use it to reduce chunks of byte-wise atomic memcpy. use seq_lock::{AtomicChunk, Chunk}; // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/atomic_cell.rs#L969-L1016. #[inline] #[must_use] fn lock(addr: usize) -> &'static SeqLock { // The number of locks is a prime number because we want to make sure `addr % LEN` gets // dispersed across all locks. // // crossbeam-utils 0.8.7 uses 97 here but does not use CachePadded, // so the actual concurrency level will be smaller. const LEN: usize = 67; #[allow(clippy::declare_interior_mutable_const)] const L: CachePadded = CachePadded::new(SeqLock::new()); static LOCKS: [CachePadded; LEN] = [ L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, ]; // If the modulus is a constant number, the compiler will use crazy math to transform this into // a sequence of cheap arithmetic operations rather than using the slow modulo instruction. &LOCKS[addr % LEN] } macro_rules! atomic { ($atomic_type:ident, $int_type:ident, $align:literal) => { #[repr(C, align($align))] pub(crate) struct $atomic_type { v: UnsafeCell<$int_type>, } impl $atomic_type { const LEN: usize = mem::size_of::<$int_type>() / mem::size_of::(); #[inline] unsafe fn chunks(&self) -> &[AtomicChunk; Self::LEN] { static_assert!($atomic_type::LEN > 1); static_assert!(mem::size_of::<$int_type>() % mem::size_of::() == 0); // SAFETY: the caller must uphold the safety contract for `chunks`. unsafe { &*(self.v.get() as *const $int_type as *const [AtomicChunk; Self::LEN]) } } #[inline] fn optimistic_read(&self) -> $int_type { // Using `MaybeUninit<[usize; Self::LEN]>` here doesn't change codegen: https://godbolt.org/z/86f8s733M let mut dst: [Chunk; Self::LEN] = [0; Self::LEN]; // SAFETY: // - There are no threads that perform non-atomic concurrent write operations. // - There is no writer that updates the value using atomic operations of different granularity. // // If the atomic operation is not used here, it will cause a data race // when `write` performs concurrent write operation. // Such a data race is sometimes considered virtually unproblematic // in SeqLock implementations: // // - https://github.com/Amanieu/seqlock/issues/2 // - https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/atomic_cell.rs#L1111-L1116 // - https://rust-lang.zulipchat.com/#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/avoiding.20UB.20due.20to.20races.20by.20discarding.20result.3F // // However, in our use case, the implementation that loads/stores value as // chunks of usize is enough fast and sound, so we use that implementation. // // See also atomic-memcpy crate, a generic implementation of this pattern: // https://github.com/taiki-e/atomic-memcpy let chunks = unsafe { self.chunks() }; for i in 0..Self::LEN { dst[i] = chunks[i].load(Ordering::Relaxed); } // SAFETY: integers are plain old data types so we can always transmute to them. unsafe { mem::transmute::<[Chunk; Self::LEN], $int_type>(dst) } } #[inline] fn read(&self, _guard: &SeqLockWriteGuard<'static>) -> $int_type { // This calls optimistic_read that can return teared value, but the resulting value // is guaranteed not to be teared because we hold the lock to write. self.optimistic_read() } #[inline] fn write(&self, val: $int_type, _guard: &SeqLockWriteGuard<'static>) { // SAFETY: integers are plain old data types so we can always transmute them to arrays of integers. let val = unsafe { mem::transmute::<$int_type, [Chunk; Self::LEN]>(val) }; // SAFETY: // - The guard guarantees that we hold the lock to write. // - There are no threads that perform non-atomic concurrent read or write operations. // // See optimistic_read for the reason that atomic operations are used here. let chunks = unsafe { self.chunks() }; for i in 0..Self::LEN { chunks[i].store(val[i], Ordering::Relaxed); } } } // Send is implicitly implemented. // SAFETY: any data races are prevented by the lock and atomic operation. unsafe impl Sync for $atomic_type {} impl_default_no_fetch_ops!($atomic_type, $int_type); impl_default_bit_opts!($atomic_type, $int_type); impl $atomic_type { #[inline] pub(crate) const fn new(v: $int_type) -> Self { Self { v: UnsafeCell::new(v) } } #[inline] pub(crate) fn is_lock_free() -> bool { Self::is_always_lock_free() } #[inline] pub(crate) const fn is_always_lock_free() -> bool { false } #[inline] pub(crate) fn get_mut(&mut self) -> &mut $int_type { // SAFETY: the mutable reference guarantees unique ownership. // (UnsafeCell::get_mut requires Rust 1.50) unsafe { &mut *self.v.get() } } #[inline] pub(crate) fn into_inner(self) -> $int_type { self.v.into_inner() } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn load(&self, order: Ordering) -> $int_type { crate::utils::assert_load_ordering(order); let lock = lock(self.v.get() as usize); // Try doing an optimistic read first. if let Some(stamp) = lock.optimistic_read() { let val = self.optimistic_read(); if lock.validate_read(stamp) { return val; } } // Grab a regular write lock so that writers don't starve this load. let guard = lock.write(); let val = self.read(&guard); // The value hasn't been changed. Drop the guard without incrementing the stamp. guard.abort(); val } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn store(&self, val: $int_type, order: Ordering) { crate::utils::assert_store_ordering(order); let guard = lock(self.v.get() as usize).write(); self.write(val, &guard) } #[inline] pub(crate) fn swap(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(val, &guard); prev } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { crate::utils::assert_compare_exchange_ordering(success, failure); let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); if prev == current { self.write(new, &guard); Ok(prev) } else { // The value hasn't been changed. Drop the guard without incrementing the stamp. guard.abort(); Err(prev) } } #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.compare_exchange(current, new, success, failure) } #[inline] pub(crate) fn fetch_add(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(prev.wrapping_add(val), &guard); prev } #[inline] pub(crate) fn fetch_sub(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(prev.wrapping_sub(val), &guard); prev } #[inline] pub(crate) fn fetch_and(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(prev & val, &guard); prev } #[inline] pub(crate) fn fetch_nand(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(!(prev & val), &guard); prev } #[inline] pub(crate) fn fetch_or(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(prev | val, &guard); prev } #[inline] pub(crate) fn fetch_xor(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(prev ^ val, &guard); prev } #[inline] pub(crate) fn fetch_max(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(core::cmp::max(prev, val), &guard); prev } #[inline] pub(crate) fn fetch_min(&self, val: $int_type, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(core::cmp::min(prev, val), &guard); prev } #[inline] pub(crate) fn fetch_not(&self, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(!prev, &guard); prev } #[inline] pub(crate) fn not(&self, order: Ordering) { self.fetch_not(order); } #[inline] pub(crate) fn fetch_neg(&self, _order: Ordering) -> $int_type { let guard = lock(self.v.get() as usize).write(); let prev = self.read(&guard); self.write(prev.wrapping_neg(), &guard); prev } #[inline] pub(crate) fn neg(&self, order: Ordering) { self.fetch_neg(order); } #[inline] pub(crate) const fn as_ptr(&self) -> *mut $int_type { self.v.get() } } }; } #[cfg_attr(portable_atomic_no_cfg_target_has_atomic, cfg(any(test, portable_atomic_no_atomic_64)))] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any(test, not(target_has_atomic = "64"))) )] cfg_no_fast_atomic_64! { atomic!(AtomicI64, i64, 8); atomic!(AtomicU64, u64, 8); } atomic!(AtomicI128, i128, 16); atomic!(AtomicU128, u128, 16); #[cfg(test)] mod tests { use super::*; cfg_no_fast_atomic_64! { test_atomic_int!(i64); test_atomic_int!(u64); } test_atomic_int!(i128); test_atomic_int!(u128); // load/store/swap implementation is not affected by signedness, so it is // enough to test only unsigned types. cfg_no_fast_atomic_64! { stress_test!(u64); } stress_test!(u128); } portable-atomic/src/imp/fallback/seq_lock.rs0000644000175000017500000001040614661133735022105 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // Adapted from https://github.com/crossbeam-rs/crossbeam/blob/crossbeam-utils-0.8.7/crossbeam-utils/src/atomic/seq_lock.rs. use core::{ mem::ManuallyDrop, sync::atomic::{self, Ordering}, }; use super::utils::Backoff; // See mod.rs for details. #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] pub(super) use core::sync::atomic::AtomicU64 as AtomicStamp; #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] pub(super) use core::sync::atomic::AtomicUsize as AtomicStamp; #[cfg(not(any(target_pointer_width = "16", target_pointer_width = "32")))] pub(super) type Stamp = usize; #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] pub(super) type Stamp = u64; // See mod.rs for details. pub(super) type AtomicChunk = AtomicStamp; pub(super) type Chunk = Stamp; /// A simple stamped lock. pub(super) struct SeqLock { /// The current state of the lock. /// /// All bits except the least significant one hold the current stamp. When locked, the state /// equals 1 and doesn't contain a valid stamp. state: AtomicStamp, } impl SeqLock { #[inline] pub(super) const fn new() -> Self { Self { state: AtomicStamp::new(0) } } /// If not locked, returns the current stamp. /// /// This method should be called before optimistic reads. #[inline] pub(super) fn optimistic_read(&self) -> Option { let state = self.state.load(Ordering::Acquire); if state == 1 { None } else { Some(state) } } /// Returns `true` if the current stamp is equal to `stamp`. /// /// This method should be called after optimistic reads to check whether they are valid. The /// argument `stamp` should correspond to the one returned by method `optimistic_read`. #[inline] pub(super) fn validate_read(&self, stamp: Stamp) -> bool { atomic::fence(Ordering::Acquire); self.state.load(Ordering::Relaxed) == stamp } /// Grabs the lock for writing. #[inline] pub(super) fn write(&self) -> SeqLockWriteGuard<'_> { let mut backoff = Backoff::new(); loop { let previous = self.state.swap(1, Ordering::Acquire); if previous != 1 { atomic::fence(Ordering::Release); return SeqLockWriteGuard { lock: self, state: previous }; } while self.state.load(Ordering::Relaxed) == 1 { backoff.snooze(); } } } } /// An RAII guard that releases the lock and increments the stamp when dropped. #[must_use] pub(super) struct SeqLockWriteGuard<'a> { /// The parent lock. lock: &'a SeqLock, /// The stamp before locking. state: Stamp, } impl SeqLockWriteGuard<'_> { /// Releases the lock without incrementing the stamp. #[inline] pub(super) fn abort(self) { // We specifically don't want to call drop(), since that's // what increments the stamp. let this = ManuallyDrop::new(self); // Restore the stamp. // // Release ordering for synchronizing with `optimistic_read`. this.lock.state.store(this.state, Ordering::Release); } } impl Drop for SeqLockWriteGuard<'_> { #[inline] fn drop(&mut self) { // Release the lock and increment the stamp. // // Release ordering for synchronizing with `optimistic_read`. self.lock.state.store(self.state.wrapping_add(2), Ordering::Release); } } #[cfg(test)] mod tests { use super::SeqLock; #[test] fn smoke() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); assert!(lock.validate_read(before)); { let _guard = lock.write(); } assert!(!lock.validate_read(before)); let after = lock.optimistic_read().unwrap(); assert_ne!(before, after); } #[test] fn test_abort() { let lock = SeqLock::new(); let before = lock.optimistic_read().unwrap(); { let guard = lock.write(); guard.abort(); } let after = lock.optimistic_read().unwrap(); assert_eq!(before, after, "aborted write does not update the stamp"); } } portable-atomic/src/gen/0000775000175000017500000000000014661133735016165 5ustar jamespagejamespageportable-atomic/src/gen/utils.rs0000644000175000017500000001204114661133735017667 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT // This file is @generated by target_spec.sh. // It is not intended for manual editing. #![allow(unused_macros)] // On AArch64, the base register of load/store/atomic instructions must be 64-bit. // Passing a 32-bit value to `in(reg)` on AArch64 results in the upper bits // having an undefined value, but to work correctly with ILP32 ABI, the upper // bits must be zero, which is handled here by casting to u64. Another way to // handle this is to pass it as a pointer and clear the upper bits inside asm, // but it is easier to overlook than cast, which can catch overlooks by // asm_sub_register lint. // See also https://github.com/ARM-software/abi-aa/blob/2023Q1/aapcs64/aapcs64.rst#57pointers // // Except for x86_64, which can use 32-bit registers in the destination operand // (on x86_64, we use the ptr_modifier macro to handle this), we need to do the // same for ILP32 ABI on other 64-bit architectures. (At least, as far as I can // see from the assembly generated by LLVM, this is also required for MIPS64 N32 // ABI. I don't know about the RISC-V s64ilp32 ABI for which a patch was // recently submitted to the kernel, but in any case, this should be a safe // default for such ABIs). // // Known architectures that have such ABI are x86_64 (X32), aarch64 (ILP32), // mips64 (N32), and riscv64 (s64ilp32, not merged yet though). (As of // 2023-06-05, only the former two are supported by rustc.) However, we list all // known 64-bit architectures because similar ABIs may exist or future added for // other architectures. #[cfg(all( target_pointer_width = "32", any( target_arch = "aarch64", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", ), ))] macro_rules! ptr_reg { ($ptr:ident) => {{ let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _) #[cfg(not(portable_atomic_no_asm_maybe_uninit))] #[allow(clippy::ptr_as_ptr)] { // If we cast to u64 here, the provenance will be lost, // so we convert to MaybeUninit via zero extend helper. crate::utils::zero_extend64_ptr($ptr as *mut ()) } #[cfg(portable_atomic_no_asm_maybe_uninit)] { // Use cast on old rustc because it does not support MaybeUninit // registers. This is still permissive-provenance compatible and // is sound. $ptr as u64 } }}; } #[cfg(not(all( target_pointer_width = "32", any( target_arch = "aarch64", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", ), )))] macro_rules! ptr_reg { ($ptr:ident) => {{ let _: *const _ = $ptr; // ensure $ptr is a pointer (*mut _ or *const _) $ptr // cast is unnecessary here. }}; } // Some 64-bit architectures have ABI with 32-bit pointer width (e.g., x86_64 X32 ABI, // AArch64 ILP32 ABI, MIPS64 N32 ABI). On those targets, AtomicU64 is available // and fast, so use it to implement normal sequence lock. // // See ptr_reg macro for the reason why all known 64-bit architectures are listed. #[cfg(feature = "fallback")] #[cfg(any( not(any(target_pointer_width = "16", target_pointer_width = "32")), // i.e., 64-bit or greater target_arch = "aarch64", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", ))] #[macro_use] mod fast_atomic_64_macros { macro_rules! cfg_has_fast_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } macro_rules! cfg_no_fast_atomic_64 { ($($tt:tt)*) => {}; } } #[cfg(feature = "fallback")] #[cfg(not(any( not(any(target_pointer_width = "16", target_pointer_width = "32")), // i.e., 64-bit or greater target_arch = "aarch64", target_arch = "bpf", target_arch = "loongarch64", target_arch = "mips64", target_arch = "mips64r6", target_arch = "nvptx64", target_arch = "powerpc64", target_arch = "riscv64", target_arch = "s390x", target_arch = "sparc64", target_arch = "wasm64", target_arch = "x86_64", )))] #[macro_use] mod fast_atomic_64_macros { macro_rules! cfg_has_fast_atomic_64 { ($($tt:tt)*) => {}; } macro_rules! cfg_no_fast_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } } portable-atomic/src/lib.rs0000644000175000017500000047553014661133735016544 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT /*! Portable atomic types including support for 128-bit atomics, atomic float, etc. - Provide all atomic integer types (`Atomic{I,U}{8,16,32,64}`) for all targets that can use atomic CAS. (i.e., all targets that can use `std`, and most no-std targets) - Provide `AtomicI128` and `AtomicU128`. - Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float)) - Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR) - Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 ARM, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise) - Provide stable equivalents of the standard library's atomic types' unstable APIs, such as [`AtomicPtr::fetch_*`](https://github.com/rust-lang/rust/issues/99108), [`AtomicBool::fetch_not`](https://github.com/rust-lang/rust/issues/98485). - Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), [`from_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.from_ptr) and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+. - Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc. ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] portable-atomic = "1" ``` The default features are mainly for users who use atomics larger than the pointer width. If you don't need them, disabling the default features may reduce code size and compile time slightly. ```toml [dependencies] portable-atomic = { version = "1", default-features = false } ``` If your crate supports no-std environment and requires atomic CAS, enabling the `require-cas` feature will allow the `portable-atomic` to display helpful error messages to users on targets requiring additional action on the user side to provide atomic CAS. ```toml [dependencies] portable-atomic = { version = "1.3", default-features = false, features = ["require-cas"] } ``` *Compiler support: requires rustc 1.34+* ## 128-bit atomics support Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), aarch64 (Rust 1.59+), powerpc64 (nightly only), and s390x (nightly only), otherwise the fallback implementation is used. On x86_64, even if `cmpxchg16b` is not available at compile-time (note: `cmpxchg16b` target feature is enabled by default only on Apple targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg. They are usually implemented using inline assembly, and when using Miri or ThreadSanitizer that do not support inline assembly, core intrinsics are used instead of inline assembly if possible. See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md) for details. ## Optional features - **`fallback`** *(enabled by default)*
Enable fallback implementations. Disabling this allows only atomic types for which the platform natively supports atomic operations. - **`float`**
Provide `AtomicF{32,64}`. Note that most of `fetch_*` operations of atomic floats are implemented using CAS loops, which can be slower than equivalent operations of atomic integers. ([GPU targets have atomic instructions for float, so we plan to use these instructions for GPU targets in the future.](https://github.com/taiki-e/portable-atomic/issues/34)) - **`std`**
Use `std`. - **`require-cas`**
Emit compile error if atomic CAS is not available. See [Usage](#usage) section and [#100](https://github.com/taiki-e/portable-atomic/pull/100) for more. - **`serde`**
Implement `serde::{Serialize,Deserialize}` for atomic types. Note: - The MSRV when this feature is enabled depends on the MSRV of [serde]. - **`critical-section`**
When this feature is enabled, this crate uses [critical-section] to provide atomic CAS for targets where it is not natively available. When enabling it, you should provide a suitable critical section implementation for the current target, see the [critical-section] documentation for details on how to do so. `critical-section` support is useful to get atomic CAS when the [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) can't be used, such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts needs extra care due to e.g. real-time requirements. Note that with the `critical-section` feature, critical sections are taken for all atomic operations, while with [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core) some operations don't require disabling interrupts (loads and stores, but additionally on MSP430 `add`, `sub`, `and`, `or`, `xor`, `not`). Therefore, for better performance, if all the `critical-section` implementation for your target does is disable interrupts, prefer using `unsafe-assume-single-core` feature instead. Note: - The MSRV when this feature is enabled depends on the MSRV of [critical-section]. - It is usually *not* recommended to always enable this feature in dependencies of the library. Enabling this feature will prevent the end user from having the chance to take advantage of other (potentially) efficient implementations ([Implementations provided by `unsafe-assume-single-core` feature, default implementations on MSP430 and AVR](#optional-features-unsafe-assume-single-core), implementation proposed in [#60], etc. Other systems may also be supported in the future). The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where other implementations are known not to work.) As an example, the end-user's `Cargo.toml` that uses a crate that provides a critical-section implementation and a crate that depends on portable-atomic as an option would be expected to look like this: ```toml [dependencies] portable-atomic = { version = "1", default-features = false, features = ["critical-section"] } crate-provides-critical-section-impl = "..." crate-uses-portable-atomic-as-feature = { version = "...", features = ["portable-atomic"] } ``` - **`unsafe-assume-single-core`**
Assume that the target is single-core. When this feature is enabled, this crate provides atomic CAS for targets where atomic CAS is not available in the standard library by disabling interrupts. This feature is `unsafe`, and note the following safety requirements: - Enabling this feature for multi-core systems is always **unsound**. - This uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode. Enabling this feature in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent. The following are known cases: - On pre-v6 ARM, this disables only IRQs by default. For many systems (e.g., GBA) this is enough. If the system need to disable both IRQs and FIQs, you need to enable the `disable-fiq` feature together. - On RISC-V without A-extension, this generates code for machine-mode (M-mode) by default. If you enable the `s-mode` together, this generates code for supervisor-mode (S-mode). In particular, `qemu-system-riscv*` uses [OpenSBI](https://github.com/riscv-software-src/opensbi) as the default firmware. See also [the `interrupt` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md). Consider using the [`critical-section` feature](#optional-features-critical-section) for systems that cannot use this feature. It is **very strongly discouraged** to enable this feature in libraries that depend on `portable-atomic`. The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer targeting a single-core chip.) ARMv6-M (thumbv6m), pre-v6 ARM (e.g., thumbv4t, thumbv5te), RISC-V without A-extension, and Xtensa are currently supported. Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this feature. Enabling this feature for targets that have atomic CAS will result in a compile error. Feel free to submit an issue if your target is not supported yet. ## Optional cfg One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags): ```toml # .cargo/config.toml [target.] rustflags = ["--cfg", "portable_atomic_no_outline_atomics"] ``` Or set environment variable: ```sh RUSTFLAGS="--cfg portable_atomic_no_outline_atomics" cargo ... ``` - **`--cfg portable_atomic_unsafe_assume_single_core`**
Since 1.4.0, this cfg is an alias of [`unsafe-assume-single-core` feature](#optional-features-unsafe-assume-single-core). Originally, we were providing these as cfgs instead of features, but based on a strong request from the embedded ecosystem, we have agreed to provide them as features as well. See [#94](https://github.com/taiki-e/portable-atomic/pull/94) for more. - **`--cfg portable_atomic_no_outline_atomics`**
Disable dynamic dispatching by run-time CPU feature detection. If dynamic dispatching by run-time CPU feature detection is enabled, it allows maintaining support for older CPUs while using features that are not supported on older CPUs, such as CMPXCHG16B (x86_64) and FEAT_LSE (aarch64). Note: - Dynamic detection is currently only enabled in Rust 1.59+ for aarch64, in Rust 1.59+ (AVX) or 1.69+ (CMPXCHG16B) for x86_64, nightly only for powerpc64 (disabled by default), otherwise it works the same as when this cfg is set. - If the required target features are enabled at compile-time, the atomic operations are inlined. - This is compatible with no-std (as with all features except `std`). - On some targets, run-time detection is disabled by default mainly for compatibility with older versions of operating systems or incomplete build environments, and can be enabled by `--cfg portable_atomic_outline_atomics`. (When both cfg are enabled, `*_no_*` cfg is preferred.) - Some aarch64 targets enable LLVM's `outline-atomics` target feature by default, so if you set this cfg, you may want to disable that as well. (portable-atomic's outline-atomics does not depend on the compiler-rt symbols, so even if you need to disable LLVM's outline-atomics, you may not need to disable portable-atomic's outline-atomics.) See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md). ## Related Projects - [atomic-maybe-uninit]: Atomic operations on potentially uninitialized integers. - [atomic-memcpy]: Byte-wise atomic memcpy. [#60]: https://github.com/taiki-e/portable-atomic/issues/60 [atomic-maybe-uninit]: https://github.com/taiki-e/atomic-maybe-uninit [atomic-memcpy]: https://github.com/taiki-e/atomic-memcpy [critical-section]: https://github.com/rust-embedded/critical-section [rust-lang/rust#100650]: https://github.com/rust-lang/rust/issues/100650 [serde]: https://github.com/serde-rs/serde */ #![no_std] #![doc(test( no_crate_inject, attr( deny(warnings, rust_2018_idioms, single_use_lifetimes), allow(dead_code, unused_variables) ) ))] #![cfg_attr(not(portable_atomic_no_unsafe_op_in_unsafe_fn), warn(unsafe_op_in_unsafe_fn))] // unsafe_op_in_unsafe_fn requires Rust 1.52 #![cfg_attr(portable_atomic_no_unsafe_op_in_unsafe_fn, allow(unused_unsafe))] #![warn( // Lints that may help when writing public library. missing_debug_implementations, // missing_docs, clippy::alloc_instead_of_core, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::impl_trait_in_params, clippy::missing_inline_in_public_items, clippy::std_instead_of_alloc, clippy::std_instead_of_core, )] #![cfg_attr(not(portable_atomic_no_asm), warn(missing_docs))] // module-level #![allow(missing_docs)] doesn't work for macros on old rustc #![allow( clippy::cast_lossless, clippy::inline_always, clippy::naive_bytecount, clippy::unreadable_literal )] // asm_experimental_arch // AVR, MSP430, and Xtensa are tier 3 platforms and require nightly anyway. // On tier 2 platforms (powerpc64 and s390x), we use cfg set by build script to // determine whether this feature is available or not. #![cfg_attr( all( not(portable_atomic_no_asm), any( target_arch = "avr", target_arch = "msp430", all(target_arch = "xtensa", portable_atomic_unsafe_assume_single_core), all(target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch), all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch), ), ), feature(asm_experimental_arch) )] // Old nightly only // These features are already stabilized or have already been removed from compilers, // and can safely be enabled for old nightly as long as version detection works. // - cfg(target_has_atomic) // - #[target_feature(enable = "cmpxchg16b")] on x86_64 // - asm! on ARM, AArch64, RISC-V, x86_64 // - llvm_asm! on AVR (tier 3) and MSP430 (tier 3) // - #[instruction_set] on non-Linux/Android pre-v6 ARM (tier 3) #![cfg_attr(portable_atomic_unstable_cfg_target_has_atomic, feature(cfg_target_has_atomic))] #![cfg_attr( all( target_arch = "x86_64", portable_atomic_unstable_cmpxchg16b_target_feature, not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), feature = "fallback", ), feature(cmpxchg16b_target_feature) )] #![cfg_attr( all( portable_atomic_unstable_asm, any( target_arch = "aarch64", target_arch = "arm", target_arch = "riscv32", target_arch = "riscv64", target_arch = "x86_64", ), ), feature(asm) )] #![cfg_attr( all(any(target_arch = "avr", target_arch = "msp430"), portable_atomic_no_asm), feature(llvm_asm) )] #![cfg_attr( all( target_arch = "arm", portable_atomic_unstable_isa_attribute, any(test, portable_atomic_unsafe_assume_single_core), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(target_has_atomic = "ptr"), ), feature(isa_attribute) )] // Miri and/or ThreadSanitizer only // They do not support inline assembly, so we need to use unstable features instead. // Since they require nightly compilers anyway, we can use the unstable features. #![cfg_attr( all( any(target_arch = "aarch64", target_arch = "powerpc64", target_arch = "s390x"), any(miri, portable_atomic_sanitize_thread), ), feature(core_intrinsics) )] // This feature is only enabled for old nightly because cmpxchg16b_intrinsic has been stabilized. #![cfg_attr( all( target_arch = "x86_64", portable_atomic_unstable_cmpxchg16b_intrinsic, any(miri, portable_atomic_sanitize_thread), ), feature(stdsimd) )] // docs.rs only #![cfg_attr(portable_atomic_doc_cfg, feature(doc_cfg))] #![cfg_attr( all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "bpf", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), ), allow(unused_imports, unused_macros) )] // There are currently no 8-bit, 128-bit, or higher builtin targets. // (Although some of our generic code is written with the future // addition of 128-bit targets in mind.) // Note that Rust (and C99) pointers must be at least 16-bits: https://github.com/rust-lang/rust/pull/49305 #[cfg(not(any( target_pointer_width = "16", target_pointer_width = "32", target_pointer_width = "64", )))] compile_error!( "portable-atomic currently only supports targets with {16,32,64}-bit pointer width; \ if you need support for others, \ please submit an issue at " ); #[cfg(portable_atomic_unsafe_assume_single_core)] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( not(portable_atomic_no_atomic_cas), not(any( target_arch = "arm", target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", target_arch = "xtensa", )), )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "ptr", not(any( target_arch = "arm", target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", target_arch = "xtensa", )), )) )] compile_error!( "cfg(portable_atomic_unsafe_assume_single_core) does not compatible with this target;\n\ if you need cfg(portable_atomic_unsafe_assume_single_core) support for this target,\n\ please submit an issue at " ); #[cfg(portable_atomic_no_outline_atomics)] #[cfg(not(any( target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc64", target_arch = "x86_64", )))] compile_error!("cfg(portable_atomic_no_outline_atomics) does not compatible with this target"); #[cfg(portable_atomic_outline_atomics)] #[cfg(not(any(target_arch = "aarch64", target_arch = "powerpc64")))] compile_error!("cfg(portable_atomic_outline_atomics) does not compatible with this target"); #[cfg(portable_atomic_disable_fiq)] #[cfg(not(all( target_arch = "arm", not(any(target_feature = "mclass", portable_atomic_target_feature = "mclass")), )))] compile_error!("cfg(portable_atomic_disable_fiq) does not compatible with this target"); #[cfg(portable_atomic_s_mode)] #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] compile_error!("cfg(portable_atomic_s_mode) does not compatible with this target"); #[cfg(portable_atomic_force_amo)] #[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] compile_error!("cfg(portable_atomic_force_amo) does not compatible with this target"); #[cfg(portable_atomic_disable_fiq)] #[cfg(not(portable_atomic_unsafe_assume_single_core))] compile_error!( "cfg(portable_atomic_disable_fiq) may only be used together with cfg(portable_atomic_unsafe_assume_single_core)" ); #[cfg(portable_atomic_s_mode)] #[cfg(not(portable_atomic_unsafe_assume_single_core))] compile_error!( "cfg(portable_atomic_s_mode) may only be used together with cfg(portable_atomic_unsafe_assume_single_core)" ); #[cfg(portable_atomic_force_amo)] #[cfg(not(portable_atomic_unsafe_assume_single_core))] compile_error!( "cfg(portable_atomic_force_amo) may only be used together with cfg(portable_atomic_unsafe_assume_single_core)" ); #[cfg(all(portable_atomic_unsafe_assume_single_core, feature = "critical-section"))] compile_error!( "you may not enable feature `critical-section` and cfg(portable_atomic_unsafe_assume_single_core) at the same time" ); #[cfg(feature = "require-cas")] #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] compile_error!( "dependents require atomic CAS but not available on this target by default;\n\ consider enabling one of the `unsafe-assume-single-core` or `critical-section` Cargo features.\n\ see for more." ); #[cfg(any(test, feature = "std"))] extern crate std; #[macro_use] mod cfgs; #[cfg(target_pointer_width = "128")] pub use {cfg_has_atomic_128 as cfg_has_atomic_ptr, cfg_no_atomic_128 as cfg_no_atomic_ptr}; #[cfg(target_pointer_width = "16")] pub use {cfg_has_atomic_16 as cfg_has_atomic_ptr, cfg_no_atomic_16 as cfg_no_atomic_ptr}; #[cfg(target_pointer_width = "32")] pub use {cfg_has_atomic_32 as cfg_has_atomic_ptr, cfg_no_atomic_32 as cfg_no_atomic_ptr}; #[cfg(target_pointer_width = "64")] pub use {cfg_has_atomic_64 as cfg_has_atomic_ptr, cfg_no_atomic_64 as cfg_no_atomic_ptr}; #[macro_use] mod utils; #[cfg(test)] #[macro_use] mod tests; #[doc(no_inline)] pub use core::sync::atomic::Ordering; #[doc(no_inline)] // LLVM doesn't support fence/compiler_fence for MSP430. #[cfg(not(target_arch = "msp430"))] pub use core::sync::atomic::{compiler_fence, fence}; #[cfg(target_arch = "msp430")] pub use imp::msp430::{compiler_fence, fence}; mod imp; pub mod hint { //! Re-export of the [`core::hint`] module. //! //! The only difference from the [`core::hint`] module is that [`spin_loop`] //! is available in all rust versions that this crate supports. //! //! ``` //! use portable_atomic::hint; //! //! hint::spin_loop(); //! ``` #[doc(no_inline)] pub use core::hint::*; /// Emits a machine instruction to signal the processor that it is running in /// a busy-wait spin-loop ("spin lock"). /// /// Upon receiving the spin-loop signal the processor can optimize its behavior by, /// for example, saving power or switching hyper-threads. /// /// This function is different from [`thread::yield_now`] which directly /// yields to the system's scheduler, whereas `spin_loop` does not interact /// with the operating system. /// /// A common use case for `spin_loop` is implementing bounded optimistic /// spinning in a CAS loop in synchronization primitives. To avoid problems /// like priority inversion, it is strongly recommended that the spin loop is /// terminated after a finite amount of iterations and an appropriate blocking /// syscall is made. /// /// **Note:** On platforms that do not support receiving spin-loop hints this /// function does not do anything at all. /// /// [`thread::yield_now`]: https://doc.rust-lang.org/std/thread/fn.yield_now.html #[inline] pub fn spin_loop() { #[allow(deprecated)] core::sync::atomic::spin_loop_hint(); } } #[cfg(doc)] use core::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst}; use core::{fmt, ptr}; #[cfg(miri)] use crate::utils::strict; cfg_has_atomic_8! { cfg_has_atomic_cas! { // See https://github.com/rust-lang/rust/pull/114034 for details. // https://github.com/rust-lang/rust/blob/9339f446a5302cd5041d3f3b5e59761f36699167/library/core/src/sync/atomic.rs#L134 // https://godbolt.org/z/5W85abT58 #[cfg(portable_atomic_no_cfg_target_has_atomic)] const EMULATE_ATOMIC_BOOL: bool = cfg!(all( not(portable_atomic_no_atomic_cas), any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64"), )); #[cfg(not(portable_atomic_no_cfg_target_has_atomic))] const EMULATE_ATOMIC_BOOL: bool = cfg!(all( target_has_atomic = "8", any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64"), )); } // cfg_has_atomic_cas! /// A boolean type which can be safely shared between threads. /// /// This type has the same in-memory representation as a [`bool`]. /// /// If the compiler and the platform support atomic loads and stores of `u8`, /// this type is a wrapper for the standard library's /// [`AtomicBool`](core::sync::atomic::AtomicBool). If the platform supports it /// but the compiler does not, atomic operations are implemented using inline /// assembly. #[repr(C, align(1))] pub struct AtomicBool { v: core::cell::UnsafeCell, } impl Default for AtomicBool { /// Creates an `AtomicBool` initialized to `false`. #[inline] fn default() -> Self { Self::new(false) } } impl From for AtomicBool { /// Converts a `bool` into an `AtomicBool`. #[inline] fn from(b: bool) -> Self { Self::new(b) } } // Send is implicitly implemented. // SAFETY: any data races are prevented by disabling interrupts or // atomic intrinsics (see module-level comments). unsafe impl Sync for AtomicBool {} // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for AtomicBool {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for AtomicBool {} impl_debug_and_serde!(AtomicBool); impl AtomicBool { /// Creates a new `AtomicBool`. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// let atomic_true = AtomicBool::new(true); /// let atomic_false = AtomicBool::new(false); /// ``` #[inline] #[must_use] pub const fn new(v: bool) -> Self { static_assert_layout!(AtomicBool, bool); Self { v: core::cell::UnsafeCell::new(v as u8) } } /// Creates a new `AtomicBool` from a pointer. /// /// # Safety /// /// * `ptr` must be aligned to `align_of::()` (note that on some platforms this can /// be bigger than `align_of::()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value /// behind `ptr` must have a happens-before relationship with atomic accesses via the returned /// value (or vice-versa). /// * In other words, time periods where the value is accessed atomically may not overlap /// with periods where the value is accessed non-atomically. /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done /// from the same thread. /// * If this atomic type is *not* lock-free: /// * Any accesses to the value behind `ptr` must have a happens-before relationship /// with accesses via the returned value (or vice-versa). /// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must /// be compatible with operations performed by this atomic type. /// * This method must not be used to create overlapping or mixed-size atomic accesses, as /// these are not supported by the memory model. /// /// [valid]: core::ptr#safety #[inline] #[must_use] pub unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// let is_lock_free = AtomicBool::is_lock_free(); /// ``` #[inline] #[must_use] pub fn is_lock_free() -> bool { imp::AtomicU8::is_lock_free() } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// **Note:** If the atomic operation relies on dynamic CPU feature detection, /// this type may be lock-free even if the function returns false. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// const IS_ALWAYS_LOCK_FREE: bool = AtomicBool::is_always_lock_free(); /// ``` #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { imp::AtomicU8::is_always_lock_free() } /// Returns a mutable reference to the underlying [`bool`]. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let mut some_bool = AtomicBool::new(true); /// assert_eq!(*some_bool.get_mut(), true); /// *some_bool.get_mut() = false; /// assert_eq!(some_bool.load(Ordering::SeqCst), false); /// ``` #[inline] pub fn get_mut(&mut self) -> &mut bool { // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *(self.v.get() as *mut bool) } } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are /// concurrently accessing the atomic data. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicBool; /// /// let some_bool = AtomicBool::new(true); /// assert_eq!(some_bool.into_inner(), true); /// ``` #[inline] pub fn into_inner(self) -> bool { self.v.into_inner() != 0 } /// Loads a value from the bool. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// assert_eq!(some_bool.load(Ordering::Relaxed), true); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> bool { self.as_atomic_u8().load(order) != 0 } /// Stores a value into the bool. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Acquire`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// some_bool.store(false, Ordering::Relaxed); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, val: bool, order: Ordering) { self.as_atomic_u8().store(val as u8, order); } cfg_has_atomic_cas! { /// Stores a value into the bool, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, val: bool, order: Ordering) -> bool { if EMULATE_ATOMIC_BOOL { if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) } } else { self.as_atomic_u8().swap(val as u8, order) != 0 } } /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let some_bool = AtomicBool::new(true); /// /// assert_eq!( /// some_bool.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed), /// Ok(true) /// ); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// /// assert_eq!( /// some_bool.compare_exchange(true, true, Ordering::SeqCst, Ordering::Acquire), /// Err(false) /// ); /// assert_eq!(some_bool.load(Ordering::Relaxed), false); /// ``` #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: bool, new: bool, success: Ordering, failure: Ordering, ) -> Result { if EMULATE_ATOMIC_BOOL { crate::utils::assert_compare_exchange_ordering(success, failure); let order = crate::utils::upgrade_success_ordering(success, failure); let old = if current == new { // This is a no-op, but we still need to perform the operation // for memory ordering reasons. self.fetch_or(false, order) } else { // This sets the value to the new one and returns the old one. self.swap(new, order) }; if old == current { Ok(old) } else { Err(old) } } else { match self.as_atomic_u8().compare_exchange(current as u8, new as u8, success, failure) { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } } } /// Stores a value into the [`bool`] if the current value is the same as the `current` value. /// /// Unlike [`AtomicBool::compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The /// return value is a result indicating whether the new value was written and containing the /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let val = AtomicBool::new(false); /// /// let new = true; /// let mut old = val.load(Ordering::Relaxed); /// loop { /// match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { /// Ok(_) => break, /// Err(x) => old = x, /// } /// } /// ``` #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: bool, new: bool, success: Ordering, failure: Ordering, ) -> Result { if EMULATE_ATOMIC_BOOL { return self.compare_exchange(current, new, success, failure); } match self.as_atomic_u8().compare_exchange_weak(current as u8, new as u8, success, failure) { Ok(x) => Ok(x != 0), Err(x) => Err(x != 0), } } /// Logical "and" with a boolean value. /// /// Performs a logical "and" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { self.as_atomic_u8().fetch_and(val as u8, order) != 0 } /// Logical "and" with a boolean value. /// /// Performs a logical "and" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Unlike `fetch_and`, this does not return the previous value. /// /// `and` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_and` on some platforms. /// /// - x86/x86_64: `lock and` instead of `cmpxchg` loop /// - MSP430: `and` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.and(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(true); /// foo.and(true, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// foo.and(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn and(&self, val: bool, order: Ordering) { self.as_atomic_u8().and(val as u8, order); } /// Logical "nand" with a boolean value. /// /// Performs a logical "nand" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L811-L825 if val { // !(x & true) == !x // We must invert the bool. self.fetch_xor(true, order) } else { // !(x & false) == true // We must set the bool to true. self.swap(true, order) } } /// Logical "or" with a boolean value. /// /// Performs a logical "or" operation on the current value and the argument `val`, and sets the /// new value to the result. /// /// Returns the previous value. /// /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { self.as_atomic_u8().fetch_or(val as u8, order) != 0 } /// Logical "or" with a boolean value. /// /// Performs a logical "or" operation on the current value and the argument `val`, and sets the /// new value to the result. /// /// Unlike `fetch_or`, this does not return the previous value. /// /// `or` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_or` on some platforms. /// /// - x86/x86_64: `lock or` instead of `cmpxchg` loop /// - MSP430: `bis` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.or(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// foo.or(true, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(false); /// foo.or(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn or(&self, val: bool, order: Ordering) { self.as_atomic_u8().or(val as u8, order); } /// Logical "xor" with a boolean value. /// /// Performs a logical "xor" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { self.as_atomic_u8().fetch_xor(val as u8, order) != 0 } /// Logical "xor" with a boolean value. /// /// Performs a logical "xor" operation on the current value and the argument `val`, and sets /// the new value to the result. /// /// Unlike `fetch_xor`, this does not return the previous value. /// /// `xor` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_xor` on some platforms. /// /// - x86/x86_64: `lock xor` instead of `cmpxchg` loop /// - MSP430: `xor` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.xor(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// /// let foo = AtomicBool::new(true); /// foo.xor(true, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// foo.xor(false, Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn xor(&self, val: bool, order: Ordering) { self.as_atomic_u8().xor(val as u8, order); } /// Logical "not" with a boolean value. /// /// Performs a logical "not" operation on the current value, and sets /// the new value to the result. /// /// Returns the previous value. /// /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_not(&self, order: Ordering) -> bool { self.fetch_xor(true, order) } /// Logical "not" with a boolean value. /// /// Performs a logical "not" operation on the current value, and sets /// the new value to the result. /// /// Unlike `fetch_not`, this does not return the previous value. /// /// `not` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This function may generate more efficient code than `fetch_not` on some platforms. /// /// - x86/x86_64: `lock xor` instead of `cmpxchg` loop /// - MSP430: `xor` instead of disabling interrupts /// /// Note: On x86/x86_64, the use of either function should not usually /// affect the generated code, because LLVM can properly optimize the case /// where the result is unused. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicBool, Ordering}; /// /// let foo = AtomicBool::new(true); /// foo.not(Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), false); /// /// let foo = AtomicBool::new(false); /// foo.not(Ordering::SeqCst); /// assert_eq!(foo.load(Ordering::SeqCst), true); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn not(&self, order: Ordering) { self.xor(true, order); } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function /// returned `Some(_)`, else `Err(previous_value)`. /// /// Note: This may call the function multiple times if the value has been /// changed from other threads in the meantime, as long as the function /// returns `Some(_)`, but the function will have been applied only once to /// the stored value. /// /// `fetch_update` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering for /// when the operation finally succeeds while the second describes the /// required ordering for loads. These correspond to the success and failure /// orderings of [`compare_exchange`](Self::compare_exchange) respectively. /// /// Using [`Acquire`] as success ordering makes the store part of this /// operation [`Relaxed`], and using [`Release`] makes the final successful /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], /// [`Acquire`] or [`Relaxed`]. /// /// # Considerations /// /// This method is not magic; it is not provided by the hardware. /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), /// and suffers from the same drawbacks. /// In particular, this method will not circumvent the [ABA Problem]. /// /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem /// /// # Panics /// /// Panics if `fetch_order` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ```rust /// use portable_atomic::{AtomicBool, Ordering}; /// /// let x = AtomicBool::new(false); /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false)); /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false)); /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true)); /// assert_eq!(x.load(Ordering::SeqCst), false); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result where F: FnMut(bool) -> Option, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } } // cfg_has_atomic_cas! const_fn! { // This function is actually `const fn`-compatible on Rust 1.32+, // but makes `const fn` only on Rust 1.58+ to match other atomic types. const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying [`bool`]. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut bool { self.v.get() as *mut bool } } #[inline] fn as_atomic_u8(&self) -> &imp::AtomicU8 { // SAFETY: AtomicBool and imp::AtomicU8 have the same layout, // and both access data in the same way. unsafe { &*(self as *const Self as *const imp::AtomicU8) } } } } // cfg_has_atomic_8! cfg_has_atomic_ptr! { /// A raw pointer type which can be safely shared between threads. /// /// This type has the same in-memory representation as a `*mut T`. /// /// If the compiler and the platform support atomic loads and stores of pointers, /// this type is a wrapper for the standard library's /// [`AtomicPtr`](core::sync::atomic::AtomicPtr). If the platform supports it /// but the compiler does not, atomic operations are implemented using inline /// assembly. // We can use #[repr(transparent)] here, but #[repr(C, align(N))] // will show clearer docs. #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] #[cfg_attr(target_pointer_width = "128", repr(C, align(16)))] pub struct AtomicPtr { inner: imp::AtomicPtr, } impl Default for AtomicPtr { /// Creates a null `AtomicPtr`. #[inline] fn default() -> Self { Self::new(ptr::null_mut()) } } impl From<*mut T> for AtomicPtr { #[inline] fn from(p: *mut T) -> Self { Self::new(p) } } impl fmt::Debug for AtomicPtr { #[allow(clippy::missing_inline_in_public_items)] // fmt is not hot path fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L2024 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f) } } impl fmt::Pointer for AtomicPtr { #[allow(clippy::missing_inline_in_public_items)] // fmt is not hot path fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L2024 fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f) } } // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for AtomicPtr {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for AtomicPtr {} impl AtomicPtr { /// Creates a new `AtomicPtr`. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// let ptr = &mut 5; /// let atomic_ptr = AtomicPtr::new(ptr); /// ``` #[inline] #[must_use] pub const fn new(p: *mut T) -> Self { static_assert_layout!(AtomicPtr<()>, *mut ()); Self { inner: imp::AtomicPtr::new(p) } } /// Creates a new `AtomicPtr` from a pointer. /// /// # Safety /// /// * `ptr` must be aligned to `align_of::>()` (note that on some platforms this /// can be bigger than `align_of::<*mut T>()`). /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value /// behind `ptr` must have a happens-before relationship with atomic accesses via the returned /// value (or vice-versa). /// * In other words, time periods where the value is accessed atomically may not overlap /// with periods where the value is accessed non-atomically. /// * This requirement is trivially satisfied if `ptr` is never used non-atomically for the /// duration of lifetime `'a`. Most use cases should be able to follow this guideline. /// * This requirement is also trivially satisfied if all accesses (atomic or not) are done /// from the same thread. /// * If this atomic type is *not* lock-free: /// * Any accesses to the value behind `ptr` must have a happens-before relationship /// with accesses via the returned value (or vice-versa). /// * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must /// be compatible with operations performed by this atomic type. /// * This method must not be used to create overlapping or mixed-size atomic accesses, as /// these are not supported by the memory model. /// /// [valid]: core::ptr#safety #[inline] #[must_use] pub unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// let is_lock_free = AtomicPtr::<()>::is_lock_free(); /// ``` #[inline] #[must_use] pub fn is_lock_free() -> bool { >::is_lock_free() } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// **Note:** If the atomic operation relies on dynamic CPU feature detection, /// this type may be lock-free even if the function returns false. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// const IS_ALWAYS_LOCK_FREE: bool = AtomicPtr::<()>::is_always_lock_free(); /// ``` #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { >::is_always_lock_free() } /// Returns a mutable reference to the underlying pointer. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let mut data = 10; /// let mut atomic_ptr = AtomicPtr::new(&mut data); /// let mut other_data = 5; /// *atomic_ptr.get_mut() = &mut other_data; /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5); /// ``` #[inline] pub fn get_mut(&mut self) -> &mut *mut T { self.inner.get_mut() } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are /// concurrently accessing the atomic data. /// /// # Examples /// /// ``` /// use portable_atomic::AtomicPtr; /// /// let mut data = 5; /// let atomic_ptr = AtomicPtr::new(&mut data); /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5); /// ``` #[inline] pub fn into_inner(self) -> *mut T { self.inner.into_inner() } /// Loads a value from the pointer. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let value = some_ptr.load(Ordering::Relaxed); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> *mut T { self.inner.load(order) } /// Stores a value into the pointer. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Acquire`] or [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; /// /// some_ptr.store(other_ptr, Ordering::Relaxed); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, ptr: *mut T, order: Ordering) { self.inner.store(ptr, order); } cfg_has_atomic_cas! { /// Stores a value into the pointer, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; /// /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { self.inner.swap(ptr, order) } /// Stores a value into the pointer if the current value is the same as the `current` value. /// /// The return value is a result indicating whether the new value was written and containing /// the previous value. On success this value is guaranteed to be equal to `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let other_ptr = &mut 10; /// /// let value = some_ptr.compare_exchange(ptr, other_ptr, Ordering::SeqCst, Ordering::Relaxed); /// ``` #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { self.inner.compare_exchange(current, new, success, failure) } /// Stores a value into the pointer if the current value is the same as the `current` value. /// /// Unlike [`AtomicPtr::compare_exchange`], this function is allowed to spuriously fail even when the /// comparison succeeds, which can result in more efficient code on some platforms. The /// return value is a result indicating whether the new value was written and containing the /// previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let some_ptr = AtomicPtr::new(&mut 5); /// /// let new = &mut 10; /// let mut old = some_ptr.load(Ordering::Relaxed); /// loop { /// match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { /// Ok(_) => break, /// Err(x) => old = x, /// } /// } /// ``` #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: *mut T, new: *mut T, success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { self.inner.compare_exchange_weak(current, new, success, failure) } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function /// returned `Some(_)`, else `Err(previous_value)`. /// /// Note: This may call the function multiple times if the value has been /// changed from other threads in the meantime, as long as the function /// returns `Some(_)`, but the function will have been applied only once to /// the stored value. /// /// `fetch_update` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. The first describes the required ordering for /// when the operation finally succeeds while the second describes the /// required ordering for loads. These correspond to the success and failure /// orderings of [`compare_exchange`](Self::compare_exchange) respectively. /// /// Using [`Acquire`] as success ordering makes the store part of this /// operation [`Relaxed`], and using [`Release`] makes the final successful /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], /// [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `fetch_order` is [`Release`], [`AcqRel`]. /// /// # Considerations /// /// This method is not magic; it is not provided by the hardware. /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), /// and suffers from the same drawbacks. /// In particular, this method will not circumvent the [ABA Problem]. /// /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem /// /// # Examples /// /// ```rust /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let ptr: *mut _ = &mut 5; /// let some_ptr = AtomicPtr::new(ptr); /// /// let new: *mut _ = &mut 10; /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr)); /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| { /// if x == ptr { /// Some(new) /// } else { /// None /// } /// }); /// assert_eq!(result, Ok(ptr)); /// assert_eq!(some_ptr.load(Ordering::SeqCst), new); /// ``` #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result<*mut T, *mut T> where F: FnMut(*mut T) -> Option<*mut T>, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } #[cfg(miri)] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces fn fetch_update_(&self, order: Ordering, mut f: F) -> *mut T where F: FnMut(*mut T) -> *mut T, { // This is a private function and all instances of `f` only operate on the value // loaded, so there is no need to synchronize the first load/failed CAS. let mut prev = self.load(Ordering::Relaxed); loop { let next = f(prev); match self.compare_exchange_weak(prev, next, order, Ordering::Relaxed) { Ok(x) => return x, Err(next_prev) => prev = next_prev, } } } /// Offsets the pointer's address by adding `val` (in units of `T`), /// returning the previous pointer. /// /// This is equivalent to using [`wrapping_add`] to atomically perform the /// equivalent of `ptr = ptr.wrapping_add(val);`. /// /// This method operates in units of `T`, which means that it cannot be used /// to offset the pointer by an amount which is not a multiple of /// `size_of::()`. This can sometimes be inconvenient, as you may want to /// work with a deliberately misaligned pointer. In such cases, you may use /// the [`fetch_byte_add`](Self::fetch_byte_add) method instead. /// /// `fetch_ptr_add` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note /// that using [`Acquire`] makes the store part of this operation /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let atom = AtomicPtr::::new(core::ptr::null_mut()); /// assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0); /// // Note: units of `size_of::()`. /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 8); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_add(val.wrapping_mul(core::mem::size_of::()), order) } /// Offsets the pointer's address by subtracting `val` (in units of `T`), /// returning the previous pointer. /// /// This is equivalent to using [`wrapping_sub`] to atomically perform the /// equivalent of `ptr = ptr.wrapping_sub(val);`. /// /// This method operates in units of `T`, which means that it cannot be used /// to offset the pointer by an amount which is not a multiple of /// `size_of::()`. This can sometimes be inconvenient, as you may want to /// work with a deliberately misaligned pointer. In such cases, you may use /// the [`fetch_byte_sub`](Self::fetch_byte_sub) method instead. /// /// `fetch_ptr_sub` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub /// /// # Examples /// /// ``` /// use portable_atomic::{AtomicPtr, Ordering}; /// /// let array = [1i32, 2i32]; /// let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _); /// /// assert!(core::ptr::eq(atom.fetch_ptr_sub(1, Ordering::Relaxed), &array[1],)); /// assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0])); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_sub(val.wrapping_mul(core::mem::size_of::()), order) } /// Offsets the pointer's address by adding `val` *bytes*, returning the /// previous pointer. /// /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically /// perform `ptr = ptr.cast::().wrapping_add(val).cast::()`. /// /// `fetch_byte_add` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note /// that using [`Acquire`] makes the store part of this operation /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add /// [`cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let atom = AtomicPtr::::new(core::ptr::null_mut()); /// assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0); /// // Note: in units of bytes, not `size_of::()`. /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 1); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| strict::map_addr(x, |x| x.wrapping_add(val))) } #[cfg(not(miri))] { self.as_atomic_usize().fetch_add(val, order) as *mut T } } /// Offsets the pointer's address by subtracting `val` *bytes*, returning the /// previous pointer. /// /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically /// perform `ptr = ptr.cast::().wrapping_sub(val).cast::()`. /// /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the /// memory ordering of this operation. All ordering modes are possible. Note /// that using [`Acquire`] makes the store part of this operation /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. /// /// [`wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub /// [`cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let atom = AtomicPtr::::new(sptr::invalid_mut(1)); /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1); /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| strict::map_addr(x, |x| x.wrapping_sub(val))) } #[cfg(not(miri))] { self.as_atomic_usize().fetch_sub(val, order) as *mut T } } /// Performs a bitwise "or" operation on the address of the current pointer, /// and the argument `val`, and stores a pointer with provenance of the /// current pointer and the resulting address. /// /// This is equivalent to using [`map_addr`] to atomically perform /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged /// pointer schemes to atomically set tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the /// stored value without losing provenance, you may use [`map_addr`]. For /// example: `a.fetch_or(val).map_addr(|a| a | val)`. /// /// `fetch_or` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// This API and its claimed semantics are part of the Strict Provenance /// experiment, see the [module documentation for `ptr`][core::ptr] for /// details. /// /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let pointer = &mut 3i64 as *mut i64; /// /// let atom = AtomicPtr::::new(pointer); /// // Tag the bottom bit of the pointer. /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0); /// // Extract and untag. /// let tagged = atom.load(Ordering::Relaxed); /// assert_eq!(tagged.addr() & 1, 1); /// assert_eq!(tagged.map_addr(|p| p & !1), pointer); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| strict::map_addr(x, |x| x | val)) } #[cfg(not(miri))] { self.as_atomic_usize().fetch_or(val, order) as *mut T } } /// Performs a bitwise "and" operation on the address of the current /// pointer, and the argument `val`, and stores a pointer with provenance of /// the current pointer and the resulting address. /// /// This is equivalent to using [`map_addr`] to atomically perform /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged /// pointer schemes to atomically unset tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the /// stored value without losing provenance, you may use [`map_addr`]. For /// example: `a.fetch_and(val).map_addr(|a| a & val)`. /// /// `fetch_and` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// This API and its claimed semantics are part of the Strict Provenance /// experiment, see the [module documentation for `ptr`][core::ptr] for /// details. /// /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let pointer = &mut 3i64 as *mut i64; /// // A tagged pointer /// let atom = AtomicPtr::::new(pointer.map_addr(|a| a | 1)); /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1); /// // Untag, and extract the previously tagged pointer. /// let untagged = atom.fetch_and(!1, Ordering::Relaxed).map_addr(|a| a & !1); /// assert_eq!(untagged, pointer); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| strict::map_addr(x, |x| x & val)) } #[cfg(not(miri))] { self.as_atomic_usize().fetch_and(val, order) as *mut T } } /// Performs a bitwise "xor" operation on the address of the current /// pointer, and the argument `val`, and stores a pointer with provenance of /// the current pointer and the resulting address. /// /// This is equivalent to using [`map_addr`] to atomically perform /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged /// pointer schemes to atomically toggle tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the /// stored value without losing provenance, you may use [`map_addr`]. For /// example: `a.fetch_xor(val).map_addr(|a| a ^ val)`. /// /// `fetch_xor` takes an [`Ordering`] argument which describes the memory /// ordering of this operation. All ordering modes are possible. Note that /// using [`Acquire`] makes the store part of this operation [`Relaxed`], /// and using [`Release`] makes the load part [`Relaxed`]. /// /// This API and its claimed semantics are part of the Strict Provenance /// experiment, see the [module documentation for `ptr`][core::ptr] for /// details. /// /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let pointer = &mut 3i64 as *mut i64; /// let atom = AtomicPtr::::new(pointer); /// /// // Toggle a tag bit on the pointer. /// atom.fetch_xor(1, Ordering::Relaxed); /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { self.fetch_update_(order, |x| strict::map_addr(x, |x| x ^ val)) } #[cfg(not(miri))] { self.as_atomic_usize().fetch_xor(val, order) as *mut T } } /// Sets the bit at the specified bit-position to 1. /// /// Returns `true` if the specified bit was previously set to 1. /// /// `bit_set` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This corresponds to x86's `lock bts`, and the implementation calls them on x86/x86_64. /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let pointer = &mut 3i64 as *mut i64; /// /// let atom = AtomicPtr::::new(pointer); /// // Tag the bottom bit of the pointer. /// assert!(!atom.bit_set(0, Ordering::Relaxed)); /// // Extract and untag. /// let tagged = atom.load(Ordering::Relaxed); /// assert_eq!(tagged.addr() & 1, 1); /// assert_eq!(tagged.map_addr(|p| p & !1), pointer); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_set(&self, bit: u32, order: Ordering) -> bool { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); self.fetch_or(mask, order) as usize & mask != 0 } #[cfg(not(miri))] { self.as_atomic_usize().bit_set(bit, order) } } /// Clears the bit at the specified bit-position to 1. /// /// Returns `true` if the specified bit was previously set to 1. /// /// `bit_clear` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This corresponds to x86's `lock btr`, and the implementation calls them on x86/x86_64. /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let pointer = &mut 3i64 as *mut i64; /// // A tagged pointer /// let atom = AtomicPtr::::new(pointer.map_addr(|a| a | 1)); /// assert!(atom.bit_set(0, Ordering::Relaxed)); /// // Untag /// assert!(atom.bit_clear(0, Ordering::Relaxed)); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); self.fetch_and(!mask, order) as usize & mask != 0 } #[cfg(not(miri))] { self.as_atomic_usize().bit_clear(bit, order) } } /// Toggles the bit at the specified bit-position. /// /// Returns `true` if the specified bit was previously set to 1. /// /// `bit_toggle` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. /// /// This corresponds to x86's `lock btc`, and the implementation calls them on x86/x86_64. /// /// # Examples /// /// ``` /// # #![allow(unstable_name_collisions)] /// use portable_atomic::{AtomicPtr, Ordering}; /// use sptr::Strict; // stable polyfill for strict provenance /// /// let pointer = &mut 3i64 as *mut i64; /// let atom = AtomicPtr::::new(pointer); /// /// // Toggle a tag bit on the pointer. /// atom.bit_toggle(0, Ordering::Relaxed); /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool { // Ideally, we would always use AtomicPtr::fetch_* since it is strict-provenance // compatible, but it is unstable. So, for now emulate it only on cfg(miri). // Code using AtomicUsize::fetch_* via casts is still permissive-provenance // compatible and is sound. // TODO: Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, // use AtomicPtr::fetch_* in all cases from the version in which it is stabilized. #[cfg(miri)] { let mask = 1_usize.wrapping_shl(bit); self.fetch_xor(mask, order) as usize & mask != 0 } #[cfg(not(miri))] { self.as_atomic_usize().bit_toggle(bit, order) } } #[cfg(not(miri))] #[inline] fn as_atomic_usize(&self) -> &AtomicUsize { static_assert!( core::mem::size_of::>() == core::mem::size_of::() ); static_assert!( core::mem::align_of::>() == core::mem::align_of::() ); // SAFETY: AtomicPtr and AtomicUsize have the same layout, // and both access data in the same way. unsafe { &*(self as *const Self as *const AtomicUsize) } } } // cfg_has_atomic_cas! const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying pointer. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut *mut T { self.inner.as_ptr() } } } } // cfg_has_atomic_ptr! macro_rules! atomic_int { // TODO: support AtomicF{16,128} once https://github.com/rust-lang/rust/issues/116909 stabilized. (AtomicU32, $int_type:ident, $align:literal) => { atomic_int!(int, AtomicU32, $int_type, $align); #[cfg(feature = "float")] atomic_int!(float, AtomicF32, f32, AtomicU32, $int_type, $align); }; (AtomicU64, $int_type:ident, $align:literal) => { atomic_int!(int, AtomicU64, $int_type, $align); #[cfg(feature = "float")] atomic_int!(float, AtomicF64, f64, AtomicU64, $int_type, $align); }; ($atomic_type:ident, $int_type:ident, $align:literal) => { atomic_int!(int, $atomic_type, $int_type, $align); }; // Atomic{I,U}* impls (int, $atomic_type:ident, $int_type:ident, $align:literal) => { doc_comment! { concat!("An integer type which can be safely shared between threads. This type has the same in-memory representation as the underlying integer type, [`", stringify!($int_type), "`]. If the compiler and the platform support atomic loads and stores of [`", stringify!($int_type), "`], this type is a wrapper for the standard library's `", stringify!($atomic_type), "`. If the platform supports it but the compiler does not, atomic operations are implemented using inline assembly. Otherwise synchronizes using global locks. You can call [`", stringify!($atomic_type), "::is_lock_free()`] to check whether atomic instructions or locks will be used. " ), // We can use #[repr(transparent)] here, but #[repr(C, align(N))] // will show clearer docs. #[repr(C, align($align))] pub struct $atomic_type { inner: imp::$atomic_type, } } impl Default for $atomic_type { #[inline] fn default() -> Self { Self::new($int_type::default()) } } impl From<$int_type> for $atomic_type { #[inline] fn from(v: $int_type) -> Self { Self::new(v) } } // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for $atomic_type {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for $atomic_type {} impl_debug_and_serde!($atomic_type); impl $atomic_type { doc_comment! { concat!( "Creates a new atomic integer. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; let atomic_forty_two = ", stringify!($atomic_type), "::new(42); ```" ), #[inline] #[must_use] pub const fn new(v: $int_type) -> Self { static_assert_layout!($atomic_type, $int_type); Self { inner: imp::$atomic_type::new(v) } } } doc_comment! { concat!("Creates a new reference to an atomic integer from a pointer. # Safety * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`). * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value behind `ptr` must have a happens-before relationship with atomic accesses via the returned value (or vice-versa). * In other words, time periods where the value is accessed atomically may not overlap with periods where the value is accessed non-atomically. * This requirement is trivially satisfied if `ptr` is never used non-atomically for the duration of lifetime `'a`. Most use cases should be able to follow this guideline. * This requirement is also trivially satisfied if all accesses (atomic or not) are done from the same thread. * If this atomic type is *not* lock-free: * Any accesses to the value behind `ptr` must have a happens-before relationship with accesses via the returned value (or vice-versa). * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must be compatible with operations performed by this atomic type. * This method must not be used to create overlapping or mixed-size atomic accesses, as these are not supported by the memory model. [valid]: core::ptr#safety"), #[inline] #[must_use] pub unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } doc_comment! { concat!("Returns `true` if operations on values of this type are lock-free. If the compiler or the platform doesn't support the necessary atomic instructions, global locks for every potentially concurrent atomic operation will be used. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; let is_lock_free = ", stringify!($atomic_type), "::is_lock_free(); ```"), #[inline] #[must_use] pub fn is_lock_free() -> bool { ::is_lock_free() } } doc_comment! { concat!("Returns `true` if operations on values of this type are lock-free. If the compiler or the platform doesn't support the necessary atomic instructions, global locks for every potentially concurrent atomic operation will be used. **Note:** If the atomic operation relies on dynamic CPU feature detection, this type may be lock-free even if the function returns false. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; const IS_ALWAYS_LOCK_FREE: bool = ", stringify!($atomic_type), "::is_always_lock_free(); ```"), #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { ::is_always_lock_free() } } doc_comment! { concat!("Returns a mutable reference to the underlying integer.\n This is safe because the mutable reference guarantees that no other threads are concurrently accessing the atomic data. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let mut some_var = ", stringify!($atomic_type), "::new(10); assert_eq!(*some_var.get_mut(), 10); *some_var.get_mut() = 5; assert_eq!(some_var.load(Ordering::SeqCst), 5); ```"), #[inline] pub fn get_mut(&mut self) -> &mut $int_type { self.inner.get_mut() } } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 doc_comment! { concat!("Consumes the atomic and returns the contained value. This is safe because passing `self` by value guarantees that no other threads are concurrently accessing the atomic data. # Examples ``` use portable_atomic::", stringify!($atomic_type), "; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!(some_var.into_inner(), 5); ```"), #[inline] pub fn into_inner(self) -> $int_type { self.inner.into_inner() } } doc_comment! { concat!("Loads a value from the atomic integer. `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. # Panics Panics if `order` is [`Release`] or [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!(some_var.load(Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> $int_type { self.inner.load(order) } } doc_comment! { concat!("Stores a value into the atomic integer. `store` takes an [`Ordering`] argument which describes the memory ordering of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. # Panics Panics if `order` is [`Acquire`] or [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); some_var.store(10, Ordering::Relaxed); assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, val: $int_type, order: Ordering) { self.inner.store(val, order) } } cfg_has_atomic_cas! { doc_comment! { concat!("Stores a value into the atomic integer, returning the previous value. `swap` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.swap(val, order) } } doc_comment! { concat!("Stores a value into the atomic integer if the current value is the same as the `current` value. The return value is a result indicating whether the new value was written and containing the previous value. On success this value is guaranteed to be equal to `current`. `compare_exchange` takes two [`Ordering`] arguments to describe the memory ordering of this operation. `success` describes the required ordering for the read-modify-write operation that takes place if the comparison with `current` succeeds. `failure` describes the required ordering for the load operation that takes place when the comparison fails. Using [`Acquire`] as success ordering makes the store part of this operation [`Relaxed`], and using [`Release`] makes the successful load [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. # Panics Panics if `failure` is [`Release`], [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let some_var = ", stringify!($atomic_type), "::new(5); assert_eq!( some_var.compare_exchange(5, 10, Ordering::Acquire, Ordering::Relaxed), Ok(5), ); assert_eq!(some_var.load(Ordering::Relaxed), 10); assert_eq!( some_var.compare_exchange(6, 12, Ordering::SeqCst, Ordering::Acquire), Err(10), ); assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.inner.compare_exchange(current, new, success, failure) } } doc_comment! { concat!("Stores a value into the atomic integer if the current value is the same as the `current` value. Unlike [`compare_exchange`](Self::compare_exchange) this function is allowed to spuriously fail even when the comparison succeeds, which can result in more efficient code on some platforms. The return value is a result indicating whether the new value was written and containing the previous value. `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory ordering of this operation. `success` describes the required ordering for the read-modify-write operation that takes place if the comparison with `current` succeeds. `failure` describes the required ordering for the load operation that takes place when the comparison fails. Using [`Acquire`] as success ordering makes the store part of this operation [`Relaxed`], and using [`Release`] makes the successful load [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. # Panics Panics if `failure` is [`Release`], [`AcqRel`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let val = ", stringify!($atomic_type), "::new(4); let mut old = val.load(Ordering::Relaxed); loop { let new = old * 2; match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) { Ok(_) => break, Err(x) => old = x, } } ```"), #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: $int_type, new: $int_type, success: Ordering, failure: Ordering, ) -> Result<$int_type, $int_type> { self.inner.compare_exchange_weak(current, new, success, failure) } } doc_comment! { concat!("Adds to the current value, returning the previous value. This operation wraps around on overflow. `fetch_add` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_add(val, order) } } doc_comment! { concat!("Adds to the current value. This operation wraps around on overflow. Unlike `fetch_add`, this does not return the previous value. `add` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_add` on some platforms. - MSP430: `add` instead of disabling interrupts ({8,16}-bit atomics) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); foo.add(10, Ordering::SeqCst); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn add(&self, val: $int_type, order: Ordering) { self.inner.add(val, order); } } doc_comment! { concat!("Subtracts from the current value, returning the previous value. This operation wraps around on overflow. `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(20); assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_sub(val, order) } } doc_comment! { concat!("Subtracts from the current value. This operation wraps around on overflow. Unlike `fetch_sub`, this does not return the previous value. `sub` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_sub` on some platforms. - MSP430: `sub` instead of disabling interrupts ({8,16}-bit atomics) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(20); foo.sub(10, Ordering::SeqCst); assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn sub(&self, val: $int_type, order: Ordering) { self.inner.sub(val, order); } } doc_comment! { concat!("Bitwise \"and\" with the current value. Performs a bitwise \"and\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_and` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b100001); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_and(val, order) } } doc_comment! { concat!("Bitwise \"and\" with the current value. Performs a bitwise \"and\" operation on the current value and the argument `val`, and sets the new value to the result. Unlike `fetch_and`, this does not return the previous value. `and` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_and` on some platforms. - x86/x86_64: `lock and` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `and` instead of disabling interrupts ({8,16}-bit atomics) Note: On x86/x86_64, the use of either function should not usually affect the generated code, because LLVM can properly optimize the case where the result is unused. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b100001); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn and(&self, val: $int_type, order: Ordering) { self.inner.and(val, order); } } doc_comment! { concat!("Bitwise \"nand\" with the current value. Performs a bitwise \"nand\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0x13); assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13); assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_nand(val, order) } } doc_comment! { concat!("Bitwise \"or\" with the current value. Performs a bitwise \"or\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_or` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b111111); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_or(val, order) } } doc_comment! { concat!("Bitwise \"or\" with the current value. Performs a bitwise \"or\" operation on the current value and the argument `val`, and sets the new value to the result. Unlike `fetch_or`, this does not return the previous value. `or` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_or` on some platforms. - x86/x86_64: `lock or` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `or` instead of disabling interrupts ({8,16}-bit atomics) Note: On x86/x86_64, the use of either function should not usually affect the generated code, because LLVM can properly optimize the case where the result is unused. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b111111); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn or(&self, val: $int_type, order: Ordering) { self.inner.or(val, order); } } doc_comment! { concat!("Bitwise \"xor\" with the current value. Performs a bitwise \"xor\" operation on the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101); assert_eq!(foo.load(Ordering::SeqCst), 0b011110); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_xor(val, order) } } doc_comment! { concat!("Bitwise \"xor\" with the current value. Performs a bitwise \"xor\" operation on the current value and the argument `val`, and sets the new value to the result. Unlike `fetch_xor`, this does not return the previous value. `xor` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_xor` on some platforms. - x86/x86_64: `lock xor` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `xor` instead of disabling interrupts ({8,16}-bit atomics) Note: On x86/x86_64, the use of either function should not usually affect the generated code, because LLVM can properly optimize the case where the result is unused. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b101101); foo.xor(0b110011, Ordering::SeqCst); assert_eq!(foo.load(Ordering::SeqCst), 0b011110); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn xor(&self, val: $int_type, order: Ordering) { self.inner.xor(val, order); } } doc_comment! { concat!("Fetches the value, and applies a function to it that returns an optional new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else `Err(previous_value)`. Note: This may call the function multiple times if the value has been changed from other threads in the meantime, as long as the function returns `Some(_)`, but the function will have been applied only once to the stored value. `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. The first describes the required ordering for when the operation finally succeeds while the second describes the required ordering for loads. These correspond to the success and failure orderings of [`compare_exchange`](Self::compare_exchange) respectively. Using [`Acquire`] as success ordering makes the store part of this operation [`Relaxed`], and using [`Release`] makes the final successful load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. # Panics Panics if `fetch_order` is [`Release`], [`AcqRel`]. # Considerations This method is not magic; it is not provided by the hardware. It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), and suffers from the same drawbacks. In particular, this method will not circumvent the [ABA Problem]. [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem # Examples ```rust use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let x = ", stringify!($atomic_type), "::new(7); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7)); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7)); assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); assert_eq!(x.load(Ordering::SeqCst), 9); ```"), #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result<$int_type, $int_type> where F: FnMut($int_type) -> Option<$int_type>, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } } doc_comment! { concat!("Maximum with the current value. Finds the maximum of the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_max` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23); assert_eq!(foo.load(Ordering::SeqCst), 42); ``` If you want to obtain the maximum value in one step, you can use the following: ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); let bar = 42; let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar); assert!(max_foo == 42); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_max(val, order) } } doc_comment! { concat!("Minimum with the current value. Finds the minimum of the current value and the argument `val`, and sets the new value to the result. Returns the previous value. `fetch_min` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23); assert_eq!(foo.load(Ordering::Relaxed), 23); assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23); assert_eq!(foo.load(Ordering::Relaxed), 22); ``` If you want to obtain the minimum value in one step, you can use the following: ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(23); let bar = 12; let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar); assert_eq!(min_foo, 12); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { self.inner.fetch_min(val, order) } } doc_comment! { concat!("Sets the bit at the specified bit-position to 1. Returns `true` if the specified bit was previously set to 1. `bit_set` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This corresponds to x86's `lock bts`, and the implementation calls them on x86/x86_64. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b0000); assert!(!foo.bit_set(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0001); assert!(foo.bit_set(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0001); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_set(&self, bit: u32, order: Ordering) -> bool { self.inner.bit_set(bit, order) } } doc_comment! { concat!("Clears the bit at the specified bit-position to 1. Returns `true` if the specified bit was previously set to 1. `bit_clear` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This corresponds to x86's `lock btr`, and the implementation calls them on x86/x86_64. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b0001); assert!(foo.bit_clear(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0000); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool { self.inner.bit_clear(bit, order) } } doc_comment! { concat!("Toggles the bit at the specified bit-position. Returns `true` if the specified bit was previously set to 1. `bit_toggle` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This corresponds to x86's `lock btc`, and the implementation calls them on x86/x86_64. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0b0000); assert!(!foo.bit_toggle(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0001); assert!(foo.bit_toggle(0, Ordering::Relaxed)); assert_eq!(foo.load(Ordering::Relaxed), 0b0000); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool { self.inner.bit_toggle(bit, order) } } doc_comment! { concat!("Logical negates the current value, and sets the new value to the result. Returns the previous value. `fetch_not` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); assert_eq!(foo.fetch_not(Ordering::Relaxed), 0); assert_eq!(foo.load(Ordering::Relaxed), !0); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_not(&self, order: Ordering) -> $int_type { self.inner.fetch_not(order) } doc_comment! { concat!("Logical negates the current value, and sets the new value to the result. Unlike `fetch_not`, this does not return the previous value. `not` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_not` on some platforms. - x86/x86_64: `lock not` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) - MSP430: `inv` instead of disabling interrupts ({8,16}-bit atomics) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(0); foo.not(Ordering::Relaxed); assert_eq!(foo.load(Ordering::Relaxed), !0); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn not(&self, order: Ordering) { self.inner.not(order); } } } doc_comment! { concat!("Negates the current value, and sets the new value to the result. Returns the previous value. `fetch_neg` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(5); assert_eq!(foo.fetch_neg(Ordering::Relaxed), 5); assert_eq!(foo.load(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg()); assert_eq!(foo.fetch_neg(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg()); assert_eq!(foo.load(Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_neg(&self, order: Ordering) -> $int_type { self.inner.fetch_neg(order) } doc_comment! { concat!("Negates the current value, and sets the new value to the result. Unlike `fetch_neg`, this does not return the previous value. `neg` takes an [`Ordering`] argument which describes the memory ordering of this operation. All ordering modes are possible. Note that using [`Acquire`] makes the store part of this operation [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`]. This function may generate more efficient code than `fetch_neg` on some platforms. - x86/x86_64: `lock neg` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64) # Examples ``` use portable_atomic::{", stringify!($atomic_type), ", Ordering}; let foo = ", stringify!($atomic_type), "::new(5); foo.neg(Ordering::Relaxed); assert_eq!(foo.load(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg()); foo.neg(Ordering::Relaxed); assert_eq!(foo.load(Ordering::Relaxed), 5); ```"), #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn neg(&self, order: Ordering) { self.inner.neg(order); } } } } // cfg_has_atomic_cas! const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying integer. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut $int_type { self.inner.as_ptr() } } } }; // AtomicF* impls (float, $atomic_type:ident, $float_type:ident, $atomic_int_type:ident, $int_type:ident, $align:literal ) => { doc_comment! { concat!("A floating point type which can be safely shared between threads. This type has the same in-memory representation as the underlying floating point type, [`", stringify!($float_type), "`]. " ), #[cfg_attr(portable_atomic_doc_cfg, doc(cfg(feature = "float")))] // We can use #[repr(transparent)] here, but #[repr(C, align(N))] // will show clearer docs. #[repr(C, align($align))] pub struct $atomic_type { inner: imp::float::$atomic_type, } } impl Default for $atomic_type { #[inline] fn default() -> Self { Self::new($float_type::default()) } } impl From<$float_type> for $atomic_type { #[inline] fn from(v: $float_type) -> Self { Self::new(v) } } // UnwindSafe is implicitly implemented. #[cfg(not(portable_atomic_no_core_unwind_safe))] impl core::panic::RefUnwindSafe for $atomic_type {} #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))] impl std::panic::RefUnwindSafe for $atomic_type {} impl_debug_and_serde!($atomic_type); impl $atomic_type { /// Creates a new atomic float. #[inline] #[must_use] pub const fn new(v: $float_type) -> Self { static_assert_layout!($atomic_type, $float_type); Self { inner: imp::float::$atomic_type::new(v) } } doc_comment! { concat!("Creates a new reference to an atomic float from a pointer. # Safety * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($float_type), ">()`). * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`. * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value behind `ptr` must have a happens-before relationship with atomic accesses via the returned value (or vice-versa). * In other words, time periods where the value is accessed atomically may not overlap with periods where the value is accessed non-atomically. * This requirement is trivially satisfied if `ptr` is never used non-atomically for the duration of lifetime `'a`. Most use cases should be able to follow this guideline. * This requirement is also trivially satisfied if all accesses (atomic or not) are done from the same thread. * If this atomic type is *not* lock-free: * Any accesses to the value behind `ptr` must have a happens-before relationship with accesses via the returned value (or vice-versa). * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must be compatible with operations performed by this atomic type. * This method must not be used to create overlapping or mixed-size atomic accesses, as these are not supported by the memory model. [valid]: core::ptr#safety"), #[inline] #[must_use] pub unsafe fn from_ptr<'a>(ptr: *mut $float_type) -> &'a Self { #[allow(clippy::cast_ptr_alignment)] // SAFETY: guaranteed by the caller unsafe { &*(ptr as *mut Self) } } } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. #[inline] #[must_use] pub fn is_lock_free() -> bool { ::is_lock_free() } /// Returns `true` if operations on values of this type are lock-free. /// /// If the compiler or the platform doesn't support the necessary /// atomic instructions, global locks for every potentially /// concurrent atomic operation will be used. /// /// **Note:** If the atomic operation relies on dynamic CPU feature detection, /// this type may be lock-free even if the function returns false. #[inline] #[must_use] pub const fn is_always_lock_free() -> bool { ::is_always_lock_free() } /// Returns a mutable reference to the underlying float. /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. #[inline] pub fn get_mut(&mut self) -> &mut $float_type { self.inner.get_mut() } // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types. // https://github.com/rust-lang/rust/issues/76314 /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are /// concurrently accessing the atomic data. #[inline] pub fn into_inner(self) -> $float_type { self.inner.into_inner() } /// Loads a value from the atomic float. /// /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation. /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Release`] or [`AcqRel`]. #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn load(&self, order: Ordering) -> $float_type { self.inner.load(order) } /// Stores a value into the atomic float. /// /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation. /// Possible values are [`SeqCst`], [`Release`] and [`Relaxed`]. /// /// # Panics /// /// Panics if `order` is [`Acquire`] or [`AcqRel`]. #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn store(&self, val: $float_type, order: Ordering) { self.inner.store(val, order) } cfg_has_atomic_cas! { /// Stores a value into the atomic float, returning the previous value. /// /// `swap` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn swap(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.swap(val, order) } /// Stores a value into the atomic float if the current value is the same as /// the `current` value. /// /// The return value is a result indicating whether the new value was written and /// containing the previous value. On success this value is guaranteed to be equal to /// `current`. /// /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { self.inner.compare_exchange(current, new, success, failure) } /// Stores a value into the atomic float if the current value is the same as /// the `current` value. /// Unlike [`compare_exchange`](Self::compare_exchange) /// this function is allowed to spuriously fail even /// when the comparison succeeds, which can result in more efficient code on some /// platforms. The return value is a result indicating whether the new value was /// written and containing the previous value. /// /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory /// ordering of this operation. `success` describes the required ordering for the /// read-modify-write operation that takes place if the comparison with `current` succeeds. /// `failure` describes the required ordering for the load operation that takes place when /// the comparison fails. Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the successful load /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `failure` is [`Release`], [`AcqRel`]. #[inline] #[cfg_attr(portable_atomic_doc_cfg, doc(alias = "compare_and_swap"))] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn compare_exchange_weak( &self, current: $float_type, new: $float_type, success: Ordering, failure: Ordering, ) -> Result<$float_type, $float_type> { self.inner.compare_exchange_weak(current, new, success, failure) } /// Adds to the current value, returning the previous value. /// /// This operation wraps around on overflow. /// /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_add(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_add(val, order) } /// Subtracts from the current value, returning the previous value. /// /// This operation wraps around on overflow. /// /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_sub(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_sub(val, order) } /// Fetches the value, and applies a function to it that returns an optional /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else /// `Err(previous_value)`. /// /// Note: This may call the function multiple times if the value has been changed from other threads in /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied /// only once to the stored value. /// /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation. /// The first describes the required ordering for when the operation finally succeeds while the second /// describes the required ordering for loads. These correspond to the success and failure orderings of /// [`compare_exchange`](Self::compare_exchange) respectively. /// /// Using [`Acquire`] as success ordering makes the store part /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`]. /// /// # Panics /// /// Panics if `fetch_order` is [`Release`], [`AcqRel`]. /// /// # Considerations /// /// This method is not magic; it is not provided by the hardware. /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak), /// and suffers from the same drawbacks. /// In particular, this method will not circumvent the [ABA Problem]. /// /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem #[inline] #[cfg_attr( any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri), track_caller )] pub fn fetch_update( &self, set_order: Ordering, fetch_order: Ordering, mut f: F, ) -> Result<$float_type, $float_type> where F: FnMut($float_type) -> Option<$float_type>, { let mut prev = self.load(fetch_order); while let Some(next) = f(prev) { match self.compare_exchange_weak(prev, next, set_order, fetch_order) { x @ Ok(_) => return x, Err(next_prev) => prev = next_prev, } } Err(prev) } /// Maximum with the current value. /// /// Finds the maximum of the current value and the argument `val`, and /// sets the new value to the result. /// /// Returns the previous value. /// /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_max(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_max(val, order) } /// Minimum with the current value. /// /// Finds the minimum of the current value and the argument `val`, and /// sets the new value to the result. /// /// Returns the previous value. /// /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_min(&self, val: $float_type, order: Ordering) -> $float_type { self.inner.fetch_min(val, order) } /// Negates the current value, and sets the new value to the result. /// /// Returns the previous value. /// /// `fetch_neg` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_neg(&self, order: Ordering) -> $float_type { self.inner.fetch_neg(order) } /// Computes the absolute value of the current value, and sets the /// new value to the result. /// /// Returns the previous value. /// /// `fetch_abs` takes an [`Ordering`] argument which describes the memory ordering /// of this operation. All ordering modes are possible. Note that using /// [`Acquire`] makes the store part of this operation [`Relaxed`], and /// using [`Release`] makes the load part [`Relaxed`]. #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_abs(&self, order: Ordering) -> $float_type { self.inner.fetch_abs(order) } } // cfg_has_atomic_cas! #[cfg(not(portable_atomic_no_const_raw_ptr_deref))] doc_comment! { concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`. See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the portability of this operation (there are almost no issues). This is `const fn` on Rust 1.58+."), #[inline] pub const fn as_bits(&self) -> &$atomic_int_type { self.inner.as_bits() } } #[cfg(portable_atomic_no_const_raw_ptr_deref)] doc_comment! { concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`. See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the portability of this operation (there are almost no issues). This is `const fn` on Rust 1.58+."), #[inline] pub fn as_bits(&self) -> &$atomic_int_type { self.inner.as_bits() } } const_fn! { const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]; /// Returns a mutable pointer to the underlying float. /// /// Returning an `*mut` pointer from a shared reference to this atomic is /// safe because the atomic types work with interior mutability. Any use of /// the returned raw pointer requires an `unsafe` block and has to uphold /// the safety requirements. If there is concurrent access, note the following /// additional safety requirements: /// /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent /// operations on it must be atomic. /// - Otherwise, any concurrent operations on it must be compatible with /// operations performed by this atomic type. /// /// This is `const fn` on Rust 1.58+. #[inline] pub const fn as_ptr(&self) -> *mut $float_type { self.inner.as_ptr() } } } }; } cfg_has_atomic_ptr! { #[cfg(target_pointer_width = "16")] atomic_int!(AtomicIsize, isize, 2); #[cfg(target_pointer_width = "16")] atomic_int!(AtomicUsize, usize, 2); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicIsize, isize, 4); #[cfg(target_pointer_width = "32")] atomic_int!(AtomicUsize, usize, 4); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicIsize, isize, 8); #[cfg(target_pointer_width = "64")] atomic_int!(AtomicUsize, usize, 8); #[cfg(target_pointer_width = "128")] atomic_int!(AtomicIsize, isize, 16); #[cfg(target_pointer_width = "128")] atomic_int!(AtomicUsize, usize, 16); } cfg_has_atomic_8! { atomic_int!(AtomicI8, i8, 1); atomic_int!(AtomicU8, u8, 1); } cfg_has_atomic_16! { atomic_int!(AtomicI16, i16, 2); atomic_int!(AtomicU16, u16, 2); } cfg_has_atomic_32! { atomic_int!(AtomicI32, i32, 4); atomic_int!(AtomicU32, u32, 4); } cfg_has_atomic_64! { atomic_int!(AtomicI64, i64, 8); atomic_int!(AtomicU64, u64, 8); } cfg_has_atomic_128! { atomic_int!(AtomicI128, i128, 16); atomic_int!(AtomicU128, u128, 16); } portable-atomic/src/utils.rs0000644000175000017500000004112314661133735017121 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT #![cfg_attr(not(all(test, feature = "float")), allow(dead_code, unused_macros))] #[macro_use] #[path = "gen/utils.rs"] mod gen; use core::sync::atomic::Ordering; macro_rules! static_assert { ($cond:expr $(,)?) => {{ let [] = [(); true as usize - $crate::utils::_assert_is_bool($cond) as usize]; }}; } pub(crate) const fn _assert_is_bool(v: bool) -> bool { v } macro_rules! static_assert_layout { ($atomic_type:ty, $value_type:ty) => { static_assert!( core::mem::align_of::<$atomic_type>() == core::mem::size_of::<$atomic_type>() ); static_assert!(core::mem::size_of::<$atomic_type>() == core::mem::size_of::<$value_type>()); }; } // #[doc = concat!(...)] requires Rust 1.54 macro_rules! doc_comment { ($doc:expr, $($tt:tt)*) => { #[doc = $doc] $($tt)* }; } // Adapted from https://github.com/BurntSushi/memchr/blob/2.4.1/src/memchr/x86/mod.rs#L9-L71. /// # Safety /// /// - the caller must uphold the safety contract for the function returned by $detect_body. /// - the memory pointed by the function pointer returned by $detect_body must be visible from any threads. /// /// The second requirement is always met if the function pointer is to the function definition. /// (Currently, all uses of this macro in our code are in this case.) #[allow(unused_macros)] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc64", all(target_arch = "x86_64", not(any(target_env = "sgx", miri))), ))] macro_rules! ifunc { (unsafe fn($($arg_pat:ident: $arg_ty:ty),*) $(-> $ret_ty:ty)? { $($detect_body:tt)* }) => {{ type FnTy = unsafe fn($($arg_ty),*) $(-> $ret_ty)?; static FUNC: core::sync::atomic::AtomicPtr<()> = core::sync::atomic::AtomicPtr::new(detect as *mut ()); #[cold] unsafe fn detect($($arg_pat: $arg_ty),*) $(-> $ret_ty)? { let func: FnTy = { $($detect_body)* }; FUNC.store(func as *mut (), core::sync::atomic::Ordering::Relaxed); // SAFETY: the caller must uphold the safety contract for the function returned by $detect_body. unsafe { func($($arg_pat),*) } } // SAFETY: `FnTy` is a function pointer, which is always safe to transmute with a `*mut ()`. // (To force the caller to use unsafe block for this macro, do not use // unsafe block here.) let func = { core::mem::transmute::<*mut (), FnTy>(FUNC.load(core::sync::atomic::Ordering::Relaxed)) }; // SAFETY: the caller must uphold the safety contract for the function returned by $detect_body. // (To force the caller to use unsafe block for this macro, do not use // unsafe block here.) func($($arg_pat),*) }}; } #[allow(unused_macros)] #[cfg(not(portable_atomic_no_outline_atomics))] #[cfg(any( target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc64", all(target_arch = "x86_64", not(any(target_env = "sgx", miri))), ))] macro_rules! fn_alias { ( $(#[$($fn_attr:tt)*])* $vis:vis unsafe fn($($arg_pat:ident: $arg_ty:ty),*) $(-> $ret_ty:ty)?; $(#[$($alias_attr:tt)*])* $new:ident = $from:ident($($last_args:tt)*); $($rest:tt)* ) => { $(#[$($fn_attr)*])* $(#[$($alias_attr)*])* $vis unsafe fn $new($($arg_pat: $arg_ty),*) $(-> $ret_ty)? { // SAFETY: the caller must uphold the safety contract. unsafe { $from($($arg_pat,)* $($last_args)*) } } fn_alias! { $(#[$($fn_attr)*])* $vis unsafe fn($($arg_pat: $arg_ty),*) $(-> $ret_ty)?; $($rest)* } }; ( $(#[$($attr:tt)*])* $vis:vis unsafe fn($($arg_pat:ident: $arg_ty:ty),*) $(-> $ret_ty:ty)?; ) => {} } /// Make the given function const if the given condition is true. macro_rules! const_fn { ( const_if: #[cfg($($cfg:tt)+)]; $(#[$($attr:tt)*])* $vis:vis const fn $($rest:tt)* ) => { #[cfg($($cfg)+)] $(#[$($attr)*])* $vis const fn $($rest)* #[cfg(not($($cfg)+))] $(#[$($attr)*])* $vis fn $($rest)* }; } /// Implements `core::fmt::Debug` and `serde::{Serialize, Deserialize}` (when serde /// feature is enabled) for atomic bool, integer, or float. macro_rules! impl_debug_and_serde { ($atomic_type:ident) => { impl fmt::Debug for $atomic_type { #[allow(clippy::missing_inline_in_public_items)] // fmt is not hot path fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L2024 fmt::Debug::fmt(&self.load(Ordering::Relaxed), f) } } #[cfg(feature = "serde")] #[cfg_attr(portable_atomic_doc_cfg, doc(cfg(feature = "serde")))] impl serde::ser::Serialize for $atomic_type { #[allow(clippy::missing_inline_in_public_items)] // serde doesn't use inline on std atomic's Serialize/Deserialize impl fn serialize(&self, serializer: S) -> Result where S: serde::ser::Serializer, { // https://github.com/serde-rs/serde/blob/v1.0.152/serde/src/ser/impls.rs#L958-L959 self.load(Ordering::Relaxed).serialize(serializer) } } #[cfg(feature = "serde")] #[cfg_attr(portable_atomic_doc_cfg, doc(cfg(feature = "serde")))] impl<'de> serde::de::Deserialize<'de> for $atomic_type { #[allow(clippy::missing_inline_in_public_items)] // serde doesn't use inline on std atomic's Serialize/Deserialize impl fn deserialize(deserializer: D) -> Result where D: serde::de::Deserializer<'de>, { serde::de::Deserialize::deserialize(deserializer).map(Self::new) } } }; } // We do not provide `nand` because it cannot be optimized on neither x86 nor MSP430. // https://godbolt.org/z/7TzjKqYvE macro_rules! impl_default_no_fetch_ops { ($atomic_type:ident, bool) => { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn and(&self, val: bool, order: Ordering) { self.fetch_and(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn or(&self, val: bool, order: Ordering) { self.fetch_or(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn xor(&self, val: bool, order: Ordering) { self.fetch_xor(val, order); } } }; ($atomic_type:ident, $int_type:ident) => { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn add(&self, val: $int_type, order: Ordering) { self.fetch_add(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn sub(&self, val: $int_type, order: Ordering) { self.fetch_sub(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn and(&self, val: $int_type, order: Ordering) { self.fetch_and(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn or(&self, val: $int_type, order: Ordering) { self.fetch_or(val, order); } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn xor(&self, val: $int_type, order: Ordering) { self.fetch_xor(val, order); } } }; } macro_rules! impl_default_bit_opts { ($atomic_type:ident, $int_type:ident) => { impl $atomic_type { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn bit_set(&self, bit: u32, order: Ordering) -> bool { let mask = <$int_type>::wrapping_shl(1, bit); self.fetch_or(mask, order) & mask != 0 } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn bit_clear(&self, bit: u32, order: Ordering) -> bool { let mask = <$int_type>::wrapping_shl(1, bit); self.fetch_and(!mask, order) & mask != 0 } #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub(crate) fn bit_toggle(&self, bit: u32, order: Ordering) -> bool { let mask = <$int_type>::wrapping_shl(1, bit); self.fetch_xor(mask, order) & mask != 0 } } }; } // This just outputs the input as is, but can be used like an item-level block by using it with cfg. macro_rules! items { ($($tt:tt)*) => { $($tt)* }; } // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L3155 #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn assert_load_ordering(order: Ordering) { match order { Ordering::Acquire | Ordering::Relaxed | Ordering::SeqCst => {} Ordering::Release => panic!("there is no such thing as a release load"), Ordering::AcqRel => panic!("there is no such thing as an acquire-release load"), _ => unreachable!("{:?}", order), } } // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L3140 #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn assert_store_ordering(order: Ordering) { match order { Ordering::Release | Ordering::Relaxed | Ordering::SeqCst => {} Ordering::Acquire => panic!("there is no such thing as an acquire store"), Ordering::AcqRel => panic!("there is no such thing as an acquire-release store"), _ => unreachable!("{:?}", order), } } // https://github.com/rust-lang/rust/blob/1.70.0/library/core/src/sync/atomic.rs#L3221 #[inline] #[cfg_attr(all(debug_assertions, not(portable_atomic_no_track_caller)), track_caller)] pub(crate) fn assert_compare_exchange_ordering(success: Ordering, failure: Ordering) { match success { Ordering::AcqRel | Ordering::Acquire | Ordering::Relaxed | Ordering::Release | Ordering::SeqCst => {} _ => unreachable!("{:?}, {:?}", success, failure), } match failure { Ordering::Acquire | Ordering::Relaxed | Ordering::SeqCst => {} Ordering::Release => panic!("there is no such thing as a release failure ordering"), Ordering::AcqRel => panic!("there is no such thing as an acquire-release failure ordering"), _ => unreachable!("{:?}, {:?}", success, failure), } } // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0418r2.html // https://github.com/rust-lang/rust/pull/98383 #[allow(dead_code)] #[inline] pub(crate) fn upgrade_success_ordering(success: Ordering, failure: Ordering) -> Ordering { match (success, failure) { (Ordering::Relaxed, Ordering::Acquire) => Ordering::Acquire, (Ordering::Release, Ordering::Acquire) => Ordering::AcqRel, (_, Ordering::SeqCst) => Ordering::SeqCst, _ => success, } } /// Zero-extends the given 32-bit pointer to `MaybeUninit`. /// This is used for 64-bit architecture's 32-bit ABI (e.g., AArch64 ILP32 ABI). /// See ptr_reg! macro in src/gen/utils.rs for details. #[cfg(not(portable_atomic_no_asm_maybe_uninit))] #[cfg(target_pointer_width = "32")] #[allow(dead_code)] #[inline] pub(crate) fn zero_extend64_ptr(v: *mut ()) -> core::mem::MaybeUninit { #[repr(C)] struct ZeroExtended { #[cfg(target_endian = "big")] pad: *mut (), v: *mut (), #[cfg(target_endian = "little")] pad: *mut (), } // SAFETY: we can safely transmute any 64-bit value to MaybeUninit. unsafe { core::mem::transmute(ZeroExtended { v, pad: core::ptr::null_mut() }) } } #[allow(dead_code)] #[cfg(any( target_arch = "aarch64", target_arch = "powerpc64", target_arch = "s390x", target_arch = "x86_64", ))] /// A 128-bit value represented as a pair of 64-bit values. /// /// This type is `#[repr(C)]`, both fields have the same in-memory representation /// and are plain old data types, so access to the fields is always safe. #[derive(Clone, Copy)] #[repr(C)] pub(crate) union U128 { pub(crate) whole: u128, pub(crate) pair: Pair, } #[allow(dead_code)] #[cfg(target_arch = "arm")] /// A 64-bit value represented as a pair of 32-bit values. /// /// This type is `#[repr(C)]`, both fields have the same in-memory representation /// and are plain old data types, so access to the fields is always safe. #[derive(Clone, Copy)] #[repr(C)] pub(crate) union U64 { pub(crate) whole: u64, pub(crate) pair: Pair, } #[allow(dead_code)] #[derive(Clone, Copy)] #[repr(C)] pub(crate) struct Pair { // little endian order #[cfg(any(target_endian = "little", target_arch = "aarch64", target_arch = "arm"))] pub(crate) lo: T, pub(crate) hi: T, // big endian order #[cfg(not(any(target_endian = "little", target_arch = "aarch64", target_arch = "arm")))] pub(crate) lo: T, } #[allow(dead_code)] type MinWord = u32; #[cfg(target_arch = "riscv32")] type RegSize = u32; #[cfg(target_arch = "riscv64")] type RegSize = u64; // Adapted from https://github.com/taiki-e/atomic-maybe-uninit/blob/v0.3.0/src/utils.rs#L210. // Helper for implementing sub-word atomic operations using word-sized LL/SC loop or CAS loop. // // Refs: https://github.com/llvm/llvm-project/blob/llvmorg-17.0.0-rc2/llvm/lib/CodeGen/AtomicExpandPass.cpp#L699 // (aligned_ptr, shift, mask) #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] #[allow(dead_code)] #[inline] pub(crate) fn create_sub_word_mask_values(ptr: *mut T) -> (*mut MinWord, RegSize, RegSize) { use core::mem; const SHIFT_MASK: bool = !cfg!(any( target_arch = "riscv32", target_arch = "riscv64", target_arch = "loongarch64", target_arch = "s390x", )); let ptr_mask = mem::size_of::() - 1; let aligned_ptr = strict::with_addr(ptr, ptr as usize & !ptr_mask) as *mut MinWord; let ptr_lsb = if SHIFT_MASK { ptr as usize & ptr_mask } else { // We use 32-bit wrapping shift instructions in asm on these platforms. ptr as usize }; let shift = if cfg!(any(target_endian = "little", target_arch = "s390x")) { ptr_lsb.wrapping_mul(8) } else { (ptr_lsb ^ (mem::size_of::() - mem::size_of::())).wrapping_mul(8) }; let mut mask: RegSize = (1 << (mem::size_of::() * 8)) - 1; // !(0 as T) as RegSize if SHIFT_MASK { mask <<= shift; } (aligned_ptr, shift as RegSize, mask) } /// Emulate strict provenance. /// /// Once strict_provenance is stable, migrate to the standard library's APIs. #[cfg(any(miri, target_arch = "riscv32", target_arch = "riscv64"))] #[allow(dead_code)] pub(crate) mod strict { /// Replace the address portion of this pointer with a new address. #[inline] #[must_use] pub(crate) fn with_addr(ptr: *mut T, addr: usize) -> *mut T { // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic. // // In the mean-time, this operation is defined to be "as if" it was // a wrapping_add, so we can emulate it as such. This should properly // restore pointer provenance even under today's compiler. let offset = addr.wrapping_sub(ptr as usize); // This is the canonical desugaring of this operation. (ptr as *mut u8).wrapping_add(offset) as *mut T } /// Run an operation of some kind on a pointer. #[inline] #[must_use] pub(crate) fn map_addr(ptr: *mut T, f: impl FnOnce(usize) -> usize) -> *mut T { with_addr(ptr, f(ptr as usize)) } } portable-atomic/src/tests/0000775000175000017500000000000014661133735016556 5ustar jamespagejamespageportable-atomic/src/tests/mod.rs0000644000175000017500000002637514661133735017716 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT #![allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks, clippy::wildcard_imports )] #[macro_use] pub(crate) mod helper; #[allow(dead_code)] #[path = "../../version.rs"] mod version; use super::*; test_atomic_bool_pub!(); test_atomic_ptr_pub!(); test_atomic_int_pub!(isize); test_atomic_int_pub!(usize); test_atomic_int_pub!(i8); test_atomic_int_pub!(u8); test_atomic_int_pub!(i16); test_atomic_int_pub!(u16); test_atomic_int_pub!(i32); test_atomic_int_pub!(u32); test_atomic_int_pub!(i64); test_atomic_int_pub!(u64); test_atomic_int_pub!(i128); test_atomic_int_pub!(u128); #[cfg(feature = "float")] test_atomic_float_pub!(f32); #[cfg(feature = "float")] test_atomic_float_pub!(f64); #[deny(improper_ctypes)] extern "C" { fn _atomic_bool_ffi_safety(_: AtomicBool); fn _atomic_ptr_ffi_safety(_: AtomicPtr); fn _atomic_isize_ffi_safety(_: AtomicIsize); fn _atomic_usize_ffi_safety(_: AtomicUsize); fn _atomic_i8_ffi_safety(_: AtomicI8); fn _atomic_u8_ffi_safety(_: AtomicU8); fn _atomic_i16_ffi_safety(_: AtomicI16); fn _atomic_u16_ffi_safety(_: AtomicU16); fn _atomic_i32_ffi_safety(_: AtomicI32); fn _atomic_u32_ffi_safety(_: AtomicU32); fn _atomic_i64_ffi_safety(_: AtomicI64); fn _atomic_u64_ffi_safety(_: AtomicU64); // TODO: 128-bit integers are not FFI safe // https://github.com/rust-lang/unsafe-code-guidelines/issues/119 // https://github.com/rust-lang/rust/issues/54341 // fn _atomic_i128_ffi_safety(_: AtomicI128); // fn _atomic_u128_ffi_safety(_: AtomicU128); #[cfg(feature = "float")] fn _atomic_f32_ffi_safety(_: AtomicF32); #[cfg(feature = "float")] fn _atomic_f64_ffi_safety(_: AtomicF64); } #[test] fn test_is_lock_free() { assert!(AtomicI8::is_always_lock_free()); assert!(AtomicI8::is_lock_free()); assert!(AtomicU8::is_always_lock_free()); assert!(AtomicU8::is_lock_free()); assert!(AtomicI16::is_always_lock_free()); assert!(AtomicI16::is_lock_free()); assert!(AtomicU16::is_always_lock_free()); assert!(AtomicU16::is_lock_free()); assert!(AtomicI32::is_always_lock_free()); assert!(AtomicI32::is_lock_free()); assert!(AtomicU32::is_always_lock_free()); assert!(AtomicU32::is_lock_free()); #[cfg(not(portable_atomic_no_cfg_target_has_atomic))] { if cfg!(all( feature = "fallback", target_arch = "arm", not(any(miri, portable_atomic_sanitize_thread)), not(portable_atomic_no_asm), any(target_os = "linux", target_os = "android"), not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), not(portable_atomic_no_outline_atomics), not(target_has_atomic = "64"), not(portable_atomic_test_outline_atomics_detect_false), )) { assert!(!AtomicI64::is_always_lock_free()); assert!(AtomicI64::is_lock_free()); assert!(!AtomicU64::is_always_lock_free()); assert!(AtomicU64::is_lock_free()); } else if cfg!(target_has_atomic = "64") { assert!(AtomicI64::is_always_lock_free()); assert!(AtomicI64::is_lock_free()); assert!(AtomicU64::is_always_lock_free()); assert!(AtomicU64::is_lock_free()); } else { assert!(!AtomicI64::is_always_lock_free()); assert!(!AtomicI64::is_lock_free()); assert!(!AtomicU64::is_always_lock_free()); assert!(!AtomicU64::is_lock_free()); } } if cfg!(portable_atomic_no_asm) && cfg!(not(portable_atomic_unstable_asm)) { assert!(!AtomicI128::is_always_lock_free()); assert!(!AtomicI128::is_lock_free()); assert!(!AtomicU128::is_always_lock_free()); assert!(!AtomicU128::is_lock_free()); } else if cfg!(any( target_arch = "aarch64", all( target_arch = "x86_64", any(target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b"), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", ), ), all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch), )) { assert!(AtomicI128::is_always_lock_free()); assert!(AtomicI128::is_lock_free()); assert!(AtomicU128::is_always_lock_free()); assert!(AtomicU128::is_lock_free()); } else { assert!(!AtomicI128::is_always_lock_free()); assert!(!AtomicU128::is_always_lock_free()); #[cfg(not(any(target_arch = "x86_64", target_arch = "powerpc64")))] { assert!(!AtomicI128::is_lock_free()); assert!(!AtomicU128::is_lock_free()); } #[cfg(target_arch = "x86_64")] { let has_cmpxchg16b = cfg!(all( feature = "fallback", not(portable_atomic_no_cmpxchg16b_target_feature), not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), not(portable_atomic_test_outline_atomics_detect_false), )) && std::is_x86_feature_detected!("cmpxchg16b"); assert_eq!(AtomicI128::is_lock_free(), has_cmpxchg16b); assert_eq!(AtomicU128::is_lock_free(), has_cmpxchg16b); } #[cfg(target_arch = "powerpc64")] { // TODO(powerpc64): is_powerpc_feature_detected is unstable } } } // test version parsing code used in the build script. #[test] fn test_rustc_version() { use version::Version; // rustc 1.34 (rustup) let v = Version::parse( "rustc 1.34.2 (6c2484dc3 2019-05-13) binary: rustc commit-hash: 6c2484dc3c532c052f159264e970278d8b77cdc9 commit-date: 2019-05-13 host: x86_64-apple-darwin release: 1.34.2 LLVM version: 8.0", ) .unwrap(); assert_eq!(v, Version::stable(34, 8)); // rustc 1.67 (rustup) let v = Version::parse( "rustc 1.67.0 (fc594f156 2023-01-24) binary: rustc commit-hash: fc594f15669680fa70d255faec3ca3fb507c3405 commit-date: 2023-01-24 host: aarch64-apple-darwin release: 1.67.0 LLVM version: 15.0.6", ) .unwrap(); assert_eq!(v, Version::stable(67, 15)); // rustc 1.68-beta (rustup) let v = Version::parse( "rustc 1.68.0-beta.2 (10b73bf73 2023-02-01) binary: rustc commit-hash: 10b73bf73a6b770cd92ad8ff538173bc3298411c commit-date: 2023-02-01 host: aarch64-apple-darwin release: 1.68.0-beta.2 LLVM version: 15.0.6", ) .unwrap(); // We do not distinguish between stable and beta because we are only // interested in whether unstable features are potentially available. assert_eq!(v, Version::stable(68, 15)); // rustc nightly-2019-01-27 (rustup) let v = Version::parse( "rustc 1.33.0-nightly (20c2cba61 2019-01-26) binary: rustc commit-hash: 20c2cba61dc83e612d25ed496025171caa3db30f commit-date: 2019-01-26 host: x86_64-apple-darwin release: 1.33.0-nightly LLVM version: 8.0", ) .unwrap(); assert_eq!(v.minor, 33); assert!(v.nightly); assert_eq!(v.llvm, 8); assert_eq!(v.commit_date().year, 2019); assert_eq!(v.commit_date().month, 1); assert_eq!(v.commit_date().day, 26); // rustc 1.69-nightly (rustup) let v = Version::parse( "rustc 1.69.0-nightly (bd39bbb4b 2023-02-07) binary: rustc commit-hash: bd39bbb4bb92df439bf6d85470e296cc6a47ffbd commit-date: 2023-02-07 host: aarch64-apple-darwin release: 1.69.0-nightly LLVM version: 15.0.7", ) .unwrap(); assert_eq!(v.minor, 69); assert!(v.nightly); assert_eq!(v.llvm, 15); assert_eq!(v.commit_date().year, 2023); assert_eq!(v.commit_date().month, 2); assert_eq!(v.commit_date().day, 7); // clippy-driver 1.69-nightly (rustup) let v = Version::parse( "rustc 1.69.0-nightly (bd39bbb4b 2023-02-07) binary: rustc commit-hash: bd39bbb4bb92df439bf6d85470e296cc6a47ffbd commit-date: 2023-02-07 host: aarch64-apple-darwin release: 1.69.0-nightly LLVM version: 15.0.7", ) .unwrap(); assert_eq!(v.minor, 69); assert!(v.nightly); assert_eq!(v.llvm, 15); assert_eq!(v.commit_date().year, 2023); assert_eq!(v.commit_date().month, 2); assert_eq!(v.commit_date().day, 7); // rustc 1.69-dev (from source: ./x.py build) let v = Version::parse( "rustc 1.69.0-dev binary: rustc commit-hash: unknown commit-date: unknown host: aarch64-unknown-linux-gnu release: 1.69.0-dev LLVM version: 16.0.0", ) .unwrap(); assert_eq!(v.minor, 69); assert!(v.nightly); assert_eq!(v.llvm, 16); assert_eq!(v.commit_date().year, 0); assert_eq!(v.commit_date().month, 0); assert_eq!(v.commit_date().day, 0); // rustc 1.64 (debian 11: apt-get install cargo) let v = Version::parse( "rustc 1.48.0 binary: rustc commit-hash: unknown commit-date: unknown host: aarch64-unknown-linux-gnu release: 1.48.0 LLVM version: 11.0", ) .unwrap(); assert_eq!(v, Version::stable(48, 11)); // rustc 1.67 (fedora: dnf install cargo) let v = Version::parse( "rustc 1.67.0 (fc594f156 2023-01-24) (Fedora 1.67.0-2.fc37) binary: rustc commit-hash: fc594f15669680fa70d255faec3ca3fb507c3405 commit-date: 2023-01-24 host: aarch64-unknown-linux-gnu release: 1.67.0 LLVM version: 15.0.7", ) .unwrap(); assert_eq!(v, Version::stable(67, 15)); // rustc 1.64 (alpine: apk add cargo) let v = Version::parse( "rustc 1.64.0 binary: rustc commit-hash: unknown commit-date: unknown host: aarch64-alpine-linux-musl release: 1.64.0 LLVM version: 15.0.3", ) .unwrap(); assert_eq!(v, Version::stable(64, 15)); } #[cfg(feature = "serde")] #[test] fn test_serde() { use test_helper::serde::{assert_tokens, DebugPartialEq, Token}; macro_rules! t { ($atomic_type:ty, $value_type:ident, $token_type:ident) => { std::eprint!("test_serde {} ... ", stringify!($value_type)); assert_tokens(&DebugPartialEq(<$atomic_type>::new($value_type::MAX)), &[ Token::$token_type($value_type::MAX as _), ]); assert_tokens(&DebugPartialEq(<$atomic_type>::new($value_type::MIN)), &[ Token::$token_type($value_type::MIN as _), ]); std::eprintln!("ok"); }; } assert_tokens(&DebugPartialEq(AtomicBool::new(true)), &[Token::Bool(true)]); assert_tokens(&DebugPartialEq(AtomicBool::new(false)), &[Token::Bool(false)]); t!(AtomicIsize, isize, I64); t!(AtomicUsize, usize, U64); t!(AtomicI8, i8, I8); t!(AtomicU8, u8, U8); t!(AtomicI16, i16, I16); t!(AtomicU16, u16, U16); t!(AtomicI32, i32, I32); t!(AtomicU32, u32, U32); t!(AtomicI64, i64, I64); t!(AtomicU64, u64, U64); // TODO: serde_test doesn't support Token::{I128,U128}: https://github.com/serde-rs/test/pull/6 // t!(AtomicI128, i128, I128); // t!(AtomicU128, u128, U128); #[cfg(feature = "float")] t!(AtomicF32, f32, F32); #[cfg(feature = "float")] #[cfg(not(target_arch = "mips"))] // LLVM 17 (nightly-2023-08-09) bug: assertion failed at core/src/num/diy_float.rs:78:9 t!(AtomicF64, f64, F64); } portable-atomic/src/tests/helper.rs0000644000175000017500000031467014661133735020414 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT #![allow(unused_macros)] use core::sync::atomic::Ordering; macro_rules! __test_atomic_common { ($atomic_type:ty, $value_type:ty) => { #[test] fn assert_auto_traits() { fn _assert() {} _assert::<$atomic_type>(); } #[test] fn alignment() { // https://github.com/rust-lang/rust/blob/1.70.0/library/core/tests/atomic.rs#L250 assert_eq!(core::mem::align_of::<$atomic_type>(), core::mem::size_of::<$atomic_type>()); assert_eq!(core::mem::size_of::<$atomic_type>(), core::mem::size_of::<$value_type>()); } #[test] fn is_lock_free() { const IS_ALWAYS_LOCK_FREE: bool = <$atomic_type>::is_always_lock_free(); assert_eq!(IS_ALWAYS_LOCK_FREE, <$atomic_type>::is_always_lock_free()); let is_lock_free = <$atomic_type>::is_lock_free(); if IS_ALWAYS_LOCK_FREE { // If is_always_lock_free is true, then is_lock_free must always be true. assert!(is_lock_free); } } }; } macro_rules! __test_atomic_pub_common { ($atomic_type:ty, $value_type:ty) => { #[test] fn assert_ref_unwind_safe() { #[cfg(not(all(portable_atomic_no_core_unwind_safe, not(feature = "std"))))] static_assertions::assert_impl_all!($atomic_type: std::panic::RefUnwindSafe); #[cfg(all(portable_atomic_no_core_unwind_safe, not(feature = "std")))] static_assertions::assert_not_impl_all!($atomic_type: std::panic::RefUnwindSafe); } }; } macro_rules! __test_atomic_int_load_store { ($atomic_type:ty, $int_type:ident, single_thread) => { __test_atomic_common!($atomic_type, $int_type); use crate::tests::helper::*; #[test] fn accessor() { let mut a = <$atomic_type>::new(10); assert_eq!(*a.get_mut(), 10); *a.get_mut() = 5; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert_eq!(a.into_inner(), 5); } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(10); for &order in &test_helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), 10); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(10); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(10, order)); for (&load_order, &store_order) in test_helper::LOAD_ORDERINGS.iter().zip(&test_helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), 10); VAR.store(5, store_order); assert_eq!(VAR.load(load_order), 5); VAR.store(10, store_order); let a = <$atomic_type>::new(1); assert_eq!(a.load(load_order), 1); a.store(2, store_order); assert_eq!(a.load(load_order), 2); } } }; ($atomic_type:ty, $int_type:ident) => { __test_atomic_int_load_store!($atomic_type, $int_type, single_thread); use crossbeam_utils::thread; use std::{collections::BTreeSet, vec, vec::Vec}; #[test] fn stress_load_store() { let (iterations, threads) = stress_test_config(); let data1 = (0..iterations).map(|_| fastrand::$int_type(..)).collect::>(); let set = data1.iter().copied().collect::>(); let a = <$atomic_type>::new(data1[fastrand::usize(0..iterations)]); let now = &std::time::Instant::now(); thread::scope(|s| { for _ in 0..threads { s.spawn(|_| { let now = *now; for i in 0..iterations { a.store(data1[i], rand_store_ordering()); } std::eprintln!("store end={:?}", now.elapsed()); }); s.spawn(|_| { let now = *now; let mut v = vec![0; iterations]; for i in 0..iterations { v[i] = a.load(rand_load_ordering()); } std::eprintln!("load end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } }) .unwrap(); } }; } macro_rules! __test_atomic_float_load_store { ($atomic_type:ty, $float_type:ident, single_thread) => { __test_atomic_common!($atomic_type, $float_type); use crate::tests::helper::*; #[test] fn accessor() { let mut a = <$atomic_type>::new(10.0); assert_eq!(*a.get_mut(), 10.0); *a.get_mut() = 5.0; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert_eq!(a.into_inner(), 5.0); } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(10.0); for &order in &test_helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), 10.0); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(10.0); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(10.0, order)); for (&load_order, &store_order) in test_helper::LOAD_ORDERINGS.iter().zip(&test_helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), 10.0); VAR.store(5.0, store_order); assert_eq!(VAR.load(load_order), 5.0); VAR.store(10.0, store_order); let a = <$atomic_type>::new(1.0); assert_eq!(a.load(load_order), 1.0); a.store(2.0, store_order); assert_eq!(a.load(load_order), 2.0); } } }; ($atomic_type:ty, $float_type:ident) => { __test_atomic_float_load_store!($atomic_type, $float_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_bool_load_store { ($atomic_type:ty, single_thread) => { __test_atomic_common!($atomic_type, bool); use crate::tests::helper::*; #[test] fn accessor() { let mut a = <$atomic_type>::new(false); assert_eq!(*a.get_mut(), false); *a.get_mut() = true; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert_eq!(a.into_inner(), true); } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(false); for &order in &test_helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), false); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(false); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(false, order)); for (&load_order, &store_order) in test_helper::LOAD_ORDERINGS.iter().zip(&test_helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), false); VAR.store(true, store_order); assert_eq!(VAR.load(load_order), true); VAR.store(false, store_order); let a = <$atomic_type>::new(true); assert_eq!(a.load(load_order), true); a.store(false, store_order); assert_eq!(a.load(load_order), false); } } }; ($atomic_type:ty) => { __test_atomic_bool_load_store!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_ptr_load_store { ($atomic_type:ty, single_thread) => { __test_atomic_common!($atomic_type, *mut u8); use crate::tests::helper::*; use std::ptr; #[test] fn accessor() { let mut v = 1; let mut a = <$atomic_type>::new(ptr::null_mut()); assert!(a.get_mut().is_null()); *a.get_mut() = &mut v; assert_eq!(a.as_ptr() as *const (), &a as *const _ as *const ()); assert!(!a.into_inner().is_null()); } // https://bugs.llvm.org/show_bug.cgi?id=37061 #[test] fn static_load_only() { static VAR: $atomic_type = <$atomic_type>::new(ptr::null_mut()); for &order in &test_helper::LOAD_ORDERINGS { assert_eq!(VAR.load(order), ptr::null_mut()); } } #[test] fn load_store() { static VAR: $atomic_type = <$atomic_type>::new(ptr::null_mut()); test_load_ordering(|order| VAR.load(order)); test_store_ordering(|order| VAR.store(ptr::null_mut(), order)); let mut v = 1_u8; let p = &mut v as *mut u8; for (&load_order, &store_order) in test_helper::LOAD_ORDERINGS.iter().zip(&test_helper::STORE_ORDERINGS) { assert_eq!(VAR.load(load_order), ptr::null_mut()); VAR.store(p, store_order); assert_eq!(VAR.load(load_order), p); VAR.store(ptr::null_mut(), store_order); let a = <$atomic_type>::new(p); assert_eq!(a.load(load_order), p); a.store(ptr::null_mut(), store_order); assert_eq!(a.load(load_order), ptr::null_mut()); } } }; ($atomic_type:ty) => { __test_atomic_ptr_load_store!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_int { ($atomic_type:ty, $int_type:ident, single_thread) => { use core::$int_type; #[test] fn swap() { let a = <$atomic_type>::new(5); test_swap_ordering(|order| a.swap(5, order)); for &order in &test_helper::SWAP_ORDERINGS { assert_eq!(a.swap(10, order), 5); assert_eq!(a.swap(5, order), 10); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(5); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(5, 5, success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(5); assert_eq!(a.compare_exchange(5, 10, success, failure), Ok(5)); assert_eq!(a.load(Ordering::Relaxed), 10); assert_eq!(a.compare_exchange(6, 12, success, failure), Err(10)); assert_eq!(a.load(Ordering::Relaxed), 10); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(4); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(4, 4, success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(4); assert_eq!(a.compare_exchange_weak(6, 8, success, failure), Err(4)); let mut old = a.load(Ordering::Relaxed); loop { let new = old * 2; match a.compare_exchange_weak(old, new, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), 8); } } #[test] fn fetch_add() { let a = <$atomic_type>::new(0); test_swap_ordering(|order| a.fetch_add(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0); assert_eq!(a.fetch_add(10, order), 0); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MAX); assert_eq!(a.fetch_add(1, order), $int_type::MAX); assert_eq!(a.load(Ordering::Relaxed), $int_type::MAX.wrapping_add(1)); } } #[test] fn add() { let a = <$atomic_type>::new(0); test_swap_ordering(|order| a.add(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0); a.add(10, order); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MAX); a.add(1, order); assert_eq!(a.load(Ordering::Relaxed), $int_type::MAX.wrapping_add(1)); } } #[test] fn fetch_sub() { let a = <$atomic_type>::new(20); test_swap_ordering(|order| a.fetch_sub(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(20); assert_eq!(a.fetch_sub(10, order), 20); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MIN); assert_eq!(a.fetch_sub(1, order), $int_type::MIN); assert_eq!(a.load(Ordering::Relaxed), $int_type::MIN.wrapping_sub(1)); } } #[test] fn sub() { let a = <$atomic_type>::new(20); test_swap_ordering(|order| a.sub(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(20); a.sub(10, order); assert_eq!(a.load(Ordering::Relaxed), 10); let a = <$atomic_type>::new($int_type::MIN); a.sub(1, order); assert_eq!(a.load(Ordering::Relaxed), $int_type::MIN.wrapping_sub(1)); } } #[test] fn fetch_and() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.fetch_and(0b101101, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); assert_eq!(a.fetch_and(0b110011, order), 0b101101); assert_eq!(a.load(Ordering::Relaxed), 0b100001); } } #[test] fn and() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.and(0b101101, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); a.and(0b110011, order); assert_eq!(a.load(Ordering::Relaxed), 0b100001); } } #[test] fn fetch_nand() { let a = <$atomic_type>::new(0x13); test_swap_ordering(|order| a.fetch_nand(0x31, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0x13); assert_eq!(a.fetch_nand(0x31, order), 0x13); assert_eq!(a.load(Ordering::Relaxed), !(0x13 & 0x31)); } } #[test] fn fetch_or() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.fetch_or(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); assert_eq!(a.fetch_or(0b110011, order), 0b101101); assert_eq!(a.load(Ordering::Relaxed), 0b111111); } } #[test] fn or() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.or(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); a.or(0b110011, order); assert_eq!(a.load(Ordering::Relaxed), 0b111111); } } #[test] fn fetch_xor() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.fetch_xor(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); assert_eq!(a.fetch_xor(0b110011, order), 0b101101); assert_eq!(a.load(Ordering::Relaxed), 0b011110); } } #[test] fn xor() { let a = <$atomic_type>::new(0b101101); test_swap_ordering(|order| a.xor(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b101101); a.xor(0b110011, order); assert_eq!(a.load(Ordering::Relaxed), 0b011110); } } #[test] fn fetch_max() { let a = <$atomic_type>::new(23); test_swap_ordering(|order| a.fetch_max(23, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23); assert_eq!(a.fetch_max(22, order), 23); assert_eq!(a.load(Ordering::Relaxed), 23); assert_eq!(a.fetch_max(24, order), 23); assert_eq!(a.load(Ordering::Relaxed), 24); let a = <$atomic_type>::new(0); assert_eq!(a.fetch_max(1, order), 0); assert_eq!(a.load(Ordering::Relaxed), 1); assert_eq!(a.fetch_max(0, order), 1); assert_eq!(a.load(Ordering::Relaxed), 1); let a = <$atomic_type>::new(!0); assert_eq!(a.fetch_max(0, order), !0); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(!0, 0)); } } #[test] fn fetch_min() { let a = <$atomic_type>::new(23); test_swap_ordering(|order| a.fetch_min(23, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23); assert_eq!(a.fetch_min(24, order), 23); assert_eq!(a.load(Ordering::Relaxed), 23); assert_eq!(a.fetch_min(22, order), 23); assert_eq!(a.load(Ordering::Relaxed), 22); let a = <$atomic_type>::new(1); assert_eq!(a.fetch_min(0, order), 1); assert_eq!(a.load(Ordering::Relaxed), 0); assert_eq!(a.fetch_min(1, order), 0); assert_eq!(a.load(Ordering::Relaxed), 0); let a = <$atomic_type>::new(!0); assert_eq!(a.fetch_min(0, order), !0); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(!0, 0)); } } #[test] fn fetch_not() { let a = <$atomic_type>::new(1); test_swap_ordering(|order| a.fetch_not(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(1); assert_eq!(a.fetch_not(order), 1); assert_eq!(a.load(Ordering::Relaxed), !1); } } #[test] fn not() { let a = <$atomic_type>::new(1); test_swap_ordering(|order| a.not(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(1); a.not(order); assert_eq!(a.load(Ordering::Relaxed), !1); } } #[test] fn fetch_neg() { let a = <$atomic_type>::new(5); test_swap_ordering(|order| a.fetch_neg(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(5); assert_eq!(a.fetch_neg(order), 5); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::wrapping_neg(5)); assert_eq!(a.fetch_neg(order), <$int_type>::wrapping_neg(5)); assert_eq!(a.load(Ordering::Relaxed), 5); let a = <$atomic_type>::new(<$int_type>::MIN); assert_eq!(a.fetch_neg(order), <$int_type>::MIN); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN.wrapping_neg()); assert_eq!(a.fetch_neg(order), <$int_type>::MIN.wrapping_neg()); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN); } } #[test] fn neg() { let a = <$atomic_type>::new(5); test_swap_ordering(|order| a.neg(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(5); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::wrapping_neg(5)); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), 5); let a = <$atomic_type>::new(<$int_type>::MIN); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN.wrapping_neg()); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), <$int_type>::MIN); } } #[test] fn bit_set() { let a = <$atomic_type>::new(0b0001); test_swap_ordering(|order| assert!(a.bit_set(0, order))); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b0000); assert!(!a.bit_set(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0001); assert!(a.bit_set(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0001); } } #[test] fn bit_clear() { let a = <$atomic_type>::new(0b0000); test_swap_ordering(|order| assert!(!a.bit_clear(0, order))); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b0001); assert!(a.bit_clear(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0000); assert!(!a.bit_clear(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0000); } } #[test] fn bit_toggle() { let a = <$atomic_type>::new(0b0000); test_swap_ordering(|order| a.bit_toggle(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0b0000); assert!(!a.bit_toggle(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0001); assert!(a.bit_toggle(0, order)); assert_eq!(a.load(Ordering::Relaxed), 0b0000); } } ::quickcheck::quickcheck! { fn quickcheck_swap(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.swap(y, order), x); assert_eq!(a.swap(x, order), y); } true } fn quickcheck_compare_exchange(x: $int_type, y: $int_type) -> bool { #[cfg(all( target_arch = "arm", not(any(target_feature = "v6", portable_atomic_target_feature = "v6")), ))] { // TODO: LLVM bug: // https://github.com/llvm/llvm-project/issues/61880 // https://github.com/taiki-e/portable-atomic/issues/2 if core::mem::size_of::<$int_type>() <= 2 { return true; } } let z = loop { let z = fastrand::$int_type(..); if z != y { break z; } }; for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); assert_eq!(a.load(Ordering::Relaxed), y); assert_eq!(a.compare_exchange(z, x, success, failure).unwrap_err(), y); assert_eq!(a.load(Ordering::Relaxed), y); } true } fn quickcheck_fetch_add(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_add(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_add(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_add(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_add(x)); } true } fn quickcheck_add(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.add(y, order); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_add(y)); let a = <$atomic_type>::new(y); a.add(x, order); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_add(x)); } true } fn quickcheck_fetch_sub(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_sub(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_sub(y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_sub(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_sub(x)); } true } fn quickcheck_sub(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.sub(y, order); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_sub(y)); let a = <$atomic_type>::new(y); a.sub(x, order); assert_eq!(a.load(Ordering::Relaxed), y.wrapping_sub(x)); } true } fn quickcheck_fetch_and(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_and(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x & y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_and(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y & x); } true } fn quickcheck_and(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.and(y, order); assert_eq!(a.load(Ordering::Relaxed), x & y); let a = <$atomic_type>::new(y); a.and(x, order); assert_eq!(a.load(Ordering::Relaxed), y & x); } true } fn quickcheck_fetch_nand(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_nand(y, order), x); assert_eq!(a.load(Ordering::Relaxed), !(x & y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_nand(x, order), y); assert_eq!(a.load(Ordering::Relaxed), !(y & x)); } true } fn quickcheck_fetch_or(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_or(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x | y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_or(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y | x); } true } fn quickcheck_or(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.or(y, order); assert_eq!(a.load(Ordering::Relaxed), x | y); let a = <$atomic_type>::new(y); a.or(x, order); assert_eq!(a.load(Ordering::Relaxed), y | x); } true } fn quickcheck_fetch_xor(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_xor(y, order), x); assert_eq!(a.load(Ordering::Relaxed), x ^ y); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_xor(x, order), y); assert_eq!(a.load(Ordering::Relaxed), y ^ x); } true } fn quickcheck_xor(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.xor(y, order); assert_eq!(a.load(Ordering::Relaxed), x ^ y); let a = <$atomic_type>::new(y); a.xor(x, order); assert_eq!(a.load(Ordering::Relaxed), y ^ x); } true } fn quickcheck_fetch_max(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_max(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_max(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::max(y, x)); } true } fn quickcheck_fetch_min(x: $int_type, y: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_min(y, order), x); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(x, y)); let a = <$atomic_type>::new(y); assert_eq!(a.fetch_min(x, order), y); assert_eq!(a.load(Ordering::Relaxed), core::cmp::min(y, x)); } true } fn quickcheck_fetch_not(x: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_not(order), x); assert_eq!(a.load(Ordering::Relaxed), !x); assert_eq!(a.fetch_not(order), !x); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_not(x: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.not(order); assert_eq!(a.load(Ordering::Relaxed), !x); a.not(order); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_fetch_neg(x: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.fetch_neg(order), x); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_neg()); assert_eq!(a.fetch_neg(order), x.wrapping_neg()); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_neg(x: $int_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), x.wrapping_neg()); a.neg(order); assert_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_bit_set(x: $int_type, bit: u32) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); let b = a.bit_set(bit, order); let mask = <$int_type>::wrapping_shl(1, bit); assert_eq!(a.load(Ordering::Relaxed), x | mask); assert_eq!(b, x & mask != 0); } true } fn quickcheck_bit_clear(x: $int_type, bit: u32) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); let b = a.bit_clear(bit, order); let mask = <$int_type>::wrapping_shl(1, bit); assert_eq!(a.load(Ordering::Relaxed), x & !mask); assert_eq!(b, x & mask != 0); } true } fn quickcheck_bit_toggle(x: $int_type, bit: u32) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); let b = a.bit_toggle(bit, order); let mask = <$int_type>::wrapping_shl(1, bit); assert_eq!(a.load(Ordering::Relaxed), x ^ mask); assert_eq!(b, x & mask != 0); } true } } }; ($atomic_type:ty, $int_type:ident) => { __test_atomic_int!($atomic_type, $int_type, single_thread); #[test] fn stress_swap() { let (iterations, threads) = stress_test_config(); let data1 = &(0..threads) .map(|_| (0..iterations).map(|_| fastrand::$int_type(..)).collect::>()) .collect::>(); let data2 = &(0..threads) .map(|_| (0..iterations).map(|_| fastrand::$int_type(..)).collect::>()) .collect::>(); let set = &data1 .iter() .flat_map(|v| v.iter().copied()) .chain(data2.iter().flat_map(|v| v.iter().copied())) .collect::>(); let a = &<$atomic_type>::new(data2[0][fastrand::usize(0..iterations)]); let now = &std::time::Instant::now(); thread::scope(|s| { for thread in 0..threads { if thread % 2 == 0 { s.spawn(move |_| { let now = *now; for i in 0..iterations { a.store(data1[thread][i], rand_store_ordering()); } std::eprintln!("store end={:?}", now.elapsed()); }); } else { s.spawn(|_| { let now = *now; let mut v = vec![0; iterations]; for i in 0..iterations { v[i] = a.load(rand_load_ordering()); } std::eprintln!("load end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } s.spawn(move |_| { let now = *now; let mut v = vec![0; iterations]; for i in 0..iterations { v[i] = a.swap(data2[thread][i], rand_swap_ordering()); } std::eprintln!("swap end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } }) .unwrap(); } #[test] fn stress_compare_exchange() { let (iterations, threads) = stress_test_config(); let data1 = &(0..threads) .map(|_| (0..iterations).map(|_| fastrand::$int_type(..)).collect::>()) .collect::>(); let data2 = &(0..threads) .map(|_| (0..iterations).map(|_| fastrand::$int_type(..)).collect::>()) .collect::>(); let set = &data1 .iter() .flat_map(|v| v.iter().copied()) .chain(data2.iter().flat_map(|v| v.iter().copied())) .collect::>(); let a = &<$atomic_type>::new(data2[0][fastrand::usize(0..iterations)]); let now = &std::time::Instant::now(); thread::scope(|s| { for thread in 0..threads { s.spawn(move |_| { let now = *now; for i in 0..iterations { a.store(data1[thread][i], rand_store_ordering()); } std::eprintln!("store end={:?}", now.elapsed()); }); s.spawn(|_| { let now = *now; let mut v = vec![data2[0][0]; iterations]; for i in 0..iterations { v[i] = a.load(rand_load_ordering()); } std::eprintln!("load end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); s.spawn(move |_| { let now = *now; let mut v = vec![data2[0][0]; iterations]; for i in 0..iterations { let old = if i % 2 == 0 { fastrand::$int_type(..) } else { a.load(Ordering::Relaxed) }; let new = data2[thread][i]; let o = rand_compare_exchange_ordering(); match a.compare_exchange(old, new, o.0, o.1) { Ok(r) => assert_eq!(old, r), Err(r) => v[i] = r, } } std::eprintln!("compare_exchange end={:?}", now.elapsed()); for v in v { assert!(set.contains(&v), "v={}", v); } }); } }) .unwrap(); } }; } macro_rules! __test_atomic_float { ($atomic_type:ty, $float_type:ident, single_thread) => { use core::$float_type; #[test] fn swap() { let a = <$atomic_type>::new(5.0); test_swap_ordering(|order| a.swap(5.0, order)); for &order in &test_helper::SWAP_ORDERINGS { assert_eq!(a.swap(10.0, order), 5.0); assert_eq!(a.swap(5.0, order), 10.0); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(5.0); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(5.0, 5.0, success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(5.0); assert_eq!(a.compare_exchange(5.0, 10.0, success, failure), Ok(5.0)); assert_eq!(a.load(Ordering::Relaxed), 10.0); assert_eq!(a.compare_exchange(6.0, 12.0, success, failure), Err(10.0)); assert_eq!(a.load(Ordering::Relaxed), 10.0); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(4.0); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(4.0, 4.0, success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(4.0); assert_eq!(a.compare_exchange_weak(6.0, 8.0, success, failure), Err(4.0)); let mut old = a.load(Ordering::Relaxed); loop { let new = old * 2.0; match a.compare_exchange_weak(old, new, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), 8.0); } } #[test] fn fetch_add() { let a = <$atomic_type>::new(0.0); test_swap_ordering(|order| a.fetch_add(0.0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(0.0); assert_eq!(a.fetch_add(10.0, order), 0.0); assert_eq!(a.load(Ordering::Relaxed), 10.0); let a = <$atomic_type>::new($float_type::MAX); assert_eq!(a.fetch_add(1.0, order), $float_type::MAX); assert_eq!(a.load(Ordering::Relaxed), $float_type::MAX + 1.0); } } #[test] fn fetch_sub() { let a = <$atomic_type>::new(20.0); test_swap_ordering(|order| a.fetch_sub(0.0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(20.0); assert_eq!(a.fetch_sub(10.0, order), 20.0); assert_eq!(a.load(Ordering::Relaxed), 10.0); let a = <$atomic_type>::new($float_type::MIN); assert_eq!(a.fetch_sub(1.0, order), $float_type::MIN); assert_eq!(a.load(Ordering::Relaxed), $float_type::MIN - 1.0); } } #[test] fn fetch_max() { let a = <$atomic_type>::new(23.0); test_swap_ordering(|order| a.fetch_max(23.0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23.0); assert_eq!(a.fetch_max(22.0, order), 23.0); assert_eq!(a.load(Ordering::Relaxed), 23.0); assert_eq!(a.fetch_max(24.0, order), 23.0); assert_eq!(a.load(Ordering::Relaxed), 24.0); } } #[test] fn fetch_min() { let a = <$atomic_type>::new(23.0); test_swap_ordering(|order| a.fetch_min(23.0, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(23.0); assert_eq!(a.fetch_min(24.0, order), 23.0); assert_eq!(a.load(Ordering::Relaxed), 23.0); assert_eq!(a.fetch_min(22.0, order), 23.0); assert_eq!(a.load(Ordering::Relaxed), 22.0); } } #[test] fn fetch_neg() { let a = <$atomic_type>::new(5.0); test_swap_ordering(|order| a.fetch_neg(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(5.0); assert_eq!(a.fetch_neg(order), 5.0); assert_eq!(a.load(Ordering::Relaxed), -5.0); assert_eq!(a.fetch_neg(order), -5.0); assert_eq!(a.load(Ordering::Relaxed), 5.0); } } #[test] fn fetch_abs() { let a = <$atomic_type>::new(23.0); test_swap_ordering(|order| a.fetch_abs(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(-23.0); assert_eq!(a.fetch_abs(order), -23.0); assert_eq!(a.load(Ordering::Relaxed), 23.0); assert_eq!(a.fetch_abs(order), 23.0); assert_eq!(a.load(Ordering::Relaxed), 23.0); } } ::quickcheck::quickcheck! { fn quickcheck_swap(x: $float_type, y: $float_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.swap(y, order), x); assert_float_op_eq!(a.swap(x, order), y); } true } fn quickcheck_compare_exchange(x: $float_type, y: $float_type) -> bool { let z = loop { let z = fastrand::$float_type(); if z != y { break z; } }; for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); assert_float_op_eq!(a.load(Ordering::Relaxed), y); assert_float_op_eq!( a.compare_exchange(z, x, success, failure).unwrap_err(), y, ); assert_float_op_eq!(a.load(Ordering::Relaxed), y); } true } fn quickcheck_fetch_add(x: $float_type, y: $float_type) -> bool { if cfg!(all(not(debug_assertions), target_arch = "x86", not(target_feature = "sse2"))) { // TODO: rustc bug: // https://github.com/rust-lang/rust/issues/72327 // https://github.com/rust-lang/rust/issues/73288 return true; } for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_add(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x + y); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_add(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y + x); } true } fn quickcheck_fetch_sub(x: $float_type, y: $float_type) -> bool { if cfg!(all(not(debug_assertions), target_arch = "x86", not(target_feature = "sse2"))) { // TODO: rustc bug: // https://github.com/rust-lang/rust/issues/72327 // https://github.com/rust-lang/rust/issues/73288 return true; } for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_sub(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x - y); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_sub(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y - x); } true } fn quickcheck_fetch_max(x: $float_type, y: $float_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_max(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x.max(y)); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_max(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y.max(x)); } true } fn quickcheck_fetch_min(x: $float_type, y: $float_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_min(y, order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), x.min(y)); let a = <$atomic_type>::new(y); assert_float_op_eq!(a.fetch_min(x, order), y); assert_float_op_eq!(a.load(Ordering::Relaxed), y.min(x)); } true } fn quickcheck_fetch_neg(x: $float_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_neg(order), x); assert_float_op_eq!(a.load(Ordering::Relaxed), -x); assert_float_op_eq!(a.fetch_neg(order), -x); assert_float_op_eq!(a.load(Ordering::Relaxed), x); } true } fn quickcheck_fetch_abs(x: $float_type) -> bool { for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(x); assert_float_op_eq!(a.fetch_abs(order), x); assert_float_op_eq!(a.fetch_abs(order), x.abs()); assert_float_op_eq!(a.load(Ordering::Relaxed), x.abs()); } true } } }; ($atomic_type:ty, $float_type:ident) => { __test_atomic_float!($atomic_type, $float_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_bool { ($atomic_type:ty, single_thread) => { #[test] fn swap() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.swap(true, order)); for &order in &test_helper::SWAP_ORDERINGS { assert_eq!(a.swap(true, order), true); assert_eq!(a.swap(false, order), true); assert_eq!(a.swap(false, order), false); assert_eq!(a.swap(true, order), false); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(true); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(true, true, success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.compare_exchange(true, false, success, failure), Ok(true)); assert_eq!(a.load(Ordering::Relaxed), false); assert_eq!(a.compare_exchange(true, true, success, failure), Err(false)); assert_eq!(a.load(Ordering::Relaxed), false); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(false); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(false, false, success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(false); assert_eq!(a.compare_exchange_weak(true, true, success, failure), Err(false)); let mut old = a.load(Ordering::Relaxed); let new = true; loop { match a.compare_exchange_weak(old, new, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_and() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_and(true, order), true)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_and(false, order), true); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_and(true, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_and(false, order), false); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_and(true, order), false); assert_eq!(a.load(Ordering::Relaxed), false); } } #[test] fn and() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.and(true, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.and(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(true); a.and(true, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); a.and(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.and(true, order); assert_eq!(a.load(Ordering::Relaxed), false); } } #[test] fn fetch_or() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_or(false, order), true)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_or(false, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_or(true, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_or(false, order), false); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_or(true, order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn or() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.or(false, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.or(false, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); a.or(true, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); a.or(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.or(true, order); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_xor() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_xor(false, order), true)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_xor(false, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_xor(true, order), true); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_xor(false, order), false); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_xor(true, order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn xor() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.xor(false, order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.xor(false, order); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); a.xor(true, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.xor(false, order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.xor(true, order); assert_eq!(a.load(Ordering::Relaxed), true); } } ::quickcheck::quickcheck! { fn quickcheck_compare_exchange(x: bool, y: bool) -> bool { let z = !y; for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!(a.compare_exchange(x, y, success, failure).unwrap(), x); assert_eq!(a.load(Ordering::Relaxed), y); assert_eq!(a.compare_exchange(z, x, success, failure).unwrap_err(), y); assert_eq!(a.load(Ordering::Relaxed), y); } true } } }; ($atomic_type:ty) => { __test_atomic_bool!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_ptr { ($atomic_type:ty, single_thread) => { #[test] fn swap() { let a = <$atomic_type>::new(ptr::null_mut()); test_swap_ordering(|order| a.swap(ptr::null_mut(), order)); let x = &mut 1; for &order in &test_helper::SWAP_ORDERINGS { assert_eq!(a.swap(x, order), ptr::null_mut()); assert_eq!(a.swap(ptr::null_mut(), order), x as _); } } #[test] fn compare_exchange() { let a = <$atomic_type>::new(ptr::null_mut()); test_compare_exchange_ordering(|success, failure| { a.compare_exchange(ptr::null_mut(), ptr::null_mut(), success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(ptr::null_mut()); let x = &mut 1; assert_eq!( a.compare_exchange(ptr::null_mut(), x, success, failure), Ok(ptr::null_mut()), ); assert_eq!(a.load(Ordering::Relaxed), x as _); assert_eq!( a.compare_exchange(ptr::null_mut(), ptr::null_mut(), success, failure), Err(x as _), ); assert_eq!(a.load(Ordering::Relaxed), x as _); } } #[test] fn compare_exchange_weak() { let a = <$atomic_type>::new(ptr::null_mut()); test_compare_exchange_ordering(|success, failure| { a.compare_exchange_weak(ptr::null_mut(), ptr::null_mut(), success, failure) }); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(ptr::null_mut()); let x = &mut 1; assert_eq!(a.compare_exchange_weak(x, x, success, failure), Err(ptr::null_mut())); let mut old = a.load(Ordering::Relaxed); loop { match a.compare_exchange_weak(old, x, success, failure) { Ok(_) => break, Err(x) => old = x, } } assert_eq!(a.load(Ordering::Relaxed), x as _); } } }; ($atomic_type:ty) => { __test_atomic_ptr!($atomic_type, single_thread); // TODO: multi thread }; } macro_rules! __test_atomic_int_load_store_pub { ($atomic_type:ty, $int_type:ident) => { __test_atomic_pub_common!($atomic_type, $int_type); use std::{boxed::Box, mem}; #[test] fn impls() { let a = <$atomic_type>::default(); let b = <$atomic_type>::from(0); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); unsafe { let ptr: *mut Align16<$int_type> = Box::into_raw(Box::new(Align16(0))); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr.cast::<$int_type>()); *a.as_ptr() = 1; } assert_eq!((*ptr).0, 1); drop(Box::from_raw(ptr)); } } }; } macro_rules! __test_atomic_int_pub { ($atomic_type:ty, $int_type:ident) => { #[test] fn fetch_update() { let a = <$atomic_type>::new(7); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(7); assert_eq!(a.fetch_update(success, failure, |_| None), Err(7)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1)), Ok(7)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1)), Ok(8)); assert_eq!(a.load(Ordering::SeqCst), 9); } } ::quickcheck::quickcheck! { fn quickcheck_fetch_update(x: $int_type, y: $int_type) -> bool { let z = loop { let z = fastrand::$int_type(..); if z != y { break z; } }; for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(x); assert_eq!( a.fetch_update(success, failure, |_| Some(y)) .unwrap(), x ); assert_eq!( a.fetch_update(success, failure, |_| Some(z)) .unwrap(), y ); assert_eq!(a.load(Ordering::Relaxed), z); assert_eq!( a.fetch_update(success, failure, |z| if z == y { Some(z) } else { None }) .unwrap_err(), z ); assert_eq!(a.load(Ordering::Relaxed), z); } true } } }; } macro_rules! __test_atomic_float_pub { ($atomic_type:ty, $float_type:ident) => { __test_atomic_pub_common!($atomic_type, $float_type); use std::{boxed::Box, mem}; #[test] fn fetch_update() { let a = <$atomic_type>::new(7.0); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(7.0); assert_eq!(a.fetch_update(success, failure, |_| None), Err(7.0)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1.0)), Ok(7.0)); assert_eq!(a.fetch_update(success, failure, |x| Some(x + 1.0)), Ok(8.0)); assert_eq!(a.load(Ordering::SeqCst), 9.0); } } #[test] fn impls() { let a = <$atomic_type>::default(); let b = <$atomic_type>::from(0.0); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); unsafe { let ptr: *mut Align16<$float_type> = Box::into_raw(Box::new(Align16(0.0))); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr.cast::<$float_type>()); *a.as_ptr() = 1.0; } assert_eq!((*ptr).0, 1.0); drop(Box::from_raw(ptr)); } } }; } macro_rules! __test_atomic_bool_pub { ($atomic_type:ty) => { __test_atomic_pub_common!($atomic_type, bool); use std::{boxed::Box, mem}; #[test] fn fetch_nand() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| assert_eq!(a.fetch_nand(false, order), true)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_nand(false, order), true); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(true); assert_eq!(a.fetch_nand(true, order), true); assert_eq!(a.load(Ordering::Relaxed) as usize, 0); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_nand(false, order), false); assert_eq!(a.load(Ordering::Relaxed), true); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_nand(true, order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_not() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.fetch_not(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); assert_eq!(a.fetch_not(order), true); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); assert_eq!(a.fetch_not(order), false); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn not() { let a = <$atomic_type>::new(true); test_swap_ordering(|order| a.fetch_not(order)); for &order in &test_helper::SWAP_ORDERINGS { let a = <$atomic_type>::new(true); a.not(order); assert_eq!(a.load(Ordering::Relaxed), false); let a = <$atomic_type>::new(false); a.not(order); assert_eq!(a.load(Ordering::Relaxed), true); } } #[test] fn fetch_update() { let a = <$atomic_type>::new(false); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(false); assert_eq!(a.fetch_update(success, failure, |_| None), Err(false)); assert_eq!(a.fetch_update(success, failure, |x| Some(!x)), Ok(false)); assert_eq!(a.fetch_update(success, failure, |x| Some(!x)), Ok(true)); assert_eq!(a.load(Ordering::SeqCst), false); } } #[test] fn impls() { let a = <$atomic_type>::default(); let b = <$atomic_type>::from(false); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); unsafe { let ptr: *mut bool = Box::into_raw(Box::new(false)); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr); *a.as_ptr() = true; } assert_eq!((*ptr), true); drop(Box::from_raw(ptr)); } } }; } macro_rules! __test_atomic_ptr_pub { ($atomic_type:ty) => { __test_atomic_pub_common!($atomic_type, *mut u8); use sptr::Strict; use std::{boxed::Box, mem}; #[test] fn fetch_update() { let a = <$atomic_type>::new(ptr::null_mut()); test_compare_exchange_ordering(|set, fetch| a.fetch_update(set, fetch, |x| Some(x))); for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { let a = <$atomic_type>::new(ptr::null_mut()); assert_eq!(a.fetch_update(success, failure, |_| None), Err(ptr::null_mut())); assert_eq!( a.fetch_update(success, failure, |_| Some(&a as *const _ as *mut _)), Ok(ptr::null_mut()) ); assert_eq!(a.load(Ordering::SeqCst), &a as *const _ as *mut _); } } #[test] fn impls() { let a = <$atomic_type>::default(); let b = <$atomic_type>::from(ptr::null_mut()); assert_eq!(a.load(Ordering::SeqCst), b.load(Ordering::SeqCst)); assert_eq!(std::format!("{:?}", a), std::format!("{:?}", a.load(Ordering::SeqCst))); assert_eq!(std::format!("{:p}", a), std::format!("{:p}", a.load(Ordering::SeqCst))); unsafe { let ptr: *mut Align16<*mut u8> = Box::into_raw(Box::new(Align16(ptr::null_mut()))); assert!(ptr as usize % mem::align_of::<$atomic_type>() == 0); { let a = <$atomic_type>::from_ptr(ptr.cast::<*mut u8>()); *a.as_ptr() = ptr::null_mut::().wrapping_add(1); } assert_eq!((*ptr).0, ptr::null_mut::().wrapping_add(1)); drop(Box::from_raw(ptr)); } } // https://github.com/rust-lang/rust/blob/1.70.0/library/core/tests/atomic.rs#L130-L213 #[test] fn ptr_add_null() { let atom = AtomicPtr::::new(core::ptr::null_mut()); assert_eq!(atom.fetch_ptr_add(1, Ordering::SeqCst).addr(), 0); assert_eq!(atom.load(Ordering::SeqCst).addr(), 8); assert_eq!(atom.fetch_byte_add(1, Ordering::SeqCst).addr(), 8); assert_eq!(atom.load(Ordering::SeqCst).addr(), 9); assert_eq!(atom.fetch_ptr_sub(1, Ordering::SeqCst).addr(), 9); assert_eq!(atom.load(Ordering::SeqCst).addr(), 1); assert_eq!(atom.fetch_byte_sub(1, Ordering::SeqCst).addr(), 1); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0); } #[test] fn ptr_add_data() { let num = 0i64; let n = &num as *const i64 as *mut _; let atom = AtomicPtr::::new(n); assert_eq!(atom.fetch_ptr_add(1, Ordering::SeqCst), n); assert_eq!(atom.load(Ordering::SeqCst), n.wrapping_add(1)); assert_eq!(atom.fetch_ptr_sub(1, Ordering::SeqCst), n.wrapping_add(1)); assert_eq!(atom.load(Ordering::SeqCst), n); let bytes_from_n = |b| n.cast::().wrapping_add(b).cast::(); assert_eq!(atom.fetch_byte_add(1, Ordering::SeqCst), n); assert_eq!(atom.load(Ordering::SeqCst), bytes_from_n(1)); assert_eq!(atom.fetch_byte_add(5, Ordering::SeqCst), bytes_from_n(1)); assert_eq!(atom.load(Ordering::SeqCst), bytes_from_n(6)); assert_eq!(atom.fetch_byte_sub(1, Ordering::SeqCst), bytes_from_n(6)); assert_eq!(atom.load(Ordering::SeqCst), bytes_from_n(5)); assert_eq!(atom.fetch_byte_sub(5, Ordering::SeqCst), bytes_from_n(5)); assert_eq!(atom.load(Ordering::SeqCst), n); } #[test] fn ptr_bitops() { let atom = AtomicPtr::::new(core::ptr::null_mut()); assert_eq!(atom.fetch_or(0b0111, Ordering::SeqCst).addr(), 0); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0b0111); assert_eq!(atom.fetch_and(0b1101, Ordering::SeqCst).addr(), 0b0111); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0b0101); assert_eq!(atom.fetch_xor(0b1111, Ordering::SeqCst).addr(), 0b0101); assert_eq!(atom.load(Ordering::SeqCst).addr(), 0b1010); } #[test] fn ptr_bitops_tagging() { const MASK_TAG: usize = 0b1111; const MASK_PTR: usize = !MASK_TAG; #[repr(align(16))] struct Tagme(u128); let tagme = Tagme(1000); let ptr = &tagme as *const Tagme as *mut Tagme; let atom: AtomicPtr = AtomicPtr::new(ptr); assert_eq!(ptr.addr() & MASK_TAG, 0); assert_eq!(atom.fetch_or(0b0111, Ordering::SeqCst), ptr); assert_eq!(atom.load(Ordering::SeqCst), ptr.map_addr(|a| a | 0b111)); assert_eq!( atom.fetch_and(MASK_PTR | 0b0010, Ordering::SeqCst), ptr.map_addr(|a| a | 0b111) ); assert_eq!(atom.load(Ordering::SeqCst), ptr.map_addr(|a| a | 0b0010)); assert_eq!(atom.fetch_xor(0b1011, Ordering::SeqCst), ptr.map_addr(|a| a | 0b0010)); assert_eq!(atom.load(Ordering::SeqCst), ptr.map_addr(|a| a | 0b1001)); assert_eq!(atom.fetch_and(MASK_PTR, Ordering::SeqCst), ptr.map_addr(|a| a | 0b1001)); assert_eq!(atom.load(Ordering::SeqCst), ptr); } #[test] fn bit_set() { let a = <$atomic_type>::new(ptr::null_mut::().cast::().map_addr(|a| a | 1)); test_swap_ordering(|order| assert!(a.bit_set(0, order))); for &order in &test_helper::SWAP_ORDERINGS { let pointer = &mut 1u64 as *mut u64 as *mut u8; let atom = <$atomic_type>::new(pointer); // Tag the bottom bit of the pointer. assert!(!atom.bit_set(0, order)); // Extract and untag. let tagged = atom.load(Ordering::Relaxed); assert_eq!(tagged.addr() & 1, 1); assert_eq!(tagged.map_addr(|p| p & !1), pointer); } } #[test] fn bit_clear() { let a = <$atomic_type>::new(ptr::null_mut::().cast::()); test_swap_ordering(|order| assert!(!a.bit_clear(0, order))); for &order in &test_helper::SWAP_ORDERINGS { let pointer = &mut 1u64 as *mut u64 as *mut u8; // A tagged pointer let atom = <$atomic_type>::new(pointer.map_addr(|a| a | 1)); assert!(atom.bit_set(0, order)); // Untag assert!(atom.bit_clear(0, order)); } } #[test] fn bit_toggle() { let a = <$atomic_type>::new(ptr::null_mut::().cast::()); test_swap_ordering(|order| a.bit_toggle(0, order)); for &order in &test_helper::SWAP_ORDERINGS { let pointer = &mut 1u64 as *mut u64 as *mut u8; let atom = <$atomic_type>::new(pointer); // Toggle a tag bit on the pointer. atom.bit_toggle(0, order); assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1); } } }; } macro_rules! test_atomic_int_load_store { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type); } } }; } macro_rules! test_atomic_bool_load_store { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_bool { use super::*; __test_atomic_bool_load_store!(AtomicBool); } }; } macro_rules! test_atomic_ptr_load_store { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr); } }; } macro_rules! test_atomic_int_single_thread { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type, single_thread); __test_atomic_int!([], $int_type, single_thread); } } }; } macro_rules! test_atomic_bool_single_thread { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_bool { use super::*; __test_atomic_bool_load_store!(AtomicBool, single_thread); __test_atomic_bool!(AtomicBool, single_thread); } }; } macro_rules! test_atomic_ptr_single_thread { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr, single_thread); __test_atomic_ptr!(AtomicPtr, single_thread); } }; } macro_rules! test_atomic_int { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type); __test_atomic_int!([], $int_type); } } }; } macro_rules! test_atomic_bool { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_bool { use super::*; __test_atomic_bool_load_store!(AtomicBool); __test_atomic_bool!(AtomicBool); } }; } macro_rules! test_atomic_ptr { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] #[allow(unstable_name_collisions)] // for sptr crate mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr); __test_atomic_ptr!(AtomicPtr); } }; } macro_rules! test_atomic_int_pub { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type); __test_atomic_int!([], $int_type); __test_atomic_int_load_store_pub!([], $int_type); __test_atomic_int_pub!([], $int_type); } } }; } macro_rules! test_atomic_int_load_store_pub { ($int_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_int_load_store!([], $int_type); __test_atomic_int_load_store_pub!([], $int_type); } } }; } #[cfg(feature = "float")] macro_rules! test_atomic_float_pub { ($float_type:ident) => { paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use super::*; __test_atomic_float_load_store!([], $float_type); __test_atomic_float!([], $float_type); __test_atomic_float_pub!([], $float_type); } } }; } macro_rules! test_atomic_bool_pub { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod test_atomic_bool { use super::*; __test_atomic_bool_load_store!(AtomicBool); __test_atomic_bool!(AtomicBool); __test_atomic_bool_pub!(AtomicBool); } }; } macro_rules! test_atomic_ptr_pub { () => { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] #[allow(unstable_name_collisions)] // for sptr crate mod test_atomic_ptr { use super::*; __test_atomic_ptr_load_store!(AtomicPtr); __test_atomic_ptr!(AtomicPtr); __test_atomic_ptr_pub!(AtomicPtr); } }; } // Asserts that `$a` and `$b` have performed equivalent operations. #[cfg(feature = "float")] macro_rules! assert_float_op_eq { ($a:expr, $b:expr $(,)?) => {{ // See also: // - https://github.com/rust-lang/unsafe-code-guidelines/issues/237. // - https://github.com/rust-lang/portable-simd/issues/39. let a = $a; let b = $b; if a.is_nan() && b.is_nan() // don't check sign of NaN: https://github.com/rust-lang/rust/issues/55131 || a.is_infinite() && b.is_infinite() && a.is_sign_positive() == b.is_sign_positive() && a.is_sign_negative() == b.is_sign_negative() { // ok } else { assert_eq!(a, b); } }}; } #[allow(clippy::disallowed_methods)] // set_var/remove_var is fine as we run tests with RUST_TEST_THREADS=1 #[cfg_attr(not(portable_atomic_no_track_caller), track_caller)] pub(crate) fn assert_panic(f: impl FnOnce() -> T) -> std::string::String { let backtrace = std::env::var_os("RUST_BACKTRACE"); let hook = std::panic::take_hook(); std::env::set_var("RUST_BACKTRACE", "0"); // Suppress backtrace std::panic::set_hook(std::boxed::Box::new(|_| {})); // Suppress panic msg let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)); std::panic::set_hook(hook); match backtrace { Some(v) => std::env::set_var("RUST_BACKTRACE", v), None => std::env::remove_var("RUST_BACKTRACE"), } let msg = res.unwrap_err(); msg.downcast_ref::() .cloned() .unwrap_or_else(|| msg.downcast_ref::<&'static str>().copied().unwrap().into()) } pub(crate) fn rand_load_ordering() -> Ordering { test_helper::LOAD_ORDERINGS[fastrand::usize(0..test_helper::LOAD_ORDERINGS.len())] } pub(crate) fn test_load_ordering(f: impl Fn(Ordering) -> T) { for &order in &test_helper::LOAD_ORDERINGS { f(order); } if !skip_should_panic_test() { assert_eq!( assert_panic(|| f(Ordering::Release)), "there is no such thing as a release load" ); assert_eq!( assert_panic(|| f(Ordering::AcqRel)), "there is no such thing as an acquire-release load" ); } } pub(crate) fn rand_store_ordering() -> Ordering { test_helper::STORE_ORDERINGS[fastrand::usize(0..test_helper::STORE_ORDERINGS.len())] } pub(crate) fn test_store_ordering(f: impl Fn(Ordering) -> T) { for &order in &test_helper::STORE_ORDERINGS { f(order); } if !skip_should_panic_test() { assert_eq!( assert_panic(|| f(Ordering::Acquire)), "there is no such thing as an acquire store" ); assert_eq!( assert_panic(|| f(Ordering::AcqRel)), "there is no such thing as an acquire-release store" ); } } pub(crate) fn rand_compare_exchange_ordering() -> (Ordering, Ordering) { test_helper::COMPARE_EXCHANGE_ORDERINGS [fastrand::usize(0..test_helper::COMPARE_EXCHANGE_ORDERINGS.len())] } pub(crate) fn test_compare_exchange_ordering( f: impl Fn(Ordering, Ordering) -> T, ) { for &(success, failure) in &test_helper::COMPARE_EXCHANGE_ORDERINGS { f(success, failure); } if !skip_should_panic_test() { for &order in &test_helper::SWAP_ORDERINGS { let msg = assert_panic(|| f(order, Ordering::AcqRel)); assert!( msg == "there is no such thing as an acquire-release failure ordering" || msg == "there is no such thing as an acquire-release load", "{}", msg ); let msg = assert_panic(|| f(order, Ordering::Release)); assert!( msg == "there is no such thing as a release failure ordering" || msg == "there is no such thing as a release load", "{}", msg ); } } } pub(crate) fn rand_swap_ordering() -> Ordering { test_helper::SWAP_ORDERINGS[fastrand::usize(0..test_helper::SWAP_ORDERINGS.len())] } pub(crate) fn test_swap_ordering(f: impl Fn(Ordering) -> T) { for &order in &test_helper::SWAP_ORDERINGS { f(order); } } // for stress test generated by __test_atomic_* macros pub(crate) fn stress_test_config() -> (usize, usize) { let iterations = if cfg!(miri) { 50 } else if cfg!(debug_assertions) { 5_000 } else { 25_000 }; let threads = if cfg!(debug_assertions) { 2 } else { fastrand::usize(2..=8) }; std::eprintln!("threads={}", threads); (iterations, threads) } fn skip_should_panic_test() -> bool { // Miri's panic handling is slow // MSAN false positive: https://gist.github.com/taiki-e/dd6269a8ffec46284fdc764a4849f884 is_panic_abort() || cfg!(miri) || option_env!("CARGO_PROFILE_RELEASE_LTO").map_or(false, |v| v == "fat") && build_context::SANITIZE.contains("memory") } // For -C panic=abort -Z panic_abort_tests: https://github.com/rust-lang/rust/issues/67650 fn is_panic_abort() -> bool { build_context::PANIC.contains("abort") } #[repr(C, align(16))] pub(crate) struct Align16(pub(crate) T); // Test the cases that should not fail if the memory ordering is implemented correctly. // This is still not exhaustive and only tests a few cases. // This currently only supports 32-bit or more integers. macro_rules! __stress_test_acquire_release { (should_pass, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { #[test] fn []() { __stress_test_acquire_release!([], $int_type, $write, $load_order, $store_order); } } }; (can_panic, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { // Currently, to make this test work well enough outside of Miri, tens of thousands // of iterations are needed, but this test is slow in some environments. // So, ignore on non-Miri environments by default. See also catch_unwind_on_weak_memory_arch. #[test] #[cfg_attr(not(miri), ignore)] fn []() { can_panic("a=", || __stress_test_acquire_release!([], $int_type, $write, $load_order, $store_order)); } } }; ($atomic_type:ident, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => {{ use super::*; use crossbeam_utils::thread; use std::{ convert::TryFrom, sync::atomic::{AtomicUsize, Ordering}, }; let mut n: usize = if cfg!(miri) { 10 } else { 50_000 }; // This test is relatively fast because it spawns only one thread, but // the iterations are limited to a maximum value of integers. if $int_type::try_from(n).is_err() { n = $int_type::MAX as usize; } let a = &$atomic_type::new(0); let b = &AtomicUsize::new(0); thread::scope(|s| { s.spawn(|_| { for i in 0..n { b.store(i, Ordering::Relaxed); a.$write(i as _, Ordering::$store_order); } }); loop { let a = a.load(Ordering::$load_order); let b = b.load(Ordering::Relaxed); assert!(a as usize <= b, "a={},b={}", a, b); if a as usize == n - 1 { break; } } }) .unwrap(); }}; } macro_rules! __stress_test_seqcst { (should_pass, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { // Currently, to make this test work well enough outside of Miri, tens of thousands // of iterations are needed, but this test is very slow in some environments because // it creates two threads for each iteration. // So, ignore on QEMU by default. #[test] #[cfg_attr(qemu, ignore)] fn []() { __stress_test_seqcst!([], $write, $load_order, $store_order); } } }; (can_panic, $int_type:ident, $write:ident, $load_order:ident, $store_order:ident) => { paste::paste! { // Currently, to make this test work well enough outside of Miri, tens of thousands // of iterations are needed, but this test is very slow in some environments because // it creates two threads for each iteration. // So, ignore on non-Miri environments by default. See also catch_unwind_on_non_seqcst_arch. #[test] #[cfg_attr(not(miri), ignore)] fn []() { can_panic("c=2", || __stress_test_seqcst!([], $write, $load_order, $store_order)); } } }; ($atomic_type:ident, $write:ident, $load_order:ident, $store_order:ident) => {{ use super::*; use crossbeam_utils::thread; use std::sync::atomic::{AtomicUsize, Ordering}; let n: usize = if cfg!(miri) { 8 } else if cfg!(valgrind) || build_context::SANITIZE.contains("address") || build_context::SANITIZE.contains("memory") { 50 } else if option_env!("GITHUB_ACTIONS").is_some() && cfg!(not(target_os = "linux")) { // GitHub Actions' macOS and Windows runners are slow. 5_000 } else { 50_000 }; let a = &$atomic_type::new(0); let b = &$atomic_type::new(0); let c = &AtomicUsize::new(0); let ready = &AtomicUsize::new(0); thread::scope(|s| { for n in 0..n { a.store(0, Ordering::Relaxed); b.store(0, Ordering::Relaxed); c.store(0, Ordering::Relaxed); let h_a = s.spawn(|_| { while ready.load(Ordering::Relaxed) == 0 {} a.$write(1, Ordering::$store_order); if b.load(Ordering::$load_order) == 0 { c.fetch_add(1, Ordering::Relaxed); } }); let h_b = s.spawn(|_| { while ready.load(Ordering::Relaxed) == 0 {} b.$write(1, Ordering::$store_order); if a.load(Ordering::$load_order) == 0 { c.fetch_add(1, Ordering::Relaxed); } }); ready.store(1, Ordering::Relaxed); h_a.join().unwrap(); h_b.join().unwrap(); let c = c.load(Ordering::Relaxed); assert!(c == 0 || c == 1, "c={},n={}", c, n); } }) .unwrap(); }}; } // Catches unwinding panic on architectures with weak memory models. #[allow(dead_code, clippy::used_underscore_binding)] pub(crate) fn catch_unwind_on_weak_memory_arch(pat: &str, f: impl Fn()) { // With x86 TSO, RISC-V TSO (optional, not default), SPARC TSO (optional, default), // and IBM-370 memory models should never be a panic here. // Miri emulates weak memory models regardless of target architectures. if cfg!(all( any( target_arch = "x86", target_arch = "x86_64", target_arch = "s390x", target_arch = "sparc", target_arch = "sparc64", ), not(any(miri)), )) { f(); } else if !is_panic_abort() { // This could be is_err on architectures with weak memory models. // However, this does not necessarily mean that it will always be panic, // and implementing it with stronger orderings is also okay. match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) { Ok(()) => { // panic!(); } Err(msg) => { let msg = msg .downcast_ref::() .cloned() .unwrap_or_else(|| msg.downcast_ref::<&'static str>().copied().unwrap().into()); assert!(msg.contains(pat), "{}", msg); } } } } // Catches unwinding panic on architectures with non-sequentially consistent memory models. #[allow(dead_code, clippy::used_underscore_binding)] pub(crate) fn catch_unwind_on_non_seqcst_arch(pat: &str, f: impl Fn()) { if !is_panic_abort() { // This could be Err on architectures with non-sequentially consistent memory models. // However, this does not necessarily mean that it will always be panic, // and implementing it with stronger orderings is also okay. match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) { Ok(()) => { // panic!(); } Err(msg) => { let msg = msg .downcast_ref::() .cloned() .unwrap_or_else(|| msg.downcast_ref::<&'static str>().copied().unwrap().into()); assert!(msg.contains(pat), "{}", msg); } } } } macro_rules! stress_test_load_store { ($int_type:ident) => { // debug mode is slow. #[cfg(any(not(debug_assertions), miri))] paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_weak_memory_arch as can_panic; __stress_test_acquire_release!(can_panic, $int_type, store, Relaxed, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, store, Relaxed, Release); __stress_test_acquire_release!(can_panic, $int_type, store, Relaxed, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, store, Acquire, Relaxed); __stress_test_acquire_release!(should_pass, $int_type, store, Acquire, Release); __stress_test_acquire_release!(should_pass, $int_type, store, Acquire, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, store, SeqCst, Relaxed); __stress_test_acquire_release!(should_pass, $int_type, store, SeqCst, Release); __stress_test_acquire_release!(should_pass, $int_type, store, SeqCst, SeqCst); } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_non_seqcst_arch as can_panic; __stress_test_seqcst!(can_panic, $int_type, store, Relaxed, Relaxed); __stress_test_seqcst!(can_panic, $int_type, store, Relaxed, Release); __stress_test_seqcst!(can_panic, $int_type, store, Relaxed, SeqCst); __stress_test_seqcst!(can_panic, $int_type, store, Acquire, Relaxed); __stress_test_seqcst!(can_panic, $int_type, store, Acquire, Release); __stress_test_seqcst!(can_panic, $int_type, store, Acquire, SeqCst); __stress_test_seqcst!(can_panic, $int_type, store, SeqCst, Relaxed); __stress_test_seqcst!(can_panic, $int_type, store, SeqCst, Release); __stress_test_seqcst!(should_pass, $int_type, store, SeqCst, SeqCst); } } }; } macro_rules! stress_test { ($int_type:ident) => { stress_test_load_store!($int_type); // debug mode is slow. #[cfg(any(not(debug_assertions), miri))] paste::paste! { #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_weak_memory_arch as can_panic; __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, Acquire); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, Release); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, AcqRel); __stress_test_acquire_release!(can_panic, $int_type, swap, Relaxed, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, swap, Acquire, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, swap, Acquire, Acquire); __stress_test_acquire_release!(should_pass, $int_type, swap, Acquire, Release); __stress_test_acquire_release!(should_pass, $int_type, swap, Acquire, AcqRel); __stress_test_acquire_release!(should_pass, $int_type, swap, Acquire, SeqCst); __stress_test_acquire_release!(can_panic, $int_type, swap, SeqCst, Relaxed); __stress_test_acquire_release!(can_panic, $int_type, swap, SeqCst, Acquire); __stress_test_acquire_release!(should_pass, $int_type, swap, SeqCst, Release); __stress_test_acquire_release!(should_pass, $int_type, swap, SeqCst, AcqRel); __stress_test_acquire_release!(should_pass, $int_type, swap, SeqCst, SeqCst); } #[allow( clippy::alloc_instead_of_core, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks )] mod [] { use crate::tests::helper::catch_unwind_on_non_seqcst_arch as can_panic; __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, Relaxed); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, Acquire); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, Release); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, AcqRel); __stress_test_seqcst!(can_panic, $int_type, swap, Relaxed, SeqCst); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, Relaxed); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, Acquire); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, Release); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, AcqRel); __stress_test_seqcst!(can_panic, $int_type, swap, Acquire, SeqCst); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, Relaxed); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, Acquire); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, Release); __stress_test_seqcst!(can_panic, $int_type, swap, SeqCst, AcqRel); __stress_test_seqcst!(should_pass, $int_type, swap, SeqCst, SeqCst); } } }; } portable-atomic/src/cfgs.rs0000644000175000017500000003271014661133735016705 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT #![allow(missing_docs)] #[cfg(not(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), )))] #[macro_use] mod atomic_8_16_macros { #[macro_export] macro_rules! cfg_has_atomic_8 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_8 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_has_atomic_16 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_16 { ($($tt:tt)*) => {}; } } #[cfg(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), ))] #[macro_use] mod atomic_8_16_macros { #[macro_export] macro_rules! cfg_has_atomic_8 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_8 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_has_atomic_16 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_16 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg(all( any(not(target_pointer_width = "16"), feature = "fallback"), not(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), )), ))] #[macro_use] mod atomic_32_macros { #[macro_export] macro_rules! cfg_has_atomic_32 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_32 { ($($tt:tt)*) => {}; } } #[cfg(not(all( any(not(target_pointer_width = "16"), feature = "fallback"), not(all( portable_atomic_no_atomic_load_store, not(any( target_arch = "avr", target_arch = "msp430", target_arch = "riscv32", target_arch = "riscv64", feature = "critical-section", )), )), )))] #[macro_use] mod atomic_32_macros { #[macro_export] macro_rules! cfg_has_atomic_32 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_32 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( all( feature = "fallback", any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), not(portable_atomic_no_atomic_64), not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( all( feature = "fallback", any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), )) )] #[macro_use] mod atomic_64_macros { #[macro_export] macro_rules! cfg_has_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_64 { ($($tt:tt)*) => {}; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(any( all( feature = "fallback", any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), not(portable_atomic_no_atomic_64), not(any(target_pointer_width = "16", target_pointer_width = "32")), ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(any( all( feature = "fallback", any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ), ), target_has_atomic = "64", not(any(target_pointer_width = "16", target_pointer_width = "32")), ))) )] #[macro_use] mod atomic_64_macros { #[macro_export] macro_rules! cfg_has_atomic_64 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_64 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg_attr( not(feature = "fallback"), cfg(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all( target_arch = "x86_64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_cmpxchg16b_target_feature), not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), portable_atomic_outline_atomics, // TODO(powerpc64): currently disabled by default any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ), all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch), )) )] #[cfg_attr( all(feature = "fallback", portable_atomic_no_cfg_target_has_atomic), cfg(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[cfg_attr( all(feature = "fallback", not(portable_atomic_no_cfg_target_has_atomic)), cfg(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[macro_use] mod atomic_128_macros { #[macro_export] macro_rules! cfg_has_atomic_128 { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_128 { ($($tt:tt)*) => {}; } } #[cfg_attr( not(feature = "fallback"), cfg(not(any( all( target_arch = "aarch64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), ), all( target_arch = "x86_64", any(not(portable_atomic_no_asm), portable_atomic_unstable_asm), any( target_feature = "cmpxchg16b", portable_atomic_target_feature = "cmpxchg16b", all( feature = "fallback", not(portable_atomic_no_cmpxchg16b_target_feature), not(portable_atomic_no_outline_atomics), not(any(target_env = "sgx", miri)), ), ), ), all( target_arch = "powerpc64", portable_atomic_unstable_asm_experimental_arch, any( target_feature = "quadword-atomics", portable_atomic_target_feature = "quadword-atomics", all( feature = "fallback", not(portable_atomic_no_outline_atomics), portable_atomic_outline_atomics, // TODO(powerpc64): currently disabled by default any( all( target_os = "linux", any( target_env = "gnu", all( any(target_env = "musl", target_env = "ohos"), not(target_feature = "crt-static"), ), portable_atomic_outline_atomics, ), ), target_os = "android", target_os = "freebsd", ), not(any(miri, portable_atomic_sanitize_thread)), ), ), ), all(target_arch = "s390x", portable_atomic_unstable_asm_experimental_arch), ))) )] #[cfg_attr( all(feature = "fallback", portable_atomic_no_cfg_target_has_atomic), cfg(not(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[cfg_attr( all(feature = "fallback", not(portable_atomic_no_cfg_target_has_atomic)), cfg(not(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[macro_use] mod atomic_128_macros { #[macro_export] macro_rules! cfg_has_atomic_128 { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_128 { ($($tt:tt)*) => { $($tt)* }; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", )) )] #[macro_use] mod atomic_cas_macros { #[macro_export] macro_rules! cfg_has_atomic_cas { ($($tt:tt)*) => { $($tt)* }; } #[macro_export] macro_rules! cfg_no_atomic_cas { ($($tt:tt)*) => {}; } } #[cfg_attr( portable_atomic_no_cfg_target_has_atomic, cfg(not(any( not(portable_atomic_no_atomic_cas), portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[cfg_attr( not(portable_atomic_no_cfg_target_has_atomic), cfg(not(any( target_has_atomic = "ptr", portable_atomic_unsafe_assume_single_core, feature = "critical-section", target_arch = "avr", target_arch = "msp430", ))) )] #[macro_use] mod atomic_cas_macros { #[macro_export] macro_rules! cfg_has_atomic_cas { ($($tt:tt)*) => {}; } #[macro_export] macro_rules! cfg_no_atomic_cas { ($($tt:tt)*) => { $($tt)* }; } } // Check that all cfg_ macros work. mod check { crate::cfg_has_atomic_8! { type _Atomic8 = (); } crate::cfg_no_atomic_8! { type _Atomic8 = (); } crate::cfg_has_atomic_16! { type _Atomic16 = (); } crate::cfg_no_atomic_16! { type _Atomic16 = (); } crate::cfg_has_atomic_32! { type _Atomic32 = (); } crate::cfg_no_atomic_32! { type _Atomic32 = (); } crate::cfg_has_atomic_64! { type _Atomic64 = (); } crate::cfg_no_atomic_64! { type _Atomic64 = (); } crate::cfg_has_atomic_128! { type _Atomic128 = (); } crate::cfg_no_atomic_128! { type _Atomic128 = (); } crate::cfg_has_atomic_ptr! { type _AtomicPtr = (); } crate::cfg_no_atomic_ptr! { type _AtomicPtr = (); } crate::cfg_has_atomic_cas! { type __AtomicPtr = (); } crate::cfg_no_atomic_cas! { type __AtomicPtr = (); } #[allow(unused_imports)] use { _Atomic128 as _, _Atomic16 as _, _Atomic32 as _, _Atomic64 as _, _Atomic8 as _, _AtomicPtr as _, __AtomicPtr as _, }; } portable-atomic/CHANGELOG.md0000644000175000017500000006122514661133735016442 0ustar jamespagejamespage# Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org). ## [Unreleased] ## [1.6.0] - 2023-12-06 - Add `cfg_{has,no}_atomic_{8,16,32,64,128,ptr}` macros to enable code when the corresponding atomic implementation is available/unavailable. - Add `cfg_{has,no}_atomic_cas` macros to enable code when atomic CAS/RMW implementation is available/unavailable. - Improve support for RISC-V targets without atomic CAS. ## [1.5.1] - 2023-10-29 - Fix bug in `i{8,16}` `fetch_{or,xor}` on RISC-V without A-extension where `unsafe-assume-single-core` and `force-amo` are enabled. - Optimize `swap` for targets that do not have native atomic CAS instructions. ## [1.5.0] - 2023-10-23 **Note:** This release has been yanked due to a bug fixed in 1.5.1. - Add `from_ptr`. - Add `force-amo` feature (`portable_atomic_force_amo` cfg) for single-core RISC-V without A-extension. ([#124](https://github.com/taiki-e/portable-atomic/pull/124)) - Support run-time detection on AArch64 on pre-1.61 rustc. ([#98](https://github.com/taiki-e/portable-atomic/pull/98)) This also solves [a compatibility issue with rustc_codegen_cranelift](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1400). - Support run-time detection of FEAT_LSE2. ([#126](https://github.com/taiki-e/portable-atomic/pull/126)) - Support run-time detection of FEAT_LSE on AArch64 NetBSD. ([#66](https://github.com/taiki-e/portable-atomic/pull/66)) - Acknowledge ESP-IDF targets' 64-bit atomics are not lock-free. See [#122](https://github.com/taiki-e/portable-atomic/issues/122) for more. - Optimize 128-bit weak CAS on powerpc64. - Optimize interrupt disable on no-std pre-v6 ARM where `unsafe-assume-single-core` and `disable-fiq` are enabled. ([771c45d](https://github.com/taiki-e/portable-atomic/commit/771c45da2d2afc4f83df033dd4bdf3f976d14a74)) - Improve detection of Apple hardware. ([5c3a43b](https://github.com/taiki-e/portable-atomic/commit/5c3a43b53f1c4188f9dd597599633bc1a315bf44)) - Improve compatibility with the future version of Miri. ## [1.4.3] - 2023-08-25 - Optimize AArch64 128-bit atomic store/swap/fetch_and/fetch_or when the `lse128` target feature is enabled at compile-time. ([#68](https://github.com/taiki-e/portable-atomic/pull/68)) - Optimize AArch64 128-bit atomic load/store when the `rcpc3` target feature is enabled at compile-time. ([#68](https://github.com/taiki-e/portable-atomic/pull/68)) - Optimize inline assemblies on ARM, AArch64, and MSP430. ## [1.4.2] - 2023-07-27 - Optimize `AtomicBool` on RISC-V/LoongArch64. This is the same as [rust-lang/rust#114034](https://github.com/rust-lang/rust/pull/114034), but is available for all rustc versions. ## [1.4.1] - 2023-07-15 - Improve compatibility with the future version of Miri. ## [1.4.0] - 2023-07-11 - Allow using embedded-related cfgs as Cargo features. ([#94](https://github.com/taiki-e/portable-atomic/pull/94), thanks @Dirbaio) Originally, we were providing these as cfgs instead of features, but based on a strong request from the embedded ecosystem, we have agreed to provide them as features as well. See [#94](https://github.com/taiki-e/portable-atomic/pull/94) for more. cfgs are kept and can be used as aliases for features. - Acknowledge all x86_64 Apple targets support 128-bit atomics. Our code already recognizes this via `cfg(target_feature)`, so this only affects docs and users using pre-1.69 stable rustc. See also [rust-lang/rust#112150](https://github.com/rust-lang/rust/pull/112150). - Optimize 128-bit atomics on aarch64/s390x. ## [1.3.3] - 2023-05-31 - Fix build error on aarch64 ILP32 ABI targets (tier 3). - Optimize 128-bit atomics on s390x. ## [1.3.2] - 2023-05-09 - Fix bug in powerpc64/s390x 128-bit atomic RMWs on old nightly. - Optimize 128-bit atomics on powerpc64/s390x. ## [1.3.1] - 2023-05-07 - Documentation improvements. ## [1.3.0] - 2023-05-06 - Add `require-cas` feature. ([#100](https://github.com/taiki-e/portable-atomic/pull/100)) If your crate supports no-std environment and requires atomic CAS, enabling this feature will allow the `portable-atomic` to display helpful error messages to users on targets requiring additional action on the user side to provide atomic CAS. ```toml [dependencies] portable-atomic = { version = "1.3", default-features = false, features = ["require-cas"] } ``` See [#100](https://github.com/taiki-e/portable-atomic/pull/100) for more. - Support `portable_atomic_unsafe_assume_single_core` cfg on Xtensa targets without atomic CAS. ([#86](https://github.com/taiki-e/portable-atomic/pull/86)) - Fix bug in AArch64 128-bit SeqCst load when FEAT_LSE2 is enabled at compile-time. This is [the same bug that was fixed in the recently released GCC 13.1](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108891). LLVM also has the same bug, which had not yet been fixed when the patch was created; I will open a bug report if necessary after looking into the situation in LLVM. ([a29154b](https://github.com/taiki-e/portable-atomic/commit/a29154b21da270e90cb86f6865b591ab36eade7d)) - Fix compile error on `bpf{eb,el}-unknown-none` (tier 3) and `mipsel-sony-psx` (tier 3) when `critical-section` feature is disabled. - Various optimizations - Optimize x86_64 128-bit outline-atomics. This improves performance by up to 15% in concurrent RMW/store for cases where the `cmpxchg16b` target feature is not available at compile-time. ([40c4cd4](https://github.com/taiki-e/portable-atomic/commit/40c4cd4f682f1cb153f18d4d6a88795bafaf5667)) - Optimize x86_64 128-bit load that uses cmpxchg16b. ([40c4cd4](https://github.com/taiki-e/portable-atomic/commit/40c4cd4f682f1cb153f18d4d6a88795bafaf5667)) - Optimize aarch64 128-bit load that uses FEAT_LSE. ([40c4cd4](https://github.com/taiki-e/portable-atomic/commit/40c4cd4f682f1cb153f18d4d6a88795bafaf5667)) - Optimize pre-ARMv6 Linux/Android 64-bit atomics. ([efacc89](https://github.com/taiki-e/portable-atomic/commit/efacc89c210d7a34ef5e879821112189da5d1901)) - Support outline-atomics for powerpc64 128-bit atomics. This is currently disabled by default, and can be enabled by `--cfg portable_atomic_outline_atomics`. ([#90](https://github.com/taiki-e/portable-atomic/pull/90)) - Optimize aarch64 outline-atomics on linux-musl. On linux-musl, outline-atomics is enabled by default only when dynamic linking is enabled. When static linking is enabled, this can be enabled by `--cfg portable_atomic_outline_atomics`. See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md#run-time-feature-detection) for more. ([8418235](https://github.com/taiki-e/portable-atomic/commit/84182354e4a149074e28bda4683d538e5fb617ce), [31d0862](https://github.com/taiki-e/portable-atomic/commit/31d08623d4e21af207ff2343f5553b9b5a030452)) ## [1.2.0] - 2023-03-25 - Make 64-bit atomics lock-free on ARM Linux/Android targets that do not have 64-bit atomics (e.g., armv5te-unknown-linux-gnueabi, arm-linux-androideabi, etc.) when the kernel version is 3.1 or later. ([#82](https://github.com/taiki-e/portable-atomic/pull/82)) - Fix aarch64 128-bit atomics performance regression on Apple hardware. ([#89](https://github.com/taiki-e/portable-atomic/pull/89)) - Optimize 128-bit atomics on aarch64, x86_64, powerpc64, and s390x. ## [1.1.0] - 2023-03-24 - Add `Atomic{I,U}*::bit_{set,clear,toggle}` and `AtomicPtr::bit_{set,clear,toggle}`. ([#72](https://github.com/taiki-e/portable-atomic/pull/72)) They correspond to x86's `lock bt{s,r,c}`, and the implementation calls them on x86/x86_64. - Add `AtomicU*::{fetch_neg,neg}` methods. Previously it was only available on `AtomicI*` and `AtomicF*`. - Add `as_ptr` method to all atomic types. ([#79](https://github.com/taiki-e/portable-atomic/pull/79)) - Make `AtomicF{32,64}::as_bits` const on Rust 1.58+. ([#79](https://github.com/taiki-e/portable-atomic/pull/79)) - Relax ordering in `Serialize` impl to reflect the [upstream change](https://github.com/serde-rs/serde/pull/2263). - Optimize x86_64 outline-atomics for 128-bit atomics. - Support outline-atomics for cmpxchg16b on Rust 1.69+ (i.e., on Rust 1.69+, x86_64 128-bit atomics is lock-free on all Intel chips and almost all AMD chips, even if cmpxchg16b is not available at compile-time.). Previously it was only nightly. ([#80](https://github.com/taiki-e/portable-atomic/pull/80)) - portable-atomic no longer enables outline-atomics on target where run-time feature detection is not available. ([#80](https://github.com/taiki-e/portable-atomic/pull/80)) - Optimize aarch64 outline-atomics for 128-bit atomics. - Support more targets and improve performance. ([#63](https://github.com/taiki-e/portable-atomic/pull/63), [#64](https://github.com/taiki-e/portable-atomic/pull/64), [#67](https://github.com/taiki-e/portable-atomic/pull/67), [#69](https://github.com/taiki-e/portable-atomic/pull/69), [#75](https://github.com/taiki-e/portable-atomic/pull/75), [#76](https://github.com/taiki-e/portable-atomic/pull/76), [#77](https://github.com/taiki-e/portable-atomic/pull/77)) See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md#run-time-feature-detection) for a list of platforms that support outline-atomics. Most of these improvements have already been [submitted and accepted in rust-lang/stdarch](https://github.com/rust-lang/stdarch/pulls?q=is%3Apr+author%3Ataiki-e+std_detect) and will soon be available in `std::arch::is_aarch64_feature_detected`. - portable-atomic no longer enables outline-atomics on target where run-time feature detection is not available. - Performance improvements. ([#70](https://github.com/taiki-e/portable-atomic/pull/70), [#81](https://github.com/taiki-e/portable-atomic/pull/81), [6c189ae](https://github.com/taiki-e/portable-atomic/commit/6c189ae1792ce0c08b4f56b6e6c256c223475ce2), [13c92b0](https://github.com/taiki-e/portable-atomic/commit/13c92b015a8e8646a4b885229157547354d03b9e), etc.) - Improve support for old nightly. ([#73](https://github.com/taiki-e/portable-atomic/pull/73), [872feb9](https://github.com/taiki-e/portable-atomic/commit/872feb9d7f3a4ca7cf9b63935265d46498fcae99)) - Documentation improvements. ## [1.0.1] - 2023-01-21 - Optimize `Atomic{I,U}*::{fetch_not,not}` methods. ([#62](https://github.com/taiki-e/portable-atomic/pull/62)) ## [1.0.0] - 2023-01-15 - Add `critical-section` feature to use [critical-section](https://github.com/rust-embedded/critical-section) on targets where atomic CAS is not natively available. ([#51](https://github.com/taiki-e/portable-atomic/pull/51), thanks @Dirbaio) This is useful to get atomic CAS when `--cfg portable_atomic_unsafe_assume_single_core` can't be used, such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts needs extra care due to e.g. real-time requirements. See [documentation](https://github.com/taiki-e/portable-atomic#optional-features-critical-section) for more. - Remove `outline-atomics` feature. This was no-op since 0.3.19. - Documentation improvements. ## [0.3.20] - 2023-05-07 The latest version of portable-atomic is 1.x. This release makes portable-atomic 0.3 is built on top of portable-atomic 1.x to make bug fixes and improvements such as [support for new targets](https://github.com/taiki-e/portable-atomic/pull/86) in 1.x available to the ecosystem that depends on older portable-atomic. portable-atomic 0.3 is still maintained passively, but upgrading to portable-atomic 1.x is recommended. (There are no breaking changes from 0.3, except that a deprecated no-op `outline-atomics` Cargo feature has been removed.) ([#99](https://github.com/taiki-e/portable-atomic/pull/99)) ## [0.3.19] - 2022-12-25 - Add `AtomicI*::{fetch_neg,neg}` and `AtomicF*::fetch_neg` methods. ([#54](https://github.com/taiki-e/portable-atomic/pull/54)) `AtomicI*::neg` are equivalent to the corresponding `fetch_*` methods, but do not return the previous value. They are intended for optimization on platforms that have atomic instructions for the corresponding operation, such as x86's `lock neg`. Currently, optimizations by these methods (`neg`) are only guaranteed for x86/x86_64. - Add `Atomic{I,U}*::{fetch_not,not}` methods. ([#54](https://github.com/taiki-e/portable-atomic/pull/54)) `Atomic{I,U}*::not` are equivalent to the corresponding `fetch_*` methods, but do not return the previous value. They are intended for optimization on platforms that have atomic instructions for the corresponding operation, such as x86's `lock not`, MSP430's `inv`. Currently, optimizations by these methods (`not`) are only guaranteed for x86/x86_64 and MSP430. (Note: `AtomicBool` already has `fetch_not` and `not` methods.) - Enable outline-atomics for 128-bit atomics by default. ([#57](https://github.com/taiki-e/portable-atomic/pull/57)) See [#57](https://github.com/taiki-e/portable-atomic/pull/57) for more. - Improve support for old nightly compilers. ## [0.3.18] - 2022-12-15 - Fix build error when not using `portable_atomic_unsafe_assume_single_core` cfg on AVR and MSP430 custom targets. ([#50](https://github.com/taiki-e/portable-atomic/pull/50)) Since 0.3.11, atomic CAS was supported without the cfg on AVR and MSP430 builtin targets, but that change was not applied to custom targets. ## [0.3.17] - 2022-12-14 - Optimize x86_64 128-bit atomic load/store on AMD CPU with AVX. ([#49](https://github.com/taiki-e/portable-atomic/pull/49)) - Improve support for custom targets on old rustc. ## [0.3.16] - 2022-12-09 - Add `Atomic{I,U}*::{add,sub,and,or,xor}` and `AtomicBool::{and,or,xor}` methods. ([#47](https://github.com/taiki-e/portable-atomic/pull/47)) They are equivalent to the corresponding `fetch_*` methods, but do not return the previous value. They are intended for optimization on platforms that implement atomics using inline assembly, such as the MSP430. Currently, optimizations by these methods (`add`,`sub`,`and`,`or`,`xor`) are only guaranteed for MSP430; on x86/x86_64, LLVM can optimize in most cases, so cases, where this would improve things, should be rare. - Various improvements to `portable_atomic_unsafe_assume_single_core` cfg. ([#44](https://github.com/taiki-e/portable-atomic/pull/44), [#40](https://github.com/taiki-e/portable-atomic/pull/40)) - Support disabling FIQs on pre-v6 ARM under `portable_atomic_disable_fiq` cfg. - Support RISC-V supervisor mode under `portable_atomic_s_mode` cfg. - Optimize interrupt restore on AVR and MSP430. ([#40](https://github.com/taiki-e/portable-atomic/pull/40)) - Documentation improvements. See [#44](https://github.com/taiki-e/portable-atomic/pull/44) for more. ## [0.3.15] - 2022-09-09 - Implement workaround for std cpuid bug due to LLVM bug ([rust-lang/rust#101346](https://github.com/rust-lang/rust/issues/101346), [llvm/llvm-project#57550](https://github.com/llvm/llvm-project/issues/57550)). - Our use case is likely not affected, but we implement this just in case. - We've confirmed that the uses of inline assembly in this crate are not affected by this LLVM bug. ## [0.3.14] - 2022-09-04 - Optimize atomic load/store on no-std pre-v6 ARM when `portable_atomic_unsafe_assume_single_core` cfg is used. ([#36](https://github.com/taiki-e/portable-atomic/pull/36)) - Support pre-power8 powerpc64le. powerpc64le's default cpu version is power8, but you can technically compile it for the old cpu using the unsafe `-C target-cpu` rustc flag. ## [0.3.13] - 2022-08-15 - Use track_caller when debug assertions are enabled on Rust 1.46+. - Make powerpc64 128-bit atomics compatible with Miri and ThreadSanitizer on LLVM 15+. - Document that 128-bit atomics are compatible with Miri and ThreadSanitizer on recent nightly. ## [0.3.12] - 2022-08-13 - Support atomic CAS on no-std pre-v6 ARM targets (e.g., thumbv4t-none-eabi) under unsafe cfg `portable_atomic_unsafe_assume_single_core`. ([#28](https://github.com/taiki-e/portable-atomic/pull/28)) ## [0.3.11] - 2022-08-12 - Always provide atomic CAS for MSP430 and AVR. ([#31](https://github.com/taiki-e/portable-atomic/pull/31)) This previously required unsafe cfg `portable_atomic_unsafe_assume_single_core`, but since all MSP430 and AVR are single-core, we can safely provide atomic CAS based on disabling interrupts. - Support `fence` and `compiler_fence` on MSP430. (On MSP430, the standard library's fences are currently unavailable due to LLVM errors.) - Update safety requirements for unsafe cfg `portable_atomic_unsafe_assume_single_core` to mention use of privileged instructions to disable interrupts. - Atomic operations based on disabling interrupts on single-core systems are now considered lock-free. The previous behavior was inconsistent because we consider the pre-v6 ARM Linux's atomic operations provided in a similar way by the Linux kernel to be lock-free. - Respect `-Z allow-features`. ## [0.3.10] - 2022-08-03 - Optimize AArch64 128-bit atomic load when the `lse` target feature is enabled at compile-time. ([#20](https://github.com/taiki-e/portable-atomic/pull/20)) ## [0.3.9] - 2022-08-03 - Fix build error on old Miri. - Documentation improvements. ## [0.3.8] - 2022-08-02 - Make AArch64 and s390x 128-bit atomics compatible with Miri and ThreadSanitizer. ## [0.3.7] - 2022-07-31 - Provide stable equivalent of [`#![feature(strict_provenance_atomic_ptr)]`](https://github.com/rust-lang/rust/issues/99108). ([#23](https://github.com/taiki-e/portable-atomic/pull/23)) - `AtomicPtr::fetch_ptr_{add,sub}` - `AtomicPtr::fetch_byte_{add,sub}` - `AtomicPtr::fetch_{or,and,xor}` These APIs are compatible with strict-provenance on `cfg(miri)`. Otherwise, they are compatible with permissive-provenance. Once `#![feature(strict_provenance_atomic_ptr)]` is stabilized, these APIs will be strict-provenance compatible in all cases from the version in which it is stabilized. - Provide stable equivalent of [`#![feature(atomic_bool_fetch_not)]`](https://github.com/rust-lang/rust/issues/98485). ([#24](https://github.com/taiki-e/portable-atomic/pull/24)) - `AtomicBool::fetch_not` - Optimize x86_64 128-bit RMWs. ([#22](https://github.com/taiki-e/portable-atomic/pull/22)) - Optimize x86_64 outline-atomics. - Optimize inline assemblies on ARM and AArch64. - Revert [thumbv6m atomic load/store changes made in 0.3.5](https://github.com/taiki-e/portable-atomic/pull/18). This is because [rust-lang/rust#99595](https://github.com/rust-lang/rust/pull/99595) has been reverted, so this is no longer needed. ## [0.3.6] - 2022-07-26 - Fix build failure due to the existence of the `specs` directory. - Documentation improvements. - Optimize inline assemblies on x86_64, RISC-V, and MSP430. ## [0.3.5] - 2022-07-23 **Note:** This release has been yanked due to a bug fixed in 0.3.6. - Provide thumbv6m atomic load/store which is planned to be removed from the standard library in [rust-lang/rust#99595](https://github.com/rust-lang/rust/pull/99595). ([#18](https://github.com/taiki-e/portable-atomic/pull/18)) - Optimize inline assemblies on AArch64, RISC-V, and powerpc64. ## [0.3.4] - 2022-06-25 - Optimize x86_64 128-bit atomic store. ## [0.3.3] - 2022-06-24 - Allow CAS failure ordering stronger than success ordering. ([#17](https://github.com/taiki-e/portable-atomic/pull/17)) ## [0.3.2] - 2022-06-19 - Optimize x86_64 128-bit atomic load/store on Intel CPU with AVX. ([#16](https://github.com/taiki-e/portable-atomic/pull/16)) - Support native 128-bit atomic operations for powerpc64 (le or pwr8+, currently nightly-only). - Fix behavior differences between stable and nightly. ([#15](https://github.com/taiki-e/portable-atomic/pull/15)) ## [0.3.1] - 2022-06-16 - Optimize AArch64 128-bit atomic load/store when the `lse2` target feature is enabled at compile-time. ([#11](https://github.com/taiki-e/portable-atomic/pull/11)) - Relax ordering in `Debug` impl to reflect std changes. ([#12](https://github.com/taiki-e/portable-atomic/pull/12)) ## [0.3.0] - 2022-03-25 - Support native 128-bit atomic operations for s390x (currently nightly-only). - Add `AtomicF{32,64}::fetch_abs`. - Add `#[must_use]` to constructors. - Use 128-bit atomic operation mappings same as LLVM on AArch64. - Remove `parking_lot` optional feature to allow the use of this crate within global allocators. ## [0.2.1] - 2022-03-17 - Implement AArch64 outline-atomics. ## [0.2.0] - 2022-03-10 - Remove `i128` feature. `Atomic{I,U}128` are now always enabled. - Add `outline-atomics` feature. Currently, this is the same as the 0.1's `i128-dynamic`, except that `fallback` feature is not implicitly enabled. - Remove `i128-dynamic` feature in favor of `outline-atomics` feature. - Add `AtomicF{32,64}::as_bits`. ## [0.1.4] - 2022-03-02 - Support native 128-bit atomic operations for AArch64 at Rust 1.59+. This was previously supported only on nightly. ([#6](https://github.com/taiki-e/portable-atomic/pull/6)) ## [0.1.3] - 2022-02-28 - Fix inline assembly for RISC-V without A-extension. ## [0.1.2] - 2022-02-26 **Note:** This release has been yanked due to a bug fixed in 0.1.3. - Add `parking_lot` feature to use parking_lot in global locks of fallback implementation. - Fix bug in cmpxchg16b support. ([#5](https://github.com/taiki-e/portable-atomic/pull/5)) ## [0.1.1] - 2022-02-25 **Note:** This release has been yanked due to a bug fixed in 0.1.3. - Fix doc cfg on `Atomic{I,U}128`. ## [0.1.0] - 2022-02-24 **Note:** This release has been yanked due to a bug fixed in 0.1.3. Initial release [Unreleased]: https://github.com/taiki-e/portable-atomic/compare/v1.6.0...HEAD [1.6.0]: https://github.com/taiki-e/portable-atomic/compare/v1.5.1...v1.6.0 [1.5.1]: https://github.com/taiki-e/portable-atomic/compare/v1.5.0...v1.5.1 [1.5.0]: https://github.com/taiki-e/portable-atomic/compare/v1.4.3...v1.5.0 [1.4.3]: https://github.com/taiki-e/portable-atomic/compare/v1.4.2...v1.4.3 [1.4.2]: https://github.com/taiki-e/portable-atomic/compare/v1.4.1...v1.4.2 [1.4.1]: https://github.com/taiki-e/portable-atomic/compare/v1.4.0...v1.4.1 [1.4.0]: https://github.com/taiki-e/portable-atomic/compare/v1.3.3...v1.4.0 [1.3.3]: https://github.com/taiki-e/portable-atomic/compare/v1.3.2...v1.3.3 [1.3.2]: https://github.com/taiki-e/portable-atomic/compare/v1.3.1...v1.3.2 [1.3.1]: https://github.com/taiki-e/portable-atomic/compare/v1.3.0...v1.3.1 [1.3.0]: https://github.com/taiki-e/portable-atomic/compare/v1.2.0...v1.3.0 [1.2.0]: https://github.com/taiki-e/portable-atomic/compare/v1.1.0...v1.2.0 [1.1.0]: https://github.com/taiki-e/portable-atomic/compare/v1.0.1...v1.1.0 [1.0.1]: https://github.com/taiki-e/portable-atomic/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/taiki-e/portable-atomic/compare/v0.3.19...v1.0.0 [0.3.20]: https://github.com/taiki-e/portable-atomic/compare/v0.3.19...v0.3.20 [0.3.19]: https://github.com/taiki-e/portable-atomic/compare/v0.3.18...v0.3.19 [0.3.18]: https://github.com/taiki-e/portable-atomic/compare/v0.3.17...v0.3.18 [0.3.17]: https://github.com/taiki-e/portable-atomic/compare/v0.3.16...v0.3.17 [0.3.16]: https://github.com/taiki-e/portable-atomic/compare/v0.3.15...v0.3.16 [0.3.15]: https://github.com/taiki-e/portable-atomic/compare/v0.3.14...v0.3.15 [0.3.14]: https://github.com/taiki-e/portable-atomic/compare/v0.3.13...v0.3.14 [0.3.13]: https://github.com/taiki-e/portable-atomic/compare/v0.3.12...v0.3.13 [0.3.12]: https://github.com/taiki-e/portable-atomic/compare/v0.3.11...v0.3.12 [0.3.11]: https://github.com/taiki-e/portable-atomic/compare/v0.3.10...v0.3.11 [0.3.10]: https://github.com/taiki-e/portable-atomic/compare/v0.3.9...v0.3.10 [0.3.9]: https://github.com/taiki-e/portable-atomic/compare/v0.3.8...v0.3.9 [0.3.8]: https://github.com/taiki-e/portable-atomic/compare/v0.3.7...v0.3.8 [0.3.7]: https://github.com/taiki-e/portable-atomic/compare/v0.3.6...v0.3.7 [0.3.6]: https://github.com/taiki-e/portable-atomic/compare/v0.3.5...v0.3.6 [0.3.5]: https://github.com/taiki-e/portable-atomic/compare/v0.3.4...v0.3.5 [0.3.4]: https://github.com/taiki-e/portable-atomic/compare/v0.3.3...v0.3.4 [0.3.3]: https://github.com/taiki-e/portable-atomic/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/taiki-e/portable-atomic/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/taiki-e/portable-atomic/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/taiki-e/portable-atomic/compare/v0.2.1...v0.3.0 [0.2.1]: https://github.com/taiki-e/portable-atomic/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/taiki-e/portable-atomic/compare/v0.1.4...v0.2.0 [0.1.4]: https://github.com/taiki-e/portable-atomic/compare/v0.1.3...v0.1.4 [0.1.3]: https://github.com/taiki-e/portable-atomic/compare/v0.1.2...v0.1.3 [0.1.2]: https://github.com/taiki-e/portable-atomic/compare/v0.1.1...v0.1.2 [0.1.1]: https://github.com/taiki-e/portable-atomic/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/taiki-e/portable-atomic/releases/tag/v0.1.0 portable-atomic/version.rs0000644000175000017500000001017614661133735016663 0ustar jamespagejamespage// SPDX-License-Identifier: Apache-2.0 OR MIT use std::{env, process::Command, str}; pub(crate) fn rustc_version() -> Option { let rustc = env::var_os("RUSTC")?; // Use verbose version output because the packagers add extra strings to the normal version output. let output = Command::new(rustc).args(&["--version", "--verbose"]).output().ok()?; let verbose_version = str::from_utf8(&output.stdout).ok()?; Version::parse(verbose_version) } #[cfg_attr(test, derive(Debug, PartialEq))] pub(crate) struct Version { pub(crate) minor: u32, pub(crate) nightly: bool, commit_date: Date, pub(crate) llvm: u32, } impl Version { // The known latest stable version. If we unable to determine // the rustc version, we assume this is the current version. // It is no problem if this is older than the actual latest stable. // LLVM version is assumed to be the minimum external LLVM version: // https://github.com/rust-lang/rust/blob/1.74.0/src/bootstrap/llvm.rs#L558 pub(crate) const LATEST: Self = Self::stable(74, 15); pub(crate) const fn stable(rustc_minor: u32, llvm_major: u32) -> Self { Self { minor: rustc_minor, nightly: false, commit_date: Date::UNKNOWN, llvm: llvm_major } } pub(crate) fn probe(&self, minor: u32, year: u16, month: u8, day: u8) -> bool { if self.nightly { self.minor > minor || self.commit_date >= Date::new(year, month, day) } else { self.minor >= minor } } #[cfg(test)] pub(crate) fn commit_date(&self) -> &Date { &self.commit_date } pub(crate) fn parse(verbose_version: &str) -> Option { let mut release = verbose_version .lines() .find(|line| line.starts_with("release: ")) .map(|line| &line["release: ".len()..])? .splitn(2, '-'); let version = release.next().unwrap(); let channel = release.next().unwrap_or_default(); let mut digits = version.splitn(3, '.'); let major = digits.next()?.parse::().ok()?; if major != 1 { return None; } let minor = digits.next()?.parse::().ok()?; let _patch = digits.next().unwrap_or("0").parse::().ok()?; let nightly = channel == "nightly" || channel == "dev"; let llvm_major = (|| { let version = verbose_version .lines() .find(|line| line.starts_with("LLVM version: ")) .map(|line| &line["LLVM version: ".len()..])?; let mut digits = version.splitn(3, '.'); let major = digits.next()?.parse::().ok()?; let _minor = digits.next()?.parse::().ok()?; let _patch = digits.next().unwrap_or("0").parse::().ok()?; Some(major) })() .unwrap_or(0); // we don't refer commit date on stable/beta. if nightly { let commit_date = (|| { let mut commit_date = verbose_version .lines() .find(|line| line.starts_with("commit-date: ")) .map(|line| &line["commit-date: ".len()..])? .splitn(3, '-'); let year = commit_date.next()?.parse::().ok()?; let month = commit_date.next()?.parse::().ok()?; let day = commit_date.next()?.parse::().ok()?; if month > 12 || day > 31 { return None; } Some(Date::new(year, month, day)) })(); Some(Self { minor, nightly, commit_date: commit_date.unwrap_or(Date::UNKNOWN), llvm: llvm_major, }) } else { Some(Self::stable(minor, llvm_major)) } } } #[derive(PartialEq, PartialOrd)] #[cfg_attr(test, derive(Debug))] pub(crate) struct Date { pub(crate) year: u16, pub(crate) month: u8, pub(crate) day: u8, } impl Date { const UNKNOWN: Self = Self::new(0, 0, 0); const fn new(year: u16, month: u8, day: u8) -> Self { Self { year, month, day } } } portable-atomic/.cargo-checksum.json0000664000175000017500000001071414661133735020474 0ustar jamespagejamespage{"files":{"CHANGELOG.md":"e7dafc5269137adcaaddbd78bd6fa5c42121598e115c9c2fcad64f1295b9397d","Cargo.toml":"7378ac02801e3740ae2d2052e2efde1669907b3198a665a8712b59762b765eaa","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"85091dd4fe4bd5a09ca7a32a8289814688803b3a42bbae49cb222912b20fe84f","build.rs":"76d2ad8feb99253317b299b70675f524fe4977439acc3cb0210498e10cdde467","no_atomic.rs":"f3cbde2210b7275786334ac8baa6900da591f7dc72c1c15f958b059a4faec9e2","src/cfgs.rs":"a6c3ebc8c4a7a3e1b6764d4548e0656df7f0fbd1111b8fb985067c59abe10f6f","src/gen/utils.rs":"c2fedb10f6ffaeaab452448035411d320b022ac8b40bd7d39a9915a1721bfd9c","src/imp/arm_linux.rs":"db5f26797ae08ca94ddefd70eb1686892ff337399f6d69febba9990a179b28cf","src/imp/atomic128/README.md":"ab18c8b14daf59254b50b10073e15ea83a2a5d05923e7676a1c1817d93677c62","src/imp/atomic128/aarch64.rs":"97391aa4e91892ff907482558d93fc99d921f23262328de6e7e220a26dd3ddae","src/imp/atomic128/detect/aarch64_aa64reg.rs":"623cd4b1abd456394a11d9abd9fc0019aa872bbeaf24a1e03b1befa5a1432bd6","src/imp/atomic128/detect/aarch64_fuchsia.rs":"4fa7ca4676a26b832b128f56c8fdf89509ebf500c79fce3261559cb3fab8d96f","src/imp/atomic128/detect/aarch64_macos.rs":"f0fc115eafa758c4bbf67876e947292a7fe91705edaa66d4f801f7a3b6a8ab26","src/imp/atomic128/detect/aarch64_windows.rs":"946d40c46cde3dc5fb752c663bdd55f8eb9da6786c2c55f4d0d63e65e336f773","src/imp/atomic128/detect/auxv.rs":"69e938e157a737fdc8fd7b2bd7d5e02d25e0e4ed750f290bce8de73d5452b2ef","src/imp/atomic128/detect/common.rs":"dfe6096fad93071f7a47d75cfdafc6c7e4075e4545a10ed69dd1f858511288b5","src/imp/atomic128/detect/x86_64.rs":"e07734056d5da7c6d44770b89218cb97aadc2a13edbcd8c3c90db09c8f7b262a","src/imp/atomic128/intrinsics.rs":"ea0fc4eabe519d43b66f908564b1d0d1f49529f9c397aeb1ede94600b3ff02e6","src/imp/atomic128/macros.rs":"41ee6ec2d04083306e2552b194ecd9557514618cd856bcf967f4f7a6ebf6f85a","src/imp/atomic128/powerpc64.rs":"f5341e1efb9924c7292ac4cdb8f2168c28d7e9bbc3328e5c0688a7b4467c6065","src/imp/atomic128/s390x.rs":"341f33441149798a7fceb585326c6eb0541bf9594f6bdd926306af7b859f5b74","src/imp/atomic128/x86_64.rs":"5fecbefb4bb366e2811fdafab3d9dabb016577bd05240467cf82a4fde66558fc","src/imp/core_atomic.rs":"b8547eea89e18fd06959dd72afb37d218f561415ebe5d917ff66500c1c77ae62","src/imp/fallback/mod.rs":"c464f4fa00d79c56da919ab11eaef91e4ecd771d5d75e95cb5de8e4633542505","src/imp/fallback/outline_atomics.rs":"0cf233a0b0d5861e90eb443c55352308659fda209bbb0eac3b7db30ea90e3d4d","src/imp/fallback/seq_lock.rs":"b591a77f202095e31c855f61932145e85206a489ee1a0b23b89e4411ef02807e","src/imp/fallback/seq_lock_wide.rs":"e8f22b7bda9eb7b55c4c216dd78a2c4e3ca3ba8fda3385d1a55605e302d39f53","src/imp/fallback/utils.rs":"4800db994c3995e44d1ce5ec31f741a212a64481bbd90f86cc4327f90e7d7b05","src/imp/float.rs":"20b9b64298e236cd86c930b9e40085688fa10b359a7cbe346d39c7202920a6ad","src/imp/interrupt/README.md":"396d099bf7519755780fef3933657022bd5e9f41210cc4177e18e29bac6fede1","src/imp/interrupt/armv4t.rs":"4aafd3341a806b9a72e26c6c1f8a64f0642c39f5aa8fa0913f45955555af4cb7","src/imp/interrupt/armv6m.rs":"21f500ffbfd801b20dfb14e192b995dd26c3031adb5c9d9523b6a62ef235b601","src/imp/interrupt/avr.rs":"19c3264f1be0d92b818c5f9ee0c331c3e67d6c11d4dd688f858bd1da99cc80b2","src/imp/interrupt/mod.rs":"9965cba53776c9364499cc94ce3dbde65283bb96376d99e98aa003c44de59035","src/imp/interrupt/msp430.rs":"18bc58601eb34ca19112b8ac08a239ccf9cdf49a1da24e402bcf554f18804b7e","src/imp/interrupt/riscv.rs":"cd17e5a75407aee29aa250104369eead10167d2d94073430e233f2e6b730bce0","src/imp/interrupt/xtensa.rs":"dcacc9f0014f81de0a3fc8a8af8ce95ccdb888da12793cef534ff5859298ea7f","src/imp/mod.rs":"7ea8bc9713f00dd6461ce7acc8b0ce6d50e2463f2383ee8b3ee1bcfca1a26d9e","src/imp/msp430.rs":"643d5da69adf4bd81f60dd08ee72e41489a9a89161866c56dc2dea26721713a1","src/imp/riscv.rs":"f53e16e35651bbb915277913265288d7e3f590e700c587ec98aec91abb3e46a2","src/imp/x86.rs":"203dc57d04c65f1828158542c6343e5adf22a0afc0f30b1938097d53501a2caf","src/lib.rs":"ebefa8284f884d4ff4da6961984bb07cf5b076dd71a444b602143cb972faa281","src/tests/helper.rs":"2c5cfd4e8666c9b2c8ae3ba4650f4027e1bcd321931f47984d02727963a31df5","src/tests/mod.rs":"ab52e354e4add7dfff086a8ac3b14d138a627d62588c8e63731c235e1084e716","src/utils.rs":"53d359d02b7693d9d48996f99c05beb760906b1be5ff7f75eaa7abfd073a4fdf","version.rs":"ce2cae97a1641e659bb82f11fb3b7356c16f47c392ead0a2b307f059fc3862f8"},"package":"7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"}proc-macro2/0000775000175000017500000000000014661133735013667 5ustar jamespagejamespageproc-macro2/build.rs0000644000175000017500000001733014661133735015336 0ustar jamespagejamespage#![allow(unknown_lints)] #![allow(unexpected_cfgs)] use std::env; use std::ffi::OsString; use std::iter; use std::path::Path; use std::process::{self, Command, Stdio}; use std::str; fn main() { let rustc = rustc_minor_version().unwrap_or(u32::MAX); if rustc >= 80 { println!("cargo:rustc-check-cfg=cfg(fuzzing)"); println!("cargo:rustc-check-cfg=cfg(no_is_available)"); println!("cargo:rustc-check-cfg=cfg(no_literal_byte_character)"); println!("cargo:rustc-check-cfg=cfg(no_literal_c_string)"); println!("cargo:rustc-check-cfg=cfg(no_source_text)"); println!("cargo:rustc-check-cfg=cfg(proc_macro_span)"); println!("cargo:rustc-check-cfg=cfg(procmacro2_backtrace)"); println!("cargo:rustc-check-cfg=cfg(procmacro2_nightly_testing)"); println!("cargo:rustc-check-cfg=cfg(procmacro2_semver_exempt)"); println!("cargo:rustc-check-cfg=cfg(randomize_layout)"); println!("cargo:rustc-check-cfg=cfg(span_locations)"); println!("cargo:rustc-check-cfg=cfg(super_unstable)"); println!("cargo:rustc-check-cfg=cfg(wrap_proc_macro)"); } let docs_rs = env::var_os("DOCS_RS").is_some(); let semver_exempt = cfg!(procmacro2_semver_exempt) || docs_rs; if semver_exempt { // https://github.com/dtolnay/proc-macro2/issues/147 println!("cargo:rustc-cfg=procmacro2_semver_exempt"); } if semver_exempt || cfg!(feature = "span-locations") { // Provide methods Span::start and Span::end which give the line/column // location of a token. This is behind a cfg because tracking location // inside spans is a performance hit. println!("cargo:rustc-cfg=span_locations"); } if rustc < 57 { // Do not use proc_macro::is_available() to detect whether the proc // macro API is available vs needs to be polyfilled. Instead, use the // proc macro API unconditionally and catch the panic that occurs if it // isn't available. println!("cargo:rustc-cfg=no_is_available"); } if rustc < 66 { // Do not call libproc_macro's Span::source_text. Always return None. println!("cargo:rustc-cfg=no_source_text"); } if rustc < 79 { // Do not call Literal::byte_character nor Literal::c_string. They can // be emulated by way of Literal::from_str. println!("cargo:rustc-cfg=no_literal_byte_character"); println!("cargo:rustc-cfg=no_literal_c_string"); } if !cfg!(feature = "proc-macro") { println!("cargo:rerun-if-changed=build.rs"); return; } println!("cargo:rerun-if-changed=build/probe.rs"); let proc_macro_span; let consider_rustc_bootstrap; if compile_probe(false) { // This is a nightly or dev compiler, so it supports unstable features // regardless of RUSTC_BOOTSTRAP. No need to rerun build script if // RUSTC_BOOTSTRAP is changed. proc_macro_span = true; consider_rustc_bootstrap = false; } else if let Some(rustc_bootstrap) = env::var_os("RUSTC_BOOTSTRAP") { if compile_probe(true) { // This is a stable or beta compiler for which the user has set // RUSTC_BOOTSTRAP to turn on unstable features. Rerun build script // if they change it. proc_macro_span = true; consider_rustc_bootstrap = true; } else if rustc_bootstrap == "1" { // This compiler does not support the proc macro Span API in the // form that proc-macro2 expects. No need to pay attention to // RUSTC_BOOTSTRAP. proc_macro_span = false; consider_rustc_bootstrap = false; } else { // This is a stable or beta compiler for which RUSTC_BOOTSTRAP is // set to restrict the use of unstable features by this crate. proc_macro_span = false; consider_rustc_bootstrap = true; } } else { // Without RUSTC_BOOTSTRAP, this compiler does not support the proc // macro Span API in the form that proc-macro2 expects, but try again if // the user turns on unstable features. proc_macro_span = false; consider_rustc_bootstrap = true; } if proc_macro_span || !semver_exempt { // Wrap types from libproc_macro rather than polyfilling the whole API. // Enabled as long as procmacro2_semver_exempt is not set, because we // can't emulate the unstable API without emulating everything else. // Also enabled unconditionally on nightly, in which case the // procmacro2_semver_exempt surface area is implemented by using the // nightly-only proc_macro API. println!("cargo:rustc-cfg=wrap_proc_macro"); } if proc_macro_span { // Enable non-dummy behavior of Span::start and Span::end methods which // requires an unstable compiler feature. Enabled when building with // nightly, unless `-Z allow-feature` in RUSTFLAGS disallows unstable // features. println!("cargo:rustc-cfg=proc_macro_span"); } if semver_exempt && proc_macro_span { // Implement the semver exempt API in terms of the nightly-only // proc_macro API. println!("cargo:rustc-cfg=super_unstable"); } if consider_rustc_bootstrap { println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); } } fn compile_probe(rustc_bootstrap: bool) -> bool { if env::var_os("RUSTC_STAGE").is_some() { // We are running inside rustc bootstrap. This is a highly non-standard // environment with issues such as: // // https://github.com/rust-lang/cargo/issues/11138 // https://github.com/rust-lang/rust/issues/114839 // // Let's just not use nightly features here. return false; } let rustc = cargo_env_var("RUSTC"); let out_dir = cargo_env_var("OUT_DIR"); let probefile = Path::new("build").join("probe.rs"); let rustc_wrapper = env::var_os("RUSTC_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let rustc_workspace_wrapper = env::var_os("RUSTC_WORKSPACE_WRAPPER").filter(|wrapper| !wrapper.is_empty()); let mut rustc = rustc_wrapper .into_iter() .chain(rustc_workspace_wrapper) .chain(iter::once(rustc)); let mut cmd = Command::new(rustc.next().unwrap()); cmd.args(rustc); if !rustc_bootstrap { cmd.env_remove("RUSTC_BOOTSTRAP"); } cmd.stderr(Stdio::null()) .arg("--edition=2021") .arg("--crate-name=proc_macro2") .arg("--crate-type=lib") .arg("--cap-lints=allow") .arg("--emit=dep-info,metadata") .arg("--out-dir") .arg(out_dir) .arg(probefile); if let Some(target) = env::var_os("TARGET") { cmd.arg("--target").arg(target); } // If Cargo wants to set RUSTFLAGS, use that. if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") { if !rustflags.is_empty() { for arg in rustflags.split('\x1f') { cmd.arg(arg); } } } match cmd.status() { Ok(status) => status.success(), Err(_) => false, } } fn rustc_minor_version() -> Option { let rustc = cargo_env_var("RUSTC"); let output = Command::new(rustc).arg("--version").output().ok()?; let version = str::from_utf8(&output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } pieces.next()?.parse().ok() } fn cargo_env_var(key: &str) -> OsString { env::var_os(key).unwrap_or_else(|| { eprintln!( "Environment variable ${} is not set during execution of build script", key, ); process::exit(1); }) } proc-macro2/README.md0000644000175000017500000000743214661133735015152 0ustar jamespagejamespage# proc-macro2 [github](https://github.com/dtolnay/proc-macro2) [crates.io](https://crates.io/crates/proc-macro2) [docs.rs](https://docs.rs/proc-macro2) [build status](https://github.com/dtolnay/proc-macro2/actions?query=branch%3Amaster) A wrapper around the procedural macro API of the compiler's `proc_macro` crate. This library serves two purposes: - **Bring proc-macro-like functionality to other contexts like build.rs and main.rs.** Types from `proc_macro` are entirely specific to procedural macros and cannot ever exist in code outside of a procedural macro. Meanwhile `proc_macro2` types may exist anywhere including non-macro code. By developing foundational libraries like [syn] and [quote] against `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem becomes easily applicable to many other use cases and we avoid reimplementing non-macro equivalents of those libraries. - **Make procedural macros unit testable.** As a consequence of being specific to procedural macros, nothing that uses `proc_macro` can be executed from a unit test. In order for helper libraries or components of a macro to be testable in isolation, they must be implemented using `proc_macro2`. [syn]: https://github.com/dtolnay/syn [quote]: https://github.com/dtolnay/quote ## Usage ```toml [dependencies] proc-macro2 = "1.0" ``` The skeleton of a typical procedural macro typically looks like this: ```rust extern crate proc_macro; #[proc_macro_derive(MyDerive)] pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input = proc_macro2::TokenStream::from(input); let output: proc_macro2::TokenStream = { /* transform input */ }; proc_macro::TokenStream::from(output) } ``` If parsing with [Syn], you'll use [`parse_macro_input!`] instead to propagate parse errors correctly back to the compiler when parsing fails. [`parse_macro_input!`]: https://docs.rs/syn/2.0/syn/macro.parse_macro_input.html ## Unstable features The default feature set of proc-macro2 tracks the most recent stable compiler API. Functionality in `proc_macro` that is not yet stable is not exposed by proc-macro2 by default. To opt into the additional APIs available in the most recent nightly compiler, the `procmacro2_semver_exempt` config flag must be passed to rustc. We will polyfill those nightly-only APIs back to Rust 1.56.0. As these are unstable APIs that track the nightly compiler, minor versions of proc-macro2 may make breaking changes to them at any time. ``` RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build ``` Note that this must not only be done for your crate, but for any crate that depends on your crate. This infectious nature is intentional, as it serves as a reminder that you are outside of the normal semver guarantees. Semver exempt methods are marked as such in the proc-macro2 documentation.
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. proc-macro2/build/0000775000175000017500000000000014661133735014766 5ustar jamespagejamespageproc-macro2/build/probe.rs0000644000175000017500000000122714661133735016443 0ustar jamespagejamespage// This code exercises the surface area that we expect of Span's unstable API. // If the current toolchain is able to compile it, then proc-macro2 is able to // offer these APIs too. #![feature(proc_macro_span)] extern crate proc_macro; use core::ops::{Range, RangeBounds}; use proc_macro::{Literal, Span}; pub fn byte_range(this: &Span) -> Range { this.byte_range() } pub fn join(this: &Span, other: Span) -> Option { this.join(other) } pub fn subspan>(this: &Literal, range: R) -> Option { this.subspan(range) } // Include in sccache cache key. const _: Option<&str> = option_env!("RUSTC_BOOTSTRAP"); proc-macro2/LICENSE-APACHE0000644000175000017500000002277314661133735015624 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS proc-macro2/Cargo.toml0000644000175000017500000000424014661133735015615 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.56" name = "proc-macro2" version = "1.0.86" authors = [ "David Tolnay ", "Alex Crichton ", ] build = "build.rs" autobins = false autoexamples = false autotests = false autobenches = false description = "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case." documentation = "https://docs.rs/proc-macro2" readme = "README.md" keywords = [ "macros", "syn", ] categories = ["development-tools::procedural-macro-helpers"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/proc-macro2" [package.metadata.docs.rs] rustc-args = [ "--cfg", "procmacro2_semver_exempt", ] rustdoc-args = [ "--cfg", "procmacro2_semver_exempt", "--generate-link-to-definition", ] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.playground] features = ["span-locations"] [lib] name = "proc_macro2" path = "src/lib.rs" doc-scrape-examples = false [[test]] name = "comments" path = "tests/comments.rs" [[test]] name = "features" path = "tests/features.rs" [[test]] name = "marker" path = "tests/marker.rs" [[test]] name = "test" path = "tests/test.rs" [[test]] name = "test_fmt" path = "tests/test_fmt.rs" [[test]] name = "test_size" path = "tests/test_size.rs" [dependencies.unicode-ident] version = "1.0" [dev-dependencies.flate2] version = "1.0" [dev-dependencies.quote] version = "1.0" default-features = false [dev-dependencies.rayon] version = "1.0" [dev-dependencies.rustversion] version = "1" [dev-dependencies.tar] version = "0.4" [features] default = ["proc-macro"] nightly = [] proc-macro = [] span-locations = [] proc-macro2/tests/0000775000175000017500000000000014661133735015031 5ustar jamespagejamespageproc-macro2/tests/comments.rs0000644000175000017500000000654114661133735017230 0ustar jamespagejamespage#![allow(clippy::assertions_on_result_states)] use proc_macro2::{Delimiter, Literal, Spacing, TokenStream, TokenTree}; // #[doc = "..."] -> "..." fn lit_of_outer_doc_comment(tokens: &TokenStream) -> Literal { lit_of_doc_comment(tokens, false) } // #![doc = "..."] -> "..." fn lit_of_inner_doc_comment(tokens: &TokenStream) -> Literal { lit_of_doc_comment(tokens, true) } fn lit_of_doc_comment(tokens: &TokenStream, inner: bool) -> Literal { let mut iter = tokens.clone().into_iter(); match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '#'); assert_eq!(punct.spacing(), Spacing::Alone); } _ => panic!("wrong token {:?}", tokens), } if inner { match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '!'); assert_eq!(punct.spacing(), Spacing::Alone); } _ => panic!("wrong token {:?}", tokens), } } iter = match iter.next().unwrap() { TokenTree::Group(group) => { assert_eq!(group.delimiter(), Delimiter::Bracket); assert!(iter.next().is_none(), "unexpected token {:?}", tokens); group.stream().into_iter() } _ => panic!("wrong token {:?}", tokens), }; match iter.next().unwrap() { TokenTree::Ident(ident) => assert_eq!(ident.to_string(), "doc"), _ => panic!("wrong token {:?}", tokens), } match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '='); assert_eq!(punct.spacing(), Spacing::Alone); } _ => panic!("wrong token {:?}", tokens), } match iter.next().unwrap() { TokenTree::Literal(literal) => { assert!(iter.next().is_none(), "unexpected token {:?}", tokens); literal } _ => panic!("wrong token {:?}", tokens), } } #[test] fn closed_immediately() { let stream = "/**/".parse::().unwrap(); let tokens = stream.into_iter().collect::>(); assert!(tokens.is_empty(), "not empty -- {:?}", tokens); } #[test] fn incomplete() { assert!("/*/".parse::().is_err()); } #[test] fn lit() { let stream = "/// doc".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc\""); let stream = "//! doc".parse::().unwrap(); let lit = lit_of_inner_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc\""); let stream = "/** doc */".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc \""); let stream = "/*! doc */".parse::().unwrap(); let lit = lit_of_inner_doc_comment(&stream); assert_eq!(lit.to_string(), "\" doc \""); } #[test] fn carriage_return() { let stream = "///\r\n".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\"\""); let stream = "/**\r\n*/".parse::().unwrap(); let lit = lit_of_outer_doc_comment(&stream); assert_eq!(lit.to_string(), "\"\\r\\n\""); "///\r".parse::().unwrap_err(); "///\r \n".parse::().unwrap_err(); "/**\r \n*/".parse::().unwrap_err(); } proc-macro2/tests/test.rs0000644000175000017500000006424014661133735016362 0ustar jamespagejamespage#![allow( clippy::assertions_on_result_states, clippy::items_after_statements, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::non_ascii_literal, clippy::octal_escapes )] use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::ffi::CStr; use std::iter; use std::str::{self, FromStr}; #[test] fn idents() { assert_eq!( Ident::new("String", Span::call_site()).to_string(), "String" ); assert_eq!(Ident::new("fn", Span::call_site()).to_string(), "fn"); assert_eq!(Ident::new("_", Span::call_site()).to_string(), "_"); } #[test] fn raw_idents() { assert_eq!( Ident::new_raw("String", Span::call_site()).to_string(), "r#String" ); assert_eq!(Ident::new_raw("fn", Span::call_site()).to_string(), "r#fn"); } #[test] #[should_panic(expected = "`r#_` cannot be a raw identifier")] fn ident_raw_underscore() { Ident::new_raw("_", Span::call_site()); } #[test] #[should_panic(expected = "`r#super` cannot be a raw identifier")] fn ident_raw_reserved() { Ident::new_raw("super", Span::call_site()); } #[test] #[should_panic(expected = "Ident is not allowed to be empty; use Option")] fn ident_empty() { Ident::new("", Span::call_site()); } #[test] #[should_panic(expected = "Ident cannot be a number; use Literal instead")] fn ident_number() { Ident::new("255", Span::call_site()); } #[test] #[should_panic(expected = "\"a#\" is not a valid Ident")] fn ident_invalid() { Ident::new("a#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn raw_ident_empty() { Ident::new("r#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn raw_ident_number() { Ident::new("r#255", Span::call_site()); } #[test] #[should_panic(expected = "\"r#a#\" is not a valid Ident")] fn raw_ident_invalid() { Ident::new("r#a#", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn lifetime_empty() { Ident::new("'", Span::call_site()); } #[test] #[should_panic(expected = "not a valid Ident")] fn lifetime_number() { Ident::new("'255", Span::call_site()); } #[test] #[should_panic(expected = r#""'a#" is not a valid Ident"#)] fn lifetime_invalid() { Ident::new("'a#", Span::call_site()); } #[test] fn literal_string() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::string(""), r#" "" "#); assert(Literal::string("aA"), r#" "aA" "#); assert(Literal::string("\t"), r#" "\t" "#); assert(Literal::string("❤"), r#" "❤" "#); assert(Literal::string("'"), r#" "'" "#); assert(Literal::string("\""), r#" "\"" "#); assert(Literal::string("\0"), r#" "\0" "#); assert(Literal::string("\u{1}"), r#" "\u{1}" "#); assert( Literal::string("a\00b\07c\08d\0e\0"), r#" "a\x000b\x007c\08d\0e\0" "#, ); "\"\\\r\n x\"".parse::().unwrap(); "\"\\\r\n \rx\"".parse::().unwrap_err(); } #[test] fn literal_raw_string() { "r\"\r\n\"".parse::().unwrap(); fn raw_string_literal_with_hashes(n: usize) -> String { let mut literal = String::new(); literal.push('r'); literal.extend(iter::repeat('#').take(n)); literal.push('"'); literal.push('"'); literal.extend(iter::repeat('#').take(n)); literal } raw_string_literal_with_hashes(255) .parse::() .unwrap(); // https://github.com/rust-lang/rust/pull/95251 raw_string_literal_with_hashes(256) .parse::() .unwrap_err(); } #[test] fn literal_byte_character() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::byte_character(b'a'), r#" b'a' "#); assert(Literal::byte_character(b'\0'), r#" b'\0' "#); assert(Literal::byte_character(b'\t'), r#" b'\t' "#); assert(Literal::byte_character(b'\n'), r#" b'\n' "#); assert(Literal::byte_character(b'\r'), r#" b'\r' "#); assert(Literal::byte_character(b'\''), r#" b'\'' "#); assert(Literal::byte_character(b'\\'), r#" b'\\' "#); assert(Literal::byte_character(b'\x1f'), r#" b'\x1F' "#); assert(Literal::byte_character(b'"'), r#" b'"' "#); } #[test] fn literal_byte_string() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::byte_string(b""), r#" b"" "#); assert(Literal::byte_string(b"\0"), r#" b"\0" "#); assert(Literal::byte_string(b"\t"), r#" b"\t" "#); assert(Literal::byte_string(b"\n"), r#" b"\n" "#); assert(Literal::byte_string(b"\r"), r#" b"\r" "#); assert(Literal::byte_string(b"\""), r#" b"\"" "#); assert(Literal::byte_string(b"\\"), r#" b"\\" "#); assert(Literal::byte_string(b"\x1f"), r#" b"\x1F" "#); assert(Literal::byte_string(b"'"), r#" b"'" "#); assert( Literal::byte_string(b"a\00b\07c\08d\0e\0"), r#" b"a\x000b\x007c\08d\0e\0" "#, ); "b\"\\\r\n x\"".parse::().unwrap(); "b\"\\\r\n \rx\"".parse::().unwrap_err(); "b\"\\\r\n \u{a0}x\"".parse::().unwrap_err(); "br\"\u{a0}\"".parse::().unwrap_err(); } #[test] fn literal_c_string() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::c_string(<&CStr>::default()), r#" c"" "#); assert( Literal::c_string(CStr::from_bytes_with_nul(b"aA\0").unwrap()), r#" c"aA" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"aA\0").unwrap()), r#" c"aA" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\t\0").unwrap()), r#" c"\t" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\xE2\x9D\xA4\0").unwrap()), r#" c"❤" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"'\0").unwrap()), r#" c"'" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\"\0").unwrap()), r#" c"\"" "#, ); assert( Literal::c_string(CStr::from_bytes_with_nul(b"\x7F\xFF\xFE\xCC\xB3\0").unwrap()), r#" c"\u{7f}\xFF\xFE\u{333}" "#, ); let strings = r###" c"hello\x80我叫\u{1F980}" // from the RFC cr"\" cr##"Hello "world"!"## c"\t\n\r\"\\" "###; let mut tokens = strings.parse::().unwrap().into_iter(); for expected in &[ r#"c"hello\x80我叫\u{1F980}""#, r#"cr"\""#, r###"cr##"Hello "world"!"##"###, r#"c"\t\n\r\"\\""#, ] { match tokens.next().unwrap() { TokenTree::Literal(literal) => { assert_eq!(literal.to_string(), *expected); } unexpected => panic!("unexpected token: {:?}", unexpected), } } if let Some(unexpected) = tokens.next() { panic!("unexpected token: {:?}", unexpected); } for invalid in &[r#"c"\0""#, r#"c"\x00""#, r#"c"\u{0}""#, "c\"\0\""] { if let Ok(unexpected) = invalid.parse::() { panic!("unexpected token: {:?}", unexpected); } } } #[test] fn literal_character() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected.trim()); } assert(Literal::character('a'), r#" 'a' "#); assert(Literal::character('\t'), r#" '\t' "#); assert(Literal::character('❤'), r#" '❤' "#); assert(Literal::character('\''), r#" '\'' "#); assert(Literal::character('"'), r#" '"' "#); assert(Literal::character('\0'), r#" '\0' "#); assert(Literal::character('\u{1}'), r#" '\u{1}' "#); } #[test] fn literal_integer() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected); } assert(Literal::u8_suffixed(10), "10u8"); assert(Literal::u16_suffixed(10), "10u16"); assert(Literal::u32_suffixed(10), "10u32"); assert(Literal::u64_suffixed(10), "10u64"); assert(Literal::u128_suffixed(10), "10u128"); assert(Literal::usize_suffixed(10), "10usize"); assert(Literal::i8_suffixed(10), "10i8"); assert(Literal::i16_suffixed(10), "10i16"); assert(Literal::i32_suffixed(10), "10i32"); assert(Literal::i64_suffixed(10), "10i64"); assert(Literal::i128_suffixed(10), "10i128"); assert(Literal::isize_suffixed(10), "10isize"); assert(Literal::u8_unsuffixed(10), "10"); assert(Literal::u16_unsuffixed(10), "10"); assert(Literal::u32_unsuffixed(10), "10"); assert(Literal::u64_unsuffixed(10), "10"); assert(Literal::u128_unsuffixed(10), "10"); assert(Literal::usize_unsuffixed(10), "10"); assert(Literal::i8_unsuffixed(10), "10"); assert(Literal::i16_unsuffixed(10), "10"); assert(Literal::i32_unsuffixed(10), "10"); assert(Literal::i64_unsuffixed(10), "10"); assert(Literal::i128_unsuffixed(10), "10"); assert(Literal::isize_unsuffixed(10), "10"); assert(Literal::i32_suffixed(-10), "-10i32"); assert(Literal::i32_unsuffixed(-10), "-10"); } #[test] fn literal_float() { #[track_caller] fn assert(literal: Literal, expected: &str) { assert_eq!(literal.to_string(), expected); } assert(Literal::f32_suffixed(10.0), "10f32"); assert(Literal::f32_suffixed(-10.0), "-10f32"); assert(Literal::f64_suffixed(10.0), "10f64"); assert(Literal::f64_suffixed(-10.0), "-10f64"); assert(Literal::f32_unsuffixed(10.0), "10.0"); assert(Literal::f32_unsuffixed(-10.0), "-10.0"); assert(Literal::f64_unsuffixed(10.0), "10.0"); assert(Literal::f64_unsuffixed(-10.0), "-10.0"); assert( Literal::f64_unsuffixed(1e100), "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0", ); } #[test] fn literal_suffix() { fn token_count(p: &str) -> usize { p.parse::().unwrap().into_iter().count() } assert_eq!(token_count("999u256"), 1); assert_eq!(token_count("999r#u256"), 3); assert_eq!(token_count("1."), 1); assert_eq!(token_count("1.f32"), 3); assert_eq!(token_count("1.0_0"), 1); assert_eq!(token_count("1._0"), 3); assert_eq!(token_count("1._m"), 3); assert_eq!(token_count("\"\"s"), 1); assert_eq!(token_count("r\"\"r"), 1); assert_eq!(token_count("r#\"\"#r"), 1); assert_eq!(token_count("b\"\"b"), 1); assert_eq!(token_count("br\"\"br"), 1); assert_eq!(token_count("br#\"\"#br"), 1); assert_eq!(token_count("c\"\"c"), 1); assert_eq!(token_count("cr\"\"cr"), 1); assert_eq!(token_count("cr#\"\"#cr"), 1); assert_eq!(token_count("'c'c"), 1); assert_eq!(token_count("b'b'b"), 1); assert_eq!(token_count("0E"), 1); assert_eq!(token_count("0o0A"), 1); assert_eq!(token_count("0E--0"), 4); assert_eq!(token_count("0.0ECMA"), 1); } #[test] fn literal_iter_negative() { let negative_literal = Literal::i32_suffixed(-3); let tokens = TokenStream::from(TokenTree::Literal(negative_literal)); let mut iter = tokens.into_iter(); match iter.next().unwrap() { TokenTree::Punct(punct) => { assert_eq!(punct.as_char(), '-'); assert_eq!(punct.spacing(), Spacing::Alone); } unexpected => panic!("unexpected token {:?}", unexpected), } match iter.next().unwrap() { TokenTree::Literal(literal) => { assert_eq!(literal.to_string(), "3i32"); } unexpected => panic!("unexpected token {:?}", unexpected), } assert!(iter.next().is_none()); } #[test] fn literal_parse() { assert!("1".parse::().is_ok()); assert!("-1".parse::().is_ok()); assert!("-1u12".parse::().is_ok()); assert!("1.0".parse::().is_ok()); assert!("-1.0".parse::().is_ok()); assert!("-1.0f12".parse::().is_ok()); assert!("'a'".parse::().is_ok()); assert!("\"\n\"".parse::().is_ok()); assert!("0 1".parse::().is_err()); assert!(" 0".parse::().is_err()); assert!("0 ".parse::().is_err()); assert!("/* comment */0".parse::().is_err()); assert!("0/* comment */".parse::().is_err()); assert!("0// comment".parse::().is_err()); assert!("- 1".parse::().is_err()); assert!("- 1.0".parse::().is_err()); assert!("-\"\"".parse::().is_err()); } #[test] fn literal_span() { let positive = "0.1".parse::().unwrap(); let negative = "-0.1".parse::().unwrap(); let subspan = positive.subspan(1..2); #[cfg(not(span_locations))] { let _ = negative; assert!(subspan.is_none()); } #[cfg(span_locations)] { assert_eq!(positive.span().start().column, 0); assert_eq!(positive.span().end().column, 3); assert_eq!(negative.span().start().column, 0); assert_eq!(negative.span().end().column, 4); assert_eq!(subspan.unwrap().source_text().unwrap(), "."); } assert!(positive.subspan(1..4).is_none()); } #[cfg(span_locations)] #[test] fn source_text() { let input = " 𓀕 a z "; let mut tokens = input .parse::() .unwrap() .into_iter(); let first = tokens.next().unwrap(); assert_eq!("𓀕", first.span().source_text().unwrap()); let second = tokens.next().unwrap(); let third = tokens.next().unwrap(); assert_eq!("z", third.span().source_text().unwrap()); assert_eq!("a", second.span().source_text().unwrap()); } #[test] fn roundtrip() { fn roundtrip(p: &str) { println!("parse: {}", p); let s = p.parse::().unwrap().to_string(); println!("first: {}", s); let s2 = s.parse::().unwrap().to_string(); assert_eq!(s, s2); } roundtrip("a"); roundtrip("<<"); roundtrip("<<="); roundtrip( " 1 1.0 1f32 2f64 1usize 4isize 4e10 1_000 1_0i32 8u8 9 0 0xffffffffffffffffffffffffffffffff 1x 1u80 1f320 ", ); roundtrip("'a"); roundtrip("'_"); roundtrip("'static"); roundtrip(r"'\u{10__FFFF}'"); roundtrip("\"\\u{10_F0FF__}foo\\u{1_0_0_0__}\""); } #[test] fn fail() { fn fail(p: &str) { if let Ok(s) = p.parse::() { panic!("should have failed to parse: {}\n{:#?}", p, s); } } fail("' static"); fail("r#1"); fail("r#_"); fail("\"\\u{0000000}\""); // overlong unicode escape (rust allows at most 6 hex digits) fail("\"\\u{999999}\""); // outside of valid range of char fail("\"\\u{_0}\""); // leading underscore fail("\"\\u{}\""); // empty fail("b\"\r\""); // bare carriage return in byte string fail("r\"\r\""); // bare carriage return in raw string fail("\"\\\r \""); // backslash carriage return fail("'aa'aa"); fail("br##\"\"#"); fail("cr##\"\"#"); fail("\"\\\n\u{85}\r\""); } #[cfg(span_locations)] #[test] fn span_test() { check_spans( "\ /// This is a document comment testing 123 { testing 234 }", &[ (1, 0, 1, 30), // # (1, 0, 1, 30), // [ ... ] (1, 0, 1, 30), // doc (1, 0, 1, 30), // = (1, 0, 1, 30), // "This is..." (2, 0, 2, 7), // testing (2, 8, 2, 11), // 123 (3, 0, 5, 1), // { ... } (4, 2, 4, 9), // testing (4, 10, 4, 13), // 234 ], ); } #[cfg(procmacro2_semver_exempt)] #[test] fn default_span() { let start = Span::call_site().start(); assert_eq!(start.line, 1); assert_eq!(start.column, 0); let end = Span::call_site().end(); assert_eq!(end.line, 1); assert_eq!(end.column, 0); let source_file = Span::call_site().source_file(); assert_eq!(source_file.path().to_string_lossy(), ""); assert!(!source_file.is_real()); } #[cfg(procmacro2_semver_exempt)] #[test] fn span_join() { let source1 = "aaa\nbbb" .parse::() .unwrap() .into_iter() .collect::>(); let source2 = "ccc\nddd" .parse::() .unwrap() .into_iter() .collect::>(); assert!(source1[0].span().source_file() != source2[0].span().source_file()); assert_eq!( source1[0].span().source_file(), source1[1].span().source_file() ); let joined1 = source1[0].span().join(source1[1].span()); let joined2 = source1[0].span().join(source2[0].span()); assert!(joined1.is_some()); assert!(joined2.is_none()); let start = joined1.unwrap().start(); let end = joined1.unwrap().end(); assert_eq!(start.line, 1); assert_eq!(start.column, 0); assert_eq!(end.line, 2); assert_eq!(end.column, 3); assert_eq!( joined1.unwrap().source_file(), source1[0].span().source_file() ); } #[test] fn no_panic() { let s = str::from_utf8(b"b\'\xc2\x86 \x00\x00\x00^\"").unwrap(); assert!(s.parse::().is_err()); } #[test] fn punct_before_comment() { let mut tts = TokenStream::from_str("~// comment").unwrap().into_iter(); match tts.next().unwrap() { TokenTree::Punct(tt) => { assert_eq!(tt.as_char(), '~'); assert_eq!(tt.spacing(), Spacing::Alone); } wrong => panic!("wrong token {:?}", wrong), } } #[test] fn joint_last_token() { // This test verifies that we match the behavior of libproc_macro *not* in // the range nightly-2020-09-06 through nightly-2020-09-10, in which this // behavior was temporarily broken. // See https://github.com/rust-lang/rust/issues/76399 let joint_punct = Punct::new(':', Spacing::Joint); let stream = TokenStream::from(TokenTree::Punct(joint_punct)); let punct = match stream.into_iter().next().unwrap() { TokenTree::Punct(punct) => punct, _ => unreachable!(), }; assert_eq!(punct.spacing(), Spacing::Joint); } #[test] fn raw_identifier() { let mut tts = TokenStream::from_str("r#dyn").unwrap().into_iter(); match tts.next().unwrap() { TokenTree::Ident(raw) => assert_eq!("r#dyn", raw.to_string()), wrong => panic!("wrong token {:?}", wrong), } assert!(tts.next().is_none()); } #[test] fn test_debug_ident() { let ident = Ident::new("proc_macro", Span::call_site()); #[cfg(not(span_locations))] let expected = "Ident(proc_macro)"; #[cfg(span_locations)] let expected = "Ident { sym: proc_macro }"; assert_eq!(expected, format!("{:?}", ident)); } #[test] fn test_debug_tokenstream() { let tts = TokenStream::from_str("[a + 1]").unwrap(); #[cfg(not(span_locations))] let expected = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a, }, Punct { char: '+', spacing: Alone, }, Literal { lit: 1, }, ], }, ]\ "; #[cfg(not(span_locations))] let expected_before_trailing_commas = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a }, Punct { char: '+', spacing: Alone }, Literal { lit: 1 } ] } ]\ "; #[cfg(span_locations)] let expected = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a, span: bytes(2..3), }, Punct { char: '+', spacing: Alone, span: bytes(4..5), }, Literal { lit: 1, span: bytes(6..7), }, ], span: bytes(1..8), }, ]\ "; #[cfg(span_locations)] let expected_before_trailing_commas = "\ TokenStream [ Group { delimiter: Bracket, stream: TokenStream [ Ident { sym: a, span: bytes(2..3) }, Punct { char: '+', spacing: Alone, span: bytes(4..5) }, Literal { lit: 1, span: bytes(6..7) } ], span: bytes(1..8) } ]\ "; let actual = format!("{:#?}", tts); if actual.ends_with(",\n]") { assert_eq!(expected, actual); } else { assert_eq!(expected_before_trailing_commas, actual); } } #[test] fn default_tokenstream_is_empty() { let default_token_stream = ::default(); assert!(default_token_stream.is_empty()); } #[test] fn tokenstream_size_hint() { let tokens = "a b (c d) e".parse::().unwrap(); assert_eq!(tokens.into_iter().size_hint(), (4, Some(4))); } #[test] fn tuple_indexing() { // This behavior may change depending on https://github.com/rust-lang/rust/pull/71322 let mut tokens = "tuple.0.0".parse::().unwrap().into_iter(); assert_eq!("tuple", tokens.next().unwrap().to_string()); assert_eq!(".", tokens.next().unwrap().to_string()); assert_eq!("0.0", tokens.next().unwrap().to_string()); assert!(tokens.next().is_none()); } #[cfg(span_locations)] #[test] fn non_ascii_tokens() { check_spans("// abc", &[]); check_spans("// ábc", &[]); check_spans("// abc x", &[]); check_spans("// ábc x", &[]); check_spans("/* abc */ x", &[(1, 10, 1, 11)]); check_spans("/* ábc */ x", &[(1, 10, 1, 11)]); check_spans("/* ab\nc */ x", &[(2, 5, 2, 6)]); check_spans("/* áb\nc */ x", &[(2, 5, 2, 6)]); check_spans("/*** abc */ x", &[(1, 12, 1, 13)]); check_spans("/*** ábc */ x", &[(1, 12, 1, 13)]); check_spans(r#""abc""#, &[(1, 0, 1, 5)]); check_spans(r#""ábc""#, &[(1, 0, 1, 5)]); check_spans(r##"r#"abc"#"##, &[(1, 0, 1, 8)]); check_spans(r##"r#"ábc"#"##, &[(1, 0, 1, 8)]); check_spans("r#\"a\nc\"#", &[(1, 0, 2, 3)]); check_spans("r#\"á\nc\"#", &[(1, 0, 2, 3)]); check_spans("'a'", &[(1, 0, 1, 3)]); check_spans("'á'", &[(1, 0, 1, 3)]); check_spans("//! abc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("//! ábc", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("//! abc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("//! ábc\n", &[(1, 0, 1, 7), (1, 0, 1, 7), (1, 0, 1, 7)]); check_spans("/*! abc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); check_spans("/*! ábc */", &[(1, 0, 1, 10), (1, 0, 1, 10), (1, 0, 1, 10)]); check_spans("/*! a\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); check_spans("/*! á\nc */", &[(1, 0, 2, 4), (1, 0, 2, 4), (1, 0, 2, 4)]); check_spans("abc", &[(1, 0, 1, 3)]); check_spans("ábc", &[(1, 0, 1, 3)]); check_spans("ábć", &[(1, 0, 1, 3)]); check_spans("abc// foo", &[(1, 0, 1, 3)]); check_spans("ábc// foo", &[(1, 0, 1, 3)]); check_spans("ábć// foo", &[(1, 0, 1, 3)]); check_spans("b\"a\\\n c\"", &[(1, 0, 2, 3)]); } #[cfg(span_locations)] fn check_spans(p: &str, mut lines: &[(usize, usize, usize, usize)]) { let ts = p.parse::().unwrap(); check_spans_internal(ts, &mut lines); assert!(lines.is_empty(), "leftover ranges: {:?}", lines); } #[cfg(span_locations)] fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usize)]) { for i in ts { if let Some((&(sline, scol, eline, ecol), rest)) = lines.split_first() { *lines = rest; let start = i.span().start(); assert_eq!(start.line, sline, "sline did not match for {}", i); assert_eq!(start.column, scol, "scol did not match for {}", i); let end = i.span().end(); assert_eq!(end.line, eline, "eline did not match for {}", i); assert_eq!(end.column, ecol, "ecol did not match for {}", i); if let TokenTree::Group(g) = i { check_spans_internal(g.stream().clone(), lines); } } } } #[test] fn whitespace() { // space, horizontal tab, vertical tab, form feed, carriage return, line // feed, non-breaking space, left-to-right mark, right-to-left mark let various_spaces = " \t\u{b}\u{c}\r\n\u{a0}\u{200e}\u{200f}"; let tokens = various_spaces.parse::().unwrap(); assert_eq!(tokens.into_iter().count(), 0); let lone_carriage_returns = " \r \r\r\n "; lone_carriage_returns.parse::().unwrap(); } #[test] fn byte_order_mark() { let string = "\u{feff}foo"; let tokens = string.parse::().unwrap(); match tokens.into_iter().next().unwrap() { TokenTree::Ident(ident) => assert_eq!(ident, "foo"), _ => unreachable!(), } let string = "foo\u{feff}"; string.parse::().unwrap_err(); } #[cfg(span_locations)] fn create_span() -> proc_macro2::Span { let tts: TokenStream = "1".parse().unwrap(); match tts.into_iter().next().unwrap() { TokenTree::Literal(literal) => literal.span(), _ => unreachable!(), } } #[cfg(span_locations)] #[test] fn test_invalidate_current_thread_spans() { let actual = format!("{:#?}", create_span()); assert_eq!(actual, "bytes(1..2)"); let actual = format!("{:#?}", create_span()); assert_eq!(actual, "bytes(3..4)"); proc_macro2::extra::invalidate_current_thread_spans(); let actual = format!("{:#?}", create_span()); // Test that span offsets have been reset after the call // to invalidate_current_thread_spans() assert_eq!(actual, "bytes(1..2)"); } #[cfg(span_locations)] #[test] #[should_panic(expected = "Invalid span with no related FileInfo!")] fn test_use_span_after_invalidation() { let span = create_span(); proc_macro2::extra::invalidate_current_thread_spans(); span.source_text(); } proc-macro2/tests/test_fmt.rs0000644000175000017500000000244014661133735017222 0ustar jamespagejamespage#![allow(clippy::from_iter_instead_of_collect)] use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use std::iter; #[test] fn test_fmt_group() { let ident = Ident::new("x", Span::call_site()); let inner = TokenStream::from_iter(iter::once(TokenTree::Ident(ident))); let parens_empty = Group::new(Delimiter::Parenthesis, TokenStream::new()); let parens_nonempty = Group::new(Delimiter::Parenthesis, inner.clone()); let brackets_empty = Group::new(Delimiter::Bracket, TokenStream::new()); let brackets_nonempty = Group::new(Delimiter::Bracket, inner.clone()); let braces_empty = Group::new(Delimiter::Brace, TokenStream::new()); let braces_nonempty = Group::new(Delimiter::Brace, inner.clone()); let none_empty = Group::new(Delimiter::None, TokenStream::new()); let none_nonempty = Group::new(Delimiter::None, inner); // Matches libproc_macro. assert_eq!("()", parens_empty.to_string()); assert_eq!("(x)", parens_nonempty.to_string()); assert_eq!("[]", brackets_empty.to_string()); assert_eq!("[x]", brackets_nonempty.to_string()); assert_eq!("{ }", braces_empty.to_string()); assert_eq!("{ x }", braces_nonempty.to_string()); assert_eq!("", none_empty.to_string()); assert_eq!("x", none_nonempty.to_string()); } proc-macro2/tests/marker.rs0000644000175000017500000000527114661133735016663 0ustar jamespagejamespage#![allow(clippy::extra_unused_type_parameters)] use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; macro_rules! assert_impl { ($ty:ident is $($marker:ident) and +) => { #[test] #[allow(non_snake_case)] fn $ty() { fn assert_implemented() {} assert_implemented::<$ty>(); } }; ($ty:ident is not $($marker:ident) or +) => { #[test] #[allow(non_snake_case)] fn $ty() { $( { // Implemented for types that implement $marker. #[allow(dead_code)] trait IsNotImplemented { fn assert_not_implemented() {} } impl IsNotImplemented for T {} // Implemented for the type being tested. trait IsImplemented { fn assert_not_implemented() {} } impl IsImplemented for $ty {} // If $ty does not implement $marker, there is no ambiguity // in the following trait method call. <$ty>::assert_not_implemented(); } )+ } }; } assert_impl!(Delimiter is Send and Sync); assert_impl!(Spacing is Send and Sync); assert_impl!(Group is not Send or Sync); assert_impl!(Ident is not Send or Sync); assert_impl!(LexError is not Send or Sync); assert_impl!(Literal is not Send or Sync); assert_impl!(Punct is not Send or Sync); assert_impl!(Span is not Send or Sync); assert_impl!(TokenStream is not Send or Sync); assert_impl!(TokenTree is not Send or Sync); #[cfg(procmacro2_semver_exempt)] mod semver_exempt { use proc_macro2::{LineColumn, SourceFile}; assert_impl!(LineColumn is Send and Sync); assert_impl!(SourceFile is not Send or Sync); } mod unwind_safe { use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; #[cfg(procmacro2_semver_exempt)] use proc_macro2::{LineColumn, SourceFile}; use std::panic::{RefUnwindSafe, UnwindSafe}; macro_rules! assert_unwind_safe { ($($types:ident)*) => { $( assert_impl!($types is UnwindSafe and RefUnwindSafe); )* }; } assert_unwind_safe! { Delimiter Group Ident LexError Literal Punct Spacing Span TokenStream TokenTree } #[cfg(procmacro2_semver_exempt)] assert_unwind_safe! { LineColumn SourceFile } } proc-macro2/tests/test_size.rs0000644000175000017500000000754314661133735017417 0ustar jamespagejamespage#![allow(unused_attributes)] extern crate proc_macro; use std::mem; #[rustversion::attr(before(1.64), ignore = "requires Rust 1.64+")] #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[test] fn test_proc_macro_size() { assert_eq!(mem::size_of::(), 4); assert_eq!(mem::size_of::>(), 4); assert_eq!(mem::size_of::(), 20); assert_eq!(mem::size_of::(), 12); assert_eq!(mem::size_of::(), 8); assert_eq!(mem::size_of::(), 16); assert_eq!(mem::size_of::(), 4); } #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(wrap_proc_macro, ignore = "wrapper mode")] #[cfg_attr(span_locations, ignore = "span locations are on")] #[test] fn test_proc_macro2_fallback_size_without_locations() { assert_eq!(mem::size_of::(), 0); assert_eq!(mem::size_of::>(), 1); assert_eq!(mem::size_of::(), 16); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 8); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 8); } #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(wrap_proc_macro, ignore = "wrapper mode")] #[cfg_attr(not(span_locations), ignore = "span locations are off")] #[test] fn test_proc_macro2_fallback_size_with_locations() { assert_eq!(mem::size_of::(), 8); assert_eq!(mem::size_of::>(), 12); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 16); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 8); } #[rustversion::attr(before(1.71), ignore = "requires Rust 1.71+")] #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(not(wrap_proc_macro), ignore = "fallback mode")] #[cfg_attr(span_locations, ignore = "span locations are on")] #[test] fn test_proc_macro2_wrapper_size_without_locations() { assert_eq!(mem::size_of::(), 4); assert_eq!(mem::size_of::>(), 8); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 12); assert_eq!(mem::size_of::(), 24); assert_eq!(mem::size_of::(), 32); } #[rustversion::attr(before(1.65), ignore = "requires Rust 1.65+")] #[cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit")] #[cfg_attr(randomize_layout, ignore = "disabled due to randomized layout")] #[cfg_attr(not(wrap_proc_macro), ignore = "fallback mode")] #[cfg_attr(not(span_locations), ignore = "span locations are off")] #[test] fn test_proc_macro2_wrapper_size_with_locations() { assert_eq!(mem::size_of::(), 12); assert_eq!(mem::size_of::>(), 12); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 20); assert_eq!(mem::size_of::(), 32); assert_eq!(mem::size_of::(), 32); } proc-macro2/tests/features.rs0000644000175000017500000000023014661133735017206 0ustar jamespagejamespage#[test] #[ignore] fn make_sure_no_proc_macro() { assert!( !cfg!(feature = "proc-macro"), "still compiled with proc_macro?" ); } proc-macro2/LICENSE-MIT0000644000175000017500000000177714661133735015335 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. proc-macro2/src/0000775000175000017500000000000014661133735014456 5ustar jamespagejamespageproc-macro2/src/extra.rs0000644000175000017500000001205414661133735016147 0ustar jamespagejamespage//! Items which do not have a correspondence to any API in the proc_macro crate, //! but are necessary to include in proc-macro2. use crate::fallback; use crate::imp; use crate::marker::{ProcMacroAutoTraits, MARKER}; use crate::Span; use core::fmt::{self, Debug}; /// Invalidate any `proc_macro2::Span` that exist on the current thread. /// /// The implementation of `Span` uses thread-local data structures and this /// function clears them. Calling any method on a `Span` on the current thread /// created prior to the invalidation will return incorrect values or crash. /// /// This function is useful for programs that process more than 232 /// bytes of Rust source code on the same thread. Just like rustc, proc-macro2 /// uses 32-bit source locations, and these wrap around when the total source /// code processed by the same thread exceeds 232 bytes (4 /// gigabytes). After a wraparound, `Span` methods such as `source_text()` can /// return wrong data. /// /// # Example /// /// As of late 2023, there is 200 GB of Rust code published on crates.io. /// Looking at just the newest version of every crate, it is 16 GB of code. So a /// workload that involves parsing it all would overflow a 32-bit source /// location unless spans are being invalidated. /// /// ``` /// use flate2::read::GzDecoder; /// use std::ffi::OsStr; /// use std::io::{BufReader, Read}; /// use std::str::FromStr; /// use tar::Archive; /// /// rayon::scope(|s| { /// for krate in every_version_of_every_crate() { /// s.spawn(move |_| { /// proc_macro2::extra::invalidate_current_thread_spans(); /// /// let reader = BufReader::new(krate); /// let tar = GzDecoder::new(reader); /// let mut archive = Archive::new(tar); /// for entry in archive.entries().unwrap() { /// let mut entry = entry.unwrap(); /// let path = entry.path().unwrap(); /// if path.extension() != Some(OsStr::new("rs")) { /// continue; /// } /// let mut content = String::new(); /// entry.read_to_string(&mut content).unwrap(); /// match proc_macro2::TokenStream::from_str(&content) { /// Ok(tokens) => {/* ... */}, /// Err(_) => continue, /// } /// } /// }); /// } /// }); /// # /// # fn every_version_of_every_crate() -> Vec { /// # Vec::new() /// # } /// ``` /// /// # Panics /// /// This function is not applicable to and will panic if called from a /// procedural macro. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn invalidate_current_thread_spans() { crate::imp::invalidate_current_thread_spans(); } /// An object that holds a [`Group`]'s `span_open()` and `span_close()` together /// in a more compact representation than holding those 2 spans individually. /// /// [`Group`]: crate::Group #[derive(Copy, Clone)] pub struct DelimSpan { inner: DelimSpanEnum, _marker: ProcMacroAutoTraits, } #[derive(Copy, Clone)] enum DelimSpanEnum { #[cfg(wrap_proc_macro)] Compiler { join: proc_macro::Span, open: proc_macro::Span, close: proc_macro::Span, }, Fallback(fallback::Span), } impl DelimSpan { pub(crate) fn new(group: &imp::Group) -> Self { #[cfg(wrap_proc_macro)] let inner = match group { imp::Group::Compiler(group) => DelimSpanEnum::Compiler { join: group.span(), open: group.span_open(), close: group.span_close(), }, imp::Group::Fallback(group) => DelimSpanEnum::Fallback(group.span()), }; #[cfg(not(wrap_proc_macro))] let inner = DelimSpanEnum::Fallback(group.span()); DelimSpan { inner, _marker: MARKER, } } /// Returns a span covering the entire delimited group. pub fn join(&self) -> Span { match &self.inner { #[cfg(wrap_proc_macro)] DelimSpanEnum::Compiler { join, .. } => Span::_new(imp::Span::Compiler(*join)), DelimSpanEnum::Fallback(span) => Span::_new_fallback(*span), } } /// Returns a span for the opening punctuation of the group only. pub fn open(&self) -> Span { match &self.inner { #[cfg(wrap_proc_macro)] DelimSpanEnum::Compiler { open, .. } => Span::_new(imp::Span::Compiler(*open)), DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.first_byte()), } } /// Returns a span for the closing punctuation of the group only. pub fn close(&self) -> Span { match &self.inner { #[cfg(wrap_proc_macro)] DelimSpanEnum::Compiler { close, .. } => Span::_new(imp::Span::Compiler(*close)), DelimSpanEnum::Fallback(span) => Span::_new_fallback(span.last_byte()), } } } impl Debug for DelimSpan { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.join(), f) } } proc-macro2/src/wrapper.rs0000644000175000017500000007325514661133735016516 0ustar jamespagejamespageuse crate::detection::inside_proc_macro; #[cfg(span_locations)] use crate::location::LineColumn; use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; use core::fmt::{self, Debug, Display}; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use core::str::FromStr; use std::ffi::CStr; use std::panic; #[cfg(super_unstable)] use std::path::PathBuf; #[derive(Clone)] pub(crate) enum TokenStream { Compiler(DeferredTokenStream), Fallback(fallback::TokenStream), } // Work around https://github.com/rust-lang/rust/issues/65080. // In `impl Extend for TokenStream` which is used heavily by quote, // we hold on to the appended tokens and do proc_macro::TokenStream::extend as // late as possible to batch together consecutive uses of the Extend impl. #[derive(Clone)] pub(crate) struct DeferredTokenStream { stream: proc_macro::TokenStream, extra: Vec, } pub(crate) enum LexError { Compiler(proc_macro::LexError), Fallback(fallback::LexError), // Rustc was supposed to return a LexError, but it panicked instead. // https://github.com/rust-lang/rust/issues/58736 CompilerPanic, } #[cold] fn mismatch(line: u32) -> ! { #[cfg(procmacro2_backtrace)] { let backtrace = std::backtrace::Backtrace::force_capture(); panic!("compiler/fallback mismatch #{}\n\n{}", line, backtrace) } #[cfg(not(procmacro2_backtrace))] { panic!("compiler/fallback mismatch #{}", line) } } impl DeferredTokenStream { fn new(stream: proc_macro::TokenStream) -> Self { DeferredTokenStream { stream, extra: Vec::new(), } } fn is_empty(&self) -> bool { self.stream.is_empty() && self.extra.is_empty() } fn evaluate_now(&mut self) { // If-check provides a fast short circuit for the common case of `extra` // being empty, which saves a round trip over the proc macro bridge. // Improves macro expansion time in winrt by 6% in debug mode. if !self.extra.is_empty() { self.stream.extend(self.extra.drain(..)); } } fn into_token_stream(mut self) -> proc_macro::TokenStream { self.evaluate_now(); self.stream } } impl TokenStream { pub fn new() -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) } else { TokenStream::Fallback(fallback::TokenStream::new()) } } pub fn is_empty(&self) -> bool { match self { TokenStream::Compiler(tts) => tts.is_empty(), TokenStream::Fallback(tts) => tts.is_empty(), } } fn unwrap_nightly(self) -> proc_macro::TokenStream { match self { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), } } fn unwrap_stable(self) -> fallback::TokenStream { match self { TokenStream::Compiler(_) => mismatch(line!()), TokenStream::Fallback(s) => s, } } } impl FromStr for TokenStream { type Err = LexError; fn from_str(src: &str) -> Result { if inside_proc_macro() { Ok(TokenStream::Compiler(DeferredTokenStream::new( proc_macro_parse(src)?, ))) } else { Ok(TokenStream::Fallback(src.parse()?)) } } } // Work around https://github.com/rust-lang/rust/issues/58736. fn proc_macro_parse(src: &str) -> Result { let result = panic::catch_unwind(|| src.parse().map_err(LexError::Compiler)); result.unwrap_or_else(|_| Err(LexError::CompilerPanic)) } impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Display::fmt(tts, f), } } } impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { TokenStream::Compiler(DeferredTokenStream::new(inner)) } } impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { match inner { TokenStream::Compiler(inner) => inner.into_token_stream(), TokenStream::Fallback(inner) => inner.to_string().parse().unwrap(), } } } impl From for TokenStream { fn from(inner: fallback::TokenStream) -> Self { TokenStream::Fallback(inner) } } // Assumes inside_proc_macro(). fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { match token { TokenTree::Group(tt) => tt.inner.unwrap_nightly().into(), TokenTree::Punct(tt) => { let spacing = match tt.spacing() { Spacing::Joint => proc_macro::Spacing::Joint, Spacing::Alone => proc_macro::Spacing::Alone, }; let mut punct = proc_macro::Punct::new(tt.as_char(), spacing); punct.set_span(tt.span().inner.unwrap_nightly()); punct.into() } TokenTree::Ident(tt) => tt.inner.unwrap_nightly().into(), TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(), } } impl From for TokenStream { fn from(token: TokenTree) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(into_compiler_token(token).into())) } else { TokenStream::Fallback(token.into()) } } } impl FromIterator for TokenStream { fn from_iter>(trees: I) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new( trees.into_iter().map(into_compiler_token).collect(), )) } else { TokenStream::Fallback(trees.into_iter().collect()) } } } impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { let mut streams = streams.into_iter(); match streams.next() { Some(TokenStream::Compiler(mut first)) => { first.evaluate_now(); first.stream.extend(streams.map(|s| match s { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), })); TokenStream::Compiler(first) } Some(TokenStream::Fallback(mut first)) => { first.extend(streams.map(|s| match s { TokenStream::Fallback(s) => s, TokenStream::Compiler(_) => mismatch(line!()), })); TokenStream::Fallback(first) } None => TokenStream::new(), } } } impl Extend for TokenStream { fn extend>(&mut self, stream: I) { match self { TokenStream::Compiler(tts) => { // Here is the reason for DeferredTokenStream. for token in stream { tts.extra.push(into_compiler_token(token)); } } TokenStream::Fallback(tts) => tts.extend(stream), } } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { match self { TokenStream::Compiler(tts) => { tts.evaluate_now(); tts.stream .extend(streams.into_iter().map(TokenStream::unwrap_nightly)); } TokenStream::Fallback(tts) => { tts.extend(streams.into_iter().map(TokenStream::unwrap_stable)); } } } } impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Debug::fmt(tts, f), } } } impl LexError { pub(crate) fn span(&self) -> Span { match self { LexError::Compiler(_) | LexError::CompilerPanic => Span::call_site(), LexError::Fallback(e) => Span::Fallback(e.span()), } } } impl From for LexError { fn from(e: proc_macro::LexError) -> Self { LexError::Compiler(e) } } impl From for LexError { fn from(e: fallback::LexError) -> Self { LexError::Fallback(e) } } impl Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Debug::fmt(e, f), LexError::Fallback(e) => Debug::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Debug::fmt(&fallback, f) } } } } impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Display::fmt(e, f), LexError::Fallback(e) => Display::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Display::fmt(&fallback, f) } } } } #[derive(Clone)] pub(crate) enum TokenTreeIter { Compiler(proc_macro::token_stream::IntoIter), Fallback(fallback::TokenTreeIter), } impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = TokenTreeIter; fn into_iter(self) -> TokenTreeIter { match self { TokenStream::Compiler(tts) => { TokenTreeIter::Compiler(tts.into_token_stream().into_iter()) } TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()), } } } impl Iterator for TokenTreeIter { type Item = TokenTree; fn next(&mut self) -> Option { let token = match self { TokenTreeIter::Compiler(iter) => iter.next()?, TokenTreeIter::Fallback(iter) => return iter.next(), }; Some(match token { proc_macro::TokenTree::Group(tt) => crate::Group::_new(Group::Compiler(tt)).into(), proc_macro::TokenTree::Punct(tt) => { let spacing = match tt.spacing() { proc_macro::Spacing::Joint => Spacing::Joint, proc_macro::Spacing::Alone => Spacing::Alone, }; let mut o = Punct::new(tt.as_char(), spacing); o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); o.into() } proc_macro::TokenTree::Ident(s) => crate::Ident::_new(Ident::Compiler(s)).into(), proc_macro::TokenTree::Literal(l) => crate::Literal::_new(Literal::Compiler(l)).into(), }) } fn size_hint(&self) -> (usize, Option) { match self { TokenTreeIter::Compiler(tts) => tts.size_hint(), TokenTreeIter::Fallback(tts) => tts.size_hint(), } } } #[derive(Clone, PartialEq, Eq)] #[cfg(super_unstable)] pub(crate) enum SourceFile { Compiler(proc_macro::SourceFile), Fallback(fallback::SourceFile), } #[cfg(super_unstable)] impl SourceFile { fn nightly(sf: proc_macro::SourceFile) -> Self { SourceFile::Compiler(sf) } /// Get the path to this source file as a string. pub fn path(&self) -> PathBuf { match self { SourceFile::Compiler(a) => a.path(), SourceFile::Fallback(a) => a.path(), } } pub fn is_real(&self) -> bool { match self { SourceFile::Compiler(a) => a.is_real(), SourceFile::Fallback(a) => a.is_real(), } } } #[cfg(super_unstable)] impl Debug for SourceFile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { SourceFile::Compiler(a) => Debug::fmt(a, f), SourceFile::Fallback(a) => Debug::fmt(a, f), } } } #[derive(Copy, Clone)] pub(crate) enum Span { Compiler(proc_macro::Span), Fallback(fallback::Span), } impl Span { pub fn call_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::call_site()) } else { Span::Fallback(fallback::Span::call_site()) } } pub fn mixed_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::mixed_site()) } else { Span::Fallback(fallback::Span::mixed_site()) } } #[cfg(super_unstable)] pub fn def_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::def_site()) } else { Span::Fallback(fallback::Span::def_site()) } } pub fn resolved_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub fn located_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub fn unwrap(self) -> proc_macro::Span { match self { Span::Compiler(s) => s, Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), } } #[cfg(super_unstable)] pub fn source_file(&self) -> SourceFile { match self { Span::Compiler(s) => SourceFile::nightly(s.source_file()), Span::Fallback(s) => SourceFile::Fallback(s.source_file()), } } #[cfg(span_locations)] pub fn byte_range(&self) -> Range { match self { #[cfg(proc_macro_span)] Span::Compiler(s) => s.byte_range(), #[cfg(not(proc_macro_span))] Span::Compiler(_) => 0..0, Span::Fallback(s) => s.byte_range(), } } #[cfg(span_locations)] pub fn start(&self) -> LineColumn { match self { Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.start(), } } #[cfg(span_locations)] pub fn end(&self) -> LineColumn { match self { Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.end(), } } pub fn join(&self, other: Span) -> Option { let ret = match (self, other) { #[cfg(proc_macro_span)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), _ => return None, }; Some(ret) } #[cfg(super_unstable)] pub fn eq(&self, other: &Span) -> bool { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => a.eq(b), (Span::Fallback(a), Span::Fallback(b)) => a.eq(b), _ => false, } } pub fn source_text(&self) -> Option { match self { #[cfg(not(no_source_text))] Span::Compiler(s) => s.source_text(), #[cfg(no_source_text)] Span::Compiler(_) => None, Span::Fallback(s) => s.source_text(), } } fn unwrap_nightly(self) -> proc_macro::Span { match self { Span::Compiler(s) => s, Span::Fallback(_) => mismatch(line!()), } } } impl From for crate::Span { fn from(proc_span: proc_macro::Span) -> Self { crate::Span::_new(Span::Compiler(proc_span)) } } impl From for Span { fn from(inner: fallback::Span) -> Self { Span::Fallback(inner) } } impl Debug for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Span::Compiler(s) => Debug::fmt(s, f), Span::Fallback(s) => Debug::fmt(s, f), } } } pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { match span { Span::Compiler(s) => { debug.field("span", &s); } Span::Fallback(s) => fallback::debug_span_field_if_nontrivial(debug, s), } } #[derive(Clone)] pub(crate) enum Group { Compiler(proc_macro::Group), Fallback(fallback::Group), } impl Group { pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self { match stream { TokenStream::Compiler(tts) => { let delimiter = match delimiter { Delimiter::Parenthesis => proc_macro::Delimiter::Parenthesis, Delimiter::Bracket => proc_macro::Delimiter::Bracket, Delimiter::Brace => proc_macro::Delimiter::Brace, Delimiter::None => proc_macro::Delimiter::None, }; Group::Compiler(proc_macro::Group::new(delimiter, tts.into_token_stream())) } TokenStream::Fallback(stream) => { Group::Fallback(fallback::Group::new(delimiter, stream)) } } } pub fn delimiter(&self) -> Delimiter { match self { Group::Compiler(g) => match g.delimiter() { proc_macro::Delimiter::Parenthesis => Delimiter::Parenthesis, proc_macro::Delimiter::Bracket => Delimiter::Bracket, proc_macro::Delimiter::Brace => Delimiter::Brace, proc_macro::Delimiter::None => Delimiter::None, }, Group::Fallback(g) => g.delimiter(), } } pub fn stream(&self) -> TokenStream { match self { Group::Compiler(g) => TokenStream::Compiler(DeferredTokenStream::new(g.stream())), Group::Fallback(g) => TokenStream::Fallback(g.stream()), } } pub fn span(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span()), Group::Fallback(g) => Span::Fallback(g.span()), } } pub fn span_open(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span_open()), Group::Fallback(g) => Span::Fallback(g.span_open()), } } pub fn span_close(&self) -> Span { match self { Group::Compiler(g) => Span::Compiler(g.span_close()), Group::Fallback(g) => Span::Fallback(g.span_close()), } } pub fn set_span(&mut self, span: Span) { match (self, span) { (Group::Compiler(g), Span::Compiler(s)) => g.set_span(s), (Group::Fallback(g), Span::Fallback(s)) => g.set_span(s), (Group::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Group::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } fn unwrap_nightly(self) -> proc_macro::Group { match self { Group::Compiler(g) => g, Group::Fallback(_) => mismatch(line!()), } } } impl From for Group { fn from(g: fallback::Group) -> Self { Group::Fallback(g) } } impl Display for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { Group::Compiler(group) => Display::fmt(group, formatter), Group::Fallback(group) => Display::fmt(group, formatter), } } } impl Debug for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self { Group::Compiler(group) => Debug::fmt(group, formatter), Group::Fallback(group) => Debug::fmt(group, formatter), } } } #[derive(Clone)] pub(crate) enum Ident { Compiler(proc_macro::Ident), Fallback(fallback::Ident), } impl Ident { #[track_caller] pub fn new_checked(string: &str, span: Span) -> Self { match span { Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new(string, s)), Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_checked(string, s)), } } pub fn new_unchecked(string: &str, span: fallback::Span) -> Self { Ident::Fallback(fallback::Ident::new_unchecked(string, span)) } #[track_caller] pub fn new_raw_checked(string: &str, span: Span) -> Self { match span { Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)), Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw_checked(string, s)), } } pub fn new_raw_unchecked(string: &str, span: fallback::Span) -> Self { Ident::Fallback(fallback::Ident::new_raw_unchecked(string, span)) } pub fn span(&self) -> Span { match self { Ident::Compiler(t) => Span::Compiler(t.span()), Ident::Fallback(t) => Span::Fallback(t.span()), } } pub fn set_span(&mut self, span: Span) { match (self, span) { (Ident::Compiler(t), Span::Compiler(s)) => t.set_span(s), (Ident::Fallback(t), Span::Fallback(s)) => t.set_span(s), (Ident::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Ident::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } fn unwrap_nightly(self) -> proc_macro::Ident { match self { Ident::Compiler(s) => s, Ident::Fallback(_) => mismatch(line!()), } } } impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { match (self, other) { (Ident::Compiler(t), Ident::Compiler(o)) => t.to_string() == o.to_string(), (Ident::Fallback(t), Ident::Fallback(o)) => t == o, (Ident::Compiler(_), Ident::Fallback(_)) => mismatch(line!()), (Ident::Fallback(_), Ident::Compiler(_)) => mismatch(line!()), } } } impl PartialEq for Ident where T: ?Sized + AsRef, { fn eq(&self, other: &T) -> bool { let other = other.as_ref(); match self { Ident::Compiler(t) => t.to_string() == other, Ident::Fallback(t) => t == other, } } } impl Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Ident::Compiler(t) => Display::fmt(t, f), Ident::Fallback(t) => Display::fmt(t, f), } } } impl Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Ident::Compiler(t) => Debug::fmt(t, f), Ident::Fallback(t) => Debug::fmt(t, f), } } } #[derive(Clone)] pub(crate) enum Literal { Compiler(proc_macro::Literal), Fallback(fallback::Literal), } macro_rules! suffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( pub fn $name(n: $kind) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::$name(n)) } else { Literal::Fallback(fallback::Literal::$name(n)) } } )*) } macro_rules! unsuffixed_integers { ($($name:ident => $kind:ident,)*) => ($( pub fn $name(n: $kind) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::$name(n)) } else { Literal::Fallback(fallback::Literal::$name(n)) } } )*) } impl Literal { pub unsafe fn from_str_unchecked(repr: &str) -> Self { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::from_str(repr).expect("invalid literal")) } else { Literal::Fallback(unsafe { fallback::Literal::from_str_unchecked(repr) }) } } suffixed_numbers! { u8_suffixed => u8, u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, i128_suffixed => i128, isize_suffixed => isize, f32_suffixed => f32, f64_suffixed => f64, } unsuffixed_integers! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, i128_unsuffixed => i128, isize_unsuffixed => isize, } pub fn f32_unsuffixed(f: f32) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::f32_unsuffixed(f)) } else { Literal::Fallback(fallback::Literal::f32_unsuffixed(f)) } } pub fn f64_unsuffixed(f: f64) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::f64_unsuffixed(f)) } else { Literal::Fallback(fallback::Literal::f64_unsuffixed(f)) } } pub fn string(string: &str) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::string(string)) } else { Literal::Fallback(fallback::Literal::string(string)) } } pub fn character(ch: char) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::character(ch)) } else { Literal::Fallback(fallback::Literal::character(ch)) } } pub fn byte_character(byte: u8) -> Literal { if inside_proc_macro() { Literal::Compiler({ #[cfg(not(no_literal_byte_character))] { proc_macro::Literal::byte_character(byte) } #[cfg(no_literal_byte_character)] { let fallback = fallback::Literal::byte_character(byte); fallback.repr.parse::().unwrap() } }) } else { Literal::Fallback(fallback::Literal::byte_character(byte)) } } pub fn byte_string(bytes: &[u8]) -> Literal { if inside_proc_macro() { Literal::Compiler(proc_macro::Literal::byte_string(bytes)) } else { Literal::Fallback(fallback::Literal::byte_string(bytes)) } } pub fn c_string(string: &CStr) -> Literal { if inside_proc_macro() { Literal::Compiler({ #[cfg(not(no_literal_c_string))] { proc_macro::Literal::c_string(string) } #[cfg(no_literal_c_string)] { let fallback = fallback::Literal::c_string(string); fallback.repr.parse::().unwrap() } }) } else { Literal::Fallback(fallback::Literal::c_string(string)) } } pub fn span(&self) -> Span { match self { Literal::Compiler(lit) => Span::Compiler(lit.span()), Literal::Fallback(lit) => Span::Fallback(lit.span()), } } pub fn set_span(&mut self, span: Span) { match (self, span) { (Literal::Compiler(lit), Span::Compiler(s)) => lit.set_span(s), (Literal::Fallback(lit), Span::Fallback(s)) => lit.set_span(s), (Literal::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Literal::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub fn subspan>(&self, range: R) -> Option { match self { #[cfg(proc_macro_span)] Literal::Compiler(lit) => lit.subspan(range).map(Span::Compiler), #[cfg(not(proc_macro_span))] Literal::Compiler(_lit) => None, Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback), } } fn unwrap_nightly(self) -> proc_macro::Literal { match self { Literal::Compiler(s) => s, Literal::Fallback(_) => mismatch(line!()), } } } impl From for Literal { fn from(s: fallback::Literal) -> Self { Literal::Fallback(s) } } impl FromStr for Literal { type Err = LexError; fn from_str(repr: &str) -> Result { if inside_proc_macro() { let literal = proc_macro::Literal::from_str(repr)?; Ok(Literal::Compiler(literal)) } else { let literal = fallback::Literal::from_str(repr)?; Ok(Literal::Fallback(literal)) } } } impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Literal::Compiler(t) => Display::fmt(t, f), Literal::Fallback(t) => Display::fmt(t, f), } } } impl Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Literal::Compiler(t) => Debug::fmt(t, f), Literal::Fallback(t) => Debug::fmt(t, f), } } } #[cfg(span_locations)] pub(crate) fn invalidate_current_thread_spans() { if inside_proc_macro() { panic!( "proc_macro2::extra::invalidate_current_thread_spans is not available in procedural macros" ); } else { crate::fallback::invalidate_current_thread_spans(); } } proc-macro2/src/parse.rs0000644000175000017500000006766514661133735016160 0ustar jamespagejamespageuse crate::fallback::{ self, is_ident_continue, is_ident_start, Group, LexError, Literal, Span, TokenStream, TokenStreamBuilder, }; use crate::{Delimiter, Punct, Spacing, TokenTree}; use core::char; use core::str::{Bytes, CharIndices, Chars}; #[derive(Copy, Clone, Eq, PartialEq)] pub(crate) struct Cursor<'a> { pub rest: &'a str, #[cfg(span_locations)] pub off: u32, } impl<'a> Cursor<'a> { pub fn advance(&self, bytes: usize) -> Cursor<'a> { let (_front, rest) = self.rest.split_at(bytes); Cursor { rest, #[cfg(span_locations)] off: self.off + _front.chars().count() as u32, } } pub fn starts_with(&self, s: &str) -> bool { self.rest.starts_with(s) } pub fn starts_with_char(&self, ch: char) -> bool { self.rest.starts_with(ch) } pub fn starts_with_fn(&self, f: Pattern) -> bool where Pattern: FnMut(char) -> bool, { self.rest.starts_with(f) } pub fn is_empty(&self) -> bool { self.rest.is_empty() } fn len(&self) -> usize { self.rest.len() } fn as_bytes(&self) -> &'a [u8] { self.rest.as_bytes() } fn bytes(&self) -> Bytes<'a> { self.rest.bytes() } fn chars(&self) -> Chars<'a> { self.rest.chars() } fn char_indices(&self) -> CharIndices<'a> { self.rest.char_indices() } fn parse(&self, tag: &str) -> Result, Reject> { if self.starts_with(tag) { Ok(self.advance(tag.len())) } else { Err(Reject) } } } pub(crate) struct Reject; type PResult<'a, O> = Result<(Cursor<'a>, O), Reject>; fn skip_whitespace(input: Cursor) -> Cursor { let mut s = input; while !s.is_empty() { let byte = s.as_bytes()[0]; if byte == b'/' { if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) && !s.starts_with("//!") { let (cursor, _) = take_until_newline_or_eof(s); s = cursor; continue; } else if s.starts_with("/**/") { s = s.advance(4); continue; } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) && !s.starts_with("/*!") { match block_comment(s) { Ok((rest, _)) => { s = rest; continue; } Err(Reject) => return s, } } } match byte { b' ' | 0x09..=0x0d => { s = s.advance(1); continue; } b if b.is_ascii() => {} _ => { let ch = s.chars().next().unwrap(); if is_whitespace(ch) { s = s.advance(ch.len_utf8()); continue; } } } return s; } s } fn block_comment(input: Cursor) -> PResult<&str> { if !input.starts_with("/*") { return Err(Reject); } let mut depth = 0usize; let bytes = input.as_bytes(); let mut i = 0usize; let upper = bytes.len() - 1; while i < upper { if bytes[i] == b'/' && bytes[i + 1] == b'*' { depth += 1; i += 1; // eat '*' } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { depth -= 1; if depth == 0 { return Ok((input.advance(i + 2), &input.rest[..i + 2])); } i += 1; // eat '/' } i += 1; } Err(Reject) } fn is_whitespace(ch: char) -> bool { // Rust treats left-to-right mark and right-to-left mark as whitespace ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' } fn word_break(input: Cursor) -> Result { match input.chars().next() { Some(ch) if is_ident_continue(ch) => Err(Reject), Some(_) | None => Ok(input), } } // Rustc's representation of a macro expansion error in expression position or // type position. const ERROR: &str = "(/*ERROR*/)"; pub(crate) fn token_stream(mut input: Cursor) -> Result { let mut trees = TokenStreamBuilder::new(); let mut stack = Vec::new(); loop { input = skip_whitespace(input); if let Ok((rest, ())) = doc_comment(input, &mut trees) { input = rest; continue; } #[cfg(span_locations)] let lo = input.off; let first = match input.bytes().next() { Some(first) => first, None => match stack.last() { None => return Ok(trees.build()), #[cfg(span_locations)] Some((lo, _frame)) => { return Err(LexError { span: Span { lo: *lo, hi: *lo }, }) } #[cfg(not(span_locations))] Some(_frame) => return Err(LexError { span: Span {} }), }, }; if let Some(open_delimiter) = match first { b'(' if !input.starts_with(ERROR) => Some(Delimiter::Parenthesis), b'[' => Some(Delimiter::Bracket), b'{' => Some(Delimiter::Brace), _ => None, } { input = input.advance(1); let frame = (open_delimiter, trees); #[cfg(span_locations)] let frame = (lo, frame); stack.push(frame); trees = TokenStreamBuilder::new(); } else if let Some(close_delimiter) = match first { b')' => Some(Delimiter::Parenthesis), b']' => Some(Delimiter::Bracket), b'}' => Some(Delimiter::Brace), _ => None, } { let frame = match stack.pop() { Some(frame) => frame, None => return Err(lex_error(input)), }; #[cfg(span_locations)] let (lo, frame) = frame; let (open_delimiter, outer) = frame; if open_delimiter != close_delimiter { return Err(lex_error(input)); } input = input.advance(1); let mut g = Group::new(open_delimiter, trees.build()); g.set_span(Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: input.off, }); trees = outer; trees.push_token_from_parser(TokenTree::Group(crate::Group::_new_fallback(g))); } else { let (rest, mut tt) = match leaf_token(input) { Ok((rest, tt)) => (rest, tt), Err(Reject) => return Err(lex_error(input)), }; tt.set_span(crate::Span::_new_fallback(Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: rest.off, })); trees.push_token_from_parser(tt); input = rest; } } } fn lex_error(cursor: Cursor) -> LexError { #[cfg(not(span_locations))] let _ = cursor; LexError { span: Span { #[cfg(span_locations)] lo: cursor.off, #[cfg(span_locations)] hi: cursor.off, }, } } fn leaf_token(input: Cursor) -> PResult { if let Ok((input, l)) = literal(input) { // must be parsed before ident Ok((input, TokenTree::Literal(crate::Literal::_new_fallback(l)))) } else if let Ok((input, p)) = punct(input) { Ok((input, TokenTree::Punct(p))) } else if let Ok((input, i)) = ident(input) { Ok((input, TokenTree::Ident(i))) } else if input.starts_with(ERROR) { let rest = input.advance(ERROR.len()); let repr = crate::Literal::_new_fallback(Literal::_new(ERROR.to_owned())); Ok((rest, TokenTree::Literal(repr))) } else { Err(Reject) } } fn ident(input: Cursor) -> PResult { if [ "r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#", "c\"", "cr\"", "cr#", ] .iter() .any(|prefix| input.starts_with(prefix)) { Err(Reject) } else { ident_any(input) } } fn ident_any(input: Cursor) -> PResult { let raw = input.starts_with("r#"); let rest = input.advance((raw as usize) << 1); let (rest, sym) = ident_not_raw(rest)?; if !raw { let ident = crate::Ident::_new(crate::imp::Ident::new_unchecked( sym, fallback::Span::call_site(), )); return Ok((rest, ident)); } match sym { "_" | "super" | "self" | "Self" | "crate" => return Err(Reject), _ => {} } let ident = crate::Ident::_new(crate::imp::Ident::new_raw_unchecked( sym, fallback::Span::call_site(), )); Ok((rest, ident)) } fn ident_not_raw(input: Cursor) -> PResult<&str> { let mut chars = input.char_indices(); match chars.next() { Some((_, ch)) if is_ident_start(ch) => {} _ => return Err(Reject), } let mut end = input.len(); for (i, ch) in chars { if !is_ident_continue(ch) { end = i; break; } } Ok((input.advance(end), &input.rest[..end])) } pub(crate) fn literal(input: Cursor) -> PResult { let rest = literal_nocapture(input)?; let end = input.len() - rest.len(); Ok((rest, Literal::_new(input.rest[..end].to_string()))) } fn literal_nocapture(input: Cursor) -> Result { if let Ok(ok) = string(input) { Ok(ok) } else if let Ok(ok) = byte_string(input) { Ok(ok) } else if let Ok(ok) = c_string(input) { Ok(ok) } else if let Ok(ok) = byte(input) { Ok(ok) } else if let Ok(ok) = character(input) { Ok(ok) } else if let Ok(ok) = float(input) { Ok(ok) } else if let Ok(ok) = int(input) { Ok(ok) } else { Err(Reject) } } fn literal_suffix(input: Cursor) -> Cursor { match ident_not_raw(input) { Ok((input, _)) => input, Err(Reject) => input, } } fn string(input: Cursor) -> Result { if let Ok(input) = input.parse("\"") { cooked_string(input) } else if let Ok(input) = input.parse("r") { raw_string(input) } else { Err(Reject) } } fn cooked_string(mut input: Cursor) -> Result { let mut chars = input.char_indices(); while let Some((i, ch)) = chars.next() { match ch { '"' => { let input = input.advance(i + 1); return Ok(literal_suffix(input)); } '\r' => match chars.next() { Some((_, '\n')) => {} _ => break, }, '\\' => match chars.next() { Some((_, 'x')) => { backslash_x_char(&mut chars)?; } Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0')) => {} Some((_, 'u')) => { backslash_u(&mut chars)?; } Some((newline, ch @ ('\n' | '\r'))) => { input = input.advance(newline + 1); trailing_backslash(&mut input, ch as u8)?; chars = input.char_indices(); } _ => break, }, _ch => {} } } Err(Reject) } fn raw_string(input: Cursor) -> Result { let (input, delimiter) = delimiter_of_raw_string(input)?; let mut bytes = input.bytes().enumerate(); while let Some((i, byte)) = bytes.next() { match byte { b'"' if input.rest[i + 1..].starts_with(delimiter) => { let rest = input.advance(i + 1 + delimiter.len()); return Ok(literal_suffix(rest)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, _ => {} } } Err(Reject) } fn byte_string(input: Cursor) -> Result { if let Ok(input) = input.parse("b\"") { cooked_byte_string(input) } else if let Ok(input) = input.parse("br") { raw_byte_string(input) } else { Err(Reject) } } fn cooked_byte_string(mut input: Cursor) -> Result { let mut bytes = input.bytes().enumerate(); while let Some((offset, b)) = bytes.next() { match b { b'"' => { let input = input.advance(offset + 1); return Ok(literal_suffix(input)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, b'\\' => match bytes.next() { Some((_, b'x')) => { backslash_x_byte(&mut bytes)?; } Some((_, b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"')) => {} Some((newline, b @ (b'\n' | b'\r'))) => { input = input.advance(newline + 1); trailing_backslash(&mut input, b)?; bytes = input.bytes().enumerate(); } _ => break, }, b if b.is_ascii() => {} _ => break, } } Err(Reject) } fn delimiter_of_raw_string(input: Cursor) -> PResult<&str> { for (i, byte) in input.bytes().enumerate() { match byte { b'"' => { if i > 255 { // https://github.com/rust-lang/rust/pull/95251 return Err(Reject); } return Ok((input.advance(i + 1), &input.rest[..i])); } b'#' => {} _ => break, } } Err(Reject) } fn raw_byte_string(input: Cursor) -> Result { let (input, delimiter) = delimiter_of_raw_string(input)?; let mut bytes = input.bytes().enumerate(); while let Some((i, byte)) = bytes.next() { match byte { b'"' if input.rest[i + 1..].starts_with(delimiter) => { let rest = input.advance(i + 1 + delimiter.len()); return Ok(literal_suffix(rest)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, other => { if !other.is_ascii() { break; } } } } Err(Reject) } fn c_string(input: Cursor) -> Result { if let Ok(input) = input.parse("c\"") { cooked_c_string(input) } else if let Ok(input) = input.parse("cr") { raw_c_string(input) } else { Err(Reject) } } fn raw_c_string(input: Cursor) -> Result { let (input, delimiter) = delimiter_of_raw_string(input)?; let mut bytes = input.bytes().enumerate(); while let Some((i, byte)) = bytes.next() { match byte { b'"' if input.rest[i + 1..].starts_with(delimiter) => { let rest = input.advance(i + 1 + delimiter.len()); return Ok(literal_suffix(rest)); } b'\r' => match bytes.next() { Some((_, b'\n')) => {} _ => break, }, b'\0' => break, _ => {} } } Err(Reject) } fn cooked_c_string(mut input: Cursor) -> Result { let mut chars = input.char_indices(); while let Some((i, ch)) = chars.next() { match ch { '"' => { let input = input.advance(i + 1); return Ok(literal_suffix(input)); } '\r' => match chars.next() { Some((_, '\n')) => {} _ => break, }, '\\' => match chars.next() { Some((_, 'x')) => { backslash_x_nonzero(&mut chars)?; } Some((_, 'n' | 'r' | 't' | '\\' | '\'' | '"')) => {} Some((_, 'u')) => { if backslash_u(&mut chars)? == '\0' { break; } } Some((newline, ch @ ('\n' | '\r'))) => { input = input.advance(newline + 1); trailing_backslash(&mut input, ch as u8)?; chars = input.char_indices(); } _ => break, }, '\0' => break, _ch => {} } } Err(Reject) } fn byte(input: Cursor) -> Result { let input = input.parse("b'")?; let mut bytes = input.bytes().enumerate(); let ok = match bytes.next().map(|(_, b)| b) { Some(b'\\') => match bytes.next().map(|(_, b)| b) { Some(b'x') => backslash_x_byte(&mut bytes).is_ok(), Some(b'n' | b'r' | b't' | b'\\' | b'0' | b'\'' | b'"') => true, _ => false, }, b => b.is_some(), }; if !ok { return Err(Reject); } let (offset, _) = bytes.next().ok_or(Reject)?; if !input.chars().as_str().is_char_boundary(offset) { return Err(Reject); } let input = input.advance(offset).parse("'")?; Ok(literal_suffix(input)) } fn character(input: Cursor) -> Result { let input = input.parse("'")?; let mut chars = input.char_indices(); let ok = match chars.next().map(|(_, ch)| ch) { Some('\\') => match chars.next().map(|(_, ch)| ch) { Some('x') => backslash_x_char(&mut chars).is_ok(), Some('u') => backslash_u(&mut chars).is_ok(), Some('n' | 'r' | 't' | '\\' | '0' | '\'' | '"') => true, _ => false, }, ch => ch.is_some(), }; if !ok { return Err(Reject); } let (idx, _) = chars.next().ok_or(Reject)?; let input = input.advance(idx).parse("'")?; Ok(literal_suffix(input)) } macro_rules! next_ch { ($chars:ident @ $pat:pat) => { match $chars.next() { Some((_, ch)) => match ch { $pat => ch, _ => return Err(Reject), }, None => return Err(Reject), } }; } fn backslash_x_char(chars: &mut I) -> Result<(), Reject> where I: Iterator, { next_ch!(chars @ '0'..='7'); next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); Ok(()) } fn backslash_x_byte(chars: &mut I) -> Result<(), Reject> where I: Iterator, { next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'); Ok(()) } fn backslash_x_nonzero(chars: &mut I) -> Result<(), Reject> where I: Iterator, { let first = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); let second = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); if first == '0' && second == '0' { Err(Reject) } else { Ok(()) } } fn backslash_u(chars: &mut I) -> Result where I: Iterator, { next_ch!(chars @ '{'); let mut value = 0; let mut len = 0; for (_, ch) in chars { let digit = match ch { '0'..='9' => ch as u8 - b'0', 'a'..='f' => 10 + ch as u8 - b'a', 'A'..='F' => 10 + ch as u8 - b'A', '_' if len > 0 => continue, '}' if len > 0 => return char::from_u32(value).ok_or(Reject), _ => break, }; if len == 6 { break; } value *= 0x10; value += u32::from(digit); len += 1; } Err(Reject) } fn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> { let mut whitespace = input.bytes().enumerate(); loop { if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') { return Err(Reject); } match whitespace.next() { Some((_, b @ (b' ' | b'\t' | b'\n' | b'\r'))) => { last = b; } Some((offset, _)) => { *input = input.advance(offset); return Ok(()); } None => return Err(Reject), } } } fn float(input: Cursor) -> Result { let mut rest = float_digits(input)?; if let Some(ch) = rest.chars().next() { if is_ident_start(ch) { rest = ident_not_raw(rest)?.0; } } word_break(rest) } fn float_digits(input: Cursor) -> Result { let mut chars = input.chars().peekable(); match chars.next() { Some(ch) if '0' <= ch && ch <= '9' => {} _ => return Err(Reject), } let mut len = 1; let mut has_dot = false; let mut has_exp = false; while let Some(&ch) = chars.peek() { match ch { '0'..='9' | '_' => { chars.next(); len += 1; } '.' => { if has_dot { break; } chars.next(); if chars .peek() .map_or(false, |&ch| ch == '.' || is_ident_start(ch)) { return Err(Reject); } len += 1; has_dot = true; } 'e' | 'E' => { chars.next(); len += 1; has_exp = true; break; } _ => break, } } if !(has_dot || has_exp) { return Err(Reject); } if has_exp { let token_before_exp = if has_dot { Ok(input.advance(len - 1)) } else { Err(Reject) }; let mut has_sign = false; let mut has_exp_value = false; while let Some(&ch) = chars.peek() { match ch { '+' | '-' => { if has_exp_value { break; } if has_sign { return token_before_exp; } chars.next(); len += 1; has_sign = true; } '0'..='9' => { chars.next(); len += 1; has_exp_value = true; } '_' => { chars.next(); len += 1; } _ => break, } } if !has_exp_value { return token_before_exp; } } Ok(input.advance(len)) } fn int(input: Cursor) -> Result { let mut rest = digits(input)?; if let Some(ch) = rest.chars().next() { if is_ident_start(ch) { rest = ident_not_raw(rest)?.0; } } word_break(rest) } fn digits(mut input: Cursor) -> Result { let base = if input.starts_with("0x") { input = input.advance(2); 16 } else if input.starts_with("0o") { input = input.advance(2); 8 } else if input.starts_with("0b") { input = input.advance(2); 2 } else { 10 }; let mut len = 0; let mut empty = true; for b in input.bytes() { match b { b'0'..=b'9' => { let digit = (b - b'0') as u64; if digit >= base { return Err(Reject); } } b'a'..=b'f' => { let digit = 10 + (b - b'a') as u64; if digit >= base { break; } } b'A'..=b'F' => { let digit = 10 + (b - b'A') as u64; if digit >= base { break; } } b'_' => { if empty && base == 10 { return Err(Reject); } len += 1; continue; } _ => break, }; len += 1; empty = false; } if empty { Err(Reject) } else { Ok(input.advance(len)) } } fn punct(input: Cursor) -> PResult { let (rest, ch) = punct_char(input)?; if ch == '\'' { if ident_any(rest)?.0.starts_with_char('\'') { Err(Reject) } else { Ok((rest, Punct::new('\'', Spacing::Joint))) } } else { let kind = match punct_char(rest) { Ok(_) => Spacing::Joint, Err(Reject) => Spacing::Alone, }; Ok((rest, Punct::new(ch, kind))) } } fn punct_char(input: Cursor) -> PResult { if input.starts_with("//") || input.starts_with("/*") { // Do not accept `/` of a comment as a punct. return Err(Reject); } let mut chars = input.chars(); let first = match chars.next() { Some(ch) => ch, None => { return Err(Reject); } }; let recognized = "~!@#$%^&*-=+|;:,<.>/?'"; if recognized.contains(first) { Ok((input.advance(first.len_utf8()), first)) } else { Err(Reject) } } fn doc_comment<'a>(input: Cursor<'a>, trees: &mut TokenStreamBuilder) -> PResult<'a, ()> { #[cfg(span_locations)] let lo = input.off; let (rest, (comment, inner)) = doc_comment_contents(input)?; let fallback_span = Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: rest.off, }; let span = crate::Span::_new_fallback(fallback_span); let mut scan_for_bare_cr = comment; while let Some(cr) = scan_for_bare_cr.find('\r') { let rest = &scan_for_bare_cr[cr + 1..]; if !rest.starts_with('\n') { return Err(Reject); } scan_for_bare_cr = rest; } let mut pound = Punct::new('#', Spacing::Alone); pound.set_span(span); trees.push_token_from_parser(TokenTree::Punct(pound)); if inner { let mut bang = Punct::new('!', Spacing::Alone); bang.set_span(span); trees.push_token_from_parser(TokenTree::Punct(bang)); } let doc_ident = crate::Ident::_new(crate::imp::Ident::new_unchecked("doc", fallback_span)); let mut equal = Punct::new('=', Spacing::Alone); equal.set_span(span); let mut literal = crate::Literal::string(comment); literal.set_span(span); let mut bracketed = TokenStreamBuilder::with_capacity(3); bracketed.push_token_from_parser(TokenTree::Ident(doc_ident)); bracketed.push_token_from_parser(TokenTree::Punct(equal)); bracketed.push_token_from_parser(TokenTree::Literal(literal)); let group = Group::new(Delimiter::Bracket, bracketed.build()); let mut group = crate::Group::_new_fallback(group); group.set_span(span); trees.push_token_from_parser(TokenTree::Group(group)); Ok((rest, ())) } fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> { if input.starts_with("//!") { let input = input.advance(3); let (input, s) = take_until_newline_or_eof(input); Ok((input, (s, true))) } else if input.starts_with("/*!") { let (input, s) = block_comment(input)?; Ok((input, (&s[3..s.len() - 2], true))) } else if input.starts_with("///") { let input = input.advance(3); if input.starts_with_char('/') { return Err(Reject); } let (input, s) = take_until_newline_or_eof(input); Ok((input, (s, false))) } else if input.starts_with("/**") && !input.rest[3..].starts_with('*') { let (input, s) = block_comment(input)?; Ok((input, (&s[3..s.len() - 2], false))) } else { Err(Reject) } } fn take_until_newline_or_eof(input: Cursor) -> (Cursor, &str) { let chars = input.char_indices(); for (i, ch) in chars { if ch == '\n' { return (input.advance(i), &input.rest[..i]); } else if ch == '\r' && input.rest[i + 1..].starts_with('\n') { return (input.advance(i + 1), &input.rest[..i]); } } (input.advance(input.len()), input.rest) } proc-macro2/src/detection.rs0000644000175000017500000000521714661133735017005 0ustar jamespagejamespageuse core::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Once; static WORKS: AtomicUsize = AtomicUsize::new(0); static INIT: Once = Once::new(); pub(crate) fn inside_proc_macro() -> bool { match WORKS.load(Ordering::Relaxed) { 1 => return false, 2 => return true, _ => {} } INIT.call_once(initialize); inside_proc_macro() } pub(crate) fn force_fallback() { WORKS.store(1, Ordering::Relaxed); } pub(crate) fn unforce_fallback() { initialize(); } #[cfg(not(no_is_available))] fn initialize() { let available = proc_macro::is_available(); WORKS.store(available as usize + 1, Ordering::Relaxed); } // Swap in a null panic hook to avoid printing "thread panicked" to stderr, // then use catch_unwind to determine whether the compiler's proc_macro is // working. When proc-macro2 is used from outside of a procedural macro all // of the proc_macro crate's APIs currently panic. // // The Once is to prevent the possibility of this ordering: // // thread 1 calls take_hook, gets the user's original hook // thread 1 calls set_hook with the null hook // thread 2 calls take_hook, thinks null hook is the original hook // thread 2 calls set_hook with the null hook // thread 1 calls set_hook with the actual original hook // thread 2 calls set_hook with what it thinks is the original hook // // in which the user's hook has been lost. // // There is still a race condition where a panic in a different thread can // happen during the interval that the user's original panic hook is // unregistered such that their hook is incorrectly not called. This is // sufficiently unlikely and less bad than printing panic messages to stderr // on correct use of this crate. Maybe there is a libstd feature request // here. For now, if a user needs to guarantee that this failure mode does // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from // the main thread before launching any other threads. #[cfg(no_is_available)] fn initialize() { use std::panic::{self, PanicInfo}; type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; let null_hook: Box = Box::new(|_panic_info| { /* ignore */ }); let sanity_check = &*null_hook as *const PanicHook; let original_hook = panic::take_hook(); panic::set_hook(null_hook); let works = panic::catch_unwind(proc_macro::Span::call_site).is_ok(); WORKS.store(works as usize + 1, Ordering::Relaxed); let hopefully_null_hook = panic::take_hook(); panic::set_hook(original_hook); if sanity_check != &*hopefully_null_hook { panic!("observed race condition in proc_macro2::inside_proc_macro"); } } proc-macro2/src/lib.rs0000644000175000017500000013107714661133735015601 0ustar jamespagejamespage//! [![github]](https://github.com/dtolnay/proc-macro2) [![crates-io]](https://crates.io/crates/proc-macro2) [![docs-rs]](crate) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! A wrapper around the procedural macro API of the compiler's [`proc_macro`] //! crate. This library serves two purposes: //! //! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/ //! //! - **Bring proc-macro-like functionality to other contexts like build.rs and //! main.rs.** Types from `proc_macro` are entirely specific to procedural //! macros and cannot ever exist in code outside of a procedural macro. //! Meanwhile `proc_macro2` types may exist anywhere including non-macro code. //! By developing foundational libraries like [syn] and [quote] against //! `proc_macro2` rather than `proc_macro`, the procedural macro ecosystem //! becomes easily applicable to many other use cases and we avoid //! reimplementing non-macro equivalents of those libraries. //! //! - **Make procedural macros unit testable.** As a consequence of being //! specific to procedural macros, nothing that uses `proc_macro` can be //! executed from a unit test. In order for helper libraries or components of //! a macro to be testable in isolation, they must be implemented using //! `proc_macro2`. //! //! [syn]: https://github.com/dtolnay/syn //! [quote]: https://github.com/dtolnay/quote //! //! # Usage //! //! The skeleton of a typical procedural macro typically looks like this: //! //! ``` //! extern crate proc_macro; //! //! # const IGNORE: &str = stringify! { //! #[proc_macro_derive(MyDerive)] //! # }; //! # #[cfg(wrap_proc_macro)] //! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { //! let input = proc_macro2::TokenStream::from(input); //! //! let output: proc_macro2::TokenStream = { //! /* transform input */ //! # input //! }; //! //! proc_macro::TokenStream::from(output) //! } //! ``` //! //! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to //! propagate parse errors correctly back to the compiler when parsing fails. //! //! [`parse_macro_input!`]: https://docs.rs/syn/2.0/syn/macro.parse_macro_input.html //! //! # Unstable features //! //! The default feature set of proc-macro2 tracks the most recent stable //! compiler API. Functionality in `proc_macro` that is not yet stable is not //! exposed by proc-macro2 by default. //! //! To opt into the additional APIs available in the most recent nightly //! compiler, the `procmacro2_semver_exempt` config flag must be passed to //! rustc. We will polyfill those nightly-only APIs back to Rust 1.56.0. As //! these are unstable APIs that track the nightly compiler, minor versions of //! proc-macro2 may make breaking changes to them at any time. //! //! ```sh //! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build //! ``` //! //! Note that this must not only be done for your crate, but for any crate that //! depends on your crate. This infectious nature is intentional, as it serves //! as a reminder that you are outside of the normal semver guarantees. //! //! Semver exempt methods are marked as such in the proc-macro2 documentation. //! //! # Thread-Safety //! //! Most types in this crate are `!Sync` because the underlying compiler //! types make use of thread-local memory, meaning they cannot be accessed from //! a different thread. // Proc-macro2 types in rustdoc of other crates get linked to here. #![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.86")] #![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))] #![cfg_attr(super_unstable, feature(proc_macro_def_site))] #![cfg_attr(docsrs, feature(doc_cfg))] #![deny(unsafe_op_in_unsafe_fn)] #![allow( clippy::cast_lossless, clippy::cast_possible_truncation, clippy::checked_conversions, clippy::doc_markdown, clippy::incompatible_msrv, clippy::items_after_statements, clippy::iter_without_into_iter, clippy::let_underscore_untyped, clippy::manual_assert, clippy::manual_range_contains, clippy::missing_safety_doc, clippy::must_use_candidate, clippy::needless_doctest_main, clippy::new_without_default, clippy::return_self_not_must_use, clippy::shadow_unrelated, clippy::trivially_copy_pass_by_ref, clippy::unnecessary_wraps, clippy::unused_self, clippy::used_underscore_binding, clippy::vec_init_then_push )] #[cfg(all(procmacro2_semver_exempt, wrap_proc_macro, not(super_unstable)))] compile_error! {"\ Something is not right. If you've tried to turn on \ procmacro2_semver_exempt, you need to ensure that it \ is turned on for the compilation of the proc-macro2 \ build script as well. "} #[cfg(all( procmacro2_nightly_testing, feature = "proc-macro", not(proc_macro_span) ))] compile_error! {"\ Build script probe failed to compile. "} extern crate alloc; #[cfg(feature = "proc-macro")] extern crate proc_macro; mod marker; mod parse; mod rcvec; #[cfg(wrap_proc_macro)] mod detection; // Public for proc_macro2::fallback::force() and unforce(), but those are quite // a niche use case so we omit it from rustdoc. #[doc(hidden)] pub mod fallback; pub mod extra; #[cfg(not(wrap_proc_macro))] use crate::fallback as imp; #[path = "wrapper.rs"] #[cfg(wrap_proc_macro)] mod imp; #[cfg(span_locations)] mod location; use crate::extra::DelimSpan; use crate::marker::{ProcMacroAutoTraits, MARKER}; use core::cmp::Ordering; use core::fmt::{self, Debug, Display}; use core::hash::{Hash, Hasher}; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use core::str::FromStr; use std::error::Error; use std::ffi::CStr; #[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub use crate::location::LineColumn; /// An abstract stream of tokens, or more concretely a sequence of token trees. /// /// This type provides interfaces for iterating over token trees and for /// collecting token trees into one stream. /// /// Token stream is both the input and output of `#[proc_macro]`, /// `#[proc_macro_attribute]` and `#[proc_macro_derive]` definitions. #[derive(Clone)] pub struct TokenStream { inner: imp::TokenStream, _marker: ProcMacroAutoTraits, } /// Error returned from `TokenStream::from_str`. pub struct LexError { inner: imp::LexError, _marker: ProcMacroAutoTraits, } impl TokenStream { fn _new(inner: imp::TokenStream) -> Self { TokenStream { inner, _marker: MARKER, } } fn _new_fallback(inner: fallback::TokenStream) -> Self { TokenStream { inner: inner.into(), _marker: MARKER, } } /// Returns an empty `TokenStream` containing no token trees. pub fn new() -> Self { TokenStream::_new(imp::TokenStream::new()) } /// Checks if this `TokenStream` is empty. pub fn is_empty(&self) -> bool { self.inner.is_empty() } } /// `TokenStream::default()` returns an empty stream, /// i.e. this is equivalent with `TokenStream::new()`. impl Default for TokenStream { fn default() -> Self { TokenStream::new() } } /// Attempts to break the string into tokens and parse those tokens into a token /// stream. /// /// May fail for a number of reasons, for example, if the string contains /// unbalanced delimiters or characters not existing in the language. /// /// NOTE: Some errors may cause panics instead of returning `LexError`. We /// reserve the right to change these errors into `LexError`s later. impl FromStr for TokenStream { type Err = LexError; fn from_str(src: &str) -> Result { let e = src.parse().map_err(|e| LexError { inner: e, _marker: MARKER, })?; Ok(TokenStream::_new(e)) } } #[cfg(feature = "proc-macro")] #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { TokenStream::_new(inner.into()) } } #[cfg(feature = "proc-macro")] #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { inner.inner.into() } } impl From for TokenStream { fn from(token: TokenTree) -> Self { TokenStream::_new(imp::TokenStream::from(token)) } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { self.inner.extend(streams); } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { self.inner .extend(streams.into_iter().map(|stream| stream.inner)); } } /// Collects a number of token trees into a single stream. impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { TokenStream::_new(streams.into_iter().collect()) } } impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { TokenStream::_new(streams.into_iter().map(|i| i.inner).collect()) } } /// Prints the token stream as a string that is supposed to be losslessly /// convertible back into the same token stream (modulo spans), except for /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative /// numeric literals. impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } /// Prints token in a form convenient for debugging. impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } impl LexError { pub fn span(&self) -> Span { Span::_new(self.inner.span()) } } impl Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } impl Error for LexError {} /// The source file of a given `Span`. /// /// This type is semver exempt and not exposed by default. #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] #[derive(Clone, PartialEq, Eq)] pub struct SourceFile { inner: imp::SourceFile, _marker: ProcMacroAutoTraits, } #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] impl SourceFile { fn _new(inner: imp::SourceFile) -> Self { SourceFile { inner, _marker: MARKER, } } /// Get the path to this source file. /// /// ### Note /// /// If the code span associated with this `SourceFile` was generated by an /// external macro, this may not be an actual path on the filesystem. Use /// [`is_real`] to check. /// /// Also note that even if `is_real` returns `true`, if /// `--remap-path-prefix` was passed on the command line, the path as given /// may not actually be valid. /// /// [`is_real`]: #method.is_real pub fn path(&self) -> PathBuf { self.inner.path() } /// Returns `true` if this source file is a real source file, and not /// generated by an external macro's expansion. pub fn is_real(&self) -> bool { self.inner.is_real() } } #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] impl Debug for SourceFile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } /// A region of source code, along with macro expansion information. #[derive(Copy, Clone)] pub struct Span { inner: imp::Span, _marker: ProcMacroAutoTraits, } impl Span { fn _new(inner: imp::Span) -> Self { Span { inner, _marker: MARKER, } } fn _new_fallback(inner: fallback::Span) -> Self { Span { inner: inner.into(), _marker: MARKER, } } /// The span of the invocation of the current procedural macro. /// /// Identifiers created with this span will be resolved as if they were /// written directly at the macro call location (call-site hygiene) and /// other code at the macro call site will be able to refer to them as well. pub fn call_site() -> Self { Span::_new(imp::Span::call_site()) } /// The span located at the invocation of the procedural macro, but with /// local variables, labels, and `$crate` resolved at the definition site /// of the macro. This is the same hygiene behavior as `macro_rules`. pub fn mixed_site() -> Self { Span::_new(imp::Span::mixed_site()) } /// A span that resolves at the macro definition site. /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn def_site() -> Self { Span::_new(imp::Span::def_site()) } /// Creates a new span with the same line/column information as `self` but /// that resolves symbols as though it were at `other`. pub fn resolved_at(&self, other: Span) -> Span { Span::_new(self.inner.resolved_at(other.inner)) } /// Creates a new span with the same name resolution behavior as `self` but /// with the line/column information of `other`. pub fn located_at(&self, other: Span) -> Span { Span::_new(self.inner.located_at(other.inner)) } /// Convert `proc_macro2::Span` to `proc_macro::Span`. /// /// This method is available when building with a nightly compiler, or when /// building with rustc 1.29+ *without* semver exempt features. /// /// # Panics /// /// Panics if called from outside of a procedural macro. Unlike /// `proc_macro2::Span`, the `proc_macro::Span` type can only exist within /// the context of a procedural macro invocation. #[cfg(wrap_proc_macro)] pub fn unwrap(self) -> proc_macro::Span { self.inner.unwrap() } // Soft deprecated. Please use Span::unwrap. #[cfg(wrap_proc_macro)] #[doc(hidden)] pub fn unstable(self) -> proc_macro::Span { self.unwrap() } /// The original source file into which this span points. /// /// This method is semver exempt and not exposed by default. #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn source_file(&self) -> SourceFile { SourceFile::_new(self.inner.source_file()) } /// Returns the span's byte position range in the source file. /// /// This method requires the `"span-locations"` feature to be enabled. /// /// When executing in a procedural macro context, the returned range is only /// accurate if compiled with a nightly toolchain. The stable toolchain does /// not have this information available. When executing outside of a /// procedural macro, such as main.rs or build.rs, the byte range is always /// accurate regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn byte_range(&self) -> Range { self.inner.byte_range() } /// Get the starting line/column in the source file for this span. /// /// This method requires the `"span-locations"` feature to be enabled. /// /// When executing in a procedural macro context, the returned line/column /// are only meaningful if compiled with a nightly toolchain. The stable /// toolchain does not have this information available. When executing /// outside of a procedural macro, such as main.rs or build.rs, the /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn start(&self) -> LineColumn { self.inner.start() } /// Get the ending line/column in the source file for this span. /// /// This method requires the `"span-locations"` feature to be enabled. /// /// When executing in a procedural macro context, the returned line/column /// are only meaningful if compiled with a nightly toolchain. The stable /// toolchain does not have this information available. When executing /// outside of a procedural macro, such as main.rs or build.rs, the /// line/column are always meaningful regardless of toolchain. #[cfg(span_locations)] #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] pub fn end(&self) -> LineColumn { self.inner.end() } /// Create a new span encompassing `self` and `other`. /// /// Returns `None` if `self` and `other` are from different files. /// /// Warning: the underlying [`proc_macro::Span::join`] method is /// nightly-only. When called from within a procedural macro not using a /// nightly compiler, this method will always return `None`. /// /// [`proc_macro::Span::join`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.join pub fn join(&self, other: Span) -> Option { self.inner.join(other.inner).map(Span::_new) } /// Compares two spans to see if they're equal. /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] #[cfg_attr(docsrs, doc(cfg(procmacro2_semver_exempt)))] pub fn eq(&self, other: &Span) -> bool { self.inner.eq(&other.inner) } /// Returns the source text behind a span. This preserves the original /// source code, including spaces and comments. It only returns a result if /// the span corresponds to real source code. /// /// Note: The observable result of a macro should only rely on the tokens /// and not on this source text. The result of this function is a best /// effort to be used for diagnostics only. pub fn source_text(&self) -> Option { self.inner.source_text() } } /// Prints a span in a form convenient for debugging. impl Debug for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`). #[derive(Clone)] pub enum TokenTree { /// A token stream surrounded by bracket delimiters. Group(Group), /// An identifier. Ident(Ident), /// A single punctuation character (`+`, `,`, `$`, etc.). Punct(Punct), /// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc. Literal(Literal), } impl TokenTree { /// Returns the span of this tree, delegating to the `span` method of /// the contained token or a delimited stream. pub fn span(&self) -> Span { match self { TokenTree::Group(t) => t.span(), TokenTree::Ident(t) => t.span(), TokenTree::Punct(t) => t.span(), TokenTree::Literal(t) => t.span(), } } /// Configures the span for *only this token*. /// /// Note that if this token is a `Group` then this method will not configure /// the span of each of the internal tokens, this will simply delegate to /// the `set_span` method of each variant. pub fn set_span(&mut self, span: Span) { match self { TokenTree::Group(t) => t.set_span(span), TokenTree::Ident(t) => t.set_span(span), TokenTree::Punct(t) => t.set_span(span), TokenTree::Literal(t) => t.set_span(span), } } } impl From for TokenTree { fn from(g: Group) -> Self { TokenTree::Group(g) } } impl From for TokenTree { fn from(g: Ident) -> Self { TokenTree::Ident(g) } } impl From for TokenTree { fn from(g: Punct) -> Self { TokenTree::Punct(g) } } impl From for TokenTree { fn from(g: Literal) -> Self { TokenTree::Literal(g) } } /// Prints the token tree as a string that is supposed to be losslessly /// convertible back into the same token tree (modulo spans), except for /// possibly `TokenTree::Group`s with `Delimiter::None` delimiters and negative /// numeric literals. impl Display for TokenTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenTree::Group(t) => Display::fmt(t, f), TokenTree::Ident(t) => Display::fmt(t, f), TokenTree::Punct(t) => Display::fmt(t, f), TokenTree::Literal(t) => Display::fmt(t, f), } } } /// Prints token tree in a form convenient for debugging. impl Debug for TokenTree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Each of these has the name in the struct type in the derived debug, // so don't bother with an extra layer of indirection match self { TokenTree::Group(t) => Debug::fmt(t, f), TokenTree::Ident(t) => { let mut debug = f.debug_struct("Ident"); debug.field("sym", &format_args!("{}", t)); imp::debug_span_field_if_nontrivial(&mut debug, t.span().inner); debug.finish() } TokenTree::Punct(t) => Debug::fmt(t, f), TokenTree::Literal(t) => Debug::fmt(t, f), } } } /// A delimited token stream. /// /// A `Group` internally contains a `TokenStream` which is surrounded by /// `Delimiter`s. #[derive(Clone)] pub struct Group { inner: imp::Group, } /// Describes how a sequence of token trees is delimited. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Delimiter { /// `( ... )` Parenthesis, /// `{ ... }` Brace, /// `[ ... ]` Bracket, /// `∅ ... ∅` /// /// An invisible delimiter, that may, for example, appear around tokens /// coming from a "macro variable" `$var`. It is important to preserve /// operator priorities in cases like `$var * 3` where `$var` is `1 + 2`. /// Invisible delimiters may not survive roundtrip of a token stream through /// a string. /// ///
/// /// Note: rustc currently can ignore the grouping of tokens delimited by `None` in the output /// of a proc_macro. Only `None`-delimited groups created by a macro_rules macro in the input /// of a proc_macro macro are preserved, and only in very specific circumstances. /// Any `None`-delimited groups (re)created by a proc_macro will therefore not preserve /// operator priorities as indicated above. The other `Delimiter` variants should be used /// instead in this context. This is a rustc bug. For details, see /// [rust-lang/rust#67062](https://github.com/rust-lang/rust/issues/67062). /// ///
None, } impl Group { fn _new(inner: imp::Group) -> Self { Group { inner } } fn _new_fallback(inner: fallback::Group) -> Self { Group { inner: inner.into(), } } /// Creates a new `Group` with the given delimiter and token stream. /// /// This constructor will set the span for this group to /// `Span::call_site()`. To change the span you can use the `set_span` /// method below. pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self { Group { inner: imp::Group::new(delimiter, stream.inner), } } /// Returns the punctuation used as the delimiter for this group: a set of /// parentheses, square brackets, or curly braces. pub fn delimiter(&self) -> Delimiter { self.inner.delimiter() } /// Returns the `TokenStream` of tokens that are delimited in this `Group`. /// /// Note that the returned token stream does not include the delimiter /// returned above. pub fn stream(&self) -> TokenStream { TokenStream::_new(self.inner.stream()) } /// Returns the span for the delimiters of this token stream, spanning the /// entire `Group`. /// /// ```text /// pub fn span(&self) -> Span { /// ^^^^^^^ /// ``` pub fn span(&self) -> Span { Span::_new(self.inner.span()) } /// Returns the span pointing to the opening delimiter of this group. /// /// ```text /// pub fn span_open(&self) -> Span { /// ^ /// ``` pub fn span_open(&self) -> Span { Span::_new(self.inner.span_open()) } /// Returns the span pointing to the closing delimiter of this group. /// /// ```text /// pub fn span_close(&self) -> Span { /// ^ /// ``` pub fn span_close(&self) -> Span { Span::_new(self.inner.span_close()) } /// Returns an object that holds this group's `span_open()` and /// `span_close()` together (in a more compact representation than holding /// those 2 spans individually). pub fn delim_span(&self) -> DelimSpan { DelimSpan::new(&self.inner) } /// Configures the span for this `Group`'s delimiters, but not its internal /// tokens. /// /// This method will **not** set the span of all the internal tokens spanned /// by this group, but rather it will only set the span of the delimiter /// tokens at the level of the `Group`. pub fn set_span(&mut self, span: Span) { self.inner.set_span(span.inner); } } /// Prints the group as a string that should be losslessly convertible back /// into the same group (modulo spans), except for possibly `TokenTree::Group`s /// with `Delimiter::None` delimiters. impl Display for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, formatter) } } impl Debug for Group { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, formatter) } } /// A `Punct` is a single punctuation character like `+`, `-` or `#`. /// /// Multicharacter operators like `+=` are represented as two instances of /// `Punct` with different forms of `Spacing` returned. #[derive(Clone)] pub struct Punct { ch: char, spacing: Spacing, span: Span, } /// Whether a `Punct` is followed immediately by another `Punct` or followed by /// another token or whitespace. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Spacing { /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`. Alone, /// E.g. `+` is `Joint` in `+=` or `'` is `Joint` in `'#`. /// /// Additionally, single quote `'` can join with identifiers to form /// lifetimes `'ident`. Joint, } impl Punct { /// Creates a new `Punct` from the given character and spacing. /// /// The `ch` argument must be a valid punctuation character permitted by the /// language, otherwise the function will panic. /// /// The returned `Punct` will have the default span of `Span::call_site()` /// which can be further configured with the `set_span` method below. pub fn new(ch: char, spacing: Spacing) -> Self { Punct { ch, spacing, span: Span::call_site(), } } /// Returns the value of this punctuation character as `char`. pub fn as_char(&self) -> char { self.ch } /// Returns the spacing of this punctuation character, indicating whether /// it's immediately followed by another `Punct` in the token stream, so /// they can potentially be combined into a multicharacter operator /// (`Joint`), or it's followed by some other token or whitespace (`Alone`) /// so the operator has certainly ended. pub fn spacing(&self) -> Spacing { self.spacing } /// Returns the span for this punctuation character. pub fn span(&self) -> Span { self.span } /// Configure the span for this punctuation character. pub fn set_span(&mut self, span: Span) { self.span = span; } } /// Prints the punctuation character as a string that should be losslessly /// convertible back into the same character. impl Display for Punct { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.ch, f) } } impl Debug for Punct { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut debug = fmt.debug_struct("Punct"); debug.field("char", &self.ch); debug.field("spacing", &self.spacing); imp::debug_span_field_if_nontrivial(&mut debug, self.span.inner); debug.finish() } } /// A word of Rust code, which may be a keyword or legal variable name. /// /// An identifier consists of at least one Unicode code point, the first of /// which has the XID_Start property and the rest of which have the XID_Continue /// property. /// /// - The empty string is not an identifier. Use `Option`. /// - A lifetime is not an identifier. Use `syn::Lifetime` instead. /// /// An identifier constructed with `Ident::new` is permitted to be a Rust /// keyword, though parsing one through its [`Parse`] implementation rejects /// Rust keywords. Use `input.call(Ident::parse_any)` when parsing to match the /// behaviour of `Ident::new`. /// /// [`Parse`]: https://docs.rs/syn/2.0/syn/parse/trait.Parse.html /// /// # Examples /// /// A new ident can be created from a string using the `Ident::new` function. /// A span must be provided explicitly which governs the name resolution /// behavior of the resulting identifier. /// /// ``` /// use proc_macro2::{Ident, Span}; /// /// fn main() { /// let call_ident = Ident::new("calligraphy", Span::call_site()); /// /// println!("{}", call_ident); /// } /// ``` /// /// An ident can be interpolated into a token stream using the `quote!` macro. /// /// ``` /// use proc_macro2::{Ident, Span}; /// use quote::quote; /// /// fn main() { /// let ident = Ident::new("demo", Span::call_site()); /// /// // Create a variable binding whose name is this ident. /// let expanded = quote! { let #ident = 10; }; /// /// // Create a variable binding with a slightly different name. /// let temp_ident = Ident::new(&format!("new_{}", ident), Span::call_site()); /// let expanded = quote! { let #temp_ident = 10; }; /// } /// ``` /// /// A string representation of the ident is available through the `to_string()` /// method. /// /// ``` /// # use proc_macro2::{Ident, Span}; /// # /// # let ident = Ident::new("another_identifier", Span::call_site()); /// # /// // Examine the ident as a string. /// let ident_string = ident.to_string(); /// if ident_string.len() > 60 { /// println!("Very long identifier: {}", ident_string) /// } /// ``` #[derive(Clone)] pub struct Ident { inner: imp::Ident, _marker: ProcMacroAutoTraits, } impl Ident { fn _new(inner: imp::Ident) -> Self { Ident { inner, _marker: MARKER, } } /// Creates a new `Ident` with the given `string` as well as the specified /// `span`. /// /// The `string` argument must be a valid identifier permitted by the /// language, otherwise the function will panic. /// /// Note that `span`, currently in rustc, configures the hygiene information /// for this identifier. /// /// As of this time `Span::call_site()` explicitly opts-in to "call-site" /// hygiene meaning that identifiers created with this span will be resolved /// as if they were written directly at the location of the macro call, and /// other code at the macro call site will be able to refer to them as well. /// /// Later spans like `Span::def_site()` will allow to opt-in to /// "definition-site" hygiene meaning that identifiers created with this /// span will be resolved at the location of the macro definition and other /// code at the macro call site will not be able to refer to them. /// /// Due to the current importance of hygiene this constructor, unlike other /// tokens, requires a `Span` to be specified at construction. /// /// # Panics /// /// Panics if the input string is neither a keyword nor a legal variable /// name. If you are not sure whether the string contains an identifier and /// need to handle an error case, use /// syn::parse_str::<Ident> /// rather than `Ident::new`. #[track_caller] pub fn new(string: &str, span: Span) -> Self { Ident::_new(imp::Ident::new_checked(string, span.inner)) } /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). The /// `string` argument must be a valid identifier permitted by the language /// (including keywords, e.g. `fn`). Keywords which are usable in path /// segments (e.g. `self`, `super`) are not supported, and will cause a /// panic. #[track_caller] pub fn new_raw(string: &str, span: Span) -> Self { Ident::_new(imp::Ident::new_raw_checked(string, span.inner)) } /// Returns the span of this `Ident`. pub fn span(&self) -> Span { Span::_new(self.inner.span()) } /// Configures the span of this `Ident`, possibly changing its hygiene /// context. pub fn set_span(&mut self, span: Span) { self.inner.set_span(span.inner); } } impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { self.inner == other.inner } } impl PartialEq for Ident where T: ?Sized + AsRef, { fn eq(&self, other: &T) -> bool { self.inner == other } } impl Eq for Ident {} impl PartialOrd for Ident { fn partial_cmp(&self, other: &Ident) -> Option { Some(self.cmp(other)) } } impl Ord for Ident { fn cmp(&self, other: &Ident) -> Ordering { self.to_string().cmp(&other.to_string()) } } impl Hash for Ident { fn hash(&self, hasher: &mut H) { self.to_string().hash(hasher); } } /// Prints the identifier as a string that should be losslessly convertible back /// into the same identifier. impl Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } impl Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } /// A literal string (`"hello"`), byte string (`b"hello"`), character (`'a'`), /// byte character (`b'a'`), an integer or floating point number with or without /// a suffix (`1`, `1u8`, `2.3`, `2.3f32`). /// /// Boolean literals like `true` and `false` do not belong here, they are /// `Ident`s. #[derive(Clone)] pub struct Literal { inner: imp::Literal, _marker: ProcMacroAutoTraits, } macro_rules! suffixed_int_literals { ($($name:ident => $kind:ident,)*) => ($( /// Creates a new suffixed integer literal with the specified value. /// /// This function will create an integer like `1u32` where the integer /// value specified is the first part of the token and the integral is /// also suffixed at the end. Literals created from negative numbers may /// not survive roundtrips through `TokenStream` or strings and may be /// broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` /// span by default, which can be configured with the `set_span` method /// below. pub fn $name(n: $kind) -> Literal { Literal::_new(imp::Literal::$name(n)) } )*) } macro_rules! unsuffixed_int_literals { ($($name:ident => $kind:ident,)*) => ($( /// Creates a new unsuffixed integer literal with the specified value. /// /// This function will create an integer like `1` where the integer /// value specified is the first part of the token. No suffix is /// specified on this token, meaning that invocations like /// `Literal::i8_unsuffixed(1)` are equivalent to /// `Literal::u32_unsuffixed(1)`. Literals created from negative numbers /// may not survive roundtrips through `TokenStream` or strings and may /// be broken into two tokens (`-` and positive literal). /// /// Literals created through this method have the `Span::call_site()` /// span by default, which can be configured with the `set_span` method /// below. pub fn $name(n: $kind) -> Literal { Literal::_new(imp::Literal::$name(n)) } )*) } impl Literal { fn _new(inner: imp::Literal) -> Self { Literal { inner, _marker: MARKER, } } fn _new_fallback(inner: fallback::Literal) -> Self { Literal { inner: inner.into(), _marker: MARKER, } } suffixed_int_literals! { u8_suffixed => u8, u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, i128_suffixed => i128, isize_suffixed => isize, } unsuffixed_int_literals! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, i128_unsuffixed => i128, isize_unsuffixed => isize, } /// Creates a new unsuffixed floating-point literal. /// /// This constructor is similar to those like `Literal::i8_unsuffixed` where /// the float's value is emitted directly into the token but no suffix is /// used, so it may be inferred to be a `f64` later in the compiler. /// Literals created from negative numbers may not survive round-trips /// through `TokenStream` or strings and may be broken into two tokens (`-` /// and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f64_unsuffixed(f: f64) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f64_unsuffixed(f)) } /// Creates a new suffixed floating-point literal. /// /// This constructor will create a literal like `1.0f64` where the value /// specified is the preceding part of the token and `f64` is the suffix of /// the token. This token will always be inferred to be an `f64` in the /// compiler. Literals created from negative numbers may not survive /// round-trips through `TokenStream` or strings and may be broken into two /// tokens (`-` and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f64_suffixed(f: f64) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f64_suffixed(f)) } /// Creates a new unsuffixed floating-point literal. /// /// This constructor is similar to those like `Literal::i8_unsuffixed` where /// the float's value is emitted directly into the token but no suffix is /// used, so it may be inferred to be a `f64` later in the compiler. /// Literals created from negative numbers may not survive round-trips /// through `TokenStream` or strings and may be broken into two tokens (`-` /// and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f32_unsuffixed(f: f32) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f32_unsuffixed(f)) } /// Creates a new suffixed floating-point literal. /// /// This constructor will create a literal like `1.0f32` where the value /// specified is the preceding part of the token and `f32` is the suffix of /// the token. This token will always be inferred to be an `f32` in the /// compiler. Literals created from negative numbers may not survive /// round-trips through `TokenStream` or strings and may be broken into two /// tokens (`-` and positive literal). /// /// # Panics /// /// This function requires that the specified float is finite, for example /// if it is infinity or NaN this function will panic. pub fn f32_suffixed(f: f32) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f32_suffixed(f)) } /// String literal. pub fn string(string: &str) -> Literal { Literal::_new(imp::Literal::string(string)) } /// Character literal. pub fn character(ch: char) -> Literal { Literal::_new(imp::Literal::character(ch)) } /// Byte character literal. pub fn byte_character(byte: u8) -> Literal { Literal::_new(imp::Literal::byte_character(byte)) } /// Byte string literal. pub fn byte_string(bytes: &[u8]) -> Literal { Literal::_new(imp::Literal::byte_string(bytes)) } /// C string literal. pub fn c_string(string: &CStr) -> Literal { Literal::_new(imp::Literal::c_string(string)) } /// Returns the span encompassing this literal. pub fn span(&self) -> Span { Span::_new(self.inner.span()) } /// Configures the span associated for this literal. pub fn set_span(&mut self, span: Span) { self.inner.set_span(span.inner); } /// Returns a `Span` that is a subset of `self.span()` containing only /// the source bytes in range `range`. Returns `None` if the would-be /// trimmed span is outside the bounds of `self`. /// /// Warning: the underlying [`proc_macro::Literal::subspan`] method is /// nightly-only. When called from within a procedural macro not using a /// nightly compiler, this method will always return `None`. /// /// [`proc_macro::Literal::subspan`]: https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.subspan pub fn subspan>(&self, range: R) -> Option { self.inner.subspan(range).map(Span::_new) } // Intended for the `quote!` macro to use when constructing a proc-macro2 // token out of a macro_rules $:literal token, which is already known to be // a valid literal. This avoids reparsing/validating the literal's string // representation. This is not public API other than for quote. #[doc(hidden)] pub unsafe fn from_str_unchecked(repr: &str) -> Self { Literal::_new(unsafe { imp::Literal::from_str_unchecked(repr) }) } } impl FromStr for Literal { type Err = LexError; fn from_str(repr: &str) -> Result { repr.parse().map(Literal::_new).map_err(|inner| LexError { inner, _marker: MARKER, }) } } impl Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.inner, f) } } impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.inner, f) } } /// Public implementation details for the `TokenStream` type, such as iterators. pub mod token_stream { use crate::marker::{ProcMacroAutoTraits, MARKER}; use crate::{imp, TokenTree}; use core::fmt::{self, Debug}; pub use crate::TokenStream; /// An iterator over `TokenStream`'s `TokenTree`s. /// /// The iteration is "shallow", e.g. the iterator doesn't recurse into /// delimited groups, and returns whole groups as token trees. #[derive(Clone)] pub struct IntoIter { inner: imp::TokenTreeIter, _marker: ProcMacroAutoTraits, } impl Iterator for IntoIter { type Item = TokenTree; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("TokenStream ")?; f.debug_list().entries(self.clone()).finish() } } impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { IntoIter { inner: self.inner.into_iter(), _marker: MARKER, } } } } proc-macro2/src/location.rs0000644000175000017500000000154714661133735016641 0ustar jamespagejamespageuse core::cmp::Ordering; /// A line-column pair representing the start or end of a `Span`. /// /// This type is semver exempt and not exposed by default. #[cfg_attr(docsrs, doc(cfg(feature = "span-locations")))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct LineColumn { /// The 1-indexed line in the source file on which the span starts or ends /// (inclusive). pub line: usize, /// The 0-indexed column (in UTF-8 characters) in the source file on which /// the span starts or ends (inclusive). pub column: usize, } impl Ord for LineColumn { fn cmp(&self, other: &Self) -> Ordering { self.line .cmp(&other.line) .then(self.column.cmp(&other.column)) } } impl PartialOrd for LineColumn { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } proc-macro2/src/rcvec.rs0000644000175000017500000000552514661133735016133 0ustar jamespagejamespageuse alloc::rc::Rc; use alloc::vec; use core::mem; use core::panic::RefUnwindSafe; use core::slice; pub(crate) struct RcVec { inner: Rc>, } pub(crate) struct RcVecBuilder { inner: Vec, } pub(crate) struct RcVecMut<'a, T> { inner: &'a mut Vec, } #[derive(Clone)] pub(crate) struct RcVecIntoIter { inner: vec::IntoIter, } impl RcVec { pub fn is_empty(&self) -> bool { self.inner.is_empty() } pub fn len(&self) -> usize { self.inner.len() } pub fn iter(&self) -> slice::Iter { self.inner.iter() } pub fn make_mut(&mut self) -> RcVecMut where T: Clone, { RcVecMut { inner: Rc::make_mut(&mut self.inner), } } pub fn get_mut(&mut self) -> Option> { let inner = Rc::get_mut(&mut self.inner)?; Some(RcVecMut { inner }) } pub fn make_owned(mut self) -> RcVecBuilder where T: Clone, { let vec = if let Some(owned) = Rc::get_mut(&mut self.inner) { mem::take(owned) } else { Vec::clone(&self.inner) }; RcVecBuilder { inner: vec } } } impl RcVecBuilder { pub fn new() -> Self { RcVecBuilder { inner: Vec::new() } } pub fn with_capacity(cap: usize) -> Self { RcVecBuilder { inner: Vec::with_capacity(cap), } } pub fn push(&mut self, element: T) { self.inner.push(element); } pub fn extend(&mut self, iter: impl IntoIterator) { self.inner.extend(iter); } pub fn as_mut(&mut self) -> RcVecMut { RcVecMut { inner: &mut self.inner, } } pub fn build(self) -> RcVec { RcVec { inner: Rc::new(self.inner), } } } impl<'a, T> RcVecMut<'a, T> { pub fn push(&mut self, element: T) { self.inner.push(element); } pub fn extend(&mut self, iter: impl IntoIterator) { self.inner.extend(iter); } pub fn pop(&mut self) -> Option { self.inner.pop() } pub fn as_mut(&mut self) -> RcVecMut { RcVecMut { inner: self.inner } } } impl Clone for RcVec { fn clone(&self) -> Self { RcVec { inner: Rc::clone(&self.inner), } } } impl IntoIterator for RcVecBuilder { type Item = T; type IntoIter = RcVecIntoIter; fn into_iter(self) -> Self::IntoIter { RcVecIntoIter { inner: self.inner.into_iter(), } } } impl Iterator for RcVecIntoIter { type Item = T; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl RefUnwindSafe for RcVec where T: RefUnwindSafe {} proc-macro2/src/marker.rs0000644000175000017500000000107514661133735016306 0ustar jamespagejamespageuse alloc::rc::Rc; use core::marker::PhantomData; use core::panic::{RefUnwindSafe, UnwindSafe}; // Zero sized marker with the correct set of autotrait impls we want all proc // macro types to have. #[derive(Copy, Clone)] #[cfg_attr( all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)), derive(PartialEq, Eq) )] pub(crate) struct ProcMacroAutoTraits(PhantomData>); pub(crate) const MARKER: ProcMacroAutoTraits = ProcMacroAutoTraits(PhantomData); impl UnwindSafe for ProcMacroAutoTraits {} impl RefUnwindSafe for ProcMacroAutoTraits {} proc-macro2/src/fallback.rs0000644000175000017500000007770314661133735016577 0ustar jamespagejamespage#[cfg(span_locations)] use crate::location::LineColumn; use crate::parse::{self, Cursor}; use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut}; use crate::{Delimiter, Spacing, TokenTree}; #[cfg(all(span_locations, not(fuzzing)))] use alloc::collections::BTreeMap; #[cfg(all(span_locations, not(fuzzing)))] use core::cell::RefCell; #[cfg(span_locations)] use core::cmp; use core::fmt::{self, Debug, Display, Write}; use core::mem::ManuallyDrop; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use core::ptr; use core::str::{self, FromStr}; use std::ffi::CStr; #[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; /// Force use of proc-macro2's fallback implementation of the API for now, even /// if the compiler's implementation is available. pub fn force() { #[cfg(wrap_proc_macro)] crate::detection::force_fallback(); } /// Resume using the compiler's implementation of the proc macro API if it is /// available. pub fn unforce() { #[cfg(wrap_proc_macro)] crate::detection::unforce_fallback(); } #[derive(Clone)] pub(crate) struct TokenStream { inner: RcVec, } #[derive(Debug)] pub(crate) struct LexError { pub(crate) span: Span, } impl LexError { pub(crate) fn span(&self) -> Span { self.span } pub(crate) fn call_site() -> Self { LexError { span: Span::call_site(), } } } impl TokenStream { pub fn new() -> Self { TokenStream { inner: RcVecBuilder::new().build(), } } pub fn is_empty(&self) -> bool { self.inner.len() == 0 } fn take_inner(self) -> RcVecBuilder { let nodrop = ManuallyDrop::new(self); unsafe { ptr::read(&nodrop.inner) }.make_owned() } } fn push_token_from_proc_macro(mut vec: RcVecMut, token: TokenTree) { // https://github.com/dtolnay/proc-macro2/issues/235 match token { TokenTree::Literal(crate::Literal { #[cfg(wrap_proc_macro)] inner: crate::imp::Literal::Fallback(literal), #[cfg(not(wrap_proc_macro))] inner: literal, .. }) if literal.repr.starts_with('-') => { push_negative_literal(vec, literal); } _ => vec.push(token), } #[cold] fn push_negative_literal(mut vec: RcVecMut, mut literal: Literal) { literal.repr.remove(0); let mut punct = crate::Punct::new('-', Spacing::Alone); punct.set_span(crate::Span::_new_fallback(literal.span)); vec.push(TokenTree::Punct(punct)); vec.push(TokenTree::Literal(crate::Literal::_new_fallback(literal))); } } // Nonrecursive to prevent stack overflow. impl Drop for TokenStream { fn drop(&mut self) { let mut inner = match self.inner.get_mut() { Some(inner) => inner, None => return, }; while let Some(token) = inner.pop() { let group = match token { TokenTree::Group(group) => group.inner, _ => continue, }; #[cfg(wrap_proc_macro)] let group = match group { crate::imp::Group::Fallback(group) => group, crate::imp::Group::Compiler(_) => continue, }; inner.extend(group.stream.take_inner()); } } } pub(crate) struct TokenStreamBuilder { inner: RcVecBuilder, } impl TokenStreamBuilder { pub fn new() -> Self { TokenStreamBuilder { inner: RcVecBuilder::new(), } } pub fn with_capacity(cap: usize) -> Self { TokenStreamBuilder { inner: RcVecBuilder::with_capacity(cap), } } pub fn push_token_from_parser(&mut self, tt: TokenTree) { self.inner.push(tt); } pub fn build(self) -> TokenStream { TokenStream { inner: self.inner.build(), } } } #[cfg(span_locations)] fn get_cursor(src: &str) -> Cursor { #[cfg(fuzzing)] return Cursor { rest: src, off: 1 }; // Create a dummy file & add it to the source map #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let mut sm = sm.borrow_mut(); let span = sm.add_file(src); Cursor { rest: src, off: span.lo, } }) } #[cfg(not(span_locations))] fn get_cursor(src: &str) -> Cursor { Cursor { rest: src } } impl FromStr for TokenStream { type Err = LexError; fn from_str(src: &str) -> Result { // Create a dummy file & add it to the source map let mut cursor = get_cursor(src); // Strip a byte order mark if present const BYTE_ORDER_MARK: &str = "\u{feff}"; if cursor.starts_with(BYTE_ORDER_MARK) { cursor = cursor.advance(BYTE_ORDER_MARK.len()); } parse::token_stream(cursor) } } impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("cannot parse string into token stream") } } impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut joint = false; for (i, tt) in self.inner.iter().enumerate() { if i != 0 && !joint { write!(f, " ")?; } joint = false; match tt { TokenTree::Group(tt) => Display::fmt(tt, f), TokenTree::Ident(tt) => Display::fmt(tt, f), TokenTree::Punct(tt) => { joint = tt.spacing() == Spacing::Joint; Display::fmt(tt, f) } TokenTree::Literal(tt) => Display::fmt(tt, f), }?; } Ok(()) } } impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("TokenStream ")?; f.debug_list().entries(self.clone()).finish() } } #[cfg(feature = "proc-macro")] impl From for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { inner .to_string() .parse() .expect("compiler token stream parse failed") } } #[cfg(feature = "proc-macro")] impl From for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { inner .to_string() .parse() .expect("failed to parse to compiler tokens") } } impl From for TokenStream { fn from(tree: TokenTree) -> Self { let mut stream = RcVecBuilder::new(); push_token_from_proc_macro(stream.as_mut(), tree); TokenStream { inner: stream.build(), } } } impl FromIterator for TokenStream { fn from_iter>(tokens: I) -> Self { let mut stream = TokenStream::new(); stream.extend(tokens); stream } } impl FromIterator for TokenStream { fn from_iter>(streams: I) -> Self { let mut v = RcVecBuilder::new(); for stream in streams { v.extend(stream.take_inner()); } TokenStream { inner: v.build() } } } impl Extend for TokenStream { fn extend>(&mut self, tokens: I) { let mut vec = self.inner.make_mut(); tokens .into_iter() .for_each(|token| push_token_from_proc_macro(vec.as_mut(), token)); } } impl Extend for TokenStream { fn extend>(&mut self, streams: I) { self.inner.make_mut().extend(streams.into_iter().flatten()); } } pub(crate) type TokenTreeIter = RcVecIntoIter; impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = TokenTreeIter; fn into_iter(self) -> TokenTreeIter { self.take_inner().into_iter() } } #[cfg(procmacro2_semver_exempt)] #[derive(Clone, PartialEq, Eq)] pub(crate) struct SourceFile { path: PathBuf, } #[cfg(procmacro2_semver_exempt)] impl SourceFile { /// Get the path to this source file as a string. pub fn path(&self) -> PathBuf { self.path.clone() } pub fn is_real(&self) -> bool { false } } #[cfg(procmacro2_semver_exempt)] impl Debug for SourceFile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("SourceFile") .field("path", &self.path()) .field("is_real", &self.is_real()) .finish() } } #[cfg(all(span_locations, not(fuzzing)))] thread_local! { static SOURCE_MAP: RefCell = RefCell::new(SourceMap { // Start with a single dummy file which all call_site() and def_site() // spans reference. files: vec![FileInfo { source_text: String::new(), span: Span { lo: 0, hi: 0 }, lines: vec![0], char_index_to_byte_offset: BTreeMap::new(), }], }); } #[cfg(span_locations)] pub(crate) fn invalidate_current_thread_spans() { #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| sm.borrow_mut().files.truncate(1)); } #[cfg(all(span_locations, not(fuzzing)))] struct FileInfo { source_text: String, span: Span, lines: Vec, char_index_to_byte_offset: BTreeMap, } #[cfg(all(span_locations, not(fuzzing)))] impl FileInfo { fn offset_line_column(&self, offset: usize) -> LineColumn { assert!(self.span_within(Span { lo: offset as u32, hi: offset as u32, })); let offset = offset - self.span.lo as usize; match self.lines.binary_search(&offset) { Ok(found) => LineColumn { line: found + 1, column: 0, }, Err(idx) => LineColumn { line: idx, column: offset - self.lines[idx - 1], }, } } fn span_within(&self, span: Span) -> bool { span.lo >= self.span.lo && span.hi <= self.span.hi } fn byte_range(&mut self, span: Span) -> Range { let lo_char = (span.lo - self.span.lo) as usize; // Look up offset of the largest already-computed char index that is // less than or equal to the current requested one. We resume counting // chars from that point. let (&last_char_index, &last_byte_offset) = self .char_index_to_byte_offset .range(..=lo_char) .next_back() .unwrap_or((&0, &0)); let lo_byte = if last_char_index == lo_char { last_byte_offset } else { let total_byte_offset = match self.source_text[last_byte_offset..] .char_indices() .nth(lo_char - last_char_index) { Some((additional_offset, _ch)) => last_byte_offset + additional_offset, None => self.source_text.len(), }; self.char_index_to_byte_offset .insert(lo_char, total_byte_offset); total_byte_offset }; let trunc_lo = &self.source_text[lo_byte..]; let char_len = (span.hi - span.lo) as usize; lo_byte..match trunc_lo.char_indices().nth(char_len) { Some((offset, _ch)) => lo_byte + offset, None => self.source_text.len(), } } fn source_text(&mut self, span: Span) -> String { let byte_range = self.byte_range(span); self.source_text[byte_range].to_owned() } } /// Computes the offsets of each line in the given source string /// and the total number of characters #[cfg(all(span_locations, not(fuzzing)))] fn lines_offsets(s: &str) -> (usize, Vec) { let mut lines = vec![0]; let mut total = 0; for ch in s.chars() { total += 1; if ch == '\n' { lines.push(total); } } (total, lines) } #[cfg(all(span_locations, not(fuzzing)))] struct SourceMap { files: Vec, } #[cfg(all(span_locations, not(fuzzing)))] impl SourceMap { fn next_start_pos(&self) -> u32 { // Add 1 so there's always space between files. // // We'll always have at least 1 file, as we initialize our files list // with a dummy file. self.files.last().unwrap().span.hi + 1 } fn add_file(&mut self, src: &str) -> Span { let (len, lines) = lines_offsets(src); let lo = self.next_start_pos(); let span = Span { lo, hi: lo + (len as u32), }; self.files.push(FileInfo { source_text: src.to_owned(), span, lines, // Populated lazily by source_text(). char_index_to_byte_offset: BTreeMap::new(), }); span } #[cfg(procmacro2_semver_exempt)] fn filepath(&self, span: Span) -> PathBuf { for (i, file) in self.files.iter().enumerate() { if file.span_within(span) { return PathBuf::from(if i == 0 { "".to_owned() } else { format!("", i) }); } } unreachable!("Invalid span with no related FileInfo!"); } fn fileinfo(&self, span: Span) -> &FileInfo { for file in &self.files { if file.span_within(span) { return file; } } unreachable!("Invalid span with no related FileInfo!"); } fn fileinfo_mut(&mut self, span: Span) -> &mut FileInfo { for file in &mut self.files { if file.span_within(span) { return file; } } unreachable!("Invalid span with no related FileInfo!"); } } #[derive(Clone, Copy, PartialEq, Eq)] pub(crate) struct Span { #[cfg(span_locations)] pub(crate) lo: u32, #[cfg(span_locations)] pub(crate) hi: u32, } impl Span { #[cfg(not(span_locations))] pub fn call_site() -> Self { Span {} } #[cfg(span_locations)] pub fn call_site() -> Self { Span { lo: 0, hi: 0 } } pub fn mixed_site() -> Self { Span::call_site() } #[cfg(procmacro2_semver_exempt)] pub fn def_site() -> Self { Span::call_site() } pub fn resolved_at(&self, _other: Span) -> Span { // Stable spans consist only of line/column information, so // `resolved_at` and `located_at` only select which span the // caller wants line/column information from. *self } pub fn located_at(&self, other: Span) -> Span { other } #[cfg(procmacro2_semver_exempt)] pub fn source_file(&self) -> SourceFile { #[cfg(fuzzing)] return SourceFile { path: PathBuf::from(""), }; #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); let path = sm.filepath(*self); SourceFile { path } }) } #[cfg(span_locations)] pub fn byte_range(&self) -> Range { #[cfg(fuzzing)] return 0..0; #[cfg(not(fuzzing))] { if self.is_call_site() { 0..0 } else { SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self)) } } } #[cfg(span_locations)] pub fn start(&self) -> LineColumn { #[cfg(fuzzing)] return LineColumn { line: 0, column: 0 }; #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); let fi = sm.fileinfo(*self); fi.offset_line_column(self.lo as usize) }) } #[cfg(span_locations)] pub fn end(&self) -> LineColumn { #[cfg(fuzzing)] return LineColumn { line: 0, column: 0 }; #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); let fi = sm.fileinfo(*self); fi.offset_line_column(self.hi as usize) }) } #[cfg(not(span_locations))] pub fn join(&self, _other: Span) -> Option { Some(Span {}) } #[cfg(span_locations)] pub fn join(&self, other: Span) -> Option { #[cfg(fuzzing)] return { let _ = other; None }; #[cfg(not(fuzzing))] SOURCE_MAP.with(|sm| { let sm = sm.borrow(); // If `other` is not within the same FileInfo as us, return None. if !sm.fileinfo(*self).span_within(other) { return None; } Some(Span { lo: cmp::min(self.lo, other.lo), hi: cmp::max(self.hi, other.hi), }) }) } #[cfg(not(span_locations))] pub fn source_text(&self) -> Option { None } #[cfg(span_locations)] pub fn source_text(&self) -> Option { #[cfg(fuzzing)] return None; #[cfg(not(fuzzing))] { if self.is_call_site() { None } else { Some(SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).source_text(*self))) } } } #[cfg(not(span_locations))] pub(crate) fn first_byte(self) -> Self { self } #[cfg(span_locations)] pub(crate) fn first_byte(self) -> Self { Span { lo: self.lo, hi: cmp::min(self.lo.saturating_add(1), self.hi), } } #[cfg(not(span_locations))] pub(crate) fn last_byte(self) -> Self { self } #[cfg(span_locations)] pub(crate) fn last_byte(self) -> Self { Span { lo: cmp::max(self.hi.saturating_sub(1), self.lo), hi: self.hi, } } #[cfg(span_locations)] fn is_call_site(&self) -> bool { self.lo == 0 && self.hi == 0 } } impl Debug for Span { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[cfg(span_locations)] return write!(f, "bytes({}..{})", self.lo, self.hi); #[cfg(not(span_locations))] write!(f, "Span") } } pub(crate) fn debug_span_field_if_nontrivial(debug: &mut fmt::DebugStruct, span: Span) { #[cfg(span_locations)] { if span.is_call_site() { return; } } if cfg!(span_locations) { debug.field("span", &span); } } #[derive(Clone)] pub(crate) struct Group { delimiter: Delimiter, stream: TokenStream, span: Span, } impl Group { pub fn new(delimiter: Delimiter, stream: TokenStream) -> Self { Group { delimiter, stream, span: Span::call_site(), } } pub fn delimiter(&self) -> Delimiter { self.delimiter } pub fn stream(&self) -> TokenStream { self.stream.clone() } pub fn span(&self) -> Span { self.span } pub fn span_open(&self) -> Span { self.span.first_byte() } pub fn span_close(&self) -> Span { self.span.last_byte() } pub fn set_span(&mut self, span: Span) { self.span = span; } } impl Display for Group { // We attempt to match libproc_macro's formatting. // Empty parens: () // Nonempty parens: (...) // Empty brackets: [] // Nonempty brackets: [...] // Empty braces: { } // Nonempty braces: { ... } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (open, close) = match self.delimiter { Delimiter::Parenthesis => ("(", ")"), Delimiter::Brace => ("{ ", "}"), Delimiter::Bracket => ("[", "]"), Delimiter::None => ("", ""), }; f.write_str(open)?; Display::fmt(&self.stream, f)?; if self.delimiter == Delimiter::Brace && !self.stream.inner.is_empty() { f.write_str(" ")?; } f.write_str(close)?; Ok(()) } } impl Debug for Group { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut debug = fmt.debug_struct("Group"); debug.field("delimiter", &self.delimiter); debug.field("stream", &self.stream); debug_span_field_if_nontrivial(&mut debug, self.span); debug.finish() } } #[derive(Clone)] pub(crate) struct Ident { sym: Box, span: Span, raw: bool, } impl Ident { #[track_caller] pub fn new_checked(string: &str, span: Span) -> Self { validate_ident(string); Ident::new_unchecked(string, span) } pub fn new_unchecked(string: &str, span: Span) -> Self { Ident { sym: Box::from(string), span, raw: false, } } #[track_caller] pub fn new_raw_checked(string: &str, span: Span) -> Self { validate_ident_raw(string); Ident::new_raw_unchecked(string, span) } pub fn new_raw_unchecked(string: &str, span: Span) -> Self { Ident { sym: Box::from(string), span, raw: true, } } pub fn span(&self) -> Span { self.span } pub fn set_span(&mut self, span: Span) { self.span = span; } } pub(crate) fn is_ident_start(c: char) -> bool { c == '_' || unicode_ident::is_xid_start(c) } pub(crate) fn is_ident_continue(c: char) -> bool { unicode_ident::is_xid_continue(c) } #[track_caller] fn validate_ident(string: &str) { if string.is_empty() { panic!("Ident is not allowed to be empty; use Option"); } if string.bytes().all(|digit| b'0' <= digit && digit <= b'9') { panic!("Ident cannot be a number; use Literal instead"); } fn ident_ok(string: &str) -> bool { let mut chars = string.chars(); let first = chars.next().unwrap(); if !is_ident_start(first) { return false; } for ch in chars { if !is_ident_continue(ch) { return false; } } true } if !ident_ok(string) { panic!("{:?} is not a valid Ident", string); } } #[track_caller] fn validate_ident_raw(string: &str) { validate_ident(string); match string { "_" | "super" | "self" | "Self" | "crate" => { panic!("`r#{}` cannot be a raw identifier", string); } _ => {} } } impl PartialEq for Ident { fn eq(&self, other: &Ident) -> bool { self.sym == other.sym && self.raw == other.raw } } impl PartialEq for Ident where T: ?Sized + AsRef, { fn eq(&self, other: &T) -> bool { let other = other.as_ref(); if self.raw { other.starts_with("r#") && *self.sym == other[2..] } else { *self.sym == *other } } } impl Display for Ident { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.raw { f.write_str("r#")?; } Display::fmt(&self.sym, f) } } #[allow(clippy::missing_fields_in_debug)] impl Debug for Ident { // Ident(proc_macro), Ident(r#union) #[cfg(not(span_locations))] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_tuple("Ident"); debug.field(&format_args!("{}", self)); debug.finish() } // Ident { // sym: proc_macro, // span: bytes(128..138) // } #[cfg(span_locations)] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut debug = f.debug_struct("Ident"); debug.field("sym", &format_args!("{}", self)); debug_span_field_if_nontrivial(&mut debug, self.span); debug.finish() } } #[derive(Clone)] pub(crate) struct Literal { pub(crate) repr: String, span: Span, } macro_rules! suffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( pub fn $name(n: $kind) -> Literal { Literal::_new(format!(concat!("{}", stringify!($kind)), n)) } )*) } macro_rules! unsuffixed_numbers { ($($name:ident => $kind:ident,)*) => ($( pub fn $name(n: $kind) -> Literal { Literal::_new(n.to_string()) } )*) } impl Literal { pub(crate) fn _new(repr: String) -> Self { Literal { repr, span: Span::call_site(), } } pub(crate) unsafe fn from_str_unchecked(repr: &str) -> Self { Literal::_new(repr.to_owned()) } suffixed_numbers! { u8_suffixed => u8, u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, i128_suffixed => i128, isize_suffixed => isize, f32_suffixed => f32, f64_suffixed => f64, } unsuffixed_numbers! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, i128_unsuffixed => i128, isize_unsuffixed => isize, } pub fn f32_unsuffixed(f: f32) -> Literal { let mut s = f.to_string(); if !s.contains('.') { s.push_str(".0"); } Literal::_new(s) } pub fn f64_unsuffixed(f: f64) -> Literal { let mut s = f.to_string(); if !s.contains('.') { s.push_str(".0"); } Literal::_new(s) } pub fn string(string: &str) -> Literal { let mut repr = String::with_capacity(string.len() + 2); repr.push('"'); escape_utf8(string, &mut repr); repr.push('"'); Literal::_new(repr) } pub fn character(ch: char) -> Literal { let mut repr = String::new(); repr.push('\''); if ch == '"' { // escape_debug turns this into '\"' which is unnecessary. repr.push(ch); } else { repr.extend(ch.escape_debug()); } repr.push('\''); Literal::_new(repr) } pub fn byte_character(byte: u8) -> Literal { let mut repr = "b'".to_string(); #[allow(clippy::match_overlapping_arm)] match byte { b'\0' => repr.push_str(r"\0"), b'\t' => repr.push_str(r"\t"), b'\n' => repr.push_str(r"\n"), b'\r' => repr.push_str(r"\r"), b'\'' => repr.push_str(r"\'"), b'\\' => repr.push_str(r"\\"), b'\x20'..=b'\x7E' => repr.push(byte as char), _ => { let _ = write!(repr, r"\x{:02X}", byte); } } repr.push('\''); Literal::_new(repr) } pub fn byte_string(bytes: &[u8]) -> Literal { let mut repr = "b\"".to_string(); let mut bytes = bytes.iter(); while let Some(&b) = bytes.next() { #[allow(clippy::match_overlapping_arm)] match b { b'\0' => repr.push_str(match bytes.as_slice().first() { // circumvent clippy::octal_escapes lint Some(b'0'..=b'7') => r"\x00", _ => r"\0", }), b'\t' => repr.push_str(r"\t"), b'\n' => repr.push_str(r"\n"), b'\r' => repr.push_str(r"\r"), b'"' => repr.push_str("\\\""), b'\\' => repr.push_str(r"\\"), b'\x20'..=b'\x7E' => repr.push(b as char), _ => { let _ = write!(repr, r"\x{:02X}", b); } } } repr.push('"'); Literal::_new(repr) } pub fn c_string(string: &CStr) -> Literal { let mut repr = "c\"".to_string(); let mut bytes = string.to_bytes(); while !bytes.is_empty() { let (valid, invalid) = match str::from_utf8(bytes) { Ok(all_valid) => { bytes = b""; (all_valid, bytes) } Err(utf8_error) => { let (valid, rest) = bytes.split_at(utf8_error.valid_up_to()); let valid = str::from_utf8(valid).unwrap(); let invalid = utf8_error .error_len() .map_or(rest, |error_len| &rest[..error_len]); bytes = &bytes[valid.len() + invalid.len()..]; (valid, invalid) } }; escape_utf8(valid, &mut repr); for &byte in invalid { let _ = write!(repr, r"\x{:02X}", byte); } } repr.push('"'); Literal::_new(repr) } pub fn span(&self) -> Span { self.span } pub fn set_span(&mut self, span: Span) { self.span = span; } pub fn subspan>(&self, range: R) -> Option { #[cfg(not(span_locations))] { let _ = range; None } #[cfg(span_locations)] { use core::ops::Bound; let lo = match range.start_bound() { Bound::Included(start) => { let start = u32::try_from(*start).ok()?; self.span.lo.checked_add(start)? } Bound::Excluded(start) => { let start = u32::try_from(*start).ok()?; self.span.lo.checked_add(start)?.checked_add(1)? } Bound::Unbounded => self.span.lo, }; let hi = match range.end_bound() { Bound::Included(end) => { let end = u32::try_from(*end).ok()?; self.span.lo.checked_add(end)?.checked_add(1)? } Bound::Excluded(end) => { let end = u32::try_from(*end).ok()?; self.span.lo.checked_add(end)? } Bound::Unbounded => self.span.hi, }; if lo <= hi && hi <= self.span.hi { Some(Span { lo, hi }) } else { None } } } } impl FromStr for Literal { type Err = LexError; fn from_str(repr: &str) -> Result { let mut cursor = get_cursor(repr); #[cfg(span_locations)] let lo = cursor.off; let negative = cursor.starts_with_char('-'); if negative { cursor = cursor.advance(1); if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) { return Err(LexError::call_site()); } } if let Ok((rest, mut literal)) = parse::literal(cursor) { if rest.is_empty() { if negative { literal.repr.insert(0, '-'); } literal.span = Span { #[cfg(span_locations)] lo, #[cfg(span_locations)] hi: rest.off, }; return Ok(literal); } } Err(LexError::call_site()) } } impl Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.repr, f) } } impl Debug for Literal { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let mut debug = fmt.debug_struct("Literal"); debug.field("lit", &format_args!("{}", self.repr)); debug_span_field_if_nontrivial(&mut debug, self.span); debug.finish() } } fn escape_utf8(string: &str, repr: &mut String) { let mut chars = string.chars(); while let Some(ch) = chars.next() { if ch == '\0' { repr.push_str( if chars .as_str() .starts_with(|next| '0' <= next && next <= '7') { // circumvent clippy::octal_escapes lint r"\x00" } else { r"\0" }, ); } else if ch == '\'' { // escape_debug turns this into "\'" which is unnecessary. repr.push(ch); } else { repr.extend(ch.escape_debug()); } } } proc-macro2/rust-toolchain.toml0000644000175000017500000000004614661133735017535 0ustar jamespagejamespage[toolchain] components = ["rust-src"] proc-macro2/.cargo-checksum.json0000664000175000017500000000361114661133735017534 0ustar jamespagejamespage{"files":{"Cargo.toml":"41a9465146a2b62a642e29f065718649e686d3c9585736596392dd941c9b0bef","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"c609b6865476d6c35879784e9155367a97a0da496aa5c3c61488440a20f59883","build.rs":"cf78c0005f11d54ca42dbaee77cb76a440e6fa2e0b64798d3f74c04770a0ad2b","build/probe.rs":"971fd2178dc506ccdc5c2065c37b77696a4aee8e00330ca52625db4a857f68d3","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/extra.rs":"29f094473279a29b71c3cc9f5fa27c2e2c30c670390cf7e4b7cf451486cc857e","src/fallback.rs":"be1ce5e32c88c29d41d2ab663375951817d52decce3dc9e335ec22378be8fa65","src/lib.rs":"97ca48f50ad15fbcef42b31fb4fbfb8e4a1c5f946d776aa44fd04b37d7c64b32","src/location.rs":"9225c5a55f03b56cce42bc55ceb509e8216a5e0b24c94aa1cd071b04e3d6c15f","src/marker.rs":"c11c5a1be8bdf18be3fcd224393f350a9aae7ce282e19ce583c84910c6903a8f","src/parse.rs":"4b77cddbc2752bc4d38a65acd8b96b6786c5220d19b1e1b37810257b5d24132d","src/rcvec.rs":"1c3c48c4f819927cc445ae15ca3bb06775feff2fd1cb21901ae4c40c7e6b4e82","src/wrapper.rs":"e41df9abc846b40f0cf01150d22b91944d07cde93bc72aa34798101652675844","tests/comments.rs":"31115b3a56c83d93eef2fb4c9566bf4543e302560732986161b98aef504785ed","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"473e962ee1aa0633dd5cf9a973b3bbd0ef43b740d4b7f6d008ff455a6b89d386","tests/test.rs":"2e7106f582367d168638be7364d4e9aadbe0affca8b51dd80f0b3977cc2fcf83","tests/test_fmt.rs":"b7743b612af65f2c88cbe109d50a093db7aa7e87f9e37bf45b7bbaeb240aa020","tests/test_size.rs":"62d8373ea46b669b87bc90a9c49b6d02f90ff4c21f9a25acebf60c9926e01fb7"},"package":"5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"}pyo3/0000775000175000017500000000000014661133735012435 5ustar jamespagejamespagepyo3/guide/0000775000175000017500000000000014661133735013532 5ustar jamespagejamespagepyo3/guide/src/0000775000175000017500000000000014661133735014321 5ustar jamespagejamespagepyo3/guide/src/parallelism.md0000644000175000017500000001361514661133735017154 0ustar jamespagejamespage# Parallelism CPython has the infamous [Global Interpreter Lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock), which prevents several threads from executing Python bytecode in parallel. This makes threading in Python a bad fit for [CPU-bound](https://en.wikipedia.org/wiki/CPU-bound) tasks and often forces developers to accept the overhead of multiprocessing. In PyO3 parallelism can be easily achieved in Rust-only code. Let's take a look at our [word-count](https://github.com/PyO3/pyo3/blob/main/examples/word-count/src/lib.rs) example, where we have a `search` function that utilizes the [rayon](https://github.com/rayon-rs/rayon) crate to count words in parallel. ```rust,no_run # #![allow(dead_code)] use pyo3::prelude::*; // These traits let us use `par_lines` and `map`. use rayon::str::ParallelString; use rayon::iter::ParallelIterator; /// Count the occurrences of needle in line, case insensitive fn count_line(line: &str, needle: &str) -> usize { let mut total = 0; for word in line.split(' ') { if word == needle { total += 1; } } total } #[pyfunction] fn search(contents: &str, needle: &str) -> usize { contents .par_lines() .map(|line| count_line(line, needle)) .sum() } ``` But let's assume you have a long running Rust function which you would like to execute several times in parallel. For the sake of example let's take a sequential version of the word count: ```rust,no_run # #![allow(dead_code)] # fn count_line(line: &str, needle: &str) -> usize { # let mut total = 0; # for word in line.split(' ') { # if word == needle { # total += 1; # } # } # total # } # fn search_sequential(contents: &str, needle: &str) -> usize { contents.lines().map(|line| count_line(line, needle)).sum() } ``` To enable parallel execution of this function, the [`Python::allow_threads`] method can be used to temporarily release the GIL, thus allowing other Python threads to run. We then have a function exposed to the Python runtime which calls `search_sequential` inside a closure passed to [`Python::allow_threads`] to enable true parallelism: ```rust,no_run # #![allow(dead_code)] # use pyo3::prelude::*; # # fn count_line(line: &str, needle: &str) -> usize { # let mut total = 0; # for word in line.split(' ') { # if word == needle { # total += 1; # } # } # total # } # # fn search_sequential(contents: &str, needle: &str) -> usize { # contents.lines().map(|line| count_line(line, needle)).sum() # } #[pyfunction] fn search_sequential_allow_threads(py: Python<'_>, contents: &str, needle: &str) -> usize { py.allow_threads(|| search_sequential(contents, needle)) } ``` Now Python threads can use more than one CPU core, resolving the limitation which usually makes multi-threading in Python only good for IO-bound tasks: ```Python from concurrent.futures import ThreadPoolExecutor from word_count import search_sequential_allow_threads executor = ThreadPoolExecutor(max_workers=2) future_1 = executor.submit( word_count.search_sequential_allow_threads, contents, needle ) future_2 = executor.submit( word_count.search_sequential_allow_threads, contents, needle ) result_1 = future_1.result() result_2 = future_2.result() ``` ## Benchmark Let's benchmark the `word-count` example to verify that we really did unlock parallelism with PyO3. We are using `pytest-benchmark` to benchmark four word count functions: 1. Pure Python version 2. Rust parallel version 3. Rust sequential version 4. Rust sequential version executed twice with two Python threads The benchmark script can be found [here](https://github.com/PyO3/pyo3/blob/main/examples/word-count/tests/test_word_count.py), and we can run `nox` in the `word-count` folder to benchmark these functions. While the results of the benchmark of course depend on your machine, the relative results should be similar to this (mid 2020): ```text -------------------------------------------------------------------------------------------------- benchmark: 4 tests ------------------------------------------------------------------------------------------------- Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test_word_count_rust_parallel 1.7315 (1.0) 4.6495 (1.0) 1.9972 (1.0) 0.4299 (1.0) 1.8142 (1.0) 0.2049 (1.0) 40;46 500.6943 (1.0) 375 1 test_word_count_rust_sequential 7.3348 (4.24) 10.3556 (2.23) 8.0035 (4.01) 0.7785 (1.81) 7.5597 (4.17) 0.8641 (4.22) 26;5 124.9457 (0.25) 121 1 test_word_count_rust_sequential_twice_with_threads 7.9839 (4.61) 10.3065 (2.22) 8.4511 (4.23) 0.4709 (1.10) 8.2457 (4.55) 0.3927 (1.92) 17;17 118.3274 (0.24) 114 1 test_word_count_python_sequential 27.3985 (15.82) 45.4527 (9.78) 28.9604 (14.50) 4.1449 (9.64) 27.5781 (15.20) 0.4638 (2.26) 3;5 34.5299 (0.07) 35 1 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ``` You can see that the Python threaded version is not much slower than the Rust sequential version, which means compared to an execution on a single CPU core the speed has doubled. [`Python::allow_threads`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.allow_threads pyo3/guide/src/debugging.md0000644000175000017500000000534214661133735016600 0ustar jamespagejamespage# Debugging ## Macros PyO3's attributes (`#[pyclass]`, `#[pymodule]`, etc.) are [procedural macros](https://doc.rust-lang.org/reference/procedural-macros.html), which means that they rewrite the source of the annotated item. You can view the generated source with the following command, which also expands a few other things: ```bash cargo rustc --profile=check -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expanded.rs ``` (You might need to install [rustfmt](https://github.com/rust-lang-nursery/rustfmt) if you don't already have it.) You can also debug classic `!`-macros by adding `-Z trace-macros`: ```bash cargo rustc --profile=check -- -Z unstable-options --pretty=expanded -Z trace-macros > expanded.rs; rustfmt expanded.rs ``` Note that those commands require using the nightly build of rust and may occasionally have bugs. See [cargo expand](https://github.com/dtolnay/cargo-expand) for a more elaborate and stable version of those commands. ## Running with Valgrind Valgrind is a tool to detect memory management bugs such as memory leaks. You first need to install a debug build of Python, otherwise Valgrind won't produce usable results. In Ubuntu there's e.g. a `python3-dbg` package. Activate an environment with the debug interpreter and recompile. If you're on Linux, use `ldd` with the name of your binary and check that you're linking e.g. `libpython3.7d.so.1.0` instead of `libpython3.7.so.1.0`. [Download the suppressions file for CPython](https://raw.githubusercontent.com/python/cpython/master/Misc/valgrind-python.supp). Run Valgrind with `valgrind --suppressions=valgrind-python.supp ./my-command --with-options` ## Getting a stacktrace The best start to investigate a crash such as an segmentation fault is a backtrace. You can set `RUST_BACKTRACE=1` as an environment variable to get the stack trace on a `panic!`. Alternatively you can use a debugger such as `gdb` to explore the issue. Rust provides a wrapper, `rust-gdb`, which has pretty-printers for inspecting Rust variables. Since PyO3 uses `cdylib` for Python shared objects, it does not receive the pretty-print debug hooks in `rust-gdb` ([rust-lang/rust#96365](https://github.com/rust-lang/rust/issues/96365)). The mentioned issue contains a workaround for enabling pretty-printers in this case. * Link against a debug build of python as described in the previous chapter * Run `rust-gdb ` * Set a breakpoint (`b`) on `rust_panic` if you are investigating a `panic!` * Enter `r` to run * After the crash occurred, enter `bt` or `bt full` to print the stacktrace Often it is helpful to run a small piece of Python code to exercise a section of Rust. ```console rust-gdb --args python -c "import my_package; my_package.sum_to_string(1, 2)" ``` pyo3/guide/src/async-await.md0000644000175000017500000001074014661133735017063 0ustar jamespagejamespage# Using `async` and `await` *This feature is still in active development. See [the related issue](https://github.com/PyO3/pyo3/issues/1632).* `#[pyfunction]` and `#[pymethods]` attributes also support `async fn`. ```rust # #![allow(dead_code)] # #[cfg(feature = "experimental-async")] { use std::{thread, time::Duration}; use futures::channel::oneshot; use pyo3::prelude::*; #[pyfunction] #[pyo3(signature=(seconds, result=None))] async fn sleep(seconds: f64, result: Option) -> Option { let (tx, rx) = oneshot::channel(); thread::spawn(move || { thread::sleep(Duration::from_secs_f64(seconds)); tx.send(()).unwrap(); }); rx.await.unwrap(); result } # } ``` *Python awaitables instantiated with this method can only be awaited in *asyncio* context. Other Python async runtime may be supported in the future.* ## `Send + 'static` constraint Resulting future of an `async fn` decorated by `#[pyfunction]` must be `Send + 'static` to be embedded in a Python object. As a consequence, `async fn` parameters and return types must also be `Send + 'static`, so it is not possible to have a signature like `async fn does_not_compile<'py>(arg: Bound<'py, PyAny>) -> Bound<'py, PyAny>`. However, there is an exception for method receivers, so async methods can accept `&self`/`&mut self`. Note that this means that the class instance is borrowed for as long as the returned future is not completed, even across yield points and while waiting for I/O operations to complete. Hence, other methods cannot obtain exclusive borrows while the future is still being polled. This is the same as how async methods in Rust generally work but it is more problematic for Rust code interfacing with Python code due to pervasive shared mutability. This strongly suggests to prefer shared borrows `&self` over exclusive ones `&mut self` to avoid racy borrow check failures at runtime. ## Implicit GIL holding Even if it is not possible to pass a `py: Python<'py>` parameter to `async fn`, the GIL is still held during the execution of the future – it's also the case for regular `fn` without `Python<'py>`/`Bound<'py, PyAny>` parameter, yet the GIL is held. It is still possible to get a `Python` marker using [`Python::with_gil`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.with_gil); because `with_gil` is reentrant and optimized, the cost will be negligible. ## Release the GIL across `.await` There is currently no simple way to release the GIL when awaiting a future, *but solutions are currently in development*. Here is the advised workaround for now: ```rust,ignore use std::{ future::Future, pin::{Pin, pin}, task::{Context, Poll}, }; use pyo3::prelude::*; struct AllowThreads(F); impl Future for AllowThreads where F: Future + Unpin + Send, F::Output: Send, { type Output = F::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let waker = cx.waker(); Python::with_gil(|gil| { gil.allow_threads(|| pin!(&mut self.0).poll(&mut Context::from_waker(waker))) }) } } ``` ## Cancellation Cancellation on the Python side can be caught using [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) type, by annotating a function parameter with `#[pyo3(cancel_handle)]`. ```rust # #![allow(dead_code)] # #[cfg(feature = "experimental-async")] { use futures::FutureExt; use pyo3::prelude::*; use pyo3::coroutine::CancelHandle; #[pyfunction] async fn cancellable(#[pyo3(cancel_handle)] mut cancel: CancelHandle) { futures::select! { /* _ = ... => println!("done"), */ _ = cancel.cancelled().fuse() => println!("cancelled"), } } # } ``` ## The `Coroutine` type To make a Rust future awaitable in Python, PyO3 defines a [`Coroutine`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.Coroutine.html) type, which implements the Python [coroutine protocol](https://docs.python.org/3/library/collections.abc.html#collections.abc.Coroutine). Each `coroutine.send` call is translated to a `Future::poll` call. If a [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) parameter is declared, the exception passed to `coroutine.throw` call is stored in it and can be retrieved with [`CancelHandle::cancelled`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html#method.cancelled); otherwise, it cancels the Rust future, and the exception is reraised; *The type does not yet have a public constructor until the design is finalized.* pyo3/guide/src/changelog.md0000644000175000017500000000004014661133735016562 0ustar jamespagejamespage{{#include ../../CHANGELOG.md}} pyo3/guide/src/class.md0000644000175000017500000013733614661133735015763 0ustar jamespagejamespage# Python classes PyO3 exposes a group of attributes powered by Rust's proc macro system for defining Python classes as Rust structs. The main attribute is `#[pyclass]`, which is placed upon a Rust `struct` or `enum` to generate a Python type for it. They will usually also have *one* `#[pymethods]`-annotated `impl` block for the struct, which is used to define Python methods and constants for the generated Python type. (If the [`multiple-pymethods`] feature is enabled, each `#[pyclass]` is allowed to have multiple `#[pymethods]` blocks.) `#[pymethods]` may also have implementations for Python magic methods such as `__str__`. This chapter will discuss the functionality and configuration these attributes offer. Below is a list of links to the relevant section of this chapter for each: - [`#[pyclass]`](#defining-a-new-class) - [`#[pyo3(get, set)]`](#object-properties-using-pyo3get-set) - [`#[pymethods]`](#instance-methods) - [`#[new]`](#constructor) - [`#[getter]`](#object-properties-using-getter-and-setter) - [`#[setter]`](#object-properties-using-getter-and-setter) - [`#[staticmethod]`](#static-methods) - [`#[classmethod]`](#class-methods) - [`#[classattr]`](#class-attributes) - [`#[args]`](#method-arguments) - [Magic methods and slots](class/protocols.md) - [Classes as function arguments](#classes-as-function-arguments) ## Defining a new class To define a custom Python class, add the `#[pyclass]` attribute to a Rust struct or enum. ```rust # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass] struct MyClass { inner: i32, } // A "tuple" struct #[pyclass] struct Number(i32); // PyO3 supports unit-only enums (which contain only unit variants) // These simple enums behave similarly to Python's enumerations (enum.Enum) #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant = 30, // PyO3 supports custom discriminants. } // PyO3 supports custom discriminants in unit-only enums #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum HttpResponse { Ok = 200, NotFound = 404, Teapot = 418, // ... } // PyO3 also supports enums with Struct and Tuple variants // These complex enums have sligtly different behavior from the simple enums above // They are meant to work with instance checks and match statement patterns // The variants can be mixed and matched // Struct variants have named fields while tuple enums generate generic names for fields in order _0, _1, _2, ... // Apart from this both types are functionally identical #[pyclass] enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 }, RegularPolygon(u32, f64), Nothing(), } ``` The above example generates implementations for [`PyTypeInfo`] and [`PyClass`] for `MyClass`, `Number`, `MyEnum`, `HttpResponse`, and `Shape`. To see these generated implementations, refer to the [implementation details](#implementation-details) at the end of this chapter. ### Restrictions To integrate Rust types with Python, PyO3 needs to place some restrictions on the types which can be annotated with `#[pyclass]`. In particular, they must have no lifetime parameters, no generic parameters, and must implement `Send`. The reason for each of these is explained below. #### No lifetime parameters Rust lifetimes are used by the Rust compiler to reason about a program's memory safety. They are a compile-time only concept; there is no way to access Rust lifetimes at runtime from a dynamic language like Python. As soon as Rust data is exposed to Python, there is no guarantee that the Rust compiler can make on how long the data will live. Python is a reference-counted language and those references can be held for an arbitrarily long time which is untraceable by the Rust compiler. The only possible way to express this correctly is to require that any `#[pyclass]` does not borrow data for any lifetime shorter than the `'static` lifetime, i.e. the `#[pyclass]` cannot have any lifetime parameters. When you need to share ownership of data between Python and Rust, instead of using borrowed references with lifetimes consider using reference-counted smart pointers such as [`Arc`] or [`Py`]. #### No generic parameters A Rust `struct Foo` with a generic parameter `T` generates new compiled implementations each time it is used with a different concrete type for `T`. These new implementations are generated by the compiler at each usage site. This is incompatible with wrapping `Foo` in Python, where there needs to be a single compiled implementation of `Foo` which is integrated with the Python interpreter. Currently, the best alternative is to write a macro which expands to a new `#[pyclass]` for each instantiation you want: ```rust # #![allow(dead_code)] use pyo3::prelude::*; struct GenericClass { data: T, } macro_rules! create_interface { ($name: ident, $type: ident) => { #[pyclass] pub struct $name { inner: GenericClass<$type>, } #[pymethods] impl $name { #[new] pub fn new(data: $type) -> Self { Self { inner: GenericClass { data: data }, } } } }; } create_interface!(IntClass, i64); create_interface!(FloatClass, String); ``` #### Must be Send Because Python objects are freely shared between threads by the Python interpreter, there is no guarantee which thread will eventually drop the object. Therefore all types annotated with `#[pyclass]` must implement `Send` (unless annotated with [`#[pyclass(unsendable)]`](#customizing-the-class)). ## Constructor By default, it is not possible to create an instance of a custom class from Python code. To declare a constructor, you need to define a method and annotate it with the `#[new]` attribute. Only Python's `__new__` method can be specified, `__init__` is not available. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Number(value) } } ``` Alternatively, if your `new` method may fail you can return `PyResult`. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::exceptions::PyValueError; # #[pyclass] # struct Nonzero(i32); # #[pymethods] impl Nonzero { #[new] fn py_new(value: i32) -> PyResult { if value == 0 { Err(PyValueError::new_err("cannot be zero")) } else { Ok(Nonzero(value)) } } } ``` If you want to return an existing object (for example, because your `new` method caches the values it returns), `new` can return `pyo3::Py`. As you can see, the Rust method name is not important here; this way you can still, use `new()` for a Rust-level constructor. If no method marked with `#[new]` is declared, object instances can only be created from Rust, but not from Python. For arguments, see the [`Method arguments`](#method-arguments) section below. ## Adding the class to a module The next step is to create the module initializer and add our class to it: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # #[pyclass] # struct Number(i32); # #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } ``` ## Bound and interior mutability Often is useful to turn a `#[pyclass]` type `T` into a Python object and access it from Rust code. The [`Py`] and [`Bound<'py, T>`] smart pointers are the ways to represent a Python object in PyO3's API. More detail can be found about them [in the Python objects](./types.md#pyo3s-smart-pointers) section of the guide. Most Python objects do not offer exclusive (`&mut`) access (see the [section on Python's memory model](./python-from-rust.md#pythons-memory-model)). However, Rust structs wrapped as Python objects (called `pyclass` types) often *do* need `&mut` access. Due to the GIL, PyO3 *can* guarantee exclusive access to them. The Rust borrow checker cannot reason about `&mut` references once an object's ownership has been passed to the Python interpreter. This means that borrow checking is done at runtime using with a scheme very similar to `std::cell::RefCell`. This is known as [interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html). Users who are familiar with `RefCell` can use `Py` and `Bound<'py, T>` just like `RefCell`. For users who are not very familiar with `RefCell`, here is a reminder of Rust's rules of borrowing: - At any given time, you can have either (but not both of) one mutable reference or any number of immutable references. - References can never outlast the data they refer to. `Py` and `Bound<'py, T>`, like `RefCell`, ensure these borrowing rules by tracking references at runtime. ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { #[pyo3(get)] num: i32, } Python::with_gil(|py| { let obj = Bound::new(py, MyClass { num: 3 }).unwrap(); { let obj_ref = obj.borrow(); // Get PyRef assert_eq!(obj_ref.num, 3); // You cannot get PyRefMut unless all PyRefs are dropped assert!(obj.try_borrow_mut().is_err()); } { let mut obj_mut = obj.borrow_mut(); // Get PyRefMut obj_mut.num = 5; // You cannot get any other refs until the PyRefMut is dropped assert!(obj.try_borrow().is_err()); assert!(obj.try_borrow_mut().is_err()); } // You can convert `Bound` to a Python object pyo3::py_run!(py, obj, "assert obj.num == 5"); }); ``` A `Bound<'py, T>` is restricted to the GIL lifetime `'py`. To make the object longer lived (for example, to store it in a struct on the Rust side), use `Py`. `Py` needs a `Python<'_>` token to allow access: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { num: i32, } fn return_myclass() -> Py { Python::with_gil(|py| Py::new(py, MyClass { num: 1 }).unwrap()) } let obj = return_myclass(); Python::with_gil(move |py| { let bound = obj.bind(py); // Py::bind returns &Bound<'py, MyClass> let obj_ref = bound.borrow(); // Get PyRef assert_eq!(obj_ref.num, 1); }); ``` ### frozen classes: Opting out of interior mutability As detailed above, runtime borrow checking is currently enabled by default. But a class can opt of out it by declaring itself `frozen`. It can still use interior mutability via standard Rust types like `RefCell` or `Mutex`, but it is not bound to the implementation provided by PyO3 and can choose the most appropriate strategy on field-by-field basis. Classes which are `frozen` and also `Sync`, e.g. they do use `Mutex` but not `RefCell`, can be accessed without needing the Python GIL via the `Bound::get` and `Py::get` methods: ```rust use std::sync::atomic::{AtomicUsize, Ordering}; # use pyo3::prelude::*; #[pyclass(frozen)] struct FrozenCounter { value: AtomicUsize, } let py_counter: Py = Python::with_gil(|py| { let counter = FrozenCounter { value: AtomicUsize::new(0), }; Py::new(py, counter).unwrap() }); py_counter.get().value.fetch_add(1, Ordering::Relaxed); Python::with_gil(move |_py| drop(py_counter)); ``` Frozen classes are likely to become the default thereby guiding the PyO3 ecosystem towards a more deliberate application of interior mutability. Eventually, this should enable further optimizations of PyO3's internals and avoid downstream code paying the cost of interior mutability when it is not actually required. ## Customizing the class {{#include ../pyclass-parameters.md}} These parameters are covered in various sections of this guide. ### Return type Generally, `#[new]` methods have to return `T: Into>` or `PyResult where T: Into>`. For constructors that may fail, you should wrap the return type in a PyResult as well. Consult the table below to determine which type your constructor should return: | | **Cannot fail** | **May fail** | |-----------------------------|---------------------------|-----------------------------------| |**No inheritance** | `T` | `PyResult` | |**Inheritance(T Inherits U)**| `(T, U)` | `PyResult<(T, U)>` | |**Inheritance(General Case)**| [`PyClassInitializer`] | `PyResult>` | ## Inheritance By default, `object`, i.e. `PyAny` is used as the base class. To override this default, use the `extends` parameter for `pyclass` with the full path to the base class. Currently, only classes defined in Rust and builtins provided by PyO3 can be inherited from; inheriting from other classes defined in Python is not yet supported ([#991](https://github.com/PyO3/pyo3/issues/991)). For convenience, `(T, U)` implements `Into>` where `U` is the base class of `T`. But for a more deeply nested inheritance, you have to return `PyClassInitializer` explicitly. To get a parent class from a child, use [`PyRef`] instead of `&self` for methods, or [`PyRefMut`] instead of `&mut self`. Then you can access a parent class by `self_.as_super()` as `&PyRef`, or by `self_.into_super()` as `PyRef` (and similar for the `PyRefMut` case). For convenience, `self_.as_ref()` can also be used to get `&Self::BaseClass` directly; however, this approach does not let you access base clases higher in the inheritance hierarchy, for which you would need to chain multiple `as_super` or `into_super` calls. ```rust # use pyo3::prelude::*; #[pyclass(subclass)] struct BaseClass { val1: usize, } #[pymethods] impl BaseClass { #[new] fn new() -> Self { BaseClass { val1: 10 } } pub fn method1(&self) -> PyResult { Ok(self.val1) } } #[pyclass(extends=BaseClass, subclass)] struct SubClass { val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> (Self, BaseClass) { (SubClass { val2: 15 }, BaseClass::new()) } fn method2(self_: PyRef<'_, Self>) -> PyResult { let super_ = self_.as_super(); // Get &PyRef super_.method1().map(|x| x * self_.val2) } } #[pyclass(extends=SubClass)] struct SubSubClass { val3: usize, } #[pymethods] impl SubSubClass { #[new] fn new() -> PyClassInitializer { PyClassInitializer::from(SubClass::new()).add_subclass(SubSubClass { val3: 20 }) } fn method3(self_: PyRef<'_, Self>) -> PyResult { let base = self_.as_super().as_super(); // Get &PyRef<'_, BaseClass> base.method1().map(|x| x * self_.val3) } fn method4(self_: PyRef<'_, Self>) -> PyResult { let v = self_.val3; let super_ = self_.into_super(); // Get PyRef<'_, SubClass> SubClass::method2(super_).map(|x| x * v) } fn get_values(self_: PyRef<'_, Self>) -> (usize, usize, usize) { let val1 = self_.as_super().as_super().val1; let val2 = self_.as_super().val2; (val1, val2, self_.val3) } fn double_values(mut self_: PyRefMut<'_, Self>) { self_.as_super().as_super().val1 *= 2; self_.as_super().val2 *= 2; self_.val3 *= 2; } #[staticmethod] fn factory_method(py: Python<'_>, val: usize) -> PyResult { let base = PyClassInitializer::from(BaseClass::new()); let sub = base.add_subclass(SubClass { val2: val }); if val % 2 == 0 { Ok(Py::new(py, sub)?.to_object(py)) } else { let sub_sub = sub.add_subclass(SubSubClass { val3: val }); Ok(Py::new(py, sub_sub)?.to_object(py)) } } } # Python::with_gil(|py| { # let subsub = pyo3::Py::new(py, SubSubClass::new()).unwrap(); # pyo3::py_run!(py, subsub, "assert subsub.method1() == 10"); # pyo3::py_run!(py, subsub, "assert subsub.method2() == 150"); # pyo3::py_run!(py, subsub, "assert subsub.method3() == 200"); # pyo3::py_run!(py, subsub, "assert subsub.method4() == 3000"); # pyo3::py_run!(py, subsub, "assert subsub.get_values() == (10, 15, 20)"); # pyo3::py_run!(py, subsub, "assert subsub.double_values() == None"); # pyo3::py_run!(py, subsub, "assert subsub.get_values() == (20, 30, 40)"); # let subsub = SubSubClass::factory_method(py, 2).unwrap(); # let subsubsub = SubSubClass::factory_method(py, 3).unwrap(); # let cls = py.get_type_bound::(); # pyo3::py_run!(py, subsub cls, "assert not isinstance(subsub, cls)"); # pyo3::py_run!(py, subsubsub cls, "assert isinstance(subsubsub, cls)"); # }); ``` You can inherit native types such as `PyDict`, if they implement [`PySizedLayout`]({{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PySizedLayout.html). This is not supported when building for the Python limited API (aka the `abi3` feature of PyO3). To convert between the Rust type and its native base class, you can take `slf` as a Python object. To access the Rust fields use `slf.borrow()` or `slf.borrow_mut()`, and to access the base class use `slf.downcast::()`. ```rust # #[cfg(not(Py_LIMITED_API))] { # use pyo3::prelude::*; use pyo3::types::PyDict; use std::collections::HashMap; #[pyclass(extends=PyDict)] #[derive(Default)] struct DictWithCounter { counter: HashMap, } #[pymethods] impl DictWithCounter { #[new] fn new() -> Self { Self::default() } fn set(slf: &Bound<'_, Self>, key: String, value: Bound<'_, PyAny>) -> PyResult<()> { slf.borrow_mut().counter.entry(key.clone()).or_insert(0); let dict = slf.downcast::()?; dict.set_item(key, value) } } # Python::with_gil(|py| { # let cnt = pyo3::Py::new(py, DictWithCounter::new()).unwrap(); # pyo3::py_run!(py, cnt, "cnt.set('abc', 10); assert cnt['abc'] == 10") # }); # } ``` If `SubClass` does not provide a base class initialization, the compilation fails. ```rust,compile_fail # use pyo3::prelude::*; #[pyclass] struct BaseClass { val1: usize, } #[pyclass(extends=BaseClass)] struct SubClass { val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> Self { SubClass { val2: 15 } } } ``` The `__new__` constructor of a native base class is called implicitly when creating a new instance from Python. Be sure to accept arguments in the `#[new]` method that you want the base class to get, even if they are not used in that `fn`: ```rust # #[allow(dead_code)] # #[cfg(not(Py_LIMITED_API))] { # use pyo3::prelude::*; use pyo3::types::PyDict; #[pyclass(extends=PyDict)] struct MyDict { private: i32, } #[pymethods] impl MyDict { #[new] #[pyo3(signature = (*args, **kwargs))] fn new(args: &Bound<'_, PyAny>, kwargs: Option<&Bound<'_, PyAny>>) -> Self { Self { private: 0 } } // some custom methods that use `private` here... } # Python::with_gil(|py| { # let cls = py.get_type_bound::(); # pyo3::py_run!(py, cls, "cls(a=1, b=2)") # }); # } ``` Here, the `args` and `kwargs` allow creating instances of the subclass passing initial items, such as `MyDict(item_sequence)` or `MyDict(a=1, b=2)`. ## Object properties PyO3 supports two ways to add properties to your `#[pyclass]`: - For simple struct fields with no side effects, a `#[pyo3(get, set)]` attribute can be added directly to the field definition in the `#[pyclass]`. - For properties which require computation you can define `#[getter]` and `#[setter]` functions in the [`#[pymethods]`](#instance-methods) block. We'll cover each of these in the following sections. ### Object properties using `#[pyo3(get, set)]` For simple cases where a member variable is just read and written with no side effects, you can declare getters and setters in your `#[pyclass]` field definition using the `pyo3` attribute, like in the example below: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { #[pyo3(get, set)] num: i32, } ``` The above would make the `num` field available for reading and writing as a `self.num` Python property. To expose the property with a different name to the field, specify this alongside the rest of the options, e.g. `#[pyo3(get, set, name = "custom_name")]`. Properties can be readonly or writeonly by using just `#[pyo3(get)]` or `#[pyo3(set)]` respectively. To use these annotations, your field type must implement some conversion traits: - For `get` the field type must implement both `IntoPy` and `Clone`. - For `set` the field type must implement `FromPyObject`. For example, implementations of those traits are provided for the `Cell` type, if the inner type also implements the trait. This means you can use `#[pyo3(get, set)]` on fields wrapped in a `Cell`. ### Object properties using `#[getter]` and `#[setter]` For cases which don't satisfy the `#[pyo3(get, set)]` trait requirements, or need side effects, descriptor methods can be defined in a `#[pymethods]` `impl` block. This is done using the `#[getter]` and `#[setter]` attributes, like in the example below: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass { num: i32, } #[pymethods] impl MyClass { #[getter] fn num(&self) -> PyResult { Ok(self.num) } } ``` A getter or setter's function name is used as the property name by default. There are several ways how to override the name. If a function name starts with `get_` or `set_` for getter or setter respectively, the descriptor name becomes the function name with this prefix removed. This is also useful in case of Rust keywords like `type` ([raw identifiers](https://doc.rust-lang.org/edition-guide/rust-2018/module-system/raw-identifiers.html) can be used since Rust 2018). ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[getter] fn get_num(&self) -> PyResult { Ok(self.num) } #[setter] fn set_num(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` In this case, a property `num` is defined and available from Python code as `self.num`. Both the `#[getter]` and `#[setter]` attributes accept one parameter. If this parameter is specified, it is used as the property name, i.e. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[getter(number)] fn num(&self) -> PyResult { Ok(self.num) } #[setter(number)] fn set_num(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` In this case, the property `number` is defined and available from Python code as `self.number`. Attributes defined by `#[setter]` or `#[pyo3(set)]` will always raise `AttributeError` on `del` operations. Support for defining custom `del` behavior is tracked in [#1778](https://github.com/PyO3/pyo3/issues/1778). ## Instance methods To define a Python compatible method, an `impl` block for your struct has to be annotated with the `#[pymethods]` attribute. PyO3 generates Python compatible wrappers for all functions in this block with some variations, like descriptors, class method static methods, etc. Since Rust allows any number of `impl` blocks, you can easily split methods between those accessible to Python (and Rust) and those accessible only to Rust. However to have multiple `#[pymethods]`-annotated `impl` blocks for the same struct you must enable the [`multiple-pymethods`] feature of PyO3. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { fn method1(&self) -> PyResult { Ok(10) } fn set_method(&mut self, value: i32) -> PyResult<()> { self.num = value; Ok(()) } } ``` Calls to these methods are protected by the GIL, so both `&self` and `&mut self` can be used. The return type must be `PyResult` or `T` for some `T` that implements `IntoPy`; the latter is allowed if the method cannot raise Python exceptions. A `Python` parameter can be specified as part of method signature, in this case the `py` argument gets injected by the method wrapper, e.g. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { fn method2(&self, py: Python<'_>) -> PyResult { Ok(10) } } ``` From the Python perspective, the `method2` in this example does not accept any arguments. ## Class methods To create a class method for a custom class, the method needs to be annotated with the `#[classmethod]` attribute. This is the equivalent of the Python decorator `@classmethod`. ```rust # use pyo3::prelude::*; # use pyo3::types::PyType; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { #[classmethod] fn cls_method(cls: &Bound<'_, PyType>) -> PyResult { Ok(10) } } ``` Declares a class method callable from Python. * The first parameter is the type object of the class on which the method is called. This may be the type object of a derived class. * The first parameter implicitly has type `&Bound<'_, PyType>`. * For details on `parameter-list`, see the documentation of `Method arguments` section. * The return type must be `PyResult` or `T` for some `T` that implements `IntoPy`. ### Constructors which accept a class argument To create a constructor which takes a positional class argument, you can combine the `#[classmethod]` and `#[new]` modifiers: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyType; # #[pyclass] # struct BaseClass(PyObject); # #[pymethods] impl BaseClass { #[new] #[classmethod] fn py_new(cls: &Bound<'_, PyType>) -> PyResult { // Get an abstract attribute (presumably) declared on a subclass of this class. let subclass_attr: Bound<'_, PyAny> = cls.getattr("a_class_attr")?; Ok(Self(subclass_attr.unbind())) } } ``` ## Static methods To create a static method for a custom class, the method needs to be annotated with the `#[staticmethod]` attribute. The return type must be `T` or `PyResult` for some `T` that implements `IntoPy`. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass { # #[allow(dead_code)] # num: i32, # } #[pymethods] impl MyClass { #[staticmethod] fn static_method(param1: i32, param2: &str) -> PyResult { Ok(10) } } ``` ## Class attributes To create a class attribute (also called [class variable][classattr]), a method without any arguments can be annotated with the `#[classattr]` attribute. ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} #[pymethods] impl MyClass { #[classattr] fn my_attribute() -> String { "hello".to_string() } } Python::with_gil(|py| { let my_class = py.get_type_bound::(); pyo3::py_run!(py, my_class, "assert my_class.my_attribute == 'hello'") }); ``` > Note: if the method has a `Result` return type and returns an `Err`, PyO3 will panic during class creation. If the class attribute is defined with `const` code only, one can also annotate associated constants: ```rust # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} #[pymethods] impl MyClass { #[classattr] const MY_CONST_ATTRIBUTE: &'static str = "foobar"; } ``` ## Classes as function arguments Free functions defined using `#[pyfunction]` interact with classes through the same mechanisms as the self parameters of instance methods, i.e. they can take GIL-bound references, GIL-bound reference wrappers or GIL-indepedent references: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] struct MyClass { my_field: i32, } // Take a reference when the underlying `Bound` is irrelevant. #[pyfunction] fn increment_field(my_class: &mut MyClass) { my_class.my_field += 1; } // Take a reference wrapper when borrowing should be automatic, // but interaction with the underlying `Bound` is desired. #[pyfunction] fn print_field(my_class: PyRef<'_, MyClass>) { println!("{}", my_class.my_field); } // Take a reference to the underlying Bound // when borrowing needs to be managed manually. #[pyfunction] fn increment_then_print_field(my_class: &Bound<'_, MyClass>) { my_class.borrow_mut().my_field += 1; println!("{}", my_class.borrow().my_field); } // Take a GIL-indepedent reference when you want to store the reference elsewhere. #[pyfunction] fn print_refcnt(my_class: Py, py: Python<'_>) { println!("{}", my_class.get_refcnt(py)); } ``` Classes can also be passed by value if they can be cloned, i.e. they automatically implement `FromPyObject` if they implement `Clone`, e.g. via `#[derive(Clone)]`: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] #[derive(Clone)] struct MyClass { my_field: Box, } #[pyfunction] fn dissamble_clone(my_class: MyClass) { let MyClass { mut my_field } = my_class; *my_field += 1; } ``` Note that `#[derive(FromPyObject)]` on a class is usually not useful as it tries to construct a new Rust value by filling in the fields by looking up attributes of any given Python value. ## Method arguments Similar to `#[pyfunction]`, the `#[pyo3(signature = (...))]` attribute can be used to specify the way that `#[pymethods]` accept arguments. Consult the documentation for [`function signatures`](./function/signature.md) to see the parameters this attribute accepts. The following example defines a class `MyClass` with a method `method`. This method has a signature that sets default values for `num` and `name`, and indicates that `py_args` should collect all extra positional arguments and `py_kwargs` all extra keyword arguments: ```rust # use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; # # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[new] #[pyo3(signature = (num=-1))] fn new(num: i32) -> Self { MyClass { num } } #[pyo3(signature = (num=10, *py_args, name="Hello", **py_kwargs))] fn method( &mut self, num: i32, py_args: &Bound<'_, PyTuple>, name: &str, py_kwargs: Option<&Bound<'_, PyDict>>, ) -> String { let num_before = self.num; self.num = num; format!( "num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} ", num, num_before, py_args, name, py_kwargs, ) } } ``` In Python, this might be used like: ```python >>> import mymodule >>> mc = mymodule.MyClass() >>> print(mc.method(44, False, "World", 666, x=44, y=55)) py_args=('World', 666), py_kwargs=Some({'x': 44, 'y': 55}), name=Hello, num=44, num_before=-1 >>> print(mc.method(num=-1, name="World")) py_args=(), py_kwargs=None, name=World, num=-1, num_before=44 ``` The [`#[pyo3(text_signature = "...")`](./function/signature.md#overriding-the-generated-signature) option for `#[pyfunction]` also works for `#[pymethods]`. ```rust # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyType; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(text_signature = "(c, d)")] fn new(c: i32, d: &str) -> Self { Self {} } // the self argument should be written $self #[pyo3(text_signature = "($self, e, f)")] fn my_method(&self, e: i32, f: i32) -> i32 { e + f } // similarly for classmethod arguments, use $cls #[classmethod] #[pyo3(text_signature = "($cls, e, f)")] fn my_class_method(cls: &Bound<'_, PyType>, e: i32, f: i32) -> i32 { e + f } #[staticmethod] #[pyo3(text_signature = "(e, f)")] fn my_static_method(e: i32, f: i32) -> i32 { e + f } } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let inspect = PyModule::import_bound(py, "inspect")?.getattr("signature")?; # let module = PyModule::new_bound(py, "my_module")?; # module.add_class::()?; # let class = module.getattr("MyClass")?; # # if cfg!(not(Py_LIMITED_API)) || py.version_info() >= (3, 10) { # let doc: String = class.getattr("__doc__")?.extract()?; # assert_eq!(doc, ""); # # let sig: String = inspect # .call1((&class,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(c, d)"); # } else { # let doc: String = class.getattr("__doc__")?.extract()?; # assert_eq!(doc, ""); # # inspect.call1((&class,)).expect_err("`text_signature` on classes is not compatible with compilation in `abi3` mode until Python 3.10 or greater"); # } # # { # let method = class.getattr("my_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(self, /, e, f)"); # } # # { # let method = class.getattr("my_class_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(e, f)"); // inspect.signature skips the $cls arg # } # # { # let method = class.getattr("my_static_method")?; # # assert!(method.getattr("__doc__")?.is_none()); # # let sig: String = inspect # .call1((method,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(e, f)"); # } # # Ok(()) # }) # } ``` Note that `text_signature` on `#[new]` is not compatible with compilation in `abi3` mode until Python 3.10 or greater. ### Method receivers and lifetime elision PyO3 supports writing instance methods using the normal method receivers for shared `&self` and unique `&mut self` references. This interacts with [lifetime elision][lifetime-elision] insofar as the lifetime of a such a receiver is assigned to all elided output lifetime parameters. This is a good default for general Rust code where return values are more likely to borrow from the receiver than from the other arguments, if they contain any lifetimes at all. However, when returning bound references `Bound<'py, T>` in PyO3-based code, the GIL lifetime `'py` should usually be derived from a GIL token `py: Python<'py>` passed as an argument instead of the receiver. Specifically, signatures like ```rust,ignore fn frobnicate(&self, py: Python) -> Bound; ``` will not work as they are inferred as ```rust,ignore fn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'a, Foo>; ``` instead of the intended ```rust,ignore fn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'py, Foo>; ``` and should usually be written as ```rust,ignore fn frobnicate<'py>(&self, py: Python<'py>) -> Bound<'py, Foo>; ``` The same problem does not exist for `#[pyfunction]`s as the special case for receiver lifetimes does not apply and indeed a signature like ```rust,ignore fn frobnicate(bar: &Bar, py: Python) -> Bound; ``` will yield compiler error [E0106 "missing lifetime specifier"][compiler-error-e0106]. ## `#[pyclass]` enums Enum support in PyO3 comes in two flavors, depending on what kind of variants the enum has: simple and complex. ### Simple enums A simple enum (a.k.a. C-like enum) has only unit variants. PyO3 adds a class attribute for each variant, so you can access them in Python without defining `#[new]`. PyO3 also provides default implementations of `__richcmp__` and `__int__`, so they can be compared using `==`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant, } Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let y = Py::new(py, MyEnum::OtherVariant).unwrap(); let cls = py.get_type_bound::(); pyo3::py_run!(py, x y cls, r#" assert x == cls.Variant assert y == cls.OtherVariant assert x != y "#) }) ``` You can also convert your simple enums into `int`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Variant, OtherVariant = 10, } Python::with_gil(|py| { let cls = py.get_type_bound::(); let x = MyEnum::Variant as i32; // The exact value is assigned by the compiler. pyo3::py_run!(py, cls x, r#" assert int(cls.Variant) == x assert int(cls.OtherVariant) == 10 "#) }) ``` PyO3 also provides `__repr__` for enums: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum{ Variant, OtherVariant, } Python::with_gil(|py| { let cls = py.get_type_bound::(); let x = Py::new(py, MyEnum::Variant).unwrap(); pyo3::py_run!(py, cls x, r#" assert repr(x) == 'MyEnum.Variant' assert repr(cls.OtherVariant) == 'MyEnum.OtherVariant' "#) }) ``` All methods defined by PyO3 can be overridden. For example here's how you override `__repr__`: ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum MyEnum { Answer = 42, } #[pymethods] impl MyEnum { fn __repr__(&self) -> &'static str { "42" } } Python::with_gil(|py| { let cls = py.get_type_bound::(); pyo3::py_run!(py, cls, "assert repr(cls.Answer) == '42'") }) ``` Enums and their variants can also be renamed using `#[pyo3(name)]`. ```rust # use pyo3::prelude::*; #[pyclass(eq, eq_int, name = "RenamedEnum")] #[derive(PartialEq)] enum MyEnum { #[pyo3(name = "UPPERCASE")] Variant, } Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant).unwrap(); let cls = py.get_type_bound::(); pyo3::py_run!(py, x cls, r#" assert repr(x) == 'RenamedEnum.UPPERCASE' assert x == cls.UPPERCASE "#) }) ``` Ordering of enum variants is optionally added using `#[pyo3(ord)]`. *Note: Implementation of the `PartialOrd` trait is required when passing the `ord` argument. If not implemented, a compile time error is raised.* ```rust # use pyo3::prelude::*; #[pyclass(eq, ord)] #[derive(PartialEq, PartialOrd)] enum MyEnum{ A, B, C, } Python::with_gil(|py| { let cls = py.get_type_bound::(); let a = Py::new(py, MyEnum::A).unwrap(); let b = Py::new(py, MyEnum::B).unwrap(); let c = Py::new(py, MyEnum::C).unwrap(); pyo3::py_run!(py, cls a b c, r#" assert (a < b) == True assert (c <= b) == False assert (c > a) == True "#) }) ``` You may not use enums as a base class or let enums inherit from other classes. ```rust,compile_fail # use pyo3::prelude::*; #[pyclass(subclass)] enum BadBase { Var1, } ``` ```rust,compile_fail # use pyo3::prelude::*; #[pyclass(subclass)] struct Base; #[pyclass(extends=Base)] enum BadSubclass { Var1, } ``` `#[pyclass]` enums are currently not interoperable with `IntEnum` in Python. ### Complex enums An enum is complex if it has any non-unit (struct or tuple) variants. PyO3 supports only struct and tuple variants in a complex enum. Unit variants aren't supported at present (the recommendation is to use an empty tuple enum instead). PyO3 adds a class attribute for each variant, which may be used to construct values and in match patterns. PyO3 also provides getter methods for all fields of each variant. ```rust # use pyo3::prelude::*; #[pyclass] enum Shape { Circle { radius: f64 }, Rectangle { width: f64, height: f64 }, RegularPolygon(u32, f64), Nothing { }, } # #[cfg(Py_3_10)] Python::with_gil(|py| { let circle = Shape::Circle { radius: 10.0 }.into_py(py); let square = Shape::RegularPolygon(4, 10.0).into_py(py); let cls = py.get_type_bound::(); pyo3::py_run!(py, circle square cls, r#" assert isinstance(circle, cls) assert isinstance(circle, cls.Circle) assert circle.radius == 10.0 assert isinstance(square, cls) assert isinstance(square, cls.RegularPolygon) assert square[0] == 4 # Gets _0 field assert square[1] == 10.0 # Gets _1 field def count_vertices(cls, shape): match shape: case cls.Circle(): return 0 case cls.Rectangle(): return 4 case cls.RegularPolygon(n): return n case cls.Nothing(): return 0 assert count_vertices(cls, circle) == 0 assert count_vertices(cls, square) == 4 "#) }) ``` WARNING: `Py::new` and `.into_py` are currently inconsistent. Note how the constructed value is _not_ an instance of the specific variant. For this reason, constructing values is only recommended using `.into_py`. ```rust # use pyo3::prelude::*; #[pyclass] enum MyEnum { Variant { i: i32 }, } Python::with_gil(|py| { let x = Py::new(py, MyEnum::Variant { i: 42 }).unwrap(); let cls = py.get_type_bound::(); pyo3::py_run!(py, x cls, r#" assert isinstance(x, cls) assert not isinstance(x, cls.Variant) "#) }) ``` The constructor of each generated class can be customized using the `#[pyo3(constructor = (...))]` attribute. This uses the same syntax as the [`#[pyo3(signature = (...))]`](function/signature.md) attribute on function and methods and supports the same options. To apply this attribute simply place it on top of a variant in a `#[pyclass]` complex enum as shown below: ```rust # use pyo3::prelude::*; #[pyclass] enum Shape { #[pyo3(constructor = (radius=1.0))] Circle { radius: f64 }, #[pyo3(constructor = (*, width, height))] Rectangle { width: f64, height: f64 }, #[pyo3(constructor = (side_count, radius=1.0))] RegularPolygon { side_count: u32, radius: f64 }, Nothing { }, } # #[cfg(Py_3_10)] Python::with_gil(|py| { let cls = py.get_type_bound::(); pyo3::py_run!(py, cls, r#" circle = cls.Circle() assert isinstance(circle, cls) assert isinstance(circle, cls.Circle) assert circle.radius == 1.0 square = cls.Rectangle(width = 1, height = 1) assert isinstance(square, cls) assert isinstance(square, cls.Rectangle) assert square.width == 1 assert square.height == 1 hexagon = cls.RegularPolygon(6) assert isinstance(hexagon, cls) assert isinstance(hexagon, cls.RegularPolygon) assert hexagon.side_count == 6 assert hexagon.radius == 1 "#) }) ``` ## Implementation details The `#[pyclass]` macros rely on a lot of conditional code generation: each `#[pyclass]` can optionally have a `#[pymethods]` block. To support this flexibility the `#[pyclass]` macro expands to a blob of boilerplate code which sets up the structure for ["dtolnay specialization"](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md). This implementation pattern enables the Rust compiler to use `#[pymethods]` implementations when they are present, and fall back to default (empty) definitions when they are not. This simple technique works for the case when there is zero or one implementations. To support multiple `#[pymethods]` for a `#[pyclass]` (in the [`multiple-pymethods`] feature), a registry mechanism provided by the [`inventory`](https://github.com/dtolnay/inventory) crate is used instead. This collects `impl`s at library load time, but isn't supported on all platforms. See [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) for more details. The `#[pyclass]` macro expands to roughly the code seen below. The `PyClassImplCollector` is the type used internally by PyO3 for dtolnay specialization: ```rust # #[cfg(not(feature = "multiple-pymethods"))] { # use pyo3::prelude::*; // Note: the implementation differs slightly with the `multiple-pymethods` feature enabled. struct MyClass { # #[allow(dead_code)] num: i32, } impl pyo3::types::DerefToPyAny for MyClass {} # #[allow(deprecated)] # #[cfg(feature = "gil-refs")] unsafe impl pyo3::type_object::HasPyGilRef for MyClass { type AsRefTarget = pyo3::PyCell; } unsafe impl pyo3::type_object::PyTypeInfo for MyClass { const NAME: &'static str = "MyClass"; const MODULE: ::std::option::Option<&'static str> = ::std::option::Option::None; #[inline] fn type_object_raw(py: pyo3::Python<'_>) -> *mut pyo3::ffi::PyTypeObject { ::lazy_type_object() .get_or_init(py) .as_type_ptr() } } impl pyo3::PyClass for MyClass { type Frozen = pyo3::pyclass::boolean_struct::False; } impl<'a, 'py> pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a MyClass { type Holder = ::std::option::Option>; #[inline] fn extract(obj: &'a pyo3::Bound<'py, PyAny>, holder: &'a mut Self::Holder) -> pyo3::PyResult { pyo3::impl_::extract_argument::extract_pyclass_ref(obj, holder) } } impl<'a, 'py> pyo3::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a mut MyClass { type Holder = ::std::option::Option>; #[inline] fn extract(obj: &'a pyo3::Bound<'py, PyAny>, holder: &'a mut Self::Holder) -> pyo3::PyResult { pyo3::impl_::extract_argument::extract_pyclass_ref_mut(obj, holder) } } impl pyo3::IntoPy for MyClass { fn into_py(self, py: pyo3::Python<'_>) -> pyo3::PyObject { pyo3::IntoPy::into_py(pyo3::Py::new(py, self).unwrap(), py) } } impl pyo3::impl_::pyclass::PyClassImpl for MyClass { const IS_BASETYPE: bool = false; const IS_SUBCLASS: bool = false; const IS_MAPPING: bool = false; const IS_SEQUENCE: bool = false; type BaseType = PyAny; type ThreadChecker = pyo3::impl_::pyclass::SendablePyClass; type PyClassMutability = <::PyClassMutability as pyo3::impl_::pycell::PyClassMutability>::MutableChild; type Dict = pyo3::impl_::pyclass::PyClassDummySlot; type WeakRef = pyo3::impl_::pyclass::PyClassDummySlot; type BaseNativeType = pyo3::PyAny; fn items_iter() -> pyo3::impl_::pyclass::PyClassItemsIter { use pyo3::impl_::pyclass::*; let collector = PyClassImplCollector::::new(); static INTRINSIC_ITEMS: PyClassItems = PyClassItems { slots: &[], methods: &[] }; PyClassItemsIter::new(&INTRINSIC_ITEMS, collector.py_methods()) } fn lazy_type_object() -> &'static pyo3::impl_::pyclass::LazyTypeObject { use pyo3::impl_::pyclass::LazyTypeObject; static TYPE_OBJECT: LazyTypeObject = LazyTypeObject::new(); &TYPE_OBJECT } fn doc(py: Python<'_>) -> pyo3::PyResult<&'static ::std::ffi::CStr> { use pyo3::impl_::pyclass::*; static DOC: pyo3::sync::GILOnceCell<::std::borrow::Cow<'static, ::std::ffi::CStr>> = pyo3::sync::GILOnceCell::new(); DOC.get_or_try_init(py, || { let collector = PyClassImplCollector::::new(); build_pyclass_doc(::NAME, pyo3::ffi::c_str!(""), collector.new_text_signature()) }).map(::std::ops::Deref::deref) } } # Python::with_gil(|py| { # let cls = py.get_type_bound::(); # pyo3::py_run!(py, cls, "assert cls.__name__ == 'MyClass'") # }); # } ``` [`PyTypeInfo`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeInfo.html [`Py`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html [`Bound<'_, T>`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html [`PyClass`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/trait.PyClass.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html [`PyClassInitializer`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass_init/struct.PyClassInitializer.html [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html [classattr]: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables [`multiple-pymethods`]: features.md#multiple-pymethods [lifetime-elision]: https://doc.rust-lang.org/reference/lifetime-elision.html [compiler-error-e0106]: https://doc.rust-lang.org/error_codes/E0106.html pyo3/guide/src/ecosystem.md0000644000175000017500000000060314661133735016653 0ustar jamespagejamespage# The PyO3 ecosystem This portion of the guide is dedicated to crates which are external to the main PyO3 project and provide additional functionality you might find useful. Because these projects evolve independently of the PyO3 repository the content of these articles may fall out of date over time; please file issues on the PyO3 GitHub to alert maintainers when this is the case. pyo3/guide/src/rust-from-python.md0000644000175000017500000000110114661133735020107 0ustar jamespagejamespage# Using Rust from Python This chapter of the guide is dedicated to explaining how to wrap Rust code into Python objects. PyO3 uses Rust's "procedural macros" to provide a powerful yet simple API to denote what Rust code should map into Python objects. The three types of Python objects which PyO3 can produce are: - Python modules, via the `#[pymodule]` macro - Python functions, via the `#[pyfunction]` macro - Python classes, via the `#[pyclass]` macro (plus `#[pymethods]` to define methods for those clases) The following subchapters go through each of these in turn. pyo3/guide/src/building-and-distribution.md0000644000175000017500000006600614661133735021723 0ustar jamespagejamespage# Building and distribution This chapter of the guide goes into detail on how to build and distribute projects using PyO3. The way to achieve this is very different depending on whether the project is a Python module implemented in Rust, or a Rust binary embedding Python. For both types of project there are also common problems such as the Python version to build for and the [linker](https://en.wikipedia.org/wiki/Linker_(computing)) arguments to use. The material in this chapter is intended for users who have already read the PyO3 [README](./index.md). It covers in turn the choices that can be made for Python modules and for Rust binaries. There is also a section at the end about cross-compiling projects using PyO3. There is an additional sub-chapter dedicated to [supporting multiple Python versions](./building-and-distribution/multiple-python-versions.md). ## Configuring the Python version PyO3 uses a build script (backed by the [`pyo3-build-config`] crate) to determine the Python version and set the correct linker arguments. By default it will attempt to use the following in order: - Any active Python virtualenv. - The `python` executable (if it's a Python 3 interpreter). - The `python3` executable. You can override the Python interpreter by setting the `PYO3_PYTHON` environment variable, e.g. `PYO3_PYTHON=python3.7`, `PYO3_PYTHON=/usr/bin/python3.9`, or even a PyPy interpreter `PYO3_PYTHON=pypy3`. Once the Python interpreter is located, `pyo3-build-config` executes it to query the information in the `sysconfig` module which is needed to configure the rest of the compilation. To validate the configuration which PyO3 will use, you can run a compilation with the environment variable `PYO3_PRINT_CONFIG=1` set. An example output of doing this is shown below: ```console $ PYO3_PRINT_CONFIG=1 cargo build Compiling pyo3 v0.14.1 (/home/david/dev/pyo3) error: failed to run custom build command for `pyo3 v0.14.1 (/home/david/dev/pyo3)` Caused by: process didn't exit successfully: `/home/david/dev/pyo3/target/debug/build/pyo3-7a8cf4fe22e959b7/build-script-build` (exit status: 101) --- stdout cargo:rerun-if-env-changed=PYO3_CROSS cargo:rerun-if-env-changed=PYO3_CROSS_LIB_DIR cargo:rerun-if-env-changed=PYO3_CROSS_PYTHON_VERSION cargo:rerun-if-env-changed=PYO3_PRINT_CONFIG -- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile -- implementation=CPython version=3.8 shared=true abi3=false lib_name=python3.8 lib_dir=/usr/lib executable=/usr/bin/python pointer_width=64 build_flags= suppress_build_script_link_lines=false ``` The `PYO3_ENVIRONMENT_SIGNATURE` environment variable can be used to trigger rebuilds when its value changes, it has no other effect. ### Advanced: config files If you save the above output config from `PYO3_PRINT_CONFIG` to a file, it is possible to manually override the contents and feed it back into PyO3 using the `PYO3_CONFIG_FILE` env var. If your build environment is unusual enough that PyO3's regular configuration detection doesn't work, using a config file like this will give you the flexibility to make PyO3 work for you. To see the full set of options supported, see the documentation for the [`InterpreterConfig` struct](https://docs.rs/pyo3-build-config/{{#PYO3_DOCS_VERSION}}/pyo3_build_config/struct.InterpreterConfig.html). ## Building Python extension modules Python extension modules need to be compiled differently depending on the OS (and architecture) that they are being compiled for. As well as multiple OSes (and architectures), there are also many different Python versions which are actively supported. Packages uploaded to [PyPI](https://pypi.org/) usually want to upload prebuilt "wheels" covering many OS/arch/version combinations so that users on all these different platforms don't have to compile the package themselves. Package vendors can opt-in to the "abi3" limited Python API which allows their wheels to be used on multiple Python versions, reducing the number of wheels they need to compile, but restricts the functionality they can use. There are many ways to go about this: it is possible to use `cargo` to build the extension module (along with some manual work, which varies with OS). The PyO3 ecosystem has two packaging tools, [`maturin`] and [`setuptools-rust`], which abstract over the OS difference and also support building wheels for PyPI upload. PyO3 has some Cargo features to configure projects for building Python extension modules: - The `extension-module` feature, which must be enabled when building Python extension modules. - The `abi3` feature and its version-specific `abi3-pyXY` companions, which are used to opt-in to the limited Python API in order to support multiple Python versions in a single wheel. This section describes each of these packaging tools before describing how to build manually without them. It then proceeds with an explanation of the `extension-module` feature. Finally, there is a section describing PyO3's `abi3` features. ### Packaging tools The PyO3 ecosystem has two main choices to abstract the process of developing Python extension modules: - [`maturin`] is a command-line tool to build, package and upload Python modules. It makes opinionated choices about project layout meaning it needs very little configuration. This makes it a great choice for users who are building a Python extension from scratch and don't need flexibility. - [`setuptools-rust`] is an add-on for `setuptools` which adds extra keyword arguments to the `setup.py` configuration file. It requires more configuration than `maturin`, however this gives additional flexibility for users adding Rust to an existing Python package that can't satisfy `maturin`'s constraints. Consult each project's documentation for full details on how to get started using them and how to upload wheels to PyPI. It should be noted that while `maturin` is able to build [manylinux](https://github.com/pypa/manylinux)-compliant wheels out-of-the-box, `setuptools-rust` requires a bit more effort, [relying on Docker](https://setuptools-rust.readthedocs.io/en/latest/building_wheels.html) for this purpose. There are also [`maturin-starter`] and [`setuptools-rust-starter`] examples in the PyO3 repository. ### Manual builds To build a PyO3-based Python extension manually, start by running `cargo build` as normal in a library project which uses PyO3's `extension-module` feature and has the [`cdylib` crate type](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field). Once built, symlink (or copy) and rename the shared library from Cargo's `target/` directory to your desired output directory: - on macOS, rename `libyour_module.dylib` to `your_module.so`. - on Windows, rename `libyour_module.dll` to `your_module.pyd`. - on Linux, rename `libyour_module.so` to `your_module.so`. You can then open a Python shell in the output directory and you'll be able to run `import your_module`. If you're packaging your library for redistribution, you should indicated the Python interpreter your library is compiled for by including the [platform tag](#platform-tags) in its name. This prevents incompatible interpreters from trying to import your library. If you're compiling for PyPy you *must* include the platform tag, or PyPy will ignore the module. #### Bazel builds To use PyO3 with bazel one needs to manually configure PyO3, PyO3-ffi and PyO3-macros. In particular, one needs to make sure that it is compiled with the right python flags for the version you intend to use. For example see: 1. https://github.com/OliverFM/pytorch_with_gazelle -- for a minimal example of a repo that can use PyO3, PyTorch and Gazelle to generate python Build files. 2. https://github.com/TheButlah/rules_pyo3 -- which has more extensive support, but is outdated. #### Platform tags Rather than using just the `.so` or `.pyd` extension suggested above (depending on OS), you can prefix the shared library extension with a platform tag to indicate the interpreter it is compatible with. You can query your interpreter's platform tag from the `sysconfig` module. Some example outputs of this are seen below: ```bash # CPython 3.10 on macOS .cpython-310-darwin.so # PyPy 7.3 (Python 3.8) on Linux $ python -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX"))' .pypy38-pp73-x86_64-linux-gnu.so ``` So, for example, a valid module library name on CPython 3.10 for macOS is `your_module.cpython-310-darwin.so`, and its equivalent when compiled for PyPy 7.3 on Linux would be `your_module.pypy38-pp73-x86_64-linux-gnu.so`. See [PEP 3149](https://peps.python.org/pep-3149/) for more background on platform tags. #### macOS On macOS, because the `extension-module` feature disables linking to `libpython` ([see the next section](#the-extension-module-feature)), some additional linker arguments need to be set. `maturin` and `setuptools-rust` both pass these arguments for PyO3 automatically, but projects using manual builds will need to set these directly in order to support macOS. The easiest way to set the correct linker arguments is to add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) with the following content: ```rust,ignore fn main() { pyo3_build_config::add_extension_module_link_args(); } ``` Remember to also add `pyo3-build-config` to the `build-dependencies` section in `Cargo.toml`. An alternative to using `pyo3-build-config` is add the following to a cargo configuration file (e.g. `.cargo/config.toml`): ```toml [target.x86_64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] [target.aarch64-apple-darwin] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] ``` Using the MacOS system python3 (`/usr/bin/python3`, as opposed to python installed via homebrew, pyenv, nix, etc.) may result in runtime errors such as `Library not loaded: @rpath/Python3.framework/Versions/3.8/Python3`. These can be resolved with another addition to `.cargo/config.toml`: ```toml [build] rustflags = [ "-C", "link-args=-Wl,-rpath,/Library/Developer/CommandLineTools/Library/Frameworks", ] ``` Alternatively, one can include in `build.rs`: ```rust fn main() { println!( "cargo:rustc-link-arg=-Wl,-rpath,/Library/Developer/CommandLineTools/Library/Frameworks" ); } ``` For more discussion on and workarounds for MacOS linking problems [see this issue](https://github.com/PyO3/pyo3/issues/1800#issuecomment-906786649). Finally, don't forget that on MacOS the `extension-module` feature will cause `cargo test` to fail without the `--no-default-features` flag (see [the FAQ](https://pyo3.rs/main/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror)). ### The `extension-module` feature PyO3's `extension-module` feature is used to disable [linking](https://en.wikipedia.org/wiki/Linker_(computing)) to `libpython` on Unix targets. This is necessary because by default PyO3 links to `libpython`. This makes binaries, tests, and examples "just work". However, Python extensions on Unix must not link to libpython for [manylinux](https://www.python.org/dev/peps/pep-0513/) compliance. The downside of not linking to `libpython` is that binaries, tests, and examples (which usually embed Python) will fail to build. If you have an extension module as well as other outputs in a single project, you need to use optional Cargo features to disable the `extension-module` when you're not building the extension module. See [the FAQ](faq.md#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror) for an example workaround. ### `Py_LIMITED_API`/`abi3` By default, Python extension modules can only be used with the same Python version they were compiled against. For example, an extension module built for Python 3.5 can't be imported in Python 3.8. [PEP 384](https://www.python.org/dev/peps/pep-0384/) introduced the idea of the limited Python API, which would have a stable ABI enabling extension modules built with it to be used against multiple Python versions. This is also known as `abi3`. The advantage of building extension modules using the limited Python API is that package vendors only need to build and distribute a single copy (for each OS / architecture), and users can install it on all Python versions from the [minimum version](#minimum-python-version-for-abi3) and up. The downside of this is that PyO3 can't use optimizations which rely on being compiled against a known exact Python version. It's up to you to decide whether this matters for your extension module. It's also possible to design your extension module such that you can distribute `abi3` wheels but allow users compiling from source to benefit from additional optimizations - see the [support for multiple python versions](./building-and-distribution/multiple-python-versions.md) section of this guide, in particular the `#[cfg(Py_LIMITED_API)]` flag. There are three steps involved in making use of `abi3` when building Python packages as wheels: 1. Enable the `abi3` feature in `pyo3`. This ensures `pyo3` only calls Python C-API functions which are part of the stable API, and on Windows also ensures that the project links against the correct shared object (no special behavior is required on other platforms): ```toml [dependencies] pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["abi3"] } ``` 2. Ensure that the built shared objects are correctly marked as `abi3`. This is accomplished by telling your build system that you're using the limited API. [`maturin`] >= 0.9.0 and [`setuptools-rust`] >= 0.11.4 support `abi3` wheels. See the [corresponding](https://github.com/PyO3/maturin/pull/353) [PRs](https://github.com/PyO3/setuptools-rust/pull/82) for more. 3. Ensure that the `.whl` is correctly marked as `abi3`. For projects using `setuptools`, this is accomplished by passing `--py-limited-api=cp3x` (where `x` is the minimum Python version supported by the wheel, e.g. `--py-limited-api=cp35` for Python 3.5) to `setup.py bdist_wheel`. #### Minimum Python version for `abi3` Because a single `abi3` wheel can be used with many different Python versions, PyO3 has feature flags `abi3-py37`, `abi3-py38`, `abi3-py39` etc. to set the minimum required Python version for your `abi3` wheel. For example, if you set the `abi3-py37` feature, your extension wheel can be used on all Python 3 versions from Python 3.7 and up. `maturin` and `setuptools-rust` will give the wheel a name like `my-extension-1.0-cp37-abi3-manylinux2020_x86_64.whl`. As your extension module may be run with multiple different Python versions you may occasionally find you need to check the Python version at runtime to customize behavior. See [the relevant section of this guide](./building-and-distribution/multiple-python-versions.md#checking-the-python-version-at-runtime) on supporting multiple Python versions at runtime. PyO3 is only able to link your extension module to abi3 version up to and including your host Python version. E.g., if you set `abi3-py38` and try to compile the crate with a host of Python 3.7, the build will fail. > Note: If you set more that one of these `abi3` version feature flags the lowest version always wins. For example, with both `abi3-py37` and `abi3-py38` set, PyO3 would build a wheel which supports Python 3.7 and up. #### Building `abi3` extensions without a Python interpreter As an advanced feature, you can build PyO3 wheel without calling Python interpreter with the environment variable `PYO3_NO_PYTHON` set. Also, if the build host Python interpreter is not found or is too old or otherwise unusable, PyO3 will still attempt to compile `abi3` extension modules after displaying a warning message. On Unix-like systems this works unconditionally; on Windows you must also set the `RUSTFLAGS` environment variable to contain `-L native=/path/to/python/libs` so that the linker can find `python3.lib`. If the `python3.dll` import library is not available, an experimental `generate-import-lib` crate feature may be enabled, and the required library will be created and used by PyO3 automatically. *Note*: MSVC targets require LLVM binutils (`llvm-dlltool`) to be available in `PATH` for the automatic import library generation feature to work. #### Missing features Due to limitations in the Python API, there are a few `pyo3` features that do not work when compiling for `abi3`. These are: - `#[pyo3(text_signature = "...")]` does not work on classes until Python 3.10 or greater. - The `dict` and `weakref` options on classes are not supported until Python 3.9 or greater. - The buffer API is not supported until Python 3.11 or greater. - Optimizations which rely on knowledge of the exact Python version compiled against. ## Embedding Python in Rust If you want to embed the Python interpreter inside a Rust program, there are two modes in which this can be done: dynamically and statically. We'll cover each of these modes in the following sections. Each of them affect how you must distribute your program. Instead of learning how to do this yourself, you might want to consider using a project like [PyOxidizer] to ship your application and all of its dependencies in a single file. PyO3 automatically switches between the two linking modes depending on whether the Python distribution you have configured PyO3 to use ([see above](#configuring-the-python-version)) contains a shared library or a static library. The static library is most often seen in Python distributions compiled from source without the `--enable-shared` configuration option. ### Dynamically embedding the Python interpreter Embedding the Python interpreter dynamically is much easier than doing so statically. This is done by linking your program against a Python shared library (such as `libpython.3.9.so` on UNIX, or `python39.dll` on Windows). The implementation of the Python interpreter resides inside the shared library. This means that when the OS runs your Rust program it also needs to be able to find the Python shared library. This mode of embedding works well for Rust tests which need access to the Python interpreter. It is also great for Rust software which is installed inside a Python virtualenv, because the virtualenv sets up appropriate environment variables to locate the correct Python shared library. For distributing your program to non-technical users, you will have to consider including the Python shared library in your distribution as well as setting up wrapper scripts to set the right environment variables (such as `LD_LIBRARY_PATH` on UNIX, or `PATH` on Windows). Note that PyPy cannot be embedded in Rust (or any other software). Support for this is tracked on the [PyPy issue tracker](https://github.com/pypy/pypy/issues/3836). ### Statically embedding the Python interpreter Embedding the Python interpreter statically means including the contents of a Python static library directly inside your Rust binary. This means that to distribute your program you only need to ship your binary file: it contains the Python interpreter inside the binary! On Windows static linking is almost never done, so Python distributions don't usually include a static library. The information below applies only to UNIX. The Python static library is usually called `libpython.a`. Static linking has a lot of complications, listed below. For these reasons PyO3 does not yet have first-class support for this embedding mode. See [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416) for more information and to discuss any issues you encounter. The [`auto-initialize`](features.md#auto-initialize) feature is deliberately disabled when embedding the interpreter statically because this is often unintentionally done by new users to PyO3 running test programs. Trying out PyO3 is much easier using dynamic embedding. The known complications are: - To import compiled extension modules (such as other Rust extension modules, or those written in C), your binary must have the correct linker flags set during compilation to export the original contents of `libpython.a` so that extensions can use them (e.g. `-Wl,--export-dynamic`). - The C compiler and flags which were used to create `libpython.a` must be compatible with your Rust compiler and flags, else you will experience compilation failures. Significantly different compiler versions may see errors like this: ```text lto1: fatal error: bytecode stream in file 'rust-numpy/target/release/deps/libpyo3-6a7fb2ed970dbf26.rlib' generated with LTO version 6.0 instead of the expected 6.2 ``` Mismatching flags may lead to errors like this: ```text /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpython3.9.a(zlibmodule.o): relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE ``` If you encounter these or other complications when linking the interpreter statically, discuss them on [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416). It is hoped that eventually that discussion will contain enough information and solutions that PyO3 can offer first-class support for static embedding. ### Import your module when embedding the Python interpreter When you run your Rust binary with an embedded interpreter, any `#[pymodule]` created modules won't be accessible to import unless added to a table called `PyImport_Inittab` before the embedded interpreter is initialized. This will cause Python statements in your embedded interpreter such as `import your_new_module` to fail. You can call the macro [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) with your module before initializing the Python interpreter to add the module function into that table. (The Python interpreter will be initialized by calling `prepare_freethreaded_python`, `with_embedded_python_interpreter`, or `Python::with_gil` with the [`auto-initialize`](features.md#auto-initialize) feature enabled.) ## Cross Compiling Thanks to Rust's great cross-compilation support, cross-compiling using PyO3 is relatively straightforward. To get started, you'll need a few pieces of software: * A toolchain for your target. * The appropriate options in your Cargo `.config` for the platform you're targeting and the toolchain you are using. * A Python interpreter that's already been compiled for your target (optional when building "abi3" extension modules). * A Python interpreter that is built for your host and available through the `PATH` or setting the [`PYO3_PYTHON`](#configuring-the-python-version) variable (optional when building "abi3" extension modules). After you've obtained the above, you can build a cross-compiled PyO3 module by using Cargo's `--target` flag. PyO3's build script will detect that you are attempting a cross-compile based on your host machine and the desired target. When cross-compiling, PyO3's build script cannot execute the target Python interpreter to query the configuration, so there are a few additional environment variables you may need to set: * `PYO3_CROSS`: If present this variable forces PyO3 to configure as a cross-compilation. * `PYO3_CROSS_LIB_DIR`: This variable can be set to the directory containing the target's libpython DSO and the associated `_sysconfigdata*.py` file for Unix-like targets, or the Python DLL import libraries for the Windows target. This variable is only needed when the output binary must link to libpython explicitly (e.g. when targeting Windows and Android or embedding a Python interpreter), or when it is absolutely required to get the interpreter configuration from `_sysconfigdata*.py`. * `PYO3_CROSS_PYTHON_VERSION`: Major and minor version (e.g. 3.9) of the target Python installation. This variable is only needed if PyO3 cannot determine the version to target from `abi3-py3*` features, or if `PYO3_CROSS_LIB_DIR` is not set, or if there are multiple versions of Python present in `PYO3_CROSS_LIB_DIR`. * `PYO3_CROSS_PYTHON_IMPLEMENTATION`: Python implementation name ("CPython" or "PyPy") of the target Python installation. CPython is assumed by default when this variable is not set, unless `PYO3_CROSS_LIB_DIR` is set for a Unix-like target and PyO3 can get the interpreter configuration from `_sysconfigdata*.py`. An experimental `pyo3` crate feature `generate-import-lib` enables the user to cross-compile extension modules for Windows targets without setting the `PYO3_CROSS_LIB_DIR` environment variable or providing any Windows Python library files. It uses an external [`python3-dll-a`] crate to generate import libraries for the Python DLL for MinGW-w64 and MSVC compile targets. `python3-dll-a` uses the binutils `dlltool` program to generate DLL import libraries for MinGW-w64 targets. It is possible to override the default `dlltool` command name for the cross target by setting `PYO3_MINGW_DLLTOOL` environment variable. *Note*: MSVC targets require LLVM binutils or MSVC build tools to be available on the host system. More specifically, `python3-dll-a` requires `llvm-dlltool` or `lib.exe` executable to be present in `PATH` when targeting `*-pc-windows-msvc`. The Zig compiler executable can be used in place of `llvm-dlltool` when the `ZIG_COMMAND` environment variable is set to the installed Zig program name (`"zig"` or `"python -m ziglang"`). An example might look like the following (assuming your target's sysroot is at `/home/pyo3/cross/sysroot` and that your target is `armv7`): ```sh export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target armv7-unknown-linux-gnueabihf ``` If there are multiple python versions at the cross lib directory and you cannot set a more precise location to include both the `libpython` DSO and `_sysconfigdata*.py` files, you can set the required version: ```sh export PYO3_CROSS_PYTHON_VERSION=3.8 export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target armv7-unknown-linux-gnueabihf ``` Or another example with the same sys root but building for Windows: ```sh export PYO3_CROSS_PYTHON_VERSION=3.9 export PYO3_CROSS_LIB_DIR="/home/pyo3/cross/sysroot/usr/lib" cargo build --target x86_64-pc-windows-gnu ``` Any of the `abi3-py3*` features can be enabled instead of setting `PYO3_CROSS_PYTHON_VERSION` in the above examples. `PYO3_CROSS_LIB_DIR` can often be omitted when cross compiling extension modules for Unix and macOS targets, or when cross compiling extension modules for Windows and the experimental `generate-import-lib` crate feature is enabled. The following resources may also be useful for cross-compiling: - [github.com/japaric/rust-cross](https://github.com/japaric/rust-cross) is a primer on cross compiling Rust. - [github.com/rust-embedded/cross](https://github.com/rust-embedded/cross) uses Docker to make Rust cross-compilation easier. [`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config [`maturin-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/maturin-starter [`setuptools-rust-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/setuptools-rust-starter [`maturin`]: https://github.com/PyO3/maturin [`setuptools-rust`]: https://github.com/PyO3/setuptools-rust [PyOxidizer]: https://github.com/indygreg/PyOxidizer [`python3-dll-a`]: https://docs.rs/python3-dll-a/latest/python3_dll_a/ pyo3/guide/src/contributing.md0000644000175000017500000000004314661133735017345 0ustar jamespagejamespage{{#include ../../Contributing.md}} pyo3/guide/src/function/0000775000175000017500000000000014661133735016146 5ustar jamespagejamespagepyo3/guide/src/function/error-handling.md0000644000175000017500000002157214661133735021410 0ustar jamespagejamespage# Error handling This chapter contains a little background of error handling in Rust and how PyO3 integrates this with Python exceptions. This covers enough detail to create a `#[pyfunction]` which raises Python exceptions from errors originating in Rust. There is a later section of the guide on [Python exceptions](../exception.md) which covers exception types in more detail. ## Representing Python exceptions Rust code uses the generic [`Result`] enum to propagate errors. The error type `E` is chosen by the code author to describe the possible errors which can happen. PyO3 has the [`PyErr`] type which represents a Python exception. If a PyO3 API could result in a Python exception being raised, the return type of that `API` will be [`PyResult`], which is an alias for the type `Result`. In summary: - When Python exceptions are raised and caught by PyO3, the exception will be stored in the `Err` variant of the `PyResult`. - Passing Python exceptions through Rust code then uses all the "normal" techniques such as the `?` operator, with `PyErr` as the error type. - Finally, when a `PyResult` crosses from Rust back to Python via PyO3, if the result is an `Err` variant the contained exception will be raised. (There are many great tutorials on Rust error handling and the `?` operator, so this guide will not go into detail on Rust-specific topics.) ## Raising an exception from a function As indicated in the previous section, when a `PyResult` containing an `Err` crosses from Rust to Python, PyO3 will raise the exception contained within. Accordingly, to raise an exception from a `#[pyfunction]`, change the return type `T` to `PyResult`. When the function returns an `Err` it will raise a Python exception. (Other `Result` types can be used as long as the error `E` has a `From` conversion for `PyErr`, see [custom Rust error types](#custom-rust-error-types) below.) This also works for functions in `#[pymethods]`. For example, the following `check_positive` function raises a `ValueError` when the input is negative: ```rust use pyo3::exceptions::PyValueError; use pyo3::prelude::*; #[pyfunction] fn check_positive(x: i32) -> PyResult<()> { if x < 0 { Err(PyValueError::new_err("x is negative")) } else { Ok(()) } } # # fn main(){ # Python::with_gil(|py|{ # let fun = pyo3::wrap_pyfunction_bound!(check_positive, py).unwrap(); # fun.call1((-1,)).unwrap_err(); # fun.call1((1,)).unwrap(); # }); # } ``` All built-in Python exception types are defined in the [`pyo3::exceptions`] module. They have a `new_err` constructor to directly build a `PyErr`, as seen in the example above. ## Custom Rust error types PyO3 will automatically convert a `Result` returned by a `#[pyfunction]` into a `PyResult` as long as there is an implementation of `std::from::From for PyErr`. Many error types in the Rust standard library have a [`From`] conversion defined in this way. If the type `E` you are handling is defined in a third-party crate, see the section on [foreign rust error types](#foreign-rust-error-types) below for ways to work with this error. The following example makes use of the implementation of `From for PyErr` to raise exceptions encountered when parsing strings as integers: ```rust # use pyo3::prelude::*; use std::num::ParseIntError; #[pyfunction] fn parse_int(x: &str) -> Result { x.parse() } # fn main() { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(parse_int, py).unwrap(); # let value: usize = fun.call1(("5",)).unwrap().extract().unwrap(); # assert_eq!(value, 5); # }); # } ``` When passed a string which doesn't contain a floating-point number, the exception raised will look like the below: ```python >>> parse_int("bar") Traceback (most recent call last): File "", line 1, in ValueError: invalid digit found in string ``` As a more complete example, the following snippet defines a Rust error named `CustomIOError`. It then defines a `From for PyErr`, which returns a `PyErr` representing Python's `OSError`. Therefore, it can use this error in the result of a `#[pyfunction]` directly, relying on the conversion if it has to be propagated into a Python exception. ```rust use pyo3::exceptions::PyOSError; use pyo3::prelude::*; use std::fmt; #[derive(Debug)] struct CustomIOError; impl std::error::Error for CustomIOError {} impl fmt::Display for CustomIOError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Oh no!") } } impl std::convert::From for PyErr { fn from(err: CustomIOError) -> PyErr { PyOSError::new_err(err.to_string()) } } pub struct Connection {/* ... */} fn bind(addr: String) -> Result { if &addr == "0.0.0.0" { Err(CustomIOError) } else { Ok(Connection{ /* ... */}) } } #[pyfunction] fn connect(s: String) -> Result<(), CustomIOError> { bind(s)?; // etc. Ok(()) } fn main() { Python::with_gil(|py| { let fun = pyo3::wrap_pyfunction_bound!(connect, py).unwrap(); let err = fun.call1(("0.0.0.0",)).unwrap_err(); assert!(err.is_instance_of::(py)); }); } ``` If lazy construction of the Python exception instance is desired, the [`PyErrArguments`]({{#PYO3_DOCS_URL}}/pyo3/trait.PyErrArguments.html) trait can be implemented instead of `From`. In that case, actual exception argument creation is delayed until the `PyErr` is needed. A final note is that any errors `E` which have a `From` conversion can be used with the `?` ("try") operator with them. An alternative implementation of the above `parse_int` which instead returns `PyResult` is below: ```rust use pyo3::prelude::*; fn parse_int(s: String) -> PyResult { let x = s.parse()?; Ok(x) } # # use pyo3::exceptions::PyValueError; # # fn main() { # Python::with_gil(|py| { # assert_eq!(parse_int(String::from("1")).unwrap(), 1); # assert_eq!(parse_int(String::from("1337")).unwrap(), 1337); # # assert!(parse_int(String::from("-1")) # .unwrap_err() # .is_instance_of::(py)); # assert!(parse_int(String::from("foo")) # .unwrap_err() # .is_instance_of::(py)); # assert!(parse_int(String::from("13.37")) # .unwrap_err() # .is_instance_of::(py)); # }) # } ``` ## Foreign Rust error types The Rust compiler will not permit implementation of traits for types outside of the crate where the type is defined. (This is known as the "orphan rule".) Given a type `OtherError` which is defined in third-party code, there are two main strategies available to integrate it with PyO3: - Create a newtype wrapper, e.g. `MyOtherError`. Then implement `From for PyErr` (or `PyErrArguments`), as well as `From` for `MyOtherError`. - Use Rust's Result combinators such as `map_err` to write code freely to convert `OtherError` into whatever is needed. This requires boilerplate at every usage however gives unlimited flexibility. To detail the newtype strategy a little further, the key trick is to return `Result` from the `#[pyfunction]`. This means that PyO3 will make use of `From for PyErr` to create Python exceptions while the `#[pyfunction]` implementation can use `?` to convert `OtherError` to `MyOtherError` automatically. The following example demonstrates this for some imaginary third-party crate `some_crate` with a function `get_x` returning `Result`: ```rust # mod some_crate { # pub struct OtherError(()); # impl OtherError { # pub fn message(&self) -> &'static str { "some error occurred" } # } # pub fn get_x() -> Result { Ok(5) } # } use pyo3::prelude::*; use pyo3::exceptions::PyValueError; use some_crate::{OtherError, get_x}; struct MyOtherError(OtherError); impl From for PyErr { fn from(error: MyOtherError) -> Self { PyValueError::new_err(error.0.message()) } } impl From for MyOtherError { fn from(other: OtherError) -> Self { Self(other) } } #[pyfunction] fn wrapped_get_x() -> Result { // get_x is a function returning Result let x: i32 = get_x()?; Ok(x) } # fn main() { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(wrapped_get_x, py).unwrap(); # let value: usize = fun.call0().unwrap().extract().unwrap(); # assert_eq!(value, 5); # }); # } ``` [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html [`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html [`PyResult`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/type.PyResult.html [`PyErr`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html [`pyo3::exceptions`]: {{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html pyo3/guide/src/function/signature.md0000644000175000017500000002712414661133735020475 0ustar jamespagejamespage# Function signatures The `#[pyfunction]` attribute also accepts parameters to control how the generated Python function accepts arguments. Just like in Python, arguments can be positional-only, keyword-only, or accept either. `*args` lists and `**kwargs` dicts can also be accepted. These parameters also work for `#[pymethods]` which will be introduced in the [Python Classes](../class.md) section of the guide. Like Python, by default PyO3 accepts all arguments as either positional or keyword arguments. Most arguments are required by default, except for trailing `Option<_>` arguments, which are [implicitly given a default of `None`](#trailing-optional-arguments). This behaviour can be configured by the `#[pyo3(signature = (...))]` option which allows writing a signature in Python syntax. This section of the guide goes into detail about use of the `#[pyo3(signature = (...))]` option and its related option `#[pyo3(text_signature = "...")]` ## Using `#[pyo3(signature = (...))]` For example, below is a function that accepts arbitrary keyword arguments (`**kwargs` in Python syntax) and returns the number that was passed: ```rust use pyo3::prelude::*; use pyo3::types::PyDict; #[pyfunction] #[pyo3(signature = (**kwds))] fn num_kwds(kwds: Option<&Bound<'_, PyDict>>) -> usize { kwds.map_or(0, |dict| dict.len()) } #[pymodule] fn module_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(num_kwds, m)?) } ``` Just like in Python, the following constructs can be part of the signature:: * `/`: positional-only arguments separator, each parameter defined before `/` is a positional-only parameter. * `*`: var arguments separator, each parameter defined after `*` is a keyword-only parameter. * `*args`: "args" is var args. Type of the `args` parameter has to be `&Bound<'_, PyTuple>`. * `**kwargs`: "kwargs" receives keyword arguments. The type of the `kwargs` parameter has to be `Option<&Bound<'_, PyDict>>`. * `arg=Value`: arguments with default value. If the `arg` argument is defined after var arguments, it is treated as a keyword-only argument. Note that `Value` has to be valid rust code, PyO3 just inserts it into the generated code unmodified. Example: ```rust # use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; # # #[pyclass] # struct MyClass { # num: i32, # } #[pymethods] impl MyClass { #[new] #[pyo3(signature = (num=-1))] fn new(num: i32) -> Self { MyClass { num } } #[pyo3(signature = (num=10, *py_args, name="Hello", **py_kwargs))] fn method( &mut self, num: i32, py_args: &Bound<'_, PyTuple>, name: &str, py_kwargs: Option<&Bound<'_, PyDict>>, ) -> String { let num_before = self.num; self.num = num; format!( "num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} ", num, num_before, py_args, name, py_kwargs, ) } fn make_change(&mut self, num: i32) -> PyResult { self.num = num; Ok(format!("num={}", self.num)) } } ``` Arguments of type `Python` must not be part of the signature: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (lambda))] pub fn simple_python_bound_function(py: Python<'_>, lambda: PyObject) -> PyResult<()> { Ok(()) } ``` N.B. the position of the `/` and `*` arguments (if included) control the system of handling positional and keyword arguments. In Python: ```python import mymodule mc = mymodule.MyClass() print(mc.method(44, False, "World", 666, x=44, y=55)) print(mc.method(num=-1, name="World")) print(mc.make_change(44, False)) ``` Produces output: ```text py_args=('World', 666), py_kwargs=Some({'x': 44, 'y': 55}), name=Hello, num=44 py_args=(), py_kwargs=None, name=World, num=-1 num=44 num=-1 ``` > Note: to use keywords like `struct` as a function argument, use "raw identifier" syntax `r#struct` in both the signature and the function definition: > > ```rust > # #![allow(dead_code)] > # use pyo3::prelude::*; > #[pyfunction(signature = (r#struct = "foo"))] > fn function_with_keyword(r#struct: &str) { > # let _ = r#struct; > /* ... */ > } > ``` ## Trailing optional arguments
⚠️ Warning: This behaviour is being phased out 🛠️ The special casing of trailing optional arguments is deprecated. In a future `pyo3` version, arguments of type `Option<..>` will share the same behaviour as other arguments, they are required unless a default is set using `#[pyo3(signature = (...))]`. This is done to better align the Python and Rust definition of such functions and make it more intuitive to rewrite them from Python in Rust. Specifically `def some_fn(a: int, b: Optional[int]): ...` will not automatically default `b` to `none`, but requires an explicit default if desired, where as in current `pyo3` it is handled the other way around. During the migration window a `#[pyo3(signature = (...))]` will be required to silence the deprecation warning. After support for trailing optional arguments is fully removed, the signature attribute can be removed if all arguments should be required.
As a convenience, functions without a `#[pyo3(signature = (...))]` option will treat trailing `Option` arguments as having a default of `None`. In the example below, PyO3 will create `increment` with a signature of `increment(x, amount=None)`. ```rust #![allow(deprecated)] use pyo3::prelude::*; /// Returns a copy of `x` increased by `amount`. /// /// If `amount` is unspecified or `None`, equivalent to `x + 1`. #[pyfunction] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(increment, py)?; # # let inspect = PyModule::import_bound(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # # #[cfg(Py_3_8)] // on 3.7 the signature doesn't render b, upstream bug? # assert_eq!(sig, "(x, amount=None)"); # # Ok(()) # }) # } ``` To make trailing `Option` arguments required, but still accept `None`, add a `#[pyo3(signature = (...))]` annotation. For the example above, this would be `#[pyo3(signature = (x, amount))]`: ```rust # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (x, amount))] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(increment, py)?; # # let inspect = PyModule::import_bound(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # # #[cfg(Py_3_8)] // on 3.7 the signature doesn't render b, upstream bug? # assert_eq!(sig, "(x, amount)"); # # Ok(()) # }) # } ``` To help avoid confusion, PyO3 requires `#[pyo3(signature = (...))]` when an `Option` argument is surrounded by arguments which aren't `Option`. ## Making the function signature available to Python The function signature is exposed to Python via the `__text_signature__` attribute. PyO3 automatically generates this for every `#[pyfunction]` and all `#[pymethods]` directly from the Rust function, taking into account any override done with the `#[pyo3(signature = (...))]` option. This automatic generation can only display the value of default arguments for strings, integers, boolean types, and `None`. Any other default arguments will be displayed as `...`. (`.pyi` type stub files commonly also use `...` for default arguments in the same way.) In cases where the automatically-generated signature needs adjusting, it can [be overridden](#overriding-the-generated-signature) using the `#[pyo3(text_signature)]` option.) The example below creates a function `add` which accepts two positional-only arguments `a` and `b`, where `b` has a default value of zero. ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /))] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # # let inspect = PyModule::import_bound(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # # #[cfg(Py_3_8)] // on 3.7 the signature doesn't render b, upstream bug? # assert_eq!(sig, "(a, b=0, /)"); # # Ok(()) # }) # } ``` The following IPython output demonstrates how this generated signature will be seen from Python tooling: ```text >>> pyo3_test.add.__text_signature__ '(a, b=..., /)' >>> pyo3_test.add? Signature: pyo3_test.add(a, b=0, /) Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` ### Overriding the generated signature The `#[pyo3(text_signature = "()")]` attribute can be used to override the default generated signature. In the snippet below, the text signature attribute is used to include the default value of `0` for the argument `b`, instead of the automatically-generated default value of `...`: ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /), text_signature = "(a, b=0, /)")] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # # let inspect = PyModule::import_bound(py, "inspect")?.getattr("signature")?; # let sig: String = inspect # .call1((fun,))? # .call_method0("__str__")? # .extract()?; # assert_eq!(sig, "(a, b=0, /)"); # # Ok(()) # }) # } ``` PyO3 will include the contents of the annotation unmodified as the `__text_signature__`. Below shows how IPython will now present this (see the default value of 0 for b): ```text >>> pyo3_test.add.__text_signature__ '(a, b=0, /)' >>> pyo3_test.add? Signature: pyo3_test.add(a, b=0, /) Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` If no signature is wanted at all, `#[pyo3(text_signature = None)]` will disable the built-in signature. The snippet below demonstrates use of this: ```rust use pyo3::prelude::*; /// This function adds two unsigned 64-bit integers. #[pyfunction] #[pyo3(signature = (a, b=0, /), text_signature = None)] fn add(a: u64, b: u64) -> u64 { a + b } # # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(add, py)?; # # let doc: String = fun.getattr("__doc__")?.extract()?; # assert_eq!(doc, "This function adds two unsigned 64-bit integers."); # assert!(fun.getattr("__text_signature__")?.is_none()); # # Ok(()) # }) # } ``` Now the function's `__text_signature__` will be set to `None`, and IPython will not display any signature in the help: ```text >>> pyo3_test.add.__text_signature__ == None True >>> pyo3_test.add? Docstring: This function adds two unsigned 64-bit integers. Type: builtin_function_or_method ``` pyo3/guide/src/getting-started.md0000644000175000017500000001503214661133735017747 0ustar jamespagejamespage# Installation To get started using PyO3 you will need three things: a Rust toolchain, a Python environment, and a way to build. We'll cover each of these below. > If you'd like to chat to the PyO3 maintainers and other PyO3 users, consider joining the [PyO3 Discord server](https://discord.gg/33kcChzH7f). We're keen to hear about your experience getting started, so we can make PyO3 as accessible as possible for everyone! ## Rust First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.63. If you can run `rustc --version` and the version is new enough you're good to go! ## Python To use PyO3, you need at least Python 3.7. While you can simply use the default Python interpreter on your system, it is recommended to use a virtual environment. ## Virtualenvs While you can use any virtualenv manager you like, we recommend the use of `pyenv` in particular if you want to develop or test for multiple different Python versions, so that is what the examples in this book will use. The installation instructions for `pyenv` can be found [here](https://github.com/pyenv/pyenv#getting-pyenv). (Note: To get the `pyenv activate` and `pyenv virtualenv` commands, you will also need to install the [`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv) plugin. The [pyenv installer](https://github.com/pyenv/pyenv-installer#installation--update--uninstallation) will install both together.) It can be useful to keep the sources used when installing using `pyenv` so that future debugging can see the original source files. This can be done by passing the `--keep` flag as part of the `pyenv install` command. For example: ```bash pyenv install 3.12 --keep ``` ### Building There are a number of build and Python package management systems such as [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](./building-and-distribution.md#manual-builds). We recommend the use of `maturin`, which you can install [here](https://maturin.rs/installation.html). It is developed to work with PyO3 and provides the most "batteries included" experience, especially if you are aiming to publish to PyPI. `maturin` is just a Python package, so you can add it in the same way you already install Python packages. System Python: ```bash pip install maturin --user ``` pipx: ```bash pipx install maturin ``` pyenv: ```bash pyenv activate pyo3 pip install maturin ``` poetry: ```bash poetry add -G dev maturin ``` After installation, you can run `maturin --version` to check that you have correctly installed it. # Starting a new project First you should create the folder and virtual environment that are going to contain your new project. Here we will use the recommended `pyenv`: ```bash mkdir pyo3-example cd pyo3-example pyenv virtualenv pyo3 pyenv local pyo3 ``` After this, you should install your build manager. In this example, we will use `maturin`. After you've activated your virtualenv, add `maturin` to it: ```bash pip install maturin ``` Now you can initialize the new project: ```bash maturin init ``` If `maturin` is already installed, you can create a new project using that directly as well: ```bash maturin new -b pyo3 pyo3-example cd pyo3-example pyenv virtualenv pyo3 pyenv local pyo3 ``` # Adding to an existing project Sadly, `maturin` cannot currently be run in existing projects, so if you want to use Python in an existing project you basically have two options: 1. Create a new project as above and move your existing code into that project 2. Manually edit your project configuration as necessary If you opt for the second option, here are the things you need to pay attention to: ## Cargo.toml Make sure that the Rust crate you want to be able to access from Python is compiled into a library. You can have a binary output as well, but the code you want to access from Python has to be in the library part. Also, make sure that the crate type is `cdylib` and add PyO3 as a dependency as so: ```toml # If you already have [package] information in `Cargo.toml`, you can ignore # this section! [package] # `name` here is name of the package. name = "pyo3_start" # these are good defaults: version = "0.1.0" edition = "2021" [lib] # The name of the native library. This is the name which will be used in Python to import the # library (i.e. `import string_sum`). If you change this, you must also change the name of the # `#[pymodule]` in `src/lib.rs`. name = "pyo3_example" # "cdylib" is necessary to produce a shared library for Python to import from. crate-type = ["cdylib"] [dependencies] pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["extension-module"] } ``` ## pyproject.toml You should also create a `pyproject.toml` with the following contents: ```toml [build-system] requires = ["maturin>=1,<2"] build-backend = "maturin" [project] name = "pyo3_example" requires-python = ">=3.7" classifiers = [ "Programming Language :: Rust", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] ``` ## Running code After this you can setup Rust code to be available in Python as below; for example, you can place this code in `src/lib.rs`: ```rust use pyo3::prelude::*; /// Formats the sum of two numbers as string. #[pyfunction] fn sum_as_string(a: usize, b: usize) -> PyResult { Ok((a + b).to_string()) } /// A Python module implemented in Rust. The name of this function must match /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to /// import the module. #[pymodule] fn pyo3_example(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(sum_as_string, m)?) } ``` Now you can run `maturin develop` to prepare the Python package, after which you can use it like so: ```bash $ maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import pyo3_example >>> pyo3_example.sum_as_string(5, 20) '25' ``` For more instructions on how to use Python code from Rust, see the [Python from Rust](python-from-rust.md) page. ## Maturin Import Hook In development, any changes in the code would require running `maturin develop` before testing. To streamline the development process, you may want to install [Maturin Import Hook](https://github.com/PyO3/maturin-import-hook) which will run `maturin develop` automatically when the library with code changes is being imported. pyo3/guide/src/advanced.md0000644000175000017500000000062114661133735016405 0ustar jamespagejamespage# Advanced topics ## FFI PyO3 exposes much of Python's C API through the `ffi` module. The C API is naturally unsafe and requires you to manage reference counts, errors and specific invariants yourself. Please refer to the [C API Reference Manual](https://docs.python.org/3/c-api/) and [The Rustonomicon](https://doc.rust-lang.org/nightly/nomicon/ffi.html) before using any function from that API. pyo3/guide/src/module.md0000644000175000017500000001207314661133735016131 0ustar jamespagejamespage# Python modules You can create a module using `#[pymodule]`: ```rust use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } /// This module is implemented in Rust. #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?) } ``` The `#[pymodule]` procedural macro takes care of exporting the initialization function of your module to Python. The module's name defaults to the name of the Rust function. You can override the module name by using `#[pyo3(name = "custom_name")]`: ```rust use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule(name = "custom_name")] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?) } ``` The name of the module must match the name of the `.so` or `.pyd` file. Otherwise, you will get an import error in Python with the following message: `ImportError: dynamic module does not define module export function (PyInit_name_of_your_module)` To import the module, either: - copy the shared library as described in [Manual builds](building-and-distribution.md#manual-builds), or - use a tool, e.g. `maturin develop` with [maturin](https://github.com/PyO3/maturin) or `python setup.py develop` with [setuptools-rust](https://github.com/PyO3/setuptools-rust). ## Documentation The [Rust doc comments](https://doc.rust-lang.org/stable/book/ch03-04-comments.html) of the module initialization function will be applied automatically as the Python docstring of your module. For example, building off of the above code, this will print `This module is implemented in Rust.`: ```python import my_extension print(my_extension.__doc__) ``` ## Python submodules You can create a module hierarchy within a single extension module by using [`Bound<'_, PyModule>::add_submodule()`]({{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyModuleMethods.html#tymethod.add_submodule). For example, you could define the modules `parent_module` and `parent_module.child_module`. ```rust use pyo3::prelude::*; #[pymodule] fn parent_module(m: &Bound<'_, PyModule>) -> PyResult<()> { register_child_module(m)?; Ok(()) } fn register_child_module(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { let child_module = PyModule::new_bound(parent_module.py(), "child_module")?; child_module.add_function(wrap_pyfunction!(func, &child_module)?)?; parent_module.add_submodule(&child_module) } #[pyfunction] fn func() -> String { "func".to_string() } # Python::with_gil(|py| { # use pyo3::wrap_pymodule; # use pyo3::types::IntoPyDict; # let parent_module = wrap_pymodule!(parent_module)(py); # let ctx = [("parent_module", parent_module)].into_py_dict_bound(py); # # py.run_bound("assert parent_module.child_module.func() == 'func'", None, Some(&ctx)).unwrap(); # }) ``` Note that this does not define a package, so this won’t allow Python code to directly import submodules by using `from parent_module import child_module`. For more information, see [#759](https://github.com/PyO3/pyo3/issues/759) and [#1517](https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021). It is not necessary to add `#[pymodule]` on nested modules, which is only required on the top-level module. ## Declarative modules Another syntax based on Rust inline modules is also available to declare modules. For example: ```rust # mod declarative_module_test { use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule] mod my_extension { use super::*; #[pymodule_export] use super::double; // Exports the double function as part of the module #[pyfunction] // This will be part of the module fn triple(x: usize) -> usize { x * 3 } #[pyclass] // This will be part of the module struct Unit; #[pymodule] mod submodule { // This is a submodule } #[pymodule_init] fn init(m: &Bound<'_, PyModule>) -> PyResult<()> { // Arbitrary code to run at the module initialization m.add("double2", m.getattr("double")?) } } # } ``` The `#[pymodule]` macro automatically sets the `module` attribute of the `#[pyclass]` macros declared inside of it with its name. For nested modules, the name of the parent module is automatically added. In the following example, the `Unit` class will have for `module` `my_extension.submodule` because it is properly nested but the `Ext` class will have for `module` the default `builtins` because it not nested. You can provide the `submodule` argument to `pymodule()` for modules that are not top-level modules. ```rust # mod declarative_module_module_attr_test { use pyo3::prelude::*; #[pyclass] struct Ext; #[pymodule] mod my_extension { use super::*; #[pymodule_export] use super::Ext; #[pymodule(submodule)] mod submodule { use super::*; // This is a submodule #[pyclass] // This will be part of the module struct Unit; } } # } ``` It is possible to customize the `module` value for a `#[pymodule]` with the `#[pyo3(module = "MY_MODULE")]` option. pyo3/guide/src/features.md0000644000175000017500000002431514661133735016464 0ustar jamespagejamespage# Features reference PyO3 provides a number of Cargo features to customize functionality. This chapter of the guide provides detail on each of them. By default, only the `macros` feature is enabled. ## Features for extension module authors ### `extension-module` This feature is required when building a Python extension module using PyO3. It tells PyO3's build script to skip linking against `libpython.so` on Unix platforms, where this must not be done. See the [building and distribution](building-and-distribution.md#the-extension-module-feature) section for further detail. ### `abi3` This feature is used when building Python extension modules to create wheels which are compatible with multiple Python versions. It restricts PyO3's API to a subset of the full Python API which is guaranteed by [PEP 384](https://www.python.org/dev/peps/pep-0384/) to be forwards-compatible with future Python versions. See the [building and distribution](building-and-distribution.md#py_limited_apiabi3) section for further detail. ### The `abi3-pyXY` features (`abi3-py37`, `abi3-py38`, `abi3-py39`, `abi3-py310` and `abi3-py311`) These features are extensions of the `abi3` feature to specify the exact minimum Python version which the multiple-version-wheel will support. See the [building and distribution](building-and-distribution.md#minimum-python-version-for-abi3) section for further detail. ### `generate-import-lib` This experimental feature is used to generate import libraries for Python DLL for MinGW-w64 and MSVC (cross-)compile targets. Enabling it allows to (cross-)compile extension modules to any Windows targets without having to install the Windows Python distribution files for the target. See the [building and distribution](building-and-distribution.md#building-abi3-extensions-without-a-python-interpreter) section for further detail. ## Features for embedding Python in Rust ### `auto-initialize` This feature changes [`Python::with_gil`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.with_gil) to automatically initialize a Python interpreter (by calling [`prepare_freethreaded_python`]({{#PYO3_DOCS_URL}}/pyo3/fn.prepare_freethreaded_python.html)) if needed. If you do not enable this feature, you should call `pyo3::prepare_freethreaded_python()` before attempting to call any other Python APIs. ## Advanced Features ### `experimental-async` This feature adds support for `async fn` in `#[pyfunction]` and `#[pymethods]`. The feature has some unfinished refinements and performance improvements. To help finish this off, see [issue #1632](https://github.com/PyO3/pyo3/issues/1632) and its associated draft PRs. ### `experimental-inspect` This feature adds the `pyo3::inspect` module, as well as `IntoPy::type_output` and `FromPyObject::type_input` APIs to produce Python type "annotations" for Rust types. This is a first step towards adding first-class support for generating type annotations automatically in PyO3, however work is needed to finish this off. All feedback and offers of help welcome on [issue #2454](https://github.com/PyO3/pyo3/issues/2454). ### `gil-refs` This feature is a backwards-compatibility feature to allow continued use of the "GIL Refs" APIs deprecated in PyO3 0.21. These APIs have performance drawbacks and soundness edge cases which the newer `Bound` smart pointer and accompanying APIs resolve. This feature and the APIs it enables is expected to be removed in a future PyO3 version. ### `py-clone` This feature was introduced to ease migration. It was found that delayed reference counts cannot be made sound and hence `Clon`ing an instance of `Py` must panic without the GIL being held. To avoid migrations introducing new panics without warning, the `Clone` implementation itself is now gated behind this feature. ### `pyo3_disable_reference_pool` This is a performance-oriented conditional compilation flag, e.g. [set via `$RUSTFLAGS`][set-configuration-options], which disabled the global reference pool and the assocaited overhead for the crossing the Python-Rust boundary. However, if enabled, `Drop`ping an instance of `Py` without the GIL being held will abort the process. ### `macros` This feature enables a dependency on the `pyo3-macros` crate, which provides the procedural macros portion of PyO3's API: - `#[pymodule]` - `#[pyfunction]` - `#[pyclass]` - `#[pymethods]` - `#[derive(FromPyObject)]` It also provides the `py_run!` macro. These macros require a number of dependencies which may not be needed by users who just need PyO3 for Python FFI. Disabling this feature enables faster builds for those users, as these dependencies will not be built if this feature is disabled. > This feature is enabled by default. To disable it, set `default-features = false` for the `pyo3` entry in your Cargo.toml. ### `multiple-pymethods` This feature enables each `#[pyclass]` to have more than one `#[pymethods]` block. Most users should only need a single `#[pymethods]` per `#[pyclass]`. In addition, not all platforms (e.g. Wasm) are supported by `inventory`, which is used in the implementation of the feature. For this reason this feature is not enabled by default, meaning fewer dependencies and faster compilation for the majority of users. See [the `#[pyclass]` implementation details](class.md#implementation-details) for more information. ### `nightly` The `nightly` feature needs the nightly Rust compiler. This allows PyO3 to use the `auto_traits` and `negative_impls` features to fix the `Python::allow_threads` function. ### `resolve-config` The `resolve-config` feature of the `pyo3-build-config` crate controls whether that crate's build script automatically resolves a Python interpreter / build configuration. This feature is primarily useful when building PyO3 itself. By default this feature is not enabled, meaning you can freely use `pyo3-build-config` as a standalone library to read or write PyO3 build configuration files or resolve metadata about a Python interpreter. ## Optional Dependencies These features enable conversions between Python types and types from other Rust crates, enabling easy access to the rest of the Rust ecosystem. ### `anyhow` Adds a dependency on [anyhow](https://docs.rs/anyhow). Enables a conversion from [anyhow](https://docs.rs/anyhow)’s [`Error`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling. ### `chrono` Adds a dependency on [chrono](https://docs.rs/chrono). Enables a conversion from [chrono](https://docs.rs/chrono)'s types to python: - [TimeDelta](https://docs.rs/chrono/latest/chrono/struct.TimeDelta.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [FixedOffset](https://docs.rs/chrono/latest/chrono/offset/struct.FixedOffset.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html) - [Utc](https://docs.rs/chrono/latest/chrono/offset/struct.Utc.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html) - [NaiveDate](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDate.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html) - [NaiveTime](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html) - [DateTime](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html) ### `chrono-tz` Adds a dependency on [chrono-tz](https://docs.rs/chrono-tz). Enables conversion from and to [`Tz`](https://docs.rs/chrono-tz/latest/chrono_tz/enum.Tz.html). It requires at least Python 3.9. ### `either` Adds a dependency on [either](https://docs.rs/either). Enables a conversions into [either](https://docs.rs/either)’s [`Either`](https://docs.rs/either/latest/either/enum.Either.html) type. ### `eyre` Adds a dependency on [eyre](https://docs.rs/eyre). Enables a conversion from [eyre](https://docs.rs/eyre)’s [`Report`](https://docs.rs/eyre/latest/eyre/struct.Report.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling. ### `hashbrown` Adds a dependency on [hashbrown](https://docs.rs/hashbrown) and enables conversions into its [`HashMap`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html) and [`HashSet`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html) types. ### `indexmap` Adds a dependency on [indexmap](https://docs.rs/indexmap) and enables conversions into its [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html) type. ### `num-bigint` Adds a dependency on [num-bigint](https://docs.rs/num-bigint) and enables conversions into its [`BigInt`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html) and [`BigUint`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html) types. ### `num-complex` Adds a dependency on [num-complex](https://docs.rs/num-complex) and enables conversions into its [`Complex`](https://docs.rs/num-complex/latest/num_complex/struct.Complex.html) type. ### `num-rational` Adds a dependency on [num-rational](https://docs.rs/num-rational) and enables conversions into its [`Ratio`](https://docs.rs/num-rational/latest/num_rational/struct.Ratio.html) type. ### `rust_decimal` Adds a dependency on [rust_decimal](https://docs.rs/rust_decimal) and enables conversions into its [`Decimal`](https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html) type. ### `serde` Enables (de)serialization of `Py` objects via [serde](https://serde.rs/). This allows to use [`#[derive(Serialize, Deserialize)`](https://serde.rs/derive.html) on structs that hold references to `#[pyclass]` instances ```rust # #[cfg(feature = "serde")] # #[allow(dead_code)] # mod serde_only { # use pyo3::prelude::*; # use serde::{Deserialize, Serialize}; #[pyclass] #[derive(Serialize, Deserialize)] struct Permission { name: String, } #[pyclass] #[derive(Serialize, Deserialize)] struct User { username: String, permissions: Vec>, } # } ``` ### `smallvec` Adds a dependency on [smallvec](https://docs.rs/smallvec) and enables conversions into its [`SmallVec`](https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html) type. [set-configuration-options]: https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options pyo3/guide/src/function-calls.md0000644000175000017500000000003314661133735017556 0ustar jamespagejamespage# Calling Python functions pyo3/guide/src/building-and-distribution/0000775000175000017500000000000014661133735021373 5ustar jamespagejamespagepyo3/guide/src/building-and-distribution/multiple-python-versions.md0000644000175000017500000001212014661133735026727 0ustar jamespagejamespage# Supporting multiple Python versions PyO3 supports all actively-supported Python 3 and PyPy versions. As much as possible, this is done internally to PyO3 so that your crate's code does not need to adapt to the differences between each version. However, as Python features grow and change between versions, PyO3 cannot a completely identical API for every Python version. This may require you to add conditional compilation to your crate or runtime checks for the Python version. This section of the guide first introduces the `pyo3-build-config` crate, which you can use as a `build-dependency` to add additional `#[cfg]` flags which allow you to support multiple Python versions at compile-time. Second, we'll show how to check the Python version at runtime. This can be useful when building for multiple versions with the `abi3` feature, where the Python API compiled against is not always the same as the one in use. ## Conditional compilation for different Python versions The `pyo3-build-config` exposes multiple [`#[cfg]` flags](https://doc.rust-lang.org/rust-by-example/attribute/cfg.html) which can be used to conditionally compile code for a given Python version. PyO3 itself depends on this crate, so by using it you can be sure that you are configured correctly for the Python version PyO3 is building against. This allows us to write code like the following ```rust,ignore #[cfg(Py_3_7)] fn function_only_supported_on_python_3_7_and_up() {} #[cfg(not(Py_3_8))] fn function_only_supported_before_python_3_8() {} #[cfg(not(Py_LIMITED_API))] fn function_incompatible_with_abi3_feature() {} ``` The following sections first show how to add these `#[cfg]` flags to your build process, and then cover some common patterns flags in a little more detail. To see a full reference of all the `#[cfg]` flags provided, see the [`pyo3-build-cfg` docs](https://docs.rs/pyo3-build-config). ### Using `pyo3-build-config` You can use the `#[cfg]` flags in just two steps: 1. Add `pyo3-build-config` with the [`resolve-config`](../features.md#resolve-config) feature enabled to your crate's build dependencies in `Cargo.toml`: ```toml [build-dependencies] pyo3-build-config = { {{#PYO3_CRATE_VERSION}}, features = ["resolve-config"] } ``` 2. Add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) file to your crate with the following contents: ```rust,ignore fn main() { // If you have an existing build.rs file, just add this line to it. pyo3_build_config::use_pyo3_cfgs(); } ``` After these steps you are ready to annotate your code! ### Common usages of `pyo3-build-cfg` flags The `#[cfg]` flags added by `pyo3-build-cfg` can be combined with all of Rust's logic in the `#[cfg]` attribute to create very precise conditional code generation. The following are some common patterns implemented using these flags: ```text #[cfg(Py_3_7)] ``` This `#[cfg]` marks code that will only be present on Python 3.7 and upwards. There are similar options `Py_3_8`, `Py_3_9`, `Py_3_10` and so on for each minor version. ```text #[cfg(not(Py_3_7))] ``` This `#[cfg]` marks code that will only be present on Python versions before (but not including) Python 3.7. ```text #[cfg(not(Py_LIMITED_API))] ``` This `#[cfg]` marks code that is only available when building for the unlimited Python API (i.e. PyO3's `abi3` feature is not enabled). This might be useful if you want to ship your extension module as an `abi3` wheel and also allow users to compile it from source to make use of optimizations only possible with the unlimited API. ```text #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] ``` This `#[cfg]` marks code which is available when running Python 3.9 or newer, or when using the unlimited API with an older Python version. Patterns like this are commonly seen on Python APIs which were added to the limited Python API in a specific minor version. ```text #[cfg(PyPy)] ``` This `#[cfg]` marks code which is running on PyPy. ## Checking the Python version at runtime When building with PyO3's `abi3` feature, your extension module will be compiled against a specific [minimum version](../building-and-distribution.md#minimum-python-version-for-abi3) of Python, but may be running on newer Python versions. For example with PyO3's `abi3-py38` feature, your extension will be compiled as if it were for Python 3.8. If you were using `pyo3-build-config`, `#[cfg(Py_3_8)]` would be present. Your user could freely install and run your abi3 extension on Python 3.9. There's no way to detect your user doing that at compile time, so instead you need to fall back to runtime checks. PyO3 provides the APIs [`Python::version()`] and [`Python::version_info()`] to query the running Python version. This allows you to do the following, for example: ```rust use pyo3::Python; Python::with_gil(|py| { // PyO3 supports Python 3.7 and up. assert!(py.version_info() >= (3, 7)); assert!(py.version_info() >= (3, 7, 0)); }); ``` [`Python::version()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version [`Python::version_info()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version_info pyo3/guide/src/conversions/0000775000175000017500000000000014661133735016671 5ustar jamespagejamespagepyo3/guide/src/conversions/tables.md0000644000175000017500000001723314661133735020471 0ustar jamespagejamespage## Mapping of Rust types to Python types When writing functions callable from Python (such as a `#[pyfunction]` or in a `#[pymethods]` block), the trait `FromPyObject` is required for function arguments, and `IntoPy` is required for function return values. Consult the tables in the following section to find the Rust types provided by PyO3 which implement these traits. ### Argument Types When accepting a function argument, it is possible to either use Rust library types or PyO3's Python-native types. (See the next section for discussion on when to use each.) The table below contains the Python type and the corresponding function argument types that will accept them: | Python | Rust | Rust (Python-native) | | ------------- |:-------------------------------:|:--------------------:| | `object` | - | `PyAny` | | `str` | `String`, `Cow`, `&str`, `char`, `OsString`, `PathBuf`, `Path` | `PyString`, `PyUnicode` | | `bytes` | `Vec`, `&[u8]`, `Cow<[u8]>` | `PyBytes` | | `bool` | `bool` | `PyBool` | | `int` | `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`, `num_bigint::BigInt`[^1], `num_bigint::BigUint`[^1] | `PyLong` | | `float` | `f32`, `f64` | `PyFloat` | | `complex` | `num_complex::Complex`[^2] | `PyComplex` | | `fractions.Fraction`| `num_rational::Ratio`[^8] | - | | `list[T]` | `Vec` | `PyList` | | `dict[K, V]` | `HashMap`, `BTreeMap`, `hashbrown::HashMap`[^3], `indexmap::IndexMap`[^4] | `PyDict` | | `tuple[T, U]` | `(T, U)`, `Vec` | `PyTuple` | | `set[T]` | `HashSet`, `BTreeSet`, `hashbrown::HashSet`[^3] | `PySet` | | `frozenset[T]` | `HashSet`, `BTreeSet`, `hashbrown::HashSet`[^3] | `PyFrozenSet` | | `bytearray` | `Vec`, `Cow<[u8]>` | `PyByteArray` | | `slice` | - | `PySlice` | | `type` | - | `PyType` | | `module` | - | `PyModule` | | `collections.abc.Buffer` | - | `PyBuffer` | | `datetime.datetime` | `SystemTime`, `chrono::DateTime`[^5], `chrono::NaiveDateTime`[^5] | `PyDateTime` | | `datetime.date` | `chrono::NaiveDate`[^5] | `PyDate` | | `datetime.time` | `chrono::NaiveTime`[^5] | `PyTime` | | `datetime.tzinfo` | `chrono::FixedOffset`[^5], `chrono::Utc`[^5], `chrono_tz::TimeZone`[^6] | `PyTzInfo` | | `datetime.timedelta` | `Duration`, `chrono::Duration`[^5] | `PyDelta` | | `decimal.Decimal` | `rust_decimal::Decimal`[^7] | - | | `ipaddress.IPv4Address` | `std::net::IpAddr`, `std::net::IpV4Addr` | - | | `ipaddress.IPv6Address` | `std::net::IpAddr`, `std::net::IpV6Addr` | - | | `os.PathLike ` | `PathBuf`, `Path` | `PyString`, `PyUnicode` | | `pathlib.Path` | `PathBuf`, `Path` | `PyString`, `PyUnicode` | | `typing.Optional[T]` | `Option` | - | | `typing.Sequence[T]` | `Vec` | `PySequence` | | `typing.Mapping[K, V]` | `HashMap`, `BTreeMap`, `hashbrown::HashMap`[^3], `indexmap::IndexMap`[^4] | `&PyMapping` | | `typing.Iterator[Any]` | - | `PyIterator` | | `typing.Union[...]` | See [`#[derive(FromPyObject)]`](traits.md#deriving-frompyobject-for-enums) | - | It is also worth remembering the following special types: | What | Description | | ---------------- | ------------------------------------- | | `Python<'py>` | A GIL token, used to pass to PyO3 constructors to prove ownership of the GIL. | | `Bound<'py, T>` | A Python object connected to the GIL lifetime. This provides access to most of PyO3's APIs. | | `Py` | A Python object isolated from the GIL lifetime. This can be sent to other threads. | | `PyObject` | An alias for `Py` | | `PyRef` | A `#[pyclass]` borrowed immutably. | | `PyRefMut` | A `#[pyclass]` borrowed mutably. | For more detail on accepting `#[pyclass]` values as function arguments, see [the section of this guide on Python Classes](../class.md). #### Using Rust library types vs Python-native types Using Rust library types as function arguments will incur a conversion cost compared to using the Python-native types. Using the Python-native types is almost zero-cost (they just require a type check similar to the Python builtin function `isinstance()`). However, once that conversion cost has been paid, the Rust standard library types offer a number of benefits: - You can write functionality in native-speed Rust code (free of Python's runtime costs). - You get better interoperability with the rest of the Rust ecosystem. - You can use `Python::allow_threads` to release the Python GIL and let other Python threads make progress while your Rust code is executing. - You also benefit from stricter type checking. For example you can specify `Vec`, which will only accept a Python `list` containing integers. The Python-native equivalent, `&PyList`, would accept a Python `list` containing Python objects of any type. For most PyO3 usage the conversion cost is worth paying to get these benefits. As always, if you're not sure it's worth it in your case, benchmark it! ### Returning Rust values to Python When returning values from functions callable from Python, [PyO3's smart pointers](../types.md#pyo3s-smart-pointers) (`Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`) can be used with zero cost. Because `Bound<'py, T>` and `Borrowed<'a, 'py, T>` have lifetime parameters, the Rust compiler may ask for lifetime annotations to be added to your function. See the [section of the guide dedicated to this](../types.md#function-argument-lifetimes). If your function is fallible, it should return `PyResult` or `Result` where `E` implements `From for PyErr`. This will raise a `Python` exception if the `Err` variant is returned. Finally, the following Rust types are also able to convert to Python as return values: | Rust type | Resulting Python Type | | ------------- |:-------------------------------:| | `String` | `str` | | `&str` | `str` | | `bool` | `bool` | | Any integer type (`i32`, `u32`, `usize`, etc) | `int` | | `f32`, `f64` | `float` | | `Option` | `Optional[T]` | | `(T, U)` | `Tuple[T, U]` | | `Vec` | `List[T]` | | `Cow<[u8]>` | `bytes` | | `HashMap` | `Dict[K, V]` | | `BTreeMap` | `Dict[K, V]` | | `HashSet` | `Set[T]` | | `BTreeSet` | `Set[T]` | | `Py` | `T` | | `Bound` | `T` | | `PyRef` | `T` | | `PyRefMut` | `T` | [^1]: Requires the `num-bigint` optional feature. [^2]: Requires the `num-complex` optional feature. [^3]: Requires the `hashbrown` optional feature. [^4]: Requires the `indexmap` optional feature. [^5]: Requires the `chrono` optional feature. [^6]: Requires the `chrono-tz` optional feature. [^7]: Requires the `rust_decimal` optional feature. [^8]: Requires the `num-rational` optional feature. pyo3/guide/src/conversions/traits.md0000644000175000017500000004064614661133735020531 0ustar jamespagejamespage## Conversion traits PyO3 provides some handy traits to convert between Python types and Rust types. ### `.extract()` and the `FromPyObject` trait The easiest way to convert a Python object to a Rust value is using `.extract()`. It returns a `PyResult` with a type error if the conversion fails, so usually you will use something like ```rust # use pyo3::prelude::*; # use pyo3::types::PyList; # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let list = PyList::new_bound(py, b"foo"); let v: Vec = list.extract()?; # assert_eq!(&v, &[102, 111, 111]); # Ok(()) # }) # } ``` This method is available for many Python object types, and can produce a wide variety of Rust types, which you can check out in the implementor list of [`FromPyObject`]. [`FromPyObject`] is also implemented for your own Rust types wrapped as Python objects (see [the chapter about classes](../class.md)). There, in order to both be able to operate on mutable references *and* satisfy Rust's rules of non-aliasing mutable references, you have to extract the PyO3 reference wrappers [`PyRef`] and [`PyRefMut`]. They work like the reference wrappers of `std::cell::RefCell` and ensure (at runtime) that Rust borrows are allowed. #### Deriving [`FromPyObject`] [`FromPyObject`] can be automatically derived for many kinds of structs and enums if the member types themselves implement `FromPyObject`. This even includes members with a generic type `T: FromPyObject`. Derivation for empty enums, enum variants and structs is not supported. #### Deriving [`FromPyObject`] for structs The derivation generates code that will attempt to access the attribute `my_string` on the Python object, i.e. `obj.getattr("my_string")`, and call `extract()` on the attribute. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyStruct { my_string: String, } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let module = PyModule::from_code_bound( # py, # "class Foo: # def __init__(self): # self.my_string = 'test'", # "", # "", # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rustystruct: RustyStruct = instance.extract()?; # assert_eq!(rustystruct.my_string, "test"); # Ok(()) # }) # } ``` By setting the `#[pyo3(item)]` attribute on the field, PyO3 will attempt to extract the value by calling the `get_item` method on the Python object. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item)] my_string: String, } # # use pyo3::types::PyDict; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let dict = PyDict::new_bound(py); # dict.set_item("my_string", "test")?; # # let rustystruct: RustyStruct = dict.extract()?; # assert_eq!(rustystruct.my_string, "test"); # Ok(()) # }) # } ``` The argument passed to `getattr` and `get_item` can also be configured: ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyStruct { #[pyo3(item("key"))] string_in_mapping: String, #[pyo3(attribute("name"))] string_attr: String, } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let module = PyModule::from_code_bound( # py, # "class Foo(dict): # def __init__(self): # self.name = 'test' # self['key'] = 'test2'", # "", # "", # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rustystruct: RustyStruct = instance.extract()?; # assert_eq!(rustystruct.string_attr, "test"); # assert_eq!(rustystruct.string_in_mapping, "test2"); # # Ok(()) # }) # } ``` This tries to extract `string_attr` from the attribute `name` and `string_in_mapping` from a mapping with the key `"key"`. The arguments for `attribute` are restricted to non-empty string literals while `item` can take any valid literal that implements `ToBorrowedObject`. You can use `#[pyo3(from_item_all)]` on a struct to extract every field with `get_item` method. In this case, you can't use `#[pyo3(attribute)]` or barely use `#[pyo3(item)]` on any field. However, using `#[pyo3(item("key"))]` to specify the key for a field is still allowed. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] #[pyo3(from_item_all)] struct RustyStruct { foo: String, bar: String, #[pyo3(item("foobar"))] baz: String, } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let py_dict = py.eval_bound("{'foo': 'foo', 'bar': 'bar', 'foobar': 'foobar'}", None, None)?; # let rustystruct: RustyStruct = py_dict.extract()?; # assert_eq!(rustystruct.foo, "foo"); # assert_eq!(rustystruct.bar, "bar"); # assert_eq!(rustystruct.baz, "foobar"); # # Ok(()) # }) # } ``` #### Deriving [`FromPyObject`] for tuple structs Tuple structs are also supported but do not allow customizing the extraction. The input is always assumed to be a Python tuple with the same length as the Rust type, the `n`th field is extracted from the `n`th item in the Python tuple. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTuple(String, String); # use pyo3::types::PyTuple; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let tuple = PyTuple::new_bound(py, vec!["test", "test2"]); # # let rustytuple: RustyTuple = tuple.extract()?; # assert_eq!(rustytuple.0, "test"); # assert_eq!(rustytuple.1, "test2"); # # Ok(()) # }) # } ``` Tuple structs with a single field are treated as wrapper types which are described in the following section. To override this behaviour and ensure that the input is in fact a tuple, specify the struct as ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTuple((String,)); # use pyo3::types::PyTuple; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let tuple = PyTuple::new_bound(py, vec!["test"]); # # let rustytuple: RustyTuple = tuple.extract()?; # assert_eq!((rustytuple.0).0, "test"); # # Ok(()) # }) # } ``` #### Deriving [`FromPyObject`] for wrapper types The `pyo3(transparent)` attribute can be used on structs with exactly one field. This results in extracting directly from the input object, i.e. `obj.extract()`, rather than trying to access an item or attribute. This behaviour is enabled per default for newtype structs and tuple-variants with a single field. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] struct RustyTransparentTupleStruct(String); #[derive(FromPyObject)] #[pyo3(transparent)] struct RustyTransparentStruct { inner: String, } # use pyo3::types::PyString; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let s = PyString::new_bound(py, "test"); # # let tup: RustyTransparentTupleStruct = s.extract()?; # assert_eq!(tup.0, "test"); # # let stru: RustyTransparentStruct = s.extract()?; # assert_eq!(stru.inner, "test"); # # Ok(()) # }) # } ``` #### Deriving [`FromPyObject`] for enums The `FromPyObject` derivation for enums generates code that tries to extract the variants in the order of the fields. As soon as a variant can be extracted successfully, that variant is returned. This makes it possible to extract Python union types like `str | int`. The same customizations and restrictions described for struct derivations apply to enum variants, i.e. a tuple variant assumes that the input is a Python tuple, and a struct variant defaults to extracting fields as attributes but can be configured in the same manner. The `transparent` attribute can be applied to single-field-variants. ```rust use pyo3::prelude::*; #[derive(FromPyObject)] # #[derive(Debug)] enum RustyEnum<'py> { Int(usize), // input is a positive int String(String), // input is a string IntTuple(usize, usize), // input is a 2-tuple with positive ints StringIntTuple(String, usize), // input is a 2-tuple with String and int Coordinates3d { // needs to be in front of 2d x: usize, y: usize, z: usize, }, Coordinates2d { // only gets checked if the input did not have `z` #[pyo3(attribute("x"))] a: usize, #[pyo3(attribute("y"))] b: usize, }, #[pyo3(transparent)] CatchAll(Bound<'py, PyAny>), // This extraction never fails } # # use pyo3::types::{PyBytes, PyString}; # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # { # let thing = 42_u8.to_object(py); # let rust_thing: RustyEnum<'_> = thing.extract(py)?; # # assert_eq!( # 42, # match rust_thing { # RustyEnum::Int(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = PyString::new_bound(py, "text"); # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # "text", # match rust_thing { # RustyEnum::String(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = (32_u8, 73_u8).to_object(py); # let rust_thing: RustyEnum<'_> = thing.extract(py)?; # # assert_eq!( # (32, 73), # match rust_thing { # RustyEnum::IntTuple(i, j) => (i, j), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let thing = ("foo", 73_u8).to_object(py); # let rust_thing: RustyEnum<'_> = thing.extract(py)?; # # assert_eq!( # (String::from("foo"), 73), # match rust_thing { # RustyEnum::StringIntTuple(i, j) => (i, j), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # { # let module = PyModule::from_code_bound( # py, # "class Foo(dict): # def __init__(self): # self.x = 0 # self.y = 1 # self.z = 2", # "", # "", # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rust_thing: RustyEnum<'_> = instance.extract()?; # # assert_eq!( # (0, 1, 2), # match rust_thing { # RustyEnum::Coordinates3d { x, y, z } => (x, y, z), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let module = PyModule::from_code_bound( # py, # "class Foo(dict): # def __init__(self): # self.x = 3 # self.y = 4", # "", # "", # )?; # # let class = module.getattr("Foo")?; # let instance = class.call0()?; # let rust_thing: RustyEnum<'_> = instance.extract()?; # # assert_eq!( # (3, 4), # match rust_thing { # RustyEnum::Coordinates2d { a, b } => (a, b), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = PyBytes::new_bound(py, b"text"); # let rust_thing: RustyEnum<'_> = thing.extract()?; # # assert_eq!( # b"text", # match rust_thing { # RustyEnum::CatchAll(ref i) => i.downcast::()?.as_bytes(), # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # Ok(()) # }) # } ``` If none of the enum variants match, a `PyTypeError` containing the names of the tested variants is returned. The names reported in the error message can be customized through the `#[pyo3(annotation = "name")]` attribute, e.g. to use conventional Python type names: ```rust use pyo3::prelude::*; #[derive(FromPyObject)] # #[derive(Debug)] enum RustyEnum { #[pyo3(transparent, annotation = "str")] String(String), #[pyo3(transparent, annotation = "int")] Int(isize), } # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # { # let thing = 42_u8.to_object(py); # let rust_thing: RustyEnum = thing.extract(py)?; # # assert_eq!( # 42, # match rust_thing { # RustyEnum::Int(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = "foo".to_object(py); # let rust_thing: RustyEnum = thing.extract(py)?; # # assert_eq!( # "foo", # match rust_thing { # RustyEnum::String(i) => i, # other => unreachable!("Error extracting: {:?}", other), # } # ); # } # # { # let thing = b"foo".to_object(py); # let error = thing.extract::(py).unwrap_err(); # assert!(error.is_instance_of::(py)); # } # # Ok(()) # }) # } ``` If the input is neither a string nor an integer, the error message will be: `"'' cannot be converted to 'str | int'"`. #### `#[derive(FromPyObject)]` Container Attributes - `pyo3(transparent)` - extract the field directly from the object as `obj.extract()` instead of `get_item()` or `getattr()` - Newtype structs and tuple-variants are treated as transparent per default. - only supported for single-field structs and enum variants - `pyo3(annotation = "name")` - changes the name of the failed variant in the generated error message in case of failure. - e.g. `pyo3("int")` reports the variant's type as `int`. - only supported for enum variants #### `#[derive(FromPyObject)]` Field Attributes - `pyo3(attribute)`, `pyo3(attribute("name"))` - retrieve the field from an attribute, possibly with a custom name specified as an argument - argument must be a string-literal. - `pyo3(item)`, `pyo3(item("key"))` - retrieve the field from a mapping, possibly with the custom key specified as an argument. - can be any literal that implements `ToBorrowedObject` - `pyo3(from_py_with = "...")` - apply a custom function to convert the field from Python the desired Rust type. - the argument must be the name of the function as a string. - the function signature must be `fn(&Bound) -> PyResult` where `T` is the Rust type of the argument. ### `IntoPy` This trait defines the to-python conversion for a Rust type. It is usually implemented as `IntoPy`, which is the trait needed for returning a value from `#[pyfunction]` and `#[pymethods]`. All types in PyO3 implement this trait, as does a `#[pyclass]` which doesn't use `extends`. Occasionally you may choose to implement this for custom types which are mapped to Python types _without_ having a unique python type. ```rust use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(PyObject); impl IntoPy for MyPyObjectWrapper { fn into_py(self, py: Python<'_>) -> PyObject { self.0 } } ``` ### The `ToPyObject` trait [`ToPyObject`] is a conversion trait that allows various objects to be converted into [`PyObject`]. `IntoPy` serves the same purpose, except that it consumes `self`. [`IntoPy`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPy.html [`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`ToPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.ToPyObject.html [`PyObject`]: {{#PYO3_DOCS_URL}}/pyo3/type.PyObject.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html pyo3/guide/src/class/0000775000175000017500000000000014661133735015426 5ustar jamespagejamespagepyo3/guide/src/class/object.md0000644000175000017500000002142314661133735017216 0ustar jamespagejamespage# Basic object customization Recall the `Number` class from the previous chapter: ```rust # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass] struct Number(i32); #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Self(value) } } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } ``` At this point Python code can import the module, access the class and create class instances - but nothing else. ```python from my_module import Number n = Number(5) print(n) ``` ```text ``` ### String representations It can't even print an user-readable representation of itself! We can fix that by defining the `__repr__` and `__str__` methods inside a `#[pymethods]` block. We do this by accessing the value contained inside `Number`. ```rust # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { // For `__repr__` we want to return a string that Python code could use to recreate // the `Number`, like `Number(5)` for example. fn __repr__(&self) -> String { // We use the `format!` macro to create a string. Its first argument is a // format string, followed by any number of parameters which replace the // `{}`'s in the format string. // // 👇 Tuple field access in Rust uses a dot format!("Number({})", self.0) } // `__str__` is generally used to create an "informal" representation, so we // just forward to `i32`'s `ToString` trait implementation to print a bare number. fn __str__(&self) -> String { self.0.to_string() } } ``` #### Accessing the class name In the `__repr__`, we used a hard-coded class name. This is sometimes not ideal, because if the class is subclassed in Python, we would like the repr to reflect the subclass name. This is typically done in Python code by accessing `self.__class__.__name__`. In order to be able to access the Python type information *and* the Rust struct, we need to use a `Bound` as the `self` argument. ```rust # use pyo3::prelude::*; # use pyo3::types::PyString; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __repr__(slf: &Bound<'_, Self>) -> PyResult { // This is the equivalent of `self.__class__.__name__` in Python. let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; // To access fields of the Rust struct, we need to borrow the `PyCell`. Ok(format!("{}({})", class_name, slf.borrow().0)) } } ``` ### Hashing Let's also implement hashing. We'll just hash the `i32`. For that we need a [`Hasher`]. The one provided by `std` is [`DefaultHasher`], which uses the [SipHash] algorithm. ```rust use std::collections::hash_map::DefaultHasher; // Required to call the `.hash` and `.finish` methods, which are defined on traits. use std::hash::{Hash, Hasher}; # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } } ``` To implement `__hash__` using the Rust [`Hash`] trait implementation, the `hash` option can be used. This option is only available for `frozen` classes to prevent accidental hash changes from mutating the object. If you need an `__hash__` implementation for a mutable class, use the manual method from above. This option also requires `eq`: According to the [Python docs](https://docs.python.org/3/reference/datamodel.html#object.__hash__) "If a class does not define an `__eq__()` method it should not define a `__hash__()` operation either" ```rust # use pyo3::prelude::*; # #[pyclass(frozen, eq, hash)] #[derive(PartialEq, Hash)] struct Number(i32); ``` > **Note**: When implementing `__hash__` and comparisons, it is important that the following property holds: > > ```text > k1 == k2 -> hash(k1) == hash(k2) > ``` > > In other words, if two keys are equal, their hashes must also be equal. In addition you must take > care that your classes' hash doesn't change during its lifetime. In this tutorial we do that by not > letting Python code change our `Number` class. In other words, it is immutable. > > By default, all `#[pyclass]` types have a default hash implementation from Python. > Types which should not be hashable can override this by setting `__hash__` to None. > This is the same mechanism as for a pure-Python class. This is done like so: > > ```rust > # use pyo3::prelude::*; > #[pyclass] > struct NotHashable {} > > #[pymethods] > impl NotHashable { > #[classattr] > const __hash__: Option> = None; > } > ``` ### Comparisons PyO3 supports the usual magic comparison methods available in Python such as `__eq__`, `__lt__` and so on. It is also possible to support all six operations at once with `__richcmp__`. This method will be called with a value of `CompareOp` depending on the operation. ```rust use pyo3::class::basic::CompareOp; # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } } ``` If you obtain the result by comparing two Rust values, as in this example, you can take a shortcut using `CompareOp::matches`: ```rust use pyo3::class::basic::CompareOp; # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool { op.matches(self.0.cmp(&other.0)) } } ``` It checks that the `std::cmp::Ordering` obtained from Rust's `Ord` matches the given `CompareOp`. Alternatively, you can implement just equality using `__eq__`: ```rust # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __eq__(&self, other: &Self) -> bool { self.0 == other.0 } } # fn main() -> PyResult<()> { # Python::with_gil(|py| { # let x = &Bound::new(py, Number(4))?; # let y = &Bound::new(py, Number(4))?; # assert!(x.eq(y)?); # assert!(!x.ne(y)?); # Ok(()) # }) # } ``` To implement `__eq__` using the Rust [`PartialEq`] trait implementation, the `eq` option can be used. ```rust # use pyo3::prelude::*; # #[pyclass(eq)] #[derive(PartialEq)] struct Number(i32); ``` To implement `__lt__`, `__le__`, `__gt__`, & `__ge__` using the Rust `PartialOrd` trait implementation, the `ord` option can be used. *Note: Requires `eq`.* ```rust # use pyo3::prelude::*; # #[pyclass(eq, ord)] #[derive(PartialEq, PartialOrd)] struct Number(i32); ``` ### Truthyness We'll consider `Number` to be `True` if it is nonzero: ```rust # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __bool__(&self) -> bool { self.0 != 0 } } ``` ### Final code ```rust use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use pyo3::prelude::*; use pyo3::class::basic::CompareOp; use pyo3::types::PyString; #[pyclass] struct Number(i32); #[pymethods] impl Number { #[new] fn new(value: i32) -> Self { Self(value) } fn __repr__(slf: &Bound<'_, Self>) -> PyResult { let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; Ok(format!("{}({})", class_name, slf.borrow().0)) } fn __str__(&self) -> String { self.0.to_string() } fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } fn __bool__(&self) -> bool { self.0 != 0 } } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } ``` [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html [`Hasher`]: https://doc.rust-lang.org/std/hash/trait.Hasher.html [`DefaultHasher`]: https://doc.rust-lang.org/std/collections/hash_map/struct.DefaultHasher.html [SipHash]: https://en.wikipedia.org/wiki/SipHash [`PartialEq`]: https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html pyo3/guide/src/class/protocols.md0000644000175000017500000004711114661133735017776 0ustar jamespagejamespage# Class customizations Python's object model defines several protocols for different object behavior, such as the sequence, mapping, and number protocols. Python classes support these protocols by implementing "magic" methods, such as `__str__` or `__repr__`. Because of the double-underscores surrounding their name, these are also known as "dunder" methods. PyO3 makes it possible for every magic method to be implemented in `#[pymethods]` just as they would be done in a regular Python class, with a few notable differences: - `__new__` and `__init__` are replaced by the [`#[new]` attribute](../class.md#constructor). - `__del__` is not yet supported, but may be in the future. - `__buffer__` and `__release_buffer__` are currently not supported and instead PyO3 supports [`__getbuffer__` and `__releasebuffer__`](#buffer-objects) methods (these predate [PEP 688](https://peps.python.org/pep-0688/#python-level-buffer-protocol)), again this may change in the future. - PyO3 adds [`__traverse__` and `__clear__`](#garbage-collector-integration) methods for controlling garbage collection. - The Python C-API which PyO3 is implemented upon requires many magic methods to have a specific function signature in C and be placed into special "slots" on the class type object. This limits the allowed argument and return types for these methods. They are listed in detail in the section below. If a magic method is not on the list above (for example `__init_subclass__`), then it should just work in PyO3. If this is not the case, please file a bug report. ## Magic Methods handled by PyO3 If a function name in `#[pymethods]` is a magic method which is known to need special handling, it will be automatically placed into the correct slot in the Python type object. The function name is taken from the usual rules for naming `#[pymethods]`: the `#[pyo3(name = "...")]` attribute is used if present, otherwise the Rust function name is used. The magic methods handled by PyO3 are very similar to the standard Python ones on [this page](https://docs.python.org/3/reference/datamodel.html#special-method-names) - in particular they are the subset which have slots as [defined here](https://docs.python.org/3/c-api/typeobj.html). When PyO3 handles a magic method, a couple of changes apply compared to other `#[pymethods]`: - The Rust function signature is restricted to match the magic method. - The `#[pyo3(signature = (...)]` and `#[pyo3(text_signature = "...")]` attributes are not allowed. The following sections list all magic methods for which PyO3 implements the necessary special handling. The given signatures should be interpreted as follows: - All methods take a receiver as first argument, shown as ``. It can be `&self`, `&mut self` or a `Bound` reference like `self_: PyRef<'_, Self>` and `self_: PyRefMut<'_, Self>`, as described [here](../class.md#inheritance). - An optional `Python<'py>` argument is always allowed as the first argument. - Return values can be optionally wrapped in `PyResult`. - `object` means that any type is allowed that can be extracted from a Python object (if argument) or converted to a Python object (if return value). - Other types must match what's given, e.g. `pyo3::basic::CompareOp` for `__richcmp__`'s second argument. - For the comparison and arithmetic methods, extraction errors are not propagated as exceptions, but lead to a return of `NotImplemented`. - For some magic methods, the return values are not restricted by PyO3, but checked by the Python interpreter. For example, `__str__` needs to return a string object. This is indicated by `object (Python type)`. ### Basic object customization - `__str__() -> object (str)` - `__repr__() -> object (str)` - `__hash__() -> isize` Objects that compare equal must have the same hash value. Any type up to 64 bits may be returned instead of `isize`, PyO3 will convert to an isize automatically (wrapping unsigned types like `u64` and `usize`).
Disabling Python's default hash By default, all `#[pyclass]` types have a default hash implementation from Python. Types which should not be hashable can override this by setting `__hash__` to `None`. This is the same mechanism as for a pure-Python class. This is done like so: ```rust # use pyo3::prelude::*; # #[pyclass] struct NotHashable {} #[pymethods] impl NotHashable { #[classattr] const __hash__: Option = None; } ```
- `__lt__(, object) -> object` - `__le__(, object) -> object` - `__eq__(, object) -> object` - `__ne__(, object) -> object` - `__gt__(, object) -> object` - `__ge__(, object) -> object` The implementations of Python's "rich comparison" operators `<`, `<=`, `==`, `!=`, `>` and `>=` respectively. _Note that implementing any of these methods will cause Python not to generate a default `__hash__` implementation, so consider also implementing `__hash__`._
Return type The return type will normally be `bool` or `PyResult`, however any Python object can be returned.
- `__richcmp__(, object, pyo3::basic::CompareOp) -> object` Implements Python comparison operations (`==`, `!=`, `<`, `<=`, `>`, and `>=`) in a single method. The `CompareOp` argument indicates the comparison operation being performed. You can use [`CompareOp::matches`] to adapt a Rust `std::cmp::Ordering` result to the requested comparison. _This method cannot be implemented in combination with any of `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__`, or `__ge__`._ _Note that implementing `__richcmp__` will cause Python not to generate a default `__hash__` implementation, so consider implementing `__hash__` when implementing `__richcmp__`._
Return type The return type will normally be `PyResult`, but any Python object can be returned. If you want to leave some operations unimplemented, you can return `py.NotImplemented()` for some of the operations: ```rust use pyo3::class::basic::CompareOp; # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> PyObject { match op { CompareOp::Eq => (self.0 == other.0).into_py(py), CompareOp::Ne => (self.0 != other.0).into_py(py), _ => py.NotImplemented(), } } } ``` If the second argument `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.
- `__getattr__(, object) -> object` - `__getattribute__(, object) -> object`
Differences between `__getattr__` and `__getattribute__` As in Python, `__getattr__` is only called if the attribute is not found by normal attribute lookup. `__getattribute__`, on the other hand, is called for *every* attribute access. If it wants to access existing attributes on `self`, it needs to be very careful not to introduce infinite recursion, and use `baseclass.__getattribute__()`.
- `__setattr__(, value: object) -> ()` - `__delattr__(, object) -> ()` Overrides attribute access. - `__bool__() -> bool` Determines the "truthyness" of an object. - `__call__(, ...) -> object` - here, any argument list can be defined as for normal `pymethods` ### Iterable objects Iterators can be defined using these methods: - `__iter__() -> object` - `__next__() -> Option or IterNextOutput` ([see details](#returning-a-value-from-iteration)) Returning `None` from `__next__` indicates that that there are no further items. Example: ```rust use pyo3::prelude::*; #[pyclass] struct MyIterator { iter: Box + Send>, } #[pymethods] impl MyIterator { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { slf.iter.next() } } ``` In many cases you'll have a distinction between the type being iterated over (i.e. the *iterable*) and the iterator it provides. In this case, the iterable only needs to implement `__iter__()` while the iterator must implement both `__iter__()` and `__next__()`. For example: ```rust # use pyo3::prelude::*; #[pyclass] struct Iter { inner: std::vec::IntoIter, } #[pymethods] impl Iter { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { slf.inner.next() } } #[pyclass] struct Container { iter: Vec, } #[pymethods] impl Container { fn __iter__(slf: PyRef<'_, Self>) -> PyResult> { let iter = Iter { inner: slf.iter.clone().into_iter(), }; Py::new(slf.py(), iter) } } # Python::with_gil(|py| { # let container = Container { iter: vec![1, 2, 3, 4] }; # let inst = pyo3::Py::new(py, container).unwrap(); # pyo3::py_run!(py, inst, "assert list(inst) == [1, 2, 3, 4]"); # pyo3::py_run!(py, inst, "assert list(iter(iter(inst))) == [1, 2, 3, 4]"); # }); ``` For more details on Python's iteration protocols, check out [the "Iterator Types" section of the library documentation](https://docs.python.org/library/stdtypes.html#iterator-types). #### Returning a value from iteration This guide has so far shown how to use `Option` to implement yielding values during iteration. In Python a generator can also return a value. To express this in Rust, PyO3 provides the [`IterNextOutput`] enum to both `Yield` values and `Return` a final value - see its docs for further details and an example. ### Awaitable objects - `__await__() -> object` - `__aiter__() -> object` - `__anext__() -> Option or IterANextOutput` ### Mapping & Sequence types The magic methods in this section can be used to implement Python container types. They are two main categories of container in Python: "mappings" such as `dict`, with arbitrary keys, and "sequences" such as `list` and `tuple`, with integer keys. The Python C-API which PyO3 is built upon has separate "slots" for sequences and mappings. When writing a `class` in pure Python, there is no such distinction in the implementation - a `__getitem__` implementation will fill the slots for both the mapping and sequence forms, for example. By default PyO3 reproduces the Python behaviour of filling both mapping and sequence slots. This makes sense for the "simple" case which matches Python, and also for sequences, where the mapping slot is used anyway to implement slice indexing. Mapping types usually will not want the sequence slots filled. Having them filled will lead to outcomes which may be unwanted, such as: - The mapping type will successfully cast to [`PySequence`]. This may lead to consumers of the type handling it incorrectly. - Python provides a default implementation of `__iter__` for sequences, which calls `__getitem__` with consecutive positive integers starting from 0 until an `IndexError` is returned. Unless the mapping only contains consecutive positive integer keys, this `__iter__` implementation will likely not be the intended behavior. Use the `#[pyclass(mapping)]` annotation to instruct PyO3 to only fill the mapping slots, leaving the sequence ones empty. This will apply to `__getitem__`, `__setitem__`, and `__delitem__`. Use the `#[pyclass(sequence)]` annotation to instruct PyO3 to fill the `sq_length` slot instead of the `mp_length` slot for `__len__`. This will help libraries such as `numpy` recognise the class as a sequence, however will also cause CPython to automatically add the sequence length to any negative indices before passing them to `__getitem__`. (`__getitem__`, `__setitem__` and `__delitem__` mapping slots are still used for sequences, for slice operations.) - `__len__() -> usize` Implements the built-in function `len()`. - `__contains__(, object) -> bool` Implements membership test operators. Should return true if `item` is in `self`, false otherwise. For objects that don’t define `__contains__()`, the membership test simply traverses the sequence until it finds a match.
Disabling Python's default contains By default, all `#[pyclass]` types with an `__iter__` method support a default implementation of the `in` operator. Types which do not want this can override this by setting `__contains__` to `None`. This is the same mechanism as for a pure-Python class. This is done like so: ```rust # use pyo3::prelude::*; # #[pyclass] struct NoContains {} #[pymethods] impl NoContains { #[classattr] const __contains__: Option = None; } ```
- `__getitem__(, object) -> object` Implements retrieval of the `self[a]` element. *Note:* Negative integer indexes are not handled specially by PyO3. However, for classes with `#[pyclass(sequence)]`, when a negative index is accessed via `PySequence::get_item`, the underlying C API already adjusts the index to be positive. - `__setitem__(, object, object) -> ()` Implements assignment to the `self[a]` element. Should only be implemented if elements can be replaced. Same behavior regarding negative indices as for `__getitem__`. - `__delitem__(, object) -> ()` Implements deletion of the `self[a]` element. Should only be implemented if elements can be deleted. Same behavior regarding negative indices as for `__getitem__`. * `fn __concat__(&self, other: impl FromPyObject) -> PyResult` Concatenates two sequences. Used by the `+` operator, after trying the numeric addition via the `__add__` and `__radd__` methods. * `fn __repeat__(&self, count: isize) -> PyResult` Repeats the sequence `count` times. Used by the `*` operator, after trying the numeric multiplication via the `__mul__` and `__rmul__` methods. * `fn __inplace_concat__(&self, other: impl FromPyObject) -> PyResult` Concatenates two sequences. Used by the `+=` operator, after trying the numeric addition via the `__iadd__` method. * `fn __inplace_repeat__(&self, count: isize) -> PyResult` Concatenates two sequences. Used by the `*=` operator, after trying the numeric multiplication via the `__imul__` method. ### Descriptors - `__get__(, object, object) -> object` - `__set__(, object, object) -> ()` - `__delete__(, object) -> ()` ### Numeric types Binary arithmetic operations (`+`, `-`, `*`, `@`, `/`, `//`, `%`, `divmod()`, `pow()` and `**`, `<<`, `>>`, `&`, `^`, and `|`) and their reflected versions: (If the `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.) - `__add__(, object) -> object` - `__radd__(, object) -> object` - `__sub__(, object) -> object` - `__rsub__(, object) -> object` - `__mul__(, object) -> object` - `__rmul__(, object) -> object` - `__matmul__(, object) -> object` - `__rmatmul__(, object) -> object` - `__floordiv__(, object) -> object` - `__rfloordiv__(, object) -> object` - `__truediv__(, object) -> object` - `__rtruediv__(, object) -> object` - `__divmod__(, object) -> object` - `__rdivmod__(, object) -> object` - `__mod__(, object) -> object` - `__rmod__(, object) -> object` - `__lshift__(, object) -> object` - `__rlshift__(, object) -> object` - `__rshift__(, object) -> object` - `__rrshift__(, object) -> object` - `__and__(, object) -> object` - `__rand__(, object) -> object` - `__xor__(, object) -> object` - `__rxor__(, object) -> object` - `__or__(, object) -> object` - `__ror__(, object) -> object` - `__pow__(, object, object) -> object` - `__rpow__(, object, object) -> object` In-place assignment operations (`+=`, `-=`, `*=`, `@=`, `/=`, `//=`, `%=`, `**=`, `<<=`, `>>=`, `&=`, `^=`, `|=`): - `__iadd__(, object) -> ()` - `__isub__(, object) -> ()` - `__imul__(, object) -> ()` - `__imatmul__(, object) -> ()` - `__itruediv__(, object) -> ()` - `__ifloordiv__(, object) -> ()` - `__imod__(, object) -> ()` - `__ipow__(, object, object) -> ()` - `__ilshift__(, object) -> ()` - `__irshift__(, object) -> ()` - `__iand__(, object) -> ()` - `__ixor__(, object) -> ()` - `__ior__(, object) -> ()` Unary operations (`-`, `+`, `abs()` and `~`): - `__pos__() -> object` - `__neg__() -> object` - `__abs__() -> object` - `__invert__() -> object` Coercions: - `__index__() -> object (int)` - `__int__() -> object (int)` - `__float__() -> object (float)` ### Buffer objects - `__getbuffer__(, *mut ffi::Py_buffer, flags) -> ()` - `__releasebuffer__(, *mut ffi::Py_buffer) -> ()` Errors returned from `__releasebuffer__` will be sent to `sys.unraiseablehook`. It is strongly advised to never return an error from `__releasebuffer__`, and if it really is necessary, to make best effort to perform any required freeing operations before returning. `__releasebuffer__` will not be called a second time; anything not freed will be leaked. ### Garbage Collector Integration If your type owns references to other Python objects, you will need to integrate with Python's garbage collector so that the GC is aware of those references. To do this, implement the two methods `__traverse__` and `__clear__`. These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API. `__traverse__` must call `visit.call()` for each reference to another Python object. `__clear__` must clear out any mutable references to other Python objects (thus breaking reference cycles). Immutable references do not have to be cleared, as every cycle must contain at least one mutable reference. - `__traverse__(, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>` - `__clear__() -> ()` Example: ```rust use pyo3::prelude::*; use pyo3::PyTraverseError; use pyo3::gc::PyVisit; #[pyclass] struct ClassWithGCSupport { obj: Option, } #[pymethods] impl ClassWithGCSupport { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { if let Some(obj) = &self.obj { visit.call(obj)? } Ok(()) } fn __clear__(&mut self) { // Clear reference, this decrements ref counter. self.obj = None; } } ``` Usually, an implementation of `__traverse__` should do nothing but calls to `visit.call`. Most importantly, safe access to the GIL is prohibited inside implementations of `__traverse__`, i.e. `Python::with_gil` will panic. > Note: these methods are part of the C API, PyPy does not necessarily honor them. If you are building for PyPy you should measure memory consumption to make sure you do not have runaway memory growth. See [this issue on the PyPy bug tracker](https://github.com/pypy/pypy/issues/3848). [`IterNextOutput`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/enum.IterNextOutput.html [`PySequence`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PySequence.html [`CompareOp::matches`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/enum.CompareOp.html#method.matches pyo3/guide/src/class/numeric.md0000644000175000017500000003041614661133735017414 0ustar jamespagejamespage# Emulating numeric types At this point we have a `Number` class that we can't actually do any math on! Before proceeding, we should think about how we want to handle overflows. There are three obvious solutions: - We can have infinite precision just like Python's `int`. However that would be quite boring - we'd be reinventing the wheel. - We can raise exceptions whenever `Number` overflows, but that makes the API painful to use. - We can wrap around the boundary of `i32`. This is the approach we'll take here. To do that we'll just forward to `i32`'s `wrapping_*` methods. ### Fixing our constructor Let's address the first overflow, in `Number`'s constructor: ```python from my_module import Number n = Number(1 << 1337) ``` ```text Traceback (most recent call last): File "example.py", line 3, in n = Number(1 << 1337) OverflowError: Python int too large to convert to C long ``` Instead of relying on the default [`FromPyObject`] extraction to parse arguments, we can specify our own extraction function, using the `#[pyo3(from_py_with = "...")]` attribute. Unfortunately PyO3 doesn't provide a way to wrap Python integers out of the box, but we can do a Python call to mask it and cast it to an `i32`. ```rust # #![allow(dead_code)] use pyo3::prelude::*; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; // 👇 This intentionally overflows! Ok(val as i32) } ``` We also add documentation, via `///` comments, which are visible to Python users. ```rust # #![allow(dead_code)] use pyo3::prelude::*; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; Ok(val as i32) } /// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not. /// It's not a story C would tell you. It's a Rust legend. #[pyclass(module = "my_module")] struct Number(i32); #[pymethods] impl Number { #[new] fn new(#[pyo3(from_py_with = "wrap")] value: i32) -> Self { Self(value) } } ``` With that out of the way, let's implement some operators: ```rust use pyo3::exceptions::{PyZeroDivisionError, PyValueError}; # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __add__(&self, other: &Self) -> Self { Self(self.0.wrapping_add(other.0)) } fn __sub__(&self, other: &Self) -> Self { Self(self.0.wrapping_sub(other.0)) } fn __mul__(&self, other: &Self) -> Self { Self(self.0.wrapping_mul(other.0)) } fn __truediv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __floordiv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __rshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __lshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } } ``` ### Unary arithmetic operations ```rust # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # #[pymethods] impl Number { fn __pos__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __neg__(&self) -> Self { Self(-self.0) } fn __abs__(&self) -> Self { Self(self.0.abs()) } fn __invert__(&self) -> Self { Self(!self.0) } } ``` ### Support for the `complex()`, `int()` and `float()` built-in functions. ```rust # use pyo3::prelude::*; # # #[pyclass] # struct Number(i32); # use pyo3::types::PyComplex; #[pymethods] impl Number { fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { self.0 as f64 } fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> { PyComplex::from_doubles_bound(py, self.0 as f64, 0.0) } } ``` We do not implement the in-place operations like `__iadd__` because we do not wish to mutate `Number`. Similarly we're not interested in supporting operations with different types, so we do not implement the reflected operations like `__radd__` either. Now Python can use our `Number` class: ```python from my_module import Number def hash_djb2(s: str): ''' A version of Daniel J. Bernstein's djb2 string hashing algorithm Like many hashing algorithms, it relies on integer wrapping. ''' n = Number(0) five = Number(5) for x in s: n = Number(ord(x)) + ((n << five) - n) return n assert hash_djb2('l50_50') == Number(-1152549421) ``` ### Final code ```rust use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use pyo3::exceptions::{PyValueError, PyZeroDivisionError}; use pyo3::prelude::*; use pyo3::class::basic::CompareOp; use pyo3::types::{PyComplex, PyString}; fn wrap(obj: &Bound<'_, PyAny>) -> PyResult { let val = obj.call_method1("__and__", (0xFFFFFFFF_u32,))?; let val: u32 = val.extract()?; Ok(val as i32) } /// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not. /// It's not a story C would tell you. It's a Rust legend. #[pyclass(module = "my_module")] struct Number(i32); #[pymethods] impl Number { #[new] fn new(#[pyo3(from_py_with = "wrap")] value: i32) -> Self { Self(value) } fn __repr__(slf: &Bound<'_, Self>) -> PyResult { // Get the class name dynamically in case `Number` is subclassed let class_name: Bound<'_, PyString> = slf.get_type().qualname()?; Ok(format!("{}({})", class_name, slf.borrow().0)) } fn __str__(&self) -> String { self.0.to_string() } fn __hash__(&self) -> u64 { let mut hasher = DefaultHasher::new(); self.0.hash(&mut hasher); hasher.finish() } fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult { match op { CompareOp::Lt => Ok(self.0 < other.0), CompareOp::Le => Ok(self.0 <= other.0), CompareOp::Eq => Ok(self.0 == other.0), CompareOp::Ne => Ok(self.0 != other.0), CompareOp::Gt => Ok(self.0 > other.0), CompareOp::Ge => Ok(self.0 >= other.0), } } fn __bool__(&self) -> bool { self.0 != 0 } fn __add__(&self, other: &Self) -> Self { Self(self.0.wrapping_add(other.0)) } fn __sub__(&self, other: &Self) -> Self { Self(self.0.wrapping_sub(other.0)) } fn __mul__(&self, other: &Self) -> Self { Self(self.0.wrapping_mul(other.0)) } fn __truediv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __floordiv__(&self, other: &Self) -> PyResult { match self.0.checked_div(other.0) { Some(i) => Ok(Self(i)), None => Err(PyZeroDivisionError::new_err("division by zero")), } } fn __rshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __lshift__(&self, other: &Self) -> PyResult { match other.0.try_into() { Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))), Err(_) => Err(PyValueError::new_err("negative shift count")), } } fn __xor__(&self, other: &Self) -> Self { Self(self.0 ^ other.0) } fn __or__(&self, other: &Self) -> Self { Self(self.0 | other.0) } fn __and__(&self, other: &Self) -> Self { Self(self.0 & other.0) } fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { self.0 as f64 } fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> { PyComplex::from_doubles_bound(py, self.0 as f64, 0.0) } } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } # const SCRIPT: &'static str = r#" # def hash_djb2(s: str): # n = Number(0) # five = Number(5) # # for x in s: # n = Number(ord(x)) + ((n << five) - n) # return n # # assert hash_djb2('l50_50') == Number(-1152549421) # assert hash_djb2('logo') == Number(3327403) # assert hash_djb2('horizon') == Number(1097468315) # # # assert Number(2) + Number(2) == Number(4) # assert Number(2) + Number(2) != Number(5) # # assert Number(13) - Number(7) == Number(6) # assert Number(13) - Number(-7) == Number(20) # # assert Number(13) / Number(7) == Number(1) # assert Number(13) // Number(7) == Number(1) # # assert Number(13) * Number(7) == Number(13*7) # # assert Number(13) > Number(7) # assert Number(13) < Number(20) # assert Number(13) == Number(13) # assert Number(13) >= Number(7) # assert Number(13) <= Number(20) # assert Number(13) == Number(13) # # # assert (True if Number(1) else False) # assert (False if Number(0) else True) # # # assert int(Number(13)) == 13 # assert float(Number(13)) == 13 # assert Number.__doc__ == "Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not.\nIt's not a story C would tell you. It's a Rust legend." # assert Number(12345234523452) == Number(1498514748) # try: # import inspect # assert inspect.signature(Number).__str__() == '(value)' # except ValueError: # # Not supported with `abi3` before Python 3.10 # pass # assert Number(1337).__str__() == '1337' # assert Number(1337).__repr__() == 'Number(1337)' "#; # # use pyo3::PyTypeInfo; # # fn main() -> PyResult<()> { # Python::with_gil(|py| -> PyResult<()> { # let globals = PyModule::import_bound(py, "__main__")?.dict(); # globals.set_item("Number", Number::type_object_bound(py))?; # # py.run_bound(SCRIPT, Some(&globals), None)?; # Ok(()) # }) # } ``` ## Appendix: Writing some unsafe code At the beginning of this chapter we said that PyO3 doesn't provide a way to wrap Python integers out of the box but that's a half truth. There's not a PyO3 API for it, but there's a Python C API function that does: ```c unsigned long PyLong_AsUnsignedLongMask(PyObject *obj) ``` We can call this function from Rust by using [`pyo3::ffi::PyLong_AsUnsignedLongMask`]. This is an *unsafe* function, which means we have to use an unsafe block to call it and take responsibility for upholding the contracts of this function. Let's review those contracts: - The GIL must be held. If it's not, calling this function causes a data race. - The pointer must be valid, i.e. it must be properly aligned and point to a valid Python object. Let's create that helper function. The signature has to be `fn(&Bound<'_, PyAny>) -> PyResult`. - `&Bound<'_, PyAny>` represents a checked borrowed reference, so the pointer derived from it is valid (and not null). - Whenever we have borrowed references to Python objects in scope, it is guaranteed that the GIL is held. This reference is also where we can get a [`Python`] token to use in our call to [`PyErr::take`]. ```rust # #![allow(dead_code)] use std::os::raw::c_ulong; use pyo3::prelude::*; use pyo3::ffi; fn wrap(obj: &Bound<'_, PyAny>) -> Result { let py: Python<'_> = obj.py(); unsafe { let ptr = obj.as_ptr(); let ret: c_ulong = ffi::PyLong_AsUnsignedLongMask(ptr); if ret == c_ulong::MAX { if let Some(err) = PyErr::take(py) { return Err(err); } } Ok(ret as i32) } } ``` [`PyErr::take`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.PyErr.html#method.take [`Python`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html [`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`pyo3::ffi::PyLong_AsUnsignedLongMask`]: {{#PYO3_DOCS_URL}}/pyo3/ffi/fn.PyLong_AsUnsignedLongMask.html pyo3/guide/src/class/call.md0000644000175000017500000001040714661133735016663 0ustar jamespagejamespage# Emulating callable objects Classes can be callable if they have a `#[pymethod]` named `__call__`. This allows instances of a class to behave similar to functions. This method's signature must look like `__call__(, ...) -> object` - here, any argument list can be defined as for normal pymethods ### Example: Implementing a call counter The following pyclass is a basic decorator - its constructor takes a Python object as argument and calls that object when called. An equivalent Python implementation is linked at the end. An example crate containing this pyclass can be found [here](https://github.com/PyO3/pyo3/tree/main/examples/decorator) ```rust,ignore {{#include ../../../examples/decorator/src/lib.rs}} ``` Python code: ```python {{#include ../../../examples/decorator/tests/example.py}} ``` Output: ```text say_hello has been called 1 time(s). hello say_hello has been called 2 time(s). hello say_hello has been called 3 time(s). hello say_hello has been called 4 time(s). hello ``` ### Pure Python implementation A Python implementation of this looks similar to the Rust version: ```python class Counter: def __init__(self, wraps): self.count = 0 self.wraps = wraps def __call__(self, *args, **kwargs): self.count += 1 print(f"{self.wraps.__name__} has been called {self.count} time(s)") self.wraps(*args, **kwargs) ``` Note that it can also be implemented as a higher order function: ```python def Counter(wraps): count = 0 def call(*args, **kwargs): nonlocal count count += 1 print(f"{wraps.__name__} has been called {count} time(s)") return wraps(*args, **kwargs) return call ``` ### What is the `Cell` for? A [previous implementation] used a normal `u64`, which meant it required a `&mut self` receiver to update the count: ```rust,ignore #[pyo3(signature = (*args, **kwargs))] fn __call__( &mut self, py: Python<'_>, args: &Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult> { self.count += 1; let name = self.wraps.getattr(py, "__name__")?; println!("{} has been called {} time(s).", name, self.count); // After doing something, we finally forward the call to the wrapped function let ret = self.wraps.call(py, args, kwargs)?; // We could do something with the return value of // the function before returning it Ok(ret) } ``` The problem with this is that the `&mut self` receiver means PyO3 has to borrow it exclusively, and hold this borrow across the`self.wraps.call(py, args, kwargs)` call. This call returns control to the user's Python code which is free to call arbitrary things, *including* the decorated function. If that happens PyO3 is unable to create a second unique borrow and will be forced to raise an exception. As a result, something innocent like this will raise an exception: ```py @Counter def say_hello(): if say_hello.count < 2: print(f"hello from decorator") say_hello() # RuntimeError: Already borrowed ``` The implementation in this chapter fixes that by never borrowing exclusively; all the methods take `&self` as receivers, of which multiple may exist simultaneously. This requires a shared counter and the easiest way to do that is to use [`Cell`], so that's what is used here. This shows the dangers of running arbitrary Python code - note that "running arbitrary Python code" can be far more subtle than the example above: - Python's asynchronous executor may park the current thread in the middle of Python code, even in Python code that *you* control, and let other Python code run. - Dropping arbitrary Python objects may invoke destructors defined in Python (`__del__` methods). - Calling Python's C-api (most PyO3 apis call C-api functions internally) may raise exceptions, which may allow Python code in signal handlers to run. This is especially important if you are writing unsafe code; Python code must never be able to cause undefined behavior. You must ensure that your Rust code is in a consistent state before doing any of the above things. [previous implementation]: https://github.com/PyO3/pyo3/discussions/2598 "Thread Safe Decorator · Discussion #2598 · PyO3/pyo3" [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html "Cell in std::cell - Rust" pyo3/guide/src/python-typing-hints.md0000644000175000017500000002123614661133735020621 0ustar jamespagejamespage# Typing and IDE hints for your Python package PyO3 provides an easy to use interface to code native Python libraries in Rust. The accompanying Maturin allows you to build and publish them as a package. Yet, for a better user experience, Python libraries should provide typing hints and documentation for all public entities, so that IDEs can show them during development and type analyzing tools such as `mypy` can use them to properly verify the code. Currently the best solution for the problem is to manually maintain `*.pyi` files and ship them along with the package. There is a sketch of a roadmap towards completing [the `experimental-inspect` feature](./features.md#experimental-inspect) which may eventually lead to automatic type annotations generated by PyO3. This needs more testing and implementation, please see [issue #2454](https://github.com/PyO3/pyo3/issues/2454). ## Introduction to `pyi` files `pyi` files (an abbreviation for `Python Interface`) are called "stub files" in most of the documentation related to them. A very good definition of what it is can be found in [old MyPy documentation](https://github.com/python/mypy/wiki/Creating-Stubs-For-Python-Modules): > A stubs file only contains a description of the public interface of the module without any implementations. There is also [extensive documentation on type stubs on the official Python typing documentation](https://typing.readthedocs.io/en/latest/source/stubs.html). Most Python developers probably already encountered them when trying to use their IDE's "Go to Definition" function on any builtin type. For example, the definitions of a few standard exceptions look like this: ```python class BaseException(object): args: Tuple[Any, ...] __cause__: BaseException | None __context__: BaseException | None __suppress_context__: bool __traceback__: TracebackType | None def __init__(self, *args: object) -> None: ... def __str__(self) -> str: ... def __repr__(self) -> str: ... def with_traceback(self: _TBE, tb: TracebackType | None) -> _TBE: ... class SystemExit(BaseException): code: int class Exception(BaseException): ... class StopIteration(Exception): value: Any ``` As we can see, those are not full definitions containing implementation, but just a description of the interface. It is usually all that the user of the library needs. ### What do the PEPs say? At the time of writing this documentation, the `pyi` files are referenced in three PEPs. [PEP8 - Style Guide for Python Code - #Function Annotations](https://www.python.org/dev/peps/pep-0008/#function-annotations) (last point) recommends all third party library creators to provide stub files as the source of knowledge about the package for type checker tools. > (...) it is expected that users of third party library packages may want to run type checkers over those packages. For this purpose [PEP 484](https://www.python.org/dev/peps/pep-0484) recommends the use of stub files: .pyi files that are read by the type checker in preference of the corresponding .py files. (...) [PEP484 - Type Hints - #Stub Files](https://www.python.org/dev/peps/pep-0484/#stub-files) defines stub files as follows. > Stub files are files containing type hints that are only for use by the type checker, not at runtime. It contains a specification for them (highly recommended reading, since it contains at least one thing that is not used in normal Python code) and also some general information about where to store the stub files. [PEP561 - Distributing and Packaging Type Information](https://www.python.org/dev/peps/pep-0561/) describes in detail how to build packages that will enable type checking. In particular it contains information about how the stub files must be distributed in order for type checkers to use them. ## How to do it? [PEP561](https://www.python.org/dev/peps/pep-0561/) recognizes three ways of distributing type information: * `inline` - the typing is placed directly in source (`py`) files; * `separate package with stub files` - the typing is placed in `pyi` files distributed in their own, separate package; * `in-package stub files` - the typing is placed in `pyi` files distributed in the same package as source files. The first way is tricky with PyO3 since we do not have `py` files. When it has been investigated and necessary changes are implemented, this document will be updated. The second way is easy to do, and the whole work can be fully separated from the main library code. The example repo for the package with stub files can be found in [PEP561 references section](https://www.python.org/dev/peps/pep-0561/#references): [Stub package repository](https://github.com/ethanhs/stub-package) The third way is described below. ### Including `pyi` files in your PyO3/Maturin build package When source files are in the same package as stub files, they should be placed next to each other. We need a way to do that with Maturin. Also, in order to mark our package as typing-enabled we need to add an empty file named `py.typed` to the package. #### If you do not have other Python files If you do not need to add any other Python files apart from `pyi` to the package, Maturin provides a way to do most of the work for you. As documented in the [Maturin Guide](https://github.com/PyO3/maturin/#mixed-rustpython-projects), the only thing you need to do is to create a stub file for your module named `.pyi` in your project root and Maturin will do the rest. ```text my-rust-project/ ├── Cargo.toml ├── my_project.pyi # <<< add type stubs for Rust functions in the my_project module here ├── pyproject.toml └── src └── lib.rs ``` For an example `pyi` file see the [`my_project.pyi` content](#my_projectpyi-content) section. #### If you need other Python files If you need to add other Python files apart from `pyi` to the package, you can do it also, but that requires some more work. Maturin provides an easy way to add files to a package ([documentation](https://github.com/PyO3/maturin/blob/0dee40510083c03607834c821eea76964140a126/Readme.md#mixed-rustpython-projects)). You just need to create a folder with the name of your module next to the `Cargo.toml` file (for customization see documentation linked above). The folder structure would be: ```text my-project ├── Cargo.toml ├── my_project │ ├── __init__.py │ ├── my_project.pyi │ ├── other_python_file.py │ └── py.typed ├── pyproject.toml ├── Readme.md └── src └── lib.rs ``` Let's go a little bit more into detail regarding the files inside the package folder. ##### `__init__.py` content As we now specify our own package content, we have to provide the `__init__.py` file, so the folder is treated as a package and we can import things from it. We can always use the same content that Maturin creates for us if we do not specify a Python source folder. For PyO3 bindings it would be: ```python from .my_project import * ``` That way everything that is exposed by our native module can be imported directly from the package. ##### `py.typed` requirement As stated in [PEP561](https://www.python.org/dev/peps/pep-0561/): > Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing. This marker applies recursively: if a top-level package includes it, all its sub-packages MUST support type checking as well. If we do not include that file, some IDEs might still use our `pyi` files to show hints, but the type checkers might not. MyPy will raise an error in this situation: ```text error: Skipping analyzing "my_project": found module but no type hints or library stubs ``` The file is just a marker file, so it should be empty. ##### `my_project.pyi` content Our module stub file. This document does not aim at describing how to write them, since you can find a lot of documentation on it, starting from the already quoted [PEP484](https://www.python.org/dev/peps/pep-0484/#stub-files). The example can look like this: ```python class Car: """ A class representing a car. :param body_type: the name of body type, e.g. hatchback, sedan :param horsepower: power of the engine in horsepower """ def __init__(self, body_type: str, horsepower: int) -> None: ... @classmethod def from_unique_name(cls, name: str) -> 'Car': """ Creates a Car based on unique name :param name: model name of a car to be created :return: a Car instance with default data """ def best_color(self) -> str: """ Gets the best color for the car. :return: the name of the color our great algorithm thinks is the best for this car """ ``` pyo3/guide/src/memory.md0000644000175000017500000002674714661133735016171 0ustar jamespagejamespage# Memory management
⚠️ Warning: API update in progress 🛠️ PyO3 0.21 has introduced a significant new API, termed the "Bound" API after the new smart pointer `Bound`. This section on memory management is heavily weighted towards the now-deprecated "GIL Refs" API, which suffered from the drawbacks detailed here as well as CPU overheads. See [the smart pointer types](./types.md#pyo3s-smart-pointers) for description on the new, simplified, memory model of the Bound API, which is built as a thin wrapper on Python reference counting.
Rust and Python have very different notions of memory management. Rust has a strict memory model with concepts of ownership, borrowing, and lifetimes, where memory is freed at predictable points in program execution. Python has a looser memory model in which variables are reference-counted with shared, mutable state by default. A global interpreter lock (GIL) is needed to prevent race conditions, and a garbage collector is needed to break reference cycles. Memory in Python is freed eventually by the garbage collector, but not usually in a predictable way. PyO3 bridges the Rust and Python memory models with two different strategies for accessing memory allocated on Python's heap from inside Rust. These are GIL Refs such as `&'py PyAny`, and GIL-independent `Py` smart pointers. ## GIL-bound memory PyO3's GIL Refs such as `&'py PyAny` make PyO3 more ergonomic to use by ensuring that their lifetime can never be longer than the duration the Python GIL is held. This means that most of PyO3's API can assume the GIL is held. (If PyO3 could not assume this, every PyO3 API would need to take a `Python` GIL token to prove that the GIL is held.) This allows us to write very simple and easy-to-understand programs like this: ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // py.eval() is part of the GIL Refs API let hello = py .eval("\"Hello World!\"", None, None)? .downcast::()?; println!("Python says: {}", hello); Ok(()) })?; # Ok(()) # } ``` Internally, calling `Python::with_gil()` creates a `GILPool` which owns the memory pointed to by the reference. In the example above, the lifetime of the reference `hello` is bound to the `GILPool`. When the `with_gil()` closure ends the `GILPool` is also dropped and the Python reference counts of the variables it owns are decreased, releasing them to the Python garbage collector. Most of the time we don't have to think about this, but consider the following: ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] Python::with_gil(|py| -> PyResult<()> { for _ in 0..10 { #[allow(deprecated)] // py.eval() is part of the GIL Refs API let hello = py .eval("\"Hello World!\"", None, None)? .downcast::()?; println!("Python says: {}", hello); } // There are 10 copies of `hello` on Python's heap here. Ok(()) })?; # Ok(()) # } ``` We might assume that the `hello` variable's memory is freed at the end of each loop iteration, but in fact we create 10 copies of `hello` on Python's heap. This may seem surprising at first, but it is completely consistent with Rust's memory model. The `hello` variable is dropped at the end of each loop, but it is only a reference to the memory owned by the `GILPool`, and its lifetime is bound to the `GILPool`, not the for loop. The `GILPool` isn't dropped until the end of the `with_gil()` closure, at which point the 10 copies of `hello` are finally released to the Python garbage collector.
⚠️ Warning: `GILPool` is no longer the preferred way to manage memory with PyO3 🛠️ PyO3 0.21 has introduced a new API known as the Bound API, which doesn't have the same surprising results. Instead, each `Bound` smart pointer releases the Python reference immediately on drop. See [the smart pointer types](./types.md#pyo3s-smart-pointers) for more details.
In general we don't want unbounded memory growth during loops! One workaround is to acquire and release the GIL with each iteration of the loop. ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] for _ in 0..10 { Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // py.eval() is part of the GIL Refs API let hello = py .eval("\"Hello World!\"", None, None)? .downcast::()?; println!("Python says: {}", hello); Ok(()) })?; // only one copy of `hello` at a time } # Ok(()) # } ``` It might not be practical or performant to acquire and release the GIL so many times. Another workaround is to work with the `GILPool` object directly, but this is unsafe. ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] Python::with_gil(|py| -> PyResult<()> { for _ in 0..10 { #[allow(deprecated)] // `new_pool` is not needed in code not using the GIL Refs API let pool = unsafe { py.new_pool() }; let py = pool.python(); #[allow(deprecated)] // py.eval() is part of the GIL Refs API let hello = py .eval("\"Hello World!\"", None, None)? .downcast::()?; println!("Python says: {}", hello); } Ok(()) })?; # Ok(()) # } ``` The unsafe method `Python::new_pool` allows you to create a nested `GILPool` from which you can retrieve a new `py: Python` GIL token. Variables created with this new GIL token are bound to the nested `GILPool` and will be released when the nested `GILPool` is dropped. Here, the nested `GILPool` is dropped at the end of each loop iteration, before the `with_gil()` closure ends. When doing this, you must be very careful to ensure that once the `GILPool` is dropped you do not retain access to any owned references created after the `GILPool` was created. Read the documentation for `Python::new_pool()` for more information on safety. This memory management can also be applicable when writing extension modules. `#[pyfunction]` and `#[pymethods]` will create a `GILPool` which lasts the entire function call, releasing objects when the function returns. Most functions only create a few objects, meaning this doesn't have a significant impact. Occasionally functions with long complex loops may need to use `Python::new_pool` as shown above.
⚠️ Warning: `GILPool` is no longer the preferred way to manage memory with PyO3 🛠️ PyO3 0.21 has introduced a new API known as the Bound API, which doesn't have the same surprising results. Instead, each `Bound` smart pointer releases the Python reference immediately on drop. See [the smart pointer types](./types.md#pyo3s-smart-pointers) for more details.
## GIL-independent memory Sometimes we need a reference to memory on Python's heap that can outlive the GIL. Python's `Py` is analogous to `Arc`, but for variables whose memory is allocated on Python's heap. Cloning a `Py` increases its internal reference count just like cloning `Arc`. The smart pointer can outlive the "GIL is held" period in which it was created. It isn't magic, though. We need to reacquire the GIL to access the memory pointed to by the `Py`. What happens to the memory when the last `Py` is dropped and its reference count reaches zero? It depends whether or not we are holding the GIL. ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // py.eval() is part of the GIL Refs API let hello: Py = py.eval("\"Hello World!\"", None, None)?.extract()?; #[allow(deprecated)] // as_ref is part of the GIL Refs API { println!("Python says: {}", hello.as_ref(py)); } Ok(()) })?; # Ok(()) # } ``` At the end of the `Python::with_gil()` closure `hello` is dropped, and then the GIL is dropped. Since `hello` is dropped while the GIL is still held by the current thread, its memory is released to the Python garbage collector immediately. This example wasn't very interesting. We could have just used a GIL-bound `&PyString` reference. What happens when the last `Py` is dropped while we are *not* holding the GIL? ```rust # #![allow(unused_imports, dead_code)] # #[cfg(not(pyo3_disable_reference_pool))] { # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] # { let hello: Py = Python::with_gil(|py| { #[allow(deprecated)] // py.eval() is part of the GIL Refs API py.eval("\"Hello World!\"", None, None)?.extract() })?; // Do some stuff... // Now sometime later in the program we want to access `hello`. Python::with_gil(|py| { #[allow(deprecated)] // as_ref is part of the deprecated "GIL Refs" API. let hello = hello.as_ref(py); println!("Python says: {}", hello); }); // Now we're done with `hello`. drop(hello); // Memory *not* released here. // Sometime later we need the GIL again for something... Python::with_gil(|py| // Memory for `hello` is released here. # () ); # } # Ok(()) # } # } ``` When `hello` is dropped *nothing* happens to the pointed-to memory on Python's heap because nothing _can_ happen if we're not holding the GIL. Fortunately, the memory isn't leaked. If the `pyo3_disable_reference_pool` conditional compilation flag is not enabled, PyO3 keeps track of the memory internally and will release it the next time we acquire the GIL. We can avoid the delay in releasing memory if we are careful to drop the `Py` while the GIL is held. ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] # { #[allow(deprecated)] // py.eval() is part of the GIL Refs API let hello: Py = Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?; // Do some stuff... // Now sometime later in the program: Python::with_gil(|py| { #[allow(deprecated)] // as_ref is part of the GIL Refs API { println!("Python says: {}", hello.as_ref(py)); } drop(hello); // Memory released here. }); # } # Ok(()) # } ``` We could also have used `Py::into_ref()`, which consumes `self`, instead of `Py::as_ref()`. But note that in addition to being slower than `as_ref()`, `into_ref()` binds the memory to the lifetime of the `GILPool`, which means that rather than being released immediately, the memory will not be released until the GIL is dropped. ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyString; # fn main() -> PyResult<()> { # #[cfg(feature = "gil-refs")] # { #[allow(deprecated)] // py.eval() is part of the GIL Refs API let hello: Py = Python::with_gil(|py| py.eval("\"Hello World!\"", None, None)?.extract())?; // Do some stuff... // Now sometime later in the program: Python::with_gil(|py| { #[allow(deprecated)] // into_ref is part of the GIL Refs API { println!("Python says: {}", hello.into_ref(py)); } // Memory not released yet. // Do more stuff... // Memory released here at end of `with_gil()` closure. }); # } # Ok(()) # } ``` pyo3/guide/src/function.md0000644000175000017500000001762014661133735016474 0ustar jamespagejamespage# Python functions The `#[pyfunction]` attribute is used to define a Python function from a Rust function. Once defined, the function needs to be added to a [module](./module.md) using the `wrap_pyfunction!` macro. The following example defines a function called `double` in a Python module called `my_extension`: ```rust use pyo3::prelude::*; #[pyfunction] fn double(x: usize) -> usize { x * 2 } #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?) } ``` This chapter of the guide explains full usage of the `#[pyfunction]` attribute. In this first section, the following topics are covered: - [Function options](#function-options) - [`#[pyo3(name = "...")]`](#name) - [`#[pyo3(signature = (...))]`](#signature) - [`#[pyo3(text_signature = "...")]`](#text_signature) - [`#[pyo3(pass_module)]`](#pass_module) - [Per-argument options](#per-argument-options) - [Advanced function patterns](#advanced-function-patterns) - [`#[pyfn]` shorthand](#pyfn-shorthand) There are also additional sections on the following topics: - [Function Signatures](./function/signature.md) ## Function options The `#[pyo3]` attribute can be used to modify properties of the generated Python function. It can take any combination of the following options: - `#[pyo3(name = "...")]` Overrides the name exposed to Python. In the following example, the Rust function `no_args_py` will be added to the Python module `module_with_functions` as the Python function `no_args`: ```rust use pyo3::prelude::*; #[pyfunction] #[pyo3(name = "no_args")] fn no_args_py() -> usize { 42 } #[pymodule] fn module_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(no_args_py, m)?) } # Python::with_gil(|py| { # let m = pyo3::wrap_pymodule!(module_with_functions)(py); # assert!(m.getattr(py, "no_args").is_ok()); # assert!(m.getattr(py, "no_args_py").is_err()); # }); ``` - `#[pyo3(signature = (...))]` Defines the function signature in Python. See [Function Signatures](./function/signature.md). - `#[pyo3(text_signature = "...")]` Overrides the PyO3-generated function signature visible in Python tooling (such as via [`inspect.signature`]). See the [corresponding topic in the Function Signatures subchapter](./function/signature.md#making-the-function-signature-available-to-python). - `#[pyo3(pass_module)]` Set this option to make PyO3 pass the containing module as the first argument to the function. It is then possible to use the module in the function body. The first argument **must** be of type `&Bound<'_, PyModule>`, `Bound<'_, PyModule>`, or `Py`. The following example creates a function `pyfunction_with_module` which returns the containing module's name (i.e. `module_with_fn`): ```rust use pyo3::prelude::*; use pyo3::types::PyString; #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module<'py>( module: &Bound<'py, PyModule>, ) -> PyResult> { module.name() } #[pymodule] fn module_with_fn(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?) } ``` ## Per-argument options The `#[pyo3]` attribute can be used on individual arguments to modify properties of them in the generated function. It can take any combination of the following options: - `#[pyo3(from_py_with = "...")]` Set this on an option to specify a custom function to convert the function argument from Python to the desired Rust type, instead of using the default `FromPyObject` extraction. The function signature must be `fn(&Bound<'_, PyAny>) -> PyResult` where `T` is the Rust type of the argument. The following example uses `from_py_with` to convert the input Python object to its length: ```rust use pyo3::prelude::*; fn get_length(obj: &Bound<'_, PyAny>) -> PyResult { obj.len() } #[pyfunction] fn object_length(#[pyo3(from_py_with = "get_length")] argument: usize) -> usize { argument } # Python::with_gil(|py| { # let f = pyo3::wrap_pyfunction_bound!(object_length)(py).unwrap(); # assert_eq!(f.call1((vec![1, 2, 3],)).unwrap().extract::().unwrap(), 3); # }); ``` ## Advanced function patterns ### Calling Python functions in Rust You can pass Python `def`'d functions and built-in functions to Rust functions [`PyFunction`] corresponds to regular Python functions while [`PyCFunction`] describes built-ins such as `repr()`. You can also use [`Bound<'_, PyAny>::is_callable`] to check if you have a callable object. `is_callable` will return `true` for functions (including lambdas), methods and objects with a `__call__` method. You can call the object with [`Bound<'_, PyAny>::call`] with the args as first parameter and the kwargs (or `None`) as second parameter. There are also [`Bound<'_, PyAny>::call0`] with no args and [`Bound<'_, PyAny>::call1`] with only positional args. ### Calling Rust functions in Python The ways to convert a Rust function into a Python object vary depending on the function: - Named functions, e.g. `fn foo()`: add `#[pyfunction]` and then use [`wrap_pyfunction!`] to get the corresponding [`PyCFunction`]. - Anonymous functions (or closures), e.g. `foo: fn()` either: - use a `#[pyclass]` struct which stores the function as a field and implement `__call__` to call the stored function. - use `PyCFunction::new_closure` to create an object directly from the function. [`Bound<'_, PyAny>::is_callable`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.is_callable [`Bound<'_, PyAny>::call`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call [`Bound<'_, PyAny>::call0`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call0 [`Bound<'_, PyAny>::call1`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call1 [`wrap_pyfunction!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.wrap_pyfunction.html [`PyFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFunction.html [`PyCFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyCFunction.html ### Accessing the FFI functions In order to make Rust functions callable from Python, PyO3 generates an `extern "C"` function whose exact signature depends on the Rust signature. (PyO3 chooses the optimal Python argument passing convention.) It then embeds the call to the Rust function inside this FFI-wrapper function. This wrapper handles extraction of the regular arguments and the keyword arguments from the input `PyObject`s. The `wrap_pyfunction` macro can be used to directly get a `Bound` given a `#[pyfunction]` and a `Bound`: `wrap_pyfunction!(rust_fun, module)`. ## `#[pyfn]` shorthand There is a shorthand to `#[pyfunction]` and `wrap_pymodule!`: the function can be placed inside the module definition and annotated with `#[pyfn]`. To simplify PyO3, it is expected that `#[pyfn]` may be removed in a future release (See [#694](https://github.com/PyO3/pyo3/issues/694)). An example of `#[pyfn]` is below: ```rust use pyo3::prelude::*; #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m)] fn double(x: usize) -> usize { x * 2 } Ok(()) } ``` `#[pyfn(m)]` is just syntactic sugar for `#[pyfunction]`, and takes all the same options documented in the rest of this chapter. The code above is expanded to the following: ```rust use pyo3::prelude::*; #[pymodule] fn my_extension(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfunction] fn double(x: usize) -> usize { x * 2 } m.add_function(wrap_pyfunction!(double, m)?) } ``` [`inspect.signature`]: https://docs.python.org/3/library/inspect.html#inspect.signature pyo3/guide/src/types.md0000644000175000017500000006045314661133735016015 0ustar jamespagejamespage# Python object types PyO3 offers two main sets of types to interact with Python objects. This section of the guide expands into detail about these types and how to choose which to use. The first set of types are the [smart pointers][smart-pointers] which all Python objects are wrapped in. These are `Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`. The [first section below](#pyo3s-smart-pointers) expands on each of these in detail and why there are three of them. The second set of types are types which fill in the generic parameter `T` of the smart pointers. The most common is `PyAny`, which represents any Python object (similar to Python's `typing.Any`). There are also concrete types for many Python built-in types, such as `PyList`, `PyDict`, and `PyTuple`. User defined `#[pyclass]` types also fit this category. The [second section below](#concrete-python-types) expands on how to use these types. Before PyO3 0.21, PyO3's main API to interact with Python objects was a deprecated API known as the "GIL Refs" API, containing reference types such as `&PyAny`, `&PyList`, and `&PyCell` for user-defined `#[pyclass]` types. The [third section below](#the-gil-refs-api) details this deprecated API. ## PyO3's smart pointers PyO3's API offers three generic smart pointers: `Py`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>`. For each of these the type parameter `T` will be filled by a [concrete Python type](#concrete-python-types). For example, a Python list object can be represented by `Py`, `Bound<'py, PyList>`, and `Borrowed<'a, 'py, PyList>`. These smart pointers behave differently due to their lifetime parameters. `Py` has no lifetime parameters, `Bound<'py, T>` has [the `'py` lifetime](./python-from-rust.md#the-py-lifetime) as a parameter, and `Borrowed<'a, 'py, T>` has the `'py` lifetime plus an additional lifetime `'a` to denote the lifetime it is borrowing data for. (You can read more about these lifetimes in the subsections below). Python objects are reference counted, like [`std::sync::Arc`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html). A major reason for these smart pointers is to bring Python's reference counting to a Rust API. The recommendation of when to use each of these smart pointers is as follows: - Use `Bound<'py, T>` for as much as possible, as it offers the most efficient and complete API. - Use `Py` mostly just for storage inside Rust `struct`s which do not want to or can't add a lifetime parameter for `Bound<'py, T>`. - `Borrowed<'a, 'py, T>` is almost never used. It is occasionally present at the boundary between Rust and the Python interpreter, for example when borrowing data from Python tuples (which is safe because they are immutable). The sections below also explain these smart pointers in a little more detail. ### `Py` (and `PyObject`) [`Py`][Py] is the foundational smart pointer in PyO3's API. The type parameter `T` denotes the type of the Python object. Very frequently this is `PyAny`, meaning any Python object. This is so common that `Py` has a type alias `PyObject`. Because `Py` is not bound to [the `'py` lifetime](./python-from-rust.md#the-py-lifetime), it is the type to use when storing a Python object inside a Rust `struct` or `enum` which do not want to have a lifetime parameter. In particular, [`#[pyclass]`][pyclass] types are not permitted to have a lifetime, so `Py` is the correct type to store Python objects inside them. The lack of binding to the `'py` lifetime also carries drawbacks: - Almost all methods on `Py` require a `Python<'py>` token as the first argument - Other functionality, such as [`Drop`][Drop], needs to check at runtime for attachment to the Python GIL, at a small performance cost Because of the drawbacks `Bound<'py, T>` is preferred for many of PyO3's APIs. In particular, `Bound<'py, T>` is the better for function arguments. To convert a `Py` into a `Bound<'py, T>`, the `Py::bind` and `Py::into_bound` methods are available. `Bound<'py, T>` can be converted back into `Py` using [`Bound::unbind`]. ### `Bound<'py, T>` [`Bound<'py, T>`][Bound] is the counterpart to `Py` which is also bound to the `'py` lifetime. It can be thought of as equivalent to the Rust tuple `(Python<'py>, Py)`. By having the binding to the `'py` lifetime, `Bound<'py, T>` can offer the complete PyO3 API at maximum efficiency. This means that in almost all cases where `Py` is not necessary for lifetime reasons, `Bound<'py, T>` should be used. `Bound<'py, T>` engages in Python reference counting. This means that `Bound<'py, T>` owns a Python object. Rust code which just wants to borrow a Python object should use a shared reference `&Bound<'py, T>`. Just like `std::sync::Arc`, using `.clone()` and `drop()` will cheaply increment and decrement the reference count of the object (just in this case, the reference counting is implemented by the Python interpreter itself). To give an example of how `Bound<'py, T>` is PyO3's primary API type, consider the following Python code: ```python def example(): x = list() # create a Python list x.append(1) # append the integer 1 to it y = x # create a second reference to the list del x # delete the original reference ``` Using PyO3's API, and in particular `Bound<'py, PyList>`, this code translates into the following Rust code: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn example<'py>(py: Python<'py>) -> PyResult<()> { let x: Bound<'py, PyList> = PyList::empty_bound(py); x.append(1)?; let y: Bound<'py, PyList> = x.clone(); // y is a new reference to the same list drop(x); // release the original reference x Ok(()) } # Python::with_gil(example).unwrap(); ``` Or, without the type annotations: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn example(py: Python<'_>) -> PyResult<()> { let x = PyList::empty_bound(py); x.append(1)?; let y = x.clone(); drop(x); Ok(()) } # Python::with_gil(example).unwrap(); ``` #### Function argument lifetimes Because the `'py` lifetime often appears in many function arguments as part of the `Bound<'py, T>` smart pointer, the Rust compiler will often require annotations of input and output lifetimes. This occurs when the function output has at least one lifetime, and there is more than one lifetime present on the inputs. To demonstrate, consider this function which takes accepts Python objects and applies the [Python `+` operation][PyAnyMethods::add] to them: ```rust,compile_fail # use pyo3::prelude::*; fn add(left: &'_ Bound<'_, PyAny>, right: &'_ Bound<'_, PyAny>) -> PyResult> { left.add(right) } ``` Because the Python `+` operation might raise an exception, this function returns `PyResult>`. It doesn't need ownership of the inputs, so it takes `&Bound<'_, PyAny>` shared references. To demonstrate the point, all lifetimes have used the wildcard `'_` to allow the Rust compiler to attempt to infer them. Because there are four input lifetimes (two lifetimes of the shared references, and two `'py` lifetimes unnamed inside the `Bound<'_, PyAny>` pointers), the compiler cannot reason about which must be connected to the output. The correct way to solve this is to add the `'py` lifetime as a parameter for the function, and name all the `'py` lifetimes inside the `Bound<'py, PyAny>` smart pointers. For the shared references, it's also fine to reduce `&'_` to just `&`. The working end result is below: ```rust # use pyo3::prelude::*; fn add<'py>( left: &Bound<'py, PyAny>, right: &Bound<'py, PyAny>, ) -> PyResult> { left.add(right) } # Python::with_gil(|py| { # let s = pyo3::types::PyString::new_bound(py, "s"); # assert!(add(&s, &s).unwrap().eq("ss").unwrap()); # }) ``` If naming the `'py` lifetime adds unwanted complexity to the function signature, it is also acceptable to return `PyObject` (aka `Py`), which has no lifetime. The cost is instead paid by a slight increase in implementation complexity, as seen by the introduction of a call to [`Bound::unbind`]: ```rust # use pyo3::prelude::*; fn add(left: &Bound<'_, PyAny>, right: &Bound<'_, PyAny>) -> PyResult { let output: Bound<'_, PyAny> = left.add(right)?; Ok(output.unbind()) } # Python::with_gil(|py| { # let s = pyo3::types::PyString::new_bound(py, "s"); # assert!(add(&s, &s).unwrap().bind(py).eq("ss").unwrap()); # }) ``` ### `Borrowed<'a, 'py, T>` [`Borrowed<'a, 'py, T>`][Borrowed] is an advanced type used just occasionally at the edge of interaction with the Python interpreter. It can be thought of as analogous to the shared reference `&'a Bound<'py, T>`. The difference is that `Borrowed<'a, 'py, T>` is just a smart pointer rather than a reference-to-a-smart-pointer, which is a helpful reduction in indirection in specific interactions with the Python interpreter. `Borrowed<'a, 'py, T>` dereferences to `Bound<'py, T>`, so all methods on `Bound<'py, T>` are available on `Borrowed<'a, 'py, T>`. An example where `Borrowed<'a, 'py, T>` is used is in [`PyTupleMethods::get_borrowed_item`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html#tymethod.get_item): ```rust use pyo3::prelude::*; use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // Create a new tuple with the elements (0, 1, 2) let t = PyTuple::new_bound(py, [0, 1, 2]); for i in 0..=2 { let entry: Borrowed<'_, 'py, PyAny> = t.get_borrowed_item(i)?; // `PyAnyMethods::extract` is available on `Borrowed` // via the dereference to `Bound` let value: usize = entry.extract()?; assert_eq!(i, value); } # Ok(()) # } # Python::with_gil(example).unwrap(); ``` ### Casting between smart pointer types To convert between `Py` and `Bound<'py, T>` use the `bind()` / `into_bound()` methods. Use the `as_unbound()` / `unbind()` methods to go back from `Bound<'py, T>` to `Py`. ```rust,ignore let obj: Py = ...; let bound: &Bound<'py, PyAny> = obj.bind(py); let bound: Bound<'py, PyAny> = obj.into_bound(py); let obj: &Py = bound.as_unbound(); let obj: Py = bound.unbind(); ``` To convert between `Bound<'py, T>` and `Borrowed<'a, 'py, T>` use the `as_borrowed()` method. `Borrowed<'a, 'py, T>` has a deref coercion to `Bound<'py, T>`. Use the `to_owned()` method to increment the Python reference count and to create a new `Bound<'py, T>` from the `Borrowed<'a, 'py, T>`. ```rust,ignore let bound: Bound<'py, PyAny> = ...; let borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed(); // deref coercion let bound: &Bound<'py, PyAny> = &borrowed; // create a new Bound by increase the Python reference count let bound: Bound<'py, PyAny> = borrowed.to_owned(); ``` To convert between `Py` and `Borrowed<'a, 'py, T>` use the `bind_borrowed()` method. Use either `as_unbound()` or `.to_owned().unbind()` to go back to `Py` from `Borrowed<'a, 'py, T>`, via `Bound<'py, T>`. ```rust,ignore let obj: Py = ...; let borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed(); // via deref coercion to Bound and then using Bound::as_unbound let obj: &Py = borrowed.as_unbound(); // via a new Bound by increasing the Python reference count, and unbind it let obj: Py = borrowed.to_owned().unbind(). ``` ## Concrete Python types In all of `Py`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`, the type parameter `T` denotes the type of the Python object referred to by the smart pointer. This parameter `T` can be filled by: - [`PyAny`][PyAny], which represents any Python object, - Native Python types such as `PyList`, `PyTuple`, and `PyDict`, and - [`#[pyclass]`][pyclass] types defined from Rust The following subsections covers some further detail about how to work with these types: - the APIs that are available for these concrete types, - how to cast `Bound<'py, T>` to a specific concrete type, and - how to get Rust data out of a `Bound<'py, T>`. ### Using APIs for concrete Python types Each concrete Python type such as `PyAny`, `PyTuple` and `PyDict` exposes its API on the corresponding bound smart pointer `Bound<'py, PyAny>`, `Bound<'py, PyTuple>` and `Bound<'py, PyDict>`. Each type's API is exposed as a trait: [`PyAnyMethods`], [`PyTupleMethods`], [`PyDictMethods`], and so on for all concrete types. Using traits rather than associated methods on the `Bound` smart pointer is done for a couple of reasons: - Clarity of documentation: each trait gets its own documentation page in the PyO3 API docs. If all methods were on the `Bound` smart pointer directly, the vast majority of PyO3's API would be on a single, extremely long, documentation page. - Consistency: downstream code implementing Rust APIs for existing Python types can also follow this pattern of using a trait. Downstream code would not be allowed to add new associated methods directly on the `Bound` type. - Future design: it is hoped that a future Rust with [arbitrary self types](https://github.com/rust-lang/rust/issues/44874) will remove the need for these traits in favour of placing the methods directly on `PyAny`, `PyTuple`, `PyDict`, and so on. These traits are all included in the `pyo3::prelude` module, so with the glob import `use pyo3::prelude::*` the full PyO3 API is made available to downstream code. The following function accesses the first item in the input Python list, using the `.get_item()` method from the `PyListMethods` trait: ```rust use pyo3::prelude::*; use pyo3::types::PyList; fn get_first_item<'py>(list: &Bound<'py, PyList>) -> PyResult> { list.get_item(0) } # Python::with_gil(|py| { # let l = PyList::new_bound(py, ["hello world"]); # assert!(get_first_item(&l).unwrap().eq("hello world").unwrap()); # }) ``` ### Casting between Python object types To cast `Bound<'py, T>` smart pointers to some other type, use the [`.downcast()`][PyAnyMethods::downcast] family of functions. This converts `&Bound<'py, T>` to a different `&Bound<'py, U>`, without transferring ownership. There is also [`.downcast_into()`][PyAnyMethods::downcast_into] to convert `Bound<'py, T>` to `Bound<'py, U>` with transfer of ownership. These methods are available for all types `T` which implement the [`PyTypeCheck`] trait. Casting to `Bound<'py, PyAny>` can be done with `.as_any()` or `.into_any()`. For example, the following snippet shows how to cast `Bound<'py, PyAny>` to `Bound<'py, PyTuple>`: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = PyTuple::empty_bound(py).into_any(); // use `.downcast()` to cast to `PyTuple` without transferring ownership let _: &Bound<'py, PyTuple> = obj.downcast()?; // use `.downcast_into()` to cast to `PyTuple` with transfer of ownership let _: Bound<'py, PyTuple> = obj.downcast_into()?; # Ok(()) # } # Python::with_gil(example).unwrap() ``` Custom [`#[pyclass]`][pyclass] types implement [`PyTypeCheck`], so `.downcast()` also works for these types. The snippet below is the same as the snippet above casting instead to a custom type `MyClass`: ```rust use pyo3::prelude::*; #[pyclass] struct MyClass {} # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = Bound::new(py, MyClass {})?.into_any(); // use `.downcast()` to cast to `MyClass` without transferring ownership let _: &Bound<'py, MyClass> = obj.downcast()?; // use `.downcast_into()` to cast to `MyClass` with transfer of ownership let _: Bound<'py, MyClass> = obj.downcast_into()?; # Ok(()) # } # Python::with_gil(example).unwrap() ``` ### Extracting Rust data from Python objects To extract Rust data from Python objects, use [`.extract()`][PyAnyMethods::extract] instead of `.downcast()`. This method is available for all types which implement the [`FromPyObject`] trait. For example, the following snippet extracts a Rust tuple of integers from a Python tuple: ```rust # use pyo3::prelude::*; # use pyo3::types::PyTuple; # fn example<'py>(py: Python<'py>) -> PyResult<()> { // create a new Python `tuple`, and use `.into_any()` to erase the type let obj: Bound<'py, PyAny> = PyTuple::new_bound(py, [1, 2, 3]).into_any(); // extracting the Python `tuple` to a rust `(i32, i32, i32)` tuple let (x, y, z) = obj.extract::<(i32, i32, i32)>()?; assert_eq!((x, y, z), (1, 2, 3)); # Ok(()) # } # Python::with_gil(example).unwrap() ``` To avoid copying data, [`#[pyclass]`][pyclass] types can directly reference Rust data stored within the Python objects without needing to `.extract()`. See the [corresponding documentation in the class section of the guide](./class.md#bound-and-interior-mutability) for more detail. ## The GIL Refs API The GIL Refs API was PyO3's primary API prior to PyO3 0.21. The main difference was that instead of the `Bound<'py, PyAny>` smart pointer, the "GIL Reference" `&'py PyAny` was used. (This was similar for other Python types.) As of PyO3 0.21, the GIL Refs API is deprecated. See the [migration guide](./migration.md#from-020-to-021) for details on how to upgrade. The following sections note some historical detail about the GIL Refs API. ### [`PyAny`][PyAny] **Represented:** a Python object of unspecified type. In the GIL Refs API, this was only accessed as the GIL Ref `&'py PyAny`. **Used:** `&'py PyAny` was used to refer to some Python object when the GIL lifetime was available for the whole duration access was needed. For example, intermediate values and arguments to `pyfunction`s or `pymethod`s implemented in Rust where any type is allowed. **Conversions:** For a `&PyAny` object reference `any` where the underlying object is a Python-native type such as a list: ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyList; # #[cfg(feature = "gil-refs")] # Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // PyList::empty is part of the deprecated "GIL Refs" API. let obj: &PyAny = PyList::empty(py); // To &PyList with PyAny::downcast let _: &PyList = obj.downcast()?; // To Py (aka PyObject) with .into() let _: Py = obj.into(); // To Py with PyAny::extract let _: Py = obj.extract()?; # Ok(()) # }).unwrap(); ``` For a `&PyAny` object reference `any` where the underlying object is a `#[pyclass]`: ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # #[pyclass] #[derive(Clone)] struct MyClass { } # #[cfg(feature = "gil-refs")] # Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // into_ref is part of the deprecated GIL Refs API let obj: &PyAny = Py::new(py, MyClass {})?.into_ref(py); // To &PyCell with PyAny::downcast #[allow(deprecated)] // &PyCell is part of the deprecated GIL Refs API let _: &PyCell = obj.downcast()?; // To Py (aka PyObject) with .into() let _: Py = obj.into(); // To Py with PyAny::extract let _: Py = obj.extract()?; // To MyClass with PyAny::extract, if MyClass: Clone let _: MyClass = obj.extract()?; // To PyRef<'_, MyClass> or PyRefMut<'_, MyClass> with PyAny::extract let _: PyRef<'_, MyClass> = obj.extract()?; let _: PyRefMut<'_, MyClass> = obj.extract()?; # Ok(()) # }).unwrap(); ``` ### `PyTuple`, `PyDict`, and many more **Represented:** a native Python object of known type. In the GIL Refs API, they were only accessed as the GIL Refs `&'py PyTuple`, `&'py PyDict`. **Used:** `&'py PyTuple` and similar were used to operate with native Python types while holding the GIL. Like `PyAny`, this is the most convenient form to use for function arguments and intermediate values. These GIL Refs implement `Deref`, so they all expose the same methods which can be found on `PyAny`. To see all Python types exposed by `PyO3` consult the [`pyo3::types`][pyo3::types] module. **Conversions:** ```rust # #![allow(unused_imports)] # use pyo3::prelude::*; # use pyo3::types::PyList; # #[cfg(feature = "gil-refs")] # Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // PyList::empty is part of the deprecated "GIL Refs" API. let list = PyList::empty(py); // Use methods from PyAny on all Python types with Deref implementation let _ = list.repr()?; // To &PyAny automatically with Deref implementation let _: &PyAny = list; // To &PyAny explicitly with .as_ref() #[allow(deprecated)] // as_ref is part of the deprecated "GIL Refs" API. let _: &PyAny = list.as_ref(); // To Py with .into() or Py::from() let _: Py = list.into(); // To PyObject with .into() or .to_object(py) let _: PyObject = list.into(); # Ok(()) # }).unwrap(); ``` ### `Py` and `PyObject` **Represented:** a GIL-independent reference to a Python object. This can be a Python native type (like `PyTuple`), or a `pyclass` type implemented in Rust. The most commonly-used variant, `Py`, is also known as `PyObject`. **Used:** Whenever you want to carry around references to a Python object without caring about a GIL lifetime. For example, storing Python object references in a Rust struct that outlives the Python-Rust FFI boundary, or returning objects from functions implemented in Rust back to Python. Can be cloned using Python reference counts with `.clone()`. ### `PyCell` **Represented:** a reference to a Rust object (instance of `PyClass`) wrapped in a Python object. The cell part is an analog to stdlib's [`RefCell`][RefCell] to allow access to `&mut` references. **Used:** for accessing pure-Rust API of the instance (members and functions taking `&SomeType` or `&mut SomeType`) while maintaining the aliasing rules of Rust references. Like PyO3's Python native types, the GIL Ref `&PyCell` implements `Deref`, so it also exposed all of the methods on `PyAny`. **Conversions:** `PyCell` was used to access `&T` and `&mut T` via `PyRef` and `PyRefMut` respectively. ```rust #![allow(unused_imports)] # use pyo3::prelude::*; # #[pyclass] struct MyClass { } # #[cfg(feature = "gil-refs")] # Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // &PyCell is part of the deprecated GIL Refs API let cell: &PyCell = PyCell::new(py, MyClass {})?; // To PyRef with .borrow() or .try_borrow() let py_ref: PyRef<'_, MyClass> = cell.try_borrow()?; let _: &MyClass = &*py_ref; # drop(py_ref); // To PyRefMut with .borrow_mut() or .try_borrow_mut() let mut py_ref_mut: PyRefMut<'_, MyClass> = cell.try_borrow_mut()?; let _: &mut MyClass = &mut *py_ref_mut; # Ok(()) # }).unwrap(); ``` `PyCell` was also accessed like a Python-native type. ```rust #![allow(unused_imports)] # use pyo3::prelude::*; # #[pyclass] struct MyClass { } # #[cfg(feature = "gil-refs")] # Python::with_gil(|py| -> PyResult<()> { #[allow(deprecated)] // &PyCell is part of the deprecate GIL Refs API let cell: &PyCell = PyCell::new(py, MyClass {})?; // Use methods from PyAny on PyCell with Deref implementation let _ = cell.repr()?; // To &PyAny automatically with Deref implementation let _: &PyAny = cell; // To &PyAny explicitly with .as_ref() #[allow(deprecated)] // as_ref is part of the deprecated "GIL Refs" API. let _: &PyAny = cell.as_ref(); # Ok(()) # }).unwrap(); ``` [Bound]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html [`Bound::unbind`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.unbind [Py]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html [PyAnyMethods::add]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.add [PyAnyMethods::extract]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.extract [PyAnyMethods::downcast]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.downcast [PyAnyMethods::downcast_into]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.downcast_into [`PyTypeCheck`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeCheck.html [`PyAnyMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html [`PyDictMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyDictMethods.html [`PyTupleMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html [pyclass]: class.md [Borrowed]: {{#PYO3_DOCS_URL}}/pyo3/struct.Borrowed.html [Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html [eval]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval [clone_ref]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html#method.clone_ref [pyo3::types]: {{#PYO3_DOCS_URL}}/pyo3/types/index.html [PyAny]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html [PyList_append]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyList.html#method.append [RefCell]: https://doc.rust-lang.org/std/cell/struct.RefCell.html [smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html pyo3/guide/src/faq.md0000644000175000017500000002043114661133735015410 0ustar jamespagejamespage# Frequently Asked Questions and troubleshooting Sorry that you're having trouble using PyO3. If you can't find the answer to your problem in the list below, you can also reach out for help on [GitHub Discussions](https://github.com/PyO3/pyo3/discussions) and on [Discord](https://discord.gg/33kcChzH7f). ## I'm experiencing deadlocks using PyO3 with lazy_static or once_cell! `lazy_static` and `once_cell::sync` both use locks to ensure that initialization is performed only by a single thread. Because the Python GIL is an additional lock this can lead to deadlocks in the following way: 1. A thread (thread A) which has acquired the Python GIL starts initialization of a `lazy_static` value. 2. The initialization code calls some Python API which temporarily releases the GIL e.g. `Python::import`. 3. Another thread (thread B) acquires the Python GIL and attempts to access the same `lazy_static` value. 4. Thread B is blocked, because it waits for `lazy_static`'s initialization to lock to release. 5. Thread A is blocked, because it waits to re-acquire the GIL which thread B still holds. 6. Deadlock. PyO3 provides a struct [`GILOnceCell`] which works equivalently to `OnceCell` but relies solely on the Python GIL for thread safety. This means it can be used in place of `lazy_static` or `once_cell` where you are experiencing the deadlock described above. See the documentation for [`GILOnceCell`] for an example how to use it. [`GILOnceCell`]: {{#PYO3_DOCS_URL}}/pyo3/sync/struct.GILOnceCell.html ## I can't run `cargo test`; or I can't build in a Cargo workspace: I'm having linker issues like "Symbol not found" or "Undefined reference to _PyExc_SystemError"! Currently, [#340](https://github.com/PyO3/pyo3/issues/340) causes `cargo test` to fail with linking errors when the `extension-module` feature is activated. Linking errors can also happen when building in a cargo workspace where a different crate also uses PyO3 (see [#2521](https://github.com/PyO3/pyo3/issues/2521)). For now, there are three ways we can work around these issues. 1. Make the `extension-module` feature optional. Build with `maturin develop --features "extension-module"` ```toml [dependencies.pyo3] {{#PYO3_CRATE_VERSION}} [features] extension-module = ["pyo3/extension-module"] ``` 2. Make the `extension-module` feature optional and default. Run tests with `cargo test --no-default-features`: ```toml [dependencies.pyo3] {{#PYO3_CRATE_VERSION}} [features] extension-module = ["pyo3/extension-module"] default = ["extension-module"] ``` 3. If you are using a [`pyproject.toml`](https://maturin.rs/metadata.html) file to control maturin settings, add the following section: ```toml [tool.maturin] features = ["pyo3/extension-module"] # Or for maturin 0.12: # cargo-extra-args = ["--features", "pyo3/extension-module"] ``` ## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory! The Rust book suggests to [put integration tests inside a `tests/` directory](https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests). For a PyO3 `extension-module` project where the `crate-type` is set to `"cdylib"` in your `Cargo.toml`, the compiler won't be able to find your crate and will display errors such as `E0432` or `E0463`: ```text error[E0432]: unresolved import `my_crate` --> tests/test_my_crate.rs:1:5 | 1 | use my_crate; | ^^^^^^^^^^^^ no external crate `my_crate` ``` The best solution is to make your crate types include both `rlib` and `cdylib`: ```toml # Cargo.toml [lib] crate-type = ["cdylib", "rlib"] ``` ## Ctrl-C doesn't do anything while my Rust code is executing! This is because Ctrl-C raises a SIGINT signal, which is handled by the calling Python process by simply setting a flag to action upon later. This flag isn't checked while Rust code called from Python is executing, only once control returns to the Python interpreter. You can give the Python interpreter a chance to process the signal properly by calling `Python::check_signals`. It's good practice to call this function regularly if you have a long-running Rust function so that your users can cancel it. ## `#[pyo3(get)]` clones my field! You may have a nested struct similar to this: ```rust # use pyo3::prelude::*; #[pyclass] #[derive(Clone)] struct Inner {/* fields omitted */} #[pyclass] struct Outer { #[pyo3(get)] inner: Inner, } #[pymethods] impl Outer { #[new] fn __new__() -> Self { Self { inner: Inner {} } } } ``` When Python code accesses `Outer`'s field, PyO3 will return a new object on every access (note that their addresses are different): ```python outer = Outer() a = outer.inner b = outer.inner assert a is b, f"a: {a}\nb: {b}" ``` ```text AssertionError: a: b: ``` This can be especially confusing if the field is mutable, as getting the field and then mutating it won't persist - you'll just get a fresh clone of the original on the next access. Unfortunately Python and Rust don't agree about ownership - if PyO3 gave out references to (possibly) temporary Rust objects to Python code, Python code could then keep that reference alive indefinitely. Therefore returning Rust objects requires cloning. If you don't want that cloning to happen, a workaround is to allocate the field on the Python heap and store a reference to that, by using [`Py<...>`]({{#PYO3_DOCS_URL}}/pyo3/struct.Py.html): ```rust # use pyo3::prelude::*; #[pyclass] struct Inner {/* fields omitted */} #[pyclass] struct Outer { inner: Py, } #[pymethods] impl Outer { #[new] fn __new__(py: Python<'_>) -> PyResult { Ok(Self { inner: Py::new(py, Inner {})?, }) } #[getter] fn inner(&self, py: Python<'_>) -> Py { self.inner.clone_ref(py) } } ``` This time `a` and `b` *are* the same object: ```python outer = Outer() a = outer.inner b = outer.inner assert a is b, f"a: {a}\nb: {b}" print(f"a: {a}\nb: {b}") ``` ```text a: b: ``` The downside to this approach is that any Rust code working on the `Outer` struct now has to acquire the GIL to do anything with its field. ## I want to use the `pyo3` crate re-exported from dependency but the proc-macros fail! All PyO3 proc-macros (`#[pyclass]`, `#[pyfunction]`, `#[derive(FromPyObject)]` and so on) expect the `pyo3` crate to be available under that name in your crate root, which is the normal situation when `pyo3` is a direct dependency of your crate. However, when the dependency is renamed, or your crate only indirectly depends on `pyo3`, you need to let the macro code know where to find the crate. This is done with the `crate` attribute: ```rust # use pyo3::prelude::*; # pub extern crate pyo3; # mod reexported { pub use ::pyo3; } #[pyclass] #[pyo3(crate = "reexported::pyo3")] struct MyClass; ``` ## I'm trying to call Python from Rust but I get `STATUS_DLL_NOT_FOUND` or `STATUS_ENTRYPOINT_NOT_FOUND`! This happens on Windows when linking to the python DLL fails or the wrong one is linked. The Python DLL on Windows will usually be called something like: - `python3X.dll` for Python 3.X, e.g. `python310.dll` for Python 3.10 - `python3.dll` when using PyO3's `abi3` feature The DLL needs to be locatable using the [Windows DLL search order](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-unpackaged-apps). Some ways to achieve this are: - Put the Python DLL in the same folder as your build artifacts - Add the directory containing the Python DLL to your `PATH` environment variable, for example `C:\Users\\AppData\Local\Programs\Python\Python310` - If this happens when you are *distributing* your program, consider using [PyOxidizer](https://github.com/indygreg/PyOxidizer) to package it with your binary. If the wrong DLL is linked it is possible that this happened because another program added itself and its own Python DLLs to `PATH`. Rearrange your `PATH` variables to give the correct DLL priority. > **Note**: Changes to `PATH` (or any other environment variable) are not visible to existing shells. Restart it for changes to take effect. For advanced troubleshooting, [Dependency Walker](https://www.dependencywalker.com/) can be used to diagnose linking errors. pyo3/guide/src/python-from-rust/0000775000175000017500000000000014661133735017576 5ustar jamespagejamespagepyo3/guide/src/python-from-rust/calling-existing-code.md0000644000175000017500000002631614661133735024277 0ustar jamespagejamespage# Executing existing Python code If you already have some existing Python code that you need to execute from Rust, the following FAQs can help you select the right PyO3 functionality for your situation: ## Want to access Python APIs? Then use `PyModule::import_bound`. [`PyModule::import_bound`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.import_bound) can be used to get handle to a Python module from Rust. You can use this to import and use any Python module available in your environment. ```rust use pyo3::prelude::*; fn main() -> PyResult<()> { Python::with_gil(|py| { let builtins = PyModule::import_bound(py, "builtins")?; let total: i32 = builtins .getattr("sum")? .call1((vec![1, 2, 3],))? .extract()?; assert_eq!(total, 6); Ok(()) }) } ``` ## Want to run just an expression? Then use `eval_bound`. [`Python::eval_bound`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval_bound) is a method to execute a [Python expression](https://docs.python.org/3.7/reference/expressions.html) and return the evaluated value as a `Bound<'py, PyAny>` object. ```rust use pyo3::prelude::*; # fn main() -> Result<(), ()> { Python::with_gil(|py| { let result = py .eval_bound("[i * 10 for i in range(5)]", None, None) .map_err(|e| { e.print_and_set_sys_last_vars(py); })?; let res: Vec = result.extract().unwrap(); assert_eq!(res, vec![0, 10, 20, 30, 40]); Ok(()) }) # } ``` ## Want to run statements? Then use `run_bound`. [`Python::run_bound`] is a method to execute one or more [Python statements](https://docs.python.org/3.7/reference/simple_stmts.html). This method returns nothing (like any Python statement), but you can get access to manipulated objects via the `locals` dict. You can also use the [`py_run!`] macro, which is a shorthand for [`Python::run_bound`]. Since [`py_run!`] panics on exceptions, we recommend you use this macro only for quickly testing your Python extensions. ```rust use pyo3::prelude::*; use pyo3::py_run; # fn main() { #[pyclass] struct UserData { id: u32, name: String, } #[pymethods] impl UserData { fn as_tuple(&self) -> (u32, String) { (self.id, self.name.clone()) } fn __repr__(&self) -> PyResult { Ok(format!("User {}(id: {})", self.name, self.id)) } } Python::with_gil(|py| { let userdata = UserData { id: 34, name: "Yu".to_string(), }; let userdata = Py::new(py, userdata).unwrap(); let userdata_as_tuple = (34, "Yu"); py_run!(py, userdata userdata_as_tuple, r#" assert repr(userdata) == "User Yu(id: 34)" assert userdata.as_tuple() == userdata_as_tuple "#); }) # } ``` ## You have a Python file or code snippet? Then use `PyModule::from_code_bound`. [`PyModule::from_code_bound`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.from_code_bound) can be used to generate a Python module which can then be used just as if it was imported with `PyModule::import`. **Warning**: This will compile and execute code. **Never** pass untrusted code to this function! ```rust use pyo3::{prelude::*, types::IntoPyDict}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let activators = PyModule::from_code_bound( py, r#" def relu(x): """see https://en.wikipedia.org/wiki/Rectifier_(neural_networks)""" return max(0.0, x) def leaky_relu(x, slope=0.01): return x if x >= 0 else x * slope "#, "activators.py", "activators", )?; let relu_result: f64 = activators.getattr("relu")?.call1((-1.0,))?.extract()?; assert_eq!(relu_result, 0.0); let kwargs = [("slope", 0.2)].into_py_dict_bound(py); let lrelu_result: f64 = activators .getattr("leaky_relu")? .call((-1.0,), Some(&kwargs))? .extract()?; assert_eq!(lrelu_result, -0.2); # Ok(()) }) # } ``` ## Want to embed Python in Rust with additional modules? Python maintains the `sys.modules` dict as a cache of all imported modules. An import in Python will first attempt to lookup the module from this dict, and if not present will use various strategies to attempt to locate and load the module. The [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) macro can be used to add additional `#[pymodule]` modules to an embedded Python interpreter. The macro **must** be invoked _before_ initializing Python. As an example, the below adds the module `foo` to the embedded interpreter: ```rust use pyo3::prelude::*; #[pyfunction] fn add_one(x: i64) -> i64 { x + 1 } #[pymodule] fn foo(foo_module: &Bound<'_, PyModule>) -> PyResult<()> { foo_module.add_function(wrap_pyfunction!(add_one, foo_module)?)?; Ok(()) } fn main() -> PyResult<()> { pyo3::append_to_inittab!(foo); Python::with_gil(|py| Python::run_bound(py, "import foo; foo.add_one(6)", None, None)) } ``` If `append_to_inittab` cannot be used due to constraints in the program, an alternative is to create a module using [`PyModule::new_bound`] and insert it manually into `sys.modules`: ```rust use pyo3::prelude::*; use pyo3::types::PyDict; #[pyfunction] pub fn add_one(x: i64) -> i64 { x + 1 } fn main() -> PyResult<()> { Python::with_gil(|py| { // Create new module let foo_module = PyModule::new_bound(py, "foo")?; foo_module.add_function(wrap_pyfunction!(add_one, &foo_module)?)?; // Import and get sys.modules let sys = PyModule::import_bound(py, "sys")?; let py_modules: Bound<'_, PyDict> = sys.getattr("modules")?.downcast_into()?; // Insert foo into sys.modules py_modules.set_item("foo", foo_module)?; // Now we can import + run our python code Python::run_bound(py, "import foo; foo.add_one(6)", None, None) }) } ``` ## Include multiple Python files You can include a file at compile time by using [`std::include_str`](https://doc.rust-lang.org/std/macro.include_str.html) macro. Or you can load a file at runtime by using [`std::fs::read_to_string`](https://doc.rust-lang.org/std/fs/fn.read_to_string.html) function. Many Python files can be included and loaded as modules. If one file depends on another you must preserve correct order while declaring `PyModule`. Example directory structure: ```text . ├── Cargo.lock ├── Cargo.toml ├── python_app │ ├── app.py │ └── utils │ └── foo.py └── src └── main.rs ``` `python_app/app.py`: ```python from utils.foo import bar def run(): return bar() ``` `python_app/utils/foo.py`: ```python def bar(): return "baz" ``` The example below shows: * how to include content of `app.py` and `utils/foo.py` into your rust binary * how to call function `run()` (declared in `app.py`) that needs function imported from `utils/foo.py` `src/main.rs`: ```rust,ignore use pyo3::prelude::*; fn main() -> PyResult<()> { let py_foo = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/python_app/utils/foo.py" )); let py_app = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/python_app/app.py")); let from_python = Python::with_gil(|py| -> PyResult> { PyModule::from_code_bound(py, py_foo, "utils.foo", "utils.foo")?; let app: Py = PyModule::from_code_bound(py, py_app, "", "")? .getattr("run")? .into(); app.call0(py) }); println!("py: {}", from_python?); Ok(()) } ``` The example below shows: * how to load content of `app.py` at runtime so that it sees its dependencies automatically * how to call function `run()` (declared in `app.py`) that needs function imported from `utils/foo.py` It is recommended to use absolute paths because then your binary can be run from anywhere as long as your `app.py` is in the expected directory (in this example that directory is `/usr/share/python_app`). `src/main.rs`: ```rust,no_run use pyo3::prelude::*; use pyo3::types::PyList; use std::fs; use std::path::Path; fn main() -> PyResult<()> { let path = Path::new("/usr/share/python_app"); let py_app = fs::read_to_string(path.join("app.py"))?; let from_python = Python::with_gil(|py| -> PyResult> { let syspath = py .import_bound("sys")? .getattr("path")? .downcast_into::()?; syspath.insert(0, &path)?; let app: Py = PyModule::from_code_bound(py, &py_app, "", "")? .getattr("run")? .into(); app.call0(py) }); println!("py: {}", from_python?); Ok(()) } ``` [`Python::run`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.run [`py_run!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.py_run.html ## Need to use a context manager from Rust? Use context managers by directly invoking `__enter__` and `__exit__`. ```rust use pyo3::prelude::*; fn main() { Python::with_gil(|py| { let custom_manager = PyModule::from_code_bound( py, r#" class House(object): def __init__(self, address): self.address = address def __enter__(self): print(f"Welcome to {self.address}!") def __exit__(self, type, value, traceback): if type: print(f"Sorry you had {type} trouble at {self.address}") else: print(f"Thank you for visiting {self.address}, come again soon!") "#, "house.py", "house", ) .unwrap(); let house_class = custom_manager.getattr("House").unwrap(); let house = house_class.call1(("123 Main Street",)).unwrap(); house.call_method0("__enter__").unwrap(); let result = py.eval_bound("undefined_variable + 1", None, None); // If the eval threw an exception we'll pass it through to the context manager. // Otherwise, __exit__ is called with empty arguments (Python "None"). match result { Ok(_) => { let none = py.None(); house .call_method1("__exit__", (&none, &none, &none)) .unwrap(); } Err(e) => { house .call_method1( "__exit__", ( e.get_type_bound(py), e.value_bound(py), e.traceback_bound(py), ), ) .unwrap(); } } }) } ``` ## Handling system signals/interrupts (Ctrl-C) The best way to handle system signals when running Rust code is to periodically call `Python::check_signals` to handle any signals captured by Python's signal handler. See also [the FAQ entry](../faq.md#ctrl-c-doesnt-do-anything-while-my-rust-code-is-executing). Alternatively, set Python's `signal` module to take the default action for a signal: ```rust use pyo3::prelude::*; # fn main() -> PyResult<()> { Python::with_gil(|py| -> PyResult<()> { let signal = py.import_bound("signal")?; // Set SIGINT to have the default action signal .getattr("signal")? .call1((signal.getattr("SIGINT")?, signal.getattr("SIG_DFL")?))?; Ok(()) }) # } ``` [`PyModule::new_bound`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.new_bound pyo3/guide/src/python-from-rust/function-calls.md0000644000175000017500000001120414661133735023035 0ustar jamespagejamespage# Calling Python functions The `Bound<'py, T>` smart pointer (such as `Bound<'py, PyAny>`, `Bound<'py, PyList>`, or `Bound<'py, MyClass>`) can be used to call Python functions. PyO3 offers two APIs to make function calls: * [`call`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call) - call any callable Python object. * [`call_method`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method) - call a method on the Python object. Both of these APIs take `args` and `kwargs` arguments (for positional and keyword arguments respectively). There are variants for less complex calls: * [`call1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call1) and [`call_method1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method1) to call only with positional `args`. * [`call0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call0) and [`call_method0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method0) to call with no arguments. For convenience the [`Py`](../types.md#pyt-and-pyobject) smart pointer also exposes these same six API methods, but needs a `Python` token as an additional first argument to prove the GIL is held. The example below calls a Python function behind a `PyObject` (aka `Py`) reference: ```rust use pyo3::prelude::*; use pyo3::types::PyTuple; fn main() -> PyResult<()> { let arg1 = "arg1"; let arg2 = "arg2"; let arg3 = "arg3"; Python::with_gil(|py| { let fun: Py = PyModule::from_code_bound( py, "def example(*args, **kwargs): if args != (): print('called with args', args) if kwargs != {}: print('called with kwargs', kwargs) if args == () and kwargs == {}: print('called with no arguments')", "", "", )? .getattr("example")? .into(); // call object without any arguments fun.call0(py)?; // pass object with Rust tuple of positional arguments let args = (arg1, arg2, arg3); fun.call1(py, args)?; // call object with Python tuple of positional arguments let args = PyTuple::new_bound(py, &[arg1, arg2, arg3]); fun.call1(py, args)?; Ok(()) }) } ``` ## Creating keyword arguments For the `call` and `call_method` APIs, `kwargs` are `Option<&Bound<'py, PyDict>>`, so can either be `None` or `Some(&dict)`. You can use the [`IntoPyDict`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.IntoPyDict.html) trait to convert other dict-like containers, e.g. `HashMap` or `BTreeMap`, as well as tuples with up to 10 elements and `Vec`s where each element is a two-element tuple. ```rust use pyo3::prelude::*; use pyo3::types::IntoPyDict; use std::collections::HashMap; fn main() -> PyResult<()> { let key1 = "key1"; let val1 = 1; let key2 = "key2"; let val2 = 2; Python::with_gil(|py| { let fun: Py = PyModule::from_code_bound( py, "def example(*args, **kwargs): if args != (): print('called with args', args) if kwargs != {}: print('called with kwargs', kwargs) if args == () and kwargs == {}: print('called with no arguments')", "", "", )? .getattr("example")? .into(); // call object with PyDict let kwargs = [(key1, val1)].into_py_dict_bound(py); fun.call_bound(py, (), Some(&kwargs))?; // pass arguments as Vec let kwargs = vec![(key1, val1), (key2, val2)]; fun.call_bound(py, (), Some(&kwargs.into_py_dict_bound(py)))?; // pass arguments as HashMap let mut kwargs = HashMap::<&str, i32>::new(); kwargs.insert(key1, 1); fun.call_bound(py, (), Some(&kwargs.into_py_dict_bound(py)))?; Ok(()) }) } ```
During PyO3's [migration from "GIL Refs" to the `Bound` smart pointer](../migration.md#migrating-from-the-gil-refs-api-to-boundt), `Py::call` is temporarily named [`Py::call_bound`]({{#PYO3_DOCS_URL}}/pyo3/struct.Py.html#method.call_bound) (and `call_method` is temporarily `call_method_bound`). (This temporary naming is only the case for the `Py` smart pointer. The methods on the `&PyAny` GIL Ref such as `call` have not been given replacements, and the methods on the `Bound` smart pointer such as [`Bound::call`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call) already use follow the newest API conventions.)
pyo3/guide/src/python-from-rust.md0000644000175000017500000000611414661133735020120 0ustar jamespagejamespage# Calling Python in Rust code This chapter of the guide documents some ways to interact with Python code from Rust. Below is an introduction to the `'py` lifetime and some general remarks about how PyO3's API reasons about Python code. The subchapters also cover the following topics: - Python object types available in PyO3's API - How to work with Python exceptions - How to call Python functions - How to execute existing Python code ## The `'py` lifetime To safely interact with the Python interpreter a Rust thread must have a corresponding Python thread state and hold the [Global Interpreter Lock (GIL)](#the-global-interpreter-lock). PyO3 has a `Python<'py>` token that is used to prove that these conditions are met. Its lifetime `'py` is a central part of PyO3's API. The `Python<'py>` token serves three purposes: * It provides global APIs for the Python interpreter, such as [`py.eval_bound()`][eval] and [`py.import_bound()`][import]. * It can be passed to functions that require a proof of holding the GIL, such as [`Py::clone_ref`][clone_ref]. * Its lifetime `'py` is used to bind many of PyO3's types to the Python interpreter, such as [`Bound<'py, T>`][Bound]. PyO3's types that are bound to the `'py` lifetime, for example `Bound<'py, T>`, all contain a `Python<'py>` token. This means they have full access to the Python interpreter and offer a complete API for interacting with Python objects. Consult [PyO3's API documentation][obtaining-py] to learn how to acquire one of these tokens. ### The Global Interpreter Lock Concurrent programming in Python is aided by the Global Interpreter Lock (GIL), which ensures that only one Python thread can use the Python interpreter and its API at the same time. This allows it to be used to synchronize code. See the [`pyo3::sync`] module for synchronization tools PyO3 offers that are based on the GIL's guarantees. Non-Python operations (system calls and native Rust code) can unlock the GIL. See [the section on parallelism](parallelism.md) for how to do that using PyO3's API. ## Python's memory model Python's memory model differs from Rust's memory model in two key ways: - There is no concept of ownership; all Python objects are shared and usually implemented via reference counting - There is no concept of exclusive (`&mut`) references; any reference can mutate a Python object PyO3's API reflects this by providing [smart pointer][smart-pointers] types, `Py`, `Bound<'py, T>`, and (the very rarely used) `Borrowed<'a, 'py, T>`. These smart pointers all use Python reference counting. See the [subchapter on types](./types.md) for more detail on these types. Because of the lack of exclusive `&mut` references, PyO3's APIs for Python objects, for example [`PyListMethods::append`], use shared references. This is safe because Python objects have internal mechanisms to prevent data races (as of time of writing, the Python GIL). [smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html [obtaining-py]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#obtaining-a-python-token [`pyo3::sync`]: {{#PYO3_DOCS_URL}}/pyo3/sync/index.html pyo3/guide/src/SUMMARY.md0000644000175000017500000000330714661133735016001 0ustar jamespagejamespage# Summary [Introduction](index.md) --- - [Getting started](getting-started.md) - [Using Rust from Python](rust-from-python.md) - [Python modules](module.md) - [Python functions](function.md) - [Function signatures](function/signature.md) - [Error handling](function/error-handling.md) - [Python classes](class.md) - [Class customizations](class/protocols.md) - [Basic object customization](class/object.md) - [Emulating numeric types](class/numeric.md) - [Emulating callable objects](class/call.md) - [Calling Python from Rust](python-from-rust.md) - [Python object types](types.md) - [Python exceptions](exception.md) - [Calling Python functions](python-from-rust/function-calls.md) - [Executing existing Python code](python-from-rust/calling-existing-code.md) - [Type conversions](conversions.md) - [Mapping of Rust types to Python types](conversions/tables.md) - [Conversion traits](conversions/traits.md) - [Using `async` and `await`](async-await.md) - [Parallelism](parallelism.md) - [Debugging](debugging.md) - [Features reference](features.md) - [Memory management](memory.md) - [Performance](performance.md) - [Advanced topics](advanced.md) - [Building and distribution](building-and-distribution.md) - [Supporting multiple Python versions](building-and-distribution/multiple-python-versions.md) - [Useful crates](ecosystem.md) - [Logging](ecosystem/logging.md) - [Using `async` and `await`](ecosystem/async-await.md) - [FAQ and troubleshooting](faq.md) --- [Appendix A: Migration guide](migration.md) [Appendix B: Trait bounds](trait-bounds.md) [Appendix C: Python typing hints](python-typing-hints.md) [CHANGELOG](changelog.md) --- [Contributing](contributing.md) pyo3/guide/src/exception.md0000644000175000017500000000760114661133735016643 0ustar jamespagejamespage# Python exceptions ## Defining a new exception Use the [`create_exception!`] macro: ```rust use pyo3::create_exception; create_exception!(module, MyError, pyo3::exceptions::PyException); ``` * `module` is the name of the containing module. * `MyError` is the name of the new exception type. For example: ```rust use pyo3::prelude::*; use pyo3::create_exception; use pyo3::types::IntoPyDict; use pyo3::exceptions::PyException; create_exception!(mymodule, CustomError, PyException); Python::with_gil(|py| { let ctx = [("CustomError", py.get_type_bound::())].into_py_dict_bound(py); pyo3::py_run!( py, *ctx, "assert str(CustomError) == \"\"" ); pyo3::py_run!(py, *ctx, "assert CustomError('oops').args == ('oops',)"); }); ``` When using PyO3 to create an extension module, you can add the new exception to the module like this, so that it is importable from Python: ```rust use pyo3::prelude::*; use pyo3::exceptions::PyException; pyo3::create_exception!(mymodule, CustomError, PyException); #[pymodule] fn mymodule(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { // ... other elements added to module ... m.add("CustomError", py.get_type_bound::())?; Ok(()) } ``` ## Raising an exception As described in the [function error handling](./function/error-handling.md) chapter, to raise an exception from a `#[pyfunction]` or `#[pymethods]`, return an `Err(PyErr)`. PyO3 will automatically raise this exception for you when returning the result to Python. You can also manually write and fetch errors in the Python interpreter's global state: ```rust use pyo3::{Python, PyErr}; use pyo3::exceptions::PyTypeError; Python::with_gil(|py| { PyTypeError::new_err("Error").restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); }); ``` ## Checking exception types Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#isinstance) method to check an object's type. In PyO3 every object has the [`PyAny::is_instance`] and [`PyAny::is_instance_of`] methods which do the same thing. ```rust use pyo3::prelude::*; use pyo3::types::{PyBool, PyList}; Python::with_gil(|py| { assert!(PyBool::new_bound(py, true).is_instance_of::()); let list = PyList::new_bound(py, &[1, 2, 3, 4]); assert!(!list.is_instance_of::()); assert!(list.is_instance_of::()); }); ``` To check the type of an exception, you can similarly do: ```rust # use pyo3::exceptions::PyTypeError; # use pyo3::prelude::*; # Python::with_gil(|py| { # let err = PyTypeError::new_err(()); err.is_instance_of::(py); # }); ``` ## Using exceptions defined in Python code It is possible to use an exception defined in Python code as a native Rust type. The `import_exception!` macro allows importing a specific exception class and defines a Rust type for that exception. ```rust #![allow(dead_code)] use pyo3::prelude::*; mod io { pyo3::import_exception!(io, UnsupportedOperation); } fn tell(file: &Bound<'_, PyAny>) -> PyResult { match file.call_method0("tell") { Err(_) => Err(io::UnsupportedOperation::new_err("not supported: tell")), Ok(x) => x.extract::(), } } ``` [`pyo3::exceptions`]({{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html) defines exceptions for several standard library modules. [`create_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.create_exception.html [`import_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.import_exception.html [`PyErr`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html [`PyResult`]: {{#PYO3_DOCS_URL}}/pyo3/type.PyResult.html [`PyErr::from_value`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html#method.from_value [`PyAny::is_instance`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance [`PyAny::is_instance_of`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance_of pyo3/guide/src/performance.md0000644000175000017500000001334514661133735017150 0ustar jamespagejamespage# Performance To achieve the best possible performance, it is useful to be aware of several tricks and sharp edges concerning PyO3's API. ## `extract` versus `downcast` Pythonic API implemented using PyO3 are often polymorphic, i.e. they will accept `&Bound<'_, PyAny>` and try to turn this into multiple more concrete types to which the requested operation is applied. This often leads to chains of calls to `extract`, e.g. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::{exceptions::PyTypeError, types::PyList}; fn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult> { todo!() } fn frobnicate_vec<'py>(vec: Vec>) -> PyResult> { todo!() } #[pyfunction] fn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult> { if let Ok(list) = value.extract::>() { frobnicate_list(&list) } else if let Ok(vec) = value.extract::>>() { frobnicate_vec(vec) } else { Err(PyTypeError::new_err("Cannot frobnicate that type.")) } } ``` This suboptimal as the `FromPyObject` trait requires `extract` to have a `Result` return type. For native types like `PyList`, it faster to use `downcast` (which `extract` calls internally) when the error value is ignored. This avoids the costly conversion of a `PyDowncastError` to a `PyErr` required to fulfil the `FromPyObject` contract, i.e. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::{exceptions::PyTypeError, types::PyList}; # fn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult> { todo!() } # fn frobnicate_vec<'py>(vec: Vec>) -> PyResult> { todo!() } # #[pyfunction] fn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult> { // Use `downcast` instead of `extract` as turning `PyDowncastError` into `PyErr` is quite costly. if let Ok(list) = value.downcast::() { frobnicate_list(list) } else if let Ok(vec) = value.extract::>>() { frobnicate_vec(vec) } else { Err(PyTypeError::new_err("Cannot frobnicate that type.")) } } ``` ## Access to Bound implies access to GIL token Calling `Python::with_gil` is effectively a no-op when the GIL is already held, but checking that this is the case still has a cost. If an existing GIL token can not be accessed, for example when implementing a pre-existing trait, but a GIL-bound reference is available, this cost can be avoided by exploiting that access to GIL-bound reference gives zero-cost access to a GIL token via `Bound::py`. For example, instead of writing ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; struct Foo(Py); struct FooBound<'py>(Bound<'py, PyList>); impl PartialEq for FooBound<'_> { fn eq(&self, other: &Foo) -> bool { Python::with_gil(|py| { let len = other.0.bind(py).len(); self.0.len() == len }) } } ``` use the more efficient ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # struct Foo(Py); # struct FooBound<'py>(Bound<'py, PyList>); # impl PartialEq for FooBound<'_> { fn eq(&self, other: &Foo) -> bool { // Access to `&Bound<'py, PyAny>` implies access to `Python<'py>`. let py = self.0.py(); let len = other.0.bind(py).len(); self.0.len() == len } } ``` ## Disable the global reference pool PyO3 uses global mutable state to keep track of deferred reference count updates implied by `impl Drop for Py` being called without the GIL being held. The necessary synchronization to obtain and apply these reference count updates when PyO3-based code next acquires the GIL is somewhat expensive and can become a significant part of the cost of crossing the Python-Rust boundary. This functionality can be avoided by setting the `pyo3_disable_reference_pool` conditional compilation flag. This removes the global reference pool and the associated costs completely. However, it does _not_ remove the `Drop` implementation for `Py` which is necessary to interoperate with existing Rust code written without PyO3-based code in mind. To stay compatible with the wider Rust ecosystem in these cases, we keep the implementation but abort when `Drop` is called without the GIL being held. If `pyo3_leak_on_drop_without_reference_pool` is additionally enabled, objects dropped without the GIL being held will be leaked instead which is always sound but might have determinal effects like resource exhaustion in the long term. This limitation is important to keep in mind when this setting is used, especially when embedding Python code into a Rust application as it is quite easy to accidentally drop a `Py` (or types containing it like `PyErr`, `PyBackedStr` or `PyBackedBytes`) returned from `Python::with_gil` without making sure to re-acquire the GIL beforehand. For example, the following code ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::PyList; let numbers: Py = Python::with_gil(|py| PyList::empty_bound(py).unbind()); Python::with_gil(|py| { numbers.bind(py).append(23).unwrap(); }); Python::with_gil(|py| { numbers.bind(py).append(42).unwrap(); }); ``` will abort if the list not explicitly disposed via ```rust # use pyo3::prelude::*; # use pyo3::types::PyList; let numbers: Py = Python::with_gil(|py| PyList::empty_bound(py).unbind()); Python::with_gil(|py| { numbers.bind(py).append(23).unwrap(); }); Python::with_gil(|py| { numbers.bind(py).append(42).unwrap(); }); Python::with_gil(move |py| { drop(numbers); }); ``` [conditional-compilation]: https://doc.rust-lang.org/reference/conditional-compilation.html pyo3/guide/src/conversions.md0000644000175000017500000000030214661133735017204 0ustar jamespagejamespage# Type conversions In this portion of the guide we'll talk about the mapping of Python types to Rust types offered by PyO3, as well as the traits available to perform conversions between them. pyo3/guide/src/migration.md0000644000175000017500000020703714661133735016643 0ustar jamespagejamespage# Migrating from older PyO3 versions This guide can help you upgrade code through breaking changes from one PyO3 version to the next. For a detailed list of all changes, see the [CHANGELOG](changelog.md). ## from 0.21.* to 0.22 ### Deprecation of `gil-refs` feature continues
Click to expand Following the introduction of the "Bound" API in PyO3 0.21 and the planned removal of the "GIL Refs" API, all functionality related to GIL Refs is now gated behind the `gil-refs` feature and emits a deprecation warning on use. See the 0.21 migration entry for help upgrading.
### Deprecation of implicit default for trailing optional arguments
Click to expand With `pyo3` 0.22 the implicit `None` default for trailing `Option` type argument is deprecated. To migrate, place a `#[pyo3(signature = (...))]` attribute on affected functions or methods and specify the desired behavior. The migration warning specifies the corresponding signature to keep the current behavior. With 0.23 the signature will be required for any function containing `Option` type parameters to prevent accidental and unnoticed changes in behavior. With 0.24 this restriction will be lifted again and `Option` type arguments will be treated as any other argument _without_ special handling. Before: ```rust # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; #[pyfunction] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } ``` After: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (x, amount=None))] fn increment(x: u64, amount: Option) -> u64 { x + amount.unwrap_or(1) } ```
### `Py::clone` is now gated behind the `py-clone` feature
Click to expand If you rely on `impl Clone for Py` to fulfil trait requirements imposed by existing Rust code written without PyO3-based code in mind, the newly introduced feature `py-clone` must be enabled. However, take care to note that the behaviour is different from previous versions. If `Clone` was called without the GIL being held, we tried to delay the application of these reference count increments until PyO3-based code would re-acquire it. This turned out to be impossible to implement in a sound manner and hence was removed. Now, if `Clone` is called without the GIL being held, we panic instead for which calling code might not be prepared. Related to this, we also added a `pyo3_disable_reference_pool` conditional compilation flag which removes the infrastructure necessary to apply delayed reference count decrements implied by `impl Drop for Py`. They do not appear to be a soundness hazard as they should lead to memory leaks in the worst case. However, the global synchronization adds significant overhead to cross the Python-Rust boundary. Enabling this feature will remove these costs and make the `Drop` implementation abort the process if called without the GIL being held instead.
### Require explicit opt-in for comparison for simple enums
Click to expand With `pyo3` 0.22 the new `#[pyo3(eq)]` options allows automatic implementation of Python equality using Rust's `PartialEq`. Previously simple enums automatically implemented equality in terms of their discriminants. To make PyO3 more consistent, this automatic equality implementation is deprecated in favour of having opt-ins for all `#[pyclass]` types. Similarly, simple enums supported comparison with integers, which is not covered by Rust's `PartialEq` derive, so has been split out into the `#[pyo3(eq_int)]` attribute. To migrate, place a `#[pyo3(eq, eq_int)]` attribute on simple enum classes. Before: ```rust # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; #[pyclass] enum SimpleEnum { VariantA, VariantB = 42, } ``` After: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum SimpleEnum { VariantA, VariantB = 42, } ```
### `PyType::name` reworked to better match Python `__name__`
Click to expand This function previously would try to read directly from Python type objects' C API field (`tp_name`), in which case it would return a `Cow::Borrowed`. However the contents of `tp_name` don't have well-defined semantics. Instead `PyType::name()` now returns the equivalent of Python `__name__` and returns `PyResult>`. The closest equivalent to PyO3 0.21's version of `PyType::name()` has been introduced as a new function `PyType::fully_qualified_name()`, which is equivalent to `__module__` and `__qualname__` joined as `module.qualname`. Before: ```rust,ignore # #![allow(deprecated, dead_code)] # use pyo3::prelude::*; # use pyo3::types::{PyBool}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); let name = bool_type.name()?.into_owned(); println!("Hello, {}", name); let mut name_upper = bool_type.name()?; name_upper.to_mut().make_ascii_uppercase(); println!("Hello, {}", name_upper); Ok(()) }) # } ``` After: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::{PyBool}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); let name = bool_type.name()?; println!("Hello, {}", name); // (if the full dotted path was desired, switch from `name()` to `fully_qualified_name()`) let mut name_upper = bool_type.fully_qualified_name()?.to_string(); name_upper.make_ascii_uppercase(); println!("Hello, {}", name_upper); Ok(()) }) # } ```
## from 0.20.* to 0.21
Click to expand PyO3 0.21 introduces a new `Bound<'py, T>` smart pointer which replaces the existing "GIL Refs" API to interact with Python objects. For example, in PyO3 0.20 the reference `&'py PyAny` would be used to interact with Python objects. In PyO3 0.21 the updated type is `Bound<'py, PyAny>`. Making this change moves Rust ownership semantics out of PyO3's internals and into user code. This change fixes [a known soundness edge case of interaction with gevent](https://github.com/PyO3/pyo3/issues/3668) as well as improves CPU and [memory performance](https://github.com/PyO3/pyo3/issues/1056). For a full history of discussion see https://github.com/PyO3/pyo3/issues/3382. The "GIL Ref" `&'py PyAny` and similar types such as `&'py PyDict` continue to be available as a deprecated API. Due to the advantages of the new API it is advised that all users make the effort to upgrade as soon as possible. In addition to the major API type overhaul, PyO3 has needed to make a few small breaking adjustments to other APIs to close correctness and soundness gaps. The recommended steps to update to PyO3 0.21 is as follows: 1. Enable the `gil-refs` feature to silence deprecations related to the API change 2. Fix all other PyO3 0.21 migration steps 3. Disable the `gil-refs` feature and migrate off the deprecated APIs The following sections are laid out in this order.
### Enable the `gil-refs` feature
Click to expand To make the transition for the PyO3 ecosystem away from the GIL Refs API as smooth as possible, in PyO3 0.21 no APIs consuming or producing GIL Refs have been altered. Instead, variants using `Bound` smart pointers have been introduced, for example `PyTuple::new_bound` which returns `Bound` is the replacement form of `PyTuple::new`. The GIL Ref APIs have been deprecated, but to make migration easier it is possible to disable these deprecation warnings by enabling the `gil-refs` feature. > The one single exception where an existing API was changed in-place is the `pyo3::intern!` macro. Almost all uses of this macro did not need to update code to account it changing to return `&Bound` immediately, and adding an `intern_bound!` replacement was perceived as adding more work for users. It is recommended that users do this as a first step of updating to PyO3 0.21 so that the deprecation warnings do not get in the way of resolving the rest of the migration steps. Before: ```toml # Cargo.toml [dependencies] pyo3 = "0.20" ``` After: ```toml # Cargo.toml [dependencies] pyo3 = { version = "0.21", features = ["gil-refs"] } ```
### `PyTypeInfo` and `PyTryFrom` have been adjusted
Click to expand The `PyTryFrom` trait has aged poorly, its `try_from` method now conflicts with `TryFrom::try_from` in the 2021 edition prelude. A lot of its functionality was also duplicated with `PyTypeInfo`. To tighten up the PyO3 traits as part of the deprecation of the GIL Refs API the `PyTypeInfo` trait has had a simpler companion `PyTypeCheck`. The methods `PyAny::downcast` and `PyAny::downcast_exact` no longer use `PyTryFrom` as a bound, instead using `PyTypeCheck` and `PyTypeInfo` respectively. To migrate, switch all type casts to use `obj.downcast()` instead of `try_from(obj)` (and similar for `downcast_exact`). Before: ```rust,ignore # #![allow(deprecated)] # use pyo3::prelude::*; # use pyo3::types::{PyInt, PyList}; # fn main() -> PyResult<()> { Python::with_gil(|py| { let list = PyList::new(py, 0..5); let b = ::try_from(list.get_item(0).unwrap())?; Ok(()) }) # } ``` After: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::{PyInt, PyList}; # fn main() -> PyResult<()> { Python::with_gil(|py| { // Note that PyList::new is deprecated for PyList::new_bound as part of the GIL Refs API removal, // see the section below on migration to Bound. #[allow(deprecated)] let list = PyList::new(py, 0..5); let b = list.get_item(0).unwrap().downcast::()?; Ok(()) }) # } ```
### `Iter(A)NextOutput` are deprecated
Click to expand The `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`. The `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated. Most importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`. Only the return types `Option` and `Result, E>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration. Starting with an implementation of a Python iterator using `IterNextOutput`, e.g. ```rust #![allow(deprecated)] use pyo3::prelude::*; use pyo3::iter::IterNextOutput; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> IterNextOutput { if self.count < 5 { self.count += 1; IterNextOutput::Yield(self.count) } else { IterNextOutput::Return("done") } } } ``` If returning `"done"` via `StopIteration` is not really required, this should be written as ```rust use pyo3::prelude::*; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> Option { if self.count < 5 { self.count += 1; Some(self.count) } else { None } } } ``` This form also has additional benefits: It has already worked in previous PyO3 versions, it matches the signature of Rust's [`Iterator` trait](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) and it allows using a fast path in CPython which completely avoids the cost of raising a `StopIteration` exception. Note that using [`Option::transpose`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose) and the `Result, E>` variant, this form can also be used to wrap fallible iterators. Alternatively, the implementation can also be done as it would in Python itself, i.e. by "raising" a `StopIteration` exception ```rust use pyo3::prelude::*; use pyo3::exceptions::PyStopIteration; #[pyclass] struct PyClassIter { count: usize, } #[pymethods] impl PyClassIter { fn __next__(&mut self) -> PyResult { if self.count < 5 { self.count += 1; Ok(self.count) } else { Err(PyStopIteration::new_err("done")) } } } ``` Finally, an asynchronous iterator can directly return an awaitable without confusing wrapping ```rust use pyo3::prelude::*; #[pyclass] struct PyClassAwaitable { number: usize, } #[pymethods] impl PyClassAwaitable { fn __next__(&self) -> usize { self.number } fn __await__(slf: Py) -> Py { slf } } #[pyclass] struct PyClassAsyncIter { number: usize, } #[pymethods] impl PyClassAsyncIter { fn __anext__(&mut self) -> PyClassAwaitable { self.number += 1; PyClassAwaitable { number: self.number, } } fn __aiter__(slf: Py) -> Py { slf } } ```
### `PyType::name` has been renamed to `PyType::qualname`
Click to expand `PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name), matching the `__qualname__` attribute. The newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.
### `PyCell` has been deprecated
Click to expand Interactions with Python objects implemented in Rust no longer need to go though `PyCell`. Instead iteractions with Python object now consistently go through `Bound` or `Py` independently of whether `T` is native Python object or a `#[pyclass]` implemented in Rust. Use `Bound::new` or `Py::new` respectively to create and `Bound::borrow(_mut)` / `Py::borrow(_mut)` to borrow the Rust object.
### Migrating from the GIL Refs API to `Bound`
Click to expand To minimise breakage of code using the GIL Refs API, the `Bound` smart pointer has been introduced by adding complements to all functions which accept or return GIL Refs. This allows code to migrate by replacing the deprecated APIs with the new ones. To identify what to migrate, temporarily switch off the `gil-refs` feature to see deprecation warnings on [almost](#cases-where-pyo3-cannot-emit-gil-ref-deprecation-warnings) all uses of APIs accepting and producing GIL Refs . Over one or more PRs it should be possible to follow the deprecation hints to update code. Depending on your development environment, switching off the `gil-refs` feature may introduce [some very targeted breakages](#deactivating-the-gil-refs-feature), so you may need to fixup those first. For example, the following APIs have gained updated variants: - `PyList::new`, `PyTyple::new` and similar constructors have replacements `PyList::new_bound`, `PyTuple::new_bound` etc. - `FromPyObject::extract` has a new `FromPyObject::extract_bound` (see the section below) - The `PyTypeInfo` trait has had new `_bound` methods added to accept / return `Bound`. Because the new `Bound` API brings ownership out of the PyO3 framework and into user code, there are a few places where user code is expected to need to adjust while switching to the new API: - Code will need to add the occasional `&` to borrow the new smart pointer as `&Bound` to pass these types around (or use `.clone()` at the very small cost of increasing the Python reference count) - `Bound` and `Bound` cannot support indexing with `list[0]`, you should use `list.get_item(0)` instead. - `Bound::iter_borrowed` is slightly more efficient than `Bound::iter`. The default iteration of `Bound` cannot return borrowed references because Rust does not (yet) have "lending iterators". Similarly `Bound::get_borrowed_item` is more efficient than `Bound::get_item` for the same reason. - `&Bound` does not implement `FromPyObject` (although it might be possible to do this in the future once the GIL Refs API is completely removed). Use `bound_any.downcast::()` instead of `bound_any.extract::<&Bound>()`. - `Bound::to_str` now borrows from the `Bound` rather than from the `'py` lifetime, so code will need to store the smart pointer as a value in some cases where previously `&PyString` was just used as a temporary. (There are some more details relating to this in [the section below](#deactivating-the-gil-refs-feature).) - `.extract::<&str>()` now borrows from the source Python object. The simplest way to update is to change to `.extract::()`, which retains ownership of the Python reference. See more information [in the section on deactivating the `gil-refs` feature](#deactivating-the-gil-refs-feature). To convert between `&PyAny` and `&Bound` use the `as_borrowed()` method: ```rust,ignore let gil_ref: &PyAny = ...; let bound: &Bound = &gil_ref.as_borrowed(); ``` To convert between `Py` and `Bound` use the `bind()` / `into_bound()` methods, and `as_unbound()` / `unbind()` to go back from `Bound` to `Py`. ```rust,ignore let obj: Py = ...; let bound: &Bound<'py, PyList> = obj.bind(py); let bound: Bound<'py, PyList> = obj.into_bound(py); let obj: &Py = bound.as_unbound(); let obj: Py = bound.unbind(); ```
⚠️ Warning: dangling pointer trap 💣 > Because of the ownership changes, code which uses `.as_ptr()` to convert `&PyAny` and other GIL Refs to a `*mut pyo3_ffi::PyObject` should take care to avoid creating dangling pointers now that `Bound` carries ownership. > > For example, the following pattern with `Option<&PyAny>` can easily create a dangling pointer when migrating to the `Bound` smart pointer: > > ```rust,ignore > let opt: Option<&PyAny> = ...; > let p: *mut ffi::PyObject = opt.map_or(std::ptr::null_mut(), |any| any.as_ptr()); > ``` > > The correct way to migrate this code is to use `.as_ref()` to avoid dropping the `Bound` in the `map_or` closure: > > ```rust,ignore > let opt: Option> = ...; > let p: *mut ffi::PyObject = opt.as_ref().map_or(std::ptr::null_mut(), Bound::as_ptr); > ```
#### Migrating `FromPyObject` implementations `FromPyObject` has had a new method `extract_bound` which takes `&Bound<'py, PyAny>` as an argument instead of `&PyAny`. Both `extract` and `extract_bound` have been given default implementations in terms of the other, to avoid breaking code immediately on update to 0.21. All implementations of `FromPyObject` should be switched from `extract` to `extract_bound`. Before: ```rust,ignore impl<'py> FromPyObject<'py> for MyType { fn extract(obj: &'py PyAny) -> PyResult { /* ... */ } } ``` After: ```rust,ignore impl<'py> FromPyObject<'py> for MyType { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { /* ... */ } } ``` The expectation is that in 0.22 `extract_bound` will have the default implementation removed and in 0.23 `extract` will be removed. #### Cases where PyO3 cannot emit GIL Ref deprecation warnings Despite a large amount of deprecations warnings produced by PyO3 to aid with the transition from GIL Refs to the Bound API, there are a few cases where PyO3 cannot automatically warn on uses of GIL Refs. It is worth checking for these cases manually after the deprecation warnings have all been addressed: - Individual implementations of the `FromPyObject` trait cannot be deprecated, so PyO3 cannot warn about uses of code patterns like `.extract<&PyAny>()` which produce a GIL Ref. - GIL Refs in `#[pyfunction]` arguments emit a warning, but if the GIL Ref is wrapped inside another container such as `Vec<&PyAny>` then PyO3 cannot warn against this. - The `wrap_pyfunction!(function)(py)` deferred argument form of the `wrap_pyfunction` macro taking `py: Python<'py>` produces a GIL Ref, and due to limitations in type inference PyO3 cannot warn against this specific case.
### Deactivating the `gil-refs` feature
Click to expand As a final step of migration, deactivating the `gil-refs` feature will set up code for best performance and is intended to set up a forward-compatible API for PyO3 0.22. At this point code that needed to manage GIL Ref memory can safely remove uses of `GILPool` (which are constructed by calls to `Python::new_pool` and `Python::with_pool`). Deprecation warnings will highlight these cases. There is just one case of code that changes upon disabling these features: `FromPyObject` trait implementations for types that borrow directly from the input data cannot be implemented by PyO3 without GIL Refs (while the GIL Refs API is in the process of being removed). The main types affected are `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>`. To make PyO3's core functionality continue to work while the GIL Refs API is in the process of being removed, disabling the `gil-refs` feature moves the implementations of `FromPyObject` for `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>` to a new temporary trait `FromPyObjectBound`. This trait is the expected future form of `FromPyObject` and has an additional lifetime `'a` to enable these types to borrow data from Python objects. PyO3 0.21 has introduced the [`PyBackedStr`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedStr.html) and [`PyBackedBytes`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedBytes.html) types to help with this case. The easiest way to avoid lifetime challenges from extracting `&str` is to use these. For more complex types like `Vec<&str>`, is now impossible to extract directly from a Python object and `Vec` is the recommended upgrade path. A key thing to note here is because extracting to these types now ties them to the input lifetime, some extremely common patterns may need to be split into multiple Rust lines. For example, the following snippet of calling `.extract::<&str>()` directly on the result of `.getattr()` needs to be adjusted when deactivating the `gil-refs` feature. Before: ```rust # #[cfg(feature = "gil-refs")] { # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { #[allow(deprecated)] // GIL Ref API let obj: &'py PyType = py.get_type::(); let name: &'py str = obj.getattr("__name__")?.extract()?; assert_eq!(name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); # } ``` After: ```rust # #[cfg(any(not(Py_LIMITED_API), Py_3_10))] { # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { let obj: Bound<'py, PyType> = py.get_type_bound::(); let name_obj: Bound<'py, PyAny> = obj.getattr("__name__")?; // the lifetime of the data is no longer `'py` but the much shorter // lifetime of the `name_obj` smart pointer above let name: &'_ str = name_obj.extract()?; assert_eq!(name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); # } ``` To avoid needing to worry about lifetimes at all, it is also possible to use the new `PyBackedStr` type, which stores a reference to the Python `str` without a lifetime attachment. In particular, `PyBackedStr` helps for `abi3` builds for Python older than 3.10. Due to limitations in the `abi3` CPython API for those older versions, PyO3 cannot offer a `FromPyObjectBound` implementation for `&str` on those versions. The easiest way to migrate for older `abi3` builds is to replace any cases of `.extract::<&str>()` with `.extract::()`. Alternatively, use `.extract::>()`, `.extract::()` to copy the data into Rust. The following example uses the same snippet as those just above, but this time the final extracted type is `PyBackedStr`: ```rust # use pyo3::prelude::*; # use pyo3::types::{PyList, PyType}; # fn example<'py>(py: Python<'py>) -> PyResult<()> { use pyo3::pybacked::PyBackedStr; let obj: Bound<'py, PyType> = py.get_type_bound::(); let name: PyBackedStr = obj.getattr("__name__")?.extract()?; assert_eq!(&*name, "list"); # Ok(()) # } # Python::with_gil(example).unwrap(); ```
## from 0.19.* to 0.20 ### Drop support for older technologies
Click to expand PyO3 0.20 has increased minimum Rust version to 1.56. This enables use of newer language features and simplifies maintenance of the project.
### `PyDict::get_item` now returns a `Result`
Click to expand `PyDict::get_item` in PyO3 0.19 and older was implemented using a Python API which would suppress all exceptions and return `None` in those cases. This included errors in `__hash__` and `__eq__` implementations of the key being looked up. Newer recommendations by the Python core developers advise against using these APIs which suppress exceptions, instead allowing exceptions to bubble upwards. `PyDict::get_item_with_error` already implemented this recommended behavior, so that API has been renamed to `PyDict::get_item`. Before: ```rust,ignore use pyo3::prelude::*; use pyo3::exceptions::PyTypeError; use pyo3::types::{PyDict, IntoPyDict}; # fn main() { # let _ = Python::with_gil(|py| { let dict: &PyDict = [("a", 1)].into_py_dict(py); // `a` is in the dictionary, with value 1 assert!(dict.get_item("a").map_or(Ok(false), |x| x.eq(1))?); // `b` is not in the dictionary assert!(dict.get_item("b").is_none()); // `dict` is not hashable, so this fails with a `TypeError` assert!(dict .get_item_with_error(dict) .unwrap_err() .is_instance_of::(py)); }); # } ``` After: ```rust,ignore use pyo3::prelude::*; use pyo3::exceptions::PyTypeError; use pyo3::types::{PyDict, IntoPyDict}; # fn main() { # let _ = Python::with_gil(|py| -> PyResult<()> { let dict: &PyDict = [("a", 1)].into_py_dict(py); // `a` is in the dictionary, with value 1 assert!(dict.get_item("a")?.map_or(Ok(false), |x| x.eq(1))?); // `b` is not in the dictionary assert!(dict.get_item("b")?.is_none()); // `dict` is not hashable, so this fails with a `TypeError` assert!(dict .get_item(dict) .unwrap_err() .is_instance_of::(py)); Ok(()) }); # } ```
### Required arguments are no longer accepted after optional arguments
Click to expand [Trailing `Option` arguments](./function/signature.md#trailing-optional-arguments) have an automatic default of `None`. To avoid unwanted changes when modifying function signatures, in PyO3 0.18 it was deprecated to have a required argument after an `Option` argument without using `#[pyo3(signature = (...))]` to specify the intended defaults. In PyO3 0.20, this becomes a hard error. Before: ```rust,ignore #[pyfunction] fn x_or_y(x: Option, y: u64) -> u64 { x.unwrap_or(y) } ``` After: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (x, y))] // both x and y have no defaults and are required fn x_or_y(x: Option, y: u64) -> u64 { x.unwrap_or(y) } ```
### Remove deprecated function forms
Click to expand In PyO3 0.18 the `#[args]` attribute for `#[pymethods]`, and directly specifying the function signature in `#[pyfunction]`, was deprecated. This functionality has been removed in PyO3 0.20. Before: ```rust,ignore #[pyfunction] #[pyo3(a, b = "0", "/")] fn add(a: u64, b: u64) -> u64 { a + b } ``` After: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] #[pyo3(signature = (a, b=0, /))] fn add(a: u64, b: u64) -> u64 { a + b } ```
### `IntoPyPointer` trait removed
Click to expand The trait `IntoPyPointer`, which provided the `into_ptr` method on many types, has been removed. `into_ptr` is now available as an inherent method on all types that previously implemented this trait.
### `AsPyPointer` now `unsafe` trait
Click to expand The trait `AsPyPointer` is now `unsafe trait`, meaning any external implementation of it must be marked as `unsafe impl`, and ensure that they uphold the invariant of returning valid pointers.
## from 0.18.* to 0.19 ### Access to `Python` inside `__traverse__` implementations are now forbidden
Click to expand During `__traverse__` implementations for Python's Garbage Collection it is forbidden to do anything other than visit the members of the `#[pyclass]` being traversed. This means making Python function calls or other API calls are forbidden. Previous versions of PyO3 would allow access to `Python` (e.g. via `Python::with_gil`), which could cause the Python interpreter to crash or otherwise confuse the garbage collection algorithm. Attempts to acquire the GIL will now panic. See [#3165](https://github.com/PyO3/pyo3/issues/3165) for more detail. ```rust,ignore # use pyo3::prelude::*; #[pyclass] struct SomeClass {} impl SomeClass { fn __traverse__(&self, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>` { Python::with_gil(|| { /*...*/ }) // ERROR: this will panic } } ```
### Smarter `anyhow::Error` / `eyre::Report` conversion when inner error is "simple" `PyErr`
Click to expand When converting from `anyhow::Error` or `eyre::Report` to `PyErr`, if the inner error is a "simple" `PyErr` (with no source error), then the inner error will be used directly as the `PyErr` instead of wrapping it in a new `PyRuntimeError` with the original information converted into a string. ```rust,ignore # #[cfg(feature = "anyhow")] # #[allow(dead_code)] # mod anyhow_only { # use pyo3::prelude::*; # use pyo3::exceptions::PyValueError; #[pyfunction] fn raise_err() -> anyhow::Result<()> { Err(PyValueError::new_err("original error message").into()) } fn main() { Python::with_gil(|py| { let rs_func = wrap_pyfunction!(raise_err, py).unwrap(); pyo3::py_run!( py, rs_func, r" try: rs_func() except Exception as e: print(repr(e)) " ); }) } # } ``` Before, the above code would have printed `RuntimeError('ValueError: original error message')`, which might be confusing. After, the same code will print `ValueError: original error message`, which is more straightforward. However, if the `anyhow::Error` or `eyre::Report` has a source, then the original exception will still be wrapped in a `PyRuntimeError`.
### The deprecated `Python::acquire_gil` was removed and `Python::with_gil` must be used instead
Click to expand While the API provided by [`Python::acquire_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.acquire_gil) seems convenient, it is somewhat brittle as the design of the GIL token [`Python`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html) relies on proper nesting and panics if not used correctly, e.g. ```rust,ignore # #![allow(dead_code, deprecated)] # use pyo3::prelude::*; #[pyclass] struct SomeClass {} struct ObjectAndGuard { object: Py, guard: GILGuard, } impl ObjectAndGuard { fn new() -> Self { let guard = Python::acquire_gil(); let object = Py::new(guard.python(), SomeClass {}).unwrap(); Self { object, guard } } } let first = ObjectAndGuard::new(); let second = ObjectAndGuard::new(); // Panics because the guard within `second` is still alive. drop(first); drop(second); ``` The replacement is [`Python::with_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.with_gil) which is more cumbersome but enforces the proper nesting by design, e.g. ```rust,ignore # #![allow(dead_code)] # use pyo3::prelude::*; #[pyclass] struct SomeClass {} struct Object { object: Py, } impl Object { fn new(py: Python<'_>) -> Self { let object = Py::new(py, SomeClass {}).unwrap(); Self { object } } } // It either forces us to release the GIL before aquiring it again. let first = Python::with_gil(|py| Object::new(py)); let second = Python::with_gil(|py| Object::new(py)); drop(first); drop(second); // Or it ensures releasing the inner lock before the outer one. Python::with_gil(|py| { let first = Object::new(py); let second = Python::with_gil(|py| Object::new(py)); drop(first); drop(second); }); ``` Furthermore, `Python::acquire_gil` provides ownership of a `GILGuard` which can be freely stored and passed around. This is usually not helpful as it may keep the lock held for a long time thereby blocking progress in other parts of the program. Due to the generative lifetime attached to the GIL token supplied by `Python::with_gil`, the problem is avoided as the GIL token can only be passed down the call chain. Often, this issue can also be avoided entirely as any GIL-bound reference `&'py PyAny` implies access to a GIL token `Python<'py>` via the [`PyAny::py`](https://docs.rs/pyo3/latest/pyo3/types/struct.PyAny.html#method.py) method.
## from 0.17.* to 0.18 ### Required arguments after `Option<_>` arguments will no longer be automatically inferred
Click to expand In `#[pyfunction]` and `#[pymethods]`, if a "required" function input such as `i32` came after an `Option<_>` input, then the `Option<_>` would be implicitly treated as required. (All trailing `Option<_>` arguments were treated as optional with a default value of `None`). Starting with PyO3 0.18, this is deprecated and a future PyO3 version will require a [`#[pyo3(signature = (...))]` option](./function/signature.md) to explicitly declare the programmer's intention. Before, x in the below example would be required to be passed from Python code: ```rust,compile_fail # #![allow(dead_code)] # use pyo3::prelude::*; #[pyfunction] fn required_argument_after_option(x: Option, y: i32) {} ``` After, specify the intended Python signature explicitly: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; // If x really was intended to be required #[pyfunction(signature = (x, y))] fn required_argument_after_option_a(x: Option, y: i32) {} // If x was intended to be optional, y needs a default too #[pyfunction(signature = (x=None, y=0))] fn required_argument_after_option_b(x: Option, y: i32) {} ```
### `__text_signature__` is now automatically generated for `#[pyfunction]` and `#[pymethods]`
Click to expand The [`#[pyo3(text_signature = "...")]` option](./function/signature.md#making-the-function-signature-available-to-python) was previously the only supported way to set the `__text_signature__` attribute on generated Python functions. PyO3 is now able to automatically populate `__text_signature__` for all functions automatically based on their Rust signature (or the [new `#[pyo3(signature = (...))]` option](./function/signature.md)). These automatically-generated `__text_signature__` values will currently only render `...` for all default values. Many `#[pyo3(text_signature = "...")]` options can be removed from functions when updating to PyO3 0.18, however in cases with default values a manual implementation may still be preferred for now. As examples: ```rust # use pyo3::prelude::*; // The `text_signature` option here is no longer necessary, as PyO3 will automatically // generate exactly the same value. #[pyfunction(text_signature = "(a, b, c)")] fn simple_function(a: i32, b: i32, c: i32) {} // The `text_signature` still provides value here as of PyO3 0.18, because the automatically // generated signature would be "(a, b=..., c=...)". #[pyfunction(signature = (a, b = 1, c = 2), text_signature = "(a, b=1, c=2)")] fn function_with_defaults(a: i32, b: i32, c: i32) {} # fn main() { # Python::with_gil(|py| { # let simple = wrap_pyfunction_bound!(simple_function, py).unwrap(); # assert_eq!(simple.getattr("__text_signature__").unwrap().to_string(), "(a, b, c)"); # let defaulted = wrap_pyfunction_bound!(function_with_defaults, py).unwrap(); # assert_eq!(defaulted.getattr("__text_signature__").unwrap().to_string(), "(a, b=1, c=2)"); # }) # } ```
## from 0.16.* to 0.17 ### Type checks have been changed for `PyMapping` and `PySequence` types
Click to expand Previously the type checks for `PyMapping` and `PySequence` (implemented in `PyTryFrom`) used the Python C-API functions `PyMapping_Check` and `PySequence_Check`. Unfortunately these functions are not sufficient for distinguishing such types, leading to inconsistent behavior (see [pyo3/pyo3#2072](https://github.com/PyO3/pyo3/issues/2072)). PyO3 0.17 changes these downcast checks to explicitly test if the type is a subclass of the corresponding abstract base class `collections.abc.Mapping` or `collections.abc.Sequence`. Note this requires calling into Python, which may incur a performance penalty over the previous method. If this performance penalty is a problem, you may be able to perform your own checks and use `try_from_unchecked` (unsafe). Another side-effect is that a pyclass defined in Rust with PyO3 will need to be _registered_ with the corresponding Python abstract base class for downcasting to succeed. `PySequence::register` and `PyMapping:register` have been added to make it easy to do this from Rust code. These are equivalent to calling `collections.abc.Mapping.register(MappingPyClass)` or `collections.abc.Sequence.register(SequencePyClass)` from Python. For example, for a mapping class defined in Rust: ```rust,compile_fail use pyo3::prelude::*; use std::collections::HashMap; #[pyclass(mapping)] struct Mapping { index: HashMap, } #[pymethods] impl Mapping { #[new] fn new(elements: Option<&PyList>) -> PyResult { // ... // truncated implementation of this mapping pyclass - basically a wrapper around a HashMap } ``` You must register the class with `collections.abc.Mapping` before the downcast will work: ```rust,compile_fail let m = Py::new(py, Mapping { index }).unwrap(); assert!(m.as_ref(py).downcast::().is_err()); PyMapping::register::(py).unwrap(); assert!(m.as_ref(py).downcast::().is_ok()); ``` Note that this requirement may go away in the future when a pyclass is able to inherit from the abstract base class directly (see [pyo3/pyo3#991](https://github.com/PyO3/pyo3/issues/991)).
### The `multiple-pymethods` feature now requires Rust 1.62
Click to expand Due to limitations in the `inventory` crate which the `multiple-pymethods` feature depends on, this feature now requires Rust 1.62. For more information see [dtolnay/inventory#32](https://github.com/dtolnay/inventory/issues/32).
### Added `impl IntoPy> for &str`
Click to expand This may cause inference errors. Before: ```rust,compile_fail # use pyo3::prelude::*; # # fn main() { Python::with_gil(|py| { // Cannot infer either `Py` or `Py` let _test = "test".into_py(py); }); # } ``` After, some type annotations may be necessary: ```rust # use pyo3::prelude::*; # # fn main() { Python::with_gil(|py| { let _test: Py = "test".into_py(py); }); # } ```
### The `pyproto` feature is now disabled by default
Click to expand In preparation for removing the deprecated `#[pyproto]` attribute macro in a future PyO3 version, it is now gated behind an opt-in feature flag. This also gives a slight saving to compile times for code which does not use the deprecated macro.
### `PyTypeObject` trait has been deprecated
Click to expand The `PyTypeObject` trait already was near-useless; almost all functionality was already on the `PyTypeInfo` trait, which `PyTypeObject` had a blanket implementation based upon. In PyO3 0.17 the final method, `PyTypeObject::type_object` was moved to `PyTypeInfo::type_object`. To migrate, update trait bounds and imports from `PyTypeObject` to `PyTypeInfo`. Before: ```rust,ignore use pyo3::Python; use pyo3::type_object::PyTypeObject; use pyo3::types::PyType; fn get_type_object(py: Python<'_>) -> &PyType { T::type_object(py) } ``` After ```rust,ignore use pyo3::{Python, PyTypeInfo}; use pyo3::types::PyType; fn get_type_object(py: Python<'_>) -> &PyType { T::type_object(py) } # Python::with_gil(|py| { get_type_object::(py); }); ```
### `impl IntoPy for [T; N]` now requires `T: IntoPy` rather than `T: ToPyObject`
Click to expand If this leads to errors, simply implement `IntoPy`. Because pyclasses already implement `IntoPy`, you probably don't need to worry about this.
### Each `#[pymodule]` can now only be initialized once per process
Click to expand To make PyO3 modules sound in the presence of Python sub-interpreters, for now it has been necessary to explicitly disable the ability to initialize a `#[pymodule]` more than once in the same process. Attempting to do this will now raise an `ImportError`.
## from 0.15.* to 0.16 ### Drop support for older technologies
Click to expand PyO3 0.16 has increased minimum Rust version to 1.48 and minimum Python version to 3.7. This enables use of newer language features (enabling some of the other additions in 0.16) and simplifies maintenance of the project.
### `#[pyproto]` has been deprecated
Click to expand In PyO3 0.15, the `#[pymethods]` attribute macro gained support for implementing "magic methods" such as `__str__` (aka "dunder" methods). This implementation was not quite finalized at the time, with a few edge cases to be decided upon. The existing `#[pyproto]` attribute macro was left untouched, because it covered these edge cases. In PyO3 0.16, the `#[pymethods]` implementation has been completed and is now the preferred way to implement magic methods. To allow the PyO3 project to move forward, `#[pyproto]` has been deprecated (with expected removal in PyO3 0.18). Migration from `#[pyproto]` to `#[pymethods]` is straightforward; copying the existing methods directly from the `#[pyproto]` trait implementation is all that is needed in most cases. Before: ```rust,compile_fail use pyo3::prelude::*; use pyo3::class::{PyObjectProtocol, PyIterProtocol}; use pyo3::types::PyString; #[pyclass] struct MyClass {} #[pyproto] impl PyObjectProtocol for MyClass { fn __str__(&self) -> &'static [u8] { b"hello, world" } } #[pyproto] impl PyIterProtocol for MyClass { fn __iter__(slf: PyRef) -> PyResult<&PyAny> { PyString::new(slf.py(), "hello, world").iter() } } ``` After ```rust,compile_fail use pyo3::prelude::*; use pyo3::types::PyString; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { fn __str__(&self) -> &'static [u8] { b"hello, world" } fn __iter__(slf: PyRef) -> PyResult<&PyAny> { PyString::new(slf.py(), "hello, world").iter() } } ```
### Removed `PartialEq` for object wrappers
Click to expand The Python object wrappers `Py` and `PyAny` had implementations of `PartialEq` so that `object_a == object_b` would compare the Python objects for pointer equality, which corresponds to the `is` operator, not the `==` operator in Python. This has been removed in favor of a new method: use `object_a.is(object_b)`. This also has the advantage of not requiring the same wrapper type for `object_a` and `object_b`; you can now directly compare a `Py` with a `&PyAny` without having to convert. To check for Python object equality (the Python `==` operator), use the new method `eq()`.
### Container magic methods now match Python behavior
Click to expand In PyO3 0.15, `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` would generate only the _mapping_ implementation for a `#[pyclass]`. To match the Python behavior, these methods now generate both the _mapping_ **and** _sequence_ implementations. This means that classes implementing these `#[pymethods]` will now also be treated as sequences, same as a Python `class` would be. Small differences in behavior may result: - PyO3 will allow instances of these classes to be cast to `PySequence` as well as `PyMapping`. - Python will provide a default implementation of `__iter__` (if the class did not have one) which repeatedly calls `__getitem__` with integers (starting at 0) until an `IndexError` is raised. To explain this in detail, consider the following Python class: ```python class ExampleContainer: def __len__(self): return 5 def __getitem__(self, idx: int) -> int: if idx < 0 or idx > 5: raise IndexError() return idx ``` This class implements a Python [sequence](https://docs.python.org/3/glossary.html#term-sequence). The `__len__` and `__getitem__` methods are also used to implement a Python [mapping](https://docs.python.org/3/glossary.html#term-mapping). In the Python C-API, these methods are not shared: the sequence `__len__` and `__getitem__` are defined by the `sq_length` and `sq_item` slots, and the mapping equivalents are `mp_length` and `mp_subscript`. There are similar distinctions for `__setitem__` and `__delitem__`. Because there is no such distinction from Python, implementing these methods will fill the mapping and sequence slots simultaneously. A Python class with `__len__` implemented, for example, will have both the `sq_length` and `mp_length` slots filled. The PyO3 behavior in 0.16 has been changed to be closer to this Python behavior by default.
### `wrap_pymodule!` and `wrap_pyfunction!` now respect privacy correctly
Click to expand Prior to PyO3 0.16 the `wrap_pymodule!` and `wrap_pyfunction!` macros could use modules and functions whose defining `fn` was not reachable according Rust privacy rules. For example, the following code was legal before 0.16, but in 0.16 is rejected because the `wrap_pymodule!` macro cannot access the `private_submodule` function: ```rust,compile_fail mod foo { use pyo3::prelude::*; #[pymodule] fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> { Ok(()) } } use pyo3::prelude::*; use foo::*; #[pymodule] fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(private_submodule))?; Ok(()) } ``` To fix it, make the private submodule visible, e.g. with `pub` or `pub(crate)`. ```rust,ignore mod foo { use pyo3::prelude::*; #[pymodule] pub(crate) fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> { Ok(()) } } use pyo3::prelude::*; use pyo3::wrap_pymodule; use foo::*; #[pymodule] fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_wrapped(wrap_pymodule!(private_submodule))?; Ok(()) } ```
## from 0.14.* to 0.15 ### Changes in sequence indexing
Click to expand For all types that take sequence indices (`PyList`, `PyTuple` and `PySequence`), the API has been made consistent to only take `usize` indices, for consistency with Rust's indexing conventions. Negative indices, which were only sporadically supported even in APIs that took `isize`, now aren't supported anywhere. Further, the `get_item` methods now always return a `PyResult` instead of panicking on invalid indices. The `Index` trait has been implemented instead, and provides the same panic behavior as on Rust vectors. Note that *slice* indices (accepted by `PySequence::get_slice` and other) still inherit the Python behavior of clamping the indices to the actual length, and not panicking/returning an error on out of range indices. An additional advantage of using Rust's indexing conventions for these types is that these types can now also support Rust's indexing operators as part of a consistent API: ```rust,ignore #![allow(deprecated)] use pyo3::{Python, types::PyList}; Python::with_gil(|py| { let list = PyList::new(py, &[1, 2, 3]); assert_eq!(list[0..2].to_string(), "[1, 2]"); }); ```
## from 0.13.* to 0.14 ### `auto-initialize` feature is now opt-in
Click to expand For projects embedding Python in Rust, PyO3 no longer automatically initializes a Python interpreter on the first call to `Python::with_gil` (or `Python::acquire_gil`) unless the [`auto-initialize` feature](features.md#auto-initialize) is enabled.
### New `multiple-pymethods` feature
Click to expand `#[pymethods]` have been reworked with a simpler default implementation which removes the dependency on the `inventory` crate. This reduces dependencies and compile times for the majority of users. The limitation of the new default implementation is that it cannot support multiple `#[pymethods]` blocks for the same `#[pyclass]`. If you need this functionality, you must enable the `multiple-pymethods` feature which will switch `#[pymethods]` to the inventory-based implementation.
### Deprecated `#[pyproto]` methods
Click to expand Some protocol (aka `__dunder__`) methods such as `__bytes__` and `__format__` have been possible to implement two ways in PyO3 for some time: via a `#[pyproto]` (e.g. `PyObjectProtocol` for the methods listed here), or by writing them directly in `#[pymethods]`. This is only true for a handful of the `#[pyproto]` methods (for technical reasons to do with the way PyO3 currently interacts with the Python C-API). In the interest of having only one way to do things, the `#[pyproto]` forms of these methods have been deprecated. To migrate just move the affected methods from a `#[pyproto]` to a `#[pymethods]` block. Before: ```rust,compile_fail use pyo3::prelude::*; use pyo3::class::basic::PyObjectProtocol; #[pyclass] struct MyClass {} #[pyproto] impl PyObjectProtocol for MyClass { fn __bytes__(&self) -> &'static [u8] { b"hello, world" } } ``` After: ```rust use pyo3::prelude::*; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { fn __bytes__(&self) -> &'static [u8] { b"hello, world" } } ```
## from 0.12.* to 0.13 ### Minimum Rust version increased to Rust 1.45
Click to expand PyO3 `0.13` makes use of new Rust language features stabilized between Rust 1.40 and Rust 1.45. If you are using a Rust compiler older than Rust 1.45, you will need to update your toolchain to be able to continue using PyO3.
### Runtime changes to support the CPython limited API
Click to expand In PyO3 `0.13` support was added for compiling against the CPython limited API. This had a number of implications for _all_ PyO3 users, described here. The largest of these is that all types created from PyO3 are what CPython calls "heap" types. The specific implications of this are: - If you wish to subclass one of these types _from Rust_ you must mark it `#[pyclass(subclass)]`, as you would if you wished to allow subclassing it from Python code. - Type objects are now mutable - Python code can set attributes on them. - `__module__` on types without `#[pyclass(module="mymodule")]` no longer returns `builtins`, it now raises `AttributeError`.
## from 0.11.* to 0.12 ### `PyErr` has been reworked
Click to expand In PyO3 `0.12` the `PyErr` type has been re-implemented to be significantly more compatible with the standard Rust error handling ecosystem. Specifically `PyErr` now implements `Error + Send + Sync`, which are the standard traits used for error types. While this has necessitated the removal of a number of APIs, the resulting `PyErr` type should now be much more easier to work with. The following sections list the changes in detail and how to migrate to the new APIs.
#### `PyErr::new` and `PyErr::from_type` now require `Send + Sync` for their argument
Click to expand For most uses no change will be needed. If you are trying to construct `PyErr` from a value that is not `Send + Sync`, you will need to first create the Python object and then use `PyErr::from_instance`. Similarly, any types which implemented `PyErrArguments` will now need to be `Send + Sync`.
#### `PyErr`'s contents are now private
Click to expand It is no longer possible to access the fields `.ptype`, `.pvalue` and `.ptraceback` of a `PyErr`. You should instead now use the new methods `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`.
#### `PyErrValue` and `PyErr::from_value` have been removed
Click to expand As these were part the internals of `PyErr` which have been reworked, these APIs no longer exist. If you used this API, it is recommended to use `PyException::new_err` (see [the section on Exception types](#exception-types-have-been-reworked)).
#### `Into>` for `PyErr` has been removed
Click to expand This implementation was redundant. Just construct the `Result::Err` variant directly. Before: ```rust,compile_fail let result: PyResult<()> = PyErr::new::("error message").into(); ``` After (also using the new reworked exception types; see the following section): ```rust # use pyo3::{PyResult, exceptions::PyTypeError}; let result: PyResult<()> = Err(PyTypeError::new_err("error message")); ```
### Exception types have been reworked
Click to expand Previously exception types were zero-sized marker types purely used to construct `PyErr`. In PyO3 0.12, these types have been replaced with full definitions and are usable in the same way as `PyAny`, `PyDict` etc. This makes it possible to interact with Python exception objects. The new types also have names starting with the "Py" prefix. For example, before: ```rust,ignore let err: PyErr = TypeError::py_err("error message"); ``` After: ```rust,ignore # use pyo3::{PyErr, PyResult, Python, type_object::PyTypeObject}; # use pyo3::exceptions::{PyBaseException, PyTypeError}; # Python::with_gil(|py| -> PyResult<()> { let err: PyErr = PyTypeError::new_err("error message"); // Uses Display for PyErr, new for PyO3 0.12 assert_eq!(err.to_string(), "TypeError: error message"); // Now possible to interact with exception instances, new for PyO3 0.12 let instance: &PyBaseException = err.instance(py); assert_eq!( instance.getattr("__class__")?, PyTypeError::type_object(py).as_ref() ); # Ok(()) # }).unwrap(); ```
### `FromPy` has been removed
Click to expand To simplify the PyO3 conversion traits, the `FromPy` trait has been removed. Previously there were two ways to define the to-Python conversion for a type: `FromPy for PyObject` and `IntoPy for T`. Now there is only one way to define the conversion, `IntoPy`, so downstream crates may need to adjust accordingly. Before: ```rust,compile_fail # use pyo3::prelude::*; struct MyPyObjectWrapper(PyObject); impl FromPy for PyObject { fn from_py(other: MyPyObjectWrapper, _py: Python<'_>) -> Self { other.0 } } ``` After ```rust # use pyo3::prelude::*; # #[allow(dead_code)] struct MyPyObjectWrapper(PyObject); impl IntoPy for MyPyObjectWrapper { fn into_py(self, _py: Python<'_>) -> PyObject { self.0 } } ``` Similarly, code which was using the `FromPy` trait can be trivially rewritten to use `IntoPy`. Before: ```rust,compile_fail # use pyo3::prelude::*; # Python::with_gil(|py| { let obj = PyObject::from_py(1.234, py); # }) ``` After: ```rust # use pyo3::prelude::*; # Python::with_gil(|py| { let obj: PyObject = 1.234.into_py(py); # }) ```
### `PyObject` is now a type alias of `Py`
Click to expand This should change very little from a usage perspective. If you implemented traits for both `PyObject` and `Py`, you may find you can just remove the `PyObject` implementation.
### `AsPyRef` has been removed
Click to expand As `PyObject` has been changed to be just a type alias, the only remaining implementor of `AsPyRef` was `Py`. This removed the need for a trait, so the `AsPyRef::as_ref` method has been moved to `Py::as_ref`. This should require no code changes except removing `use pyo3::AsPyRef` for code which did not use `pyo3::prelude::*`. Before: ```rust,ignore use pyo3::{AsPyRef, Py, types::PyList}; # pyo3::Python::with_gil(|py| { let list_py: Py = PyList::empty(py).into(); let list_ref: &PyList = list_py.as_ref(py); # }) ``` After: ```rust,ignore use pyo3::{Py, types::PyList}; # pyo3::Python::with_gil(|py| { let list_py: Py = PyList::empty(py).into(); let list_ref: &PyList = list_py.as_ref(py); # }) ```
## from 0.10.* to 0.11 ### Stable Rust
Click to expand PyO3 now supports the stable Rust toolchain. The minimum required version is 1.39.0.
### `#[pyclass]` structs must now be `Send` or `unsendable`
Click to expand Because `#[pyclass]` structs can be sent between threads by the Python interpreter, they must implement `Send` or declared as `unsendable` (by `#[pyclass(unsendable)]`). Note that `unsendable` is added in PyO3 `0.11.1` and `Send` is always required in PyO3 `0.11.0`. This may "break" some code which previously was accepted, even though it could be unsound. There can be two fixes: 1. If you think that your `#[pyclass]` actually must be `Send`able, then let's implement `Send`. A common, safer way is using thread-safe types. E.g., `Arc` instead of `Rc`, `Mutex` instead of `RefCell`, and `Box` instead of `Box`. Before: ```rust,compile_fail use pyo3::prelude::*; use std::rc::Rc; use std::cell::RefCell; #[pyclass] struct NotThreadSafe { shared_bools: Rc>>, closure: Box, } ``` After: ```rust # #![allow(dead_code)] use pyo3::prelude::*; use std::sync::{Arc, Mutex}; #[pyclass] struct ThreadSafe { shared_bools: Arc>>, closure: Box, } ``` In situations where you cannot change your `#[pyclass]` to automatically implement `Send` (e.g., when it contains a raw pointer), you can use `unsafe impl Send`. In such cases, care should be taken to ensure the struct is actually thread safe. See [the Rustonomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html) for more. 2. If you think that your `#[pyclass]` should not be accessed by another thread, you can use `unsendable` flag. A class marked with `unsendable` panics when accessed by another thread, making it thread-safe to expose an unsendable object to the Python interpreter. Before: ```rust,compile_fail use pyo3::prelude::*; #[pyclass] struct Unsendable { pointers: Vec<*mut std::os::raw::c_char>, } ``` After: ```rust # #![allow(dead_code)] use pyo3::prelude::*; #[pyclass(unsendable)] struct Unsendable { pointers: Vec<*mut std::os::raw::c_char>, } ```
### All `PyObject` and `Py` methods now take `Python` as an argument
Click to expand Previously, a few methods such as `Object::get_refcnt` did not take `Python` as an argument (to ensure that the Python GIL was held by the current thread). Technically, this was not sound. To migrate, just pass a `py` argument to any calls to these methods. Before: ```rust,compile_fail # pyo3::Python::with_gil(|py| { py.None().get_refcnt(); # }) ``` After: ```rust # pyo3::Python::with_gil(|py| { py.None().get_refcnt(py); # }) ```
## from 0.9.* to 0.10 ### `ObjectProtocol` is removed
Click to expand All methods are moved to [`PyAny`]. And since now all native types (e.g., `PyList`) implements `Deref`, all you need to do is remove `ObjectProtocol` from your code. Or if you use `ObjectProtocol` by `use pyo3::prelude::*`, you have to do nothing. Before: ```rust,compile_fail,ignore use pyo3::ObjectProtocol; # pyo3::Python::with_gil(|py| { let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap(); let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap(); assert_eq!(hi.len().unwrap(), 5); # }) ``` After: ```rust,ignore # pyo3::Python::with_gil(|py| { let obj = py.eval("lambda: 'Hi :)'", None, None).unwrap(); let hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap(); assert_eq!(hi.len().unwrap(), 5); # }) ```
### No `#![feature(specialization)]` in user code
Click to expand While PyO3 itself still requires specialization and nightly Rust, now you don't have to use `#![feature(specialization)]` in your crate.
## from 0.8.* to 0.9 ### `#[new]` interface
Click to expand [`PyRawObject`](https://docs.rs/pyo3/0.8.5/pyo3/type_object/struct.PyRawObject.html) is now removed and our syntax for constructors has changed. Before: ```rust,compile_fail #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new(obj: &PyRawObject) { obj.init(MyClass {}) } } ``` After: ```rust # use pyo3::prelude::*; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new() -> Self { MyClass {} } } ``` Basically you can return `Self` or `Result` directly. For more, see [the constructor section](class.md#constructor) of this guide.
### PyCell
Click to expand PyO3 0.9 introduces `PyCell`, which is a [`RefCell`]-like object wrapper for ensuring Rust's rules regarding aliasing of references are upheld. For more detail, see the [Rust Book's section on Rust's rules of references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references) For `#[pymethods]` or `#[pyfunction]`s, your existing code should continue to work without any change. Python exceptions will automatically be raised when your functions are used in a way which breaks Rust's rules of references. Here is an example. ```rust # use pyo3::prelude::*; #[pyclass] struct Names { names: Vec, } #[pymethods] impl Names { #[new] fn new() -> Self { Names { names: vec![] } } fn merge(&mut self, other: &mut Names) { self.names.append(&mut other.names) } } # Python::with_gil(|py| { # let names = Py::new(py, Names::new()).unwrap(); # pyo3::py_run!(py, names, r" # try: # names.merge(names) # assert False, 'Unreachable' # except RuntimeError as e: # assert str(e) == 'Already borrowed' # "); # }) ``` `Names` has a `merge` method, which takes `&mut self` and another argument of type `&mut Self`. Given this `#[pyclass]`, calling `names.merge(names)` in Python raises a [`PyBorrowMutError`] exception, since it requires two mutable borrows of `names`. However, for `#[pyproto]` and some functions, you need to manually fix the code. #### Object creation In 0.8 object creation was done with `PyRef::new` and `PyRefMut::new`. In 0.9 these have both been removed. To upgrade code, please use `PyCell::new` instead. If you need [`PyRef`] or [`PyRefMut`], just call `.borrow()` or `.borrow_mut()` on the newly-created `PyCell`. Before: ```rust,compile_fail # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} # Python::with_gil(|py| { let obj_ref = PyRef::new(py, MyClass {}).unwrap(); # }) ``` After: ```rust,ignore # use pyo3::prelude::*; # #[pyclass] # struct MyClass {} # Python::with_gil(|py| { let obj = PyCell::new(py, MyClass {}).unwrap(); let obj_ref = obj.borrow(); # }) ``` #### Object extraction For `PyClass` types `T`, `&T` and `&mut T` no longer have [`FromPyObject`] implementations. Instead you should extract `PyRef` or `PyRefMut`, respectively. If `T` implements `Clone`, you can extract `T` itself. In addition, you can also extract `&PyCell`, though you rarely need it. Before: ```compile_fail let obj: &PyAny = create_obj(); let obj_ref: &MyClass = obj.extract().unwrap(); let obj_ref_mut: &mut MyClass = obj.extract().unwrap(); ``` After: ```rust,ignore # use pyo3::prelude::*; # use pyo3::types::IntoPyDict; # #[pyclass] #[derive(Clone)] struct MyClass {} # #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }} # Python::with_gil(|py| { # let typeobj = py.get_type::(); # let d = [("c", typeobj)].into_py_dict(py); # let create_obj = || py.eval("c()", None, Some(d)).unwrap(); let obj: &PyAny = create_obj(); let obj_cell: &PyCell = obj.extract().unwrap(); let obj_cloned: MyClass = obj.extract().unwrap(); // extracted by cloning the object { let obj_ref: PyRef<'_, MyClass> = obj.extract().unwrap(); // we need to drop obj_ref before we can extract a PyRefMut due to Rust's rules of references } let obj_ref_mut: PyRefMut<'_, MyClass> = obj.extract().unwrap(); # }) ``` #### `#[pyproto]` Most of the arguments to methods in `#[pyproto]` impls require a [`FromPyObject`] implementation. So if your protocol methods take `&T` or `&mut T` (where `T: PyClass`), please use [`PyRef`] or [`PyRefMut`] instead. Before: ```rust,compile_fail # use pyo3::prelude::*; # use pyo3::class::PySequenceProtocol; #[pyclass] struct ByteSequence { elements: Vec, } #[pyproto] impl PySequenceProtocol for ByteSequence { fn __concat__(&self, other: &Self) -> PyResult { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Ok(Self { elements }) } } ``` After: ```rust,compile_fail # use pyo3::prelude::*; # use pyo3::class::PySequenceProtocol; #[pyclass] struct ByteSequence { elements: Vec, } #[pyproto] impl PySequenceProtocol for ByteSequence { fn __concat__(&self, other: PyRef<'p, Self>) -> PyResult { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Ok(Self { elements }) } } ```
[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html [`PyAny`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html [`PyBorrowMutError`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyBorrowMutError.html [`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html pyo3/guide/src/index.md0000644000175000017500000000167414661133735015760 0ustar jamespagejamespage# The PyO3 user guide Welcome to the PyO3 user guide! This book is a companion to [PyO3's API docs](https://docs.rs/pyo3). It contains examples and documentation to explain all of PyO3's use cases in detail. The rough order of material in this user guide is as follows: 1. Getting started 2. Wrapping Rust code for use from Python 3. How to use Python code from Rust 4. Remaining topics which go into advanced concepts in detail Please choose from the chapters on the left to jump to individual topics, or continue below to start with PyO3's README.
⚠️ Warning: API update in progress 🛠️ PyO3 0.21 has introduced a significant new API, termed the "Bound" API after the new smart pointer `Bound`. While most of this guide has been updated to the new API, it is possible some stray references to the older "GIL Refs" API such as `&PyAny` remain.

{{#include ../../README.md}} pyo3/guide/src/ecosystem/0000775000175000017500000000000014661133735016334 5ustar jamespagejamespagepyo3/guide/src/ecosystem/async-await.md0000644000175000017500000004313014661133735021075 0ustar jamespagejamespage# Using `async` and `await` *`async`/`await` support is currently being integrated in PyO3. See the [dedicated documentation](../async-await.md)* If you are working with a Python library that makes use of async functions or wish to provide Python bindings for an async Rust library, [`pyo3-asyncio`](https://github.com/awestlake87/pyo3-asyncio) likely has the tools you need. It provides conversions between async functions in both Python and Rust and was designed with first-class support for popular Rust runtimes such as [`tokio`](https://tokio.rs/) and [`async-std`](https://async.rs/). In addition, all async Python code runs on the default `asyncio` event loop, so `pyo3-asyncio` should work just fine with existing Python libraries. In the following sections, we'll give a general overview of `pyo3-asyncio` explaining how to call async Python functions with PyO3, how to call async Rust functions from Python, and how to configure your codebase to manage the runtimes of both. ## Quickstart Here are some examples to get you started right away! A more detailed breakdown of the concepts in these examples can be found in the following sections. ### Rust Applications Here we initialize the runtime, import Python's `asyncio` library and run the given future to completion using Python's default `EventLoop` and `async-std`. Inside the future, we convert `asyncio` sleep into a Rust future and await it. ```toml # Cargo.toml dependencies [dependencies] pyo3 = { version = "0.14" } pyo3-asyncio = { version = "0.14", features = ["attributes", "async-std-runtime"] } async-std = "1.9" ``` ```rust //! main.rs use pyo3::prelude::*; #[pyo3_asyncio::async_std::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::async_std::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) })?; fut.await?; Ok(()) } ``` The same application can be written to use `tokio` instead using the `#[pyo3_asyncio::tokio::main]` attribute. ```toml # Cargo.toml dependencies [dependencies] pyo3 = { version = "0.14" } pyo3-asyncio = { version = "0.14", features = ["attributes", "tokio-runtime"] } tokio = "1.4" ``` ```rust //! main.rs use pyo3::prelude::*; #[pyo3_asyncio::tokio::main] async fn main() -> PyResult<()> { let fut = Python::with_gil(|py| { let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::tokio::into_future(asyncio.call_method1("sleep", (1.into_py(py),))?) })?; fut.await?; Ok(()) } ``` More details on the usage of this library can be found in the [API docs](https://awestlake87.github.io/pyo3-asyncio/master/doc) and the primer below. ### PyO3 Native Rust Modules PyO3 Asyncio can also be used to write native modules with async functions. Add the `[lib]` section to `Cargo.toml` to make your library a `cdylib` that Python can import. ```toml [lib] name = "my_async_module" crate-type = ["cdylib"] ``` Make your project depend on `pyo3` with the `extension-module` feature enabled and select your `pyo3-asyncio` runtime: For `async-std`: ```toml [dependencies] pyo3 = { version = "0.14", features = ["extension-module"] } pyo3-asyncio = { version = "0.14", features = ["async-std-runtime"] } async-std = "1.9" ``` For `tokio`: ```toml [dependencies] pyo3 = { version = "0.14", features = ["extension-module"] } pyo3-asyncio = { version = "0.14", features = ["tokio-runtime"] } tokio = "1.4" ``` Export an async function that makes use of `async-std`: ```rust //! lib.rs use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] fn rust_sleep(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>> { pyo3_asyncio::async_std::future_into_py(py, async { async_std::task::sleep(std::time::Duration::from_secs(1)).await; Ok(Python::with_gil(|py| py.None())) }) } #[pymodule] fn my_async_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rust_sleep, m)?) } ``` If you want to use `tokio` instead, here's what your module should look like: ```rust //! lib.rs use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] fn rust_sleep(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>>> { pyo3_asyncio::tokio::future_into_py(py, async { tokio::time::sleep(std::time::Duration::from_secs(1)).await; Ok(Python::with_gil(|py| py.None())) }) } #[pymodule] fn my_async_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rust_sleep, m)?) } ``` You can build your module with maturin (see the [Using Rust in Python](https://pyo3.rs/main/#using-rust-from-python) section in the PyO3 guide for setup instructions). After that you should be able to run the Python REPL to try it out. ```bash maturin develop && python3 🔗 Found pyo3 bindings 🐍 Found CPython 3.8 at python3 Finished dev [unoptimized + debuginfo] target(s) in 0.04s Python 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import asyncio >>> >>> from my_async_module import rust_sleep >>> >>> async def main(): >>> await rust_sleep() >>> >>> # should sleep for 1s >>> asyncio.run(main()) >>> ``` ## Awaiting an Async Python Function in Rust Let's take a look at a dead simple async Python function: ```python # Sleep for 1 second async def py_sleep(): await asyncio.sleep(1) ``` **Async functions in Python are simply functions that return a `coroutine` object**. For our purposes, we really don't need to know much about these `coroutine` objects. The key factor here is that calling an `async` function is _just like calling a regular function_, the only difference is that we have to do something special with the object that it returns. Normally in Python, that something special is the `await` keyword, but in order to await this coroutine in Rust, we first need to convert it into Rust's version of a `coroutine`: a `Future`. That's where `pyo3-asyncio` comes in. [`pyo3_asyncio::async_std::into_future`](https://docs.rs/pyo3-asyncio/latest/pyo3_asyncio/async_std/fn.into_future.html) performs this conversion for us. The following example uses `into_future` to call the `py_sleep` function shown above and then await the coroutine object returned from the call: ```rust use pyo3::prelude::*; #[pyo3_asyncio::tokio::main] async fn main() -> PyResult<()> { let future = Python::with_gil(|py| -> PyResult<_> { // import the module containing the py_sleep function let example = py.import("example")?; // calling the py_sleep method like a normal function // returns a coroutine let coroutine = example.call_method0("py_sleep")?; // convert the coroutine into a Rust future using the // tokio runtime pyo3_asyncio::tokio::into_future(coroutine) })?; // await the future future.await?; Ok(()) } ``` Alternatively, the below example shows how to write a `#[pyfunction]` which uses `into_future` to receive and await a coroutine argument: ```rust #[pyfunction] fn await_coro(coro: &Bound<'_, PyAny>>) -> PyResult<()> { // convert the coroutine into a Rust future using the // async_std runtime let f = pyo3_asyncio::async_std::into_future(coro)?; pyo3_asyncio::async_std::run_until_complete(coro.py(), async move { // await the future f.await?; Ok(()) }) } ``` This could be called from Python as: ```python import asyncio async def py_sleep(): asyncio.sleep(1) await_coro(py_sleep()) ``` If you wanted to pass a callable function to the `#[pyfunction]` instead, (i.e. the last line becomes `await_coro(py_sleep))`, then the above example needs to be tweaked to first call the callable to get the coroutine: ```rust #[pyfunction] fn await_coro(callable: &Bound<'_, PyAny>>) -> PyResult<()> { // get the coroutine by calling the callable let coro = callable.call0()?; // convert the coroutine into a Rust future using the // async_std runtime let f = pyo3_asyncio::async_std::into_future(coro)?; pyo3_asyncio::async_std::run_until_complete(coro.py(), async move { // await the future f.await?; Ok(()) }) } ``` This can be particularly helpful where you need to repeatedly create and await a coroutine. Trying to await the same coroutine multiple times will raise an error: ```python RuntimeError: cannot reuse already awaited coroutine ``` > If you're interested in learning more about `coroutines` and `awaitables` in general, check out the > [Python 3 `asyncio` docs](https://docs.python.org/3/library/asyncio-task.html) for more information. ## Awaiting a Rust Future in Python Here we have the same async function as before written in Rust using the [`async-std`](https://async.rs/) runtime: ```rust /// Sleep for 1 second async fn rust_sleep() { async_std::task::sleep(std::time::Duration::from_secs(1)).await; } ``` Similar to Python, Rust's async functions also return a special object called a `Future`: ```rust let future = rust_sleep(); ``` We can convert this `Future` object into Python to make it `awaitable`. This tells Python that you can use the `await` keyword with it. In order to do this, we'll call [`pyo3_asyncio::async_std::future_into_py`](https://docs.rs/pyo3-asyncio/latest/pyo3_asyncio/async_std/fn.future_into_py.html): ```rust use pyo3::prelude::*; async fn rust_sleep() { async_std::task::sleep(std::time::Duration::from_secs(1)).await; } #[pyfunction] fn call_rust_sleep(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>>> { pyo3_asyncio::async_std::future_into_py(py, async move { rust_sleep().await; Ok(Python::with_gil(|py| py.None())) }) } ``` In Python, we can call this pyo3 function just like any other async function: ```python from example import call_rust_sleep async def rust_sleep(): await call_rust_sleep() ``` ## Managing Event Loops Python's event loop requires some special treatment, especially regarding the main thread. Some of Python's `asyncio` features, like proper signal handling, require control over the main thread, which doesn't always play well with Rust. Luckily, Rust's event loops are pretty flexible and don't _need_ control over the main thread, so in `pyo3-asyncio`, we decided the best way to handle Rust/Python interop was to just surrender the main thread to Python and run Rust's event loops in the background. Unfortunately, since most event loop implementations _prefer_ control over the main thread, this can still make some things awkward. ### PyO3 Asyncio Initialization Because Python needs to control the main thread, we can't use the convenient proc macros from Rust runtimes to handle the `main` function or `#[test]` functions. Instead, the initialization for PyO3 has to be done from the `main` function and the main thread must block on [`pyo3_asyncio::async_std::run_until_complete`](https://docs.rs/pyo3-asyncio/latest/pyo3_asyncio/async_std/fn.run_until_complete.html). Because we have to block on one of those functions, we can't use [`#[async_std::main]`](https://docs.rs/async-std/latest/async_std/attr.main.html) or [`#[tokio::main]`](https://docs.rs/tokio/1.1.0/tokio/attr.main.html) since it's not a good idea to make long blocking calls during an async function. > Internally, these `#[main]` proc macros are expanded to something like this: > ```rust > fn main() { > // your async main fn > async fn _main_impl() { /* ... */ } > Runtime::new().block_on(_main_impl()); > } > ``` > Making a long blocking call inside the `Future` that's being driven by `block_on` prevents that > thread from doing anything else and can spell trouble for some runtimes (also this will actually > deadlock a single-threaded runtime!). Many runtimes have some sort of `spawn_blocking` mechanism > that can avoid this problem, but again that's not something we can use here since we need it to > block on the _main_ thread. For this reason, `pyo3-asyncio` provides its own set of proc macros to provide you with this initialization. These macros are intended to mirror the initialization of `async-std` and `tokio` while also satisfying the Python runtime's needs. Here's a full example of PyO3 initialization with the `async-std` runtime: ```rust use pyo3::prelude::*; #[pyo3_asyncio::async_std::main] async fn main() -> PyResult<()> { // PyO3 is initialized - Ready to go let fut = Python::with_gil(|py| -> PyResult<_> { let asyncio = py.import("asyncio")?; // convert asyncio.sleep into a Rust Future pyo3_asyncio::async_std::into_future( asyncio.call_method1("sleep", (1.into_py(py),))? ) })?; fut.await?; Ok(()) } ``` ### A Note About `asyncio.run` In Python 3.7+, the recommended way to run a top-level coroutine with `asyncio` is with `asyncio.run`. In `v0.13` we recommended against using this function due to initialization issues, but in `v0.14` it's perfectly valid to use this function... with a caveat. Since our Rust <--> Python conversions require a reference to the Python event loop, this poses a problem. Imagine we have a PyO3 Asyncio module that defines a `rust_sleep` function like in previous examples. You might rightfully assume that you can call pass this directly into `asyncio.run` like this: ```python import asyncio from my_async_module import rust_sleep asyncio.run(rust_sleep()) ``` You might be surprised to find out that this throws an error: ```bash Traceback (most recent call last): File "example.py", line 5, in asyncio.run(rust_sleep()) RuntimeError: no running event loop ``` What's happening here is that we are calling `rust_sleep` _before_ the future is actually running on the event loop created by `asyncio.run`. This is counter-intuitive, but expected behaviour, and unfortunately there doesn't seem to be a good way of solving this problem within PyO3 Asyncio itself. However, we can make this example work with a simple workaround: ```python import asyncio from my_async_module import rust_sleep # Calling main will just construct the coroutine that later calls rust_sleep. # - This ensures that rust_sleep will be called when the event loop is running, # not before. async def main(): await rust_sleep() # Run the main() coroutine at the top-level instead asyncio.run(main()) ``` ### Non-standard Python Event Loops Python allows you to use alternatives to the default `asyncio` event loop. One popular alternative is `uvloop`. In `v0.13` using non-standard event loops was a bit of an ordeal, but in `v0.14` it's trivial. #### Using `uvloop` in a PyO3 Asyncio Native Extensions ```toml # Cargo.toml [lib] name = "my_async_module" crate-type = ["cdylib"] [dependencies] pyo3 = { version = "0.14", features = ["extension-module"] } pyo3-asyncio = { version = "0.14", features = ["tokio-runtime"] } async-std = "1.9" tokio = "1.4" ``` ```rust //! lib.rs use pyo3::{prelude::*, wrap_pyfunction}; #[pyfunction] fn rust_sleep(py: Python<'_>) -> PyResult<&Bound<'_, PyAny>>> { pyo3_asyncio::tokio::future_into_py(py, async { tokio::time::sleep(std::time::Duration::from_secs(1)).await; Ok(Python::with_gil(|py| py.None())) }) } #[pymodule] fn my_async_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rust_sleep, m)?)?; Ok(()) } ``` ```bash $ maturin develop && python3 🔗 Found pyo3 bindings 🐍 Found CPython 3.8 at python3 Finished dev [unoptimized + debuginfo] target(s) in 0.04s Python 3.8.8 (default, Apr 13 2021, 19:58:26) [GCC 7.3.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> import asyncio >>> import uvloop >>> >>> import my_async_module >>> >>> uvloop.install() >>> >>> async def main(): ... await my_async_module.rust_sleep() ... >>> asyncio.run(main()) >>> ``` #### Using `uvloop` in Rust Applications Using `uvloop` in Rust applications is a bit trickier, but it's still possible with relatively few modifications. Unfortunately, we can't make use of the `#[pyo3_asyncio::::main]` attribute with non-standard event loops. This is because the `#[pyo3_asyncio::::main]` proc macro has to interact with the Python event loop before we can install the `uvloop` policy. ```toml [dependencies] async-std = "1.9" pyo3 = "0.14" pyo3-asyncio = { version = "0.14", features = ["async-std-runtime"] } ``` ```rust //! main.rs use pyo3::{prelude::*, types::PyType}; fn main() -> PyResult<()> { pyo3::prepare_freethreaded_python(); Python::with_gil(|py| { let uvloop = py.import("uvloop")?; uvloop.call_method0("install")?; // store a reference for the assertion let uvloop = PyObject::from(uvloop); pyo3_asyncio::async_std::run(py, async move { // verify that we are on a uvloop.Loop Python::with_gil(|py| -> PyResult<()> { assert!(pyo3_asyncio::async_std::get_current_loop(py)?.is_instance( uvloop .as_ref(py) .getattr("Loop")? )?); Ok(()) })?; async_std::task::sleep(std::time::Duration::from_secs(1)).await; Ok(()) }) }) } ``` ## Additional Information - Managing event loop references can be tricky with pyo3-asyncio. See [Event Loop References](https://docs.rs/pyo3-asyncio/#event-loop-references) in the API docs to get a better intuition for how event loop references are managed in this library. - Testing pyo3-asyncio libraries and applications requires a custom test harness since Python requires control over the main thread. You can find a testing guide in the [API docs for the `testing` module](https://docs.rs/pyo3-asyncio/latest/pyo3_asyncio/testing) pyo3/guide/src/ecosystem/logging.md0000644000175000017500000000615414661133735020310 0ustar jamespagejamespage# Logging It is desirable if both the Python and Rust parts of the application end up logging using the same configuration into the same place. This section of the guide briefly discusses how to connect the two languages' logging ecosystems together. The recommended way for Python extension modules is to configure Rust's logger to send log messages to Python using the `pyo3-log` crate. For users who want to do the opposite and send Python log messages to Rust, see the note at the end of this guide. ## Using `pyo3-log` to send Rust log messages to Python The [pyo3-log] crate allows sending the messages from the Rust side to Python's [logging] system. This is mostly suitable for writing native extensions for Python programs. Use [`pyo3_log::init`][init] to install the logger in its default configuration. It's also possible to tweak its configuration (mostly to tune its performance). ```rust use log::info; use pyo3::prelude::*; #[pyfunction] fn log_something() { // This will use the logger installed in `my_module` to send the `info` // message to the Python logging facilities. info!("Something!"); } #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { // A good place to install the Rust -> Python logger. pyo3_log::init(); m.add_function(wrap_pyfunction!(log_something, m)?)?; Ok(()) } ``` Then it is up to the Python side to actually output the messages somewhere. ```python import logging import my_module FORMAT = '%(levelname)s %(name)s %(asctime)-15s %(filename)s:%(lineno)d %(message)s' logging.basicConfig(format=FORMAT) logging.getLogger().setLevel(logging.INFO) my_module.log_something() ``` It is important to initialize the Python loggers first, before calling any Rust functions that may log. This limitation can be worked around if it is not possible to satisfy, read the documentation about [caching]. ## The Python to Rust direction To have python logs be handled by Rust, one need only register a rust function to handle logs emitted from the core python logging module. This has been implemented within the [pyo3-pylogger] crate. ```rust use log::{info, warn}; use pyo3::prelude::*; fn main() -> PyResult<()> { // register the host handler with python logger, providing a logger target // set the name here to something appropriate for your application pyo3_pylogger::register("example_application_py_logger"); // initialize up a logger env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init(); // Log some messages from Rust. info!("Just some normal information!"); warn!("Something spooky happened!"); // Log some messages from Python Python::with_gil(|py| { py.run( " import logging logging.error('Something bad happened') ", None, None, ) }) } ``` [logging]: https://docs.python.org/3/library/logging.html [pyo3-log]: https://crates.io/crates/pyo3-log [init]: https://docs.rs/pyo3-log/*/pyo3_log/fn.init.html [caching]: https://docs.rs/pyo3-log/*/pyo3_log/#performance-filtering-and-caching [pyo3-pylogger]: https://crates.io/crates/pyo3-pylogger pyo3/guide/src/trait-bounds.md0000644000175000017500000004056614661133735017267 0ustar jamespagejamespage# Using in Python a Rust function with trait bounds PyO3 allows for easy conversion from Rust to Python for certain functions and classes (see the [conversion table](conversions/tables.md)). However, it is not always straightforward to convert Rust code that requires a given trait implementation as an argument. This tutorial explains how to convert a Rust function that takes a trait as argument for use in Python with classes implementing the same methods as the trait. Why is this useful? ### Pros - Make your Rust code available to Python users - Code complex algorithms in Rust with the help of the borrow checker ### Cons - Not as fast as native Rust (type conversion has to be performed and one part of the code runs in Python) - You need to adapt your code to expose it ## Example Let's work with the following basic example of an implementation of a optimization solver operating on a given model. Let's say we have a function `solve` that operates on a model and mutates its state. The argument of the function can be any model that implements the `Model` trait : ```rust # #![allow(dead_code)] pub trait Model { fn set_variables(&mut self, inputs: &Vec); fn compute(&mut self); fn get_results(&self) -> Vec; } pub fn solve(model: &mut T) { println!("Magic solver that mutates the model into a resolved state"); } ``` Let's assume we have the following constraints: - We cannot change that code as it runs on many Rust models. - We also have many Python models that cannot be solved as this solver is not available in that language. Rewriting it in Python would be cumbersome and error-prone, as everything is already available in Rust. How could we expose this solver to Python thanks to PyO3 ? ## Implementation of the trait bounds for the Python class If a Python class implements the same three methods as the `Model` trait, it seems logical it could be adapted to use the solver. However, it is not possible to pass a `PyObject` to it as it does not implement the Rust trait (even if the Python model has the required methods). In order to implement the trait, we must write a wrapper around the calls in Rust to the Python model. The method signatures must be the same as the trait, keeping in mind that the Rust trait cannot be changed for the purpose of making the code available in Python. The Python model we want to expose is the following one, which already contains all the required methods: ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 - 3 for elt in self.inputs] def get_results(self): return self.results ``` The following wrapper will call the Python model from Rust, using a struct to hold the model as a `PyAny` object: ```rust # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyList; # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } struct UserModel { model: Py, } impl Model for UserModel { fn set_variables(&mut self, var: &Vec) { println!("Rust calling Python to set the variables"); Python::with_gil(|py| { self.model .bind(py) .call_method("set_variables", (PyList::new_bound(py, var),), None) .unwrap(); }) } fn get_results(&self) -> Vec { println!("Rust calling Python to get the results"); Python::with_gil(|py| { self.model .bind(py) .call_method("get_results", (), None) .unwrap() .extract() .unwrap() }) } fn compute(&mut self) { println!("Rust calling Python to perform the computation"); Python::with_gil(|py| { self.model .bind(py) .call_method("compute", (), None) .unwrap(); }) } } ``` Now that this bit is implemented, let's expose the model wrapper to Python. Let's add the PyO3 annotations and add a constructor: ```rust # #![allow(dead_code)] # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # use pyo3::prelude::*; #[pyclass] struct UserModel { model: Py, } #[pymodule] fn trait_exposure(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; Ok(()) } #[pymethods] impl UserModel { #[new] pub fn new(model: Py) -> Self { UserModel { model } } } ``` Now we add the PyO3 annotations to the trait implementation: ```rust,ignore #[pymethods] impl Model for UserModel { // the previous trait implementation } ``` However, the previous code will not compile. The compilation error is the following one: `error: #[pymethods] cannot be used on trait impl blocks` That's a bummer! However, we can write a second wrapper around these functions to call them directly. This wrapper will also perform the type conversions between Python and Rust. ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } # # impl Model for UserModel { # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::with_gil(|py| { # self.model.bind(py) # .call_method("set_variables", (PyList::new_bound(py, var),), None) # .unwrap(); # }) # } # # fn get_results(&self) -> Vec { # println!("Rust calling Python to get the results"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("get_results", (), None) # .unwrap() # .extract() # .unwrap() # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # # } # } #[pymethods] impl UserModel { pub fn set_variables(&mut self, var: Vec) { println!("Set variables from Python calling Rust"); Model::set_variables(self, &var) } pub fn get_results(&mut self) -> Vec { println!("Get results from Python calling Rust"); Model::get_results(self) } pub fn compute(&mut self) { println!("Compute from Python calling Rust"); Model::compute(self) } } ``` This wrapper handles the type conversion between the PyO3 requirements and the trait. In order to meet PyO3 requirements, this wrapper must: - return an object of type `PyResult` - use only values, not references in the method signatures Let's run the file python file: ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 - 3 for elt in self.inputs] def get_results(self): return self.results if __name__=="__main__": import trait_exposure myModel = Model() my_rust_model = trait_exposure.UserModel(myModel) my_rust_model.set_variables([2.0]) print("Print value from Python: ", myModel.inputs) my_rust_model.compute() print("Print value from Python through Rust: ", my_rust_model.get_results()) print("Print value directly from Python: ", myModel.get_results()) ``` This outputs: ```block Set variables from Python calling Rust Set variables from Rust calling Python Print value from Python: [2.0] Compute from Python calling Rust Compute from Rust calling Python Get results from Python calling Rust Get results from Rust calling Python Print value from Python through Rust: [1.0] Print value directly from Python: [1.0] ``` We have now successfully exposed a Rust model that implements the `Model` trait to Python! We will now expose the `solve` function, but before, let's talk about types errors. ## Type errors in Python What happens if you have type errors when using Python and how can you improve the error messages? ### Wrong types in Python function arguments Let's assume in the first case that you will use in your Python file `my_rust_model.set_variables(2.0)` instead of `my_rust_model.set_variables([2.0])`. The Rust signature expects a vector, which corresponds to a list in Python. What happens if instead of a vector, we pass a single value ? At the execution of Python, we get : ```block File "main.py", line 15, in my_rust_model.set_variables(2) TypeError ``` It is a type error and Python points to it, so it's easy to identify and solve. ### Wrong types in Python method signatures Let's assume now that the return type of one of the methods of our Model class is wrong, for example the `get_results` method that is expected to return a `Vec` in Rust, a list in Python. ```python class Model: def set_variables(self, inputs): self.inputs = inputs def compute(self): self.results = [elt**2 -3 for elt in self.inputs] def get_results(self): return self.results[0] #return self.results <-- this is the expected output ``` This call results in the following panic: ```block pyo3_runtime.PanicException: called `Result::unwrap()` on an `Err` value: PyErr { type: Py(0x10dcf79f0, PhantomData) } ``` This error code is not helpful for a Python user that does not know anything about Rust, or someone that does not know PyO3 was used to interface the Rust code. However, as we are responsible for making the Rust code available to Python, we can do something about it. The issue is that we called `unwrap` anywhere we could, and therefore any panic from PyO3 will be directly forwarded to the end user. Let's modify the code performing the type conversion to give a helpful error message to the Python user: We used in our `get_results` method the following call that performs the type conversion: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } impl Model for UserModel { fn get_results(&self) -> Vec { println!("Rust calling Python to get the results"); Python::with_gil(|py| { self.model .bind(py) .call_method("get_results", (), None) .unwrap() .extract() .unwrap() }) } # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::with_gil(|py| { # self.model.bind(py) # .call_method("set_variables", (PyList::new_bound(py, var),), None) # .unwrap(); # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # } } ``` Let's break it down in order to perform better error handling: ```rust # #![allow(dead_code)] # use pyo3::prelude::*; # use pyo3::types::PyList; # # pub trait Model { # fn set_variables(&mut self, inputs: &Vec); # fn compute(&mut self); # fn get_results(&self) -> Vec; # } # # #[pyclass] # struct UserModel { # model: Py, # } impl Model for UserModel { fn get_results(&self) -> Vec { println!("Get results from Rust calling Python"); Python::with_gil(|py| { let py_result: Bound<'_, PyAny> = self .model .bind(py) .call_method("get_results", (), None) .unwrap(); if py_result.get_type().name().unwrap() != "list" { panic!( "Expected a list for the get_results() method signature, got {}", py_result.get_type().name().unwrap() ); } py_result.extract() }) .unwrap() } # fn set_variables(&mut self, var: &Vec) { # println!("Rust calling Python to set the variables"); # Python::with_gil(|py| { # let py_model = self.model.bind(py) # .call_method("set_variables", (PyList::new_bound(py, var),), None) # .unwrap(); # }) # } # # fn compute(&mut self) { # println!("Rust calling Python to perform the computation"); # Python::with_gil(|py| { # self.model # .bind(py) # .call_method("compute", (), None) # .unwrap(); # }) # } } ``` By doing so, you catch the result of the Python computation and check its type in order to be able to deliver a better error message before performing the unwrapping. Of course, it does not cover all the possible wrong outputs: the user could return a list of strings instead of a list of floats. In this case, a runtime panic would still occur due to PyO3, but with an error message much more difficult to decipher for non-rust user. It is up to the developer exposing the rust code to decide how much effort to invest into Python type error handling and improved error messages. ## The final code Now let's expose the `solve()` function to make it available from Python. It is not possible to directly expose the `solve` function to Python, as the type conversion cannot be performed. It requires an object implementing the `Model` trait as input. However, the `UserModel` already implements this trait. Because of this, we can write a function wrapper that takes the `UserModel`--which has already been exposed to Python--as an argument in order to call the core function `solve`. It is also required to make the struct public. ```rust # #![allow(dead_code)] use pyo3::prelude::*; use pyo3::types::PyList; pub trait Model { fn set_variables(&mut self, var: &Vec); fn get_results(&self) -> Vec; fn compute(&mut self); } pub fn solve(model: &mut T) { println!("Magic solver that mutates the model into a resolved state"); } #[pyfunction] #[pyo3(name = "solve")] pub fn solve_wrapper(model: &mut UserModel) { solve(model); } #[pyclass] pub struct UserModel { model: Py, } #[pymodule] fn trait_exposure(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_function(wrap_pyfunction!(solve_wrapper, m)?)?; Ok(()) } #[pymethods] impl UserModel { #[new] pub fn new(model: Py) -> Self { UserModel { model } } pub fn set_variables(&mut self, var: Vec) { println!("Set variables from Python calling Rust"); Model::set_variables(self, &var) } pub fn get_results(&mut self) -> Vec { println!("Get results from Python calling Rust"); Model::get_results(self) } pub fn compute(&mut self) { Model::compute(self) } } impl Model for UserModel { fn set_variables(&mut self, var: &Vec) { println!("Rust calling Python to set the variables"); Python::with_gil(|py| { self.model .bind(py) .call_method("set_variables", (PyList::new_bound(py, var),), None) .unwrap(); }) } fn get_results(&self) -> Vec { println!("Get results from Rust calling Python"); Python::with_gil(|py| { let py_result: Bound<'_, PyAny> = self .model .bind(py) .call_method("get_results", (), None) .unwrap(); if py_result.get_type().name().unwrap() != "list" { panic!( "Expected a list for the get_results() method signature, got {}", py_result.get_type().name().unwrap() ); } py_result.extract() }) .unwrap() } fn compute(&mut self) { println!("Rust calling Python to perform the computation"); Python::with_gil(|py| { self.model .bind(py) .call_method("compute", (), None) .unwrap(); }) } } ``` pyo3/guide/book.toml0000644000175000017500000000055214661133735015361 0ustar jamespagejamespage[book] title = "PyO3 user guide" description = "PyO3 user guide" author = "PyO3 Project and Contributors" [preprocessor.pyo3_version] command = "python3 guide/pyo3_version.py" [output.html] git-repository-url = "https://github.com/PyO3/pyo3/tree/main/guide" edit-url-template = "https://github.com/PyO3/pyo3/edit/main/guide/{path}" playground.runnable = false pyo3/guide/pyo3_version.py0000644000175000017500000000326514661133735016547 0ustar jamespagejamespage"""Simple mdbook preprocessor to inject pyo3 version into the guide. It will replace: - {{#PYO3_VERSION_TAG}} with the contents of the PYO3_VERSION_TAG environment var - {{#PYO3_DOCS_URL}} with the location of docs (e.g. 'https://docs.rs/pyo3/0.13.2') - {{#PYO3_CRATE_VERSION}} with a relevant toml snippet (e.g. 'version = "0.13.2"') Tested against mdbook 0.4.10. """ import json import os import sys # Set PYO3_VERSION in CI to build the correct version into links PYO3_VERSION_TAG = os.environ.get("PYO3_VERSION_TAG", "main") if PYO3_VERSION_TAG == "main": PYO3_DOCS_URL = "https://pyo3.rs/main/doc" PYO3_DOCS_VERSION = "latest" PYO3_CRATE_VERSION = 'git = "https://github.com/pyo3/pyo3"' else: # v0.13.2 -> 0.13.2 version = PYO3_VERSION_TAG.lstrip("v") PYO3_DOCS_URL = f"https://docs.rs/pyo3/{version}" PYO3_DOCS_VERSION = version PYO3_CRATE_VERSION = f'version = "{version}"' def replace_section_content(section): if not isinstance(section, dict) or "Chapter" not in section: return # Replace raw and url-encoded forms section["Chapter"]["content"] = ( section["Chapter"]["content"] .replace("{{#PYO3_VERSION_TAG}}", PYO3_VERSION_TAG) .replace("{{#PYO3_DOCS_URL}}", PYO3_DOCS_URL) .replace("{{#PYO3_DOCS_VERSION}}", PYO3_DOCS_VERSION) .replace("{{#PYO3_CRATE_VERSION}}", PYO3_CRATE_VERSION) ) for sub_item in section["Chapter"]["sub_items"]: replace_section_content(sub_item) for line in sys.stdin: if line: [context, book] = json.loads(line) for section in book["sections"]: replace_section_content(section) json.dump(book, fp=sys.stdout) pyo3/guide/pyclass-parameters.md0000644000175000017500000001060114661133735017667 0ustar jamespagejamespage`#[pyclass]` can be used with the following parameters: | Parameter | Description | | :- | :- | | `constructor` | This is currently only allowed on [variants of complex enums][params-constructor]. It allows customization of the generated class constructor for each variant. It uses the same syntax and supports the same options as the `signature` attribute of functions and methods. | | `crate = "some::path"` | Path to import the `pyo3` crate, if it's not accessible at `::pyo3`. | | `dict` | Gives instances of this class an empty `__dict__` to store custom attributes. | | `eq` | Implements `__eq__` using the `PartialEq` implementation of the underlying Rust datatype. | | `eq_int` | Implements `__eq__` using `__int__` for simple enums. | | `extends = BaseType` | Use a custom baseclass. Defaults to [`PyAny`][params-1] | | `freelist = N` | Implements a [free list][params-2] of size N. This can improve performance for types that are often created and deleted in quick succession. Profile your code to see whether `freelist` is right for you. | | `frozen` | Declares that your pyclass is immutable. It removes the borrow checker overhead when retrieving a shared reference to the Rust struct, but disables the ability to get a mutable reference. | | `get_all` | Generates getters for all fields of the pyclass. | | `hash` | Implements `__hash__` using the `Hash` implementation of the underlying Rust datatype. | | `mapping` | Inform PyO3 that this class is a [`Mapping`][params-mapping], and so leave its implementation of sequence C-API slots empty. | | `module = "module_name"` | Python code will see the class as being defined in this module. Defaults to `builtins`. | | `name = "python_name"` | Sets the name that Python sees this class as. Defaults to the name of the Rust struct. | | `ord` | Implements `__lt__`, `__gt__`, `__le__`, & `__ge__` using the `PartialOrd` implementation of the underlying Rust datatype. *Requires `eq`* | | `rename_all = "renaming_rule"` | Applies renaming rules to every getters and setters of a struct, or every variants of an enum. Possible values are: "camelCase", "kebab-case", "lowercase", "PascalCase", "SCREAMING-KEBAB-CASE", "SCREAMING_SNAKE_CASE", "snake_case", "UPPERCASE". | | `sequence` | Inform PyO3 that this class is a [`Sequence`][params-sequence], and so leave its C-API mapping length slot empty. | | `set_all` | Generates setters for all fields of the pyclass. | | `subclass` | Allows other Python classes and `#[pyclass]` to inherit from this class. Enums cannot be subclassed. | | `text_signature = "(arg1, arg2, ...)"` | Sets the text signature for the Python class' `__new__` method. | | `unsendable` | Required if your struct is not [`Send`][params-3]. Rather than using `unsendable`, consider implementing your struct in a threadsafe way by e.g. substituting [`Rc`][params-4] with [`Arc`][params-5]. By using `unsendable`, your class will panic when accessed by another thread. Also note the Python's GC is multi-threaded and while unsendable classes will not be traversed on foreign threads to avoid UB, this can lead to memory leaks. | | `weakref` | Allows this class to be [weakly referenceable][params-6]. | All of these parameters can either be passed directly on the `#[pyclass(...)]` annotation, or as one or more accompanying `#[pyo3(...)]` annotations, e.g.: ```rust,ignore // Argument supplied directly to the `#[pyclass]` annotation. #[pyclass(name = "SomeName", subclass)] struct MyClass {} // Argument supplied as a separate annotation. #[pyclass] #[pyo3(name = "SomeName", subclass)] struct MyClass {} ``` [params-1]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyAny.html [params-2]: https://en.wikipedia.org/wiki/Free_list [params-3]: https://doc.rust-lang.org/std/marker/trait.Send.html [params-4]: https://doc.rust-lang.org/std/rc/struct.Rc.html [params-5]: https://doc.rust-lang.org/std/sync/struct.Arc.html [params-6]: https://docs.python.org/3/library/weakref.html [params-constructor]: https://pyo3.rs/latest/class.html#complex-enums [params-mapping]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types [params-sequence]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types pyo3/Releasing.md0000644000175000017500000000656614661133735014703 0ustar jamespagejamespage# Releasing This is notes for the current process of releasing a new PyO3 version. Replace `` in all instructions below with the new version. ## 1. Prepare the release commit Follow the process below to update all required pieces to bump the version. All these changes are done in a single commit because it makes it clear to git readers what happened to bump the version. It also makes it easy to cherry-pick the version bump onto the `main` branch when tidying up branch history at the end of the release process. 1. Replace all instances of the PyO3 current version and the with the new version to be released. Places to check: - `Cargo.toml` for all PyO3 crates in the repository. - Examples in `README.md` - PyO3 version embedded into documentation like the README. - `pre-script.rhai` templates for the examples. - `[towncrier]` section in `pyproject.toml`. Some of the above locations may already have the new version with a `-dev` suffix, which needs to be removed. **Make sure not to modify the CHANGELOG during this step!** 2. Run `towncrier build` to generate the CHANGELOG. The version used by `towncrier` should automatically be correct because of the update to `pyproject.toml` in step 1. 3. Manually edit the CHANGELOG for final notes. Steps to do: - Adjust wording of any release lines to make them clearer for users / fix typos. - Add a new link at the bottom for the new version, and update the `Unreleased` link. 4. Create the commit containing all the above changes, with a message of `release: `. Push to `release-` branch on the main PyO3 repository, where `` depends on whether this is a major or minor release: - for O.X.0 minor releases, just use `0.X`, e.g. `release-0.17`. This will become the maintenance branch after release. - for 0.X.Y patch releases, use the full `0.X.Y`, e.g. `release-0.17.1`. This will be deleted after merge. ## 2. Create the release PR and draft release notes Open a PR for the branch, and confirm that it passes CI. For `0.X.0` minor releases, the PR should be merging into `main`, for `0.X.Y` patch releases, the PR should be merging the `release-0.X` maintenance branch. On https://github.com/PyO3/pyo3/releases, click "Draft a new release". The tag will be a new tag of `v` (note preceding `v`) and target should be the `release-` branch you just pushed. Write release notes which match the style of previous releases. You can get the list of contributors by running `nox -s contributors -- v release-` to get contributors from the previous version tag through to the branch tip you just pushed. (This uses the GitHub API, so you'll need to push the branch first.) Save as a draft and wait for now. ## 3. Leave for a cooling off period Wait a couple of days in case anyone wants to hold up the release to add bugfixes etc. ## 4. Put live To put live: - 1. run `nox -s publish` to put live on crates.io - 2. publish the release on Github - 3. merge the release PR ## 5. Tidy the main branch If the release PR targeted a branch other than main, you will need to cherry-pick the version bumps, CHANGELOG modifications and removal of towncrier `newsfragments` and open another PR to land these on main. ## 6. Delete the release branch (patch releases only) For 0.X.Y patch releases, the release branch is no longer needed, so it should be deleted. pyo3/build.rs0000644000175000017500000000376014661133735014106 0ustar jamespagejamespageuse std::env; use pyo3_build_config::pyo3_build_script_impl::{cargo_env_var, errors::Result}; use pyo3_build_config::{bail, print_feature_cfgs, InterpreterConfig}; fn ensure_auto_initialize_ok(interpreter_config: &InterpreterConfig) -> Result<()> { if cargo_env_var("CARGO_FEATURE_AUTO_INITIALIZE").is_some() && !interpreter_config.shared { bail!( "The `auto-initialize` feature is enabled, but your python installation only supports \ embedding the Python interpreter statically. If you are attempting to run tests, or a \ binary which is okay to link dynamically, install a Python distribution which ships \ with the Python shared library.\n\ \n\ Embedding the Python interpreter statically does not yet have first-class support in \ PyO3. If you are sure you intend to do this, disable the `auto-initialize` feature.\n\ \n\ For more information, see \ https://pyo3.rs/v{pyo3_version}/\ building-and-distribution.html#embedding-python-in-rust", pyo3_version = env::var("CARGO_PKG_VERSION").unwrap() ); } Ok(()) } /// Prepares the PyO3 crate for compilation. /// /// This loads the config from pyo3-build-config and then makes some additional checks to improve UX /// for users. /// /// Emits the cargo configuration based on this config as well as a few checks of the Rust compiler /// version to enable features which aren't supported on MSRV. fn configure_pyo3() -> Result<()> { let interpreter_config = pyo3_build_config::get(); ensure_auto_initialize_ok(interpreter_config)?; for cfg in interpreter_config.build_script_outputs() { println!("{}", cfg) } // Emit cfgs like `invalid_from_utf8_lint` print_feature_cfgs(); Ok(()) } fn main() { pyo3_build_config::print_expected_cfgs(); if let Err(e) = configure_pyo3() { eprintln!("error: {}", e.report()); std::process::exit(1) } } pyo3/README.md0000644000175000017500000004077614661133735013730 0ustar jamespagejamespage# PyO3 [![actions status](https://img.shields.io/github/actions/workflow/status/PyO3/pyo3/ci.yml?branch=main&logo=github&style=)](https://github.com/PyO3/pyo3/actions) [![benchmark](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/PyO3/pyo3) [![codecov](https://img.shields.io/codecov/c/gh/PyO3/pyo3?logo=codecov)](https://codecov.io/gh/PyO3/pyo3) [![crates.io](https://img.shields.io/crates/v/pyo3?logo=rust)](https://crates.io/crates/pyo3) [![minimum rustc 1.63](https://img.shields.io/badge/rustc-1.63+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html) [![discord server](https://img.shields.io/discord/1209263839632424990?logo=discord)](https://discord.gg/33kcChzH7f) [![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green?logo=github)](https://github.com/PyO3/pyo3/blob/main/Contributing.md) [Rust](https://www.rust-lang.org/) bindings for [Python](https://www.python.org/), including tools for creating native Python extension modules. Running and interacting with Python code from a Rust binary is also supported. - User Guide: [stable](https://pyo3.rs) | [main](https://pyo3.rs/main) - API Documentation: [stable](https://docs.rs/pyo3/) | [main](https://pyo3.rs/main/doc) ## Usage PyO3 supports the following software versions: - Python 3.7 and up (CPython, PyPy, and GraalPy) - Rust 1.63 and up You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn. ### Using Rust from Python PyO3 can be used to generate a native Python module. The easiest way to try this out for the first time is to use [`maturin`](https://github.com/PyO3/maturin). `maturin` is a tool for building and publishing Rust-based Python packages with minimal configuration. The following steps install `maturin`, use it to generate and build a new Python package, and then launch Python to import and execute a function from the package. First, follow the commands below to create a new directory containing a new Python `virtualenv`, and install `maturin` into the virtualenv using Python's package manager, `pip`: ```bash # (replace string_sum with the desired package name) $ mkdir string_sum $ cd string_sum $ python -m venv .env $ source .env/bin/activate $ pip install maturin ``` Still inside this `string_sum` directory, now run `maturin init`. This will generate the new package source. When given the choice of bindings to use, select pyo3 bindings: ```bash $ maturin init ✔ 🤷 What kind of bindings to use? · pyo3 ✨ Done! New project created string_sum ``` The most important files generated by this command are `Cargo.toml` and `lib.rs`, which will look roughly like the following: **`Cargo.toml`** ```toml [package] name = "string_sum" version = "0.1.0" edition = "2021" [lib] # The name of the native library. This is the name which will be used in Python to import the # library (i.e. `import string_sum`). If you change this, you must also change the name of the # `#[pymodule]` in `src/lib.rs`. name = "string_sum" # "cdylib" is necessary to produce a shared library for Python to import from. # # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: # crate-type = ["cdylib", "rlib"] crate-type = ["cdylib"] [dependencies] pyo3 = { version = "0.22.2", features = ["extension-module"] } ``` **`src/lib.rs`** ```rust use pyo3::prelude::*; /// Formats the sum of two numbers as string. #[pyfunction] fn sum_as_string(a: usize, b: usize) -> PyResult { Ok((a + b).to_string()) } /// A Python module implemented in Rust. The name of this function must match /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to /// import the module. #[pymodule] fn string_sum(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(sum_as_string, m)?)?; Ok(()) } ``` Finally, run `maturin develop`. This will build the package and install it into the Python virtualenv previously created and activated. The package is then ready to be used from `python`: ```bash $ maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import string_sum >>> string_sum.sum_as_string(5, 20) '25' ``` To make changes to the package, just edit the Rust source code and then re-run `maturin develop` to recompile. To run this all as a single copy-and-paste, use the bash script below (replace `string_sum` in the first command with the desired package name): ```bash mkdir string_sum && cd "$_" python -m venv .env source .env/bin/activate pip install maturin maturin init --bindings pyo3 maturin develop ``` If you want to be able to run `cargo test` or use this project in a Cargo workspace and are running into linker issues, there are some workarounds in [the FAQ](https://pyo3.rs/latest/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror). As well as with `maturin`, it is possible to build using [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](https://pyo3.rs/latest/building-and-distribution.html#manual-builds). Both offer more flexibility than `maturin` but require more configuration to get started. ### Using Python from Rust To embed Python into a Rust binary, you need to ensure that your Python installation contains a shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give some example code which runs an embedded Python interpreter. To install the Python shared library on Ubuntu: ```bash sudo apt install python3-dev ``` To install the Python shared library on RPM based distributions (e.g. Fedora, Red Hat, SuSE), install the `python3-devel` package. Start a new project with `cargo new` and add `pyo3` to the `Cargo.toml` like this: ```toml [dependencies.pyo3] version = "0.22.2" features = ["auto-initialize"] ``` Example program displaying the value of `sys.version` and the current user name: ```rust use pyo3::prelude::*; use pyo3::types::IntoPyDict; fn main() -> PyResult<()> { Python::with_gil(|py| { let sys = py.import_bound("sys")?; let version: String = sys.getattr("version")?.extract()?; let locals = [("os", py.import_bound("os")?)].into_py_dict_bound(py); let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"; let user: String = py.eval_bound(code, None, Some(&locals))?.extract()?; println!("Hello {}, I'm Python {}", user, version); Ok(()) }) } ``` The guide has [a section](https://pyo3.rs/latest/python-from-rust.html) with lots of examples about this topic. ## Tools and libraries - [maturin](https://github.com/PyO3/maturin) _Build and publish crates with pyo3, rust-cpython or cffi bindings as well as rust binaries as python packages_ - [setuptools-rust](https://github.com/PyO3/setuptools-rust) _Setuptools plugin for Rust support_. - [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://docs.rs/pyo3/*/pyo3/types/struct.PyDict.html)_ - [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_ - [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_ - [pyo3-log](https://github.com/vorner/pyo3-log) _Bridge from Rust to Python logging_ - [pythonize](https://github.com/davidhewitt/pythonize) _Serde serializer for converting Rust objects to JSON-compatible Python objects_ - [pyo3-asyncio](https://github.com/awestlake87/pyo3-asyncio) _Utilities for working with Python's Asyncio library and async functions_ - [rustimport](https://github.com/mityax/rustimport) _Directly import Rust files or crates from Python, without manual compilation step. Provides pyo3 integration by default and generates pyo3 binding code automatically._ - [pyo3-arrow](https://crates.io/crates/pyo3-arrow) _Lightweight [Apache Arrow](https://arrow.apache.org/) integration for pyo3._ ## Examples - [autopy](https://github.com/autopilot-rs/autopy) _A simple, cross-platform GUI automation library for Python and Rust._ - Contains an example of building wheels on TravisCI and appveyor using [cibuildwheel](https://github.com/pypa/cibuildwheel) - [ballista-python](https://github.com/apache/arrow-ballista-python) _A Python library that binds to Apache Arrow distributed query engine Ballista._ - [bed-reader](https://github.com/fastlmm/bed-reader) _Read and write the PLINK BED format, simply and efficiently._ - Shows Rayon/ndarray::parallel (including capturing errors, controlling thread num), Python types to Rust generics, Github Actions - [cryptography](https://github.com/pyca/cryptography/tree/main/src/rust) _Python cryptography library with some functionality in Rust._ - [css-inline](https://github.com/Stranger6667/css-inline/tree/master/bindings/python) _CSS inlining for Python implemented in Rust._ - [datafusion-python](https://github.com/apache/arrow-datafusion-python) _A Python library that binds to Apache Arrow in-memory query engine DataFusion._ - [deltalake-python](https://github.com/delta-io/delta-rs/tree/main/python) _Native Delta Lake Python binding based on delta-rs with Pandas integration._ - [fastbloom](https://github.com/yankun1992/fastbloom) _A fast [bloom filter](https://github.com/yankun1992/fastbloom#BloomFilter) | [counting bloom filter](https://github.com/yankun1992/fastbloom#countingbloomfilter) implemented by Rust for Rust and Python!_ - [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library._ - [feos](https://github.com/feos-org/feos) _Lightning fast thermodynamic modeling in Rust with fully developed Python interface._ - [forust](https://github.com/jinlow/forust) _A lightweight gradient boosted decision tree library written in Rust._ - [granian](https://github.com/emmett-framework/granian) _A Rust HTTP server for Python applications._ - [greptimedb](https://github.com/GreptimeTeam/greptimedb/tree/main/src/script) _Support [Python scripting](https://docs.greptime.com/user-guide/python-scripts/overview) in the database_ - [haem](https://github.com/BooleanCat/haem) _A Python library for working on Bioinformatics problems._ - [html-py-ever](https://github.com/PyO3/setuptools-rust/tree/main/examples/html-py-ever) _Using [html5ever](https://github.com/servo/html5ever) through [kuchiki](https://github.com/kuchiki-rs/kuchiki) to speed up html parsing and css-selecting._ - [hyperjson](https://github.com/mre/hyperjson) _A hyper-fast Python module for reading/writing JSON data using Rust's serde-json._ - [inline-python](https://github.com/fusion-engineering/inline-python) _Inline Python code directly in your Rust code._ - [johnnycanencrypt](https://github.com/kushaldas/johnnycanencrypt) OpenPGP library with Yubikey support. - [jsonschema-rs](https://github.com/Stranger6667/jsonschema-rs/tree/master/bindings/python) _Fast JSON Schema validation library._ - [mocpy](https://github.com/cds-astro/mocpy) _Astronomical Python library offering data structures for describing any arbitrary coverage regions on the unit sphere._ - [opendal](https://github.com/apache/opendal/tree/main/bindings/python) _A data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way._ - [orjson](https://github.com/ijl/orjson) _Fast Python JSON library._ - [ormsgpack](https://github.com/aviramha/ormsgpack) _Fast Python msgpack library._ - [point-process](https://github.com/ManifoldFR/point-process-rust/tree/master/pylib) _High level API for pointprocesses as a Python library._ - [polaroid](https://github.com/daggy1234/polaroid) _Hyper Fast and safe image manipulation library for Python written in Rust._ - [polars](https://github.com/pola-rs/polars) _Fast multi-threaded DataFrame library in Rust | Python | Node.js._ - [pydantic-core](https://github.com/pydantic/pydantic-core) _Core validation logic for pydantic written in Rust._ - [pyheck](https://github.com/kevinheavey/pyheck) _Fast case conversion library, built by wrapping [heck](https://github.com/withoutboats/heck)._ - Quite easy to follow as there's not much code. - [pyre](https://github.com/Project-Dream-Weaver/pyre-http) _Fast Python HTTP server written in Rust._ - [pyreqwest_impersonate](https://github.com/deedy5/pyreqwest_impersonate) _The fastest python HTTP client that can impersonate web browsers by mimicking their headers and TLS/JA3/JA4/HTTP2 fingerprints._ - [ril-py](https://github.com/Cryptex-github/ril-py) _A performant and high-level image processing library for Python written in Rust._ - [river](https://github.com/online-ml/river) _Online machine learning in python, the computationally heavy statistics algorithms are implemented in Rust._ - [rust-python-coverage](https://github.com/cjermain/rust-python-coverage) _Example PyO3 project with automated test coverage for Rust and Python._ - [tiktoken](https://github.com/openai/tiktoken) _A fast BPE tokeniser for use with OpenAI's models._ - [tokenizers](https://github.com/huggingface/tokenizers/tree/main/bindings/python) _Python bindings to the Hugging Face tokenizers (NLP) written in Rust._ - [tzfpy](http://github.com/ringsaturn/tzfpy) _A fast package to convert longitude/latitude to timezone name._ - [utiles](https://github.com/jessekrubin/utiles) _Fast Python web-map tile utilities_ - [wasmer-python](https://github.com/wasmerio/wasmer-python) _Python library to run WebAssembly binaries._ ## Articles and other media - [(Video) Extending Python with Rust using PyO3](https://www.youtube.com/watch?v=T45ZEmSR1-s) - Dec 16, 2023 - [A Week of PyO3 + rust-numpy (How to Speed Up Your Data Pipeline X Times)](https://terencezl.github.io/blog/2023/06/06/a-week-of-pyo3-rust-numpy/) - Jun 6, 2023 - [(Podcast) PyO3 with David Hewitt](https://rustacean-station.org/episode/david-hewitt/) - May 19, 2023 - [Making Python 100x faster with less than 100 lines of Rust](https://ohadravid.github.io/posts/2023-03-rusty-python/) - Mar 28, 2023 - [How Pydantic V2 leverages Rust's Superpowers](https://fosdem.org/2023/schedule/event/rust_how_pydantic_v2_leverages_rusts_superpowers/) - Feb 4, 2023 - [How we extended the River stats module with Rust using PyO3](https://boring-guy.sh/posts/river-rust/) - Dec 23, 2022 - [Nine Rules for Writing Python Extensions in Rust](https://towardsdatascience.com/nine-rules-for-writing-python-extensions-in-rust-d35ea3a4ec29?sk=f8d808d5f414154fdb811e4137011437) - Dec 31, 2021 - [Calling Rust from Python using PyO3](https://saidvandeklundert.net/learn/2021-11-18-calling-rust-from-python-using-pyo3/) - Nov 18, 2021 - [davidhewitt's 2021 talk at Rust Manchester meetup](https://www.youtube.com/watch?v=-XyWG_klSAw&t=320s) - Aug 19, 2021 - [Incrementally porting a small Python project to Rust](https://blog.waleedkhan.name/port-python-to-rust/) - Apr 29, 2021 - [Vortexa - Integrating Rust into Python](https://www.vortexa.com/insight/integrating-rust-into-python) - Apr 12, 2021 - [Writing and publishing a Python module in Rust](https://blog.yossarian.net/2020/08/02/Writing-and-publishing-a-python-module-in-rust) - Aug 2, 2020 ## Contributing Everyone is welcomed to contribute to PyO3! There are many ways to support the project, such as: - help PyO3 users with issues on GitHub and [Discord](https://discord.gg/33kcChzH7f) - improve documentation - write features and bugfixes - publish blogs and examples of how to use PyO3 Our [contributing notes](https://github.com/PyO3/pyo3/blob/main/Contributing.md) and [architecture guide](https://github.com/PyO3/pyo3/blob/main/Architecture.md) have more resources if you wish to volunteer time for PyO3 and are searching where to start. If you don't have time to contribute yourself but still wish to support the project's future success, some of our maintainers have GitHub sponsorship pages: - [davidhewitt](https://github.com/sponsors/davidhewitt) - [messense](https://github.com/sponsors/messense) ## License PyO3 is licensed under the [Apache-2.0 license](LICENSE-APACHE) or the [MIT license](LICENSE-MIT), at your option. Python is licensed under the [Python License](https://docs.python.org/3/license.html). Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in PyO3 by you, as defined in the Apache License, shall be dual-licensed as above, without any additional terms or conditions. Deploys by Netlify pyo3/LICENSE-APACHE0000644000175000017500000002503514661133735014364 0ustar jamespagejamespage Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. pyo3/assets/0000775000175000017500000000000014661133735013737 5ustar jamespagejamespagepyo3/assets/script.py0000644000175000017500000000006414661133735015613 0ustar jamespagejamespage# Used in PyModule examples. class Blah: pass pyo3/Contributing.md0000644000175000017500000002662114661133735015433 0ustar jamespagejamespage# Contributing Thank you for your interest in contributing to PyO3! All are welcome - please consider reading our [Code of Conduct](https://github.com/PyO3/pyo3/blob/main/Code-of-Conduct.md) to keep our community positive and inclusive. If you are searching for ideas how to contribute, proceed to the ["Getting started contributing"](#getting-started-contributing) section. If you have found a specific issue to contribute to and need information about the development process, you may find the section ["Writing pull requests"](#writing-pull-requests) helpful. If you want to become familiar with the codebase, see [Architecture.md](https://github.com/PyO3/pyo3/blob/main/Architecture.md). ## Getting started contributing Please join in with any part of PyO3 which interests you. We use GitHub issues to record all bugs and ideas. Feel free to request an issue to be assigned to you if you want to work on it. You can browse the API of the non-public parts of PyO3 [here](https://pyo3.netlify.app/internal/doc/pyo3/index.html). The following sections also contain specific ideas on where to start contributing to PyO3. ## Setting up a development environment To work and develop PyO3, you need Python & Rust installed on your system. * We encourage the use of [rustup](https://rustup.rs/) to be able to select and choose specific toolchains based on the project. * [Pyenv](https://github.com/pyenv/pyenv) is also highly recommended for being able to choose a specific Python version. * [virtualenv](https://virtualenv.pypa.io/en/latest/) can also be used with or without Pyenv to use specific installed Python versions. * [`nox`][nox] is used to automate many of our CI tasks. ### Help users identify bugs The [PyO3 Discord server](https://discord.gg/33kcChzH7f) is very active with users who are new to PyO3, and often completely new to Rust. Helping them debug is a great way to get experience with the PyO3 codebase. Helping others often reveals bugs, documentation weaknesses, and missing APIs. It's a good idea to open GitHub issues for these immediately so the resolution can be designed and implemented! ### Implement issues ready for development Issues where the solution is clear and work is not in progress use the [needs-implementer](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-implementer) label. Don't be afraid if the solution is not clear to you! The core PyO3 contributors will be happy to mentor you through any questions you have to help you write the solution. ### Help write great docs PyO3 has a user guide (using mdbook) as well as the usual Rust API docs. The aim is for both of these to be detailed, easy to understand, and up-to-date. Pull requests are always welcome to fix typos, change wording, add examples, etc. There are some specific areas of focus where help is currently needed for the documentation: - Issues requesting documentation improvements are tracked with the [documentation](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Adocumentation) label. - Not all APIs had docs or examples when they were made. The goal is to have documentation on all PyO3 APIs ([#306](https://github.com/PyO3/pyo3/issues/306)). If you see an API lacking a doc, please write one and open a PR! To build the docs (including all features), install [`nox`][nox] and then run ```shell nox -s docs -- open ``` #### Doctests We use lots of code blocks in our docs. Run `cargo test --doc` when making changes to check that the doctests still work, or `cargo test` to run all the tests including doctests. See https://doc.rust-lang.org/rustdoc/documentation-tests.html for a guide on doctests. #### Building the guide You can preview the user guide by building it locally with `mdbook`. First, install [`mdbook`][mdbook] and [`nox`][nox]. Then, run ```shell nox -s build-guide -- --open ``` To check all links in the guide are valid, also install [`lychee`][lychee] and use the `check-guide` session instead: ```shell nox -s check-guide ``` ### Help design the next PyO3 Issues which don't yet have a clear solution use the [needs-design](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-design) label. If any of these issues interest you, please join in with the conversation on the issue! All opinions are valued, and if you're interested in going further with e.g. draft PRs to experiment with API designs, even better! ### Review pull requests Everybody is welcome to submit comments on open PRs. Please help ensure new PyO3 APIs are safe, performant, tidy, and easy to use! ## Writing pull requests Here are a few things to note when you are writing PRs. ### Continuous Integration The PyO3 repo uses GitHub Actions. PRs are blocked from merging if CI is not successful. Formatting, linting and tests are checked for all Rust and Python code. In addition, all warnings in Rust code are disallowed (using `RUSTFLAGS="-D warnings"`). Tests run with all supported Python versions with the latest stable Rust compiler, as well as for Python 3.9 with the minimum supported Rust version. If you are adding a new feature, you should add it to the `full` feature in our *Cargo.toml** so that it is tested in CI. You can run these tests yourself with `nox`. Use `nox -l` to list the full set of subcommands you can run. #### Linting Python code `nox -s ruff` #### Linting Rust code `nox -s rustfmt` #### Semver checks `cargo semver-checks check-release` #### Clippy `nox -s clippy-all` #### Tests `cargo test --features full` #### Check all conditional compilation `nox -s check-feature-powerset` #### UI Tests PyO3 uses [`trybuild`](https://github.com/dtolnay/trybuild) to develop UI tests to capture error messages from the Rust compiler for some of the macro functionality. Because there are several feature combinations for these UI tests, when updating them all (e.g. for a new Rust compiler version) it may be helpful to use the `update-ui-tests` nox session: ```bash nox -s update-ui-tests ``` ### Documenting changes We use [towncrier](https://towncrier.readthedocs.io/en/stable/index.html) to generate a CHANGELOG for each release. To include your changes in the release notes, you should create one (or more) news items in the `newsfragments` directory. Valid news items should be saved as `..md` where `` is the pull request number and `` is one of the following: - `packaging` - for dependency changes and Python / Rust version compatibility changes - `added` - for new features - `changed` - for features which already existed but have been altered or deprecated - `removed` - for features which have been removed - `fixed` - for "changed" features which were classed as a bugfix Docs-only PRs do not need news items; start your PR title with `docs:` to skip the check. ### Style guide #### Generic code PyO3 has a lot of generic APIs to increase usability. These can come at the cost of generic code bloat. Where reasonable, try to implement a concrete sub-portion of generic functions. There are two forms of this: - If the concrete sub-portion doesn't benefit from re-use by other functions, name it `inner` and keep it as a local to the function. - If the concrete sub-portion is re-used by other functions, preferably name it `_foo` and place it directly below `foo` in the source code (where `foo` is the original generic function). #### FFI calls PyO3 makes a lot of FFI calls to Python's C API using raw pointers. Where possible try to avoid using pointers-to-temporaries in expressions: ```rust // dangerous pyo3::ffi::Something(name.to_object(py).as_ptr()); // because the following refactoring is a use-after-free error: let name = name.to_object(py).as_ptr(); pyo3::ffi::Something(name) ``` Instead, prefer to bind the safe owned `PyObject` wrapper before passing to ffi functions: ```rust let name: PyObject = name.to_object(py); pyo3::ffi::Something(name.as_ptr()) // name will automatically be freed when it falls out of scope ``` ## Python and Rust version support policy PyO3 aims to keep sufficient compatibility to make packaging Python extensions built with PyO3 feasible on most common package managers. To keep package maintainers' lives simpler, PyO3 will commit, wherever possible, to only adjust minimum supported Rust and Python versions at the same time. This bump will only come in an `0.x` release, roughly once per year, after the oldest supported Python version reaches its end-of-life. (Check https://endoflife.date/python for a clear timetable on these.) Below are guidelines on what compatibility all PRs are expected to deliver for each language. ### Python PyO3 supports all officially supported Python versions, as well as the latest PyPy3 release. All of these versions are tested in CI. ### Rust PyO3 aims to make use of up-to-date Rust language features to keep the implementation as efficient as possible. The minimum Rust version supported will be decided when the release which bumps Python and Rust versions is made. At the time, the minimum Rust version will be set no higher than the lowest Rust version shipped in the current Debian, RHEL and Alpine Linux distributions. CI tests both the most recent stable Rust version and the minimum supported Rust version. Because of Rust's stability guarantees this is sufficient to confirm support for all Rust versions in between. ## Benchmarking PyO3 has two sets of benchmarks for evaluating some aspects of its performance. The benchmark suite is currently very small - please open PRs with new benchmarks if you're interested in helping to expand it! First, there are Rust-based benchmarks located in the `pyo3-benches` subdirectory. You can run these benchmarks with: nox -s bench Second, there is a Python-based benchmark contained in the `pytests` subdirectory. You can read more about it [here](https://github.com/PyO3/pyo3/tree/main/pytests). ## Code coverage You can view what code is and isn't covered by PyO3's tests. We aim to have 100% coverage - please check coverage and add tests if you notice a lack of coverage! - First, ensure the llvm-cov cargo plugin is installed. You may need to run the plugin through cargo once before using it with `nox`. ```shell cargo install cargo-llvm-cov cargo llvm-cov ``` - Then, generate an `lcov.info` file with ```shell nox -s coverage -- lcov ``` You can install an IDE plugin to view the coverage. For example, if you use VSCode: - Add the [coverage-gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) plugin. - Add these settings to VSCode's `settings.json`: ```json { "coverage-gutters.coverageFileNames": [ "lcov.info", "cov.xml", "coverage.xml", ], "coverage-gutters.showLineCoverage": true } ``` - You should now be able to see green highlights for code that is tested, and red highlights for code that is not tested. ## Sponsor this project At the moment there is no official organisation that accepts sponsorship on PyO3's behalf. If you're seeking to provide significant funding to the PyO3 ecosystem, please reach out to us on [GitHub](https://github.com/PyO3/pyo3/issues/new) or [Discord](https://discord.gg/33kcChzH7f) and we can discuss. In the meanwhile, some of our maintainers have personal GitHub sponsorship pages and would be grateful for your support: - [davidhewitt](https://github.com/sponsors/davidhewitt) - [messense](https://github.com/sponsors/messense) [mdbook]: https://rust-lang.github.io/mdBook/cli/index.html [lychee]: https://github.com/lycheeverse/lychee [nox]: https://github.com/theacodes/nox pyo3/emscripten/0000775000175000017500000000000014661133735014606 5ustar jamespagejamespagepyo3/emscripten/Makefile0000644000175000017500000000535214661133735016251 0ustar jamespagejamespageCURDIR=$(abspath .) # These three are passed in from nox. BUILDROOT ?= $(CURDIR)/builddir PYMAJORMINORMICRO ?= 3.11.0 EMSCRIPTEN_VERSION=3.1.13 export EMSDKDIR = $(BUILDROOT)/emsdk PLATFORM=wasm32_emscripten SYSCONFIGDATA_NAME=_sysconfigdata__$(PLATFORM) # BASH_ENV tells bash to source emsdk_env.sh on startup. export BASH_ENV := $(CURDIR)/env.sh # Use bash to run each command so that env.sh will be used. SHELL := /bin/bash # Set version variables. version_tuple := $(subst ., ,$(PYMAJORMINORMICRO:v%=%)) PYMAJOR=$(word 1,$(version_tuple)) PYMINOR=$(word 2,$(version_tuple)) PYMICRO=$(word 3,$(version_tuple)) PYVERSION=$(PYMAJORMINORMICRO) PYMAJORMINOR=$(PYMAJOR).$(PYMINOR) PYTHONURL=https://www.python.org/ftp/python/$(PYMAJORMINORMICRO)/Python-$(PYVERSION).tgz PYTHONTARBALL=$(BUILDROOT)/downloads/Python-$(PYVERSION).tgz PYTHONBUILD=$(BUILDROOT)/build/Python-$(PYVERSION) PYTHONLIBDIR=$(BUILDROOT)/install/Python-$(PYVERSION)/lib all: $(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a $(BUILDROOT)/.exists: mkdir -p $(BUILDROOT) touch $@ # Install emscripten $(EMSDKDIR): $(CURDIR)/emscripten_patches/* $(BUILDROOT)/.exists git clone https://github.com/emscripten-core/emsdk.git --depth 1 --branch $(EMSCRIPTEN_VERSION) $(EMSDKDIR) $(EMSDKDIR)/emsdk install $(EMSCRIPTEN_VERSION) cd $(EMSDKDIR)/upstream/emscripten && cat $(CURDIR)/emscripten_patches/* | patch -p1 $(EMSDKDIR)/emsdk activate $(EMSCRIPTEN_VERSION) $(PYTHONTARBALL): [ -d $(BUILDROOT)/downloads ] || mkdir -p $(BUILDROOT)/downloads wget -q -O $@ $(PYTHONURL) $(PYTHONBUILD)/.patched: $(PYTHONTARBALL) [ -d $(PYTHONBUILD) ] || ( \ mkdir -p $(dir $(PYTHONBUILD));\ tar -C $(dir $(PYTHONBUILD)) -xf $(PYTHONTARBALL) \ ) touch $@ $(PYTHONBUILD)/Makefile: $(PYTHONBUILD)/.patched $(BUILDROOT)/emsdk cd $(PYTHONBUILD) && \ CONFIG_SITE=Tools/wasm/config.site-wasm32-emscripten \ emconfigure ./configure -C \ --host=wasm32-unknown-emscripten \ --build=$(shell $(PYTHONBUILD)/config.guess) \ --with-emscripten-target=browser \ --enable-wasm-dynamic-linking \ --with-build-python=python3.11 $(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a : $(PYTHONBUILD)/Makefile cd $(PYTHONBUILD) && \ emmake make -j3 libpython$(PYMAJORMINOR).a # Generate sysconfigdata _PYTHON_SYSCONFIGDATA_NAME=$(SYSCONFIGDATA_NAME) _PYTHON_PROJECT_BASE=$(PYTHONBUILD) python3.11 -m sysconfig --generate-posix-vars cp `cat pybuilddir.txt`/$(SYSCONFIGDATA_NAME).py $(PYTHONBUILD)/Lib mkdir -p $(PYTHONLIBDIR) # Copy libexpat.a, libmpdec.a, and libpython3.11.a # In noxfile, we explicitly link libexpat and libmpdec via RUSTFLAGS find $(PYTHONBUILD) -name '*.a' -exec cp {} $(PYTHONLIBDIR) \; # Install Python stdlib cp -r $(PYTHONBUILD)/Lib $(PYTHONLIBDIR)/python$(PYMAJORMINOR) clean: rm -rf $(BUILDROOT) pyo3/emscripten/emscripten_patches/0000775000175000017500000000000014661133735020466 5ustar jamespagejamespagepyo3/emscripten/emscripten_patches/0001-Add-_gxx_personality_v0-stub-to-library.js.patch0000644000175000017500000000202614661133735032224 0ustar jamespagejamespageFrom 4b56f37c3dc9185a235a8314086c4d7a6239b2f8 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Sat, 4 Jun 2022 19:19:47 -0700 Subject: [PATCH] Add _gxx_personality_v0 stub to library.js Mitigation for an incompatibility between Rust and Emscripten: https://github.com/rust-lang/rust/issues/85821 https://github.com/emscripten-core/emscripten/issues/17128 --- src/library.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/library.js b/src/library.js index e7bb4c38e..7d01744df 100644 --- a/src/library.js +++ b/src/library.js @@ -403,6 +403,8 @@ mergeInto(LibraryManager.library, { abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']); }, + __gxx_personality_v0: function() {}, + // ========================================================================== // time.h // ========================================================================== -- 2.25.1 pyo3/emscripten/runner.py0000755000175000017500000000023614661133735016473 0ustar jamespagejamespage#!/usr/local/bin/python import pathlib import sys import subprocess p = pathlib.Path(sys.argv[1]) sys.exit(subprocess.call(["node", p.name], cwd=p.parent)) pyo3/emscripten/env.sh0000644000175000017500000000035714661133735015735 0ustar jamespagejamespage#!/bin/bash # Activate emsdk environment. emsdk_env.sh writes a lot to stderr so we suppress # the output. This also prevents it from complaining when emscripten isn't yet # installed. source "$EMSDKDIR/emsdk_env.sh" 2> /dev/null || true pyo3/emscripten/pybuilddir.txt0000644000175000017500000000003314661133735017510 0ustar jamespagejamespagebuild/lib.linux-x86_64-3.11pyo3/pyo3-runtime/0000775000175000017500000000000014661133735015010 5ustar jamespagejamespagepyo3/pyo3-runtime/README.md0000644000175000017500000000001514661133735016261 0ustar jamespagejamespageComing soon! pyo3/pyo3-runtime/LICENSE-APACHE0000644000175000017500000002503514661133735016737 0ustar jamespagejamespage Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. pyo3/pyo3-runtime/pyproject.toml0000644000175000017500000000166614661133735017733 0ustar jamespagejamespage[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "pyo3-runtime" dynamic = ["version"] description = '' readme = "README.md" requires-python = ">=3.7" license = "MIT OR Apache-2.0" keywords = [] authors = [ { name = "David Hewitt", email = "1939362+davidhewitt@users.noreply.github.com" }, ] classifiers = [ "Development Status :: 4 - Beta", "Programming Language :: Python", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", ] dependencies = [] [project.urls] Homepage = "https://github.com/PyO3/pyo3" [tool.hatch.version] path = "src/pyo3_runtime/__init__.py" pyo3/pyo3-runtime/tests/0000775000175000017500000000000014661133735016152 5ustar jamespagejamespagepyo3/pyo3-runtime/tests/__init__.py0000644000175000017500000000000014661133735020247 0ustar jamespagejamespagepyo3/pyo3-runtime/LICENSE-MIT0000644000175000017500000000212314661133735016440 0ustar jamespagejamespageCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3/pyo3-runtime/src/0000775000175000017500000000000014661133735015577 5ustar jamespagejamespagepyo3/pyo3-runtime/src/pyo3_runtime/0000775000175000017500000000000014661133735020234 5ustar jamespagejamespagepyo3/pyo3-runtime/src/pyo3_runtime/__init__.py0000644000175000017500000000002614661133735022341 0ustar jamespagejamespage__version__ = "0.0.1" pyo3/Cargo.toml0000644000175000017500000001244314661133735014367 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.63" name = "pyo3" version = "0.22.2" authors = ["PyO3 Project and Contributors "] exclude = [ "/.gitignore", ".cargo/config", "/codecov.yml", "/Makefile", "/pyproject.toml", "/noxfile.py", "/.github", "/tests/test_compile_error.rs", "/tests/ui", ] description = "Bindings to Python interpreter" homepage = "https://github.com/pyo3/pyo3" documentation = "https://docs.rs/crate/pyo3/" readme = "README.md" keywords = [ "pyo3", "python", "cpython", "ffi", ] categories = [ "api-bindings", "development-tools::ffi", ] license = "MIT OR Apache-2.0" repository = "https://github.com/pyo3/pyo3" [package.metadata.docs.rs] features = [ "full", "gil-refs", ] no-default-features = true rustdoc-args = [ "--cfg", "docsrs", ] [dependencies.anyhow] version = "1.0.1" optional = true [dependencies.cfg-if] version = "1.0" [dependencies.chrono] version = "0.4.25" optional = true default-features = false [dependencies.chrono-tz] version = ">= 0.6, < 0.10" optional = true default-features = false [dependencies.either] version = "1.9" optional = true [dependencies.eyre] version = ">= 0.4, < 0.7" optional = true [dependencies.hashbrown] version = ">= 0.9, < 0.15" optional = true [dependencies.indexmap] version = ">= 1.6, < 3" optional = true [dependencies.indoc] version = "2.0.1" optional = true [dependencies.inventory] version = "0.3.0" optional = true [dependencies.libc] version = "0.2.62" [dependencies.memoffset] version = "0.9" [dependencies.num-bigint] version = "0.4.2" optional = true [dependencies.num-complex] version = ">= 0.2, < 0.5" optional = true [dependencies.num-rational] version = "0.4.1" optional = true [dependencies.once_cell] version = "1.13" [dependencies.pyo3-ffi] version = "=0.22.2" [dependencies.pyo3-macros] version = "=0.22.2" optional = true [dependencies.rust_decimal] version = "1.15" optional = true default-features = false [dependencies.serde] version = "1.0" optional = true [dependencies.smallvec] version = "1.0" optional = true [dependencies.unindent] version = "0.2.1" optional = true [dev-dependencies.assert_approx_eq] version = "1.1.0" [dev-dependencies.chrono] version = "0.4.25" [dev-dependencies.chrono-tz] version = ">= 0.6, < 0.10" [dev-dependencies.futures] version = "0.3.28" [dev-dependencies.proptest] version = "1.0" features = ["std"] default-features = false [dev-dependencies.rayon] version = "1.6.1" [dev-dependencies.send_wrapper] version = "0.6" [dev-dependencies.serde] version = "1.0" features = ["derive"] [dev-dependencies.serde_json] version = "1.0.61" [dev-dependencies.trybuild] version = ">=1.0.70" [build-dependencies.pyo3-build-config] version = "=0.22.2" features = ["resolve-config"] [features] abi3 = [ "pyo3-build-config/abi3", "pyo3-ffi/abi3", ] abi3-py310 = [ "abi3-py311", "pyo3-build-config/abi3-py310", "pyo3-ffi/abi3-py310", ] abi3-py311 = [ "abi3-py312", "pyo3-build-config/abi3-py311", "pyo3-ffi/abi3-py311", ] abi3-py312 = [ "abi3", "pyo3-build-config/abi3-py312", "pyo3-ffi/abi3-py312", ] abi3-py37 = [ "abi3-py38", "pyo3-build-config/abi3-py37", "pyo3-ffi/abi3-py37", ] abi3-py38 = [ "abi3-py39", "pyo3-build-config/abi3-py38", "pyo3-ffi/abi3-py38", ] abi3-py39 = [ "abi3-py310", "pyo3-build-config/abi3-py39", "pyo3-ffi/abi3-py39", ] auto-initialize = [] default = ["macros"] experimental-async = [ "macros", "pyo3-macros/experimental-async", ] experimental-inspect = [] extension-module = ["pyo3-ffi/extension-module"] full = [ "macros", "anyhow", "chrono", "chrono-tz", "either", "experimental-async", "experimental-inspect", "eyre", "hashbrown", "indexmap", "num-bigint", "num-complex", "num-rational", "py-clone", "rust_decimal", "serde", "smallvec", ] generate-import-lib = ["pyo3-ffi/generate-import-lib"] gil-refs = ["pyo3-macros/gil-refs"] macros = [ "pyo3-macros", "indoc", "unindent", ] multiple-pymethods = [ "inventory", "pyo3-macros/multiple-pymethods", ] nightly = [] py-clone = [] [target."cfg(not(target_has_atomic = \"64\"))".dependencies.portable-atomic] version = "1.0" [lints.clippy] checked_conversions = "warn" dbg_macro = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" let_unit_value = "warn" manual_assert = "warn" manual_ok_or = "warn" todo = "warn" unnecessary_wraps = "warn" used_underscore_binding = "warn" useless_transmute = "warn" [lints.rust] elided_lifetimes_in_paths = "warn" invalid_doc_attributes = "warn" rust_2021_prelude_collisions = "warn" unused_lifetimes = "warn" [lints.rust.rust_2018_idioms] level = "warn" priority = -1 [lints.rustdoc] bare_urls = "warn" broken_intra_doc_links = "warn" pyo3/tests/0000775000175000017500000000000014661133735013577 5ustar jamespagejamespagepyo3/tests/test_multiple_pymethods.rs0000644000175000017500000000317614661133735021140 0ustar jamespagejamespage#![cfg(feature = "multiple-pymethods")] use pyo3::prelude::*; use pyo3::types::PyType; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct PyClassWithMultiplePyMethods {} #[pymethods] impl PyClassWithMultiplePyMethods { #[new] fn new() -> Self { Self {} } } #[pymethods] impl PyClassWithMultiplePyMethods { fn __call__(&self) -> &'static str { "call" } } #[pymethods] impl PyClassWithMultiplePyMethods { fn method(&self) -> &'static str { "method" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[classmethod] fn classmethod(_ty: &Bound<'_, PyType>) -> &'static str { "classmethod" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[staticmethod] fn staticmethod() -> &'static str { "staticmethod" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[classattr] fn class_attribute() -> &'static str { "class_attribute" } } #[pymethods] impl PyClassWithMultiplePyMethods { #[classattr] const CLASS_ATTRIBUTE: &'static str = "CLASS_ATTRIBUTE"; } #[test] fn test_class_with_multiple_pymethods() { Python::with_gil(|py| { let cls = py.get_type_bound::(); py_assert!(py, cls, "cls()() == 'call'"); py_assert!(py, cls, "cls().method() == 'method'"); py_assert!(py, cls, "cls.classmethod() == 'classmethod'"); py_assert!(py, cls, "cls.staticmethod() == 'staticmethod'"); py_assert!(py, cls, "cls.class_attribute == 'class_attribute'"); py_assert!(py, cls, "cls.CLASS_ATTRIBUTE == 'CLASS_ATTRIBUTE'"); }) } pyo3/tests/test_static_slots.rs0000644000175000017500000000264214661133735017721 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::exceptions::PyIndexError; use pyo3::prelude::*; use pyo3::types::IntoPyDict; use pyo3::py_run; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct Count5(); #[pymethods] impl Count5 { #[new] fn new() -> Self { Self() } #[staticmethod] fn __len__() -> usize { 5 } #[staticmethod] fn __getitem__(idx: isize) -> PyResult { if idx < 0 { Err(PyIndexError::new_err("Count5 cannot count backwards")) } else if idx > 4 { Err(PyIndexError::new_err("Count5 cannot count higher than 5")) } else { Ok(idx as f64 + 1.0) } } } /// Return a dict with `s = Count5()`. fn test_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { let d = [("Count5", py.get_type_bound::())].into_py_dict_bound(py); // Though we can construct `s` in Rust, let's test `__new__` works. py_run!(py, *d, "s = Count5()"); d } #[test] fn test_len() { Python::with_gil(|py| { let d = test_dict(py); py_assert!(py, *d, "len(s) == 5"); }); } #[test] fn test_getitem() { Python::with_gil(|py| { let d = test_dict(py); py_assert!(py, *d, "s[4] == 5.0"); }); } #[test] fn test_list() { Python::with_gil(|py| { let d = test_dict(py); py_assert!(py, *d, "list(s) == [1.0, 2.0, 3.0, 4.0, 5.0]"); }); } pyo3/tests/test_declarative_module.rs0000644000175000017500000001344114661133735021035 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::create_exception; use pyo3::exceptions::PyException; use pyo3::prelude::*; use pyo3::sync::GILOnceCell; #[cfg(not(Py_LIMITED_API))] use pyo3::types::PyBool; #[path = "../src/tests/common.rs"] mod common; mod some_module { use pyo3::create_exception; use pyo3::exceptions::PyException; use pyo3::prelude::*; #[pyclass] pub struct SomePyClass; create_exception!(some_module, SomeException, PyException); } #[pyclass] struct ValueClass { value: usize, } #[pymethods] impl ValueClass { #[new] fn new(value: usize) -> Self { Self { value } } } #[pyclass(module = "module")] struct LocatedClass {} #[pyfunction] fn double(x: usize) -> usize { x * 2 } create_exception!( declarative_module, MyError, PyException, "Some description." ); #[pymodule(submodule)] mod external_submodule {} /// A module written using declarative syntax. #[pymodule] mod declarative_module { #[pymodule_export] use super::declarative_submodule; #[pymodule_export] // This is not a real constraint but to test cfg attribute support #[cfg(not(Py_LIMITED_API))] use super::LocatedClass; use super::*; #[pymodule_export] use super::{declarative_module2, double, MyError, ValueClass as Value}; // test for #4036 #[pymodule_export] use super::some_module::SomePyClass; // test for #4036 #[pymodule_export] use super::some_module::SomeException; #[pymodule_export] use super::external_submodule; #[pymodule] mod inner { use super::*; #[pyfunction] fn triple(x: usize) -> usize { x * 3 } #[pyclass(name = "Struct")] struct Struct; #[pymethods] impl Struct { #[new] fn new() -> Self { Self } } #[pyclass(module = "foo")] struct StructInCustomModule; #[pyclass(eq, eq_int, name = "Enum")] #[derive(PartialEq)] enum Enum { A, B, } #[pyclass(eq, eq_int, module = "foo")] #[derive(PartialEq)] enum EnumInCustomModule { A, B, } } #[pymodule(submodule)] #[pyo3(module = "custom_root")] mod inner_custom_root { use super::*; #[pyclass] struct Struct; } #[pyo3::prelude::pymodule] mod full_path_inner {} #[pymodule_init] fn init(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add("double2", m.getattr("double")?) } } #[pyfunction] fn double_value(v: &ValueClass) -> usize { v.value * 2 } #[pymodule] mod declarative_submodule { #[pymodule_export] use super::{double, double_value}; } #[pymodule(name = "declarative_module_renamed")] mod declarative_module2 { #[pymodule_export] use super::double; } fn declarative_module(py: Python<'_>) -> &Bound<'_, PyModule> { static MODULE: GILOnceCell> = GILOnceCell::new(); MODULE .get_or_init(py, || pyo3::wrap_pymodule!(declarative_module)(py)) .bind(py) } #[test] fn test_declarative_module() { Python::with_gil(|py| { let m = declarative_module(py); py_assert!( py, m, "m.__doc__ == 'A module written using declarative syntax.'" ); py_assert!(py, m, "m.double(2) == 4"); py_assert!(py, m, "m.inner.triple(3) == 9"); py_assert!(py, m, "m.declarative_submodule.double(4) == 8"); py_assert!( py, m, "m.declarative_submodule.double_value(m.ValueClass(1)) == 2" ); py_assert!(py, m, "str(m.MyError('foo')) == 'foo'"); py_assert!(py, m, "m.declarative_module_renamed.double(2) == 4"); #[cfg(Py_LIMITED_API)] py_assert!(py, m, "not hasattr(m, 'LocatedClass')"); #[cfg(not(Py_LIMITED_API))] py_assert!(py, m, "hasattr(m, 'LocatedClass')"); py_assert!(py, m, "isinstance(m.inner.Struct(), m.inner.Struct)"); py_assert!(py, m, "isinstance(m.inner.Enum.A, m.inner.Enum)"); py_assert!(py, m, "hasattr(m, 'external_submodule')") }) } #[cfg(not(Py_LIMITED_API))] #[pyclass(extends = PyBool)] struct ExtendsBool; #[cfg(not(Py_LIMITED_API))] #[pymodule] mod class_initialization_module { #[pymodule_export] use super::ExtendsBool; } #[test] #[cfg(not(Py_LIMITED_API))] fn test_class_initialization_fails() { Python::with_gil(|py| { let err = class_initialization_module::_PYO3_DEF .make_module(py) .unwrap_err(); assert_eq!( err.to_string(), "RuntimeError: An error occurred while initializing class ExtendsBool" ); }) } #[pymodule] mod r#type { #[pymodule_export] use super::double; } #[test] fn test_raw_ident_module() { Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(r#type)(py).into_bound(py); py_assert!(py, m, "m.double(2) == 4"); }) } #[test] fn test_module_names() { Python::with_gil(|py| { let m = declarative_module(py); py_assert!( py, m, "m.inner.Struct.__module__ == 'declarative_module.inner'" ); py_assert!(py, m, "m.inner.StructInCustomModule.__module__ == 'foo'"); py_assert!( py, m, "m.inner.Enum.__module__ == 'declarative_module.inner'" ); py_assert!(py, m, "m.inner.EnumInCustomModule.__module__ == 'foo'"); py_assert!( py, m, "m.inner_custom_root.Struct.__module__ == 'custom_root.inner_custom_root'" ); }) } #[test] fn test_inner_module_full_path() { Python::with_gil(|py| { let m = declarative_module(py); py_assert!(py, m, "m.full_path_inner"); }) } pyo3/tests/test_macro_docs.rs0000644000175000017500000000154214661133735017315 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::IntoPyDict; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[pyclass] /// The MacroDocs class. #[doc = concat!("Some macro ", "class ", "docs.")] /// A very interesting type! struct MacroDocs {} #[pymethods] impl MacroDocs { #[doc = concat!("A macro ", "example.")] /// With mixed doc types. fn macro_doc(&self) {} } #[test] fn meth_doc() { Python::with_gil(|py| { let d = [("C", py.get_type_bound::())].into_py_dict_bound(py); py_assert!( py, *d, "C.__doc__ == 'The MacroDocs class.\\nSome macro class docs.\\nA very interesting type!'" ); py_assert!( py, *d, "C.macro_doc.__doc__ == 'A macro example.\\nWith mixed doc types.'" ); }); } pyo3/tests/test_various.rs0000644000175000017500000001214714661133735016677 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::PyTuple; use std::fmt; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct MutRefArg { n: i32, } #[pymethods] impl MutRefArg { fn get(&self) -> i32 { self.n } fn set_other(&self, mut other: PyRefMut<'_, MutRefArg>) { other.n = 100; } } #[test] fn mut_ref_arg() { Python::with_gil(|py| { let inst1 = Py::new(py, MutRefArg { n: 0 }).unwrap(); let inst2 = Py::new(py, MutRefArg { n: 0 }).unwrap(); py_run!(py, inst1 inst2, "inst1.set_other(inst2)"); let inst2 = inst2.bind(py).borrow(); assert_eq!(inst2.n, 100); }); } #[pyclass] struct PyUsize { #[pyo3(get)] pub value: usize, } #[pyfunction] fn get_zero() -> PyUsize { PyUsize { value: 0 } } #[test] /// Checks that we can use return a custom class in arbitrary function and use those functions /// both in rust and python fn return_custom_class() { Python::with_gil(|py| { // Using from rust assert_eq!(get_zero().value, 0); // Using from python let get_zero = wrap_pyfunction_bound!(get_zero)(py).unwrap(); py_assert!(py, get_zero, "get_zero().value == 0"); }); } #[test] fn intopytuple_primitive() { Python::with_gil(|py| { let tup = (1, 2, "foo"); py_assert!(py, tup, "tup == (1, 2, 'foo')"); py_assert!(py, tup, "tup[0] == 1"); py_assert!(py, tup, "tup[1] == 2"); py_assert!(py, tup, "tup[2] == 'foo'"); }); } #[pyclass] struct SimplePyClass {} #[test] fn intopytuple_pyclass() { Python::with_gil(|py| { let tup = ( Py::new(py, SimplePyClass {}).unwrap(), Py::new(py, SimplePyClass {}).unwrap(), ); py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'"); py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[1]).__name__"); py_assert!(py, tup, "tup[0] != tup[1]"); }); } #[test] fn pytuple_primitive_iter() { Python::with_gil(|py| { let tup = PyTuple::new_bound(py, [1u32, 2, 3].iter()); py_assert!(py, tup, "tup == (1, 2, 3)"); }); } #[test] fn pytuple_pyclass_iter() { Python::with_gil(|py| { let tup = PyTuple::new_bound( py, [ Py::new(py, SimplePyClass {}).unwrap(), Py::new(py, SimplePyClass {}).unwrap(), ] .iter(), ); py_assert!(py, tup, "type(tup[0]).__name__ == 'SimplePyClass'"); py_assert!(py, tup, "type(tup[0]).__name__ == type(tup[0]).__name__"); py_assert!(py, tup, "tup[0] != tup[1]"); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn test_pickle() { use pyo3::types::PyDict; #[pyclass(dict, module = "test_module")] struct PickleSupport {} #[pymethods] impl PickleSupport { #[new] fn new() -> PickleSupport { PickleSupport {} } pub fn __reduce__<'py>( slf: &Bound<'py, Self>, py: Python<'py>, ) -> PyResult<(PyObject, Bound<'py, PyTuple>, PyObject)> { let cls = slf.to_object(py).getattr(py, "__class__")?; let dict = slf.to_object(py).getattr(py, "__dict__")?; Ok((cls, PyTuple::empty_bound(py), dict)) } } fn add_module(module: Bound<'_, PyModule>) -> PyResult<()> { PyModule::import_bound(module.py(), "sys")? .dict() .get_item("modules") .unwrap() .unwrap() .downcast::()? .set_item(module.name()?, module) } Python::with_gil(|py| { let module = PyModule::new_bound(py, "test_module").unwrap(); module.add_class::().unwrap(); add_module(module).unwrap(); let inst = Py::new(py, PickleSupport {}).unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.__dict__ == {'a': 1} import pickle inst2 = pickle.loads(pickle.dumps(inst)) assert inst2.__dict__ == {'a': 1} "# ); }); } /// Testing https://github.com/PyO3/pyo3/issues/1106. A result type that /// implements `From for PyErr` should be automatically converted /// when using `#[pyfunction]`. /// /// This only makes sure that valid `Result` types do work. For an invalid /// enum type, see `ui/invalid_result_conversion.py`. #[derive(Debug)] struct MyError { pub descr: &'static str, } impl fmt::Display for MyError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "My error message: {}", self.descr) } } /// Important for the automatic conversion to `PyErr`. impl From for PyErr { fn from(err: MyError) -> pyo3::PyErr { pyo3::exceptions::PyOSError::new_err(err.to_string()) } } #[pyfunction] fn result_conversion_function() -> Result<(), MyError> { Err(MyError { descr: "something went wrong", }) } #[test] fn test_result_conversion() { Python::with_gil(|py| { wrap_pyfunction_bound!(result_conversion_function)(py).unwrap(); }); } pyo3/tests/test_getter_setter.rs0000644000175000017500000001561114661133735020066 0ustar jamespagejamespage#![cfg(feature = "macros")] use std::cell::Cell; use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::{IntoPyDict, PyList}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct ClassWithProperties { num: i32, } #[pymethods] impl ClassWithProperties { fn get_num(&self) -> i32 { self.num } #[getter(DATA)] /// a getter for data fn get_data(&self) -> i32 { self.num } #[setter(DATA)] fn set_data(&mut self, value: i32) { self.num = value; } #[getter] /// a getter with a type un-wrapped by PyResult fn get_unwrapped(&self) -> i32 { self.num } #[setter] fn set_unwrapped(&mut self, value: i32) { self.num = value; } #[setter] fn set_from_len(&mut self, #[pyo3(from_py_with = "extract_len")] value: i32) { self.num = value; } #[setter] fn set_from_any(&mut self, value: &Bound<'_, PyAny>) -> PyResult<()> { self.num = value.extract()?; Ok(()) } #[getter] fn get_data_list<'py>(&self, py: Python<'py>) -> Bound<'py, PyList> { PyList::new_bound(py, [self.num]) } } fn extract_len(any: &Bound<'_, PyAny>) -> PyResult { any.len().map(|len| len as i32) } #[test] fn class_with_properties() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithProperties { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.get_num() == 10"); py_run!(py, inst, "assert inst.get_num() == inst.DATA"); py_run!(py, inst, "inst.DATA = 20"); py_run!(py, inst, "assert inst.get_num() == 20 == inst.DATA"); py_expect_exception!(py, inst, "del inst.DATA", PyAttributeError); py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 20"); py_run!(py, inst, "inst.unwrapped = 42"); py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 42"); py_run!(py, inst, "assert inst.data_list == [42]"); py_run!(py, inst, "inst.from_len = [0, 0, 0]"); py_run!(py, inst, "assert inst.get_num() == 3"); py_run!(py, inst, "inst.from_any = 15"); py_run!(py, inst, "assert inst.get_num() == 15"); let d = [("C", py.get_type_bound::())].into_py_dict_bound(py); py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'"); }); } #[pyclass] struct GetterSetter { #[pyo3(get, set)] num: i32, #[pyo3(get, set)] text: String, } #[pymethods] impl GetterSetter { fn get_num2(&self) -> i32 { self.num } } #[test] fn getter_setter_autogen() { Python::with_gil(|py| { let inst = Py::new( py, GetterSetter { num: 10, text: "Hello".to_string(), }, ) .unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); py_run!( py, inst, "assert inst.text == 'Hello'; inst.text = 'There'; assert inst.text == 'There'" ); }); } #[pyclass] struct RefGetterSetter { num: i32, } #[pymethods] impl RefGetterSetter { #[getter] fn get_num(slf: PyRef<'_, Self>) -> i32 { slf.num } #[setter] fn set_num(mut slf: PyRefMut<'_, Self>, value: i32) { slf.num = value; } } #[test] fn ref_getter_setter() { // Regression test for #837 Python::with_gil(|py| { let inst = Py::new(py, RefGetterSetter { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } #[pyclass] struct TupleClassGetterSetter(i32); #[pymethods] impl TupleClassGetterSetter { #[getter(num)] fn get_num(&self) -> i32 { self.0 } #[setter(num)] fn set_num(&mut self, value: i32) { self.0 = value; } } #[test] fn tuple_struct_getter_setter() { Python::with_gil(|py| { let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap(); py_assert!(py, inst, "inst.num == 10"); py_run!(py, inst, "inst.num = 20"); py_assert!(py, inst, "inst.num == 20"); }); } #[pyclass(get_all, set_all)] struct All { num: i32, } #[test] fn get_set_all() { Python::with_gil(|py| { let inst = Py::new(py, All { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } #[pyclass(get_all)] struct All2 { #[pyo3(set)] num: i32, } #[test] fn get_all_and_set() { Python::with_gil(|py| { let inst = Py::new(py, All2 { num: 10 }).unwrap(); py_run!(py, inst, "assert inst.num == 10"); py_run!(py, inst, "inst.num = 20; assert inst.num == 20"); }); } #[pyclass] struct CellGetterSetter { #[pyo3(get, set)] cell_inner: Cell, } #[test] fn cell_getter_setter() { let c = CellGetterSetter { cell_inner: Cell::new(10), }; Python::with_gil(|py| { let inst = Py::new(py, c).unwrap().to_object(py); let cell = Cell::new(20).to_object(py); py_run!(py, cell, "assert cell == 20"); py_run!(py, inst, "assert inst.cell_inner == 10"); py_run!( py, inst, "inst.cell_inner = 20; assert inst.cell_inner == 20" ); }); } #[test] fn borrowed_value_with_lifetime_of_self() { #[pyclass] struct BorrowedValue {} #[pymethods] impl BorrowedValue { #[getter] fn value(&self) -> &str { "value" } } Python::with_gil(|py| { let inst = Py::new(py, BorrowedValue {}).unwrap().to_object(py); py_run!(py, inst, "assert inst.value == 'value'"); }); } #[test] fn frozen_py_field_get() { #[pyclass(frozen)] struct FrozenPyField { #[pyo3(get)] value: Py, } Python::with_gil(|py| { let inst = Py::new( py, FrozenPyField { value: "value".into_py(py), }, ) .unwrap() .to_object(py); py_run!(py, inst, "assert inst.value == 'value'"); }); } #[test] fn test_optional_setter() { #[pyclass] struct SimpleClass { field: Option, } #[pymethods] impl SimpleClass { #[getter] fn get_field(&self) -> Option { self.field } #[setter] fn set_field(&mut self, field: Option) { self.field = field; } } Python::with_gil(|py| { let instance = Py::new(py, SimpleClass { field: None }).unwrap(); py_run!(py, instance, "assert instance.field is None"); py_run!( py, instance, "instance.field = 42; assert instance.field == 42" ); py_run!( py, instance, "instance.field = None; assert instance.field is None" ); }) } pyo3/tests/test_text_signature.rs0000644000175000017500000002650214661133735020254 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; use pyo3::{types::PyType, wrap_pymodule}; #[path = "../src/tests/common.rs"] mod common; #[test] fn class_without_docs_or_signature() { #[pyclass] struct MyClass {} Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj.__doc__ is None"); py_assert!(py, typeobj, "typeobj.__text_signature__ is None"); }); } #[test] fn class_with_docs() { /// docs line1 #[pyclass] /// docs line2 struct MyClass {} Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'"); py_assert!(py, typeobj, "typeobj.__text_signature__ is None"); }); } #[test] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)] fn class_with_signature_no_doc() { #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(signature = (a, b=None, *, c=42), text_signature = "(a, b=None, *, c=42)")] fn __new__(a: i32, b: Option, c: i32) -> Self { let _ = (a, b, c); Self {} } } Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj.__doc__ == ''"); py_assert!( py, typeobj, "typeobj.__text_signature__ == '(a, b=None, *, c=42)'" ); }); } #[test] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)] fn class_with_docs_and_signature() { /// docs line1 #[pyclass] /// docs line2 struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(signature = (a, b=None, *, c=42), text_signature = "(a, b=None, *, c=42)")] fn __new__(a: i32, b: Option, c: i32) -> Self { let _ = (a, b, c); Self {} } } Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj.__doc__ == 'docs line1\\ndocs line2'"); py_assert!( py, typeobj, "typeobj.__text_signature__ == '(a, b=None, *, c=42)'" ); }); } #[test] fn test_function() { #[pyfunction(signature = (a, b=None, *, c=42))] #[pyo3(text_signature = "(a, b=None, *, c=42)")] fn my_function(a: i32, b: Option, c: i32) { let _ = (a, b, c); } Python::with_gil(|py| { let f = wrap_pyfunction_bound!(my_function)(py).unwrap(); py_assert!(py, f, "f.__text_signature__ == '(a, b=None, *, c=42)'"); }); } #[test] fn test_auto_test_signature_function() { #[pyfunction] fn my_function(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyfunction(pass_module)] fn my_function_2(module: &Bound<'_, PyModule>, a: i32, b: i32, c: i32) { let _ = (module, a, b, c); } #[pyfunction(signature = (a, /, b = None, *, c = 5))] fn my_function_3(a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[pyfunction(signature = (a, /, b = None, *args, c, d=5, **kwargs))] fn my_function_4( a: i32, b: Option, args: &Bound<'_, PyTuple>, c: i32, d: i32, kwargs: Option<&Bound<'_, PyDict>>, ) { let _ = (a, b, args, c, d, kwargs); } #[pyfunction(signature = (a = 1, /, b = None, c = 1.5, d=5, e = "pyo3", f = 'f', h = true))] fn my_function_5(a: i32, b: Option, c: f32, d: i32, e: &str, f: char, h: bool) { let _ = (a, b, c, d, e, f, h); } #[pyfunction] #[pyo3(signature=(a, b=None, c=None))] fn my_function_6(a: i32, b: Option, c: Option) { let _ = (a, b, c); } Python::with_gil(|py| { let f = wrap_pyfunction_bound!(my_function)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, b, c)', f.__text_signature__" ); let f = wrap_pyfunction_bound!(my_function_2)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '($module, a, b, c)', f.__text_signature__" ); let f = wrap_pyfunction_bound!(my_function_3)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, /, b=None, *, c=5)', f.__text_signature__" ); let f = wrap_pyfunction_bound!(my_function_4)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, /, b=None, *args, c, d=5, **kwargs)', f.__text_signature__" ); let f = wrap_pyfunction_bound!(my_function_5)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a=1, /, b=None, c=1.5, d=5, e=\"pyo3\", f=\\'f\\', h=True)', f.__text_signature__" ); let f = wrap_pyfunction_bound!(my_function_6)(py).unwrap(); py_assert!( py, f, "f.__text_signature__ == '(a, b=None, c=None)', f.__text_signature__" ); }); } #[test] fn test_auto_test_signature_method() { #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] fn new(a: i32, b: i32, c: i32) -> Self { let _ = (a, b, c); Self {} } fn method(&self, a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyo3(signature = (a, /, b = None, *, c = 5))] fn method_2(&self, a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[pyo3(signature = (a, /, b = None, *args, c, d=5, **kwargs))] fn method_3( &self, a: i32, b: Option, args: &Bound<'_, PyTuple>, c: i32, d: i32, kwargs: Option<&Bound<'_, PyDict>>, ) { let _ = (a, b, args, c, d, kwargs); } #[staticmethod] fn staticmethod(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[classmethod] fn classmethod(cls: &Bound<'_, PyType>, a: i32, b: i32, c: i32) { let _ = (cls, a, b, c); } } Python::with_gil(|py| { let cls = py.get_type_bound::(); #[cfg(any(not(Py_LIMITED_API), Py_3_10))] py_assert!(py, cls, "cls.__text_signature__ == '(a, b, c)'"); py_assert!( py, cls, "cls.method.__text_signature__ == '($self, a, b, c)'" ); py_assert!( py, cls, "cls.method_2.__text_signature__ == '($self, a, /, b=None, *, c=5)'" ); py_assert!( py, cls, "cls.method_3.__text_signature__ == '($self, a, /, b=None, *args, c, d=5, **kwargs)'" ); py_assert!( py, cls, "cls.staticmethod.__text_signature__ == '(a, b, c)'" ); py_assert!( py, cls, "cls.classmethod.__text_signature__ == '($cls, a, b, c)'" ); }); } #[test] fn test_auto_test_signature_opt_out() { #[pyfunction(text_signature = None)] fn my_function(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyfunction(signature = (a, /, b = None, *, c = 5), text_signature = None)] fn my_function_2(a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[new] #[pyo3(text_signature = None)] fn new(a: i32, b: i32, c: i32) -> Self { let _ = (a, b, c); Self {} } #[pyo3(text_signature = None)] fn method(&self, a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[pyo3(signature = (a, /, b = None, *, c = 5), text_signature = None)] fn method_2(&self, a: i32, b: Option, c: i32) { let _ = (a, b, c); } #[staticmethod] #[pyo3(text_signature = None)] fn staticmethod(a: i32, b: i32, c: i32) { let _ = (a, b, c); } #[classmethod] #[pyo3(text_signature = None)] fn classmethod(cls: &Bound<'_, PyType>, a: i32, b: i32, c: i32) { let _ = (cls, a, b, c); } } Python::with_gil(|py| { let f = wrap_pyfunction_bound!(my_function)(py).unwrap(); py_assert!(py, f, "f.__text_signature__ == None"); let f = wrap_pyfunction_bound!(my_function_2)(py).unwrap(); py_assert!(py, f, "f.__text_signature__ == None"); let cls = py.get_type_bound::(); py_assert!(py, cls, "cls.__text_signature__ == None"); py_assert!(py, cls, "cls.method.__text_signature__ == None"); py_assert!(py, cls, "cls.method_2.__text_signature__ == None"); py_assert!(py, cls, "cls.staticmethod.__text_signature__ == None"); py_assert!(py, cls, "cls.classmethod.__text_signature__ == None"); }); } #[test] fn test_pyfn() { #[pymodule] fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m, signature = (a, b=None, *, c=42))] #[pyo3(text_signature = "(a, b=None, *, c=42)")] fn my_function(a: i32, b: Option, c: i32) { let _ = (a, b, c); } Ok(()) } Python::with_gil(|py| { let m = wrap_pymodule!(my_module)(py); py_assert!( py, m, "m.my_function.__text_signature__ == '(a, b=None, *, c=42)'" ); }); } #[test] fn test_methods() { #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[pyo3(text_signature = "($self, a)")] fn method(&self, a: i32) { let _ = a; } #[pyo3(text_signature = "($self, b)")] fn pyself_method(_this: &Bound<'_, Self>, b: i32) { let _ = b; } #[classmethod] #[pyo3(text_signature = "($cls, c)")] fn class_method(_cls: &Bound<'_, PyType>, c: i32) { let _ = c; } #[staticmethod] #[pyo3(text_signature = "(d)")] fn static_method(d: i32) { let _ = d; } } Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!( py, typeobj, "typeobj.method.__text_signature__ == '($self, a)'" ); py_assert!( py, typeobj, "typeobj.pyself_method.__text_signature__ == '($self, b)'" ); py_assert!( py, typeobj, "typeobj.class_method.__text_signature__ == '($cls, c)'" ); py_assert!( py, typeobj, "typeobj.static_method.__text_signature__ == '(d)'" ); }); } #[test] #[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)] fn test_raw_identifiers() { #[pyclass] struct r#MyClass {} #[pymethods] impl MyClass { #[new] fn new() -> MyClass { MyClass {} } fn r#method(&self) {} } Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj.__text_signature__ == '()'"); py_assert!( py, typeobj, "typeobj.method.__text_signature__ == '($self)'" ); }); } pyo3/tests/test_serde.rs0000644000175000017500000000450314661133735016306 0ustar jamespagejamespage#[cfg(feature = "serde")] mod test_serde { use pyo3::prelude::*; use serde::{Deserialize, Serialize}; #[pyclass] #[derive(Debug, Serialize, Deserialize)] struct Group { name: String, } #[pyclass] #[derive(Debug, Serialize, Deserialize)] struct User { username: String, group: Option>, friends: Vec>, } #[test] fn test_serialize() { let friend1 = User { username: "friend 1".into(), group: None, friends: vec![], }; let friend2 = User { username: "friend 2".into(), group: None, friends: vec![], }; let user = Python::with_gil(|py| { let py_friend1 = Py::new(py, friend1).expect("failed to create friend 1"); let py_friend2 = Py::new(py, friend2).expect("failed to create friend 2"); let friends = vec![py_friend1, py_friend2]; let py_group = Py::new( py, Group { name: "group name".into(), }, ) .unwrap(); User { username: "danya".into(), group: Some(py_group), friends, } }); let serialized = serde_json::to_string(&user).expect("failed to serialize"); assert_eq!( serialized, r#"{"username":"danya","group":{"name":"group name"},"friends":[{"username":"friend 1","group":null,"friends":[]},{"username":"friend 2","group":null,"friends":[]}]}"# ); } #[test] fn test_deserialize() { let serialized = r#"{"username": "danya", "friends": [{"username": "friend", "group": {"name": "danya's friends"}, "friends": []}]}"#; let user: User = serde_json::from_str(serialized).expect("failed to deserialize"); assert_eq!(user.username, "danya"); assert!(user.group.is_none()); assert_eq!(user.friends.len(), 1usize); let friend = user.friends.first().unwrap(); Python::with_gil(|py| { assert_eq!(friend.borrow(py).username, "friend"); assert_eq!( friend.borrow(py).group.as_ref().unwrap().borrow(py).name, "danya's friends" ) }); } } pyo3/tests/test_datetime_import.rs0000644000175000017500000000160614661133735020373 0ustar jamespagejamespage#![cfg(not(Py_LIMITED_API))] use pyo3::{prelude::*, types::PyDate}; #[test] #[should_panic(expected = "module 'datetime' has no attribute 'datetime_CAPI'")] fn test_bad_datetime_module_panic() { // Create an empty temporary directory // with an empty "datetime" module which we'll put on the sys.path let tmpdir = std::env::temp_dir(); let tmpdir = tmpdir.join("pyo3_test_date_check"); let _ = std::fs::remove_dir_all(&tmpdir); std::fs::create_dir(&tmpdir).unwrap(); std::fs::File::create(tmpdir.join("datetime.py")).unwrap(); Python::with_gil(|py: Python<'_>| { let sys = py.import_bound("sys").unwrap(); sys.getattr("path") .unwrap() .call_method1("insert", (0, tmpdir)) .unwrap(); // This should panic because the "datetime" module is empty PyDate::new_bound(py, 2018, 1, 1).unwrap(); }); } pyo3/tests/test_pyself.rs0000644000175000017500000000607414661133735016513 0ustar jamespagejamespage#![cfg(feature = "macros")] //! Test slf: PyRef/PyMutRef(especially, slf.into::) works use pyo3::prelude::*; use pyo3::types::{PyBytes, PyString}; use std::collections::HashMap; #[path = "../src/tests/common.rs"] mod common; /// Assumes it's a file reader or so. /// Inspired by https://github.com/jothan/cordoba, thanks. #[pyclass] #[derive(Clone, Debug)] struct Reader { inner: HashMap, } #[pymethods] impl Reader { fn clone_ref<'a, 'py>(slf: &'a Bound<'py, Self>) -> &'a Bound<'py, Self> { slf } fn clone_ref_with_py<'a, 'py>( slf: &'a Bound<'py, Self>, _py: Python<'py>, ) -> &'a Bound<'py, Self> { slf } fn get_iter(slf: &Bound<'_, Self>, keys: Py) -> Iter { Iter { reader: slf.clone().unbind(), keys, idx: 0, } } fn get_iter_and_reset( mut slf: PyRefMut<'_, Self>, keys: Py, py: Python<'_>, ) -> PyResult { let reader = Py::new(py, slf.clone())?; slf.inner.clear(); Ok(Iter { reader, keys, idx: 0, }) } } #[pyclass] #[derive(Debug)] struct Iter { reader: Py, keys: Py, idx: usize, } #[pymethods] impl Iter { #[allow(clippy::self_named_constructors)] fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(mut slf: PyRefMut<'_, Self>) -> PyResult> { let bytes = slf.keys.bind(slf.py()).as_bytes(); match bytes.get(slf.idx) { Some(&b) => { slf.idx += 1; let py = slf.py(); let reader = slf.reader.bind(py); let reader_ref = reader.try_borrow()?; let res = reader_ref .inner .get(&b) .map(|s| PyString::new_bound(py, s).into()); Ok(res) } None => Ok(None), } } } fn reader() -> Reader { let reader = [(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")]; Reader { inner: reader.iter().map(|(k, v)| (*k, (*v).to_string())).collect(), } } #[test] fn test_nested_iter() { Python::with_gil(|py| { let reader: PyObject = reader().into_py(py); py_assert!( py, reader, "list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']" ); }); } #[test] fn test_clone_ref() { Python::with_gil(|py| { let reader: PyObject = reader().into_py(py); py_assert!(py, reader, "reader == reader.clone_ref()"); py_assert!(py, reader, "reader == reader.clone_ref_with_py()"); }); } #[test] fn test_nested_iter_reset() { Python::with_gil(|py| { let reader = Bound::new(py, reader()).unwrap(); py_assert!( py, reader, "list(reader.get_iter_and_reset(bytes([3, 5, 2]))) == ['c', 'e', 'b']" ); let reader_ref = reader.borrow(); assert!(reader_ref.inner.is_empty()); }); } pyo3/tests/test_class_basics.rs0000644000175000017500000004210014661133735017630 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::PyType; use pyo3::{py_run, PyClass}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct EmptyClass {} #[test] fn empty_class() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); // By default, don't allow creating instances from python. assert!(typeobj.call((), None).is_err()); py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'"); }); } #[pyclass] struct UnitClass; #[test] fn unit_class() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); // By default, don't allow creating instances from python. assert!(typeobj.call((), None).is_err()); py_assert!(py, typeobj, "typeobj.__name__ == 'UnitClass'"); }); } /// Line1 ///Line2 /// Line3 // this is not doc string #[pyclass] struct ClassWithDocs { /// Property field #[pyo3(get, set)] value: i32, /// Read-only property field #[pyo3(get)] readonly: i32, /// Write-only property field #[pyo3(set)] #[allow(dead_code)] // Rust detects field is never read writeonly: i32, } #[test] fn class_with_docstr() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_run!( py, typeobj, "assert typeobj.__doc__ == 'Line1\\nLine2\\n Line3'" ); py_run!( py, typeobj, "assert typeobj.value.__doc__ == 'Property field'" ); py_run!( py, typeobj, "assert typeobj.readonly.__doc__ == 'Read-only property field'" ); py_run!( py, typeobj, "assert typeobj.writeonly.__doc__ == 'Write-only property field'" ); }); } #[pyclass(name = "CustomName")] struct EmptyClass2 {} #[pymethods] impl EmptyClass2 { #[pyo3(name = "custom_fn")] fn bar(&self) {} #[staticmethod] #[pyo3(name = "custom_static")] fn bar_static() {} #[getter] #[pyo3(name = "custom_getter")] fn foo(&self) -> i32 { 5 } } #[test] fn custom_names() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj.__name__ == 'CustomName'"); py_assert!(py, typeobj, "typeobj.custom_fn.__name__ == 'custom_fn'"); py_assert!( py, typeobj, "typeobj.custom_static.__name__ == 'custom_static'" ); py_assert!( py, typeobj, "typeobj.custom_getter.__name__ == 'custom_getter'" ); py_assert!(py, typeobj, "not hasattr(typeobj, 'bar')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'bar_static')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'foo')"); }); } #[pyclass(name = "loop")] struct ClassRustKeywords { #[pyo3(name = "unsafe", get, set)] unsafe_variable: usize, } #[pymethods] impl ClassRustKeywords { #[pyo3(name = "struct")] fn struct_method(&self) {} #[staticmethod] #[pyo3(name = "type")] fn type_method() {} } #[test] fn keyword_names() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj.__name__ == 'loop'"); py_assert!(py, typeobj, "typeobj.struct.__name__ == 'struct'"); py_assert!(py, typeobj, "typeobj.type.__name__ == 'type'"); py_assert!(py, typeobj, "typeobj.unsafe.__name__ == 'unsafe'"); py_assert!(py, typeobj, "not hasattr(typeobj, 'unsafe_variable')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'struct_method')"); py_assert!(py, typeobj, "not hasattr(typeobj, 'type_method')"); }); } #[pyclass] struct RawIdents { #[pyo3(get, set)] r#type: i64, } #[pymethods] impl RawIdents { fn r#fn(&self) {} } #[test] fn test_raw_idents() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "not hasattr(typeobj, 'r#fn')"); py_assert!(py, typeobj, "hasattr(typeobj, 'fn')"); py_assert!(py, typeobj, "hasattr(typeobj, 'type')"); }); } #[pyclass] struct EmptyClassInModule {} // Ignored because heap types do not show up as being in builtins, instead they // raise AttributeError: // https://github.com/python/cpython/blob/v3.11.1/Objects/typeobject.c#L541-L570 #[test] #[ignore] fn empty_class_in_module() { Python::with_gil(|py| { let module = PyModule::new_bound(py, "test_module.nested").unwrap(); module.add_class::().unwrap(); let ty = module.getattr("EmptyClassInModule").unwrap(); assert_eq!( ty.getattr("__name__").unwrap().extract::().unwrap(), "EmptyClassInModule" ); let module: String = ty.getattr("__module__").unwrap().extract().unwrap(); // Rationale: The class can be added to many modules, but will only be initialized once. // We currently have no way of determining a canonical module, so builtins is better // than using whatever calls init first. assert_eq!(module, "builtins"); }); } #[pyclass] struct ClassWithObjectField { // It used to be that PyObject was not supported with (get, set) // - this test is just ensuring it compiles. #[pyo3(get, set)] value: PyObject, } #[pymethods] impl ClassWithObjectField { #[new] fn new(value: PyObject) -> ClassWithObjectField { Self { value } } } #[test] fn class_with_object_field() { Python::with_gil(|py| { let ty = py.get_type_bound::(); py_assert!(py, ty, "ty(5).value == 5"); py_assert!(py, ty, "ty(None).value == None"); }); } #[pyclass(frozen, eq, hash)] #[derive(PartialEq, Hash)] struct ClassWithHash { value: usize, } #[test] fn class_with_hash() { Python::with_gil(|py| { use pyo3::types::IntoPyDict; let class = ClassWithHash { value: 42 }; let hash = { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); class.hash(&mut hasher); hasher.finish() as isize }; let env = [ ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_py(py)), ] .into_py_dict_bound(py); py_assert!(py, *env, "hash(obj) == hsh"); }); } #[pyclass(unsendable, subclass)] struct UnsendableBase { value: std::rc::Rc, } #[pymethods] impl UnsendableBase { #[new] fn new(value: usize) -> UnsendableBase { Self { value: std::rc::Rc::new(value), } } #[getter] fn value(&self) -> usize { *self.value } } #[pyclass(extends=UnsendableBase)] struct UnsendableChild {} #[pymethods] impl UnsendableChild { #[new] fn new(value: usize) -> (UnsendableChild, UnsendableBase) { (UnsendableChild {}, UnsendableBase::new(value)) } } fn test_unsendable() -> PyResult<()> { let (keep_obj_here, obj) = Python::with_gil(|py| -> PyResult<_> { let obj: Py = PyType::new_bound::(py).call1((5,))?.extract()?; // Accessing the value inside this thread should not panic let caught_panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| -> PyResult<_> { assert_eq!(obj.getattr(py, "value")?.extract::(py)?, 5); Ok(()) })) .is_err(); assert!(!caught_panic); Ok((obj.clone_ref(py), obj)) })?; let caught_panic = std::thread::spawn(move || { // This access must panic Python::with_gil(move |py| { obj.borrow(py); }); }) .join(); Python::with_gil(|_py| drop(keep_obj_here)); if let Err(err) = caught_panic { if let Some(msg) = err.downcast_ref::() { panic!("{}", msg); } } Ok(()) } /// If a class is marked as `unsendable`, it panics when accessed by another thread. #[test] #[cfg_attr(target_arch = "wasm32", ignore)] #[should_panic( expected = "test_class_basics::UnsendableBase is unsendable, but sent to another thread" )] fn panic_unsendable_base() { test_unsendable::().unwrap(); } #[test] #[cfg_attr(target_arch = "wasm32", ignore)] #[should_panic( expected = "test_class_basics::UnsendableBase is unsendable, but sent to another thread" )] fn panic_unsendable_child() { test_unsendable::().unwrap(); } fn get_length(obj: &Bound<'_, PyAny>) -> PyResult { let length = obj.len()?; Ok(length) } fn is_even(obj: &Bound<'_, PyAny>) -> PyResult { obj.extract::().map(|i| i % 2 == 0) } #[pyclass] struct ClassWithFromPyWithMethods {} #[pymethods] impl ClassWithFromPyWithMethods { fn instance_method(&self, #[pyo3(from_py_with = "get_length")] argument: usize) -> usize { argument } #[classmethod] fn classmethod( _cls: &Bound<'_, PyType>, #[pyo3(from_py_with = "Bound::<'_, PyAny>::len")] argument: usize, ) -> usize { argument } #[staticmethod] fn staticmethod(#[pyo3(from_py_with = "get_length")] argument: usize) -> usize { argument } fn __contains__(&self, #[pyo3(from_py_with = "is_even")] obj: bool) -> bool { obj } } #[test] fn test_pymethods_from_py_with() { Python::with_gil(|py| { let instance = Py::new(py, ClassWithFromPyWithMethods {}).unwrap(); py_run!( py, instance, r#" arg = {1: 1, 2: 3} assert instance.instance_method(arg) == 2 assert instance.classmethod(arg) == 2 assert instance.staticmethod(arg) == 2 assert 42 in instance assert 73 not in instance "# ); }) } #[pyclass] struct TupleClass(#[pyo3(get, set, name = "value")] i32); #[test] fn test_tuple_struct_class() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); assert!(typeobj.call((), None).is_err()); py_assert!(py, typeobj, "typeobj.__name__ == 'TupleClass'"); let instance = Py::new(py, TupleClass(5)).unwrap(); py_run!( py, instance, r#" assert instance.value == 5; instance.value = 1234; assert instance.value == 1234; "# ); assert_eq!(instance.borrow(py).0, 1234); }); } #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(dict, subclass)] struct DunderDictSupport { // Make sure that dict_offset runs with non-zero sized Self _pad: [u8; 32], } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn dunder_dict_support() { Python::with_gil(|py| { let inst = Py::new( py, DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.a == 1 "# ); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn access_dunder_dict() { Python::with_gil(|py| { let inst = Py::new( py, DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.__dict__ == {'a': 1} "# ); }); } // If the base class has dict support, child class also has dict #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(extends=DunderDictSupport)] struct InheritDict { _value: usize, } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn inherited_dict() { Python::with_gil(|py| { let inst = Py::new( py, ( InheritDict { _value: 0 }, DunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ), ) .unwrap(); py_run!( py, inst, r#" inst.a = 1 assert inst.a == 1 "# ); }); } #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(weakref, dict)] struct WeakRefDunderDictSupport { // Make sure that weaklist_offset runs with non-zero sized Self _pad: [u8; 32], } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn weakref_dunder_dict_support() { Python::with_gil(|py| { let inst = Py::new( py, WeakRefDunderDictSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1" ); }); } #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(weakref, subclass)] struct WeakRefSupport { _pad: [u8; 32], } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn weakref_support() { Python::with_gil(|py| { let inst = Py::new( py, WeakRefSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ) .unwrap(); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst" ); }); } // If the base class has weakref support, child class also has weakref. #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] #[pyclass(extends=WeakRefSupport)] struct InheritWeakRef { _value: usize, } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn inherited_weakref() { Python::with_gil(|py| { let inst = Py::new( py, ( InheritWeakRef { _value: 0 }, WeakRefSupport { _pad: *b"DEADBEEFDEADBEEFDEADBEEFDEADBEEF", }, ), ) .unwrap(); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst" ); }); } #[test] fn access_frozen_class_without_gil() { use std::sync::atomic::{AtomicUsize, Ordering}; #[pyclass(frozen)] struct FrozenCounter { value: AtomicUsize, } let py_counter: Py = Python::with_gil(|py| { let counter = FrozenCounter { value: AtomicUsize::new(0), }; let cell = Bound::new(py, counter).unwrap(); cell.get().value.fetch_add(1, Ordering::Relaxed); cell.into() }); assert_eq!(py_counter.get().value.load(Ordering::Relaxed), 1); Python::with_gil(move |_py| drop(py_counter)); } #[test] #[cfg(Py_3_8)] // sys.unraisablehook not available until Python 3.8 #[cfg_attr(target_arch = "wasm32", ignore)] fn drop_unsendable_elsewhere() { use common::UnraisableCapture; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; use std::thread::spawn; #[pyclass(unsendable)] struct Unsendable { dropped: Arc, } impl Drop for Unsendable { fn drop(&mut self) { self.dropped.store(true, Ordering::SeqCst); } } Python::with_gil(|py| { let capture = UnraisableCapture::install(py); let dropped = Arc::new(AtomicBool::new(false)); let unsendable = Py::new( py, Unsendable { dropped: dropped.clone(), }, ) .unwrap(); py.allow_threads(|| { spawn(move || { Python::with_gil(move |_py| { drop(unsendable); }); }) .join() .unwrap(); }); assert!(!dropped.load(Ordering::SeqCst)); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "RuntimeError: test_class_basics::drop_unsendable_elsewhere::Unsendable is unsendable, but is being dropped on another thread"); assert!(object.is_none(py)); capture.borrow_mut(py).uninstall(py); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn test_unsendable_dict() { #[pyclass(dict, unsendable)] struct UnsendableDictClass {} #[pymethods] impl UnsendableDictClass { #[new] fn new() -> Self { UnsendableDictClass {} } } Python::with_gil(|py| { let inst = Py::new(py, UnsendableDictClass {}).unwrap(); py_run!(py, inst, "assert inst.__dict__ == {}"); }); } #[test] #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] fn test_unsendable_dict_with_weakref() { #[pyclass(dict, unsendable, weakref)] struct UnsendableDictClassWithWeakRef {} #[pymethods] impl UnsendableDictClassWithWeakRef { #[new] fn new() -> Self { Self {} } } Python::with_gil(|py| { let inst = Py::new(py, UnsendableDictClassWithWeakRef {}).unwrap(); py_run!(py, inst, "assert inst.__dict__ == {}"); py_run!( py, inst, "import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1" ); }); } pyo3/tests/test_macros.rs0000644000175000017500000000462714661133735016477 0ustar jamespagejamespage#![cfg(feature = "macros")] //! Ensure that pyo3 macros can be used inside macro_rules! use pyo3::prelude::*; #[macro_use] #[path = "../src/tests/common.rs"] mod common; macro_rules! make_struct_using_macro { // Ensure that one doesn't need to fall back on the escape type: tt // in order to macro create pyclass. ($class_name:ident, $py_name:literal) => { #[pyclass(name=$py_name)] struct $class_name {} }; } make_struct_using_macro!(MyBaseClass, "MyClass"); macro_rules! set_extends_via_macro { ($class_name:ident, $base_class:path) => { // Try and pass a variable into the extends parameter #[pyclass(extends=$base_class)] struct $class_name {} }; } set_extends_via_macro!(MyClass2, MyBaseClass); // // Check that pyfunctiona nd text_signature can be called with macro arguments. // macro_rules! fn_macro { ($sig:literal, $a_exp:expr, $b_exp:expr, $c_exp: expr) => { // Try and pass a variable into the signature parameter #[pyfunction(signature = ($a_exp, $b_exp, *, $c_exp))] #[pyo3(text_signature = $sig)] fn my_function_in_macro(a: i32, b: Option, c: i32) { let _ = (a, b, c); } }; } fn_macro!("(a, b=None, *, c=42)", a, b = None, c = 42); macro_rules! property_rename_via_macro { ($prop_name:ident) => { #[pyclass] struct ClassWithProperty { member: u64, } #[pymethods] impl ClassWithProperty { #[getter($prop_name)] fn get_member(&self) -> u64 { self.member } #[setter($prop_name)] fn set_member(&mut self, member: u64) { self.member = member; } } }; } property_rename_via_macro!(my_new_property_name); #[test] fn test_macro_rules_interactions() { Python::with_gil(|py| { let my_base = py.get_type_bound::(); py_assert!(py, my_base, "my_base.__name__ == 'MyClass'"); let my_func = wrap_pyfunction_bound!(my_function_in_macro, py).unwrap(); py_assert!( py, my_func, "my_func.__text_signature__ == '(a, b=None, *, c=42)'" ); let renamed_prop = py.get_type_bound::(); py_assert!( py, renamed_prop, "hasattr(renamed_prop, 'my_new_property_name')" ); }); } pyo3/tests/test_proto_methods.rs0000644000175000017500000005202314661133735020072 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::exceptions::{PyAttributeError, PyIndexError, PyValueError}; use pyo3::types::{PyDict, PyList, PyMapping, PySequence, PySlice, PyType}; use pyo3::{prelude::*, py_run}; use std::iter; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct EmptyClass; #[pyclass] struct ExampleClass { #[pyo3(get, set)] value: i32, custom_attr: Option, } #[pymethods] impl ExampleClass { fn __getattr__(&self, py: Python<'_>, attr: &str) -> PyResult { if attr == "special_custom_attr" { Ok(self.custom_attr.into_py(py)) } else { Err(PyAttributeError::new_err(attr.to_string())) } } fn __setattr__(&mut self, attr: &str, value: &Bound<'_, PyAny>) -> PyResult<()> { if attr == "special_custom_attr" { self.custom_attr = Some(value.extract()?); Ok(()) } else { Err(PyAttributeError::new_err(attr.to_string())) } } fn __delattr__(&mut self, attr: &str) -> PyResult<()> { if attr == "special_custom_attr" { self.custom_attr = None; Ok(()) } else { Err(PyAttributeError::new_err(attr.to_string())) } } fn __str__(&self) -> String { self.value.to_string() } fn __repr__(&self) -> String { format!("ExampleClass(value={})", self.value) } fn __hash__(&self) -> u64 { let i64_value: i64 = self.value.into(); i64_value as u64 } fn __bool__(&self) -> bool { self.value != 0 } } fn make_example(py: Python<'_>) -> Bound<'_, ExampleClass> { Bound::new( py, ExampleClass { value: 5, custom_attr: Some(20), }, ) .unwrap() } #[test] fn test_getattr() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!( example_py .getattr("value") .unwrap() .extract::() .unwrap(), 5, ); assert_eq!( example_py .getattr("special_custom_attr") .unwrap() .extract::() .unwrap(), 20, ); assert!(example_py .getattr("other_attr") .unwrap_err() .is_instance_of::(py)); }) } #[test] fn test_setattr() { Python::with_gil(|py| { let example_py = make_example(py); example_py.setattr("special_custom_attr", 15).unwrap(); assert_eq!( example_py .getattr("special_custom_attr") .unwrap() .extract::() .unwrap(), 15, ); }) } #[test] fn test_delattr() { Python::with_gil(|py| { let example_py = make_example(py); example_py.delattr("special_custom_attr").unwrap(); assert!(example_py.getattr("special_custom_attr").unwrap().is_none()); }) } #[test] fn test_str() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!(example_py.str().unwrap(), "5"); }) } #[test] fn test_repr() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!(example_py.repr().unwrap(), "ExampleClass(value=5)"); }) } #[test] fn test_hash() { Python::with_gil(|py| { let example_py = make_example(py); assert_eq!(example_py.hash().unwrap(), 5); }) } #[test] fn test_bool() { Python::with_gil(|py| { let example_py = make_example(py); assert!(example_py.is_truthy().unwrap()); example_py.borrow_mut().value = 0; assert!(!example_py.is_truthy().unwrap()); }) } #[pyclass] pub struct LenOverflow; #[pymethods] impl LenOverflow { fn __len__(&self) -> usize { (isize::MAX as usize) + 1 } } #[test] fn len_overflow() { Python::with_gil(|py| { let inst = Py::new(py, LenOverflow).unwrap(); py_expect_exception!(py, inst, "len(inst)", PyOverflowError); }); } #[pyclass] pub struct Mapping { values: Py, } #[pymethods] impl Mapping { fn __len__(&self, py: Python<'_>) -> usize { self.values.bind(py).len() } fn __getitem__<'py>(&self, key: &Bound<'py, PyAny>) -> PyResult> { let any: &Bound<'py, PyAny> = self.values.bind(key.py()); any.get_item(key) } fn __setitem__<'py>(&self, key: &Bound<'py, PyAny>, value: &Bound<'py, PyAny>) -> PyResult<()> { self.values.bind(key.py()).set_item(key, value) } fn __delitem__(&self, key: &Bound<'_, PyAny>) -> PyResult<()> { self.values.bind(key.py()).del_item(key) } } #[test] fn mapping() { Python::with_gil(|py| { PyMapping::register::(py).unwrap(); let inst = Py::new( py, Mapping { values: PyDict::new_bound(py).into(), }, ) .unwrap(); let mapping: &Bound<'_, PyMapping> = inst.bind(py).downcast().unwrap(); py_assert!(py, inst, "len(inst) == 0"); py_run!(py, inst, "inst['foo'] = 'foo'"); py_assert!(py, inst, "inst['foo'] == 'foo'"); py_run!(py, inst, "del inst['foo']"); py_expect_exception!(py, inst, "inst['foo']", PyKeyError); // Default iteration will call __getitem__ with integer indices // which fails with a KeyError py_expect_exception!(py, inst, "[*inst] == []", PyKeyError, "0"); // check mapping protocol assert_eq!(mapping.len().unwrap(), 0); mapping.set_item(0, 5).unwrap(); assert_eq!(mapping.len().unwrap(), 1); assert_eq!(mapping.get_item(0).unwrap().extract::().unwrap(), 5); mapping.del_item(0).unwrap(); assert_eq!(mapping.len().unwrap(), 0); }); } #[derive(FromPyObject)] enum SequenceIndex<'py> { Integer(isize), Slice(Bound<'py, PySlice>), } #[pyclass] pub struct Sequence { values: Vec, } #[pymethods] impl Sequence { fn __len__(&self) -> usize { self.values.len() } fn __getitem__(&self, index: SequenceIndex<'_>, py: Python<'_>) -> PyResult { match index { SequenceIndex::Integer(index) => { let uindex = self.usize_index(index)?; self.values .get(uindex) .map(|o| o.clone_ref(py)) .ok_or_else(|| PyIndexError::new_err(index)) } // Just to prove that slicing can be implemented SequenceIndex::Slice(s) => Ok(s.into()), } } fn __setitem__(&mut self, index: isize, value: PyObject) -> PyResult<()> { let uindex = self.usize_index(index)?; self.values .get_mut(uindex) .map(|place| *place = value) .ok_or_else(|| PyIndexError::new_err(index)) } fn __delitem__(&mut self, index: isize) -> PyResult<()> { let uindex = self.usize_index(index)?; if uindex >= self.values.len() { Err(PyIndexError::new_err(index)) } else { self.values.remove(uindex); Ok(()) } } fn append(&mut self, value: PyObject) { self.values.push(value); } } impl Sequence { fn usize_index(&self, index: isize) -> PyResult { if index < 0 { let corrected_index = index + self.values.len() as isize; if corrected_index < 0 { Err(PyIndexError::new_err(index)) } else { Ok(corrected_index as usize) } } else { Ok(index as usize) } } } #[test] fn sequence() { Python::with_gil(|py| { PySequence::register::(py).unwrap(); let inst = Py::new(py, Sequence { values: vec![] }).unwrap(); let sequence: &Bound<'_, PySequence> = inst.bind(py).downcast().unwrap(); py_assert!(py, inst, "len(inst) == 0"); py_expect_exception!(py, inst, "inst[0]", PyIndexError); py_run!(py, inst, "inst.append('foo')"); py_assert!(py, inst, "inst[0] == 'foo'"); py_assert!(py, inst, "inst[-1] == 'foo'"); py_expect_exception!(py, inst, "inst[1]", PyIndexError); py_expect_exception!(py, inst, "inst[-2]", PyIndexError); py_assert!(py, inst, "[*inst] == ['foo']"); py_run!(py, inst, "del inst[0]"); py_expect_exception!(py, inst, "inst['foo']", PyTypeError); py_assert!(py, inst, "inst[0:2] == slice(0, 2)"); // check sequence protocol // we don't implement sequence length so that CPython doesn't attempt to correct negative // indices. assert!(sequence.len().is_err()); // however regular python len() works thanks to mp_len slot assert_eq!(inst.bind(py).len().unwrap(), 0); py_run!(py, inst, "inst.append(0)"); sequence.set_item(0, 5).unwrap(); assert_eq!(inst.bind(py).len().unwrap(), 1); assert_eq!(sequence.get_item(0).unwrap().extract::().unwrap(), 5); sequence.del_item(0).unwrap(); assert_eq!(inst.bind(py).len().unwrap(), 0); }); } #[pyclass] struct Iterator { iter: Box + Send>, } #[pymethods] impl Iterator { fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__(mut slf: PyRefMut<'_, Self>) -> Option { slf.iter.next() } } #[test] fn iterator() { Python::with_gil(|py| { let inst = Py::new( py, Iterator { iter: Box::new(5..8), }, ) .unwrap(); py_assert!(py, inst, "iter(inst) is inst"); py_assert!(py, inst, "list(inst) == [5, 6, 7]"); }); } #[pyclass] struct Callable; #[pymethods] impl Callable { fn __call__(&self, arg: i32) -> i32 { arg * 6 } } #[pyclass] struct NotCallable; #[test] fn callable() { Python::with_gil(|py| { let c = Py::new(py, Callable).unwrap(); py_assert!(py, c, "callable(c)"); py_assert!(py, c, "c(7) == 42"); let nc = Py::new(py, NotCallable).unwrap(); py_assert!(py, nc, "not callable(nc)"); }); } #[pyclass] #[derive(Debug)] struct SetItem { key: i32, val: i32, } #[pymethods] impl SetItem { fn __setitem__(&mut self, key: i32, val: i32) { self.key = key; self.val = val; } } #[test] fn setitem() { Python::with_gil(|py| { let c = Bound::new(py, SetItem { key: 0, val: 0 }).unwrap(); py_run!(py, c, "c[1] = 2"); { let c = c.borrow(); assert_eq!(c.key, 1); assert_eq!(c.val, 2); } py_expect_exception!(py, c, "del c[1]", PyNotImplementedError); }); } #[pyclass] struct DelItem { key: i32, } #[pymethods] impl DelItem { fn __delitem__(&mut self, key: i32) { self.key = key; } } #[test] fn delitem() { Python::with_gil(|py| { let c = Bound::new(py, DelItem { key: 0 }).unwrap(); py_run!(py, c, "del c[1]"); { let c = c.borrow(); assert_eq!(c.key, 1); } py_expect_exception!(py, c, "c[1] = 2", PyNotImplementedError); }); } #[pyclass] struct SetDelItem { val: Option, } #[pymethods] impl SetDelItem { fn __setitem__(&mut self, _key: i32, val: i32) { self.val = Some(val); } fn __delitem__(&mut self, _key: i32) { self.val = None; } } #[test] fn setdelitem() { Python::with_gil(|py| { let c = Bound::new(py, SetDelItem { val: None }).unwrap(); py_run!(py, c, "c[1] = 2"); { let c = c.borrow(); assert_eq!(c.val, Some(2)); } py_run!(py, c, "del c[1]"); let c = c.borrow(); assert_eq!(c.val, None); }); } #[pyclass] struct Contains {} #[pymethods] impl Contains { fn __contains__(&self, item: i32) -> bool { item >= 0 } } #[test] fn contains() { Python::with_gil(|py| { let c = Py::new(py, Contains {}).unwrap(); py_run!(py, c, "assert 1 in c"); py_run!(py, c, "assert -1 not in c"); py_expect_exception!(py, c, "assert 'wrong type' not in c", PyTypeError); }); } #[pyclass] struct GetItem {} #[pymethods] impl GetItem { fn __getitem__(&self, idx: &Bound<'_, PyAny>) -> PyResult<&'static str> { if let Ok(slice) = idx.downcast::() { let indices = slice.indices(1000)?; if indices.start == 100 && indices.stop == 200 && indices.step == 1 { return Ok("slice"); } } else if let Ok(idx) = idx.extract::() { if idx == 1 { return Ok("int"); } } Err(PyValueError::new_err("error")) } } #[test] fn test_getitem() { Python::with_gil(|py| { let ob = Py::new(py, GetItem {}).unwrap(); py_assert!(py, ob, "ob[1] == 'int'"); py_assert!(py, ob, "ob[100:200:1] == 'slice'"); }); } #[pyclass] struct ClassWithGetAttr { #[pyo3(get, set)] data: u32, } #[pymethods] impl ClassWithGetAttr { fn __getattr__(&self, _name: &str) -> u32 { self.data * 2 } } #[test] fn getattr_doesnt_override_member() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithGetAttr { data: 4 }).unwrap(); py_assert!(py, inst, "inst.data == 4"); py_assert!(py, inst, "inst.a == 8"); }); } #[pyclass] struct ClassWithGetAttribute { #[pyo3(get, set)] data: u32, } #[pymethods] impl ClassWithGetAttribute { fn __getattribute__(&self, _name: &str) -> u32 { self.data * 2 } } #[test] fn getattribute_overrides_member() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithGetAttribute { data: 4 }).unwrap(); py_assert!(py, inst, "inst.data == 8"); py_assert!(py, inst, "inst.y == 8"); }); } #[pyclass] struct ClassWithGetAttrAndGetAttribute; #[pymethods] impl ClassWithGetAttrAndGetAttribute { fn __getattribute__(&self, name: &str) -> PyResult { if name == "exists" { Ok(42) } else if name == "error" { Err(PyValueError::new_err("bad")) } else { Err(PyAttributeError::new_err("fallback")) } } fn __getattr__(&self, name: &str) -> PyResult { if name == "lucky" { Ok(57) } else { Err(PyAttributeError::new_err("no chance")) } } } #[test] fn getattr_and_getattribute() { Python::with_gil(|py| { let inst = Py::new(py, ClassWithGetAttrAndGetAttribute).unwrap(); py_assert!(py, inst, "inst.exists == 42"); py_assert!(py, inst, "inst.lucky == 57"); py_expect_exception!(py, inst, "inst.error", PyValueError); py_expect_exception!(py, inst, "inst.unlucky", PyAttributeError); }); } /// Wraps a Python future and yield it once. #[pyclass] #[derive(Debug)] struct OnceFuture { future: PyObject, polled: bool, } #[pymethods] impl OnceFuture { #[new] fn new(future: PyObject) -> Self { OnceFuture { future, polled: false, } } fn __await__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __next__<'py>(&mut self, py: Python<'py>) -> Option<&Bound<'py, PyAny>> { if !self.polled { self.polled = true; Some(self.future.bind(py)) } else { None } } } #[test] #[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop) fn test_await() { Python::with_gil(|py| { let once = py.get_type_bound::(); let source = r#" import asyncio import sys async def main(): res = await Once(await asyncio.sleep(0.1)) assert res is None # For an odd error similar to https://bugs.python.org/issue38563 if sys.platform == "win32" and sys.version_info >= (3, 8, 0): asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(main()) "#; let globals = PyModule::import_bound(py, "__main__").unwrap().dict(); globals.set_item("Once", once).unwrap(); py.run_bound(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } #[pyclass] struct AsyncIterator { future: Option>, } #[pymethods] impl AsyncIterator { #[new] fn new(future: Py) -> Self { Self { future: Some(future), } } fn __aiter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> { slf } fn __anext__(&mut self) -> Option> { self.future.take() } } #[test] #[cfg(not(target_arch = "wasm32"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop) fn test_anext_aiter() { Python::with_gil(|py| { let once = py.get_type_bound::(); let source = r#" import asyncio import sys async def main(): count = 0 async for result in AsyncIterator(Once(await asyncio.sleep(0.1))): # The Once is awaited as part of the `async for` and produces None assert result is None count +=1 assert count == 1 # For an odd error similar to https://bugs.python.org/issue38563 if sys.platform == "win32" and sys.version_info >= (3, 8, 0): asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) asyncio.run(main()) "#; let globals = PyModule::import_bound(py, "__main__").unwrap().dict(); globals.set_item("Once", once).unwrap(); globals .set_item("AsyncIterator", py.get_type_bound::()) .unwrap(); py.run_bound(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } /// Increment the count when `__get__` is called. #[pyclass] struct DescrCounter { #[pyo3(get)] count: usize, } #[pymethods] impl DescrCounter { #[new] fn new() -> Self { DescrCounter { count: 0 } } /// Each access will increase the count fn __get__<'a>( mut slf: PyRefMut<'a, Self>, _instance: &Bound<'_, PyAny>, _owner: Option<&Bound<'_, PyType>>, ) -> PyRefMut<'a, Self> { slf.count += 1; slf } /// Allow assigning a new counter to the descriptor, copying the count across fn __set__(&self, _instance: &Bound<'_, PyAny>, new_value: &mut Self) { new_value.count = self.count; } /// Delete to reset the counter fn __delete__(&mut self, _instance: &Bound<'_, PyAny>) { self.count = 0; } } #[test] fn descr_getset() { Python::with_gil(|py| { let counter = py.get_type_bound::(); let source = pyo3::indoc::indoc!( r#" class Class: counter = Counter() # access via type counter = Class.counter assert counter.count == 1 # access with instance directly assert Counter.__get__(counter, Class()).count == 2 # access via instance c = Class() assert c.counter.count == 3 # __set__ c.counter = Counter() assert c.counter.count == 4 # __delete__ del c.counter assert c.counter.count == 1 "# ); let globals = PyModule::import_bound(py, "__main__").unwrap().dict(); globals.set_item("Counter", counter).unwrap(); py.run_bound(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } #[pyclass] struct NotHashable; #[pymethods] impl NotHashable { #[classattr] const __hash__: Option = None; } #[test] fn test_hash_opt_out() { // By default Python provides a hash implementation, which can be disabled by setting __hash__ // to None. Python::with_gil(|py| { let empty = Py::new(py, EmptyClass).unwrap(); py_assert!(py, empty, "hash(empty) is not None"); let not_hashable = Py::new(py, NotHashable).unwrap(); py_expect_exception!(py, not_hashable, "hash(not_hashable)", PyTypeError); }) } /// Class with __iter__ gets default contains from CPython. #[pyclass] struct DefaultedContains; #[pymethods] impl DefaultedContains { fn __iter__(&self, py: Python<'_>) -> PyObject { PyList::new_bound(py, ["a", "b", "c"]) .as_ref() .iter() .unwrap() .into() } } #[pyclass] struct NoContains; #[pymethods] impl NoContains { fn __iter__(&self, py: Python<'_>) -> PyObject { PyList::new_bound(py, ["a", "b", "c"]) .as_ref() .iter() .unwrap() .into() } // Equivalent to the opt-out const form in NotHashable above, just more verbose, to confirm this // also works. #[classattr] fn __contains__() -> Option { None } } #[test] fn test_contains_opt_out() { Python::with_gil(|py| { let defaulted_contains = Py::new(py, DefaultedContains).unwrap(); py_assert!(py, defaulted_contains, "'a' in defaulted_contains"); let no_contains = Py::new(py, NoContains).unwrap(); py_expect_exception!(py, no_contains, "'a' in no_contains", PyTypeError); }) } pyo3/tests/test_class_new.rs0000644000175000017500000001571114661133735017165 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::sync::GILOnceCell; use pyo3::types::IntoPyDict; #[pyclass] struct EmptyClassWithNew {} #[pymethods] impl EmptyClassWithNew { #[new] fn new() -> EmptyClassWithNew { EmptyClassWithNew {} } } #[test] fn empty_class_with_new() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); assert!(typeobj .call((), None) .unwrap() .downcast::() .is_ok()); // Calling with arbitrary args or kwargs is not ok assert!(typeobj.call(("some", "args"), None).is_err()); assert!(typeobj .call((), Some(&[("some", "kwarg")].into_py_dict_bound(py))) .is_err()); }); } #[pyclass] struct UnitClassWithNew; #[pymethods] impl UnitClassWithNew { #[new] fn new() -> Self { Self } } #[test] fn unit_class_with_new() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); assert!(typeobj .call((), None) .unwrap() .downcast::() .is_ok()); }); } #[pyclass] struct TupleClassWithNew(i32); #[pymethods] impl TupleClassWithNew { #[new] fn new(arg: i32) -> Self { Self(arg) } } #[test] fn tuple_class_with_new() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); let wrp = typeobj.call((42,), None).unwrap(); let obj = wrp.downcast::().unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.0, 42); }); } #[pyclass] #[derive(Debug)] struct NewWithOneArg { data: i32, } #[pymethods] impl NewWithOneArg { #[new] fn new(arg: i32) -> NewWithOneArg { NewWithOneArg { data: arg } } } #[test] fn new_with_one_arg() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); let wrp = typeobj.call((42,), None).unwrap(); let obj = wrp.downcast::().unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.data, 42); }); } #[pyclass] struct NewWithTwoArgs { data1: i32, data2: i32, } #[pymethods] impl NewWithTwoArgs { #[new] fn new(arg1: i32, arg2: i32) -> Self { NewWithTwoArgs { data1: arg1, data2: arg2, } } } #[test] fn new_with_two_args() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); let wrp = typeobj .call((10, 20), None) .map_err(|e| e.display(py)) .unwrap(); let obj = wrp.downcast::().unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.data1, 10); assert_eq!(obj_ref.data2, 20); }); } #[pyclass(subclass)] struct SuperClass { #[pyo3(get)] from_rust: bool, } #[pymethods] impl SuperClass { #[new] fn new() -> Self { SuperClass { from_rust: true } } } /// Checks that `subclass.__new__` works correctly. /// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug. #[test] fn subclass_new() { Python::with_gil(|py| { let super_cls = py.get_type_bound::(); let source = pyo3::indoc::indoc!( r#" class Class(SuperClass): def __new__(cls): return super().__new__(cls) # This should return an instance of Class @property def from_rust(self): return False c = Class() assert c.from_rust is False "# ); let globals = PyModule::import_bound(py, "__main__").unwrap().dict(); globals.set_item("SuperClass", super_cls).unwrap(); py.run_bound(source, Some(&globals), None) .map_err(|e| e.display(py)) .unwrap(); }); } #[pyclass] #[derive(Debug)] struct NewWithCustomError {} struct CustomError; impl From for PyErr { fn from(_error: CustomError) -> PyErr { PyValueError::new_err("custom error") } } #[pymethods] impl NewWithCustomError { #[new] fn new() -> Result { Err(CustomError) } } #[test] fn new_with_custom_error() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); let err = typeobj.call0().unwrap_err(); assert_eq!(err.to_string(), "ValueError: custom error"); }); } #[pyclass] struct NewExisting { #[pyo3(get)] num: usize, } #[pymethods] impl NewExisting { #[new] fn new(py: pyo3::Python<'_>, val: usize) -> pyo3::Py { static PRE_BUILT: GILOnceCell<[pyo3::Py; 2]> = GILOnceCell::new(); let existing = PRE_BUILT.get_or_init(py, || { [ pyo3::Py::new(py, NewExisting { num: 0 }).unwrap(), pyo3::Py::new(py, NewExisting { num: 1 }).unwrap(), ] }); if val < existing.len() { return existing[val].clone_ref(py); } pyo3::Py::new(py, NewExisting { num: val }).unwrap() } } #[test] fn test_new_existing() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); let obj1 = typeobj.call1((0,)).unwrap(); let obj2 = typeobj.call1((0,)).unwrap(); let obj3 = typeobj.call1((1,)).unwrap(); let obj4 = typeobj.call1((1,)).unwrap(); let obj5 = typeobj.call1((2,)).unwrap(); let obj6 = typeobj.call1((2,)).unwrap(); assert!(obj1.getattr("num").unwrap().extract::().unwrap() == 0); assert!(obj2.getattr("num").unwrap().extract::().unwrap() == 0); assert!(obj3.getattr("num").unwrap().extract::().unwrap() == 1); assert!(obj4.getattr("num").unwrap().extract::().unwrap() == 1); assert!(obj5.getattr("num").unwrap().extract::().unwrap() == 2); assert!(obj6.getattr("num").unwrap().extract::().unwrap() == 2); assert!(obj1.is(&obj2)); assert!(obj3.is(&obj4)); assert!(!obj1.is(&obj3)); assert!(!obj1.is(&obj5)); assert!(!obj5.is(&obj6)); }); } #[pyclass] struct NewReturnsPy; #[pymethods] impl NewReturnsPy { #[new] fn new(py: Python<'_>) -> PyResult> { Py::new(py, NewReturnsPy) } } #[test] fn test_new_returns_py() { Python::with_gil(|py| { let type_ = py.get_type_bound::(); let obj = type_.call0().unwrap(); assert!(obj.is_exact_instance_of::()); }) } #[pyclass] struct NewReturnsBound; #[pymethods] impl NewReturnsBound { #[new] fn new(py: Python<'_>) -> PyResult> { Bound::new(py, NewReturnsBound) } } #[test] fn test_new_returns_bound() { Python::with_gil(|py| { let type_ = py.get_type_bound::(); let obj = type_.call0().unwrap(); assert!(obj.is_exact_instance_of::()); }) } pyo3/tests/test_pyfunction.rs0000644000175000017500000004146514661133735017412 0ustar jamespagejamespage#![cfg(feature = "macros")] use std::collections::HashMap; #[cfg(not(Py_LIMITED_API))] use pyo3::buffer::PyBuffer; use pyo3::ffi::c_str; use pyo3::prelude::*; #[cfg(not(Py_LIMITED_API))] use pyo3::types::PyDateTime; #[cfg(not(any(Py_LIMITED_API, PyPy)))] use pyo3::types::PyFunction; use pyo3::types::{self, PyCFunction}; #[path = "../src/tests/common.rs"] mod common; #[pyfunction(name = "struct")] fn struct_function() {} #[test] fn test_rust_keyword_name() { Python::with_gil(|py| { let f = wrap_pyfunction_bound!(struct_function)(py).unwrap(); py_assert!(py, f, "f.__name__ == 'struct'"); }); } #[pyfunction(signature = (arg = true))] fn optional_bool(arg: Option) -> String { format!("{:?}", arg) } #[test] fn test_optional_bool() { // Regression test for issue #932 Python::with_gil(|py| { let f = wrap_pyfunction_bound!(optional_bool)(py).unwrap(); py_assert!(py, f, "f() == 'Some(true)'"); py_assert!(py, f, "f(True) == 'Some(true)'"); py_assert!(py, f, "f(False) == 'Some(false)'"); py_assert!(py, f, "f(None) == 'None'"); }); } #[cfg(not(Py_LIMITED_API))] #[pyfunction] fn buffer_inplace_add(py: Python<'_>, x: PyBuffer, y: PyBuffer) { let x = x.as_mut_slice(py).unwrap(); let y = y.as_slice(py).unwrap(); for (xi, yi) in x.iter().zip(y) { let xi_plus_yi = xi.get() + yi.get(); xi.set(xi_plus_yi); } } #[cfg(not(Py_LIMITED_API))] #[test] fn test_buffer_add() { Python::with_gil(|py| { let f = wrap_pyfunction_bound!(buffer_inplace_add)(py).unwrap(); py_expect_exception!( py, f, r#" import array a = array.array("i", [0, 1, 2, 3]) b = array.array("I", [0, 1, 2, 3]) f(a, b) "#, PyBufferError ); pyo3::py_run!( py, f, r#" import array a = array.array("i", [0, 1, 2, 3]) b = array.array("i", [2, 3, 4, 5]) f(a, b) assert a, array.array("i", [2, 4, 6, 8]) "# ); }); } #[cfg(not(any(Py_LIMITED_API, PyPy)))] #[pyfunction] fn function_with_pyfunction_arg<'py>(fun: &Bound<'py, PyFunction>) -> PyResult> { fun.call((), None) } #[pyfunction] fn function_with_pycfunction_arg<'py>( fun: &Bound<'py, PyCFunction>, ) -> PyResult> { fun.call((), None) } #[test] fn test_functions_with_function_args() { Python::with_gil(|py| { let py_cfunc_arg = wrap_pyfunction_bound!(function_with_pycfunction_arg)(py).unwrap(); let bool_to_string = wrap_pyfunction_bound!(optional_bool)(py).unwrap(); pyo3::py_run!( py, py_cfunc_arg bool_to_string, r#" assert py_cfunc_arg(bool_to_string) == "Some(true)" "# ); #[cfg(not(any(Py_LIMITED_API, PyPy)))] { let py_func_arg = wrap_pyfunction_bound!(function_with_pyfunction_arg)(py).unwrap(); pyo3::py_run!( py, py_func_arg, r#" def foo(): return "bar" assert py_func_arg(foo) == "bar" "# ); } }); } #[cfg(not(Py_LIMITED_API))] fn datetime_to_timestamp(dt: &Bound<'_, PyAny>) -> PyResult { let dt = dt.downcast::()?; let ts: f64 = dt.call_method0("timestamp")?.extract()?; Ok(ts as i64) } #[cfg(not(Py_LIMITED_API))] #[pyfunction] fn function_with_custom_conversion( #[pyo3(from_py_with = "datetime_to_timestamp")] timestamp: i64, ) -> i64 { timestamp } #[cfg(not(Py_LIMITED_API))] #[test] fn test_function_with_custom_conversion() { Python::with_gil(|py| { let custom_conv_func = wrap_pyfunction_bound!(function_with_custom_conversion)(py).unwrap(); pyo3::py_run!( py, custom_conv_func, r#" import datetime dt = datetime.datetime.fromtimestamp(1612040400) assert custom_conv_func(dt) == 1612040400 "# ) }); } #[cfg(not(Py_LIMITED_API))] #[test] fn test_function_with_custom_conversion_error() { Python::with_gil(|py| { let custom_conv_func = wrap_pyfunction_bound!(function_with_custom_conversion)(py).unwrap(); py_expect_exception!( py, custom_conv_func, "custom_conv_func(['a'])", PyTypeError, "argument 'timestamp': 'list' object cannot be converted to 'PyDateTime'" ); }); } #[test] fn test_from_py_with_defaults() { fn optional_int(x: &Bound<'_, PyAny>) -> PyResult> { if x.is_none() { Ok(None) } else { Some(x.extract()).transpose() } } // issue 2280 combination of from_py_with and Option did not compile #[pyfunction] #[pyo3(signature = (int=None))] fn from_py_with_option(#[pyo3(from_py_with = "optional_int")] int: Option) -> i32 { int.unwrap_or(0) } #[pyfunction(signature = (len=0))] fn from_py_with_default( #[pyo3(from_py_with = " as PyAnyMethods>::len")] len: usize, ) -> usize { len } Python::with_gil(|py| { let f = wrap_pyfunction_bound!(from_py_with_option)(py).unwrap(); assert_eq!(f.call0().unwrap().extract::().unwrap(), 0); assert_eq!(f.call1((123,)).unwrap().extract::().unwrap(), 123); assert_eq!(f.call1((999,)).unwrap().extract::().unwrap(), 999); let f2 = wrap_pyfunction_bound!(from_py_with_default)(py).unwrap(); assert_eq!(f2.call0().unwrap().extract::().unwrap(), 0); assert_eq!(f2.call1(("123",)).unwrap().extract::().unwrap(), 3); assert_eq!(f2.call1(("1234",)).unwrap().extract::().unwrap(), 4); }); } #[pyclass] #[derive(Debug, FromPyObject)] struct ValueClass { #[pyo3(get)] value: usize, } #[pyfunction] #[pyo3(signature=(str_arg, int_arg, tuple_arg, option_arg = None, struct_arg = None))] fn conversion_error( str_arg: &str, int_arg: i64, tuple_arg: (String, f64), option_arg: Option, struct_arg: Option, ) { println!( "{:?} {:?} {:?} {:?} {:?}", str_arg, int_arg, tuple_arg, option_arg, struct_arg ); } #[test] fn test_conversion_error() { Python::with_gil(|py| { let conversion_error = wrap_pyfunction_bound!(conversion_error)(py).unwrap(); py_expect_exception!( py, conversion_error, "conversion_error(None, None, None, None, None)", PyTypeError, "argument 'str_arg': 'NoneType' object cannot be converted to 'PyString'" ); py_expect_exception!( py, conversion_error, "conversion_error(100, None, None, None, None)", PyTypeError, "argument 'str_arg': 'int' object cannot be converted to 'PyString'" ); py_expect_exception!( py, conversion_error, "conversion_error('string1', 'string2', None, None, None)", PyTypeError, "argument 'int_arg': 'str' object cannot be interpreted as an integer" ); py_expect_exception!( py, conversion_error, "conversion_error('string1', -100, 'string2', None, None)", PyTypeError, "argument 'tuple_arg': 'str' object cannot be converted to 'PyTuple'" ); py_expect_exception!( py, conversion_error, "conversion_error('string1', -100, ('string2', 10.), 'string3', None)", PyTypeError, "argument 'option_arg': 'str' object cannot be interpreted as an integer" ); let exception = py_expect_exception!( py, conversion_error, " class ValueClass: def __init__(self, value): self.value = value conversion_error('string1', -100, ('string2', 10.), None, ValueClass(\"no_expected_type\"))", PyTypeError ); assert_eq!( extract_traceback(py, exception), "TypeError: argument 'struct_arg': failed to \ extract field ValueClass.value: TypeError: 'str' object cannot be interpreted as an integer" ); let exception = py_expect_exception!( py, conversion_error, " class ValueClass: def __init__(self, value): self.value = value conversion_error('string1', -100, ('string2', 10.), None, ValueClass(-5))", PyTypeError ); assert_eq!( extract_traceback(py, exception), "TypeError: argument 'struct_arg': failed to \ extract field ValueClass.value: OverflowError: can't convert negative int to unsigned" ); }); } /// Helper function that concatenates the error message from /// each error in the traceback into a single string that can /// be tested. fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String { let mut error_msg = error.to_string(); while let Some(cause) = error.cause(py) { error_msg.push_str(": "); error_msg.push_str(&cause.to_string()); error = cause } error_msg } #[test] fn test_pycfunction_new() { use pyo3::ffi; Python::with_gil(|py| { unsafe extern "C" fn c_fn( _self: *mut ffi::PyObject, _args: *mut ffi::PyObject, ) -> *mut ffi::PyObject { ffi::PyLong_FromLong(4200) } let py_fn = PyCFunction::new_bound( py, c_fn, c_str!("py_fn"), c_str!("py_fn for test (this is the docstring)"), None, ) .unwrap(); py_assert!(py, py_fn, "py_fn() == 4200"); py_assert!( py, py_fn, "py_fn.__doc__ == 'py_fn for test (this is the docstring)'" ); }); } #[test] fn test_pycfunction_new_with_keywords() { use pyo3::ffi; use std::ffi::CString; use std::os::raw::{c_char, c_long}; use std::ptr; Python::with_gil(|py| { unsafe extern "C" fn c_fn( _self: *mut ffi::PyObject, args: *mut ffi::PyObject, kwds: *mut ffi::PyObject, ) -> *mut ffi::PyObject { let mut foo: c_long = 0; let mut bar: c_long = 0; let foo_ptr: *mut c_long = &mut foo; let bar_ptr: *mut c_long = &mut bar; let foo_name = CString::new("foo").unwrap(); let foo_name_raw: *mut c_char = foo_name.into_raw(); let kw_bar_name = CString::new("kw_bar").unwrap(); let kw_bar_name_raw: *mut c_char = kw_bar_name.into_raw(); let mut arglist = vec![foo_name_raw, kw_bar_name_raw, ptr::null_mut()]; let arglist_ptr: *mut *mut c_char = arglist.as_mut_ptr(); let arg_pattern: *const c_char = CString::new("l|l").unwrap().into_raw(); ffi::PyArg_ParseTupleAndKeywords( args, kwds, arg_pattern, arglist_ptr, foo_ptr, bar_ptr, ); ffi::PyLong_FromLong(foo * bar) } let py_fn = PyCFunction::new_with_keywords_bound( py, c_fn, c_str!("py_fn"), c_str!("py_fn for test (this is the docstring)"), None, ) .unwrap(); py_assert!(py, py_fn, "py_fn(42, kw_bar=100) == 4200"); py_assert!(py, py_fn, "py_fn(foo=42, kw_bar=100) == 4200"); py_assert!( py, py_fn, "py_fn.__doc__ == 'py_fn for test (this is the docstring)'" ); }); } #[test] fn test_closure() { Python::with_gil(|py| { let f = |args: &Bound<'_, types::PyTuple>, _kwargs: Option<&Bound<'_, types::PyDict>>| -> PyResult<_> { Python::with_gil(|py| { let res: Vec<_> = args .iter() .map(|elem| { if let Ok(i) = elem.extract::() { (i + 1).into_py(py) } else if let Ok(f) = elem.extract::() { (2. * f).into_py(py) } else if let Ok(mut s) = elem.extract::() { s.push_str("-py"); s.into_py(py) } else { panic!("unexpected argument type for {:?}", elem) } }) .collect(); Ok(res) }) }; let closure_py = PyCFunction::new_closure_bound( py, Some(c_str!("test_fn")), Some(c_str!("test_fn doc")), f, ) .unwrap(); py_assert!(py, closure_py, "closure_py(42) == [43]"); py_assert!(py, closure_py, "closure_py.__name__ == 'test_fn'"); py_assert!(py, closure_py, "closure_py.__doc__ == 'test_fn doc'"); py_assert!( py, closure_py, "closure_py(42, 3.14, 'foo') == [43, 6.28, 'foo-py']" ); }); } #[test] fn test_closure_counter() { Python::with_gil(|py| { let counter = std::cell::RefCell::new(0); let counter_fn = move |_args: &Bound<'_, types::PyTuple>, _kwargs: Option<&Bound<'_, types::PyDict>>| -> PyResult { let mut counter = counter.borrow_mut(); *counter += 1; Ok(*counter) }; let counter_py = PyCFunction::new_closure_bound(py, None, None, counter_fn).unwrap(); py_assert!(py, counter_py, "counter_py() == 1"); py_assert!(py, counter_py, "counter_py() == 2"); py_assert!(py, counter_py, "counter_py() == 3"); }); } #[test] fn use_pyfunction() { mod function_in_module { use pyo3::prelude::*; #[pyfunction] pub fn foo(x: i32) -> i32 { x } } Python::with_gil(|py| { use function_in_module::foo; // check imported name can be wrapped let f = wrap_pyfunction_bound!(foo, py).unwrap(); assert_eq!(f.call1((5,)).unwrap().extract::().unwrap(), 5); assert_eq!(f.call1((42,)).unwrap().extract::().unwrap(), 42); // check path import can be wrapped let f2 = wrap_pyfunction_bound!(function_in_module::foo, py).unwrap(); assert_eq!(f2.call1((5,)).unwrap().extract::().unwrap(), 5); assert_eq!(f2.call1((42,)).unwrap().extract::().unwrap(), 42); }) } #[pyclass] struct Key(String); #[pyclass] struct Value(i32); #[pyfunction] fn return_value_borrows_from_arguments<'py>( py: Python<'py>, key: &'py Key, value: &'py Value, ) -> HashMap<&'py str, i32> { py.allow_threads(move || { let mut map = HashMap::new(); map.insert(key.0.as_str(), value.0); map }) } #[test] fn test_return_value_borrows_from_arguments() { Python::with_gil(|py| { let function = wrap_pyfunction_bound!(return_value_borrows_from_arguments, py).unwrap(); let key = Py::new(py, Key("key".to_owned())).unwrap(); let value = Py::new(py, Value(42)).unwrap(); py_assert!(py, function key value, "function(key, value) == { \"key\": 42 }"); }); } #[test] fn test_some_wrap_arguments() { // https://github.com/PyO3/pyo3/issues/3460 const NONE: Option = None; #[pyfunction(signature = (a = 1, b = Some(2), c = None, d = NONE))] fn some_wrap_arguments( a: Option, b: Option, c: Option, d: Option, ) -> [Option; 4] { [a, b, c, d] } Python::with_gil(|py| { let function = wrap_pyfunction_bound!(some_wrap_arguments, py).unwrap(); py_assert!(py, function, "function() == [1, 2, None, None]"); }) } #[test] fn test_reference_to_bound_arguments() { #[pyfunction] #[pyo3(signature = (x, y = None))] fn reference_args<'py>( x: &Bound<'py, PyAny>, y: Option<&Bound<'py, PyAny>>, ) -> PyResult> { y.map_or_else(|| Ok(x.clone()), |y| y.add(x)) } Python::with_gil(|py| { let function = wrap_pyfunction_bound!(reference_args, py).unwrap(); py_assert!(py, function, "function(1) == 1"); py_assert!(py, function, "function(1, 2) == 3"); }) } #[test] fn test_pyfunction_raw_ident() { #[pyfunction] fn r#struct() -> bool { true } #[pyfunction] #[pyo3(name = "r#enum")] fn raw_ident() -> bool { true } #[pymodule] fn m(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(r#struct, m)?)?; m.add_function(wrap_pyfunction!(raw_ident, m)?)?; Ok(()) } Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(m)(py); py_assert!(py, m, "m.struct()"); py_assert!(py, m, "m.enum()"); }) } pyo3/tests/test_class_attributes.rs0000644000175000017500000001557314661133735020570 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct Foo { #[pyo3(get)] x: i32, } #[pyclass] struct Bar { #[pyo3(get)] x: i32, } #[pymethods] impl Foo { #[classattr] const MY_CONST: &'static str = "foobar"; #[classattr] #[pyo3(name = "RENAMED_CONST")] const MY_CONST_2: &'static str = "foobar_2"; #[classattr] fn a() -> i32 { 5 } #[classattr] #[pyo3(name = "B")] fn b() -> String { "bar".to_string() } #[classattr] fn bar() -> Bar { Bar { x: 2 } } #[classattr] fn a_foo() -> Foo { Foo { x: 1 } } #[classattr] fn a_foo_with_py(py: Python<'_>) -> Py { Py::new(py, Foo { x: 1 }).unwrap() } } #[test] fn class_attributes() { Python::with_gil(|py| { let foo_obj = py.get_type_bound::(); py_assert!(py, foo_obj, "foo_obj.MY_CONST == 'foobar'"); py_assert!(py, foo_obj, "foo_obj.RENAMED_CONST == 'foobar_2'"); py_assert!(py, foo_obj, "foo_obj.a == 5"); py_assert!(py, foo_obj, "foo_obj.B == 'bar'"); py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1"); py_assert!(py, foo_obj, "foo_obj.a_foo_with_py.x == 1"); }); } // Ignored because heap types are not immutable: // https://github.com/python/cpython/blob/master/Objects/typeobject.c#L3399-L3409 #[test] #[ignore] fn class_attributes_are_immutable() { Python::with_gil(|py| { let foo_obj = py.get_type_bound::(); py_expect_exception!(py, foo_obj, "foo_obj.a = 6", PyTypeError); }); } #[pymethods] impl Bar { #[classattr] fn a_foo() -> Foo { Foo { x: 3 } } } #[test] fn recursive_class_attributes() { Python::with_gil(|py| { let foo_obj = py.get_type_bound::(); let bar_obj = py.get_type_bound::(); py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1"); py_assert!(py, foo_obj, "foo_obj.bar.x == 2"); py_assert!(py, bar_obj, "bar_obj.a_foo.x == 3"); }); } #[test] fn test_fallible_class_attribute() { use pyo3::{exceptions::PyValueError, types::PyString}; struct CaptureStdErr<'py> { oldstderr: Bound<'py, PyAny>, string_io: Bound<'py, PyAny>, } impl<'py> CaptureStdErr<'py> { fn new(py: Python<'py>) -> PyResult { let sys = py.import_bound("sys")?; let oldstderr = sys.getattr("stderr")?; let string_io = py.import_bound("io")?.getattr("StringIO")?.call0()?; sys.setattr("stderr", &string_io)?; Ok(Self { oldstderr, string_io, }) } fn reset(self) -> PyResult { let py = self.string_io.py(); let payload = self .string_io .getattr("getvalue")? .call0()? .downcast::()? .to_cow()? .into_owned(); let sys = py.import_bound("sys")?; sys.setattr("stderr", self.oldstderr)?; Ok(payload) } } #[pyclass] struct BrokenClass; #[pymethods] impl BrokenClass { #[classattr] fn fails_to_init() -> PyResult { Err(PyValueError::new_err("failed to create class attribute")) } } Python::with_gil(|py| { let stderr = CaptureStdErr::new(py).unwrap(); assert!(std::panic::catch_unwind(|| py.get_type_bound::()).is_err()); assert_eq!( stderr.reset().unwrap().trim(), "\ ValueError: failed to create class attribute The above exception was the direct cause of the following exception: RuntimeError: An error occurred while initializing `BrokenClass.fails_to_init` The above exception was the direct cause of the following exception: RuntimeError: An error occurred while initializing class BrokenClass" ) }); } #[pyclass(get_all, set_all, rename_all = "camelCase")] struct StructWithRenamedFields { first_field: bool, second_field: u8, #[pyo3(name = "third_field")] fourth_field: bool, } #[pymethods] impl StructWithRenamedFields { #[new] fn new() -> Self { Self { first_field: true, second_field: 5, fourth_field: false, } } } #[test] fn test_renaming_all_struct_fields() { use pyo3::types::PyBool; Python::with_gil(|py| { let struct_class = py.get_type_bound::(); let struct_obj = struct_class.call0().unwrap(); assert!(struct_obj .setattr("firstField", PyBool::new_bound(py, false)) .is_ok()); py_assert!(py, struct_obj, "struct_obj.firstField == False"); py_assert!(py, struct_obj, "struct_obj.secondField == 5"); assert!(struct_obj .setattr("third_field", PyBool::new_bound(py, true)) .is_ok()); py_assert!(py, struct_obj, "struct_obj.third_field == True"); }); } macro_rules! test_case { ($struct_name: ident, $rule: literal, $field_name: ident, $renamed_field_name: literal, $test_name: ident) => { #[pyclass(get_all, set_all, rename_all = $rule)] #[allow(non_snake_case)] struct $struct_name { $field_name: u8, } #[pymethods] impl $struct_name { #[new] fn new() -> Self { Self { $field_name: 0 } } } #[test] fn $test_name() { //use pyo3::types::PyInt; Python::with_gil(|py| { let struct_class = py.get_type_bound::<$struct_name>(); let struct_obj = struct_class.call0().unwrap(); assert!(struct_obj.setattr($renamed_field_name, 2).is_ok()); let attr = struct_obj.getattr($renamed_field_name).unwrap(); assert_eq!(2, attr.extract().unwrap()); }); } }; } test_case!( LowercaseTest, "lowercase", fieldOne, "fieldone", test_rename_all_lowercase ); test_case!( CamelCaseTest, "camelCase", field_one, "fieldOne", test_rename_all_camel_case ); test_case!( KebabCaseTest, "kebab-case", field_one, "field-one", test_rename_all_kebab_case ); test_case!( PascalCaseTest, "PascalCase", field_one, "FieldOne", test_rename_all_pascal_case ); test_case!( ScreamingSnakeCaseTest, "SCREAMING_SNAKE_CASE", field_one, "FIELD_ONE", test_rename_all_screaming_snake_case ); test_case!( ScreamingKebabCaseTest, "SCREAMING-KEBAB-CASE", field_one, "FIELD-ONE", test_rename_all_screaming_kebab_case ); test_case!( SnakeCaseTest, "snake_case", fieldOne, "field_one", test_rename_all_snake_case ); test_case!( UppercaseTest, "UPPERCASE", fieldOne, "FIELDONE", test_rename_all_uppercase ); pyo3/tests/test_string.rs0000644000175000017500000000103014661133735016502 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; #[path = "../src/tests/common.rs"] mod common; #[pyfunction] fn take_str(_s: &str) {} #[test] fn test_unicode_encode_error() { Python::with_gil(|py| { let take_str = wrap_pyfunction_bound!(take_str)(py).unwrap(); py_expect_exception!( py, take_str, "take_str('\\ud800')", PyUnicodeEncodeError, "'utf-8' codec can't encode character '\\ud800' in position 0: surrogates not allowed" ); }); } pyo3/tests/test_enum.rs0000644000175000017500000002123714661133735016153 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; #[path = "../src/tests/common.rs"] mod common; #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] pub enum MyEnum { Variant, OtherVariant, } #[test] fn test_enum_class_attr() { Python::with_gil(|py| { let my_enum = py.get_type_bound::(); let var = Py::new(py, MyEnum::Variant).unwrap(); py_assert!(py, my_enum var, "my_enum.Variant == var"); }) } #[pyfunction] fn return_enum() -> MyEnum { MyEnum::Variant } #[test] fn test_return_enum() { Python::with_gil(|py| { let f = wrap_pyfunction_bound!(return_enum)(py).unwrap(); let mynum = py.get_type_bound::(); py_run!(py, f mynum, "assert f() == mynum.Variant") }); } #[pyfunction] fn enum_arg(e: MyEnum) { assert_eq!(MyEnum::OtherVariant, e) } #[test] fn test_enum_arg() { Python::with_gil(|py| { let f = wrap_pyfunction_bound!(enum_arg)(py).unwrap(); let mynum = py.get_type_bound::(); py_run!(py, f mynum, "f(mynum.OtherVariant)") }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] enum CustomDiscriminant { One = 1, Two = 2, } #[test] fn test_custom_discriminant() { Python::with_gil(|py| { #[allow(non_snake_case)] let CustomDiscriminant = py.get_type_bound::(); let one = Py::new(py, CustomDiscriminant::One).unwrap(); let two = Py::new(py, CustomDiscriminant::Two).unwrap(); py_run!(py, CustomDiscriminant one two, r#" assert CustomDiscriminant.One == one assert CustomDiscriminant.Two == two assert one != two "#); }) } #[test] fn test_enum_to_int() { Python::with_gil(|py| { let one = Py::new(py, CustomDiscriminant::One).unwrap(); py_assert!(py, one, "int(one) == 1"); let v = Py::new(py, MyEnum::Variant).unwrap(); let v_value = MyEnum::Variant as isize; py_run!(py, v v_value, "int(v) == v_value"); }) } #[test] fn test_enum_compare_int() { Python::with_gil(|py| { let one = Py::new(py, CustomDiscriminant::One).unwrap(); py_run!( py, one, r#" assert one == 1 assert 1 == one assert one != 2 "# ) }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] #[repr(u8)] enum SmallEnum { V = 1, } #[test] fn test_enum_compare_int_no_throw_when_overflow() { Python::with_gil(|py| { let v = Py::new(py, SmallEnum::V).unwrap(); py_assert!(py, v, "v != 1<<30") }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] #[repr(usize)] #[allow(clippy::enum_clike_unportable_variant)] enum BigEnum { V = usize::MAX, } #[test] fn test_big_enum_no_overflow() { Python::with_gil(|py| { let usize_max = usize::MAX; let v = Py::new(py, BigEnum::V).unwrap(); py_assert!(py, usize_max v, "v == usize_max"); py_assert!(py, usize_max v, "int(v) == usize_max"); }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] #[repr(u16, align(8))] enum TestReprParse { V, } #[test] fn test_repr_parse() { assert_eq!(std::mem::align_of::(), 8); } #[pyclass(eq, eq_int, name = "MyEnum")] #[derive(Debug, PartialEq, Eq, Clone)] pub enum RenameEnum { Variant, } #[test] fn test_rename_enum_repr_correct() { Python::with_gil(|py| { let var1 = Py::new(py, RenameEnum::Variant).unwrap(); py_assert!(py, var1, "repr(var1) == 'MyEnum.Variant'"); }) } #[pyclass(eq, eq_int)] #[derive(Debug, PartialEq, Eq, Clone)] pub enum RenameVariantEnum { #[pyo3(name = "VARIANT")] Variant, } #[test] fn test_rename_variant_repr_correct() { Python::with_gil(|py| { let var1 = Py::new(py, RenameVariantEnum::Variant).unwrap(); py_assert!(py, var1, "repr(var1) == 'RenameVariantEnum.VARIANT'"); }) } #[pyclass(eq, eq_int, rename_all = "SCREAMING_SNAKE_CASE")] #[derive(Debug, PartialEq, Eq, Clone)] #[allow(clippy::enum_variant_names)] enum RenameAllVariantsEnum { VariantOne, VariantTwo, #[pyo3(name = "VariantThree")] VariantFour, } #[test] fn test_renaming_all_enum_variants() { Python::with_gil(|py| { let enum_obj = py.get_type_bound::(); py_assert!(py, enum_obj, "enum_obj.VARIANT_ONE == enum_obj.VARIANT_ONE"); py_assert!(py, enum_obj, "enum_obj.VARIANT_TWO == enum_obj.VARIANT_TWO"); py_assert!( py, enum_obj, "enum_obj.VariantThree == enum_obj.VariantThree" ); }); } #[pyclass(module = "custom_module")] #[derive(Debug, Clone)] enum CustomModuleComplexEnum { Variant(), } #[test] fn test_custom_module() { Python::with_gil(|py| { let enum_obj = py.get_type_bound::(); py_assert!( py, enum_obj, "enum_obj.Variant.__module__ == 'custom_module'" ); }); } #[pyclass(eq)] #[derive(Debug, Clone, PartialEq)] pub enum EqOnly { VariantA, VariantB, } #[test] fn test_simple_enum_eq_only() { Python::with_gil(|py| { let var1 = Py::new(py, EqOnly::VariantA).unwrap(); let var2 = Py::new(py, EqOnly::VariantA).unwrap(); let var3 = Py::new(py, EqOnly::VariantB).unwrap(); py_assert!(py, var1 var2, "var1 == var2"); py_assert!(py, var1 var3, "var1 != var3"); }) } #[pyclass(frozen, eq, eq_int, hash)] #[derive(PartialEq, Hash)] enum SimpleEnumWithHash { A, B, } #[test] fn test_simple_enum_with_hash() { Python::with_gil(|py| { use pyo3::types::IntoPyDict; let class = SimpleEnumWithHash::A; let hash = { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); class.hash(&mut hasher); hasher.finish() as isize }; let env = [ ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_py(py)), ] .into_py_dict_bound(py); py_assert!(py, *env, "hash(obj) == hsh"); }); } #[pyclass(eq, hash)] #[derive(PartialEq, Hash)] enum ComplexEnumWithHash { A(u32), B { msg: String }, } #[test] fn test_complex_enum_with_hash() { Python::with_gil(|py| { use pyo3::types::IntoPyDict; let class = ComplexEnumWithHash::B { msg: String::from("Hello"), }; let hash = { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); class.hash(&mut hasher); hasher.finish() as isize }; let env = [ ("obj", Py::new(py, class).unwrap().into_any()), ("hsh", hash.into_py(py)), ] .into_py_dict_bound(py); py_assert!(py, *env, "hash(obj) == hsh"); }); } #[allow(deprecated)] mod deprecated { use crate::py_assert; use pyo3::prelude::*; use pyo3::py_run; #[pyclass] #[derive(Debug, PartialEq, Eq, Clone)] pub enum MyEnum { Variant, OtherVariant, } #[test] fn test_enum_eq_enum() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); let var2 = Py::new(py, MyEnum::Variant).unwrap(); let other_var = Py::new(py, MyEnum::OtherVariant).unwrap(); py_assert!(py, var1 var2, "var1 == var2"); py_assert!(py, var1 other_var, "var1 != other_var"); py_assert!(py, var1 var2, "(var1 != var2) == False"); }) } #[test] fn test_enum_eq_incomparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); py_assert!(py, var1, "(var1 == 'foo') == False"); py_assert!(py, var1, "(var1 != 'foo') == True"); }) } #[pyclass] enum CustomDiscriminant { One = 1, Two = 2, } #[test] fn test_custom_discriminant() { Python::with_gil(|py| { #[allow(non_snake_case)] let CustomDiscriminant = py.get_type_bound::(); let one = Py::new(py, CustomDiscriminant::One).unwrap(); let two = Py::new(py, CustomDiscriminant::Two).unwrap(); py_run!(py, CustomDiscriminant one two, r#" assert CustomDiscriminant.One == one assert CustomDiscriminant.Two == two assert CustomDiscriminant.One == 1 assert CustomDiscriminant.Two == 2 assert one != two assert CustomDiscriminant.One != 2 assert CustomDiscriminant.Two != 1 "#); }) } } pyo3/tests/test_exceptions.rs0000644000175000017500000000613114661133735017364 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::{exceptions, py_run}; use std::error::Error; use std::fmt; #[cfg(not(target_os = "windows"))] use std::fs::File; #[path = "../src/tests/common.rs"] mod common; #[pyfunction] #[cfg(not(target_os = "windows"))] fn fail_to_open_file() -> PyResult<()> { File::open("not_there.txt")?; Ok(()) } #[test] #[cfg_attr(target_arch = "wasm32", ignore)] // Not sure why this fails. #[cfg(not(target_os = "windows"))] fn test_filenotfounderror() { Python::with_gil(|py| { let fail_to_open_file = wrap_pyfunction_bound!(fail_to_open_file)(py).unwrap(); py_run!( py, fail_to_open_file, r#" try: fail_to_open_file() except FileNotFoundError as e: assert str(e) == "No such file or directory (os error 2)" "# ); }); } #[derive(Debug)] struct CustomError; impl Error for CustomError {} impl fmt::Display for CustomError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Oh no!") } } impl std::convert::From for PyErr { fn from(err: CustomError) -> PyErr { exceptions::PyOSError::new_err(err.to_string()) } } fn fail_with_custom_error() -> Result<(), CustomError> { Err(CustomError) } #[pyfunction] fn call_fail_with_custom_error() -> PyResult<()> { fail_with_custom_error()?; Ok(()) } #[test] fn test_custom_error() { Python::with_gil(|py| { let call_fail_with_custom_error = wrap_pyfunction_bound!(call_fail_with_custom_error)(py).unwrap(); py_run!( py, call_fail_with_custom_error, r#" try: call_fail_with_custom_error() except OSError as e: assert str(e) == "Oh no!" "# ); }); } #[test] fn test_exception_nosegfault() { use std::net::TcpListener; fn io_err() -> PyResult<()> { TcpListener::bind("no:address")?; Ok(()) } fn parse_int() -> PyResult<()> { "@_@".parse::()?; Ok(()) } assert!(io_err().is_err()); assert!(parse_int().is_err()); } #[test] #[cfg(Py_3_8)] fn test_write_unraisable() { use common::UnraisableCapture; use pyo3::{exceptions::PyRuntimeError, ffi, types::PyNotImplemented}; Python::with_gil(|py| { let capture = UnraisableCapture::install(py); assert!(capture.borrow(py).capture.is_none()); let err = PyRuntimeError::new_err("foo"); err.write_unraisable_bound(py, None); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "RuntimeError: foo"); assert!(object.is_none(py)); let err = PyRuntimeError::new_err("bar"); err.write_unraisable_bound(py, Some(&PyNotImplemented::get_bound(py))); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "RuntimeError: bar"); assert!(object.as_ptr() == unsafe { ffi::Py_NotImplemented() }); capture.borrow_mut(py).uninstall(py); }); } pyo3/tests/test_mapping.rs0000644000175000017500000000667214661133735016650 0ustar jamespagejamespage#![cfg(feature = "macros")] use std::collections::HashMap; use pyo3::exceptions::PyKeyError; use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::IntoPyDict; use pyo3::types::PyList; use pyo3::types::PyMapping; use pyo3::types::PySequence; #[path = "../src/tests/common.rs"] mod common; #[pyclass(mapping)] struct Mapping { index: HashMap, } #[pymethods] impl Mapping { #[new] #[pyo3(signature=(elements=None))] fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult { if let Some(pylist) = elements { let mut elems = HashMap::with_capacity(pylist.len()); for (i, pyelem) in pylist.into_iter().enumerate() { let elem = pyelem.extract()?; elems.insert(elem, i); } Ok(Self { index: elems }) } else { Ok(Self { index: HashMap::new(), }) } } fn __len__(&self) -> usize { self.index.len() } fn __getitem__(&self, query: String) -> PyResult { self.index .get(&query) .copied() .ok_or_else(|| PyKeyError::new_err("unknown key")) } fn __setitem__(&mut self, key: String, value: usize) { self.index.insert(key, value); } fn __delitem__(&mut self, key: String) -> PyResult<()> { if self.index.remove(&key).is_none() { Err(PyKeyError::new_err("unknown key")) } else { Ok(()) } } #[pyo3(signature=(key, default=None))] fn get(&self, py: Python<'_>, key: &str, default: Option) -> Option { self.index .get(key) .map(|value| value.into_py(py)) .or(default) } } /// Return a dict with `m = Mapping(['1', '2', '3'])`. fn map_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { let d = [("Mapping", py.get_type_bound::())].into_py_dict_bound(py); py_run!(py, *d, "m = Mapping(['1', '2', '3'])"); d } #[test] fn test_getitem() { Python::with_gil(|py| { let d = map_dict(py); py_assert!(py, *d, "m['1'] == 0"); py_assert!(py, *d, "m['2'] == 1"); py_assert!(py, *d, "m['3'] == 2"); py_expect_exception!(py, *d, "print(m['4'])", PyKeyError); }); } #[test] fn test_setitem() { Python::with_gil(|py| { let d = map_dict(py); py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4"); py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0"); py_assert!(py, *d, "len(m) == 4"); py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError); py_expect_exception!(py, *d, "m[0] = -1", PyTypeError); }); } #[test] fn test_delitem() { Python::with_gil(|py| { let d = map_dict(py); py_run!( py, *d, "del m['1']; assert len(m) == 2 and m['2'] == 1 and m['3'] == 2" ); py_expect_exception!(py, *d, "del m[-1]", PyTypeError); py_expect_exception!(py, *d, "del m['4']", PyKeyError); }); } #[test] fn mapping_is_not_sequence() { Python::with_gil(|py| { let mut index = HashMap::new(); index.insert("Foo".into(), 1); index.insert("Bar".into(), 2); let m = Py::new(py, Mapping { index }).unwrap(); PyMapping::register::(py).unwrap(); assert!(m.bind(py).downcast::().is_ok()); assert!(m.bind(py).downcast::().is_err()); }); } pyo3/tests/test_methods.rs0000644000175000017500000007466014661133735016662 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::PySequence; use pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct InstanceMethod { member: i32, } #[pymethods] impl InstanceMethod { /// Test method fn method(&self) -> i32 { self.member } // Checks that &Self works fn add_other(&self, other: &Self) -> i32 { self.member + other.member } } #[test] fn instance_method() { Python::with_gil(|py| { let obj = Bound::new(py, InstanceMethod { member: 42 }).unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.method(), 42); py_assert!(py, obj, "obj.method() == 42"); py_assert!(py, obj, "obj.add_other(obj) == 84"); py_assert!(py, obj, "obj.method.__doc__ == 'Test method'"); }); } #[pyclass] struct InstanceMethodWithArgs { member: i32, } #[pymethods] impl InstanceMethodWithArgs { fn method(&self, multiplier: i32) -> i32 { self.member * multiplier } } #[test] fn instance_method_with_args() { Python::with_gil(|py| { let obj = Bound::new(py, InstanceMethodWithArgs { member: 7 }).unwrap(); let obj_ref = obj.borrow(); assert_eq!(obj_ref.method(6), 42); py_assert!(py, obj, "obj.method(3) == 21"); py_assert!(py, obj, "obj.method(multiplier=6) == 42"); }); } #[pyclass] struct ClassMethod {} #[pymethods] impl ClassMethod { #[new] fn new() -> Self { ClassMethod {} } #[classmethod] /// Test class method. fn method(cls: &Bound<'_, PyType>) -> PyResult { Ok(format!("{}.method()!", cls.qualname()?)) } #[classmethod] fn method_owned(cls: Py, py: Python<'_>) -> PyResult { Ok(format!("{}.method_owned()!", cls.bind(py).qualname()?)) } } #[test] fn class_method() { Python::with_gil(|py| { let d = [("C", py.get_type_bound::())].into_py_dict_bound(py); py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'"); py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'"); py_assert!( py, *d, "C().method_owned() == 'ClassMethod.method_owned()!'" ); py_assert!(py, *d, "C.method.__doc__ == 'Test class method.'"); py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'"); }); } #[pyclass] struct ClassMethodWithArgs {} #[pymethods] impl ClassMethodWithArgs { #[classmethod] fn method(cls: &Bound<'_, PyType>, input: &Bound<'_, PyString>) -> PyResult { Ok(format!("{}.method({})", cls.qualname()?, input)) } } #[test] fn class_method_with_args() { Python::with_gil(|py| { let d = [("C", py.get_type_bound::())].into_py_dict_bound(py); py_assert!( py, *d, "C.method('abc') == 'ClassMethodWithArgs.method(abc)'" ); }); } #[pyclass] struct StaticMethod {} #[pymethods] impl StaticMethod { #[new] fn new() -> Self { StaticMethod {} } #[staticmethod] /// Test static method. fn method(_py: Python<'_>) -> &'static str { "StaticMethod.method()!" } } #[test] fn static_method() { Python::with_gil(|py| { assert_eq!(StaticMethod::method(py), "StaticMethod.method()!"); let d = [("C", py.get_type_bound::())].into_py_dict_bound(py); py_assert!(py, *d, "C.method() == 'StaticMethod.method()!'"); py_assert!(py, *d, "C().method() == 'StaticMethod.method()!'"); py_assert!(py, *d, "C.method.__doc__ == 'Test static method.'"); py_assert!(py, *d, "C().method.__doc__ == 'Test static method.'"); }); } #[pyclass] struct StaticMethodWithArgs {} #[pymethods] impl StaticMethodWithArgs { #[staticmethod] fn method(_py: Python<'_>, input: i32) -> String { format!("0x{:x}", input) } } #[test] fn static_method_with_args() { Python::with_gil(|py| { assert_eq!(StaticMethodWithArgs::method(py, 1234), "0x4d2"); let d = [("C", py.get_type_bound::())].into_py_dict_bound(py); py_assert!(py, *d, "C.method(1337) == '0x539'"); }); } #[pyclass] struct MethSignature {} #[pymethods] impl MethSignature { #[pyo3(signature = (test = None))] fn get_optional(&self, test: Option) -> i32 { test.unwrap_or(10) } #[pyo3(signature = (test = None))] fn get_optional2(&self, test: Option) -> Option { test } #[pyo3(signature=(_t1 = None, t2 = None, _t3 = None))] fn get_optional_positional( &self, _t1: Option, t2: Option, _t3: Option, ) -> Option { t2 } #[pyo3(signature = (test = 10))] fn get_default(&self, test: i32) -> i32 { test } #[pyo3(signature = (*, test = 10))] fn get_kwarg(&self, test: i32) -> i32 { test } #[pyo3(signature = (*args, **kwargs))] fn get_kwargs( &self, py: Python<'_>, args: &Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyObject { [args.to_object(py), kwargs.to_object(py)].to_object(py) } #[pyo3(signature = (a, *args, **kwargs))] fn get_pos_arg_kw( &self, py: Python<'_>, a: i32, args: &Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyObject { [a.to_object(py), args.to_object(py), kwargs.to_object(py)].to_object(py) } #[pyo3(signature = (a, b, /))] fn get_pos_only(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, b))] fn get_pos_only_and_pos(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, b, c = 5))] fn get_pos_only_and_pos_and_kw(&self, a: i32, b: i32, c: i32) -> i32 { a + b + c } #[pyo3(signature = (a, /, *, b))] fn get_pos_only_and_kw_only(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, *, b = 3))] fn get_pos_only_and_kw_only_with_default(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (a, /, b, *, c, d = 5))] fn get_all_arg_types_together(&self, a: i32, b: i32, c: i32, d: i32) -> i32 { a + b + c + d } #[pyo3(signature = (a, /, *args))] fn get_pos_only_with_varargs(&self, a: i32, args: Vec) -> i32 { a + args.iter().sum::() } #[pyo3(signature = (a, /, **kwargs))] fn get_pos_only_with_kwargs( &self, py: Python<'_>, a: i32, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyObject { [a.to_object(py), kwargs.to_object(py)].to_object(py) } #[pyo3(signature = (a=0, /, **kwargs))] fn get_optional_pos_only_with_kwargs( &self, py: Python<'_>, a: i32, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyObject { [a.to_object(py), kwargs.to_object(py)].to_object(py) } #[pyo3(signature = (*, a = 2, b = 3))] fn get_kwargs_only_with_defaults(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (*, a, b))] fn get_kwargs_only(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (*, a = 1, b))] fn get_kwargs_only_with_some_default(&self, a: i32, b: i32) -> i32 { a + b } #[pyo3(signature = (*args, a))] fn get_args_and_required_keyword( &self, py: Python<'_>, args: &Bound<'_, PyTuple>, a: i32, ) -> PyObject { (args, a).to_object(py) } #[pyo3(signature = (a, b = 2, *, c = 3))] fn get_pos_arg_kw_sep1(&self, a: i32, b: i32, c: i32) -> i32 { a + b + c } #[pyo3(signature = (a, *, b = 2, c = 3))] fn get_pos_arg_kw_sep2(&self, a: i32, b: i32, c: i32) -> i32 { a + b + c } #[pyo3(signature = (a, **kwargs))] fn get_pos_kw(&self, py: Python<'_>, a: i32, kwargs: Option<&Bound<'_, PyDict>>) -> PyObject { [a.to_object(py), kwargs.to_object(py)].to_object(py) } // "args" can be anything that can be extracted from PyTuple #[pyo3(signature = (*args))] fn args_as_vec(&self, args: Vec) -> i32 { args.iter().sum() } } #[test] fn meth_signature() { Python::with_gil(|py| { let inst = Py::new(py, MethSignature {}).unwrap(); py_run!(py, inst, "assert inst.get_optional() == 10"); py_run!(py, inst, "assert inst.get_optional(100) == 100"); py_run!(py, inst, "assert inst.get_optional2() == None"); py_run!(py, inst, "assert inst.get_optional2(100) == 100"); py_run!( py, inst, "assert inst.get_optional_positional(1, 2, 3) == 2" ); py_run!(py, inst, "assert inst.get_optional_positional(1) == None"); py_run!(py, inst, "assert inst.get_default() == 10"); py_run!(py, inst, "assert inst.get_default(100) == 100"); py_run!(py, inst, "assert inst.get_kwarg() == 10"); py_expect_exception!(py, inst, "inst.get_kwarg(100)", PyTypeError); py_run!(py, inst, "assert inst.get_kwarg(test=100) == 100"); py_run!(py, inst, "assert inst.get_kwargs() == [(), None]"); py_run!(py, inst, "assert inst.get_kwargs(1,2,3) == [(1,2,3), None]"); py_run!( py, inst, "assert inst.get_kwargs(t=1,n=2) == [(), {'t': 1, 'n': 2}]" ); py_run!( py, inst, "assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]" ); py_run!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]"); py_run!( py, inst, "assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]" ); py_run!( py, inst, "assert inst.get_pos_arg_kw(1, b=2) == [1, (), {'b': 2}]" ); py_run!(py, inst, "assert inst.get_pos_arg_kw(a=1) == [1, (), None]"); py_expect_exception!(py, inst, "inst.get_pos_arg_kw()", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(1, a=1)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_arg_kw(b=2)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_only(10, 11) == 21"); py_expect_exception!(py, inst, "inst.get_pos_only(10, b = 11)", PyTypeError); py_expect_exception!(py, inst, "inst.get_pos_only(a = 10, b = 11)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_only_and_pos(10, 11) == 21"); py_run!( py, inst, "assert inst.get_pos_only_and_pos(10, b = 11) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_pos(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26" ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26" ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21" ); py_run!( py, inst, "assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_pos_and_kw(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_and_kw_only(10, b = 11) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only(10, 11)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_and_kw_only_with_default(10) == 13" ); py_run!( py, inst, "assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21" ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only_with_default(10, 11)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_pos_only_and_kw_only_with_default(a = 10, b = 11)", PyTypeError ); py_run!( py, inst, "assert inst.get_all_arg_types_together(10, 10, c = 10) == 35" ); py_run!( py, inst, "assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40" ); py_run!( py, inst, "assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40" ); py_expect_exception!( py, inst, "inst.get_all_arg_types_together(10, 10, 10)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_all_arg_types_together(a = 10, b = 10, c = 10)", PyTypeError ); py_run!(py, inst, "assert inst.get_pos_only_with_varargs(10) == 10"); py_run!( py, inst, "assert inst.get_pos_only_with_varargs(10, 10) == 20" ); py_run!( py, inst, "assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50" ); py_expect_exception!( py, inst, "inst.get_pos_only_with_varargs(a = 10)", PyTypeError ); py_run!( py, inst, "assert inst.get_pos_only_with_kwargs(10) == [10, None]" ); py_run!( py, inst, "assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]" ); py_run!( py, inst, "assert inst.get_pos_only_with_kwargs(10, b = 10, c = 10, d = 10, e = 10) == [10, {'b': 10, 'c': 10, 'd': 10, 'e': 10}]" ); py_expect_exception!( py, inst, "inst.get_pos_only_with_kwargs(a = 10)", PyTypeError ); py_expect_exception!( py, inst, "inst.get_pos_only_with_kwargs(a = 10, b = 10)", PyTypeError ); py_run!( py, inst, "assert inst.get_optional_pos_only_with_kwargs() == [0, None]" ); py_run!( py, inst, "assert inst.get_optional_pos_only_with_kwargs(10) == [10, None]" ); py_run!( py, inst, "assert inst.get_optional_pos_only_with_kwargs(a=10) == [0, {'a': 10}]" ); py_run!(py, inst, "assert inst.get_kwargs_only_with_defaults() == 5"); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(a = 8) == 11" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(b = 8) == 10" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_defaults(b = 1, a = 1) == 2" ); py_run!(py, inst, "assert inst.get_kwargs_only(a = 1, b = 1) == 2"); py_run!(py, inst, "assert inst.get_kwargs_only(b = 1, a = 1) == 2"); py_run!( py, inst, "assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_some_default(b = 1) == 2" ); py_run!( py, inst, "assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3" ); py_expect_exception!( py, inst, "inst.get_kwargs_only_with_some_default()", PyTypeError ); py_run!( py, inst, "assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)" ); py_run!( py, inst, "assert inst.get_args_and_required_keyword(a=1) == ((), 1)" ); py_expect_exception!( py, inst, "inst.get_args_and_required_keyword()", PyTypeError ); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1) == 6"); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2) == 6"); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(1, 2, c=13) == 16" ); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16" ); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16" ); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep1(c=13, b=2, a=1) == 16" ); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep1(1, 2, 3)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_arg_kw_sep2(1) == 6"); py_run!( py, inst, "assert inst.get_pos_arg_kw_sep2(1, b=12, c=13) == 26" ); py_expect_exception!(py, inst, "inst.get_pos_arg_kw_sep2(1, 2)", PyTypeError); py_run!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]"); py_expect_exception!(py, inst, "inst.get_pos_kw(1,2)", PyTypeError); py_run!(py, inst, "assert inst.args_as_vec(1,2,3) == 6"); }); } #[pyclass] /// A class with "documentation". struct MethDocs { x: i32, } #[pymethods] impl MethDocs { /// A method with "documentation" as well. fn method(&self) -> i32 { 0 } #[getter] /// `int`: a very "important" member of 'this' instance. fn get_x(&self) -> i32 { self.x } } #[test] fn meth_doc() { Python::with_gil(|py| { let d = [("C", py.get_type_bound::())].into_py_dict_bound(py); py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'"); py_assert!( py, *d, "C.method.__doc__ == 'A method with \"documentation\" as well.'" ); py_assert!( py, *d, "C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'" ); }); } #[pyclass] struct MethodWithLifeTime {} #[pymethods] impl MethodWithLifeTime { fn set_to_list<'py>(&self, set: &Bound<'py, PySet>) -> PyResult> { let py = set.py(); let mut items = vec![]; for _ in 0..set.len() { items.push(set.pop().unwrap()); } let list = PyList::new_bound(py, items); list.sort()?; Ok(list) } } #[test] fn method_with_lifetime() { Python::with_gil(|py| { let obj = Py::new(py, MethodWithLifeTime {}).unwrap(); py_run!( py, obj, "assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]" ); }); } #[pyclass] struct MethodWithPyClassArg { #[pyo3(get)] value: i64, } #[pymethods] impl MethodWithPyClassArg { fn add(&self, other: &MethodWithPyClassArg) -> MethodWithPyClassArg { MethodWithPyClassArg { value: self.value + other.value, } } fn add_pyref(&self, other: PyRef<'_, MethodWithPyClassArg>) -> MethodWithPyClassArg { MethodWithPyClassArg { value: self.value + other.value, } } fn inplace_add(&self, other: &mut MethodWithPyClassArg) { other.value += self.value; } fn inplace_add_pyref(&self, mut other: PyRefMut<'_, MethodWithPyClassArg>) { other.value += self.value; } #[pyo3(signature=(other = None))] fn optional_add(&self, other: Option<&MethodWithPyClassArg>) -> MethodWithPyClassArg { MethodWithPyClassArg { value: self.value + other.map(|o| o.value).unwrap_or(10), } } #[pyo3(signature=(other = None))] fn optional_inplace_add(&self, other: Option<&mut MethodWithPyClassArg>) { if let Some(other) = other { other.value += self.value; } } } #[test] fn method_with_pyclassarg() { Python::with_gil(|py| { let obj1 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); let obj2 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap(); let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict_bound(py); py_run!(py, *d, "obj = obj1.add(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.add_pyref(obj2); assert obj.value == 20"); py_run!(py, *d, "obj = obj1.optional_add(); assert obj.value == 20"); py_run!( py, *d, "obj = obj1.optional_add(obj2); assert obj.value == 20" ); py_run!(py, *d, "obj1.inplace_add(obj2); assert obj.value == 20"); py_run!( py, *d, "obj1.inplace_add_pyref(obj2); assert obj2.value == 30" ); py_run!( py, *d, "obj1.optional_inplace_add(); assert obj2.value == 30" ); py_run!( py, *d, "obj1.optional_inplace_add(obj2); assert obj2.value == 40" ); }); } #[pyclass] #[cfg(unix)] struct CfgStruct {} #[pyclass] #[cfg(not(unix))] struct CfgStruct {} #[pymethods] #[cfg(unix)] impl CfgStruct { fn unix_method(&self) -> &str { "unix" } #[cfg(not(unix))] fn never_compiled_method(&self) {} } #[pymethods] #[cfg(not(unix))] impl CfgStruct { fn not_unix_method(&self) -> &str { "not unix" } #[cfg(unix)] fn never_compiled_method(&self) {} } #[test] fn test_cfg_attrs() { Python::with_gil(|py| { let inst = Py::new(py, CfgStruct {}).unwrap(); #[cfg(unix)] { py_assert!(py, inst, "inst.unix_method() == 'unix'"); py_assert!(py, inst, "not hasattr(inst, 'not_unix_method')"); } #[cfg(not(unix))] { py_assert!(py, inst, "not hasattr(inst, 'unix_method')"); py_assert!(py, inst, "inst.not_unix_method() == 'not unix'"); } py_assert!(py, inst, "not hasattr(inst, 'never_compiled_method')"); }); } #[pyclass] #[derive(Default)] struct FromSequence { #[pyo3(get)] numbers: Vec, } #[pymethods] impl FromSequence { #[new] #[pyo3(signature=(seq = None))] fn new(seq: Option<&Bound<'_, PySequence>>) -> PyResult { if let Some(seq) = seq { Ok(FromSequence { numbers: seq.as_ref().extract::>()?, }) } else { Ok(FromSequence::default()) } } } #[test] fn test_from_sequence() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); py_assert!(py, typeobj, "typeobj(range(0, 4)).numbers == [0, 1, 2, 3]"); }); } #[pyclass] struct r#RawIdents { #[pyo3(get, set)] r#type: PyObject, r#subtype: PyObject, r#subsubtype: PyObject, } #[pymethods] impl r#RawIdents { #[new] pub fn r#new( r#_py: Python<'_>, r#type: PyObject, r#subtype: PyObject, r#subsubtype: PyObject, ) -> Self { Self { r#type, r#subtype, r#subsubtype, } } #[getter(r#subtype)] pub fn r#get_subtype(&self, py: Python<'_>) -> PyObject { self.r#subtype.clone_ref(py) } #[setter(r#subtype)] pub fn r#set_subtype(&mut self, r#subtype: PyObject) { self.r#subtype = r#subtype; } #[getter] pub fn r#get_subsubtype(&self, py: Python<'_>) -> PyObject { self.r#subsubtype.clone_ref(py) } #[setter] pub fn r#set_subsubtype(&mut self, r#subsubtype: PyObject) { self.r#subsubtype = r#subsubtype; } pub fn r#__call__(&mut self, r#type: PyObject) { self.r#type = r#type; } #[staticmethod] pub fn r#static_method(r#type: PyObject) -> PyObject { r#type } #[classmethod] pub fn r#class_method(_: &Bound<'_, PyType>, r#type: PyObject) -> PyObject { r#type } #[classattr] pub fn r#class_attr_fn() -> i32 { 5 } #[classattr] const r#CLASS_ATTR_CONST: i32 = 6; #[pyo3(signature = (r#struct = "foo"))] fn method_with_keyword<'a>(&self, r#struct: &'a str) -> &'a str { r#struct } } #[test] fn test_raw_idents() { Python::with_gil(|py| { let raw_idents_type = py.get_type_bound::(); assert_eq!(raw_idents_type.qualname().unwrap(), "RawIdents"); py_run!( py, raw_idents_type, r#" instance = raw_idents_type(type=None, subtype=5, subsubtype="foo") assert instance.type is None assert instance.subtype == 5 assert instance.subsubtype == "foo" instance.type = 1 instance.subtype = 2 instance.subsubtype = 3 assert instance.type == 1 assert instance.subtype == 2 assert instance.subsubtype == 3 assert raw_idents_type.static_method(type=30) == 30 assert instance.class_method(type=40) == 40 instance(type=50) assert instance.type == 50 assert raw_idents_type.class_attr_fn == 5 assert raw_idents_type.CLASS_ATTR_CONST == 6 assert instance.method_with_keyword() == "foo" assert instance.method_with_keyword("bar") == "bar" assert instance.method_with_keyword(struct="baz") == "baz" "# ); }) } // Regression test for issue 1505 - Python argument not detected correctly when inside a macro. #[pyclass] struct Issue1505 {} macro_rules! pymethods { ( #[pymethods] impl $ty: ty { fn $fn:ident (&self, $arg:ident : $arg_ty:ty) {} } ) => { #[pymethods] impl $ty { fn $fn(&self, $arg: $arg_ty) {} } }; } pymethods!( #[pymethods] impl Issue1505 { fn issue_1505(&self, _py: Python<'_>) {} } ); // Regression test for issue 1506 - incorrect macro hygiene. // By applying the `#[pymethods]` attribute inside a macro_rules! macro, this separates the macro // call scope from the scope of the impl block. For this to work our macros must be careful to not // cheat hygiene! #[pyclass] struct Issue1506 {} macro_rules! issue_1506 { (#[pymethods] $($body:tt)*) => { #[pymethods] $($body)* }; } issue_1506!( #[pymethods] impl Issue1506 { #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506( &self, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_mut( &mut self, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_custom_receiver( _slf: Py, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_custom_receiver_explicit( _slf: Py, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[new] #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_new( _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) -> Self { Issue1506 {} } #[getter("foo")] fn issue_1506_getter(&self, _py: Python<'_>) -> i32 { 5 } #[setter("foo")] fn issue_1506_setter(&self, _py: Python<'_>, _value: i32) {} #[staticmethod] #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_static( _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } #[classmethod] #[pyo3(signature = (_arg, _args, _kwargs=None))] fn issue_1506_class( _cls: &Bound<'_, PyType>, _py: Python<'_>, _arg: &Bound<'_, PyAny>, _args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>, ) { } } ); #[pyclass] struct Issue1696 {} pymethods!( #[pymethods] impl Issue1696 { fn issue_1696(&self, _x: &InstanceMethod) {} } ); #[test] fn test_option_pyclass_arg() { // Option<&PyClass> argument with a default set in a signature regressed to a compile // error in PyO3 0.17.0 - this test it continues to be accepted. #[pyclass] struct SomePyClass {} #[pyfunction(signature = (arg=None))] fn option_class_arg(arg: Option<&SomePyClass>) -> Option { arg.map(|_| SomePyClass {}) } Python::with_gil(|py| { let f = wrap_pyfunction_bound!(option_class_arg, py).unwrap(); assert!(f.call0().unwrap().is_none()); let obj = Py::new(py, SomePyClass {}).unwrap(); assert!(f .call1((obj,)) .unwrap() .extract::>() .is_ok()); }) } #[test] fn test_issue_2988() { #[pyfunction] #[pyo3(signature = ( _data = vec![], _data2 = vec![], ))] pub fn _foo( _data: Vec, // The from_py_with here looks a little odd, we just need some way // to encourage the macro to expand the from_py_with default path too #[pyo3(from_py_with = " as PyAnyMethods>::extract")] _data2: Vec, ) { } } pyo3/tests/test_buffer_protocol.rs0000644000175000017500000001160714661133735020401 0ustar jamespagejamespage#![cfg(feature = "macros")] #![cfg(any(not(Py_LIMITED_API), Py_3_11))] use pyo3::buffer::PyBuffer; use pyo3::exceptions::PyBufferError; use pyo3::ffi; use pyo3::prelude::*; use pyo3::types::IntoPyDict; use std::ffi::CString; use std::os::raw::{c_int, c_void}; use std::ptr; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct TestBufferClass { vec: Vec, drop_called: Arc, } #[pymethods] impl TestBufferClass { unsafe fn __getbuffer__( slf: Bound<'_, Self>, view: *mut ffi::Py_buffer, flags: c_int, ) -> PyResult<()> { fill_view_from_readonly_data(view, flags, &slf.borrow().vec, slf.into_any()) } unsafe fn __releasebuffer__(&self, view: *mut ffi::Py_buffer) { // Release memory held by the format string drop(CString::from_raw((*view).format)); } } impl Drop for TestBufferClass { fn drop(&mut self) { print!("dropped"); self.drop_called.store(true, Ordering::Relaxed); } } #[test] fn test_buffer() { let drop_called = Arc::new(AtomicBool::new(false)); Python::with_gil(|py| { let instance = Py::new( py, TestBufferClass { vec: vec![b' ', b'2', b'3'], drop_called: drop_called.clone(), }, ) .unwrap(); let env = [("ob", instance)].into_py_dict_bound(py); py_assert!(py, *env, "bytes(ob) == b' 23'"); }); assert!(drop_called.load(Ordering::Relaxed)); } #[test] fn test_buffer_referenced() { let drop_called = Arc::new(AtomicBool::new(false)); let buf = { let input = vec![b' ', b'2', b'3']; Python::with_gil(|py| { let instance: PyObject = TestBufferClass { vec: input.clone(), drop_called: drop_called.clone(), } .into_py(py); let buf = PyBuffer::::get_bound(instance.bind(py)).unwrap(); assert_eq!(buf.to_vec(py).unwrap(), input); drop(instance); buf }) }; assert!(!drop_called.load(Ordering::Relaxed)); Python::with_gil(|_| { drop(buf); }); assert!(drop_called.load(Ordering::Relaxed)); } #[test] #[cfg(Py_3_8)] // sys.unraisablehook not available until Python 3.8 fn test_releasebuffer_unraisable_error() { use common::UnraisableCapture; use pyo3::exceptions::PyValueError; #[pyclass] struct ReleaseBufferError {} #[pymethods] impl ReleaseBufferError { unsafe fn __getbuffer__( slf: Bound<'_, Self>, view: *mut ffi::Py_buffer, flags: c_int, ) -> PyResult<()> { static BUF_BYTES: &[u8] = b"hello world"; fill_view_from_readonly_data(view, flags, BUF_BYTES, slf.into_any()) } unsafe fn __releasebuffer__(&self, _view: *mut ffi::Py_buffer) -> PyResult<()> { Err(PyValueError::new_err("oh dear")) } } Python::with_gil(|py| { let capture = UnraisableCapture::install(py); let instance = Py::new(py, ReleaseBufferError {}).unwrap(); let env = [("ob", instance.clone_ref(py))].into_py_dict_bound(py); assert!(capture.borrow(py).capture.is_none()); py_assert!(py, *env, "bytes(ob) == b'hello world'"); let (err, object) = capture.borrow_mut(py).capture.take().unwrap(); assert_eq!(err.to_string(), "ValueError: oh dear"); assert!(object.is(&instance)); capture.borrow_mut(py).uninstall(py); }); } /// # Safety /// /// `view` must be a valid pointer to ffi::Py_buffer, or null /// `data` must outlive the Python lifetime of `owner` (i.e. data must be owned by owner, or data /// must be static data) unsafe fn fill_view_from_readonly_data( view: *mut ffi::Py_buffer, flags: c_int, data: &[u8], owner: Bound<'_, PyAny>, ) -> PyResult<()> { if view.is_null() { return Err(PyBufferError::new_err("View is null")); } if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE { return Err(PyBufferError::new_err("Object is not writable")); } (*view).obj = owner.into_ptr(); (*view).buf = data.as_ptr() as *mut c_void; (*view).len = data.len() as isize; (*view).readonly = 1; (*view).itemsize = 1; (*view).format = if (flags & ffi::PyBUF_FORMAT) == ffi::PyBUF_FORMAT { let msg = CString::new("B").unwrap(); msg.into_raw() } else { ptr::null_mut() }; (*view).ndim = 1; (*view).shape = if (flags & ffi::PyBUF_ND) == ffi::PyBUF_ND { &mut (*view).len } else { ptr::null_mut() }; (*view).strides = if (flags & ffi::PyBUF_STRIDES) == ffi::PyBUF_STRIDES { &mut (*view).itemsize } else { ptr::null_mut() }; (*view).suboffsets = ptr::null_mut(); (*view).internal = ptr::null_mut(); Ok(()) } pyo3/tests/test_datetime.rs0000644000175000017500000001456414661133735017010 0ustar jamespagejamespage#![cfg(not(Py_LIMITED_API))] use pyo3::prelude::*; use pyo3::types::{timezone_utc_bound, IntoPyDict, PyDate, PyDateTime, PyTime}; use pyo3_ffi::PyDateTime_IMPORT; fn _get_subclasses<'py>( py: Python<'py>, py_type: &str, args: &str, ) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>, Bound<'py, PyAny>)> { // Import the class from Python and create some subclasses let datetime = py.import_bound("datetime")?; let locals = [(py_type, datetime.getattr(py_type)?)].into_py_dict_bound(py); let make_subclass_py = format!("class Subklass({}):\n pass", py_type); let make_sub_subclass_py = "class SubSubklass(Subklass):\n pass"; py.run_bound(&make_subclass_py, None, Some(&locals))?; py.run_bound(make_sub_subclass_py, None, Some(&locals))?; // Construct an instance of the base class let obj = py.eval_bound(&format!("{}({})", py_type, args), None, Some(&locals))?; // Construct an instance of the subclass let sub_obj = py.eval_bound(&format!("Subklass({})", args), None, Some(&locals))?; // Construct an instance of the sub-subclass let sub_sub_obj = py.eval_bound(&format!("SubSubklass({})", args), None, Some(&locals))?; Ok((obj, sub_obj, sub_sub_obj)) } macro_rules! assert_check_exact { ($check_func:ident, $check_func_exact:ident, $obj: expr) => { unsafe { use pyo3::ffi::*; assert!($check_func(($obj).as_ptr()) != 0); assert!($check_func_exact(($obj).as_ptr()) != 0); } }; } macro_rules! assert_check_only { ($check_func:ident, $check_func_exact:ident, $obj: expr) => { unsafe { use pyo3::ffi::*; assert!($check_func(($obj).as_ptr()) != 0); assert!($check_func_exact(($obj).as_ptr()) == 0); } }; } #[test] fn test_date_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "date", "2018, 1, 1").unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_exact!(PyDate_Check, PyDate_CheckExact, obj); assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_obj); assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj); assert!(obj.is_instance_of::()); assert!(!obj.is_instance_of::()); assert!(!obj.is_instance_of::()); }); } #[test] fn test_time_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "time", "12, 30, 15").unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_exact!(PyTime_Check, PyTime_CheckExact, obj); assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_obj); assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj); assert!(!obj.is_instance_of::()); assert!(obj.is_instance_of::()); assert!(!obj.is_instance_of::()); }); } #[test] fn test_datetime_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "datetime", "2018, 1, 1, 13, 30, 15") .map_err(|e| e.display(py)) .unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_only!(PyDate_Check, PyDate_CheckExact, obj); assert_check_exact!(PyDateTime_Check, PyDateTime_CheckExact, obj); assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_obj); assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_sub_obj); assert!(obj.is_instance_of::()); assert!(!obj.is_instance_of::()); assert!(obj.is_instance_of::()); }); } #[test] fn test_delta_check() { Python::with_gil(|py| { let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, "timedelta", "1, -3").unwrap(); unsafe { PyDateTime_IMPORT() } assert_check_exact!(PyDelta_Check, PyDelta_CheckExact, obj); assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_obj); assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj); }); } #[test] fn test_datetime_utc() { use assert_approx_eq::assert_approx_eq; use pyo3::types::PyDateTime; Python::with_gil(|py| { let utc = timezone_utc_bound(py); let dt = PyDateTime::new_bound(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap(); let locals = [("dt", dt)].into_py_dict_bound(py); let offset: f32 = py .eval_bound("dt.utcoffset().total_seconds()", None, Some(&locals)) .unwrap() .extract() .unwrap(); assert_approx_eq!(offset, 0f32); }); } static INVALID_DATES: &[(i32, u8, u8)] = &[ (-1, 1, 1), (0, 1, 1), (10000, 1, 1), (2 << 30, 1, 1), (2018, 0, 1), (2018, 13, 1), (2018, 1, 0), (2017, 2, 29), (2018, 1, 32), ]; static INVALID_TIMES: &[(u8, u8, u8, u32)] = &[(25, 0, 0, 0), (255, 0, 0, 0), (0, 60, 0, 0), (0, 0, 61, 0)]; #[test] fn test_pydate_out_of_bounds() { use pyo3::types::PyDate; Python::with_gil(|py| { for val in INVALID_DATES { let (year, month, day) = val; let dt = PyDate::new_bound(py, *year, *month, *day); dt.unwrap_err(); } }); } #[test] fn test_pytime_out_of_bounds() { use pyo3::types::PyTime; Python::with_gil(|py| { for val in INVALID_TIMES { let (hour, minute, second, microsecond) = val; let dt = PyTime::new_bound(py, *hour, *minute, *second, *microsecond, None); dt.unwrap_err(); } }); } #[test] fn test_pydatetime_out_of_bounds() { use pyo3::types::PyDateTime; use std::iter; Python::with_gil(|py| { let valid_time = (0, 0, 0, 0); let valid_date = (2018, 1, 1); let invalid_dates = INVALID_DATES.iter().zip(iter::repeat(&valid_time)); let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.iter()); let vals = invalid_dates.chain(invalid_times); for val in vals { let (date, time) = val; let (year, month, day) = date; let (hour, minute, second, microsecond) = time; let dt = PyDateTime::new_bound( py, *year, *month, *day, *hour, *minute, *second, *microsecond, None, ); dt.unwrap_err(); } }); } pyo3/tests/test_class_comparisons.rs0000644000175000017500000002046014661133735020726 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; #[path = "../src/tests/common.rs"] mod common; #[pyclass(eq)] #[derive(Debug, Clone, PartialEq)] pub enum MyEnum { Variant, OtherVariant, } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub enum MyEnumOrd { Variant, OtherVariant, } #[test] fn test_enum_eq_enum() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); let var2 = Py::new(py, MyEnum::Variant).unwrap(); let other_var = Py::new(py, MyEnum::OtherVariant).unwrap(); py_assert!(py, var1 var2, "var1 == var2"); py_assert!(py, var1 other_var, "var1 != other_var"); py_assert!(py, var1 var2, "(var1 != var2) == False"); }) } #[test] fn test_enum_eq_incomparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); py_assert!(py, var1, "(var1 == 'foo') == False"); py_assert!(py, var1, "(var1 != 'foo') == True"); }) } #[test] fn test_enum_ord_comparable_opt_in_only() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnum::Variant).unwrap(); let var2 = Py::new(py, MyEnum::OtherVariant).unwrap(); // ordering on simple enums if opt in only, thus raising an error below py_expect_exception!(py, var1 var2, "(var1 > var2) == False", PyTypeError); }) } #[test] fn test_simple_enum_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyEnumOrd::Variant).unwrap(); let var2 = Py::new(py, MyEnumOrd::OtherVariant).unwrap(); let var3 = Py::new(py, MyEnumOrd::OtherVariant).unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == False"); py_assert!(py, var1 var2, "(var1 < var2) == True"); py_assert!(py, var1 var2, "(var1 >= var2) == False"); py_assert!(py, var2 var3, "(var3 >= var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub enum MyComplexEnumOrd { Variant(i32), OtherVariant(String), } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub enum MyComplexEnumOrd2 { Variant { msg: String, idx: u32 }, OtherVariant { name: String, idx: u32 }, } #[test] fn test_complex_enum_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new(py, MyComplexEnumOrd::Variant(-2)).unwrap(); let var2 = Py::new(py, MyComplexEnumOrd::Variant(5)).unwrap(); let var3 = Py::new(py, MyComplexEnumOrd::OtherVariant("a".to_string())).unwrap(); let var4 = Py::new(py, MyComplexEnumOrd::OtherVariant("b".to_string())).unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == False"); py_assert!(py, var1 var2, "(var1 < var2) == True"); py_assert!(py, var1 var2, "(var1 >= var2) == False"); py_assert!(py, var1 var2, "(var1 <= var2) == True"); py_assert!(py, var1 var3, "(var1 >= var3) == False"); py_assert!(py, var1 var3, "(var1 <= var3) == True"); py_assert!(py, var3 var4, "(var3 >= var4) == False"); py_assert!(py, var3 var4, "(var3 <= var4) == True"); let var5 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "hello".to_string(), idx: 1, }, ) .unwrap(); let var6 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "hello".to_string(), idx: 1, }, ) .unwrap(); let var7 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "goodbye".to_string(), idx: 7, }, ) .unwrap(); let var8 = Py::new( py, MyComplexEnumOrd2::Variant { msg: "about".to_string(), idx: 0, }, ) .unwrap(); let var9 = Py::new( py, MyComplexEnumOrd2::OtherVariant { name: "albert".to_string(), idx: 1, }, ) .unwrap(); py_assert!(py, var5 var6, "(var5 == var6) == True"); py_assert!(py, var5 var6, "(var5 <= var6) == True"); py_assert!(py, var6 var7, "(var6 <= var7) == False"); py_assert!(py, var6 var7, "(var6 >= var7) == True"); py_assert!(py, var5 var8, "(var5 > var8) == True"); py_assert!(py, var8 var9, "(var9 > var8) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub struct Point { x: i32, y: i32, z: i32, } #[test] fn test_struct_numeric_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new(py, Point { x: 10, y: 2, z: 3 }).unwrap(); let var2 = Py::new(py, Point { x: 2, y: 2, z: 3 }).unwrap(); let var3 = Py::new(py, Point { x: 1, y: 22, z: 4 }).unwrap(); let var4 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap(); let var5 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == False"); py_assert!(py, var2 var3, "(var3 < var2) == True"); py_assert!(py, var3 var4, "(var3 > var4) == True"); py_assert!(py, var4 var5, "(var4 == var5) == True"); py_assert!(py, var3 var5, "(var3 != var5) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone, PartialOrd)] pub struct Person { surname: String, given_name: String, } #[test] fn test_struct_string_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new( py, Person { surname: "zzz".to_string(), given_name: "bob".to_string(), }, ) .unwrap(); let var2 = Py::new( py, Person { surname: "aaa".to_string(), given_name: "sally".to_string(), }, ) .unwrap(); let var3 = Py::new( py, Person { surname: "eee".to_string(), given_name: "qqq".to_string(), }, ) .unwrap(); let var4 = Py::new( py, Person { surname: "ddd".to_string(), given_name: "aaa".to_string(), }, ) .unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == False"); py_assert!(py, var1 var3, "(var1 >= var3) == True"); py_assert!(py, var2 var3, "(var2 >= var3) == False"); py_assert!(py, var3 var4, "(var3 >= var4) == True"); py_assert!(py, var3 var4, "(var3 != var4) == True"); }) } #[pyclass(eq, ord)] #[derive(Debug, PartialEq, Eq, Clone)] pub struct Record { name: String, title: String, idx: u32, } impl PartialOrd for Record { fn partial_cmp(&self, other: &Self) -> Option { Some(self.idx.partial_cmp(&other.idx).unwrap()) } } #[test] fn test_struct_custom_ord_comparable() { Python::with_gil(|py| { let var1 = Py::new( py, Record { name: "zzz".to_string(), title: "bbb".to_string(), idx: 9, }, ) .unwrap(); let var2 = Py::new( py, Record { name: "ddd".to_string(), title: "aaa".to_string(), idx: 1, }, ) .unwrap(); let var3 = Py::new( py, Record { name: "vvv".to_string(), title: "ggg".to_string(), idx: 19, }, ) .unwrap(); let var4 = Py::new( py, Record { name: "vvv".to_string(), title: "ggg".to_string(), idx: 19, }, ) .unwrap(); py_assert!(py, var1 var2, "(var1 > var2) == True"); py_assert!(py, var1 var2, "(var1 <= var2) == False"); py_assert!(py, var1 var3, "(var1 >= var3) == False"); py_assert!(py, var2 var3, "(var2 >= var3) == False"); py_assert!(py, var3 var4, "(var3 == var4) == True"); py_assert!(py, var2 var4, "(var2 != var4) == True"); }) } pyo3/tests/test_wrap_pyfunction_deduction.rs0000644000175000017500000000123514661133735022470 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::{prelude::*, types::PyCFunction}; #[pyfunction] fn f() {} #[cfg(feature = "gil-refs")] pub fn add_wrapped(wrapper: &impl Fn(Python<'_>) -> PyResult<&PyCFunction>) { let _ = wrapper; } #[test] fn wrap_pyfunction_deduction() { #[allow(deprecated)] #[cfg(feature = "gil-refs")] add_wrapped(wrap_pyfunction!(f)); #[cfg(not(feature = "gil-refs"))] add_wrapped_bound(wrap_pyfunction!(f)); } pub fn add_wrapped_bound(wrapper: &impl Fn(Python<'_>) -> PyResult>) { let _ = wrapper; } #[test] fn wrap_pyfunction_deduction_bound() { add_wrapped_bound(wrap_pyfunction_bound!(f)); } pyo3/tests/test_inheritance.rs0000644000175000017500000002126314661133735017477 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::IntoPyDict; #[path = "../src/tests/common.rs"] mod common; #[pyclass(subclass)] struct BaseClass { #[pyo3(get)] val1: usize, } #[pyclass(subclass)] struct SubclassAble {} #[test] fn subclass() { Python::with_gil(|py| { let d = [("SubclassAble", py.get_type_bound::())].into_py_dict_bound(py); py.run_bound( "class A(SubclassAble): pass\nassert issubclass(A, SubclassAble)", None, Some(&d), ) .map_err(|e| e.display(py)) .unwrap(); }); } #[pymethods] impl BaseClass { #[new] fn new() -> Self { BaseClass { val1: 10 } } fn base_method(&self, x: usize) -> usize { x * self.val1 } fn base_set(&mut self, fn_: &Bound<'_, PyAny>) -> PyResult<()> { let value: usize = fn_.call0()?.extract()?; self.val1 = value; Ok(()) } } #[pyclass(extends=BaseClass)] struct SubClass { #[pyo3(get)] val2: usize, } #[pymethods] impl SubClass { #[new] fn new() -> (Self, BaseClass) { (SubClass { val2: 5 }, BaseClass { val1: 10 }) } fn sub_method(&self, x: usize) -> usize { x * self.val2 } fn sub_set_and_ret(&mut self, x: usize) -> usize { self.val2 = x; x } } #[test] fn inheritance_with_new_methods() { Python::with_gil(|py| { let typeobj = py.get_type_bound::(); let inst = typeobj.call((), None).unwrap(); py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5"); }); } #[test] fn call_base_and_sub_methods() { Python::with_gil(|py| { let obj = Py::new(py, SubClass::new()).unwrap(); py_run!( py, obj, r#" assert obj.base_method(10) == 100 assert obj.sub_method(10) == 50 "# ); }); } #[test] fn mutation_fails() { Python::with_gil(|py| { let obj = Py::new(py, SubClass::new()).unwrap(); let global = [("obj", obj)].into_py_dict_bound(py); let e = py .run_bound( "obj.base_set(lambda: obj.sub_set_and_ret(1))", Some(&global), None, ) .unwrap_err(); assert_eq!(&e.to_string(), "RuntimeError: Already borrowed"); }); } #[test] fn is_subclass_and_is_instance() { Python::with_gil(|py| { let sub_ty = py.get_type_bound::(); let base_ty = py.get_type_bound::(); assert!(sub_ty.is_subclass_of::().unwrap()); assert!(sub_ty.is_subclass(&base_ty).unwrap()); let obj = Bound::new(py, SubClass::new()).unwrap().into_any(); assert!(obj.is_instance_of::()); assert!(obj.is_instance_of::()); assert!(obj.is_instance(&sub_ty).unwrap()); assert!(obj.is_instance(&base_ty).unwrap()); }); } #[pyclass(subclass)] struct BaseClassWithResult { _val: usize, } #[pymethods] impl BaseClassWithResult { #[new] fn new(value: isize) -> PyResult { Ok(Self { _val: std::convert::TryFrom::try_from(value)?, }) } } #[pyclass(extends=BaseClassWithResult)] struct SubClass2 {} #[pymethods] impl SubClass2 { #[new] fn new(value: isize) -> PyResult<(Self, BaseClassWithResult)> { let base = BaseClassWithResult::new(value)?; Ok((Self {}, base)) } } #[test] fn handle_result_in_new() { Python::with_gil(|py| { let subclass = py.get_type_bound::(); py_run!( py, subclass, r#" try: subclass(-10) assert Fals except ValueError as e: pass except Exception as e: raise e "# ); }); } // Subclassing builtin types is not allowed in the LIMITED API. #[cfg(not(Py_LIMITED_API))] mod inheriting_native_type { use super::*; use pyo3::exceptions::PyException; use pyo3::types::PyDict; #[cfg(not(PyPy))] #[test] fn inherit_set() { use pyo3::types::PySet; #[cfg(not(PyPy))] #[pyclass(extends=PySet)] #[derive(Debug)] struct SetWithName { #[pyo3(get, name = "name")] _name: &'static str, } #[cfg(not(PyPy))] #[pymethods] impl SetWithName { #[new] fn new() -> Self { SetWithName { _name: "Hello :)" } } } Python::with_gil(|py| { let set_sub = pyo3::Py::new(py, SetWithName::new()).unwrap(); py_run!( py, set_sub, r#"set_sub.add(10); assert list(set_sub) == [10]; assert set_sub.name == "Hello :)""# ); }); } #[pyclass(extends=PyDict)] #[derive(Debug)] struct DictWithName { #[pyo3(get, name = "name")] _name: &'static str, } #[pymethods] impl DictWithName { #[new] fn new() -> Self { DictWithName { _name: "Hello :)" } } } #[test] fn inherit_dict() { Python::with_gil(|py| { let dict_sub = pyo3::Py::new(py, DictWithName::new()).unwrap(); py_run!( py, dict_sub, r#"dict_sub[0] = 1; assert dict_sub[0] == 1; assert dict_sub.name == "Hello :)""# ); }); } #[test] fn inherit_dict_drop() { Python::with_gil(|py| { let dict_sub = pyo3::Py::new(py, DictWithName::new()).unwrap(); assert_eq!(dict_sub.get_refcnt(py), 1); let item = &py.eval_bound("object()", None, None).unwrap(); assert_eq!(item.get_refcnt(), 1); dict_sub.bind(py).set_item("foo", item).unwrap(); assert_eq!(item.get_refcnt(), 2); drop(dict_sub); assert_eq!(item.get_refcnt(), 1); }) } #[pyclass(extends=PyException)] struct CustomException { #[pyo3(get)] context: &'static str, } #[pymethods] impl CustomException { #[new] fn new(_exc_arg: &Bound<'_, PyAny>) -> Self { CustomException { context: "Hello :)", } } } #[test] fn custom_exception() { Python::with_gil(|py| { let cls = py.get_type_bound::(); let dict = [("cls", &cls)].into_py_dict_bound(py); let res = py.run_bound( "e = cls('hello'); assert str(e) == 'hello'; assert e.context == 'Hello :)'; raise e", None, Some(&dict) ); let err = res.unwrap_err(); assert!(err.matches(py, &cls), "{}", err); // catching the exception in Python also works: py_run!( py, cls, r#" try: raise cls("foo") except cls: pass "# ) }) } } #[pyclass(subclass)] struct SimpleClass {} #[pymethods] impl SimpleClass { #[new] fn new() -> Self { Self {} } } #[test] fn test_subclass_ref_counts() { // regression test for issue #1363 Python::with_gil(|py| { #[allow(non_snake_case)] let SimpleClass = py.get_type_bound::(); py_run!( py, SimpleClass, r#" import gc import sys class SubClass(SimpleClass): pass gc.collect() count = sys.getrefcount(SubClass) for i in range(1000): c = SubClass() del c gc.collect() after = sys.getrefcount(SubClass) # depending on Python's GC the count may be either identical or exactly 1000 higher, # both are expected values that are not representative of the issue. # # (With issue #1363 the count will be decreased.) assert after == count or (after == count + 1000), f"{after} vs {count}" "# ); }) } #[test] #[cfg(not(Py_LIMITED_API))] fn module_add_class_inherit_bool_fails() { use pyo3::types::PyBool; #[pyclass(extends = PyBool)] struct ExtendsBool; Python::with_gil(|py| { let m = PyModule::new_bound(py, "test_module").unwrap(); let err = m.add_class::().unwrap_err(); assert_eq!( err.to_string(), "RuntimeError: An error occurred while initializing class ExtendsBool" ); assert_eq!( err.cause(py).unwrap().to_string(), "TypeError: type 'bool' is not an acceptable base type" ); }) } pyo3/tests/test_buffer.rs0000644000175000017500000000755614661133735016470 0ustar jamespagejamespage#![cfg(feature = "macros")] #![cfg(any(not(Py_LIMITED_API), Py_3_11))] use pyo3::{buffer::PyBuffer, exceptions::PyBufferError, ffi, prelude::*}; use std::{ os::raw::{c_int, c_void}, ptr, }; #[macro_use] #[path = "../src/tests/common.rs"] mod common; enum TestGetBufferError { NullShape, NullStrides, IncorrectItemSize, IncorrectFormat, IncorrectAlignment, } #[pyclass] struct TestBufferErrors { buf: Vec, error: Option, } #[pymethods] impl TestBufferErrors { unsafe fn __getbuffer__( slf: PyRefMut<'_, Self>, view: *mut ffi::Py_buffer, flags: c_int, ) -> PyResult<()> { if view.is_null() { return Err(PyBufferError::new_err("View is null")); } if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE { return Err(PyBufferError::new_err("Object is not writable")); } let bytes = &slf.buf; (*view).buf = bytes.as_ptr() as *mut c_void; (*view).len = bytes.len() as isize; (*view).readonly = 1; (*view).itemsize = std::mem::size_of::() as isize; let msg = ffi::c_str!("I"); (*view).format = msg.as_ptr() as *mut _; (*view).ndim = 1; (*view).shape = &mut (*view).len; (*view).strides = &mut (*view).itemsize; (*view).suboffsets = ptr::null_mut(); (*view).internal = ptr::null_mut(); if let Some(err) = &slf.error { use TestGetBufferError::*; match err { NullShape => { (*view).shape = std::ptr::null_mut(); } NullStrides => { (*view).strides = std::ptr::null_mut(); } IncorrectItemSize => { (*view).itemsize += 1; } IncorrectFormat => { (*view).format = ffi::c_str!("B").as_ptr() as _; } IncorrectAlignment => (*view).buf = (*view).buf.add(1), } } (*view).obj = slf.into_ptr(); Ok(()) } } #[test] fn test_get_buffer_errors() { Python::with_gil(|py| { let instance = Py::new( py, TestBufferErrors { buf: vec![0, 1, 2, 3], error: None, }, ) .unwrap(); assert!(PyBuffer::::get_bound(instance.bind(py)).is_ok()); instance.borrow_mut(py).error = Some(TestGetBufferError::NullShape); assert_eq!( PyBuffer::::get_bound(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: shape is null" ); instance.borrow_mut(py).error = Some(TestGetBufferError::NullStrides); assert_eq!( PyBuffer::::get_bound(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: strides is null" ); instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectItemSize); assert_eq!( PyBuffer::::get_bound(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: buffer contents are not compatible with u32" ); instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectFormat); assert_eq!( PyBuffer::::get_bound(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: buffer contents are not compatible with u32" ); instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectAlignment); assert_eq!( PyBuffer::::get_bound(instance.bind(py)) .unwrap_err() .to_string(), "BufferError: buffer contents are insufficiently aligned for u32" ); }); } pyo3/tests/test_anyhow.rs0000644000175000017500000000220414661133735016505 0ustar jamespagejamespage#![cfg(feature = "anyhow")] use pyo3::wrap_pyfunction_bound; #[test] fn test_anyhow_py_function_ok_result() { use pyo3::{py_run, pyfunction, Python}; #[pyfunction] #[allow(clippy::unnecessary_wraps)] fn produce_ok_result() -> anyhow::Result { Ok(String::from("OK buddy")) } Python::with_gil(|py| { let func = wrap_pyfunction_bound!(produce_ok_result)(py).unwrap(); py_run!( py, func, r#" func() "# ); }); } #[test] fn test_anyhow_py_function_err_result() { use pyo3::prelude::PyDictMethods; use pyo3::{pyfunction, types::PyDict, Python}; #[pyfunction] fn produce_err_result() -> anyhow::Result { anyhow::bail!("error time") } Python::with_gil(|py| { let func = wrap_pyfunction_bound!(produce_err_result)(py).unwrap(); let locals = PyDict::new_bound(py); locals.set_item("func", func).unwrap(); py.run_bound( r#" func() "#, None, Some(&locals), ) .unwrap_err(); }); } pyo3/tests/test_class_conversion.rs0000644000175000017500000000717214661133735020563 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; #[macro_use] #[path = "../src/tests/common.rs"] mod common; #[pyclass] #[derive(Clone, Debug, PartialEq)] struct Cloneable { x: i32, } #[test] fn test_cloneable_pyclass() { let c = Cloneable { x: 10 }; Python::with_gil(|py| { let py_c = Py::new(py, c.clone()).unwrap().to_object(py); let c2: Cloneable = py_c.extract(py).unwrap(); assert_eq!(c, c2); { let rc: PyRef<'_, Cloneable> = py_c.extract(py).unwrap(); assert_eq!(&c, &*rc); // Drops PyRef before taking PyRefMut } let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap(); assert_eq!(&c, &*mrc); }); } #[pyclass(subclass)] #[derive(Default)] struct BaseClass { value: i32, } #[pymethods] impl BaseClass { fn foo(&self) -> &'static str { "BaseClass" } } #[pyclass(extends=BaseClass)] struct SubClass {} #[pymethods] impl SubClass { fn foo(&self) -> &'static str { "SubClass" } } #[pyclass] struct PolymorphicContainer { #[pyo3(get, set)] inner: Py, } #[test] fn test_polymorphic_container_stores_base_class() { Python::with_gil(|py| { let p = Py::new( py, PolymorphicContainer { inner: Py::new(py, BaseClass::default()).unwrap(), }, ) .unwrap() .to_object(py); py_assert!(py, p, "p.inner.foo() == 'BaseClass'"); }); } #[test] fn test_polymorphic_container_stores_sub_class() { Python::with_gil(|py| { let p = Py::new( py, PolymorphicContainer { inner: Py::new(py, BaseClass::default()).unwrap(), }, ) .unwrap() .to_object(py); p.bind(py) .setattr( "inner", Py::new( py, PyClassInitializer::from(BaseClass::default()).add_subclass(SubClass {}), ) .unwrap(), ) .unwrap(); py_assert!(py, p, "p.inner.foo() == 'SubClass'"); }); } #[test] fn test_polymorphic_container_does_not_accept_other_types() { Python::with_gil(|py| { let p = Py::new( py, PolymorphicContainer { inner: Py::new(py, BaseClass::default()).unwrap(), }, ) .unwrap() .to_object(py); let setattr = |value: PyObject| p.bind(py).setattr("inner", value); assert!(setattr(1i32.into_py(py)).is_err()); assert!(setattr(py.None()).is_err()); assert!(setattr((1i32, 2i32).into_py(py)).is_err()); }); } #[test] fn test_pyref_as_base() { Python::with_gil(|py| { let cell = Bound::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap(); // First try PyRefMut let sub: PyRefMut<'_, SubClass> = cell.borrow_mut(); let mut base: PyRefMut<'_, BaseClass> = sub.into_super(); assert_eq!(120, base.value); base.value = 999; assert_eq!(999, base.value); drop(base); // Repeat for PyRef let sub: PyRef<'_, SubClass> = cell.borrow(); let base: PyRef<'_, BaseClass> = sub.into_super(); assert_eq!(999, base.value); }); } #[test] fn test_pycell_deref() { Python::with_gil(|py| { let obj = Bound::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap(); // Should be able to deref as PyAny assert_eq!( obj.call_method0("foo") .and_then(|e| e.extract::()) .unwrap(), "SubClass" ); }); } pyo3/tests/test_super.rs0000644000175000017500000000234014661133735016337 0ustar jamespagejamespage#![cfg(all(feature = "macros", not(PyPy)))] use pyo3::{prelude::*, types::PySuper}; #[pyclass(subclass)] struct BaseClass { val1: usize, } #[pymethods] impl BaseClass { #[new] fn new() -> Self { BaseClass { val1: 10 } } pub fn method(&self) -> usize { self.val1 } } #[pyclass(extends=BaseClass)] struct SubClass {} #[pymethods] impl SubClass { #[new] fn new() -> (Self, BaseClass) { (SubClass {}, BaseClass::new()) } fn method<'py>(self_: &Bound<'py, Self>) -> PyResult> { let super_ = self_.py_super()?; super_.call_method("method", (), None) } fn method_super_new<'py>(self_: &Bound<'py, Self>) -> PyResult> { #[cfg_attr(not(feature = "gil-refs"), allow(deprecated))] let super_ = PySuper::new_bound(&self_.get_type(), self_)?; super_.call_method("method", (), None) } } #[test] fn test_call_super_method() { Python::with_gil(|py| { let cls = py.get_type_bound::(); pyo3::py_run!( py, cls, r#" obj = cls() assert obj.method() == 10 assert obj.method_super_new() == 10 "# ) }); } pyo3/tests/test_frompyobject.rs0000644000175000017500000004243114661133735017711 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::exceptions::PyValueError; use pyo3::prelude::*; use pyo3::types::{PyDict, PyList, PyString, PyTuple}; #[macro_use] #[path = "../src/tests/common.rs"] mod common; /// Helper function that concatenates the error message from /// each error in the traceback into a single string that can /// be tested. fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String { let mut error_msg = error.to_string(); while let Some(cause) = error.cause(py) { error_msg.push_str(": "); error_msg.push_str(&cause.to_string()); error = cause } error_msg } #[derive(Debug, FromPyObject)] pub struct A<'py> { #[pyo3(attribute)] s: String, #[pyo3(item)] t: Bound<'py, PyString>, #[pyo3(attribute("foo"))] p: Bound<'py, PyAny>, } #[pyclass] pub struct PyA { #[pyo3(get)] s: String, #[pyo3(get)] foo: Option, } #[pymethods] impl PyA { fn __getitem__(&self, key: String) -> pyo3::PyResult { if key == "t" { Ok("bar".into()) } else { Err(PyValueError::new_err("Failed")) } } } #[test] fn test_named_fields_struct() { Python::with_gil(|py| { let pya = PyA { s: "foo".into(), foo: None, }; let py_c = Py::new(py, pya).unwrap(); let a = py_c .extract::>(py) .expect("Failed to extract A from PyA"); assert_eq!(a.s, "foo"); assert_eq!(a.t.to_string_lossy(), "bar"); assert!(a.p.is_none()); }); } #[derive(Debug, FromPyObject)] #[pyo3(transparent)] pub struct B { test: String, } #[test] fn test_transparent_named_field_struct() { Python::with_gil(|py| { let test: PyObject = "test".into_py(py); let b = test .extract::(py) .expect("Failed to extract B from String"); assert_eq!(b.test, "test"); let test: PyObject = 1.into_py(py); let b = test.extract::(py); assert!(b.is_err()); }); } #[derive(Debug, FromPyObject)] #[pyo3(transparent)] pub struct D { test: T, } #[test] fn test_generic_transparent_named_field_struct() { Python::with_gil(|py| { let test: PyObject = "test".into_py(py); let d = test .extract::>(py) .expect("Failed to extract D from String"); assert_eq!(d.test, "test"); let test = 1usize.into_py(py); let d = test .extract::>(py) .expect("Failed to extract D from String"); assert_eq!(d.test, 1); }); } #[derive(Debug, FromPyObject)] pub struct E { test: T, test2: T2, } #[pyclass] #[derive(Clone)] pub struct PyE { #[pyo3(get)] test: String, #[pyo3(get)] test2: usize, } #[test] fn test_generic_named_fields_struct() { Python::with_gil(|py| { let pye = PyE { test: "test".into(), test2: 2, } .into_py(py); let e = pye .extract::>(py) .expect("Failed to extract E from PyE"); assert_eq!(e.test, "test"); assert_eq!(e.test2, 2); let e = pye.extract::>(py); assert!(e.is_err()); }); } #[derive(Debug, FromPyObject)] pub struct C { #[pyo3(attribute("test"))] test: String, } #[test] fn test_named_field_with_ext_fn() { Python::with_gil(|py| { let pyc = PyE { test: "foo".into(), test2: 0, } .into_py(py); let c = pyc.extract::(py).expect("Failed to extract C from PyE"); assert_eq!(c.test, "foo"); }); } #[derive(Debug, FromPyObject)] pub struct Tuple(String, usize); #[test] fn test_tuple_struct() { Python::with_gil(|py| { let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]); let tup = tup.extract::(); assert!(tup.is_err()); let tup = PyTuple::new_bound(py, &["test".into_py(py), 1.into_py(py)]); let tup = tup .extract::() .expect("Failed to extract Tuple from PyTuple"); assert_eq!(tup.0, "test"); assert_eq!(tup.1, 1); }); } #[derive(Debug, FromPyObject)] pub struct TransparentTuple(String); #[test] fn test_transparent_tuple_struct() { Python::with_gil(|py| { let tup: PyObject = 1.into_py(py); let tup = tup.extract::(py); assert!(tup.is_err()); let test: PyObject = "test".into_py(py); let tup = test .extract::(py) .expect("Failed to extract TransparentTuple from PyTuple"); assert_eq!(tup.0, "test"); }); } #[pyclass] struct PyBaz { #[pyo3(get)] tup: (String, String), #[pyo3(get)] e: PyE, } #[derive(Debug, FromPyObject)] #[allow(dead_code)] struct Baz { e: E, tup: Tuple, } #[test] fn test_struct_nested_type_errors() { Python::with_gil(|py| { let pybaz = PyBaz { tup: ("test".into(), "test".into()), e: PyE { test: "foo".into(), test2: 0, }, } .into_py(py); let test = pybaz.extract::>(py); assert!(test.is_err()); assert_eq!( extract_traceback(py,test.unwrap_err()), "TypeError: failed to extract field Baz.tup: TypeError: failed to extract field Tuple.1: \ TypeError: \'str\' object cannot be interpreted as an integer" ); }); } #[test] fn test_struct_nested_type_errors_with_generics() { Python::with_gil(|py| { let pybaz = PyBaz { tup: ("test".into(), "test".into()), e: PyE { test: "foo".into(), test2: 0, }, } .into_py(py); let test = pybaz.extract::>(py); assert!(test.is_err()); assert_eq!( extract_traceback(py, test.unwrap_err()), "TypeError: failed to extract field Baz.e: TypeError: failed to extract field E.test: \ TypeError: \'str\' object cannot be interpreted as an integer", ); }); } #[test] fn test_transparent_struct_error_message() { Python::with_gil(|py| { let tup: PyObject = 1.into_py(py); let tup = tup.extract::(py); assert!(tup.is_err()); assert_eq!( extract_traceback(py,tup.unwrap_err()), "TypeError: failed to extract field B.test: TypeError: \'int\' object cannot be converted \ to \'PyString\'" ); }); } #[test] fn test_tuple_struct_error_message() { Python::with_gil(|py| { let tup: PyObject = (1, "test").into_py(py); let tup = tup.extract::(py); assert!(tup.is_err()); assert_eq!( extract_traceback(py, tup.unwrap_err()), "TypeError: failed to extract field Tuple.0: TypeError: \'int\' object cannot be \ converted to \'PyString\'" ); }); } #[test] fn test_transparent_tuple_error_message() { Python::with_gil(|py| { let tup: PyObject = 1.into_py(py); let tup = tup.extract::(py); assert!(tup.is_err()); assert_eq!( extract_traceback(py, tup.unwrap_err()), "TypeError: failed to extract field TransparentTuple.0: TypeError: 'int' object \ cannot be converted to 'PyString'", ); }); } #[derive(Debug, FromPyObject)] pub enum Foo<'py> { TupleVar(usize, String), StructVar { test: Bound<'py, PyString>, }, #[pyo3(transparent)] TransparentTuple(usize), #[pyo3(transparent)] TransparentStructVar { a: Option, }, StructVarGetAttrArg { #[pyo3(attribute("bla"))] a: bool, }, StructWithGetItem { #[pyo3(item)] a: String, }, StructWithGetItemArg { #[pyo3(item("foo"))] a: String, }, } #[pyclass] pub struct PyBool { #[pyo3(get)] bla: bool, } #[test] fn test_enum() { Python::with_gil(|py| { let tup = PyTuple::new_bound(py, &[1.into_py(py), "test".into_py(py)]); let f = tup .extract::>() .expect("Failed to extract Foo from tuple"); match f { Foo::TupleVar(test, test2) => { assert_eq!(test, 1); assert_eq!(test2, "test"); } _ => panic!("Expected extracting Foo::TupleVar, got {:?}", f), } let pye = PyE { test: "foo".into(), test2: 0, } .into_py(py); let f = pye .extract::>(py) .expect("Failed to extract Foo from PyE"); match f { Foo::StructVar { test } => assert_eq!(test.to_string_lossy(), "foo"), _ => panic!("Expected extracting Foo::StructVar, got {:?}", f), } let int: PyObject = 1.into_py(py); let f = int .extract::>(py) .expect("Failed to extract Foo from int"); match f { Foo::TransparentTuple(test) => assert_eq!(test, 1), _ => panic!("Expected extracting Foo::TransparentTuple, got {:?}", f), } let none = py.None(); let f = none .extract::>(py) .expect("Failed to extract Foo from int"); match f { Foo::TransparentStructVar { a } => assert!(a.is_none()), _ => panic!("Expected extracting Foo::TransparentStructVar, got {:?}", f), } let pybool = PyBool { bla: true }.into_py(py); let f = pybool .extract::>(py) .expect("Failed to extract Foo from PyBool"); match f { Foo::StructVarGetAttrArg { a } => assert!(a), _ => panic!("Expected extracting Foo::StructVarGetAttrArg, got {:?}", f), } let dict = PyDict::new_bound(py); dict.set_item("a", "test").expect("Failed to set item"); let f = dict .extract::>() .expect("Failed to extract Foo from dict"); match f { Foo::StructWithGetItem { a } => assert_eq!(a, "test"), _ => panic!("Expected extracting Foo::StructWithGetItem, got {:?}", f), } let dict = PyDict::new_bound(py); dict.set_item("foo", "test").expect("Failed to set item"); let f = dict .extract::>() .expect("Failed to extract Foo from dict"); match f { Foo::StructWithGetItemArg { a } => assert_eq!(a, "test"), _ => panic!("Expected extracting Foo::StructWithGetItemArg, got {:?}", f), } }); } #[test] fn test_enum_error() { Python::with_gil(|py| { let dict = PyDict::new_bound(py); let err = dict.extract::>().unwrap_err(); assert_eq!( err.to_string(), "\ TypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple | TransparentStructVar | StructVarGetAttrArg | StructWithGetItem | StructWithGetItemArg') - variant TupleVar (TupleVar): TypeError: 'dict' object cannot be converted to 'PyTuple' - variant StructVar (StructVar): AttributeError: 'dict' object has no attribute 'test' - variant TransparentTuple (TransparentTuple): TypeError: failed to extract field Foo::TransparentTuple.0, caused by TypeError: 'dict' object cannot be interpreted as an integer - variant TransparentStructVar (TransparentStructVar): TypeError: failed to extract field Foo::TransparentStructVar.a, caused by TypeError: 'dict' object cannot be converted to 'PyString' - variant StructVarGetAttrArg (StructVarGetAttrArg): AttributeError: 'dict' object has no attribute 'bla' - variant StructWithGetItem (StructWithGetItem): KeyError: 'a' - variant StructWithGetItemArg (StructWithGetItemArg): KeyError: 'foo'" ); let tup = PyTuple::empty_bound(py); let err = tup.extract::>().unwrap_err(); assert_eq!( err.to_string(), "\ TypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple | TransparentStructVar | StructVarGetAttrArg | StructWithGetItem | StructWithGetItemArg') - variant TupleVar (TupleVar): ValueError: expected tuple of length 2, but got tuple of length 0 - variant StructVar (StructVar): AttributeError: 'tuple' object has no attribute 'test' - variant TransparentTuple (TransparentTuple): TypeError: failed to extract field Foo::TransparentTuple.0, caused by TypeError: 'tuple' object cannot be interpreted as an integer - variant TransparentStructVar (TransparentStructVar): TypeError: failed to extract field Foo::TransparentStructVar.a, caused by TypeError: 'tuple' object cannot be converted to 'PyString' - variant StructVarGetAttrArg (StructVarGetAttrArg): AttributeError: 'tuple' object has no attribute 'bla' - variant StructWithGetItem (StructWithGetItem): TypeError: tuple indices must be integers or slices, not str - variant StructWithGetItemArg (StructWithGetItemArg): TypeError: tuple indices must be integers or slices, not str" ); }); } #[derive(Debug, FromPyObject)] enum EnumWithCatchAll<'py> { #[allow(dead_code)] #[pyo3(transparent)] Foo(Foo<'py>), #[pyo3(transparent)] CatchAll(Bound<'py, PyAny>), } #[test] fn test_enum_catch_all() { Python::with_gil(|py| { let dict = PyDict::new_bound(py); let f = dict .extract::>() .expect("Failed to extract EnumWithCatchAll from dict"); match f { EnumWithCatchAll::CatchAll(any) => { let d = any.extract::>().expect("Expected pydict"); assert!(d.is_empty()); } _ => panic!( "Expected extracting EnumWithCatchAll::CatchAll, got {:?}", f ), } }); } #[derive(Debug, FromPyObject)] pub enum Bar { #[pyo3(annotation = "str")] A(String), #[pyo3(annotation = "uint")] B(usize), #[pyo3(annotation = "int", transparent)] C(isize), } #[test] fn test_err_rename() { Python::with_gil(|py| { let dict = PyDict::new_bound(py); let f = dict.extract::(); assert!(f.is_err()); assert_eq!( f.unwrap_err().to_string(), "\ TypeError: failed to extract enum Bar ('str | uint | int') - variant A (str): TypeError: failed to extract field Bar::A.0, caused by TypeError: 'dict' object cannot be converted to 'PyString' - variant B (uint): TypeError: failed to extract field Bar::B.0, caused by TypeError: 'dict' object cannot be interpreted as an integer - variant C (int): TypeError: failed to extract field Bar::C.0, caused by TypeError: 'dict' object cannot be interpreted as an integer" ); }); } #[derive(Debug, FromPyObject)] pub struct Zap { #[pyo3(item)] name: String, #[pyo3(from_py_with = "Bound::<'_, PyAny>::len", item("my_object"))] some_object_length: usize, } #[test] fn test_from_py_with() { Python::with_gil(|py| { let py_zap = py .eval_bound( r#"{"name": "whatever", "my_object": [1, 2, 3]}"#, None, None, ) .expect("failed to create dict"); let zap = py_zap.extract::().unwrap(); assert_eq!(zap.name, "whatever"); assert_eq!(zap.some_object_length, 3usize); }); } #[derive(Debug, FromPyObject)] pub struct ZapTuple( String, #[pyo3(from_py_with = "Bound::<'_, PyAny>::len")] usize, ); #[test] fn test_from_py_with_tuple_struct() { Python::with_gil(|py| { let py_zap = py .eval_bound(r#"("whatever", [1, 2, 3])"#, None, None) .expect("failed to create tuple"); let zap = py_zap.extract::().unwrap(); assert_eq!(zap.0, "whatever"); assert_eq!(zap.1, 3usize); }); } #[test] fn test_from_py_with_tuple_struct_error() { Python::with_gil(|py| { let py_zap = py .eval_bound(r#"("whatever", [1, 2, 3], "third")"#, None, None) .expect("failed to create tuple"); let f = py_zap.extract::(); assert!(f.is_err()); assert_eq!( f.unwrap_err().to_string(), "ValueError: expected tuple of length 2, but got tuple of length 3" ); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] pub enum ZapEnum { Zip(#[pyo3(from_py_with = "Bound::<'_, PyAny>::len")] usize), Zap( String, #[pyo3(from_py_with = "Bound::<'_, PyAny>::len")] usize, ), } #[test] fn test_from_py_with_enum() { Python::with_gil(|py| { let py_zap = py .eval_bound(r#"("whatever", [1, 2, 3])"#, None, None) .expect("failed to create tuple"); let zap = py_zap.extract::().unwrap(); let expected_zap = ZapEnum::Zip(2); assert_eq!(zap, expected_zap); }); } #[derive(Debug, FromPyObject, PartialEq, Eq)] #[pyo3(transparent)] pub struct TransparentFromPyWith { #[pyo3(from_py_with = "Bound::<'_, PyAny>::len")] len: usize, } #[test] fn test_transparent_from_py_with() { Python::with_gil(|py| { let result = PyList::new_bound(py, [1, 2, 3]) .extract::() .unwrap(); let expected = TransparentFromPyWith { len: 3 }; assert_eq!(result, expected); }); } pyo3/tests/test_default_impls.rs0000644000175000017500000000155414661133735020037 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; #[path = "../src/tests/common.rs"] mod common; // Test default generated __repr__. #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum TestDefaultRepr { Var, } #[test] fn test_default_slot_exists() { Python::with_gil(|py| { let test_object = Py::new(py, TestDefaultRepr::Var).unwrap(); py_assert!( py, test_object, "repr(test_object) == 'TestDefaultRepr.Var'" ); }) } #[pyclass(eq, eq_int)] #[derive(PartialEq)] enum OverrideSlot { Var, } #[pymethods] impl OverrideSlot { fn __repr__(&self) -> &str { "overridden" } } #[test] fn test_override_slot() { Python::with_gil(|py| { let test_object = Py::new(py, OverrideSlot::Var).unwrap(); py_assert!(py, test_object, "repr(test_object) == 'overridden'"); }) } pyo3/tests/test_variable_arguments.rs0000644000175000017500000000230214661133735021051 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct MyClass {} #[pymethods] impl MyClass { #[staticmethod] #[pyo3(signature = (*args))] fn test_args(args: Bound<'_, PyTuple>) -> Bound<'_, PyTuple> { args } #[staticmethod] #[pyo3(signature = (**kwargs))] fn test_kwargs(kwargs: Option>) -> Option> { kwargs } } #[test] fn variable_args() { Python::with_gil(|py| { let my_obj = py.get_type_bound::(); py_assert!(py, my_obj, "my_obj.test_args() == ()"); py_assert!(py, my_obj, "my_obj.test_args(1) == (1,)"); py_assert!(py, my_obj, "my_obj.test_args(1, 2) == (1, 2)"); }); } #[test] fn variable_kwargs() { Python::with_gil(|py| { let my_obj = py.get_type_bound::(); py_assert!(py, my_obj, "my_obj.test_kwargs() == None"); py_assert!(py, my_obj, "my_obj.test_kwargs(test=1) == {'test': 1}"); py_assert!( py, my_obj, "my_obj.test_kwargs(test1=1, test2=2) == {'test1':1, 'test2':2}" ); }); } pyo3/tests/test_arithmetics.rs0000644000175000017500000006015614661133735017526 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::class::basic::CompareOp; use pyo3::prelude::*; use pyo3::py_run; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct UnaryArithmetic { inner: f64, } #[pymethods] impl UnaryArithmetic { #[new] fn new(value: f64) -> Self { UnaryArithmetic { inner: value } } fn __repr__(&self) -> String { format!("UA({})", self.inner) } fn __neg__(&self) -> Self { Self::new(-self.inner) } fn __pos__(&self) -> Self { Self::new(self.inner) } fn __abs__(&self) -> Self { Self::new(self.inner.abs()) } fn __invert__(&self) -> Self { Self::new(self.inner.recip()) } #[pyo3(signature=(_ndigits=None))] fn __round__(&self, _ndigits: Option) -> Self { Self::new(self.inner.round()) } } #[test] fn unary_arithmetic() { Python::with_gil(|py| { let c = Py::new(py, UnaryArithmetic::new(2.7)).unwrap(); py_run!(py, c, "assert repr(-c) == 'UA(-2.7)'"); py_run!(py, c, "assert repr(+c) == 'UA(2.7)'"); py_run!(py, c, "assert repr(abs(c)) == 'UA(2.7)'"); py_run!(py, c, "assert repr(~c) == 'UA(0.37037037037037035)'"); py_run!(py, c, "assert repr(round(c)) == 'UA(3)'"); py_run!(py, c, "assert repr(round(c, 1)) == 'UA(3)'"); let c: Bound<'_, PyAny> = c.extract(py).unwrap(); assert_py_eq!(c.neg().unwrap().repr().unwrap().as_any(), "UA(-2.7)"); assert_py_eq!(c.pos().unwrap().repr().unwrap().as_any(), "UA(2.7)"); assert_py_eq!(c.abs().unwrap().repr().unwrap().as_any(), "UA(2.7)"); assert_py_eq!( c.bitnot().unwrap().repr().unwrap().as_any(), "UA(0.37037037037037035)" ); }); } #[pyclass] struct Indexable(i32); #[pymethods] impl Indexable { fn __index__(&self) -> i32 { self.0 } fn __int__(&self) -> i32 { self.0 } fn __float__(&self) -> f64 { f64::from(self.0) } fn __invert__(&self) -> Self { Self(!self.0) } } #[test] fn indexable() { Python::with_gil(|py| { let i = Py::new(py, Indexable(5)).unwrap(); py_run!(py, i, "assert int(i) == 5"); py_run!(py, i, "assert [0, 1, 2, 3, 4, 5][i] == 5"); py_run!(py, i, "assert float(i) == 5.0"); py_run!(py, i, "assert int(~i) == -6"); }) } #[pyclass] struct InPlaceOperations { value: u32, } #[pymethods] impl InPlaceOperations { fn __repr__(&self) -> String { format!("IPO({:?})", self.value) } fn __iadd__(&mut self, other: u32) { self.value += other; } fn __isub__(&mut self, other: u32) { self.value -= other; } fn __imul__(&mut self, other: u32) { self.value *= other; } fn __ilshift__(&mut self, other: u32) { self.value <<= other; } fn __irshift__(&mut self, other: u32) { self.value >>= other; } fn __iand__(&mut self, other: u32) { self.value &= other; } fn __ixor__(&mut self, other: u32) { self.value ^= other; } fn __ior__(&mut self, other: u32) { self.value |= other; } fn __ipow__(&mut self, other: u32, _modulo: Option) { self.value = self.value.pow(other); } } #[test] fn inplace_operations() { Python::with_gil(|py| { let init = |value, code| { let c = Py::new(py, InPlaceOperations { value }).unwrap(); py_run!(py, c, code); }; init(0, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'"); init(10, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'"); init(12, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'"); init(12, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'"); init(12, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'"); init(12, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'"); init(3, "d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'"); init( 3, "d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'", ); }); } #[pyclass] struct BinaryArithmetic {} #[pymethods] impl BinaryArithmetic { fn __repr__(&self) -> &'static str { "BA" } fn __add__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA + {:?}", rhs) } fn __sub__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA - {:?}", rhs) } fn __mul__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA * {:?}", rhs) } fn __matmul__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA @ {:?}", rhs) } fn __truediv__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA / {:?}", rhs) } fn __floordiv__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA // {:?}", rhs) } fn __mod__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA % {:?}", rhs) } fn __divmod__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("divmod(BA, {:?})", rhs) } fn __lshift__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA << {:?}", rhs) } fn __rshift__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA >> {:?}", rhs) } fn __and__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA & {:?}", rhs) } fn __xor__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA ^ {:?}", rhs) } fn __or__(&self, rhs: &Bound<'_, PyAny>) -> String { format!("BA | {:?}", rhs) } fn __pow__(&self, rhs: &Bound<'_, PyAny>, mod_: Option) -> String { format!("BA ** {:?} (mod: {:?})", rhs, mod_) } } #[test] fn binary_arithmetic() { Python::with_gil(|py| { let c = Py::new(py, BinaryArithmetic {}).unwrap(); py_run!(py, c, "assert c + c == 'BA + BA'"); py_run!(py, c, "assert c.__add__(c) == 'BA + BA'"); py_run!(py, c, "assert c + 1 == 'BA + 1'"); py_run!(py, c, "assert c - 1 == 'BA - 1'"); py_run!(py, c, "assert c * 1 == 'BA * 1'"); py_run!(py, c, "assert c @ 1 == 'BA @ 1'"); py_run!(py, c, "assert c / 1 == 'BA / 1'"); py_run!(py, c, "assert c // 1 == 'BA // 1'"); py_run!(py, c, "assert c % 1 == 'BA % 1'"); py_run!(py, c, "assert divmod(c, 1) == 'divmod(BA, 1)'"); py_run!(py, c, "assert c << 1 == 'BA << 1'"); py_run!(py, c, "assert c >> 1 == 'BA >> 1'"); py_run!(py, c, "assert c & 1 == 'BA & 1'"); py_run!(py, c, "assert c ^ 1 == 'BA ^ 1'"); py_run!(py, c, "assert c | 1 == 'BA | 1'"); py_run!(py, c, "assert c ** 1 == 'BA ** 1 (mod: None)'"); // Class with __add__ only should not allow the reverse op; // this is consistent with Python classes. py_expect_exception!(py, c, "1 + c", PyTypeError); py_expect_exception!(py, c, "1 - c", PyTypeError); py_expect_exception!(py, c, "1 * c", PyTypeError); py_expect_exception!(py, c, "1 @ c", PyTypeError); py_expect_exception!(py, c, "1 / c", PyTypeError); py_expect_exception!(py, c, "1 // c", PyTypeError); py_expect_exception!(py, c, "1 % c", PyTypeError); py_expect_exception!(py, c, "divmod(1, c)", PyTypeError); py_expect_exception!(py, c, "1 << c", PyTypeError); py_expect_exception!(py, c, "1 >> c", PyTypeError); py_expect_exception!(py, c, "1 & c", PyTypeError); py_expect_exception!(py, c, "1 ^ c", PyTypeError); py_expect_exception!(py, c, "1 | c", PyTypeError); py_expect_exception!(py, c, "1 ** c", PyTypeError); py_run!(py, c, "assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'"); let c: Bound<'_, PyAny> = c.extract(py).unwrap(); assert_py_eq!(c.add(&c).unwrap(), "BA + BA"); assert_py_eq!(c.sub(&c).unwrap(), "BA - BA"); assert_py_eq!(c.mul(&c).unwrap(), "BA * BA"); assert_py_eq!(c.matmul(&c).unwrap(), "BA @ BA"); assert_py_eq!(c.div(&c).unwrap(), "BA / BA"); assert_py_eq!(c.floor_div(&c).unwrap(), "BA // BA"); assert_py_eq!(c.rem(&c).unwrap(), "BA % BA"); assert_py_eq!(c.divmod(&c).unwrap(), "divmod(BA, BA)"); assert_py_eq!(c.lshift(&c).unwrap(), "BA << BA"); assert_py_eq!(c.rshift(&c).unwrap(), "BA >> BA"); assert_py_eq!(c.bitand(&c).unwrap(), "BA & BA"); assert_py_eq!(c.bitor(&c).unwrap(), "BA | BA"); assert_py_eq!(c.bitxor(&c).unwrap(), "BA ^ BA"); assert_py_eq!(c.pow(&c, py.None()).unwrap(), "BA ** BA (mod: None)"); }); } #[pyclass] struct RhsArithmetic {} #[pymethods] impl RhsArithmetic { fn __radd__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} + RA", other) } fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} - RA", other) } fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} * RA", other) } fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} << RA", other) } fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} >> RA", other) } fn __rand__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} & RA", other) } fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} ^ RA", other) } fn __ror__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} | RA", other) } fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&Bound<'_, PyAny>>) -> String { format!("{:?} ** RA", other) } } #[test] fn rhs_arithmetic() { Python::with_gil(|py| { let c = Py::new(py, RhsArithmetic {}).unwrap(); py_run!(py, c, "assert c.__radd__(1) == '1 + RA'"); py_run!(py, c, "assert 1 + c == '1 + RA'"); py_run!(py, c, "assert c.__rsub__(1) == '1 - RA'"); py_run!(py, c, "assert 1 - c == '1 - RA'"); py_run!(py, c, "assert c.__rmul__(1) == '1 * RA'"); py_run!(py, c, "assert 1 * c == '1 * RA'"); py_run!(py, c, "assert c.__rlshift__(1) == '1 << RA'"); py_run!(py, c, "assert 1 << c == '1 << RA'"); py_run!(py, c, "assert c.__rrshift__(1) == '1 >> RA'"); py_run!(py, c, "assert 1 >> c == '1 >> RA'"); py_run!(py, c, "assert c.__rand__(1) == '1 & RA'"); py_run!(py, c, "assert 1 & c == '1 & RA'"); py_run!(py, c, "assert c.__rxor__(1) == '1 ^ RA'"); py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); py_run!(py, c, "assert c.__ror__(1) == '1 | RA'"); py_run!(py, c, "assert 1 | c == '1 | RA'"); py_run!(py, c, "assert c.__rpow__(1) == '1 ** RA'"); py_run!(py, c, "assert 1 ** c == '1 ** RA'"); }); } #[pyclass] struct LhsAndRhs {} impl std::fmt::Debug for LhsAndRhs { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "LR") } } #[pymethods] impl LhsAndRhs { // fn __repr__(&self) -> &'static str { // "BA" // } fn __add__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} + {:?}", lhs, rhs) } fn __sub__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} - {:?}", lhs, rhs) } fn __mul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} * {:?}", lhs, rhs) } fn __lshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} << {:?}", lhs, rhs) } fn __rshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} >> {:?}", lhs, rhs) } fn __and__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} & {:?}", lhs, rhs) } fn __xor__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} ^ {:?}", lhs, rhs) } fn __or__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} | {:?}", lhs, rhs) } fn __pow__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>, _mod: Option) -> String { format!("{:?} ** {:?}", lhs, rhs) } fn __matmul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String { format!("{:?} @ {:?}", lhs, rhs) } fn __radd__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} + RA", other) } fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} - RA", other) } fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} * RA", other) } fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} << RA", other) } fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} >> RA", other) } fn __rand__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} & RA", other) } fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} ^ RA", other) } fn __ror__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} | RA", other) } fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&Bound<'_, PyAny>>) -> String { format!("{:?} ** RA", other) } fn __rmatmul__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} @ RA", other) } fn __rtruediv__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} / RA", other) } fn __rfloordiv__(&self, other: &Bound<'_, PyAny>) -> String { format!("{:?} // RA", other) } } #[test] fn lhs_fellback_to_rhs() { Python::with_gil(|py| { let c = Py::new(py, LhsAndRhs {}).unwrap(); // If the light hand value is `LhsAndRhs`, LHS is used. py_run!(py, c, "assert c + 1 == 'LR + 1'"); py_run!(py, c, "assert c - 1 == 'LR - 1'"); py_run!(py, c, "assert c * 1 == 'LR * 1'"); py_run!(py, c, "assert c << 1 == 'LR << 1'"); py_run!(py, c, "assert c >> 1 == 'LR >> 1'"); py_run!(py, c, "assert c & 1 == 'LR & 1'"); py_run!(py, c, "assert c ^ 1 == 'LR ^ 1'"); py_run!(py, c, "assert c | 1 == 'LR | 1'"); py_run!(py, c, "assert c ** 1 == 'LR ** 1'"); py_run!(py, c, "assert c @ 1 == 'LR @ 1'"); // Fellback to RHS because of type mismatching py_run!(py, c, "assert 1 + c == '1 + RA'"); py_run!(py, c, "assert 1 - c == '1 - RA'"); py_run!(py, c, "assert 1 * c == '1 * RA'"); py_run!(py, c, "assert 1 << c == '1 << RA'"); py_run!(py, c, "assert 1 >> c == '1 >> RA'"); py_run!(py, c, "assert 1 & c == '1 & RA'"); py_run!(py, c, "assert 1 ^ c == '1 ^ RA'"); py_run!(py, c, "assert 1 | c == '1 | RA'"); py_run!(py, c, "assert 1 ** c == '1 ** RA'"); py_run!(py, c, "assert 1 @ c == '1 @ RA'"); }); } #[pyclass] struct RichComparisons {} #[pymethods] impl RichComparisons { fn __repr__(&self) -> &'static str { "RC" } fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> String { match op { CompareOp::Lt => format!("{} < {:?}", self.__repr__(), other), CompareOp::Le => format!("{} <= {:?}", self.__repr__(), other), CompareOp::Eq => format!("{} == {:?}", self.__repr__(), other), CompareOp::Ne => format!("{} != {:?}", self.__repr__(), other), CompareOp::Gt => format!("{} > {:?}", self.__repr__(), other), CompareOp::Ge => format!("{} >= {:?}", self.__repr__(), other), } } } #[pyclass] struct RichComparisons2 {} #[pymethods] impl RichComparisons2 { fn __repr__(&self) -> &'static str { "RC2" } fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> PyObject { match op { CompareOp::Eq => true.into_py(other.py()), CompareOp::Ne => false.into_py(other.py()), _ => other.py().NotImplemented(), } } } #[test] fn rich_comparisons() { Python::with_gil(|py| { let c = Py::new(py, RichComparisons {}).unwrap(); py_run!(py, c, "assert (c < c) == 'RC < RC'"); py_run!(py, c, "assert (c < 1) == 'RC < 1'"); py_run!(py, c, "assert (1 < c) == 'RC > 1'"); py_run!(py, c, "assert (c <= c) == 'RC <= RC'"); py_run!(py, c, "assert (c <= 1) == 'RC <= 1'"); py_run!(py, c, "assert (1 <= c) == 'RC >= 1'"); py_run!(py, c, "assert (c == c) == 'RC == RC'"); py_run!(py, c, "assert (c == 1) == 'RC == 1'"); py_run!(py, c, "assert (1 == c) == 'RC == 1'"); py_run!(py, c, "assert (c != c) == 'RC != RC'"); py_run!(py, c, "assert (c != 1) == 'RC != 1'"); py_run!(py, c, "assert (1 != c) == 'RC != 1'"); py_run!(py, c, "assert (c > c) == 'RC > RC'"); py_run!(py, c, "assert (c > 1) == 'RC > 1'"); py_run!(py, c, "assert (1 > c) == 'RC < 1'"); py_run!(py, c, "assert (c >= c) == 'RC >= RC'"); py_run!(py, c, "assert (c >= 1) == 'RC >= 1'"); py_run!(py, c, "assert (1 >= c) == 'RC <= 1'"); }); } #[test] fn rich_comparisons_python_3_type_error() { Python::with_gil(|py| { let c2 = Py::new(py, RichComparisons2 {}).unwrap(); py_expect_exception!(py, c2, "c2 < c2", PyTypeError); py_expect_exception!(py, c2, "c2 < 1", PyTypeError); py_expect_exception!(py, c2, "1 < c2", PyTypeError); py_expect_exception!(py, c2, "c2 <= c2", PyTypeError); py_expect_exception!(py, c2, "c2 <= 1", PyTypeError); py_expect_exception!(py, c2, "1 <= c2", PyTypeError); py_run!(py, c2, "assert (c2 == c2) == True"); py_run!(py, c2, "assert (c2 == 1) == True"); py_run!(py, c2, "assert (1 == c2) == True"); py_run!(py, c2, "assert (c2 != c2) == False"); py_run!(py, c2, "assert (c2 != 1) == False"); py_run!(py, c2, "assert (1 != c2) == False"); py_expect_exception!(py, c2, "c2 > c2", PyTypeError); py_expect_exception!(py, c2, "c2 > 1", PyTypeError); py_expect_exception!(py, c2, "1 > c2", PyTypeError); py_expect_exception!(py, c2, "c2 >= c2", PyTypeError); py_expect_exception!(py, c2, "c2 >= 1", PyTypeError); py_expect_exception!(py, c2, "1 >= c2", PyTypeError); }); } // Checks that binary operations for which the arguments don't match the // required type, return NotImplemented. mod return_not_implemented { use super::*; #[pyclass] struct RichComparisonToSelf {} #[pymethods] impl RichComparisonToSelf { fn __repr__(&self) -> &'static str { "RC_Self" } fn __richcmp__(&self, other: PyRef<'_, Self>, _op: CompareOp) -> PyObject { other.py().None() } fn __add__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __sub__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __mul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __matmul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __truediv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __floordiv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __mod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __pow__(slf: PyRef<'_, Self>, _other: u8, _modulo: Option) -> PyRef<'_, Self> { slf } fn __lshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __rshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __divmod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __and__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __or__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } fn __xor__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> { slf } // Inplace assignments fn __iadd__(&mut self, _other: PyRef<'_, Self>) {} fn __isub__(&mut self, _other: PyRef<'_, Self>) {} fn __imul__(&mut self, _other: PyRef<'_, Self>) {} fn __imatmul__(&mut self, _other: PyRef<'_, Self>) {} fn __itruediv__(&mut self, _other: PyRef<'_, Self>) {} fn __ifloordiv__(&mut self, _other: PyRef<'_, Self>) {} fn __imod__(&mut self, _other: PyRef<'_, Self>) {} fn __ilshift__(&mut self, _other: PyRef<'_, Self>) {} fn __irshift__(&mut self, _other: PyRef<'_, Self>) {} fn __iand__(&mut self, _other: PyRef<'_, Self>) {} fn __ior__(&mut self, _other: PyRef<'_, Self>) {} fn __ixor__(&mut self, _other: PyRef<'_, Self>) {} fn __ipow__(&mut self, _other: PyRef<'_, Self>, _modulo: Option) {} } fn _test_binary_dunder(dunder: &str) { Python::with_gil(|py| { let c2 = Py::new(py, RichComparisonToSelf {}).unwrap(); py_run!( py, c2, &format!( "class Other: pass\nassert c2.__{}__(Other()) is NotImplemented", dunder ) ); }); } fn _test_binary_operator(operator: &str, dunder: &str) { _test_binary_dunder(dunder); Python::with_gil(|py| { let c2 = Py::new(py, RichComparisonToSelf {}).unwrap(); py_expect_exception!( py, c2, &format!("class Other: pass\nc2 {} Other()", operator), PyTypeError ); }); } fn _test_inplace_binary_operator(operator: &str, dunder: &str) { _test_binary_operator(operator, dunder); } #[test] fn equality() { _test_binary_dunder("eq"); _test_binary_dunder("ne"); } #[test] fn ordering() { _test_binary_operator("<", "lt"); _test_binary_operator("<=", "le"); _test_binary_operator(">", "gt"); _test_binary_operator(">=", "ge"); } #[test] fn bitwise() { _test_binary_operator("&", "and"); _test_binary_operator("|", "or"); _test_binary_operator("^", "xor"); _test_binary_operator("<<", "lshift"); _test_binary_operator(">>", "rshift"); } #[test] fn arith() { _test_binary_operator("+", "add"); _test_binary_operator("-", "sub"); _test_binary_operator("*", "mul"); _test_binary_operator("@", "matmul"); _test_binary_operator("/", "truediv"); _test_binary_operator("//", "floordiv"); _test_binary_operator("%", "mod"); _test_binary_operator("**", "pow"); } #[test] fn reverse_arith() { _test_binary_dunder("radd"); _test_binary_dunder("rsub"); _test_binary_dunder("rmul"); _test_binary_dunder("rmatmul"); _test_binary_dunder("rtruediv"); _test_binary_dunder("rfloordiv"); _test_binary_dunder("rmod"); _test_binary_dunder("rdivmod"); _test_binary_dunder("rpow"); } #[test] fn inplace_bitwise() { _test_inplace_binary_operator("&=", "iand"); _test_inplace_binary_operator("|=", "ior"); _test_inplace_binary_operator("^=", "ixor"); _test_inplace_binary_operator("<<=", "ilshift"); _test_inplace_binary_operator(">>=", "irshift"); } #[test] fn inplace_arith() { _test_inplace_binary_operator("+=", "iadd"); _test_inplace_binary_operator("-=", "isub"); _test_inplace_binary_operator("*=", "imul"); _test_inplace_binary_operator("@=", "imatmul"); _test_inplace_binary_operator("/=", "itruediv"); _test_inplace_binary_operator("//=", "ifloordiv"); _test_inplace_binary_operator("%=", "imod"); _test_inplace_binary_operator("**=", "ipow"); } } pyo3/tests/test_no_imports.rs0000644000175000017500000001044114661133735017373 0ustar jamespagejamespage//! Tests that various macros work correctly without any PyO3 imports. #![cfg(feature = "macros")] use pyo3::prelude::PyAnyMethods; #[pyo3::pyfunction] #[pyo3(name = "identity", signature = (x = None))] fn basic_function(py: pyo3::Python<'_>, x: Option) -> pyo3::PyObject { x.unwrap_or_else(|| py.None()) } #[cfg(feature = "gil-refs")] #[allow(deprecated)] #[pyo3::pymodule] fn basic_module(_py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> { #[pyfn(m)] fn answer() -> usize { 42 } m.add_function(pyo3::wrap_pyfunction!(basic_function, m)?)?; Ok(()) } #[pyo3::pymodule] fn basic_module_bound(m: &pyo3::Bound<'_, pyo3::types::PyModule>) -> pyo3::PyResult<()> { #[pyfn(m)] fn answer() -> usize { 42 } pyo3::types::PyModuleMethods::add_function( m, pyo3::wrap_pyfunction_bound!(basic_function, m)?, )?; Ok(()) } #[pyo3::pyclass] struct BasicClass { #[pyo3(get)] v: usize, #[pyo3(get, set)] s: String, } #[pyo3::pymethods] impl BasicClass { #[classattr] const OKAY: bool = true; #[new] fn new(arg: &pyo3::Bound<'_, pyo3::PyAny>) -> pyo3::PyResult { if let Ok(v) = arg.extract::() { Ok(Self { v, s: "".to_string(), }) } else { Ok(Self { v: 0, s: arg.extract()?, }) } } #[getter] fn get_property(&self) -> usize { self.v * 100 } #[setter] fn set_property(&mut self, value: usize) { self.v = value / 100 } /// Some documentation here #[classmethod] fn classmethod<'a, 'py>( cls: &'a pyo3::Bound<'py, pyo3::types::PyType>, ) -> &'a pyo3::Bound<'py, pyo3::types::PyType> { cls } #[staticmethod] fn staticmethod(py: pyo3::Python<'_>, v: usize) -> pyo3::Py { use pyo3::IntoPy; v.to_string().into_py(py) } fn __add__(&self, other: usize) -> usize { self.v + other } fn __iadd__(&mut self, other: pyo3::PyRef<'_, Self>) { self.v += other.v; self.s.push_str(&other.s); } fn mutate(mut slf: pyo3::PyRefMut<'_, Self>) { slf.v += slf.v; slf.s.push('!'); } } #[test] fn test_basic() { pyo3::Python::with_gil(|py| { let module = pyo3::wrap_pymodule!(basic_module_bound)(py); let cls = py.get_type_bound::(); let d = pyo3::types::IntoPyDict::into_py_dict_bound( [ ("mod", module.bind(py).as_any()), ("cls", &cls), ("a", &cls.call1((8,)).unwrap()), ("b", &cls.call1(("foo",)).unwrap()), ], py, ); pyo3::py_run!(py, *d, "assert mod.answer() == 42"); pyo3::py_run!(py, *d, "assert mod.identity() is None"); pyo3::py_run!(py, *d, "v = object(); assert mod.identity(v) is v"); pyo3::py_run!(py, *d, "assert cls.OKAY"); pyo3::py_run!(py, *d, "assert (a.v, a.s) == (8, '')"); pyo3::py_run!(py, *d, "assert (b.v, b.s) == (0, 'foo')"); pyo3::py_run!(py, *d, "b.property = 314"); pyo3::py_run!(py, *d, "assert b.property == 300"); pyo3::py_run!( py, *d, "assert cls.classmethod.__doc__ == 'Some documentation here'" ); pyo3::py_run!(py, *d, "assert cls.classmethod() is cls"); pyo3::py_run!(py, *d, "assert cls.staticmethod(5) == '5'"); pyo3::py_run!(py, *d, "a.s = 'bar'; assert a.s == 'bar'"); pyo3::py_run!(py, *d, "a.mutate(); assert (a.v, a.s) == (16, 'bar!')"); pyo3::py_run!(py, *d, "assert a + 9 == 25"); pyo3::py_run!(py, *d, "b += a; assert (b.v, b.s) == (19, 'foobar!')"); }); } #[pyo3::pyclass] struct NewClassMethod { #[pyo3(get)] cls: pyo3::PyObject, } #[pyo3::pymethods] impl NewClassMethod { #[new] #[classmethod] fn new(cls: &pyo3::Bound<'_, pyo3::types::PyType>) -> Self { Self { cls: cls.clone().into_any().unbind(), } } } #[test] fn test_new_class_method() { pyo3::Python::with_gil(|py| { let cls = py.get_type_bound::(); pyo3::py_run!(py, cls, "assert cls().cls is cls"); }); } pyo3/tests/test_append_to_inittab.rs0000644000175000017500000000205114661133735020663 0ustar jamespagejamespage#![cfg(all(feature = "macros", not(PyPy)))] use pyo3::prelude::*; #[pyfunction] fn foo() -> usize { 123 } #[pymodule] fn module_fn_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(foo, m)?)?; Ok(()) } #[pymodule] mod module_mod_with_functions { #[pymodule_export] use super::foo; } #[cfg(not(PyPy))] #[test] fn test_module_append_to_inittab() { use pyo3::append_to_inittab; append_to_inittab!(module_fn_with_functions); append_to_inittab!(module_mod_with_functions); Python::with_gil(|py| { py.run_bound( r#" import module_fn_with_functions assert module_fn_with_functions.foo() == 123 "#, None, None, ) .map_err(|e| e.display(py)) .unwrap(); }); Python::with_gil(|py| { py.run_bound( r#" import module_mod_with_functions assert module_mod_with_functions.foo() == 123 "#, None, None, ) .map_err(|e| e.display(py)) .unwrap(); }); } pyo3/tests/test_gc.rs0000644000175000017500000003551314661133735015602 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::class::PyTraverseError; use pyo3::class::PyVisit; use pyo3::prelude::*; use pyo3::py_run; use std::cell::Cell; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; #[path = "../src/tests/common.rs"] mod common; #[pyclass(freelist = 2)] struct ClassWithFreelist {} #[test] fn class_with_freelist() { let ptr = Python::with_gil(|py| { let inst = Py::new(py, ClassWithFreelist {}).unwrap(); let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap(); let ptr = inst.as_ptr(); drop(inst); ptr }); Python::with_gil(|py| { let inst3 = Py::new(py, ClassWithFreelist {}).unwrap(); assert_eq!(ptr, inst3.as_ptr()); let inst4 = Py::new(py, ClassWithFreelist {}).unwrap(); assert_ne!(ptr, inst4.as_ptr()) }); } struct TestDropCall { drop_called: Arc, } impl Drop for TestDropCall { fn drop(&mut self) { self.drop_called.store(true, Ordering::Relaxed); } } #[allow(dead_code)] #[pyclass] struct DataIsDropped { member1: TestDropCall, member2: TestDropCall, } #[test] fn data_is_dropped() { let drop_called1 = Arc::new(AtomicBool::new(false)); let drop_called2 = Arc::new(AtomicBool::new(false)); Python::with_gil(|py| { let data_is_dropped = DataIsDropped { member1: TestDropCall { drop_called: Arc::clone(&drop_called1), }, member2: TestDropCall { drop_called: Arc::clone(&drop_called2), }, }; let inst = Py::new(py, data_is_dropped).unwrap(); assert!(!drop_called1.load(Ordering::Relaxed)); assert!(!drop_called2.load(Ordering::Relaxed)); drop(inst); }); assert!(drop_called1.load(Ordering::Relaxed)); assert!(drop_called2.load(Ordering::Relaxed)); } #[allow(dead_code)] #[pyclass] struct GcIntegration { self_ref: PyObject, dropped: TestDropCall, } #[pymethods] impl GcIntegration { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.self_ref) } fn __clear__(&mut self) { Python::with_gil(|py| { self.self_ref = py.None(); }); } } #[test] fn gc_integration() { let drop_called = Arc::new(AtomicBool::new(false)); Python::with_gil(|py| { let inst = Bound::new( py, GcIntegration { self_ref: py.None(), dropped: TestDropCall { drop_called: Arc::clone(&drop_called), }, }, ) .unwrap(); let mut borrow = inst.borrow_mut(); borrow.self_ref = inst.to_object(py); py_run!(py, inst, "import gc; assert inst in gc.get_objects()"); }); Python::with_gil(|py| { py.run_bound("import gc; gc.collect()", None, None).unwrap(); assert!(drop_called.load(Ordering::Relaxed)); }); } #[pyclass] struct GcNullTraversal { cycle: Option>, null: Option>, } #[pymethods] impl GcNullTraversal { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.cycle)?; visit.call(&self.null)?; // Should not segfault Ok(()) } fn __clear__(&mut self) { self.cycle = None; self.null = None; } } #[test] fn gc_null_traversal() { Python::with_gil(|py| { let obj = Py::new( py, GcNullTraversal { cycle: None, null: None, }, ) .unwrap(); obj.borrow_mut(py).cycle = Some(obj.clone_ref(py)); // the object doesn't have to be cleaned up, it just needs to be traversed. py.run_bound("import gc; gc.collect()", None, None).unwrap(); }); } #[pyclass(subclass)] struct BaseClassWithDrop { data: Option>, } #[pymethods] impl BaseClassWithDrop { #[new] fn new() -> BaseClassWithDrop { BaseClassWithDrop { data: None } } } impl Drop for BaseClassWithDrop { fn drop(&mut self) { if let Some(data) = &self.data { data.store(true, Ordering::Relaxed); } } } #[pyclass(extends = BaseClassWithDrop)] struct SubClassWithDrop { data: Option>, } #[pymethods] impl SubClassWithDrop { #[new] fn new() -> (Self, BaseClassWithDrop) { ( SubClassWithDrop { data: None }, BaseClassWithDrop { data: None }, ) } } impl Drop for SubClassWithDrop { fn drop(&mut self) { if let Some(data) = &self.data { data.store(true, Ordering::Relaxed); } } } #[test] fn inheritance_with_new_methods_with_drop() { let drop_called1 = Arc::new(AtomicBool::new(false)); let drop_called2 = Arc::new(AtomicBool::new(false)); Python::with_gil(|py| { let _typebase = py.get_type_bound::(); let typeobj = py.get_type_bound::(); let inst = typeobj.call((), None).unwrap(); let obj = inst.downcast::().unwrap(); let mut obj_ref_mut = obj.borrow_mut(); obj_ref_mut.data = Some(Arc::clone(&drop_called1)); let base: &mut BaseClassWithDrop = obj_ref_mut.as_mut(); base.data = Some(Arc::clone(&drop_called2)); }); assert!(drop_called1.load(Ordering::Relaxed)); assert!(drop_called2.load(Ordering::Relaxed)); } #[pyclass] struct TraversableClass { traversed: AtomicBool, } impl TraversableClass { fn new() -> Self { Self { traversed: AtomicBool::new(false), } } } #[pymethods] impl TraversableClass { fn __clear__(&mut self) {} #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.traversed.store(true, Ordering::Relaxed); Ok(()) } } #[test] fn gc_during_borrow() { Python::with_gil(|py| { unsafe { // get the traverse function let ty = py.get_type_bound::(); let traverse = get_type_traverse(ty.as_type_ptr()).unwrap(); // create an object and check that traversing it works normally // when it's not borrowed let cell = Bound::new(py, TraversableClass::new()).unwrap(); let obj = cell.to_object(py); assert!(!cell.borrow().traversed.load(Ordering::Relaxed)); traverse(obj.as_ptr(), novisit, std::ptr::null_mut()); assert!(cell.borrow().traversed.load(Ordering::Relaxed)); // create an object and check that it is not traversed if the GC // is invoked while it is already borrowed mutably let cell2 = Bound::new(py, TraversableClass::new()).unwrap(); let obj2 = cell2.to_object(py); let guard = cell2.borrow_mut(); assert!(!guard.traversed.load(Ordering::Relaxed)); traverse(obj2.as_ptr(), novisit, std::ptr::null_mut()); assert!(!guard.traversed.load(Ordering::Relaxed)); drop(guard); } }); } #[pyclass] struct PartialTraverse { member: PyObject, } impl PartialTraverse { fn new(py: Python<'_>) -> Self { Self { member: py.None() } } } #[pymethods] impl PartialTraverse { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.member)?; // In the test, we expect this to never be hit unreachable!() } } #[test] fn traverse_partial() { Python::with_gil(|py| unsafe { // get the traverse function let ty = py.get_type_bound::(); let traverse = get_type_traverse(ty.as_type_ptr()).unwrap(); // confirm that traversing errors let obj = Py::new(py, PartialTraverse::new(py)).unwrap(); assert_eq!( traverse(obj.as_ptr(), visit_error, std::ptr::null_mut()), -1 ); }) } #[pyclass] struct PanickyTraverse { member: PyObject, } impl PanickyTraverse { fn new(py: Python<'_>) -> Self { Self { member: py.None() } } } #[pymethods] impl PanickyTraverse { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(&self.member)?; panic!("at the disco"); } } #[test] fn traverse_panic() { Python::with_gil(|py| unsafe { // get the traverse function let ty = py.get_type_bound::(); let traverse = get_type_traverse(ty.as_type_ptr()).unwrap(); // confirm that traversing errors let obj = Py::new(py, PanickyTraverse::new(py)).unwrap(); assert_eq!(traverse(obj.as_ptr(), novisit, std::ptr::null_mut()), -1); }) } #[pyclass] struct TriesGILInTraverse {} #[pymethods] impl TriesGILInTraverse { fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { Python::with_gil(|_py| Ok(())) } } #[test] fn tries_gil_in_traverse() { Python::with_gil(|py| unsafe { // get the traverse function let ty = py.get_type_bound::(); let traverse = get_type_traverse(ty.as_type_ptr()).unwrap(); // confirm that traversing panicks let obj = Py::new(py, TriesGILInTraverse {}).unwrap(); assert_eq!(traverse(obj.as_ptr(), novisit, std::ptr::null_mut()), -1); }) } #[pyclass] struct HijackedTraverse { traversed: Cell, hijacked: Cell, } impl HijackedTraverse { fn new() -> Self { Self { traversed: Cell::new(false), hijacked: Cell::new(false), } } fn traversed_and_hijacked(&self) -> (bool, bool) { (self.traversed.get(), self.hijacked.get()) } } #[pymethods] impl HijackedTraverse { #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.traversed.set(true); Ok(()) } } #[allow(dead_code)] trait Traversable { fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>; } impl<'a> Traversable for PyRef<'a, HijackedTraverse> { fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.hijacked.set(true); Ok(()) } } #[test] fn traverse_cannot_be_hijacked() { Python::with_gil(|py| unsafe { // get the traverse function let ty = py.get_type_bound::(); let traverse = get_type_traverse(ty.as_type_ptr()).unwrap(); let cell = Bound::new(py, HijackedTraverse::new()).unwrap(); let obj = cell.to_object(py); assert_eq!(cell.borrow().traversed_and_hijacked(), (false, false)); traverse(obj.as_ptr(), novisit, std::ptr::null_mut()); assert_eq!(cell.borrow().traversed_and_hijacked(), (true, false)); }) } #[allow(dead_code)] #[pyclass] struct DropDuringTraversal { cycle: Cell>>, dropped: TestDropCall, } #[pymethods] impl DropDuringTraversal { #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.cycle.take(); Ok(()) } fn __clear__(&mut self) { self.cycle.take(); } } #[cfg(not(pyo3_disable_reference_pool))] #[test] fn drop_during_traversal_with_gil() { let drop_called = Arc::new(AtomicBool::new(false)); Python::with_gil(|py| { let inst = Py::new( py, DropDuringTraversal { cycle: Cell::new(None), dropped: TestDropCall { drop_called: Arc::clone(&drop_called), }, }, ) .unwrap(); inst.borrow_mut(py).cycle.set(Some(inst.clone_ref(py))); drop(inst); }); // due to the internal GC mechanism, we may need multiple // (but not too many) collections to get `inst` actually dropped. for _ in 0..10 { Python::with_gil(|py| { py.run_bound("import gc; gc.collect()", None, None).unwrap(); }); } assert!(drop_called.load(Ordering::Relaxed)); } #[cfg(not(pyo3_disable_reference_pool))] #[test] fn drop_during_traversal_without_gil() { let drop_called = Arc::new(AtomicBool::new(false)); let inst = Python::with_gil(|py| { let inst = Py::new( py, DropDuringTraversal { cycle: Cell::new(None), dropped: TestDropCall { drop_called: Arc::clone(&drop_called), }, }, ) .unwrap(); inst.borrow_mut(py).cycle.set(Some(inst.clone_ref(py))); inst }); drop(inst); // due to the internal GC mechanism, we may need multiple // (but not too many) collections to get `inst` actually dropped. for _ in 0..10 { Python::with_gil(|py| { py.run_bound("import gc; gc.collect()", None, None).unwrap(); }); } assert!(drop_called.load(Ordering::Relaxed)); } #[pyclass(unsendable)] struct UnsendableTraversal { traversed: Cell, } #[pymethods] impl UnsendableTraversal { fn __clear__(&mut self) {} #[allow(clippy::unnecessary_wraps)] fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> { self.traversed.set(true); Ok(()) } } #[test] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled fn unsendable_are_not_traversed_on_foreign_thread() { #[derive(Clone, Copy)] struct SendablePtr(*mut pyo3::ffi::PyObject); unsafe impl Send for SendablePtr {} Python::with_gil(|py| unsafe { let ty = py.get_type_bound::(); let traverse = get_type_traverse(ty.as_type_ptr()).unwrap(); let obj = Py::new( py, UnsendableTraversal { traversed: Cell::new(false), }, ) .unwrap(); let ptr = SendablePtr(obj.as_ptr()); std::thread::spawn(move || { // traversal on foreign thread is a no-op assert_eq!(traverse({ ptr }.0, novisit, std::ptr::null_mut()), 0); }) .join() .unwrap(); assert!(!obj.borrow(py).traversed.get()); // traversal on home thread still works assert_eq!(traverse({ ptr }.0, novisit, std::ptr::null_mut()), 0); assert!(obj.borrow(py).traversed.get()); }); } // Manual traversal utilities unsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option { std::mem::transmute(pyo3::ffi::PyType_GetSlot(tp, pyo3::ffi::Py_tp_traverse)) } // a dummy visitor function extern "C" fn novisit( _object: *mut pyo3::ffi::PyObject, _arg: *mut core::ffi::c_void, ) -> std::os::raw::c_int { 0 } // a visitor function which errors (returns nonzero code) extern "C" fn visit_error( _object: *mut pyo3::ffi::PyObject, _arg: *mut core::ffi::c_void, ) -> std::os::raw::c_int { -1 } pyo3/tests/test_module.rs0000644000175000017500000003032114661133735016466 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::py_run; use pyo3::types::PyString; use pyo3::types::{IntoPyDict, PyDict, PyTuple}; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct AnonClass {} #[pyclass] struct ValueClass { value: usize, } #[pymethods] impl ValueClass { #[new] fn new(value: usize) -> ValueClass { ValueClass { value } } } #[pyclass(module = "module")] struct LocatedClass {} #[pyfunction] /// Doubles the given value fn double(x: usize) -> usize { x * 2 } /// This module is implemented in Rust. #[pymodule] fn module_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m)] #[pyo3(name = "no_parameters")] fn function_with_name() -> usize { 42 } #[pyfn(m)] #[pyo3(pass_module)] fn with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult> { module.name() } #[pyfn(m)] fn double_value(v: &ValueClass) -> usize { v.value * 2 } m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add("foo", "bar")?; m.add_function(wrap_pyfunction!(double, m)?)?; m.add("also_double", wrap_pyfunction!(double, m)?)?; Ok(()) } #[test] fn test_module_with_functions() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let d = [( "module_with_functions", wrap_pymodule!(module_with_functions)(py), )] .into_py_dict_bound(py); py_assert!( py, *d, "module_with_functions.__doc__ == 'This module is implemented in Rust.'" ); py_assert!(py, *d, "module_with_functions.no_parameters() == 42"); py_assert!(py, *d, "module_with_functions.foo == 'bar'"); py_assert!(py, *d, "module_with_functions.AnonClass != None"); py_assert!(py, *d, "module_with_functions.LocatedClass != None"); py_assert!( py, *d, "module_with_functions.LocatedClass.__module__ == 'module'" ); py_assert!(py, *d, "module_with_functions.double(3) == 6"); py_assert!( py, *d, "module_with_functions.double.__doc__ == 'Doubles the given value'" ); py_assert!(py, *d, "module_with_functions.also_double(3) == 6"); py_assert!( py, *d, "module_with_functions.also_double.__doc__ == 'Doubles the given value'" ); py_assert!( py, *d, "module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2" ); py_assert!( py, *d, "module_with_functions.with_module() == 'module_with_functions'" ); }); } /// This module uses a legacy two-argument module function. #[pymodule] fn module_with_explicit_py_arg(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(double, m)?)?; Ok(()) } #[test] fn test_module_with_explicit_py_arg() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let d = [( "module_with_explicit_py_arg", wrap_pymodule!(module_with_explicit_py_arg)(py), )] .into_py_dict_bound(py); py_assert!(py, *d, "module_with_explicit_py_arg.double(3) == 6"); }); } #[pymodule(name = "other_name")] fn some_name(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add("other_name", "other_name")?; Ok(()) } #[test] fn test_module_renaming() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let d = [("different_name", wrap_pymodule!(some_name)(py))].into_py_dict_bound(py); py_run!(py, *d, "assert different_name.__name__ == 'other_name'"); }); } #[test] fn test_module_from_code_bound() { Python::with_gil(|py| { let adder_mod = PyModule::from_code_bound( py, "def add(a,b):\n\treturn a+b", "adder_mod.py", "adder_mod", ) .expect("Module code should be loaded"); let add_func = adder_mod .getattr("add") .expect("Add function should be in the module") .to_object(py); let ret_value: i32 = add_func .call1(py, (1, 2)) .expect("A value should be returned") .extract(py) .expect("The value should be able to be converted to an i32"); assert_eq!(ret_value, 3); }); } #[pyfunction] fn r#move() -> usize { 42 } #[pymodule] fn raw_ident_module(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(r#move, module)?) } #[test] fn test_raw_idents() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let module = wrap_pymodule!(raw_ident_module)(py); py_assert!(py, module, "module.move() == 42"); }); } #[pyfunction] #[pyo3(name = "foobar")] fn custom_named_fn() -> usize { 42 } #[test] fn test_custom_names() { #[pymodule] fn custom_names(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?; Ok(()) } Python::with_gil(|py| { let module = pyo3::wrap_pymodule!(custom_names)(py); py_assert!(py, module, "not hasattr(module, 'custom_named_fn')"); py_assert!(py, module, "module.foobar() == 42"); }); } #[test] fn test_module_dict() { #[pymodule] fn module_dict(m: &Bound<'_, PyModule>) -> PyResult<()> { m.dict().set_item("yay", "me")?; Ok(()) } Python::with_gil(|py| { let module = pyo3::wrap_pymodule!(module_dict)(py); py_assert!(py, module, "module.yay == 'me'"); }); } #[test] fn test_module_dunder_all() { Python::with_gil(|py| { #[pymodule] fn dunder_all(m: &Bound<'_, PyModule>) -> PyResult<()> { m.dict().set_item("yay", "me")?; m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?; Ok(()) } let module = pyo3::wrap_pymodule!(dunder_all)(py); py_assert!(py, module, "module.__all__ == ['foobar']"); }); } #[pyfunction] fn subfunction() -> String { "Subfunction".to_string() } fn submodule(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(subfunction, module)?)?; Ok(()) } #[pymodule] fn submodule_with_init_fn(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(subfunction, module)?)?; Ok(()) } #[pyfunction] fn superfunction() -> String { "Superfunction".to_string() } #[pymodule] fn supermodule(module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(wrap_pyfunction!(superfunction, module)?)?; let module_to_add = PyModule::new_bound(module.py(), "submodule")?; submodule(&module_to_add)?; module.add_submodule(&module_to_add)?; let module_to_add = PyModule::new_bound(module.py(), "submodule_with_init_fn")?; submodule_with_init_fn(&module_to_add)?; module.add_submodule(&module_to_add)?; Ok(()) } #[test] fn test_module_nesting() { use pyo3::wrap_pymodule; Python::with_gil(|py| { let supermodule = wrap_pymodule!(supermodule)(py); py_assert!( py, supermodule, "supermodule.superfunction() == 'Superfunction'" ); py_assert!( py, supermodule, "supermodule.submodule.subfunction() == 'Subfunction'" ); py_assert!( py, supermodule, "supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'" ); }); } // Test that argument parsing specification works for pyfunctions #[pyfunction(signature = (a=5, *args))] fn ext_vararg_fn(py: Python<'_>, a: i32, args: &Bound<'_, PyTuple>) -> PyObject { [a.to_object(py), args.into_py(py)].to_object(py) } #[pymodule] fn vararg_module(m: &Bound<'_, PyModule>) -> PyResult<()> { #[pyfn(m, signature = (a=5, *args))] fn int_vararg_fn(py: Python<'_>, a: i32, args: &Bound<'_, PyTuple>) -> PyObject { ext_vararg_fn(py, a, args) } m.add_function(wrap_pyfunction!(ext_vararg_fn, m)?).unwrap(); Ok(()) } #[test] fn test_vararg_module() { Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(vararg_module)(py); py_assert!(py, m, "m.ext_vararg_fn() == [5, ()]"); py_assert!(py, m, "m.ext_vararg_fn(1, 2) == [1, (2,)]"); py_assert!(py, m, "m.int_vararg_fn() == [5, ()]"); py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]"); }); } #[test] fn test_module_with_constant() { // Regression test for #1102 #[pymodule] fn module_with_constant(m: &Bound<'_, PyModule>) -> PyResult<()> { const ANON: AnonClass = AnonClass {}; m.add("ANON", ANON)?; m.add_class::()?; Ok(()) } Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(module_with_constant)(py); py_assert!(py, m, "isinstance(m.ANON, m.AnonClass)"); }); } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult> { module.name() } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module_owned( module: Py, py: Python<'_>, ) -> PyResult> { module.bind(py).name() } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module_and_py<'py>( module: &Bound<'py, PyModule>, _python: Python<'py>, ) -> PyResult> { module.name() } #[pyfunction] #[pyo3(pass_module)] fn pyfunction_with_module_and_arg<'py>( module: &Bound<'py, PyModule>, string: String, ) -> PyResult<(Bound<'py, PyString>, String)> { module.name().map(|s| (s, string)) } #[pyfunction(signature = (string="foo"))] #[pyo3(pass_module)] fn pyfunction_with_module_and_default_arg<'py>( module: &Bound<'py, PyModule>, string: &str, ) -> PyResult<(Bound<'py, PyString>, String)> { module.name().map(|s| (s, string.into())) } #[pyfunction(signature = (*args, **kwargs))] #[pyo3(pass_module)] fn pyfunction_with_module_and_args_kwargs<'py>( module: &Bound<'py, PyModule>, args: &Bound<'py, PyTuple>, kwargs: Option<&Bound<'py, PyDict>>, ) -> PyResult<(Bound<'py, PyString>, usize, Option)> { module .name() .map(|s| (s, args.len(), kwargs.map(|d| d.len()))) } #[pymodule] fn module_with_functions_with_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_owned, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_py, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_arg, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_default_arg, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module_and_args_kwargs, m)?)?; m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?; Ok(()) } #[test] fn test_module_functions_with_module() { Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py); py_assert!( py, m, "m.pyfunction_with_module() == 'module_with_functions_with_module'" ); py_assert!( py, m, "m.pyfunction_with_module_owned() == 'module_with_functions_with_module'" ); py_assert!( py, m, "m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'" ); py_assert!( py, m, "m.pyfunction_with_module_and_default_arg() \ == ('module_with_functions_with_module', 'foo')" ); py_assert!( py, m, "m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \ == ('module_with_functions_with_module', 1, 2)" ); }); } #[test] fn test_module_doc_hidden() { #[doc(hidden)] #[allow(clippy::unnecessary_wraps)] #[pymodule] fn my_module(_m: &Bound<'_, PyModule>) -> PyResult<()> { Ok(()) } Python::with_gil(|py| { let m = pyo3::wrap_pymodule!(my_module)(py); py_assert!(py, m, "m.__doc__ == ''"); }) } pyo3/tests/test_coroutine.rs0000644000175000017500000002233714661133735017220 0ustar jamespagejamespage#![cfg(feature = "experimental-async")] #![cfg(not(target_arch = "wasm32"))] use std::{task::Poll, thread, time::Duration}; use futures::{channel::oneshot, future::poll_fn, FutureExt}; #[cfg(not(target_has_atomic = "64"))] use portable_atomic::{AtomicBool, Ordering}; use pyo3::{ coroutine::CancelHandle, prelude::*, py_run, types::{IntoPyDict, PyType}, }; #[cfg(target_has_atomic = "64")] use std::sync::atomic::{AtomicBool, Ordering}; #[path = "../src/tests/common.rs"] mod common; fn handle_windows(test: &str) -> String { let set_event_loop_policy = r#" import asyncio, sys if sys.platform == "win32": asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) "#; pyo3::unindent::unindent(set_event_loop_policy) + &pyo3::unindent::unindent(test) } #[test] fn noop_coroutine() { #[pyfunction] async fn noop() -> usize { 42 } Python::with_gil(|gil| { let noop = wrap_pyfunction_bound!(noop, gil).unwrap(); let test = "import asyncio; assert asyncio.run(noop()) == 42"; py_run!(gil, noop, &handle_windows(test)); }) } #[test] fn test_coroutine_qualname() { #[pyfunction] async fn my_fn() {} #[pyclass] struct MyClass; #[pymethods] impl MyClass { #[new] fn new() -> Self { Self } // TODO use &self when possible async fn my_method(_self: Py) {} #[classmethod] async fn my_classmethod(_cls: Py) {} #[staticmethod] async fn my_staticmethod() {} } Python::with_gil(|gil| { let test = r#" for coro, name, qualname in [ (my_fn(), "my_fn", "my_fn"), (MyClass().my_method(), "my_method", "MyClass.my_method"), #(MyClass().my_classmethod(), "my_classmethod", "MyClass.my_classmethod"), (MyClass.my_staticmethod(), "my_staticmethod", "MyClass.my_staticmethod"), ]: assert coro.__name__ == name and coro.__qualname__ == qualname "#; let locals = [ ( "my_fn", wrap_pyfunction_bound!(my_fn, gil) .unwrap() .as_borrowed() .as_any(), ), ("MyClass", gil.get_type_bound::().as_any()), ] .into_py_dict_bound(gil); py_run!(gil, *locals, &handle_windows(test)); }) } #[test] fn sleep_0_like_coroutine() { #[pyfunction] async fn sleep_0() -> usize { let mut waken = false; poll_fn(|cx| { if !waken { cx.waker().wake_by_ref(); waken = true; return Poll::Pending; } Poll::Ready(42) }) .await } Python::with_gil(|gil| { let sleep_0 = wrap_pyfunction_bound!(sleep_0, gil).unwrap(); let test = "import asyncio; assert asyncio.run(sleep_0()) == 42"; py_run!(gil, sleep_0, &handle_windows(test)); }) } #[pyfunction] async fn sleep(seconds: f64) -> usize { let (tx, rx) = oneshot::channel(); thread::spawn(move || { thread::sleep(Duration::from_secs_f64(seconds)); tx.send(42).unwrap(); }); rx.await.unwrap() } #[test] fn sleep_coroutine() { Python::with_gil(|gil| { let sleep = wrap_pyfunction_bound!(sleep, gil).unwrap(); let test = r#"import asyncio; assert asyncio.run(sleep(0.1)) == 42"#; py_run!(gil, sleep, &handle_windows(test)); }) } #[test] fn cancelled_coroutine() { Python::with_gil(|gil| { let sleep = wrap_pyfunction_bound!(sleep, gil).unwrap(); let test = r#" import asyncio async def main(): task = asyncio.create_task(sleep(999)) await asyncio.sleep(0) task.cancel() await task asyncio.run(main()) "#; let globals = gil.import_bound("__main__").unwrap().dict(); globals.set_item("sleep", sleep).unwrap(); let err = gil .run_bound( &pyo3::unindent::unindent(&handle_windows(test)), Some(&globals), None, ) .unwrap_err(); assert_eq!( err.value_bound(gil).get_type().qualname().unwrap(), "CancelledError" ); }) } #[test] fn coroutine_cancel_handle() { #[pyfunction] async fn cancellable_sleep( seconds: f64, #[pyo3(cancel_handle)] mut cancel: CancelHandle, ) -> usize { futures::select! { _ = sleep(seconds).fuse() => 42, _ = cancel.cancelled().fuse() => 0, } } Python::with_gil(|gil| { let cancellable_sleep = wrap_pyfunction_bound!(cancellable_sleep, gil).unwrap(); let test = r#" import asyncio; async def main(): task = asyncio.create_task(cancellable_sleep(999)) await asyncio.sleep(0) task.cancel() return await task assert asyncio.run(main()) == 0 "#; let globals = gil.import_bound("__main__").unwrap().dict(); globals .set_item("cancellable_sleep", cancellable_sleep) .unwrap(); gil.run_bound( &pyo3::unindent::unindent(&handle_windows(test)), Some(&globals), None, ) .unwrap(); }) } #[test] fn coroutine_is_cancelled() { #[pyfunction] async fn sleep_loop(#[pyo3(cancel_handle)] cancel: CancelHandle) { while !cancel.is_cancelled() { sleep(0.001).await; } } Python::with_gil(|gil| { let sleep_loop = wrap_pyfunction_bound!(sleep_loop, gil).unwrap(); let test = r#" import asyncio; async def main(): task = asyncio.create_task(sleep_loop()) await asyncio.sleep(0) task.cancel() await task asyncio.run(main()) "#; let globals = gil.import_bound("__main__").unwrap().dict(); globals.set_item("sleep_loop", sleep_loop).unwrap(); gil.run_bound( &pyo3::unindent::unindent(&handle_windows(test)), Some(&globals), None, ) .unwrap(); }) } #[test] fn coroutine_panic() { #[pyfunction] async fn panic() { panic!("test panic"); } Python::with_gil(|gil| { let panic = wrap_pyfunction_bound!(panic, gil).unwrap(); let test = r#" import asyncio coro = panic() try: asyncio.run(coro) except BaseException as err: assert type(err).__name__ == "PanicException" assert str(err) == "test panic" else: assert False try: coro.send(None) except RuntimeError as err: assert str(err) == "cannot reuse already awaited coroutine" else: assert False; "#; py_run!(gil, panic, &handle_windows(test)); }) } #[test] fn test_async_method_receiver() { #[pyclass] struct Counter(usize); #[pymethods] impl Counter { #[new] fn new() -> Self { Self(0) } async fn get(&self) -> usize { self.0 } async fn incr(&mut self) -> usize { self.0 += 1; self.0 } } static IS_DROPPED: AtomicBool = AtomicBool::new(false); impl Drop for Counter { fn drop(&mut self) { IS_DROPPED.store(true, Ordering::SeqCst); } } Python::with_gil(|gil| { let test = r#" import asyncio obj = Counter() coro1 = obj.get() coro2 = obj.get() try: obj.incr() # borrow checking should fail except RuntimeError as err: pass else: assert False assert asyncio.run(coro1) == 0 coro2.close() coro3 = obj.incr() try: obj.incr() # borrow checking should fail except RuntimeError as err: pass else: assert False try: obj.get() # borrow checking should fail except RuntimeError as err: pass else: assert False assert asyncio.run(coro3) == 1 "#; let locals = [("Counter", gil.get_type_bound::())].into_py_dict_bound(gil); py_run!(gil, *locals, test); }); assert!(IS_DROPPED.load(Ordering::SeqCst)); } #[test] fn test_async_method_receiver_with_other_args() { #[pyclass] struct Value(i32); #[pymethods] impl Value { #[new] fn new() -> Self { Self(0) } async fn get_value_plus_with(&self, v1: i32, v2: i32) -> i32 { self.0 + v1 + v2 } async fn set_value(&mut self, new_value: i32) -> i32 { self.0 = new_value; self.0 } } Python::with_gil(|gil| { let test = r#" import asyncio v = Value() assert asyncio.run(v.get_value_plus_with(3, 0)) == 3 assert asyncio.run(v.set_value(10)) == 10 assert asyncio.run(v.get_value_plus_with(1, 1)) == 12 "#; let locals = [("Value", gil.get_type_bound::())].into_py_dict_bound(gil); py_run!(gil, *locals, test); }); } pyo3/tests/test_bytes.rs0000644000175000017500000000247414661133735016337 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; use pyo3::types::PyBytes; #[path = "../src/tests/common.rs"] mod common; #[pyfunction] fn bytes_pybytes_conversion(bytes: &[u8]) -> &[u8] { bytes } #[test] fn test_pybytes_bytes_conversion() { Python::with_gil(|py| { let f = wrap_pyfunction_bound!(bytes_pybytes_conversion)(py).unwrap(); py_assert!(py, f, "f(b'Hello World') == b'Hello World'"); }); } #[pyfunction] fn bytes_vec_conversion(py: Python<'_>, bytes: Vec) -> Bound<'_, PyBytes> { PyBytes::new_bound(py, bytes.as_slice()) } #[test] fn test_pybytes_vec_conversion() { Python::with_gil(|py| { let f = wrap_pyfunction_bound!(bytes_vec_conversion)(py).unwrap(); py_assert!(py, f, "f(b'Hello World') == b'Hello World'"); }); } #[test] fn test_bytearray_vec_conversion() { Python::with_gil(|py| { let f = wrap_pyfunction_bound!(bytes_vec_conversion)(py).unwrap(); py_assert!(py, f, "f(bytearray(b'Hello World')) == b'Hello World'"); }); } #[test] fn test_py_as_bytes() { let pyobj: pyo3::Py = Python::with_gil(|py| pyo3::types::PyBytes::new_bound(py, b"abc").unbind()); let data = Python::with_gil(|py| pyobj.as_bytes(py)); assert_eq!(data, b"abc"); Python::with_gil(move |_py| drop(pyobj)); } pyo3/tests/test_sequence.rs0000644000175000017500000002201014661133735017005 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::exceptions::{PyIndexError, PyValueError}; use pyo3::types::{IntoPyDict, PyList, PyMapping, PySequence}; use pyo3::{ffi, prelude::*}; use pyo3::py_run; #[path = "../src/tests/common.rs"] mod common; #[pyclass] struct ByteSequence { elements: Vec, } #[pymethods] impl ByteSequence { #[new] #[pyo3(signature=(elements = None))] fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult { if let Some(pylist) = elements { let mut elems = Vec::with_capacity(pylist.len()); for pyelem in pylist { let elem = pyelem.extract()?; elems.push(elem); } Ok(Self { elements: elems }) } else { Ok(Self { elements: Vec::new(), }) } } fn __len__(&self) -> usize { self.elements.len() } fn __getitem__(&self, idx: isize) -> PyResult { self.elements .get(idx as usize) .copied() .ok_or_else(|| PyIndexError::new_err("list index out of range")) } fn __setitem__(&mut self, idx: isize, value: u8) { self.elements[idx as usize] = value; } fn __delitem__(&mut self, mut idx: isize) -> PyResult<()> { let self_len = self.elements.len() as isize; if idx < 0 { idx += self_len; } if (idx < self_len) && (idx >= 0) { self.elements.remove(idx as usize); Ok(()) } else { Err(PyIndexError::new_err("list index out of range")) } } fn __contains__(&self, other: &Bound<'_, PyAny>) -> bool { match other.extract::() { Ok(x) => self.elements.contains(&x), Err(_) => false, } } fn __concat__(&self, other: &Self) -> Self { let mut elements = self.elements.clone(); elements.extend_from_slice(&other.elements); Self { elements } } fn __inplace_concat__(mut slf: PyRefMut<'_, Self>, other: &Self) -> Py { slf.elements.extend_from_slice(&other.elements); slf.into() } fn __repeat__(&self, count: isize) -> PyResult { if count >= 0 { let mut elements = Vec::with_capacity(self.elements.len() * count as usize); for _ in 0..count { elements.extend(&self.elements); } Ok(Self { elements }) } else { Err(PyValueError::new_err("invalid repeat count")) } } fn __inplace_repeat__(mut slf: PyRefMut<'_, Self>, count: isize) -> PyResult> { if count >= 0 { let mut elements = Vec::with_capacity(slf.elements.len() * count as usize); for _ in 0..count { elements.extend(&slf.elements); } slf.elements = elements; Ok(slf.into()) } else { Err(PyValueError::new_err("invalid repeat count")) } } } /// Return a dict with `s = ByteSequence([1, 2, 3])`. fn seq_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> { let d = [("ByteSequence", py.get_type_bound::())].into_py_dict_bound(py); // Though we can construct `s` in Rust, let's test `__new__` works. py_run!(py, *d, "s = ByteSequence([1, 2, 3])"); d } #[test] fn test_getitem() { Python::with_gil(|py| { let d = seq_dict(py); py_assert!(py, *d, "s[0] == 1"); py_assert!(py, *d, "s[1] == 2"); py_assert!(py, *d, "s[2] == 3"); py_expect_exception!(py, *d, "print(s[-4])", PyIndexError); py_expect_exception!(py, *d, "print(s[4])", PyIndexError); }); } #[test] fn test_setitem() { Python::with_gil(|py| { let d = seq_dict(py); py_run!(py, *d, "s[0] = 4; assert list(s) == [4, 2, 3]"); py_expect_exception!(py, *d, "s[0] = 'hello'", PyTypeError); }); } #[test] fn test_delitem() { Python::with_gil(|py| { let d = [("ByteSequence", py.get_type_bound::())].into_py_dict_bound(py); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]" ); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]" ); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]" ); py_run!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]" ); py_expect_exception!( py, *d, "s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))", PyIndexError ); py_expect_exception!( py, *d, "s = ByteSequence([1, 2, 3]); del s[4]", PyIndexError ); }); } #[test] fn test_contains() { Python::with_gil(|py| { let d = seq_dict(py); py_assert!(py, *d, "1 in s"); py_assert!(py, *d, "2 in s"); py_assert!(py, *d, "3 in s"); py_assert!(py, *d, "4 not in s"); py_assert!(py, *d, "'hello' not in s"); }); } #[test] fn test_concat() { Python::with_gil(|py| { let d = seq_dict(py); py_run!( py, *d, "s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]" ); py_expect_exception!( py, *d, "s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2", PyTypeError ); }); } #[test] fn test_inplace_concat() { Python::with_gil(|py| { let d = seq_dict(py); py_run!( py, *d, "s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]" ); py_expect_exception!(py, *d, "s += 'hello'", PyTypeError); }); } #[test] fn test_repeat() { Python::with_gil(|py| { let d = seq_dict(py); py_run!(py, *d, "s2 = s * 2; assert list(s2) == [1, 2, 3, 1, 2, 3]"); py_expect_exception!(py, *d, "s2 = s * -1", PyValueError); }); } #[test] fn test_inplace_repeat() { Python::with_gil(|py| { let d = [("ByteSequence", py.get_type_bound::())].into_py_dict_bound(py); py_run!( py, *d, "s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]" ); py_expect_exception!(py, *d, "s = ByteSequence([1, 2]); s *= -1", PyValueError); }); } // Check that #[pyo3(get, set)] works correctly for Vec #[pyclass] struct GenericList { #[pyo3(get, set)] items: Vec, } #[test] fn test_generic_list_get() { Python::with_gil(|py| { let list: PyObject = GenericList { items: [1, 2, 3].iter().map(|i| i.to_object(py)).collect(), } .into_py(py); py_assert!(py, list, "list.items == [1, 2, 3]"); }); } #[test] fn test_generic_list_set() { Python::with_gil(|py| { let list = Bound::new(py, GenericList { items: vec![] }).unwrap(); py_run!(py, list, "list.items = [1, 2, 3]"); assert!(list .borrow() .items .iter() .zip(&[1u32, 2, 3]) .all(|(a, b)| a.bind(py).eq(b.into_py(py)).unwrap())); }); } #[pyclass(sequence)] struct OptionList { #[pyo3(get, set)] items: Vec>, } #[pymethods] impl OptionList { fn __len__(&self) -> usize { self.items.len() } fn __getitem__(&self, idx: isize) -> PyResult> { match self.items.get(idx as usize) { Some(x) => Ok(*x), None => Err(PyIndexError::new_err("Index out of bounds")), } } } #[test] fn test_option_list_get() { // Regression test for #798 Python::with_gil(|py| { let list = Py::new( py, OptionList { items: vec![Some(1), None], }, ) .unwrap(); py_assert!(py, list, "list[0] == 1"); py_assert!(py, list, "list[1] == None"); py_expect_exception!(py, list, "list[2]", PyIndexError); }); } #[test] fn sequence_is_not_mapping() { Python::with_gil(|py| { let list = Bound::new( py, OptionList { items: vec![Some(1), None], }, ) .unwrap() .into_any(); PySequence::register::(py).unwrap(); assert!(list.downcast::().is_err()); assert!(list.downcast::().is_ok()); }) } #[test] fn sequence_length() { Python::with_gil(|py| { let list = Bound::new( py, OptionList { items: vec![Some(1), None], }, ) .unwrap() .into_any(); assert_eq!(list.len().unwrap(), 2); assert_eq!(unsafe { ffi::PySequence_Length(list.as_ptr()) }, 2); assert_eq!(unsafe { ffi::PyMapping_Length(list.as_ptr()) }, -1); unsafe { ffi::PyErr_Clear() }; }) } pyo3/tests/test_field_cfg.rs0000644000175000017500000000117214661133735017105 0ustar jamespagejamespage#![cfg(feature = "macros")] use pyo3::prelude::*; #[pyclass] struct CfgClass { #[pyo3(get, set)] #[cfg(any())] pub a: u32, #[pyo3(get, set)] // This is always true #[cfg(any( target_family = "unix", target_family = "windows", target_family = "wasm" ))] pub b: u32, } #[test] fn test_cfg() { Python::with_gil(|py| { let cfg = CfgClass { b: 3 }; let py_cfg = Py::new(py, cfg).unwrap(); assert!(py_cfg.bind(py).getattr("a").is_err()); let b: u32 = py_cfg.bind(py).getattr("b").unwrap().extract().unwrap(); assert_eq!(b, 3); }); } pyo3/tests/test_dict_iter.rs0000644000175000017500000000075314661133735017155 0ustar jamespagejamespageuse pyo3::prelude::*; use pyo3::types::IntoPyDict; #[test] #[cfg_attr(target_arch = "wasm32", ignore)] // Not sure why this fails. fn iter_dict_nosegv() { Python::with_gil(|py| { const LEN: usize = 10_000_000; let dict = (0..LEN as u64).map(|i| (i, i * 2)).into_py_dict_bound(py); let mut sum = 0; for (k, _v) in dict { let i: u64 = k.extract().unwrap(); sum += i; } assert_eq!(sum, 49_999_995_000_000); }); } pyo3/LICENSE-MIT0000644000175000017500000000212314661133735014065 0ustar jamespagejamespageCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3/src/0000775000175000017500000000000014661133735013224 5ustar jamespagejamespagepyo3/src/prelude.rs0000644000175000017500000000366014661133735015235 0ustar jamespagejamespage//! PyO3's prelude. //! //! The purpose of this module is to alleviate imports of many commonly used items of the PyO3 crate //! by adding a glob import to the top of pyo3 heavy modules: //! //! ``` //! # #![allow(unused_imports)] //! use pyo3::prelude::*; //! ``` pub use crate::conversion::{FromPyObject, IntoPy, ToPyObject}; #[cfg(feature = "gil-refs")] #[allow(deprecated)] pub use crate::conversion::{PyTryFrom, PyTryInto}; pub use crate::err::{PyErr, PyResult}; pub use crate::instance::{Borrowed, Bound, Py, PyObject}; pub use crate::marker::Python; #[cfg(feature = "gil-refs")] #[allow(deprecated)] pub use crate::pycell::PyCell; pub use crate::pycell::{PyRef, PyRefMut}; pub use crate::pyclass_init::PyClassInitializer; pub use crate::types::{PyAny, PyModule}; #[cfg(feature = "gil-refs")] pub use crate::PyNativeType; #[cfg(feature = "macros")] pub use pyo3_macros::{pyclass, pyfunction, pymethods, pymodule, FromPyObject}; #[cfg(feature = "macros")] pub use crate::{wrap_pyfunction, wrap_pyfunction_bound}; pub use crate::types::any::PyAnyMethods; pub use crate::types::boolobject::PyBoolMethods; pub use crate::types::bytearray::PyByteArrayMethods; pub use crate::types::bytes::PyBytesMethods; pub use crate::types::capsule::PyCapsuleMethods; pub use crate::types::complex::PyComplexMethods; pub use crate::types::dict::PyDictMethods; pub use crate::types::float::PyFloatMethods; pub use crate::types::frozenset::PyFrozenSetMethods; pub use crate::types::list::PyListMethods; pub use crate::types::mapping::PyMappingMethods; pub use crate::types::module::PyModuleMethods; pub use crate::types::sequence::PySequenceMethods; pub use crate::types::set::PySetMethods; pub use crate::types::slice::PySliceMethods; pub use crate::types::string::PyStringMethods; pub use crate::types::traceback::PyTracebackMethods; pub use crate::types::tuple::PyTupleMethods; pub use crate::types::typeobject::PyTypeMethods; pub use crate::types::weakref::PyWeakrefMethods; pyo3/src/marshal.rs0000644000175000017500000000646614661133735015233 0ustar jamespagejamespage#![cfg(not(Py_LIMITED_API))] //! Support for the Python `marshal` format. use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::types::{PyAny, PyBytes}; use crate::{ffi, Bound}; use crate::{AsPyPointer, PyResult, Python}; use std::os::raw::c_int; /// The current version of the marshal binary format. pub const VERSION: i32 = 4; /// Deprecated form of [`dumps_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`dumps` will be replaced by `dumps_bound` in a future PyO3 version" )] pub fn dumps<'py>( py: Python<'py>, object: &impl AsPyPointer, version: i32, ) -> PyResult<&'py PyBytes> { dumps_bound(py, object, version).map(Bound::into_gil_ref) } /// Serialize an object to bytes using the Python built-in marshal module. /// /// The built-in marshalling only supports a limited range of objects. /// The exact types supported depend on the version argument. /// The [`VERSION`] constant holds the highest version currently supported. /// /// See the [Python documentation](https://docs.python.org/3/library/marshal.html) for more details. /// /// # Examples /// ``` /// # use pyo3::{marshal, types::PyDict, prelude::PyDictMethods}; /// # pyo3::Python::with_gil(|py| { /// let dict = PyDict::new_bound(py); /// dict.set_item("aap", "noot").unwrap(); /// dict.set_item("mies", "wim").unwrap(); /// dict.set_item("zus", "jet").unwrap(); /// /// let bytes = marshal::dumps_bound(py, &dict, marshal::VERSION); /// # }); /// ``` pub fn dumps_bound<'py>( py: Python<'py>, object: &impl AsPyPointer, version: i32, ) -> PyResult> { unsafe { ffi::PyMarshal_WriteObjectToString(object.as_ptr(), version as c_int) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Deprecated form of [`loads_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`loads` will be replaced by `loads_bound` in a future PyO3 version" )] pub fn loads<'py, B>(py: Python<'py>, data: &B) -> PyResult<&'py PyAny> where B: AsRef<[u8]> + ?Sized, { loads_bound(py, data).map(Bound::into_gil_ref) } /// Deserialize an object from bytes using the Python built-in marshal module. pub fn loads_bound<'py, B>(py: Python<'py>, data: &B) -> PyResult> where B: AsRef<[u8]> + ?Sized, { let data = data.as_ref(); unsafe { ffi::PyMarshal_ReadObjectFromString(data.as_ptr().cast(), data.len() as isize) .assume_owned_or_err(py) } } #[cfg(test)] mod tests { use super::*; use crate::types::{bytes::PyBytesMethods, dict::PyDictMethods, PyDict}; #[test] fn marshal_roundtrip() { Python::with_gil(|py| { let dict = PyDict::new_bound(py); dict.set_item("aap", "noot").unwrap(); dict.set_item("mies", "wim").unwrap(); dict.set_item("zus", "jet").unwrap(); let pybytes = dumps_bound(py, &dict, VERSION).expect("marshalling failed"); let deserialized = loads_bound(py, pybytes.as_bytes()).expect("unmarshalling failed"); assert!(equal(py, &dict, &deserialized)); }); } fn equal(_py: Python<'_>, a: &impl AsPyPointer, b: &impl AsPyPointer) -> bool { unsafe { ffi::PyObject_RichCompareBool(a.as_ptr(), b.as_ptr(), ffi::Py_EQ) != 0 } } } pyo3/src/py_result_ext.rs0000644000175000017500000000125614661133735016502 0ustar jamespagejamespageuse crate::{types::any::PyAnyMethods, Bound, PyAny, PyResult, PyTypeCheck}; pub(crate) trait PyResultExt<'py>: crate::sealed::Sealed { fn downcast_into(self) -> PyResult>; unsafe fn downcast_into_unchecked(self) -> PyResult>; } impl<'py> PyResultExt<'py> for PyResult> { #[inline] fn downcast_into(self) -> PyResult> where { self.and_then(|instance| instance.downcast_into().map_err(Into::into)) } #[inline] unsafe fn downcast_into_unchecked(self) -> PyResult> { self.map(|instance| instance.downcast_into_unchecked()) } } pyo3/src/instance.rs0000644000175000017500000022706514661133735015410 0ustar jamespagejamespageuse crate::err::{self, PyErr, PyResult}; use crate::impl_::pycell::PyClassObject; use crate::internal_tricks::ptr_from_ref; use crate::pycell::{PyBorrowError, PyBorrowMutError}; use crate::pyclass::boolean_struct::{False, True}; #[cfg(feature = "gil-refs")] use crate::type_object::HasPyGilRef; use crate::types::{any::PyAnyMethods, string::PyStringMethods, typeobject::PyTypeMethods}; use crate::types::{DerefToPyAny, PyDict, PyString, PyTuple}; use crate::{ ffi, AsPyPointer, DowncastError, FromPyObject, IntoPy, PyAny, PyClass, PyClassInitializer, PyRef, PyRefMut, PyTypeInfo, Python, ToPyObject, }; use crate::{gil, PyTypeCheck}; use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::ops::Deref; use std::ptr::NonNull; /// Types that are built into the Python interpreter. /// /// PyO3 is designed in a way that all references to those types are bound /// to the GIL, which is why you can get a token from all references of those /// types. /// /// # Safety /// /// This trait must only be implemented for types which cannot be accessed without the GIL. #[cfg(feature = "gil-refs")] pub unsafe trait PyNativeType: Sized { /// The form of this which is stored inside a `Py` smart pointer. type AsRefSource: HasPyGilRef; /// Cast `&self` to a `Borrowed` smart pointer. /// /// `Borrowed` implements `Deref>`, so can also be used in locations /// where `Bound` is expected. /// /// This is available as a migration tool to adjust code from the deprecated "GIL Refs" /// API to the `Bound` smart pointer API. #[inline] fn as_borrowed(&self) -> Borrowed<'_, '_, Self::AsRefSource> { // Safety: &'py Self is expected to be a Python pointer, // so has the same layout as Borrowed<'py, 'py, T> Borrowed( unsafe { NonNull::new_unchecked(ptr_from_ref(self) as *mut _) }, PhantomData, self.py(), ) } /// Returns a GIL marker constrained to the lifetime of this type. #[inline] fn py(&self) -> Python<'_> { unsafe { Python::assume_gil_acquired() } } /// Cast `&PyAny` to `&Self` without no type checking. /// /// # Safety /// /// `obj` must have the same layout as `*const ffi::PyObject` and must be /// an instance of a type corresponding to `Self`. unsafe fn unchecked_downcast(obj: &PyAny) -> &Self { &*(obj.as_ptr() as *const Self) } } /// A GIL-attached equivalent to [`Py`]. /// /// This type can be thought of as equivalent to the tuple `(Py, Python<'py>)`. By having the `'py` /// lifetime of the [`Python<'py>`] token, this ties the lifetime of the [`Bound<'py, T>`] smart pointer /// to the lifetime of the GIL and allows PyO3 to call Python APIs at maximum efficiency. /// /// To access the object in situations where the GIL is not held, convert it to [`Py`] /// using [`.unbind()`][Bound::unbind]. This includes situations where the GIL is temporarily /// released, such as [`Python::allow_threads`](crate::Python::allow_threads)'s closure. /// /// See #[doc = concat!("[the guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/types.html#boundpy-t)")] /// for more detail. #[repr(transparent)] pub struct Bound<'py, T>(Python<'py>, ManuallyDrop>); impl<'py, T> Bound<'py, T> where T: PyClass, { /// Creates a new instance `Bound` of a `#[pyclass]` on the Python heap. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Foo {/* fields omitted */} /// /// # fn main() -> PyResult<()> { /// let foo: Py = Python::with_gil(|py| -> PyResult<_> { /// let foo: Bound<'_, Foo> = Bound::new(py, Foo {})?; /// Ok(foo.into()) /// })?; /// # Python::with_gil(move |_py| drop(foo)); /// # Ok(()) /// # } /// ``` pub fn new( py: Python<'py>, value: impl Into>, ) -> PyResult> { value.into().create_class_object(py) } } impl<'py> Bound<'py, PyAny> { /// Constructs a new `Bound<'py, PyAny>` from a pointer. Panics if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership #[inline] #[track_caller] pub unsafe fn from_owned_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { Self(py, ManuallyDrop::new(Py::from_owned_ptr(py, ptr))) } /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns `None` if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership #[inline] pub unsafe fn from_owned_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option { Py::from_owned_ptr_or_opt(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch` /// if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership #[inline] pub unsafe fn from_owned_ptr_or_err( py: Python<'py>, ptr: *mut ffi::PyObject, ) -> PyResult { Py::from_owned_ptr_or_err(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. /// Panics if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object #[inline] #[track_caller] pub unsafe fn from_borrowed_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { Self(py, ManuallyDrop::new(Py::from_borrowed_ptr(py, ptr))) } /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. /// Returns `None` if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null #[inline] pub unsafe fn from_borrowed_ptr_or_opt( py: Python<'py>, ptr: *mut ffi::PyObject, ) -> Option { Py::from_borrowed_ptr_or_opt(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference. /// Returns an `Err` by calling `PyErr::fetch` if `ptr` is null. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null #[inline] pub unsafe fn from_borrowed_ptr_or_err( py: Python<'py>, ptr: *mut ffi::PyObject, ) -> PyResult { Py::from_borrowed_ptr_or_err(py, ptr).map(|obj| Self(py, ManuallyDrop::new(obj))) } /// This slightly strange method is used to obtain `&Bound` from a pointer in macro code /// where we need to constrain the lifetime `'a` safely. /// /// Note that `'py` is required to outlive `'a` implicitly by the nature of the fact that /// `&'a Bound<'py>` means that `Bound<'py>` exists for at least the lifetime `'a`. /// /// # Safety /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a`. The `ptr` can /// be either a borrowed reference or an owned reference, it does not matter, as this is /// just `&Bound` there will never be any ownership transfer. #[inline] pub(crate) unsafe fn ref_from_ptr<'a>( _py: Python<'py>, ptr: &'a *mut ffi::PyObject, ) -> &'a Self { &*ptr_from_ref(ptr).cast::>() } /// Variant of the above which returns `None` for null pointers. /// /// # Safety /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a, or null. #[inline] pub(crate) unsafe fn ref_from_ptr_or_opt<'a>( _py: Python<'py>, ptr: &'a *mut ffi::PyObject, ) -> &'a Option { &*ptr_from_ref(ptr).cast::>>() } } impl<'py, T> Bound<'py, T> where T: PyClass, { /// Immutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRef`] exists. /// Multiple immutable borrows can be taken out at the same time. /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// # Examples /// /// ```rust /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?; /// let inner: &u8 = &foo.borrow().inner; /// /// assert_eq!(*inner, 73); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use /// [`try_borrow`](#method.try_borrow). #[inline] #[track_caller] pub fn borrow(&self) -> PyRef<'py, T> { PyRef::borrow(self) } /// Mutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRefMut`] exists. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?; /// foo.borrow_mut().inner = 35; /// /// assert_eq!(foo.borrow().inner, 35); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// Panics if the value is currently borrowed. For a non-panicking variant, use /// [`try_borrow_mut`](#method.try_borrow_mut). #[inline] #[track_caller] pub fn borrow_mut(&self) -> PyRefMut<'py, T> where T: PyClass, { PyRefMut::borrow(self) } /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed. /// /// The borrow lasts while the returned [`PyRef`] exists. /// /// This is the non-panicking variant of [`borrow`](#method.borrow). /// /// For frozen classes, the simpler [`get`][Self::get] is available. #[inline] pub fn try_borrow(&self) -> Result, PyBorrowError> { PyRef::try_borrow(self) } /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed. /// /// The borrow lasts while the returned [`PyRefMut`] exists. /// /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). #[inline] pub fn try_borrow_mut(&self) -> Result, PyBorrowMutError> where T: PyClass, { PyRefMut::try_borrow(self) } /// Provide an immutable borrow of the value `T` without acquiring the GIL. /// /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. /// /// # Examples /// /// ``` /// use std::sync::atomic::{AtomicUsize, Ordering}; /// # use pyo3::prelude::*; /// /// #[pyclass(frozen)] /// struct FrozenCounter { /// value: AtomicUsize, /// } /// /// Python::with_gil(|py| { /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; /// /// let py_counter = Bound::new(py, counter).unwrap(); /// /// py_counter.get().value.fetch_add(1, Ordering::Relaxed); /// }); /// ``` #[inline] pub fn get(&self) -> &T where T: PyClass + Sync, { self.1.get() } #[inline] pub(crate) fn get_class_object(&self) -> &PyClassObject { self.1.get_class_object() } } impl<'py, T> std::fmt::Debug for Bound<'py, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let any = self.as_any(); python_format(any, any.repr(), f) } } impl<'py, T> std::fmt::Display for Bound<'py, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { let any = self.as_any(); python_format(any, any.str(), f) } } fn python_format( any: &Bound<'_, PyAny>, format_result: PyResult>, f: &mut std::fmt::Formatter<'_>, ) -> Result<(), std::fmt::Error> { match format_result { Result::Ok(s) => return f.write_str(&s.to_string_lossy()), Result::Err(err) => err.write_unraisable_bound(any.py(), Some(any)), } match any.get_type().name() { Result::Ok(name) => std::write!(f, "", name), Result::Err(_err) => f.write_str(""), } } // The trait bound is needed to avoid running into the auto-deref recursion // limit (error[E0055]), because `Bound` would deref into itself. See: // https://github.com/rust-lang/rust/issues/19509 impl<'py, T> Deref for Bound<'py, T> where T: DerefToPyAny, { type Target = Bound<'py, PyAny>; #[inline] fn deref(&self) -> &Bound<'py, PyAny> { self.as_any() } } impl<'py, T> AsRef> for Bound<'py, T> { #[inline] fn as_ref(&self) -> &Bound<'py, PyAny> { self.as_any() } } impl Clone for Bound<'_, T> { #[inline] fn clone(&self) -> Self { Self(self.0, ManuallyDrop::new(self.1.clone_ref(self.0))) } } impl Drop for Bound<'_, T> { #[inline] fn drop(&mut self) { unsafe { ffi::Py_DECREF(self.as_ptr()) } } } impl<'py, T> Bound<'py, T> { /// Returns the GIL token associated with this object. #[inline] pub fn py(&self) -> Python<'py> { self.0 } /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.1.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { ManuallyDrop::new(self).as_ptr() } /// Helper to cast to `Bound<'py, PyAny>`. #[inline] pub fn as_any(&self) -> &Bound<'py, PyAny> { // Safety: all Bound have the same memory layout, and all Bound are valid // Bound, so pointer casting is valid. unsafe { &*ptr_from_ref(self).cast::>() } } /// Helper to cast to `Bound<'py, PyAny>`, transferring ownership. #[inline] pub fn into_any(self) -> Bound<'py, PyAny> { // Safety: all Bound are valid Bound Bound(self.0, ManuallyDrop::new(self.unbind().into_any())) } /// Casts this `Bound` to a `Borrowed` smart pointer. #[inline] pub fn as_borrowed<'a>(&'a self) -> Borrowed<'a, 'py, T> { Borrowed( unsafe { NonNull::new_unchecked(self.as_ptr()) }, PhantomData, self.py(), ) } /// Removes the connection for this `Bound` from the GIL, allowing /// it to cross thread boundaries. #[inline] pub fn unbind(self) -> Py { // Safety: the type T is known to be correct and the ownership of the // pointer is transferred to the new Py instance. let non_null = (ManuallyDrop::new(self).1).0; unsafe { Py::from_non_null(non_null) } } /// Removes the connection for this `Bound` from the GIL, allowing /// it to cross thread boundaries, without transferring ownership. #[inline] pub fn as_unbound(&self) -> &Py { &self.1 } /// Casts this `Bound` as the corresponding "GIL Ref" type. /// /// This is a helper to be used for migration from the deprecated "GIL Refs" API. #[inline] #[cfg(feature = "gil-refs")] pub fn as_gil_ref(&'py self) -> &'py T::AsRefTarget where T: HasPyGilRef, { #[allow(deprecated)] unsafe { self.py().from_borrowed_ptr(self.as_ptr()) } } /// Casts this `Bound` as the corresponding "GIL Ref" type, registering the pointer on the /// [release pool](Python::from_owned_ptr). /// /// This is a helper to be used for migration from the deprecated "GIL Refs" API. #[inline] #[cfg(feature = "gil-refs")] pub fn into_gil_ref(self) -> &'py T::AsRefTarget where T: HasPyGilRef, { #[allow(deprecated)] unsafe { self.py().from_owned_ptr(self.into_ptr()) } } } unsafe impl AsPyPointer for Bound<'_, T> { #[inline] fn as_ptr(&self) -> *mut ffi::PyObject { self.1.as_ptr() } } /// A borrowed equivalent to `Bound`. /// /// The advantage of this over `&Bound` is that it avoids the need to have a pointer-to-pointer, as Bound /// is already a pointer to an `ffi::PyObject``. /// /// Similarly, this type is `Copy` and `Clone`, like a shared reference (`&T`). #[repr(transparent)] pub struct Borrowed<'a, 'py, T>(NonNull, PhantomData<&'a Py>, Python<'py>); impl<'py, T> Borrowed<'_, 'py, T> { /// Creates a new owned [`Bound`] from this borrowed reference by /// increasing the reference count. /// /// # Example /// ``` /// use pyo3::{prelude::*, types::PyTuple}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let tuple = PyTuple::new_bound(py, [1, 2, 3]); /// /// // borrows from `tuple`, so can only be /// // used while `tuple` stays alive /// let borrowed = tuple.get_borrowed_item(0)?; /// /// // creates a new owned reference, which /// // can be used indendently of `tuple` /// let bound = borrowed.to_owned(); /// drop(tuple); /// /// assert_eq!(bound.extract::().unwrap(), 1); /// Ok(()) /// }) /// # } pub fn to_owned(self) -> Bound<'py, T> { (*self).clone() } } impl<'a, 'py> Borrowed<'a, 'py, PyAny> { /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Panics if `ptr` is null. /// /// Prefer to use [`Bound::from_borrowed_ptr`], as that avoids the major safety risk /// of needing to precisely define the lifetime `'a` for which the borrow is valid. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it is the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] #[track_caller] pub unsafe fn from_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { Self( NonNull::new(ptr).unwrap_or_else(|| crate::err::panic_after_error(py)), PhantomData, py, ) } /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns `None` if `ptr` is null. /// /// Prefer to use [`Bound::from_borrowed_ptr_or_opt`], as that avoids the major safety risk /// of needing to precisely define the lifetime `'a` for which the borrow is valid. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it is the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] pub unsafe fn from_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option { NonNull::new(ptr).map(|ptr| Self(ptr, PhantomData, py)) } /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch` /// if `ptr` is null. /// /// Prefer to use [`Bound::from_borrowed_ptr_or_err`], as that avoids the major safety risk /// of needing to precisely define the lifetime `'a` for which the borrow is valid. /// /// # Safety /// /// - `ptr` must be a valid pointer to a Python object, or null /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it is the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] pub unsafe fn from_ptr_or_err(py: Python<'py>, ptr: *mut ffi::PyObject) -> PyResult { NonNull::new(ptr).map_or_else( || Err(PyErr::fetch(py)), |ptr| Ok(Self(ptr, PhantomData, py)), ) } /// # Safety /// This is similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by /// the caller and it's the caller's responsibility to ensure that the reference this is /// derived from is valid for the lifetime `'a`. #[inline] pub(crate) unsafe fn from_ptr_unchecked(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self { Self(NonNull::new_unchecked(ptr), PhantomData, py) } #[inline] #[cfg(not(feature = "gil-refs"))] pub(crate) fn downcast(self) -> Result, DowncastError<'a, 'py>> where T: PyTypeCheck, { if T::type_check(&self) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(DowncastError::new_from_borrowed(self, T::NAME)) } } /// Converts this `PyAny` to a concrete Python type without checking validity. /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. #[inline] pub(crate) unsafe fn downcast_unchecked(self) -> Borrowed<'a, 'py, T> { Borrowed(self.0, PhantomData, self.2) } } impl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> { /// Create borrow on a Bound #[inline] fn from(instance: &'a Bound<'py, T>) -> Self { instance.as_borrowed() } } #[cfg(feature = "gil-refs")] impl<'py, T> Borrowed<'py, 'py, T> where T: HasPyGilRef, { pub(crate) fn into_gil_ref(self) -> &'py T::AsRefTarget { // Safety: self is a borrow over `'py`. #[allow(deprecated)] unsafe { self.py().from_borrowed_ptr(self.0.as_ptr()) } } } impl std::fmt::Debug for Borrowed<'_, '_, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Bound::fmt(self, f) } } impl<'py, T> Deref for Borrowed<'_, 'py, T> { type Target = Bound<'py, T>; #[inline] fn deref(&self) -> &Bound<'py, T> { // safety: Bound has the same layout as NonNull unsafe { &*ptr_from_ref(&self.0).cast() } } } impl Clone for Borrowed<'_, '_, T> { #[inline] fn clone(&self) -> Self { *self } } impl Copy for Borrowed<'_, '_, T> {} impl ToPyObject for Borrowed<'_, '_, T> { /// Converts `Py` instance -> PyObject. #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { (*self).into_py(py) } } impl IntoPy for Borrowed<'_, '_, T> { /// Converts `Py` instance -> PyObject. #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.to_owned().into_py(py) } } /// A GIL-independent reference to an object allocated on the Python heap. /// /// This type does not auto-dereference to the inner object because you must prove you hold the GIL to access it. /// Instead, call one of its methods to access the inner object: /// - [`Py::bind`] or [`Py::into_bound`], to borrow a GIL-bound reference to the contained object. /// - [`Py::borrow`], [`Py::try_borrow`], [`Py::borrow_mut`], or [`Py::try_borrow_mut`], /// /// to get a (mutable) reference to a contained pyclass, using a scheme similar to std's [`RefCell`]. /// See the #[doc = concat!("[guide entry](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#bound-and-interior-mutability)")] /// for more information. /// - You can call methods directly on `Py` with [`Py::call_bound`], [`Py::call_method_bound`] and friends. /// /// These require passing in the [`Python<'py>`](crate::Python) token but are otherwise similar to the corresponding /// methods on [`PyAny`]. /// /// # Example: Storing Python objects in `#[pyclass]` structs /// /// Usually `Bound<'py, T>` is recommended for interacting with Python objects as its lifetime `'py` /// is an association to the GIL and that enables many operations to be done as efficiently as possible. /// /// However, `#[pyclass]` structs cannot carry a lifetime, so `Py` is the only way to store /// a Python object in a `#[pyclass]` struct. /// /// For example, this won't compile: /// /// ```compile_fail /// # use pyo3::prelude::*; /// # use pyo3::types::PyDict; /// # /// #[pyclass] /// struct Foo<'py> { /// inner: Bound<'py, PyDict>, /// } /// /// impl Foo { /// fn new() -> Foo { /// let foo = Python::with_gil(|py| { /// // `py` will only last for this scope. /// /// // `Bound<'py, PyDict>` inherits the GIL lifetime from `py` and /// // so won't be able to outlive this closure. /// let dict: Bound<'_, PyDict> = PyDict::new_bound(py); /// /// // because `Foo` contains `dict` its lifetime /// // is now also tied to `py`. /// Foo { inner: dict } /// }); /// // Foo is no longer valid. /// // Returning it from this function is a 💥 compiler error 💥 /// foo /// } /// } /// ``` /// /// [`Py`]`` can be used to get around this by converting `dict` into a GIL-independent reference: /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// #[pyclass] /// struct Foo { /// inner: Py, /// } /// /// #[pymethods] /// impl Foo { /// #[new] /// fn __new__() -> Foo { /// Python::with_gil(|py| { /// let dict: Py = PyDict::new_bound(py).unbind(); /// Foo { inner: dict } /// }) /// } /// } /// # /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| { /// # let m = pyo3::types::PyModule::new_bound(py, "test")?; /// # m.add_class::()?; /// # /// # let foo: Bound<'_, Foo> = m.getattr("Foo")?.call0()?.downcast_into()?; /// # let dict = &foo.borrow().inner; /// # let dict: &Bound<'_, PyDict> = dict.bind(py); /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// This can also be done with other pyclasses: /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Bar {/* ... */} /// /// #[pyclass] /// struct Foo { /// inner: Py, /// } /// /// #[pymethods] /// impl Foo { /// #[new] /// fn __new__() -> PyResult { /// Python::with_gil(|py| { /// let bar: Py = Py::new(py, Bar {})?; /// Ok(Foo { inner: bar }) /// }) /// } /// } /// # /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| { /// # let m = pyo3::types::PyModule::new_bound(py, "test")?; /// # m.add_class::()?; /// # /// # let foo: Bound<'_, Foo> = m.getattr("Foo")?.call0()?.downcast_into()?; /// # let bar = &foo.borrow().inner; /// # let bar: &Bar = &*bar.borrow(py); /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// # Example: Shared ownership of Python objects /// /// `Py` can be used to share ownership of a Python object, similar to std's [`Rc`]``. /// As with [`Rc`]``, cloning it increases its reference count rather than duplicating /// the underlying object. /// /// This can be done using either [`Py::clone_ref`] or [`Py`]``'s [`Clone`] trait implementation. /// [`Py::clone_ref`] will be faster if you happen to be already holding the GIL. /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// # fn main() { /// Python::with_gil(|py| { /// let first: Py = PyDict::new_bound(py).unbind(); /// /// // All of these are valid syntax /// let second = Py::clone_ref(&first, py); /// let third = first.clone_ref(py); /// #[cfg(feature = "py-clone")] /// let fourth = Py::clone(&first); /// #[cfg(feature = "py-clone")] /// let fifth = first.clone(); /// /// // Disposing of our original `Py` just decrements the reference count. /// drop(first); /// /// // They all point to the same object /// assert!(second.is(&third)); /// #[cfg(feature = "py-clone")] /// assert!(fourth.is(&fifth)); /// #[cfg(feature = "py-clone")] /// assert!(second.is(&fourth)); /// }); /// # } /// ``` /// /// # Preventing reference cycles /// /// It is easy to accidentally create reference cycles using [`Py`]``. /// The Python interpreter can break these reference cycles within pyclasses if they /// [integrate with the garbage collector][gc]. If your pyclass contains other Python /// objects you should implement it to avoid leaking memory. /// /// # A note on Python reference counts /// /// Dropping a [`Py`]`` will eventually decrease Python's reference count /// of the pointed-to variable, allowing Python's garbage collector to free /// the associated memory, but this may not happen immediately. This is /// because a [`Py`]`` can be dropped at any time, but the Python reference /// count can only be modified when the GIL is held. /// /// If a [`Py`]`` is dropped while its thread happens to be holding the /// GIL then the Python reference count will be decreased immediately. /// Otherwise, the reference count will be decreased the next time the GIL is /// reacquired. /// /// If you happen to be already holding the GIL, [`Py::drop_ref`] will decrease /// the Python reference count immediately and will execute slightly faster than /// relying on implicit [`Drop`]s. /// /// # A note on `Send` and `Sync` /// /// Accessing this object is threadsafe, since any access to its API requires a [`Python<'py>`](crate::Python) token. /// As you can only get this by acquiring the GIL, `Py<...>` implements [`Send`] and [`Sync`]. /// /// [`Rc`]: std::rc::Rc /// [`RefCell`]: std::cell::RefCell /// [gc]: https://pyo3.rs/main/class/protocols.html#garbage-collector-integration #[repr(transparent)] pub struct Py(NonNull, PhantomData); // The inner value is only accessed through ways that require proving the gil is held #[cfg(feature = "nightly")] unsafe impl crate::marker::Ungil for Py {} unsafe impl Send for Py {} unsafe impl Sync for Py {} impl Py where T: PyClass, { /// Creates a new instance `Py` of a `#[pyclass]` on the Python heap. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Foo {/* fields omitted */} /// /// # fn main() -> PyResult<()> { /// let foo = Python::with_gil(|py| -> PyResult<_> { /// let foo: Py = Py::new(py, Foo {})?; /// Ok(foo) /// })?; /// # Python::with_gil(move |_py| drop(foo)); /// # Ok(()) /// # } /// ``` pub fn new(py: Python<'_>, value: impl Into>) -> PyResult> { Bound::new(py, value).map(Bound::unbind) } } #[cfg(feature = "gil-refs")] impl Py where T: HasPyGilRef, { /// Borrows a GIL-bound reference to the contained `T`. /// /// By binding to the GIL lifetime, this allows the GIL-bound reference to not require /// [`Python<'py>`](crate::Python) for any of its methods, which makes calling methods /// on it more ergonomic. /// /// For native types, this reference is `&T`. For pyclasses, this is `&PyCell`. /// /// Note that the lifetime of the returned reference is the shortest of `&self` and /// [`Python<'py>`](crate::Python). /// Consider using [`Py::into_ref`] instead if this poses a problem. /// /// # Examples /// /// Get access to `&PyList` from `Py`: /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::types::PyList; /// # /// Python::with_gil(|py| { /// let list: Py = PyList::empty_bound(py).into(); /// # #[allow(deprecated)] /// let list: &PyList = list.as_ref(py); /// assert_eq!(list.len(), 0); /// }); /// ``` /// /// Get access to `&PyCell` from `Py`: /// /// ``` /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct MyClass {} /// /// Python::with_gil(|py| { /// let my_class: Py = Py::new(py, MyClass {}).unwrap(); /// # #[allow(deprecated)] /// let my_class_cell: &PyCell = my_class.as_ref(py); /// assert!(my_class_cell.try_borrow().is_ok()); /// }); /// ``` #[deprecated( since = "0.21.0", note = "use `obj.bind(py)` instead of `obj.as_ref(py)`" )] pub fn as_ref<'py>(&'py self, _py: Python<'py>) -> &'py T::AsRefTarget { let any = self.as_ptr() as *const PyAny; unsafe { PyNativeType::unchecked_downcast(&*any) } } /// Borrows a GIL-bound reference to the contained `T` independently of the lifetime of `T`. /// /// This method is similar to [`as_ref`](#method.as_ref) but consumes `self` and registers the /// Python object reference in PyO3's object storage. The reference count for the Python /// object will not be decreased until the GIL lifetime ends. /// /// You should prefer using [`as_ref`](#method.as_ref) if you can as it'll have less overhead. /// /// # Examples /// /// [`Py::as_ref`]'s lifetime limitation forbids creating a function that references a /// variable created inside the function. /// /// ```rust,compile_fail /// # use pyo3::prelude::*; /// # /// fn new_py_any<'py>(py: Python<'py>, value: impl IntoPy>) -> &'py PyAny { /// let obj: Py = value.into_py(py); /// /// // The lifetime of the return value of this function is the shortest /// // of `obj` and `py`. As `obj` is owned by the current function, /// // Rust won't let the return value escape this function! /// obj.as_ref(py) /// } /// ``` /// /// This can be solved by using [`Py::into_ref`] instead, which does not suffer from this issue. /// Note that the lifetime of the [`Python<'py>`](crate::Python) token is transferred to /// the returned reference. /// /// ```rust /// # use pyo3::prelude::*; /// # #[allow(dead_code)] // This is just to show it compiles. /// fn new_py_any<'py>(py: Python<'py>, value: impl IntoPy>) -> &'py PyAny { /// let obj: Py = value.into_py(py); /// /// // This reference's lifetime is determined by `py`'s lifetime. /// // Because that originates from outside this function, /// // this return value is allowed. /// # #[allow(deprecated)] /// obj.into_ref(py) /// } /// ``` #[deprecated( since = "0.21.0", note = "use `obj.into_bound(py)` instead of `obj.into_ref(py)`" )] pub fn into_ref(self, py: Python<'_>) -> &T::AsRefTarget { #[allow(deprecated)] unsafe { py.from_owned_ptr(self.into_ptr()) } } } impl Py { /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.0.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { ManuallyDrop::new(self).0.as_ptr() } /// Helper to cast to `Py`. #[inline] pub fn as_any(&self) -> &Py { // Safety: all Py have the same memory layout, and all Py are valid // Py, so pointer casting is valid. unsafe { &*ptr_from_ref(self).cast::>() } } /// Helper to cast to `Py`, transferring ownership. #[inline] pub fn into_any(self) -> Py { // Safety: all Py are valid Py unsafe { Py::from_non_null(ManuallyDrop::new(self).0) } } } impl Py where T: PyClass, { /// Immutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRef`] exists. /// Multiple immutable borrows can be taken out at the same time. /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// Equivalent to `self.bind(py).borrow()` - see [`Bound::borrow`]. /// /// # Examples /// /// ```rust /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Py = Py::new(py, Foo { inner: 73 })?; /// let inner: &u8 = &foo.borrow(py).inner; /// /// assert_eq!(*inner, 73); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use /// [`try_borrow`](#method.try_borrow). #[inline] #[track_caller] pub fn borrow<'py>(&'py self, py: Python<'py>) -> PyRef<'py, T> { self.bind(py).borrow() } /// Mutably borrows the value `T`. /// /// This borrow lasts while the returned [`PyRefMut`] exists. /// /// Equivalent to `self.bind(py).borrow_mut()` - see [`Bound::borrow_mut`]. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # /// #[pyclass] /// struct Foo { /// inner: u8, /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let foo: Py = Py::new(py, Foo { inner: 73 })?; /// foo.borrow_mut(py).inner = 35; /// /// assert_eq!(foo.borrow(py).inner, 35); /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Panics /// Panics if the value is currently borrowed. For a non-panicking variant, use /// [`try_borrow_mut`](#method.try_borrow_mut). #[inline] #[track_caller] pub fn borrow_mut<'py>(&'py self, py: Python<'py>) -> PyRefMut<'py, T> where T: PyClass, { self.bind(py).borrow_mut() } /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed. /// /// The borrow lasts while the returned [`PyRef`] exists. /// /// This is the non-panicking variant of [`borrow`](#method.borrow). /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// Equivalent to `self.bind(py).try_borrow()` - see [`Bound::try_borrow`]. #[inline] pub fn try_borrow<'py>(&'py self, py: Python<'py>) -> Result, PyBorrowError> { self.bind(py).try_borrow() } /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed. /// /// The borrow lasts while the returned [`PyRefMut`] exists. /// /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). /// /// Equivalent to `self.bind(py).try_borrow_mut()` - see [`Bound::try_borrow_mut`]. #[inline] pub fn try_borrow_mut<'py>( &'py self, py: Python<'py>, ) -> Result, PyBorrowMutError> where T: PyClass, { self.bind(py).try_borrow_mut() } /// Provide an immutable borrow of the value `T` without acquiring the GIL. /// /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. /// /// # Examples /// /// ``` /// use std::sync::atomic::{AtomicUsize, Ordering}; /// # use pyo3::prelude::*; /// /// #[pyclass(frozen)] /// struct FrozenCounter { /// value: AtomicUsize, /// } /// /// let cell = Python::with_gil(|py| { /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; /// /// Py::new(py, counter).unwrap() /// }); /// /// cell.get().value.fetch_add(1, Ordering::Relaxed); /// # Python::with_gil(move |_py| drop(cell)); /// ``` #[inline] pub fn get(&self) -> &T where T: PyClass + Sync, { // Safety: The class itself is frozen and `Sync` unsafe { &*self.get_class_object().get_ptr() } } /// Get a view on the underlying `PyClass` contents. #[inline] pub(crate) fn get_class_object(&self) -> &PyClassObject { let class_object = self.as_ptr().cast::>(); // Safety: Bound is known to contain an object which is laid out in memory as a // PyClassObject. unsafe { &*class_object } } } impl Py { /// Attaches this `Py` to the given Python context, allowing access to further Python APIs. #[inline] pub fn bind<'py>(&self, _py: Python<'py>) -> &Bound<'py, T> { // Safety: `Bound` has the same layout as `Py` unsafe { &*ptr_from_ref(self).cast() } } /// Same as `bind` but takes ownership of `self`. #[inline] pub fn into_bound(self, py: Python<'_>) -> Bound<'_, T> { Bound(py, ManuallyDrop::new(self)) } /// Same as `bind` but produces a `Borrowed` instead of a `Bound`. #[inline] pub fn bind_borrowed<'a, 'py>(&'a self, py: Python<'py>) -> Borrowed<'a, 'py, T> { Borrowed(self.0, PhantomData, py) } /// Returns whether `self` and `other` point to the same object. To compare /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq). /// /// This is equivalent to the Python expression `self is other`. #[inline] pub fn is(&self, o: &U) -> bool { self.as_ptr() == o.as_ptr() } /// Gets the reference count of the `ffi::PyObject` pointer. #[inline] pub fn get_refcnt(&self, _py: Python<'_>) -> isize { unsafe { ffi::Py_REFCNT(self.0.as_ptr()) } } /// Makes a clone of `self`. /// /// This creates another pointer to the same object, increasing its reference count. /// /// You should prefer using this method over [`Clone`] if you happen to be holding the GIL already. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// # fn main() { /// Python::with_gil(|py| { /// let first: Py = PyDict::new_bound(py).unbind(); /// let second = Py::clone_ref(&first, py); /// /// // Both point to the same object /// assert!(first.is(&second)); /// }); /// # } /// ``` #[inline] pub fn clone_ref(&self, _py: Python<'_>) -> Py { unsafe { ffi::Py_INCREF(self.as_ptr()); Self::from_non_null(self.0) } } /// Drops `self` and immediately decreases its reference count. /// /// This method is a micro-optimisation over [`Drop`] if you happen to be holding the GIL /// already. /// /// Note that if you are using [`Bound`], you do not need to use [`Self::drop_ref`] since /// [`Bound`] guarantees that the GIL is held. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// # fn main() { /// Python::with_gil(|py| { /// let object: Py = PyDict::new_bound(py).unbind(); /// /// // some usage of object /// /// object.drop_ref(py); /// }); /// # } /// ``` #[inline] pub fn drop_ref(self, py: Python<'_>) { let _ = self.into_bound(py); } /// Returns whether the object is considered to be None. /// /// This is equivalent to the Python expression `self is None`. pub fn is_none(&self, _py: Python<'_>) -> bool { unsafe { ffi::Py_None() == self.as_ptr() } } /// Returns whether the object is Ellipsis, e.g. `...`. /// /// This is equivalent to the Python expression `self is ...`. #[deprecated(since = "0.20.0", note = "use `.is(py.Ellipsis())` instead")] pub fn is_ellipsis(&self) -> bool { unsafe { ffi::Py_Ellipsis() == self.as_ptr() } } /// Returns whether the object is considered to be true. /// /// This is equivalent to the Python expression `bool(self)`. #[deprecated(since = "0.21.0", note = "use `.is_truthy()` instead")] pub fn is_true(&self, py: Python<'_>) -> PyResult { self.is_truthy(py) } /// Returns whether the object is considered to be true. /// /// This applies truth value testing equivalent to the Python expression `bool(self)`. pub fn is_truthy(&self, py: Python<'_>) -> PyResult { let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; err::error_on_minusone(py, v)?; Ok(v != 0) } /// Extracts some type from the Python object. /// /// This is a wrapper function around `FromPyObject::extract()`. pub fn extract<'a, 'py, D>(&'a self, py: Python<'py>) -> PyResult where D: crate::conversion::FromPyObjectBound<'a, 'py>, // TODO it might be possible to relax this bound in future, to allow // e.g. `.extract::<&str>(py)` where `py` is short-lived. 'py: 'a, { self.bind(py).as_any().extract() } /// Retrieves an attribute value. /// /// This is equivalent to the Python expression `self.attr_name`. /// /// If calling this method becomes performance-critical, the [`intern!`](crate::intern) macro /// can be used to intern `attr_name`, thereby avoiding repeated temporary allocations of /// Python strings. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn version(sys: Py, py: Python<'_>) -> PyResult { /// sys.getattr(py, intern!(py, "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import_bound("sys").unwrap().unbind(); /// # version(sys, py).unwrap(); /// # }); /// ``` pub fn getattr(&self, py: Python<'_>, attr_name: N) -> PyResult where N: IntoPy>, { self.bind(py).as_any().getattr(attr_name).map(Bound::unbind) } /// Sets an attribute value. /// /// This is equivalent to the Python expression `self.attr_name = value`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPy, PyObject, Python, PyResult}; /// # /// #[pyfunction] /// fn set_answer(ob: PyObject, py: Python<'_>) -> PyResult<()> { /// ob.setattr(py, intern!(py, "answer"), 42) /// } /// # /// # Python::with_gil(|py| { /// # let ob = PyModule::new_bound(py, "empty").unwrap().into_py(py); /// # set_answer(ob, py).unwrap(); /// # }); /// ``` pub fn setattr(&self, py: Python<'_>, attr_name: N, value: V) -> PyResult<()> where N: IntoPy>, V: IntoPy>, { self.bind(py) .as_any() .setattr(attr_name, value.into_py(py).into_bound(py)) } /// Deprecated form of [`call_bound`][Py::call_bound]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`call` will be replaced by `call_bound` in a future PyO3 version" )] #[inline] pub fn call(&self, py: Python<'_>, args: A, kwargs: Option<&PyDict>) -> PyResult where A: IntoPy>, { self.call_bound(py, args, kwargs.map(PyDict::as_borrowed).as_deref()) } /// Calls the object. /// /// This is equivalent to the Python expression `self(*args, **kwargs)`. pub fn call_bound( &self, py: Python<'_>, args: impl IntoPy>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult { self.bind(py).as_any().call(args, kwargs).map(Bound::unbind) } /// Calls the object with only positional arguments. /// /// This is equivalent to the Python expression `self(*args)`. pub fn call1(&self, py: Python<'_>, args: impl IntoPy>) -> PyResult { self.bind(py).as_any().call1(args).map(Bound::unbind) } /// Calls the object without arguments. /// /// This is equivalent to the Python expression `self()`. pub fn call0(&self, py: Python<'_>) -> PyResult { self.bind(py).as_any().call0().map(Bound::unbind) } /// Deprecated form of [`call_method_bound`][Py::call_method_bound]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`call_method` will be replaced by `call_method_bound` in a future PyO3 version" )] #[inline] pub fn call_method( &self, py: Python<'_>, name: N, args: A, kwargs: Option<&PyDict>, ) -> PyResult where N: IntoPy>, A: IntoPy>, { self.call_method_bound(py, name, args, kwargs.map(PyDict::as_borrowed).as_deref()) } /// Calls a method on the object. /// /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `name`. pub fn call_method_bound( &self, py: Python<'_>, name: N, args: A, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult where N: IntoPy>, A: IntoPy>, { self.bind(py) .as_any() .call_method(name, args, kwargs) .map(Bound::unbind) } /// Calls a method on the object with only positional arguments. /// /// This is equivalent to the Python expression `self.name(*args)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `name`. pub fn call_method1(&self, py: Python<'_>, name: N, args: A) -> PyResult where N: IntoPy>, A: IntoPy>, { self.bind(py) .as_any() .call_method1(name, args) .map(Bound::unbind) } /// Calls a method on the object with no arguments. /// /// This is equivalent to the Python expression `self.name()`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern) /// macro can be used to intern `name`. pub fn call_method0(&self, py: Python<'_>, name: N) -> PyResult where N: IntoPy>, { self.bind(py).as_any().call_method0(name).map(Bound::unbind) } /// Create a `Py` instance by taking ownership of the given FFI pointer. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. /// /// Callers must own the object referred to by `ptr`, as this function /// implicitly takes ownership of that object. /// /// # Panics /// Panics if `ptr` is null. #[inline] #[track_caller] pub unsafe fn from_owned_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py { match NonNull::new(ptr) { Some(nonnull_ptr) => Py(nonnull_ptr, PhantomData), None => crate::err::panic_after_error(py), } } /// Create a `Py` instance by taking ownership of the given FFI pointer. /// /// If `ptr` is null then the current Python exception is fetched as a [`PyErr`]. /// /// # Safety /// If non-null, `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_owned_ptr_or_err( py: Python<'_>, ptr: *mut ffi::PyObject, ) -> PyResult> { match NonNull::new(ptr) { Some(nonnull_ptr) => Ok(Py(nonnull_ptr, PhantomData)), None => Err(PyErr::fetch(py)), } } /// Create a `Py` instance by taking ownership of the given FFI pointer. /// /// If `ptr` is null then `None` is returned. /// /// # Safety /// If non-null, `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_owned_ptr_or_opt(_py: Python<'_>, ptr: *mut ffi::PyObject) -> Option { NonNull::new(ptr).map(|nonnull_ptr| Py(nonnull_ptr, PhantomData)) } /// Create a `Py` instance by creating a new reference from the given FFI pointer. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. /// /// # Panics /// Panics if `ptr` is null. #[inline] #[track_caller] pub unsafe fn from_borrowed_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py { match Self::from_borrowed_ptr_or_opt(py, ptr) { Some(slf) => slf, None => crate::err::panic_after_error(py), } } /// Create a `Py` instance by creating a new reference from the given FFI pointer. /// /// If `ptr` is null then the current Python exception is fetched as a `PyErr`. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_borrowed_ptr_or_err( py: Python<'_>, ptr: *mut ffi::PyObject, ) -> PyResult { Self::from_borrowed_ptr_or_opt(py, ptr).ok_or_else(|| PyErr::fetch(py)) } /// Create a `Py` instance by creating a new reference from the given FFI pointer. /// /// If `ptr` is null then `None` is returned. /// /// # Safety /// `ptr` must be a pointer to a Python object of type T. #[inline] pub unsafe fn from_borrowed_ptr_or_opt( _py: Python<'_>, ptr: *mut ffi::PyObject, ) -> Option { NonNull::new(ptr).map(|nonnull_ptr| { ffi::Py_INCREF(ptr); Py(nonnull_ptr, PhantomData) }) } /// For internal conversions. /// /// # Safety /// `ptr` must point to a Python object of type T. unsafe fn from_non_null(ptr: NonNull) -> Self { Self(ptr, PhantomData) } } impl ToPyObject for Py { /// Converts `Py` instance -> PyObject. #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { self.clone_ref(py).into_any() } } impl IntoPy for Py { /// Converts a `Py` instance to `PyObject`. /// Consumes `self` without calling `Py_DECREF()`. #[inline] fn into_py(self, _py: Python<'_>) -> PyObject { self.into_any() } } impl IntoPy for &'_ Py { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl ToPyObject for Bound<'_, T> { /// Converts `&Bound` instance -> PyObject, increasing the reference count. #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { self.clone().into_py(py) } } impl IntoPy for Bound<'_, T> { /// Converts a `Bound` instance to `PyObject`. #[inline] fn into_py(self, _py: Python<'_>) -> PyObject { self.into_any().unbind() } } impl IntoPy for &Bound<'_, T> { /// Converts `&Bound` instance -> PyObject, increasing the reference count. #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } unsafe impl crate::AsPyPointer for Py { /// Gets the underlying FFI pointer, returns a borrowed pointer. #[inline] fn as_ptr(&self) -> *mut ffi::PyObject { self.0.as_ptr() } } #[cfg(feature = "gil-refs")] impl std::convert::From<&'_ T> for PyObject where T: PyNativeType, { #[inline] fn from(obj: &T) -> Self { obj.as_borrowed().to_owned().into_any().unbind() } } impl std::convert::From> for PyObject where T: AsRef, { #[inline] fn from(other: Py) -> Self { other.into_any() } } impl std::convert::From> for PyObject where T: AsRef, { #[inline] fn from(other: Bound<'_, T>) -> Self { let py = other.py(); other.into_py(py) } } impl std::convert::From> for Py { #[inline] fn from(other: Bound<'_, T>) -> Self { other.unbind() } } // `&PyCell` can be converted to `Py` #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl std::convert::From<&crate::PyCell> for Py where T: PyClass, { fn from(cell: &crate::PyCell) -> Self { cell.as_borrowed().to_owned().unbind() } } impl<'a, T> std::convert::From> for Py where T: PyClass, { fn from(pyref: PyRef<'a, T>) -> Self { unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } } } impl<'a, T> std::convert::From> for Py where T: PyClass, { fn from(pyref: PyRefMut<'a, T>) -> Self { unsafe { Py::from_borrowed_ptr(pyref.py(), pyref.as_ptr()) } } } /// If the GIL is held this increments `self`'s reference count. /// Otherwise, it will panic. /// /// Only available if the `py-clone` feature is enabled. #[cfg(feature = "py-clone")] impl Clone for Py { #[track_caller] fn clone(&self) -> Self { unsafe { gil::register_incref(self.0); } Self(self.0, PhantomData) } } /// Dropping a `Py` instance decrements the reference count /// on the object by one if the GIL is held. /// /// Otherwise and by default, this registers the underlying pointer to have its reference count /// decremented the next time PyO3 acquires the GIL. /// /// However, if the `pyo3_disable_reference_pool` conditional compilation flag /// is enabled, it will abort the process. impl Drop for Py { #[track_caller] fn drop(&mut self) { unsafe { gil::register_decref(self.0); } } } impl FromPyObject<'_> for Py where T: PyTypeCheck, { /// Extracts `Self` from the source `PyObject`. fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { ob.extract::>().map(Bound::unbind) } } impl<'py, T> FromPyObject<'py> for Bound<'py, T> where T: PyTypeCheck, { /// Extracts `Self` from the source `PyObject`. fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { ob.downcast().cloned().map_err(Into::into) } } /// `Py` can be used as an error when T is an Error. /// /// However for GIL lifetime reasons, cause() cannot be implemented for `Py`. /// Use .as_ref() to get the GIL-scoped error if you need to inspect the cause. #[cfg(feature = "gil-refs")] impl std::error::Error for Py where T: std::error::Error + PyTypeInfo, T::AsRefTarget: std::fmt::Display, { } impl std::fmt::Display for Py where T: PyTypeInfo, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Python::with_gil(|py| std::fmt::Display::fmt(self.bind(py), f)) } } impl std::fmt::Debug for Py { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Py").field(&self.0.as_ptr()).finish() } } /// A commonly-used alias for `Py`. /// /// This is an owned reference a Python object without any type information. This value can also be /// safely sent between threads. /// /// See the documentation for [`Py`](struct.Py.html). pub type PyObject = Py; impl PyObject { /// Deprecated form of [`PyObject::downcast_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyObject::downcast` will be replaced by `PyObject::downcast_bound` in a future PyO3 version" )] #[inline] pub fn downcast<'py, T>( &'py self, py: Python<'py>, ) -> Result<&'py T, crate::err::PyDowncastError<'py>> where T: PyTypeCheck, { self.downcast_bound::(py) .map(Bound::as_gil_ref) .map_err(crate::err::PyDowncastError::from_downcast_err) } /// Downcast this `PyObject` to a concrete Python type or pyclass. /// /// Note that you can often avoid downcasting yourself by just specifying /// the desired type in function or method signatures. /// However, manual downcasting is sometimes necessary. /// /// For extracting a Rust-only type, see [`Py::extract`](struct.Py.html#method.extract). /// /// # Example: Downcasting to a specific Python object /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { /// let any: PyObject = PyDict::new_bound(py).into(); /// /// assert!(any.downcast_bound::(py).is_ok()); /// assert!(any.downcast_bound::(py).is_err()); /// }); /// ``` /// /// # Example: Getting a reference to a pyclass /// /// This is useful if you want to mutate a `PyObject` that /// might actually be a pyclass. /// /// ```rust /// # fn main() -> Result<(), pyo3::PyErr> { /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Class { /// i: i32, /// } /// /// Python::with_gil(|py| { /// let class: PyObject = Py::new(py, Class { i: 0 }).unwrap().into_py(py); /// /// let class_bound = class.downcast_bound::(py)?; /// /// class_bound.borrow_mut().i += 1; /// /// // Alternatively you can get a `PyRefMut` directly /// let class_ref: PyRefMut<'_, Class> = class.extract(py)?; /// assert_eq!(class_ref.i, 1); /// Ok(()) /// }) /// # } /// ``` #[inline] pub fn downcast_bound<'py, T>( &self, py: Python<'py>, ) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeCheck, { self.bind(py).downcast() } /// Deprecated form of [`PyObject::downcast_bound_unchecked`] /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyObject::downcast_unchecked` will be replaced by `PyObject::downcast_bound_unchecked` in a future PyO3 version" )] #[inline] pub unsafe fn downcast_unchecked<'py, T>(&'py self, py: Python<'py>) -> &T where T: HasPyGilRef, { self.downcast_bound_unchecked::(py).as_gil_ref() } /// Casts the PyObject to a concrete Python object type without checking validity. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. #[inline] pub unsafe fn downcast_bound_unchecked<'py, T>(&self, py: Python<'py>) -> &Bound<'py, T> { self.bind(py).downcast_unchecked() } } #[cfg(test)] mod tests { use super::{Bound, Py, PyObject}; use crate::types::{dict::IntoPyDict, PyAnyMethods, PyCapsule, PyDict, PyString}; use crate::{ffi, Borrowed, PyAny, PyResult, Python, ToPyObject}; #[test] fn test_call() { Python::with_gil(|py| { let obj = py.get_type_bound::().to_object(py); let assert_repr = |obj: &Bound<'_, PyAny>, expected: &str| { assert_eq!(obj.repr().unwrap(), expected); }; assert_repr(obj.call0(py).unwrap().bind(py), "{}"); assert_repr(obj.call1(py, ()).unwrap().bind(py), "{}"); assert_repr(obj.call_bound(py, (), None).unwrap().bind(py), "{}"); assert_repr(obj.call1(py, ((('x', 1),),)).unwrap().bind(py), "{'x': 1}"); assert_repr( obj.call_bound(py, (), Some(&[('x', 1)].into_py_dict_bound(py))) .unwrap() .bind(py), "{'x': 1}", ); }) } #[test] fn test_call_for_non_existing_method() { Python::with_gil(|py| { let obj: PyObject = PyDict::new_bound(py).into(); assert!(obj.call_method0(py, "asdf").is_err()); assert!(obj .call_method_bound(py, "nonexistent_method", (1,), None) .is_err()); assert!(obj.call_method0(py, "nonexistent_method").is_err()); assert!(obj.call_method1(py, "nonexistent_method", (1,)).is_err()); }); } #[test] fn py_from_dict() { let dict: Py = Python::with_gil(|py| { let native = PyDict::new_bound(py); Py::from(native) }); Python::with_gil(move |py| { assert_eq!(dict.get_refcnt(py), 1); }); } #[test] fn pyobject_from_py() { Python::with_gil(|py| { let dict: Py = PyDict::new_bound(py).unbind(); let cnt = dict.get_refcnt(py); let p: PyObject = dict.into(); assert_eq!(p.get_refcnt(py), cnt); }); } #[test] fn attr() -> PyResult<()> { use crate::types::PyModule; Python::with_gil(|py| { const CODE: &str = r#" class A: pass a = A() "#; let module = PyModule::from_code_bound(py, CODE, "", "")?; let instance: Py = module.getattr("a")?.into(); instance.getattr(py, "foo").unwrap_err(); instance.setattr(py, "foo", "bar")?; assert!(instance .getattr(py, "foo")? .bind(py) .eq(PyString::new_bound(py, "bar"))?); instance.getattr(py, "foo")?; Ok(()) }) } #[test] fn pystring_attr() -> PyResult<()> { use crate::types::PyModule; Python::with_gil(|py| { const CODE: &str = r#" class A: pass a = A() "#; let module = PyModule::from_code_bound(py, CODE, "", "")?; let instance: Py = module.getattr("a")?.into(); let foo = crate::intern!(py, "foo"); let bar = crate::intern!(py, "bar"); instance.getattr(py, foo).unwrap_err(); instance.setattr(py, foo, bar)?; assert!(instance.getattr(py, foo)?.bind(py).eq(bar)?); Ok(()) }) } #[test] fn invalid_attr() -> PyResult<()> { Python::with_gil(|py| { let instance: Py = py.eval_bound("object()", None, None)?.into(); instance.getattr(py, "foo").unwrap_err(); // Cannot assign arbitrary attributes to `object` instance.setattr(py, "foo", "bar").unwrap_err(); Ok(()) }) } #[test] fn test_py2_from_py_object() { Python::with_gil(|py| { let instance = py.eval_bound("object()", None, None).unwrap(); let ptr = instance.as_ptr(); let instance: Bound<'_, PyAny> = instance.extract().unwrap(); assert_eq!(instance.as_ptr(), ptr); }) } #[test] fn test_py2_into_py_object() { Python::with_gil(|py| { let instance = py .eval_bound("object()", None, None) .unwrap() .as_borrowed() .to_owned(); let ptr = instance.as_ptr(); let instance: PyObject = instance.clone().unbind(); assert_eq!(instance.as_ptr(), ptr); }) } #[test] #[allow(deprecated)] fn test_is_ellipsis() { Python::with_gil(|py| { let v = py .eval_bound("...", None, None) .map_err(|e| e.display(py)) .unwrap() .to_object(py); assert!(v.is_ellipsis()); let not_ellipsis = 5.to_object(py); assert!(!not_ellipsis.is_ellipsis()); }); } #[test] fn test_debug_fmt() { Python::with_gil(|py| { let obj = "hello world".to_object(py).into_bound(py); assert_eq!(format!("{:?}", obj), "'hello world'"); }); } #[test] fn test_display_fmt() { Python::with_gil(|py| { let obj = "hello world".to_object(py).into_bound(py); assert_eq!(format!("{}", obj), "hello world"); }); } #[test] fn test_bound_as_any() { Python::with_gil(|py| { let obj = PyString::new_bound(py, "hello world"); let any = obj.as_any(); assert_eq!(any.as_ptr(), obj.as_ptr()); }); } #[test] fn test_bound_into_any() { Python::with_gil(|py| { let obj = PyString::new_bound(py, "hello world"); let any = obj.clone().into_any(); assert_eq!(any.as_ptr(), obj.as_ptr()); }); } #[test] fn test_bound_py_conversions() { Python::with_gil(|py| { let obj: Bound<'_, PyString> = PyString::new_bound(py, "hello world"); let obj_unbound: &Py = obj.as_unbound(); let _: &Bound<'_, PyString> = obj_unbound.bind(py); let obj_unbound: Py = obj.unbind(); let obj: Bound<'_, PyString> = obj_unbound.into_bound(py); assert_eq!(obj, "hello world"); }); } #[test] fn bound_from_borrowed_ptr_constructors() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { fn check_drop<'py>( py: Python<'py>, method: impl FnOnce(*mut ffi::PyObject) -> Bound<'py, PyAny>, ) { let mut dropped = false; let capsule = PyCapsule::new_bound_with_destructor( py, (&mut dropped) as *mut _ as usize, None, |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) }, ) .unwrap(); let bound = method(capsule.as_ptr()); assert!(!dropped); // creating the bound should have increased the refcount drop(capsule); assert!(!dropped); // dropping the bound should now also decrease the refcount and free the object drop(bound); assert!(dropped); } check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr(py, ptr) }); check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr_or_opt(py, ptr).unwrap() }); check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr_or_err(py, ptr).unwrap() }); }) } #[test] fn borrowed_ptr_constructors() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { fn check_drop<'py>( py: Python<'py>, method: impl FnOnce(&*mut ffi::PyObject) -> Borrowed<'_, 'py, PyAny>, ) { let mut dropped = false; let capsule = PyCapsule::new_bound_with_destructor( py, (&mut dropped) as *mut _ as usize, None, |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) }, ) .unwrap(); let ptr = &capsule.as_ptr(); let _borrowed = method(ptr); assert!(!dropped); // creating the borrow should not have increased the refcount drop(capsule); assert!(dropped); } check_drop(py, |&ptr| unsafe { Borrowed::from_ptr(py, ptr) }); check_drop(py, |&ptr| unsafe { Borrowed::from_ptr_or_opt(py, ptr).unwrap() }); check_drop(py, |&ptr| unsafe { Borrowed::from_ptr_or_err(py, ptr).unwrap() }); }) } #[test] fn explicit_drop_ref() { Python::with_gil(|py| { let object: Py = PyDict::new_bound(py).unbind(); let object2 = object.clone_ref(py); assert_eq!(object.as_ptr(), object2.as_ptr()); assert_eq!(object.get_refcnt(py), 2); object.drop_ref(py); assert_eq!(object2.get_refcnt(py), 1); object2.drop_ref(py); }); } #[cfg(feature = "macros")] mod using_macros { use super::*; #[crate::pyclass(crate = "crate")] struct SomeClass(i32); #[test] fn py_borrow_methods() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { let instance = Py::new(py, SomeClass(0)).unwrap(); assert_eq!(instance.borrow(py).0, 0); assert_eq!(instance.try_borrow(py).unwrap().0, 0); assert_eq!(instance.borrow_mut(py).0, 0); assert_eq!(instance.try_borrow_mut(py).unwrap().0, 0); instance.borrow_mut(py).0 = 123; assert_eq!(instance.borrow(py).0, 123); assert_eq!(instance.try_borrow(py).unwrap().0, 123); assert_eq!(instance.borrow_mut(py).0, 123); assert_eq!(instance.try_borrow_mut(py).unwrap().0, 123); }) } #[test] fn bound_borrow_methods() { // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { let instance = Bound::new(py, SomeClass(0)).unwrap(); assert_eq!(instance.borrow().0, 0); assert_eq!(instance.try_borrow().unwrap().0, 0); assert_eq!(instance.borrow_mut().0, 0); assert_eq!(instance.try_borrow_mut().unwrap().0, 0); instance.borrow_mut().0 = 123; assert_eq!(instance.borrow().0, 123); assert_eq!(instance.try_borrow().unwrap().0, 123); assert_eq!(instance.borrow_mut().0, 123); assert_eq!(instance.try_borrow_mut().unwrap().0, 123); }) } #[crate::pyclass(frozen, crate = "crate")] struct FrozenClass(i32); #[test] fn test_frozen_get() { Python::with_gil(|py| { for i in 0..10 { let instance = Py::new(py, FrozenClass(i)).unwrap(); assert_eq!(instance.get().0, i); assert_eq!(instance.bind(py).get().0, i); } }) } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn cell_tryfrom() { use crate::{PyCell, PyTryInto}; // More detailed tests of the underlying semantics in pycell.rs Python::with_gil(|py| { let instance: &PyAny = Py::new(py, SomeClass(0)).unwrap().into_ref(py); let _: &PyCell = PyTryInto::try_into(instance).unwrap(); let _: &PyCell = PyTryInto::try_into_exact(instance).unwrap(); }) } } } pyo3/src/type_object.rs0000644000175000017500000002142714661133735016105 0ustar jamespagejamespage//! Python type object information use crate::ffi_ptr_ext::FfiPtrExt; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyType}; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, Bound, Python}; /// `T: PyLayout` represents that `T` is a concrete representation of `U` in the Python heap. /// E.g., `PyClassObject` is a concrete representation of all `pyclass`es, and `ffi::PyObject` /// is of `PyAny`. /// /// This trait is intended to be used internally. /// /// # Safety /// /// This trait must only be implemented for types which represent valid layouts of Python objects. pub unsafe trait PyLayout {} /// `T: PySizedLayout` represents that `T` is not a instance of /// [`PyVarObject`](https://docs.python.org/3.8/c-api/structures.html?highlight=pyvarobject#c.PyVarObject). /// In addition, that `T` is a concrete representation of `U`. pub trait PySizedLayout: PyLayout + Sized {} /// Specifies that this type has a "GIL-bound Reference" form. /// /// This is expected to be deprecated in the near future, see /// /// # Safety /// /// - `Py::as_ref` will hand out references to `Self::AsRefTarget`. /// - `Self::AsRefTarget` must have the same layout as `UnsafeCell`. #[cfg(feature = "gil-refs")] pub unsafe trait HasPyGilRef { /// Utility type to make Py::as_ref work. type AsRefTarget: PyNativeType; } #[cfg(feature = "gil-refs")] unsafe impl HasPyGilRef for T where T: PyNativeType, { type AsRefTarget = Self; } /// Python type information. /// All Python native types (e.g., `PyDict`) and `#[pyclass]` structs implement this trait. /// /// This trait is marked unsafe because: /// - specifying the incorrect layout can lead to memory errors /// - the return value of type_object must always point to the same PyTypeObject instance /// /// It is safely implemented by the `pyclass` macro. /// /// # Safety /// /// Implementations must provide an implementation for `type_object_raw` which infallibly produces a /// non-null pointer to the corresponding Python type object. #[cfg(feature = "gil-refs")] pub unsafe trait PyTypeInfo: Sized + HasPyGilRef { /// Class name. const NAME: &'static str; /// Module name, if any. const MODULE: Option<&'static str>; /// Returns the PyTypeObject instance for this type. fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject; /// Returns the safe abstraction over the type object. #[inline] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyTypeInfo::type_object` will be replaced by `PyTypeInfo::type_object_bound` in a future PyO3 version" )] fn type_object(py: Python<'_>) -> &PyType { // This isn't implemented in terms of `type_object_bound` because this just borrowed the // object, for legacy reasons. #[allow(deprecated)] unsafe { py.from_borrowed_ptr(Self::type_object_raw(py) as _) } } /// Returns the safe abstraction over the type object. #[inline] fn type_object_bound(py: Python<'_>) -> Bound<'_, PyType> { // Making the borrowed object `Bound` is necessary for soundness reasons. It's an extreme // edge case, but arbitrary Python code _could_ change the __class__ of an object and cause // the type object to be freed. // // By making `Bound` we assume ownership which is then safe against races. unsafe { Self::type_object_raw(py) .cast::() .assume_borrowed_unchecked(py) .to_owned() .downcast_into_unchecked() } } /// Checks if `object` is an instance of this type or a subclass of this type. #[inline] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyTypeInfo::is_type_of` will be replaced by `PyTypeInfo::is_type_of_bound` in a future PyO3 version" )] fn is_type_of(object: &PyAny) -> bool { Self::is_type_of_bound(&object.as_borrowed()) } /// Checks if `object` is an instance of this type or a subclass of this type. #[inline] fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 } } /// Checks if `object` is an instance of this type. #[inline] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyTypeInfo::is_exact_type_of` will be replaced by `PyTypeInfo::is_exact_type_of_bound` in a future PyO3 version" )] fn is_exact_type_of(object: &PyAny) -> bool { Self::is_exact_type_of_bound(&object.as_borrowed()) } /// Checks if `object` is an instance of this type. #[inline] fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::Py_TYPE(object.as_ptr()) == Self::type_object_raw(object.py()) } } } /// Python type information. /// All Python native types (e.g., `PyDict`) and `#[pyclass]` structs implement this trait. /// /// This trait is marked unsafe because: /// - specifying the incorrect layout can lead to memory errors /// - the return value of type_object must always point to the same PyTypeObject instance /// /// It is safely implemented by the `pyclass` macro. /// /// # Safety /// /// Implementations must provide an implementation for `type_object_raw` which infallibly produces a /// non-null pointer to the corresponding Python type object. #[cfg(not(feature = "gil-refs"))] pub unsafe trait PyTypeInfo: Sized { /// Class name. const NAME: &'static str; /// Module name, if any. const MODULE: Option<&'static str>; /// Returns the PyTypeObject instance for this type. fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject; /// Returns the safe abstraction over the type object. #[inline] fn type_object_bound(py: Python<'_>) -> Bound<'_, PyType> { // Making the borrowed object `Bound` is necessary for soundness reasons. It's an extreme // edge case, but arbitrary Python code _could_ change the __class__ of an object and cause // the type object to be freed. // // By making `Bound` we assume ownership which is then safe against races. unsafe { Self::type_object_raw(py) .cast::() .assume_borrowed_unchecked(py) .to_owned() .downcast_into_unchecked() } } /// Checks if `object` is an instance of this type or a subclass of this type. #[inline] fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 } } /// Checks if `object` is an instance of this type. #[inline] fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::Py_TYPE(object.as_ptr()) == Self::type_object_raw(object.py()) } } } /// Implemented by types which can be used as a concrete Python type inside `Py` smart pointers. #[cfg(feature = "gil-refs")] pub trait PyTypeCheck: HasPyGilRef { /// Name of self. This is used in error messages, for example. const NAME: &'static str; /// Checks if `object` is an instance of `Self`, which may include a subtype. /// /// This should be equivalent to the Python expression `isinstance(object, Self)`. fn type_check(object: &Bound<'_, PyAny>) -> bool; } /// Implemented by types which can be used as a concrete Python type inside `Py` smart pointers. #[cfg(not(feature = "gil-refs"))] pub trait PyTypeCheck { /// Name of self. This is used in error messages, for example. const NAME: &'static str; /// Checks if `object` is an instance of `Self`, which may include a subtype. /// /// This should be equivalent to the Python expression `isinstance(object, Self)`. fn type_check(object: &Bound<'_, PyAny>) -> bool; } impl PyTypeCheck for T where T: PyTypeInfo, { const NAME: &'static str = ::NAME; #[inline] fn type_check(object: &Bound<'_, PyAny>) -> bool { T::is_type_of_bound(object) } } #[inline] pub(crate) unsafe fn get_tp_alloc(tp: *mut ffi::PyTypeObject) -> Option { #[cfg(not(Py_LIMITED_API))] { (*tp).tp_alloc } #[cfg(Py_LIMITED_API)] { let ptr = ffi::PyType_GetSlot(tp, ffi::Py_tp_alloc); std::mem::transmute(ptr) } } #[inline] pub(crate) unsafe fn get_tp_free(tp: *mut ffi::PyTypeObject) -> ffi::freefunc { #[cfg(not(Py_LIMITED_API))] { (*tp).tp_free.unwrap() } #[cfg(Py_LIMITED_API)] { let ptr = ffi::PyType_GetSlot(tp, ffi::Py_tp_free); debug_assert_ne!(ptr, std::ptr::null_mut()); std::mem::transmute(ptr) } } pyo3/src/pyclass/0000775000175000017500000000000014661133735014702 5ustar jamespagejamespagepyo3/src/pyclass/create_type_object.rs0000644000175000017500000005721014661133735021105 0ustar jamespagejamespageuse crate::{ exceptions::PyTypeError, ffi, impl_::{ pycell::PyClassObject, pyclass::{ assign_sequence_item_from_mapping, get_sequence_item_from_mapping, tp_dealloc, tp_dealloc_with_gc, MaybeRuntimePyMethodDef, PyClassItemsIter, }, pymethods::{Getter, Setter}, trampoline::trampoline, }, internal_tricks::ptr_from_ref, types::{typeobject::PyTypeMethods, PyType}, Py, PyClass, PyGetterDef, PyMethodDefType, PyResult, PySetterDef, PyTypeInfo, Python, }; use std::{ collections::HashMap, ffi::{CStr, CString}, os::raw::{c_char, c_int, c_ulong, c_void}, ptr, }; pub(crate) struct PyClassTypeObject { pub type_object: Py, #[allow(dead_code)] // This is purely a cache that must live as long as the type object getset_destructors: Vec, } pub(crate) fn create_type_object(py: Python<'_>) -> PyResult where T: PyClass, { // Written this way to monomorphize the majority of the logic. #[allow(clippy::too_many_arguments)] unsafe fn inner( py: Python<'_>, base: *mut ffi::PyTypeObject, dealloc: unsafe extern "C" fn(*mut ffi::PyObject), dealloc_with_gc: unsafe extern "C" fn(*mut ffi::PyObject), is_mapping: bool, is_sequence: bool, doc: &'static CStr, dict_offset: Option, weaklist_offset: Option, is_basetype: bool, items_iter: PyClassItemsIter, name: &'static str, module: Option<&'static str>, size_of: usize, ) -> PyResult { PyTypeBuilder { slots: Vec::new(), method_defs: Vec::new(), member_defs: Vec::new(), getset_builders: HashMap::new(), cleanup: Vec::new(), tp_base: base, tp_dealloc: dealloc, tp_dealloc_with_gc: dealloc_with_gc, is_mapping, is_sequence, has_new: false, has_dealloc: false, has_getitem: false, has_setitem: false, has_traverse: false, has_clear: false, dict_offset: None, class_flags: 0, #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] buffer_procs: Default::default(), } .type_doc(doc) .offsets(dict_offset, weaklist_offset) .set_is_basetype(is_basetype) .class_items(items_iter) .build(py, name, module, size_of) } unsafe { inner( py, T::BaseType::type_object_raw(py), tp_dealloc::, tp_dealloc_with_gc::, T::IS_MAPPING, T::IS_SEQUENCE, T::doc(py)?, T::dict_offset(), T::weaklist_offset(), T::IS_BASETYPE, T::items_iter(), T::NAME, T::MODULE, std::mem::size_of::>(), ) } } type PyTypeBuilderCleanup = Box; struct PyTypeBuilder { slots: Vec, method_defs: Vec, member_defs: Vec, getset_builders: HashMap<&'static CStr, GetSetDefBuilder>, /// Used to patch the type objects for the things there's no /// PyType_FromSpec API for... there's no reason this should work, /// except for that it does and we have tests. cleanup: Vec, tp_base: *mut ffi::PyTypeObject, tp_dealloc: ffi::destructor, tp_dealloc_with_gc: ffi::destructor, is_mapping: bool, is_sequence: bool, has_new: bool, has_dealloc: bool, has_getitem: bool, has_setitem: bool, has_traverse: bool, has_clear: bool, dict_offset: Option, class_flags: c_ulong, // Before Python 3.9, need to patch in buffer methods manually (they don't work in slots) #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] buffer_procs: ffi::PyBufferProcs, } impl PyTypeBuilder { /// # Safety /// The given pointer must be of the correct type for the given slot unsafe fn push_slot(&mut self, slot: c_int, pfunc: *mut T) { match slot { ffi::Py_tp_new => self.has_new = true, ffi::Py_tp_dealloc => self.has_dealloc = true, ffi::Py_mp_subscript => self.has_getitem = true, ffi::Py_mp_ass_subscript => self.has_setitem = true, ffi::Py_tp_traverse => { self.has_traverse = true; self.class_flags |= ffi::Py_TPFLAGS_HAVE_GC; } ffi::Py_tp_clear => self.has_clear = true, #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] ffi::Py_bf_getbuffer => { // Safety: slot.pfunc is a valid function pointer self.buffer_procs.bf_getbuffer = Some(std::mem::transmute::<*mut T, ffi::getbufferproc>(pfunc)); } #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))] ffi::Py_bf_releasebuffer => { // Safety: slot.pfunc is a valid function pointer self.buffer_procs.bf_releasebuffer = Some(std::mem::transmute::<*mut T, ffi::releasebufferproc>(pfunc)); } _ => {} } self.slots.push(ffi::PyType_Slot { slot, pfunc: pfunc as _, }); } /// # Safety /// It is the caller's responsibility that `data` is of the correct type for the given slot. unsafe fn push_raw_vec_slot(&mut self, slot: c_int, mut data: Vec) { if !data.is_empty() { // Python expects a zeroed entry to mark the end of the defs data.push(std::mem::zeroed()); self.push_slot(slot, Box::into_raw(data.into_boxed_slice()) as *mut c_void); } } fn pymethod_def(&mut self, def: &PyMethodDefType) { match def { PyMethodDefType::Getter(getter) => self .getset_builders .entry(getter.name) .or_default() .add_getter(getter), PyMethodDefType::Setter(setter) => self .getset_builders .entry(setter.name) .or_default() .add_setter(setter), PyMethodDefType::Method(def) | PyMethodDefType::Class(def) | PyMethodDefType::Static(def) => self.method_defs.push(def.as_method_def()), // These class attributes are added after the type gets created by LazyStaticType PyMethodDefType::ClassAttribute(_) => {} PyMethodDefType::StructMember(def) => self.member_defs.push(*def), } } fn finalize_methods_and_properties(&mut self) -> Vec { let method_defs: Vec = std::mem::take(&mut self.method_defs); // Safety: Py_tp_methods expects a raw vec of PyMethodDef unsafe { self.push_raw_vec_slot(ffi::Py_tp_methods, method_defs) }; let member_defs = std::mem::take(&mut self.member_defs); // Safety: Py_tp_members expects a raw vec of PyMemberDef unsafe { self.push_raw_vec_slot(ffi::Py_tp_members, member_defs) }; let mut getset_destructors = Vec::with_capacity(self.getset_builders.len()); #[allow(unused_mut)] let mut property_defs: Vec<_> = self .getset_builders .iter() .map(|(name, builder)| { let (def, destructor) = builder.as_get_set_def(name); getset_destructors.push(destructor); def }) .collect(); // PyPy automatically adds __dict__ getter / setter. #[cfg(not(PyPy))] // Supported on unlimited API for all versions, and on 3.9+ for limited API #[cfg(any(Py_3_9, not(Py_LIMITED_API)))] if let Some(dict_offset) = self.dict_offset { let get_dict; let closure; // PyObject_GenericGetDict not in the limited API until Python 3.10. #[cfg(any(not(Py_LIMITED_API), Py_3_10))] { let _ = dict_offset; get_dict = ffi::PyObject_GenericGetDict; closure = ptr::null_mut(); } // ... so we write a basic implementation ourselves #[cfg(not(any(not(Py_LIMITED_API), Py_3_10)))] { extern "C" fn get_dict_impl( object: *mut ffi::PyObject, closure: *mut c_void, ) -> *mut ffi::PyObject { unsafe { trampoline(|_| { let dict_offset = closure as ffi::Py_ssize_t; // we don't support negative dict_offset here; PyO3 doesn't set it negative assert!(dict_offset > 0); // TODO: use `.byte_offset` on MSRV 1.75 let dict_ptr = object .cast::() .offset(dict_offset) .cast::<*mut ffi::PyObject>(); if (*dict_ptr).is_null() { std::ptr::write(dict_ptr, ffi::PyDict_New()); } Ok(ffi::_Py_XNewRef(*dict_ptr)) }) } } get_dict = get_dict_impl; closure = dict_offset as _; } property_defs.push(ffi::PyGetSetDef { name: ffi::c_str!("__dict__").as_ptr(), get: Some(get_dict), set: Some(ffi::PyObject_GenericSetDict), doc: ptr::null(), closure, }); } // Safety: Py_tp_getset expects a raw vec of PyGetSetDef unsafe { self.push_raw_vec_slot(ffi::Py_tp_getset, property_defs) }; // If mapping methods implemented, define sequence methods get implemented too. // CPython does the same for Python `class` statements. // NB we don't implement sq_length to avoid annoying CPython behaviour of automatically adding // the length to negative indices. // Don't add these methods for "pure" mappings. if !self.is_mapping && self.has_getitem { // Safety: This is the correct slot type for Py_sq_item unsafe { self.push_slot( ffi::Py_sq_item, get_sequence_item_from_mapping as *mut c_void, ) } } if !self.is_mapping && self.has_setitem { // Safety: This is the correct slot type for Py_sq_ass_item unsafe { self.push_slot( ffi::Py_sq_ass_item, assign_sequence_item_from_mapping as *mut c_void, ) } } getset_destructors } fn set_is_basetype(mut self, is_basetype: bool) -> Self { if is_basetype { self.class_flags |= ffi::Py_TPFLAGS_BASETYPE; } self } /// # Safety /// All slots in the PyClassItemsIter should be correct unsafe fn class_items(mut self, iter: PyClassItemsIter) -> Self { for items in iter { for slot in items.slots { self.push_slot(slot.slot, slot.pfunc); } for method in items.methods { let built_method; let method = match method { MaybeRuntimePyMethodDef::Runtime(builder) => { built_method = builder(); &built_method } MaybeRuntimePyMethodDef::Static(method) => method, }; self.pymethod_def(method); } } self } fn type_doc(mut self, type_doc: &'static CStr) -> Self { let slice = type_doc.to_bytes(); if !slice.is_empty() { unsafe { self.push_slot(ffi::Py_tp_doc, type_doc.as_ptr() as *mut c_char) } // Running this causes PyPy to segfault. #[cfg(all(not(PyPy), not(Py_LIMITED_API), not(Py_3_10)))] { // Until CPython 3.10, tp_doc was treated specially for // heap-types, and it removed the text_signature value from it. // We go in after the fact and replace tp_doc with something // that _does_ include the text_signature value! self.cleanup .push(Box::new(move |_self, type_object| unsafe { ffi::PyObject_Free((*type_object).tp_doc as _); let data = ffi::PyMem_Malloc(slice.len()); data.copy_from(slice.as_ptr() as _, slice.len()); (*type_object).tp_doc = data as _; })) } } self } fn offsets( mut self, dict_offset: Option, #[allow(unused_variables)] weaklist_offset: Option, ) -> Self { self.dict_offset = dict_offset; #[cfg(Py_3_9)] { #[inline(always)] fn offset_def(name: &'static CStr, offset: ffi::Py_ssize_t) -> ffi::PyMemberDef { ffi::PyMemberDef { name: name.as_ptr().cast(), type_code: ffi::Py_T_PYSSIZET, offset, flags: ffi::Py_READONLY, doc: std::ptr::null_mut(), } } // __dict__ support if let Some(dict_offset) = dict_offset { self.member_defs .push(offset_def(ffi::c_str!("__dictoffset__"), dict_offset)); } // weakref support if let Some(weaklist_offset) = weaklist_offset { self.member_defs.push(offset_def( ffi::c_str!("__weaklistoffset__"), weaklist_offset, )); } } // Setting buffer protocols, tp_dictoffset and tp_weaklistoffset via slots doesn't work until // Python 3.9, so on older versions we must manually fixup the type object. #[cfg(all(not(Py_LIMITED_API), not(Py_3_9)))] { self.cleanup .push(Box::new(move |builder, type_object| unsafe { (*(*type_object).tp_as_buffer).bf_getbuffer = builder.buffer_procs.bf_getbuffer; (*(*type_object).tp_as_buffer).bf_releasebuffer = builder.buffer_procs.bf_releasebuffer; if let Some(dict_offset) = dict_offset { (*type_object).tp_dictoffset = dict_offset; } if let Some(weaklist_offset) = weaklist_offset { (*type_object).tp_weaklistoffset = weaklist_offset; } })); } self } fn build( mut self, py: Python<'_>, name: &'static str, module_name: Option<&'static str>, basicsize: usize, ) -> PyResult { // `c_ulong` and `c_uint` have the same size // on some platforms (like windows) #![allow(clippy::useless_conversion)] let getset_destructors = self.finalize_methods_and_properties(); unsafe { self.push_slot(ffi::Py_tp_base, self.tp_base) } if !self.has_new { // Safety: This is the correct slot type for Py_tp_new unsafe { self.push_slot(ffi::Py_tp_new, no_constructor_defined as *mut c_void) } } let tp_dealloc = if self.has_traverse || unsafe { ffi::PyType_IS_GC(self.tp_base) == 1 } { self.tp_dealloc_with_gc } else { self.tp_dealloc }; unsafe { self.push_slot(ffi::Py_tp_dealloc, tp_dealloc as *mut c_void) } if self.has_clear && !self.has_traverse { return Err(PyTypeError::new_err(format!( "`#[pyclass]` {} implements __clear__ without __traverse__", name ))); } // For sequences, implement sq_length instead of mp_length if self.is_sequence { for slot in &mut self.slots { if slot.slot == ffi::Py_mp_length { slot.slot = ffi::Py_sq_length; } } } // Add empty sentinel at the end // Safety: python expects this empty slot unsafe { self.push_slot(0, ptr::null_mut::()) } let class_name = py_class_qualified_name(module_name, name)?; let mut spec = ffi::PyType_Spec { name: class_name.as_ptr() as _, basicsize: basicsize as c_int, itemsize: 0, flags: (ffi::Py_TPFLAGS_DEFAULT | self.class_flags) .try_into() .unwrap(), slots: self.slots.as_mut_ptr(), }; // Safety: We've correctly setup the PyType_Spec at this point let type_object: Py = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyType_FromSpec(&mut spec))? }; #[cfg(not(Py_3_11))] bpo_45315_workaround(py, class_name); for cleanup in std::mem::take(&mut self.cleanup) { cleanup(&self, type_object.bind(py).as_type_ptr()); } Ok(PyClassTypeObject { type_object, getset_destructors, }) } } fn py_class_qualified_name(module_name: Option<&str>, class_name: &str) -> PyResult { Ok(CString::new(format!( "{}.{}", module_name.unwrap_or("builtins"), class_name ))?) } /// Workaround for Python issue 45315; no longer necessary in Python 3.11 #[inline] #[cfg(not(Py_3_11))] fn bpo_45315_workaround(py: Python<'_>, class_name: CString) { #[cfg(Py_LIMITED_API)] { // Must check version at runtime for abi3 wheels - they could run against a higher version // than the build config suggests. use crate::sync::GILOnceCell; static IS_PYTHON_3_11: GILOnceCell = GILOnceCell::new(); if *IS_PYTHON_3_11.get_or_init(py, || py.version_info() >= (3, 11)) { // No fix needed - the wheel is running on a sufficiently new interpreter. return; } } #[cfg(not(Py_LIMITED_API))] { // suppress unused variable warning let _ = py; } std::mem::forget(class_name); } /// Default new implementation unsafe extern "C" fn no_constructor_defined( _subtype: *mut ffi::PyTypeObject, _args: *mut ffi::PyObject, _kwds: *mut ffi::PyObject, ) -> *mut ffi::PyObject { trampoline(|_| { Err(crate::exceptions::PyTypeError::new_err( "No constructor defined", )) }) } #[derive(Default)] struct GetSetDefBuilder { doc: Option<&'static CStr>, getter: Option, setter: Option, } impl GetSetDefBuilder { fn add_getter(&mut self, getter: &PyGetterDef) { // TODO: be smarter about merging getter and setter docs if self.doc.is_none() { self.doc = Some(getter.doc); } // TODO: return an error if getter already defined? self.getter = Some(getter.meth) } fn add_setter(&mut self, setter: &PySetterDef) { // TODO: be smarter about merging getter and setter docs if self.doc.is_none() { self.doc = Some(setter.doc); } // TODO: return an error if setter already defined? self.setter = Some(setter.meth) } fn as_get_set_def(&self, name: &'static CStr) -> (ffi::PyGetSetDef, GetSetDefDestructor) { let getset_type = match (self.getter, self.setter) { (Some(getter), None) => GetSetDefType::Getter(getter), (None, Some(setter)) => GetSetDefType::Setter(setter), (Some(getter), Some(setter)) => { GetSetDefType::GetterAndSetter(Box::new(GetterAndSetter { getter, setter })) } (None, None) => { unreachable!("GetSetDefBuilder expected to always have either getter or setter") } }; let getset_def = getset_type.create_py_get_set_def(name, self.doc); let destructor = GetSetDefDestructor { closure: getset_type, }; (getset_def, destructor) } } #[allow(dead_code)] // a stack of fields which are purely to cache until dropped struct GetSetDefDestructor { closure: GetSetDefType, } /// Possible forms of property - either a getter, setter, or both enum GetSetDefType { Getter(Getter), Setter(Setter), // The box is here so that the `GetterAndSetter` has a stable // memory address even if the `GetSetDefType` enum is moved GetterAndSetter(Box), } pub(crate) struct GetterAndSetter { getter: Getter, setter: Setter, } impl GetSetDefType { /// Fills a PyGetSetDef structure /// It is only valid for as long as this GetSetDefType remains alive, /// as well as name and doc members pub(crate) fn create_py_get_set_def( &self, name: &CStr, doc: Option<&CStr>, ) -> ffi::PyGetSetDef { let (get, set, closure): (Option, Option, *mut c_void) = match self { &Self::Getter(closure) => { unsafe extern "C" fn getter( slf: *mut ffi::PyObject, closure: *mut c_void, ) -> *mut ffi::PyObject { // Safety: PyO3 sets the closure when constructing the ffi getter so this cast should always be valid let getter: Getter = std::mem::transmute(closure); trampoline(|py| getter(py, slf)) } (Some(getter), None, closure as Getter as _) } &Self::Setter(closure) => { unsafe extern "C" fn setter( slf: *mut ffi::PyObject, value: *mut ffi::PyObject, closure: *mut c_void, ) -> c_int { // Safety: PyO3 sets the closure when constructing the ffi setter so this cast should always be valid let setter: Setter = std::mem::transmute(closure); trampoline(|py| setter(py, slf, value)) } (None, Some(setter), closure as Setter as _) } Self::GetterAndSetter(closure) => { unsafe extern "C" fn getset_getter( slf: *mut ffi::PyObject, closure: *mut c_void, ) -> *mut ffi::PyObject { let getset: &GetterAndSetter = &*closure.cast(); trampoline(|py| (getset.getter)(py, slf)) } unsafe extern "C" fn getset_setter( slf: *mut ffi::PyObject, value: *mut ffi::PyObject, closure: *mut c_void, ) -> c_int { let getset: &GetterAndSetter = &*closure.cast(); trampoline(|py| (getset.setter)(py, slf, value)) } ( Some(getset_getter), Some(getset_setter), ptr_from_ref::(closure) as *mut _, ) } }; ffi::PyGetSetDef { name: name.as_ptr(), doc: doc.map_or(ptr::null(), CStr::as_ptr), get, set, closure, } } } pyo3/src/pyclass/gc.rs0000644000175000017500000000235214661133735015641 0ustar jamespagejamespageuse std::os::raw::{c_int, c_void}; use crate::{ffi, AsPyPointer, Python}; /// Error returned by a `__traverse__` visitor implementation. #[repr(transparent)] pub struct PyTraverseError(pub(crate) c_int); /// Object visitor for GC. #[derive(Clone)] pub struct PyVisit<'p> { pub(crate) visit: ffi::visitproc, pub(crate) arg: *mut c_void, /// VisitProc contains a Python instance to ensure that /// 1) it is cannot be moved out of the traverse() call /// 2) it cannot be sent to other threads pub(crate) _py: Python<'p>, } impl<'p> PyVisit<'p> { /// Visit `obj`. pub fn call(&self, obj: &T) -> Result<(), PyTraverseError> where T: AsPyPointer, { let ptr = obj.as_ptr(); if !ptr.is_null() { let r = unsafe { (self.visit)(ptr, self.arg) }; if r == 0 { Ok(()) } else { Err(PyTraverseError(r)) } } else { Ok(()) } } /// Creates the PyVisit from the arguments to tp_traverse #[doc(hidden)] pub unsafe fn from_raw(visit: ffi::visitproc, arg: *mut c_void, py: Python<'p>) -> Self { Self { visit, arg, _py: py, } } } pyo3/src/coroutine.rs0000644000175000017500000001343214661133735015602 0ustar jamespagejamespage//! Python coroutine implementation, used notably when wrapping `async fn` //! with `#[pyfunction]`/`#[pymethods]`. use std::{ future::Future, panic, pin::Pin, sync::Arc, task::{Context, Poll, Waker}, }; use pyo3_macros::{pyclass, pymethods}; use crate::{ coroutine::{cancel::ThrowCallback, waker::AsyncioWaker}, exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration}, panic::PanicException, types::{string::PyStringMethods, PyIterator, PyString}, Bound, IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python, }; pub(crate) mod cancel; mod waker; pub use cancel::CancelHandle; const COROUTINE_REUSED_ERROR: &str = "cannot reuse already awaited coroutine"; /// Python coroutine wrapping a [`Future`]. #[pyclass(crate = "crate")] pub struct Coroutine { name: Option>, qualname_prefix: Option<&'static str>, throw_callback: Option, future: Option> + Send>>>, waker: Option>, } impl Coroutine { /// Wrap a future into a Python coroutine. /// /// Coroutine `send` polls the wrapped future, ignoring the value passed /// (should always be `None` anyway). /// /// `Coroutine `throw` drop the wrapped future and reraise the exception passed pub(crate) fn new( name: Option>, qualname_prefix: Option<&'static str>, throw_callback: Option, future: F, ) -> Self where F: Future> + Send + 'static, T: IntoPy, E: Into, { let wrap = async move { let obj = future.await.map_err(Into::into)?; // SAFETY: GIL is acquired when future is polled (see `Coroutine::poll`) Ok(obj.into_py(unsafe { Python::assume_gil_acquired() })) }; Self { name, qualname_prefix, throw_callback, future: Some(Box::pin(wrap)), waker: None, } } fn poll(&mut self, py: Python<'_>, throw: Option) -> PyResult { // raise if the coroutine has already been run to completion let future_rs = match self.future { Some(ref mut fut) => fut, None => return Err(PyRuntimeError::new_err(COROUTINE_REUSED_ERROR)), }; // reraise thrown exception it match (throw, &self.throw_callback) { (Some(exc), Some(cb)) => cb.throw(exc), (Some(exc), None) => { self.close(); return Err(PyErr::from_value_bound(exc.into_bound(py))); } (None, _) => {} } // create a new waker, or try to reset it in place if let Some(waker) = self.waker.as_mut().and_then(Arc::get_mut) { waker.reset(); } else { self.waker = Some(Arc::new(AsyncioWaker::new())); } let waker = Waker::from(self.waker.clone().unwrap()); // poll the Rust future and forward its results if ready // polling is UnwindSafe because the future is dropped in case of panic let poll = || future_rs.as_mut().poll(&mut Context::from_waker(&waker)); match panic::catch_unwind(panic::AssertUnwindSafe(poll)) { Ok(Poll::Ready(res)) => { self.close(); return Err(PyStopIteration::new_err(res?)); } Err(err) => { self.close(); return Err(PanicException::from_panic_payload(err)); } _ => {} } // otherwise, initialize the waker `asyncio.Future` if let Some(future) = self.waker.as_ref().unwrap().initialize_future(py)? { // `asyncio.Future` must be awaited; fortunately, it implements `__iter__ = __await__` // and will yield itself if its result has not been set in polling above if let Some(future) = PyIterator::from_bound_object(&future.as_borrowed()) .unwrap() .next() { // future has not been leaked into Python for now, and Rust code can only call // `set_result(None)` in `Wake` implementation, so it's safe to unwrap return Ok(future.unwrap().into()); } } // if waker has been waken during future polling, this is roughly equivalent to // `await asyncio.sleep(0)`, so just yield `None`. Ok(py.None().into_py(py)) } } #[pymethods(crate = "crate")] impl Coroutine { #[getter] fn __name__(&self, py: Python<'_>) -> PyResult> { match &self.name { Some(name) => Ok(name.clone_ref(py)), None => Err(PyAttributeError::new_err("__name__")), } } #[getter] fn __qualname__(&self, py: Python<'_>) -> PyResult> { match (&self.name, &self.qualname_prefix) { (Some(name), Some(prefix)) => Ok(format!("{}.{}", prefix, name.bind(py).to_cow()?) .as_str() .into_py(py)), (Some(name), None) => Ok(name.clone_ref(py)), (None, _) => Err(PyAttributeError::new_err("__qualname__")), } } fn send(&mut self, py: Python<'_>, _value: &Bound<'_, PyAny>) -> PyResult { self.poll(py, None) } fn throw(&mut self, py: Python<'_>, exc: PyObject) -> PyResult { self.poll(py, Some(exc)) } fn close(&mut self) { // the Rust future is dropped, and the field set to `None` // to indicate the coroutine has been run to completion drop(self.future.take()); } fn __await__(self_: Py) -> Py { self_ } fn __next__(&mut self, py: Python<'_>) -> PyResult { self.poll(py, None) } } pyo3/src/conversions/0000775000175000017500000000000014661133735015574 5ustar jamespagejamespagepyo3/src/conversions/rust_decimal.rs0000644000175000017500000001701214661133735020614 0ustar jamespagejamespage#![cfg(feature = "rust_decimal")] //! Conversions to and from [rust_decimal](https://docs.rs/rust_decimal)'s [`Decimal`] type. //! //! This is useful for converting Python's decimal.Decimal into and from a native Rust type. //! //! # Setup //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"rust_decimal\"] }")] //! rust_decimal = "1.0" //! ``` //! //! Note that you must use a compatible version of rust_decimal and PyO3. //! The required rust_decimal version may vary based on the version of PyO3. //! //! # Example //! //! Rust code to create a function that adds one to a Decimal //! //! ```rust //! use rust_decimal::Decimal; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(d: Decimal) -> Decimal { //! d + Decimal::ONE //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality //! //! //! ```python //! from my_module import add_one //! from decimal import Decimal //! //! d = Decimal("2") //! value = add_one(d) //! //! assert d + 1 == value //! ``` use crate::exceptions::PyValueError; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::string::PyStringMethods; use crate::types::PyType; use crate::{Bound, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject}; use rust_decimal::Decimal; use std::str::FromStr; impl FromPyObject<'_> for Decimal { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { // use the string representation to not be lossy if let Ok(val) = obj.extract() { Ok(Decimal::new(val, 0)) } else { let py_str = &obj.str()?; let rs_str = &py_str.to_cow()?; Decimal::from_str(rs_str).or_else(|_| { Decimal::from_scientific(rs_str).map_err(|e| PyValueError::new_err(e.to_string())) }) } } } static DECIMAL_CLS: GILOnceCell> = GILOnceCell::new(); fn get_decimal_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { DECIMAL_CLS.get_or_try_init_type_ref(py, "decimal", "Decimal") } impl ToPyObject for Decimal { fn to_object(&self, py: Python<'_>) -> PyObject { // TODO: handle error gracefully when ToPyObject can error // look up the decimal.Decimal let dec_cls = get_decimal_cls(py).expect("failed to load decimal.Decimal"); // now call the constructor with the Rust Decimal string-ified // to not be lossy let ret = dec_cls .call1((self.to_string(),)) .expect("failed to call decimal.Decimal(value)"); ret.to_object(py) } } impl IntoPy for Decimal { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } #[cfg(test)] mod test_rust_decimal { use super::*; use crate::err::PyErr; use crate::types::dict::PyDictMethods; use crate::types::PyDict; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; macro_rules! convert_constants { ($name:ident, $rs:expr, $py:literal) => { #[test] fn $name() { Python::with_gil(|py| { let rs_orig = $rs; let rs_dec = rs_orig.into_py(py); let locals = PyDict::new_bound(py); locals.set_item("rs_dec", &rs_dec).unwrap(); // Checks if Rust Decimal -> Python Decimal conversion is correct py.run_bound( &format!( "import decimal\npy_dec = decimal.Decimal({})\nassert py_dec == rs_dec", $py ), None, Some(&locals), ) .unwrap(); // Checks if Python Decimal -> Rust Decimal conversion is correct let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let py_result: Decimal = py_dec.extract().unwrap(); assert_eq!(rs_orig, py_result); }) } }; } convert_constants!(convert_zero, Decimal::ZERO, "0"); convert_constants!(convert_one, Decimal::ONE, "1"); convert_constants!(convert_neg_one, Decimal::NEGATIVE_ONE, "-1"); convert_constants!(convert_two, Decimal::TWO, "2"); convert_constants!(convert_ten, Decimal::TEN, "10"); convert_constants!(convert_one_hundred, Decimal::ONE_HUNDRED, "100"); convert_constants!(convert_one_thousand, Decimal::ONE_THOUSAND, "1000"); #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_roundtrip( lo in any::(), mid in any::(), high in any::(), negative in any::(), scale in 0..28u32 ) { let num = Decimal::from_parts(lo, mid, high, negative, scale); Python::with_gil(|py| { let rs_dec = num.into_py(py); let locals = PyDict::new_bound(py); locals.set_item("rs_dec", &rs_dec).unwrap(); py.run_bound( &format!( "import decimal\npy_dec = decimal.Decimal(\"{}\")\nassert py_dec == rs_dec", num), None, Some(&locals)).unwrap(); let roundtripped: Decimal = rs_dec.extract(py).unwrap(); assert_eq!(num, roundtripped); }) } #[test] fn test_integers(num in any::()) { Python::with_gil(|py| { let py_num = num.into_py(py); let roundtripped: Decimal = py_num.extract(py).unwrap(); let rs_dec = Decimal::new(num, 0); assert_eq!(rs_dec, roundtripped); }) } } #[test] fn test_nan() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "import decimal\npy_dec = decimal.Decimal(\"NaN\")", None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } #[test] fn test_scientific_notation() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "import decimal\npy_dec = decimal.Decimal(\"1e3\")", None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Decimal = py_dec.extract().unwrap(); let rs_dec = Decimal::from_scientific("1e3").unwrap(); assert_eq!(rs_dec, roundtripped); }) } #[test] fn test_infinity() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "import decimal\npy_dec = decimal.Decimal(\"Infinity\")", None, Some(&locals), ) .unwrap(); let py_dec = locals.get_item("py_dec").unwrap().unwrap(); let roundtripped: Result = py_dec.extract(); assert!(roundtripped.is_err()); }) } } pyo3/src/conversions/eyre.rs0000644000175000017500000001545014661133735017111 0ustar jamespagejamespage#![cfg(feature = "eyre")] //! A conversion from //! [eyre](https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications.")’s //! [`Report`] type to [`PyErr`]. //! //! Use of an error handling library like [eyre] is common in application code and when you just //! want error handling to be easy. If you are writing a library or you need more control over your //! errors you might want to design your own error type instead. //! //! When the inner error is a [`PyErr`] without source, it will be extracted out. //! Otherwise a Python [`RuntimeError`] will be created. //! You might find that you need to map the error from your Rust code into another Python exception. //! See [`PyErr::new`] for more information about that. //! //! For information about error handling in general, see the [Error handling] chapter of the Rust //! book. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! eyre = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"eyre\"] }")] //! ``` //! //! Note that you must use compatible versions of eyre and PyO3. //! The required eyre version may vary based on the version of PyO3. //! //! # Example: Propagating a `PyErr` into [`eyre::Report`] //! //! ```rust //! use pyo3::prelude::*; //! use std::path::PathBuf; //! //! // A wrapper around a Rust function. //! // The pyfunction macro performs the conversion to a PyErr //! #[pyfunction] //! fn py_open(filename: PathBuf) -> eyre::Result> { //! let data = std::fs::read(filename)?; //! Ok(data) //! } //! //! fn main() { //! let error = Python::with_gil(|py| -> PyResult> { //! let fun = wrap_pyfunction_bound!(py_open, py)?; //! let text = fun.call1(("foo.txt",))?.extract::>()?; //! Ok(text) //! }).unwrap_err(); //! //! println!("{}", error); //! } //! ``` //! //! # Example: Using `eyre` in general //! //! Note that you don't need this feature to convert a [`PyErr`] into an [`eyre::Report`], because //! it can already convert anything that implements [`Error`](std::error::Error): //! //! ```rust //! use pyo3::prelude::*; //! use pyo3::types::PyBytes; //! //! // An example function that must handle multiple error types. //! // //! // To do this you usually need to design your own error type or use //! // `Box`. `eyre` is a convenient alternative for this. //! pub fn decompress(bytes: &[u8]) -> eyre::Result { //! // An arbitrary example of a Python api you //! // could call inside an application... //! // This might return a `PyErr`. //! let res = Python::with_gil(|py| { //! let zlib = PyModule::import_bound(py, "zlib")?; //! let decompress = zlib.getattr("decompress")?; //! let bytes = PyBytes::new_bound(py, bytes); //! let value = decompress.call1((bytes,))?; //! value.extract::>() //! })?; //! //! // This might be a `FromUtf8Error`. //! let text = String::from_utf8(res)?; //! //! Ok(text) //! } //! //! fn main() -> eyre::Result<()> { //! let bytes: &[u8] = b"x\x9c\x8b\xcc/U(\xce\xc8/\xcdIQ((\xcaOJL\xca\xa9T\ //! (-NU(\xc9HU\xc8\xc9LJ\xcbI,IUH.\x02\x91\x99y\xc5%\ //! \xa9\x89)z\x00\xf2\x15\x12\xfe"; //! let text = decompress(bytes)?; //! //! println!("The text is \"{}\"", text); //! # assert_eq!(text, "You should probably use the libflate crate instead."); //! Ok(()) //! } //! ``` //! //! [eyre]: https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications." //! [`RuntimeError`]: https://docs.python.org/3/library/exceptions.html#RuntimeError "Built-in Exceptions — Python documentation" //! [Error handling]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html "Recoverable Errors with Result - The Rust Programming Language" use crate::exceptions::PyRuntimeError; use crate::PyErr; use eyre::Report; /// Converts [`eyre::Report`] to a [`PyErr`] containing a [`PyRuntimeError`]. /// /// If you want to raise a different Python exception you will have to do so manually. See /// [`PyErr::new`] for more information about that. impl From for PyErr { fn from(mut error: Report) -> Self { // Errors containing a PyErr without chain or context are returned as the underlying error if error.source().is_none() { error = match error.downcast::() { Ok(py_err) => return py_err, Err(error) => error, }; } PyRuntimeError::new_err(format!("{:?}", error)) } } #[cfg(test)] mod tests { use crate::exceptions::{PyRuntimeError, PyValueError}; use crate::prelude::*; use crate::types::IntoPyDict; use eyre::{bail, eyre, Report, Result, WrapErr}; fn f() -> Result<()> { use std::io; bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!")); } fn g() -> Result<()> { f().wrap_err("f failed") } fn h() -> Result<()> { g().wrap_err("g failed") } #[test] fn test_pyo3_exception_contents() { let err = h().unwrap_err(); let expected_contents = format!("{:?}", err); let pyerr = PyErr::from(err); Python::with_gil(|py| { let locals = [("err", pyerr)].into_py_dict_bound(py); let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value_bound(py).to_string(), expected_contents); }) } fn k() -> Result<()> { Err(eyre!("Some sort of error")) } #[test] fn test_pyo3_exception_contents2() { let err = k().unwrap_err(); let expected_contents = format!("{:?}", err); let pyerr = PyErr::from(err); Python::with_gil(|py| { let locals = [("err", pyerr)].into_py_dict_bound(py); let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value_bound(py).to_string(), expected_contents); }) } #[test] fn test_pyo3_unwrap_simple_err() { let origin_exc = PyValueError::new_err("Value Error"); let report: Report = origin_exc.into(); let converted: PyErr = report.into(); assert!(Python::with_gil( |py| converted.is_instance_of::(py) )) } #[test] fn test_pyo3_unwrap_complex_err() { let origin_exc = PyValueError::new_err("Value Error"); let mut report: Report = origin_exc.into(); report = report.wrap_err("Wrapped"); let converted: PyErr = report.into(); assert!(Python::with_gil( |py| converted.is_instance_of::(py) )) } } pyo3/src/conversions/chrono_tz.rs0000644000175000017500000000676014661133735020156 0ustar jamespagejamespage#![cfg(all(Py_3_9, feature = "chrono-tz"))] //! Conversions to and from [chrono-tz](https://docs.rs/chrono-tz/)’s `Tz`. //! //! This feature requires at least Python 3.9. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! chrono-tz = "0.8" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"chrono-tz\"] }")] //! ``` //! //! Note that you must use compatible versions of chrono, chrono-tz and PyO3. //! The required chrono version may vary based on the version of PyO3. //! //! # Example: Convert a `zoneinfo.ZoneInfo` to chrono-tz's `Tz` //! //! ```rust,no_run //! use chrono_tz::Tz; //! use pyo3::{Python, ToPyObject}; //! //! fn main() { //! pyo3::prepare_freethreaded_python(); //! Python::with_gil(|py| { //! // Convert to Python //! let py_tzinfo = Tz::Europe__Paris.to_object(py); //! // Convert back to Rust //! assert_eq!(py_tzinfo.extract::(py).unwrap(), Tz::Europe__Paris); //! }); //! } //! ``` use crate::exceptions::PyValueError; use crate::pybacked::PyBackedStr; use crate::sync::GILOnceCell; use crate::types::{any::PyAnyMethods, PyType}; use crate::{ intern, Bound, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject, }; use chrono_tz::Tz; use std::str::FromStr; impl ToPyObject for Tz { fn to_object(&self, py: Python<'_>) -> PyObject { static ZONE_INFO: GILOnceCell> = GILOnceCell::new(); ZONE_INFO .get_or_try_init_type_ref(py, "zoneinfo", "ZoneInfo") .unwrap() .call1((self.name(),)) .unwrap() .unbind() } } impl IntoPy for Tz { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'_> for Tz { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { Tz::from_str( &ob.getattr(intern!(ob.py(), "key"))? .extract::()?, ) .map_err(|e| PyValueError::new_err(e.to_string())) } } #[cfg(all(test, not(windows)))] // Troubles loading timezones on Windows mod tests { use super::*; #[test] fn test_frompyobject() { Python::with_gil(|py| { assert_eq!( new_zoneinfo(py, "Europe/Paris").extract::().unwrap(), Tz::Europe__Paris ); assert_eq!(new_zoneinfo(py, "UTC").extract::().unwrap(), Tz::UTC); assert_eq!( new_zoneinfo(py, "Etc/GMT-5").extract::().unwrap(), Tz::Etc__GMTMinus5 ); }); } #[test] fn test_topyobject() { Python::with_gil(|py| { let assert_eq = |l: PyObject, r: Bound<'_, PyAny>| { assert!(l.bind(py).eq(r).unwrap()); }; assert_eq( Tz::Europe__Paris.to_object(py), new_zoneinfo(py, "Europe/Paris"), ); assert_eq(Tz::UTC.to_object(py), new_zoneinfo(py, "UTC")); assert_eq( Tz::Etc__GMTMinus5.to_object(py), new_zoneinfo(py, "Etc/GMT-5"), ); }); } fn new_zoneinfo<'py>(py: Python<'py>, name: &str) -> Bound<'py, PyAny> { zoneinfo_class(py).call1((name,)).unwrap() } fn zoneinfo_class(py: Python<'_>) -> Bound<'_, PyAny> { py.import_bound("zoneinfo") .unwrap() .getattr("ZoneInfo") .unwrap() } } pyo3/src/conversions/serde.rs0000644000175000017500000000237314661133735017247 0ustar jamespagejamespage#![cfg(feature = "serde")] //! Enables (de)serialization of [`Py`]`` objects via [serde](https://docs.rs/serde). //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"serde\"] }")] //! serde = "1.0" //! ``` use crate::{Py, PyAny, PyClass, Python}; use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer}; impl Serialize for Py where T: Serialize + PyClass, { fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> where S: Serializer, { Python::with_gil(|py| { self.try_borrow(py) .map_err(|e| ser::Error::custom(e.to_string()))? .serialize(serializer) }) } } impl<'de, T> Deserialize<'de> for Py where T: PyClass + Deserialize<'de>, { fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let deserialized = T::deserialize(deserializer)?; Python::with_gil(|py| { Py::new(py, deserialized).map_err(|e| de::Error::custom(e.to_string())) }) } } pyo3/src/conversions/indexmap.rs0000644000175000017500000001567314661133735017761 0ustar jamespagejamespage#![cfg(feature = "indexmap")] //! Conversions to and from [indexmap](https://docs.rs/indexmap/)’s //! `IndexMap`. //! //! [`indexmap::IndexMap`] is a hash table that is closely compatible with the standard [`std::collections::HashMap`], //! with the difference that it preserves the insertion order when iterating over keys. It was inspired //! by Python's 3.6+ dict implementation. //! //! Dictionary order is guaranteed to be insertion order in Python, hence IndexMap is a good candidate //! for maintaining an equivalent behaviour in Rust. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! indexmap = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"indexmap\"] }")] //! ``` //! //! Note that you must use compatible versions of indexmap and PyO3. //! The required indexmap version may vary based on the version of PyO3. //! //! # Examples //! //! Using [indexmap](https://docs.rs/indexmap) to return a dictionary with some statistics //! about a list of numbers. Because of the insertion order guarantees, the Python code will //! always print the same result, matching users' expectations about Python's dict. //! ```rust //! use indexmap::{indexmap, IndexMap}; //! use pyo3::prelude::*; //! //! fn median(data: &Vec) -> f32 { //! let sorted_data = data.clone().sort(); //! let mid = data.len() / 2; //! if data.len() % 2 == 0 { //! data[mid] as f32 //! } //! else { //! (data[mid] + data[mid - 1]) as f32 / 2.0 //! } //! } //! //! fn mean(data: &Vec) -> f32 { //! data.iter().sum::() as f32 / data.len() as f32 //! } //! fn mode(data: &Vec) -> f32 { //! let mut frequency = IndexMap::new(); // we can use IndexMap as any hash table //! //! for &element in data { //! *frequency.entry(element).or_insert(0) += 1; //! } //! //! frequency //! .iter() //! .max_by(|a, b| a.1.cmp(&b.1)) //! .map(|(k, _v)| *k) //! .unwrap() as f32 //! } //! //! #[pyfunction] //! fn calculate_statistics(data: Vec) -> IndexMap<&'static str, f32> { //! indexmap! { //! "median" => median(&data), //! "mean" => mean(&data), //! "mode" => mode(&data), //! } //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(calculate_statistics, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code: //! ```python //! from my_module import calculate_statistics //! //! data = [1, 1, 1, 3, 4, 5] //! print(calculate_statistics(data)) //! # always prints {"median": 2.0, "mean": 2.5, "mode": 1.0} in the same order //! # if another hash table was used, the order could be random //! ``` use crate::types::*; use crate::{Bound, FromPyObject, IntoPy, PyErr, PyObject, Python, ToPyObject}; use std::{cmp, hash}; impl ToPyObject for indexmap::IndexMap where K: hash::Hash + cmp::Eq + ToPyObject, V: ToPyObject, H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { IntoPyDict::into_py_dict_bound(self, py).into() } } impl IntoPy for indexmap::IndexMap where K: hash::Hash + cmp::Eq + IntoPy, V: IntoPy, H: hash::BuildHasher, { fn into_py(self, py: Python<'_>) -> PyObject { let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); IntoPyDict::into_py_dict_bound(iter, py).into() } } impl<'py, K, V, S> FromPyObject<'py> for indexmap::IndexMap where K: FromPyObject<'py> + cmp::Eq + hash::Hash, V: FromPyObject<'py>, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = indexmap::IndexMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } } #[cfg(test)] mod test_indexmap { use crate::types::*; use crate::{IntoPy, PyObject, Python, ToPyObject}; #[test] fn test_indexmap_indexmap_to_python() { Python::with_gil(|py| { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); let m = map.to_object(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!( map, py_map.extract::>().unwrap() ); }); } #[test] fn test_indexmap_indexmap_into_python() { Python::with_gil(|py| { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); let m: PyObject = map.into_py(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); }); } #[test] fn test_indexmap_indexmap_into_dict() { Python::with_gil(|py| { let mut map = indexmap::IndexMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict_bound(py); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_indexmap_indexmap_insertion_order_round_trip() { Python::with_gil(|py| { let n = 20; let mut map = indexmap::IndexMap::::new(); for i in 1..=n { if i % 2 == 1 { map.insert(i, i); } else { map.insert(n - i, i); } } let py_map = map.clone().into_py_dict_bound(py); let trip_map = py_map.extract::>().unwrap(); for (((k1, v1), (k2, v2)), (k3, v3)) in map.iter().zip(py_map.iter()).zip(trip_map.iter()) { let k2 = k2.extract::().unwrap(); let v2 = v2.extract::().unwrap(); assert_eq!((k1, v1), (&k2, &v2)); assert_eq!((k1, v1), (k3, v3)); assert_eq!((&k2, &v2), (k3, v3)); } }); } } pyo3/src/conversions/hashbrown.rs0000644000175000017500000001365014661133735020140 0ustar jamespagejamespage#![cfg(feature = "hashbrown")] //! Conversions to and from [hashbrown](https://docs.rs/hashbrown/)’s //! `HashMap` and `HashSet`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! hashbrown = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"hashbrown\"] }")] //! ``` //! //! Note that you must use compatible versions of hashbrown and PyO3. //! The required hashbrown version may vary based on the version of PyO3. use crate::{ types::any::PyAnyMethods, types::dict::PyDictMethods, types::frozenset::PyFrozenSetMethods, types::set::{new_from_iter, PySetMethods}, types::{IntoPyDict, PyDict, PyFrozenSet, PySet}, Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use std::{cmp, hash}; impl ToPyObject for hashbrown::HashMap where K: hash::Hash + cmp::Eq + ToPyObject, V: ToPyObject, H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { IntoPyDict::into_py_dict_bound(self, py).into() } } impl IntoPy for hashbrown::HashMap where K: hash::Hash + cmp::Eq + IntoPy, V: IntoPy, H: hash::BuildHasher, { fn into_py(self, py: Python<'_>) -> PyObject { let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); IntoPyDict::into_py_dict_bound(iter, py).into() } } impl<'py, K, V, S> FromPyObject<'py> for hashbrown::HashMap where K: FromPyObject<'py> + cmp::Eq + hash::Hash, V: FromPyObject<'py>, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = hashbrown::HashMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } } impl ToPyObject for hashbrown::HashSet where T: hash::Hash + Eq + ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { new_from_iter(py, self) .expect("Failed to create Python set from hashbrown::HashSet") .into() } } impl IntoPy for hashbrown::HashSet where K: IntoPy + Eq + hash::Hash, S: hash::BuildHasher + Default, { fn into_py(self, py: Python<'_>) -> PyObject { new_from_iter(py, self.into_iter().map(|item| item.into_py(py))) .expect("Failed to create Python set from hashbrown::HashSet") .into() } } impl<'py, K, S> FromPyObject<'py> for hashbrown::HashSet where K: FromPyObject<'py> + cmp::Eq + hash::Hash, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { match ob.downcast::() { Ok(set) => set.iter().map(|any| any.extract()).collect(), Err(err) => { if let Ok(frozen_set) = ob.downcast::() { frozen_set.iter().map(|any| any.extract()).collect() } else { Err(PyErr::from(err)) } } } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_hashbrown_hashmap_to_python() { Python::with_gil(|py| { let mut map = hashbrown::HashMap::::new(); map.insert(1, 1); let m = map.to_object(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!(map, py_map.extract().unwrap()); }); } #[test] fn test_hashbrown_hashmap_into_python() { Python::with_gil(|py| { let mut map = hashbrown::HashMap::::new(); map.insert(1, 1); let m: PyObject = map.into_py(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); }); } #[test] fn test_hashbrown_hashmap_into_dict() { Python::with_gil(|py| { let mut map = hashbrown::HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict_bound(py); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_extract_hashbrown_hashset() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); let hash_set: hashbrown::HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); let set = PyFrozenSet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); let hash_set: hashbrown::HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); }); } #[test] fn test_hashbrown_hashset_into_py() { Python::with_gil(|py| { let hs: hashbrown::HashSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let hso: PyObject = hs.clone().into_py(py); assert_eq!(hs, hso.extract(py).unwrap()); }); } } pyo3/src/conversions/chrono.rs0000644000175000017500000013647014661133735017443 0ustar jamespagejamespage#![cfg(feature = "chrono")] //! Conversions to and from [chrono](https://docs.rs/chrono/)’s `Duration`, //! `NaiveDate`, `NaiveTime`, `DateTime`, `FixedOffset`, and `Utc`. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! chrono = "0.4" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"chrono\"] }")] //! ``` //! //! Note that you must use compatible versions of chrono and PyO3. //! The required chrono version may vary based on the version of PyO3. //! //! # Example: Convert a `datetime.datetime` to chrono's `DateTime` //! //! ```rust //! use chrono::{DateTime, Duration, TimeZone, Utc}; //! use pyo3::{Python, ToPyObject}; //! //! fn main() { //! pyo3::prepare_freethreaded_python(); //! Python::with_gil(|py| { //! // Build some chrono values //! let chrono_datetime = Utc.with_ymd_and_hms(2022, 1, 1, 12, 0, 0).unwrap(); //! let chrono_duration = Duration::seconds(1); //! // Convert them to Python //! let py_datetime = chrono_datetime.to_object(py); //! let py_timedelta = chrono_duration.to_object(py); //! // Do an operation in Python //! let py_sum = py_datetime.call_method1(py, "__add__", (py_timedelta,)).unwrap(); //! // Convert back to Rust //! let chrono_sum: DateTime = py_sum.extract(py).unwrap(); //! println!("DateTime: {}", chrono_datetime); //! }); //! } //! ``` use crate::exceptions::{PyTypeError, PyUserWarning, PyValueError}; #[cfg(Py_LIMITED_API)] use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; #[cfg(not(Py_LIMITED_API))] use crate::types::datetime::timezone_from_offset; #[cfg(not(Py_LIMITED_API))] use crate::types::{ timezone_utc_bound, PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTzInfo, PyTzInfoAccess, }; #[cfg(Py_LIMITED_API)] use crate::{intern, DowncastError}; use crate::{Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject}; use chrono::offset::{FixedOffset, Utc}; use chrono::{ DateTime, Datelike, Duration, NaiveDate, NaiveDateTime, NaiveTime, Offset, TimeZone, Timelike, }; impl ToPyObject for Duration { fn to_object(&self, py: Python<'_>) -> PyObject { // Total number of days let days = self.num_days(); // Remainder of seconds let secs_dur = *self - Duration::days(days); let secs = secs_dur.num_seconds(); // Fractional part of the microseconds let micros = (secs_dur - Duration::seconds(secs_dur.num_seconds())) .num_microseconds() // This should never panic since we are just getting the fractional // part of the total microseconds, which should never overflow. .unwrap(); #[cfg(not(Py_LIMITED_API))] { // We do not need to check the days i64 to i32 cast from rust because // python will panic with OverflowError. // We pass true as the `normalize` parameter since we'd need to do several checks here to // avoid that, and it shouldn't have a big performance impact. // The seconds and microseconds cast should never overflow since it's at most the number of seconds per day PyDelta::new_bound( py, days.try_into().unwrap_or(i32::MAX), secs.try_into().unwrap(), micros.try_into().unwrap(), true, ) .expect("failed to construct delta") .into() } #[cfg(Py_LIMITED_API)] { DatetimeTypes::get(py) .timedelta .call1(py, (days, secs, micros)) .expect("failed to construct datetime.timedelta") } } } impl IntoPy for Duration { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'_> for Duration { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { // Python size are much lower than rust size so we do not need bound checks. // 0 <= microseconds < 1000000 // 0 <= seconds < 3600*24 // -999999999 <= days <= 999999999 #[cfg(not(Py_LIMITED_API))] let (days, seconds, microseconds) = { let delta = ob.downcast::()?; ( delta.get_days().into(), delta.get_seconds().into(), delta.get_microseconds().into(), ) }; #[cfg(Py_LIMITED_API)] let (days, seconds, microseconds) = { check_type(ob, &DatetimeTypes::get(ob.py()).timedelta, "PyDelta")?; ( ob.getattr(intern!(ob.py(), "days"))?.extract()?, ob.getattr(intern!(ob.py(), "seconds"))?.extract()?, ob.getattr(intern!(ob.py(), "microseconds"))?.extract()?, ) }; Ok( Duration::days(days) + Duration::seconds(seconds) + Duration::microseconds(microseconds), ) } } impl ToPyObject for NaiveDate { fn to_object(&self, py: Python<'_>) -> PyObject { let DateArgs { year, month, day } = self.into(); #[cfg(not(Py_LIMITED_API))] { PyDate::new_bound(py, year, month, day) .expect("failed to construct date") .into() } #[cfg(Py_LIMITED_API)] { DatetimeTypes::get(py) .date .call1(py, (year, month, day)) .expect("failed to construct datetime.date") } } } impl IntoPy for NaiveDate { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'_> for NaiveDate { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { #[cfg(not(Py_LIMITED_API))] { let date = ob.downcast::()?; py_date_to_naive_date(date) } #[cfg(Py_LIMITED_API)] { check_type(ob, &DatetimeTypes::get(ob.py()).date, "PyDate")?; py_date_to_naive_date(ob) } } } impl ToPyObject for NaiveTime { fn to_object(&self, py: Python<'_>) -> PyObject { let TimeArgs { hour, min, sec, micro, truncated_leap_second, } = self.into(); #[cfg(not(Py_LIMITED_API))] let time = PyTime::new_bound(py, hour, min, sec, micro, None).expect("Failed to construct time"); #[cfg(Py_LIMITED_API)] let time = DatetimeTypes::get(py) .time .bind(py) .call1((hour, min, sec, micro)) .expect("failed to construct datetime.time"); if truncated_leap_second { warn_truncated_leap_second(&time); } time.into() } } impl IntoPy for NaiveTime { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'_> for NaiveTime { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { #[cfg(not(Py_LIMITED_API))] { let time = ob.downcast::()?; py_time_to_naive_time(time) } #[cfg(Py_LIMITED_API)] { check_type(ob, &DatetimeTypes::get(ob.py()).time, "PyTime")?; py_time_to_naive_time(ob) } } } impl ToPyObject for NaiveDateTime { fn to_object(&self, py: Python<'_>) -> PyObject { naive_datetime_to_py_datetime(py, self, None) } } impl IntoPy for NaiveDateTime { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'_> for NaiveDateTime { fn extract_bound(dt: &Bound<'_, PyAny>) -> PyResult { #[cfg(not(Py_LIMITED_API))] let dt = dt.downcast::()?; #[cfg(Py_LIMITED_API)] check_type(dt, &DatetimeTypes::get(dt.py()).datetime, "PyDateTime")?; // If the user tries to convert a timezone aware datetime into a naive one, // we return a hard error. We could silently remove tzinfo, or assume local timezone // and do a conversion, but better leave this decision to the user of the library. #[cfg(not(Py_LIMITED_API))] let has_tzinfo = dt.get_tzinfo_bound().is_some(); #[cfg(Py_LIMITED_API)] let has_tzinfo = !dt.getattr(intern!(dt.py(), "tzinfo"))?.is_none(); if has_tzinfo { return Err(PyTypeError::new_err("expected a datetime without tzinfo")); } let dt = NaiveDateTime::new(py_date_to_naive_date(dt)?, py_time_to_naive_time(dt)?); Ok(dt) } } impl ToPyObject for DateTime { fn to_object(&self, py: Python<'_>) -> PyObject { // FIXME: convert to better timezone representation here than just convert to fixed offset // See https://github.com/PyO3/pyo3/issues/3266 let tz = self.offset().fix().to_object(py); let tz = tz.bind(py).downcast().unwrap(); naive_datetime_to_py_datetime(py, &self.naive_local(), Some(tz)) } } impl IntoPy for DateTime { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'py>> FromPyObject<'_> for DateTime { fn extract_bound(dt: &Bound<'_, PyAny>) -> PyResult> { #[cfg(not(Py_LIMITED_API))] let dt = dt.downcast::()?; #[cfg(Py_LIMITED_API)] check_type(dt, &DatetimeTypes::get(dt.py()).datetime, "PyDateTime")?; #[cfg(not(Py_LIMITED_API))] let tzinfo = dt.get_tzinfo_bound(); #[cfg(Py_LIMITED_API)] let tzinfo: Option> = dt.getattr(intern!(dt.py(), "tzinfo"))?.extract()?; let tz = if let Some(tzinfo) = tzinfo { tzinfo.extract()? } else { return Err(PyTypeError::new_err( "expected a datetime with non-None tzinfo", )); }; let naive_dt = NaiveDateTime::new(py_date_to_naive_date(dt)?, py_time_to_naive_time(dt)?); naive_dt.and_local_timezone(tz).single().ok_or_else(|| { PyValueError::new_err(format!( "The datetime {:?} contains an incompatible or ambiguous timezone", dt )) }) } } impl ToPyObject for FixedOffset { fn to_object(&self, py: Python<'_>) -> PyObject { let seconds_offset = self.local_minus_utc(); #[cfg(not(Py_LIMITED_API))] { let td = PyDelta::new_bound(py, 0, seconds_offset, 0, true) .expect("failed to construct timedelta"); timezone_from_offset(&td) .expect("Failed to construct PyTimezone") .into() } #[cfg(Py_LIMITED_API)] { let td = Duration::seconds(seconds_offset.into()).into_py(py); DatetimeTypes::get(py) .timezone .call1(py, (td,)) .expect("failed to construct datetime.timezone") } } } impl IntoPy for FixedOffset { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'_> for FixedOffset { /// Convert python tzinfo to rust [`FixedOffset`]. /// /// Note that the conversion will result in precision lost in microseconds as chrono offset /// does not supports microseconds. fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { #[cfg(not(Py_LIMITED_API))] let ob = ob.downcast::()?; #[cfg(Py_LIMITED_API)] check_type(ob, &DatetimeTypes::get(ob.py()).tzinfo, "PyTzInfo")?; // Passing `()` (so Python's None) to the `utcoffset` function will only // work for timezones defined as fixed offsets in Python. // Any other timezone would require a datetime as the parameter, and return // None if the datetime is not provided. // Trying to convert None to a PyDelta in the next line will then fail. let py_timedelta = ob.call_method1("utcoffset", ((),))?; if py_timedelta.is_none() { return Err(PyTypeError::new_err(format!( "{:?} is not a fixed offset timezone", ob ))); } let total_seconds: Duration = py_timedelta.extract()?; // This cast is safe since the timedelta is limited to -24 hours and 24 hours. let total_seconds = total_seconds.num_seconds() as i32; FixedOffset::east_opt(total_seconds) .ok_or_else(|| PyValueError::new_err("fixed offset out of bounds")) } } impl ToPyObject for Utc { fn to_object(&self, py: Python<'_>) -> PyObject { timezone_utc_bound(py).into() } } impl IntoPy for Utc { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl FromPyObject<'_> for Utc { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { let py_utc = timezone_utc_bound(ob.py()); if ob.eq(py_utc)? { Ok(Utc) } else { Err(PyValueError::new_err("expected datetime.timezone.utc")) } } } struct DateArgs { year: i32, month: u8, day: u8, } impl From<&NaiveDate> for DateArgs { fn from(value: &NaiveDate) -> Self { Self { year: value.year(), month: value.month() as u8, day: value.day() as u8, } } } struct TimeArgs { hour: u8, min: u8, sec: u8, micro: u32, truncated_leap_second: bool, } impl From<&NaiveTime> for TimeArgs { fn from(value: &NaiveTime) -> Self { let ns = value.nanosecond(); let checked_sub = ns.checked_sub(1_000_000_000); let truncated_leap_second = checked_sub.is_some(); let micro = checked_sub.unwrap_or(ns) / 1000; Self { hour: value.hour() as u8, min: value.minute() as u8, sec: value.second() as u8, micro, truncated_leap_second, } } } fn naive_datetime_to_py_datetime( py: Python<'_>, naive_datetime: &NaiveDateTime, #[cfg(not(Py_LIMITED_API))] tzinfo: Option<&Bound<'_, PyTzInfo>>, #[cfg(Py_LIMITED_API)] tzinfo: Option<&Bound<'_, PyAny>>, ) -> PyObject { let DateArgs { year, month, day } = (&naive_datetime.date()).into(); let TimeArgs { hour, min, sec, micro, truncated_leap_second, } = (&naive_datetime.time()).into(); #[cfg(not(Py_LIMITED_API))] let datetime = PyDateTime::new_bound(py, year, month, day, hour, min, sec, micro, tzinfo) .expect("failed to construct datetime"); #[cfg(Py_LIMITED_API)] let datetime = DatetimeTypes::get(py) .datetime .bind(py) .call1((year, month, day, hour, min, sec, micro, tzinfo)) .expect("failed to construct datetime.datetime"); if truncated_leap_second { warn_truncated_leap_second(&datetime); } datetime.into() } fn warn_truncated_leap_second(obj: &Bound<'_, PyAny>) { let py = obj.py(); if let Err(e) = PyErr::warn_bound( py, &py.get_type_bound::(), "ignored leap-second, `datetime` does not support leap-seconds", 0, ) { e.write_unraisable_bound(py, Some(&obj.as_borrowed())) }; } #[cfg(not(Py_LIMITED_API))] fn py_date_to_naive_date(py_date: &impl PyDateAccess) -> PyResult { NaiveDate::from_ymd_opt( py_date.get_year(), py_date.get_month().into(), py_date.get_day().into(), ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range date")) } #[cfg(Py_LIMITED_API)] fn py_date_to_naive_date(py_date: &Bound<'_, PyAny>) -> PyResult { NaiveDate::from_ymd_opt( py_date.getattr(intern!(py_date.py(), "year"))?.extract()?, py_date.getattr(intern!(py_date.py(), "month"))?.extract()?, py_date.getattr(intern!(py_date.py(), "day"))?.extract()?, ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range date")) } #[cfg(not(Py_LIMITED_API))] fn py_time_to_naive_time(py_time: &impl PyTimeAccess) -> PyResult { NaiveTime::from_hms_micro_opt( py_time.get_hour().into(), py_time.get_minute().into(), py_time.get_second().into(), py_time.get_microsecond(), ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range time")) } #[cfg(Py_LIMITED_API)] fn py_time_to_naive_time(py_time: &Bound<'_, PyAny>) -> PyResult { NaiveTime::from_hms_micro_opt( py_time.getattr(intern!(py_time.py(), "hour"))?.extract()?, py_time .getattr(intern!(py_time.py(), "minute"))? .extract()?, py_time .getattr(intern!(py_time.py(), "second"))? .extract()?, py_time .getattr(intern!(py_time.py(), "microsecond"))? .extract()?, ) .ok_or_else(|| PyValueError::new_err("invalid or out-of-range time")) } #[cfg(Py_LIMITED_API)] fn check_type(value: &Bound<'_, PyAny>, t: &PyObject, type_name: &'static str) -> PyResult<()> { if !value.is_instance(t.bind(value.py()))? { return Err(DowncastError::new(value, type_name).into()); } Ok(()) } #[cfg(Py_LIMITED_API)] struct DatetimeTypes { date: PyObject, datetime: PyObject, time: PyObject, timedelta: PyObject, timezone: PyObject, timezone_utc: PyObject, tzinfo: PyObject, } #[cfg(Py_LIMITED_API)] impl DatetimeTypes { fn get(py: Python<'_>) -> &Self { static TYPES: GILOnceCell = GILOnceCell::new(); TYPES .get_or_try_init(py, || { let datetime = py.import_bound("datetime")?; let timezone = datetime.getattr("timezone")?; Ok::<_, PyErr>(Self { date: datetime.getattr("date")?.into(), datetime: datetime.getattr("datetime")?.into(), time: datetime.getattr("time")?.into(), timedelta: datetime.getattr("timedelta")?.into(), timezone_utc: timezone.getattr("utc")?.into(), timezone: timezone.into(), tzinfo: datetime.getattr("tzinfo")?.into(), }) }) .expect("failed to load datetime module") } } #[cfg(Py_LIMITED_API)] fn timezone_utc_bound(py: Python<'_>) -> Bound<'_, PyAny> { DatetimeTypes::get(py).timezone_utc.bind(py).clone() } #[cfg(test)] mod tests { use super::*; use crate::{types::PyTuple, Py}; use std::{cmp::Ordering, panic}; #[test] // Only Python>=3.9 has the zoneinfo package // We skip the test on windows too since we'd need to install // tzdata there to make this work. #[cfg(all(Py_3_9, not(target_os = "windows")))] fn test_zoneinfo_is_not_fixed_offset() { use crate::types::any::PyAnyMethods; use crate::types::dict::PyDictMethods; Python::with_gil(|py| { let locals = crate::types::PyDict::new_bound(py); py.run_bound( "import zoneinfo; zi = zoneinfo.ZoneInfo('Europe/London')", None, Some(&locals), ) .unwrap(); let result: PyResult = locals.get_item("zi").unwrap().unwrap().extract(); assert!(result.is_err()); let res = result.err().unwrap(); // Also check the error message is what we expect let msg = res.value_bound(py).repr().unwrap().to_string(); assert_eq!(msg, "TypeError(\"zoneinfo.ZoneInfo(key='Europe/London') is not a fixed offset timezone\")"); }); } #[test] fn test_timezone_aware_to_naive_fails() { // Test that if a user tries to convert a python's timezone aware datetime into a naive // one, the conversion fails. Python::with_gil(|py| { let py_datetime = new_py_datetime_ob(py, "datetime", (2022, 1, 1, 1, 0, 0, 0, python_utc(py))); // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails let res: PyResult = py_datetime.extract(); assert_eq!( res.unwrap_err().value_bound(py).repr().unwrap().to_string(), "TypeError('expected a datetime without tzinfo')" ); }); } #[test] fn test_naive_to_timezone_aware_fails() { // Test that if a user tries to convert a python's timezone aware datetime into a naive // one, the conversion fails. Python::with_gil(|py| { let py_datetime = new_py_datetime_ob(py, "datetime", (2022, 1, 1, 1, 0, 0, 0)); // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails let res: PyResult> = py_datetime.extract(); assert_eq!( res.unwrap_err().value_bound(py).repr().unwrap().to_string(), "TypeError('expected a datetime with non-None tzinfo')" ); // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails let res: PyResult> = py_datetime.extract(); assert_eq!( res.unwrap_err().value_bound(py).repr().unwrap().to_string(), "TypeError('expected a datetime with non-None tzinfo')" ); }); } #[test] fn test_invalid_types_fail() { // Test that if a user tries to convert a python's timezone aware datetime into a naive // one, the conversion fails. Python::with_gil(|py| { let none = py.None().into_bound(py); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be converted to 'PyDelta'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be converted to 'PyTzInfo'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "ValueError: expected datetime.timezone.utc" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be converted to 'PyTime'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be converted to 'PyDate'" ); assert_eq!( none.extract::().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be converted to 'PyDateTime'" ); assert_eq!( none.extract::>().unwrap_err().to_string(), "TypeError: 'NoneType' object cannot be converted to 'PyDateTime'" ); assert_eq!( none.extract::>() .unwrap_err() .to_string(), "TypeError: 'NoneType' object cannot be converted to 'PyDateTime'" ); }); } #[test] fn test_pyo3_timedelta_topyobject() { // Utility function used to check different durations. // The `name` parameter is used to identify the check in case of a failure. let check = |name: &'static str, delta: Duration, py_days, py_seconds, py_ms| { Python::with_gil(|py| { let delta = delta.to_object(py); let py_delta = new_py_datetime_ob(py, "timedelta", (py_days, py_seconds, py_ms)); assert!( delta.bind(py).eq(&py_delta).unwrap(), "{}: {} != {}", name, delta, py_delta ); }); }; let delta = Duration::days(-1) + Duration::seconds(1) + Duration::microseconds(-10); check("delta normalization", delta, -1, 1, -10); // Check the minimum value allowed by PyDelta, which is different // from the minimum value allowed in Duration. This should pass. let delta = Duration::seconds(-86399999913600); // min check("delta min value", delta, -999999999, 0, 0); // Same, for max value let delta = Duration::seconds(86399999999999) + Duration::nanoseconds(999999000); // max check("delta max value", delta, 999999999, 86399, 999999); // Also check that trying to convert an out of bound value panics. Python::with_gil(|py| { assert!(panic::catch_unwind(|| Duration::min_value().to_object(py)).is_err()); assert!(panic::catch_unwind(|| Duration::max_value().to_object(py)).is_err()); }); } #[test] fn test_pyo3_timedelta_frompyobject() { // Utility function used to check different durations. // The `name` parameter is used to identify the check in case of a failure. let check = |name: &'static str, delta: Duration, py_days, py_seconds, py_ms| { Python::with_gil(|py| { let py_delta = new_py_datetime_ob(py, "timedelta", (py_days, py_seconds, py_ms)); let py_delta: Duration = py_delta.extract().unwrap(); assert_eq!(py_delta, delta, "{}: {} != {}", name, py_delta, delta); }) }; // Check the minimum value allowed by PyDelta, which is different // from the minimum value allowed in Duration. This should pass. check( "min py_delta value", Duration::seconds(-86399999913600), -999999999, 0, 0, ); // Same, for max value check( "max py_delta value", Duration::seconds(86399999999999) + Duration::microseconds(999999), 999999999, 86399, 999999, ); // This check is to assert that we can't construct every possible Duration from a PyDelta // since they have different bounds. Python::with_gil(|py| { let low_days: i32 = -1000000000; // This is possible assert!(panic::catch_unwind(|| Duration::days(low_days as i64)).is_ok()); // This panics on PyDelta::new assert!(panic::catch_unwind(|| { let py_delta = new_py_datetime_ob(py, "timedelta", (low_days, 0, 0)); if let Ok(_duration) = py_delta.extract::() { // So we should never get here } }) .is_err()); let high_days: i32 = 1000000000; // This is possible assert!(panic::catch_unwind(|| Duration::days(high_days as i64)).is_ok()); // This panics on PyDelta::new assert!(panic::catch_unwind(|| { let py_delta = new_py_datetime_ob(py, "timedelta", (high_days, 0, 0)); if let Ok(_duration) = py_delta.extract::() { // So we should never get here } }) .is_err()); }); } #[test] fn test_pyo3_date_topyobject() { let eq_ymd = |name: &'static str, year, month, day| { Python::with_gil(|py| { let date = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .to_object(py); let py_date = new_py_datetime_ob(py, "date", (year, month, day)); assert_eq!( date.bind(py).compare(&py_date).unwrap(), Ordering::Equal, "{}: {} != {}", name, date, py_date ); }) }; eq_ymd("past date", 2012, 2, 29); eq_ymd("min date", 1, 1, 1); eq_ymd("future date", 3000, 6, 5); eq_ymd("max date", 9999, 12, 31); } #[test] fn test_pyo3_date_frompyobject() { let eq_ymd = |name: &'static str, year, month, day| { Python::with_gil(|py| { let py_date = new_py_datetime_ob(py, "date", (year, month, day)); let py_date: NaiveDate = py_date.extract().unwrap(); let date = NaiveDate::from_ymd_opt(year, month, day).unwrap(); assert_eq!(py_date, date, "{}: {} != {}", name, date, py_date); }) }; eq_ymd("past date", 2012, 2, 29); eq_ymd("min date", 1, 1, 1); eq_ymd("future date", 3000, 6, 5); eq_ymd("max date", 9999, 12, 31); } #[test] fn test_pyo3_datetime_topyobject_utc() { Python::with_gil(|py| { let check_utc = |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| { let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, ms) .unwrap() .and_utc(); let datetime = datetime.to_object(py); let py_datetime = new_py_datetime_ob( py, "datetime", ( year, month, day, hour, minute, second, py_ms, python_utc(py), ), ); assert_eq!( datetime.bind(py).compare(&py_datetime).unwrap(), Ordering::Equal, "{}: {} != {}", name, datetime, py_datetime ); }; check_utc("regular", 2014, 5, 6, 7, 8, 9, 999_999, 999_999); assert_warnings!( py, check_utc("leap second", 2014, 5, 6, 7, 8, 59, 1_999_999, 999_999), [( PyUserWarning, "ignored leap-second, `datetime` does not support leap-seconds" )] ); }) } #[test] fn test_pyo3_datetime_topyobject_fixed_offset() { Python::with_gil(|py| { let check_fixed_offset = |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| { let offset = FixedOffset::east_opt(3600).unwrap(); let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, ms) .unwrap() .and_local_timezone(offset) .unwrap(); let datetime = datetime.to_object(py); let py_tz = offset.to_object(py); let py_datetime = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, py_ms, py_tz), ); assert_eq!( datetime.bind(py).compare(&py_datetime).unwrap(), Ordering::Equal, "{}: {} != {}", name, datetime, py_datetime ); }; check_fixed_offset("regular", 2014, 5, 6, 7, 8, 9, 999_999, 999_999); assert_warnings!( py, check_fixed_offset("leap second", 2014, 5, 6, 7, 8, 59, 1_999_999, 999_999), [( PyUserWarning, "ignored leap-second, `datetime` does not support leap-seconds" )] ); }) } #[test] fn test_pyo3_datetime_frompyobject_utc() { Python::with_gil(|py| { let year = 2014; let month = 5; let day = 6; let hour = 7; let minute = 8; let second = 9; let micro = 999_999; let tz_utc = timezone_utc_bound(py); let py_datetime = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, micro, tz_utc), ); let py_datetime: DateTime = py_datetime.extract().unwrap(); let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, micro) .unwrap() .and_utc(); assert_eq!(py_datetime, datetime,); }) } #[test] fn test_pyo3_datetime_frompyobject_fixed_offset() { Python::with_gil(|py| { let year = 2014; let month = 5; let day = 6; let hour = 7; let minute = 8; let second = 9; let micro = 999_999; let offset = FixedOffset::east_opt(3600).unwrap(); let py_tz = offset.to_object(py); let py_datetime = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, micro, py_tz), ); let datetime_from_py: DateTime = py_datetime.extract().unwrap(); let datetime = NaiveDate::from_ymd_opt(year, month, day) .unwrap() .and_hms_micro_opt(hour, minute, second, micro) .unwrap(); let datetime = datetime.and_local_timezone(offset).unwrap(); assert_eq!(datetime_from_py, datetime); assert!( py_datetime.extract::>().is_err(), "Extracting Utc from nonzero FixedOffset timezone will fail" ); let utc = python_utc(py); let py_datetime_utc = new_py_datetime_ob( py, "datetime", (year, month, day, hour, minute, second, micro, utc), ); assert!( py_datetime_utc.extract::>().is_ok(), "Extracting FixedOffset from Utc timezone will succeed" ); }) } #[test] fn test_pyo3_offset_fixed_topyobject() { Python::with_gil(|py| { // Chrono offset let offset = FixedOffset::east_opt(3600).unwrap().to_object(py); // Python timezone from timedelta let td = new_py_datetime_ob(py, "timedelta", (0, 3600, 0)); let py_timedelta = new_py_datetime_ob(py, "timezone", (td,)); // Should be equal assert!(offset.bind(py).eq(py_timedelta).unwrap()); // Same but with negative values let offset = FixedOffset::east_opt(-3600).unwrap().to_object(py); let td = new_py_datetime_ob(py, "timedelta", (0, -3600, 0)); let py_timedelta = new_py_datetime_ob(py, "timezone", (td,)); assert!(offset.bind(py).eq(py_timedelta).unwrap()); }) } #[test] fn test_pyo3_offset_fixed_frompyobject() { Python::with_gil(|py| { let py_timedelta = new_py_datetime_ob(py, "timedelta", (0, 3600, 0)); let py_tzinfo = new_py_datetime_ob(py, "timezone", (py_timedelta,)); let offset: FixedOffset = py_tzinfo.extract().unwrap(); assert_eq!(FixedOffset::east_opt(3600).unwrap(), offset); }) } #[test] fn test_pyo3_offset_utc_topyobject() { Python::with_gil(|py| { let utc = Utc.to_object(py); let py_utc = python_utc(py); assert!(utc.bind(py).is(&py_utc)); }) } #[test] fn test_pyo3_offset_utc_frompyobject() { Python::with_gil(|py| { let py_utc = python_utc(py); let py_utc: Utc = py_utc.extract().unwrap(); assert_eq!(Utc, py_utc); let py_timedelta = new_py_datetime_ob(py, "timedelta", (0, 0, 0)); let py_timezone_utc = new_py_datetime_ob(py, "timezone", (py_timedelta,)); let py_timezone_utc: Utc = py_timezone_utc.extract().unwrap(); assert_eq!(Utc, py_timezone_utc); let py_timedelta = new_py_datetime_ob(py, "timedelta", (0, 3600, 0)); let py_timezone = new_py_datetime_ob(py, "timezone", (py_timedelta,)); assert!(py_timezone.extract::().is_err()); }) } #[test] fn test_pyo3_time_topyobject() { Python::with_gil(|py| { let check_time = |name: &'static str, hour, minute, second, ms, py_ms| { let time = NaiveTime::from_hms_micro_opt(hour, minute, second, ms) .unwrap() .to_object(py); let py_time = new_py_datetime_ob(py, "time", (hour, minute, second, py_ms)); assert!( time.bind(py).eq(&py_time).unwrap(), "{}: {} != {}", name, time, py_time ); }; check_time("regular", 3, 5, 7, 999_999, 999_999); assert_warnings!( py, check_time("leap second", 3, 5, 59, 1_999_999, 999_999), [( PyUserWarning, "ignored leap-second, `datetime` does not support leap-seconds" )] ); }) } #[test] fn test_pyo3_time_frompyobject() { let hour = 3; let minute = 5; let second = 7; let micro = 999_999; Python::with_gil(|py| { let py_time = new_py_datetime_ob(py, "time", (hour, minute, second, micro)); let py_time: NaiveTime = py_time.extract().unwrap(); let time = NaiveTime::from_hms_micro_opt(hour, minute, second, micro).unwrap(); assert_eq!(py_time, time); }) } fn new_py_datetime_ob<'py>( py: Python<'py>, name: &str, args: impl IntoPy>, ) -> Bound<'py, PyAny> { py.import_bound("datetime") .unwrap() .getattr(name) .unwrap() .call1(args) .unwrap() } fn python_utc(py: Python<'_>) -> Bound<'_, PyAny> { py.import_bound("datetime") .unwrap() .getattr("timezone") .unwrap() .getattr("utc") .unwrap() } #[cfg(not(target_arch = "wasm32"))] mod proptests { use super::*; use crate::tests::common::CatchWarnings; use crate::types::IntoPyDict; use proptest::prelude::*; proptest! { // Range is limited to 1970 to 2038 due to windows limitations #[test] fn test_pyo3_offset_fixed_frompyobject_created_in_python(timestamp in 0..(i32::MAX as i64), timedelta in -86399i32..=86399i32) { Python::with_gil(|py| { let globals = [("datetime", py.import_bound("datetime").unwrap())].into_py_dict_bound(py); let code = format!("datetime.datetime.fromtimestamp({}).replace(tzinfo=datetime.timezone(datetime.timedelta(seconds={})))", timestamp, timedelta); let t = py.eval_bound(&code, Some(&globals), None).unwrap(); // Get ISO 8601 string from python let py_iso_str = t.call_method0("isoformat").unwrap(); // Get ISO 8601 string from rust let t = t.extract::>().unwrap(); // Python doesn't print the seconds of the offset if they are 0 let rust_iso_str = if timedelta % 60 == 0 { t.format("%Y-%m-%dT%H:%M:%S%:z").to_string() } else { t.format("%Y-%m-%dT%H:%M:%S%::z").to_string() }; // They should be equal assert_eq!(py_iso_str.to_string(), rust_iso_str); }) } #[test] fn test_duration_roundtrip(days in -999999999i64..=999999999i64) { // Test roundtrip conversion rust->python->rust for all allowed // python values of durations (from -999999999 to 999999999 days), Python::with_gil(|py| { let dur = Duration::days(days); let py_delta = dur.into_py(py); let roundtripped: Duration = py_delta.extract(py).expect("Round trip"); assert_eq!(dur, roundtripped); }) } #[test] fn test_fixed_offset_roundtrip(secs in -86399i32..=86399i32) { Python::with_gil(|py| { let offset = FixedOffset::east_opt(secs).unwrap(); let py_offset = offset.into_py(py); let roundtripped: FixedOffset = py_offset.extract(py).expect("Round trip"); assert_eq!(offset, roundtripped); }) } #[test] fn test_naive_date_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32 ) { // Test roundtrip conversion rust->python->rust for all allowed // python dates (from year 1 to year 9999) Python::with_gil(|py| { // We use to `from_ymd_opt` constructor so that we only test valid `NaiveDate`s. // This is to skip the test if we are creating an invalid date, like February 31. if let Some(date) = NaiveDate::from_ymd_opt(year, month, day) { let py_date = date.to_object(py); let roundtripped: NaiveDate = py_date.extract(py).expect("Round trip"); assert_eq!(date, roundtripped); } }) } #[test] fn test_naive_time_roundtrip( hour in 0u32..=23u32, min in 0u32..=59u32, sec in 0u32..=59u32, micro in 0u32..=1_999_999u32 ) { // Test roundtrip conversion rust->python->rust for naive times. // Python time has a resolution of microseconds, so we only test // NaiveTimes with microseconds resolution, even if NaiveTime has nanosecond // resolution. Python::with_gil(|py| { if let Some(time) = NaiveTime::from_hms_micro_opt(hour, min, sec, micro) { // Wrap in CatchWarnings to avoid to_object firing warning for truncated leap second let py_time = CatchWarnings::enter(py, |_| Ok(time.to_object(py))).unwrap(); let roundtripped: NaiveTime = py_time.extract(py).expect("Round trip"); // Leap seconds are not roundtripped let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time); assert_eq!(expected_roundtrip_time, roundtripped); } }) } #[test] fn test_naive_datetime_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32, hour in 0u32..=24u32, min in 0u32..=60u32, sec in 0u32..=60u32, micro in 0u32..=999_999u32 ) { Python::with_gil(|py| { let date_opt = NaiveDate::from_ymd_opt(year, month, day); let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro); if let (Some(date), Some(time)) = (date_opt, time_opt) { let dt = NaiveDateTime::new(date, time); let pydt = dt.to_object(py); let roundtripped: NaiveDateTime = pydt.extract(py).expect("Round trip"); assert_eq!(dt, roundtripped); } }) } #[test] fn test_utc_datetime_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32, hour in 0u32..=23u32, min in 0u32..=59u32, sec in 0u32..=59u32, micro in 0u32..=1_999_999u32 ) { Python::with_gil(|py| { let date_opt = NaiveDate::from_ymd_opt(year, month, day); let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro); if let (Some(date), Some(time)) = (date_opt, time_opt) { let dt: DateTime = NaiveDateTime::new(date, time).and_utc(); // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second let py_dt = CatchWarnings::enter(py, |_| Ok(dt.into_py(py))).unwrap(); let roundtripped: DateTime = py_dt.extract(py).expect("Round trip"); // Leap seconds are not roundtripped let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time); let expected_roundtrip_dt: DateTime = NaiveDateTime::new(date, expected_roundtrip_time).and_utc(); assert_eq!(expected_roundtrip_dt, roundtripped); } }) } #[test] fn test_fixed_offset_datetime_roundtrip( year in 1i32..=9999i32, month in 1u32..=12u32, day in 1u32..=31u32, hour in 0u32..=23u32, min in 0u32..=59u32, sec in 0u32..=59u32, micro in 0u32..=1_999_999u32, offset_secs in -86399i32..=86399i32 ) { Python::with_gil(|py| { let date_opt = NaiveDate::from_ymd_opt(year, month, day); let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro); let offset = FixedOffset::east_opt(offset_secs).unwrap(); if let (Some(date), Some(time)) = (date_opt, time_opt) { let dt: DateTime = NaiveDateTime::new(date, time).and_local_timezone(offset).unwrap(); // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second let py_dt = CatchWarnings::enter(py, |_| Ok(dt.into_py(py))).unwrap(); let roundtripped: DateTime = py_dt.extract(py).expect("Round trip"); // Leap seconds are not roundtripped let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time); let expected_roundtrip_dt: DateTime = NaiveDateTime::new(date, expected_roundtrip_time).and_local_timezone(offset).unwrap(); assert_eq!(expected_roundtrip_dt, roundtripped); } }) } } } } pyo3/src/conversions/num_complex.rs0000644000175000017500000002725014661133735020474 0ustar jamespagejamespage#![cfg(feature = "num-complex")] //! Conversions to and from [num-complex](https://docs.rs/num-complex)’ //! [`Complex`]`<`[`f32`]`>` and [`Complex`]`<`[`f64`]`>`. //! //! num-complex’ [`Complex`] supports more operations than PyO3's [`PyComplex`] //! and can be used with the rest of the Rust ecosystem. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! num-complex = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"num-complex\"] }")] //! ``` //! //! Note that you must use compatible versions of num-complex and PyO3. //! The required num-complex version may vary based on the version of PyO3. //! //! # Examples //! //! Using [num-complex](https://docs.rs/num-complex) and [nalgebra](https://docs.rs/nalgebra) //! to create a pyfunction that calculates the eigenvalues of a 2x2 matrix. //! ```ignore //! # // not tested because nalgebra isn't supported on msrv //! # // please file an issue if it breaks! //! use nalgebra::base::{dimension::Const, Matrix}; //! use num_complex::Complex; //! use pyo3::prelude::*; //! //! type T = Complex; //! //! #[pyfunction] //! fn get_eigenvalues(m11: T, m12: T, m21: T, m22: T) -> Vec { //! let mat = Matrix::, Const<2>, _>::new(m11, m12, m21, m22); //! //! match mat.eigenvalues() { //! Some(e) => e.data.as_slice().to_vec(), //! None => vec![], //! } //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(get_eigenvalues, m)?)?; //! Ok(()) //! } //! # // test //! # use assert_approx_eq::assert_approx_eq; //! # use nalgebra::ComplexField; //! # use pyo3::types::PyComplex; //! # //! # fn main() -> PyResult<()> { //! # Python::with_gil(|py| -> PyResult<()> { //! # let module = PyModule::new_bound(py, "my_module")?; //! # //! # module.add_function(&wrap_pyfunction!(get_eigenvalues, module)?)?; //! # //! # let m11 = PyComplex::from_doubles_bound(py, 0_f64, -1_f64); //! # let m12 = PyComplex::from_doubles_bound(py, 1_f64, 0_f64); //! # let m21 = PyComplex::from_doubles_bound(py, 2_f64, -1_f64); //! # let m22 = PyComplex::from_doubles_bound(py, -1_f64, 0_f64); //! # //! # let result = module //! # .getattr("get_eigenvalues")? //! # .call1((m11, m12, m21, m22))?; //! # println!("eigenvalues: {:?}", result); //! # //! # let result = result.extract::>()?; //! # let e0 = result[0]; //! # let e1 = result[1]; //! # //! # assert_approx_eq!(e0, Complex::new(1_f64, -1_f64)); //! # assert_approx_eq!(e1, Complex::new(-2_f64, 0_f64)); //! # //! # Ok(()) //! # }) //! # } //! ``` //! //! Python code: //! ```python //! from my_module import get_eigenvalues //! //! m11 = complex(0,-1) //! m12 = complex(1,0) //! m21 = complex(2,-1) //! m22 = complex(-1,0) //! //! result = get_eigenvalues(m11,m12,m21,m22) //! assert result == [complex(1,-1), complex(-2,0)] //! ``` use crate::{ ffi, ffi_ptr_ext::FfiPtrExt, types::{any::PyAnyMethods, PyComplex}, Bound, FromPyObject, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use num_complex::Complex; use std::os::raw::c_double; impl PyComplex { /// Deprecated form of [`PyComplex::from_complex_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyComplex::from_complex` will be replaced by `PyComplex::from_complex_bound` in a future PyO3 version" )] pub fn from_complex>(py: Python<'_>, complex: Complex) -> &PyComplex { Self::from_complex_bound(py, complex).into_gil_ref() } /// Creates a new Python `PyComplex` object from `num_complex`'s [`Complex`]. pub fn from_complex_bound>( py: Python<'_>, complex: Complex, ) -> Bound<'_, PyComplex> { unsafe { ffi::PyComplex_FromDoubles(complex.re.into(), complex.im.into()) .assume_owned(py) .downcast_into_unchecked() } } } macro_rules! complex_conversion { ($float: ty) => { #[cfg_attr(docsrs, doc(cfg(feature = "num-complex")))] impl ToPyObject for Complex<$float> { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { crate::IntoPy::::into_py(self.to_owned(), py) } } #[cfg_attr(docsrs, doc(cfg(feature = "num-complex")))] impl crate::IntoPy for Complex<$float> { fn into_py(self, py: Python<'_>) -> PyObject { unsafe { let raw_obj = ffi::PyComplex_FromDoubles(self.re as c_double, self.im as c_double); PyObject::from_owned_ptr(py, raw_obj) } } } #[cfg_attr(docsrs, doc(cfg(feature = "num-complex")))] impl FromPyObject<'_> for Complex<$float> { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult> { #[cfg(not(any(Py_LIMITED_API, PyPy)))] unsafe { let val = ffi::PyComplex_AsCComplex(obj.as_ptr()); if val.real == -1.0 { if let Some(err) = PyErr::take(obj.py()) { return Err(err); } } Ok(Complex::new(val.real as $float, val.imag as $float)) } #[cfg(any(Py_LIMITED_API, PyPy))] unsafe { let complex; let obj = if obj.is_instance_of::() { obj } else if let Some(method) = obj.lookup_special(crate::intern!(obj.py(), "__complex__"))? { complex = method.call0()?; &complex } else { // `obj` might still implement `__float__` or `__index__`, which will be // handled by `PyComplex_{Real,Imag}AsDouble`, including propagating any // errors if those methods don't exist / raise exceptions. obj }; let ptr = obj.as_ptr(); let real = ffi::PyComplex_RealAsDouble(ptr); if real == -1.0 { if let Some(err) = PyErr::take(obj.py()) { return Err(err); } } let imag = ffi::PyComplex_ImagAsDouble(ptr); Ok(Complex::new(real as $float, imag as $float)) } } } }; } complex_conversion!(f32); complex_conversion!(f64); #[cfg(test)] mod tests { use super::*; use crate::types::{complex::PyComplexMethods, PyModule}; #[test] fn from_complex() { Python::with_gil(|py| { let complex = Complex::new(3.0, 1.2); let py_c = PyComplex::from_complex_bound(py, complex); assert_eq!(py_c.real(), 3.0); assert_eq!(py_c.imag(), 1.2); }); } #[test] fn to_from_complex() { Python::with_gil(|py| { let val = Complex::new(3.0, 1.2); let obj = val.to_object(py); assert_eq!(obj.extract::>(py).unwrap(), val); }); } #[test] fn from_complex_err() { Python::with_gil(|py| { let obj = vec![1].to_object(py); assert!(obj.extract::>(py).is_err()); }); } #[test] fn from_python_magic() { Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class A: def __complex__(self): return 3.0+1.2j class B: def __float__(self): return 3.0 class C: def __index__(self): return 3 "#, "test.py", "test", ) .unwrap(); let from_complex = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( from_complex.extract::>().unwrap(), Complex::new(3.0, 1.2) ); let from_float = module.getattr("B").unwrap().call0().unwrap(); assert_eq!( from_float.extract::>().unwrap(), Complex::new(3.0, 0.0) ); // Before Python 3.8, `__index__` wasn't tried by `float`/`complex`. #[cfg(Py_3_8)] { let from_index = module.getattr("C").unwrap().call0().unwrap(); assert_eq!( from_index.extract::>().unwrap(), Complex::new(3.0, 0.0) ); } }) } #[test] fn from_python_inherited_magic() { Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class First: pass class ComplexMixin: def __complex__(self): return 3.0+1.2j class FloatMixin: def __float__(self): return 3.0 class IndexMixin: def __index__(self): return 3 class A(First, ComplexMixin): pass class B(First, FloatMixin): pass class C(First, IndexMixin): pass "#, "test.py", "test", ) .unwrap(); let from_complex = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( from_complex.extract::>().unwrap(), Complex::new(3.0, 1.2) ); let from_float = module.getattr("B").unwrap().call0().unwrap(); assert_eq!( from_float.extract::>().unwrap(), Complex::new(3.0, 0.0) ); #[cfg(Py_3_8)] { let from_index = module.getattr("C").unwrap().call0().unwrap(); assert_eq!( from_index.extract::>().unwrap(), Complex::new(3.0, 0.0) ); } }) } #[test] fn from_python_noncallable_descriptor_magic() { // Functions and lambdas implement the descriptor protocol in a way that makes // `type(inst).attr(inst)` equivalent to `inst.attr()` for methods, but this isn't the only // way the descriptor protocol might be implemented. Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class A: @property def __complex__(self): return lambda: 3.0+1.2j "#, "test.py", "test", ) .unwrap(); let obj = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( obj.extract::>().unwrap(), Complex::new(3.0, 1.2) ); }) } #[test] fn from_python_nondescriptor_magic() { // Magic methods don't need to implement the descriptor protocol, if they're callable. Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class MyComplex: def __call__(self): return 3.0+1.2j class A: __complex__ = MyComplex() "#, "test.py", "test", ) .unwrap(); let obj = module.getattr("A").unwrap().call0().unwrap(); assert_eq!( obj.extract::>().unwrap(), Complex::new(3.0, 1.2) ); }) } } pyo3/src/conversions/num_bigint.rs0000644000175000017500000003617014661133735020302 0ustar jamespagejamespage#![cfg(feature = "num-bigint")] //! Conversions to and from [num-bigint](https://docs.rs/num-bigint)’s [`BigInt`] and [`BigUint`] types. //! //! This is useful for converting Python integers when they may not fit in Rust's built-in integer types. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! num-bigint = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"num-bigint\"] }")] //! ``` //! //! Note that you must use compatible versions of num-bigint and PyO3. //! The required num-bigint version may vary based on the version of PyO3. //! //! ## Examples //! //! Using [`BigInt`] to correctly increment an arbitrary precision integer. //! This is not possible with Rust's native integers if the Python integer is too large, //! in which case it will fail its conversion and raise `OverflowError`. //! ```rust //! use num_bigint::BigInt; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_one(n: BigInt) -> BigInt { //! n + 1 //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_one, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code: //! ```python //! from my_module import add_one //! //! n = 1 << 1337 //! value = add_one(n) //! //! assert n + 1 == value //! ``` #[cfg(not(Py_LIMITED_API))] use crate::ffi_ptr_ext::FfiPtrExt; #[cfg(Py_LIMITED_API)] use crate::types::{bytes::PyBytesMethods, PyBytes}; use crate::{ ffi, instance::Bound, types::{any::PyAnyMethods, PyLong}, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject, }; use num_bigint::{BigInt, BigUint}; #[cfg(not(Py_LIMITED_API))] use num_bigint::Sign; // for identical functionality between BigInt and BigUint macro_rules! bigint_conversion { ($rust_ty: ty, $is_signed: literal, $to_bytes: path) => { #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl ToPyObject for $rust_ty { #[cfg(not(Py_LIMITED_API))] fn to_object(&self, py: Python<'_>) -> PyObject { let bytes = $to_bytes(self); #[cfg(not(Py_3_13))] { unsafe { ffi::_PyLong_FromByteArray( bytes.as_ptr().cast(), bytes.len(), 1, $is_signed.into(), ) .assume_owned(py) .unbind() } } #[cfg(Py_3_13)] { if $is_signed { unsafe { ffi::PyLong_FromNativeBytes( bytes.as_ptr().cast(), bytes.len(), ffi::Py_ASNATIVEBYTES_LITTLE_ENDIAN, ) .assume_owned(py) } } else { unsafe { ffi::PyLong_FromUnsignedNativeBytes( bytes.as_ptr().cast(), bytes.len(), ffi::Py_ASNATIVEBYTES_LITTLE_ENDIAN, ) .assume_owned(py) } } .unbind() } } #[cfg(Py_LIMITED_API)] fn to_object(&self, py: Python<'_>) -> PyObject { let bytes = $to_bytes(self); let bytes_obj = PyBytes::new_bound(py, &bytes); let kwargs = if $is_signed { let kwargs = crate::types::PyDict::new_bound(py); kwargs.set_item(crate::intern!(py, "signed"), true).unwrap(); Some(kwargs) } else { None }; py.get_type_bound::() .call_method("from_bytes", (bytes_obj, "little"), kwargs.as_ref()) .expect("int.from_bytes() failed during to_object()") // FIXME: #1813 or similar .into() } } #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl IntoPy for $rust_ty { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } }; } bigint_conversion!(BigUint, false, BigUint::to_bytes_le); bigint_conversion!(BigInt, true, BigInt::to_signed_bytes_le); #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl<'py> FromPyObject<'py> for BigInt { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let py = ob.py(); // fast path - checking for subclass of `int` just checks a bit in the type object let num_owned: Py; let num = if let Ok(long) = ob.downcast::() { long } else { num_owned = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyNumber_Index(ob.as_ptr()))? }; num_owned.bind(py) }; #[cfg(not(Py_LIMITED_API))] { let mut buffer = int_to_u32_vec::(num)?; let sign = if buffer.last().copied().map_or(false, |last| last >> 31 != 0) { // BigInt::new takes an unsigned array, so need to convert from two's complement // flip all bits, 'subtract' 1 (by adding one to the unsigned array) let mut elements = buffer.iter_mut(); for element in elements.by_ref() { *element = (!*element).wrapping_add(1); if *element != 0 { // if the element didn't wrap over, no need to keep adding further ... break; } } // ... so just two's complement the rest for element in elements { *element = !*element; } Sign::Minus } else { Sign::Plus }; Ok(BigInt::new(sign, buffer)) } #[cfg(Py_LIMITED_API)] { let n_bits = int_n_bits(num)?; if n_bits == 0 { return Ok(BigInt::from(0isize)); } let bytes = int_to_py_bytes(num, (n_bits + 8) / 8, true)?; Ok(BigInt::from_signed_bytes_le(bytes.as_bytes())) } } } #[cfg_attr(docsrs, doc(cfg(feature = "num-bigint")))] impl<'py> FromPyObject<'py> for BigUint { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { let py = ob.py(); // fast path - checking for subclass of `int` just checks a bit in the type object let num_owned: Py; let num = if let Ok(long) = ob.downcast::() { long } else { num_owned = unsafe { Py::from_owned_ptr_or_err(py, ffi::PyNumber_Index(ob.as_ptr()))? }; num_owned.bind(py) }; #[cfg(not(Py_LIMITED_API))] { let buffer = int_to_u32_vec::(num)?; Ok(BigUint::new(buffer)) } #[cfg(Py_LIMITED_API)] { let n_bits = int_n_bits(num)?; if n_bits == 0 { return Ok(BigUint::from(0usize)); } let bytes = int_to_py_bytes(num, (n_bits + 7) / 8, false)?; Ok(BigUint::from_bytes_le(bytes.as_bytes())) } } } #[cfg(not(any(Py_LIMITED_API, Py_3_13)))] #[inline] fn int_to_u32_vec(long: &Bound<'_, PyLong>) -> PyResult> { let mut buffer = Vec::new(); let n_bits = int_n_bits(long)?; if n_bits == 0 { return Ok(buffer); } let n_digits = if SIGNED { (n_bits + 32) / 32 } else { (n_bits + 31) / 32 }; buffer.reserve_exact(n_digits); unsafe { crate::err::error_on_minusone( long.py(), ffi::_PyLong_AsByteArray( long.as_ptr().cast(), buffer.as_mut_ptr() as *mut u8, n_digits * 4, 1, SIGNED.into(), ), )?; buffer.set_len(n_digits) }; buffer .iter_mut() .for_each(|chunk| *chunk = u32::from_le(*chunk)); Ok(buffer) } #[cfg(all(not(Py_LIMITED_API), Py_3_13))] #[inline] fn int_to_u32_vec(long: &Bound<'_, PyLong>) -> PyResult> { let mut buffer = Vec::new(); let mut flags = ffi::Py_ASNATIVEBYTES_LITTLE_ENDIAN; if !SIGNED { flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE; } let n_bytes = unsafe { ffi::PyLong_AsNativeBytes(long.as_ptr().cast(), std::ptr::null_mut(), 0, flags) }; let n_bytes_unsigned: usize = n_bytes .try_into() .map_err(|_| crate::PyErr::fetch(long.py()))?; if n_bytes == 0 { return Ok(buffer); } // TODO: use div_ceil when MSRV >= 1.73 let n_digits = { let adjust = if n_bytes % 4 == 0 { 0 } else { 1 }; (n_bytes_unsigned / 4) + adjust }; buffer.reserve_exact(n_digits); unsafe { ffi::PyLong_AsNativeBytes( long.as_ptr().cast(), buffer.as_mut_ptr().cast(), (n_digits * 4).try_into().unwrap(), flags, ); buffer.set_len(n_digits); }; buffer .iter_mut() .for_each(|chunk| *chunk = u32::from_le(*chunk)); Ok(buffer) } #[cfg(Py_LIMITED_API)] fn int_to_py_bytes<'py>( long: &Bound<'py, PyLong>, n_bytes: usize, is_signed: bool, ) -> PyResult> { use crate::intern; let py = long.py(); let kwargs = if is_signed { let kwargs = crate::types::PyDict::new_bound(py); kwargs.set_item(intern!(py, "signed"), true)?; Some(kwargs) } else { None }; let bytes = long.call_method( intern!(py, "to_bytes"), (n_bytes, intern!(py, "little")), kwargs.as_ref(), )?; Ok(bytes.downcast_into()?) } #[inline] #[cfg(any(not(Py_3_13), Py_LIMITED_API))] fn int_n_bits(long: &Bound<'_, PyLong>) -> PyResult { let py = long.py(); #[cfg(not(Py_LIMITED_API))] { // fast path let n_bits = unsafe { ffi::_PyLong_NumBits(long.as_ptr()) }; if n_bits == (-1isize as usize) { return Err(crate::PyErr::fetch(py)); } Ok(n_bits) } #[cfg(Py_LIMITED_API)] { // slow path long.call_method0(crate::intern!(py, "bit_length")) .and_then(|any| any.extract()) } } #[cfg(test)] mod tests { use super::*; use crate::types::{PyDict, PyModule}; use indoc::indoc; fn rust_fib() -> impl Iterator where T: From, for<'a> &'a T: std::ops::Add, { let mut f0: T = T::from(1); let mut f1: T = T::from(1); std::iter::from_fn(move || { let f2 = &f0 + &f1; Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2))) }) } fn python_fib(py: Python<'_>) -> impl Iterator + '_ { let mut f0 = 1.to_object(py); let mut f1 = 1.to_object(py); std::iter::from_fn(move || { let f2 = f0.call_method1(py, "__add__", (f1.bind(py),)).unwrap(); Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2))) }) } #[test] fn convert_biguint() { Python::with_gil(|py| { // check the first 2000 numbers in the fibonacci sequence for (py_result, rs_result) in python_fib(py).zip(rust_fib::()).take(2000) { // Python -> Rust assert_eq!(py_result.extract::(py).unwrap(), rs_result); // Rust -> Python assert!(py_result.bind(py).eq(rs_result).unwrap()); } }); } #[test] fn convert_bigint() { Python::with_gil(|py| { // check the first 2000 numbers in the fibonacci sequence for (py_result, rs_result) in python_fib(py).zip(rust_fib::()).take(2000) { // Python -> Rust assert_eq!(py_result.extract::(py).unwrap(), rs_result); // Rust -> Python assert!(py_result.bind(py).eq(&rs_result).unwrap()); // negate let rs_result = rs_result * -1; let py_result = py_result.call_method0(py, "__neg__").unwrap(); // Python -> Rust assert_eq!(py_result.extract::(py).unwrap(), rs_result); // Rust -> Python assert!(py_result.bind(py).eq(rs_result).unwrap()); } }); } fn python_index_class(py: Python<'_>) -> Bound<'_, PyModule> { let index_code = indoc!( r#" class C: def __init__(self, x): self.x = x def __index__(self): return self.x "# ); PyModule::from_code_bound(py, index_code, "index.py", "index").unwrap() } #[test] fn convert_index_class() { Python::with_gil(|py| { let index = python_index_class(py); let locals = PyDict::new_bound(py); locals.set_item("index", index).unwrap(); let ob = py.eval_bound("index.C(10)", None, Some(&locals)).unwrap(); let _: BigInt = ob.extract().unwrap(); }); } #[test] fn handle_zero() { Python::with_gil(|py| { let zero: BigInt = 0.to_object(py).extract(py).unwrap(); assert_eq!(zero, BigInt::from(0)); }) } /// `OverflowError` on converting Python int to BigInt, see issue #629 #[test] fn check_overflow() { Python::with_gil(|py| { macro_rules! test { ($T:ty, $value:expr, $py:expr) => { let value = $value; println!("{}: {}", stringify!($T), value); let python_value = value.clone().into_py(py); let roundtrip_value = python_value.extract::<$T>(py).unwrap(); assert_eq!(value, roundtrip_value); }; } for i in 0..=256usize { // test a lot of values to help catch other bugs too test!(BigInt, BigInt::from(i), py); test!(BigUint, BigUint::from(i), py); test!(BigInt, -BigInt::from(i), py); test!(BigInt, BigInt::from(1) << i, py); test!(BigUint, BigUint::from(1u32) << i, py); test!(BigInt, -BigInt::from(1) << i, py); test!(BigInt, (BigInt::from(1) << i) + 1u32, py); test!(BigUint, (BigUint::from(1u32) << i) + 1u32, py); test!(BigInt, (-BigInt::from(1) << i) + 1u32, py); test!(BigInt, (BigInt::from(1) << i) - 1u32, py); test!(BigUint, (BigUint::from(1u32) << i) - 1u32, py); test!(BigInt, (-BigInt::from(1) << i) - 1u32, py); } }); } } pyo3/src/conversions/anyhow.rs0000644000175000017500000001514514661133735017453 0ustar jamespagejamespage#![cfg(feature = "anyhow")] //! A conversion from //! [anyhow](https://docs.rs/anyhow/ "A trait object based error system for easy idiomatic error handling in Rust applications.")’s //! [`Error`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html "Anyhows `Error` type, a wrapper around a dynamic error type") //! type to [`PyErr`]. //! //! Use of an error handling library like [anyhow] is common in application code and when you just //! want error handling to be easy. If you are writing a library or you need more control over your //! errors you might want to design your own error type instead. //! //! When the inner error is a [`PyErr`] without source, it will be extracted out. //! Otherwise a Python [`RuntimeError`] will be created. //! You might find that you need to map the error from your Rust code into another Python exception. //! See [`PyErr::new`] for more information about that. //! //! For information about error handling in general, see the [Error handling] chapter of the Rust //! book. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! anyhow = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"anyhow\"] }")] //! ``` //! //! Note that you must use compatible versions of anyhow and PyO3. //! The required anyhow version may vary based on the version of PyO3. //! //! # Example: Propagating a `PyErr` into [`anyhow::Error`] //! //! ```rust //! use pyo3::prelude::*; //! use std::path::PathBuf; //! //! // A wrapper around a Rust function. //! // The pyfunction macro performs the conversion to a PyErr //! #[pyfunction] //! fn py_open(filename: PathBuf) -> anyhow::Result> { //! let data = std::fs::read(filename)?; //! Ok(data) //! } //! //! fn main() { //! let error = Python::with_gil(|py| -> PyResult> { //! let fun = wrap_pyfunction_bound!(py_open, py)?; //! let text = fun.call1(("foo.txt",))?.extract::>()?; //! Ok(text) //! }).unwrap_err(); //! //! println!("{}", error); //! } //! ``` //! //! # Example: Using `anyhow` in general //! //! Note that you don't need this feature to convert a [`PyErr`] into an [`anyhow::Error`], because //! it can already convert anything that implements [`Error`](std::error::Error): //! //! ```rust //! use pyo3::prelude::*; //! use pyo3::types::PyBytes; //! //! // An example function that must handle multiple error types. //! // //! // To do this you usually need to design your own error type or use //! // `Box`. `anyhow` is a convenient alternative for this. //! pub fn decompress(bytes: &[u8]) -> anyhow::Result { //! // An arbitrary example of a Python api you //! // could call inside an application... //! // This might return a `PyErr`. //! let res = Python::with_gil(|py| { //! let zlib = PyModule::import_bound(py, "zlib")?; //! let decompress = zlib.getattr("decompress")?; //! let bytes = PyBytes::new_bound(py, bytes); //! let value = decompress.call1((bytes,))?; //! value.extract::>() //! })?; //! //! // This might be a `FromUtf8Error`. //! let text = String::from_utf8(res)?; //! //! Ok(text) //! } //! //! fn main() -> anyhow::Result<()> { //! let bytes: &[u8] = b"x\x9c\x8b\xcc/U(\xce\xc8/\xcdIQ((\xcaOJL\xca\xa9T\ //! (-NU(\xc9HU\xc8\xc9LJ\xcbI,IUH.\x02\x91\x99y\xc5%\ //! \xa9\x89)z\x00\xf2\x15\x12\xfe"; //! let text = decompress(bytes)?; //! //! println!("The text is \"{}\"", text); //! # assert_eq!(text, "You should probably use the libflate crate instead."); //! Ok(()) //! } //! ``` //! //! [`RuntimeError`]: https://docs.python.org/3/library/exceptions.html#RuntimeError "Built-in Exceptions — Python documentation" //! [Error handling]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html "Recoverable Errors with Result - The Rust Programming Language" use crate::exceptions::PyRuntimeError; use crate::PyErr; impl From for PyErr { fn from(mut error: anyhow::Error) -> Self { // Errors containing a PyErr without chain or context are returned as the underlying error if error.source().is_none() { error = match error.downcast::() { Ok(py_err) => return py_err, Err(error) => error, }; } PyRuntimeError::new_err(format!("{:?}", error)) } } #[cfg(test)] mod test_anyhow { use crate::exceptions::{PyRuntimeError, PyValueError}; use crate::prelude::*; use crate::types::IntoPyDict; use anyhow::{anyhow, bail, Context, Result}; fn f() -> Result<()> { use std::io; bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!")); } fn g() -> Result<()> { f().context("f failed") } fn h() -> Result<()> { g().context("g failed") } #[test] fn test_pyo3_exception_contents() { let err = h().unwrap_err(); let expected_contents = format!("{:?}", err); let pyerr = PyErr::from(err); Python::with_gil(|py| { let locals = [("err", pyerr)].into_py_dict_bound(py); let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value_bound(py).to_string(), expected_contents); }) } fn k() -> Result<()> { Err(anyhow!("Some sort of error")) } #[test] fn test_pyo3_exception_contents2() { let err = k().unwrap_err(); let expected_contents = format!("{:?}", err); let pyerr = PyErr::from(err); Python::with_gil(|py| { let locals = [("err", pyerr)].into_py_dict_bound(py); let pyerr = py.run_bound("raise err", None, Some(&locals)).unwrap_err(); assert_eq!(pyerr.value_bound(py).to_string(), expected_contents); }) } #[test] fn test_pyo3_unwrap_simple_err() { let origin_exc = PyValueError::new_err("Value Error"); let err: anyhow::Error = origin_exc.into(); let converted: PyErr = err.into(); assert!(Python::with_gil( |py| converted.is_instance_of::(py) )) } #[test] fn test_pyo3_unwrap_complex_err() { let origin_exc = PyValueError::new_err("Value Error"); let mut err: anyhow::Error = origin_exc.into(); err = err.context("Context"); let converted: PyErr = err.into(); assert!(Python::with_gil( |py| converted.is_instance_of::(py) )) } } pyo3/src/conversions/mod.rs0000644000175000017500000000053314661133735016720 0ustar jamespagejamespage//! This module contains conversions between various Rust object and their representation in Python. pub mod anyhow; pub mod chrono; pub mod chrono_tz; pub mod either; pub mod eyre; pub mod hashbrown; pub mod indexmap; pub mod num_bigint; pub mod num_complex; pub mod num_rational; pub mod rust_decimal; pub mod serde; pub mod smallvec; mod std; pyo3/src/conversions/std/0000775000175000017500000000000014661133735016366 5ustar jamespagejamespagepyo3/src/conversions/std/option.rs0000644000175000017500000000335714661133735020252 0ustar jamespagejamespageuse crate::{ ffi, types::any::PyAnyMethods, AsPyPointer, Bound, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, }; /// `Option::Some` is converted like `T`. /// `Option::None` is converted to Python `None`. impl ToPyObject for Option where T: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { self.as_ref() .map_or_else(|| py.None(), |val| val.to_object(py)) } } impl IntoPy for Option where T: IntoPy, { fn into_py(self, py: Python<'_>) -> PyObject { self.map_or_else(|| py.None(), |val| val.into_py(py)) } } impl<'py, T> FromPyObject<'py> for Option where T: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { if obj.is_none() { Ok(None) } else { obj.extract().map(Some) } } } /// Convert `None` into a null pointer. unsafe impl AsPyPointer for Option where T: AsPyPointer, { #[inline] fn as_ptr(&self) -> *mut ffi::PyObject { self.as_ref() .map_or_else(std::ptr::null_mut, |t| t.as_ptr()) } } #[cfg(test)] mod tests { use crate::{PyObject, Python}; #[test] fn test_option_as_ptr() { Python::with_gil(|py| { use crate::AsPyPointer; let mut option: Option = None; assert_eq!(option.as_ptr(), std::ptr::null_mut()); let none = py.None(); option = Some(none.clone_ref(py)); let ref_cnt = none.get_refcnt(py); assert_eq!(option.as_ptr(), none.as_ptr()); // Ensure ref count not changed by as_ptr call assert_eq!(none.get_refcnt(py), ref_cnt); }); } } pyo3/src/conversions/std/path.rs0000644000175000017500000001042514661133735017670 0ustar jamespagejamespageuse crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::{ffi, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject}; use std::borrow::Cow; use std::ffi::OsString; use std::path::{Path, PathBuf}; impl ToPyObject for Path { fn to_object(&self, py: Python<'_>) -> PyObject { self.as_os_str().to_object(py) } } // See osstr.rs for why there's no FromPyObject impl for &Path impl FromPyObject<'_> for PathBuf { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { // We use os.fspath to get the underlying path as bytes or str let path = unsafe { ffi::PyOS_FSPath(ob.as_ptr()).assume_owned_or_err(ob.py())? }; Ok(path.extract::()?.into()) } } impl<'a> IntoPy for &'a Path { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.as_os_str().to_object(py) } } impl<'a> ToPyObject for Cow<'a, Path> { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { self.as_os_str().to_object(py) } } impl<'a> IntoPy for Cow<'a, Path> { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl ToPyObject for PathBuf { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { self.as_os_str().to_object(py) } } impl IntoPy for PathBuf { fn into_py(self, py: Python<'_>) -> PyObject { self.into_os_string().to_object(py) } } impl<'a> IntoPy for &'a PathBuf { fn into_py(self, py: Python<'_>) -> PyObject { self.as_os_str().to_object(py) } } #[cfg(test)] mod tests { use crate::types::{PyAnyMethods, PyStringMethods}; use crate::{types::PyString, IntoPy, PyObject, Python, ToPyObject}; use std::borrow::Cow; use std::fmt::Debug; use std::path::{Path, PathBuf}; #[test] #[cfg(not(windows))] fn test_non_utf8_conversion() { Python::with_gil(|py| { use std::ffi::OsStr; #[cfg(not(target_os = "wasi"))] use std::os::unix::ffi::OsStrExt; #[cfg(target_os = "wasi")] use std::os::wasi::ffi::OsStrExt; // this is not valid UTF-8 let payload = &[250, 251, 252, 253, 254, 255, 0, 255]; let path = Path::new(OsStr::from_bytes(payload)); // do a roundtrip into Pythonland and back and compare let py_str: PyObject = path.into_py(py); let path_2: PathBuf = py_str.extract(py).unwrap(); assert_eq!(path, path_2); }); } #[test] fn test_topyobject_roundtrip() { Python::with_gil(|py| { fn test_roundtrip + Debug>(py: Python<'_>, obj: T) { let pyobject = obj.to_object(py); let pystring = pyobject.downcast_bound::(py).unwrap(); assert_eq!(pystring.to_string_lossy(), obj.as_ref().to_string_lossy()); let roundtripped_obj: PathBuf = pystring.extract().unwrap(); assert_eq!(obj.as_ref(), roundtripped_obj.as_path()); } let path = Path::new("Hello\0\n🐍"); test_roundtrip::<&Path>(py, path); test_roundtrip::>(py, Cow::Borrowed(path)); test_roundtrip::>(py, Cow::Owned(path.to_path_buf())); test_roundtrip::(py, path.to_path_buf()); }); } #[test] fn test_intopy_roundtrip() { Python::with_gil(|py| { fn test_roundtrip + AsRef + Debug + Clone>( py: Python<'_>, obj: T, ) { let pyobject = obj.clone().into_py(py); let pystring = pyobject.downcast_bound::(py).unwrap(); assert_eq!(pystring.to_string_lossy(), obj.as_ref().to_string_lossy()); let roundtripped_obj: PathBuf = pystring.extract().unwrap(); assert_eq!(obj.as_ref(), roundtripped_obj.as_path()); } let path = Path::new("Hello\0\n🐍"); test_roundtrip::<&Path>(py, path); test_roundtrip::(py, path.to_path_buf()); test_roundtrip::<&PathBuf>(py, &path.to_path_buf()); }) } } pyo3/src/conversions/std/num.rs0000644000175000017500000007136714661133735017547 0ustar jamespagejamespageuse crate::ffi_ptr_ext::FfiPtrExt; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::types::any::PyAnyMethods; use crate::{ exceptions, ffi, Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use std::num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, }; use std::os::raw::c_long; macro_rules! int_fits_larger_int { ($rust_type:ty, $larger_type:ty) => { impl ToPyObject for $rust_type { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { (*self as $larger_type).into_py(py) } } impl IntoPy for $rust_type { fn into_py(self, py: Python<'_>) -> PyObject { (self as $larger_type).into_py(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { <$larger_type>::type_output() } } impl FromPyObject<'_> for $rust_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: $larger_type = obj.extract()?; <$rust_type>::try_from(val) .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string())) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { <$larger_type>::type_input() } } }; } macro_rules! extract_int { ($obj:ident, $error_val:expr, $pylong_as:expr) => { extract_int!($obj, $error_val, $pylong_as, false) }; ($obj:ident, $error_val:expr, $pylong_as:expr, $force_index_call: literal) => { // In python 3.8+ `PyLong_AsLong` and friends takes care of calling `PyNumber_Index`, // however 3.8 & 3.9 do lossy conversion of floats, hence we only use the // simplest logic for 3.10+ where that was fixed - python/cpython#82180. // `PyLong_AsUnsignedLongLong` does not call `PyNumber_Index`, hence the `force_index_call` argument // See https://github.com/PyO3/pyo3/pull/3742 for detials if cfg!(Py_3_10) && !$force_index_call { err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as($obj.as_ptr()) }) } else if let Ok(long) = $obj.downcast::() { // fast path - checking for subclass of `int` just checks a bit in the type $object err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as(long.as_ptr()) }) } else { unsafe { let num = ffi::PyNumber_Index($obj.as_ptr()).assume_owned_or_err($obj.py())?; err_if_invalid_value($obj.py(), $error_val, $pylong_as(num.as_ptr())) } } }; } macro_rules! int_convert_u64_or_i64 { ($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ll_or_ull:expr, $force_index_call:literal) => { impl ToPyObject for $rust_type { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_owned_ptr(py, $pylong_from_ll_or_ull(*self)) } } } impl IntoPy for $rust_type { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_owned_ptr(py, $pylong_from_ll_or_ull(self)) } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl FromPyObject<'_> for $rust_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<$rust_type> { extract_int!(obj, !0, $pylong_as_ll_or_ull, $force_index_call) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } macro_rules! int_fits_c_long { ($rust_type:ty) => { impl ToPyObject for $rust_type { fn to_object(&self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_owned_ptr(py, ffi::PyLong_FromLong(*self as c_long)) } } } impl IntoPy for $rust_type { fn into_py(self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_owned_ptr(py, ffi::PyLong_FromLong(self as c_long)) } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl<'py> FromPyObject<'py> for $rust_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: c_long = extract_int!(obj, -1, ffi::PyLong_AsLong)?; <$rust_type>::try_from(val) .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string())) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } int_fits_c_long!(i8); int_fits_c_long!(u8); int_fits_c_long!(i16); int_fits_c_long!(u16); int_fits_c_long!(i32); // If c_long is 64-bits, we can use more types with int_fits_c_long!: #[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] int_fits_c_long!(u32); #[cfg(any(target_pointer_width = "32", target_os = "windows"))] int_fits_larger_int!(u32, u64); #[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] int_fits_c_long!(i64); // manual implementation for i64 on systems with 32-bit long #[cfg(any(target_pointer_width = "32", target_os = "windows"))] int_convert_u64_or_i64!(i64, ffi::PyLong_FromLongLong, ffi::PyLong_AsLongLong, false); #[cfg(all(target_pointer_width = "64", not(target_os = "windows")))] int_fits_c_long!(isize); #[cfg(any(target_pointer_width = "32", target_os = "windows"))] int_fits_larger_int!(isize, i64); int_fits_larger_int!(usize, u64); // u64 has a manual implementation as it never fits into signed long int_convert_u64_or_i64!( u64, ffi::PyLong_FromUnsignedLongLong, ffi::PyLong_AsUnsignedLongLong, true ); #[cfg(all(not(Py_LIMITED_API), not(GraalPy)))] mod fast_128bit_int_conversion { use super::*; // for 128bit Integers macro_rules! int_convert_128 { ($rust_type: ty, $is_signed: literal) => { impl ToPyObject for $rust_type { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { (*self).into_py(py) } } impl IntoPy for $rust_type { fn into_py(self, py: Python<'_>) -> PyObject { #[cfg(not(Py_3_13))] { let bytes = self.to_le_bytes(); unsafe { ffi::_PyLong_FromByteArray( bytes.as_ptr().cast(), bytes.len(), 1, $is_signed.into(), ) .assume_owned(py) .unbind() } } #[cfg(Py_3_13)] { let bytes = self.to_ne_bytes(); if $is_signed { unsafe { ffi::PyLong_FromNativeBytes( bytes.as_ptr().cast(), bytes.len(), ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN, ) .assume_owned(py) } } else { unsafe { ffi::PyLong_FromUnsignedNativeBytes( bytes.as_ptr().cast(), bytes.len(), ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN, ) .assume_owned(py) } } .unbind() } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl FromPyObject<'_> for $rust_type { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<$rust_type> { let num = unsafe { ffi::PyNumber_Index(ob.as_ptr()).assume_owned_or_err(ob.py())? }; let mut buffer = [0u8; std::mem::size_of::<$rust_type>()]; #[cfg(not(Py_3_13))] { crate::err::error_on_minusone(ob.py(), unsafe { ffi::_PyLong_AsByteArray( num.as_ptr() as *mut ffi::PyLongObject, buffer.as_mut_ptr(), buffer.len(), 1, $is_signed.into(), ) })?; Ok(<$rust_type>::from_le_bytes(buffer)) } #[cfg(Py_3_13)] { let mut flags = ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN; if !$is_signed { flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE; } let actual_size: usize = unsafe { ffi::PyLong_AsNativeBytes( num.as_ptr(), buffer.as_mut_ptr().cast(), buffer .len() .try_into() .expect("length of buffer fits in Py_ssize_t"), flags, ) } .try_into() .map_err(|_| PyErr::fetch(ob.py()))?; if actual_size as usize > buffer.len() { return Err(crate::exceptions::PyOverflowError::new_err( "Python int larger than 128 bits", )); } Ok(<$rust_type>::from_ne_bytes(buffer)) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } int_convert_128!(i128, true); int_convert_128!(u128, false); } // For ABI3 we implement the conversion manually. #[cfg(any(Py_LIMITED_API, GraalPy))] mod slow_128bit_int_conversion { use super::*; const SHIFT: usize = 64; // for 128bit Integers macro_rules! int_convert_128 { ($rust_type: ty, $half_type: ty) => { impl ToPyObject for $rust_type { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { (*self).into_py(py) } } impl IntoPy for $rust_type { fn into_py(self, py: Python<'_>) -> PyObject { let lower = (self as u64).into_py(py); let upper = ((self >> SHIFT) as $half_type).into_py(py); let shift = SHIFT.into_py(py); unsafe { let shifted = PyObject::from_owned_ptr( py, ffi::PyNumber_Lshift(upper.as_ptr(), shift.as_ptr()), ); PyObject::from_owned_ptr( py, ffi::PyNumber_Or(shifted.as_ptr(), lower.as_ptr()), ) } } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("int") } } impl FromPyObject<'_> for $rust_type { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult<$rust_type> { let py = ob.py(); unsafe { let lower = err_if_invalid_value( py, -1 as _, ffi::PyLong_AsUnsignedLongLongMask(ob.as_ptr()), )? as $rust_type; let shift = SHIFT.into_py(py); let shifted = PyObject::from_owned_ptr_or_err( py, ffi::PyNumber_Rshift(ob.as_ptr(), shift.as_ptr()), )?; let upper: $half_type = shifted.extract(py)?; Ok((<$rust_type>::from(upper) << SHIFT) | lower) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } }; } int_convert_128!(i128, i64); int_convert_128!(u128, u64); } fn err_if_invalid_value( py: Python<'_>, invalid_value: T, actual_value: T, ) -> PyResult { if actual_value == invalid_value { if let Some(err) = PyErr::take(py) { return Err(err); } } Ok(actual_value) } macro_rules! nonzero_int_impl { ($nonzero_type:ty, $primitive_type:ty) => { impl ToPyObject for $nonzero_type { fn to_object(&self, py: Python<'_>) -> PyObject { self.get().to_object(py) } } impl IntoPy for $nonzero_type { fn into_py(self, py: Python<'_>) -> PyObject { self.get().into_py(py) } } impl FromPyObject<'_> for $nonzero_type { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let val: $primitive_type = obj.extract()?; <$nonzero_type>::try_from(val) .map_err(|_| exceptions::PyValueError::new_err("invalid zero value")) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { <$primitive_type>::type_input() } } }; } nonzero_int_impl!(NonZeroI8, i8); nonzero_int_impl!(NonZeroI16, i16); nonzero_int_impl!(NonZeroI32, i32); nonzero_int_impl!(NonZeroI64, i64); nonzero_int_impl!(NonZeroI128, i128); nonzero_int_impl!(NonZeroIsize, isize); nonzero_int_impl!(NonZeroU8, u8); nonzero_int_impl!(NonZeroU16, u16); nonzero_int_impl!(NonZeroU32, u32); nonzero_int_impl!(NonZeroU64, u64); nonzero_int_impl!(NonZeroU128, u128); nonzero_int_impl!(NonZeroUsize, usize); #[cfg(test)] mod test_128bit_integers { use super::*; #[cfg(not(target_arch = "wasm32"))] use crate::types::PyDict; #[cfg(not(target_arch = "wasm32"))] use crate::types::dict::PyDictMethods; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_i128_roundtrip(x: i128) { Python::with_gil(|py| { let x_py = x.into_py(py); let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: i128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) } #[test] fn test_nonzero_i128_roundtrip( x in any::() .prop_filter("Values must not be 0", |x| x != &0) .prop_map(|x| NonZeroI128::new(x).unwrap()) ) { Python::with_gil(|py| { let x_py = x.into_py(py); let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: NonZeroI128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) } } #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_u128_roundtrip(x: u128) { Python::with_gil(|py| { let x_py = x.into_py(py); let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: u128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) } #[test] fn test_nonzero_u128_roundtrip( x in any::() .prop_filter("Values must not be 0", |x| x != &0) .prop_map(|x| NonZeroU128::new(x).unwrap()) ) { Python::with_gil(|py| { let x_py = x.into_py(py); let locals = PyDict::new_bound(py); locals.set_item("x_py", x_py.clone_ref(py)).unwrap(); py.run_bound(&format!("assert x_py == {}", x), None, Some(&locals)).unwrap(); let roundtripped: NonZeroU128 = x_py.extract(py).unwrap(); assert_eq!(x, roundtripped); }) } } #[test] fn test_i128_max() { Python::with_gil(|py| { let v = i128::MAX; let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert_eq!(v as u128, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }) } #[test] fn test_i128_min() { Python::with_gil(|py| { let v = i128::MIN; let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); assert!(obj.extract::(py).is_err()); }) } #[test] fn test_u128_max() { Python::with_gil(|py| { let v = u128::MAX; let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }) } #[test] fn test_i128_overflow() { Python::with_gil(|py| { let obj = py.eval_bound("(1 << 130) * -1", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_u128_overflow() { Python::with_gil(|py| { let obj = py.eval_bound("1 << 130", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_i128_max() { Python::with_gil(|py| { let v = NonZeroI128::new(i128::MAX).unwrap(); let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert_eq!( NonZeroU128::new(v.get() as u128).unwrap(), obj.extract::(py).unwrap() ); assert!(obj.extract::(py).is_err()); }) } #[test] fn test_nonzero_i128_min() { Python::with_gil(|py| { let v = NonZeroI128::new(i128::MIN).unwrap(); let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); assert!(obj.extract::(py).is_err()); }) } #[test] fn test_nonzero_u128_max() { Python::with_gil(|py| { let v = NonZeroU128::new(u128::MAX).unwrap(); let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }) } #[test] fn test_nonzero_i128_overflow() { Python::with_gil(|py| { let obj = py.eval_bound("(1 << 130) * -1", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_u128_overflow() { Python::with_gil(|py| { let obj = py.eval_bound("1 << 130", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_i128_zero_value() { Python::with_gil(|py| { let obj = py.eval_bound("0", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } #[test] fn test_nonzero_u128_zero_value() { Python::with_gil(|py| { let obj = py.eval_bound("0", None, None).unwrap(); let err = obj.extract::().unwrap_err(); assert!(err.is_instance_of::(py)); }) } } #[cfg(test)] mod tests { use crate::Python; use crate::ToPyObject; use std::num::*; #[test] fn test_u32_max() { Python::with_gil(|py| { let v = u32::MAX; let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert_eq!(u64::from(v), obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }); } #[test] fn test_i64_max() { Python::with_gil(|py| { let v = i64::MAX; let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert_eq!(v as u64, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }); } #[test] fn test_i64_min() { Python::with_gil(|py| { let v = i64::MIN; let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); assert!(obj.extract::(py).is_err()); }); } #[test] fn test_u64_max() { Python::with_gil(|py| { let v = u64::MAX; let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }); } macro_rules! test_common ( ($test_mod_name:ident, $t:ty) => ( mod $test_mod_name { use crate::exceptions; use crate::ToPyObject; use crate::Python; #[test] fn from_py_string_type_error() { Python::with_gil(|py| { let obj = ("123").to_object(py); let err = obj.extract::<$t>(py).unwrap_err(); assert!(err.is_instance_of::(py)); }); } #[test] fn from_py_float_type_error() { Python::with_gil(|py| { let obj = (12.3).to_object(py); let err = obj.extract::<$t>(py).unwrap_err(); assert!(err.is_instance_of::(py));}); } #[test] fn to_py_object_and_back() { Python::with_gil(|py| { let val = 123 as $t; let obj = val.to_object(py); assert_eq!(obj.extract::<$t>(py).unwrap(), val as $t);}); } } ) ); test_common!(i8, i8); test_common!(u8, u8); test_common!(i16, i16); test_common!(u16, u16); test_common!(i32, i32); test_common!(u32, u32); test_common!(i64, i64); test_common!(u64, u64); test_common!(isize, isize); test_common!(usize, usize); test_common!(i128, i128); test_common!(u128, u128); #[test] fn test_nonzero_u32_max() { Python::with_gil(|py| { let v = NonZeroU32::new(u32::MAX).unwrap(); let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert_eq!(NonZeroU64::from(v), obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }); } #[test] fn test_nonzero_i64_max() { Python::with_gil(|py| { let v = NonZeroI64::new(i64::MAX).unwrap(); let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert_eq!( NonZeroU64::new(v.get() as u64).unwrap(), obj.extract::(py).unwrap() ); assert!(obj.extract::(py).is_err()); }); } #[test] fn test_nonzero_i64_min() { Python::with_gil(|py| { let v = NonZeroI64::new(i64::MIN).unwrap(); let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); assert!(obj.extract::(py).is_err()); }); } #[test] fn test_nonzero_u64_max() { Python::with_gil(|py| { let v = NonZeroU64::new(u64::MAX).unwrap(); let obj = v.to_object(py); assert_eq!(v, obj.extract::(py).unwrap()); assert!(obj.extract::(py).is_err()); }); } macro_rules! test_nonzero_common ( ($test_mod_name:ident, $t:ty) => ( mod $test_mod_name { use crate::exceptions; use crate::ToPyObject; use crate::Python; use std::num::*; #[test] fn from_py_string_type_error() { Python::with_gil(|py| { let obj = ("123").to_object(py); let err = obj.extract::<$t>(py).unwrap_err(); assert!(err.is_instance_of::(py)); }); } #[test] fn from_py_float_type_error() { Python::with_gil(|py| { let obj = (12.3).to_object(py); let err = obj.extract::<$t>(py).unwrap_err(); assert!(err.is_instance_of::(py));}); } #[test] fn to_py_object_and_back() { Python::with_gil(|py| { let val = <$t>::new(123).unwrap(); let obj = val.to_object(py); assert_eq!(obj.extract::<$t>(py).unwrap(), val);}); } } ) ); test_nonzero_common!(nonzero_i8, NonZeroI8); test_nonzero_common!(nonzero_u8, NonZeroU8); test_nonzero_common!(nonzero_i16, NonZeroI16); test_nonzero_common!(nonzero_u16, NonZeroU16); test_nonzero_common!(nonzero_i32, NonZeroI32); test_nonzero_common!(nonzero_u32, NonZeroU32); test_nonzero_common!(nonzero_i64, NonZeroI64); test_nonzero_common!(nonzero_u64, NonZeroU64); test_nonzero_common!(nonzero_isize, NonZeroIsize); test_nonzero_common!(nonzero_usize, NonZeroUsize); test_nonzero_common!(nonzero_i128, NonZeroI128); test_nonzero_common!(nonzero_u128, NonZeroU128); #[test] fn test_i64_bool() { Python::with_gil(|py| { let obj = true.to_object(py); assert_eq!(1, obj.extract::(py).unwrap()); let obj = false.to_object(py); assert_eq!(0, obj.extract::(py).unwrap()); }) } #[test] fn test_i64_f64() { Python::with_gil(|py| { let obj = 12.34f64.to_object(py); let err = obj.extract::(py).unwrap_err(); assert!(err.is_instance_of::(py)); // with no remainder let obj = 12f64.to_object(py); let err = obj.extract::(py).unwrap_err(); assert!(err.is_instance_of::(py)); }) } } pyo3/src/conversions/std/ipaddr.rs0000755000175000017500000000726014661133735020205 0ustar jamespagejamespageuse std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use crate::exceptions::PyValueError; use crate::instance::Bound; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::string::PyStringMethods; use crate::types::PyType; use crate::{intern, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject}; impl FromPyObject<'_> for IpAddr { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { match obj.getattr(intern!(obj.py(), "packed")) { Ok(packed) => { if let Ok(packed) = packed.extract::<[u8; 4]>() { Ok(IpAddr::V4(Ipv4Addr::from(packed))) } else if let Ok(packed) = packed.extract::<[u8; 16]>() { Ok(IpAddr::V6(Ipv6Addr::from(packed))) } else { Err(PyValueError::new_err("invalid packed length")) } } Err(_) => { // We don't have a .packed attribute, so we try to construct an IP from str(). obj.str()?.to_cow()?.parse().map_err(PyValueError::new_err) } } } } impl ToPyObject for Ipv4Addr { fn to_object(&self, py: Python<'_>) -> PyObject { static IPV4_ADDRESS: GILOnceCell> = GILOnceCell::new(); IPV4_ADDRESS .get_or_try_init_type_ref(py, "ipaddress", "IPv4Address") .expect("failed to load ipaddress.IPv4Address") .call1((u32::from_be_bytes(self.octets()),)) .expect("failed to construct ipaddress.IPv4Address") .unbind() } } impl ToPyObject for Ipv6Addr { fn to_object(&self, py: Python<'_>) -> PyObject { static IPV6_ADDRESS: GILOnceCell> = GILOnceCell::new(); IPV6_ADDRESS .get_or_try_init_type_ref(py, "ipaddress", "IPv6Address") .expect("failed to load ipaddress.IPv6Address") .call1((u128::from_be_bytes(self.octets()),)) .expect("failed to construct ipaddress.IPv6Address") .unbind() } } impl ToPyObject for IpAddr { fn to_object(&self, py: Python<'_>) -> PyObject { match self { IpAddr::V4(ip) => ip.to_object(py), IpAddr::V6(ip) => ip.to_object(py), } } } impl IntoPy for IpAddr { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } #[cfg(test)] mod test_ipaddr { use std::str::FromStr; use crate::types::PyString; use super::*; #[test] fn test_roundtrip() { Python::with_gil(|py| { fn roundtrip(py: Python<'_>, ip: &str) { let ip = IpAddr::from_str(ip).unwrap(); let py_cls = if ip.is_ipv4() { "IPv4Address" } else { "IPv6Address" }; let pyobj = ip.into_py(py); let repr = pyobj.bind(py).repr().unwrap(); let repr = repr.to_string_lossy(); assert_eq!(repr, format!("{}('{}')", py_cls, ip)); let ip2: IpAddr = pyobj.extract(py).unwrap(); assert_eq!(ip, ip2); } roundtrip(py, "127.0.0.1"); roundtrip(py, "::1"); roundtrip(py, "0.0.0.0"); }); } #[test] fn test_from_pystring() { Python::with_gil(|py| { let py_str = PyString::new_bound(py, "0:0:0:0:0:0:0:1"); let ip: IpAddr = py_str.to_object(py).extract(py).unwrap(); assert_eq!(ip, IpAddr::from_str("::1").unwrap()); let py_str = PyString::new_bound(py, "invalid"); assert!(py_str.to_object(py).extract::(py).is_err()); }); } } pyo3/src/conversions/std/set.rs0000644000175000017500000001264514661133735017535 0ustar jamespagejamespageuse std::{cmp, collections, hash}; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ instance::Bound, types::any::PyAnyMethods, types::frozenset::PyFrozenSetMethods, types::set::{new_from_iter, PySetMethods}, types::{PyFrozenSet, PySet}, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; impl ToPyObject for collections::HashSet where T: hash::Hash + Eq + ToPyObject, S: hash::BuildHasher + Default, { fn to_object(&self, py: Python<'_>) -> PyObject { new_from_iter(py, self) .expect("Failed to create Python set from HashSet") .into() } } impl ToPyObject for collections::BTreeSet where T: hash::Hash + Eq + ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { new_from_iter(py, self) .expect("Failed to create Python set from BTreeSet") .into() } } impl IntoPy for collections::HashSet where K: IntoPy + Eq + hash::Hash, S: hash::BuildHasher + Default, { fn into_py(self, py: Python<'_>) -> PyObject { new_from_iter(py, self.into_iter().map(|item| item.into_py(py))) .expect("Failed to create Python set from HashSet") .into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::set_of(K::type_output()) } } impl<'py, K, S> FromPyObject<'py> for collections::HashSet where K: FromPyObject<'py> + cmp::Eq + hash::Hash, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { match ob.downcast::() { Ok(set) => set.iter().map(|any| any.extract()).collect(), Err(err) => { if let Ok(frozen_set) = ob.downcast::() { frozen_set.iter().map(|any| any.extract()).collect() } else { Err(PyErr::from(err)) } } } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::set_of(K::type_input()) } } impl IntoPy for collections::BTreeSet where K: IntoPy + cmp::Ord, { fn into_py(self, py: Python<'_>) -> PyObject { new_from_iter(py, self.into_iter().map(|item| item.into_py(py))) .expect("Failed to create Python set from BTreeSet") .into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::set_of(K::type_output()) } } impl<'py, K> FromPyObject<'py> for collections::BTreeSet where K: FromPyObject<'py> + cmp::Ord, { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { match ob.downcast::() { Ok(set) => set.iter().map(|any| any.extract()).collect(), Err(err) => { if let Ok(frozen_set) = ob.downcast::() { frozen_set.iter().map(|any| any.extract()).collect() } else { Err(PyErr::from(err)) } } } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::set_of(K::type_input()) } } #[cfg(test)] mod tests { use crate::types::{any::PyAnyMethods, PyFrozenSet, PySet}; use crate::{IntoPy, PyObject, Python, ToPyObject}; use std::collections::{BTreeSet, HashSet}; #[test] fn test_extract_hashset() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); let hash_set: HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); let set = PyFrozenSet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); let hash_set: HashSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); }); } #[test] fn test_extract_btreeset() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); let hash_set: BTreeSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); let set = PyFrozenSet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); let hash_set: BTreeSet = set.extract().unwrap(); assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect()); }); } #[test] fn test_set_into_py() { Python::with_gil(|py| { let bt: BTreeSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let hs: HashSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let bto: PyObject = bt.clone().into_py(py); let hso: PyObject = hs.clone().into_py(py); assert_eq!(bt, bto.extract(py).unwrap()); assert_eq!(hs, hso.extract(py).unwrap()); }); } #[test] fn test_set_to_object() { Python::with_gil(|py| { let bt: BTreeSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let hs: HashSet = [1, 2, 3, 4, 5].iter().cloned().collect(); let bto: PyObject = bt.to_object(py); let hso: PyObject = hs.to_object(py); assert_eq!(bt, bto.extract(py).unwrap()); assert_eq!(hs, hso.extract(py).unwrap()); }); } } pyo3/src/conversions/std/osstr.rs0000644000175000017500000001663514661133735020117 0ustar jamespagejamespageuse crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::PyString; use crate::{ffi, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject}; use std::borrow::Cow; use std::ffi::{OsStr, OsString}; impl ToPyObject for OsStr { fn to_object(&self, py: Python<'_>) -> PyObject { // If the string is UTF-8, take the quick and easy shortcut if let Some(valid_utf8_path) = self.to_str() { return valid_utf8_path.to_object(py); } // All targets besides windows support the std::os::unix::ffi::OsStrExt API: // https://doc.rust-lang.org/src/std/sys_common/mod.rs.html#59 #[cfg(not(windows))] { #[cfg(target_os = "wasi")] let bytes = std::os::wasi::ffi::OsStrExt::as_bytes(self); #[cfg(not(target_os = "wasi"))] let bytes = std::os::unix::ffi::OsStrExt::as_bytes(self); let ptr = bytes.as_ptr().cast(); let len = bytes.len() as ffi::Py_ssize_t; unsafe { // DecodeFSDefault automatically chooses an appropriate decoding mechanism to // parse os strings losslessly (i.e. surrogateescape most of the time) let pystring = ffi::PyUnicode_DecodeFSDefaultAndSize(ptr, len); PyObject::from_owned_ptr(py, pystring) } } #[cfg(windows)] { let wstr: Vec = std::os::windows::ffi::OsStrExt::encode_wide(self).collect(); unsafe { // This will not panic because the data from encode_wide is well-formed Windows // string data PyObject::from_owned_ptr( py, ffi::PyUnicode_FromWideChar(wstr.as_ptr(), wstr.len() as ffi::Py_ssize_t), ) } } } } // There's no FromPyObject implementation for &OsStr because albeit possible on Unix, this would // be impossible to implement on Windows. Hence it's omitted entirely impl FromPyObject<'_> for OsString { fn extract_bound(ob: &Bound<'_, PyAny>) -> PyResult { let pystring = ob.downcast::()?; #[cfg(not(windows))] { // Decode from Python's lossless bytes string representation back into raw bytes let fs_encoded_bytes = unsafe { crate::Py::::from_owned_ptr( ob.py(), ffi::PyUnicode_EncodeFSDefault(pystring.as_ptr()), ) }; // Create an OsStr view into the raw bytes from Python #[cfg(target_os = "wasi")] let os_str: &OsStr = std::os::wasi::ffi::OsStrExt::from_bytes(fs_encoded_bytes.as_bytes(ob.py())); #[cfg(not(target_os = "wasi"))] let os_str: &OsStr = std::os::unix::ffi::OsStrExt::from_bytes(fs_encoded_bytes.as_bytes(ob.py())); Ok(os_str.to_os_string()) } #[cfg(windows)] { use crate::types::string::PyStringMethods; // Take the quick and easy shortcut if UTF-8 if let Ok(utf8_string) = pystring.to_cow() { return Ok(utf8_string.into_owned().into()); } // Get an owned allocated wide char buffer from PyString, which we have to deallocate // ourselves let size = unsafe { ffi::PyUnicode_AsWideChar(pystring.as_ptr(), std::ptr::null_mut(), 0) }; crate::err::error_on_minusone(ob.py(), size)?; let mut buffer = vec![0; size as usize]; let bytes_read = unsafe { ffi::PyUnicode_AsWideChar(pystring.as_ptr(), buffer.as_mut_ptr(), size) }; assert_eq!(bytes_read, size); // Copy wide char buffer into OsString let os_string = std::os::windows::ffi::OsStringExt::from_wide(&buffer); Ok(os_string) } } } impl IntoPy for &'_ OsStr { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl ToPyObject for Cow<'_, OsStr> { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { (self as &OsStr).to_object(py) } } impl IntoPy for Cow<'_, OsStr> { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl ToPyObject for OsString { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { (self as &OsStr).to_object(py) } } impl IntoPy for OsString { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } impl<'a> IntoPy for &'a OsString { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } #[cfg(test)] mod tests { use crate::types::{PyAnyMethods, PyStringMethods}; use crate::{types::PyString, IntoPy, PyObject, Python, ToPyObject}; use std::fmt::Debug; use std::{ borrow::Cow, ffi::{OsStr, OsString}, }; #[test] #[cfg(not(windows))] fn test_non_utf8_conversion() { Python::with_gil(|py| { #[cfg(not(target_os = "wasi"))] use std::os::unix::ffi::OsStrExt; #[cfg(target_os = "wasi")] use std::os::wasi::ffi::OsStrExt; // this is not valid UTF-8 let payload = &[250, 251, 252, 253, 254, 255, 0, 255]; let os_str = OsStr::from_bytes(payload); // do a roundtrip into Pythonland and back and compare let py_str: PyObject = os_str.into_py(py); let os_str_2: OsString = py_str.extract(py).unwrap(); assert_eq!(os_str, os_str_2); }); } #[test] fn test_topyobject_roundtrip() { Python::with_gil(|py| { fn test_roundtrip + Debug>(py: Python<'_>, obj: T) { let pyobject = obj.to_object(py); let pystring = pyobject.downcast_bound::(py).unwrap(); assert_eq!(pystring.to_string_lossy(), obj.as_ref().to_string_lossy()); let roundtripped_obj: OsString = pystring.extract().unwrap(); assert_eq!(obj.as_ref(), roundtripped_obj.as_os_str()); } let os_str = OsStr::new("Hello\0\n🐍"); test_roundtrip::<&OsStr>(py, os_str); test_roundtrip::>(py, Cow::Borrowed(os_str)); test_roundtrip::>(py, Cow::Owned(os_str.to_os_string())); test_roundtrip::(py, os_str.to_os_string()); }); } #[test] fn test_intopy_roundtrip() { Python::with_gil(|py| { fn test_roundtrip + AsRef + Debug + Clone>( py: Python<'_>, obj: T, ) { let pyobject = obj.clone().into_py(py); let pystring = pyobject.downcast_bound::(py).unwrap(); assert_eq!(pystring.to_string_lossy(), obj.as_ref().to_string_lossy()); let roundtripped_obj: OsString = pystring.extract().unwrap(); assert!(obj.as_ref() == roundtripped_obj.as_os_str()); } let os_str = OsStr::new("Hello\0\n🐍"); test_roundtrip::<&OsStr>(py, os_str); test_roundtrip::(py, os_str.to_os_string()); test_roundtrip::<&OsString>(py, &os_str.to_os_string()); }) } } pyo3/src/conversions/std/map.rs0000644000175000017500000001274514661133735017520 0ustar jamespagejamespageuse std::{cmp, collections, hash}; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ instance::Bound, types::dict::PyDictMethods, types::{any::PyAnyMethods, IntoPyDict, PyDict}, FromPyObject, IntoPy, PyAny, PyErr, PyObject, Python, ToPyObject, }; impl ToPyObject for collections::HashMap where K: hash::Hash + cmp::Eq + ToPyObject, V: ToPyObject, H: hash::BuildHasher, { fn to_object(&self, py: Python<'_>) -> PyObject { IntoPyDict::into_py_dict_bound(self, py).into() } } impl ToPyObject for collections::BTreeMap where K: cmp::Eq + ToPyObject, V: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { IntoPyDict::into_py_dict_bound(self, py).into() } } impl IntoPy for collections::HashMap where K: hash::Hash + cmp::Eq + IntoPy, V: IntoPy, H: hash::BuildHasher, { fn into_py(self, py: Python<'_>) -> PyObject { let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); IntoPyDict::into_py_dict_bound(iter, py).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::dict_of(K::type_output(), V::type_output()) } } impl IntoPy for collections::BTreeMap where K: cmp::Eq + IntoPy, V: IntoPy, { fn into_py(self, py: Python<'_>) -> PyObject { let iter = self .into_iter() .map(|(k, v)| (k.into_py(py), v.into_py(py))); IntoPyDict::into_py_dict_bound(iter, py).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::dict_of(K::type_output(), V::type_output()) } } impl<'py, K, V, S> FromPyObject<'py> for collections::HashMap where K: FromPyObject<'py> + cmp::Eq + hash::Hash, V: FromPyObject<'py>, S: hash::BuildHasher + Default, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = collections::HashMap::with_capacity_and_hasher(dict.len(), S::default()); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::mapping_of(K::type_input(), V::type_input()) } } impl<'py, K, V> FromPyObject<'py> for collections::BTreeMap where K: FromPyObject<'py> + cmp::Ord, V: FromPyObject<'py>, { fn extract_bound(ob: &Bound<'py, PyAny>) -> Result { let dict = ob.downcast::()?; let mut ret = collections::BTreeMap::new(); for (k, v) in dict { ret.insert(k.extract()?, v.extract()?); } Ok(ret) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::mapping_of(K::type_input(), V::type_input()) } } #[cfg(test)] mod tests { use super::*; use std::collections::{BTreeMap, HashMap}; #[test] fn test_hashmap_to_python() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let m = map.to_object(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!(map, py_map.extract().unwrap()); }); } #[test] fn test_btreemap_to_python() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let m = map.to_object(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); assert_eq!(map, py_map.extract().unwrap()); }); } #[test] fn test_hashmap_into_python() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let m: PyObject = map.into_py(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); }); } #[test] fn test_btreemap_into_py() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let m: PyObject = map.into_py(py); let py_map = m.downcast_bound::(py).unwrap(); assert!(py_map.len() == 1); assert!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap() == 1 ); }); } } pyo3/src/conversions/std/array.rs0000644000175000017500000002014114661133735020046 0ustar jamespagejamespageuse crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::PySequence; use crate::{ err::DowncastError, ffi, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject, }; use crate::{exceptions, PyErr}; impl IntoPy for [T; N] where T: IntoPy, { fn into_py(self, py: Python<'_>) -> PyObject { unsafe { let len = N as ffi::Py_ssize_t; let ptr = ffi::PyList_New(len); // We create the `Py` pointer here for two reasons: // - panics if the ptr is null // - its Drop cleans up the list if user code panics. let list: Py = Py::from_owned_ptr(py, ptr); for (i, obj) in (0..len).zip(self) { let obj = obj.into_py(py).into_ptr(); #[cfg(not(Py_LIMITED_API))] ffi::PyList_SET_ITEM(ptr, i, obj); #[cfg(Py_LIMITED_API)] ffi::PyList_SetItem(ptr, i, obj); } list } } } impl ToPyObject for [T; N] where T: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { self.as_ref().to_object(py) } } impl<'py, T, const N: usize> FromPyObject<'py> for [T; N] where T: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { create_array_from_obj(obj) } } fn create_array_from_obj<'py, T, const N: usize>(obj: &Bound<'py, PyAny>) -> PyResult<[T; N]> where T: FromPyObject<'py>, { // Types that pass `PySequence_Check` usually implement enough of the sequence protocol // to support this function and if not, we will only fail extraction safely. let seq = unsafe { if ffi::PySequence_Check(obj.as_ptr()) != 0 { obj.downcast_unchecked::() } else { return Err(DowncastError::new(obj, "Sequence").into()); } }; let seq_len = seq.len()?; if seq_len != N { return Err(invalid_sequence_length(N, seq_len)); } array_try_from_fn(|idx| seq.get_item(idx).and_then(|any| any.extract())) } // TODO use std::array::try_from_fn, if that stabilises: // (https://github.com/rust-lang/rust/issues/89379) fn array_try_from_fn(mut cb: F) -> Result<[T; N], E> where F: FnMut(usize) -> Result, { // Helper to safely create arrays since the standard library doesn't // provide one yet. Shouldn't be necessary in the future. struct ArrayGuard { dst: *mut T, initialized: usize, } impl Drop for ArrayGuard { fn drop(&mut self) { debug_assert!(self.initialized <= N); let initialized_part = core::ptr::slice_from_raw_parts_mut(self.dst, self.initialized); unsafe { core::ptr::drop_in_place(initialized_part); } } } // [MaybeUninit; N] would be "nicer" but is actually difficult to create - there are nightly // APIs which would make this easier. let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit(); let mut guard: ArrayGuard = ArrayGuard { dst: array.as_mut_ptr() as _, initialized: 0, }; unsafe { let mut value_ptr = array.as_mut_ptr() as *mut T; for i in 0..N { core::ptr::write(value_ptr, cb(i)?); value_ptr = value_ptr.offset(1); guard.initialized += 1; } core::mem::forget(guard); Ok(array.assume_init()) } } fn invalid_sequence_length(expected: usize, actual: usize) -> PyErr { exceptions::PyValueError::new_err(format!( "expected a sequence of length {} (got {})", expected, actual )) } #[cfg(test)] mod tests { use std::{ panic, sync::atomic::{AtomicUsize, Ordering}, }; use crate::types::any::PyAnyMethods; use crate::{types::PyList, IntoPy, PyResult, Python, ToPyObject}; #[test] fn array_try_from_fn() { static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); struct CountDrop; impl Drop for CountDrop { fn drop(&mut self) { DROP_COUNTER.fetch_add(1, Ordering::SeqCst); } } let _ = catch_unwind_silent(move || { let _: Result<[CountDrop; 4], ()> = super::array_try_from_fn(|idx| { #[allow(clippy::manual_assert)] if idx == 2 { panic!("peek a boo"); } Ok(CountDrop) }); }); assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2); } #[test] fn test_extract_bytearray_to_array() { Python::with_gil(|py| { let v: [u8; 33] = py .eval_bound( "bytearray(b'abcabcabcabcabcabcabcabcabcabcabc')", None, None, ) .unwrap() .extract() .unwrap(); assert!(&v == b"abcabcabcabcabcabcabcabcabcabcabc"); }) } #[test] fn test_extract_small_bytearray_to_array() { Python::with_gil(|py| { let v: [u8; 3] = py .eval_bound("bytearray(b'abc')", None, None) .unwrap() .extract() .unwrap(); assert!(&v == b"abc"); }); } #[test] fn test_topyobject_array_conversion() { Python::with_gil(|py| { let array: [f32; 4] = [0.0, -16.0, 16.0, 42.0]; let pyobject = array.to_object(py); let pylist = pyobject.downcast_bound::(py).unwrap(); assert_eq!(pylist.get_item(0).unwrap().extract::().unwrap(), 0.0); assert_eq!(pylist.get_item(1).unwrap().extract::().unwrap(), -16.0); assert_eq!(pylist.get_item(2).unwrap().extract::().unwrap(), 16.0); assert_eq!(pylist.get_item(3).unwrap().extract::().unwrap(), 42.0); }); } #[test] fn test_extract_invalid_sequence_length() { Python::with_gil(|py| { let v: PyResult<[u8; 3]> = py .eval_bound("bytearray(b'abcdefg')", None, None) .unwrap() .extract(); assert_eq!( v.unwrap_err().to_string(), "ValueError: expected a sequence of length 3 (got 7)" ); }) } #[test] fn test_intopy_array_conversion() { Python::with_gil(|py| { let array: [f32; 4] = [0.0, -16.0, 16.0, 42.0]; let pyobject = array.into_py(py); let pylist = pyobject.downcast_bound::(py).unwrap(); assert_eq!(pylist.get_item(0).unwrap().extract::().unwrap(), 0.0); assert_eq!(pylist.get_item(1).unwrap().extract::().unwrap(), -16.0); assert_eq!(pylist.get_item(2).unwrap().extract::().unwrap(), 16.0); assert_eq!(pylist.get_item(3).unwrap().extract::().unwrap(), 42.0); }); } #[test] fn test_extract_non_iterable_to_array() { Python::with_gil(|py| { let v = py.eval_bound("42", None, None).unwrap(); v.extract::().unwrap(); v.extract::<[i32; 1]>().unwrap_err(); }); } #[cfg(feature = "macros")] #[test] fn test_pyclass_intopy_array_conversion() { #[crate::pyclass(crate = "crate")] struct Foo; Python::with_gil(|py| { let array: [Foo; 8] = [Foo, Foo, Foo, Foo, Foo, Foo, Foo, Foo]; let pyobject = array.into_py(py); let list = pyobject.downcast_bound::(py).unwrap(); let _bound = list.get_item(4).unwrap().downcast::().unwrap(); }); } // https://stackoverflow.com/a/59211505 fn catch_unwind_silent(f: F) -> std::thread::Result where F: FnOnce() -> R + panic::UnwindSafe, { let prev_hook = panic::take_hook(); panic::set_hook(Box::new(|_| {})); let result = panic::catch_unwind(f); panic::set_hook(prev_hook); result } } pyo3/src/conversions/std/mod.rs0000644000175000017500000000020714661133735017510 0ustar jamespagejamespagemod array; mod cell; mod ipaddr; mod map; mod num; mod option; mod osstr; mod path; mod set; mod slice; mod string; mod time; mod vec; pyo3/src/conversions/std/cell.rs0000644000175000017500000000116114661133735017650 0ustar jamespagejamespageuse std::cell::Cell; use crate::{ types::any::PyAnyMethods, Bound, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, }; impl ToPyObject for Cell { fn to_object(&self, py: Python<'_>) -> PyObject { self.get().to_object(py) } } impl> IntoPy for Cell { fn into_py(self, py: Python<'_>) -> PyObject { self.get().into_py(py) } } impl<'py, T: FromPyObject<'py>> FromPyObject<'py> for Cell { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { ob.extract().map(Cell::new) } } pyo3/src/conversions/std/slice.rs0000644000175000017500000001026514661133735020035 0ustar jamespagejamespageuse std::borrow::Cow; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ types::{PyByteArray, PyByteArrayMethods, PyBytes}, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject, }; impl<'a> IntoPy for &'a [u8] { fn into_py(self, py: Python<'_>) -> PyObject { PyBytes::new_bound(py, self).unbind().into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("bytes") } } #[cfg(feature = "gil-refs")] impl<'py> crate::FromPyObject<'py> for &'py [u8] { fn extract_bound(obj: &crate::Bound<'py, PyAny>) -> PyResult { Ok(obj.clone().into_gil_ref().downcast::()?.as_bytes()) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } #[cfg(not(feature = "gil-refs"))] impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for &'a [u8] { fn from_py_object_bound(obj: crate::Borrowed<'a, '_, PyAny>) -> PyResult { Ok(obj.downcast::()?.as_bytes()) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } /// Special-purpose trait impl to efficiently handle both `bytes` and `bytearray` /// /// If the source object is a `bytes` object, the `Cow` will be borrowed and /// pointing into the source object, and no copying or heap allocations will happen. /// If it is a `bytearray`, its contents will be copied to an owned `Cow`. #[cfg(feature = "gil-refs")] impl<'py> crate::FromPyObject<'py> for Cow<'py, [u8]> { fn extract_bound(ob: &crate::Bound<'py, PyAny>) -> PyResult { use crate::types::PyAnyMethods; if let Ok(bytes) = ob.downcast::() { return Ok(Cow::Borrowed(bytes.clone().into_gil_ref().as_bytes())); } let byte_array = ob.downcast::()?; Ok(Cow::Owned(byte_array.to_vec())) } } #[cfg(not(feature = "gil-refs"))] impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for Cow<'a, [u8]> { fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult { if let Ok(bytes) = ob.downcast::() { return Ok(Cow::Borrowed(bytes.as_bytes())); } let byte_array = ob.downcast::()?; Ok(Cow::Owned(byte_array.to_vec())) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } impl ToPyObject for Cow<'_, [u8]> { fn to_object(&self, py: Python<'_>) -> Py { PyBytes::new_bound(py, self.as_ref()).into() } } impl IntoPy> for Cow<'_, [u8]> { fn into_py(self, py: Python<'_>) -> Py { self.to_object(py) } } #[cfg(test)] mod tests { use std::borrow::Cow; use crate::{ types::{any::PyAnyMethods, PyBytes}, Python, ToPyObject, }; #[test] fn test_extract_bytes() { Python::with_gil(|py| { let py_bytes = py.eval_bound("b'Hello Python'", None, None).unwrap(); let bytes: &[u8] = py_bytes.extract().unwrap(); assert_eq!(bytes, b"Hello Python"); }); } #[test] fn test_cow_impl() { Python::with_gil(|py| { let bytes = py.eval_bound(r#"b"foobar""#, None, None).unwrap(); let cow = bytes.extract::>().unwrap(); assert_eq!(cow, Cow::<[u8]>::Borrowed(b"foobar")); let byte_array = py .eval_bound(r#"bytearray(b"foobar")"#, None, None) .unwrap(); let cow = byte_array.extract::>().unwrap(); assert_eq!(cow, Cow::<[u8]>::Owned(b"foobar".to_vec())); let something_else_entirely = py.eval_bound("42", None, None).unwrap(); something_else_entirely .extract::>() .unwrap_err(); let cow = Cow::<[u8]>::Borrowed(b"foobar").to_object(py); assert!(cow.bind(py).is_instance_of::()); let cow = Cow::<[u8]>::Owned(b"foobar".to_vec()).to_object(py); assert!(cow.bind(py).is_instance_of::()); }); } } pyo3/src/conversions/std/string.rs0000644000175000017500000002012314661133735020236 0ustar jamespagejamespageuse std::borrow::Cow; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ instance::Bound, types::{any::PyAnyMethods, string::PyStringMethods, PyString}, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject, }; /// Converts a Rust `str` to a Python object. /// See `PyString::new` for details on the conversion. impl ToPyObject for str { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { PyString::new_bound(py, self).into() } } impl<'a> IntoPy for &'a str { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { PyString::new_bound(py, self).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl<'a> IntoPy> for &'a str { #[inline] fn into_py(self, py: Python<'_>) -> Py { PyString::new_bound(py, self).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } /// Converts a Rust `Cow<'_, str>` to a Python object. /// See `PyString::new` for details on the conversion. impl ToPyObject for Cow<'_, str> { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { PyString::new_bound(py, self).into() } } impl IntoPy for Cow<'_, str> { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } /// Converts a Rust `String` to a Python object. /// See `PyString::new` for details on the conversion. impl ToPyObject for String { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { PyString::new_bound(py, self).into() } } impl ToPyObject for char { fn to_object(&self, py: Python<'_>) -> PyObject { self.into_py(py) } } impl IntoPy for char { fn into_py(self, py: Python<'_>) -> PyObject { let mut bytes = [0u8; 4]; PyString::new_bound(py, self.encode_utf8(&mut bytes)).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } impl IntoPy for String { fn into_py(self, py: Python<'_>) -> PyObject { PyString::new_bound(py, &self).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("str") } } impl<'a> IntoPy for &'a String { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { PyString::new_bound(py, self).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { ::type_output() } } /// Allows extracting strings from Python objects. /// Accepts Python `str` objects. #[cfg(feature = "gil-refs")] impl<'py> FromPyObject<'py> for &'py str { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { ob.clone().into_gil_ref().downcast::()?.to_str() } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } #[cfg(all(not(feature = "gil-refs"), any(Py_3_10, not(Py_LIMITED_API))))] impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for &'a str { fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult { ob.downcast::()?.to_str() } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } #[cfg(feature = "gil-refs")] impl<'py> FromPyObject<'py> for Cow<'py, str> { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { ob.extract().map(Cow::Owned) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } #[cfg(not(feature = "gil-refs"))] impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for Cow<'a, str> { fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult { ob.downcast::()?.to_cow() } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } /// Allows extracting strings from Python objects. /// Accepts Python `str` and `unicode` objects. impl FromPyObject<'_> for String { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { obj.downcast::()?.to_cow().map(Cow::into_owned) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } impl FromPyObject<'_> for char { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let s = obj.downcast::()?.to_cow()?; let mut iter = s.chars(); if let (Some(ch), None) = (iter.next(), iter.next()) { Ok(ch) } else { Err(crate::exceptions::PyValueError::new_err( "expected a string of length 1", )) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::Python; use crate::{IntoPy, PyObject, ToPyObject}; use std::borrow::Cow; #[test] fn test_cow_into_py() { Python::with_gil(|py| { let s = "Hello Python"; let py_string: PyObject = Cow::Borrowed(s).into_py(py); assert_eq!(s, py_string.extract::>(py).unwrap()); let py_string: PyObject = Cow::::Owned(s.into()).into_py(py); assert_eq!(s, py_string.extract::>(py).unwrap()); }) } #[test] fn test_cow_to_object() { Python::with_gil(|py| { let s = "Hello Python"; let py_string = Cow::Borrowed(s).to_object(py); assert_eq!(s, py_string.extract::>(py).unwrap()); let py_string = Cow::::Owned(s.into()).to_object(py); assert_eq!(s, py_string.extract::>(py).unwrap()); }) } #[test] fn test_non_bmp() { Python::with_gil(|py| { let s = "\u{1F30F}"; let py_string = s.to_object(py); assert_eq!(s, py_string.extract::(py).unwrap()); }) } #[test] fn test_extract_str() { Python::with_gil(|py| { let s = "Hello Python"; let py_string = s.to_object(py); let s2: Cow<'_, str> = py_string.bind(py).extract().unwrap(); assert_eq!(s, s2); }) } #[test] fn test_extract_char() { Python::with_gil(|py| { let ch = '😃'; let py_string = ch.to_object(py); let ch2: char = py_string.bind(py).extract().unwrap(); assert_eq!(ch, ch2); }) } #[test] fn test_extract_char_err() { Python::with_gil(|py| { let s = "Hello Python"; let py_string = s.to_object(py); let err: crate::PyResult = py_string.bind(py).extract(); assert!(err .unwrap_err() .to_string() .contains("expected a string of length 1")); }) } #[test] fn test_string_into_py() { Python::with_gil(|py| { let s = "Hello Python"; let s2 = s.to_owned(); let s3 = &s2; assert_eq!( s, IntoPy::::into_py(s3, py) .extract::>(py) .unwrap() ); assert_eq!( s, IntoPy::::into_py(s2, py) .extract::>(py) .unwrap() ); assert_eq!( s, IntoPy::::into_py(s, py) .extract::>(py) .unwrap() ); }) } } pyo3/src/conversions/std/vec.rs0000644000175000017500000000170614661133735017513 0ustar jamespagejamespage#[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::types::list::new_from_iter; use crate::{IntoPy, PyObject, Python, ToPyObject}; impl ToPyObject for [T] where T: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { let mut iter = self.iter().map(|e| e.to_object(py)); let list = new_from_iter(py, &mut iter); list.into() } } impl ToPyObject for Vec where T: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { self.as_slice().to_object(py) } } impl IntoPy for Vec where T: IntoPy, { fn into_py(self, py: Python<'_>) -> PyObject { let mut iter = self.into_iter().map(|e| e.into_py(py)); let list = new_from_iter(py, &mut iter); list.into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::list_of(T::type_output()) } } pyo3/src/conversions/std/time.rs0000755000175000017500000003037014661133735017676 0ustar jamespagejamespageuse crate::exceptions::{PyOverflowError, PyValueError}; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; #[cfg(Py_LIMITED_API)] use crate::types::PyType; #[cfg(not(Py_LIMITED_API))] use crate::types::{timezone_utc_bound, PyDateTime, PyDelta, PyDeltaAccess}; #[cfg(Py_LIMITED_API)] use crate::Py; use crate::{ intern, Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use std::time::{Duration, SystemTime, UNIX_EPOCH}; const SECONDS_PER_DAY: u64 = 24 * 60 * 60; impl FromPyObject<'_> for Duration { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { #[cfg(not(Py_LIMITED_API))] let (days, seconds, microseconds) = { let delta = obj.downcast::()?; ( delta.get_days(), delta.get_seconds(), delta.get_microseconds(), ) }; #[cfg(Py_LIMITED_API)] let (days, seconds, microseconds): (i32, i32, i32) = { ( obj.getattr(intern!(obj.py(), "days"))?.extract()?, obj.getattr(intern!(obj.py(), "seconds"))?.extract()?, obj.getattr(intern!(obj.py(), "microseconds"))?.extract()?, ) }; // We cast let days = u64::try_from(days).map_err(|_| { PyValueError::new_err( "It is not possible to convert a negative timedelta to a Rust Duration", ) })?; let seconds = u64::try_from(seconds).unwrap(); // 0 <= seconds < 3600*24 let microseconds = u32::try_from(microseconds).unwrap(); // 0 <= microseconds < 1000000 // We convert let total_seconds = days * SECONDS_PER_DAY + seconds; // We casted from i32, this can't overflow let nanoseconds = microseconds.checked_mul(1_000).unwrap(); // 0 <= microseconds < 1000000 Ok(Duration::new(total_seconds, nanoseconds)) } } impl ToPyObject for Duration { fn to_object(&self, py: Python<'_>) -> PyObject { let days = self.as_secs() / SECONDS_PER_DAY; let seconds = self.as_secs() % SECONDS_PER_DAY; let microseconds = self.subsec_micros(); #[cfg(not(Py_LIMITED_API))] { PyDelta::new_bound( py, days.try_into() .expect("Too large Rust duration for timedelta"), seconds.try_into().unwrap(), microseconds.try_into().unwrap(), false, ) .expect("failed to construct timedelta (overflow?)") .into() } #[cfg(Py_LIMITED_API)] { static TIMEDELTA: GILOnceCell> = GILOnceCell::new(); TIMEDELTA .get_or_try_init_type_ref(py, "datetime", "timedelta") .unwrap() .call1((days, seconds, microseconds)) .unwrap() .into() } } } impl IntoPy for Duration { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } // Conversions between SystemTime and datetime do not rely on the floating point timestamp of the // timestamp/fromtimestamp APIs to avoid possible precision loss but goes through the // timedelta/std::time::Duration types by taking for reference point the UNIX epoch. // // TODO: it might be nice to investigate using timestamps anyway, at least when the datetime is a safe range. impl FromPyObject<'_> for SystemTime { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let duration_since_unix_epoch: Duration = obj .call_method1(intern!(obj.py(), "__sub__"), (unix_epoch_py(obj.py()),))? .extract()?; UNIX_EPOCH .checked_add(duration_since_unix_epoch) .ok_or_else(|| { PyOverflowError::new_err("Overflow error when converting the time to Rust") }) } } impl ToPyObject for SystemTime { fn to_object(&self, py: Python<'_>) -> PyObject { let duration_since_unix_epoch = self.duration_since(UNIX_EPOCH).unwrap().into_py(py); unix_epoch_py(py) .call_method1(py, intern!(py, "__add__"), (duration_since_unix_epoch,)) .unwrap() } } impl IntoPy for SystemTime { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } fn unix_epoch_py(py: Python<'_>) -> &PyObject { static UNIX_EPOCH: GILOnceCell = GILOnceCell::new(); UNIX_EPOCH .get_or_try_init(py, || { #[cfg(not(Py_LIMITED_API))] { Ok::<_, PyErr>( PyDateTime::new_bound( py, 1970, 1, 1, 0, 0, 0, 0, Some(&timezone_utc_bound(py)), )? .into(), ) } #[cfg(Py_LIMITED_API)] { let datetime = py.import_bound("datetime")?; let utc = datetime.getattr("timezone")?.getattr("utc")?; Ok::<_, PyErr>( datetime .getattr("datetime")? .call1((1970, 1, 1, 0, 0, 0, 0, utc)) .unwrap() .into(), ) } }) .unwrap() } #[cfg(test)] mod tests { use super::*; use crate::types::PyDict; use std::panic; #[test] fn test_duration_frompyobject() { Python::with_gil(|py| { assert_eq!( new_timedelta(py, 0, 0, 0).extract::().unwrap(), Duration::new(0, 0) ); assert_eq!( new_timedelta(py, 1, 0, 0).extract::().unwrap(), Duration::new(86400, 0) ); assert_eq!( new_timedelta(py, 0, 1, 0).extract::().unwrap(), Duration::new(1, 0) ); assert_eq!( new_timedelta(py, 0, 0, 1).extract::().unwrap(), Duration::new(0, 1_000) ); assert_eq!( new_timedelta(py, 1, 1, 1).extract::().unwrap(), Duration::new(86401, 1_000) ); assert_eq!( timedelta_class(py) .getattr("max") .unwrap() .extract::() .unwrap(), Duration::new(86399999999999, 999999000) ); }); } #[test] fn test_duration_frompyobject_negative() { Python::with_gil(|py| { assert_eq!( new_timedelta(py, 0, -1, 0) .extract::() .unwrap_err() .to_string(), "ValueError: It is not possible to convert a negative timedelta to a Rust Duration" ); }) } #[test] fn test_duration_topyobject() { Python::with_gil(|py| { let assert_eq = |l: PyObject, r: Bound<'_, PyAny>| { assert!(l.bind(py).eq(r).unwrap()); }; assert_eq( Duration::new(0, 0).to_object(py), new_timedelta(py, 0, 0, 0), ); assert_eq( Duration::new(86400, 0).to_object(py), new_timedelta(py, 1, 0, 0), ); assert_eq( Duration::new(1, 0).to_object(py), new_timedelta(py, 0, 1, 0), ); assert_eq( Duration::new(0, 1_000).to_object(py), new_timedelta(py, 0, 0, 1), ); assert_eq( Duration::new(0, 1).to_object(py), new_timedelta(py, 0, 0, 0), ); assert_eq( Duration::new(86401, 1_000).to_object(py), new_timedelta(py, 1, 1, 1), ); assert_eq( Duration::new(86399999999999, 999999000).to_object(py), timedelta_class(py).getattr("max").unwrap(), ); }); } #[test] fn test_duration_topyobject_overflow() { Python::with_gil(|py| { assert!(panic::catch_unwind(|| Duration::MAX.to_object(py)).is_err()); }) } #[test] fn test_time_frompyobject() { Python::with_gil(|py| { assert_eq!( new_datetime(py, 1970, 1, 1, 0, 0, 0, 0) .extract::() .unwrap(), UNIX_EPOCH ); assert_eq!( new_datetime(py, 2020, 2, 3, 4, 5, 6, 7) .extract::() .unwrap(), UNIX_EPOCH .checked_add(Duration::new(1580702706, 7000)) .unwrap() ); assert_eq!( max_datetime(py).extract::().unwrap(), UNIX_EPOCH .checked_add(Duration::new(253402300799, 999999000)) .unwrap() ); }); } #[test] fn test_time_frompyobject_before_epoch() { Python::with_gil(|py| { assert_eq!( new_datetime(py, 1950, 1, 1, 0, 0, 0, 0) .extract::() .unwrap_err() .to_string(), "ValueError: It is not possible to convert a negative timedelta to a Rust Duration" ); }) } #[test] fn test_time_topyobject() { Python::with_gil(|py| { let assert_eq = |l: PyObject, r: Bound<'_, PyAny>| { assert!(l.bind(py).eq(r).unwrap()); }; assert_eq( UNIX_EPOCH .checked_add(Duration::new(1580702706, 7123)) .unwrap() .into_py(py), new_datetime(py, 2020, 2, 3, 4, 5, 6, 7), ); assert_eq( UNIX_EPOCH .checked_add(Duration::new(253402300799, 999999000)) .unwrap() .into_py(py), max_datetime(py), ); }); } #[allow(clippy::too_many_arguments)] fn new_datetime( py: Python<'_>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, ) -> Bound<'_, PyAny> { datetime_class(py) .call1(( year, month, day, hour, minute, second, microsecond, tz_utc(py), )) .unwrap() } fn max_datetime(py: Python<'_>) -> Bound<'_, PyAny> { let naive_max = datetime_class(py).getattr("max").unwrap(); let kargs = PyDict::new_bound(py); kargs.set_item("tzinfo", tz_utc(py)).unwrap(); naive_max.call_method("replace", (), Some(&kargs)).unwrap() } #[test] fn test_time_topyobject_overflow() { let big_system_time = UNIX_EPOCH .checked_add(Duration::new(300000000000, 0)) .unwrap(); Python::with_gil(|py| { assert!(panic::catch_unwind(|| big_system_time.into_py(py)).is_err()); }) } fn tz_utc(py: Python<'_>) -> Bound<'_, PyAny> { py.import_bound("datetime") .unwrap() .getattr("timezone") .unwrap() .getattr("utc") .unwrap() } fn new_timedelta( py: Python<'_>, days: i32, seconds: i32, microseconds: i32, ) -> Bound<'_, PyAny> { timedelta_class(py) .call1((days, seconds, microseconds)) .unwrap() } fn datetime_class(py: Python<'_>) -> Bound<'_, PyAny> { py.import_bound("datetime") .unwrap() .getattr("datetime") .unwrap() } fn timedelta_class(py: Python<'_>) -> Bound<'_, PyAny> { py.import_bound("datetime") .unwrap() .getattr("timedelta") .unwrap() } } pyo3/src/conversions/either.rs0000644000175000017500000001176214661133735017427 0ustar jamespagejamespage#![cfg(feature = "either")] //! Conversion to/from //! [either](https://docs.rs/either/ "A library for easy idiomatic error handling and reporting in Rust applications")’s //! [`Either`] type to a union of two Python types. //! //! Use of a generic sum type like [either] is common when you want to either accept one of two possible //! types as an argument or return one of two possible types from a function, without having to define //! a helper type manually yourself. //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! ## change * to the version you want to use, ideally the latest. //! either = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"either\"] }")] //! ``` //! //! Note that you must use compatible versions of either and PyO3. //! The required either version may vary based on the version of PyO3. //! //! # Example: Convert a `int | str` to `Either`. //! //! ```rust //! use either::Either; //! use pyo3::{Python, ToPyObject}; //! //! fn main() { //! pyo3::prepare_freethreaded_python(); //! Python::with_gil(|py| { //! // Create a string and an int in Python. //! let py_str = "crab".to_object(py); //! let py_int = 42.to_object(py); //! // Now convert it to an Either. //! let either_str: Either = py_str.extract(py).unwrap(); //! let either_int: Either = py_int.extract(py).unwrap(); //! }); //! } //! ``` //! //! [either](https://docs.rs/either/ "A library for easy idiomatic error handling and reporting in Rust applications")’s #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::{ exceptions::PyTypeError, types::any::PyAnyMethods, Bound, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, }; use either::Either; #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl IntoPy for Either where L: IntoPy, R: IntoPy, { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { match self { Either::Left(l) => l.into_py(py), Either::Right(r) => r.into_py(py), } } } #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl ToPyObject for Either where L: ToPyObject, R: ToPyObject, { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { match self { Either::Left(l) => l.to_object(py), Either::Right(r) => r.to_object(py), } } } #[cfg_attr(docsrs, doc(cfg(feature = "either")))] impl<'py, L, R> FromPyObject<'py> for Either where L: FromPyObject<'py>, R: FromPyObject<'py>, { #[inline] fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { if let Ok(l) = obj.extract::() { Ok(Either::Left(l)) } else if let Ok(r) = obj.extract::() { Ok(Either::Right(r)) } else { // TODO: it might be nice to use the `type_input()` name here once `type_input` // is not experimental, rather than the Rust type names. let err_msg = format!( "failed to convert the value to 'Union[{}, {}]'", std::any::type_name::(), std::any::type_name::() ); Err(PyTypeError::new_err(err_msg)) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::union_of(&[L::type_input(), R::type_input()]) } } #[cfg(test)] mod tests { use std::borrow::Cow; use crate::exceptions::PyTypeError; use crate::{Python, ToPyObject}; use either::Either; #[test] fn test_either_conversion() { type E = Either; type E1 = Either; type E2 = Either; Python::with_gil(|py| { let l = E::Left(42); let obj_l = l.to_object(py); assert_eq!(obj_l.extract::(py).unwrap(), 42); assert_eq!(obj_l.extract::(py).unwrap(), l); let r = E::Right("foo".to_owned()); let obj_r = r.to_object(py); assert_eq!(obj_r.extract::>(py).unwrap(), "foo"); assert_eq!(obj_r.extract::(py).unwrap(), r); let obj_s = "foo".to_object(py); let err = obj_s.extract::(py).unwrap_err(); assert!(err.is_instance_of::(py)); assert_eq!( err.to_string(), "TypeError: failed to convert the value to 'Union[i32, f32]'" ); let obj_i = 42.to_object(py); assert_eq!(obj_i.extract::(py).unwrap(), E1::Left(42)); assert_eq!(obj_i.extract::(py).unwrap(), E2::Left(42.0)); let obj_f = 42.0.to_object(py); assert_eq!(obj_f.extract::(py).unwrap(), E1::Right(42.0)); assert_eq!(obj_f.extract::(py).unwrap(), E2::Left(42.0)); }); } } pyo3/src/conversions/smallvec.rs0000644000175000017500000001004314661133735017744 0ustar jamespagejamespage#![cfg(feature = "smallvec")] //! Conversions to and from [smallvec](https://docs.rs/smallvec/). //! //! # Setup //! //! To use this feature, add this to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] //! # change * to the latest versions //! smallvec = "*" #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"smallvec\"] }")] //! ``` //! //! Note that you must use compatible versions of smallvec and PyO3. //! The required smallvec version may vary based on the version of PyO3. use crate::exceptions::PyTypeError; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::types::any::PyAnyMethods; use crate::types::list::new_from_iter; use crate::types::{PySequence, PyString}; use crate::{ err::DowncastError, ffi, Bound, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, }; use smallvec::{Array, SmallVec}; impl ToPyObject for SmallVec where A: Array, A::Item: ToPyObject, { fn to_object(&self, py: Python<'_>) -> PyObject { self.as_slice().to_object(py) } } impl IntoPy for SmallVec where A: Array, A::Item: IntoPy, { fn into_py(self, py: Python<'_>) -> PyObject { let mut iter = self.into_iter().map(|e| e.into_py(py)); let list = new_from_iter(py, &mut iter); list.into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::list_of(A::Item::type_output()) } } impl<'py, A> FromPyObject<'py> for SmallVec where A: Array, A::Item: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { if obj.is_instance_of::() { return Err(PyTypeError::new_err("Can't extract `str` to `SmallVec`")); } extract_sequence(obj) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::sequence_of(A::Item::type_input()) } } fn extract_sequence<'py, A>(obj: &Bound<'py, PyAny>) -> PyResult> where A: Array, A::Item: FromPyObject<'py>, { // Types that pass `PySequence_Check` usually implement enough of the sequence protocol // to support this function and if not, we will only fail extraction safely. let seq = unsafe { if ffi::PySequence_Check(obj.as_ptr()) != 0 { obj.downcast_unchecked::() } else { return Err(DowncastError::new(obj, "Sequence").into()); } }; let mut sv = SmallVec::with_capacity(seq.len().unwrap_or(0)); for item in seq.iter()? { sv.push(item?.extract::()?); } Ok(sv) } #[cfg(test)] mod tests { use super::*; use crate::types::{PyDict, PyList}; #[test] fn test_smallvec_into_py() { Python::with_gil(|py| { let sv: SmallVec<[u64; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect(); let hso: PyObject = sv.clone().into_py(py); let l = PyList::new_bound(py, [1, 2, 3, 4, 5]); assert!(l.eq(hso).unwrap()); }); } #[test] fn test_smallvec_from_py_object() { Python::with_gil(|py| { let l = PyList::new_bound(py, [1, 2, 3, 4, 5]); let sv: SmallVec<[u64; 8]> = l.extract().unwrap(); assert_eq!(sv.as_slice(), [1, 2, 3, 4, 5]); }); } #[test] fn test_smallvec_from_py_object_fails() { Python::with_gil(|py| { let dict = PyDict::new_bound(py); let sv: PyResult> = dict.extract(); assert_eq!( sv.unwrap_err().to_string(), "TypeError: 'dict' object cannot be converted to 'Sequence'" ); }); } #[test] fn test_smallvec_to_object() { Python::with_gil(|py| { let sv: SmallVec<[u64; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect(); let hso: PyObject = sv.to_object(py); let l = PyList::new_bound(py, [1, 2, 3, 4, 5]); assert!(l.eq(hso).unwrap()); }); } } pyo3/src/conversions/num_rational.rs0000644000175000017500000002065514661133735020640 0ustar jamespagejamespage#![cfg(feature = "num-rational")] //! Conversions to and from [num-rational](https://docs.rs/num-rational) types. //! //! This is useful for converting between Python's [fractions.Fraction](https://docs.python.org/3/library/fractions.html) into and from a native Rust //! type. //! //! //! To use this feature, add to your **`Cargo.toml`**: //! //! ```toml //! [dependencies] #![doc = concat!("pyo3 = { version = \"", env!("CARGO_PKG_VERSION"), "\", features = [\"num-rational\"] }")] //! num-rational = "0.4.1" //! ``` //! //! # Example //! //! Rust code to create a function that adds five to a fraction: //! //! ```rust //! use num_rational::Ratio; //! use pyo3::prelude::*; //! //! #[pyfunction] //! fn add_five_to_fraction(fraction: Ratio) -> Ratio { //! fraction + Ratio::new(5, 1) //! } //! //! #[pymodule] //! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(add_five_to_fraction, m)?)?; //! Ok(()) //! } //! ``` //! //! Python code that validates the functionality: //! ```python //! from my_module import add_five_to_fraction //! from fractions import Fraction //! //! fraction = Fraction(2,1) //! fraction_plus_five = add_five_to_fraction(f) //! assert fraction + 5 == fraction_plus_five //! ``` use crate::ffi; use crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::PyType; use crate::{Bound, FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject}; #[cfg(feature = "num-bigint")] use num_bigint::BigInt; use num_rational::Ratio; static FRACTION_CLS: GILOnceCell> = GILOnceCell::new(); fn get_fraction_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { FRACTION_CLS.get_or_try_init_type_ref(py, "fractions", "Fraction") } macro_rules! rational_conversion { ($int: ty) => { impl<'py> FromPyObject<'py> for Ratio<$int> { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { let py = obj.py(); let py_numerator_obj = obj.getattr(crate::intern!(py, "numerator"))?; let py_denominator_obj = obj.getattr(crate::intern!(py, "denominator"))?; let numerator_owned = unsafe { Bound::from_owned_ptr_or_err(py, ffi::PyNumber_Long(py_numerator_obj.as_ptr()))? }; let denominator_owned = unsafe { Bound::from_owned_ptr_or_err( py, ffi::PyNumber_Long(py_denominator_obj.as_ptr()), )? }; let rs_numerator: $int = numerator_owned.extract()?; let rs_denominator: $int = denominator_owned.extract()?; Ok(Ratio::new(rs_numerator, rs_denominator)) } } impl ToPyObject for Ratio<$int> { fn to_object(&self, py: Python<'_>) -> PyObject { let fraction_cls = get_fraction_cls(py).expect("failed to load fractions.Fraction"); let ret = fraction_cls .call1((self.numer().clone(), self.denom().clone())) .expect("failed to call fractions.Fraction(value)"); ret.to_object(py) } } impl IntoPy for Ratio<$int> { fn into_py(self, py: Python<'_>) -> PyObject { self.to_object(py) } } }; } rational_conversion!(i8); rational_conversion!(i16); rational_conversion!(i32); rational_conversion!(isize); rational_conversion!(i64); #[cfg(feature = "num-bigint")] rational_conversion!(BigInt); #[cfg(test)] mod tests { use super::*; use crate::types::dict::PyDictMethods; use crate::types::PyDict; #[cfg(not(target_arch = "wasm32"))] use proptest::prelude::*; #[test] fn test_negative_fraction() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "import fractions\npy_frac = fractions.Fraction(-0.125)", None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(-1, 8); assert_eq!(roundtripped, rs_frac); }) } #[test] fn test_obj_with_incorrect_atts() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "not_fraction = \"contains_incorrect_atts\"", None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("not_fraction").unwrap().unwrap(); assert!(py_frac.extract::>().is_err()); }) } #[test] fn test_fraction_with_fraction_type() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "import fractions\npy_frac = fractions.Fraction(fractions.Fraction(10))", None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(10, 1); assert_eq!(roundtripped, rs_frac); }) } #[test] fn test_fraction_with_decimal() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "import fractions\n\nfrom decimal import Decimal\npy_frac = fractions.Fraction(Decimal(\"1.1\"))", None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(11, 10); assert_eq!(roundtripped, rs_frac); }) } #[test] fn test_fraction_with_num_den() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); py.run_bound( "import fractions\npy_frac = fractions.Fraction(10,5)", None, Some(&locals), ) .unwrap(); let py_frac = locals.get_item("py_frac").unwrap().unwrap(); let roundtripped: Ratio = py_frac.extract().unwrap(); let rs_frac = Ratio::new(10, 5); assert_eq!(roundtripped, rs_frac); }) } #[cfg(target_arch = "wasm32")] #[test] fn test_int_roundtrip() { Python::with_gil(|py| { let rs_frac = Ratio::new(1, 2); let py_frac: PyObject = rs_frac.into_py(py); let roundtripped: Ratio = py_frac.extract(py).unwrap(); assert_eq!(rs_frac, roundtripped); // float conversion }) } #[cfg(target_arch = "wasm32")] #[test] fn test_big_int_roundtrip() { Python::with_gil(|py| { let rs_frac = Ratio::from_float(5.5).unwrap(); let py_frac: PyObject = rs_frac.clone().into_py(py); let roundtripped: Ratio = py_frac.extract(py).unwrap(); assert_eq!(rs_frac, roundtripped); }) } #[cfg(not(target_arch = "wasm32"))] proptest! { #[test] fn test_int_roundtrip(num in any::(), den in any::()) { Python::with_gil(|py| { let rs_frac = Ratio::new(num, den); let py_frac = rs_frac.into_py(py); let roundtripped: Ratio = py_frac.extract(py).unwrap(); assert_eq!(rs_frac, roundtripped); }) } #[test] #[cfg(feature = "num-bigint")] fn test_big_int_roundtrip(num in any::()) { Python::with_gil(|py| { let rs_frac = Ratio::from_float(num).unwrap(); let py_frac = rs_frac.clone().into_py(py); let roundtripped: Ratio = py_frac.extract(py).unwrap(); assert_eq!(roundtripped, rs_frac); }) } } #[test] fn test_infinity() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); let py_bound = py.run_bound( "import fractions\npy_frac = fractions.Fraction(\"Infinity\")", None, Some(&locals), ); assert!(py_bound.is_err()); }) } } pyo3/src/sealed.rs0000644000175000017500000000220314661133735015022 0ustar jamespagejamespageuse crate::types::{ PyBool, PyByteArray, PyBytes, PyCapsule, PyComplex, PyDict, PyFloat, PyFrozenSet, PyList, PyMapping, PyModule, PySequence, PySet, PySlice, PyString, PyTraceback, PyTuple, PyType, }; use crate::{ffi, Bound, PyAny, PyResult}; pub trait Sealed {} // for FfiPtrExt impl Sealed for *mut ffi::PyObject {} // for PyResultExt impl Sealed for PyResult> {} // for Py(...)Methods impl Sealed for Bound<'_, PyAny> {} impl Sealed for Bound<'_, PyBool> {} impl Sealed for Bound<'_, PyByteArray> {} impl Sealed for Bound<'_, PyBytes> {} impl Sealed for Bound<'_, PyCapsule> {} impl Sealed for Bound<'_, PyComplex> {} impl Sealed for Bound<'_, PyDict> {} impl Sealed for Bound<'_, PyFloat> {} impl Sealed for Bound<'_, PyFrozenSet> {} impl Sealed for Bound<'_, PyList> {} impl Sealed for Bound<'_, PyMapping> {} impl Sealed for Bound<'_, PyModule> {} impl Sealed for Bound<'_, PySequence> {} impl Sealed for Bound<'_, PySet> {} impl Sealed for Bound<'_, PySlice> {} impl Sealed for Bound<'_, PyString> {} impl Sealed for Bound<'_, PyTraceback> {} impl Sealed for Bound<'_, PyTuple> {} impl Sealed for Bound<'_, PyType> {} pyo3/src/lib.rs0000644000175000017500000006121514661133735014343 0ustar jamespagejamespage#![warn(missing_docs)] #![cfg_attr(feature = "nightly", feature(auto_traits, negative_impls))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] // Deny some lints in doctests. // Use `#[allow(...)]` locally to override. #![doc(test(attr( deny( rust_2018_idioms, unused_lifetimes, rust_2021_prelude_collisions, warnings ), allow( unused_variables, unused_assignments, unused_extern_crates, // FIXME https://github.com/rust-lang/rust/issues/121621#issuecomment-1965156376 unknown_lints, non_local_definitions, ) )))] //! Rust bindings to the Python interpreter. //! //! PyO3 can be used to write native Python modules or run Python code and modules from Rust. //! //! See [the guide] for a detailed introduction. //! //! # PyO3's object types //! //! PyO3 has several core types that you should familiarize yourself with: //! //! ## The `Python<'py>` object, and the `'py` lifetime //! //! Holding the [global interpreter lock] (GIL) is modeled with the [`Python<'py>`](Python) token. Many //! Python APIs require that the GIL is held, and PyO3 uses this token as proof that these APIs //! can be called safely. It can be explicitly acquired and is also implicitly acquired by PyO3 //! as it wraps Rust functions and structs into Python functions and objects. //! //! The [`Python<'py>`](Python) token's lifetime `'py` is common to many PyO3 APIs: //! - Types that also have the `'py` lifetime, such as the [`Bound<'py, T>`](Bound) smart pointer, are //! bound to the Python GIL and rely on this to offer their functionality. These types often //! have a [`.py()`](Bound::py) method to get the associated [`Python<'py>`](Python) token. //! - Functions which depend on the `'py` lifetime, such as [`PyList::new_bound`](types::PyList::new_bound), //! require a [`Python<'py>`](Python) token as an input. Sometimes the token is passed implicitly by //! taking a [`Bound<'py, T>`](Bound) or other type which is bound to the `'py` lifetime. //! - Traits which depend on the `'py` lifetime, such as [`FromPyObject<'py>`](FromPyObject), usually have //! inputs or outputs which depend on the lifetime. Adding the lifetime to the trait allows //! these inputs and outputs to express their binding to the GIL in the Rust type system. //! //! ## Python object smart pointers //! //! PyO3 has two core smart pointers to refer to Python objects, [`Py`](Py) and its GIL-bound //! form [`Bound<'py, T>`](Bound) which carries the `'py` lifetime. (There is also //! [`Borrowed<'a, 'py, T>`](instance::Borrowed), but it is used much more rarely). //! //! The type parameter `T` in these smart pointers can be filled by: //! - [`PyAny`], e.g. `Py` or `Bound<'py, PyAny>`, where the Python object type is not //! known. `Py` is so common it has a type alias [`PyObject`]. //! - Concrete Python types like [`PyList`](types::PyList) or [`PyTuple`](types::PyTuple). //! - Rust types which are exposed to Python using the [`#[pyclass]`](macro@pyclass) macro. //! //! See the [guide][types] for an explanation of the different Python object types. //! //! ## PyErr //! //! The vast majority of operations in this library will return [`PyResult<...>`](PyResult). //! This is an alias for the type `Result<..., PyErr>`. //! //! A `PyErr` represents a Python exception. A `PyErr` returned to Python code will be raised as a //! Python exception. Errors from `PyO3` itself are also exposed as Python exceptions. //! //! # Feature flags //! //! PyO3 uses [feature flags] to enable you to opt-in to additional functionality. For a detailed //! description, see the [Features chapter of the guide]. //! //! ## Default feature flags //! //! The following features are turned on by default: //! - `macros`: Enables various macros, including all the attribute macros. //! //! ## Optional feature flags //! //! The following features customize PyO3's behavior: //! //! - `abi3`: Restricts PyO3's API to a subset of the full Python API which is guaranteed by //! [PEP 384] to be forward-compatible with future Python versions. //! - `auto-initialize`: Changes [`Python::with_gil`] to automatically initialize the Python //! interpreter if needed. //! - `extension-module`: This will tell the linker to keep the Python symbols unresolved, so that //! your module can also be used with statically linked Python interpreters. Use this feature when //! building an extension module. //! - `multiple-pymethods`: Enables the use of multiple [`#[pymethods]`](macro@crate::pymethods) //! blocks per [`#[pyclass]`](macro@crate::pyclass). This adds a dependency on the [inventory] //! crate, which is not supported on all platforms. //! //! The following features enable interactions with other crates in the Rust ecosystem: //! - [`anyhow`]: Enables a conversion from [anyhow]’s [`Error`][anyhow_error] type to [`PyErr`]. //! - [`chrono`]: Enables a conversion from [chrono]'s structures to the equivalent Python ones. //! - [`chrono-tz`]: Enables a conversion from [chrono-tz]'s `Tz` enum. Requires Python 3.9+. //! - [`either`]: Enables conversions between Python objects and [either]'s [`Either`] type. //! - [`eyre`]: Enables a conversion from [eyre]’s [`Report`] type to [`PyErr`]. //! - [`hashbrown`]: Enables conversions between Python objects and [hashbrown]'s [`HashMap`] and //! [`HashSet`] types. //! - [`indexmap`][indexmap_feature]: Enables conversions between Python dictionary and [indexmap]'s [`IndexMap`]. //! - [`num-bigint`]: Enables conversions between Python objects and [num-bigint]'s [`BigInt`] and //! [`BigUint`] types. //! - [`num-complex`]: Enables conversions between Python objects and [num-complex]'s [`Complex`] //! type. //! - [`num-rational`]: Enables conversions between Python's fractions.Fraction and [num-rational]'s types //! - [`rust_decimal`]: Enables conversions between Python's decimal.Decimal and [rust_decimal]'s //! [`Decimal`] type. //! - [`serde`]: Allows implementing [serde]'s [`Serialize`] and [`Deserialize`] traits for //! [`Py`]`` for all `T` that implement [`Serialize`] and [`Deserialize`]. //! - [`smallvec`][smallvec]: Enables conversions between Python list and [smallvec]'s [`SmallVec`]. //! //! ## Unstable features //! //! - `nightly`: Uses `#![feature(auto_traits, negative_impls)]` to define [`Ungil`] as an auto trait. // //! ## `rustc` environment flags //! //! PyO3 uses `rustc`'s `--cfg` flags to enable or disable code used for different Python versions. //! If you want to do this for your own crate, you can do so with the [`pyo3-build-config`] crate. //! //! - `Py_3_7`, `Py_3_8`, `Py_3_9`, `Py_3_10`: Marks code that is only enabled when //! compiling for a given minimum Python version. //! - `Py_LIMITED_API`: Marks code enabled when the `abi3` feature flag is enabled. //! - `PyPy` - Marks code enabled when compiling for PyPy. //! //! # Minimum supported Rust and Python versions //! //! PyO3 supports the following software versions: //! - Python 3.7 and up (CPython and PyPy) //! - Rust 1.63 and up //! //! # Example: Building a native Python module //! //! PyO3 can be used to generate a native Python module. The easiest way to try this out for the //! first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based //! Python packages with minimal configuration. The following steps set up some files for an example //! Python module, install `maturin`, and then show how to build and import the Python module. //! //! First, create a new folder (let's call it `string_sum`) containing the following two files: //! //! **`Cargo.toml`** //! //! ```toml //! [package] //! name = "string-sum" //! version = "0.1.0" //! edition = "2021" //! //! [lib] //! name = "string_sum" //! # "cdylib" is necessary to produce a shared library for Python to import from. //! # //! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able //! # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: //! # crate-type = ["cdylib", "rlib"] //! crate-type = ["cdylib"] //! //! [dependencies.pyo3] #![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"), "\"")] //! features = ["extension-module"] //! ``` //! //! **`src/lib.rs`** //! ```rust //! use pyo3::prelude::*; //! //! /// Formats the sum of two numbers as string. //! #[pyfunction] //! fn sum_as_string(a: usize, b: usize) -> PyResult { //! Ok((a + b).to_string()) //! } //! //! /// A Python module implemented in Rust. //! #[pymodule] //! fn string_sum(m: &Bound<'_, PyModule>) -> PyResult<()> { //! m.add_function(wrap_pyfunction!(sum_as_string, m)?)?; //! //! Ok(()) //! } //! ``` //! //! With those two files in place, now `maturin` needs to be installed. This can be done using //! Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin` //! into it: //! ```bash //! $ cd string_sum //! $ python -m venv .env //! $ source .env/bin/activate //! $ pip install maturin //! ``` //! //! Now build and execute the module: //! ```bash //! $ maturin develop //! # lots of progress output as maturin runs the compilation... //! $ python //! >>> import string_sum //! >>> string_sum.sum_as_string(5, 20) //! '25' //! ``` //! //! As well as with `maturin`, it is possible to build using [setuptools-rust] or //! [manually][manual_builds]. Both offer more flexibility than `maturin` but require further //! configuration. //! //! # Example: Using Python from Rust //! //! To embed Python into a Rust binary, you need to ensure that your Python installation contains a //! shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give //! some example code which runs an embedded Python interpreter. //! //! To install the Python shared library on Ubuntu: //! ```bash //! sudo apt install python3-dev //! ``` //! //! Start a new project with `cargo new` and add `pyo3` to the `Cargo.toml` like this: //! ```toml //! [dependencies.pyo3] #![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"), "\"")] //! # this is necessary to automatically initialize the Python interpreter //! features = ["auto-initialize"] //! ``` //! //! Example program displaying the value of `sys.version` and the current user name: //! ```rust //! use pyo3::prelude::*; //! use pyo3::types::IntoPyDict; //! //! fn main() -> PyResult<()> { //! Python::with_gil(|py| { //! let sys = py.import_bound("sys")?; //! let version: String = sys.getattr("version")?.extract()?; //! //! let locals = [("os", py.import_bound("os")?)].into_py_dict_bound(py); //! let code = "os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'"; //! let user: String = py.eval_bound(code, None, Some(&locals))?.extract()?; //! //! println!("Hello {}, I'm Python {}", user, version); //! Ok(()) //! }) //! } //! ``` //! //! The guide has [a section][calling_rust] with lots of examples about this topic. //! //! # Other Examples //! //! The PyO3 [README](https://github.com/PyO3/pyo3#readme) contains quick-start examples for both //! using [Rust from Python] and [Python from Rust]. //! //! The PyO3 repository's [examples subdirectory] //! contains some basic packages to demonstrate usage of PyO3. //! //! There are many projects using PyO3 - see a list of some at //! . //! //! [anyhow]: https://docs.rs/anyhow/ "A trait object based error system for easy idiomatic error handling in Rust applications." //! [anyhow_error]: https://docs.rs/anyhow/latest/anyhow/struct.Error.html "Anyhows `Error` type, a wrapper around a dynamic error type" //! [`anyhow`]: ./anyhow/index.html "Documentation about the `anyhow` feature." //! [inventory]: https://docs.rs/inventory //! [`HashMap`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html //! [`HashSet`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html //! [`SmallVec`]: https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html //! [`IndexMap`]: https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html //! [`BigInt`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html //! [`BigUint`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html //! [`Complex`]: https://docs.rs/num-complex/latest/num_complex/struct.Complex.html //! [`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html //! [`Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html //! [chrono]: https://docs.rs/chrono/ "Date and Time for Rust." //! [chrono-tz]: https://docs.rs/chrono-tz/ "TimeZone implementations for chrono from the IANA database." //! [`chrono`]: ./chrono/index.html "Documentation about the `chrono` feature." //! [`chrono-tz`]: ./chrono-tz/index.html "Documentation about the `chrono-tz` feature." //! [either]: https://docs.rs/either/ "A type that represents one of two alternatives." //! [`either`]: ./either/index.html "Documentation about the `either` feature." //! [`Either`]: https://docs.rs/either/latest/either/enum.Either.html //! [eyre]: https://docs.rs/eyre/ "A library for easy idiomatic error handling and reporting in Rust applications." //! [`Report`]: https://docs.rs/eyre/latest/eyre/struct.Report.html //! [`eyre`]: ./eyre/index.html "Documentation about the `eyre` feature." //! [`hashbrown`]: ./hashbrown/index.html "Documentation about the `hashbrown` feature." //! [indexmap_feature]: ./indexmap/index.html "Documentation about the `indexmap` feature." //! [`maturin`]: https://github.com/PyO3/maturin "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" //! [`num-bigint`]: ./num_bigint/index.html "Documentation about the `num-bigint` feature." //! [`num-complex`]: ./num_complex/index.html "Documentation about the `num-complex` feature." //! [`num-rational`]: ./num_rational/index.html "Documentation about the `num-rational` feature." //! [`pyo3-build-config`]: https://docs.rs/pyo3-build-config //! [rust_decimal]: https://docs.rs/rust_decimal //! [`rust_decimal`]: ./rust_decimal/index.html "Documenation about the `rust_decimal` feature." //! [`Decimal`]: https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html //! [`serde`]: <./serde/index.html> "Documentation about the `serde` feature." #![doc = concat!("[calling_rust]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/python-from-rust.html \"Calling Python from Rust - PyO3 user guide\"")] //! [examples subdirectory]: https://github.com/PyO3/pyo3/tree/main/examples //! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html "Features - The Cargo Book" //! [global interpreter lock]: https://docs.python.org/3/glossary.html#term-global-interpreter-lock //! [hashbrown]: https://docs.rs/hashbrown //! [smallvec]: https://docs.rs/smallvec //! [indexmap]: https://docs.rs/indexmap #![doc = concat!("[manual_builds]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution.html#manual-builds \"Manual builds - Building and Distribution - PyO3 user guide\"")] //! [num-bigint]: https://docs.rs/num-bigint //! [num-complex]: https://docs.rs/num-complex //! [num-rational]: https://docs.rs/num-rational //! [serde]: https://docs.rs/serde //! [setuptools-rust]: https://github.com/PyO3/setuptools-rust "Setuptools plugin for Rust extensions" //! [the guide]: https://pyo3.rs "PyO3 user guide" #![doc = concat!("[types]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/types.html \"GIL lifetimes, mutability and Python object types\"")] //! [PEP 384]: https://www.python.org/dev/peps/pep-0384 "PEP 384 -- Defining a Stable ABI" //! [Python from Rust]: https://github.com/PyO3/pyo3#using-python-from-rust //! [Rust from Python]: https://github.com/PyO3/pyo3#using-rust-from-python #![doc = concat!("[Features chapter of the guide]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/features.html#features-reference \"Features Reference - PyO3 user guide\"")] //! [`Ungil`]: crate::marker::Ungil pub use crate::class::*; pub use crate::conversion::{AsPyPointer, FromPyObject, IntoPy, ToPyObject}; #[cfg(feature = "gil-refs")] #[allow(deprecated)] pub use crate::conversion::{FromPyPointer, PyTryFrom, PyTryInto}; #[cfg(feature = "gil-refs")] pub use crate::err::PyDowncastError; pub use crate::err::{DowncastError, DowncastIntoError, PyErr, PyErrArguments, PyResult, ToPyErr}; #[cfg(feature = "gil-refs")] #[allow(deprecated)] pub use crate::gil::GILPool; #[cfg(not(any(PyPy, GraalPy)))] pub use crate::gil::{prepare_freethreaded_python, with_embedded_python_interpreter}; #[cfg(feature = "gil-refs")] pub use crate::instance::PyNativeType; pub use crate::instance::{Borrowed, Bound, Py, PyObject}; pub use crate::marker::Python; #[cfg(feature = "gil-refs")] #[allow(deprecated)] pub use crate::pycell::PyCell; pub use crate::pycell::{PyRef, PyRefMut}; pub use crate::pyclass::PyClass; pub use crate::pyclass_init::PyClassInitializer; pub use crate::type_object::{PyTypeCheck, PyTypeInfo}; pub use crate::types::PyAny; pub use crate::version::PythonVersionInfo; pub(crate) mod ffi_ptr_ext; pub(crate) mod py_result_ext; pub(crate) mod sealed; /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead /// of `use pyo3::class::basic::CompareOp`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod class { pub use self::gc::{PyTraverseError, PyVisit}; #[doc(hidden)] pub use self::methods::{ PyClassAttributeDef, PyGetterDef, PyMethodDef, PyMethodDefType, PyMethodType, PySetterDef, }; #[doc(hidden)] pub mod methods { // frozen with the contents of the `impl_::pymethods` module in 0.20, // this should probably all be replaced with deprecated type aliases and removed. pub use crate::impl_::pymethods::{ IPowModulo, PyClassAttributeDef, PyGetterDef, PyMethodDef, PyMethodDefType, PyMethodType, PySetterDef, }; } /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead /// of `use pyo3::class::basic::CompareOp`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod basic { pub use crate::pyclass::CompareOp; } /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::IterANextOutput` instead /// of `use pyo3::class::pyasync::IterANextOutput`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod pyasync { #[allow(deprecated)] pub use crate::pyclass::{IterANextOutput, PyIterANextOutput}; } /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::IterNextOutput` instead /// of `use pyo3::class::pyasync::IterNextOutput`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod iter { #[allow(deprecated)] pub use crate::pyclass::{IterNextOutput, PyIterNextOutput}; } /// Old module which contained some implementation details of the `#[pyproto]` module. /// /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::PyTraverseError` instead /// of `use pyo3::class::gc::PyTraverseError`. /// /// For compatibility reasons this has not yet been removed, however will be done so /// once is resolved. pub mod gc { pub use crate::pyclass::{PyTraverseError, PyVisit}; } } #[cfg(feature = "macros")] #[doc(hidden)] pub use { indoc, // Re-exported for py_run unindent, // Re-exported for py_run }; #[cfg(all(feature = "macros", feature = "multiple-pymethods"))] #[doc(hidden)] pub use inventory; // Re-exported for `#[pyclass]` and `#[pymethods]` with `multiple-pymethods`. /// Tests and helpers which reside inside PyO3's main library. Declared first so that macros /// are available in unit tests. #[cfg(test)] #[macro_use] mod tests; #[macro_use] mod internal_tricks; pub mod buffer; #[doc(hidden)] pub mod callback; pub mod conversion; mod conversions; #[cfg(feature = "experimental-async")] pub mod coroutine; #[macro_use] #[doc(hidden)] #[cfg(feature = "gil-refs")] pub mod derive_utils; mod err; pub mod exceptions; pub mod ffi; mod gil; #[doc(hidden)] pub mod impl_; mod instance; pub mod marker; pub mod marshal; #[macro_use] pub mod sync; pub mod panic; pub mod pybacked; pub mod pycell; pub mod pyclass; pub mod pyclass_init; pub mod type_object; pub mod types; mod version; #[allow(unused_imports)] // with no features enabled this module has no public exports pub use crate::conversions::*; #[cfg(feature = "macros")] pub use pyo3_macros::{pyfunction, pymethods, pymodule, FromPyObject}; /// A proc macro used to expose Rust structs and fieldless enums as Python objects. /// #[doc = include_str!("../guide/pyclass-parameters.md")] /// /// For more on creating Python classes, /// see the [class section of the guide][1]. /// #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html")] #[cfg(feature = "macros")] pub use pyo3_macros::pyclass; #[cfg(feature = "macros")] #[macro_use] mod macros; #[cfg(feature = "experimental-inspect")] pub mod inspect; // Putting the declaration of prelude at the end seems to help encourage rustc and rustdoc to prefer using // other paths to the same items. (e.g. `pyo3::types::PyAnyMethods` instead of `pyo3::prelude::PyAnyMethods`). pub mod prelude; /// Ths module only contains re-exports of pyo3 deprecation warnings and exists /// purely to make compiler error messages nicer. /// /// (The compiler uses this module in error messages, probably because it's a public /// re-export at a shorter path than `pyo3::impl_::deprecations`.) #[doc(hidden)] pub mod deprecations { pub use crate::impl_::deprecations::*; } /// Test readme and user guide #[cfg(doctest)] pub mod doc_test { macro_rules! doctests { ($($path:expr => $mod:ident),* $(,)?) => { $( #[doc = include_str!(concat!("../", $path))] mod $mod{} )* }; } doctests! { "README.md" => readme_md, "guide/src/advanced.md" => guide_advanced_md, "guide/src/async-await.md" => guide_async_await_md, "guide/src/building-and-distribution.md" => guide_building_and_distribution_md, "guide/src/building-and-distribution/multiple-python-versions.md" => guide_bnd_multiple_python_versions_md, "guide/src/class.md" => guide_class_md, "guide/src/class/call.md" => guide_class_call, "guide/src/class/object.md" => guide_class_object, "guide/src/class/numeric.md" => guide_class_numeric, "guide/src/class/protocols.md" => guide_class_protocols_md, "guide/src/conversions.md" => guide_conversions_md, "guide/src/conversions/tables.md" => guide_conversions_tables_md, "guide/src/conversions/traits.md" => guide_conversions_traits_md, "guide/src/debugging.md" => guide_debugging_md, // deliberate choice not to test guide/ecosystem because those pages depend on external // crates such as pyo3_asyncio. "guide/src/exception.md" => guide_exception_md, "guide/src/faq.md" => guide_faq_md, "guide/src/features.md" => guide_features_md, "guide/src/function.md" => guide_function_md, "guide/src/function/error-handling.md" => guide_function_error_handling_md, "guide/src/function/signature.md" => guide_function_signature_md, "guide/src/memory.md" => guide_memory_md, "guide/src/migration.md" => guide_migration_md, "guide/src/module.md" => guide_module_md, "guide/src/parallelism.md" => guide_parallelism_md, "guide/src/performance.md" => guide_performance_md, "guide/src/python-from-rust.md" => guide_python_from_rust_md, "guide/src/python-from-rust/calling-existing-code.md" => guide_pfr_calling_existing_code_md, "guide/src/python-from-rust/function-calls.md" => guide_pfr_function_calls_md, "guide/src/python-typing-hints.md" => guide_python_typing_hints_md, "guide/src/rust-from-python.md" => guide_rust_from_python_md, "guide/src/trait-bounds.md" => guide_trait_bounds_md, "guide/src/types.md" => guide_types_md, } } pyo3/src/buffer.rs0000644000175000017500000010503714661133735015047 0ustar jamespagejamespage#![cfg(any(not(Py_LIMITED_API), Py_3_11))] // Copyright (c) 2017 Daniel Grunwald // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. //! `PyBuffer` implementation use crate::Bound; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{err, exceptions::PyBufferError, ffi, FromPyObject, PyAny, PyResult, Python}; use std::marker::PhantomData; use std::os::raw; use std::pin::Pin; use std::{cell, mem, ptr, slice}; use std::{ffi::CStr, fmt::Debug}; /// Allows access to the underlying buffer used by a python object such as `bytes`, `bytearray` or `array.array`. // use Pin because Python expects that the Py_buffer struct has a stable memory address #[repr(transparent)] pub struct PyBuffer(Pin>, PhantomData); // PyBuffer is thread-safe: the shape of the buffer is immutable while a Py_buffer exists. // Accessing the buffer contents is protected using the GIL. unsafe impl Send for PyBuffer {} unsafe impl Sync for PyBuffer {} impl Debug for PyBuffer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("PyBuffer") .field("buf", &self.0.buf) .field("obj", &self.0.obj) .field("len", &self.0.len) .field("itemsize", &self.0.itemsize) .field("readonly", &self.0.readonly) .field("ndim", &self.0.ndim) .field("format", &self.0.format) .field("shape", &self.0.shape) .field("strides", &self.0.strides) .field("suboffsets", &self.0.suboffsets) .field("internal", &self.0.internal) .finish() } } /// Represents the type of a Python buffer element. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ElementType { /// A signed integer type. SignedInteger { /// The width of the signed integer in bytes. bytes: usize, }, /// An unsigned integer type. UnsignedInteger { /// The width of the unsigned integer in bytes. bytes: usize, }, /// A boolean type. Bool, /// A float type. Float { /// The width of the float in bytes. bytes: usize, }, /// An unknown type. This may occur when parsing has failed. Unknown, } impl ElementType { /// Determines the `ElementType` from a Python `struct` module format string. /// /// See for more information /// about struct format strings. pub fn from_format(format: &CStr) -> ElementType { match format.to_bytes() { [size] | [b'@', size] => native_element_type_from_type_char(*size), [b'=' | b'<' | b'>' | b'!', size] => standard_element_type_from_type_char(*size), _ => ElementType::Unknown, } } } fn native_element_type_from_type_char(type_char: u8) -> ElementType { use self::ElementType::*; match type_char { b'c' => UnsignedInteger { bytes: mem::size_of::(), }, b'b' => SignedInteger { bytes: mem::size_of::(), }, b'B' => UnsignedInteger { bytes: mem::size_of::(), }, b'?' => Bool, b'h' => SignedInteger { bytes: mem::size_of::(), }, b'H' => UnsignedInteger { bytes: mem::size_of::(), }, b'i' => SignedInteger { bytes: mem::size_of::(), }, b'I' => UnsignedInteger { bytes: mem::size_of::(), }, b'l' => SignedInteger { bytes: mem::size_of::(), }, b'L' => UnsignedInteger { bytes: mem::size_of::(), }, b'q' => SignedInteger { bytes: mem::size_of::(), }, b'Q' => UnsignedInteger { bytes: mem::size_of::(), }, b'n' => SignedInteger { bytes: mem::size_of::(), }, b'N' => UnsignedInteger { bytes: mem::size_of::(), }, b'e' => Float { bytes: 2 }, b'f' => Float { bytes: 4 }, b'd' => Float { bytes: 8 }, _ => Unknown, } } fn standard_element_type_from_type_char(type_char: u8) -> ElementType { use self::ElementType::*; match type_char { b'c' | b'B' => UnsignedInteger { bytes: 1 }, b'b' => SignedInteger { bytes: 1 }, b'?' => Bool, b'h' => SignedInteger { bytes: 2 }, b'H' => UnsignedInteger { bytes: 2 }, b'i' | b'l' => SignedInteger { bytes: 4 }, b'I' | b'L' => UnsignedInteger { bytes: 4 }, b'q' => SignedInteger { bytes: 8 }, b'Q' => UnsignedInteger { bytes: 8 }, b'e' => Float { bytes: 2 }, b'f' => Float { bytes: 4 }, b'd' => Float { bytes: 8 }, _ => Unknown, } } #[cfg(target_endian = "little")] fn is_matching_endian(c: u8) -> bool { c == b'@' || c == b'=' || c == b'>' } #[cfg(target_endian = "big")] fn is_matching_endian(c: u8) -> bool { c == b'@' || c == b'=' || c == b'>' || c == b'!' } /// Trait implemented for possible element types of `PyBuffer`. /// /// # Safety /// /// This trait must only be implemented for types which represent valid elements of Python buffers. pub unsafe trait Element: Copy { /// Gets whether the element specified in the format string is potentially compatible. /// Alignment and size are checked separately from this function. fn is_compatible_format(format: &CStr) -> bool; } impl<'py, T: Element> FromPyObject<'py> for PyBuffer { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult> { Self::get_bound(obj) } } impl PyBuffer { /// Deprecated form of [`PyBuffer::get_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyBuffer::get` will be replaced by `PyBuffer::get_bound` in a future PyO3 version" )] pub fn get(obj: &PyAny) -> PyResult> { Self::get_bound(&obj.as_borrowed()) } /// Gets the underlying buffer from the specified python object. pub fn get_bound(obj: &Bound<'_, PyAny>) -> PyResult> { // TODO: use nightly API Box::new_uninit() once stable let mut buf = Box::new(mem::MaybeUninit::uninit()); let buf: Box = { err::error_on_minusone(obj.py(), unsafe { ffi::PyObject_GetBuffer(obj.as_ptr(), buf.as_mut_ptr(), ffi::PyBUF_FULL_RO) })?; // Safety: buf is initialized by PyObject_GetBuffer. // TODO: use nightly API Box::assume_init() once stable unsafe { mem::transmute(buf) } }; // Create PyBuffer immediately so that if validation checks fail, the PyBuffer::drop code // will call PyBuffer_Release (thus avoiding any leaks). let buf = PyBuffer(Pin::from(buf), PhantomData); if buf.0.shape.is_null() { Err(PyBufferError::new_err("shape is null")) } else if buf.0.strides.is_null() { Err(PyBufferError::new_err("strides is null")) } else if mem::size_of::() != buf.item_size() || !T::is_compatible_format(buf.format()) { Err(PyBufferError::new_err(format!( "buffer contents are not compatible with {}", std::any::type_name::() ))) } else if buf.0.buf.align_offset(mem::align_of::()) != 0 { Err(PyBufferError::new_err(format!( "buffer contents are insufficiently aligned for {}", std::any::type_name::() ))) } else { Ok(buf) } } /// Gets the pointer to the start of the buffer memory. /// /// Warning: the buffer memory might be mutated by other Python functions, /// and thus may only be accessed while the GIL is held. #[inline] pub fn buf_ptr(&self) -> *mut raw::c_void { self.0.buf } /// Gets a pointer to the specified item. /// /// If `indices.len() < self.dimensions()`, returns the start address of the sub-array at the specified dimension. pub fn get_ptr(&self, indices: &[usize]) -> *mut raw::c_void { let shape = &self.shape()[..indices.len()]; for i in 0..indices.len() { assert!(indices[i] < shape[i]); } unsafe { ffi::PyBuffer_GetPointer( #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, #[cfg(Py_3_11)] { indices.as_ptr().cast() }, #[cfg(not(Py_3_11))] { indices.as_ptr() as *mut ffi::Py_ssize_t }, ) } } /// Gets whether the underlying buffer is read-only. #[inline] pub fn readonly(&self) -> bool { self.0.readonly != 0 } /// Gets the size of a single element, in bytes. /// Important exception: when requesting an unformatted buffer, item_size still has the value #[inline] pub fn item_size(&self) -> usize { self.0.itemsize as usize } /// Gets the total number of items. #[inline] pub fn item_count(&self) -> usize { (self.0.len as usize) / (self.0.itemsize as usize) } /// `item_size() * item_count()`. /// For contiguous arrays, this is the length of the underlying memory block. /// For non-contiguous arrays, it is the length that the logical structure would have if it were copied to a contiguous representation. #[inline] pub fn len_bytes(&self) -> usize { self.0.len as usize } /// Gets the number of dimensions. /// /// May be 0 to indicate a single scalar value. #[inline] pub fn dimensions(&self) -> usize { self.0.ndim as usize } /// Returns an array of length `dimensions`. `shape()[i]` is the length of the array in dimension number `i`. /// /// May return None for single-dimensional arrays or scalar values (`dimensions() <= 1`); /// You can call `item_count()` to get the length of the single dimension. /// /// Despite Python using an array of signed integers, the values are guaranteed to be non-negative. /// However, dimensions of length 0 are possible and might need special attention. #[inline] pub fn shape(&self) -> &[usize] { unsafe { slice::from_raw_parts(self.0.shape.cast(), self.0.ndim as usize) } } /// Returns an array that holds, for each dimension, the number of bytes to skip to get to the next element in the dimension. /// /// Stride values can be any integer. For regular arrays, strides are usually positive, /// but a consumer MUST be able to handle the case `strides[n] <= 0`. #[inline] pub fn strides(&self) -> &[isize] { unsafe { slice::from_raw_parts(self.0.strides, self.0.ndim as usize) } } /// An array of length ndim. /// If `suboffsets[n] >= 0`, the values stored along the nth dimension are pointers and the suboffset value dictates how many bytes to add to each pointer after de-referencing. /// A suboffset value that is negative indicates that no de-referencing should occur (striding in a contiguous memory block). /// /// If all suboffsets are negative (i.e. no de-referencing is needed), then this field must be NULL (the default value). #[inline] pub fn suboffsets(&self) -> Option<&[isize]> { unsafe { if self.0.suboffsets.is_null() { None } else { Some(slice::from_raw_parts( self.0.suboffsets, self.0.ndim as usize, )) } } } /// A NUL terminated string in struct module style syntax describing the contents of a single item. #[inline] pub fn format(&self) -> &CStr { if self.0.format.is_null() { ffi::c_str!("B") } else { unsafe { CStr::from_ptr(self.0.format) } } } /// Gets whether the buffer is contiguous in C-style order (last index varies fastest when visiting items in order of memory address). #[inline] pub fn is_c_contiguous(&self) -> bool { unsafe { ffi::PyBuffer_IsContiguous(&*self.0, b'C' as std::os::raw::c_char) != 0 } } /// Gets whether the buffer is contiguous in Fortran-style order (first index varies fastest when visiting items in order of memory address). #[inline] pub fn is_fortran_contiguous(&self) -> bool { unsafe { ffi::PyBuffer_IsContiguous(&*self.0, b'F' as std::os::raw::c_char) != 0 } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is C-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell]> { if self.is_c_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut ReadOnlyCell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer is not read-only /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is C-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell]> { if !self.readonly() && self.is_c_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut cell::Cell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is Fortran-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_fortran_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell]> { if mem::size_of::() == self.item_size() && self.is_fortran_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut ReadOnlyCell, self.item_count(), )) } } else { None } } /// Gets the buffer memory as a slice. /// /// This function succeeds if: /// * the buffer is not read-only /// * the buffer format is compatible with `T` /// * alignment and size of buffer elements is matching the expectations for type `T` /// * the buffer is Fortran-style contiguous /// /// The returned slice uses type `Cell` because it's theoretically possible for any call into the Python runtime /// to modify the values in the slice. pub fn as_fortran_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell]> { if !self.readonly() && self.is_fortran_contiguous() { unsafe { Some(slice::from_raw_parts( self.0.buf as *mut cell::Cell, self.item_count(), )) } } else { None } } /// Copies the buffer elements to the specified slice. /// If the buffer is multi-dimensional, the elements are written in C-style order. /// /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// you can use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_to_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> { self._copy_to_slice(py, target, b'C') } /// Copies the buffer elements to the specified slice. /// If the buffer is multi-dimensional, the elements are written in Fortran-style order. /// /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// you can use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_to_fortran_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> { self._copy_to_slice(py, target, b'F') } fn _copy_to_slice(&self, py: Python<'_>, target: &mut [T], fort: u8) -> PyResult<()> { if mem::size_of_val(target) != self.len_bytes() { return Err(PyBufferError::new_err(format!( "slice to copy to (of length {}) does not match buffer length of {}", target.len(), self.item_count() ))); } err::error_on_minusone(py, unsafe { ffi::PyBuffer_ToContiguous( target.as_mut_ptr().cast(), #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, self.0.len, fort as std::os::raw::c_char, ) }) } /// Copies the buffer elements to a newly allocated vector. /// If the buffer is multi-dimensional, the elements are written in C-style order. /// /// Fails if the buffer format is not compatible with type `T`. pub fn to_vec(&self, py: Python<'_>) -> PyResult> { self._to_vec(py, b'C') } /// Copies the buffer elements to a newly allocated vector. /// If the buffer is multi-dimensional, the elements are written in Fortran-style order. /// /// Fails if the buffer format is not compatible with type `T`. pub fn to_fortran_vec(&self, py: Python<'_>) -> PyResult> { self._to_vec(py, b'F') } fn _to_vec(&self, py: Python<'_>, fort: u8) -> PyResult> { let item_count = self.item_count(); let mut vec: Vec = Vec::with_capacity(item_count); // Copy the buffer into the uninitialized space in the vector. // Due to T:Copy, we don't need to be concerned with Drop impls. err::error_on_minusone(py, unsafe { ffi::PyBuffer_ToContiguous( vec.as_ptr() as *mut raw::c_void, #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, self.0.len, fort as std::os::raw::c_char, ) })?; // set vector length to mark the now-initialized space as usable unsafe { vec.set_len(item_count) }; Ok(vec) } /// Copies the specified slice into the buffer. /// If the buffer is multi-dimensional, the elements in the slice are expected to be in C-style order. /// /// * Fails if the buffer is read-only. /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_from_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> { self._copy_from_slice(py, source, b'C') } /// Copies the specified slice into the buffer. /// If the buffer is multi-dimensional, the elements in the slice are expected to be in Fortran-style order. /// /// * Fails if the buffer is read-only. /// * Fails if the slice does not have the correct length (`buf.item_count()`). /// * Fails if the buffer format is not compatible with type `T`. /// /// To check whether the buffer format is compatible before calling this method, /// use `::is_compatible_format(buf.format())`. /// Alternatively, `match buffer::ElementType::from_format(buf.format())`. pub fn copy_from_fortran_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> { self._copy_from_slice(py, source, b'F') } fn _copy_from_slice(&self, py: Python<'_>, source: &[T], fort: u8) -> PyResult<()> { if self.readonly() { return Err(PyBufferError::new_err("cannot write to read-only buffer")); } else if mem::size_of_val(source) != self.len_bytes() { return Err(PyBufferError::new_err(format!( "slice to copy from (of length {}) does not match buffer length of {}", source.len(), self.item_count() ))); } err::error_on_minusone(py, unsafe { ffi::PyBuffer_FromContiguous( #[cfg(Py_3_11)] &*self.0, #[cfg(not(Py_3_11))] { &*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer }, #[cfg(Py_3_11)] { source.as_ptr().cast() }, #[cfg(not(Py_3_11))] { source.as_ptr() as *mut raw::c_void }, self.0.len, fort as std::os::raw::c_char, ) }) } /// Releases the buffer object, freeing the reference to the Python object /// which owns the buffer. /// /// This will automatically be called on drop. pub fn release(self, _py: Python<'_>) { // First move self into a ManuallyDrop, so that PyBuffer::drop will // never be called. (It would acquire the GIL and call PyBuffer_Release // again.) let mut mdself = mem::ManuallyDrop::new(self); unsafe { // Next, make the actual PyBuffer_Release call. ffi::PyBuffer_Release(&mut *mdself.0); // Finally, drop the contained Pin> in place, to free the // Box memory. let inner: *mut Pin> = &mut mdself.0; ptr::drop_in_place(inner); } } } impl Drop for PyBuffer { fn drop(&mut self) { Python::with_gil(|_| unsafe { ffi::PyBuffer_Release(&mut *self.0) }); } } /// Like [std::cell::Cell], but only provides read-only access to the data. /// /// `&ReadOnlyCell` is basically a safe version of `*const T`: /// The data cannot be modified through the reference, but other references may /// be modifying the data. #[repr(transparent)] pub struct ReadOnlyCell(cell::UnsafeCell); impl ReadOnlyCell { /// Returns a copy of the current value. #[inline] pub fn get(&self) -> T { unsafe { *self.0.get() } } /// Returns a pointer to the current value. #[inline] pub fn as_ptr(&self) -> *const T { self.0.get() } } macro_rules! impl_element( ($t:ty, $f:ident) => { unsafe impl Element for $t { fn is_compatible_format(format: &CStr) -> bool { let slice = format.to_bytes(); if slice.len() > 1 && !is_matching_endian(slice[0]) { return false; } ElementType::from_format(format) == ElementType::$f { bytes: mem::size_of::<$t>() } } } } ); impl_element!(u8, UnsignedInteger); impl_element!(u16, UnsignedInteger); impl_element!(u32, UnsignedInteger); impl_element!(u64, UnsignedInteger); impl_element!(usize, UnsignedInteger); impl_element!(i8, SignedInteger); impl_element!(i16, SignedInteger); impl_element!(i32, SignedInteger); impl_element!(i64, SignedInteger); impl_element!(isize, SignedInteger); impl_element!(f32, Float); impl_element!(f64, Float); #[cfg(test)] mod tests { use super::PyBuffer; use crate::ffi; use crate::types::any::PyAnyMethods; use crate::Python; #[test] fn test_debug() { Python::with_gil(|py| { let bytes = py.eval_bound("b'abcde'", None, None).unwrap(); let buffer: PyBuffer = PyBuffer::get_bound(&bytes).unwrap(); let expected = format!( concat!( "PyBuffer {{ buf: {:?}, obj: {:?}, ", "len: 5, itemsize: 1, readonly: 1, ", "ndim: 1, format: {:?}, shape: {:?}, ", "strides: {:?}, suboffsets: {:?}, internal: {:?} }}", ), buffer.0.buf, buffer.0.obj, buffer.0.format, buffer.0.shape, buffer.0.strides, buffer.0.suboffsets, buffer.0.internal ); let debug_repr = format!("{:?}", buffer); assert_eq!(debug_repr, expected); }); } #[test] fn test_element_type_from_format() { use super::ElementType; use super::ElementType::*; use std::mem::size_of; use std::os::raw; for (cstr, expected) in [ // @ prefix goes to native_element_type_from_type_char ( ffi::c_str!("@b"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@c"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@b"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@B"), UnsignedInteger { bytes: size_of::(), }, ), (ffi::c_str!("@?"), Bool), ( ffi::c_str!("@h"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@H"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@i"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@I"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@l"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@L"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@q"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@Q"), UnsignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@n"), SignedInteger { bytes: size_of::(), }, ), ( ffi::c_str!("@N"), UnsignedInteger { bytes: size_of::(), }, ), (ffi::c_str!("@e"), Float { bytes: 2 }), (ffi::c_str!("@f"), Float { bytes: 4 }), (ffi::c_str!("@d"), Float { bytes: 8 }), (ffi::c_str!("@z"), Unknown), // = prefix goes to standard_element_type_from_type_char (ffi::c_str!("=b"), SignedInteger { bytes: 1 }), (ffi::c_str!("=c"), UnsignedInteger { bytes: 1 }), (ffi::c_str!("=B"), UnsignedInteger { bytes: 1 }), (ffi::c_str!("=?"), Bool), (ffi::c_str!("=h"), SignedInteger { bytes: 2 }), (ffi::c_str!("=H"), UnsignedInteger { bytes: 2 }), (ffi::c_str!("=l"), SignedInteger { bytes: 4 }), (ffi::c_str!("=l"), SignedInteger { bytes: 4 }), (ffi::c_str!("=I"), UnsignedInteger { bytes: 4 }), (ffi::c_str!("=L"), UnsignedInteger { bytes: 4 }), (ffi::c_str!("=q"), SignedInteger { bytes: 8 }), (ffi::c_str!("=Q"), UnsignedInteger { bytes: 8 }), (ffi::c_str!("=e"), Float { bytes: 2 }), (ffi::c_str!("=f"), Float { bytes: 4 }), (ffi::c_str!("=d"), Float { bytes: 8 }), (ffi::c_str!("=z"), Unknown), (ffi::c_str!("=0"), Unknown), // unknown prefix -> Unknown (ffi::c_str!(":b"), Unknown), ] { assert_eq!( ElementType::from_format(cstr), expected, "element from format &Cstr: {:?}", cstr, ); } } #[test] fn test_compatible_size() { // for the cast in PyBuffer::shape() assert_eq!( std::mem::size_of::(), std::mem::size_of::() ); } #[test] fn test_bytes_buffer() { Python::with_gil(|py| { let bytes = py.eval_bound("b'abcde'", None, None).unwrap(); let buffer = PyBuffer::get_bound(&bytes).unwrap(); assert_eq!(buffer.dimensions(), 1); assert_eq!(buffer.item_count(), 5); assert_eq!(buffer.format().to_str().unwrap(), "B"); assert_eq!(buffer.shape(), [5]); // single-dimensional buffer is always contiguous assert!(buffer.is_c_contiguous()); assert!(buffer.is_fortran_contiguous()); let slice = buffer.as_slice(py).unwrap(); assert_eq!(slice.len(), 5); assert_eq!(slice[0].get(), b'a'); assert_eq!(slice[2].get(), b'c'); assert_eq!(unsafe { *(buffer.get_ptr(&[1]) as *mut u8) }, b'b'); assert!(buffer.as_mut_slice(py).is_none()); assert!(buffer.copy_to_slice(py, &mut [0u8]).is_err()); let mut arr = [0; 5]; buffer.copy_to_slice(py, &mut arr).unwrap(); assert_eq!(arr, b"abcde" as &[u8]); assert!(buffer.copy_from_slice(py, &[0u8; 5]).is_err()); assert_eq!(buffer.to_vec(py).unwrap(), b"abcde"); }); } #[test] fn test_array_buffer() { Python::with_gil(|py| { let array = py .import_bound("array") .unwrap() .call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None) .unwrap(); let buffer = PyBuffer::get_bound(&array).unwrap(); assert_eq!(buffer.dimensions(), 1); assert_eq!(buffer.item_count(), 4); assert_eq!(buffer.format().to_str().unwrap(), "f"); assert_eq!(buffer.shape(), [4]); // array creates a 1D contiguious buffer, so it's both C and F contiguous. This would // be more interesting if we can come up with a 2D buffer but I think it would need a // third-party lib or a custom class. // C-contiguous fns let slice = buffer.as_slice(py).unwrap(); assert_eq!(slice.len(), 4); assert_eq!(slice[0].get(), 1.0); assert_eq!(slice[3].get(), 2.5); let mut_slice = buffer.as_mut_slice(py).unwrap(); assert_eq!(mut_slice.len(), 4); assert_eq!(mut_slice[0].get(), 1.0); mut_slice[3].set(2.75); assert_eq!(slice[3].get(), 2.75); buffer .copy_from_slice(py, &[10.0f32, 11.0, 12.0, 13.0]) .unwrap(); assert_eq!(slice[2].get(), 12.0); assert_eq!(buffer.to_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]); // F-contiguous fns let buffer = PyBuffer::get_bound(&array).unwrap(); let slice = buffer.as_fortran_slice(py).unwrap(); assert_eq!(slice.len(), 4); assert_eq!(slice[1].get(), 11.0); let mut_slice = buffer.as_fortran_mut_slice(py).unwrap(); assert_eq!(mut_slice.len(), 4); assert_eq!(mut_slice[2].get(), 12.0); mut_slice[3].set(2.75); assert_eq!(slice[3].get(), 2.75); buffer .copy_from_fortran_slice(py, &[10.0f32, 11.0, 12.0, 13.0]) .unwrap(); assert_eq!(slice[2].get(), 12.0); assert_eq!(buffer.to_fortran_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]); }); } } pyo3/src/tests/0000775000175000017500000000000014661133735014366 5ustar jamespagejamespagepyo3/src/tests/common.rs0000644000175000017500000001356214661133735016231 0ustar jamespagejamespage// the inner mod enables the #![allow(dead_code)] to // be applied - `test_utils.rs` uses `include!` to pull in this file /// Common macros and helpers for tests #[allow(dead_code)] // many tests do not use the complete set of functionality offered here #[macro_use] mod inner { #[allow(unused_imports)] // pulls in `use crate as pyo3` in `test_utils.rs` use super::*; use pyo3::prelude::*; use pyo3::types::{IntoPyDict, PyList}; #[macro_export] macro_rules! py_assert { ($py:expr, $($val:ident)+, $assertion:literal) => { pyo3::py_run!($py, $($val)+, concat!("assert ", $assertion)) }; ($py:expr, *$dict:expr, $assertion:literal) => { pyo3::py_run!($py, *$dict, concat!("assert ", $assertion)) }; } #[macro_export] macro_rules! assert_py_eq { ($val:expr, $expected:expr) => { assert!($val.eq($expected).unwrap()); }; } #[macro_export] macro_rules! py_expect_exception { // Case1: idents & no err_msg ($py:expr, $($val:ident)+, $code:expr, $err:ident) => {{ use pyo3::types::IntoPyDict; let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict_bound($py); py_expect_exception!($py, *d, $code, $err) }}; // Case2: dict & no err_msg ($py:expr, *$dict:expr, $code:expr, $err:ident) => {{ let res = $py.run_bound($code, None, Some(&$dict.as_borrowed())); let err = res.expect_err(&format!("Did not raise {}", stringify!($err))); if !err.matches($py, $py.get_type_bound::()) { panic!("Expected {} but got {:?}", stringify!($err), err) } err }}; // Case3: idents & err_msg ($py:expr, $($val:ident)+, $code:expr, $err:ident, $err_msg:literal) => {{ let err = py_expect_exception!($py, $($val)+, $code, $err); // Suppose that the error message looks like 'TypeError: ~' assert_eq!(format!("Py{}", err), concat!(stringify!($err), ": ", $err_msg)); err }}; // Case4: dict & err_msg ($py:expr, *$dict:expr, $code:expr, $err:ident, $err_msg:literal) => {{ let err = py_expect_exception!($py, *$dict, $code, $err); assert_eq!(format!("Py{}", err), concat!(stringify!($err), ": ", $err_msg)); err }}; } // sys.unraisablehook not available until Python 3.8 #[cfg(all(feature = "macros", Py_3_8))] #[pyclass(crate = "pyo3")] pub struct UnraisableCapture { pub capture: Option<(PyErr, PyObject)>, old_hook: Option, } #[cfg(all(feature = "macros", Py_3_8))] #[pymethods(crate = "pyo3")] impl UnraisableCapture { pub fn hook(&mut self, unraisable: Bound<'_, PyAny>) { let err = PyErr::from_value_bound(unraisable.getattr("exc_value").unwrap()); let instance = unraisable.getattr("object").unwrap(); self.capture = Some((err, instance.into())); } } #[cfg(all(feature = "macros", Py_3_8))] impl UnraisableCapture { pub fn install(py: Python<'_>) -> Py { let sys = py.import_bound("sys").unwrap(); let old_hook = sys.getattr("unraisablehook").unwrap().into(); let capture = Py::new( py, UnraisableCapture { capture: None, old_hook: Some(old_hook), }, ) .unwrap(); sys.setattr("unraisablehook", capture.getattr(py, "hook").unwrap()) .unwrap(); capture } pub fn uninstall(&mut self, py: Python<'_>) { let old_hook = self.old_hook.take().unwrap(); let sys = py.import_bound("sys").unwrap(); sys.setattr("unraisablehook", old_hook).unwrap(); } } pub struct CatchWarnings<'py> { catch_warnings: Bound<'py, PyAny>, } impl<'py> CatchWarnings<'py> { pub fn enter( py: Python<'py>, f: impl FnOnce(&Bound<'py, PyList>) -> PyResult, ) -> PyResult { let warnings = py.import_bound("warnings")?; let kwargs = [("record", true)].into_py_dict_bound(py); let catch_warnings = warnings .getattr("catch_warnings")? .call((), Some(&kwargs))?; let list = catch_warnings.call_method0("__enter__")?.downcast_into()?; let _guard = Self { catch_warnings }; f(&list) } } impl Drop for CatchWarnings<'_> { fn drop(&mut self) { let py = self.catch_warnings.py(); self.catch_warnings .call_method1("__exit__", (py.None(), py.None(), py.None())) .unwrap(); } } #[macro_export] macro_rules! assert_warnings { ($py:expr, $body:expr, [$(($category:ty, $message:literal)),+] $(,)? ) => {{ $crate::tests::common::CatchWarnings::enter($py, |w| { use $crate::types::{PyListMethods, PyStringMethods}; $body; let expected_warnings = [$((<$category as $crate::type_object::PyTypeInfo>::type_object_bound($py), $message)),+]; assert_eq!(w.len(), expected_warnings.len()); for (warning, (category, message)) in w.iter().zip(expected_warnings) { assert!(warning.getattr("category").unwrap().is(&category)); assert_eq!( warning.getattr("message").unwrap().str().unwrap().to_string_lossy(), message ); } Ok(()) }) .unwrap(); }}; } } #[allow(unused_imports)] // some tests use just the macros and none of the other functionality pub use inner::*; pyo3/src/tests/mod.rs0000644000175000017500000000037114661133735015512 0ustar jamespagejamespage#[macro_use] pub(crate) mod common { use crate as pyo3; include!("./common.rs"); } /// Test macro hygiene - this is in the crate since we won't have /// `pyo3` available in the crate root. #[cfg(all(test, feature = "macros"))] mod hygiene; pyo3/src/tests/hygiene/0000775000175000017500000000000014661133735016016 5ustar jamespagejamespagepyo3/src/tests/hygiene/pymethods.rs0000644000175000017500000002311614661133735020401 0ustar jamespagejamespage#![no_implicit_prelude] #![allow(unused_variables, clippy::unnecessary_wraps)] #[crate::pyclass] #[pyo3(crate = "crate")] pub struct Dummy; #[crate::pyclass] #[pyo3(crate = "crate")] pub struct DummyIter; #[crate::pymethods] #[pyo3(crate = "crate")] impl Dummy { ////////////////////// // Basic customization ////////////////////// fn __repr__(&self) -> &'static str { "Dummy" } fn __str__(&self) -> &'static str { "Dummy" } fn __bytes__<'py>(&self, py: crate::Python<'py>) -> crate::Bound<'py, crate::types::PyBytes> { crate::types::PyBytes::new_bound(py, &[0]) } fn __format__(&self, format_spec: ::std::string::String) -> ::std::string::String { ::std::unimplemented!() } fn __lt__(&self, other: &Self) -> bool { false } fn __le__(&self, other: &Self) -> bool { false } fn __eq__(&self, other: &Self) -> bool { false } fn __ne__(&self, other: &Self) -> bool { false } fn __gt__(&self, other: &Self) -> bool { false } fn __ge__(&self, other: &Self) -> bool { false } fn __hash__(&self) -> u64 { 42 } fn __bool__(&self) -> bool { true } ////////////////////// // Customizing attribute access ////////////////////// fn __getattr__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> { ::std::unimplemented!() } fn __getattribute__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> { ::std::unimplemented!() } fn __setattr__(&mut self, name: ::std::string::String, value: ::std::string::String) {} fn __delattr__(&mut self, name: ::std::string::String) {} fn __dir__<'py>(&self, py: crate::Python<'py>) -> crate::Bound<'py, crate::types::PyList> { crate::types::PyList::new_bound(py, ::std::vec![0_u8]) } ////////////////////// // Implementing Descriptors ////////////////////// fn __get__( &self, instance: &crate::Bound<'_, crate::PyAny>, owner: &crate::Bound<'_, crate::PyAny>, ) -> crate::PyResult<&crate::Bound<'_, crate::PyAny>> { ::std::unimplemented!() } fn __set__( &self, instance: &crate::Bound<'_, crate::PyAny>, owner: &crate::Bound<'_, crate::PyAny>, ) { } fn __delete__(&self, instance: &crate::Bound<'_, crate::PyAny>) {} fn __set_name__( &self, owner: &crate::Bound<'_, crate::PyAny>, name: &crate::Bound<'_, crate::PyAny>, ) { } ////////////////////// // Implementing Descriptors ////////////////////// fn __len__(&self) -> usize { 0 } fn __getitem__(&self, key: u32) -> crate::PyResult { ::std::result::Result::Err(crate::exceptions::PyKeyError::new_err("boo")) } fn __setitem__(&self, key: u32, value: u32) {} fn __delitem__(&self, key: u32) {} fn __iter__(_: crate::pycell::PyRef<'_, Self>, py: crate::Python<'_>) -> crate::Py { crate::Py::new(py, DummyIter {}).unwrap() } fn __next__(&mut self) -> ::std::option::Option<()> { ::std::option::Option::None } fn __reversed__( slf: crate::pycell::PyRef<'_, Self>, py: crate::Python<'_>, ) -> crate::Py { crate::Py::new(py, DummyIter {}).unwrap() } fn __contains__(&self, item: u32) -> bool { false } ////////////////////// // Emulating numeric types ////////////////////// fn __add__(&self, other: &Self) -> Dummy { Dummy {} } fn __sub__(&self, other: &Self) -> Dummy { Dummy {} } fn __mul__(&self, other: &Self) -> Dummy { Dummy {} } fn __truediv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __floordiv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __mod__(&self, _other: &Self) -> u32 { 0 } fn __divmod__(&self, _other: &Self) -> (u32, u32) { (0, 0) } fn __pow__(&self, _other: &Self, modulo: ::std::option::Option) -> Dummy { Dummy {} } fn __lshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __rshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __and__(&self, other: &Self) -> Dummy { Dummy {} } fn __xor__(&self, other: &Self) -> Dummy { Dummy {} } fn __or__(&self, other: &Self) -> Dummy { Dummy {} } fn __radd__(&self, other: &Self) -> Dummy { Dummy {} } fn __rrsub__(&self, other: &Self) -> Dummy { Dummy {} } fn __rmul__(&self, other: &Self) -> Dummy { Dummy {} } fn __rtruediv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __rfloordiv__(&self, _other: &Self) -> crate::PyResult<()> { ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err("boo")) } fn __rmod__(&self, _other: &Self) -> u32 { 0 } fn __rdivmod__(&self, _other: &Self) -> (u32, u32) { (0, 0) } fn __rpow__(&self, _other: &Self, modulo: ::std::option::Option) -> Dummy { Dummy {} } fn __rlshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __rrshift__(&self, other: &Self) -> Dummy { Dummy {} } fn __rand__(&self, other: &Self) -> Dummy { Dummy {} } fn __rxor__(&self, other: &Self) -> Dummy { Dummy {} } fn __ror__(&self, other: &Self) -> Dummy { Dummy {} } fn __iadd__(&mut self, other: &Self) {} fn __irsub__(&mut self, other: &Self) {} fn __imul__(&mut self, other: &Self) {} fn __itruediv__(&mut self, _other: &Self) {} fn __ifloordiv__(&mut self, _other: &Self) {} fn __imod__(&mut self, _other: &Self) {} fn __ipow__(&mut self, _other: &Self, modulo: ::std::option::Option) {} fn __ilshift__(&mut self, other: &Self) {} fn __irshift__(&mut self, other: &Self) {} fn __iand__(&mut self, other: &Self) {} fn __ixor__(&mut self, other: &Self) {} fn __ior__(&mut self, other: &Self) {} fn __neg__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __pos__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __abs__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __invert__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } fn __complex__<'py>( &self, py: crate::Python<'py>, ) -> crate::Bound<'py, crate::types::PyComplex> { crate::types::PyComplex::from_doubles_bound(py, 0.0, 0.0) } fn __int__(&self) -> u32 { 0 } fn __float__(&self) -> f64 { 0.0 } fn __index__(&self) -> u32 { 0 } #[pyo3(signature=(ndigits=::std::option::Option::None))] fn __round__(&self, ndigits: ::std::option::Option) -> u32 { 0 } fn __trunc__(&self) -> u32 { 0 } fn __floor__(&self) -> u32 { 0 } fn __ceil__(&self) -> u32 { 0 } ////////////////////// // With Statement Context Managers ////////////////////// fn __enter__(&mut self) {} fn __exit__( &mut self, exc_type: &crate::Bound<'_, crate::PyAny>, exc_value: &crate::Bound<'_, crate::PyAny>, traceback: &crate::Bound<'_, crate::PyAny>, ) { } ////////////////////// // Awaitable Objects ////////////////////// fn __await__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> { slf } ////////////////////// // Asynchronous Iterators ////////////////////// fn __aiter__( slf: crate::pycell::PyRef<'_, Self>, py: crate::Python<'_>, ) -> crate::Py { crate::Py::new(py, DummyIter {}).unwrap() } fn __anext__(&mut self) -> ::std::option::Option<()> { ::std::option::Option::None } ////////////////////// // Asynchronous Context Managers ////////////////////// fn __aenter__(&mut self) {} fn __aexit__( &mut self, exc_type: &crate::Bound<'_, crate::PyAny>, exc_value: &crate::Bound<'_, crate::PyAny>, traceback: &crate::Bound<'_, crate::PyAny>, ) { } // Things with attributes #[pyo3(signature = (_y, *, _z=2))] fn test(&self, _y: &Dummy, _z: i32) {} #[staticmethod] fn staticmethod() {} #[classmethod] fn clsmethod(_: &crate::Bound<'_, crate::types::PyType>) {} #[pyo3(signature = (*_args, **_kwds))] fn __call__( &self, _args: &crate::Bound<'_, crate::types::PyTuple>, _kwds: ::std::option::Option<&crate::Bound<'_, crate::types::PyDict>>, ) -> crate::PyResult { ::std::unimplemented!() } #[new] fn new(a: u8) -> Self { Dummy {} } #[getter] fn get(&self) -> i32 { 0 } #[setter] fn set(&mut self, _v: i32) {} #[classattr] fn class_attr() -> i32 { 0 } // Dunder methods invented for protocols // PyGcProtocol // Buffer protocol? } // Ensure that crate argument is also accepted inline #[crate::pyclass(crate = "crate")] struct Dummy2; #[crate::pymethods(crate = "crate")] impl Dummy2 {} pyo3/src/tests/hygiene/pyfunction.rs0000644000175000017500000000125714661133735020565 0ustar jamespagejamespage#![no_implicit_prelude] #![allow(unused_variables, clippy::unnecessary_wraps)] #[crate::pyfunction] #[pyo3(crate = "crate")] fn do_something(x: i32) -> crate::PyResult { ::std::result::Result::Ok(x) } #[test] #[cfg(feature = "gil-refs")] fn invoke_wrap_pyfunction() { crate::Python::with_gil(|py| { #[allow(deprecated)] let func = crate::wrap_pyfunction!(do_something)(py).unwrap(); crate::py_run!(py, func, r#"func(5)"#); }); } #[test] fn invoke_wrap_pyfunction_bound() { crate::Python::with_gil(|py| { let func = crate::wrap_pyfunction_bound!(do_something, py).unwrap(); crate::py_run!(py, func, r#"func(5)"#); }); } pyo3/src/tests/hygiene/pymodule.rs0000644000175000017500000000266414661133735020230 0ustar jamespagejamespage#![no_implicit_prelude] #![allow(unused_variables, clippy::unnecessary_wraps)] #[crate::pyfunction] #[pyo3(crate = "crate")] fn do_something(x: i32) -> crate::PyResult { ::std::result::Result::Ok(x) } #[cfg(feature = "gil-refs")] #[allow(deprecated)] #[crate::pymodule] #[pyo3(crate = "crate")] fn foo(_py: crate::Python<'_>, _m: &crate::types::PyModule) -> crate::PyResult<()> { ::std::result::Result::Ok(()) } #[crate::pymodule] #[pyo3(crate = "crate")] fn foo_bound( _py: crate::Python<'_>, _m: &crate::Bound<'_, crate::types::PyModule>, ) -> crate::PyResult<()> { ::std::result::Result::Ok(()) } #[cfg(feature = "gil-refs")] #[allow(deprecated)] #[crate::pymodule] #[pyo3(crate = "crate")] fn my_module(_py: crate::Python<'_>, m: &crate::types::PyModule) -> crate::PyResult<()> { m.add_function(crate::wrap_pyfunction!(do_something, m)?)?; m.add_wrapped(crate::wrap_pymodule!(foo))?; ::std::result::Result::Ok(()) } #[crate::pymodule] #[pyo3(crate = "crate")] fn my_module_bound(m: &crate::Bound<'_, crate::types::PyModule>) -> crate::PyResult<()> { as crate::types::PyModuleMethods>::add_function( m, crate::wrap_pyfunction_bound!(do_something, m)?, )?; as crate::types::PyModuleMethods>::add_wrapped( m, crate::wrap_pymodule!(foo_bound), )?; ::std::result::Result::Ok(()) } pyo3/src/tests/hygiene/pyclass.rs0000644000175000017500000000241014661133735020035 0ustar jamespagejamespage#![no_implicit_prelude] #![allow(unused_variables)] #[crate::pyclass] #[pyo3(crate = "crate")] #[derive(::std::clone::Clone)] pub struct Foo; #[crate::pyclass] #[pyo3(crate = "crate")] pub struct Foo2; #[cfg_attr(any(Py_3_9, not(Py_LIMITED_API)), crate::pyclass( name = "ActuallyBar", freelist = 8, unsendable, subclass, extends = crate::types::PyAny, module = "Spam", weakref, dict ))] #[cfg_attr(not(any(Py_3_9, not(Py_LIMITED_API))), crate::pyclass( name = "ActuallyBar", freelist = 8, unsendable, subclass, extends = crate::types::PyAny, module = "Spam" ))] #[pyo3(crate = "crate")] pub struct Bar { #[pyo3(get, set)] a: u8, #[pyo3(get, set)] b: Foo, #[pyo3(set)] c: ::std::option::Option>, } #[crate::pyclass(eq, eq_int)] #[pyo3(crate = "crate")] #[derive(PartialEq)] pub enum Enum { Var0, } #[crate::pyclass] #[pyo3(crate = "crate")] pub struct Foo3 { #[pyo3(get, set)] #[cfg(any())] field: i32, #[pyo3(get, set)] #[cfg(not(any()))] field: u32, } #[crate::pyclass] #[pyo3(crate = "crate")] pub struct Foo4 { #[pyo3(get, set)] #[cfg(any())] #[cfg(not(any()))] field: i32, #[pyo3(get, set)] #[cfg(not(any()))] field: u32, } pyo3/src/tests/hygiene/mod.rs0000644000175000017500000000053714661133735017146 0ustar jamespagejamespage// The modules in this test are used to check PyO3 macro expansion is hygienic. By locating the test // inside the crate the global `::pyo3` namespace is not available, so in combination with // #[pyo3(crate = "crate")] this validates that all macro expansion respects the setting. mod misc; mod pyclass; mod pyfunction; mod pymethods; mod pymodule; pyo3/src/tests/hygiene/misc.rs0000644000175000017500000000230614661133735017316 0ustar jamespagejamespage#![no_implicit_prelude] #[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] struct Derive1(#[allow(dead_code)] i32); // newtype case #[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] #[allow(dead_code)] struct Derive2(i32, i32); // tuple case #[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] #[allow(dead_code)] struct Derive3 { f: i32, #[pyo3(item(42))] g: i32, } // struct case #[derive(crate::FromPyObject)] #[pyo3(crate = "crate")] #[allow(dead_code)] enum Derive4 { A(i32), B { f: i32 }, } // enum case crate::create_exception!(mymodule, CustomError, crate::exceptions::PyException); crate::import_exception!(socket, gaierror); #[allow(dead_code)] fn intern(py: crate::Python<'_>) { let _foo = crate::intern!(py, "foo"); let _bar = crate::intern!(py, stringify!(bar)); } #[allow(dead_code)] #[cfg(not(PyPy))] fn append_to_inittab() { #[crate::pymodule] #[pyo3(crate = "crate")] #[allow(clippy::unnecessary_wraps)] fn module_for_inittab( _: crate::Python<'_>, _: &crate::Bound<'_, crate::types::PyModule>, ) -> crate::PyResult<()> { ::std::result::Result::Ok(()) } crate::append_to_inittab!(module_for_inittab); } pyo3/src/exceptions.rs0000644000175000017500000011274714661133735015765 0ustar jamespagejamespage//! Exception and warning types defined by Python. //! //! The structs in this module represent Python's built-in exceptions and //! warnings, while the modules comprise structs representing errors defined in //! Python code. //! //! The latter are created with the //! [`import_exception`](crate::import_exception) macro, which you can use //! yourself to import Python classes that are ultimately derived from //! `BaseException`. use crate::{ffi, Bound, PyResult, Python}; use std::ffi::CStr; use std::ops; /// The boilerplate to convert between a Rust type and a Python exception. #[doc(hidden)] #[macro_export] macro_rules! impl_exception_boilerplate { ($name: ident) => { // FIXME https://github.com/PyO3/pyo3/issues/3903 #[allow(unknown_lints, non_local_definitions)] #[cfg(feature = "gil-refs")] impl ::std::convert::From<&$name> for $crate::PyErr { #[inline] fn from(err: &$name) -> $crate::PyErr { #[allow(deprecated)] $crate::PyErr::from_value(err) } } $crate::impl_exception_boilerplate_bound!($name); #[cfg(feature = "gil-refs")] impl ::std::error::Error for $name { fn source(&self) -> ::std::option::Option<&(dyn ::std::error::Error + 'static)> { unsafe { #[allow(deprecated)] let cause: &$crate::exceptions::PyBaseException = self .py() .from_owned_ptr_or_opt($crate::ffi::PyException_GetCause(self.as_ptr()))?; ::std::option::Option::Some(cause) } } } impl $crate::ToPyErr for $name {} }; } #[doc(hidden)] #[macro_export] macro_rules! impl_exception_boilerplate_bound { ($name: ident) => { impl $name { /// Creates a new [`PyErr`] of this type. /// /// [`PyErr`]: https://docs.rs/pyo3/latest/pyo3/struct.PyErr.html "PyErr in pyo3" #[inline] #[allow(dead_code)] pub fn new_err(args: A) -> $crate::PyErr where A: $crate::PyErrArguments + ::std::marker::Send + ::std::marker::Sync + 'static, { $crate::PyErr::new::<$name, A>(args) } } }; } /// Defines a Rust type for an exception defined in Python code. /// /// # Syntax /// /// ```import_exception!(module, MyError)``` /// /// * `module` is the name of the containing module. /// * `MyError` is the name of the new exception type. /// /// # Examples /// ``` /// use pyo3::import_exception; /// use pyo3::types::IntoPyDict; /// use pyo3::Python; /// /// import_exception!(socket, gaierror); /// /// Python::with_gil(|py| { /// let ctx = [("gaierror", py.get_type_bound::())].into_py_dict_bound(py); /// pyo3::py_run!(py, *ctx, "import socket; assert gaierror is socket.gaierror"); /// }); /// /// ``` #[macro_export] macro_rules! import_exception { ($module: expr, $name: ident) => { /// A Rust type representing an exception defined in Python code. /// /// This type was created by the [`pyo3::import_exception!`] macro - see its documentation /// for more information. /// /// [`pyo3::import_exception!`]: https://docs.rs/pyo3/latest/pyo3/macro.import_exception.html "import_exception in pyo3" #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::pyobject_native_type_core!( $name, $name::type_object_raw, #module=::std::option::Option::Some(stringify!($module)) ); impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::types::PyTypeMethods; static TYPE_OBJECT: $crate::impl_::exceptions::ImportedExceptionTypeObject = $crate::impl_::exceptions::ImportedExceptionTypeObject::new(stringify!($module), stringify!($name)); TYPE_OBJECT.get(py).as_type_ptr() } } }; } /// Variant of [`import_exception`](crate::import_exception) that does not emit code needed to /// use the imported exception type as a GIL Ref. /// /// This is useful only during migration as a way to avoid generating needless code. #[macro_export] macro_rules! import_exception_bound { ($module: expr, $name: ident) => { /// A Rust type representing an exception defined in Python code. /// /// This type was created by the [`pyo3::import_exception_bound!`] macro - see its documentation /// for more information. /// /// [`pyo3::import_exception_bound!`]: https://docs.rs/pyo3/latest/pyo3/macro.import_exception.html "import_exception in pyo3" #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate_bound!($name); // FIXME remove this: was necessary while `PyTypeInfo` requires `HasPyGilRef`, // should change in 0.22. #[cfg(feature = "gil-refs")] unsafe impl $crate::type_object::HasPyGilRef for $name { type AsRefTarget = $crate::PyAny; } $crate::pyobject_native_type_info!( $name, $name::type_object_raw, ::std::option::Option::Some(stringify!($module)) ); impl $crate::types::DerefToPyAny for $name {} impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::types::PyTypeMethods; static TYPE_OBJECT: $crate::impl_::exceptions::ImportedExceptionTypeObject = $crate::impl_::exceptions::ImportedExceptionTypeObject::new( stringify!($module), stringify!($name), ); TYPE_OBJECT.get(py).as_type_ptr() } } }; } /// Defines a new exception type. /// /// # Syntax /// /// * `module` is the name of the containing module. /// * `name` is the name of the new exception type. /// * `base` is the base class of `MyError`, usually [`PyException`]. /// * `doc` (optional) is the docstring visible to users (with `.__doc__` and `help()`) and /// /// accompanies your error type in your crate's documentation. /// /// # Examples /// /// ``` /// use pyo3::prelude::*; /// use pyo3::create_exception; /// use pyo3::exceptions::PyException; /// /// create_exception!(my_module, MyError, PyException, "Some description."); /// /// #[pyfunction] /// fn raise_myerror() -> PyResult<()> { /// let err = MyError::new_err("Some error happened."); /// Err(err) /// } /// /// #[pymodule] /// fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> { /// m.add("MyError", m.py().get_type_bound::())?; /// m.add_function(wrap_pyfunction!(raise_myerror, m)?)?; /// Ok(()) /// } /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction_bound!(raise_myerror, py)?; /// # let locals = pyo3::types::PyDict::new_bound(py); /// # locals.set_item("MyError", py.get_type_bound::())?; /// # locals.set_item("raise_myerror", fun)?; /// # /// # py.run_bound( /// # "try: /// # raise_myerror() /// # except MyError as e: /// # assert e.__doc__ == 'Some description.' /// # assert str(e) == 'Some error happened.'", /// # None, /// # Some(&locals), /// # )?; /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// Python code can handle this exception like any other exception: /// /// ```python /// from my_module import MyError, raise_myerror /// /// try: /// raise_myerror() /// except MyError as e: /// assert e.__doc__ == 'Some description.' /// assert str(e) == 'Some error happened.' /// ``` /// #[macro_export] macro_rules! create_exception { ($module: expr, $name: ident, $base: ty) => { #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::create_exception_type_object!($module, $name, $base, ::std::option::Option::None); }; ($module: expr, $name: ident, $base: ty, $doc: expr) => { #[repr(transparent)] #[allow(non_camel_case_types)] // E.g. `socket.herror` #[doc = $doc] pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::create_exception_type_object!( $module, $name, $base, ::std::option::Option::Some($doc) ); }; } /// `impl PyTypeInfo for $name` where `$name` is an /// exception newly defined in Rust code. #[doc(hidden)] #[macro_export] macro_rules! create_exception_type_object { ($module: expr, $name: ident, $base: ty, $doc: expr) => { $crate::pyobject_native_type_core!( $name, $name::type_object_raw, #module=::std::option::Option::Some(stringify!($module)) ); impl $name { fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { use $crate::sync::GILOnceCell; static TYPE_OBJECT: GILOnceCell<$crate::Py<$crate::types::PyType>> = GILOnceCell::new(); TYPE_OBJECT .get_or_init(py, || $crate::PyErr::new_type_bound( py, concat!(stringify!($module), ".", stringify!($name)), $doc, ::std::option::Option::Some(&py.get_type_bound::<$base>()), ::std::option::Option::None, ).expect("Failed to initialize new exception type.") ).as_ptr() as *mut $crate::ffi::PyTypeObject } } }; } macro_rules! impl_native_exception ( ($name:ident, $exc_name:ident, $doc:expr, $layout:path $(, #checkfunction=$checkfunction:path)?) => ( #[doc = $doc] #[allow(clippy::upper_case_acronyms)] pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::pyobject_native_type!($name, $layout, |_py| unsafe { $crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject } $(, #checkfunction=$checkfunction)?); ); ($name:ident, $exc_name:ident, $doc:expr) => ( impl_native_exception!($name, $exc_name, $doc, $crate::ffi::PyBaseExceptionObject); ) ); #[cfg(windows)] macro_rules! impl_windows_native_exception ( ($name:ident, $exc_name:ident, $doc:expr, $layout:path) => ( #[cfg(windows)] #[doc = $doc] #[allow(clippy::upper_case_acronyms)] pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::pyobject_native_type!($name, $layout, |_py| unsafe { $crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject }); ); ($name:ident, $exc_name:ident, $doc:expr) => ( impl_windows_native_exception!($name, $exc_name, $doc, $crate::ffi::PyBaseExceptionObject); ) ); macro_rules! native_doc( ($name: literal, $alt: literal) => ( concat!( "Represents Python's [`", $name, "`](https://docs.python.org/3/library/exceptions.html#", $name, ") exception. ", $alt ) ); ($name: literal) => ( concat!( " Represents Python's [`", $name, "`](https://docs.python.org/3/library/exceptions.html#", $name, ") exception. # Example: Raising ", $name, " from Rust This exception can be sent to Python code by converting it into a [`PyErr`](crate::PyErr), where Python code can then catch it. ``` use pyo3::prelude::*; use pyo3::exceptions::Py", $name, "; #[pyfunction] fn always_throws() -> PyResult<()> { let message = \"I'm ", $name ,", and I was raised from Rust.\"; Err(Py", $name, "::new_err(message)) } # # Python::with_gil(|py| { # let fun = pyo3::wrap_pyfunction_bound!(always_throws, py).unwrap(); # let err = fun.call0().expect_err(\"called a function that should always return an error but the return value was Ok\"); # assert!(err.is_instance_of::(py)) # }); ``` Python code: ```python from my_module import always_throws try: always_throws() except ", $name, " as e: print(f\"Caught an exception: {e}\") ``` # Example: Catching ", $name, " in Rust ``` use pyo3::prelude::*; use pyo3::exceptions::Py", $name, "; Python::with_gil(|py| { let result: PyResult<()> = py.run_bound(\"raise ", $name, "\", None, None); let error_type = match result { Ok(_) => \"Not an error\", Err(error) if error.is_instance_of::(py) => \"" , $name, "\", Err(_) => \"Some other error\", }; assert_eq!(error_type, \"", $name, "\"); }); ``` " ) ); ); impl_native_exception!( PyBaseException, PyExc_BaseException, native_doc!("BaseException"), ffi::PyBaseExceptionObject, #checkfunction=ffi::PyExceptionInstance_Check ); impl_native_exception!(PyException, PyExc_Exception, native_doc!("Exception")); impl_native_exception!( PyStopAsyncIteration, PyExc_StopAsyncIteration, native_doc!("StopAsyncIteration") ); impl_native_exception!( PyStopIteration, PyExc_StopIteration, native_doc!("StopIteration"), ffi::PyStopIterationObject ); impl_native_exception!( PyGeneratorExit, PyExc_GeneratorExit, native_doc!("GeneratorExit") ); impl_native_exception!( PyArithmeticError, PyExc_ArithmeticError, native_doc!("ArithmeticError") ); impl_native_exception!(PyLookupError, PyExc_LookupError, native_doc!("LookupError")); impl_native_exception!( PyAssertionError, PyExc_AssertionError, native_doc!("AssertionError") ); impl_native_exception!( PyAttributeError, PyExc_AttributeError, native_doc!("AttributeError") ); impl_native_exception!(PyBufferError, PyExc_BufferError, native_doc!("BufferError")); impl_native_exception!(PyEOFError, PyExc_EOFError, native_doc!("EOFError")); impl_native_exception!( PyFloatingPointError, PyExc_FloatingPointError, native_doc!("FloatingPointError") ); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PyOSError, PyExc_OSError, native_doc!("OSError"), ffi::PyOSErrorObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!(PyOSError, PyExc_OSError, native_doc!("OSError")); impl_native_exception!(PyImportError, PyExc_ImportError, native_doc!("ImportError")); impl_native_exception!( PyModuleNotFoundError, PyExc_ModuleNotFoundError, native_doc!("ModuleNotFoundError") ); impl_native_exception!(PyIndexError, PyExc_IndexError, native_doc!("IndexError")); impl_native_exception!(PyKeyError, PyExc_KeyError, native_doc!("KeyError")); impl_native_exception!( PyKeyboardInterrupt, PyExc_KeyboardInterrupt, native_doc!("KeyboardInterrupt") ); impl_native_exception!(PyMemoryError, PyExc_MemoryError, native_doc!("MemoryError")); impl_native_exception!(PyNameError, PyExc_NameError, native_doc!("NameError")); impl_native_exception!( PyOverflowError, PyExc_OverflowError, native_doc!("OverflowError") ); impl_native_exception!( PyRuntimeError, PyExc_RuntimeError, native_doc!("RuntimeError") ); impl_native_exception!( PyRecursionError, PyExc_RecursionError, native_doc!("RecursionError") ); impl_native_exception!( PyNotImplementedError, PyExc_NotImplementedError, native_doc!("NotImplementedError") ); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError"), ffi::PySyntaxErrorObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!(PySyntaxError, PyExc_SyntaxError, native_doc!("SyntaxError")); impl_native_exception!( PyReferenceError, PyExc_ReferenceError, native_doc!("ReferenceError") ); impl_native_exception!(PySystemError, PyExc_SystemError, native_doc!("SystemError")); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PySystemExit, PyExc_SystemExit, native_doc!("SystemExit"), ffi::PySystemExitObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!(PySystemExit, PyExc_SystemExit, native_doc!("SystemExit")); impl_native_exception!(PyTypeError, PyExc_TypeError, native_doc!("TypeError")); impl_native_exception!( PyUnboundLocalError, PyExc_UnboundLocalError, native_doc!("UnboundLocalError") ); #[cfg(not(any(PyPy, GraalPy)))] impl_native_exception!( PyUnicodeError, PyExc_UnicodeError, native_doc!("UnicodeError"), ffi::PyUnicodeErrorObject ); #[cfg(any(PyPy, GraalPy))] impl_native_exception!( PyUnicodeError, PyExc_UnicodeError, native_doc!("UnicodeError") ); // these four errors need arguments, so they're too annoying to write tests for using macros... impl_native_exception!( PyUnicodeDecodeError, PyExc_UnicodeDecodeError, native_doc!("UnicodeDecodeError", "") ); impl_native_exception!( PyUnicodeEncodeError, PyExc_UnicodeEncodeError, native_doc!("UnicodeEncodeError", "") ); impl_native_exception!( PyUnicodeTranslateError, PyExc_UnicodeTranslateError, native_doc!("UnicodeTranslateError", "") ); #[cfg(Py_3_11)] impl_native_exception!( PyBaseExceptionGroup, PyExc_BaseExceptionGroup, native_doc!("BaseExceptionGroup", "") ); impl_native_exception!(PyValueError, PyExc_ValueError, native_doc!("ValueError")); impl_native_exception!( PyZeroDivisionError, PyExc_ZeroDivisionError, native_doc!("ZeroDivisionError") ); impl_native_exception!( PyBlockingIOError, PyExc_BlockingIOError, native_doc!("BlockingIOError") ); impl_native_exception!( PyBrokenPipeError, PyExc_BrokenPipeError, native_doc!("BrokenPipeError") ); impl_native_exception!( PyChildProcessError, PyExc_ChildProcessError, native_doc!("ChildProcessError") ); impl_native_exception!( PyConnectionError, PyExc_ConnectionError, native_doc!("ConnectionError") ); impl_native_exception!( PyConnectionAbortedError, PyExc_ConnectionAbortedError, native_doc!("ConnectionAbortedError") ); impl_native_exception!( PyConnectionRefusedError, PyExc_ConnectionRefusedError, native_doc!("ConnectionRefusedError") ); impl_native_exception!( PyConnectionResetError, PyExc_ConnectionResetError, native_doc!("ConnectionResetError") ); impl_native_exception!( PyFileExistsError, PyExc_FileExistsError, native_doc!("FileExistsError") ); impl_native_exception!( PyFileNotFoundError, PyExc_FileNotFoundError, native_doc!("FileNotFoundError") ); impl_native_exception!( PyInterruptedError, PyExc_InterruptedError, native_doc!("InterruptedError") ); impl_native_exception!( PyIsADirectoryError, PyExc_IsADirectoryError, native_doc!("IsADirectoryError") ); impl_native_exception!( PyNotADirectoryError, PyExc_NotADirectoryError, native_doc!("NotADirectoryError") ); impl_native_exception!( PyPermissionError, PyExc_PermissionError, native_doc!("PermissionError") ); impl_native_exception!( PyProcessLookupError, PyExc_ProcessLookupError, native_doc!("ProcessLookupError") ); impl_native_exception!( PyTimeoutError, PyExc_TimeoutError, native_doc!("TimeoutError") ); impl_native_exception!( PyEnvironmentError, PyExc_EnvironmentError, native_doc!("EnvironmentError") ); impl_native_exception!(PyIOError, PyExc_IOError, native_doc!("IOError")); #[cfg(windows)] impl_windows_native_exception!( PyWindowsError, PyExc_WindowsError, native_doc!("WindowsError") ); impl PyUnicodeDecodeError { /// Deprecated form of [`PyUnicodeDecodeError::new_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyUnicodeDecodeError::new` will be replaced by `PyUnicodeDecodeError::new_bound` in a future PyO3 version" )] pub fn new<'p>( py: Python<'p>, encoding: &CStr, input: &[u8], range: ops::Range, reason: &CStr, ) -> PyResult<&'p PyUnicodeDecodeError> { Ok(PyUnicodeDecodeError::new_bound(py, encoding, input, range, reason)?.into_gil_ref()) } /// Creates a Python `UnicodeDecodeError`. pub fn new_bound<'p>( py: Python<'p>, encoding: &CStr, input: &[u8], range: ops::Range, reason: &CStr, ) -> PyResult> { use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; unsafe { ffi::PyUnicodeDecodeError_Create( encoding.as_ptr(), input.as_ptr().cast(), input.len() as ffi::Py_ssize_t, range.start as ffi::Py_ssize_t, range.end as ffi::Py_ssize_t, reason.as_ptr(), ) .assume_owned_or_err(py) } .downcast_into() } /// Deprecated form of [`PyUnicodeDecodeError::new_utf8_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyUnicodeDecodeError::new_utf8` will be replaced by `PyUnicodeDecodeError::new_utf8_bound` in a future PyO3 version" )] pub fn new_utf8<'p>( py: Python<'p>, input: &[u8], err: std::str::Utf8Error, ) -> PyResult<&'p PyUnicodeDecodeError> { Ok(PyUnicodeDecodeError::new_utf8_bound(py, input, err)?.into_gil_ref()) } /// Creates a Python `UnicodeDecodeError` from a Rust UTF-8 decoding error. /// /// # Examples /// /// ``` /// #![cfg_attr(invalid_from_utf8_lint, allow(invalid_from_utf8))] /// use pyo3::prelude::*; /// use pyo3::exceptions::PyUnicodeDecodeError; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let invalid_utf8 = b"fo\xd8o"; /// let err = std::str::from_utf8(invalid_utf8).expect_err("should be invalid utf8"); /// let decode_err = PyUnicodeDecodeError::new_utf8_bound(py, invalid_utf8, err)?; /// assert_eq!( /// decode_err.to_string(), /// "'utf-8' codec can't decode byte 0xd8 in position 2: invalid utf-8" /// ); /// Ok(()) /// }) /// # } pub fn new_utf8_bound<'p>( py: Python<'p>, input: &[u8], err: std::str::Utf8Error, ) -> PyResult> { let pos = err.valid_up_to(); PyUnicodeDecodeError::new_bound( py, ffi::c_str!("utf-8"), input, pos..(pos + 1), ffi::c_str!("invalid utf-8"), ) } } impl_native_exception!(PyWarning, PyExc_Warning, native_doc!("Warning")); impl_native_exception!(PyUserWarning, PyExc_UserWarning, native_doc!("UserWarning")); impl_native_exception!( PyDeprecationWarning, PyExc_DeprecationWarning, native_doc!("DeprecationWarning") ); impl_native_exception!( PyPendingDeprecationWarning, PyExc_PendingDeprecationWarning, native_doc!("PendingDeprecationWarning") ); impl_native_exception!( PySyntaxWarning, PyExc_SyntaxWarning, native_doc!("SyntaxWarning") ); impl_native_exception!( PyRuntimeWarning, PyExc_RuntimeWarning, native_doc!("RuntimeWarning") ); impl_native_exception!( PyFutureWarning, PyExc_FutureWarning, native_doc!("FutureWarning") ); impl_native_exception!( PyImportWarning, PyExc_ImportWarning, native_doc!("ImportWarning") ); impl_native_exception!( PyUnicodeWarning, PyExc_UnicodeWarning, native_doc!("UnicodeWarning") ); impl_native_exception!( PyBytesWarning, PyExc_BytesWarning, native_doc!("BytesWarning") ); impl_native_exception!( PyResourceWarning, PyExc_ResourceWarning, native_doc!("ResourceWarning") ); #[cfg(Py_3_10)] impl_native_exception!( PyEncodingWarning, PyExc_EncodingWarning, native_doc!("EncodingWarning") ); #[cfg(test)] macro_rules! test_exception { ($exc_ty:ident $(, |$py:tt| $constructor:expr )?) => { #[allow(non_snake_case)] #[test] fn $exc_ty () { use super::$exc_ty; $crate::Python::with_gil(|py| { use $crate::types::PyAnyMethods; let err: $crate::PyErr = { None $( .or(Some({ let $py = py; $constructor })) )? .unwrap_or($exc_ty::new_err("a test exception")) }; assert!(err.is_instance_of::<$exc_ty>(py)); let value = err.value_bound(py).as_any().downcast::<$exc_ty>().unwrap(); #[cfg(feature = "gil-refs")] { use std::error::Error; let value = value.as_gil_ref(); assert!(value.source().is_none()); err.set_cause(py, Some($crate::exceptions::PyValueError::new_err("a cause"))); assert!(value.source().is_some()); } assert!($crate::PyErr::from(value.clone()).is_instance_of::<$exc_ty>(py)); }) } }; } /// Exceptions defined in Python's [`asyncio`](https://docs.python.org/3/library/asyncio.html) /// module. pub mod asyncio { import_exception!(asyncio, CancelledError); import_exception!(asyncio, InvalidStateError); import_exception!(asyncio, TimeoutError); import_exception!(asyncio, IncompleteReadError); import_exception!(asyncio, LimitOverrunError); import_exception!(asyncio, QueueEmpty); import_exception!(asyncio, QueueFull); #[cfg(test)] mod tests { test_exception!(CancelledError); test_exception!(InvalidStateError); test_exception!(TimeoutError); test_exception!(IncompleteReadError, |_| IncompleteReadError::new_err(( "partial", "expected" ))); test_exception!(LimitOverrunError, |_| LimitOverrunError::new_err(( "message", "consumed" ))); test_exception!(QueueEmpty); test_exception!(QueueFull); } } /// Exceptions defined in Python's [`socket`](https://docs.python.org/3/library/socket.html) /// module. pub mod socket { import_exception!(socket, herror); import_exception!(socket, gaierror); import_exception!(socket, timeout); #[cfg(test)] mod tests { test_exception!(herror); test_exception!(gaierror); test_exception!(timeout); } } #[cfg(test)] mod tests { use super::*; use crate::types::any::PyAnyMethods; use crate::types::{IntoPyDict, PyDict}; use crate::PyErr; #[cfg(feature = "gil-refs")] use crate::PyNativeType; import_exception_bound!(socket, gaierror); import_exception_bound!(email.errors, MessageError); #[test] fn test_check_exception() { Python::with_gil(|py| { let err: PyErr = gaierror::new_err(()); let socket = py .import_bound("socket") .map_err(|e| e.display(py)) .expect("could not import socket"); let d = PyDict::new_bound(py); d.set_item("socket", socket) .map_err(|e| e.display(py)) .expect("could not setitem"); d.set_item("exc", err) .map_err(|e| e.display(py)) .expect("could not setitem"); py.run_bound("assert isinstance(exc, socket.gaierror)", None, Some(&d)) .map_err(|e| e.display(py)) .expect("assertion failed"); }); } #[test] fn test_check_exception_nested() { Python::with_gil(|py| { let err: PyErr = MessageError::new_err(()); let email = py .import_bound("email") .map_err(|e| e.display(py)) .expect("could not import email"); let d = PyDict::new_bound(py); d.set_item("email", email) .map_err(|e| e.display(py)) .expect("could not setitem"); d.set_item("exc", err) .map_err(|e| e.display(py)) .expect("could not setitem"); py.run_bound( "assert isinstance(exc, email.errors.MessageError)", None, Some(&d), ) .map_err(|e| e.display(py)) .expect("assertion failed"); }); } #[test] fn custom_exception() { create_exception!(mymodule, CustomError, PyException); Python::with_gil(|py| { let error_type = py.get_type_bound::(); let ctx = [("CustomError", error_type)].into_py_dict_bound(py); let type_description: String = py .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); py.run_bound( "assert CustomError('oops').args == ('oops',)", None, Some(&ctx), ) .unwrap(); py.run_bound("assert CustomError.__doc__ is None", None, Some(&ctx)) .unwrap(); }); } #[test] fn custom_exception_dotted_module() { create_exception!(mymodule.exceptions, CustomError, PyException); Python::with_gil(|py| { let error_type = py.get_type_bound::(); let ctx = [("CustomError", error_type)].into_py_dict_bound(py); let type_description: String = py .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!( type_description, "" ); }); } #[test] fn custom_exception_doc() { create_exception!(mymodule, CustomError, PyException, "Some docs"); Python::with_gil(|py| { let error_type = py.get_type_bound::(); let ctx = [("CustomError", error_type)].into_py_dict_bound(py); let type_description: String = py .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); py.run_bound( "assert CustomError('oops').args == ('oops',)", None, Some(&ctx), ) .unwrap(); py.run_bound( "assert CustomError.__doc__ == 'Some docs'", None, Some(&ctx), ) .unwrap(); }); } #[test] fn custom_exception_doc_expr() { create_exception!( mymodule, CustomError, PyException, concat!("Some", " more ", stringify!(docs)) ); Python::with_gil(|py| { let error_type = py.get_type_bound::(); let ctx = [("CustomError", error_type)].into_py_dict_bound(py); let type_description: String = py .eval_bound("str(CustomError)", None, Some(&ctx)) .unwrap() .extract() .unwrap(); assert_eq!(type_description, ""); py.run_bound( "assert CustomError('oops').args == ('oops',)", None, Some(&ctx), ) .unwrap(); py.run_bound( "assert CustomError.__doc__ == 'Some more docs'", None, Some(&ctx), ) .unwrap(); }); } #[test] fn native_exception_debug() { Python::with_gil(|py| { let exc = py .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error") .into_value(py) .into_bound(py); assert_eq!( format!("{:?}", exc), exc.repr().unwrap().extract::().unwrap() ); }); } #[test] fn native_exception_display() { Python::with_gil(|py| { let exc = py .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error") .into_value(py) .into_bound(py); assert_eq!( exc.to_string(), exc.str().unwrap().extract::().unwrap() ); }); } #[test] #[cfg(feature = "gil-refs")] fn native_exception_chain() { use std::error::Error; Python::with_gil(|py| { #[allow(deprecated)] let exc = py .run_bound( "raise Exception('banana') from TypeError('peach')", None, None, ) .expect_err("raising should have given us an error") .into_value(py) .into_ref(py); assert_eq!(format!("{:?}", exc), "Exception('banana')"); let source = exc.source().expect("cause should exist"); assert_eq!(format!("{:?}", source), "TypeError('peach')"); let source_source = source.source(); assert!(source_source.is_none(), "source_source should be None"); }); } #[test] fn unicode_decode_error() { let invalid_utf8 = b"fo\xd8o"; #[cfg_attr(invalid_from_utf8_lint, allow(invalid_from_utf8))] let err = std::str::from_utf8(invalid_utf8).expect_err("should be invalid utf8"); Python::with_gil(|py| { let decode_err = PyUnicodeDecodeError::new_utf8_bound(py, invalid_utf8, err).unwrap(); assert_eq!( format!("{:?}", decode_err), "UnicodeDecodeError('utf-8', b'fo\\xd8o', 2, 3, 'invalid utf-8')" ); // Restoring should preserve the same error let e: PyErr = decode_err.into(); e.restore(py); assert_eq!( PyErr::fetch(py).to_string(), "UnicodeDecodeError: \'utf-8\' codec can\'t decode byte 0xd8 in position 2: invalid utf-8" ); }); } #[cfg(Py_3_11)] test_exception!(PyBaseExceptionGroup, |_| PyBaseExceptionGroup::new_err(( "msg", vec![PyValueError::new_err("err")] ))); test_exception!(PyBaseException); test_exception!(PyException); test_exception!(PyStopAsyncIteration); test_exception!(PyStopIteration); test_exception!(PyGeneratorExit); test_exception!(PyArithmeticError); test_exception!(PyLookupError); test_exception!(PyAssertionError); test_exception!(PyAttributeError); test_exception!(PyBufferError); test_exception!(PyEOFError); test_exception!(PyFloatingPointError); test_exception!(PyOSError); test_exception!(PyImportError); test_exception!(PyModuleNotFoundError); test_exception!(PyIndexError); test_exception!(PyKeyError); test_exception!(PyKeyboardInterrupt); test_exception!(PyMemoryError); test_exception!(PyNameError); test_exception!(PyOverflowError); test_exception!(PyRuntimeError); test_exception!(PyRecursionError); test_exception!(PyNotImplementedError); test_exception!(PySyntaxError); test_exception!(PyReferenceError); test_exception!(PySystemError); test_exception!(PySystemExit); test_exception!(PyTypeError); test_exception!(PyUnboundLocalError); test_exception!(PyUnicodeError); test_exception!(PyUnicodeDecodeError, |py| { let invalid_utf8 = b"fo\xd8o"; #[cfg_attr(invalid_from_utf8_lint, allow(invalid_from_utf8))] let err = std::str::from_utf8(invalid_utf8).expect_err("should be invalid utf8"); PyErr::from_value_bound( PyUnicodeDecodeError::new_utf8_bound(py, invalid_utf8, err) .unwrap() .into_any(), ) }); test_exception!(PyUnicodeEncodeError, |py| py .eval_bound("chr(40960).encode('ascii')", None, None) .unwrap_err()); test_exception!(PyUnicodeTranslateError, |_| { PyUnicodeTranslateError::new_err(("\u{3042}", 0, 1, "ouch")) }); test_exception!(PyValueError); test_exception!(PyZeroDivisionError); test_exception!(PyBlockingIOError); test_exception!(PyBrokenPipeError); test_exception!(PyChildProcessError); test_exception!(PyConnectionError); test_exception!(PyConnectionAbortedError); test_exception!(PyConnectionRefusedError); test_exception!(PyConnectionResetError); test_exception!(PyFileExistsError); test_exception!(PyFileNotFoundError); test_exception!(PyInterruptedError); test_exception!(PyIsADirectoryError); test_exception!(PyNotADirectoryError); test_exception!(PyPermissionError); test_exception!(PyProcessLookupError); test_exception!(PyTimeoutError); test_exception!(PyEnvironmentError); test_exception!(PyIOError); #[cfg(windows)] test_exception!(PyWindowsError); test_exception!(PyWarning); test_exception!(PyUserWarning); test_exception!(PyDeprecationWarning); test_exception!(PyPendingDeprecationWarning); test_exception!(PySyntaxWarning); test_exception!(PyRuntimeWarning); test_exception!(PyFutureWarning); test_exception!(PyImportWarning); test_exception!(PyUnicodeWarning); test_exception!(PyBytesWarning); #[cfg(Py_3_10)] test_exception!(PyEncodingWarning); } pyo3/src/conversion.rs0000644000175000017500000006160314661133735015763 0ustar jamespagejamespage//! Defines conversions between Rust and Python types. use crate::err::PyResult; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::pyclass::boolean_struct::False; use crate::types::any::PyAnyMethods; use crate::types::PyTuple; use crate::{ffi, Borrowed, Bound, Py, PyAny, PyClass, PyObject, PyRef, PyRefMut, Python}; #[cfg(feature = "gil-refs")] use { crate::{ err::{self, PyDowncastError}, gil, PyNativeType, }, std::ptr::NonNull, }; /// Returns a borrowed pointer to a Python object. /// /// The returned pointer will be valid for as long as `self` is. It may be null depending on the /// implementation. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyString; /// use pyo3::ffi; /// /// Python::with_gil(|py| { /// let s: Py = "foo".into_py(py); /// let ptr = s.as_ptr(); /// /// let is_really_a_pystring = unsafe { ffi::PyUnicode_CheckExact(ptr) }; /// assert_eq!(is_really_a_pystring, 1); /// }); /// ``` /// /// # Safety /// /// For callers, it is your responsibility to make sure that the underlying Python object is not dropped too /// early. For example, the following code will cause undefined behavior: /// /// ```rust,no_run /// # use pyo3::prelude::*; /// # use pyo3::ffi; /// # /// Python::with_gil(|py| { /// let ptr: *mut ffi::PyObject = 0xabad1dea_u32.into_py(py).as_ptr(); /// /// let isnt_a_pystring = unsafe { /// // `ptr` is dangling, this is UB /// ffi::PyUnicode_CheckExact(ptr) /// }; /// # assert_eq!(isnt_a_pystring, 0); /// }); /// ``` /// /// This happens because the pointer returned by `as_ptr` does not carry any lifetime information /// and the Python object is dropped immediately after the `0xabad1dea_u32.into_py(py).as_ptr()` /// expression is evaluated. To fix the problem, bind Python object to a local variable like earlier /// to keep the Python object alive until the end of its scope. /// /// Implementors must ensure this returns a valid pointer to a Python object, which borrows a reference count from `&self`. pub unsafe trait AsPyPointer { /// Returns the underlying FFI pointer as a borrowed pointer. fn as_ptr(&self) -> *mut ffi::PyObject; } /// Conversion trait that allows various objects to be converted into `PyObject`. pub trait ToPyObject { /// Converts self into a Python object. fn to_object(&self, py: Python<'_>) -> PyObject; } /// Defines a conversion from a Rust type to a Python object. /// /// It functions similarly to std's [`Into`] trait, but requires a [GIL token](Python) /// as an argument. Many functions and traits internal to PyO3 require this trait as a bound, /// so a lack of this trait can manifest itself in different error messages. /// /// # Examples /// ## With `#[pyclass]` /// The easiest way to implement `IntoPy` is by exposing a struct as a native Python object /// by annotating it with [`#[pyclass]`](crate::prelude::pyclass). /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Number { /// #[pyo3(get, set)] /// value: i32, /// } /// ``` /// Python code will see this as an instance of the `Number` class with a `value` attribute. /// /// ## Conversion to a Python object /// /// However, it may not be desirable to expose the existence of `Number` to Python code. /// `IntoPy` allows us to define a conversion to an appropriate Python object. /// ```rust /// use pyo3::prelude::*; /// /// # #[allow(dead_code)] /// struct Number { /// value: i32, /// } /// /// impl IntoPy for Number { /// fn into_py(self, py: Python<'_>) -> PyObject { /// // delegates to i32's IntoPy implementation. /// self.value.into_py(py) /// } /// } /// ``` /// Python code will see this as an `int` object. /// /// ## Dynamic conversion into Python objects. /// It is also possible to return a different Python object depending on some condition. /// This is useful for types like enums that can carry different types. /// /// ```rust /// use pyo3::prelude::*; /// /// enum Value { /// Integer(i32), /// String(String), /// None, /// } /// /// impl IntoPy for Value { /// fn into_py(self, py: Python<'_>) -> PyObject { /// match self { /// Self::Integer(val) => val.into_py(py), /// Self::String(val) => val.into_py(py), /// Self::None => py.None(), /// } /// } /// } /// # fn main() { /// # Python::with_gil(|py| { /// # let v = Value::Integer(73).into_py(py); /// # let v = v.extract::(py).unwrap(); /// # /// # let v = Value::String("foo".into()).into_py(py); /// # let v = v.extract::(py).unwrap(); /// # /// # let v = Value::None.into_py(py); /// # let v = v.extract::>>(py).unwrap(); /// # }); /// # } /// ``` /// Python code will see this as any of the `int`, `string` or `None` objects. #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot be converted to a Python object", note = "`IntoPy` is automatically implemented by the `#[pyclass]` macro", note = "if you do not wish to have a corresponding Python type, implement it manually", note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`" ) )] pub trait IntoPy: Sized { /// Performs the conversion. fn into_py(self, py: Python<'_>) -> T; /// Extracts the type hint information for this type when it appears as a return value. /// /// For example, `Vec` would return `List[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of [`FromPyObject::type_input`]. /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::Any } } /// Extract a type from a Python object. /// /// /// Normal usage is through the `extract` methods on [`Bound`] and [`Py`], which forward to this trait. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyString; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// // Calling `.extract()` on a `Bound` smart pointer /// let obj: Bound<'_, PyString> = PyString::new_bound(py, "blah"); /// let s: String = obj.extract()?; /// # assert_eq!(s, "blah"); /// /// // Calling `.extract(py)` on a `Py` smart pointer /// let obj: Py = obj.unbind(); /// let s: String = obj.extract(py)?; /// # assert_eq!(s, "blah"); /// # Ok(()) /// }) /// # } /// ``` /// // /// FIXME: until `FromPyObject` can pick up a second lifetime, the below commentary is no longer // /// true. Update and restore this documentation at that time. // /// // /// Note: depending on the implementation, the lifetime of the extracted result may // /// depend on the lifetime of the `obj` or the `prepared` variable. // /// // /// For example, when extracting `&str` from a Python byte string, the resulting string slice will // /// point to the existing string data (lifetime: `'py`). // /// On the other hand, when extracting `&str` from a Python Unicode string, the preparation step // /// will convert the string to UTF-8, and the resulting string slice will have lifetime `'prepared`. // /// Since which case applies depends on the runtime type of the Python object, // /// both the `obj` and `prepared` variables must outlive the resulting string slice. /// /// During the migration of PyO3 from the "GIL Refs" API to the `Bound` smart pointer, this trait /// has two methods `extract` and `extract_bound` which are defaulted to call each other. To avoid /// infinite recursion, implementors must implement at least one of these methods. The recommendation /// is to implement `extract_bound` and leave `extract` as the default implementation. pub trait FromPyObject<'py>: Sized { /// Extracts `Self` from the source GIL Ref `obj`. /// /// Implementors are encouraged to implement `extract_bound` and leave this method as the /// default implementation, which will forward calls to `extract_bound`. #[cfg(feature = "gil-refs")] fn extract(ob: &'py PyAny) -> PyResult { Self::extract_bound(&ob.as_borrowed()) } /// Extracts `Self` from the bound smart pointer `obj`. /// /// Implementors are encouraged to implement this method and leave `extract` defaulted, as /// this will be most compatible with PyO3's future API. fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult; /// Extracts the type hint information for this type when it appears as an argument. /// /// For example, `Vec` would return `Sequence[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of [`IntoPy::type_output`]. /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Any } } mod from_py_object_bound_sealed { /// Private seal for the `FromPyObjectBound` trait. /// /// This prevents downstream types from implementing the trait before /// PyO3 is ready to declare the trait as public API. pub trait Sealed {} // This generic implementation is why the seal is separate from // `crate::sealed::Sealed`. impl<'py, T> Sealed for T where T: super::FromPyObject<'py> {} #[cfg(not(feature = "gil-refs"))] impl Sealed for &'_ str {} #[cfg(not(feature = "gil-refs"))] impl Sealed for std::borrow::Cow<'_, str> {} #[cfg(not(feature = "gil-refs"))] impl Sealed for &'_ [u8] {} #[cfg(not(feature = "gil-refs"))] impl Sealed for std::borrow::Cow<'_, [u8]> {} } /// Expected form of [`FromPyObject`] to be used in a future PyO3 release. /// /// The difference between this and `FromPyObject` is that this trait takes an /// additional lifetime `'a`, which is the lifetime of the input `Bound`. /// /// This allows implementations for `&'a str` and `&'a [u8]`, which could not /// be expressed by the existing `FromPyObject` trait once the GIL Refs API was /// removed. /// /// # Usage /// /// Users are prevented from implementing this trait, instead they should implement /// the normal `FromPyObject` trait. This trait has a blanket implementation /// for `T: FromPyObject`. /// /// The only case where this trait may have a use case to be implemented is when the /// lifetime of the extracted value is tied to the lifetime `'a` of the input `Bound` /// instead of the GIL lifetime `py`, as is the case for the `&'a str` implementation. /// /// Please contact the PyO3 maintainers if you believe you have a use case for implementing /// this trait before PyO3 is ready to change the main `FromPyObject` trait to take an /// additional lifetime. /// /// Similarly, users should typically not call these trait methods and should instead /// use this via the `extract` method on `Bound` and `Py`. pub trait FromPyObjectBound<'a, 'py>: Sized + from_py_object_bound_sealed::Sealed { /// Extracts `Self` from the bound smart pointer `obj`. /// /// Users are advised against calling this method directly: instead, use this via /// [`Bound<'_, PyAny>::extract`] or [`Py::extract`]. fn from_py_object_bound(ob: Borrowed<'a, 'py, PyAny>) -> PyResult; /// Extracts the type hint information for this type when it appears as an argument. /// /// For example, `Vec` would return `Sequence[int]`. /// The default implementation returns `Any`, which is correct for any type. /// /// For most types, the return value for this method will be identical to that of [`IntoPy::type_output`]. /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument. #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Any } } impl<'py, T> FromPyObjectBound<'_, 'py> for T where T: FromPyObject<'py>, { fn from_py_object_bound(ob: Borrowed<'_, 'py, PyAny>) -> PyResult { Self::extract_bound(&ob) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { ::type_input() } } /// Identity conversion: allows using existing `PyObject` instances where /// `T: ToPyObject` is expected. impl ToPyObject for &'_ T { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { ::to_object(*self, py) } } impl IntoPy for &'_ PyAny { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) } } } impl IntoPy for &'_ T where T: AsRef, { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_borrowed_ptr(py, self.as_ref().as_ptr()) } } } #[allow(deprecated)] #[cfg(feature = "gil-refs")] impl<'py, T> FromPyObject<'py> for &'py crate::PyCell where T: PyClass, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { obj.clone().into_gil_ref().downcast().map_err(Into::into) } } impl FromPyObject<'_> for T where T: PyClass + Clone, { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let bound = obj.downcast::()?; Ok(bound.try_borrow()?.clone()) } } impl<'py, T> FromPyObject<'py> for PyRef<'py, T> where T: PyClass, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { obj.downcast::()?.try_borrow().map_err(Into::into) } } impl<'py, T> FromPyObject<'py> for PyRefMut<'py, T> where T: PyClass, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { obj.downcast::()?.try_borrow_mut().map_err(Into::into) } } /// Trait implemented by Python object types that allow a checked downcast. /// If `T` implements `PyTryFrom`, we can convert `&PyAny` to `&T`. /// /// This trait is similar to `std::convert::TryFrom` #[cfg(feature = "gil-refs")] #[deprecated(since = "0.21.0")] pub trait PyTryFrom<'v>: Sized + PyNativeType { /// Cast from a concrete Python object type to PyObject. #[deprecated( since = "0.21.0", note = "use `value.downcast::()` instead of `T::try_from(value)`" )] fn try_from>(value: V) -> Result<&'v Self, PyDowncastError<'v>>; /// Cast from a concrete Python object type to PyObject. With exact type check. #[deprecated( since = "0.21.0", note = "use `value.downcast_exact::()` instead of `T::try_from_exact(value)`" )] fn try_from_exact>(value: V) -> Result<&'v Self, PyDowncastError<'v>>; /// Cast a PyAny to a specific type of PyObject. The caller must /// have already verified the reference is for this type. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. #[deprecated( since = "0.21.0", note = "use `value.downcast_unchecked::()` instead of `T::try_from_unchecked(value)`" )] unsafe fn try_from_unchecked>(value: V) -> &'v Self; } /// Trait implemented by Python object types that allow a checked downcast. /// This trait is similar to `std::convert::TryInto` #[cfg(feature = "gil-refs")] #[deprecated(since = "0.21.0")] pub trait PyTryInto: Sized { /// Cast from PyObject to a concrete Python object type. #[deprecated( since = "0.21.0", note = "use `value.downcast()` instead of `value.try_into()`" )] fn try_into(&self) -> Result<&T, PyDowncastError<'_>>; /// Cast from PyObject to a concrete Python object type. With exact type check. #[deprecated( since = "0.21.0", note = "use `value.downcast()` instead of `value.try_into_exact()`" )] fn try_into_exact(&self) -> Result<&T, PyDowncastError<'_>>; } #[cfg(feature = "gil-refs")] #[allow(deprecated)] mod implementations { use super::*; use crate::type_object::PyTypeInfo; // TryFrom implies TryInto impl PyTryInto for PyAny where U: for<'v> PyTryFrom<'v>, { fn try_into(&self) -> Result<&U, PyDowncastError<'_>> { >::try_from(self) } fn try_into_exact(&self) -> Result<&U, PyDowncastError<'_>> { U::try_from_exact(self) } } impl<'v, T> PyTryFrom<'v> for T where T: PyTypeInfo + PyNativeType, { fn try_from>(value: V) -> Result<&'v Self, PyDowncastError<'v>> { value.into().downcast() } fn try_from_exact>(value: V) -> Result<&'v Self, PyDowncastError<'v>> { value.into().downcast_exact() } #[inline] unsafe fn try_from_unchecked>(value: V) -> &'v Self { value.into().downcast_unchecked() } } impl<'v, T> PyTryFrom<'v> for crate::PyCell where T: 'v + PyClass, { fn try_from>(value: V) -> Result<&'v Self, PyDowncastError<'v>> { value.into().downcast() } fn try_from_exact>(value: V) -> Result<&'v Self, PyDowncastError<'v>> { let value = value.into(); unsafe { if T::is_exact_type_of(value) { Ok(Self::try_from_unchecked(value)) } else { Err(PyDowncastError::new(value, T::NAME)) } } } #[inline] unsafe fn try_from_unchecked>(value: V) -> &'v Self { value.into().downcast_unchecked() } } } /// Converts `()` to an empty Python tuple. impl IntoPy> for () { fn into_py(self, py: Python<'_>) -> Py { PyTuple::empty_bound(py).unbind() } } /// Raw level conversion between `*mut ffi::PyObject` and PyO3 types. /// /// # Safety /// /// See safety notes on individual functions. #[cfg(feature = "gil-refs")] #[deprecated(since = "0.21.0")] pub unsafe trait FromPyPointer<'p>: Sized { /// Convert from an arbitrary `PyObject`. /// /// # Safety /// /// Implementations must ensure the object does not get freed during `'p` /// and ensure that `ptr` is of the correct type. /// Note that it must be safe to decrement the reference count of `ptr`. #[deprecated( since = "0.21.0", note = "use `Py::from_owned_ptr_or_opt(py, ptr)` or `Bound::from_owned_ptr_or_opt(py, ptr)` instead" )] unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self>; /// Convert from an arbitrary `PyObject` or panic. /// /// # Safety /// /// Relies on [`from_owned_ptr_or_opt`](#method.from_owned_ptr_or_opt). #[deprecated( since = "0.21.0", note = "use `Py::from_owned_ptr(py, ptr)` or `Bound::from_owned_ptr(py, ptr)` instead" )] unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { #[allow(deprecated)] Self::from_owned_ptr_or_opt(py, ptr).unwrap_or_else(|| err::panic_after_error(py)) } /// Convert from an arbitrary `PyObject` or panic. /// /// # Safety /// /// Relies on [`from_owned_ptr_or_opt`](#method.from_owned_ptr_or_opt). #[deprecated( since = "0.21.0", note = "use `Py::from_owned_ptr(py, ptr)` or `Bound::from_owned_ptr(py, ptr)` instead" )] unsafe fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { #[allow(deprecated)] Self::from_owned_ptr_or_panic(py, ptr) } /// Convert from an arbitrary `PyObject`. /// /// # Safety /// /// Relies on [`from_owned_ptr_or_opt`](#method.from_owned_ptr_or_opt). #[deprecated( since = "0.21.0", note = "use `Py::from_owned_ptr_or_err(py, ptr)` or `Bound::from_owned_ptr_or_err(py, ptr)` instead" )] unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<&'p Self> { #[allow(deprecated)] Self::from_owned_ptr_or_opt(py, ptr).ok_or_else(|| err::PyErr::fetch(py)) } /// Convert from an arbitrary borrowed `PyObject`. /// /// # Safety /// /// Implementations must ensure the object does not get freed during `'p` and avoid type confusion. #[deprecated( since = "0.21.0", note = "use `Py::from_borrowed_ptr_or_opt(py, ptr)` or `Bound::from_borrowed_ptr_or_opt(py, ptr)` instead" )] unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self>; /// Convert from an arbitrary borrowed `PyObject`. /// /// # Safety /// /// Relies on unsafe fn [`from_borrowed_ptr_or_opt`](#method.from_borrowed_ptr_or_opt). #[deprecated( since = "0.21.0", note = "use `Py::from_borrowed_ptr(py, ptr)` or `Bound::from_borrowed_ptr(py, ptr)` instead" )] unsafe fn from_borrowed_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { #[allow(deprecated)] Self::from_borrowed_ptr_or_opt(py, ptr).unwrap_or_else(|| err::panic_after_error(py)) } /// Convert from an arbitrary borrowed `PyObject`. /// /// # Safety /// /// Relies on unsafe fn [`from_borrowed_ptr_or_opt`](#method.from_borrowed_ptr_or_opt). #[deprecated( since = "0.21.0", note = "use `Py::from_borrowed_ptr(py, ptr)` or `Bound::from_borrowed_ptr(py, ptr)` instead" )] unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self { #[allow(deprecated)] Self::from_borrowed_ptr_or_panic(py, ptr) } /// Convert from an arbitrary borrowed `PyObject`. /// /// # Safety /// /// Relies on unsafe fn [`from_borrowed_ptr_or_opt`](#method.from_borrowed_ptr_or_opt). #[deprecated( since = "0.21.0", note = "use `Py::from_borrowed_ptr_or_err(py, ptr)` or `Bound::from_borrowed_ptr_or_err(py, ptr)` instead" )] unsafe fn from_borrowed_ptr_or_err( py: Python<'p>, ptr: *mut ffi::PyObject, ) -> PyResult<&'p Self> { #[allow(deprecated)] Self::from_borrowed_ptr_or_opt(py, ptr).ok_or_else(|| err::PyErr::fetch(py)) } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] unsafe impl<'p, T> FromPyPointer<'p> for T where T: 'p + crate::PyNativeType, { unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self> { gil::register_owned(py, NonNull::new(ptr)?); Some(&*(ptr as *mut Self)) } unsafe fn from_borrowed_ptr_or_opt( _py: Python<'p>, ptr: *mut ffi::PyObject, ) -> Option<&'p Self> { NonNull::new(ptr as *mut Self).map(|p| &*p.as_ptr()) } } /// ```rust,compile_fail /// use pyo3::prelude::*; /// /// #[pyclass] /// struct TestClass { /// num: u32, /// } /// /// let t = TestClass { num: 10 }; /// /// Python::with_gil(|py| { /// let pyvalue = Py::new(py, t).unwrap().to_object(py); /// let t: TestClass = pyvalue.extract(py).unwrap(); /// }) /// ``` mod test_no_clone {} #[cfg(test)] mod tests { #[cfg(feature = "gil-refs")] #[allow(deprecated)] mod deprecated { use super::super::PyTryFrom; use crate::types::{IntoPyDict, PyAny, PyDict, PyList}; use crate::{Python, ToPyObject}; #[test] fn test_try_from() { Python::with_gil(|py| { let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py); let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref(); assert!(>::try_from(list).is_ok()); assert!(>::try_from(dict).is_ok()); assert!(>::try_from(list).is_ok()); assert!(>::try_from(dict).is_ok()); }); } #[test] fn test_try_from_exact() { Python::with_gil(|py| { let list: &PyAny = vec![3, 6, 5, 4, 7].to_object(py).into_ref(py); let dict: &PyAny = vec![("reverse", true)].into_py_dict(py).as_ref(); assert!(PyList::try_from_exact(list).is_ok()); assert!(PyDict::try_from_exact(dict).is_ok()); assert!(PyAny::try_from_exact(list).is_err()); assert!(PyAny::try_from_exact(dict).is_err()); }); } #[test] fn test_try_from_unchecked() { Python::with_gil(|py| { let list = PyList::new(py, [1, 2, 3]); let val = unsafe { ::try_from_unchecked(list.as_ref()) }; assert!(list.is(val)); }); } } } pyo3/src/impl_/0000775000175000017500000000000014661133735014324 5ustar jamespagejamespagepyo3/src/impl_/extract_argument.rs0000644000175000017500000007607614661133735020264 0ustar jamespagejamespageuse crate::{ conversion::FromPyObjectBound, exceptions::PyTypeError, ffi, pyclass::boolean_struct::False, types::{any::PyAnyMethods, dict::PyDictMethods, tuple::PyTupleMethods, PyDict, PyTuple}, Borrowed, Bound, PyAny, PyClass, PyErr, PyRef, PyRefMut, PyResult, PyTypeCheck, Python, }; /// Helper type used to keep implementation more concise. /// /// (Function argument extraction borrows input arguments.) type PyArg<'py> = Borrowed<'py, 'py, PyAny>; /// A trait which is used to help PyO3 macros extract function arguments. /// /// `#[pyclass]` structs need to extract as `PyRef` and `PyRefMut` /// wrappers rather than extracting `&T` and `&mut T` directly. The `Holder` type is used /// to hold these temporary wrappers - the way the macro is constructed, these wrappers /// will be dropped as soon as the pyfunction call ends. /// /// There exists a trivial blanket implementation for `T: FromPyObject` with `Holder = ()`. pub trait PyFunctionArgument<'a, 'py>: Sized + 'a { type Holder: FunctionArgumentHolder; fn extract(obj: &'a Bound<'py, PyAny>, holder: &'a mut Self::Holder) -> PyResult; } impl<'a, 'py, T> PyFunctionArgument<'a, 'py> for T where T: FromPyObjectBound<'a, 'py> + 'a, { type Holder = (); #[inline] fn extract(obj: &'a Bound<'py, PyAny>, _: &'a mut ()) -> PyResult { obj.extract() } } impl<'a, 'py, T: 'py> PyFunctionArgument<'a, 'py> for &'a Bound<'py, T> where T: PyTypeCheck, { type Holder = Option<()>; #[inline] fn extract(obj: &'a Bound<'py, PyAny>, _: &'a mut Option<()>) -> PyResult { obj.downcast().map_err(Into::into) } } impl<'a, 'py, T: 'py> PyFunctionArgument<'a, 'py> for Option<&'a Bound<'py, T>> where T: PyTypeCheck, { type Holder = (); #[inline] fn extract(obj: &'a Bound<'py, PyAny>, _: &'a mut ()) -> PyResult { if obj.is_none() { Ok(None) } else { Ok(Some(obj.downcast()?)) } } } #[cfg(all(Py_LIMITED_API, not(any(feature = "gil-refs", Py_3_10))))] impl<'a> PyFunctionArgument<'a, '_> for &'a str { type Holder = Option>; #[inline] fn extract( obj: &'a Bound<'_, PyAny>, holder: &'a mut Option>, ) -> PyResult { Ok(holder.insert(obj.extract()?)) } } /// Trait for types which can be a function argument holder - they should /// to be able to const-initialize to an empty value. pub trait FunctionArgumentHolder: Sized { const INIT: Self; } impl FunctionArgumentHolder for () { const INIT: Self = (); } impl FunctionArgumentHolder for Option { const INIT: Self = None; } #[inline] pub fn extract_pyclass_ref<'a, 'py: 'a, T: PyClass>( obj: &'a Bound<'py, PyAny>, holder: &'a mut Option>, ) -> PyResult<&'a T> { Ok(&*holder.insert(obj.extract()?)) } #[inline] pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass>( obj: &'a Bound<'py, PyAny>, holder: &'a mut Option>, ) -> PyResult<&'a mut T> { Ok(&mut *holder.insert(obj.extract()?)) } /// The standard implementation of how PyO3 extracts a `#[pyfunction]` or `#[pymethod]` function argument. #[doc(hidden)] pub fn extract_argument<'a, 'py, T>( obj: &'a Bound<'py, PyAny>, holder: &'a mut T::Holder, arg_name: &str, ) -> PyResult where T: PyFunctionArgument<'a, 'py>, { match PyFunctionArgument::extract(obj, holder) { Ok(value) => Ok(value), Err(e) => Err(argument_extraction_error(obj.py(), arg_name, e)), } } /// Alternative to [`extract_argument`] used for `Option` arguments. This is necessary because Option<&T> /// does not implement `PyFunctionArgument` for `T: PyClass`. #[doc(hidden)] pub fn extract_optional_argument<'a, 'py, T>( obj: Option<&'a Bound<'py, PyAny>>, holder: &'a mut T::Holder, arg_name: &str, default: fn() -> Option, ) -> PyResult> where T: PyFunctionArgument<'a, 'py>, { match obj { Some(obj) => { if obj.is_none() { // Explicit `None` will result in None being used as the function argument Ok(None) } else { extract_argument(obj, holder, arg_name).map(Some) } } _ => Ok(default()), } } /// Alternative to [`extract_argument`] used when the argument has a default value provided by an annotation. #[doc(hidden)] pub fn extract_argument_with_default<'a, 'py, T>( obj: Option<&'a Bound<'py, PyAny>>, holder: &'a mut T::Holder, arg_name: &str, default: fn() -> T, ) -> PyResult where T: PyFunctionArgument<'a, 'py>, { match obj { Some(obj) => extract_argument(obj, holder, arg_name), None => Ok(default()), } } /// Alternative to [`extract_argument`] used when the argument has a `#[pyo3(from_py_with)]` annotation. #[doc(hidden)] pub fn from_py_with<'a, 'py, T>( obj: &'a Bound<'py, PyAny>, arg_name: &str, extractor: impl Into>, ) -> PyResult { match extractor.into().call(obj) { Ok(value) => Ok(value), Err(e) => Err(argument_extraction_error(obj.py(), arg_name, e)), } } /// Alternative to [`extract_argument`] used when the argument has a `#[pyo3(from_py_with)]` annotation and also a default value. #[doc(hidden)] pub fn from_py_with_with_default<'a, 'py, T>( obj: Option<&'a Bound<'py, PyAny>>, arg_name: &str, extractor: impl Into>, default: fn() -> T, ) -> PyResult { match obj { Some(obj) => from_py_with(obj, arg_name, extractor), None => Ok(default()), } } /// Adds the argument name to the error message of an error which occurred during argument extraction. /// /// Only modifies TypeError. (Cannot guarantee all exceptions have constructors from /// single string.) #[doc(hidden)] #[cold] pub fn argument_extraction_error(py: Python<'_>, arg_name: &str, error: PyErr) -> PyErr { if error .get_type_bound(py) .is(&py.get_type_bound::()) { let remapped_error = PyTypeError::new_err(format!( "argument '{}': {}", arg_name, error.value_bound(py) )); remapped_error.set_cause(py, error.cause(py)); remapped_error } else { error } } /// Unwraps the Option<&PyAny> produced by the FunctionDescription `extract_arguments_` methods. /// They check if required methods are all provided. /// /// # Safety /// `argument` must not be `None` #[doc(hidden)] #[inline] pub unsafe fn unwrap_required_argument<'a, 'py>( argument: Option<&'a Bound<'py, PyAny>>, ) -> &'a Bound<'py, PyAny> { match argument { Some(value) => value, #[cfg(debug_assertions)] None => unreachable!("required method argument was not extracted"), #[cfg(not(debug_assertions))] None => std::hint::unreachable_unchecked(), } } pub struct KeywordOnlyParameterDescription { pub name: &'static str, pub required: bool, } /// Function argument specification for a `#[pyfunction]` or `#[pymethod]`. pub struct FunctionDescription { pub cls_name: Option<&'static str>, pub func_name: &'static str, pub positional_parameter_names: &'static [&'static str], pub positional_only_parameters: usize, pub required_positional_parameters: usize, pub keyword_only_parameters: &'static [KeywordOnlyParameterDescription], } impl FunctionDescription { fn full_name(&self) -> String { if let Some(cls_name) = self.cls_name { format!("{}.{}()", cls_name, self.func_name) } else { format!("{}()", self.func_name) } } /// Equivalent of `extract_arguments_tuple_dict` which uses the Python C-API "fastcall" convention. /// /// # Safety /// - `args` must be a pointer to a C-style array of valid `ffi::PyObject` pointers, or NULL. /// - `kwnames` must be a pointer to a PyTuple, or NULL. /// - `nargs + kwnames.len()` is the total length of the `args` array. #[cfg(not(Py_LIMITED_API))] pub unsafe fn extract_arguments_fastcall<'py, V, K>( &self, py: Python<'py>, args: *const *mut ffi::PyObject, nargs: ffi::Py_ssize_t, kwnames: *mut ffi::PyObject, output: &mut [Option>], ) -> PyResult<(V::Varargs, K::Varkeywords)> where V: VarargsHandler<'py>, K: VarkeywordsHandler<'py>, { let num_positional_parameters = self.positional_parameter_names.len(); debug_assert!(nargs >= 0); debug_assert!(self.positional_only_parameters <= num_positional_parameters); debug_assert!(self.required_positional_parameters <= num_positional_parameters); debug_assert_eq!( output.len(), num_positional_parameters + self.keyword_only_parameters.len() ); // Handle positional arguments // Safety: // - Option has the same memory layout as `*mut ffi::PyObject` // - we both have the GIL and can borrow these input references for the `'py` lifetime. let args: *const Option> = args.cast(); let positional_args_provided = nargs as usize; let remaining_positional_args = if args.is_null() { debug_assert_eq!(positional_args_provided, 0); &[] } else { // Can consume at most the number of positional parameters in the function definition, // the rest are varargs. let positional_args_to_consume = num_positional_parameters.min(positional_args_provided); let (positional_parameters, remaining) = std::slice::from_raw_parts(args, positional_args_provided) .split_at(positional_args_to_consume); output[..positional_args_to_consume].copy_from_slice(positional_parameters); remaining }; let varargs = V::handle_varargs_fastcall(py, remaining_positional_args, self)?; // Handle keyword arguments let mut varkeywords = K::Varkeywords::default(); // Safety: kwnames is known to be a pointer to a tuple, or null // - we both have the GIL and can borrow this input reference for the `'py` lifetime. let kwnames: Option> = Borrowed::from_ptr_or_opt(py, kwnames).map(|kwnames| kwnames.downcast_unchecked()); if let Some(kwnames) = kwnames { let kwargs = ::std::slice::from_raw_parts( // Safety: PyArg has the same memory layout as `*mut ffi::PyObject` args.offset(nargs).cast::>(), kwnames.len(), ); self.handle_kwargs::( kwnames.iter_borrowed().zip(kwargs.iter().copied()), &mut varkeywords, num_positional_parameters, output, )? } // Once all inputs have been processed, check that all required arguments have been provided. self.ensure_no_missing_required_positional_arguments(output, positional_args_provided)?; self.ensure_no_missing_required_keyword_arguments(output)?; Ok((varargs, varkeywords)) } /// Extracts the `args` and `kwargs` provided into `output`, according to this function /// definition. /// /// `output` must have the same length as this function has positional and keyword-only /// parameters (as per the `positional_parameter_names` and `keyword_only_parameters` /// respectively). /// /// Unexpected, duplicate or invalid arguments will cause this function to return `TypeError`. /// /// # Safety /// - `args` must be a pointer to a PyTuple. /// - `kwargs` must be a pointer to a PyDict, or NULL. pub unsafe fn extract_arguments_tuple_dict<'py, V, K>( &self, py: Python<'py>, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, output: &mut [Option>], ) -> PyResult<(V::Varargs, K::Varkeywords)> where V: VarargsHandler<'py>, K: VarkeywordsHandler<'py>, { // Safety: // - `args` is known to be a tuple // - `kwargs` is known to be a dict or null // - we both have the GIL and can borrow these input references for the `'py` lifetime. let args: Borrowed<'py, 'py, PyTuple> = Borrowed::from_ptr(py, args).downcast_unchecked::(); let kwargs: Option> = Borrowed::from_ptr_or_opt(py, kwargs).map(|kwargs| kwargs.downcast_unchecked()); let num_positional_parameters = self.positional_parameter_names.len(); debug_assert!(self.positional_only_parameters <= num_positional_parameters); debug_assert!(self.required_positional_parameters <= num_positional_parameters); debug_assert_eq!( output.len(), num_positional_parameters + self.keyword_only_parameters.len() ); // Copy positional arguments into output for (i, arg) in args .iter_borrowed() .take(num_positional_parameters) .enumerate() { output[i] = Some(arg); } // If any arguments remain, push them to varargs (if possible) or error let varargs = V::handle_varargs_tuple(&args, self)?; // Handle keyword arguments let mut varkeywords = K::Varkeywords::default(); if let Some(kwargs) = kwargs { self.handle_kwargs::( kwargs.iter_borrowed(), &mut varkeywords, num_positional_parameters, output, )? } // Once all inputs have been processed, check that all required arguments have been provided. self.ensure_no_missing_required_positional_arguments(output, args.len())?; self.ensure_no_missing_required_keyword_arguments(output)?; Ok((varargs, varkeywords)) } #[inline] fn handle_kwargs<'py, K, I>( &self, kwargs: I, varkeywords: &mut K::Varkeywords, num_positional_parameters: usize, output: &mut [Option>], ) -> PyResult<()> where K: VarkeywordsHandler<'py>, I: IntoIterator, PyArg<'py>)>, { debug_assert_eq!( num_positional_parameters, self.positional_parameter_names.len() ); debug_assert_eq!( output.len(), num_positional_parameters + self.keyword_only_parameters.len() ); let mut positional_only_keyword_arguments = Vec::new(); for (kwarg_name_py, value) in kwargs { // Safety: All keyword arguments should be UTF-8 strings, but if it's not, `.to_str()` // will return an error anyway. #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] let kwarg_name = unsafe { kwarg_name_py.downcast_unchecked::() }.to_str(); #[cfg(all(not(Py_3_10), Py_LIMITED_API))] let kwarg_name = kwarg_name_py.extract::(); if let Ok(kwarg_name_owned) = kwarg_name { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] let kwarg_name = kwarg_name_owned; #[cfg(all(not(Py_3_10), Py_LIMITED_API))] let kwarg_name: &str = &kwarg_name_owned; // Try to place parameter in keyword only parameters if let Some(i) = self.find_keyword_parameter_in_keyword_only(kwarg_name) { if output[i + num_positional_parameters] .replace(value) .is_some() { return Err(self.multiple_values_for_argument(kwarg_name)); } continue; } // Repeat for positional parameters if let Some(i) = self.find_keyword_parameter_in_positional(kwarg_name) { if i < self.positional_only_parameters { // If accepting **kwargs, then it's allowed for the name of the // kwarg to conflict with a postional-only argument - the value // will go into **kwargs anyway. if K::handle_varkeyword(varkeywords, kwarg_name_py, value, self).is_err() { positional_only_keyword_arguments.push(kwarg_name_owned); } } else if output[i].replace(value).is_some() { return Err(self.multiple_values_for_argument(kwarg_name)); } continue; } }; K::handle_varkeyword(varkeywords, kwarg_name_py, value, self)? } if !positional_only_keyword_arguments.is_empty() { #[cfg(all(not(Py_3_10), Py_LIMITED_API))] let positional_only_keyword_arguments: Vec<_> = positional_only_keyword_arguments .iter() .map(std::ops::Deref::deref) .collect(); return Err(self.positional_only_keyword_arguments(&positional_only_keyword_arguments)); } Ok(()) } #[inline] fn find_keyword_parameter_in_positional(&self, kwarg_name: &str) -> Option { self.positional_parameter_names .iter() .position(|¶m_name| param_name == kwarg_name) } #[inline] fn find_keyword_parameter_in_keyword_only(&self, kwarg_name: &str) -> Option { // Compare the keyword name against each parameter in turn. This is exactly the same method // which CPython uses to map keyword names. Although it's O(num_parameters), the number of // parameters is expected to be small so it's not worth constructing a mapping. self.keyword_only_parameters .iter() .position(|param_desc| param_desc.name == kwarg_name) } #[inline] fn ensure_no_missing_required_positional_arguments( &self, output: &[Option>], positional_args_provided: usize, ) -> PyResult<()> { if positional_args_provided < self.required_positional_parameters { for out in &output[positional_args_provided..self.required_positional_parameters] { if out.is_none() { return Err(self.missing_required_positional_arguments(output)); } } } Ok(()) } #[inline] fn ensure_no_missing_required_keyword_arguments( &self, output: &[Option>], ) -> PyResult<()> { let keyword_output = &output[self.positional_parameter_names.len()..]; for (param, out) in self.keyword_only_parameters.iter().zip(keyword_output) { if param.required && out.is_none() { return Err(self.missing_required_keyword_arguments(keyword_output)); } } Ok(()) } #[cold] fn too_many_positional_arguments(&self, args_provided: usize) -> PyErr { let was = if args_provided == 1 { "was" } else { "were" }; let msg = if self.required_positional_parameters != self.positional_parameter_names.len() { format!( "{} takes from {} to {} positional arguments but {} {} given", self.full_name(), self.required_positional_parameters, self.positional_parameter_names.len(), args_provided, was ) } else { format!( "{} takes {} positional arguments but {} {} given", self.full_name(), self.positional_parameter_names.len(), args_provided, was ) }; PyTypeError::new_err(msg) } #[cold] fn multiple_values_for_argument(&self, argument: &str) -> PyErr { PyTypeError::new_err(format!( "{} got multiple values for argument '{}'", self.full_name(), argument )) } #[cold] fn unexpected_keyword_argument(&self, argument: PyArg<'_>) -> PyErr { PyTypeError::new_err(format!( "{} got an unexpected keyword argument '{}'", self.full_name(), argument.as_any() )) } #[cold] fn positional_only_keyword_arguments(&self, parameter_names: &[&str]) -> PyErr { let mut msg = format!( "{} got some positional-only arguments passed as keyword arguments: ", self.full_name() ); push_parameter_list(&mut msg, parameter_names); PyTypeError::new_err(msg) } #[cold] fn missing_required_arguments(&self, argument_type: &str, parameter_names: &[&str]) -> PyErr { let arguments = if parameter_names.len() == 1 { "argument" } else { "arguments" }; let mut msg = format!( "{} missing {} required {} {}: ", self.full_name(), parameter_names.len(), argument_type, arguments, ); push_parameter_list(&mut msg, parameter_names); PyTypeError::new_err(msg) } #[cold] fn missing_required_keyword_arguments(&self, keyword_outputs: &[Option>]) -> PyErr { debug_assert_eq!(self.keyword_only_parameters.len(), keyword_outputs.len()); let missing_keyword_only_arguments: Vec<_> = self .keyword_only_parameters .iter() .zip(keyword_outputs) .filter_map(|(keyword_desc, out)| { if keyword_desc.required && out.is_none() { Some(keyword_desc.name) } else { None } }) .collect(); debug_assert!(!missing_keyword_only_arguments.is_empty()); self.missing_required_arguments("keyword", &missing_keyword_only_arguments) } #[cold] fn missing_required_positional_arguments(&self, output: &[Option>]) -> PyErr { let missing_positional_arguments: Vec<_> = self .positional_parameter_names .iter() .take(self.required_positional_parameters) .zip(output) .filter_map(|(param, out)| if out.is_none() { Some(*param) } else { None }) .collect(); debug_assert!(!missing_positional_arguments.is_empty()); self.missing_required_arguments("positional", &missing_positional_arguments) } } /// A trait used to control whether to accept varargs in FunctionDescription::extract_argument_(method) functions. pub trait VarargsHandler<'py> { type Varargs; /// Called by `FunctionDescription::extract_arguments_fastcall` with any additional arguments. fn handle_varargs_fastcall( py: Python<'py>, varargs: &[Option>], function_description: &FunctionDescription, ) -> PyResult; /// Called by `FunctionDescription::extract_arguments_tuple_dict` with the original tuple. /// /// Additional arguments are those in the tuple slice starting from `function_description.positional_parameter_names.len()`. fn handle_varargs_tuple( args: &Bound<'py, PyTuple>, function_description: &FunctionDescription, ) -> PyResult; } /// Marker struct which indicates varargs are not allowed. pub struct NoVarargs; impl<'py> VarargsHandler<'py> for NoVarargs { type Varargs = (); #[inline] fn handle_varargs_fastcall( _py: Python<'py>, varargs: &[Option>], function_description: &FunctionDescription, ) -> PyResult { let extra_arguments = varargs.len(); if extra_arguments > 0 { return Err(function_description.too_many_positional_arguments( function_description.positional_parameter_names.len() + extra_arguments, )); } Ok(()) } #[inline] fn handle_varargs_tuple( args: &Bound<'py, PyTuple>, function_description: &FunctionDescription, ) -> PyResult { let positional_parameter_count = function_description.positional_parameter_names.len(); let provided_args_count = args.len(); if provided_args_count <= positional_parameter_count { Ok(()) } else { Err(function_description.too_many_positional_arguments(provided_args_count)) } } } /// Marker struct which indicates varargs should be collected into a `PyTuple`. pub struct TupleVarargs; impl<'py> VarargsHandler<'py> for TupleVarargs { type Varargs = Bound<'py, PyTuple>; #[inline] fn handle_varargs_fastcall( py: Python<'py>, varargs: &[Option>], _function_description: &FunctionDescription, ) -> PyResult { Ok(PyTuple::new_bound(py, varargs)) } #[inline] fn handle_varargs_tuple( args: &Bound<'py, PyTuple>, function_description: &FunctionDescription, ) -> PyResult { let positional_parameters = function_description.positional_parameter_names.len(); Ok(args.get_slice(positional_parameters, args.len())) } } /// A trait used to control whether to accept varkeywords in FunctionDescription::extract_argument_(method) functions. pub trait VarkeywordsHandler<'py> { type Varkeywords: Default; fn handle_varkeyword( varkeywords: &mut Self::Varkeywords, name: PyArg<'py>, value: PyArg<'py>, function_description: &FunctionDescription, ) -> PyResult<()>; } /// Marker struct which indicates unknown keywords are not permitted. pub struct NoVarkeywords; impl<'py> VarkeywordsHandler<'py> for NoVarkeywords { type Varkeywords = (); #[inline] fn handle_varkeyword( _varkeywords: &mut Self::Varkeywords, name: PyArg<'py>, _value: PyArg<'py>, function_description: &FunctionDescription, ) -> PyResult<()> { Err(function_description.unexpected_keyword_argument(name)) } } /// Marker struct which indicates unknown keywords should be collected into a `PyDict`. pub struct DictVarkeywords; impl<'py> VarkeywordsHandler<'py> for DictVarkeywords { type Varkeywords = Option>; #[inline] fn handle_varkeyword( varkeywords: &mut Self::Varkeywords, name: PyArg<'py>, value: PyArg<'py>, _function_description: &FunctionDescription, ) -> PyResult<()> { varkeywords .get_or_insert_with(|| PyDict::new_bound(name.py())) .set_item(name, value) } } fn push_parameter_list(msg: &mut String, parameter_names: &[&str]) { let len = parameter_names.len(); for (i, parameter) in parameter_names.iter().enumerate() { if i != 0 { if len > 2 { msg.push(','); } if i == len - 1 { msg.push_str(" and ") } else { msg.push(' ') } } msg.push('\''); msg.push_str(parameter); msg.push('\''); } } #[cfg(test)] mod tests { use crate::types::{IntoPyDict, PyTuple}; use crate::Python; use super::{push_parameter_list, FunctionDescription, NoVarargs, NoVarkeywords}; #[test] fn unexpected_keyword_argument() { let function_description = FunctionDescription { cls_name: None, func_name: "example", positional_parameter_names: &[], positional_only_parameters: 0, required_positional_parameters: 0, keyword_only_parameters: &[], }; Python::with_gil(|py| { let args = PyTuple::empty_bound(py); let kwargs = [("foo", 0u8)].into_py_dict_bound(py); let err = unsafe { function_description .extract_arguments_tuple_dict::( py, args.as_ptr(), kwargs.as_ptr(), &mut [], ) .unwrap_err() }; assert_eq!( err.to_string(), "TypeError: example() got an unexpected keyword argument 'foo'" ); }) } #[test] fn keyword_not_string() { let function_description = FunctionDescription { cls_name: None, func_name: "example", positional_parameter_names: &[], positional_only_parameters: 0, required_positional_parameters: 0, keyword_only_parameters: &[], }; Python::with_gil(|py| { let args = PyTuple::empty_bound(py); let kwargs = [(1u8, 1u8)].into_py_dict_bound(py); let err = unsafe { function_description .extract_arguments_tuple_dict::( py, args.as_ptr(), kwargs.as_ptr(), &mut [], ) .unwrap_err() }; assert_eq!( err.to_string(), "TypeError: example() got an unexpected keyword argument '1'" ); }) } #[test] fn missing_required_arguments() { let function_description = FunctionDescription { cls_name: None, func_name: "example", positional_parameter_names: &["foo", "bar"], positional_only_parameters: 0, required_positional_parameters: 2, keyword_only_parameters: &[], }; Python::with_gil(|py| { let args = PyTuple::empty_bound(py); let mut output = [None, None]; let err = unsafe { function_description.extract_arguments_tuple_dict::( py, args.as_ptr(), std::ptr::null_mut(), &mut output, ) } .unwrap_err(); assert_eq!( err.to_string(), "TypeError: example() missing 2 required positional arguments: 'foo' and 'bar'" ); }) } #[test] fn push_parameter_list_empty() { let mut s = String::new(); push_parameter_list(&mut s, &[]); assert_eq!(&s, ""); } #[test] fn push_parameter_list_one() { let mut s = String::new(); push_parameter_list(&mut s, &["a"]); assert_eq!(&s, "'a'"); } #[test] fn push_parameter_list_two() { let mut s = String::new(); push_parameter_list(&mut s, &["a", "b"]); assert_eq!(&s, "'a' and 'b'"); } #[test] fn push_parameter_list_three() { let mut s = String::new(); push_parameter_list(&mut s, &["a", "b", "c"]); assert_eq!(&s, "'a', 'b', and 'c'"); } #[test] fn push_parameter_list_four() { let mut s = String::new(); push_parameter_list(&mut s, &["a", "b", "c", "d"]); assert_eq!(&s, "'a', 'b', 'c', and 'd'"); } } pyo3/src/impl_/not_send.rs0000644000175000017500000000052614661133735016504 0ustar jamespagejamespageuse std::marker::PhantomData; use crate::Python; /// A marker type that makes the type !Send. /// Workaround for lack of !Send on stable (). pub(crate) struct NotSend(PhantomData<*mut Python<'static>>); #[cfg(feature = "gil-refs")] pub(crate) const NOT_SEND: NotSend = NotSend(PhantomData); pyo3/src/impl_/pymethods.rs0000644000175000017500000003622314661133735016712 0ustar jamespagejamespageuse crate::callback::IntoPyCallbackOutput; use crate::exceptions::PyStopAsyncIteration; use crate::gil::LockGIL; use crate::impl_::panic::PanicTrap; use crate::pycell::{PyBorrowError, PyBorrowMutError}; use crate::pyclass::boolean_struct::False; use crate::types::any::PyAnyMethods; #[cfg(feature = "gil-refs")] use crate::types::{PyModule, PyType}; use crate::{ ffi, Borrowed, Bound, DowncastError, Py, PyAny, PyClass, PyClassInitializer, PyErr, PyObject, PyRef, PyRefMut, PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python, }; use std::ffi::CStr; use std::fmt; use std::os::raw::{c_int, c_void}; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::ptr::null_mut; /// Python 3.8 and up - __ipow__ has modulo argument correctly populated. #[cfg(Py_3_8)] #[repr(transparent)] pub struct IPowModulo(*mut ffi::PyObject); /// Python 3.7 and older - __ipow__ does not have modulo argument correctly populated. #[cfg(not(Py_3_8))] #[repr(transparent)] pub struct IPowModulo(#[allow(dead_code)] std::mem::MaybeUninit<*mut ffi::PyObject>); /// Helper to use as pymethod ffi definition #[allow(non_camel_case_types)] pub type ipowfunc = unsafe extern "C" fn( arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, arg3: IPowModulo, ) -> *mut ffi::PyObject; impl IPowModulo { #[cfg(Py_3_8)] #[inline] pub fn as_ptr(self) -> *mut ffi::PyObject { self.0 } #[cfg(not(Py_3_8))] #[inline] pub fn as_ptr(self) -> *mut ffi::PyObject { // Safety: returning a borrowed pointer to Python `None` singleton unsafe { ffi::Py_None() } } } /// `PyMethodDefType` represents different types of Python callable objects. /// It is used by the `#[pymethods]` attribute. #[cfg_attr(test, derive(Clone))] pub enum PyMethodDefType { /// Represents class method Class(PyMethodDef), /// Represents static method Static(PyMethodDef), /// Represents normal method Method(PyMethodDef), /// Represents class attribute, used by `#[attribute]` ClassAttribute(PyClassAttributeDef), /// Represents getter descriptor, used by `#[getter]` Getter(PyGetterDef), /// Represents setter descriptor, used by `#[setter]` Setter(PySetterDef), /// Represents a struct member StructMember(ffi::PyMemberDef), } #[derive(Copy, Clone, Debug)] pub enum PyMethodType { PyCFunction(ffi::PyCFunction), PyCFunctionWithKeywords(ffi::PyCFunctionWithKeywords), #[cfg(not(Py_LIMITED_API))] PyCFunctionFastWithKeywords(ffi::_PyCFunctionFastWithKeywords), } pub type PyClassAttributeFactory = for<'p> fn(Python<'p>) -> PyResult; // TODO: it would be nice to use CStr in these types, but then the constructors can't be const fn // until `CStr::from_bytes_with_nul_unchecked` is const fn. #[derive(Clone, Debug)] pub struct PyMethodDef { pub(crate) ml_name: &'static CStr, pub(crate) ml_meth: PyMethodType, pub(crate) ml_flags: c_int, pub(crate) ml_doc: &'static CStr, } #[derive(Copy, Clone)] pub struct PyClassAttributeDef { pub(crate) name: &'static CStr, pub(crate) meth: PyClassAttributeFactory, } #[derive(Clone)] pub struct PyGetterDef { pub(crate) name: &'static CStr, pub(crate) meth: Getter, pub(crate) doc: &'static CStr, } #[derive(Clone)] pub struct PySetterDef { pub(crate) name: &'static CStr, pub(crate) meth: Setter, pub(crate) doc: &'static CStr, } unsafe impl Sync for PyMethodDef {} unsafe impl Sync for PyGetterDef {} unsafe impl Sync for PySetterDef {} impl PyMethodDef { /// Define a function with no `*args` and `**kwargs`. pub const fn noargs( ml_name: &'static CStr, cfunction: ffi::PyCFunction, ml_doc: &'static CStr, ) -> Self { Self { ml_name, ml_meth: PyMethodType::PyCFunction(cfunction), ml_flags: ffi::METH_NOARGS, ml_doc, } } /// Define a function that can take `*args` and `**kwargs`. pub const fn cfunction_with_keywords( ml_name: &'static CStr, cfunction: ffi::PyCFunctionWithKeywords, ml_doc: &'static CStr, ) -> Self { Self { ml_name, ml_meth: PyMethodType::PyCFunctionWithKeywords(cfunction), ml_flags: ffi::METH_VARARGS | ffi::METH_KEYWORDS, ml_doc, } } /// Define a function that can take `*args` and `**kwargs`. #[cfg(not(Py_LIMITED_API))] pub const fn fastcall_cfunction_with_keywords( ml_name: &'static CStr, cfunction: ffi::_PyCFunctionFastWithKeywords, ml_doc: &'static CStr, ) -> Self { Self { ml_name, ml_meth: PyMethodType::PyCFunctionFastWithKeywords(cfunction), ml_flags: ffi::METH_FASTCALL | ffi::METH_KEYWORDS, ml_doc, } } pub const fn flags(mut self, flags: c_int) -> Self { self.ml_flags |= flags; self } /// Convert `PyMethodDef` to Python method definition struct `ffi::PyMethodDef` pub(crate) fn as_method_def(&self) -> ffi::PyMethodDef { let meth = match self.ml_meth { PyMethodType::PyCFunction(meth) => ffi::PyMethodDefPointer { PyCFunction: meth }, PyMethodType::PyCFunctionWithKeywords(meth) => ffi::PyMethodDefPointer { PyCFunctionWithKeywords: meth, }, #[cfg(not(Py_LIMITED_API))] PyMethodType::PyCFunctionFastWithKeywords(meth) => ffi::PyMethodDefPointer { _PyCFunctionFastWithKeywords: meth, }, }; ffi::PyMethodDef { ml_name: self.ml_name.as_ptr(), ml_meth: meth, ml_flags: self.ml_flags, ml_doc: self.ml_doc.as_ptr(), } } } impl PyClassAttributeDef { /// Define a class attribute. pub const fn new(name: &'static CStr, meth: PyClassAttributeFactory) -> Self { Self { name, meth } } } // Manual implementation because `Python<'_>` does not implement `Debug` and // trait bounds on `fn` compiler-generated derive impls are too restrictive. impl fmt::Debug for PyClassAttributeDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PyClassAttributeDef") .field("name", &self.name) .finish() } } /// Class getter / setters pub(crate) type Getter = for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> PyResult<*mut ffi::PyObject>; pub(crate) type Setter = for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject, *mut ffi::PyObject) -> PyResult; impl PyGetterDef { /// Define a getter. pub const fn new(name: &'static CStr, getter: Getter, doc: &'static CStr) -> Self { Self { name, meth: getter, doc, } } } impl PySetterDef { /// Define a setter. pub const fn new(name: &'static CStr, setter: Setter, doc: &'static CStr) -> Self { Self { name, meth: setter, doc, } } } /// Calls an implementation of __traverse__ for tp_traverse #[doc(hidden)] pub unsafe fn _call_traverse( slf: *mut ffi::PyObject, impl_: fn(&T, PyVisit<'_>) -> Result<(), PyTraverseError>, visit: ffi::visitproc, arg: *mut c_void, ) -> c_int where T: PyClass, { // It is important the implementation of `__traverse__` cannot safely access the GIL, // c.f. https://github.com/PyO3/pyo3/issues/3165, and hence we do not expose our GIL // token to the user code and lock safe methods for acquiring the GIL. // (This includes enforcing the `&self` method receiver as e.g. `PyRef` could // reconstruct a GIL token via `PyRef::py`.) // Since we do not create a `GILPool` at all, it is important that our usage of the GIL // token does not produce any owned objects thereby calling into `register_owned`. let trap = PanicTrap::new("uncaught panic inside __traverse__ handler"); let py = Python::assume_gil_acquired(); let slf = Borrowed::from_ptr_unchecked(py, slf).downcast_unchecked::(); let borrow = PyRef::try_borrow_threadsafe(&slf); let visit = PyVisit::from_raw(visit, arg, py); let retval = if let Ok(borrow) = borrow { let _lock = LockGIL::during_traverse(); match catch_unwind(AssertUnwindSafe(move || impl_(&*borrow, visit))) { Ok(res) => match res { Ok(()) => 0, Err(PyTraverseError(value)) => value, }, Err(_err) => -1, } } else { 0 }; trap.disarm(); retval } // Autoref-based specialization for handling `__next__` returning `Option` pub struct IterBaseTag; impl IterBaseTag { #[inline] pub fn convert(self, py: Python<'_>, value: Value) -> PyResult where Value: IntoPyCallbackOutput, { value.convert(py) } } pub trait IterBaseKind { #[inline] fn iter_tag(&self) -> IterBaseTag { IterBaseTag } } impl IterBaseKind for &Value {} pub struct IterOptionTag; impl IterOptionTag { #[inline] pub fn convert( self, py: Python<'_>, value: Option, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<*mut ffi::PyObject>, { match value { Some(value) => value.convert(py), None => Ok(null_mut()), } } } pub trait IterOptionKind { #[inline] fn iter_tag(&self) -> IterOptionTag { IterOptionTag } } impl IterOptionKind for Option {} pub struct IterResultOptionTag; impl IterResultOptionTag { #[inline] pub fn convert( self, py: Python<'_>, value: Result, Error>, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<*mut ffi::PyObject>, Error: Into, { match value { Ok(Some(value)) => value.convert(py), Ok(None) => Ok(null_mut()), Err(err) => Err(err.into()), } } } pub trait IterResultOptionKind { #[inline] fn iter_tag(&self) -> IterResultOptionTag { IterResultOptionTag } } impl IterResultOptionKind for Result, Error> {} // Autoref-based specialization for handling `__anext__` returning `Option` pub struct AsyncIterBaseTag; impl AsyncIterBaseTag { #[inline] pub fn convert(self, py: Python<'_>, value: Value) -> PyResult where Value: IntoPyCallbackOutput, { value.convert(py) } } pub trait AsyncIterBaseKind { #[inline] fn async_iter_tag(&self) -> AsyncIterBaseTag { AsyncIterBaseTag } } impl AsyncIterBaseKind for &Value {} pub struct AsyncIterOptionTag; impl AsyncIterOptionTag { #[inline] pub fn convert( self, py: Python<'_>, value: Option, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<*mut ffi::PyObject>, { match value { Some(value) => value.convert(py), None => Err(PyStopAsyncIteration::new_err(())), } } } pub trait AsyncIterOptionKind { #[inline] fn async_iter_tag(&self) -> AsyncIterOptionTag { AsyncIterOptionTag } } impl AsyncIterOptionKind for Option {} pub struct AsyncIterResultOptionTag; impl AsyncIterResultOptionTag { #[inline] pub fn convert( self, py: Python<'_>, value: Result, Error>, ) -> PyResult<*mut ffi::PyObject> where Value: IntoPyCallbackOutput<*mut ffi::PyObject>, Error: Into, { match value { Ok(Some(value)) => value.convert(py), Ok(None) => Err(PyStopAsyncIteration::new_err(())), Err(err) => Err(err.into()), } } } pub trait AsyncIterResultOptionKind { #[inline] fn async_iter_tag(&self) -> AsyncIterResultOptionTag { AsyncIterResultOptionTag } } impl AsyncIterResultOptionKind for Result, Error> {} /// Used in `#[classmethod]` to pass the class object to the method /// and also in `#[pyfunction(pass_module)]`. /// /// This is a wrapper to avoid implementing `From` for GIL Refs. /// /// Once the GIL Ref API is fully removed, it should be possible to simplify /// this to just `&'a Bound<'py, T>` and `From` implementations. pub struct BoundRef<'a, 'py, T>(pub &'a Bound<'py, T>); impl<'a, 'py> BoundRef<'a, 'py, PyAny> { pub unsafe fn ref_from_ptr(py: Python<'py>, ptr: &'a *mut ffi::PyObject) -> Self { BoundRef(Bound::ref_from_ptr(py, ptr)) } pub unsafe fn ref_from_ptr_or_opt( py: Python<'py>, ptr: &'a *mut ffi::PyObject, ) -> Option { Bound::ref_from_ptr_or_opt(py, ptr).as_ref().map(BoundRef) } pub fn downcast(self) -> Result, DowncastError<'a, 'py>> { self.0.downcast::().map(BoundRef) } pub unsafe fn downcast_unchecked(self) -> BoundRef<'a, 'py, T> { BoundRef(self.0.downcast_unchecked::()) } } // GIL Ref implementations for &'a T ran into trouble with orphan rules, // so explicit implementations are used instead for the two relevant types. #[cfg(feature = "gil-refs")] impl<'a> From> for &'a PyType { #[inline] fn from(bound: BoundRef<'a, 'a, PyType>) -> Self { bound.0.as_gil_ref() } } #[cfg(feature = "gil-refs")] impl<'a> From> for &'a PyModule { #[inline] fn from(bound: BoundRef<'a, 'a, PyModule>) -> Self { bound.0.as_gil_ref() } } #[allow(deprecated)] #[cfg(feature = "gil-refs")] impl<'a, 'py, T: PyClass> From> for &'a crate::PyCell { #[inline] fn from(bound: BoundRef<'a, 'py, T>) -> Self { bound.0.as_gil_ref() } } impl<'a, 'py, T: PyClass> TryFrom> for PyRef<'py, T> { type Error = PyBorrowError; #[inline] fn try_from(value: BoundRef<'a, 'py, T>) -> Result { value.0.try_borrow() } } impl<'a, 'py, T: PyClass> TryFrom> for PyRefMut<'py, T> { type Error = PyBorrowMutError; #[inline] fn try_from(value: BoundRef<'a, 'py, T>) -> Result { value.0.try_borrow_mut() } } impl<'a, 'py, T> From> for Bound<'py, T> { #[inline] fn from(bound: BoundRef<'a, 'py, T>) -> Self { bound.0.clone() } } impl<'a, 'py, T> From> for &'a Bound<'py, T> { #[inline] fn from(bound: BoundRef<'a, 'py, T>) -> Self { bound.0 } } impl From> for Py { #[inline] fn from(bound: BoundRef<'_, '_, T>) -> Self { bound.0.clone().unbind() } } impl<'py, T> std::ops::Deref for BoundRef<'_, 'py, T> { type Target = Bound<'py, T>; #[inline] fn deref(&self) -> &Self::Target { self.0 } } pub unsafe fn tp_new_impl( py: Python<'_>, initializer: PyClassInitializer, target_type: *mut ffi::PyTypeObject, ) -> PyResult<*mut ffi::PyObject> { initializer .create_class_object_of_type(py, target_type) .map(Bound::into_ptr) } pyo3/src/impl_/pyclass/0000775000175000017500000000000014661133735016002 5ustar jamespagejamespagepyo3/src/impl_/pyclass/lazy_type_object.rs0000644000175000017500000001742414661133735021724 0ustar jamespagejamespageuse std::{ cell::RefCell, ffi::CStr, marker::PhantomData, thread::{self, ThreadId}, }; use crate::{ exceptions::PyRuntimeError, ffi, impl_::pyclass::MaybeRuntimePyMethodDef, pyclass::{create_type_object, PyClassTypeObject}, sync::{GILOnceCell, GILProtected}, types::PyType, Bound, PyClass, PyErr, PyMethodDefType, PyObject, PyResult, Python, }; use super::PyClassItemsIter; /// Lazy type object for PyClass. #[doc(hidden)] pub struct LazyTypeObject(LazyTypeObjectInner, PhantomData); // Non-generic inner of LazyTypeObject to keep code size down struct LazyTypeObjectInner { value: GILOnceCell, // Threads which have begun initialization of the `tp_dict`. Used for // reentrant initialization detection. initializing_threads: GILProtected>>, tp_dict_filled: GILOnceCell<()>, } impl LazyTypeObject { /// Creates an uninitialized `LazyTypeObject`. #[allow(clippy::new_without_default)] pub const fn new() -> Self { LazyTypeObject( LazyTypeObjectInner { value: GILOnceCell::new(), initializing_threads: GILProtected::new(RefCell::new(Vec::new())), tp_dict_filled: GILOnceCell::new(), }, PhantomData, ) } } impl LazyTypeObject { /// Gets the type object contained by this `LazyTypeObject`, initializing it if needed. pub fn get_or_init<'py>(&self, py: Python<'py>) -> &Bound<'py, PyType> { self.get_or_try_init(py).unwrap_or_else(|err| { err.print(py); panic!("failed to create type object for {}", T::NAME) }) } /// Fallible version of the above. pub(crate) fn get_or_try_init<'py>(&self, py: Python<'py>) -> PyResult<&Bound<'py, PyType>> { self.0 .get_or_try_init(py, create_type_object::, T::NAME, T::items_iter()) } } impl LazyTypeObjectInner { // Uses dynamically dispatched fn(Python<'py>) -> PyResult // so that this code is only instantiated once, instead of for every T // like the generic LazyTypeObject methods above. fn get_or_try_init<'py>( &self, py: Python<'py>, init: fn(Python<'py>) -> PyResult, name: &str, items_iter: PyClassItemsIter, ) -> PyResult<&Bound<'py, PyType>> { (|| -> PyResult<_> { let type_object = self .value .get_or_try_init(py, || init(py))? .type_object .bind(py); self.ensure_init(type_object, name, items_iter)?; Ok(type_object) })() .map_err(|err| { wrap_in_runtime_error( py, err, format!("An error occurred while initializing class {}", name), ) }) } fn ensure_init( &self, type_object: &Bound<'_, PyType>, name: &str, items_iter: PyClassItemsIter, ) -> PyResult<()> { let py = type_object.py(); // We might want to fill the `tp_dict` with python instances of `T` // itself. In order to do so, we must first initialize the type object // with an empty `tp_dict`: now we can create instances of `T`. // // Then we fill the `tp_dict`. Multiple threads may try to fill it at // the same time, but only one of them will succeed. // // More importantly, if a thread is performing initialization of the // `tp_dict`, it can still request the type object through `get_or_init`, // but the `tp_dict` may appear empty of course. if self.tp_dict_filled.get(py).is_some() { // `tp_dict` is already filled: ok. return Ok(()); } let thread_id = thread::current().id(); { let mut threads = self.initializing_threads.get(py).borrow_mut(); if threads.contains(&thread_id) { // Reentrant call: just return the type object, even if the // `tp_dict` is not filled yet. return Ok(()); } threads.push(thread_id); } struct InitializationGuard<'a> { initializing_threads: &'a GILProtected>>, py: Python<'a>, thread_id: ThreadId, } impl Drop for InitializationGuard<'_> { fn drop(&mut self) { let mut threads = self.initializing_threads.get(self.py).borrow_mut(); threads.retain(|id| *id != self.thread_id); } } let guard = InitializationGuard { initializing_threads: &self.initializing_threads, py, thread_id, }; // Pre-compute the class attribute objects: this can temporarily // release the GIL since we're calling into arbitrary user code. It // means that another thread can continue the initialization in the // meantime: at worst, we'll just make a useless computation. let mut items = vec![]; for class_items in items_iter { for def in class_items.methods { let built_method; let method = match def { MaybeRuntimePyMethodDef::Runtime(builder) => { built_method = builder(); &built_method } MaybeRuntimePyMethodDef::Static(method) => method, }; if let PyMethodDefType::ClassAttribute(attr) = method { match (attr.meth)(py) { Ok(val) => items.push((attr.name, val)), Err(err) => { return Err(wrap_in_runtime_error( py, err, format!( "An error occurred while initializing `{}.{}`", name, attr.name.to_str().unwrap() ), )) } } } } } // Now we hold the GIL and we can assume it won't be released until we // return from the function. let result = self.tp_dict_filled.get_or_try_init(py, move || { let result = initialize_tp_dict(py, type_object.as_ptr(), items); // Initialization successfully complete, can clear the thread list. // (No further calls to get_or_init() will try to init, on any thread.) std::mem::forget(guard); self.initializing_threads.get(py).replace(Vec::new()); result }); if let Err(err) = result { return Err(wrap_in_runtime_error( py, err.clone_ref(py), format!("An error occurred while initializing `{}.__dict__`", name), )); } Ok(()) } } fn initialize_tp_dict( py: Python<'_>, type_object: *mut ffi::PyObject, items: Vec<(&'static CStr, PyObject)>, ) -> PyResult<()> { // We hold the GIL: the dictionary update can be considered atomic from // the POV of other threads. for (key, val) in items { crate::err::error_on_minusone(py, unsafe { ffi::PyObject_SetAttrString(type_object, key.as_ptr(), val.into_ptr()) })?; } Ok(()) } // This is necessary for making static `LazyTypeObject`s unsafe impl Sync for LazyTypeObject {} #[cold] fn wrap_in_runtime_error(py: Python<'_>, err: PyErr, message: String) -> PyErr { let runtime_err = PyRuntimeError::new_err(message); runtime_err.set_cause(py, Some(err)); runtime_err } pyo3/src/impl_/coroutine.rs0000644000175000017500000000534514661133735016706 0ustar jamespagejamespageuse std::{ future::Future, ops::{Deref, DerefMut}, }; use crate::{ coroutine::{cancel::ThrowCallback, Coroutine}, instance::Bound, pycell::impl_::PyClassBorrowChecker, pyclass::boolean_struct::False, types::{PyAnyMethods, PyString}, IntoPy, Py, PyAny, PyClass, PyErr, PyObject, PyResult, Python, }; pub fn new_coroutine( name: &Bound<'_, PyString>, qualname_prefix: Option<&'static str>, throw_callback: Option, future: F, ) -> Coroutine where F: Future> + Send + 'static, T: IntoPy, E: Into, { Coroutine::new( Some(name.clone().into()), qualname_prefix, throw_callback, future, ) } fn get_ptr(obj: &Py) -> *mut T { obj.get_class_object().get_ptr() } pub struct RefGuard(Py); impl RefGuard { pub fn new(obj: &Bound<'_, PyAny>) -> PyResult { let bound = obj.downcast::()?; bound.get_class_object().borrow_checker().try_borrow()?; Ok(RefGuard(bound.clone().unbind())) } } impl Deref for RefGuard { type Target = T; fn deref(&self) -> &Self::Target { // SAFETY: `RefGuard` has been built from `PyRef` and provides the same guarantees unsafe { &*get_ptr(&self.0) } } } impl Drop for RefGuard { fn drop(&mut self) { Python::with_gil(|gil| { self.0 .bind(gil) .get_class_object() .borrow_checker() .release_borrow() }) } } pub struct RefMutGuard>(Py); impl> RefMutGuard { pub fn new(obj: &Bound<'_, PyAny>) -> PyResult { let bound = obj.downcast::()?; bound.get_class_object().borrow_checker().try_borrow_mut()?; Ok(RefMutGuard(bound.clone().unbind())) } } impl> Deref for RefMutGuard { type Target = T; fn deref(&self) -> &Self::Target { // SAFETY: `RefMutGuard` has been built from `PyRefMut` and provides the same guarantees unsafe { &*get_ptr(&self.0) } } } impl> DerefMut for RefMutGuard { fn deref_mut(&mut self) -> &mut Self::Target { // SAFETY: `RefMutGuard` has been built from `PyRefMut` and provides the same guarantees unsafe { &mut *get_ptr(&self.0) } } } impl> Drop for RefMutGuard { fn drop(&mut self) { Python::with_gil(|gil| { self.0 .bind(gil) .get_class_object() .borrow_checker() .release_borrow_mut() }) } } pyo3/src/impl_/pyfunction.rs0000644000175000017500000000627214661133735017075 0ustar jamespagejamespageuse crate::{ types::{PyCFunction, PyModule}, Borrowed, Bound, PyResult, Python, }; pub use crate::impl_::pymethods::PyMethodDef; /// Trait to enable the use of `wrap_pyfunction` with both `Python` and `PyModule`, /// and also to infer the return type of either `&'py PyCFunction` or `Bound<'py, PyCFunction>`. pub trait WrapPyFunctionArg<'py, T> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult; } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Bound<'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(&self)) } } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Bound<'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(self)) } } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Borrowed<'_, 'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(&self)) } } impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, 'py, PyModule> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.py(), method_def, Some(self)) } } // For Python<'py>, only the GIL Ref form exists to avoid causing type inference to kick in. // The `wrap_pyfunction_bound!` macro is needed for the Bound form. #[cfg(feature = "gil-refs")] impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for Python<'py> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> { PyCFunction::internal_new(self, method_def, None).map(Bound::into_gil_ref) } } #[cfg(not(feature = "gil-refs"))] impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Python<'py> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self, method_def, None) } } #[cfg(feature = "gil-refs")] impl<'py> WrapPyFunctionArg<'py, &'py PyCFunction> for &'py PyModule { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult<&'py PyCFunction> { use crate::PyNativeType; PyCFunction::internal_new(self.py(), method_def, Some(&self.as_borrowed())) .map(Bound::into_gil_ref) } } /// Helper for `wrap_pyfunction_bound!` to guarantee return type of `Bound<'py, PyCFunction>`. pub struct OnlyBound(pub T); impl<'py, T> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for OnlyBound where T: WrapPyFunctionArg<'py, Bound<'py, PyCFunction>>, { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { WrapPyFunctionArg::wrap_pyfunction(self.0, method_def) } } #[cfg(feature = "gil-refs")] impl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for OnlyBound> { fn wrap_pyfunction(self, method_def: &PyMethodDef) -> PyResult> { PyCFunction::internal_new(self.0, method_def, None) } } pyo3/src/impl_/trampoline.rs0000644000175000017500000001625314661133735017051 0ustar jamespagejamespage//! Trampolines for various pyfunction and pymethod implementations. //! //! They exist to monomorphise std::panic::catch_unwind once into PyO3, rather than inline in every //! function, thus saving a huge amount of compile-time complexity. use std::{ any::Any, os::raw::c_int, panic::{self, UnwindSafe}, }; use crate::gil::GILGuard; use crate::{ callback::PyCallbackOutput, ffi, ffi_ptr_ext::FfiPtrExt, impl_::panic::PanicTrap, methods::IPowModulo, panic::PanicException, types::PyModule, Py, PyResult, Python, }; #[inline] pub unsafe fn module_init( f: for<'py> unsafe fn(Python<'py>) -> PyResult>, ) -> *mut ffi::PyObject { trampoline(|py| f(py).map(|module| module.into_ptr())) } #[inline] #[allow(clippy::used_underscore_binding)] pub unsafe fn noargs( slf: *mut ffi::PyObject, _args: *mut ffi::PyObject, f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> PyResult<*mut ffi::PyObject>, ) -> *mut ffi::PyObject { #[cfg(not(GraalPy))] // this is not specified and GraalPy does not pass null here debug_assert!(_args.is_null()); trampoline(|py| f(py, slf)) } macro_rules! trampoline { (pub fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty;) => { #[inline] pub unsafe fn $name( $($arg_names: $arg_types,)* f: for<'py> unsafe fn (Python<'py>, $($arg_types),*) -> PyResult<$ret>, ) -> $ret { trampoline(|py| f(py, $($arg_names,)*)) } } } macro_rules! trampolines { ($(pub fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty);* ;) => { $(trampoline!(pub fn $name($($arg_names: $arg_types),*) -> $ret;));*; } } trampolines!( pub fn fastcall_with_keywords( slf: *mut ffi::PyObject, args: *const *mut ffi::PyObject, nargs: ffi::Py_ssize_t, kwnames: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn cfunction_with_keywords( slf: *mut ffi::PyObject, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, ) -> *mut ffi::PyObject; ); // Trampolines used by slot methods trampolines!( pub fn getattrofunc(slf: *mut ffi::PyObject, attr: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn setattrofunc( slf: *mut ffi::PyObject, attr: *mut ffi::PyObject, value: *mut ffi::PyObject, ) -> c_int; pub fn binaryfunc(slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn descrgetfunc( slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn getiterfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn hashfunc(slf: *mut ffi::PyObject) -> ffi::Py_hash_t; pub fn inquiry(slf: *mut ffi::PyObject) -> c_int; pub fn iternextfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn lenfunc(slf: *mut ffi::PyObject) -> ffi::Py_ssize_t; pub fn newfunc( subtype: *mut ffi::PyTypeObject, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn objobjproc(slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject) -> c_int; pub fn reprfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; pub fn richcmpfunc( slf: *mut ffi::PyObject, other: *mut ffi::PyObject, op: c_int, ) -> *mut ffi::PyObject; pub fn ssizeargfunc(arg1: *mut ffi::PyObject, arg2: ffi::Py_ssize_t) -> *mut ffi::PyObject; pub fn ternaryfunc( slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, ) -> *mut ffi::PyObject; pub fn unaryfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject; ); #[cfg(any(not(Py_LIMITED_API), Py_3_11))] trampoline! { pub fn getbufferproc(slf: *mut ffi::PyObject, buf: *mut ffi::Py_buffer, flags: c_int) -> c_int; } #[cfg(any(not(Py_LIMITED_API), Py_3_11))] #[inline] pub unsafe fn releasebufferproc( slf: *mut ffi::PyObject, buf: *mut ffi::Py_buffer, f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject, *mut ffi::Py_buffer) -> PyResult<()>, ) { trampoline_unraisable(|py| f(py, slf, buf), slf) } #[inline] pub(crate) unsafe fn dealloc( slf: *mut ffi::PyObject, f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> (), ) { // After calling tp_dealloc the object is no longer valid, // so pass null_mut() to the context. // // (Note that we don't allow the implementation `f` to fail.) trampoline_unraisable( |py| { f(py, slf); Ok(()) }, std::ptr::null_mut(), ) } // Ipowfunc is a unique case where PyO3 has its own type // to workaround a problem on 3.7 (see IPowModulo type definition). // Once 3.7 support dropped can just remove this. trampoline!( pub fn ipowfunc( arg1: *mut ffi::PyObject, arg2: *mut ffi::PyObject, arg3: IPowModulo, ) -> *mut ffi::PyObject; ); /// Implementation of trampoline functions, which sets up a GILPool and calls F. /// /// Panics during execution are trapped so that they don't propagate through any /// outer FFI boundary. /// /// The GIL must already be held when this is called. #[inline] pub(crate) unsafe fn trampoline(body: F) -> R where F: for<'py> FnOnce(Python<'py>) -> PyResult + UnwindSafe, R: PyCallbackOutput, { let trap = PanicTrap::new("uncaught panic at ffi boundary"); // SAFETY: This function requires the GIL to already be held. let guard = GILGuard::assume(); let py = guard.python(); let out = panic_result_into_callback_output( py, panic::catch_unwind(move || -> PyResult<_> { body(py) }), ); trap.disarm(); out } /// Converts the output of std::panic::catch_unwind into a Python function output, either by raising a Python /// exception or by unwrapping the contained success output. #[inline] fn panic_result_into_callback_output( py: Python<'_>, panic_result: Result, Box>, ) -> R where R: PyCallbackOutput, { let py_err = match panic_result { Ok(Ok(value)) => return value, Ok(Err(py_err)) => py_err, Err(payload) => PanicException::from_panic_payload(payload), }; py_err.restore(py); R::ERR_VALUE } /// Implementation of trampoline for functions which can't return an error. /// /// Panics during execution are trapped so that they don't propagate through any /// outer FFI boundary. /// /// Exceptions produced are sent to `sys.unraisablehook`. /// /// # Safety /// /// - ctx must be either a valid ffi::PyObject or NULL /// - The GIL must already be held when this is called. #[inline] unsafe fn trampoline_unraisable(body: F, ctx: *mut ffi::PyObject) where F: for<'py> FnOnce(Python<'py>) -> PyResult<()> + UnwindSafe, { let trap = PanicTrap::new("uncaught panic at ffi boundary"); // SAFETY: The GIL is already held. let guard = GILGuard::assume(); let py = guard.python(); if let Err(py_err) = panic::catch_unwind(move || body(py)) .unwrap_or_else(|payload| Err(PanicException::from_panic_payload(payload))) { py_err.write_unraisable_bound(py, ctx.assume_borrowed_or_opt(py).as_deref()); } trap.disarm(); } pyo3/src/impl_/exceptions.rs0000644000175000017500000000144014661133735017050 0ustar jamespagejamespageuse crate::{sync::GILOnceCell, types::PyType, Bound, Py, Python}; pub struct ImportedExceptionTypeObject { imported_value: GILOnceCell>, module: &'static str, name: &'static str, } impl ImportedExceptionTypeObject { pub const fn new(module: &'static str, name: &'static str) -> Self { Self { imported_value: GILOnceCell::new(), module, name, } } pub fn get<'py>(&self, py: Python<'py>) -> &Bound<'py, PyType> { self.imported_value .get_or_try_init_type_ref(py, self.module, self.name) .unwrap_or_else(|e| { panic!( "failed to import exception {}.{}: {}", self.module, self.name, e ) }) } } pyo3/src/impl_/pymodule.rs0000644000175000017500000002371114661133735016532 0ustar jamespagejamespage//! Implementation details of `#[pymodule]` which need to be accessible from proc-macro generated code. use std::{cell::UnsafeCell, ffi::CStr, marker::PhantomData}; #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))), not(target_has_atomic = "64"), ))] use portable_atomic::{AtomicI64, Ordering}; #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))), target_has_atomic = "64", ))] use std::sync::atomic::{AtomicI64, Ordering}; #[cfg(not(any(PyPy, GraalPy)))] use crate::exceptions::PyImportError; use crate::{ ffi, sync::GILOnceCell, types::{PyCFunction, PyModule, PyModuleMethods}, Bound, Py, PyClass, PyMethodDef, PyResult, PyTypeInfo, Python, }; /// `Sync` wrapper of `ffi::PyModuleDef`. pub struct ModuleDef { // wrapped in UnsafeCell so that Rust compiler treats this as interior mutability ffi_def: UnsafeCell, initializer: ModuleInitializer, /// Interpreter ID where module was initialized (not applicable on PyPy). #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))) ))] interpreter: AtomicI64, /// Initialized module object, cached to avoid reinitialization. module: GILOnceCell>, } /// Wrapper to enable initializer to be used in const fns. pub struct ModuleInitializer(pub for<'py> fn(&Bound<'py, PyModule>) -> PyResult<()>); unsafe impl Sync for ModuleDef {} impl ModuleDef { /// Make new module definition with given module name. pub const unsafe fn new( name: &'static CStr, doc: &'static CStr, initializer: ModuleInitializer, ) -> Self { const INIT: ffi::PyModuleDef = ffi::PyModuleDef { m_base: ffi::PyModuleDef_HEAD_INIT, m_name: std::ptr::null(), m_doc: std::ptr::null(), m_size: 0, m_methods: std::ptr::null_mut(), m_slots: std::ptr::null_mut(), m_traverse: None, m_clear: None, m_free: None, }; let ffi_def = UnsafeCell::new(ffi::PyModuleDef { m_name: name.as_ptr(), m_doc: doc.as_ptr(), ..INIT }); ModuleDef { ffi_def, initializer, // -1 is never expected to be a valid interpreter ID #[cfg(all( not(any(PyPy, GraalPy)), Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))) ))] interpreter: AtomicI64::new(-1), module: GILOnceCell::new(), } } /// Builds a module using user given initializer. Used for [`#[pymodule]`][crate::pymodule]. pub fn make_module(&'static self, py: Python<'_>) -> PyResult> { #[cfg(all(PyPy, not(Py_3_8)))] { use crate::types::any::PyAnyMethods; const PYPY_GOOD_VERSION: [u8; 3] = [7, 3, 8]; let version = py .import_bound("sys")? .getattr("implementation")? .getattr("version")?; if version.lt(crate::types::PyTuple::new_bound(py, PYPY_GOOD_VERSION))? { let warn = py.import_bound("warnings")?.getattr("warn")?; warn.call1(( "PyPy 3.7 versions older than 7.3.8 are known to have binary \ compatibility issues which may cause segfaults. Please upgrade.", ))?; } } // Check the interpreter ID has not changed, since we currently have no way to guarantee // that static data is not reused across interpreters. // // PyPy does not have subinterpreters, so no need to check interpreter ID. #[cfg(not(any(PyPy, GraalPy)))] { // PyInterpreterState_Get is only available on 3.9 and later, but is missing // from python3.dll for Windows stable API on 3.9 #[cfg(all(Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10)))))] { let current_interpreter = unsafe { ffi::PyInterpreterState_GetID(ffi::PyInterpreterState_Get()) }; crate::err::error_on_minusone(py, current_interpreter)?; if let Err(initialized_interpreter) = self.interpreter.compare_exchange( -1, current_interpreter, Ordering::SeqCst, Ordering::SeqCst, ) { if initialized_interpreter != current_interpreter { return Err(PyImportError::new_err( "PyO3 modules do not yet support subinterpreters, see https://github.com/PyO3/pyo3/issues/576", )); } } } #[cfg(not(all(Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))))))] { // CPython before 3.9 does not have APIs to check the interpreter ID, so best that can be // done to guard against subinterpreters is fail if the module is initialized twice if self.module.get(py).is_some() { return Err(PyImportError::new_err( "PyO3 modules compiled for CPython 3.8 or older may only be initialized once per interpreter process" )); } } } self.module .get_or_try_init(py, || { let module = unsafe { Py::::from_owned_ptr_or_err( py, ffi::PyModule_Create(self.ffi_def.get()), )? }; self.initializer.0(module.bind(py))?; Ok(module) }) .map(|py_module| py_module.clone_ref(py)) } } /// Trait to add an element (class, function...) to a module. /// /// Currently only implemented for classes. pub trait PyAddToModule { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()>; } /// For adding native types (non-pyclass) to a module. pub struct AddTypeToModule(PhantomData); impl AddTypeToModule { #[allow(clippy::new_without_default)] pub const fn new() -> Self { AddTypeToModule(PhantomData) } } impl PyAddToModule for AddTypeToModule { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add(T::NAME, T::type_object_bound(module.py())) } } /// For adding a class to a module. pub struct AddClassToModule(PhantomData); impl AddClassToModule { #[allow(clippy::new_without_default)] pub const fn new() -> Self { AddClassToModule(PhantomData) } } impl PyAddToModule for AddClassToModule { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_class::() } } /// For adding a function to a module. impl PyAddToModule for PyMethodDef { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_function(PyCFunction::internal_new(module.py(), self, Some(module))?) } } /// For adding a module to a module. impl PyAddToModule for ModuleDef { fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add_submodule(self.make_module(module.py())?.bind(module.py())) } } #[cfg(test)] mod tests { use std::{ borrow::Cow, ffi::CStr, sync::atomic::{AtomicBool, Ordering}, }; use crate::{ ffi, types::{any::PyAnyMethods, module::PyModuleMethods, PyModule}, Bound, PyResult, Python, }; use super::{ModuleDef, ModuleInitializer}; #[test] fn module_init() { static MODULE_DEF: ModuleDef = unsafe { ModuleDef::new( ffi::c_str!("test_module"), ffi::c_str!("some doc"), ModuleInitializer(|m| { m.add("SOME_CONSTANT", 42)?; Ok(()) }), ) }; Python::with_gil(|py| { let module = MODULE_DEF.make_module(py).unwrap().into_bound(py); assert_eq!( module .getattr("__name__") .unwrap() .extract::>() .unwrap(), "test_module", ); assert_eq!( module .getattr("__doc__") .unwrap() .extract::>() .unwrap(), "some doc", ); assert_eq!( module .getattr("SOME_CONSTANT") .unwrap() .extract::() .unwrap(), 42, ); }) } #[test] fn module_def_new() { // To get coverage for ModuleDef::new() need to create a non-static ModuleDef, however init // etc require static ModuleDef, so this test needs to be separated out. static NAME: &CStr = ffi::c_str!("test_module"); static DOC: &CStr = ffi::c_str!("some doc"); static INIT_CALLED: AtomicBool = AtomicBool::new(false); #[allow(clippy::unnecessary_wraps)] fn init(_: &Bound<'_, PyModule>) -> PyResult<()> { INIT_CALLED.store(true, Ordering::SeqCst); Ok(()) } unsafe { let module_def: ModuleDef = ModuleDef::new(NAME, DOC, ModuleInitializer(init)); assert_eq!((*module_def.ffi_def.get()).m_name, NAME.as_ptr() as _); assert_eq!((*module_def.ffi_def.get()).m_doc, DOC.as_ptr() as _); Python::with_gil(|py| { module_def.initializer.0(&py.import_bound("builtins").unwrap()).unwrap(); assert!(INIT_CALLED.load(Ordering::SeqCst)); }) } } } pyo3/src/impl_/pyclass.rs0000644000175000017500000012714014661133735016353 0ustar jamespagejamespage#[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ exceptions::{PyAttributeError, PyNotImplementedError, PyRuntimeError, PyValueError}, ffi, impl_::freelist::FreeList, impl_::pycell::{GetBorrowChecker, PyClassMutability, PyClassObjectLayout}, pyclass_init::PyObjectInit, types::{any::PyAnyMethods, PyBool}, Borrowed, IntoPy, Py, PyAny, PyClass, PyErr, PyMethodDefType, PyResult, PyTypeInfo, Python, ToPyObject, }; use std::{ borrow::Cow, ffi::{CStr, CString}, marker::PhantomData, os::raw::{c_int, c_void}, ptr::NonNull, thread, }; mod lazy_type_object; pub use lazy_type_object::LazyTypeObject; /// Gets the offset of the dictionary from the start of the object in bytes. #[inline] pub fn dict_offset() -> ffi::Py_ssize_t { PyClassObject::::dict_offset() } /// Gets the offset of the weakref list from the start of the object in bytes. #[inline] pub fn weaklist_offset() -> ffi::Py_ssize_t { PyClassObject::::weaklist_offset() } /// Represents the `__dict__` field for `#[pyclass]`. pub trait PyClassDict { /// Initial form of a [PyObject](crate::ffi::PyObject) `__dict__` reference. const INIT: Self; /// Empties the dictionary of its key-value pairs. #[inline] fn clear_dict(&mut self, _py: Python<'_>) {} private_decl! {} } /// Represents the `__weakref__` field for `#[pyclass]`. pub trait PyClassWeakRef { /// Initializes a `weakref` instance. const INIT: Self; /// Clears the weak references to the given object. /// /// # Safety /// - `_obj` must be a pointer to the pyclass instance which contains `self`. /// - The GIL must be held. #[inline] unsafe fn clear_weakrefs(&mut self, _obj: *mut ffi::PyObject, _py: Python<'_>) {} private_decl! {} } /// Zero-sized dummy field. pub struct PyClassDummySlot; impl PyClassDict for PyClassDummySlot { private_impl! {} const INIT: Self = PyClassDummySlot; } impl PyClassWeakRef for PyClassDummySlot { private_impl! {} const INIT: Self = PyClassDummySlot; } /// Actual dict field, which holds the pointer to `__dict__`. /// /// `#[pyclass(dict)]` automatically adds this. #[repr(transparent)] #[allow(dead_code)] // These are constructed in INIT and used by the macro code pub struct PyClassDictSlot(*mut ffi::PyObject); impl PyClassDict for PyClassDictSlot { private_impl! {} const INIT: Self = Self(std::ptr::null_mut()); #[inline] fn clear_dict(&mut self, _py: Python<'_>) { if !self.0.is_null() { unsafe { ffi::PyDict_Clear(self.0) } } } } /// Actual weakref field, which holds the pointer to `__weakref__`. /// /// `#[pyclass(weakref)]` automatically adds this. #[repr(transparent)] #[allow(dead_code)] // These are constructed in INIT and used by the macro code pub struct PyClassWeakRefSlot(*mut ffi::PyObject); impl PyClassWeakRef for PyClassWeakRefSlot { private_impl! {} const INIT: Self = Self(std::ptr::null_mut()); #[inline] unsafe fn clear_weakrefs(&mut self, obj: *mut ffi::PyObject, _py: Python<'_>) { if !self.0.is_null() { ffi::PyObject_ClearWeakRefs(obj) } } } /// This type is used as a "dummy" type on which dtolnay specializations are /// applied to apply implementations from `#[pymethods]` pub struct PyClassImplCollector(PhantomData); impl PyClassImplCollector { pub fn new() -> Self { Self(PhantomData) } } impl Default for PyClassImplCollector { fn default() -> Self { Self::new() } } impl Clone for PyClassImplCollector { fn clone(&self) -> Self { *self } } impl Copy for PyClassImplCollector {} pub enum MaybeRuntimePyMethodDef { /// Used in cases where const functionality is not sufficient to define the method /// purely at compile time. Runtime(fn() -> PyMethodDefType), Static(PyMethodDefType), } pub struct PyClassItems { pub methods: &'static [MaybeRuntimePyMethodDef], pub slots: &'static [ffi::PyType_Slot], } // Allow PyClassItems in statics unsafe impl Sync for PyClassItems {} /// Implements the underlying functionality of `#[pyclass]`, assembled by various proc macros. /// /// Users are discouraged from implementing this trait manually; it is a PyO3 implementation detail /// and may be changed at any time. pub trait PyClassImpl: Sized + 'static { /// #[pyclass(subclass)] const IS_BASETYPE: bool = false; /// #[pyclass(extends=...)] const IS_SUBCLASS: bool = false; /// #[pyclass(mapping)] const IS_MAPPING: bool = false; /// #[pyclass(sequence)] const IS_SEQUENCE: bool = false; /// Base class type BaseType: PyTypeInfo + PyClassBaseType; /// Immutable or mutable type PyClassMutability: PyClassMutability + GetBorrowChecker; /// Specify this class has `#[pyclass(dict)]` or not. type Dict: PyClassDict; /// Specify this class has `#[pyclass(weakref)]` or not. type WeakRef: PyClassWeakRef; /// The closest native ancestor. This is `PyAny` by default, and when you declare /// `#[pyclass(extends=PyDict)]`, it's `PyDict`. #[cfg(feature = "gil-refs")] type BaseNativeType: PyTypeInfo + PyNativeType; /// The closest native ancestor. This is `PyAny` by default, and when you declare /// `#[pyclass(extends=PyDict)]`, it's `PyDict`. #[cfg(not(feature = "gil-refs"))] type BaseNativeType: PyTypeInfo; /// This handles following two situations: /// 1. In case `T` is `Send`, stub `ThreadChecker` is used and does nothing. /// This implementation is used by default. Compile fails if `T: !Send`. /// 2. In case `T` is `!Send`, `ThreadChecker` panics when `T` is accessed by another thread. /// This implementation is used when `#[pyclass(unsendable)]` is given. /// Panicking makes it safe to expose `T: !Send` to the Python interpreter, where all objects /// can be accessed by multiple threads by `threading` module. type ThreadChecker: PyClassThreadChecker; #[cfg(feature = "multiple-pymethods")] type Inventory: PyClassInventory; /// Rendered class doc fn doc(py: Python<'_>) -> PyResult<&'static CStr>; fn items_iter() -> PyClassItemsIter; #[inline] fn dict_offset() -> Option { None } #[inline] fn weaklist_offset() -> Option { None } fn lazy_type_object() -> &'static LazyTypeObject; } /// Runtime helper to build a class docstring from the `doc` and `text_signature`. /// /// This is done at runtime because the class text signature is collected via dtolnay /// specialization in to the `#[pyclass]` macro from the `#[pymethods]` macro. pub fn build_pyclass_doc( class_name: &'static str, doc: &'static CStr, text_signature: Option<&'static str>, ) -> PyResult> { if let Some(text_signature) = text_signature { let doc = CString::new(format!( "{}{}\n--\n\n{}", class_name, text_signature, doc.to_str().unwrap(), )) .map_err(|_| PyValueError::new_err("class doc cannot contain nul bytes"))?; Ok(Cow::Owned(doc)) } else { Ok(Cow::Borrowed(doc)) } } /// Iterator used to process all class items during type instantiation. pub struct PyClassItemsIter { /// Iteration state idx: usize, /// Items from the `#[pyclass]` macro pyclass_items: &'static PyClassItems, /// Items from the `#[pymethods]` macro #[cfg(not(feature = "multiple-pymethods"))] pymethods_items: &'static PyClassItems, /// Items from the `#[pymethods]` macro with inventory #[cfg(feature = "multiple-pymethods")] pymethods_items: Box>, } impl PyClassItemsIter { pub fn new( pyclass_items: &'static PyClassItems, #[cfg(not(feature = "multiple-pymethods"))] pymethods_items: &'static PyClassItems, #[cfg(feature = "multiple-pymethods")] pymethods_items: Box< dyn Iterator, >, ) -> Self { Self { idx: 0, pyclass_items, pymethods_items, } } } impl Iterator for PyClassItemsIter { type Item = &'static PyClassItems; #[cfg(not(feature = "multiple-pymethods"))] fn next(&mut self) -> Option { match self.idx { 0 => { self.idx += 1; Some(self.pyclass_items) } 1 => { self.idx += 1; Some(self.pymethods_items) } // Termination clause _ => None, } } #[cfg(feature = "multiple-pymethods")] fn next(&mut self) -> Option { match self.idx { 0 => { self.idx += 1; Some(self.pyclass_items) } // Termination clause _ => self.pymethods_items.next(), } } } // Traits describing known special methods. macro_rules! slot_fragment_trait { ($trait_name:ident, $($default_method:tt)*) => { #[allow(non_camel_case_types)] pub trait $trait_name: Sized { $($default_method)* } impl $trait_name for &'_ PyClassImplCollector {} } } slot_fragment_trait! { PyClass__getattribute__SlotFragment, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn __getattribute__( self, py: Python<'_>, slf: *mut ffi::PyObject, attr: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { let res = ffi::PyObject_GenericGetAttr(slf, attr); if res.is_null() { Err(PyErr::fetch(py)) } else { Ok(res) } } } slot_fragment_trait! { PyClass__getattr__SlotFragment, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn __getattr__( self, py: Python<'_>, _slf: *mut ffi::PyObject, attr: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Err(PyErr::new::( (Py::::from_borrowed_ptr(py, attr),) )) } } #[doc(hidden)] #[macro_export] macro_rules! generate_pyclass_getattro_slot { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, attr: *mut $crate::ffi::PyObject, ) -> *mut $crate::ffi::PyObject { $crate::impl_::trampoline::getattrofunc(_slf, attr, |py, _slf, attr| { use ::std::result::Result::*; use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); // Strategy: // - Try __getattribute__ first. Its default is PyObject_GenericGetAttr. // - If it returns a result, use it. // - If it fails with AttributeError, try __getattr__. // - If it fails otherwise, reraise. match collector.__getattribute__(py, _slf, attr) { Ok(obj) => Ok(obj), Err(e) if e.is_instance_of::<$crate::exceptions::PyAttributeError>(py) => { collector.__getattr__(py, _slf, attr) } Err(e) => Err(e), } }) } $crate::ffi::PyType_Slot { slot: $crate::ffi::Py_tp_getattro, pfunc: __wrap as $crate::ffi::getattrofunc as _, } }}; } pub use generate_pyclass_getattro_slot; /// Macro which expands to three items /// - Trait for a __setitem__ dunder /// - Trait for the corresponding __delitem__ dunder /// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders macro_rules! define_pyclass_setattr_slot { ( $set_trait:ident, $del_trait:ident, $set:ident, $del:ident, $set_error:expr, $del_error:expr, $generate_macro:ident, $slot:ident, $func_ty:ident, ) => { slot_fragment_trait! { $set_trait, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn $set( self, _py: Python<'_>, _slf: *mut ffi::PyObject, _attr: *mut ffi::PyObject, _value: NonNull, ) -> PyResult<()> { $set_error } } slot_fragment_trait! { $del_trait, /// # Safety: _slf and _attr must be valid non-null Python objects #[inline] unsafe fn $del( self, _py: Python<'_>, _slf: *mut ffi::PyObject, _attr: *mut ffi::PyObject, ) -> PyResult<()> { $del_error } } #[doc(hidden)] #[macro_export] macro_rules! $generate_macro { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, attr: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject, ) -> ::std::os::raw::c_int { $crate::impl_::trampoline::setattrofunc( _slf, attr, value, |py, _slf, attr, value| { use ::std::option::Option::*; use $crate::callback::IntoPyCallbackOutput; use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); if let Some(value) = ::std::ptr::NonNull::new(value) { collector.$set(py, _slf, attr, value).convert(py) } else { collector.$del(py, _slf, attr).convert(py) } }, ) } $crate::ffi::PyType_Slot { slot: $crate::ffi::$slot, pfunc: __wrap as $crate::ffi::$func_ty as _, } }}; } pub use $generate_macro; }; } define_pyclass_setattr_slot! { PyClass__setattr__SlotFragment, PyClass__delattr__SlotFragment, __setattr__, __delattr__, Err(PyAttributeError::new_err("can't set attribute")), Err(PyAttributeError::new_err("can't delete attribute")), generate_pyclass_setattr_slot, Py_tp_setattro, setattrofunc, } define_pyclass_setattr_slot! { PyClass__set__SlotFragment, PyClass__delete__SlotFragment, __set__, __delete__, Err(PyNotImplementedError::new_err("can't set descriptor")), Err(PyNotImplementedError::new_err("can't delete descriptor")), generate_pyclass_setdescr_slot, Py_tp_descr_set, descrsetfunc, } define_pyclass_setattr_slot! { PyClass__setitem__SlotFragment, PyClass__delitem__SlotFragment, __setitem__, __delitem__, Err(PyNotImplementedError::new_err("can't set item")), Err(PyNotImplementedError::new_err("can't delete item")), generate_pyclass_setitem_slot, Py_mp_ass_subscript, objobjargproc, } /// Macro which expands to three items /// - Trait for a lhs dunder e.g. __add__ /// - Trait for the corresponding rhs e.g. __radd__ /// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders macro_rules! define_pyclass_binary_operator_slot { ( $lhs_trait:ident, $rhs_trait:ident, $lhs:ident, $rhs:ident, $generate_macro:ident, $slot:ident, $func_ty:ident, ) => { slot_fragment_trait! { $lhs_trait, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn $lhs( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { $rhs_trait, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn $rhs( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } #[doc(hidden)] #[macro_export] macro_rules! $generate_macro { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, _other: *mut $crate::ffi::PyObject, ) -> *mut $crate::ffi::PyObject { $crate::impl_::trampoline::binaryfunc(_slf, _other, |py, _slf, _other| { use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); let lhs_result = collector.$lhs(py, _slf, _other)?; if lhs_result == $crate::ffi::Py_NotImplemented() { $crate::ffi::Py_DECREF(lhs_result); collector.$rhs(py, _other, _slf) } else { ::std::result::Result::Ok(lhs_result) } }) } $crate::ffi::PyType_Slot { slot: $crate::ffi::$slot, pfunc: __wrap as $crate::ffi::$func_ty as _, } }}; } pub use $generate_macro; }; } define_pyclass_binary_operator_slot! { PyClass__add__SlotFragment, PyClass__radd__SlotFragment, __add__, __radd__, generate_pyclass_add_slot, Py_nb_add, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__sub__SlotFragment, PyClass__rsub__SlotFragment, __sub__, __rsub__, generate_pyclass_sub_slot, Py_nb_subtract, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__mul__SlotFragment, PyClass__rmul__SlotFragment, __mul__, __rmul__, generate_pyclass_mul_slot, Py_nb_multiply, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__mod__SlotFragment, PyClass__rmod__SlotFragment, __mod__, __rmod__, generate_pyclass_mod_slot, Py_nb_remainder, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__divmod__SlotFragment, PyClass__rdivmod__SlotFragment, __divmod__, __rdivmod__, generate_pyclass_divmod_slot, Py_nb_divmod, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__lshift__SlotFragment, PyClass__rlshift__SlotFragment, __lshift__, __rlshift__, generate_pyclass_lshift_slot, Py_nb_lshift, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__rshift__SlotFragment, PyClass__rrshift__SlotFragment, __rshift__, __rrshift__, generate_pyclass_rshift_slot, Py_nb_rshift, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__and__SlotFragment, PyClass__rand__SlotFragment, __and__, __rand__, generate_pyclass_and_slot, Py_nb_and, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__or__SlotFragment, PyClass__ror__SlotFragment, __or__, __ror__, generate_pyclass_or_slot, Py_nb_or, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__xor__SlotFragment, PyClass__rxor__SlotFragment, __xor__, __rxor__, generate_pyclass_xor_slot, Py_nb_xor, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__matmul__SlotFragment, PyClass__rmatmul__SlotFragment, __matmul__, __rmatmul__, generate_pyclass_matmul_slot, Py_nb_matrix_multiply, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__truediv__SlotFragment, PyClass__rtruediv__SlotFragment, __truediv__, __rtruediv__, generate_pyclass_truediv_slot, Py_nb_true_divide, binaryfunc, } define_pyclass_binary_operator_slot! { PyClass__floordiv__SlotFragment, PyClass__rfloordiv__SlotFragment, __floordiv__, __rfloordiv__, generate_pyclass_floordiv_slot, Py_nb_floor_divide, binaryfunc, } slot_fragment_trait! { PyClass__pow__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __pow__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, _mod: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__rpow__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __rpow__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, _mod: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } #[doc(hidden)] #[macro_export] macro_rules! generate_pyclass_pow_slot { ($cls:ty) => {{ unsafe extern "C" fn __wrap( _slf: *mut $crate::ffi::PyObject, _other: *mut $crate::ffi::PyObject, _mod: *mut $crate::ffi::PyObject, ) -> *mut $crate::ffi::PyObject { $crate::impl_::trampoline::ternaryfunc(_slf, _other, _mod, |py, _slf, _other, _mod| { use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); let lhs_result = collector.__pow__(py, _slf, _other, _mod)?; if lhs_result == $crate::ffi::Py_NotImplemented() { $crate::ffi::Py_DECREF(lhs_result); collector.__rpow__(py, _other, _slf, _mod) } else { ::std::result::Result::Ok(lhs_result) } }) } $crate::ffi::PyType_Slot { slot: $crate::ffi::Py_nb_power, pfunc: __wrap as $crate::ffi::ternaryfunc as _, } }}; } pub use generate_pyclass_pow_slot; slot_fragment_trait! { PyClass__lt__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __lt__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__le__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __le__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__eq__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __eq__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__ne__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __ne__( self, py: Python<'_>, slf: *mut ffi::PyObject, other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { // By default `__ne__` will try `__eq__` and invert the result let slf = Borrowed::from_ptr(py, slf); let other = Borrowed::from_ptr(py, other); slf.eq(other).map(|is_eq| PyBool::new_bound(py, !is_eq).to_owned().into_ptr()) } } slot_fragment_trait! { PyClass__gt__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __gt__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } slot_fragment_trait! { PyClass__ge__SlotFragment, /// # Safety: _slf and _other must be valid non-null Python objects #[inline] unsafe fn __ge__( self, py: Python<'_>, _slf: *mut ffi::PyObject, _other: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { Ok(py.NotImplemented().into_ptr()) } } #[doc(hidden)] #[macro_export] macro_rules! generate_pyclass_richcompare_slot { ($cls:ty) => {{ #[allow(unknown_lints, non_local_definitions)] impl $cls { #[allow(non_snake_case)] unsafe extern "C" fn __pymethod___richcmp____( slf: *mut $crate::ffi::PyObject, other: *mut $crate::ffi::PyObject, op: ::std::os::raw::c_int, ) -> *mut $crate::ffi::PyObject { $crate::impl_::trampoline::richcmpfunc(slf, other, op, |py, slf, other, op| { use $crate::class::basic::CompareOp; use $crate::impl_::pyclass::*; let collector = PyClassImplCollector::<$cls>::new(); match CompareOp::from_raw(op).expect("invalid compareop") { CompareOp::Lt => collector.__lt__(py, slf, other), CompareOp::Le => collector.__le__(py, slf, other), CompareOp::Eq => collector.__eq__(py, slf, other), CompareOp::Ne => collector.__ne__(py, slf, other), CompareOp::Gt => collector.__gt__(py, slf, other), CompareOp::Ge => collector.__ge__(py, slf, other), } }) } } $crate::ffi::PyType_Slot { slot: $crate::ffi::Py_tp_richcompare, pfunc: <$cls>::__pymethod___richcmp____ as $crate::ffi::richcmpfunc as _, } }}; } pub use generate_pyclass_richcompare_slot; use super::{pycell::PyClassObject, pymethods::BoundRef}; /// Implements a freelist. /// /// Do not implement this trait manually. Instead, use `#[pyclass(freelist = N)]` /// on a Rust struct to implement it. pub trait PyClassWithFreeList: PyClass { fn get_free_list(py: Python<'_>) -> &mut FreeList<*mut ffi::PyObject>; } /// Implementation of tp_alloc for `freelist` classes. /// /// # Safety /// - `subtype` must be a valid pointer to the type object of T or a subclass. /// - The GIL must be held. pub unsafe extern "C" fn alloc_with_freelist( subtype: *mut ffi::PyTypeObject, nitems: ffi::Py_ssize_t, ) -> *mut ffi::PyObject { let py = Python::assume_gil_acquired(); #[cfg(not(Py_3_8))] bpo_35810_workaround(py, subtype); let self_type = T::type_object_raw(py); // If this type is a variable type or the subtype is not equal to this type, we cannot use the // freelist if nitems == 0 && subtype == self_type { if let Some(obj) = T::get_free_list(py).pop() { ffi::PyObject_Init(obj, subtype); return obj as _; } } ffi::PyType_GenericAlloc(subtype, nitems) } /// Implementation of tp_free for `freelist` classes. /// /// # Safety /// - `obj` must be a valid pointer to an instance of T (not a subclass). /// - The GIL must be held. pub unsafe extern "C" fn free_with_freelist(obj: *mut c_void) { let obj = obj as *mut ffi::PyObject; debug_assert_eq!( T::type_object_raw(Python::assume_gil_acquired()), ffi::Py_TYPE(obj) ); if let Some(obj) = T::get_free_list(Python::assume_gil_acquired()).insert(obj) { let ty = ffi::Py_TYPE(obj); // Deduce appropriate inverse of PyType_GenericAlloc let free = if ffi::PyType_IS_GC(ty) != 0 { ffi::PyObject_GC_Del } else { ffi::PyObject_Free }; free(obj as *mut c_void); #[cfg(Py_3_8)] if ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE) != 0 { ffi::Py_DECREF(ty as *mut ffi::PyObject); } } } /// Workaround for Python issue 35810; no longer necessary in Python 3.8 #[inline] #[cfg(not(Py_3_8))] unsafe fn bpo_35810_workaround(py: Python<'_>, ty: *mut ffi::PyTypeObject) { #[cfg(Py_LIMITED_API)] { // Must check version at runtime for abi3 wheels - they could run against a higher version // than the build config suggests. use crate::sync::GILOnceCell; static IS_PYTHON_3_8: GILOnceCell = GILOnceCell::new(); if *IS_PYTHON_3_8.get_or_init(py, || py.version_info() >= (3, 8)) { // No fix needed - the wheel is running on a sufficiently new interpreter. return; } } #[cfg(not(Py_LIMITED_API))] { // suppress unused variable warning let _ = py; } ffi::Py_INCREF(ty as *mut ffi::PyObject); } /// Implementation detail. Only to be used through our proc macro code. /// Method storage for `#[pyclass]`. /// Allows arbitrary `#[pymethod]` blocks to submit their methods, /// which are eventually collected by `#[pyclass]`. #[cfg(feature = "multiple-pymethods")] pub trait PyClassInventory: inventory::Collect { /// Returns the items for a single `#[pymethods] impl` block fn items(&'static self) -> &'static PyClassItems; } // Items from #[pymethods] if not using inventory. #[cfg(not(feature = "multiple-pymethods"))] pub trait PyMethods { fn py_methods(self) -> &'static PyClassItems; } #[cfg(not(feature = "multiple-pymethods"))] impl PyMethods for &'_ PyClassImplCollector { fn py_methods(self) -> &'static PyClassItems { &PyClassItems { methods: &[], slots: &[], } } } // Text signature for __new__ pub trait PyClassNewTextSignature { fn new_text_signature(self) -> Option<&'static str>; } impl PyClassNewTextSignature for &'_ PyClassImplCollector { #[inline] fn new_text_signature(self) -> Option<&'static str> { None } } // Thread checkers #[doc(hidden)] pub trait PyClassThreadChecker: Sized { fn ensure(&self); fn check(&self) -> bool; fn can_drop(&self, py: Python<'_>) -> bool; fn new() -> Self; private_decl! {} } /// Default thread checker for `#[pyclass]`. /// /// Keeping the T: Send bound here slightly improves the compile /// error message to hint to users to figure out what's wrong /// when `#[pyclass]` types do not implement `Send`. #[doc(hidden)] pub struct SendablePyClass(PhantomData); impl PyClassThreadChecker for SendablePyClass { fn ensure(&self) {} fn check(&self) -> bool { true } fn can_drop(&self, _py: Python<'_>) -> bool { true } #[inline] fn new() -> Self { SendablePyClass(PhantomData) } private_impl! {} } /// Thread checker for `#[pyclass(unsendable)]` types. /// Panics when the value is accessed by another thread. #[doc(hidden)] pub struct ThreadCheckerImpl(thread::ThreadId); impl ThreadCheckerImpl { fn ensure(&self, type_name: &'static str) { assert_eq!( thread::current().id(), self.0, "{} is unsendable, but sent to another thread", type_name ); } fn check(&self) -> bool { thread::current().id() == self.0 } fn can_drop(&self, py: Python<'_>, type_name: &'static str) -> bool { if thread::current().id() != self.0 { PyRuntimeError::new_err(format!( "{} is unsendable, but is being dropped on another thread", type_name )) .write_unraisable_bound(py, None); return false; } true } } impl PyClassThreadChecker for ThreadCheckerImpl { fn ensure(&self) { self.ensure(std::any::type_name::()); } fn check(&self) -> bool { self.check() } fn can_drop(&self, py: Python<'_>) -> bool { self.can_drop(py, std::any::type_name::()) } fn new() -> Self { ThreadCheckerImpl(thread::current().id()) } private_impl! {} } /// Trait denoting that this class is suitable to be used as a base type for PyClass. #[cfg_attr( all(diagnostic_namespace, feature = "abi3"), diagnostic::on_unimplemented( note = "with the `abi3` feature enabled, PyO3 does not support subclassing native types" ) )] pub trait PyClassBaseType: Sized { type LayoutAsBase: PyClassObjectLayout; type BaseNativeType; type Initializer: PyObjectInit; type PyClassMutability: PyClassMutability; } /// All mutable PyClasses can be used as a base type. /// /// In the future this will be extended to immutable PyClasses too. impl PyClassBaseType for T { type LayoutAsBase = crate::impl_::pycell::PyClassObject; type BaseNativeType = T::BaseNativeType; type Initializer = crate::pyclass_init::PyClassInitializer; type PyClassMutability = T::PyClassMutability; } /// Implementation of tp_dealloc for pyclasses without gc pub(crate) unsafe extern "C" fn tp_dealloc(obj: *mut ffi::PyObject) { crate::impl_::trampoline::dealloc(obj, PyClassObject::::tp_dealloc) } /// Implementation of tp_dealloc for pyclasses with gc pub(crate) unsafe extern "C" fn tp_dealloc_with_gc(obj: *mut ffi::PyObject) { #[cfg(not(PyPy))] { ffi::PyObject_GC_UnTrack(obj.cast()); } crate::impl_::trampoline::dealloc(obj, PyClassObject::::tp_dealloc) } pub(crate) unsafe extern "C" fn get_sequence_item_from_mapping( obj: *mut ffi::PyObject, index: ffi::Py_ssize_t, ) -> *mut ffi::PyObject { let index = ffi::PyLong_FromSsize_t(index); if index.is_null() { return std::ptr::null_mut(); } let result = ffi::PyObject_GetItem(obj, index); ffi::Py_DECREF(index); result } pub(crate) unsafe extern "C" fn assign_sequence_item_from_mapping( obj: *mut ffi::PyObject, index: ffi::Py_ssize_t, value: *mut ffi::PyObject, ) -> c_int { let index = ffi::PyLong_FromSsize_t(index); if index.is_null() { return -1; } let result = if value.is_null() { ffi::PyObject_DelItem(obj, index) } else { ffi::PyObject_SetItem(obj, index, value) }; ffi::Py_DECREF(index); result } /// Helper trait to locate field within a `#[pyclass]` for a `#[pyo3(get)]`. /// /// Below MSRV 1.77 we can't use `std::mem::offset_of!`, and the replacement in /// `memoffset::offset_of` doesn't work in const contexts for types containing `UnsafeCell`. /// /// # Safety /// /// The trait is unsafe to implement because producing an incorrect offset will lead to UB. pub unsafe trait OffsetCalculator { /// Offset to the field within a `PyClassObject`, in bytes. fn offset() -> usize; } // Used in generated implementations of OffsetCalculator pub fn class_offset() -> usize { offset_of!(PyClassObject, contents) } // Used in generated implementations of OffsetCalculator pub use memoffset::offset_of; /// Type which uses specialization on impl blocks to determine how to read a field from a Rust pyclass /// as part of a `#[pyo3(get)]` annotation. pub struct PyClassGetterGenerator< // structural information about the field: class type, field type, where the field is within the // class struct ClassT: PyClass, FieldT, Offset: OffsetCalculator, // on Rust 1.77+ this could be a const OFFSET: usize // additional metadata about the field which is used to switch between different implementations // at compile time const IS_PY_T: bool, const IMPLEMENTS_TOPYOBJECT: bool, >(PhantomData<(ClassT, FieldT, Offset)>); impl< ClassT: PyClass, FieldT, Offset: OffsetCalculator, const IS_PY_T: bool, const IMPLEMENTS_TOPYOBJECT: bool, > PyClassGetterGenerator { /// Safety: constructing this type requires that there exists a value of type FieldT /// at the calculated offset within the type ClassT. pub const unsafe fn new() -> Self { Self(PhantomData) } } impl< ClassT: PyClass, U, Offset: OffsetCalculator>, const IMPLEMENTS_TOPYOBJECT: bool, > PyClassGetterGenerator, Offset, true, IMPLEMENTS_TOPYOBJECT> { /// `Py` fields have a potential optimization to use Python's "struct members" to read /// the field directly from the struct, rather than using a getter function. /// /// This is the most efficient operation the Python interpreter could possibly do to /// read a field, but it's only possible for us to allow this for frozen classes. pub fn generate(&self, name: &'static CStr, doc: &'static CStr) -> PyMethodDefType { use crate::pyclass::boolean_struct::private::Boolean; if ClassT::Frozen::VALUE { PyMethodDefType::StructMember(ffi::PyMemberDef { name: name.as_ptr(), type_code: ffi::Py_T_OBJECT_EX, offset: Offset::offset() as ffi::Py_ssize_t, flags: ffi::Py_READONLY, doc: doc.as_ptr(), }) } else { PyMethodDefType::Getter(crate::PyGetterDef { name, meth: pyo3_get_value_topyobject::, Offset>, doc, }) } } } /// Field is not `Py`; try to use `ToPyObject` to avoid potentially expensive clones of containers like `Vec` impl> PyClassGetterGenerator { pub const fn generate(&self, name: &'static CStr, doc: &'static CStr) -> PyMethodDefType { PyMethodDefType::Getter(crate::PyGetterDef { name, meth: pyo3_get_value_topyobject::, doc, }) } } #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot be converted to a Python object", label = "required by `#[pyo3(get)]` to create a readable property from a field of type `{Self}`", note = "implement `ToPyObject` or `IntoPy + Clone` for `{Self}` to define the conversion", ) )] pub trait PyO3GetField: IntoPy> + Clone {} impl> + Clone> PyO3GetField for T {} /// Base case attempts to use IntoPy + Clone, which was the only behaviour before PyO3 0.22. impl> PyClassGetterGenerator { pub const fn generate(&self, name: &'static CStr, doc: &'static CStr) -> PyMethodDefType // The bound goes here rather than on the block so that this impl is always available // if no specialization is used instead where FieldT: PyO3GetField, { PyMethodDefType::Getter(crate::PyGetterDef { name, meth: pyo3_get_value::, doc, }) } } /// Trait used to combine with zero-sized types to calculate at compile time /// some property of a type. /// /// The trick uses the fact that an associated constant has higher priority /// than a trait constant, so we can use the trait to define the false case. /// /// The true case is defined in the zero-sized type's impl block, which is /// gated on some property like trait bound or only being implemented /// for fixed concrete types. pub trait Probe { const VALUE: bool = false; } macro_rules! probe { ($name:ident) => { pub struct $name(PhantomData); impl Probe for $name {} }; } probe!(IsPyT); impl IsPyT> { pub const VALUE: bool = true; } probe!(IsToPyObject); impl IsToPyObject { pub const VALUE: bool = true; } fn pyo3_get_value_topyobject< ClassT: PyClass, FieldT: ToPyObject, Offset: OffsetCalculator, >( py: Python<'_>, obj: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { // Check for mutable aliasing let _holder = unsafe { BoundRef::ref_from_ptr(py, &obj) .downcast_unchecked::() .try_borrow()? }; let value = unsafe { obj.cast::().add(Offset::offset()).cast::() }; // SAFETY: Offset is known to describe the location of the value, and // _holder is preventing mutable aliasing Ok((unsafe { &*value }).to_object(py).into_ptr()) } fn pyo3_get_value< ClassT: PyClass, FieldT: IntoPy> + Clone, Offset: OffsetCalculator, >( py: Python<'_>, obj: *mut ffi::PyObject, ) -> PyResult<*mut ffi::PyObject> { // Check for mutable aliasing let _holder = unsafe { BoundRef::ref_from_ptr(py, &obj) .downcast_unchecked::() .try_borrow()? }; let value = unsafe { obj.cast::().add(Offset::offset()).cast::() }; // SAFETY: Offset is known to describe the location of the value, and // _holder is preventing mutable aliasing Ok((unsafe { &*value }).clone().into_py(py).into_ptr()) } #[cfg(test)] #[cfg(feature = "macros")] mod tests { use super::*; #[test] fn get_py_for_frozen_class() { #[crate::pyclass(crate = "crate", frozen)] struct FrozenClass { #[pyo3(get)] value: Py, } let mut methods = Vec::new(); let mut slots = Vec::new(); for items in FrozenClass::items_iter() { methods.extend(items.methods.iter().map(|m| match m { MaybeRuntimePyMethodDef::Static(m) => m.clone(), MaybeRuntimePyMethodDef::Runtime(r) => r(), })); slots.extend_from_slice(items.slots); } assert_eq!(methods.len(), 1); assert!(slots.is_empty()); match methods.first() { Some(PyMethodDefType::StructMember(member)) => { assert_eq!(unsafe { CStr::from_ptr(member.name) }, ffi::c_str!("value")); assert_eq!(member.type_code, ffi::Py_T_OBJECT_EX); assert_eq!( member.offset, (memoffset::offset_of!(PyClassObject, contents) + memoffset::offset_of!(FrozenClass, value)) as ffi::Py_ssize_t ); assert_eq!(member.flags, ffi::Py_READONLY); } _ => panic!("Expected a StructMember"), } } #[test] fn get_py_for_non_frozen_class() { #[crate::pyclass(crate = "crate")] struct FrozenClass { #[pyo3(get)] value: Py, } let mut methods = Vec::new(); let mut slots = Vec::new(); for items in FrozenClass::items_iter() { methods.extend(items.methods.iter().map(|m| match m { MaybeRuntimePyMethodDef::Static(m) => m.clone(), MaybeRuntimePyMethodDef::Runtime(r) => r(), })); slots.extend_from_slice(items.slots); } assert_eq!(methods.len(), 1); assert!(slots.is_empty()); match methods.first() { Some(PyMethodDefType::Getter(getter)) => { assert_eq!(getter.name, ffi::c_str!("value")); assert_eq!(getter.doc, ffi::c_str!("")); // tests for the function pointer are in test_getter_setter.py } _ => panic!("Expected a StructMember"), } } } pyo3/src/impl_/pycell.rs0000644000175000017500000000026614661133735016164 0ustar jamespagejamespage//! Externally-accessible implementation of pycell pub use crate::pycell::impl_::{ GetBorrowChecker, PyClassMutability, PyClassObject, PyClassObjectBase, PyClassObjectLayout, }; pyo3/src/impl_/wrap.rs0000644000175000017500000000502714661133735015645 0ustar jamespagejamespageuse std::convert::Infallible; use crate::{ffi, IntoPy, PyObject, PyResult, Python}; /// Used to wrap values in `Option` for default arguments. pub trait SomeWrap { fn wrap(self) -> Option; } impl SomeWrap for T { fn wrap(self) -> Option { Some(self) } } impl SomeWrap for Option { fn wrap(self) -> Self { self } } /// Used to wrap the result of `#[pyfunction]` and `#[pymethods]`. #[cfg_attr( diagnostic_namespace, diagnostic::on_unimplemented( message = "`{Self}` cannot be converted to a Python object", note = "`IntoPy` is automatically implemented by the `#[pyclass]` macro", note = "if you do not wish to have a corresponding Python type, implement `IntoPy` manually", note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`" ) )] pub trait OkWrap { type Error; fn wrap(self) -> Result; } // The T: IntoPy bound here is necessary to prevent the // implementation for Result from conflicting impl OkWrap for T where T: IntoPy, { type Error = Infallible; #[inline] fn wrap(self) -> Result { Ok(self) } } impl OkWrap for Result where T: IntoPy, { type Error = E; #[inline] fn wrap(self) -> Result { self } } /// This is a follow-up function to `OkWrap::wrap` that converts the result into /// a `*mut ffi::PyObject` pointer. pub fn map_result_into_ptr>( py: Python<'_>, result: PyResult, ) -> PyResult<*mut ffi::PyObject> { result.map(|obj| obj.into_py(py).into_ptr()) } /// This is a follow-up function to `OkWrap::wrap` that converts the result into /// a safe wrapper. pub fn map_result_into_py>( py: Python<'_>, result: PyResult, ) -> PyResult { result.map(|err| err.into_py(py)) } #[cfg(test)] mod tests { use super::*; #[test] fn wrap_option() { let a: Option = SomeWrap::wrap(42); assert_eq!(a, Some(42)); let b: Option = SomeWrap::wrap(None); assert_eq!(b, None); } #[test] fn wrap_result() { let a: Result = OkWrap::wrap(42u8); assert!(matches!(a, Ok(42))); let b: PyResult = OkWrap::wrap(Ok(42u8)); assert!(matches!(b, Ok(42))); let c: Result = OkWrap::wrap(Err("error")); assert_eq!(c, Err("error")); } } pyo3/src/impl_/frompyobject.rs0000644000175000017500000001057714661133735017405 0ustar jamespagejamespageuse crate::types::any::PyAnyMethods; use crate::Bound; use crate::{exceptions::PyTypeError, FromPyObject, PyAny, PyErr, PyResult, Python}; pub enum Extractor<'a, 'py, T> { Bound(fn(&'a Bound<'py, PyAny>) -> PyResult), #[cfg(feature = "gil-refs")] GilRef(fn(&'a PyAny) -> PyResult), } impl<'a, 'py, T> From) -> PyResult> for Extractor<'a, 'py, T> { fn from(value: fn(&'a Bound<'py, PyAny>) -> PyResult) -> Self { Self::Bound(value) } } #[cfg(feature = "gil-refs")] impl<'a, T> From PyResult> for Extractor<'a, '_, T> { fn from(value: fn(&'a PyAny) -> PyResult) -> Self { Self::GilRef(value) } } impl<'a, 'py, T> Extractor<'a, 'py, T> { pub(crate) fn call(self, obj: &'a Bound<'py, PyAny>) -> PyResult { match self { Extractor::Bound(f) => f(obj), #[cfg(feature = "gil-refs")] Extractor::GilRef(f) => f(obj.as_gil_ref()), } } } #[cold] pub fn failed_to_extract_enum( py: Python<'_>, type_name: &str, variant_names: &[&str], error_names: &[&str], errors: &[PyErr], ) -> PyErr { // TODO maybe use ExceptionGroup on Python 3.11+ ? let mut err_msg = format!( "failed to extract enum {} ('{}')", type_name, error_names.join(" | ") ); for ((variant_name, error_name), error) in variant_names.iter().zip(error_names).zip(errors) { use std::fmt::Write; write!( &mut err_msg, "\n- variant {variant_name} ({error_name}): {error_msg}", variant_name = variant_name, error_name = error_name, error_msg = extract_traceback(py, error.clone_ref(py)), ) .unwrap(); } PyTypeError::new_err(err_msg) } /// Flattens a chain of errors into a single string. fn extract_traceback(py: Python<'_>, mut error: PyErr) -> String { use std::fmt::Write; let mut error_msg = error.to_string(); while let Some(cause) = error.cause(py) { write!(&mut error_msg, ", caused by {}", cause).unwrap(); error = cause } error_msg } pub fn extract_struct_field<'py, T>( obj: &Bound<'py, PyAny>, struct_name: &str, field_name: &str, ) -> PyResult where T: FromPyObject<'py>, { match obj.extract() { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_struct_field( obj.py(), err, struct_name, field_name, )), } } pub fn extract_struct_field_with<'a, 'py, T>( extractor: impl Into>, obj: &'a Bound<'py, PyAny>, struct_name: &str, field_name: &str, ) -> PyResult { match extractor.into().call(obj) { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_struct_field( obj.py(), err, struct_name, field_name, )), } } #[cold] fn failed_to_extract_struct_field( py: Python<'_>, inner_err: PyErr, struct_name: &str, field_name: &str, ) -> PyErr { let new_err = PyTypeError::new_err(format!( "failed to extract field {}.{}", struct_name, field_name )); new_err.set_cause(py, ::std::option::Option::Some(inner_err)); new_err } pub fn extract_tuple_struct_field<'py, T>( obj: &Bound<'py, PyAny>, struct_name: &str, index: usize, ) -> PyResult where T: FromPyObject<'py>, { match obj.extract() { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_tuple_struct_field( obj.py(), err, struct_name, index, )), } } pub fn extract_tuple_struct_field_with<'a, 'py, T>( extractor: impl Into>, obj: &'a Bound<'py, PyAny>, struct_name: &str, index: usize, ) -> PyResult { match extractor.into().call(obj) { Ok(value) => Ok(value), Err(err) => Err(failed_to_extract_tuple_struct_field( obj.py(), err, struct_name, index, )), } } #[cold] fn failed_to_extract_tuple_struct_field( py: Python<'_>, inner_err: PyErr, struct_name: &str, index: usize, ) -> PyErr { let new_err = PyTypeError::new_err(format!("failed to extract field {}.{}", struct_name, index)); new_err.set_cause(py, ::std::option::Option::Some(inner_err)); new_err } pyo3/src/impl_/freelist.rs0000644000175000017500000000350314661133735016506 0ustar jamespagejamespage//! Support for [free allocation lists][1]. //! //! This can improve performance for types that are often created and deleted in quick succession. //! //! Rather than implementing this manually, //! implement it by annotating a struct with `#[pyclass(freelist = N)]`, //! where `N` is the size of the freelist. //! //! [1]: https://en.wikipedia.org/wiki/Free_list use std::mem; /// Represents a slot of a [`FreeList`]. pub enum Slot { /// A free slot. Empty, /// An allocated slot. Filled(T), } /// A free allocation list. /// /// See [the parent module](crate::impl_::freelist) for more details. pub struct FreeList { entries: Vec>, split: usize, capacity: usize, } impl FreeList { /// Creates a new `FreeList` instance with specified capacity. pub fn with_capacity(capacity: usize) -> FreeList { let entries = (0..capacity).map(|_| Slot::Empty).collect::>(); FreeList { entries, split: 0, capacity, } } /// Pops the first non empty item. pub fn pop(&mut self) -> Option { let idx = self.split; if idx == 0 { None } else { match mem::replace(&mut self.entries[idx - 1], Slot::Empty) { Slot::Filled(v) => { self.split = idx - 1; Some(v) } _ => panic!("FreeList is corrupt"), } } } /// Inserts a value into the list. Returns `Some(val)` if the `FreeList` is full. pub fn insert(&mut self, val: T) -> Option { let next = self.split + 1; if next < self.capacity { self.entries[self.split] = Slot::Filled(val); self.split = next; None } else { Some(val) } } } pyo3/src/impl_/panic.rs0000644000175000017500000000112514661133735015761 0ustar jamespagejamespage/// Type which will panic if dropped. /// /// If this is dropped during a panic, this will cause an abort. /// /// Use this to avoid letting unwinds cross through the FFI boundary, which is UB. pub struct PanicTrap { msg: &'static str, } impl PanicTrap { #[inline] pub const fn new(msg: &'static str) -> Self { Self { msg } } #[inline] pub const fn disarm(self) { std::mem::forget(self) } } impl Drop for PanicTrap { fn drop(&mut self) { // Panic here will abort the process, assuming in an unwind. panic!("{}", self.msg) } } pyo3/src/impl_/deprecations.rs0000644000175000017500000000363314661133735017355 0ustar jamespagejamespage//! Symbols used to denote deprecated usages of PyO3's proc macros. use crate::{PyResult, Python}; #[deprecated(since = "0.20.0", note = "use `#[new]` instead of `#[__new__]`")] pub const PYMETHODS_NEW_DEPRECATED_FORM: () = (); pub fn inspect_type(t: T, _: &GilRefs) -> T { t } pub fn inspect_fn(f: fn(A) -> PyResult, _: &GilRefs) -> fn(A) -> PyResult { f } pub struct GilRefs(OptionGilRefs); pub struct OptionGilRefs(NotAGilRef); pub struct NotAGilRef(std::marker::PhantomData); pub trait IsGilRef {} #[cfg(feature = "gil-refs")] impl IsGilRef for &'_ T {} impl GilRefs { #[allow(clippy::new_without_default)] pub fn new() -> Self { GilRefs(OptionGilRefs(NotAGilRef(std::marker::PhantomData))) } } impl GilRefs> { #[deprecated(since = "0.21.0", note = "use `wrap_pyfunction_bound!` instead")] pub fn is_python(&self) {} } impl GilRefs { #[deprecated( since = "0.21.0", note = "use `&Bound<'_, T>` instead for this function argument" )] pub fn function_arg(&self) {} #[deprecated( since = "0.21.0", note = "use `&Bound<'_, PyAny>` as the argument for this `from_py_with` extractor" )] pub fn from_py_with_arg(&self) {} } impl OptionGilRefs> { #[deprecated( since = "0.21.0", note = "use `Option<&Bound<'_, T>>` instead for this function argument" )] pub fn function_arg(&self) {} } impl NotAGilRef { pub fn function_arg(&self) {} pub fn from_py_with_arg(&self) {} pub fn is_python(&self) {} } impl std::ops::Deref for GilRefs { type Target = OptionGilRefs; fn deref(&self) -> &Self::Target { &self.0 } } impl std::ops::Deref for OptionGilRefs { type Target = NotAGilRef; fn deref(&self) -> &Self::Target { &self.0 } } pyo3/src/pyclass.rs0000644000175000017500000001660414661133735015255 0ustar jamespagejamespage//! `PyClass` and related traits. use crate::{ callback::IntoPyCallbackOutput, ffi, impl_::pyclass::PyClassImpl, IntoPy, PyObject, PyResult, PyTypeInfo, Python, }; use std::{cmp::Ordering, os::raw::c_int}; mod create_type_object; mod gc; pub(crate) use self::create_type_object::{create_type_object, PyClassTypeObject}; pub use self::gc::{PyTraverseError, PyVisit}; /// Types that can be used as Python classes. /// /// The `#[pyclass]` attribute implements this trait for your Rust struct - /// you shouldn't implement this trait directly. #[allow(deprecated)] #[cfg(feature = "gil-refs")] pub trait PyClass: PyTypeInfo> + PyClassImpl { /// Whether the pyclass is frozen. /// /// This can be enabled via `#[pyclass(frozen)]`. type Frozen: Frozen; } /// Types that can be used as Python classes. /// /// The `#[pyclass]` attribute implements this trait for your Rust struct - /// you shouldn't implement this trait directly. #[cfg(not(feature = "gil-refs"))] pub trait PyClass: PyTypeInfo + PyClassImpl { /// Whether the pyclass is frozen. /// /// This can be enabled via `#[pyclass(frozen)]`. type Frozen: Frozen; } /// Operators for the `__richcmp__` method #[derive(Debug, Clone, Copy)] pub enum CompareOp { /// The *less than* operator. Lt = ffi::Py_LT as isize, /// The *less than or equal to* operator. Le = ffi::Py_LE as isize, /// The equality operator. Eq = ffi::Py_EQ as isize, /// The *not equal to* operator. Ne = ffi::Py_NE as isize, /// The *greater than* operator. Gt = ffi::Py_GT as isize, /// The *greater than or equal to* operator. Ge = ffi::Py_GE as isize, } impl CompareOp { /// Conversion from the C enum. pub fn from_raw(op: c_int) -> Option { match op { ffi::Py_LT => Some(CompareOp::Lt), ffi::Py_LE => Some(CompareOp::Le), ffi::Py_EQ => Some(CompareOp::Eq), ffi::Py_NE => Some(CompareOp::Ne), ffi::Py_GT => Some(CompareOp::Gt), ffi::Py_GE => Some(CompareOp::Ge), _ => None, } } /// Returns if a Rust [`std::cmp::Ordering`] matches this ordering query. /// /// Usage example: /// /// ```rust /// # use pyo3::prelude::*; /// # use pyo3::class::basic::CompareOp; /// /// #[pyclass] /// struct Size { /// size: usize, /// } /// /// #[pymethods] /// impl Size { /// fn __richcmp__(&self, other: &Size, op: CompareOp) -> bool { /// op.matches(self.size.cmp(&other.size)) /// } /// } /// ``` pub fn matches(&self, result: Ordering) -> bool { match self { CompareOp::Eq => result == Ordering::Equal, CompareOp::Ne => result != Ordering::Equal, CompareOp::Lt => result == Ordering::Less, CompareOp::Le => result != Ordering::Greater, CompareOp::Gt => result == Ordering::Greater, CompareOp::Ge => result != Ordering::Less, } } } /// Output of `__next__` which can either `yield` the next value in the iteration, or /// `return` a value to raise `StopIteration` in Python. /// /// Usage example: /// /// ```rust /// # #![allow(deprecated)] /// use pyo3::prelude::*; /// use pyo3::iter::IterNextOutput; /// /// #[pyclass] /// struct PyClassIter { /// count: usize, /// } /// /// #[pymethods] /// impl PyClassIter { /// #[new] /// pub fn new() -> Self { /// PyClassIter { count: 0 } /// } /// /// fn __next__(&mut self) -> IterNextOutput { /// if self.count < 5 { /// self.count += 1; /// // Given an instance `counter`, First five `next(counter)` calls yield 1, 2, 3, 4, 5. /// IterNextOutput::Yield(self.count) /// } else { /// // At the sixth time, we get a `StopIteration` with `'Ended'`. /// // try: /// // next(counter) /// // except StopIteration as e: /// // assert e.value == 'Ended' /// IterNextOutput::Return("Ended") /// } /// } /// } /// ``` #[deprecated(since = "0.21.0", note = "Use `Option` or `PyStopIteration` instead.")] pub enum IterNextOutput { /// The value yielded by the iterator. Yield(T), /// The `StopIteration` object. Return(U), } /// Alias of `IterNextOutput` with `PyObject` yield & return values. #[deprecated(since = "0.21.0", note = "Use `Option` or `PyStopIteration` instead.")] #[allow(deprecated)] pub type PyIterNextOutput = IterNextOutput; #[allow(deprecated)] impl IntoPyCallbackOutput<*mut ffi::PyObject> for IterNextOutput where T: IntoPy, U: IntoPy, { fn convert(self, py: Python<'_>) -> PyResult<*mut ffi::PyObject> { match self { IterNextOutput::Yield(o) => Ok(o.into_py(py).into_ptr()), IterNextOutput::Return(o) => { Err(crate::exceptions::PyStopIteration::new_err(o.into_py(py))) } } } } /// Output of `__anext__`. /// /// #[deprecated( since = "0.21.0", note = "Use `Option` or `PyStopAsyncIteration` instead." )] pub enum IterANextOutput { /// An expression which the generator yielded. Yield(T), /// A `StopAsyncIteration` object. Return(U), } /// An [IterANextOutput] of Python objects. #[deprecated( since = "0.21.0", note = "Use `Option` or `PyStopAsyncIteration` instead." )] #[allow(deprecated)] pub type PyIterANextOutput = IterANextOutput; #[allow(deprecated)] impl IntoPyCallbackOutput<*mut ffi::PyObject> for IterANextOutput where T: IntoPy, U: IntoPy, { fn convert(self, py: Python<'_>) -> PyResult<*mut ffi::PyObject> { match self { IterANextOutput::Yield(o) => Ok(o.into_py(py).into_ptr()), IterANextOutput::Return(o) => Err(crate::exceptions::PyStopAsyncIteration::new_err( o.into_py(py), )), } } } /// A workaround for [associated const equality](https://github.com/rust-lang/rust/issues/92827). /// /// This serves to have True / False values in the [`PyClass`] trait's `Frozen` type. #[doc(hidden)] pub mod boolean_struct { pub(crate) mod private { use super::*; /// A way to "seal" the boolean traits. pub trait Boolean { const VALUE: bool; } impl Boolean for True { const VALUE: bool = true; } impl Boolean for False { const VALUE: bool = false; } } pub struct True(()); pub struct False(()); } /// A trait which is used to describe whether a `#[pyclass]` is frozen. #[doc(hidden)] pub trait Frozen: boolean_struct::private::Boolean {} impl Frozen for boolean_struct::True {} impl Frozen for boolean_struct::False {} mod tests { #[test] fn test_compare_op_matches() { use super::CompareOp; use std::cmp::Ordering; assert!(CompareOp::Eq.matches(Ordering::Equal)); assert!(CompareOp::Ne.matches(Ordering::Less)); assert!(CompareOp::Ge.matches(Ordering::Greater)); assert!(CompareOp::Gt.matches(Ordering::Greater)); assert!(CompareOp::Le.matches(Ordering::Equal)); assert!(CompareOp::Lt.matches(Ordering::Less)); } } pyo3/src/impl_.rs0000644000175000017500000000124014661133735014665 0ustar jamespagejamespage#![allow(missing_docs)] //! Internals of PyO3 which are accessed by code expanded from PyO3's procedural macros. //! //! Usage of any of these APIs in downstream code is implicitly acknowledging that these //! APIs may may change at any time without documentation in the CHANGELOG and without //! breaking semver guarantees. #[cfg(feature = "experimental-async")] pub mod coroutine; pub mod deprecations; pub mod exceptions; pub mod extract_argument; pub mod freelist; pub mod frompyobject; pub(crate) mod not_send; pub mod panic; pub mod pycell; pub mod pyclass; pub mod pyfunction; pub mod pymethods; pub mod pymodule; #[doc(hidden)] pub mod trampoline; pub mod wrap; pyo3/src/test_utils.rs0000644000175000017500000000006314661133735015766 0ustar jamespagejamespageuse crate as pyo3; include!("../tests/common.rs"); pyo3/src/pybacked.rs0000644000175000017500000004133014661133735015353 0ustar jamespagejamespage//! Contains types for working with Python objects that own the underlying data. use std::{ops::Deref, ptr::NonNull, sync::Arc}; use crate::{ types::{ any::PyAnyMethods, bytearray::PyByteArrayMethods, bytes::PyBytesMethods, string::PyStringMethods, PyByteArray, PyBytes, PyString, }, Bound, DowncastError, FromPyObject, IntoPy, Py, PyAny, PyErr, PyResult, Python, ToPyObject, }; /// A wrapper around `str` where the storage is owned by a Python `bytes` or `str` object. /// /// This type gives access to the underlying data via a `Deref` implementation. #[cfg_attr(feature = "py-clone", derive(Clone))] pub struct PyBackedStr { #[allow(dead_code)] // only held so that the storage is not dropped storage: Py, data: NonNull, } impl Deref for PyBackedStr { type Target = str; fn deref(&self) -> &str { // Safety: `data` is known to be immutable and owned by self unsafe { self.data.as_ref() } } } impl AsRef for PyBackedStr { fn as_ref(&self) -> &str { self } } impl AsRef<[u8]> for PyBackedStr { fn as_ref(&self) -> &[u8] { self.as_bytes() } } // Safety: the underlying Python str (or bytes) is immutable and // safe to share between threads unsafe impl Send for PyBackedStr {} unsafe impl Sync for PyBackedStr {} impl std::fmt::Display for PyBackedStr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.deref().fmt(f) } } impl_traits!(PyBackedStr, str); impl TryFrom> for PyBackedStr { type Error = PyErr; fn try_from(py_string: Bound<'_, PyString>) -> Result { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] { let s = py_string.to_str()?; let data = NonNull::from(s); Ok(Self { storage: py_string.as_any().to_owned().unbind(), data, }) } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] { let bytes = py_string.encode_utf8()?; let s = unsafe { std::str::from_utf8_unchecked(bytes.as_bytes()) }; let data = NonNull::from(s); Ok(Self { storage: bytes.into_any().unbind(), data, }) } } } impl FromPyObject<'_> for PyBackedStr { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let py_string = obj.downcast::()?.to_owned(); Self::try_from(py_string) } } impl ToPyObject for PyBackedStr { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn to_object(&self, py: Python<'_>) -> Py { self.storage.clone_ref(py) } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] fn to_object(&self, py: Python<'_>) -> Py { PyString::new_bound(py, self).into_any().unbind() } } impl IntoPy> for PyBackedStr { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn into_py(self, _py: Python<'_>) -> Py { self.storage } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] fn into_py(self, py: Python<'_>) -> Py { PyString::new_bound(py, &self).into_any().unbind() } } /// A wrapper around `[u8]` where the storage is either owned by a Python `bytes` object, or a Rust `Box<[u8]>`. /// /// This type gives access to the underlying data via a `Deref` implementation. #[cfg_attr(feature = "py-clone", derive(Clone))] pub struct PyBackedBytes { #[allow(dead_code)] // only held so that the storage is not dropped storage: PyBackedBytesStorage, data: NonNull<[u8]>, } #[allow(dead_code)] #[cfg_attr(feature = "py-clone", derive(Clone))] enum PyBackedBytesStorage { Python(Py), Rust(Arc<[u8]>), } impl Deref for PyBackedBytes { type Target = [u8]; fn deref(&self) -> &[u8] { // Safety: `data` is known to be immutable and owned by self unsafe { self.data.as_ref() } } } impl AsRef<[u8]> for PyBackedBytes { fn as_ref(&self) -> &[u8] { self } } // Safety: the underlying Python bytes or Rust bytes is immutable and // safe to share between threads unsafe impl Send for PyBackedBytes {} unsafe impl Sync for PyBackedBytes {} impl PartialEq<[u8; N]> for PyBackedBytes { fn eq(&self, other: &[u8; N]) -> bool { self.deref() == other } } impl PartialEq for [u8; N] { fn eq(&self, other: &PyBackedBytes) -> bool { self == other.deref() } } impl PartialEq<&[u8; N]> for PyBackedBytes { fn eq(&self, other: &&[u8; N]) -> bool { self.deref() == *other } } impl PartialEq for &[u8; N] { fn eq(&self, other: &PyBackedBytes) -> bool { self == &other.deref() } } impl_traits!(PyBackedBytes, [u8]); impl From> for PyBackedBytes { fn from(py_bytes: Bound<'_, PyBytes>) -> Self { let b = py_bytes.as_bytes(); let data = NonNull::from(b); Self { storage: PyBackedBytesStorage::Python(py_bytes.to_owned().unbind()), data, } } } impl From> for PyBackedBytes { fn from(py_bytearray: Bound<'_, PyByteArray>) -> Self { let s = Arc::<[u8]>::from(py_bytearray.to_vec()); let data = NonNull::from(s.as_ref()); Self { storage: PyBackedBytesStorage::Rust(s), data, } } } impl FromPyObject<'_> for PyBackedBytes { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { if let Ok(bytes) = obj.downcast::() { Ok(Self::from(bytes.to_owned())) } else if let Ok(bytearray) = obj.downcast::() { Ok(Self::from(bytearray.to_owned())) } else { Err(DowncastError::new(obj, "`bytes` or `bytearray`").into()) } } } impl ToPyObject for PyBackedBytes { fn to_object(&self, py: Python<'_>) -> Py { match &self.storage { PyBackedBytesStorage::Python(bytes) => bytes.to_object(py), PyBackedBytesStorage::Rust(bytes) => PyBytes::new_bound(py, bytes).into_any().unbind(), } } } impl IntoPy> for PyBackedBytes { fn into_py(self, py: Python<'_>) -> Py { match self.storage { PyBackedBytesStorage::Python(bytes) => bytes.into_any(), PyBackedBytesStorage::Rust(bytes) => PyBytes::new_bound(py, &bytes).into_any().unbind(), } } } macro_rules! impl_traits { ($slf:ty, $equiv:ty) => { impl std::fmt::Debug for $slf { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.deref().fmt(f) } } impl PartialEq for $slf { fn eq(&self, other: &Self) -> bool { self.deref() == other.deref() } } impl PartialEq<$equiv> for $slf { fn eq(&self, other: &$equiv) -> bool { self.deref() == other } } impl PartialEq<&$equiv> for $slf { fn eq(&self, other: &&$equiv) -> bool { self.deref() == *other } } impl PartialEq<$slf> for $equiv { fn eq(&self, other: &$slf) -> bool { self == other.deref() } } impl PartialEq<$slf> for &$equiv { fn eq(&self, other: &$slf) -> bool { self == &other.deref() } } impl Eq for $slf {} impl PartialOrd for $slf { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl PartialOrd<$equiv> for $slf { fn partial_cmp(&self, other: &$equiv) -> Option { self.deref().partial_cmp(other) } } impl PartialOrd<$slf> for $equiv { fn partial_cmp(&self, other: &$slf) -> Option { self.partial_cmp(other.deref()) } } impl Ord for $slf { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.deref().cmp(other.deref()) } } impl std::hash::Hash for $slf { fn hash(&self, state: &mut H) { self.deref().hash(state) } } }; } use impl_traits; #[cfg(test)] mod test { use super::*; use crate::Python; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; #[test] fn py_backed_str_empty() { Python::with_gil(|py| { let s = PyString::new_bound(py, ""); let py_backed_str = s.extract::().unwrap(); assert_eq!(&*py_backed_str, ""); }); } #[test] fn py_backed_str() { Python::with_gil(|py| { let s = PyString::new_bound(py, "hello"); let py_backed_str = s.extract::().unwrap(); assert_eq!(&*py_backed_str, "hello"); }); } #[test] fn py_backed_str_try_from() { Python::with_gil(|py| { let s = PyString::new_bound(py, "hello"); let py_backed_str = PyBackedStr::try_from(s).unwrap(); assert_eq!(&*py_backed_str, "hello"); }); } #[test] fn py_backed_str_to_object() { Python::with_gil(|py| { let orig_str = PyString::new_bound(py, "hello"); let py_backed_str = orig_str.extract::().unwrap(); let new_str = py_backed_str.to_object(py); assert_eq!(new_str.extract::(py).unwrap(), "hello"); #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] assert!(new_str.is(&orig_str)); }); } #[test] fn py_backed_str_into_py() { Python::with_gil(|py| { let orig_str = PyString::new_bound(py, "hello"); let py_backed_str = orig_str.extract::().unwrap(); let new_str = py_backed_str.into_py(py); assert_eq!(new_str.extract::(py).unwrap(), "hello"); #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] assert!(new_str.is(&orig_str)); }); } #[test] fn py_backed_bytes_empty() { Python::with_gil(|py| { let b = PyBytes::new_bound(py, b""); let py_backed_bytes = b.extract::().unwrap(); assert_eq!(&*py_backed_bytes, b""); }); } #[test] fn py_backed_bytes() { Python::with_gil(|py| { let b = PyBytes::new_bound(py, b"abcde"); let py_backed_bytes = b.extract::().unwrap(); assert_eq!(&*py_backed_bytes, b"abcde"); }); } #[test] fn py_backed_bytes_from_bytes() { Python::with_gil(|py| { let b = PyBytes::new_bound(py, b"abcde"); let py_backed_bytes = PyBackedBytes::from(b); assert_eq!(&*py_backed_bytes, b"abcde"); }); } #[test] fn py_backed_bytes_from_bytearray() { Python::with_gil(|py| { let b = PyByteArray::new_bound(py, b"abcde"); let py_backed_bytes = PyBackedBytes::from(b); assert_eq!(&*py_backed_bytes, b"abcde"); }); } #[test] fn py_backed_bytes_into_py() { Python::with_gil(|py| { let orig_bytes = PyBytes::new_bound(py, b"abcde"); let py_backed_bytes = PyBackedBytes::from(orig_bytes.clone()); assert!(py_backed_bytes.to_object(py).is(&orig_bytes)); assert!(py_backed_bytes.into_py(py).is(&orig_bytes)); }); } #[test] fn rust_backed_bytes_into_py() { Python::with_gil(|py| { let orig_bytes = PyByteArray::new_bound(py, b"abcde"); let rust_backed_bytes = PyBackedBytes::from(orig_bytes); assert!(matches!( rust_backed_bytes.storage, PyBackedBytesStorage::Rust(_) )); let to_object = rust_backed_bytes.to_object(py).into_bound(py); assert!(&to_object.is_exact_instance_of::()); assert_eq!(&to_object.extract::().unwrap(), b"abcde"); let into_py = rust_backed_bytes.into_py(py).into_bound(py); assert!(&into_py.is_exact_instance_of::()); assert_eq!(&into_py.extract::().unwrap(), b"abcde"); }); } #[test] fn test_backed_types_send_sync() { fn is_send() {} fn is_sync() {} is_send::(); is_sync::(); is_send::(); is_sync::(); } #[cfg(feature = "py-clone")] #[test] fn test_backed_str_clone() { Python::with_gil(|py| { let s1: PyBackedStr = PyString::new_bound(py, "hello").try_into().unwrap(); let s2 = s1.clone(); assert_eq!(s1, s2); drop(s1); assert_eq!(s2, "hello"); }); } #[test] fn test_backed_str_eq() { Python::with_gil(|py| { let s1: PyBackedStr = PyString::new_bound(py, "hello").try_into().unwrap(); let s2: PyBackedStr = PyString::new_bound(py, "hello").try_into().unwrap(); assert_eq!(s1, "hello"); assert_eq!(s1, s2); let s3: PyBackedStr = PyString::new_bound(py, "abcde").try_into().unwrap(); assert_eq!("abcde", s3); assert_ne!(s1, s3); }); } #[test] fn test_backed_str_hash() { Python::with_gil(|py| { let h = { let mut hasher = DefaultHasher::new(); "abcde".hash(&mut hasher); hasher.finish() }; let s1: PyBackedStr = PyString::new_bound(py, "abcde").try_into().unwrap(); let h1 = { let mut hasher = DefaultHasher::new(); s1.hash(&mut hasher); hasher.finish() }; assert_eq!(h, h1); }); } #[test] fn test_backed_str_ord() { Python::with_gil(|py| { let mut a = vec!["a", "c", "d", "b", "f", "g", "e"]; let mut b = a .iter() .map(|s| PyString::new_bound(py, s).try_into().unwrap()) .collect::>(); a.sort(); b.sort(); assert_eq!(a, b); }) } #[cfg(feature = "py-clone")] #[test] fn test_backed_bytes_from_bytes_clone() { Python::with_gil(|py| { let b1: PyBackedBytes = PyBytes::new_bound(py, b"abcde").into(); let b2 = b1.clone(); assert_eq!(b1, b2); drop(b1); assert_eq!(b2, b"abcde"); }); } #[cfg(feature = "py-clone")] #[test] fn test_backed_bytes_from_bytearray_clone() { Python::with_gil(|py| { let b1: PyBackedBytes = PyByteArray::new_bound(py, b"abcde").into(); let b2 = b1.clone(); assert_eq!(b1, b2); drop(b1); assert_eq!(b2, b"abcde"); }); } #[test] fn test_backed_bytes_eq() { Python::with_gil(|py| { let b1: PyBackedBytes = PyBytes::new_bound(py, b"abcde").into(); let b2: PyBackedBytes = PyByteArray::new_bound(py, b"abcde").into(); assert_eq!(b1, b"abcde"); assert_eq!(b1, b2); let b3: PyBackedBytes = PyBytes::new_bound(py, b"hello").into(); assert_eq!(b"hello", b3); assert_ne!(b1, b3); }); } #[test] fn test_backed_bytes_hash() { Python::with_gil(|py| { let h = { let mut hasher = DefaultHasher::new(); b"abcde".hash(&mut hasher); hasher.finish() }; let b1: PyBackedBytes = PyBytes::new_bound(py, b"abcde").into(); let h1 = { let mut hasher = DefaultHasher::new(); b1.hash(&mut hasher); hasher.finish() }; let b2: PyBackedBytes = PyByteArray::new_bound(py, b"abcde").into(); let h2 = { let mut hasher = DefaultHasher::new(); b2.hash(&mut hasher); hasher.finish() }; assert_eq!(h, h1); assert_eq!(h, h2); }); } #[test] fn test_backed_bytes_ord() { Python::with_gil(|py| { let mut a = vec![b"a", b"c", b"d", b"b", b"f", b"g", b"e"]; let mut b = a .iter() .map(|&b| PyBytes::new_bound(py, b).into()) .collect::>(); a.sort(); b.sort(); assert_eq!(a, b); }) } } pyo3/src/callback.rs0000644000175000017500000001002214661133735015317 0ustar jamespagejamespage//! Utilities for a Python callable object that invokes a Rust function. use crate::err::{PyErr, PyResult}; use crate::exceptions::PyOverflowError; use crate::ffi::{self, Py_hash_t}; use crate::{IntoPy, PyObject, Python}; use std::os::raw::c_int; /// A type which can be the return type of a python C-API callback pub trait PyCallbackOutput: Copy { /// The error value to return to python if the callback raised an exception const ERR_VALUE: Self; } impl PyCallbackOutput for *mut ffi::PyObject { const ERR_VALUE: Self = std::ptr::null_mut(); } impl PyCallbackOutput for std::os::raw::c_int { const ERR_VALUE: Self = -1; } impl PyCallbackOutput for ffi::Py_ssize_t { const ERR_VALUE: Self = -1; } /// Convert the result of callback function into the appropriate return value. pub trait IntoPyCallbackOutput { fn convert(self, py: Python<'_>) -> PyResult; } impl IntoPyCallbackOutput for Result where T: IntoPyCallbackOutput, E: Into, { #[inline] fn convert(self, py: Python<'_>) -> PyResult { match self { Ok(v) => v.convert(py), Err(e) => Err(e.into()), } } } impl IntoPyCallbackOutput<*mut ffi::PyObject> for T where T: IntoPy, { #[inline] fn convert(self, py: Python<'_>) -> PyResult<*mut ffi::PyObject> { Ok(self.into_py(py).into_ptr()) } } impl IntoPyCallbackOutput for *mut ffi::PyObject { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self) } } impl IntoPyCallbackOutput for () { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(0) } } impl IntoPyCallbackOutput for bool { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self as c_int) } } impl IntoPyCallbackOutput<()> for () { #[inline] fn convert(self, _: Python<'_>) -> PyResult<()> { Ok(()) } } impl IntoPyCallbackOutput for usize { #[inline] fn convert(self, _py: Python<'_>) -> PyResult { self.try_into().map_err(|_err| PyOverflowError::new_err(())) } } // Converters needed for `#[pyproto]` implementations impl IntoPyCallbackOutput for bool { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self) } } impl IntoPyCallbackOutput for usize { #[inline] fn convert(self, _: Python<'_>) -> PyResult { Ok(self) } } impl IntoPyCallbackOutput for T where T: IntoPy, { #[inline] fn convert(self, py: Python<'_>) -> PyResult { Ok(self.into_py(py)) } } pub trait WrappingCastTo { fn wrapping_cast(self) -> T; } macro_rules! wrapping_cast { ($from:ty, $to:ty) => { impl WrappingCastTo<$to> for $from { #[inline] fn wrapping_cast(self) -> $to { self as $to } } }; } wrapping_cast!(u8, Py_hash_t); wrapping_cast!(u16, Py_hash_t); wrapping_cast!(u32, Py_hash_t); wrapping_cast!(usize, Py_hash_t); wrapping_cast!(u64, Py_hash_t); wrapping_cast!(i8, Py_hash_t); wrapping_cast!(i16, Py_hash_t); wrapping_cast!(i32, Py_hash_t); wrapping_cast!(isize, Py_hash_t); wrapping_cast!(i64, Py_hash_t); pub struct HashCallbackOutput(Py_hash_t); impl IntoPyCallbackOutput for HashCallbackOutput { #[inline] fn convert(self, _py: Python<'_>) -> PyResult { let hash = self.0; if hash == -1 { Ok(-2) } else { Ok(hash) } } } impl IntoPyCallbackOutput for T where T: WrappingCastTo, { #[inline] fn convert(self, _py: Python<'_>) -> PyResult { Ok(HashCallbackOutput(self.wrapping_cast())) } } #[doc(hidden)] #[inline] pub fn convert(py: Python<'_>, value: T) -> PyResult where T: IntoPyCallbackOutput, { value.convert(py) } pyo3/src/err/0000775000175000017500000000000014661133735014014 5ustar jamespagejamespagepyo3/src/err/impls.rs0000644000175000017500000001501214661133735015503 0ustar jamespagejamespageuse crate::{err::PyErrArguments, exceptions, IntoPy, PyErr, PyObject, Python}; use std::io; /// Convert `PyErr` to `io::Error` impl From for io::Error { fn from(err: PyErr) -> Self { let kind = Python::with_gil(|py| { if err.is_instance_of::(py) { io::ErrorKind::BrokenPipe } else if err.is_instance_of::(py) { io::ErrorKind::ConnectionRefused } else if err.is_instance_of::(py) { io::ErrorKind::ConnectionAborted } else if err.is_instance_of::(py) { io::ErrorKind::ConnectionReset } else if err.is_instance_of::(py) { io::ErrorKind::Interrupted } else if err.is_instance_of::(py) { io::ErrorKind::NotFound } else if err.is_instance_of::(py) { io::ErrorKind::PermissionDenied } else if err.is_instance_of::(py) { io::ErrorKind::AlreadyExists } else if err.is_instance_of::(py) { io::ErrorKind::WouldBlock } else if err.is_instance_of::(py) { io::ErrorKind::TimedOut } else { io::ErrorKind::Other } }); io::Error::new(kind, err) } } /// Create `PyErr` from `io::Error` /// (`OSError` except if the `io::Error` is wrapping a Python exception, /// in this case the exception is returned) impl From for PyErr { fn from(err: io::Error) -> PyErr { // If the error wraps a Python error we return it if err.get_ref().map_or(false, |e| e.is::()) { return *err.into_inner().unwrap().downcast().unwrap(); } match err.kind() { io::ErrorKind::BrokenPipe => exceptions::PyBrokenPipeError::new_err(err), io::ErrorKind::ConnectionRefused => exceptions::PyConnectionRefusedError::new_err(err), io::ErrorKind::ConnectionAborted => exceptions::PyConnectionAbortedError::new_err(err), io::ErrorKind::ConnectionReset => exceptions::PyConnectionResetError::new_err(err), io::ErrorKind::Interrupted => exceptions::PyInterruptedError::new_err(err), io::ErrorKind::NotFound => exceptions::PyFileNotFoundError::new_err(err), io::ErrorKind::PermissionDenied => exceptions::PyPermissionError::new_err(err), io::ErrorKind::AlreadyExists => exceptions::PyFileExistsError::new_err(err), io::ErrorKind::WouldBlock => exceptions::PyBlockingIOError::new_err(err), io::ErrorKind::TimedOut => exceptions::PyTimeoutError::new_err(err), _ => exceptions::PyOSError::new_err(err), } } } impl PyErrArguments for io::Error { fn arguments(self, py: Python<'_>) -> PyObject { self.to_string().into_py(py) } } impl From> for PyErr { fn from(err: io::IntoInnerError) -> PyErr { err.into_error().into() } } impl PyErrArguments for io::IntoInnerError { fn arguments(self, py: Python<'_>) -> PyObject { self.into_error().arguments(py) } } impl From for PyErr { fn from(_: std::convert::Infallible) -> PyErr { unreachable!() } } macro_rules! impl_to_pyerr { ($err: ty, $pyexc: ty) => { impl PyErrArguments for $err { fn arguments(self, py: Python<'_>) -> PyObject { self.to_string().into_py(py) } } impl std::convert::From<$err> for PyErr { fn from(err: $err) -> PyErr { <$pyexc>::new_err(err) } } }; } impl_to_pyerr!(std::array::TryFromSliceError, exceptions::PyValueError); impl_to_pyerr!(std::num::ParseIntError, exceptions::PyValueError); impl_to_pyerr!(std::num::ParseFloatError, exceptions::PyValueError); impl_to_pyerr!(std::num::TryFromIntError, exceptions::PyValueError); impl_to_pyerr!(std::str::ParseBoolError, exceptions::PyValueError); impl_to_pyerr!(std::ffi::IntoStringError, exceptions::PyUnicodeDecodeError); impl_to_pyerr!(std::ffi::NulError, exceptions::PyValueError); impl_to_pyerr!(std::str::Utf8Error, exceptions::PyUnicodeDecodeError); impl_to_pyerr!(std::string::FromUtf8Error, exceptions::PyUnicodeDecodeError); impl_to_pyerr!( std::string::FromUtf16Error, exceptions::PyUnicodeDecodeError ); impl_to_pyerr!( std::char::DecodeUtf16Error, exceptions::PyUnicodeDecodeError ); impl_to_pyerr!(std::net::AddrParseError, exceptions::PyValueError); #[cfg(test)] mod tests { use crate::{PyErr, Python}; use std::io; #[test] fn io_errors() { use crate::types::any::PyAnyMethods; let check_err = |kind, expected_ty| { Python::with_gil(|py| { let rust_err = io::Error::new(kind, "some error msg"); let py_err: PyErr = rust_err.into(); let py_err_msg = format!("{}: some error msg", expected_ty); assert_eq!(py_err.to_string(), py_err_msg); let py_error_clone = py_err.clone_ref(py); let rust_err_from_py_err: io::Error = py_err.into(); assert_eq!(rust_err_from_py_err.to_string(), py_err_msg); assert_eq!(rust_err_from_py_err.kind(), kind); let py_err_recovered_from_rust_err: PyErr = rust_err_from_py_err.into(); assert!(py_err_recovered_from_rust_err .value_bound(py) .is(py_error_clone.value_bound(py))); // It should be the same exception }) }; check_err(io::ErrorKind::BrokenPipe, "BrokenPipeError"); check_err(io::ErrorKind::ConnectionRefused, "ConnectionRefusedError"); check_err(io::ErrorKind::ConnectionAborted, "ConnectionAbortedError"); check_err(io::ErrorKind::ConnectionReset, "ConnectionResetError"); check_err(io::ErrorKind::Interrupted, "InterruptedError"); check_err(io::ErrorKind::NotFound, "FileNotFoundError"); check_err(io::ErrorKind::PermissionDenied, "PermissionError"); check_err(io::ErrorKind::AlreadyExists, "FileExistsError"); check_err(io::ErrorKind::WouldBlock, "BlockingIOError"); check_err(io::ErrorKind::TimedOut, "TimeoutError"); } } pyo3/src/err/mod.rs0000644000175000017500000013454014661133735015146 0ustar jamespagejamespageuse crate::instance::Bound; use crate::panic::PanicException; use crate::type_object::PyTypeInfo; use crate::types::any::PyAnyMethods; use crate::types::{string::PyStringMethods, typeobject::PyTypeMethods, PyTraceback, PyType}; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ exceptions::{self, PyBaseException}, ffi, }; use crate::{Borrowed, IntoPy, Py, PyAny, PyObject, Python, ToPyObject}; use std::borrow::Cow; use std::cell::UnsafeCell; use std::ffi::CString; mod err_state; mod impls; pub use err_state::PyErrArguments; use err_state::{PyErrState, PyErrStateLazyFnOutput, PyErrStateNormalized}; /// Represents a Python exception. /// /// To avoid needing access to [`Python`] in `Into` conversions to create `PyErr` (thus improving /// compatibility with `?` and other Rust errors) this type supports creating exceptions instances /// in a lazy fashion, where the full Python object for the exception is created only when needed. /// /// Accessing the contained exception in any way, such as with [`value_bound`](PyErr::value_bound), /// [`get_type_bound`](PyErr::get_type_bound), or [`is_instance_bound`](PyErr::is_instance_bound) /// will create the full exception object if it was not already created. pub struct PyErr { // Safety: can only hand out references when in the "normalized" state. Will never change // after normalization. // // The state is temporarily removed from the PyErr during normalization, to avoid // concurrent modifications. state: UnsafeCell>, } // The inner value is only accessed through ways that require proving the gil is held #[cfg(feature = "nightly")] unsafe impl crate::marker::Ungil for PyErr {} unsafe impl Send for PyErr {} unsafe impl Sync for PyErr {} /// Represents the result of a Python call. pub type PyResult = Result; /// Error that indicates a failure to convert a PyAny to a more specific Python type. #[derive(Debug)] #[cfg(feature = "gil-refs")] pub struct PyDowncastError<'a> { from: &'a PyAny, to: Cow<'static, str>, } #[cfg(feature = "gil-refs")] impl<'a> PyDowncastError<'a> { /// Create a new `PyDowncastError` representing a failure to convert the object /// `from` into the type named in `to`. pub fn new(from: &'a PyAny, to: impl Into>) -> Self { PyDowncastError { from, to: to.into(), } } /// Compatibility API to convert the Bound variant `DowncastError` into the /// gil-ref variant pub(crate) fn from_downcast_err(DowncastError { from, to }: DowncastError<'a, 'a>) -> Self { #[allow(deprecated)] let from = unsafe { from.py().from_borrowed_ptr(from.as_ptr()) }; Self { from, to } } } /// Error that indicates a failure to convert a PyAny to a more specific Python type. #[derive(Debug)] pub struct DowncastError<'a, 'py> { from: Borrowed<'a, 'py, PyAny>, to: Cow<'static, str>, } impl<'a, 'py> DowncastError<'a, 'py> { /// Create a new `PyDowncastError` representing a failure to convert the object /// `from` into the type named in `to`. pub fn new(from: &'a Bound<'py, PyAny>, to: impl Into>) -> Self { DowncastError { from: from.as_borrowed(), to: to.into(), } } #[cfg(not(feature = "gil-refs"))] pub(crate) fn new_from_borrowed( from: Borrowed<'a, 'py, PyAny>, to: impl Into>, ) -> Self { DowncastError { from, to: to.into(), } } } /// Error that indicates a failure to convert a PyAny to a more specific Python type. #[derive(Debug)] pub struct DowncastIntoError<'py> { from: Bound<'py, PyAny>, to: Cow<'static, str>, } impl<'py> DowncastIntoError<'py> { /// Create a new `DowncastIntoError` representing a failure to convert the object /// `from` into the type named in `to`. pub fn new(from: Bound<'py, PyAny>, to: impl Into>) -> Self { DowncastIntoError { from, to: to.into(), } } /// Consumes this `DowncastIntoError` and returns the original object, allowing continued /// use of it after a failed conversion. /// /// See [`downcast_into`][PyAnyMethods::downcast_into] for an example. pub fn into_inner(self) -> Bound<'py, PyAny> { self.from } } impl PyErr { /// Creates a new PyErr of type `T`. /// /// `args` can be: /// * a tuple: the exception instance will be created using the equivalent to the Python /// expression `T(*tuple)` /// * any other value: the exception instance will be created using the equivalent to the Python /// expression `T(value)` /// /// This exception instance will be initialized lazily. This avoids the need for the Python GIL /// to be held, but requires `args` to be `Send` and `Sync`. If `args` is not `Send` or `Sync`, /// consider using [`PyErr::from_value_bound`] instead. /// /// If `T` does not inherit from `BaseException`, then a `TypeError` will be returned. /// /// If calling T's constructor with `args` raises an exception, that exception will be returned. /// /// # Examples /// /// ``` /// use pyo3::prelude::*; /// use pyo3::exceptions::PyTypeError; /// /// #[pyfunction] /// fn always_throws() -> PyResult<()> { /// Err(PyErr::new::("Error message")) /// } /// # /// # Python::with_gil(|py| { /// # let fun = pyo3::wrap_pyfunction_bound!(always_throws, py).unwrap(); /// # let err = fun.call0().expect_err("called a function that should always return an error but the return value was Ok"); /// # assert!(err.is_instance_of::(py)) /// # }); /// ``` /// /// In most cases, you can use a concrete exception's constructor instead: /// /// ``` /// use pyo3::prelude::*; /// use pyo3::exceptions::PyTypeError; /// /// #[pyfunction] /// fn always_throws() -> PyResult<()> { /// Err(PyTypeError::new_err("Error message")) /// } /// # /// # Python::with_gil(|py| { /// # let fun = pyo3::wrap_pyfunction_bound!(always_throws, py).unwrap(); /// # let err = fun.call0().expect_err("called a function that should always return an error but the return value was Ok"); /// # assert!(err.is_instance_of::(py)) /// # }); /// ``` #[inline] pub fn new(args: A) -> PyErr where T: PyTypeInfo, A: PyErrArguments + Send + Sync + 'static, { PyErr::from_state(PyErrState::Lazy(Box::new(move |py| { PyErrStateLazyFnOutput { ptype: T::type_object_bound(py).into(), pvalue: args.arguments(py), } }))) } /// Deprecated form of [`PyErr::from_type_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::from_type` will be replaced by `PyErr::from_type_bound` in a future PyO3 version" )] pub fn from_type(ty: &PyType, args: A) -> PyErr where A: PyErrArguments + Send + Sync + 'static, { PyErr::from_state(PyErrState::lazy(ty.into(), args)) } /// Constructs a new PyErr from the given Python type and arguments. /// /// `ty` is the exception type; usually one of the standard exceptions /// like `exceptions::PyRuntimeError`. /// /// `args` is either a tuple or a single value, with the same meaning as in [`PyErr::new`]. /// /// If `ty` does not inherit from `BaseException`, then a `TypeError` will be returned. /// /// If calling `ty` with `args` raises an exception, that exception will be returned. pub fn from_type_bound(ty: Bound<'_, PyType>, args: A) -> PyErr where A: PyErrArguments + Send + Sync + 'static, { PyErr::from_state(PyErrState::lazy(ty.unbind().into_any(), args)) } /// Deprecated form of [`PyErr::from_value_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::from_value` will be replaced by `PyErr::from_value_bound` in a future PyO3 version" )] pub fn from_value(obj: &PyAny) -> PyErr { PyErr::from_value_bound(obj.as_borrowed().to_owned()) } /// Creates a new PyErr. /// /// If `obj` is a Python exception object, the PyErr will contain that object. /// /// If `obj` is a Python exception type object, this is equivalent to `PyErr::from_type(obj, ())`. /// /// Otherwise, a `TypeError` is created. /// /// # Examples /// ```rust /// use pyo3::prelude::*; /// use pyo3::PyTypeInfo; /// use pyo3::exceptions::PyTypeError; /// use pyo3::types::PyString; /// /// Python::with_gil(|py| { /// // Case #1: Exception object /// let err = PyErr::from_value_bound(PyTypeError::new_err("some type error") /// .value_bound(py).clone().into_any()); /// assert_eq!(err.to_string(), "TypeError: some type error"); /// /// // Case #2: Exception type /// let err = PyErr::from_value_bound(PyTypeError::type_object_bound(py).into_any()); /// assert_eq!(err.to_string(), "TypeError: "); /// /// // Case #3: Invalid exception value /// let err = PyErr::from_value_bound(PyString::new_bound(py, "foo").into_any()); /// assert_eq!( /// err.to_string(), /// "TypeError: exceptions must derive from BaseException" /// ); /// }); /// ``` pub fn from_value_bound(obj: Bound<'_, PyAny>) -> PyErr { let state = match obj.downcast_into::() { Ok(obj) => PyErrState::normalized(obj), Err(err) => { // Assume obj is Type[Exception]; let later normalization handle if this // is not the case let obj = err.into_inner(); let py = obj.py(); PyErrState::lazy(obj.into_py(py), py.None()) } }; PyErr::from_state(state) } /// Deprecated form of [`PyErr::get_type_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::get_type` will be replaced by `PyErr::get_type_bound` in a future PyO3 version" )] pub fn get_type<'py>(&'py self, py: Python<'py>) -> &'py PyType { self.get_type_bound(py).into_gil_ref() } /// Returns the type of this exception. /// /// # Examples /// ```rust /// use pyo3::{prelude::*, exceptions::PyTypeError, types::PyType}; /// /// Python::with_gil(|py| { /// let err: PyErr = PyTypeError::new_err(("some type error",)); /// assert!(err.get_type_bound(py).is(&PyType::new_bound::(py))); /// }); /// ``` pub fn get_type_bound<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> { self.normalized(py).ptype(py) } /// Deprecated form of [`PyErr::value_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::value` will be replaced by `PyErr::value_bound` in a future PyO3 version" )] pub fn value<'py>(&'py self, py: Python<'py>) -> &'py PyBaseException { self.value_bound(py).as_gil_ref() } /// Returns the value of this exception. /// /// # Examples /// /// ```rust /// use pyo3::{exceptions::PyTypeError, PyErr, Python}; /// /// Python::with_gil(|py| { /// let err: PyErr = PyTypeError::new_err(("some type error",)); /// assert!(err.is_instance_of::(py)); /// assert_eq!(err.value_bound(py).to_string(), "some type error"); /// }); /// ``` pub fn value_bound<'py>(&self, py: Python<'py>) -> &Bound<'py, PyBaseException> { self.normalized(py).pvalue.bind(py) } /// Consumes self to take ownership of the exception value contained in this error. pub fn into_value(self, py: Python<'_>) -> Py { // NB technically this causes one reference count increase and decrease in quick succession // on pvalue, but it's probably not worth optimizing this right now for the additional code // complexity. let normalized = self.normalized(py); let exc = normalized.pvalue.clone_ref(py); if let Some(tb) = normalized.ptraceback(py) { unsafe { ffi::PyException_SetTraceback(exc.as_ptr(), tb.as_ptr()); } } exc } /// Deprecated form of [`PyErr::traceback_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::traceback` will be replaced by `PyErr::traceback_bound` in a future PyO3 version" )] pub fn traceback<'py>(&'py self, py: Python<'py>) -> Option<&'py PyTraceback> { self.normalized(py).ptraceback(py).map(|b| b.into_gil_ref()) } /// Returns the traceback of this exception object. /// /// # Examples /// ```rust /// use pyo3::{exceptions::PyTypeError, Python}; /// /// Python::with_gil(|py| { /// let err = PyTypeError::new_err(("some type error",)); /// assert!(err.traceback_bound(py).is_none()); /// }); /// ``` pub fn traceback_bound<'py>(&self, py: Python<'py>) -> Option> { self.normalized(py).ptraceback(py) } /// Gets whether an error is present in the Python interpreter's global state. #[inline] pub fn occurred(_: Python<'_>) -> bool { unsafe { !ffi::PyErr_Occurred().is_null() } } /// Takes the current error from the Python interpreter's global state and clears the global /// state. If no error is set, returns `None`. /// /// If the error is a `PanicException` (which would have originated from a panic in a pyo3 /// callback) then this function will resume the panic. /// /// Use this function when it is not known if an error should be present. If the error is /// expected to have been set, for example from [`PyErr::occurred`] or by an error return value /// from a C FFI function, use [`PyErr::fetch`]. pub fn take(py: Python<'_>) -> Option { Self::_take(py) } #[cfg(not(Py_3_12))] fn _take(py: Python<'_>) -> Option { let (ptype, pvalue, ptraceback) = unsafe { let mut ptype: *mut ffi::PyObject = std::ptr::null_mut(); let mut pvalue: *mut ffi::PyObject = std::ptr::null_mut(); let mut ptraceback: *mut ffi::PyObject = std::ptr::null_mut(); ffi::PyErr_Fetch(&mut ptype, &mut pvalue, &mut ptraceback); // Convert to Py immediately so that any references are freed by early return. let ptype = PyObject::from_owned_ptr_or_opt(py, ptype); let pvalue = PyObject::from_owned_ptr_or_opt(py, pvalue); let ptraceback = PyObject::from_owned_ptr_or_opt(py, ptraceback); // A valid exception state should always have a non-null ptype, but the other two may be // null. let ptype = match ptype { Some(ptype) => ptype, None => { debug_assert!( pvalue.is_none(), "Exception type was null but value was not null" ); debug_assert!( ptraceback.is_none(), "Exception type was null but traceback was not null" ); return None; } }; (ptype, pvalue, ptraceback) }; if ptype.as_ptr() == PanicException::type_object_raw(py).cast() { let msg = pvalue .as_ref() .and_then(|obj| obj.bind(py).str().ok()) .map(|py_str| py_str.to_string_lossy().into()) .unwrap_or_else(|| String::from("Unwrapped panic from Python code")); let state = PyErrState::FfiTuple { ptype, pvalue, ptraceback, }; Self::print_panic_and_unwind(py, state, msg) } Some(PyErr::from_state(PyErrState::FfiTuple { ptype, pvalue, ptraceback, })) } #[cfg(Py_3_12)] fn _take(py: Python<'_>) -> Option { let state = PyErrStateNormalized::take(py)?; let pvalue = state.pvalue.bind(py); if pvalue.get_type().as_ptr() == PanicException::type_object_raw(py).cast() { let msg: String = pvalue .str() .map(|py_str| py_str.to_string_lossy().into()) .unwrap_or_else(|_| String::from("Unwrapped panic from Python code")); Self::print_panic_and_unwind(py, PyErrState::Normalized(state), msg) } Some(PyErr::from_state(PyErrState::Normalized(state))) } fn print_panic_and_unwind(py: Python<'_>, state: PyErrState, msg: String) -> ! { eprintln!("--- PyO3 is resuming a panic after fetching a PanicException from Python. ---"); eprintln!("Python stack trace below:"); state.restore(py); unsafe { ffi::PyErr_PrintEx(0); } std::panic::resume_unwind(Box::new(msg)) } /// Equivalent to [PyErr::take], but when no error is set: /// - Panics in debug mode. /// - Returns a `SystemError` in release mode. /// /// This behavior is consistent with Python's internal handling of what happens when a C return /// value indicates an error occurred but the global error state is empty. (A lack of exception /// should be treated as a bug in the code which returned an error code but did not set an /// exception.) /// /// Use this function when the error is expected to have been set, for example from /// [PyErr::occurred] or by an error return value from a C FFI function. #[cfg_attr(debug_assertions, track_caller)] #[inline] pub fn fetch(py: Python<'_>) -> PyErr { const FAILED_TO_FETCH: &str = "attempted to fetch exception but none was set"; match PyErr::take(py) { Some(err) => err, #[cfg(debug_assertions)] None => panic!("{}", FAILED_TO_FETCH), #[cfg(not(debug_assertions))] None => exceptions::PySystemError::new_err(FAILED_TO_FETCH), } } /// Deprecated form of [`PyErr::new_type_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::new_type` will be replaced by `PyErr::new_type_bound` in a future PyO3 version" )] pub fn new_type( py: Python<'_>, name: &str, doc: Option<&str>, base: Option<&PyType>, dict: Option, ) -> PyResult> { Self::new_type_bound( py, name, doc, base.map(PyNativeType::as_borrowed).as_deref(), dict, ) } /// Creates a new exception type with the given name and docstring. /// /// - `base` can be an existing exception type to subclass, or a tuple of classes. /// - `dict` specifies an optional dictionary of class variables and methods. /// - `doc` will be the docstring seen by python users. /// /// /// # Errors /// /// This function returns an error if `name` is not of the form `.`. /// /// # Panics /// /// This function will panic if `name` or `doc` cannot be converted to [`CString`]s. pub fn new_type_bound<'py>( py: Python<'py>, name: &str, doc: Option<&str>, base: Option<&Bound<'py, PyType>>, dict: Option, ) -> PyResult> { let base: *mut ffi::PyObject = match base { None => std::ptr::null_mut(), Some(obj) => obj.as_ptr(), }; let dict: *mut ffi::PyObject = match dict { None => std::ptr::null_mut(), Some(obj) => obj.as_ptr(), }; let null_terminated_name = CString::new(name).expect("Failed to initialize nul terminated exception name"); let null_terminated_doc = doc.map(|d| CString::new(d).expect("Failed to initialize nul terminated docstring")); let null_terminated_doc_ptr = match null_terminated_doc.as_ref() { Some(c) => c.as_ptr(), None => std::ptr::null(), }; let ptr = unsafe { ffi::PyErr_NewExceptionWithDoc( null_terminated_name.as_ptr(), null_terminated_doc_ptr, base, dict, ) }; unsafe { Py::from_owned_ptr_or_err(py, ptr) } } /// Prints a standard traceback to `sys.stderr`. pub fn display(&self, py: Python<'_>) { #[cfg(Py_3_12)] unsafe { ffi::PyErr_DisplayException(self.value_bound(py).as_ptr()) } #[cfg(not(Py_3_12))] unsafe { // keep the bound `traceback` alive for entire duration of // PyErr_Display. if we inline this, the `Bound` will be dropped // after the argument got evaluated, leading to call with a dangling // pointer. let traceback = self.traceback_bound(py); let type_bound = self.get_type_bound(py); ffi::PyErr_Display( type_bound.as_ptr(), self.value_bound(py).as_ptr(), traceback .as_ref() .map_or(std::ptr::null_mut(), |traceback| traceback.as_ptr()), ) } } /// Calls `sys.excepthook` and then prints a standard traceback to `sys.stderr`. pub fn print(&self, py: Python<'_>) { self.clone_ref(py).restore(py); unsafe { ffi::PyErr_PrintEx(0) } } /// Calls `sys.excepthook` and then prints a standard traceback to `sys.stderr`. /// /// Additionally sets `sys.last_{type,value,traceback,exc}` attributes to this exception. pub fn print_and_set_sys_last_vars(&self, py: Python<'_>) { self.clone_ref(py).restore(py); unsafe { ffi::PyErr_PrintEx(1) } } /// Returns true if the current exception matches the exception in `exc`. /// /// If `exc` is a class object, this also returns `true` when `self` is an instance of a subclass. /// If `exc` is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match. pub fn matches(&self, py: Python<'_>, exc: T) -> bool where T: ToPyObject, { self.is_instance_bound(py, exc.to_object(py).bind(py)) } /// Deprecated form of `PyErr::is_instance_bound`. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::is_instance` will be replaced by `PyErr::is_instance_bound` in a future PyO3 version" )] #[inline] pub fn is_instance(&self, py: Python<'_>, ty: &PyAny) -> bool { self.is_instance_bound(py, &ty.as_borrowed()) } /// Returns true if the current exception is instance of `T`. #[inline] pub fn is_instance_bound(&self, py: Python<'_>, ty: &Bound<'_, PyAny>) -> bool { let type_bound = self.get_type_bound(py); (unsafe { ffi::PyErr_GivenExceptionMatches(type_bound.as_ptr(), ty.as_ptr()) }) != 0 } /// Returns true if the current exception is instance of `T`. #[inline] pub fn is_instance_of(&self, py: Python<'_>) -> bool where T: PyTypeInfo, { self.is_instance_bound(py, &T::type_object_bound(py)) } /// Writes the error back to the Python interpreter's global state. /// This is the opposite of `PyErr::fetch()`. #[inline] pub fn restore(self, py: Python<'_>) { self.state .into_inner() .expect("PyErr state should never be invalid outside of normalization") .restore(py) } /// Deprecated form of `PyErr::write_unraisable_bound`. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::write_unraisable` will be replaced by `PyErr::write_unraisable_bound` in a future PyO3 version" )] #[inline] pub fn write_unraisable(self, py: Python<'_>, obj: Option<&PyAny>) { self.write_unraisable_bound(py, obj.map(PyAny::as_borrowed).as_deref()) } /// Reports the error as unraisable. /// /// This calls `sys.unraisablehook()` using the current exception and obj argument. /// /// This method is useful to report errors in situations where there is no good mechanism /// to report back to the Python land. In Python this is used to indicate errors in /// background threads or destructors which are protected. In Rust code this is commonly /// useful when you are calling into a Python callback which might fail, but there is no /// obvious way to handle this error other than logging it. /// /// Calling this method has the benefit that the error goes back into a standardized callback /// in Python which for instance allows unittests to ensure that no unraisable error /// actually happend by hooking `sys.unraisablehook`. /// /// Example: /// ```rust /// # use pyo3::prelude::*; /// # use pyo3::exceptions::PyRuntimeError; /// # fn failing_function() -> PyResult<()> { Err(PyRuntimeError::new_err("foo")) } /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// match failing_function() { /// Err(pyerr) => pyerr.write_unraisable_bound(py, None), /// Ok(..) => { /* do something here */ } /// } /// Ok(()) /// }) /// # } #[inline] pub fn write_unraisable_bound(self, py: Python<'_>, obj: Option<&Bound<'_, PyAny>>) { self.restore(py); unsafe { ffi::PyErr_WriteUnraisable(obj.map_or(std::ptr::null_mut(), Bound::as_ptr)) } } /// Deprecated form of [`PyErr::warn_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::warn` will be replaced by `PyErr::warn_bound` in a future PyO3 version" )] pub fn warn(py: Python<'_>, category: &PyAny, message: &str, stacklevel: i32) -> PyResult<()> { Self::warn_bound(py, &category.as_borrowed(), message, stacklevel) } /// Issues a warning message. /// /// May return an `Err(PyErr)` if warnings-as-errors is enabled. /// /// Equivalent to `warnings.warn()` in Python. /// /// The `category` should be one of the `Warning` classes available in /// [`pyo3::exceptions`](crate::exceptions), or a subclass. The Python /// object can be retrieved using [`Python::get_type_bound()`]. /// /// Example: /// ```rust /// # use pyo3::prelude::*; /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let user_warning = py.get_type_bound::(); /// PyErr::warn_bound(py, &user_warning, "I am warning you", 0)?; /// Ok(()) /// }) /// # } /// ``` pub fn warn_bound<'py>( py: Python<'py>, category: &Bound<'py, PyAny>, message: &str, stacklevel: i32, ) -> PyResult<()> { let message = CString::new(message)?; error_on_minusone(py, unsafe { ffi::PyErr_WarnEx( category.as_ptr(), message.as_ptr(), stacklevel as ffi::Py_ssize_t, ) }) } /// Deprecated form of [`PyErr::warn_explicit_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyErr::warn_explicit` will be replaced by `PyErr::warn_explicit_bound` in a future PyO3 version" )] pub fn warn_explicit( py: Python<'_>, category: &PyAny, message: &str, filename: &str, lineno: i32, module: Option<&str>, registry: Option<&PyAny>, ) -> PyResult<()> { Self::warn_explicit_bound( py, &category.as_borrowed(), message, filename, lineno, module, registry.map(PyNativeType::as_borrowed).as_deref(), ) } /// Issues a warning message, with more control over the warning attributes. /// /// May return a `PyErr` if warnings-as-errors is enabled. /// /// Equivalent to `warnings.warn_explicit()` in Python. /// /// The `category` should be one of the `Warning` classes available in /// [`pyo3::exceptions`](crate::exceptions), or a subclass. pub fn warn_explicit_bound<'py>( py: Python<'py>, category: &Bound<'py, PyAny>, message: &str, filename: &str, lineno: i32, module: Option<&str>, registry: Option<&Bound<'py, PyAny>>, ) -> PyResult<()> { let message = CString::new(message)?; let filename = CString::new(filename)?; let module = module.map(CString::new).transpose()?; let module_ptr = match module { None => std::ptr::null_mut(), Some(s) => s.as_ptr(), }; let registry: *mut ffi::PyObject = match registry { None => std::ptr::null_mut(), Some(obj) => obj.as_ptr(), }; error_on_minusone(py, unsafe { ffi::PyErr_WarnExplicit( category.as_ptr(), message.as_ptr(), filename.as_ptr(), lineno, module_ptr, registry, ) }) } /// Clone the PyErr. This requires the GIL, which is why PyErr does not implement Clone. /// /// # Examples /// ```rust /// use pyo3::{exceptions::PyTypeError, PyErr, Python, prelude::PyAnyMethods}; /// Python::with_gil(|py| { /// let err: PyErr = PyTypeError::new_err(("some type error",)); /// let err_clone = err.clone_ref(py); /// assert!(err.get_type_bound(py).is(&err_clone.get_type_bound(py))); /// assert!(err.value_bound(py).is(err_clone.value_bound(py))); /// match err.traceback_bound(py) { /// None => assert!(err_clone.traceback_bound(py).is_none()), /// Some(tb) => assert!(err_clone.traceback_bound(py).unwrap().is(&tb)), /// } /// }); /// ``` #[inline] pub fn clone_ref(&self, py: Python<'_>) -> PyErr { PyErr::from_state(PyErrState::Normalized(self.normalized(py).clone_ref(py))) } /// Return the cause (either an exception instance, or None, set by `raise ... from ...`) /// associated with the exception, as accessible from Python through `__cause__`. pub fn cause(&self, py: Python<'_>) -> Option { use crate::ffi_ptr_ext::FfiPtrExt; let obj = unsafe { ffi::PyException_GetCause(self.value_bound(py).as_ptr()).assume_owned_or_opt(py) }; // PyException_GetCause is documented as potentially returning PyNone, but only GraalPy seems to actually do that #[cfg(GraalPy)] if let Some(cause) = &obj { if cause.is_none() { return None; } } obj.map(Self::from_value_bound) } /// Set the cause associated with the exception, pass `None` to clear it. pub fn set_cause(&self, py: Python<'_>, cause: Option) { let value = self.value_bound(py); let cause = cause.map(|err| err.into_value(py)); unsafe { // PyException_SetCause _steals_ a reference to cause, so must use .into_ptr() ffi::PyException_SetCause( value.as_ptr(), cause.map_or(std::ptr::null_mut(), Py::into_ptr), ); } } #[inline] fn from_state(state: PyErrState) -> PyErr { PyErr { state: UnsafeCell::new(Some(state)), } } #[inline] fn normalized(&self, py: Python<'_>) -> &PyErrStateNormalized { if let Some(PyErrState::Normalized(n)) = unsafe { // Safety: self.state will never be written again once normalized. &*self.state.get() } { return n; } self.make_normalized(py) } #[cold] fn make_normalized(&self, py: Python<'_>) -> &PyErrStateNormalized { // This process is safe because: // - Access is guaranteed not to be concurrent thanks to `Python` GIL token // - Write happens only once, and then never will change again. // - State is set to None during the normalization process, so that a second // concurrent normalization attempt will panic before changing anything. let state = unsafe { (*self.state.get()) .take() .expect("Cannot normalize a PyErr while already normalizing it.") }; unsafe { let self_state = &mut *self.state.get(); *self_state = Some(PyErrState::Normalized(state.normalize(py))); match self_state { Some(PyErrState::Normalized(n)) => n, _ => unreachable!(), } } } } impl std::fmt::Debug for PyErr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { Python::with_gil(|py| { f.debug_struct("PyErr") .field("type", &self.get_type_bound(py)) .field("value", self.value_bound(py)) .field("traceback", &self.traceback_bound(py)) .finish() }) } } impl std::fmt::Display for PyErr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Python::with_gil(|py| { let value = self.value_bound(py); let type_name = value.get_type().qualname().map_err(|_| std::fmt::Error)?; write!(f, "{}", type_name)?; if let Ok(s) = value.str() { write!(f, ": {}", &s.to_string_lossy()) } else { write!(f, ": ") } }) } } impl std::error::Error for PyErr {} impl IntoPy for PyErr { fn into_py(self, py: Python<'_>) -> PyObject { self.into_value(py).into() } } impl ToPyObject for PyErr { fn to_object(&self, py: Python<'_>) -> PyObject { self.clone_ref(py).into_py(py) } } impl<'a> IntoPy for &'a PyErr { fn into_py(self, py: Python<'_>) -> PyObject { self.clone_ref(py).into_py(py) } } struct PyDowncastErrorArguments { from: Py, to: Cow<'static, str>, } impl PyErrArguments for PyDowncastErrorArguments { fn arguments(self, py: Python<'_>) -> PyObject { const FAILED_TO_EXTRACT: Cow<'_, str> = Cow::Borrowed(""); let from = self.from.bind(py).qualname(); let from = match &from { Ok(qn) => qn.to_cow().unwrap_or(FAILED_TO_EXTRACT), Err(_) => FAILED_TO_EXTRACT, }; format!("'{}' object cannot be converted to '{}'", from, self.to).to_object(py) } } /// Python exceptions that can be converted to [`PyErr`]. /// /// This is used to implement [`From> for PyErr`]. /// /// Users should not need to implement this trait directly. It is implemented automatically in the /// [`crate::import_exception!`] and [`crate::create_exception!`] macros. pub trait ToPyErr {} impl<'py, T> std::convert::From> for PyErr where T: ToPyErr, { #[inline] fn from(err: Bound<'py, T>) -> PyErr { PyErr::from_value_bound(err.into_any()) } } /// Convert `PyDowncastError` to Python `TypeError`. #[cfg(feature = "gil-refs")] impl<'a> std::convert::From> for PyErr { fn from(err: PyDowncastError<'_>) -> PyErr { let args = PyDowncastErrorArguments { from: err.from.get_type().into(), to: err.to, }; exceptions::PyTypeError::new_err(args) } } #[cfg(feature = "gil-refs")] impl<'a> std::error::Error for PyDowncastError<'a> {} #[cfg(feature = "gil-refs")] impl<'a> std::fmt::Display for PyDowncastError<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { display_downcast_error(f, &self.from.as_borrowed(), &self.to) } } /// Convert `DowncastError` to Python `TypeError`. impl std::convert::From> for PyErr { fn from(err: DowncastError<'_, '_>) -> PyErr { let args = PyDowncastErrorArguments { from: err.from.get_type().into(), to: err.to, }; exceptions::PyTypeError::new_err(args) } } impl std::error::Error for DowncastError<'_, '_> {} impl std::fmt::Display for DowncastError<'_, '_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { display_downcast_error(f, &self.from, &self.to) } } /// Convert `DowncastIntoError` to Python `TypeError`. impl std::convert::From> for PyErr { fn from(err: DowncastIntoError<'_>) -> PyErr { let args = PyDowncastErrorArguments { from: err.from.get_type().into(), to: err.to, }; exceptions::PyTypeError::new_err(args) } } impl std::error::Error for DowncastIntoError<'_> {} impl std::fmt::Display for DowncastIntoError<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { display_downcast_error(f, &self.from, &self.to) } } fn display_downcast_error( f: &mut std::fmt::Formatter<'_>, from: &Bound<'_, PyAny>, to: &str, ) -> std::fmt::Result { write!( f, "'{}' object cannot be converted to '{}'", from.get_type().qualname().map_err(|_| std::fmt::Error)?, to ) } #[track_caller] pub fn panic_after_error(_py: Python<'_>) -> ! { unsafe { ffi::PyErr_Print(); } panic!("Python API call failed"); } /// Returns Ok if the error code is not -1. #[inline] pub(crate) fn error_on_minusone(py: Python<'_>, result: T) -> PyResult<()> { if result != T::MINUS_ONE { Ok(()) } else { Err(PyErr::fetch(py)) } } pub(crate) trait SignedInteger: Eq { const MINUS_ONE: Self; } macro_rules! impl_signed_integer { ($t:ty) => { impl SignedInteger for $t { const MINUS_ONE: Self = -1; } }; } impl_signed_integer!(i8); impl_signed_integer!(i16); impl_signed_integer!(i32); impl_signed_integer!(i64); impl_signed_integer!(i128); impl_signed_integer!(isize); #[cfg(test)] mod tests { use super::PyErrState; use crate::exceptions::{self, PyTypeError, PyValueError}; use crate::{PyErr, PyTypeInfo, Python}; #[test] fn no_error() { assert!(Python::with_gil(PyErr::take).is_none()); } #[test] fn set_valueerror() { Python::with_gil(|py| { let err: PyErr = exceptions::PyValueError::new_err("some exception message"); assert!(err.is_instance_of::(py)); err.restore(py); assert!(PyErr::occurred(py)); let err = PyErr::fetch(py); assert!(err.is_instance_of::(py)); assert_eq!(err.to_string(), "ValueError: some exception message"); }) } #[test] fn invalid_error_type() { Python::with_gil(|py| { let err: PyErr = PyErr::new::(()); assert!(err.is_instance_of::(py)); err.restore(py); let err = PyErr::fetch(py); assert!(err.is_instance_of::(py)); assert_eq!( err.to_string(), "TypeError: exceptions must derive from BaseException" ); }) } #[test] fn set_typeerror() { Python::with_gil(|py| { let err: PyErr = exceptions::PyTypeError::new_err(()); err.restore(py); assert!(PyErr::occurred(py)); drop(PyErr::fetch(py)); }); } #[test] #[should_panic(expected = "new panic")] fn fetching_panic_exception_resumes_unwind() { use crate::panic::PanicException; Python::with_gil(|py| { let err: PyErr = PanicException::new_err("new panic"); err.restore(py); assert!(PyErr::occurred(py)); // should resume unwind let _ = PyErr::fetch(py); }); } #[test] #[should_panic(expected = "new panic")] #[cfg(not(Py_3_12))] fn fetching_normalized_panic_exception_resumes_unwind() { use crate::panic::PanicException; Python::with_gil(|py| { let err: PyErr = PanicException::new_err("new panic"); // Restoring an error doesn't normalize it before Python 3.12, // so we have to explicitly test this case. let _ = err.normalized(py); err.restore(py); assert!(PyErr::occurred(py)); // should resume unwind let _ = PyErr::fetch(py); }); } #[test] fn err_debug() { // Debug representation should be like the following (without the newlines): // PyErr { // type: , // value: Exception('banana'), // traceback: Some("); assert_eq!(fields.next().unwrap(), "value: Exception('banana')"); let traceback = fields.next().unwrap(); assert!(traceback.starts_with("traceback: Some()")); assert!(fields.next().is_none()); }); } #[test] fn err_display() { Python::with_gil(|py| { let err = py .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error"); assert_eq!(err.to_string(), "Exception: banana"); }); } #[test] fn test_pyerr_send_sync() { fn is_send() {} fn is_sync() {} is_send::(); is_sync::(); is_send::(); is_sync::(); } #[test] fn test_pyerr_matches() { Python::with_gil(|py| { let err = PyErr::new::("foo"); assert!(err.matches(py, PyValueError::type_object_bound(py))); assert!(err.matches( py, ( PyValueError::type_object_bound(py), PyTypeError::type_object_bound(py) ) )); assert!(!err.matches(py, PyTypeError::type_object_bound(py))); // String is not a valid exception class, so we should get a TypeError let err: PyErr = PyErr::from_type_bound(crate::types::PyString::type_object_bound(py), "foo"); assert!(err.matches(py, PyTypeError::type_object_bound(py))); }) } #[test] fn test_pyerr_cause() { Python::with_gil(|py| { let err = py .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error"); assert!(err.cause(py).is_none()); let err = py .run_bound( "raise Exception('banana') from Exception('apple')", None, None, ) .expect_err("raising should have given us an error"); let cause = err .cause(py) .expect("raising from should have given us a cause"); assert_eq!(cause.to_string(), "Exception: apple"); err.set_cause(py, None); assert!(err.cause(py).is_none()); let new_cause = exceptions::PyValueError::new_err("orange"); err.set_cause(py, Some(new_cause)); let cause = err .cause(py) .expect("set_cause should have given us a cause"); assert_eq!(cause.to_string(), "ValueError: orange"); }); } #[test] fn warnings() { use crate::types::any::PyAnyMethods; // Note: although the warning filter is interpreter global, keeping the // GIL locked should prevent effects to be visible to other testing // threads. Python::with_gil(|py| { let cls = py.get_type_bound::(); // Reset warning filter to default state let warnings = py.import_bound("warnings").unwrap(); warnings.call_method0("resetwarnings").unwrap(); // First, test the warning is emitted assert_warnings!( py, { PyErr::warn_bound(py, &cls, "I am warning you", 0).unwrap() }, [(exceptions::PyUserWarning, "I am warning you")] ); // Test with raising warnings .call_method1("simplefilter", ("error", &cls)) .unwrap(); PyErr::warn_bound(py, &cls, "I am warning you", 0).unwrap_err(); // Test with error for an explicit module warnings.call_method0("resetwarnings").unwrap(); warnings .call_method1("filterwarnings", ("error", "", &cls, "pyo3test")) .unwrap(); // This has the wrong module and will not raise, just be emitted assert_warnings!( py, { PyErr::warn_bound(py, &cls, "I am warning you", 0).unwrap() }, [(exceptions::PyUserWarning, "I am warning you")] ); let err = PyErr::warn_explicit_bound( py, &cls, "I am warning you", "pyo3test.py", 427, None, None, ) .unwrap_err(); assert!(err .value_bound(py) .getattr("args") .unwrap() .get_item(0) .unwrap() .eq("I am warning you") .unwrap()); // Finally, reset filter again warnings.call_method0("resetwarnings").unwrap(); }); } } pyo3/src/err/err_state.rs0000644000175000017500000002040714661133735016353 0ustar jamespagejamespageuse crate::{ exceptions::{PyBaseException, PyTypeError}, ffi, types::{PyTraceback, PyType}, Bound, IntoPy, Py, PyAny, PyObject, PyTypeInfo, Python, }; pub(crate) struct PyErrStateNormalized { #[cfg(not(Py_3_12))] ptype: Py, pub pvalue: Py, #[cfg(not(Py_3_12))] ptraceback: Option>, } impl PyErrStateNormalized { #[cfg(not(Py_3_12))] pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> { self.ptype.bind(py).clone() } #[cfg(Py_3_12)] pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> { use crate::types::any::PyAnyMethods; self.pvalue.bind(py).get_type() } #[cfg(not(Py_3_12))] pub(crate) fn ptraceback<'py>(&self, py: Python<'py>) -> Option> { self.ptraceback .as_ref() .map(|traceback| traceback.bind(py).clone()) } #[cfg(Py_3_12)] pub(crate) fn ptraceback<'py>(&self, py: Python<'py>) -> Option> { use crate::ffi_ptr_ext::FfiPtrExt; use crate::types::any::PyAnyMethods; unsafe { ffi::PyException_GetTraceback(self.pvalue.as_ptr()) .assume_owned_or_opt(py) .map(|b| b.downcast_into_unchecked()) } } #[cfg(Py_3_12)] pub(crate) fn take(py: Python<'_>) -> Option { unsafe { Py::from_owned_ptr_or_opt(py, ffi::PyErr_GetRaisedException()) } .map(|pvalue| PyErrStateNormalized { pvalue }) } #[cfg(not(Py_3_12))] unsafe fn from_normalized_ffi_tuple( py: Python<'_>, ptype: *mut ffi::PyObject, pvalue: *mut ffi::PyObject, ptraceback: *mut ffi::PyObject, ) -> Self { PyErrStateNormalized { ptype: Py::from_owned_ptr_or_opt(py, ptype).expect("Exception type missing"), pvalue: Py::from_owned_ptr_or_opt(py, pvalue).expect("Exception value missing"), ptraceback: Py::from_owned_ptr_or_opt(py, ptraceback), } } pub fn clone_ref(&self, py: Python<'_>) -> Self { Self { #[cfg(not(Py_3_12))] ptype: self.ptype.clone_ref(py), pvalue: self.pvalue.clone_ref(py), #[cfg(not(Py_3_12))] ptraceback: self .ptraceback .as_ref() .map(|ptraceback| ptraceback.clone_ref(py)), } } } pub(crate) struct PyErrStateLazyFnOutput { pub(crate) ptype: PyObject, pub(crate) pvalue: PyObject, } pub(crate) type PyErrStateLazyFn = dyn for<'py> FnOnce(Python<'py>) -> PyErrStateLazyFnOutput + Send + Sync; pub(crate) enum PyErrState { Lazy(Box), #[cfg(not(Py_3_12))] FfiTuple { ptype: PyObject, pvalue: Option, ptraceback: Option, }, Normalized(PyErrStateNormalized), } /// Helper conversion trait that allows to use custom arguments for lazy exception construction. pub trait PyErrArguments: Send + Sync { /// Arguments for exception fn arguments(self, py: Python<'_>) -> PyObject; } impl PyErrArguments for T where T: IntoPy + Send + Sync, { fn arguments(self, py: Python<'_>) -> PyObject { self.into_py(py) } } impl PyErrState { pub(crate) fn lazy(ptype: Py, args: impl PyErrArguments + 'static) -> Self { PyErrState::Lazy(Box::new(move |py| PyErrStateLazyFnOutput { ptype, pvalue: args.arguments(py), })) } pub(crate) fn normalized(pvalue: Bound<'_, PyBaseException>) -> Self { #[cfg(not(Py_3_12))] use crate::types::any::PyAnyMethods; Self::Normalized(PyErrStateNormalized { #[cfg(not(Py_3_12))] ptype: pvalue.get_type().into(), #[cfg(not(Py_3_12))] ptraceback: unsafe { Py::from_owned_ptr_or_opt( pvalue.py(), ffi::PyException_GetTraceback(pvalue.as_ptr()), ) }, pvalue: pvalue.into(), }) } pub(crate) fn normalize(self, py: Python<'_>) -> PyErrStateNormalized { match self { #[cfg(not(Py_3_12))] PyErrState::Lazy(lazy) => { let (ptype, pvalue, ptraceback) = lazy_into_normalized_ffi_tuple(py, lazy); unsafe { PyErrStateNormalized::from_normalized_ffi_tuple(py, ptype, pvalue, ptraceback) } } #[cfg(Py_3_12)] PyErrState::Lazy(lazy) => { // To keep the implementation simple, just write the exception into the interpreter, // which will cause it to be normalized raise_lazy(py, lazy); PyErrStateNormalized::take(py) .expect("exception missing after writing to the interpreter") } #[cfg(not(Py_3_12))] PyErrState::FfiTuple { ptype, pvalue, ptraceback, } => { let mut ptype = ptype.into_ptr(); let mut pvalue = pvalue.map_or(std::ptr::null_mut(), Py::into_ptr); let mut ptraceback = ptraceback.map_or(std::ptr::null_mut(), Py::into_ptr); unsafe { ffi::PyErr_NormalizeException(&mut ptype, &mut pvalue, &mut ptraceback); PyErrStateNormalized::from_normalized_ffi_tuple(py, ptype, pvalue, ptraceback) } } PyErrState::Normalized(normalized) => normalized, } } #[cfg(not(Py_3_12))] pub(crate) fn restore(self, py: Python<'_>) { let (ptype, pvalue, ptraceback) = match self { PyErrState::Lazy(lazy) => lazy_into_normalized_ffi_tuple(py, lazy), PyErrState::FfiTuple { ptype, pvalue, ptraceback, } => ( ptype.into_ptr(), pvalue.map_or(std::ptr::null_mut(), Py::into_ptr), ptraceback.map_or(std::ptr::null_mut(), Py::into_ptr), ), PyErrState::Normalized(PyErrStateNormalized { ptype, pvalue, ptraceback, }) => ( ptype.into_ptr(), pvalue.into_ptr(), ptraceback.map_or(std::ptr::null_mut(), Py::into_ptr), ), }; unsafe { ffi::PyErr_Restore(ptype, pvalue, ptraceback) } } #[cfg(Py_3_12)] pub(crate) fn restore(self, py: Python<'_>) { match self { PyErrState::Lazy(lazy) => raise_lazy(py, lazy), PyErrState::Normalized(PyErrStateNormalized { pvalue }) => unsafe { ffi::PyErr_SetRaisedException(pvalue.into_ptr()) }, } } } #[cfg(not(Py_3_12))] fn lazy_into_normalized_ffi_tuple( py: Python<'_>, lazy: Box, ) -> (*mut ffi::PyObject, *mut ffi::PyObject, *mut ffi::PyObject) { // To be consistent with 3.12 logic, go via raise_lazy, but also then normalize // the resulting exception raise_lazy(py, lazy); let mut ptype = std::ptr::null_mut(); let mut pvalue = std::ptr::null_mut(); let mut ptraceback = std::ptr::null_mut(); unsafe { ffi::PyErr_Fetch(&mut ptype, &mut pvalue, &mut ptraceback); ffi::PyErr_NormalizeException(&mut ptype, &mut pvalue, &mut ptraceback); } (ptype, pvalue, ptraceback) } /// Raises a "lazy" exception state into the Python interpreter. /// /// In principle this could be split in two; first a function to create an exception /// in a normalized state, and then a call to `PyErr_SetRaisedException` to raise it. /// /// This would require either moving some logic from C to Rust, or requesting a new /// API in CPython. fn raise_lazy(py: Python<'_>, lazy: Box) { let PyErrStateLazyFnOutput { ptype, pvalue } = lazy(py); unsafe { if ffi::PyExceptionClass_Check(ptype.as_ptr()) == 0 { ffi::PyErr_SetString( PyTypeError::type_object_raw(py).cast(), ffi::c_str!("exceptions must derive from BaseException").as_ptr(), ) } else { ffi::PyErr_SetObject(ptype.as_ptr(), pvalue.as_ptr()) } } } pyo3/src/sync.rs0000644000175000017500000002556114661133735014555 0ustar jamespagejamespage//! Synchronization mechanisms based on the Python GIL. //! //! With the acceptance of [PEP 703] (aka a "freethreaded Python") for Python 3.13, these //! are likely to undergo significant developments in the future. //! //! [PEP 703]: https://peps.python.org/pep-703/ use crate::{ types::{any::PyAnyMethods, PyString, PyType}, Bound, Py, PyResult, PyVisit, Python, }; use std::cell::UnsafeCell; /// Value with concurrent access protected by the GIL. /// /// This is a synchronization primitive based on Python's global interpreter lock (GIL). /// It ensures that only one thread at a time can access the inner value via shared references. /// It can be combined with interior mutability to obtain mutable references. /// /// # Example /// /// Combining `GILProtected` with `RefCell` enables mutable access to static data: /// /// ``` /// # use pyo3::prelude::*; /// use pyo3::sync::GILProtected; /// use std::cell::RefCell; /// /// static NUMBERS: GILProtected>> = GILProtected::new(RefCell::new(Vec::new())); /// /// Python::with_gil(|py| { /// NUMBERS.get(py).borrow_mut().push(42); /// }); /// ``` pub struct GILProtected { value: T, } impl GILProtected { /// Place the given value under the protection of the GIL. pub const fn new(value: T) -> Self { Self { value } } /// Gain access to the inner value by giving proof of having acquired the GIL. pub fn get<'py>(&'py self, _py: Python<'py>) -> &'py T { &self.value } /// Gain access to the inner value by giving proof that garbage collection is happening. pub fn traverse<'py>(&'py self, _visit: PyVisit<'py>) -> &'py T { &self.value } } unsafe impl Sync for GILProtected where T: Send {} /// A write-once cell similar to [`once_cell::OnceCell`](https://docs.rs/once_cell/latest/once_cell/). /// /// Unlike `once_cell::sync` which blocks threads to achieve thread safety, this implementation /// uses the Python GIL to mediate concurrent access. This helps in cases where `once_cell` or /// `lazy_static`'s synchronization strategy can lead to deadlocks when interacting with the Python /// GIL. For an example, see #[doc = concat!("[the FAQ section](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/faq.html)")] /// of the guide. /// /// Note that: /// 1) `get_or_init` and `get_or_try_init` do not protect against infinite recursion /// from reentrant initialization. /// 2) If the initialization function `f` provided to `get_or_init` (or `get_or_try_init`) /// temporarily releases the GIL (e.g. by calling `Python::import`) then it is possible /// for a second thread to also begin initializing the `GITOnceCell`. Even when this /// happens `GILOnceCell` guarantees that only **one** write to the cell ever occurs - /// this is treated as a race, other threads will discard the value they compute and /// return the result of the first complete computation. /// /// # Examples /// /// The following example shows how to use `GILOnceCell` to share a reference to a Python list /// between threads: /// /// ``` /// use pyo3::sync::GILOnceCell; /// use pyo3::prelude::*; /// use pyo3::types::PyList; /// /// static LIST_CELL: GILOnceCell> = GILOnceCell::new(); /// /// pub fn get_shared_list(py: Python<'_>) -> &Bound<'_, PyList> { /// LIST_CELL /// .get_or_init(py, || PyList::empty_bound(py).unbind()) /// .bind(py) /// } /// # Python::with_gil(|py| assert_eq!(get_shared_list(py).len(), 0)); /// ``` #[derive(Default)] pub struct GILOnceCell(UnsafeCell>); // T: Send is needed for Sync because the thread which drops the GILOnceCell can be different // to the thread which fills it. unsafe impl Sync for GILOnceCell {} unsafe impl Send for GILOnceCell {} impl GILOnceCell { /// Create a `GILOnceCell` which does not yet contain a value. pub const fn new() -> Self { Self(UnsafeCell::new(None)) } /// Get a reference to the contained value, or `None` if the cell has not yet been written. #[inline] pub fn get(&self, _py: Python<'_>) -> Option<&T> { // Safe because if the cell has not yet been written, None is returned. unsafe { &*self.0.get() }.as_ref() } /// Get a reference to the contained value, initializing it if needed using the provided /// closure. /// /// See the type-level documentation for detail on re-entrancy and concurrent initialization. #[inline] pub fn get_or_init(&self, py: Python<'_>, f: F) -> &T where F: FnOnce() -> T, { if let Some(value) = self.get(py) { return value; } match self.init(py, || Ok::(f())) { Ok(value) => value, Err(void) => match void {}, } } /// Like `get_or_init`, but accepts a fallible initialization function. If it fails, the cell /// is left uninitialized. /// /// See the type-level documentation for detail on re-entrancy and concurrent initialization. #[inline] pub fn get_or_try_init(&self, py: Python<'_>, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { if let Some(value) = self.get(py) { return Ok(value); } self.init(py, f) } #[cold] fn init(&self, py: Python<'_>, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { // Note that f() could temporarily release the GIL, so it's possible that another thread // writes to this GILOnceCell before f() finishes. That's fine; we'll just have to discard // the value computed here and accept a bit of wasted computation. let value = f()?; let _ = self.set(py, value); Ok(self.get(py).unwrap()) } /// Get the contents of the cell mutably. This is only possible if the reference to the cell is /// unique. pub fn get_mut(&mut self) -> Option<&mut T> { self.0.get_mut().as_mut() } /// Set the value in the cell. /// /// If the cell has already been written, `Err(value)` will be returned containing the new /// value which was not written. pub fn set(&self, _py: Python<'_>, value: T) -> Result<(), T> { // Safe because GIL is held, so no other thread can be writing to this cell concurrently. let inner = unsafe { &mut *self.0.get() }; if inner.is_some() { return Err(value); } *inner = Some(value); Ok(()) } /// Takes the value out of the cell, moving it back to an uninitialized state. /// /// Has no effect and returns None if the cell has not yet been written. pub fn take(&mut self) -> Option { self.0.get_mut().take() } /// Consumes the cell, returning the wrapped value. /// /// Returns None if the cell has not yet been written. pub fn into_inner(self) -> Option { self.0.into_inner() } } impl GILOnceCell> { /// Get a reference to the contained Python type, initializing it if needed. /// /// This is a shorthand method for `get_or_init` which imports the type from Python on init. pub(crate) fn get_or_try_init_type_ref<'py>( &self, py: Python<'py>, module_name: &str, attr_name: &str, ) -> PyResult<&Bound<'py, PyType>> { self.get_or_try_init(py, || { let type_object = py .import_bound(module_name)? .getattr(attr_name)? .downcast_into()?; Ok(type_object.unbind()) }) .map(|ty| ty.bind(py)) } } /// Interns `text` as a Python string and stores a reference to it in static storage. /// /// A reference to the same Python string is returned on each invocation. /// /// # Example: Using `intern!` to avoid needlessly recreating the same Python string /// /// ``` /// use pyo3::intern; /// # use pyo3::{prelude::*, types::PyDict}; /// /// #[pyfunction] /// fn create_dict(py: Python<'_>) -> PyResult> { /// let dict = PyDict::new_bound(py); /// // 👇 A new `PyString` is created /// // for every call of this function. /// dict.set_item("foo", 42)?; /// Ok(dict) /// } /// /// #[pyfunction] /// fn create_dict_faster(py: Python<'_>) -> PyResult> { /// let dict = PyDict::new_bound(py); /// // 👇 A `PyString` is created once and reused /// // for the lifetime of the program. /// dict.set_item(intern!(py, "foo"), 42)?; /// Ok(dict) /// } /// # /// # Python::with_gil(|py| { /// # let fun_slow = wrap_pyfunction_bound!(create_dict, py).unwrap(); /// # let dict = fun_slow.call0().unwrap(); /// # assert!(dict.contains("foo").unwrap()); /// # let fun = wrap_pyfunction_bound!(create_dict_faster, py).unwrap(); /// # let dict = fun.call0().unwrap(); /// # assert!(dict.contains("foo").unwrap()); /// # }); /// ``` #[macro_export] macro_rules! intern { ($py: expr, $text: expr) => {{ static INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text); INTERNED.get($py) }}; } /// Implementation detail for `intern!` macro. #[doc(hidden)] pub struct Interned(&'static str, GILOnceCell>); impl Interned { /// Creates an empty holder for an interned `str`. pub const fn new(value: &'static str) -> Self { Interned(value, GILOnceCell::new()) } /// Gets or creates the interned `str` value. #[inline] pub fn get<'py>(&self, py: Python<'py>) -> &Bound<'py, PyString> { self.1 .get_or_init(py, || PyString::intern_bound(py, self.0).into()) .bind(py) } } #[cfg(test)] mod tests { use super::*; use crate::types::{dict::PyDictMethods, PyDict}; #[test] fn test_intern() { Python::with_gil(|py| { let foo1 = "foo"; let foo2 = intern!(py, "foo"); let foo3 = intern!(py, stringify!(foo)); let dict = PyDict::new_bound(py); dict.set_item(foo1, 42_usize).unwrap(); assert!(dict.contains(foo2).unwrap()); assert_eq!( dict.get_item(foo3) .unwrap() .unwrap() .extract::() .unwrap(), 42 ); }); } #[test] fn test_once_cell() { Python::with_gil(|py| { let mut cell = GILOnceCell::new(); assert!(cell.get(py).is_none()); assert_eq!(cell.get_or_try_init(py, || Err(5)), Err(5)); assert!(cell.get(py).is_none()); assert_eq!(cell.get_or_try_init(py, || Ok::<_, ()>(2)), Ok(&2)); assert_eq!(cell.get(py), Some(&2)); assert_eq!(cell.get_or_try_init(py, || Err(5)), Ok(&2)); assert_eq!(cell.take(), Some(2)); assert_eq!(cell.into_inner(), None) }) } } pyo3/src/ffi/0000775000175000017500000000000014661133735013770 5ustar jamespagejamespagepyo3/src/ffi/mod.rs0000644000175000017500000000231514661133735015114 0ustar jamespagejamespage//! Raw FFI declarations for Python's C API. //! //! This module provides low level bindings to the Python interpreter. //! It is meant for advanced users only - regular PyO3 users shouldn't //! need to interact with this module at all. //! //! The contents of this module are not documented here, as it would entail //! basically copying the documentation from CPython. Consult the [Python/C API Reference //! Manual][capi] for up-to-date documentation. //! //! # Safety //! //! The functions in this module lack individual safety documentation, but //! generally the following apply: //! - Pointer arguments have to point to a valid Python object of the correct type, //! although null pointers are sometimes valid input. //! - The vast majority can only be used safely while the GIL is held. //! - Some functions have additional safety requirements, consult the //! [Python/C API Reference Manual][capi] for more information. //! //! [capi]: https://docs.python.org/3/c-api/index.html #[cfg(test)] mod tests; // reexport raw bindings exposed in pyo3_ffi pub use pyo3_ffi::*; /// Helper to enable #\[pymethods\] to see the workaround for __ipow__ on Python 3.7 #[doc(hidden)] pub use crate::impl_::pymethods::ipowfunc; pyo3/src/ffi/tests.rs0000644000175000017500000002277214661133735015510 0ustar jamespagejamespageuse crate::ffi::*; use crate::types::any::PyAnyMethods; use crate::Python; #[cfg(all(not(Py_LIMITED_API), any(not(PyPy), feature = "macros")))] use crate::types::PyString; #[cfg(not(Py_LIMITED_API))] use crate::{types::PyDict, Bound, IntoPy, Py, PyAny}; #[cfg(not(any(Py_3_12, Py_LIMITED_API)))] use libc::wchar_t; #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[test] fn test_datetime_fromtimestamp() { Python::with_gil(|py| { let args: Py = (100,).into_py(py); let dt = unsafe { PyDateTime_IMPORT(); Bound::from_owned_ptr(py, PyDateTime_FromTimestamp(args.as_ptr())) }; let locals = PyDict::new_bound(py); locals.set_item("dt", dt).unwrap(); py.run_bound( "import datetime; assert dt == datetime.datetime.fromtimestamp(100)", None, Some(&locals), ) .unwrap(); }) } #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[test] fn test_date_fromtimestamp() { Python::with_gil(|py| { let args: Py = (100,).into_py(py); let dt = unsafe { PyDateTime_IMPORT(); Bound::from_owned_ptr(py, PyDate_FromTimestamp(args.as_ptr())) }; let locals = PyDict::new_bound(py); locals.set_item("dt", dt).unwrap(); py.run_bound( "import datetime; assert dt == datetime.date.fromtimestamp(100)", None, Some(&locals), ) .unwrap(); }) } #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[test] fn test_utc_timezone() { Python::with_gil(|py| { let utc_timezone: Bound<'_, PyAny> = unsafe { PyDateTime_IMPORT(); Bound::from_borrowed_ptr(py, PyDateTime_TimeZone_UTC()) }; let locals = PyDict::new_bound(py); locals.set_item("utc_timezone", utc_timezone).unwrap(); py.run_bound( "import datetime; assert utc_timezone is datetime.timezone.utc", None, Some(&locals), ) .unwrap(); }) } #[test] #[cfg(not(Py_LIMITED_API))] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_timezone_from_offset() { use crate::{ffi_ptr_ext::FfiPtrExt, types::PyDelta}; Python::with_gil(|py| { let delta = PyDelta::new_bound(py, 0, 100, 0, false).unwrap(); let tz = unsafe { PyTimeZone_FromOffset(delta.as_ptr()).assume_owned(py) }; crate::py_run!( py, tz, "import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100))" ); }) } #[test] #[cfg(not(Py_LIMITED_API))] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_timezone_from_offset_and_name() { use crate::{ffi_ptr_ext::FfiPtrExt, types::PyDelta}; Python::with_gil(|py| { let delta = PyDelta::new_bound(py, 0, 100, 0, false).unwrap(); let tzname = PyString::new_bound(py, "testtz"); let tz = unsafe { PyTimeZone_FromOffsetAndName(delta.as_ptr(), tzname.as_ptr()).assume_owned(py) }; crate::py_run!( py, tz, "import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100), 'testtz')" ); }) } #[test] #[cfg(not(Py_LIMITED_API))] fn ascii_object_bitfield() { let ob_base: PyObject = unsafe { std::mem::zeroed() }; let mut o = PyASCIIObject { ob_base, length: 0, #[cfg(not(PyPy))] hash: 0, state: 0u32, #[cfg(not(Py_3_12))] wstr: std::ptr::null_mut() as *mut wchar_t, }; unsafe { assert_eq!(o.interned(), 0); assert_eq!(o.kind(), 0); assert_eq!(o.compact(), 0); assert_eq!(o.ascii(), 0); #[cfg(not(Py_3_12))] assert_eq!(o.ready(), 0); let interned_count = if cfg!(Py_3_12) { 2 } else { 4 }; for i in 0..interned_count { o.set_interned(i); assert_eq!(o.interned(), i); } for i in 0..8 { o.set_kind(i); assert_eq!(o.kind(), i); } o.set_compact(1); assert_eq!(o.compact(), 1); o.set_ascii(1); assert_eq!(o.ascii(), 1); #[cfg(not(Py_3_12))] o.set_ready(1); #[cfg(not(Py_3_12))] assert_eq!(o.ready(), 1); } } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy)))] fn ascii() { Python::with_gil(|py| { // This test relies on implementation details of PyString. let s = PyString::new_bound(py, "hello, world"); let ptr = s.as_ptr(); unsafe { let ascii_ptr = ptr as *mut PyASCIIObject; let ascii = ascii_ptr.as_ref().unwrap(); assert_eq!(ascii.interned(), 0); assert_eq!(ascii.kind(), PyUnicode_1BYTE_KIND); assert_eq!(ascii.compact(), 1); assert_eq!(ascii.ascii(), 1); #[cfg(not(Py_3_12))] assert_eq!(ascii.ready(), 1); assert_eq!(PyUnicode_IS_ASCII(ptr), 1); assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 1); assert!(!PyUnicode_1BYTE_DATA(ptr).is_null()); // 2 and 4 byte macros return nonsense for this string instance. assert_eq!(PyUnicode_KIND(ptr), PyUnicode_1BYTE_KIND); assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null()); // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings. assert!(!PyUnicode_DATA(ptr).is_null()); assert_eq!(PyUnicode_GET_LENGTH(ptr), s.len().unwrap() as Py_ssize_t); assert_eq!(PyUnicode_IS_READY(ptr), 1); // This has potential to mutate object. But it should be a no-op since // we're already ready. assert_eq!(PyUnicode_READY(ptr), 0); } }) } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy)))] fn ucs4() { Python::with_gil(|py| { let s = "哈哈🐈"; let py_string = PyString::new_bound(py, s); let ptr = py_string.as_ptr(); unsafe { let ascii_ptr = ptr as *mut PyASCIIObject; let ascii = ascii_ptr.as_ref().unwrap(); assert_eq!(ascii.interned(), 0); assert_eq!(ascii.kind(), PyUnicode_4BYTE_KIND); assert_eq!(ascii.compact(), 1); assert_eq!(ascii.ascii(), 0); #[cfg(not(Py_3_12))] assert_eq!(ascii.ready(), 1); assert_eq!(PyUnicode_IS_ASCII(ptr), 0); assert_eq!(PyUnicode_IS_COMPACT(ptr), 1); assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 0); assert!(!PyUnicode_4BYTE_DATA(ptr).is_null()); assert_eq!(PyUnicode_KIND(ptr), PyUnicode_4BYTE_KIND); assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null()); // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings. assert!(!PyUnicode_DATA(ptr).is_null()); assert_eq!( PyUnicode_GET_LENGTH(ptr), py_string.len().unwrap() as Py_ssize_t ); assert_eq!(PyUnicode_IS_READY(ptr), 1); // This has potential to mutate object. But it should be a no-op since // we're already ready. assert_eq!(PyUnicode_READY(ptr), 0); } }) } #[test] #[cfg(not(Py_LIMITED_API))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons #[cfg(not(PyPy))] fn test_get_tzinfo() { use crate::types::timezone_utc_bound; crate::Python::with_gil(|py| { use crate::types::{PyDateTime, PyTime}; let utc = &timezone_utc_bound(py); let dt = PyDateTime::new_bound(py, 2018, 1, 1, 0, 0, 0, 0, Some(utc)).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) } .is(utc) ); let dt = PyDateTime::new_bound(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) } .is_none() ); let t = PyTime::new_bound(py, 0, 0, 0, 0, Some(utc)).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }.is(utc) ); let t = PyTime::new_bound(py, 0, 0, 0, 0, None).unwrap(); assert!( unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) } .is_none() ); }) } #[test] fn test_inc_dec_ref() { Python::with_gil(|py| { let obj = py.eval_bound("object()", None, None).unwrap(); let ref_count = obj.get_refcnt(); let ptr = obj.as_ptr(); unsafe { Py_INCREF(ptr) }; assert_eq!(obj.get_refcnt(), ref_count + 1); unsafe { Py_DECREF(ptr) }; assert_eq!(obj.get_refcnt(), ref_count); }) } #[test] #[cfg(Py_3_12)] fn test_inc_dec_ref_immortal() { Python::with_gil(|py| { let obj = py.None(); let ref_count = obj.get_refcnt(py); let ptr = obj.as_ptr(); unsafe { Py_INCREF(ptr) }; assert_eq!(obj.get_refcnt(py), ref_count); unsafe { Py_DECREF(ptr) }; assert_eq!(obj.get_refcnt(py), ref_count); }) } pyo3/src/internal_tricks.rs0000644000175000017500000001332614661133735016770 0ustar jamespagejamespageuse crate::ffi::{Py_ssize_t, PY_SSIZE_T_MAX}; pub struct PrivateMarker; macro_rules! private_decl { () => { /// This trait is private to implement; this method exists to make it /// impossible to implement outside the crate. fn __private__(&self) -> crate::internal_tricks::PrivateMarker; }; } macro_rules! private_impl { () => { fn __private__(&self) -> crate::internal_tricks::PrivateMarker { crate::internal_tricks::PrivateMarker } }; } macro_rules! pyo3_exception { ($doc: expr, $name: ident, $base: ty) => { #[doc = $doc] #[repr(transparent)] #[allow(non_camel_case_types)] pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); $crate::create_exception_type_object!(pyo3_runtime, $name, $base, Some($doc)); }; } /// Convert an usize index into a Py_ssize_t index, clamping overflow to /// PY_SSIZE_T_MAX. pub(crate) fn get_ssize_index(index: usize) -> Py_ssize_t { index.min(PY_SSIZE_T_MAX as usize) as Py_ssize_t } /// Implementations used for slice indexing PySequence, PyTuple, and PyList #[cfg(feature = "gil-refs")] macro_rules! index_impls { ( $ty:ty, $ty_name:literal, $len:expr, $get_slice:expr $(,)? ) => { impl std::ops::Index for $ty { // Always PyAny output (even if the slice operation returns something else) type Output = PyAny; #[track_caller] fn index(&self, index: usize) -> &Self::Output { self.get_item(index).unwrap_or_else(|_| { crate::internal_tricks::index_len_fail(index, $ty_name, $len(self)) }) } } impl std::ops::Index> for $ty { type Output = $ty; #[track_caller] fn index( &self, std::ops::Range { start, end }: std::ops::Range, ) -> &Self::Output { let len = $len(self); if start > len { crate::internal_tricks::slice_start_index_len_fail(start, $ty_name, len) } else if end > len { crate::internal_tricks::slice_end_index_len_fail(end, $ty_name, len) } else if start > end { crate::internal_tricks::slice_index_order_fail(start, end) } else { $get_slice(self, start, end) } } } impl std::ops::Index> for $ty { type Output = $ty; #[track_caller] fn index( &self, std::ops::RangeFrom { start }: std::ops::RangeFrom, ) -> &Self::Output { let len = $len(self); if start > len { crate::internal_tricks::slice_start_index_len_fail(start, $ty_name, len) } else { $get_slice(self, start, len) } } } impl std::ops::Index for $ty { type Output = $ty; #[track_caller] fn index(&self, _: std::ops::RangeFull) -> &Self::Output { let len = $len(self); $get_slice(self, 0, len) } } impl std::ops::Index> for $ty { type Output = $ty; #[track_caller] fn index(&self, range: std::ops::RangeInclusive) -> &Self::Output { let exclusive_end = range .end() .checked_add(1) .expect("range end exceeds Python limit"); &self[*range.start()..exclusive_end] } } impl std::ops::Index> for $ty { type Output = $ty; #[track_caller] fn index(&self, std::ops::RangeTo { end }: std::ops::RangeTo) -> &Self::Output { &self[0..end] } } impl std::ops::Index> for $ty { type Output = $ty; #[track_caller] fn index( &self, std::ops::RangeToInclusive { end }: std::ops::RangeToInclusive, ) -> &Self::Output { &self[0..=end] } } }; } // these error messages are shamelessly "borrowed" from std. #[inline(never)] #[cold] #[track_caller] #[cfg(feature = "gil-refs")] pub(crate) fn index_len_fail(index: usize, ty_name: &str, len: usize) -> ! { panic!( "index {} out of range for {} of length {}", index, ty_name, len ); } #[inline(never)] #[cold] #[track_caller] #[cfg(feature = "gil-refs")] pub(crate) fn slice_start_index_len_fail(index: usize, ty_name: &str, len: usize) -> ! { panic!( "range start index {} out of range for {} of length {}", index, ty_name, len ); } #[inline(never)] #[cold] #[track_caller] #[cfg(feature = "gil-refs")] pub(crate) fn slice_end_index_len_fail(index: usize, ty_name: &str, len: usize) -> ! { panic!( "range end index {} out of range for {} of length {}", index, ty_name, len ); } #[inline(never)] #[cold] #[track_caller] #[cfg(feature = "gil-refs")] pub(crate) fn slice_index_order_fail(index: usize, end: usize) -> ! { panic!("slice index starts at {} but ends at {}", index, end); } // TODO: use ptr::from_ref on MSRV 1.76 #[inline] pub(crate) const fn ptr_from_ref(t: &T) -> *const T { t as *const T } // TODO: use ptr::from_mut on MSRV 1.76 #[inline] pub(crate) fn ptr_from_mut(t: &mut T) -> *mut T { t as *mut T } pyo3/src/types/0000775000175000017500000000000014661133735014370 5ustar jamespagejamespagepyo3/src/types/code.rs0000644000175000017500000000126714661133735015654 0ustar jamespagejamespageuse crate::ffi; use crate::PyAny; /// Represents a Python code object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyCode>`][crate::Bound]. #[repr(transparent)] pub struct PyCode(PyAny); pyobject_native_type_core!( PyCode, pyobject_native_static_type_object!(ffi::PyCode_Type), #checkfunction=ffi::PyCode_Check ); #[cfg(test)] mod tests { use super::*; use crate::types::PyTypeMethods; use crate::{PyTypeInfo, Python}; #[test] fn test_type_object() { Python::with_gil(|py| { assert_eq!(PyCode::type_object_bound(py).name().unwrap(), "code"); }) } } pyo3/src/types/num.rs0000644000175000017500000000112614661133735015533 0ustar jamespagejamespageuse crate::{ffi, PyAny}; /// Represents a Python `int` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyLong>`][crate::Bound]. /// /// You can usually avoid directly working with this type /// by using [`ToPyObject`](crate::conversion::ToPyObject) /// and [`extract`](super::PyAnyMethods::extract) /// with the primitive Rust integer types. #[repr(transparent)] pub struct PyLong(PyAny); pyobject_native_type_core!(PyLong, pyobject_native_static_type_object!(ffi::PyLong_Type), #checkfunction=ffi::PyLong_Check); pyo3/src/types/list.rs0000644000175000017500000012621714661133735015720 0ustar jamespagejamespageuse std::iter::FusedIterator; use crate::err::{self, PyResult}; use crate::ffi::{self, Py_ssize_t}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Borrowed; use crate::internal_tricks::get_ssize_index; use crate::types::{PySequence, PyTuple}; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{Bound, PyAny, PyObject, Python, ToPyObject}; use crate::types::any::PyAnyMethods; use crate::types::sequence::PySequenceMethods; /// Represents a Python `list`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyList>`][Bound]. /// /// For APIs available on `list` objects, see the [`PyListMethods`] trait which is implemented for /// [`Bound<'py, PyDict>`][Bound]. #[repr(transparent)] pub struct PyList(PyAny); pyobject_native_type_core!(PyList, pyobject_native_static_type_object!(ffi::PyList_Type), #checkfunction=ffi::PyList_Check); #[inline] #[track_caller] pub(crate) fn new_from_iter<'py>( py: Python<'py>, elements: &mut dyn ExactSizeIterator, ) -> Bound<'py, PyList> { unsafe { // PyList_New checks for overflow but has a bad error message, so we check ourselves let len: Py_ssize_t = elements .len() .try_into() .expect("out of range integral type conversion attempted on `elements.len()`"); let ptr = ffi::PyList_New(len); // We create the `Bound` pointer here for two reasons: // - panics if the ptr is null // - its Drop cleans up the list if user code or the asserts panic. let list = ptr.assume_owned(py).downcast_into_unchecked(); let mut counter: Py_ssize_t = 0; for obj in elements.take(len as usize) { #[cfg(not(Py_LIMITED_API))] ffi::PyList_SET_ITEM(ptr, counter, obj.into_ptr()); #[cfg(Py_LIMITED_API)] ffi::PyList_SetItem(ptr, counter, obj.into_ptr()); counter += 1; } assert!(elements.next().is_none(), "Attempted to create PyList but `elements` was larger than reported by its `ExactSizeIterator` implementation."); assert_eq!(len, counter, "Attempted to create PyList but `elements` was smaller than reported by its `ExactSizeIterator` implementation."); list } } impl PyList { /// Constructs a new list with the given elements. /// /// If you want to create a [`PyList`] with elements of different or unknown types, or from an /// iterable that doesn't implement [`ExactSizeIterator`], use [`PyListMethods::append`]. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyList; /// /// # fn main() { /// Python::with_gil(|py| { /// let elements: Vec = vec![0, 1, 2, 3, 4, 5]; /// let list = PyList::new_bound(py, elements); /// assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5]"); /// }); /// # } /// ``` /// /// # Panics /// /// This function will panic if `element`'s [`ExactSizeIterator`] implementation is incorrect. /// All standard library structures implement this trait correctly, if they do, so calling this /// function with (for example) [`Vec`]`` or `&[T]` will always succeed. #[track_caller] pub fn new_bound( py: Python<'_>, elements: impl IntoIterator, ) -> Bound<'_, PyList> where T: ToPyObject, U: ExactSizeIterator, { let mut iter = elements.into_iter().map(|e| e.to_object(py)); new_from_iter(py, &mut iter) } /// Constructs a new empty list. pub fn empty_bound(py: Python<'_>) -> Bound<'_, PyList> { unsafe { ffi::PyList_New(0) .assume_owned(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyList { /// Deprecated form of [`PyList::new_bound`]. #[inline] #[track_caller] #[deprecated( since = "0.21.0", note = "`PyList::new` will be replaced by `PyList::new_bound` in a future PyO3 version" )] pub fn new(py: Python<'_>, elements: impl IntoIterator) -> &PyList where T: ToPyObject, U: ExactSizeIterator, { Self::new_bound(py, elements).into_gil_ref() } /// Deprecated form of [`PyList::empty_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyList::empty` will be replaced by `PyList::empty_bound` in a future PyO3 version" )] pub fn empty(py: Python<'_>) -> &PyList { Self::empty_bound(py).into_gil_ref() } /// Returns the length of the list. pub fn len(&self) -> usize { self.as_borrowed().len() } /// Checks if the list is empty. pub fn is_empty(&self) -> bool { self.as_borrowed().is_empty() } /// Returns `self` cast as a `PySequence`. pub fn as_sequence(&self) -> &PySequence { unsafe { self.downcast_unchecked() } } /// Gets the list item at the specified index. /// # Example /// ``` /// use pyo3::{prelude::*, types::PyList}; /// Python::with_gil(|py| { /// let list = PyList::new_bound(py, [2, 3, 5, 7]); /// let obj = list.get_item(0); /// assert_eq!(obj.unwrap().extract::().unwrap(), 2); /// }); /// ``` pub fn get_item(&self, index: usize) -> PyResult<&PyAny> { self.as_borrowed().get_item(index).map(Bound::into_gil_ref) } /// Gets the list item at the specified index. Undefined behavior on bad index. Use with caution. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the list. #[cfg(not(Py_LIMITED_API))] pub unsafe fn get_item_unchecked(&self, index: usize) -> &PyAny { self.as_borrowed().get_item_unchecked(index).into_gil_ref() } /// Takes the slice `self[low:high]` and returns it as a new list. /// /// Indices must be nonnegative, and out-of-range indices are clipped to /// `self.len()`. pub fn get_slice(&self, low: usize, high: usize) -> &PyList { self.as_borrowed().get_slice(low, high).into_gil_ref() } /// Sets the item at the specified index. /// /// Raises `IndexError` if the index is out of range. pub fn set_item(&self, index: usize, item: I) -> PyResult<()> where I: ToPyObject, { self.as_borrowed().set_item(index, item) } /// Deletes the `index`th element of self. /// /// This is equivalent to the Python statement `del self[i]`. #[inline] pub fn del_item(&self, index: usize) -> PyResult<()> { self.as_borrowed().del_item(index) } /// Assigns the sequence `seq` to the slice of `self` from `low` to `high`. /// /// This is equivalent to the Python statement `self[low:high] = v`. #[inline] pub fn set_slice(&self, low: usize, high: usize, seq: &PyAny) -> PyResult<()> { self.as_borrowed().set_slice(low, high, &seq.as_borrowed()) } /// Deletes the slice from `low` to `high` from `self`. /// /// This is equivalent to the Python statement `del self[low:high]`. #[inline] pub fn del_slice(&self, low: usize, high: usize) -> PyResult<()> { self.as_borrowed().del_slice(low, high) } /// Appends an item to the list. pub fn append(&self, item: I) -> PyResult<()> where I: ToPyObject, { self.as_borrowed().append(item) } /// Inserts an item at the specified index. /// /// If `index >= self.len()`, inserts at the end. pub fn insert(&self, index: usize, item: I) -> PyResult<()> where I: ToPyObject, { self.as_borrowed().insert(index, item) } /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. #[inline] pub fn contains(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().contains(value) } /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. #[inline] pub fn index(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().index(value) } /// Returns an iterator over this list's items. pub fn iter(&self) -> PyListIterator<'_> { PyListIterator(self.as_borrowed().iter()) } /// Sorts the list in-place. Equivalent to the Python expression `l.sort()`. pub fn sort(&self) -> PyResult<()> { self.as_borrowed().sort() } /// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`. pub fn reverse(&self) -> PyResult<()> { self.as_borrowed().reverse() } /// Return a new tuple containing the contents of the list; equivalent to the Python expression `tuple(list)`. /// /// This method is equivalent to `self.as_sequence().to_tuple()` and faster than `PyTuple::new(py, this_list)`. pub fn to_tuple(&self) -> &PyTuple { self.as_borrowed().to_tuple().into_gil_ref() } } #[cfg(feature = "gil-refs")] index_impls!(PyList, "list", PyList::len, PyList::get_slice); /// Implementation of functionality for [`PyList`]. /// /// These methods are defined for the `Bound<'py, PyList>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyList")] pub trait PyListMethods<'py>: crate::sealed::Sealed { /// Returns the length of the list. fn len(&self) -> usize; /// Checks if the list is empty. fn is_empty(&self) -> bool; /// Returns `self` cast as a `PySequence`. fn as_sequence(&self) -> &Bound<'py, PySequence>; /// Returns `self` cast as a `PySequence`. fn into_sequence(self) -> Bound<'py, PySequence>; /// Gets the list item at the specified index. /// # Example /// ``` /// use pyo3::{prelude::*, types::PyList}; /// Python::with_gil(|py| { /// let list = PyList::new_bound(py, [2, 3, 5, 7]); /// let obj = list.get_item(0); /// assert_eq!(obj.unwrap().extract::().unwrap(), 2); /// }); /// ``` fn get_item(&self, index: usize) -> PyResult>; /// Gets the list item at the specified index. Undefined behavior on bad index. Use with caution. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the list. #[cfg(not(Py_LIMITED_API))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny>; /// Takes the slice `self[low:high]` and returns it as a new list. /// /// Indices must be nonnegative, and out-of-range indices are clipped to /// `self.len()`. fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyList>; /// Sets the item at the specified index. /// /// Raises `IndexError` if the index is out of range. fn set_item(&self, index: usize, item: I) -> PyResult<()> where I: ToPyObject; /// Deletes the `index`th element of self. /// /// This is equivalent to the Python statement `del self[i]`. fn del_item(&self, index: usize) -> PyResult<()>; /// Assigns the sequence `seq` to the slice of `self` from `low` to `high`. /// /// This is equivalent to the Python statement `self[low:high] = v`. fn set_slice(&self, low: usize, high: usize, seq: &Bound<'_, PyAny>) -> PyResult<()>; /// Deletes the slice from `low` to `high` from `self`. /// /// This is equivalent to the Python statement `del self[low:high]`. fn del_slice(&self, low: usize, high: usize) -> PyResult<()>; /// Appends an item to the list. fn append(&self, item: I) -> PyResult<()> where I: ToPyObject; /// Inserts an item at the specified index. /// /// If `index >= self.len()`, inserts at the end. fn insert(&self, index: usize, item: I) -> PyResult<()> where I: ToPyObject; /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. fn contains(&self, value: V) -> PyResult where V: ToPyObject; /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. fn index(&self, value: V) -> PyResult where V: ToPyObject; /// Returns an iterator over this list's items. fn iter(&self) -> BoundListIterator<'py>; /// Sorts the list in-place. Equivalent to the Python expression `l.sort()`. fn sort(&self) -> PyResult<()>; /// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`. fn reverse(&self) -> PyResult<()>; /// Return a new tuple containing the contents of the list; equivalent to the Python expression `tuple(list)`. /// /// This method is equivalent to `self.as_sequence().to_tuple()` and faster than `PyTuple::new(py, this_list)`. fn to_tuple(&self) -> Bound<'py, PyTuple>; } impl<'py> PyListMethods<'py> for Bound<'py, PyList> { /// Returns the length of the list. fn len(&self) -> usize { unsafe { #[cfg(not(Py_LIMITED_API))] let size = ffi::PyList_GET_SIZE(self.as_ptr()); #[cfg(Py_LIMITED_API)] let size = ffi::PyList_Size(self.as_ptr()); // non-negative Py_ssize_t should always fit into Rust usize size as usize } } /// Checks if the list is empty. fn is_empty(&self) -> bool { self.len() == 0 } /// Returns `self` cast as a `PySequence`. fn as_sequence(&self) -> &Bound<'py, PySequence> { unsafe { self.downcast_unchecked() } } /// Returns `self` cast as a `PySequence`. fn into_sequence(self) -> Bound<'py, PySequence> { unsafe { self.into_any().downcast_into_unchecked() } } /// Gets the list item at the specified index. /// # Example /// ``` /// use pyo3::{prelude::*, types::PyList}; /// Python::with_gil(|py| { /// let list = PyList::new_bound(py, [2, 3, 5, 7]); /// let obj = list.get_item(0); /// assert_eq!(obj.unwrap().extract::().unwrap(), 2); /// }); /// ``` fn get_item(&self, index: usize) -> PyResult> { unsafe { // PyList_GetItem return borrowed ptr; must make owned for safety (see #890). ffi::PyList_GetItem(self.as_ptr(), index as Py_ssize_t) .assume_borrowed_or_err(self.py()) .map(Borrowed::to_owned) } } /// Gets the list item at the specified index. Undefined behavior on bad index. Use with caution. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the list. #[cfg(not(Py_LIMITED_API))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny> { // PyList_GET_ITEM return borrowed ptr; must make owned for safety (see #890). ffi::PyList_GET_ITEM(self.as_ptr(), index as Py_ssize_t) .assume_borrowed(self.py()) .to_owned() } /// Takes the slice `self[low:high]` and returns it as a new list. /// /// Indices must be nonnegative, and out-of-range indices are clipped to /// `self.len()`. fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyList> { unsafe { ffi::PyList_GetSlice(self.as_ptr(), get_ssize_index(low), get_ssize_index(high)) .assume_owned(self.py()) .downcast_into_unchecked() } } /// Sets the item at the specified index. /// /// Raises `IndexError` if the index is out of range. fn set_item(&self, index: usize, item: I) -> PyResult<()> where I: ToPyObject, { fn inner(list: &Bound<'_, PyList>, index: usize, item: Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(list.py(), unsafe { ffi::PyList_SetItem(list.as_ptr(), get_ssize_index(index), item.into_ptr()) }) } let py = self.py(); inner(self, index, item.to_object(py).into_bound(py)) } /// Deletes the `index`th element of self. /// /// This is equivalent to the Python statement `del self[i]`. #[inline] fn del_item(&self, index: usize) -> PyResult<()> { self.as_sequence().del_item(index) } /// Assigns the sequence `seq` to the slice of `self` from `low` to `high`. /// /// This is equivalent to the Python statement `self[low:high] = v`. #[inline] fn set_slice(&self, low: usize, high: usize, seq: &Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PyList_SetSlice( self.as_ptr(), get_ssize_index(low), get_ssize_index(high), seq.as_ptr(), ) }) } /// Deletes the slice from `low` to `high` from `self`. /// /// This is equivalent to the Python statement `del self[low:high]`. #[inline] fn del_slice(&self, low: usize, high: usize) -> PyResult<()> { self.as_sequence().del_slice(low, high) } /// Appends an item to the list. fn append(&self, item: I) -> PyResult<()> where I: ToPyObject, { fn inner(list: &Bound<'_, PyList>, item: Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(list.py(), unsafe { ffi::PyList_Append(list.as_ptr(), item.as_ptr()) }) } let py = self.py(); inner(self, item.to_object(py).into_bound(py)) } /// Inserts an item at the specified index. /// /// If `index >= self.len()`, inserts at the end. fn insert(&self, index: usize, item: I) -> PyResult<()> where I: ToPyObject, { fn inner(list: &Bound<'_, PyList>, index: usize, item: Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(list.py(), unsafe { ffi::PyList_Insert(list.as_ptr(), get_ssize_index(index), item.as_ptr()) }) } let py = self.py(); inner(self, index, item.to_object(py).into_bound(py)) } /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. #[inline] fn contains(&self, value: V) -> PyResult where V: ToPyObject, { self.as_sequence().contains(value) } /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. #[inline] fn index(&self, value: V) -> PyResult where V: ToPyObject, { self.as_sequence().index(value) } /// Returns an iterator over this list's items. fn iter(&self) -> BoundListIterator<'py> { BoundListIterator::new(self.clone()) } /// Sorts the list in-place. Equivalent to the Python expression `l.sort()`. fn sort(&self) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PyList_Sort(self.as_ptr()) }) } /// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`. fn reverse(&self) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PyList_Reverse(self.as_ptr()) }) } /// Return a new tuple containing the contents of the list; equivalent to the Python expression `tuple(list)`. /// /// This method is equivalent to `self.as_sequence().to_tuple()` and faster than `PyTuple::new(py, this_list)`. fn to_tuple(&self) -> Bound<'py, PyTuple> { unsafe { ffi::PyList_AsTuple(self.as_ptr()) .assume_owned(self.py()) .downcast_into_unchecked() } } } /// Used by `PyList::iter()`. #[cfg(feature = "gil-refs")] pub struct PyListIterator<'a>(BoundListIterator<'a>); #[cfg(feature = "gil-refs")] impl<'a> Iterator for PyListIterator<'a> { type Item = &'a PyAny; #[inline] fn next(&mut self) -> Option { self.0.next().map(Bound::into_gil_ref) } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[cfg(feature = "gil-refs")] impl<'a> DoubleEndedIterator for PyListIterator<'a> { #[inline] fn next_back(&mut self) -> Option { self.0.next_back().map(Bound::into_gil_ref) } } #[cfg(feature = "gil-refs")] impl<'a> ExactSizeIterator for PyListIterator<'a> { fn len(&self) -> usize { self.0.len() } } #[cfg(feature = "gil-refs")] impl FusedIterator for PyListIterator<'_> {} #[cfg(feature = "gil-refs")] impl<'a> IntoIterator for &'a PyList { type Item = &'a PyAny; type IntoIter = PyListIterator<'a>; fn into_iter(self) -> Self::IntoIter { self.iter() } } /// Used by `PyList::iter()`. pub struct BoundListIterator<'py> { list: Bound<'py, PyList>, index: usize, length: usize, } impl<'py> BoundListIterator<'py> { fn new(list: Bound<'py, PyList>) -> Self { let length: usize = list.len(); BoundListIterator { list, index: 0, length, } } unsafe fn get_item(&self, index: usize) -> Bound<'py, PyAny> { #[cfg(any(Py_LIMITED_API, PyPy))] let item = self.list.get_item(index).expect("list.get failed"); #[cfg(not(any(Py_LIMITED_API, PyPy)))] let item = self.list.get_item_unchecked(index); item } } impl<'py> Iterator for BoundListIterator<'py> { type Item = Bound<'py, PyAny>; #[inline] fn next(&mut self) -> Option { let length = self.length.min(self.list.len()); if self.index < length { let item = unsafe { self.get_item(self.index) }; self.index += 1; Some(item) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } } impl DoubleEndedIterator for BoundListIterator<'_> { #[inline] fn next_back(&mut self) -> Option { let length = self.length.min(self.list.len()); if self.index < length { let item = unsafe { self.get_item(length - 1) }; self.length = length - 1; Some(item) } else { None } } } impl ExactSizeIterator for BoundListIterator<'_> { fn len(&self) -> usize { self.length.saturating_sub(self.index) } } impl FusedIterator for BoundListIterator<'_> {} impl<'py> IntoIterator for Bound<'py, PyList> { type Item = Bound<'py, PyAny>; type IntoIter = BoundListIterator<'py>; fn into_iter(self) -> Self::IntoIter { BoundListIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PyList> { type Item = Bound<'py, PyAny>; type IntoIter = BoundListIterator<'py>; fn into_iter(self) -> Self::IntoIter { self.iter() } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::types::list::PyListMethods; use crate::types::sequence::PySequenceMethods; use crate::types::{PyList, PyTuple}; use crate::Python; use crate::{IntoPy, PyObject, ToPyObject}; #[test] fn test_new() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(3, list.get_item(1).unwrap().extract::().unwrap()); assert_eq!(5, list.get_item(2).unwrap().extract::().unwrap()); assert_eq!(7, list.get_item(3).unwrap().extract::().unwrap()); }); } #[test] fn test_len() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 2, 3, 4]); assert_eq!(4, list.len()); }); } #[test] fn test_get_item() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(3, list.get_item(1).unwrap().extract::().unwrap()); assert_eq!(5, list.get_item(2).unwrap().extract::().unwrap()); assert_eq!(7, list.get_item(3).unwrap().extract::().unwrap()); }); } #[test] fn test_get_slice() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); let slice = list.get_slice(1, 3); assert_eq!(2, slice.len()); let slice = list.get_slice(1, 7); assert_eq!(3, slice.len()); }); } #[test] fn test_set_item() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); let val = 42i32.to_object(py); let val2 = 42i32.to_object(py); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); list.set_item(0, val).unwrap(); assert_eq!(42, list.get_item(0).unwrap().extract::().unwrap()); assert!(list.set_item(10, val2).is_err()); }); } #[test] fn test_set_item_refcnt() { Python::with_gil(|py| { let obj = py.eval_bound("object()", None, None).unwrap(); let cnt; { let v = vec![2]; let ob = v.to_object(py); let list = ob.downcast_bound::(py).unwrap(); cnt = obj.get_refcnt(); list.set_item(0, &obj).unwrap(); } assert_eq!(cnt, obj.get_refcnt()); }); } #[test] fn test_insert() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); let val = 42i32.to_object(py); let val2 = 43i32.to_object(py); assert_eq!(4, list.len()); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); list.insert(0, val).unwrap(); list.insert(1000, val2).unwrap(); assert_eq!(6, list.len()); assert_eq!(42, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(2, list.get_item(1).unwrap().extract::().unwrap()); assert_eq!(43, list.get_item(5).unwrap().extract::().unwrap()); }); } #[test] fn test_insert_refcnt() { Python::with_gil(|py| { let cnt; let obj = py.eval_bound("object()", None, None).unwrap(); { let list = PyList::empty_bound(py); cnt = obj.get_refcnt(); list.insert(0, &obj).unwrap(); } assert_eq!(cnt, obj.get_refcnt()); }); } #[test] fn test_append() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2]); list.append(3).unwrap(); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(3, list.get_item(1).unwrap().extract::().unwrap()); }); } #[test] fn test_append_refcnt() { Python::with_gil(|py| { let cnt; let obj = py.eval_bound("object()", None, None).unwrap(); { let list = PyList::empty_bound(py); cnt = obj.get_refcnt(); list.append(&obj).unwrap(); } assert_eq!(cnt, obj.get_refcnt()); }); } #[test] fn test_iter() { Python::with_gil(|py| { let v = vec![2, 3, 5, 7]; let list = PyList::new_bound(py, &v); let mut idx = 0; for el in list { assert_eq!(v[idx], el.extract::().unwrap()); idx += 1; } assert_eq!(idx, v.len()); }); } #[test] fn test_iter_size_hint() { Python::with_gil(|py| { let v = vec![2, 3, 5, 7]; let ob = v.to_object(py); let list = ob.downcast_bound::(py).unwrap(); let mut iter = list.iter(); assert_eq!(iter.size_hint(), (v.len(), Some(v.len()))); iter.next(); assert_eq!(iter.size_hint(), (v.len() - 1, Some(v.len() - 1))); // Exhaust iterator. for _ in &mut iter {} assert_eq!(iter.size_hint(), (0, Some(0))); }); } #[test] fn test_iter_rev() { Python::with_gil(|py| { let v = vec![2, 3, 5, 7]; let ob = v.to_object(py); let list = ob.downcast_bound::(py).unwrap(); let mut iter = list.iter().rev(); assert_eq!(iter.size_hint(), (4, Some(4))); assert_eq!(iter.next().unwrap().extract::().unwrap(), 7); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(iter.next().unwrap().extract::().unwrap(), 5); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(iter.next().unwrap().extract::().unwrap(), 3); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(iter.next().unwrap().extract::().unwrap(), 2); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_into_iter() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 2, 3, 4]); for (i, item) in list.iter().enumerate() { assert_eq!((i + 1) as i32, item.extract::().unwrap()); } }); } #[test] fn test_into_iter_bound() { use crate::types::any::PyAnyMethods; Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 2, 3, 4]); let mut items = vec![]; for item in &list { items.push(item.extract::().unwrap()); } assert_eq!(items, vec![1, 2, 3, 4]); }); } #[test] fn test_as_sequence() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 2, 3, 4]); assert_eq!(list.as_sequence().len().unwrap(), 4); assert_eq!( list.as_sequence() .get_item(1) .unwrap() .extract::() .unwrap(), 2 ); }); } #[test] fn test_into_sequence() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 2, 3, 4]); let sequence = list.into_sequence(); assert_eq!(sequence.len().unwrap(), 4); assert_eq!(sequence.get_item(1).unwrap().extract::().unwrap(), 2); }); } #[test] fn test_extract() { Python::with_gil(|py| { let v = vec![2, 3, 5, 7]; let list = PyList::new_bound(py, &v); let v2 = list.as_ref().extract::>().unwrap(); assert_eq!(v, v2); }); } #[test] fn test_sort() { Python::with_gil(|py| { let v = vec![7, 3, 2, 5]; let list = PyList::new_bound(py, &v); assert_eq!(7, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(3, list.get_item(1).unwrap().extract::().unwrap()); assert_eq!(2, list.get_item(2).unwrap().extract::().unwrap()); assert_eq!(5, list.get_item(3).unwrap().extract::().unwrap()); list.sort().unwrap(); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(3, list.get_item(1).unwrap().extract::().unwrap()); assert_eq!(5, list.get_item(2).unwrap().extract::().unwrap()); assert_eq!(7, list.get_item(3).unwrap().extract::().unwrap()); }); } #[test] fn test_reverse() { Python::with_gil(|py| { let v = vec![2, 3, 5, 7]; let list = PyList::new_bound(py, &v); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(3, list.get_item(1).unwrap().extract::().unwrap()); assert_eq!(5, list.get_item(2).unwrap().extract::().unwrap()); assert_eq!(7, list.get_item(3).unwrap().extract::().unwrap()); list.reverse().unwrap(); assert_eq!(7, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(5, list.get_item(1).unwrap().extract::().unwrap()); assert_eq!(3, list.get_item(2).unwrap().extract::().unwrap()); assert_eq!(2, list.get_item(3).unwrap().extract::().unwrap()); }); } #[test] fn test_array_into_py() { Python::with_gil(|py| { let array: PyObject = [1, 2].into_py(py); let list = array.downcast_bound::(py).unwrap(); assert_eq!(1, list.get_item(0).unwrap().extract::().unwrap()); assert_eq!(2, list.get_item(1).unwrap().extract::().unwrap()); }); } #[test] fn test_list_get_item_invalid_index() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); let obj = list.get_item(5); assert!(obj.is_err()); assert_eq!( obj.unwrap_err().to_string(), "IndexError: list index out of range" ); }); } #[test] fn test_list_get_item_sanity() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); let obj = list.get_item(0); assert_eq!(obj.unwrap().extract::().unwrap(), 2); }); } #[cfg(not(any(Py_LIMITED_API, PyPy)))] #[test] fn test_list_get_item_unchecked_sanity() { Python::with_gil(|py| { let list = PyList::new_bound(py, [2, 3, 5, 7]); let obj = unsafe { list.get_item_unchecked(0) }; assert_eq!(obj.extract::().unwrap(), 2); }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_list_index_trait() { Python::with_gil(|py| { let list = PyList::new(py, [2, 3, 5]); assert_eq!(2, list[0].extract::().unwrap()); assert_eq!(3, list[1].extract::().unwrap()); assert_eq!(5, list[2].extract::().unwrap()); }); } #[test] #[should_panic] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_list_index_trait_panic() { Python::with_gil(|py| { let list = PyList::new(py, [2, 3, 5]); let _ = &list[7]; }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_list_index_trait_ranges() { Python::with_gil(|py| { let list = PyList::new(py, [2, 3, 5]); assert_eq!(vec![3, 5], list[1..3].extract::>().unwrap()); assert_eq!(Vec::::new(), list[3..3].extract::>().unwrap()); assert_eq!(vec![3, 5], list[1..].extract::>().unwrap()); assert_eq!(Vec::::new(), list[3..].extract::>().unwrap()); assert_eq!(vec![2, 3, 5], list[..].extract::>().unwrap()); assert_eq!(vec![3, 5], list[1..=2].extract::>().unwrap()); assert_eq!(vec![2, 3], list[..2].extract::>().unwrap()); assert_eq!(vec![2, 3], list[..=1].extract::>().unwrap()); }) } #[test] #[should_panic = "range start index 5 out of range for list of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_list_index_trait_range_panic_start() { Python::with_gil(|py| { let list = PyList::new(py, [2, 3, 5]); list[5..10].extract::>().unwrap(); }) } #[test] #[should_panic = "range end index 10 out of range for list of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_list_index_trait_range_panic_end() { Python::with_gil(|py| { let list = PyList::new(py, [2, 3, 5]); list[1..10].extract::>().unwrap(); }) } #[test] #[should_panic = "slice index starts at 2 but ends at 1"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_list_index_trait_range_panic_wrong_order() { Python::with_gil(|py| { let list = PyList::new(py, [2, 3, 5]); #[allow(clippy::reversed_empty_ranges)] list[2..1].extract::>().unwrap(); }) } #[test] #[should_panic = "range start index 8 out of range for list of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_list_index_trait_range_from_panic() { Python::with_gil(|py| { let list = PyList::new(py, [2, 3, 5]); list[8..].extract::>().unwrap(); }) } #[test] fn test_list_del_item() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 1, 2, 3, 5, 8]); assert!(list.del_item(10).is_err()); assert_eq!(1, list.get_item(0).unwrap().extract::().unwrap()); assert!(list.del_item(0).is_ok()); assert_eq!(1, list.get_item(0).unwrap().extract::().unwrap()); assert!(list.del_item(0).is_ok()); assert_eq!(2, list.get_item(0).unwrap().extract::().unwrap()); assert!(list.del_item(0).is_ok()); assert_eq!(3, list.get_item(0).unwrap().extract::().unwrap()); assert!(list.del_item(0).is_ok()); assert_eq!(5, list.get_item(0).unwrap().extract::().unwrap()); assert!(list.del_item(0).is_ok()); assert_eq!(8, list.get_item(0).unwrap().extract::().unwrap()); assert!(list.del_item(0).is_ok()); assert_eq!(0, list.len()); assert!(list.del_item(0).is_err()); }); } #[test] fn test_list_set_slice() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 1, 2, 3, 5, 8]); let ins = PyList::new_bound(py, [7, 4]); list.set_slice(1, 4, &ins).unwrap(); assert_eq!([1, 7, 4, 5, 8], list.extract::<[i32; 5]>().unwrap()); list.set_slice(3, 100, &PyList::empty_bound(py)).unwrap(); assert_eq!([1, 7, 4], list.extract::<[i32; 3]>().unwrap()); }); } #[test] fn test_list_del_slice() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 1, 2, 3, 5, 8]); list.del_slice(1, 4).unwrap(); assert_eq!([1, 5, 8], list.extract::<[i32; 3]>().unwrap()); list.del_slice(1, 100).unwrap(); assert_eq!([1], list.extract::<[i32; 1]>().unwrap()); }); } #[test] fn test_list_contains() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 1, 2, 3, 5, 8]); assert_eq!(6, list.len()); let bad_needle = 7i32.to_object(py); assert!(!list.contains(&bad_needle).unwrap()); let good_needle = 8i32.to_object(py); assert!(list.contains(&good_needle).unwrap()); let type_coerced_needle = 8f32.to_object(py); assert!(list.contains(&type_coerced_needle).unwrap()); }); } #[test] fn test_list_index() { Python::with_gil(|py| { let list = PyList::new_bound(py, [1, 1, 2, 3, 5, 8]); assert_eq!(0, list.index(1i32).unwrap()); assert_eq!(2, list.index(2i32).unwrap()); assert_eq!(3, list.index(3i32).unwrap()); assert_eq!(4, list.index(5i32).unwrap()); assert_eq!(5, list.index(8i32).unwrap()); assert!(list.index(42i32).is_err()); }); } use std::ops::Range; // An iterator that lies about its `ExactSizeIterator` implementation. // See https://github.com/PyO3/pyo3/issues/2118 struct FaultyIter(Range, usize); impl Iterator for FaultyIter { type Item = usize; fn next(&mut self) -> Option { self.0.next() } } impl ExactSizeIterator for FaultyIter { fn len(&self) -> usize { self.1 } } #[test] #[should_panic( expected = "Attempted to create PyList but `elements` was larger than reported by its `ExactSizeIterator` implementation." )] fn too_long_iterator() { Python::with_gil(|py| { let iter = FaultyIter(0..usize::MAX, 73); let _list = PyList::new_bound(py, iter); }) } #[test] #[should_panic( expected = "Attempted to create PyList but `elements` was smaller than reported by its `ExactSizeIterator` implementation." )] fn too_short_iterator() { Python::with_gil(|py| { let iter = FaultyIter(0..35, 73); let _list = PyList::new_bound(py, iter); }) } #[test] #[should_panic( expected = "out of range integral type conversion attempted on `elements.len()`" )] fn overflowing_size() { Python::with_gil(|py| { let iter = FaultyIter(0..0, usize::MAX); let _list = PyList::new_bound(py, iter); }) } #[cfg(feature = "macros")] #[test] fn bad_clone_mem_leaks() { use crate::{Py, PyAny}; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0); #[crate::pyclass] #[pyo3(crate = "crate")] struct Bad(usize); impl Clone for Bad { fn clone(&self) -> Self { // This panic should not lead to a memory leak assert_ne!(self.0, 42); NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst); Bad(self.0) } } impl Drop for Bad { fn drop(&mut self) { NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst); } } impl ToPyObject for Bad { fn to_object(&self, py: Python<'_>) -> Py { self.to_owned().into_py(py) } } struct FaultyIter(Range, usize); impl Iterator for FaultyIter { type Item = Bad; fn next(&mut self) -> Option { self.0.next().map(|i| { NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst); Bad(i) }) } } impl ExactSizeIterator for FaultyIter { fn len(&self) -> usize { self.1 } } Python::with_gil(|py| { std::panic::catch_unwind(|| { let iter = FaultyIter(0..50, 50); let _list = PyList::new_bound(py, iter); }) .unwrap_err(); }); assert_eq!( NEEDS_DESTRUCTING_COUNT.load(SeqCst), 0, "Some destructors did not run" ); } #[test] fn test_list_to_tuple() { Python::with_gil(|py| { let list = PyList::new_bound(py, vec![1, 2, 3]); let tuple = list.to_tuple(); let tuple_expected = PyTuple::new_bound(py, vec![1, 2, 3]); assert!(tuple.eq(tuple_expected).unwrap()); }) } } pyo3/src/types/function.rs0000644000175000017500000002160214661133735016562 0ustar jamespagejamespage#[cfg(feature = "gil-refs")] use crate::derive_utils::PyFunctionArguments; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::types::capsule::PyCapsuleMethods; use crate::types::module::PyModuleMethods; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ ffi, impl_::pymethods::{self, PyMethodDef}, types::{PyCapsule, PyDict, PyModule, PyString, PyTuple}, }; use crate::{Bound, IntoPy, Py, PyAny, PyResult, Python}; use std::cell::UnsafeCell; use std::ffi::CStr; /// Represents a builtin Python function object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyCFunction>`][Bound]. #[repr(transparent)] pub struct PyCFunction(PyAny); pyobject_native_type_core!(PyCFunction, pyobject_native_static_type_object!(ffi::PyCFunction_Type), #checkfunction=ffi::PyCFunction_Check); impl PyCFunction { /// Deprecated form of [`PyCFunction::new_with_keywords_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyCFunction::new_with_keywords` will be replaced by `PyCFunction::new_with_keywords_bound` in a future PyO3 version" )] pub fn new_with_keywords<'a>( fun: ffi::PyCFunctionWithKeywords, name: &'static CStr, doc: &'static CStr, py_or_module: PyFunctionArguments<'a>, ) -> PyResult<&'a Self> { let (py, module) = py_or_module.into_py_and_maybe_module(); Self::internal_new( py, &PyMethodDef::cfunction_with_keywords(name, fun, doc), module.map(PyNativeType::as_borrowed).as_deref(), ) .map(Bound::into_gil_ref) } /// Create a new built-in function with keywords (*args and/or **kwargs). /// /// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c"" literals), /// use the [`c_str!`](crate::ffi::c_str) macro. pub fn new_with_keywords_bound<'py>( py: Python<'py>, fun: ffi::PyCFunctionWithKeywords, name: &'static CStr, doc: &'static CStr, module: Option<&Bound<'py, PyModule>>, ) -> PyResult> { Self::internal_new( py, &PyMethodDef::cfunction_with_keywords(name, fun, doc), module, ) } /// Deprecated form of [`PyCFunction::new`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyCFunction::new` will be replaced by `PyCFunction::new_bound` in a future PyO3 version" )] pub fn new<'a>( fun: ffi::PyCFunction, name: &'static CStr, doc: &'static CStr, py_or_module: PyFunctionArguments<'a>, ) -> PyResult<&'a Self> { let (py, module) = py_or_module.into_py_and_maybe_module(); Self::internal_new( py, &PyMethodDef::noargs(name, fun, doc), module.map(PyNativeType::as_borrowed).as_deref(), ) .map(Bound::into_gil_ref) } /// Create a new built-in function which takes no arguments. /// /// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c"" literals), /// use the [`c_str!`](crate::ffi::c_str) macro. pub fn new_bound<'py>( py: Python<'py>, fun: ffi::PyCFunction, name: &'static CStr, doc: &'static CStr, module: Option<&Bound<'py, PyModule>>, ) -> PyResult> { Self::internal_new(py, &PyMethodDef::noargs(name, fun, doc), module) } /// Deprecated form of [`PyCFunction::new_closure`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyCFunction::new_closure` will be replaced by `PyCFunction::new_closure_bound` in a future PyO3 version" )] pub fn new_closure<'a, F, R>( py: Python<'a>, name: Option<&'static CStr>, doc: Option<&'static CStr>, closure: F, ) -> PyResult<&'a PyCFunction> where F: Fn(&PyTuple, Option<&PyDict>) -> R + Send + 'static, R: crate::callback::IntoPyCallbackOutput<*mut ffi::PyObject>, { Self::new_closure_bound(py, name, doc, move |args, kwargs| { closure(args.as_gil_ref(), kwargs.map(Bound::as_gil_ref)) }) .map(Bound::into_gil_ref) } /// Create a new function from a closure. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::{py_run, types::{PyCFunction, PyDict, PyTuple}}; /// /// Python::with_gil(|py| { /// let add_one = |args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>| -> PyResult<_> { /// let i = args.extract::<(i64,)>()?.0; /// Ok(i+1) /// }; /// let add_one = PyCFunction::new_closure_bound(py, None, None, add_one).unwrap(); /// py_run!(py, add_one, "assert add_one(42) == 43"); /// }); /// ``` pub fn new_closure_bound<'py, F, R>( py: Python<'py>, name: Option<&'static CStr>, doc: Option<&'static CStr>, closure: F, ) -> PyResult> where F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static, R: crate::callback::IntoPyCallbackOutput<*mut ffi::PyObject>, { let name = name.unwrap_or(ffi::c_str!("pyo3-closure")); let doc = doc.unwrap_or(ffi::c_str!("")); let method_def = pymethods::PyMethodDef::cfunction_with_keywords(name, run_closure::, doc); let def = method_def.as_method_def(); let capsule = PyCapsule::new_bound( py, ClosureDestructor:: { closure, def: UnsafeCell::new(def), }, Some(CLOSURE_CAPSULE_NAME.to_owned()), )?; // Safety: just created the capsule with type ClosureDestructor above let data = unsafe { capsule.reference::>() }; unsafe { ffi::PyCFunction_NewEx(data.def.get(), capsule.as_ptr(), std::ptr::null_mut()) .assume_owned_or_err(py) .downcast_into_unchecked() } } #[doc(hidden)] pub fn internal_new<'py>( py: Python<'py>, method_def: &PyMethodDef, module: Option<&Bound<'py, PyModule>>, ) -> PyResult> { let (mod_ptr, module_name): (_, Option>) = if let Some(m) = module { let mod_ptr = m.as_ptr(); (mod_ptr, Some(m.name()?.into_py(py))) } else { (std::ptr::null_mut(), None) }; let def = method_def.as_method_def(); // FIXME: stop leaking the def let def = Box::into_raw(Box::new(def)); let module_name_ptr = module_name .as_ref() .map_or(std::ptr::null_mut(), Py::as_ptr); unsafe { ffi::PyCFunction_NewEx(def, mod_ptr, module_name_ptr) .assume_owned_or_err(py) .downcast_into_unchecked() } } } static CLOSURE_CAPSULE_NAME: &CStr = ffi::c_str!("pyo3-closure"); unsafe extern "C" fn run_closure( capsule_ptr: *mut ffi::PyObject, args: *mut ffi::PyObject, kwargs: *mut ffi::PyObject, ) -> *mut ffi::PyObject where F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static, R: crate::callback::IntoPyCallbackOutput<*mut ffi::PyObject>, { use crate::types::any::PyAnyMethods; crate::impl_::trampoline::cfunction_with_keywords( capsule_ptr, args, kwargs, |py, capsule_ptr, args, kwargs| { let boxed_fn: &ClosureDestructor = &*(ffi::PyCapsule_GetPointer(capsule_ptr, CLOSURE_CAPSULE_NAME.as_ptr()) as *mut ClosureDestructor); let args = Bound::ref_from_ptr(py, &args).downcast_unchecked::(); let kwargs = Bound::ref_from_ptr_or_opt(py, &kwargs) .as_ref() .map(|b| b.downcast_unchecked::()); let result = (boxed_fn.closure)(args, kwargs); crate::callback::convert(py, result) }, ) } struct ClosureDestructor { closure: F, // Wrapped in UnsafeCell because Python C-API wants a *mut pointer // to this member. def: UnsafeCell, } // Safety: F is send and none of the fields are ever mutated unsafe impl Send for ClosureDestructor {} /// Represents a Python function object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyFunction>`][Bound]. #[repr(transparent)] #[cfg(all(not(Py_LIMITED_API), not(all(PyPy, not(Py_3_8)))))] pub struct PyFunction(PyAny); #[cfg(all(not(Py_LIMITED_API), not(all(PyPy, not(Py_3_8)))))] pyobject_native_type_core!(PyFunction, pyobject_native_static_type_object!(ffi::PyFunction_Type), #checkfunction=ffi::PyFunction_Check); pyo3/src/types/capsule.rs0000644000175000017500000005070714661133735016401 0ustar jamespagejamespageuse crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, PyAny}; use crate::{Bound, Python}; use crate::{PyErr, PyResult}; use std::ffi::{CStr, CString}; use std::os::raw::{c_char, c_int, c_void}; /// Represents a Python Capsule /// as described in [Capsules](https://docs.python.org/3/c-api/capsule.html#capsules): /// > This subtype of PyObject represents an opaque value, useful for C extension /// > modules who need to pass an opaque value (as a void* pointer) through Python /// > code to other C code. It is often used to make a C function pointer defined /// > in one module available to other modules, so the regular import mechanism can /// > be used to access C APIs defined in dynamically loaded modules. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyCapsule>`][Bound]. /// /// For APIs available on capsule objects, see the [`PyCapsuleMethods`] trait which is implemented for /// [`Bound<'py, PyCapsule>`][Bound]. /// /// # Example /// ``` /// use pyo3::{prelude::*, types::PyCapsule}; /// use std::ffi::CString; /// /// #[repr(C)] /// struct Foo { /// pub val: u32, /// } /// /// let r = Python::with_gil(|py| -> PyResult<()> { /// let foo = Foo { val: 123 }; /// let name = CString::new("builtins.capsule").unwrap(); /// /// let capsule = PyCapsule::new_bound(py, foo, Some(name.clone()))?; /// /// let module = PyModule::import_bound(py, "builtins")?; /// module.add("capsule", capsule)?; /// /// let cap: &Foo = unsafe { PyCapsule::import(py, name.as_ref())? }; /// assert_eq!(cap.val, 123); /// Ok(()) /// }); /// assert!(r.is_ok()); /// ``` #[repr(transparent)] pub struct PyCapsule(PyAny); pyobject_native_type_core!(PyCapsule, pyobject_native_static_type_object!(ffi::PyCapsule_Type), #checkfunction=ffi::PyCapsule_CheckExact); impl PyCapsule { /// Constructs a new capsule whose contents are `value`, associated with `name`. /// `name` is the identifier for the capsule; if it is stored as an attribute of a module, /// the name should be in the format `"modulename.attribute"`. /// /// It is checked at compile time that the type T is not zero-sized. Rust function items /// need to be cast to a function pointer (`fn(args) -> result`) to be put into a capsule. /// /// # Example /// /// ``` /// use pyo3::{prelude::*, types::PyCapsule}; /// use std::ffi::CString; /// /// Python::with_gil(|py| { /// let name = CString::new("foo").unwrap(); /// let capsule = PyCapsule::new_bound(py, 123_u32, Some(name)).unwrap(); /// let val = unsafe { capsule.reference::() }; /// assert_eq!(*val, 123); /// }); /// ``` /// /// However, attempting to construct a `PyCapsule` with a zero-sized type will not compile: /// /// ```compile_fail /// use pyo3::{prelude::*, types::PyCapsule}; /// use std::ffi::CString; /// /// Python::with_gil(|py| { /// let capsule = PyCapsule::new_bound(py, (), None).unwrap(); // Oops! `()` is zero sized! /// }); /// ``` pub fn new_bound( py: Python<'_>, value: T, name: Option, ) -> PyResult> { Self::new_bound_with_destructor(py, value, name, |_, _| {}) } /// Constructs a new capsule whose contents are `value`, associated with `name`. /// /// Also provides a destructor: when the `PyCapsule` is destroyed, it will be passed the original object, /// as well as a `*mut c_void` which will point to the capsule's context, if any. /// /// The `destructor` must be `Send`, because there is no guarantee which thread it will eventually /// be called from. pub fn new_bound_with_destructor< T: 'static + Send + AssertNotZeroSized, F: FnOnce(T, *mut c_void) + Send, >( py: Python<'_>, value: T, name: Option, destructor: F, ) -> PyResult> { AssertNotZeroSized::assert_not_zero_sized(&value); // Sanity check for capsule layout debug_assert_eq!(memoffset::offset_of!(CapsuleContents::, value), 0); let name_ptr = name.as_ref().map_or(std::ptr::null(), |name| name.as_ptr()); let val = Box::new(CapsuleContents { value, destructor, name, }); unsafe { ffi::PyCapsule_New( Box::into_raw(val).cast(), name_ptr, Some(capsule_destructor::), ) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Imports an existing capsule. /// /// The `name` should match the path to the module attribute exactly in the form /// of `"module.attribute"`, which should be the same as the name within the capsule. /// /// # Safety /// /// It must be known that the capsule imported by `name` contains an item of type `T`. pub unsafe fn import<'py, T>(py: Python<'py>, name: &CStr) -> PyResult<&'py T> { let ptr = ffi::PyCapsule_Import(name.as_ptr(), false as c_int); if ptr.is_null() { Err(PyErr::fetch(py)) } else { Ok(&*ptr.cast::()) } } } #[cfg(feature = "gil-refs")] impl PyCapsule { /// Deprecated form of [`PyCapsule::new_bound`]. #[deprecated( since = "0.21.0", note = "`PyCapsule::new` will be replaced by `PyCapsule::new_bound` in a future PyO3 version" )] pub fn new( py: Python<'_>, value: T, name: Option, ) -> PyResult<&Self> { Self::new_bound(py, value, name).map(Bound::into_gil_ref) } /// Deprecated form of [`PyCapsule::new_bound_with_destructor`]. #[deprecated( since = "0.21.0", note = "`PyCapsule::new_with_destructor` will be replaced by `PyCapsule::new_bound_with_destructor` in a future PyO3 version" )] pub fn new_with_destructor< T: 'static + Send + AssertNotZeroSized, F: FnOnce(T, *mut c_void) + Send, >( py: Python<'_>, value: T, name: Option, destructor: F, ) -> PyResult<&'_ Self> { Self::new_bound_with_destructor(py, value, name, destructor).map(Bound::into_gil_ref) } /// Sets the context pointer in the capsule. /// /// Returns an error if this capsule is not valid. /// /// # Notes /// /// The context is treated much like the value of the capsule, but should likely act as /// a place to store any state management when using the capsule. /// /// If you want to store a Rust value as the context, and drop it from the destructor, use /// `Box::into_raw` to convert it into a pointer, see the example. /// /// # Example /// /// ``` /// use std::sync::mpsc::{channel, Sender}; /// use libc::c_void; /// use pyo3::{prelude::*, types::PyCapsule}; /// /// let (tx, rx) = channel::(); /// /// fn destructor(val: u32, context: *mut c_void) { /// let ctx = unsafe { *Box::from_raw(context.cast::>()) }; /// ctx.send("Destructor called!".to_string()).unwrap(); /// } /// /// Python::with_gil(|py| { /// let capsule = /// PyCapsule::new_bound_with_destructor(py, 123, None, destructor as fn(u32, *mut c_void)) /// .unwrap(); /// let context = Box::new(tx); // `Sender` is our context, box it up and ship it! /// capsule.set_context(Box::into_raw(context).cast()).unwrap(); /// // This scope will end, causing our destructor to be called... /// }); /// /// assert_eq!(rx.recv(), Ok("Destructor called!".to_string())); /// ``` pub fn set_context(&self, context: *mut c_void) -> PyResult<()> { self.as_borrowed().set_context(context) } /// Gets the current context stored in the capsule. If there is no context, the pointer /// will be null. /// /// Returns an error if this capsule is not valid. pub fn context(&self) -> PyResult<*mut c_void> { self.as_borrowed().context() } /// Obtains a reference to the value of this capsule. /// /// # Safety /// /// It must be known that this capsule is valid and its pointer is to an item of type `T`. pub unsafe fn reference(&self) -> &T { self.as_borrowed().reference() } /// Gets the raw `c_void` pointer to the value in this capsule. /// /// Returns null if this capsule is not valid. pub fn pointer(&self) -> *mut c_void { self.as_borrowed().pointer() } /// Checks if this is a valid capsule. /// /// Returns true if the stored `pointer()` is non-null. pub fn is_valid(&self) -> bool { self.as_borrowed().is_valid() } /// Retrieves the name of this capsule, if set. /// /// Returns an error if this capsule is not valid. pub fn name(&self) -> PyResult> { self.as_borrowed().name() } } /// Implementation of functionality for [`PyCapsule`]. /// /// These methods are defined for the `Bound<'py, PyCapsule>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyCapsule")] pub trait PyCapsuleMethods<'py>: crate::sealed::Sealed { /// Sets the context pointer in the capsule. /// /// Returns an error if this capsule is not valid. /// /// # Notes /// /// The context is treated much like the value of the capsule, but should likely act as /// a place to store any state management when using the capsule. /// /// If you want to store a Rust value as the context, and drop it from the destructor, use /// `Box::into_raw` to convert it into a pointer, see the example. /// /// # Example /// /// ``` /// use std::sync::mpsc::{channel, Sender}; /// use libc::c_void; /// use pyo3::{prelude::*, types::PyCapsule}; /// /// let (tx, rx) = channel::(); /// /// fn destructor(val: u32, context: *mut c_void) { /// let ctx = unsafe { *Box::from_raw(context.cast::>()) }; /// ctx.send("Destructor called!".to_string()).unwrap(); /// } /// /// Python::with_gil(|py| { /// let capsule = /// PyCapsule::new_bound_with_destructor(py, 123, None, destructor as fn(u32, *mut c_void)) /// .unwrap(); /// let context = Box::new(tx); // `Sender` is our context, box it up and ship it! /// capsule.set_context(Box::into_raw(context).cast()).unwrap(); /// // This scope will end, causing our destructor to be called... /// }); /// /// assert_eq!(rx.recv(), Ok("Destructor called!".to_string())); /// ``` fn set_context(&self, context: *mut c_void) -> PyResult<()>; /// Gets the current context stored in the capsule. If there is no context, the pointer /// will be null. /// /// Returns an error if this capsule is not valid. fn context(&self) -> PyResult<*mut c_void>; /// Obtains a reference to the value of this capsule. /// /// # Safety /// /// It must be known that this capsule is valid and its pointer is to an item of type `T`. unsafe fn reference(&self) -> &'py T; /// Gets the raw `c_void` pointer to the value in this capsule. /// /// Returns null if this capsule is not valid. fn pointer(&self) -> *mut c_void; /// Checks if this is a valid capsule. /// /// Returns true if the stored `pointer()` is non-null. fn is_valid(&self) -> bool; /// Retrieves the name of this capsule, if set. /// /// Returns an error if this capsule is not valid. fn name(&self) -> PyResult>; } impl<'py> PyCapsuleMethods<'py> for Bound<'py, PyCapsule> { #[allow(clippy::not_unsafe_ptr_arg_deref)] fn set_context(&self, context: *mut c_void) -> PyResult<()> { let result = unsafe { ffi::PyCapsule_SetContext(self.as_ptr(), context) }; if result != 0 { Err(PyErr::fetch(self.py())) } else { Ok(()) } } fn context(&self) -> PyResult<*mut c_void> { let ctx = unsafe { ffi::PyCapsule_GetContext(self.as_ptr()) }; if ctx.is_null() { ensure_no_error(self.py())? } Ok(ctx) } unsafe fn reference(&self) -> &'py T { &*self.pointer().cast() } fn pointer(&self) -> *mut c_void { unsafe { let ptr = ffi::PyCapsule_GetPointer(self.as_ptr(), name_ptr_ignore_error(self)); if ptr.is_null() { ffi::PyErr_Clear(); } ptr } } fn is_valid(&self) -> bool { // As well as if the stored pointer is null, PyCapsule_IsValid also returns false if // self.as_ptr() is null or not a ptr to a PyCapsule object. Both of these are guaranteed // to not be the case thanks to invariants of this PyCapsule struct. let r = unsafe { ffi::PyCapsule_IsValid(self.as_ptr(), name_ptr_ignore_error(self)) }; r != 0 } fn name(&self) -> PyResult> { unsafe { let ptr = ffi::PyCapsule_GetName(self.as_ptr()); if ptr.is_null() { ensure_no_error(self.py())?; Ok(None) } else { Ok(Some(CStr::from_ptr(ptr))) } } } } // C layout, as PyCapsule::get_reference depends on `T` being first. #[repr(C)] struct CapsuleContents { /// Value of the capsule value: T, /// Destructor to be used by the capsule destructor: D, /// Name used when creating the capsule name: Option, } // Wrapping ffi::PyCapsule_Destructor for a user supplied FnOnce(T) for capsule destructor unsafe extern "C" fn capsule_destructor( capsule: *mut ffi::PyObject, ) { let ptr = ffi::PyCapsule_GetPointer(capsule, ffi::PyCapsule_GetName(capsule)); let ctx = ffi::PyCapsule_GetContext(capsule); let CapsuleContents { value, destructor, .. } = *Box::from_raw(ptr.cast::>()); destructor(value, ctx) } /// Guarantee `T` is not zero sized at compile time. // credit: `` #[doc(hidden)] pub trait AssertNotZeroSized: Sized { const _CONDITION: usize = (std::mem::size_of::() == 0) as usize; const _CHECK: &'static str = ["PyCapsule value type T must not be zero-sized!"][Self::_CONDITION]; #[allow(path_statements, clippy::no_effect)] fn assert_not_zero_sized(&self) { ::_CHECK; } } impl AssertNotZeroSized for T {} fn ensure_no_error(py: Python<'_>) -> PyResult<()> { if let Some(err) = PyErr::take(py) { Err(err) } else { Ok(()) } } fn name_ptr_ignore_error(slf: &Bound<'_, PyCapsule>) -> *const c_char { let ptr = unsafe { ffi::PyCapsule_GetName(slf.as_ptr()) }; if ptr.is_null() { unsafe { ffi::PyErr_Clear() }; } ptr } #[cfg(test)] mod tests { use libc::c_void; use crate::prelude::PyModule; use crate::types::capsule::PyCapsuleMethods; use crate::types::module::PyModuleMethods; use crate::{types::PyCapsule, Py, PyResult, Python}; use std::ffi::CString; use std::sync::mpsc::{channel, Sender}; #[test] fn test_pycapsule_struct() -> PyResult<()> { #[repr(C)] struct Foo { pub val: u32, } impl Foo { fn get_val(&self) -> u32 { self.val } } Python::with_gil(|py| -> PyResult<()> { let foo = Foo { val: 123 }; let name = CString::new("foo").unwrap(); let cap = PyCapsule::new_bound(py, foo, Some(name.clone()))?; assert!(cap.is_valid()); let foo_capi = unsafe { cap.reference::() }; assert_eq!(foo_capi.val, 123); assert_eq!(foo_capi.get_val(), 123); assert_eq!(cap.name().unwrap(), Some(name.as_ref())); Ok(()) }) } #[test] fn test_pycapsule_func() { fn foo(x: u32) -> u32 { x } let cap: Py = Python::with_gil(|py| { let name = CString::new("foo").unwrap(); let cap = PyCapsule::new_bound(py, foo as fn(u32) -> u32, Some(name)).unwrap(); cap.into() }); Python::with_gil(move |py| { let f = unsafe { cap.bind(py).reference:: u32>() }; assert_eq!(f(123), 123); }); } #[test] fn test_pycapsule_context() -> PyResult<()> { Python::with_gil(|py| { let name = CString::new("foo").unwrap(); let cap = PyCapsule::new_bound(py, 0, Some(name))?; let c = cap.context()?; assert!(c.is_null()); let ctx = Box::new(123_u32); cap.set_context(Box::into_raw(ctx).cast())?; let ctx_ptr: *mut c_void = cap.context()?; let ctx = unsafe { *Box::from_raw(ctx_ptr.cast::()) }; assert_eq!(ctx, 123); Ok(()) }) } #[test] fn test_pycapsule_import() -> PyResult<()> { #[repr(C)] struct Foo { pub val: u32, } Python::with_gil(|py| -> PyResult<()> { let foo = Foo { val: 123 }; let name = CString::new("builtins.capsule").unwrap(); let capsule = PyCapsule::new_bound(py, foo, Some(name.clone()))?; let module = PyModule::import_bound(py, "builtins")?; module.add("capsule", capsule)?; // check error when wrong named passed for capsule. let wrong_name = CString::new("builtins.non_existant").unwrap(); let result: PyResult<&Foo> = unsafe { PyCapsule::import(py, wrong_name.as_ref()) }; assert!(result.is_err()); // corret name is okay. let cap: &Foo = unsafe { PyCapsule::import(py, name.as_ref())? }; assert_eq!(cap.val, 123); Ok(()) }) } #[test] fn test_vec_storage() { let cap: Py = Python::with_gil(|py| { let name = CString::new("foo").unwrap(); let stuff: Vec = vec![1, 2, 3, 4]; let cap = PyCapsule::new_bound(py, stuff, Some(name)).unwrap(); cap.into() }); Python::with_gil(move |py| { let ctx: &Vec = unsafe { cap.bind(py).reference() }; assert_eq!(ctx, &[1, 2, 3, 4]); }) } #[test] fn test_vec_context() { let context: Vec = vec![1, 2, 3, 4]; let cap: Py = Python::with_gil(|py| { let name = CString::new("foo").unwrap(); let cap = PyCapsule::new_bound(py, 0, Some(name)).unwrap(); cap.set_context(Box::into_raw(Box::new(&context)).cast()) .unwrap(); cap.into() }); Python::with_gil(move |py| { let ctx_ptr: *mut c_void = cap.bind(py).context().unwrap(); let ctx = unsafe { *Box::from_raw(ctx_ptr.cast::<&Vec>()) }; assert_eq!(ctx, &vec![1_u8, 2, 3, 4]); }) } #[test] fn test_pycapsule_destructor() { let (tx, rx) = channel::(); fn destructor(_val: u32, ctx: *mut c_void) { assert!(!ctx.is_null()); let context = unsafe { *Box::from_raw(ctx.cast::>()) }; context.send(true).unwrap(); } Python::with_gil(move |py| { let name = CString::new("foo").unwrap(); let cap = PyCapsule::new_bound_with_destructor(py, 0, Some(name), destructor).unwrap(); cap.set_context(Box::into_raw(Box::new(tx)).cast()).unwrap(); }); // the destructor was called. assert_eq!(rx.recv(), Ok(true)); } #[test] fn test_pycapsule_no_name() { Python::with_gil(|py| { let cap = PyCapsule::new_bound(py, 0usize, None).unwrap(); assert_eq!(unsafe { cap.reference::() }, &0usize); assert_eq!(cap.name().unwrap(), None); assert_eq!(cap.context().unwrap(), std::ptr::null_mut()); }); } } pyo3/src/types/none.rs0000644000175000017500000000645114661133735015701 0ustar jamespagejamespageuse crate::ffi_ptr_ext::FfiPtrExt; use crate::{ ffi, types::any::PyAnyMethods, Borrowed, Bound, IntoPy, PyAny, PyObject, PyTypeInfo, Python, ToPyObject, }; /// Represents the Python `None` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyNone>`][Bound]. #[repr(transparent)] pub struct PyNone(PyAny); pyobject_native_type_named!(PyNone); pyobject_native_type_extract!(PyNone); impl PyNone { /// Returns the `None` object. /// Deprecated form of [`PyNone::get_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyNone::get` will be replaced by `PyNone::get_bound` in a future PyO3 version" )] #[inline] pub fn get(py: Python<'_>) -> &PyNone { Self::get_bound(py).into_gil_ref() } /// Returns the `None` object. #[inline] pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNone> { unsafe { ffi::Py_None().assume_borrowed(py).downcast_unchecked() } } } unsafe impl PyTypeInfo for PyNone { const NAME: &'static str = "NoneType"; const MODULE: Option<&'static str> = None; fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject { unsafe { ffi::Py_TYPE(ffi::Py_None()) } } #[inline] fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool { // NoneType is not usable as a base type Self::is_exact_type_of_bound(object) } #[inline] fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool { object.is(&**Self::get_bound(object.py())) } } /// `()` is converted to Python `None`. impl ToPyObject for () { fn to_object(&self, py: Python<'_>) -> PyObject { PyNone::get_bound(py).into_py(py) } } impl IntoPy for () { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { PyNone::get_bound(py).into_py(py) } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::types::{PyDict, PyNone}; use crate::{IntoPy, PyObject, PyTypeInfo, Python, ToPyObject}; #[test] fn test_none_is_itself() { Python::with_gil(|py| { assert!(PyNone::get_bound(py).is_instance_of::()); assert!(PyNone::get_bound(py).is_exact_instance_of::()); }) } #[test] fn test_none_type_object_consistent() { Python::with_gil(|py| { assert!(PyNone::get_bound(py) .get_type() .is(&PyNone::type_object_bound(py))); }) } #[test] fn test_none_is_none() { Python::with_gil(|py| { assert!(PyNone::get_bound(py) .downcast::() .unwrap() .is_none()); }) } #[test] fn test_unit_to_object_is_none() { Python::with_gil(|py| { assert!(().to_object(py).downcast_bound::(py).is_ok()); }) } #[test] fn test_unit_into_py_is_none() { Python::with_gil(|py| { let obj: PyObject = ().into_py(py); assert!(obj.downcast_bound::(py).is_ok()); }) } #[test] fn test_dict_is_not_none() { Python::with_gil(|py| { assert!(PyDict::new_bound(py).downcast::().is_err()); }) } } pyo3/src/types/frame.rs0000644000175000017500000000062614661133735016032 0ustar jamespagejamespageuse crate::ffi; use crate::PyAny; /// Represents a Python frame. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyFrame>`][crate::Bound]. #[repr(transparent)] pub struct PyFrame(PyAny); pyobject_native_type_core!( PyFrame, pyobject_native_static_type_object!(ffi::PyFrame_Type), #checkfunction=ffi::PyFrame_Check ); pyo3/src/types/float.rs0000644000175000017500000001276614661133735016055 0ustar jamespagejamespageuse super::any::PyAnyMethods; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound, FromPyObject, IntoPy, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; use std::os::raw::c_double; /// Represents a Python `float` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyFloat>`][Bound]. /// /// For APIs available on `float` objects, see the [`PyFloatMethods`] trait which is implemented for /// [`Bound<'py, PyFloat>`][Bound]. /// /// You can usually avoid directly working with this type /// by using [`ToPyObject`] and [`extract`][PyAnyMethods::extract] /// with [`f32`]/[`f64`]. #[repr(transparent)] pub struct PyFloat(PyAny); pyobject_native_type!( PyFloat, ffi::PyFloatObject, pyobject_native_static_type_object!(ffi::PyFloat_Type), #checkfunction=ffi::PyFloat_Check ); impl PyFloat { /// Creates a new Python `float` object. pub fn new_bound(py: Python<'_>, val: c_double) -> Bound<'_, PyFloat> { unsafe { ffi::PyFloat_FromDouble(val) .assume_owned(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyFloat { /// Deprecated form of [`PyFloat::new_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyFloat::new` will be replaced by `PyFloat::new_bound` in a future PyO3 version" )] pub fn new(py: Python<'_>, val: f64) -> &'_ Self { Self::new_bound(py, val).into_gil_ref() } /// Gets the value of this float. pub fn value(&self) -> c_double { self.as_borrowed().value() } } /// Implementation of functionality for [`PyFloat`]. /// /// These methods are defined for the `Bound<'py, PyFloat>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyFloat")] pub trait PyFloatMethods<'py>: crate::sealed::Sealed { /// Gets the value of this float. fn value(&self) -> c_double; } impl<'py> PyFloatMethods<'py> for Bound<'py, PyFloat> { fn value(&self) -> c_double { #[cfg(not(Py_LIMITED_API))] unsafe { // Safety: self is PyFloat object ffi::PyFloat_AS_DOUBLE(self.as_ptr()) } #[cfg(Py_LIMITED_API)] unsafe { ffi::PyFloat_AsDouble(self.as_ptr()) } } } impl ToPyObject for f64 { fn to_object(&self, py: Python<'_>) -> PyObject { PyFloat::new_bound(py, *self).into() } } impl IntoPy for f64 { fn into_py(self, py: Python<'_>) -> PyObject { PyFloat::new_bound(py, self).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("float") } } impl<'py> FromPyObject<'py> for f64 { // PyFloat_AsDouble returns -1.0 upon failure #![allow(clippy::float_cmp)] fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { // On non-limited API, .value() uses PyFloat_AS_DOUBLE which // allows us to have an optimized fast path for the case when // we have exactly a `float` object (it's not worth going through // `isinstance` machinery for subclasses). #[cfg(not(Py_LIMITED_API))] if let Ok(float) = obj.downcast_exact::() { return Ok(float.value()); } let v = unsafe { ffi::PyFloat_AsDouble(obj.as_ptr()) }; if v == -1.0 { if let Some(err) = PyErr::take(obj.py()) { return Err(err); } } Ok(v) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } impl ToPyObject for f32 { fn to_object(&self, py: Python<'_>) -> PyObject { PyFloat::new_bound(py, f64::from(*self)).into() } } impl IntoPy for f32 { fn into_py(self, py: Python<'_>) -> PyObject { PyFloat::new_bound(py, f64::from(self)).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("float") } } impl<'py> FromPyObject<'py> for f32 { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { Ok(obj.extract::()? as f32) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } #[cfg(test)] mod tests { use crate::{ types::{PyFloat, PyFloatMethods}, Python, ToPyObject, }; macro_rules! num_to_py_object_and_back ( ($func_name:ident, $t1:ty, $t2:ty) => ( #[test] fn $func_name() { use assert_approx_eq::assert_approx_eq; Python::with_gil(|py| { let val = 123 as $t1; let obj = val.to_object(py); assert_approx_eq!(obj.extract::<$t2>(py).unwrap(), val as $t2); }); } ) ); num_to_py_object_and_back!(to_from_f64, f64, f64); num_to_py_object_and_back!(to_from_f32, f32, f32); num_to_py_object_and_back!(int_to_float, i32, f64); #[test] fn test_float_value() { use assert_approx_eq::assert_approx_eq; Python::with_gil(|py| { let v = 1.23f64; let obj = PyFloat::new_bound(py, 1.23); assert_approx_eq!(v, obj.value()); }); } } pyo3/src/types/typeobject.rs0000644000175000017500000003463514661133735017117 0ustar jamespagejamespageuse crate::err::{self, PyResult}; use crate::instance::Borrowed; #[cfg(not(Py_3_13))] use crate::pybacked::PyBackedStr; use crate::types::any::PyAnyMethods; use crate::types::PyTuple; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, Bound, PyAny, PyTypeInfo, Python}; use super::PyString; /// Represents a reference to a Python `type` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyType>`][Bound]. /// /// For APIs available on `type` objects, see the [`PyTypeMethods`] trait which is implemented for /// [`Bound<'py, PyType>`][Bound]. #[repr(transparent)] pub struct PyType(PyAny); pyobject_native_type_core!(PyType, pyobject_native_static_type_object!(ffi::PyType_Type), #checkfunction=ffi::PyType_Check); impl PyType { /// Creates a new type object. #[inline] pub fn new_bound(py: Python<'_>) -> Bound<'_, PyType> { T::type_object_bound(py) } /// Converts the given FFI pointer into `Bound`, to use in safe code. /// /// The function creates a new reference from the given pointer, and returns /// it as a `Bound`. /// /// # Safety /// - The pointer must be a valid non-null reference to a `PyTypeObject` #[inline] pub unsafe fn from_borrowed_type_ptr( py: Python<'_>, p: *mut ffi::PyTypeObject, ) -> Bound<'_, PyType> { Borrowed::from_ptr_unchecked(py, p.cast()) .downcast_unchecked() .to_owned() } } #[cfg(feature = "gil-refs")] impl PyType { /// Deprecated form of [`PyType::new_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyType::new` will be replaced by `PyType::new_bound` in a future PyO3 version" )] pub fn new(py: Python<'_>) -> &PyType { T::type_object_bound(py).into_gil_ref() } /// Retrieves the underlying FFI pointer associated with this Python object. #[inline] pub fn as_type_ptr(&self) -> *mut ffi::PyTypeObject { self.as_borrowed().as_type_ptr() } /// Deprecated form of [`PyType::from_borrowed_type_ptr`]. /// /// # Safety /// /// - The pointer must a valid non-null reference to a `PyTypeObject`. #[inline] #[deprecated( since = "0.21.0", note = "Use `PyType::from_borrowed_type_ptr` instead" )] pub unsafe fn from_type_ptr(py: Python<'_>, p: *mut ffi::PyTypeObject) -> &PyType { Self::from_borrowed_type_ptr(py, p).into_gil_ref() } /// Gets the name of the `PyType`. Equivalent to `self.__name__` in Python. pub fn name(&self) -> PyResult<&PyString> { self.as_borrowed().name().map(Bound::into_gil_ref) } /// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`. /// Equivalent to `self.__qualname__` in Python. pub fn qualname(&self) -> PyResult<&PyString> { self.as_borrowed().qualname().map(Bound::into_gil_ref) } // `module` and `fully_qualified_name` intentionally omitted /// Checks whether `self` is a subclass of `other`. /// /// Equivalent to the Python expression `issubclass(self, other)`. pub fn is_subclass(&self, other: &PyAny) -> PyResult { self.as_borrowed().is_subclass(&other.as_borrowed()) } /// Checks whether `self` is a subclass of type `T`. /// /// Equivalent to the Python expression `issubclass(self, T)`, if the type /// `T` is known at compile time. pub fn is_subclass_of(&self) -> PyResult where T: PyTypeInfo, { self.as_borrowed().is_subclass_of::() } } /// Implementation of functionality for [`PyType`]. /// /// These methods are defined for the `Bound<'py, PyType>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyType")] pub trait PyTypeMethods<'py>: crate::sealed::Sealed { /// Retrieves the underlying FFI pointer associated with this Python object. fn as_type_ptr(&self) -> *mut ffi::PyTypeObject; /// Gets the name of the `PyType`. Equivalent to `self.__name__` in Python. fn name(&self) -> PyResult>; /// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`. /// Equivalent to `self.__qualname__` in Python. fn qualname(&self) -> PyResult>; /// Gets the name of the module defining the `PyType`. fn module(&self) -> PyResult>; /// Gets the [fully qualified name](https://peps.python.org/pep-0737/#add-pytype-getfullyqualifiedname-function) of the `PyType`. fn fully_qualified_name(&self) -> PyResult>; /// Checks whether `self` is a subclass of `other`. /// /// Equivalent to the Python expression `issubclass(self, other)`. fn is_subclass(&self, other: &Bound<'_, PyAny>) -> PyResult; /// Checks whether `self` is a subclass of type `T`. /// /// Equivalent to the Python expression `issubclass(self, T)`, if the type /// `T` is known at compile time. fn is_subclass_of(&self) -> PyResult where T: PyTypeInfo; /// Return the method resolution order for this type. /// /// Equivalent to the Python expression `self.__mro__`. fn mro(&self) -> Bound<'py, PyTuple>; /// Return Python bases /// /// Equivalent to the Python expression `self.__bases__`. fn bases(&self) -> Bound<'py, PyTuple>; } impl<'py> PyTypeMethods<'py> for Bound<'py, PyType> { /// Retrieves the underlying FFI pointer associated with this Python object. #[inline] fn as_type_ptr(&self) -> *mut ffi::PyTypeObject { self.as_ptr() as *mut ffi::PyTypeObject } /// Gets the name of the `PyType`. fn name(&self) -> PyResult> { #[cfg(not(Py_3_11))] let name = self .getattr(intern!(self.py(), "__name__"))? .downcast_into()?; #[cfg(Py_3_11)] let name = unsafe { use crate::ffi_ptr_ext::FfiPtrExt; ffi::PyType_GetName(self.as_type_ptr()) .assume_owned_or_err(self.py())? // SAFETY: setting `__name__` from Python is required to be a `str` .downcast_into_unchecked() }; Ok(name) } /// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`. fn qualname(&self) -> PyResult> { #[cfg(not(Py_3_11))] let name = self .getattr(intern!(self.py(), "__qualname__"))? .downcast_into()?; #[cfg(Py_3_11)] let name = unsafe { use crate::ffi_ptr_ext::FfiPtrExt; ffi::PyType_GetQualName(self.as_type_ptr()) .assume_owned_or_err(self.py())? // SAFETY: setting `__qualname__` from Python is required to be a `str` .downcast_into_unchecked() }; Ok(name) } /// Gets the name of the module defining the `PyType`. fn module(&self) -> PyResult> { #[cfg(not(Py_3_13))] let name = self.getattr(intern!(self.py(), "__module__"))?; #[cfg(Py_3_13)] let name = unsafe { use crate::ffi_ptr_ext::FfiPtrExt; ffi::PyType_GetModuleName(self.as_type_ptr()).assume_owned_or_err(self.py())? }; // `__module__` is never guaranteed to be a `str` name.downcast_into().map_err(Into::into) } /// Gets the [fully qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`. fn fully_qualified_name(&self) -> PyResult> { #[cfg(not(Py_3_13))] let name = { let module = self.getattr(intern!(self.py(), "__module__"))?; let qualname = self.getattr(intern!(self.py(), "__qualname__"))?; let module_str = module.extract::()?; if module_str == "builtins" || module_str == "__main__" { qualname.downcast_into()? } else { PyString::new_bound(self.py(), &format!("{}.{}", module, qualname)) } }; #[cfg(Py_3_13)] let name = unsafe { use crate::ffi_ptr_ext::FfiPtrExt; ffi::PyType_GetFullyQualifiedName(self.as_type_ptr()) .assume_owned_or_err(self.py())? .downcast_into_unchecked() }; Ok(name) } /// Checks whether `self` is a subclass of `other`. /// /// Equivalent to the Python expression `issubclass(self, other)`. fn is_subclass(&self, other: &Bound<'_, PyAny>) -> PyResult { let result = unsafe { ffi::PyObject_IsSubclass(self.as_ptr(), other.as_ptr()) }; err::error_on_minusone(self.py(), result)?; Ok(result == 1) } /// Checks whether `self` is a subclass of type `T`. /// /// Equivalent to the Python expression `issubclass(self, T)`, if the type /// `T` is known at compile time. fn is_subclass_of(&self) -> PyResult where T: PyTypeInfo, { self.is_subclass(&T::type_object_bound(self.py())) } fn mro(&self) -> Bound<'py, PyTuple> { #[cfg(any(Py_LIMITED_API, PyPy))] let mro = self .getattr(intern!(self.py(), "__mro__")) .expect("Cannot get `__mro__` from object.") .extract() .expect("Unexpected type in `__mro__` attribute."); #[cfg(not(any(Py_LIMITED_API, PyPy)))] let mro = unsafe { use crate::ffi_ptr_ext::FfiPtrExt; (*self.as_type_ptr()) .tp_mro .assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked() }; mro } fn bases(&self) -> Bound<'py, PyTuple> { #[cfg(any(Py_LIMITED_API, PyPy))] let bases = self .getattr(intern!(self.py(), "__bases__")) .expect("Cannot get `__bases__` from object.") .extract() .expect("Unexpected type in `__bases__` attribute."); #[cfg(not(any(Py_LIMITED_API, PyPy)))] let bases = unsafe { use crate::ffi_ptr_ext::FfiPtrExt; (*self.as_type_ptr()) .tp_bases .assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked() }; bases } } #[cfg(test)] mod tests { use crate::types::{ PyAnyMethods, PyBool, PyInt, PyLong, PyModule, PyTuple, PyType, PyTypeMethods, }; use crate::PyAny; use crate::Python; #[test] fn test_type_is_subclass() { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); let long_type = py.get_type_bound::(); assert!(bool_type.is_subclass(&long_type).unwrap()); }); } #[test] fn test_type_is_subclass_of() { Python::with_gil(|py| { assert!(py .get_type_bound::() .is_subclass_of::() .unwrap()); }); } #[test] fn test_mro() { Python::with_gil(|py| { assert!(py .get_type_bound::() .mro() .eq(PyTuple::new_bound( py, [ py.get_type_bound::(), py.get_type_bound::(), py.get_type_bound::() ] )) .unwrap()); }); } #[test] fn test_bases_bool() { Python::with_gil(|py| { assert!(py .get_type_bound::() .bases() .eq(PyTuple::new_bound(py, [py.get_type_bound::()])) .unwrap()); }); } #[test] fn test_bases_object() { Python::with_gil(|py| { assert!(py .get_type_bound::() .bases() .eq(PyTuple::empty_bound(py)) .unwrap()); }); } #[test] fn test_type_names_standard() { Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class MyClass: pass "#, file!(), "test_module", ) .expect("module create failed"); let my_class = module.getattr("MyClass").unwrap(); let my_class_type = my_class.downcast_into::().unwrap(); assert_eq!(my_class_type.name().unwrap(), "MyClass"); assert_eq!(my_class_type.qualname().unwrap(), "MyClass"); assert_eq!(my_class_type.module().unwrap(), "test_module"); assert_eq!( my_class_type.fully_qualified_name().unwrap(), "test_module.MyClass" ); }); } #[test] fn test_type_names_builtin() { Python::with_gil(|py| { let bool_type = py.get_type_bound::(); assert_eq!(bool_type.name().unwrap(), "bool"); assert_eq!(bool_type.qualname().unwrap(), "bool"); assert_eq!(bool_type.module().unwrap(), "builtins"); assert_eq!(bool_type.fully_qualified_name().unwrap(), "bool"); }); } #[test] fn test_type_names_nested() { Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class OuterClass: class InnerClass: pass "#, file!(), "test_module", ) .expect("module create failed"); let outer_class = module.getattr("OuterClass").unwrap(); let inner_class = outer_class.getattr("InnerClass").unwrap(); let inner_class_type = inner_class.downcast_into::().unwrap(); assert_eq!(inner_class_type.name().unwrap(), "InnerClass"); assert_eq!( inner_class_type.qualname().unwrap(), "OuterClass.InnerClass" ); assert_eq!(inner_class_type.module().unwrap(), "test_module"); assert_eq!( inner_class_type.fully_qualified_name().unwrap(), "test_module.OuterClass.InnerClass" ); }); } } pyo3/src/types/traceback.rs0000644000175000017500000001404414661133735016656 0ustar jamespagejamespageuse crate::err::{error_on_minusone, PyResult}; use crate::types::{any::PyAnyMethods, string::PyStringMethods, PyString}; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, Bound, PyAny}; /// Represents a Python traceback. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTraceback>`][Bound]. /// /// For APIs available on traceback objects, see the [`PyTracebackMethods`] trait which is implemented for /// [`Bound<'py, PyTraceback>`][Bound]. #[repr(transparent)] pub struct PyTraceback(PyAny); pyobject_native_type_core!( PyTraceback, pyobject_native_static_type_object!(ffi::PyTraceBack_Type), #checkfunction=ffi::PyTraceBack_Check ); #[cfg(feature = "gil-refs")] impl PyTraceback { /// Formats the traceback as a string. /// /// This does not include the exception type and value. The exception type and value can be /// formatted using the `Display` implementation for `PyErr`. /// /// # Example /// /// The following code formats a Python traceback and exception pair from Rust: /// /// ```rust /// # use pyo3::{Python, PyResult, prelude::PyTracebackMethods}; /// # let result: PyResult<()> = /// Python::with_gil(|py| { /// let err = py /// .run_bound("raise Exception('banana')", None, None) /// .expect_err("raise will create a Python error"); /// /// let traceback = err.traceback_bound(py).expect("raised exception will have a traceback"); /// assert_eq!( /// format!("{}{}", traceback.format()?, err), /// "\ /// Traceback (most recent call last): /// File \"\", line 1, in /// Exception: banana\ /// " /// ); /// Ok(()) /// }) /// # ; /// # result.expect("example failed"); /// ``` pub fn format(&self) -> PyResult { self.as_borrowed().format() } } /// Implementation of functionality for [`PyTraceback`]. /// /// These methods are defined for the `Bound<'py, PyTraceback>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyTraceback")] pub trait PyTracebackMethods<'py>: crate::sealed::Sealed { /// Formats the traceback as a string. /// /// This does not include the exception type and value. The exception type and value can be /// formatted using the `Display` implementation for `PyErr`. /// /// # Example /// /// The following code formats a Python traceback and exception pair from Rust: /// /// ```rust /// # use pyo3::{Python, PyResult, prelude::PyTracebackMethods}; /// # let result: PyResult<()> = /// Python::with_gil(|py| { /// let err = py /// .run_bound("raise Exception('banana')", None, None) /// .expect_err("raise will create a Python error"); /// /// let traceback = err.traceback_bound(py).expect("raised exception will have a traceback"); /// assert_eq!( /// format!("{}{}", traceback.format()?, err), /// "\ /// Traceback (most recent call last): /// File \"\", line 1, in /// Exception: banana\ /// " /// ); /// Ok(()) /// }) /// # ; /// # result.expect("example failed"); /// ``` fn format(&self) -> PyResult; } impl<'py> PyTracebackMethods<'py> for Bound<'py, PyTraceback> { fn format(&self) -> PyResult { let py = self.py(); let string_io = py .import_bound(intern!(py, "io"))? .getattr(intern!(py, "StringIO"))? .call0()?; let result = unsafe { ffi::PyTraceBack_Print(self.as_ptr(), string_io.as_ptr()) }; error_on_minusone(py, result)?; let formatted = string_io .getattr(intern!(py, "getvalue"))? .call0()? .downcast::()? .to_cow()? .into_owned(); Ok(formatted) } } #[cfg(test)] mod tests { use crate::{ types::{any::PyAnyMethods, dict::PyDictMethods, traceback::PyTracebackMethods, PyDict}, IntoPy, PyErr, Python, }; #[test] fn format_traceback() { Python::with_gil(|py| { let err = py .run_bound("raise Exception('banana')", None, None) .expect_err("raising should have given us an error"); assert_eq!( err.traceback_bound(py).unwrap().format().unwrap(), "Traceback (most recent call last):\n File \"\", line 1, in \n" ); }) } #[test] fn test_err_from_value() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); // Produce an error from python so that it has a traceback py.run_bound( r" try: raise ValueError('raised exception') except Exception as e: err = e ", None, Some(&locals), ) .unwrap(); let err = PyErr::from_value_bound(locals.get_item("err").unwrap().unwrap()); let traceback = err.value_bound(py).getattr("__traceback__").unwrap(); assert!(err.traceback_bound(py).unwrap().is(&traceback)); }) } #[test] fn test_err_into_py() { Python::with_gil(|py| { let locals = PyDict::new_bound(py); // Produce an error from python so that it has a traceback py.run_bound( r" def f(): raise ValueError('raised exception') ", None, Some(&locals), ) .unwrap(); let f = locals.get_item("f").unwrap().unwrap(); let err = f.call0().unwrap_err(); let traceback = err.traceback_bound(py).unwrap(); let err_object = err.clone_ref(py).into_py(py).into_bound(py); assert!(err_object.getattr("__traceback__").unwrap().is(&traceback)); }) } } pyo3/src/types/set.rs0000644000175000017500000003651214661133735015536 0ustar jamespagejamespageuse crate::types::PyIterator; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ err::{self, PyErr, PyResult}, ffi_ptr_ext::FfiPtrExt, instance::Bound, py_result_ext::PyResultExt, types::any::PyAnyMethods, }; use crate::{ffi, PyAny, PyObject, Python, ToPyObject}; use std::ptr; /// Represents a Python `set`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PySet>`][Bound]. /// /// For APIs available on `set` objects, see the [`PySetMethods`] trait which is implemented for /// [`Bound<'py, PySet>`][Bound]. #[repr(transparent)] pub struct PySet(PyAny); #[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type!( PySet, ffi::PySetObject, pyobject_native_static_type_object!(ffi::PySet_Type), #checkfunction=ffi::PySet_Check ); #[cfg(any(PyPy, GraalPy))] pyobject_native_type_core!( PySet, pyobject_native_static_type_object!(ffi::PySet_Type), #checkfunction=ffi::PySet_Check ); impl PySet { /// Creates a new set with elements from the given slice. /// /// Returns an error if some element is not hashable. #[inline] pub fn new_bound<'a, 'p, T: ToPyObject + 'a>( py: Python<'p>, elements: impl IntoIterator, ) -> PyResult> { new_from_iter(py, elements) } /// Creates a new empty set. pub fn empty_bound(py: Python<'_>) -> PyResult> { unsafe { ffi::PySet_New(ptr::null_mut()) .assume_owned_or_err(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PySet { /// Deprecated form of [`PySet::new_bound`]. #[deprecated( since = "0.21.0", note = "`PySet::new` will be replaced by `PySet::new_bound` in a future PyO3 version" )] #[inline] pub fn new<'a, 'p, T: ToPyObject + 'a>( py: Python<'p>, elements: impl IntoIterator, ) -> PyResult<&'p PySet> { Self::new_bound(py, elements).map(Bound::into_gil_ref) } /// Deprecated form of [`PySet::empty_bound`]. #[deprecated( since = "0.21.2", note = "`PySet::empty` will be replaced by `PySet::empty_bound` in a future PyO3 version" )] pub fn empty(py: Python<'_>) -> PyResult<&PySet> { Self::empty_bound(py).map(Bound::into_gil_ref) } /// Removes all elements from the set. #[inline] pub fn clear(&self) { self.as_borrowed().clear() } /// Returns the number of items in the set. /// /// This is equivalent to the Python expression `len(self)`. #[inline] pub fn len(&self) -> usize { self.as_borrowed().len() } /// Checks if set is empty. pub fn is_empty(&self) -> bool { self.as_borrowed().is_empty() } /// Determines if the set contains the specified key. /// /// This is equivalent to the Python expression `key in self`. pub fn contains(&self, key: K) -> PyResult where K: ToPyObject, { self.as_borrowed().contains(key) } /// Removes the element from the set if it is present. /// /// Returns `true` if the element was present in the set. pub fn discard(&self, key: K) -> PyResult where K: ToPyObject, { self.as_borrowed().discard(key) } /// Adds an element to the set. pub fn add(&self, key: K) -> PyResult<()> where K: ToPyObject, { self.as_borrowed().add(key) } /// Removes and returns an arbitrary element from the set. pub fn pop(&self) -> Option { self.as_borrowed().pop().map(Bound::unbind) } /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. pub fn iter(&self) -> PySetIterator<'_> { PySetIterator(BoundSetIterator::new(self.as_borrowed().to_owned())) } } /// Implementation of functionality for [`PySet`]. /// /// These methods are defined for the `Bound<'py, PySet>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PySet")] pub trait PySetMethods<'py>: crate::sealed::Sealed { /// Removes all elements from the set. fn clear(&self); /// Returns the number of items in the set. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> usize; /// Checks if set is empty. fn is_empty(&self) -> bool { self.len() == 0 } /// Determines if the set contains the specified key. /// /// This is equivalent to the Python expression `key in self`. fn contains(&self, key: K) -> PyResult where K: ToPyObject; /// Removes the element from the set if it is present. /// /// Returns `true` if the element was present in the set. fn discard(&self, key: K) -> PyResult where K: ToPyObject; /// Adds an element to the set. fn add(&self, key: K) -> PyResult<()> where K: ToPyObject; /// Removes and returns an arbitrary element from the set. fn pop(&self) -> Option>; /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. fn iter(&self) -> BoundSetIterator<'py>; } impl<'py> PySetMethods<'py> for Bound<'py, PySet> { #[inline] fn clear(&self) { unsafe { ffi::PySet_Clear(self.as_ptr()); } } #[inline] fn len(&self) -> usize { unsafe { ffi::PySet_Size(self.as_ptr()) as usize } } fn contains(&self, key: K) -> PyResult where K: ToPyObject, { fn inner(set: &Bound<'_, PySet>, key: Bound<'_, PyAny>) -> PyResult { match unsafe { ffi::PySet_Contains(set.as_ptr(), key.as_ptr()) } { 1 => Ok(true), 0 => Ok(false), _ => Err(PyErr::fetch(set.py())), } } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn discard(&self, key: K) -> PyResult where K: ToPyObject, { fn inner(set: &Bound<'_, PySet>, key: Bound<'_, PyAny>) -> PyResult { match unsafe { ffi::PySet_Discard(set.as_ptr(), key.as_ptr()) } { 1 => Ok(true), 0 => Ok(false), _ => Err(PyErr::fetch(set.py())), } } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn add(&self, key: K) -> PyResult<()> where K: ToPyObject, { fn inner(set: &Bound<'_, PySet>, key: Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(set.py(), unsafe { ffi::PySet_Add(set.as_ptr(), key.as_ptr()) }) } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn pop(&self) -> Option> { let element = unsafe { ffi::PySet_Pop(self.as_ptr()).assume_owned_or_err(self.py()) }; match element { Ok(e) => Some(e), Err(_) => None, } } fn iter(&self) -> BoundSetIterator<'py> { BoundSetIterator::new(self.clone()) } } /// PyO3 implementation of an iterator for a Python `set` object. #[cfg(feature = "gil-refs")] pub struct PySetIterator<'py>(BoundSetIterator<'py>); #[cfg(feature = "gil-refs")] impl<'py> Iterator for PySetIterator<'py> { type Item = &'py super::PyAny; /// Advances the iterator and returns the next value. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. #[inline] fn next(&mut self) -> Option { self.0.next().map(Bound::into_gil_ref) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[cfg(feature = "gil-refs")] impl ExactSizeIterator for PySetIterator<'_> { fn len(&self) -> usize { self.0.len() } } #[cfg(feature = "gil-refs")] impl<'py> IntoIterator for &'py PySet { type Item = &'py PyAny; type IntoIter = PySetIterator<'py>; /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. fn into_iter(self) -> Self::IntoIter { PySetIterator(BoundSetIterator::new(self.as_borrowed().to_owned())) } } impl<'py> IntoIterator for Bound<'py, PySet> { type Item = Bound<'py, PyAny>; type IntoIter = BoundSetIterator<'py>; /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. fn into_iter(self) -> Self::IntoIter { BoundSetIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PySet> { type Item = Bound<'py, PyAny>; type IntoIter = BoundSetIterator<'py>; /// Returns an iterator of values in this set. /// /// # Panics /// /// If PyO3 detects that the set is mutated during iteration, it will panic. fn into_iter(self) -> Self::IntoIter { self.iter() } } /// PyO3 implementation of an iterator for a Python `set` object. pub struct BoundSetIterator<'p> { it: Bound<'p, PyIterator>, // Remaining elements in the set. This is fine to store because // Python will error if the set changes size during iteration. remaining: usize, } impl<'py> BoundSetIterator<'py> { pub(super) fn new(set: Bound<'py, PySet>) -> Self { Self { it: PyIterator::from_bound_object(&set).unwrap(), remaining: set.len(), } } } impl<'py> Iterator for BoundSetIterator<'py> { type Item = Bound<'py, super::PyAny>; /// Advances the iterator and returns the next value. fn next(&mut self) -> Option { self.remaining = self.remaining.saturating_sub(1); self.it.next().map(Result::unwrap) } fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl<'py> ExactSizeIterator for BoundSetIterator<'py> { fn len(&self) -> usize { self.remaining } } #[inline] pub(crate) fn new_from_iter( py: Python<'_>, elements: impl IntoIterator, ) -> PyResult> { fn inner<'py>( py: Python<'py>, elements: &mut dyn Iterator, ) -> PyResult> { let set = unsafe { // We create the `Py` pointer because its Drop cleans up the set if user code panics. ffi::PySet_New(std::ptr::null_mut()) .assume_owned_or_err(py)? .downcast_into_unchecked() }; let ptr = set.as_ptr(); for obj in elements { err::error_on_minusone(py, unsafe { ffi::PySet_Add(ptr, obj.as_ptr()) })?; } Ok(set) } let mut iter = elements.into_iter().map(|e| e.to_object(py)); inner(py, &mut iter) } #[cfg(test)] mod tests { use super::PySet; use crate::{ types::{PyAnyMethods, PySetMethods}, Python, ToPyObject, }; use std::collections::HashSet; #[test] fn test_set_new() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); assert_eq!(1, set.len()); let v = vec![1]; assert!(PySet::new_bound(py, &[v]).is_err()); }); } #[test] fn test_set_empty() { Python::with_gil(|py| { let set = PySet::empty_bound(py).unwrap(); assert_eq!(0, set.len()); assert!(set.is_empty()); }); } #[test] fn test_set_len() { Python::with_gil(|py| { let mut v = HashSet::new(); let ob = v.to_object(py); let set = ob.downcast_bound::(py).unwrap(); assert_eq!(0, set.len()); v.insert(7); let ob = v.to_object(py); let set2 = ob.downcast_bound::(py).unwrap(); assert_eq!(1, set2.len()); }); } #[test] fn test_set_clear() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); assert_eq!(1, set.len()); set.clear(); assert_eq!(0, set.len()); }); } #[test] fn test_set_contains() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); assert!(set.contains(1).unwrap()); }); } #[test] fn test_set_discard() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); assert!(!set.discard(2).unwrap()); assert_eq!(1, set.len()); assert!(set.discard(1).unwrap()); assert_eq!(0, set.len()); assert!(!set.discard(1).unwrap()); assert!(set.discard(vec![1, 2]).is_err()); }); } #[test] fn test_set_add() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1, 2]).unwrap(); set.add(1).unwrap(); // Add a dupliated element assert!(set.contains(1).unwrap()); }); } #[test] fn test_set_pop() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); let val = set.pop(); assert!(val.is_some()); let val2 = set.pop(); assert!(val2.is_none()); assert!(py .eval_bound("print('Exception state should not be set.')", None, None) .is_ok()); }); } #[test] fn test_set_iter() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); for el in set { assert_eq!(1i32, el.extract::<'_, i32>().unwrap()); } }); } #[test] fn test_set_iter_bound() { use crate::types::any::PyAnyMethods; Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); for el in &set { assert_eq!(1i32, el.extract::().unwrap()); } }); } #[test] #[should_panic] fn test_set_iter_mutation() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); for _ in &set { let _ = set.add(42); } }); } #[test] #[should_panic] fn test_set_iter_mutation_same_len() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1, 2, 3, 4, 5]).unwrap(); for item in &set { let item: i32 = item.extract().unwrap(); let _ = set.del_item(item); let _ = set.add(item + 10); } }); } #[test] fn test_set_iter_size_hint() { Python::with_gil(|py| { let set = PySet::new_bound(py, &[1]).unwrap(); let mut iter = set.iter(); // Exact size assert_eq!(iter.len(), 1); assert_eq!(iter.size_hint(), (1, Some(1))); iter.next(); assert_eq!(iter.len(), 0); assert_eq!(iter.size_hint(), (0, Some(0))); }); } } pyo3/src/types/ellipsis.rs0000644000175000017500000000457414661133735016572 0ustar jamespagejamespageuse crate::{ ffi, ffi_ptr_ext::FfiPtrExt, types::any::PyAnyMethods, Borrowed, Bound, PyAny, PyTypeInfo, Python, }; /// Represents the Python `Ellipsis` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyEllipsis>`][Bound]. #[repr(transparent)] pub struct PyEllipsis(PyAny); pyobject_native_type_named!(PyEllipsis); pyobject_native_type_extract!(PyEllipsis); impl PyEllipsis { /// Returns the `Ellipsis` object. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyEllipsis::get` will be replaced by `PyEllipsis::get_bound` in a future PyO3 version" )] #[inline] pub fn get(py: Python<'_>) -> &PyEllipsis { Self::get_bound(py).into_gil_ref() } /// Returns the `Ellipsis` object. #[inline] pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyEllipsis> { unsafe { ffi::Py_Ellipsis().assume_borrowed(py).downcast_unchecked() } } } unsafe impl PyTypeInfo for PyEllipsis { const NAME: &'static str = "ellipsis"; const MODULE: Option<&'static str> = None; fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject { unsafe { ffi::Py_TYPE(ffi::Py_Ellipsis()) } } #[inline] fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool { // ellipsis is not usable as a base type Self::is_exact_type_of_bound(object) } #[inline] fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool { object.is(&**Self::get_bound(object.py())) } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::types::{PyDict, PyEllipsis}; use crate::{PyTypeInfo, Python}; #[test] fn test_ellipsis_is_itself() { Python::with_gil(|py| { assert!(PyEllipsis::get_bound(py).is_instance_of::()); assert!(PyEllipsis::get_bound(py).is_exact_instance_of::()); }) } #[test] fn test_ellipsis_type_object_consistent() { Python::with_gil(|py| { assert!(PyEllipsis::get_bound(py) .get_type() .is(&PyEllipsis::type_object_bound(py))); }) } #[test] fn test_dict_is_not_ellipsis() { Python::with_gil(|py| { assert!(PyDict::new_bound(py).downcast::().is_err()); }) } } pyo3/src/types/pysuper.rs0000644000175000017500000000451314661133735016446 0ustar jamespagejamespageuse crate::instance::Bound; use crate::types::any::PyAnyMethods; use crate::types::PyType; use crate::{ffi, PyTypeInfo}; use crate::{PyAny, PyResult}; /// Represents a Python `super` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PySuper>`][Bound]. #[repr(transparent)] pub struct PySuper(PyAny); pyobject_native_type_core!( PySuper, pyobject_native_static_type_object!(ffi::PySuper_Type) ); impl PySuper { /// Deprecated form of `PySuper::new_bound`. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PySuper::new` will be replaced by `PySuper::new_bound` in a future PyO3 version" )] pub fn new<'py>(ty: &'py PyType, obj: &'py PyAny) -> PyResult<&'py PySuper> { use crate::PyNativeType; Self::new_bound(&ty.as_borrowed(), &obj.as_borrowed()).map(Bound::into_gil_ref) } /// Constructs a new super object. More read about super object: [docs](https://docs.python.org/3/library/functions.html#super) /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass(subclass)] /// struct BaseClass { /// val1: usize, /// } /// /// #[pymethods] /// impl BaseClass { /// #[new] /// fn new() -> Self { /// BaseClass { val1: 10 } /// } /// /// pub fn method(&self) -> usize { /// self.val1 /// } /// } /// /// #[pyclass(extends=BaseClass)] /// struct SubClass {} /// /// #[pymethods] /// impl SubClass { /// #[new] /// fn new() -> (Self, BaseClass) { /// (SubClass {}, BaseClass::new()) /// } /// /// fn method<'py>(self_: &Bound<'py, Self>) -> PyResult> { /// let super_ = self_.py_super()?; /// super_.call_method("method", (), None) /// } /// } /// ``` pub fn new_bound<'py>( ty: &Bound<'py, PyType>, obj: &Bound<'py, PyAny>, ) -> PyResult> { PySuper::type_object_bound(ty.py()) .call1((ty, obj)) .map(|any| { // Safety: super() always returns instance of super unsafe { any.downcast_into_unchecked() } }) } } pyo3/src/types/memoryview.rs0000644000175000017500000000411414661133735017137 0ustar jamespagejamespageuse crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::{ffi, Bound, PyAny}; #[cfg(feature = "gil-refs")] use crate::{AsPyPointer, PyNativeType}; /// Represents a Python `memoryview`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyMemoryView>`][Bound]. #[repr(transparent)] pub struct PyMemoryView(PyAny); pyobject_native_type_core!(PyMemoryView, pyobject_native_static_type_object!(ffi::PyMemoryView_Type), #checkfunction=ffi::PyMemoryView_Check); impl PyMemoryView { /// Deprecated form of [`PyMemoryView::from_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyMemoryView::from` will be replaced by `PyMemoryView::from_bound` in a future PyO3 version" )] pub fn from(src: &PyAny) -> PyResult<&PyMemoryView> { PyMemoryView::from_bound(&src.as_borrowed()).map(Bound::into_gil_ref) } /// Creates a new Python `memoryview` object from another Python object that /// implements the buffer protocol. pub fn from_bound<'py>(src: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyMemoryView_FromObject(src.as_ptr()) .assume_owned_or_err(src.py()) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl<'py> TryFrom<&'py PyAny> for &'py PyMemoryView { type Error = crate::PyErr; /// Creates a new Python `memoryview` object from another Python object that /// implements the buffer protocol. fn try_from(value: &'py PyAny) -> Result { PyMemoryView::from_bound(&value.as_borrowed()).map(Bound::into_gil_ref) } } impl<'py> TryFrom<&Bound<'py, PyAny>> for Bound<'py, PyMemoryView> { type Error = crate::PyErr; /// Creates a new Python `memoryview` object from another Python object that /// implements the buffer protocol. fn try_from(value: &Bound<'py, PyAny>) -> Result { PyMemoryView::from_bound(value) } } pyo3/src/types/sequence.rs0000644000175000017500000011317414661133735016553 0ustar jamespagejamespageuse crate::err::{self, DowncastError, PyErr, PyResult}; use crate::exceptions::PyTypeError; use crate::ffi_ptr_ext::FfiPtrExt; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::instance::Bound; use crate::internal_tricks::get_ssize_index; use crate::py_result_ext::PyResultExt; use crate::sync::GILOnceCell; use crate::type_object::PyTypeInfo; use crate::types::{any::PyAnyMethods, PyAny, PyList, PyString, PyTuple, PyType}; #[cfg(feature = "gil-refs")] use crate::{err::PyDowncastError, PyNativeType}; use crate::{ffi, FromPyObject, Py, PyTypeCheck, Python, ToPyObject}; /// Represents a reference to a Python object supporting the sequence protocol. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PySequence>`][Bound]. /// /// For APIs available on sequence objects, see the [`PySequenceMethods`] trait which is implemented for /// [`Bound<'py, PySequence>`][Bound]. #[repr(transparent)] pub struct PySequence(PyAny); pyobject_native_type_named!(PySequence); pyobject_native_type_extract!(PySequence); impl PySequence { /// Register a pyclass as a subclass of `collections.abc.Sequence` (from the Python standard /// library). This is equivalent to `collections.abc.Sequence.register(T)` in Python. /// This registration is required for a pyclass to be downcastable from `PyAny` to `PySequence`. pub fn register(py: Python<'_>) -> PyResult<()> { let ty = T::type_object_bound(py); get_sequence_abc(py)?.call_method1("register", (ty,))?; Ok(()) } } #[cfg(feature = "gil-refs")] impl PySequence { /// Returns the number of objects in sequence. /// /// This is equivalent to the Python expression `len(self)`. #[inline] pub fn len(&self) -> PyResult { self.as_borrowed().len() } /// Returns whether the sequence is empty. #[inline] pub fn is_empty(&self) -> PyResult { self.as_borrowed().is_empty() } /// Returns the concatenation of `self` and `other`. /// /// This is equivalent to the Python expression `self + other`. #[inline] pub fn concat(&self, other: &PySequence) -> PyResult<&PySequence> { self.as_borrowed() .concat(&other.as_borrowed()) .map(Bound::into_gil_ref) } /// Returns the result of repeating a sequence object `count` times. /// /// This is equivalent to the Python expression `self * count`. #[inline] pub fn repeat(&self, count: usize) -> PyResult<&PySequence> { self.as_borrowed().repeat(count).map(Bound::into_gil_ref) } /// Concatenates `self` and `other`, in place if possible. /// /// This is equivalent to the Python expression `self.__iadd__(other)`. /// /// The Python statement `self += other` is syntactic sugar for `self = /// self.__iadd__(other)`. `__iadd__` should modify and return `self` if /// possible, but create and return a new object if not. #[inline] pub fn in_place_concat(&self, other: &PySequence) -> PyResult<&PySequence> { self.as_borrowed() .in_place_concat(&other.as_borrowed()) .map(Bound::into_gil_ref) } /// Repeats the sequence object `count` times and updates `self`, if possible. /// /// This is equivalent to the Python expression `self.__imul__(other)`. /// /// The Python statement `self *= other` is syntactic sugar for `self = /// self.__imul__(other)`. `__imul__` should modify and return `self` if /// possible, but create and return a new object if not. #[inline] pub fn in_place_repeat(&self, count: usize) -> PyResult<&PySequence> { self.as_borrowed() .in_place_repeat(count) .map(Bound::into_gil_ref) } /// Returns the `index`th element of the Sequence. /// /// This is equivalent to the Python expression `self[index]` without support of negative indices. #[inline] pub fn get_item(&self, index: usize) -> PyResult<&PyAny> { self.as_borrowed().get_item(index).map(Bound::into_gil_ref) } /// Returns the slice of sequence object between `begin` and `end`. /// /// This is equivalent to the Python expression `self[begin:end]`. #[inline] pub fn get_slice(&self, begin: usize, end: usize) -> PyResult<&PySequence> { self.as_borrowed() .get_slice(begin, end) .map(Bound::into_gil_ref) } /// Assigns object `item` to the `i`th element of self. /// /// This is equivalent to the Python statement `self[i] = v`. #[inline] pub fn set_item(&self, i: usize, item: I) -> PyResult<()> where I: ToPyObject, { self.as_borrowed().set_item(i, item) } /// Deletes the `i`th element of self. /// /// This is equivalent to the Python statement `del self[i]`. #[inline] pub fn del_item(&self, i: usize) -> PyResult<()> { self.as_borrowed().del_item(i) } /// Assigns the sequence `v` to the slice of `self` from `i1` to `i2`. /// /// This is equivalent to the Python statement `self[i1:i2] = v`. #[inline] pub fn set_slice(&self, i1: usize, i2: usize, v: &PyAny) -> PyResult<()> { self.as_borrowed().set_slice(i1, i2, &v.as_borrowed()) } /// Deletes the slice from `i1` to `i2` from `self`. /// /// This is equivalent to the Python statement `del self[i1:i2]`. #[inline] pub fn del_slice(&self, i1: usize, i2: usize) -> PyResult<()> { self.as_borrowed().del_slice(i1, i2) } /// Returns the number of occurrences of `value` in self, that is, return the /// number of keys for which `self[key] == value`. #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub fn count(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().count(value) } /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. #[inline] pub fn contains(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().contains(value) } /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. #[inline] pub fn index(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().index(value) } /// Returns a fresh list based on the Sequence. #[inline] pub fn to_list(&self) -> PyResult<&PyList> { self.as_borrowed().to_list().map(Bound::into_gil_ref) } /// Returns a fresh tuple based on the Sequence. #[inline] pub fn to_tuple(&self) -> PyResult<&PyTuple> { self.as_borrowed().to_tuple().map(Bound::into_gil_ref) } } /// Implementation of functionality for [`PySequence`]. /// /// These methods are defined for the `Bound<'py, PySequence>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PySequence")] pub trait PySequenceMethods<'py>: crate::sealed::Sealed { /// Returns the number of objects in sequence. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> PyResult; /// Returns whether the sequence is empty. fn is_empty(&self) -> PyResult; /// Returns the concatenation of `self` and `other`. /// /// This is equivalent to the Python expression `self + other`. fn concat(&self, other: &Bound<'_, PySequence>) -> PyResult>; /// Returns the result of repeating a sequence object `count` times. /// /// This is equivalent to the Python expression `self * count`. fn repeat(&self, count: usize) -> PyResult>; /// Concatenates `self` and `other`, in place if possible. /// /// This is equivalent to the Python expression `self.__iadd__(other)`. /// /// The Python statement `self += other` is syntactic sugar for `self = /// self.__iadd__(other)`. `__iadd__` should modify and return `self` if /// possible, but create and return a new object if not. fn in_place_concat(&self, other: &Bound<'_, PySequence>) -> PyResult>; /// Repeats the sequence object `count` times and updates `self`, if possible. /// /// This is equivalent to the Python expression `self.__imul__(other)`. /// /// The Python statement `self *= other` is syntactic sugar for `self = /// self.__imul__(other)`. `__imul__` should modify and return `self` if /// possible, but create and return a new object if not. fn in_place_repeat(&self, count: usize) -> PyResult>; /// Returns the `index`th element of the Sequence. /// /// This is equivalent to the Python expression `self[index]` without support of negative indices. fn get_item(&self, index: usize) -> PyResult>; /// Returns the slice of sequence object between `begin` and `end`. /// /// This is equivalent to the Python expression `self[begin:end]`. fn get_slice(&self, begin: usize, end: usize) -> PyResult>; /// Assigns object `item` to the `i`th element of self. /// /// This is equivalent to the Python statement `self[i] = v`. fn set_item(&self, i: usize, item: I) -> PyResult<()> where I: ToPyObject; /// Deletes the `i`th element of self. /// /// This is equivalent to the Python statement `del self[i]`. fn del_item(&self, i: usize) -> PyResult<()>; /// Assigns the sequence `v` to the slice of `self` from `i1` to `i2`. /// /// This is equivalent to the Python statement `self[i1:i2] = v`. fn set_slice(&self, i1: usize, i2: usize, v: &Bound<'_, PyAny>) -> PyResult<()>; /// Deletes the slice from `i1` to `i2` from `self`. /// /// This is equivalent to the Python statement `del self[i1:i2]`. fn del_slice(&self, i1: usize, i2: usize) -> PyResult<()>; /// Returns the number of occurrences of `value` in self, that is, return the /// number of keys for which `self[key] == value`. #[cfg(not(PyPy))] fn count(&self, value: V) -> PyResult where V: ToPyObject; /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. fn contains(&self, value: V) -> PyResult where V: ToPyObject; /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. fn index(&self, value: V) -> PyResult where V: ToPyObject; /// Returns a fresh list based on the Sequence. fn to_list(&self) -> PyResult>; /// Returns a fresh tuple based on the Sequence. fn to_tuple(&self) -> PyResult>; } impl<'py> PySequenceMethods<'py> for Bound<'py, PySequence> { #[inline] fn len(&self) -> PyResult { let v = unsafe { ffi::PySequence_Size(self.as_ptr()) }; crate::err::error_on_minusone(self.py(), v)?; Ok(v as usize) } #[inline] fn is_empty(&self) -> PyResult { self.len().map(|l| l == 0) } #[inline] fn concat(&self, other: &Bound<'_, PySequence>) -> PyResult> { unsafe { ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn repeat(&self, count: usize) -> PyResult> { unsafe { ffi::PySequence_Repeat(self.as_ptr(), get_ssize_index(count)) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn in_place_concat(&self, other: &Bound<'_, PySequence>) -> PyResult> { unsafe { ffi::PySequence_InPlaceConcat(self.as_ptr(), other.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn in_place_repeat(&self, count: usize) -> PyResult> { unsafe { ffi::PySequence_InPlaceRepeat(self.as_ptr(), get_ssize_index(count)) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn get_item(&self, index: usize) -> PyResult> { unsafe { ffi::PySequence_GetItem(self.as_ptr(), get_ssize_index(index)) .assume_owned_or_err(self.py()) } } #[inline] fn get_slice(&self, begin: usize, end: usize) -> PyResult> { unsafe { ffi::PySequence_GetSlice(self.as_ptr(), get_ssize_index(begin), get_ssize_index(end)) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn set_item(&self, i: usize, item: I) -> PyResult<()> where I: ToPyObject, { fn inner(seq: &Bound<'_, PySequence>, i: usize, item: Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(seq.py(), unsafe { ffi::PySequence_SetItem(seq.as_ptr(), get_ssize_index(i), item.as_ptr()) }) } let py = self.py(); inner(self, i, item.to_object(py).into_bound(py)) } #[inline] fn del_item(&self, i: usize) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PySequence_DelItem(self.as_ptr(), get_ssize_index(i)) }) } #[inline] fn set_slice(&self, i1: usize, i2: usize, v: &Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PySequence_SetSlice( self.as_ptr(), get_ssize_index(i1), get_ssize_index(i2), v.as_ptr(), ) }) } #[inline] fn del_slice(&self, i1: usize, i2: usize) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PySequence_DelSlice(self.as_ptr(), get_ssize_index(i1), get_ssize_index(i2)) }) } #[inline] #[cfg(not(PyPy))] fn count(&self, value: V) -> PyResult where V: ToPyObject, { fn inner(seq: &Bound<'_, PySequence>, value: Bound<'_, PyAny>) -> PyResult { let r = unsafe { ffi::PySequence_Count(seq.as_ptr(), value.as_ptr()) }; crate::err::error_on_minusone(seq.py(), r)?; Ok(r as usize) } let py = self.py(); inner(self, value.to_object(py).into_bound(py)) } #[inline] fn contains(&self, value: V) -> PyResult where V: ToPyObject, { fn inner(seq: &Bound<'_, PySequence>, value: Bound<'_, PyAny>) -> PyResult { let r = unsafe { ffi::PySequence_Contains(seq.as_ptr(), value.as_ptr()) }; match r { 0 => Ok(false), 1 => Ok(true), _ => Err(PyErr::fetch(seq.py())), } } let py = self.py(); inner(self, value.to_object(py).into_bound(py)) } #[inline] fn index(&self, value: V) -> PyResult where V: ToPyObject, { fn inner(seq: &Bound<'_, PySequence>, value: Bound<'_, PyAny>) -> PyResult { let r = unsafe { ffi::PySequence_Index(seq.as_ptr(), value.as_ptr()) }; crate::err::error_on_minusone(seq.py(), r)?; Ok(r as usize) } let py = self.py(); inner(self, value.to_object(self.py()).into_bound(py)) } #[inline] fn to_list(&self) -> PyResult> { unsafe { ffi::PySequence_List(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn to_tuple(&self) -> PyResult> { unsafe { ffi::PySequence_Tuple(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } } #[inline] #[cfg(feature = "gil-refs")] fn sequence_len(seq: &PySequence) -> usize { seq.len().expect("failed to get sequence length") } #[inline] #[cfg(feature = "gil-refs")] fn sequence_slice(seq: &PySequence, start: usize, end: usize) -> &PySequence { seq.get_slice(start, end) .expect("sequence slice operation failed") } #[cfg(feature = "gil-refs")] index_impls!(PySequence, "sequence", sequence_len, sequence_slice); impl<'py, T> FromPyObject<'py> for Vec where T: FromPyObject<'py>, { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { if obj.is_instance_of::() { return Err(PyTypeError::new_err("Can't extract `str` to `Vec`")); } extract_sequence(obj) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::sequence_of(T::type_input()) } } fn extract_sequence<'py, T>(obj: &Bound<'py, PyAny>) -> PyResult> where T: FromPyObject<'py>, { // Types that pass `PySequence_Check` usually implement enough of the sequence protocol // to support this function and if not, we will only fail extraction safely. let seq = unsafe { if ffi::PySequence_Check(obj.as_ptr()) != 0 { obj.downcast_unchecked::() } else { return Err(DowncastError::new(obj, "Sequence").into()); } }; let mut v = Vec::with_capacity(seq.len().unwrap_or(0)); for item in seq.iter()? { v.push(item?.extract::()?); } Ok(v) } fn get_sequence_abc(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { static SEQUENCE_ABC: GILOnceCell> = GILOnceCell::new(); SEQUENCE_ABC.get_or_try_init_type_ref(py, "collections.abc", "Sequence") } impl PyTypeCheck for PySequence { const NAME: &'static str = "Sequence"; #[inline] fn type_check(object: &Bound<'_, PyAny>) -> bool { // Using `is_instance` for `collections.abc.Sequence` is slow, so provide // optimized cases for list and tuples as common well-known sequences PyList::is_type_of_bound(object) || PyTuple::is_type_of_bound(object) || get_sequence_abc(object.py()) .and_then(|abc| object.is_instance(abc)) .unwrap_or_else(|err| { err.write_unraisable_bound(object.py(), Some(&object.as_borrowed())); false }) } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl<'v> crate::PyTryFrom<'v> for PySequence { /// Downcasting to `PySequence` requires the concrete class to be a subclass (or registered /// subclass) of `collections.abc.Sequence` (from the Python standard library) - i.e. /// `isinstance(, collections.abc.Sequence) == True`. fn try_from>(value: V) -> Result<&'v PySequence, PyDowncastError<'v>> { let value = value.into(); if PySequence::type_check(&value.as_borrowed()) { unsafe { return Ok(value.downcast_unchecked::()) } } Err(PyDowncastError::new(value, "Sequence")) } fn try_from_exact>(value: V) -> Result<&'v PySequence, PyDowncastError<'v>> { value.into().downcast() } #[inline] unsafe fn try_from_unchecked>(value: V) -> &'v PySequence { let ptr = value.into() as *const _ as *const PySequence; &*ptr } } #[cfg(test)] mod tests { use crate::types::{PyAnyMethods, PyList, PySequence, PySequenceMethods, PyTuple}; use crate::{PyObject, Python, ToPyObject}; fn get_object() -> PyObject { // Convenience function for getting a single unique object Python::with_gil(|py| { let obj = py.eval_bound("object()", None, None).unwrap(); obj.to_object(py) }) } #[test] fn test_numbers_are_not_sequences() { Python::with_gil(|py| { let v = 42i32; assert!(v.to_object(py).downcast_bound::(py).is_err()); }); } #[test] fn test_strings_are_sequences() { Python::with_gil(|py| { let v = "London Calling"; assert!(v.to_object(py).downcast_bound::(py).is_ok()); }); } #[test] fn test_strings_cannot_be_extracted_to_vec() { Python::with_gil(|py| { let v = "London Calling"; let ob = v.to_object(py); assert!(ob.extract::>(py).is_err()); assert!(ob.extract::>(py).is_err()); }); } #[test] fn test_seq_empty() { Python::with_gil(|py| { let v: Vec = vec![]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert_eq!(0, seq.len().unwrap()); let needle = 7i32.to_object(py); assert!(!seq.contains(&needle).unwrap()); }); } #[test] fn test_seq_is_empty() { Python::with_gil(|py| { let list = vec![1].to_object(py); let seq = list.downcast_bound::(py).unwrap(); assert!(!seq.is_empty().unwrap()); let vec: Vec = Vec::new(); let empty_list = vec.to_object(py); let empty_seq = empty_list.downcast_bound::(py).unwrap(); assert!(empty_seq.is_empty().unwrap()); }); } #[test] fn test_seq_contains() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert_eq!(6, seq.len().unwrap()); let bad_needle = 7i32.to_object(py); assert!(!seq.contains(&bad_needle).unwrap()); let good_needle = 8i32.to_object(py); assert!(seq.contains(&good_needle).unwrap()); let type_coerced_needle = 8f32.to_object(py); assert!(seq.contains(&type_coerced_needle).unwrap()); }); } #[test] fn test_seq_get_item() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert_eq!(1, seq.get_item(0).unwrap().extract::().unwrap()); assert_eq!(1, seq.get_item(1).unwrap().extract::().unwrap()); assert_eq!(2, seq.get_item(2).unwrap().extract::().unwrap()); assert_eq!(3, seq.get_item(3).unwrap().extract::().unwrap()); assert_eq!(5, seq.get_item(4).unwrap().extract::().unwrap()); assert_eq!(8, seq.get_item(5).unwrap().extract::().unwrap()); assert!(seq.get_item(10).is_err()); }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_index_trait() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2]; let ob = v.to_object(py); let seq = ob.downcast::(py).unwrap(); assert_eq!(1, seq[0].extract::().unwrap()); assert_eq!(1, seq[1].extract::().unwrap()); assert_eq!(2, seq[2].extract::().unwrap()); }); } #[test] #[should_panic = "index 7 out of range for sequence"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_index_trait_panic() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2]; let ob = v.to_object(py); let seq = ob.downcast::(py).unwrap(); let _ = &seq[7]; }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_index_trait_ranges() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2]; let ob = v.to_object(py); let seq = ob.downcast::(py).unwrap(); assert_eq!(vec![1, 2], seq[1..3].extract::>().unwrap()); assert_eq!(Vec::::new(), seq[3..3].extract::>().unwrap()); assert_eq!(vec![1, 2], seq[1..].extract::>().unwrap()); assert_eq!(Vec::::new(), seq[3..].extract::>().unwrap()); assert_eq!(vec![1, 1, 2], seq[..].extract::>().unwrap()); assert_eq!(vec![1, 2], seq[1..=2].extract::>().unwrap()); assert_eq!(vec![1, 1], seq[..2].extract::>().unwrap()); assert_eq!(vec![1, 1], seq[..=1].extract::>().unwrap()); }) } #[test] #[should_panic = "range start index 5 out of range for sequence of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_index_trait_range_panic_start() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2]; let ob = v.to_object(py); let seq = ob.downcast::(py).unwrap(); seq[5..10].extract::>().unwrap(); }) } #[test] #[should_panic = "range end index 10 out of range for sequence of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_index_trait_range_panic_end() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2]; let ob = v.to_object(py); let seq = ob.downcast::(py).unwrap(); seq[1..10].extract::>().unwrap(); }) } #[test] #[should_panic = "slice index starts at 2 but ends at 1"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_index_trait_range_panic_wrong_order() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2]; let ob = v.to_object(py); let seq = ob.downcast::(py).unwrap(); #[allow(clippy::reversed_empty_ranges)] seq[2..1].extract::>().unwrap(); }) } #[test] #[should_panic = "range start index 8 out of range for sequence of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_index_trait_range_from_panic() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2]; let ob = v.to_object(py); let seq = ob.downcast::(py).unwrap(); seq[8..].extract::>().unwrap(); }) } #[test] fn test_seq_del_item() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert!(seq.del_item(10).is_err()); assert_eq!(1, seq.get_item(0).unwrap().extract::().unwrap()); assert!(seq.del_item(0).is_ok()); assert_eq!(1, seq.get_item(0).unwrap().extract::().unwrap()); assert!(seq.del_item(0).is_ok()); assert_eq!(2, seq.get_item(0).unwrap().extract::().unwrap()); assert!(seq.del_item(0).is_ok()); assert_eq!(3, seq.get_item(0).unwrap().extract::().unwrap()); assert!(seq.del_item(0).is_ok()); assert_eq!(5, seq.get_item(0).unwrap().extract::().unwrap()); assert!(seq.del_item(0).is_ok()); assert_eq!(8, seq.get_item(0).unwrap().extract::().unwrap()); assert!(seq.del_item(0).is_ok()); assert_eq!(0, seq.len().unwrap()); assert!(seq.del_item(0).is_err()); }); } #[test] fn test_seq_set_item() { Python::with_gil(|py| { let v: Vec = vec![1, 2]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert_eq!(2, seq.get_item(1).unwrap().extract::().unwrap()); assert!(seq.set_item(1, 10).is_ok()); assert_eq!(10, seq.get_item(1).unwrap().extract::().unwrap()); }); } #[test] fn test_seq_set_item_refcnt() { let obj = get_object(); Python::with_gil(|py| { let v: Vec = vec![1, 2]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert!(seq.set_item(1, &obj).is_ok()); assert!(seq.get_item(1).unwrap().as_ptr() == obj.as_ptr()); }); Python::with_gil(move |py| { assert_eq!(1, obj.get_refcnt(py)); }); } #[test] fn test_seq_get_slice() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert_eq!( [1, 2, 3], seq.get_slice(1, 4).unwrap().extract::<[i32; 3]>().unwrap() ); assert_eq!( [3, 5, 8], seq.get_slice(3, 100) .unwrap() .extract::<[i32; 3]>() .unwrap() ); }); } #[test] fn test_set_slice() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let w: Vec = vec![7, 4]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let ins = w.to_object(py); seq.set_slice(1, 4, ins.bind(py)).unwrap(); assert_eq!([1, 7, 4, 5, 8], seq.extract::<[i32; 5]>().unwrap()); seq.set_slice(3, 100, &PyList::empty_bound(py)).unwrap(); assert_eq!([1, 7, 4], seq.extract::<[i32; 3]>().unwrap()); }); } #[test] fn test_del_slice() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); seq.del_slice(1, 4).unwrap(); assert_eq!([1, 5, 8], seq.extract::<[i32; 3]>().unwrap()); seq.del_slice(1, 100).unwrap(); assert_eq!([1], seq.extract::<[i32; 1]>().unwrap()); }); } #[test] fn test_seq_index() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert_eq!(0, seq.index(1i32).unwrap()); assert_eq!(2, seq.index(2i32).unwrap()); assert_eq!(3, seq.index(3i32).unwrap()); assert_eq!(4, seq.index(5i32).unwrap()); assert_eq!(5, seq.index(8i32).unwrap()); assert!(seq.index(42i32).is_err()); }); } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn test_seq_count() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert_eq!(2, seq.count(1i32).unwrap()); assert_eq!(1, seq.count(2i32).unwrap()); assert_eq!(1, seq.count(3i32).unwrap()); assert_eq!(1, seq.count(5i32).unwrap()); assert_eq!(1, seq.count(8i32).unwrap()); assert_eq!(0, seq.count(42i32).unwrap()); }); } #[test] fn test_seq_iter() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let mut idx = 0; for el in seq.iter().unwrap() { assert_eq!(v[idx], el.unwrap().extract::().unwrap()); idx += 1; } assert_eq!(idx, v.len()); }); } #[test] fn test_seq_strings() { Python::with_gil(|py| { let v = vec!["It", "was", "the", "worst", "of", "times"]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let bad_needle = "blurst".to_object(py); assert!(!seq.contains(bad_needle).unwrap()); let good_needle = "worst".to_object(py); assert!(seq.contains(good_needle).unwrap()); }); } #[test] fn test_seq_concat() { Python::with_gil(|py| { let v: Vec = vec![1, 2, 3]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let concat_seq = seq.concat(seq).unwrap(); assert_eq!(6, concat_seq.len().unwrap()); let concat_v: Vec = vec![1, 2, 3, 1, 2, 3]; for (el, cc) in concat_seq.iter().unwrap().zip(concat_v) { assert_eq!(cc, el.unwrap().extract::().unwrap()); } }); } #[test] fn test_seq_concat_string() { Python::with_gil(|py| { let v = "string"; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let concat_seq = seq.concat(seq).unwrap(); assert_eq!(12, concat_seq.len().unwrap()); let concat_v = "stringstring".to_owned(); for (el, cc) in seq.iter().unwrap().zip(concat_v.chars()) { assert_eq!(cc, el.unwrap().extract::().unwrap()); } }); } #[test] fn test_seq_repeat() { Python::with_gil(|py| { let v = vec!["foo", "bar"]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let repeat_seq = seq.repeat(3).unwrap(); assert_eq!(6, repeat_seq.len().unwrap()); let repeated = ["foo", "bar", "foo", "bar", "foo", "bar"]; for (el, rpt) in repeat_seq.iter().unwrap().zip(repeated.iter()) { assert_eq!(*rpt, el.unwrap().extract::().unwrap()); } }); } #[test] fn test_seq_inplace() { Python::with_gil(|py| { let v = vec!["foo", "bar"]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let rep_seq = seq.in_place_repeat(3).unwrap(); assert_eq!(6, seq.len().unwrap()); assert!(seq.is(&rep_seq)); let conc_seq = seq.in_place_concat(seq).unwrap(); assert_eq!(12, seq.len().unwrap()); assert!(seq.is(&conc_seq)); }); } #[test] fn test_list_coercion() { Python::with_gil(|py| { let v = vec!["foo", "bar"]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert!(seq .to_list() .unwrap() .eq(PyList::new_bound(py, &v)) .unwrap()); }); } #[test] fn test_strings_coerce_to_lists() { Python::with_gil(|py| { let v = "foo"; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert!(seq .to_list() .unwrap() .eq(PyList::new_bound(py, ["f", "o", "o"])) .unwrap()); }); } #[test] fn test_tuple_coercion() { Python::with_gil(|py| { let v = ("foo", "bar"); let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert!(seq .to_tuple() .unwrap() .eq(PyTuple::new_bound(py, ["foo", "bar"])) .unwrap()); }); } #[test] fn test_lists_coerce_to_tuples() { Python::with_gil(|py| { let v = vec!["foo", "bar"]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); assert!(seq .to_tuple() .unwrap() .eq(PyTuple::new_bound(py, &v)) .unwrap()); }); } #[test] fn test_extract_tuple_to_vec() { Python::with_gil(|py| { let v: Vec = py .eval_bound("(1, 2)", None, None) .unwrap() .extract() .unwrap(); assert!(v == [1, 2]); }); } #[test] fn test_extract_range_to_vec() { Python::with_gil(|py| { let v: Vec = py .eval_bound("range(1, 5)", None, None) .unwrap() .extract() .unwrap(); assert!(v == [1, 2, 3, 4]); }); } #[test] fn test_extract_bytearray_to_vec() { Python::with_gil(|py| { let v: Vec = py .eval_bound("bytearray(b'abc')", None, None) .unwrap() .extract() .unwrap(); assert!(v == b"abc"); }); } #[test] fn test_seq_downcast_unchecked() { Python::with_gil(|py| { let v = vec!["foo", "bar"]; let ob = v.to_object(py); let seq = ob.downcast_bound::(py).unwrap(); let type_ptr = seq.as_ref(); let seq_from = unsafe { type_ptr.downcast_unchecked::() }; assert!(seq_from.to_list().is_ok()); }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_seq_try_from() { use crate::PyTryFrom; Python::with_gil(|py| { let list = PyList::empty(py); let _ = ::try_from(list).unwrap(); let _ = PySequence::try_from_exact(list).unwrap(); }); } } pyo3/src/types/tuple.rs0000644000175000017500000013333014661133735016070 0ustar jamespagejamespageuse std::iter::FusedIterator; use crate::ffi::{self, Py_ssize_t}; use crate::ffi_ptr_ext::FfiPtrExt; #[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; use crate::instance::Borrowed; use crate::internal_tricks::get_ssize_index; use crate::types::{any::PyAnyMethods, sequence::PySequenceMethods, PyList, PySequence}; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ exceptions, Bound, FromPyObject, IntoPy, Py, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject, }; #[inline] #[track_caller] fn new_from_iter<'py>( py: Python<'py>, elements: &mut dyn ExactSizeIterator, ) -> Bound<'py, PyTuple> { unsafe { // PyTuple_New checks for overflow but has a bad error message, so we check ourselves let len: Py_ssize_t = elements .len() .try_into() .expect("out of range integral type conversion attempted on `elements.len()`"); let ptr = ffi::PyTuple_New(len); // - Panics if the ptr is null // - Cleans up the tuple if `convert` or the asserts panic let tup = ptr.assume_owned(py).downcast_into_unchecked(); let mut counter: Py_ssize_t = 0; for obj in elements.take(len as usize) { #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] ffi::PyTuple_SET_ITEM(ptr, counter, obj.into_ptr()); #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] ffi::PyTuple_SetItem(ptr, counter, obj.into_ptr()); counter += 1; } assert!(elements.next().is_none(), "Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation."); assert_eq!(len, counter, "Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation."); tup } } /// Represents a Python `tuple` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTuple>`][Bound]. /// /// For APIs available on `tuple` objects, see the [`PyTupleMethods`] trait which is implemented for /// [`Bound<'py, PyTuple>`][Bound]. #[repr(transparent)] pub struct PyTuple(PyAny); pyobject_native_type_core!(PyTuple, pyobject_native_static_type_object!(ffi::PyTuple_Type), #checkfunction=ffi::PyTuple_Check); impl PyTuple { /// Constructs a new tuple with the given elements. /// /// If you want to create a [`PyTuple`] with elements of different or unknown types, or from an /// iterable that doesn't implement [`ExactSizeIterator`], create a Rust tuple with the given /// elements and convert it at once using `into_py`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyTuple; /// /// # fn main() { /// Python::with_gil(|py| { /// let elements: Vec = vec![0, 1, 2, 3, 4, 5]; /// let tuple = PyTuple::new_bound(py, elements); /// assert_eq!(format!("{:?}", tuple), "(0, 1, 2, 3, 4, 5)"); /// }); /// # } /// ``` /// /// # Panics /// /// This function will panic if `element`'s [`ExactSizeIterator`] implementation is incorrect. /// All standard library structures implement this trait correctly, if they do, so calling this /// function using [`Vec`]`` or `&[T]` will always succeed. #[track_caller] pub fn new_bound( py: Python<'_>, elements: impl IntoIterator, ) -> Bound<'_, PyTuple> where T: ToPyObject, U: ExactSizeIterator, { let mut elements = elements.into_iter().map(|e| e.to_object(py)); new_from_iter(py, &mut elements) } /// Constructs an empty tuple (on the Python side, a singleton object). pub fn empty_bound(py: Python<'_>) -> Bound<'_, PyTuple> { unsafe { ffi::PyTuple_New(0) .assume_owned(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyTuple { /// Deprecated form of `PyTuple::new_bound`. #[track_caller] #[deprecated( since = "0.21.0", note = "`PyTuple::new` will be replaced by `PyTuple::new_bound` in a future PyO3 version" )] pub fn new( py: Python<'_>, elements: impl IntoIterator, ) -> &PyTuple where T: ToPyObject, U: ExactSizeIterator, { Self::new_bound(py, elements).into_gil_ref() } /// Deprecated form of `PyTuple::empty_bound`. #[deprecated( since = "0.21.0", note = "`PyTuple::empty` will be replaced by `PyTuple::empty_bound` in a future PyO3 version" )] pub fn empty(py: Python<'_>) -> &PyTuple { Self::empty_bound(py).into_gil_ref() } /// Gets the length of the tuple. pub fn len(&self) -> usize { self.as_borrowed().len() } /// Checks if the tuple is empty. pub fn is_empty(&self) -> bool { self.as_borrowed().is_empty() } /// Returns `self` cast as a `PySequence`. pub fn as_sequence(&self) -> &PySequence { unsafe { self.downcast_unchecked() } } /// Takes the slice `self[low:high]` and returns it as a new tuple. /// /// Indices must be nonnegative, and out-of-range indices are clipped to /// `self.len()`. pub fn get_slice(&self, low: usize, high: usize) -> &PyTuple { self.as_borrowed().get_slice(low, high).into_gil_ref() } /// Gets the tuple item at the specified index. /// # Example /// ``` /// use pyo3::{prelude::*, types::PyTuple}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let ob = (1, 2, 3).to_object(py); /// let tuple = ob.downcast_bound::(py).unwrap(); /// let obj = tuple.get_item(0); /// assert_eq!(obj.unwrap().extract::().unwrap(), 1); /// Ok(()) /// }) /// # } /// ``` pub fn get_item(&self, index: usize) -> PyResult<&PyAny> { self.as_borrowed() .get_borrowed_item(index) .map(Borrowed::into_gil_ref) } /// Gets the tuple item at the specified index. Undefined behavior on bad index. Use with caution. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] pub unsafe fn get_item_unchecked(&self, index: usize) -> &PyAny { self.as_borrowed() .get_borrowed_item_unchecked(index) .into_gil_ref() } /// Returns `self` as a slice of objects. #[cfg(not(any(Py_LIMITED_API, GraalPy)))] pub fn as_slice(&self) -> &[&PyAny] { // This is safe because &PyAny has the same memory layout as *mut ffi::PyObject, // and because tuples are immutable. unsafe { let ptr = self.as_ptr() as *mut ffi::PyTupleObject; let slice = std::slice::from_raw_parts((*ptr).ob_item.as_ptr(), self.len()); &*(slice as *const [*mut ffi::PyObject] as *const [&PyAny]) } } /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. #[inline] pub fn contains(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().contains(value) } /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. #[inline] pub fn index(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().index(value) } /// Returns an iterator over the tuple items. pub fn iter(&self) -> PyTupleIterator<'_> { PyTupleIterator(BorrowedTupleIterator::new(self.as_borrowed())) } /// Return a new list containing the contents of this tuple; equivalent to the Python expression `list(tuple)`. /// /// This method is equivalent to `self.as_sequence().to_list()` and faster than `PyList::new(py, self)`. pub fn to_list(&self) -> &PyList { self.as_borrowed().to_list().into_gil_ref() } } #[cfg(feature = "gil-refs")] index_impls!(PyTuple, "tuple", PyTuple::len, PyTuple::get_slice); /// Implementation of functionality for [`PyTuple`]. /// /// These methods are defined for the `Bound<'py, PyTuple>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyTuple")] pub trait PyTupleMethods<'py>: crate::sealed::Sealed { /// Gets the length of the tuple. fn len(&self) -> usize; /// Checks if the tuple is empty. fn is_empty(&self) -> bool; /// Returns `self` cast as a `PySequence`. fn as_sequence(&self) -> &Bound<'py, PySequence>; /// Returns `self` cast as a `PySequence`. fn into_sequence(self) -> Bound<'py, PySequence>; /// Takes the slice `self[low:high]` and returns it as a new tuple. /// /// Indices must be nonnegative, and out-of-range indices are clipped to /// `self.len()`. fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyTuple>; /// Gets the tuple item at the specified index. /// # Example /// ``` /// use pyo3::{prelude::*, types::PyTuple}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let ob = (1, 2, 3).to_object(py); /// let tuple = ob.downcast_bound::(py).unwrap(); /// let obj = tuple.get_item(0); /// assert_eq!(obj.unwrap().extract::().unwrap(), 1); /// Ok(()) /// }) /// # } /// ``` fn get_item(&self, index: usize) -> PyResult>; /// Like [`get_item`][PyTupleMethods::get_item], but returns a borrowed object, which is a slight performance optimization /// by avoiding a reference count change. fn get_borrowed_item<'a>(&'a self, index: usize) -> PyResult>; /// Gets the tuple item at the specified index. Undefined behavior on bad index. Use with caution. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny>; /// Like [`get_item_unchecked`][PyTupleMethods::get_item_unchecked], but returns a borrowed object, /// which is a slight performance optimization by avoiding a reference count change. /// /// # Safety /// /// Caller must verify that the index is within the bounds of the tuple. #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny>; /// Returns `self` as a slice of objects. #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn as_slice(&self) -> &[Bound<'py, PyAny>]; /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. fn contains(&self, value: V) -> PyResult where V: ToPyObject; /// Returns the first index `i` for which `self[i] == value`. /// /// This is equivalent to the Python expression `self.index(value)`. fn index(&self, value: V) -> PyResult where V: ToPyObject; /// Returns an iterator over the tuple items. fn iter(&self) -> BoundTupleIterator<'py>; /// Like [`iter`][PyTupleMethods::iter], but produces an iterator which returns borrowed objects, /// which is a slight performance optimization by avoiding a reference count change. fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py>; /// Return a new list containing the contents of this tuple; equivalent to the Python expression `list(tuple)`. /// /// This method is equivalent to `self.as_sequence().to_list()` and faster than `PyList::new(py, self)`. fn to_list(&self) -> Bound<'py, PyList>; } impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> { fn len(&self) -> usize { unsafe { #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] let size = ffi::PyTuple_GET_SIZE(self.as_ptr()); #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] let size = ffi::PyTuple_Size(self.as_ptr()); // non-negative Py_ssize_t should always fit into Rust uint size as usize } } fn is_empty(&self) -> bool { self.len() == 0 } fn as_sequence(&self) -> &Bound<'py, PySequence> { unsafe { self.downcast_unchecked() } } fn into_sequence(self) -> Bound<'py, PySequence> { unsafe { self.into_any().downcast_into_unchecked() } } fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyTuple> { unsafe { ffi::PyTuple_GetSlice(self.as_ptr(), get_ssize_index(low), get_ssize_index(high)) .assume_owned(self.py()) .downcast_into_unchecked() } } fn get_item(&self, index: usize) -> PyResult> { self.get_borrowed_item(index).map(Borrowed::to_owned) } fn get_borrowed_item<'a>(&'a self, index: usize) -> PyResult> { self.as_borrowed().get_borrowed_item(index) } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny> { self.get_borrowed_item_unchecked(index).to_owned() } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny> { self.as_borrowed().get_borrowed_item_unchecked(index) } #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn as_slice(&self) -> &[Bound<'py, PyAny>] { // SAFETY: self is known to be a tuple object, and tuples are immutable let items = unsafe { &(*self.as_ptr().cast::()).ob_item }; // SAFETY: Bound<'py, PyAny> has the same memory layout as *mut ffi::PyObject unsafe { std::slice::from_raw_parts(items.as_ptr().cast(), self.len()) } } #[inline] fn contains(&self, value: V) -> PyResult where V: ToPyObject, { self.as_sequence().contains(value) } #[inline] fn index(&self, value: V) -> PyResult where V: ToPyObject, { self.as_sequence().index(value) } fn iter(&self) -> BoundTupleIterator<'py> { BoundTupleIterator::new(self.clone()) } fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py> { self.as_borrowed().iter_borrowed() } fn to_list(&self) -> Bound<'py, PyList> { self.as_sequence() .to_list() .expect("failed to convert tuple to list") } } impl<'a, 'py> Borrowed<'a, 'py, PyTuple> { fn get_borrowed_item(self, index: usize) -> PyResult> { unsafe { ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t) .assume_borrowed_or_err(self.py()) } } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> { ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t).assume_borrowed(self.py()) } pub(crate) fn iter_borrowed(self) -> BorrowedTupleIterator<'a, 'py> { BorrowedTupleIterator::new(self) } } /// Used by `PyTuple::iter()`. #[cfg(feature = "gil-refs")] pub struct PyTupleIterator<'a>(BorrowedTupleIterator<'a, 'a>); #[cfg(feature = "gil-refs")] impl<'a> Iterator for PyTupleIterator<'a> { type Item = &'a PyAny; #[inline] fn next(&mut self) -> Option { self.0.next().map(Borrowed::into_gil_ref) } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[cfg(feature = "gil-refs")] impl<'a> DoubleEndedIterator for PyTupleIterator<'a> { #[inline] fn next_back(&mut self) -> Option { self.0.next_back().map(Borrowed::into_gil_ref) } } #[cfg(feature = "gil-refs")] impl<'a> ExactSizeIterator for PyTupleIterator<'a> { fn len(&self) -> usize { self.0.len() } } #[cfg(feature = "gil-refs")] impl FusedIterator for PyTupleIterator<'_> {} #[cfg(feature = "gil-refs")] impl<'a> IntoIterator for &'a PyTuple { type Item = &'a PyAny; type IntoIter = PyTupleIterator<'a>; fn into_iter(self) -> Self::IntoIter { PyTupleIterator(BorrowedTupleIterator::new(self.as_borrowed())) } } /// Used by `PyTuple::into_iter()`. pub struct BoundTupleIterator<'py> { tuple: Bound<'py, PyTuple>, index: usize, length: usize, } impl<'py> BoundTupleIterator<'py> { fn new(tuple: Bound<'py, PyTuple>) -> Self { let length = tuple.len(); BoundTupleIterator { tuple, index: 0, length, } } } impl<'py> Iterator for BoundTupleIterator<'py> { type Item = Bound<'py, PyAny>; #[inline] fn next(&mut self) -> Option { if self.index < self.length { let item = unsafe { BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.index).to_owned() }; self.index += 1; Some(item) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } } impl<'py> DoubleEndedIterator for BoundTupleIterator<'py> { #[inline] fn next_back(&mut self) -> Option { if self.index < self.length { let item = unsafe { BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.length - 1) .to_owned() }; self.length -= 1; Some(item) } else { None } } } impl<'py> ExactSizeIterator for BoundTupleIterator<'py> { fn len(&self) -> usize { self.length.saturating_sub(self.index) } } impl FusedIterator for BoundTupleIterator<'_> {} impl<'py> IntoIterator for Bound<'py, PyTuple> { type Item = Bound<'py, PyAny>; type IntoIter = BoundTupleIterator<'py>; fn into_iter(self) -> Self::IntoIter { BoundTupleIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PyTuple> { type Item = Bound<'py, PyAny>; type IntoIter = BoundTupleIterator<'py>; fn into_iter(self) -> Self::IntoIter { self.iter() } } /// Used by `PyTuple::iter_borrowed()`. pub struct BorrowedTupleIterator<'a, 'py> { tuple: Borrowed<'a, 'py, PyTuple>, index: usize, length: usize, } impl<'a, 'py> BorrowedTupleIterator<'a, 'py> { fn new(tuple: Borrowed<'a, 'py, PyTuple>) -> Self { let length = tuple.len(); BorrowedTupleIterator { tuple, index: 0, length, } } unsafe fn get_item( tuple: Borrowed<'a, 'py, PyTuple>, index: usize, ) -> Borrowed<'a, 'py, PyAny> { #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] let item = tuple.get_borrowed_item(index).expect("tuple.get failed"); #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] let item = tuple.get_borrowed_item_unchecked(index); item } } impl<'a, 'py> Iterator for BorrowedTupleIterator<'a, 'py> { type Item = Borrowed<'a, 'py, PyAny>; #[inline] fn next(&mut self) -> Option { if self.index < self.length { let item = unsafe { Self::get_item(self.tuple, self.index) }; self.index += 1; Some(item) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } } impl<'a, 'py> DoubleEndedIterator for BorrowedTupleIterator<'a, 'py> { #[inline] fn next_back(&mut self) -> Option { if self.index < self.length { let item = unsafe { Self::get_item(self.tuple, self.length - 1) }; self.length -= 1; Some(item) } else { None } } } impl<'a, 'py> ExactSizeIterator for BorrowedTupleIterator<'a, 'py> { fn len(&self) -> usize { self.length.saturating_sub(self.index) } } impl FusedIterator for BorrowedTupleIterator<'_, '_> {} impl IntoPy> for Bound<'_, PyTuple> { fn into_py(self, _: Python<'_>) -> Py { self.unbind() } } impl IntoPy> for &'_ Bound<'_, PyTuple> { fn into_py(self, _: Python<'_>) -> Py { self.clone().unbind() } } #[cold] fn wrong_tuple_length(t: &Bound<'_, PyTuple>, expected_length: usize) -> PyErr { let msg = format!( "expected tuple of length {}, but got tuple of length {}", expected_length, t.len() ); exceptions::PyValueError::new_err(msg) } macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+} => { impl <$($T: ToPyObject),+> ToPyObject for ($($T,)+) { fn to_object(&self, py: Python<'_>) -> PyObject { array_into_tuple(py, [$(self.$n.to_object(py)),+]).into() } } impl <$($T: IntoPy),+> IntoPy for ($($T,)+) { fn into_py(self, py: Python<'_>) -> PyObject { array_into_tuple(py, [$(self.$n.into_py(py)),+]).into() } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::Tuple(Some(vec![$( $T::type_output() ),+])) } } impl <$($T: IntoPy),+> IntoPy> for ($($T,)+) { fn into_py(self, py: Python<'_>) -> Py { array_into_tuple(py, [$(self.$n.into_py(py)),+]) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::Tuple(Some(vec![$( $T::type_output() ),+])) } } impl<'py, $($T: FromPyObject<'py>),+> FromPyObject<'py> for ($($T,)+) { fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult { let t = obj.downcast::()?; if t.len() == $length { #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] return Ok(($(t.get_borrowed_item($n)?.extract::<$T>()?,)+)); #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] unsafe {return Ok(($(t.get_borrowed_item_unchecked($n).extract::<$T>()?,)+));} } else { Err(wrong_tuple_length(t, $length)) } } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { TypeInfo::Tuple(Some(vec![$( $T::type_input() ),+])) } } }); fn array_into_tuple(py: Python<'_>, array: [PyObject; N]) -> Py { unsafe { let ptr = ffi::PyTuple_New(N.try_into().expect("0 < N <= 12")); let tup = Py::from_owned_ptr(py, ptr); for (index, obj) in array.into_iter().enumerate() { #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] ffi::PyTuple_SET_ITEM(ptr, index as ffi::Py_ssize_t, obj.into_ptr()); #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))] ffi::PyTuple_SetItem(ptr, index as ffi::Py_ssize_t, obj.into_ptr()); } tup } } tuple_conversion!(1, (ref0, 0, T0)); tuple_conversion!(2, (ref0, 0, T0), (ref1, 1, T1)); tuple_conversion!(3, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2)); tuple_conversion!( 4, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3) ); tuple_conversion!( 5, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4) ); tuple_conversion!( 6, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5) ); tuple_conversion!( 7, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6) ); tuple_conversion!( 8, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7) ); tuple_conversion!( 9, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8) ); tuple_conversion!( 10, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8), (ref9, 9, T9) ); tuple_conversion!( 11, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8), (ref9, 9, T9), (ref10, 10, T10) ); tuple_conversion!( 12, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2), (ref3, 3, T3), (ref4, 4, T4), (ref5, 5, T5), (ref6, 6, T6), (ref7, 7, T7), (ref8, 8, T8), (ref9, 9, T9), (ref10, 10, T10), (ref11, 11, T11) ); #[cfg(test)] mod tests { use crate::types::{any::PyAnyMethods, tuple::PyTupleMethods, PyList, PyTuple}; use crate::{Python, ToPyObject}; use std::collections::HashSet; #[test] fn test_new() { Python::with_gil(|py| { let ob = PyTuple::new_bound(py, [1, 2, 3]); assert_eq!(3, ob.len()); let ob = ob.as_any(); assert_eq!((1, 2, 3), ob.extract().unwrap()); let mut map = HashSet::new(); map.insert(1); map.insert(2); PyTuple::new_bound(py, map); }); } #[test] fn test_len() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); assert_eq!(3, tuple.len()); assert!(!tuple.is_empty()); let ob = tuple.as_any(); assert_eq!((1, 2, 3), ob.extract().unwrap()); }); } #[test] fn test_empty() { Python::with_gil(|py| { let tuple = PyTuple::empty_bound(py); assert!(tuple.is_empty()); assert_eq!(0, tuple.len()); }); } #[test] fn test_slice() { Python::with_gil(|py| { let tup = PyTuple::new_bound(py, [2, 3, 5, 7]); let slice = tup.get_slice(1, 3); assert_eq!(2, slice.len()); let slice = tup.get_slice(1, 7); assert_eq!(3, slice.len()); }); } #[test] fn test_iter() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); assert_eq!(3, tuple.len()); let mut iter = tuple.iter(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_iter_rev() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); assert_eq!(3, tuple.len()); let mut iter = tuple.iter().rev(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_bound_iter() { Python::with_gil(|py| { let tuple = PyTuple::new_bound(py, [1, 2, 3]); assert_eq!(3, tuple.len()); let mut iter = tuple.iter(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(1, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(3, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_bound_iter_rev() { Python::with_gil(|py| { let tuple = PyTuple::new_bound(py, [1, 2, 3]); assert_eq!(3, tuple.len()); let mut iter = tuple.iter().rev(); assert_eq!(iter.size_hint(), (3, Some(3))); assert_eq!(3, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (2, Some(2))); assert_eq!(2, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (1, Some(1))); assert_eq!(1, iter.next().unwrap().extract::().unwrap()); assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert!(iter.next().is_none()); }); } #[test] fn test_into_iter() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); assert_eq!(3, tuple.len()); for (i, item) in tuple.iter().enumerate() { assert_eq!(i + 1, item.extract::<'_, usize>().unwrap()); } }); } #[test] fn test_into_iter_bound() { use crate::Bound; Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &Bound<'_, PyTuple> = ob.downcast_bound(py).unwrap(); assert_eq!(3, tuple.len()); let mut items = vec![]; for item in tuple { items.push(item.extract::().unwrap()); } assert_eq!(items, vec![1, 2, 3]); }); } #[test] #[cfg(not(any(Py_LIMITED_API, GraalPy)))] fn test_as_slice() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); let slice = tuple.as_slice(); assert_eq!(3, slice.len()); assert_eq!(1_i32, slice[0].extract::<'_, i32>().unwrap()); assert_eq!(2_i32, slice[1].extract::<'_, i32>().unwrap()); assert_eq!(3_i32, slice[2].extract::<'_, i32>().unwrap()); }); } #[test] fn test_tuple_lengths_up_to_12() { Python::with_gil(|py| { let t0 = (0,).to_object(py); let t1 = (0, 1).to_object(py); let t2 = (0, 1, 2).to_object(py); let t3 = (0, 1, 2, 3).to_object(py); let t4 = (0, 1, 2, 3, 4).to_object(py); let t5 = (0, 1, 2, 3, 4, 5).to_object(py); let t6 = (0, 1, 2, 3, 4, 5, 6).to_object(py); let t7 = (0, 1, 2, 3, 4, 5, 6, 7).to_object(py); let t8 = (0, 1, 2, 3, 4, 5, 6, 7, 8).to_object(py); let t9 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9).to_object(py); let t10 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10).to_object(py); let t11 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11).to_object(py); assert_eq!(t0.extract::<(i32,)>(py).unwrap(), (0,)); assert_eq!(t1.extract::<(i32, i32)>(py).unwrap(), (0, 1,)); assert_eq!(t2.extract::<(i32, i32, i32)>(py).unwrap(), (0, 1, 2,)); assert_eq!( t3.extract::<(i32, i32, i32, i32,)>(py).unwrap(), (0, 1, 2, 3,) ); assert_eq!( t4.extract::<(i32, i32, i32, i32, i32,)>(py).unwrap(), (0, 1, 2, 3, 4,) ); assert_eq!( t5.extract::<(i32, i32, i32, i32, i32, i32,)>(py).unwrap(), (0, 1, 2, 3, 4, 5,) ); assert_eq!( t6.extract::<(i32, i32, i32, i32, i32, i32, i32,)>(py) .unwrap(), (0, 1, 2, 3, 4, 5, 6,) ); assert_eq!( t7.extract::<(i32, i32, i32, i32, i32, i32, i32, i32,)>(py) .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7,) ); assert_eq!( t8.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32,)>(py) .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8,) ); assert_eq!( t9.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>(py) .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9,) ); assert_eq!( t10.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>(py) .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,) ); assert_eq!( t11.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>(py) .unwrap(), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,) ); }) } #[test] fn test_tuple_get_item_invalid_index() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); let obj = tuple.get_item(5); assert!(obj.is_err()); assert_eq!( obj.unwrap_err().to_string(), "IndexError: tuple index out of range" ); }); } #[test] fn test_tuple_get_item_sanity() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); let obj = tuple.get_item(0); assert_eq!(obj.unwrap().extract::().unwrap(), 1); }); } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[test] fn test_tuple_get_item_unchecked_sanity() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); let obj = unsafe { tuple.get_item_unchecked(0) }; assert_eq!(obj.extract::().unwrap(), 1); }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_tuple_index_trait() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &PyTuple = ob.downcast(py).unwrap(); assert_eq!(1, tuple[0].extract::().unwrap()); assert_eq!(2, tuple[1].extract::().unwrap()); assert_eq!(3, tuple[2].extract::().unwrap()); }); } #[test] #[should_panic] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_tuple_index_trait_panic() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &PyTuple = ob.downcast(py).unwrap(); let _ = &tuple[7]; }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_tuple_index_trait_ranges() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &PyTuple = ob.downcast(py).unwrap(); assert_eq!(vec![2, 3], tuple[1..3].extract::>().unwrap()); assert_eq!( Vec::::new(), tuple[3..3].extract::>().unwrap() ); assert_eq!(vec![2, 3], tuple[1..].extract::>().unwrap()); assert_eq!(Vec::::new(), tuple[3..].extract::>().unwrap()); assert_eq!(vec![1, 2, 3], tuple[..].extract::>().unwrap()); assert_eq!(vec![2, 3], tuple[1..=2].extract::>().unwrap()); assert_eq!(vec![1, 2], tuple[..2].extract::>().unwrap()); assert_eq!(vec![1, 2], tuple[..=1].extract::>().unwrap()); }) } #[test] #[should_panic = "range start index 5 out of range for tuple of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_tuple_index_trait_range_panic_start() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &PyTuple = ob.downcast(py).unwrap(); tuple[5..10].extract::>().unwrap(); }) } #[test] #[should_panic = "range end index 10 out of range for tuple of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_tuple_index_trait_range_panic_end() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &PyTuple = ob.downcast(py).unwrap(); tuple[1..10].extract::>().unwrap(); }) } #[test] #[should_panic = "slice index starts at 2 but ends at 1"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_tuple_index_trait_range_panic_wrong_order() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &PyTuple = ob.downcast(py).unwrap(); #[allow(clippy::reversed_empty_ranges)] tuple[2..1].extract::>().unwrap(); }) } #[test] #[should_panic = "range start index 8 out of range for tuple of length 3"] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_tuple_index_trait_range_from_panic() { Python::with_gil(|py| { let ob = (1, 2, 3).to_object(py); let tuple: &PyTuple = ob.downcast(py).unwrap(); tuple[8..].extract::>().unwrap(); }) } #[test] fn test_tuple_contains() { Python::with_gil(|py| { let ob = (1, 1, 2, 3, 5, 8).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); assert_eq!(6, tuple.len()); let bad_needle = 7i32.to_object(py); assert!(!tuple.contains(&bad_needle).unwrap()); let good_needle = 8i32.to_object(py); assert!(tuple.contains(&good_needle).unwrap()); let type_coerced_needle = 8f32.to_object(py); assert!(tuple.contains(&type_coerced_needle).unwrap()); }); } #[test] fn test_tuple_index() { Python::with_gil(|py| { let ob = (1, 1, 2, 3, 5, 8).to_object(py); let tuple = ob.downcast_bound::(py).unwrap(); assert_eq!(0, tuple.index(1i32).unwrap()); assert_eq!(2, tuple.index(2i32).unwrap()); assert_eq!(3, tuple.index(3i32).unwrap()); assert_eq!(4, tuple.index(5i32).unwrap()); assert_eq!(5, tuple.index(8i32).unwrap()); assert!(tuple.index(42i32).is_err()); }); } use std::ops::Range; // An iterator that lies about its `ExactSizeIterator` implementation. // See https://github.com/PyO3/pyo3/issues/2118 struct FaultyIter(Range, usize); impl Iterator for FaultyIter { type Item = usize; fn next(&mut self) -> Option { self.0.next() } } impl ExactSizeIterator for FaultyIter { fn len(&self) -> usize { self.1 } } #[test] #[should_panic( expected = "Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation." )] fn too_long_iterator() { Python::with_gil(|py| { let iter = FaultyIter(0..usize::MAX, 73); let _tuple = PyTuple::new_bound(py, iter); }) } #[test] #[should_panic( expected = "Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation." )] fn too_short_iterator() { Python::with_gil(|py| { let iter = FaultyIter(0..35, 73); let _tuple = PyTuple::new_bound(py, iter); }) } #[test] #[should_panic( expected = "out of range integral type conversion attempted on `elements.len()`" )] fn overflowing_size() { Python::with_gil(|py| { let iter = FaultyIter(0..0, usize::MAX); let _tuple = PyTuple::new_bound(py, iter); }) } #[cfg(feature = "macros")] #[test] fn bad_clone_mem_leaks() { use crate::{IntoPy, Py, PyAny}; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0); #[crate::pyclass] #[pyo3(crate = "crate")] struct Bad(usize); impl Clone for Bad { fn clone(&self) -> Self { // This panic should not lead to a memory leak assert_ne!(self.0, 42); NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst); Bad(self.0) } } impl Drop for Bad { fn drop(&mut self) { NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst); } } impl ToPyObject for Bad { fn to_object(&self, py: Python<'_>) -> Py { self.to_owned().into_py(py) } } struct FaultyIter(Range, usize); impl Iterator for FaultyIter { type Item = Bad; fn next(&mut self) -> Option { self.0.next().map(|i| { NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst); Bad(i) }) } } impl ExactSizeIterator for FaultyIter { fn len(&self) -> usize { self.1 } } Python::with_gil(|py| { std::panic::catch_unwind(|| { let iter = FaultyIter(0..50, 50); let _tuple = PyTuple::new_bound(py, iter); }) .unwrap_err(); }); assert_eq!( NEEDS_DESTRUCTING_COUNT.load(SeqCst), 0, "Some destructors did not run" ); } #[cfg(feature = "macros")] #[test] fn bad_clone_mem_leaks_2() { use crate::{IntoPy, Py, PyAny}; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0); #[crate::pyclass] #[pyo3(crate = "crate")] struct Bad(usize); impl Clone for Bad { fn clone(&self) -> Self { // This panic should not lead to a memory leak assert_ne!(self.0, 3); NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst); Bad(self.0) } } impl Drop for Bad { fn drop(&mut self) { NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst); } } impl ToPyObject for Bad { fn to_object(&self, py: Python<'_>) -> Py { self.to_owned().into_py(py) } } let s = (Bad(1), Bad(2), Bad(3), Bad(4)); NEEDS_DESTRUCTING_COUNT.store(4, SeqCst); Python::with_gil(|py| { std::panic::catch_unwind(|| { let _tuple: Py = s.to_object(py); }) .unwrap_err(); }); drop(s); assert_eq!( NEEDS_DESTRUCTING_COUNT.load(SeqCst), 0, "Some destructors did not run" ); } #[test] fn test_tuple_to_list() { Python::with_gil(|py| { let tuple = PyTuple::new_bound(py, vec![1, 2, 3]); let list = tuple.to_list(); let list_expected = PyList::new_bound(py, vec![1, 2, 3]); assert!(list.eq(list_expected).unwrap()); }) } #[test] fn test_tuple_as_sequence() { Python::with_gil(|py| { let tuple = PyTuple::new_bound(py, vec![1, 2, 3]); let sequence = tuple.as_sequence(); assert!(tuple.get_item(0).unwrap().eq(1).unwrap()); assert!(sequence.get_item(0).unwrap().eq(1).unwrap()); assert_eq!(tuple.len(), 3); assert_eq!(sequence.len().unwrap(), 3); }) } #[test] fn test_tuple_into_sequence() { Python::with_gil(|py| { let tuple = PyTuple::new_bound(py, vec![1, 2, 3]); let sequence = tuple.into_sequence(); assert!(sequence.get_item(0).unwrap().eq(1).unwrap()); assert_eq!(sequence.len().unwrap(), 3); }) } #[test] fn test_bound_tuple_get_item() { Python::with_gil(|py| { let tuple = PyTuple::new_bound(py, vec![1, 2, 3, 4]); assert_eq!(tuple.len(), 4); assert_eq!(tuple.get_item(0).unwrap().extract::().unwrap(), 1); assert_eq!( tuple .get_borrowed_item(1) .unwrap() .extract::() .unwrap(), 2 ); #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] { assert_eq!( unsafe { tuple.get_item_unchecked(2) } .extract::() .unwrap(), 3 ); assert_eq!( unsafe { tuple.get_borrowed_item_unchecked(3) } .extract::() .unwrap(), 4 ); } }) } } pyo3/src/types/notimplemented.rs0000644000175000017500000000521114661133735017757 0ustar jamespagejamespageuse crate::{ ffi, ffi_ptr_ext::FfiPtrExt, types::any::PyAnyMethods, Borrowed, Bound, PyAny, PyTypeInfo, Python, }; /// Represents the Python `NotImplemented` object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyNotImplemented>`][Bound]. #[repr(transparent)] pub struct PyNotImplemented(PyAny); pyobject_native_type_named!(PyNotImplemented); pyobject_native_type_extract!(PyNotImplemented); impl PyNotImplemented { /// Returns the `NotImplemented` object. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyNotImplemented::get` will be replaced by `PyNotImplemented::get_bound` in a future PyO3 version" )] #[inline] pub fn get(py: Python<'_>) -> &PyNotImplemented { Self::get_bound(py).into_gil_ref() } /// Returns the `NotImplemented` object. #[inline] pub fn get_bound(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> { unsafe { ffi::Py_NotImplemented() .assume_borrowed(py) .downcast_unchecked() } } } unsafe impl PyTypeInfo for PyNotImplemented { const NAME: &'static str = "NotImplementedType"; const MODULE: Option<&'static str> = None; fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject { unsafe { ffi::Py_TYPE(ffi::Py_NotImplemented()) } } #[inline] fn is_type_of_bound(object: &Bound<'_, PyAny>) -> bool { // NotImplementedType is not usable as a base type Self::is_exact_type_of_bound(object) } #[inline] fn is_exact_type_of_bound(object: &Bound<'_, PyAny>) -> bool { object.is(&**Self::get_bound(object.py())) } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::types::{PyDict, PyNotImplemented}; use crate::{PyTypeInfo, Python}; #[test] fn test_notimplemented_is_itself() { Python::with_gil(|py| { assert!(PyNotImplemented::get_bound(py).is_instance_of::()); assert!(PyNotImplemented::get_bound(py).is_exact_instance_of::()); }) } #[test] fn test_notimplemented_type_object_consistent() { Python::with_gil(|py| { assert!(PyNotImplemented::get_bound(py) .get_type() .is(&PyNotImplemented::type_object_bound(py))); }) } #[test] fn test_dict_is_not_notimplemented() { Python::with_gil(|py| { assert!(PyDict::new_bound(py) .downcast::() .is_err()); }) } } pyo3/src/types/mapping.rs0000644000175000017500000003474714661133735016406 0ustar jamespagejamespageuse crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::py_result_ext::PyResultExt; use crate::sync::GILOnceCell; use crate::type_object::PyTypeInfo; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyDict, PySequence, PyType}; #[cfg(feature = "gil-refs")] use crate::{err::PyDowncastError, PyNativeType}; use crate::{ffi, Py, PyTypeCheck, Python, ToPyObject}; /// Represents a reference to a Python object supporting the mapping protocol. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyMapping>`][Bound]. /// /// For APIs available on mapping objects, see the [`PyMappingMethods`] trait which is implemented for /// [`Bound<'py, PyMapping>`][Bound]. #[repr(transparent)] pub struct PyMapping(PyAny); pyobject_native_type_named!(PyMapping); pyobject_native_type_extract!(PyMapping); impl PyMapping { /// Register a pyclass as a subclass of `collections.abc.Mapping` (from the Python standard /// library). This is equivalent to `collections.abc.Mapping.register(T)` in Python. /// This registration is required for a pyclass to be downcastable from `PyAny` to `PyMapping`. pub fn register(py: Python<'_>) -> PyResult<()> { let ty = T::type_object_bound(py); get_mapping_abc(py)?.call_method1("register", (ty,))?; Ok(()) } } #[cfg(feature = "gil-refs")] impl PyMapping { /// Returns the number of objects in the mapping. /// /// This is equivalent to the Python expression `len(self)`. #[inline] pub fn len(&self) -> PyResult { self.as_borrowed().len() } /// Returns whether the mapping is empty. #[inline] pub fn is_empty(&self) -> PyResult { self.as_borrowed().is_empty() } /// Determines if the mapping contains the specified key. /// /// This is equivalent to the Python expression `key in self`. pub fn contains(&self, key: K) -> PyResult where K: ToPyObject, { self.as_borrowed().contains(key) } /// Gets the item in self with key `key`. /// /// Returns an `Err` if the item with specified key is not found, usually `KeyError`. /// /// This is equivalent to the Python expression `self[key]`. #[inline] pub fn get_item(&self, key: K) -> PyResult<&PyAny> where K: ToPyObject, { self.as_borrowed().get_item(key).map(Bound::into_gil_ref) } /// Sets the item in self with key `key`. /// /// This is equivalent to the Python expression `self[key] = value`. #[inline] pub fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject, { self.as_borrowed().set_item(key, value) } /// Deletes the item with key `key`. /// /// This is equivalent to the Python statement `del self[key]`. #[inline] pub fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject, { self.as_borrowed().del_item(key) } /// Returns a sequence containing all keys in the mapping. #[inline] pub fn keys(&self) -> PyResult<&PySequence> { self.as_borrowed().keys().map(Bound::into_gil_ref) } /// Returns a sequence containing all values in the mapping. #[inline] pub fn values(&self) -> PyResult<&PySequence> { self.as_borrowed().values().map(Bound::into_gil_ref) } /// Returns a sequence of tuples of all (key, value) pairs in the mapping. #[inline] pub fn items(&self) -> PyResult<&PySequence> { self.as_borrowed().items().map(Bound::into_gil_ref) } } /// Implementation of functionality for [`PyMapping`]. /// /// These methods are defined for the `Bound<'py, PyMapping>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyMapping")] pub trait PyMappingMethods<'py>: crate::sealed::Sealed { /// Returns the number of objects in the mapping. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> PyResult; /// Returns whether the mapping is empty. fn is_empty(&self) -> PyResult; /// Determines if the mapping contains the specified key. /// /// This is equivalent to the Python expression `key in self`. fn contains(&self, key: K) -> PyResult where K: ToPyObject; /// Gets the item in self with key `key`. /// /// Returns an `Err` if the item with specified key is not found, usually `KeyError`. /// /// This is equivalent to the Python expression `self[key]`. fn get_item(&self, key: K) -> PyResult> where K: ToPyObject; /// Sets the item in self with key `key`. /// /// This is equivalent to the Python expression `self[key] = value`. fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject; /// Deletes the item with key `key`. /// /// This is equivalent to the Python statement `del self[key]`. fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject; /// Returns a sequence containing all keys in the mapping. fn keys(&self) -> PyResult>; /// Returns a sequence containing all values in the mapping. fn values(&self) -> PyResult>; /// Returns a sequence of tuples of all (key, value) pairs in the mapping. fn items(&self) -> PyResult>; } impl<'py> PyMappingMethods<'py> for Bound<'py, PyMapping> { #[inline] fn len(&self) -> PyResult { let v = unsafe { ffi::PyMapping_Size(self.as_ptr()) }; crate::err::error_on_minusone(self.py(), v)?; Ok(v as usize) } #[inline] fn is_empty(&self) -> PyResult { self.len().map(|l| l == 0) } fn contains(&self, key: K) -> PyResult where K: ToPyObject, { PyAnyMethods::contains(&**self, key) } #[inline] fn get_item(&self, key: K) -> PyResult> where K: ToPyObject, { PyAnyMethods::get_item(&**self, key) } #[inline] fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject, { PyAnyMethods::set_item(&**self, key, value) } #[inline] fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject, { PyAnyMethods::del_item(&**self, key) } #[inline] fn keys(&self) -> PyResult> { unsafe { ffi::PyMapping_Keys(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn values(&self) -> PyResult> { unsafe { ffi::PyMapping_Values(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn items(&self) -> PyResult> { unsafe { ffi::PyMapping_Items(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } } fn get_mapping_abc(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> { static MAPPING_ABC: GILOnceCell> = GILOnceCell::new(); MAPPING_ABC.get_or_try_init_type_ref(py, "collections.abc", "Mapping") } impl PyTypeCheck for PyMapping { const NAME: &'static str = "Mapping"; #[inline] fn type_check(object: &Bound<'_, PyAny>) -> bool { // Using `is_instance` for `collections.abc.Mapping` is slow, so provide // optimized case dict as a well-known mapping PyDict::is_type_of_bound(object) || get_mapping_abc(object.py()) .and_then(|abc| object.is_instance(abc)) .unwrap_or_else(|err| { err.write_unraisable_bound(object.py(), Some(&object.as_borrowed())); false }) } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl<'v> crate::PyTryFrom<'v> for PyMapping { /// Downcasting to `PyMapping` requires the concrete class to be a subclass (or registered /// subclass) of `collections.abc.Mapping` (from the Python standard library) - i.e. /// `isinstance(, collections.abc.Mapping) == True`. fn try_from>(value: V) -> Result<&'v PyMapping, PyDowncastError<'v>> { let value = value.into(); if PyMapping::type_check(&value.as_borrowed()) { unsafe { return Ok(value.downcast_unchecked()) } } Err(PyDowncastError::new(value, "Mapping")) } #[inline] fn try_from_exact>(value: V) -> Result<&'v PyMapping, PyDowncastError<'v>> { value.into().downcast() } #[inline] unsafe fn try_from_unchecked>(value: V) -> &'v PyMapping { let ptr = value.into() as *const _ as *const PyMapping; &*ptr } } #[cfg(test)] mod tests { use std::collections::HashMap; use crate::{exceptions::PyKeyError, types::PyTuple}; use super::*; #[test] fn test_len() { Python::with_gil(|py| { let mut v = HashMap::new(); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); assert_eq!(0, mapping.len().unwrap()); assert!(mapping.is_empty().unwrap()); v.insert(7, 32); let ob = v.to_object(py); let mapping2 = ob.downcast_bound::(py).unwrap(); assert_eq!(1, mapping2.len().unwrap()); assert!(!mapping2.is_empty().unwrap()); }); } #[test] fn test_contains() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert("key0", 1234); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); mapping.set_item("key1", "foo").unwrap(); assert!(mapping.contains("key0").unwrap()); assert!(mapping.contains("key1").unwrap()); assert!(!mapping.contains("key2").unwrap()); }); } #[test] fn test_get_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); assert_eq!( 32, mapping.get_item(7i32).unwrap().extract::().unwrap() ); assert!(mapping .get_item(8i32) .unwrap_err() .is_instance_of::(py)); }); } #[test] fn test_set_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); assert!(mapping.set_item(7i32, 42i32).is_ok()); // change assert!(mapping.set_item(8i32, 123i32).is_ok()); // insert assert_eq!( 42i32, mapping.get_item(7i32).unwrap().extract::().unwrap() ); assert_eq!( 123i32, mapping.get_item(8i32).unwrap().extract::().unwrap() ); }); } #[test] fn test_del_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); assert!(mapping.del_item(7i32).is_ok()); assert_eq!(0, mapping.len().unwrap()); assert!(mapping .get_item(7i32) .unwrap_err() .is_instance_of::(py)); }); } #[test] fn test_items() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; let mut value_sum = 0; for el in mapping.items().unwrap().iter().unwrap() { let tuple = el.unwrap().downcast_into::().unwrap(); key_sum += tuple.get_item(0).unwrap().extract::().unwrap(); value_sum += tuple.get_item(1).unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_keys() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; for el in mapping.keys().unwrap().iter().unwrap() { key_sum += el.unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); }); } #[test] fn test_values() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let mapping = ob.downcast_bound::(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut values_sum = 0; for el in mapping.values().unwrap().iter().unwrap() { values_sum += el.unwrap().extract::().unwrap(); } assert_eq!(32 + 42 + 123, values_sum); }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_mapping_try_from() { use crate::PyTryFrom; Python::with_gil(|py| { let dict = PyDict::new(py); let _ = ::try_from(dict).unwrap(); let _ = PyMapping::try_from_exact(dict).unwrap(); }); } } pyo3/src/types/iterator.rs0000644000175000017500000002760614661133735016600 0ustar jamespagejamespageuse crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Borrowed; use crate::py_result_ext::PyResultExt; use crate::{ffi, Bound, PyAny, PyErr, PyResult, PyTypeCheck}; #[cfg(feature = "gil-refs")] use crate::{AsPyPointer, PyDowncastError, PyNativeType}; /// A Python iterator object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyIterator>`][Bound]. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let list = py.eval_bound("iter([1, 2, 3, 4])", None, None)?; /// let numbers: PyResult> = list /// .iter()? /// .map(|i| i.and_then(|i|i.extract::())) /// .collect(); /// let sum: usize = numbers?.iter().sum(); /// assert_eq!(sum, 10); /// Ok(()) /// }) /// # } /// ``` #[repr(transparent)] pub struct PyIterator(PyAny); pyobject_native_type_named!(PyIterator); pyobject_native_type_extract!(PyIterator); impl PyIterator { /// Deprecated form of `PyIterator::from_bound_object`. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyIterator::from_object` will be replaced by `PyIterator::from_bound_object` in a future PyO3 version" )] pub fn from_object(obj: &PyAny) -> PyResult<&PyIterator> { Self::from_bound_object(&obj.as_borrowed()).map(Bound::into_gil_ref) } /// Builds an iterator for an iterable Python object; the equivalent of calling `iter(obj)` in Python. /// /// Usually it is more convenient to write [`obj.iter()`][crate::types::any::PyAnyMethods::iter], /// which is a more concise way of calling this function. pub fn from_bound_object<'py>(obj: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyObject_GetIter(obj.as_ptr()) .assume_owned_or_err(obj.py()) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl<'p> Iterator for &'p PyIterator { type Item = PyResult<&'p PyAny>; /// Retrieves the next item from an iterator. /// /// Returns `None` when the iterator is exhausted. /// If an exception occurs, returns `Some(Err(..))`. /// Further `next()` calls after an exception occurs are likely /// to repeatedly result in the same exception. fn next(&mut self) -> Option { self.as_borrowed() .next() .map(|result| result.map(Bound::into_gil_ref)) } #[cfg(not(Py_LIMITED_API))] fn size_hint(&self) -> (usize, Option) { self.as_borrowed().size_hint() } } impl<'py> Iterator for Bound<'py, PyIterator> { type Item = PyResult>; /// Retrieves the next item from an iterator. /// /// Returns `None` when the iterator is exhausted. /// If an exception occurs, returns `Some(Err(..))`. /// Further `next()` calls after an exception occurs are likely /// to repeatedly result in the same exception. #[inline] fn next(&mut self) -> Option { Borrowed::from(&*self).next() } #[cfg(not(Py_LIMITED_API))] fn size_hint(&self) -> (usize, Option) { let hint = unsafe { ffi::PyObject_LengthHint(self.as_ptr(), 0) }; (hint.max(0) as usize, None) } } impl<'py> Borrowed<'_, 'py, PyIterator> { // TODO: this method is on Borrowed so that &'py PyIterator can use this; once that // implementation is deleted this method should be moved to the `Bound<'py, PyIterator> impl fn next(self) -> Option>> { let py = self.py(); match unsafe { ffi::PyIter_Next(self.as_ptr()).assume_owned_or_opt(py) } { Some(obj) => Some(Ok(obj)), None => PyErr::take(py).map(Err), } } } impl<'py> IntoIterator for &Bound<'py, PyIterator> { type Item = PyResult>; type IntoIter = Bound<'py, PyIterator>; fn into_iter(self) -> Self::IntoIter { self.clone() } } impl PyTypeCheck for PyIterator { const NAME: &'static str = "Iterator"; fn type_check(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyIter_Check(object.as_ptr()) != 0 } } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl<'v> crate::PyTryFrom<'v> for PyIterator { fn try_from>(value: V) -> Result<&'v PyIterator, PyDowncastError<'v>> { let value = value.into(); unsafe { if ffi::PyIter_Check(value.as_ptr()) != 0 { Ok(value.downcast_unchecked()) } else { Err(PyDowncastError::new(value, "Iterator")) } } } fn try_from_exact>(value: V) -> Result<&'v PyIterator, PyDowncastError<'v>> { value.into().downcast() } #[inline] unsafe fn try_from_unchecked>(value: V) -> &'v PyIterator { let ptr = value.into() as *const _ as *const PyIterator; &*ptr } } #[cfg(test)] mod tests { use super::PyIterator; use crate::exceptions::PyTypeError; use crate::types::{PyAnyMethods, PyDict, PyList, PyListMethods}; use crate::{Python, ToPyObject}; #[test] fn vec_iter() { Python::with_gil(|py| { let obj = vec![10, 20].to_object(py); let inst = obj.bind(py); let mut it = inst.iter().unwrap(); assert_eq!( 10_i32, it.next().unwrap().unwrap().extract::<'_, i32>().unwrap() ); assert_eq!( 20_i32, it.next().unwrap().unwrap().extract::<'_, i32>().unwrap() ); assert!(it.next().is_none()); }); } #[test] fn iter_refcnt() { let (obj, count) = Python::with_gil(|py| { let obj = vec![10, 20].to_object(py); let count = obj.get_refcnt(py); (obj, count) }); Python::with_gil(|py| { let inst = obj.bind(py); let mut it = inst.iter().unwrap(); assert_eq!( 10_i32, it.next().unwrap().unwrap().extract::<'_, i32>().unwrap() ); }); Python::with_gil(move |py| { assert_eq!(count, obj.get_refcnt(py)); }); } #[test] fn iter_item_refcnt() { Python::with_gil(|py| { let count; let obj = py.eval_bound("object()", None, None).unwrap(); let list = { let list = PyList::empty_bound(py); list.append(10).unwrap(); list.append(&obj).unwrap(); count = obj.get_refcnt(); list.to_object(py) }; { let inst = list.bind(py); let mut it = inst.iter().unwrap(); assert_eq!( 10_i32, it.next().unwrap().unwrap().extract::<'_, i32>().unwrap() ); assert!(it.next().unwrap().unwrap().is(&obj)); assert!(it.next().is_none()); } assert_eq!(count, obj.get_refcnt()); }); } #[test] fn fibonacci_generator() { let fibonacci_generator = r#" def fibonacci(target): a = 1 b = 1 for _ in range(target): yield a a, b = b, a + b "#; Python::with_gil(|py| { let context = PyDict::new_bound(py); py.run_bound(fibonacci_generator, None, Some(&context)) .unwrap(); let generator = py.eval_bound("fibonacci(5)", None, Some(&context)).unwrap(); for (actual, expected) in generator.iter().unwrap().zip(&[1, 1, 2, 3, 5]) { let actual = actual.unwrap().extract::().unwrap(); assert_eq!(actual, *expected) } }); } #[test] fn fibonacci_generator_bound() { use crate::types::any::PyAnyMethods; use crate::Bound; let fibonacci_generator = r#" def fibonacci(target): a = 1 b = 1 for _ in range(target): yield a a, b = b, a + b "#; Python::with_gil(|py| { let context = PyDict::new_bound(py); py.run_bound(fibonacci_generator, None, Some(&context)) .unwrap(); let generator: Bound<'_, PyIterator> = py .eval_bound("fibonacci(5)", None, Some(&context)) .unwrap() .downcast_into() .unwrap(); let mut items = vec![]; for actual in &generator { let actual = actual.unwrap().extract::().unwrap(); items.push(actual); } assert_eq!(items, [1, 1, 2, 3, 5]); }); } #[test] fn int_not_iterable() { Python::with_gil(|py| { let x = 5.to_object(py); let err = PyIterator::from_bound_object(x.bind(py)).unwrap_err(); assert!(err.is_instance_of::(py)); }); } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn iterator_try_from() { Python::with_gil(|py| { let obj: crate::Py = vec![10, 20].to_object(py).as_ref(py).iter().unwrap().into(); let iter = ::try_from(obj.as_ref(py)).unwrap(); assert!(obj.is(iter)); }); } #[test] #[cfg(feature = "macros")] fn python_class_not_iterator() { use crate::PyErr; #[crate::pyclass(crate = "crate")] struct Downcaster { failed: Option, } #[crate::pymethods(crate = "crate")] impl Downcaster { fn downcast_iterator(&mut self, obj: &crate::Bound<'_, crate::PyAny>) { self.failed = Some(obj.downcast::().unwrap_err().into()); } } // Regression test for 2913 Python::with_gil(|py| { let downcaster = crate::Py::new(py, Downcaster { failed: None }).unwrap(); crate::py_run!( py, downcaster, r#" from collections.abc import Sequence class MySequence(Sequence): def __init__(self): self._data = [1, 2, 3] def __getitem__(self, index): return self._data[index] def __len__(self): return len(self._data) downcaster.downcast_iterator(MySequence()) "# ); assert_eq!( downcaster.borrow_mut(py).failed.take().unwrap().to_string(), "TypeError: 'MySequence' object cannot be converted to 'Iterator'" ); }); } #[test] #[cfg(feature = "macros")] fn python_class_iterator() { #[crate::pyfunction(crate = "crate")] fn assert_iterator(obj: &crate::Bound<'_, crate::PyAny>) { assert!(obj.downcast::().is_ok()) } // Regression test for 2913 Python::with_gil(|py| { let assert_iterator = crate::wrap_pyfunction_bound!(assert_iterator, py).unwrap(); crate::py_run!( py, assert_iterator, r#" class MyIter: def __next__(self): raise StopIteration assert_iterator(MyIter()) "# ); }); } #[test] #[cfg(not(Py_LIMITED_API))] fn length_hint_becomes_size_hint_lower_bound() { Python::with_gil(|py| { let list = py.eval_bound("[1, 2, 3]", None, None).unwrap(); let iter = list.iter().unwrap(); let hint = iter.size_hint(); assert_eq!(hint, (3, None)); }); } } pyo3/src/types/datetime.rs0000644000175000017500000010003614661133735016530 0ustar jamespagejamespage//! Safe Rust wrappers for types defined in the Python `datetime` library //! //! For more details about these types, see the [Python //! documentation](https://docs.python.org/3/library/datetime.html) use crate::err::PyResult; use crate::ffi::{ self, PyDateTime_CAPI, PyDateTime_FromTimestamp, PyDateTime_IMPORT, PyDate_FromTimestamp, }; use crate::ffi::{ PyDateTime_DATE_GET_FOLD, PyDateTime_DATE_GET_HOUR, PyDateTime_DATE_GET_MICROSECOND, PyDateTime_DATE_GET_MINUTE, PyDateTime_DATE_GET_SECOND, }; #[cfg(GraalPy)] use crate::ffi::{PyDateTime_DATE_GET_TZINFO, PyDateTime_TIME_GET_TZINFO, Py_IsNone}; use crate::ffi::{ PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_MICROSECONDS, PyDateTime_DELTA_GET_SECONDS, }; use crate::ffi::{PyDateTime_GET_DAY, PyDateTime_GET_MONTH, PyDateTime_GET_YEAR}; use crate::ffi::{ PyDateTime_TIME_GET_FOLD, PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND, PyDateTime_TIME_GET_MINUTE, PyDateTime_TIME_GET_SECOND, }; use crate::ffi_ptr_ext::FfiPtrExt; #[cfg(feature = "gil-refs")] use crate::instance::PyNativeType; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::PyTuple; use crate::{Bound, IntoPy, Py, PyAny, PyErr, Python}; use std::os::raw::c_int; #[cfg(feature = "chrono")] use std::ptr; fn ensure_datetime_api(py: Python<'_>) -> PyResult<&'static PyDateTime_CAPI> { if let Some(api) = unsafe { pyo3_ffi::PyDateTimeAPI().as_ref() } { Ok(api) } else { unsafe { PyDateTime_IMPORT(); pyo3_ffi::PyDateTimeAPI().as_ref() } .ok_or_else(|| PyErr::fetch(py)) } } fn expect_datetime_api(py: Python<'_>) -> &'static PyDateTime_CAPI { ensure_datetime_api(py).expect("failed to import `datetime` C API") } // Type Check macros // // These are bindings around the C API typecheck macros, all of them return // `1` if True and `0` if False. In all type check macros, the argument (`op`) // must not be `NULL`. The implementations here all call ensure_datetime_api // to ensure that the PyDateTimeAPI is initialized before use // // // # Safety // // These functions must only be called when the GIL is held! macro_rules! ffi_fun_with_autoinit { ($(#[$outer:meta] unsafe fn $name: ident($arg: ident: *mut PyObject) -> $ret: ty;)*) => { $( #[$outer] #[allow(non_snake_case)] /// # Safety /// /// Must only be called while the GIL is held unsafe fn $name($arg: *mut crate::ffi::PyObject) -> $ret { let _ = ensure_datetime_api(Python::assume_gil_acquired()); crate::ffi::$name($arg) } )* }; } ffi_fun_with_autoinit! { /// Check if `op` is a `PyDateTimeAPI.DateType` or subtype. unsafe fn PyDate_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.DateTimeType` or subtype. unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.TimeType` or subtype. unsafe fn PyTime_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.DetaType` or subtype. unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int; /// Check if `op` is a `PyDateTimeAPI.TZInfoType` or subtype. unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int; } // Access traits /// Trait for accessing the date components of a struct containing a date. pub trait PyDateAccess { /// Returns the year, as a positive int. /// /// Implementations should conform to the upstream documentation: /// fn get_year(&self) -> i32; /// Returns the month, as an int from 1 through 12. /// /// Implementations should conform to the upstream documentation: /// fn get_month(&self) -> u8; /// Returns the day, as an int from 1 through 31. /// /// Implementations should conform to the upstream documentation: /// fn get_day(&self) -> u8; } /// Trait for accessing the components of a struct containing a timedelta. /// /// Note: These access the individual components of a (day, second, /// microsecond) representation of the delta, they are *not* intended as /// aliases for calculating the total duration in each of these units. pub trait PyDeltaAccess { /// Returns the number of days, as an int from -999999999 to 999999999. /// /// Implementations should conform to the upstream documentation: /// fn get_days(&self) -> i32; /// Returns the number of seconds, as an int from 0 through 86399. /// /// Implementations should conform to the upstream documentation: /// fn get_seconds(&self) -> i32; /// Returns the number of microseconds, as an int from 0 through 999999. /// /// Implementations should conform to the upstream documentation: /// fn get_microseconds(&self) -> i32; } /// Trait for accessing the time components of a struct containing a time. pub trait PyTimeAccess { /// Returns the hour, as an int from 0 through 23. /// /// Implementations should conform to the upstream documentation: /// fn get_hour(&self) -> u8; /// Returns the minute, as an int from 0 through 59. /// /// Implementations should conform to the upstream documentation: /// fn get_minute(&self) -> u8; /// Returns the second, as an int from 0 through 59. /// /// Implementations should conform to the upstream documentation: /// fn get_second(&self) -> u8; /// Returns the microsecond, as an int from 0 through 999999. /// /// Implementations should conform to the upstream documentation: /// fn get_microsecond(&self) -> u32; /// Returns whether this date is the later of two moments with the /// same representation, during a repeated interval. /// /// This typically occurs at the end of daylight savings time. Only valid if the /// represented time is ambiguous. /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail. fn get_fold(&self) -> bool; } /// Trait for accessing the components of a struct containing a tzinfo. pub trait PyTzInfoAccess<'py> { /// Deprecated form of `get_tzinfo_bound`. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`get_tzinfo` will be replaced by `get_tzinfo_bound` in a future PyO3 version" )] fn get_tzinfo(&self) -> Option<&'py PyTzInfo> { self.get_tzinfo_bound().map(Bound::into_gil_ref) } /// Returns the tzinfo (which may be None). /// /// Implementations should conform to the upstream documentation: /// /// fn get_tzinfo_bound(&self) -> Option>; } /// Bindings around `datetime.date`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyDate>`][Bound]. #[repr(transparent)] pub struct PyDate(PyAny); pyobject_native_type!( PyDate, crate::ffi::PyDateTime_Date, |py| expect_datetime_api(py).DateType, #module=Some("datetime"), #checkfunction=PyDate_Check ); impl PyDate { /// Deprecated form of [`PyDate::new_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyDate::new` will be replaced by `PyDate::new_bound` in a future PyO3 version" )] pub fn new(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<&PyDate> { Self::new_bound(py, year, month, day).map(Bound::into_gil_ref) } /// Creates a new `datetime.date`. pub fn new_bound(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult> { let api = ensure_datetime_api(py)?; unsafe { (api.Date_FromDate)(year, c_int::from(month), c_int::from(day), api.DateType) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Deprecated form of [`PyDate::from_timestamp_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyDate::from_timestamp` will be replaced by `PyDate::from_timestamp_bound` in a future PyO3 version" )] pub fn from_timestamp(py: Python<'_>, timestamp: i64) -> PyResult<&PyDate> { Self::from_timestamp_bound(py, timestamp).map(Bound::into_gil_ref) } /// Construct a `datetime.date` from a POSIX timestamp /// /// This is equivalent to `datetime.date.fromtimestamp` pub fn from_timestamp_bound(py: Python<'_>, timestamp: i64) -> PyResult> { let time_tuple = PyTuple::new_bound(py, [timestamp]); // safety ensure that the API is loaded let _api = ensure_datetime_api(py)?; unsafe { PyDate_FromTimestamp(time_tuple.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyDateAccess for PyDate { fn get_year(&self) -> i32 { self.as_borrowed().get_year() } fn get_month(&self) -> u8 { self.as_borrowed().get_month() } fn get_day(&self) -> u8 { self.as_borrowed().get_day() } } impl PyDateAccess for Bound<'_, PyDate> { fn get_year(&self) -> i32 { unsafe { PyDateTime_GET_YEAR(self.as_ptr()) } } fn get_month(&self) -> u8 { unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 } } fn get_day(&self) -> u8 { unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 } } } /// Bindings for `datetime.datetime`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyDateTime>`][Bound]. #[repr(transparent)] pub struct PyDateTime(PyAny); pyobject_native_type!( PyDateTime, crate::ffi::PyDateTime_DateTime, |py| expect_datetime_api(py).DateTimeType, #module=Some("datetime"), #checkfunction=PyDateTime_Check ); impl PyDateTime { /// Deprecated form of [`PyDateTime::new_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyDateTime::new` will be replaced by `PyDateTime::new_bound` in a future PyO3 version" )] #[allow(clippy::too_many_arguments)] pub fn new<'py>( py: Python<'py>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&'py PyTzInfo>, ) -> PyResult<&'py PyDateTime> { Self::new_bound( py, year, month, day, hour, minute, second, microsecond, tzinfo.map(PyTzInfo::as_borrowed).as_deref(), ) .map(Bound::into_gil_ref) } /// Creates a new `datetime.datetime` object. #[allow(clippy::too_many_arguments)] pub fn new_bound<'py>( py: Python<'py>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, ) -> PyResult> { let api = ensure_datetime_api(py)?; unsafe { (api.DateTime_FromDateAndTime)( year, c_int::from(month), c_int::from(day), c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), api.DateTimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Deprecated form of [`PyDateTime::new_bound_with_fold`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyDateTime::new_with_fold` will be replaced by `PyDateTime::new_bound_with_fold` in a future PyO3 version" )] #[allow(clippy::too_many_arguments)] pub fn new_with_fold<'py>( py: Python<'py>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&'py PyTzInfo>, fold: bool, ) -> PyResult<&'py PyDateTime> { Self::new_bound_with_fold( py, year, month, day, hour, minute, second, microsecond, tzinfo.map(PyTzInfo::as_borrowed).as_deref(), fold, ) .map(Bound::into_gil_ref) } /// Alternate constructor that takes a `fold` parameter. A `true` value for this parameter /// signifies this this datetime is the later of two moments with the same representation, /// during a repeated interval. /// /// This typically occurs at the end of daylight savings time. Only valid if the /// represented time is ambiguous. /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail. #[allow(clippy::too_many_arguments)] pub fn new_bound_with_fold<'py>( py: Python<'py>, year: i32, month: u8, day: u8, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, fold: bool, ) -> PyResult> { let api = ensure_datetime_api(py)?; unsafe { (api.DateTime_FromDateAndTimeAndFold)( year, c_int::from(month), c_int::from(day), c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), c_int::from(fold), api.DateTimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Deprecated form of [`PyDateTime::from_timestamp_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyDateTime::from_timestamp` will be replaced by `PyDateTime::from_timestamp_bound` in a future PyO3 version" )] pub fn from_timestamp<'py>( py: Python<'py>, timestamp: f64, tzinfo: Option<&'py PyTzInfo>, ) -> PyResult<&'py PyDateTime> { Self::from_timestamp_bound(py, timestamp, tzinfo.map(PyTzInfo::as_borrowed).as_deref()) .map(Bound::into_gil_ref) } /// Construct a `datetime` object from a POSIX timestamp /// /// This is equivalent to `datetime.datetime.fromtimestamp` pub fn from_timestamp_bound<'py>( py: Python<'py>, timestamp: f64, tzinfo: Option<&Bound<'py, PyTzInfo>>, ) -> PyResult> { let args = IntoPy::>::into_py((timestamp, tzinfo), py).into_bound(py); // safety ensure API is loaded let _api = ensure_datetime_api(py)?; unsafe { PyDateTime_FromTimestamp(args.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyDateAccess for PyDateTime { fn get_year(&self) -> i32 { self.as_borrowed().get_year() } fn get_month(&self) -> u8 { self.as_borrowed().get_month() } fn get_day(&self) -> u8 { self.as_borrowed().get_day() } } impl PyDateAccess for Bound<'_, PyDateTime> { fn get_year(&self) -> i32 { unsafe { PyDateTime_GET_YEAR(self.as_ptr()) } } fn get_month(&self) -> u8 { unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 } } fn get_day(&self) -> u8 { unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 } } } #[cfg(feature = "gil-refs")] impl PyTimeAccess for PyDateTime { fn get_hour(&self) -> u8 { self.as_borrowed().get_hour() } fn get_minute(&self) -> u8 { self.as_borrowed().get_minute() } fn get_second(&self) -> u8 { self.as_borrowed().get_second() } fn get_microsecond(&self) -> u32 { self.as_borrowed().get_microsecond() } fn get_fold(&self) -> bool { self.as_borrowed().get_fold() } } impl PyTimeAccess for Bound<'_, PyDateTime> { fn get_hour(&self) -> u8 { unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as u8 } } fn get_minute(&self) -> u8 { unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as u8 } } fn get_second(&self) -> u8 { unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as u8 } } fn get_microsecond(&self) -> u32 { unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 } } fn get_fold(&self) -> bool { unsafe { PyDateTime_DATE_GET_FOLD(self.as_ptr()) > 0 } } } #[cfg(feature = "gil-refs")] impl<'py> PyTzInfoAccess<'py> for &'py PyDateTime { fn get_tzinfo_bound(&self) -> Option> { self.as_borrowed().get_tzinfo_bound() } } impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyDateTime> { fn get_tzinfo_bound(&self) -> Option> { let ptr = self.as_ptr() as *mut ffi::PyDateTime_DateTime; #[cfg(not(GraalPy))] unsafe { if (*ptr).hastzinfo != 0 { Some( (*ptr) .tzinfo .assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } else { None } } #[cfg(GraalPy)] unsafe { let res = PyDateTime_DATE_GET_TZINFO(ptr as *mut ffi::PyObject); if Py_IsNone(res) == 1 { None } else { Some( res.assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } } } } /// Bindings for `datetime.time`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTime>`][Bound]. #[repr(transparent)] pub struct PyTime(PyAny); pyobject_native_type!( PyTime, crate::ffi::PyDateTime_Time, |py| expect_datetime_api(py).TimeType, #module=Some("datetime"), #checkfunction=PyTime_Check ); impl PyTime { /// Deprecated form of [`PyTime::new_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyTime::new` will be replaced by `PyTime::new_bound` in a future PyO3 version" )] pub fn new<'py>( py: Python<'py>, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&'py PyTzInfo>, ) -> PyResult<&'py PyTime> { Self::new_bound( py, hour, minute, second, microsecond, tzinfo.map(PyTzInfo::as_borrowed).as_deref(), ) .map(Bound::into_gil_ref) } /// Creates a new `datetime.time` object. pub fn new_bound<'py>( py: Python<'py>, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, ) -> PyResult> { let api = ensure_datetime_api(py)?; unsafe { (api.Time_FromTime)( c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), api.TimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Deprecated form of [`PyTime::new_bound_with_fold`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyTime::new_with_fold` will be replaced by `PyTime::new_bound_with_fold` in a future PyO3 version" )] pub fn new_with_fold<'py>( py: Python<'py>, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&'py PyTzInfo>, fold: bool, ) -> PyResult<&'py PyTime> { Self::new_bound_with_fold( py, hour, minute, second, microsecond, tzinfo.map(PyTzInfo::as_borrowed).as_deref(), fold, ) .map(Bound::into_gil_ref) } /// Alternate constructor that takes a `fold` argument. See [`PyDateTime::new_bound_with_fold`]. pub fn new_bound_with_fold<'py>( py: Python<'py>, hour: u8, minute: u8, second: u8, microsecond: u32, tzinfo: Option<&Bound<'py, PyTzInfo>>, fold: bool, ) -> PyResult> { let api = ensure_datetime_api(py)?; unsafe { (api.Time_FromTimeAndFold)( c_int::from(hour), c_int::from(minute), c_int::from(second), microsecond as c_int, opt_to_pyobj(tzinfo), fold as c_int, api.TimeType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyTimeAccess for PyTime { fn get_hour(&self) -> u8 { self.as_borrowed().get_hour() } fn get_minute(&self) -> u8 { self.as_borrowed().get_minute() } fn get_second(&self) -> u8 { self.as_borrowed().get_second() } fn get_microsecond(&self) -> u32 { self.as_borrowed().get_microsecond() } fn get_fold(&self) -> bool { self.as_borrowed().get_fold() } } impl PyTimeAccess for Bound<'_, PyTime> { fn get_hour(&self) -> u8 { unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as u8 } } fn get_minute(&self) -> u8 { unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as u8 } } fn get_second(&self) -> u8 { unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as u8 } } fn get_microsecond(&self) -> u32 { unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 } } fn get_fold(&self) -> bool { unsafe { PyDateTime_TIME_GET_FOLD(self.as_ptr()) != 0 } } } #[cfg(feature = "gil-refs")] impl<'py> PyTzInfoAccess<'py> for &'py PyTime { fn get_tzinfo_bound(&self) -> Option> { self.as_borrowed().get_tzinfo_bound() } } impl<'py> PyTzInfoAccess<'py> for Bound<'py, PyTime> { fn get_tzinfo_bound(&self) -> Option> { let ptr = self.as_ptr() as *mut ffi::PyDateTime_Time; #[cfg(not(GraalPy))] unsafe { if (*ptr).hastzinfo != 0 { Some( (*ptr) .tzinfo .assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } else { None } } #[cfg(GraalPy)] unsafe { let res = PyDateTime_TIME_GET_TZINFO(ptr as *mut ffi::PyObject); if Py_IsNone(res) == 1 { None } else { Some( res.assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked(), ) } } } } /// Bindings for `datetime.tzinfo`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyTzInfo>`][Bound]. /// /// This is an abstract base class and cannot be constructed directly. /// For concrete time zone implementations, see [`timezone_utc_bound`] and /// the [`zoneinfo` module](https://docs.python.org/3/library/zoneinfo.html). #[repr(transparent)] pub struct PyTzInfo(PyAny); pyobject_native_type!( PyTzInfo, crate::ffi::PyObject, |py| expect_datetime_api(py).TZInfoType, #module=Some("datetime"), #checkfunction=PyTZInfo_Check ); /// Deprecated form of [`timezone_utc_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`timezone_utc` will be replaced by `timezone_utc_bound` in a future PyO3 version" )] pub fn timezone_utc(py: Python<'_>) -> &PyTzInfo { timezone_utc_bound(py).into_gil_ref() } /// Equivalent to `datetime.timezone.utc` pub fn timezone_utc_bound(py: Python<'_>) -> Bound<'_, PyTzInfo> { // TODO: this _could_ have a borrowed form `timezone_utc_borrowed`, but that seems // like an edge case optimization and we'd prefer in PyO3 0.21 to use `Bound` as // much as possible unsafe { expect_datetime_api(py) .TimeZone_UTC .assume_borrowed(py) .to_owned() .downcast_into_unchecked() } } /// Equivalent to `datetime.timezone` constructor /// /// Only used internally #[cfg(feature = "chrono")] pub(crate) fn timezone_from_offset<'py>( offset: &Bound<'py, PyDelta>, ) -> PyResult> { let py = offset.py(); let api = ensure_datetime_api(py)?; unsafe { (api.TimeZone_FromTimeZone)(offset.as_ptr(), ptr::null_mut()) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Bindings for `datetime.timedelta`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyDelta>`][Bound]. #[repr(transparent)] pub struct PyDelta(PyAny); pyobject_native_type!( PyDelta, crate::ffi::PyDateTime_Delta, |py| expect_datetime_api(py).DeltaType, #module=Some("datetime"), #checkfunction=PyDelta_Check ); impl PyDelta { /// Deprecated form of [`PyDelta::new_bound`]. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyDelta::new` will be replaced by `PyDelta::new_bound` in a future PyO3 version" )] pub fn new( py: Python<'_>, days: i32, seconds: i32, microseconds: i32, normalize: bool, ) -> PyResult<&PyDelta> { Self::new_bound(py, days, seconds, microseconds, normalize).map(Bound::into_gil_ref) } /// Creates a new `timedelta`. pub fn new_bound( py: Python<'_>, days: i32, seconds: i32, microseconds: i32, normalize: bool, ) -> PyResult> { let api = ensure_datetime_api(py)?; unsafe { (api.Delta_FromDelta)( days as c_int, seconds as c_int, microseconds as c_int, normalize as c_int, api.DeltaType, ) .assume_owned_or_err(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyDeltaAccess for PyDelta { fn get_days(&self) -> i32 { self.as_borrowed().get_days() } fn get_seconds(&self) -> i32 { self.as_borrowed().get_seconds() } fn get_microseconds(&self) -> i32 { self.as_borrowed().get_microseconds() } } impl PyDeltaAccess for Bound<'_, PyDelta> { fn get_days(&self) -> i32 { unsafe { PyDateTime_DELTA_GET_DAYS(self.as_ptr()) } } fn get_seconds(&self) -> i32 { unsafe { PyDateTime_DELTA_GET_SECONDS(self.as_ptr()) } } fn get_microseconds(&self) -> i32 { unsafe { PyDateTime_DELTA_GET_MICROSECONDS(self.as_ptr()) } } } // Utility function which returns a borrowed reference to either // the underlying tzinfo or None. fn opt_to_pyobj(opt: Option<&Bound<'_, PyTzInfo>>) -> *mut ffi::PyObject { match opt { Some(tzi) => tzi.as_ptr(), None => unsafe { ffi::Py_None() }, } } #[cfg(test)] mod tests { use super::*; #[cfg(feature = "macros")] use crate::py_run; #[test] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_datetime_fromtimestamp() { Python::with_gil(|py| { let dt = PyDateTime::from_timestamp_bound(py, 100.0, None).unwrap(); py_run!( py, dt, "import datetime; assert dt == datetime.datetime.fromtimestamp(100)" ); let dt = PyDateTime::from_timestamp_bound(py, 100.0, Some(&timezone_utc_bound(py))).unwrap(); py_run!( py, dt, "import datetime; assert dt == datetime.datetime.fromtimestamp(100, datetime.timezone.utc)" ); }) } #[test] #[cfg(feature = "macros")] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_date_fromtimestamp() { Python::with_gil(|py| { let dt = PyDate::from_timestamp_bound(py, 100).unwrap(); py_run!( py, dt, "import datetime; assert dt == datetime.date.fromtimestamp(100)" ); }) } #[test] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_new_with_fold() { Python::with_gil(|py| { let a = PyDateTime::new_bound_with_fold(py, 2021, 1, 23, 20, 32, 40, 341516, None, false); let b = PyDateTime::new_bound_with_fold(py, 2021, 1, 23, 20, 32, 40, 341516, None, true); assert!(!a.unwrap().get_fold()); assert!(b.unwrap().get_fold()); }); } #[test] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_get_tzinfo() { crate::Python::with_gil(|py| { let utc = timezone_utc_bound(py); let dt = PyDateTime::new_bound(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap(); assert!(dt.get_tzinfo_bound().unwrap().eq(&utc).unwrap()); let dt = PyDateTime::new_bound(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap(); assert!(dt.get_tzinfo_bound().is_none()); let t = PyTime::new_bound(py, 0, 0, 0, 0, Some(&utc)).unwrap(); assert!(t.get_tzinfo_bound().unwrap().eq(utc).unwrap()); let t = PyTime::new_bound(py, 0, 0, 0, 0, None).unwrap(); assert!(t.get_tzinfo_bound().is_none()); }); } #[test] #[cfg(all(feature = "macros", feature = "chrono"))] #[cfg_attr(target_arch = "wasm32", ignore)] // DateTime import fails on wasm for mysterious reasons fn test_timezone_from_offset() { Python::with_gil(|py| { assert!( timezone_from_offset(&PyDelta::new_bound(py, 0, -3600, 0, true).unwrap()) .unwrap() .call_method1("utcoffset", ((),)) .unwrap() .downcast_into::() .unwrap() .eq(PyDelta::new_bound(py, 0, -3600, 0, true).unwrap()) .unwrap() ); assert!( timezone_from_offset(&PyDelta::new_bound(py, 0, 3600, 0, true).unwrap()) .unwrap() .call_method1("utcoffset", ((),)) .unwrap() .downcast_into::() .unwrap() .eq(PyDelta::new_bound(py, 0, 3600, 0, true).unwrap()) .unwrap() ); timezone_from_offset(&PyDelta::new_bound(py, 1, 0, 0, true).unwrap()).unwrap_err(); }) } } pyo3/src/types/weakref/0000775000175000017500000000000014661133735016014 5ustar jamespagejamespagepyo3/src/types/weakref/proxy.rs0000644000175000017500000016643414661133735017557 0ustar jamespagejamespageuse crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::type_object::PyTypeCheck; use crate::types::any::PyAny; use crate::{ffi, Borrowed, Bound, ToPyObject}; #[cfg(feature = "gil-refs")] use crate::{type_object::PyTypeInfo, PyNativeType}; use super::PyWeakrefMethods; /// Represents any Python `weakref` Proxy type. /// /// In Python this is created by calling `weakref.proxy`. /// This is either a `weakref.ProxyType` or a `weakref.CallableProxyType` (`weakref.ProxyTypes`). #[repr(transparent)] pub struct PyWeakrefProxy(PyAny); pyobject_native_type_named!(PyWeakrefProxy); pyobject_native_type_extract!(PyWeakrefProxy); // TODO: We known the layout but this cannot be implemented, due to the lack of public typeobject pointers. And it is 2 distinct types // #[cfg(not(Py_LIMITED_API))] // pyobject_native_type_sized!(PyWeakrefProxy, ffi::PyWeakReference); impl PyTypeCheck for PyWeakrefProxy { const NAME: &'static str = "weakref.ProxyTypes"; fn type_check(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyWeakref_CheckProxy(object.as_ptr()) > 0 } } } /// TODO: UPDATE DOCS impl PyWeakrefProxy { /// Constructs a new Weak Reference (`weakref.proxy`/`weakref.ProxyType`/`weakref.CallableProxyType`) for the given object. /// /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag). /// /// # Examples #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefProxy; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let foo = Bound::new(py, Foo {})?; /// let weakref = PyWeakrefProxy::new_bound(&foo)?; /// assert!( /// // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::` /// weakref.upgrade() /// .map_or(false, |obj| obj.is(&foo)) /// ); /// /// let weakref2 = PyWeakrefProxy::new_bound(&foo)?; /// assert!(weakref.is(&weakref2)); /// /// drop(foo); /// /// assert!(weakref.upgrade().is_none()); /// Ok(()) /// }) /// # } /// ``` #[inline] pub fn new_bound<'py>(object: &Bound<'py, PyAny>) -> PyResult> { // TODO: Is this inner pattern still necessary Here? fn inner<'py>(object: &Bound<'py, PyAny>) -> PyResult> { unsafe { Bound::from_owned_ptr_or_err( object.py(), ffi::PyWeakref_NewProxy(object.as_ptr(), ffi::Py_None()), ) .downcast_into_unchecked() } } inner(object) } /// Constructs a new Weak Reference (`weakref.proxy`/`weakref.ProxyType`/`weakref.CallableProxyType`) for the given object with a callback. /// /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag) or if the `callback` is not callable or None. /// /// # Examples #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefProxy; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pyfunction] /// fn callback(wref: Bound<'_, PyWeakrefProxy>) -> PyResult<()> { /// let py = wref.py(); /// assert!(wref.upgrade_as::()?.is_none()); /// py.run_bound("counter = 1", None, None) /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// py.run_bound("counter = 0", None, None)?; /// assert_eq!(py.eval_bound("counter", None, None)?.extract::()?, 0); /// let foo = Bound::new(py, Foo{})?; /// /// // This is fine. /// let weakref = PyWeakrefProxy::new_bound_with(&foo, py.None())?; /// assert!(weakref.upgrade_as::()?.is_some()); /// assert!( /// // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::` /// weakref.upgrade() /// .map_or(false, |obj| obj.is(&foo)) /// ); /// assert_eq!(py.eval_bound("counter", None, None)?.extract::()?, 0); /// /// let weakref2 = PyWeakrefProxy::new_bound_with(&foo, wrap_pyfunction_bound!(callback, py)?)?; /// assert!(!weakref.is(&weakref2)); // Not the same weakref /// assert!(weakref.eq(&weakref2)?); // But Equal, since they point to the same object /// /// drop(foo); /// /// assert!(weakref.upgrade_as::()?.is_none()); /// assert_eq!(py.eval_bound("counter", None, None)?.extract::()?, 1); /// Ok(()) /// }) /// # } /// ``` #[inline] pub fn new_bound_with<'py, C>( object: &Bound<'py, PyAny>, callback: C, ) -> PyResult> where C: ToPyObject, { fn inner<'py>( object: &Bound<'py, PyAny>, callback: Bound<'py, PyAny>, ) -> PyResult> { unsafe { Bound::from_owned_ptr_or_err( object.py(), ffi::PyWeakref_NewProxy(object.as_ptr(), callback.as_ptr()), ) .downcast_into_unchecked() } } let py = object.py(); inner(object, callback.to_object(py).into_bound(py)) } } /// TODO: UPDATE DOCS #[cfg(feature = "gil-refs")] impl PyWeakrefProxy { /// Deprecated form of [`PyWeakrefProxy::new_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyWeakrefProxy::new` will be replaced by `PyWeakrefProxy::new_bound` in a future PyO3 version" )] pub fn new(object: &T) -> PyResult<&PyWeakrefProxy> where T: PyNativeType, { Self::new_bound(object.as_borrowed().as_any()).map(Bound::into_gil_ref) } /// Deprecated form of [`PyWeakrefProxy::new_bound_with`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyWeakrefProxy::new_with` will be replaced by `PyWeakrefProxy::new_bound_with` in a future PyO3 version" )] pub fn new_with(object: &T, callback: C) -> PyResult<&PyWeakrefProxy> where T: PyNativeType, C: ToPyObject, { Self::new_bound_with(object.as_borrowed().as_any(), callback).map(Bound::into_gil_ref) } /// Upgrade the weakref to a direct object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefProxy; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefProxy>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefProxy::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ProxyType`]: https://docs.python.org/3/library/weakref.html#weakref.ProxyType /// [`weakref.proxy`]: https://docs.python.org/3/library/weakref.html#weakref.proxy pub fn upgrade_as(&self) -> PyResult> where T: PyTypeCheck, { Ok(self .as_borrowed() .upgrade_as::()? .map(Bound::into_gil_ref)) } /// Upgrade the weakref to a direct object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. /// The `weakref` is still allowed to be `None`, if the referenced object has been cleaned up. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefProxy; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefProxy>) -> String { /// if let Some(data_src) = unsafe { reference.upgrade_as_unchecked::() } { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// format!("Processing '{}': score = {}", name, score) /// } else { /// "The supplied data reference is nolonger relavent.".to_owned() /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefProxy::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ProxyType`]: https://docs.python.org/3/library/weakref.html#weakref.ProxyType /// [`weakref.proxy`]: https://docs.python.org/3/library/weakref.html#weakref.proxy pub unsafe fn upgrade_as_unchecked(&self) -> Option<&T::AsRefTarget> where T: PyTypeCheck, { self.as_borrowed() .upgrade_as_unchecked::() .map(Bound::into_gil_ref) } /// Upgrade the weakref to an exact direct object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefProxy; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefProxy>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as_exact::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefProxy::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ProxyType`]: https://docs.python.org/3/library/weakref.html#weakref.ProxyType /// [`weakref.proxy`]: https://docs.python.org/3/library/weakref.html#weakref.proxy pub fn upgrade_as_exact(&self) -> PyResult> where T: PyTypeInfo, { Ok(self .as_borrowed() .upgrade_as_exact::()? .map(Bound::into_gil_ref)) } /// Upgrade the weakref to a [`PyAny`] reference to the target if possible. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// This function returns `Some(&'py PyAny)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`weakref.ProxyType`] (or [`weakref.CallableProxyType`], result of calling [`weakref.proxy`]). /// It produces similair results using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefProxy; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefProxy>) -> PyResult { /// if let Some(object) = reference.upgrade() { /// Ok(format!("The object '{}' refered by this reference still exists.", object.getattr("__class__")?.getattr("__qualname__")?)) /// } else { /// Ok("The object, which this reference refered to, no longer exists".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefProxy::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object 'Foo' refered by this reference still exists." /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object, which this reference refered to, no longer exists" /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ProxyType`]: https://docs.python.org/3/library/weakref.html#weakref.ProxyType /// [`weakref.CallableProxyType`]: https://docs.python.org/3/library/weakref.html#weakref.CallableProxyType /// [`weakref.proxy`]: https://docs.python.org/3/library/weakref.html#weakref.proxy pub fn upgrade(&self) -> Option<&'_ PyAny> { self.as_borrowed().upgrade().map(Bound::into_gil_ref) } /// Retrieve to a object pointed to by the weakref. /// /// This function returns `&'py PyAny`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`weakref.ProxyType`] (or [`weakref.CallableProxyType`], result of calling [`weakref.proxy`]). /// It produces similair results using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefProxy; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn get_class(reference: Borrowed<'_, '_, PyWeakrefProxy>) -> PyResult { /// reference /// .get_object() /// .getattr("__class__")? /// .repr() /// .map(|repr| repr.to_string()) /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let object = Bound::new(py, Foo{})?; /// let reference = PyWeakrefProxy::new_bound(&object)?; /// /// assert_eq!( /// get_class(reference.as_borrowed())?, /// "" /// ); /// /// drop(object); /// /// assert_eq!(get_class(reference.as_borrowed())?, ""); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ProxyType`]: https://docs.python.org/3/library/weakref.html#weakref.ProxyType /// [`weakref.CallableProxyType`]: https://docs.python.org/3/library/weakref.html#weakref.CallableProxyType /// [`weakref.proxy`]: https://docs.python.org/3/library/weakref.html#weakref.proxy pub fn get_object(&self) -> &'_ PyAny { self.as_borrowed().get_object().into_gil_ref() } } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefProxy> { fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref.ProxyType' (or `weakref.CallableProxyType`) instance should be valid (non-null and actually a weakref reference)") } } #[cfg(test)] mod tests { use crate::exceptions::{PyAttributeError, PyReferenceError, PyTypeError}; use crate::types::any::{PyAny, PyAnyMethods}; use crate::types::weakref::{PyWeakrefMethods, PyWeakrefProxy}; use crate::{Bound, PyResult, Python}; #[cfg(all(Py_3_13, not(Py_LIMITED_API)))] const DEADREF_FIX: Option<&str> = None; #[cfg(all(not(Py_3_13), not(Py_LIMITED_API)))] const DEADREF_FIX: Option<&str> = Some("NoneType"); #[cfg(not(Py_LIMITED_API))] fn check_repr( reference: &Bound<'_, PyWeakrefProxy>, object: &Bound<'_, PyAny>, class: Option<&str>, ) -> PyResult<()> { let repr = reference.repr()?.to_string(); #[cfg(Py_3_13)] let (first_part, second_part) = repr.split_once(';').unwrap(); #[cfg(not(Py_3_13))] let (first_part, second_part) = repr.split_once(" to ").unwrap(); { let (msg, addr) = first_part.split_once("0x").unwrap(); assert_eq!(msg, ") -> PyResult> { py.run_bound("class A:\n pass\n", None, None)?; py.eval_bound("A", None, None).downcast_into::() } #[test] fn test_weakref_proxy_behavior() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(!reference.is(&object)); assert!(reference.get_object().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!( reference.get_type().to_string(), format!("", CLASS_NAME) ); assert_eq!( reference.getattr("__class__")?.to_string(), "" ); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, &object, Some("A"))?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert!(reference.call0().err().map_or(false, |err| { let result = err.is_instance_of::(py); #[cfg(not(Py_LIMITED_API))] let result = result & (err.value_bound(py).to_string() == format!("{} object is not callable", CLASS_NAME)); result })); drop(object); assert!(reference.get_object().is_none()); assert!(reference .getattr("__class__") .err() .map_or(false, |err| err.is_instance_of::(py))); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, py.None().bind(py), None)?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert!(reference.call0().err().map_or(false, |err| { let result = err.is_instance_of::(py); #[cfg(not(Py_LIMITED_API))] let result = result & (err.value_bound(py).to_string() == format!("{} object is not callable", CLASS_NAME)); result })); Ok(()) }) } #[test] fn test_weakref_upgrade_as() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade().is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.get_object().is(&object)); drop(object); assert!(reference.get_object().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. #[cfg(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))))] mod pyo3_pyclass { use super::*; use crate::{pyclass, Py}; #[pyclass(weakref, crate = "crate")] struct WeakrefablePyClass {} #[test] fn test_weakref_proxy_behavior() -> PyResult<()> { Python::with_gil(|py| { let object: Bound<'_, WeakrefablePyClass> = Bound::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(!reference.is(&object)); assert!(reference.get_object().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!( reference.get_type().to_string(), format!("", CLASS_NAME) ); assert_eq!( reference.getattr("__class__")?.to_string(), "" ); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, object.as_any(), Some("WeakrefablePyClass"))?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert!(reference.call0().err().map_or(false, |err| { let result = err.is_instance_of::(py); #[cfg(not(Py_LIMITED_API))] let result = result & (err.value_bound(py).to_string() == format!("{} object is not callable", CLASS_NAME)); result })); drop(object); assert!(reference.get_object().is_none()); assert!(reference .getattr("__class__") .err() .map_or(false, |err| err.is_instance_of::(py))); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, py.None().bind(py), None)?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert!(reference.call0().err().map_or(false, |err| { let result = err.is_instance_of::(py); #[cfg(not(Py_LIMITED_API))] let result = result & (err.value_bound(py).to_string() == format!("{} object is not callable", CLASS_NAME)); result })); Ok(()) }) } #[test] fn test_weakref_upgrade_as() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade().is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.get_object().is(&object)); drop(object); assert!(reference.get_object().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } } } mod callable_proxy { use super::*; #[cfg(all(not(Py_LIMITED_API), Py_3_10))] const CLASS_NAME: &str = ""; #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))] const CLASS_NAME: &str = ""; mod python_class { use super::*; use crate::{py_result_ext::PyResultExt, types::PyType}; fn get_type(py: Python<'_>) -> PyResult> { py.run_bound( "class A:\n def __call__(self):\n return 'This class is callable!'\n", None, None, )?; py.eval_bound("A", None, None).downcast_into::() } #[test] fn test_weakref_proxy_behavior() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(!reference.is(&object)); assert!(reference.get_object().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); assert_eq!( reference.getattr("__class__")?.to_string(), "" ); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, &object, Some("A"))?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert_eq!(reference.call0()?.to_string(), "This class is callable!"); drop(object); assert!(reference.get_object().is_none()); assert!(reference .getattr("__class__") .err() .map_or(false, |err| err.is_instance_of::(py))); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, py.None().bind(py), None)?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert!(reference .call0() .err() .map_or(false, |err| err.is_instance_of::(py) & (err.value_bound(py).to_string() == "weakly-referenced object no longer exists"))); Ok(()) }) } #[test] fn test_weakref_upgrade_as() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade().is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.get_object().is(&object)); drop(object); assert!(reference.get_object().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. #[cfg(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))))] mod pyo3_pyclass { use super::*; use crate::{pyclass, pymethods, Py}; #[pyclass(weakref, crate = "crate")] struct WeakrefablePyClass {} #[pymethods(crate = "crate")] impl WeakrefablePyClass { fn __call__(&self) -> &str { "This class is callable!" } } #[test] fn test_weakref_proxy_behavior() -> PyResult<()> { Python::with_gil(|py| { let object: Bound<'_, WeakrefablePyClass> = Bound::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(&object)?; assert!(!reference.is(&object)); assert!(reference.get_object().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); assert_eq!( reference.getattr("__class__")?.to_string(), "" ); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, object.as_any(), Some("WeakrefablePyClass"))?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert_eq!(reference.call0()?.to_string(), "This class is callable!"); drop(object); assert!(reference.get_object().is_none()); assert!(reference .getattr("__class__") .err() .map_or(false, |err| err.is_instance_of::(py))); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, py.None().bind(py), None)?; assert!(reference .getattr("__callback__") .err() .map_or(false, |err| err.is_instance_of::(py))); assert!(reference .call0() .err() .map_or(false, |err| err.is_instance_of::(py) & (err.value_bound(py).to_string() == "weakly-referenced object no longer exists"))); Ok(()) }) } #[test] fn test_weakref_upgrade_as() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade().is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.get_object().is(&object)); drop(object); assert!(reference.get_object().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefProxy::new_bound(object.bind(py))?; assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } } } } pyo3/src/types/weakref/mod.rs0000644000175000017500000000027514661133735017143 0ustar jamespagejamespagepub use anyref::{PyWeakref, PyWeakrefMethods}; pub use proxy::PyWeakrefProxy; pub use reference::PyWeakrefReference; pub(crate) mod anyref; pub(crate) mod proxy; pub(crate) mod reference; pyo3/src/types/weakref/anyref.rs0000644000175000017500000017305114661133735017653 0ustar jamespagejamespageuse crate::err::{DowncastError, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::type_object::{PyTypeCheck, PyTypeInfo}; use crate::types::any::{PyAny, PyAnyMethods}; use crate::{ffi, Borrowed, Bound}; #[cfg(feature = "gil-refs")] use crate::PyNativeType; /// Represents any Python `weakref` reference. /// /// In Python this is created by calling `weakref.ref` or `weakref.proxy`. #[repr(transparent)] pub struct PyWeakref(PyAny); pyobject_native_type_named!(PyWeakref); pyobject_native_type_extract!(PyWeakref); // TODO: We known the layout but this cannot be implemented, due to the lack of public typeobject pointers // #[cfg(not(Py_LIMITED_API))] // pyobject_native_type_sized!(PyWeakref, ffi::PyWeakReference); impl PyTypeCheck for PyWeakref { const NAME: &'static str = "weakref"; fn type_check(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyWeakref_Check(object.as_ptr()) > 0 } } } #[cfg(feature = "gil-refs")] impl PyWeakref { // TODO: MAYBE ADD CREATION METHODS OR EASY CASTING?; /// Upgrade the weakref to a direct object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`] or retrieving the Object from Python. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::{PyWeakref, PyWeakrefProxy}; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakref>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let proxy = PyWeakrefProxy::new_bound(&data)?; // Retrieve this as an PyMethods argument. /// let reference = proxy.downcast::()?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject pub fn upgrade_as(&self) -> PyResult> where T: PyTypeCheck, { Ok(self .as_borrowed() .upgrade_as::()? .map(Bound::into_gil_ref)) } /// Upgrade the weakref to a direct object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`] or retrieving the Object from Python. /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. /// The `weakref` is still allowed to be `None`, if the referenced object has been cleaned up. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::{PyWeakref, PyWeakrefProxy}; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakref>) -> String { /// if let Some(data_src) = unsafe { reference.upgrade_as_unchecked::() } { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// format!("Processing '{}': score = {}", name, score) /// } else { /// "The supplied data reference is nolonger relavent.".to_owned() /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let proxy = PyWeakrefProxy::new_bound(&data)?; // Retrieve this as an PyMethods argument. /// let reference = proxy.downcast::()?; /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject pub unsafe fn upgrade_as_unchecked(&self) -> Option<&T::AsRefTarget> where T: PyTypeCheck, { self.as_borrowed() .upgrade_as_unchecked::() .map(Bound::into_gil_ref) } /// Upgrade the weakref to an exact direct object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`] or retrieving the Object from Python. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::{PyWeakref, PyWeakrefProxy}; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakref>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as_exact::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let proxy = PyWeakrefProxy::new_bound(&data)?; // Retrieve this as an PyMethods argument. /// let reference = proxy.downcast::()?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject pub fn upgrade_as_exact(&self) -> PyResult> where T: PyTypeInfo, { Ok(self .as_borrowed() .upgrade_as_exact::()? .map(Bound::into_gil_ref)) } /// Upgrade the weakref to a [`PyAny`] reference to the target if possible. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// This function returns `Some(&'py PyAny)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`PyWeakref`] (Any Python `weakref` weakreference). /// It produces similair results as using [`PyWeakref_GetObject`] in the C api or retrieving the Object from Python. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::{PyWeakref, PyWeakrefProxy}; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakref>) -> PyResult { /// if let Some(object) = reference.upgrade() { /// Ok(format!("The object '{}' refered by this reference still exists.", object.getattr("__class__")?.getattr("__qualname__")?)) /// } else { /// Ok("The object, which this reference refered to, no longer exists".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let proxy = PyWeakrefProxy::new_bound(&data)?; // Retrieve this as an PyMethods argument. /// let reference = proxy.downcast::()?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object 'Foo' refered by this reference still exists." /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object, which this reference refered to, no longer exists" /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject pub fn upgrade(&self) -> Option<&'_ PyAny> { self.as_borrowed().upgrade().map(Bound::into_gil_ref) } /// Retrieve to a object pointed to by the weakref. /// /// This function returns `&'py PyAny`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`PyWeakref`] (Any Python `weakref` weakreference). /// It produces similair results as using [`PyWeakref_GetObject`] in the C api or retrieving the Object from Python. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::{PyWeakref, PyWeakrefProxy}; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn get_class(reference: Borrowed<'_, '_, PyWeakref>) -> PyResult { /// reference /// .get_object() /// .getattr("__class__")? /// .repr() /// .map(|repr| repr.to_string()) /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let object = Bound::new(py, Foo{})?; /// let proxy = PyWeakrefProxy::new_bound(&object)?; // Retrieve this as an PyMethods argument. /// let reference = proxy.downcast::()?; /// /// assert_eq!( /// get_class(reference.as_borrowed())?, /// "" /// ); /// /// drop(object); /// /// assert_eq!(get_class(reference.as_borrowed())?, ""); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject pub fn get_object(&self) -> &'_ PyAny { self.as_borrowed().get_object().into_gil_ref() } } /// Implementation of functionality for [`PyWeakref`]. /// /// These methods are defined for the `Bound<'py, PyWeakref>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyWeakref")] pub trait PyWeakrefMethods<'py> { /// Upgrade the weakref to a direct Bound object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref fn upgrade_as(&self) -> PyResult>> where T: PyTypeCheck, { self.upgrade() .map(Bound::downcast_into::) .transpose() .map_err(Into::into) } /// Upgrade the weakref to a Borrowed object reference. /// /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(data_src) = reference.upgrade_borrowed_as::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref? fn upgrade_borrowed_as<'a, T>(&'a self) -> PyResult>> where T: PyTypeCheck, 'py: 'a, { // TODO: Replace when Borrowed::downcast exists match self.upgrade_borrowed() { None => Ok(None), Some(object) if T::type_check(&object) => { Ok(Some(unsafe { object.downcast_unchecked() })) } Some(object) => Err(DowncastError::new(&object, T::NAME).into()), } } /// Upgrade the weakref to a direct Bound object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. /// The `weakref` is still allowed to be `None`, if the referenced object has been cleaned up. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> String { /// if let Some(data_src) = unsafe { reference.upgrade_as_unchecked::() } { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// format!("Processing '{}': score = {}", name, score) /// } else { /// "The supplied data reference is nolonger relavent.".to_owned() /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref unsafe fn upgrade_as_unchecked(&self) -> Option> { Some(self.upgrade()?.downcast_into_unchecked()) } /// Upgrade the weakref to a Borrowed object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. /// /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. /// The `weakref` is still allowed to be `None`, if the referenced object has been cleaned up. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> String { /// if let Some(data_src) = unsafe { reference.upgrade_borrowed_as_unchecked::() } { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// format!("Processing '{}': score = {}", name, score) /// } else { /// "The supplied data reference is nolonger relavent.".to_owned() /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref? unsafe fn upgrade_borrowed_as_unchecked<'a, T>(&'a self) -> Option> where 'py: 'a, { Some(self.upgrade_borrowed()?.downcast_unchecked()) } /// Upgrade the weakref to a exact direct Bound object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as_exact::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref fn upgrade_as_exact(&self) -> PyResult>> where T: PyTypeInfo, { self.upgrade() .map(Bound::downcast_into_exact) .transpose() .map_err(Into::into) } /// Upgrade the weakref to a exact Borrowed object reference. /// /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`]. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(data_src) = reference.upgrade_borrowed_as_exact::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref? fn upgrade_borrowed_as_exact<'a, T>(&'a self) -> PyResult>> where T: PyTypeInfo, 'py: 'a, { // TODO: Replace when Borrowed::downcast_exact exists match self.upgrade_borrowed() { None => Ok(None), Some(object) if object.is_exact_instance_of::() => { Ok(Some(unsafe { object.downcast_unchecked() })) } Some(object) => Err(DowncastError::new(&object, T::NAME).into()), } } /// Upgrade the weakref to a Bound [`PyAny`] reference to the target object if possible. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// This function returns `Some(Bound<'py, PyAny>)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(object) = reference.upgrade() { /// Ok(format!("The object '{}' refered by this reference still exists.", object.getattr("__class__")?.getattr("__qualname__")?)) /// } else { /// Ok("The object, which this reference refered to, no longer exists".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object 'Foo' refered by this reference still exists." /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object, which this reference refered to, no longer exists" /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref fn upgrade(&self) -> Option> { let object = self.get_object(); if object.is_none() { None } else { Some(object) } } /// Upgrade the weakref to a Borrowed [`PyAny`] reference to the target object if possible. /// /// It is named `upgrade_borrowed` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// This function returns `Some(Borrowed<'_, 'py, PyAny>)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(object) = reference.upgrade_borrowed() { /// Ok(format!("The object '{}' refered by this reference still exists.", object.getattr("__class__")?.getattr("__qualname__")?)) /// } else { /// Ok("The object, which this reference refered to, no longer exists".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object 'Foo' refered by this reference still exists." /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object, which this reference refered to, no longer exists" /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref fn upgrade_borrowed<'a>(&'a self) -> Option> where 'py: 'a, { let object = self.get_object_borrowed(); if object.is_none() { None } else { Some(object) } } /// Retrieve to a Bound object pointed to by the weakref. /// /// This function returns `Bound<'py, PyAny>`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn get_class(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// reference /// .get_object() /// .getattr("__class__")? /// .repr() /// .map(|repr| repr.to_string()) /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let object = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&object)?; /// /// assert_eq!( /// get_class(reference.as_borrowed())?, /// "" /// ); /// /// drop(object); /// /// assert_eq!(get_class(reference.as_borrowed())?, ""); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref fn get_object(&self) -> Bound<'py, PyAny> { // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. self.get_object_borrowed().to_owned() } /// Retrieve to a Borrowed object pointed to by the weakref. /// /// This function returns `Borrowed<'py, PyAny>`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// It produces similair results to using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn get_class(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// reference /// .get_object_borrowed() /// .getattr("__class__")? /// .repr() /// .map(|repr| repr.to_string()) /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let object = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&object)?; /// /// assert_eq!( /// get_class(reference.as_borrowed())?, /// "" /// ); /// /// drop(object); /// /// assert_eq!(get_class(reference.as_borrowed())?, ""); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref #[track_caller] // TODO: This function is the reason every function tracks caller, however it only panics when the weakref object is not actually a weakreference type. So is it this neccessary? fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny>; } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakref> { fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref' weak reference instance should be valid (non-null and actually a weakref reference)") } } #[cfg(test)] mod tests { use crate::types::any::{PyAny, PyAnyMethods}; use crate::types::weakref::{PyWeakref, PyWeakrefMethods, PyWeakrefProxy, PyWeakrefReference}; use crate::{Bound, PyResult, Python}; fn new_reference<'py>(object: &Bound<'py, PyAny>) -> PyResult> { let reference = PyWeakrefReference::new_bound(object)?; reference.into_any().downcast_into().map_err(Into::into) } fn new_proxy<'py>(object: &Bound<'py, PyAny>) -> PyResult> { let reference = PyWeakrefProxy::new_bound(object)?; reference.into_any().downcast_into().map_err(Into::into) } mod python_class { use super::*; use crate::{py_result_ext::PyResultExt, types::PyType}; fn get_type(py: Python<'_>) -> PyResult> { py.run_bound("class A:\n pass\n", None, None)?; py.eval_bound("A", None, None).downcast_into::() } #[test] fn test_weakref_upgrade_as() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.upgrade().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } #[test] fn test_weakref_get_object() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.get_object().is(&object)); drop(object); assert!(not_call_retrievable || reference.call0()?.is(&reference.get_object())); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.get_object().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = create_reference(&object)?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. #[cfg(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))))] mod pyo3_pyclass { use super::*; use crate::{pyclass, Py}; #[pyclass(weakref, crate = "crate")] struct WeakrefablePyClass {} #[test] fn test_weakref_upgrade_as() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, ) -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } inner(new_reference)?; inner(new_proxy) } #[test] fn test_weakref_upgrade() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.upgrade().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } #[test] fn test_weakref_get_object() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.get_object().is(&object)); drop(object); assert!(not_call_retrievable || reference.call0()?.is(&reference.get_object())); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.get_object().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { fn inner( create_reference: impl for<'py> FnOnce( &Bound<'py, PyAny>, ) -> PyResult>, call_retrievable: bool, ) -> PyResult<()> { let not_call_retrievable = !call_retrievable; Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = create_reference(object.bind(py))?; assert!(not_call_retrievable || reference.call0()?.is(&object)); assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(not_call_retrievable || reference.call0()?.is_none()); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } inner(new_reference, true)?; inner(new_proxy, false) } } } pyo3/src/types/weakref/reference.rs0000644000175000017500000011450414661133735020323 0ustar jamespagejamespageuse crate::err::PyResult; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAny; use crate::{ffi, Borrowed, Bound, ToPyObject}; #[cfg(any(any(PyPy, GraalPy, Py_LIMITED_API), feature = "gil-refs"))] use crate::type_object::PyTypeCheck; #[cfg(feature = "gil-refs")] use crate::{type_object::PyTypeInfo, PyNativeType}; use super::PyWeakrefMethods; /// Represents a Python `weakref.ReferenceType`. /// /// In Python this is created by calling `weakref.ref`. #[repr(transparent)] pub struct PyWeakrefReference(PyAny); #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] pyobject_native_type!( PyWeakrefReference, ffi::PyWeakReference, pyobject_native_static_type_object!(ffi::_PyWeakref_RefType), #module=Some("weakref"), #checkfunction=ffi::PyWeakref_CheckRefExact ); // When targetting alternative or multiple interpreters, it is better to not use the internal API. #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] pyobject_native_type_named!(PyWeakrefReference); #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] pyobject_native_type_extract!(PyWeakrefReference); #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] impl PyTypeCheck for PyWeakrefReference { const NAME: &'static str = "weakref.ReferenceType"; fn type_check(object: &Bound<'_, PyAny>) -> bool { unsafe { ffi::PyWeakref_CheckRef(object.as_ptr()) > 0 } } } impl PyWeakrefReference { /// Constructs a new Weak Reference (`weakref.ref`/`weakref.ReferenceType`) for the given object. /// /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag). /// /// # Examples #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let foo = Bound::new(py, Foo {})?; /// let weakref = PyWeakrefReference::new_bound(&foo)?; /// assert!( /// // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::` /// weakref.upgrade() /// .map_or(false, |obj| obj.is(&foo)) /// ); /// /// let weakref2 = PyWeakrefReference::new_bound(&foo)?; /// assert!(weakref.is(&weakref2)); /// /// drop(foo); /// /// assert!(weakref.upgrade().is_none()); /// Ok(()) /// }) /// # } /// ``` pub fn new_bound<'py>(object: &Bound<'py, PyAny>) -> PyResult> { // TODO: Is this inner pattern still necessary Here? fn inner<'py>(object: &Bound<'py, PyAny>) -> PyResult> { unsafe { Bound::from_owned_ptr_or_err( object.py(), ffi::PyWeakref_NewRef(object.as_ptr(), ffi::Py_None()), ) .downcast_into_unchecked() } } inner(object) } /// Constructs a new Weak Reference (`weakref.ref`/`weakref.ReferenceType`) for the given object with a callback. /// /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag) or if the `callback` is not callable or None. /// /// # Examples #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pyfunction] /// fn callback(wref: Bound<'_, PyWeakrefReference>) -> PyResult<()> { /// let py = wref.py(); /// assert!(wref.upgrade_as::()?.is_none()); /// py.run_bound("counter = 1", None, None) /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// py.run_bound("counter = 0", None, None)?; /// assert_eq!(py.eval_bound("counter", None, None)?.extract::()?, 0); /// let foo = Bound::new(py, Foo{})?; /// /// // This is fine. /// let weakref = PyWeakrefReference::new_bound_with(&foo, py.None())?; /// assert!(weakref.upgrade_as::()?.is_some()); /// assert!( /// // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::` /// weakref.upgrade() /// .map_or(false, |obj| obj.is(&foo)) /// ); /// assert_eq!(py.eval_bound("counter", None, None)?.extract::()?, 0); /// /// let weakref2 = PyWeakrefReference::new_bound_with(&foo, wrap_pyfunction_bound!(callback, py)?)?; /// assert!(!weakref.is(&weakref2)); // Not the same weakref /// assert!(weakref.eq(&weakref2)?); // But Equal, since they point to the same object /// /// drop(foo); /// /// assert!(weakref.upgrade_as::()?.is_none()); /// assert_eq!(py.eval_bound("counter", None, None)?.extract::()?, 1); /// Ok(()) /// }) /// # } /// ``` pub fn new_bound_with<'py, C>( object: &Bound<'py, PyAny>, callback: C, ) -> PyResult> where C: ToPyObject, { fn inner<'py>( object: &Bound<'py, PyAny>, callback: Bound<'py, PyAny>, ) -> PyResult> { unsafe { Bound::from_owned_ptr_or_err( object.py(), ffi::PyWeakref_NewRef(object.as_ptr(), callback.as_ptr()), ) .downcast_into_unchecked() } } let py = object.py(); inner(object, callback.to_object(py).into_bound(py)) } } #[cfg(feature = "gil-refs")] impl PyWeakrefReference { /// Deprecated form of [`PyWeakrefReference::new_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyWeakrefReference::new` will be replaced by `PyWeakrefReference::new_bound` in a future PyO3 version" )] pub fn new(object: &T) -> PyResult<&PyWeakrefReference> where T: PyNativeType, { Self::new_bound(object.as_borrowed().as_any()).map(Bound::into_gil_ref) } /// Deprecated form of [`PyWeakrefReference::new_bound_with`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyWeakrefReference::new_with` will be replaced by `PyWeakrefReference::new_bound_with` in a future PyO3 version" )] pub fn new_with(object: &T, callback: C) -> PyResult<&PyWeakrefReference> where T: PyNativeType, C: ToPyObject, { Self::new_bound_with(object.as_borrowed().as_any(), callback).map(Bound::into_gil_ref) } /// Upgrade the weakref to a direct object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`] or calling the [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref pub fn upgrade_as(&self) -> PyResult> where T: PyTypeCheck, { Ok(self .as_borrowed() .upgrade_as::()? .map(Bound::into_gil_ref)) } /// Upgrade the weakref to a direct object reference unchecked. The type of the recovered object is not checked before downcasting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`] or calling the [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// /// # Safety /// Callers must ensure that the type is valid or risk type confusion. /// The `weakref` is still allowed to be `None`, if the referenced object has been cleaned up. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> String { /// if let Some(data_src) = unsafe { reference.upgrade_as_unchecked::() } { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// format!("Processing '{}': score = {}", name, score) /// } else { /// "The supplied data reference is nolonger relavent.".to_owned() /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed()), /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref pub unsafe fn upgrade_as_unchecked(&self) -> Option<&T::AsRefTarget> where T: PyTypeCheck, { self.as_borrowed() .upgrade_as_unchecked::() .map(Bound::into_gil_ref) } /// Upgrade the weakref to an exact direct object reference. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// In Python it would be equivalent to [`PyWeakref_GetObject`] or calling the [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// #[pymethods] /// impl Foo { /// fn get_data(&self) -> (&str, u32) { /// ("Dave", 10) /// } /// } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(data_src) = reference.upgrade_as_exact::()? { /// let data = data_src.borrow(); /// let (name, score) = data.get_data(); /// Ok(format!("Processing '{}': score = {}", name, score)) /// } else { /// Ok("The supplied data reference is nolonger relavent.".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "Processing 'Dave': score = 10" /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The supplied data reference is nolonger relavent." /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref pub fn upgrade_as_exact(&self) -> PyResult> where T: PyTypeInfo, { Ok(self .as_borrowed() .upgrade_as_exact::()? .map(Bound::into_gil_ref)) } /// Upgrade the weakref to a [`PyAny`] reference to the target if possible. /// /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade). /// This function returns `Some(&'py PyAny)` if the reference still exists, otherwise `None` will be returned. /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// It produces similair results to calling the `weakref.ReferenceType` or using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// if let Some(object) = reference.upgrade() { /// Ok(format!("The object '{}' refered by this reference still exists.", object.getattr("__class__")?.getattr("__qualname__")?)) /// } else { /// Ok("The object, which this reference refered to, no longer exists".to_owned()) /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let data = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&data)?; /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object 'Foo' refered by this reference still exists." /// ); /// /// drop(data); /// /// assert_eq!( /// parse_data(reference.as_borrowed())?, /// "The object, which this reference refered to, no longer exists" /// ); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref pub fn upgrade(&self) -> Option<&'_ PyAny> { self.as_borrowed().upgrade().map(Bound::into_gil_ref) } /// Retrieve to a object pointed to by the weakref. /// /// This function returns `&'py PyAny`, which is either the object if it still exists, otherwise it will refer to [`PyNone`](crate::types::PyNone). /// /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]). /// It produces similair results to calling the `weakref.ReferenceType` or using [`PyWeakref_GetObject`] in the C api. /// /// # Example #[cfg_attr( not(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9))))), doc = "```rust,ignore" )] #[cfg_attr( all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))), doc = "```rust" )] /// use pyo3::prelude::*; /// use pyo3::types::PyWeakrefReference; /// /// #[pyclass(weakref)] /// struct Foo { /* fields omitted */ } /// /// fn get_class(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult { /// reference /// .get_object() /// .getattr("__class__")? /// .repr() /// .map(|repr| repr.to_string()) /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let object = Bound::new(py, Foo{})?; /// let reference = PyWeakrefReference::new_bound(&object)?; /// /// assert_eq!( /// get_class(reference.as_borrowed())?, /// "" /// ); /// /// drop(object); /// /// assert_eq!(get_class(reference.as_borrowed())?, ""); /// /// Ok(()) /// }) /// # } /// ``` /// /// # Panics /// This function panics is the current object is invalid. /// If used propperly this is never the case. (NonNull and actually a weakref type) /// /// [`PyWeakref_GetObject`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetObject /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref pub fn get_object(&self) -> &'_ PyAny { self.as_borrowed().get_object().into_gil_ref() } } impl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefReference> { fn get_object_borrowed(&self) -> Borrowed<'_, 'py, PyAny> { // PyWeakref_GetObject does some error checking, however we ensure the passed object is Non-Null and a Weakref type. unsafe { ffi::PyWeakref_GetObject(self.as_ptr()).assume_borrowed_or_err(self.py()) } .expect("The 'weakref.ReferenceType' instance should be valid (non-null and actually a weakref reference)") } } #[cfg(test)] mod tests { use crate::types::any::{PyAny, PyAnyMethods}; use crate::types::weakref::{PyWeakrefMethods, PyWeakrefReference}; use crate::{Bound, PyResult, Python}; #[cfg(all(not(Py_LIMITED_API), Py_3_10))] const CLASS_NAME: &str = ""; #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))] const CLASS_NAME: &str = ""; fn check_repr( reference: &Bound<'_, PyWeakrefReference>, object: Option<(&Bound<'_, PyAny>, &str)>, ) -> PyResult<()> { let repr = reference.repr()?.to_string(); let (first_part, second_part) = repr.split_once("; ").unwrap(); { let (msg, addr) = first_part.split_once("0x").unwrap(); assert_eq!(msg, " { let (msg, addr) = second_part.split_once("0x").unwrap(); // Avoid testing on reprs directly since they the quoting and full path vs class name tends to be changedi undocumented. assert!(msg.starts_with("to '")); assert!(msg.contains(class)); assert!(msg.ends_with("' at ")); assert!(addr .to_lowercase() .contains(format!("{:x?}", object.as_ptr()).split_at(2).1)); } None => { assert_eq!(second_part, "dead>") } } Ok(()) } mod python_class { use super::*; use crate::{py_result_ext::PyResultExt, types::PyType}; fn get_type(py: Python<'_>) -> PyResult> { py.run_bound("class A:\n pass\n", None, None)?; py.eval_bound("A", None, None).downcast_into::() } #[test] fn test_weakref_reference_behavior() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; assert!(!reference.is(&object)); assert!(reference.get_object().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.getattr("__class__")?.to_string(), CLASS_NAME); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, Some((object.as_any(), "A")))?; assert!(reference .getattr("__callback__") .map_or(false, |result| result.is_none())); assert!(reference.call0()?.is(&object)); drop(object); assert!(reference.get_object().is_none()); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.getattr("__class__")?.to_string(), CLASS_NAME); check_repr(&reference, None)?; assert!(reference .getattr("__callback__") .map_or(false, |result| result.is_none())); assert!(reference.call0()?.is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_as() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr() && obj.is_exact_instance(&class))); } drop(object); { // This test is a bit weird but ok. let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; assert!(reference.call0()?.is(&object)); assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.call0()?.is_none()); assert!(reference.upgrade().is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; assert!(reference.call0()?.is(&object)); assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.call0()?.is_none()); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; assert!(reference.call0()?.is(&object)); assert!(reference.get_object().is(&object)); drop(object); assert!(reference.call0()?.is(&reference.get_object())); assert!(reference.call0()?.is_none()); assert!(reference.get_object().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { Python::with_gil(|py| { let class = get_type(py)?; let object = class.call0()?; let reference = PyWeakrefReference::new_bound(&object)?; assert!(reference.call0()?.is(&object)); assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(reference.call0()?.is_none()); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } } // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable. #[cfg(all(feature = "macros", not(all(Py_LIMITED_API, not(Py_3_9)))))] mod pyo3_pyclass { use super::*; use crate::{pyclass, Py}; #[pyclass(weakref, crate = "crate")] struct WeakrefablePyClass {} #[test] fn test_weakref_reference_behavior() -> PyResult<()> { Python::with_gil(|py| { let object: Bound<'_, WeakrefablePyClass> = Bound::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(&object)?; assert!(!reference.is(&object)); assert!(reference.get_object().is(&object)); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.get_type().to_string(), CLASS_NAME); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.getattr("__class__")?.to_string(), CLASS_NAME); #[cfg(not(Py_LIMITED_API))] check_repr(&reference, Some((object.as_any(), "WeakrefablePyClass")))?; assert!(reference .getattr("__callback__") .map_or(false, |result| result.is_none())); assert!(reference.call0()?.is(&object)); drop(object); assert!(reference.get_object().is_none()); #[cfg(not(Py_LIMITED_API))] assert_eq!(reference.getattr("__class__")?.to_string(), CLASS_NAME); check_repr(&reference, None)?; assert!(reference .getattr("__callback__") .map_or(false, |result| result.is_none())); assert!(reference.call0()?.is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_as() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = reference.upgrade_borrowed_as::(); assert!(obj.is_ok()); let obj = obj.unwrap(); assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed_as_unchecked() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_some()); assert!(obj.map_or(false, |obj| obj.as_ptr() == object.as_ptr())); } drop(object); { let obj = unsafe { reference.upgrade_borrowed_as_unchecked::() }; assert!(obj.is_none()); } Ok(()) }) } #[test] fn test_weakref_upgrade() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; assert!(reference.call0()?.is(&object)); assert!(reference.upgrade().is_some()); assert!(reference.upgrade().map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.call0()?.is_none()); assert!(reference.upgrade().is_none()); Ok(()) }) } #[test] fn test_weakref_upgrade_borrowed() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; assert!(reference.call0()?.is(&object)); assert!(reference.upgrade_borrowed().is_some()); assert!(reference .upgrade_borrowed() .map_or(false, |obj| obj.is(&object))); drop(object); assert!(reference.call0()?.is_none()); assert!(reference.upgrade_borrowed().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; assert!(reference.call0()?.is(&object)); assert!(reference.get_object().is(&object)); drop(object); assert!(reference.call0()?.is(&reference.get_object())); assert!(reference.call0()?.is_none()); assert!(reference.get_object().is_none()); Ok(()) }) } #[test] fn test_weakref_get_object_borrowed() -> PyResult<()> { Python::with_gil(|py| { let object = Py::new(py, WeakrefablePyClass {})?; let reference = PyWeakrefReference::new_bound(object.bind(py))?; assert!(reference.call0()?.is(&object)); assert!(reference.get_object_borrowed().is(&object)); drop(object); assert!(reference.call0()?.is_none()); assert!(reference.get_object_borrowed().is_none()); Ok(()) }) } } } pyo3/src/types/mod.rs0000644000175000017500000003374114661133735015523 0ustar jamespagejamespage//! Various types defined by the Python interpreter such as `int`, `str` and `tuple`. pub use self::any::{PyAny, PyAnyMethods}; pub use self::boolobject::{PyBool, PyBoolMethods}; pub use self::bytearray::{PyByteArray, PyByteArrayMethods}; pub use self::bytes::{PyBytes, PyBytesMethods}; pub use self::capsule::{PyCapsule, PyCapsuleMethods}; #[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] pub use self::code::PyCode; pub use self::complex::{PyComplex, PyComplexMethods}; #[allow(deprecated)] #[cfg(all(not(Py_LIMITED_API), feature = "gil-refs"))] pub use self::datetime::timezone_utc; #[cfg(not(Py_LIMITED_API))] pub use self::datetime::{ timezone_utc_bound, PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTzInfo, PyTzInfoAccess, }; pub use self::dict::{IntoPyDict, PyDict, PyDictMethods}; #[cfg(not(any(PyPy, GraalPy)))] pub use self::dict::{PyDictItems, PyDictKeys, PyDictValues}; pub use self::ellipsis::PyEllipsis; pub use self::float::{PyFloat, PyFloatMethods}; #[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] pub use self::frame::PyFrame; pub use self::frozenset::{PyFrozenSet, PyFrozenSetBuilder, PyFrozenSetMethods}; pub use self::function::PyCFunction; #[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] pub use self::function::PyFunction; pub use self::iterator::PyIterator; pub use self::list::{PyList, PyListMethods}; pub use self::mapping::{PyMapping, PyMappingMethods}; pub use self::memoryview::PyMemoryView; pub use self::module::{PyModule, PyModuleMethods}; pub use self::none::PyNone; pub use self::notimplemented::PyNotImplemented; pub use self::num::PyLong; pub use self::num::PyLong as PyInt; #[cfg(not(any(PyPy, GraalPy)))] pub use self::pysuper::PySuper; pub use self::sequence::{PySequence, PySequenceMethods}; pub use self::set::{PySet, PySetMethods}; pub use self::slice::{PySlice, PySliceIndices, PySliceMethods}; #[cfg(not(Py_LIMITED_API))] pub use self::string::PyStringData; pub use self::string::{PyString, PyString as PyUnicode, PyStringMethods}; pub use self::traceback::{PyTraceback, PyTracebackMethods}; pub use self::tuple::{PyTuple, PyTupleMethods}; pub use self::typeobject::{PyType, PyTypeMethods}; pub use self::weakref::{PyWeakref, PyWeakrefMethods, PyWeakrefProxy, PyWeakrefReference}; /// Iteration over Python collections. /// /// When working with a Python collection, one approach is to convert it to a Rust collection such /// as `Vec` or `HashMap`. However this is a relatively expensive operation. If you just want to /// visit all their items, consider iterating over the collections directly: /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// # pub fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let dict = py.eval_bound("{'a':'b', 'c':'d'}", None, None)?.downcast_into::()?; /// /// for (key, value) in &dict { /// println!("key: {}, value: {}", key, value); /// } /// /// Ok(()) /// }) /// # } /// ``` /// /// If PyO3 detects that the collection is mutated during iteration, it will panic. /// /// These iterators use Python's C-API directly. However in certain cases, like when compiling for /// the Limited API and PyPy, the underlying structures are opaque and that may not be possible. /// In these cases the iterators are implemented by forwarding to [`PyIterator`]. pub mod iter { pub use super::dict::BoundDictIterator; pub use super::frozenset::BoundFrozenSetIterator; pub use super::list::BoundListIterator; pub use super::set::BoundSetIterator; pub use super::tuple::{BorrowedTupleIterator, BoundTupleIterator}; #[cfg(feature = "gil-refs")] pub use super::{ dict::PyDictIterator, frozenset::PyFrozenSetIterator, list::PyListIterator, set::PySetIterator, tuple::PyTupleIterator, }; } /// Python objects that have a base type. /// /// This marks types that can be upcast into a [`PyAny`] and used in its place. /// This essentially includes every Python object except [`PyAny`] itself. /// /// This is used to provide the [`Deref>`](std::ops::Deref) /// implementations for [`Bound<'_, T>`](crate::Bound). /// /// Users should not need to implement this trait directly. It's implementation /// is provided by the [`#[pyclass]`](macro@crate::pyclass) attribute. /// /// ## Note /// This is needed because the compiler currently tries to figure out all the /// types in a deref-chain before starting to look for applicable method calls. /// So we need to prevent [`Bound<'_, PyAny`](crate::Bound) dereferencing to /// itself in order to avoid running into the recursion limit. This trait is /// used to exclude this from our blanket implementation. See [this Rust /// issue][1] for more details. If the compiler limitation gets resolved, this /// trait will be removed. /// /// [1]: https://github.com/rust-lang/rust/issues/19509 pub trait DerefToPyAny { // Empty. } // Implementations core to all native types #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type_base( ($name:ty $(;$generics:ident)* ) => { #[cfg(feature = "gil-refs")] unsafe impl<$($generics,)*> $crate::PyNativeType for $name { type AsRefSource = Self; } #[cfg(feature = "gil-refs")] impl<$($generics,)*> ::std::fmt::Debug for $name { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> { use $crate::{PyNativeType, types::{PyAnyMethods, PyStringMethods}}; let s = self.as_borrowed().repr().or(::std::result::Result::Err(::std::fmt::Error))?; f.write_str(&s.to_string_lossy()) } } #[cfg(feature = "gil-refs")] impl<$($generics,)*> ::std::fmt::Display for $name { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> { use $crate::{PyNativeType, types::{PyAnyMethods, PyStringMethods, PyTypeMethods}}; match self.as_borrowed().str() { ::std::result::Result::Ok(s) => return f.write_str(&s.to_string_lossy()), ::std::result::Result::Err(err) => err.write_unraisable_bound(self.py(), ::std::option::Option::Some(&self.as_borrowed())), } match self.as_borrowed().get_type().name() { ::std::result::Result::Ok(name) => ::std::write!(f, "", name), ::std::result::Result::Err(_err) => f.write_str(""), } } } #[cfg(feature = "gil-refs")] impl<$($generics,)*> $crate::ToPyObject for $name { #[inline] fn to_object(&self, py: $crate::Python<'_>) -> $crate::PyObject { unsafe { $crate::PyObject::from_borrowed_ptr(py, self.as_ptr()) } } } }; ); // Implementations core to all native types except for PyAny (because they don't // make sense on PyAny / have different implementations). #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type_named ( ($name:ty $(;$generics:ident)*) => { $crate::pyobject_native_type_base!($name $(;$generics)*); impl<$($generics,)*> ::std::convert::AsRef<$crate::PyAny> for $name { #[inline] fn as_ref(&self) -> &$crate::PyAny { &self.0 } } impl<$($generics,)*> ::std::ops::Deref for $name { type Target = $crate::PyAny; #[inline] fn deref(&self) -> &$crate::PyAny { &self.0 } } unsafe impl<$($generics,)*> $crate::AsPyPointer for $name { /// Gets the underlying FFI pointer, returns a borrowed pointer. #[inline] fn as_ptr(&self) -> *mut $crate::ffi::PyObject { self.0.as_ptr() } } // FIXME https://github.com/PyO3/pyo3/issues/3903 #[allow(unknown_lints, non_local_definitions)] #[cfg(feature = "gil-refs")] impl<$($generics,)*> $crate::IntoPy<$crate::Py<$name>> for &'_ $name { #[inline] fn into_py(self, py: $crate::Python<'_>) -> $crate::Py<$name> { unsafe { $crate::Py::from_borrowed_ptr(py, self.as_ptr()) } } } // FIXME https://github.com/PyO3/pyo3/issues/3903 #[allow(unknown_lints, non_local_definitions)] #[cfg(feature = "gil-refs")] impl<$($generics,)*> ::std::convert::From<&'_ $name> for $crate::Py<$name> { #[inline] fn from(other: &$name) -> Self { use $crate::PyNativeType; unsafe { $crate::Py::from_borrowed_ptr(other.py(), other.as_ptr()) } } } // FIXME https://github.com/PyO3/pyo3/issues/3903 #[allow(unknown_lints, non_local_definitions)] #[cfg(feature = "gil-refs")] impl<'a, $($generics,)*> ::std::convert::From<&'a $name> for &'a $crate::PyAny { fn from(ob: &'a $name) -> Self { unsafe{&*(ob as *const $name as *const $crate::PyAny)} } } impl $crate::types::DerefToPyAny for $name {} }; ); #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_static_type_object( ($typeobject:expr) => { |_py| unsafe { ::std::ptr::addr_of_mut!($typeobject) } }; ); #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type_info( ($name:ty, $typeobject:expr, $module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => { unsafe impl<$($generics,)*> $crate::type_object::PyTypeInfo for $name { const NAME: &'static str = stringify!($name); const MODULE: ::std::option::Option<&'static str> = $module; #[inline] #[allow(clippy::redundant_closure_call)] fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { $typeobject(py) } $( #[inline] fn is_type_of_bound(obj: &$crate::Bound<'_, $crate::PyAny>) -> bool { #[allow(unused_unsafe)] unsafe { $checkfunction(obj.as_ptr()) > 0 } } )? } impl $name { #[doc(hidden)] pub const _PYO3_DEF: $crate::impl_::pymodule::AddTypeToModule = $crate::impl_::pymodule::AddTypeToModule::new(); } }; ); // NOTE: This macro is not included in pyobject_native_type_base! // because rust-numpy has a special implementation. #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type_extract { ($name:ty $(;$generics:ident)*) => { // FIXME https://github.com/PyO3/pyo3/issues/3903 #[allow(unknown_lints, non_local_definitions)] #[cfg(feature = "gil-refs")] impl<'py, $($generics,)*> $crate::FromPyObject<'py> for &'py $name { #[inline] fn extract_bound(obj: &$crate::Bound<'py, $crate::PyAny>) -> $crate::PyResult { ::std::clone::Clone::clone(obj).into_gil_ref().downcast().map_err(::std::convert::Into::into) } } } } /// Declares all of the boilerplate for Python types. #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type_core { ($name:ty, $typeobject:expr, #module=$module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => { $crate::pyobject_native_type_named!($name $(;$generics)*); $crate::pyobject_native_type_info!($name, $typeobject, $module $(, #checkfunction=$checkfunction)? $(;$generics)*); $crate::pyobject_native_type_extract!($name $(;$generics)*); }; ($name:ty, $typeobject:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => { $crate::pyobject_native_type_core!($name, $typeobject, #module=::std::option::Option::Some("builtins") $(, #checkfunction=$checkfunction)? $(;$generics)*); }; } #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type_sized { ($name:ty, $layout:path $(;$generics:ident)*) => { unsafe impl $crate::type_object::PyLayout<$name> for $layout {} impl $crate::type_object::PySizedLayout<$name> for $layout {} impl<$($generics,)*> $crate::impl_::pyclass::PyClassBaseType for $name { type LayoutAsBase = $crate::impl_::pycell::PyClassObjectBase<$layout>; type BaseNativeType = $name; type Initializer = $crate::pyclass_init::PyNativeTypeInitializer; type PyClassMutability = $crate::pycell::impl_::ImmutableClass; } } } /// Declares all of the boilerplate for Python types which can be inherited from (because the exact /// Python layout is known). #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type { ($name:ty, $layout:path, $typeobject:expr $(, #module=$module:expr)? $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => { $crate::pyobject_native_type_core!($name, $typeobject $(, #module=$module)? $(, #checkfunction=$checkfunction)? $(;$generics)*); // To prevent inheriting native types with ABI3 #[cfg(not(Py_LIMITED_API))] $crate::pyobject_native_type_sized!($name, $layout $(;$generics)*); }; } pub(crate) mod any; pub(crate) mod boolobject; pub(crate) mod bytearray; pub(crate) mod bytes; pub(crate) mod capsule; #[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] mod code; pub(crate) mod complex; #[cfg(not(Py_LIMITED_API))] pub(crate) mod datetime; pub(crate) mod dict; mod ellipsis; pub(crate) mod float; #[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))] mod frame; pub(crate) mod frozenset; mod function; pub(crate) mod iterator; pub(crate) mod list; pub(crate) mod mapping; mod memoryview; pub(crate) mod module; mod none; mod notimplemented; mod num; #[cfg(not(any(PyPy, GraalPy)))] mod pysuper; pub(crate) mod sequence; pub(crate) mod set; pub(crate) mod slice; pub(crate) mod string; pub(crate) mod traceback; pub(crate) mod tuple; pub(crate) mod typeobject; pub(crate) mod weakref; pyo3/src/types/bytearray.rs0000644000175000017500000005505314661133735016746 0ustar jamespagejamespageuse crate::err::{PyErr, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::{Borrowed, Bound}; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::{ffi, PyAny, Python}; #[cfg(feature = "gil-refs")] use crate::{AsPyPointer, PyNativeType}; use std::slice; /// Represents a Python `bytearray`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyByteArray>`][Bound]. /// /// For APIs available on `bytearray` objects, see the [`PyByteArrayMethods`] trait which is implemented for /// [`Bound<'py, PyByteArray>`][Bound]. #[repr(transparent)] pub struct PyByteArray(PyAny); pyobject_native_type_core!(PyByteArray, pyobject_native_static_type_object!(ffi::PyByteArray_Type), #checkfunction=ffi::PyByteArray_Check); impl PyByteArray { /// Creates a new Python bytearray object. /// /// The byte string is initialized by copying the data from the `&[u8]`. pub fn new_bound<'py>(py: Python<'py>, src: &[u8]) -> Bound<'py, PyByteArray> { let ptr = src.as_ptr().cast(); let len = src.len() as ffi::Py_ssize_t; unsafe { ffi::PyByteArray_FromStringAndSize(ptr, len) .assume_owned(py) .downcast_into_unchecked() } } /// Creates a new Python `bytearray` object with an `init` closure to write its contents. /// Before calling `init` the bytearray is zero-initialised. /// * If Python raises a MemoryError on the allocation, `new_with` will return /// it inside `Err`. /// * If `init` returns `Err(e)`, `new_with` will return `Err(e)`. /// * If `init` returns `Ok(())`, `new_with` will return `Ok(&PyByteArray)`. /// /// # Examples /// /// ``` /// use pyo3::{prelude::*, types::PyByteArray}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let py_bytearray = PyByteArray::new_bound_with(py, 10, |bytes: &mut [u8]| { /// bytes.copy_from_slice(b"Hello Rust"); /// Ok(()) /// })?; /// let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() }; /// assert_eq!(bytearray, b"Hello Rust"); /// Ok(()) /// }) /// # } /// ``` pub fn new_bound_with( py: Python<'_>, len: usize, init: F, ) -> PyResult> where F: FnOnce(&mut [u8]) -> PyResult<()>, { unsafe { // Allocate buffer and check for an error let pybytearray: Bound<'_, Self> = ffi::PyByteArray_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t) .assume_owned_or_err(py)? .downcast_into_unchecked(); let buffer: *mut u8 = ffi::PyByteArray_AsString(pybytearray.as_ptr()).cast(); debug_assert!(!buffer.is_null()); // Zero-initialise the uninitialised bytearray std::ptr::write_bytes(buffer, 0u8, len); // (Further) Initialise the bytearray in init // If init returns an Err, pypybytearray will automatically deallocate the buffer init(std::slice::from_raw_parts_mut(buffer, len)).map(|_| pybytearray) } } /// Creates a new Python `bytearray` object from another Python object that /// implements the buffer protocol. pub fn from_bound<'py>(src: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyByteArray_FromObject(src.as_ptr()) .assume_owned_or_err(src.py()) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyByteArray { /// Deprecated form of [`PyByteArray::new_bound`] #[deprecated( since = "0.21.0", note = "`PyByteArray::new` will be replaced by `PyByteArray::new_bound` in a future PyO3 version" )] pub fn new<'py>(py: Python<'py>, src: &[u8]) -> &'py PyByteArray { Self::new_bound(py, src).into_gil_ref() } /// Deprecated form of [`PyByteArray::new_bound_with`] #[deprecated( since = "0.21.0", note = "`PyByteArray::new_with` will be replaced by `PyByteArray::new_bound_with` in a future PyO3 version" )] pub fn new_with(py: Python<'_>, len: usize, init: F) -> PyResult<&PyByteArray> where F: FnOnce(&mut [u8]) -> PyResult<()>, { Self::new_bound_with(py, len, init).map(Bound::into_gil_ref) } /// Deprecated form of [`PyByteArray::from_bound`] #[deprecated( since = "0.21.0", note = "`PyByteArray::from` will be replaced by `PyByteArray::from_bound` in a future PyO3 version" )] pub fn from(src: &PyAny) -> PyResult<&PyByteArray> { PyByteArray::from_bound(&src.as_borrowed()).map(Bound::into_gil_ref) } /// Gets the length of the bytearray. #[inline] pub fn len(&self) -> usize { self.as_borrowed().len() } /// Checks if the bytearray is empty. pub fn is_empty(&self) -> bool { self.as_borrowed().is_empty() } /// Gets the start of the buffer containing the contents of the bytearray. /// /// # Safety /// /// See the safety requirements of [`PyByteArray::as_bytes`] and [`PyByteArray::as_bytes_mut`]. pub fn data(&self) -> *mut u8 { self.as_borrowed().data() } /// Extracts a slice of the `ByteArray`'s entire buffer. /// /// # Safety /// /// Mutation of the `bytearray` invalidates the slice. If it is used afterwards, the behavior is /// undefined. /// /// These mutations may occur in Python code as well as from Rust: /// - Calling methods like [`PyByteArray::as_bytes_mut`] and [`PyByteArray::resize`] will /// invalidate the slice. /// - Actions like dropping objects or raising exceptions can invoke `__del__`methods or signal /// handlers, which may execute arbitrary Python code. This means that if Python code has a /// reference to the `bytearray` you cannot safely use the vast majority of PyO3's API whilst /// using the slice. /// /// As a result, this slice should only be used for short-lived operations without executing any /// Python code, such as copying into a Vec. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::exceptions::PyRuntimeError; /// use pyo3::types::PyByteArray; /// /// #[pyfunction] /// fn a_valid_function(bytes: &Bound<'_, PyByteArray>) -> PyResult<()> { /// let section = { /// // SAFETY: We promise to not let the interpreter regain control /// // or invoke any PyO3 APIs while using the slice. /// let slice = unsafe { bytes.as_bytes() }; /// /// // Copy only a section of `bytes` while avoiding /// // `to_vec` which copies the entire thing. /// let section = slice /// .get(6..11) /// .ok_or_else(|| PyRuntimeError::new_err("input is not long enough"))?; /// Vec::from(section) /// }; /// /// // Now we can do things with `section` and call PyO3 APIs again. /// // ... /// # assert_eq!(§ion, b"world"); /// /// Ok(()) /// } /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction_bound!(a_valid_function, py)?; /// # let locals = pyo3::types::PyDict::new_bound(py); /// # locals.set_item("a_valid_function", fun)?; /// # /// # py.run_bound( /// # r#"b = bytearray(b"hello world") /// # a_valid_function(b) /// # /// # try: /// # a_valid_function(bytearray()) /// # except RuntimeError as e: /// # assert str(e) == 'input is not long enough'"#, /// # None, /// # Some(&locals), /// # )?; /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// # Incorrect usage /// /// The following `bug` function is unsound ⚠️ /// /// ```rust,no_run /// # use pyo3::prelude::*; /// # use pyo3::types::PyByteArray; /// /// # #[allow(dead_code)] /// #[pyfunction] /// fn bug(py: Python<'_>, bytes: &Bound<'_, PyByteArray>) { /// let slice = unsafe { bytes.as_bytes() }; /// /// // This explicitly yields control back to the Python interpreter... /// // ...but it's not always this obvious. Many things do this implicitly. /// py.allow_threads(|| { /// // Python code could be mutating through its handle to `bytes`, /// // which makes reading it a data race, which is undefined behavior. /// println!("{:?}", slice[0]); /// }); /// /// // Python code might have mutated it, so we can not rely on the slice /// // remaining valid. As such this is also undefined behavior. /// println!("{:?}", slice[0]); /// } /// ``` pub unsafe fn as_bytes(&self) -> &[u8] { self.as_borrowed().as_bytes() } /// Extracts a mutable slice of the `ByteArray`'s entire buffer. /// /// # Safety /// /// Any other accesses of the `bytearray`'s buffer invalidate the slice. If it is used /// afterwards, the behavior is undefined. The safety requirements of [`PyByteArray::as_bytes`] /// apply to this function as well. #[allow(clippy::mut_from_ref)] pub unsafe fn as_bytes_mut(&self) -> &mut [u8] { self.as_borrowed().as_bytes_mut() } /// Copies the contents of the bytearray to a Rust vector. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::types::PyByteArray; /// # Python::with_gil(|py| { /// let bytearray = PyByteArray::new_bound(py, b"Hello World."); /// let mut copied_message = bytearray.to_vec(); /// assert_eq!(b"Hello World.", copied_message.as_slice()); /// /// copied_message[11] = b'!'; /// assert_eq!(b"Hello World!", copied_message.as_slice()); /// /// pyo3::py_run!(py, bytearray, "assert bytearray == b'Hello World.'"); /// # }); /// ``` pub fn to_vec(&self) -> Vec { self.as_borrowed().to_vec() } /// Resizes the bytearray object to the new length `len`. /// /// Note that this will invalidate any pointers obtained by [PyByteArray::data], as well as /// any (unsafe) slices obtained from [PyByteArray::as_bytes] and [PyByteArray::as_bytes_mut]. pub fn resize(&self, len: usize) -> PyResult<()> { self.as_borrowed().resize(len) } } /// Implementation of functionality for [`PyByteArray`]. /// /// These methods are defined for the `Bound<'py, PyByteArray>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyByteArray")] pub trait PyByteArrayMethods<'py>: crate::sealed::Sealed { /// Gets the length of the bytearray. fn len(&self) -> usize; /// Checks if the bytearray is empty. fn is_empty(&self) -> bool; /// Gets the start of the buffer containing the contents of the bytearray. /// /// # Safety /// /// See the safety requirements of [`PyByteArrayMethods::as_bytes`] and [`PyByteArrayMethods::as_bytes_mut`]. fn data(&self) -> *mut u8; /// Extracts a slice of the `ByteArray`'s entire buffer. /// /// # Safety /// /// Mutation of the `bytearray` invalidates the slice. If it is used afterwards, the behavior is /// undefined. /// /// These mutations may occur in Python code as well as from Rust: /// - Calling methods like [`PyByteArrayMethods::as_bytes_mut`] and [`PyByteArrayMethods::resize`] will /// invalidate the slice. /// - Actions like dropping objects or raising exceptions can invoke `__del__`methods or signal /// handlers, which may execute arbitrary Python code. This means that if Python code has a /// reference to the `bytearray` you cannot safely use the vast majority of PyO3's API whilst /// using the slice. /// /// As a result, this slice should only be used for short-lived operations without executing any /// Python code, such as copying into a Vec. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::exceptions::PyRuntimeError; /// use pyo3::types::PyByteArray; /// /// #[pyfunction] /// fn a_valid_function(bytes: &Bound<'_, PyByteArray>) -> PyResult<()> { /// let section = { /// // SAFETY: We promise to not let the interpreter regain control /// // or invoke any PyO3 APIs while using the slice. /// let slice = unsafe { bytes.as_bytes() }; /// /// // Copy only a section of `bytes` while avoiding /// // `to_vec` which copies the entire thing. /// let section = slice /// .get(6..11) /// .ok_or_else(|| PyRuntimeError::new_err("input is not long enough"))?; /// Vec::from(section) /// }; /// /// // Now we can do things with `section` and call PyO3 APIs again. /// // ... /// # assert_eq!(§ion, b"world"); /// /// Ok(()) /// } /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = wrap_pyfunction_bound!(a_valid_function, py)?; /// # let locals = pyo3::types::PyDict::new_bound(py); /// # locals.set_item("a_valid_function", fun)?; /// # /// # py.run_bound( /// # r#"b = bytearray(b"hello world") /// # a_valid_function(b) /// # /// # try: /// # a_valid_function(bytearray()) /// # except RuntimeError as e: /// # assert str(e) == 'input is not long enough'"#, /// # None, /// # Some(&locals), /// # )?; /// # /// # Ok(()) /// # }) /// # } /// ``` /// /// # Incorrect usage /// /// The following `bug` function is unsound ⚠️ /// /// ```rust,no_run /// # use pyo3::prelude::*; /// # use pyo3::types::PyByteArray; /// /// # #[allow(dead_code)] /// #[pyfunction] /// fn bug(py: Python<'_>, bytes: &Bound<'_, PyByteArray>) { /// let slice = unsafe { bytes.as_bytes() }; /// /// // This explicitly yields control back to the Python interpreter... /// // ...but it's not always this obvious. Many things do this implicitly. /// py.allow_threads(|| { /// // Python code could be mutating through its handle to `bytes`, /// // which makes reading it a data race, which is undefined behavior. /// println!("{:?}", slice[0]); /// }); /// /// // Python code might have mutated it, so we can not rely on the slice /// // remaining valid. As such this is also undefined behavior. /// println!("{:?}", slice[0]); /// } /// ``` unsafe fn as_bytes(&self) -> &[u8]; /// Extracts a mutable slice of the `ByteArray`'s entire buffer. /// /// # Safety /// /// Any other accesses of the `bytearray`'s buffer invalidate the slice. If it is used /// afterwards, the behavior is undefined. The safety requirements of [`PyByteArrayMethods::as_bytes`] /// apply to this function as well. #[allow(clippy::mut_from_ref)] unsafe fn as_bytes_mut(&self) -> &mut [u8]; /// Copies the contents of the bytearray to a Rust vector. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::types::PyByteArray; /// # Python::with_gil(|py| { /// let bytearray = PyByteArray::new_bound(py, b"Hello World."); /// let mut copied_message = bytearray.to_vec(); /// assert_eq!(b"Hello World.", copied_message.as_slice()); /// /// copied_message[11] = b'!'; /// assert_eq!(b"Hello World!", copied_message.as_slice()); /// /// pyo3::py_run!(py, bytearray, "assert bytearray == b'Hello World.'"); /// # }); /// ``` fn to_vec(&self) -> Vec; /// Resizes the bytearray object to the new length `len`. /// /// Note that this will invalidate any pointers obtained by [PyByteArrayMethods::data], as well as /// any (unsafe) slices obtained from [PyByteArrayMethods::as_bytes] and [PyByteArrayMethods::as_bytes_mut]. fn resize(&self, len: usize) -> PyResult<()>; } impl<'py> PyByteArrayMethods<'py> for Bound<'py, PyByteArray> { #[inline] fn len(&self) -> usize { // non-negative Py_ssize_t should always fit into Rust usize unsafe { ffi::PyByteArray_Size(self.as_ptr()) as usize } } fn is_empty(&self) -> bool { self.len() == 0 } fn data(&self) -> *mut u8 { self.as_borrowed().data() } unsafe fn as_bytes(&self) -> &[u8] { self.as_borrowed().as_bytes() } #[allow(clippy::mut_from_ref)] unsafe fn as_bytes_mut(&self) -> &mut [u8] { self.as_borrowed().as_bytes_mut() } fn to_vec(&self) -> Vec { unsafe { self.as_bytes() }.to_vec() } fn resize(&self, len: usize) -> PyResult<()> { unsafe { let result = ffi::PyByteArray_Resize(self.as_ptr(), len as ffi::Py_ssize_t); if result == 0 { Ok(()) } else { Err(PyErr::fetch(self.py())) } } } } impl<'a> Borrowed<'a, '_, PyByteArray> { fn data(&self) -> *mut u8 { unsafe { ffi::PyByteArray_AsString(self.as_ptr()).cast() } } #[allow(clippy::wrong_self_convention)] unsafe fn as_bytes(self) -> &'a [u8] { slice::from_raw_parts(self.data(), self.len()) } #[allow(clippy::wrong_self_convention)] unsafe fn as_bytes_mut(self) -> &'a mut [u8] { slice::from_raw_parts_mut(self.data(), self.len()) } } #[cfg(feature = "gil-refs")] impl<'py> TryFrom<&'py PyAny> for &'py PyByteArray { type Error = crate::PyErr; /// Creates a new Python `bytearray` object from another Python object that /// implements the buffer protocol. fn try_from(value: &'py PyAny) -> Result { PyByteArray::from_bound(&value.as_borrowed()).map(Bound::into_gil_ref) } } impl<'py> TryFrom<&Bound<'py, PyAny>> for Bound<'py, PyByteArray> { type Error = crate::PyErr; /// Creates a new Python `bytearray` object from another Python object that /// implements the buffer protocol. fn try_from(value: &Bound<'py, PyAny>) -> Result { PyByteArray::from_bound(value) } } #[cfg(test)] mod tests { use crate::types::{PyAnyMethods, PyByteArray, PyByteArrayMethods}; use crate::{exceptions, Bound, PyAny, PyObject, Python}; #[test] fn test_len() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new_bound(py, src); assert_eq!(src.len(), bytearray.len()); }); } #[test] fn test_as_bytes() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new_bound(py, src); let slice = unsafe { bytearray.as_bytes() }; assert_eq!(src, slice); assert_eq!(bytearray.data() as *const _, slice.as_ptr()); }); } #[test] fn test_as_bytes_mut() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new_bound(py, src); let slice = unsafe { bytearray.as_bytes_mut() }; assert_eq!(src, slice); assert_eq!(bytearray.data(), slice.as_mut_ptr()); slice[0..5].copy_from_slice(b"Hi..."); assert_eq!(bytearray.str().unwrap(), "bytearray(b'Hi... Python')"); }); } #[test] fn test_to_vec() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new_bound(py, src); let vec = bytearray.to_vec(); assert_eq!(src, vec.as_slice()); }); } #[test] fn test_from() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new_bound(py, src); let ba: PyObject = bytearray.into(); let bytearray = PyByteArray::from_bound(ba.bind(py)).unwrap(); assert_eq!(src, unsafe { bytearray.as_bytes() }); }); } #[test] fn test_from_err() { Python::with_gil(|py| { if let Err(err) = PyByteArray::from_bound(py.None().bind(py)) { assert!(err.is_instance_of::(py)); } else { panic!("error"); } }); } #[test] fn test_try_from() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray: &Bound<'_, PyAny> = &PyByteArray::new_bound(py, src); let bytearray: Bound<'_, PyByteArray> = TryInto::try_into(bytearray).unwrap(); assert_eq!(src, unsafe { bytearray.as_bytes() }); }); } #[test] fn test_resize() { Python::with_gil(|py| { let src = b"Hello Python"; let bytearray = PyByteArray::new_bound(py, src); bytearray.resize(20).unwrap(); assert_eq!(20, bytearray.len()); }); } #[test] fn test_byte_array_new_with() -> super::PyResult<()> { Python::with_gil(|py| -> super::PyResult<()> { let py_bytearray = PyByteArray::new_bound_with(py, 10, |b: &mut [u8]| { b.copy_from_slice(b"Hello Rust"); Ok(()) })?; let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() }; assert_eq!(bytearray, b"Hello Rust"); Ok(()) }) } #[test] fn test_byte_array_new_with_zero_initialised() -> super::PyResult<()> { Python::with_gil(|py| -> super::PyResult<()> { let py_bytearray = PyByteArray::new_bound_with(py, 10, |_b: &mut [u8]| Ok(()))?; let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() }; assert_eq!(bytearray, &[0; 10]); Ok(()) }) } #[test] fn test_byte_array_new_with_error() { use crate::exceptions::PyValueError; Python::with_gil(|py| { let py_bytearray_result = PyByteArray::new_bound_with(py, 10, |_b: &mut [u8]| { Err(PyValueError::new_err("Hello Crustaceans!")) }); assert!(py_bytearray_result.is_err()); assert!(py_bytearray_result .err() .unwrap() .is_instance_of::(py)); }) } } pyo3/src/types/boolobject.rs0000644000175000017500000002363214661133735017064 0ustar jamespagejamespage#[cfg(feature = "experimental-inspect")] use crate::inspect::types::TypeInfo; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ exceptions::PyTypeError, ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound, types::typeobject::PyTypeMethods, Borrowed, FromPyObject, IntoPy, PyAny, PyObject, PyResult, Python, ToPyObject, }; use super::any::PyAnyMethods; /// Represents a Python `bool`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyBool>`][Bound]. /// /// For APIs available on `bool` objects, see the [`PyBoolMethods`] trait which is implemented for /// [`Bound<'py, PyBool>`][Bound]. #[repr(transparent)] pub struct PyBool(PyAny); pyobject_native_type!(PyBool, ffi::PyObject, pyobject_native_static_type_object!(ffi::PyBool_Type), #checkfunction=ffi::PyBool_Check); impl PyBool { /// Depending on `val`, returns `true` or `false`. /// /// # Note /// This returns a [`Borrowed`] reference to one of Pythons `True` or /// `False` singletons #[inline] pub fn new_bound(py: Python<'_>, val: bool) -> Borrowed<'_, '_, Self> { unsafe { if val { ffi::Py_True() } else { ffi::Py_False() } .assume_borrowed(py) .downcast_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyBool { /// Deprecated form of [`PyBool::new_bound`] #[deprecated( since = "0.21.0", note = "`PyBool::new` will be replaced by `PyBool::new_bound` in a future PyO3 version" )] #[inline] pub fn new(py: Python<'_>, val: bool) -> &PyBool { #[allow(deprecated)] unsafe { py.from_borrowed_ptr(if val { ffi::Py_True() } else { ffi::Py_False() }) } } /// Gets whether this boolean is `true`. #[inline] pub fn is_true(&self) -> bool { self.as_borrowed().is_true() } } /// Implementation of functionality for [`PyBool`]. /// /// These methods are defined for the `Bound<'py, PyBool>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyBool")] pub trait PyBoolMethods<'py>: crate::sealed::Sealed { /// Gets whether this boolean is `true`. fn is_true(&self) -> bool; } impl<'py> PyBoolMethods<'py> for Bound<'py, PyBool> { #[inline] fn is_true(&self) -> bool { self.as_ptr() == unsafe { crate::ffi::Py_True() } } } /// Compare `Bound` with `bool`. impl PartialEq for Bound<'_, PyBool> { #[inline] fn eq(&self, other: &bool) -> bool { self.as_borrowed() == *other } } /// Compare `&Bound` with `bool`. impl PartialEq for &'_ Bound<'_, PyBool> { #[inline] fn eq(&self, other: &bool) -> bool { self.as_borrowed() == *other } } /// Compare `Bound` with `&bool`. impl PartialEq<&'_ bool> for Bound<'_, PyBool> { #[inline] fn eq(&self, other: &&bool) -> bool { self.as_borrowed() == **other } } /// Compare `bool` with `Bound` impl PartialEq> for bool { #[inline] fn eq(&self, other: &Bound<'_, PyBool>) -> bool { *self == other.as_borrowed() } } /// Compare `bool` with `&Bound` impl PartialEq<&'_ Bound<'_, PyBool>> for bool { #[inline] fn eq(&self, other: &&'_ Bound<'_, PyBool>) -> bool { *self == other.as_borrowed() } } /// Compare `&bool` with `Bound` impl PartialEq> for &'_ bool { #[inline] fn eq(&self, other: &Bound<'_, PyBool>) -> bool { **self == other.as_borrowed() } } /// Compare `Borrowed` with `bool` impl PartialEq for Borrowed<'_, '_, PyBool> { #[inline] fn eq(&self, other: &bool) -> bool { self.is_true() == *other } } /// Compare `Borrowed` with `&bool` impl PartialEq<&bool> for Borrowed<'_, '_, PyBool> { #[inline] fn eq(&self, other: &&bool) -> bool { self.is_true() == **other } } /// Compare `bool` with `Borrowed` impl PartialEq> for bool { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyBool>) -> bool { *self == other.is_true() } } /// Compare `&bool` with `Borrowed` impl PartialEq> for &'_ bool { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyBool>) -> bool { **self == other.is_true() } } /// Converts a Rust `bool` to a Python `bool`. impl ToPyObject for bool { #[inline] fn to_object(&self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_borrowed_ptr( py, if *self { ffi::Py_True() } else { ffi::Py_False() }, ) } } } impl IntoPy for bool { #[inline] fn into_py(self, py: Python<'_>) -> PyObject { PyBool::new_bound(py, self).into_py(py) } #[cfg(feature = "experimental-inspect")] fn type_output() -> TypeInfo { TypeInfo::builtin("bool") } } /// Converts a Python `bool` to a Rust `bool`. /// /// Fails with `TypeError` if the input is not a Python `bool`. impl FromPyObject<'_> for bool { fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult { let err = match obj.downcast::() { Ok(obj) => return Ok(obj.is_true()), Err(err) => err, }; let is_numpy_bool = { let ty = obj.get_type(); ty.module().map_or(false, |module| module == "numpy") && ty .name() .map_or(false, |name| name == "bool_" || name == "bool") }; if is_numpy_bool { let missing_conversion = |obj: &Bound<'_, PyAny>| { PyTypeError::new_err(format!( "object of type '{}' does not define a '__bool__' conversion", obj.get_type() )) }; #[cfg(not(any(Py_LIMITED_API, PyPy)))] unsafe { let ptr = obj.as_ptr(); if let Some(tp_as_number) = (*(*ptr).ob_type).tp_as_number.as_ref() { if let Some(nb_bool) = tp_as_number.nb_bool { match (nb_bool)(ptr) { 0 => return Ok(false), 1 => return Ok(true), _ => return Err(crate::PyErr::fetch(obj.py())), } } } return Err(missing_conversion(obj)); } #[cfg(any(Py_LIMITED_API, PyPy))] { let meth = obj .lookup_special(crate::intern!(obj.py(), "__bool__"))? .ok_or_else(|| missing_conversion(obj))?; let obj = meth.call0()?.downcast_into::()?; return Ok(obj.is_true()); } } Err(err.into()) } #[cfg(feature = "experimental-inspect")] fn type_input() -> TypeInfo { Self::type_output() } } #[cfg(test)] mod tests { use crate::types::any::PyAnyMethods; use crate::types::boolobject::PyBoolMethods; use crate::types::PyBool; use crate::Python; use crate::ToPyObject; #[test] fn test_true() { Python::with_gil(|py| { assert!(PyBool::new_bound(py, true).is_true()); let t = PyBool::new_bound(py, true); assert!(t.extract::().unwrap()); assert!(true.to_object(py).is(&*PyBool::new_bound(py, true))); }); } #[test] fn test_false() { Python::with_gil(|py| { assert!(!PyBool::new_bound(py, false).is_true()); let t = PyBool::new_bound(py, false); assert!(!t.extract::().unwrap()); assert!(false.to_object(py).is(&*PyBool::new_bound(py, false))); }); } #[test] fn test_pybool_comparisons() { Python::with_gil(|py| { let py_bool = PyBool::new_bound(py, true); let py_bool_false = PyBool::new_bound(py, false); let rust_bool = true; // Bound<'_, PyBool> == bool assert_eq!(*py_bool, rust_bool); assert_ne!(*py_bool_false, rust_bool); // Bound<'_, PyBool> == &bool assert_eq!(*py_bool, &rust_bool); assert_ne!(*py_bool_false, &rust_bool); // &Bound<'_, PyBool> == bool assert_eq!(&*py_bool, rust_bool); assert_ne!(&*py_bool_false, rust_bool); // &Bound<'_, PyBool> == &bool assert_eq!(&*py_bool, &rust_bool); assert_ne!(&*py_bool_false, &rust_bool); // bool == Bound<'_, PyBool> assert_eq!(rust_bool, *py_bool); assert_ne!(rust_bool, *py_bool_false); // bool == &Bound<'_, PyBool> assert_eq!(rust_bool, &*py_bool); assert_ne!(rust_bool, &*py_bool_false); // &bool == Bound<'_, PyBool> assert_eq!(&rust_bool, *py_bool); assert_ne!(&rust_bool, *py_bool_false); // &bool == &Bound<'_, PyBool> assert_eq!(&rust_bool, &*py_bool); assert_ne!(&rust_bool, &*py_bool_false); // Borrowed<'_, '_, PyBool> == bool assert_eq!(py_bool, rust_bool); assert_ne!(py_bool_false, rust_bool); // Borrowed<'_, '_, PyBool> == &bool assert_eq!(py_bool, &rust_bool); assert_ne!(py_bool_false, &rust_bool); // bool == Borrowed<'_, '_, PyBool> assert_eq!(rust_bool, py_bool); assert_ne!(rust_bool, py_bool_false); // &bool == Borrowed<'_, '_, PyBool> assert_eq!(&rust_bool, py_bool); assert_ne!(&rust_bool, py_bool_false); assert_eq!(py_bool, rust_bool); assert_ne!(py_bool_false, rust_bool); }) } } pyo3/src/types/any.rs0000644000175000017500000026152414661133735015535 0ustar jamespagejamespageuse crate::class::basic::CompareOp; use crate::conversion::{AsPyPointer, FromPyObjectBound, IntoPy, ToPyObject}; use crate::err::{DowncastError, DowncastIntoError, PyErr, PyResult}; use crate::exceptions::{PyAttributeError, PyTypeError}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Bound; use crate::internal_tricks::ptr_from_ref; use crate::py_result_ext::PyResultExt; use crate::type_object::{PyTypeCheck, PyTypeInfo}; #[cfg(not(any(PyPy, GraalPy)))] use crate::types::PySuper; use crate::types::{PyDict, PyIterator, PyList, PyString, PyTuple, PyType}; use crate::{err, ffi, Py, Python}; #[cfg(feature = "gil-refs")] use crate::{err::PyDowncastError, type_object::HasPyGilRef, PyNativeType}; use std::cell::UnsafeCell; use std::cmp::Ordering; use std::os::raw::c_int; /// Represents any Python object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyAny>`][Bound]. /// /// For APIs available on all Python objects, see the [`PyAnyMethods`] trait which is implemented for /// [`Bound<'py, PyAny>`][Bound]. /// /// See #[doc = concat!("[the guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/types.html#concrete-python-types)")] /// for an explanation of the different Python object types. #[repr(transparent)] pub struct PyAny(UnsafeCell); unsafe impl AsPyPointer for PyAny { #[inline] fn as_ptr(&self) -> *mut ffi::PyObject { self.0.get() } } #[allow(non_snake_case)] // Copied here as the macro does not accept deprecated functions. // Originally ffi::object::PyObject_Check, but this is not in the Python C API. fn PyObject_Check(_: *mut ffi::PyObject) -> c_int { 1 } pyobject_native_type_base!(PyAny); pyobject_native_type_info!( PyAny, pyobject_native_static_type_object!(ffi::PyBaseObject_Type), Some("builtins"), #checkfunction=PyObject_Check ); pyobject_native_type_extract!(PyAny); pyobject_native_type_sized!(PyAny, ffi::PyObject); #[cfg(feature = "gil-refs")] impl PyAny { /// Returns whether `self` and `other` point to the same object. To compare /// the equality of two objects (the `==` operator), use [`eq`](PyAny::eq). /// /// This is equivalent to the Python expression `self is other`. #[inline] pub fn is(&self, other: &T) -> bool { self.as_borrowed().is(other) } /// Determines whether this object has the given attribute. /// /// This is equivalent to the Python expression `hasattr(self, attr_name)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn has_version(sys: &Bound<'_, PyModule>) -> PyResult { /// sys.hasattr(intern!(sys.py(), "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import_bound("sys").unwrap(); /// # has_version(&sys).unwrap(); /// # }); /// ``` pub fn hasattr(&self, attr_name: N) -> PyResult where N: IntoPy>, { self.as_borrowed().hasattr(attr_name) } /// Retrieves an attribute value. /// /// This is equivalent to the Python expression `self.attr_name`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn version<'py>(sys: &Bound<'py, PyModule>) -> PyResult> { /// sys.getattr(intern!(sys.py(), "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import_bound("sys").unwrap(); /// # version(&sys).unwrap(); /// # }); /// ``` pub fn getattr(&self, attr_name: N) -> PyResult<&PyAny> where N: IntoPy>, { self.as_borrowed() .getattr(attr_name) .map(Bound::into_gil_ref) } /// Sets an attribute value. /// /// This is equivalent to the Python expression `self.attr_name = value`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn set_answer(ob: &Bound<'_, PyAny>) -> PyResult<()> { /// ob.setattr(intern!(ob.py(), "answer"), 42) /// } /// # /// # Python::with_gil(|py| { /// # let ob = PyModule::new_bound(py, "empty").unwrap(); /// # set_answer(&ob).unwrap(); /// # }); /// ``` pub fn setattr(&self, attr_name: N, value: V) -> PyResult<()> where N: IntoPy>, V: ToPyObject, { self.as_borrowed().setattr(attr_name, value) } /// Deletes an attribute. /// /// This is equivalent to the Python statement `del self.attr_name`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. pub fn delattr(&self, attr_name: N) -> PyResult<()> where N: IntoPy>, { self.as_borrowed().delattr(attr_name) } /// Returns an [`Ordering`] between `self` and `other`. /// /// This is equivalent to the following Python code: /// ```python /// if self == other: /// return Equal /// elif a < b: /// return Less /// elif a > b: /// return Greater /// else: /// raise TypeError("PyAny::compare(): All comparisons returned false") /// ``` /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyFloat; /// use std::cmp::Ordering; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a = PyFloat::new_bound(py, 0_f64); /// let b = PyFloat::new_bound(py, 42_f64); /// assert_eq!(a.compare(b)?, Ordering::Less); /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// It will return `PyErr` for values that cannot be compared: /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyFloat, PyString}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a = PyFloat::new_bound(py, 0_f64); /// let b = PyString::new_bound(py, "zero"); /// assert!(a.compare(b).is_err()); /// Ok(()) /// })?; /// # Ok(())} /// ``` pub fn compare(&self, other: O) -> PyResult where O: ToPyObject, { self.as_borrowed().compare(other) } /// Tests whether two Python objects obey a given [`CompareOp`]. /// /// [`lt`](Self::lt), [`le`](Self::le), [`eq`](Self::eq), [`ne`](Self::ne), /// [`gt`](Self::gt) and [`ge`](Self::ge) are the specialized versions /// of this function. /// /// Depending on the value of `compare_op`, this is equivalent to one of the /// following Python expressions: /// /// | `compare_op` | Python expression | /// | :---: | :----: | /// | [`CompareOp::Eq`] | `self == other` | /// | [`CompareOp::Ne`] | `self != other` | /// | [`CompareOp::Lt`] | `self < other` | /// | [`CompareOp::Le`] | `self <= other` | /// | [`CompareOp::Gt`] | `self > other` | /// | [`CompareOp::Ge`] | `self >= other` | /// /// # Examples /// /// ```rust /// use pyo3::class::basic::CompareOp; /// use pyo3::prelude::*; /// use pyo3::types::PyInt; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a: Bound<'_, PyInt> = 0_u8.into_py(py).into_bound(py).downcast_into()?; /// let b: Bound<'_, PyInt> = 42_u8.into_py(py).into_bound(py).downcast_into()?; /// assert!(a.rich_compare(b, CompareOp::Le)?.is_truthy()?); /// Ok(()) /// })?; /// # Ok(())} /// ``` pub fn rich_compare(&self, other: O, compare_op: CompareOp) -> PyResult<&PyAny> where O: ToPyObject, { self.as_borrowed() .rich_compare(other, compare_op) .map(Bound::into_gil_ref) } /// Tests whether this object is less than another. /// /// This is equivalent to the Python expression `self < other`. pub fn lt(&self, other: O) -> PyResult where O: ToPyObject, { self.as_borrowed().lt(other) } /// Tests whether this object is less than or equal to another. /// /// This is equivalent to the Python expression `self <= other`. pub fn le(&self, other: O) -> PyResult where O: ToPyObject, { self.as_borrowed().le(other) } /// Tests whether this object is equal to another. /// /// This is equivalent to the Python expression `self == other`. pub fn eq(&self, other: O) -> PyResult where O: ToPyObject, { self.as_borrowed().eq(other) } /// Tests whether this object is not equal to another. /// /// This is equivalent to the Python expression `self != other`. pub fn ne(&self, other: O) -> PyResult where O: ToPyObject, { self.as_borrowed().ne(other) } /// Tests whether this object is greater than another. /// /// This is equivalent to the Python expression `self > other`. pub fn gt(&self, other: O) -> PyResult where O: ToPyObject, { self.as_borrowed().gt(other) } /// Tests whether this object is greater than or equal to another. /// /// This is equivalent to the Python expression `self >= other`. pub fn ge(&self, other: O) -> PyResult where O: ToPyObject, { self.as_borrowed().ge(other) } /// Determines whether this object appears callable. /// /// This is equivalent to Python's [`callable()`][1] function. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let builtins = PyModule::import_bound(py, "builtins")?; /// let print = builtins.getattr("print")?; /// assert!(print.is_callable()); /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// This is equivalent to the Python statement `assert callable(print)`. /// /// Note that unless an API needs to distinguish between callable and /// non-callable objects, there is no point in checking for callability. /// Instead, it is better to just do the call and handle potential /// exceptions. /// /// [1]: https://docs.python.org/3/library/functions.html#callable pub fn is_callable(&self) -> bool { self.as_borrowed().is_callable() } /// Calls the object. /// /// This is equivalent to the Python expression `self(*args, **kwargs)`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// const CODE: &str = r#" /// def function(*args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {"cruel": "world"} /// return "called with args and kwargs" /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let fun = module.getattr("function")?; /// let args = ("hello",); /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; /// let result = fun.call(args, Some(&kwargs))?; /// assert_eq!(result.extract::()?, "called with args and kwargs"); /// Ok(()) /// }) /// # } /// ``` pub fn call( &self, args: impl IntoPy>, kwargs: Option<&PyDict>, ) -> PyResult<&PyAny> { self.as_borrowed() .call(args, kwargs.map(PyDict::as_borrowed).as_deref()) .map(Bound::into_gil_ref) } /// Calls the object without arguments. /// /// This is equivalent to the Python expression `self()`. /// /// # Examples /// /// ```no_run /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let module = PyModule::import_bound(py, "builtins")?; /// let help = module.getattr("help")?; /// help.call0()?; /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// This is equivalent to the Python expression `help()`. pub fn call0(&self) -> PyResult<&PyAny> { self.as_borrowed().call0().map(Bound::into_gil_ref) } /// Calls the object with only positional arguments. /// /// This is equivalent to the Python expression `self(*args)`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// const CODE: &str = r#" /// def function(*args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {} /// return "called with args" /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let fun = module.getattr("function")?; /// let args = ("hello",); /// let result = fun.call1(args)?; /// assert_eq!(result.extract::()?, "called with args"); /// Ok(()) /// }) /// # } /// ``` pub fn call1(&self, args: impl IntoPy>) -> PyResult<&PyAny> { self.as_borrowed().call1(args).map(Bound::into_gil_ref) } /// Calls a method on the object. /// /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// const CODE: &str = r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {"cruel": "world"} /// return "called with args and kwargs" /// a = A() /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let args = ("hello",); /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; /// let result = instance.call_method("method", args, Some(&kwargs))?; /// assert_eq!(result.extract::()?, "called with args and kwargs"); /// Ok(()) /// }) /// # } /// ``` pub fn call_method(&self, name: N, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyAny> where N: IntoPy>, A: IntoPy>, { self.as_borrowed() .call_method(name, args, kwargs.map(PyDict::as_borrowed).as_deref()) .map(Bound::into_gil_ref) } /// Calls a method on the object without arguments. /// /// This is equivalent to the Python expression `self.name()`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// const CODE: &str = r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == () /// assert kwargs == {} /// return "called with no arguments" /// a = A() /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let result = instance.call_method0("method")?; /// assert_eq!(result.extract::()?, "called with no arguments"); /// Ok(()) /// }) /// # } /// ``` pub fn call_method0(&self, name: N) -> PyResult<&PyAny> where N: IntoPy>, { self.as_borrowed() .call_method0(name) .map(Bound::into_gil_ref) } /// Calls a method on the object with only positional arguments. /// /// This is equivalent to the Python expression `self.name(*args)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// const CODE: &str = r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {} /// return "called with args" /// a = A() /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let args = ("hello",); /// let result = instance.call_method1("method", args)?; /// assert_eq!(result.extract::()?, "called with args"); /// Ok(()) /// }) /// # } /// ``` pub fn call_method1(&self, name: N, args: A) -> PyResult<&PyAny> where N: IntoPy>, A: IntoPy>, { self.as_borrowed() .call_method1(name, args) .map(Bound::into_gil_ref) } /// Returns whether the object is considered to be true. /// /// This is equivalent to the Python expression `bool(self)`. #[deprecated(since = "0.21.0", note = "use `.is_truthy()` instead")] pub fn is_true(&self) -> PyResult { self.is_truthy() } /// Returns whether the object is considered to be true. /// /// This applies truth value testing equivalent to the Python expression `bool(self)`. pub fn is_truthy(&self) -> PyResult { self.as_borrowed().is_truthy() } /// Returns whether the object is considered to be None. /// /// This is equivalent to the Python expression `self is None`. #[inline] pub fn is_none(&self) -> bool { self.as_borrowed().is_none() } /// Returns whether the object is Ellipsis, e.g. `...`. /// /// This is equivalent to the Python expression `self is ...`. #[deprecated(since = "0.20.0", note = "use `.is(py.Ellipsis())` instead")] pub fn is_ellipsis(&self) -> bool { self.as_borrowed().is_ellipsis() } /// Returns true if the sequence or mapping has a length of 0. /// /// This is equivalent to the Python expression `len(self) == 0`. pub fn is_empty(&self) -> PyResult { self.as_borrowed().is_empty() } /// Gets an item from the collection. /// /// This is equivalent to the Python expression `self[key]`. pub fn get_item(&self, key: K) -> PyResult<&PyAny> where K: ToPyObject, { self.as_borrowed().get_item(key).map(Bound::into_gil_ref) } /// Sets a collection item value. /// /// This is equivalent to the Python expression `self[key] = value`. pub fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject, { self.as_borrowed().set_item(key, value) } /// Deletes an item from the collection. /// /// This is equivalent to the Python expression `del self[key]`. pub fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject, { self.as_borrowed().del_item(key) } /// Takes an object and returns an iterator for it. /// /// This is typically a new iterator but if the argument is an iterator, /// this returns itself. pub fn iter(&self) -> PyResult<&PyIterator> { self.as_borrowed().iter().map(Bound::into_gil_ref) } /// Returns the Python type object for this object's type. pub fn get_type(&self) -> &PyType { self.as_borrowed().get_type().into_gil_ref() } /// Returns the Python type pointer for this object. #[inline] pub fn get_type_ptr(&self) -> *mut ffi::PyTypeObject { self.as_borrowed().get_type_ptr() } /// Downcast this `PyAny` to a concrete Python type or pyclass. /// /// Note that you can often avoid downcasting yourself by just specifying /// the desired type in function or method signatures. /// However, manual downcasting is sometimes necessary. /// /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). /// /// # Example: Downcasting to a specific Python object /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { /// let dict = PyDict::new_bound(py); /// assert!(dict.is_instance_of::()); /// let any = dict.as_any(); /// /// assert!(any.downcast::().is_ok()); /// assert!(any.downcast::().is_err()); /// }); /// ``` /// /// # Example: Getting a reference to a pyclass /// /// This is useful if you want to mutate a `PyObject` that /// might actually be a pyclass. /// /// ```rust /// # fn main() -> Result<(), pyo3::PyErr> { /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Class { /// i: i32, /// } /// /// Python::with_gil(|py| { /// let class = Py::new(py, Class { i: 0 }).unwrap().into_bound(py).into_any(); /// /// let class_bound: &Bound<'_, Class> = class.downcast()?; /// /// class_bound.borrow_mut().i += 1; /// /// // Alternatively you can get a `PyRefMut` directly /// let class_ref: PyRefMut<'_, Class> = class.extract()?; /// assert_eq!(class_ref.i, 1); /// Ok(()) /// }) /// # } /// ``` #[inline] pub fn downcast(&self) -> Result<&T, PyDowncastError<'_>> where T: PyTypeCheck, { if T::type_check(&self.as_borrowed()) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(PyDowncastError::new(self, T::NAME)) } } /// Downcast this `PyAny` to a concrete Python type or pyclass (but not a subclass of it). /// /// It is almost always better to use [`PyAny::downcast`] because it accounts for Python /// subtyping. Use this method only when you do not want to allow subtypes. /// /// The advantage of this method over [`PyAny::downcast`] is that it is faster. The implementation /// of `downcast_exact` uses the equivalent of the Python expression `type(self) is T`, whereas /// `downcast` uses `isinstance(self, T)`. /// /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). /// /// # Example: Downcasting to a specific Python object but not a subtype /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyBool, PyLong}; /// /// Python::with_gil(|py| { /// let b = PyBool::new_bound(py, true); /// assert!(b.is_instance_of::()); /// let any: &Bound<'_, PyAny> = b.as_any(); /// /// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int` /// // but `downcast_exact` will not. /// assert!(any.downcast::().is_ok()); /// assert!(any.downcast_exact::().is_err()); /// /// assert!(any.downcast_exact::().is_ok()); /// }); /// ``` #[inline] pub fn downcast_exact(&self) -> Result<&T, PyDowncastError<'_>> where T: PyTypeInfo, { if T::is_exact_type_of_bound(&self.as_borrowed()) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(PyDowncastError::new(self, T::NAME)) } } /// Converts this `PyAny` to a concrete Python type without checking validity. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. #[inline] pub unsafe fn downcast_unchecked(&self) -> &T where T: HasPyGilRef, { &*(self.as_ptr() as *const T) } /// Extracts some type from the Python object. /// /// This is a wrapper function around /// [`FromPyObject::extract()`](crate::FromPyObject::extract). #[inline] pub fn extract<'py, D>(&'py self) -> PyResult where D: FromPyObjectBound<'py, 'py>, { FromPyObjectBound::from_py_object_bound(self.as_borrowed()) } /// Returns the reference count for the Python object. pub fn get_refcnt(&self) -> isize { self.as_borrowed().get_refcnt() } /// Computes the "repr" representation of self. /// /// This is equivalent to the Python expression `repr(self)`. pub fn repr(&self) -> PyResult<&PyString> { self.as_borrowed().repr().map(Bound::into_gil_ref) } /// Computes the "str" representation of self. /// /// This is equivalent to the Python expression `str(self)`. pub fn str(&self) -> PyResult<&PyString> { self.as_borrowed().str().map(Bound::into_gil_ref) } /// Retrieves the hash code of self. /// /// This is equivalent to the Python expression `hash(self)`. pub fn hash(&self) -> PyResult { self.as_borrowed().hash() } /// Returns the length of the sequence or mapping. /// /// This is equivalent to the Python expression `len(self)`. pub fn len(&self) -> PyResult { self.as_borrowed().len() } /// Returns the list of attributes of this object. /// /// This is equivalent to the Python expression `dir(self)`. pub fn dir(&self) -> PyResult<&PyList> { self.as_borrowed().dir().map(Bound::into_gil_ref) } /// Checks whether this object is an instance of type `ty`. /// /// This is equivalent to the Python expression `isinstance(self, ty)`. #[inline] pub fn is_instance(&self, ty: &PyAny) -> PyResult { self.as_borrowed().is_instance(&ty.as_borrowed()) } /// Checks whether this object is an instance of exactly type `ty` (not a subclass). /// /// This is equivalent to the Python expression `type(self) is ty`. #[inline] pub fn is_exact_instance(&self, ty: &PyAny) -> bool { self.as_borrowed().is_exact_instance(&ty.as_borrowed()) } /// Checks whether this object is an instance of type `T`. /// /// This is equivalent to the Python expression `isinstance(self, T)`, /// if the type `T` is known at compile time. #[inline] pub fn is_instance_of(&self) -> bool { self.as_borrowed().is_instance_of::() } /// Checks whether this object is an instance of exactly type `T`. /// /// This is equivalent to the Python expression `type(self) is T`, /// if the type `T` is known at compile time. #[inline] pub fn is_exact_instance_of(&self) -> bool { self.as_borrowed().is_exact_instance_of::() } /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. pub fn contains(&self, value: V) -> PyResult where V: ToPyObject, { self.as_borrowed().contains(value) } /// Returns a GIL marker constrained to the lifetime of this type. #[inline] pub fn py(&self) -> Python<'_> { PyNativeType::py(self) } /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { ptr_from_ref(self) as *mut ffi::PyObject } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(&self) -> *mut ffi::PyObject { // Safety: self.as_ptr() returns a valid non-null pointer let ptr = self.as_ptr(); unsafe { ffi::Py_INCREF(ptr) }; ptr } /// Return a proxy object that delegates method calls to a parent or sibling class of type. /// /// This is equivalent to the Python expression `super()` #[cfg(not(any(PyPy, GraalPy)))] pub fn py_super(&self) -> PyResult<&PySuper> { self.as_borrowed().py_super().map(Bound::into_gil_ref) } } /// This trait represents the Python APIs which are usable on all Python objects. /// /// It is recommended you import this trait via `use pyo3::prelude::*` rather than /// by importing this trait directly. #[doc(alias = "PyAny")] pub trait PyAnyMethods<'py>: crate::sealed::Sealed { /// Returns whether `self` and `other` point to the same object. To compare /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq). /// /// This is equivalent to the Python expression `self is other`. fn is(&self, other: &T) -> bool; /// Determines whether this object has the given attribute. /// /// This is equivalent to the Python expression `hasattr(self, attr_name)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn has_version(sys: &Bound<'_, PyModule>) -> PyResult { /// sys.hasattr(intern!(sys.py(), "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import_bound("sys").unwrap(); /// # has_version(&sys).unwrap(); /// # }); /// ``` fn hasattr(&self, attr_name: N) -> PyResult where N: IntoPy>; /// Retrieves an attribute value. /// /// This is equivalent to the Python expression `self.attr_name`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn version<'py>(sys: &Bound<'py, PyModule>) -> PyResult> { /// sys.getattr(intern!(sys.py(), "version")) /// } /// # /// # Python::with_gil(|py| { /// # let sys = py.import_bound("sys").unwrap(); /// # version(&sys).unwrap(); /// # }); /// ``` fn getattr(&self, attr_name: N) -> PyResult> where N: IntoPy>; /// Sets an attribute value. /// /// This is equivalent to the Python expression `self.attr_name = value`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Example: `intern!`ing the attribute name /// /// ``` /// # use pyo3::{prelude::*, intern}; /// # /// #[pyfunction] /// fn set_answer(ob: &Bound<'_, PyAny>) -> PyResult<()> { /// ob.setattr(intern!(ob.py(), "answer"), 42) /// } /// # /// # Python::with_gil(|py| { /// # let ob = PyModule::new_bound(py, "empty").unwrap(); /// # set_answer(&ob).unwrap(); /// # }); /// ``` fn setattr(&self, attr_name: N, value: V) -> PyResult<()> where N: IntoPy>, V: ToPyObject; /// Deletes an attribute. /// /// This is equivalent to the Python statement `del self.attr_name`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. fn delattr(&self, attr_name: N) -> PyResult<()> where N: IntoPy>; /// Returns an [`Ordering`] between `self` and `other`. /// /// This is equivalent to the following Python code: /// ```python /// if self == other: /// return Equal /// elif a < b: /// return Less /// elif a > b: /// return Greater /// else: /// raise TypeError("PyAny::compare(): All comparisons returned false") /// ``` /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyFloat; /// use std::cmp::Ordering; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a = PyFloat::new_bound(py, 0_f64); /// let b = PyFloat::new_bound(py, 42_f64); /// assert_eq!(a.compare(b)?, Ordering::Less); /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// It will return `PyErr` for values that cannot be compared: /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyFloat, PyString}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a = PyFloat::new_bound(py, 0_f64); /// let b = PyString::new_bound(py, "zero"); /// assert!(a.compare(b).is_err()); /// Ok(()) /// })?; /// # Ok(())} /// ``` fn compare(&self, other: O) -> PyResult where O: ToPyObject; /// Tests whether two Python objects obey a given [`CompareOp`]. /// /// [`lt`](Self::lt), [`le`](Self::le), [`eq`](Self::eq), [`ne`](Self::ne), /// [`gt`](Self::gt) and [`ge`](Self::ge) are the specialized versions /// of this function. /// /// Depending on the value of `compare_op`, this is equivalent to one of the /// following Python expressions: /// /// | `compare_op` | Python expression | /// | :---: | :----: | /// | [`CompareOp::Eq`] | `self == other` | /// | [`CompareOp::Ne`] | `self != other` | /// | [`CompareOp::Lt`] | `self < other` | /// | [`CompareOp::Le`] | `self <= other` | /// | [`CompareOp::Gt`] | `self > other` | /// | [`CompareOp::Ge`] | `self >= other` | /// /// # Examples /// /// ```rust /// use pyo3::class::basic::CompareOp; /// use pyo3::prelude::*; /// use pyo3::types::PyInt; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let a: Bound<'_, PyInt> = 0_u8.into_py(py).into_bound(py).downcast_into()?; /// let b: Bound<'_, PyInt> = 42_u8.into_py(py).into_bound(py).downcast_into()?; /// assert!(a.rich_compare(b, CompareOp::Le)?.is_truthy()?); /// Ok(()) /// })?; /// # Ok(())} /// ``` fn rich_compare(&self, other: O, compare_op: CompareOp) -> PyResult> where O: ToPyObject; /// Computes the negative of self. /// /// Equivalent to the Python expression `-self`. fn neg(&self) -> PyResult>; /// Computes the positive of self. /// /// Equivalent to the Python expression `+self`. fn pos(&self) -> PyResult>; /// Computes the absolute of self. /// /// Equivalent to the Python expression `abs(self)`. fn abs(&self) -> PyResult>; /// Computes `~self`. fn bitnot(&self) -> PyResult>; /// Tests whether this object is less than another. /// /// This is equivalent to the Python expression `self < other`. fn lt(&self, other: O) -> PyResult where O: ToPyObject; /// Tests whether this object is less than or equal to another. /// /// This is equivalent to the Python expression `self <= other`. fn le(&self, other: O) -> PyResult where O: ToPyObject; /// Tests whether this object is equal to another. /// /// This is equivalent to the Python expression `self == other`. fn eq(&self, other: O) -> PyResult where O: ToPyObject; /// Tests whether this object is not equal to another. /// /// This is equivalent to the Python expression `self != other`. fn ne(&self, other: O) -> PyResult where O: ToPyObject; /// Tests whether this object is greater than another. /// /// This is equivalent to the Python expression `self > other`. fn gt(&self, other: O) -> PyResult where O: ToPyObject; /// Tests whether this object is greater than or equal to another. /// /// This is equivalent to the Python expression `self >= other`. fn ge(&self, other: O) -> PyResult where O: ToPyObject; /// Computes `self + other`. fn add(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self - other`. fn sub(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self * other`. fn mul(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self @ other`. fn matmul(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self / other`. fn div(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self // other`. fn floor_div(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self % other`. fn rem(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `divmod(self, other)`. fn divmod(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self << other`. fn lshift(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self >> other`. fn rshift(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self ** other % modulus` (`pow(self, other, modulus)`). /// `py.None()` may be passed for the `modulus`. fn pow(&self, other: O1, modulus: O2) -> PyResult> where O1: ToPyObject, O2: ToPyObject; /// Computes `self & other`. fn bitand(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self | other`. fn bitor(&self, other: O) -> PyResult> where O: ToPyObject; /// Computes `self ^ other`. fn bitxor(&self, other: O) -> PyResult> where O: ToPyObject; /// Determines whether this object appears callable. /// /// This is equivalent to Python's [`callable()`][1] function. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let builtins = PyModule::import_bound(py, "builtins")?; /// let print = builtins.getattr("print")?; /// assert!(print.is_callable()); /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// This is equivalent to the Python statement `assert callable(print)`. /// /// Note that unless an API needs to distinguish between callable and /// non-callable objects, there is no point in checking for callability. /// Instead, it is better to just do the call and handle potential /// exceptions. /// /// [1]: https://docs.python.org/3/library/functions.html#callable fn is_callable(&self) -> bool; /// Calls the object. /// /// This is equivalent to the Python expression `self(*args, **kwargs)`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// const CODE: &str = r#" /// def function(*args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {"cruel": "world"} /// return "called with args and kwargs" /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let fun = module.getattr("function")?; /// let args = ("hello",); /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; /// let result = fun.call(args, Some(&kwargs))?; /// assert_eq!(result.extract::()?, "called with args and kwargs"); /// Ok(()) /// }) /// # } /// ``` fn call( &self, args: impl IntoPy>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult>; /// Calls the object without arguments. /// /// This is equivalent to the Python expression `self()`. /// /// # Examples /// /// ```no_run /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let module = PyModule::import_bound(py, "builtins")?; /// let help = module.getattr("help")?; /// help.call0()?; /// Ok(()) /// })?; /// # Ok(())} /// ``` /// /// This is equivalent to the Python expression `help()`. fn call0(&self) -> PyResult>; /// Calls the object with only positional arguments. /// /// This is equivalent to the Python expression `self(*args)`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// const CODE: &str = r#" /// def function(*args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {} /// return "called with args" /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let fun = module.getattr("function")?; /// let args = ("hello",); /// let result = fun.call1(args)?; /// assert_eq!(result.extract::()?, "called with args"); /// Ok(()) /// }) /// # } /// ``` fn call1(&self, args: impl IntoPy>) -> PyResult>; /// Calls a method on the object. /// /// This is equivalent to the Python expression `self.name(*args, **kwargs)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::PyDict; /// /// const CODE: &str = r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {"cruel": "world"} /// return "called with args and kwargs" /// a = A() /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let args = ("hello",); /// let kwargs = PyDict::new_bound(py); /// kwargs.set_item("cruel", "world")?; /// let result = instance.call_method("method", args, Some(&kwargs))?; /// assert_eq!(result.extract::()?, "called with args and kwargs"); /// Ok(()) /// }) /// # } /// ``` fn call_method( &self, name: N, args: A, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult> where N: IntoPy>, A: IntoPy>; /// Calls a method on the object without arguments. /// /// This is equivalent to the Python expression `self.name()`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// const CODE: &str = r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == () /// assert kwargs == {} /// return "called with no arguments" /// a = A() /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let result = instance.call_method0("method")?; /// assert_eq!(result.extract::()?, "called with no arguments"); /// Ok(()) /// }) /// # } /// ``` fn call_method0(&self, name: N) -> PyResult> where N: IntoPy>; /// Calls a method on the object with only positional arguments. /// /// This is equivalent to the Python expression `self.name(*args)`. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `name`. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// const CODE: &str = r#" /// class A: /// def method(self, *args, **kwargs): /// assert args == ("hello",) /// assert kwargs == {} /// return "called with args" /// a = A() /// "#; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let module = PyModule::from_code_bound(py, CODE, "", "")?; /// let instance = module.getattr("a")?; /// let args = ("hello",); /// let result = instance.call_method1("method", args)?; /// assert_eq!(result.extract::()?, "called with args"); /// Ok(()) /// }) /// # } /// ``` fn call_method1(&self, name: N, args: A) -> PyResult> where N: IntoPy>, A: IntoPy>; /// Returns whether the object is considered to be true. /// /// This is equivalent to the Python expression `bool(self)`. fn is_truthy(&self) -> PyResult; /// Returns whether the object is considered to be None. /// /// This is equivalent to the Python expression `self is None`. fn is_none(&self) -> bool; /// Returns whether the object is Ellipsis, e.g. `...`. /// /// This is equivalent to the Python expression `self is ...`. fn is_ellipsis(&self) -> bool; /// Returns true if the sequence or mapping has a length of 0. /// /// This is equivalent to the Python expression `len(self) == 0`. fn is_empty(&self) -> PyResult; /// Gets an item from the collection. /// /// This is equivalent to the Python expression `self[key]`. fn get_item(&self, key: K) -> PyResult> where K: ToPyObject; /// Sets a collection item value. /// /// This is equivalent to the Python expression `self[key] = value`. fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject; /// Deletes an item from the collection. /// /// This is equivalent to the Python expression `del self[key]`. fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject; /// Takes an object and returns an iterator for it. /// /// This is typically a new iterator but if the argument is an iterator, /// this returns itself. fn iter(&self) -> PyResult>; /// Returns the Python type object for this object's type. fn get_type(&self) -> Bound<'py, PyType>; /// Returns the Python type pointer for this object. fn get_type_ptr(&self) -> *mut ffi::PyTypeObject; /// Downcast this `PyAny` to a concrete Python type or pyclass. /// /// Note that you can often avoid downcasting yourself by just specifying /// the desired type in function or method signatures. /// However, manual downcasting is sometimes necessary. /// /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). /// /// # Example: Downcasting to a specific Python object /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { /// let dict = PyDict::new_bound(py); /// assert!(dict.is_instance_of::()); /// let any = dict.as_any(); /// /// assert!(any.downcast::().is_ok()); /// assert!(any.downcast::().is_err()); /// }); /// ``` /// /// # Example: Getting a reference to a pyclass /// /// This is useful if you want to mutate a `PyObject` that /// might actually be a pyclass. /// /// ```rust /// # fn main() -> Result<(), pyo3::PyErr> { /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Class { /// i: i32, /// } /// /// Python::with_gil(|py| { /// let class = Py::new(py, Class { i: 0 }).unwrap().into_bound(py).into_any(); /// /// let class_bound: &Bound<'_, Class> = class.downcast()?; /// /// class_bound.borrow_mut().i += 1; /// /// // Alternatively you can get a `PyRefMut` directly /// let class_ref: PyRefMut<'_, Class> = class.extract()?; /// assert_eq!(class_ref.i, 1); /// Ok(()) /// }) /// # } /// ``` fn downcast(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeCheck; /// Like `downcast` but takes ownership of `self`. /// /// In case of an error, it is possible to retrieve `self` again via [`DowncastIntoError::into_inner`]. /// /// # Example /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyDict, PyList}; /// /// Python::with_gil(|py| { /// let obj: Bound<'_, PyAny> = PyDict::new_bound(py).into_any(); /// /// let obj: Bound<'_, PyAny> = match obj.downcast_into::() { /// Ok(_) => panic!("obj should not be a list"), /// Err(err) => err.into_inner(), /// }; /// /// // obj is a dictionary /// assert!(obj.downcast_into::().is_ok()); /// }) /// ``` fn downcast_into(self) -> Result, DowncastIntoError<'py>> where T: PyTypeCheck; /// Downcast this `PyAny` to a concrete Python type or pyclass (but not a subclass of it). /// /// It is almost always better to use [`PyAnyMethods::downcast`] because it accounts for Python /// subtyping. Use this method only when you do not want to allow subtypes. /// /// The advantage of this method over [`PyAnyMethods::downcast`] is that it is faster. The implementation /// of `downcast_exact` uses the equivalent of the Python expression `type(self) is T`, whereas /// `downcast` uses `isinstance(self, T)`. /// /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract). /// /// # Example: Downcasting to a specific Python object but not a subtype /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{PyBool, PyLong}; /// /// Python::with_gil(|py| { /// let b = PyBool::new_bound(py, true); /// assert!(b.is_instance_of::()); /// let any: &Bound<'_, PyAny> = b.as_any(); /// /// // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int` /// // but `downcast_exact` will not. /// assert!(any.downcast::().is_ok()); /// assert!(any.downcast_exact::().is_err()); /// /// assert!(any.downcast_exact::().is_ok()); /// }); /// ``` fn downcast_exact(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeInfo; /// Like `downcast_exact` but takes ownership of `self`. fn downcast_into_exact(self) -> Result, DowncastIntoError<'py>> where T: PyTypeInfo; /// Converts this `PyAny` to a concrete Python type without checking validity. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. unsafe fn downcast_unchecked(&self) -> &Bound<'py, T>; /// Like `downcast_unchecked` but takes ownership of `self`. /// /// # Safety /// /// Callers must ensure that the type is valid or risk type confusion. unsafe fn downcast_into_unchecked(self) -> Bound<'py, T>; /// Extracts some type from the Python object. /// /// This is a wrapper function around /// [`FromPyObject::extract_bound()`](crate::FromPyObject::extract_bound). fn extract<'a, T>(&'a self) -> PyResult where T: FromPyObjectBound<'a, 'py>; /// Returns the reference count for the Python object. fn get_refcnt(&self) -> isize; /// Computes the "repr" representation of self. /// /// This is equivalent to the Python expression `repr(self)`. fn repr(&self) -> PyResult>; /// Computes the "str" representation of self. /// /// This is equivalent to the Python expression `str(self)`. fn str(&self) -> PyResult>; /// Retrieves the hash code of self. /// /// This is equivalent to the Python expression `hash(self)`. fn hash(&self) -> PyResult; /// Returns the length of the sequence or mapping. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> PyResult; /// Returns the list of attributes of this object. /// /// This is equivalent to the Python expression `dir(self)`. fn dir(&self) -> PyResult>; /// Checks whether this object is an instance of type `ty`. /// /// This is equivalent to the Python expression `isinstance(self, ty)`. fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult; /// Checks whether this object is an instance of exactly type `ty` (not a subclass). /// /// This is equivalent to the Python expression `type(self) is ty`. fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool; /// Checks whether this object is an instance of type `T`. /// /// This is equivalent to the Python expression `isinstance(self, T)`, /// if the type `T` is known at compile time. fn is_instance_of(&self) -> bool; /// Checks whether this object is an instance of exactly type `T`. /// /// This is equivalent to the Python expression `type(self) is T`, /// if the type `T` is known at compile time. fn is_exact_instance_of(&self) -> bool; /// Determines if self contains `value`. /// /// This is equivalent to the Python expression `value in self`. fn contains(&self, value: V) -> PyResult where V: ToPyObject; /// Return a proxy object that delegates method calls to a parent or sibling class of type. /// /// This is equivalent to the Python expression `super()` #[cfg(not(any(PyPy, GraalPy)))] fn py_super(&self) -> PyResult>; } macro_rules! implement_binop { ($name:ident, $c_api:ident, $op:expr) => { #[doc = concat!("Computes `self ", $op, " other`.")] fn $name(&self, other: O) -> PyResult> where O: ToPyObject, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Bound<'_, PyAny>, ) -> PyResult> { unsafe { ffi::$c_api(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py()) } } let py = self.py(); inner(self, other.to_object(py).into_bound(py)) } }; } impl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> { #[inline] fn is(&self, other: &T) -> bool { self.as_ptr() == other.as_ptr() } fn hasattr(&self, attr_name: N) -> PyResult where N: IntoPy>, { // PyObject_HasAttr suppresses all exceptions, which was the behaviour of `hasattr` in Python 2. // Use an implementation which suppresses only AttributeError, which is consistent with `hasattr` in Python 3. fn inner(py: Python<'_>, getattr_result: PyResult>) -> PyResult { match getattr_result { Ok(_) => Ok(true), Err(err) if err.is_instance_of::(py) => Ok(false), Err(e) => Err(e), } } inner(self.py(), self.getattr(attr_name)) } fn getattr(&self, attr_name: N) -> PyResult> where N: IntoPy>, { fn inner<'py>( any: &Bound<'py, PyAny>, attr_name: Bound<'_, PyString>, ) -> PyResult> { unsafe { ffi::PyObject_GetAttr(any.as_ptr(), attr_name.as_ptr()) .assume_owned_or_err(any.py()) } } let py = self.py(); inner(self, attr_name.into_py(self.py()).into_bound(py)) } fn setattr(&self, attr_name: N, value: V) -> PyResult<()> where N: IntoPy>, V: ToPyObject, { fn inner( any: &Bound<'_, PyAny>, attr_name: Bound<'_, PyString>, value: Bound<'_, PyAny>, ) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_SetAttr(any.as_ptr(), attr_name.as_ptr(), value.as_ptr()) }) } let py = self.py(); inner( self, attr_name.into_py(py).into_bound(py), value.to_object(py).into_bound(py), ) } fn delattr(&self, attr_name: N) -> PyResult<()> where N: IntoPy>, { fn inner(any: &Bound<'_, PyAny>, attr_name: Bound<'_, PyString>) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_DelAttr(any.as_ptr(), attr_name.as_ptr()) }) } let py = self.py(); inner(self, attr_name.into_py(py).into_bound(py)) } fn compare(&self, other: O) -> PyResult where O: ToPyObject, { fn inner(any: &Bound<'_, PyAny>, other: Bound<'_, PyAny>) -> PyResult { let other = other.as_ptr(); // Almost the same as ffi::PyObject_RichCompareBool, but this one doesn't try self == other. // See https://github.com/PyO3/pyo3/issues/985 for more. let do_compare = |other, op| unsafe { ffi::PyObject_RichCompare(any.as_ptr(), other, op) .assume_owned_or_err(any.py()) .and_then(|obj| obj.is_truthy()) }; if do_compare(other, ffi::Py_EQ)? { Ok(Ordering::Equal) } else if do_compare(other, ffi::Py_LT)? { Ok(Ordering::Less) } else if do_compare(other, ffi::Py_GT)? { Ok(Ordering::Greater) } else { Err(PyTypeError::new_err( "PyAny::compare(): All comparisons returned false", )) } } let py = self.py(); inner(self, other.to_object(py).into_bound(py)) } fn rich_compare(&self, other: O, compare_op: CompareOp) -> PyResult> where O: ToPyObject, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Bound<'_, PyAny>, compare_op: CompareOp, ) -> PyResult> { unsafe { ffi::PyObject_RichCompare(any.as_ptr(), other.as_ptr(), compare_op as c_int) .assume_owned_or_err(any.py()) } } let py = self.py(); inner(self, other.to_object(py).into_bound(py), compare_op) } fn neg(&self) -> PyResult> { unsafe { ffi::PyNumber_Negative(self.as_ptr()).assume_owned_or_err(self.py()) } } fn pos(&self) -> PyResult> { fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyNumber_Positive(any.as_ptr()).assume_owned_or_err(any.py()) } } inner(self) } fn abs(&self) -> PyResult> { fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyNumber_Absolute(any.as_ptr()).assume_owned_or_err(any.py()) } } inner(self) } fn bitnot(&self) -> PyResult> { fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult> { unsafe { ffi::PyNumber_Invert(any.as_ptr()).assume_owned_or_err(any.py()) } } inner(self) } fn lt(&self, other: O) -> PyResult where O: ToPyObject, { self.rich_compare(other, CompareOp::Lt) .and_then(|any| any.is_truthy()) } fn le(&self, other: O) -> PyResult where O: ToPyObject, { self.rich_compare(other, CompareOp::Le) .and_then(|any| any.is_truthy()) } fn eq(&self, other: O) -> PyResult where O: ToPyObject, { self.rich_compare(other, CompareOp::Eq) .and_then(|any| any.is_truthy()) } fn ne(&self, other: O) -> PyResult where O: ToPyObject, { self.rich_compare(other, CompareOp::Ne) .and_then(|any| any.is_truthy()) } fn gt(&self, other: O) -> PyResult where O: ToPyObject, { self.rich_compare(other, CompareOp::Gt) .and_then(|any| any.is_truthy()) } fn ge(&self, other: O) -> PyResult where O: ToPyObject, { self.rich_compare(other, CompareOp::Ge) .and_then(|any| any.is_truthy()) } implement_binop!(add, PyNumber_Add, "+"); implement_binop!(sub, PyNumber_Subtract, "-"); implement_binop!(mul, PyNumber_Multiply, "*"); implement_binop!(matmul, PyNumber_MatrixMultiply, "@"); implement_binop!(div, PyNumber_TrueDivide, "/"); implement_binop!(floor_div, PyNumber_FloorDivide, "//"); implement_binop!(rem, PyNumber_Remainder, "%"); implement_binop!(lshift, PyNumber_Lshift, "<<"); implement_binop!(rshift, PyNumber_Rshift, ">>"); implement_binop!(bitand, PyNumber_And, "&"); implement_binop!(bitor, PyNumber_Or, "|"); implement_binop!(bitxor, PyNumber_Xor, "^"); /// Computes `divmod(self, other)`. fn divmod(&self, other: O) -> PyResult> where O: ToPyObject, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Bound<'_, PyAny>, ) -> PyResult> { unsafe { ffi::PyNumber_Divmod(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py()) } } let py = self.py(); inner(self, other.to_object(py).into_bound(py)) } /// Computes `self ** other % modulus` (`pow(self, other, modulus)`). /// `py.None()` may be passed for the `modulus`. fn pow(&self, other: O1, modulus: O2) -> PyResult> where O1: ToPyObject, O2: ToPyObject, { fn inner<'py>( any: &Bound<'py, PyAny>, other: Bound<'_, PyAny>, modulus: Bound<'_, PyAny>, ) -> PyResult> { unsafe { ffi::PyNumber_Power(any.as_ptr(), other.as_ptr(), modulus.as_ptr()) .assume_owned_or_err(any.py()) } } let py = self.py(); inner( self, other.to_object(py).into_bound(py), modulus.to_object(py).into_bound(py), ) } fn is_callable(&self) -> bool { unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 } } fn call( &self, args: impl IntoPy>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult> { fn inner<'py>( any: &Bound<'py, PyAny>, args: Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult> { unsafe { ffi::PyObject_Call( any.as_ptr(), args.as_ptr(), kwargs.map_or(std::ptr::null_mut(), |dict| dict.as_ptr()), ) .assume_owned_or_err(any.py()) } } let py = self.py(); inner(self, args.into_py(py).into_bound(py), kwargs) } fn call0(&self) -> PyResult> { cfg_if::cfg_if! { if #[cfg(all( not(PyPy), not(GraalPy), any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // PyObject_CallNoArgs was added to python in 3.9 but to limited API in 3.10 ))] { // Optimized path on python 3.9+ unsafe { ffi::PyObject_CallNoArgs(self.as_ptr()).assume_owned_or_err(self.py()) } } else { self.call((), None) } } } fn call1(&self, args: impl IntoPy>) -> PyResult> { self.call(args, None) } fn call_method( &self, name: N, args: A, kwargs: Option<&Bound<'_, PyDict>>, ) -> PyResult> where N: IntoPy>, A: IntoPy>, { self.getattr(name) .and_then(|method| method.call(args, kwargs)) } fn call_method0(&self, name: N) -> PyResult> where N: IntoPy>, { cfg_if::cfg_if! { if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy, GraalPy))))] { let py = self.py(); // Optimized path on python 3.9+ unsafe { let name = name.into_py(py).into_bound(py); ffi::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr()).assume_owned_or_err(py) } } else { self.call_method(name, (), None) } } } fn call_method1(&self, name: N, args: A) -> PyResult> where N: IntoPy>, A: IntoPy>, { self.call_method(name, args, None) } fn is_truthy(&self) -> PyResult { let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) }; err::error_on_minusone(self.py(), v)?; Ok(v != 0) } #[inline] fn is_none(&self) -> bool { unsafe { ffi::Py_None() == self.as_ptr() } } fn is_ellipsis(&self) -> bool { unsafe { ffi::Py_Ellipsis() == self.as_ptr() } } fn is_empty(&self) -> PyResult { self.len().map(|l| l == 0) } fn get_item(&self, key: K) -> PyResult> where K: ToPyObject, { fn inner<'py>( any: &Bound<'py, PyAny>, key: Bound<'_, PyAny>, ) -> PyResult> { unsafe { ffi::PyObject_GetItem(any.as_ptr(), key.as_ptr()).assume_owned_or_err(any.py()) } } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject, { fn inner( any: &Bound<'_, PyAny>, key: Bound<'_, PyAny>, value: Bound<'_, PyAny>, ) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_SetItem(any.as_ptr(), key.as_ptr(), value.as_ptr()) }) } let py = self.py(); inner( self, key.to_object(py).into_bound(py), value.to_object(py).into_bound(py), ) } fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject, { fn inner(any: &Bound<'_, PyAny>, key: Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(any.py(), unsafe { ffi::PyObject_DelItem(any.as_ptr(), key.as_ptr()) }) } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn iter(&self) -> PyResult> { PyIterator::from_bound_object(self) } fn get_type(&self) -> Bound<'py, PyType> { unsafe { PyType::from_borrowed_type_ptr(self.py(), ffi::Py_TYPE(self.as_ptr())) } } #[inline] fn get_type_ptr(&self) -> *mut ffi::PyTypeObject { unsafe { ffi::Py_TYPE(self.as_ptr()) } } #[inline] fn downcast(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeCheck, { if T::type_check(self) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(DowncastError::new(self, T::NAME)) } } #[inline] fn downcast_into(self) -> Result, DowncastIntoError<'py>> where T: PyTypeCheck, { if T::type_check(&self) { // Safety: type_check is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_into_unchecked() }) } else { Err(DowncastIntoError::new(self, T::NAME)) } } #[inline] fn downcast_exact(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>> where T: PyTypeInfo, { if self.is_exact_instance_of::() { // Safety: is_exact_instance_of is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_unchecked() }) } else { Err(DowncastError::new(self, T::NAME)) } } #[inline] fn downcast_into_exact(self) -> Result, DowncastIntoError<'py>> where T: PyTypeInfo, { if self.is_exact_instance_of::() { // Safety: is_exact_instance_of is responsible for ensuring that the type is correct Ok(unsafe { self.downcast_into_unchecked() }) } else { Err(DowncastIntoError::new(self, T::NAME)) } } #[inline] unsafe fn downcast_unchecked(&self) -> &Bound<'py, T> { &*ptr_from_ref(self).cast() } #[inline] unsafe fn downcast_into_unchecked(self) -> Bound<'py, T> { std::mem::transmute(self) } fn extract<'a, T>(&'a self) -> PyResult where T: FromPyObjectBound<'a, 'py>, { FromPyObjectBound::from_py_object_bound(self.as_borrowed()) } fn get_refcnt(&self) -> isize { unsafe { ffi::Py_REFCNT(self.as_ptr()) } } fn repr(&self) -> PyResult> { unsafe { ffi::PyObject_Repr(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } fn str(&self) -> PyResult> { unsafe { ffi::PyObject_Str(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } fn hash(&self) -> PyResult { let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) }; crate::err::error_on_minusone(self.py(), v)?; Ok(v) } fn len(&self) -> PyResult { let v = unsafe { ffi::PyObject_Size(self.as_ptr()) }; crate::err::error_on_minusone(self.py(), v)?; Ok(v as usize) } fn dir(&self) -> PyResult> { unsafe { ffi::PyObject_Dir(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[inline] fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult { let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) }; err::error_on_minusone(self.py(), result)?; Ok(result == 1) } #[inline] fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool { self.get_type().is(ty) } #[inline] fn is_instance_of(&self) -> bool { T::is_type_of_bound(self) } #[inline] fn is_exact_instance_of(&self) -> bool { T::is_exact_type_of_bound(self) } fn contains(&self, value: V) -> PyResult where V: ToPyObject, { fn inner(any: &Bound<'_, PyAny>, value: Bound<'_, PyAny>) -> PyResult { match unsafe { ffi::PySequence_Contains(any.as_ptr(), value.as_ptr()) } { 0 => Ok(false), 1 => Ok(true), _ => Err(PyErr::fetch(any.py())), } } let py = self.py(); inner(self, value.to_object(py).into_bound(py)) } #[cfg(not(any(PyPy, GraalPy)))] fn py_super(&self) -> PyResult> { PySuper::new_bound(&self.get_type(), self) } } impl<'py> Bound<'py, PyAny> { /// Retrieve an attribute value, skipping the instance dictionary during the lookup but still /// binding the object to the instance. /// /// This is useful when trying to resolve Python's "magic" methods like `__getitem__`, which /// are looked up starting from the type object. This returns an `Option` as it is not /// typically a direct error for the special lookup to fail, as magic methods are optional in /// many situations in which they might be called. /// /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used /// to intern `attr_name`. #[allow(dead_code)] // Currently only used with num-complex+abi3, so dead without that. pub(crate) fn lookup_special(&self, attr_name: N) -> PyResult>> where N: IntoPy>, { let py = self.py(); let self_type = self.get_type(); let attr = if let Ok(attr) = self_type.getattr(attr_name) { attr } else { return Ok(None); }; // Manually resolve descriptor protocol. if cfg!(Py_3_10) || unsafe { ffi::PyType_HasFeature(attr.get_type_ptr(), ffi::Py_TPFLAGS_HEAPTYPE) } != 0 { // This is the preferred faster path, but does not work on static types (generally, // types defined in extension modules) before Python 3.10. unsafe { let descr_get_ptr = ffi::PyType_GetSlot(attr.get_type_ptr(), ffi::Py_tp_descr_get); if descr_get_ptr.is_null() { return Ok(Some(attr)); } let descr_get: ffi::descrgetfunc = std::mem::transmute(descr_get_ptr); let ret = descr_get(attr.as_ptr(), self.as_ptr(), self_type.as_ptr()); ret.assume_owned_or_err(py).map(Some) } } else if let Ok(descr_get) = attr .get_type() .as_borrowed() .getattr(crate::intern!(py, "__get__")) { descr_get.call1((attr, self, self_type)).map(Some) } else { Ok(Some(attr)) } } } #[cfg(test)] mod tests { use crate::{ basic::CompareOp, types::{IntoPyDict, PyAny, PyAnyMethods, PyBool, PyList, PyLong, PyModule, PyTypeMethods}, Bound, PyTypeInfo, Python, ToPyObject, }; #[test] fn test_lookup_special() { Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class CustomCallable: def __call__(self): return 1 class SimpleInt: def __int__(self): return 1 class InheritedInt(SimpleInt): pass class NoInt: pass class NoDescriptorInt: __int__ = CustomCallable() class InstanceOverrideInt: def __int__(self): return 1 instance_override = InstanceOverrideInt() instance_override.__int__ = lambda self: 2 class ErrorInDescriptorInt: @property def __int__(self): raise ValueError("uh-oh!") class NonHeapNonDescriptorInt: # A static-typed callable that doesn't implement `__get__`. These are pretty hard to come by. __int__ = int "#, "test.py", "test", ) .unwrap(); let int = crate::intern!(py, "__int__"); let eval_int = |obj: Bound<'_, PyAny>| obj.lookup_special(int)?.unwrap().call0()?.extract::(); let simple = module.getattr("SimpleInt").unwrap().call0().unwrap(); assert_eq!(eval_int(simple).unwrap(), 1); let inherited = module.getattr("InheritedInt").unwrap().call0().unwrap(); assert_eq!(eval_int(inherited).unwrap(), 1); let no_descriptor = module.getattr("NoDescriptorInt").unwrap().call0().unwrap(); assert_eq!(eval_int(no_descriptor).unwrap(), 1); let missing = module.getattr("NoInt").unwrap().call0().unwrap(); assert!(missing.as_borrowed().lookup_special(int).unwrap().is_none()); // Note the instance override should _not_ call the instance method that returns 2, // because that's not how special lookups are meant to work. let instance_override = module.getattr("instance_override").unwrap(); assert_eq!(eval_int(instance_override).unwrap(), 1); let descriptor_error = module .getattr("ErrorInDescriptorInt") .unwrap() .call0() .unwrap(); assert!(descriptor_error.as_borrowed().lookup_special(int).is_err()); let nonheap_nondescriptor = module .getattr("NonHeapNonDescriptorInt") .unwrap() .call0() .unwrap(); assert_eq!(eval_int(nonheap_nondescriptor).unwrap(), 0); }) } #[test] fn test_call_for_non_existing_method() { Python::with_gil(|py| { let a = py.eval_bound("42", None, None).unwrap(); a.call_method0("__str__").unwrap(); // ok assert!(a.call_method("nonexistent_method", (1,), None).is_err()); assert!(a.call_method0("nonexistent_method").is_err()); assert!(a.call_method1("nonexistent_method", (1,)).is_err()); }); } #[test] fn test_call_with_kwargs() { Python::with_gil(|py| { let list = vec![3, 6, 5, 4, 7].to_object(py); let dict = vec![("reverse", true)].into_py_dict_bound(py); list.call_method_bound(py, "sort", (), Some(&dict)).unwrap(); assert_eq!(list.extract::>(py).unwrap(), vec![7, 6, 5, 4, 3]); }); } #[test] fn test_call_method0() { Python::with_gil(|py| { let module = PyModule::from_code_bound( py, r#" class SimpleClass: def foo(self): return 42 "#, file!(), "test_module", ) .expect("module creation failed"); let simple_class = module.getattr("SimpleClass").unwrap().call0().unwrap(); assert_eq!( simple_class .call_method0("foo") .unwrap() .extract::() .unwrap(), 42 ); }) } #[test] fn test_type() { Python::with_gil(|py| { let obj = py.eval_bound("42", None, None).unwrap(); assert_eq!(obj.get_type().as_type_ptr(), obj.get_type_ptr()); }); } #[test] fn test_dir() { Python::with_gil(|py| { let obj = py.eval_bound("42", None, None).unwrap(); let dir = py .eval_bound("dir(42)", None, None) .unwrap() .downcast_into::() .unwrap(); let a = obj .dir() .unwrap() .into_iter() .map(|x| x.extract::().unwrap()); let b = dir.into_iter().map(|x| x.extract::().unwrap()); assert!(a.eq(b)); }); } #[test] fn test_hasattr() { Python::with_gil(|py| { let x = 5.to_object(py).into_bound(py); assert!(x.is_instance_of::()); assert!(x.hasattr("to_bytes").unwrap()); assert!(!x.hasattr("bbbbbbytes").unwrap()); }) } #[cfg(feature = "macros")] #[test] #[allow(unknown_lints, non_local_definitions)] fn test_hasattr_error() { use crate::exceptions::PyValueError; use crate::prelude::*; #[pyclass(crate = "crate")] struct GetattrFail; #[pymethods(crate = "crate")] impl GetattrFail { fn __getattr__(&self, attr: PyObject) -> PyResult { Err(PyValueError::new_err(attr)) } } Python::with_gil(|py| { let obj = Py::new(py, GetattrFail).unwrap(); let obj = obj.bind(py).as_ref(); assert!(obj .hasattr("foo") .unwrap_err() .is_instance_of::(py)); }) } #[test] fn test_nan_eq() { Python::with_gil(|py| { let nan = py.eval_bound("float('nan')", None, None).unwrap(); assert!(nan.compare(&nan).is_err()); }); } #[test] fn test_any_is_instance_of() { Python::with_gil(|py| { let x = 5.to_object(py).into_bound(py); assert!(x.is_instance_of::()); let l = vec![&x, &x].to_object(py).into_bound(py); assert!(l.is_instance_of::()); }); } #[test] fn test_any_is_instance() { Python::with_gil(|py| { let l = vec![1u8, 2].to_object(py).into_bound(py); assert!(l.is_instance(&py.get_type_bound::()).unwrap()); }); } #[test] fn test_any_is_exact_instance_of() { Python::with_gil(|py| { let x = 5.to_object(py).into_bound(py); assert!(x.is_exact_instance_of::()); let t = PyBool::new_bound(py, true); assert!(t.is_instance_of::()); assert!(!t.is_exact_instance_of::()); assert!(t.is_exact_instance_of::()); let l = vec![&x, &x].to_object(py).into_bound(py); assert!(l.is_exact_instance_of::()); }); } #[test] fn test_any_is_exact_instance() { Python::with_gil(|py| { let t = PyBool::new_bound(py, true); assert!(t.is_instance(&py.get_type_bound::()).unwrap()); assert!(!t.is_exact_instance(&py.get_type_bound::())); assert!(t.is_exact_instance(&py.get_type_bound::())); }); } #[test] fn test_any_contains() { Python::with_gil(|py| { let v: Vec = vec![1, 1, 2, 3, 5, 8]; let ob = v.to_object(py).into_bound(py); let bad_needle = 7i32.to_object(py); assert!(!ob.contains(&bad_needle).unwrap()); let good_needle = 8i32.to_object(py); assert!(ob.contains(&good_needle).unwrap()); let type_coerced_needle = 8f32.to_object(py); assert!(ob.contains(&type_coerced_needle).unwrap()); let n: u32 = 42; let bad_haystack = n.to_object(py).into_bound(py); let irrelevant_needle = 0i32.to_object(py); assert!(bad_haystack.contains(&irrelevant_needle).is_err()); }); } // This is intentionally not a test, it's a generic function used by the tests below. fn test_eq_methods_generic(list: &[T]) where T: PartialEq + PartialOrd + ToPyObject, { Python::with_gil(|py| { for a in list { for b in list { let a_py = a.to_object(py).into_bound(py); let b_py = b.to_object(py).into_bound(py); assert_eq!( a.lt(b), a_py.lt(&b_py).unwrap(), "{} < {} should be {}.", a_py, b_py, a.lt(b) ); assert_eq!( a.le(b), a_py.le(&b_py).unwrap(), "{} <= {} should be {}.", a_py, b_py, a.le(b) ); assert_eq!( a.eq(b), a_py.eq(&b_py).unwrap(), "{} == {} should be {}.", a_py, b_py, a.eq(b) ); assert_eq!( a.ne(b), a_py.ne(&b_py).unwrap(), "{} != {} should be {}.", a_py, b_py, a.ne(b) ); assert_eq!( a.gt(b), a_py.gt(&b_py).unwrap(), "{} > {} should be {}.", a_py, b_py, a.gt(b) ); assert_eq!( a.ge(b), a_py.ge(&b_py).unwrap(), "{} >= {} should be {}.", a_py, b_py, a.ge(b) ); } } }); } #[test] fn test_eq_methods_integers() { let ints = [-4, -4, 1, 2, 0, -100, 1_000_000]; test_eq_methods_generic(&ints); } #[test] fn test_eq_methods_strings() { let strings = ["Let's", "test", "some", "eq", "methods"]; test_eq_methods_generic(&strings); } #[test] fn test_eq_methods_floats() { let floats = [ -1.0, 2.5, 0.0, 3.0, std::f64::consts::PI, 10.0, 10.0 / 3.0, -1_000_000.0, ]; test_eq_methods_generic(&floats); } #[test] fn test_eq_methods_bools() { let bools = [true, false]; test_eq_methods_generic(&bools); } #[test] fn test_rich_compare_type_error() { Python::with_gil(|py| { let py_int = 1.to_object(py).into_bound(py); let py_str = "1".to_object(py).into_bound(py); assert!(py_int.rich_compare(&py_str, CompareOp::Lt).is_err()); assert!(!py_int .rich_compare(py_str, CompareOp::Eq) .unwrap() .is_truthy() .unwrap()); }) } #[test] fn test_is_ellipsis() { Python::with_gil(|py| { let v = py .eval_bound("...", None, None) .map_err(|e| e.display(py)) .unwrap(); assert!(v.is_ellipsis()); let not_ellipsis = 5.to_object(py).into_bound(py); assert!(!not_ellipsis.is_ellipsis()); }); } #[test] fn test_is_callable() { Python::with_gil(|py| { assert!(PyList::type_object_bound(py).is_callable()); let not_callable = 5.to_object(py).into_bound(py); assert!(!not_callable.is_callable()); }); } #[test] fn test_is_empty() { Python::with_gil(|py| { let empty_list = PyList::empty_bound(py).into_any(); assert!(empty_list.is_empty().unwrap()); let list = PyList::new_bound(py, vec![1, 2, 3]).into_any(); assert!(!list.is_empty().unwrap()); let not_container = 5.to_object(py).into_bound(py); assert!(not_container.is_empty().is_err()); }); } #[cfg(feature = "macros")] #[test] #[allow(unknown_lints, non_local_definitions)] fn test_fallible_dir() { use crate::exceptions::PyValueError; use crate::prelude::*; #[pyclass(crate = "crate")] struct DirFail; #[pymethods(crate = "crate")] impl DirFail { fn __dir__(&self) -> PyResult { Err(PyValueError::new_err("uh-oh!")) } } Python::with_gil(|py| { let obj = Bound::new(py, DirFail).unwrap(); assert!(obj.dir().unwrap_err().is_instance_of::(py)); }) } } pyo3/src/types/bytes.rs0000644000175000017500000003325614661133735016073 0ustar jamespagejamespageuse crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::{Borrowed, Bound}; use crate::types::any::PyAnyMethods; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, Py, PyAny, PyResult, Python}; use std::ops::Index; use std::slice::SliceIndex; use std::str; /// Represents a Python `bytes` object. /// /// This type is immutable. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyBytes>`][Bound]. /// /// For APIs available on `bytes` objects, see the [`PyBytesMethods`] trait which is implemented for /// [`Bound<'py, PyBytes>`][Bound]. /// /// # Equality /// /// For convenience, [`Bound<'py, PyBytes>`][Bound] implements [`PartialEq<[u8]>`][PartialEq] to allow comparing the /// data in the Python bytes to a Rust `[u8]` byte slice. /// /// This is not always the most appropriate way to compare Python bytes, as Python bytes subclasses /// may have different equality semantics. In situations where subclasses overriding equality might be /// relevant, use [`PyAnyMethods::eq`], at cost of the additional overhead of a Python method call. /// /// ```rust /// # use pyo3::prelude::*; /// use pyo3::types::PyBytes; /// /// # Python::with_gil(|py| { /// let py_bytes = PyBytes::new_bound(py, b"foo".as_slice()); /// // via PartialEq<[u8]> /// assert_eq!(py_bytes, b"foo".as_slice()); /// /// // via Python equality /// let other = PyBytes::new_bound(py, b"foo".as_slice()); /// assert!(py_bytes.as_any().eq(other).unwrap()); /// /// // Note that `eq` will convert it's argument to Python using `ToPyObject`, /// // so the following does not compare equal since the slice will convert into a /// // `list`, not a `bytes` object. /// assert!(!py_bytes.as_any().eq(b"foo".as_slice()).unwrap()); /// # }); /// ``` #[repr(transparent)] pub struct PyBytes(PyAny); pyobject_native_type_core!(PyBytes, pyobject_native_static_type_object!(ffi::PyBytes_Type), #checkfunction=ffi::PyBytes_Check); impl PyBytes { /// Creates a new Python bytestring object. /// The bytestring is initialized by copying the data from the `&[u8]`. /// /// Panics if out of memory. pub fn new_bound<'p>(py: Python<'p>, s: &[u8]) -> Bound<'p, PyBytes> { let ptr = s.as_ptr().cast(); let len = s.len() as ffi::Py_ssize_t; unsafe { ffi::PyBytes_FromStringAndSize(ptr, len) .assume_owned(py) .downcast_into_unchecked() } } /// Creates a new Python `bytes` object with an `init` closure to write its contents. /// Before calling `init` the bytes' contents are zero-initialised. /// * If Python raises a MemoryError on the allocation, `new_with` will return /// it inside `Err`. /// * If `init` returns `Err(e)`, `new_with` will return `Err(e)`. /// * If `init` returns `Ok(())`, `new_with` will return `Ok(&PyBytes)`. /// /// # Examples /// /// ``` /// use pyo3::{prelude::*, types::PyBytes}; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let py_bytes = PyBytes::new_bound_with(py, 10, |bytes: &mut [u8]| { /// bytes.copy_from_slice(b"Hello Rust"); /// Ok(()) /// })?; /// let bytes: &[u8] = py_bytes.extract()?; /// assert_eq!(bytes, b"Hello Rust"); /// Ok(()) /// }) /// # } /// ``` pub fn new_bound_with(py: Python<'_>, len: usize, init: F) -> PyResult> where F: FnOnce(&mut [u8]) -> PyResult<()>, { unsafe { let pyptr = ffi::PyBytes_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t); // Check for an allocation error and return it let pybytes = pyptr.assume_owned_or_err(py)?.downcast_into_unchecked(); let buffer: *mut u8 = ffi::PyBytes_AsString(pyptr).cast(); debug_assert!(!buffer.is_null()); // Zero-initialise the uninitialised bytestring std::ptr::write_bytes(buffer, 0u8, len); // (Further) Initialise the bytestring in init // If init returns an Err, pypybytearray will automatically deallocate the buffer init(std::slice::from_raw_parts_mut(buffer, len)).map(|_| pybytes) } } /// Creates a new Python byte string object from a raw pointer and length. /// /// Panics if out of memory. /// /// # Safety /// /// This function dereferences the raw pointer `ptr` as the /// leading pointer of a slice of length `len`. [As with /// `std::slice::from_raw_parts`, this is /// unsafe](https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety). pub unsafe fn bound_from_ptr(py: Python<'_>, ptr: *const u8, len: usize) -> Bound<'_, PyBytes> { ffi::PyBytes_FromStringAndSize(ptr.cast(), len as isize) .assume_owned(py) .downcast_into_unchecked() } } #[cfg(feature = "gil-refs")] impl PyBytes { /// Deprecated form of [`PyBytes::new_bound`]. #[deprecated( since = "0.21.0", note = "`PyBytes::new` will be replaced by `PyBytes::new_bound` in a future PyO3 version" )] pub fn new<'p>(py: Python<'p>, s: &[u8]) -> &'p PyBytes { Self::new_bound(py, s).into_gil_ref() } /// Deprecated form of [`PyBytes::new_bound_with`]. #[deprecated( since = "0.21.0", note = "`PyBytes::new_with` will be replaced by `PyBytes::new_bound_with` in a future PyO3 version" )] pub fn new_with(py: Python<'_>, len: usize, init: F) -> PyResult<&PyBytes> where F: FnOnce(&mut [u8]) -> PyResult<()>, { Self::new_bound_with(py, len, init).map(Bound::into_gil_ref) } /// Deprecated form of [`PyBytes::bound_from_ptr`]. /// /// # Safety /// See [`PyBytes::bound_from_ptr`]. #[deprecated( since = "0.21.0", note = "`PyBytes::from_ptr` will be replaced by `PyBytes::bound_from_ptr` in a future PyO3 version" )] pub unsafe fn from_ptr(py: Python<'_>, ptr: *const u8, len: usize) -> &PyBytes { Self::bound_from_ptr(py, ptr, len).into_gil_ref() } /// Gets the Python string as a byte slice. #[inline] pub fn as_bytes(&self) -> &[u8] { self.as_borrowed().as_bytes() } } /// Implementation of functionality for [`PyBytes`]. /// /// These methods are defined for the `Bound<'py, PyBytes>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyBytes")] pub trait PyBytesMethods<'py>: crate::sealed::Sealed { /// Gets the Python string as a byte slice. fn as_bytes(&self) -> &[u8]; } impl<'py> PyBytesMethods<'py> for Bound<'py, PyBytes> { #[inline] fn as_bytes(&self) -> &[u8] { self.as_borrowed().as_bytes() } } impl<'a> Borrowed<'a, '_, PyBytes> { /// Gets the Python string as a byte slice. #[allow(clippy::wrong_self_convention)] pub(crate) fn as_bytes(self) -> &'a [u8] { unsafe { let buffer = ffi::PyBytes_AsString(self.as_ptr()) as *const u8; let length = ffi::PyBytes_Size(self.as_ptr()) as usize; debug_assert!(!buffer.is_null()); std::slice::from_raw_parts(buffer, length) } } } impl Py { /// Gets the Python bytes as a byte slice. Because Python bytes are /// immutable, the result may be used for as long as the reference to /// `self` is held, including when the GIL is released. pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] { self.bind_borrowed(py).as_bytes() } } /// This is the same way [Vec] is indexed. #[cfg(feature = "gil-refs")] impl> Index for PyBytes { type Output = I::Output; fn index(&self, index: I) -> &Self::Output { &self.as_bytes()[index] } } /// This is the same way [Vec] is indexed. impl> Index for Bound<'_, PyBytes> { type Output = I::Output; fn index(&self, index: I) -> &Self::Output { &self.as_bytes()[index] } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq<[u8]> for Bound<'_, PyBytes> { #[inline] fn eq(&self, other: &[u8]) -> bool { self.as_borrowed() == *other } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq<&'_ [u8]> for Bound<'_, PyBytes> { #[inline] fn eq(&self, other: &&[u8]) -> bool { self.as_borrowed() == **other } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq> for [u8] { #[inline] fn eq(&self, other: &Bound<'_, PyBytes>) -> bool { *self == other.as_borrowed() } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq<&'_ Bound<'_, PyBytes>> for [u8] { #[inline] fn eq(&self, other: &&Bound<'_, PyBytes>) -> bool { *self == other.as_borrowed() } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq> for &'_ [u8] { #[inline] fn eq(&self, other: &Bound<'_, PyBytes>) -> bool { **self == other.as_borrowed() } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq<[u8]> for &'_ Bound<'_, PyBytes> { #[inline] fn eq(&self, other: &[u8]) -> bool { self.as_borrowed() == other } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq<[u8]> for Borrowed<'_, '_, PyBytes> { #[inline] fn eq(&self, other: &[u8]) -> bool { self.as_bytes() == other } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq<&[u8]> for Borrowed<'_, '_, PyBytes> { #[inline] fn eq(&self, other: &&[u8]) -> bool { *self == **other } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq> for [u8] { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyBytes>) -> bool { other == self } } /// Compares whether the Python bytes object is equal to the [u8]. /// /// In some cases Python equality might be more appropriate; see the note on [`PyBytes`]. impl PartialEq> for &'_ [u8] { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyBytes>) -> bool { other == self } } #[cfg(test)] mod tests { use super::*; #[test] fn test_bytes_index() { Python::with_gil(|py| { let bytes = PyBytes::new_bound(py, b"Hello World"); assert_eq!(bytes[1], b'e'); }); } #[test] fn test_bound_bytes_index() { Python::with_gil(|py| { let bytes = PyBytes::new_bound(py, b"Hello World"); assert_eq!(bytes[1], b'e'); let bytes = &bytes; assert_eq!(bytes[1], b'e'); }); } #[test] fn test_bytes_new_with() -> super::PyResult<()> { Python::with_gil(|py| -> super::PyResult<()> { let py_bytes = PyBytes::new_bound_with(py, 10, |b: &mut [u8]| { b.copy_from_slice(b"Hello Rust"); Ok(()) })?; let bytes: &[u8] = py_bytes.extract()?; assert_eq!(bytes, b"Hello Rust"); Ok(()) }) } #[test] fn test_bytes_new_with_zero_initialised() -> super::PyResult<()> { Python::with_gil(|py| -> super::PyResult<()> { let py_bytes = PyBytes::new_bound_with(py, 10, |_b: &mut [u8]| Ok(()))?; let bytes: &[u8] = py_bytes.extract()?; assert_eq!(bytes, &[0; 10]); Ok(()) }) } #[test] fn test_bytes_new_with_error() { use crate::exceptions::PyValueError; Python::with_gil(|py| { let py_bytes_result = PyBytes::new_bound_with(py, 10, |_b: &mut [u8]| { Err(PyValueError::new_err("Hello Crustaceans!")) }); assert!(py_bytes_result.is_err()); assert!(py_bytes_result .err() .unwrap() .is_instance_of::(py)); }); } #[test] fn test_comparisons() { Python::with_gil(|py| { let b = b"hello, world".as_slice(); let py_bytes = PyBytes::new_bound(py, b); assert_eq!(py_bytes, b"hello, world".as_slice()); assert_eq!(py_bytes, b); assert_eq!(&py_bytes, b); assert_eq!(b, py_bytes); assert_eq!(b, &py_bytes); assert_eq!(py_bytes, *b); assert_eq!(&py_bytes, *b); assert_eq!(*b, py_bytes); assert_eq!(*b, &py_bytes); let py_string = py_bytes.as_borrowed(); assert_eq!(py_string, b); assert_eq!(&py_string, b); assert_eq!(b, py_string); assert_eq!(b, &py_string); assert_eq!(py_string, *b); assert_eq!(*b, py_string); }) } } pyo3/src/types/module.rs0000644000175000017500000005640714661133735016235 0ustar jamespagejamespageuse crate::callback::IntoPyCallbackOutput; use crate::err::{PyErr, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::py_result_ext::PyResultExt; use crate::pyclass::PyClass; use crate::types::{ any::PyAnyMethods, list::PyListMethods, PyAny, PyCFunction, PyDict, PyList, PyString, }; use crate::{exceptions, ffi, Bound, IntoPy, Py, PyObject, Python}; use std::ffi::CString; use std::str; #[cfg(feature = "gil-refs")] use {super::PyStringMethods, crate::PyNativeType}; /// Represents a Python [`module`][1] object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyModule>`][Bound]. /// /// For APIs available on `module` objects, see the [`PyModuleMethods`] trait which is implemented for /// [`Bound<'py, PyModule>`][Bound]. /// /// As with all other Python objects, modules are first class citizens. /// This means they can be passed to or returned from functions, /// created dynamically, assigned to variables and so forth. /// /// [1]: https://docs.python.org/3/tutorial/modules.html #[repr(transparent)] pub struct PyModule(PyAny); pyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), #checkfunction=ffi::PyModule_Check); impl PyModule { /// Creates a new module object with the `__name__` attribute set to `name`. /// /// # Examples /// /// ``` rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let module = PyModule::new_bound(py, "my_module")?; /// /// assert_eq!(module.name()?, "my_module"); /// Ok(()) /// })?; /// # Ok(())} /// ``` pub fn new_bound<'py>(py: Python<'py>, name: &str) -> PyResult> { // Could use PyModule_NewObject, but it doesn't exist on PyPy. let name = CString::new(name)?; unsafe { ffi::PyModule_New(name.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Imports the Python module with the specified name. /// /// # Examples /// /// ```no_run /// # fn main() { /// use pyo3::prelude::*; /// /// Python::with_gil(|py| { /// let module = PyModule::import_bound(py, "antigravity").expect("No flying for you."); /// }); /// # } /// ``` /// /// This is equivalent to the following Python expression: /// ```python /// import antigravity /// ``` pub fn import_bound(py: Python<'_>, name: N) -> PyResult> where N: IntoPy>, { let name: Py = name.into_py(py); unsafe { ffi::PyImport_Import(name.as_ptr()) .assume_owned_or_err(py) .downcast_into_unchecked() } } /// Creates and loads a module named `module_name`, /// containing the Python code passed to `code` /// and pretending to live at `file_name`. /// ///
///
⚠ ️
///
    //
    ///  Warning: This will compile and execute code. Never pass untrusted code to this function!
    ///
    /// 
/// /// # Errors /// /// Returns `PyErr` if: /// - `code` is not syntactically correct Python. /// - Any Python exceptions are raised while initializing the module. /// - Any of the arguments cannot be converted to [`CString`]s. /// /// # Example: bundle in a file at compile time with [`include_str!`][std::include_str]: /// /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// // This path is resolved relative to this file. /// let code = include_str!("../../assets/script.py"); /// /// Python::with_gil(|py| -> PyResult<()> { /// PyModule::from_code_bound(py, code, "example.py", "example")?; /// Ok(()) /// })?; /// # Ok(()) /// # } /// ``` /// /// # Example: Load a file at runtime with [`std::fs::read_to_string`]. /// /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// // This path is resolved by however the platform resolves paths, /// // which also makes this less portable. Consider using `include_str` /// // if you just want to bundle a script with your module. /// let code = std::fs::read_to_string("assets/script.py")?; /// /// Python::with_gil(|py| -> PyResult<()> { /// PyModule::from_code_bound(py, &code, "example.py", "example")?; /// Ok(()) /// })?; /// Ok(()) /// # } /// ``` pub fn from_code_bound<'py>( py: Python<'py>, code: &str, file_name: &str, module_name: &str, ) -> PyResult> { let data = CString::new(code)?; let filename = CString::new(file_name)?; let module = CString::new(module_name)?; unsafe { let code = ffi::Py_CompileString(data.as_ptr(), filename.as_ptr(), ffi::Py_file_input) .assume_owned_or_err(py)?; ffi::PyImport_ExecCodeModuleEx(module.as_ptr(), code.as_ptr(), filename.as_ptr()) .assume_owned_or_err(py) .downcast_into() } } } #[cfg(feature = "gil-refs")] impl PyModule { /// Deprecated form of [`PyModule::new_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyModule::new` will be replaced by `PyModule::new_bound` in a future PyO3 version" )] pub fn new<'py>(py: Python<'py>, name: &str) -> PyResult<&'py PyModule> { Self::new_bound(py, name).map(Bound::into_gil_ref) } /// Deprecated form of [`PyModule::import_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyModule::import` will be replaced by `PyModule::import_bound` in a future PyO3 version" )] pub fn import(py: Python<'_>, name: N) -> PyResult<&PyModule> where N: IntoPy>, { Self::import_bound(py, name).map(Bound::into_gil_ref) } /// Deprecated form of [`PyModule::from_code_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyModule::from_code` will be replaced by `PyModule::from_code_bound` in a future PyO3 version" )] pub fn from_code<'py>( py: Python<'py>, code: &str, file_name: &str, module_name: &str, ) -> PyResult<&'py PyModule> { Self::from_code_bound(py, code, file_name, module_name).map(Bound::into_gil_ref) } /// Returns the module's `__dict__` attribute, which contains the module's symbol table. pub fn dict(&self) -> &PyDict { self.as_borrowed().dict().into_gil_ref() } /// Returns the index (the `__all__` attribute) of the module, /// creating one if needed. /// /// `__all__` declares the items that will be imported with `from my_module import *`. pub fn index(&self) -> PyResult<&PyList> { self.as_borrowed().index().map(Bound::into_gil_ref) } /// Returns the name (the `__name__` attribute) of the module. /// /// May fail if the module does not have a `__name__` attribute. pub fn name(&self) -> PyResult<&str> { self.as_borrowed().name()?.into_gil_ref().to_str() } /// Returns the filename (the `__file__` attribute) of the module. /// /// May fail if the module does not have a `__file__` attribute. pub fn filename(&self) -> PyResult<&str> { self.as_borrowed().filename()?.into_gil_ref().to_str() } /// Adds an attribute to the module. /// /// For adding classes, functions or modules, prefer to use [`PyModule::add_class`], /// [`PyModule::add_function`] or [`PyModule::add_submodule`] instead, respectively. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pymodule] /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> { /// module.add("c", 299_792_458)?; /// Ok(()) /// } /// ``` /// /// Python code can then do the following: /// /// ```python /// from my_module import c /// /// print("c is", c) /// ``` /// /// This will result in the following output: /// /// ```text /// c is 299792458 /// ``` pub fn add(&self, name: &str, value: V) -> PyResult<()> where V: IntoPy, { self.as_borrowed().add(name, value) } /// Adds a new class to the module. /// /// Notice that this method does not take an argument. /// Instead, this method is *generic*, and requires us to use the /// "turbofish" syntax to specify the class we want to add. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Foo { /* fields omitted */ } /// /// #[pymodule] /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> { /// module.add_class::()?; /// Ok(()) /// } /// ``` /// /// Python code can see this class as such: /// ```python /// from my_module import Foo /// /// print("Foo is", Foo) /// ``` /// /// This will result in the following output: /// ```text /// Foo is /// ``` /// /// Note that as we haven't defined a [constructor][1], Python code can't actually /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported /// anything that can return instances of `Foo`). /// #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#constructor")] pub fn add_class(&self) -> PyResult<()> where T: PyClass, { self.as_borrowed().add_class::() } /// Adds a function or a (sub)module to a module, using the functions name as name. /// /// Prefer to use [`PyModule::add_function`] and/or [`PyModule::add_submodule`] instead. pub fn add_wrapped<'a, T>(&'a self, wrapper: &impl Fn(Python<'a>) -> T) -> PyResult<()> where T: IntoPyCallbackOutput, { self.as_borrowed().add_wrapped(wrapper) } /// Adds a submodule to a module. /// /// This is especially useful for creating module hierarchies. /// /// Note that this doesn't define a *package*, so this won't allow Python code /// to directly import submodules by using /// `from my_module import submodule`. /// For more information, see [#759][1] and [#1517][2]. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pymodule] /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> { /// let submodule = PyModule::new_bound(py, "submodule")?; /// submodule.add("super_useful_constant", "important")?; /// /// module.add_submodule(&submodule)?; /// Ok(()) /// } /// ``` /// /// Python code can then do the following: /// /// ```python /// import my_module /// /// print("super_useful_constant is", my_module.submodule.super_useful_constant) /// ``` /// /// This will result in the following output: /// /// ```text /// super_useful_constant is important /// ``` /// /// [1]: https://github.com/PyO3/pyo3/issues/759 /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021 pub fn add_submodule(&self, module: &PyModule) -> PyResult<()> { self.as_borrowed().add_submodule(&module.as_borrowed()) } /// Add a function to a module. /// /// Note that this also requires the [`wrap_pyfunction!`][2] macro /// to wrap a function annotated with [`#[pyfunction]`][1]. /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyfunction] /// fn say_hello() { /// println!("Hello world!") /// } /// #[pymodule] /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> { /// module.add_function(wrap_pyfunction!(say_hello, module)?) /// } /// ``` /// /// Python code can then do the following: /// /// ```python /// from my_module import say_hello /// /// say_hello() /// ``` /// /// This will result in the following output: /// /// ```text /// Hello world! /// ``` /// /// [1]: crate::prelude::pyfunction /// [2]: crate::wrap_pyfunction pub fn add_function<'a>(&'a self, fun: &'a PyCFunction) -> PyResult<()> { let name = fun .as_borrowed() .getattr(__name__(self.py()))? .downcast_into::()?; let name = name.to_cow()?; self.add(&name, fun) } } /// Implementation of functionality for [`PyModule`]. /// /// These methods are defined for the `Bound<'py, PyModule>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyModule")] pub trait PyModuleMethods<'py>: crate::sealed::Sealed { /// Returns the module's `__dict__` attribute, which contains the module's symbol table. fn dict(&self) -> Bound<'py, PyDict>; /// Returns the index (the `__all__` attribute) of the module, /// creating one if needed. /// /// `__all__` declares the items that will be imported with `from my_module import *`. fn index(&self) -> PyResult>; /// Returns the name (the `__name__` attribute) of the module. /// /// May fail if the module does not have a `__name__` attribute. fn name(&self) -> PyResult>; /// Returns the filename (the `__file__` attribute) of the module. /// /// May fail if the module does not have a `__file__` attribute. fn filename(&self) -> PyResult>; /// Adds an attribute to the module. /// /// For adding classes, functions or modules, prefer to use [`PyModuleMethods::add_class`], /// [`PyModuleMethods::add_function`] or [`PyModuleMethods::add_submodule`] instead, /// respectively. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pymodule] /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> { /// module.add("c", 299_792_458)?; /// Ok(()) /// } /// ``` /// /// Python code can then do the following: /// /// ```python /// from my_module import c /// /// print("c is", c) /// ``` /// /// This will result in the following output: /// /// ```text /// c is 299792458 /// ``` fn add(&self, name: N, value: V) -> PyResult<()> where N: IntoPy>, V: IntoPy; /// Adds a new class to the module. /// /// Notice that this method does not take an argument. /// Instead, this method is *generic*, and requires us to use the /// "turbofish" syntax to specify the class we want to add. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Foo { /* fields omitted */ } /// /// #[pymodule] /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> { /// module.add_class::()?; /// Ok(()) /// } /// ``` /// /// Python code can see this class as such: /// ```python /// from my_module import Foo /// /// print("Foo is", Foo) /// ``` /// /// This will result in the following output: /// ```text /// Foo is /// ``` /// /// Note that as we haven't defined a [constructor][1], Python code can't actually /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported /// anything that can return instances of `Foo`). /// #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#constructor")] fn add_class(&self) -> PyResult<()> where T: PyClass; /// Adds a function or a (sub)module to a module, using the functions name as name. /// /// Prefer to use [`PyModuleMethods::add_function`] and/or [`PyModuleMethods::add_submodule`] /// instead. fn add_wrapped(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()> where T: IntoPyCallbackOutput; /// Adds a submodule to a module. /// /// This is especially useful for creating module hierarchies. /// /// Note that this doesn't define a *package*, so this won't allow Python code /// to directly import submodules by using /// `from my_module import submodule`. /// For more information, see [#759][1] and [#1517][2]. /// /// # Examples /// /// ```rust /// use pyo3::prelude::*; /// /// #[pymodule] /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> { /// let submodule = PyModule::new_bound(py, "submodule")?; /// submodule.add("super_useful_constant", "important")?; /// /// module.add_submodule(&submodule)?; /// Ok(()) /// } /// ``` /// /// Python code can then do the following: /// /// ```python /// import my_module /// /// print("super_useful_constant is", my_module.submodule.super_useful_constant) /// ``` /// /// This will result in the following output: /// /// ```text /// super_useful_constant is important /// ``` /// /// [1]: https://github.com/PyO3/pyo3/issues/759 /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021 fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()>; /// Add a function to a module. /// /// Note that this also requires the [`wrap_pyfunction!`][2] macro /// to wrap a function annotated with [`#[pyfunction]`][1]. /// /// ```rust /// use pyo3::prelude::*; /// /// #[pyfunction] /// fn say_hello() { /// println!("Hello world!") /// } /// #[pymodule] /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> { /// module.add_function(wrap_pyfunction!(say_hello, module)?) /// } /// ``` /// /// Python code can then do the following: /// /// ```python /// from my_module import say_hello /// /// say_hello() /// ``` /// /// This will result in the following output: /// /// ```text /// Hello world! /// ``` /// /// [1]: crate::prelude::pyfunction /// [2]: crate::wrap_pyfunction fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()>; } impl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> { fn dict(&self) -> Bound<'py, PyDict> { unsafe { // PyModule_GetDict returns borrowed ptr; must make owned for safety (see #890). ffi::PyModule_GetDict(self.as_ptr()) .assume_borrowed(self.py()) .to_owned() .downcast_into_unchecked() } } fn index(&self) -> PyResult> { let __all__ = __all__(self.py()); match self.getattr(__all__) { Ok(idx) => idx.downcast_into().map_err(PyErr::from), Err(err) => { if err.is_instance_of::(self.py()) { let l = PyList::empty_bound(self.py()); self.setattr(__all__, &l).map_err(PyErr::from)?; Ok(l) } else { Err(err) } } } } fn name(&self) -> PyResult> { #[cfg(not(PyPy))] { unsafe { ffi::PyModule_GetNameObject(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } #[cfg(PyPy)] { self.dict() .get_item("__name__") .map_err(|_| exceptions::PyAttributeError::new_err("__name__"))? .downcast_into() .map_err(PyErr::from) } } fn filename(&self) -> PyResult> { #[cfg(not(PyPy))] unsafe { ffi::PyModule_GetFilenameObject(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } #[cfg(PyPy)] { self.dict() .get_item("__file__") .map_err(|_| exceptions::PyAttributeError::new_err("__file__"))? .downcast_into() .map_err(PyErr::from) } } fn add(&self, name: N, value: V) -> PyResult<()> where N: IntoPy>, V: IntoPy, { fn inner( module: &Bound<'_, PyModule>, name: Bound<'_, PyString>, value: Bound<'_, PyAny>, ) -> PyResult<()> { module .index()? .append(&name) .expect("could not append __name__ to __all__"); module.setattr(name, value.into_py(module.py())) } let py = self.py(); inner( self, name.into_py(py).into_bound(py), value.into_py(py).into_bound(py), ) } fn add_class(&self) -> PyResult<()> where T: PyClass, { let py = self.py(); self.add(T::NAME, T::lazy_type_object().get_or_try_init(py)?) } fn add_wrapped(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()> where T: IntoPyCallbackOutput, { fn inner(module: &Bound<'_, PyModule>, object: Bound<'_, PyAny>) -> PyResult<()> { let name = object.getattr(__name__(module.py()))?; module.add(name.downcast_into::()?, object) } let py = self.py(); inner(self, wrapper(py).convert(py)?.into_bound(py)) } fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()> { let name = module.name()?; self.add(name, module) } fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()> { let name = fun.getattr(__name__(self.py()))?; self.add(name.downcast_into::()?, fun) } } fn __all__(py: Python<'_>) -> &Bound<'_, PyString> { intern!(py, "__all__") } fn __name__(py: Python<'_>) -> &Bound<'_, PyString> { intern!(py, "__name__") } #[cfg(test)] mod tests { use crate::{ types::{module::PyModuleMethods, PyModule}, Python, }; #[test] fn module_import_and_name() { Python::with_gil(|py| { let builtins = PyModule::import_bound(py, "builtins").unwrap(); assert_eq!(builtins.name().unwrap(), "builtins"); }) } #[test] fn module_filename() { use crate::types::string::PyStringMethods; Python::with_gil(|py| { let site = PyModule::import_bound(py, "site").unwrap(); assert!(site .filename() .unwrap() .to_cow() .unwrap() .ends_with("site.py")); }) } } pyo3/src/types/slice.rs0000644000175000017500000001734214661133735016042 0ustar jamespagejamespageuse crate::err::{PyErr, PyResult}; use crate::ffi; use crate::ffi_ptr_ext::FfiPtrExt; use crate::types::any::PyAnyMethods; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{Bound, PyAny, PyObject, Python, ToPyObject}; /// Represents a Python `slice`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PySlice>`][Bound]. /// /// For APIs available on `slice` objects, see the [`PySliceMethods`] trait which is implemented for /// [`Bound<'py, PySlice>`][Bound]. /// /// Only `isize` indices supported at the moment by the `PySlice` object. #[repr(transparent)] pub struct PySlice(PyAny); pyobject_native_type!( PySlice, ffi::PySliceObject, pyobject_native_static_type_object!(ffi::PySlice_Type), #checkfunction=ffi::PySlice_Check ); /// Return value from [`PySliceMethods::indices`]. #[derive(Debug, Eq, PartialEq)] pub struct PySliceIndices { /// Start of the slice /// /// It can be -1 when the step is negative, otherwise it's non-negative. pub start: isize, /// End of the slice /// /// It can be -1 when the step is negative, otherwise it's non-negative. pub stop: isize, /// Increment to use when iterating the slice from `start` to `stop`. pub step: isize, /// The length of the slice calculated from the original input sequence. pub slicelength: usize, } impl PySliceIndices { /// Creates a new `PySliceIndices`. pub fn new(start: isize, stop: isize, step: isize) -> PySliceIndices { PySliceIndices { start, stop, step, slicelength: 0, } } } impl PySlice { /// Constructs a new slice with the given elements. pub fn new_bound(py: Python<'_>, start: isize, stop: isize, step: isize) -> Bound<'_, PySlice> { unsafe { ffi::PySlice_New( ffi::PyLong_FromSsize_t(start), ffi::PyLong_FromSsize_t(stop), ffi::PyLong_FromSsize_t(step), ) .assume_owned(py) .downcast_into_unchecked() } } /// Constructs a new full slice that is equivalent to `::`. pub fn full_bound(py: Python<'_>) -> Bound<'_, PySlice> { unsafe { ffi::PySlice_New(ffi::Py_None(), ffi::Py_None(), ffi::Py_None()) .assume_owned(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PySlice { /// Deprecated form of `PySlice::new_bound`. #[deprecated( since = "0.21.0", note = "`PySlice::new` will be replaced by `PySlice::new_bound` in a future PyO3 version" )] pub fn new(py: Python<'_>, start: isize, stop: isize, step: isize) -> &PySlice { Self::new_bound(py, start, stop, step).into_gil_ref() } /// Deprecated form of `PySlice::full_bound`. #[deprecated( since = "0.21.0", note = "`PySlice::full` will be replaced by `PySlice::full_bound` in a future PyO3 version" )] pub fn full(py: Python<'_>) -> &PySlice { PySlice::full_bound(py).into_gil_ref() } /// Retrieves the start, stop, and step indices from the slice object, /// assuming a sequence of length `length`, and stores the length of the /// slice in its `slicelength` member. #[inline] pub fn indices(&self, length: isize) -> PyResult { self.as_borrowed().indices(length) } } /// Implementation of functionality for [`PySlice`]. /// /// These methods are defined for the `Bound<'py, PyTuple>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PySlice")] pub trait PySliceMethods<'py>: crate::sealed::Sealed { /// Retrieves the start, stop, and step indices from the slice object, /// assuming a sequence of length `length`, and stores the length of the /// slice in its `slicelength` member. fn indices(&self, length: isize) -> PyResult; } impl<'py> PySliceMethods<'py> for Bound<'py, PySlice> { fn indices(&self, length: isize) -> PyResult { unsafe { let mut slicelength: isize = 0; let mut start: isize = 0; let mut stop: isize = 0; let mut step: isize = 0; let r = ffi::PySlice_GetIndicesEx( self.as_ptr(), length, &mut start, &mut stop, &mut step, &mut slicelength, ); if r == 0 { Ok(PySliceIndices { start, stop, step, // non-negative isize should always fit into usize slicelength: slicelength as _, }) } else { Err(PyErr::fetch(self.py())) } } } } impl ToPyObject for PySliceIndices { fn to_object(&self, py: Python<'_>) -> PyObject { PySlice::new_bound(py, self.start, self.stop, self.step).into() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_py_slice_new() { Python::with_gil(|py| { let slice = PySlice::new_bound(py, isize::MIN, isize::MAX, 1); assert_eq!( slice.getattr("start").unwrap().extract::().unwrap(), isize::MIN ); assert_eq!( slice.getattr("stop").unwrap().extract::().unwrap(), isize::MAX ); assert_eq!( slice.getattr("step").unwrap().extract::().unwrap(), 1 ); }); } #[test] fn test_py_slice_full() { Python::with_gil(|py| { let slice = PySlice::full_bound(py); assert!(slice.getattr("start").unwrap().is_none(),); assert!(slice.getattr("stop").unwrap().is_none(),); assert!(slice.getattr("step").unwrap().is_none(),); assert_eq!( slice.indices(0).unwrap(), PySliceIndices { start: 0, stop: 0, step: 1, slicelength: 0, }, ); assert_eq!( slice.indices(42).unwrap(), PySliceIndices { start: 0, stop: 42, step: 1, slicelength: 42, }, ); }); } #[test] fn test_py_slice_indices_new() { let start = 0; let stop = 0; let step = 0; assert_eq!( PySliceIndices::new(start, stop, step), PySliceIndices { start, stop, step, slicelength: 0 } ); let start = 0; let stop = 100; let step = 10; assert_eq!( PySliceIndices::new(start, stop, step), PySliceIndices { start, stop, step, slicelength: 0 } ); let start = 0; let stop = -10; let step = -1; assert_eq!( PySliceIndices::new(start, stop, step), PySliceIndices { start, stop, step, slicelength: 0 } ); let start = 0; let stop = -10; let step = 20; assert_eq!( PySliceIndices::new(start, stop, step), PySliceIndices { start, stop, step, slicelength: 0 } ); } } pyo3/src/types/string.rs0000644000175000017500000007721614661133735016257 0ustar jamespagejamespage#[cfg(not(Py_LIMITED_API))] use crate::exceptions::PyUnicodeDecodeError; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::Borrowed; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::bytes::PyBytesMethods; use crate::types::PyBytes; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, Bound, IntoPy, Py, PyAny, PyResult, Python}; use std::borrow::Cow; use std::str; /// Represents raw data backing a Python `str`. /// /// Python internally stores strings in various representations. This enumeration /// represents those variations. #[cfg(not(Py_LIMITED_API))] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum PyStringData<'a> { /// UCS1 representation. Ucs1(&'a [u8]), /// UCS2 representation. Ucs2(&'a [u16]), /// UCS4 representation. Ucs4(&'a [u32]), } #[cfg(not(Py_LIMITED_API))] impl<'a> PyStringData<'a> { /// Obtain the raw bytes backing this instance as a [u8] slice. pub fn as_bytes(&self) -> &[u8] { match self { Self::Ucs1(s) => s, Self::Ucs2(s) => unsafe { std::slice::from_raw_parts(s.as_ptr().cast(), s.len() * self.value_width_bytes()) }, Self::Ucs4(s) => unsafe { std::slice::from_raw_parts(s.as_ptr().cast(), s.len() * self.value_width_bytes()) }, } } /// Size in bytes of each value/item in the underlying slice. #[inline] pub fn value_width_bytes(&self) -> usize { match self { Self::Ucs1(_) => 1, Self::Ucs2(_) => 2, Self::Ucs4(_) => 4, } } /// Convert the raw data to a Rust string. /// /// For UCS-1 / UTF-8, returns a borrow into the original slice. For UCS-2 and UCS-4, /// returns an owned string. /// /// Returns [PyUnicodeDecodeError] if the string data isn't valid in its purported /// storage format. This should only occur for strings that were created via Python /// C APIs that skip input validation (like `PyUnicode_FromKindAndData`) and should /// never occur for strings that were created from Python code. pub fn to_string(self, py: Python<'_>) -> PyResult> { use std::ffi::CStr; match self { Self::Ucs1(data) => match str::from_utf8(data) { Ok(s) => Ok(Cow::Borrowed(s)), Err(e) => Err(PyUnicodeDecodeError::new_utf8_bound(py, data, e)?.into()), }, Self::Ucs2(data) => match String::from_utf16(data) { Ok(s) => Ok(Cow::Owned(s)), Err(e) => { let mut message = e.to_string().as_bytes().to_vec(); message.push(0); Err(PyUnicodeDecodeError::new_bound( py, ffi::c_str!("utf-16"), self.as_bytes(), 0..self.as_bytes().len(), CStr::from_bytes_with_nul(&message).unwrap(), )? .into()) } }, Self::Ucs4(data) => match data.iter().map(|&c| std::char::from_u32(c)).collect() { Some(s) => Ok(Cow::Owned(s)), None => Err(PyUnicodeDecodeError::new_bound( py, ffi::c_str!("utf-32"), self.as_bytes(), 0..self.as_bytes().len(), ffi::c_str!("error converting utf-32"), )? .into()), }, } } /// Convert the raw data to a Rust string, possibly with data loss. /// /// Invalid code points will be replaced with `U+FFFD REPLACEMENT CHARACTER`. /// /// Returns a borrow into original data, when possible, or owned data otherwise. /// /// The return value of this function should only disagree with [Self::to_string] /// when that method would error. pub fn to_string_lossy(self) -> Cow<'a, str> { match self { Self::Ucs1(data) => String::from_utf8_lossy(data), Self::Ucs2(data) => Cow::Owned(String::from_utf16_lossy(data)), Self::Ucs4(data) => Cow::Owned( data.iter() .map(|&c| std::char::from_u32(c).unwrap_or('\u{FFFD}')) .collect(), ), } } } /// Represents a Python `string` (a Unicode string object). /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyString>`][Bound]. /// /// For APIs available on `str` objects, see the [`PyStringMethods`] trait which is implemented for /// [`Bound<'py, PyString>`][Bound]. /// /// # Equality /// /// For convenience, [`Bound<'py, PyString>`] implements [`PartialEq`] to allow comparing the /// data in the Python string to a Rust UTF-8 string slice. /// /// This is not always the most appropriate way to compare Python strings, as Python string subclasses /// may have different equality semantics. In situations where subclasses overriding equality might be /// relevant, use [`PyAnyMethods::eq`], at cost of the additional overhead of a Python method call. /// /// ```rust /// # use pyo3::prelude::*; /// use pyo3::types::PyString; /// /// # Python::with_gil(|py| { /// let py_string = PyString::new_bound(py, "foo"); /// // via PartialEq /// assert_eq!(py_string, "foo"); /// /// // via Python equality /// assert!(py_string.as_any().eq("foo").unwrap()); /// # }); /// ``` #[repr(transparent)] pub struct PyString(PyAny); pyobject_native_type_core!(PyString, pyobject_native_static_type_object!(ffi::PyUnicode_Type), #checkfunction=ffi::PyUnicode_Check); impl PyString { /// Creates a new Python string object. /// /// Panics if out of memory. pub fn new_bound<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> { let ptr = s.as_ptr().cast(); let len = s.len() as ffi::Py_ssize_t; unsafe { ffi::PyUnicode_FromStringAndSize(ptr, len) .assume_owned(py) .downcast_into_unchecked() } } /// Intern the given string /// /// This will return a reference to the same Python string object if called repeatedly with the same string. /// /// Note that while this is more memory efficient than [`PyString::new_bound`], it unconditionally allocates a /// temporary Python string object and is thereby slower than [`PyString::new_bound`]. /// /// Panics if out of memory. pub fn intern_bound<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> { let ptr = s.as_ptr().cast(); let len = s.len() as ffi::Py_ssize_t; unsafe { let mut ob = ffi::PyUnicode_FromStringAndSize(ptr, len); if !ob.is_null() { ffi::PyUnicode_InternInPlace(&mut ob); } ob.assume_owned(py).downcast_into_unchecked() } } /// Attempts to create a Python string from a Python [bytes-like object]. /// /// [bytes-like object]: (https://docs.python.org/3/glossary.html#term-bytes-like-object). pub fn from_object_bound<'py>( src: &Bound<'py, PyAny>, encoding: &str, errors: &str, ) -> PyResult> { unsafe { ffi::PyUnicode_FromEncodedObject( src.as_ptr(), encoding.as_ptr().cast(), errors.as_ptr().cast(), ) .assume_owned_or_err(src.py()) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyString { /// Deprecated form of [`PyString::new_bound`]. #[deprecated( since = "0.21.0", note = "`PyString::new` will be replaced by `PyString::new_bound` in a future PyO3 version" )] pub fn new<'py>(py: Python<'py>, s: &str) -> &'py Self { Self::new_bound(py, s).into_gil_ref() } /// Deprecated form of [`PyString::intern_bound`]. #[deprecated( since = "0.21.0", note = "`PyString::intern` will be replaced by `PyString::intern_bound` in a future PyO3 version" )] pub fn intern<'py>(py: Python<'py>, s: &str) -> &'py Self { Self::intern_bound(py, s).into_gil_ref() } /// Deprecated form of [`PyString::from_object_bound`]. #[deprecated( since = "0.21.0", note = "`PyString::from_object` will be replaced by `PyString::from_object_bound` in a future PyO3 version" )] pub fn from_object<'py>(src: &'py PyAny, encoding: &str, errors: &str) -> PyResult<&'py Self> { Self::from_object_bound(&src.as_borrowed(), encoding, errors).map(Bound::into_gil_ref) } /// Gets the Python string as a Rust UTF-8 string slice. /// /// Returns a `UnicodeEncodeError` if the input is not valid unicode /// (containing unpaired surrogates). pub fn to_str(&self) -> PyResult<&str> { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] { self.as_borrowed().to_str() } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] { let bytes = self.as_borrowed().encode_utf8()?.into_gil_ref(); Ok(unsafe { std::str::from_utf8_unchecked(bytes.as_bytes()) }) } } /// Converts the `PyString` into a Rust string, avoiding copying when possible. /// /// Returns a `UnicodeEncodeError` if the input is not valid unicode /// (containing unpaired surrogates). pub fn to_cow(&self) -> PyResult> { self.as_borrowed().to_cow() } /// Converts the `PyString` into a Rust string. /// /// Unpaired surrogates invalid UTF-8 sequences are /// replaced with `U+FFFD REPLACEMENT CHARACTER`. pub fn to_string_lossy(&self) -> Cow<'_, str> { self.as_borrowed().to_string_lossy() } /// Obtains the raw data backing the Python string. /// /// If the Python string object was created through legacy APIs, its internal storage format /// will be canonicalized before data is returned. /// /// # Safety /// /// This function implementation relies on manually decoding a C bitfield. In practice, this /// works well on common little-endian architectures such as x86_64, where the bitfield has a /// common representation (even if it is not part of the C spec). The PyO3 CI tests this API on /// x86_64 platforms. /// /// By using this API, you accept responsibility for testing that PyStringData behaves as /// expected on the targets where you plan to distribute your software. #[cfg(not(any(Py_LIMITED_API, GraalPy, PyPy)))] pub unsafe fn data(&self) -> PyResult> { self.as_borrowed().data() } } /// Implementation of functionality for [`PyString`]. /// /// These methods are defined for the `Bound<'py, PyString>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyString")] pub trait PyStringMethods<'py>: crate::sealed::Sealed { /// Gets the Python string as a Rust UTF-8 string slice. /// /// Returns a `UnicodeEncodeError` if the input is not valid unicode /// (containing unpaired surrogates). #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn to_str(&self) -> PyResult<&str>; /// Converts the `PyString` into a Rust string, avoiding copying when possible. /// /// Returns a `UnicodeEncodeError` if the input is not valid unicode /// (containing unpaired surrogates). fn to_cow(&self) -> PyResult>; /// Converts the `PyString` into a Rust string. /// /// Unpaired surrogates invalid UTF-8 sequences are /// replaced with `U+FFFD REPLACEMENT CHARACTER`. fn to_string_lossy(&self) -> Cow<'_, str>; /// Encodes this string as a Python `bytes` object, using UTF-8 encoding. fn encode_utf8(&self) -> PyResult>; /// Obtains the raw data backing the Python string. /// /// If the Python string object was created through legacy APIs, its internal storage format /// will be canonicalized before data is returned. /// /// # Safety /// /// This function implementation relies on manually decoding a C bitfield. In practice, this /// works well on common little-endian architectures such as x86_64, where the bitfield has a /// common representation (even if it is not part of the C spec). The PyO3 CI tests this API on /// x86_64 platforms. /// /// By using this API, you accept responsibility for testing that PyStringData behaves as /// expected on the targets where you plan to distribute your software. #[cfg(not(any(Py_LIMITED_API, GraalPy, PyPy)))] unsafe fn data(&self) -> PyResult>; } impl<'py> PyStringMethods<'py> for Bound<'py, PyString> { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] fn to_str(&self) -> PyResult<&str> { self.as_borrowed().to_str() } fn to_cow(&self) -> PyResult> { self.as_borrowed().to_cow() } fn to_string_lossy(&self) -> Cow<'_, str> { self.as_borrowed().to_string_lossy() } fn encode_utf8(&self) -> PyResult> { unsafe { ffi::PyUnicode_AsUTF8String(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked::() } } #[cfg(not(any(Py_LIMITED_API, GraalPy, PyPy)))] unsafe fn data(&self) -> PyResult> { self.as_borrowed().data() } } impl<'a> Borrowed<'a, '_, PyString> { #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] #[allow(clippy::wrong_self_convention)] pub(crate) fn to_str(self) -> PyResult<&'a str> { // PyUnicode_AsUTF8AndSize only available on limited API starting with 3.10. let mut size: ffi::Py_ssize_t = 0; let data: *const u8 = unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size).cast() }; if data.is_null() { Err(crate::PyErr::fetch(self.py())) } else { Ok(unsafe { std::str::from_utf8_unchecked(std::slice::from_raw_parts(data, size as usize)) }) } } #[allow(clippy::wrong_self_convention)] pub(crate) fn to_cow(self) -> PyResult> { // TODO: this method can probably be deprecated once Python 3.9 support is dropped, // because all versions then support the more efficient `to_str`. #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] { self.to_str().map(Cow::Borrowed) } #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] { let bytes = self.encode_utf8()?; Ok(Cow::Owned( unsafe { str::from_utf8_unchecked(bytes.as_bytes()) }.to_owned(), )) } } #[allow(clippy::wrong_self_convention)] fn to_string_lossy(self) -> Cow<'a, str> { let ptr = self.as_ptr(); let py = self.py(); #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] if let Ok(s) = self.to_str() { return Cow::Borrowed(s); } let bytes = unsafe { ffi::PyUnicode_AsEncodedString( ptr, ffi::c_str!("utf-8").as_ptr(), ffi::c_str!("surrogatepass").as_ptr(), ) .assume_owned(py) .downcast_into_unchecked::() }; Cow::Owned(String::from_utf8_lossy(bytes.as_bytes()).into_owned()) } #[cfg(not(any(Py_LIMITED_API, GraalPy, PyPy)))] unsafe fn data(self) -> PyResult> { let ptr = self.as_ptr(); #[cfg(not(Py_3_12))] #[allow(deprecated)] { let ready = ffi::PyUnicode_READY(ptr); if ready != 0 { // Exception was created on failure. return Err(crate::PyErr::fetch(self.py())); } } // The string should be in its canonical form after calling `PyUnicode_READY()`. // And non-canonical form not possible after Python 3.12. So it should be safe // to call these APIs. let length = ffi::PyUnicode_GET_LENGTH(ptr) as usize; let raw_data = ffi::PyUnicode_DATA(ptr); let kind = ffi::PyUnicode_KIND(ptr); match kind { ffi::PyUnicode_1BYTE_KIND => Ok(PyStringData::Ucs1(std::slice::from_raw_parts( raw_data as *const u8, length, ))), ffi::PyUnicode_2BYTE_KIND => Ok(PyStringData::Ucs2(std::slice::from_raw_parts( raw_data as *const u16, length, ))), ffi::PyUnicode_4BYTE_KIND => Ok(PyStringData::Ucs4(std::slice::from_raw_parts( raw_data as *const u32, length, ))), _ => unreachable!(), } } } impl Py { /// Gets the Python string as a Rust UTF-8 string slice. /// /// Returns a `UnicodeEncodeError` if the input is not valid unicode /// (containing unpaired surrogates). /// /// Because `str` objects are immutable, the returned slice is independent of /// the GIL lifetime. #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] pub fn to_str<'a>(&'a self, py: Python<'_>) -> PyResult<&'a str> { self.bind_borrowed(py).to_str() } /// Converts the `PyString` into a Rust string, avoiding copying when possible. /// /// Returns a `UnicodeEncodeError` if the input is not valid unicode /// (containing unpaired surrogates). /// /// Because `str` objects are immutable, the returned slice is independent of /// the GIL lifetime. pub fn to_cow<'a>(&'a self, py: Python<'_>) -> PyResult> { self.bind_borrowed(py).to_cow() } /// Converts the `PyString` into a Rust string. /// /// Unpaired surrogates invalid UTF-8 sequences are /// replaced with `U+FFFD REPLACEMENT CHARACTER`. /// /// Because `str` objects are immutable, the returned slice is independent of /// the GIL lifetime. pub fn to_string_lossy<'a>(&'a self, py: Python<'_>) -> Cow<'a, str> { self.bind_borrowed(py).to_string_lossy() } } impl IntoPy> for Bound<'_, PyString> { fn into_py(self, _py: Python<'_>) -> Py { self.unbind() } } impl IntoPy> for &Bound<'_, PyString> { fn into_py(self, _py: Python<'_>) -> Py { self.clone().unbind() } } impl IntoPy> for &'_ Py { fn into_py(self, py: Python<'_>) -> Py { self.clone_ref(py) } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq for Bound<'_, PyString> { #[inline] fn eq(&self, other: &str) -> bool { self.as_borrowed() == *other } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq<&'_ str> for Bound<'_, PyString> { #[inline] fn eq(&self, other: &&str) -> bool { self.as_borrowed() == **other } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq> for str { #[inline] fn eq(&self, other: &Bound<'_, PyString>) -> bool { *self == other.as_borrowed() } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq<&'_ Bound<'_, PyString>> for str { #[inline] fn eq(&self, other: &&Bound<'_, PyString>) -> bool { *self == other.as_borrowed() } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq> for &'_ str { #[inline] fn eq(&self, other: &Bound<'_, PyString>) -> bool { **self == other.as_borrowed() } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq for &'_ Bound<'_, PyString> { #[inline] fn eq(&self, other: &str) -> bool { self.as_borrowed() == other } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq for Borrowed<'_, '_, PyString> { #[inline] fn eq(&self, other: &str) -> bool { #[cfg(not(Py_3_13))] { self.to_cow().map_or(false, |s| s == other) } #[cfg(Py_3_13)] unsafe { ffi::PyUnicode_EqualToUTF8AndSize( self.as_ptr(), other.as_ptr().cast(), other.len() as _, ) == 1 } } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq<&str> for Borrowed<'_, '_, PyString> { #[inline] fn eq(&self, other: &&str) -> bool { *self == **other } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq> for str { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyString>) -> bool { other == self } } /// Compares whether the data in the Python string is equal to the given UTF8. /// /// In some cases Python equality might be more appropriate; see the note on [`PyString`]. impl PartialEq> for &'_ str { #[inline] fn eq(&self, other: &Borrowed<'_, '_, PyString>) -> bool { other == self } } #[cfg(test)] mod tests { use super::*; use crate::{PyObject, ToPyObject}; #[test] fn test_to_cow_utf8() { Python::with_gil(|py| { let s = "ascii 🐈"; let py_string = PyString::new_bound(py, s); assert_eq!(s, py_string.to_cow().unwrap()); }) } #[test] fn test_to_cow_surrogate() { Python::with_gil(|py| { let py_string = py .eval_bound(r"'\ud800'", None, None) .unwrap() .downcast_into::() .unwrap(); assert!(py_string.to_cow().is_err()); }) } #[test] fn test_to_cow_unicode() { Python::with_gil(|py| { let s = "哈哈🐈"; let py_string = PyString::new_bound(py, s); assert_eq!(s, py_string.to_cow().unwrap()); }) } #[test] fn test_encode_utf8_unicode() { Python::with_gil(|py| { let s = "哈哈🐈"; let obj = PyString::new_bound(py, s); assert_eq!(s.as_bytes(), obj.encode_utf8().unwrap().as_bytes()); }) } #[test] fn test_encode_utf8_surrogate() { Python::with_gil(|py| { let obj: PyObject = py.eval_bound(r"'\ud800'", None, None).unwrap().into(); assert!(obj .bind(py) .downcast::() .unwrap() .encode_utf8() .is_err()); }) } #[test] fn test_to_string_lossy() { Python::with_gil(|py| { let py_string = py .eval_bound(r"'🐈 Hello \ud800World'", None, None) .unwrap() .downcast_into::() .unwrap(); assert_eq!(py_string.to_string_lossy(), "🐈 Hello ���World"); }) } #[test] fn test_debug_string() { Python::with_gil(|py| { let v = "Hello\n".to_object(py); let s = v.downcast_bound::(py).unwrap(); assert_eq!(format!("{:?}", s), "'Hello\\n'"); }) } #[test] fn test_display_string() { Python::with_gil(|py| { let v = "Hello\n".to_object(py); let s = v.downcast_bound::(py).unwrap(); assert_eq!(format!("{}", s), "Hello\n"); }) } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy)))] fn test_string_data_ucs1() { Python::with_gil(|py| { let s = PyString::new_bound(py, "hello, world"); let data = unsafe { s.data().unwrap() }; assert_eq!(data, PyStringData::Ucs1(b"hello, world")); assert_eq!(data.to_string(py).unwrap(), Cow::Borrowed("hello, world")); assert_eq!(data.to_string_lossy(), Cow::Borrowed("hello, world")); }) } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy)))] fn test_string_data_ucs1_invalid() { Python::with_gil(|py| { // 0xfe is not allowed in UTF-8. let buffer = b"f\xfe\0"; let ptr = unsafe { crate::ffi::PyUnicode_FromKindAndData( crate::ffi::PyUnicode_1BYTE_KIND as _, buffer.as_ptr().cast(), 2, ) }; assert!(!ptr.is_null()); let s = unsafe { ptr.assume_owned(py).downcast_into_unchecked::() }; let data = unsafe { s.data().unwrap() }; assert_eq!(data, PyStringData::Ucs1(b"f\xfe")); let err = data.to_string(py).unwrap_err(); assert!(err .get_type_bound(py) .is(&py.get_type_bound::())); assert!(err .to_string() .contains("'utf-8' codec can't decode byte 0xfe in position 1")); assert_eq!(data.to_string_lossy(), Cow::Borrowed("f�")); }); } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy)))] fn test_string_data_ucs2() { Python::with_gil(|py| { let s = py.eval_bound("'foo\\ud800'", None, None).unwrap(); let py_string = s.downcast::().unwrap(); let data = unsafe { py_string.data().unwrap() }; assert_eq!(data, PyStringData::Ucs2(&[102, 111, 111, 0xd800])); assert_eq!( data.to_string_lossy(), Cow::Owned::("foo�".to_string()) ); }) } #[test] #[cfg(all(not(any(Py_LIMITED_API, PyPy)), target_endian = "little"))] fn test_string_data_ucs2_invalid() { Python::with_gil(|py| { // U+FF22 (valid) & U+d800 (never valid) let buffer = b"\x22\xff\x00\xd8\x00\x00"; let ptr = unsafe { crate::ffi::PyUnicode_FromKindAndData( crate::ffi::PyUnicode_2BYTE_KIND as _, buffer.as_ptr().cast(), 2, ) }; assert!(!ptr.is_null()); let s = unsafe { ptr.assume_owned(py).downcast_into_unchecked::() }; let data = unsafe { s.data().unwrap() }; assert_eq!(data, PyStringData::Ucs2(&[0xff22, 0xd800])); let err = data.to_string(py).unwrap_err(); assert!(err .get_type_bound(py) .is(&py.get_type_bound::())); assert!(err .to_string() .contains("'utf-16' codec can't decode bytes in position 0-3")); assert_eq!(data.to_string_lossy(), Cow::Owned::("B�".into())); }); } #[test] #[cfg(not(any(Py_LIMITED_API, PyPy)))] fn test_string_data_ucs4() { Python::with_gil(|py| { let s = "哈哈🐈"; let py_string = PyString::new_bound(py, s); let data = unsafe { py_string.data().unwrap() }; assert_eq!(data, PyStringData::Ucs4(&[21704, 21704, 128008])); assert_eq!(data.to_string_lossy(), Cow::Owned::(s.to_string())); }) } #[test] #[cfg(all(not(any(Py_LIMITED_API, PyPy)), target_endian = "little"))] fn test_string_data_ucs4_invalid() { Python::with_gil(|py| { // U+20000 (valid) & U+d800 (never valid) let buffer = b"\x00\x00\x02\x00\x00\xd8\x00\x00\x00\x00\x00\x00"; let ptr = unsafe { crate::ffi::PyUnicode_FromKindAndData( crate::ffi::PyUnicode_4BYTE_KIND as _, buffer.as_ptr().cast(), 2, ) }; assert!(!ptr.is_null()); let s = unsafe { ptr.assume_owned(py).downcast_into_unchecked::() }; let data = unsafe { s.data().unwrap() }; assert_eq!(data, PyStringData::Ucs4(&[0x20000, 0xd800])); let err = data.to_string(py).unwrap_err(); assert!(err .get_type_bound(py) .is(&py.get_type_bound::())); assert!(err .to_string() .contains("'utf-32' codec can't decode bytes in position 0-7")); assert_eq!(data.to_string_lossy(), Cow::Owned::("𠀀�".into())); }); } #[test] fn test_intern_string() { Python::with_gil(|py| { let py_string1 = PyString::intern_bound(py, "foo"); assert_eq!(py_string1, "foo"); let py_string2 = PyString::intern_bound(py, "foo"); assert_eq!(py_string2, "foo"); assert_eq!(py_string1.as_ptr(), py_string2.as_ptr()); let py_string3 = PyString::intern_bound(py, "bar"); assert_eq!(py_string3, "bar"); assert_ne!(py_string1.as_ptr(), py_string3.as_ptr()); }); } #[test] fn test_py_to_str_utf8() { Python::with_gil(|py| { let s = "ascii 🐈"; let py_string: Py = PyString::new_bound(py, s).into_py(py); #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] assert_eq!(s, py_string.to_str(py).unwrap()); assert_eq!(s, py_string.to_cow(py).unwrap()); }) } #[test] fn test_py_to_str_surrogate() { Python::with_gil(|py| { let py_string: Py = py .eval_bound(r"'\ud800'", None, None) .unwrap() .extract() .unwrap(); #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] assert!(py_string.to_str(py).is_err()); assert!(py_string.to_cow(py).is_err()); }) } #[test] fn test_py_to_string_lossy() { Python::with_gil(|py| { let py_string: Py = py .eval_bound(r"'🐈 Hello \ud800World'", None, None) .unwrap() .extract() .unwrap(); assert_eq!(py_string.to_string_lossy(py), "🐈 Hello ���World"); }) } #[test] fn test_comparisons() { Python::with_gil(|py| { let s = "hello, world"; let py_string = PyString::new_bound(py, s); assert_eq!(py_string, "hello, world"); assert_eq!(py_string, s); assert_eq!(&py_string, s); assert_eq!(s, py_string); assert_eq!(s, &py_string); assert_eq!(py_string, *s); assert_eq!(&py_string, *s); assert_eq!(*s, py_string); assert_eq!(*s, &py_string); let py_string = py_string.as_borrowed(); assert_eq!(py_string, s); assert_eq!(&py_string, s); assert_eq!(s, py_string); assert_eq!(s, &py_string); assert_eq!(py_string, *s); assert_eq!(*s, py_string); }) } } pyo3/src/types/complex.rs0000644000175000017500000002522214661133735016406 0ustar jamespagejamespage#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] use crate::py_result_ext::PyResultExt; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, types::any::PyAnyMethods, Bound, PyAny, Python}; use std::os::raw::c_double; /// Represents a Python [`complex`](https://docs.python.org/3/library/functions.html#complex) object. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyComplex>`][Bound]. /// /// For APIs available on `complex` objects, see the [`PyComplexMethods`] trait which is implemented for /// [`Bound<'py, PyComplex>`][Bound]. /// /// Note that `PyComplex` supports only basic operations. For advanced operations /// consider using [num-complex](https://docs.rs/num-complex)'s [`Complex`] type instead. /// This optional dependency can be activated with the `num-complex` feature flag. /// /// [`Complex`]: https://docs.rs/num-complex/latest/num_complex/struct.Complex.html #[repr(transparent)] pub struct PyComplex(PyAny); pyobject_native_type!( PyComplex, ffi::PyComplexObject, pyobject_native_static_type_object!(ffi::PyComplex_Type), #checkfunction=ffi::PyComplex_Check ); impl PyComplex { /// Creates a new `PyComplex` from the given real and imaginary values. pub fn from_doubles_bound( py: Python<'_>, real: c_double, imag: c_double, ) -> Bound<'_, PyComplex> { use crate::ffi_ptr_ext::FfiPtrExt; unsafe { ffi::PyComplex_FromDoubles(real, imag) .assume_owned(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyComplex { /// Deprecated form of [`PyComplex::from_doubles_bound`] #[deprecated( since = "0.21.0", note = "`PyComplex::from_doubles` will be replaced by `PyComplex::from_doubles_bound` in a future PyO3 version" )] pub fn from_doubles(py: Python<'_>, real: c_double, imag: c_double) -> &PyComplex { Self::from_doubles_bound(py, real, imag).into_gil_ref() } /// Returns the real part of the complex number. pub fn real(&self) -> c_double { self.as_borrowed().real() } /// Returns the imaginary part of the complex number. pub fn imag(&self) -> c_double { self.as_borrowed().imag() } } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] mod not_limited_impls { use crate::Borrowed; use super::*; use std::ops::{Add, Div, Mul, Neg, Sub}; #[cfg(feature = "gil-refs")] impl PyComplex { /// Returns `|self|`. pub fn abs(&self) -> c_double { self.as_borrowed().abs() } /// Returns `self` raised to the power of `other`. pub fn pow<'py>(&'py self, other: &'py PyComplex) -> &'py PyComplex { self.as_borrowed().pow(&other.as_borrowed()).into_gil_ref() } } macro_rules! bin_ops { ($trait:ident, $fn:ident, $op:tt) => { impl<'py> $trait for Borrowed<'_, 'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn $fn(self, other: Self) -> Self::Output { PyAnyMethods::$fn(self.as_any(), other) .downcast_into().expect( concat!("Complex method ", stringify!($fn), " failed.") ) } } #[cfg(feature = "gil-refs")] impl<'py> $trait for &'py PyComplex { type Output = &'py PyComplex; fn $fn(self, other: &'py PyComplex) -> &'py PyComplex { (self.as_borrowed() $op other.as_borrowed()).into_gil_ref() } } impl<'py> $trait for &Bound<'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn $fn(self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> { self.as_borrowed() $op other.as_borrowed() } } impl<'py> $trait> for &Bound<'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn $fn(self, other: Bound<'py, PyComplex>) -> Bound<'py, PyComplex> { self.as_borrowed() $op other.as_borrowed() } } impl<'py> $trait for Bound<'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn $fn(self, other: Bound<'py, PyComplex>) -> Bound<'py, PyComplex> { self.as_borrowed() $op other.as_borrowed() } } impl<'py> $trait<&Self> for Bound<'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn $fn(self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> { self.as_borrowed() $op other.as_borrowed() } } }; } bin_ops!(Add, add, +); bin_ops!(Sub, sub, -); bin_ops!(Mul, mul, *); bin_ops!(Div, div, /); #[cfg(feature = "gil-refs")] impl<'py> Neg for &'py PyComplex { type Output = &'py PyComplex; fn neg(self) -> &'py PyComplex { (-self.as_borrowed()).into_gil_ref() } } impl<'py> Neg for Borrowed<'_, 'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn neg(self) -> Self::Output { PyAnyMethods::neg(self.as_any()) .downcast_into() .expect("Complex method __neg__ failed.") } } impl<'py> Neg for &Bound<'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn neg(self) -> Bound<'py, PyComplex> { -self.as_borrowed() } } impl<'py> Neg for Bound<'py, PyComplex> { type Output = Bound<'py, PyComplex>; fn neg(self) -> Bound<'py, PyComplex> { -self.as_borrowed() } } #[cfg(test)] mod tests { use super::PyComplex; use crate::{types::complex::PyComplexMethods, Python}; use assert_approx_eq::assert_approx_eq; #[test] fn test_add() { Python::with_gil(|py| { let l = PyComplex::from_doubles_bound(py, 3.0, 1.2); let r = PyComplex::from_doubles_bound(py, 1.0, 2.6); let res = l + r; assert_approx_eq!(res.real(), 4.0); assert_approx_eq!(res.imag(), 3.8); }); } #[test] fn test_sub() { Python::with_gil(|py| { let l = PyComplex::from_doubles_bound(py, 3.0, 1.2); let r = PyComplex::from_doubles_bound(py, 1.0, 2.6); let res = l - r; assert_approx_eq!(res.real(), 2.0); assert_approx_eq!(res.imag(), -1.4); }); } #[test] fn test_mul() { Python::with_gil(|py| { let l = PyComplex::from_doubles_bound(py, 3.0, 1.2); let r = PyComplex::from_doubles_bound(py, 1.0, 2.6); let res = l * r; assert_approx_eq!(res.real(), -0.12); assert_approx_eq!(res.imag(), 9.0); }); } #[test] fn test_div() { Python::with_gil(|py| { let l = PyComplex::from_doubles_bound(py, 3.0, 1.2); let r = PyComplex::from_doubles_bound(py, 1.0, 2.6); let res = l / r; assert_approx_eq!(res.real(), 0.788_659_793_814_432_9); assert_approx_eq!(res.imag(), -0.850_515_463_917_525_7); }); } #[test] fn test_neg() { Python::with_gil(|py| { let val = PyComplex::from_doubles_bound(py, 3.0, 1.2); let res = -val; assert_approx_eq!(res.real(), -3.0); assert_approx_eq!(res.imag(), -1.2); }); } #[test] fn test_abs() { Python::with_gil(|py| { let val = PyComplex::from_doubles_bound(py, 3.0, 1.2); assert_approx_eq!(val.abs(), 3.231_098_884_280_702_2); }); } #[test] fn test_pow() { Python::with_gil(|py| { let l = PyComplex::from_doubles_bound(py, 3.0, 1.2); let r = PyComplex::from_doubles_bound(py, 1.2, 2.6); let val = l.pow(&r); assert_approx_eq!(val.real(), -1.419_309_997_016_603_7); assert_approx_eq!(val.imag(), -0.541_297_466_033_544_6); }); } } } /// Implementation of functionality for [`PyComplex`]. /// /// These methods are defined for the `Bound<'py, PyComplex>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyComplex")] pub trait PyComplexMethods<'py>: crate::sealed::Sealed { /// Returns the real part of the complex number. fn real(&self) -> c_double; /// Returns the imaginary part of the complex number. fn imag(&self) -> c_double; /// Returns `|self|`. #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn abs(&self) -> c_double; /// Returns `self` raised to the power of `other`. #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex>; } impl<'py> PyComplexMethods<'py> for Bound<'py, PyComplex> { fn real(&self) -> c_double { unsafe { ffi::PyComplex_RealAsDouble(self.as_ptr()) } } fn imag(&self) -> c_double { unsafe { ffi::PyComplex_ImagAsDouble(self.as_ptr()) } } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn abs(&self) -> c_double { PyAnyMethods::abs(self.as_any()) .downcast_into() .expect("Complex method __abs__ failed.") .extract() .expect("Failed to extract to c double.") } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> { Python::with_gil(|py| { PyAnyMethods::pow(self.as_any(), other, py.None()) .downcast_into() .expect("Complex method __pow__ failed.") }) } } #[cfg(test)] mod tests { use super::PyComplex; use crate::{types::complex::PyComplexMethods, Python}; use assert_approx_eq::assert_approx_eq; #[test] fn test_from_double() { use assert_approx_eq::assert_approx_eq; Python::with_gil(|py| { let complex = PyComplex::from_doubles_bound(py, 3.0, 1.2); assert_approx_eq!(complex.real(), 3.0); assert_approx_eq!(complex.imag(), 1.2); }); } } pyo3/src/types/dict.rs0000644000175000017500000013741414661133735015671 0ustar jamespagejamespageuse super::PyMapping; use crate::err::{self, PyErr, PyResult}; use crate::ffi::Py_ssize_t; use crate::ffi_ptr_ext::FfiPtrExt; use crate::instance::{Borrowed, Bound}; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::{PyAny, PyList}; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ffi, Python, ToPyObject}; /// Represents a Python `dict`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyDict>`][Bound]. /// /// For APIs available on `dict` objects, see the [`PyDictMethods`] trait which is implemented for /// [`Bound<'py, PyDict>`][Bound]. #[repr(transparent)] pub struct PyDict(PyAny); pyobject_native_type!( PyDict, ffi::PyDictObject, pyobject_native_static_type_object!(ffi::PyDict_Type), #checkfunction=ffi::PyDict_Check ); /// Represents a Python `dict_keys`. #[cfg(not(any(PyPy, GraalPy)))] #[repr(transparent)] pub struct PyDictKeys(PyAny); #[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type_core!( PyDictKeys, pyobject_native_static_type_object!(ffi::PyDictKeys_Type), #checkfunction=ffi::PyDictKeys_Check ); /// Represents a Python `dict_values`. #[cfg(not(any(PyPy, GraalPy)))] #[repr(transparent)] pub struct PyDictValues(PyAny); #[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type_core!( PyDictValues, pyobject_native_static_type_object!(ffi::PyDictValues_Type), #checkfunction=ffi::PyDictValues_Check ); /// Represents a Python `dict_items`. #[cfg(not(any(PyPy, GraalPy)))] #[repr(transparent)] pub struct PyDictItems(PyAny); #[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type_core!( PyDictItems, pyobject_native_static_type_object!(ffi::PyDictItems_Type), #checkfunction=ffi::PyDictItems_Check ); impl PyDict { /// Creates a new empty dictionary. pub fn new_bound(py: Python<'_>) -> Bound<'_, PyDict> { unsafe { ffi::PyDict_New().assume_owned(py).downcast_into_unchecked() } } /// Creates a new dictionary from the sequence given. /// /// The sequence must consist of `(PyObject, PyObject)`. This is /// equivalent to `dict([("a", 1), ("b", 2)])`. /// /// Returns an error on invalid input. In the case of key collisions, /// this keeps the last entry seen. #[cfg(not(any(PyPy, GraalPy)))] pub fn from_sequence_bound<'py>(seq: &Bound<'py, PyAny>) -> PyResult> { let py = seq.py(); let dict = Self::new_bound(py); err::error_on_minusone(py, unsafe { ffi::PyDict_MergeFromSeq2(dict.as_ptr(), seq.as_ptr(), 1) })?; Ok(dict) } } #[cfg(feature = "gil-refs")] impl PyDict { /// Deprecated form of [`new_bound`][PyDict::new_bound]. #[deprecated( since = "0.21.0", note = "`PyDict::new` will be replaced by `PyDict::new_bound` in a future PyO3 version" )] #[inline] pub fn new(py: Python<'_>) -> &PyDict { Self::new_bound(py).into_gil_ref() } /// Deprecated form of [`from_sequence_bound`][PyDict::from_sequence_bound]. #[deprecated( since = "0.21.0", note = "`PyDict::from_sequence` will be replaced by `PyDict::from_sequence_bound` in a future PyO3 version" )] #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub fn from_sequence(seq: &PyAny) -> PyResult<&PyDict> { Self::from_sequence_bound(&seq.as_borrowed()).map(Bound::into_gil_ref) } /// Returns a new dictionary that contains the same key-value pairs as self. /// /// This is equivalent to the Python expression `self.copy()`. pub fn copy(&self) -> PyResult<&PyDict> { self.as_borrowed().copy().map(Bound::into_gil_ref) } /// Empties an existing dictionary of all key-value pairs. pub fn clear(&self) { self.as_borrowed().clear() } /// Return the number of items in the dictionary. /// /// This is equivalent to the Python expression `len(self)`. pub fn len(&self) -> usize { self.as_borrowed().len() } /// Checks if the dict is empty, i.e. `len(self) == 0`. pub fn is_empty(&self) -> bool { self.as_borrowed().is_empty() } /// Determines if the dictionary contains the specified key. /// /// This is equivalent to the Python expression `key in self`. pub fn contains(&self, key: K) -> PyResult where K: ToPyObject, { self.as_borrowed().contains(key) } /// Gets an item from the dictionary. /// /// Returns `Ok(None)` if the item is not present. To get a `KeyError` for /// non-existing keys, use [`PyAny::get_item`]. /// /// Returns `Err(PyErr)` if Python magic methods `__hash__` or `__eq__` used in dictionary /// lookup raise an exception, for example if the key `K` is not hashable. Usually it is /// best to bubble this error up to the caller using the `?` operator. /// /// # Examples /// /// The following example calls `get_item` for the dictionary `{"a": 1}` with various /// keys. /// - `get_item("a")` returns `Ok(Some(...))`, with the `PyAny` being a reference to the Python /// int `1`. /// - `get_item("b")` returns `Ok(None)`, because "b" is not in the dictionary. /// - `get_item(dict)` returns an `Err(PyErr)`. The error will be a `TypeError` because a dict is not /// hashable. /// /// ```rust /// use pyo3::prelude::*; /// use pyo3::types::{IntoPyDict}; /// use pyo3::exceptions::{PyTypeError, PyKeyError}; /// /// # fn main() { /// # let _ = /// Python::with_gil(|py| -> PyResult<()> { /// let dict = &[("a", 1)].into_py_dict_bound(py); /// // `a` is in the dictionary, with value 1 /// assert!(dict.get_item("a")?.map_or(Ok(false), |x| x.eq(1))?); /// // `b` is not in the dictionary /// assert!(dict.get_item("b")?.is_none()); /// // `dict` is not hashable, so this returns an error /// assert!(dict.get_item(dict).unwrap_err().is_instance_of::(py)); /// /// // `PyAny::get_item("b")` will raise a `KeyError` instead of returning `None` /// let any = dict.as_any(); /// assert!(any.get_item("b").unwrap_err().is_instance_of::(py)); /// Ok(()) /// }); /// # } /// ``` pub fn get_item(&self, key: K) -> PyResult> where K: ToPyObject, { match self.as_borrowed().get_item(key) { Ok(Some(item)) => Ok(Some(item.into_gil_ref())), Ok(None) => Ok(None), Err(e) => Err(e), } } /// Deprecated version of `get_item`. #[deprecated( since = "0.20.0", note = "this is now equivalent to `PyDict::get_item`" )] #[inline] pub fn get_item_with_error(&self, key: K) -> PyResult> where K: ToPyObject, { self.get_item(key) } /// Sets an item value. /// /// This is equivalent to the Python statement `self[key] = value`. pub fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject, { self.as_borrowed().set_item(key, value) } /// Deletes an item. /// /// This is equivalent to the Python statement `del self[key]`. pub fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject, { self.as_borrowed().del_item(key) } /// Returns a list of dict keys. /// /// This is equivalent to the Python expression `list(dict.keys())`. pub fn keys(&self) -> &PyList { self.as_borrowed().keys().into_gil_ref() } /// Returns a list of dict values. /// /// This is equivalent to the Python expression `list(dict.values())`. pub fn values(&self) -> &PyList { self.as_borrowed().values().into_gil_ref() } /// Returns a list of dict items. /// /// This is equivalent to the Python expression `list(dict.items())`. pub fn items(&self) -> &PyList { self.as_borrowed().items().into_gil_ref() } /// Returns an iterator of `(key, value)` pairs in this dictionary. /// /// # Panics /// /// If PyO3 detects that the dictionary is mutated during iteration, it will panic. /// It is allowed to modify values as you iterate over the dictionary, but only /// so long as the set of keys does not change. pub fn iter(&self) -> PyDictIterator<'_> { PyDictIterator(self.as_borrowed().iter()) } /// Returns `self` cast as a `PyMapping`. pub fn as_mapping(&self) -> &PyMapping { unsafe { self.downcast_unchecked() } } /// Update this dictionary with the key/value pairs from another. /// /// This is equivalent to the Python expression `self.update(other)`. If `other` is a `PyDict`, you may want /// to use `self.update(other.as_mapping())`, note: `PyDict::as_mapping` is a zero-cost conversion. pub fn update(&self, other: &PyMapping) -> PyResult<()> { self.as_borrowed().update(&other.as_borrowed()) } /// Add key/value pairs from another dictionary to this one only when they do not exist in this. /// /// This is equivalent to the Python expression `self.update({k: v for k, v in other.items() if k not in self})`. /// If `other` is a `PyDict`, you may want to use `self.update_if_missing(other.as_mapping())`, /// note: `PyDict::as_mapping` is a zero-cost conversion. /// /// This method uses [`PyDict_Merge`](https://docs.python.org/3/c-api/dict.html#c.PyDict_Merge) internally, /// so should have the same performance as `update`. pub fn update_if_missing(&self, other: &PyMapping) -> PyResult<()> { self.as_borrowed().update_if_missing(&other.as_borrowed()) } } /// Implementation of functionality for [`PyDict`]. /// /// These methods are defined for the `Bound<'py, PyDict>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyDict")] pub trait PyDictMethods<'py>: crate::sealed::Sealed { /// Returns a new dictionary that contains the same key-value pairs as self. /// /// This is equivalent to the Python expression `self.copy()`. fn copy(&self) -> PyResult>; /// Empties an existing dictionary of all key-value pairs. fn clear(&self); /// Return the number of items in the dictionary. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> usize; /// Checks if the dict is empty, i.e. `len(self) == 0`. fn is_empty(&self) -> bool; /// Determines if the dictionary contains the specified key. /// /// This is equivalent to the Python expression `key in self`. fn contains(&self, key: K) -> PyResult where K: ToPyObject; /// Gets an item from the dictionary. /// /// Returns `None` if the item is not present, or if an error occurs. /// /// To get a `KeyError` for non-existing keys, use `PyAny::get_item`. fn get_item(&self, key: K) -> PyResult>> where K: ToPyObject; /// Sets an item value. /// /// This is equivalent to the Python statement `self[key] = value`. fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject; /// Deletes an item. /// /// This is equivalent to the Python statement `del self[key]`. fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject; /// Returns a list of dict keys. /// /// This is equivalent to the Python expression `list(dict.keys())`. fn keys(&self) -> Bound<'py, PyList>; /// Returns a list of dict values. /// /// This is equivalent to the Python expression `list(dict.values())`. fn values(&self) -> Bound<'py, PyList>; /// Returns a list of dict items. /// /// This is equivalent to the Python expression `list(dict.items())`. fn items(&self) -> Bound<'py, PyList>; /// Returns an iterator of `(key, value)` pairs in this dictionary. /// /// # Panics /// /// If PyO3 detects that the dictionary is mutated during iteration, it will panic. /// It is allowed to modify values as you iterate over the dictionary, but only /// so long as the set of keys does not change. fn iter(&self) -> BoundDictIterator<'py>; /// Returns `self` cast as a `PyMapping`. fn as_mapping(&self) -> &Bound<'py, PyMapping>; /// Returns `self` cast as a `PyMapping`. fn into_mapping(self) -> Bound<'py, PyMapping>; /// Update this dictionary with the key/value pairs from another. /// /// This is equivalent to the Python expression `self.update(other)`. If `other` is a `PyDict`, you may want /// to use `self.update(other.as_mapping())`, note: `PyDict::as_mapping` is a zero-cost conversion. fn update(&self, other: &Bound<'_, PyMapping>) -> PyResult<()>; /// Add key/value pairs from another dictionary to this one only when they do not exist in this. /// /// This is equivalent to the Python expression `self.update({k: v for k, v in other.items() if k not in self})`. /// If `other` is a `PyDict`, you may want to use `self.update_if_missing(other.as_mapping())`, /// note: `PyDict::as_mapping` is a zero-cost conversion. /// /// This method uses [`PyDict_Merge`](https://docs.python.org/3/c-api/dict.html#c.PyDict_Merge) internally, /// so should have the same performance as `update`. fn update_if_missing(&self, other: &Bound<'_, PyMapping>) -> PyResult<()>; } impl<'py> PyDictMethods<'py> for Bound<'py, PyDict> { fn copy(&self) -> PyResult> { unsafe { ffi::PyDict_Copy(self.as_ptr()) .assume_owned_or_err(self.py()) .downcast_into_unchecked() } } fn clear(&self) { unsafe { ffi::PyDict_Clear(self.as_ptr()) } } fn len(&self) -> usize { dict_len(self) as usize } fn is_empty(&self) -> bool { self.len() == 0 } fn contains(&self, key: K) -> PyResult where K: ToPyObject, { fn inner(dict: &Bound<'_, PyDict>, key: Bound<'_, PyAny>) -> PyResult { match unsafe { ffi::PyDict_Contains(dict.as_ptr(), key.as_ptr()) } { 1 => Ok(true), 0 => Ok(false), _ => Err(PyErr::fetch(dict.py())), } } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn get_item(&self, key: K) -> PyResult>> where K: ToPyObject, { fn inner<'py>( dict: &Bound<'py, PyDict>, key: Bound<'_, PyAny>, ) -> PyResult>> { let py = dict.py(); match unsafe { ffi::PyDict_GetItemWithError(dict.as_ptr(), key.as_ptr()) .assume_borrowed_or_opt(py) .map(Borrowed::to_owned) } { some @ Some(_) => Ok(some), None => PyErr::take(py).map(Err).transpose(), } } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn set_item(&self, key: K, value: V) -> PyResult<()> where K: ToPyObject, V: ToPyObject, { fn inner( dict: &Bound<'_, PyDict>, key: Bound<'_, PyAny>, value: Bound<'_, PyAny>, ) -> PyResult<()> { err::error_on_minusone(dict.py(), unsafe { ffi::PyDict_SetItem(dict.as_ptr(), key.as_ptr(), value.as_ptr()) }) } let py = self.py(); inner( self, key.to_object(py).into_bound(py), value.to_object(py).into_bound(py), ) } fn del_item(&self, key: K) -> PyResult<()> where K: ToPyObject, { fn inner(dict: &Bound<'_, PyDict>, key: Bound<'_, PyAny>) -> PyResult<()> { err::error_on_minusone(dict.py(), unsafe { ffi::PyDict_DelItem(dict.as_ptr(), key.as_ptr()) }) } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn keys(&self) -> Bound<'py, PyList> { unsafe { ffi::PyDict_Keys(self.as_ptr()) .assume_owned(self.py()) .downcast_into_unchecked() } } fn values(&self) -> Bound<'py, PyList> { unsafe { ffi::PyDict_Values(self.as_ptr()) .assume_owned(self.py()) .downcast_into_unchecked() } } fn items(&self) -> Bound<'py, PyList> { unsafe { ffi::PyDict_Items(self.as_ptr()) .assume_owned(self.py()) .downcast_into_unchecked() } } fn iter(&self) -> BoundDictIterator<'py> { BoundDictIterator::new(self.clone()) } fn as_mapping(&self) -> &Bound<'py, PyMapping> { unsafe { self.downcast_unchecked() } } fn into_mapping(self) -> Bound<'py, PyMapping> { unsafe { self.into_any().downcast_into_unchecked() } } fn update(&self, other: &Bound<'_, PyMapping>) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PyDict_Update(self.as_ptr(), other.as_ptr()) }) } fn update_if_missing(&self, other: &Bound<'_, PyMapping>) -> PyResult<()> { err::error_on_minusone(self.py(), unsafe { ffi::PyDict_Merge(self.as_ptr(), other.as_ptr(), 0) }) } } impl<'a, 'py> Borrowed<'a, 'py, PyDict> { /// Iterates over the contents of this dictionary without incrementing reference counts. /// /// # Safety /// It must be known that this dictionary will not be modified during iteration. pub(crate) unsafe fn iter_borrowed(self) -> BorrowedDictIter<'a, 'py> { BorrowedDictIter::new(self) } } fn dict_len(dict: &Bound<'_, PyDict>) -> Py_ssize_t { #[cfg(any(not(Py_3_8), PyPy, GraalPy, Py_LIMITED_API))] unsafe { ffi::PyDict_Size(dict.as_ptr()) } #[cfg(all(Py_3_8, not(PyPy), not(GraalPy), not(Py_LIMITED_API)))] unsafe { (*dict.as_ptr().cast::()).ma_used } } /// PyO3 implementation of an iterator for a Python `dict` object. #[cfg(feature = "gil-refs")] pub struct PyDictIterator<'py>(BoundDictIterator<'py>); #[cfg(feature = "gil-refs")] impl<'py> Iterator for PyDictIterator<'py> { type Item = (&'py PyAny, &'py PyAny); #[inline] fn next(&mut self) -> Option { let (key, value) = self.0.next()?; Some((key.into_gil_ref(), value.into_gil_ref())) } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[cfg(feature = "gil-refs")] impl<'py> ExactSizeIterator for PyDictIterator<'py> { fn len(&self) -> usize { self.0.len() } } #[cfg(feature = "gil-refs")] impl<'a> IntoIterator for &'a PyDict { type Item = (&'a PyAny, &'a PyAny); type IntoIter = PyDictIterator<'a>; fn into_iter(self) -> Self::IntoIter { self.iter() } } /// PyO3 implementation of an iterator for a Python `dict` object. pub struct BoundDictIterator<'py> { dict: Bound<'py, PyDict>, ppos: ffi::Py_ssize_t, di_used: ffi::Py_ssize_t, len: ffi::Py_ssize_t, } impl<'py> Iterator for BoundDictIterator<'py> { type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>); #[inline] fn next(&mut self) -> Option { let ma_used = dict_len(&self.dict); // These checks are similar to what CPython does. // // If the dimension of the dict changes e.g. key-value pairs are removed // or added during iteration, this will panic next time when `next` is called if self.di_used != ma_used { self.di_used = -1; panic!("dictionary changed size during iteration"); }; // If the dict is changed in such a way that the length remains constant // then this will panic at the end of iteration - similar to this: // // d = {"a":1, "b":2, "c": 3} // // for k, v in d.items(): // d[f"{k}_"] = 4 // del d[k] // print(k) // if self.len == -1 { self.di_used = -1; panic!("dictionary keys changed during iteration"); }; let mut key: *mut ffi::PyObject = std::ptr::null_mut(); let mut value: *mut ffi::PyObject = std::ptr::null_mut(); if unsafe { ffi::PyDict_Next(self.dict.as_ptr(), &mut self.ppos, &mut key, &mut value) } != 0 { self.len -= 1; let py = self.dict.py(); // Safety: // - PyDict_Next returns borrowed values // - we have already checked that `PyDict_Next` succeeded, so we can assume these to be non-null Some(( unsafe { key.assume_borrowed_unchecked(py) }.to_owned(), unsafe { value.assume_borrowed_unchecked(py) }.to_owned(), )) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } } impl<'py> ExactSizeIterator for BoundDictIterator<'py> { fn len(&self) -> usize { self.len as usize } } impl<'py> BoundDictIterator<'py> { fn new(dict: Bound<'py, PyDict>) -> Self { let len = dict_len(&dict); BoundDictIterator { dict, ppos: 0, di_used: len, len, } } } impl<'py> IntoIterator for Bound<'py, PyDict> { type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>); type IntoIter = BoundDictIterator<'py>; fn into_iter(self) -> Self::IntoIter { BoundDictIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PyDict> { type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>); type IntoIter = BoundDictIterator<'py>; fn into_iter(self) -> Self::IntoIter { self.iter() } } mod borrowed_iter { use super::*; /// Variant of the above which is used to iterate the items of the dictionary /// without incrementing reference counts. This is only safe if it's known /// that the dictionary will not be modified during iteration. pub struct BorrowedDictIter<'a, 'py> { dict: Borrowed<'a, 'py, PyDict>, ppos: ffi::Py_ssize_t, len: ffi::Py_ssize_t, } impl<'a, 'py> Iterator for BorrowedDictIter<'a, 'py> { type Item = (Borrowed<'a, 'py, PyAny>, Borrowed<'a, 'py, PyAny>); #[inline] fn next(&mut self) -> Option { let mut key: *mut ffi::PyObject = std::ptr::null_mut(); let mut value: *mut ffi::PyObject = std::ptr::null_mut(); // Safety: self.dict lives sufficiently long that the pointer is not dangling if unsafe { ffi::PyDict_Next(self.dict.as_ptr(), &mut self.ppos, &mut key, &mut value) } != 0 { let py = self.dict.py(); self.len -= 1; // Safety: // - PyDict_Next returns borrowed values // - we have already checked that `PyDict_Next` succeeded, so we can assume these to be non-null Some(unsafe { (key.assume_borrowed(py), value.assume_borrowed(py)) }) } else { None } } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } } impl ExactSizeIterator for BorrowedDictIter<'_, '_> { fn len(&self) -> usize { self.len as usize } } impl<'a, 'py> BorrowedDictIter<'a, 'py> { pub(super) fn new(dict: Borrowed<'a, 'py, PyDict>) -> Self { let len = dict_len(&dict); BorrowedDictIter { dict, ppos: 0, len } } } } pub(crate) use borrowed_iter::BorrowedDictIter; /// Conversion trait that allows a sequence of tuples to be converted into `PyDict` /// Primary use case for this trait is `call` and `call_method` methods as keywords argument. pub trait IntoPyDict: Sized { /// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed /// depends on implementation. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`IntoPyDict::into_py_dict` will be replaced by `IntoPyDict::into_py_dict_bound` in a future PyO3 version" )] fn into_py_dict(self, py: Python<'_>) -> &PyDict { Self::into_py_dict_bound(self, py).into_gil_ref() } /// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed /// depends on implementation. fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict>; } impl IntoPyDict for I where T: PyDictItem, I: IntoIterator, { fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> { let dict = PyDict::new_bound(py); for item in self { dict.set_item(item.key(), item.value()) .expect("Failed to set_item on dict"); } dict } } /// Represents a tuple which can be used as a PyDict item. pub trait PyDictItem { type K: ToPyObject; type V: ToPyObject; fn key(&self) -> &Self::K; fn value(&self) -> &Self::V; } impl PyDictItem for (K, V) where K: ToPyObject, V: ToPyObject, { type K = K; type V = V; fn key(&self) -> &Self::K { &self.0 } fn value(&self) -> &Self::V { &self.1 } } impl PyDictItem for &(K, V) where K: ToPyObject, V: ToPyObject, { type K = K; type V = V; fn key(&self) -> &Self::K { &self.0 } fn value(&self) -> &Self::V { &self.1 } } #[cfg(test)] mod tests { use super::*; use crate::types::PyTuple; use std::collections::{BTreeMap, HashMap}; #[test] fn test_new() { Python::with_gil(|py| { let dict = [(7, 32)].into_py_dict_bound(py); assert_eq!( 32, dict.get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert!(dict.get_item(8i32).unwrap().is_none()); let map: HashMap = [(7, 32)].iter().cloned().collect(); assert_eq!(map, dict.extract().unwrap()); let map: BTreeMap = [(7, 32)].iter().cloned().collect(); assert_eq!(map, dict.extract().unwrap()); }); } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn test_from_sequence() { Python::with_gil(|py| { let items = PyList::new_bound(py, vec![("a", 1), ("b", 2)]); let dict = PyDict::from_sequence_bound(&items).unwrap(); assert_eq!( 1, dict.get_item("a") .unwrap() .unwrap() .extract::() .unwrap() ); assert_eq!( 2, dict.get_item("b") .unwrap() .unwrap() .extract::() .unwrap() ); let map: HashMap = [("a".into(), 1), ("b".into(), 2)].into_iter().collect(); assert_eq!(map, dict.extract().unwrap()); let map: BTreeMap = [("a".into(), 1), ("b".into(), 2)].into_iter().collect(); assert_eq!(map, dict.extract().unwrap()); }); } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn test_from_sequence_err() { Python::with_gil(|py| { let items = PyList::new_bound(py, vec!["a", "b"]); assert!(PyDict::from_sequence_bound(&items).is_err()); }); } #[test] fn test_copy() { Python::with_gil(|py| { let dict = [(7, 32)].into_py_dict_bound(py); let ndict = dict.copy().unwrap(); assert_eq!( 32, ndict .get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert!(ndict.get_item(8i32).unwrap().is_none()); }); } #[test] fn test_len() { Python::with_gil(|py| { let mut v = HashMap::new(); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); assert_eq!(0, dict.len()); v.insert(7, 32); let ob = v.to_object(py); let dict2 = ob.downcast_bound::(py).unwrap(); assert_eq!(1, dict2.len()); }); } #[test] fn test_contains() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); assert!(dict.contains(7i32).unwrap()); assert!(!dict.contains(8i32).unwrap()); }); } #[test] fn test_get_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); assert_eq!( 32, dict.get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert!(dict.get_item(8i32).unwrap().is_none()); }); } #[test] #[allow(deprecated)] #[cfg(all(not(any(PyPy, GraalPy)), feature = "gil-refs"))] fn test_get_item_with_error() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let dict = ob.downcast::(py).unwrap(); assert_eq!( 32, dict.get_item_with_error(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert!(dict.get_item_with_error(8i32).unwrap().is_none()); assert!(dict .get_item_with_error(dict) .unwrap_err() .is_instance_of::(py)); }); } #[test] fn test_set_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); assert!(dict.set_item(7i32, 42i32).is_ok()); // change assert!(dict.set_item(8i32, 123i32).is_ok()); // insert assert_eq!( 42i32, dict.get_item(7i32) .unwrap() .unwrap() .extract::() .unwrap() ); assert_eq!( 123i32, dict.get_item(8i32) .unwrap() .unwrap() .extract::() .unwrap() ); }); } #[test] fn test_set_item_refcnt() { Python::with_gil(|py| { let cnt; let obj = py.eval_bound("object()", None, None).unwrap(); { cnt = obj.get_refcnt(); let _dict = [(10, &obj)].into_py_dict_bound(py); } { assert_eq!(cnt, obj.get_refcnt()); } }); } #[test] fn test_set_item_does_not_update_original_object() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); assert!(dict.set_item(7i32, 42i32).is_ok()); // change assert!(dict.set_item(8i32, 123i32).is_ok()); // insert assert_eq!(32i32, v[&7i32]); // not updated! assert_eq!(None, v.get(&8i32)); }); } #[test] fn test_del_item() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); assert!(dict.del_item(7i32).is_ok()); assert_eq!(0, dict.len()); assert!(dict.get_item(7i32).unwrap().is_none()); }); } #[test] fn test_del_item_does_not_update_original_object() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); assert!(dict.del_item(7i32).is_ok()); // change assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated! }); } #[test] fn test_items() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; let mut value_sum = 0; for el in dict.items() { let tuple = el.downcast::().unwrap(); key_sum += tuple.get_item(0).unwrap().extract::().unwrap(); value_sum += tuple.get_item(1).unwrap().extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_keys() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut key_sum = 0; for el in dict.keys() { key_sum += el.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); }); } #[test] fn test_values() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); // Can't just compare against a vector of tuples since we don't have a guaranteed ordering. let mut values_sum = 0; for el in dict.values() { values_sum += el.extract::().unwrap(); } assert_eq!(32 + 42 + 123, values_sum); }); } #[test] fn test_iter() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); let mut key_sum = 0; let mut value_sum = 0; for (key, value) in dict { key_sum += key.extract::().unwrap(); value_sum += value.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_iter_bound() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict: &Bound<'_, PyDict> = ob.downcast_bound(py).unwrap(); let mut key_sum = 0; let mut value_sum = 0; for (key, value) in dict { key_sum += key.extract::().unwrap(); value_sum += value.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_iter_value_mutated() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); for (key, value) in dict { dict.set_item(key, value.extract::().unwrap() + 7) .unwrap(); } }); } #[test] #[should_panic] fn test_iter_key_mutated() { Python::with_gil(|py| { let mut v = HashMap::new(); for i in 0..10 { v.insert(i * 2, i * 2); } let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); for (i, (key, value)) in dict.iter().enumerate() { let key = key.extract::().unwrap(); let value = value.extract::().unwrap(); dict.set_item(key + 1, value + 1).unwrap(); if i > 1000 { // avoid this test just running out of memory if it fails break; }; } }); } #[test] #[should_panic] fn test_iter_key_mutated_constant_len() { Python::with_gil(|py| { let mut v = HashMap::new(); for i in 0..10 { v.insert(i * 2, i * 2); } let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); for (i, (key, value)) in dict.iter().enumerate() { let key = key.extract::().unwrap(); let value = value.extract::().unwrap(); dict.del_item(key).unwrap(); dict.set_item(key + 1, value + 1).unwrap(); if i > 1000 { // avoid this test just running out of memory if it fails break; }; } }); } #[test] fn test_iter_size_hint() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); let mut iter = dict.iter(); assert_eq!(iter.size_hint(), (v.len(), Some(v.len()))); iter.next(); assert_eq!(iter.size_hint(), (v.len() - 1, Some(v.len() - 1))); // Exhaust iterator. for _ in &mut iter {} assert_eq!(iter.size_hint(), (0, Some(0))); assert!(iter.next().is_none()); assert_eq!(iter.size_hint(), (0, Some(0))); }); } #[test] fn test_into_iter() { Python::with_gil(|py| { let mut v = HashMap::new(); v.insert(7, 32); v.insert(8, 42); v.insert(9, 123); let ob = v.to_object(py); let dict = ob.downcast_bound::(py).unwrap(); let mut key_sum = 0; let mut value_sum = 0; for (key, value) in dict { key_sum += key.extract::().unwrap(); value_sum += value.extract::().unwrap(); } assert_eq!(7 + 8 + 9, key_sum); assert_eq!(32 + 42 + 123, value_sum); }); } #[test] fn test_hashmap_into_dict() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict_bound(py); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_btreemap_into_dict() { Python::with_gil(|py| { let mut map = BTreeMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict_bound(py); assert_eq!(py_map.len(), 1); assert_eq!( py_map .get_item(1) .unwrap() .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn test_vec_into_dict() { Python::with_gil(|py| { let vec = vec![("a", 1), ("b", 2), ("c", 3)]; let py_map = vec.into_py_dict_bound(py); assert_eq!(py_map.len(), 3); assert_eq!( py_map .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); }); } #[test] fn test_slice_into_dict() { Python::with_gil(|py| { let arr = [("a", 1), ("b", 2), ("c", 3)]; let py_map = arr.into_py_dict_bound(py); assert_eq!(py_map.len(), 3); assert_eq!( py_map .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); }); } #[test] fn dict_as_mapping() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict_bound(py); assert_eq!(py_map.as_mapping().len().unwrap(), 1); assert_eq!( py_map .as_mapping() .get_item(1) .unwrap() .extract::() .unwrap(), 1 ); }); } #[test] fn dict_into_mapping() { Python::with_gil(|py| { let mut map = HashMap::::new(); map.insert(1, 1); let py_map = map.into_py_dict_bound(py); let py_mapping = py_map.into_mapping(); assert_eq!(py_mapping.len().unwrap(), 1); assert_eq!(py_mapping.get_item(1).unwrap().extract::().unwrap(), 1); }); } #[cfg(not(any(PyPy, GraalPy)))] fn abc_dict(py: Python<'_>) -> Bound<'_, PyDict> { let mut map = HashMap::<&'static str, i32>::new(); map.insert("a", 1); map.insert("b", 2); map.insert("c", 3); map.into_py_dict_bound(py) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn dict_keys_view() { Python::with_gil(|py| { let dict = abc_dict(py); let keys = dict.call_method0("keys").unwrap(); assert!(keys .is_instance(&py.get_type_bound::().as_borrowed()) .unwrap()); }) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn dict_values_view() { Python::with_gil(|py| { let dict = abc_dict(py); let values = dict.call_method0("values").unwrap(); assert!(values .is_instance(&py.get_type_bound::().as_borrowed()) .unwrap()); }) } #[test] #[cfg(not(any(PyPy, GraalPy)))] fn dict_items_view() { Python::with_gil(|py| { let dict = abc_dict(py); let items = dict.call_method0("items").unwrap(); assert!(items .is_instance(&py.get_type_bound::().as_borrowed()) .unwrap()); }) } #[test] fn dict_update() { Python::with_gil(|py| { let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict_bound(py); let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict_bound(py); dict.update(other.as_mapping()).unwrap(); assert_eq!(dict.len(), 4); assert_eq!( dict.get_item("a") .unwrap() .unwrap() .extract::() .unwrap(), 1 ); assert_eq!( dict.get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 4 ); assert_eq!( dict.get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 5 ); assert_eq!( dict.get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); assert_eq!(other.len(), 3); assert_eq!( other .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 4 ); assert_eq!( other .get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 5 ); assert_eq!( other .get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); }) } #[test] fn dict_update_if_missing() { Python::with_gil(|py| { let dict = [("a", 1), ("b", 2), ("c", 3)].into_py_dict_bound(py); let other = [("b", 4), ("c", 5), ("d", 6)].into_py_dict_bound(py); dict.update_if_missing(other.as_mapping()).unwrap(); assert_eq!(dict.len(), 4); assert_eq!( dict.get_item("a") .unwrap() .unwrap() .extract::() .unwrap(), 1 ); assert_eq!( dict.get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 2 ); assert_eq!( dict.get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 3 ); assert_eq!( dict.get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); assert_eq!(other.len(), 3); assert_eq!( other .get_item("b") .unwrap() .unwrap() .extract::() .unwrap(), 4 ); assert_eq!( other .get_item("c") .unwrap() .unwrap() .extract::() .unwrap(), 5 ); assert_eq!( other .get_item("d") .unwrap() .unwrap() .extract::() .unwrap(), 6 ); }) } } pyo3/src/types/frozenset.rs0000644000175000017500000003001214661133735016747 0ustar jamespagejamespageuse crate::types::PyIterator; #[cfg(feature = "gil-refs")] use crate::PyNativeType; use crate::{ err::{self, PyErr, PyResult}, ffi, ffi_ptr_ext::FfiPtrExt, py_result_ext::PyResultExt, types::any::PyAnyMethods, Bound, PyAny, PyObject, Python, ToPyObject, }; use std::ptr; /// Allows building a Python `frozenset` one item at a time pub struct PyFrozenSetBuilder<'py> { py_frozen_set: Bound<'py, PyFrozenSet>, } impl<'py> PyFrozenSetBuilder<'py> { /// Create a new `FrozenSetBuilder`. /// Since this allocates a `PyFrozenSet` internally it may /// panic when running out of memory. pub fn new(py: Python<'py>) -> PyResult> { Ok(PyFrozenSetBuilder { py_frozen_set: PyFrozenSet::empty_bound(py)?, }) } /// Adds an element to the set. pub fn add(&mut self, key: K) -> PyResult<()> where K: ToPyObject, { fn inner(frozenset: &Bound<'_, PyFrozenSet>, key: PyObject) -> PyResult<()> { err::error_on_minusone(frozenset.py(), unsafe { ffi::PySet_Add(frozenset.as_ptr(), key.as_ptr()) }) } inner(&self.py_frozen_set, key.to_object(self.py_frozen_set.py())) } /// Deprecated form of [`PyFrozenSetBuilder::finalize_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyFrozenSetBuilder::finalize` will be replaced by `PyFrozenSetBuilder::finalize_bound` in a future PyO3 version" )] pub fn finalize(self) -> &'py PyFrozenSet { self.finalize_bound().into_gil_ref() } /// Finish building the set and take ownership of its current value pub fn finalize_bound(self) -> Bound<'py, PyFrozenSet> { self.py_frozen_set } } /// Represents a Python `frozenset`. /// /// Values of this type are accessed via PyO3's smart pointers, e.g. as /// [`Py`][crate::Py] or [`Bound<'py, PyFrozenSet>`][Bound]. /// /// For APIs available on `frozenset` objects, see the [`PyFrozenSetMethods`] trait which is implemented for /// [`Bound<'py, PyFrozenSet>`][Bound]. #[repr(transparent)] pub struct PyFrozenSet(PyAny); #[cfg(not(any(PyPy, GraalPy)))] pyobject_native_type!( PyFrozenSet, ffi::PySetObject, pyobject_native_static_type_object!(ffi::PyFrozenSet_Type), #checkfunction=ffi::PyFrozenSet_Check ); #[cfg(any(PyPy, GraalPy))] pyobject_native_type_core!( PyFrozenSet, pyobject_native_static_type_object!(ffi::PyFrozenSet_Type), #checkfunction=ffi::PyFrozenSet_Check ); impl PyFrozenSet { /// Creates a new frozenset. /// /// May panic when running out of memory. #[inline] pub fn new_bound<'a, 'p, T: ToPyObject + 'a>( py: Python<'p>, elements: impl IntoIterator, ) -> PyResult> { new_from_iter(py, elements) } /// Creates a new empty frozen set pub fn empty_bound(py: Python<'_>) -> PyResult> { unsafe { ffi::PyFrozenSet_New(ptr::null_mut()) .assume_owned_or_err(py) .downcast_into_unchecked() } } } #[cfg(feature = "gil-refs")] impl PyFrozenSet { /// Deprecated form of [`PyFrozenSet::new_bound`]. #[inline] #[deprecated( since = "0.21.0", note = "`PyFrozenSet::new` will be replaced by `PyFrozenSet::new_bound` in a future PyO3 version" )] pub fn new<'a, 'p, T: ToPyObject + 'a>( py: Python<'p>, elements: impl IntoIterator, ) -> PyResult<&'p PyFrozenSet> { Self::new_bound(py, elements).map(Bound::into_gil_ref) } /// Deprecated form of [`PyFrozenSet::empty_bound`]. #[deprecated( since = "0.21.0", note = "`PyFrozenSet::empty` will be replaced by `PyFrozenSet::empty_bound` in a future PyO3 version" )] pub fn empty(py: Python<'_>) -> PyResult<&'_ PyFrozenSet> { Self::empty_bound(py).map(Bound::into_gil_ref) } /// Return the number of items in the set. /// This is equivalent to len(p) on a set. #[inline] pub fn len(&self) -> usize { self.as_borrowed().len() } /// Check if set is empty. pub fn is_empty(&self) -> bool { self.as_borrowed().is_empty() } /// Determine if the set contains the specified key. /// This is equivalent to the Python expression `key in self`. pub fn contains(&self, key: K) -> PyResult where K: ToPyObject, { self.as_borrowed().contains(key) } /// Returns an iterator of values in this frozen set. pub fn iter(&self) -> PyFrozenSetIterator<'_> { PyFrozenSetIterator(BoundFrozenSetIterator::new(self.as_borrowed().to_owned())) } } /// Implementation of functionality for [`PyFrozenSet`]. /// /// These methods are defined for the `Bound<'py, PyFrozenSet>` smart pointer, so to use method call /// syntax these methods are separated into a trait, because stable Rust does not yet support /// `arbitrary_self_types`. #[doc(alias = "PyFrozenSet")] pub trait PyFrozenSetMethods<'py>: crate::sealed::Sealed { /// Returns the number of items in the set. /// /// This is equivalent to the Python expression `len(self)`. fn len(&self) -> usize; /// Checks if set is empty. fn is_empty(&self) -> bool { self.len() == 0 } /// Determines if the set contains the specified key. /// /// This is equivalent to the Python expression `key in self`. fn contains(&self, key: K) -> PyResult where K: ToPyObject; /// Returns an iterator of values in this set. fn iter(&self) -> BoundFrozenSetIterator<'py>; } impl<'py> PyFrozenSetMethods<'py> for Bound<'py, PyFrozenSet> { #[inline] fn len(&self) -> usize { unsafe { ffi::PySet_Size(self.as_ptr()) as usize } } fn contains(&self, key: K) -> PyResult where K: ToPyObject, { fn inner(frozenset: &Bound<'_, PyFrozenSet>, key: Bound<'_, PyAny>) -> PyResult { match unsafe { ffi::PySet_Contains(frozenset.as_ptr(), key.as_ptr()) } { 1 => Ok(true), 0 => Ok(false), _ => Err(PyErr::fetch(frozenset.py())), } } let py = self.py(); inner(self, key.to_object(py).into_bound(py)) } fn iter(&self) -> BoundFrozenSetIterator<'py> { BoundFrozenSetIterator::new(self.clone()) } } /// PyO3 implementation of an iterator for a Python `frozenset` object. #[cfg(feature = "gil-refs")] pub struct PyFrozenSetIterator<'py>(BoundFrozenSetIterator<'py>); #[cfg(feature = "gil-refs")] impl<'py> Iterator for PyFrozenSetIterator<'py> { type Item = &'py super::PyAny; /// Advances the iterator and returns the next value. #[inline] fn next(&mut self) -> Option { self.0.next().map(Bound::into_gil_ref) } fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } #[cfg(feature = "gil-refs")] impl ExactSizeIterator for PyFrozenSetIterator<'_> { #[inline] fn len(&self) -> usize { self.0.len() } } #[cfg(feature = "gil-refs")] impl<'py> IntoIterator for &'py PyFrozenSet { type Item = &'py PyAny; type IntoIter = PyFrozenSetIterator<'py>; /// Returns an iterator of values in this set. fn into_iter(self) -> Self::IntoIter { PyFrozenSetIterator(BoundFrozenSetIterator::new(self.as_borrowed().to_owned())) } } impl<'py> IntoIterator for Bound<'py, PyFrozenSet> { type Item = Bound<'py, PyAny>; type IntoIter = BoundFrozenSetIterator<'py>; /// Returns an iterator of values in this set. fn into_iter(self) -> Self::IntoIter { BoundFrozenSetIterator::new(self) } } impl<'py> IntoIterator for &Bound<'py, PyFrozenSet> { type Item = Bound<'py, PyAny>; type IntoIter = BoundFrozenSetIterator<'py>; /// Returns an iterator of values in this set. fn into_iter(self) -> Self::IntoIter { self.iter() } } /// PyO3 implementation of an iterator for a Python `frozenset` object. pub struct BoundFrozenSetIterator<'p> { it: Bound<'p, PyIterator>, // Remaining elements in the frozenset remaining: usize, } impl<'py> BoundFrozenSetIterator<'py> { pub(super) fn new(set: Bound<'py, PyFrozenSet>) -> Self { Self { it: PyIterator::from_bound_object(&set).unwrap(), remaining: set.len(), } } } impl<'py> Iterator for BoundFrozenSetIterator<'py> { type Item = Bound<'py, super::PyAny>; /// Advances the iterator and returns the next value. fn next(&mut self) -> Option { self.remaining = self.remaining.saturating_sub(1); self.it.next().map(Result::unwrap) } fn size_hint(&self) -> (usize, Option) { (self.remaining, Some(self.remaining)) } } impl<'py> ExactSizeIterator for BoundFrozenSetIterator<'py> { fn len(&self) -> usize { self.remaining } } #[inline] pub(crate) fn new_from_iter( py: Python<'_>, elements: impl IntoIterator, ) -> PyResult> { fn inner<'py>( py: Python<'py>, elements: &mut dyn Iterator, ) -> PyResult> { let set = unsafe { // We create the `Py` pointer because its Drop cleans up the set if user code panics. ffi::PyFrozenSet_New(std::ptr::null_mut()) .assume_owned_or_err(py)? .downcast_into_unchecked() }; let ptr = set.as_ptr(); for obj in elements { err::error_on_minusone(py, unsafe { ffi::PySet_Add(ptr, obj.as_ptr()) })?; } Ok(set) } let mut iter = elements.into_iter().map(|e| e.to_object(py)); inner(py, &mut iter) } #[cfg(test)] mod tests { use super::*; #[test] fn test_frozenset_new_and_len() { Python::with_gil(|py| { let set = PyFrozenSet::new_bound(py, &[1]).unwrap(); assert_eq!(1, set.len()); let v = vec![1]; assert!(PyFrozenSet::new_bound(py, &[v]).is_err()); }); } #[test] fn test_frozenset_empty() { Python::with_gil(|py| { let set = PyFrozenSet::empty_bound(py).unwrap(); assert_eq!(0, set.len()); assert!(set.is_empty()); }); } #[test] fn test_frozenset_contains() { Python::with_gil(|py| { let set = PyFrozenSet::new_bound(py, &[1]).unwrap(); assert!(set.contains(1).unwrap()); }); } #[test] fn test_frozenset_iter() { Python::with_gil(|py| { let set = PyFrozenSet::new_bound(py, &[1]).unwrap(); for el in set { assert_eq!(1i32, el.extract::().unwrap()); } }); } #[test] fn test_frozenset_iter_bound() { Python::with_gil(|py| { let set = PyFrozenSet::new_bound(py, &[1]).unwrap(); for el in &set { assert_eq!(1i32, el.extract::().unwrap()); } }); } #[test] fn test_frozenset_iter_size_hint() { Python::with_gil(|py| { let set = PyFrozenSet::new_bound(py, &[1]).unwrap(); let mut iter = set.iter(); // Exact size assert_eq!(iter.len(), 1); assert_eq!(iter.size_hint(), (1, Some(1))); iter.next(); assert_eq!(iter.len(), 0); assert_eq!(iter.size_hint(), (0, Some(0))); }); } #[test] fn test_frozenset_builder() { use super::PyFrozenSetBuilder; Python::with_gil(|py| { let mut builder = PyFrozenSetBuilder::new(py).unwrap(); // add an item builder.add(1).unwrap(); builder.add(2).unwrap(); builder.add(2).unwrap(); // finalize it let set = builder.finalize_bound(); assert!(set.contains(1).unwrap()); assert!(set.contains(2).unwrap()); assert!(!set.contains(3).unwrap()); }); } } pyo3/src/gil.rs0000644000175000017500000007160314661133735014352 0ustar jamespagejamespage//! Interaction with Python's global interpreter lock #[cfg(feature = "gil-refs")] use crate::impl_::not_send::{NotSend, NOT_SEND}; #[cfg(pyo3_disable_reference_pool)] use crate::impl_::panic::PanicTrap; use crate::{ffi, Python}; #[cfg(not(pyo3_disable_reference_pool))] use once_cell::sync::Lazy; use std::cell::Cell; #[cfg(all(feature = "gil-refs", debug_assertions))] use std::cell::RefCell; #[cfg(all(feature = "gil-refs", not(debug_assertions)))] use std::cell::UnsafeCell; use std::{mem, ptr::NonNull, sync}; static START: sync::Once = sync::Once::new(); std::thread_local! { /// This is an internal counter in pyo3 monitoring whether this thread has the GIL. /// /// It will be incremented whenever a GILGuard or GILPool is created, and decremented whenever /// they are dropped. /// /// As a result, if this thread has the GIL, GIL_COUNT is greater than zero. /// /// Additionally, we sometimes need to prevent safe access to the GIL, /// e.g. when implementing `__traverse__`, which is represented by a negative value. static GIL_COUNT: Cell = const { Cell::new(0) }; /// Temporarily hold objects that will be released when the GILPool drops. #[cfg(all(feature = "gil-refs", debug_assertions))] static OWNED_OBJECTS: RefCell = const { RefCell::new(Vec::new()) }; #[cfg(all(feature = "gil-refs", not(debug_assertions)))] static OWNED_OBJECTS: UnsafeCell = const { UnsafeCell::new(Vec::new()) }; } const GIL_LOCKED_DURING_TRAVERSE: isize = -1; /// Checks whether the GIL is acquired. /// /// Note: This uses pyo3's internal count rather than PyGILState_Check for two reasons: /// 1) for performance /// 2) PyGILState_Check always returns 1 if the sub-interpreter APIs have ever been called, /// which could lead to incorrect conclusions that the GIL is held. #[inline(always)] fn gil_is_acquired() -> bool { GIL_COUNT.try_with(|c| c.get() > 0).unwrap_or(false) } /// Prepares the use of Python in a free-threaded context. /// /// If the Python interpreter is not already initialized, this function will initialize it with /// signal handling disabled (Python will not raise the `KeyboardInterrupt` exception). Python /// signal handling depends on the notion of a 'main thread', which must be the thread that /// initializes the Python interpreter. /// /// If the Python interpreter is already initialized, this function has no effect. /// /// This function is unavailable under PyPy because PyPy cannot be embedded in Rust (or any other /// software). Support for this is tracked on the /// [PyPy issue tracker](https://github.com/pypy/pypy/issues/3836). /// /// # Examples /// ```rust /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// pyo3::prepare_freethreaded_python(); /// Python::with_gil(|py| py.run_bound("print('Hello World')", None, None)) /// # } /// ``` #[cfg(not(any(PyPy, GraalPy)))] pub fn prepare_freethreaded_python() { // Protect against race conditions when Python is not yet initialized and multiple threads // concurrently call 'prepare_freethreaded_python()'. Note that we do not protect against // concurrent initialization of the Python runtime by other users of the Python C API. START.call_once_force(|_| unsafe { // Use call_once_force because if initialization panics, it's okay to try again. if ffi::Py_IsInitialized() == 0 { ffi::Py_InitializeEx(0); // Release the GIL. ffi::PyEval_SaveThread(); } }); } /// Executes the provided closure with an embedded Python interpreter. /// /// This function initializes the Python interpreter, executes the provided closure, and then /// finalizes the Python interpreter. /// /// After execution all Python resources are cleaned up, and no further Python APIs can be called. /// Because many Python modules implemented in C do not support multiple Python interpreters in a /// single process, it is not safe to call this function more than once. (Many such modules will not /// initialize correctly on the second run.) /// /// # Panics /// - If the Python interpreter is already initialized before calling this function. /// /// # Safety /// - This function should only ever be called once per process (usually as part of the `main` /// function). It is also not thread-safe. /// - No Python APIs can be used after this function has finished executing. /// - The return value of the closure must not contain any Python value, _including_ `PyResult`. /// /// # Examples /// /// ```rust /// unsafe { /// pyo3::with_embedded_python_interpreter(|py| { /// if let Err(e) = py.run_bound("print('Hello World')", None, None) { /// // We must make sure to not return a `PyErr`! /// e.print(py); /// } /// }); /// } /// ``` #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn with_embedded_python_interpreter(f: F) -> R where F: for<'p> FnOnce(Python<'p>) -> R, { assert_eq!( ffi::Py_IsInitialized(), 0, "called `with_embedded_python_interpreter` but a Python interpreter is already running." ); ffi::Py_InitializeEx(0); let result = { let guard = GILGuard::assume(); let py = guard.python(); // Import the threading module - this ensures that it will associate this thread as the "main" // thread, which is important to avoid an `AssertionError` at finalization. py.import_bound("threading").unwrap(); // Execute the closure. f(py) }; // Finalize the Python interpreter. ffi::Py_Finalize(); result } /// RAII type that represents the Global Interpreter Lock acquisition. pub(crate) enum GILGuard { /// Indicates the GIL was already held with this GILGuard was acquired. Assumed, /// Indicates that we actually acquired the GIL when this GILGuard was acquired Ensured { gstate: ffi::PyGILState_STATE, #[cfg(feature = "gil-refs")] #[allow(deprecated)] pool: mem::ManuallyDrop, }, } impl GILGuard { /// PyO3 internal API for acquiring the GIL. The public API is Python::with_gil. /// /// If the GIL was already acquired via PyO3, this returns /// `GILGuard::Assumed`. Otherwise, the GIL will be acquired and /// `GILGuard::Ensured` will be returned. pub(crate) fn acquire() -> Self { if gil_is_acquired() { // SAFETY: We just checked that the GIL is already acquired. return unsafe { Self::assume() }; } // Maybe auto-initialize the GIL: // - If auto-initialize feature set and supported, try to initialize the interpreter. // - If the auto-initialize feature is set but unsupported, emit hard errors only when the // extension-module feature is not activated - extension modules don't care about // auto-initialize so this avoids breaking existing builds. // - Otherwise, just check the GIL is initialized. cfg_if::cfg_if! { if #[cfg(all(feature = "auto-initialize", not(any(PyPy, GraalPy))))] { prepare_freethreaded_python(); } else { // This is a "hack" to make running `cargo test` for PyO3 convenient (i.e. no need // to specify `--features auto-initialize` manually. Tests within the crate itself // all depend on the auto-initialize feature for conciseness but Cargo does not // provide a mechanism to specify required features for tests. #[cfg(not(any(PyPy, GraalPy)))] if option_env!("CARGO_PRIMARY_PACKAGE").is_some() { prepare_freethreaded_python(); } START.call_once_force(|_| unsafe { // Use call_once_force because if there is a panic because the interpreter is // not initialized, it's fine for the user to initialize the interpreter and // retry. assert_ne!( ffi::Py_IsInitialized(), 0, "The Python interpreter is not initialized and the `auto-initialize` \ feature is not enabled.\n\n\ Consider calling `pyo3::prepare_freethreaded_python()` before attempting \ to use Python APIs." ); }); } } // SAFETY: We have ensured the Python interpreter is initialized. unsafe { Self::acquire_unchecked() } } /// Acquires the `GILGuard` without performing any state checking. /// /// This can be called in "unsafe" contexts where the normal interpreter state /// checking performed by `GILGuard::acquire` may fail. This includes calling /// as part of multi-phase interpreter initialization. pub(crate) unsafe fn acquire_unchecked() -> Self { if gil_is_acquired() { return Self::assume(); } let gstate = ffi::PyGILState_Ensure(); // acquire GIL increment_gil_count(); #[cfg(feature = "gil-refs")] #[allow(deprecated)] let pool = mem::ManuallyDrop::new(GILPool::new()); #[cfg(not(pyo3_disable_reference_pool))] if let Some(pool) = Lazy::get(&POOL) { pool.update_counts(Python::assume_gil_acquired()); } GILGuard::Ensured { gstate, #[cfg(feature = "gil-refs")] pool, } } /// Acquires the `GILGuard` while assuming that the GIL is already held. pub(crate) unsafe fn assume() -> Self { increment_gil_count(); let guard = GILGuard::Assumed; #[cfg(not(pyo3_disable_reference_pool))] if let Some(pool) = Lazy::get(&POOL) { pool.update_counts(guard.python()); } guard } /// Gets the Python token associated with this [`GILGuard`]. #[inline] pub fn python(&self) -> Python<'_> { unsafe { Python::assume_gil_acquired() } } } /// The Drop implementation for `GILGuard` will release the GIL. impl Drop for GILGuard { fn drop(&mut self) { match self { GILGuard::Assumed => {} GILGuard::Ensured { gstate, #[cfg(feature = "gil-refs")] pool, } => unsafe { // Drop the objects in the pool before attempting to release the thread state #[cfg(feature = "gil-refs")] mem::ManuallyDrop::drop(pool); ffi::PyGILState_Release(*gstate); }, } decrement_gil_count(); } } // Vector of PyObject type PyObjVec = Vec>; #[cfg(not(pyo3_disable_reference_pool))] /// Thread-safe storage for objects which were dec_ref while the GIL was not held. struct ReferencePool { pending_decrefs: sync::Mutex, } #[cfg(not(pyo3_disable_reference_pool))] impl ReferencePool { const fn new() -> Self { Self { pending_decrefs: sync::Mutex::new(Vec::new()), } } fn register_decref(&self, obj: NonNull) { self.pending_decrefs.lock().unwrap().push(obj); } fn update_counts(&self, _py: Python<'_>) { let mut pending_decrefs = self.pending_decrefs.lock().unwrap(); if pending_decrefs.is_empty() { return; } let decrefs = mem::take(&mut *pending_decrefs); drop(pending_decrefs); for ptr in decrefs { unsafe { ffi::Py_DECREF(ptr.as_ptr()) }; } } } #[cfg(not(pyo3_disable_reference_pool))] unsafe impl Send for ReferencePool {} #[cfg(not(pyo3_disable_reference_pool))] unsafe impl Sync for ReferencePool {} #[cfg(not(pyo3_disable_reference_pool))] static POOL: Lazy = Lazy::new(ReferencePool::new); /// A guard which can be used to temporarily release the GIL and restore on `Drop`. pub(crate) struct SuspendGIL { count: isize, tstate: *mut ffi::PyThreadState, } impl SuspendGIL { pub(crate) unsafe fn new() -> Self { let count = GIL_COUNT.with(|c| c.replace(0)); let tstate = ffi::PyEval_SaveThread(); Self { count, tstate } } } impl Drop for SuspendGIL { fn drop(&mut self) { GIL_COUNT.with(|c| c.set(self.count)); unsafe { ffi::PyEval_RestoreThread(self.tstate); // Update counts of PyObjects / Py that were cloned or dropped while the GIL was released. #[cfg(not(pyo3_disable_reference_pool))] if let Some(pool) = Lazy::get(&POOL) { pool.update_counts(Python::assume_gil_acquired()); } } } } /// Used to lock safe access to the GIL pub(crate) struct LockGIL { count: isize, } impl LockGIL { /// Lock access to the GIL while an implementation of `__traverse__` is running pub fn during_traverse() -> Self { Self::new(GIL_LOCKED_DURING_TRAVERSE) } fn new(reason: isize) -> Self { let count = GIL_COUNT.with(|c| c.replace(reason)); Self { count } } #[cold] fn bail(current: isize) { match current { GIL_LOCKED_DURING_TRAVERSE => panic!( "Access to the GIL is prohibited while a __traverse__ implmentation is running." ), _ => panic!("Access to the GIL is currently prohibited."), } } } impl Drop for LockGIL { fn drop(&mut self) { GIL_COUNT.with(|c| c.set(self.count)); } } /// A RAII pool which PyO3 uses to store owned Python references. /// /// See the [Memory Management] chapter of the guide for more information about how PyO3 uses /// [`GILPool`] to manage memory. /// /// [Memory Management]: https://pyo3.rs/main/memory.html#gil-bound-memory #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`GILPool` has no function if PyO3's deprecated GIL Refs API is not used" )] pub struct GILPool { /// Initial length of owned objects and anys. /// `Option` is used since TSL can be broken when `new` is called from `atexit`. start: Option, _not_send: NotSend, } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl GILPool { /// Creates a new [`GILPool`]. This function should only ever be called with the GIL held. /// /// It is recommended not to use this API directly, but instead to use `Python::new_pool`, as /// that guarantees the GIL is held. /// /// # Safety /// /// As well as requiring the GIL, see the safety notes on `Python::new_pool`. #[inline] pub unsafe fn new() -> GILPool { // Update counts of PyObjects / Py that have been cloned or dropped since last acquisition #[cfg(not(pyo3_disable_reference_pool))] if let Some(pool) = Lazy::get(&POOL) { pool.update_counts(Python::assume_gil_acquired()); } GILPool { start: OWNED_OBJECTS .try_with(|owned_objects| { #[cfg(debug_assertions)] let len = owned_objects.borrow().len(); #[cfg(not(debug_assertions))] // SAFETY: This is not re-entrant. let len = unsafe { (*owned_objects.get()).len() }; len }) .ok(), _not_send: NOT_SEND, } } /// Gets the Python token associated with this [`GILPool`]. #[inline] pub fn python(&self) -> Python<'_> { unsafe { Python::assume_gil_acquired() } } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl Drop for GILPool { fn drop(&mut self) { if let Some(start) = self.start { let owned_objects = OWNED_OBJECTS.with(|owned_objects| { #[cfg(debug_assertions)] let mut owned_objects = owned_objects.borrow_mut(); #[cfg(not(debug_assertions))] // SAFETY: `OWNED_OBJECTS` is released before calling Py_DECREF, // or Py_DECREF may call `GILPool::drop` recursively, resulting in invalid borrowing. let owned_objects = unsafe { &mut *owned_objects.get() }; if start < owned_objects.len() { owned_objects.split_off(start) } else { Vec::new() } }); for obj in owned_objects { unsafe { ffi::Py_DECREF(obj.as_ptr()); } } } } } /// Increments the reference count of a Python object if the GIL is held. If /// the GIL is not held, this function will panic. /// /// # Safety /// The object must be an owned Python reference. #[cfg(feature = "py-clone")] #[track_caller] pub unsafe fn register_incref(obj: NonNull) { if gil_is_acquired() { ffi::Py_INCREF(obj.as_ptr()) } else { panic!("Cannot clone pointer into Python heap without the GIL being held."); } } /// Registers a Python object pointer inside the release pool, to have its reference count decreased /// the next time the GIL is acquired in pyo3. /// /// If the GIL is held, the reference count will be decreased immediately instead of being queued /// for later. /// /// # Safety /// The object must be an owned Python reference. #[track_caller] pub unsafe fn register_decref(obj: NonNull) { if gil_is_acquired() { ffi::Py_DECREF(obj.as_ptr()) } else { #[cfg(not(pyo3_disable_reference_pool))] POOL.register_decref(obj); #[cfg(all( pyo3_disable_reference_pool, not(pyo3_leak_on_drop_without_reference_pool) ))] { let _trap = PanicTrap::new("Aborting the process to avoid panic-from-drop."); panic!("Cannot drop pointer into Python heap without the GIL being held."); } } } /// Registers an owned object inside the GILPool, to be released when the GILPool drops. /// /// # Safety /// The object must be an owned Python reference. #[cfg(feature = "gil-refs")] pub unsafe fn register_owned(_py: Python<'_>, obj: NonNull) { debug_assert!(gil_is_acquired()); // Ignores the error in case this function called from `atexit`. let _ = OWNED_OBJECTS.try_with(|owned_objects| { #[cfg(debug_assertions)] owned_objects.borrow_mut().push(obj); #[cfg(not(debug_assertions))] // SAFETY: This is not re-entrant. unsafe { (*owned_objects.get()).push(obj); } }); } /// Increments pyo3's internal GIL count - to be called whenever GILPool or GILGuard is created. #[inline(always)] fn increment_gil_count() { // Ignores the error in case this function called from `atexit`. let _ = GIL_COUNT.try_with(|c| { let current = c.get(); if current < 0 { LockGIL::bail(current); } c.set(current + 1); }); } /// Decrements pyo3's internal GIL count - to be called whenever GILPool or GILGuard is dropped. #[inline(always)] fn decrement_gil_count() { // Ignores the error in case this function called from `atexit`. let _ = GIL_COUNT.try_with(|c| { let current = c.get(); debug_assert!( current > 0, "Negative GIL count detected. Please report this error to the PyO3 repo as a bug." ); c.set(current - 1); }); } #[cfg(test)] mod tests { use super::GIL_COUNT; #[cfg(feature = "gil-refs")] #[allow(deprecated)] use super::OWNED_OBJECTS; #[cfg(not(pyo3_disable_reference_pool))] use super::{gil_is_acquired, POOL}; #[cfg(feature = "gil-refs")] use crate::{ffi, gil}; use crate::{gil::GILGuard, types::any::PyAnyMethods}; use crate::{PyObject, Python}; use std::ptr::NonNull; fn get_object(py: Python<'_>) -> PyObject { py.eval_bound("object()", None, None).unwrap().unbind() } #[cfg(feature = "gil-refs")] fn owned_object_count() -> usize { #[cfg(debug_assertions)] let len = OWNED_OBJECTS.with(|owned_objects| owned_objects.borrow().len()); #[cfg(not(debug_assertions))] let len = OWNED_OBJECTS.with(|owned_objects| unsafe { (*owned_objects.get()).len() }); len } #[cfg(not(pyo3_disable_reference_pool))] fn pool_dec_refs_does_not_contain(obj: &PyObject) -> bool { !POOL .pending_decrefs .lock() .unwrap() .contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) }) } #[cfg(not(pyo3_disable_reference_pool))] fn pool_dec_refs_contains(obj: &PyObject) -> bool { POOL.pending_decrefs .lock() .unwrap() .contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) }) } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_owned() { Python::with_gil(|py| { let obj = get_object(py); let obj_ptr = obj.as_ptr(); // Ensure that obj does not get freed let _ref = obj.clone_ref(py); unsafe { { let pool = py.new_pool(); gil::register_owned(pool.python(), NonNull::new_unchecked(obj.into_ptr())); assert_eq!(owned_object_count(), 1); assert_eq!(ffi::Py_REFCNT(obj_ptr), 2); } { let _pool = py.new_pool(); assert_eq!(owned_object_count(), 0); assert_eq!(ffi::Py_REFCNT(obj_ptr), 1); } } }) } #[test] #[cfg(feature = "gil-refs")] #[allow(deprecated)] fn test_owned_nested() { Python::with_gil(|py| { let obj = get_object(py); // Ensure that obj does not get freed let _ref = obj.clone_ref(py); let obj_ptr = obj.as_ptr(); unsafe { { let _pool = py.new_pool(); assert_eq!(owned_object_count(), 0); gil::register_owned(py, NonNull::new_unchecked(obj.into_ptr())); assert_eq!(owned_object_count(), 1); assert_eq!(ffi::Py_REFCNT(obj_ptr), 2); { let _pool = py.new_pool(); let obj = get_object(py); gil::register_owned(py, NonNull::new_unchecked(obj.into_ptr())); assert_eq!(owned_object_count(), 2); } assert_eq!(owned_object_count(), 1); } { assert_eq!(owned_object_count(), 0); assert_eq!(ffi::Py_REFCNT(obj_ptr), 1); } } }); } #[test] fn test_pyobject_drop_with_gil_decreases_refcnt() { Python::with_gil(|py| { let obj = get_object(py); // Create a reference to drop with the GIL. let reference = obj.clone_ref(py); assert_eq!(obj.get_refcnt(py), 2); #[cfg(not(pyo3_disable_reference_pool))] assert!(pool_dec_refs_does_not_contain(&obj)); // With the GIL held, reference count will be decreased immediately. drop(reference); assert_eq!(obj.get_refcnt(py), 1); #[cfg(not(pyo3_disable_reference_pool))] assert!(pool_dec_refs_does_not_contain(&obj)); }); } #[test] #[cfg(all(not(pyo3_disable_reference_pool), not(target_arch = "wasm32")))] // We are building wasm Python with pthreads disabled fn test_pyobject_drop_without_gil_doesnt_decrease_refcnt() { let obj = Python::with_gil(|py| { let obj = get_object(py); // Create a reference to drop without the GIL. let reference = obj.clone_ref(py); assert_eq!(obj.get_refcnt(py), 2); assert!(pool_dec_refs_does_not_contain(&obj)); // Drop reference in a separate thread which doesn't have the GIL. std::thread::spawn(move || drop(reference)).join().unwrap(); // The reference count should not have changed (the GIL has always // been held by this thread), it is remembered to release later. assert_eq!(obj.get_refcnt(py), 2); assert!(pool_dec_refs_contains(&obj)); obj }); // Next time the GIL is acquired, the reference is released Python::with_gil(|py| { assert_eq!(obj.get_refcnt(py), 1); assert!(pool_dec_refs_does_not_contain(&obj)); }); } #[test] #[allow(deprecated)] fn test_gil_counts() { // Check with_gil and GILGuard both increase counts correctly let get_gil_count = || GIL_COUNT.with(|c| c.get()); assert_eq!(get_gil_count(), 0); Python::with_gil(|_| { assert_eq!(get_gil_count(), 1); let pool = unsafe { GILGuard::assume() }; assert_eq!(get_gil_count(), 2); let pool2 = unsafe { GILGuard::assume() }; assert_eq!(get_gil_count(), 3); drop(pool); assert_eq!(get_gil_count(), 2); Python::with_gil(|_| { // nested with_gil updates gil count assert_eq!(get_gil_count(), 3); }); assert_eq!(get_gil_count(), 2); drop(pool2); assert_eq!(get_gil_count(), 1); }); assert_eq!(get_gil_count(), 0); } #[test] fn test_allow_threads() { assert!(!gil_is_acquired()); Python::with_gil(|py| { assert!(gil_is_acquired()); py.allow_threads(move || { assert!(!gil_is_acquired()); Python::with_gil(|_| assert!(gil_is_acquired())); assert!(!gil_is_acquired()); }); assert!(gil_is_acquired()); }); assert!(!gil_is_acquired()); } #[cfg(feature = "py-clone")] #[test] #[should_panic] fn test_allow_threads_updates_refcounts() { Python::with_gil(|py| { // Make a simple object with 1 reference let obj = get_object(py); assert!(obj.get_refcnt(py) == 1); // Clone the object without the GIL which should panic py.allow_threads(|| obj.clone()); }); } #[test] fn dropping_gil_does_not_invalidate_references() { // Acquiring GIL for the second time should be safe - see #864 Python::with_gil(|py| { let obj = Python::with_gil(|_| py.eval_bound("object()", None, None).unwrap()); // After gil2 drops, obj should still have a reference count of one assert_eq!(obj.get_refcnt(), 1); }) } #[cfg(feature = "py-clone")] #[test] fn test_clone_with_gil() { Python::with_gil(|py| { let obj = get_object(py); let count = obj.get_refcnt(py); // Cloning with the GIL should increase reference count immediately #[allow(clippy::redundant_clone)] let c = obj.clone(); assert_eq!(count + 1, c.get_refcnt(py)); }) } #[test] #[cfg(not(pyo3_disable_reference_pool))] fn test_update_counts_does_not_deadlock() { // update_counts can run arbitrary Python code during Py_DECREF. // if the locking is implemented incorrectly, it will deadlock. use crate::ffi; use crate::gil::GILGuard; Python::with_gil(|py| { let obj = get_object(py); unsafe extern "C" fn capsule_drop(capsule: *mut ffi::PyObject) { // This line will implicitly call update_counts // -> and so cause deadlock if update_counts is not handling recursion correctly. let pool = GILGuard::assume(); // Rebuild obj so that it can be dropped PyObject::from_owned_ptr( pool.python(), ffi::PyCapsule_GetPointer(capsule, std::ptr::null()) as _, ); } let ptr = obj.into_ptr(); let capsule = unsafe { ffi::PyCapsule_New(ptr as _, std::ptr::null(), Some(capsule_drop)) }; POOL.register_decref(NonNull::new(capsule).unwrap()); // Updating the counts will call decref on the capsule, which calls capsule_drop POOL.update_counts(py); }) } #[test] #[cfg(not(pyo3_disable_reference_pool))] fn test_gil_guard_update_counts() { use crate::gil::GILGuard; Python::with_gil(|py| { let obj = get_object(py); // For GILGuard::acquire POOL.register_decref(NonNull::new(obj.clone_ref(py).into_ptr()).unwrap()); assert!(pool_dec_refs_contains(&obj)); let _guard = GILGuard::acquire(); assert!(pool_dec_refs_does_not_contain(&obj)); // For GILGuard::assume POOL.register_decref(NonNull::new(obj.clone_ref(py).into_ptr()).unwrap()); assert!(pool_dec_refs_contains(&obj)); let _guard2 = unsafe { GILGuard::assume() }; assert!(pool_dec_refs_does_not_contain(&obj)); }) } } pyo3/src/pycell.rs0000644000175000017500000011732614661133735015072 0ustar jamespagejamespage//! PyO3's interior mutability primitive. //! //! Rust has strict aliasing rules - you can either have any number of immutable (shared) references or one mutable //! reference. Python's ownership model is the complete opposite of that - any Python object //! can be referenced any number of times, and mutation is allowed from any reference. //! //! PyO3 deals with these differences by employing the [Interior Mutability] //! pattern. This requires that PyO3 enforces the borrowing rules and it has two mechanisms for //! doing so: //! - Statically it can enforce threadsafe access with the [`Python<'py>`](crate::Python) token. //! All Rust code holding that token, or anything derived from it, can assume that they have //! safe access to the Python interpreter's state. For this reason all the native Python objects //! can be mutated through shared references. //! - However, methods and functions in Rust usually *do* need `&mut` references. While PyO3 can //! use the [`Python<'py>`](crate::Python) token to guarantee thread-safe access to them, it cannot //! statically guarantee uniqueness of `&mut` references. As such those references have to be tracked //! dynamically at runtime, using `PyCell` and the other types defined in this module. This works //! similar to std's [`RefCell`](std::cell::RefCell) type. //! //! # When *not* to use PyCell //! //! Usually you can use `&mut` references as method and function receivers and arguments, and you //! won't need to use `PyCell` directly: //! //! ```rust //! use pyo3::prelude::*; //! //! #[pyclass] //! struct Number { //! inner: u32, //! } //! //! #[pymethods] //! impl Number { //! fn increment(&mut self) { //! self.inner += 1; //! } //! } //! ``` //! //! The [`#[pymethods]`](crate::pymethods) proc macro will generate this wrapper function (and more), //! using `PyCell` under the hood: //! //! ```rust,ignore //! # use pyo3::prelude::*; //! # #[pyclass] //! # struct Number { //! # inner: u32, //! # } //! # //! # #[pymethods] //! # impl Number { //! # fn increment(&mut self) { //! # self.inner += 1; //! # } //! # } //! # //! // The function which is exported to Python looks roughly like the following //! unsafe extern "C" fn __pymethod_increment__( //! _slf: *mut pyo3::ffi::PyObject, //! _args: *mut pyo3::ffi::PyObject, //! ) -> *mut pyo3::ffi::PyObject { //! use :: pyo3 as _pyo3; //! _pyo3::impl_::trampoline::noargs(_slf, _args, |py, _slf| { //! # #[allow(deprecated)] //! let _cell = py //! .from_borrowed_ptr::<_pyo3::PyAny>(_slf) //! .downcast::<_pyo3::PyCell>()?; //! let mut _ref = _cell.try_borrow_mut()?; //! let _slf: &mut Number = &mut *_ref; //! _pyo3::callback::convert(py, Number::increment(_slf)) //! }) //! } //! ``` //! //! # When to use PyCell //! ## Using pyclasses from Rust //! //! However, we *do* need `PyCell` if we want to call its methods from Rust: //! ```rust //! # use pyo3::prelude::*; //! # //! # #[pyclass] //! # struct Number { //! # inner: u32, //! # } //! # //! # #[pymethods] //! # impl Number { //! # fn increment(&mut self) { //! # self.inner += 1; //! # } //! # } //! # fn main() -> PyResult<()> { //! Python::with_gil(|py| { //! let n = Py::new(py, Number { inner: 0 })?; //! //! // We borrow the guard and then dereference //! // it to get a mutable reference to Number //! let mut guard: PyRefMut<'_, Number> = n.bind(py).borrow_mut(); //! let n_mutable: &mut Number = &mut *guard; //! //! n_mutable.increment(); //! //! // To avoid panics we must dispose of the //! // `PyRefMut` before borrowing again. //! drop(guard); //! //! let n_immutable: &Number = &n.bind(py).borrow(); //! assert_eq!(n_immutable.inner, 1); //! //! Ok(()) //! }) //! # } //! ``` //! ## Dealing with possibly overlapping mutable references //! //! It is also necessary to use `PyCell` if you can receive mutable arguments that may overlap. //! Suppose the following function that swaps the values of two `Number`s: //! ``` //! # use pyo3::prelude::*; //! # #[pyclass] //! # pub struct Number { //! # inner: u32, //! # } //! #[pyfunction] //! fn swap_numbers(a: &mut Number, b: &mut Number) { //! std::mem::swap(&mut a.inner, &mut b.inner); //! } //! # fn main() { //! # Python::with_gil(|py| { //! # let n = Py::new(py, Number{inner: 35}).unwrap(); //! # let n2 = n.clone_ref(py); //! # assert!(n.is(&n2)); //! # let fun = pyo3::wrap_pyfunction_bound!(swap_numbers, py).unwrap(); //! # fun.call1((n, n2)).expect_err("Managed to create overlapping mutable references. Note: this is undefined behaviour."); //! # }); //! # } //! ``` //! When users pass in the same `Number` as both arguments, one of the mutable borrows will //! fail and raise a `RuntimeError`: //! ```text //! >>> a = Number() //! >>> swap_numbers(a, a) //! Traceback (most recent call last): //! File "", line 1, in //! RuntimeError: Already borrowed //! ``` //! //! It is better to write that function like this: //! ```rust,ignore //! # #![allow(deprecated)] //! # use pyo3::prelude::*; //! # #[pyclass] //! # pub struct Number { //! # inner: u32, //! # } //! #[pyfunction] //! fn swap_numbers(a: &PyCell, b: &PyCell) { //! // Check that the pointers are unequal //! if !a.is(b) { //! std::mem::swap(&mut a.borrow_mut().inner, &mut b.borrow_mut().inner); //! } else { //! // Do nothing - they are the same object, so don't need swapping. //! } //! } //! # fn main() { //! # // With duplicate numbers //! # Python::with_gil(|py| { //! # let n = Py::new(py, Number{inner: 35}).unwrap(); //! # let n2 = n.clone_ref(py); //! # assert!(n.is(&n2)); //! # let fun = pyo3::wrap_pyfunction_bound!(swap_numbers, py).unwrap(); //! # fun.call1((n, n2)).unwrap(); //! # }); //! # //! # // With two different numbers //! # Python::with_gil(|py| { //! # let n = Py::new(py, Number{inner: 35}).unwrap(); //! # let n2 = Py::new(py, Number{inner: 42}).unwrap(); //! # assert!(!n.is(&n2)); //! # let fun = pyo3::wrap_pyfunction_bound!(swap_numbers, py).unwrap(); //! # fun.call1((&n, &n2)).unwrap(); //! # let n: u32 = n.borrow(py).inner; //! # let n2: u32 = n2.borrow(py).inner; //! # assert_eq!(n, 42); //! # assert_eq!(n2, 35); //! # }); //! # } //! ``` //! See the [guide] for more information. //! //! [guide]: https://pyo3.rs/latest/class.html#pycell-and-interior-mutability "PyCell and interior mutability" //! [Interior Mutability]: https://doc.rust-lang.org/book/ch15-05-interior-mutability.html "RefCell and the Interior Mutability Pattern - The Rust Programming Language" use crate::conversion::AsPyPointer; use crate::exceptions::PyRuntimeError; use crate::ffi_ptr_ext::FfiPtrExt; use crate::internal_tricks::{ptr_from_mut, ptr_from_ref}; use crate::pyclass::{boolean_struct::False, PyClass}; use crate::types::any::PyAnyMethods; #[cfg(feature = "gil-refs")] use crate::{ conversion::ToPyObject, impl_::pyclass::PyClassImpl, pyclass::boolean_struct::True, pyclass_init::PyClassInitializer, type_object::{PyLayout, PySizedLayout}, types::PyAny, PyNativeType, PyResult, PyTypeCheck, }; use crate::{ffi, Bound, IntoPy, PyErr, PyObject, Python}; use std::fmt; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; pub(crate) mod impl_; #[cfg(feature = "gil-refs")] use self::impl_::PyClassObject; use impl_::{PyClassBorrowChecker, PyClassObjectLayout}; /// A container type for (mutably) accessing [`PyClass`] values /// /// `PyCell` autodereferences to [`PyAny`], so you can call `PyAny`'s methods on a `PyCell`. /// /// # Examples /// /// This example demonstrates getting a mutable reference of the contained `PyClass`. /// ```rust /// use pyo3::prelude::*; /// /// #[pyclass] /// struct Number { /// inner: u32, /// } /// /// #[pymethods] /// impl Number { /// fn increment(&mut self) { /// self.inner += 1; /// } /// } /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// # #[allow(deprecated)] /// let n = PyCell::new(py, Number { inner: 0 })?; /// /// let n_mutable: &mut Number = &mut n.borrow_mut(); /// n_mutable.increment(); /// /// Ok(()) /// }) /// # } /// ``` /// For more information on how, when and why (not) to use `PyCell` please see the /// [module-level documentation](self). #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`PyCell` was merged into `Bound`, use that instead; see the migration guide for more info" )] #[repr(transparent)] pub struct PyCell(PyClassObject); #[cfg(feature = "gil-refs")] #[allow(deprecated)] unsafe impl PyNativeType for PyCell { type AsRefSource = T; } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl PyCell { /// Makes a new `PyCell` on the Python heap and return the reference to it. /// /// In cases where the value in the cell does not need to be accessed immediately after /// creation, consider [`Py::new`](crate::Py::new) as a more efficient alternative. #[deprecated( since = "0.21.0", note = "use `Bound::new(py, value)` or `Py::new(py, value)` instead of `PyCell::new(py, value)`" )] pub fn new(py: Python<'_>, value: impl Into>) -> PyResult<&Self> { Bound::new(py, value).map(Bound::into_gil_ref) } /// Immutably borrows the value `T`. This borrow lasts as long as the returned `PyRef` exists. /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// # Panics /// /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use /// [`try_borrow`](#method.try_borrow). pub fn borrow(&self) -> PyRef<'_, T> { PyRef::borrow(&self.as_borrowed()) } /// Mutably borrows the value `T`. This borrow lasts as long as the returned `PyRefMut` exists. /// /// # Panics /// /// Panics if the value is currently borrowed. For a non-panicking variant, use /// [`try_borrow_mut`](#method.try_borrow_mut). pub fn borrow_mut(&self) -> PyRefMut<'_, T> where T: PyClass, { PyRefMut::borrow(&self.as_borrowed()) } /// Immutably borrows the value `T`, returning an error if the value is currently /// mutably borrowed. This borrow lasts as long as the returned `PyRef` exists. /// /// This is the non-panicking variant of [`borrow`](#method.borrow). /// /// For frozen classes, the simpler [`get`][Self::get] is available. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// #[pyclass] /// struct Class {} /// /// Python::with_gil(|py| { /// # #[allow(deprecated)] /// let c = PyCell::new(py, Class {}).unwrap(); /// { /// let m = c.borrow_mut(); /// assert!(c.try_borrow().is_err()); /// } /// /// { /// let m = c.borrow(); /// assert!(c.try_borrow().is_ok()); /// } /// }); /// ``` pub fn try_borrow(&self) -> Result, PyBorrowError> { PyRef::try_borrow(&self.as_borrowed()) } /// Mutably borrows the value `T`, returning an error if the value is currently borrowed. /// This borrow lasts as long as the returned `PyRefMut` exists. /// /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut). /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// #[pyclass] /// struct Class {} /// Python::with_gil(|py| { /// # #[allow(deprecated)] /// let c = PyCell::new(py, Class {}).unwrap(); /// { /// let m = c.borrow(); /// assert!(c.try_borrow_mut().is_err()); /// } /// /// assert!(c.try_borrow_mut().is_ok()); /// }); /// ``` pub fn try_borrow_mut(&self) -> Result, PyBorrowMutError> where T: PyClass, { PyRefMut::try_borrow(&self.as_borrowed()) } /// Immutably borrows the value `T`, returning an error if the value is /// currently mutably borrowed. /// /// # Safety /// /// This method is unsafe because it does not return a `PyRef`, /// thus leaving the borrow flag untouched. Mutably borrowing the `PyCell` /// while the reference returned by this method is alive is undefined behaviour. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// #[pyclass] /// struct Class {} /// Python::with_gil(|py| { /// # #[allow(deprecated)] /// let c = PyCell::new(py, Class {}).unwrap(); /// /// { /// let m = c.borrow_mut(); /// assert!(unsafe { c.try_borrow_unguarded() }.is_err()); /// } /// /// { /// let m = c.borrow(); /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok()); /// } /// }); /// ``` pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, PyBorrowError> { self.0.ensure_threadsafe(); self.0 .borrow_checker() .try_borrow_unguarded() .map(|_: ()| &*self.0.get_ptr()) } /// Provide an immutable borrow of the value `T` without acquiring the GIL. /// /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`]. /// /// While the GIL is usually required to get access to `&PyCell`, /// compared to [`borrow`][Self::borrow] or [`try_borrow`][Self::try_borrow] /// this avoids any thread or borrow checking overhead at runtime. /// /// # Examples /// /// ``` /// use std::sync::atomic::{AtomicUsize, Ordering}; /// # use pyo3::prelude::*; /// /// #[pyclass(frozen)] /// struct FrozenCounter { /// value: AtomicUsize, /// } /// /// Python::with_gil(|py| { /// let counter = FrozenCounter { value: AtomicUsize::new(0) }; /// /// # #[allow(deprecated)] /// let cell = PyCell::new(py, counter).unwrap(); /// /// cell.get().value.fetch_add(1, Ordering::Relaxed); /// }); /// ``` pub fn get(&self) -> &T where T: PyClass + Sync, { // SAFETY: The class itself is frozen and `Sync` and we do not access anything but `self.contents.value`. unsafe { &*self.get_ptr() } } /// Replaces the wrapped value with a new one, returning the old value. /// /// # Panics /// /// Panics if the value is currently borrowed. #[inline] pub fn replace(&self, t: T) -> T where T: PyClass, { std::mem::replace(&mut *self.borrow_mut(), t) } /// Replaces the wrapped value with a new one computed from `f`, returning the old value. /// /// # Panics /// /// Panics if the value is currently borrowed. pub fn replace_with T>(&self, f: F) -> T where T: PyClass, { let mut_borrow = &mut *self.borrow_mut(); let replacement = f(mut_borrow); std::mem::replace(mut_borrow, replacement) } /// Swaps the wrapped value of `self` with the wrapped value of `other`. /// /// # Panics /// /// Panics if the value in either `PyCell` is currently borrowed. #[inline] pub fn swap(&self, other: &Self) where T: PyClass, { std::mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut()) } pub(crate) fn get_ptr(&self) -> *mut T { self.0.get_ptr() } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] unsafe impl PyLayout for PyCell {} #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl PySizedLayout for PyCell {} #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl PyTypeCheck for PyCell where T: PyClass, { const NAME: &'static str = ::NAME; fn type_check(object: &Bound<'_, PyAny>) -> bool { ::type_check(object) } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] unsafe impl AsPyPointer for PyCell { fn as_ptr(&self) -> *mut ffi::PyObject { ptr_from_ref(self) as *mut _ } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl ToPyObject for &PyCell { fn to_object(&self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) } } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl AsRef for PyCell { fn as_ref(&self) -> &PyAny { #[allow(deprecated)] unsafe { self.py().from_borrowed_ptr(self.as_ptr()) } } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl Deref for PyCell { type Target = PyAny; fn deref(&self) -> &PyAny { #[allow(deprecated)] unsafe { self.py().from_borrowed_ptr(self.as_ptr()) } } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl fmt::Debug for PyCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_borrow() { Ok(borrow) => f.debug_struct("RefCell").field("value", &borrow).finish(), Err(_) => { struct BorrowedPlaceholder; impl fmt::Debug for BorrowedPlaceholder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("") } } f.debug_struct("RefCell") .field("value", &BorrowedPlaceholder) .finish() } } } } /// A wrapper type for an immutably borrowed value from a [`Bound<'py, T>`]. /// /// See the [`Bound`] documentation for more information. /// /// # Examples /// /// You can use [`PyRef`] as an alternative to a `&self` receiver when /// - you need to access the pointer of the [`Bound`], or /// - you want to get a super class. /// ``` /// # use pyo3::prelude::*; /// #[pyclass(subclass)] /// struct Parent { /// basename: &'static str, /// } /// /// #[pyclass(extends=Parent)] /// struct Child { /// name: &'static str, /// } /// /// #[pymethods] /// impl Child { /// #[new] /// fn new() -> (Self, Parent) { /// (Child { name: "Caterpillar" }, Parent { basename: "Butterfly" }) /// } /// /// fn format(slf: PyRef<'_, Self>) -> String { /// // We can get *mut ffi::PyObject from PyRef /// let refcnt = unsafe { pyo3::ffi::Py_REFCNT(slf.as_ptr()) }; /// // We can get &Self::BaseType by as_ref /// let basename = slf.as_ref().basename; /// format!("{}(base: {}, cnt: {})", slf.name, basename, refcnt) /// } /// } /// # Python::with_gil(|py| { /// # let sub = Py::new(py, Child::new()).unwrap(); /// # pyo3::py_run!(py, sub, "assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 4)', sub.format()"); /// # }); /// ``` /// /// See the [module-level documentation](self) for more information. #[repr(transparent)] pub struct PyRef<'p, T: PyClass> { // TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to // store `Borrowed` here instead, avoiding reference counting overhead. inner: Bound<'p, T>, } impl<'p, T: PyClass> PyRef<'p, T> { /// Returns a `Python` token that is bound to the lifetime of the `PyRef`. pub fn py(&self) -> Python<'p> { self.inner.py() } } impl<'p, T, U> AsRef for PyRef<'p, T> where T: PyClass, U: PyClass, { fn as_ref(&self) -> &T::BaseType { self.as_super() } } impl<'py, T: PyClass> PyRef<'py, T> { /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.inner.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { self.inner.clone().into_ptr() } #[track_caller] pub(crate) fn borrow(obj: &Bound<'py, T>) -> Self { Self::try_borrow(obj).expect("Already mutably borrowed") } pub(crate) fn try_borrow(obj: &Bound<'py, T>) -> Result { let cell = obj.get_class_object(); cell.ensure_threadsafe(); cell.borrow_checker() .try_borrow() .map(|_| Self { inner: obj.clone() }) } pub(crate) fn try_borrow_threadsafe(obj: &Bound<'py, T>) -> Result { let cell = obj.get_class_object(); cell.check_threadsafe()?; cell.borrow_checker() .try_borrow() .map(|_| Self { inner: obj.clone() }) } } impl<'p, T, U> PyRef<'p, T> where T: PyClass, U: PyClass, { /// Gets a `PyRef`. /// /// While `as_ref()` returns a reference of type `&T::BaseType`, this cannot be /// used to get the base of `T::BaseType`. /// /// But with the help of this method, you can get hold of instances of the /// super-superclass when needed. /// /// # Examples /// ``` /// # use pyo3::prelude::*; /// #[pyclass(subclass)] /// struct Base1 { /// name1: &'static str, /// } /// /// #[pyclass(extends=Base1, subclass)] /// struct Base2 { /// name2: &'static str, /// } /// /// #[pyclass(extends=Base2)] /// struct Sub { /// name3: &'static str, /// } /// /// #[pymethods] /// impl Sub { /// #[new] /// fn new() -> PyClassInitializer { /// PyClassInitializer::from(Base1 { name1: "base1" }) /// .add_subclass(Base2 { name2: "base2" }) /// .add_subclass(Self { name3: "sub" }) /// } /// fn name(slf: PyRef<'_, Self>) -> String { /// let subname = slf.name3; /// let super_ = slf.into_super(); /// format!("{} {} {}", super_.as_ref().name1, super_.name2, subname) /// } /// } /// # Python::with_gil(|py| { /// # let sub = Py::new(py, Sub::new()).unwrap(); /// # pyo3::py_run!(py, sub, "assert sub.name() == 'base1 base2 sub'") /// # }); /// ``` pub fn into_super(self) -> PyRef<'p, U> { let py = self.py(); PyRef { inner: unsafe { ManuallyDrop::new(self) .as_ptr() .assume_owned(py) .downcast_into_unchecked() }, } } /// Borrows a shared reference to `PyRef`. /// /// With the help of this method, you can access attributes and call methods /// on the superclass without consuming the `PyRef`. This method can also /// be chained to access the super-superclass (and so on). /// /// # Examples /// ``` /// # use pyo3::prelude::*; /// #[pyclass(subclass)] /// struct Base { /// base_name: &'static str, /// } /// #[pymethods] /// impl Base { /// fn base_name_len(&self) -> usize { /// self.base_name.len() /// } /// } /// /// #[pyclass(extends=Base)] /// struct Sub { /// sub_name: &'static str, /// } /// /// #[pymethods] /// impl Sub { /// #[new] /// fn new() -> (Self, Base) { /// (Self { sub_name: "sub_name" }, Base { base_name: "base_name" }) /// } /// fn sub_name_len(&self) -> usize { /// self.sub_name.len() /// } /// fn format_name_lengths(slf: PyRef<'_, Self>) -> String { /// format!("{} {}", slf.as_super().base_name_len(), slf.sub_name_len()) /// } /// } /// # Python::with_gil(|py| { /// # let sub = Py::new(py, Sub::new()).unwrap(); /// # pyo3::py_run!(py, sub, "assert sub.format_name_lengths() == '9 8'") /// # }); /// ``` pub fn as_super(&self) -> &PyRef<'p, U> { let ptr = ptr_from_ref::>(&self.inner) // `Bound` has the same layout as `Bound` .cast::>() // `Bound` has the same layout as `PyRef` .cast::>(); unsafe { &*ptr } } } impl<'p, T: PyClass> Deref for PyRef<'p, T> { type Target = T; #[inline] fn deref(&self) -> &T { unsafe { &*self.inner.get_class_object().get_ptr() } } } impl<'p, T: PyClass> Drop for PyRef<'p, T> { fn drop(&mut self) { self.inner .get_class_object() .borrow_checker() .release_borrow() } } impl IntoPy for PyRef<'_, T> { fn into_py(self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_borrowed_ptr(py, self.inner.as_ptr()) } } } impl IntoPy for &'_ PyRef<'_, T> { fn into_py(self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_borrowed_ptr(py, self.inner.as_ptr()) } } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl<'a, T: PyClass> std::convert::TryFrom<&'a PyCell> for crate::PyRef<'a, T> { type Error = PyBorrowError; fn try_from(cell: &'a crate::PyCell) -> Result { cell.try_borrow() } } unsafe impl<'a, T: PyClass> AsPyPointer for PyRef<'a, T> { fn as_ptr(&self) -> *mut ffi::PyObject { self.inner.as_ptr() } } impl fmt::Debug for PyRef<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } /// A wrapper type for a mutably borrowed value from a [`Bound<'py, T>`]. /// /// See the [module-level documentation](self) for more information. #[repr(transparent)] pub struct PyRefMut<'p, T: PyClass> { // TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to // store `Borrowed` here instead, avoiding reference counting overhead. inner: Bound<'p, T>, } impl<'p, T: PyClass> PyRefMut<'p, T> { /// Returns a `Python` token that is bound to the lifetime of the `PyRefMut`. pub fn py(&self) -> Python<'p> { self.inner.py() } } impl<'p, T, U> AsRef for PyRefMut<'p, T> where T: PyClass, U: PyClass, { fn as_ref(&self) -> &T::BaseType { PyRefMut::downgrade(self).as_super() } } impl<'p, T, U> AsMut for PyRefMut<'p, T> where T: PyClass, U: PyClass, { fn as_mut(&mut self) -> &mut T::BaseType { self.as_super() } } impl<'py, T: PyClass> PyRefMut<'py, T> { /// Returns the raw FFI pointer represented by self. /// /// # Safety /// /// Callers are responsible for ensuring that the pointer does not outlive self. /// /// The reference is borrowed; callers should not decrease the reference count /// when they are finished with the pointer. #[inline] pub fn as_ptr(&self) -> *mut ffi::PyObject { self.inner.as_ptr() } /// Returns an owned raw FFI pointer represented by self. /// /// # Safety /// /// The reference is owned; when finished the caller should either transfer ownership /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)). #[inline] pub fn into_ptr(self) -> *mut ffi::PyObject { self.inner.clone().into_ptr() } #[inline] #[track_caller] pub(crate) fn borrow(obj: &Bound<'py, T>) -> Self { Self::try_borrow(obj).expect("Already borrowed") } pub(crate) fn try_borrow(obj: &Bound<'py, T>) -> Result { let cell = obj.get_class_object(); cell.ensure_threadsafe(); cell.borrow_checker() .try_borrow_mut() .map(|_| Self { inner: obj.clone() }) } pub(crate) fn downgrade(slf: &Self) -> &PyRef<'py, T> { // `PyRefMut` and `PyRef` have the same layout unsafe { &*ptr_from_ref(slf).cast() } } } impl<'p, T, U> PyRefMut<'p, T> where T: PyClass, U: PyClass, { /// Gets a `PyRef`. /// /// See [`PyRef::into_super`] for more. pub fn into_super(self) -> PyRefMut<'p, U> { let py = self.py(); PyRefMut { inner: unsafe { ManuallyDrop::new(self) .as_ptr() .assume_owned(py) .downcast_into_unchecked() }, } } /// Borrows a mutable reference to `PyRefMut`. /// /// With the help of this method, you can mutate attributes and call mutating /// methods on the superclass without consuming the `PyRefMut`. This method /// can also be chained to access the super-superclass (and so on). /// /// See [`PyRef::as_super`] for more. pub fn as_super(&mut self) -> &mut PyRefMut<'p, U> { let ptr = ptr_from_mut::>(&mut self.inner) // `Bound` has the same layout as `Bound` .cast::>() // `Bound` has the same layout as `PyRefMut`, // and the mutable borrow on `self` prevents aliasing .cast::>(); unsafe { &mut *ptr } } } impl<'p, T: PyClass> Deref for PyRefMut<'p, T> { type Target = T; #[inline] fn deref(&self) -> &T { unsafe { &*self.inner.get_class_object().get_ptr() } } } impl<'p, T: PyClass> DerefMut for PyRefMut<'p, T> { #[inline] fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.inner.get_class_object().get_ptr() } } } impl<'p, T: PyClass> Drop for PyRefMut<'p, T> { fn drop(&mut self) { self.inner .get_class_object() .borrow_checker() .release_borrow_mut() } } impl> IntoPy for PyRefMut<'_, T> { fn into_py(self, py: Python<'_>) -> PyObject { unsafe { PyObject::from_borrowed_ptr(py, self.inner.as_ptr()) } } } impl> IntoPy for &'_ PyRefMut<'_, T> { fn into_py(self, py: Python<'_>) -> PyObject { self.inner.clone().into_py(py) } } unsafe impl<'a, T: PyClass> AsPyPointer for PyRefMut<'a, T> { fn as_ptr(&self) -> *mut ffi::PyObject { self.inner.as_ptr() } } #[cfg(feature = "gil-refs")] #[allow(deprecated)] impl<'a, T: PyClass> std::convert::TryFrom<&'a PyCell> for crate::PyRefMut<'a, T> { type Error = PyBorrowMutError; fn try_from(cell: &'a crate::PyCell) -> Result { cell.try_borrow_mut() } } impl + fmt::Debug> fmt::Debug for PyRefMut<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(self.deref(), f) } } /// An error type returned by [`Bound::try_borrow`]. /// /// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`. pub struct PyBorrowError { _private: (), } impl fmt::Debug for PyBorrowError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PyBorrowError").finish() } } impl fmt::Display for PyBorrowError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt("Already mutably borrowed", f) } } impl From for PyErr { fn from(other: PyBorrowError) -> Self { PyRuntimeError::new_err(other.to_string()) } } /// An error type returned by [`Bound::try_borrow_mut`]. /// /// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`. pub struct PyBorrowMutError { _private: (), } impl fmt::Debug for PyBorrowMutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("PyBorrowMutError").finish() } } impl fmt::Display for PyBorrowMutError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt("Already borrowed", f) } } impl From for PyErr { fn from(other: PyBorrowMutError) -> Self { PyRuntimeError::new_err(other.to_string()) } } #[cfg(test)] #[cfg(feature = "macros")] mod tests { use super::*; #[crate::pyclass] #[pyo3(crate = "crate")] #[derive(Copy, Clone, PartialEq, Eq, Debug)] struct SomeClass(i32); #[cfg(feature = "gil-refs")] mod deprecated { use super::*; #[test] fn pycell_replace() { Python::with_gil(|py| { #[allow(deprecated)] let cell = PyCell::new(py, SomeClass(0)).unwrap(); assert_eq!(*cell.borrow(), SomeClass(0)); let previous = cell.replace(SomeClass(123)); assert_eq!(previous, SomeClass(0)); assert_eq!(*cell.borrow(), SomeClass(123)); }) } #[test] #[should_panic(expected = "Already borrowed: PyBorrowMutError")] fn pycell_replace_panic() { Python::with_gil(|py| { #[allow(deprecated)] let cell = PyCell::new(py, SomeClass(0)).unwrap(); let _guard = cell.borrow(); cell.replace(SomeClass(123)); }) } #[test] fn pycell_replace_with() { Python::with_gil(|py| { #[allow(deprecated)] let cell = PyCell::new(py, SomeClass(0)).unwrap(); assert_eq!(*cell.borrow(), SomeClass(0)); let previous = cell.replace_with(|value| { *value = SomeClass(2); SomeClass(123) }); assert_eq!(previous, SomeClass(2)); assert_eq!(*cell.borrow(), SomeClass(123)); }) } #[test] #[should_panic(expected = "Already borrowed: PyBorrowMutError")] fn pycell_replace_with_panic() { Python::with_gil(|py| { #[allow(deprecated)] let cell = PyCell::new(py, SomeClass(0)).unwrap(); let _guard = cell.borrow(); cell.replace_with(|_| SomeClass(123)); }) } #[test] fn pycell_swap() { Python::with_gil(|py| { #[allow(deprecated)] let cell = PyCell::new(py, SomeClass(0)).unwrap(); #[allow(deprecated)] let cell2 = PyCell::new(py, SomeClass(123)).unwrap(); assert_eq!(*cell.borrow(), SomeClass(0)); assert_eq!(*cell2.borrow(), SomeClass(123)); cell.swap(cell2); assert_eq!(*cell.borrow(), SomeClass(123)); assert_eq!(*cell2.borrow(), SomeClass(0)); }) } #[test] #[should_panic(expected = "Already borrowed: PyBorrowMutError")] fn pycell_swap_panic() { Python::with_gil(|py| { #[allow(deprecated)] let cell = PyCell::new(py, SomeClass(0)).unwrap(); #[allow(deprecated)] let cell2 = PyCell::new(py, SomeClass(123)).unwrap(); let _guard = cell.borrow(); cell.swap(cell2); }) } #[test] #[should_panic(expected = "Already borrowed: PyBorrowMutError")] fn pycell_swap_panic_other_borrowed() { Python::with_gil(|py| { #[allow(deprecated)] let cell = PyCell::new(py, SomeClass(0)).unwrap(); #[allow(deprecated)] let cell2 = PyCell::new(py, SomeClass(123)).unwrap(); let _guard = cell2.borrow(); cell.swap(cell2); }) } } #[test] fn test_as_ptr() { Python::with_gil(|py| { let cell = Bound::new(py, SomeClass(0)).unwrap(); let ptr = cell.as_ptr(); assert_eq!(cell.borrow().as_ptr(), ptr); assert_eq!(cell.borrow_mut().as_ptr(), ptr); }) } #[test] fn test_into_ptr() { Python::with_gil(|py| { let cell = Bound::new(py, SomeClass(0)).unwrap(); let ptr = cell.as_ptr(); assert_eq!(cell.borrow().into_ptr(), ptr); unsafe { ffi::Py_DECREF(ptr) }; assert_eq!(cell.borrow_mut().into_ptr(), ptr); unsafe { ffi::Py_DECREF(ptr) }; }) } #[crate::pyclass] #[pyo3(crate = "crate", subclass)] struct BaseClass { val1: usize, } #[crate::pyclass] #[pyo3(crate = "crate", extends=BaseClass, subclass)] struct SubClass { val2: usize, } #[crate::pyclass] #[pyo3(crate = "crate", extends=SubClass)] struct SubSubClass { val3: usize, } #[crate::pymethods] #[pyo3(crate = "crate")] impl SubSubClass { #[new] fn new(py: Python<'_>) -> crate::Py { let init = crate::PyClassInitializer::from(BaseClass { val1: 10 }) .add_subclass(SubClass { val2: 15 }) .add_subclass(SubSubClass { val3: 20 }); crate::Py::new(py, init).expect("allocation error") } fn get_values(self_: PyRef<'_, Self>) -> (usize, usize, usize) { let val1 = self_.as_super().as_super().val1; let val2 = self_.as_super().val2; (val1, val2, self_.val3) } fn double_values(mut self_: PyRefMut<'_, Self>) { self_.as_super().as_super().val1 *= 2; self_.as_super().val2 *= 2; self_.val3 *= 2; } } #[test] fn test_pyref_as_super() { Python::with_gil(|py| { let obj = SubSubClass::new(py).into_bound(py); let pyref = obj.borrow(); assert_eq!(pyref.as_super().as_super().val1, 10); assert_eq!(pyref.as_super().val2, 15); assert_eq!(pyref.as_ref().val2, 15); // `as_ref` also works assert_eq!(pyref.val3, 20); assert_eq!(SubSubClass::get_values(pyref), (10, 15, 20)); }); } #[test] fn test_pyrefmut_as_super() { Python::with_gil(|py| { let obj = SubSubClass::new(py).into_bound(py); assert_eq!(SubSubClass::get_values(obj.borrow()), (10, 15, 20)); { let mut pyrefmut = obj.borrow_mut(); assert_eq!(pyrefmut.as_super().as_ref().val1, 10); pyrefmut.as_super().as_super().val1 -= 5; pyrefmut.as_super().val2 -= 3; pyrefmut.as_mut().val2 -= 2; // `as_mut` also works pyrefmut.val3 -= 5; } assert_eq!(SubSubClass::get_values(obj.borrow()), (5, 10, 15)); SubSubClass::double_values(obj.borrow_mut()); assert_eq!(SubSubClass::get_values(obj.borrow()), (10, 20, 30)); }); } #[test] fn test_pyrefs_in_python() { Python::with_gil(|py| { let obj = SubSubClass::new(py); crate::py_run!(py, obj, "assert obj.get_values() == (10, 15, 20)"); crate::py_run!(py, obj, "assert obj.double_values() is None"); crate::py_run!(py, obj, "assert obj.get_values() == (20, 30, 40)"); }); } } pyo3/src/inspect/0000775000175000017500000000000014661133735014671 5ustar jamespagejamespagepyo3/src/inspect/mod.rs0000644000175000017500000000021014661133735016005 0ustar jamespagejamespage//! Runtime inspection of objects exposed to Python. //! //! Tracking issue: . pub mod types; pyo3/src/inspect/types.rs0000644000175000017500000003643014661133735016407 0ustar jamespagejamespage//! Data types used to describe runtime Python types. use std::borrow::Cow; use std::fmt::{Display, Formatter}; /// Designation of a Python type. /// /// This enum is used to handle advanced types, such as types with generics. /// Its [`Display`] implementation can be used to convert to the type hint notation (e.g. `List[int]`). #[derive(Debug, Clone, Eq, PartialEq)] pub enum TypeInfo { /// The type `typing.Any`, which represents any possible value (unknown type). Any, /// The type `typing.None`. None, /// The type `typing.NoReturn`, which represents functions that never return (they can still panic / throw, similar to `never` in Rust). NoReturn, /// The type `typing.Callable`. /// /// The first argument represents the parameters of the callable: /// - `Some` of a vector of types to represent the signature, /// - `None` if the signature is unknown (allows any number of arguments with type `Any`). /// /// The second argument represents the return type. Callable(Option>, Box), /// The type `typing.tuple`. /// /// The argument represents the contents of the tuple: /// - `Some` of a vector of types to represent the accepted types, /// - `Some` of an empty vector for the empty tuple, /// - `None` if the number and type of accepted values is unknown. /// /// If the number of accepted values is unknown, but their type is, use [`Self::UnsizedTypedTuple`]. Tuple(Option>), /// The type `typing.Tuple`. /// /// Use this variant to represent a tuple of unknown size but of known types. /// /// If the type is unknown, or if the number of elements is known, use [`Self::Tuple`]. UnsizedTypedTuple(Box), /// A Python class. Class { /// The module this class comes from. module: ModuleName, /// The name of this class, as it appears in a type hint. name: Cow<'static, str>, /// The generics accepted by this class (empty vector if this class is not generic). type_vars: Vec, }, } /// Declares which module a type is a part of. #[derive(Debug, Clone, Eq, PartialEq)] pub enum ModuleName { /// The type is built-in: it doesn't need to be imported. Builtin, /// The type is in the current module: it doesn't need to be imported in this module, but needs to be imported in others. CurrentModule, /// The type is in the specified module. Module(Cow<'static, str>), } impl TypeInfo { /// Returns the module in which a type is declared. /// /// Returns `None` if the type is declared in the current module. pub fn module_name(&self) -> Option<&str> { match self { TypeInfo::Any | TypeInfo::None | TypeInfo::NoReturn | TypeInfo::Callable(_, _) | TypeInfo::Tuple(_) | TypeInfo::UnsizedTypedTuple(_) => Some("typing"), TypeInfo::Class { module, .. } => match module { ModuleName::Builtin => Some("builtins"), ModuleName::CurrentModule => None, ModuleName::Module(name) => Some(name), }, } } /// Returns the name of a type. /// /// The name of a type is the part of the hint that is not generic (e.g. `List` instead of `List[int]`). pub fn name(&self) -> Cow<'_, str> { Cow::from(match self { TypeInfo::Any => "Any", TypeInfo::None => "None", TypeInfo::NoReturn => "NoReturn", TypeInfo::Callable(_, _) => "Callable", TypeInfo::Tuple(_) => "Tuple", TypeInfo::UnsizedTypedTuple(_) => "Tuple", TypeInfo::Class { name, .. } => name, }) } } // Utilities for easily instantiating TypeInfo structures for built-in/common types. impl TypeInfo { /// The Python `Optional` type. pub fn optional_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Optional"), type_vars: vec![t], } } /// The Python `Union` type. pub fn union_of(types: &[TypeInfo]) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Union"), type_vars: types.to_vec(), } } /// The Python `List` type. pub fn list_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("List"), type_vars: vec![t], } } /// The Python `Sequence` type. pub fn sequence_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Sequence"), type_vars: vec![t], } } /// The Python `Set` type. pub fn set_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Set"), type_vars: vec![t], } } /// The Python `FrozenSet` type. pub fn frozen_set_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("FrozenSet"), type_vars: vec![t], } } /// The Python `Iterable` type. pub fn iterable_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Iterable"), type_vars: vec![t], } } /// The Python `Iterator` type. pub fn iterator_of(t: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Iterator"), type_vars: vec![t], } } /// The Python `Dict` type. pub fn dict_of(k: TypeInfo, v: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Dict"), type_vars: vec![k, v], } } /// The Python `Mapping` type. pub fn mapping_of(k: TypeInfo, v: TypeInfo) -> TypeInfo { TypeInfo::Class { module: ModuleName::Module(Cow::from("typing")), name: Cow::from("Mapping"), type_vars: vec![k, v], } } /// Convenience factory for non-generic builtins (e.g. `int`). pub fn builtin(name: &'static str) -> TypeInfo { TypeInfo::Class { module: ModuleName::Builtin, name: Cow::from(name), type_vars: vec![], } } } impl Display for TypeInfo { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { TypeInfo::Any | TypeInfo::None | TypeInfo::NoReturn => write!(f, "{}", self.name()), TypeInfo::Callable(input, output) => { write!(f, "Callable[")?; if let Some(input) = input { write!(f, "[")?; let mut comma = false; for arg in input { if comma { write!(f, ", ")?; } write!(f, "{}", arg)?; comma = true; } write!(f, "]")?; } else { write!(f, "...")?; } write!(f, ", {}]", output) } TypeInfo::Tuple(types) => { write!(f, "Tuple[")?; if let Some(types) = types { if types.is_empty() { write!(f, "()")?; } else { let mut comma = false; for t in types { if comma { write!(f, ", ")?; } write!(f, "{}", t)?; comma = true; } } } else { write!(f, "...")?; } write!(f, "]") } TypeInfo::UnsizedTypedTuple(t) => write!(f, "Tuple[{}, ...]", t), TypeInfo::Class { name, type_vars, .. } => { write!(f, "{}", name)?; if !type_vars.is_empty() { write!(f, "[")?; let mut comma = false; for var in type_vars { if comma { write!(f, ", ")?; } write!(f, "{}", var)?; comma = true; } write!(f, "]") } else { Ok(()) } } } } } #[cfg(test)] mod test { use std::borrow::Cow; use crate::inspect::types::{ModuleName, TypeInfo}; pub fn assert_display(t: &TypeInfo, expected: &str) { assert_eq!(format!("{}", t), expected) } #[test] fn basic() { assert_display(&TypeInfo::Any, "Any"); assert_display(&TypeInfo::None, "None"); assert_display(&TypeInfo::NoReturn, "NoReturn"); assert_display(&TypeInfo::builtin("int"), "int"); } #[test] fn callable() { let any_to_int = TypeInfo::Callable(None, Box::new(TypeInfo::builtin("int"))); assert_display(&any_to_int, "Callable[..., int]"); let sum = TypeInfo::Callable( Some(vec![TypeInfo::builtin("int"), TypeInfo::builtin("int")]), Box::new(TypeInfo::builtin("int")), ); assert_display(&sum, "Callable[[int, int], int]"); } #[test] fn tuple() { let any = TypeInfo::Tuple(None); assert_display(&any, "Tuple[...]"); let triple = TypeInfo::Tuple(Some(vec![ TypeInfo::builtin("int"), TypeInfo::builtin("str"), TypeInfo::builtin("bool"), ])); assert_display(&triple, "Tuple[int, str, bool]"); let empty = TypeInfo::Tuple(Some(vec![])); assert_display(&empty, "Tuple[()]"); let typed = TypeInfo::UnsizedTypedTuple(Box::new(TypeInfo::builtin("bool"))); assert_display(&typed, "Tuple[bool, ...]"); } #[test] fn class() { let class1 = TypeInfo::Class { module: ModuleName::CurrentModule, name: Cow::from("MyClass"), type_vars: vec![], }; assert_display(&class1, "MyClass"); let class2 = TypeInfo::Class { module: ModuleName::CurrentModule, name: Cow::from("MyClass"), type_vars: vec![TypeInfo::builtin("int"), TypeInfo::builtin("bool")], }; assert_display(&class2, "MyClass[int, bool]"); } #[test] fn collections() { let int = TypeInfo::builtin("int"); let bool = TypeInfo::builtin("bool"); let str = TypeInfo::builtin("str"); let list = TypeInfo::list_of(int.clone()); assert_display(&list, "List[int]"); let sequence = TypeInfo::sequence_of(bool.clone()); assert_display(&sequence, "Sequence[bool]"); let optional = TypeInfo::optional_of(str.clone()); assert_display(&optional, "Optional[str]"); let iterable = TypeInfo::iterable_of(int.clone()); assert_display(&iterable, "Iterable[int]"); let iterator = TypeInfo::iterator_of(bool); assert_display(&iterator, "Iterator[bool]"); let dict = TypeInfo::dict_of(int.clone(), str.clone()); assert_display(&dict, "Dict[int, str]"); let mapping = TypeInfo::mapping_of(int, str.clone()); assert_display(&mapping, "Mapping[int, str]"); let set = TypeInfo::set_of(str.clone()); assert_display(&set, "Set[str]"); let frozen_set = TypeInfo::frozen_set_of(str); assert_display(&frozen_set, "FrozenSet[str]"); } #[test] fn complicated() { let int = TypeInfo::builtin("int"); assert_display(&int, "int"); let bool = TypeInfo::builtin("bool"); assert_display(&bool, "bool"); let str = TypeInfo::builtin("str"); assert_display(&str, "str"); let any = TypeInfo::Any; assert_display(&any, "Any"); let params = TypeInfo::union_of(&[int.clone(), str]); assert_display(¶ms, "Union[int, str]"); let func = TypeInfo::Callable(Some(vec![params, any]), Box::new(bool)); assert_display(&func, "Callable[[Union[int, str], Any], bool]"); let dict = TypeInfo::mapping_of(int, func); assert_display( &dict, "Mapping[int, Callable[[Union[int, str], Any], bool]]", ); } } #[cfg(test)] mod conversion { use std::collections::{HashMap, HashSet}; use crate::inspect::types::test::assert_display; use crate::{FromPyObject, IntoPy}; #[test] fn unsigned_int() { assert_display(&usize::type_output(), "int"); assert_display(&usize::type_input(), "int"); assert_display(&u8::type_output(), "int"); assert_display(&u8::type_input(), "int"); assert_display(&u16::type_output(), "int"); assert_display(&u16::type_input(), "int"); assert_display(&u32::type_output(), "int"); assert_display(&u32::type_input(), "int"); assert_display(&u64::type_output(), "int"); assert_display(&u64::type_input(), "int"); } #[test] fn signed_int() { assert_display(&isize::type_output(), "int"); assert_display(&isize::type_input(), "int"); assert_display(&i8::type_output(), "int"); assert_display(&i8::type_input(), "int"); assert_display(&i16::type_output(), "int"); assert_display(&i16::type_input(), "int"); assert_display(&i32::type_output(), "int"); assert_display(&i32::type_input(), "int"); assert_display(&i64::type_output(), "int"); assert_display(&i64::type_input(), "int"); } #[test] fn float() { assert_display(&f32::type_output(), "float"); assert_display(&f32::type_input(), "float"); assert_display(&f64::type_output(), "float"); assert_display(&f64::type_input(), "float"); } #[test] fn bool() { assert_display(&bool::type_output(), "bool"); assert_display(&bool::type_input(), "bool"); } #[test] fn text() { assert_display(&String::type_output(), "str"); assert_display(&String::type_input(), "str"); assert_display(&<&[u8]>::type_output(), "bytes"); assert_display( &<&[u8] as crate::conversion::FromPyObjectBound>::type_input(), "bytes", ); } #[test] fn collections() { assert_display(&>::type_output(), "List[int]"); assert_display(&>::type_input(), "Sequence[int]"); assert_display(&>::type_output(), "Set[int]"); assert_display(&>::type_input(), "Set[int]"); assert_display(&>::type_output(), "Dict[int, float]"); assert_display(&>::type_input(), "Mapping[int, float]"); assert_display(&<(usize, f32)>::type_input(), "Tuple[int, float]"); } } pyo3/src/version.rs0000644000175000017500000001157014661133735015261 0ustar jamespagejamespage/// Represents the major, minor, and patch (if any) versions of this interpreter. /// /// This struct is usually created with [`Python::version`]. /// /// # Examples /// /// ```rust /// # use pyo3::Python; /// Python::with_gil(|py| { /// // PyO3 supports Python 3.7 and up. /// assert!(py.version_info() >= (3, 7)); /// assert!(py.version_info() >= (3, 7, 0)); /// }); /// ``` /// /// [`Python::version`]: crate::marker::Python::version #[derive(Debug)] pub struct PythonVersionInfo<'py> { /// Python major version (e.g. `3`). pub major: u8, /// Python minor version (e.g. `11`). pub minor: u8, /// Python patch version (e.g. `0`). pub patch: u8, /// Python version suffix, if applicable (e.g. `a0`). pub suffix: Option<&'py str>, } impl<'py> PythonVersionInfo<'py> { /// Parses a hard-coded Python interpreter version string (e.g. 3.9.0a4+). pub(crate) fn from_str(version_number_str: &'py str) -> Result { fn split_and_parse_number(version_part: &str) -> (u8, Option<&str>) { match version_part.find(|c: char| !c.is_ascii_digit()) { None => (version_part.parse().unwrap(), None), Some(version_part_suffix_start) => { let (version_part, version_part_suffix) = version_part.split_at(version_part_suffix_start); (version_part.parse().unwrap(), Some(version_part_suffix)) } } } let mut parts = version_number_str.split('.'); let major_str = parts.next().ok_or("Python major version missing")?; let minor_str = parts.next().ok_or("Python minor version missing")?; let patch_str = parts.next(); if parts.next().is_some() { return Err("Python version string has too many parts"); }; let major = major_str .parse() .map_err(|_| "Python major version not an integer")?; let (minor, suffix) = split_and_parse_number(minor_str); if suffix.is_some() { assert!(patch_str.is_none()); return Ok(PythonVersionInfo { major, minor, patch: 0, suffix, }); } let (patch, suffix) = patch_str.map(split_and_parse_number).unwrap_or_default(); Ok(PythonVersionInfo { major, minor, patch, suffix, }) } } impl PartialEq<(u8, u8)> for PythonVersionInfo<'_> { fn eq(&self, other: &(u8, u8)) -> bool { self.major == other.0 && self.minor == other.1 } } impl PartialEq<(u8, u8, u8)> for PythonVersionInfo<'_> { fn eq(&self, other: &(u8, u8, u8)) -> bool { self.major == other.0 && self.minor == other.1 && self.patch == other.2 } } impl PartialOrd<(u8, u8)> for PythonVersionInfo<'_> { fn partial_cmp(&self, other: &(u8, u8)) -> Option { (self.major, self.minor).partial_cmp(other) } } impl PartialOrd<(u8, u8, u8)> for PythonVersionInfo<'_> { fn partial_cmp(&self, other: &(u8, u8, u8)) -> Option { (self.major, self.minor, self.patch).partial_cmp(other) } } #[cfg(test)] mod test { use super::*; use crate::Python; #[test] fn test_python_version_info() { Python::with_gil(|py| { let version = py.version_info(); #[cfg(Py_3_7)] assert!(version >= (3, 7)); #[cfg(Py_3_7)] assert!(version >= (3, 7, 0)); #[cfg(Py_3_8)] assert!(version >= (3, 8)); #[cfg(Py_3_8)] assert!(version >= (3, 8, 0)); #[cfg(Py_3_9)] assert!(version >= (3, 9)); #[cfg(Py_3_9)] assert!(version >= (3, 9, 0)); #[cfg(Py_3_10)] assert!(version >= (3, 10)); #[cfg(Py_3_10)] assert!(version >= (3, 10, 0)); #[cfg(Py_3_11)] assert!(version >= (3, 11)); #[cfg(Py_3_11)] assert!(version >= (3, 11, 0)); }); } #[test] fn test_python_version_info_parse() { assert!(PythonVersionInfo::from_str("3.5.0a1").unwrap() >= (3, 5, 0)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() >= (3, 5, 0)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() == (3, 5, 0)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() != (3, 5, 1)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() < (3, 5, 3)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() == (3, 5, 2)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() == (3, 5)); assert!(PythonVersionInfo::from_str("3.5+").unwrap() == (3, 5)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() < (3, 6)); assert!(PythonVersionInfo::from_str("3.5.2a1+").unwrap() > (3, 4)); } } pyo3/src/panic.rs0000644000175000017500000000174714661133735014673 0ustar jamespagejamespage//! Helper to convert Rust panics to Python exceptions. use crate::exceptions::PyBaseException; use crate::PyErr; use std::any::Any; pyo3_exception!( " The exception raised when Rust code called from Python panics. Like SystemExit, this exception is derived from BaseException so that it will typically propagate all the way through the stack and cause the Python interpreter to exit. ", PanicException, PyBaseException ); impl PanicException { /// Creates a new PanicException from a panic payload. /// /// Attempts to format the error in the same way panic does. #[cold] pub(crate) fn from_panic_payload(payload: Box) -> PyErr { if let Some(string) = payload.downcast_ref::() { Self::new_err((string.clone(),)) } else if let Some(s) = payload.downcast_ref::<&str>() { Self::new_err((s.to_string(),)) } else { Self::new_err(("panic from Rust code",)) } } } pyo3/src/coroutine/0000775000175000017500000000000014661133735015233 5ustar jamespagejamespagepyo3/src/coroutine/cancel.rs0000644000175000017500000000414714661133735017032 0ustar jamespagejamespageuse crate::{Py, PyAny, PyObject}; use std::future::Future; use std::pin::Pin; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll, Waker}; #[derive(Debug, Default)] struct Inner { exception: Option, waker: Option, } /// Helper used to wait and retrieve exception thrown in [`Coroutine`](super::Coroutine). /// /// Only the last exception thrown can be retrieved. #[derive(Debug, Default)] pub struct CancelHandle(Arc>); impl CancelHandle { /// Create a new `CoroutineCancel`. pub fn new() -> Self { Default::default() } /// Returns whether the associated coroutine has been cancelled. pub fn is_cancelled(&self) -> bool { self.0.lock().unwrap().exception.is_some() } /// Poll to retrieve the exception thrown in the associated coroutine. pub fn poll_cancelled(&mut self, cx: &mut Context<'_>) -> Poll { let mut inner = self.0.lock().unwrap(); if let Some(exc) = inner.exception.take() { return Poll::Ready(exc); } if let Some(ref waker) = inner.waker { if cx.waker().will_wake(waker) { return Poll::Pending; } } inner.waker = Some(cx.waker().clone()); Poll::Pending } /// Retrieve the exception thrown in the associated coroutine. pub async fn cancelled(&mut self) -> PyObject { Cancelled(self).await } #[doc(hidden)] pub fn throw_callback(&self) -> ThrowCallback { ThrowCallback(self.0.clone()) } } // Because `poll_fn` is not available in MSRV struct Cancelled<'a>(&'a mut CancelHandle); impl Future for Cancelled<'_> { type Output = PyObject; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { self.0.poll_cancelled(cx) } } #[doc(hidden)] pub struct ThrowCallback(Arc>); impl ThrowCallback { pub(super) fn throw(&self, exc: Py) { let mut inner = self.0.lock().unwrap(); inner.exception = Some(exc); if let Some(waker) = inner.waker.take() { waker.wake(); } } } pyo3/src/coroutine/waker.rs0000644000175000017500000000734014661133735016714 0ustar jamespagejamespageuse crate::sync::GILOnceCell; use crate::types::any::PyAnyMethods; use crate::types::PyCFunction; use crate::{intern, wrap_pyfunction_bound, Bound, Py, PyAny, PyObject, PyResult, Python}; use pyo3_macros::pyfunction; use std::sync::Arc; use std::task::Wake; /// Lazy `asyncio.Future` wrapper, implementing [`Wake`] by calling `Future.set_result`. /// /// asyncio future is let uninitialized until [`initialize_future`][1] is called. /// If [`wake`][2] is called before future initialization (during Rust future polling), /// [`initialize_future`][1] will return `None` (it is roughly equivalent to `asyncio.sleep(0)`) /// /// [1]: AsyncioWaker::initialize_future /// [2]: AsyncioWaker::wake pub struct AsyncioWaker(GILOnceCell>); impl AsyncioWaker { pub(super) fn new() -> Self { Self(GILOnceCell::new()) } pub(super) fn reset(&mut self) { self.0.take(); } pub(super) fn initialize_future<'py>( &self, py: Python<'py>, ) -> PyResult>> { let init = || LoopAndFuture::new(py).map(Some); let loop_and_future = self.0.get_or_try_init(py, init)?.as_ref(); Ok(loop_and_future.map(|LoopAndFuture { future, .. }| future.bind(py))) } } impl Wake for AsyncioWaker { fn wake(self: Arc) { self.wake_by_ref() } fn wake_by_ref(self: &Arc) { Python::with_gil(|gil| { if let Some(loop_and_future) = self.0.get_or_init(gil, || None) { loop_and_future .set_result(gil) .expect("unexpected error in coroutine waker"); } }); } } struct LoopAndFuture { event_loop: PyObject, future: PyObject, } impl LoopAndFuture { fn new(py: Python<'_>) -> PyResult { static GET_RUNNING_LOOP: GILOnceCell = GILOnceCell::new(); let import = || -> PyResult<_> { let module = py.import_bound("asyncio")?; Ok(module.getattr("get_running_loop")?.into()) }; let event_loop = GET_RUNNING_LOOP.get_or_try_init(py, import)?.call0(py)?; let future = event_loop.call_method0(py, "create_future")?; Ok(Self { event_loop, future }) } fn set_result(&self, py: Python<'_>) -> PyResult<()> { static RELEASE_WAITER: GILOnceCell> = GILOnceCell::new(); let release_waiter = RELEASE_WAITER.get_or_try_init(py, || { wrap_pyfunction_bound!(release_waiter, py).map(Bound::unbind) })?; // `Future.set_result` must be called in event loop thread, // so it requires `call_soon_threadsafe` let call_soon_threadsafe = self.event_loop.call_method1( py, intern!(py, "call_soon_threadsafe"), (release_waiter, self.future.bind(py)), ); if let Err(err) = call_soon_threadsafe { // `call_soon_threadsafe` will raise if the event loop is closed; // instead of catching an unspecific `RuntimeError`, check directly if it's closed. let is_closed = self.event_loop.call_method0(py, "is_closed")?; if !is_closed.extract(py)? { return Err(err); } } Ok(()) } } /// Call `future.set_result` if the future is not done. /// /// Future can be cancelled by the event loop before being waken. /// See #[pyfunction(crate = "crate")] fn release_waiter(future: &Bound<'_, PyAny>) -> PyResult<()> { let done = future.call_method0(intern!(future.py(), "done"))?; if !done.extract::()? { future.call_method1(intern!(future.py(), "set_result"), (future.py().None(),))?; } Ok(()) } pyo3/src/pycell/0000775000175000017500000000000014661133735014514 5ustar jamespagejamespagepyo3/src/pycell/impl_.rs0000644000175000017500000004420214661133735016162 0ustar jamespagejamespage#![allow(missing_docs)] //! Crate-private implementation of PyClassObject use std::cell::{Cell, UnsafeCell}; use std::marker::PhantomData; use std::mem::ManuallyDrop; use crate::impl_::pyclass::{ PyClassBaseType, PyClassDict, PyClassImpl, PyClassThreadChecker, PyClassWeakRef, }; use crate::type_object::{get_tp_free, PyLayout, PySizedLayout}; use crate::{ffi, PyClass, PyTypeInfo, Python}; use super::{PyBorrowError, PyBorrowMutError}; pub trait PyClassMutability { // The storage for this inheritance layer. Only the first mutable class in // an inheritance hierarchy needs to store the borrow flag. type Storage: PyClassBorrowChecker; // The borrow flag needed to implement this class' mutability. Empty until // the first mutable class, at which point it is BorrowChecker and will be // for all subclasses. type Checker: PyClassBorrowChecker; type ImmutableChild: PyClassMutability; type MutableChild: PyClassMutability; } pub struct ImmutableClass(()); pub struct MutableClass(()); pub struct ExtendsMutableAncestor(PhantomData); impl PyClassMutability for ImmutableClass { type Storage = EmptySlot; type Checker = EmptySlot; type ImmutableChild = ImmutableClass; type MutableChild = MutableClass; } impl PyClassMutability for MutableClass { type Storage = BorrowChecker; type Checker = BorrowChecker; type ImmutableChild = ExtendsMutableAncestor; type MutableChild = ExtendsMutableAncestor; } impl PyClassMutability for ExtendsMutableAncestor { type Storage = EmptySlot; type Checker = BorrowChecker; type ImmutableChild = ExtendsMutableAncestor; type MutableChild = ExtendsMutableAncestor; } #[derive(Debug, Copy, Clone, Eq, PartialEq)] struct BorrowFlag(usize); impl BorrowFlag { pub(crate) const UNUSED: BorrowFlag = BorrowFlag(0); const HAS_MUTABLE_BORROW: BorrowFlag = BorrowFlag(usize::MAX); const fn increment(self) -> Self { Self(self.0 + 1) } const fn decrement(self) -> Self { Self(self.0 - 1) } } pub struct EmptySlot(()); pub struct BorrowChecker(Cell); pub trait PyClassBorrowChecker { /// Initial value for self fn new() -> Self; /// Increments immutable borrow count, if possible fn try_borrow(&self) -> Result<(), PyBorrowError>; #[cfg(feature = "gil-refs")] fn try_borrow_unguarded(&self) -> Result<(), PyBorrowError>; /// Decrements immutable borrow count fn release_borrow(&self); /// Increments mutable borrow count, if possible fn try_borrow_mut(&self) -> Result<(), PyBorrowMutError>; /// Decremements mutable borrow count fn release_borrow_mut(&self); } impl PyClassBorrowChecker for EmptySlot { #[inline] fn new() -> Self { EmptySlot(()) } #[inline] fn try_borrow(&self) -> Result<(), PyBorrowError> { Ok(()) } #[inline] #[cfg(feature = "gil-refs")] fn try_borrow_unguarded(&self) -> Result<(), PyBorrowError> { Ok(()) } #[inline] fn release_borrow(&self) {} #[inline] fn try_borrow_mut(&self) -> Result<(), PyBorrowMutError> { unreachable!() } #[inline] fn release_borrow_mut(&self) { unreachable!() } } impl PyClassBorrowChecker for BorrowChecker { #[inline] fn new() -> Self { Self(Cell::new(BorrowFlag::UNUSED)) } fn try_borrow(&self) -> Result<(), PyBorrowError> { let flag = self.0.get(); if flag != BorrowFlag::HAS_MUTABLE_BORROW { self.0.set(flag.increment()); Ok(()) } else { Err(PyBorrowError { _private: () }) } } #[cfg(feature = "gil-refs")] fn try_borrow_unguarded(&self) -> Result<(), PyBorrowError> { let flag = self.0.get(); if flag != BorrowFlag::HAS_MUTABLE_BORROW { Ok(()) } else { Err(PyBorrowError { _private: () }) } } fn release_borrow(&self) { let flag = self.0.get(); self.0.set(flag.decrement()) } fn try_borrow_mut(&self) -> Result<(), PyBorrowMutError> { let flag = self.0.get(); if flag == BorrowFlag::UNUSED { self.0.set(BorrowFlag::HAS_MUTABLE_BORROW); Ok(()) } else { Err(PyBorrowMutError { _private: () }) } } fn release_borrow_mut(&self) { self.0.set(BorrowFlag::UNUSED) } } pub trait GetBorrowChecker { fn borrow_checker( class_object: &PyClassObject, ) -> &::Checker; } impl> GetBorrowChecker for MutableClass { fn borrow_checker(class_object: &PyClassObject) -> &BorrowChecker { &class_object.contents.borrow_checker } } impl> GetBorrowChecker for ImmutableClass { fn borrow_checker(class_object: &PyClassObject) -> &EmptySlot { &class_object.contents.borrow_checker } } impl, M: PyClassMutability> GetBorrowChecker for ExtendsMutableAncestor where T::BaseType: PyClassImpl + PyClassBaseType>, ::PyClassMutability: PyClassMutability, { fn borrow_checker(class_object: &PyClassObject) -> &BorrowChecker { <::PyClassMutability as GetBorrowChecker>::borrow_checker(&class_object.ob_base) } } /// Base layout of PyClassObject. #[doc(hidden)] #[repr(C)] pub struct PyClassObjectBase { ob_base: T, } unsafe impl PyLayout for PyClassObjectBase where U: PySizedLayout {} #[doc(hidden)] pub trait PyClassObjectLayout: PyLayout { fn ensure_threadsafe(&self); fn check_threadsafe(&self) -> Result<(), PyBorrowError>; /// Implementation of tp_dealloc. /// # Safety /// - slf must be a valid pointer to an instance of a T or a subclass. /// - slf must not be used after this call (as it will be freed). unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject); } impl PyClassObjectLayout for PyClassObjectBase where U: PySizedLayout, T: PyTypeInfo, { fn ensure_threadsafe(&self) {} fn check_threadsafe(&self) -> Result<(), PyBorrowError> { Ok(()) } unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject) { let type_obj = T::type_object_raw(py); // For `#[pyclass]` types which inherit from PyAny, we can just call tp_free if type_obj == std::ptr::addr_of_mut!(ffi::PyBaseObject_Type) { return get_tp_free(ffi::Py_TYPE(slf))(slf.cast()); } // More complex native types (e.g. `extends=PyDict`) require calling the base's dealloc. #[cfg(not(Py_LIMITED_API))] { if let Some(dealloc) = (*type_obj).tp_dealloc { // Before CPython 3.11 BaseException_dealloc would use Py_GC_UNTRACK which // assumes the exception is currently GC tracked, so we have to re-track // before calling the dealloc so that it can safely call Py_GC_UNTRACK. #[cfg(not(any(Py_3_11, PyPy)))] if ffi::PyType_FastSubclass(type_obj, ffi::Py_TPFLAGS_BASE_EXC_SUBCLASS) == 1 { ffi::PyObject_GC_Track(slf.cast()); } dealloc(slf); } else { get_tp_free(ffi::Py_TYPE(slf))(slf.cast()); } } #[cfg(Py_LIMITED_API)] unreachable!("subclassing native types is not possible with the `abi3` feature"); } } /// The layout of a PyClass as a Python object #[repr(C)] pub struct PyClassObject { pub(crate) ob_base: ::LayoutAsBase, pub(crate) contents: PyClassObjectContents, } #[repr(C)] pub(crate) struct PyClassObjectContents { pub(crate) value: ManuallyDrop>, pub(crate) borrow_checker: ::Storage, pub(crate) thread_checker: T::ThreadChecker, pub(crate) dict: T::Dict, pub(crate) weakref: T::WeakRef, } impl PyClassObject { pub(crate) fn get_ptr(&self) -> *mut T { self.contents.value.get() } /// Gets the offset of the dictionary from the start of the struct in bytes. pub(crate) fn dict_offset() -> ffi::Py_ssize_t { use memoffset::offset_of; let offset = offset_of!(PyClassObject, contents) + offset_of!(PyClassObjectContents, dict); // Py_ssize_t may not be equal to isize on all platforms #[allow(clippy::useless_conversion)] offset.try_into().expect("offset should fit in Py_ssize_t") } /// Gets the offset of the weakref list from the start of the struct in bytes. pub(crate) fn weaklist_offset() -> ffi::Py_ssize_t { use memoffset::offset_of; let offset = offset_of!(PyClassObject, contents) + offset_of!(PyClassObjectContents, weakref); // Py_ssize_t may not be equal to isize on all platforms #[allow(clippy::useless_conversion)] offset.try_into().expect("offset should fit in Py_ssize_t") } } impl PyClassObject { pub(crate) fn borrow_checker(&self) -> &::Checker { T::PyClassMutability::borrow_checker(self) } } unsafe impl PyLayout for PyClassObject {} impl PySizedLayout for PyClassObject {} impl PyClassObjectLayout for PyClassObject where ::LayoutAsBase: PyClassObjectLayout, { fn ensure_threadsafe(&self) { self.contents.thread_checker.ensure(); self.ob_base.ensure_threadsafe(); } fn check_threadsafe(&self) -> Result<(), PyBorrowError> { if !self.contents.thread_checker.check() { return Err(PyBorrowError { _private: () }); } self.ob_base.check_threadsafe() } unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject) { // Safety: Python only calls tp_dealloc when no references to the object remain. let class_object = &mut *(slf.cast::>()); if class_object.contents.thread_checker.can_drop(py) { ManuallyDrop::drop(&mut class_object.contents.value); } class_object.contents.dict.clear_dict(py); class_object.contents.weakref.clear_weakrefs(slf, py); ::LayoutAsBase::tp_dealloc(py, slf) } } #[cfg(test)] #[cfg(feature = "macros")] mod tests { use super::*; use crate::prelude::*; use crate::pyclass::boolean_struct::{False, True}; #[pyclass(crate = "crate", subclass)] struct MutableBase; #[pyclass(crate = "crate", extends = MutableBase, subclass)] struct MutableChildOfMutableBase; #[pyclass(crate = "crate", extends = MutableBase, frozen, subclass)] struct ImmutableChildOfMutableBase; #[pyclass(crate = "crate", extends = MutableChildOfMutableBase)] struct MutableChildOfMutableChildOfMutableBase; #[pyclass(crate = "crate", extends = ImmutableChildOfMutableBase)] struct MutableChildOfImmutableChildOfMutableBase; #[pyclass(crate = "crate", extends = MutableChildOfMutableBase, frozen)] struct ImmutableChildOfMutableChildOfMutableBase; #[pyclass(crate = "crate", extends = ImmutableChildOfMutableBase, frozen)] struct ImmutableChildOfImmutableChildOfMutableBase; #[pyclass(crate = "crate", frozen, subclass)] struct ImmutableBase; #[pyclass(crate = "crate", extends = ImmutableBase, subclass)] struct MutableChildOfImmutableBase; #[pyclass(crate = "crate", extends = ImmutableBase, frozen, subclass)] struct ImmutableChildOfImmutableBase; #[pyclass(crate = "crate", extends = MutableChildOfImmutableBase)] struct MutableChildOfMutableChildOfImmutableBase; #[pyclass(crate = "crate", extends = ImmutableChildOfImmutableBase)] struct MutableChildOfImmutableChildOfImmutableBase; #[pyclass(crate = "crate", extends = MutableChildOfImmutableBase, frozen)] struct ImmutableChildOfMutableChildOfImmutableBase; #[pyclass(crate = "crate", extends = ImmutableChildOfImmutableBase, frozen)] struct ImmutableChildOfImmutableChildOfImmutableBase; fn assert_mutable>() {} fn assert_immutable>() {} fn assert_mutable_with_mutable_ancestor< T: PyClass>, >() { } fn assert_immutable_with_mutable_ancestor< T: PyClass>, >() { } #[test] fn test_inherited_mutability() { // mutable base assert_mutable::(); // children of mutable base have a mutable ancestor assert_mutable_with_mutable_ancestor::(); assert_immutable_with_mutable_ancestor::(); // grandchildren of mutable base have a mutable ancestor assert_mutable_with_mutable_ancestor::(); assert_mutable_with_mutable_ancestor::(); assert_immutable_with_mutable_ancestor::(); assert_immutable_with_mutable_ancestor::(); // immutable base and children assert_immutable::(); assert_immutable::(); assert_immutable::(); // mutable children of immutable at any level are simply mutable assert_mutable::(); assert_mutable::(); // children of the mutable child display this property assert_mutable_with_mutable_ancestor::(); assert_immutable_with_mutable_ancestor::(); } #[test] fn test_mutable_borrow_prevents_further_borrows() { Python::with_gil(|py| { let mmm = Py::new( py, PyClassInitializer::from(MutableBase) .add_subclass(MutableChildOfMutableBase) .add_subclass(MutableChildOfMutableChildOfMutableBase), ) .unwrap(); let mmm_bound: &Bound<'_, MutableChildOfMutableChildOfMutableBase> = mmm.bind(py); let mmm_refmut = mmm_bound.borrow_mut(); // Cannot take any other mutable or immutable borrows whilst the object is borrowed mutably assert!(mmm_bound .extract::>() .is_err()); assert!(mmm_bound .extract::>() .is_err()); assert!(mmm_bound.extract::>().is_err()); assert!(mmm_bound .extract::>() .is_err()); assert!(mmm_bound .extract::>() .is_err()); assert!(mmm_bound.extract::>().is_err()); // With the borrow dropped, all other borrow attempts will succeed drop(mmm_refmut); assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound.extract::>().is_ok()); assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound.extract::>().is_ok()); }) } #[test] fn test_immutable_borrows_prevent_mutable_borrows() { Python::with_gil(|py| { let mmm = Py::new( py, PyClassInitializer::from(MutableBase) .add_subclass(MutableChildOfMutableBase) .add_subclass(MutableChildOfMutableChildOfMutableBase), ) .unwrap(); let mmm_bound: &Bound<'_, MutableChildOfMutableChildOfMutableBase> = mmm.bind(py); let mmm_refmut = mmm_bound.borrow(); // Further immutable borrows are ok assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound.extract::>().is_ok()); // Further mutable borrows are not ok assert!(mmm_bound .extract::>() .is_err()); assert!(mmm_bound .extract::>() .is_err()); assert!(mmm_bound.extract::>().is_err()); // With the borrow dropped, all mutable borrow attempts will succeed drop(mmm_refmut); assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound .extract::>() .is_ok()); assert!(mmm_bound.extract::>().is_ok()); }) } } pyo3/src/macros.rs0000644000175000017500000001662114661133735015062 0ustar jamespagejamespage/// A convenient macro to execute a Python code snippet, with some local variables set. /// /// # Panics /// /// This macro internally calls [`Python::run_bound`](crate::Python::run_bound) and panics /// if it returns `Err`, after printing the error to stdout. /// /// If you need to handle failures, please use [`Python::run_bound`](crate::marker::Python::run_bound) instead. /// /// # Examples /// ``` /// use pyo3::{prelude::*, py_run, types::PyList}; /// /// Python::with_gil(|py| { /// let list = PyList::new_bound(py, &[1, 2, 3]); /// py_run!(py, list, "assert list == [1, 2, 3]"); /// }); /// ``` /// /// You can use this macro to test pyfunctions or pyclasses quickly. /// /// ``` /// use pyo3::{prelude::*, py_run}; /// /// #[pyclass] /// #[derive(Debug)] /// struct Time { /// hour: u32, /// minute: u32, /// second: u32, /// } /// /// #[pymethods] /// impl Time { /// fn repl_japanese(&self) -> String { /// format!("{}時{}分{}秒", self.hour, self.minute, self.second) /// } /// #[getter] /// fn hour(&self) -> u32 { /// self.hour /// } /// fn as_tuple(&self) -> (u32, u32, u32) { /// (self.hour, self.minute, self.second) /// } /// } /// /// Python::with_gil(|py| { /// let time = Py::new(py, Time {hour: 8, minute: 43, second: 16}).unwrap(); /// let time_as_tuple = (8, 43, 16); /// py_run!(py, time time_as_tuple, r#" /// assert time.hour == 8 /// assert time.repl_japanese() == "8時43分16秒" /// assert time.as_tuple() == time_as_tuple /// "#); /// }); /// ``` /// /// If you need to prepare the `locals` dict by yourself, you can pass it as `*locals`. /// /// ``` /// use pyo3::prelude::*; /// use pyo3::types::IntoPyDict; /// /// #[pyclass] /// struct MyClass; /// /// #[pymethods] /// impl MyClass { /// #[new] /// fn new() -> Self { /// MyClass {} /// } /// } /// /// Python::with_gil(|py| { /// let locals = [("C", py.get_type_bound::())].into_py_dict_bound(py); /// pyo3::py_run!(py, *locals, "c = C()"); /// }); /// ``` #[macro_export] macro_rules! py_run { ($py:expr, $($val:ident)+, $code:literal) => {{ $crate::py_run_impl!($py, $($val)+, $crate::indoc::indoc!($code)) }}; ($py:expr, $($val:ident)+, $code:expr) => {{ $crate::py_run_impl!($py, $($val)+, &$crate::unindent::unindent($code)) }}; ($py:expr, *$dict:expr, $code:literal) => {{ $crate::py_run_impl!($py, *$dict, $crate::indoc::indoc!($code)) }}; ($py:expr, *$dict:expr, $code:expr) => {{ $crate::py_run_impl!($py, *$dict, &$crate::unindent::unindent($code)) }}; } #[macro_export] #[doc(hidden)] macro_rules! py_run_impl { ($py:expr, $($val:ident)+, $code:expr) => {{ use $crate::types::IntoPyDict; use $crate::ToPyObject; let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict_bound($py); $crate::py_run_impl!($py, *d, $code) }}; ($py:expr, *$dict:expr, $code:expr) => {{ use ::std::option::Option::*; #[allow(unused_imports)] #[cfg(feature = "gil-refs")] use $crate::PyNativeType; if let ::std::result::Result::Err(e) = $py.run_bound($code, None, Some(&$dict.as_borrowed())) { e.print($py); // So when this c api function the last line called printed the error to stderr, // the output is only written into a buffer which is never flushed because we // panic before flushing. This is where this hack comes into place $py.run_bound("import sys; sys.stderr.flush()", None, None) .unwrap(); ::std::panic!("{}", $code) } }}; } /// Wraps a Rust function annotated with [`#[pyfunction]`](macro@crate::pyfunction). /// /// This can be used with [`PyModule::add_function`](crate::types::PyModuleMethods::add_function) to /// add free functions to a [`PyModule`](crate::types::PyModule) - see its documentation for more /// information. /// /// During the migration from the GIL Ref API to the Bound API, the return type of this macro will /// be either the `&'py PyModule` GIL Ref or `Bound<'py, PyModule>` according to the second /// argument. /// /// For backwards compatibility, if the second argument is `Python<'py>` then the return type will /// be `&'py PyModule` GIL Ref. To get `Bound<'py, PyModule>`, use the [`crate::wrap_pyfunction_bound!`] /// macro instead. #[macro_export] macro_rules! wrap_pyfunction { ($function:path) => { &|py_or_module| { use $function as wrapped_pyfunction; $crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction( py_or_module, &wrapped_pyfunction::_PYO3_DEF, ) } }; ($function:path, $py_or_module:expr) => {{ use $function as wrapped_pyfunction; let check_gil_refs = $crate::impl_::deprecations::GilRefs::new(); let py_or_module = $crate::impl_::deprecations::inspect_type($py_or_module, &check_gil_refs); check_gil_refs.is_python(); $crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction( py_or_module, &wrapped_pyfunction::_PYO3_DEF, ) }}; } /// Wraps a Rust function annotated with [`#[pyfunction]`](macro@crate::pyfunction). /// /// This can be used with [`PyModule::add_function`](crate::types::PyModuleMethods::add_function) to /// add free functions to a [`PyModule`](crate::types::PyModule) - see its documentation for more /// information. #[macro_export] macro_rules! wrap_pyfunction_bound { ($function:path) => { &|py_or_module| { use $function as wrapped_pyfunction; $crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction( $crate::impl_::pyfunction::OnlyBound(py_or_module), &wrapped_pyfunction::_PYO3_DEF, ) } }; ($function:path, $py_or_module:expr) => {{ use $function as wrapped_pyfunction; $crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction( $crate::impl_::pyfunction::OnlyBound($py_or_module), &wrapped_pyfunction::_PYO3_DEF, ) }}; } /// Returns a function that takes a [`Python`](crate::Python) instance and returns a /// Python module. /// /// Use this together with [`#[pymodule]`](crate::pymodule) and /// [`PyModule::add_wrapped`](crate::types::PyModuleMethods::add_wrapped). #[macro_export] macro_rules! wrap_pymodule { ($module:path) => { &|py| { use $module as wrapped_pymodule; wrapped_pymodule::_PYO3_DEF .make_module(py) .expect("failed to wrap pymodule") } }; } /// Add the module to the initialization table in order to make embedded Python code to use it. /// Module name is the argument. /// /// Use it before [`prepare_freethreaded_python`](crate::prepare_freethreaded_python) and /// leave feature `auto-initialize` off #[cfg(not(any(PyPy, GraalPy)))] #[macro_export] macro_rules! append_to_inittab { ($module:ident) => { unsafe { if $crate::ffi::Py_IsInitialized() != 0 { ::std::panic!( "called `append_to_inittab` but a Python interpreter is already running." ); } $crate::ffi::PyImport_AppendInittab( $module::__PYO3_NAME.as_ptr(), ::std::option::Option::Some($module::__pyo3_init), ); } }; } pyo3/src/pyclass_init.rs0000644000175000017500000002421014661133735016270 0ustar jamespagejamespage//! Contains initialization utilities for `#[pyclass]`. use crate::callback::IntoPyCallbackOutput; use crate::ffi_ptr_ext::FfiPtrExt; use crate::impl_::pyclass::{PyClassBaseType, PyClassDict, PyClassThreadChecker, PyClassWeakRef}; use crate::types::PyAnyMethods; use crate::{ffi, Bound, Py, PyClass, PyErr, PyResult, Python}; use crate::{ ffi::PyTypeObject, pycell::impl_::{PyClassBorrowChecker, PyClassMutability, PyClassObjectContents}, type_object::{get_tp_alloc, PyTypeInfo}, }; use std::{ cell::UnsafeCell, marker::PhantomData, mem::{ManuallyDrop, MaybeUninit}, }; /// Initializer for Python types. /// /// This trait is intended to use internally for distinguishing `#[pyclass]` and /// Python native types. pub trait PyObjectInit: Sized { /// # Safety /// - `subtype` must be a valid pointer to a type object of T or a subclass. unsafe fn into_new_object( self, py: Python<'_>, subtype: *mut PyTypeObject, ) -> PyResult<*mut ffi::PyObject>; private_decl! {} } /// Initializer for Python native types, like `PyDict`. pub struct PyNativeTypeInitializer(PhantomData); impl PyObjectInit for PyNativeTypeInitializer { unsafe fn into_new_object( self, py: Python<'_>, subtype: *mut PyTypeObject, ) -> PyResult<*mut ffi::PyObject> { unsafe fn inner( py: Python<'_>, type_object: *mut PyTypeObject, subtype: *mut PyTypeObject, ) -> PyResult<*mut ffi::PyObject> { // HACK (due to FIXME below): PyBaseObject_Type's tp_new isn't happy with NULL arguments let is_base_object = type_object == std::ptr::addr_of_mut!(ffi::PyBaseObject_Type); if is_base_object { let alloc = get_tp_alloc(subtype).unwrap_or(ffi::PyType_GenericAlloc); let obj = alloc(subtype, 0); return if obj.is_null() { Err(PyErr::fetch(py)) } else { Ok(obj) }; } #[cfg(Py_LIMITED_API)] unreachable!("subclassing native types is not possible with the `abi3` feature"); #[cfg(not(Py_LIMITED_API))] { match (*type_object).tp_new { // FIXME: Call __new__ with actual arguments Some(newfunc) => { let obj = newfunc(subtype, std::ptr::null_mut(), std::ptr::null_mut()); if obj.is_null() { Err(PyErr::fetch(py)) } else { Ok(obj) } } None => Err(crate::exceptions::PyTypeError::new_err( "base type without tp_new", )), } } } let type_object = T::type_object_raw(py); inner(py, type_object, subtype) } private_impl! {} } /// Initializer for our `#[pyclass]` system. /// /// You can use this type to initialize complicatedly nested `#[pyclass]`. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # use pyo3::py_run; /// #[pyclass(subclass)] /// struct BaseClass { /// #[pyo3(get)] /// basename: &'static str, /// } /// #[pyclass(extends=BaseClass, subclass)] /// struct SubClass { /// #[pyo3(get)] /// subname: &'static str, /// } /// #[pyclass(extends=SubClass)] /// struct SubSubClass { /// #[pyo3(get)] /// subsubname: &'static str, /// } /// /// #[pymethods] /// impl SubSubClass { /// #[new] /// fn new() -> PyClassInitializer { /// PyClassInitializer::from(BaseClass { basename: "base" }) /// .add_subclass(SubClass { subname: "sub" }) /// .add_subclass(SubSubClass { /// subsubname: "subsub", /// }) /// } /// } /// Python::with_gil(|py| { /// let typeobj = py.get_type_bound::(); /// let sub_sub_class = typeobj.call((), None).unwrap(); /// py_run!( /// py, /// sub_sub_class, /// r#" /// assert sub_sub_class.basename == 'base' /// assert sub_sub_class.subname == 'sub' /// assert sub_sub_class.subsubname == 'subsub'"# /// ); /// }); /// ``` pub struct PyClassInitializer(PyClassInitializerImpl); enum PyClassInitializerImpl { Existing(Py), New { init: T, super_init: ::Initializer, }, } impl PyClassInitializer { /// Constructs a new initializer from value `T` and base class' initializer. /// /// It is recommended to use `add_subclass` instead of this method for most usage. pub fn new(init: T, super_init: ::Initializer) -> Self { Self(PyClassInitializerImpl::New { init, super_init }) } /// Constructs a new initializer from an initializer for the base class. /// /// # Examples /// ``` /// use pyo3::prelude::*; /// /// #[pyclass(subclass)] /// struct BaseClass { /// #[pyo3(get)] /// value: i32, /// } /// /// impl BaseClass { /// fn new(value: i32) -> PyResult { /// Ok(Self { value }) /// } /// } /// /// #[pyclass(extends=BaseClass)] /// struct SubClass {} /// /// #[pymethods] /// impl SubClass { /// #[new] /// fn new(value: i32) -> PyResult> { /// let base_init = PyClassInitializer::from(BaseClass::new(value)?); /// Ok(base_init.add_subclass(SubClass {})) /// } /// } /// /// fn main() -> PyResult<()> { /// Python::with_gil(|py| { /// let m = PyModule::new_bound(py, "example")?; /// m.add_class::()?; /// m.add_class::()?; /// /// let instance = m.getattr("SubClass")?.call1((92,))?; /// /// // `SubClass` does not have a `value` attribute, but `BaseClass` does. /// let n = instance.getattr("value")?.extract::()?; /// assert_eq!(n, 92); /// /// Ok(()) /// }) /// } /// ``` pub fn add_subclass(self, subclass_value: S) -> PyClassInitializer where S: PyClass, S::BaseType: PyClassBaseType, { PyClassInitializer::new(subclass_value, self) } /// Creates a new PyCell and initializes it. pub(crate) fn create_class_object(self, py: Python<'_>) -> PyResult> where T: PyClass, { unsafe { self.create_class_object_of_type(py, T::type_object_raw(py)) } } /// Creates a new class object and initializes it given a typeobject `subtype`. /// /// # Safety /// `subtype` must be a valid pointer to the type object of T or a subclass. pub(crate) unsafe fn create_class_object_of_type( self, py: Python<'_>, target_type: *mut crate::ffi::PyTypeObject, ) -> PyResult> where T: PyClass, { /// Layout of a PyClassObject after base new has been called, but the contents have not yet been /// written. #[repr(C)] struct PartiallyInitializedClassObject { _ob_base: ::LayoutAsBase, contents: MaybeUninit>, } let (init, super_init) = match self.0 { PyClassInitializerImpl::Existing(value) => return Ok(value.into_bound(py)), PyClassInitializerImpl::New { init, super_init } => (init, super_init), }; let obj = super_init.into_new_object(py, target_type)?; let part_init: *mut PartiallyInitializedClassObject = obj.cast(); std::ptr::write( (*part_init).contents.as_mut_ptr(), PyClassObjectContents { value: ManuallyDrop::new(UnsafeCell::new(init)), borrow_checker: ::Storage::new(), thread_checker: T::ThreadChecker::new(), dict: T::Dict::INIT, weakref: T::WeakRef::INIT, }, ); // Safety: obj is a valid pointer to an object of type `target_type`, which` is a known // subclass of `T` Ok(obj.assume_owned(py).downcast_into_unchecked()) } } impl PyObjectInit for PyClassInitializer { unsafe fn into_new_object( self, py: Python<'_>, subtype: *mut PyTypeObject, ) -> PyResult<*mut ffi::PyObject> { self.create_class_object_of_type(py, subtype) .map(Bound::into_ptr) } private_impl! {} } impl From for PyClassInitializer where T: PyClass, T::BaseType: PyClassBaseType>, { #[inline] fn from(value: T) -> PyClassInitializer { Self::new(value, PyNativeTypeInitializer(PhantomData)) } } impl From<(S, B)> for PyClassInitializer where S: PyClass, B: PyClass, B::BaseType: PyClassBaseType>, { fn from(sub_and_base: (S, B)) -> PyClassInitializer { let (sub, base) = sub_and_base; PyClassInitializer::from(base).add_subclass(sub) } } impl From> for PyClassInitializer { #[inline] fn from(value: Py) -> PyClassInitializer { PyClassInitializer(PyClassInitializerImpl::Existing(value)) } } impl<'py, T: PyClass> From> for PyClassInitializer { #[inline] fn from(value: Bound<'py, T>) -> PyClassInitializer { PyClassInitializer::from(value.unbind()) } } // Implementation used by proc macros to allow anything convertible to PyClassInitializer to be // the return value of pyclass #[new] method (optionally wrapped in `Result`). impl IntoPyCallbackOutput> for U where T: PyClass, U: Into>, { #[inline] fn convert(self, _py: Python<'_>) -> PyResult> { Ok(self.into()) } } pyo3/src/marker.rs0000644000175000017500000013561614661133735015065 0ustar jamespagejamespage//! Fundamental properties of objects tied to the Python interpreter. //! //! The Python interpreter is not threadsafe. To protect the Python interpreter in multithreaded //! scenarios there is a global lock, the *global interpreter lock* (hereafter referred to as *GIL*) //! that must be held to safely interact with Python objects. This is why in PyO3 when you acquire //! the GIL you get a [`Python`] marker token that carries the *lifetime* of holding the GIL and all //! borrowed references to Python objects carry this lifetime as well. This will statically ensure //! that you can never use Python objects after dropping the lock - if you mess this up it will be //! caught at compile time and your program will fail to compile. //! //! It also supports this pattern that many extension modules employ: //! - Drop the GIL, so that other Python threads can acquire it and make progress themselves //! - Do something independently of the Python interpreter, like IO, a long running calculation or //! awaiting a future //! - Once that is done, reacquire the GIL //! //! That API is provided by [`Python::allow_threads`] and enforced via the [`Ungil`] bound on the //! closure and the return type. This is done by relying on the [`Send`] auto trait. `Ungil` is //! defined as the following: //! //! ```rust //! # #![allow(dead_code)] //! pub unsafe trait Ungil {} //! //! unsafe impl Ungil for T {} //! ``` //! //! We piggy-back off the `Send` auto trait because it is not possible to implement custom auto //! traits on stable Rust. This is the solution which enables it for as many types as possible while //! making the API usable. //! //! In practice this API works quite well, but it comes with some drawbacks: //! //! ## Drawbacks //! //! There is no reason to prevent `!Send` types like [`Rc`] from crossing the closure. After all, //! [`Python::allow_threads`] just lets other Python threads run - it does not itself launch a new //! thread. //! //! ```rust, compile_fail //! # #[cfg(feature = "nightly")] //! # compile_error!("this actually works on nightly") //! use pyo3::prelude::*; //! use std::rc::Rc; //! //! fn main() { //! Python::with_gil(|py| { //! let rc = Rc::new(5); //! //! py.allow_threads(|| { //! // This would actually be fine... //! println!("{:?}", *rc); //! }); //! }); //! } //! ``` //! //! Because we are using `Send` for something it's not quite meant for, other code that //! (correctly) upholds the invariants of [`Send`] can cause problems. //! //! [`SendWrapper`] is one of those. Per its documentation: //! //! > A wrapper which allows you to move around non-Send-types between threads, as long as you //! > access the contained value only from within the original thread and make sure that it is //! > dropped from within the original thread. //! //! This will "work" to smuggle Python references across the closure, because we're not actually //! doing anything with threads: //! //! ```rust, no_run //! use pyo3::prelude::*; //! use pyo3::types::PyString; //! use send_wrapper::SendWrapper; //! //! Python::with_gil(|py| { //! let string = PyString::new_bound(py, "foo"); //! //! let wrapped = SendWrapper::new(string); //! //! py.allow_threads(|| { //! # #[cfg(not(feature = "nightly"))] //! # { //! // 💥 Unsound! 💥 //! let smuggled: &Bound<'_, PyString> = &*wrapped; //! println!("{:?}", smuggled); //! # } //! }); //! }); //! ``` //! //! For now the answer to that is "don't do that". //! //! # A proper implementation using an auto trait //! //! However on nightly Rust and when PyO3's `nightly` feature is //! enabled, `Ungil` is defined as the following: //! //! ```rust //! # #[cfg(any())] //! # { //! #![feature(auto_traits, negative_impls)] //! //! pub unsafe auto trait Ungil {} //! //! // It is unimplemented for the `Python` struct and Python objects. //! impl !Ungil for Python<'_> {} //! impl !Ungil for ffi::PyObject {} //! //! // `Py` wraps it in a safe api, so this is OK //! unsafe impl Ungil for Py {} //! # } //! ``` //! //! With this feature enabled, the above two examples will start working and not working, respectively. //! //! [`SendWrapper`]: https://docs.rs/send_wrapper/latest/send_wrapper/struct.SendWrapper.html //! [`Rc`]: std::rc::Rc //! [`Py`]: crate::Py use crate::err::{self, PyErr, PyResult}; use crate::ffi_ptr_ext::FfiPtrExt; use crate::gil::{GILGuard, SuspendGIL}; use crate::impl_::not_send::NotSend; use crate::py_result_ext::PyResultExt; use crate::types::any::PyAnyMethods; use crate::types::{ PyAny, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString, PyType, }; use crate::version::PythonVersionInfo; use crate::{ffi, Bound, IntoPy, Py, PyObject, PyTypeInfo}; #[allow(deprecated)] #[cfg(feature = "gil-refs")] use crate::{gil::GILPool, FromPyPointer, PyNativeType}; use std::ffi::{CStr, CString}; use std::marker::PhantomData; use std::os::raw::c_int; /// Types that are safe to access while the GIL is not held. /// /// # Safety /// /// The type must not carry borrowed Python references or, if it does, not allow access to them if /// the GIL is not held. /// /// See the [module-level documentation](self) for more information. /// /// # Examples /// /// This tracking is currently imprecise as it relies on the [`Send`] auto trait on stable Rust. /// For example, an `Rc` smart pointer should be usable without the GIL, but we currently prevent that: /// /// ```compile_fail /// # use pyo3::prelude::*; /// use std::rc::Rc; /// /// Python::with_gil(|py| { /// let rc = Rc::new(42); /// /// py.allow_threads(|| { /// println!("{:?}", rc); /// }); /// }); /// ``` /// /// This also implies that the interplay between `with_gil` and `allow_threads` is unsound, for example /// one can circumvent this protection using the [`send_wrapper`](https://docs.rs/send_wrapper/) crate: /// /// ```no_run /// # use pyo3::prelude::*; /// # use pyo3::types::PyString; /// use send_wrapper::SendWrapper; /// /// Python::with_gil(|py| { /// let string = PyString::new_bound(py, "foo"); /// /// let wrapped = SendWrapper::new(string); /// /// py.allow_threads(|| { /// let sneaky: &Bound<'_, PyString> = &*wrapped; /// /// println!("{:?}", sneaky); /// }); /// }); /// ``` /// /// Fixing this loophole on stable Rust has significant ergonomic issues, but it is fixed when using /// nightly Rust and the `nightly` feature, c.f. [#2141](https://github.com/PyO3/pyo3/issues/2141). #[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag #[cfg(not(feature = "nightly"))] pub unsafe trait Ungil {} #[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag #[cfg(not(feature = "nightly"))] unsafe impl Ungil for T {} #[cfg(feature = "nightly")] mod nightly { macro_rules! define { ($($tt:tt)*) => { $($tt)* } } define! { /// Types that are safe to access while the GIL is not held. /// /// # Safety /// /// The type must not carry borrowed Python references or, if it does, not allow access to them if /// the GIL is not held. /// /// See the [module-level documentation](self) for more information. /// /// # Examples /// /// Types which are `Ungil` cannot be used in contexts where the GIL was released, e.g. /// /// ```compile_fail /// # use pyo3::prelude::*; /// # use pyo3::types::PyString; /// Python::with_gil(|py| { /// let string = PyString::new_bound(py, "foo"); /// /// py.allow_threads(|| { /// println!("{:?}", string); /// }); /// }); /// ``` /// /// This applies to the GIL token `Python` itself as well, e.g. /// /// ```compile_fail /// # use pyo3::prelude::*; /// Python::with_gil(|py| { /// py.allow_threads(|| { /// drop(py); /// }); /// }); /// ``` /// /// On nightly Rust, this is not based on the [`Send`] auto trait and hence we are able /// to prevent incorrectly circumventing it using e.g. the [`send_wrapper`](https://docs.rs/send_wrapper/) crate: /// /// ```compile_fail /// # use pyo3::prelude::*; /// # use pyo3::types::PyString; /// use send_wrapper::SendWrapper; /// /// Python::with_gil(|py| { /// let string = PyString::new_bound(py, "foo"); /// /// let wrapped = SendWrapper::new(string); /// /// py.allow_threads(|| { /// let sneaky: &PyString = *wrapped; /// /// println!("{:?}", sneaky); /// }); /// }); /// ``` /// /// This also enables using non-[`Send`] types in `allow_threads`, /// at least if they are not also bound to the GIL: /// /// ```rust /// # use pyo3::prelude::*; /// use std::rc::Rc; /// /// Python::with_gil(|py| { /// let rc = Rc::new(42); /// /// py.allow_threads(|| { /// println!("{:?}", rc); /// }); /// }); /// ``` pub unsafe auto trait Ungil {} } impl !Ungil for crate::Python<'_> {} // This means that PyString, PyList, etc all inherit !Ungil from this. impl !Ungil for crate::PyAny {} // All the borrowing wrappers #[allow(deprecated)] #[cfg(feature = "gil-refs")] impl !Ungil for crate::PyCell {} impl !Ungil for crate::PyRef<'_, T> {} impl !Ungil for crate::PyRefMut<'_, T> {} // FFI pointees impl !Ungil for crate::ffi::PyObject {} impl !Ungil for crate::ffi::PyLongObject {} impl !Ungil for crate::ffi::PyThreadState {} impl !Ungil for crate::ffi::PyInterpreterState {} impl !Ungil for crate::ffi::PyWeakReference {} impl !Ungil for crate::ffi::PyFrameObject {} impl !Ungil for crate::ffi::PyCodeObject {} #[cfg(not(Py_LIMITED_API))] impl !Ungil for crate::ffi::PyDictKeysObject {} #[cfg(not(any(Py_LIMITED_API, Py_3_10)))] impl !Ungil for crate::ffi::PyArena {} } #[cfg(feature = "nightly")] pub use nightly::Ungil; /// A marker token that represents holding the GIL. /// /// It serves three main purposes: /// - It provides a global API for the Python interpreter, such as [`Python::eval_bound`]. /// - It can be passed to functions that require a proof of holding the GIL, such as /// [`Py::clone_ref`]. /// - Its lifetime represents the scope of holding the GIL which can be used to create Rust /// references that are bound to it, such as [`Bound<'py, PyAny>`]. /// /// Note that there are some caveats to using it that you might need to be aware of. See the /// [Deadlocks](#deadlocks) and [Releasing and freeing memory](#releasing-and-freeing-memory) /// paragraphs for more information about that. /// /// # Obtaining a Python token /// /// The following are the recommended ways to obtain a [`Python<'py>`] token, in order of preference: /// - If you already have something with a lifetime bound to the GIL, such as [`Bound<'py, PyAny>`], you can /// use its `.py()` method to get a token. /// - In a function or method annotated with [`#[pyfunction]`](crate::pyfunction) or [`#[pymethods]`](crate::pymethods) you can declare it /// as a parameter, and PyO3 will pass in the token when Python code calls it. /// - When you need to acquire the GIL yourself, such as when calling Python code from Rust, you /// should call [`Python::with_gil`] to do that and pass your code as a closure to it. /// /// The first two options are zero-cost; [`Python::with_gil`] requires runtime checking and may need to block /// to acquire the GIL. /// /// # Deadlocks /// /// Note that the GIL can be temporarily released by the Python interpreter during a function call /// (e.g. importing a module). In general, you don't need to worry about this because the GIL is /// reacquired before returning to the Rust code: /// /// ```text /// `Python` exists |=====================================| /// GIL actually held |==========| |================| /// Rust code running |=======| |==| |======| /// ``` /// /// This behaviour can cause deadlocks when trying to lock a Rust mutex while holding the GIL: /// /// * Thread 1 acquires the GIL /// * Thread 1 locks a mutex /// * Thread 1 makes a call into the Python interpreter which releases the GIL /// * Thread 2 acquires the GIL /// * Thread 2 tries to locks the mutex, blocks /// * Thread 1's Python interpreter call blocks trying to reacquire the GIL held by thread 2 /// /// To avoid deadlocking, you should release the GIL before trying to lock a mutex or `await`ing in /// asynchronous code, e.g. with [`Python::allow_threads`]. /// /// # Releasing and freeing memory /// /// The [`Python<'py>`] type can be used to create references to variables owned by the Python /// interpreter, using functions such as [`Python::eval_bound`] and [`PyModule::import_bound`]. #[derive(Copy, Clone)] pub struct Python<'py>(PhantomData<(&'py GILGuard, NotSend)>); impl Python<'_> { /// Acquires the global interpreter lock, allowing access to the Python interpreter. The /// provided closure `F` will be executed with the acquired `Python` marker token. /// /// If implementing [`#[pymethods]`](crate::pymethods) or [`#[pyfunction]`](crate::pyfunction), /// declare `py: Python` as an argument. PyO3 will pass in the token to grant access to the GIL /// context in which the function is running, avoiding the need to call `with_gil`. /// /// If the [`auto-initialize`] feature is enabled and the Python runtime is not already /// initialized, this function will initialize it. See #[cfg_attr( not(any(PyPy, GraalPy)), doc = "[`prepare_freethreaded_python`](crate::prepare_freethreaded_python)" )] #[cfg_attr(PyPy, doc = "`prepare_freethreaded_python`")] /// for details. /// /// If the current thread does not yet have a Python "thread state" associated with it, /// a new one will be automatically created before `F` is executed and destroyed after `F` /// completes. /// /// # Panics /// /// - If the [`auto-initialize`] feature is not enabled and the Python interpreter is not /// initialized. /// /// # Examples /// /// ``` /// use pyo3::prelude::*; /// /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let x: i32 = py.eval_bound("5", None, None)?.extract()?; /// assert_eq!(x, 5); /// Ok(()) /// }) /// # } /// ``` /// /// [`auto-initialize`]: https://pyo3.rs/main/features.html#auto-initialize #[inline] pub fn with_gil(f: F) -> R where F: for<'py> FnOnce(Python<'py>) -> R, { let guard = GILGuard::acquire(); // SAFETY: Either the GIL was already acquired or we just created a new `GILGuard`. f(guard.python()) } /// Like [`Python::with_gil`] except Python interpreter state checking is skipped. /// /// Normally when the GIL is acquired, we check that the Python interpreter is an /// appropriate state (e.g. it is fully initialized). This function skips those /// checks. /// /// # Safety /// /// If [`Python::with_gil`] would succeed, it is safe to call this function. /// /// In most cases, you should use [`Python::with_gil`]. /// /// A justified scenario for calling this function is during multi-phase interpreter /// initialization when [`Python::with_gil`] would fail before // this link is only valid on 3.8+not pypy and up. #[cfg_attr( all(Py_3_8, not(PyPy)), doc = "[`_Py_InitializeMain`](crate::ffi::_Py_InitializeMain)" )] #[cfg_attr(any(not(Py_3_8), PyPy), doc = "`_Py_InitializeMain`")] /// is called because the interpreter is only partially initialized. /// /// Behavior in other scenarios is not documented. #[inline] pub unsafe fn with_gil_unchecked(f: F) -> R where F: for<'py> FnOnce(Python<'py>) -> R, { let guard = GILGuard::acquire_unchecked(); f(guard.python()) } } impl<'py> Python<'py> { /// Temporarily releases the GIL, thus allowing other Python threads to run. The GIL will be /// reacquired when `F`'s scope ends. /// /// If you don't need to touch the Python /// interpreter for some time and have other Python threads around, this will let you run /// Rust-only code while letting those other Python threads make progress. /// /// Only types that implement [`Ungil`] can cross the closure. See the /// [module level documentation](self) for more information. /// /// If you need to pass Python objects into the closure you can use [`Py`]``to create a /// reference independent of the GIL lifetime. However, you cannot do much with those without a /// [`Python`] token, for which you'd need to reacquire the GIL. /// /// # Example: Releasing the GIL while running a computation in Rust-only code /// /// ``` /// use pyo3::prelude::*; /// /// #[pyfunction] /// fn sum_numbers(py: Python<'_>, numbers: Vec) -> PyResult { /// // We release the GIL here so any other Python threads get a chance to run. /// py.allow_threads(move || { /// // An example of an "expensive" Rust calculation /// let sum = numbers.iter().sum(); /// /// Ok(sum) /// }) /// } /// # /// # fn main() -> PyResult<()> { /// # Python::with_gil(|py| -> PyResult<()> { /// # let fun = pyo3::wrap_pyfunction_bound!(sum_numbers, py)?; /// # let res = fun.call1((vec![1_u32, 2, 3],))?; /// # assert_eq!(res.extract::()?, 6_u32); /// # Ok(()) /// # }) /// # } /// ``` /// /// Please see the [Parallelism] chapter of the guide for a thorough discussion of using /// [`Python::allow_threads`] in this manner. /// /// # Example: Passing borrowed Python references into the closure is not allowed /// /// ```compile_fail /// use pyo3::prelude::*; /// use pyo3::types::PyString; /// /// fn parallel_print(py: Python<'_>) { /// let s = PyString::new_bound(py, "This object cannot be accessed without holding the GIL >_<"); /// py.allow_threads(move || { /// println!("{:?}", s); // This causes a compile error. /// }); /// } /// ``` /// /// [`Py`]: crate::Py /// [`PyString`]: crate::types::PyString /// [auto-traits]: https://doc.rust-lang.org/nightly/unstable-book/language-features/auto-traits.html /// [Parallelism]: https://pyo3.rs/main/parallelism.html pub fn allow_threads(self, f: F) -> T where F: Ungil + FnOnce() -> T, T: Ungil, { // Use a guard pattern to handle reacquiring the GIL, // so that the GIL will be reacquired even if `f` panics. // The `Send` bound on the closure prevents the user from // transferring the `Python` token into the closure. let _guard = unsafe { SuspendGIL::new() }; f() } /// Deprecated version of [`Python::eval_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`Python::eval` will be replaced by `Python::eval_bound` in a future PyO3 version" )] pub fn eval( self, code: &str, globals: Option<&'py PyDict>, locals: Option<&'py PyDict>, ) -> PyResult<&'py PyAny> { self.eval_bound( code, globals.map(PyNativeType::as_borrowed).as_deref(), locals.map(PyNativeType::as_borrowed).as_deref(), ) .map(Bound::into_gil_ref) } /// Evaluates a Python expression in the given context and returns the result. /// /// If `globals` is `None`, it defaults to Python module `__main__`. /// If `locals` is `None`, it defaults to the value of `globals`. /// /// If `globals` doesn't contain `__builtins__`, default `__builtins__` /// will be added automatically. /// /// # Examples /// /// ``` /// # use pyo3::prelude::*; /// # Python::with_gil(|py| { /// let result = py.eval_bound("[i * 10 for i in range(5)]", None, None).unwrap(); /// let res: Vec = result.extract().unwrap(); /// assert_eq!(res, vec![0, 10, 20, 30, 40]) /// # }); /// ``` pub fn eval_bound( self, code: &str, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult> { self.run_code(code, ffi::Py_eval_input, globals, locals) } /// Deprecated version of [`Python::run_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`Python::run` will be replaced by `Python::run_bound` in a future PyO3 version" )] pub fn run( self, code: &str, globals: Option<&PyDict>, locals: Option<&PyDict>, ) -> PyResult<()> { self.run_bound( code, globals.map(PyNativeType::as_borrowed).as_deref(), locals.map(PyNativeType::as_borrowed).as_deref(), ) } /// Executes one or more Python statements in the given context. /// /// If `globals` is `None`, it defaults to Python module `__main__`. /// If `locals` is `None`, it defaults to the value of `globals`. /// /// If `globals` doesn't contain `__builtins__`, default `__builtins__` /// will be added automatically. /// /// # Examples /// ``` /// use pyo3::{ /// prelude::*, /// types::{PyBytes, PyDict}, /// }; /// Python::with_gil(|py| { /// let locals = PyDict::new_bound(py); /// py.run_bound( /// r#" /// import base64 /// s = 'Hello Rust!' /// ret = base64.b64encode(s.encode('utf-8')) /// "#, /// None, /// Some(&locals), /// ) /// .unwrap(); /// let ret = locals.get_item("ret").unwrap().unwrap(); /// let b64 = ret.downcast::().unwrap(); /// assert_eq!(b64.as_bytes(), b"SGVsbG8gUnVzdCE="); /// }); /// ``` /// /// You can use [`py_run!`](macro.py_run.html) for a handy alternative of `run` /// if you don't need `globals` and unwrapping is OK. pub fn run_bound( self, code: &str, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult<()> { let res = self.run_code(code, ffi::Py_file_input, globals, locals); res.map(|obj| { debug_assert!(obj.is_none()); }) } /// Runs code in the given context. /// /// `start` indicates the type of input expected: one of `Py_single_input`, /// `Py_file_input`, or `Py_eval_input`. /// /// If `globals` is `None`, it defaults to Python module `__main__`. /// If `locals` is `None`, it defaults to the value of `globals`. fn run_code( self, code: &str, start: c_int, globals: Option<&Bound<'py, PyDict>>, locals: Option<&Bound<'py, PyDict>>, ) -> PyResult> { let code = CString::new(code)?; unsafe { let mptr = ffi::PyImport_AddModule(ffi::c_str!("__main__").as_ptr()); if mptr.is_null() { return Err(PyErr::fetch(self)); } let globals = globals .map(|dict| dict.as_ptr()) .unwrap_or_else(|| ffi::PyModule_GetDict(mptr)); let locals = locals.map(|dict| dict.as_ptr()).unwrap_or(globals); // If `globals` don't provide `__builtins__`, most of the code will fail if Python // version is <3.10. That's probably not what user intended, so insert `__builtins__` // for them. // // See also: // - https://github.com/python/cpython/pull/24564 (the same fix in CPython 3.10) // - https://github.com/PyO3/pyo3/issues/3370 let builtins_s = crate::intern!(self, "__builtins__").as_ptr(); let has_builtins = ffi::PyDict_Contains(globals, builtins_s); if has_builtins == -1 { return Err(PyErr::fetch(self)); } if has_builtins == 0 { // Inherit current builtins. let builtins = ffi::PyEval_GetBuiltins(); // `PyDict_SetItem` doesn't take ownership of `builtins`, but `PyEval_GetBuiltins` // seems to return a borrowed reference, so no leak here. if ffi::PyDict_SetItem(globals, builtins_s, builtins) == -1 { return Err(PyErr::fetch(self)); } } let code_obj = ffi::Py_CompileString(code.as_ptr(), ffi::c_str!("").as_ptr(), start); if code_obj.is_null() { return Err(PyErr::fetch(self)); } let res_ptr = ffi::PyEval_EvalCode(code_obj, globals, locals); ffi::Py_DECREF(code_obj); res_ptr.assume_owned_or_err(self).downcast_into_unchecked() } } /// Gets the Python type object for type `T`. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`Python::get_type` will be replaced by `Python::get_type_bound` in a future PyO3 version" )] #[inline] pub fn get_type(self) -> &'py PyType where T: PyTypeInfo, { self.get_type_bound::().into_gil_ref() } /// Gets the Python type object for type `T`. #[inline] pub fn get_type_bound(self) -> Bound<'py, PyType> where T: PyTypeInfo, { T::type_object_bound(self) } /// Deprecated form of [`Python::import_bound`] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "`Python::import` will be replaced by `Python::import_bound` in a future PyO3 version" )] pub fn import(self, name: N) -> PyResult<&'py PyModule> where N: IntoPy>, { Self::import_bound(self, name).map(Bound::into_gil_ref) } /// Imports the Python module with the specified name. pub fn import_bound(self, name: N) -> PyResult> where N: IntoPy>, { PyModule::import_bound(self, name) } /// Gets the Python builtin value `None`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn None(self) -> PyObject { PyNone::get_bound(self).into_py(self) } /// Gets the Python builtin value `Ellipsis`, or `...`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn Ellipsis(self) -> PyObject { PyEllipsis::get_bound(self).into_py(self) } /// Gets the Python builtin value `NotImplemented`. #[allow(non_snake_case)] // the Python keyword starts with uppercase #[inline] pub fn NotImplemented(self) -> PyObject { PyNotImplemented::get_bound(self).into_py(self) } /// Gets the running Python interpreter version as a string. /// /// # Examples /// ```rust /// # use pyo3::Python; /// Python::with_gil(|py| { /// // The full string could be, for example: /// // "3.10.0 (tags/v3.10.0:b494f59, Oct 4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)]" /// assert!(py.version().starts_with("3.")); /// }); /// ``` pub fn version(self) -> &'py str { unsafe { CStr::from_ptr(ffi::Py_GetVersion()) .to_str() .expect("Python version string not UTF-8") } } /// Gets the running Python interpreter version as a struct similar to /// `sys.version_info`. /// /// # Examples /// ```rust /// # use pyo3::Python; /// Python::with_gil(|py| { /// // PyO3 supports Python 3.7 and up. /// assert!(py.version_info() >= (3, 7)); /// assert!(py.version_info() >= (3, 7, 0)); /// }); /// ``` pub fn version_info(self) -> PythonVersionInfo<'py> { let version_str = self.version(); // Portion of the version string returned by Py_GetVersion up to the first space is the // version number. let version_number_str = version_str.split(' ').next().unwrap_or(version_str); PythonVersionInfo::from_str(version_number_str).unwrap() } /// Registers the object in the release pool, and tries to downcast to specific type. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `obj.downcast_bound::(py)` instead of `py.checked_cast_as::(obj)`" )] pub fn checked_cast_as( self, obj: PyObject, ) -> Result<&'py T, crate::err::PyDowncastError<'py>> where T: crate::PyTypeCheck, { #[allow(deprecated)] obj.into_ref(self).downcast() } /// Registers the object in the release pool, and does an unchecked downcast /// to the specific type. /// /// # Safety /// /// Callers must ensure that ensure that the cast is valid. #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `obj.downcast_bound_unchecked::(py)` instead of `py.cast_as::(obj)`" )] pub unsafe fn cast_as(self, obj: PyObject) -> &'py T where T: crate::type_object::HasPyGilRef, { #[allow(deprecated)] obj.into_ref(self).downcast_unchecked() } /// Registers the object pointer in the release pool, /// and does an unchecked downcast to the specific type. /// /// # Safety /// /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention, deprecated)] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `Py::from_owned_ptr(py, ptr)` or `Bound::from_owned_ptr(py, ptr)` instead" )] pub unsafe fn from_owned_ptr(self, ptr: *mut ffi::PyObject) -> &'py T where T: FromPyPointer<'py>, { FromPyPointer::from_owned_ptr(self, ptr) } /// Registers the owned object pointer in the release pool. /// /// Returns `Err(PyErr)` if the pointer is NULL. /// Does an unchecked downcast to the specific type. /// /// # Safety /// /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention, deprecated)] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `Py::from_owned_ptr_or_err(py, ptr)` or `Bound::from_owned_ptr_or_err(py, ptr)` instead" )] pub unsafe fn from_owned_ptr_or_err(self, ptr: *mut ffi::PyObject) -> PyResult<&'py T> where T: FromPyPointer<'py>, { FromPyPointer::from_owned_ptr_or_err(self, ptr) } /// Registers the owned object pointer in release pool. /// /// Returns `None` if the pointer is NULL. /// Does an unchecked downcast to the specific type. /// /// # Safety /// /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention, deprecated)] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `Py::from_owned_ptr_or_opt(py, ptr)` or `Bound::from_owned_ptr_or_opt(py, ptr)` instead" )] pub unsafe fn from_owned_ptr_or_opt(self, ptr: *mut ffi::PyObject) -> Option<&'py T> where T: FromPyPointer<'py>, { FromPyPointer::from_owned_ptr_or_opt(self, ptr) } /// Does an unchecked downcast to the specific type. /// /// Panics if the pointer is NULL. /// /// # Safety /// /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention, deprecated)] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `Py::from_borrowed_ptr(py, ptr)` or `Bound::from_borrowed_ptr(py, ptr)` instead" )] pub unsafe fn from_borrowed_ptr(self, ptr: *mut ffi::PyObject) -> &'py T where T: FromPyPointer<'py>, { FromPyPointer::from_borrowed_ptr(self, ptr) } /// Does an unchecked downcast to the specific type. /// /// Returns `Err(PyErr)` if the pointer is NULL. /// /// # Safety /// /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention, deprecated)] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `Py::from_borrowed_ptr_or_err(py, ptr)` or `Bound::from_borrowed_ptr_or_err(py, ptr)` instead" )] pub unsafe fn from_borrowed_ptr_or_err(self, ptr: *mut ffi::PyObject) -> PyResult<&'py T> where T: FromPyPointer<'py>, { FromPyPointer::from_borrowed_ptr_or_err(self, ptr) } /// Does an unchecked downcast to the specific type. /// /// Returns `None` if the pointer is NULL. /// /// # Safety /// /// Callers must ensure that ensure that the cast is valid. #[allow(clippy::wrong_self_convention, deprecated)] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "use `Py::from_borrowed_ptr_or_opt(py, ptr)` or `Bound::from_borrowed_ptr_or_opt(py, ptr)` instead" )] pub unsafe fn from_borrowed_ptr_or_opt(self, ptr: *mut ffi::PyObject) -> Option<&'py T> where T: FromPyPointer<'py>, { FromPyPointer::from_borrowed_ptr_or_opt(self, ptr) } /// Lets the Python interpreter check and handle any pending signals. This will invoke the /// corresponding signal handlers registered in Python (if any). /// /// Returns `Err(`[`PyErr`]`)` if any signal handler raises an exception. /// /// These signals include `SIGINT` (normally raised by CTRL + C), which by default raises /// `KeyboardInterrupt`. For this reason it is good practice to call this function regularly /// as part of long-running Rust functions so that users can cancel it. /// /// # Example /// /// ```rust /// # #![allow(dead_code)] // this example is quite impractical to test /// use pyo3::prelude::*; /// /// # fn main() { /// #[pyfunction] /// fn loop_forever(py: Python<'_>) -> PyResult<()> { /// loop { /// // As this loop is infinite it should check for signals every once in a while. /// // Using `?` causes any `PyErr` (potentially containing `KeyboardInterrupt`) /// // to break out of the loop. /// py.check_signals()?; /// /// // do work here /// # break Ok(()) // don't actually loop forever /// } /// } /// # } /// ``` /// /// # Note /// /// This function calls [`PyErr_CheckSignals()`][1] which in turn may call signal handlers. /// As Python's [`signal`][2] API allows users to define custom signal handlers, calling this /// function allows arbitrary Python code inside signal handlers to run. /// /// If the function is called from a non-main thread, or under a non-main Python interpreter, /// it does nothing yet still returns `Ok(())`. /// /// [1]: https://docs.python.org/3/c-api/exceptions.html?highlight=pyerr_checksignals#c.PyErr_CheckSignals /// [2]: https://docs.python.org/3/library/signal.html pub fn check_signals(self) -> PyResult<()> { err::error_on_minusone(self, unsafe { ffi::PyErr_CheckSignals() }) } /// Create a new pool for managing PyO3's GIL Refs. This has no functional /// use for code which does not use the deprecated GIL Refs API. /// /// When this `GILPool` is dropped, all GIL Refs created after this `GILPool` will /// all have their Python reference counts decremented, potentially allowing Python to drop /// the corresponding Python objects. /// /// Typical usage of PyO3 will not need this API, as [`Python::with_gil`] automatically creates /// a `GILPool` where appropriate. /// /// Advanced uses of PyO3 which perform long-running tasks which never free the GIL may need /// to use this API to clear memory, as PyO3 usually does not clear memory until the GIL is /// released. /// /// # Examples /// /// ```rust /// # use pyo3::prelude::*; /// Python::with_gil(|py| { /// // Some long-running process like a webserver, which never releases the GIL. /// loop { /// // Create a new pool, so that PyO3 can clear memory at the end of the loop. /// #[allow(deprecated)] // `new_pool` is not needed in code not using the GIL Refs API /// let pool = unsafe { py.new_pool() }; /// /// // It is recommended to *always* immediately set py to the pool's Python, to help /// // avoid creating references with invalid lifetimes. /// let py = pool.python(); /// /// // do stuff... /// # break; // Exit the loop so that doctest terminates! /// } /// }); /// ``` /// /// # Safety /// /// Extreme care must be taken when using this API, as misuse can lead to accessing invalid /// memory. In addition, the caller is responsible for guaranteeing that the GIL remains held /// for the entire lifetime of the returned `GILPool`. /// /// Two best practices are required when using this API: /// - From the moment `new_pool()` is called, only the `Python` token from the returned /// `GILPool` (accessible using [`.python()`]) should be used in PyO3 APIs. All other older /// `Python` tokens with longer lifetimes are unsafe to use until the `GILPool` is dropped, /// because they can be used to create PyO3 owned references which have lifetimes which /// outlive the `GILPool`. /// - Similarly, methods on existing owned references will implicitly refer back to the /// `Python` token which that reference was originally created with. If the returned values /// from these methods are owned references they will inherit the same lifetime. As a result, /// Rust's lifetime rules may allow them to outlive the `GILPool`, even though this is not /// safe for reasons discussed above. Care must be taken to never access these return values /// after the `GILPool` is dropped, unless they are converted to `Py` *before* the pool /// is dropped. /// /// [`.python()`]: crate::GILPool::python #[inline] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "code not using the GIL Refs API can safely remove use of `Python::new_pool`" )] #[allow(deprecated)] pub unsafe fn new_pool(self) -> GILPool { GILPool::new() } } impl Python<'_> { /// Creates a scope using a new pool for managing PyO3's GIL Refs. This has no functional /// use for code which does not use the deprecated GIL Refs API. /// /// This is a safe alterantive to [`new_pool`][Self::new_pool] as /// it limits the closure to using the new GIL token at the cost of /// being unable to capture existing GIL-bound references. /// /// Note that on stable Rust, this API suffers from the same the `SendWrapper` loophole /// as [`allow_threads`][Self::allow_threads], c.f. the documentation of the [`Ungil`] trait, /// /// # Examples /// /// ```rust /// # use pyo3::prelude::*; /// Python::with_gil(|py| { /// // Some long-running process like a webserver, which never releases the GIL. /// loop { /// // Create a new scope, so that PyO3 can clear memory at the end of the loop. /// #[allow(deprecated)] // `with_pool` is not needed in code not using the GIL Refs API /// py.with_pool(|py| { /// // do stuff... /// }); /// # break; // Exit the loop so that doctest terminates! /// } /// }); /// ``` /// /// The `Ungil` bound on the closure does prevent hanging on to existing GIL-bound references /// /// ```compile_fail /// # #![allow(deprecated)] /// # use pyo3::prelude::*; /// # use pyo3::types::PyString; /// /// Python::with_gil(|py| { /// let old_str = PyString::new(py, "a message from the past"); /// /// py.with_pool(|_py| { /// print!("{:?}", old_str); /// }); /// }); /// ``` /// /// or continuing to use the old GIL token /// /// ```compile_fail /// # use pyo3::prelude::*; /// /// Python::with_gil(|old_py| { /// old_py.with_pool(|_new_py| { /// let _none = old_py.None(); /// }); /// }); /// ``` #[inline] #[cfg(feature = "gil-refs")] #[deprecated( since = "0.21.0", note = "code not using the GIL Refs API can safely remove use of `Python::with_pool`" )] #[allow(deprecated)] pub fn with_pool(&self, f: F) -> R where F: for<'py> FnOnce(Python<'py>) -> R + Ungil, { // SAFETY: The closure is `Ungil`, // i.e. it does not capture any GIL-bound references // and accesses only the newly created GIL token. let pool = unsafe { GILPool::new() }; f(pool.python()) } } impl<'unbound> Python<'unbound> { /// Unsafely creates a Python token with an unbounded lifetime. /// /// Many of PyO3 APIs use `Python<'_>` as proof that the GIL is held, but this function can be /// used to call them unsafely. /// /// # Safety /// /// - This token and any borrowed Python references derived from it can only be safely used /// whilst the currently executing thread is actually holding the GIL. /// - This function creates a token with an *unbounded* lifetime. Safe code can assume that /// holding a `Python<'py>` token means the GIL is and stays acquired for the lifetime `'py`. /// If you let it or borrowed Python references escape to safe code you are /// responsible for bounding the lifetime `'unbound` appropriately. For more on unbounded /// lifetimes, see the [nomicon]. /// /// [nomicon]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html #[inline] pub unsafe fn assume_gil_acquired() -> Python<'unbound> { Python(PhantomData) } } #[cfg(test)] mod tests { use super::*; use crate::types::{IntoPyDict, PyList}; #[test] fn test_eval() { Python::with_gil(|py| { // Make sure builtin names are accessible let v: i32 = py .eval_bound("min(1, 2)", None, None) .map_err(|e| e.display(py)) .unwrap() .extract() .unwrap(); assert_eq!(v, 1); let d = [("foo", 13)].into_py_dict_bound(py); // Inject our own global namespace let v: i32 = py .eval_bound("foo + 29", Some(&d), None) .unwrap() .extract() .unwrap(); assert_eq!(v, 42); // Inject our own local namespace let v: i32 = py .eval_bound("foo + 29", None, Some(&d)) .unwrap() .extract() .unwrap(); assert_eq!(v, 42); // Make sure builtin names are still accessible when using a local namespace let v: i32 = py .eval_bound("min(foo, 2)", None, Some(&d)) .unwrap() .extract() .unwrap(); assert_eq!(v, 2); }); } #[test] #[cfg(not(target_arch = "wasm32"))] // We are building wasm Python with pthreads disabled fn test_allow_threads_releases_and_acquires_gil() { Python::with_gil(|py| { let b = std::sync::Arc::new(std::sync::Barrier::new(2)); let b2 = b.clone(); std::thread::spawn(move || Python::with_gil(|_| b2.wait())); py.allow_threads(|| { // If allow_threads does not release the GIL, this will deadlock because // the thread spawned above will never be able to acquire the GIL. b.wait(); }); unsafe { // If the GIL is not reacquired at the end of allow_threads, this call // will crash the Python interpreter. let tstate = ffi::PyEval_SaveThread(); ffi::PyEval_RestoreThread(tstate); } }); } #[test] fn test_allow_threads_panics_safely() { Python::with_gil(|py| { let result = std::panic::catch_unwind(|| unsafe { let py = Python::assume_gil_acquired(); py.allow_threads(|| { panic!("There was a panic!"); }); }); // Check panic was caught assert!(result.is_err()); // If allow_threads is implemented correctly, this thread still owns the GIL here // so the following Python calls should not cause crashes. let list = PyList::new_bound(py, [1, 2, 3, 4]); assert_eq!(list.extract::>().unwrap(), vec![1, 2, 3, 4]); }); } #[cfg(not(pyo3_disable_reference_pool))] #[test] fn test_allow_threads_pass_stuff_in() { let list = Python::with_gil(|py| PyList::new_bound(py, vec!["foo", "bar"]).unbind()); let mut v = vec![1, 2, 3]; let a = std::sync::Arc::new(String::from("foo")); Python::with_gil(|py| { py.allow_threads(|| { drop((list, &mut v, a)); }); }); } #[test] #[cfg(not(Py_LIMITED_API))] fn test_acquire_gil() { const GIL_NOT_HELD: c_int = 0; const GIL_HELD: c_int = 1; // Before starting the interpreter the state of calling `PyGILState_Check` // seems to be undefined, so let's ensure that Python is up. #[cfg(not(any(PyPy, GraalPy)))] crate::prepare_freethreaded_python(); let state = unsafe { crate::ffi::PyGILState_Check() }; assert_eq!(state, GIL_NOT_HELD); Python::with_gil(|_| { let state = unsafe { crate::ffi::PyGILState_Check() }; assert_eq!(state, GIL_HELD); }); let state = unsafe { crate::ffi::PyGILState_Check() }; assert_eq!(state, GIL_NOT_HELD); } #[test] fn test_ellipsis() { Python::with_gil(|py| { assert_eq!(py.Ellipsis().to_string(), "Ellipsis"); let v = py .eval_bound("...", None, None) .map_err(|e| e.display(py)) .unwrap(); assert!(v.eq(py.Ellipsis()).unwrap()); }); } #[test] fn test_py_run_inserts_globals() { use crate::types::dict::PyDictMethods; Python::with_gil(|py| { let namespace = PyDict::new_bound(py); py.run_bound("class Foo: pass", Some(&namespace), Some(&namespace)) .unwrap(); assert!(matches!(namespace.get_item("Foo"), Ok(Some(..)))); assert!(matches!(namespace.get_item("__builtins__"), Ok(Some(..)))); }) } } pyo3/src/ffi_ptr_ext.rs0000644000175000017500000000456114661133735016107 0ustar jamespagejamespageuse crate::sealed::Sealed; use crate::{ ffi, instance::{Borrowed, Bound}, PyAny, PyResult, Python, }; pub(crate) trait FfiPtrExt: Sealed { unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult>; unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option>; unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny>; /// Assumes this pointer is borrowed from a parent object. /// /// Warning: the lifetime `'a` is not bounded by the function arguments; the caller is /// responsible to ensure this is tied to some appropriate lifetime. unsafe fn assume_borrowed_or_err<'a>(self, py: Python<'_>) -> PyResult>; /// Same as `assume_borrowed_or_err`, but doesn't fetch an error on NULL. unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option>; /// Same as `assume_borrowed_or_err`, but panics on NULL. unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>; /// Same as `assume_borrowed_or_err`, but does not check for NULL. unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>; } impl FfiPtrExt for *mut ffi::PyObject { #[inline] unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult> { Bound::from_owned_ptr_or_err(py, self) } #[inline] unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option> { Bound::from_owned_ptr_or_opt(py, self) } #[inline] #[track_caller] unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny> { Bound::from_owned_ptr(py, self) } #[inline] unsafe fn assume_borrowed_or_err<'a>( self, py: Python<'_>, ) -> PyResult> { Borrowed::from_ptr_or_err(py, self) } #[inline] unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option> { Borrowed::from_ptr_or_opt(py, self) } #[inline] #[track_caller] unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> { Borrowed::from_ptr(py, self) } #[inline] unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> { Borrowed::from_ptr_unchecked(py, self) } } pyo3/src/derive_utils.rs0000644000175000017500000000172114661133735016267 0ustar jamespagejamespage//! Functionality for the code generated by the derive backend use crate::{types::PyModule, Python}; /// Enum to abstract over the arguments of Python function wrappers. pub enum PyFunctionArguments<'a> { Python(Python<'a>), PyModule(&'a PyModule), } impl<'a> PyFunctionArguments<'a> { pub fn into_py_and_maybe_module(self) -> (Python<'a>, Option<&'a PyModule>) { match self { PyFunctionArguments::Python(py) => (py, None), PyFunctionArguments::PyModule(module) => { let py = crate::PyNativeType::py(module); (py, Some(module)) } } } } impl<'a> From> for PyFunctionArguments<'a> { fn from(py: Python<'a>) -> PyFunctionArguments<'a> { PyFunctionArguments::Python(py) } } impl<'a> From<&'a PyModule> for PyFunctionArguments<'a> { fn from(module: &'a PyModule) -> PyFunctionArguments<'a> { PyFunctionArguments::PyModule(module) } } pyo3/CHANGELOG.md0000644000175000017500000042655414661133735014264 0ustar jamespagejamespage# Changelog All notable changes to this project will be documented in this file. For help with updating to new PyO3 versions, please see the [migration guide](https://pyo3.rs/latest/migration.html). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). To see unreleased changes, please see the [CHANGELOG on the main branch guide](https://pyo3.rs/main/changelog.html). ## [0.22.2] - 2024-07-17 ### Packaging - Require opt-in to freethreaded Python using the `UNSAFE_PYO3_BUILD_FREE_THREADED=1` environment variable (it is not yet supported by PyO3). [#4327](https://github.com/PyO3/pyo3/pull/4327) ### Changed - Use FFI function calls for reference counting on all abi3 versions. [#4324](https://github.com/PyO3/pyo3/pull/4324) - `#[pymodule(...)]` now directly accepts all relevant `#[pyo3(...)]` options. [#4330](https://github.com/PyO3/pyo3/pull/4330) ### Fixed - Fix compile failure in declarative `#[pymodule]` under presence of `#![no_implicit_prelude]`. [#4328](https://github.com/PyO3/pyo3/pull/4328) - Fix compile failure due to c-string literals on Rust < 1.79. [#4353](https://github.com/PyO3/pyo3/pull/4353) ## [0.22.1] - 2024-07-06 ### Added - Add `#[pyo3(submodule)]` option for declarative `#[pymodule]`s. [#4301](https://github.com/PyO3/pyo3/pull/4301) - Implement `PartialEq` for `Bound<'py, PyBool>`. [#4305](https://github.com/PyO3/pyo3/pull/4305) ### Fixed - Return `NotImplemented` instead of raising `TypeError` from generated equality method when comparing different types. [#4287](https://github.com/PyO3/pyo3/pull/4287) - Handle full-path `#[pyo3::prelude::pymodule]` and similar for `#[pyclass]` and `#[pyfunction]` in declarative modules.[#4288](https://github.com/PyO3/pyo3/pull/4288) - Fix 128-bit int regression on big-endian platforms with Python <3.13. [#4291](https://github.com/PyO3/pyo3/pull/4291) - Stop generating code that will never be covered with declarative modules. [#4297](https://github.com/PyO3/pyo3/pull/4297) - Fix invalid deprecation warning for trailing optional on `#[setter]` function. [#4304](https://github.com/PyO3/pyo3/pull/4304) ## [0.22.0] - 2024-06-24 ### Packaging - Update `heck` dependency to 0.5. [#3966](https://github.com/PyO3/pyo3/pull/3966) - Extend range of supported versions of `chrono-tz` optional dependency to include version 0.10. [#4061](https://github.com/PyO3/pyo3/pull/4061) - Update MSRV to 1.63. [#4129](https://github.com/PyO3/pyo3/pull/4129) - Add optional `num-rational` feature to add conversions with Python's `fractions.Fraction`. [#4148](https://github.com/PyO3/pyo3/pull/4148) - Support Python 3.13. [#4184](https://github.com/PyO3/pyo3/pull/4184) ### Added - Add `PyWeakref`, `PyWeakrefReference` and `PyWeakrefProxy`. [#3835](https://github.com/PyO3/pyo3/pull/3835) - Support `#[pyclass]` on enums that have tuple variants. [#4072](https://github.com/PyO3/pyo3/pull/4072) - Add support for scientific notation in `Decimal` conversion. [#4079](https://github.com/PyO3/pyo3/pull/4079) - Add `pyo3_disable_reference_pool` conditional compilation flag to avoid the overhead of the global reference pool at the cost of known limitations as explained in the performance section of the guide. [#4095](https://github.com/PyO3/pyo3/pull/4095) - Add `#[pyo3(constructor = (...))]` to customize the generated constructors for complex enum variants. [#4158](https://github.com/PyO3/pyo3/pull/4158) - Add `PyType::module`, which always matches Python `__module__`. [#4196](https://github.com/PyO3/pyo3/pull/4196) - Add `PyType::fully_qualified_name` which matches the "fully qualified name" defined in [PEP 737](https://peps.python.org/pep-0737). [#4196](https://github.com/PyO3/pyo3/pull/4196) - Add `PyTypeMethods::mro` and `PyTypeMethods::bases`. [#4197](https://github.com/PyO3/pyo3/pull/4197) - Add `#[pyclass(ord)]` to implement ordering based on `PartialOrd`. [#4202](https://github.com/PyO3/pyo3/pull/4202) - Implement `ToPyObject` and `IntoPy` for `PyBackedStr` and `PyBackedBytes`. [#4205](https://github.com/PyO3/pyo3/pull/4205) - Add `#[pyclass(hash)]` option to implement `__hash__` in terms of the `Hash` implementation [#4206](https://github.com/PyO3/pyo3/pull/4206) - Add `#[pyclass(eq)]` option to generate `__eq__` based on `PartialEq`, and `#[pyclass(eq_int)]` for simple enums to implement equality based on their discriminants. [#4210](https://github.com/PyO3/pyo3/pull/4210) - Implement `From>` for `PyClassInitializer`. [#4214](https://github.com/PyO3/pyo3/pull/4214) - Add `as_super` methods to `PyRef` and `PyRefMut` for accesing the base class by reference. [#4219](https://github.com/PyO3/pyo3/pull/4219) - Implement `PartialEq` for `Bound<'py, PyString>`. [#4245](https://github.com/PyO3/pyo3/pull/4245) - Implement `PyModuleMethods::filename` on PyPy. [#4249](https://github.com/PyO3/pyo3/pull/4249) - Implement `PartialEq<[u8]>` for `Bound<'py, PyBytes>`. [#4250](https://github.com/PyO3/pyo3/pull/4250) - Add `pyo3_ffi::c_str` macro to create `&'static CStr` on Rust versions which don't have 1.77's `c""` literals. [#4255](https://github.com/PyO3/pyo3/pull/4255) - Support `bool` conversion with `numpy` 2.0's `numpy.bool` type [#4258](https://github.com/PyO3/pyo3/pull/4258) - Add `PyAnyMethods::{bitnot, matmul, floor_div, rem, divmod}`. [#4264](https://github.com/PyO3/pyo3/pull/4264) ### Changed - Change the type of `PySliceIndices::slicelength` and the `length` parameter of `PySlice::indices()`. [#3761](https://github.com/PyO3/pyo3/pull/3761) - Deprecate implicit default for trailing optional arguments [#4078](https://github.com/PyO3/pyo3/pull/4078) - `Clone`ing pointers into the Python heap has been moved behind the `py-clone` feature, as it must panic without the GIL being held as a soundness fix. [#4095](https://github.com/PyO3/pyo3/pull/4095) - Add `#[track_caller]` to all `Py`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>` methods which can panic. [#4098](https://github.com/PyO3/pyo3/pull/4098) - Change `PyAnyMethods::dir` to be fallible and return `PyResult>` (and similar for `PyAny::dir`). [#4100](https://github.com/PyO3/pyo3/pull/4100) - The global reference pool (to track pending reference count decrements) is now initialized lazily to avoid the overhead of taking a mutex upon function entry when the functionality is not actually used. [#4178](https://github.com/PyO3/pyo3/pull/4178) - Emit error messages when using `weakref` or `dict` when compiling for `abi3` for Python older than 3.9. [#4194](https://github.com/PyO3/pyo3/pull/4194) - Change `PyType::name` to always match Python `__name__`. [#4196](https://github.com/PyO3/pyo3/pull/4196) - Remove CPython internal ffi call for complex number including: add, sub, mul, div, neg, abs, pow. Added PyAnyMethods::{abs, pos, neg} [#4201](https://github.com/PyO3/pyo3/pull/4201) - Deprecate implicit integer comparision for simple enums in favor of `#[pyclass(eq_int)]`. [#4210](https://github.com/PyO3/pyo3/pull/4210) - Set the `module=` attribute of declarative modules' child `#[pymodule]`s and `#[pyclass]`es. [#4213](https://github.com/PyO3/pyo3/pull/4213) - Set the `module` option for complex enum variants from the value set on the complex enum `module`. [#4228](https://github.com/PyO3/pyo3/pull/4228) - Respect the Python "limited API" when building for the `abi3` feature on PyPy or GraalPy. [#4237](https://github.com/PyO3/pyo3/pull/4237) - Optimize code generated by `#[pyo3(get)]` on `#[pyclass]` fields. [#4254](https://github.com/PyO3/pyo3/pull/4254) - `PyCFunction::new`, `PyCFunction::new_with_keywords` and `PyCFunction::new_closure` now take `&'static CStr` name and doc arguments (previously was `&'static str`). [#4255](https://github.com/PyO3/pyo3/pull/4255) - The `experimental-declarative-modules` feature is now stabilized and available by default. [#4257](https://github.com/PyO3/pyo3/pull/4257) ### Fixed - Fix panic when `PYO3_CROSS_LIB_DIR` is set to a missing path. [#4043](https://github.com/PyO3/pyo3/pull/4043) - Fix a compile error when exporting an exception created with `create_exception!` living in a different Rust module using the `declarative-module` feature. [#4086](https://github.com/PyO3/pyo3/pull/4086) - Fix FFI definitions of `PY_VECTORCALL_ARGUMENTS_OFFSET` and `PyVectorcall_NARGS` to fix a false-positive assertion. [#4104](https://github.com/PyO3/pyo3/pull/4104) - Disable `PyUnicode_DATA` on PyPy: not exposed by PyPy. [#4116](https://github.com/PyO3/pyo3/pull/4116) - Correctly handle `#[pyo3(from_py_with = ...)]` attribute on dunder (`__magic__`) method arguments instead of silently ignoring it. [#4117](https://github.com/PyO3/pyo3/pull/4117) - Fix a compile error when declaring a standalone function or class method with a Python name that is a Rust keyword. [#4226](https://github.com/PyO3/pyo3/pull/4226) - Fix declarative modules discarding doc comments on the `mod` node. [#4236](https://github.com/PyO3/pyo3/pull/4236) - Fix `__dict__` attribute missing for `#[pyclass(dict)]` instances when building for `abi3` on Python 3.9. [#4251](https://github.com/PyO3/pyo3/pull/4251) ## [0.21.2] - 2024-04-16 ### Changed - Deprecate the `PySet::empty()` gil-ref constructor. [#4082](https://github.com/PyO3/pyo3/pull/4082) ### Fixed - Fix compile error for `async fn` in `#[pymethods]` with a `&self` receiver and more than one additional argument. [#4035](https://github.com/PyO3/pyo3/pull/4035) - Improve error message for wrong receiver type in `__traverse__`. [#4045](https://github.com/PyO3/pyo3/pull/4045) - Fix compile error when exporting a `#[pyclass]` living in a different Rust module using the `experimental-declarative-modules` feature. [#4054](https://github.com/PyO3/pyo3/pull/4054) - Fix `missing_docs` lint triggering on documented `#[pymodule]` functions. [#4067](https://github.com/PyO3/pyo3/pull/4067) - Fix undefined symbol errors for extension modules on AIX (by linking `libpython`). [#4073](https://github.com/PyO3/pyo3/pull/4073) ## [0.21.1] - 2024-04-01 ### Added - Implement `Send` and `Sync` for `PyBackedStr` and `PyBackedBytes`. [#4007](https://github.com/PyO3/pyo3/pull/4007) - Implement `Clone`, `Debug`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` implementation for `PyBackedBytes` and `PyBackedStr`, and `Display` for `PyBackedStr`. [#4020](https://github.com/PyO3/pyo3/pull/4020) - Add `import_exception_bound!` macro to import exception types without generating GIL Ref functionality for them. [#4027](https://github.com/PyO3/pyo3/pull/4027) ### Changed - Emit deprecation warning for uses of GIL Refs as `#[setter]` function arguments. [#3998](https://github.com/PyO3/pyo3/pull/3998) - Add `#[inline]` hints on many `Bound` and `Borrowed` methods. [#4024](https://github.com/PyO3/pyo3/pull/4024) ### Fixed - Handle `#[pyo3(from_py_with = "")]` in `#[setter]` methods [#3995](https://github.com/PyO3/pyo3/pull/3995) - Allow extraction of `&Bound` in `#[setter]` methods. [#3998](https://github.com/PyO3/pyo3/pull/3998) - Fix some uncovered code blocks emitted by `#[pymodule]`, `#[pyfunction]` and `#[pyclass]` macros. [#4009](https://github.com/PyO3/pyo3/pull/4009) - Fix typo in the panic message when a class referenced in `pyo3::import_exception!` does not exist. [#4012](https://github.com/PyO3/pyo3/pull/4012) - Fix compile error when using an async `#[pymethod]` with a receiver and additional arguments. [#4015](https://github.com/PyO3/pyo3/pull/4015) ## [0.21.0] - 2024-03-25 ### Added - Add support for GraalPy (24.0 and up). [#3247](https://github.com/PyO3/pyo3/pull/3247) - Add `PyMemoryView` type. [#3514](https://github.com/PyO3/pyo3/pull/3514) - Allow `async fn` in for `#[pyfunction]` and `#[pymethods]`, with the `experimental-async` feature. [#3540](https://github.com/PyO3/pyo3/pull/3540) [#3588](https://github.com/PyO3/pyo3/pull/3588) [#3599](https://github.com/PyO3/pyo3/pull/3599) [#3931](https://github.com/PyO3/pyo3/pull/3931) - Implement `PyTypeInfo` for `PyEllipsis`, `PyNone` and `PyNotImplemented`. [#3577](https://github.com/PyO3/pyo3/pull/3577) - Support `#[pyclass]` on enums that have non-unit variants. [#3582](https://github.com/PyO3/pyo3/pull/3582) - Support `chrono` feature with `abi3` feature. [#3664](https://github.com/PyO3/pyo3/pull/3664) - `FromPyObject`, `IntoPy` and `ToPyObject` are implemented on `std::duration::Duration` [#3670](https://github.com/PyO3/pyo3/pull/3670) - Add `PyString::to_cow`. Add `Py::to_str`, `Py::to_cow`, and `Py::to_string_lossy`, as ways to access Python string data safely beyond the GIL lifetime. [#3677](https://github.com/PyO3/pyo3/pull/3677) - Add `Bound` and `Borrowed` smart pointers as a new API for accessing Python objects. [#3686](https://github.com/PyO3/pyo3/pull/3686) - Add `PyNativeType::as_borrowed` to convert "GIL refs" to the new `Bound` smart pointer. [#3692](https://github.com/PyO3/pyo3/pull/3692) - Add `FromPyObject::extract_bound` method, to migrate `FromPyObject` implementations to the Bound API. [#3706](https://github.com/PyO3/pyo3/pull/3706) - Add `gil-refs` feature to allow continued use of the deprecated GIL Refs APIs. [#3707](https://github.com/PyO3/pyo3/pull/3707) - Add methods to `PyAnyMethods` for binary operators (`add`, `sub`, etc.) [#3712](https://github.com/PyO3/pyo3/pull/3712) - Add `chrono-tz` feature allowing conversion between `chrono_tz::Tz` and `zoneinfo.ZoneInfo` [#3730](https://github.com/PyO3/pyo3/pull/3730) - Add FFI definition `PyType_GetModuleByDef`. [#3734](https://github.com/PyO3/pyo3/pull/3734) - Conversion between `std::time::SystemTime` and `datetime.datetime` [#3736](https://github.com/PyO3/pyo3/pull/3736) - Add `Py::as_any` and `Py::into_any`. [#3785](https://github.com/PyO3/pyo3/pull/3785) - Add `PyStringMethods::encode_utf8`. [#3801](https://github.com/PyO3/pyo3/pull/3801) - Add `PyBackedStr` and `PyBackedBytes`, as alternatives to `&str` and `&bytes` where a Python object owns the data. [#3802](https://github.com/PyO3/pyo3/pull/3802) [#3991](https://github.com/PyO3/pyo3/pull/3991) - Allow `#[pymodule]` macro on Rust `mod` blocks, with the `experimental-declarative-modules` feature. [#3815](https://github.com/PyO3/pyo3/pull/3815) - Implement `ExactSizeIterator` for `set` and `frozenset` iterators on `abi3` feature. [#3849](https://github.com/PyO3/pyo3/pull/3849) - Add `Py::drop_ref` to explicitly drop a `Py`` and immediately decrease the Python reference count if the GIL is already held. [#3871](https://github.com/PyO3/pyo3/pull/3871) - Allow `#[pymodule]` macro on single argument functions that take `&Bound<'_, PyModule>`. [#3905](https://github.com/PyO3/pyo3/pull/3905) - Implement `FromPyObject` for `Cow`. [#3928](https://github.com/PyO3/pyo3/pull/3928) - Implement `Default` for `GILOnceCell`. [#3971](https://github.com/PyO3/pyo3/pull/3971) - Add `PyDictMethods::into_mapping`, `PyListMethods::into_sequence` and `PyTupleMethods::into_sequence`. [#3982](https://github.com/PyO3/pyo3/pull/3982) ### Changed - `PyDict::from_sequence` now takes a single argument of type `&PyAny` (previously took two arguments `Python` and `PyObject`). [#3532](https://github.com/PyO3/pyo3/pull/3532) - Deprecate `Py::is_ellipsis` and `PyAny::is_ellipsis` in favour of `any.is(py.Ellipsis())`. [#3577](https://github.com/PyO3/pyo3/pull/3577) - Split some `PyTypeInfo` functionality into new traits `HasPyGilRef` and `PyTypeCheck`. [#3600](https://github.com/PyO3/pyo3/pull/3600) - Deprecate `PyTryFrom` and `PyTryInto` traits in favor of `any.downcast()` via the `PyTypeCheck` and `PyTypeInfo` traits. [#3601](https://github.com/PyO3/pyo3/pull/3601) - Allow async methods to accept `&self`/`&mut self` [#3609](https://github.com/PyO3/pyo3/pull/3609) - `FromPyObject` for set types now also accept `frozenset` objects as input. [#3632](https://github.com/PyO3/pyo3/pull/3632) - `FromPyObject` for `bool` now also accepts NumPy's `bool_` as input. [#3638](https://github.com/PyO3/pyo3/pull/3638) - Add `AsRefSource` associated type to `PyNativeType`. [#3653](https://github.com/PyO3/pyo3/pull/3653) - Rename `.is_true` to `.is_truthy` on `PyAny` and `Py` to clarify that the test is not based on identity with or equality to the True singleton. [#3657](https://github.com/PyO3/pyo3/pull/3657) - `PyType::name` is now `PyType::qualname` whereas `PyType::name` efficiently accesses the full name which includes the module name. [#3660](https://github.com/PyO3/pyo3/pull/3660) - The `Iter(A)NextOutput` types are now deprecated and `__(a)next__` can directly return anything which can be converted into Python objects, i.e. awaitables do not need to be wrapped into `IterANextOutput` or `Option` any more. `Option` can still be used as well and returning `None` will trigger the fast path for `__next__`, stopping iteration without having to raise a `StopIteration` exception. [#3661](https://github.com/PyO3/pyo3/pull/3661) - Implement `FromPyObject` on `chrono::DateTime` for all `Tz`, not just `FixedOffset` and `Utc`. [#3663](https://github.com/PyO3/pyo3/pull/3663) - Add lifetime parameter to `PyTzInfoAccess` trait. For the deprecated gil-ref API, the trait is now implemented for `&'py PyTime` and `&'py PyDateTime` instead of `PyTime` and `PyDate`. [#3679](https://github.com/PyO3/pyo3/pull/3679) - Calls to `__traverse__` become no-ops for unsendable pyclasses if on the wrong thread, thereby avoiding hard aborts at the cost of potential leakage. [#3689](https://github.com/PyO3/pyo3/pull/3689) - Include `PyNativeType` in `pyo3::prelude`. [#3692](https://github.com/PyO3/pyo3/pull/3692) - Improve performance of `extract::` (and other integer types) by avoiding call to `__index__()` converting the value to an integer for 3.10+. Gives performance improvement of around 30% for successful extraction. [#3742](https://github.com/PyO3/pyo3/pull/3742) - Relax bound of `FromPyObject` for `Py` to just `T: PyTypeCheck`. [#3776](https://github.com/PyO3/pyo3/pull/3776) - `PySet` and `PyFrozenSet` iterators now always iterate the equivalent of `iter(set)`. (A "fast path" with no noticeable performance benefit was removed.) [#3849](https://github.com/PyO3/pyo3/pull/3849) - Move implementations of `FromPyObject` for `&str`, `Cow`, `&[u8]` and `Cow<[u8]>` onto a temporary trait `FromPyObjectBound` when `gil-refs` feature is deactivated. [#3928](https://github.com/PyO3/pyo3/pull/3928) - Deprecate `GILPool`, `Python::with_pool`, and `Python::new_pool`. [#3947](https://github.com/PyO3/pyo3/pull/3947) ### Removed - Remove all functionality deprecated in PyO3 0.19. [#3603](https://github.com/PyO3/pyo3/pull/3603) ### Fixed - Match PyPy 7.3.14 in removing PyPy-only symbol `Py_MAX_NDIMS` in favour of `PyBUF_MAX_NDIM`. [#3757](https://github.com/PyO3/pyo3/pull/3757) - Fix segmentation fault using `datetime` types when an invalid `datetime` module is on sys.path. [#3818](https://github.com/PyO3/pyo3/pull/3818) - Fix `non_local_definitions` lint warning triggered by many PyO3 macros. [#3901](https://github.com/PyO3/pyo3/pull/3901) - Disable `PyCode` and `PyCode_Type` on PyPy: `PyCode_Type` is not exposed by PyPy. [#3934](https://github.com/PyO3/pyo3/pull/3934) ## [0.21.0-beta.0] - 2024-03-10 Prerelease of PyO3 0.21. See [the GitHub diff](https://github.com/pyo3/pyo3/compare/v0.21.0-beta.0...v0.21.0) for what changed between 0.21.0-beta.0 and the final release. ## [0.20.3] - 2024-02-23 ### Packaging - Add `portable-atomic` dependency. [#3619](https://github.com/PyO3/pyo3/pull/3619) - Check maximum version of Python at build time and for versions not yet supported require opt-in to the `abi3` stable ABI by the environment variable `PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1`. [#3821](https://github.com/PyO3/pyo3/pull/3821) ### Fixed - Use `portable-atomic` to support platforms without 64-bit atomics. [#3619](https://github.com/PyO3/pyo3/pull/3619) - Fix compilation failure with `either` feature enabled without `experimental-inspect` enabled. [#3834](https://github.com/PyO3/pyo3/pull/3834) ## [0.20.2] - 2024-01-04 ### Packaging - Pin `pyo3` and `pyo3-ffi` dependencies on `pyo3-build-config` to require the same patch version, i.e. `pyo3` 0.20.2 requires _exactly_ `pyo3-build-config` 0.20.2. [#3721](https://github.com/PyO3/pyo3/pull/3721) ### Fixed - Fix compile failure when building `pyo3` 0.20.0 with latest `pyo3-build-config` 0.20.X. [#3724](https://github.com/PyO3/pyo3/pull/3724) - Fix docs.rs build. [#3722](https://github.com/PyO3/pyo3/pull/3722) ## [0.20.1] - 2023-12-30 ### Added - Add optional `either` feature to add conversions for `either::Either` sum type. [#3456](https://github.com/PyO3/pyo3/pull/3456) - Add optional `smallvec` feature to add conversions for `smallvec::SmallVec`. [#3507](https://github.com/PyO3/pyo3/pull/3507) - Add `take` and `into_inner` methods to `GILOnceCell` [#3556](https://github.com/PyO3/pyo3/pull/3556) - `#[classmethod]` methods can now also receive `Py` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587) - `#[pyfunction(pass_module)]` can now also receive `Py` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587) - Add `traverse` method to `GILProtected`. [#3616](https://github.com/PyO3/pyo3/pull/3616) - Added `abi3-py312` feature [#3687](https://github.com/PyO3/pyo3/pull/3687) ### Fixed - Fix minimum version specification for optional `chrono` dependency. [#3512](https://github.com/PyO3/pyo3/pull/3512) - Silenced new `clippy::unnecessary_fallible_conversions` warning when using a `Py` `self` receiver. [#3564](https://github.com/PyO3/pyo3/pull/3564) ## [0.20.0] - 2023-10-11 ### Packaging - Dual-license PyO3 under either the Apache 2.0 OR the MIT license. This makes the project GPLv2 compatible. [#3108](https://github.com/PyO3/pyo3/pull/3108) - Update MSRV to Rust 1.56. [#3208](https://github.com/PyO3/pyo3/pull/3208) - Bump `indoc` dependency to 2.0 and `unindent` dependency to 0.2. [#3237](https://github.com/PyO3/pyo3/pull/3237) - Bump `syn` dependency to 2.0. [#3239](https://github.com/PyO3/pyo3/pull/3239) - Drop support for debug builds of Python 3.7. [#3387](https://github.com/PyO3/pyo3/pull/3387) - Bump `chrono` optional dependency to require 0.4.25 or newer. [#3427](https://github.com/PyO3/pyo3/pull/3427) - Support Python 3.12. [#3488](https://github.com/PyO3/pyo3/pull/3488) ### Added - Support `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__` and `__ge__` in `#[pymethods]`. [#3203](https://github.com/PyO3/pyo3/pull/3203) - Add FFI definition `Py_GETENV`. [#3336](https://github.com/PyO3/pyo3/pull/3336) - Add `as_ptr` and `into_ptr` inherent methods for `Py`, `PyAny`, `PyRef`, and `PyRefMut`. [#3359](https://github.com/PyO3/pyo3/pull/3359) - Implement `DoubleEndedIterator` for `PyTupleIterator` and `PyListIterator`. [#3366](https://github.com/PyO3/pyo3/pull/3366) - Add `#[pyclass(rename_all = "...")]` option: this allows renaming all getters and setters of a struct, or all variants of an enum. Available renaming rules are: `"camelCase"`, `"kebab-case"`, `"lowercase"`, `"PascalCase"`, `"SCREAMING-KEBAB-CASE"`, `"SCREAMING_SNAKE_CASE"`, `"snake_case"`, `"UPPERCASE"`. [#3384](https://github.com/PyO3/pyo3/pull/3384) - Add FFI definitions `PyObject_GC_IsTracked` and `PyObject_GC_IsFinalized` on Python 3.9 and up (PyPy 3.10 and up). [#3403](https://github.com/PyO3/pyo3/pull/3403) - Add types for `None`, `Ellipsis`, and `NotImplemented`. [#3408](https://github.com/PyO3/pyo3/pull/3408) - Add FFI definitions for the `Py_mod_multiple_interpreters` constant and its possible values. [#3494](https://github.com/PyO3/pyo3/pull/3494) - Add FFI definitions for `PyInterpreterConfig` struct, its constants and `Py_NewInterpreterFromConfig`. [#3502](https://github.com/PyO3/pyo3/pull/3502) ### Changed - Change `PySet::discard` to return `PyResult` (previously returned nothing). [#3281](https://github.com/PyO3/pyo3/pull/3281) - Optimize implmentation of `IntoPy` for Rust tuples to Python tuples. [#3321](https://github.com/PyO3/pyo3/pull/3321) - Change `PyDict::get_item` to no longer suppress arbitrary exceptions (the return type is now `PyResult>` instead of `Option<&PyAny>`), and deprecate `PyDict::get_item_with_error`. [#3330](https://github.com/PyO3/pyo3/pull/3330) - Deprecate FFI definitions which are deprecated in Python 3.12. [#3336](https://github.com/PyO3/pyo3/pull/3336) - `AsPyPointer` is now an `unsafe trait`. [#3358](https://github.com/PyO3/pyo3/pull/3358) - Accept all `os.PathLike` values in implementation of `FromPyObject` for `PathBuf`. [#3374](https://github.com/PyO3/pyo3/pull/3374) - Add `__builtins__` to globals in `py.run()` and `py.eval()` if they're missing. [#3378](https://github.com/PyO3/pyo3/pull/3378) - Optimize implementation of `FromPyObject` for `BigInt` and `BigUint`. [#3379](https://github.com/PyO3/pyo3/pull/3379) - `PyIterator::from_object` and `PyByteArray::from` now take a single argument of type `&PyAny` (previously took two arguments `Python` and `AsPyPointer`). [#3389](https://github.com/PyO3/pyo3/pull/3389) - Replace `AsPyPointer` with `AsRef` as a bound in the blanket implementation of `From<&T> for PyObject`. [#3391](https://github.com/PyO3/pyo3/pull/3391) - Replace blanket `impl IntoPy for &T where T: AsPyPointer` with implementations of `impl IntoPy` for `&PyAny`, `&T where T: AsRef`, and `&Py`. [#3393](https://github.com/PyO3/pyo3/pull/3393) - Preserve `std::io::Error` kind in implementation of `From` for `PyErr` [#3396](https://github.com/PyO3/pyo3/pull/3396) - Try to select a relevant `ErrorKind` in implementation of `From` for `OSError` subclass. [#3397](https://github.com/PyO3/pyo3/pull/3397) - Retrieve the original `PyErr` in implementation of `From` for `PyErr` if the `std::io::Error` has been built using a Python exception (previously would create a new exception wrapping the `std::io::Error`). [#3402](https://github.com/PyO3/pyo3/pull/3402) - `#[pymodule]` will now return the same module object on repeated import by the same Python interpreter, on Python 3.9 and up. [#3446](https://github.com/PyO3/pyo3/pull/3446) - Truncate leap-seconds and warn when converting `chrono` types to Python `datetime` types (`datetime` cannot represent leap-seconds). [#3458](https://github.com/PyO3/pyo3/pull/3458) - `Err` returned from `#[pyfunction]` will now have a non-None `__context__` if called from inside a `catch` block. [#3455](https://github.com/PyO3/pyo3/pull/3455) - Deprecate undocumented `#[__new__]` form of `#[new]` attribute. [#3505](https://github.com/PyO3/pyo3/pull/3505) ### Removed - Remove all functionality deprecated in PyO3 0.18, including `#[args]` attribute for `#[pymethods]`. [#3232](https://github.com/PyO3/pyo3/pull/3232) - Remove `IntoPyPointer` trait in favour of `into_ptr` inherent methods. [#3385](https://github.com/PyO3/pyo3/pull/3385) ### Fixed - Handle exceptions properly in `PySet::discard`. [#3281](https://github.com/PyO3/pyo3/pull/3281) - The `PyTupleIterator` type returned by `PyTuple::iter` is now public and hence can be named by downstream crates. [#3366](https://github.com/PyO3/pyo3/pull/3366) - Linking of `PyOS_FSPath` on PyPy. [#3374](https://github.com/PyO3/pyo3/pull/3374) - Fix memory leak in `PyTypeBuilder::build`. [#3401](https://github.com/PyO3/pyo3/pull/3401) - Disable removed FFI definitions `_Py_GetAllocatedBlocks`, `_PyObject_GC_Malloc`, and `_PyObject_GC_Calloc` on Python 3.11 and up. [#3403](https://github.com/PyO3/pyo3/pull/3403) - Fix `ResourceWarning` and crashes related to GC when running with debug builds of CPython. [#3404](https://github.com/PyO3/pyo3/pull/3404) - Some-wrapping of `Option` default arguments will no longer re-wrap `Some(T)` or expressions evaluating to `None`. [#3461](https://github.com/PyO3/pyo3/pull/3461) - Fix `IterNextOutput::Return` not returning a value on PyPy. [#3471](https://github.com/PyO3/pyo3/pull/3471) - Emit compile errors instead of ignoring macro invocations inside `#[pymethods]` blocks. [#3491](https://github.com/PyO3/pyo3/pull/3491) - Emit error on invalid arguments to `#[new]`, `#[classmethod]`, `#[staticmethod]`, and `#[classattr]`. [#3484](https://github.com/PyO3/pyo3/pull/3484) - Disable `PyMarshal_WriteObjectToString` from `PyMarshal_ReadObjectFromString` with the `abi3` feature. [#3490](https://github.com/PyO3/pyo3/pull/3490) - Fix FFI definitions for `_PyFrameEvalFunction` on Python 3.11 and up (it now receives a `_PyInterpreterFrame` opaque struct). [#3500](https://github.com/PyO3/pyo3/pull/3500) ## [0.19.2] - 2023-08-01 ### Added - Add FFI definitions `PyState_AddModule`, `PyState_RemoveModule` and `PyState_FindModule` for PyPy 3.9 and up. [#3295](https://github.com/PyO3/pyo3/pull/3295) - Add FFI definitions `_PyObject_CallFunction_SizeT` and `_PyObject_CallMethod_SizeT`. [#3297](https://github.com/PyO3/pyo3/pull/3297) - Add a "performance" section to the guide collecting performance-related tricks and problems. [#3304](https://github.com/PyO3/pyo3/pull/3304) - Add `PyErr::Display` for all Python versions, and FFI symbol `PyErr_DisplayException` for Python 3.12. [#3334](https://github.com/PyO3/pyo3/pull/3334) - Add FFI definition `PyType_GetDict()` for Python 3.12. [#3339](https://github.com/PyO3/pyo3/pull/3339) - Add `PyAny::downcast_exact`. [#3346](https://github.com/PyO3/pyo3/pull/3346) - Add `PySlice::full()` to construct a full slice (`::`). [#3353](https://github.com/PyO3/pyo3/pull/3353) ### Changed - Update `PyErr` for 3.12 betas to avoid deprecated ffi methods. [#3306](https://github.com/PyO3/pyo3/pull/3306) - Update FFI definitions of `object.h` for Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335) - Update `pyo3::ffi` struct definitions to be compatible with 3.12.0b4. [#3342](https://github.com/PyO3/pyo3/pull/3342) - Optimize conversion of `float` to `f64` (and `PyFloat::value`) on non-abi3 builds. [#3345](https://github.com/PyO3/pyo3/pull/3345) ### Fixed - Fix timezone conversion bug for FixedOffset datetimes that were being incorrectly converted to and from UTC. [#3269](https://github.com/PyO3/pyo3/pull/3269) - Fix `SystemError` raised in `PyUnicodeDecodeError_Create` on PyPy 3.10. [#3297](https://github.com/PyO3/pyo3/pull/3297) - Correct FFI definition `Py_EnterRecursiveCall` to return `c_int` (was incorrectly returning `()`). [#3300](https://github.com/PyO3/pyo3/pull/3300) - Fix case where `PyErr::matches` and `PyErr::is_instance` returned results inconsistent with `PyErr::get_type`. [#3313](https://github.com/PyO3/pyo3/pull/3313) - Fix loss of panic message in `PanicException` when unwinding after the exception was "normalized". [#3326](https://github.com/PyO3/pyo3/pull/3326) - Fix `PyErr::from_value` and `PyErr::into_value` losing traceback on conversion. [#3328](https://github.com/PyO3/pyo3/pull/3328) - Fix reference counting of immortal objects on Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335) ## [0.19.1] - 2023-07-03 ### Packaging - Extend range of supported versions of `hashbrown` optional dependency to include version 0.14 [#3258](https://github.com/PyO3/pyo3/pull/3258) - Extend range of supported versions of `indexmap` optional dependency to include version 2. [#3277](https://github.com/PyO3/pyo3/pull/3277) - Support PyPy 3.10. [#3289](https://github.com/PyO3/pyo3/pull/3289) ### Added - Add `pyo3::types::PyFrozenSetBuilder` to allow building a `PyFrozenSet` item by item. [#3156](https://github.com/PyO3/pyo3/pull/3156) - Add support for converting to and from Python's `ipaddress.IPv4Address`/`ipaddress.IPv6Address` and `std::net::IpAddr`. [#3197](https://github.com/PyO3/pyo3/pull/3197) - Add support for `num-bigint` feature in combination with `abi3`. [#3198](https://github.com/PyO3/pyo3/pull/3198) - Add `PyErr_GetRaisedException()`, `PyErr_SetRaisedException()` to FFI definitions for Python 3.12 and later. [#3248](https://github.com/PyO3/pyo3/pull/3248) - Add `Python::with_pool` which is a safer but more limited alternative to `Python::new_pool`. [#3263](https://github.com/PyO3/pyo3/pull/3263) - Add `PyDict::get_item_with_error` on PyPy. [#3270](https://github.com/PyO3/pyo3/pull/3270) - Allow `#[new]` methods may to return `Py` in order to return existing instances. [#3287](https://github.com/PyO3/pyo3/pull/3287) ### Fixed - Fix conversion of classes implementing `__complex__` to `Complex` when using `abi3` or PyPy. [#3185](https://github.com/PyO3/pyo3/pull/3185) - Stop suppressing unrelated exceptions in `PyAny::hasattr`. [#3271](https://github.com/PyO3/pyo3/pull/3271) - Fix memory leak when creating `PySet` or `PyFrozenSet` or returning types converted into these internally, e.g. `HashSet` or `BTreeSet`. [#3286](https://github.com/PyO3/pyo3/pull/3286) ## [0.19.0] - 2023-05-31 ### Packaging - Correct dependency on syn to version 1.0.85 instead of the incorrect version 1.0.56. [#3152](https://github.com/PyO3/pyo3/pull/3152) ### Added - Accept `text_signature` option (and automatically generate signature) for `#[new]` in `#[pymethods]`. [#2980](https://github.com/PyO3/pyo3/pull/2980) - Add support for converting to and from Python's `decimal.Decimal` and `rust_decimal::Decimal`. [#3016](https://github.com/PyO3/pyo3/pull/3016) - Add `#[pyo3(from_item_all)]` when deriving `FromPyObject` to specify `get_item` as getter for all fields. [#3120](https://github.com/PyO3/pyo3/pull/3120) - Add `pyo3::exceptions::PyBaseExceptionGroup` for Python 3.11, and corresponding FFI definition `PyExc_BaseExceptionGroup`. [#3141](https://github.com/PyO3/pyo3/pull/3141) - Accept `#[new]` with `#[classmethod]` to create a constructor which receives a (subtype's) class/`PyType` as its first argument. [#3157](https://github.com/PyO3/pyo3/pull/3157) - Add `PyClass::get` and `Py::get` for GIL-indepedent access to classes with `#[pyclass(frozen)]`. [#3158](https://github.com/PyO3/pyo3/pull/3158) - Add `PyAny::is_exact_instance` and `PyAny::is_exact_instance_of`. [#3161](https://github.com/PyO3/pyo3/pull/3161) ### Changed - `PyAny::is_instance_of::(obj)` is now equivalent to `T::is_type_of(obj)`, and now returns `bool` instead of `PyResult`. [#2881](https://github.com/PyO3/pyo3/pull/2881) - Deprecate `text_signature` option on `#[pyclass]` structs. [#2980](https://github.com/PyO3/pyo3/pull/2980) - No longer wrap `anyhow::Error`/`eyre::Report` containing a basic `PyErr` without a chain in a `PyRuntimeError`. [#3004](https://github.com/PyO3/pyo3/pull/3004) - - Change `#[getter]` and `#[setter]` to use a common call "trampoline" to slightly reduce generated code size and compile times. [#3029](https://github.com/PyO3/pyo3/pull/3029) - Improve default values for str, numbers and bool in automatically-generated `text_signature`. [#3050](https://github.com/PyO3/pyo3/pull/3050) - Improve default value for `None` in automatically-generated `text_signature`. [#3066](https://github.com/PyO3/pyo3/pull/3066) - Rename `PySequence::list` and `PySequence::tuple` to `PySequence::to_list` and `PySequence::to_tuple`. (The old names continue to exist as deprecated forms.) [#3111](https://github.com/PyO3/pyo3/pull/3111) - Extend the lifetime of the GIL token returned by `PyRef::py` and `PyRefMut::py` to match the underlying borrow. [#3131](https://github.com/PyO3/pyo3/pull/3131) - Safe access to the GIL, for example via `Python::with_gil`, is now locked inside of implementations of the `__traverse__` slot. [#3168](https://github.com/PyO3/pyo3/pull/3168) ### Removed - Remove all functionality deprecated in PyO3 0.17, most prominently `Python::acquire_gil` is replaced by `Python::with_gil`. [#2981](https://github.com/PyO3/pyo3/pull/2981) ### Fixed - Correct FFI definitions `PyGetSetDef`, `PyMemberDef`, `PyStructSequence_Field` and `PyStructSequence_Desc` to have `*const c_char` members for `name` and `doc` (not `*mut c_char`). [#3036](https://github.com/PyO3/pyo3/pull/3036) - Fix panic on `fmt::Display`, instead return `""` string and report error via `sys.unraisablehook()` [#3062](https://github.com/PyO3/pyo3/pull/3062) - Fix a compile error of "temporary value dropped while borrowed" when `#[pyfunction]`s take references into `#[pyclass]`es [#3142](https://github.com/PyO3/pyo3/pull/3142) - Fix crashes caused by PyO3 applying deferred reference count updates when entering a `__traverse__` implementation. [#3168](https://github.com/PyO3/pyo3/pull/3168) - Forbid running the `Drop` implementations of unsendable classes on other threads. [#3176](https://github.com/PyO3/pyo3/pull/3176) - Fix a compile error when `#[pymethods]` items come from somewhere else (for example, as a macro argument) and a custom receiver like `Py` is used. [#3178](https://github.com/PyO3/pyo3/pull/3178) ## [0.18.3] - 2023-04-13 ### Added - Add `GILProtected` to mediate concurrent access to a value using Python's global interpreter lock (GIL). [#2975](https://github.com/PyO3/pyo3/pull/2975) - Support `PyASCIIObject` / `PyUnicode` and associated methods on big-endian architectures. [#3015](https://github.com/PyO3/pyo3/pull/3015) - Add FFI definition `_PyDict_Contains_KnownHash()` for CPython 3.10 and up. [#3088](https://github.com/PyO3/pyo3/pull/3088) ### Fixed - Fix compile error for `#[pymethods]` and `#[pyfunction]` called "output". [#3022](https://github.com/PyO3/pyo3/pull/3022) - Fix compile error in generated code for magic methods implemented as a `#[staticmethod]`. [#3055](https://github.com/PyO3/pyo3/pull/3055) - Fix `is_instance` for `PyDateTime` (would incorrectly check for a `PyDate`). [#3071](https://github.com/PyO3/pyo3/pull/3071) - Fix upstream deprecation of `PyUnicode_InternImmortal` since Python 3.10. [#3071](https://github.com/PyO3/pyo3/pull/3087) ## [0.18.2] - 2023-03-24 ### Packaging - Disable default features of `chrono` to avoid depending on `time` v0.1.x. [#2939](https://github.com/PyO3/pyo3/pull/2939) ### Added - Implement `IntoPy`, `ToPyObject` and `FromPyObject` for `Cow<[u8]>` to efficiently handle both `bytes` and `bytearray` objects. [#2899](https://github.com/PyO3/pyo3/pull/2899) - Implement `IntoPy`, `ToPyObject` and `FromPyObject` for `Cell`. [#3014](https://github.com/PyO3/pyo3/pull/3014) - Add `PyList::to_tuple()`, as a convenient and efficient conversion from lists to tuples. [#3042](https://github.com/PyO3/pyo3/pull/3042) - Add `PyTuple::to_list()`, as a convenient and efficient conversion from tuples to lists. [#3044](https://github.com/PyO3/pyo3/pull/3044) ### Changed - Optimize `PySequence` conversion for `list` and `tuple` inputs. [#2944](https://github.com/PyO3/pyo3/pull/2944) - Improve exception raised when creating `#[pyclass]` type object fails during module import. [#2947](https://github.com/PyO3/pyo3/pull/2947) - Optimize `PyMapping` conversion for `dict` inputs. [#2954](https://github.com/PyO3/pyo3/pull/2954) - Allow `create_exception!` to take a `dotted.module` to place the exception in a submodule. [#2979](https://github.com/PyO3/pyo3/pull/2979) ### Fixed - Fix a reference counting race condition affecting `PyObject`s cloned in `allow_threads` blocks. [#2952](https://github.com/PyO3/pyo3/pull/2952) - Fix `clippy::redundant_closure` lint on default arguments in `#[pyo3(signature = (...))]` annotations. [#2990](https://github.com/PyO3/pyo3/pull/2990) - Fix `non_snake_case` lint on generated code in `#[pyfunction]` macro. [#2993](https://github.com/PyO3/pyo3/pull/2993) - Fix some FFI definitions for the upcoming PyPy 3.10 release. [#3031](https://github.com/PyO3/pyo3/pull/3031) ## [0.18.1] - 2023-02-07 ### Added - Add `PyErr::write_unraisable()`. [#2889](https://github.com/PyO3/pyo3/pull/2889) - Add `Python::Ellipsis()` and `PyAny::is_ellipsis()` methods. [#2911](https://github.com/PyO3/pyo3/pull/2911) - Add `PyDict::update()` and `PyDict::update_if_missing()` methods. [#2912](https://github.com/PyO3/pyo3/pull/2912) ### Changed - FFI definition `PyIter_Check` on CPython 3.7 is now implemented as `hasattr(type(obj), "__next__")`, which works correctly on all platforms and adds support for `abi3`. [#2914](https://github.com/PyO3/pyo3/pull/2914) - Warn about unknown config keys in `PYO3_CONFIG_FILE` instead of denying. [#2926](https://github.com/PyO3/pyo3/pull/2926) ### Fixed - Send errors returned by `__releasebuffer__` to `sys.unraisablehook` rather than causing `SystemError`. [#2886](https://github.com/PyO3/pyo3/pull/2886) - Fix downcast to `PyIterator` succeeding for Python classes which did not implement `__next__`. [#2914](https://github.com/PyO3/pyo3/pull/2914) - Fix segfault in `__traverse__` when visiting `None` fields of `Option`. [#2921](https://github.com/PyO3/pyo3/pull/2921) - Fix `#[pymethods(crate = "...")]` option being ignored. [#2923](https://github.com/PyO3/pyo3/pull/2923) - Link against `pythonXY_d.dll` for debug Python builds on Windows. [#2937](https://github.com/PyO3/pyo3/pull/2937) ## [0.18.0] - 2023-01-17 ### Packaging - Relax `indexmap` optional depecency to allow `>= 1.6, < 2`. [#2849](https://github.com/PyO3/pyo3/pull/2849) - Relax `hashbrown` optional dependency to allow `>= 0.9, < 0.14`. [#2875](https://github.com/PyO3/pyo3/pull/2875) - Update `memoffset` dependency to 0.8. [#2875](https://github.com/PyO3/pyo3/pull/2875) ### Added - Add `GILOnceCell::get_or_try_init` for fallible `GILOnceCell` initialization. [#2398](https://github.com/PyO3/pyo3/pull/2398) - Add experimental feature `experimental-inspect` with `type_input()` and `type_output()` helpers to get the Python type of any Python-compatible object. [#2490](https://github.com/PyO3/pyo3/pull/2490) [#2882](https://github.com/PyO3/pyo3/pull/2882) - The `#[pyclass]` macro can now take `get_all` and `set_all` to create getters and setters for every field. [#2692](https://github.com/PyO3/pyo3/pull/2692) - Add `#[pyo3(signature = (...))]` option for `#[pyfunction]` and `#[pymethods]`. [#2702](https://github.com/PyO3/pyo3/pull/2702) - `pyo3-build-config`: rebuild when `PYO3_ENVIRONMENT_SIGNATURE` environment variable value changes. [#2727](https://github.com/PyO3/pyo3/pull/2727) - Add conversions between non-zero int types in `std::num` and Python `int`. [#2730](https://github.com/PyO3/pyo3/pull/2730) - Add `Py::downcast()` as a companion to `PyAny::downcast()`, as well as `downcast_unchecked()` for both types. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Add types for all built-in `Warning` classes as well as `PyErr::warn_explicit`. [#2742](https://github.com/PyO3/pyo3/pull/2742) - Add `abi3-py311` feature. [#2776](https://github.com/PyO3/pyo3/pull/2776) - Add FFI definition `_PyErr_ChainExceptions()` for CPython. [#2788](https://github.com/PyO3/pyo3/pull/2788) - Add FFI definitions `PyVectorcall_NARGS` and `PY_VECTORCALL_ARGUMENTS_OFFSET` for PyPy 3.8 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811) - Add `PyList::get_item_unchecked` for PyPy. [#2827](https://github.com/PyO3/pyo3/pull/2827) ### Changed - PyO3's macros now emit a much nicer error message if function return values don't implement the required trait(s). [#2664](https://github.com/PyO3/pyo3/pull/2664) - Use a TypeError, rather than a ValueError, when refusing to treat a str as a Vec. [#2685](https://github.com/PyO3/pyo3/pull/2685) - Change `PyCFunction::new_closure` to take `name` and `doc` arguments. [#2686](https://github.com/PyO3/pyo3/pull/2686) - `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now take `&PyAny` instead of `&PyType` arguments, so that they work with objects that pretend to be types using `__subclasscheck__` and `__instancecheck__`. [#2695](https://github.com/PyO3/pyo3/pull/2695) - Deprecate `#[args]` attribute and passing "args" specification directly to `#[pyfunction]` in favor of the new `#[pyo3(signature = (...))]` option. [#2702](https://github.com/PyO3/pyo3/pull/2702) - Deprecate required arguments after `Option` arguments to `#[pyfunction]` and `#[pymethods]` without also using `#[pyo3(signature)]` to specify whether the arguments should be required or have defaults. [#2703](https://github.com/PyO3/pyo3/pull/2703) - Change `#[pyfunction]` and `#[pymethods]` to use a common call "trampoline" to slightly reduce generated code size and compile times. [#2705](https://github.com/PyO3/pyo3/pull/2705) - `PyAny::cast_as()` and `Py::cast_as()` are now deprecated in favor of `PyAny::downcast()` and the new `Py::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Relax lifetime bounds on `PyAny::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734) - Automatically generate `__text_signature__` for all Python functions created using `#[pyfunction]` and `#[pymethods]`. [#2784](https://github.com/PyO3/pyo3/pull/2784) - Accept any iterator in `PySet::new` and `PyFrozenSet::new`. [#2795](https://github.com/PyO3/pyo3/pull/2795) - Mixing `#[cfg(...)]` and `#[pyo3(...)]` attributes on `#[pyclass]` struct fields will now work. [#2796](https://github.com/PyO3/pyo3/pull/2796) - Re-enable `PyFunction` on when building for abi3 or PyPy. [#2838](https://github.com/PyO3/pyo3/pull/2838) - Improve `derive(FromPyObject)` to use `intern!` when applicable for `#[pyo3(item)]`. [#2879](https://github.com/PyO3/pyo3/pull/2879) ### Removed - Remove the deprecated `pyproto` feature, `#[pyproto]` macro, and all accompanying APIs. [#2587](https://github.com/PyO3/pyo3/pull/2587) - Remove all functionality deprecated in PyO3 0.16. [#2843](https://github.com/PyO3/pyo3/pull/2843) ### Fixed - Disable `PyModule::filename` on PyPy. [#2715](https://github.com/PyO3/pyo3/pull/2715) - `PyCodeObject` is now once again defined with fields on Python 3.7. [#2726](https://github.com/PyO3/pyo3/pull/2726) - Raise a `TypeError` if `#[new]` pymethods with no arguments receive arguments when called from Python. [#2749](https://github.com/PyO3/pyo3/pull/2749) - Use the `NOARGS` argument calling convention for methods that have a single `py: Python` argument (as a performance optimization). [#2760](https://github.com/PyO3/pyo3/pull/2760) - Fix truncation of `isize` values to `c_long` in `PySlice::new`. [#2769](https://github.com/PyO3/pyo3/pull/2769) - Fix soundness issue with FFI definition `PyUnicodeDecodeError_Create` on PyPy leading to indeterminate behavior (typically a `TypeError`). [#2772](https://github.com/PyO3/pyo3/pull/2772) - Allow functions taking `**kwargs` to accept keyword arguments which share a name with a positional-only argument (as permitted by PEP 570). [#2800](https://github.com/PyO3/pyo3/pull/2800) - Fix unresolved symbol for `PyObject_Vectorcall` on PyPy 3.9 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811) - Fix memory leak in `PyCFunction::new_closure`. [#2842](https://github.com/PyO3/pyo3/pull/2842) ## [0.17.3] - 2022-11-01 ### Packaging - Support Python 3.11. (Previous versions of PyO3 0.17 have been tested against Python 3.11 release candidates and are expected to be compatible, this is the first version tested against Python 3.11.0.) [#2708](https://github.com/PyO3/pyo3/pull/2708) ### Added - Implemented `ExactSizeIterator` for `PyListIterator`, `PyDictIterator`, `PySetIterator` and `PyFrozenSetIterator`. [#2676](https://github.com/PyO3/pyo3/pull/2676) ### Fixed - Fix regression of `impl FromPyObject for [T; N]` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since version 0.17.0. This the same fix that was applied `impl FromPyObject for Vec` in version 0.17.1 extended to fixed-size arrays. [#2675](https://github.com/PyO3/pyo3/pull/2675) - Fix UB in `FunctionDescription::extract_arguments_fastcall` due to creating slices from a null pointer. [#2687](https://github.com/PyO3/pyo3/pull/2687) ## [0.17.2] - 2022-10-04 ### Packaging - Added optional `chrono` feature to convert `chrono` types into types in the `datetime` module. [#2612](https://github.com/PyO3/pyo3/pull/2612) ### Added - Add support for `num-bigint` feature on `PyPy`. [#2626](https://github.com/PyO3/pyo3/pull/2626) ### Fixed - Correctly implement `__richcmp__` for enums, fixing `__ne__` returning always returning `True`. [#2622](https://github.com/PyO3/pyo3/pull/2622) - Fix compile error since 0.17.0 with `Option<&SomePyClass>` argument with a default. [#2630](https://github.com/PyO3/pyo3/pull/2630) - Fix regression of `impl FromPyObject for Vec` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since 0.17.0. [#2631](https://github.com/PyO3/pyo3/pull/2631) ## [0.17.1] - 2022-08-28 ### Fixed - Fix visibility of `PyDictItems`, `PyDictKeys`, and `PyDictValues` types added in PyO3 0.17.0. - Fix compile failure when using `#[pyo3(from_py_with = "...")]` attribute on an argument of type `Option`. [#2592](https://github.com/PyO3/pyo3/pull/2592) - Fix clippy `redundant-closure` lint on `**kwargs` arguments for `#[pyfunction]` and `#[pymethods]`. [#2595](https://github.com/PyO3/pyo3/pull/2595) ## [0.17.0] - 2022-08-23 ### Packaging - Update inventory dependency to `0.3` (the `multiple-pymethods` feature now requires Rust 1.62 for correctness). [#2492](https://github.com/PyO3/pyo3/pull/2492) ### Added - Add `timezone_utc`. [#1588](https://github.com/PyO3/pyo3/pull/1588) - Implement `ToPyObject` for `[T; N]`. [#2313](https://github.com/PyO3/pyo3/pull/2313) - Add `PyDictKeys`, `PyDictValues` and `PyDictItems` Rust types. [#2358](https://github.com/PyO3/pyo3/pull/2358) - Add `append_to_inittab`. [#2377](https://github.com/PyO3/pyo3/pull/2377) - Add FFI definition `PyFrame_GetCode`. [#2406](https://github.com/PyO3/pyo3/pull/2406) - Add `PyCode` and `PyFrame` high level objects. [#2408](https://github.com/PyO3/pyo3/pull/2408) - Add FFI definitions `Py_fstring_input`, `sendfunc`, and `_PyErr_StackItem`. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Add `PyDateTime::new_with_fold`, `PyTime::new_with_fold`, `PyTime::get_fold`, and `PyDateTime::get_fold` for PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Add `#[pyclass(frozen)]`. [#2448](https://github.com/PyO3/pyo3/pull/2448) - Accept `#[pyo3(name)]` on enum variants. [#2457](https://github.com/PyO3/pyo3/pull/2457) - Add `CompareOp::matches` to implement `__richcmp__` as the result of a Rust `std::cmp::Ordering` comparison. [#2460](https://github.com/PyO3/pyo3/pull/2460) - Add `PySuper` type. [#2486](https://github.com/PyO3/pyo3/pull/2486) - Support PyPy on Windows with the `generate-import-lib` feature. [#2506](https://github.com/PyO3/pyo3/pull/2506) - Add FFI definitions `Py_EnterRecursiveCall` and `Py_LeaveRecursiveCall`. [#2511](https://github.com/PyO3/pyo3/pull/2511) - Add `PyDict::get_item_with_error`. [#2536](https://github.com/PyO3/pyo3/pull/2536) - Add `#[pyclass(sequence)]` option. [#2567](https://github.com/PyO3/pyo3/pull/2567) ### Changed - Change datetime constructors taking a `tzinfo` to take `Option<&PyTzInfo>` instead of `Option<&PyObject>`: `PyDateTime::new`, `PyDateTime::new_with_fold`, `PyTime::new`, and `PyTime::new_with_fold`. [#1588](https://github.com/PyO3/pyo3/pull/1588) - Move `PyTypeObject::type_object` method to the `PyTypeInfo` trait, and deprecate the `PyTypeObject` trait. [#2287](https://github.com/PyO3/pyo3/pull/2287) - Methods of `Py` and `PyAny` now accept `impl IntoPy>` rather than just `&str` to allow use of the `intern!` macro. [#2312](https://github.com/PyO3/pyo3/pull/2312) - Change the deprecated `pyproto` feature to be opt-in instead of opt-out. [#2322](https://github.com/PyO3/pyo3/pull/2322) - Emit better error messages when `#[pyfunction]` return types do not implement `IntoPy`. [#2326](https://github.com/PyO3/pyo3/pull/2326) - Require `T: IntoPy` for `impl IntoPy for [T; N]` instead of `T: ToPyObject`. [#2326](https://github.com/PyO3/pyo3/pull/2326) - Deprecate the `ToBorrowedObject` trait. [#2333](https://github.com/PyO3/pyo3/pull/2333) - Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380) - Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380) - Allow `#[classattr]` methods to be fallible. [#2385](https://github.com/PyO3/pyo3/pull/2385) - Prevent multiple `#[pymethods]` with the same name for a single `#[pyclass]`. [#2399](https://github.com/PyO3/pyo3/pull/2399) - Fixup `lib_name` when using `PYO3_CONFIG_FILE`. [#2404](https://github.com/PyO3/pyo3/pull/2404) - Add a message to the `ValueError` raised by the `#[derive(FromPyObject)]` implementation for a tuple struct. [#2414](https://github.com/PyO3/pyo3/pull/2414) - Allow `#[classattr]` methods to take `Python` argument. [#2456](https://github.com/PyO3/pyo3/pull/2456) - Rework `PyCapsule` type to resolve soundness issues: [#2485](https://github.com/PyO3/pyo3/pull/2485) - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take `name: Option` instead of `&CStr`. - The destructor `F` in `PyCapsule::new_with_destructor` must now be `Send`. - `PyCapsule::get_context` deprecated in favor of `PyCapsule::context` which doesn't take a `py: Python<'_>` argument. - `PyCapsule::set_context` no longer takes a `py: Python<'_>` argument. - `PyCapsule::name` now returns `PyResult>` instead of `&CStr`. - `FromPyObject::extract` for `Vec` no longer accepts Python `str` inputs. [#2500](https://github.com/PyO3/pyo3/pull/2500) - Ensure each `#[pymodule]` is only initialized once. [#2523](https://github.com/PyO3/pyo3/pull/2523) - `pyo3_build_config::add_extension_module_link_args` now also emits linker arguments for `wasm32-unknown-emscripten`. [#2538](https://github.com/PyO3/pyo3/pull/2538) - Type checks for `PySequence` and `PyMapping` now require inputs to inherit from (or register with) `collections.abc.Sequence` and `collections.abc.Mapping` respectively. [#2477](https://github.com/PyO3/pyo3/pull/2477) - Disable `PyFunction` on when building for abi3 or PyPy. [#2542](https://github.com/PyO3/pyo3/pull/2542) - Deprecate `Python::acquire_gil`. [#2549](https://github.com/PyO3/pyo3/pull/2549) ### Removed - Remove all functionality deprecated in PyO3 0.15. [#2283](https://github.com/PyO3/pyo3/pull/2283) - Make the `Dict`, `WeakRef` and `BaseNativeType` members of the `PyClass` private implementation details. [#2572](https://github.com/PyO3/pyo3/pull/2572) ### Fixed - Enable incorrectly disabled FFI definition `PyThreadState_DeleteCurrent`. [#2357](https://github.com/PyO3/pyo3/pull/2357) - Fix `wrap_pymodule` interactions with name resolution rules: it no longer "sees through" glob imports of `use submodule::*` when `submodule::submodule` is a `#[pymodule]`. [#2363](https://github.com/PyO3/pyo3/pull/2363) - Correct FFI definition `PyEval_EvalCodeEx` to take `*const *mut PyObject` array arguments instead of `*mut *mut PyObject`. [#2368](https://github.com/PyO3/pyo3/pull/2368) - Fix "raw-ident" structs (e.g. `#[pyclass] struct r#RawName`) incorrectly having `r#` at the start of the class name created in Python. [#2395](https://github.com/PyO3/pyo3/pull/2395) - Correct FFI definition `Py_tracefunc` to be `unsafe extern "C" fn` (was previously safe). [#2407](https://github.com/PyO3/pyo3/pull/2407) - Fix compile failure with `#[pyo3(from_py_with = "...")]` annotations on a field in a `#[derive(FromPyObject)]` struct. [#2414](https://github.com/PyO3/pyo3/pull/2414) - Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` lacking leading underscores in their names. [#2421](https://github.com/PyO3/pyo3/pull/2421) - Remove FFI definition `PyArena` on Python 3.10 and up. [#2421](https://github.com/PyO3/pyo3/pull/2421) - Fix FFI definition `PyCompilerFlags` missing member `cf_feature_version` on Python 3.8 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyAsyncMethods` missing member `am_send` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyGenObject` having multiple incorrect members on various Python versions. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PySyntaxErrorObject` missing members `end_lineno` and `end_offset` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyHeapTypeObject` missing member `ht_module` on Python 3.9 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423) - Fix FFI definition `PyFrameObject` having multiple incorrect members on various Python versions. [#2424](https://github.com/PyO3/pyo3/pull/2424) [#2434](https://github.com/PyO3/pyo3/pull/2434) - Fix FFI definition `PyTypeObject` missing deprecated field `tp_print` on Python 3.8. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Fix FFI definitions `PyDateTime_CAPI`. `PyDateTime_Date`, `PyASCIIObject`, `PyBaseExceptionObject`, `PyListObject`, and `PyTypeObject` on PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428) - Fix FFI definition `_inittab` field `initfunc` typo'd as `initfun`. [#2431](https://github.com/PyO3/pyo3/pull/2431) - Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` incorrectly having `fold` member. [#2432](https://github.com/PyO3/pyo3/pull/2432) - Fix FFI definitions `PyTypeObject`. `PyHeapTypeObject`, and `PyCFunctionObject` having incorrect members on PyPy 3.9. [#2433](https://github.com/PyO3/pyo3/pull/2433) - Fix FFI definition `PyGetSetDef` to have `*const c_char` for `doc` member (not `*mut c_char`). [#2439](https://github.com/PyO3/pyo3/pull/2439) - Fix `#[pyo3(from_py_with = "...")]` being ignored for 1-element tuple structs and transparent structs. [#2440](https://github.com/PyO3/pyo3/pull/2440) - Use `memoffset` to avoid UB when computing `PyCell` layout. [#2450](https://github.com/PyO3/pyo3/pull/2450) - Fix incorrect enum names being returned by the generated `repr` for enums renamed by `#[pyclass(name = "...")]` [#2457](https://github.com/PyO3/pyo3/pull/2457) - Fix `PyObject_CallNoArgs` incorrectly being available when building for abi3 on Python 3.9. [#2476](https://github.com/PyO3/pyo3/pull/2476) - Fix several clippy warnings generated by `#[pyfunction]` arguments. [#2503](https://github.com/PyO3/pyo3/pull/2503) ## [0.16.6] - 2022-08-23 ### Changed - Fix soundness issues with `PyCapsule` type with select workarounds. Users are encourage to upgrade to PyO3 0.17 at their earliest convenience which contains API breakages which fix the issues in a long-term fashion. [#2522](https://github.com/PyO3/pyo3/pull/2522) - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take ownership of a copy of the `name` to resolve a possible use-after-free. - `PyCapsule::name` now returns an empty `CStr` instead of dereferencing a null pointer if the capsule has no name. - The destructor `F` in `PyCapsule::new_with_destructor` will never be called if the capsule is deleted from a thread other than the one which the capsule was created in (a warning will be emitted). - Panics during drop of panic payload caught by PyO3 will now abort. [#2544](https://github.com/PyO3/pyo3/pull/2544) ## [0.16.5] - 2022-05-15 ### Added - Add an experimental `generate-import-lib` feature to support auto-generating non-abi3 python import libraries for Windows targets. [#2364](https://github.com/PyO3/pyo3/pull/2364) - Add FFI definition `Py_ExitStatusException`. [#2374](https://github.com/PyO3/pyo3/pull/2374) ### Changed - Deprecate experimental `generate-abi3-import-lib` feature in favor of the new `generate-import-lib` feature. [#2364](https://github.com/PyO3/pyo3/pull/2364) ### Fixed - Added missing `warn_default_encoding` field to `PyConfig` on 3.10+. The previously missing field could result in incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370) - Fixed order of `pathconfig_warnings` and `program_name` fields of `PyConfig` on 3.10+. Previously, the order of the fields was swapped and this could lead to incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370) ## [0.16.4] - 2022-04-14 ### Added - Add `PyTzInfoAccess` trait for safe access to time zone information. [#2263](https://github.com/PyO3/pyo3/pull/2263) - Add an experimental `generate-abi3-import-lib` feature to auto-generate `python3.dll` import libraries for Windows. [#2282](https://github.com/PyO3/pyo3/pull/2282) - Add FFI definitions for `PyDateTime_BaseTime` and `PyDateTime_BaseDateTime`. [#2294](https://github.com/PyO3/pyo3/pull/2294) ### Changed - Improved performance of failing calls to `FromPyObject::extract` which is common when functions accept multiple distinct types. [#2279](https://github.com/PyO3/pyo3/pull/2279) - Default to "m" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288) - Allow to compile "abi3" extensions without a working build host Python interpreter. [#2293](https://github.com/PyO3/pyo3/pull/2293) ### Fixed - Crates depending on PyO3 can collect code coverage via LLVM instrumentation using stable Rust. [#2286](https://github.com/PyO3/pyo3/pull/2286) - Fix segfault when calling FFI methods `PyDateTime_DATE_GET_TZINFO` or `PyDateTime_TIME_GET_TZINFO` on `datetime` or `time` without a tzinfo. [#2289](https://github.com/PyO3/pyo3/pull/2289) - Fix directory names starting with the letter `n` breaking serialization of the interpreter configuration on Windows since PyO3 0.16.3. [#2299](https://github.com/PyO3/pyo3/pull/2299) ## [0.16.3] - 2022-04-05 ### Packaging - Extend `parking_lot` dependency supported versions to include 0.12. [#2239](https://github.com/PyO3/pyo3/pull/2239) ### Added - Add methods to `pyo3_build_config::InterpreterConfig` to run Python scripts using the configured executable. [#2092](https://github.com/PyO3/pyo3/pull/2092) - Add `as_bytes` method to `Py`. [#2235](https://github.com/PyO3/pyo3/pull/2235) - Add FFI definitions for `PyType_FromModuleAndSpec`, `PyType_GetModule`, `PyType_GetModuleState` and `PyModule_AddType`. [#2250](https://github.com/PyO3/pyo3/pull/2250) - Add `pyo3_build_config::cross_compiling_from_to` as a helper to detect when PyO3 is cross-compiling. [#2253](https://github.com/PyO3/pyo3/pull/2253) - Add `#[pyclass(mapping)]` option to leave sequence slots empty in container implementations. [#2265](https://github.com/PyO3/pyo3/pull/2265) - Add `PyString::intern` to enable usage of the Python's built-in string interning. [#2268](https://github.com/PyO3/pyo3/pull/2268) - Add `intern!` macro which can be used to amortize the cost of creating Python strings by storing them inside a `GILOnceCell`. [#2269](https://github.com/PyO3/pyo3/pull/2269) - Add `PYO3_CROSS_PYTHON_IMPLEMENTATION` environment variable for selecting the default cross Python implementation. [#2272](https://github.com/PyO3/pyo3/pull/2272) ### Changed - Allow `#[pyo3(crate = "...", text_signature = "...")]` options to be used directly in `#[pyclass(crate = "...", text_signature = "...")]`. [#2234](https://github.com/PyO3/pyo3/pull/2234) - Make `PYO3_CROSS_LIB_DIR` environment variable optional when cross compiling. [#2241](https://github.com/PyO3/pyo3/pull/2241) - Mark `METH_FASTCALL` calling convention as limited API on Python 3.10. [#2250](https://github.com/PyO3/pyo3/pull/2250) - Deprecate `pyo3_build_config::cross_compiling` in favor of `pyo3_build_config::cross_compiling_from_to`. [#2253](https://github.com/PyO3/pyo3/pull/2253) ### Fixed - Fix `abi3-py310` feature: use Python 3.10 ABI when available instead of silently falling back to the 3.9 ABI. [#2242](https://github.com/PyO3/pyo3/pull/2242) - Use shared linking mode when cross compiling against a [Framework bundle](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html) for macOS. [#2233](https://github.com/PyO3/pyo3/pull/2233) - Fix panic during compilation when `PYO3_CROSS_LIB_DIR` is set for some host/target combinations. [#2232](https://github.com/PyO3/pyo3/pull/2232) - Correct dependency version for `syn` to require minimal patch version 1.0.56. [#2240](https://github.com/PyO3/pyo3/pull/2240) ## [0.16.2] - 2022-03-15 ### Packaging - Warn when modules are imported on PyPy 3.7 versions older than PyPy 7.3.8, as they are known to have binary compatibility issues. [#2217](https://github.com/PyO3/pyo3/pull/2217) - Ensure build script of `pyo3-ffi` runs before that of `pyo3` to fix cross compilation. [#2224](https://github.com/PyO3/pyo3/pull/2224) ## [0.16.1] - 2022-03-05 ### Packaging - Extend `hashbrown` optional dependency supported versions to include 0.12. [#2197](https://github.com/PyO3/pyo3/pull/2197) ### Fixed - Fix incorrect platform detection for Windows in `pyo3-build-config`. [#2198](https://github.com/PyO3/pyo3/pull/2198) - Fix regression from 0.16 preventing cross compiling to aarch64 macOS. [#2201](https://github.com/PyO3/pyo3/pull/2201) ## [0.16.0] - 2022-02-27 ### Packaging - Update MSRV to Rust 1.48. [#2004](https://github.com/PyO3/pyo3/pull/2004) - Update `indoc` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004) - Drop support for Python 3.6, remove `abi3-py36` feature. [#2006](https://github.com/PyO3/pyo3/pull/2006) - `pyo3-build-config` no longer enables the `resolve-config` feature by default. [#2008](https://github.com/PyO3/pyo3/pull/2008) - Update `inventory` optional dependency to 0.2. [#2019](https://github.com/PyO3/pyo3/pull/2019) - Drop `paste` dependency. [#2081](https://github.com/PyO3/pyo3/pull/2081) - The bindings found in `pyo3::ffi` are now a re-export of a separate `pyo3-ffi` crate. [#2126](https://github.com/PyO3/pyo3/pull/2126) - Support PyPy 3.9. [#2143](https://github.com/PyO3/pyo3/pull/2143) ### Added - Add `PyCapsule` type exposing the [Capsule API](https://docs.python.org/3/c-api/capsule.html#capsules). [#1980](https://github.com/PyO3/pyo3/pull/1980) - Add `pyo3_build_config::Sysconfigdata` and supporting APIs. [#1996](https://github.com/PyO3/pyo3/pull/1996) - Add `Py::setattr` method. [#2009](https://github.com/PyO3/pyo3/pull/2009) - Add `#[pyo3(crate = "some::path")]` option to all attribute macros (except the deprecated `#[pyproto]`). [#2022](https://github.com/PyO3/pyo3/pull/2022) - Enable `create_exception!` macro to take an optional docstring. [#2027](https://github.com/PyO3/pyo3/pull/2027) - Enable `#[pyclass]` for fieldless (aka C-like) enums. [#2034](https://github.com/PyO3/pyo3/pull/2034) - Add buffer magic methods `__getbuffer__` and `__releasebuffer__` to `#[pymethods]`. [#2067](https://github.com/PyO3/pyo3/pull/2067) - Add support for paths in `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Enable `wrap_pyfunction!` to wrap a `#[pyfunction]` implemented in a different Rust module or crate. [#2091](https://github.com/PyO3/pyo3/pull/2091) - Add `PyAny::contains` method (`in` operator for `PyAny`). [#2115](https://github.com/PyO3/pyo3/pull/2115) - Add `PyMapping::contains` method (`in` operator for `PyMapping`). [#2133](https://github.com/PyO3/pyo3/pull/2133) - Add garbage collection magic magic methods `__traverse__` and `__clear__` to `#[pymethods]`. [#2159](https://github.com/PyO3/pyo3/pull/2159) - Add support for `from_py_with` on struct tuples and enums to override the default from-Python conversion. [#2181](https://github.com/PyO3/pyo3/pull/2181) - Add `eq`, `ne`, `lt`, `le`, `gt`, `ge` methods to `PyAny` that wrap `rich_compare`. [#2175](https://github.com/PyO3/pyo3/pull/2175) - Add `Py::is` and `PyAny::is` methods to check for object identity. [#2183](https://github.com/PyO3/pyo3/pull/2183) - Add support for the `__getattribute__` magic method. [#2187](https://github.com/PyO3/pyo3/pull/2187) ### Changed - `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now operate run-time type object instead of a type known at compile-time. The old behavior is still available as `PyType::is_subclass_of`, `PyErr::is_instance_of` and `PyAny::is_instance_of`. [#1985](https://github.com/PyO3/pyo3/pull/1985) - Rename some methods on `PyErr` (the old names are just marked deprecated for now): [#2026](https://github.com/PyO3/pyo3/pull/2026) - `pytype` -> `get_type` - `pvalue` -> `value` (and deprecate equivalent `instance`) - `ptraceback` -> `traceback` - `from_instance` -> `from_value` - `into_instance` -> `into_value` - `PyErr::new_type` now takes an optional docstring and now returns `PyResult>` rather than a `ffi::PyTypeObject` pointer. [#2027](https://github.com/PyO3/pyo3/pull/2027) - Deprecate `PyType::is_instance`; it is inconsistent with other `is_instance` methods in PyO3. Instead of `typ.is_instance(obj)`, use `obj.is_instance(typ)`. [#2031](https://github.com/PyO3/pyo3/pull/2031) - `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` now implement both a Python mapping and sequence by default. [#2065](https://github.com/PyO3/pyo3/pull/2065) - Improve performance and error messages for `#[derive(FromPyObject)]` for enums. [#2068](https://github.com/PyO3/pyo3/pull/2068) - Reduce generated LLVM code size (to improve compile times) for: - internal `handle_panic` helper [#2074](https://github.com/PyO3/pyo3/pull/2074) [#2158](https://github.com/PyO3/pyo3/pull/2158) - `#[pyfunction]` and `#[pymethods]` argument extraction [#2075](https://github.com/PyO3/pyo3/pull/2075) [#2085](https://github.com/PyO3/pyo3/pull/2085) - `#[pyclass]` type object creation [#2076](https://github.com/PyO3/pyo3/pull/2076) [#2081](https://github.com/PyO3/pyo3/pull/2081) [#2157](https://github.com/PyO3/pyo3/pull/2157) - Respect Rust privacy rules for items wrapped with `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Add modulo argument to `__ipow__` magic method. [#2083](https://github.com/PyO3/pyo3/pull/2083) - Fix FFI definition for `_PyCFunctionFast`. [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTimeAPI` and `PyDateTime_TimeZone_UTC` are now unsafe functions instead of statics. [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTimeAPI` does not implicitly call `PyDateTime_IMPORT` anymore to reflect the original Python API more closely. Before the first call to `PyDateTime_IMPORT` a null pointer is returned. Therefore before calling any of the following FFI functions `PyDateTime_IMPORT` must be called to avoid undefined behavior: [#2126](https://github.com/PyO3/pyo3/pull/2126) - `PyDateTime_TimeZone_UTC` - `PyDate_Check` - `PyDate_CheckExact` - `PyDateTime_Check` - `PyDateTime_CheckExact` - `PyTime_Check` - `PyTime_CheckExact` - `PyDelta_Check` - `PyDelta_CheckExact` - `PyTZInfo_Check` - `PyTZInfo_CheckExact` - `PyDateTime_FromTimestamp` - `PyDate_FromTimestamp` - Deprecate the `gc` option for `pyclass` (e.g. `#[pyclass(gc)]`). Just implement a `__traverse__` `#[pymethod]`. [#2159](https://github.com/PyO3/pyo3/pull/2159) - The `ml_meth` field of `PyMethodDef` is now represented by the `PyMethodDefPointer` union. [2166](https://github.com/PyO3/pyo3/pull/2166) - Deprecate the `#[pyproto]` traits. [#2173](https://github.com/PyO3/pyo3/pull/2173) ### Removed - Remove all functionality deprecated in PyO3 0.14. [#2007](https://github.com/PyO3/pyo3/pull/2007) - Remove `Default` impl for `PyMethodDef`. [#2166](https://github.com/PyO3/pyo3/pull/2166) - Remove `PartialEq` impl for `Py` and `PyAny` (use the new `is` instead). [#2183](https://github.com/PyO3/pyo3/pull/2183) ### Fixed - Fix undefined symbol for `PyObject_HasAttr` on PyPy. [#2025](https://github.com/PyO3/pyo3/pull/2025) - Fix memory leak in `PyErr::into_value`. [#2026](https://github.com/PyO3/pyo3/pull/2026) - Fix clippy warning `needless-option-as-deref` in code generated by `#[pyfunction]` and `#[pymethods]`. [#2040](https://github.com/PyO3/pyo3/pull/2040) - Fix undefined behavior in `PySlice::indices`. [#2061](https://github.com/PyO3/pyo3/pull/2061) - Fix the `wrap_pymodule!` macro using the wrong name for a `#[pymodule]` with a `#[pyo3(name = "..")]` attribute. [#2081](https://github.com/PyO3/pyo3/pull/2081) - Fix magic methods in `#[pymethods]` accepting implementations with the wrong number of arguments. [#2083](https://github.com/PyO3/pyo3/pull/2083) - Fix panic in `#[pyfunction]` generated code when a required argument following an `Option` was not provided. [#2093](https://github.com/PyO3/pyo3/pull/2093) - Fixed undefined behavior caused by incorrect `ExactSizeIterator` implementations. [#2124](https://github.com/PyO3/pyo3/pull/2124) - Fix missing FFI definition `PyCMethod_New` on Python 3.9 and up. [#2143](https://github.com/PyO3/pyo3/pull/2143) - Add missing FFI definitions `_PyLong_NumBits` and `_PyLong_AsByteArray` on PyPy. [#2146](https://github.com/PyO3/pyo3/pull/2146) - Fix memory leak in implementation of `AsPyPointer` for `Option`. [#2160](https://github.com/PyO3/pyo3/pull/2160) - Fix FFI definition of `_PyLong_NumBits` to return `size_t` instead of `c_int`. [#2161](https://github.com/PyO3/pyo3/pull/2161) - Fix `TypeError` thrown when argument parsing failed missing the originating causes. [2177](https://github.com/PyO3/pyo3/pull/2178) ## [0.15.2] - 2022-04-14 ### Packaging - Backport of PyPy 3.9 support from PyO3 0.16. [#2262](https://github.com/PyO3/pyo3/pull/2262) ## [0.15.1] - 2021-11-19 ### Added - Add implementations for `Py::as_ref` and `Py::into_ref` for `Py`, `Py` and `Py`. [#1682](https://github.com/PyO3/pyo3/pull/1682) - Add `PyTraceback` type to represent and format Python tracebacks. [#1977](https://github.com/PyO3/pyo3/pull/1977) ### Changed - `#[classattr]` constants with a known magic method name (which is lowercase) no longer trigger lint warnings expecting constants to be uppercase. [#1969](https://github.com/PyO3/pyo3/pull/1969) ### Fixed - Fix creating `#[classattr]` by functions with the name of a known magic method. [#1969](https://github.com/PyO3/pyo3/pull/1969) - Fix use of `catch_unwind` in `allow_threads` which can cause fatal crashes. [#1989](https://github.com/PyO3/pyo3/pull/1989) - Fix build failure on PyPy when abi3 features are activated. [#1991](https://github.com/PyO3/pyo3/pull/1991) - Fix mingw platform detection. [#1993](https://github.com/PyO3/pyo3/pull/1993) - Fix panic in `__get__` implementation when accessing descriptor on type object. [#1997](https://github.com/PyO3/pyo3/pull/1997) ## [0.15.0] - 2021-11-03 ### Packaging - `pyo3`'s `Cargo.toml` now advertises `links = "python"` to inform Cargo that it links against *libpython*. [#1819](https://github.com/PyO3/pyo3/pull/1819) - Added optional `anyhow` feature to convert `anyhow::Error` into `PyErr`. [#1822](https://github.com/PyO3/pyo3/pull/1822) - Support Python 3.10. [#1889](https://github.com/PyO3/pyo3/pull/1889) - Added optional `eyre` feature to convert `eyre::Report` into `PyErr`. [#1893](https://github.com/PyO3/pyo3/pull/1893) - Support PyPy 3.8. [#1948](https://github.com/PyO3/pyo3/pull/1948) ### Added - Add `PyList::get_item_unchecked` and `PyTuple::get_item_unchecked` to get items without bounds checks. [#1733](https://github.com/PyO3/pyo3/pull/1733) - Support `#[doc = include_str!(...)]` attributes on Rust 1.54 and up. [#1746](https://github.com/PyO3/pyo3/issues/1746) - Add `PyAny::py` as a convenience for `PyNativeType::py`. [#1751](https://github.com/PyO3/pyo3/pull/1751) - Add implementation of `std::ops::Index` for `PyList`, `PyTuple` and `PySequence`. [#1825](https://github.com/PyO3/pyo3/pull/1825) - Add range indexing implementations of `std::ops::Index` for `PyList`, `PyTuple` and `PySequence`. [#1829](https://github.com/PyO3/pyo3/pull/1829) - Add `PyMapping` type to represent the Python mapping protocol. [#1844](https://github.com/PyO3/pyo3/pull/1844) - Add commonly-used sequence methods to `PyList` and `PyTuple`. [#1849](https://github.com/PyO3/pyo3/pull/1849) - Add `as_sequence` methods to `PyList` and `PyTuple`. [#1860](https://github.com/PyO3/pyo3/pull/1860) - Add support for magic methods in `#[pymethods]`, intended as a replacement for `#[pyproto]`. [#1864](https://github.com/PyO3/pyo3/pull/1864) - Add `abi3-py310` feature. [#1889](https://github.com/PyO3/pyo3/pull/1889) - Add `PyCFunction::new_closure` to create a Python function from a Rust closure. [#1901](https://github.com/PyO3/pyo3/pull/1901) - Add support for positional-only arguments in `#[pyfunction]`. [#1925](https://github.com/PyO3/pyo3/pull/1925) - Add `PyErr::take` to attempt to fetch a Python exception if present. [#1957](https://github.com/PyO3/pyo3/pull/1957) ### Changed - `PyList`, `PyTuple` and `PySequence`'s APIs now accepts only `usize` indices instead of `isize`. [#1733](https://github.com/PyO3/pyo3/pull/1733), [#1802](https://github.com/PyO3/pyo3/pull/1802), [#1803](https://github.com/PyO3/pyo3/pull/1803) - `PyList::get_item` and `PyTuple::get_item` now return `PyResult<&PyAny>` instead of panicking. [#1733](https://github.com/PyO3/pyo3/pull/1733) - `PySequence::in_place_repeat` and `PySequence::in_place_concat` now return `PyResult<&PySequence>` instead of `PyResult<()>`, which is needed in case of immutable sequences such as tuples. [#1803](https://github.com/PyO3/pyo3/pull/1803) - `PySequence::get_slice` now returns `PyResult<&PySequence>` instead of `PyResult<&PyAny>`. [#1829](https://github.com/PyO3/pyo3/pull/1829) - Deprecate `PyTuple::split_from`. [#1804](https://github.com/PyO3/pyo3/pull/1804) - Deprecate `PyTuple::slice`, new method `PyTuple::get_slice` added with `usize` indices. [#1828](https://github.com/PyO3/pyo3/pull/1828) - Deprecate FFI definitions `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags` when building for Python 3.9. [#1830](https://github.com/PyO3/pyo3/pull/1830) - Mark FFI definitions removed in Python 3.10 `PyParser_ASTFromString`, `PyParser_ASTFromStringObject`, `PyParser_ASTFromFile`, `PyParser_ASTFromFileObject`, `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags`, `PyParser_SimpleParseString`, `PyParser_SimpleParseFile`, `Py_SymtableString`, and `Py_SymtableStringObject`. [#1830](https://github.com/PyO3/pyo3/pull/1830) - `#[pymethods]` now handles magic methods similarly to `#[pyproto]`. In the future, `#[pyproto]` may be deprecated. [#1864](https://github.com/PyO3/pyo3/pull/1864) - Deprecate FFI definitions `PySys_AddWarnOption`, `PySys_AddWarnOptionUnicode` and `PySys_HasWarnOptions`. [#1887](https://github.com/PyO3/pyo3/pull/1887) - Deprecate `#[call]` attribute in favor of using `fn __call__`. [#1929](https://github.com/PyO3/pyo3/pull/1929) - Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942) - Change `PyErr::fetch` to panic in debug mode if no exception is present. [#1957](https://github.com/PyO3/pyo3/pull/1957) ### Fixed - Fix building with a conda environment on Windows. [#1873](https://github.com/PyO3/pyo3/pull/1873) - Fix panic on Python 3.6 when calling `Python::with_gil` with Python initialized but threading not initialized. [#1874](https://github.com/PyO3/pyo3/pull/1874) - Fix incorrect linking to version-specific DLL instead of `python3.dll` when cross-compiling to Windows with `abi3`. [#1880](https://github.com/PyO3/pyo3/pull/1880) - Fix FFI definition for `PyTuple_ClearFreeList` incorrectly being present for Python 3.9 and up. [#1887](https://github.com/PyO3/pyo3/pull/1887) - Fix panic in generated `#[derive(FromPyObject)]` for enums. [#1888](https://github.com/PyO3/pyo3/pull/1888) - Fix cross-compiling to Python 3.7 builds with the "m" abi flag. [#1908](https://github.com/PyO3/pyo3/pull/1908) - Fix `__mod__` magic method fallback to `__rmod__`. [#1934](https://github.com/PyO3/pyo3/pull/1934). - Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942) ## [0.14.5] - 2021-09-05 ### Added - Make `pyo3_build_config::InterpreterConfig` and subfields public. [#1848](https://github.com/PyO3/pyo3/pull/1848) - Add `resolve-config` feature to the `pyo3-build-config` to control whether its build script does anything. [#1856](https://github.com/PyO3/pyo3/pull/1856) ### Fixed - Fix 0.14.4 compile regression on `s390x-unknown-linux-gnu` target. [#1850](https://github.com/PyO3/pyo3/pull/1850) ## [0.14.4] - 2021-08-29 ### Changed - Mark `PyString::data` as `unsafe` and disable it and some supporting PyUnicode FFI APIs (which depend on a C bitfield) on big-endian targets. [#1834](https://github.com/PyO3/pyo3/pull/1834) ## [0.14.3] - 2021-08-22 ### Added - Add `PyString::data` to access the raw bytes stored in a Python string. [#1794](https://github.com/PyO3/pyo3/pull/1794) ### Fixed - Raise `AttributeError` to avoid panic when calling `del` on a `#[setter]` defined class property. [#1779](https://github.com/PyO3/pyo3/pull/1779) - Restrict FFI definitions `PyGILState_Check` and `Py_tracefunc` to the unlimited API. [#1787](https://github.com/PyO3/pyo3/pull/1787) - Add missing `_type` field to `PyStatus` struct definition. [#1791](https://github.com/PyO3/pyo3/pull/1791) - Reduce lower bound `num-complex` optional dependency to support interop with `rust-numpy` and `ndarray` when building with the MSRV of 1.41 [#1799](https://github.com/PyO3/pyo3/pull/1799) - Fix memory leak in `Python::run_code`. [#1806](https://github.com/PyO3/pyo3/pull/1806) - Fix memory leak in `PyModule::from_code`. [#1810](https://github.com/PyO3/pyo3/pull/1810) - Remove use of `pyo3::` in `pyo3::types::datetime` which broke builds using `-Z avoid-dev-deps` [#1811](https://github.com/PyO3/pyo3/pull/1811) ## [0.14.2] - 2021-08-09 ### Added - Add `indexmap` feature to add `ToPyObject`, `IntoPy` and `FromPyObject` implementations for `indexmap::IndexMap`. [#1728](https://github.com/PyO3/pyo3/pull/1728) - Add `pyo3_build_config::add_extension_module_link_args` to use in build scripts to set linker arguments (for macOS). [#1755](https://github.com/PyO3/pyo3/pull/1755) - Add `Python::with_gil_unchecked` unsafe variation of `Python::with_gil` to allow obtaining a `Python` in scenarios where `Python::with_gil` would fail. [#1769](https://github.com/PyO3/pyo3/pull/1769) ### Changed - `PyErr::new` no longer acquires the Python GIL internally. [#1724](https://github.com/PyO3/pyo3/pull/1724) - Reverted PyO3 0.14.0's use of `cargo:rustc-cdylib-link-arg` in its build script, as Cargo unintentionally allowed crates to pass linker args to downstream crates in this way. Projects supporting macOS may need to restore `.cargo/config.toml` files. [#1755](https://github.com/PyO3/pyo3/pull/1755) ### Fixed - Fix regression in 0.14.0 rejecting usage of `#[doc(hidden)]` on structs and functions annotated with PyO3 macros. [#1722](https://github.com/PyO3/pyo3/pull/1722) - Fix regression in 0.14.0 leading to incorrect code coverage being computed for `#[pyfunction]`s. [#1726](https://github.com/PyO3/pyo3/pull/1726) - Fix incorrect FFI definition of `Py_Buffer` on PyPy. [#1737](https://github.com/PyO3/pyo3/pull/1737) - Fix incorrect calculation of `dictoffset` on 32-bit Windows. [#1475](https://github.com/PyO3/pyo3/pull/1475) - Fix regression in 0.13.2 leading to linking to incorrect Python library on Windows "gnu" targets. [#1759](https://github.com/PyO3/pyo3/pull/1759) - Fix compiler warning: deny trailing semicolons in expression macro. [#1762](https://github.com/PyO3/pyo3/pull/1762) - Fix incorrect FFI definition of `Py_DecodeLocale`. The 2nd argument is now `*mut Py_ssize_t` instead of `Py_ssize_t`. [#1766](https://github.com/PyO3/pyo3/pull/1766) ## [0.14.1] - 2021-07-04 ### Added - Implement `IntoPy` for `&PathBuf` and `&OsString`. [#1712](https://github.com/PyO3/pyo3/pull/1712) ### Fixed - Fix crashes on PyPy due to incorrect definitions of `PyList_SET_ITEM`. [#1713](https://github.com/PyO3/pyo3/pull/1713) ## [0.14.0] - 2021-07-03 ### Packaging - Update `num-bigint` optional dependency to 0.4. [#1481](https://github.com/PyO3/pyo3/pull/1481) - Update `num-complex` optional dependency to 0.4. [#1482](https://github.com/PyO3/pyo3/pull/1482) - Extend `hashbrown` optional dependency supported versions to include 0.11. [#1496](https://github.com/PyO3/pyo3/pull/1496) - Support PyPy 3.7. [#1538](https://github.com/PyO3/pyo3/pull/1538) ### Added - Extend conversions for `[T; N]` to all `N` using const generics (on Rust 1.51 and up). [#1128](https://github.com/PyO3/pyo3/pull/1128) - Add conversions between `OsStr`/ `OsString` and Python strings. [#1379](https://github.com/PyO3/pyo3/pull/1379) - Add conversions between `Path`/ `PathBuf` and Python strings (and `pathlib.Path` objects). [#1379](https://github.com/PyO3/pyo3/pull/1379) [#1654](https://github.com/PyO3/pyo3/pull/1654) - Add a new set of `#[pyo3(...)]` attributes to control various PyO3 macro functionality: - `#[pyo3(from_py_with = "...")]` function arguments and struct fields to override the default from-Python conversion. [#1411](https://github.com/PyO3/pyo3/pull/1411) - `#[pyo3(name = "...")]` for setting Python names. [#1567](https://github.com/PyO3/pyo3/pull/1567) - `#[pyo3(text_signature = "...")]` for setting text signature. [#1658](https://github.com/PyO3/pyo3/pull/1658) - Add FFI definition `PyCFunction_CheckExact` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425) - Add FFI definition `Py_IS_TYPE`. [#1429](https://github.com/PyO3/pyo3/pull/1429) - Add FFI definition `_Py_InitializeMain`. [#1473](https://github.com/PyO3/pyo3/pull/1473) - Add FFI definitions from `cpython/import.h`.[#1475](https://github.com/PyO3/pyo3/pull/1475) - Add tuple and unit struct support for `#[pyclass]` macro. [#1504](https://github.com/PyO3/pyo3/pull/1504) - Add FFI definition `PyDateTime_TimeZone_UTC`. [#1572](https://github.com/PyO3/pyo3/pull/1572) - Add support for `#[pyclass(extends=Exception)]`. [#1591](https://github.com/PyO3/pyo3/pull/1591) - Add `PyErr::cause` and `PyErr::set_cause`. [#1679](https://github.com/PyO3/pyo3/pull/1679) - Add FFI definitions from `cpython/pystate.h`. [#1687](https://github.com/PyO3/pyo3/pull/1687/) - Add `wrap_pyfunction!` macro to `pyo3::prelude`. [#1695](https://github.com/PyO3/pyo3/pull/1695) ### Changed - Allow only one `#[pymethods]` block per `#[pyclass]` by default, to remove the dependency on `inventory`. Add a `multiple-pymethods` feature to opt-in the original behavior and dependency on `inventory`. [#1457](https://github.com/PyO3/pyo3/pull/1457) - Change `PyTimeAccess::get_fold` to return a `bool` instead of a `u8`. [#1397](https://github.com/PyO3/pyo3/pull/1397) - Deprecate FFI definition `PyCFunction_Call` for Python 3.9 and up. [#1425](https://github.com/PyO3/pyo3/pull/1425) - Deprecate FFI definition `PyModule_GetFilename`. [#1425](https://github.com/PyO3/pyo3/pull/1425) - The `auto-initialize` feature is no longer enabled by default. [#1443](https://github.com/PyO3/pyo3/pull/1443) - Change `PyCFunction::new` and `PyCFunction::new_with_keywords` to take `&'static str` arguments rather than implicitly copying (and leaking) them. [#1450](https://github.com/PyO3/pyo3/pull/1450) - Deprecate `PyModule::call`, `PyModule::call0`, `PyModule::call1` and `PyModule::get`. [#1492](https://github.com/PyO3/pyo3/pull/1492) - Add length information to `PyBufferError`s raised from `PyBuffer::copy_to_slice` and `PyBuffer::copy_from_slice`. [#1534](https://github.com/PyO3/pyo3/pull/1534) - Automatically set `-undefined` and `dynamic_lookup` linker arguments on macOS with the `extension-module` feature. [#1539](https://github.com/PyO3/pyo3/pull/1539) - Deprecate `#[pyproto]` methods which are easier to implement as `#[pymethods]`: [#1560](https://github.com/PyO3/pyo3/pull/1560) - `PyBasicProtocol::__bytes__` and `PyBasicProtocol::__format__` - `PyContextProtocol::__enter__` and `PyContextProtocol::__exit__` - `PyDescrProtocol::__delete__` and `PyDescrProtocol::__set_name__` - `PyMappingProtocol::__reversed__` - `PyNumberProtocol::__complex__` and `PyNumberProtocol::__round__` - `PyAsyncProtocol::__aenter__` and `PyAsyncProtocol::__aexit__` - Deprecate several attributes in favor of the new `#[pyo3(...)]` options: - `#[name = "..."]`, replaced by `#[pyo3(name = "...")]` [#1567](https://github.com/PyO3/pyo3/pull/1567) - `#[pyfn(m, "name")]`, replaced by `#[pyfn(m)] #[pyo3(name = "...")]`. [#1610](https://github.com/PyO3/pyo3/pull/1610) - `#[pymodule(name)]`, replaced by `#[pymodule] #[pyo3(name = "...")]` [#1650](https://github.com/PyO3/pyo3/pull/1650) - `#[text_signature = "..."]`, replaced by `#[pyo3(text_signature = "...")]`. [#1658](https://github.com/PyO3/pyo3/pull/1658) - Reduce LLVM line counts to improve compilation times. [#1604](https://github.com/PyO3/pyo3/pull/1604) - No longer call `PyEval_InitThreads` in `#[pymodule]` init code. [#1630](https://github.com/PyO3/pyo3/pull/1630) - Use `METH_FASTCALL` argument passing convention, when possible, to improve `#[pyfunction]` and method performance. [#1619](https://github.com/PyO3/pyo3/pull/1619), [#1660](https://github.com/PyO3/pyo3/pull/1660) - Filter sysconfigdata candidates by architecture when cross-compiling. [#1626](https://github.com/PyO3/pyo3/pull/1626) ### Removed - Remove deprecated exception names `BaseException` etc. [#1426](https://github.com/PyO3/pyo3/pull/1426) - Remove deprecated methods `Python::is_instance`, `Python::is_subclass`, `Python::release`, `Python::xdecref`, and `Py::from_owned_ptr_or_panic`. [#1426](https://github.com/PyO3/pyo3/pull/1426) - Remove many FFI definitions which never existed in the Python C-API: - (previously deprecated) `PyGetSetDef_INIT`, `PyGetSetDef_DICT`, `PyCoro_Check`, `PyCoroWrapper_Check`, and `PyAsyncGen_Check` [#1426](https://github.com/PyO3/pyo3/pull/1426) - `PyMethodDef_INIT` [#1426](https://github.com/PyO3/pyo3/pull/1426) - `PyTypeObject_INIT` [#1429](https://github.com/PyO3/pyo3/pull/1429) - `PyObject_Check`, `PySuper_Check`, and `FreeFunc` [#1438](https://github.com/PyO3/pyo3/pull/1438) - `PyModuleDef_INIT` [#1630](https://github.com/PyO3/pyo3/pull/1630) - Remove pyclass implementation details from `PyTypeInfo`: - `Type`, `DESCRIPTION`, and `FLAGS` [#1456](https://github.com/PyO3/pyo3/pull/1456) - `BaseType`, `BaseLayout`, `Layout`, `Initializer` [#1596](https://github.com/PyO3/pyo3/pull/1596) - Remove `PYO3_CROSS_INCLUDE_DIR` environment variable and the associated C header parsing functionality. [#1521](https://github.com/PyO3/pyo3/pull/1521) - Remove `raw_pycfunction!` macro. [#1619](https://github.com/PyO3/pyo3/pull/1619) - Remove `PyClassAlloc` trait. [#1657](https://github.com/PyO3/pyo3/pull/1657) - Remove `PyList::get_parked_item`. [#1664](https://github.com/PyO3/pyo3/pull/1664) ### Fixed - Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425) - `PYO3_CROSS_LIB_DIR` environment variable no long required when compiling for x86-64 Python from macOS arm64 and reverse. [#1428](https://github.com/PyO3/pyo3/pull/1428) - Fix FFI definition `_PyEval_RequestCodeExtraIndex`, which took an argument of the wrong type. [#1429](https://github.com/PyO3/pyo3/pull/1429) - Fix FFI definition `PyIndex_Check` missing with the `abi3` feature. [#1436](https://github.com/PyO3/pyo3/pull/1436) - Fix incorrect `TypeError` raised when keyword-only argument passed along with a positional argument in `*args`. [#1440](https://github.com/PyO3/pyo3/pull/1440) - Fix inability to use a named lifetime for `&PyTuple` of `*args` in `#[pyfunction]`. [#1440](https://github.com/PyO3/pyo3/pull/1440) - Fix use of Python argument for `#[pymethods]` inside macro expansions. [#1505](https://github.com/PyO3/pyo3/pull/1505) - No longer include `__doc__` in `__all__` generated for `#[pymodule]`. [#1509](https://github.com/PyO3/pyo3/pull/1509) - Always use cross-compiling configuration if any of the `PYO3_CROSS` family of environment variables are set. [#1514](https://github.com/PyO3/pyo3/pull/1514) - Support `EnvironmentError`, `IOError`, and `WindowsError` on PyPy. [#1533](https://github.com/PyO3/pyo3/pull/1533) - Fix unnecessary rebuilds when cycling between `cargo check` and `cargo clippy` in a Python virtualenv. [#1557](https://github.com/PyO3/pyo3/pull/1557) - Fix segfault when dereferencing `ffi::PyDateTimeAPI` without the GIL. [#1563](https://github.com/PyO3/pyo3/pull/1563) - Fix memory leak in `FromPyObject` implementations for `u128` and `i128`. [#1638](https://github.com/PyO3/pyo3/pull/1638) - Fix `#[pyclass(extends=PyDict)]` leaking the dict contents on drop. [#1657](https://github.com/PyO3/pyo3/pull/1657) - Fix segfault when calling `PyList::get_item` with negative indices. [#1668](https://github.com/PyO3/pyo3/pull/1668) - Fix FFI definitions of `PyEval_SetProfile`/`PyEval_SetTrace` to take `Option` parameters. [#1692](https://github.com/PyO3/pyo3/pull/1692) - Fix `ToPyObject` impl for `HashSet` to accept non-default hashers. [#1702](https://github.com/PyO3/pyo3/pull/1702) ## [0.13.2] - 2021-02-12 ### Packaging - Lower minimum supported Rust version to 1.41. [#1421](https://github.com/PyO3/pyo3/pull/1421) ### Added - Add unsafe API `with_embedded_python_interpreter` to initialize a Python interpreter, execute a closure, and finalize the interpreter. [#1355](https://github.com/PyO3/pyo3/pull/1355) - Add `serde` feature which provides implementations of `Serialize` and `Deserialize` for `Py`. [#1366](https://github.com/PyO3/pyo3/pull/1366) - Add FFI definition `_PyCFunctionFastWithKeywords` on Python 3.7 and up. [#1384](https://github.com/PyO3/pyo3/pull/1384) - Add `PyDateTime::new_with_fold` method. [#1398](https://github.com/PyO3/pyo3/pull/1398) - Add `size_hint` impls for `{PyDict,PyList,PySet,PyTuple}Iterator`s. [#1699](https://github.com/PyO3/pyo3/pull/1699) ### Changed - `prepare_freethreaded_python` will no longer register an `atexit` handler to call `Py_Finalize`. This resolves a number of issues with incompatible C extensions causing crashes at finalization. [#1355](https://github.com/PyO3/pyo3/pull/1355) - Mark `PyLayout::py_init`, `PyClassDict::clear_dict`, and `opt_to_pyobj` safe, as they do not perform any unsafe operations. [#1404](https://github.com/PyO3/pyo3/pull/1404) ### Fixed - Fix support for using `r#raw_idents` as argument names in pyfunctions. [#1383](https://github.com/PyO3/pyo3/pull/1383) - Fix typo in FFI definition for `PyFunction_GetCode` (was incorrectly `PyFunction_Code`). [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix FFI definitions `PyMarshal_WriteObjectToString` and `PyMarshal_ReadObjectFromString` as available in limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix FFI definitions `PyListObject` and those from `funcobject.h` as requiring non-limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387) - Fix unqualified `Result` usage in `pyobject_native_type_base`. [#1402](https://github.com/PyO3/pyo3/pull/1402) - Fix build on systems where the default Python encoding is not UTF-8. [#1405](https://github.com/PyO3/pyo3/pull/1405) - Fix build on mingw / MSYS2. [#1423](https://github.com/PyO3/pyo3/pull/1423) ## [0.13.1] - 2021-01-10 ### Added - Add support for `#[pyclass(dict)]` and `#[pyclass(weakref)]` with the `abi3` feature on Python 3.9 and up. [#1342](https://github.com/PyO3/pyo3/pull/1342) - Add FFI definitions `PyOS_BeforeFork`, `PyOS_AfterFork_Parent`, `PyOS_AfterFork_Child` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348) - Add an `auto-initialize` feature to control whether PyO3 should automatically initialize an embedded Python interpreter. For compatibility this feature is enabled by default in PyO3 0.13.1, but is planned to become opt-in from PyO3 0.14.0. [#1347](https://github.com/PyO3/pyo3/pull/1347) - Add support for cross-compiling to Windows without needing `PYO3_CROSS_INCLUDE_DIR`. [#1350](https://github.com/PyO3/pyo3/pull/1350) ### Deprecated - Deprecate FFI definitions `PyEval_CallObjectWithKeywords`, `PyEval_CallObject`, `PyEval_CallFunction`, `PyEval_CallMethod` when building for Python 3.9. [#1338](https://github.com/PyO3/pyo3/pull/1338) - Deprecate FFI definitions `PyGetSetDef_DICT` and `PyGetSetDef_INIT` which have never been in the Python API. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Deprecate FFI definitions `PyGen_NeedsFinalizing`, `PyImport_Cleanup` (removed in 3.9), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definition `PyOS_AfterFork` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definitions `PyCoro_Check`, `PyAsyncGen_Check`, and `PyCoroWrapper_Check`, which have never been in the Python API (for the first two, it is possible to use `PyCoro_CheckExact` and `PyAsyncGen_CheckExact` instead; these are the actual functions provided by the Python API). [#1348](https://github.com/PyO3/pyo3/pull/1348) - Deprecate FFI definitions for `PyUnicode_FromUnicode`, `PyUnicode_AsUnicode` and `PyUnicode_AsUnicodeAndSize`, which will be removed from 3.12 and up due to [PEP 623](https://www.python.org/dev/peps/pep-0623/). [#1370](https://github.com/PyO3/pyo3/pull/1370) ### Removed - Remove FFI definition `PyFrame_ClearFreeList` when building for Python 3.9. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Remove FFI definition `_PyDict_Contains` when building for Python 3.10. [#1341](https://github.com/PyO3/pyo3/pull/1341) - Remove FFI definitions `PyGen_NeedsFinalizing` and `PyImport_Cleanup` (for 3.9 and up), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348) ### Fixed - Stop including `Py_TRACE_REFS` config setting automatically if `Py_DEBUG` is set on Python 3.8 and up. [#1334](https://github.com/PyO3/pyo3/pull/1334) - Remove `#[deny(warnings)]` attribute (and instead refuse warnings only in CI). [#1340](https://github.com/PyO3/pyo3/pull/1340) - Fix deprecation warning for missing `__module__` with `#[pyclass]`. [#1343](https://github.com/PyO3/pyo3/pull/1343) - Correct return type of `PyFrozenSet::empty` to `&PyFrozenSet` (was incorrectly `&PySet`). [#1351](https://github.com/PyO3/pyo3/pull/1351) - Fix missing `Py_INCREF` on heap type objects on Python versions before 3.8. [#1365](https://github.com/PyO3/pyo3/pull/1365) ## [0.13.0] - 2020-12-22 ### Packaging - Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250) - Bump minimum supported Rust version to 1.45. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Bump indoc dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Bump paste dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272) - Rename internal crates `pyo3cls` and `pyo3-derive-backend` to `pyo3-macros` and `pyo3-macros-backend` respectively. [#1317](https://github.com/PyO3/pyo3/pull/1317) ### Added - Add support for building for CPython limited API. Opting-in to the limited API enables a single extension wheel built with PyO3 to be installable on multiple Python versions. This required a few minor changes to runtime behavior of of PyO3 `#[pyclass]` types. See the migration guide for full details. [#1152](https://github.com/PyO3/pyo3/pull/1152) - Add feature flags `abi3-py36`, `abi3-py37`, `abi3-py38` etc. to set the minimum Python version when using the limited API. [#1263](https://github.com/PyO3/pyo3/pull/1263) - Add argument names to `TypeError` messages generated by pymethod wrappers. [#1212](https://github.com/PyO3/pyo3/pull/1212) - Add FFI definitions for PEP 587 "Python Initialization Configuration". [#1247](https://github.com/PyO3/pyo3/pull/1247) - Add FFI definitions for `PyEval_SetProfile` and `PyEval_SetTrace`. [#1255](https://github.com/PyO3/pyo3/pull/1255) - Add FFI definitions for context.h functions (`PyContext_New`, etc). [#1259](https://github.com/PyO3/pyo3/pull/1259) - Add `PyAny::is_instance` method. [#1276](https://github.com/PyO3/pyo3/pull/1276) - Add support for conversion between `char` and `PyString`. [#1282](https://github.com/PyO3/pyo3/pull/1282) - Add FFI definitions for `PyBuffer_SizeFromFormat`, `PyObject_LengthHint`, `PyObject_CallNoArgs`, `PyObject_CallOneArg`, `PyObject_CallMethodNoArgs`, `PyObject_CallMethodOneArg`, `PyObject_VectorcallDict`, and `PyObject_VectorcallMethod`. [#1287](https://github.com/PyO3/pyo3/pull/1287) - Add conversions between `u128`/`i128` and `PyLong` for PyPy. [#1310](https://github.com/PyO3/pyo3/pull/1310) - Add `Python::version` and `Python::version_info` to get the running interpreter version. [#1322](https://github.com/PyO3/pyo3/pull/1322) - Add conversions for tuples of length 10, 11, and 12. [#1454](https://github.com/PyO3/pyo3/pull/1454) ### Changed - Change return type of `PyType::name` from `Cow` to `PyResult<&str>`. [#1152](https://github.com/PyO3/pyo3/pull/1152) - `#[pyclass(subclass)]` is now required for subclassing from Rust (was previously just required for subclassing from Python). [#1152](https://github.com/PyO3/pyo3/pull/1152) - Change `PyIterator` to be consistent with other native types: it is now used as `&PyIterator` instead of `PyIterator<'a>`. [#1176](https://github.com/PyO3/pyo3/pull/1176) - Change formatting of `PyDowncastError` messages to be closer to Python's builtin error messages. [#1212](https://github.com/PyO3/pyo3/pull/1212) - Change `Debug` and `Display` impls for `PyException` to be consistent with `PyAny`. [#1275](https://github.com/PyO3/pyo3/pull/1275) - Change `Debug` impl of `PyErr` to output more helpful information (acquiring the GIL if necessary). [#1275](https://github.com/PyO3/pyo3/pull/1275) - Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278) - Optimize `PyAny::call0`, `Py::call0` and `PyAny::call_method0` and `Py::call_method0` on Python 3.9 and up. [#1287](https://github.com/PyO3/pyo3/pull/1285) - Require double-quotes for pyclass name argument e.g `#[pyclass(name = "MyClass")]`. [#1303](https://github.com/PyO3/pyo3/pull/1303) ### Deprecated - Deprecate `Python::is_instance`, `Python::is_subclass`, `Python::release`, and `Python::xdecref`. [#1292](https://github.com/PyO3/pyo3/pull/1292) ### Removed - Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217) - Remove unused `python3` feature. [#1235](https://github.com/PyO3/pyo3/pull/1235) ### Fixed - Fix missing field in `PyCodeObject` struct (`co_posonlyargcount`) - caused invalid access to other fields in Python >3.7. [#1260](https://github.com/PyO3/pyo3/pull/1260) - Fix building for `x86_64-unknown-linux-musl` target from `x86_64-unknown-linux-gnu` host. [#1267](https://github.com/PyO3/pyo3/pull/1267) - Fix `#[text_signature]` interacting badly with rust `r#raw_identifiers`. [#1286](https://github.com/PyO3/pyo3/pull/1286) - Fix FFI definitions for `PyObject_Vectorcall` and `PyVectorcall_Call`. [#1287](https://github.com/PyO3/pyo3/pull/1285) - Fix building with Anaconda python inside a virtualenv. [#1290](https://github.com/PyO3/pyo3/pull/1290) - Fix definition of opaque FFI types. [#1312](https://github.com/PyO3/pyo3/pull/1312) - Fix using custom error type in pyclass `#[new]` methods. [#1319](https://github.com/PyO3/pyo3/pull/1319) ## [0.12.4] - 2020-11-28 ### Fixed - Fix reference count bug in implementation of `From>` for `PyObject`, a regression introduced in PyO3 0.12. [#1297](https://github.com/PyO3/pyo3/pull/1297) ## [0.12.3] - 2020-10-12 ### Fixed - Fix support for Rust versions 1.39 to 1.44, broken by an incorrect internal update to paste 1.0 which was done in PyO3 0.12.2. [#1234](https://github.com/PyO3/pyo3/pull/1234) ## [0.12.2] - 2020-10-12 ### Added - Add support for keyword-only arguments without default values in `#[pyfunction]`. [#1209](https://github.com/PyO3/pyo3/pull/1209) - Add `Python::check_signals` as a safe a wrapper for `PyErr_CheckSignals`. [#1214](https://github.com/PyO3/pyo3/pull/1214) ### Fixed - Fix invalid document for protocol methods. [#1169](https://github.com/PyO3/pyo3/pull/1169) - Hide docs of PyO3 private implementation details in `pyo3::class::methods`. [#1169](https://github.com/PyO3/pyo3/pull/1169) - Fix unnecessary rebuild on PATH changes when the python interpreter is provided by PYO3_PYTHON. [#1231](https://github.com/PyO3/pyo3/pull/1231) ## [0.12.1] - 2020-09-16 ### Fixed - Fix building for a 32-bit Python on 64-bit Windows with a 64-bit Rust toolchain. [#1179](https://github.com/PyO3/pyo3/pull/1179) - Fix building on platforms where `c_char` is `u8`. [#1182](https://github.com/PyO3/pyo3/pull/1182) ## [0.12.0] - 2020-09-12 ### Added - Add FFI definitions `Py_FinalizeEx`, `PyOS_getsig`, and `PyOS_setsig`. [#1021](https://github.com/PyO3/pyo3/pull/1021) - Add `PyString::to_str` for accessing `PyString` as `&str`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Add `Python::with_gil` for executing a closure with the Python GIL. [#1037](https://github.com/PyO3/pyo3/pull/1037) - Add type information to failures in `PyAny::downcast`. [#1050](https://github.com/PyO3/pyo3/pull/1050) - Implement `Debug` for `PyIterator`. [#1051](https://github.com/PyO3/pyo3/pull/1051) - Add `PyBytes::new_with` and `PyByteArray::new_with` for initialising `bytes` and `bytearray` objects using a closure. [#1074](https://github.com/PyO3/pyo3/pull/1074) - Add `#[derive(FromPyObject)]` macro for enums and structs. [#1065](https://github.com/PyO3/pyo3/pull/1065) - Add `Py::as_ref` and `Py::into_ref` for converting `Py` to `&T`. [#1098](https://github.com/PyO3/pyo3/pull/1098) - Add ability to return `Result` types other than `PyResult` from `#[pyfunction]`, `#[pymethod]` and `#[pyproto]` functions. [#1106](https://github.com/PyO3/pyo3/pull/1118). - Implement `ToPyObject`, `IntoPy`, and `FromPyObject` for [hashbrown](https://crates.io/crates/hashbrown)'s `HashMap` and `HashSet` types (requires the `hashbrown` feature). [#1114](https://github.com/PyO3/pyo3/pull/1114) - Add `#[pyfunction(pass_module)]` and `#[pyfn(pass_module)]` to pass the module object as the first function argument. [#1143](https://github.com/PyO3/pyo3/pull/1143) - Add `PyModule::add_function` and `PyModule::add_submodule` as typed alternatives to `PyModule::add_wrapped`. [#1143](https://github.com/PyO3/pyo3/pull/1143) - Add native `PyCFunction` and `PyFunction` types. [#1163](https://github.com/PyO3/pyo3/pull/1163) ### Changed - Rework exception types: [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Rename exception types from e.g. `RuntimeError` to `PyRuntimeError`. The old names continue to exist but are deprecated. - Exception objects are now accessible as `&T` or `Py`, just like other Python-native types. - Rename `PyException::py_err` to `PyException::new_err`. - Rename `PyUnicodeDecodeErr::new_err` to `PyUnicodeDecodeErr::new`. - Remove `PyStopIteration::stop_iteration`. - Require `T: Send` for the return value `T` of `Python::allow_threads`. [#1036](https://github.com/PyO3/pyo3/pull/1036) - Rename `PYTHON_SYS_EXECUTABLE` to `PYO3_PYTHON`. The old name will continue to work (undocumented) but will be removed in a future release. [#1039](https://github.com/PyO3/pyo3/pull/1039) - Remove `unsafe` from signature of `PyType::as_type_ptr`. [#1047](https://github.com/PyO3/pyo3/pull/1047) - Change return type of `PyIterator::from_object` to `PyResult` (was `Result`). [#1051](https://github.com/PyO3/pyo3/pull/1051) - `IntoPy` is no longer implied by `FromPy`. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Change `PyObject` to be a type alias for `Py`. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Rework `PyErr` to be compatible with the `std::error::Error` trait: [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Implement `Display`, `Error`, `Send` and `Sync` for `PyErr` and `PyErrArguments`. - Add `PyErr::instance` for accessing `PyErr` as `&PyBaseException`. - `PyErr`'s fields are now an implementation detail. The equivalent values can be accessed with `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`. - Change receiver of `PyErr::print` and `PyErr::print_and_set_sys_last_vars` to `&self` (was `self`). - Remove `PyErrValue`, `PyErr::from_value`, `PyErr::into_normalized`, and `PyErr::normalize`. - Remove `PyException::into`. - Remove `Into>` for `PyErr` and `PyException`. - Change methods generated by `#[pyproto]` to return `NotImplemented` if Python should try a reversed operation. #[1072](https://github.com/PyO3/pyo3/pull/1072) - Change argument to `PyModule::add` to `impl IntoPy` (was `impl ToPyObject`). #[1124](https://github.com/PyO3/pyo3/pull/1124) ### Removed - Remove many exception and `PyErr` APIs; see the "changed" section above. [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115) - Remove `PyString::to_string` (use new `PyString::to_str`). [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `PyString::as_bytes`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `Python::register_any`. [#1023](https://github.com/PyO3/pyo3/pull/1023) - Remove `GILGuard::acquire` from the public API. Use `Python::acquire_gil` or `Python::with_gil`. [#1036](https://github.com/PyO3/pyo3/pull/1036) - Remove the `FromPy` trait. [#1063](https://github.com/PyO3/pyo3/pull/1063) - Remove the `AsPyRef` trait. [#1098](https://github.com/PyO3/pyo3/pull/1098) ### Fixed - Correct FFI definitions `Py_SetProgramName` and `Py_SetPythonHome` to take `*const` arguments (was `*mut`). [#1021](https://github.com/PyO3/pyo3/pull/1021) - Fix `FromPyObject` for `num_bigint::BigInt` for Python objects with an `__index__` method. [#1027](https://github.com/PyO3/pyo3/pull/1027) - Correct FFI definition `_PyLong_AsByteArray` to take `*mut c_uchar` argument (was `*const c_uchar`). [#1029](https://github.com/PyO3/pyo3/pull/1029) - Fix segfault with `#[pyclass(dict, unsendable)]`. [#1058](https://github.com/PyO3/pyo3/pull/1058) [#1059](https://github.com/PyO3/pyo3/pull/1059) - Fix using `&Self` as an argument type for functions in a `#[pymethods]` block. [#1071](https://github.com/PyO3/pyo3/pull/1071) - Fix best-effort build against PyPy 3.6. [#1092](https://github.com/PyO3/pyo3/pull/1092) - Fix many cases of lifetime elision in `#[pyproto]` implementations. [#1093](https://github.com/PyO3/pyo3/pull/1093) - Fix detection of Python build configuration when cross-compiling. [#1095](https://github.com/PyO3/pyo3/pull/1095) - Always link against libpython on android with the `extension-module` feature. [#1095](https://github.com/PyO3/pyo3/pull/1095) - Fix the `+` operator not trying `__radd__` when both `__add__` and `__radd__` are defined in `PyNumberProtocol` (and similar for all other reversible operators). [#1107](https://github.com/PyO3/pyo3/pull/1107) - Fix building with Anaconda python. [#1175](https://github.com/PyO3/pyo3/pull/1175) ## [0.11.1] - 2020-06-30 ### Added - `#[pyclass(unsendable)]`. [#1009](https://github.com/PyO3/pyo3/pull/1009) ### Changed - Update `parking_lot` dependency to `0.11`. [#1010](https://github.com/PyO3/pyo3/pull/1010) ## [0.11.0] - 2020-06-28 ### Added - Support stable versions of Rust (>=1.39). [#969](https://github.com/PyO3/pyo3/pull/969) - Add FFI definition `PyObject_AsFileDescriptor`. [#938](https://github.com/PyO3/pyo3/pull/938) - Add `PyByteArray::data`, `PyByteArray::as_bytes`, and `PyByteArray::as_bytes_mut`. [#967](https://github.com/PyO3/pyo3/pull/967) - Add `GILOnceCell` to use in situations where `lazy_static` or `once_cell` can deadlock. [#975](https://github.com/PyO3/pyo3/pull/975) - Add `Py::borrow`, `Py::borrow_mut`, `Py::try_borrow`, and `Py::try_borrow_mut` for accessing `#[pyclass]` values. [#976](https://github.com/PyO3/pyo3/pull/976) - Add `IterNextOutput` and `IterANextOutput` for returning from `__next__` / `__anext__`. [#997](https://github.com/PyO3/pyo3/pull/997) ### Changed - Simplify internals of `#[pyo3(get)]` attribute. (Remove the hidden API `GetPropertyValue`.) [#934](https://github.com/PyO3/pyo3/pull/934) - Call `Py_Finalize` at exit to flush buffers, etc. [#943](https://github.com/PyO3/pyo3/pull/943) - Add type parameter to PyBuffer. #[951](https://github.com/PyO3/pyo3/pull/951) - Require `Send` bound for `#[pyclass]`. [#966](https://github.com/PyO3/pyo3/pull/966) - Add `Python` argument to most methods on `PyObject` and `Py` to ensure GIL safety. [#970](https://github.com/PyO3/pyo3/pull/970) - Change signature of `PyTypeObject::type_object` - now takes `Python` argument and returns `&PyType`. [#970](https://github.com/PyO3/pyo3/pull/970) - Change return type of `PyTuple::slice` and `PyTuple::split_from` from `Py` to `&PyTuple`. [#970](https://github.com/PyO3/pyo3/pull/970) - Change return type of `PyTuple::as_slice` to `&[&PyAny]`. [#971](https://github.com/PyO3/pyo3/pull/971) - Rename `PyTypeInfo::type_object` to `type_object_raw`, and add `Python` argument. [#975](https://github.com/PyO3/pyo3/pull/975) - Update `num-complex` optional dependendency from `0.2` to `0.3`. [#977](https://github.com/PyO3/pyo3/pull/977) - Update `num-bigint` optional dependendency from `0.2` to `0.3`. [#978](https://github.com/PyO3/pyo3/pull/978) - `#[pyproto]` is re-implemented without specialization. [#961](https://github.com/PyO3/pyo3/pull/961) - `PyClassAlloc::alloc` is renamed to `PyClassAlloc::new`. [#990](https://github.com/PyO3/pyo3/pull/990) - `#[pyproto]` methods can now have return value `T` or `PyResult` (previously only `PyResult` was supported). [#996](https://github.com/PyO3/pyo3/pull/996) - `#[pyproto]` methods can now skip annotating the return type if it is `()`. [#998](https://github.com/PyO3/pyo3/pull/998) ### Removed - Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930) ### Fixed - Fix passing explicit `None` to `Option` argument `#[pyfunction]` with a default value. [#936](https://github.com/PyO3/pyo3/pull/936) - Fix `PyClass.__new__`'s not respecting subclasses when inherited by a Python class. [#990](https://github.com/PyO3/pyo3/pull/990) - Fix returning `Option` from `#[pyproto]` methods. [#996](https://github.com/PyO3/pyo3/pull/996) - Fix accepting `PyRef` and `PyRefMut` to `#[getter]` and `#[setter]` methods. [#999](https://github.com/PyO3/pyo3/pull/999) ## [0.10.1] - 2020-05-14 ### Fixed - Fix deadlock in `Python::acquire_gil` after dropping a `PyObject` or `Py`. [#924](https://github.com/PyO3/pyo3/pull/924) ## [0.10.0] - 2020-05-13 ### Added - Add FFI definition `_PyDict_NewPresized`. [#849](https://github.com/PyO3/pyo3/pull/849) - Implement `IntoPy` for `HashSet` and `BTreeSet`. [#864](https://github.com/PyO3/pyo3/pull/864) - Add `PyAny::dir` method. [#886](https://github.com/PyO3/pyo3/pull/886) - Gate macros behind a `macros` feature (enabled by default). [#897](https://github.com/PyO3/pyo3/pull/897) - Add ability to define class attributes using `#[classattr]` on functions in `#[pymethods]`. [#905](https://github.com/PyO3/pyo3/pull/905) - Implement `Clone` for `PyObject` and `Py`. [#908](https://github.com/PyO3/pyo3/pull/908) - Implement `Deref` for all builtin types. (`PyList`, `PyTuple`, `PyDict` etc.) [#911](https://github.com/PyO3/pyo3/pull/911) - Implement `Deref` for `PyCell`. [#911](https://github.com/PyO3/pyo3/pull/911) - Add `#[classattr]` support for associated constants in `#[pymethods]`. [#914](https://github.com/PyO3/pyo3/pull/914) ### Changed - Panics will now be raised as a Python `PanicException`. [#797](https://github.com/PyO3/pyo3/pull/797) - Change `PyObject` and `Py` reference counts to decrement immediately upon drop when the GIL is held. [#851](https://github.com/PyO3/pyo3/pull/851) - Allow `PyIterProtocol` methods to use either `PyRef` or `PyRefMut` as the receiver type. [#856](https://github.com/PyO3/pyo3/pull/856) - Change the implementation of `FromPyObject` for `Py` to apply to a wider range of `T`, including all `T: PyClass`. [#880](https://github.com/PyO3/pyo3/pull/880) - Move all methods from the `ObjectProtocol` trait to the `PyAny` struct. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove need for `#![feature(specialization)]` in crates depending on PyO3. [#917](https://github.com/PyO3/pyo3/pull/917) ### Removed - Remove `PyMethodsProtocol` trait. [#889](https://github.com/PyO3/pyo3/pull/889) - Remove `num-traits` dependency. [#895](https://github.com/PyO3/pyo3/pull/895) - Remove `ObjectProtocol` trait. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove `PyAny::None`. Users should use `Python::None` instead. [#911](https://github.com/PyO3/pyo3/pull/911) - Remove all `*ProtocolImpl` traits. [#917](https://github.com/PyO3/pyo3/pull/917) ### Fixed - Fix support for `__radd__` and other `__r*__` methods as implementations for Python mathematical operators. [#839](https://github.com/PyO3/pyo3/pull/839) - Fix panics during garbage collection when traversing objects that were already mutably borrowed. [#855](https://github.com/PyO3/pyo3/pull/855) - Prevent `&'static` references to Python objects as arguments to `#[pyfunction]` and `#[pymethods]`. [#869](https://github.com/PyO3/pyo3/pull/869) - Fix lifetime safety bug with `AsPyRef::as_ref`. [#876](https://github.com/PyO3/pyo3/pull/876) - Fix `#[pyo3(get)]` attribute on `Py` fields. [#880](https://github.com/PyO3/pyo3/pull/880) - Fix segmentation faults caused by functions such as `PyList::get_item` returning borrowed objects when it was not safe to do so. [#890](https://github.com/PyO3/pyo3/pull/890) - Fix segmentation faults caused by nested `Python::acquire_gil` calls creating dangling references. [#893](https://github.com/PyO3/pyo3/pull/893) - Fix segmentatation faults when a panic occurs during a call to `Python::allow_threads`. [#912](https://github.com/PyO3/pyo3/pull/912) ## [0.9.2] - 2020-04-09 ### Added - `FromPyObject` implementations for `HashSet` and `BTreeSet`. [#842](https://github.com/PyO3/pyo3/pull/842) ### Fixed - Correctly detect 32bit architecture. [#830](https://github.com/PyO3/pyo3/pull/830) ## [0.9.1] - 2020-03-23 ### Fixed - Error messages for `#[pyclass]`. [#826](https://github.com/PyO3/pyo3/pull/826) - `FromPyObject` implementation for `PySequence`. [#827](https://github.com/PyO3/pyo3/pull/827) ## [0.9.0] - 2020-03-19 ### Added - `PyCell`, which has RefCell-like features. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyClass`, `PyLayout`, `PyClassInitializer`. [#683](https://github.com/PyO3/pyo3/pull/683) - Implemented `IntoIterator` for `PySet` and `PyFrozenSet`. [#716](https://github.com/PyO3/pyo3/pull/716) - `FromPyObject` is now automatically implemented for `T: Clone` pyclasses. [#730](https://github.com/PyO3/pyo3/pull/730) - `#[pyo3(get)]` and `#[pyo3(set)]` will now use the Rust doc-comment from the field for the Python property. [#755](https://github.com/PyO3/pyo3/pull/755) - `#[setter]` functions may now take an argument of `Pyo3::Python`. [#760](https://github.com/PyO3/pyo3/pull/760) - `PyTypeInfo::BaseLayout` and `PyClass::BaseNativeType`. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyDowncastImpl`. [#770](https://github.com/PyO3/pyo3/pull/770) - Implement `FromPyObject` and `IntoPy` traits for arrays (up to 32). [#778](https://github.com/PyO3/pyo3/pull/778) - `migration.md` and `types.md` in the guide. [#795](https://github.com/PyO3/pyo3/pull/795), #[802](https://github.com/PyO3/pyo3/pull/802) - `ffi::{_PyBytes_Resize, _PyDict_Next, _PyDict_Contains, _PyDict_GetDictPtr}`. #[820](https://github.com/PyO3/pyo3/pull/820) ### Changed - `#[new]` does not take `PyRawObject` and can return `Self`. [#683](https://github.com/PyO3/pyo3/pull/683) - The blanket implementations for `FromPyObject` for `&T` and `&mut T` are no longer specializable. Implement `PyTryFrom` for your type to control the behavior of `FromPyObject::extract` for your types. [#713](https://github.com/PyO3/pyo3/pull/713) - The implementation for `IntoPy for T` where `U: FromPy` is no longer specializable. Control the behavior of this via the implementation of `FromPy`. [#713](https://github.com/PyO3/pyo3/pull/713) - Use `parking_lot::Mutex` instead of `spin::Mutex`. [#734](https://github.com/PyO3/pyo3/pull/734) - Bumped minimum Rust version to `1.42.0-nightly 2020-01-21`. [#761](https://github.com/PyO3/pyo3/pull/761) - `PyRef` and `PyRefMut` are renewed for `PyCell`. [#770](https://github.com/PyO3/pyo3/pull/770) - Some new FFI functions for Python 3.8. [#784](https://github.com/PyO3/pyo3/pull/784) - `PyAny` is now on the top level module and prelude. [#816](https://github.com/PyO3/pyo3/pull/816) ### Removed - `PyRawObject`. [#683](https://github.com/PyO3/pyo3/pull/683) - `PyNoArgsFunction`. [#741](https://github.com/PyO3/pyo3/pull/741) - `initialize_type`. To set the module name for a `#[pyclass]`, use the `module` argument to the macro. #[751](https://github.com/PyO3/pyo3/pull/751) - `AsPyRef::as_mut/with/with_mut/into_py/into_mut_py`. [#770](https://github.com/PyO3/pyo3/pull/770) - `PyTryFrom::try_from_mut/try_from_mut_exact/try_from_mut_unchecked`. [#770](https://github.com/PyO3/pyo3/pull/770) - `Python::mut_from_owned_ptr/mut_from_borrowed_ptr`. [#770](https://github.com/PyO3/pyo3/pull/770) - `ObjectProtocol::get_base/get_mut_base`. [#770](https://github.com/PyO3/pyo3/pull/770) ### Fixed - Fixed unsoundness of subclassing. [#683](https://github.com/PyO3/pyo3/pull/683). - Clear error indicator when the exception is handled on the Rust side. [#719](https://github.com/PyO3/pyo3/pull/719) - Usage of raw identifiers with `#[pyo3(set)]`. [#745](https://github.com/PyO3/pyo3/pull/745) - Usage of `PyObject` with `#[pyo3(get)]`. [#760](https://github.com/PyO3/pyo3/pull/760) - `#[pymethods]` used in conjunction with `#[cfg]`. #[769](https://github.com/PyO3/pyo3/pull/769) - `"*"` in a `#[pyfunction()]` argument list incorrectly accepting any number of positional arguments (use `args = "*"` when this behavior is desired). #[792](https://github.com/PyO3/pyo3/pull/792) - `PyModule::dict`. #[809](https://github.com/PyO3/pyo3/pull/809) - Fix the case where `DESCRIPTION` is not null-terminated. #[822](https://github.com/PyO3/pyo3/pull/822) ## [0.8.5] - 2020-01-05 ### Added - Implemented `FromPyObject` for `HashMap` and `BTreeMap` - Support for `#[name = "foo"]` attribute for `#[pyfunction]` and in `#[pymethods]`. [#692](https://github.com/PyO3/pyo3/pull/692) ## [0.8.4] - 2019-12-14 ### Added - Support for `#[text_signature]` attribute. [#675](https://github.com/PyO3/pyo3/pull/675) ## [0.8.3] - 2019-11-23 ### Removed - `#[init]` is removed. [#658](https://github.com/PyO3/pyo3/pull/658) ### Fixed - Now all `&Py~` types have `!Send` bound. [#655](https://github.com/PyO3/pyo3/pull/655) - Fix a compile error raised by the stabilization of `!` type. [#672](https://github.com/PyO3/pyo3/issues/672). ## [0.8.2] - 2019-10-27 ### Added - FFI compatibility for PEP 590 Vectorcall. [#641](https://github.com/PyO3/pyo3/pull/641) ### Fixed - Fix PySequenceProtocol::set_item. [#624](https://github.com/PyO3/pyo3/pull/624) - Fix a corner case of BigInt::FromPyObject. [#630](https://github.com/PyO3/pyo3/pull/630) - Fix index errors in parameter conversion. [#631](https://github.com/PyO3/pyo3/pull/631) - Fix handling of invalid utf-8 sequences in `PyString::as_bytes`. [#639](https://github.com/PyO3/pyo3/pull/639) and `PyString::to_string_lossy` [#642](https://github.com/PyO3/pyo3/pull/642). - Remove `__contains__` and `__iter__` from PyMappingProtocol. [#644](https://github.com/PyO3/pyo3/pull/644) - Fix proc-macro definition of PySetAttrProtocol. [#645](https://github.com/PyO3/pyo3/pull/645) ## [0.8.1] - 2019-10-08 ### Added - Conversion between [num-bigint](https://github.com/rust-num/num-bigint) and Python int. [#608](https://github.com/PyO3/pyo3/pull/608) ### Fixed - Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604) - Patch specialization being broken by Rust 1.40. [#614](https://github.com/PyO3/pyo3/issues/614) - Fix a segfault around PyErr. [#597](https://github.com/PyO3/pyo3/pull/597) ## [0.8.0] - 2019-09-16 ### Added - `module` argument to `pyclass` macro. [#499](https://github.com/PyO3/pyo3/pull/499) - `py_run!` macro [#512](https://github.com/PyO3/pyo3/pull/512) - Use existing fields and methods before calling custom **getattr**. [#505](https://github.com/PyO3/pyo3/pull/505) - `PyBytes` can now be indexed just like `Vec` - Implement `IntoPy` for `PyRef` and `PyRefMut`. ### Changed - Implementing the Using the `gc` parameter for `pyclass` (e.g. `#[pyclass(gc)]`) without implementing the `class::PyGCProtocol` trait is now a compile-time error. Failing to implement this trait could lead to segfaults. [#532](https://github.com/PyO3/pyo3/pull/532) - `PyByteArray::data` has been replaced with `PyDataArray::to_vec` because returning a `&[u8]` is unsound. (See [this comment](https://github.com/PyO3/pyo3/issues/373#issuecomment-512332696) for a great write-up for why that was unsound) - Replace `mashup` with `paste`. - `GILPool` gained a `Python` marker to prevent it from being misused to release Python objects without the GIL held. ### Removed - `IntoPyObject` was replaced with `IntoPy` - `#[pyclass(subclass)]` is hidden a `unsound-subclass` feature because it's causing segmentation faults. ### Fixed - More readable error message for generics in pyclass [#503](https://github.com/PyO3/pyo3/pull/503) ## [0.7.0] - 2019-05-26 ### Added - PyPy support by omerbenamram in [#393](https://github.com/PyO3/pyo3/pull/393) - Have `PyModule` generate an index of its members (`__all__` list). - Allow `slf: PyRef` for pyclass(#419) - Allow to use lifetime specifiers in `pymethods` - Add `marshal` module. [#460](https://github.com/PyO3/pyo3/pull/460) ### Changed - `Python::run` returns `PyResult<()>` instead of `PyResult<&PyAny>`. - Methods decorated with `#[getter]` and `#[setter]` can now omit wrapping the result type in `PyResult` if they don't raise exceptions. ### Fixed - `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB. - Fixed automatic derive of `PySequenceProtocol` implementation in [#423](https://github.com/PyO3/pyo3/pull/423). - Capitalization & better wording to README.md. - Docstrings of properties is now properly set using the doc of the `#[getter]` method. - Fixed issues with `pymethods` crashing on doc comments containing double quotes. - `PySet::new` and `PyFrozenSet::new` now return `PyResult<&Py[Frozen]Set>`; exceptions are raised if the items are not hashable. - Fixed building using `venv` on Windows. - `PyTuple::new` now returns `&PyTuple` instead of `Py`. - Fixed several issues with argument parsing; notable, the `*args` and `**kwargs` tuple/dict now doesn't contain arguments that are otherwise assigned to parameters. ## [0.6.0] - 2019-03-28 ### Regressions - Currently, [#341](https://github.com/PyO3/pyo3/issues/341) causes `cargo test` to fail with weird linking errors when the `extension-module` feature is activated. For now you can work around this by making the `extension-module` feature optional and running the tests with `cargo test --no-default-features`: ```toml [dependencies.pyo3] version = "0.6.0" [features] extension-module = ["pyo3/extension-module"] default = ["extension-module"] ``` ### Added - Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3 - Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the "Cross Compiling" section in the "Building and Distribution" chapter of the guide for more details. - The `PyRef` and `PyRefMut` types, which allow to differentiate between an instance of a rust struct on the rust heap and an instance that is embedded inside a python object. By kngwyu in [#335](https://github.com/PyO3/pyo3/pull/335) - Added `FromPy` and `IntoPy` which are equivalent to `From` and `Into` except that they require a gil token. - Added `ManagedPyRef`, which should eventually replace `ToBorrowedObject`. ### Changed - Renamed `PyObjectRef` to `PyAny` in #388 - Renamed `add_function` to `add_wrapped` as it now also supports modules. - Renamed `#[pymodinit]` to `#[pymodule]` - `py.init(|| value)` becomes `Py::new(value)` - `py.init_ref(|| value)` becomes `PyRef::new(value)` - `py.init_mut(|| value)` becomes `PyRefMut::new(value)`. - `PyRawObject::init` is now infallible, e.g. it returns `()` instead of `PyResult<()>`. - Renamed `py_exception!` to `create_exception!` and refactored the error macros. - Renamed `wrap_function!` to `wrap_pyfunction!` - Renamed `#[prop(get, set)]` to `#[pyo3(get, set)]` - `#[pyfunction]` now supports the same arguments as `#[pyfn()]` - Some macros now emit proper spanned errors instead of panics. - Migrated to the 2018 edition - `crate::types::exceptions` moved to `crate::exceptions` - Replace `IntoPyTuple` with `IntoPy>`. - `IntoPyPointer` and `ToPyPointer` moved into the crate root. - `class::CompareOp` moved into `class::basic::CompareOp` - PyTypeObject is now a direct subtrait PyTypeCreate, removing the old cyclical implementation in [#350](https://github.com/PyO3/pyo3/pull/350) - Add `PyList::{sort, reverse}` by chr1sj0nes in [#357](https://github.com/PyO3/pyo3/pull/357) and [#358](https://github.com/PyO3/pyo3/pull/358) - Renamed the `typeob` module to `type_object` ### Removed - `PyToken` was removed due to unsoundness (See [#94](https://github.com/PyO3/pyo3/issues/94)). - Removed the unnecessary type parameter from `PyObjectAlloc` - `NoArgs`. Just use an empty tuple - `PyObjectWithGIL`. `PyNativeType` is sufficient now that PyToken is removed. ### Fixed - A soudness hole where every instances of a `#[pyclass]` struct was considered to be part of a python object, even though you can create instances that are not part of the python heap. This was fixed through `PyRef` and `PyRefMut`. - Fix kwargs support in [#328](https://github.com/PyO3/pyo3/pull/328). - Add full support for `__dict__` in [#403](https://github.com/PyO3/pyo3/pull/403). ## [0.5.3] - 2019-01-04 ### Fixed - Fix memory leak in ArrayList by kngwyu [#316](https://github.com/PyO3/pyo3/pull/316) ## [0.5.2] - 2018-11-25 ### Fixed - Fix undeterministic segfaults when creating many objects by kngwyu in [#281](https://github.com/PyO3/pyo3/pull/281) ## [0.5.1] - 2018-11-24 Yanked ## [0.5.0] - 2018-11-11 ### Added - `#[pyclass]` objects can now be returned from rust functions - `PyComplex` by kngwyu in [#226](https://github.com/PyO3/pyo3/pull/226) - `PyDict::from_sequence`, equivalent to `dict([(key, val), ...])` - Bindings for the `datetime` standard library types: `PyDate`, `PyTime`, `PyDateTime`, `PyTzInfo`, `PyDelta` with associated `ffi` types, by pganssle [#200](https://github.com/PyO3/pyo3/pull/200). - `PyString`, `PyUnicode`, and `PyBytes` now have an `as_bytes` method that returns `&[u8]`. - `PyObjectProtocol::get_type_ptr` by ijl in [#242](https://github.com/PyO3/pyo3/pull/242) ### Changed - Removes the types from the root module and the prelude. They now live in `pyo3::types` instead. - All exceptions are constructed with `py_err` instead of `new`, as they return `PyErr` and not `Self`. - `as_mut` and friends take and `&mut self` instead of `&self` - `ObjectProtocol::call` now takes an `Option<&PyDict>` for the kwargs instead of an `IntoPyDictPointer`. - `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`. - `PyTuple::new` now takes an `IntoIterator` instead of a slice - Updated to syn 0.15 - Splitted `PyTypeObject` into `PyTypeObject` without the create method and `PyTypeCreate` with requires `PyObjectAlloc + PyTypeInfo + Sized`. - Ran `cargo edition --fix` which prefixed path with `crate::` for rust 2018 - Renamed `async` to `pyasync` as async will be a keyword in the 2018 edition. - Starting to use `NonNull<*mut PyObject>` for Py and PyObject by ijl [#260](https://github.com/PyO3/pyo3/pull/260) ### Removed - Removed most entries from the prelude. The new prelude is small and clear. - Slowly removing specialization uses - `PyString`, `PyUnicode`, and `PyBytes` no longer have a `data` method (replaced by `as_bytes`) and `PyStringData` has been removed. - The pyobject_extract macro ### Fixed - Added an explanation that the GIL can temporarily be released even while holding a GILGuard. - Lots of clippy errors - Fix segfault on calling an unknown method on a PyObject - Work around a [bug](https://github.com/rust-lang/rust/issues/55380) in the rust compiler by kngwyu [#252](https://github.com/PyO3/pyo3/pull/252) - Fixed a segfault with subclassing pyo3 create classes and using `__class__` by kngwyu [#263](https://github.com/PyO3/pyo3/pull/263) ## [0.4.1] - 2018-08-20 ### Changed - PyTryFrom's error is always to `PyDowncastError` ### Fixed - Fixed compilation on nightly since `use_extern_macros` was stabilized ### Removed - The pyobject_downcast macro ## [0.4.0] - 2018-07-30 ### Changed - Merged both examples into one - Rustfmt all the things :heavy_check_mark: - Switched to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Removed - Conversions from tuples to PyDict due to [rust-lang/rust#52050](https://github.com/rust-lang/rust/issues/52050) ## [0.3.2] - 2018-07-22 ### Changed - Replaced `concat_idents` with mashup ## [0.3.1] - 2018-07-18 ### Fixed - Fixed scoping bug in pyobject_native_type that would break rust-numpy ## [0.3.0] - 2018-07-18 ### Added - A few internal macros became part of the public api ([#155](https://github.com/PyO3/pyo3/pull/155), [#186](https://github.com/PyO3/pyo3/pull/186)) - Always clone in getters. This allows using the get-annotation on all Clone-Types ### Changed - Upgraded to syn 0.14 which means much better error messages :tada: - 128 bit integer support by [kngwyu](https://github.com/kngwyu) ([#137](https://github.com/PyO3/pyo3/pull/173)) - `proc_macro` has been stabilized on nightly ([rust-lang/rust#52081](https://github.com/rust-lang/rust/pull/52081)). This means that we can remove the `proc_macro` feature, but now we need the `use_extern_macros` from the 2018 edition instead. - All proc macro are now prefixed with `py` and live in the prelude. This means you can use `#[pyclass]`, `#[pymethods]`, `#[pyproto]`, `#[pyfunction]` and `#[pymodinit]` directly, at least after a `use pyo3::prelude::*`. They were also moved into a module called `proc_macro`. You shouldn't use `#[pyo3::proc_macro::pyclass]` or other longer paths in attributes because `proc_macro_path_invoc` isn't going to be stabilized soon. - Renamed the `base` option in the `pyclass` macro to `extends`. - `#[pymodinit]` uses the function name as module name, unless the name is overrriden with `#[pymodinit(name)]` - The guide is now properly versioned. ## [0.2.7] - 2018-05-18 ### Fixed - Fix nightly breakage with proc_macro_path ## [0.2.6] - 2018-04-03 ### Fixed - Fix compatibility with TryFrom trait #137 ## [0.2.5] - 2018-02-21 ### Added - CPython 3.7 support ### Fixed - Embedded CPython 3.7b1 crashes on initialization #110 - Generated extension functions are weakly typed #108 - call_method\* crashes when the method does not exist #113 - Allow importing exceptions from nested modules #116 ## [0.2.4] - 2018-01-19 ### Added - Allow to get mutable ref from PyObject #106 - Drop `RefFromPyObject` trait - Add Python::register_any method ### Fixed - Fix impl `FromPyObject` for `Py` - Mark method that work with raw pointers as unsafe #95 ## [0.2.3] - 11-27-2017 ### Changed - Rustup to 1.23.0-nightly 2017-11-07 ### Fixed - Proper `c_char` usage #93 ### Removed - Remove use of now unneeded 'AsciiExt' trait ## [0.2.2] - 09-26-2017 ### Changed - Rustup to 1.22.0-nightly 2017-09-30 ## [0.2.1] - 09-26-2017 ### Fixed - Fix rustc const_fn nightly breakage ## [0.2.0] - 08-12-2017 ### Added - Added inheritance support #15 - Added weakref support #56 - Added subclass support #64 - Added `self.__dict__` supoort #68 - Added `pyo3::prelude` module #70 - Better `Iterator` support for PyTuple, PyList, PyDict #75 - Introduce IntoPyDictPointer similar to IntoPyTuple #69 ### Changed - Allow to add gc support without implementing PyGCProtocol #57 - Refactor `PyErr` implementation. Drop `py` parameter from constructor. ## [0.1.0] - 07-23-2017 ### Added - Initial release [Unreleased]: https://github.com/pyo3/pyo3/compare/v0.22.2...HEAD [0.22.2]: https://github.com/pyo3/pyo3/compare/v0.22.1...v0.22.2 [0.22.1]: https://github.com/pyo3/pyo3/compare/v0.22.0...v0.22.1 [0.22.0]: https://github.com/pyo3/pyo3/compare/v0.21.2...v0.22.0 [0.21.2]: https://github.com/pyo3/pyo3/compare/v0.21.1...v0.21.2 [0.21.1]: https://github.com/pyo3/pyo3/compare/v0.21.0...v0.21.1 [0.21.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0 [0.21.0-beta.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0-beta.0 [0.20.3]: https://github.com/pyo3/pyo3/compare/v0.20.2...v0.20.3 [0.20.2]: https://github.com/pyo3/pyo3/compare/v0.20.1...v0.20.2 [0.20.1]: https://github.com/pyo3/pyo3/compare/v0.20.0...v0.20.1 [0.20.0]: https://github.com/pyo3/pyo3/compare/v0.19.2...v0.20.0 [0.19.2]: https://github.com/pyo3/pyo3/compare/v0.19.1...v0.19.2 [0.19.1]: https://github.com/pyo3/pyo3/compare/v0.19.0...v0.19.1 [0.19.0]: https://github.com/pyo3/pyo3/compare/v0.18.3...v0.19.0 [0.18.3]: https://github.com/pyo3/pyo3/compare/v0.18.2...v0.18.3 [0.18.2]: https://github.com/pyo3/pyo3/compare/v0.18.1...v0.18.2 [0.18.1]: https://github.com/pyo3/pyo3/compare/v0.18.0...v0.18.1 [0.18.0]: https://github.com/pyo3/pyo3/compare/v0.17.3...v0.18.0 [0.17.3]: https://github.com/pyo3/pyo3/compare/v0.17.2...v0.17.3 [0.17.2]: https://github.com/pyo3/pyo3/compare/v0.17.1...v0.17.2 [0.17.1]: https://github.com/pyo3/pyo3/compare/v0.17.0...v0.17.1 [0.17.0]: https://github.com/pyo3/pyo3/compare/v0.16.6...v0.17.0 [0.16.6]: https://github.com/pyo3/pyo3/compare/v0.16.5...v0.16.6 [0.16.5]: https://github.com/pyo3/pyo3/compare/v0.16.4...v0.16.5 [0.16.4]: https://github.com/pyo3/pyo3/compare/v0.16.3...v0.16.4 [0.16.3]: https://github.com/pyo3/pyo3/compare/v0.16.2...v0.16.3 [0.16.2]: https://github.com/pyo3/pyo3/compare/v0.16.1...v0.16.2 [0.16.1]: https://github.com/pyo3/pyo3/compare/v0.16.0...v0.16.1 [0.16.0]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.16.0 [0.15.2]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.15.2 [0.15.1]: https://github.com/pyo3/pyo3/compare/v0.15.0...v0.15.1 [0.15.0]: https://github.com/pyo3/pyo3/compare/v0.14.5...v0.15.0 [0.14.5]: https://github.com/pyo3/pyo3/compare/v0.14.4...v0.14.5 [0.14.4]: https://github.com/pyo3/pyo3/compare/v0.14.3...v0.14.4 [0.14.3]: https://github.com/pyo3/pyo3/compare/v0.14.2...v0.14.3 [0.14.2]: https://github.com/pyo3/pyo3/compare/v0.14.1...v0.14.2 [0.14.1]: https://github.com/pyo3/pyo3/compare/v0.14.0...v0.14.1 [0.14.0]: https://github.com/pyo3/pyo3/compare/v0.13.2...v0.14.0 [0.13.2]: https://github.com/pyo3/pyo3/compare/v0.13.1...v0.13.2 [0.13.1]: https://github.com/pyo3/pyo3/compare/v0.13.0...v0.13.1 [0.13.0]: https://github.com/pyo3/pyo3/compare/v0.12.4...v0.13.0 [0.12.4]: https://github.com/pyo3/pyo3/compare/v0.12.3...v0.12.4 [0.12.3]: https://github.com/pyo3/pyo3/compare/v0.12.2...v0.12.3 [0.12.2]: https://github.com/pyo3/pyo3/compare/v0.12.1...v0.12.2 [0.12.1]: https://github.com/pyo3/pyo3/compare/v0.12.0...v0.12.1 [0.12.0]: https://github.com/pyo3/pyo3/compare/v0.11.1...v0.12.0 [0.11.1]: https://github.com/pyo3/pyo3/compare/v0.11.0...v0.11.1 [0.11.0]: https://github.com/pyo3/pyo3/compare/v0.10.1...v0.11.0 [0.10.1]: https://github.com/pyo3/pyo3/compare/v0.10.0...v0.10.1 [0.10.0]: https://github.com/pyo3/pyo3/compare/v0.9.2...v0.10.0 [0.9.2]: https://github.com/pyo3/pyo3/compare/v0.9.1...v0.9.2 [0.9.1]: https://github.com/pyo3/pyo3/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/pyo3/pyo3/compare/v0.8.5...v0.9.0 [0.8.5]: https://github.com/pyo3/pyo3/compare/v0.8.4...v0.8.5 [0.8.4]: https://github.com/pyo3/pyo3/compare/v0.8.3...v0.8.4 [0.8.3]: https://github.com/pyo3/pyo3/compare/v0.8.2...v0.8.3 [0.8.2]: https://github.com/pyo3/pyo3/compare/v0.8.1...v0.8.2 [0.8.1]: https://github.com/pyo3/pyo3/compare/v0.8.0...v0.8.1 [0.8.0]: https://github.com/pyo3/pyo3/compare/v0.7.0...v0.8.0 [0.7.0]: https://github.com/pyo3/pyo3/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/pyo3/pyo3/compare/v0.5.3...v0.6.0 [0.5.3]: https://github.com/pyo3/pyo3/compare/v0.5.2...v0.5.3 [0.5.2]: https://github.com/pyo3/pyo3/compare/v0.5.1...v0.5.2 [0.5.1]: https://github.com/pyo3/pyo3/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/pyo3/pyo3/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/pyo3/pyo3/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/pyo3/pyo3/compare/v0.3.2...v0.4.0 [0.3.2]: https://github.com/pyo3/pyo3/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/pyo3/pyo3/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/pyo3/pyo3/compare/v0.2.7...v0.3.0 [0.2.7]: https://github.com/pyo3/pyo3/compare/v0.2.6...v0.2.7 [0.2.6]: https://github.com/pyo3/pyo3/compare/v0.2.5...v0.2.6 [0.2.5]: https://github.com/pyo3/pyo3/compare/v0.2.4...v0.2.5 [0.2.4]: https://github.com/pyo3/pyo3/compare/v0.2.3...v0.2.4 [0.2.3]: https://github.com/pyo3/pyo3/compare/v0.2.2...v0.2.3 [0.2.2]: https://github.com/pyo3/pyo3/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/pyo3/pyo3/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/pyo3/pyo3/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/PyO3/pyo3/tree/0.1.0 pyo3/Architecture.md0000644000175000017500000002355314661133735015407 0ustar jamespagejamespage # PyO3: Architecture This document roughly describes the high-level architecture of PyO3. If you want to become familiar with the codebase you are in the right place! ## Overview PyO3 provides a bridge between Rust and Python, based on the [Python/C API]. Thus, PyO3 has low-level bindings of these API as its core. On top of that, we have higher-level bindings to operate Python objects safely. Also, to define Python classes and functions in Rust code, we have `trait PyClass` and a set of protocol traits (e.g., `PyIterProtocol`) for supporting object protocols (i.e., `__dunder__` methods). Since implementing `PyClass` requires lots of boilerplate, we have a proc-macro `#[pyclass]`. To summarize, there are six main parts to the PyO3 codebase. 1. [Low-level bindings of Python/C API.](#1-low-level-bindings-of-python-capi) - [`pyo3-ffi`] and [`src/ffi`] 2. [Bindings to Python objects.](#2-bindings-to-python-objects) - [`src/instance.rs`] and [`src/types`] 3. [`PyClass` and related functionalities.](#3-pyclass-and-related-functionalities) - [`src/pycell.rs`], [`src/pyclass.rs`], and more 4. [Procedural macros to simplify usage for users.](#4-procedural-macros-to-simplify-usage-for-users) - [`src/impl_`], [`pyo3-macros`] and [`pyo3-macros-backend`] 5. [`build.rs` and `pyo3-build-config`](#5-buildrs-and-pyo3-build-config) - [`build.rs`](https://github.com/PyO3/pyo3/tree/main/build.rs) - [`pyo3-build-config`] ## 1. Low-level bindings of Python/C API [`pyo3-ffi`] contains wrappers of the [Python/C API]. This is currently done by hand rather than automated tooling because: - it gives us best control about how to adapt C conventions to Rust, and - there are many Python interpreter versions we support in a single set of files. We aim to provide straight-forward Rust wrappers resembling the file structure of [`cpython/Include`](https://github.com/python/cpython/tree/v3.9.2/Include). However, we still lack some APIs and are continuously updating the module to match the file contents upstream in CPython. The tracking issue is [#1289](https://github.com/PyO3/pyo3/issues/1289), and contribution is welcome. In the [`pyo3-ffi`] crate, there is lots of conditional compilation such as `#[cfg(Py_LIMITED_API)]`, `#[cfg(Py_3_7)]`, and `#[cfg(PyPy)]`. `Py_LIMITED_API` corresponds to `#define Py_LIMITED_API` macro in Python/C API. With `Py_LIMITED_API`, we can build a Python-version-agnostic binary called an [abi3 wheel](https://pyo3.rs/latest/building-and-distribution.html#py_limited_apiabi3). `Py_3_7` means that the API is available from Python >= 3.7. There are also `Py_3_8`, `Py_3_9`, and so on. `PyPy` means that the API definition is for PyPy. Those flags are set in [`build.rs`](#6-buildrs-and-pyo3-build-config). ## 2. Bindings to Python objects [`src/types`] contains bindings to [built-in types](https://docs.python.org/3/library/stdtypes.html) of Python, such as `dict` and `list`. For historical reasons, Python's `object` is called `PyAny` in PyO3 and located in [`src/types/any.rs`]. Currently, `PyAny` is a straightforward wrapper of `ffi::PyObject`, defined as: ```rust #[repr(transparent)] pub struct PyAny(UnsafeCell); ``` Concrete Python objects are implemented by wrapping `PyAny`, e.g.,: ```rust #[repr(transparent)] pub struct PyDict(PyAny); ``` These types are not intended to be accessed directly, and instead are used through the `Py` and `Bound` smart pointers. We have some macros in [`src/types/mod.rs`] which make it easier to implement APIs for concrete Python types. ## 3. `PyClass` and related functionalities [`src/pycell.rs`], [`src/pyclass.rs`], and [`src/type_object.rs`] contain types and traits to make `#[pyclass]` work. Also, [`src/pyclass_init.rs`] and [`src/impl_/pyclass.rs`] have related functionalities. To realize object-oriented programming in C, all Python objects have `ob_base: PyObject` as their first field in their structure definition. Thanks to this guarantee, casting `*mut A` to `*mut PyObject` is valid if `A` is a Python object. To ensure this guarantee, we have a wrapper struct `PyCell` in [`src/pycell.rs`] which is roughly: ```rust #[repr(C)] pub struct PyCell { ob_base: crate::ffi::PyObject, inner: T, } ``` Thus, when copying a Rust struct to a Python object, we first allocate `PyCell` on the Python heap and then move `T` into it. Also, `PyCell` provides [RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html)-like methods to ensure Rust's borrow rules. See [the documentation](https://docs.rs/pyo3/latest/pyo3/pycell/struct.PyCell.html) for more. `PyCell` requires that `T` implements `PyClass`. This trait is somewhat complex and derives many traits, but the most important one is `PyTypeInfo` in [`src/type_object.rs`]. `PyTypeInfo` is also implemented for built-in types. In Python, all objects have their types, and types are also objects of `type`. For example, you can see `type({})` shows `dict` and `type(type({}))` shows `type` in Python REPL. `T: PyTypeInfo` implies that `T` has a corresponding type object. ### Protocol methods Python has some built-in special methods called dunder methods, such as `__iter__`. They are called "slots" in the [abstract objects layer](https://docs.python.org/3/c-api/abstract.html) in Python/C API. We provide a way to implement those protocols similarly, by recognizing special names in `#[pymethods]`, with a few new ones for slots that can not be implemented in Python, such as GC support. ## 4. Procedural macros to simplify usage for users. [`pyo3-macros`] provides five proc-macro APIs: `pymodule`, `pyfunction`, `pyclass`, `pymethods`, and `#[derive(FromPyObject)]`. [`pyo3-macros-backend`] has the actual implementations of these APIs. [`src/impl_`] contains `#[doc(hidden)]` functionality used in code generated by these proc-macros, such as parsing function arguments. ## 5. `build.rs` and `pyo3-build-config` PyO3 supports a wide range of OSes, interpreters and use cases. The correct environment must be detected at build time in order to set up relevant conditional compilation correctly. This logic is captured in the [`pyo3-build-config`] crate, which is a `build-dependency` of `pyo3` and `pyo3-macros`, and can also be used by downstream users in the same way. In [`pyo3-build-config`]'s `build.rs` the build environment is detected and inlined into the crate as a "config file". This works in all cases except for cross-compiling, where it is necessary to capture this from the `pyo3` `build.rs` to get some extra environment variables that Cargo doesn't set for build dependencies. The `pyo3` `build.rs` also runs some safety checks such as ensuring the Python version detected is actually supported. Some of the functionality of `pyo3-build-config`: - Find the interpreter for build and detect the Python version. - We have to set some version flags like `#[cfg(Py_3_7)]`. - If the interpreter is PyPy, we set `#[cfg(PyPy)`. - If the `PYO3_CONFIG_FILE` environment variable is set then that file's contents will be used instead of any detected configuration. - If the `PYO3_NO_PYTHON` environment variable is set then the interpreter detection is bypassed entirely and only abi3 extensions can be built. - Check if we are building a Python extension. - If we are building an extension (e.g., Python library installable by `pip`), we don't link `libpython`. Currently we use the `extension-module` feature for this purpose. This may change in the future. See [#1123](https://github.com/PyO3/pyo3/pull/1123). - Cross-compiling configuration - If `TARGET` architecture and `HOST` architecture differ, we can find cross compile information from environment variables (`PYO3_CROSS_LIB_DIR`, `PYO3_CROSS_PYTHON_VERSION` and `PYO3_CROSS_PYTHON_IMPLEMENTATION`) or system files. When cross compiling extension modules it is often possible to make it work without any additional user input. - When an experimental feature `generate-import-lib` is enabled, the `pyo3-ffi` build script can generate `python3.dll` import libraries for Windows targets automatically via an external [`python3-dll-a`] crate. This enables the users to cross compile Python extensions for Windows without having to install any Windows Python libraries. [python/c api]: https://docs.python.org/3/c-api/ [`python3-dll-a`]: https://docs.rs/python3-dll-a/latest/python3_dll_a/ [`pyo3-macros`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros [`pyo3-macros-backend`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros-backend [`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config [`pyo3-ffi`]: https://github.com/PyO3/pyo3/tree/main/pyo3-ffi [`src/class`]: https://github.com/PyO3/pyo3/tree/main/src/class [`src/ffi`]: https://github.com/PyO3/pyo3/tree/main/src/ffi [`src/types`]: https://github.com/PyO3/pyo3/tree/main/src/types [`src/impl_`]: https://github.com/PyO3/pyo3/blob/main/src/impl_ [`src/instance.rs`]: https://github.com/PyO3/pyo3/tree/main/src/instance.rs [`src/pycell.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pycell.rs [`src/pyclass.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass.rs [`src/pyclass_init.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_init.rs [`src/pyclass_slot.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_slot.rs [`src/type_object.rs`]: https://github.com/PyO3/pyo3/tree/main/src/type_object.rs [`src/class/methods.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/methods.rs [`src/class/impl_.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/impl_.rs [`src/types/any.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/any.rs [`src/types/mod.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/mod.rs pyo3/CITATION.cff0000644000175000017500000000044314661133735014326 0ustar jamespagejamespagecff-version: 1.2.0 title: PyO3 message: >- If you use this software as part of a publication and wish to cite it, please use the metadata from this file. type: software authors: - name: PyO3 Project and Contributors website: https://github.com/PyO3 license: - Apache-2.0 - MIT pyo3/Code-of-Conduct.md0000644000175000017500000000640414661133735015632 0ustar jamespagejamespage# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq pyo3/.cargo-checksum.json0000664000175000017500000005274214661133735016313 0ustar jamespagejamespage{"files":{"Architecture.md":"0abd87d6c513b75f912a6b4169bd6bf0bc1e6ada4cc2bfb956ce37d5accc96cb","CHANGELOG.md":"204fec01e8e2f4d347c00af0c507c3d53e3204ce94844a994ab2ed618deb38fb","CITATION.cff":"2d5aa5df590c4e47799ac644d15c56f9a3c5b2f3ef3b8e96946d372903ac7270","Cargo.toml":"6c60771082bc95cb0912b2a8261664e24232d35162abb7b04d85e62dc5c3bc33","Code-of-Conduct.md":"92d4a344e60e7310c654de92a26d84c99dafbfd4fab149a85d4e22f38232bafb","Contributing.md":"5ba6ee6ee7878b62f6be9af29c70ed8a015d40ca9f758807761443f3709717a8","LICENSE-APACHE":"71073d492e996de196dbe1eb1e4c94c27c014c841b288161265b2efd06d0af28","LICENSE-MIT":"afcbe3b2e6b37172b5a9ca869ee4c0b8cdc09316e5d4384864154482c33e5af6","README.md":"5be595dd9fa487b49b23791489f896a03dcb38578990ebed132705a15337c19c","Releasing.md":"3e2cf797f83cf58d2244b84788f182c5a9e31ca88e981a7ecb87671c2f32d944","assets/script.py":"e269075461009f6d5c937427d3d63c1fb99ba214828c1bffadc7142cbc12afdb","build.rs":"84d2d9002206ec617159fed3437365121bf690ccef1367b865142ba2f51169be","emscripten/Makefile":"2de779cfe5cf0787830ccef090f80621bdf876db7cc9df1e3881fdaa99a7157f","emscripten/emscripten_patches/0001-Add-_gxx_personality_v0-stub-to-library.js.patch":"66cf2245a7452739d4d4b4f3e3f0f1985cc55581121708ab8341890c33834339","emscripten/env.sh":"e868d55070251ba643846fb4b3671ee73c30abf495ecac187b5e414e399987b9","emscripten/pybuilddir.txt":"47865a6fa77ecfc7fff126c06bb04a95a0c996f04b628d6ece7e059b9f68731f","emscripten/runner.py":"4e37c58b4b652c11108bce045c61adc8de8650cf88ada5052750ac708a884f2d","guide/book.toml":"5e468284a6b476f1b88c5b5ecacc9fb4623061b6a03271d34ceff593601c947f","guide/pyclass-parameters.md":"e1883eb2d6763c33b5ca75f6c0248382eb84c2103b1f4f613719e1925e753199","guide/pyo3_version.py":"6d6d4a97615612038371bc68c37a4e4dce826196375ad5db0ef9a5e46cc066ce","guide/src/SUMMARY.md":"5e990c7f8aa86df5bc653bc57d5e26fc82a1a2bef49675cb6418c219e89403ce","guide/src/advanced.md":"df2f8bb4eec77b8950f3f1b9dd558807629c34f4a3c561a6d5c702073237bd72","guide/src/async-await.md":"d2eb746b3f19f736186659e58231a970b9de76941909b8ccecf377e5ae57a9db","guide/src/building-and-distribution.md":"993aad1d61ddb05eb6159543f1d2814b2655f7a8946b0d864e909f38d027b95b","guide/src/building-and-distribution/multiple-python-versions.md":"19532e9000f54eb34234ec511ffe18e77f42dc32f8ca47ae8d29d007570eaaa8","guide/src/changelog.md":"439803753b2afb2157fbcb7384c4465684736c0a42d63ef8f4a5bd8356dbfa69","guide/src/class.md":"414b1c169703011eebe8ffd4c76da23771bfcc9624c4420da5ad740ef87ab01e","guide/src/class/call.md":"c62fcc6ddaac949308ef4510cf225f27351296b932475de4f0a90819f19a4c77","guide/src/class/numeric.md":"70006461e9813677fa8c18166f965180dbb7a20b1c12ba0571c0042c76b67884","guide/src/class/object.md":"b7bfa610e2a06fa8cc00a9bf1a4e130dc598f1ad56d5b327ba975fb9e0b652d7","guide/src/class/protocols.md":"d040ce387e46ece60e14a2375399a19dccdc5542fb9154bb5f70b45bcdc2dbf1","guide/src/contributing.md":"655723bc7de5aa185b05be39400e87000595bcf268dd3066f7fc091be0a1aac0","guide/src/conversions.md":"50b4d3bf31d73542c837de8138007d5ac9198ae75ac9b8691270a3827906ba51","guide/src/conversions/tables.md":"ab6ee60871568acfa1ef72cbe0b40ae56b722c44b661b3934d0e7c812c9b514c","guide/src/conversions/traits.md":"543a8d44c275f46f7dfb0b691dd25238116c1f11a4409ebe1383e6234bf97063","guide/src/debugging.md":"d8aa76f919b1db028691f80c0d4d35535456bad3507205434363039d07fe12f9","guide/src/ecosystem.md":"d2a663465d9842f91bee793899dd5dd51e5431b5ced03d8bbb205c0eeaf5cc1c","guide/src/ecosystem/async-await.md":"02a6e41537118857132adc46d6dd8edc5a8b3e79b3cb058d19b16616786686a5","guide/src/ecosystem/logging.md":"214b58b37a44b232204f3f1c114afb81e1e792521c15d8788f121e35409e879d","guide/src/exception.md":"8375121094c997aa4ac53661eb9a386fc3194e629f982eba2250a40d7106f73e","guide/src/faq.md":"c41f03d93f90947bc508a323d812b36d6c37429b3e6de26a2f7acc5b17d3bd87","guide/src/features.md":"4b44436bff0b8fa9c6e6a49ad65603c30f71d50ed10113411d77f7fcd3914b1e","guide/src/function-calls.md":"7a7f84b340f532210f5293656682a5c8087542e50774ab07e1096b2d350a4484","guide/src/function.md":"20cf96648c40b6bfa983738ebe7d8083c2c912f0f4b78a21559f5053ff250637","guide/src/function/error-handling.md":"846645c88dc72b87cfe1e8444a1bb0bdfc7d70ace9faf9f7ae3bfb4483b1937b","guide/src/function/signature.md":"220cb2a2dbdb67cc8e2adcce7d9f4fad5e1d35d30cb7b5396980bfe9c18074dd","guide/src/getting-started.md":"8cf4647ab2754994d0dca502e0221a4f9378f5844267dda606c5e97f095e0083","guide/src/index.md":"bec16d0c01c379d11c4784bda7e2414285fc559cffa05fa0ed87fb18479d685c","guide/src/memory.md":"447edfc2604536632c66b146601414bcb9cff01da10a3226f411b78b9655ac1c","guide/src/migration.md":"c5857cab16794f1dab96dcea5c471e8c844289ba48dc9d58f74bb228339051ac","guide/src/module.md":"64a719898339bd0d89b3af7fe6cb2cd1a06b0cb6850c11fdd1942a110d501115","guide/src/parallelism.md":"e780318d08ed7ba61d9845f76e1257c926736d7173636d379ed4e98832f23f59","guide/src/performance.md":"95b976f2ea6b0e92fc55b7b8e03a5393ca50f26b9fcef5f580222abbc83422a2","guide/src/python-from-rust.md":"308be9b3fc1a3e0b1cb353c2062eeb49708009fbc6eaa3345652d93a518dc7bd","guide/src/python-from-rust/calling-existing-code.md":"aa3bb99288eb4c8b2e189add9baffb76d23bc3044a935c1df1d1e12d8aba8f5f","guide/src/python-from-rust/function-calls.md":"2fbbe420b41051f8e4e8f908ea677f548a17dbfd6f7b694cae7090142d4e5dcf","guide/src/python-typing-hints.md":"a95b12016cea6d10359c7459a6e11abd756c91e27e03a7f9c2a22e9d5716e7e0","guide/src/rust-from-python.md":"4ef16eb5c25780a92a994d9ddda4f27096b5929cc05ef71a60842eeee1754e2f","guide/src/trait-bounds.md":"86b4e4a7a99acfabd9b81913234f345cef396d612eefc6a06a271b5749c1a9e1","guide/src/types.md":"6d004bc4e9576d22aab3731b6c583ce4ff49a5cc5551dde74c59c2ee4acad16f","netlify.toml":"3a495930da6a0b47a86e48a5dda1aff32c5fc93cf29a60236909e0a264a63635","pyo3-runtime/LICENSE-APACHE":"71073d492e996de196dbe1eb1e4c94c27c014c841b288161265b2efd06d0af28","pyo3-runtime/LICENSE-MIT":"afcbe3b2e6b37172b5a9ca869ee4c0b8cdc09316e5d4384864154482c33e5af6","pyo3-runtime/README.md":"022371b6e623237264fb9654101bc33288f8842b5dfb9b4f5dca7215125268ba","pyo3-runtime/pyproject.toml":"a0854ec67ee05a09432e622d268235e9416d82743261046b5424d37bedf0a7eb","pyo3-runtime/src/pyo3_runtime/__init__.py":"b172e1ee0dca0b84021717191814e91b6b1c47b866981b0c8eae8ba91a6d9118","pyo3-runtime/tests/__init__.py":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/buffer.rs":"374c7fd5e72b3da758540388ba8e8de1a9e0bec4943393d64351a9d0a2992a99","src/callback.rs":"17b858ed8acead9321112265eab405fcece8788d3109875519cdbf59af750ca9","src/conversion.rs":"2ecb80a6daf821ee32025f2e54d3486c8ef4c3930c5b567a5ad877a87f97b390","src/conversions/anyhow.rs":"28e5d5a8acf2818e6e4b1956dcf2bf5b24cd36fe5012b57531944776f0c31ccb","src/conversions/chrono.rs":"81ca658b97c5e12f1c3aacf429d5525066454dc640dceece4b8cbfb9703689db","src/conversions/chrono_tz.rs":"38b4443d0d72b193c705329a9dc976ffc38b3cbd0267e4b6475f2055bb030bbb","src/conversions/either.rs":"4d6b9f36f07fd6533b2303695660a411f38dc95317df478e4d407b08634a7f49","src/conversions/eyre.rs":"e740753b90f038ba9777f8aae0ab3c2f85b7c9f61ba9fa7ca240c5451764f066","src/conversions/hashbrown.rs":"24306e4c6e4e5a51d6f6e95ee78e25a16982bacb8bbf8297ff44d43c36873a8a","src/conversions/indexmap.rs":"d809edfb6cba055f81f023ed55cb805811f34e9084e46551796f9018bfe4f9aa","src/conversions/mod.rs":"a2a73a0a45420576c8ac7cf00b22f71ef80e77ea288aa6f3310ac8a5f3894a68","src/conversions/num_bigint.rs":"847acd49f55f797b9a9c0e52792383b992113a964642e4de3d62e7c79b83844e","src/conversions/num_complex.rs":"d25d5d8e4976e3b7bef80e31232b5d9e0981226d63e5f9fe8886fd3cfb2a6e07","src/conversions/num_rational.rs":"0cd7eeee40bf87222b353b988cf635cb5581e7ed0185f1454507fe1c377f9f54","src/conversions/rust_decimal.rs":"428539641bbb385534c1e6428e54311b30bf285e9575658637ea202ecf685d3d","src/conversions/serde.rs":"00617a9ddcc7b7c9d73c581b9fcc2ea370357a0eb78f4173d7e3f6e6db66ef30","src/conversions/smallvec.rs":"65d6fde17712c399dfd2fbeff256a34d917b55f63aa5f1a50faa2da1530f06da","src/conversions/std/array.rs":"6d97876b4f5d19a89e05d9d71157ef65fae0012c57348f2d0f0631d161cd5082","src/conversions/std/cell.rs":"b9405d3c3ed1c9527dc87b7ddb2bc4b3a284acb64e1c4818b7a6150896b3ad69","src/conversions/std/ipaddr.rs":"1b9266864c36eb9b3c8ce7440076c5973a8eea443435a5900a2433107708e612","src/conversions/std/map.rs":"103dc1b205180d4fcb50c23a36aa822cfb804a2f3c9f96e92df8b91e01105fc7","src/conversions/std/mod.rs":"586319954e53dbc7481f41c20ff57a7f1befd6cb237a668beb1ee5c4c313bee7","src/conversions/std/num.rs":"c5d5625ce5b11592e537331df471f99e9d0b1c2f2ae7bc8e66c759e4c08844f2","src/conversions/std/option.rs":"70a21fcbd75203545beec41409ae80e18d1ce139b50f848047c52dbbc320d246","src/conversions/std/osstr.rs":"0fc3aa98c87ee46b0f08ac87909b67007b51858420117e8d53fe32a814cdc560","src/conversions/std/path.rs":"ff1a3bc9253a49c92a1cd40a01a1647de7ca13d10e8653b5a3da27dee52818c1","src/conversions/std/set.rs":"33f52208d4d7e1af5576efc284c171621ac79fad8d3dee7ea7d8facdddd2bf15","src/conversions/std/slice.rs":"1ad6ea1326e0d7520109f10ff2b9c62a89f6d4dc6dcb2941ea7bb228ce547889","src/conversions/std/string.rs":"e46e9b619359f8955d27a56bcbe9e197a74cd684cfedb110a25def1c08c70fd4","src/conversions/std/time.rs":"706935179647db9b024b7b88f1b32b7c5be02ba67338814461c4e93a8d21c7f8","src/conversions/std/vec.rs":"cf01937f707baff69fbdeb30b912354588e14805bec02477c73f3e0af650e6fe","src/coroutine.rs":"c8dd08d2ab425452a205b9a49bfb23505cf2c1c5621d3f9dc2cf08d8409ea6d4","src/coroutine/cancel.rs":"c445e05535ff65bbdfaf9280579b63b16b5d4c57497e9a81f217fb52ccf72668","src/coroutine/waker.rs":"f032fcaadcf4c367617aec7b0f6a234b032aa0db4b30d1de17afa93b8318ab53","src/derive_utils.rs":"3feeffed67942f73749401a7e7c71192d2362c73484b73e34d35b4520ea6d30b","src/err/err_state.rs":"74c1117b4806a4a73e334b1d1f57882860f9f5fca9ca4046165bb135a8670210","src/err/impls.rs":"af3519c77cd59986412b67176b1156ce75402e6173496a4cf5bfd4bcbd859de6","src/err/mod.rs":"b9faa7bac1bb1f27146c06b458c2f7dd7226bc243a31a80e2b10f7a01204297d","src/exceptions.rs":"8a5aabfe41916b4854f689f3a9998a8cf8ff1eb248cecc5128fbbad9d84d8287","src/ffi/mod.rs":"e606a0eca1e527b16d7f93dcb73a1ec9ac1c323c59bcf5962d0b24790b542f24","src/ffi/tests.rs":"4a54efb1bf8902cde103146dae24c99f119d3a0e4819a62da67ff2f50904a430","src/ffi_ptr_ext.rs":"477489a497dcb49e3ea053c9e99b737116b2a603eb8124385b9501f7ffc7d6b0","src/gil.rs":"34360377c4a98d05b06647298579aac624b3e246a3b688cf6daef97bf9609146","src/impl_.rs":"c96fb12abf7f7f57879fe7e95c71f7cb8b0a9cfce20965ab227937f053770dee","src/impl_/coroutine.rs":"e3d2bd4d8049236b4120ddb21b576ec47f2346348dc57887734b95266f397628","src/impl_/deprecations.rs":"f7d1bdd207f5c6bc6fa481c227bbc0783ee358fddc63843eee8b4035f174ab3a","src/impl_/exceptions.rs":"6ecaaee3d7968adff7cf63058a907ef1c8c15010fc30a39e39cfbff80acbf404","src/impl_/extract_argument.rs":"54eb675d130a8ef5ecea99495e54710ef3e2b317edb36e8c8c4649b22475dc2b","src/impl_/freelist.rs":"9cba201857124d7ce87e2c874b7f221cb20c75bab551080e50e9289a771a8ba8","src/impl_/frompyobject.rs":"fa2a9224fa7a880620d0e327c736d9f4243dea9c1e4839dc24d337bd61cdf817","src/impl_/not_send.rs":"964be0adb1999a531a921c10183811280e240ee781e31dc8ae49175737c3b7b6","src/impl_/panic.rs":"bf0c60a4650bf7ae66088c4ce744f546ca197cb170eeef0f3f0a28c57be55007","src/impl_/pycell.rs":"14e44c723a44432df9e280a2c35f5ba67c4e472fb17270efb509c5737b60dc32","src/impl_/pyclass.rs":"35fe39a4d3fbf910ef8c08f5be31176c40a230201caf45ea586d85bbc39aee0f","src/impl_/pyclass/lazy_type_object.rs":"b1ef8615169ecf484d99055edb1198ff8e915dfb0f5f73276128780ed5dd7a33","src/impl_/pyfunction.rs":"796fbd52389fb92b3f21ac8b639fa85f825166ff3cb416f854dcd8ef9a403adf","src/impl_/pymethods.rs":"60bfa2b7e58e02109940dd5b9ec5a7caa012d1505ba535211e4165d49a013039","src/impl_/pymodule.rs":"1d8d2e9f48b4f5187c802eab32b98d91ab0f0123e8902d9d81581eff86f183f4","src/impl_/trampoline.rs":"466c9fc7672424f195247281de7cc4e82c3d33eba4e987e43671ff9606ce0435","src/impl_/wrap.rs":"e405d25a72a99f264c04fe4a5607565cbd9f00d3047ca573605c9e057d70467b","src/inspect/mod.rs":"4876e6d601ed56b33c8cf2723f0cf7198da3a69a26be8d4799d8c5a935c4dd49","src/inspect/types.rs":"8a1364529f473c793d2e3b5296a9be8bd92920d9da14debc3a69a452c17b85a8","src/instance.rs":"3d6f867bcc15203f2c9c9f6d15dda621e40768f2dde407f0060e41a2051d6b8a","src/internal_tricks.rs":"25814651accc87693ed5f98e5d09e8a412260c63079f23d6fa61a3dbea3be2bd","src/lib.rs":"7cdc3e65c18d81e31d3b412545e81f665ba34106506fb70066ed8c42871fa7c9","src/macros.rs":"b7340c47ec5c2a33e5445d345c5ab1f51065ade495f744c8f9b11ab677135a2a","src/marker.rs":"f1101adef376f91eb59d200a2fbc9ade03155cd06674ac5255bc92f52f779910","src/marshal.rs":"70efd4c2fe49df7cd283c636b8c696192369016b422f7f520ef792d5418eca07","src/panic.rs":"bc49ee5591b53bdc2e1f54da75bc6917ffc2e7399eaba986635a7d60c98edd3f","src/prelude.rs":"b31f4dc8e2149164b5d2d0017262e3ab8f29a64b180cacfe56c1f972fefb1481","src/py_result_ext.rs":"68f45c17efe430321d75323628df86d3f3b7827fdd513423181cbd56773e9f34","src/pybacked.rs":"6b85a3e8f20b85230b09df125500d8f3ed9c39d47c91cb9a1c2c6a0e6114309b","src/pycell.rs":"d746cf26d78720fc56487c07b69e5b824e09ad1af9af45c20a21597f86c36f34","src/pycell/impl_.rs":"292d9252193226e99f8fa0ca45956c6dd8d1339be6a540d729060a394ef2c780","src/pyclass.rs":"60aa212fc084ca5e8215c24908f31382615e3f375495394d8cf5f16564c1f013","src/pyclass/create_type_object.rs":"7f61874ab6070a4023ebf2f2b1b55408bda795e1bf4f30602937c79d4a3e8ac5","src/pyclass/gc.rs":"7d8c914600d1d725fc13f5558982ac2bc6ecbed7e145b09ffeb5c9bb1c629b0b","src/pyclass_init.rs":"fd8aef28918fd36b3552a3046d0695e586176087ccafb8f8238ab8d09b569df4","src/sealed.rs":"d06eb67d21216773fa83c669f8d98bc65138b660d2dafed220a27f8b78a822b2","src/sync.rs":"89a861f42500a13c2b6b0b071a1eec3aa0a6a696395b4c54605bfc907ad0cdaa","src/test_utils.rs":"2fe31e1211529dffa901b9efc28d24ac4f57f5c8248d80bf7069b4437e472655","src/tests/common.rs":"e38fdfc421416b756ced6825f6708e852e9ea79fad19db65384a222fa205ee99","src/tests/hygiene/misc.rs":"9ade9eb328ef91350e409b8ff5556ca51a051a53845e5b47d158a2a99a5b5e5d","src/tests/hygiene/mod.rs":"36a5fbef6f876c897d5bd811496bb6b8ae87bc7b8937b0e1f139f862fe788699","src/tests/hygiene/pyclass.rs":"55b65d231a67d56f22ae645a150698af2362fb178212276a20ef7981e3ed8b40","src/tests/hygiene/pyfunction.rs":"b0192245e36245756b413e292b48edb182c37550b0f74f46b3dd973e89519575","src/tests/hygiene/pymethods.rs":"242afed8479ff2510e91146a62431922fac81842c014fbe21c9ca80b83037102","src/tests/hygiene/pymodule.rs":"51bbd3bf2fefa198358d28899e54efc018370e48974126441ceacc5c107c333e","src/tests/mod.rs":"f0d1c300916ef0115fc2f203b36335c29f04f38c395004c791b00c0b05a6bbe9","src/type_object.rs":"c83d3af347294395a0803aa303fa96391ae2d6d63771ae48446c97207434a842","src/types/any.rs":"20193114de482c82da6c0cac744e85ba8cd8cf03298834eeae1bfe25d9846ff0","src/types/boolobject.rs":"000e809994bbbf7e9cffaa45bf03f2d131cfd871594be361d7f822c61092749b","src/types/bytearray.rs":"8e000c9391a2a78ec6661d670aa4e9882091c1ebc108f83b78312492f9bee55d","src/types/bytes.rs":"8bd0142bee2ef3cad665e3c8c38397334cd763c43391085ee909df5089eba7e2","src/types/capsule.rs":"ce9c2564c23ee885b4964710e444bda539b81d8cc5f7f4d9e8f7015953dfc6e0","src/types/code.rs":"41f1d862f152a9c9f9c9c883d53d49b0581a05c9ac1031d2b9bb98491c0a06db","src/types/complex.rs":"85d8f27ae003d956762a9a5477d3b6d9d971bc0430c92c1b6a668ed783ff7354","src/types/datetime.rs":"2fa1318cb2db7c948ef852538a1afce1de3536d37f7083fc7d55ead04f218283","src/types/dict.rs":"a6887971277c79211ae1a8f6b6070c14264005c55dc3eac454b478ff2ff7b718","src/types/ellipsis.rs":"03246bc9e6892872d3c109e5749edecea8d7a22efcbed89d155fc417e4e47f24","src/types/float.rs":"7b80390c7fd2911a42a3e9776c18986b40d7caffe2369701fd87a0e9ff3fc0d2","src/types/frame.rs":"b1ec3469af5f2e3fa1b3a6ff0511ea9bf0722b01ff6c0008bb181f5a6c38ec8d","src/types/frozenset.rs":"68c03d88b00f4d11fd139ebb1071479b1639d9c8972d98a8744ce96f284e4f7f","src/types/function.rs":"070de41f65acf61efac187420e4d999a7e30bf65ec940b5569caff010664faf3","src/types/iterator.rs":"40fc8dd3978eb6ea6522f3c1a3b63070698c721bdc54999047e41fdaa81f7b11","src/types/list.rs":"45cb49bc48e98fd2ec1b78223f067d9ef6b4212d003de778dbd550c1dde9830a","src/types/mapping.rs":"a2e8ba3d45f4ea48abbad4137fcf1e436a7d4213637b199de4cf7e5c321f495a","src/types/memoryview.rs":"9507c10a3940ef9c2d05d7a0d773ad2c26e2d6fcd944d18cd50aa8fd0c0f8ece","src/types/mod.rs":"9d46ca85a1cda8a12d4e01cff50fddcbdd090a39fb4ff3f7e669278bfd00ba8d","src/types/module.rs":"be65753994f333635650a79fc98c5e68e645e343c898b75f77496bccfaf6764a","src/types/none.rs":"d45db4d4f660388262e60a5fa8be8e8124321efcf358c9bbe59e6563208c82d5","src/types/notimplemented.rs":"7a52b2a0b72a37913437896372258d7cb04a6bd9e0a8d890a5f83d7a8858bde8","src/types/num.rs":"fbf7ca3b5630c8068ec664f5a68e189cbe13dd595b5ae53936501d58641ec515","src/types/pysuper.rs":"1f86d35dfc41cea6e3b11592421ed6d16913ac9a6549c01a93d5c8b47a544b95","src/types/sequence.rs":"f8ff436975ad865c19a1be05437619967b87058df4555edd05454303aa5cf7f6","src/types/set.rs":"97a6f3e82ce60ce1b13cdbc87a583f51ffcb428406d39a375aeb85f56af7067d","src/types/slice.rs":"98b816ce0cba904f08b335e53c8b3aadd80bdfd854047343bd6101b70c865b5d","src/types/string.rs":"0294101cfd99848166bf4c0ff0055036f093c3d13e387524d057bc8c358c4a98","src/types/traceback.rs":"c65cc0b084afc24758ba61778575d877ce82dbdae2768a3675a659e8b619c229","src/types/tuple.rs":"d46f2ede9c26e73cb8d0fd14d77b17f86dc875e2faf5033430a04012d4840a20","src/types/typeobject.rs":"496f92134a8d470023dc5a4341c603f60e1f047d1ee14b0b34abc9095eae4717","src/types/weakref/anyref.rs":"4db73387baf5c2537633ddb0a2efb23e0b969b4b397d23d5b2a50b74a89cf243","src/types/weakref/mod.rs":"411b8ae0ab077bf3c9e39917f046f775deb44f7cc8801370169f1d48c0f35b38","src/types/weakref/proxy.rs":"dace3ff3f04162d5e80131cc644f5a4fe8846c24535e968dcccb8bc22a7599a2","src/types/weakref/reference.rs":"cd4db6f16bbca7df71433db5fa90b6f7c865cd139cda86e21baab78f0715861a","src/version.rs":"baefa2aac7b4868ae01cfefcfaf31f6f568436b6ff51628e1c69bccee90cc4b2","tests/test_anyhow.rs":"de73a60f813b7dffd53ad89931c624cb67ad8204ecb27dab201c6e220ffe808e","tests/test_append_to_inittab.rs":"90dd63d6152f57e11a6b5d2fddb9b89df7319f65ce82a4d49724b026b4032ee4","tests/test_arithmetics.rs":"ce47abfe1a614254d9e891fc115da1370b109e8795b08da906a9dd7fd95ac1eb","tests/test_buffer.rs":"ef569dc24b7912a98b551f980d03adc0bc86ae0e5f93c24dbc6af5e3d0cf892b","tests/test_buffer_protocol.rs":"cdc02a070f087b2878d05f3b43a4fdfcd39cbceb421533135942ea42940c9b9e","tests/test_bytes.rs":"c73f7ab7d7aadabbae683f0c488659f1c7cbfb1ac6c995f9c1db03b31ecdde74","tests/test_class_attributes.rs":"308f9e5a72d726337e21b93729d22b771d357b3ce8aab9acc772aa03768c91f2","tests/test_class_basics.rs":"531e59a7519255e9784716038a3950112339e28050720c9ae3c55e636479ba0b","tests/test_class_comparisons.rs":"aeb20ac8e1eab550eae609a81d468b3e07f693a668ba5fdd5db8280c402917d4","tests/test_class_conversion.rs":"86b58ba35e8925a9835af1c27c48373080d6d3fd7b91e9383f73e11dab1b775f","tests/test_class_new.rs":"47a5f1d365aa952ca10b55ce97dda0eb8662a37d2daa338e2872e7cc6248af40","tests/test_coroutine.rs":"e2e2bf03a182cb6d5f2402f29a936c3bd1d20680bbbe9c8eb855d0a1d2a9e2d9","tests/test_datetime.rs":"403118a891777b2c035bfdcd87c9430a850b5ce7deed05a3ef145300a3e67b8a","tests/test_datetime_import.rs":"552b432651b05c1e3dde3727b8756b9649b07698c7aac00f0ec85e53eaaf28b9","tests/test_declarative_module.rs":"154d738ffeacb646c8c9e71d8146a6ef1d8082521aaace6ccfce9413a17764ec","tests/test_default_impls.rs":"f6d0d3aa3e06da742d73a44e69ba779b6628d1b3ed12d414343f9209482ef64e","tests/test_dict_iter.rs":"158f11ca9f427798be86ffc41821b97cb483d4d2f334a10b1757537ec22038b2","tests/test_enum.rs":"05ba2d58371dc9e8281cc4018af94cf16c0728bb8a1e2d184a161bcfd97cbf46","tests/test_exceptions.rs":"0c76200fd4eef81bdae54420126eb9a4516e785e0f9bab94fc280de93639b956","tests/test_field_cfg.rs":"7a1e858ecffc14fc4425b002baa79b5970a587de2299230cf1d6f35a4bb8fbbc","tests/test_frompyobject.rs":"956b07495ef88734f24b3c9df786ce4f3ec3f73b4d6ad956002f28e8c8d3bb7b","tests/test_gc.rs":"3134ea322189f52ceb3d46865e44f57668d9f063327d940503337d27b6c9b8fb","tests/test_getter_setter.rs":"1f8488e8a0050b56c283660785b32a70930b66330e18a959e3978cae36aea2a1","tests/test_inheritance.rs":"08250856c7c36e6dbd9411c17689fc06929d9124d74485d4530a2c31175d4097","tests/test_macro_docs.rs":"aeae98ff64d21a977affef52a30ee97c639f2b20c7787ebb246c76bbb4807030","tests/test_macros.rs":"d7378445fb31334a9e4d40ed5c71856f7a3e0713a6198e5f0744204388c83274","tests/test_mapping.rs":"c5b8f94c7556350b91aa9143057c3383c5437f40dc873736b9d0d7aaa42aca14","tests/test_methods.rs":"042834c3c9f65220ddf76df3d8cbc56e0eb805e7026f0a1903538703ed993992","tests/test_module.rs":"e3ab7cc1bdcbb522c9f1def6567982ba561d197691b068fcb786dce58f81b224","tests/test_multiple_pymethods.rs":"4dc62f348f3b2a9ecc4bb488da7a563f6764372f51d9ae58eba1b08958d567e9","tests/test_no_imports.rs":"57d340d6aeff07955eae00e8119f4af87eca8312200fb9cb2836719fc9cbafcc","tests/test_proto_methods.rs":"00d7e52509e04b4cdf116553b55a040b8613e1b4a6fa69015a573fe88dc6d385","tests/test_pyfunction.rs":"e5faf8fa2c1d4d358b7bc513c2404ebea8b34016af8ab3d36a8d5094db1ea0d1","tests/test_pyself.rs":"05b9d99098e3615067ec66c4ebeac35b966c74b88beeea9f95933e7190e1958c","tests/test_sequence.rs":"d3177d3c9b6f4f0477776354f9eff7aadfca939eb7a1e0bcd2b98edb455d9ccf","tests/test_serde.rs":"bfefb2263e5ee6a7b5375a2672557f58ef597d41db0c77a0661e38526de4f829","tests/test_static_slots.rs":"17362add8264e51d4be799b7af1686f08108411a945f6e52264c2c6b6910d218","tests/test_string.rs":"f298dcc53d884c881db3104a73b40a71a772314573fbc98780ac970558105795","tests/test_super.rs":"26e8a2e6d64285c146410408f7c1bc8f4a33d277a8e3dca4d0a4c5b8e1d2ad95","tests/test_text_signature.rs":"c405acfffaa8663da2d8baf555def7cd0e85021dc21db76f3dca8c229b52d811","tests/test_variable_arguments.rs":"e8384e6841579605f377f2e865e67337c376adf3feb4fd85d4cf01cbf942b4cc","tests/test_various.rs":"bcb8c87ec5c4c48773d30ec96a6c6fff17a42ad5a13b5ebe5a08fa2d5a8cedb9","tests/test_wrap_pyfunction_deduction.rs":"9665861aba05c9dc40a050c32db77a1317a9347243d0900c27cfd01cc81dea1a"},"package":"831e8e819a138c36e212f3af3fd9eeffed6bf1510a805af35b0edee5ffa59433"}pyo3/netlify.toml0000644000175000017500000000015514661133735015003 0ustar jamespagejamespage[build] publish = "netlify_build/" command = ".netlify/build.sh" [build.environment] PYTHON_VERSION = "3.8" pyo3-build-config/0000775000175000017500000000000014661133735014775 5ustar jamespagejamespagepyo3-build-config/build.rs0000644000175000017500000000470214661133735016443 0ustar jamespagejamespage// Import some modules from this crate inline to generate the build config. // Allow dead code because not all code in the modules is used in this build script. #[path = "src/impl_.rs"] #[allow(dead_code)] mod impl_; #[path = "src/errors.rs"] #[allow(dead_code)] mod errors; use std::{env, path::Path}; use errors::{Context, Result}; use impl_::{env_var, make_interpreter_config, InterpreterConfig}; fn configure(interpreter_config: Option, name: &str) -> Result { let target = Path::new(&env::var_os("OUT_DIR").unwrap()).join(name); if let Some(config) = interpreter_config { config .to_writer(&mut std::fs::File::create(&target).with_context(|| { format!("failed to write config file at {}", target.display()) })?)?; Ok(true) } else { std::fs::File::create(&target) .with_context(|| format!("failed to create new file at {}", target.display()))?; Ok(false) } } /// If PYO3_CONFIG_FILE is set, copy it into the crate. fn config_file() -> Result> { if let Some(path) = env_var("PYO3_CONFIG_FILE") { let path = Path::new(&path); println!("cargo:rerun-if-changed={}", path.display()); // Absolute path is necessary because this build script is run with a cwd different to the // original `cargo build` instruction. ensure!( path.is_absolute(), "PYO3_CONFIG_FILE must be an absolute path" ); let interpreter_config = InterpreterConfig::from_path(path) .context("failed to parse contents of PYO3_CONFIG_FILE")?; Ok(Some(interpreter_config)) } else { Ok(None) } } fn generate_build_configs() -> Result<()> { let configured = configure(config_file()?, "pyo3-build-config-file.txt")?; if configured { // Don't bother trying to find an interpreter on the host system // if the user-provided config file is present. configure(None, "pyo3-build-config.txt")?; } else { configure(Some(make_interpreter_config()?), "pyo3-build-config.txt")?; } Ok(()) } fn main() { if std::env::var("CARGO_FEATURE_RESOLVE_CONFIG").is_ok() { if let Err(e) = generate_build_configs() { eprintln!("error: {}", e.report()); std::process::exit(1) } } else { eprintln!("resolve-config feature not enabled; build script in no-op mode"); } } pyo3-build-config/LICENSE-APACHE0000644000175000017500000002503514661133735016724 0ustar jamespagejamespage Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. pyo3-build-config/Cargo.toml0000644000175000017500000000272514661133735016731 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "pyo3-build-config" version = "0.22.2" authors = ["PyO3 Project and Contributors "] description = "Build configuration for the PyO3 ecosystem" homepage = "https://github.com/pyo3/pyo3" keywords = [ "pyo3", "python", "cpython", "ffi", ] categories = [ "api-bindings", "development-tools::ffi", ] license = "MIT OR Apache-2.0" repository = "https://github.com/pyo3/pyo3" [package.metadata.docs.rs] features = ["resolve-config"] [dependencies.once_cell] version = "1" [dependencies.python3-dll-a] version = "0.2.6" optional = true [dependencies.target-lexicon] version = "0.12.14" [build-dependencies.python3-dll-a] version = "0.2.6" optional = true [build-dependencies.target-lexicon] version = "0.12.14" [features] abi3 = [] abi3-py310 = ["abi3-py311"] abi3-py311 = ["abi3-py312"] abi3-py312 = ["abi3"] abi3-py37 = ["abi3-py38"] abi3-py38 = ["abi3-py39"] abi3-py39 = ["abi3-py310"] default = [] extension-module = [] resolve-config = [] pyo3-build-config/LICENSE-MIT0000644000175000017500000000212314661133735016425 0ustar jamespagejamespageCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3-build-config/src/0000775000175000017500000000000014661133735015564 5ustar jamespagejamespagepyo3-build-config/src/import_lib.rs0000644000175000017500000000416514661133735020276 0ustar jamespagejamespage//! Optional `python3.dll` import library generator for Windows use std::env; use std::path::PathBuf; use python3_dll_a::ImportLibraryGenerator; use target_lexicon::{Architecture, OperatingSystem, Triple}; use super::{PythonImplementation, PythonVersion}; use crate::errors::{Context, Error, Result}; /// Generates the `python3.dll` or `pythonXY.dll` import library for Windows targets. /// /// Places the generated import library into the build script output directory /// and returns the full library directory path. /// /// Does nothing if the target OS is not Windows. pub(super) fn generate_import_lib( target: &Triple, py_impl: PythonImplementation, py_version: Option, ) -> Result> { if target.operating_system != OperatingSystem::Windows { return Ok(None); } let out_dir = env::var_os("OUT_DIR").expect("generate_import_lib() must be called from a build script"); // Put the newly created import library into the build script output directory. let mut out_lib_dir = PathBuf::from(out_dir); out_lib_dir.push("lib"); // Convert `Architecture` enum to rustc `target_arch` option format. let arch = match target.architecture { // i686, i586, etc. Architecture::X86_32(_) => "x86".to_string(), other => other.to_string(), }; let env = target.environment.to_string(); let implementation = match py_impl { PythonImplementation::CPython => python3_dll_a::PythonImplementation::CPython, PythonImplementation::PyPy => python3_dll_a::PythonImplementation::PyPy, PythonImplementation::GraalPy => { return Err(Error::from("No support for GraalPy on Windows")) } }; ImportLibraryGenerator::new(&arch, &env) .version(py_version.map(|v| (v.major, v.minor))) .implementation(implementation) .generate(&out_lib_dir) .context("failed to generate python3.dll import library")?; let out_lib_dir_string = out_lib_dir .to_str() .ok_or("build directory is not a valid UTF-8 string")? .to_owned(); Ok(Some(out_lib_dir_string)) } pyo3-build-config/src/lib.rs0000644000175000017500000002626514661133735016711 0ustar jamespagejamespage//! Configuration used by PyO3 for conditional support of varying Python versions. //! //! This crate exposes functionality to be called from build scripts to simplify building crates //! which depend on PyO3. //! //! It used internally by the PyO3 crate's build script to apply the same configuration. #![warn(elided_lifetimes_in_paths, unused_lifetimes)] mod errors; mod impl_; #[cfg(feature = "resolve-config")] use std::{ io::Cursor, path::{Path, PathBuf}, }; use std::{env, process::Command, str::FromStr}; use once_cell::sync::OnceCell; pub use impl_::{ cross_compiling_from_to, find_all_sysconfigdata, parse_sysconfigdata, BuildFlag, BuildFlags, CrossCompileConfig, InterpreterConfig, PythonImplementation, PythonVersion, Triple, }; use target_lexicon::OperatingSystem; /// Adds all the [`#[cfg]` flags](index.html) to the current compilation. /// /// This should be called from a build script. /// /// The full list of attributes added are the following: /// /// | Flag | Description | /// | ---- | ----------- | /// | `#[cfg(Py_3_7)]`, `#[cfg(Py_3_8)]`, `#[cfg(Py_3_9)]`, `#[cfg(Py_3_10)]` | These attributes mark code only for a given Python version and up. For example, `#[cfg(Py_3_7)]` marks code which can run on Python 3.7 **and newer**. | /// | `#[cfg(Py_LIMITED_API)]` | This marks code which is run when compiling with PyO3's `abi3` feature enabled. | /// | `#[cfg(PyPy)]` | This marks code which is run when compiling for PyPy. | /// | `#[cfg(GraalPy)]` | This marks code which is run when compiling for GraalPy. | /// /// For examples of how to use these attributes, #[doc = concat!("[see PyO3's guide](https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution/multiple_python_versions.html)")] /// . #[cfg(feature = "resolve-config")] pub fn use_pyo3_cfgs() { print_expected_cfgs(); for cargo_command in get().build_script_outputs() { println!("{}", cargo_command) } } /// Adds linker arguments suitable for PyO3's `extension-module` feature. /// /// This should be called from a build script. /// /// The following link flags are added: /// - macOS: `-undefined dynamic_lookup` /// - wasm32-unknown-emscripten: `-sSIDE_MODULE=2 -sWASM_BIGINT` /// /// All other platforms currently are no-ops, however this may change as necessary /// in future. pub fn add_extension_module_link_args() { _add_extension_module_link_args(&impl_::target_triple_from_env(), std::io::stdout()) } fn _add_extension_module_link_args(triple: &Triple, mut writer: impl std::io::Write) { if triple.operating_system == OperatingSystem::Darwin { writeln!(writer, "cargo:rustc-cdylib-link-arg=-undefined").unwrap(); writeln!(writer, "cargo:rustc-cdylib-link-arg=dynamic_lookup").unwrap(); } else if triple == &Triple::from_str("wasm32-unknown-emscripten").unwrap() { writeln!(writer, "cargo:rustc-cdylib-link-arg=-sSIDE_MODULE=2").unwrap(); writeln!(writer, "cargo:rustc-cdylib-link-arg=-sWASM_BIGINT").unwrap(); } } /// Loads the configuration determined from the build environment. /// /// Because this will never change in a given compilation run, this is cached in a `once_cell`. #[cfg(feature = "resolve-config")] pub fn get() -> &'static InterpreterConfig { static CONFIG: OnceCell = OnceCell::new(); CONFIG.get_or_init(|| { // Check if we are in a build script and cross compiling to a different target. let cross_compile_config_path = resolve_cross_compile_config_path(); let cross_compiling = cross_compile_config_path .as_ref() .map(|path| path.exists()) .unwrap_or(false); // CONFIG_FILE is generated in build.rs, so it's content can vary #[allow(unknown_lints, clippy::const_is_empty)] if let Some(interpreter_config) = InterpreterConfig::from_cargo_dep_env() { interpreter_config } else if !CONFIG_FILE.is_empty() { InterpreterConfig::from_reader(Cursor::new(CONFIG_FILE)) } else if cross_compiling { InterpreterConfig::from_path(cross_compile_config_path.as_ref().unwrap()) } else { InterpreterConfig::from_reader(Cursor::new(HOST_CONFIG)) } .expect("failed to parse PyO3 config") }) } /// Build configuration provided by `PYO3_CONFIG_FILE`. May be empty if env var not set. #[doc(hidden)] #[cfg(feature = "resolve-config")] const CONFIG_FILE: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config-file.txt")); /// Build configuration discovered by `pyo3-build-config` build script. Not aware of /// cross-compilation settings. #[doc(hidden)] #[cfg(feature = "resolve-config")] const HOST_CONFIG: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config.txt")); /// Returns the path where PyO3's build.rs writes its cross compile configuration. /// /// The config file will be named `$OUT_DIR//pyo3-build-config.txt`. /// /// Must be called from a build script, returns `None` if not. #[doc(hidden)] #[cfg(feature = "resolve-config")] fn resolve_cross_compile_config_path() -> Option { env::var_os("TARGET").map(|target| { let mut path = PathBuf::from(env!("OUT_DIR")); path.push(Path::new(&target)); path.push("pyo3-build-config.txt"); path }) } /// Use certain features if we detect the compiler being used supports them. /// /// Features may be removed or added as MSRV gets bumped or new features become available, /// so this function is unstable. #[doc(hidden)] pub fn print_feature_cfgs() { let rustc_minor_version = rustc_minor_version().unwrap_or(0); // invalid_from_utf8 lint was added in Rust 1.74 if rustc_minor_version >= 74 { println!("cargo:rustc-cfg=invalid_from_utf8_lint"); } if rustc_minor_version >= 79 { println!("cargo:rustc-cfg=c_str_lit"); } // Actually this is available on 1.78, but we should avoid // https://github.com/rust-lang/rust/issues/124651 just in case if rustc_minor_version >= 79 { println!("cargo:rustc-cfg=diagnostic_namespace"); } } /// Registers `pyo3`s config names as reachable cfg expressions /// /// - /// - #[doc(hidden)] pub fn print_expected_cfgs() { if rustc_minor_version().map_or(false, |version| version < 80) { // rustc 1.80.0 stabilized `rustc-check-cfg` feature, don't emit before return; } println!("cargo:rustc-check-cfg=cfg(Py_LIMITED_API)"); println!("cargo:rustc-check-cfg=cfg(PyPy)"); println!("cargo:rustc-check-cfg=cfg(GraalPy)"); println!("cargo:rustc-check-cfg=cfg(py_sys_config, values(\"Py_DEBUG\", \"Py_REF_DEBUG\", \"Py_TRACE_REFS\", \"COUNT_ALLOCS\"))"); println!("cargo:rustc-check-cfg=cfg(invalid_from_utf8_lint)"); println!("cargo:rustc-check-cfg=cfg(pyo3_disable_reference_pool)"); println!("cargo:rustc-check-cfg=cfg(pyo3_leak_on_drop_without_reference_pool)"); println!("cargo:rustc-check-cfg=cfg(diagnostic_namespace)"); println!("cargo:rustc-check-cfg=cfg(c_str_lit)"); // allow `Py_3_*` cfgs from the minimum supported version up to the // maximum minor version (+1 for development for the next) for i in impl_::MINIMUM_SUPPORTED_VERSION.minor..=impl_::ABI3_MAX_MINOR + 1 { println!("cargo:rustc-check-cfg=cfg(Py_3_{i})"); } } /// Private exports used in PyO3's build.rs /// /// Please don't use these - they could change at any time. #[doc(hidden)] pub mod pyo3_build_script_impl { #[cfg(feature = "resolve-config")] use crate::errors::{Context, Result}; #[cfg(feature = "resolve-config")] use super::*; pub mod errors { pub use crate::errors::*; } pub use crate::impl_::{ cargo_env_var, env_var, is_linking_libpython, make_cross_compile_config, InterpreterConfig, PythonVersion, }; /// Gets the configuration for use from PyO3's build script. /// /// Differs from .get() above only in the cross-compile case, where PyO3's build script is /// required to generate a new config (as it's the first build script which has access to the /// correct value for CARGO_CFG_TARGET_OS). #[cfg(feature = "resolve-config")] pub fn resolve_interpreter_config() -> Result { // CONFIG_FILE is generated in build.rs, so it's content can vary #[allow(unknown_lints, clippy::const_is_empty)] if !CONFIG_FILE.is_empty() { let mut interperter_config = InterpreterConfig::from_reader(Cursor::new(CONFIG_FILE))?; interperter_config.generate_import_libs()?; Ok(interperter_config) } else if let Some(interpreter_config) = make_cross_compile_config()? { // This is a cross compile and need to write the config file. let path = resolve_cross_compile_config_path() .expect("resolve_interpreter_config() must be called from a build script"); let parent_dir = path.parent().ok_or_else(|| { format!( "failed to resolve parent directory of config file {}", path.display() ) })?; std::fs::create_dir_all(parent_dir).with_context(|| { format!( "failed to create config file directory {}", parent_dir.display() ) })?; interpreter_config.to_writer(&mut std::fs::File::create(&path).with_context( || format!("failed to create config file at {}", path.display()), )?)?; Ok(interpreter_config) } else { InterpreterConfig::from_reader(Cursor::new(HOST_CONFIG)) } } } fn rustc_minor_version() -> Option { static RUSTC_MINOR_VERSION: OnceCell> = OnceCell::new(); *RUSTC_MINOR_VERSION.get_or_init(|| { let rustc = env::var_os("RUSTC")?; let output = Command::new(rustc).arg("--version").output().ok()?; let version = core::str::from_utf8(&output.stdout).ok()?; let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } pieces.next()?.parse().ok() }) } #[cfg(test)] mod tests { use super::*; #[test] fn extension_module_link_args() { let mut buf = Vec::new(); // Does nothing on non-mac _add_extension_module_link_args( &Triple::from_str("x86_64-pc-windows-msvc").unwrap(), &mut buf, ); assert_eq!(buf, Vec::new()); _add_extension_module_link_args( &Triple::from_str("x86_64-apple-darwin").unwrap(), &mut buf, ); assert_eq!( std::str::from_utf8(&buf).unwrap(), "cargo:rustc-cdylib-link-arg=-undefined\n\ cargo:rustc-cdylib-link-arg=dynamic_lookup\n" ); buf.clear(); _add_extension_module_link_args( &Triple::from_str("wasm32-unknown-emscripten").unwrap(), &mut buf, ); assert_eq!( std::str::from_utf8(&buf).unwrap(), "cargo:rustc-cdylib-link-arg=-sSIDE_MODULE=2\n\ cargo:rustc-cdylib-link-arg=-sWASM_BIGINT\n" ); } } pyo3-build-config/src/impl_.rs0000644000175000017500000027677414661133735017257 0ustar jamespagejamespage//! Main implementation module included in both the `pyo3-build-config` library crate //! and its build script. // Optional python3.dll import library generator for Windows #[cfg(feature = "python3-dll-a")] #[path = "import_lib.rs"] mod import_lib; use std::{ collections::{HashMap, HashSet}, env, ffi::{OsStr, OsString}, fmt::Display, fs::{self, DirEntry}, io::{BufRead, BufReader, Read, Write}, path::{Path, PathBuf}, process::{Command, Stdio}, str, str::FromStr, }; pub use target_lexicon::Triple; use target_lexicon::{Environment, OperatingSystem}; use crate::{ bail, ensure, errors::{Context, Error, Result}, warn, }; /// Minimum Python version PyO3 supports. pub(crate) const MINIMUM_SUPPORTED_VERSION: PythonVersion = PythonVersion { major: 3, minor: 7 }; /// GraalPy may implement the same CPython version over multiple releases. const MINIMUM_SUPPORTED_VERSION_GRAALPY: PythonVersion = PythonVersion { major: 24, minor: 0, }; /// Maximum Python version that can be used as minimum required Python version with abi3. pub(crate) const ABI3_MAX_MINOR: u8 = 12; /// Gets an environment variable owned by cargo. /// /// Environment variables set by cargo are expected to be valid UTF8. pub fn cargo_env_var(var: &str) -> Option { env::var_os(var).map(|os_string| os_string.to_str().unwrap().into()) } /// Gets an external environment variable, and registers the build script to rerun if /// the variable changes. pub fn env_var(var: &str) -> Option { if cfg!(feature = "resolve-config") { println!("cargo:rerun-if-env-changed={}", var); } env::var_os(var) } /// Gets the compilation target triple from environment variables set by Cargo. /// /// Must be called from a crate build script. pub fn target_triple_from_env() -> Triple { env::var("TARGET") .expect("target_triple_from_env() must be called from a build script") .parse() .expect("Unrecognized TARGET environment variable value") } /// Configuration needed by PyO3 to build for the correct Python implementation. /// /// Usually this is queried directly from the Python interpreter, or overridden using the /// `PYO3_CONFIG_FILE` environment variable. /// /// When the `PYO3_NO_PYTHON` variable is set, or during cross compile situations, then alternative /// strategies are used to populate this type. #[cfg_attr(test, derive(Debug, PartialEq, Eq))] pub struct InterpreterConfig { /// The Python implementation flavor. /// /// Serialized to `implementation`. pub implementation: PythonImplementation, /// Python `X.Y` version. e.g. `3.9`. /// /// Serialized to `version`. pub version: PythonVersion, /// Whether link library is shared. /// /// Serialized to `shared`. pub shared: bool, /// Whether linking against the stable/limited Python 3 API. /// /// Serialized to `abi3`. pub abi3: bool, /// The name of the link library defining Python. /// /// This effectively controls the `cargo:rustc-link-lib=` value to /// control how libpython is linked. Values should not contain the `lib` /// prefix. /// /// Serialized to `lib_name`. pub lib_name: Option, /// The directory containing the Python library to link against. /// /// The effectively controls the `cargo:rustc-link-search=native=` value /// to add an additional library search path for the linker. /// /// Serialized to `lib_dir`. pub lib_dir: Option, /// Path of host `python` executable. /// /// This is a valid executable capable of running on the host/building machine. /// For configurations derived by invoking a Python interpreter, it was the /// executable invoked. /// /// Serialized to `executable`. pub executable: Option, /// Width in bits of pointers on the target machine. /// /// Serialized to `pointer_width`. pub pointer_width: Option, /// Additional relevant Python build flags / configuration settings. /// /// Serialized to `build_flags`. pub build_flags: BuildFlags, /// Whether to suppress emitting of `cargo:rustc-link-*` lines from the build script. /// /// Typically, `pyo3`'s build script will emit `cargo:rustc-link-lib=` and /// `cargo:rustc-link-search=` lines derived from other fields in this struct. In /// advanced building configurations, the default logic to derive these lines may not /// be sufficient. This field can be set to `Some(true)` to suppress the emission /// of these lines. /// /// If suppression is enabled, `extra_build_script_lines` should contain equivalent /// functionality or else a build failure is likely. pub suppress_build_script_link_lines: bool, /// Additional lines to `println!()` from Cargo build scripts. /// /// This field can be populated to enable the `pyo3` crate to emit additional lines from its /// its Cargo build script. /// /// This crate doesn't populate this field itself. Rather, it is intended to be used with /// externally provided config files to give them significant control over how the crate /// is build/configured. /// /// Serialized to multiple `extra_build_script_line` values. pub extra_build_script_lines: Vec, } impl InterpreterConfig { #[doc(hidden)] pub fn build_script_outputs(&self) -> Vec { // This should have been checked during pyo3-build-config build time. assert!(self.version >= MINIMUM_SUPPORTED_VERSION); let mut out = vec![]; // pyo3-build-config was released when Python 3.6 was supported, so minimum flag to emit is // Py_3_6 (to avoid silently breaking users who depend on this cfg). for i in 6..=self.version.minor { out.push(format!("cargo:rustc-cfg=Py_3_{}", i)); } match self.implementation { PythonImplementation::CPython => {} PythonImplementation::PyPy => out.push("cargo:rustc-cfg=PyPy".to_owned()), PythonImplementation::GraalPy => out.push("cargo:rustc-cfg=GraalPy".to_owned()), } if self.abi3 { out.push("cargo:rustc-cfg=Py_LIMITED_API".to_owned()); } for flag in &self.build_flags.0 { out.push(format!("cargo:rustc-cfg=py_sys_config=\"{}\"", flag)); } out } #[doc(hidden)] pub fn from_interpreter(interpreter: impl AsRef) -> Result { const SCRIPT: &str = r#" # Allow the script to run on Python 2, so that nicer error can be printed later. from __future__ import print_function import os.path import platform import struct import sys from sysconfig import get_config_var, get_platform PYPY = platform.python_implementation() == "PyPy" GRAALPY = platform.python_implementation() == "GraalVM" if GRAALPY: graalpy_ver = map(int, __graalpython__.get_graalvm_version().split('.')); print("graalpy_major", next(graalpy_ver)) print("graalpy_minor", next(graalpy_ver)) # sys.base_prefix is missing on Python versions older than 3.3; this allows the script to continue # so that the version mismatch can be reported in a nicer way later. base_prefix = getattr(sys, "base_prefix", None) if base_prefix: # Anaconda based python distributions have a static python executable, but include # the shared library. Use the shared library for embedding to avoid rust trying to # LTO the static library (and failing with newer gcc's, because it is old). ANACONDA = os.path.exists(os.path.join(base_prefix, "conda-meta")) else: ANACONDA = False def print_if_set(varname, value): if value is not None: print(varname, value) # Windows always uses shared linking WINDOWS = platform.system() == "Windows" # macOS framework packages use shared linking FRAMEWORK = bool(get_config_var("PYTHONFRAMEWORK")) # unix-style shared library enabled SHARED = bool(get_config_var("Py_ENABLE_SHARED")) print("implementation", platform.python_implementation()) print("version_major", sys.version_info[0]) print("version_minor", sys.version_info[1]) print("shared", PYPY or GRAALPY or ANACONDA or WINDOWS or FRAMEWORK or SHARED) print_if_set("ld_version", get_config_var("LDVERSION")) print_if_set("libdir", get_config_var("LIBDIR")) print_if_set("base_prefix", base_prefix) print("executable", sys.executable) print("calcsize_pointer", struct.calcsize("P")) print("mingw", get_platform().startswith("mingw")) print("ext_suffix", get_config_var("EXT_SUFFIX")) "#; let output = run_python_script(interpreter.as_ref(), SCRIPT)?; let map: HashMap = parse_script_output(&output); ensure!( !map.is_empty(), "broken Python interpreter: {}", interpreter.as_ref().display() ); if let Some(value) = map.get("graalpy_major") { let graalpy_version = PythonVersion { major: value .parse() .context("failed to parse GraalPy major version")?, minor: map["graalpy_minor"] .parse() .context("failed to parse GraalPy minor version")?, }; ensure!( graalpy_version >= MINIMUM_SUPPORTED_VERSION_GRAALPY, "At least GraalPy version {} needed, got {}", MINIMUM_SUPPORTED_VERSION_GRAALPY, graalpy_version ); }; let shared = map["shared"].as_str() == "True"; let version = PythonVersion { major: map["version_major"] .parse() .context("failed to parse major version")?, minor: map["version_minor"] .parse() .context("failed to parse minor version")?, }; let abi3 = is_abi3(); let implementation = map["implementation"].parse()?; let lib_name = if cfg!(windows) { default_lib_name_windows( version, implementation, abi3, map["mingw"].as_str() == "True", // This is the best heuristic currently available to detect debug build // on Windows from sysconfig - e.g. ext_suffix may be // `_d.cp312-win_amd64.pyd` for 3.12 debug build map["ext_suffix"].starts_with("_d."), ) } else { default_lib_name_unix( version, implementation, map.get("ld_version").map(String::as_str), ) }; let lib_dir = if cfg!(windows) { map.get("base_prefix") .map(|base_prefix| format!("{}\\libs", base_prefix)) } else { map.get("libdir").cloned() }; // The reason we don't use platform.architecture() here is that it's not // reliable on macOS. See https://stackoverflow.com/a/1405971/823869. // Similarly, sys.maxsize is not reliable on Windows. See // https://stackoverflow.com/questions/1405913/how-do-i-determine-if-my-python-shell-is-executing-in-32bit-or-64bit-mode-on-os/1405971#comment6209952_1405971 // and https://stackoverflow.com/a/3411134/823869. let calcsize_pointer: u32 = map["calcsize_pointer"] .parse() .context("failed to parse calcsize_pointer")?; Ok(InterpreterConfig { version, implementation, shared, abi3, lib_name: Some(lib_name), lib_dir, executable: map.get("executable").cloned(), pointer_width: Some(calcsize_pointer * 8), build_flags: BuildFlags::from_interpreter(interpreter)?, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }) } /// Generate from parsed sysconfigdata file /// /// Use [`parse_sysconfigdata`] to generate a hash map of configuration values which may be /// used to build an [`InterpreterConfig`]. pub fn from_sysconfigdata(sysconfigdata: &Sysconfigdata) -> Result { macro_rules! get_key { ($sysconfigdata:expr, $key:literal) => { $sysconfigdata .get_value($key) .ok_or(concat!($key, " not found in sysconfigdata file")) }; } macro_rules! parse_key { ($sysconfigdata:expr, $key:literal) => { get_key!($sysconfigdata, $key)? .parse() .context(concat!("could not parse value of ", $key)) }; } let soabi = get_key!(sysconfigdata, "SOABI")?; let implementation = PythonImplementation::from_soabi(soabi)?; let version = parse_key!(sysconfigdata, "VERSION")?; let shared = match sysconfigdata.get_value("Py_ENABLE_SHARED") { Some("1") | Some("true") | Some("True") => true, Some("0") | Some("false") | Some("False") => false, _ => bail!("expected a bool (1/true/True or 0/false/False) for Py_ENABLE_SHARED"), }; // macOS framework packages use shared linking (PYTHONFRAMEWORK is the framework name, hence the empty check) let framework = match sysconfigdata.get_value("PYTHONFRAMEWORK") { Some(s) => !s.is_empty(), _ => false, }; let lib_dir = get_key!(sysconfigdata, "LIBDIR").ok().map(str::to_string); let lib_name = Some(default_lib_name_unix( version, implementation, sysconfigdata.get_value("LDVERSION"), )); let pointer_width = parse_key!(sysconfigdata, "SIZEOF_VOID_P") .map(|bytes_width: u32| bytes_width * 8) .ok(); let build_flags = BuildFlags::from_sysconfigdata(sysconfigdata); Ok(InterpreterConfig { implementation, version, shared: shared || framework, abi3: is_abi3(), lib_dir, lib_name, executable: None, pointer_width, build_flags, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }) } #[doc(hidden)] pub fn from_path(path: impl AsRef) -> Result { let path = path.as_ref(); let config_file = std::fs::File::open(path) .with_context(|| format!("failed to open PyO3 config file at {}", path.display()))?; let reader = std::io::BufReader::new(config_file); InterpreterConfig::from_reader(reader) } #[doc(hidden)] pub fn from_cargo_dep_env() -> Option> { cargo_env_var("DEP_PYTHON_PYO3_CONFIG") .map(|buf| InterpreterConfig::from_reader(&*unescape(&buf))) } #[doc(hidden)] pub fn from_reader(reader: impl Read) -> Result { let reader = BufReader::new(reader); let lines = reader.lines(); macro_rules! parse_value { ($variable:ident, $value:ident) => { $variable = Some($value.trim().parse().context(format!( concat!( "failed to parse ", stringify!($variable), " from config value '{}'" ), $value ))?) }; } let mut implementation = None; let mut version = None; let mut shared = None; let mut abi3 = None; let mut lib_name = None; let mut lib_dir = None; let mut executable = None; let mut pointer_width = None; let mut build_flags = None; let mut suppress_build_script_link_lines = None; let mut extra_build_script_lines = vec![]; for (i, line) in lines.enumerate() { let line = line.context("failed to read line from config")?; let mut split = line.splitn(2, '='); let (key, value) = ( split .next() .expect("first splitn value should always be present"), split .next() .ok_or_else(|| format!("expected key=value pair on line {}", i + 1))?, ); match key { "implementation" => parse_value!(implementation, value), "version" => parse_value!(version, value), "shared" => parse_value!(shared, value), "abi3" => parse_value!(abi3, value), "lib_name" => parse_value!(lib_name, value), "lib_dir" => parse_value!(lib_dir, value), "executable" => parse_value!(executable, value), "pointer_width" => parse_value!(pointer_width, value), "build_flags" => parse_value!(build_flags, value), "suppress_build_script_link_lines" => { parse_value!(suppress_build_script_link_lines, value) } "extra_build_script_line" => { extra_build_script_lines.push(value.to_string()); } unknown => warn!("unknown config key `{}`", unknown), } } let version = version.ok_or("missing value for version")?; let implementation = implementation.unwrap_or(PythonImplementation::CPython); let abi3 = abi3.unwrap_or(false); // Fixup lib_name if it's not set let lib_name = lib_name.or_else(|| { if let Ok(Ok(target)) = env::var("TARGET").map(|target| target.parse::()) { default_lib_name_for_target(version, implementation, abi3, &target) } else { None } }); Ok(InterpreterConfig { implementation, version, shared: shared.unwrap_or(true), abi3, lib_name, lib_dir, executable, pointer_width, build_flags: build_flags.unwrap_or_default(), suppress_build_script_link_lines: suppress_build_script_link_lines.unwrap_or(false), extra_build_script_lines, }) } #[cfg(feature = "python3-dll-a")] #[allow(clippy::unnecessary_wraps)] pub fn generate_import_libs(&mut self) -> Result<()> { // Auto generate python3.dll import libraries for Windows targets. if self.lib_dir.is_none() { let target = target_triple_from_env(); let py_version = if self.abi3 { None } else { Some(self.version) }; self.lib_dir = import_lib::generate_import_lib(&target, self.implementation, py_version)?; } Ok(()) } #[cfg(not(feature = "python3-dll-a"))] #[allow(clippy::unnecessary_wraps)] pub fn generate_import_libs(&mut self) -> Result<()> { Ok(()) } #[doc(hidden)] /// Serialize the `InterpreterConfig` and print it to the environment for Cargo to pass along /// to dependent packages during build time. /// /// NB: writing to the cargo environment requires the /// [`links`](https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key) /// manifest key to be set. In this case that means this is called by the `pyo3-ffi` crate and /// available for dependent package build scripts in `DEP_PYTHON_PYO3_CONFIG`. See /// documentation for the /// [`DEP__`](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts) /// environment variable. pub fn to_cargo_dep_env(&self) -> Result<()> { let mut buf = Vec::new(); self.to_writer(&mut buf)?; // escape newlines in env var println!("cargo:PYO3_CONFIG={}", escape(&buf)); Ok(()) } #[doc(hidden)] pub fn to_writer(&self, mut writer: impl Write) -> Result<()> { macro_rules! write_line { ($value:ident) => { writeln!(writer, "{}={}", stringify!($value), self.$value).context(concat!( "failed to write ", stringify!($value), " to config" )) }; } macro_rules! write_option_line { ($value:ident) => { if let Some(value) = &self.$value { writeln!(writer, "{}={}", stringify!($value), value).context(concat!( "failed to write ", stringify!($value), " to config" )) } else { Ok(()) } }; } write_line!(implementation)?; write_line!(version)?; write_line!(shared)?; write_line!(abi3)?; write_option_line!(lib_name)?; write_option_line!(lib_dir)?; write_option_line!(executable)?; write_option_line!(pointer_width)?; write_line!(build_flags)?; write_line!(suppress_build_script_link_lines)?; for line in &self.extra_build_script_lines { writeln!(writer, "extra_build_script_line={}", line) .context("failed to write extra_build_script_line")?; } Ok(()) } /// Run a python script using the [`InterpreterConfig::executable`]. /// /// # Panics /// /// This function will panic if the [`executable`](InterpreterConfig::executable) is `None`. pub fn run_python_script(&self, script: &str) -> Result { run_python_script_with_envs( Path::new(self.executable.as_ref().expect("no interpreter executable")), script, std::iter::empty::<(&str, &str)>(), ) } /// Run a python script using the [`InterpreterConfig::executable`] with additional /// environment variables (e.g. PYTHONPATH) set. /// /// # Panics /// /// This function will panic if the [`executable`](InterpreterConfig::executable) is `None`. pub fn run_python_script_with_envs(&self, script: &str, envs: I) -> Result where I: IntoIterator, K: AsRef, V: AsRef, { run_python_script_with_envs( Path::new(self.executable.as_ref().expect("no interpreter executable")), script, envs, ) } /// Lowers the configured version to the abi3 version, if set. fn fixup_for_abi3_version(&mut self, abi3_version: Option) -> Result<()> { // PyPy doesn't support abi3; don't adjust the version if self.implementation.is_pypy() || self.implementation.is_graalpy() { return Ok(()); } if let Some(version) = abi3_version { ensure!( version <= self.version, "cannot set a minimum Python version {} higher than the interpreter version {} \ (the minimum Python version is implied by the abi3-py3{} feature)", version, self.version, version.minor, ); self.version = version; } Ok(()) } } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct PythonVersion { pub major: u8, pub minor: u8, } impl PythonVersion { const PY37: Self = PythonVersion { major: 3, minor: 7 }; } impl Display for PythonVersion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}.{}", self.major, self.minor) } } impl FromStr for PythonVersion { type Err = crate::errors::Error; fn from_str(value: &str) -> Result { let mut split = value.splitn(2, '.'); let (major, minor) = ( split .next() .expect("first splitn value should always be present"), split.next().ok_or("expected major.minor version")?, ); Ok(Self { major: major.parse().context("failed to parse major version")?, minor: minor.parse().context("failed to parse minor version")?, }) } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum PythonImplementation { CPython, PyPy, GraalPy, } impl PythonImplementation { #[doc(hidden)] pub fn is_pypy(self) -> bool { self == PythonImplementation::PyPy } #[doc(hidden)] pub fn is_graalpy(self) -> bool { self == PythonImplementation::GraalPy } #[doc(hidden)] pub fn from_soabi(soabi: &str) -> Result { if soabi.starts_with("pypy") { Ok(PythonImplementation::PyPy) } else if soabi.starts_with("cpython") { Ok(PythonImplementation::CPython) } else if soabi.starts_with("graalpy") { Ok(PythonImplementation::GraalPy) } else { bail!("unsupported Python interpreter"); } } } impl Display for PythonImplementation { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { PythonImplementation::CPython => write!(f, "CPython"), PythonImplementation::PyPy => write!(f, "PyPy"), PythonImplementation::GraalPy => write!(f, "GraalVM"), } } } impl FromStr for PythonImplementation { type Err = Error; fn from_str(s: &str) -> Result { match s { "CPython" => Ok(PythonImplementation::CPython), "PyPy" => Ok(PythonImplementation::PyPy), "GraalVM" => Ok(PythonImplementation::GraalPy), _ => bail!("unknown interpreter: {}", s), } } } /// Checks if we should look for a Python interpreter installation /// to get the target interpreter configuration. /// /// Returns `false` if `PYO3_NO_PYTHON` environment variable is set. fn have_python_interpreter() -> bool { env_var("PYO3_NO_PYTHON").is_none() } /// Checks if `abi3` or any of the `abi3-py3*` features is enabled for the PyO3 crate. /// /// Must be called from a PyO3 crate build script. fn is_abi3() -> bool { cargo_env_var("CARGO_FEATURE_ABI3").is_some() || env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").map_or(false, |os_str| os_str == "1") } /// Gets the minimum supported Python version from PyO3 `abi3-py*` features. /// /// Must be called from a PyO3 crate build script. pub fn get_abi3_version() -> Option { let minor_version = (MINIMUM_SUPPORTED_VERSION.minor..=ABI3_MAX_MINOR) .find(|i| cargo_env_var(&format!("CARGO_FEATURE_ABI3_PY3{}", i)).is_some()); minor_version.map(|minor| PythonVersion { major: 3, minor }) } /// Checks if the `extension-module` feature is enabled for the PyO3 crate. /// /// Must be called from a PyO3 crate build script. pub fn is_extension_module() -> bool { cargo_env_var("CARGO_FEATURE_EXTENSION_MODULE").is_some() } /// Checks if we need to link to `libpython` for the current build target. /// /// Must be called from a PyO3 crate build script. pub fn is_linking_libpython() -> bool { is_linking_libpython_for_target(&target_triple_from_env()) } /// Checks if we need to link to `libpython` for the target. /// /// Must be called from a PyO3 crate build script. fn is_linking_libpython_for_target(target: &Triple) -> bool { target.operating_system == OperatingSystem::Windows // See https://github.com/PyO3/pyo3/issues/4068#issuecomment-2051159852 || target.operating_system == OperatingSystem::Aix || target.environment == Environment::Android || target.environment == Environment::Androideabi || !is_extension_module() } /// Checks if we need to discover the Python library directory /// to link the extension module binary. /// /// Must be called from a PyO3 crate build script. fn require_libdir_for_target(target: &Triple) -> bool { let is_generating_libpython = cfg!(feature = "python3-dll-a") && target.operating_system == OperatingSystem::Windows && is_abi3(); is_linking_libpython_for_target(target) && !is_generating_libpython } /// Configuration needed by PyO3 to cross-compile for a target platform. /// /// Usually this is collected from the environment (i.e. `PYO3_CROSS_*` and `CARGO_CFG_TARGET_*`) /// when a cross-compilation configuration is detected. #[derive(Debug, PartialEq, Eq)] pub struct CrossCompileConfig { /// The directory containing the Python library to link against. pub lib_dir: Option, /// The version of the Python library to link against. version: Option, /// The target Python implementation hint (CPython, PyPy, GraalPy, ...) implementation: Option, /// The compile target triple (e.g. aarch64-unknown-linux-gnu) target: Triple, } impl CrossCompileConfig { /// Creates a new cross compile config struct from PyO3 environment variables /// and the build environment when cross compilation mode is detected. /// /// Returns `None` when not cross compiling. fn try_from_env_vars_host_target( env_vars: CrossCompileEnvVars, host: &Triple, target: &Triple, ) -> Result> { if env_vars.any() || Self::is_cross_compiling_from_to(host, target) { let lib_dir = env_vars.lib_dir_path()?; let version = env_vars.parse_version()?; let implementation = env_vars.parse_implementation()?; let target = target.clone(); Ok(Some(CrossCompileConfig { lib_dir, version, implementation, target, })) } else { Ok(None) } } /// Checks if compiling on `host` for `target` required "real" cross compilation. /// /// Returns `false` if the target Python interpreter can run on the host. fn is_cross_compiling_from_to(host: &Triple, target: &Triple) -> bool { // Not cross-compiling if arch-vendor-os is all the same // e.g. x86_64-unknown-linux-musl on x86_64-unknown-linux-gnu host // x86_64-pc-windows-gnu on x86_64-pc-windows-msvc host let mut compatible = host.architecture == target.architecture && host.vendor == target.vendor && host.operating_system == target.operating_system; // Not cross-compiling to compile for 32-bit Python from windows 64-bit compatible |= target.operating_system == OperatingSystem::Windows && host.operating_system == OperatingSystem::Windows; // Not cross-compiling to compile for x86-64 Python from macOS arm64 and vice versa compatible |= target.operating_system == OperatingSystem::Darwin && host.operating_system == OperatingSystem::Darwin; !compatible } /// Converts `lib_dir` member field to an UTF-8 string. /// /// The conversion can not fail because `PYO3_CROSS_LIB_DIR` variable /// is ensured contain a valid UTF-8 string. fn lib_dir_string(&self) -> Option { self.lib_dir .as_ref() .map(|s| s.to_str().unwrap().to_owned()) } } /// PyO3-specific cross compile environment variable values struct CrossCompileEnvVars { /// `PYO3_CROSS` pyo3_cross: Option, /// `PYO3_CROSS_LIB_DIR` pyo3_cross_lib_dir: Option, /// `PYO3_CROSS_PYTHON_VERSION` pyo3_cross_python_version: Option, /// `PYO3_CROSS_PYTHON_IMPLEMENTATION` pyo3_cross_python_implementation: Option, } impl CrossCompileEnvVars { /// Grabs the PyO3 cross-compile variables from the environment. /// /// Registers the build script to rerun if any of the variables changes. fn from_env() -> Self { CrossCompileEnvVars { pyo3_cross: env_var("PYO3_CROSS"), pyo3_cross_lib_dir: env_var("PYO3_CROSS_LIB_DIR"), pyo3_cross_python_version: env_var("PYO3_CROSS_PYTHON_VERSION"), pyo3_cross_python_implementation: env_var("PYO3_CROSS_PYTHON_IMPLEMENTATION"), } } /// Checks if any of the variables is set. fn any(&self) -> bool { self.pyo3_cross.is_some() || self.pyo3_cross_lib_dir.is_some() || self.pyo3_cross_python_version.is_some() || self.pyo3_cross_python_implementation.is_some() } /// Parses `PYO3_CROSS_PYTHON_VERSION` environment variable value /// into `PythonVersion`. fn parse_version(&self) -> Result> { let version = self .pyo3_cross_python_version .as_ref() .map(|os_string| { let utf8_str = os_string .to_str() .ok_or("PYO3_CROSS_PYTHON_VERSION is not valid a UTF-8 string")?; utf8_str .parse() .context("failed to parse PYO3_CROSS_PYTHON_VERSION") }) .transpose()?; Ok(version) } /// Parses `PYO3_CROSS_PYTHON_IMPLEMENTATION` environment variable value /// into `PythonImplementation`. fn parse_implementation(&self) -> Result> { let implementation = self .pyo3_cross_python_implementation .as_ref() .map(|os_string| { let utf8_str = os_string .to_str() .ok_or("PYO3_CROSS_PYTHON_IMPLEMENTATION is not valid a UTF-8 string")?; utf8_str .parse() .context("failed to parse PYO3_CROSS_PYTHON_IMPLEMENTATION") }) .transpose()?; Ok(implementation) } /// Converts the stored `PYO3_CROSS_LIB_DIR` variable value (if any) /// into a `PathBuf` instance. /// /// Ensures that the path is a valid UTF-8 string. fn lib_dir_path(&self) -> Result> { let lib_dir = self.pyo3_cross_lib_dir.as_ref().map(PathBuf::from); if let Some(dir) = lib_dir.as_ref() { ensure!( dir.to_str().is_some(), "PYO3_CROSS_LIB_DIR variable value is not a valid UTF-8 string" ); } Ok(lib_dir) } } /// Detect whether we are cross compiling and return an assembled CrossCompileConfig if so. /// /// This function relies on PyO3 cross-compiling environment variables: /// /// * `PYO3_CROSS`: If present, forces PyO3 to configure as a cross-compilation. /// * `PYO3_CROSS_LIB_DIR`: If present, must be set to the directory containing /// the target's libpython DSO and the associated `_sysconfigdata*.py` file for /// Unix-like targets, or the Python DLL import libraries for the Windows target. /// * `PYO3_CROSS_PYTHON_VERSION`: Major and minor version (e.g. 3.9) of the target Python /// installation. This variable is only needed if PyO3 cannnot determine the version to target /// from `abi3-py3*` features, or if there are multiple versions of Python present in /// `PYO3_CROSS_LIB_DIR`. /// /// See the [PyO3 User Guide](https://pyo3.rs/) for more info on cross-compiling. pub fn cross_compiling_from_to( host: &Triple, target: &Triple, ) -> Result> { let env_vars = CrossCompileEnvVars::from_env(); CrossCompileConfig::try_from_env_vars_host_target(env_vars, host, target) } /// Detect whether we are cross compiling from Cargo and `PYO3_CROSS_*` environment /// variables and return an assembled `CrossCompileConfig` if so. /// /// This must be called from PyO3's build script, because it relies on environment /// variables such as `CARGO_CFG_TARGET_OS` which aren't available at any other time. pub fn cross_compiling_from_cargo_env() -> Result> { let env_vars = CrossCompileEnvVars::from_env(); let host = Triple::host(); let target = target_triple_from_env(); CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target) } #[allow(non_camel_case_types)] #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum BuildFlag { Py_DEBUG, Py_REF_DEBUG, Py_TRACE_REFS, COUNT_ALLOCS, Other(String), } impl Display for BuildFlag { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { BuildFlag::Other(flag) => write!(f, "{}", flag), _ => write!(f, "{:?}", self), } } } impl FromStr for BuildFlag { type Err = std::convert::Infallible; fn from_str(s: &str) -> Result { match s { "Py_DEBUG" => Ok(BuildFlag::Py_DEBUG), "Py_REF_DEBUG" => Ok(BuildFlag::Py_REF_DEBUG), "Py_TRACE_REFS" => Ok(BuildFlag::Py_TRACE_REFS), "COUNT_ALLOCS" => Ok(BuildFlag::COUNT_ALLOCS), other => Ok(BuildFlag::Other(other.to_owned())), } } } /// A list of python interpreter compile-time preprocessor defines that /// we will pick up and pass to rustc via `--cfg=py_sys_config={varname}`; /// this allows using them conditional cfg attributes in the .rs files, so /// /// ```rust /// #[cfg(py_sys_config="{varname}")] /// # struct Foo; /// ``` /// /// is the equivalent of `#ifdef {varname}` in C. /// /// see Misc/SpecialBuilds.txt in the python source for what these mean. #[cfg_attr(test, derive(Debug, PartialEq, Eq))] #[derive(Clone, Default)] pub struct BuildFlags(pub HashSet); impl BuildFlags { const ALL: [BuildFlag; 4] = [ BuildFlag::Py_DEBUG, BuildFlag::Py_REF_DEBUG, BuildFlag::Py_TRACE_REFS, BuildFlag::COUNT_ALLOCS, ]; pub fn new() -> Self { BuildFlags(HashSet::new()) } fn from_sysconfigdata(config_map: &Sysconfigdata) -> Self { Self( BuildFlags::ALL .iter() .filter(|flag| { config_map .get_value(flag.to_string()) .map_or(false, |value| value == "1") }) .cloned() .collect(), ) .fixup() } /// Examine python's compile flags to pass to cfg by launching /// the interpreter and printing variables of interest from /// sysconfig.get_config_vars. fn from_interpreter(interpreter: impl AsRef) -> Result { // sysconfig is missing all the flags on windows, so we can't actually // query the interpreter directly for its build flags. if cfg!(windows) { return Ok(Self::new()); } let mut script = String::from("import sysconfig\n"); script.push_str("config = sysconfig.get_config_vars()\n"); for k in &BuildFlags::ALL { use std::fmt::Write; writeln!(&mut script, "print(config.get('{}', '0'))", k).unwrap(); } let stdout = run_python_script(interpreter.as_ref(), &script)?; let split_stdout: Vec<&str> = stdout.trim_end().lines().collect(); ensure!( split_stdout.len() == BuildFlags::ALL.len(), "Python stdout len didn't return expected number of lines: {}", split_stdout.len() ); let flags = BuildFlags::ALL .iter() .zip(split_stdout) .filter(|(_, flag_value)| *flag_value == "1") .map(|(flag, _)| flag.clone()) .collect(); Ok(Self(flags).fixup()) } fn fixup(mut self) -> Self { if self.0.contains(&BuildFlag::Py_DEBUG) { self.0.insert(BuildFlag::Py_REF_DEBUG); } self } } impl Display for BuildFlags { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut first = true; for flag in &self.0 { if first { first = false; } else { write!(f, ",")?; } write!(f, "{}", flag)?; } Ok(()) } } impl FromStr for BuildFlags { type Err = std::convert::Infallible; fn from_str(value: &str) -> Result { let mut flags = HashSet::new(); for flag in value.split_terminator(',') { flags.insert(flag.parse().unwrap()); } Ok(BuildFlags(flags)) } } fn parse_script_output(output: &str) -> HashMap { output .lines() .filter_map(|line| { let mut i = line.splitn(2, ' '); Some((i.next()?.into(), i.next()?.into())) }) .collect() } /// Parsed data from Python sysconfigdata file /// /// A hash map of all values from a sysconfigdata file. pub struct Sysconfigdata(HashMap); impl Sysconfigdata { pub fn get_value>(&self, k: S) -> Option<&str> { self.0.get(k.as_ref()).map(String::as_str) } #[allow(dead_code)] fn new() -> Self { Sysconfigdata(HashMap::new()) } #[allow(dead_code)] fn insert>(&mut self, k: S, v: S) { self.0.insert(k.into(), v.into()); } } /// Parse sysconfigdata file /// /// The sysconfigdata is simply a dictionary containing all the build time variables used for the /// python executable and library. This function necessitates a python interpreter on the host /// machine to work. Here it is read into a `Sysconfigdata` (hash map), which can be turned into an /// [`InterpreterConfig`] using /// [`from_sysconfigdata`](InterpreterConfig::from_sysconfigdata). pub fn parse_sysconfigdata(sysconfigdata_path: impl AsRef) -> Result { let sysconfigdata_path = sysconfigdata_path.as_ref(); let mut script = fs::read_to_string(sysconfigdata_path).with_context(|| { format!( "failed to read config from {}", sysconfigdata_path.display() ) })?; script += r#" for key, val in build_time_vars.items(): print(key, val) "#; let output = run_python_script(&find_interpreter()?, &script)?; Ok(Sysconfigdata(parse_script_output(&output))) } fn starts_with(entry: &DirEntry, pat: &str) -> bool { let name = entry.file_name(); name.to_string_lossy().starts_with(pat) } fn ends_with(entry: &DirEntry, pat: &str) -> bool { let name = entry.file_name(); name.to_string_lossy().ends_with(pat) } /// Finds the sysconfigdata file when the target Python library directory is set. /// /// Returns `None` if the library directory is not available, and a runtime error /// when no or multiple sysconfigdata files are found. fn find_sysconfigdata(cross: &CrossCompileConfig) -> Result> { let mut sysconfig_paths = find_all_sysconfigdata(cross)?; if sysconfig_paths.is_empty() { if let Some(lib_dir) = cross.lib_dir.as_ref() { bail!("Could not find _sysconfigdata*.py in {}", lib_dir.display()); } else { // Continue with the default configuration when PYO3_CROSS_LIB_DIR is not set. return Ok(None); } } else if sysconfig_paths.len() > 1 { let mut error_msg = String::from( "Detected multiple possible Python versions. Please set either the \ PYO3_CROSS_PYTHON_VERSION variable to the wanted version or the \ _PYTHON_SYSCONFIGDATA_NAME variable to the wanted sysconfigdata file name.\n\n\ sysconfigdata files found:", ); for path in sysconfig_paths { use std::fmt::Write; write!(&mut error_msg, "\n\t{}", path.display()).unwrap(); } bail!("{}\n", error_msg); } Ok(Some(sysconfig_paths.remove(0))) } /// Finds `_sysconfigdata*.py` files for detected Python interpreters. /// /// From the python source for `_sysconfigdata*.py` is always going to be located at /// `build/lib.{PLATFORM}-{PY_MINOR_VERSION}` when built from source. The [exact line][1] is defined as: /// /// ```py /// pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version_info[:2]) /// ``` /// /// Where get_platform returns a kebab-case formatted string containing the os, the architecture and /// possibly the os' kernel version (not the case on linux). However, when installed using a package /// manager, the `_sysconfigdata*.py` file is installed in the `${PREFIX}/lib/python3.Y/` directory. /// The `_sysconfigdata*.py` is generally in a sub-directory of the location of `libpython3.Y.so`. /// So we must find the file in the following possible locations: /// /// ```sh /// # distribution from package manager, (lib_dir may or may not include lib/) /// ${INSTALL_PREFIX}/lib/python3.Y/_sysconfigdata*.py /// ${INSTALL_PREFIX}/lib/libpython3.Y.so /// ${INSTALL_PREFIX}/lib/python3.Y/config-3.Y-${HOST_TRIPLE}/libpython3.Y.so /// /// # Built from source from host /// ${CROSS_COMPILED_LOCATION}/build/lib.linux-x86_64-Y/_sysconfigdata*.py /// ${CROSS_COMPILED_LOCATION}/libpython3.Y.so /// /// # if cross compiled, kernel release is only present on certain OS targets. /// ${CROSS_COMPILED_LOCATION}/build/lib.{OS}(-{OS-KERNEL-RELEASE})?-{ARCH}-Y/_sysconfigdata*.py /// ${CROSS_COMPILED_LOCATION}/libpython3.Y.so /// /// # PyPy includes a similar file since v73 /// ${INSTALL_PREFIX}/lib/pypy3.Y/_sysconfigdata.py /// ${INSTALL_PREFIX}/lib_pypy/_sysconfigdata.py /// ``` /// /// [1]: https://github.com/python/cpython/blob/3.5/Lib/sysconfig.py#L389 /// /// Returns an empty vector when the target Python library directory /// is not set via `PYO3_CROSS_LIB_DIR`. pub fn find_all_sysconfigdata(cross: &CrossCompileConfig) -> Result> { let sysconfig_paths = if let Some(lib_dir) = cross.lib_dir.as_ref() { search_lib_dir(lib_dir, cross).with_context(|| { format!( "failed to search the lib dir at 'PYO3_CROSS_LIB_DIR={}'", lib_dir.display() ) })? } else { return Ok(Vec::new()); }; let sysconfig_name = env_var("_PYTHON_SYSCONFIGDATA_NAME"); let mut sysconfig_paths = sysconfig_paths .iter() .filter_map(|p| { let canonical = fs::canonicalize(p).ok(); match &sysconfig_name { Some(_) => canonical.filter(|p| p.file_stem() == sysconfig_name.as_deref()), None => canonical, } }) .collect::>(); sysconfig_paths.sort(); sysconfig_paths.dedup(); Ok(sysconfig_paths) } fn is_pypy_lib_dir(path: &str, v: &Option) -> bool { let pypy_version_pat = if let Some(v) = v { format!("pypy{}", v) } else { "pypy3.".into() }; path == "lib_pypy" || path.starts_with(&pypy_version_pat) } fn is_graalpy_lib_dir(path: &str, v: &Option) -> bool { let graalpy_version_pat = if let Some(v) = v { format!("graalpy{}", v) } else { "graalpy2".into() }; path == "lib_graalpython" || path.starts_with(&graalpy_version_pat) } fn is_cpython_lib_dir(path: &str, v: &Option) -> bool { let cpython_version_pat = if let Some(v) = v { format!("python{}", v) } else { "python3.".into() }; path.starts_with(&cpython_version_pat) } /// recursive search for _sysconfigdata, returns all possibilities of sysconfigdata paths fn search_lib_dir(path: impl AsRef, cross: &CrossCompileConfig) -> Result> { let mut sysconfig_paths = vec![]; for f in fs::read_dir(path.as_ref()).with_context(|| { format!( "failed to list the entries in '{}'", path.as_ref().display() ) })? { sysconfig_paths.extend(match &f { // Python 3.7+ sysconfigdata with platform specifics Ok(f) if starts_with(f, "_sysconfigdata_") && ends_with(f, "py") => vec![f.path()], Ok(f) if f.metadata().map_or(false, |metadata| metadata.is_dir()) => { let file_name = f.file_name(); let file_name = file_name.to_string_lossy(); if file_name == "build" || file_name == "lib" { search_lib_dir(f.path(), cross)? } else if file_name.starts_with("lib.") { // check if right target os if !file_name.contains(&cross.target.operating_system.to_string()) { continue; } // Check if right arch if !file_name.contains(&cross.target.architecture.to_string()) { continue; } search_lib_dir(f.path(), cross)? } else if is_cpython_lib_dir(&file_name, &cross.version) || is_pypy_lib_dir(&file_name, &cross.version) || is_graalpy_lib_dir(&file_name, &cross.version) { search_lib_dir(f.path(), cross)? } else { continue; } } _ => continue, }); } // If we got more than one file, only take those that contain the arch name. // For ubuntu 20.04 with host architecture x86_64 and a foreign architecture of armhf // this reduces the number of candidates to 1: // // $ find /usr/lib/python3.8/ -name '_sysconfigdata*.py' -not -lname '*' // /usr/lib/python3.8/_sysconfigdata__x86_64-linux-gnu.py // /usr/lib/python3.8/_sysconfigdata__arm-linux-gnueabihf.py if sysconfig_paths.len() > 1 { let temp = sysconfig_paths .iter() .filter(|p| { p.to_string_lossy() .contains(&cross.target.architecture.to_string()) }) .cloned() .collect::>(); if !temp.is_empty() { sysconfig_paths = temp; } } Ok(sysconfig_paths) } /// Find cross compilation information from sysconfigdata file /// /// first find sysconfigdata file which follows the pattern [`_sysconfigdata_{abi}_{platform}_{multiarch}`][1] /// /// [1]: https://github.com/python/cpython/blob/3.8/Lib/sysconfig.py#L348 /// /// Returns `None` when the target Python library directory is not set. fn cross_compile_from_sysconfigdata( cross_compile_config: &CrossCompileConfig, ) -> Result> { if let Some(path) = find_sysconfigdata(cross_compile_config)? { let data = parse_sysconfigdata(path)?; let config = InterpreterConfig::from_sysconfigdata(&data)?; Ok(Some(config)) } else { Ok(None) } } /// Generates "default" cross compilation information for the target. /// /// This should work for most CPython extension modules when targeting /// Windows, macOS and Linux. /// /// Must be called from a PyO3 crate build script. #[allow(unused_mut)] fn default_cross_compile(cross_compile_config: &CrossCompileConfig) -> Result { let version = cross_compile_config .version .or_else(get_abi3_version) .ok_or_else(|| format!( "PYO3_CROSS_PYTHON_VERSION or an abi3-py3* feature must be specified \ when cross-compiling and PYO3_CROSS_LIB_DIR is not set.\n\ = help: see the PyO3 user guide for more information: https://pyo3.rs/v{}/building-and-distribution.html#cross-compiling", env!("CARGO_PKG_VERSION") ) )?; let abi3 = is_abi3(); let implementation = cross_compile_config .implementation .unwrap_or(PythonImplementation::CPython); let lib_name = default_lib_name_for_target(version, implementation, abi3, &cross_compile_config.target); let mut lib_dir = cross_compile_config.lib_dir_string(); // Auto generate python3.dll import libraries for Windows targets. #[cfg(feature = "python3-dll-a")] if lib_dir.is_none() { let py_version = if abi3 { None } else { Some(version) }; lib_dir = self::import_lib::generate_import_lib( &cross_compile_config.target, cross_compile_config .implementation .unwrap_or(PythonImplementation::CPython), py_version, )?; } Ok(InterpreterConfig { implementation, version, shared: true, abi3, lib_name, lib_dir, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }) } /// Generates "default" interpreter configuration when compiling "abi3" extensions /// without a working Python interpreter. /// /// `version` specifies the minimum supported Stable ABI CPython version. /// /// This should work for most CPython extension modules when compiling on /// Windows, macOS and Linux. /// /// Must be called from a PyO3 crate build script. fn default_abi3_config(host: &Triple, version: PythonVersion) -> InterpreterConfig { // FIXME: PyPy & GraalPy do not support the Stable ABI. let implementation = PythonImplementation::CPython; let abi3 = true; let lib_name = if host.operating_system == OperatingSystem::Windows { Some(default_lib_name_windows( version, implementation, abi3, false, false, )) } else { None }; InterpreterConfig { implementation, version, shared: true, abi3, lib_name, lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } } /// Detects the cross compilation target interpreter configuration from all /// available sources (PyO3 environment variables, Python sysconfigdata, etc.). /// /// Returns the "default" target interpreter configuration for Windows and /// when no target Python interpreter is found. /// /// Must be called from a PyO3 crate build script. fn load_cross_compile_config( cross_compile_config: CrossCompileConfig, ) -> Result { let windows = cross_compile_config.target.operating_system == OperatingSystem::Windows; let config = if windows || !have_python_interpreter() { // Load the defaults for Windows even when `PYO3_CROSS_LIB_DIR` is set // since it has no sysconfigdata files in it. // Also, do not try to look for sysconfigdata when `PYO3_NO_PYTHON` variable is set. default_cross_compile(&cross_compile_config)? } else if let Some(config) = cross_compile_from_sysconfigdata(&cross_compile_config)? { // Try to find and parse sysconfigdata files on other targets. config } else { // Fall back to the defaults when nothing else can be done. default_cross_compile(&cross_compile_config)? }; if config.lib_name.is_some() && config.lib_dir.is_none() { warn!( "The output binary will link to libpython, \ but PYO3_CROSS_LIB_DIR environment variable is not set. \ Ensure that the target Python library directory is \ in the rustc native library search path." ); } Ok(config) } // Link against python3.lib for the stable ABI on Windows. // See https://www.python.org/dev/peps/pep-0384/#linkage // // This contains only the limited ABI symbols. const WINDOWS_ABI3_LIB_NAME: &str = "python3"; fn default_lib_name_for_target( version: PythonVersion, implementation: PythonImplementation, abi3: bool, target: &Triple, ) -> Option { if target.operating_system == OperatingSystem::Windows { Some(default_lib_name_windows( version, implementation, abi3, false, false, )) } else if is_linking_libpython_for_target(target) { Some(default_lib_name_unix(version, implementation, None)) } else { None } } fn default_lib_name_windows( version: PythonVersion, implementation: PythonImplementation, abi3: bool, mingw: bool, debug: bool, ) -> String { if debug { // CPython bug: linking against python3_d.dll raises error // https://github.com/python/cpython/issues/101614 format!("python{}{}_d", version.major, version.minor) } else if abi3 && !(implementation.is_pypy() || implementation.is_graalpy()) { WINDOWS_ABI3_LIB_NAME.to_owned() } else if mingw { // https://packages.msys2.org/base/mingw-w64-python format!("python{}.{}", version.major, version.minor) } else { format!("python{}{}", version.major, version.minor) } } fn default_lib_name_unix( version: PythonVersion, implementation: PythonImplementation, ld_version: Option<&str>, ) -> String { match implementation { PythonImplementation::CPython => match ld_version { Some(ld_version) => format!("python{}", ld_version), None => { if version > PythonVersion::PY37 { // PEP 3149 ABI version tags are finally gone format!("python{}.{}", version.major, version.minor) } else { // Work around https://bugs.python.org/issue36707 format!("python{}.{}m", version.major, version.minor) } } }, PythonImplementation::PyPy => { if version >= (PythonVersion { major: 3, minor: 9 }) { match ld_version { Some(ld_version) => format!("pypy{}-c", ld_version), None => format!("pypy{}.{}-c", version.major, version.minor), } } else { format!("pypy{}-c", version.major) } } PythonImplementation::GraalPy => "python-native".to_string(), } } /// Run a python script using the specified interpreter binary. fn run_python_script(interpreter: &Path, script: &str) -> Result { run_python_script_with_envs(interpreter, script, std::iter::empty::<(&str, &str)>()) } /// Run a python script using the specified interpreter binary with additional environment /// variables (e.g. PYTHONPATH) set. fn run_python_script_with_envs(interpreter: &Path, script: &str, envs: I) -> Result where I: IntoIterator, K: AsRef, V: AsRef, { let out = Command::new(interpreter) .env("PYTHONIOENCODING", "utf-8") .envs(envs) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::inherit()) .spawn() .and_then(|mut child| { child .stdin .as_mut() .expect("piped stdin") .write_all(script.as_bytes())?; child.wait_with_output() }); match out { Err(err) => bail!( "failed to run the Python interpreter at {}: {}", interpreter.display(), err ), Ok(ok) if !ok.status.success() => bail!("Python script failed"), Ok(ok) => Ok(String::from_utf8(ok.stdout) .context("failed to parse Python script output as utf-8")?), } } fn venv_interpreter(virtual_env: &OsStr, windows: bool) -> PathBuf { if windows { Path::new(virtual_env).join("Scripts").join("python.exe") } else { Path::new(virtual_env).join("bin").join("python") } } fn conda_env_interpreter(conda_prefix: &OsStr, windows: bool) -> PathBuf { if windows { Path::new(conda_prefix).join("python.exe") } else { Path::new(conda_prefix).join("bin").join("python") } } fn get_env_interpreter() -> Option { match (env_var("VIRTUAL_ENV"), env_var("CONDA_PREFIX")) { // Use cfg rather than CARGO_CFG_TARGET_OS because this affects where files are located on the // build host (Some(dir), None) => Some(venv_interpreter(&dir, cfg!(windows))), (None, Some(dir)) => Some(conda_env_interpreter(&dir, cfg!(windows))), (Some(_), Some(_)) => { warn!( "Both VIRTUAL_ENV and CONDA_PREFIX are set. PyO3 will ignore both of these for \ locating the Python interpreter until you unset one of them." ); None } (None, None) => None, } } /// Attempts to locate a python interpreter. /// /// Locations are checked in the order listed: /// 1. If `PYO3_PYTHON` is set, this interpreter is used. /// 2. If in a virtualenv, that environment's interpreter is used. /// 3. `python`, if this is functional a Python 3.x interpreter /// 4. `python3`, as above pub fn find_interpreter() -> Result { // Trigger rebuilds when `PYO3_ENVIRONMENT_SIGNATURE` env var value changes // See https://github.com/PyO3/pyo3/issues/2724 println!("cargo:rerun-if-env-changed=PYO3_ENVIRONMENT_SIGNATURE"); if let Some(exe) = env_var("PYO3_PYTHON") { Ok(exe.into()) } else if let Some(env_interpreter) = get_env_interpreter() { Ok(env_interpreter) } else { println!("cargo:rerun-if-env-changed=PATH"); ["python", "python3"] .iter() .find(|bin| { if let Ok(out) = Command::new(bin).arg("--version").output() { // begin with `Python 3.X.X :: additional info` out.stdout.starts_with(b"Python 3") || out.stderr.starts_with(b"Python 3") || out.stdout.starts_with(b"GraalPy 3") } else { false } }) .map(PathBuf::from) .ok_or_else(|| "no Python 3.x interpreter found".into()) } } /// Locates and extracts the build host Python interpreter configuration. /// /// Lowers the configured Python version to `abi3_version` if required. fn get_host_interpreter(abi3_version: Option) -> Result { let interpreter_path = find_interpreter()?; let mut interpreter_config = InterpreterConfig::from_interpreter(interpreter_path)?; interpreter_config.fixup_for_abi3_version(abi3_version)?; Ok(interpreter_config) } /// Generates an interpreter config suitable for cross-compilation. /// /// This must be called from PyO3's build script, because it relies on environment variables such as /// CARGO_CFG_TARGET_OS which aren't available at any other time. pub fn make_cross_compile_config() -> Result> { let interpreter_config = if let Some(cross_config) = cross_compiling_from_cargo_env()? { let mut interpreter_config = load_cross_compile_config(cross_config)?; interpreter_config.fixup_for_abi3_version(get_abi3_version())?; Some(interpreter_config) } else { None }; Ok(interpreter_config) } /// Generates an interpreter config which will be hard-coded into the pyo3-build-config crate. /// Only used by `pyo3-build-config` build script. #[allow(dead_code, unused_mut)] pub fn make_interpreter_config() -> Result { let host = Triple::host(); let abi3_version = get_abi3_version(); // See if we can safely skip the Python interpreter configuration detection. // Unix "abi3" extension modules can usually be built without any interpreter. let need_interpreter = abi3_version.is_none() || require_libdir_for_target(&host); if have_python_interpreter() { match get_host_interpreter(abi3_version) { Ok(interpreter_config) => return Ok(interpreter_config), // Bail if the interpreter configuration is required to build. Err(e) if need_interpreter => return Err(e), _ => { // Fall back to the "abi3" defaults just as if `PYO3_NO_PYTHON` // environment variable was set. warn!("Compiling without a working Python interpreter."); } } } else { ensure!( abi3_version.is_some(), "An abi3-py3* feature must be specified when compiling without a Python interpreter." ); }; let mut interpreter_config = default_abi3_config(&host, abi3_version.unwrap()); // Auto generate python3.dll import libraries for Windows targets. #[cfg(feature = "python3-dll-a")] { let py_version = if interpreter_config.abi3 { None } else { Some(interpreter_config.version) }; interpreter_config.lib_dir = self::import_lib::generate_import_lib( &host, interpreter_config.implementation, py_version, )?; } Ok(interpreter_config) } fn escape(bytes: &[u8]) -> String { let mut escaped = String::with_capacity(2 * bytes.len()); for byte in bytes { const LUT: &[u8; 16] = b"0123456789abcdef"; escaped.push(LUT[(byte >> 4) as usize] as char); escaped.push(LUT[(byte & 0x0F) as usize] as char); } escaped } fn unescape(escaped: &str) -> Vec { assert!(escaped.len() % 2 == 0, "invalid hex encoding"); let mut bytes = Vec::with_capacity(escaped.len() / 2); for chunk in escaped.as_bytes().chunks_exact(2) { fn unhex(hex: u8) -> u8 { match hex { b'a'..=b'f' => hex - b'a' + 10, b'0'..=b'9' => hex - b'0', _ => panic!("invalid hex encoding"), } } bytes.push(unhex(chunk[0]) << 4 | unhex(chunk[1])); } bytes } #[cfg(test)] mod tests { use target_lexicon::triple; use super::*; #[test] fn test_config_file_roundtrip() { let config = InterpreterConfig { abi3: true, build_flags: BuildFlags::default(), pointer_width: Some(32), executable: Some("executable".into()), implementation: PythonImplementation::CPython, lib_name: Some("lib_name".into()), lib_dir: Some("lib_dir".into()), shared: true, version: MINIMUM_SUPPORTED_VERSION, suppress_build_script_link_lines: true, extra_build_script_lines: vec!["cargo:test1".to_string(), "cargo:test2".to_string()], }; let mut buf: Vec = Vec::new(); config.to_writer(&mut buf).unwrap(); assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap()); // And some different options, for variety let config = InterpreterConfig { abi3: false, build_flags: { let mut flags = HashSet::new(); flags.insert(BuildFlag::Py_DEBUG); flags.insert(BuildFlag::Other(String::from("Py_SOME_FLAG"))); BuildFlags(flags) }, pointer_width: None, executable: None, implementation: PythonImplementation::PyPy, lib_dir: None, lib_name: None, shared: true, version: PythonVersion { major: 3, minor: 10, }, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }; let mut buf: Vec = Vec::new(); config.to_writer(&mut buf).unwrap(); assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap()); } #[test] fn test_config_file_roundtrip_with_escaping() { let config = InterpreterConfig { abi3: true, build_flags: BuildFlags::default(), pointer_width: Some(32), executable: Some("executable".into()), implementation: PythonImplementation::CPython, lib_name: Some("lib_name".into()), lib_dir: Some("lib_dir\\n".into()), shared: true, version: MINIMUM_SUPPORTED_VERSION, suppress_build_script_link_lines: true, extra_build_script_lines: vec!["cargo:test1".to_string(), "cargo:test2".to_string()], }; let mut buf: Vec = Vec::new(); config.to_writer(&mut buf).unwrap(); let buf = unescape(&escape(&buf)); assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap()); } #[test] fn test_config_file_defaults() { // Only version is required assert_eq!( InterpreterConfig::from_reader("version=3.7".as_bytes()).unwrap(), InterpreterConfig { version: PythonVersion { major: 3, minor: 7 }, implementation: PythonImplementation::CPython, shared: true, abi3: false, lib_name: None, lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ) } #[test] fn test_config_file_unknown_keys() { // ext_suffix is unknown to pyo3-build-config, but it shouldn't error assert_eq!( InterpreterConfig::from_reader("version=3.7\next_suffix=.python37.so".as_bytes()) .unwrap(), InterpreterConfig { version: PythonVersion { major: 3, minor: 7 }, implementation: PythonImplementation::CPython, shared: true, abi3: false, lib_name: None, lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ) } #[test] fn build_flags_default() { assert_eq!(BuildFlags::default(), BuildFlags::new()); } #[test] fn build_flags_from_sysconfigdata() { let mut sysconfigdata = Sysconfigdata::new(); assert_eq!( BuildFlags::from_sysconfigdata(&sysconfigdata).0, HashSet::new() ); for flag in &BuildFlags::ALL { sysconfigdata.insert(flag.to_string(), "0".into()); } assert_eq!( BuildFlags::from_sysconfigdata(&sysconfigdata).0, HashSet::new() ); let mut expected_flags = HashSet::new(); for flag in &BuildFlags::ALL { sysconfigdata.insert(flag.to_string(), "1".into()); expected_flags.insert(flag.clone()); } assert_eq!( BuildFlags::from_sysconfigdata(&sysconfigdata).0, expected_flags ); } #[test] fn build_flags_fixup() { let mut build_flags = BuildFlags::new(); build_flags = build_flags.fixup(); assert!(build_flags.0.is_empty()); build_flags.0.insert(BuildFlag::Py_DEBUG); build_flags = build_flags.fixup(); // Py_DEBUG implies Py_REF_DEBUG assert!(build_flags.0.contains(&BuildFlag::Py_REF_DEBUG)); } #[test] fn parse_script_output() { let output = "foo bar\nbar foobar\n\n"; let map = super::parse_script_output(output); assert_eq!(map.len(), 2); assert_eq!(map["foo"], "bar"); assert_eq!(map["bar"], "foobar"); } #[test] fn config_from_interpreter() { // Smoke test to just see whether this works // // PyO3's CI is dependent on Python being installed, so this should be reliable. assert!(make_interpreter_config().is_ok()) } #[test] fn config_from_empty_sysconfigdata() { let sysconfigdata = Sysconfigdata::new(); assert!(InterpreterConfig::from_sysconfigdata(&sysconfigdata).is_err()); } #[test] fn config_from_sysconfigdata() { let mut sysconfigdata = Sysconfigdata::new(); // these are the minimal values required such that InterpreterConfig::from_sysconfigdata // does not error sysconfigdata.insert("SOABI", "cpython-37m-x86_64-linux-gnu"); sysconfigdata.insert("VERSION", "3.7"); sysconfigdata.insert("Py_ENABLE_SHARED", "1"); sysconfigdata.insert("LIBDIR", "/usr/lib"); sysconfigdata.insert("LDVERSION", "3.7m"); sysconfigdata.insert("SIZEOF_VOID_P", "8"); assert_eq!( InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(), InterpreterConfig { abi3: false, build_flags: BuildFlags::from_sysconfigdata(&sysconfigdata), pointer_width: Some(64), executable: None, implementation: PythonImplementation::CPython, lib_dir: Some("/usr/lib".into()), lib_name: Some("python3.7m".into()), shared: true, version: PythonVersion::PY37, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn config_from_sysconfigdata_framework() { let mut sysconfigdata = Sysconfigdata::new(); sysconfigdata.insert("SOABI", "cpython-37m-x86_64-linux-gnu"); sysconfigdata.insert("VERSION", "3.7"); // PYTHONFRAMEWORK should override Py_ENABLE_SHARED sysconfigdata.insert("Py_ENABLE_SHARED", "0"); sysconfigdata.insert("PYTHONFRAMEWORK", "Python"); sysconfigdata.insert("LIBDIR", "/usr/lib"); sysconfigdata.insert("LDVERSION", "3.7m"); sysconfigdata.insert("SIZEOF_VOID_P", "8"); assert_eq!( InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(), InterpreterConfig { abi3: false, build_flags: BuildFlags::from_sysconfigdata(&sysconfigdata), pointer_width: Some(64), executable: None, implementation: PythonImplementation::CPython, lib_dir: Some("/usr/lib".into()), lib_name: Some("python3.7m".into()), shared: true, version: PythonVersion::PY37, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); sysconfigdata = Sysconfigdata::new(); sysconfigdata.insert("SOABI", "cpython-37m-x86_64-linux-gnu"); sysconfigdata.insert("VERSION", "3.7"); // An empty PYTHONFRAMEWORK means it is not a framework sysconfigdata.insert("Py_ENABLE_SHARED", "0"); sysconfigdata.insert("PYTHONFRAMEWORK", ""); sysconfigdata.insert("LIBDIR", "/usr/lib"); sysconfigdata.insert("LDVERSION", "3.7m"); sysconfigdata.insert("SIZEOF_VOID_P", "8"); assert_eq!( InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(), InterpreterConfig { abi3: false, build_flags: BuildFlags::from_sysconfigdata(&sysconfigdata), pointer_width: Some(64), executable: None, implementation: PythonImplementation::CPython, lib_dir: Some("/usr/lib".into()), lib_name: Some("python3.7m".into()), shared: false, version: PythonVersion::PY37, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn windows_hardcoded_abi3_compile() { let host = triple!("x86_64-pc-windows-msvc"); let min_version = "3.7".parse().unwrap(); assert_eq!( default_abi3_config(&host, min_version), InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 7 }, shared: true, abi3: true, lib_name: Some("python3".into()), lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn unix_hardcoded_abi3_compile() { let host = triple!("x86_64-unknown-linux-gnu"); let min_version = "3.9".parse().unwrap(); assert_eq!( default_abi3_config(&host, min_version), InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 9 }, shared: true, abi3: true, lib_name: None, lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn windows_hardcoded_cross_compile() { let env_vars = CrossCompileEnvVars { pyo3_cross: None, pyo3_cross_lib_dir: Some("C:\\some\\path".into()), pyo3_cross_python_implementation: None, pyo3_cross_python_version: Some("3.7".into()), }; let host = triple!("x86_64-unknown-linux-gnu"); let target = triple!("i686-pc-windows-msvc"); let cross_config = CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target) .unwrap() .unwrap(); assert_eq!( default_cross_compile(&cross_config).unwrap(), InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 7 }, shared: true, abi3: false, lib_name: Some("python37".into()), lib_dir: Some("C:\\some\\path".into()), executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn mingw_hardcoded_cross_compile() { let env_vars = CrossCompileEnvVars { pyo3_cross: None, pyo3_cross_lib_dir: Some("/usr/lib/mingw".into()), pyo3_cross_python_implementation: None, pyo3_cross_python_version: Some("3.8".into()), }; let host = triple!("x86_64-unknown-linux-gnu"); let target = triple!("i686-pc-windows-gnu"); let cross_config = CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target) .unwrap() .unwrap(); assert_eq!( default_cross_compile(&cross_config).unwrap(), InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 8 }, shared: true, abi3: false, lib_name: Some("python38".into()), lib_dir: Some("/usr/lib/mingw".into()), executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn unix_hardcoded_cross_compile() { let env_vars = CrossCompileEnvVars { pyo3_cross: None, pyo3_cross_lib_dir: Some("/usr/arm64/lib".into()), pyo3_cross_python_implementation: None, pyo3_cross_python_version: Some("3.9".into()), }; let host = triple!("x86_64-unknown-linux-gnu"); let target = triple!("aarch64-unknown-linux-gnu"); let cross_config = CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target) .unwrap() .unwrap(); assert_eq!( default_cross_compile(&cross_config).unwrap(), InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 9 }, shared: true, abi3: false, lib_name: Some("python3.9".into()), lib_dir: Some("/usr/arm64/lib".into()), executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn pypy_hardcoded_cross_compile() { let env_vars = CrossCompileEnvVars { pyo3_cross: None, pyo3_cross_lib_dir: None, pyo3_cross_python_implementation: Some("PyPy".into()), pyo3_cross_python_version: Some("3.10".into()), }; let triple = triple!("x86_64-unknown-linux-gnu"); let cross_config = CrossCompileConfig::try_from_env_vars_host_target(env_vars, &triple, &triple) .unwrap() .unwrap(); assert_eq!( default_cross_compile(&cross_config).unwrap(), InterpreterConfig { implementation: PythonImplementation::PyPy, version: PythonVersion { major: 3, minor: 10 }, shared: true, abi3: false, lib_name: Some("pypy3.10-c".into()), lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ); } #[test] fn default_lib_name_windows() { use PythonImplementation::*; assert_eq!( super::default_lib_name_windows( PythonVersion { major: 3, minor: 7 }, CPython, false, false, false, ), "python37", ); assert_eq!( super::default_lib_name_windows( PythonVersion { major: 3, minor: 7 }, CPython, true, false, false, ), "python3", ); assert_eq!( super::default_lib_name_windows( PythonVersion { major: 3, minor: 7 }, CPython, false, true, false, ), "python3.7", ); assert_eq!( super::default_lib_name_windows( PythonVersion { major: 3, minor: 7 }, CPython, true, true, false, ), "python3", ); assert_eq!( super::default_lib_name_windows( PythonVersion { major: 3, minor: 7 }, PyPy, true, false, false, ), "python37", ); assert_eq!( super::default_lib_name_windows( PythonVersion { major: 3, minor: 7 }, CPython, false, false, true, ), "python37_d", ); // abi3 debug builds on windows use version-specific lib // to workaround https://github.com/python/cpython/issues/101614 assert_eq!( super::default_lib_name_windows( PythonVersion { major: 3, minor: 7 }, CPython, true, false, true, ), "python37_d", ); } #[test] fn default_lib_name_unix() { use PythonImplementation::*; // Defaults to python3.7m for CPython 3.7 assert_eq!( super::default_lib_name_unix(PythonVersion { major: 3, minor: 7 }, CPython, None), "python3.7m", ); // Defaults to pythonX.Y for CPython 3.8+ assert_eq!( super::default_lib_name_unix(PythonVersion { major: 3, minor: 8 }, CPython, None), "python3.8", ); assert_eq!( super::default_lib_name_unix(PythonVersion { major: 3, minor: 9 }, CPython, None), "python3.9", ); // Can use ldversion to override for CPython assert_eq!( super::default_lib_name_unix( PythonVersion { major: 3, minor: 9 }, CPython, Some("3.7md") ), "python3.7md", ); // PyPy 3.7 ignores ldversion assert_eq!( super::default_lib_name_unix(PythonVersion { major: 3, minor: 7 }, PyPy, Some("3.7md")), "pypy3-c", ); // PyPy 3.9 includes ldversion assert_eq!( super::default_lib_name_unix(PythonVersion { major: 3, minor: 9 }, PyPy, Some("3.9d")), "pypy3.9d-c", ); } #[test] fn parse_cross_python_version() { let env_vars = CrossCompileEnvVars { pyo3_cross: None, pyo3_cross_lib_dir: None, pyo3_cross_python_version: Some("3.9".into()), pyo3_cross_python_implementation: None, }; assert_eq!( env_vars.parse_version().unwrap(), Some(PythonVersion { major: 3, minor: 9 }) ); let env_vars = CrossCompileEnvVars { pyo3_cross: None, pyo3_cross_lib_dir: None, pyo3_cross_python_version: None, pyo3_cross_python_implementation: None, }; assert_eq!(env_vars.parse_version().unwrap(), None); let env_vars = CrossCompileEnvVars { pyo3_cross: None, pyo3_cross_lib_dir: None, pyo3_cross_python_version: Some("100".into()), pyo3_cross_python_implementation: None, }; assert!(env_vars.parse_version().is_err()); } #[test] fn interpreter_version_reduced_to_abi3() { let mut config = InterpreterConfig { abi3: true, build_flags: BuildFlags::default(), pointer_width: None, executable: None, implementation: PythonImplementation::CPython, lib_dir: None, lib_name: None, shared: true, version: PythonVersion { major: 3, minor: 7 }, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }; config .fixup_for_abi3_version(Some(PythonVersion { major: 3, minor: 7 })) .unwrap(); assert_eq!(config.version, PythonVersion { major: 3, minor: 7 }); } #[test] fn abi3_version_cannot_be_higher_than_interpreter() { let mut config = InterpreterConfig { abi3: true, build_flags: BuildFlags::new(), pointer_width: None, executable: None, implementation: PythonImplementation::CPython, lib_dir: None, lib_name: None, shared: true, version: PythonVersion { major: 3, minor: 7 }, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }; assert!(config .fixup_for_abi3_version(Some(PythonVersion { major: 3, minor: 8 })) .unwrap_err() .to_string() .contains( "cannot set a minimum Python version 3.8 higher than the interpreter version 3.7" )); } #[test] #[cfg(all( target_os = "linux", target_arch = "x86_64", feature = "resolve-config" ))] fn parse_sysconfigdata() { // A best effort attempt to get test coverage for the sysconfigdata parsing. // Might not complete successfully depending on host installation; that's ok as long as // CI demonstrates this path is covered! let interpreter_config = crate::get(); let lib_dir = match &interpreter_config.lib_dir { Some(lib_dir) => Path::new(lib_dir), // Don't know where to search for sysconfigdata; never mind. None => return, }; let cross = CrossCompileConfig { lib_dir: Some(lib_dir.into()), version: Some(interpreter_config.version), implementation: Some(interpreter_config.implementation), target: triple!("x86_64-unknown-linux-gnu"), }; let sysconfigdata_path = match find_sysconfigdata(&cross) { Ok(Some(path)) => path, // Couldn't find a matching sysconfigdata; never mind! _ => return, }; let sysconfigdata = super::parse_sysconfigdata(sysconfigdata_path).unwrap(); let parsed_config = InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(); assert_eq!( parsed_config, InterpreterConfig { abi3: false, build_flags: BuildFlags(interpreter_config.build_flags.0.clone()), pointer_width: Some(64), executable: None, implementation: PythonImplementation::CPython, lib_dir: interpreter_config.lib_dir.to_owned(), lib_name: interpreter_config.lib_name.to_owned(), shared: true, version: interpreter_config.version, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], } ) } #[test] fn test_venv_interpreter() { let base = OsStr::new("base"); assert_eq!( venv_interpreter(base, true), PathBuf::from_iter(&["base", "Scripts", "python.exe"]) ); assert_eq!( venv_interpreter(base, false), PathBuf::from_iter(&["base", "bin", "python"]) ); } #[test] fn test_conda_env_interpreter() { let base = OsStr::new("base"); assert_eq!( conda_env_interpreter(base, true), PathBuf::from_iter(&["base", "python.exe"]) ); assert_eq!( conda_env_interpreter(base, false), PathBuf::from_iter(&["base", "bin", "python"]) ); } #[test] fn test_not_cross_compiling_from_to() { assert!(cross_compiling_from_to( &triple!("x86_64-unknown-linux-gnu"), &triple!("x86_64-unknown-linux-gnu"), ) .unwrap() .is_none()); assert!(cross_compiling_from_to( &triple!("x86_64-apple-darwin"), &triple!("x86_64-apple-darwin") ) .unwrap() .is_none()); assert!(cross_compiling_from_to( &triple!("aarch64-apple-darwin"), &triple!("x86_64-apple-darwin") ) .unwrap() .is_none()); assert!(cross_compiling_from_to( &triple!("x86_64-apple-darwin"), &triple!("aarch64-apple-darwin") ) .unwrap() .is_none()); assert!(cross_compiling_from_to( &triple!("x86_64-pc-windows-msvc"), &triple!("i686-pc-windows-msvc") ) .unwrap() .is_none()); assert!(cross_compiling_from_to( &triple!("x86_64-unknown-linux-gnu"), &triple!("x86_64-unknown-linux-musl") ) .unwrap() .is_none()); } #[test] fn test_run_python_script() { // as above, this should be okay in CI where Python is presumed installed let interpreter = make_interpreter_config() .expect("could not get InterpreterConfig from installed interpreter"); let out = interpreter .run_python_script("print(2 + 2)") .expect("failed to run Python script"); assert_eq!(out.trim_end(), "4"); } #[test] fn test_run_python_script_with_envs() { // as above, this should be okay in CI where Python is presumed installed let interpreter = make_interpreter_config() .expect("could not get InterpreterConfig from installed interpreter"); let out = interpreter .run_python_script_with_envs( "import os; print(os.getenv('PYO3_TEST'))", vec![("PYO3_TEST", "42")], ) .expect("failed to run Python script"); assert_eq!(out.trim_end(), "42"); } #[test] fn test_build_script_outputs_base() { let interpreter_config = InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 8 }, shared: true, abi3: false, lib_name: Some("python3".into()), lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }; assert_eq!( interpreter_config.build_script_outputs(), [ "cargo:rustc-cfg=Py_3_6".to_owned(), "cargo:rustc-cfg=Py_3_7".to_owned(), "cargo:rustc-cfg=Py_3_8".to_owned(), ] ); let interpreter_config = InterpreterConfig { implementation: PythonImplementation::PyPy, ..interpreter_config }; assert_eq!( interpreter_config.build_script_outputs(), [ "cargo:rustc-cfg=Py_3_6".to_owned(), "cargo:rustc-cfg=Py_3_7".to_owned(), "cargo:rustc-cfg=Py_3_8".to_owned(), "cargo:rustc-cfg=PyPy".to_owned(), ] ); } #[test] fn test_build_script_outputs_abi3() { let interpreter_config = InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 7 }, shared: true, abi3: true, lib_name: Some("python3".into()), lib_dir: None, executable: None, pointer_width: None, build_flags: BuildFlags::default(), suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }; assert_eq!( interpreter_config.build_script_outputs(), [ "cargo:rustc-cfg=Py_3_6".to_owned(), "cargo:rustc-cfg=Py_3_7".to_owned(), "cargo:rustc-cfg=Py_LIMITED_API".to_owned(), ] ); let interpreter_config = InterpreterConfig { implementation: PythonImplementation::PyPy, ..interpreter_config }; assert_eq!( interpreter_config.build_script_outputs(), [ "cargo:rustc-cfg=Py_3_6".to_owned(), "cargo:rustc-cfg=Py_3_7".to_owned(), "cargo:rustc-cfg=PyPy".to_owned(), "cargo:rustc-cfg=Py_LIMITED_API".to_owned(), ] ); } #[test] fn test_build_script_outputs_debug() { let mut build_flags = BuildFlags::default(); build_flags.0.insert(BuildFlag::Py_DEBUG); let interpreter_config = InterpreterConfig { implementation: PythonImplementation::CPython, version: PythonVersion { major: 3, minor: 7 }, shared: true, abi3: false, lib_name: Some("python3".into()), lib_dir: None, executable: None, pointer_width: None, build_flags, suppress_build_script_link_lines: false, extra_build_script_lines: vec![], }; assert_eq!( interpreter_config.build_script_outputs(), [ "cargo:rustc-cfg=Py_3_6".to_owned(), "cargo:rustc-cfg=Py_3_7".to_owned(), "cargo:rustc-cfg=py_sys_config=\"Py_DEBUG\"".to_owned(), ] ); } #[test] fn test_find_sysconfigdata_in_invalid_lib_dir() { let e = find_all_sysconfigdata(&CrossCompileConfig { lib_dir: Some(PathBuf::from("/abc/123/not/a/real/path")), version: None, implementation: None, target: triple!("x86_64-unknown-linux-gnu"), }) .unwrap_err(); // actual error message is platform-dependent, so just check the context we add assert!(e.report().to_string().starts_with( "failed to search the lib dir at 'PYO3_CROSS_LIB_DIR=/abc/123/not/a/real/path'\n\ caused by:\n \ - 0: failed to list the entries in '/abc/123/not/a/real/path'\n \ - 1: \ " )); } } pyo3-build-config/src/errors.rs0000644000175000017500000000752014661133735017450 0ustar jamespagejamespage/// A simple macro for returning an error. Resembles anyhow::bail. #[macro_export] #[doc(hidden)] macro_rules! bail { ($($args: tt)+) => { return Err(format!($($args)+).into()) }; } /// A simple macro for checking a condition. Resembles anyhow::ensure. #[macro_export] #[doc(hidden)] macro_rules! ensure { ($condition:expr, $($args: tt)+) => { if !($condition) { bail!($($args)+) } }; } /// Show warning. #[macro_export] #[doc(hidden)] macro_rules! warn { ($($args: tt)+) => { println!("{}", $crate::format_warn!($($args)+)) }; } /// Format warning into string. #[macro_export] #[doc(hidden)] macro_rules! format_warn { ($($args: tt)+) => { format!("cargo:warning={}", format_args!($($args)+)) }; } /// A simple error implementation which allows chaining of errors, inspired somewhat by anyhow. #[derive(Debug)] pub struct Error { value: String, source: Option>, } /// Error report inspired by /// pub struct ErrorReport<'a>(&'a Error); impl Error { pub fn report(&self) -> ErrorReport<'_> { ErrorReport(self) } } impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.value) } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { self.source.as_deref() } } impl std::fmt::Display for ErrorReport<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use std::error::Error; self.0.fmt(f)?; let mut source = self.0.source(); if source.is_some() { writeln!(f, "\ncaused by:")?; let mut index = 0; while let Some(some_source) = source { writeln!(f, " - {}: {}", index, some_source)?; source = some_source.source(); index += 1; } } Ok(()) } } impl From for Error { fn from(value: String) -> Self { Self { value, source: None, } } } impl From<&'_ str> for Error { fn from(value: &str) -> Self { value.to_string().into() } } impl From for Error { fn from(value: std::convert::Infallible) -> Self { match value {} } } pub type Result = std::result::Result; pub trait Context { fn context(self, message: impl Into) -> Result; fn with_context(self, message: impl FnOnce() -> String) -> Result; } impl Context for Result where E: std::error::Error + 'static, { fn context(self, message: impl Into) -> Result { self.map_err(|error| Error { value: message.into(), source: Some(Box::new(error)), }) } fn with_context(self, message: impl FnOnce() -> String) -> Result { self.map_err(|error| Error { value: message(), source: Some(Box::new(error)), }) } } #[cfg(test)] mod tests { use super::*; #[test] fn error_report() { let error: Result<()> = Err(Error::from("there was an internal error")) .with_context(|| format!("failed to do {}", "something difficult")) .context("things went wrong"); assert_eq!( error .unwrap_err() .report() .to_string() .split('\n') .collect::>(), vec![ "things went wrong", "caused by:", " - 0: failed to do something difficult", " - 1: there was an internal error", "" ] ); } } pyo3-build-config/.cargo-checksum.json0000664000175000017500000000134714661133735020646 0ustar jamespagejamespage{"files":{"Cargo.toml":"7afc92dc490bf5f812ce73007e0e7e89159f010998f5c22e6fdd0fc4229e14da","LICENSE-APACHE":"71073d492e996de196dbe1eb1e4c94c27c014c841b288161265b2efd06d0af28","LICENSE-MIT":"afcbe3b2e6b37172b5a9ca869ee4c0b8cdc09316e5d4384864154482c33e5af6","build.rs":"905cbe245028aa0a6841ce7543dd8fc3e289872e7a630247d4fc81759fc938c3","src/errors.rs":"ffb63dbfa121e0bf4926cde7baa758c4af665fc0d000d2012aa7f818ce97a398","src/impl_.rs":"99044022fb6c00526e753dc62a23c602e7046de9bb3c627885cd89dce2e783b6","src/import_lib.rs":"858fa3fb5344c994498851200a0cb580d1ad5c4740ce0f4cbe59408d1c8e25a7","src/lib.rs":"8fd69acbbac29dc6dcfe68c430a1374eedb1459a58f235095f32cd2ac3a964a5"},"package":"1e8730e591b14492a8945cdff32f089250b05f5accecf74aeddf9e8272ce1fa8"}pyo3-ffi/0000775000175000017500000000000014661133735013177 5ustar jamespagejamespagepyo3-ffi/build.rs0000644000175000017500000002171414661133735014647 0ustar jamespagejamespageuse pyo3_build_config::{ bail, ensure, print_feature_cfgs, pyo3_build_script_impl::{ cargo_env_var, env_var, errors::Result, is_linking_libpython, resolve_interpreter_config, InterpreterConfig, PythonVersion, }, warn, BuildFlag, PythonImplementation, }; use std::ops::Not; /// Minimum Python version PyO3 supports. struct SupportedVersions { min: PythonVersion, max: PythonVersion, } const SUPPORTED_VERSIONS_CPYTHON: SupportedVersions = SupportedVersions { min: PythonVersion { major: 3, minor: 7 }, max: PythonVersion { major: 3, minor: 13, }, }; const SUPPORTED_VERSIONS_PYPY: SupportedVersions = SupportedVersions { min: PythonVersion { major: 3, minor: 7 }, max: PythonVersion { major: 3, minor: 10, }, }; const SUPPORTED_VERSIONS_GRAALPY: SupportedVersions = SupportedVersions { min: PythonVersion { major: 3, minor: 10, }, max: PythonVersion { major: 3, minor: 11, }, }; fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> { // This is an undocumented env var which is only really intended to be used in CI / for testing // and development. if std::env::var("UNSAFE_PYO3_SKIP_VERSION_CHECK").as_deref() == Ok("1") { return Ok(()); } match interpreter_config.implementation { PythonImplementation::CPython => { let versions = SUPPORTED_VERSIONS_CPYTHON; ensure!( interpreter_config.version >= versions.min, "the configured Python interpreter version ({}) is lower than PyO3's minimum supported version ({})", interpreter_config.version, versions.min, ); ensure!( interpreter_config.version <= versions.max || env_var("PYO3_USE_ABI3_FORWARD_COMPATIBILITY").map_or(false, |os_str| os_str == "1"), "the configured Python interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\ = help: please check if an updated version of PyO3 is available. Current version: {}\n\ = help: set PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 to suppress this check and build anyway using the stable ABI", interpreter_config.version, versions.max, std::env::var("CARGO_PKG_VERSION").unwrap(), ); } PythonImplementation::PyPy => { let versions = SUPPORTED_VERSIONS_PYPY; ensure!( interpreter_config.version >= versions.min, "the configured PyPy interpreter version ({}) is lower than PyO3's minimum supported version ({})", interpreter_config.version, versions.min, ); // PyO3 does not support abi3, so we cannot offer forward compatibility ensure!( interpreter_config.version <= versions.max, "the configured PyPy interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\ = help: please check if an updated version of PyO3 is available. Current version: {}", interpreter_config.version, versions.max, std::env::var("CARGO_PKG_VERSION").unwrap() ); } PythonImplementation::GraalPy => { let versions = SUPPORTED_VERSIONS_GRAALPY; ensure!( interpreter_config.version >= versions.min, "the configured GraalPy interpreter version ({}) is lower than PyO3's minimum supported version ({})", interpreter_config.version, versions.min, ); // GraalPy does not support abi3, so we cannot offer forward compatibility ensure!( interpreter_config.version <= versions.max, "the configured GraalPy interpreter version ({}) is newer than PyO3's maximum supported version ({})\n\ = help: please check if an updated version of PyO3 is available. Current version: {}", interpreter_config.version, versions.max, std::env::var("CARGO_PKG_VERSION").unwrap() ); } } if interpreter_config.abi3 { match interpreter_config.implementation { PythonImplementation::CPython => {} PythonImplementation::PyPy => warn!( "PyPy does not yet support abi3 so the build artifacts will be version-specific. \ See https://foss.heptapod.net/pypy/pypy/-/issues/3397 for more information." ), PythonImplementation::GraalPy => warn!( "GraalPy does not support abi3 so the build artifacts will be version-specific." ), } } Ok(()) } fn ensure_gil_enabled(interpreter_config: &InterpreterConfig) -> Result<()> { let gil_enabled = interpreter_config .build_flags .0 .contains(&BuildFlag::Other("Py_GIL_DISABLED".to_string())) .not(); ensure!( gil_enabled || std::env::var("UNSAFE_PYO3_BUILD_FREE_THREADED").map_or(false, |os_str| os_str == "1"), "the Python interpreter was built with the GIL disabled, which is not yet supported by PyO3\n\ = help: see https://github.com/PyO3/pyo3/issues/4265 for more information\n\ = help: please check if an updated version of PyO3 is available. Current version: {}\n\ = help: set UNSAFE_PYO3_BUILD_FREE_THREADED=1 to suppress this check and build anyway for free-threaded Python", std::env::var("CARGO_PKG_VERSION").unwrap() ); Ok(()) } fn ensure_target_pointer_width(interpreter_config: &InterpreterConfig) -> Result<()> { if let Some(pointer_width) = interpreter_config.pointer_width { // Try to check whether the target architecture matches the python library let rust_target = match cargo_env_var("CARGO_CFG_TARGET_POINTER_WIDTH") .unwrap() .as_str() { "64" => 64, "32" => 32, x => bail!("unexpected Rust target pointer width: {}", x), }; ensure!( rust_target == pointer_width, "your Rust target architecture ({}-bit) does not match your python interpreter ({}-bit)", rust_target, pointer_width ); } Ok(()) } fn emit_link_config(interpreter_config: &InterpreterConfig) -> Result<()> { let target_os = cargo_env_var("CARGO_CFG_TARGET_OS").unwrap(); println!( "cargo:rustc-link-lib={link_model}{alias}{lib_name}", link_model = if interpreter_config.shared { "" } else { "static=" }, alias = if target_os == "windows" { "pythonXY:" } else { "" }, lib_name = interpreter_config.lib_name.as_ref().ok_or( "attempted to link to Python shared library but config does not contain lib_name" )?, ); if let Some(lib_dir) = &interpreter_config.lib_dir { println!("cargo:rustc-link-search=native={}", lib_dir); } Ok(()) } /// Prepares the PyO3 crate for compilation. /// /// This loads the config from pyo3-build-config and then makes some additional checks to improve UX /// for users. /// /// Emits the cargo configuration based on this config as well as a few checks of the Rust compiler /// version to enable features which aren't supported on MSRV. fn configure_pyo3() -> Result<()> { let interpreter_config = resolve_interpreter_config()?; if env_var("PYO3_PRINT_CONFIG").map_or(false, |os_str| os_str == "1") { print_config_and_exit(&interpreter_config); } ensure_python_version(&interpreter_config)?; ensure_target_pointer_width(&interpreter_config)?; ensure_gil_enabled(&interpreter_config)?; // Serialize the whole interpreter config into DEP_PYTHON_PYO3_CONFIG env var. interpreter_config.to_cargo_dep_env()?; if is_linking_libpython() && !interpreter_config.suppress_build_script_link_lines { emit_link_config(&interpreter_config)?; } for cfg in interpreter_config.build_script_outputs() { println!("{}", cfg) } // Extra lines come last, to support last write wins. for line in &interpreter_config.extra_build_script_lines { println!("{}", line); } // Emit cfgs like `invalid_from_utf8_lint` print_feature_cfgs(); Ok(()) } fn print_config_and_exit(config: &InterpreterConfig) { println!("\n-- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile --"); config .to_writer(std::io::stdout()) .expect("failed to print config to stdout"); println!("\nnote: unset the PYO3_PRINT_CONFIG environment variable and retry to compile with the above config"); std::process::exit(101); } fn main() { pyo3_build_config::print_expected_cfgs(); if let Err(e) = configure_pyo3() { eprintln!("error: {}", e.report()); std::process::exit(1) } } pyo3-ffi/README.md0000644000175000017500000001377514661133735014471 0ustar jamespagejamespage# pyo3-ffi This crate provides [Rust](https://www.rust-lang.org/) FFI declarations for Python 3. It supports both the stable and the unstable component of the ABI through the use of cfg flags. Python Versions 3.7+ are supported. It is meant for advanced users only - regular PyO3 users shouldn't need to interact with this crate at all. The contents of this crate are not documented here, as it would entail basically copying the documentation from CPython. Consult the [Python/C API Reference Manual][capi] for up-to-date documentation. # Minimum supported Rust and Python versions PyO3 supports the following software versions: - Python 3.7 and up (CPython and PyPy) - Rust 1.63 and up # Example: Building Python Native modules PyO3 can be used to generate a native Python module. The easiest way to try this out for the first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based Python packages with minimal configuration. The following steps set up some files for an example Python module, install `maturin`, and then show how to build and import the Python module. First, create a new folder (let's call it `string_sum`) containing the following two files: **`Cargo.toml`** ```toml [lib] name = "string_sum" # "cdylib" is necessary to produce a shared library for Python to import from. # # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: # crate-type = ["cdylib", "rlib"] crate-type = ["cdylib"] [dependencies.pyo3-ffi] version = "*" features = ["extension-module"] ``` **`src/lib.rs`** ```rust use std::os::raw::c_char; use std::ptr; use pyo3_ffi::*; static mut MODULE_DEF: PyModuleDef = PyModuleDef { m_base: PyModuleDef_HEAD_INIT, m_name: c_str!("string_sum").as_ptr(), m_doc: c_str!("A Python module written in Rust.").as_ptr(), m_size: 0, m_methods: unsafe { METHODS.as_mut_ptr().cast() }, m_slots: std::ptr::null_mut(), m_traverse: None, m_clear: None, m_free: None, }; static mut METHODS: [PyMethodDef; 2] = [ PyMethodDef { ml_name: c_str!("sum_as_string").as_ptr(), ml_meth: PyMethodDefPointer { _PyCFunctionFast: sum_as_string, }, ml_flags: METH_FASTCALL, ml_doc: c_str!("returns the sum of two integers as a string").as_ptr(), }, // A zeroed PyMethodDef to mark the end of the array. PyMethodDef::zeroed() ]; // The module initialization function, which must be named `PyInit_`. #[allow(non_snake_case)] #[no_mangle] pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject { PyModule_Create(ptr::addr_of_mut!(MODULE_DEF)) } pub unsafe extern "C" fn sum_as_string( _self: *mut PyObject, args: *mut *mut PyObject, nargs: Py_ssize_t, ) -> *mut PyObject { if nargs != 2 { PyErr_SetString( PyExc_TypeError, c_str!("sum_as_string() expected 2 positional arguments").as_ptr(), ); return std::ptr::null_mut(); } let arg1 = *args; if PyLong_Check(arg1) == 0 { PyErr_SetString( PyExc_TypeError, c_str!("sum_as_string() expected an int for positional argument 1").as_ptr(), ); return std::ptr::null_mut(); } let arg1 = PyLong_AsLong(arg1); if !PyErr_Occurred().is_null() { return ptr::null_mut(); } let arg2 = *args.add(1); if PyLong_Check(arg2) == 0 { PyErr_SetString( PyExc_TypeError, c_str!("sum_as_string() expected an int for positional argument 2").as_ptr(), ); return std::ptr::null_mut(); } let arg2 = PyLong_AsLong(arg2); if !PyErr_Occurred().is_null() { return ptr::null_mut(); } match arg1.checked_add(arg2) { Some(sum) => { let string = sum.to_string(); PyUnicode_FromStringAndSize(string.as_ptr().cast::(), string.len() as isize) } None => { PyErr_SetString( PyExc_OverflowError, c_str!("arguments too large to add").as_ptr(), ); std::ptr::null_mut() } } } ``` With those two files in place, now `maturin` needs to be installed. This can be done using Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin` into it: ```bash $ cd string_sum $ python -m venv .env $ source .env/bin/activate $ pip install maturin ``` Now build and execute the module: ```bash $ maturin develop # lots of progress output as maturin runs the compilation... $ python >>> import string_sum >>> string_sum.sum_as_string(5, 20) '25' ``` As well as with `maturin`, it is possible to build using [setuptools-rust] or [manually][manual_builds]. Both offer more flexibility than `maturin` but require further configuration. While most projects use the safe wrapper provided by PyO3, you can take a look at the [`orjson`] library as an example on how to use `pyo3-ffi` directly. For those well versed in C and Rust the [tutorials] from the CPython documentation can be easily converted to rust as well. [tutorials]: https://docs.python.org/3/extending/ [`orjson`]: https://github.com/ijl/orjson [capi]: https://docs.python.org/3/c-api/index.html [`maturin`]: https://github.com/PyO3/maturin "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" [`pyo3-build-config`]: https://docs.rs/pyo3-build-config [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html "Features - The Cargo Book" [manual_builds]: https://pyo3.rs/latest/building-and-distribution.html#manual-builds "Manual builds - Building and Distribution - PyO3 user guide" [setuptools-rust]: https://github.com/PyO3/setuptools-rust "Setuptools plugin for Rust extensions" [PEP 384]: https://www.python.org/dev/peps/pep-0384 "PEP 384 -- Defining a Stable ABI" [Features chapter of the guide]: https://pyo3.rs/latest/features.html#features-reference "Features Reference - PyO3 user guide" pyo3-ffi/ACKNOWLEDGEMENTS0000644000175000017500000000041214661133735015447 0ustar jamespagejamespageThis is a Rust reimplementation of the CPython public header files as necessary for binary compatibility, with additional metadata to support PyPy. For original implementations please see: - https://github.com/python/cpython - https://foss.heptapod.net/pypy/pypy pyo3-ffi/LICENSE-APACHE0000644000175000017500000002503514661133735015126 0ustar jamespagejamespage Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. pyo3-ffi/Cargo.toml0000644000175000017500000000435314661133735015132 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "pyo3-ffi" version = "0.22.2" authors = ["PyO3 Project and Contributors "] links = "python" description = "Python-API bindings for the PyO3 ecosystem" homepage = "https://github.com/pyo3/pyo3" readme = "README.md" keywords = [ "pyo3", "python", "cpython", "ffi", ] categories = [ "api-bindings", "development-tools::ffi", ] license = "MIT OR Apache-2.0" repository = "https://github.com/pyo3/pyo3" [dependencies.libc] version = "0.2.62" [build-dependencies.pyo3-build-config] version = "=0.22.2" features = ["resolve-config"] [features] abi3 = ["pyo3-build-config/abi3"] abi3-py310 = [ "abi3-py311", "pyo3-build-config/abi3-py310", ] abi3-py311 = [ "abi3-py312", "pyo3-build-config/abi3-py311", ] abi3-py312 = [ "abi3", "pyo3-build-config/abi3-py312", ] abi3-py37 = [ "abi3-py38", "pyo3-build-config/abi3-py37", ] abi3-py38 = [ "abi3-py39", "pyo3-build-config/abi3-py38", ] abi3-py39 = [ "abi3-py310", "pyo3-build-config/abi3-py39", ] default = [] extension-module = ["pyo3-build-config/extension-module"] generate-import-lib = ["pyo3-build-config/python3-dll-a"] [lints.clippy] checked_conversions = "warn" dbg_macro = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" let_unit_value = "warn" manual_assert = "warn" manual_ok_or = "warn" todo = "warn" unnecessary_wraps = "warn" used_underscore_binding = "warn" useless_transmute = "warn" [lints.rust] elided_lifetimes_in_paths = "warn" invalid_doc_attributes = "warn" rust_2021_prelude_collisions = "warn" unused_lifetimes = "warn" [lints.rust.rust_2018_idioms] level = "warn" priority = -1 [lints.rustdoc] bare_urls = "warn" broken_intra_doc_links = "warn" pyo3-ffi/LICENSE-MIT0000644000175000017500000000212314661133735014627 0ustar jamespagejamespageCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3-ffi/src/0000775000175000017500000000000014661133735013766 5ustar jamespagejamespagepyo3-ffi/src/code.rs0000644000175000017500000000027214661133735015245 0ustar jamespagejamespage// This header doesn't exist in CPython, but Include/cpython/code.h does. We add // this here so that PyCodeObject has a definition under the limited API. opaque_struct!(PyCodeObject); pyo3-ffi/src/unicodeobject.rs0000644000175000017500000003306414661133735017155 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use libc::wchar_t; use std::os::raw::{c_char, c_int, c_void}; #[cfg(not(PyPy))] use std::ptr::addr_of_mut; #[cfg(not(Py_LIMITED_API))] pub type Py_UNICODE = wchar_t; pub type Py_UCS4 = u32; pub type Py_UCS2 = u16; pub type Py_UCS1 = u8; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyUnicode_Type")] pub static mut PyUnicode_Type: PyTypeObject; pub static mut PyUnicodeIter_Type: PyTypeObject; #[cfg(PyPy)] #[link_name = "PyPyUnicode_Check"] pub fn PyUnicode_Check(op: *mut PyObject) -> c_int; #[cfg(PyPy)] #[link_name = "PyPyUnicode_CheckExact"] pub fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyUnicode_Check(op: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS) } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyUnicode_Type)) as c_int } pub const Py_UNICODE_REPLACEMENT_CHARACTER: Py_UCS4 = 0xFFFD; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromStringAndSize")] pub fn PyUnicode_FromStringAndSize(u: *const c_char, size: Py_ssize_t) -> *mut PyObject; pub fn PyUnicode_FromString(u: *const c_char) -> *mut PyObject; pub fn PyUnicode_Substring( str: *mut PyObject, start: Py_ssize_t, end: Py_ssize_t, ) -> *mut PyObject; pub fn PyUnicode_AsUCS4( unicode: *mut PyObject, buffer: *mut Py_UCS4, buflen: Py_ssize_t, copy_null: c_int, ) -> *mut Py_UCS4; pub fn PyUnicode_AsUCS4Copy(unicode: *mut PyObject) -> *mut Py_UCS4; #[cfg_attr(PyPy, link_name = "PyPyUnicode_GetLength")] pub fn PyUnicode_GetLength(unicode: *mut PyObject) -> Py_ssize_t; #[cfg(not(Py_3_12))] #[deprecated(note = "Removed in Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPyUnicode_GetSize")] pub fn PyUnicode_GetSize(unicode: *mut PyObject) -> Py_ssize_t; pub fn PyUnicode_ReadChar(unicode: *mut PyObject, index: Py_ssize_t) -> Py_UCS4; pub fn PyUnicode_WriteChar( unicode: *mut PyObject, index: Py_ssize_t, character: Py_UCS4, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Resize")] pub fn PyUnicode_Resize(unicode: *mut *mut PyObject, length: Py_ssize_t) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromEncodedObject")] pub fn PyUnicode_FromEncodedObject( obj: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromObject")] pub fn PyUnicode_FromObject(obj: *mut PyObject) -> *mut PyObject; // #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromFormatV")] // pub fn PyUnicode_FromFormatV(format: *const c_char, vargs: va_list) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromFormat")] pub fn PyUnicode_FromFormat(format: *const c_char, ...) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_InternInPlace")] pub fn PyUnicode_InternInPlace(arg1: *mut *mut PyObject); #[cfg(not(Py_3_12))] #[cfg_attr(Py_3_10, deprecated(note = "Python 3.10"))] pub fn PyUnicode_InternImmortal(arg1: *mut *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyUnicode_InternFromString")] pub fn PyUnicode_InternFromString(u: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromWideChar")] pub fn PyUnicode_FromWideChar(w: *const wchar_t, size: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsWideChar")] pub fn PyUnicode_AsWideChar( unicode: *mut PyObject, w: *mut wchar_t, size: Py_ssize_t, ) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsWideCharString")] pub fn PyUnicode_AsWideCharString( unicode: *mut PyObject, size: *mut Py_ssize_t, ) -> *mut wchar_t; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromOrdinal")] pub fn PyUnicode_FromOrdinal(ordinal: c_int) -> *mut PyObject; pub fn PyUnicode_ClearFreeList() -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_GetDefaultEncoding")] pub fn PyUnicode_GetDefaultEncoding() -> *const c_char; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Decode")] pub fn PyUnicode_Decode( s: *const c_char, size: Py_ssize_t, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_AsDecodedObject( unicode: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_AsDecodedUnicode( unicode: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsEncodedObject")] pub fn PyUnicode_AsEncodedObject( unicode: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsEncodedString")] pub fn PyUnicode_AsEncodedString( unicode: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_AsEncodedUnicode( unicode: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_BuildEncodingMap(string: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_DecodeUTF7( string: *const c_char, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_DecodeUTF7Stateful( string: *const c_char, length: Py_ssize_t, errors: *const c_char, consumed: *mut Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeUTF8")] pub fn PyUnicode_DecodeUTF8( string: *const c_char, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_DecodeUTF8Stateful( string: *const c_char, length: Py_ssize_t, errors: *const c_char, consumed: *mut Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8String")] pub fn PyUnicode_AsUTF8String(unicode: *mut PyObject) -> *mut PyObject; #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8AndSize")] pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *const c_char; #[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeUTF32")] pub fn PyUnicode_DecodeUTF32( string: *const c_char, length: Py_ssize_t, errors: *const c_char, byteorder: *mut c_int, ) -> *mut PyObject; pub fn PyUnicode_DecodeUTF32Stateful( string: *const c_char, length: Py_ssize_t, errors: *const c_char, byteorder: *mut c_int, consumed: *mut Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF32String")] pub fn PyUnicode_AsUTF32String(unicode: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeUTF16")] pub fn PyUnicode_DecodeUTF16( string: *const c_char, length: Py_ssize_t, errors: *const c_char, byteorder: *mut c_int, ) -> *mut PyObject; pub fn PyUnicode_DecodeUTF16Stateful( string: *const c_char, length: Py_ssize_t, errors: *const c_char, byteorder: *mut c_int, consumed: *mut Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF16String")] pub fn PyUnicode_AsUTF16String(unicode: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_DecodeUnicodeEscape( string: *const c_char, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUnicodeEscapeString")] pub fn PyUnicode_AsUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_DecodeRawUnicodeEscape( string: *const c_char, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_AsRawUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeLatin1")] pub fn PyUnicode_DecodeLatin1( string: *const c_char, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsLatin1String")] pub fn PyUnicode_AsLatin1String(unicode: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeASCII")] pub fn PyUnicode_DecodeASCII( string: *const c_char, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsASCIIString")] pub fn PyUnicode_AsASCIIString(unicode: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_DecodeCharmap( string: *const c_char, length: Py_ssize_t, mapping: *mut PyObject, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_AsCharmapString( unicode: *mut PyObject, mapping: *mut PyObject, ) -> *mut PyObject; pub fn PyUnicode_DecodeLocaleAndSize( str: *const c_char, len: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_DecodeLocale(str: *const c_char, errors: *const c_char) -> *mut PyObject; pub fn PyUnicode_EncodeLocale(unicode: *mut PyObject, errors: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FSConverter")] pub fn PyUnicode_FSConverter(arg1: *mut PyObject, arg2: *mut c_void) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FSDecoder")] pub fn PyUnicode_FSDecoder(arg1: *mut PyObject, arg2: *mut c_void) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeFSDefault")] pub fn PyUnicode_DecodeFSDefault(s: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeFSDefaultAndSize")] pub fn PyUnicode_DecodeFSDefaultAndSize(s: *const c_char, size: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeFSDefault")] pub fn PyUnicode_EncodeFSDefault(unicode: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Concat")] pub fn PyUnicode_Concat(left: *mut PyObject, right: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_Append(pleft: *mut *mut PyObject, right: *mut PyObject); pub fn PyUnicode_AppendAndDel(pleft: *mut *mut PyObject, right: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyUnicode_Split")] pub fn PyUnicode_Split( s: *mut PyObject, sep: *mut PyObject, maxsplit: Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Splitlines")] pub fn PyUnicode_Splitlines(s: *mut PyObject, keepends: c_int) -> *mut PyObject; pub fn PyUnicode_Partition(s: *mut PyObject, sep: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_RPartition(s: *mut PyObject, sep: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_RSplit( s: *mut PyObject, sep: *mut PyObject, maxsplit: Py_ssize_t, ) -> *mut PyObject; pub fn PyUnicode_Translate( str: *mut PyObject, table: *mut PyObject, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Join")] pub fn PyUnicode_Join(separator: *mut PyObject, seq: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Tailmatch")] pub fn PyUnicode_Tailmatch( str: *mut PyObject, substr: *mut PyObject, start: Py_ssize_t, end: Py_ssize_t, direction: c_int, ) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Find")] pub fn PyUnicode_Find( str: *mut PyObject, substr: *mut PyObject, start: Py_ssize_t, end: Py_ssize_t, direction: c_int, ) -> Py_ssize_t; pub fn PyUnicode_FindChar( str: *mut PyObject, ch: Py_UCS4, start: Py_ssize_t, end: Py_ssize_t, direction: c_int, ) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Count")] pub fn PyUnicode_Count( str: *mut PyObject, substr: *mut PyObject, start: Py_ssize_t, end: Py_ssize_t, ) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Replace")] pub fn PyUnicode_Replace( str: *mut PyObject, substr: *mut PyObject, replstr: *mut PyObject, maxcount: Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Compare")] pub fn PyUnicode_Compare(left: *mut PyObject, right: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_CompareWithASCIIString")] pub fn PyUnicode_CompareWithASCIIString(left: *mut PyObject, right: *const c_char) -> c_int; #[cfg(Py_3_13)] pub fn PyUnicode_EqualToUTF8(unicode: *mut PyObject, string: *const c_char) -> c_int; #[cfg(Py_3_13)] pub fn PyUnicode_EqualToUTF8AndSize( unicode: *mut PyObject, string: *const c_char, size: Py_ssize_t, ) -> c_int; pub fn PyUnicode_RichCompare( left: *mut PyObject, right: *mut PyObject, op: c_int, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_Format")] pub fn PyUnicode_Format(format: *mut PyObject, args: *mut PyObject) -> *mut PyObject; pub fn PyUnicode_Contains(container: *mut PyObject, element: *mut PyObject) -> c_int; pub fn PyUnicode_IsIdentifier(s: *mut PyObject) -> c_int; } pyo3-ffi/src/pylifecycle.rs0000644000175000017500000000333214661133735016643 0ustar jamespagejamespageuse crate::pystate::PyThreadState; use libc::wchar_t; use std::os::raw::{c_char, c_int}; extern "C" { pub fn Py_Initialize(); pub fn Py_InitializeEx(arg1: c_int); pub fn Py_Finalize(); pub fn Py_FinalizeEx() -> c_int; #[cfg_attr(PyPy, link_name = "PyPy_IsInitialized")] pub fn Py_IsInitialized() -> c_int; pub fn Py_NewInterpreter() -> *mut PyThreadState; pub fn Py_EndInterpreter(arg1: *mut PyThreadState); #[cfg_attr(PyPy, link_name = "PyPy_AtExit")] pub fn Py_AtExit(func: Option) -> c_int; pub fn Py_Exit(arg1: c_int); pub fn Py_Main(argc: c_int, argv: *mut *mut wchar_t) -> c_int; pub fn Py_BytesMain(argc: c_int, argv: *mut *mut c_char) -> c_int; pub fn Py_SetProgramName(arg1: *const wchar_t); #[cfg_attr(PyPy, link_name = "PyPy_GetProgramName")] pub fn Py_GetProgramName() -> *mut wchar_t; pub fn Py_SetPythonHome(arg1: *const wchar_t); pub fn Py_GetPythonHome() -> *mut wchar_t; pub fn Py_GetProgramFullPath() -> *mut wchar_t; pub fn Py_GetPrefix() -> *mut wchar_t; pub fn Py_GetExecPrefix() -> *mut wchar_t; pub fn Py_GetPath() -> *mut wchar_t; pub fn Py_SetPath(arg1: *const wchar_t); // skipped _Py_CheckPython3 #[cfg_attr(PyPy, link_name = "PyPy_GetVersion")] pub fn Py_GetVersion() -> *const c_char; pub fn Py_GetPlatform() -> *const c_char; pub fn Py_GetCopyright() -> *const c_char; pub fn Py_GetCompiler() -> *const c_char; pub fn Py_GetBuildInfo() -> *const c_char; } type PyOS_sighandler_t = unsafe extern "C" fn(arg1: c_int); extern "C" { pub fn PyOS_getsig(arg1: c_int) -> PyOS_sighandler_t; pub fn PyOS_setsig(arg1: c_int, arg2: PyOS_sighandler_t) -> PyOS_sighandler_t; } pyo3-ffi/src/methodobject.rs0000644000175000017500000001715614661133735017013 0ustar jamespagejamespageuse crate::object::{PyObject, PyTypeObject, Py_TYPE}; #[cfg(Py_3_9)] use crate::PyObject_TypeCheck; use std::os::raw::{c_char, c_int, c_void}; use std::{mem, ptr}; #[cfg(all(Py_3_9, not(Py_LIMITED_API), not(GraalPy)))] pub struct PyCFunctionObject { pub ob_base: PyObject, pub m_ml: *mut PyMethodDef, pub m_self: *mut PyObject, pub m_module: *mut PyObject, pub m_weakreflist: *mut PyObject, #[cfg(not(PyPy))] pub vectorcall: Option, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyCFunction_Type")] pub static mut PyCFunction_Type: PyTypeObject; } #[cfg(Py_3_9)] #[inline] pub unsafe fn PyCFunction_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == ptr::addr_of_mut!(PyCFunction_Type)) as c_int } #[cfg(Py_3_9)] #[inline] pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, ptr::addr_of_mut!(PyCFunction_Type)) } #[cfg(not(Py_3_9))] #[inline] pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == ptr::addr_of_mut!(PyCFunction_Type)) as c_int } pub type PyCFunction = unsafe extern "C" fn(slf: *mut PyObject, args: *mut PyObject) -> *mut PyObject; #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] pub type _PyCFunctionFast = unsafe extern "C" fn( slf: *mut PyObject, args: *mut *mut PyObject, nargs: crate::pyport::Py_ssize_t, ) -> *mut PyObject; pub type PyCFunctionWithKeywords = unsafe extern "C" fn( slf: *mut PyObject, args: *mut PyObject, kwds: *mut PyObject, ) -> *mut PyObject; #[cfg(not(Py_LIMITED_API))] pub type _PyCFunctionFastWithKeywords = unsafe extern "C" fn( slf: *mut PyObject, args: *const *mut PyObject, nargs: crate::pyport::Py_ssize_t, kwnames: *mut PyObject, ) -> *mut PyObject; #[cfg(all(Py_3_9, not(Py_LIMITED_API)))] pub type PyCMethod = unsafe extern "C" fn( slf: *mut PyObject, defining_class: *mut PyTypeObject, args: *const *mut PyObject, nargs: crate::pyport::Py_ssize_t, kwnames: *mut PyObject, ) -> *mut PyObject; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyCFunction_GetFunction")] pub fn PyCFunction_GetFunction(f: *mut PyObject) -> Option; pub fn PyCFunction_GetSelf(f: *mut PyObject) -> *mut PyObject; pub fn PyCFunction_GetFlags(f: *mut PyObject) -> c_int; #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyCFunction_Call( f: *mut PyObject, args: *mut PyObject, kwds: *mut PyObject, ) -> *mut PyObject; } /// Represents the [PyMethodDef](https://docs.python.org/3/c-api/structures.html#c.PyMethodDef) /// structure. /// /// Note that CPython may leave fields uninitialized. You must ensure that /// `ml_name` != NULL before dereferencing or reading other fields. #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq)] pub struct PyMethodDef { pub ml_name: *const c_char, pub ml_meth: PyMethodDefPointer, pub ml_flags: c_int, pub ml_doc: *const c_char, } impl PyMethodDef { pub const fn zeroed() -> PyMethodDef { PyMethodDef { ml_name: ptr::null(), ml_meth: PyMethodDefPointer { Void: ptr::null_mut(), }, ml_flags: 0, ml_doc: ptr::null(), } } } impl Default for PyMethodDef { fn default() -> PyMethodDef { PyMethodDef { ml_name: ptr::null(), ml_meth: PyMethodDefPointer { Void: ptr::null_mut(), }, ml_flags: 0, ml_doc: ptr::null(), } } } /// Function types used to implement Python callables. /// /// This function pointer must be accompanied by the correct [ml_flags](PyMethodDef::ml_flags), /// otherwise the behavior is undefined. /// /// See the [Python C API documentation][1] for more information. /// /// [1]: https://docs.python.org/3/c-api/structures.html#implementing-functions-and-methods #[repr(C)] #[derive(Copy, Clone, Eq)] pub union PyMethodDefPointer { /// This variant corresponds with [`METH_VARARGS`] *or* [`METH_NOARGS`] *or* [`METH_O`]. pub PyCFunction: PyCFunction, /// This variant corresponds with [`METH_VARARGS`] | [`METH_KEYWORDS`]. pub PyCFunctionWithKeywords: PyCFunctionWithKeywords, /// This variant corresponds with [`METH_FASTCALL`]. #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] pub _PyCFunctionFast: _PyCFunctionFast, /// This variant corresponds with [`METH_FASTCALL`] | [`METH_KEYWORDS`]. #[cfg(not(Py_LIMITED_API))] pub _PyCFunctionFastWithKeywords: _PyCFunctionFastWithKeywords, /// This variant corresponds with [`METH_METHOD`] | [`METH_FASTCALL`] | [`METH_KEYWORDS`]. #[cfg(all(Py_3_9, not(Py_LIMITED_API)))] pub PyCMethod: PyCMethod, Void: *mut c_void, } impl PyMethodDefPointer { pub fn as_ptr(&self) -> *mut c_void { unsafe { self.Void } } pub fn is_null(&self) -> bool { self.as_ptr().is_null() } pub const fn zeroed() -> PyMethodDefPointer { PyMethodDefPointer { Void: ptr::null_mut(), } } } impl PartialEq for PyMethodDefPointer { fn eq(&self, other: &Self) -> bool { unsafe { self.Void == other.Void } } } impl std::fmt::Pointer for PyMethodDefPointer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let ptr = unsafe { self.Void }; std::fmt::Pointer::fmt(&ptr, f) } } const _: () = assert!(mem::size_of::() == mem::size_of::>()); #[cfg(not(Py_3_9))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyCFunction_New")] pub fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyCFunction_NewEx")] pub fn PyCFunction_NewEx( ml: *mut PyMethodDef, slf: *mut PyObject, module: *mut PyObject, ) -> *mut PyObject; } #[cfg(Py_3_9)] #[inline] pub unsafe fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject { PyCFunction_NewEx(ml, slf, std::ptr::null_mut()) } #[cfg(Py_3_9)] #[inline] pub unsafe fn PyCFunction_NewEx( ml: *mut PyMethodDef, slf: *mut PyObject, module: *mut PyObject, ) -> *mut PyObject { PyCMethod_New(ml, slf, module, std::ptr::null_mut()) } #[cfg(Py_3_9)] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyCMethod_New")] pub fn PyCMethod_New( ml: *mut PyMethodDef, slf: *mut PyObject, module: *mut PyObject, cls: *mut PyTypeObject, ) -> *mut PyObject; } /* Flag passed to newmethodobject */ pub const METH_VARARGS: c_int = 0x0001; pub const METH_KEYWORDS: c_int = 0x0002; /* METH_NOARGS and METH_O must not be combined with the flags above. */ pub const METH_NOARGS: c_int = 0x0004; pub const METH_O: c_int = 0x0008; /* METH_CLASS and METH_STATIC are a little different; these control the construction of methods for a class. These cannot be used for functions in modules. */ pub const METH_CLASS: c_int = 0x0010; pub const METH_STATIC: c_int = 0x0020; /* METH_COEXIST allows a method to be entered eventhough a slot has already filled the entry. When defined, the flag allows a separate method, "__contains__" for example, to coexist with a defined slot like sq_contains. */ pub const METH_COEXIST: c_int = 0x0040; /* METH_FASTCALL indicates the PEP 590 Vectorcall calling format. It may be specified alone or with METH_KEYWORDS. */ #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] pub const METH_FASTCALL: c_int = 0x0080; // skipped METH_STACKLESS #[cfg(all(Py_3_9, not(Py_LIMITED_API)))] pub const METH_METHOD: c_int = 0x0200; extern "C" { #[cfg(not(Py_3_9))] pub fn PyCFunction_ClearFreeList() -> c_int; } pyo3-ffi/src/dictobject.rs0000644000175000017500000001064414661133735016451 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyDict_Type")] pub static mut PyDict_Type: PyTypeObject; } #[inline] pub unsafe fn PyDict_Check(op: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS) } #[inline] pub unsafe fn PyDict_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyDict_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyDict_New")] pub fn PyDict_New() -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_GetItem")] pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_GetItemWithError")] pub fn PyDict_GetItemWithError(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_SetItem")] pub fn PyDict_SetItem(mp: *mut PyObject, key: *mut PyObject, item: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_DelItem")] pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Clear")] pub fn PyDict_Clear(mp: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyDict_Next")] pub fn PyDict_Next( mp: *mut PyObject, pos: *mut Py_ssize_t, key: *mut *mut PyObject, value: *mut *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Keys")] pub fn PyDict_Keys(mp: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_Values")] pub fn PyDict_Values(mp: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_Items")] pub fn PyDict_Items(mp: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_Size")] pub fn PyDict_Size(mp: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyDict_Copy")] pub fn PyDict_Copy(mp: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_Contains")] pub fn PyDict_Contains(mp: *mut PyObject, key: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Update")] pub fn PyDict_Update(mp: *mut PyObject, other: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_Merge")] pub fn PyDict_Merge(mp: *mut PyObject, other: *mut PyObject, _override: c_int) -> c_int; pub fn PyDict_MergeFromSeq2(d: *mut PyObject, seq2: *mut PyObject, _override: c_int) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_GetItemString")] pub fn PyDict_GetItemString(dp: *mut PyObject, key: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDict_SetItemString")] pub fn PyDict_SetItemString( dp: *mut PyObject, key: *const c_char, item: *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyDict_DelItemString")] pub fn PyDict_DelItemString(dp: *mut PyObject, key: *const c_char) -> c_int; // skipped 3.10 / ex-non-limited PyObject_GenericGetDict } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyDictKeys_Type: PyTypeObject; pub static mut PyDictValues_Type: PyTypeObject; pub static mut PyDictItems_Type: PyTypeObject; } #[inline] pub unsafe fn PyDictKeys_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyDictKeys_Type)) as c_int } #[inline] pub unsafe fn PyDictValues_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyDictValues_Type)) as c_int } #[inline] pub unsafe fn PyDictItems_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyDictItems_Type)) as c_int } #[inline] pub unsafe fn PyDictViewSet_Check(op: *mut PyObject) -> c_int { (PyDictKeys_Check(op) != 0 || PyDictItems_Check(op) != 0) as c_int } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyDictIterKey_Type: PyTypeObject; pub static mut PyDictIterValue_Type: PyTypeObject; pub static mut PyDictIterItem_Type: PyTypeObject; #[cfg(Py_3_8)] pub static mut PyDictRevIterKey_Type: PyTypeObject; #[cfg(Py_3_8)] pub static mut PyDictRevIterValue_Type: PyTypeObject; #[cfg(Py_3_8)] pub static mut PyDictRevIterItem_Type: PyTypeObject; } #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] // TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985) opaque_struct!(PyDictObject); pyo3-ffi/src/pymem.rs0000644000175000017500000000077614661133735015473 0ustar jamespagejamespageuse libc::size_t; use std::os::raw::c_void; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyMem_Malloc")] pub fn PyMem_Malloc(size: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyMem_Calloc")] pub fn PyMem_Calloc(nelem: size_t, elsize: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyMem_Realloc")] pub fn PyMem_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyMem_Free")] pub fn PyMem_Free(ptr: *mut c_void); } pyo3-ffi/src/pyhash.rs0000644000175000017500000000251014661133735015624 0ustar jamespagejamespage#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] use crate::pyport::{Py_hash_t, Py_ssize_t}; #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] use std::os::raw::{c_char, c_void}; use std::os::raw::{c_int, c_ulong}; extern "C" { // skipped non-limited _Py_HashDouble // skipped non-limited _Py_HashPointer // skipped non-limited _Py_HashPointerRaw #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] pub fn _Py_HashBytes(src: *const c_void, len: Py_ssize_t) -> Py_hash_t; } pub const _PyHASH_MULTIPLIER: c_ulong = 1000003; // skipped _PyHASH_BITS // skipped non-limited _Py_HashSecret_t #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyHash_FuncDef { pub hash: Option Py_hash_t>, pub name: *const c_char, pub hash_bits: c_int, pub seed_bits: c_int, } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] impl Default for PyHash_FuncDef { #[inline] fn default() -> Self { unsafe { std::mem::zeroed() } } } extern "C" { #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef; } // skipped Py_HASH_CUTOFF pub const Py_HASH_EXTERNAL: c_int = 0; pub const Py_HASH_SIPHASH24: c_int = 1; pub const Py_HASH_FNV: c_int = 2; // skipped Py_HASH_ALGORITHM pyo3-ffi/src/pycapsule.rs0000644000175000017500000000420014661133735016333 0ustar jamespagejamespageuse crate::object::*; use std::os::raw::{c_char, c_int, c_void}; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyCapsule_Type")] pub static mut PyCapsule_Type: PyTypeObject; } pub type PyCapsule_Destructor = unsafe extern "C" fn(o: *mut PyObject); #[inline] pub unsafe fn PyCapsule_CheckExact(ob: *mut PyObject) -> c_int { (Py_TYPE(ob) == addr_of_mut!(PyCapsule_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyCapsule_New")] pub fn PyCapsule_New( pointer: *mut c_void, name: *const c_char, destructor: Option, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyCapsule_GetPointer")] pub fn PyCapsule_GetPointer(capsule: *mut PyObject, name: *const c_char) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyCapsule_GetDestructor")] pub fn PyCapsule_GetDestructor(capsule: *mut PyObject) -> Option; #[cfg_attr(PyPy, link_name = "PyPyCapsule_GetName")] pub fn PyCapsule_GetName(capsule: *mut PyObject) -> *const c_char; #[cfg_attr(PyPy, link_name = "PyPyCapsule_GetContext")] pub fn PyCapsule_GetContext(capsule: *mut PyObject) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyCapsule_IsValid")] pub fn PyCapsule_IsValid(capsule: *mut PyObject, name: *const c_char) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyCapsule_SetPointer")] pub fn PyCapsule_SetPointer(capsule: *mut PyObject, pointer: *mut c_void) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyCapsule_SetDestructor")] pub fn PyCapsule_SetDestructor( capsule: *mut PyObject, destructor: Option, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyCapsule_SetName")] pub fn PyCapsule_SetName(capsule: *mut PyObject, name: *const c_char) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyCapsule_SetContext")] pub fn PyCapsule_SetContext(capsule: *mut PyObject, context: *mut c_void) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyCapsule_Import")] pub fn PyCapsule_Import(name: *const c_char, no_block: c_int) -> *mut c_void; } pyo3-ffi/src/marshal.rs0000644000175000017500000000136314661133735015764 0ustar jamespagejamespageuse super::{PyObject, Py_ssize_t}; use std::os::raw::{c_char, c_int}; // skipped Py_MARSHAL_VERSION // skipped PyMarshal_WriteLongToFile // skipped PyMarshal_WriteObjectToFile extern "C" { #[cfg_attr(PyPy, link_name = "PyPyMarshal_WriteObjectToString")] pub fn PyMarshal_WriteObjectToString(object: *mut PyObject, version: c_int) -> *mut PyObject; // skipped non-limited PyMarshal_ReadLongFromFile // skipped non-limited PyMarshal_ReadShortFromFile // skipped non-limited PyMarshal_ReadObjectFromFile // skipped non-limited PyMarshal_ReadLastObjectFromFile #[cfg_attr(PyPy, link_name = "PyPyMarshal_ReadObjectFromString")] pub fn PyMarshal_ReadObjectFromString(data: *const c_char, len: Py_ssize_t) -> *mut PyObject; } pyo3-ffi/src/tupleobject.rs0000644000175000017500000000272214661133735016655 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyTuple_Type")] pub static mut PyTuple_Type: PyTypeObject; pub static mut PyTupleIter_Type: PyTypeObject; } #[inline] pub unsafe fn PyTuple_Check(op: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TUPLE_SUBCLASS) } #[inline] pub unsafe fn PyTuple_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyTuple_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyTuple_New")] pub fn PyTuple_New(size: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyTuple_Size")] pub fn PyTuple_Size(arg1: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyTuple_GetItem")] pub fn PyTuple_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyTuple_SetItem")] pub fn PyTuple_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyTuple_GetSlice")] pub fn PyTuple_GetSlice( arg1: *mut PyObject, arg2: Py_ssize_t, arg3: Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyTuple_Pack")] pub fn PyTuple_Pack(arg1: Py_ssize_t, ...) -> *mut PyObject; #[cfg(not(Py_3_9))] pub fn PyTuple_ClearFreeList() -> c_int; } pyo3-ffi/src/pyarena.rs0000644000175000017500000000003114661133735015763 0ustar jamespagejamespageopaque_struct!(PyArena); pyo3-ffi/src/fileutils.rs0000644000175000017500000000042214661133735016330 0ustar jamespagejamespageuse crate::pyport::Py_ssize_t; use libc::wchar_t; use std::os::raw::c_char; extern "C" { pub fn Py_DecodeLocale(arg1: *const c_char, size: *mut Py_ssize_t) -> *mut wchar_t; pub fn Py_EncodeLocale(text: *const wchar_t, error_pos: *mut Py_ssize_t) -> *mut c_char; } pyo3-ffi/src/codecs.rs0000644000175000017500000000511014661133735015567 0ustar jamespagejamespageuse crate::object::PyObject; use std::os::raw::{c_char, c_int}; extern "C" { pub fn PyCodec_Register(search_function: *mut PyObject) -> c_int; #[cfg(Py_3_10)] #[cfg(not(PyPy))] pub fn PyCodec_Unregister(search_function: *mut PyObject) -> c_int; // skipped non-limited _PyCodec_Lookup from Include/codecs.h // skipped non-limited _PyCodec_Forget from Include/codecs.h pub fn PyCodec_KnownEncoding(encoding: *const c_char) -> c_int; pub fn PyCodec_Encode( object: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyCodec_Decode( object: *mut PyObject, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; // skipped non-limited _PyCodec_LookupTextEncoding from Include/codecs.h // skipped non-limited _PyCodec_EncodeText from Include/codecs.h // skipped non-limited _PyCodec_DecodeText from Include/codecs.h // skipped non-limited _PyCodecInfo_GetIncrementalDecoder from Include/codecs.h // skipped non-limited _PyCodecInfo_GetIncrementalEncoder from Include/codecs.h pub fn PyCodec_Encoder(encoding: *const c_char) -> *mut PyObject; pub fn PyCodec_Decoder(encoding: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyCodec_IncrementalEncoder")] pub fn PyCodec_IncrementalEncoder( encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyCodec_IncrementalDecoder")] pub fn PyCodec_IncrementalDecoder( encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyCodec_StreamReader( encoding: *const c_char, stream: *mut PyObject, errors: *const c_char, ) -> *mut PyObject; pub fn PyCodec_StreamWriter( encoding: *const c_char, stream: *mut PyObject, errors: *const c_char, ) -> *mut PyObject; pub fn PyCodec_RegisterError(name: *const c_char, error: *mut PyObject) -> c_int; pub fn PyCodec_LookupError(name: *const c_char) -> *mut PyObject; pub fn PyCodec_StrictErrors(exc: *mut PyObject) -> *mut PyObject; pub fn PyCodec_IgnoreErrors(exc: *mut PyObject) -> *mut PyObject; pub fn PyCodec_ReplaceErrors(exc: *mut PyObject) -> *mut PyObject; pub fn PyCodec_XMLCharRefReplaceErrors(exc: *mut PyObject) -> *mut PyObject; pub fn PyCodec_BackslashReplaceErrors(exc: *mut PyObject) -> *mut PyObject; // skipped non-limited PyCodec_NameReplaceErrors from Include/codecs.h // skipped non-limited Py_hexdigits from Include/codecs.h } pyo3-ffi/src/pythonrun.rs0000644000175000017500000000543014661133735016402 0ustar jamespagejamespageuse crate::object::*; #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] use libc::FILE; #[cfg(any(Py_LIMITED_API, not(Py_3_10), PyPy, GraalPy))] use std::os::raw::c_char; use std::os::raw::c_int; extern "C" { #[cfg(any(all(Py_LIMITED_API, not(PyPy)), GraalPy))] pub fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_Print")] pub fn PyErr_Print(); #[cfg_attr(PyPy, link_name = "PyPyErr_PrintEx")] pub fn PyErr_PrintEx(arg1: c_int); #[cfg_attr(PyPy, link_name = "PyPyErr_Display")] pub fn PyErr_Display(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject); #[cfg(Py_3_12)] pub fn PyErr_DisplayException(exc: *mut PyObject); } #[inline] #[cfg(PyPy)] pub unsafe fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject { // PyPy's implementation of Py_CompileString always forwards to Py_CompileStringFlags; this // is only available in the non-limited API and has a real definition for all versions in // the cpython/ subdirectory. #[cfg(Py_LIMITED_API)] extern "C" { #[link_name = "PyPy_CompileStringFlags"] pub fn Py_CompileStringFlags( string: *const c_char, p: *const c_char, s: c_int, f: *mut std::os::raw::c_void, // Actually *mut Py_CompilerFlags in the real definition ) -> *mut PyObject; } #[cfg(not(Py_LIMITED_API))] use crate::Py_CompileStringFlags; Py_CompileStringFlags(string, p, s, std::ptr::null_mut()) } // skipped PyOS_InputHook pub const PYOS_STACK_MARGIN: c_int = 2048; // skipped PyOS_CheckStack under Microsoft C #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] opaque_struct!(_mod); #[cfg(not(any(PyPy, Py_3_10)))] opaque_struct!(symtable); #[cfg(not(any(PyPy, Py_3_10)))] opaque_struct!(_node); #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[inline] pub unsafe fn PyParser_SimpleParseString(s: *const c_char, b: c_int) -> *mut _node { #[allow(deprecated)] crate::PyParser_SimpleParseStringFlags(s, b, 0) } #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[inline] pub unsafe fn PyParser_SimpleParseFile(fp: *mut FILE, s: *const c_char, b: c_int) -> *mut _node { #[allow(deprecated)] crate::PyParser_SimpleParseFileFlags(fp, s, b, 0) } extern "C" { #[cfg(not(any(PyPy, Py_3_10)))] pub fn Py_SymtableString( str: *const c_char, filename: *const c_char, start: c_int, ) -> *mut symtable; #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] pub fn Py_SymtableStringObject( str: *const c_char, filename: *mut PyObject, start: c_int, ) -> *mut symtable; } pyo3-ffi/src/traceback.rs0000644000175000017500000000145514661133735016256 0ustar jamespagejamespageuse crate::object::*; use std::os::raw::c_int; #[cfg(not(PyPy))] use std::ptr::addr_of_mut; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyTraceBack_Here")] pub fn PyTraceBack_Here(arg1: *mut crate::PyFrameObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyTraceBack_Print")] pub fn PyTraceBack_Print(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyTraceBack_Type")] pub static mut PyTraceBack_Type: PyTypeObject; #[cfg(PyPy)] #[link_name = "PyPyTraceBack_Check"] pub fn PyTraceBack_Check(op: *mut PyObject) -> c_int; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyTraceBack_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyTraceBack_Type)) as c_int } pyo3-ffi/src/longobject.rs0000644000175000017500000001111414661133735016456 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use libc::size_t; use std::os::raw::{c_char, c_double, c_int, c_long, c_longlong, c_ulong, c_ulonglong, c_void}; use std::ptr::addr_of_mut; opaque_struct!(PyLongObject); #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyLong_Type")] pub static mut PyLong_Type: PyTypeObject; } #[inline] pub unsafe fn PyLong_Check(op: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS) } #[inline] pub unsafe fn PyLong_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyLong_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyLong_FromLong")] pub fn PyLong_FromLong(arg1: c_long) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_FromUnsignedLong")] pub fn PyLong_FromUnsignedLong(arg1: c_ulong) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_FromSize_t")] pub fn PyLong_FromSize_t(arg1: size_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_FromSsize_t")] pub fn PyLong_FromSsize_t(arg1: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_FromDouble")] pub fn PyLong_FromDouble(arg1: c_double) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_AsLong")] pub fn PyLong_AsLong(arg1: *mut PyObject) -> c_long; #[cfg_attr(PyPy, link_name = "PyPyLong_AsLongAndOverflow")] pub fn PyLong_AsLongAndOverflow(arg1: *mut PyObject, arg2: *mut c_int) -> c_long; #[cfg_attr(PyPy, link_name = "PyPyLong_AsSsize_t")] pub fn PyLong_AsSsize_t(arg1: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyLong_AsSize_t")] pub fn PyLong_AsSize_t(arg1: *mut PyObject) -> size_t; #[cfg_attr(PyPy, link_name = "PyPyLong_AsUnsignedLong")] pub fn PyLong_AsUnsignedLong(arg1: *mut PyObject) -> c_ulong; #[cfg_attr(PyPy, link_name = "PyPyLong_AsUnsignedLongMask")] pub fn PyLong_AsUnsignedLongMask(arg1: *mut PyObject) -> c_ulong; // skipped non-limited _PyLong_AsInt pub fn PyLong_GetInfo() -> *mut PyObject; // skipped PyLong_AS_LONG // skipped PyLong_FromPid // skipped PyLong_AsPid // skipped _Py_PARSE_INTPTR // skipped _Py_PARSE_UINTPTR // skipped non-limited _PyLong_UnsignedShort_Converter // skipped non-limited _PyLong_UnsignedInt_Converter // skipped non-limited _PyLong_UnsignedLong_Converter // skipped non-limited _PyLong_UnsignedLongLong_Converter // skipped non-limited _PyLong_Size_t_Converter // skipped non-limited _PyLong_DigitValue // skipped non-limited _PyLong_Frexp #[cfg_attr(PyPy, link_name = "PyPyLong_AsDouble")] pub fn PyLong_AsDouble(arg1: *mut PyObject) -> c_double; #[cfg_attr(PyPy, link_name = "PyPyLong_FromVoidPtr")] pub fn PyLong_FromVoidPtr(arg1: *mut c_void) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_AsVoidPtr")] pub fn PyLong_AsVoidPtr(arg1: *mut PyObject) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyLong_FromLongLong")] pub fn PyLong_FromLongLong(arg1: c_longlong) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_FromUnsignedLongLong")] pub fn PyLong_FromUnsignedLongLong(arg1: c_ulonglong) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyLong_AsLongLong")] pub fn PyLong_AsLongLong(arg1: *mut PyObject) -> c_longlong; #[cfg_attr(PyPy, link_name = "PyPyLong_AsUnsignedLongLong")] pub fn PyLong_AsUnsignedLongLong(arg1: *mut PyObject) -> c_ulonglong; #[cfg_attr(PyPy, link_name = "PyPyLong_AsUnsignedLongLongMask")] pub fn PyLong_AsUnsignedLongLongMask(arg1: *mut PyObject) -> c_ulonglong; #[cfg_attr(PyPy, link_name = "PyPyLong_AsLongLongAndOverflow")] pub fn PyLong_AsLongLongAndOverflow(arg1: *mut PyObject, arg2: *mut c_int) -> c_longlong; #[cfg_attr(PyPy, link_name = "PyPyLong_FromString")] pub fn PyLong_FromString( arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int, ) -> *mut PyObject; } #[cfg(not(Py_LIMITED_API))] extern "C" { #[cfg_attr(PyPy, link_name = "_PyPyLong_NumBits")] #[cfg(not(Py_3_13))] pub fn _PyLong_NumBits(obj: *mut PyObject) -> size_t; } // skipped non-limited _PyLong_Format // skipped non-limited _PyLong_FormatWriter // skipped non-limited _PyLong_FormatBytesWriter // skipped non-limited _PyLong_FormatAdvancedWriter extern "C" { pub fn PyOS_strtoul(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulong; pub fn PyOS_strtol(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_long; } // skipped non-limited _PyLong_Rshift // skipped non-limited _PyLong_Lshift pyo3-ffi/src/descrobject.rs0000644000175000017500000001123014661133735016616 0ustar jamespagejamespageuse crate::methodobject::PyMethodDef; use crate::object::{PyObject, PyTypeObject}; use crate::Py_ssize_t; use std::os::raw::{c_char, c_int, c_void}; use std::ptr; pub type getter = unsafe extern "C" fn(slf: *mut PyObject, closure: *mut c_void) -> *mut PyObject; pub type setter = unsafe extern "C" fn(slf: *mut PyObject, value: *mut PyObject, closure: *mut c_void) -> c_int; /// Represents the [PyGetSetDef](https://docs.python.org/3/c-api/structures.html#c.PyGetSetDef) /// structure. /// /// Note that CPython may leave fields uninitialized. You must ensure that /// `name` != NULL before dereferencing or reading other fields. #[repr(C)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct PyGetSetDef { pub name: *const c_char, pub get: Option, pub set: Option, pub doc: *const c_char, pub closure: *mut c_void, } impl Default for PyGetSetDef { fn default() -> PyGetSetDef { PyGetSetDef { name: ptr::null(), get: None, set: None, doc: ptr::null(), closure: ptr::null_mut(), } } } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyClassMethodDescr_Type")] pub static mut PyClassMethodDescr_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyGetSetDescr_Type")] pub static mut PyGetSetDescr_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyMemberDescr_Type")] pub static mut PyMemberDescr_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyMethodDescr_Type")] pub static mut PyMethodDescr_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyWrapperDescr_Type")] pub static mut PyWrapperDescr_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyDictProxy_Type")] pub static mut PyDictProxy_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyProperty_Type")] pub static mut PyProperty_Type: PyTypeObject; } extern "C" { pub fn PyDescr_NewMethod(arg1: *mut PyTypeObject, arg2: *mut PyMethodDef) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDescr_NewClassMethod")] pub fn PyDescr_NewClassMethod(arg1: *mut PyTypeObject, arg2: *mut PyMethodDef) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDescr_NewMember")] pub fn PyDescr_NewMember(arg1: *mut PyTypeObject, arg2: *mut PyMemberDef) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDescr_NewGetSet")] pub fn PyDescr_NewGetSet(arg1: *mut PyTypeObject, arg2: *mut PyGetSetDef) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyDictProxy_New")] pub fn PyDictProxy_New(arg1: *mut PyObject) -> *mut PyObject; pub fn PyWrapper_New(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; } /// Represents the [PyMemberDef](https://docs.python.org/3/c-api/structures.html#c.PyMemberDef) /// structure. /// /// Note that CPython may leave fields uninitialized. You must always ensure that /// `name` != NULL before dereferencing or reading other fields. #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq)] pub struct PyMemberDef { pub name: *const c_char, pub type_code: c_int, pub offset: Py_ssize_t, pub flags: c_int, pub doc: *const c_char, } impl Default for PyMemberDef { fn default() -> PyMemberDef { PyMemberDef { name: ptr::null_mut(), type_code: 0, offset: 0, flags: 0, doc: ptr::null_mut(), } } } /* Types */ pub const Py_T_SHORT: c_int = 0; pub const Py_T_INT: c_int = 1; pub const Py_T_LONG: c_int = 2; pub const Py_T_FLOAT: c_int = 3; pub const Py_T_DOUBLE: c_int = 4; pub const Py_T_STRING: c_int = 5; #[deprecated(note = "Use Py_T_OBJECT_EX instead")] pub const _Py_T_OBJECT: c_int = 6; pub const Py_T_CHAR: c_int = 7; pub const Py_T_BYTE: c_int = 8; pub const Py_T_UBYTE: c_int = 9; pub const Py_T_USHORT: c_int = 10; pub const Py_T_UINT: c_int = 11; pub const Py_T_ULONG: c_int = 12; pub const Py_T_STRING_INPLACE: c_int = 13; pub const Py_T_BOOL: c_int = 14; pub const Py_T_OBJECT_EX: c_int = 16; pub const Py_T_LONGLONG: c_int = 17; pub const Py_T_ULONGLONG: c_int = 18; pub const Py_T_PYSSIZET: c_int = 19; #[deprecated(note = "Value is always none")] pub const _Py_T_NONE: c_int = 20; /* Flags */ pub const Py_READONLY: c_int = 1; #[cfg(Py_3_10)] pub const Py_AUDIT_READ: c_int = 2; // Added in 3.10, harmless no-op before that #[deprecated] pub const _Py_WRITE_RESTRICTED: c_int = 4; // Deprecated, no-op. Do not reuse the value. pub const Py_RELATIVE_OFFSET: c_int = 8; extern "C" { pub fn PyMember_GetOne(addr: *const c_char, l: *mut PyMemberDef) -> *mut PyObject; pub fn PyMember_SetOne(addr: *mut c_char, l: *mut PyMemberDef, value: *mut PyObject) -> c_int; } pyo3-ffi/src/pystate.rs0000644000175000017500000000603014661133735016022 0ustar jamespagejamespage#[cfg(any(not(PyPy), Py_3_9))] use crate::moduleobject::PyModuleDef; use crate::object::PyObject; use std::os::raw::c_int; #[cfg(not(PyPy))] use std::os::raw::c_long; pub const MAX_CO_EXTRA_USERS: c_int = 255; opaque_struct!(PyThreadState); opaque_struct!(PyInterpreterState); extern "C" { #[cfg(not(PyPy))] pub fn PyInterpreterState_New() -> *mut PyInterpreterState; #[cfg(not(PyPy))] pub fn PyInterpreterState_Clear(arg1: *mut PyInterpreterState); #[cfg(not(PyPy))] pub fn PyInterpreterState_Delete(arg1: *mut PyInterpreterState); #[cfg(all(Py_3_9, not(PyPy)))] pub fn PyInterpreterState_Get() -> *mut PyInterpreterState; #[cfg(all(Py_3_8, not(PyPy)))] pub fn PyInterpreterState_GetDict(arg1: *mut PyInterpreterState) -> *mut PyObject; #[cfg(not(PyPy))] pub fn PyInterpreterState_GetID(arg1: *mut PyInterpreterState) -> i64; #[cfg(any(not(PyPy), Py_3_9))] // only on PyPy since 3.9 #[cfg_attr(PyPy, link_name = "PyPyState_AddModule")] pub fn PyState_AddModule(arg1: *mut PyObject, arg2: *mut PyModuleDef) -> c_int; #[cfg(any(not(PyPy), Py_3_9))] // only on PyPy since 3.9 #[cfg_attr(PyPy, link_name = "PyPyState_RemoveModule")] pub fn PyState_RemoveModule(arg1: *mut PyModuleDef) -> c_int; #[cfg(any(not(PyPy), Py_3_9))] // only on PyPy since 3.9 // only has PyPy prefix since 3.10 #[cfg_attr(all(PyPy, Py_3_10), link_name = "PyPyState_FindModule")] pub fn PyState_FindModule(arg1: *mut PyModuleDef) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyThreadState_New")] pub fn PyThreadState_New(arg1: *mut PyInterpreterState) -> *mut PyThreadState; #[cfg_attr(PyPy, link_name = "PyPyThreadState_Clear")] pub fn PyThreadState_Clear(arg1: *mut PyThreadState); #[cfg_attr(PyPy, link_name = "PyPyThreadState_Delete")] pub fn PyThreadState_Delete(arg1: *mut PyThreadState); #[cfg_attr(PyPy, link_name = "PyPyThreadState_Get")] pub fn PyThreadState_Get() -> *mut PyThreadState; } #[inline] pub unsafe fn PyThreadState_GET() -> *mut PyThreadState { PyThreadState_Get() } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyThreadState_Swap")] pub fn PyThreadState_Swap(arg1: *mut PyThreadState) -> *mut PyThreadState; #[cfg_attr(PyPy, link_name = "PyPyThreadState_GetDict")] pub fn PyThreadState_GetDict() -> *mut PyObject; #[cfg(not(PyPy))] pub fn PyThreadState_SetAsyncExc(arg1: c_long, arg2: *mut PyObject) -> c_int; } // skipped non-limited / 3.9 PyThreadState_GetInterpreter // skipped non-limited / 3.9 PyThreadState_GetFrame // skipped non-limited / 3.9 PyThreadState_GetID #[repr(C)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PyGILState_STATE { PyGILState_LOCKED, PyGILState_UNLOCKED, } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure")] pub fn PyGILState_Ensure() -> PyGILState_STATE; #[cfg_attr(PyPy, link_name = "PyPyGILState_Release")] pub fn PyGILState_Release(arg1: PyGILState_STATE); #[cfg(not(PyPy))] pub fn PyGILState_GetThisThreadState() -> *mut PyThreadState; } pyo3-ffi/src/pyport.rs0000644000175000017500000000131414661133735015666 0ustar jamespagejamespagepub type PY_UINT32_T = u32; pub type PY_UINT64_T = u64; pub type PY_INT32_T = i32; pub type PY_INT64_T = i64; pub type Py_uintptr_t = ::libc::uintptr_t; pub type Py_intptr_t = ::libc::intptr_t; pub type Py_ssize_t = ::libc::ssize_t; pub type Py_hash_t = Py_ssize_t; pub type Py_uhash_t = ::libc::size_t; pub const PY_SSIZE_T_MIN: Py_ssize_t = isize::MIN as Py_ssize_t; pub const PY_SSIZE_T_MAX: Py_ssize_t = isize::MAX as Py_ssize_t; #[cfg(target_endian = "big")] pub const PY_BIG_ENDIAN: usize = 1; #[cfg(target_endian = "big")] pub const PY_LITTLE_ENDIAN: usize = 0; #[cfg(target_endian = "little")] pub const PY_BIG_ENDIAN: usize = 0; #[cfg(target_endian = "little")] pub const PY_LITTLE_ENDIAN: usize = 1; pyo3-ffi/src/enumobject.rs0000644000175000017500000000027714661133735016473 0ustar jamespagejamespageuse crate::object::PyTypeObject; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyEnum_Type: PyTypeObject; pub static mut PyReversed_Type: PyTypeObject; } pyo3-ffi/src/pyerrors.rs0000644000175000017500000004236214661133735016226 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyErr_SetNone")] pub fn PyErr_SetNone(arg1: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyErr_SetObject")] pub fn PyErr_SetObject(arg1: *mut PyObject, arg2: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyErr_SetString")] pub fn PyErr_SetString(exception: *mut PyObject, string: *const c_char); #[cfg_attr(PyPy, link_name = "PyPyErr_Occurred")] pub fn PyErr_Occurred() -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_Clear")] pub fn PyErr_Clear(); #[cfg_attr(Py_3_12, deprecated(note = "Use PyErr_GetRaisedException() instead."))] #[cfg_attr(PyPy, link_name = "PyPyErr_Fetch")] pub fn PyErr_Fetch( arg1: *mut *mut PyObject, arg2: *mut *mut PyObject, arg3: *mut *mut PyObject, ); #[cfg_attr(Py_3_12, deprecated(note = "Use PyErr_SetRaisedException() instead."))] #[cfg_attr(PyPy, link_name = "PyPyErr_Restore")] pub fn PyErr_Restore(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyErr_GetExcInfo")] pub fn PyErr_GetExcInfo( arg1: *mut *mut PyObject, arg2: *mut *mut PyObject, arg3: *mut *mut PyObject, ); #[cfg_attr(PyPy, link_name = "PyPyErr_SetExcInfo")] pub fn PyErr_SetExcInfo(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPy_FatalError")] pub fn Py_FatalError(message: *const c_char) -> !; #[cfg_attr(PyPy, link_name = "PyPyErr_GivenExceptionMatches")] pub fn PyErr_GivenExceptionMatches(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyErr_ExceptionMatches")] pub fn PyErr_ExceptionMatches(arg1: *mut PyObject) -> c_int; #[cfg_attr( Py_3_12, deprecated( note = "Use PyErr_GetRaisedException() instead, to avoid any possible de-normalization." ) )] #[cfg_attr(PyPy, link_name = "PyPyErr_NormalizeException")] pub fn PyErr_NormalizeException( arg1: *mut *mut PyObject, arg2: *mut *mut PyObject, arg3: *mut *mut PyObject, ); #[cfg(Py_3_12)] pub fn PyErr_GetRaisedException() -> *mut PyObject; #[cfg(Py_3_12)] pub fn PyErr_SetRaisedException(exc: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyException_SetTraceback")] pub fn PyException_SetTraceback(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyException_GetTraceback")] pub fn PyException_GetTraceback(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyException_GetCause")] pub fn PyException_GetCause(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyException_SetCause")] pub fn PyException_SetCause(arg1: *mut PyObject, arg2: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyException_GetContext")] pub fn PyException_GetContext(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyException_SetContext")] pub fn PyException_SetContext(arg1: *mut PyObject, arg2: *mut PyObject); #[cfg(PyPy)] #[link_name = "PyPyExceptionInstance_Class"] pub fn PyExceptionInstance_Class(x: *mut PyObject) -> *mut PyObject; } #[inline] pub unsafe fn PyExceptionClass_Check(x: *mut PyObject) -> c_int { (PyType_Check(x) != 0 && PyType_FastSubclass(x as *mut PyTypeObject, Py_TPFLAGS_BASE_EXC_SUBCLASS) != 0) as c_int } #[inline] pub unsafe fn PyExceptionInstance_Check(x: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(x), Py_TPFLAGS_BASE_EXC_SUBCLASS) } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyExceptionInstance_Class(x: *mut PyObject) -> *mut PyObject { Py_TYPE(x) as *mut PyObject } // ported from cpython exception.c (line 2096) #[cfg(PyPy)] pub unsafe fn PyUnicodeDecodeError_Create( encoding: *const c_char, object: *const c_char, length: Py_ssize_t, start: Py_ssize_t, end: Py_ssize_t, reason: *const c_char, ) -> *mut PyObject { crate::_PyObject_CallFunction_SizeT( PyExc_UnicodeDecodeError, c_str!("sy#nns").as_ptr(), encoding, object, length, start, end, reason, ) } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyExc_BaseException")] pub static mut PyExc_BaseException: *mut PyObject; #[cfg(Py_3_11)] pub static mut PyExc_BaseExceptionGroup: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_Exception")] pub static mut PyExc_Exception: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_StopAsyncIteration")] pub static mut PyExc_StopAsyncIteration: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_StopIteration")] pub static mut PyExc_StopIteration: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_GeneratorExit")] pub static mut PyExc_GeneratorExit: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ArithmeticError")] pub static mut PyExc_ArithmeticError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_LookupError")] pub static mut PyExc_LookupError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_AssertionError")] pub static mut PyExc_AssertionError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_AttributeError")] pub static mut PyExc_AttributeError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_BufferError")] pub static mut PyExc_BufferError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_EOFError")] pub static mut PyExc_EOFError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_FloatingPointError")] pub static mut PyExc_FloatingPointError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_OSError")] pub static mut PyExc_OSError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ImportError")] pub static mut PyExc_ImportError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ModuleNotFoundError")] pub static mut PyExc_ModuleNotFoundError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_IndexError")] pub static mut PyExc_IndexError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_KeyError")] pub static mut PyExc_KeyError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_KeyboardInterrupt")] pub static mut PyExc_KeyboardInterrupt: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_MemoryError")] pub static mut PyExc_MemoryError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_NameError")] pub static mut PyExc_NameError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_OverflowError")] pub static mut PyExc_OverflowError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_RuntimeError")] pub static mut PyExc_RuntimeError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_RecursionError")] pub static mut PyExc_RecursionError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_NotImplementedError")] pub static mut PyExc_NotImplementedError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_SyntaxError")] pub static mut PyExc_SyntaxError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_IndentationError")] pub static mut PyExc_IndentationError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_TabError")] pub static mut PyExc_TabError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ReferenceError")] pub static mut PyExc_ReferenceError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_SystemError")] pub static mut PyExc_SystemError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_SystemExit")] pub static mut PyExc_SystemExit: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_TypeError")] pub static mut PyExc_TypeError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_UnboundLocalError")] pub static mut PyExc_UnboundLocalError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_UnicodeError")] pub static mut PyExc_UnicodeError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_UnicodeEncodeError")] pub static mut PyExc_UnicodeEncodeError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_UnicodeDecodeError")] pub static mut PyExc_UnicodeDecodeError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_UnicodeTranslateError")] pub static mut PyExc_UnicodeTranslateError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ValueError")] pub static mut PyExc_ValueError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ZeroDivisionError")] pub static mut PyExc_ZeroDivisionError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_BlockingIOError")] pub static mut PyExc_BlockingIOError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_BrokenPipeError")] pub static mut PyExc_BrokenPipeError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ChildProcessError")] pub static mut PyExc_ChildProcessError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ConnectionError")] pub static mut PyExc_ConnectionError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ConnectionAbortedError")] pub static mut PyExc_ConnectionAbortedError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ConnectionRefusedError")] pub static mut PyExc_ConnectionRefusedError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ConnectionResetError")] pub static mut PyExc_ConnectionResetError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_FileExistsError")] pub static mut PyExc_FileExistsError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_FileNotFoundError")] pub static mut PyExc_FileNotFoundError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_InterruptedError")] pub static mut PyExc_InterruptedError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_IsADirectoryError")] pub static mut PyExc_IsADirectoryError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_NotADirectoryError")] pub static mut PyExc_NotADirectoryError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_PermissionError")] pub static mut PyExc_PermissionError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ProcessLookupError")] pub static mut PyExc_ProcessLookupError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_TimeoutError")] pub static mut PyExc_TimeoutError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_OSError")] pub static mut PyExc_EnvironmentError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_OSError")] pub static mut PyExc_IOError: *mut PyObject; #[cfg(windows)] #[cfg_attr(PyPy, link_name = "PyPyExc_OSError")] pub static mut PyExc_WindowsError: *mut PyObject; pub static mut PyExc_RecursionErrorInst: *mut PyObject; /* Predefined warning categories */ #[cfg_attr(PyPy, link_name = "PyPyExc_Warning")] pub static mut PyExc_Warning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_UserWarning")] pub static mut PyExc_UserWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_DeprecationWarning")] pub static mut PyExc_DeprecationWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_PendingDeprecationWarning")] pub static mut PyExc_PendingDeprecationWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_SyntaxWarning")] pub static mut PyExc_SyntaxWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_RuntimeWarning")] pub static mut PyExc_RuntimeWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_FutureWarning")] pub static mut PyExc_FutureWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ImportWarning")] pub static mut PyExc_ImportWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_UnicodeWarning")] pub static mut PyExc_UnicodeWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_BytesWarning")] pub static mut PyExc_BytesWarning: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ResourceWarning")] pub static mut PyExc_ResourceWarning: *mut PyObject; #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "PyPyExc_EncodingWarning")] pub static mut PyExc_EncodingWarning: *mut PyObject; } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyErr_BadArgument")] pub fn PyErr_BadArgument() -> c_int; #[cfg_attr(PyPy, link_name = "PyPyErr_NoMemory")] pub fn PyErr_NoMemory() -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_SetFromErrno")] pub fn PyErr_SetFromErrno(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_SetFromErrnoWithFilenameObject")] pub fn PyErr_SetFromErrnoWithFilenameObject( arg1: *mut PyObject, arg2: *mut PyObject, ) -> *mut PyObject; pub fn PyErr_SetFromErrnoWithFilenameObjects( arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject, ) -> *mut PyObject; pub fn PyErr_SetFromErrnoWithFilename( exc: *mut PyObject, filename: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_Format")] pub fn PyErr_Format(exception: *mut PyObject, format: *const c_char, ...) -> *mut PyObject; pub fn PyErr_SetImportErrorSubclass( arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject, arg4: *mut PyObject, ) -> *mut PyObject; pub fn PyErr_SetImportError( arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_BadInternalCall")] pub fn PyErr_BadInternalCall(); pub fn _PyErr_BadInternalCall(filename: *const c_char, lineno: c_int); #[cfg_attr(PyPy, link_name = "PyPyErr_NewException")] pub fn PyErr_NewException( name: *const c_char, base: *mut PyObject, dict: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_NewExceptionWithDoc")] pub fn PyErr_NewExceptionWithDoc( name: *const c_char, doc: *const c_char, base: *mut PyObject, dict: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_WriteUnraisable")] pub fn PyErr_WriteUnraisable(arg1: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyErr_CheckSignals")] pub fn PyErr_CheckSignals() -> c_int; #[cfg_attr(PyPy, link_name = "PyPyErr_SetInterrupt")] pub fn PyErr_SetInterrupt(); #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "PyPyErr_SetInterruptEx")] pub fn PyErr_SetInterruptEx(signum: c_int); #[cfg_attr(PyPy, link_name = "PyPyErr_SyntaxLocation")] pub fn PyErr_SyntaxLocation(filename: *const c_char, lineno: c_int); #[cfg_attr(PyPy, link_name = "PyPyErr_SyntaxLocationEx")] pub fn PyErr_SyntaxLocationEx(filename: *const c_char, lineno: c_int, col_offset: c_int); #[cfg_attr(PyPy, link_name = "PyPyErr_ProgramText")] pub fn PyErr_ProgramText(filename: *const c_char, lineno: c_int) -> *mut PyObject; #[cfg(not(PyPy))] pub fn PyUnicodeDecodeError_Create( encoding: *const c_char, object: *const c_char, length: Py_ssize_t, start: Py_ssize_t, end: Py_ssize_t, reason: *const c_char, ) -> *mut PyObject; pub fn PyUnicodeEncodeError_GetEncoding(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeDecodeError_GetEncoding(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeEncodeError_GetObject(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeDecodeError_GetObject(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeTranslateError_GetObject(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeEncodeError_GetStart(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int; pub fn PyUnicodeDecodeError_GetStart(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int; pub fn PyUnicodeTranslateError_GetStart(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int; pub fn PyUnicodeEncodeError_SetStart(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int; pub fn PyUnicodeDecodeError_SetStart(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int; pub fn PyUnicodeTranslateError_SetStart(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int; pub fn PyUnicodeEncodeError_GetEnd(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int; pub fn PyUnicodeDecodeError_GetEnd(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int; pub fn PyUnicodeTranslateError_GetEnd(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int; pub fn PyUnicodeEncodeError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int; pub fn PyUnicodeDecodeError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int; pub fn PyUnicodeTranslateError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int; pub fn PyUnicodeEncodeError_GetReason(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeDecodeError_GetReason(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeTranslateError_GetReason(arg1: *mut PyObject) -> *mut PyObject; pub fn PyUnicodeEncodeError_SetReason(exc: *mut PyObject, reason: *const c_char) -> c_int; pub fn PyUnicodeDecodeError_SetReason(exc: *mut PyObject, reason: *const c_char) -> c_int; pub fn PyUnicodeTranslateError_SetReason(exc: *mut PyObject, reason: *const c_char) -> c_int; } pyo3-ffi/src/complexobject.rs0000644000175000017500000000415014661133735017170 0ustar jamespagejamespageuse crate::object::*; use std::os::raw::{c_double, c_int}; use std::ptr::addr_of_mut; #[repr(C)] #[derive(Copy, Clone)] // non-limited pub struct Py_complex { pub real: c_double, pub imag: c_double, } #[cfg(not(Py_LIMITED_API))] extern "C" { pub fn _Py_c_sum(left: Py_complex, right: Py_complex) -> Py_complex; pub fn _Py_c_diff(left: Py_complex, right: Py_complex) -> Py_complex; pub fn _Py_c_neg(complex: Py_complex) -> Py_complex; pub fn _Py_c_prod(left: Py_complex, right: Py_complex) -> Py_complex; pub fn _Py_c_quot(dividend: Py_complex, divisor: Py_complex) -> Py_complex; pub fn _Py_c_pow(num: Py_complex, exp: Py_complex) -> Py_complex; pub fn _Py_c_abs(arg: Py_complex) -> c_double; #[cfg_attr(PyPy, link_name = "PyPyComplex_FromCComplex")] pub fn PyComplex_FromCComplex(v: Py_complex) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyComplex_AsCComplex")] pub fn PyComplex_AsCComplex(op: *mut PyObject) -> Py_complex; } #[repr(C)] #[derive(Copy, Clone)] // non-limited pub struct PyComplexObject { pub ob_base: PyObject, #[cfg(not(GraalPy))] pub cval: Py_complex, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyComplex_Type")] pub static mut PyComplex_Type: PyTypeObject; } #[inline] pub unsafe fn PyComplex_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyComplex_Type)) } #[inline] pub unsafe fn PyComplex_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyComplex_Type)) as c_int } extern "C" { // skipped non-limited PyComplex_FromCComplex #[cfg_attr(PyPy, link_name = "PyPyComplex_FromDoubles")] pub fn PyComplex_FromDoubles(real: c_double, imag: c_double) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyComplex_RealAsDouble")] pub fn PyComplex_RealAsDouble(op: *mut PyObject) -> c_double; #[cfg_attr(PyPy, link_name = "PyPyComplex_ImagAsDouble")] pub fn PyComplex_ImagAsDouble(op: *mut PyObject) -> c_double; // skipped non-limited PyComplex_AsCComplex // skipped non-limited _PyComplex_FormatAdvancedWriter } pyo3-ffi/src/osmodule.rs0000644000175000017500000000023614661133735016162 0ustar jamespagejamespageuse crate::object::PyObject; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyOS_FSPath")] pub fn PyOS_FSPath(path: *mut PyObject) -> *mut PyObject; } pyo3-ffi/src/bytesobject.rs0000644000175000017500000000446314661133735016656 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyBytes_Type")] pub static mut PyBytes_Type: PyTypeObject; pub static mut PyBytesIter_Type: PyTypeObject; } #[inline] pub unsafe fn PyBytes_Check(op: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_BYTES_SUBCLASS) } #[inline] pub unsafe fn PyBytes_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyBytes_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyBytes_FromStringAndSize")] pub fn PyBytes_FromStringAndSize(arg1: *const c_char, arg2: Py_ssize_t) -> *mut PyObject; pub fn PyBytes_FromString(arg1: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyBytes_FromObject")] pub fn PyBytes_FromObject(arg1: *mut PyObject) -> *mut PyObject; // skipped PyBytes_FromFormatV //#[cfg_attr(PyPy, link_name = "PyPyBytes_FromFormatV")] //pub fn PyBytes_FromFormatV(arg1: *const c_char, arg2: va_list) // -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyBytes_FromFormat")] pub fn PyBytes_FromFormat(arg1: *const c_char, ...) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyBytes_Size")] pub fn PyBytes_Size(arg1: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyBytes_AsString")] pub fn PyBytes_AsString(arg1: *mut PyObject) -> *mut c_char; pub fn PyBytes_Repr(arg1: *mut PyObject, arg2: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyBytes_Concat")] pub fn PyBytes_Concat(arg1: *mut *mut PyObject, arg2: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyBytes_ConcatAndDel")] pub fn PyBytes_ConcatAndDel(arg1: *mut *mut PyObject, arg2: *mut PyObject); pub fn PyBytes_DecodeEscape( arg1: *const c_char, arg2: Py_ssize_t, arg3: *const c_char, arg4: Py_ssize_t, arg5: *const c_char, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyBytes_AsStringAndSize")] pub fn PyBytes_AsStringAndSize( obj: *mut PyObject, s: *mut *mut c_char, len: *mut Py_ssize_t, ) -> c_int; } // skipped F_LJUST // skipped F_SIGN // skipped F_BLANK // skipped F_ALT // skipped F_ZERO pyo3-ffi/src/context.rs0000644000175000017500000000310414661133735016014 0ustar jamespagejamespageuse crate::object::{PyObject, PyTypeObject, Py_TYPE}; use std::os::raw::{c_char, c_int}; use std::ptr::addr_of_mut; extern "C" { pub static mut PyContext_Type: PyTypeObject; // skipped non-limited opaque PyContext pub static mut PyContextVar_Type: PyTypeObject; // skipped non-limited opaque PyContextVar pub static mut PyContextToken_Type: PyTypeObject; // skipped non-limited opaque PyContextToken } #[inline] pub unsafe fn PyContext_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyContext_Type)) as c_int } #[inline] pub unsafe fn PyContextVar_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyContextVar_Type)) as c_int } #[inline] pub unsafe fn PyContextToken_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyContextToken_Type)) as c_int } extern "C" { pub fn PyContext_New() -> *mut PyObject; pub fn PyContext_Copy(ctx: *mut PyObject) -> *mut PyObject; pub fn PyContext_CopyCurrent() -> *mut PyObject; pub fn PyContext_Enter(ctx: *mut PyObject) -> c_int; pub fn PyContext_Exit(ctx: *mut PyObject) -> c_int; pub fn PyContextVar_New(name: *const c_char, def: *mut PyObject) -> *mut PyObject; pub fn PyContextVar_Get( var: *mut PyObject, default_value: *mut PyObject, value: *mut *mut PyObject, ) -> c_int; pub fn PyContextVar_Set(var: *mut PyObject, value: *mut PyObject) -> *mut PyObject; pub fn PyContextVar_Reset(var: *mut PyObject, token: *mut PyObject) -> c_int; // skipped non-limited _PyContext_NewHamtForTests } pyo3-ffi/src/pyframe.rs0000644000175000017500000000073114661133735015776 0ustar jamespagejamespage#[cfg(not(GraalPy))] #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] use crate::PyCodeObject; #[cfg(not(Py_LIMITED_API))] use crate::PyFrameObject; use std::os::raw::c_int; #[cfg(Py_LIMITED_API)] opaque_struct!(PyFrameObject); extern "C" { pub fn PyFrame_GetLineNumber(f: *mut PyFrameObject) -> c_int; #[cfg(not(GraalPy))] #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] pub fn PyFrame_GetCode(f: *mut PyFrameObject) -> *mut PyCodeObject; } pyo3-ffi/src/lib.rs0000644000175000017500000003427314661133735015111 0ustar jamespagejamespage//! Raw FFI declarations for Python's C API. //! //! PyO3 can be used to write native Python modules or run Python code and modules from Rust. //! //! This crate just provides low level bindings to the Python interpreter. //! It is meant for advanced users only - regular PyO3 users shouldn't //! need to interact with this crate at all. //! //! The contents of this crate are not documented here, as it would entail //! basically copying the documentation from CPython. Consult the [Python/C API Reference //! Manual][capi] for up-to-date documentation. //! //! # Safety //! //! The functions in this crate lack individual safety documentation, but //! generally the following apply: //! - Pointer arguments have to point to a valid Python object of the correct type, //! although null pointers are sometimes valid input. //! - The vast majority can only be used safely while the GIL is held. //! - Some functions have additional safety requirements, consult the //! [Python/C API Reference Manual][capi] //! for more information. //! //! //! # Feature flags //! //! PyO3 uses [feature flags] to enable you to opt-in to additional functionality. For a detailed //! description, see the [Features chapter of the guide]. //! //! ## Optional feature flags //! //! The following features customize PyO3's behavior: //! //! - `abi3`: Restricts PyO3's API to a subset of the full Python API which is guaranteed by //! [PEP 384] to be forward-compatible with future Python versions. //! - `extension-module`: This will tell the linker to keep the Python symbols unresolved, so that //! your module can also be used with statically linked Python interpreters. Use this feature when //! building an extension module. //! //! ## `rustc` environment flags //! //! PyO3 uses `rustc`'s `--cfg` flags to enable or disable code used for different Python versions. //! If you want to do this for your own crate, you can do so with the [`pyo3-build-config`] crate. //! //! - `Py_3_7`, `Py_3_8`, `Py_3_9`, `Py_3_10`: Marks code that is only enabled when //! compiling for a given minimum Python version. //! - `Py_LIMITED_API`: Marks code enabled when the `abi3` feature flag is enabled. //! - `PyPy` - Marks code enabled when compiling for PyPy. //! //! # Minimum supported Rust and Python versions //! //! PyO3 supports the following software versions: //! - Python 3.7 and up (CPython and PyPy) //! - Rust 1.63 and up //! //! # Example: Building Python Native modules //! //! PyO3 can be used to generate a native Python module. The easiest way to try this out for the //! first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based //! Python packages with minimal configuration. The following steps set up some files for an example //! Python module, install `maturin`, and then show how to build and import the Python module. //! //! First, create a new folder (let's call it `string_sum`) containing the following two files: //! //! **`Cargo.toml`** //! //! ```toml //! [lib] //! name = "string_sum" //! # "cdylib" is necessary to produce a shared library for Python to import from. //! # //! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able //! # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: //! # crate-type = ["cdylib", "rlib"] //! crate-type = ["cdylib"] //! //! [dependencies.pyo3-ffi] #![doc = concat!("version = \"", env!("CARGO_PKG_VERSION"), "\"")] //! features = ["extension-module"] //! ``` //! //! **`src/lib.rs`** //! ```rust //! use std::os::raw::c_char; //! use std::ptr; //! //! use pyo3_ffi::*; //! //! static mut MODULE_DEF: PyModuleDef = PyModuleDef { //! m_base: PyModuleDef_HEAD_INIT, //! m_name: c_str!("string_sum").as_ptr(), //! m_doc: c_str!("A Python module written in Rust.").as_ptr(), //! m_size: 0, //! m_methods: unsafe { METHODS.as_mut_ptr().cast() }, //! m_slots: std::ptr::null_mut(), //! m_traverse: None, //! m_clear: None, //! m_free: None, //! }; //! //! static mut METHODS: [PyMethodDef; 2] = [ //! PyMethodDef { //! ml_name: c_str!("sum_as_string").as_ptr(), //! ml_meth: PyMethodDefPointer { //! _PyCFunctionFast: sum_as_string, //! }, //! ml_flags: METH_FASTCALL, //! ml_doc: c_str!("returns the sum of two integers as a string").as_ptr(), //! }, //! // A zeroed PyMethodDef to mark the end of the array. //! PyMethodDef::zeroed() //! ]; //! //! // The module initialization function, which must be named `PyInit_`. //! #[allow(non_snake_case)] //! #[no_mangle] //! pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject { //! PyModule_Create(ptr::addr_of_mut!(MODULE_DEF)) //! } //! //! pub unsafe extern "C" fn sum_as_string( //! _self: *mut PyObject, //! args: *mut *mut PyObject, //! nargs: Py_ssize_t, //! ) -> *mut PyObject { //! if nargs != 2 { //! PyErr_SetString( //! PyExc_TypeError, //! c_str!("sum_as_string() expected 2 positional arguments").as_ptr(), //! ); //! return std::ptr::null_mut(); //! } //! //! let arg1 = *args; //! if PyLong_Check(arg1) == 0 { //! PyErr_SetString( //! PyExc_TypeError, //! c_str!("sum_as_string() expected an int for positional argument 1").as_ptr(), //! ); //! return std::ptr::null_mut(); //! } //! //! let arg1 = PyLong_AsLong(arg1); //! if !PyErr_Occurred().is_null() { //! return ptr::null_mut(); //! } //! //! let arg2 = *args.add(1); //! if PyLong_Check(arg2) == 0 { //! PyErr_SetString( //! PyExc_TypeError, //! c_str!("sum_as_string() expected an int for positional argument 2").as_ptr(), //! ); //! return std::ptr::null_mut(); //! } //! //! let arg2 = PyLong_AsLong(arg2); //! if !PyErr_Occurred().is_null() { //! return ptr::null_mut(); //! } //! //! match arg1.checked_add(arg2) { //! Some(sum) => { //! let string = sum.to_string(); //! PyUnicode_FromStringAndSize(string.as_ptr().cast::(), string.len() as isize) //! } //! None => { //! PyErr_SetString( //! PyExc_OverflowError, //! c_str!("arguments too large to add").as_ptr(), //! ); //! std::ptr::null_mut() //! } //! } //! } //! ``` //! //! With those two files in place, now `maturin` needs to be installed. This can be done using //! Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin` //! into it: //! ```bash //! $ cd string_sum //! $ python -m venv .env //! $ source .env/bin/activate //! $ pip install maturin //! ``` //! //! Now build and execute the module: //! ```bash //! $ maturin develop //! # lots of progress output as maturin runs the compilation... //! $ python //! >>> import string_sum //! >>> string_sum.sum_as_string(5, 20) //! '25' //! ``` //! //! As well as with `maturin`, it is possible to build using [setuptools-rust] or //! [manually][manual_builds]. Both offer more flexibility than `maturin` but require further //! configuration. //! //! //! # Using Python from Rust //! //! To embed Python into a Rust binary, you need to ensure that your Python installation contains a //! shared library. The following steps demonstrate how to ensure this (for Ubuntu). //! //! To install the Python shared library on Ubuntu: //! ```bash //! sudo apt install python3-dev //! ``` //! //! While most projects use the safe wrapper provided by pyo3, //! you can take a look at the [`orjson`] library as an example on how to use `pyo3-ffi` directly. //! For those well versed in C and Rust the [tutorials] from the CPython documentation //! can be easily converted to rust as well. //! //! [tutorials]: https://docs.python.org/3/extending/ //! [`orjson`]: https://github.com/ijl/orjson //! [capi]: https://docs.python.org/3/c-api/index.html //! [`maturin`]: https://github.com/PyO3/maturin "Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages" //! [`pyo3-build-config`]: https://docs.rs/pyo3-build-config //! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html "Features - The Cargo Book" #![doc = concat!("[manual_builds]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/building-and-distribution.html#manual-builds \"Manual builds - Building and Distribution - PyO3 user guide\"")] //! [setuptools-rust]: https://github.com/PyO3/setuptools-rust "Setuptools plugin for Rust extensions" //! [PEP 384]: https://www.python.org/dev/peps/pep-0384 "PEP 384 -- Defining a Stable ABI" #![doc = concat!("[Features chapter of the guide]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/features.html#features-reference \"Features Reference - PyO3 user guide\"")] #![allow( missing_docs, non_camel_case_types, non_snake_case, non_upper_case_globals, clippy::upper_case_acronyms, clippy::missing_safety_doc )] #![warn(elided_lifetimes_in_paths, unused_lifetimes)] // Until `extern type` is stabilized, use the recommended approach to // model opaque types: // https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs macro_rules! opaque_struct { ($name:ident) => { #[repr(C)] pub struct $name([u8; 0]); }; } /// This is a helper macro to create a `&'static CStr`. /// /// It can be used on all Rust versions supported by PyO3, unlike c"" literals which /// were stabilised in Rust 1.77. /// /// Due to the nature of PyO3 making heavy use of C FFI interop with Python, it is /// common for PyO3 to use CStr. /// /// Examples: /// /// ```rust /// use std::ffi::CStr; /// /// const HELLO: &CStr = pyo3_ffi::c_str!("hello"); /// static WORLD: &CStr = pyo3_ffi::c_str!("world"); /// ``` #[macro_export] macro_rules! c_str { ($s:expr) => { $crate::_cstr_from_utf8_with_nul_checked(concat!($s, "\0")) }; } /// Private helper for `c_str!` macro. #[doc(hidden)] pub const fn _cstr_from_utf8_with_nul_checked(s: &str) -> &CStr { // TODO: Replace this implementation with `CStr::from_bytes_with_nul` when MSRV above 1.72. let bytes = s.as_bytes(); let len = bytes.len(); assert!( !bytes.is_empty() && bytes[bytes.len() - 1] == b'\0', "string is not nul-terminated" ); let mut i = 0; let non_null_len = len - 1; while i < non_null_len { assert!(bytes[i] != b'\0', "string contains null bytes"); i += 1; } unsafe { CStr::from_bytes_with_nul_unchecked(bytes) } } use std::ffi::CStr; pub use self::abstract_::*; pub use self::bltinmodule::*; pub use self::boolobject::*; pub use self::bytearrayobject::*; pub use self::bytesobject::*; pub use self::ceval::*; #[cfg(Py_LIMITED_API)] pub use self::code::*; pub use self::codecs::*; pub use self::compile::*; pub use self::complexobject::*; #[cfg(all(Py_3_8, not(Py_LIMITED_API)))] pub use self::context::*; #[cfg(not(Py_LIMITED_API))] pub use self::datetime::*; pub use self::descrobject::*; pub use self::dictobject::*; pub use self::enumobject::*; pub use self::fileobject::*; pub use self::fileutils::*; pub use self::floatobject::*; pub use self::import::*; pub use self::intrcheck::*; pub use self::iterobject::*; pub use self::listobject::*; pub use self::longobject::*; #[cfg(not(Py_LIMITED_API))] pub use self::marshal::*; pub use self::memoryobject::*; pub use self::methodobject::*; pub use self::modsupport::*; pub use self::moduleobject::*; pub use self::object::*; pub use self::objimpl::*; pub use self::osmodule::*; #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] pub use self::pyarena::*; #[cfg(Py_3_11)] pub use self::pybuffer::*; pub use self::pycapsule::*; pub use self::pyerrors::*; pub use self::pyframe::*; pub use self::pyhash::*; pub use self::pylifecycle::*; pub use self::pymem::*; pub use self::pyport::*; pub use self::pystate::*; pub use self::pystrtod::*; pub use self::pythonrun::*; pub use self::rangeobject::*; pub use self::setobject::*; pub use self::sliceobject::*; pub use self::structseq::*; pub use self::sysmodule::*; pub use self::traceback::*; pub use self::tupleobject::*; pub use self::typeslots::*; pub use self::unicodeobject::*; pub use self::warnings::*; pub use self::weakrefobject::*; mod abstract_; // skipped asdl.h // skipped ast.h mod bltinmodule; mod boolobject; mod bytearrayobject; mod bytesobject; // skipped cellobject.h mod ceval; // skipped classobject.h #[cfg(Py_LIMITED_API)] mod code; mod codecs; mod compile; mod complexobject; #[cfg(all(Py_3_8, not(Py_LIMITED_API)))] mod context; // It's actually 3.7.1, but no cfg for patches. #[cfg(not(Py_LIMITED_API))] pub(crate) mod datetime; mod descrobject; mod dictobject; // skipped dynamic_annotations.h mod enumobject; // skipped errcode.h // skipped exports.h mod fileobject; mod fileutils; mod floatobject; // skipped empty frameobject.h // skipped genericaliasobject.h mod import; // skipped interpreteridobject.h mod intrcheck; mod iterobject; mod listobject; // skipped longintrepr.h mod longobject; #[cfg(not(Py_LIMITED_API))] pub mod marshal; mod memoryobject; mod methodobject; mod modsupport; mod moduleobject; // skipped namespaceobject.h mod object; mod objimpl; // skipped odictobject.h // skipped opcode.h // skipped osdefs.h mod osmodule; // skipped parser_interface.h // skipped patchlevel.h // skipped picklebufobject.h // skipped pyctype.h // skipped py_curses.h #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))] mod pyarena; #[cfg(Py_3_11)] mod pybuffer; mod pycapsule; // skipped pydtrace.h mod pyerrors; // skipped pyexpat.h // skipped pyfpe.h mod pyframe; mod pyhash; mod pylifecycle; // skipped pymacconfig.h // skipped pymacro.h // skipped pymath.h mod pymem; mod pyport; mod pystate; // skipped pystats.h mod pythonrun; // skipped pystrhex.h // skipped pystrcmp.h mod pystrtod; // skipped pythread.h // skipped pytime.h mod rangeobject; mod setobject; mod sliceobject; mod structseq; mod sysmodule; mod traceback; // skipped tracemalloc.h mod tupleobject; mod typeslots; mod unicodeobject; mod warnings; mod weakrefobject; // Additional headers that are not exported by Python.h #[deprecated(note = "Python 3.12")] pub mod structmember; // "Limited API" definitions matching Python's `include/cpython` directory. #[cfg(not(Py_LIMITED_API))] mod cpython; #[cfg(not(Py_LIMITED_API))] pub use self::cpython::*; pyo3-ffi/src/pybuffer.rs0000644000175000017500000001107014661133735016153 0ustar jamespagejamespageuse crate::object::PyObject; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int, c_void}; use std::ptr; #[repr(C)] #[derive(Copy, Clone)] pub struct Py_buffer { pub buf: *mut c_void, /// Owned reference pub obj: *mut crate::PyObject, pub len: Py_ssize_t, pub itemsize: Py_ssize_t, pub readonly: c_int, pub ndim: c_int, pub format: *mut c_char, pub shape: *mut Py_ssize_t, pub strides: *mut Py_ssize_t, pub suboffsets: *mut Py_ssize_t, pub internal: *mut c_void, #[cfg(PyPy)] pub flags: c_int, #[cfg(PyPy)] pub _strides: [Py_ssize_t; PyBUF_MAX_NDIM], #[cfg(PyPy)] pub _shape: [Py_ssize_t; PyBUF_MAX_NDIM], } impl Py_buffer { #[allow(clippy::new_without_default)] pub const fn new() -> Self { Py_buffer { buf: ptr::null_mut(), obj: ptr::null_mut(), len: 0, itemsize: 0, readonly: 0, ndim: 0, format: ptr::null_mut(), shape: ptr::null_mut(), strides: ptr::null_mut(), suboffsets: ptr::null_mut(), internal: ptr::null_mut(), #[cfg(PyPy)] flags: 0, #[cfg(PyPy)] _strides: [0; PyBUF_MAX_NDIM], #[cfg(PyPy)] _shape: [0; PyBUF_MAX_NDIM], } } } pub type getbufferproc = unsafe extern "C" fn(*mut PyObject, *mut crate::Py_buffer, c_int) -> c_int; pub type releasebufferproc = unsafe extern "C" fn(*mut PyObject, *mut crate::Py_buffer); /* Return 1 if the getbuffer function is available, otherwise return 0. */ extern "C" { #[cfg(not(PyPy))] pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_GetBuffer")] pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, flags: c_int) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_GetPointer")] pub fn PyBuffer_GetPointer(view: *const Py_buffer, indices: *const Py_ssize_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyBuffer_SizeFromFormat")] pub fn PyBuffer_SizeFromFormat(format: *const c_char) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyBuffer_ToContiguous")] pub fn PyBuffer_ToContiguous( buf: *mut c_void, view: *const Py_buffer, len: Py_ssize_t, order: c_char, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_FromContiguous")] pub fn PyBuffer_FromContiguous( view: *const Py_buffer, buf: *const c_void, len: Py_ssize_t, order: c_char, ) -> c_int; pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_IsContiguous")] pub fn PyBuffer_IsContiguous(view: *const Py_buffer, fort: c_char) -> c_int; pub fn PyBuffer_FillContiguousStrides( ndims: c_int, shape: *mut Py_ssize_t, strides: *mut Py_ssize_t, itemsize: c_int, fort: c_char, ); #[cfg_attr(PyPy, link_name = "PyPyBuffer_FillInfo")] pub fn PyBuffer_FillInfo( view: *mut Py_buffer, o: *mut PyObject, buf: *mut c_void, len: Py_ssize_t, readonly: c_int, flags: c_int, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_Release")] pub fn PyBuffer_Release(view: *mut Py_buffer); } /// Maximum number of dimensions pub const PyBUF_MAX_NDIM: c_int = if cfg!(PyPy) { 36 } else { 64 }; /* Flags for getting buffers */ pub const PyBUF_SIMPLE: c_int = 0; pub const PyBUF_WRITABLE: c_int = 0x0001; /* we used to include an E, backwards compatible alias */ pub const PyBUF_WRITEABLE: c_int = PyBUF_WRITABLE; pub const PyBUF_FORMAT: c_int = 0x0004; pub const PyBUF_ND: c_int = 0x0008; pub const PyBUF_STRIDES: c_int = 0x0010 | PyBUF_ND; pub const PyBUF_C_CONTIGUOUS: c_int = 0x0020 | PyBUF_STRIDES; pub const PyBUF_F_CONTIGUOUS: c_int = 0x0040 | PyBUF_STRIDES; pub const PyBUF_ANY_CONTIGUOUS: c_int = 0x0080 | PyBUF_STRIDES; pub const PyBUF_INDIRECT: c_int = 0x0100 | PyBUF_STRIDES; pub const PyBUF_CONTIG: c_int = PyBUF_ND | PyBUF_WRITABLE; pub const PyBUF_CONTIG_RO: c_int = PyBUF_ND; pub const PyBUF_STRIDED: c_int = PyBUF_STRIDES | PyBUF_WRITABLE; pub const PyBUF_STRIDED_RO: c_int = PyBUF_STRIDES; pub const PyBUF_RECORDS: c_int = PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT; pub const PyBUF_RECORDS_RO: c_int = PyBUF_STRIDES | PyBUF_FORMAT; pub const PyBUF_FULL: c_int = PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT; pub const PyBUF_FULL_RO: c_int = PyBUF_INDIRECT | PyBUF_FORMAT; pub const PyBUF_READ: c_int = 0x100; pub const PyBUF_WRITE: c_int = 0x200; pyo3-ffi/src/intrcheck.rs0000644000175000017500000000120214661133735016277 0ustar jamespagejamespageuse std::os::raw::c_int; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyOS_InterruptOccurred")] pub fn PyOS_InterruptOccurred() -> c_int; #[cfg(not(Py_3_10))] #[deprecated(note = "Not documented in Python API; see Python 3.10 release notes")] pub fn PyOS_InitInterrupts(); pub fn PyOS_BeforeFork(); pub fn PyOS_AfterFork_Parent(); pub fn PyOS_AfterFork_Child(); #[deprecated(note = "use PyOS_AfterFork_Child instead")] #[cfg_attr(PyPy, link_name = "PyPyOS_AfterFork")] pub fn PyOS_AfterFork(); // skipped non-limited _PyOS_IsMainThread // skipped non-limited Windows _PyOS_SigintEvent } pyo3-ffi/src/sysmodule.rs0000644000175000017500000000253114661133735016357 0ustar jamespagejamespageuse crate::object::PyObject; use libc::wchar_t; use std::os::raw::{c_char, c_int}; extern "C" { #[cfg_attr(PyPy, link_name = "PyPySys_GetObject")] pub fn PySys_GetObject(arg1: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySys_SetObject")] pub fn PySys_SetObject(arg1: *const c_char, arg2: *mut PyObject) -> c_int; pub fn PySys_SetArgv(arg1: c_int, arg2: *mut *mut wchar_t); pub fn PySys_SetArgvEx(arg1: c_int, arg2: *mut *mut wchar_t, arg3: c_int); pub fn PySys_SetPath(arg1: *const wchar_t); #[cfg_attr(PyPy, link_name = "PyPySys_WriteStdout")] pub fn PySys_WriteStdout(format: *const c_char, ...); #[cfg_attr(PyPy, link_name = "PyPySys_WriteStderr")] pub fn PySys_WriteStderr(format: *const c_char, ...); pub fn PySys_FormatStdout(format: *const c_char, ...); pub fn PySys_FormatStderr(format: *const c_char, ...); pub fn PySys_ResetWarnOptions(); #[cfg_attr(Py_3_11, deprecated(note = "Python 3.11"))] pub fn PySys_AddWarnOption(arg1: *const wchar_t); #[cfg_attr(Py_3_11, deprecated(note = "Python 3.11"))] pub fn PySys_AddWarnOptionUnicode(arg1: *mut PyObject); #[cfg_attr(Py_3_11, deprecated(note = "Python 3.11"))] pub fn PySys_HasWarnOptions() -> c_int; pub fn PySys_AddXOption(arg1: *const wchar_t); pub fn PySys_GetXOptions() -> *mut PyObject; } pyo3-ffi/src/ceval.rs0000644000175000017500000001051714661133735015430 0ustar jamespagejamespageuse crate::object::PyObject; use crate::pystate::PyThreadState; use std::os::raw::{c_char, c_int, c_void}; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyEval_EvalCode")] pub fn PyEval_EvalCode( arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject, ) -> *mut PyObject; pub fn PyEval_EvalCodeEx( co: *mut PyObject, globals: *mut PyObject, locals: *mut PyObject, args: *const *mut PyObject, argc: c_int, kwds: *const *mut PyObject, kwdc: c_int, defs: *const *mut PyObject, defc: c_int, kwdefs: *mut PyObject, closure: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[cfg_attr(PyPy, link_name = "PyPyEval_CallObjectWithKeywords")] pub fn PyEval_CallObjectWithKeywords( func: *mut PyObject, obj: *mut PyObject, kwargs: *mut PyObject, ) -> *mut PyObject; } #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[inline] pub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject { #[allow(deprecated)] PyEval_CallObjectWithKeywords(func, arg, std::ptr::null_mut()) } extern "C" { #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[cfg_attr(PyPy, link_name = "PyPyEval_CallFunction")] pub fn PyEval_CallFunction(obj: *mut PyObject, format: *const c_char, ...) -> *mut PyObject; #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[cfg_attr(PyPy, link_name = "PyPyEval_CallMethod")] pub fn PyEval_CallMethod( obj: *mut PyObject, methodname: *const c_char, format: *const c_char, ... ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyEval_GetBuiltins")] pub fn PyEval_GetBuiltins() -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyEval_GetGlobals")] pub fn PyEval_GetGlobals() -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyEval_GetLocals")] pub fn PyEval_GetLocals() -> *mut PyObject; pub fn PyEval_GetFrame() -> *mut crate::PyFrameObject; #[cfg_attr(PyPy, link_name = "PyPy_AddPendingCall")] pub fn Py_AddPendingCall( func: Option c_int>, arg: *mut c_void, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPy_MakePendingCalls")] pub fn Py_MakePendingCalls() -> c_int; #[cfg_attr(PyPy, link_name = "PyPy_SetRecursionLimit")] pub fn Py_SetRecursionLimit(arg1: c_int); #[cfg_attr(PyPy, link_name = "PyPy_GetRecursionLimit")] pub fn Py_GetRecursionLimit() -> c_int; fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int; } extern "C" { #[cfg(Py_3_9)] #[cfg_attr(PyPy, link_name = "PyPy_EnterRecursiveCall")] pub fn Py_EnterRecursiveCall(arg1: *const c_char) -> c_int; #[cfg(Py_3_9)] #[cfg_attr(PyPy, link_name = "PyPy_LeaveRecursiveCall")] pub fn Py_LeaveRecursiveCall(); } extern "C" { pub fn PyEval_GetFuncName(arg1: *mut PyObject) -> *const c_char; pub fn PyEval_GetFuncDesc(arg1: *mut PyObject) -> *const c_char; pub fn PyEval_GetCallStats(arg1: *mut PyObject) -> *mut PyObject; pub fn PyEval_EvalFrame(arg1: *mut crate::PyFrameObject) -> *mut PyObject; pub fn PyEval_EvalFrameEx(f: *mut crate::PyFrameObject, exc: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyEval_SaveThread")] pub fn PyEval_SaveThread() -> *mut PyThreadState; #[cfg_attr(PyPy, link_name = "PyPyEval_RestoreThread")] pub fn PyEval_RestoreThread(arg1: *mut PyThreadState); } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyEval_ThreadsInitialized")] pub fn PyEval_ThreadsInitialized() -> c_int; #[cfg_attr(PyPy, link_name = "PyPyEval_InitThreads")] pub fn PyEval_InitThreads(); pub fn PyEval_AcquireLock(); pub fn PyEval_ReleaseLock(); #[cfg_attr(PyPy, link_name = "PyPyEval_AcquireThread")] pub fn PyEval_AcquireThread(tstate: *mut PyThreadState); #[cfg_attr(PyPy, link_name = "PyPyEval_ReleaseThread")] pub fn PyEval_ReleaseThread(tstate: *mut PyThreadState); #[cfg(not(Py_3_8))] pub fn PyEval_ReInitThreads(); } // skipped Py_BEGIN_ALLOW_THREADS // skipped Py_BLOCK_THREADS // skipped Py_UNBLOCK_THREADS // skipped Py_END_ALLOW_THREADS // skipped FVC_MASK // skipped FVC_NONE // skipped FVC_STR // skipped FVC_REPR // skipped FVC_ASCII // skipped FVS_MASK // skipped FVS_HAVE_SPEC pyo3-ffi/src/rangeobject.rs0000644000175000017500000000072514661133735016621 0ustar jamespagejamespageuse crate::object::*; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyRange_Type")] pub static mut PyRange_Type: PyTypeObject; pub static mut PyRangeIter_Type: PyTypeObject; pub static mut PyLongRangeIter_Type: PyTypeObject; } #[inline] pub unsafe fn PyRange_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyRange_Type)) as c_int } pyo3-ffi/src/bytearrayobject.rs0000644000175000017500000000354414661133735017531 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; use std::ptr::addr_of_mut; #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyByteArrayObject { pub ob_base: PyVarObject, pub ob_alloc: Py_ssize_t, pub ob_bytes: *mut c_char, pub ob_start: *mut c_char, #[cfg(Py_3_9)] pub ob_exports: Py_ssize_t, #[cfg(not(Py_3_9))] pub ob_exports: c_int, } #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] opaque_struct!(PyByteArrayObject); #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyByteArray_Type")] pub static mut PyByteArray_Type: PyTypeObject; pub static mut PyByteArrayIter_Type: PyTypeObject; } #[inline] pub unsafe fn PyByteArray_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyByteArray_Type)) } #[inline] pub unsafe fn PyByteArray_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyByteArray_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyByteArray_FromObject")] pub fn PyByteArray_FromObject(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyByteArray_Concat")] pub fn PyByteArray_Concat(a: *mut PyObject, b: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyByteArray_FromStringAndSize")] pub fn PyByteArray_FromStringAndSize(string: *const c_char, len: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyByteArray_Size")] pub fn PyByteArray_Size(bytearray: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyByteArray_AsString")] pub fn PyByteArray_AsString(bytearray: *mut PyObject) -> *mut c_char; #[cfg_attr(PyPy, link_name = "PyPyByteArray_Resize")] pub fn PyByteArray_Resize(bytearray: *mut PyObject, len: Py_ssize_t) -> c_int; } pyo3-ffi/src/weakrefobject.rs0000644000175000017500000000376314661133735017156 0ustar jamespagejamespageuse crate::object::*; use std::os::raw::c_int; #[cfg(not(PyPy))] use std::ptr::addr_of_mut; #[cfg(all(not(PyPy), Py_LIMITED_API, not(GraalPy)))] opaque_struct!(PyWeakReference); #[cfg(all(not(PyPy), not(Py_LIMITED_API), not(GraalPy)))] pub use crate::_PyWeakReference as PyWeakReference; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut _PyWeakref_RefType: PyTypeObject; pub static mut _PyWeakref_ProxyType: PyTypeObject; pub static mut _PyWeakref_CallableProxyType: PyTypeObject; #[cfg(PyPy)] #[link_name = "PyPyWeakref_CheckRef"] pub fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int; #[cfg(PyPy)] #[link_name = "PyPyWeakref_CheckRefExact"] pub fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int; #[cfg(PyPy)] #[link_name = "PyPyWeakref_CheckProxy"] pub fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(_PyWeakref_RefType)) } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(_PyWeakref_RefType)) as c_int } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int { ((Py_TYPE(op) == addr_of_mut!(_PyWeakref_ProxyType)) || (Py_TYPE(op) == addr_of_mut!(_PyWeakref_CallableProxyType))) as c_int } #[inline] pub unsafe fn PyWeakref_Check(op: *mut PyObject) -> c_int { (PyWeakref_CheckRef(op) != 0 || PyWeakref_CheckProxy(op) != 0) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyWeakref_NewRef")] pub fn PyWeakref_NewRef(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyWeakref_NewProxy")] pub fn PyWeakref_NewProxy(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyWeakref_GetObject")] pub fn PyWeakref_GetObject(_ref: *mut PyObject) -> *mut PyObject; } pyo3-ffi/src/cpython/0000775000175000017500000000000014661133735015452 5ustar jamespagejamespagepyo3-ffi/src/cpython/frameobject.rs0000644000175000017500000000513314661133735020301 0ustar jamespagejamespage#[cfg(not(GraalPy))] use crate::cpython::code::PyCodeObject; use crate::object::*; #[cfg(not(GraalPy))] use crate::pystate::PyThreadState; #[cfg(not(any(PyPy, GraalPy, Py_3_11)))] use std::os::raw::c_char; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub type PyFrameState = c_char; #[repr(C)] #[derive(Copy, Clone)] #[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub struct PyTryBlock { pub b_type: c_int, pub b_handler: c_int, pub b_level: c_int, } #[repr(C)] #[derive(Copy, Clone)] #[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub struct PyFrameObject { pub ob_base: PyVarObject, pub f_back: *mut PyFrameObject, pub f_code: *mut PyCodeObject, pub f_builtins: *mut PyObject, pub f_globals: *mut PyObject, pub f_locals: *mut PyObject, pub f_valuestack: *mut *mut PyObject, #[cfg(not(Py_3_10))] pub f_stacktop: *mut *mut PyObject, pub f_trace: *mut PyObject, #[cfg(Py_3_10)] pub f_stackdepth: c_int, pub f_trace_lines: c_char, pub f_trace_opcodes: c_char, pub f_gen: *mut PyObject, pub f_lasti: c_int, pub f_lineno: c_int, pub f_iblock: c_int, #[cfg(not(Py_3_10))] pub f_executing: c_char, #[cfg(Py_3_10)] pub f_state: PyFrameState, pub f_blockstack: [PyTryBlock; crate::CO_MAXBLOCKS], pub f_localsplus: [*mut PyObject; 1], } #[cfg(any(PyPy, GraalPy, Py_3_11))] opaque_struct!(PyFrameObject); // skipped _PyFrame_IsRunnable // skipped _PyFrame_IsExecuting // skipped _PyFrameHasCompleted #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyFrame_Type: PyTypeObject; } #[inline] pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyFrame_Type)) as c_int } extern "C" { #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyFrame_New")] pub fn PyFrame_New( tstate: *mut PyThreadState, code: *mut PyCodeObject, globals: *mut PyObject, locals: *mut PyObject, ) -> *mut PyFrameObject; // skipped _PyFrame_New_NoTrack pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int); #[cfg(not(any(PyPy, GraalPy, Py_3_11)))] pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock; pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int); pub fn PyFrame_FastToLocalsWithError(f: *mut PyFrameObject) -> c_int; pub fn PyFrame_FastToLocals(f: *mut PyFrameObject); // skipped _PyFrame_DebugMallocStats // skipped PyFrame_GetBack #[cfg(not(Py_3_9))] pub fn PyFrame_ClearFreeList() -> c_int; } pyo3-ffi/src/cpython/code.rs0000644000175000017500000002262414661133735016736 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; #[allow(unused_imports)] use std::os::raw::{c_char, c_int, c_short, c_uchar, c_void}; #[cfg(not(any(PyPy, GraalPy)))] use std::ptr::addr_of_mut; #[cfg(all(Py_3_8, not(any(PyPy, GraalPy)), not(Py_3_11)))] opaque_struct!(_PyOpcache); #[cfg(Py_3_12)] pub const _PY_MONITORING_LOCAL_EVENTS: usize = 10; #[cfg(Py_3_12)] pub const _PY_MONITORING_UNGROUPED_EVENTS: usize = 15; #[cfg(Py_3_12)] pub const _PY_MONITORING_EVENTS: usize = 17; #[cfg(Py_3_12)] #[repr(C)] #[derive(Clone, Copy)] pub struct _Py_LocalMonitors { pub tools: [u8; if cfg!(Py_3_13) { _PY_MONITORING_LOCAL_EVENTS } else { _PY_MONITORING_UNGROUPED_EVENTS }], } #[cfg(Py_3_12)] #[repr(C)] #[derive(Clone, Copy)] pub struct _Py_GlobalMonitors { pub tools: [u8; _PY_MONITORING_UNGROUPED_EVENTS], } // skipped _Py_CODEUNIT // skipped _Py_OPCODE // skipped _Py_OPARG // skipped _py_make_codeunit // skipped _py_set_opcode // skipped _Py_MAKE_CODEUNIT // skipped _Py_SET_OPCODE #[cfg(Py_3_12)] #[repr(C)] #[derive(Copy, Clone)] pub struct _PyCoCached { pub _co_code: *mut PyObject, pub _co_varnames: *mut PyObject, pub _co_cellvars: *mut PyObject, pub _co_freevars: *mut PyObject, } #[cfg(Py_3_12)] #[repr(C)] #[derive(Copy, Clone)] pub struct _PyCoLineInstrumentationData { pub original_opcode: u8, pub line_delta: i8, } #[cfg(Py_3_12)] #[repr(C)] #[derive(Copy, Clone)] pub struct _PyCoMonitoringData { pub local_monitors: _Py_LocalMonitors, pub active_monitors: _Py_LocalMonitors, pub tools: *mut u8, pub lines: *mut _PyCoLineInstrumentationData, pub line_tools: *mut u8, pub per_instruction_opcodes: *mut u8, pub per_instruction_tools: *mut u8, } #[cfg(all(not(any(PyPy, GraalPy)), not(Py_3_7)))] opaque_struct!(PyCodeObject); #[cfg(all(not(any(PyPy, GraalPy)), Py_3_7, not(Py_3_8)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyObject, pub co_argcount: c_int, pub co_kwonlyargcount: c_int, pub co_nlocals: c_int, pub co_stacksize: c_int, pub co_flags: c_int, pub co_firstlineno: c_int, pub co_code: *mut PyObject, pub co_consts: *mut PyObject, pub co_names: *mut PyObject, pub co_varnames: *mut PyObject, pub co_freevars: *mut PyObject, pub co_cellvars: *mut PyObject, pub co_cell2arg: *mut Py_ssize_t, pub co_filename: *mut PyObject, pub co_name: *mut PyObject, pub co_lnotab: *mut PyObject, pub co_zombieframe: *mut c_void, pub co_weakreflist: *mut PyObject, pub co_extra: *mut c_void, } #[cfg(Py_3_13)] opaque_struct!(_PyExecutorArray); #[cfg(all(not(any(PyPy, GraalPy)), Py_3_8, not(Py_3_11)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyObject, pub co_argcount: c_int, pub co_posonlyargcount: c_int, pub co_kwonlyargcount: c_int, pub co_nlocals: c_int, pub co_stacksize: c_int, pub co_flags: c_int, pub co_firstlineno: c_int, pub co_code: *mut PyObject, pub co_consts: *mut PyObject, pub co_names: *mut PyObject, pub co_varnames: *mut PyObject, pub co_freevars: *mut PyObject, pub co_cellvars: *mut PyObject, pub co_cell2arg: *mut Py_ssize_t, pub co_filename: *mut PyObject, pub co_name: *mut PyObject, #[cfg(not(Py_3_10))] pub co_lnotab: *mut PyObject, #[cfg(Py_3_10)] pub co_linetable: *mut PyObject, pub co_zombieframe: *mut c_void, pub co_weakreflist: *mut PyObject, pub co_extra: *mut c_void, pub co_opcache_map: *mut c_uchar, pub co_opcache: *mut _PyOpcache, pub co_opcache_flag: c_int, pub co_opcache_size: c_uchar, } #[cfg(all(not(any(PyPy, GraalPy)), Py_3_11))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyVarObject, pub co_consts: *mut PyObject, pub co_names: *mut PyObject, pub co_exceptiontable: *mut PyObject, pub co_flags: c_int, #[cfg(not(Py_3_12))] pub co_warmup: c_int, pub co_argcount: c_int, pub co_posonlyargcount: c_int, pub co_kwonlyargcount: c_int, pub co_stacksize: c_int, pub co_firstlineno: c_int, pub co_nlocalsplus: c_int, #[cfg(Py_3_12)] pub co_framesize: c_int, pub co_nlocals: c_int, #[cfg(not(Py_3_12))] pub co_nplaincellvars: c_int, pub co_ncellvars: c_int, pub co_nfreevars: c_int, #[cfg(Py_3_12)] pub co_version: u32, pub co_localsplusnames: *mut PyObject, pub co_localspluskinds: *mut PyObject, pub co_filename: *mut PyObject, pub co_name: *mut PyObject, pub co_qualname: *mut PyObject, pub co_linetable: *mut PyObject, pub co_weakreflist: *mut PyObject, #[cfg(not(Py_3_12))] pub _co_code: *mut PyObject, #[cfg(not(Py_3_12))] pub _co_linearray: *mut c_char, #[cfg(Py_3_13)] pub co_executors: *mut _PyExecutorArray, #[cfg(Py_3_12)] pub _co_cached: *mut _PyCoCached, #[cfg(Py_3_12)] pub _co_instrumentation_version: u64, #[cfg(Py_3_12)] pub _co_monitoring: *mut _PyCoMonitoringData, pub _co_firsttraceable: c_int, pub co_extra: *mut c_void, pub co_code_adaptive: [c_char; 1], } #[cfg(PyPy)] #[repr(C)] #[derive(Copy, Clone)] pub struct PyCodeObject { pub ob_base: PyObject, pub co_name: *mut PyObject, pub co_filename: *mut PyObject, pub co_argcount: c_int, pub co_flags: c_int, } /* Masks for co_flags */ pub const CO_OPTIMIZED: c_int = 0x0001; pub const CO_NEWLOCALS: c_int = 0x0002; pub const CO_VARARGS: c_int = 0x0004; pub const CO_VARKEYWORDS: c_int = 0x0008; pub const CO_NESTED: c_int = 0x0010; pub const CO_GENERATOR: c_int = 0x0020; /* The CO_NOFREE flag is set if there are no free or cell variables. This information is redundant, but it allows a single flag test to determine whether there is any extra work to be done when the call frame it setup. */ pub const CO_NOFREE: c_int = 0x0040; /* The CO_COROUTINE flag is set for coroutine functions (defined with ``async def`` keywords) */ pub const CO_COROUTINE: c_int = 0x0080; pub const CO_ITERABLE_COROUTINE: c_int = 0x0100; pub const CO_ASYNC_GENERATOR: c_int = 0x0200; pub const CO_FUTURE_DIVISION: c_int = 0x2000; pub const CO_FUTURE_ABSOLUTE_IMPORT: c_int = 0x4000; /* do absolute imports by default */ pub const CO_FUTURE_WITH_STATEMENT: c_int = 0x8000; pub const CO_FUTURE_PRINT_FUNCTION: c_int = 0x1_0000; pub const CO_FUTURE_UNICODE_LITERALS: c_int = 0x2_0000; pub const CO_FUTURE_BARRY_AS_BDFL: c_int = 0x4_0000; pub const CO_FUTURE_GENERATOR_STOP: c_int = 0x8_0000; // skipped CO_FUTURE_ANNOTATIONS // skipped CO_CELL_NOT_AN_ARG pub const CO_MAXBLOCKS: usize = 20; #[cfg(not(any(PyPy, GraalPy)))] #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyCode_Type: PyTypeObject; } #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyCode_Type)) as c_int } #[inline] #[cfg(all(not(any(PyPy, GraalPy)), Py_3_10, not(Py_3_11)))] pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t { crate::PyTuple_GET_SIZE((*op).co_freevars) } #[inline] #[cfg(all(not(Py_3_10), Py_3_11, not(any(PyPy, GraalPy))))] pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> c_int { (*op).co_nfreevars } extern "C" { #[cfg(PyPy)] #[link_name = "PyPyCode_Check"] pub fn PyCode_Check(op: *mut PyObject) -> c_int; #[cfg(PyPy)] #[link_name = "PyPyCode_GetNumFree"] pub fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t; } extern "C" { #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyCode_New")] pub fn PyCode_New( argcount: c_int, kwonlyargcount: c_int, nlocals: c_int, stacksize: c_int, flags: c_int, code: *mut PyObject, consts: *mut PyObject, names: *mut PyObject, varnames: *mut PyObject, freevars: *mut PyObject, cellvars: *mut PyObject, filename: *mut PyObject, name: *mut PyObject, firstlineno: c_int, lnotab: *mut PyObject, ) -> *mut PyCodeObject; #[cfg(not(GraalPy))] #[cfg(Py_3_8)] pub fn PyCode_NewWithPosOnlyArgs( argcount: c_int, posonlyargcount: c_int, kwonlyargcount: c_int, nlocals: c_int, stacksize: c_int, flags: c_int, code: *mut PyObject, consts: *mut PyObject, names: *mut PyObject, varnames: *mut PyObject, freevars: *mut PyObject, cellvars: *mut PyObject, filename: *mut PyObject, name: *mut PyObject, firstlineno: c_int, lnotab: *mut PyObject, ) -> *mut PyCodeObject; #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyCode_NewEmpty")] pub fn PyCode_NewEmpty( filename: *const c_char, funcname: *const c_char, firstlineno: c_int, ) -> *mut PyCodeObject; #[cfg(not(GraalPy))] pub fn PyCode_Addr2Line(arg1: *mut PyCodeObject, arg2: c_int) -> c_int; // skipped PyCodeAddressRange "for internal use only" // skipped _PyCode_CheckLineNumber // skipped _PyCode_ConstantKey pub fn PyCode_Optimize( code: *mut PyObject, consts: *mut PyObject, names: *mut PyObject, lnotab: *mut PyObject, ) -> *mut PyObject; pub fn _PyCode_GetExtra( code: *mut PyObject, index: Py_ssize_t, extra: *const *mut c_void, ) -> c_int; pub fn _PyCode_SetExtra(code: *mut PyObject, index: Py_ssize_t, extra: *mut c_void) -> c_int; } pyo3-ffi/src/cpython/unicodeobject.rs0000644000175000017500000005620114661133735020637 0ustar jamespagejamespage#[cfg(not(any(PyPy, GraalPy)))] use crate::Py_hash_t; use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_UNICODE, Py_ssize_t}; #[cfg(not(any(Py_3_12, GraalPy)))] use libc::wchar_t; use std::os::raw::{c_char, c_int, c_uint, c_void}; // skipped Py_UNICODE_ISSPACE() // skipped Py_UNICODE_ISLOWER() // skipped Py_UNICODE_ISUPPER() // skipped Py_UNICODE_ISTITLE() // skipped Py_UNICODE_ISLINEBREAK // skipped Py_UNICODE_TOLOWER // skipped Py_UNICODE_TOUPPER // skipped Py_UNICODE_TOTITLE // skipped Py_UNICODE_ISDECIMAL // skipped Py_UNICODE_ISDIGIT // skipped Py_UNICODE_ISNUMERIC // skipped Py_UNICODE_ISPRINTABLE // skipped Py_UNICODE_TODECIMAL // skipped Py_UNICODE_TODIGIT // skipped Py_UNICODE_TONUMERIC // skipped Py_UNICODE_ISALPHA // skipped Py_UNICODE_ISALNUM // skipped Py_UNICODE_COPY // skipped Py_UNICODE_FILL // skipped Py_UNICODE_IS_SURROGATE // skipped Py_UNICODE_IS_HIGH_SURROGATE // skipped Py_UNICODE_IS_LOW_SURROGATE // skipped Py_UNICODE_JOIN_SURROGATES // skipped Py_UNICODE_HIGH_SURROGATE // skipped Py_UNICODE_LOW_SURROGATE // generated by bindgen v0.63.0 (with small adaptations) #[repr(C)] struct BitfieldUnit { storage: Storage, } impl BitfieldUnit { #[inline] pub const fn new(storage: Storage) -> Self { Self { storage } } } #[cfg(not(GraalPy))] impl BitfieldUnit where Storage: AsRef<[u8]> + AsMut<[u8]>, { #[inline] fn get_bit(&self, index: usize) -> bool { debug_assert!(index / 8 < self.storage.as_ref().len()); let byte_index = index / 8; let byte = self.storage.as_ref()[byte_index]; let bit_index = if cfg!(target_endian = "big") { 7 - (index % 8) } else { index % 8 }; let mask = 1 << bit_index; byte & mask == mask } #[inline] fn set_bit(&mut self, index: usize, val: bool) { debug_assert!(index / 8 < self.storage.as_ref().len()); let byte_index = index / 8; let byte = &mut self.storage.as_mut()[byte_index]; let bit_index = if cfg!(target_endian = "big") { 7 - (index % 8) } else { index % 8 }; let mask = 1 << bit_index; if val { *byte |= mask; } else { *byte &= !mask; } } #[inline] fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { debug_assert!(bit_width <= 64); debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); let mut val = 0; for i in 0..(bit_width as usize) { if self.get_bit(i + bit_offset) { let index = if cfg!(target_endian = "big") { bit_width as usize - 1 - i } else { i }; val |= 1 << index; } } val } #[inline] fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { debug_assert!(bit_width <= 64); debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); for i in 0..(bit_width as usize) { let mask = 1 << i; let val_bit_is_set = val & mask == mask; let index = if cfg!(target_endian = "big") { bit_width as usize - 1 - i } else { i }; self.set_bit(index + bit_offset, val_bit_is_set); } } } #[cfg(not(GraalPy))] const STATE_INTERNED_INDEX: usize = 0; #[cfg(not(GraalPy))] const STATE_INTERNED_WIDTH: u8 = 2; #[cfg(not(GraalPy))] const STATE_KIND_INDEX: usize = STATE_INTERNED_WIDTH as usize; #[cfg(not(GraalPy))] const STATE_KIND_WIDTH: u8 = 3; #[cfg(not(GraalPy))] const STATE_COMPACT_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH) as usize; #[cfg(not(GraalPy))] const STATE_COMPACT_WIDTH: u8 = 1; #[cfg(not(GraalPy))] const STATE_ASCII_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH) as usize; #[cfg(not(GraalPy))] const STATE_ASCII_WIDTH: u8 = 1; #[cfg(not(any(Py_3_12, GraalPy)))] const STATE_READY_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize; #[cfg(not(any(Py_3_12, GraalPy)))] const STATE_READY_WIDTH: u8 = 1; // generated by bindgen v0.63.0 (with small adaptations) // The same code is generated for Python 3.7, 3.8, 3.9, 3.10, and 3.11, but the "ready" field // has been removed from Python 3.12. /// Wrapper around the `PyASCIIObject.state` bitfield with getters and setters that work /// on most little- and big-endian architectures. /// /// Memory layout of C bitfields is implementation defined, so these functions are still /// unsafe. Users must verify that they work as expected on the architectures they target. #[repr(C)] #[repr(align(4))] struct PyASCIIObjectState { bitfield_align: [u8; 0], bitfield: BitfieldUnit<[u8; 4usize]>, } // c_uint and u32 are not necessarily the same type on all targets / architectures #[cfg(not(GraalPy))] #[allow(clippy::useless_transmute)] impl PyASCIIObjectState { #[inline] unsafe fn interned(&self) -> c_uint { std::mem::transmute( self.bitfield .get(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH) as u32, ) } #[inline] unsafe fn set_interned(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield .set(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH, val as u64) } #[inline] unsafe fn kind(&self) -> c_uint { std::mem::transmute(self.bitfield.get(STATE_KIND_INDEX, STATE_KIND_WIDTH) as u32) } #[inline] unsafe fn set_kind(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield .set(STATE_KIND_INDEX, STATE_KIND_WIDTH, val as u64) } #[inline] unsafe fn compact(&self) -> c_uint { std::mem::transmute(self.bitfield.get(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH) as u32) } #[inline] unsafe fn set_compact(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield .set(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH, val as u64) } #[inline] unsafe fn ascii(&self) -> c_uint { std::mem::transmute(self.bitfield.get(STATE_ASCII_INDEX, STATE_ASCII_WIDTH) as u32) } #[inline] unsafe fn set_ascii(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield .set(STATE_ASCII_INDEX, STATE_ASCII_WIDTH, val as u64) } #[cfg(not(Py_3_12))] #[inline] unsafe fn ready(&self) -> c_uint { std::mem::transmute(self.bitfield.get(STATE_READY_INDEX, STATE_READY_WIDTH) as u32) } #[cfg(not(Py_3_12))] #[inline] unsafe fn set_ready(&mut self, val: c_uint) { let val: u32 = std::mem::transmute(val); self.bitfield .set(STATE_READY_INDEX, STATE_READY_WIDTH, val as u64) } } impl From for PyASCIIObjectState { #[inline] fn from(value: u32) -> Self { PyASCIIObjectState { bitfield_align: [], bitfield: BitfieldUnit::new(value.to_ne_bytes()), } } } impl From for u32 { #[inline] fn from(value: PyASCIIObjectState) -> Self { u32::from_ne_bytes(value.bitfield.storage) } } #[repr(C)] pub struct PyASCIIObject { pub ob_base: PyObject, #[cfg(not(GraalPy))] pub length: Py_ssize_t, #[cfg(not(any(PyPy, GraalPy)))] pub hash: Py_hash_t, /// A bit field with various properties. /// /// Rust doesn't expose bitfields. So we have accessor functions for /// retrieving values. /// /// unsigned int interned:2; // SSTATE_* constants. /// unsigned int kind:3; // PyUnicode_*_KIND constants. /// unsigned int compact:1; /// unsigned int ascii:1; /// unsigned int ready:1; /// unsigned int :24; #[cfg(not(GraalPy))] pub state: u32, #[cfg(not(any(Py_3_12, GraalPy)))] pub wstr: *mut wchar_t, } /// Interacting with the bitfield is not actually well-defined, so we mark these APIs unsafe. #[cfg(not(GraalPy))] impl PyASCIIObject { #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12 /// Get the `interned` field of the [`PyASCIIObject`] state bitfield. /// /// Returns one of: [`SSTATE_NOT_INTERNED`], [`SSTATE_INTERNED_MORTAL`], /// [`SSTATE_INTERNED_IMMORTAL`], or [`SSTATE_INTERNED_IMMORTAL_STATIC`]. #[inline] pub unsafe fn interned(&self) -> c_uint { PyASCIIObjectState::from(self.state).interned() } #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12 /// Set the `interned` field of the [`PyASCIIObject`] state bitfield. /// /// Calling this function with an argument that is not [`SSTATE_NOT_INTERNED`], /// [`SSTATE_INTERNED_MORTAL`], [`SSTATE_INTERNED_IMMORTAL`], or /// [`SSTATE_INTERNED_IMMORTAL_STATIC`] is invalid. #[inline] pub unsafe fn set_interned(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_interned(val); self.state = u32::from(state); } /// Get the `kind` field of the [`PyASCIIObject`] state bitfield. /// /// Returns one of: #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")] /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`]. #[inline] pub unsafe fn kind(&self) -> c_uint { PyASCIIObjectState::from(self.state).kind() } /// Set the `kind` field of the [`PyASCIIObject`] state bitfield. /// /// Calling this function with an argument that is not #[cfg_attr(not(Py_3_12), doc = "[`PyUnicode_WCHAR_KIND`], ")] /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`] is invalid. #[inline] pub unsafe fn set_kind(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_kind(val); self.state = u32::from(state); } /// Get the `compact` field of the [`PyASCIIObject`] state bitfield. /// /// Returns either `0` or `1`. #[inline] pub unsafe fn compact(&self) -> c_uint { PyASCIIObjectState::from(self.state).compact() } /// Set the `compact` flag of the [`PyASCIIObject`] state bitfield. /// /// Calling this function with an argument that is neither `0` nor `1` is invalid. #[inline] pub unsafe fn set_compact(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_compact(val); self.state = u32::from(state); } /// Get the `ascii` field of the [`PyASCIIObject`] state bitfield. /// /// Returns either `0` or `1`. #[inline] pub unsafe fn ascii(&self) -> c_uint { PyASCIIObjectState::from(self.state).ascii() } /// Set the `ascii` flag of the [`PyASCIIObject`] state bitfield. /// /// Calling this function with an argument that is neither `0` nor `1` is invalid. #[inline] pub unsafe fn set_ascii(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_ascii(val); self.state = u32::from(state); } /// Get the `ready` field of the [`PyASCIIObject`] state bitfield. /// /// Returns either `0` or `1`. #[cfg(not(Py_3_12))] #[inline] pub unsafe fn ready(&self) -> c_uint { PyASCIIObjectState::from(self.state).ready() } /// Set the `ready` flag of the [`PyASCIIObject`] state bitfield. /// /// Calling this function with an argument that is neither `0` nor `1` is invalid. #[cfg(not(Py_3_12))] #[inline] pub unsafe fn set_ready(&mut self, val: c_uint) { let mut state = PyASCIIObjectState::from(self.state); state.set_ready(val); self.state = u32::from(state); } } #[repr(C)] pub struct PyCompactUnicodeObject { pub _base: PyASCIIObject, #[cfg(not(GraalPy))] pub utf8_length: Py_ssize_t, #[cfg(not(GraalPy))] pub utf8: *mut c_char, #[cfg(not(any(Py_3_12, GraalPy)))] pub wstr_length: Py_ssize_t, } #[repr(C)] pub union PyUnicodeObjectData { pub any: *mut c_void, pub latin1: *mut Py_UCS1, pub ucs2: *mut Py_UCS2, pub ucs4: *mut Py_UCS4, } #[repr(C)] pub struct PyUnicodeObject { pub _base: PyCompactUnicodeObject, #[cfg(not(GraalPy))] pub data: PyUnicodeObjectData, } extern "C" { #[cfg(not(any(PyPy, GraalPy)))] pub fn _PyUnicode_CheckConsistency(op: *mut PyObject, check_content: c_int) -> c_int; } // skipped PyUnicode_GET_SIZE // skipped PyUnicode_GET_DATA_SIZE // skipped PyUnicode_AS_UNICODE // skipped PyUnicode_AS_DATA pub const SSTATE_NOT_INTERNED: c_uint = 0; pub const SSTATE_INTERNED_MORTAL: c_uint = 1; pub const SSTATE_INTERNED_IMMORTAL: c_uint = 2; #[cfg(Py_3_12)] pub const SSTATE_INTERNED_IMMORTAL_STATIC: c_uint = 3; #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint { debug_assert!(crate::PyUnicode_Check(op) != 0); #[cfg(not(Py_3_12))] debug_assert!(PyUnicode_IS_READY(op) != 0); (*(op as *mut PyASCIIObject)).ascii() } #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_COMPACT(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).compact() } #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_COMPACT_ASCII(op: *mut PyObject) -> c_uint { ((*(op as *mut PyASCIIObject)).ascii() != 0 && PyUnicode_IS_COMPACT(op) != 0).into() } #[cfg(not(Py_3_12))] #[deprecated(note = "Removed in Python 3.12")] pub const PyUnicode_WCHAR_KIND: c_uint = 0; pub const PyUnicode_1BYTE_KIND: c_uint = 1; pub const PyUnicode_2BYTE_KIND: c_uint = 2; pub const PyUnicode_4BYTE_KIND: c_uint = 4; #[cfg(not(any(GraalPy, PyPy)))] #[inline] pub unsafe fn PyUnicode_1BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS1 { PyUnicode_DATA(op) as *mut Py_UCS1 } #[cfg(not(any(GraalPy, PyPy)))] #[inline] pub unsafe fn PyUnicode_2BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS2 { PyUnicode_DATA(op) as *mut Py_UCS2 } #[cfg(not(any(GraalPy, PyPy)))] #[inline] pub unsafe fn PyUnicode_4BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS4 { PyUnicode_DATA(op) as *mut Py_UCS4 } #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint { debug_assert!(crate::PyUnicode_Check(op) != 0); #[cfg(not(Py_3_12))] debug_assert!(PyUnicode_IS_READY(op) != 0); (*(op as *mut PyASCIIObject)).kind() } #[cfg(not(GraalPy))] #[inline] pub unsafe fn _PyUnicode_COMPACT_DATA(op: *mut PyObject) -> *mut c_void { if PyUnicode_IS_ASCII(op) != 0 { (op as *mut PyASCIIObject).offset(1) as *mut c_void } else { (op as *mut PyCompactUnicodeObject).offset(1) as *mut c_void } } #[cfg(not(any(GraalPy, PyPy)))] #[inline] pub unsafe fn _PyUnicode_NONCOMPACT_DATA(op: *mut PyObject) -> *mut c_void { debug_assert!(!(*(op as *mut PyUnicodeObject)).data.any.is_null()); (*(op as *mut PyUnicodeObject)).data.any } #[cfg(not(any(GraalPy, PyPy)))] #[inline] pub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void { debug_assert!(crate::PyUnicode_Check(op) != 0); if PyUnicode_IS_COMPACT(op) != 0 { _PyUnicode_COMPACT_DATA(op) } else { _PyUnicode_NONCOMPACT_DATA(op) } } // skipped PyUnicode_WRITE // skipped PyUnicode_READ // skipped PyUnicode_READ_CHAR #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyUnicode_GET_LENGTH(op: *mut PyObject) -> Py_ssize_t { debug_assert!(crate::PyUnicode_Check(op) != 0); #[cfg(not(Py_3_12))] debug_assert!(PyUnicode_IS_READY(op) != 0); (*(op as *mut PyASCIIObject)).length } #[cfg(any(Py_3_12, GraalPy))] #[inline] pub unsafe fn PyUnicode_IS_READY(_op: *mut PyObject) -> c_uint { // kept in CPython for backwards compatibility 1 } #[cfg(not(any(GraalPy, Py_3_12)))] #[inline] pub unsafe fn PyUnicode_IS_READY(op: *mut PyObject) -> c_uint { (*(op as *mut PyASCIIObject)).ready() } #[cfg(any(Py_3_12, GraalPy))] #[inline] pub unsafe fn PyUnicode_READY(_op: *mut PyObject) -> c_int { 0 } #[cfg(not(any(Py_3_12, GraalPy)))] #[inline] pub unsafe fn PyUnicode_READY(op: *mut PyObject) -> c_int { debug_assert!(crate::PyUnicode_Check(op) != 0); if PyUnicode_IS_READY(op) != 0 { 0 } else { _PyUnicode_Ready(op) } } // skipped PyUnicode_MAX_CHAR_VALUE // skipped _PyUnicode_get_wstr_length // skipped PyUnicode_WSTR_LENGTH extern "C" { #[cfg_attr(PyPy, link_name = "PyPyUnicode_New")] pub fn PyUnicode_New(size: Py_ssize_t, maxchar: Py_UCS4) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "_PyPyUnicode_Ready")] pub fn _PyUnicode_Ready(unicode: *mut PyObject) -> c_int; // skipped _PyUnicode_Copy #[cfg(not(PyPy))] pub fn PyUnicode_CopyCharacters( to: *mut PyObject, to_start: Py_ssize_t, from: *mut PyObject, from_start: Py_ssize_t, how_many: Py_ssize_t, ) -> Py_ssize_t; // skipped _PyUnicode_FastCopyCharacters #[cfg(not(PyPy))] pub fn PyUnicode_Fill( unicode: *mut PyObject, start: Py_ssize_t, length: Py_ssize_t, fill_char: Py_UCS4, ) -> Py_ssize_t; // skipped _PyUnicode_FastFill #[cfg(not(Py_3_12))] #[deprecated] #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromUnicode")] pub fn PyUnicode_FromUnicode(u: *const Py_UNICODE, size: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromKindAndData")] pub fn PyUnicode_FromKindAndData( kind: c_int, buffer: *const c_void, size: Py_ssize_t, ) -> *mut PyObject; // skipped _PyUnicode_FromASCII // skipped _PyUnicode_FindMaxChar #[cfg(not(Py_3_12))] #[deprecated] #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUnicode")] pub fn PyUnicode_AsUnicode(unicode: *mut PyObject) -> *mut Py_UNICODE; // skipped _PyUnicode_AsUnicode #[cfg(not(Py_3_12))] #[deprecated] #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUnicodeAndSize")] pub fn PyUnicode_AsUnicodeAndSize( unicode: *mut PyObject, size: *mut Py_ssize_t, ) -> *mut Py_UNICODE; // skipped PyUnicode_GetMax } // skipped _PyUnicodeWriter // skipped _PyUnicodeWriter_Init // skipped _PyUnicodeWriter_Prepare // skipped _PyUnicodeWriter_PrepareInternal // skipped _PyUnicodeWriter_PrepareKind // skipped _PyUnicodeWriter_PrepareKindInternal // skipped _PyUnicodeWriter_WriteChar // skipped _PyUnicodeWriter_WriteStr // skipped _PyUnicodeWriter_WriteSubstring // skipped _PyUnicodeWriter_WriteASCIIString // skipped _PyUnicodeWriter_WriteLatin1String // skipped _PyUnicodeWriter_Finish // skipped _PyUnicodeWriter_Dealloc // skipped _PyUnicode_FormatAdvancedWriter extern "C" { // skipped _PyUnicode_AsStringAndSize #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8")] pub fn PyUnicode_AsUTF8(unicode: *mut PyObject) -> *const c_char; // skipped _PyUnicode_AsString pub fn PyUnicode_Encode( s: *const Py_UNICODE, size: Py_ssize_t, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_EncodeUTF7( data: *const Py_UNICODE, length: Py_ssize_t, base64SetO: c_int, base64WhiteSpace: c_int, errors: *const c_char, ) -> *mut PyObject; // skipped _PyUnicode_EncodeUTF7 // skipped _PyUnicode_AsUTF8String #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeUTF8")] pub fn PyUnicode_EncodeUTF8( data: *const Py_UNICODE, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_EncodeUTF32( data: *const Py_UNICODE, length: Py_ssize_t, errors: *const c_char, byteorder: c_int, ) -> *mut PyObject; // skipped _PyUnicode_EncodeUTF32 pub fn PyUnicode_EncodeUTF16( data: *const Py_UNICODE, length: Py_ssize_t, errors: *const c_char, byteorder: c_int, ) -> *mut PyObject; // skipped _PyUnicode_EncodeUTF16 // skipped _PyUnicode_DecodeUnicodeEscape pub fn PyUnicode_EncodeUnicodeEscape( data: *const Py_UNICODE, length: Py_ssize_t, ) -> *mut PyObject; pub fn PyUnicode_EncodeRawUnicodeEscape( data: *const Py_UNICODE, length: Py_ssize_t, ) -> *mut PyObject; // skipped _PyUnicode_AsLatin1String #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeLatin1")] pub fn PyUnicode_EncodeLatin1( data: *const Py_UNICODE, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; // skipped _PyUnicode_AsASCIIString #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeASCII")] pub fn PyUnicode_EncodeASCII( data: *const Py_UNICODE, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_EncodeCharmap( data: *const Py_UNICODE, length: Py_ssize_t, mapping: *mut PyObject, errors: *const c_char, ) -> *mut PyObject; // skipped _PyUnicode_EncodeCharmap pub fn PyUnicode_TranslateCharmap( data: *const Py_UNICODE, length: Py_ssize_t, table: *mut PyObject, errors: *const c_char, ) -> *mut PyObject; // skipped PyUnicode_EncodeMBCS #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeDecimal")] pub fn PyUnicode_EncodeDecimal( s: *mut Py_UNICODE, length: Py_ssize_t, output: *mut c_char, errors: *const c_char, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_TransformDecimalToASCII")] pub fn PyUnicode_TransformDecimalToASCII( s: *mut Py_UNICODE, length: Py_ssize_t, ) -> *mut PyObject; // skipped _PyUnicode_TransformDecimalAndSpaceToASCII } // skipped _PyUnicode_JoinArray // skipped _PyUnicode_EqualToASCIIId // skipped _PyUnicode_EqualToASCIIString // skipped _PyUnicode_XStrip // skipped _PyUnicode_InsertThousandsGrouping // skipped _Py_ascii_whitespace // skipped _PyUnicode_IsLowercase // skipped _PyUnicode_IsUppercase // skipped _PyUnicode_IsTitlecase // skipped _PyUnicode_IsXidStart // skipped _PyUnicode_IsXidContinue // skipped _PyUnicode_IsWhitespace // skipped _PyUnicode_IsLinebreak // skipped _PyUnicode_ToLowercase // skipped _PyUnicode_ToUppercase // skipped _PyUnicode_ToTitlecase // skipped _PyUnicode_ToLowerFull // skipped _PyUnicode_ToTitleFull // skipped _PyUnicode_ToUpperFull // skipped _PyUnicode_ToFoldedFull // skipped _PyUnicode_IsCaseIgnorable // skipped _PyUnicode_IsCased // skipped _PyUnicode_ToDecimalDigit // skipped _PyUnicode_ToDigit // skipped _PyUnicode_ToNumeric // skipped _PyUnicode_IsDecimalDigit // skipped _PyUnicode_IsDigit // skipped _PyUnicode_IsNumeric // skipped _PyUnicode_IsPrintable // skipped _PyUnicode_IsAlpha // skipped Py_UNICODE_strlen // skipped Py_UNICODE_strcpy // skipped Py_UNICODE_strcat // skipped Py_UNICODE_strncpy // skipped Py_UNICODE_strcmp // skipped Py_UNICODE_strncmp // skipped Py_UNICODE_strchr // skipped Py_UNICODE_strrchr // skipped _PyUnicode_FormatLong // skipped PyUnicode_AsUnicodeCopy // skipped _PyUnicode_FromId // skipped _PyUnicode_EQ // skipped _PyUnicode_ScanIdentifier pyo3-ffi/src/cpython/initconfig.rs0000644000175000017500000001413414661133735020152 0ustar jamespagejamespage/* --- PyStatus ----------------------------------------------- */ use crate::Py_ssize_t; use libc::wchar_t; use std::os::raw::{c_char, c_int, c_ulong}; #[repr(C)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum _PyStatus_TYPE { _PyStatus_TYPE_OK = 0, _PyStatus_TYPE_ERROR = 1, _PyStatus_TYPE_EXIT = 2, } #[repr(C)] #[derive(Copy, Clone)] pub struct PyStatus { pub _type: _PyStatus_TYPE, pub func: *const c_char, pub err_msg: *const c_char, pub exitcode: c_int, } extern "C" { pub fn PyStatus_Ok() -> PyStatus; pub fn PyStatus_Error(err_msg: *const c_char) -> PyStatus; pub fn PyStatus_NoMemory() -> PyStatus; pub fn PyStatus_Exit(exitcode: c_int) -> PyStatus; pub fn PyStatus_IsError(err: PyStatus) -> c_int; pub fn PyStatus_IsExit(err: PyStatus) -> c_int; pub fn PyStatus_Exception(err: PyStatus) -> c_int; } /* --- PyWideStringList ------------------------------------------------ */ #[repr(C)] #[derive(Copy, Clone)] pub struct PyWideStringList { pub length: Py_ssize_t, pub items: *mut *mut wchar_t, } extern "C" { pub fn PyWideStringList_Append(list: *mut PyWideStringList, item: *const wchar_t) -> PyStatus; pub fn PyWideStringList_Insert( list: *mut PyWideStringList, index: Py_ssize_t, item: *const wchar_t, ) -> PyStatus; } /* --- PyPreConfig ----------------------------------------------- */ #[repr(C)] #[derive(Copy, Clone)] pub struct PyPreConfig { pub _config_init: c_int, pub parse_argv: c_int, pub isolated: c_int, pub use_environment: c_int, pub configure_locale: c_int, pub coerce_c_locale: c_int, pub coerce_c_locale_warn: c_int, #[cfg(windows)] pub legacy_windows_fs_encoding: c_int, pub utf8_mode: c_int, pub dev_mode: c_int, pub allocator: c_int, } extern "C" { pub fn PyPreConfig_InitPythonConfig(config: *mut PyPreConfig); pub fn PyPreConfig_InitIsolatedConfig(config: *mut PyPreConfig); } /* --- PyConfig ---------------------------------------------- */ #[repr(C)] #[derive(Copy, Clone)] pub struct PyConfig { pub _config_init: c_int, pub isolated: c_int, pub use_environment: c_int, pub dev_mode: c_int, pub install_signal_handlers: c_int, pub use_hash_seed: c_int, pub hash_seed: c_ulong, pub faulthandler: c_int, #[cfg(all(Py_3_9, not(Py_3_10)))] pub _use_peg_parser: c_int, pub tracemalloc: c_int, #[cfg(Py_3_12)] pub perf_profiling: c_int, pub import_time: c_int, #[cfg(Py_3_11)] pub code_debug_ranges: c_int, pub show_ref_count: c_int, #[cfg(not(Py_3_9))] pub show_alloc_count: c_int, pub dump_refs: c_int, #[cfg(Py_3_11)] pub dump_refs_file: *mut wchar_t, pub malloc_stats: c_int, pub filesystem_encoding: *mut wchar_t, pub filesystem_errors: *mut wchar_t, pub pycache_prefix: *mut wchar_t, pub parse_argv: c_int, #[cfg(Py_3_10)] pub orig_argv: PyWideStringList, pub argv: PyWideStringList, #[cfg(not(Py_3_10))] pub program_name: *mut wchar_t, pub xoptions: PyWideStringList, pub warnoptions: PyWideStringList, pub site_import: c_int, pub bytes_warning: c_int, #[cfg(Py_3_10)] pub warn_default_encoding: c_int, pub inspect: c_int, pub interactive: c_int, pub optimization_level: c_int, pub parser_debug: c_int, pub write_bytecode: c_int, pub verbose: c_int, pub quiet: c_int, pub user_site_directory: c_int, pub configure_c_stdio: c_int, pub buffered_stdio: c_int, pub stdio_encoding: *mut wchar_t, pub stdio_errors: *mut wchar_t, #[cfg(windows)] pub legacy_windows_stdio: c_int, pub check_hash_pycs_mode: *mut wchar_t, #[cfg(Py_3_11)] pub use_frozen_modules: c_int, #[cfg(Py_3_11)] pub safe_path: c_int, #[cfg(Py_3_12)] pub int_max_str_digits: c_int, #[cfg(Py_3_13)] pub cpu_count: c_int, pub pathconfig_warnings: c_int, #[cfg(Py_3_10)] pub program_name: *mut wchar_t, pub pythonpath_env: *mut wchar_t, pub home: *mut wchar_t, #[cfg(Py_3_10)] pub platlibdir: *mut wchar_t, pub module_search_paths_set: c_int, pub module_search_paths: PyWideStringList, #[cfg(Py_3_11)] pub stdlib_dir: *mut wchar_t, pub executable: *mut wchar_t, pub base_executable: *mut wchar_t, pub prefix: *mut wchar_t, pub base_prefix: *mut wchar_t, pub exec_prefix: *mut wchar_t, pub base_exec_prefix: *mut wchar_t, #[cfg(all(Py_3_9, not(Py_3_10)))] pub platlibdir: *mut wchar_t, pub skip_source_first_line: c_int, pub run_command: *mut wchar_t, pub run_module: *mut wchar_t, pub run_filename: *mut wchar_t, #[cfg(Py_3_13)] pub sys_path_0: *mut wchar_t, pub _install_importlib: c_int, pub _init_main: c_int, #[cfg(all(Py_3_9, not(Py_3_12)))] pub _isolated_interpreter: c_int, #[cfg(Py_3_11)] pub _is_python_build: c_int, #[cfg(all(Py_3_9, not(Py_3_10)))] pub _orig_argv: PyWideStringList, } extern "C" { pub fn PyConfig_InitPythonConfig(config: *mut PyConfig); pub fn PyConfig_InitIsolatedConfig(config: *mut PyConfig); pub fn PyConfig_Clear(config: *mut PyConfig); pub fn PyConfig_SetString( config: *mut PyConfig, config_str: *mut *mut wchar_t, str: *const wchar_t, ) -> PyStatus; pub fn PyConfig_SetBytesString( config: *mut PyConfig, config_str: *mut *mut wchar_t, str: *const c_char, ) -> PyStatus; pub fn PyConfig_Read(config: *mut PyConfig) -> PyStatus; pub fn PyConfig_SetBytesArgv( config: *mut PyConfig, argc: Py_ssize_t, argv: *mut *const c_char, ) -> PyStatus; pub fn PyConfig_SetArgv( config: *mut PyConfig, argc: Py_ssize_t, argv: *mut *const wchar_t, ) -> PyStatus; pub fn PyConfig_SetWideStringList( config: *mut PyConfig, list: *mut PyWideStringList, length: Py_ssize_t, items: *mut *mut wchar_t, ) -> PyStatus; } /* --- Helper functions --------------------------------------- */ extern "C" { pub fn Py_GetArgcArgv(argc: *mut c_int, argv: *mut *mut *mut wchar_t); } pyo3-ffi/src/cpython/pylifecycle.rs0000644000175000017500000000512214661133735020326 0ustar jamespagejamespageuse crate::{PyConfig, PyPreConfig, PyStatus, Py_ssize_t}; use libc::wchar_t; use std::os::raw::{c_char, c_int}; // "private" functions in cpython/pylifecycle.h accepted in PEP 587 extern "C" { // skipped _Py_SetStandardStreamEncoding; pub fn Py_PreInitialize(src_config: *const PyPreConfig) -> PyStatus; pub fn Py_PreInitializeFromBytesArgs( src_config: *const PyPreConfig, argc: Py_ssize_t, argv: *mut *mut c_char, ) -> PyStatus; pub fn Py_PreInitializeFromArgs( src_config: *const PyPreConfig, argc: Py_ssize_t, argv: *mut *mut wchar_t, ) -> PyStatus; pub fn _Py_IsCoreInitialized() -> c_int; pub fn Py_InitializeFromConfig(config: *const PyConfig) -> PyStatus; pub fn _Py_InitializeMain() -> PyStatus; pub fn Py_RunMain() -> c_int; pub fn Py_ExitStatusException(status: PyStatus) -> !; // skipped _Py_RestoreSignals // skipped Py_FdIsInteractive // skipped _Py_FdIsInteractive // skipped _Py_SetProgramFullPath // skipped _Py_gitidentifier // skipped _Py_getversion // skipped _Py_IsFinalizing // skipped _PyOS_URandom // skipped _PyOS_URandomNonblock // skipped _Py_CoerceLegacyLocale // skipped _Py_LegacyLocaleDetected // skipped _Py_SetLocaleFromEnv } #[cfg(Py_3_12)] pub const PyInterpreterConfig_DEFAULT_GIL: c_int = 0; #[cfg(Py_3_12)] pub const PyInterpreterConfig_SHARED_GIL: c_int = 1; #[cfg(Py_3_12)] pub const PyInterpreterConfig_OWN_GIL: c_int = 2; #[cfg(Py_3_12)] #[repr(C)] pub struct PyInterpreterConfig { pub use_main_obmalloc: c_int, pub allow_fork: c_int, pub allow_exec: c_int, pub allow_threads: c_int, pub allow_daemon_threads: c_int, pub check_multi_interp_extensions: c_int, pub gil: c_int, } #[cfg(Py_3_12)] pub const _PyInterpreterConfig_INIT: PyInterpreterConfig = PyInterpreterConfig { use_main_obmalloc: 0, allow_fork: 0, allow_exec: 0, allow_threads: 1, allow_daemon_threads: 0, check_multi_interp_extensions: 1, gil: PyInterpreterConfig_OWN_GIL, }; #[cfg(Py_3_12)] pub const _PyInterpreterConfig_LEGACY_INIT: PyInterpreterConfig = PyInterpreterConfig { use_main_obmalloc: 1, allow_fork: 1, allow_exec: 1, allow_threads: 1, allow_daemon_threads: 1, check_multi_interp_extensions: 0, gil: PyInterpreterConfig_SHARED_GIL, }; extern "C" { #[cfg(Py_3_12)] pub fn Py_NewInterpreterFromConfig( tstate_p: *mut *mut crate::PyThreadState, config: *const PyInterpreterConfig, ) -> PyStatus; } // skipped atexit_datacallbackfunc // skipped _Py_AtExit pyo3-ffi/src/cpython/methodobject.rs0000644000175000017500000000351314661133735020467 0ustar jamespagejamespageuse crate::object::*; #[cfg(not(GraalPy))] use crate::{PyCFunctionObject, PyMethodDefPointer, METH_METHOD, METH_STATIC}; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg(not(GraalPy))] pub struct PyCMethodObject { pub func: PyCFunctionObject, pub mm_class: *mut PyTypeObject, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyCMethod_Type: PyTypeObject; } #[inline] pub unsafe fn PyCMethod_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyCMethod_Type)) as c_int } #[inline] pub unsafe fn PyCMethod_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyCMethod_Type)) } #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_FUNCTION(func: *mut PyObject) -> PyMethodDefPointer { debug_assert_eq!(PyCMethod_Check(func), 1); let func = func.cast::(); (*(*func).m_ml).ml_meth } #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_SELF(func: *mut PyObject) -> *mut PyObject { debug_assert_eq!(PyCMethod_Check(func), 1); let func = func.cast::(); if (*(*func).m_ml).ml_flags & METH_STATIC != 0 { std::ptr::null_mut() } else { (*func).m_self } } #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_FLAGS(func: *mut PyObject) -> c_int { debug_assert_eq!(PyCMethod_Check(func), 1); let func = func.cast::(); (*(*func).m_ml).ml_flags } #[cfg(not(GraalPy))] #[inline] pub unsafe fn PyCFunction_GET_CLASS(func: *mut PyObject) -> *mut PyTypeObject { debug_assert_eq!(PyCMethod_Check(func), 1); let func = func.cast::(); if (*(*func).m_ml).ml_flags & METH_METHOD != 0 { let func = func.cast::(); (*func).mm_class } else { std::ptr::null_mut() } } pyo3-ffi/src/cpython/dictobject.rs0000644000175000017500000000421014661133735020125 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::c_int; opaque_struct!(PyDictKeysObject); #[cfg(Py_3_11)] opaque_struct!(PyDictValues); #[cfg(not(GraalPy))] #[repr(C)] #[derive(Debug)] pub struct PyDictObject { pub ob_base: PyObject, pub ma_used: Py_ssize_t, pub ma_version_tag: u64, pub ma_keys: *mut PyDictKeysObject, #[cfg(not(Py_3_11))] pub ma_values: *mut *mut PyObject, #[cfg(Py_3_11)] pub ma_values: *mut PyDictValues, } extern "C" { // skipped _PyDict_GetItem_KnownHash // skipped _PyDict_GetItemIdWithError // skipped _PyDict_GetItemStringWithError // skipped PyDict_SetDefault pub fn _PyDict_SetItem_KnownHash( mp: *mut PyObject, key: *mut PyObject, item: *mut PyObject, hash: crate::Py_hash_t, ) -> c_int; // skipped _PyDict_DelItem_KnownHash // skipped _PyDict_DelItemIf // skipped _PyDict_NewKeysForClass pub fn _PyDict_Next( mp: *mut PyObject, pos: *mut Py_ssize_t, key: *mut *mut PyObject, value: *mut *mut PyObject, hash: *mut crate::Py_hash_t, ) -> c_int; // skipped PyDict_GET_SIZE // skipped _PyDict_ContainsId pub fn _PyDict_NewPresized(minused: Py_ssize_t) -> *mut PyObject; // skipped _PyDict_MaybeUntrack // skipped _PyDict_HasOnlyStringKeys // skipped _PyDict_KeysSize // skipped _PyDict_SizeOf // skipped _PyDict_Pop // skipped _PyDict_Pop_KnownHash // skipped _PyDict_FromKeys // skipped _PyDict_HasSplitTable // skipped _PyDict_MergeEx // skipped _PyDict_SetItemId // skipped _PyDict_DelItemId // skipped _PyDict_DebugMallocStats // skipped _PyObjectDict_SetItem // skipped _PyDict_LoadGlobal // skipped _PyDict_GetItemHint // skipped _PyDictViewObject // skipped _PyDictView_New // skipped _PyDictView_Intersect #[cfg(Py_3_10)] pub fn _PyDict_Contains_KnownHash( op: *mut PyObject, key: *mut PyObject, hash: crate::Py_hash_t, ) -> c_int; #[cfg(not(Py_3_10))] pub fn _PyDict_Contains(mp: *mut PyObject, key: *mut PyObject, hash: Py_ssize_t) -> c_int; } pyo3-ffi/src/cpython/pymem.rs0000644000175000017500000000324514661133735017151 0ustar jamespagejamespageuse libc::size_t; use std::os::raw::c_void; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyMem_RawMalloc")] pub fn PyMem_RawMalloc(size: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyMem_RawCalloc")] pub fn PyMem_RawCalloc(nelem: size_t, elsize: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyMem_RawRealloc")] pub fn PyMem_RawRealloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyMem_RawFree")] pub fn PyMem_RawFree(ptr: *mut c_void); // skipped _PyMem_GetCurrentAllocatorName // skipped _PyMem_RawStrdup // skipped _PyMem_Strdup // skipped _PyMem_RawWcsdup } #[repr(C)] #[derive(Copy, Clone)] pub enum PyMemAllocatorDomain { PYMEM_DOMAIN_RAW, PYMEM_DOMAIN_MEM, PYMEM_DOMAIN_OBJ, } // skipped PyMemAllocatorName #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyMemAllocatorEx { pub ctx: *mut c_void, pub malloc: Option *mut c_void>, pub calloc: Option *mut c_void>, pub realloc: Option *mut c_void>, pub free: Option, } extern "C" { #[cfg(not(any(PyPy, GraalPy)))] pub fn PyMem_GetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx); #[cfg(not(any(PyPy, GraalPy)))] pub fn PyMem_SetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx); #[cfg(not(any(PyPy, GraalPy)))] pub fn PyMem_SetupDebugHooks(); } pyo3-ffi/src/cpython/tupleobject.rs0000644000175000017500000000164014661133735020337 0ustar jamespagejamespageuse crate::object::*; #[cfg(not(PyPy))] use crate::pyport::Py_ssize_t; #[repr(C)] pub struct PyTupleObject { pub ob_base: PyVarObject, #[cfg(not(GraalPy))] pub ob_item: [*mut PyObject; 1], } // skipped _PyTuple_Resize // skipped _PyTuple_MaybeUntrack /// Macro, trading safety for speed // skipped _PyTuple_CAST #[inline] #[cfg(not(PyPy))] pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { Py_SIZE(op) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { *(*(op as *mut PyTupleObject)).ob_item.as_ptr().offset(i) } /// Macro, *only* to be used to fill in brand new tuples #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { *(*(op as *mut PyTupleObject)).ob_item.as_mut_ptr().offset(i) = v; } // skipped _PyTuple_DebugMallocStats pyo3-ffi/src/cpython/pythonrun.rs0000644000175000017500000001635614661133735020077 0ustar jamespagejamespageuse crate::object::*; #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API, Py_3_10)))] use crate::pyarena::PyArena; use crate::PyCompilerFlags; #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] use crate::{_mod, _node}; use libc::FILE; use std::os::raw::{c_char, c_int}; extern "C" { pub fn PyRun_SimpleStringFlags(arg1: *const c_char, arg2: *mut PyCompilerFlags) -> c_int; pub fn _PyRun_SimpleFileObject( fp: *mut FILE, filename: *mut PyObject, closeit: c_int, flags: *mut PyCompilerFlags, ) -> c_int; pub fn PyRun_AnyFileExFlags( fp: *mut FILE, filename: *const c_char, closeit: c_int, flags: *mut PyCompilerFlags, ) -> c_int; pub fn _PyRun_AnyFileObject( fp: *mut FILE, filename: *mut PyObject, closeit: c_int, flags: *mut PyCompilerFlags, ) -> c_int; pub fn PyRun_SimpleFileExFlags( fp: *mut FILE, filename: *const c_char, closeit: c_int, flags: *mut PyCompilerFlags, ) -> c_int; pub fn PyRun_InteractiveOneFlags( fp: *mut FILE, filename: *const c_char, flags: *mut PyCompilerFlags, ) -> c_int; pub fn PyRun_InteractiveOneObject( fp: *mut FILE, filename: *mut PyObject, flags: *mut PyCompilerFlags, ) -> c_int; pub fn PyRun_InteractiveLoopFlags( fp: *mut FILE, filename: *const c_char, flags: *mut PyCompilerFlags, ) -> c_int; pub fn _PyRun_InteractiveLoopObject( fp: *mut FILE, filename: *mut PyObject, flags: *mut PyCompilerFlags, ) -> c_int; #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromString( s: *const c_char, filename: *const c_char, start: c_int, flags: *mut PyCompilerFlags, arena: *mut PyArena, ) -> *mut _mod; #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromStringObject( s: *const c_char, filename: *mut PyObject, start: c_int, flags: *mut PyCompilerFlags, arena: *mut PyArena, ) -> *mut _mod; #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromFile( fp: *mut FILE, filename: *const c_char, enc: *const c_char, start: c_int, ps1: *const c_char, ps2: *const c_char, flags: *mut PyCompilerFlags, errcode: *mut c_int, arena: *mut PyArena, ) -> *mut _mod; #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] pub fn PyParser_ASTFromFileObject( fp: *mut FILE, filename: *mut PyObject, enc: *const c_char, start: c_int, ps1: *const c_char, ps2: *const c_char, flags: *mut PyCompilerFlags, errcode: *mut c_int, arena: *mut PyArena, ) -> *mut _mod; } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyRun_StringFlags")] pub fn PyRun_StringFlags( arg1: *const c_char, arg2: c_int, arg3: *mut PyObject, arg4: *mut PyObject, arg5: *mut PyCompilerFlags, ) -> *mut PyObject; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_FileExFlags( fp: *mut FILE, filename: *const c_char, start: c_int, globals: *mut PyObject, locals: *mut PyObject, closeit: c_int, flags: *mut PyCompilerFlags, ) -> *mut PyObject; #[cfg(not(any(PyPy, GraalPy)))] pub fn Py_CompileStringExFlags( str: *const c_char, filename: *const c_char, start: c_int, flags: *mut PyCompilerFlags, optimize: c_int, ) -> *mut PyObject; #[cfg(not(Py_LIMITED_API))] pub fn Py_CompileStringObject( str: *const c_char, filename: *mut PyObject, start: c_int, flags: *mut PyCompilerFlags, optimize: c_int, ) -> *mut PyObject; } #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject { Py_CompileStringExFlags(string, p, s, std::ptr::null_mut(), -1) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn Py_CompileStringFlags( string: *const c_char, p: *const c_char, s: c_int, f: *mut PyCompilerFlags, ) -> *mut PyObject { Py_CompileStringExFlags(string, p, s, f, -1) } // skipped _Py_SourceAsString extern "C" { #[cfg_attr(PyPy, link_name = "PyPyRun_String")] pub fn PyRun_String( string: *const c_char, s: c_int, g: *mut PyObject, l: *mut PyObject, ) -> *mut PyObject; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_AnyFile(fp: *mut FILE, name: *const c_char) -> c_int; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_AnyFileEx(fp: *mut FILE, name: *const c_char, closeit: c_int) -> c_int; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_AnyFileFlags( arg1: *mut FILE, arg2: *const c_char, arg3: *mut PyCompilerFlags, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyRun_SimpleString")] pub fn PyRun_SimpleString(s: *const c_char) -> c_int; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_SimpleFile(f: *mut FILE, p: *const c_char) -> c_int; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_SimpleFileEx(f: *mut FILE, p: *const c_char, c: c_int) -> c_int; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_InteractiveOne(f: *mut FILE, p: *const c_char) -> c_int; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_InteractiveLoop(f: *mut FILE, p: *const c_char) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyRun_File")] pub fn PyRun_File( fp: *mut FILE, p: *const c_char, s: c_int, g: *mut PyObject, l: *mut PyObject, ) -> *mut PyObject; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_FileEx( fp: *mut FILE, p: *const c_char, s: c_int, g: *mut PyObject, l: *mut PyObject, c: c_int, ) -> *mut PyObject; #[cfg(not(any(PyPy, GraalPy)))] pub fn PyRun_FileFlags( fp: *mut FILE, p: *const c_char, s: c_int, g: *mut PyObject, l: *mut PyObject, flags: *mut PyCompilerFlags, ) -> *mut PyObject; } // skipped macro PyRun_String // skipped macro PyRun_AnyFile // skipped macro PyRun_AnyFileEx // skipped macro PyRun_AnyFileFlags extern "C" { #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseStringFlags( arg1: *const c_char, arg2: c_int, arg3: c_int, ) -> *mut _node; #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseStringFlagsFilename( arg1: *const c_char, arg2: *const c_char, arg3: c_int, arg4: c_int, ) -> *mut _node; #[cfg(not(any(PyPy, GraalPy, Py_3_10)))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyParser_SimpleParseFileFlags( arg1: *mut FILE, arg2: *const c_char, arg3: c_int, arg4: c_int, ) -> *mut _node; #[cfg(PyPy)] #[cfg_attr(PyPy, link_name = "PyPy_CompileStringFlags")] pub fn Py_CompileStringFlags( string: *const c_char, p: *const c_char, s: c_int, f: *mut PyCompilerFlags, ) -> *mut PyObject; } pyo3-ffi/src/cpython/genobject.rs0000644000175000017500000000506614661133735017765 0ustar jamespagejamespageuse crate::object::*; use crate::PyFrameObject; #[cfg(not(any(PyPy, GraalPy)))] use crate::_PyErr_StackItem; #[cfg(Py_3_11)] use std::os::raw::c_char; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyGenObject { pub ob_base: PyObject, #[cfg(not(Py_3_11))] pub gi_frame: *mut PyFrameObject, #[cfg(not(Py_3_10))] pub gi_running: c_int, #[cfg(not(Py_3_12))] pub gi_code: *mut PyObject, pub gi_weakreflist: *mut PyObject, pub gi_name: *mut PyObject, pub gi_qualname: *mut PyObject, pub gi_exc_state: _PyErr_StackItem, #[cfg(Py_3_11)] pub gi_origin_or_finalizer: *mut PyObject, #[cfg(Py_3_11)] pub gi_hooks_inited: c_char, #[cfg(Py_3_11)] pub gi_closed: c_char, #[cfg(Py_3_11)] pub gi_running_async: c_char, #[cfg(Py_3_11)] pub gi_frame_state: i8, #[cfg(Py_3_11)] pub gi_iframe: [*mut PyObject; 1], } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyGen_Type: PyTypeObject; } #[inline] pub unsafe fn PyGen_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyGen_Type)) } #[inline] pub unsafe fn PyGen_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyGen_Type)) as c_int } extern "C" { pub fn PyGen_New(frame: *mut PyFrameObject) -> *mut PyObject; // skipped PyGen_NewWithQualName // skipped _PyGen_SetStopIterationValue // skipped _PyGen_FetchStopIterationValue // skipped _PyGen_yf // skipped _PyGen_Finalize #[cfg(not(any(Py_3_9, PyPy)))] #[deprecated(note = "This function was never documented in the Python API.")] pub fn PyGen_NeedsFinalizing(op: *mut PyGenObject) -> c_int; } // skipped PyCoroObject #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyCoro_Type: PyTypeObject; pub static mut _PyCoroWrapper_Type: PyTypeObject; } #[inline] pub unsafe fn PyCoro_CheckExact(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyCoro_Type)) } // skipped _PyCoro_GetAwaitableIter // skipped PyCoro_New // skipped PyAsyncGenObject #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyAsyncGen_Type: PyTypeObject; // skipped _PyAsyncGenASend_Type // skipped _PyAsyncGenWrappedValue_Type // skipped _PyAsyncGenAThrow_Type } // skipped PyAsyncGen_New #[inline] pub unsafe fn PyAsyncGen_CheckExact(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyAsyncGen_Type)) } // skipped _PyAsyncGenValueWrapperNew pyo3-ffi/src/cpython/longobject.rs0000644000175000017500000000347414661133735020154 0ustar jamespagejamespageuse crate::longobject::*; use crate::object::*; #[cfg(Py_3_13)] use crate::pyport::Py_ssize_t; use libc::size_t; #[cfg(Py_3_13)] use std::os::raw::c_void; use std::os::raw::{c_int, c_uchar}; #[cfg(Py_3_13)] extern "C" { pub fn PyLong_FromUnicodeObject(u: *mut PyObject, base: c_int) -> *mut PyObject; } #[cfg(Py_3_13)] pub const Py_ASNATIVEBYTES_DEFAULTS: c_int = -1; #[cfg(Py_3_13)] pub const Py_ASNATIVEBYTES_BIG_ENDIAN: c_int = 0; #[cfg(Py_3_13)] pub const Py_ASNATIVEBYTES_LITTLE_ENDIAN: c_int = 1; #[cfg(Py_3_13)] pub const Py_ASNATIVEBYTES_NATIVE_ENDIAN: c_int = 3; #[cfg(Py_3_13)] pub const Py_ASNATIVEBYTES_UNSIGNED_BUFFER: c_int = 4; #[cfg(Py_3_13)] pub const Py_ASNATIVEBYTES_REJECT_NEGATIVE: c_int = 8; extern "C" { // skipped _PyLong_Sign #[cfg(Py_3_13)] pub fn PyLong_AsNativeBytes( v: *mut PyObject, buffer: *mut c_void, n_bytes: Py_ssize_t, flags: c_int, ) -> Py_ssize_t; #[cfg(Py_3_13)] pub fn PyLong_FromNativeBytes( buffer: *const c_void, n_bytes: size_t, flags: c_int, ) -> *mut PyObject; #[cfg(Py_3_13)] pub fn PyLong_FromUnsignedNativeBytes( buffer: *const c_void, n_bytes: size_t, flags: c_int, ) -> *mut PyObject; // skipped PyUnstable_Long_IsCompact // skipped PyUnstable_Long_CompactValue #[cfg_attr(PyPy, link_name = "_PyPyLong_FromByteArray")] pub fn _PyLong_FromByteArray( bytes: *const c_uchar, n: size_t, little_endian: c_int, is_signed: c_int, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")] pub fn _PyLong_AsByteArray( v: *mut PyLongObject, bytes: *mut c_uchar, n: size_t, little_endian: c_int, is_signed: c_int, ) -> c_int; // skipped _PyLong_GCD } pyo3-ffi/src/cpython/descrobject.rs0000644000175000017500000000337614661133735020316 0ustar jamespagejamespageuse crate::{PyGetSetDef, PyMethodDef, PyObject, PyTypeObject}; use std::os::raw::{c_char, c_int, c_void}; pub type wrapperfunc = Option< unsafe extern "C" fn( slf: *mut PyObject, args: *mut PyObject, wrapped: *mut c_void, ) -> *mut PyObject, >; pub type wrapperfunc_kwds = Option< unsafe extern "C" fn( slf: *mut PyObject, args: *mut PyObject, wrapped: *mut c_void, kwds: *mut PyObject, ) -> *mut PyObject, >; #[repr(C)] pub struct wrapperbase { pub name: *const c_char, pub offset: c_int, pub function: *mut c_void, pub wrapper: wrapperfunc, pub doc: *const c_char, pub flags: c_int, pub name_strobj: *mut PyObject, } pub const PyWrapperFlag_KEYWORDS: c_int = 1; #[repr(C)] pub struct PyDescrObject { pub ob_base: PyObject, pub d_type: *mut PyTypeObject, pub d_name: *mut PyObject, pub d_qualname: *mut PyObject, } // skipped non-limited PyDescr_TYPE // skipped non-limited PyDescr_NAME #[repr(C)] pub struct PyMethodDescrObject { pub d_common: PyDescrObject, pub d_method: *mut PyMethodDef, #[cfg(all(not(PyPy), Py_3_8))] pub vectorcall: Option, } #[repr(C)] pub struct PyMemberDescrObject { pub d_common: PyDescrObject, pub d_member: *mut PyGetSetDef, } #[repr(C)] pub struct PyGetSetDescrObject { pub d_common: PyDescrObject, pub d_getset: *mut PyGetSetDef, } #[repr(C)] pub struct PyWrapperDescrObject { pub d_common: PyDescrObject, pub d_base: *mut wrapperbase, pub d_wrapped: *mut c_void, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut _PyMethodWrapper_Type: PyTypeObject; } // skipped non-limited PyDescr_NewWrapper // skipped non-limited PyDescr_IsData pyo3-ffi/src/cpython/pystate.rs0000644000175000017500000000653614661133735017521 0ustar jamespagejamespage#[cfg(not(PyPy))] use crate::PyThreadState; use crate::{PyFrameObject, PyInterpreterState, PyObject}; use std::os::raw::c_int; // skipped _PyInterpreterState_RequiresIDRef // skipped _PyInterpreterState_RequireIDRef // skipped _PyInterpreterState_GetMainModule pub type Py_tracefunc = unsafe extern "C" fn( obj: *mut PyObject, frame: *mut PyFrameObject, what: c_int, arg: *mut PyObject, ) -> c_int; pub const PyTrace_CALL: c_int = 0; pub const PyTrace_EXCEPTION: c_int = 1; pub const PyTrace_LINE: c_int = 2; pub const PyTrace_RETURN: c_int = 3; pub const PyTrace_C_CALL: c_int = 4; pub const PyTrace_C_EXCEPTION: c_int = 5; pub const PyTrace_C_RETURN: c_int = 6; pub const PyTrace_OPCODE: c_int = 7; // skipped PyTraceInfo // skipped CFrame #[cfg(not(PyPy))] #[repr(C)] #[derive(Clone, Copy)] pub struct _PyErr_StackItem { #[cfg(not(Py_3_11))] pub exc_type: *mut PyObject, pub exc_value: *mut PyObject, #[cfg(not(Py_3_11))] pub exc_traceback: *mut PyObject, pub previous_item: *mut _PyErr_StackItem, } // skipped _PyStackChunk // skipped _ts (aka PyThreadState) extern "C" { // skipped _PyThreadState_Prealloc // skipped _PyThreadState_UncheckedGet // skipped _PyThreadState_GetDict #[cfg_attr(PyPy, link_name = "PyPyGILState_Check")] pub fn PyGILState_Check() -> c_int; // skipped _PyGILState_GetInterpreterStateUnsafe // skipped _PyThread_CurrentFrames // skipped _PyThread_CurrentExceptions #[cfg(not(PyPy))] pub fn PyInterpreterState_Main() -> *mut PyInterpreterState; #[cfg_attr(PyPy, link_name = "PyPyInterpreterState_Head")] pub fn PyInterpreterState_Head() -> *mut PyInterpreterState; #[cfg_attr(PyPy, link_name = "PyPyInterpreterState_Next")] pub fn PyInterpreterState_Next(interp: *mut PyInterpreterState) -> *mut PyInterpreterState; #[cfg(not(PyPy))] pub fn PyInterpreterState_ThreadHead(interp: *mut PyInterpreterState) -> *mut PyThreadState; #[cfg(not(PyPy))] pub fn PyThreadState_Next(tstate: *mut PyThreadState) -> *mut PyThreadState; #[cfg_attr(PyPy, link_name = "PyPyThreadState_DeleteCurrent")] pub fn PyThreadState_DeleteCurrent(); } #[cfg(all(Py_3_9, not(Py_3_11)))] pub type _PyFrameEvalFunction = extern "C" fn( *mut crate::PyThreadState, *mut crate::PyFrameObject, c_int, ) -> *mut crate::object::PyObject; #[cfg(Py_3_11)] pub type _PyFrameEvalFunction = extern "C" fn( *mut crate::PyThreadState, *mut crate::_PyInterpreterFrame, c_int, ) -> *mut crate::object::PyObject; #[cfg(Py_3_9)] extern "C" { /// Get the frame evaluation function. pub fn _PyInterpreterState_GetEvalFrameFunc( interp: *mut PyInterpreterState, ) -> _PyFrameEvalFunction; ///Set the frame evaluation function. pub fn _PyInterpreterState_SetEvalFrameFunc( interp: *mut PyInterpreterState, eval_frame: _PyFrameEvalFunction, ); } // skipped _PyInterpreterState_GetConfig // skipped _PyInterpreterState_GetConfigCopy // skipped _PyInterpreterState_SetConfig // skipped _Py_GetConfig // skipped _PyCrossInterpreterData // skipped _PyObject_GetCrossInterpreterData // skipped _PyCrossInterpreterData_NewObject // skipped _PyCrossInterpreterData_Release // skipped _PyObject_CheckCrossInterpreterData // skipped crossinterpdatafunc // skipped _PyCrossInterpreterData_RegisterClass // skipped _PyCrossInterpreterData_Lookup pyo3-ffi/src/cpython/pyerrors.rs0000644000175000017500000001143314661133735017705 0ustar jamespagejamespageuse crate::PyObject; #[cfg(not(any(PyPy, GraalPy)))] use crate::Py_ssize_t; #[repr(C)] #[derive(Debug)] pub struct PyBaseExceptionObject { pub ob_base: PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub dict: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub args: *mut PyObject, #[cfg(all(Py_3_11, not(any(PyPy, GraalPy))))] pub notes: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub traceback: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub context: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub cause: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub suppress_context: char, } #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PySyntaxErrorObject { pub ob_base: PyObject, pub dict: *mut PyObject, pub args: *mut PyObject, #[cfg(Py_3_11)] pub notes: *mut PyObject, pub traceback: *mut PyObject, pub context: *mut PyObject, pub cause: *mut PyObject, pub suppress_context: char, pub msg: *mut PyObject, pub filename: *mut PyObject, pub lineno: *mut PyObject, pub offset: *mut PyObject, #[cfg(Py_3_10)] pub end_lineno: *mut PyObject, #[cfg(Py_3_10)] pub end_offset: *mut PyObject, pub text: *mut PyObject, pub print_file_and_line: *mut PyObject, } #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PyImportErrorObject { pub ob_base: PyObject, pub dict: *mut PyObject, pub args: *mut PyObject, #[cfg(Py_3_11)] pub notes: *mut PyObject, pub traceback: *mut PyObject, pub context: *mut PyObject, pub cause: *mut PyObject, pub suppress_context: char, pub msg: *mut PyObject, pub name: *mut PyObject, pub path: *mut PyObject, #[cfg(Py_3_12)] pub name_from: *mut PyObject, } #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PyUnicodeErrorObject { pub ob_base: PyObject, pub dict: *mut PyObject, pub args: *mut PyObject, #[cfg(Py_3_11)] pub notes: *mut PyObject, pub traceback: *mut PyObject, pub context: *mut PyObject, pub cause: *mut PyObject, pub suppress_context: char, pub encoding: *mut PyObject, pub object: *mut PyObject, pub start: Py_ssize_t, pub end: Py_ssize_t, pub reason: *mut PyObject, } #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PySystemExitObject { pub ob_base: PyObject, pub dict: *mut PyObject, pub args: *mut PyObject, #[cfg(Py_3_11)] pub notes: *mut PyObject, pub traceback: *mut PyObject, pub context: *mut PyObject, pub cause: *mut PyObject, pub suppress_context: char, pub code: *mut PyObject, } #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PyOSErrorObject { pub ob_base: PyObject, pub dict: *mut PyObject, pub args: *mut PyObject, #[cfg(Py_3_11)] pub notes: *mut PyObject, pub traceback: *mut PyObject, pub context: *mut PyObject, pub cause: *mut PyObject, pub suppress_context: char, pub myerrno: *mut PyObject, pub strerror: *mut PyObject, pub filename: *mut PyObject, pub filename2: *mut PyObject, #[cfg(windows)] pub winerror: *mut PyObject, pub written: Py_ssize_t, } #[repr(C)] #[derive(Debug)] pub struct PyStopIterationObject { pub ob_base: PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub dict: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub args: *mut PyObject, #[cfg(all(Py_3_11, not(any(PyPy, GraalPy))))] pub notes: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub traceback: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub context: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub cause: *mut PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub suppress_context: char, pub value: *mut PyObject, } extern "C" { #[cfg(not(any(PyPy, GraalPy)))] pub fn _PyErr_ChainExceptions(typ: *mut PyObject, val: *mut PyObject, tb: *mut PyObject); } // skipped PyNameErrorObject // skipped PyAttributeErrorObject // skipped PyEnvironmentErrorObject // skipped PyWindowsErrorObject // skipped _PyErr_SetKeyError // skipped _PyErr_GetTopmostException // skipped _PyErr_GetExcInfo // skipped PyErr_SetFromErrnoWithUnicodeFilename // skipped _PyErr_FormatFromCause // skipped PyErr_SetFromWindowsErrWithUnicodeFilename // skipped PyErr_SetExcFromWindowsErrWithUnicodeFilename // skipped _PyErr_TrySetFromCause // skipped PySignal_SetWakeupFd // skipped _PyErr_CheckSignals // skipped PyErr_SyntaxLocationObject // skipped PyErr_RangedSyntaxLocationObject // skipped PyErr_ProgramTextObject // skipped _PyErr_ProgramDecodedTextObject // skipped _PyUnicodeTranslateError_Create // skipped _PyErr_WriteUnraisableMsg // skipped _Py_FatalErrorFunc // skipped _Py_FatalErrorFormat // skipped Py_FatalError pyo3-ffi/src/cpython/bytesobject.rs0000644000175000017500000000110714661133735020332 0ustar jamespagejamespageuse crate::object::*; use crate::Py_ssize_t; #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] use std::os::raw::c_char; use std::os::raw::c_int; #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyBytesObject { pub ob_base: PyVarObject, pub ob_shash: crate::Py_hash_t, pub ob_sval: [c_char; 1], } #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))] opaque_struct!(PyBytesObject); extern "C" { #[cfg_attr(PyPy, link_name = "_PyPyBytes_Resize")] pub fn _PyBytes_Resize(bytes: *mut *mut PyObject, newsize: Py_ssize_t) -> c_int; } pyo3-ffi/src/cpython/pyframe.rs0000644000175000017500000000006514661133735017462 0ustar jamespagejamespage#[cfg(Py_3_11)] opaque_struct!(_PyInterpreterFrame); pyo3-ffi/src/cpython/ceval.rs0000644000175000017500000000133514661133735017112 0ustar jamespagejamespageuse crate::cpython::pystate::Py_tracefunc; use crate::object::{freefunc, PyObject}; use std::os::raw::c_int; extern "C" { // skipped non-limited _PyEval_CallTracing #[cfg(not(Py_3_11))] pub fn _PyEval_EvalFrameDefault(arg1: *mut crate::PyFrameObject, exc: c_int) -> *mut PyObject; #[cfg(Py_3_11)] pub fn _PyEval_EvalFrameDefault( tstate: *mut crate::PyThreadState, frame: *mut crate::_PyInterpreterFrame, exc: c_int, ) -> *mut crate::PyObject; pub fn _PyEval_RequestCodeExtraIndex(func: freefunc) -> c_int; pub fn PyEval_SetProfile(trace_func: Option, arg1: *mut PyObject); pub fn PyEval_SetTrace(trace_func: Option, arg1: *mut PyObject); } pyo3-ffi/src/cpython/weakrefobject.rs0000644000175000017500000000073714661133735020640 0ustar jamespagejamespage#[cfg(not(any(PyPy, GraalPy)))] pub struct _PyWeakReference { pub ob_base: crate::PyObject, pub wr_object: *mut crate::PyObject, pub wr_callback: *mut crate::PyObject, pub hash: crate::Py_hash_t, pub wr_prev: *mut crate::PyWeakReference, pub wr_next: *mut crate::PyWeakReference, #[cfg(Py_3_11)] pub vectorcall: Option, } // skipped _PyWeakref_GetWeakrefCount // skipped _PyWeakref_ClearRef // skipped PyWeakRef_GET_OBJECT pyo3-ffi/src/cpython/abstract_.rs0000644000175000017500000002362214661133735017765 0ustar jamespagejamespageuse crate::{PyObject, Py_ssize_t}; use std::os::raw::{c_char, c_int}; #[cfg(not(Py_3_11))] use crate::Py_buffer; #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] use crate::{ vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check, PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL, }; #[cfg(Py_3_8)] use libc::size_t; extern "C" { #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] pub fn _PyStack_AsDict(values: *const *mut PyObject, kwnames: *mut PyObject) -> *mut PyObject; } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] const _PY_FASTCALL_SMALL_STACK: size_t = 5; extern "C" { #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] pub fn _Py_CheckFunctionResult( tstate: *mut PyThreadState, callable: *mut PyObject, result: *mut PyObject, where_: *const c_char, ) -> *mut PyObject; #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] pub fn _PyObject_MakeTpCall( tstate: *mut PyThreadState, callable: *mut PyObject, args: *const *mut PyObject, nargs: Py_ssize_t, keywords: *mut PyObject, ) -> *mut PyObject; } #[cfg(Py_3_8)] const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t = 1 << (8 * std::mem::size_of::() as size_t - 1); #[cfg(Py_3_8)] #[inline(always)] pub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t { let n = n & !PY_VECTORCALL_ARGUMENTS_OFFSET; n.try_into().expect("cannot fail due to mask") } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option { assert!(!callable.is_null()); let tp = crate::Py_TYPE(callable); if PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL) == 0 { return None; } assert!(PyCallable_Check(callable) > 0); let offset = (*tp).tp_vectorcall_offset; assert!(offset > 0); let ptr = callable.cast::().offset(offset).cast(); *ptr } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn _PyObject_VectorcallTstate( tstate: *mut PyThreadState, callable: *mut PyObject, args: *const *mut PyObject, nargsf: size_t, kwnames: *mut PyObject, ) -> *mut PyObject { assert!(kwnames.is_null() || PyTuple_Check(kwnames) > 0); assert!(!args.is_null() || PyVectorcall_NARGS(nargsf) == 0); match PyVectorcall_Function(callable) { None => { let nargs = PyVectorcall_NARGS(nargsf); _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames) } Some(func) => { let res = func(callable, args, nargsf, kwnames); _Py_CheckFunctionResult(tstate, callable, res, std::ptr::null_mut()) } } } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyObject_Vectorcall( callable: *mut PyObject, args: *const *mut PyObject, nargsf: size_t, kwnames: *mut PyObject, ) -> *mut PyObject { _PyObject_VectorcallTstate(PyThreadState_GET(), callable, args, nargsf, kwnames) } extern "C" { #[cfg(all(PyPy, Py_3_8))] #[cfg_attr(not(Py_3_9), link_name = "_PyPyObject_Vectorcall")] #[cfg_attr(Py_3_9, link_name = "PyPyObject_Vectorcall")] pub fn PyObject_Vectorcall( callable: *mut PyObject, args: *const *mut PyObject, nargsf: size_t, kwnames: *mut PyObject, ) -> *mut PyObject; #[cfg(Py_3_8)] #[cfg_attr( all(not(any(PyPy, GraalPy)), not(Py_3_9)), link_name = "_PyObject_VectorcallDict" )] #[cfg_attr(all(PyPy, not(Py_3_9)), link_name = "_PyPyObject_VectorcallDict")] #[cfg_attr(all(PyPy, Py_3_9), link_name = "PyPyObject_VectorcallDict")] pub fn PyObject_VectorcallDict( callable: *mut PyObject, args: *const *mut PyObject, nargsf: size_t, kwdict: *mut PyObject, ) -> *mut PyObject; #[cfg(Py_3_8)] #[cfg_attr(not(any(Py_3_9, PyPy)), link_name = "_PyVectorcall_Call")] #[cfg_attr(PyPy, link_name = "PyPyVectorcall_Call")] pub fn PyVectorcall_Call( callable: *mut PyObject, tuple: *mut PyObject, dict: *mut PyObject, ) -> *mut PyObject; } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn _PyObject_FastCallTstate( tstate: *mut PyThreadState, func: *mut PyObject, args: *const *mut PyObject, nargs: Py_ssize_t, ) -> *mut PyObject { _PyObject_VectorcallTstate(tstate, func, args, nargs as size_t, std::ptr::null_mut()) } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn _PyObject_FastCall( func: *mut PyObject, args: *const *mut PyObject, nargs: Py_ssize_t, ) -> *mut PyObject { _PyObject_FastCallTstate(PyThreadState_GET(), func, args, nargs) } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject { _PyObject_VectorcallTstate( PyThreadState_GET(), func, std::ptr::null_mut(), 0, std::ptr::null_mut(), ) } extern "C" { #[cfg(PyPy)] #[link_name = "_PyPyObject_CallNoArg"] pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject; } #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject { assert!(!arg.is_null()); let args_array = [std::ptr::null_mut(), arg]; let args = args_array.as_ptr().offset(1); // For PY_VECTORCALL_ARGUMENTS_OFFSET let tstate = PyThreadState_GET(); let nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET; _PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut()) } extern "C" { #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] pub fn PyObject_VectorcallMethod( name: *mut PyObject, args: *const *mut PyObject, nargsf: size_t, kwnames: *mut PyObject, ) -> *mut PyObject; } #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyObject_CallMethodNoArgs( self_: *mut PyObject, name: *mut PyObject, ) -> *mut PyObject { PyObject_VectorcallMethod( name, &self_, 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, std::ptr::null_mut(), ) } #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] #[inline(always)] pub unsafe fn PyObject_CallMethodOneArg( self_: *mut PyObject, name: *mut PyObject, arg: *mut PyObject, ) -> *mut PyObject { let args = [self_, arg]; assert!(!arg.is_null()); PyObject_VectorcallMethod( name, args.as_ptr(), 2 | PY_VECTORCALL_ARGUMENTS_OFFSET, std::ptr::null_mut(), ) } // skipped _PyObject_VectorcallMethodId // skipped _PyObject_CallMethodIdNoArgs // skipped _PyObject_CallMethodIdOneArg // skipped _PyObject_HasLen extern "C" { #[cfg_attr(PyPy, link_name = "PyPyObject_LengthHint")] pub fn PyObject_LengthHint(o: *mut PyObject, arg1: Py_ssize_t) -> Py_ssize_t; #[cfg(not(Py_3_11))] // moved to src/buffer.rs from 3.11 #[cfg(all(Py_3_9, not(any(PyPy, GraalPy))))] pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int; } #[cfg(not(any(Py_3_9, PyPy)))] #[inline] pub unsafe fn PyObject_CheckBuffer(o: *mut PyObject) -> c_int { let tp_as_buffer = (*crate::Py_TYPE(o)).tp_as_buffer; (!tp_as_buffer.is_null() && (*tp_as_buffer).bf_getbuffer.is_some()) as c_int } #[cfg(not(Py_3_11))] // moved to src/buffer.rs from 3.11 extern "C" { #[cfg_attr(PyPy, link_name = "PyPyObject_GetBuffer")] pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, flags: c_int) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_GetPointer")] pub fn PyBuffer_GetPointer( view: *mut Py_buffer, indices: *mut Py_ssize_t, ) -> *mut std::os::raw::c_void; #[cfg_attr(PyPy, link_name = "PyPyBuffer_SizeFromFormat")] pub fn PyBuffer_SizeFromFormat(format: *const c_char) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyBuffer_ToContiguous")] pub fn PyBuffer_ToContiguous( buf: *mut std::os::raw::c_void, view: *mut Py_buffer, len: Py_ssize_t, order: c_char, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_FromContiguous")] pub fn PyBuffer_FromContiguous( view: *mut Py_buffer, buf: *mut std::os::raw::c_void, len: Py_ssize_t, order: c_char, ) -> c_int; pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_IsContiguous")] pub fn PyBuffer_IsContiguous(view: *const Py_buffer, fort: c_char) -> c_int; pub fn PyBuffer_FillContiguousStrides( ndims: c_int, shape: *mut Py_ssize_t, strides: *mut Py_ssize_t, itemsize: c_int, fort: c_char, ); #[cfg_attr(PyPy, link_name = "PyPyBuffer_FillInfo")] pub fn PyBuffer_FillInfo( view: *mut Py_buffer, o: *mut PyObject, buf: *mut std::os::raw::c_void, len: Py_ssize_t, readonly: c_int, flags: c_int, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyBuffer_Release")] pub fn PyBuffer_Release(view: *mut Py_buffer); } // PyIter_Check defined in ffi/abstract_.rs // PyIndex_Check defined in ffi/abstract_.rs // Not defined here because this file is not compiled under the // limited API, but the macros need to be defined for 3.6, 3.7 which // predate the limited API changes. // skipped PySequence_ITEM pub const PY_ITERSEARCH_COUNT: c_int = 1; pub const PY_ITERSEARCH_INDEX: c_int = 2; pub const PY_ITERSEARCH_CONTAINS: c_int = 3; extern "C" { #[cfg(not(any(PyPy, GraalPy)))] pub fn _PySequence_IterSearch( seq: *mut PyObject, obj: *mut PyObject, operation: c_int, ) -> Py_ssize_t; } // skipped _PyObject_RealIsInstance // skipped _PyObject_RealIsSubclass // skipped _PySequence_BytesToCharpArray // skipped _Py_FreeCharPArray // skipped _Py_add_one_to_index_F // skipped _Py_add_one_to_index_C // skipped _Py_convert_optional_to_ssize_t // skipped _PyNumber_Index(*mut PyObject o) pyo3-ffi/src/cpython/import.rs0000644000175000017500000000427014661133735017333 0ustar jamespagejamespageuse crate::{PyInterpreterState, PyObject}; #[cfg(not(PyPy))] use std::os::raw::c_uchar; use std::os::raw::{c_char, c_int}; // skipped PyInit__imp extern "C" { pub fn _PyImport_IsInitialized(state: *mut PyInterpreterState) -> c_int; // skipped _PyImport_GetModuleId pub fn _PyImport_SetModule(name: *mut PyObject, module: *mut PyObject) -> c_int; pub fn _PyImport_SetModuleString(name: *const c_char, module: *mut PyObject) -> c_int; pub fn _PyImport_AcquireLock(); pub fn _PyImport_ReleaseLock() -> c_int; #[cfg(not(Py_3_9))] pub fn _PyImport_FindBuiltin(name: *const c_char, modules: *mut PyObject) -> *mut PyObject; #[cfg(not(Py_3_11))] pub fn _PyImport_FindExtensionObject(a: *mut PyObject, b: *mut PyObject) -> *mut PyObject; pub fn _PyImport_FixupBuiltin( module: *mut PyObject, name: *const c_char, modules: *mut PyObject, ) -> c_int; pub fn _PyImport_FixupExtensionObject( a: *mut PyObject, b: *mut PyObject, c: *mut PyObject, d: *mut PyObject, ) -> c_int; } #[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct _inittab { pub name: *const c_char, pub initfunc: Option *mut PyObject>, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(PyPy))] pub static mut PyImport_Inittab: *mut _inittab; } extern "C" { #[cfg(not(PyPy))] pub fn PyImport_ExtendInittab(newtab: *mut _inittab) -> c_int; } #[cfg(not(PyPy))] #[repr(C)] #[derive(Copy, Clone)] pub struct _frozen { pub name: *const c_char, pub code: *const c_uchar, pub size: c_int, #[cfg(Py_3_11)] pub is_package: c_int, #[cfg(all(Py_3_11, not(Py_3_13)))] pub get_code: Option *mut PyObject>, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(PyPy))] pub static mut PyImport_FrozenModules: *const _frozen; #[cfg(all(not(PyPy), Py_3_11))] pub static mut _PyImport_FrozenBootstrap: *const _frozen; #[cfg(all(not(PyPy), Py_3_11))] pub static mut _PyImport_FrozenStdlib: *const _frozen; #[cfg(all(not(PyPy), Py_3_11))] pub static mut _PyImport_FrozenTest: *const _frozen; } pyo3-ffi/src/cpython/floatobject.rs0000644000175000017500000000133014661133735020307 0ustar jamespagejamespage#[cfg(GraalPy)] use crate::PyFloat_AsDouble; use crate::{PyFloat_Check, PyObject}; use std::os::raw::c_double; #[repr(C)] pub struct PyFloatObject { pub ob_base: PyObject, #[cfg(not(GraalPy))] pub ob_fval: c_double, } #[inline] pub unsafe fn _PyFloat_CAST(op: *mut PyObject) -> *mut PyFloatObject { debug_assert_eq!(PyFloat_Check(op), 1); op.cast() } #[inline] pub unsafe fn PyFloat_AS_DOUBLE(op: *mut PyObject) -> c_double { #[cfg(not(GraalPy))] return (*_PyFloat_CAST(op)).ob_fval; #[cfg(GraalPy)] return PyFloat_AsDouble(op); } // skipped PyFloat_Pack2 // skipped PyFloat_Pack4 // skipped PyFloat_Pack8 // skipped PyFloat_Unpack2 // skipped PyFloat_Unpack4 // skipped PyFloat_Unpack8 pyo3-ffi/src/cpython/mod.rs0000644000175000017500000000363314661133735016602 0ustar jamespagejamespagepub(crate) mod abstract_; // skipped bytearrayobject.h pub(crate) mod bytesobject; #[cfg(not(PyPy))] pub(crate) mod ceval; pub(crate) mod code; pub(crate) mod compile; pub(crate) mod descrobject; #[cfg(not(PyPy))] pub(crate) mod dictobject; // skipped fileobject.h // skipped fileutils.h pub(crate) mod frameobject; pub(crate) mod funcobject; pub(crate) mod genobject; pub(crate) mod import; #[cfg(all(Py_3_8, not(PyPy)))] pub(crate) mod initconfig; // skipped interpreteridobject.h pub(crate) mod listobject; pub(crate) mod longobject; #[cfg(all(Py_3_9, not(PyPy)))] pub(crate) mod methodobject; pub(crate) mod object; pub(crate) mod objimpl; pub(crate) mod pydebug; pub(crate) mod pyerrors; #[cfg(all(Py_3_8, not(PyPy)))] pub(crate) mod pylifecycle; pub(crate) mod pymem; pub(crate) mod pystate; pub(crate) mod pythonrun; // skipped sysmodule.h pub(crate) mod floatobject; pub(crate) mod pyframe; pub(crate) mod tupleobject; pub(crate) mod unicodeobject; pub(crate) mod weakrefobject; pub use self::abstract_::*; pub use self::bytesobject::*; #[cfg(not(PyPy))] pub use self::ceval::*; pub use self::code::*; pub use self::compile::*; pub use self::descrobject::*; #[cfg(not(PyPy))] pub use self::dictobject::*; pub use self::floatobject::*; pub use self::frameobject::*; pub use self::funcobject::*; pub use self::genobject::*; pub use self::import::*; #[cfg(all(Py_3_8, not(PyPy)))] pub use self::initconfig::*; pub use self::listobject::*; pub use self::longobject::*; #[cfg(all(Py_3_9, not(PyPy)))] pub use self::methodobject::*; pub use self::object::*; pub use self::objimpl::*; pub use self::pydebug::*; pub use self::pyerrors::*; #[cfg(Py_3_11)] pub use self::pyframe::*; #[cfg(all(Py_3_8, not(PyPy)))] pub use self::pylifecycle::*; pub use self::pymem::*; pub use self::pystate::*; pub use self::pythonrun::*; pub use self::tupleobject::*; pub use self::unicodeobject::*; #[cfg(not(any(PyPy, GraalPy)))] pub use self::weakrefobject::*; pyo3-ffi/src/cpython/pydebug.rs0000644000175000017500000000534014661133735017457 0ustar jamespagejamespageuse std::os::raw::{c_char, c_int}; #[cfg(not(Py_LIMITED_API))] #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_DebugFlag")] pub static mut Py_DebugFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_VerboseFlag")] pub static mut Py_VerboseFlag: c_int; #[deprecated(note = "Python 3.12")] pub static mut Py_QuietFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_InteractiveFlag")] pub static mut Py_InteractiveFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_InspectFlag")] pub static mut Py_InspectFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_OptimizeFlag")] pub static mut Py_OptimizeFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_NoSiteFlag")] pub static mut Py_NoSiteFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_BytesWarningFlag")] pub static mut Py_BytesWarningFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_UseClassExceptionsFlag")] pub static mut Py_UseClassExceptionsFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_FrozenFlag")] pub static mut Py_FrozenFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_IgnoreEnvironmentFlag")] pub static mut Py_IgnoreEnvironmentFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_DontWriteBytecodeFlag")] pub static mut Py_DontWriteBytecodeFlag: c_int; #[deprecated(note = "Python 3.12")] #[cfg_attr(PyPy, link_name = "PyPy_NoUserSiteDirectory")] pub static mut Py_NoUserSiteDirectory: c_int; #[deprecated(note = "Python 3.12")] pub static mut Py_UnbufferedStdioFlag: c_int; #[cfg_attr(PyPy, link_name = "PyPy_HashRandomizationFlag")] pub static mut Py_HashRandomizationFlag: c_int; #[deprecated(note = "Python 3.12")] pub static mut Py_IsolatedFlag: c_int; #[cfg(windows)] #[deprecated(note = "Python 3.12")] pub static mut Py_LegacyWindowsFSEncodingFlag: c_int; #[cfg(windows)] #[deprecated(note = "Python 3.12")] pub static mut Py_LegacyWindowsStdioFlag: c_int; } extern "C" { #[cfg(Py_3_11)] pub fn Py_GETENV(name: *const c_char) -> *mut c_char; } #[cfg(not(Py_3_11))] #[inline(always)] pub unsafe fn Py_GETENV(name: *const c_char) -> *mut c_char { #[allow(deprecated)] if Py_IgnoreEnvironmentFlag != 0 { std::ptr::null_mut() } else { libc::getenv(name) } } pyo3-ffi/src/cpython/compile.rs0000644000175000017500000000626414661133735017456 0ustar jamespagejamespage#[cfg(not(any(PyPy, Py_3_10)))] use crate::object::PyObject; #[cfg(not(any(PyPy, Py_3_10)))] use crate::pyarena::*; #[cfg(not(any(PyPy, Py_3_10)))] use crate::pythonrun::*; #[cfg(not(any(PyPy, Py_3_10)))] use crate::PyCodeObject; #[cfg(not(any(PyPy, Py_3_10)))] use std::os::raw::c_char; use std::os::raw::c_int; // skipped non-limited PyCF_MASK // skipped non-limited PyCF_MASK_OBSOLETE // skipped non-limited PyCF_SOURCE_IS_UTF8 // skipped non-limited PyCF_DONT_IMPLY_DEDENT // skipped non-limited PyCF_ONLY_AST // skipped non-limited PyCF_IGNORE_COOKIE // skipped non-limited PyCF_TYPE_COMMENTS // skipped non-limited PyCF_ALLOW_TOP_LEVEL_AWAIT // skipped non-limited PyCF_COMPILE_MASK #[repr(C)] #[derive(Copy, Clone)] pub struct PyCompilerFlags { pub cf_flags: c_int, #[cfg(Py_3_8)] pub cf_feature_version: c_int, } // skipped non-limited _PyCompilerFlags_INIT #[cfg(all(Py_3_12, not(any(Py_3_13, PyPy, GraalPy))))] #[repr(C)] #[derive(Copy, Clone)] pub struct _PyCompilerSrcLocation { pub lineno: c_int, pub end_lineno: c_int, pub col_offset: c_int, pub end_col_offset: c_int, } // skipped SRC_LOCATION_FROM_AST #[cfg(not(any(PyPy, GraalPy, Py_3_13)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyFutureFeatures { pub ff_features: c_int, #[cfg(not(Py_3_12))] pub ff_lineno: c_int, #[cfg(Py_3_12)] pub ff_location: _PyCompilerSrcLocation, } pub const FUTURE_NESTED_SCOPES: &str = "nested_scopes"; pub const FUTURE_GENERATORS: &str = "generators"; pub const FUTURE_DIVISION: &str = "division"; pub const FUTURE_ABSOLUTE_IMPORT: &str = "absolute_import"; pub const FUTURE_WITH_STATEMENT: &str = "with_statement"; pub const FUTURE_PRINT_FUNCTION: &str = "print_function"; pub const FUTURE_UNICODE_LITERALS: &str = "unicode_literals"; pub const FUTURE_BARRY_AS_BDFL: &str = "barry_as_FLUFL"; pub const FUTURE_GENERATOR_STOP: &str = "generator_stop"; // skipped non-limited FUTURE_ANNOTATIONS extern "C" { #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyNode_Compile(arg1: *mut _node, arg2: *const c_char) -> *mut PyCodeObject; #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyAST_CompileEx( _mod: *mut _mod, filename: *const c_char, flags: *mut PyCompilerFlags, optimize: c_int, arena: *mut PyArena, ) -> *mut PyCodeObject; #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyAST_CompileObject( _mod: *mut _mod, filename: *mut PyObject, flags: *mut PyCompilerFlags, optimize: c_int, arena: *mut PyArena, ) -> *mut PyCodeObject; #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyFuture_FromAST(_mod: *mut _mod, filename: *const c_char) -> *mut PyFutureFeatures; #[cfg(not(any(PyPy, Py_3_10)))] pub fn PyFuture_FromASTObject( _mod: *mut _mod, filename: *mut PyObject, ) -> *mut PyFutureFeatures; // skipped non-limited _Py_Mangle // skipped non-limited PY_INVALID_STACK_EFFECT pub fn PyCompile_OpcodeStackEffect(opcode: c_int, oparg: c_int) -> c_int; #[cfg(Py_3_8)] pub fn PyCompile_OpcodeStackEffectWithJump(opcode: c_int, oparg: c_int, jump: c_int) -> c_int; // skipped non-limited _PyASTOptimizeState // skipped non-limited _PyAST_Optimize } pyo3-ffi/src/cpython/funcobject.rs0000644000175000017500000000701714661133735020145 0ustar jamespagejamespageuse std::os::raw::c_int; #[cfg(not(all(PyPy, not(Py_3_8))))] use std::ptr::addr_of_mut; use crate::PyObject; #[cfg(all(not(any(PyPy, GraalPy)), not(Py_3_10)))] #[repr(C)] pub struct PyFunctionObject { pub ob_base: PyObject, pub func_code: *mut PyObject, pub func_globals: *mut PyObject, pub func_defaults: *mut PyObject, pub func_kwdefaults: *mut PyObject, pub func_closure: *mut PyObject, pub func_doc: *mut PyObject, pub func_name: *mut PyObject, pub func_dict: *mut PyObject, pub func_weakreflist: *mut PyObject, pub func_module: *mut PyObject, pub func_annotations: *mut PyObject, pub func_qualname: *mut PyObject, #[cfg(Py_3_8)] pub vectorcall: Option, } #[cfg(all(not(any(PyPy, GraalPy)), Py_3_10))] #[repr(C)] pub struct PyFunctionObject { pub ob_base: PyObject, pub func_globals: *mut PyObject, pub func_builtins: *mut PyObject, pub func_name: *mut PyObject, pub func_qualname: *mut PyObject, pub func_code: *mut PyObject, pub func_defaults: *mut PyObject, pub func_kwdefaults: *mut PyObject, pub func_closure: *mut PyObject, pub func_doc: *mut PyObject, pub func_dict: *mut PyObject, pub func_weakreflist: *mut PyObject, pub func_module: *mut PyObject, pub func_annotations: *mut PyObject, #[cfg(Py_3_12)] pub func_typeparams: *mut PyObject, pub vectorcall: Option, #[cfg(Py_3_11)] pub func_version: u32, } #[cfg(PyPy)] #[repr(C)] pub struct PyFunctionObject { pub ob_base: PyObject, pub func_name: *mut PyObject, } #[cfg(GraalPy)] pub struct PyFunctionObject { pub ob_base: PyObject, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(all(PyPy, not(Py_3_8))))] #[cfg_attr(PyPy, link_name = "PyPyFunction_Type")] pub static mut PyFunction_Type: crate::PyTypeObject; } #[cfg(not(all(PyPy, not(Py_3_8))))] #[inline] pub unsafe fn PyFunction_Check(op: *mut PyObject) -> c_int { (crate::Py_TYPE(op) == addr_of_mut!(PyFunction_Type)) as c_int } extern "C" { pub fn PyFunction_New(code: *mut PyObject, globals: *mut PyObject) -> *mut PyObject; pub fn PyFunction_NewWithQualName( code: *mut PyObject, globals: *mut PyObject, qualname: *mut PyObject, ) -> *mut PyObject; pub fn PyFunction_GetCode(op: *mut PyObject) -> *mut PyObject; pub fn PyFunction_GetGlobals(op: *mut PyObject) -> *mut PyObject; pub fn PyFunction_GetModule(op: *mut PyObject) -> *mut PyObject; pub fn PyFunction_GetDefaults(op: *mut PyObject) -> *mut PyObject; pub fn PyFunction_SetDefaults(op: *mut PyObject, defaults: *mut PyObject) -> c_int; pub fn PyFunction_GetKwDefaults(op: *mut PyObject) -> *mut PyObject; pub fn PyFunction_SetKwDefaults(op: *mut PyObject, defaults: *mut PyObject) -> c_int; pub fn PyFunction_GetClosure(op: *mut PyObject) -> *mut PyObject; pub fn PyFunction_SetClosure(op: *mut PyObject, closure: *mut PyObject) -> c_int; pub fn PyFunction_GetAnnotations(op: *mut PyObject) -> *mut PyObject; pub fn PyFunction_SetAnnotations(op: *mut PyObject, annotations: *mut PyObject) -> c_int; } // skipped _PyFunction_Vectorcall // skipped PyFunction_GET_CODE // skipped PyFunction_GET_GLOBALS // skipped PyFunction_GET_MODULE // skipped PyFunction_GET_DEFAULTS // skipped PyFunction_GET_KW_DEFAULTS // skipped PyFunction_GET_CLOSURE // skipped PyFunction_GET_ANNOTATIONS // skipped PyClassMethod_Type // skipped PyStaticMethod_Type // skipped PyClassMethod_New // skipped PyStaticMethod_New pyo3-ffi/src/cpython/listobject.rs0000644000175000017500000000200014661133735020150 0ustar jamespagejamespageuse crate::object::*; #[cfg(not(PyPy))] use crate::pyport::Py_ssize_t; #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyListObject { pub ob_base: PyVarObject, pub ob_item: *mut *mut PyObject, pub allocated: Py_ssize_t, } #[cfg(any(PyPy, GraalPy))] pub struct PyListObject { pub ob_base: PyObject, } // skipped _PyList_Extend // skipped _PyList_DebugMallocStats // skipped _PyList_CAST (used inline below) /// Macro, trading safety for speed #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyList_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { *(*(op as *mut PyListObject)).ob_item.offset(i) } /// Macro, *only* to be used to fill in brand new lists #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyList_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { *(*(op as *mut PyListObject)).ob_item.offset(i) = v; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyList_GET_SIZE(op: *mut PyObject) -> Py_ssize_t { Py_SIZE(op) } pyo3-ffi/src/cpython/object.rs0000644000175000017500000003322314661133735017267 0ustar jamespagejamespage#[cfg(Py_3_8)] use crate::vectorcallfunc; #[cfg(Py_3_11)] use crate::PyModuleDef; use crate::{object, PyGetSetDef, PyMemberDef, PyMethodDef, PyObject, Py_ssize_t}; use std::mem; use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void}; // skipped _Py_NewReference // skipped _Py_ForgetReference // skipped _Py_GetRefTotal // skipped _Py_Identifier // skipped _Py_static_string_init // skipped _Py_static_string // skipped _Py_IDENTIFIER #[cfg(not(Py_3_11))] // moved to src/buffer.rs from Python mod bufferinfo { use crate::Py_ssize_t; use std::os::raw::{c_char, c_int, c_void}; use std::ptr; #[repr(C)] #[derive(Copy, Clone)] pub struct Py_buffer { pub buf: *mut c_void, /// Owned reference pub obj: *mut crate::PyObject, pub len: Py_ssize_t, pub itemsize: Py_ssize_t, pub readonly: c_int, pub ndim: c_int, pub format: *mut c_char, pub shape: *mut Py_ssize_t, pub strides: *mut Py_ssize_t, pub suboffsets: *mut Py_ssize_t, pub internal: *mut c_void, #[cfg(PyPy)] pub flags: c_int, #[cfg(PyPy)] pub _strides: [Py_ssize_t; PyBUF_MAX_NDIM as usize], #[cfg(PyPy)] pub _shape: [Py_ssize_t; PyBUF_MAX_NDIM as usize], } impl Py_buffer { #[allow(clippy::new_without_default)] pub const fn new() -> Self { Py_buffer { buf: ptr::null_mut(), obj: ptr::null_mut(), len: 0, itemsize: 0, readonly: 0, ndim: 0, format: ptr::null_mut(), shape: ptr::null_mut(), strides: ptr::null_mut(), suboffsets: ptr::null_mut(), internal: ptr::null_mut(), #[cfg(PyPy)] flags: 0, #[cfg(PyPy)] _strides: [0; PyBUF_MAX_NDIM as usize], #[cfg(PyPy)] _shape: [0; PyBUF_MAX_NDIM as usize], } } } pub type getbufferproc = unsafe extern "C" fn( arg1: *mut crate::PyObject, arg2: *mut Py_buffer, arg3: c_int, ) -> c_int; pub type releasebufferproc = unsafe extern "C" fn(arg1: *mut crate::PyObject, arg2: *mut Py_buffer); /// Maximum number of dimensions pub const PyBUF_MAX_NDIM: c_int = if cfg!(PyPy) { 36 } else { 64 }; /* Flags for getting buffers */ pub const PyBUF_SIMPLE: c_int = 0; pub const PyBUF_WRITABLE: c_int = 0x0001; /* we used to include an E, backwards compatible alias */ pub const PyBUF_WRITEABLE: c_int = PyBUF_WRITABLE; pub const PyBUF_FORMAT: c_int = 0x0004; pub const PyBUF_ND: c_int = 0x0008; pub const PyBUF_STRIDES: c_int = 0x0010 | PyBUF_ND; pub const PyBUF_C_CONTIGUOUS: c_int = 0x0020 | PyBUF_STRIDES; pub const PyBUF_F_CONTIGUOUS: c_int = 0x0040 | PyBUF_STRIDES; pub const PyBUF_ANY_CONTIGUOUS: c_int = 0x0080 | PyBUF_STRIDES; pub const PyBUF_INDIRECT: c_int = 0x0100 | PyBUF_STRIDES; pub const PyBUF_CONTIG: c_int = PyBUF_ND | PyBUF_WRITABLE; pub const PyBUF_CONTIG_RO: c_int = PyBUF_ND; pub const PyBUF_STRIDED: c_int = PyBUF_STRIDES | PyBUF_WRITABLE; pub const PyBUF_STRIDED_RO: c_int = PyBUF_STRIDES; pub const PyBUF_RECORDS: c_int = PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT; pub const PyBUF_RECORDS_RO: c_int = PyBUF_STRIDES | PyBUF_FORMAT; pub const PyBUF_FULL: c_int = PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT; pub const PyBUF_FULL_RO: c_int = PyBUF_INDIRECT | PyBUF_FORMAT; pub const PyBUF_READ: c_int = 0x100; pub const PyBUF_WRITE: c_int = 0x200; } #[cfg(not(Py_3_11))] pub use self::bufferinfo::*; #[repr(C)] #[derive(Copy, Clone)] pub struct PyNumberMethods { pub nb_add: Option, pub nb_subtract: Option, pub nb_multiply: Option, pub nb_remainder: Option, pub nb_divmod: Option, pub nb_power: Option, pub nb_negative: Option, pub nb_positive: Option, pub nb_absolute: Option, pub nb_bool: Option, pub nb_invert: Option, pub nb_lshift: Option, pub nb_rshift: Option, pub nb_and: Option, pub nb_xor: Option, pub nb_or: Option, pub nb_int: Option, pub nb_reserved: *mut c_void, pub nb_float: Option, pub nb_inplace_add: Option, pub nb_inplace_subtract: Option, pub nb_inplace_multiply: Option, pub nb_inplace_remainder: Option, pub nb_inplace_power: Option, pub nb_inplace_lshift: Option, pub nb_inplace_rshift: Option, pub nb_inplace_and: Option, pub nb_inplace_xor: Option, pub nb_inplace_or: Option, pub nb_floor_divide: Option, pub nb_true_divide: Option, pub nb_inplace_floor_divide: Option, pub nb_inplace_true_divide: Option, pub nb_index: Option, pub nb_matrix_multiply: Option, pub nb_inplace_matrix_multiply: Option, } #[repr(C)] #[derive(Clone)] pub struct PySequenceMethods { pub sq_length: Option, pub sq_concat: Option, pub sq_repeat: Option, pub sq_item: Option, pub was_sq_slice: *mut c_void, pub sq_ass_item: Option, pub was_sq_ass_slice: *mut c_void, pub sq_contains: Option, pub sq_inplace_concat: Option, pub sq_inplace_repeat: Option, } #[repr(C)] #[derive(Clone, Default)] pub struct PyMappingMethods { pub mp_length: Option, pub mp_subscript: Option, pub mp_ass_subscript: Option, } #[cfg(Py_3_10)] pub type sendfunc = unsafe extern "C" fn( iter: *mut PyObject, value: *mut PyObject, result: *mut *mut PyObject, ) -> object::PySendResult; #[repr(C)] #[derive(Clone, Default)] pub struct PyAsyncMethods { pub am_await: Option, pub am_aiter: Option, pub am_anext: Option, #[cfg(Py_3_10)] pub am_send: Option, } #[repr(C)] #[derive(Clone, Default)] pub struct PyBufferProcs { pub bf_getbuffer: Option, pub bf_releasebuffer: Option, } pub type printfunc = unsafe extern "C" fn(arg1: *mut PyObject, arg2: *mut ::libc::FILE, arg3: c_int) -> c_int; #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct PyTypeObject { #[cfg(all(PyPy, not(Py_3_9)))] pub ob_refcnt: Py_ssize_t, #[cfg(all(PyPy, not(Py_3_9)))] pub ob_pypy_link: Py_ssize_t, #[cfg(all(PyPy, not(Py_3_9)))] pub ob_type: *mut PyTypeObject, #[cfg(all(PyPy, not(Py_3_9)))] pub ob_size: Py_ssize_t, #[cfg(not(all(PyPy, not(Py_3_9))))] pub ob_base: object::PyVarObject, #[cfg(GraalPy)] pub ob_size: Py_ssize_t, pub tp_name: *const c_char, pub tp_basicsize: Py_ssize_t, pub tp_itemsize: Py_ssize_t, pub tp_dealloc: Option, #[cfg(not(Py_3_8))] pub tp_print: Option, #[cfg(Py_3_8)] pub tp_vectorcall_offset: Py_ssize_t, pub tp_getattr: Option, pub tp_setattr: Option, pub tp_as_async: *mut PyAsyncMethods, pub tp_repr: Option, pub tp_as_number: *mut PyNumberMethods, pub tp_as_sequence: *mut PySequenceMethods, pub tp_as_mapping: *mut PyMappingMethods, pub tp_hash: Option, pub tp_call: Option, pub tp_str: Option, pub tp_getattro: Option, pub tp_setattro: Option, pub tp_as_buffer: *mut PyBufferProcs, pub tp_flags: c_ulong, pub tp_doc: *const c_char, pub tp_traverse: Option, pub tp_clear: Option, pub tp_richcompare: Option, pub tp_weaklistoffset: Py_ssize_t, pub tp_iter: Option, pub tp_iternext: Option, pub tp_methods: *mut PyMethodDef, pub tp_members: *mut PyMemberDef, pub tp_getset: *mut PyGetSetDef, pub tp_base: *mut PyTypeObject, pub tp_dict: *mut object::PyObject, pub tp_descr_get: Option, pub tp_descr_set: Option, pub tp_dictoffset: Py_ssize_t, pub tp_init: Option, pub tp_alloc: Option, pub tp_new: Option, pub tp_free: Option, pub tp_is_gc: Option, pub tp_bases: *mut object::PyObject, pub tp_mro: *mut object::PyObject, pub tp_cache: *mut object::PyObject, pub tp_subclasses: *mut object::PyObject, pub tp_weaklist: *mut object::PyObject, pub tp_del: Option, pub tp_version_tag: c_uint, pub tp_finalize: Option, #[cfg(Py_3_8)] pub tp_vectorcall: Option, #[cfg(Py_3_12)] pub tp_watched: c_char, #[cfg(any(all(PyPy, Py_3_8, not(Py_3_10)), all(not(PyPy), Py_3_8, not(Py_3_9))))] pub tp_print: Option, #[cfg(all(PyPy, not(Py_3_10)))] pub tp_pypy_flags: std::os::raw::c_long, #[cfg(py_sys_config = "COUNT_ALLOCS")] pub tp_allocs: Py_ssize_t, #[cfg(py_sys_config = "COUNT_ALLOCS")] pub tp_frees: Py_ssize_t, #[cfg(py_sys_config = "COUNT_ALLOCS")] pub tp_maxalloc: Py_ssize_t, #[cfg(py_sys_config = "COUNT_ALLOCS")] pub tp_prev: *mut PyTypeObject, #[cfg(py_sys_config = "COUNT_ALLOCS")] pub tp_next: *mut PyTypeObject, } #[cfg(Py_3_11)] #[repr(C)] #[derive(Clone)] pub struct _specialization_cache { pub getitem: *mut PyObject, #[cfg(Py_3_12)] pub getitem_version: u32, #[cfg(Py_3_13)] pub init: *mut PyObject, } #[repr(C)] #[derive(Clone)] pub struct PyHeapTypeObject { pub ht_type: PyTypeObject, pub as_async: PyAsyncMethods, pub as_number: PyNumberMethods, pub as_mapping: PyMappingMethods, pub as_sequence: PySequenceMethods, pub as_buffer: PyBufferProcs, pub ht_name: *mut object::PyObject, pub ht_slots: *mut object::PyObject, pub ht_qualname: *mut object::PyObject, #[cfg(not(PyPy))] pub ht_cached_keys: *mut c_void, #[cfg(Py_3_9)] pub ht_module: *mut object::PyObject, #[cfg(Py_3_11)] pub _ht_tpname: *mut c_char, #[cfg(Py_3_11)] pub _spec_cache: _specialization_cache, } impl Default for PyHeapTypeObject { #[inline] fn default() -> Self { unsafe { mem::zeroed() } } } #[inline] pub unsafe fn PyHeapType_GET_MEMBERS(etype: *mut PyHeapTypeObject) -> *mut PyMemberDef { let py_type = object::Py_TYPE(etype as *mut object::PyObject); let ptr = etype.offset((*py_type).tp_basicsize); ptr as *mut PyMemberDef } // skipped _PyType_Name // skipped _PyType_Lookup // skipped _PyType_LookupId // skipped _PyObject_LookupSpecial // skipped _PyType_CalculateMetaclass // skipped _PyType_GetDocFromInternalDoc // skipped _PyType_GetTextSignatureFromInternalDoc extern "C" { #[cfg(Py_3_11)] #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleByDef")] pub fn PyType_GetModuleByDef(ty: *mut PyTypeObject, def: *mut PyModuleDef) -> *mut PyObject; #[cfg(Py_3_12)] pub fn PyType_GetDict(o: *mut PyTypeObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_Print")] pub fn PyObject_Print(o: *mut PyObject, fp: *mut ::libc::FILE, flags: c_int) -> c_int; // skipped _Py_BreakPoint // skipped _PyObject_Dump // skipped _PyObject_IsFreed // skipped _PyObject_IsAbstract // skipped _PyObject_GetAttrId // skipped _PyObject_SetAttrId // skipped _PyObject_LookupAttr // skipped _PyObject_LookupAttrId // skipped _PyObject_GetMethod #[cfg(not(PyPy))] pub fn _PyObject_GetDictPtr(obj: *mut PyObject) -> *mut *mut PyObject; #[cfg(not(PyPy))] pub fn _PyObject_NextNotImplemented(arg1: *mut PyObject) -> *mut PyObject; pub fn PyObject_CallFinalizer(arg1: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyObject_CallFinalizerFromDealloc")] pub fn PyObject_CallFinalizerFromDealloc(arg1: *mut PyObject) -> c_int; // skipped _PyObject_GenericGetAttrWithDict // skipped _PyObject_GenericSetAttrWithDict // skipped _PyObject_FunctionStr } // skipped Py_SETREF // skipped Py_XSETREF #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut _PyNone_Type: PyTypeObject; pub static mut _PyNotImplemented_Type: PyTypeObject; } // skipped _Py_SwappedOp // skipped _PyDebugAllocatorStats // skipped _PyObject_DebugTypeStats // skipped _PyObject_ASSERT_FROM // skipped _PyObject_ASSERT_WITH_MSG // skipped _PyObject_ASSERT // skipped _PyObject_ASSERT_FAILED_MSG // skipped _PyObject_AssertFailed // skipped _PyObject_CheckConsistency // skipped _PyTrash_thread_deposit_object // skipped _PyTrash_thread_destroy_chain // skipped _PyTrash_begin // skipped _PyTrash_end // skipped _PyTrash_cond // skipped PyTrash_UNWIND_LEVEL // skipped Py_TRASHCAN_BEGIN_CONDITION // skipped Py_TRASHCAN_END // skipped Py_TRASHCAN_BEGIN // skipped Py_TRASHCAN_SAFE_BEGIN // skipped Py_TRASHCAN_SAFE_END pyo3-ffi/src/cpython/objimpl.rs0000644000175000017500000000352714661133735017461 0ustar jamespagejamespageuse libc::size_t; use std::os::raw::c_int; #[cfg(not(any(PyPy, GraalPy)))] use std::os::raw::c_void; use crate::object::*; // skipped _PyObject_SIZE // skipped _PyObject_VAR_SIZE #[cfg(not(Py_3_11))] extern "C" { pub fn _Py_GetAllocatedBlocks() -> crate::Py_ssize_t; } #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Copy, Clone)] pub struct PyObjectArenaAllocator { pub ctx: *mut c_void, pub alloc: Option *mut c_void>, pub free: Option, } #[cfg(not(any(PyPy, GraalPy)))] impl Default for PyObjectArenaAllocator { #[inline] fn default() -> Self { unsafe { std::mem::zeroed() } } } extern "C" { #[cfg(not(any(PyPy, GraalPy)))] pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator); #[cfg(not(any(PyPy, GraalPy)))] pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator); #[cfg(Py_3_9)] pub fn PyObject_IS_GC(o: *mut PyObject) -> c_int; } #[inline] #[cfg(not(Py_3_9))] pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int { (crate::PyType_IS_GC(Py_TYPE(o)) != 0 && match (*Py_TYPE(o)).tp_is_gc { Some(tp_is_gc) => tp_is_gc(o) != 0, None => true, }) as c_int } #[cfg(not(Py_3_11))] extern "C" { pub fn _PyObject_GC_Malloc(size: size_t) -> *mut PyObject; pub fn _PyObject_GC_Calloc(size: size_t) -> *mut PyObject; } #[inline] pub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int { ((*t).tp_weaklistoffset > 0) as c_int } #[inline] pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject { let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset; o.offset(weaklistoffset) as *mut *mut PyObject } // skipped PyUnstable_Object_GC_NewWithExtraData pyo3-ffi/src/abstract_.rs0000644000175000017500000003601314661133735016277 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; use std::ptr; extern "C" { #[cfg(PyPy)] #[link_name = "PyPyObject_DelAttrString"] pub fn PyObject_DelAttrString(o: *mut PyObject, attr_name: *const c_char) -> c_int; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyObject_DelAttrString(o: *mut PyObject, attr_name: *const c_char) -> c_int { PyObject_SetAttrString(o, attr_name, ptr::null_mut()) } #[inline] pub unsafe fn PyObject_DelAttr(o: *mut PyObject, attr_name: *mut PyObject) -> c_int { PyObject_SetAttr(o, attr_name, ptr::null_mut()) } extern "C" { #[cfg(all( not(PyPy), not(GraalPy), any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // Added to python in 3.9 but to limited API in 3.10 ))] #[cfg_attr(PyPy, link_name = "PyPyObject_CallNoArgs")] pub fn PyObject_CallNoArgs(func: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_Call")] pub fn PyObject_Call( callable_object: *mut PyObject, args: *mut PyObject, kw: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_CallObject")] pub fn PyObject_CallObject( callable_object: *mut PyObject, args: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_CallFunction")] pub fn PyObject_CallFunction( callable_object: *mut PyObject, format: *const c_char, ... ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_CallMethod")] pub fn PyObject_CallMethod( o: *mut PyObject, method: *const c_char, format: *const c_char, ... ) -> *mut PyObject; #[cfg(not(Py_3_13))] #[cfg_attr(PyPy, link_name = "_PyPyObject_CallFunction_SizeT")] pub fn _PyObject_CallFunction_SizeT( callable_object: *mut PyObject, format: *const c_char, ... ) -> *mut PyObject; #[cfg(not(Py_3_13))] #[cfg_attr(PyPy, link_name = "_PyPyObject_CallMethod_SizeT")] pub fn _PyObject_CallMethod_SizeT( o: *mut PyObject, method: *const c_char, format: *const c_char, ... ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_CallFunctionObjArgs")] pub fn PyObject_CallFunctionObjArgs(callable: *mut PyObject, ...) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_CallMethodObjArgs")] pub fn PyObject_CallMethodObjArgs( o: *mut PyObject, method: *mut PyObject, ... ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_Type")] pub fn PyObject_Type(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_Size")] pub fn PyObject_Size(o: *mut PyObject) -> Py_ssize_t; } #[inline] pub unsafe fn PyObject_Length(o: *mut PyObject) -> Py_ssize_t { PyObject_Size(o) } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyObject_GetItem")] pub fn PyObject_GetItem(o: *mut PyObject, key: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_SetItem")] pub fn PyObject_SetItem(o: *mut PyObject, key: *mut PyObject, v: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_DelItemString")] pub fn PyObject_DelItemString(o: *mut PyObject, key: *const c_char) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_DelItem")] pub fn PyObject_DelItem(o: *mut PyObject, key: *mut PyObject) -> c_int; } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyObject_Format")] pub fn PyObject_Format(obj: *mut PyObject, format_spec: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_GetIter")] pub fn PyObject_GetIter(arg1: *mut PyObject) -> *mut PyObject; } // Before 3.8 PyIter_Check was defined in CPython as a macro, // but the implementation of that in PyO3 did not work, see // https://github.com/PyO3/pyo3/pull/2914 // // This is a slow implementation which should function equivalently. #[cfg(not(any(Py_3_8, PyPy)))] #[inline] pub unsafe fn PyIter_Check(o: *mut PyObject) -> c_int { crate::PyObject_HasAttrString(crate::Py_TYPE(o).cast(), c_str!("__next__").as_ptr()) } extern "C" { #[cfg(any(Py_3_8, PyPy))] #[cfg_attr(PyPy, link_name = "PyPyIter_Check")] pub fn PyIter_Check(obj: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyIter_Next")] pub fn PyIter_Next(arg1: *mut PyObject) -> *mut PyObject; #[cfg(all(not(PyPy), Py_3_10))] #[cfg_attr(PyPy, link_name = "PyPyIter_Send")] pub fn PyIter_Send(iter: *mut PyObject, arg: *mut PyObject, presult: *mut *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyNumber_Check")] pub fn PyNumber_Check(o: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyNumber_Add")] pub fn PyNumber_Add(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Subtract")] pub fn PyNumber_Subtract(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Multiply")] pub fn PyNumber_Multiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_MatrixMultiply")] pub fn PyNumber_MatrixMultiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_FloorDivide")] pub fn PyNumber_FloorDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_TrueDivide")] pub fn PyNumber_TrueDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Remainder")] pub fn PyNumber_Remainder(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Divmod")] pub fn PyNumber_Divmod(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Power")] pub fn PyNumber_Power(o1: *mut PyObject, o2: *mut PyObject, o3: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Negative")] pub fn PyNumber_Negative(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Positive")] pub fn PyNumber_Positive(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Absolute")] pub fn PyNumber_Absolute(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Invert")] pub fn PyNumber_Invert(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Lshift")] pub fn PyNumber_Lshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Rshift")] pub fn PyNumber_Rshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_And")] pub fn PyNumber_And(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Xor")] pub fn PyNumber_Xor(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Or")] pub fn PyNumber_Or(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; } // Defined as this macro in Python limited API, but relies on // non-limited PyTypeObject. Don't expose this since it cannot be used. #[cfg(not(any(Py_LIMITED_API, PyPy)))] #[inline] pub unsafe fn PyIndex_Check(o: *mut PyObject) -> c_int { let tp_as_number = (*Py_TYPE(o)).tp_as_number; (!tp_as_number.is_null() && (*tp_as_number).nb_index.is_some()) as c_int } extern "C" { #[cfg(any(all(Py_3_8, Py_LIMITED_API), PyPy))] #[link_name = "PyPyIndex_Check"] pub fn PyIndex_Check(o: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyNumber_Index")] pub fn PyNumber_Index(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_AsSsize_t")] pub fn PyNumber_AsSsize_t(o: *mut PyObject, exc: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyNumber_Long")] pub fn PyNumber_Long(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_Float")] pub fn PyNumber_Float(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceAdd")] pub fn PyNumber_InPlaceAdd(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceSubtract")] pub fn PyNumber_InPlaceSubtract(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceMultiply")] pub fn PyNumber_InPlaceMultiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceMatrixMultiply")] pub fn PyNumber_InPlaceMatrixMultiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceFloorDivide")] pub fn PyNumber_InPlaceFloorDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceTrueDivide")] pub fn PyNumber_InPlaceTrueDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceRemainder")] pub fn PyNumber_InPlaceRemainder(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlacePower")] pub fn PyNumber_InPlacePower( o1: *mut PyObject, o2: *mut PyObject, o3: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceLshift")] pub fn PyNumber_InPlaceLshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceRshift")] pub fn PyNumber_InPlaceRshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceAnd")] pub fn PyNumber_InPlaceAnd(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceXor")] pub fn PyNumber_InPlaceXor(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyNumber_InPlaceOr")] pub fn PyNumber_InPlaceOr(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; pub fn PyNumber_ToBase(n: *mut PyObject, base: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_Check")] pub fn PySequence_Check(o: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySequence_Size")] pub fn PySequence_Size(o: *mut PyObject) -> Py_ssize_t; #[cfg(PyPy)] #[link_name = "PyPySequence_Length"] pub fn PySequence_Length(o: *mut PyObject) -> Py_ssize_t; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PySequence_Length(o: *mut PyObject) -> Py_ssize_t { PySequence_Size(o) } extern "C" { #[cfg_attr(PyPy, link_name = "PyPySequence_Concat")] pub fn PySequence_Concat(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_Repeat")] pub fn PySequence_Repeat(o: *mut PyObject, count: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_GetItem")] pub fn PySequence_GetItem(o: *mut PyObject, i: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_GetSlice")] pub fn PySequence_GetSlice(o: *mut PyObject, i1: Py_ssize_t, i2: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_SetItem")] pub fn PySequence_SetItem(o: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySequence_DelItem")] pub fn PySequence_DelItem(o: *mut PyObject, i: Py_ssize_t) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySequence_SetSlice")] pub fn PySequence_SetSlice( o: *mut PyObject, i1: Py_ssize_t, i2: Py_ssize_t, v: *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySequence_DelSlice")] pub fn PySequence_DelSlice(o: *mut PyObject, i1: Py_ssize_t, i2: Py_ssize_t) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySequence_Tuple")] pub fn PySequence_Tuple(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_List")] pub fn PySequence_List(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_Fast")] pub fn PySequence_Fast(o: *mut PyObject, m: *const c_char) -> *mut PyObject; // skipped PySequence_Fast_GET_SIZE // skipped PySequence_Fast_GET_ITEM // skipped PySequence_Fast_GET_ITEMS pub fn PySequence_Count(o: *mut PyObject, value: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPySequence_Contains")] pub fn PySequence_Contains(seq: *mut PyObject, ob: *mut PyObject) -> c_int; } #[inline] pub unsafe fn PySequence_In(o: *mut PyObject, value: *mut PyObject) -> c_int { PySequence_Contains(o, value) } extern "C" { #[cfg_attr(PyPy, link_name = "PyPySequence_Index")] pub fn PySequence_Index(o: *mut PyObject, value: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPySequence_InPlaceConcat")] pub fn PySequence_InPlaceConcat(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySequence_InPlaceRepeat")] pub fn PySequence_InPlaceRepeat(o: *mut PyObject, count: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyMapping_Check")] pub fn PyMapping_Check(o: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyMapping_Size")] pub fn PyMapping_Size(o: *mut PyObject) -> Py_ssize_t; #[cfg(PyPy)] #[link_name = "PyPyMapping_Length"] pub fn PyMapping_Length(o: *mut PyObject) -> Py_ssize_t; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyMapping_Length(o: *mut PyObject) -> Py_ssize_t { PyMapping_Size(o) } #[inline] pub unsafe fn PyMapping_DelItemString(o: *mut PyObject, key: *mut c_char) -> c_int { PyObject_DelItemString(o, key) } #[inline] pub unsafe fn PyMapping_DelItem(o: *mut PyObject, key: *mut PyObject) -> c_int { PyObject_DelItem(o, key) } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyMapping_HasKeyString")] pub fn PyMapping_HasKeyString(o: *mut PyObject, key: *const c_char) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyMapping_HasKey")] pub fn PyMapping_HasKey(o: *mut PyObject, key: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyMapping_Keys")] pub fn PyMapping_Keys(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyMapping_Values")] pub fn PyMapping_Values(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyMapping_Items")] pub fn PyMapping_Items(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyMapping_GetItemString")] pub fn PyMapping_GetItemString(o: *mut PyObject, key: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyMapping_SetItemString")] pub fn PyMapping_SetItemString( o: *mut PyObject, key: *const c_char, value: *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_IsInstance")] pub fn PyObject_IsInstance(object: *mut PyObject, typeorclass: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_IsSubclass")] pub fn PyObject_IsSubclass(object: *mut PyObject, typeorclass: *mut PyObject) -> c_int; } pyo3-ffi/src/moduleobject.rs0000644000175000017500000000674414661133735017021 0ustar jamespagejamespageuse crate::methodobject::PyMethodDef; use crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int, c_void}; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyModule_Type")] pub static mut PyModule_Type: PyTypeObject; } #[inline] pub unsafe fn PyModule_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyModule_Type)) } #[inline] pub unsafe fn PyModule_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyModule_Type)) as c_int } extern "C" { pub fn PyModule_NewObject(name: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyModule_New")] pub fn PyModule_New(name: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyModule_GetDict")] pub fn PyModule_GetDict(arg1: *mut PyObject) -> *mut PyObject; #[cfg(not(PyPy))] pub fn PyModule_GetNameObject(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyModule_GetName")] pub fn PyModule_GetName(arg1: *mut PyObject) -> *const c_char; #[cfg(not(all(windows, PyPy)))] #[deprecated(note = "Python 3.2")] pub fn PyModule_GetFilename(arg1: *mut PyObject) -> *const c_char; #[cfg(not(PyPy))] pub fn PyModule_GetFilenameObject(arg1: *mut PyObject) -> *mut PyObject; // skipped non-limited _PyModule_Clear // skipped non-limited _PyModule_ClearDict // skipped non-limited _PyModuleSpec_IsInitializing #[cfg_attr(PyPy, link_name = "PyPyModule_GetDef")] pub fn PyModule_GetDef(arg1: *mut PyObject) -> *mut PyModuleDef; #[cfg_attr(PyPy, link_name = "PyPyModule_GetState")] pub fn PyModule_GetState(arg1: *mut PyObject) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyModuleDef_Init")] pub fn PyModuleDef_Init(arg1: *mut PyModuleDef) -> *mut PyObject; } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyModuleDef_Type: PyTypeObject; } #[repr(C)] #[derive(Copy, Clone)] pub struct PyModuleDef_Base { pub ob_base: PyObject, pub m_init: Option *mut PyObject>, pub m_index: Py_ssize_t, pub m_copy: *mut PyObject, } pub const PyModuleDef_HEAD_INIT: PyModuleDef_Base = PyModuleDef_Base { ob_base: PyObject_HEAD_INIT, m_init: None, m_index: 0, m_copy: std::ptr::null_mut(), }; #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq)] pub struct PyModuleDef_Slot { pub slot: c_int, pub value: *mut c_void, } impl Default for PyModuleDef_Slot { fn default() -> PyModuleDef_Slot { PyModuleDef_Slot { slot: 0, value: std::ptr::null_mut(), } } } pub const Py_mod_create: c_int = 1; pub const Py_mod_exec: c_int = 2; #[cfg(Py_3_12)] pub const Py_mod_multiple_interpreters: c_int = 3; #[cfg(Py_3_12)] pub const Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED: *mut c_void = 0 as *mut c_void; #[cfg(Py_3_12)] pub const Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED: *mut c_void = 1 as *mut c_void; #[cfg(Py_3_12)] pub const Py_MOD_PER_INTERPRETER_GIL_SUPPORTED: *mut c_void = 2 as *mut c_void; // skipped non-limited _Py_mod_LAST_SLOT #[repr(C)] #[derive(Copy, Clone)] pub struct PyModuleDef { pub m_base: PyModuleDef_Base, pub m_name: *const c_char, pub m_doc: *const c_char, pub m_size: Py_ssize_t, pub m_methods: *mut PyMethodDef, pub m_slots: *mut PyModuleDef_Slot, pub m_traverse: Option, pub m_clear: Option, pub m_free: Option, } pyo3-ffi/src/datetime.rs0000644000175000017500000005660714661133735016144 0ustar jamespagejamespage//! FFI bindings to the functions and structs defined in `datetime.h` //! //! This is the unsafe thin wrapper around the [CPython C API](https://docs.python.org/3/c-api/datetime.html), //! and covers the various date and time related objects in the Python `datetime` //! standard library module. //! //! A note regarding PyPy (cpyext) support: //! //! Support for `PyDateTime_CAPI` is limited as of PyPy 7.0.0. //! `DateTime_FromTimestamp` and `Date_FromTimestamp` are currently not supported. #[cfg(GraalPy)] use crate::{PyLong_AsLong, PyLong_Check, PyObject_GetAttrString, Py_DecRef}; use crate::{PyObject, PyObject_TypeCheck, PyTypeObject, Py_TYPE}; use std::cell::UnsafeCell; #[cfg(not(GraalPy))] use std::os::raw::c_char; use std::os::raw::c_int; use std::ptr; #[cfg(not(PyPy))] use {crate::PyCapsule_Import, std::ffi::CString}; #[cfg(not(any(PyPy, GraalPy)))] use {crate::Py_hash_t, std::os::raw::c_uchar}; // Type struct wrappers const _PyDateTime_DATE_DATASIZE: usize = 4; const _PyDateTime_TIME_DATASIZE: usize = 6; const _PyDateTime_DATETIME_DATASIZE: usize = 10; #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.timedelta`. pub struct PyDateTime_Delta { pub ob_base: PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, #[cfg(not(GraalPy))] pub days: c_int, #[cfg(not(GraalPy))] pub seconds: c_int, #[cfg(not(GraalPy))] pub microseconds: c_int, } // skipped non-limited PyDateTime_TZInfo // skipped non-limited _PyDateTime_BaseTZInfo #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.time` without a `tzinfo` member. pub struct _PyDateTime_BaseTime { pub ob_base: PyObject, pub hashcode: Py_hash_t, pub hastzinfo: c_char, pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], } #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.time`. pub struct PyDateTime_Time { pub ob_base: PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, #[cfg(not(GraalPy))] pub hastzinfo: c_char, #[cfg(not(any(PyPy, GraalPy)))] pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], #[cfg(not(any(PyPy, GraalPy)))] pub fold: c_uchar, /// # Safety /// /// Care should be taken when reading this field. If the time does not have a /// tzinfo then CPython may allocate as a `_PyDateTime_BaseTime` without this field. #[cfg(not(GraalPy))] pub tzinfo: *mut PyObject, } #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.date` pub struct PyDateTime_Date { pub ob_base: PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, #[cfg(not(any(PyPy, GraalPy)))] pub hastzinfo: c_char, #[cfg(not(any(PyPy, GraalPy)))] pub data: [c_uchar; _PyDateTime_DATE_DATASIZE], } #[cfg(not(any(PyPy, GraalPy)))] #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.datetime` without a `tzinfo` member. pub struct _PyDateTime_BaseDateTime { pub ob_base: PyObject, pub hashcode: Py_hash_t, pub hastzinfo: c_char, pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], } #[repr(C)] #[derive(Debug, Copy, Clone)] /// Structure representing a `datetime.datetime`. pub struct PyDateTime_DateTime { pub ob_base: PyObject, #[cfg(not(any(PyPy, GraalPy)))] pub hashcode: Py_hash_t, #[cfg(not(GraalPy))] pub hastzinfo: c_char, #[cfg(not(any(PyPy, GraalPy)))] pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], #[cfg(not(any(PyPy, GraalPy)))] pub fold: c_uchar, /// # Safety /// /// Care should be taken when reading this field. If the time does not have a /// tzinfo then CPython may allocate as a `_PyDateTime_BaseDateTime` without this field. #[cfg(not(GraalPy))] pub tzinfo: *mut PyObject, } // skipped non-limited _PyDateTime_HAS_TZINFO // Accessor functions for PyDateTime_Date and PyDateTime_DateTime #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the year component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer greater than 0. pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { // This should work for Date or DateTime let d = *(o as *mut PyDateTime_Date); c_int::from(d.data[0]) << 8 | c_int::from(d.data[1]) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer in the range `[1, 12]`. pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { let d = *(o as *mut PyDateTime_Date); c_int::from(d.data[2]) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[1, 31]`. pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { let d = *(o as *mut PyDateTime_Date); c_int::from(d.data[3]) } // Accessor macros for times #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_HOUR { ($o: expr, $offset:expr) => { c_int::from((*$o).data[$offset + 0]) }; } #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_MINUTE { ($o: expr, $offset:expr) => { c_int::from((*$o).data[$offset + 1]) }; } #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_SECOND { ($o: expr, $offset:expr) => { c_int::from((*$o).data[$offset + 2]) }; } #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_MICROSECOND { ($o: expr, $offset:expr) => { (c_int::from((*$o).data[$offset + 3]) << 16) | (c_int::from((*$o).data[$offset + 4]) << 8) | (c_int::from((*$o).data[$offset + 5])) }; } #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_FOLD { ($o: expr) => { (*$o).fold }; } #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _PyDateTime_GET_TZINFO { ($o: expr) => { if (*$o).hastzinfo != 0 { (*$o).tzinfo } else { $crate::Py_None() } }; } // Accessor functions for DateTime #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the hour component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 23]` pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int { _PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the minute component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int { _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the second component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int { _PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the microsecond component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 999999]` pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the fold component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 1]` pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar { _PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the tzinfo component of a `PyDateTime_DateTime`. /// Returns a pointer to a `PyObject` that should be either NULL or an instance /// of a `datetime.tzinfo` subclass. pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime) } // Accessor functions for Time #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the hour component of a `PyDateTime_Time`. /// Returns a signed integer in the interval `[0, 23]` pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int { _PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the minute component of a `PyDateTime_Time`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int { _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the second component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 59]` pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int { _PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the microsecond component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 999999]` pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int { _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0) } #[cfg(not(any(PyPy, GraalPy)))] #[inline] /// Retrieve the fold component of a `PyDateTime_Time`. /// Returns a signed integer in the interval `[0, 1]` pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar { _PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the tzinfo component of a `PyDateTime_Time`. /// Returns a pointer to a `PyObject` that should be either NULL or an instance /// of a `datetime.tzinfo` subclass. pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time) } // Accessor functions #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _access_field { ($obj:expr, $type: ident, $field:ident) => { (*($obj as *mut $type)).$field }; } // Accessor functions for PyDateTime_Delta #[cfg(not(any(PyPy, GraalPy)))] macro_rules! _access_delta_field { ($obj:expr, $field:ident) => { _access_field!($obj, PyDateTime_Delta, $field) }; } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the days component of a `PyDateTime_Delta`. /// /// Returns a signed integer in the interval [-999999999, 999999999]. /// /// Note: This retrieves a component from the underlying structure, it is *not* /// a representation of the total duration of the structure. pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int { _access_delta_field!(o, days) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the seconds component of a `PyDateTime_Delta`. /// /// Returns a signed integer in the interval [0, 86399]. /// /// Note: This retrieves a component from the underlying structure, it is *not* /// a representation of the total duration of the structure. pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int { _access_delta_field!(o, seconds) } #[inline] #[cfg(not(any(PyPy, GraalPy)))] /// Retrieve the seconds component of a `PyDateTime_Delta`. /// /// Returns a signed integer in the interval [0, 999999]. /// /// Note: This retrieves a component from the underlying structure, it is *not* /// a representation of the total duration of the structure. pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int { _access_delta_field!(o, microseconds) } // Accessor functions for GraalPy. The macros on GraalPy work differently, // but copying them seems suboptimal #[inline] #[cfg(GraalPy)] pub unsafe fn _get_attr(obj: *mut PyObject, field: &std::ffi::CStr) -> c_int { let result = PyObject_GetAttrString(obj, field.as_ptr()); Py_DecRef(result); // the original macros are borrowing if PyLong_Check(result) == 1 { PyLong_AsLong(result) as c_int } else { 0 } } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("year")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("month")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("day")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("hour")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("minute")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("second")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("microsecond")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("fold")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { let res = PyObject_GetAttrString(o, c_str!("tzinfo").as_ptr().cast()); Py_DecRef(res); // the original macros are borrowing res } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("hour")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("minute")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("second")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("microsecond")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("fold")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject { let res = PyObject_GetAttrString(o, c_str!("tzinfo").as_ptr().cast()); Py_DecRef(res); // the original macros are borrowing res } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("days")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("seconds")) } #[inline] #[cfg(GraalPy)] pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int { _get_attr(o, c_str!("microseconds")) } #[cfg(PyPy)] extern "C" { // skipped _PyDateTime_HAS_TZINFO (not in PyPy) #[link_name = "PyPyDateTime_GET_YEAR"] pub fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_GET_MONTH"] pub fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_GET_DAY"] pub fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_DATE_GET_HOUR"] pub fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_DATE_GET_MINUTE"] pub fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_DATE_GET_SECOND"] pub fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_DATE_GET_MICROSECOND"] pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_GET_FOLD"] pub fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int; // skipped PyDateTime_DATE_GET_TZINFO (not in PyPy) #[link_name = "PyPyDateTime_TIME_GET_HOUR"] pub fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_TIME_GET_MINUTE"] pub fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_TIME_GET_SECOND"] pub fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_TIME_GET_MICROSECOND"] pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_TIME_GET_FOLD"] pub fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int; // skipped PyDateTime_TIME_GET_TZINFO (not in PyPy) #[link_name = "PyPyDateTime_DELTA_GET_DAYS"] pub fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_DELTA_GET_SECONDS"] pub fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int; #[link_name = "PyPyDateTime_DELTA_GET_MICROSECONDS"] pub fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int; } #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct PyDateTime_CAPI { pub DateType: *mut PyTypeObject, pub DateTimeType: *mut PyTypeObject, pub TimeType: *mut PyTypeObject, pub DeltaType: *mut PyTypeObject, pub TZInfoType: *mut PyTypeObject, pub TimeZone_UTC: *mut PyObject, pub Date_FromDate: unsafe extern "C" fn( year: c_int, month: c_int, day: c_int, cls: *mut PyTypeObject, ) -> *mut PyObject, pub DateTime_FromDateAndTime: unsafe extern "C" fn( year: c_int, month: c_int, day: c_int, hour: c_int, minute: c_int, second: c_int, microsecond: c_int, tzinfo: *mut PyObject, cls: *mut PyTypeObject, ) -> *mut PyObject, pub Time_FromTime: unsafe extern "C" fn( hour: c_int, minute: c_int, second: c_int, microsecond: c_int, tzinfo: *mut PyObject, cls: *mut PyTypeObject, ) -> *mut PyObject, pub Delta_FromDelta: unsafe extern "C" fn( days: c_int, seconds: c_int, microseconds: c_int, normalize: c_int, cls: *mut PyTypeObject, ) -> *mut PyObject, pub TimeZone_FromTimeZone: unsafe extern "C" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject, pub DateTime_FromTimestamp: unsafe extern "C" fn( cls: *mut PyTypeObject, args: *mut PyObject, kwargs: *mut PyObject, ) -> *mut PyObject, pub Date_FromTimestamp: unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject, pub DateTime_FromDateAndTimeAndFold: unsafe extern "C" fn( year: c_int, month: c_int, day: c_int, hour: c_int, minute: c_int, second: c_int, microsecond: c_int, tzinfo: *mut PyObject, fold: c_int, cls: *mut PyTypeObject, ) -> *mut PyObject, pub Time_FromTimeAndFold: unsafe extern "C" fn( hour: c_int, minute: c_int, second: c_int, microsecond: c_int, tzinfo: *mut PyObject, fold: c_int, cls: *mut PyTypeObject, ) -> *mut PyObject, } // Python already shares this object between threads, so it's no more evil for us to do it too! unsafe impl Sync for PyDateTime_CAPI {} /// Returns a pointer to a `PyDateTime_CAPI` instance /// /// # Note /// This function will return a null pointer until /// `PyDateTime_IMPORT` is called #[inline] pub unsafe fn PyDateTimeAPI() -> *mut PyDateTime_CAPI { *PyDateTimeAPI_impl.0.get() } #[inline] pub unsafe fn PyDateTime_TimeZone_UTC() -> *mut PyObject { (*PyDateTimeAPI()).TimeZone_UTC } /// Populates the `PyDateTimeAPI` object pub unsafe fn PyDateTime_IMPORT() { // PyPy expects the C-API to be initialized via PyDateTime_Import, so trying to use // `PyCapsule_Import` will behave unexpectedly in pypy. #[cfg(PyPy)] let py_datetime_c_api = PyDateTime_Import(); #[cfg(not(PyPy))] let py_datetime_c_api = { // PyDateTime_CAPSULE_NAME is a macro in C let PyDateTime_CAPSULE_NAME = CString::new("datetime.datetime_CAPI").unwrap(); PyCapsule_Import(PyDateTime_CAPSULE_NAME.as_ptr(), 1) as *mut PyDateTime_CAPI }; *PyDateTimeAPI_impl.0.get() = py_datetime_c_api; } // skipped non-limited PyDateTime_TimeZone_UTC /// Type Check macros /// /// These are bindings around the C API typecheck macros, all of them return /// `1` if True and `0` if False. In all type check macros, the argument (`op`) /// must not be `NULL`. #[inline] /// Check if `op` is a `PyDateTimeAPI.DateType` or subtype. pub unsafe fn PyDate_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, (*PyDateTimeAPI()).DateType) as c_int } #[inline] /// Check if `op`'s type is exactly `PyDateTimeAPI.DateType`. pub unsafe fn PyDate_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == (*PyDateTimeAPI()).DateType) as c_int } #[inline] /// Check if `op` is a `PyDateTimeAPI.DateTimeType` or subtype. pub unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, (*PyDateTimeAPI()).DateTimeType) as c_int } #[inline] /// Check if `op`'s type is exactly `PyDateTimeAPI.DateTimeType`. pub unsafe fn PyDateTime_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == (*PyDateTimeAPI()).DateTimeType) as c_int } #[inline] /// Check if `op` is a `PyDateTimeAPI.TimeType` or subtype. pub unsafe fn PyTime_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, (*PyDateTimeAPI()).TimeType) as c_int } #[inline] /// Check if `op`'s type is exactly `PyDateTimeAPI.TimeType`. pub unsafe fn PyTime_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == (*PyDateTimeAPI()).TimeType) as c_int } #[inline] /// Check if `op` is a `PyDateTimeAPI.DetaType` or subtype. pub unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, (*PyDateTimeAPI()).DeltaType) as c_int } #[inline] /// Check if `op`'s type is exactly `PyDateTimeAPI.DeltaType`. pub unsafe fn PyDelta_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == (*PyDateTimeAPI()).DeltaType) as c_int } #[inline] /// Check if `op` is a `PyDateTimeAPI.TZInfoType` or subtype. pub unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, (*PyDateTimeAPI()).TZInfoType) as c_int } #[inline] /// Check if `op`'s type is exactly `PyDateTimeAPI.TZInfoType`. pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == (*PyDateTimeAPI()).TZInfoType) as c_int } // skipped non-limited PyDate_FromDate // skipped non-limited PyDateTime_FromDateAndTime // skipped non-limited PyDateTime_FromDateAndTimeAndFold // skipped non-limited PyTime_FromTime // skipped non-limited PyTime_FromTimeAndFold // skipped non-limited PyDelta_FromDSU pub unsafe fn PyTimeZone_FromOffset(offset: *mut PyObject) -> *mut PyObject { ((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, std::ptr::null_mut()) } pub unsafe fn PyTimeZone_FromOffsetAndName( offset: *mut PyObject, name: *mut PyObject, ) -> *mut PyObject { ((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, name) } #[cfg(not(PyPy))] pub unsafe fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject { let f = (*PyDateTimeAPI()).DateTime_FromTimestamp; f((*PyDateTimeAPI()).DateTimeType, args, std::ptr::null_mut()) } #[cfg(not(PyPy))] pub unsafe fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject { let f = (*PyDateTimeAPI()).Date_FromTimestamp; f((*PyDateTimeAPI()).DateType, args) } #[cfg(PyPy)] extern "C" { #[link_name = "PyPyDate_FromTimestamp"] pub fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject; #[link_name = "PyPyDateTime_FromTimestamp"] pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject; } #[cfg(PyPy)] extern "C" { #[link_name = "_PyPyDateTime_Import"] pub fn PyDateTime_Import() -> *mut PyDateTime_CAPI; } // Rust specific implementation details struct PyDateTimeAPISingleton(UnsafeCell<*mut PyDateTime_CAPI>); unsafe impl Sync for PyDateTimeAPISingleton {} static PyDateTimeAPI_impl: PyDateTimeAPISingleton = PyDateTimeAPISingleton(UnsafeCell::new(ptr::null_mut())); pyo3-ffi/src/import.rs0000644000175000017500000000617014661133735015650 0ustar jamespagejamespageuse crate::object::PyObject; use std::os::raw::{c_char, c_int, c_long}; extern "C" { pub fn PyImport_GetMagicNumber() -> c_long; pub fn PyImport_GetMagicTag() -> *const c_char; #[cfg_attr(PyPy, link_name = "PyPyImport_ExecCodeModule")] pub fn PyImport_ExecCodeModule(name: *const c_char, co: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_ExecCodeModuleEx")] pub fn PyImport_ExecCodeModuleEx( name: *const c_char, co: *mut PyObject, pathname: *const c_char, ) -> *mut PyObject; pub fn PyImport_ExecCodeModuleWithPathnames( name: *const c_char, co: *mut PyObject, pathname: *const c_char, cpathname: *const c_char, ) -> *mut PyObject; pub fn PyImport_ExecCodeModuleObject( name: *mut PyObject, co: *mut PyObject, pathname: *mut PyObject, cpathname: *mut PyObject, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_GetModuleDict")] pub fn PyImport_GetModuleDict() -> *mut PyObject; // skipped Python 3.7 / ex-non-limited PyImport_GetModule pub fn PyImport_AddModuleObject(name: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_AddModule")] pub fn PyImport_AddModule(name: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_ImportModule")] pub fn PyImport_ImportModule(name: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_ImportModuleNoBlock")] pub fn PyImport_ImportModuleNoBlock(name: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_ImportModuleLevel")] pub fn PyImport_ImportModuleLevel( name: *const c_char, globals: *mut PyObject, locals: *mut PyObject, fromlist: *mut PyObject, level: c_int, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_ImportModuleLevelObject")] pub fn PyImport_ImportModuleLevelObject( name: *mut PyObject, globals: *mut PyObject, locals: *mut PyObject, fromlist: *mut PyObject, level: c_int, ) -> *mut PyObject; } #[inline] pub unsafe fn PyImport_ImportModuleEx( name: *const c_char, globals: *mut PyObject, locals: *mut PyObject, fromlist: *mut PyObject, ) -> *mut PyObject { PyImport_ImportModuleLevel(name, globals, locals, fromlist, 0) } extern "C" { pub fn PyImport_GetImporter(path: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_Import")] pub fn PyImport_Import(name: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyImport_ReloadModule")] pub fn PyImport_ReloadModule(m: *mut PyObject) -> *mut PyObject; #[cfg(not(Py_3_9))] #[deprecated(note = "Removed in Python 3.9 as it was \"For internal use only\".")] pub fn PyImport_Cleanup(); pub fn PyImport_ImportFrozenModuleObject(name: *mut PyObject) -> c_int; pub fn PyImport_ImportFrozenModule(name: *const c_char) -> c_int; pub fn PyImport_AppendInittab( name: *const c_char, initfunc: Option *mut PyObject>, ) -> c_int; } pyo3-ffi/src/pystrtod.rs0000644000175000017500000000221414661133735016221 0ustar jamespagejamespageuse crate::object::PyObject; use std::os::raw::{c_char, c_double, c_int}; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyOS_string_to_double")] pub fn PyOS_string_to_double( str: *const c_char, endptr: *mut *mut c_char, overflow_exception: *mut PyObject, ) -> c_double; #[cfg_attr(PyPy, link_name = "PyPyOS_double_to_string")] pub fn PyOS_double_to_string( val: c_double, format_code: c_char, precision: c_int, flags: c_int, _type: *mut c_int, ) -> *mut c_char; } // skipped non-limited _Py_string_to_number_with_underscores // skipped non-limited _Py_parse_inf_or_nan /* PyOS_double_to_string's "flags" parameter can be set to 0 or more of: */ pub const Py_DTSF_SIGN: c_int = 0x01; /* always add the sign */ pub const Py_DTSF_ADD_DOT_0: c_int = 0x02; /* if the result is an integer add ".0" */ pub const Py_DTSF_ALT: c_int = 0x04; /* "alternate" formatting. it's format_code specific */ /* PyOS_double_to_string's "type", if non-NULL, will be set to one of: */ pub const Py_DTST_FINITE: c_int = 0; pub const Py_DTST_INFINITE: c_int = 1; pub const Py_DTST_NAN: c_int = 2; pyo3-ffi/src/typeslots.rs0000644000175000017500000000576114661133735016411 0ustar jamespagejamespageuse std::os::raw::c_int; pub const Py_bf_getbuffer: c_int = 1; pub const Py_bf_releasebuffer: c_int = 2; pub const Py_mp_ass_subscript: c_int = 3; pub const Py_mp_length: c_int = 4; pub const Py_mp_subscript: c_int = 5; pub const Py_nb_absolute: c_int = 6; pub const Py_nb_add: c_int = 7; pub const Py_nb_and: c_int = 8; pub const Py_nb_bool: c_int = 9; pub const Py_nb_divmod: c_int = 10; pub const Py_nb_float: c_int = 11; pub const Py_nb_floor_divide: c_int = 12; pub const Py_nb_index: c_int = 13; pub const Py_nb_inplace_add: c_int = 14; pub const Py_nb_inplace_and: c_int = 15; pub const Py_nb_inplace_floor_divide: c_int = 16; pub const Py_nb_inplace_lshift: c_int = 17; pub const Py_nb_inplace_multiply: c_int = 18; pub const Py_nb_inplace_or: c_int = 19; pub const Py_nb_inplace_power: c_int = 20; pub const Py_nb_inplace_remainder: c_int = 21; pub const Py_nb_inplace_rshift: c_int = 22; pub const Py_nb_inplace_subtract: c_int = 23; pub const Py_nb_inplace_true_divide: c_int = 24; pub const Py_nb_inplace_xor: c_int = 25; pub const Py_nb_int: c_int = 26; pub const Py_nb_invert: c_int = 27; pub const Py_nb_lshift: c_int = 28; pub const Py_nb_multiply: c_int = 29; pub const Py_nb_negative: c_int = 30; pub const Py_nb_or: c_int = 31; pub const Py_nb_positive: c_int = 32; pub const Py_nb_power: c_int = 33; pub const Py_nb_remainder: c_int = 34; pub const Py_nb_rshift: c_int = 35; pub const Py_nb_subtract: c_int = 36; pub const Py_nb_true_divide: c_int = 37; pub const Py_nb_xor: c_int = 38; pub const Py_sq_ass_item: c_int = 39; pub const Py_sq_concat: c_int = 40; pub const Py_sq_contains: c_int = 41; pub const Py_sq_inplace_concat: c_int = 42; pub const Py_sq_inplace_repeat: c_int = 43; pub const Py_sq_item: c_int = 44; pub const Py_sq_length: c_int = 45; pub const Py_sq_repeat: c_int = 46; pub const Py_tp_alloc: c_int = 47; pub const Py_tp_base: c_int = 48; pub const Py_tp_bases: c_int = 49; pub const Py_tp_call: c_int = 50; pub const Py_tp_clear: c_int = 51; pub const Py_tp_dealloc: c_int = 52; pub const Py_tp_del: c_int = 53; pub const Py_tp_descr_get: c_int = 54; pub const Py_tp_descr_set: c_int = 55; pub const Py_tp_doc: c_int = 56; pub const Py_tp_getattr: c_int = 57; pub const Py_tp_getattro: c_int = 58; pub const Py_tp_hash: c_int = 59; pub const Py_tp_init: c_int = 60; pub const Py_tp_is_gc: c_int = 61; pub const Py_tp_iter: c_int = 62; pub const Py_tp_iternext: c_int = 63; pub const Py_tp_methods: c_int = 64; pub const Py_tp_new: c_int = 65; pub const Py_tp_repr: c_int = 66; pub const Py_tp_richcompare: c_int = 67; pub const Py_tp_setattr: c_int = 68; pub const Py_tp_setattro: c_int = 69; pub const Py_tp_str: c_int = 70; pub const Py_tp_traverse: c_int = 71; pub const Py_tp_members: c_int = 72; pub const Py_tp_getset: c_int = 73; pub const Py_tp_free: c_int = 74; pub const Py_nb_matrix_multiply: c_int = 75; pub const Py_nb_inplace_matrix_multiply: c_int = 76; pub const Py_am_await: c_int = 77; pub const Py_am_aiter: c_int = 78; pub const Py_am_anext: c_int = 79; pub const Py_tp_finalize: c_int = 80; pyo3-ffi/src/floatobject.rs0000644000175000017500000000301114661133735016621 0ustar jamespagejamespageuse crate::object::*; use std::os::raw::{c_double, c_int}; use std::ptr::addr_of_mut; #[cfg(Py_LIMITED_API)] // TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985) opaque_struct!(PyFloatObject); #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyFloat_Type")] pub static mut PyFloat_Type: PyTypeObject; } #[inline] pub unsafe fn PyFloat_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, addr_of_mut!(PyFloat_Type)) } #[inline] pub unsafe fn PyFloat_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyFloat_Type)) as c_int } // skipped Py_RETURN_NAN // skipped Py_RETURN_INF extern "C" { pub fn PyFloat_GetMax() -> c_double; pub fn PyFloat_GetMin() -> c_double; pub fn PyFloat_GetInfo() -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyFloat_FromString")] pub fn PyFloat_FromString(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyFloat_FromDouble")] pub fn PyFloat_FromDouble(arg1: c_double) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyFloat_AsDouble")] pub fn PyFloat_AsDouble(arg1: *mut PyObject) -> c_double; } // skipped non-limited _PyFloat_Pack2 // skipped non-limited _PyFloat_Pack4 // skipped non-limited _PyFloat_Pack8 // skipped non-limited _PyFloat_Unpack2 // skipped non-limited _PyFloat_Unpack4 // skipped non-limited _PyFloat_Unpack8 // skipped non-limited _PyFloat_DebugMallocStats // skipped non-limited _PyFloat_FormatAdvancedWriter pyo3-ffi/src/sliceobject.rs0000644000175000017500000000510314661133735016617 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_EllipsisObject")] static mut _Py_EllipsisObject: PyObject; #[cfg(GraalPy)] static mut _Py_EllipsisObjectReference: *mut PyObject; } #[inline] pub unsafe fn Py_Ellipsis() -> *mut PyObject { #[cfg(not(GraalPy))] return addr_of_mut!(_Py_EllipsisObject); #[cfg(GraalPy)] return _Py_EllipsisObjectReference; } #[cfg(not(Py_LIMITED_API))] #[repr(C)] pub struct PySliceObject { pub ob_base: PyObject, #[cfg(not(GraalPy))] pub start: *mut PyObject, #[cfg(not(GraalPy))] pub stop: *mut PyObject, #[cfg(not(GraalPy))] pub step: *mut PyObject, } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPySlice_Type")] pub static mut PySlice_Type: PyTypeObject; pub static mut PyEllipsis_Type: PyTypeObject; } #[inline] pub unsafe fn PySlice_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PySlice_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPySlice_New")] pub fn PySlice_New( start: *mut PyObject, stop: *mut PyObject, step: *mut PyObject, ) -> *mut PyObject; // skipped non-limited _PySlice_FromIndices // skipped non-limited _PySlice_GetLongIndices #[cfg_attr(PyPy, link_name = "PyPySlice_GetIndices")] pub fn PySlice_GetIndices( r: *mut PyObject, length: Py_ssize_t, start: *mut Py_ssize_t, stop: *mut Py_ssize_t, step: *mut Py_ssize_t, ) -> c_int; } #[inline] pub unsafe fn PySlice_GetIndicesEx( slice: *mut PyObject, length: Py_ssize_t, start: *mut Py_ssize_t, stop: *mut Py_ssize_t, step: *mut Py_ssize_t, slicelength: *mut Py_ssize_t, ) -> c_int { if PySlice_Unpack(slice, start, stop, step) < 0 { *slicelength = 0; -1 } else { *slicelength = PySlice_AdjustIndices(length, start, stop, *step); 0 } } extern "C" { #[cfg_attr(PyPy, link_name = "PyPySlice_Unpack")] pub fn PySlice_Unpack( slice: *mut PyObject, start: *mut Py_ssize_t, stop: *mut Py_ssize_t, step: *mut Py_ssize_t, ) -> c_int; #[cfg_attr(all(PyPy, Py_3_10), link_name = "PyPySlice_AdjustIndices")] pub fn PySlice_AdjustIndices( length: Py_ssize_t, start: *mut Py_ssize_t, stop: *mut Py_ssize_t, step: Py_ssize_t, ) -> Py_ssize_t; } pyo3-ffi/src/boolobject.rs0000644000175000017500000000324014661133735016453 0ustar jamespagejamespage#[cfg(not(GraalPy))] use crate::longobject::PyLongObject; use crate::object::*; use std::os::raw::{c_int, c_long}; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyBool_Type")] pub static mut PyBool_Type: PyTypeObject; } #[inline] pub unsafe fn PyBool_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyBool_Type)) as c_int } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_FalseStruct")] static mut _Py_FalseStruct: PyLongObject; #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_TrueStruct")] static mut _Py_TrueStruct: PyLongObject; #[cfg(GraalPy)] static mut _Py_FalseStructReference: *mut PyObject; #[cfg(GraalPy)] static mut _Py_TrueStructReference: *mut PyObject; } #[inline] pub unsafe fn Py_False() -> *mut PyObject { #[cfg(not(GraalPy))] return addr_of_mut!(_Py_FalseStruct) as *mut PyObject; #[cfg(GraalPy)] return _Py_FalseStructReference; } #[inline] pub unsafe fn Py_True() -> *mut PyObject { #[cfg(not(GraalPy))] return addr_of_mut!(_Py_TrueStruct) as *mut PyObject; #[cfg(GraalPy)] return _Py_TrueStructReference; } #[inline] pub unsafe fn Py_IsTrue(x: *mut PyObject) -> c_int { Py_Is(x, Py_True()) } #[inline] pub unsafe fn Py_IsFalse(x: *mut PyObject) -> c_int { Py_Is(x, Py_False()) } // skipped Py_RETURN_TRUE // skipped Py_RETURN_FALSE #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyBool_FromLong")] pub fn PyBool_FromLong(arg1: c_long) -> *mut PyObject; } pyo3-ffi/src/structseq.rs0000644000175000017500000000356614661133735016401 0ustar jamespagejamespageuse crate::object::{PyObject, PyTypeObject}; #[cfg(not(PyPy))] use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; #[repr(C)] #[derive(Copy, Clone)] pub struct PyStructSequence_Field { pub name: *const c_char, pub doc: *const c_char, } #[repr(C)] #[derive(Copy, Clone)] pub struct PyStructSequence_Desc { pub name: *const c_char, pub doc: *const c_char, pub fields: *mut PyStructSequence_Field, pub n_in_sequence: c_int, } // skipped PyStructSequence_UnnamedField; extern "C" { #[cfg(not(Py_LIMITED_API))] #[cfg_attr(PyPy, link_name = "PyPyStructSequence_InitType")] pub fn PyStructSequence_InitType(_type: *mut PyTypeObject, desc: *mut PyStructSequence_Desc); #[cfg(not(Py_LIMITED_API))] #[cfg_attr(PyPy, link_name = "PyPyStructSequence_InitType2")] pub fn PyStructSequence_InitType2( _type: *mut PyTypeObject, desc: *mut PyStructSequence_Desc, ) -> c_int; #[cfg(not(PyPy))] pub fn PyStructSequence_NewType(desc: *mut PyStructSequence_Desc) -> *mut PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyStructSequence_New")] pub fn PyStructSequence_New(_type: *mut PyTypeObject) -> *mut PyObject; } #[cfg(not(Py_LIMITED_API))] pub type PyStructSequence = crate::PyTupleObject; #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[inline] pub unsafe fn PyStructSequence_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) { crate::PyTuple_SET_ITEM(op, i, v) } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[inline] pub unsafe fn PyStructSequence_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject { crate::PyTuple_GET_ITEM(op, i) } extern "C" { #[cfg(not(PyPy))] pub fn PyStructSequence_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject); #[cfg(not(PyPy))] pub fn PyStructSequence_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; } pyo3-ffi/src/setobject.rs0000644000175000017500000001055714661133735016324 0ustar jamespagejamespageuse crate::object::*; #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] use crate::pyport::Py_hash_t; use crate::pyport::Py_ssize_t; use std::os::raw::c_int; use std::ptr::addr_of_mut; pub const PySet_MINSIZE: usize = 8; #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct setentry { pub key: *mut PyObject, pub hash: Py_hash_t, } #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))] #[repr(C)] #[derive(Debug)] pub struct PySetObject { pub ob_base: PyObject, pub fill: Py_ssize_t, pub used: Py_ssize_t, pub mask: Py_ssize_t, pub table: *mut setentry, pub hash: Py_hash_t, pub finger: Py_ssize_t, pub smalltable: [setentry; PySet_MINSIZE], pub weakreflist: *mut PyObject, } // skipped #[inline] #[cfg(all(not(any(PyPy, GraalPy)), not(Py_LIMITED_API)))] pub unsafe fn PySet_GET_SIZE(so: *mut PyObject) -> Py_ssize_t { debug_assert_eq!(PyAnySet_Check(so), 1); let so = so.cast::(); (*so).used } #[cfg(not(Py_LIMITED_API))] #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut _PySet_Dummy: *mut PyObject; } extern "C" { #[cfg(not(Py_LIMITED_API))] #[cfg_attr(PyPy, link_name = "_PyPySet_NextEntry")] pub fn _PySet_NextEntry( set: *mut PyObject, pos: *mut Py_ssize_t, key: *mut *mut PyObject, hash: *mut super::Py_hash_t, ) -> c_int; // skipped non-limited _PySet_Update } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPySet_Type")] pub static mut PySet_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyFrozenSet_Type")] pub static mut PyFrozenSet_Type: PyTypeObject; pub static mut PySetIter_Type: PyTypeObject; } extern "C" { #[cfg_attr(PyPy, link_name = "PyPySet_New")] pub fn PySet_New(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyFrozenSet_New")] pub fn PyFrozenSet_New(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySet_Add")] pub fn PySet_Add(set: *mut PyObject, key: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySet_Clear")] pub fn PySet_Clear(set: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySet_Contains")] pub fn PySet_Contains(anyset: *mut PyObject, key: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySet_Discard")] pub fn PySet_Discard(set: *mut PyObject, key: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPySet_Pop")] pub fn PySet_Pop(set: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPySet_Size")] pub fn PySet_Size(anyset: *mut PyObject) -> Py_ssize_t; #[cfg(PyPy)] #[link_name = "PyPyFrozenSet_CheckExact"] pub fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int; } #[inline] #[cfg(not(any(PyPy, GraalPy)))] pub unsafe fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int { (Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)) as c_int } extern "C" { #[cfg(PyPy)] #[link_name = "PyPyFrozenSet_Check"] pub fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int { (Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type) || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int } extern "C" { #[cfg(PyPy)] #[link_name = "PyPyAnySet_CheckExact"] pub fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int { (Py_TYPE(ob) == addr_of_mut!(PySet_Type) || Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)) as c_int } #[inline] pub unsafe fn PyAnySet_Check(ob: *mut PyObject) -> c_int { (PyAnySet_CheckExact(ob) != 0 || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PySet_Type)) != 0 || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int } #[inline] #[cfg(Py_3_10)] pub unsafe fn PySet_CheckExact(op: *mut PyObject) -> c_int { crate::Py_IS_TYPE(op, addr_of_mut!(PySet_Type)) } extern "C" { #[cfg(PyPy)] #[link_name = "PyPySet_Check"] pub fn PySet_Check(ob: *mut PyObject) -> c_int; } #[inline] #[cfg(not(PyPy))] pub unsafe fn PySet_Check(ob: *mut PyObject) -> c_int { (Py_TYPE(ob) == addr_of_mut!(PySet_Type) || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PySet_Type)) != 0) as c_int } pyo3-ffi/src/iterobject.rs0000644000175000017500000000142614661133735016467 0ustar jamespagejamespageuse crate::object::*; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PySeqIter_Type: PyTypeObject; pub static mut PyCallIter_Type: PyTypeObject; } #[inline] pub unsafe fn PySeqIter_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PySeqIter_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPySeqIter_New")] pub fn PySeqIter_New(arg1: *mut PyObject) -> *mut PyObject; } #[inline] pub unsafe fn PyCallIter_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyCallIter_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyCallIter_New")] pub fn PyCallIter_New(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; } pyo3-ffi/src/warnings.rs0000644000175000017500000000167714661133735016175 0ustar jamespagejamespageuse crate::object::PyObject; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyErr_WarnEx")] pub fn PyErr_WarnEx( category: *mut PyObject, message: *const c_char, stack_level: Py_ssize_t, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyErr_WarnFormat")] pub fn PyErr_WarnFormat( category: *mut PyObject, stack_level: Py_ssize_t, format: *const c_char, ... ) -> c_int; pub fn PyErr_ResourceWarning( source: *mut PyObject, stack_level: Py_ssize_t, format: *const c_char, ... ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyErr_WarnExplicit")] pub fn PyErr_WarnExplicit( category: *mut PyObject, message: *const c_char, filename: *const c_char, lineno: c_int, module: *const c_char, registry: *mut PyObject, ) -> c_int; } pyo3-ffi/src/bltinmodule.rs0000644000175000017500000000035114661133735016647 0ustar jamespagejamespageuse crate::object::PyTypeObject; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyFilter_Type: PyTypeObject; pub static mut PyMap_Type: PyTypeObject; pub static mut PyZip_Type: PyTypeObject; } pyo3-ffi/src/compile.rs0000644000175000017500000000040114661133735015755 0ustar jamespagejamespageuse std::os::raw::c_int; pub const Py_single_input: c_int = 256; pub const Py_file_input: c_int = 257; pub const Py_eval_input: c_int = 258; #[cfg(Py_3_8)] pub const Py_func_type_input: c_int = 345; #[cfg(Py_3_9)] pub const Py_fstring_input: c_int = 800; pyo3-ffi/src/memoryobject.rs0000644000175000017500000000305114661133735017030 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int}; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(Py_LIMITED_API))] pub static mut _PyManagedBuffer_Type: PyTypeObject; #[cfg_attr(PyPy, link_name = "PyPyMemoryView_Type")] pub static mut PyMemoryView_Type: PyTypeObject; } #[inline] pub unsafe fn PyMemoryView_Check(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyMemoryView_Type)) as c_int } // skipped non-limited PyMemoryView_GET_BUFFER // skipped non-limited PyMemeryView_GET_BASE extern "C" { #[cfg_attr(PyPy, link_name = "PyPyMemoryView_FromObject")] pub fn PyMemoryView_FromObject(base: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyMemoryView_FromMemory")] pub fn PyMemoryView_FromMemory( mem: *mut c_char, size: Py_ssize_t, flags: c_int, ) -> *mut PyObject; #[cfg(any(Py_3_11, not(Py_LIMITED_API)))] #[cfg_attr(PyPy, link_name = "PyPyMemoryView_FromBuffer")] pub fn PyMemoryView_FromBuffer(view: *const crate::Py_buffer) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyMemoryView_GetContiguous")] pub fn PyMemoryView_GetContiguous( base: *mut PyObject, buffertype: c_int, order: c_char, ) -> *mut PyObject; } // skipped remainder of file with comment: /* The structs are declared here so that macros can work, but they shouldn't be considered public. Don't access their fields directly, use the macros and functions instead! */ pyo3-ffi/src/structmember.rs0000644000175000017500000000211414661133735017044 0ustar jamespagejamespageuse std::os::raw::c_int; pub use crate::PyMemberDef; pub use crate::Py_T_BOOL as T_BOOL; pub use crate::Py_T_BYTE as T_BYTE; pub use crate::Py_T_CHAR as T_CHAR; pub use crate::Py_T_DOUBLE as T_DOUBLE; pub use crate::Py_T_FLOAT as T_FLOAT; pub use crate::Py_T_INT as T_INT; pub use crate::Py_T_LONG as T_LONG; pub use crate::Py_T_LONGLONG as T_LONGLONG; pub use crate::Py_T_OBJECT_EX as T_OBJECT_EX; pub use crate::Py_T_SHORT as T_SHORT; pub use crate::Py_T_STRING as T_STRING; pub use crate::Py_T_STRING_INPLACE as T_STRING_INPLACE; pub use crate::Py_T_UBYTE as T_UBYTE; pub use crate::Py_T_UINT as T_UINT; pub use crate::Py_T_ULONG as T_ULONG; pub use crate::Py_T_ULONGLONG as T_ULONGLONG; pub use crate::Py_T_USHORT as T_USHORT; #[allow(deprecated)] pub use crate::_Py_T_OBJECT as T_OBJECT; pub use crate::Py_T_PYSSIZET as T_PYSSIZET; #[allow(deprecated)] pub use crate::_Py_T_NONE as T_NONE; /* Flags */ pub use crate::Py_READONLY as READONLY; pub const READ_RESTRICTED: c_int = 2; pub const PY_WRITE_RESTRICTED: c_int = 4; pub const RESTRICTED: c_int = READ_RESTRICTED | PY_WRITE_RESTRICTED; pyo3-ffi/src/listobject.rs0000644000175000017500000000540114661133735016474 0ustar jamespagejamespageuse crate::object::*; use crate::pyport::Py_ssize_t; use std::os::raw::c_int; use std::ptr::addr_of_mut; #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg_attr(PyPy, link_name = "PyPyList_Type")] pub static mut PyList_Type: PyTypeObject; pub static mut PyListIter_Type: PyTypeObject; pub static mut PyListRevIter_Type: PyTypeObject; } #[inline] pub unsafe fn PyList_Check(op: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS) } #[inline] pub unsafe fn PyList_CheckExact(op: *mut PyObject) -> c_int { (Py_TYPE(op) == addr_of_mut!(PyList_Type)) as c_int } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyList_New")] pub fn PyList_New(size: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyList_Size")] pub fn PyList_Size(arg1: *mut PyObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyList_GetItem")] pub fn PyList_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyList_SetItem")] pub fn PyList_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyList_Insert")] pub fn PyList_Insert(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyList_Append")] pub fn PyList_Append(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyList_GetSlice")] pub fn PyList_GetSlice( arg1: *mut PyObject, arg2: Py_ssize_t, arg3: Py_ssize_t, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyList_SetSlice")] pub fn PyList_SetSlice( arg1: *mut PyObject, arg2: Py_ssize_t, arg3: Py_ssize_t, arg4: *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyList_Sort")] pub fn PyList_Sort(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyList_Reverse")] pub fn PyList_Reverse(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyList_AsTuple")] pub fn PyList_AsTuple(arg1: *mut PyObject) -> *mut PyObject; // CPython macros exported as functions on PyPy or GraalPy #[cfg(any(PyPy, GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyList_GET_ITEM")] #[cfg_attr(GraalPy, link_name = "PyList_GetItem")] pub fn PyList_GET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject; #[cfg(PyPy)] #[cfg_attr(PyPy, link_name = "PyPyList_GET_SIZE")] pub fn PyList_GET_SIZE(arg1: *mut PyObject) -> Py_ssize_t; #[cfg(any(PyPy, GraalPy))] #[cfg_attr(PyPy, link_name = "PyPyList_SET_ITEM")] #[cfg_attr(GraalPy, link_name = "_PyList_SET_ITEM")] pub fn PyList_SET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject); } pyo3-ffi/src/object.rs0000644000175000017500000006123614661133735015610 0ustar jamespagejamespageuse crate::pyport::{Py_hash_t, Py_ssize_t}; use std::mem; use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_void}; use std::ptr; #[cfg(Py_LIMITED_API)] opaque_struct!(PyTypeObject); #[cfg(not(Py_LIMITED_API))] pub use crate::cpython::object::PyTypeObject; // _PyObject_HEAD_EXTRA: conditionally defined in PyObject_HEAD_INIT // _PyObject_EXTRA_INIT: conditionally defined in PyObject_HEAD_INIT #[cfg(Py_3_12)] pub const _Py_IMMORTAL_REFCNT: Py_ssize_t = { if cfg!(target_pointer_width = "64") { c_uint::MAX as Py_ssize_t } else { // for 32-bit systems, use the lower 30 bits (see comment in CPython's object.h) (c_uint::MAX >> 2) as Py_ssize_t } }; pub const PyObject_HEAD_INIT: PyObject = PyObject { #[cfg(py_sys_config = "Py_TRACE_REFS")] _ob_next: std::ptr::null_mut(), #[cfg(py_sys_config = "Py_TRACE_REFS")] _ob_prev: std::ptr::null_mut(), #[cfg(Py_3_12)] ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 }, #[cfg(not(Py_3_12))] ob_refcnt: 1, #[cfg(PyPy)] ob_pypy_link: 0, ob_type: std::ptr::null_mut(), }; // skipped PyObject_VAR_HEAD // skipped Py_INVALID_SIZE #[repr(C)] #[derive(Copy, Clone)] #[cfg(Py_3_12)] /// This union is anonymous in CPython, so the name was given by PyO3 because /// Rust unions need a name. pub union PyObjectObRefcnt { pub ob_refcnt: Py_ssize_t, #[cfg(target_pointer_width = "64")] pub ob_refcnt_split: [crate::PY_UINT32_T; 2], } #[cfg(Py_3_12)] impl std::fmt::Debug for PyObjectObRefcnt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", unsafe { self.ob_refcnt }) } } #[cfg(not(Py_3_12))] pub type PyObjectObRefcnt = Py_ssize_t; #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct PyObject { #[cfg(py_sys_config = "Py_TRACE_REFS")] pub _ob_next: *mut PyObject, #[cfg(py_sys_config = "Py_TRACE_REFS")] pub _ob_prev: *mut PyObject, pub ob_refcnt: PyObjectObRefcnt, #[cfg(PyPy)] pub ob_pypy_link: Py_ssize_t, pub ob_type: *mut PyTypeObject, } // skipped _PyObject_CAST #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct PyVarObject { pub ob_base: PyObject, #[cfg(not(GraalPy))] pub ob_size: Py_ssize_t, } // skipped _PyVarObject_CAST #[inline] pub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int { (x == y).into() } #[inline] #[cfg(Py_3_12)] pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t { (*ob).ob_refcnt.ob_refcnt } #[inline] #[cfg(not(Py_3_12))] pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t { #[cfg(not(GraalPy))] return (*ob).ob_refcnt; #[cfg(GraalPy)] return _Py_REFCNT(ob); } #[inline] pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject { #[cfg(not(GraalPy))] return (*ob).ob_type; #[cfg(GraalPy)] return _Py_TYPE(ob); } // PyLong_Type defined in longobject.rs // PyBool_Type defined in boolobject.rs #[inline] pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t { #[cfg(not(GraalPy))] { debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyLong_Type)); debug_assert_ne!((*ob).ob_type, std::ptr::addr_of_mut!(crate::PyBool_Type)); (*ob.cast::()).ob_size } #[cfg(GraalPy)] _Py_SIZE(ob) } #[inline] pub unsafe fn Py_IS_TYPE(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int { (Py_TYPE(ob) == tp) as c_int } #[inline(always)] #[cfg(all(Py_3_12, target_pointer_width = "64"))] pub unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int { (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int } #[inline(always)] #[cfg(all(Py_3_12, target_pointer_width = "32"))] pub unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int { ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int } // skipped _Py_SET_REFCNT // skipped Py_SET_REFCNT // skipped _Py_SET_TYPE // skipped Py_SET_TYPE // skipped _Py_SET_SIZE // skipped Py_SET_SIZE pub type unaryfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject; pub type binaryfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> *mut PyObject; pub type ternaryfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject; pub type inquiry = unsafe extern "C" fn(*mut PyObject) -> c_int; pub type lenfunc = unsafe extern "C" fn(*mut PyObject) -> Py_ssize_t; pub type ssizeargfunc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t) -> *mut PyObject; pub type ssizessizeargfunc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t, Py_ssize_t) -> *mut PyObject; pub type ssizeobjargproc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t, *mut PyObject) -> c_int; pub type ssizessizeobjargproc = unsafe extern "C" fn(*mut PyObject, Py_ssize_t, Py_ssize_t, arg4: *mut PyObject) -> c_int; pub type objobjargproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int; pub type objobjproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> c_int; pub type visitproc = unsafe extern "C" fn(object: *mut PyObject, arg: *mut c_void) -> c_int; pub type traverseproc = unsafe extern "C" fn(slf: *mut PyObject, visit: visitproc, arg: *mut c_void) -> c_int; pub type freefunc = unsafe extern "C" fn(*mut c_void); pub type destructor = unsafe extern "C" fn(*mut PyObject); pub type getattrfunc = unsafe extern "C" fn(*mut PyObject, *mut c_char) -> *mut PyObject; pub type getattrofunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject) -> *mut PyObject; pub type setattrfunc = unsafe extern "C" fn(*mut PyObject, *mut c_char, *mut PyObject) -> c_int; pub type setattrofunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int; pub type reprfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject; pub type hashfunc = unsafe extern "C" fn(*mut PyObject) -> Py_hash_t; pub type richcmpfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, c_int) -> *mut PyObject; pub type getiterfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject; pub type iternextfunc = unsafe extern "C" fn(*mut PyObject) -> *mut PyObject; pub type descrgetfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject; pub type descrsetfunc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int; pub type initproc = unsafe extern "C" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int; pub type newfunc = unsafe extern "C" fn(*mut PyTypeObject, *mut PyObject, *mut PyObject) -> *mut PyObject; pub type allocfunc = unsafe extern "C" fn(*mut PyTypeObject, Py_ssize_t) -> *mut PyObject; #[cfg(Py_3_8)] pub type vectorcallfunc = unsafe extern "C" fn( callable: *mut PyObject, args: *const *mut PyObject, nargsf: libc::size_t, kwnames: *mut PyObject, ) -> *mut PyObject; #[repr(C)] #[derive(Copy, Clone)] pub struct PyType_Slot { pub slot: c_int, pub pfunc: *mut c_void, } impl Default for PyType_Slot { fn default() -> PyType_Slot { unsafe { mem::zeroed() } } } #[repr(C)] #[derive(Copy, Clone)] pub struct PyType_Spec { pub name: *const c_char, pub basicsize: c_int, pub itemsize: c_int, pub flags: c_uint, pub slots: *mut PyType_Slot, } impl Default for PyType_Spec { fn default() -> PyType_Spec { unsafe { mem::zeroed() } } } extern "C" { #[cfg_attr(PyPy, link_name = "PyPyType_FromSpec")] pub fn PyType_FromSpec(arg1: *mut PyType_Spec) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyType_FromSpecWithBases")] pub fn PyType_FromSpecWithBases(arg1: *mut PyType_Spec, arg2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyType_GetSlot")] pub fn PyType_GetSlot(arg1: *mut PyTypeObject, arg2: c_int) -> *mut c_void; #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] #[cfg_attr(PyPy, link_name = "PyPyType_FromModuleAndSpec")] pub fn PyType_FromModuleAndSpec( module: *mut PyObject, spec: *mut PyType_Spec, bases: *mut PyObject, ) -> *mut PyObject; #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] #[cfg_attr(PyPy, link_name = "PyPyType_GetModule")] pub fn PyType_GetModule(arg1: *mut PyTypeObject) -> *mut PyObject; #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleState")] pub fn PyType_GetModuleState(arg1: *mut PyTypeObject) -> *mut c_void; #[cfg(Py_3_11)] #[cfg_attr(PyPy, link_name = "PyPyType_GetName")] pub fn PyType_GetName(arg1: *mut PyTypeObject) -> *mut PyObject; #[cfg(Py_3_11)] #[cfg_attr(PyPy, link_name = "PyPyType_GetQualName")] pub fn PyType_GetQualName(arg1: *mut PyTypeObject) -> *mut PyObject; #[cfg(Py_3_13)] #[cfg_attr(PyPy, link_name = "PyPyType_GetFullyQualifiedName")] pub fn PyType_GetFullyQualifiedName(arg1: *mut PyTypeObject) -> *mut PyObject; #[cfg(Py_3_13)] #[cfg_attr(PyPy, link_name = "PyPyType_GetModuleName")] pub fn PyType_GetModuleName(arg1: *mut PyTypeObject) -> *mut PyObject; #[cfg(Py_3_12)] #[cfg_attr(PyPy, link_name = "PyPyType_FromMetaclass")] pub fn PyType_FromMetaclass( metaclass: *mut PyTypeObject, module: *mut PyObject, spec: *mut PyType_Spec, bases: *mut PyObject, ) -> *mut PyObject; #[cfg(Py_3_12)] #[cfg_attr(PyPy, link_name = "PyPyObject_GetTypeData")] pub fn PyObject_GetTypeData(obj: *mut PyObject, cls: *mut PyTypeObject) -> *mut c_void; #[cfg(Py_3_12)] #[cfg_attr(PyPy, link_name = "PyPyObject_GetTypeDataSize")] pub fn PyObject_GetTypeDataSize(cls: *mut PyTypeObject) -> Py_ssize_t; #[cfg_attr(PyPy, link_name = "PyPyType_IsSubtype")] pub fn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int; } #[inline] pub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int { (Py_TYPE(ob) == tp || PyType_IsSubtype(Py_TYPE(ob), tp) != 0) as c_int } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { /// built-in 'type' #[cfg_attr(PyPy, link_name = "PyPyType_Type")] pub static mut PyType_Type: PyTypeObject; /// built-in 'object' #[cfg_attr(PyPy, link_name = "PyPyBaseObject_Type")] pub static mut PyBaseObject_Type: PyTypeObject; /// built-in 'super' pub static mut PySuper_Type: PyTypeObject; } extern "C" { pub fn PyType_GetFlags(arg1: *mut PyTypeObject) -> c_ulong; #[cfg_attr(PyPy, link_name = "PyPyType_Ready")] pub fn PyType_Ready(t: *mut PyTypeObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyType_GenericAlloc")] pub fn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyType_GenericNew")] pub fn PyType_GenericNew( t: *mut PyTypeObject, args: *mut PyObject, kwds: *mut PyObject, ) -> *mut PyObject; pub fn PyType_ClearCache() -> c_uint; #[cfg_attr(PyPy, link_name = "PyPyType_Modified")] pub fn PyType_Modified(t: *mut PyTypeObject); #[cfg_attr(PyPy, link_name = "PyPyObject_Repr")] pub fn PyObject_Repr(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_Str")] pub fn PyObject_Str(o: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_ASCII")] pub fn PyObject_ASCII(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_Bytes")] pub fn PyObject_Bytes(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_RichCompare")] pub fn PyObject_RichCompare( arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_RichCompareBool")] pub fn PyObject_RichCompareBool(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_GetAttrString")] pub fn PyObject_GetAttrString(arg1: *mut PyObject, arg2: *const c_char) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_SetAttrString")] pub fn PyObject_SetAttrString( arg1: *mut PyObject, arg2: *const c_char, arg3: *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttrString")] pub fn PyObject_HasAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_GetAttr")] pub fn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_SetAttr")] pub fn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_HasAttr")] pub fn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_SelfIter")] pub fn PyObject_SelfIter(arg1: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_GenericGetAttr")] pub fn PyObject_GenericGetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_GenericSetAttr")] pub fn PyObject_GenericSetAttr( arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject, ) -> c_int; #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))] pub fn PyObject_GenericGetDict(arg1: *mut PyObject, arg2: *mut c_void) -> *mut PyObject; pub fn PyObject_GenericSetDict( arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut c_void, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_Hash")] pub fn PyObject_Hash(arg1: *mut PyObject) -> Py_hash_t; #[cfg_attr(PyPy, link_name = "PyPyObject_HashNotImplemented")] pub fn PyObject_HashNotImplemented(arg1: *mut PyObject) -> Py_hash_t; #[cfg_attr(PyPy, link_name = "PyPyObject_IsTrue")] pub fn PyObject_IsTrue(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_Not")] pub fn PyObject_Not(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyCallable_Check")] pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyObject_ClearWeakRefs")] pub fn PyObject_ClearWeakRefs(arg1: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPyObject_Dir")] pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject; pub fn Py_ReprEnter(arg1: *mut PyObject) -> c_int; pub fn Py_ReprLeave(arg1: *mut PyObject); } // Flag bits for printing: pub const Py_PRINT_RAW: c_int = 1; // No string quotes etc. #[cfg(all(Py_3_12, not(Py_LIMITED_API)))] pub const _Py_TPFLAGS_STATIC_BUILTIN: c_ulong = 1 << 1; #[cfg(all(Py_3_12, not(Py_LIMITED_API)))] pub const Py_TPFLAGS_MANAGED_WEAKREF: c_ulong = 1 << 3; #[cfg(all(Py_3_11, not(Py_LIMITED_API)))] pub const Py_TPFLAGS_MANAGED_DICT: c_ulong = 1 << 4; #[cfg(all(Py_3_10, not(Py_LIMITED_API)))] pub const Py_TPFLAGS_SEQUENCE: c_ulong = 1 << 5; #[cfg(all(Py_3_10, not(Py_LIMITED_API)))] pub const Py_TPFLAGS_MAPPING: c_ulong = 1 << 6; #[cfg(Py_3_10)] pub const Py_TPFLAGS_DISALLOW_INSTANTIATION: c_ulong = 1 << 7; #[cfg(Py_3_10)] pub const Py_TPFLAGS_IMMUTABLETYPE: c_ulong = 1 << 8; /// Set if the type object is dynamically allocated pub const Py_TPFLAGS_HEAPTYPE: c_ulong = 1 << 9; /// Set if the type allows subclassing pub const Py_TPFLAGS_BASETYPE: c_ulong = 1 << 10; /// Set if the type implements the vectorcall protocol (PEP 590) #[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))] pub const Py_TPFLAGS_HAVE_VECTORCALL: c_ulong = 1 << 11; // skipped non-limited _Py_TPFLAGS_HAVE_VECTORCALL /// Set if the type is 'ready' -- fully initialized pub const Py_TPFLAGS_READY: c_ulong = 1 << 12; /// Set while the type is being 'readied', to prevent recursive ready calls pub const Py_TPFLAGS_READYING: c_ulong = 1 << 13; /// Objects support garbage collection (see objimp.h) pub const Py_TPFLAGS_HAVE_GC: c_ulong = 1 << 14; const Py_TPFLAGS_HAVE_STACKLESS_EXTENSION: c_ulong = 0; #[cfg(Py_3_8)] pub const Py_TPFLAGS_METHOD_DESCRIPTOR: c_ulong = 1 << 17; pub const Py_TPFLAGS_VALID_VERSION_TAG: c_ulong = 1 << 19; /* Type is abstract and cannot be instantiated */ pub const Py_TPFLAGS_IS_ABSTRACT: c_ulong = 1 << 20; // skipped non-limited / 3.10 Py_TPFLAGS_HAVE_AM_SEND #[cfg(Py_3_12)] pub const Py_TPFLAGS_ITEMS_AT_END: c_ulong = 1 << 23; /* These flags are used to determine if a type is a subclass. */ pub const Py_TPFLAGS_LONG_SUBCLASS: c_ulong = 1 << 24; pub const Py_TPFLAGS_LIST_SUBCLASS: c_ulong = 1 << 25; pub const Py_TPFLAGS_TUPLE_SUBCLASS: c_ulong = 1 << 26; pub const Py_TPFLAGS_BYTES_SUBCLASS: c_ulong = 1 << 27; pub const Py_TPFLAGS_UNICODE_SUBCLASS: c_ulong = 1 << 28; pub const Py_TPFLAGS_DICT_SUBCLASS: c_ulong = 1 << 29; pub const Py_TPFLAGS_BASE_EXC_SUBCLASS: c_ulong = 1 << 30; pub const Py_TPFLAGS_TYPE_SUBCLASS: c_ulong = 1 << 31; pub const Py_TPFLAGS_DEFAULT: c_ulong = if cfg!(Py_3_10) { Py_TPFLAGS_HAVE_STACKLESS_EXTENSION } else { Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | Py_TPFLAGS_HAVE_VERSION_TAG }; pub const Py_TPFLAGS_HAVE_FINALIZE: c_ulong = 1; pub const Py_TPFLAGS_HAVE_VERSION_TAG: c_ulong = 1 << 18; extern "C" { #[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))] pub fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject); #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))] fn _Py_INCREF_IncRefTotal(); #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))] fn _Py_DECREF_DecRefTotal(); #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")] pub fn _Py_Dealloc(arg1: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPy_IncRef")] #[cfg_attr(GraalPy, link_name = "_Py_IncRef")] pub fn Py_IncRef(o: *mut PyObject); #[cfg_attr(PyPy, link_name = "PyPy_DecRef")] #[cfg_attr(GraalPy, link_name = "_Py_DecRef")] pub fn Py_DecRef(o: *mut PyObject); #[cfg(all(Py_3_10, not(PyPy)))] pub fn _Py_IncRef(o: *mut PyObject); #[cfg(all(Py_3_10, not(PyPy)))] pub fn _Py_DecRef(o: *mut PyObject); #[cfg(GraalPy)] pub fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t; #[cfg(GraalPy)] pub fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject; #[cfg(GraalPy)] pub fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t; } #[inline(always)] pub unsafe fn Py_INCREF(op: *mut PyObject) { // On limited API or with refcount debugging, let the interpreter do refcounting #[cfg(any(Py_LIMITED_API, py_sys_config = "Py_REF_DEBUG", GraalPy))] { // _Py_IncRef was added to the ABI in 3.10; skips null checks #[cfg(all(Py_3_10, not(PyPy)))] { _Py_IncRef(op); } #[cfg(any(not(Py_3_10), PyPy))] { Py_IncRef(op); } } // version-specific builds are allowed to directly manipulate the reference count #[cfg(not(any(any(Py_LIMITED_API, py_sys_config = "Py_REF_DEBUG", GraalPy))))] { #[cfg(all(Py_3_12, target_pointer_width = "64"))] { let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN]; let new_refcnt = cur_refcnt.wrapping_add(1); if new_refcnt == 0 { return; } (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt; } #[cfg(all(Py_3_12, target_pointer_width = "32"))] { if _Py_IsImmortal(op) != 0 { return; } (*op).ob_refcnt.ob_refcnt += 1 } #[cfg(not(Py_3_12))] { (*op).ob_refcnt += 1 } // Skipped _Py_INCREF_STAT_INC - if anyone wants this, please file an issue // or submit a PR supporting Py_STATS build option and pystats.h } } #[inline(always)] #[cfg_attr( all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)), track_caller )] pub unsafe fn Py_DECREF(op: *mut PyObject) { // On limited API or with refcount debugging, let the interpreter do refcounting // On 3.12+ we implement refcount debugging to get better assertion locations on negative refcounts #[cfg(any( Py_LIMITED_API, all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)), GraalPy ))] { // _Py_DecRef was added to the ABI in 3.10; skips null checks #[cfg(all(Py_3_10, not(PyPy)))] { _Py_DecRef(op); } #[cfg(any(not(Py_3_10), PyPy))] { Py_DecRef(op); } } #[cfg(not(any( Py_LIMITED_API, all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)), GraalPy )))] { #[cfg(Py_3_12)] if _Py_IsImmortal(op) != 0 { return; } // Skipped _Py_DECREF_STAT_INC - if anyone needs this, please file an issue // or submit a PR supporting Py_STATS build option and pystats.h #[cfg(py_sys_config = "Py_REF_DEBUG")] _Py_DECREF_DecRefTotal(); #[cfg(Py_3_12)] { (*op).ob_refcnt.ob_refcnt -= 1; #[cfg(py_sys_config = "Py_REF_DEBUG")] if (*op).ob_refcnt.ob_refcnt < 0 { let location = std::panic::Location::caller(); let filename = std::ffi::CString::new(location.file()).unwrap(); _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op); } if (*op).ob_refcnt.ob_refcnt == 0 { _Py_Dealloc(op); } } #[cfg(not(Py_3_12))] { (*op).ob_refcnt -= 1; if (*op).ob_refcnt == 0 { _Py_Dealloc(op); } } } } #[inline] pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) { let tmp = *op; if !tmp.is_null() { *op = ptr::null_mut(); Py_DECREF(tmp); } } #[inline] pub unsafe fn Py_XINCREF(op: *mut PyObject) { if !op.is_null() { Py_INCREF(op) } } #[inline] pub unsafe fn Py_XDECREF(op: *mut PyObject) { if !op.is_null() { Py_DECREF(op) } } extern "C" { #[cfg(all(Py_3_10, Py_LIMITED_API))] pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject; #[cfg(all(Py_3_10, Py_LIMITED_API))] pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject; } // Technically these macros are only available in the C header from 3.10 and up, however their // implementation works on all supported Python versions so we define these macros on all // versions for simplicity. #[inline] pub unsafe fn _Py_NewRef(obj: *mut PyObject) -> *mut PyObject { Py_INCREF(obj); obj } #[inline] pub unsafe fn _Py_XNewRef(obj: *mut PyObject) -> *mut PyObject { Py_XINCREF(obj); obj } #[cfg(all(Py_3_10, not(Py_LIMITED_API)))] #[inline] pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject { _Py_NewRef(obj) } #[cfg(all(Py_3_10, not(Py_LIMITED_API)))] #[inline] pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject { _Py_XNewRef(obj) } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_NoneStruct")] static mut _Py_NoneStruct: PyObject; #[cfg(GraalPy)] static mut _Py_NoneStructReference: *mut PyObject; } #[inline] pub unsafe fn Py_None() -> *mut PyObject { #[cfg(not(GraalPy))] return ptr::addr_of_mut!(_Py_NoneStruct); #[cfg(GraalPy)] return _Py_NoneStructReference; } #[inline] pub unsafe fn Py_IsNone(x: *mut PyObject) -> c_int { Py_Is(x, Py_None()) } // skipped Py_RETURN_NONE #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[cfg(not(GraalPy))] #[cfg_attr(PyPy, link_name = "_PyPy_NotImplementedStruct")] static mut _Py_NotImplementedStruct: PyObject; #[cfg(GraalPy)] static mut _Py_NotImplementedStructReference: *mut PyObject; } #[inline] pub unsafe fn Py_NotImplemented() -> *mut PyObject { #[cfg(not(GraalPy))] return ptr::addr_of_mut!(_Py_NotImplementedStruct); #[cfg(GraalPy)] return _Py_NotImplementedStructReference; } // skipped Py_RETURN_NOTIMPLEMENTED /* Rich comparison opcodes */ pub const Py_LT: c_int = 0; pub const Py_LE: c_int = 1; pub const Py_EQ: c_int = 2; pub const Py_NE: c_int = 3; pub const Py_GT: c_int = 4; pub const Py_GE: c_int = 5; #[cfg(Py_3_10)] #[repr(C)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PySendResult { PYGEN_RETURN = 0, PYGEN_ERROR = -1, PYGEN_NEXT = 1, } // skipped Py_RETURN_RICHCOMPARE #[inline] #[cfg(Py_LIMITED_API)] pub unsafe fn PyType_HasFeature(t: *mut PyTypeObject, f: c_ulong) -> c_int { ((PyType_GetFlags(t) & f) != 0) as c_int } #[inline] #[cfg(not(Py_LIMITED_API))] pub unsafe fn PyType_HasFeature(t: *mut PyTypeObject, f: c_ulong) -> c_int { (((*t).tp_flags & f) != 0) as c_int } #[inline] pub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_ulong) -> c_int { PyType_HasFeature(t, f) } #[inline] pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int { PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS) } #[inline] pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int { Py_IS_TYPE(op, ptr::addr_of_mut!(PyType_Type)) } pyo3-ffi/src/objimpl.rs0000644000175000017500000000627014661133735015773 0ustar jamespagejamespageuse libc::size_t; use std::os::raw::{c_int, c_void}; use crate::object::*; use crate::pyport::Py_ssize_t; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyObject_Malloc")] pub fn PyObject_Malloc(size: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyObject_Calloc")] pub fn PyObject_Calloc(nelem: size_t, elsize: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyObject_Realloc")] pub fn PyObject_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void; #[cfg_attr(PyPy, link_name = "PyPyObject_Free")] pub fn PyObject_Free(ptr: *mut c_void); // skipped PyObject_MALLOC // skipped PyObject_REALLOC // skipped PyObject_FREE // skipped PyObject_Del // skipped PyObject_DEL #[cfg_attr(PyPy, link_name = "PyPyObject_Init")] pub fn PyObject_Init(arg1: *mut PyObject, arg2: *mut PyTypeObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyObject_InitVar")] pub fn PyObject_InitVar( arg1: *mut PyVarObject, arg2: *mut PyTypeObject, arg3: Py_ssize_t, ) -> *mut PyVarObject; // skipped PyObject_INIT // skipped PyObject_INIT_VAR #[cfg_attr(PyPy, link_name = "_PyPyObject_New")] pub fn _PyObject_New(arg1: *mut PyTypeObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "_PyPyObject_NewVar")] pub fn _PyObject_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject; // skipped PyObject_New // skipped PyObject_NEW // skipped PyObject_NewVar // skipped PyObject_NEW_VAR pub fn PyGC_Collect() -> Py_ssize_t; #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "PyPyGC_Enable")] pub fn PyGC_Enable() -> c_int; #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "PyPyGC_Disable")] pub fn PyGC_Disable() -> c_int; #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "PyPyGC_IsEnabled")] pub fn PyGC_IsEnabled() -> c_int; // skipped PyUnstable_GC_VisitObjects } #[inline] pub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int { PyType_HasFeature(t, Py_TPFLAGS_HAVE_GC) } extern "C" { pub fn _PyObject_GC_Resize(arg1: *mut PyVarObject, arg2: Py_ssize_t) -> *mut PyVarObject; // skipped PyObject_GC_Resize #[cfg_attr(PyPy, link_name = "_PyPyObject_GC_New")] pub fn _PyObject_GC_New(arg1: *mut PyTypeObject) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "_PyPyObject_GC_NewVar")] pub fn _PyObject_GC_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject; #[cfg(not(PyPy))] pub fn PyObject_GC_Track(arg1: *mut c_void); #[cfg(not(PyPy))] pub fn PyObject_GC_UnTrack(arg1: *mut c_void); #[cfg_attr(PyPy, link_name = "PyPyObject_GC_Del")] pub fn PyObject_GC_Del(arg1: *mut c_void); // skipped PyObject_GC_New // skipped PyObject_GC_NewVar #[cfg(any(all(Py_3_9, not(PyPy)), Py_3_10))] // added in 3.9, or 3.10 on PyPy #[cfg_attr(PyPy, link_name = "PyPyObject_GC_IsTracked")] pub fn PyObject_GC_IsTracked(arg1: *mut PyObject) -> c_int; #[cfg(any(all(Py_3_9, not(PyPy)), Py_3_10))] // added in 3.9, or 3.10 on PyPy #[cfg_attr(PyPy, link_name = "PyPyObject_GC_IsFinalized")] pub fn PyObject_GC_IsFinalized(arg1: *mut PyObject) -> c_int; } // skipped Py_VISIT pyo3-ffi/src/modsupport.rs0000644000175000017500000001266614661133735016561 0ustar jamespagejamespageuse crate::methodobject::PyMethodDef; use crate::moduleobject::PyModuleDef; use crate::object::PyObject; use crate::pyport::Py_ssize_t; use std::os::raw::{c_char, c_int, c_long}; extern "C" { #[cfg_attr(PyPy, link_name = "PyPyArg_Parse")] pub fn PyArg_Parse(arg1: *mut PyObject, arg2: *const c_char, ...) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyArg_ParseTuple")] pub fn PyArg_ParseTuple(arg1: *mut PyObject, arg2: *const c_char, ...) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyArg_ParseTupleAndKeywords")] pub fn PyArg_ParseTupleAndKeywords( arg1: *mut PyObject, arg2: *mut PyObject, arg3: *const c_char, arg4: *mut *mut c_char, ... ) -> c_int; pub fn PyArg_ValidateKeywordArguments(arg1: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyArg_UnpackTuple")] pub fn PyArg_UnpackTuple( arg1: *mut PyObject, arg2: *const c_char, arg3: Py_ssize_t, arg4: Py_ssize_t, ... ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPy_BuildValue")] pub fn Py_BuildValue(arg1: *const c_char, ...) -> *mut PyObject; // #[cfg_attr(PyPy, link_name = "_PyPy_BuildValue_SizeT")] //pub fn _Py_BuildValue_SizeT(arg1: *const c_char, ...) // -> *mut PyObject; // #[cfg_attr(PyPy, link_name = "PyPy_VaBuildValue")] // skipped non-limited _PyArg_UnpackStack // skipped non-limited _PyArg_NoKeywords // skipped non-limited _PyArg_NoKwnames // skipped non-limited _PyArg_NoPositional // skipped non-limited _PyArg_BadArgument // skipped non-limited _PyArg_CheckPositional //pub fn Py_VaBuildValue(arg1: *const c_char, arg2: va_list) // -> *mut PyObject; // skipped non-limited _Py_VaBuildStack // skipped non-limited _PyArg_Parser // skipped non-limited _PyArg_ParseTupleAndKeywordsFast // skipped non-limited _PyArg_ParseStack // skipped non-limited _PyArg_ParseStackAndKeywords // skipped non-limited _PyArg_VaParseTupleAndKeywordsFast // skipped non-limited _PyArg_UnpackKeywords // skipped non-limited _PyArg_Fini #[cfg(Py_3_10)] #[cfg_attr(PyPy, link_name = "PyPyModule_AddObjectRef")] pub fn PyModule_AddObjectRef( module: *mut PyObject, name: *const c_char, value: *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyModule_AddObject")] pub fn PyModule_AddObject( module: *mut PyObject, name: *const c_char, value: *mut PyObject, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyModule_AddIntConstant")] pub fn PyModule_AddIntConstant( module: *mut PyObject, name: *const c_char, value: c_long, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyModule_AddStringConstant")] pub fn PyModule_AddStringConstant( module: *mut PyObject, name: *const c_char, value: *const c_char, ) -> c_int; #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))] #[cfg_attr(PyPy, link_name = "PyPyModule_AddType")] pub fn PyModule_AddType( module: *mut PyObject, type_: *mut crate::object::PyTypeObject, ) -> c_int; // skipped PyModule_AddIntMacro // skipped PyModule_AddStringMacro pub fn PyModule_SetDocString(arg1: *mut PyObject, arg2: *const c_char) -> c_int; pub fn PyModule_AddFunctions(arg1: *mut PyObject, arg2: *mut PyMethodDef) -> c_int; pub fn PyModule_ExecDef(module: *mut PyObject, def: *mut PyModuleDef) -> c_int; } pub const Py_CLEANUP_SUPPORTED: i32 = 0x2_0000; pub const PYTHON_API_VERSION: i32 = 1013; pub const PYTHON_ABI_VERSION: i32 = 3; extern "C" { #[cfg(not(py_sys_config = "Py_TRACE_REFS"))] #[cfg_attr(PyPy, link_name = "PyPyModule_Create2")] pub fn PyModule_Create2(module: *mut PyModuleDef, apiver: c_int) -> *mut PyObject; #[cfg(py_sys_config = "Py_TRACE_REFS")] fn PyModule_Create2TraceRefs(module: *mut PyModuleDef, apiver: c_int) -> *mut PyObject; #[cfg(not(py_sys_config = "Py_TRACE_REFS"))] pub fn PyModule_FromDefAndSpec2( def: *mut PyModuleDef, spec: *mut PyObject, module_api_version: c_int, ) -> *mut PyObject; #[cfg(py_sys_config = "Py_TRACE_REFS")] fn PyModule_FromDefAndSpec2TraceRefs( def: *mut PyModuleDef, spec: *mut PyObject, module_api_version: c_int, ) -> *mut PyObject; } #[cfg(py_sys_config = "Py_TRACE_REFS")] #[inline] pub unsafe fn PyModule_Create2(module: *mut PyModuleDef, apiver: c_int) -> *mut PyObject { PyModule_Create2TraceRefs(module, apiver) } #[cfg(py_sys_config = "Py_TRACE_REFS")] #[inline] pub unsafe fn PyModule_FromDefAndSpec2( def: *mut PyModuleDef, spec: *mut PyObject, module_api_version: c_int, ) -> *mut PyObject { PyModule_FromDefAndSpec2TraceRefs(def, spec, module_api_version) } #[inline] pub unsafe fn PyModule_Create(module: *mut PyModuleDef) -> *mut PyObject { PyModule_Create2( module, if cfg!(Py_LIMITED_API) { PYTHON_ABI_VERSION } else { PYTHON_API_VERSION }, ) } #[inline] pub unsafe fn PyModule_FromDefAndSpec(def: *mut PyModuleDef, spec: *mut PyObject) -> *mut PyObject { PyModule_FromDefAndSpec2( def, spec, if cfg!(Py_LIMITED_API) { PYTHON_ABI_VERSION } else { PYTHON_API_VERSION }, ) } #[cfg(not(Py_LIMITED_API))] #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut _Py_PackageContext: *const c_char; } pyo3-ffi/src/fileobject.rs0000644000175000017500000000254614661133735016447 0ustar jamespagejamespageuse crate::object::PyObject; use std::os::raw::{c_char, c_int}; pub const PY_STDIOTEXTMODE: &str = "b"; extern "C" { pub fn PyFile_FromFd( arg1: c_int, arg2: *const c_char, arg3: *const c_char, arg4: c_int, arg5: *const c_char, arg6: *const c_char, arg7: *const c_char, arg8: c_int, ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyFile_GetLine")] pub fn PyFile_GetLine(arg1: *mut PyObject, arg2: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyFile_WriteObject")] pub fn PyFile_WriteObject(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyFile_WriteString")] pub fn PyFile_WriteString(arg1: *const c_char, arg2: *mut PyObject) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyFile_AsFileDescriptor")] pub fn PyObject_AsFileDescriptor(arg1: *mut PyObject) -> c_int; } #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { #[deprecated(note = "Python 3.12")] pub static mut Py_FileSystemDefaultEncoding: *const c_char; #[deprecated(note = "Python 3.12")] pub static mut Py_FileSystemDefaultEncodeErrors: *const c_char; #[deprecated(note = "Python 3.12")] pub static mut Py_HasFileSystemDefaultEncoding: c_int; // skipped 3.12-deprecated Py_UTF8Mode } // skipped _PyIsSelectable_fd pyo3-ffi/.cargo-checksum.json0000664000175000017500000001765614661133735017062 0ustar jamespagejamespage{"files":{"ACKNOWLEDGEMENTS":"a895ab531efd09aae5db905f6a62033d81469c233d42a5c200e1b1965a145020","Cargo.toml":"4d0ec7cc0a09d72d333ff7f546959b9e219ae965fa5e4cc1c8041bedb4b70564","LICENSE-APACHE":"71073d492e996de196dbe1eb1e4c94c27c014c841b288161265b2efd06d0af28","LICENSE-MIT":"afcbe3b2e6b37172b5a9ca869ee4c0b8cdc09316e5d4384864154482c33e5af6","README.md":"d99baee4eea74af6c3b4da3436d7b83f133d1b703bf29b23d9c9b01eba921a5b","build.rs":"574cf8bf024d9d7ad7d35cc21b8d15a5947d620a09d0cd947d579dcfd6a92165","src/abstract_.rs":"dcb44cb9e6b9fee5ced3b8f19118cd9a624e262564ca11c3f0853ed0d9d1af98","src/bltinmodule.rs":"05f18e034fffafba89d8255a7502b05d6debec5ef79f37c9657fd605f2a6a39b","src/boolobject.rs":"eb86795b67f8de0063d02e6292e820f7334397756dd3ff7cf0949ef1ca9f4b99","src/bytearrayobject.rs":"2d21f6cf75fd1c98b203dde5fa6ef8b6029178c9468e28c9170be3b8958c4392","src/bytesobject.rs":"88a9d10e750d7d7917a6dd0d1259a1f86f3ca6a593a8b37c92356569bc2c5071","src/ceval.rs":"a2abc504100b91898e3c924af39348cfbd01125c13fc1389f3781d7bd6c78f6c","src/code.rs":"c6aba4ad96f04ca282e23829d6e92c8028d938b14b0698802582eae7eacb169e","src/codecs.rs":"0c86ae7c1d3d67be9a2ac3c80f6ccdd77aa0c72c46b8dc37eda23eb7619ab0b2","src/compile.rs":"9a7bdc36c8a7c9d0ae14c6db8d9c712d947458b424c8d1348f207c62c9c97b3b","src/complexobject.rs":"1336802508f77798ebd3534bca9593475ae0646a9dcb5254cdd3562bd53dcf86","src/context.rs":"12cac9b5b794d869492a7714227ef0375d41c4a13f22193523ac2b539f52b004","src/cpython/abstract_.rs":"42544ef211afba24ed1517682faa007935e8cd77ab006d5874333b62475ccdb7","src/cpython/bytesobject.rs":"85a0563f6780067b4d0f49792f6bab1d28c9de9a819aa512e4cf47effeb4e7f0","src/cpython/ceval.rs":"3cf69dc673e8cfcb0d40307dc7955526ed3002074d65cb277c282eaabd766160","src/cpython/code.rs":"136d26569c740bbfe4f4f5ffc9762404f31cdcb1b87cce26e44f9899da1e0c41","src/cpython/compile.rs":"ceeed293bb892d49ca9732489962fcb2277fe12d3c6c48f0e7828c2701d8dbb0","src/cpython/descrobject.rs":"ff8341bcf19600cbaddcc02164ff0e789b0c1ec3502537076c4bc57bb5c14570","src/cpython/dictobject.rs":"da456b35dc3f38df95e70bd958514eb627582fea437f4e6173b9ee42d1f2c88e","src/cpython/floatobject.rs":"8a835a937c05d8d6ebbe4fc15c011f019353077da55e074b29011dfddd452ed9","src/cpython/frameobject.rs":"eabc089c5a6beecbe74be31d09ce5c29c35c7dc2a160d9600b4f787a53f2c17d","src/cpython/funcobject.rs":"26794f50e0bffcd48ef9f475d0d101a634d19bf26b8fb6ddc1cb1a3fb3d22146","src/cpython/genobject.rs":"d2bf0214e0cefbad85b6ecfb66fd94ce3ce5c80afe1f1dd6afaaaf62a05dde23","src/cpython/import.rs":"713f0c93e097b1044cdd0e12954865de3fb07595d2dae2dd9f16d14c99a9ae6a","src/cpython/initconfig.rs":"e6a113b30b749aadc7b29d02fb1af2dd9f705fbe0c46ea5e0104b2e875af8a44","src/cpython/listobject.rs":"8bcbd9051dad1cc18c0f4fd4522182fce51b848d49d4252e05eb4624269a0cbc","src/cpython/longobject.rs":"79c16a61a16b103c554c944fd6452f861b1291e182c088a5e270a429580bd227","src/cpython/methodobject.rs":"98d9e9e2d4847ad79999d93d77129051a278631e4260618c2a13b7bbc55da388","src/cpython/mod.rs":"5e61a2ae53017dee57cf4e80711de92fa432628f3b77a854707e7dc4edc17237","src/cpython/object.rs":"3a4eafc8b498f0583ff8df928ff87cf53d88c4afeb78152484d7b10c1e963e8e","src/cpython/objimpl.rs":"d4ae9eb02b3ad44b3beffa2482ea1630c794c3e144fa3091c30b435175e1f064","src/cpython/pydebug.rs":"041988d8ee709ce499b729942b2f815be97d9b1f26e060db93813aa93d850c1f","src/cpython/pyerrors.rs":"de324e847b518f751061faa6703e1da0b5810765ea236d2598af82ec42613f54","src/cpython/pyframe.rs":"d99e567a14a3fbf6dfecf9342c4fa5839f55ac0f64cc22fe28dac8b27751a187","src/cpython/pylifecycle.rs":"c6440b0085c69d41dcdbf9622fcb8da7d16e8252bf511e1c61c0a945ce362d66","src/cpython/pymem.rs":"c42c0b888050bfd4ea5e3275ed1d032b7ec94714bdc4a826517ddb2541bab59e","src/cpython/pystate.rs":"371d81e613fe9a083413eaeb49c2a50523663f6fdf7b6e1aee266414e6efdaf6","src/cpython/pythonrun.rs":"eaafea0d771d421374e0afd650a72860c8b264ff647c1d2375a95035ff8524fd","src/cpython/tupleobject.rs":"9fdc041252a1b47ff8937e4968d6e0f973a5910e09979431972121749fd22aa6","src/cpython/unicodeobject.rs":"4be616fe2587aada9793206b2c1197302a3b8f05a256f5422a03351c299e580d","src/cpython/weakrefobject.rs":"11ce78dd6fe41941cc03b9f09571653e6ee921a3d9e181b9649f96d0f42b88e0","src/datetime.rs":"1d64077a0d5f67434dbb97ac6bb15f8eda66530572e4b7ec2604f7356af1c580","src/descrobject.rs":"3abc7bd7fa71a61352a438b100fff2643a24fd79409403833dd6708b7602dac9","src/dictobject.rs":"505a382e72a2d4fb2f27dd5bae2631775bc8d5ad5a8b7b1214f6dd034db10266","src/enumobject.rs":"1c0f2ab3f7ab48d92147a3bebc0c0f1251adfed6904d53a9b2bf64f32560aeda","src/fileobject.rs":"494421b1779b93e8f27d052c53c857e83b5bb2c7a47870ff00ecbcd320042afe","src/fileutils.rs":"ebec882c3f1ab47686da7bd05dec5f87f653fd115c26c3a1e475aadbf8dd729d","src/floatobject.rs":"cedc182ffeb692386c0f2e588431e18652945739adb3c412401521e3f12a5fcb","src/import.rs":"94b49da77ae6f997d0efcbb6892e3b76973891e03a16f0c7c4a31c3a8ab747f5","src/intrcheck.rs":"0b4e6ca30e123caf1892ab58cf53245f94b456d00333b93058965c08721a3523","src/iterobject.rs":"df4f345519a755ee43acde00c79480bebb34e9f21772f753820e652f4395741f","src/lib.rs":"334868fb6653b99cc92a33ffc7642fb4364219aea3119068b9e7a459c981cd1b","src/listobject.rs":"5e670e009256234c66bef48ee58737888a4517834d3c8a080f664388014dabc2","src/longobject.rs":"87214099920429c5743f812ff461f75e51724abc9c46faceaa49faf972312a5c","src/marshal.rs":"d1a51042497871a33adcd16f4c35e373405f5143be2c9666d4e726dbd3636aa6","src/memoryobject.rs":"db28fc4acd66464db2cab64f36db1a5548ca866ae4f388b99254fad7f77b11d1","src/methodobject.rs":"0871092d2f6a904e53ee466c48e586ca0b6dc540926d8a5d0506bc203b21991a","src/modsupport.rs":"f8c5d909d77660d0891f345b33caf9329b728f7224e7eaca7116aabbeb8ec83b","src/moduleobject.rs":"4ecc0512f36e29bbdfc4c86a4bb93ce471cd15ec4ab4494da64e8181b5fd89a8","src/object.rs":"e50e1d21d3cf24d6ac7103e9665699c4fc63c050dfd37c74e59829f248176b7d","src/objimpl.rs":"534a7c422cfd386aa39826d6d4070c9f3f3b9a5bedeb9413a307ede89e97b267","src/osmodule.rs":"522f0e9265167d67675d01c14f657a31a95795e3dec423dee8af7f830f6946ac","src/pyarena.rs":"53b929cf467bdb3fe7dc5fc22720dddeb6d43836d5e741f291d231c38462c4ab","src/pybuffer.rs":"743af6a4d8db9369a68e9f901353faa3729952566cbf79c466411624e6dce318","src/pycapsule.rs":"47191e027a978ecb2e03efdb9e2853bef68e305ee519b12ed2241801bc48c2db","src/pyerrors.rs":"4042fedff51feb1fc9e3b0f45cebde528568d05fa3ffdff155a28f10f47ec1c5","src/pyframe.rs":"e499a377fda6bd3d08f05f4fc289f3779c9bdf959da364bdd336b4576d07d344","src/pyhash.rs":"5f2180ea34f31edd5488703813f3c9f9d2d352455880d797f1687021495d653a","src/pylifecycle.rs":"a6c40c102d61095adbc7237c1b1cfcad5dc85d8af0cf089505a718b6cf0f00c3","src/pymem.rs":"ae18180aded033401a5354bbb4ab313f07af2ac29b7e8f1216964308124a12f1","src/pyport.rs":"d9b452351def5bc870cbc6d8a7ee4b50fbf6e469843e09edc8cdd6ce6c50d581","src/pystate.rs":"0f37aea4ed472ad38b25f794cdbac0cfbb973597f837f0a10b6164c08fe2aa9b","src/pystrtod.rs":"b29ccd17fc7d82642b5d167fb77d1071acab57c4fa6e56a5309c265aeb483aa3","src/pythonrun.rs":"677949f4a855d437373b15ece75a77a33c55162b7b0c4b0f034409f032cff0af","src/rangeobject.rs":"80761feb600397deb2a940cf94ede3693c47c4920be0a95cf5dbe3f123a6b1c1","src/setobject.rs":"d11fee4b430a6ec1567e5442743219f1bf4b1eeb1968e1948dcc22bef043f987","src/sliceobject.rs":"17c975f8cf0caa566ea6d0ac365b787b7bd4d5612333adfd80f1e6c4cc8e05e7","src/structmember.rs":"264e411d84160f91f992d8bf08f2c2c54b259a802dc77ded5267d32cc3115b7a","src/structseq.rs":"18af9ba6509f683eff0ba45c123953ca21f97586807560a6432975de88f617f6","src/sysmodule.rs":"22b2e98c23f0a6e15fcd2c068c4cae39a5e20f2cad5be25925aea8309d1dd8fd","src/traceback.rs":"0b5fd918f33d88784e0eeb62c7d91ef55fa33aa9ead274cea1ad87fd88004a77","src/tupleobject.rs":"e2fb9e8ca46aaaf828f9eef3b5f35d9cbb4f2ae324b3cc6b8e58e0788c0a8c25","src/typeslots.rs":"0fb9ad514b91d07f4465398276a9c8e40969da3dd30216cbfe905e998e4c9d80","src/unicodeobject.rs":"f7776ec49fdc7165a97d01eb945322ef72d596eab596e4a6c14b5ef1ca76d97a","src/warnings.rs":"7e53c5a45da1af53110ab09d8d7485bfbf0154a7f0e531ac9b74f3b953ab4d11","src/weakrefobject.rs":"aab75292df622b3656260f3e0a9ed98bf67f40810ed0ae5f798c1a0bd92e28a1"},"package":"5e97e919d2df92eb88ca80a037969f44e5e70356559654962cbb3316d00300c6"}pyo3-macros/0000775000175000017500000000000014661133735013717 5ustar jamespagejamespagepyo3-macros/LICENSE-APACHE0000644000175000017500000002503514661133735015646 0ustar jamespagejamespage Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. pyo3-macros/Cargo.toml0000644000175000017500000000361314661133735015650 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "pyo3-macros" version = "0.22.2" authors = ["PyO3 Project and Contributors "] description = "Proc macros for PyO3 package" homepage = "https://github.com/pyo3/pyo3" keywords = [ "pyo3", "python", "cpython", "ffi", ] categories = [ "api-bindings", "development-tools::ffi", ] license = "MIT OR Apache-2.0" repository = "https://github.com/pyo3/pyo3" [lib] proc-macro = true [dependencies.proc-macro2] version = "1.0.60" default-features = false [dependencies.pyo3-macros-backend] version = "=0.22.2" [dependencies.quote] version = "1" [dependencies.syn] version = "2" features = [ "full", "extra-traits", ] [features] experimental-async = ["pyo3-macros-backend/experimental-async"] gil-refs = ["pyo3-macros-backend/gil-refs"] multiple-pymethods = [] [lints.clippy] checked_conversions = "warn" dbg_macro = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" let_unit_value = "warn" manual_assert = "warn" manual_ok_or = "warn" todo = "warn" unnecessary_wraps = "warn" used_underscore_binding = "warn" useless_transmute = "warn" [lints.rust] elided_lifetimes_in_paths = "warn" invalid_doc_attributes = "warn" rust_2021_prelude_collisions = "warn" unused_lifetimes = "warn" [lints.rust.rust_2018_idioms] level = "warn" priority = -1 [lints.rustdoc] bare_urls = "warn" broken_intra_doc_links = "warn" pyo3-macros/LICENSE-MIT0000644000175000017500000000212314661133735015347 0ustar jamespagejamespageCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3-macros/src/0000775000175000017500000000000014661133735014506 5ustar jamespagejamespagepyo3-macros/src/lib.rs0000644000175000017500000002314614661133735015626 0ustar jamespagejamespage//! This crate declares only the proc macro attributes, as a crate defining proc macro attributes //! must not contain any other public items. #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; use pyo3_macros_backend::{ build_derive_from_pyobject, build_py_class, build_py_enum, build_py_function, build_py_methods, pymodule_function_impl, pymodule_module_impl, PyClassArgs, PyClassMethodsType, PyFunctionOptions, PyModuleOptions, }; use quote::quote; use syn::{parse_macro_input, Item}; /// A proc macro used to implement Python modules. /// /// The name of the module will be taken from the function name, unless `#[pyo3(name = "my_name")]` /// is also annotated on the function to override the name. **Important**: the module name should /// match the `lib.name` setting in `Cargo.toml`, so that Python is able to import the module /// without needing a custom import loader. /// /// Functions annotated with `#[pymodule]` can also be annotated with the following: /// /// | Annotation | Description | /// | :- | :- | /// | `#[pyo3(name = "...")]` | Defines the name of the module in Python. | /// | `#[pyo3(submodule)]` | Skips adding a `PyInit_` FFI symbol to the compiled binary. | /// | `#[pyo3(module = "...")]` | Defines the Python `dotted.path` to the parent module for use in introspection. | /// | `#[pyo3(crate = "pyo3")]` | Defines the path to PyO3 to use code generated by the macro. | /// /// For more on creating Python modules see the [module section of the guide][1]. /// /// Due to technical limitations on how `#[pymodule]` is implemented, a function marked /// `#[pymodule]` cannot have a module with the same name in the same scope. (The /// `#[pymodule]` implementation generates a hidden module with the same name containing /// metadata about the module, which is used by `wrap_pymodule!`). /// #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/module.html")] #[proc_macro_attribute] pub fn pymodule(args: TokenStream, input: TokenStream) -> TokenStream { let options = parse_macro_input!(args as PyModuleOptions); let mut ast = parse_macro_input!(input as Item); let expanded = match &mut ast { Item::Mod(module) => { match pymodule_module_impl(module, options) { // #[pymodule] on a module will rebuild the original ast, so we don't emit it here Ok(expanded) => return expanded.into(), Err(e) => Err(e), } } Item::Fn(function) => pymodule_function_impl(function, options), unsupported => Err(syn::Error::new_spanned( unsupported, "#[pymodule] only supports modules and functions.", )), } .unwrap_or_compile_error(); quote!( #ast #expanded ) .into() } #[proc_macro_attribute] pub fn pyclass(attr: TokenStream, input: TokenStream) -> TokenStream { let item = parse_macro_input!(input as Item); match item { Item::Struct(struct_) => pyclass_impl(attr, struct_, methods_type()), Item::Enum(enum_) => pyclass_enum_impl(attr, enum_, methods_type()), unsupported => { syn::Error::new_spanned(unsupported, "#[pyclass] only supports structs and enums.") .into_compile_error() .into() } } } /// A proc macro used to expose methods to Python. /// /// Methods within a `#[pymethods]` block can be annotated with as well as the following: /// /// | Annotation | Description | /// | :- | :- | /// | [`#[new]`][4] | Defines the class constructor, like Python's `__new__` method. | /// | [`#[getter]`][5] and [`#[setter]`][5] | These define getters and setters, similar to Python's `@property` decorator. This is useful for getters/setters that require computation or side effects; if that is not the case consider using [`#[pyo3(get, set)]`][11] on the struct's field(s).| /// | [`#[staticmethod]`][6]| Defines the method as a staticmethod, like Python's `@staticmethod` decorator.| /// | [`#[classmethod]`][7] | Defines the method as a classmethod, like Python's `@classmethod` decorator.| /// | [`#[classattr]`][9] | Defines a class variable. | /// | [`#[args]`][10] | Deprecated way to define a method's default arguments and allows the function to receive `*args` and `**kwargs`. Use `#[pyo3(signature = (...))]` instead. | /// | [`#[pyo3( | Any of the `#[pyo3]` options supported on [`macro@pyfunction`]. | /// /// For more on creating class methods, /// see the [class section of the guide][1]. /// /// If the [`multiple-pymethods`][2] feature is enabled, it is possible to implement /// multiple `#[pymethods]` blocks for a single `#[pyclass]`. /// This will add a transitive dependency on the [`inventory`][3] crate. /// #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#instance-methods")] #[doc = concat!("[2]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/features.html#multiple-pymethods")] /// [3]: https://docs.rs/inventory/ #[doc = concat!("[4]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#constructor")] #[doc = concat!("[5]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#object-properties-using-getter-and-setter")] #[doc = concat!("[6]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#static-methods")] #[doc = concat!("[7]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#class-methods")] #[doc = concat!("[8]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#callable-objects")] #[doc = concat!("[9]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#class-attributes")] #[doc = concat!("[10]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#method-arguments")] #[doc = concat!("[11]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#object-properties-using-pyo3get-set")] #[proc_macro_attribute] pub fn pymethods(attr: TokenStream, input: TokenStream) -> TokenStream { let methods_type = if cfg!(feature = "multiple-pymethods") { PyClassMethodsType::Inventory } else { PyClassMethodsType::Specialization }; pymethods_impl(attr, input, methods_type) } /// A proc macro used to expose Rust functions to Python. /// /// Functions annotated with `#[pyfunction]` can also be annotated with the following `#[pyo3]` /// options: /// /// | Annotation | Description | /// | :- | :- | /// | `#[pyo3(name = "...")]` | Defines the name of the function in Python. | /// | `#[pyo3(text_signature = "...")]` | Defines the `__text_signature__` attribute of the function in Python. | /// | `#[pyo3(pass_module)]` | Passes the module containing the function as a `&PyModule` first argument to the function. | /// /// For more on exposing functions see the [function section of the guide][1]. /// /// Due to technical limitations on how `#[pyfunction]` is implemented, a function marked /// `#[pyfunction]` cannot have a module with the same name in the same scope. (The /// `#[pyfunction]` implementation generates a hidden module with the same name containing /// metadata about the function, which is used by `wrap_pyfunction!`). /// #[doc = concat!("[1]: https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/function.html")] #[proc_macro_attribute] pub fn pyfunction(attr: TokenStream, input: TokenStream) -> TokenStream { let mut ast = parse_macro_input!(input as syn::ItemFn); let options = parse_macro_input!(attr as PyFunctionOptions); let expanded = build_py_function(&mut ast, options).unwrap_or_compile_error(); quote!( #ast #expanded ) .into() } #[proc_macro_derive(FromPyObject, attributes(pyo3))] pub fn derive_from_py_object(item: TokenStream) -> TokenStream { let ast = parse_macro_input!(item as syn::DeriveInput); let expanded = build_derive_from_pyobject(&ast).unwrap_or_compile_error(); quote!( #expanded ) .into() } fn pyclass_impl( attrs: TokenStream, mut ast: syn::ItemStruct, methods_type: PyClassMethodsType, ) -> TokenStream { let args = parse_macro_input!(attrs with PyClassArgs::parse_stuct_args); let expanded = build_py_class(&mut ast, args, methods_type).unwrap_or_compile_error(); quote!( #ast #expanded ) .into() } fn pyclass_enum_impl( attrs: TokenStream, mut ast: syn::ItemEnum, methods_type: PyClassMethodsType, ) -> TokenStream { let args = parse_macro_input!(attrs with PyClassArgs::parse_enum_args); let expanded = build_py_enum(&mut ast, args, methods_type).unwrap_or_compile_error(); quote!( #ast #expanded ) .into() } fn pymethods_impl( attr: TokenStream, input: TokenStream, methods_type: PyClassMethodsType, ) -> TokenStream { let mut ast = parse_macro_input!(input as syn::ItemImpl); // Apply all options as a #[pyo3] attribute on the ItemImpl // e.g. #[pymethods(crate = "crate")] impl Foo { } // -> #[pyo3(crate = "crate")] impl Foo { } let attr: TokenStream2 = attr.into(); ast.attrs.push(syn::parse_quote!( #[pyo3(#attr)] )); let expanded = build_py_methods(&mut ast, methods_type).unwrap_or_compile_error(); quote!( #ast #expanded ) .into() } fn methods_type() -> PyClassMethodsType { if cfg!(feature = "multiple-pymethods") { PyClassMethodsType::Inventory } else { PyClassMethodsType::Specialization } } trait UnwrapOrCompileError { fn unwrap_or_compile_error(self) -> TokenStream2; } impl UnwrapOrCompileError for syn::Result { fn unwrap_or_compile_error(self) -> TokenStream2 { self.unwrap_or_else(|e| e.into_compile_error()) } } pyo3-macros/.cargo-checksum.json0000664000175000017500000000063514661133735017567 0ustar jamespagejamespage{"files":{"Cargo.toml":"fc95f51f86567d3d6c3e73c0a3c54b68e787326102d0ac900c5226047ba95a37","LICENSE-APACHE":"71073d492e996de196dbe1eb1e4c94c27c014c841b288161265b2efd06d0af28","LICENSE-MIT":"afcbe3b2e6b37172b5a9ca869ee4c0b8cdc09316e5d4384864154482c33e5af6","src/lib.rs":"eba6061eafaf5066c78a9c296f43ada5c6c5aeb9ca5f86c2b094279cd280ad2e"},"package":"eb57983022ad41f9e683a599f2fd13c3664d7063a3ac5714cae4b7bee7d3f206"}pyo3-macros-backend/0000775000175000017500000000000014661133735015304 5ustar jamespagejamespagepyo3-macros-backend/build.rs0000644000175000017500000000015114661133735016744 0ustar jamespagejamespagefn main() { pyo3_build_config::print_expected_cfgs(); pyo3_build_config::print_feature_cfgs(); } pyo3-macros-backend/LICENSE-APACHE0000644000175000017500000002503514661133735017233 0ustar jamespagejamespage Copyright (c) 2017-present PyO3 Project and Contributors. https://github.com/PyO3 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. pyo3-macros-backend/Cargo.toml0000644000175000017500000000402414661133735017232 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "pyo3-macros-backend" version = "0.22.2" authors = ["PyO3 Project and Contributors "] description = "Code generation for PyO3 package" homepage = "https://github.com/pyo3/pyo3" keywords = [ "pyo3", "python", "cpython", "ffi", ] categories = [ "api-bindings", "development-tools::ffi", ] license = "MIT OR Apache-2.0" repository = "https://github.com/pyo3/pyo3" [dependencies.heck] version = "0.5" [dependencies.proc-macro2] version = "1.0.60" default-features = false [dependencies.pyo3-build-config] version = "=0.22.2" features = ["resolve-config"] [dependencies.quote] version = "1" default-features = false [dependencies.syn] version = "2.0.59" features = [ "derive", "parsing", "printing", "clone-impls", "full", "extra-traits", ] default-features = false [build-dependencies.pyo3-build-config] version = "=0.22.2" [features] experimental-async = [] gil-refs = [] [lints.clippy] checked_conversions = "warn" dbg_macro = "warn" explicit_into_iter_loop = "warn" explicit_iter_loop = "warn" filter_map_next = "warn" flat_map_option = "warn" let_unit_value = "warn" manual_assert = "warn" manual_ok_or = "warn" todo = "warn" unnecessary_wraps = "warn" used_underscore_binding = "warn" useless_transmute = "warn" [lints.rust] elided_lifetimes_in_paths = "warn" invalid_doc_attributes = "warn" rust_2021_prelude_collisions = "warn" unused_lifetimes = "warn" [lints.rust.rust_2018_idioms] level = "warn" priority = -1 [lints.rustdoc] bare_urls = "warn" broken_intra_doc_links = "warn" pyo3-macros-backend/LICENSE-MIT0000644000175000017500000000212314661133735016734 0ustar jamespagejamespageCopyright (c) 2023-present PyO3 Project and Contributors. https://github.com/PyO3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. pyo3-macros-backend/src/0000775000175000017500000000000014661133735016073 5ustar jamespagejamespagepyo3-macros-backend/src/pyfunction/0000775000175000017500000000000014661133735020271 5ustar jamespagejamespagepyo3-macros-backend/src/pyfunction/signature.rs0000644000175000017500000005112714661133735022644 0ustar jamespagejamespageuse proc_macro2::{Span, TokenStream}; use quote::ToTokens; use syn::{ ext::IdentExt, parse::{Parse, ParseStream}, punctuated::Punctuated, spanned::Spanned, Token, }; use crate::{ attributes::{kw, KeywordAttribute}, method::{FnArg, RegularArg}, }; #[derive(Clone)] pub struct Signature { paren_token: syn::token::Paren, pub items: Punctuated, } impl Parse for Signature { fn parse(input: ParseStream<'_>) -> syn::Result { let content; let paren_token = syn::parenthesized!(content in input); let items = content.parse_terminated(SignatureItem::parse, Token![,])?; Ok(Signature { paren_token, items }) } } impl ToTokens for Signature { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token .surround(tokens, |tokens| self.items.to_tokens(tokens)) } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SignatureItemArgument { pub ident: syn::Ident, pub eq_and_default: Option<(Token![=], syn::Expr)>, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SignatureItemPosargsSep { pub slash: Token![/], } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SignatureItemVarargsSep { pub asterisk: Token![*], } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SignatureItemVarargs { pub sep: SignatureItemVarargsSep, pub ident: syn::Ident, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SignatureItemKwargs { pub asterisks: (Token![*], Token![*]), pub ident: syn::Ident, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum SignatureItem { Argument(Box), PosargsSep(SignatureItemPosargsSep), VarargsSep(SignatureItemVarargsSep), Varargs(SignatureItemVarargs), Kwargs(SignatureItemKwargs), } impl Parse for SignatureItem { fn parse(input: ParseStream<'_>) -> syn::Result { let lookahead = input.lookahead1(); if lookahead.peek(Token![*]) { if input.peek2(Token![*]) { input.parse().map(SignatureItem::Kwargs) } else { let sep = input.parse()?; if input.is_empty() || input.peek(Token![,]) { Ok(SignatureItem::VarargsSep(sep)) } else { Ok(SignatureItem::Varargs(SignatureItemVarargs { sep, ident: input.parse()?, })) } } } else if lookahead.peek(Token![/]) { input.parse().map(SignatureItem::PosargsSep) } else { input.parse().map(SignatureItem::Argument) } } } impl ToTokens for SignatureItem { fn to_tokens(&self, tokens: &mut TokenStream) { match self { SignatureItem::Argument(arg) => arg.to_tokens(tokens), SignatureItem::Varargs(varargs) => varargs.to_tokens(tokens), SignatureItem::VarargsSep(sep) => sep.to_tokens(tokens), SignatureItem::Kwargs(kwargs) => kwargs.to_tokens(tokens), SignatureItem::PosargsSep(sep) => sep.to_tokens(tokens), } } } impl Parse for SignatureItemArgument { fn parse(input: ParseStream<'_>) -> syn::Result { Ok(Self { ident: input.parse()?, eq_and_default: if input.peek(Token![=]) { Some((input.parse()?, input.parse()?)) } else { None }, }) } } impl ToTokens for SignatureItemArgument { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); if let Some((eq, default)) = &self.eq_and_default { eq.to_tokens(tokens); default.to_tokens(tokens); } } } impl Parse for SignatureItemVarargsSep { fn parse(input: ParseStream<'_>) -> syn::Result { Ok(Self { asterisk: input.parse()?, }) } } impl ToTokens for SignatureItemVarargsSep { fn to_tokens(&self, tokens: &mut TokenStream) { self.asterisk.to_tokens(tokens); } } impl Parse for SignatureItemVarargs { fn parse(input: ParseStream<'_>) -> syn::Result { Ok(Self { sep: input.parse()?, ident: input.parse()?, }) } } impl ToTokens for SignatureItemVarargs { fn to_tokens(&self, tokens: &mut TokenStream) { self.sep.to_tokens(tokens); self.ident.to_tokens(tokens); } } impl Parse for SignatureItemKwargs { fn parse(input: ParseStream<'_>) -> syn::Result { Ok(Self { asterisks: (input.parse()?, input.parse()?), ident: input.parse()?, }) } } impl ToTokens for SignatureItemKwargs { fn to_tokens(&self, tokens: &mut TokenStream) { self.asterisks.0.to_tokens(tokens); self.asterisks.1.to_tokens(tokens); self.ident.to_tokens(tokens); } } impl Parse for SignatureItemPosargsSep { fn parse(input: ParseStream<'_>) -> syn::Result { Ok(Self { slash: input.parse()?, }) } } impl ToTokens for SignatureItemPosargsSep { fn to_tokens(&self, tokens: &mut TokenStream) { self.slash.to_tokens(tokens); } } pub type SignatureAttribute = KeywordAttribute; pub type ConstructorAttribute = KeywordAttribute; impl ConstructorAttribute { pub fn into_signature(self) -> SignatureAttribute { SignatureAttribute { kw: kw::signature(self.kw.span), value: self.value, } } } #[derive(Default)] pub struct PythonSignature { pub positional_parameters: Vec, pub positional_only_parameters: usize, pub required_positional_parameters: usize, pub varargs: Option, // Tuples of keyword name and whether it is required pub keyword_only_parameters: Vec<(String, bool)>, pub kwargs: Option, } impl PythonSignature { pub fn has_no_args(&self) -> bool { self.positional_parameters.is_empty() && self.keyword_only_parameters.is_empty() && self.varargs.is_none() && self.kwargs.is_none() } } pub struct FunctionSignature<'a> { pub arguments: Vec>, pub python_signature: PythonSignature, pub attribute: Option, } pub enum ParseState { /// Accepting positional parameters, which might be positional only Positional, /// Accepting positional parameters after '/' PositionalAfterPosargs, /// Accepting keyword-only parameters after '*' or '*args' Keywords, /// After `**kwargs` nothing is allowed Done, } impl ParseState { fn add_argument( &mut self, signature: &mut PythonSignature, name: String, required: bool, span: Span, ) -> syn::Result<()> { match self { ParseState::Positional | ParseState::PositionalAfterPosargs => { signature.positional_parameters.push(name); if required { signature.required_positional_parameters += 1; ensure_spanned!( signature.required_positional_parameters == signature.positional_parameters.len(), span => "cannot have required positional parameter after an optional parameter" ); } Ok(()) } ParseState::Keywords => { signature.keyword_only_parameters.push((name, required)); Ok(()) } ParseState::Done => { bail_spanned!(span => format!("no more arguments are allowed after `**{}`", signature.kwargs.as_deref().unwrap_or(""))) } } } fn add_varargs( &mut self, signature: &mut PythonSignature, varargs: &SignatureItemVarargs, ) -> syn::Result<()> { match self { ParseState::Positional | ParseState::PositionalAfterPosargs => { signature.varargs = Some(varargs.ident.to_string()); *self = ParseState::Keywords; Ok(()) } ParseState::Keywords => { bail_spanned!(varargs.span() => format!("`*{}` not allowed after `*{}`", varargs.ident, signature.varargs.as_deref().unwrap_or(""))) } ParseState::Done => { bail_spanned!(varargs.span() => format!("`*{}` not allowed after `**{}`", varargs.ident, signature.kwargs.as_deref().unwrap_or(""))) } } } fn add_kwargs( &mut self, signature: &mut PythonSignature, kwargs: &SignatureItemKwargs, ) -> syn::Result<()> { match self { ParseState::Positional | ParseState::PositionalAfterPosargs | ParseState::Keywords => { signature.kwargs = Some(kwargs.ident.to_string()); *self = ParseState::Done; Ok(()) } ParseState::Done => { bail_spanned!(kwargs.span() => format!("`**{}` not allowed after `**{}`", kwargs.ident, signature.kwargs.as_deref().unwrap_or(""))) } } } fn finish_pos_only_args( &mut self, signature: &mut PythonSignature, span: Span, ) -> syn::Result<()> { match self { ParseState::Positional => { signature.positional_only_parameters = signature.positional_parameters.len(); *self = ParseState::PositionalAfterPosargs; Ok(()) } ParseState::PositionalAfterPosargs => { bail_spanned!(span => "`/` not allowed after `/`") } ParseState::Keywords => { bail_spanned!(span => format!("`/` not allowed after `*{}`", signature.varargs.as_deref().unwrap_or(""))) } ParseState::Done => { bail_spanned!(span => format!("`/` not allowed after `**{}`", signature.kwargs.as_deref().unwrap_or(""))) } } } fn finish_pos_args(&mut self, signature: &PythonSignature, span: Span) -> syn::Result<()> { match self { ParseState::Positional | ParseState::PositionalAfterPosargs => { *self = ParseState::Keywords; Ok(()) } ParseState::Keywords => { bail_spanned!(span => format!("`*` not allowed after `*{}`", signature.varargs.as_deref().unwrap_or(""))) } ParseState::Done => { bail_spanned!(span => format!("`*` not allowed after `**{}`", signature.kwargs.as_deref().unwrap_or(""))) } } } } impl<'a> FunctionSignature<'a> { pub fn from_arguments_and_attribute( mut arguments: Vec>, attribute: SignatureAttribute, ) -> syn::Result { let mut parse_state = ParseState::Positional; let mut python_signature = PythonSignature::default(); let mut args_iter = arguments.iter_mut(); let mut next_non_py_argument_checked = |name: &syn::Ident| { for fn_arg in args_iter.by_ref() { match fn_arg { crate::method::FnArg::Py(..) => { // If the user incorrectly tried to include py: Python in the // signature, give a useful error as a hint. ensure_spanned!( name != fn_arg.name(), name.span() => "arguments of type `Python` must not be part of the signature" ); // Otherwise try next argument. continue; } crate::method::FnArg::CancelHandle(..) => { // If the user incorrectly tried to include cancel: CoroutineCancel in the // signature, give a useful error as a hint. ensure_spanned!( name != fn_arg.name(), name.span() => "`cancel_handle` argument must not be part of the signature" ); // Otherwise try next argument. continue; } _ => { ensure_spanned!( name == fn_arg.name(), name.span() => format!( "expected argument from function definition `{}` but got argument `{}`", fn_arg.name().unraw(), name.unraw(), ) ); return Ok(fn_arg); } } } bail_spanned!( name.span() => "signature entry does not have a corresponding function argument" ) }; for item in &attribute.value.items { match item { SignatureItem::Argument(arg) => { let fn_arg = next_non_py_argument_checked(&arg.ident)?; parse_state.add_argument( &mut python_signature, arg.ident.unraw().to_string(), arg.eq_and_default.is_none(), arg.span(), )?; if let Some((_, default)) = &arg.eq_and_default { if let FnArg::Regular(arg) = fn_arg { arg.default_value = Some(default.clone()); } else { unreachable!( "`Python` and `CancelHandle` are already handled above and `*args`/`**kwargs` are \ parsed and transformed below. Because the have to come last and are only allowed \ once, this has to be a regular argument." ); } } } SignatureItem::VarargsSep(sep) => { parse_state.finish_pos_args(&python_signature, sep.span())? } SignatureItem::Varargs(varargs) => { let fn_arg = next_non_py_argument_checked(&varargs.ident)?; fn_arg.to_varargs_mut()?; parse_state.add_varargs(&mut python_signature, varargs)?; } SignatureItem::Kwargs(kwargs) => { let fn_arg = next_non_py_argument_checked(&kwargs.ident)?; fn_arg.to_kwargs_mut()?; parse_state.add_kwargs(&mut python_signature, kwargs)?; } SignatureItem::PosargsSep(sep) => { parse_state.finish_pos_only_args(&mut python_signature, sep.span())? } }; } // Ensure no non-py arguments remain if let Some(arg) = args_iter.find(|arg| !matches!(arg, FnArg::Py(..) | FnArg::CancelHandle(..))) { bail_spanned!( attribute.kw.span() => format!("missing signature entry for argument `{}`", arg.name()) ); } Ok(FunctionSignature { arguments, python_signature, attribute: Some(attribute), }) } /// Without `#[pyo3(signature)]` or `#[args]` - just take the Rust function arguments as positional. pub fn from_arguments(arguments: Vec>) -> syn::Result { let mut python_signature = PythonSignature::default(); for arg in &arguments { // Python<'_> arguments don't show in Python signature if matches!(arg, FnArg::Py(..) | FnArg::CancelHandle(..)) { continue; } if let FnArg::Regular(RegularArg { ty, option_wrapped_type: None, .. }) = arg { // This argument is required, all previous arguments must also have been required ensure_spanned!( python_signature.required_positional_parameters == python_signature.positional_parameters.len(), ty.span() => "required arguments after an `Option<_>` argument are ambiguous\n\ = help: add a `#[pyo3(signature)]` annotation on this function to unambiguously specify the default values for all optional parameters" ); python_signature.required_positional_parameters = python_signature.positional_parameters.len() + 1; } python_signature .positional_parameters .push(arg.name().unraw().to_string()); } Ok(Self { arguments, python_signature, attribute: None, }) } fn default_value_for_parameter(&self, parameter: &str) -> String { let mut default = "...".to_string(); if let Some(fn_arg) = self.arguments.iter().find(|arg| arg.name() == parameter) { if let FnArg::Regular(RegularArg { default_value: Some(arg_default), .. }) = fn_arg { match arg_default { // literal values syn::Expr::Lit(syn::ExprLit { lit, .. }) => match lit { syn::Lit::Str(s) => default = s.token().to_string(), syn::Lit::Char(c) => default = c.token().to_string(), syn::Lit::Int(i) => default = i.base10_digits().to_string(), syn::Lit::Float(f) => default = f.base10_digits().to_string(), syn::Lit::Bool(b) => { default = if b.value() { "True".to_string() } else { "False".to_string() } } _ => {} }, // None syn::Expr::Path(syn::ExprPath { qself: None, path, .. }) if path.is_ident("None") => { default = "None".to_string(); } // others, unsupported yet so defaults to `...` _ => {} } } else if let FnArg::Regular(RegularArg { option_wrapped_type: Some(..), .. }) = fn_arg { // functions without a `#[pyo3(signature = (...))]` option // will treat trailing `Option` arguments as having a default of `None` default = "None".to_string(); } } default } pub fn text_signature(&self, self_argument: Option<&str>) -> String { let mut output = String::new(); output.push('('); if let Some(arg) = self_argument { output.push('$'); output.push_str(arg); } let mut maybe_push_comma = { let mut first = self_argument.is_none(); move |output: &mut String| { if !first { output.push_str(", "); } else { first = false; } } }; let py_sig = &self.python_signature; for (i, parameter) in py_sig.positional_parameters.iter().enumerate() { maybe_push_comma(&mut output); output.push_str(parameter); if i >= py_sig.required_positional_parameters { output.push('='); output.push_str(&self.default_value_for_parameter(parameter)); } if py_sig.positional_only_parameters > 0 && i + 1 == py_sig.positional_only_parameters { output.push_str(", /") } } if let Some(varargs) = &py_sig.varargs { maybe_push_comma(&mut output); output.push('*'); output.push_str(varargs); } else if !py_sig.keyword_only_parameters.is_empty() { maybe_push_comma(&mut output); output.push('*'); } for (parameter, required) in &py_sig.keyword_only_parameters { maybe_push_comma(&mut output); output.push_str(parameter); if !required { output.push('='); output.push_str(&self.default_value_for_parameter(parameter)); } } if let Some(kwargs) = &py_sig.kwargs { maybe_push_comma(&mut output); output.push_str("**"); output.push_str(kwargs); } output.push(')'); output } } pyo3-macros-backend/src/params.rs0000644000175000017500000003110714661133735017724 0ustar jamespagejamespageuse crate::utils::Ctx; use crate::{ method::{FnArg, FnSpec, RegularArg}, pyfunction::FunctionSignature, quotes::some_wrap, }; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote, quote_spanned}; use syn::spanned::Spanned; pub struct Holders { holders: Vec, gil_refs_checkers: Vec, } impl Holders { pub fn new() -> Self { Holders { holders: Vec::new(), gil_refs_checkers: Vec::new(), } } pub fn push_holder(&mut self, span: Span) -> syn::Ident { let holder = syn::Ident::new(&format!("holder_{}", self.holders.len()), span); self.holders.push(holder.clone()); holder } pub fn push_gil_refs_checker(&mut self, span: Span) -> syn::Ident { let gil_refs_checker = syn::Ident::new( &format!("gil_refs_checker_{}", self.gil_refs_checkers.len()), span, ); self.gil_refs_checkers .push(GilRefChecker::FunctionArg(gil_refs_checker.clone())); gil_refs_checker } pub fn push_from_py_with_checker(&mut self, span: Span) -> syn::Ident { let gil_refs_checker = syn::Ident::new( &format!("gil_refs_checker_{}", self.gil_refs_checkers.len()), span, ); self.gil_refs_checkers .push(GilRefChecker::FromPyWith(gil_refs_checker.clone())); gil_refs_checker } pub fn init_holders(&self, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let holders = &self.holders; let gil_refs_checkers = self.gil_refs_checkers.iter().map(|checker| match checker { GilRefChecker::FunctionArg(ident) => ident, GilRefChecker::FromPyWith(ident) => ident, }); quote! { #[allow(clippy::let_unit_value)] #(let mut #holders = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;)* #(let #gil_refs_checkers = #pyo3_path::impl_::deprecations::GilRefs::new();)* } } pub fn check_gil_refs(&self) -> TokenStream { self.gil_refs_checkers .iter() .map(|checker| match checker { GilRefChecker::FunctionArg(ident) => { quote_spanned! { ident.span() => #ident.function_arg(); } } GilRefChecker::FromPyWith(ident) => { quote_spanned! { ident.span() => #ident.from_py_with_arg(); } } }) .collect() } } enum GilRefChecker { FunctionArg(syn::Ident), FromPyWith(syn::Ident), } /// Return true if the argument list is simply (*args, **kwds). pub fn is_forwarded_args(signature: &FunctionSignature<'_>) -> bool { matches!( signature.arguments.as_slice(), [FnArg::VarArgs(..), FnArg::KwArgs(..),] ) } pub(crate) fn check_arg_for_gil_refs( tokens: TokenStream, gil_refs_checker: syn::Ident, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; quote! { #pyo3_path::impl_::deprecations::inspect_type(#tokens, &#gil_refs_checker) } } pub fn impl_arg_params( spec: &FnSpec<'_>, self_: Option<&syn::Type>, fastcall: bool, holders: &mut Holders, ctx: &Ctx, ) -> (TokenStream, Vec) { let args_array = syn::Ident::new("output", Span::call_site()); let Ctx { pyo3_path, .. } = ctx; let from_py_with = spec .signature .arguments .iter() .enumerate() .filter_map(|(i, arg)| { let from_py_with = &arg.from_py_with()?.value; let from_py_with_holder = format_ident!("from_py_with_{}", i); Some(quote_spanned! { from_py_with.span() => let e = #pyo3_path::impl_::deprecations::GilRefs::new(); let #from_py_with_holder = #pyo3_path::impl_::deprecations::inspect_fn(#from_py_with, &e); e.from_py_with_arg(); }) }) .collect::(); if !fastcall && is_forwarded_args(&spec.signature) { // In the varargs convention, we can just pass though if the signature // is (*args, **kwds). let arg_convert = spec .signature .arguments .iter() .enumerate() .map(|(i, arg)| impl_arg_param(arg, i, &mut 0, holders, ctx)) .collect(); return ( quote! { let _args = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_args); let _kwargs = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr_or_opt(py, &_kwargs); #from_py_with }, arg_convert, ); }; let positional_parameter_names = &spec.signature.python_signature.positional_parameters; let positional_only_parameters = &spec.signature.python_signature.positional_only_parameters; let required_positional_parameters = &spec .signature .python_signature .required_positional_parameters; let keyword_only_parameters = spec .signature .python_signature .keyword_only_parameters .iter() .map(|(name, required)| { quote! { #pyo3_path::impl_::extract_argument::KeywordOnlyParameterDescription { name: #name, required: #required, } } }); let num_params = positional_parameter_names.len() + keyword_only_parameters.len(); let mut option_pos = 0usize; let param_conversion = spec .signature .arguments .iter() .enumerate() .map(|(i, arg)| impl_arg_param(arg, i, &mut option_pos, holders, ctx)) .collect(); let args_handler = if spec.signature.python_signature.varargs.is_some() { quote! { #pyo3_path::impl_::extract_argument::TupleVarargs } } else { quote! { #pyo3_path::impl_::extract_argument::NoVarargs } }; let kwargs_handler = if spec.signature.python_signature.kwargs.is_some() { quote! { #pyo3_path::impl_::extract_argument::DictVarkeywords } } else { quote! { #pyo3_path::impl_::extract_argument::NoVarkeywords } }; let cls_name = if let Some(cls) = self_ { quote! { ::std::option::Option::Some(<#cls as #pyo3_path::type_object::PyTypeInfo>::NAME) } } else { quote! { ::std::option::Option::None } }; let python_name = &spec.python_name; let extract_expression = if fastcall { quote! { DESCRIPTION.extract_arguments_fastcall::<#args_handler, #kwargs_handler>( py, _args, _nargs, _kwnames, &mut #args_array )? } } else { quote! { DESCRIPTION.extract_arguments_tuple_dict::<#args_handler, #kwargs_handler>( py, _args, _kwargs, &mut #args_array )? } }; // create array of arguments, and then parse ( quote! { const DESCRIPTION: #pyo3_path::impl_::extract_argument::FunctionDescription = #pyo3_path::impl_::extract_argument::FunctionDescription { cls_name: #cls_name, func_name: stringify!(#python_name), positional_parameter_names: &[#(#positional_parameter_names),*], positional_only_parameters: #positional_only_parameters, required_positional_parameters: #required_positional_parameters, keyword_only_parameters: &[#(#keyword_only_parameters),*], }; let mut #args_array = [::std::option::Option::None; #num_params]; let (_args, _kwargs) = #extract_expression; #from_py_with }, param_conversion, ) } fn impl_arg_param( arg: &FnArg<'_>, pos: usize, option_pos: &mut usize, holders: &mut Holders, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let args_array = syn::Ident::new("output", Span::call_site()); match arg { FnArg::Regular(arg) => { let from_py_with = format_ident!("from_py_with_{}", pos); let arg_value = quote!(#args_array[#option_pos].as_deref()); *option_pos += 1; let tokens = impl_regular_arg_param(arg, from_py_with, arg_value, holders, ctx); check_arg_for_gil_refs(tokens, holders.push_gil_refs_checker(arg.ty.span()), ctx) } FnArg::VarArgs(arg) => { let holder = holders.push_holder(arg.name.span()); let name_str = arg.name.to_string(); quote_spanned! { arg.name.span() => #pyo3_path::impl_::extract_argument::extract_argument( &_args, &mut #holder, #name_str )? } } FnArg::KwArgs(arg) => { let holder = holders.push_holder(arg.name.span()); let name_str = arg.name.to_string(); quote_spanned! { arg.name.span() => #pyo3_path::impl_::extract_argument::extract_optional_argument( _kwargs.as_deref(), &mut #holder, #name_str, || ::std::option::Option::None )? } } FnArg::Py(..) => quote! { py }, FnArg::CancelHandle(..) => quote! { __cancel_handle }, } } /// Re option_pos: The option slice doesn't contain the py: Python argument, so the argument /// index and the index in option diverge when using py: Python pub(crate) fn impl_regular_arg_param( arg: &RegularArg<'_>, from_py_with: syn::Ident, arg_value: TokenStream, // expected type: Option<&'a Bound<'py, PyAny>> holders: &mut Holders, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let pyo3_path = pyo3_path.to_tokens_spanned(arg.ty.span()); // Use this macro inside this function, to ensure that all code generated here is associated // with the function argument macro_rules! quote_arg_span { ($($tokens:tt)*) => { quote_spanned!(arg.ty.span() => $($tokens)*) } } let name_str = arg.name.to_string(); let mut default = arg.default_value.as_ref().map(|expr| quote!(#expr)); // Option arguments have special treatment: the default should be specified _without_ the // Some() wrapper. Maybe this should be changed in future?! if arg.option_wrapped_type.is_some() { default = Some(default.map_or_else( || quote!(::std::option::Option::None), |tokens| some_wrap(tokens, ctx), )); } if arg.from_py_with.is_some() { if let Some(default) = default { quote_arg_span! { #pyo3_path::impl_::extract_argument::from_py_with_with_default( #arg_value, #name_str, #from_py_with as fn(_) -> _, #[allow(clippy::redundant_closure)] { || #default } )? } } else { quote_arg_span! { #pyo3_path::impl_::extract_argument::from_py_with( #pyo3_path::impl_::extract_argument::unwrap_required_argument(#arg_value), #name_str, #from_py_with as fn(_) -> _, )? } } } else if arg.option_wrapped_type.is_some() { let holder = holders.push_holder(arg.name.span()); quote_arg_span! { #pyo3_path::impl_::extract_argument::extract_optional_argument( #arg_value, &mut #holder, #name_str, #[allow(clippy::redundant_closure)] { || #default } )? } } else if let Some(default) = default { let holder = holders.push_holder(arg.name.span()); quote_arg_span! { #pyo3_path::impl_::extract_argument::extract_argument_with_default( #arg_value, &mut #holder, #name_str, #[allow(clippy::redundant_closure)] { || #default } )? } } else { let holder = holders.push_holder(arg.name.span()); quote_arg_span! { #pyo3_path::impl_::extract_argument::extract_argument( #pyo3_path::impl_::extract_argument::unwrap_required_argument(#arg_value), &mut #holder, #name_str )? } } } pyo3-macros-backend/src/method.rs0000644000175000017500000013044314661133735017724 0ustar jamespagejamespageuse std::borrow::Cow; use std::ffi::CString; use std::fmt::Display; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; use syn::{ext::IdentExt, spanned::Spanned, Ident, Result}; use crate::deprecations::deprecate_trailing_option_default; use crate::utils::{Ctx, LitCStr}; use crate::{ attributes::{FromPyWithAttribute, TextSignatureAttribute, TextSignatureAttributeValue}, deprecations::{Deprecation, Deprecations}, params::{impl_arg_params, Holders}, pyfunction::{ FunctionSignature, PyFunctionArgPyO3Attributes, PyFunctionOptions, SignatureAttribute, }, quotes, utils::{self, is_abi3, PythonDoc}, }; #[derive(Clone, Debug)] pub struct RegularArg<'a> { pub name: Cow<'a, syn::Ident>, pub ty: &'a syn::Type, pub from_py_with: Option, pub default_value: Option, pub option_wrapped_type: Option<&'a syn::Type>, } /// Pythons *args argument #[derive(Clone, Debug)] pub struct VarargsArg<'a> { pub name: Cow<'a, syn::Ident>, pub ty: &'a syn::Type, } /// Pythons **kwarg argument #[derive(Clone, Debug)] pub struct KwargsArg<'a> { pub name: Cow<'a, syn::Ident>, pub ty: &'a syn::Type, } #[derive(Clone, Debug)] pub struct CancelHandleArg<'a> { pub name: &'a syn::Ident, pub ty: &'a syn::Type, } #[derive(Clone, Debug)] pub struct PyArg<'a> { pub name: &'a syn::Ident, pub ty: &'a syn::Type, } #[derive(Clone, Debug)] pub enum FnArg<'a> { Regular(RegularArg<'a>), VarArgs(VarargsArg<'a>), KwArgs(KwargsArg<'a>), Py(PyArg<'a>), CancelHandle(CancelHandleArg<'a>), } impl<'a> FnArg<'a> { pub fn name(&self) -> &syn::Ident { match self { FnArg::Regular(RegularArg { name, .. }) => name, FnArg::VarArgs(VarargsArg { name, .. }) => name, FnArg::KwArgs(KwargsArg { name, .. }) => name, FnArg::Py(PyArg { name, .. }) => name, FnArg::CancelHandle(CancelHandleArg { name, .. }) => name, } } pub fn ty(&self) -> &'a syn::Type { match self { FnArg::Regular(RegularArg { ty, .. }) => ty, FnArg::VarArgs(VarargsArg { ty, .. }) => ty, FnArg::KwArgs(KwargsArg { ty, .. }) => ty, FnArg::Py(PyArg { ty, .. }) => ty, FnArg::CancelHandle(CancelHandleArg { ty, .. }) => ty, } } #[allow(clippy::wrong_self_convention)] pub fn from_py_with(&self) -> Option<&FromPyWithAttribute> { if let FnArg::Regular(RegularArg { from_py_with, .. }) = self { from_py_with.as_ref() } else { None } } pub fn to_varargs_mut(&mut self) -> Result<&mut Self> { if let Self::Regular(RegularArg { name, ty, option_wrapped_type: None, .. }) = self { *self = Self::VarArgs(VarargsArg { name: name.clone(), ty, }); Ok(self) } else { bail_spanned!(self.name().span() => "args cannot be optional") } } pub fn to_kwargs_mut(&mut self) -> Result<&mut Self> { if let Self::Regular(RegularArg { name, ty, option_wrapped_type: Some(..), .. }) = self { *self = Self::KwArgs(KwargsArg { name: name.clone(), ty, }); Ok(self) } else { bail_spanned!(self.name().span() => "kwargs must be Option<_>") } } /// Transforms a rust fn arg parsed with syn into a method::FnArg pub fn parse(arg: &'a mut syn::FnArg) -> Result { match arg { syn::FnArg::Receiver(recv) => { bail_spanned!(recv.span() => "unexpected receiver") } // checked in parse_fn_type syn::FnArg::Typed(cap) => { if let syn::Type::ImplTrait(_) = &*cap.ty { bail_spanned!(cap.ty.span() => IMPL_TRAIT_ERR); } let PyFunctionArgPyO3Attributes { from_py_with, cancel_handle, } = PyFunctionArgPyO3Attributes::from_attrs(&mut cap.attrs)?; let ident = match &*cap.pat { syn::Pat::Ident(syn::PatIdent { ident, .. }) => ident, other => return Err(handle_argument_error(other)), }; if utils::is_python(&cap.ty) { return Ok(Self::Py(PyArg { name: ident, ty: &cap.ty, })); } if cancel_handle.is_some() { // `PyFunctionArgPyO3Attributes::from_attrs` validates that // only compatible attributes are specified, either // `cancel_handle` or `from_py_with`, dublicates and any // combination of the two are already rejected. return Ok(Self::CancelHandle(CancelHandleArg { name: ident, ty: &cap.ty, })); } Ok(Self::Regular(RegularArg { name: Cow::Borrowed(ident), ty: &cap.ty, from_py_with, default_value: None, option_wrapped_type: utils::option_type_argument(&cap.ty), })) } } } } fn handle_argument_error(pat: &syn::Pat) -> syn::Error { let span = pat.span(); let msg = match pat { syn::Pat::Wild(_) => "wildcard argument names are not supported", syn::Pat::Struct(_) | syn::Pat::Tuple(_) | syn::Pat::TupleStruct(_) | syn::Pat::Slice(_) => "destructuring in arguments is not supported", _ => "unsupported argument", }; syn::Error::new(span, msg) } /// Represents what kind of a function a pyfunction or pymethod is #[derive(Clone, Debug)] pub enum FnType { /// Represents a pymethod annotated with `#[getter]` Getter(SelfType), /// Represents a pymethod annotated with `#[setter]` Setter(SelfType), /// Represents a regular pymethod Fn(SelfType), /// Represents a pymethod annotated with `#[new]`, i.e. the `__new__` dunder. FnNew, /// Represents a pymethod annotated with both `#[new]` and `#[classmethod]` (in either order) FnNewClass(Span), /// Represents a pymethod annotated with `#[classmethod]`, like a `@classmethod` FnClass(Span), /// Represents a pyfunction or a pymethod annotated with `#[staticmethod]`, like a `@staticmethod` FnStatic, /// Represents a pyfunction annotated with `#[pyo3(pass_module)] FnModule(Span), /// Represents a pymethod or associated constant annotated with `#[classattr]` ClassAttribute, } impl FnType { pub fn skip_first_rust_argument_in_python_signature(&self) -> bool { match self { FnType::Getter(_) | FnType::Setter(_) | FnType::Fn(_) | FnType::FnClass(_) | FnType::FnNewClass(_) | FnType::FnModule(_) => true, FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => false, } } pub fn signature_attribute_allowed(&self) -> bool { match self { FnType::Fn(_) | FnType::FnNew | FnType::FnStatic | FnType::FnClass(_) | FnType::FnNewClass(_) | FnType::FnModule(_) => true, // Setter, Getter and ClassAttribute all have fixed signatures (either take 0 or 1 // arguments) so cannot have a `signature = (...)` attribute. FnType::Getter(_) | FnType::Setter(_) | FnType::ClassAttribute => false, } } pub fn self_arg( &self, cls: Option<&syn::Type>, error_mode: ExtractErrorMode, holders: &mut Holders, ctx: &Ctx, ) -> Option { let Ctx { pyo3_path, .. } = ctx; match self { FnType::Getter(st) | FnType::Setter(st) | FnType::Fn(st) => { let mut receiver = st.receiver( cls.expect("no class given for Fn with a \"self\" receiver"), error_mode, holders, ctx, ); syn::Token![,](Span::call_site()).to_tokens(&mut receiver); Some(receiver) } FnType::FnClass(span) | FnType::FnNewClass(span) => { let py = syn::Ident::new("py", Span::call_site()); let slf: Ident = syn::Ident::new("_slf_ref", Span::call_site()); let pyo3_path = pyo3_path.to_tokens_spanned(*span); let ret = quote_spanned! { *span => #[allow(clippy::useless_conversion)] ::std::convert::Into::into( #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(#slf as *const _ as *const *mut _)) .downcast_unchecked::<#pyo3_path::types::PyType>() ), }; Some(ret) } FnType::FnModule(span) => { let py = syn::Ident::new("py", Span::call_site()); let slf: Ident = syn::Ident::new("_slf_ref", Span::call_site()); let pyo3_path = pyo3_path.to_tokens_spanned(*span); let ret = quote_spanned! { *span => #[allow(clippy::useless_conversion)] ::std::convert::Into::into( #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(#slf as *const _ as *const *mut _)) .downcast_unchecked::<#pyo3_path::types::PyModule>() ), }; Some(ret) } FnType::FnNew | FnType::FnStatic | FnType::ClassAttribute => None, } } } #[derive(Clone, Debug)] pub enum SelfType { Receiver { mutable: bool, span: Span }, TryFromBoundRef(Span), } #[derive(Clone, Copy)] pub enum ExtractErrorMode { NotImplemented, Raise, } impl ExtractErrorMode { pub fn handle_error(self, extract: TokenStream, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; match self { ExtractErrorMode::Raise => quote! { #extract? }, ExtractErrorMode::NotImplemented => quote! { match #extract { ::std::result::Result::Ok(value) => value, ::std::result::Result::Err(_) => { return #pyo3_path::callback::convert(py, py.NotImplemented()); }, } }, } } } impl SelfType { pub fn receiver( &self, cls: &syn::Type, error_mode: ExtractErrorMode, holders: &mut Holders, ctx: &Ctx, ) -> TokenStream { // Due to use of quote_spanned in this function, need to bind these idents to the // main macro callsite. let py = syn::Ident::new("py", Span::call_site()); let slf = syn::Ident::new("_slf", Span::call_site()); let Ctx { pyo3_path, .. } = ctx; match self { SelfType::Receiver { span, mutable } => { let method = if *mutable { syn::Ident::new("extract_pyclass_ref_mut", *span) } else { syn::Ident::new("extract_pyclass_ref", *span) }; let holder = holders.push_holder(*span); let pyo3_path = pyo3_path.to_tokens_spanned(*span); error_mode.handle_error( quote_spanned! { *span => #pyo3_path::impl_::extract_argument::#method::<#cls>( #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf).0, &mut #holder, ) }, ctx, ) } SelfType::TryFromBoundRef(span) => { let pyo3_path = pyo3_path.to_tokens_spanned(*span); error_mode.handle_error( quote_spanned! { *span => #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf).downcast::<#cls>() .map_err(::std::convert::Into::<#pyo3_path::PyErr>::into) .and_then( #[allow(unknown_lints, clippy::unnecessary_fallible_conversions)] // In case slf is Py (unknown_lints can be removed when MSRV is 1.75+) |bound| ::std::convert::TryFrom::try_from(bound).map_err(::std::convert::Into::into) ) }, ctx ) } } } } /// Determines which CPython calling convention a given FnSpec uses. #[derive(Clone, Debug)] pub enum CallingConvention { Noargs, // METH_NOARGS Varargs, // METH_VARARGS | METH_KEYWORDS Fastcall, // METH_FASTCALL | METH_KEYWORDS (not compatible with `abi3` feature) TpNew, // special convention for tp_new } impl CallingConvention { /// Determine default calling convention from an argument signature. /// /// Different other slots (tp_call, tp_new) can have other requirements /// and are set manually (see `parse_fn_type` below). pub fn from_signature(signature: &FunctionSignature<'_>) -> Self { if signature.python_signature.has_no_args() { Self::Noargs } else if signature.python_signature.kwargs.is_some() { // for functions that accept **kwargs, always prefer varargs Self::Varargs } else if !is_abi3() { // FIXME: available in the stable ABI since 3.10 Self::Fastcall } else { Self::Varargs } } } pub struct FnSpec<'a> { pub tp: FnType, // Rust function name pub name: &'a syn::Ident, // Wrapped python name. This should not have any leading r#. // r# can be removed by syn::ext::IdentExt::unraw() pub python_name: syn::Ident, pub signature: FunctionSignature<'a>, pub convention: CallingConvention, pub text_signature: Option, pub asyncness: Option, pub unsafety: Option, pub deprecations: Deprecations<'a>, } pub fn parse_method_receiver(arg: &syn::FnArg) -> Result { match arg { syn::FnArg::Receiver( recv @ syn::Receiver { reference: None, .. }, ) => { bail_spanned!(recv.span() => RECEIVER_BY_VALUE_ERR); } syn::FnArg::Receiver(recv @ syn::Receiver { mutability, .. }) => Ok(SelfType::Receiver { mutable: mutability.is_some(), span: recv.span(), }), syn::FnArg::Typed(syn::PatType { ty, .. }) => { if let syn::Type::ImplTrait(_) = &**ty { bail_spanned!(ty.span() => IMPL_TRAIT_ERR); } Ok(SelfType::TryFromBoundRef(ty.span())) } } } impl<'a> FnSpec<'a> { /// Parser function signature and function attributes pub fn parse( // Signature is mutable to remove the `Python` argument. sig: &'a mut syn::Signature, meth_attrs: &mut Vec, options: PyFunctionOptions, ctx: &'a Ctx, ) -> Result> { let PyFunctionOptions { text_signature, name, signature, .. } = options; let mut python_name = name.map(|name| name.value.0); let mut deprecations = Deprecations::new(ctx); let fn_type = Self::parse_fn_type(sig, meth_attrs, &mut python_name, &mut deprecations)?; ensure_signatures_on_valid_method(&fn_type, signature.as_ref(), text_signature.as_ref())?; let name = &sig.ident; let python_name = python_name.as_ref().unwrap_or(name).unraw(); let arguments: Vec<_> = sig .inputs .iter_mut() .skip(if fn_type.skip_first_rust_argument_in_python_signature() { 1 } else { 0 }) .map(FnArg::parse) .collect::>()?; let signature = if let Some(signature) = signature { FunctionSignature::from_arguments_and_attribute(arguments, signature)? } else { FunctionSignature::from_arguments(arguments)? }; let convention = if matches!(fn_type, FnType::FnNew | FnType::FnNewClass(_)) { CallingConvention::TpNew } else { CallingConvention::from_signature(&signature) }; Ok(FnSpec { tp: fn_type, name, convention, python_name, signature, text_signature, asyncness: sig.asyncness, unsafety: sig.unsafety, deprecations, }) } pub fn null_terminated_python_name(&self, ctx: &Ctx) -> LitCStr { let name = self.python_name.to_string(); let name = CString::new(name).unwrap(); LitCStr::new(name, self.python_name.span(), ctx) } fn parse_fn_type( sig: &syn::Signature, meth_attrs: &mut Vec, python_name: &mut Option, deprecations: &mut Deprecations<'_>, ) -> Result { let mut method_attributes = parse_method_attributes(meth_attrs, deprecations)?; let name = &sig.ident; let parse_receiver = |msg: &'static str| { let first_arg = sig .inputs .first() .ok_or_else(|| err_spanned!(sig.span() => msg))?; parse_method_receiver(first_arg) }; // strip get_ or set_ let strip_fn_name = |prefix: &'static str| { name.unraw() .to_string() .strip_prefix(prefix) .map(|stripped| syn::Ident::new(stripped, name.span())) }; let mut set_name_to_new = || { if let Some(name) = &python_name { bail_spanned!(name.span() => "`name` not allowed with `#[new]`"); } *python_name = Some(syn::Ident::new("__new__", Span::call_site())); Ok(()) }; let fn_type = match method_attributes.as_mut_slice() { [] => FnType::Fn(parse_receiver( "static method needs #[staticmethod] attribute", )?), [MethodTypeAttribute::StaticMethod(_)] => FnType::FnStatic, [MethodTypeAttribute::ClassAttribute(_)] => FnType::ClassAttribute, [MethodTypeAttribute::New(_)] => { set_name_to_new()?; FnType::FnNew } [MethodTypeAttribute::New(_), MethodTypeAttribute::ClassMethod(span)] | [MethodTypeAttribute::ClassMethod(span), MethodTypeAttribute::New(_)] => { set_name_to_new()?; FnType::FnNewClass(*span) } [MethodTypeAttribute::ClassMethod(_)] => { // Add a helpful hint if the classmethod doesn't look like a classmethod let span = match sig.inputs.first() { // Don't actually bother checking the type of the first argument, the compiler // will error on incorrect type. Some(syn::FnArg::Typed(first_arg)) => first_arg.ty.span(), Some(syn::FnArg::Receiver(_)) | None => bail_spanned!( sig.paren_token.span.join() => "Expected `&Bound` or `Py` as the first argument to `#[classmethod]`" ), }; FnType::FnClass(span) } [MethodTypeAttribute::Getter(_, name)] => { if let Some(name) = name.take() { ensure_spanned!( python_name.replace(name).is_none(), python_name.span() => "`name` may only be specified once" ); } else if python_name.is_none() { // Strip off "get_" prefix if needed *python_name = strip_fn_name("get_"); } FnType::Getter(parse_receiver("expected receiver for `#[getter]`")?) } [MethodTypeAttribute::Setter(_, name)] => { if let Some(name) = name.take() { ensure_spanned!( python_name.replace(name).is_none(), python_name.span() => "`name` may only be specified once" ); } else if python_name.is_none() { // Strip off "set_" prefix if needed *python_name = strip_fn_name("set_"); } FnType::Setter(parse_receiver("expected receiver for `#[setter]`")?) } [first, rest @ .., last] => { // Join as many of the spans together as possible let span = rest .iter() .fold(first.span(), |s, next| s.join(next.span()).unwrap_or(s)); let span = span.join(last.span()).unwrap_or(span); // List all the attributes in the error message let mut msg = format!("`{}` may not be combined with", first); let mut is_first = true; for attr in &*rest { msg.push_str(&format!(" `{}`", attr)); if is_first { is_first = false; } else { msg.push(','); } } if !rest.is_empty() { msg.push_str(" and"); } msg.push_str(&format!(" `{}`", last)); bail_spanned!(span => msg) } }; Ok(fn_type) } /// Return a C wrapper function for this signature. pub fn get_wrapper_function( &self, ident: &proc_macro2::Ident, cls: Option<&syn::Type>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, output_span, } = ctx; let mut cancel_handle_iter = self .signature .arguments .iter() .filter(|arg| matches!(arg, FnArg::CancelHandle(..))); let cancel_handle = cancel_handle_iter.next(); if let Some(FnArg::CancelHandle(CancelHandleArg { name, .. })) = cancel_handle { ensure_spanned!(self.asyncness.is_some(), name.span() => "`cancel_handle` attribute can only be used with `async fn`"); if let Some(FnArg::CancelHandle(CancelHandleArg { name, .. })) = cancel_handle_iter.next() { bail_spanned!(name.span() => "`cancel_handle` may only be specified once"); } } if self.asyncness.is_some() { ensure_spanned!( cfg!(feature = "experimental-async"), self.asyncness.span() => "async functions are only supported with the `experimental-async` feature" ); } let rust_call = |args: Vec, holders: &mut Holders| { let mut self_arg = || self.tp.self_arg(cls, ExtractErrorMode::Raise, holders, ctx); let call = if self.asyncness.is_some() { let throw_callback = if cancel_handle.is_some() { quote! { Some(__throw_callback) } } else { quote! { None } }; let python_name = &self.python_name; let qualname_prefix = match cls { Some(cls) => quote!(Some(<#cls as #pyo3_path::PyTypeInfo>::NAME)), None => quote!(None), }; let arg_names = (0..args.len()) .map(|i| format_ident!("arg_{}", i)) .collect::>(); let future = match self.tp { FnType::Fn(SelfType::Receiver { mutable: false, .. }) => { quote! {{ #(let #arg_names = #args;)* let __guard = #pyo3_path::impl_::coroutine::RefGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?; async move { function(&__guard, #(#arg_names),*).await } }} } FnType::Fn(SelfType::Receiver { mutable: true, .. }) => { quote! {{ #(let #arg_names = #args;)* let mut __guard = #pyo3_path::impl_::coroutine::RefMutGuard::<#cls>::new(&#pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &_slf))?; async move { function(&mut __guard, #(#arg_names),*).await } }} } _ => { if let Some(self_arg) = self_arg() { let self_checker = holders.push_gil_refs_checker(self_arg.span()); quote! { function( // NB #self_arg includes a comma, so none inserted here #pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker), #(#args),* ) } } else { quote! { function(#(#args),*) } } } }; let mut call = quote! {{ let future = #future; #pyo3_path::impl_::coroutine::new_coroutine( #pyo3_path::intern!(py, stringify!(#python_name)), #qualname_prefix, #throw_callback, async move { #pyo3_path::impl_::wrap::OkWrap::wrap(future.await) }, ) }}; if cancel_handle.is_some() { call = quote! {{ let __cancel_handle = #pyo3_path::coroutine::CancelHandle::new(); let __throw_callback = __cancel_handle.throw_callback(); #call }}; } call } else if let Some(self_arg) = self_arg() { let self_checker = holders.push_gil_refs_checker(self_arg.span()); quote! { function( // NB #self_arg includes a comma, so none inserted here #pyo3_path::impl_::deprecations::inspect_type(#self_arg &#self_checker), #(#args),* ) } } else { quote! { function(#(#args),*) } }; // We must assign the output_span to the return value of the call, // but *not* of the call itself otherwise the spans get really weird let ret_expr = quote! { let ret = #call; }; let ret_var = quote_spanned! {*output_span=> ret }; let return_conversion = quotes::map_result_into_ptr(quotes::ok_wrap(ret_var, ctx), ctx); quote! { { #ret_expr #return_conversion } } }; let func_name = &self.name; let rust_name = if let Some(cls) = cls { quote!(#cls::#func_name) } else { quote!(#func_name) }; let deprecation = deprecate_trailing_option_default(self); Ok(match self.convention { CallingConvention::Noargs => { let mut holders = Holders::new(); let args = self .signature .arguments .iter() .map(|arg| match arg { FnArg::Py(..) => quote!(py), FnArg::CancelHandle(..) => quote!(__cancel_handle), _ => unreachable!("`CallingConvention::Noargs` should not contain any arguments (reaching Python) except for `self`, which is handled below."), }) .collect(); let call = rust_call(args, &mut holders); let check_gil_refs = holders.check_gil_refs(); let init_holders = holders.init_holders(ctx); quote! { unsafe fn #ident<'py>( py: #pyo3_path::Python<'py>, _slf: *mut #pyo3_path::ffi::PyObject, ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { #deprecation let _slf_ref = &_slf; let function = #rust_name; // Shadow the function name to avoid #3017 #init_holders let result = #call; #check_gil_refs result } } } CallingConvention::Fastcall => { let mut holders = Holders::new(); let (arg_convert, args) = impl_arg_params(self, cls, true, &mut holders, ctx); let call = rust_call(args, &mut holders); let init_holders = holders.init_holders(ctx); let check_gil_refs = holders.check_gil_refs(); quote! { unsafe fn #ident<'py>( py: #pyo3_path::Python<'py>, _slf: *mut #pyo3_path::ffi::PyObject, _args: *const *mut #pyo3_path::ffi::PyObject, _nargs: #pyo3_path::ffi::Py_ssize_t, _kwnames: *mut #pyo3_path::ffi::PyObject ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { #deprecation let _slf_ref = &_slf; let function = #rust_name; // Shadow the function name to avoid #3017 #arg_convert #init_holders let result = #call; #check_gil_refs result } } } CallingConvention::Varargs => { let mut holders = Holders::new(); let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx); let call = rust_call(args, &mut holders); let init_holders = holders.init_holders(ctx); let check_gil_refs = holders.check_gil_refs(); quote! { unsafe fn #ident<'py>( py: #pyo3_path::Python<'py>, _slf: *mut #pyo3_path::ffi::PyObject, _args: *mut #pyo3_path::ffi::PyObject, _kwargs: *mut #pyo3_path::ffi::PyObject ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { #deprecation let _slf_ref = &_slf; let function = #rust_name; // Shadow the function name to avoid #3017 #arg_convert #init_holders let result = #call; #check_gil_refs result } } } CallingConvention::TpNew => { let mut holders = Holders::new(); let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx); let self_arg = self .tp .self_arg(cls, ExtractErrorMode::Raise, &mut holders, ctx); let call = quote_spanned! {*output_span=> #rust_name(#self_arg #(#args),*) }; let init_holders = holders.init_holders(ctx); let check_gil_refs = holders.check_gil_refs(); quote! { unsafe fn #ident( py: #pyo3_path::Python<'_>, _slf: *mut #pyo3_path::ffi::PyTypeObject, _args: *mut #pyo3_path::ffi::PyObject, _kwargs: *mut #pyo3_path::ffi::PyObject ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { use #pyo3_path::callback::IntoPyCallbackOutput; #deprecation let _slf_ref = &_slf; let function = #rust_name; // Shadow the function name to avoid #3017 #arg_convert #init_holders let result = #call; let initializer: #pyo3_path::PyClassInitializer::<#cls> = result.convert(py)?; #check_gil_refs #pyo3_path::impl_::pymethods::tp_new_impl(py, initializer, _slf) } } } }) } /// Return a `PyMethodDef` constructor for this function, matching the selected /// calling convention. pub fn get_methoddef(&self, wrapper: impl ToTokens, doc: &PythonDoc, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let python_name = self.null_terminated_python_name(ctx); match self.convention { CallingConvention::Noargs => quote! { #pyo3_path::impl_::pymethods::PyMethodDef::noargs( #python_name, { unsafe extern "C" fn trampoline( _slf: *mut #pyo3_path::ffi::PyObject, _args: *mut #pyo3_path::ffi::PyObject, ) -> *mut #pyo3_path::ffi::PyObject { #pyo3_path::impl_::trampoline::noargs( _slf, _args, #wrapper ) } trampoline }, #doc, ) }, CallingConvention::Fastcall => quote! { #pyo3_path::impl_::pymethods::PyMethodDef::fastcall_cfunction_with_keywords( #python_name, { unsafe extern "C" fn trampoline( _slf: *mut #pyo3_path::ffi::PyObject, _args: *const *mut #pyo3_path::ffi::PyObject, _nargs: #pyo3_path::ffi::Py_ssize_t, _kwnames: *mut #pyo3_path::ffi::PyObject ) -> *mut #pyo3_path::ffi::PyObject { #pyo3_path::impl_::trampoline::fastcall_with_keywords( _slf, _args, _nargs, _kwnames, #wrapper ) } trampoline }, #doc, ) }, CallingConvention::Varargs => quote! { #pyo3_path::impl_::pymethods::PyMethodDef::cfunction_with_keywords( #python_name, { unsafe extern "C" fn trampoline( _slf: *mut #pyo3_path::ffi::PyObject, _args: *mut #pyo3_path::ffi::PyObject, _kwargs: *mut #pyo3_path::ffi::PyObject, ) -> *mut #pyo3_path::ffi::PyObject { #pyo3_path::impl_::trampoline::cfunction_with_keywords( _slf, _args, _kwargs, #wrapper ) } trampoline }, #doc, ) }, CallingConvention::TpNew => unreachable!("tp_new cannot get a methoddef"), } } /// Forwards to [utils::get_doc] with the text signature of this spec. pub fn get_doc(&self, attrs: &[syn::Attribute], ctx: &Ctx) -> PythonDoc { let text_signature = self .text_signature_call_signature() .map(|sig| format!("{}{}", self.python_name, sig)); utils::get_doc(attrs, text_signature, ctx) } /// Creates the parenthesised arguments list for `__text_signature__` snippet based on this spec's signature /// and/or attributes. Prepend the callable name to make a complete `__text_signature__`. pub fn text_signature_call_signature(&self) -> Option { let self_argument = match &self.tp { // Getters / Setters / ClassAttribute are not callables on the Python side FnType::Getter(_) | FnType::Setter(_) | FnType::ClassAttribute => return None, FnType::Fn(_) => Some("self"), FnType::FnModule(_) => Some("module"), FnType::FnClass(_) | FnType::FnNewClass(_) => Some("cls"), FnType::FnStatic | FnType::FnNew => None, }; match self.text_signature.as_ref().map(|attr| &attr.value) { Some(TextSignatureAttributeValue::Str(s)) => Some(s.value()), None => Some(self.signature.text_signature(self_argument)), Some(TextSignatureAttributeValue::Disabled(_)) => None, } } } enum MethodTypeAttribute { New(Span), ClassMethod(Span), StaticMethod(Span), Getter(Span, Option), Setter(Span, Option), ClassAttribute(Span), } impl MethodTypeAttribute { fn span(&self) -> Span { match self { MethodTypeAttribute::New(span) | MethodTypeAttribute::ClassMethod(span) | MethodTypeAttribute::StaticMethod(span) | MethodTypeAttribute::Getter(span, _) | MethodTypeAttribute::Setter(span, _) | MethodTypeAttribute::ClassAttribute(span) => *span, } } /// Attempts to parse a method type attribute. /// /// If the attribute does not match one of the attribute names, returns `Ok(None)`. /// /// Otherwise will either return a parse error or the attribute. fn parse_if_matching_attribute( attr: &syn::Attribute, deprecations: &mut Deprecations<'_>, ) -> Result> { fn ensure_no_arguments(meta: &syn::Meta, ident: &str) -> syn::Result<()> { match meta { syn::Meta::Path(_) => Ok(()), syn::Meta::List(l) => bail_spanned!( l.span() => format!( "`#[{ident}]` does not take any arguments\n= help: did you mean `#[{ident}] #[pyo3({meta})]`?", ident = ident, meta = l.tokens, ) ), syn::Meta::NameValue(nv) => { bail_spanned!(nv.eq_token.span() => format!( "`#[{}]` does not take any arguments\n= note: this was previously accepted and ignored", ident )) } } } fn extract_name(meta: &syn::Meta, ident: &str) -> Result> { match meta { syn::Meta::Path(_) => Ok(None), syn::Meta::NameValue(nv) => bail_spanned!( nv.eq_token.span() => format!("expected `#[{}(name)]` to set the name", ident) ), syn::Meta::List(l) => { if let Ok(name) = l.parse_args::() { Ok(Some(name)) } else if let Ok(name) = l.parse_args::() { name.parse().map(Some) } else { bail_spanned!(l.tokens.span() => "expected ident or string literal for property name"); } } } } let meta = &attr.meta; let path = meta.path(); if path.is_ident("new") { ensure_no_arguments(meta, "new")?; Ok(Some(MethodTypeAttribute::New(path.span()))) } else if path.is_ident("__new__") { let span = path.span(); deprecations.push(Deprecation::PyMethodsNewDeprecatedForm, span); ensure_no_arguments(meta, "__new__")?; Ok(Some(MethodTypeAttribute::New(span))) } else if path.is_ident("classmethod") { ensure_no_arguments(meta, "classmethod")?; Ok(Some(MethodTypeAttribute::ClassMethod(path.span()))) } else if path.is_ident("staticmethod") { ensure_no_arguments(meta, "staticmethod")?; Ok(Some(MethodTypeAttribute::StaticMethod(path.span()))) } else if path.is_ident("classattr") { ensure_no_arguments(meta, "classattr")?; Ok(Some(MethodTypeAttribute::ClassAttribute(path.span()))) } else if path.is_ident("getter") { let name = extract_name(meta, "getter")?; Ok(Some(MethodTypeAttribute::Getter(path.span(), name))) } else if path.is_ident("setter") { let name = extract_name(meta, "setter")?; Ok(Some(MethodTypeAttribute::Setter(path.span(), name))) } else { Ok(None) } } } impl Display for MethodTypeAttribute { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { MethodTypeAttribute::New(_) => "#[new]".fmt(f), MethodTypeAttribute::ClassMethod(_) => "#[classmethod]".fmt(f), MethodTypeAttribute::StaticMethod(_) => "#[staticmethod]".fmt(f), MethodTypeAttribute::Getter(_, _) => "#[getter]".fmt(f), MethodTypeAttribute::Setter(_, _) => "#[setter]".fmt(f), MethodTypeAttribute::ClassAttribute(_) => "#[classattr]".fmt(f), } } } fn parse_method_attributes( attrs: &mut Vec, deprecations: &mut Deprecations<'_>, ) -> Result> { let mut new_attrs = Vec::new(); let mut found_attrs = Vec::new(); for attr in attrs.drain(..) { match MethodTypeAttribute::parse_if_matching_attribute(&attr, deprecations)? { Some(attr) => found_attrs.push(attr), None => new_attrs.push(attr), } } *attrs = new_attrs; Ok(found_attrs) } const IMPL_TRAIT_ERR: &str = "Python functions cannot have `impl Trait` arguments"; const RECEIVER_BY_VALUE_ERR: &str = "Python objects are shared, so 'self' cannot be moved out of the Python interpreter. Try `&self`, `&mut self, `slf: PyRef<'_, Self>` or `slf: PyRefMut<'_, Self>`."; fn ensure_signatures_on_valid_method( fn_type: &FnType, signature: Option<&SignatureAttribute>, text_signature: Option<&TextSignatureAttribute>, ) -> syn::Result<()> { if let Some(signature) = signature { match fn_type { FnType::Getter(_) => { debug_assert!(!fn_type.signature_attribute_allowed()); bail_spanned!(signature.kw.span() => "`signature` not allowed with `getter`") } FnType::Setter(_) => { debug_assert!(!fn_type.signature_attribute_allowed()); bail_spanned!(signature.kw.span() => "`signature` not allowed with `setter`") } FnType::ClassAttribute => { debug_assert!(!fn_type.signature_attribute_allowed()); bail_spanned!(signature.kw.span() => "`signature` not allowed with `classattr`") } _ => debug_assert!(fn_type.signature_attribute_allowed()), } } if let Some(text_signature) = text_signature { match fn_type { FnType::Getter(_) => { bail_spanned!(text_signature.kw.span() => "`text_signature` not allowed with `getter`") } FnType::Setter(_) => { bail_spanned!(text_signature.kw.span() => "`text_signature` not allowed with `setter`") } FnType::ClassAttribute => { bail_spanned!(text_signature.kw.span() => "`text_signature` not allowed with `classattr`") } _ => {} } } Ok(()) } pyo3-macros-backend/src/quotes.rs0000644000175000017500000000166314661133735017765 0ustar jamespagejamespageuse crate::utils::Ctx; use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; pub(crate) fn some_wrap(obj: TokenStream, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; quote! { #pyo3_path::impl_::wrap::SomeWrap::wrap(#obj) } } pub(crate) fn ok_wrap(obj: TokenStream, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, output_span, } = ctx; let pyo3_path = pyo3_path.to_tokens_spanned(*output_span); quote_spanned! {*output_span=> #pyo3_path::impl_::wrap::OkWrap::wrap(#obj) .map_err(::core::convert::Into::<#pyo3_path::PyErr>::into) } } pub(crate) fn map_result_into_ptr(result: TokenStream, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, output_span, } = ctx; let pyo3_path = pyo3_path.to_tokens_spanned(*output_span); quote_spanned! {*output_span=> #pyo3_path::impl_::wrap::map_result_into_ptr(py, #result) } } pyo3-macros-backend/src/pyfunction.rs0000644000175000017500000002365614661133735020651 0ustar jamespagejamespageuse crate::utils::Ctx; use crate::{ attributes::{ self, get_pyo3_options, take_attributes, take_pyo3_options, CrateAttribute, FromPyWithAttribute, NameAttribute, TextSignatureAttribute, }, deprecations::Deprecations, method::{self, CallingConvention, FnArg}, pymethod::check_generic, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; use syn::{ext::IdentExt, spanned::Spanned, Result}; use syn::{ parse::{Parse, ParseStream}, token::Comma, }; mod signature; pub use self::signature::{ConstructorAttribute, FunctionSignature, SignatureAttribute}; #[derive(Clone, Debug)] pub struct PyFunctionArgPyO3Attributes { pub from_py_with: Option, pub cancel_handle: Option, } enum PyFunctionArgPyO3Attribute { FromPyWith(FromPyWithAttribute), CancelHandle(attributes::kw::cancel_handle), } impl Parse for PyFunctionArgPyO3Attribute { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::cancel_handle) { input.parse().map(PyFunctionArgPyO3Attribute::CancelHandle) } else if lookahead.peek(attributes::kw::from_py_with) { input.parse().map(PyFunctionArgPyO3Attribute::FromPyWith) } else { Err(lookahead.error()) } } } impl PyFunctionArgPyO3Attributes { /// Parses #[pyo3(from_python_with = "func")] pub fn from_attrs(attrs: &mut Vec) -> syn::Result { let mut attributes = PyFunctionArgPyO3Attributes { from_py_with: None, cancel_handle: None, }; take_attributes(attrs, |attr| { if let Some(pyo3_attrs) = get_pyo3_options(attr)? { for attr in pyo3_attrs { match attr { PyFunctionArgPyO3Attribute::FromPyWith(from_py_with) => { ensure_spanned!( attributes.from_py_with.is_none(), from_py_with.span() => "`from_py_with` may only be specified once per argument" ); attributes.from_py_with = Some(from_py_with); } PyFunctionArgPyO3Attribute::CancelHandle(cancel_handle) => { ensure_spanned!( attributes.cancel_handle.is_none(), cancel_handle.span() => "`cancel_handle` may only be specified once per argument" ); attributes.cancel_handle = Some(cancel_handle); } } ensure_spanned!( attributes.from_py_with.is_none() || attributes.cancel_handle.is_none(), attributes.cancel_handle.unwrap().span() => "`from_py_with` and `cancel_handle` cannot be specified together" ); } Ok(true) } else { Ok(false) } })?; Ok(attributes) } } #[derive(Default)] pub struct PyFunctionOptions { pub pass_module: Option, pub name: Option, pub signature: Option, pub text_signature: Option, pub krate: Option, } impl Parse for PyFunctionOptions { fn parse(input: ParseStream<'_>) -> Result { let mut options = PyFunctionOptions::default(); while !input.is_empty() { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::name) || lookahead.peek(attributes::kw::pass_module) || lookahead.peek(attributes::kw::signature) || lookahead.peek(attributes::kw::text_signature) { options.add_attributes(std::iter::once(input.parse()?))?; if !input.is_empty() { let _: Comma = input.parse()?; } } else if lookahead.peek(syn::Token![crate]) { // TODO needs duplicate check? options.krate = Some(input.parse()?); } else { return Err(lookahead.error()); } } Ok(options) } } pub enum PyFunctionOption { Name(NameAttribute), PassModule(attributes::kw::pass_module), Signature(SignatureAttribute), TextSignature(TextSignatureAttribute), Crate(CrateAttribute), } impl Parse for PyFunctionOption { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::name) { input.parse().map(PyFunctionOption::Name) } else if lookahead.peek(attributes::kw::pass_module) { input.parse().map(PyFunctionOption::PassModule) } else if lookahead.peek(attributes::kw::signature) { input.parse().map(PyFunctionOption::Signature) } else if lookahead.peek(attributes::kw::text_signature) { input.parse().map(PyFunctionOption::TextSignature) } else if lookahead.peek(syn::Token![crate]) { input.parse().map(PyFunctionOption::Crate) } else { Err(lookahead.error()) } } } impl PyFunctionOptions { pub fn from_attrs(attrs: &mut Vec) -> syn::Result { let mut options = PyFunctionOptions::default(); options.add_attributes(take_pyo3_options(attrs)?)?; Ok(options) } pub fn add_attributes( &mut self, attrs: impl IntoIterator, ) -> Result<()> { macro_rules! set_option { ($key:ident) => { { ensure_spanned!( self.$key.is_none(), $key.span() => concat!("`", stringify!($key), "` may only be specified once") ); self.$key = Some($key); } }; } for attr in attrs { match attr { PyFunctionOption::Name(name) => set_option!(name), PyFunctionOption::PassModule(pass_module) => set_option!(pass_module), PyFunctionOption::Signature(signature) => set_option!(signature), PyFunctionOption::TextSignature(text_signature) => set_option!(text_signature), PyFunctionOption::Crate(krate) => set_option!(krate), } } Ok(()) } } pub fn build_py_function( ast: &mut syn::ItemFn, mut options: PyFunctionOptions, ) -> syn::Result { options.add_attributes(take_pyo3_options(&mut ast.attrs)?)?; impl_wrap_pyfunction(ast, options) } /// Generates python wrapper over a function that allows adding it to a python module as a python /// function pub fn impl_wrap_pyfunction( func: &mut syn::ItemFn, options: PyFunctionOptions, ) -> syn::Result { check_generic(&func.sig)?; let PyFunctionOptions { pass_module, name, signature, text_signature, krate, } = options; let ctx = &Ctx::new(&krate, Some(&func.sig)); let Ctx { pyo3_path, .. } = &ctx; let python_name = name .as_ref() .map_or_else(|| &func.sig.ident, |name| &name.value.0) .unraw(); let tp = if pass_module.is_some() { let span = match func.sig.inputs.first() { Some(syn::FnArg::Typed(first_arg)) => first_arg.ty.span(), Some(syn::FnArg::Receiver(_)) | None => bail_spanned!( func.sig.paren_token.span.join() => "expected `&PyModule` or `Py` as first argument with `pass_module`" ), }; method::FnType::FnModule(span) } else { method::FnType::FnStatic }; let arguments = func .sig .inputs .iter_mut() .skip(if tp.skip_first_rust_argument_in_python_signature() { 1 } else { 0 }) .map(FnArg::parse) .collect::>>()?; let signature = if let Some(signature) = signature { FunctionSignature::from_arguments_and_attribute(arguments, signature)? } else { FunctionSignature::from_arguments(arguments)? }; let spec = method::FnSpec { tp, name: &func.sig.ident, convention: CallingConvention::from_signature(&signature), python_name, signature, text_signature, asyncness: func.sig.asyncness, unsafety: func.sig.unsafety, deprecations: Deprecations::new(ctx), }; let vis = &func.vis; let name = &func.sig.ident; let wrapper_ident = format_ident!("__pyfunction_{}", spec.name); let wrapper = spec.get_wrapper_function(&wrapper_ident, None, ctx)?; let methoddef = spec.get_methoddef(wrapper_ident, &spec.get_doc(&func.attrs, ctx), ctx); let wrapped_pyfunction = quote! { // Create a module with the same name as the `#[pyfunction]` - this way `use ` // will actually bring both the module and the function into scope. #[doc(hidden)] #vis mod #name { pub(crate) struct MakeDef; pub const _PYO3_DEF: #pyo3_path::impl_::pymethods::PyMethodDef = MakeDef::_PYO3_DEF; } // Generate the definition inside an anonymous function in the same scope as the original function - // this avoids complications around the fact that the generated module has a different scope // (and `super` doesn't always refer to the outer scope, e.g. if the `#[pyfunction] is // inside a function body) #[allow(unknown_lints, non_local_definitions)] impl #name::MakeDef { const _PYO3_DEF: #pyo3_path::impl_::pymethods::PyMethodDef = #methoddef; } #[allow(non_snake_case)] #wrapper }; Ok(wrapped_pyfunction) } pyo3-macros-backend/src/lib.rs0000644000175000017500000000150614661133735017207 0ustar jamespagejamespage//! This crate contains the implementation of the proc macro attributes #![warn(elided_lifetimes_in_paths, unused_lifetimes)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![recursion_limit = "1024"] // Listed first so that macros in this module are available in the rest of the crate. #[macro_use] mod utils; mod attributes; mod deprecations; mod frompyobject; mod konst; mod method; mod module; mod params; mod pyclass; mod pyfunction; mod pyimpl; mod pymethod; mod pyversions; mod quotes; pub use frompyobject::build_derive_from_pyobject; pub use module::{pymodule_function_impl, pymodule_module_impl, PyModuleOptions}; pub use pyclass::{build_py_class, build_py_enum, PyClassArgs}; pub use pyfunction::{build_py_function, PyFunctionOptions}; pub use pyimpl::{build_py_methods, PyClassMethodsType}; pub use utils::get_doc; pyo3-macros-backend/src/utils.rs0000644000175000017500000002201414661133735017576 0ustar jamespagejamespageuse crate::attributes::{CrateAttribute, RenamingRule}; use proc_macro2::{Span, TokenStream}; use quote::{quote, ToTokens}; use std::ffi::CString; use syn::spanned::Spanned; use syn::{punctuated::Punctuated, Token}; /// Macro inspired by `anyhow::anyhow!` to create a compiler error with the given span. macro_rules! err_spanned { ($span:expr => $msg:expr) => { syn::Error::new($span, $msg) }; } /// Macro inspired by `anyhow::bail!` to return a compiler error with the given span. macro_rules! bail_spanned { ($span:expr => $msg:expr) => { return Err(err_spanned!($span => $msg)) }; } /// Macro inspired by `anyhow::ensure!` to return a compiler error with the given span if the /// specified condition is not met. macro_rules! ensure_spanned { ($condition:expr, $span:expr => $msg:expr) => { if !($condition) { bail_spanned!($span => $msg); } }; ($($condition:expr, $span:expr => $msg:expr;)*) => { if let Some(e) = [$( (!($condition)).then(|| err_spanned!($span => $msg)), )*] .into_iter() .flatten() .reduce(|mut acc, e| { acc.combine(e); acc }) { return Err(e); } }; } /// Check if the given type `ty` is `pyo3::Python`. pub fn is_python(ty: &syn::Type) -> bool { match unwrap_ty_group(ty) { syn::Type::Path(typath) => typath .path .segments .last() .map(|seg| seg.ident == "Python") .unwrap_or(false), _ => false, } } /// If `ty` is `Option`, return `Some(T)`, else `None`. pub fn option_type_argument(ty: &syn::Type) -> Option<&syn::Type> { if let syn::Type::Path(syn::TypePath { path, .. }) = ty { let seg = path.segments.last().filter(|s| s.ident == "Option")?; if let syn::PathArguments::AngleBracketed(params) = &seg.arguments { if let syn::GenericArgument::Type(ty) = params.args.first()? { return Some(ty); } } } None } // TODO: Replace usage of this by [`syn::LitCStr`] when on MSRV 1.77 #[derive(Clone)] pub struct LitCStr { lit: CString, span: Span, pyo3_path: PyO3CratePath, } impl LitCStr { pub fn new(lit: CString, span: Span, ctx: &Ctx) -> Self { Self { lit, span, pyo3_path: ctx.pyo3_path.clone(), } } pub fn empty(ctx: &Ctx) -> Self { Self { lit: CString::new("").unwrap(), span: Span::call_site(), pyo3_path: ctx.pyo3_path.clone(), } } } impl quote::ToTokens for LitCStr { fn to_tokens(&self, tokens: &mut TokenStream) { if cfg!(c_str_lit) { syn::LitCStr::new(&self.lit, self.span).to_tokens(tokens); } else { let pyo3_path = &self.pyo3_path; let lit = self.lit.to_str().unwrap(); tokens.extend(quote::quote_spanned!(self.span => #pyo3_path::ffi::c_str!(#lit))); } } } /// A syntax tree which evaluates to a nul-terminated docstring for Python. /// /// Typically the tokens will just be that string, but if the original docs included macro /// expressions then the tokens will be a concat!("...", "\n", "\0") expression of the strings and /// macro parts. contents such as parse the string contents. #[derive(Clone)] pub struct PythonDoc(PythonDocKind); #[derive(Clone)] enum PythonDocKind { LitCStr(LitCStr), // There is currently no way to `concat!` c-string literals, we fallback to the `c_str!` macro in // this case. Tokens(TokenStream), } /// Collects all #[doc = "..."] attributes into a TokenStream evaluating to a null-terminated string. /// /// If this doc is for a callable, the provided `text_signature` can be passed to prepend /// this to the documentation suitable for Python to extract this into the `__text_signature__` /// attribute. pub fn get_doc( attrs: &[syn::Attribute], mut text_signature: Option, ctx: &Ctx, ) -> PythonDoc { let Ctx { pyo3_path, .. } = ctx; // insert special divider between `__text_signature__` and doc // (assume text_signature is itself well-formed) if let Some(text_signature) = &mut text_signature { text_signature.push_str("\n--\n\n"); } let mut parts = Punctuated::::new(); let mut first = true; let mut current_part = text_signature.unwrap_or_default(); for attr in attrs { if attr.path().is_ident("doc") { if let Ok(nv) = attr.meta.require_name_value() { if !first { current_part.push('\n'); } else { first = false; } if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit_str), .. }) = &nv.value { // Strip single left space from literal strings, if needed. // e.g. `/// Hello world` expands to #[doc = " Hello world"] let doc_line = lit_str.value(); current_part.push_str(doc_line.strip_prefix(' ').unwrap_or(&doc_line)); } else { // This is probably a macro doc from Rust 1.54, e.g. #[doc = include_str!(...)] // Reset the string buffer, write that part, and then push this macro part too. parts.push(current_part.to_token_stream()); current_part.clear(); parts.push(nv.value.to_token_stream()); } } } } if !parts.is_empty() { // Doc contained macro pieces - return as `concat!` expression if !current_part.is_empty() { parts.push(current_part.to_token_stream()); } let mut tokens = TokenStream::new(); syn::Ident::new("concat", Span::call_site()).to_tokens(&mut tokens); syn::token::Not(Span::call_site()).to_tokens(&mut tokens); syn::token::Bracket(Span::call_site()).surround(&mut tokens, |tokens| { parts.to_tokens(tokens); syn::token::Comma(Span::call_site()).to_tokens(tokens); }); PythonDoc(PythonDocKind::Tokens( quote!(#pyo3_path::ffi::c_str!(#tokens)), )) } else { // Just a string doc - return directly with nul terminator let docs = CString::new(current_part).unwrap(); PythonDoc(PythonDocKind::LitCStr(LitCStr::new( docs, Span::call_site(), ctx, ))) } } impl quote::ToTokens for PythonDoc { fn to_tokens(&self, tokens: &mut TokenStream) { match &self.0 { PythonDocKind::LitCStr(lit) => lit.to_tokens(tokens), PythonDocKind::Tokens(toks) => toks.to_tokens(tokens), } } } pub fn unwrap_ty_group(mut ty: &syn::Type) -> &syn::Type { while let syn::Type::Group(g) = ty { ty = &*g.elem; } ty } pub struct Ctx { /// Where we can find the pyo3 crate pub pyo3_path: PyO3CratePath, /// If we are in a pymethod or pyfunction, /// this will be the span of the return type pub output_span: Span, } impl Ctx { pub(crate) fn new(attr: &Option, signature: Option<&syn::Signature>) -> Self { let pyo3_path = match attr { Some(attr) => PyO3CratePath::Given(attr.value.0.clone()), None => PyO3CratePath::Default, }; let output_span = if let Some(syn::Signature { output: syn::ReturnType::Type(_, output_type), .. }) = &signature { output_type.span() } else { Span::call_site() }; Self { pyo3_path, output_span, } } } #[derive(Clone)] pub enum PyO3CratePath { Given(syn::Path), Default, } impl PyO3CratePath { pub fn to_tokens_spanned(&self, span: Span) -> TokenStream { match self { Self::Given(path) => quote::quote_spanned! { span => #path }, Self::Default => quote::quote_spanned! { span => ::pyo3 }, } } } impl quote::ToTokens for PyO3CratePath { fn to_tokens(&self, tokens: &mut TokenStream) { match self { Self::Given(path) => path.to_tokens(tokens), Self::Default => quote::quote! { ::pyo3 }.to_tokens(tokens), } } } pub fn apply_renaming_rule(rule: RenamingRule, name: &str) -> String { use heck::*; match rule { RenamingRule::CamelCase => name.to_lower_camel_case(), RenamingRule::KebabCase => name.to_kebab_case(), RenamingRule::Lowercase => name.to_lowercase(), RenamingRule::PascalCase => name.to_upper_camel_case(), RenamingRule::ScreamingKebabCase => name.to_shouty_kebab_case(), RenamingRule::ScreamingSnakeCase => name.to_shouty_snake_case(), RenamingRule::SnakeCase => name.to_snake_case(), RenamingRule::Uppercase => name.to_uppercase(), } } pub(crate) fn is_abi3() -> bool { pyo3_build_config::get().abi3 } pyo3-macros-backend/src/pymethod.rs0000644000175000017500000017031314661133735020275 0ustar jamespagejamespageuse std::borrow::Cow; use std::ffi::CString; use crate::attributes::{NameAttribute, RenamingRule}; use crate::deprecations::deprecate_trailing_option_default; use crate::method::{CallingConvention, ExtractErrorMode, PyArg}; use crate::params::{check_arg_for_gil_refs, impl_regular_arg_param, Holders}; use crate::utils::PythonDoc; use crate::utils::{Ctx, LitCStr}; use crate::{ method::{FnArg, FnSpec, FnType, SelfType}, pyfunction::PyFunctionOptions, }; use crate::{quotes, utils}; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; use syn::{ext::IdentExt, spanned::Spanned, Result}; /// Generated code for a single pymethod item. pub struct MethodAndMethodDef { /// The implementation of the Python wrapper for the pymethod pub associated_method: TokenStream, /// The method def which will be used to register this pymethod pub method_def: TokenStream, } /// Generated code for a single pymethod item which is registered by a slot. pub struct MethodAndSlotDef { /// The implementation of the Python wrapper for the pymethod pub associated_method: TokenStream, /// The slot def which will be used to register this pymethod pub slot_def: TokenStream, } pub enum GeneratedPyMethod { Method(MethodAndMethodDef), Proto(MethodAndSlotDef), SlotTraitImpl(String, TokenStream), } pub struct PyMethod<'a> { kind: PyMethodKind, method_name: String, spec: FnSpec<'a>, } enum PyMethodKind { Fn, Proto(PyMethodProtoKind), } impl PyMethodKind { fn from_name(name: &str) -> Self { match name { // Protocol implemented through slots "__str__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__STR__)), "__repr__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__REPR__)), "__hash__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__HASH__)), "__richcmp__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__RICHCMP__)), "__get__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__GET__)), "__iter__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ITER__)), "__next__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__NEXT__)), "__await__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__AWAIT__)), "__aiter__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__AITER__)), "__anext__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ANEXT__)), "__len__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__LEN__)), "__contains__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__CONTAINS__)), "__concat__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__CONCAT__)), "__repeat__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__REPEAT__)), "__inplace_concat__" => { PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INPLACE_CONCAT__)) } "__inplace_repeat__" => { PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INPLACE_REPEAT__)) } "__getitem__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__GETITEM__)), "__pos__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__POS__)), "__neg__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__NEG__)), "__abs__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ABS__)), "__invert__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INVERT__)), "__index__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INDEX__)), "__int__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INT__)), "__float__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__FLOAT__)), "__bool__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__BOOL__)), "__iadd__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IADD__)), "__isub__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ISUB__)), "__imul__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IMUL__)), "__imatmul__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IMATMUL__)), "__itruediv__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ITRUEDIV__)), "__ifloordiv__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IFLOORDIV__)), "__imod__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IMOD__)), "__ipow__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IPOW__)), "__ilshift__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ILSHIFT__)), "__irshift__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IRSHIFT__)), "__iand__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IAND__)), "__ixor__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IXOR__)), "__ior__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IOR__)), "__getbuffer__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__GETBUFFER__)), "__releasebuffer__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__RELEASEBUFFER__)), "__clear__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__CLEAR__)), // Protocols implemented through traits "__getattribute__" => { PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GETATTRIBUTE__)) } "__getattr__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GETATTR__)), "__setattr__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SETATTR__)), "__delattr__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DELATTR__)), "__set__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SET__)), "__delete__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DELETE__)), "__setitem__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SETITEM__)), "__delitem__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DELITEM__)), "__add__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__ADD__)), "__radd__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RADD__)), "__sub__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SUB__)), "__rsub__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RSUB__)), "__mul__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__MUL__)), "__rmul__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RMUL__)), "__matmul__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__MATMUL__)), "__rmatmul__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RMATMUL__)), "__floordiv__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__FLOORDIV__)), "__rfloordiv__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RFLOORDIV__)), "__truediv__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__TRUEDIV__)), "__rtruediv__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RTRUEDIV__)), "__divmod__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DIVMOD__)), "__rdivmod__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RDIVMOD__)), "__mod__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__MOD__)), "__rmod__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RMOD__)), "__lshift__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__LSHIFT__)), "__rlshift__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RLSHIFT__)), "__rshift__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RSHIFT__)), "__rrshift__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RRSHIFT__)), "__and__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__AND__)), "__rand__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RAND__)), "__xor__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__XOR__)), "__rxor__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RXOR__)), "__or__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__OR__)), "__ror__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__ROR__)), "__pow__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__POW__)), "__rpow__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RPOW__)), "__lt__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__LT__)), "__le__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__LE__)), "__eq__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__EQ__)), "__ne__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__NE__)), "__gt__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GT__)), "__ge__" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GE__)), // Some tricky protocols which don't fit the pattern of the rest "__call__" => PyMethodKind::Proto(PyMethodProtoKind::Call), "__traverse__" => PyMethodKind::Proto(PyMethodProtoKind::Traverse), // Not a proto _ => PyMethodKind::Fn, } } } enum PyMethodProtoKind { Slot(&'static SlotDef), Call, Traverse, SlotFragment(&'static SlotFragmentDef), } impl<'a> PyMethod<'a> { fn parse( sig: &'a mut syn::Signature, meth_attrs: &mut Vec, options: PyFunctionOptions, ctx: &'a Ctx, ) -> Result { let spec = FnSpec::parse(sig, meth_attrs, options, ctx)?; let method_name = spec.python_name.to_string(); let kind = PyMethodKind::from_name(&method_name); Ok(Self { kind, method_name, spec, }) } } pub fn is_proto_method(name: &str) -> bool { match PyMethodKind::from_name(name) { PyMethodKind::Fn => false, PyMethodKind::Proto(_) => true, } } pub fn gen_py_method( cls: &syn::Type, sig: &mut syn::Signature, meth_attrs: &mut Vec, options: PyFunctionOptions, ctx: &Ctx, ) -> Result { check_generic(sig)?; ensure_function_options_valid(&options)?; let method = PyMethod::parse(sig, meth_attrs, options, ctx)?; let spec = &method.spec; let Ctx { pyo3_path, .. } = ctx; Ok(match (method.kind, &spec.tp) { // Class attributes go before protos so that class attributes can be used to set proto // method to None. (_, FnType::ClassAttribute) => { GeneratedPyMethod::Method(impl_py_class_attribute(cls, spec, ctx)?) } (PyMethodKind::Proto(proto_kind), _) => { ensure_no_forbidden_protocol_attributes(&proto_kind, spec, &method.method_name)?; match proto_kind { PyMethodProtoKind::Slot(slot_def) => { let slot = slot_def.generate_type_slot(cls, spec, &method.method_name, ctx)?; GeneratedPyMethod::Proto(slot) } PyMethodProtoKind::Call => { GeneratedPyMethod::Proto(impl_call_slot(cls, method.spec, ctx)?) } PyMethodProtoKind::Traverse => { GeneratedPyMethod::Proto(impl_traverse_slot(cls, spec, ctx)?) } PyMethodProtoKind::SlotFragment(slot_fragment_def) => { let proto = slot_fragment_def.generate_pyproto_fragment(cls, spec, ctx)?; GeneratedPyMethod::SlotTraitImpl(method.method_name, proto) } } } // ordinary functions (with some specialties) (_, FnType::Fn(_)) => GeneratedPyMethod::Method(impl_py_method_def( cls, spec, &spec.get_doc(meth_attrs, ctx), None, ctx, )?), (_, FnType::FnClass(_)) => GeneratedPyMethod::Method(impl_py_method_def( cls, spec, &spec.get_doc(meth_attrs, ctx), Some(quote!(#pyo3_path::ffi::METH_CLASS)), ctx, )?), (_, FnType::FnStatic) => GeneratedPyMethod::Method(impl_py_method_def( cls, spec, &spec.get_doc(meth_attrs, ctx), Some(quote!(#pyo3_path::ffi::METH_STATIC)), ctx, )?), // special prototypes (_, FnType::FnNew) | (_, FnType::FnNewClass(_)) => { GeneratedPyMethod::Proto(impl_py_method_def_new(cls, spec, ctx)?) } (_, FnType::Getter(self_type)) => GeneratedPyMethod::Method(impl_py_getter_def( cls, PropertyType::Function { self_type, spec, doc: spec.get_doc(meth_attrs, ctx), }, ctx, )?), (_, FnType::Setter(self_type)) => GeneratedPyMethod::Method(impl_py_setter_def( cls, PropertyType::Function { self_type, spec, doc: spec.get_doc(meth_attrs, ctx), }, ctx, )?), (_, FnType::FnModule(_)) => { unreachable!("methods cannot be FnModule") } }) } pub fn check_generic(sig: &syn::Signature) -> syn::Result<()> { let err_msg = |typ| format!("Python functions cannot have generic {} parameters", typ); for param in &sig.generics.params { match param { syn::GenericParam::Lifetime(_) => {} syn::GenericParam::Type(_) => bail_spanned!(param.span() => err_msg("type")), syn::GenericParam::Const(_) => bail_spanned!(param.span() => err_msg("const")), } } Ok(()) } fn ensure_function_options_valid(options: &PyFunctionOptions) -> syn::Result<()> { if let Some(pass_module) = &options.pass_module { bail_spanned!(pass_module.span() => "`pass_module` cannot be used on Python methods"); } Ok(()) } fn ensure_no_forbidden_protocol_attributes( proto_kind: &PyMethodProtoKind, spec: &FnSpec<'_>, method_name: &str, ) -> syn::Result<()> { if let Some(signature) = &spec.signature.attribute { // __call__ is allowed to have a signature, but nothing else is. if !matches!(proto_kind, PyMethodProtoKind::Call) { bail_spanned!(signature.kw.span() => format!("`signature` cannot be used with magic method `{}`", method_name)); } } if let Some(text_signature) = &spec.text_signature { bail_spanned!(text_signature.kw.span() => format!("`text_signature` cannot be used with magic method `{}`", method_name)); } Ok(()) } /// Also used by pyfunction. pub fn impl_py_method_def( cls: &syn::Type, spec: &FnSpec<'_>, doc: &PythonDoc, flags: Option, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let wrapper_ident = format_ident!("__pymethod_{}__", spec.python_name); let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls), ctx)?; let add_flags = flags.map(|flags| quote!(.flags(#flags))); let methoddef_type = match spec.tp { FnType::FnStatic => quote!(Static), FnType::FnClass(_) => quote!(Class), _ => quote!(Method), }; let methoddef = spec.get_methoddef(quote! { #cls::#wrapper_ident }, doc, ctx); let method_def = quote! { #pyo3_path::impl_::pyclass::MaybeRuntimePyMethodDef::Static( #pyo3_path::class::PyMethodDefType::#methoddef_type(#methoddef #add_flags) ) }; Ok(MethodAndMethodDef { associated_method, method_def, }) } /// Also used by pyclass. pub fn impl_py_method_def_new( cls: &syn::Type, spec: &FnSpec<'_>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let wrapper_ident = syn::Ident::new("__pymethod___new____", Span::call_site()); let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls), ctx)?; // Use just the text_signature_call_signature() because the class' Python name // isn't known to `#[pymethods]` - that has to be attached at runtime from the PyClassImpl // trait implementation created by `#[pyclass]`. let text_signature_body = spec.text_signature_call_signature().map_or_else( || quote!(::std::option::Option::None), |text_signature| quote!(::std::option::Option::Some(#text_signature)), ); let deprecations = &spec.deprecations; let slot_def = quote! { #pyo3_path::ffi::PyType_Slot { slot: #pyo3_path::ffi::Py_tp_new, pfunc: { unsafe extern "C" fn trampoline( subtype: *mut #pyo3_path::ffi::PyTypeObject, args: *mut #pyo3_path::ffi::PyObject, kwargs: *mut #pyo3_path::ffi::PyObject, ) -> *mut #pyo3_path::ffi::PyObject { #deprecations use #pyo3_path::impl_::pyclass::*; #[allow(unknown_lints, non_local_definitions)] impl PyClassNewTextSignature<#cls> for PyClassImplCollector<#cls> { #[inline] fn new_text_signature(self) -> ::std::option::Option<&'static str> { #text_signature_body } } #pyo3_path::impl_::trampoline::newfunc( subtype, args, kwargs, #cls::#wrapper_ident ) } trampoline } as #pyo3_path::ffi::newfunc as _ } }; Ok(MethodAndSlotDef { associated_method, slot_def, }) } fn impl_call_slot(cls: &syn::Type, mut spec: FnSpec<'_>, ctx: &Ctx) -> Result { let Ctx { pyo3_path, .. } = ctx; // HACK: __call__ proto slot must always use varargs calling convention, so change the spec. // Probably indicates there's a refactoring opportunity somewhere. spec.convention = CallingConvention::Varargs; let wrapper_ident = syn::Ident::new("__pymethod___call____", Span::call_site()); let associated_method = spec.get_wrapper_function(&wrapper_ident, Some(cls), ctx)?; let slot_def = quote! { #pyo3_path::ffi::PyType_Slot { slot: #pyo3_path::ffi::Py_tp_call, pfunc: { unsafe extern "C" fn trampoline( slf: *mut #pyo3_path::ffi::PyObject, args: *mut #pyo3_path::ffi::PyObject, kwargs: *mut #pyo3_path::ffi::PyObject, ) -> *mut #pyo3_path::ffi::PyObject { #pyo3_path::impl_::trampoline::ternaryfunc( slf, args, kwargs, #cls::#wrapper_ident ) } trampoline } as #pyo3_path::ffi::ternaryfunc as _ } }; Ok(MethodAndSlotDef { associated_method, slot_def, }) } fn impl_traverse_slot( cls: &syn::Type, spec: &FnSpec<'_>, ctx: &Ctx, ) -> syn::Result { let Ctx { pyo3_path, .. } = ctx; if let (Some(py_arg), _) = split_off_python_arg(&spec.signature.arguments) { return Err(syn::Error::new_spanned(py_arg.ty, "__traverse__ may not take `Python`. \ Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` \ should do nothing but calls to `visit.call`. Most importantly, safe access to the GIL is prohibited \ inside implementations of `__traverse__`, i.e. `Python::with_gil` will panic.")); } // check that the receiver does not try to smuggle an (implicit) `Python` token into here if let FnType::Fn(SelfType::TryFromBoundRef(span)) | FnType::Fn(SelfType::Receiver { mutable: true, span, }) = spec.tp { bail_spanned! { span => "__traverse__ may not take a receiver other than `&self`. Usually, an implementation of \ `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` \ should do nothing but calls to `visit.call`. Most importantly, safe access to the GIL is prohibited \ inside implementations of `__traverse__`, i.e. `Python::with_gil` will panic." } } let rust_fn_ident = spec.name; let associated_method = quote! { pub unsafe extern "C" fn __pymethod_traverse__( slf: *mut #pyo3_path::ffi::PyObject, visit: #pyo3_path::ffi::visitproc, arg: *mut ::std::os::raw::c_void, ) -> ::std::os::raw::c_int { #pyo3_path::impl_::pymethods::_call_traverse::<#cls>(slf, #cls::#rust_fn_ident, visit, arg) } }; let slot_def = quote! { #pyo3_path::ffi::PyType_Slot { slot: #pyo3_path::ffi::Py_tp_traverse, pfunc: #cls::__pymethod_traverse__ as #pyo3_path::ffi::traverseproc as _ } }; Ok(MethodAndSlotDef { associated_method, slot_def, }) } fn impl_py_class_attribute( cls: &syn::Type, spec: &FnSpec<'_>, ctx: &Ctx, ) -> syn::Result { let Ctx { pyo3_path, .. } = ctx; let (py_arg, args) = split_off_python_arg(&spec.signature.arguments); ensure_spanned!( args.is_empty(), args[0].ty().span() => "#[classattr] can only have one argument (of type pyo3::Python)" ); let name = &spec.name; let fncall = if py_arg.is_some() { quote!(function(py)) } else { quote!(function()) }; let wrapper_ident = format_ident!("__pymethod_{}__", name); let python_name = spec.null_terminated_python_name(ctx); let body = quotes::ok_wrap(fncall, ctx); let associated_method = quote! { fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> { let function = #cls::#name; // Shadow the method name to avoid #3017 #pyo3_path::impl_::wrap::map_result_into_py(py, #body) } }; let method_def = quote! { #pyo3_path::impl_::pyclass::MaybeRuntimePyMethodDef::Static( #pyo3_path::class::PyMethodDefType::ClassAttribute({ #pyo3_path::class::PyClassAttributeDef::new( #python_name, #cls::#wrapper_ident ) }) ) }; Ok(MethodAndMethodDef { associated_method, method_def, }) } fn impl_call_setter( cls: &syn::Type, spec: &FnSpec<'_>, self_type: &SelfType, holders: &mut Holders, ctx: &Ctx, ) -> syn::Result { let (py_arg, args) = split_off_python_arg(&spec.signature.arguments); let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders, ctx); if args.is_empty() { bail_spanned!(spec.name.span() => "setter function expected to have one argument"); } else if args.len() > 1 { bail_spanned!( args[1].ty().span() => "setter function can have at most two arguments ([pyo3::Python,] and value)" ); } let name = &spec.name; let fncall = if py_arg.is_some() { quote!(#cls::#name(#slf, py, _val)) } else { quote!(#cls::#name(#slf, _val)) }; Ok(fncall) } // Used here for PropertyType::Function, used in pyclass for descriptors. pub fn impl_py_setter_def( cls: &syn::Type, property_type: PropertyType<'_>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let python_name = property_type.null_terminated_python_name(ctx)?; let doc = property_type.doc(ctx); let mut holders = Holders::new(); let setter_impl = match property_type { PropertyType::Descriptor { field_index, field, .. } => { let slf = SelfType::Receiver { mutable: true, span: Span::call_site(), } .receiver(cls, ExtractErrorMode::Raise, &mut holders, ctx); if let Some(ident) = &field.ident { // named struct field quote!({ #slf.#ident = _val; }) } else { // tuple struct field let index = syn::Index::from(field_index); quote!({ #slf.#index = _val; }) } } PropertyType::Function { spec, self_type, .. } => impl_call_setter(cls, spec, self_type, &mut holders, ctx)?, }; let wrapper_ident = match property_type { PropertyType::Descriptor { field: syn::Field { ident: Some(ident), .. }, .. } => { format_ident!("__pymethod_set_{}__", ident) } PropertyType::Descriptor { field_index, .. } => { format_ident!("__pymethod_set_field_{}__", field_index) } PropertyType::Function { spec, .. } => { format_ident!("__pymethod_set_{}__", spec.name) } }; let extract = match &property_type { PropertyType::Function { spec, .. } => { let (_, args) = split_off_python_arg(&spec.signature.arguments); let value_arg = &args[0]; let (from_py_with, ident) = if let Some(from_py_with) = &value_arg.from_py_with().as_ref().map(|f| &f.value) { let ident = syn::Ident::new("from_py_with", from_py_with.span()); ( quote_spanned! { from_py_with.span() => let e = #pyo3_path::impl_::deprecations::GilRefs::new(); let #ident = #pyo3_path::impl_::deprecations::inspect_fn(#from_py_with, &e); e.from_py_with_arg(); }, ident, ) } else { (quote!(), syn::Ident::new("dummy", Span::call_site())) }; let arg = if let FnArg::Regular(arg) = &value_arg { arg } else { bail_spanned!(value_arg.name().span() => "The #[setter] value argument can't be *args, **kwargs or `cancel_handle`."); }; let tokens = impl_regular_arg_param( arg, ident, quote!(::std::option::Option::Some(_value.into())), &mut holders, ctx, ); let extract = check_arg_for_gil_refs(tokens, holders.push_gil_refs_checker(arg.ty.span()), ctx); let deprecation = deprecate_trailing_option_default(spec); quote! { #deprecation #from_py_with let _val = #extract; } } PropertyType::Descriptor { field, .. } => { let span = field.ty.span(); let name = field .ident .as_ref() .map(|i| i.to_string()) .unwrap_or_default(); let holder = holders.push_holder(span); let gil_refs_checker = holders.push_gil_refs_checker(span); quote! { let _val = #pyo3_path::impl_::deprecations::inspect_type( #pyo3_path::impl_::extract_argument::extract_argument(_value.into(), &mut #holder, #name)?, &#gil_refs_checker ); } } }; let mut cfg_attrs = TokenStream::new(); if let PropertyType::Descriptor { field, .. } = &property_type { for attr in field .attrs .iter() .filter(|attr| attr.path().is_ident("cfg")) { attr.to_tokens(&mut cfg_attrs); } } let init_holders = holders.init_holders(ctx); let check_gil_refs = holders.check_gil_refs(); let associated_method = quote! { #cfg_attrs unsafe fn #wrapper_ident( py: #pyo3_path::Python<'_>, _slf: *mut #pyo3_path::ffi::PyObject, _value: *mut #pyo3_path::ffi::PyObject, ) -> #pyo3_path::PyResult<::std::os::raw::c_int> { use ::std::convert::Into; let _value = #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr_or_opt(py, &_value) .ok_or_else(|| { #pyo3_path::exceptions::PyAttributeError::new_err("can't delete attribute") })?; #init_holders #extract let result = #setter_impl; #check_gil_refs #pyo3_path::callback::convert(py, result) } }; let method_def = quote! { #cfg_attrs #pyo3_path::impl_::pyclass::MaybeRuntimePyMethodDef::Static( #pyo3_path::class::PyMethodDefType::Setter( #pyo3_path::class::PySetterDef::new( #python_name, #cls::#wrapper_ident, #doc ) ) ) }; Ok(MethodAndMethodDef { associated_method, method_def, }) } fn impl_call_getter( cls: &syn::Type, spec: &FnSpec<'_>, self_type: &SelfType, holders: &mut Holders, ctx: &Ctx, ) -> syn::Result { let (py_arg, args) = split_off_python_arg(&spec.signature.arguments); let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders, ctx); ensure_spanned!( args.is_empty(), args[0].ty().span() => "getter function can only have one argument (of type pyo3::Python)" ); let name = &spec.name; let fncall = if py_arg.is_some() { quote!(#cls::#name(#slf, py)) } else { quote!(#cls::#name(#slf)) }; Ok(fncall) } // Used here for PropertyType::Function, used in pyclass for descriptors. pub fn impl_py_getter_def( cls: &syn::Type, property_type: PropertyType<'_>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let python_name = property_type.null_terminated_python_name(ctx)?; let doc = property_type.doc(ctx); let mut cfg_attrs = TokenStream::new(); if let PropertyType::Descriptor { field, .. } = &property_type { for attr in field .attrs .iter() .filter(|attr| attr.path().is_ident("cfg")) { attr.to_tokens(&mut cfg_attrs); } } let mut holders = Holders::new(); match property_type { PropertyType::Descriptor { field_index, field, .. } => { let ty = &field.ty; let field = if let Some(ident) = &field.ident { ident.to_token_stream() } else { syn::Index::from(field_index).to_token_stream() }; // TODO: on MSRV 1.77+, we can use `::std::mem::offset_of!` here, and it should // make it possible for the `MaybeRuntimePyMethodDef` to be a `Static` variant. let method_def = quote_spanned! {ty.span()=> #cfg_attrs { #[allow(unused_imports)] // might not be used if all probes are positve use #pyo3_path::impl_::pyclass::Probe; struct Offset; unsafe impl #pyo3_path::impl_::pyclass::OffsetCalculator<#cls, #ty> for Offset { fn offset() -> usize { #pyo3_path::impl_::pyclass::class_offset::<#cls>() + #pyo3_path::impl_::pyclass::offset_of!(#cls, #field) } } const GENERATOR: #pyo3_path::impl_::pyclass::PyClassGetterGenerator::< #cls, #ty, Offset, { #pyo3_path::impl_::pyclass::IsPyT::<#ty>::VALUE }, { #pyo3_path::impl_::pyclass::IsToPyObject::<#ty>::VALUE }, > = unsafe { #pyo3_path::impl_::pyclass::PyClassGetterGenerator::new() }; #pyo3_path::impl_::pyclass::MaybeRuntimePyMethodDef::Runtime( || GENERATOR.generate(#python_name, #doc) ) } }; Ok(MethodAndMethodDef { associated_method: quote! {}, method_def, }) } // Forward to `IntoPyCallbackOutput`, to handle `#[getter]`s returning results. PropertyType::Function { spec, self_type, .. } => { let wrapper_ident = format_ident!("__pymethod_get_{}__", spec.name); let call = impl_call_getter(cls, spec, self_type, &mut holders, ctx)?; let body = quote! { #pyo3_path::callback::convert(py, #call) }; let init_holders = holders.init_holders(ctx); let check_gil_refs = holders.check_gil_refs(); let associated_method = quote! { #cfg_attrs unsafe fn #wrapper_ident( py: #pyo3_path::Python<'_>, _slf: *mut #pyo3_path::ffi::PyObject ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> { #init_holders let result = #body; #check_gil_refs result } }; let method_def = quote! { #cfg_attrs #pyo3_path::impl_::pyclass::MaybeRuntimePyMethodDef::Static( #pyo3_path::class::PyMethodDefType::Getter( #pyo3_path::class::PyGetterDef::new( #python_name, #cls::#wrapper_ident, #doc ) ) ) }; Ok(MethodAndMethodDef { associated_method, method_def, }) } } } /// Split an argument of pyo3::Python from the front of the arg list, if present fn split_off_python_arg<'a>(args: &'a [FnArg<'a>]) -> (Option<&PyArg<'_>>, &[FnArg<'_>]) { match args { [FnArg::Py(py), args @ ..] => (Some(py), args), args => (None, args), } } pub enum PropertyType<'a> { Descriptor { field_index: usize, field: &'a syn::Field, python_name: Option<&'a NameAttribute>, renaming_rule: Option, }, Function { self_type: &'a SelfType, spec: &'a FnSpec<'a>, doc: PythonDoc, }, } impl PropertyType<'_> { fn null_terminated_python_name(&self, ctx: &Ctx) -> Result { match self { PropertyType::Descriptor { field, python_name, renaming_rule, .. } => { let name = match (python_name, &field.ident) { (Some(name), _) => name.value.0.to_string(), (None, Some(field_name)) => { let mut name = field_name.unraw().to_string(); if let Some(rule) = renaming_rule { name = utils::apply_renaming_rule(*rule, &name); } name } (None, None) => { bail_spanned!(field.span() => "`get` and `set` with tuple struct fields require `name`"); } }; let name = CString::new(name).unwrap(); Ok(LitCStr::new(name, field.span(), ctx)) } PropertyType::Function { spec, .. } => Ok(spec.null_terminated_python_name(ctx)), } } fn doc(&self, ctx: &Ctx) -> Cow<'_, PythonDoc> { match self { PropertyType::Descriptor { field, .. } => { Cow::Owned(utils::get_doc(&field.attrs, None, ctx)) } PropertyType::Function { doc, .. } => Cow::Borrowed(doc), } } } const __STR__: SlotDef = SlotDef::new("Py_tp_str", "reprfunc"); pub const __REPR__: SlotDef = SlotDef::new("Py_tp_repr", "reprfunc"); pub const __HASH__: SlotDef = SlotDef::new("Py_tp_hash", "hashfunc") .ret_ty(Ty::PyHashT) .return_conversion(TokenGenerator( |Ctx { pyo3_path, .. }: &Ctx| quote! { #pyo3_path::callback::HashCallbackOutput }, )); pub const __RICHCMP__: SlotDef = SlotDef::new("Py_tp_richcompare", "richcmpfunc") .extract_error_mode(ExtractErrorMode::NotImplemented) .arguments(&[Ty::Object, Ty::CompareOp]); const __GET__: SlotDef = SlotDef::new("Py_tp_descr_get", "descrgetfunc") .arguments(&[Ty::MaybeNullObject, Ty::MaybeNullObject]); const __ITER__: SlotDef = SlotDef::new("Py_tp_iter", "getiterfunc"); const __NEXT__: SlotDef = SlotDef::new("Py_tp_iternext", "iternextfunc") .return_specialized_conversion( TokenGenerator(|_| quote! { IterBaseKind, IterOptionKind, IterResultOptionKind }), TokenGenerator(|_| quote! { iter_tag }), ); const __AWAIT__: SlotDef = SlotDef::new("Py_am_await", "unaryfunc"); const __AITER__: SlotDef = SlotDef::new("Py_am_aiter", "unaryfunc"); const __ANEXT__: SlotDef = SlotDef::new("Py_am_anext", "unaryfunc").return_specialized_conversion( TokenGenerator( |_| quote! { AsyncIterBaseKind, AsyncIterOptionKind, AsyncIterResultOptionKind }, ), TokenGenerator(|_| quote! { async_iter_tag }), ); pub const __LEN__: SlotDef = SlotDef::new("Py_mp_length", "lenfunc").ret_ty(Ty::PySsizeT); const __CONTAINS__: SlotDef = SlotDef::new("Py_sq_contains", "objobjproc") .arguments(&[Ty::Object]) .ret_ty(Ty::Int); const __CONCAT__: SlotDef = SlotDef::new("Py_sq_concat", "binaryfunc").arguments(&[Ty::Object]); const __REPEAT__: SlotDef = SlotDef::new("Py_sq_repeat", "ssizeargfunc").arguments(&[Ty::PySsizeT]); const __INPLACE_CONCAT__: SlotDef = SlotDef::new("Py_sq_concat", "binaryfunc").arguments(&[Ty::Object]); const __INPLACE_REPEAT__: SlotDef = SlotDef::new("Py_sq_repeat", "ssizeargfunc").arguments(&[Ty::PySsizeT]); pub const __GETITEM__: SlotDef = SlotDef::new("Py_mp_subscript", "binaryfunc").arguments(&[Ty::Object]); const __POS__: SlotDef = SlotDef::new("Py_nb_positive", "unaryfunc"); const __NEG__: SlotDef = SlotDef::new("Py_nb_negative", "unaryfunc"); const __ABS__: SlotDef = SlotDef::new("Py_nb_absolute", "unaryfunc"); const __INVERT__: SlotDef = SlotDef::new("Py_nb_invert", "unaryfunc"); const __INDEX__: SlotDef = SlotDef::new("Py_nb_index", "unaryfunc"); pub const __INT__: SlotDef = SlotDef::new("Py_nb_int", "unaryfunc"); const __FLOAT__: SlotDef = SlotDef::new("Py_nb_float", "unaryfunc"); const __BOOL__: SlotDef = SlotDef::new("Py_nb_bool", "inquiry").ret_ty(Ty::Int); const __IADD__: SlotDef = SlotDef::new("Py_nb_inplace_add", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __ISUB__: SlotDef = SlotDef::new("Py_nb_inplace_subtract", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IMUL__: SlotDef = SlotDef::new("Py_nb_inplace_multiply", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IMATMUL__: SlotDef = SlotDef::new("Py_nb_inplace_matrix_multiply", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __ITRUEDIV__: SlotDef = SlotDef::new("Py_nb_inplace_true_divide", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IFLOORDIV__: SlotDef = SlotDef::new("Py_nb_inplace_floor_divide", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IMOD__: SlotDef = SlotDef::new("Py_nb_inplace_remainder", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IPOW__: SlotDef = SlotDef::new("Py_nb_inplace_power", "ipowfunc") .arguments(&[Ty::Object, Ty::IPowModulo]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __ILSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_lshift", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IRSHIFT__: SlotDef = SlotDef::new("Py_nb_inplace_rshift", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IAND__: SlotDef = SlotDef::new("Py_nb_inplace_and", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IXOR__: SlotDef = SlotDef::new("Py_nb_inplace_xor", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __IOR__: SlotDef = SlotDef::new("Py_nb_inplace_or", "binaryfunc") .arguments(&[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .return_self(); const __GETBUFFER__: SlotDef = SlotDef::new("Py_bf_getbuffer", "getbufferproc") .arguments(&[Ty::PyBuffer, Ty::Int]) .ret_ty(Ty::Int) .require_unsafe(); const __RELEASEBUFFER__: SlotDef = SlotDef::new("Py_bf_releasebuffer", "releasebufferproc") .arguments(&[Ty::PyBuffer]) .ret_ty(Ty::Void) .require_unsafe(); const __CLEAR__: SlotDef = SlotDef::new("Py_tp_clear", "inquiry") .arguments(&[]) .ret_ty(Ty::Int); #[derive(Clone, Copy)] enum Ty { Object, MaybeNullObject, NonNullObject, IPowModulo, CompareOp, Int, PyHashT, PySsizeT, Void, PyBuffer, } impl Ty { fn ffi_type(self, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, output_span, } = ctx; let pyo3_path = pyo3_path.to_tokens_spanned(*output_span); match self { Ty::Object | Ty::MaybeNullObject => quote! { *mut #pyo3_path::ffi::PyObject }, Ty::NonNullObject => quote! { ::std::ptr::NonNull<#pyo3_path::ffi::PyObject> }, Ty::IPowModulo => quote! { #pyo3_path::impl_::pymethods::IPowModulo }, Ty::Int | Ty::CompareOp => quote! { ::std::os::raw::c_int }, Ty::PyHashT => quote! { #pyo3_path::ffi::Py_hash_t }, Ty::PySsizeT => quote! { #pyo3_path::ffi::Py_ssize_t }, Ty::Void => quote! { () }, Ty::PyBuffer => quote! { *mut #pyo3_path::ffi::Py_buffer }, } } fn extract( self, ident: &syn::Ident, arg: &FnArg<'_>, extract_error_mode: ExtractErrorMode, holders: &mut Holders, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; match self { Ty::Object => extract_object( extract_error_mode, holders, arg, quote! { #ident }, ctx ), Ty::MaybeNullObject => extract_object( extract_error_mode, holders, arg, quote! { if #ident.is_null() { #pyo3_path::ffi::Py_None() } else { #ident } }, ctx ), Ty::NonNullObject => extract_object( extract_error_mode, holders, arg, quote! { #ident.as_ptr() }, ctx ), Ty::IPowModulo => extract_object( extract_error_mode, holders, arg, quote! { #ident.as_ptr() }, ctx ), Ty::CompareOp => extract_error_mode.handle_error( quote! { #pyo3_path::class::basic::CompareOp::from_raw(#ident) .ok_or_else(|| #pyo3_path::exceptions::PyValueError::new_err("invalid comparison operator")) }, ctx ), Ty::PySsizeT => { let ty = arg.ty(); extract_error_mode.handle_error( quote! { ::std::convert::TryInto::<#ty>::try_into(#ident).map_err(|e| #pyo3_path::exceptions::PyValueError::new_err(e.to_string())) }, ctx ) } // Just pass other types through unmodified Ty::PyBuffer | Ty::Int | Ty::PyHashT | Ty::Void => quote! { #ident }, } } } fn extract_object( extract_error_mode: ExtractErrorMode, holders: &mut Holders, arg: &FnArg<'_>, source_ptr: TokenStream, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let gil_refs_checker = holders.push_gil_refs_checker(arg.ty().span()); let name = arg.name().unraw().to_string(); let extract = if let Some(from_py_with) = arg.from_py_with().map(|from_py_with| &from_py_with.value) { let from_py_with_checker = holders.push_from_py_with_checker(from_py_with.span()); quote! { #pyo3_path::impl_::extract_argument::from_py_with( #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr).0, #name, #pyo3_path::impl_::deprecations::inspect_fn(#from_py_with, &#from_py_with_checker) as fn(_) -> _, ) } } else { let holder = holders.push_holder(Span::call_site()); quote! { #pyo3_path::impl_::extract_argument::extract_argument( #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(py, &#source_ptr).0, &mut #holder, #name ) } }; let extracted = extract_error_mode.handle_error(extract, ctx); quote! { #pyo3_path::impl_::deprecations::inspect_type(#extracted, &#gil_refs_checker) } } enum ReturnMode { ReturnSelf, Conversion(TokenGenerator), SpecializedConversion(TokenGenerator, TokenGenerator), } impl ReturnMode { fn return_call_output(&self, call: TokenStream, ctx: &Ctx, holders: &Holders) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let check_gil_refs = holders.check_gil_refs(); match self { ReturnMode::Conversion(conversion) => { let conversion = TokenGeneratorCtx(*conversion, ctx); quote! { let _result: #pyo3_path::PyResult<#conversion> = #pyo3_path::callback::convert(py, #call); #check_gil_refs #pyo3_path::callback::convert(py, _result) } } ReturnMode::SpecializedConversion(traits, tag) => { let traits = TokenGeneratorCtx(*traits, ctx); let tag = TokenGeneratorCtx(*tag, ctx); quote! { let _result = #call; use #pyo3_path::impl_::pymethods::{#traits}; #check_gil_refs (&_result).#tag().convert(py, _result) } } ReturnMode::ReturnSelf => quote! { let _result: #pyo3_path::PyResult<()> = #pyo3_path::callback::convert(py, #call); _result?; #check_gil_refs #pyo3_path::ffi::Py_XINCREF(_raw_slf); ::std::result::Result::Ok(_raw_slf) }, } } } pub struct SlotDef { slot: StaticIdent, func_ty: StaticIdent, arguments: &'static [Ty], ret_ty: Ty, extract_error_mode: ExtractErrorMode, return_mode: Option, require_unsafe: bool, } const NO_ARGUMENTS: &[Ty] = &[]; impl SlotDef { const fn new(slot: &'static str, func_ty: &'static str) -> Self { SlotDef { slot: StaticIdent(slot), func_ty: StaticIdent(func_ty), arguments: NO_ARGUMENTS, ret_ty: Ty::Object, extract_error_mode: ExtractErrorMode::Raise, return_mode: None, require_unsafe: false, } } const fn arguments(mut self, arguments: &'static [Ty]) -> Self { self.arguments = arguments; self } const fn ret_ty(mut self, ret_ty: Ty) -> Self { self.ret_ty = ret_ty; self } const fn return_conversion(mut self, return_conversion: TokenGenerator) -> Self { self.return_mode = Some(ReturnMode::Conversion(return_conversion)); self } const fn return_specialized_conversion( mut self, traits: TokenGenerator, tag: TokenGenerator, ) -> Self { self.return_mode = Some(ReturnMode::SpecializedConversion(traits, tag)); self } const fn extract_error_mode(mut self, extract_error_mode: ExtractErrorMode) -> Self { self.extract_error_mode = extract_error_mode; self } const fn return_self(mut self) -> Self { self.return_mode = Some(ReturnMode::ReturnSelf); self } const fn require_unsafe(mut self) -> Self { self.require_unsafe = true; self } pub fn generate_type_slot( &self, cls: &syn::Type, spec: &FnSpec<'_>, method_name: &str, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let SlotDef { slot, func_ty, arguments, extract_error_mode, ret_ty, return_mode, require_unsafe, } = self; if *require_unsafe { ensure_spanned!( spec.unsafety.is_some(), spec.name.span() => format!("`{}` must be `unsafe fn`", method_name) ); } let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type(ctx)).collect(); let arg_idents: &Vec<_> = &(0..arguments.len()) .map(|i| format_ident!("arg{}", i)) .collect(); let wrapper_ident = format_ident!("__pymethod_{}__", method_name); let ret_ty = ret_ty.ffi_type(ctx); let mut holders = Holders::new(); let body = generate_method_body( cls, spec, arguments, *extract_error_mode, &mut holders, return_mode.as_ref(), ctx, )?; let name = spec.name; let holders = holders.init_holders(ctx); let associated_method = quote! { unsafe fn #wrapper_ident( py: #pyo3_path::Python<'_>, _raw_slf: *mut #pyo3_path::ffi::PyObject, #(#arg_idents: #arg_types),* ) -> #pyo3_path::PyResult<#ret_ty> { let function = #cls::#name; // Shadow the method name to avoid #3017 let _slf = _raw_slf; #holders #body } }; let slot_def = quote! {{ unsafe extern "C" fn trampoline( _slf: *mut #pyo3_path::ffi::PyObject, #(#arg_idents: #arg_types),* ) -> #ret_ty { #pyo3_path::impl_::trampoline:: #func_ty ( _slf, #(#arg_idents,)* #cls::#wrapper_ident ) } #pyo3_path::ffi::PyType_Slot { slot: #pyo3_path::ffi::#slot, pfunc: trampoline as #pyo3_path::ffi::#func_ty as _ } }}; Ok(MethodAndSlotDef { associated_method, slot_def, }) } } fn generate_method_body( cls: &syn::Type, spec: &FnSpec<'_>, arguments: &[Ty], extract_error_mode: ExtractErrorMode, holders: &mut Holders, return_mode: Option<&ReturnMode>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let self_arg = spec .tp .self_arg(Some(cls), extract_error_mode, holders, ctx); let rust_name = spec.name; let args = extract_proto_arguments(spec, arguments, extract_error_mode, holders, ctx)?; let call = quote! { #cls::#rust_name(#self_arg #(#args),*) }; Ok(if let Some(return_mode) = return_mode { return_mode.return_call_output(call, ctx, holders) } else { let check_gil_refs = holders.check_gil_refs(); quote! { let result = #call; #check_gil_refs; #pyo3_path::callback::convert(py, result) } }) } struct SlotFragmentDef { fragment: &'static str, arguments: &'static [Ty], extract_error_mode: ExtractErrorMode, ret_ty: Ty, } impl SlotFragmentDef { const fn new(fragment: &'static str, arguments: &'static [Ty]) -> Self { SlotFragmentDef { fragment, arguments, extract_error_mode: ExtractErrorMode::Raise, ret_ty: Ty::Void, } } const fn extract_error_mode(mut self, extract_error_mode: ExtractErrorMode) -> Self { self.extract_error_mode = extract_error_mode; self } const fn ret_ty(mut self, ret_ty: Ty) -> Self { self.ret_ty = ret_ty; self } fn generate_pyproto_fragment( &self, cls: &syn::Type, spec: &FnSpec<'_>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let SlotFragmentDef { fragment, arguments, extract_error_mode, ret_ty, } = self; let fragment_trait = format_ident!("PyClass{}SlotFragment", fragment); let method = syn::Ident::new(fragment, Span::call_site()); let wrapper_ident = format_ident!("__pymethod_{}__", fragment); let arg_types: &Vec<_> = &arguments.iter().map(|arg| arg.ffi_type(ctx)).collect(); let arg_idents: &Vec<_> = &(0..arguments.len()) .map(|i| format_ident!("arg{}", i)) .collect(); let mut holders = Holders::new(); let body = generate_method_body( cls, spec, arguments, *extract_error_mode, &mut holders, None, ctx, )?; let ret_ty = ret_ty.ffi_type(ctx); let holders = holders.init_holders(ctx); Ok(quote! { impl #cls { unsafe fn #wrapper_ident( py: #pyo3_path::Python, _raw_slf: *mut #pyo3_path::ffi::PyObject, #(#arg_idents: #arg_types),* ) -> #pyo3_path::PyResult<#ret_ty> { let _slf = _raw_slf; #holders #body } } impl #pyo3_path::impl_::pyclass::#fragment_trait<#cls> for #pyo3_path::impl_::pyclass::PyClassImplCollector<#cls> { #[inline] unsafe fn #method( self, py: #pyo3_path::Python, _raw_slf: *mut #pyo3_path::ffi::PyObject, #(#arg_idents: #arg_types),* ) -> #pyo3_path::PyResult<#ret_ty> { #cls::#wrapper_ident(py, _raw_slf, #(#arg_idents),*) } } }) } } const __GETATTRIBUTE__: SlotFragmentDef = SlotFragmentDef::new("__getattribute__", &[Ty::Object]).ret_ty(Ty::Object); const __GETATTR__: SlotFragmentDef = SlotFragmentDef::new("__getattr__", &[Ty::Object]).ret_ty(Ty::Object); const __SETATTR__: SlotFragmentDef = SlotFragmentDef::new("__setattr__", &[Ty::Object, Ty::NonNullObject]); const __DELATTR__: SlotFragmentDef = SlotFragmentDef::new("__delattr__", &[Ty::Object]); const __SET__: SlotFragmentDef = SlotFragmentDef::new("__set__", &[Ty::Object, Ty::NonNullObject]); const __DELETE__: SlotFragmentDef = SlotFragmentDef::new("__delete__", &[Ty::Object]); const __SETITEM__: SlotFragmentDef = SlotFragmentDef::new("__setitem__", &[Ty::Object, Ty::NonNullObject]); const __DELITEM__: SlotFragmentDef = SlotFragmentDef::new("__delitem__", &[Ty::Object]); macro_rules! binary_num_slot_fragment_def { ($ident:ident, $name:literal) => { const $ident: SlotFragmentDef = SlotFragmentDef::new($name, &[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); }; } binary_num_slot_fragment_def!(__ADD__, "__add__"); binary_num_slot_fragment_def!(__RADD__, "__radd__"); binary_num_slot_fragment_def!(__SUB__, "__sub__"); binary_num_slot_fragment_def!(__RSUB__, "__rsub__"); binary_num_slot_fragment_def!(__MUL__, "__mul__"); binary_num_slot_fragment_def!(__RMUL__, "__rmul__"); binary_num_slot_fragment_def!(__MATMUL__, "__matmul__"); binary_num_slot_fragment_def!(__RMATMUL__, "__rmatmul__"); binary_num_slot_fragment_def!(__FLOORDIV__, "__floordiv__"); binary_num_slot_fragment_def!(__RFLOORDIV__, "__rfloordiv__"); binary_num_slot_fragment_def!(__TRUEDIV__, "__truediv__"); binary_num_slot_fragment_def!(__RTRUEDIV__, "__rtruediv__"); binary_num_slot_fragment_def!(__DIVMOD__, "__divmod__"); binary_num_slot_fragment_def!(__RDIVMOD__, "__rdivmod__"); binary_num_slot_fragment_def!(__MOD__, "__mod__"); binary_num_slot_fragment_def!(__RMOD__, "__rmod__"); binary_num_slot_fragment_def!(__LSHIFT__, "__lshift__"); binary_num_slot_fragment_def!(__RLSHIFT__, "__rlshift__"); binary_num_slot_fragment_def!(__RSHIFT__, "__rshift__"); binary_num_slot_fragment_def!(__RRSHIFT__, "__rrshift__"); binary_num_slot_fragment_def!(__AND__, "__and__"); binary_num_slot_fragment_def!(__RAND__, "__rand__"); binary_num_slot_fragment_def!(__XOR__, "__xor__"); binary_num_slot_fragment_def!(__RXOR__, "__rxor__"); binary_num_slot_fragment_def!(__OR__, "__or__"); binary_num_slot_fragment_def!(__ROR__, "__ror__"); const __POW__: SlotFragmentDef = SlotFragmentDef::new("__pow__", &[Ty::Object, Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); const __RPOW__: SlotFragmentDef = SlotFragmentDef::new("__rpow__", &[Ty::Object, Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); const __LT__: SlotFragmentDef = SlotFragmentDef::new("__lt__", &[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); const __LE__: SlotFragmentDef = SlotFragmentDef::new("__le__", &[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); const __EQ__: SlotFragmentDef = SlotFragmentDef::new("__eq__", &[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); const __NE__: SlotFragmentDef = SlotFragmentDef::new("__ne__", &[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); const __GT__: SlotFragmentDef = SlotFragmentDef::new("__gt__", &[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); const __GE__: SlotFragmentDef = SlotFragmentDef::new("__ge__", &[Ty::Object]) .extract_error_mode(ExtractErrorMode::NotImplemented) .ret_ty(Ty::Object); fn extract_proto_arguments( spec: &FnSpec<'_>, proto_args: &[Ty], extract_error_mode: ExtractErrorMode, holders: &mut Holders, ctx: &Ctx, ) -> Result> { let mut args = Vec::with_capacity(spec.signature.arguments.len()); let mut non_python_args = 0; for arg in &spec.signature.arguments { if let FnArg::Py(..) = arg { args.push(quote! { py }); } else { let ident = syn::Ident::new(&format!("arg{}", non_python_args), Span::call_site()); let conversions = proto_args.get(non_python_args) .ok_or_else(|| err_spanned!(arg.ty().span() => format!("Expected at most {} non-python arguments", proto_args.len())))? .extract(&ident, arg, extract_error_mode, holders, ctx); non_python_args += 1; args.push(conversions); } } if non_python_args != proto_args.len() { bail_spanned!(spec.name.span() => format!("Expected {} arguments, got {}", proto_args.len(), non_python_args)); } Ok(args) } struct StaticIdent(&'static str); impl ToTokens for StaticIdent { fn to_tokens(&self, tokens: &mut TokenStream) { syn::Ident::new(self.0, Span::call_site()).to_tokens(tokens) } } #[derive(Clone, Copy)] struct TokenGenerator(fn(&Ctx) -> TokenStream); struct TokenGeneratorCtx<'ctx>(TokenGenerator, &'ctx Ctx); impl ToTokens for TokenGeneratorCtx<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let Self(TokenGenerator(gen), ctx) = self; (gen)(ctx).to_tokens(tokens) } } pyo3-macros-backend/src/pyimpl.rs0000644000175000017500000002610114661133735017751 0ustar jamespagejamespageuse std::collections::HashSet; use crate::utils::Ctx; use crate::{ attributes::{take_pyo3_options, CrateAttribute}, konst::{ConstAttributes, ConstSpec}, pyfunction::PyFunctionOptions, pymethod::{self, is_proto_method, MethodAndMethodDef, MethodAndSlotDef}, }; use proc_macro2::TokenStream; use pymethod::GeneratedPyMethod; use quote::{format_ident, quote}; use syn::{ parse::{Parse, ParseStream}, spanned::Spanned, Result, }; /// The mechanism used to collect `#[pymethods]` into the type object #[derive(Copy, Clone)] pub enum PyClassMethodsType { Specialization, Inventory, } enum PyImplPyO3Option { Crate(CrateAttribute), } impl Parse for PyImplPyO3Option { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(syn::Token![crate]) { input.parse().map(PyImplPyO3Option::Crate) } else { Err(lookahead.error()) } } } #[derive(Default)] pub struct PyImplOptions { krate: Option, } impl PyImplOptions { pub fn from_attrs(attrs: &mut Vec) -> Result { let mut options: PyImplOptions = Default::default(); for option in take_pyo3_options(attrs)? { match option { PyImplPyO3Option::Crate(path) => options.set_crate(path)?, } } Ok(options) } fn set_crate(&mut self, path: CrateAttribute) -> Result<()> { ensure_spanned!( self.krate.is_none(), path.span() => "`crate` may only be specified once" ); self.krate = Some(path); Ok(()) } } pub fn build_py_methods( ast: &mut syn::ItemImpl, methods_type: PyClassMethodsType, ) -> syn::Result { if let Some((_, path, _)) = &ast.trait_ { bail_spanned!(path.span() => "#[pymethods] cannot be used on trait impl blocks"); } else if ast.generics != Default::default() { bail_spanned!( ast.generics.span() => "#[pymethods] cannot be used with lifetime parameters or generics" ); } else { let options = PyImplOptions::from_attrs(&mut ast.attrs)?; impl_methods(&ast.self_ty, &mut ast.items, methods_type, options) } } pub fn impl_methods( ty: &syn::Type, impls: &mut [syn::ImplItem], methods_type: PyClassMethodsType, options: PyImplOptions, ) -> syn::Result { let mut trait_impls = Vec::new(); let mut proto_impls = Vec::new(); let mut methods = Vec::new(); let mut associated_methods = Vec::new(); let mut implemented_proto_fragments = HashSet::new(); for iimpl in impls { match iimpl { syn::ImplItem::Fn(meth) => { let ctx = &Ctx::new(&options.krate, Some(&meth.sig)); let mut fun_options = PyFunctionOptions::from_attrs(&mut meth.attrs)?; fun_options.krate = fun_options.krate.or_else(|| options.krate.clone()); match pymethod::gen_py_method(ty, &mut meth.sig, &mut meth.attrs, fun_options, ctx)? { GeneratedPyMethod::Method(MethodAndMethodDef { associated_method, method_def, }) => { let attrs = get_cfg_attributes(&meth.attrs); associated_methods.push(quote!(#(#attrs)* #associated_method)); methods.push(quote!(#(#attrs)* #method_def)); } GeneratedPyMethod::SlotTraitImpl(method_name, token_stream) => { implemented_proto_fragments.insert(method_name); let attrs = get_cfg_attributes(&meth.attrs); trait_impls.push(quote!(#(#attrs)* #token_stream)); } GeneratedPyMethod::Proto(MethodAndSlotDef { associated_method, slot_def, }) => { let attrs = get_cfg_attributes(&meth.attrs); proto_impls.push(quote!(#(#attrs)* #slot_def)); associated_methods.push(quote!(#(#attrs)* #associated_method)); } } } syn::ImplItem::Const(konst) => { let ctx = &Ctx::new(&options.krate, None); let attributes = ConstAttributes::from_attrs(&mut konst.attrs, ctx)?; if attributes.is_class_attr { let spec = ConstSpec { rust_ident: konst.ident.clone(), attributes, }; let attrs = get_cfg_attributes(&konst.attrs); let MethodAndMethodDef { associated_method, method_def, } = gen_py_const(ty, &spec, ctx); methods.push(quote!(#(#attrs)* #method_def)); associated_methods.push(quote!(#(#attrs)* #associated_method)); if is_proto_method(&spec.python_name().to_string()) { // If this is a known protocol method e.g. __contains__, then allow this // symbol even though it's not an uppercase constant. konst .attrs .push(syn::parse_quote!(#[allow(non_upper_case_globals)])); } } } syn::ImplItem::Macro(m) => bail_spanned!( m.span() => "macros cannot be used as items in `#[pymethods]` impl blocks\n\ = note: this was previously accepted and ignored" ), _ => {} } } let ctx = &Ctx::new(&options.krate, None); add_shared_proto_slots(ty, &mut proto_impls, implemented_proto_fragments, ctx); let items = match methods_type { PyClassMethodsType::Specialization => impl_py_methods(ty, methods, proto_impls, ctx), PyClassMethodsType::Inventory => submit_methods_inventory(ty, methods, proto_impls, ctx), }; Ok(quote! { #(#trait_impls)* #items #[doc(hidden)] #[allow(non_snake_case)] impl #ty { #(#associated_methods)* } }) } pub fn gen_py_const(cls: &syn::Type, spec: &ConstSpec<'_>, ctx: &Ctx) -> MethodAndMethodDef { let member = &spec.rust_ident; let wrapper_ident = format_ident!("__pymethod_{}__", member); let deprecations = &spec.attributes.deprecations; let python_name = spec.null_terminated_python_name(ctx); let Ctx { pyo3_path, .. } = ctx; let associated_method = quote! { fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> { #deprecations ::std::result::Result::Ok(#pyo3_path::IntoPy::into_py(#cls::#member, py)) } }; let method_def = quote! { #pyo3_path::impl_::pyclass::MaybeRuntimePyMethodDef::Static( #pyo3_path::class::PyMethodDefType::ClassAttribute({ #pyo3_path::class::PyClassAttributeDef::new( #python_name, #cls::#wrapper_ident ) }) ) }; MethodAndMethodDef { associated_method, method_def, } } fn impl_py_methods( ty: &syn::Type, methods: Vec, proto_impls: Vec, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; quote! { #[allow(unknown_lints, non_local_definitions)] impl #pyo3_path::impl_::pyclass::PyMethods<#ty> for #pyo3_path::impl_::pyclass::PyClassImplCollector<#ty> { fn py_methods(self) -> &'static #pyo3_path::impl_::pyclass::PyClassItems { static ITEMS: #pyo3_path::impl_::pyclass::PyClassItems = #pyo3_path::impl_::pyclass::PyClassItems { methods: &[#(#methods),*], slots: &[#(#proto_impls),*] }; &ITEMS } } } } fn add_shared_proto_slots( ty: &syn::Type, proto_impls: &mut Vec, mut implemented_proto_fragments: HashSet, ctx: &Ctx, ) { let Ctx { pyo3_path, .. } = ctx; macro_rules! try_add_shared_slot { ($slot:ident, $($fragments:literal),*) => {{ let mut implemented = false; $(implemented |= implemented_proto_fragments.remove($fragments));*; if implemented { proto_impls.push(quote! { #pyo3_path::impl_::pyclass::$slot!(#ty) }) } }}; } try_add_shared_slot!( generate_pyclass_getattro_slot, "__getattribute__", "__getattr__" ); try_add_shared_slot!(generate_pyclass_setattr_slot, "__setattr__", "__delattr__"); try_add_shared_slot!(generate_pyclass_setdescr_slot, "__set__", "__delete__"); try_add_shared_slot!(generate_pyclass_setitem_slot, "__setitem__", "__delitem__"); try_add_shared_slot!(generate_pyclass_add_slot, "__add__", "__radd__"); try_add_shared_slot!(generate_pyclass_sub_slot, "__sub__", "__rsub__"); try_add_shared_slot!(generate_pyclass_mul_slot, "__mul__", "__rmul__"); try_add_shared_slot!(generate_pyclass_mod_slot, "__mod__", "__rmod__"); try_add_shared_slot!(generate_pyclass_divmod_slot, "__divmod__", "__rdivmod__"); try_add_shared_slot!(generate_pyclass_lshift_slot, "__lshift__", "__rlshift__"); try_add_shared_slot!(generate_pyclass_rshift_slot, "__rshift__", "__rrshift__"); try_add_shared_slot!(generate_pyclass_and_slot, "__and__", "__rand__"); try_add_shared_slot!(generate_pyclass_or_slot, "__or__", "__ror__"); try_add_shared_slot!(generate_pyclass_xor_slot, "__xor__", "__rxor__"); try_add_shared_slot!(generate_pyclass_matmul_slot, "__matmul__", "__rmatmul__"); try_add_shared_slot!(generate_pyclass_truediv_slot, "__truediv__", "__rtruediv__"); try_add_shared_slot!( generate_pyclass_floordiv_slot, "__floordiv__", "__rfloordiv__" ); try_add_shared_slot!(generate_pyclass_pow_slot, "__pow__", "__rpow__"); try_add_shared_slot!( generate_pyclass_richcompare_slot, "__lt__", "__le__", "__eq__", "__ne__", "__gt__", "__ge__" ); // if this assertion trips, a slot fragment has been implemented which has not been added in the // list above assert!(implemented_proto_fragments.is_empty()); } fn submit_methods_inventory( ty: &syn::Type, methods: Vec, proto_impls: Vec, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; quote! { #pyo3_path::inventory::submit! { type Inventory = <#ty as #pyo3_path::impl_::pyclass::PyClassImpl>::Inventory; Inventory::new(#pyo3_path::impl_::pyclass::PyClassItems { methods: &[#(#methods),*], slots: &[#(#proto_impls),*] }) } } } fn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec<&syn::Attribute> { attrs .iter() .filter(|attr| attr.path().is_ident("cfg")) .collect() } pyo3-macros-backend/src/attributes.rs0000644000175000017500000001762314661133735020636 0ustar jamespagejamespageuse proc_macro2::TokenStream; use quote::ToTokens; use syn::{ ext::IdentExt, parse::{Parse, ParseStream}, punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Expr, ExprPath, Ident, LitStr, Path, Result, Token, }; pub mod kw { syn::custom_keyword!(annotation); syn::custom_keyword!(attribute); syn::custom_keyword!(cancel_handle); syn::custom_keyword!(constructor); syn::custom_keyword!(dict); syn::custom_keyword!(eq); syn::custom_keyword!(eq_int); syn::custom_keyword!(extends); syn::custom_keyword!(freelist); syn::custom_keyword!(from_py_with); syn::custom_keyword!(frozen); syn::custom_keyword!(get); syn::custom_keyword!(get_all); syn::custom_keyword!(hash); syn::custom_keyword!(item); syn::custom_keyword!(from_item_all); syn::custom_keyword!(mapping); syn::custom_keyword!(module); syn::custom_keyword!(name); syn::custom_keyword!(ord); syn::custom_keyword!(pass_module); syn::custom_keyword!(rename_all); syn::custom_keyword!(sequence); syn::custom_keyword!(set); syn::custom_keyword!(set_all); syn::custom_keyword!(signature); syn::custom_keyword!(subclass); syn::custom_keyword!(submodule); syn::custom_keyword!(text_signature); syn::custom_keyword!(transparent); syn::custom_keyword!(unsendable); syn::custom_keyword!(weakref); } #[derive(Clone, Debug)] pub struct KeywordAttribute { pub kw: K, pub value: V, } /// A helper type which parses the inner type via a literal string /// e.g. `LitStrValue` -> parses "some::path" in quotes. #[derive(Clone, Debug, PartialEq, Eq)] pub struct LitStrValue(pub T); impl Parse for LitStrValue { fn parse(input: ParseStream<'_>) -> Result { let lit_str: LitStr = input.parse()?; lit_str.parse().map(LitStrValue) } } impl ToTokens for LitStrValue { fn to_tokens(&self, tokens: &mut TokenStream) { self.0.to_tokens(tokens) } } /// A helper type which parses a name via a literal string #[derive(Clone, Debug, PartialEq, Eq)] pub struct NameLitStr(pub Ident); impl Parse for NameLitStr { fn parse(input: ParseStream<'_>) -> Result { let string_literal: LitStr = input.parse()?; if let Ok(ident) = string_literal.parse_with(Ident::parse_any) { Ok(NameLitStr(ident)) } else { bail_spanned!(string_literal.span() => "expected a single identifier in double quotes") } } } impl ToTokens for NameLitStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.0.to_tokens(tokens) } } /// Available renaming rules #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RenamingRule { CamelCase, KebabCase, Lowercase, PascalCase, ScreamingKebabCase, ScreamingSnakeCase, SnakeCase, Uppercase, } /// A helper type which parses a renaming rule via a literal string #[derive(Clone, Debug, PartialEq, Eq)] pub struct RenamingRuleLitStr { pub lit: LitStr, pub rule: RenamingRule, } impl Parse for RenamingRuleLitStr { fn parse(input: ParseStream<'_>) -> Result { let string_literal: LitStr = input.parse()?; let rule = match string_literal.value().as_ref() { "camelCase" => RenamingRule::CamelCase, "kebab-case" => RenamingRule::KebabCase, "lowercase" => RenamingRule::Lowercase, "PascalCase" => RenamingRule::PascalCase, "SCREAMING-KEBAB-CASE" => RenamingRule::ScreamingKebabCase, "SCREAMING_SNAKE_CASE" => RenamingRule::ScreamingSnakeCase, "snake_case" => RenamingRule::SnakeCase, "UPPERCASE" => RenamingRule::Uppercase, _ => { bail_spanned!(string_literal.span() => "expected a valid renaming rule, possible values are: \"camelCase\", \"kebab-case\", \"lowercase\", \"PascalCase\", \"SCREAMING-KEBAB-CASE\", \"SCREAMING_SNAKE_CASE\", \"snake_case\", \"UPPERCASE\"") } }; Ok(Self { lit: string_literal, rule, }) } } impl ToTokens for RenamingRuleLitStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.lit.to_tokens(tokens) } } /// Text signatue can be either a literal string or opt-in/out #[derive(Clone, Debug, PartialEq, Eq)] pub enum TextSignatureAttributeValue { Str(LitStr), // `None` ident to disable automatic text signature generation Disabled(Ident), } impl Parse for TextSignatureAttributeValue { fn parse(input: ParseStream<'_>) -> Result { if let Ok(lit_str) = input.parse::() { return Ok(TextSignatureAttributeValue::Str(lit_str)); } let err_span = match input.parse::() { Ok(ident) if ident == "None" => { return Ok(TextSignatureAttributeValue::Disabled(ident)); } Ok(other_ident) => other_ident.span(), Err(e) => e.span(), }; Err(err_spanned!(err_span => "expected a string literal or `None`")) } } impl ToTokens for TextSignatureAttributeValue { fn to_tokens(&self, tokens: &mut TokenStream) { match self { TextSignatureAttributeValue::Str(s) => s.to_tokens(tokens), TextSignatureAttributeValue::Disabled(b) => b.to_tokens(tokens), } } } pub type ExtendsAttribute = KeywordAttribute; pub type FreelistAttribute = KeywordAttribute>; pub type ModuleAttribute = KeywordAttribute; pub type NameAttribute = KeywordAttribute; pub type RenameAllAttribute = KeywordAttribute; pub type TextSignatureAttribute = KeywordAttribute; pub type SubmoduleAttribute = kw::submodule; impl Parse for KeywordAttribute { fn parse(input: ParseStream<'_>) -> Result { let kw: K = input.parse()?; let _: Token![=] = input.parse()?; let value = input.parse()?; Ok(KeywordAttribute { kw, value }) } } impl ToTokens for KeywordAttribute { fn to_tokens(&self, tokens: &mut TokenStream) { self.kw.to_tokens(tokens); Token![=](self.kw.span()).to_tokens(tokens); self.value.to_tokens(tokens); } } pub type FromPyWithAttribute = KeywordAttribute>; /// For specifying the path to the pyo3 crate. pub type CrateAttribute = KeywordAttribute>; pub fn get_pyo3_options(attr: &syn::Attribute) -> Result>> { if attr.path().is_ident("pyo3") { attr.parse_args_with(Punctuated::parse_terminated).map(Some) } else { Ok(None) } } /// Takes attributes from an attribute vector. /// /// For each attribute in `attrs`, `extractor` is called. If `extractor` returns `Ok(true)`, then /// the attribute will be removed from the vector. /// /// This is similar to `Vec::retain` except the closure is fallible and the condition is reversed. /// (In `retain`, returning `true` keeps the element, here it removes it.) pub fn take_attributes( attrs: &mut Vec, mut extractor: impl FnMut(&Attribute) -> Result, ) -> Result<()> { *attrs = attrs .drain(..) .filter_map(|attr| { extractor(&attr) .map(move |attribute_handled| if attribute_handled { None } else { Some(attr) }) .transpose() }) .collect::>()?; Ok(()) } pub fn take_pyo3_options(attrs: &mut Vec) -> Result> { let mut out = Vec::new(); take_attributes(attrs, |attr| { if let Some(options) = get_pyo3_options(attr)? { out.extend(options); Ok(true) } else { Ok(false) } })?; Ok(out) } pyo3-macros-backend/src/pyclass.rs0000644000175000017500000023045414661133735020125 0ustar jamespagejamespageuse std::borrow::Cow; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; use syn::ext::IdentExt; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::{parse_quote, parse_quote_spanned, spanned::Spanned, Result, Token}; use crate::attributes::kw::frozen; use crate::attributes::{ self, kw, take_pyo3_options, CrateAttribute, ExtendsAttribute, FreelistAttribute, ModuleAttribute, NameAttribute, NameLitStr, RenameAllAttribute, }; use crate::deprecations::Deprecations; use crate::konst::{ConstAttributes, ConstSpec}; use crate::method::{FnArg, FnSpec, PyArg, RegularArg}; use crate::pyfunction::ConstructorAttribute; use crate::pyimpl::{gen_py_const, PyClassMethodsType}; use crate::pymethod::{ impl_py_getter_def, impl_py_setter_def, MethodAndMethodDef, MethodAndSlotDef, PropertyType, SlotDef, __GETITEM__, __HASH__, __INT__, __LEN__, __REPR__, __RICHCMP__, }; use crate::pyversions; use crate::utils::{self, apply_renaming_rule, LitCStr, PythonDoc}; use crate::utils::{is_abi3, Ctx}; use crate::PyFunctionOptions; /// If the class is derived from a Rust `struct` or `enum`. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PyClassKind { Struct, Enum, } /// The parsed arguments of the pyclass macro #[derive(Clone)] pub struct PyClassArgs { pub class_kind: PyClassKind, pub options: PyClassPyO3Options, } impl PyClassArgs { fn parse(input: ParseStream<'_>, kind: PyClassKind) -> Result { Ok(PyClassArgs { class_kind: kind, options: PyClassPyO3Options::parse(input)?, }) } pub fn parse_stuct_args(input: ParseStream<'_>) -> syn::Result { Self::parse(input, PyClassKind::Struct) } pub fn parse_enum_args(input: ParseStream<'_>) -> syn::Result { Self::parse(input, PyClassKind::Enum) } } #[derive(Clone, Default)] pub struct PyClassPyO3Options { pub krate: Option, pub dict: Option, pub eq: Option, pub eq_int: Option, pub extends: Option, pub get_all: Option, pub freelist: Option, pub frozen: Option, pub hash: Option, pub mapping: Option, pub module: Option, pub name: Option, pub ord: Option, pub rename_all: Option, pub sequence: Option, pub set_all: Option, pub subclass: Option, pub unsendable: Option, pub weakref: Option, } pub enum PyClassPyO3Option { Crate(CrateAttribute), Dict(kw::dict), Eq(kw::eq), EqInt(kw::eq_int), Extends(ExtendsAttribute), Freelist(FreelistAttribute), Frozen(kw::frozen), GetAll(kw::get_all), Hash(kw::hash), Mapping(kw::mapping), Module(ModuleAttribute), Name(NameAttribute), Ord(kw::ord), RenameAll(RenameAllAttribute), Sequence(kw::sequence), SetAll(kw::set_all), Subclass(kw::subclass), Unsendable(kw::unsendable), Weakref(kw::weakref), } impl Parse for PyClassPyO3Option { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(Token![crate]) { input.parse().map(PyClassPyO3Option::Crate) } else if lookahead.peek(kw::dict) { input.parse().map(PyClassPyO3Option::Dict) } else if lookahead.peek(kw::eq) { input.parse().map(PyClassPyO3Option::Eq) } else if lookahead.peek(kw::eq_int) { input.parse().map(PyClassPyO3Option::EqInt) } else if lookahead.peek(kw::extends) { input.parse().map(PyClassPyO3Option::Extends) } else if lookahead.peek(attributes::kw::freelist) { input.parse().map(PyClassPyO3Option::Freelist) } else if lookahead.peek(attributes::kw::frozen) { input.parse().map(PyClassPyO3Option::Frozen) } else if lookahead.peek(attributes::kw::get_all) { input.parse().map(PyClassPyO3Option::GetAll) } else if lookahead.peek(attributes::kw::hash) { input.parse().map(PyClassPyO3Option::Hash) } else if lookahead.peek(attributes::kw::mapping) { input.parse().map(PyClassPyO3Option::Mapping) } else if lookahead.peek(attributes::kw::module) { input.parse().map(PyClassPyO3Option::Module) } else if lookahead.peek(kw::name) { input.parse().map(PyClassPyO3Option::Name) } else if lookahead.peek(attributes::kw::ord) { input.parse().map(PyClassPyO3Option::Ord) } else if lookahead.peek(kw::rename_all) { input.parse().map(PyClassPyO3Option::RenameAll) } else if lookahead.peek(attributes::kw::sequence) { input.parse().map(PyClassPyO3Option::Sequence) } else if lookahead.peek(attributes::kw::set_all) { input.parse().map(PyClassPyO3Option::SetAll) } else if lookahead.peek(attributes::kw::subclass) { input.parse().map(PyClassPyO3Option::Subclass) } else if lookahead.peek(attributes::kw::unsendable) { input.parse().map(PyClassPyO3Option::Unsendable) } else if lookahead.peek(attributes::kw::weakref) { input.parse().map(PyClassPyO3Option::Weakref) } else { Err(lookahead.error()) } } } impl Parse for PyClassPyO3Options { fn parse(input: ParseStream<'_>) -> syn::Result { let mut options: PyClassPyO3Options = Default::default(); for option in Punctuated::::parse_terminated(input)? { options.set_option(option)?; } Ok(options) } } impl PyClassPyO3Options { pub fn take_pyo3_options(&mut self, attrs: &mut Vec) -> syn::Result<()> { take_pyo3_options(attrs)? .into_iter() .try_for_each(|option| self.set_option(option)) } fn set_option(&mut self, option: PyClassPyO3Option) -> syn::Result<()> { macro_rules! set_option { ($key:ident) => { { ensure_spanned!( self.$key.is_none(), $key.span() => concat!("`", stringify!($key), "` may only be specified once") ); self.$key = Some($key); } }; } let python_version = pyo3_build_config::get().version; match option { PyClassPyO3Option::Crate(krate) => set_option!(krate), PyClassPyO3Option::Dict(dict) => { ensure_spanned!( python_version >= pyversions::PY_3_9 || !is_abi3(), dict.span() => "`dict` requires Python >= 3.9 when using the `abi3` feature" ); set_option!(dict); } PyClassPyO3Option::Eq(eq) => set_option!(eq), PyClassPyO3Option::EqInt(eq_int) => set_option!(eq_int), PyClassPyO3Option::Extends(extends) => set_option!(extends), PyClassPyO3Option::Freelist(freelist) => set_option!(freelist), PyClassPyO3Option::Frozen(frozen) => set_option!(frozen), PyClassPyO3Option::GetAll(get_all) => set_option!(get_all), PyClassPyO3Option::Hash(hash) => set_option!(hash), PyClassPyO3Option::Mapping(mapping) => set_option!(mapping), PyClassPyO3Option::Module(module) => set_option!(module), PyClassPyO3Option::Name(name) => set_option!(name), PyClassPyO3Option::Ord(ord) => set_option!(ord), PyClassPyO3Option::RenameAll(rename_all) => set_option!(rename_all), PyClassPyO3Option::Sequence(sequence) => set_option!(sequence), PyClassPyO3Option::SetAll(set_all) => set_option!(set_all), PyClassPyO3Option::Subclass(subclass) => set_option!(subclass), PyClassPyO3Option::Unsendable(unsendable) => set_option!(unsendable), PyClassPyO3Option::Weakref(weakref) => { ensure_spanned!( python_version >= pyversions::PY_3_9 || !is_abi3(), weakref.span() => "`weakref` requires Python >= 3.9 when using the `abi3` feature" ); set_option!(weakref); } } Ok(()) } } pub fn build_py_class( class: &mut syn::ItemStruct, mut args: PyClassArgs, methods_type: PyClassMethodsType, ) -> syn::Result { args.options.take_pyo3_options(&mut class.attrs)?; let ctx = &Ctx::new(&args.options.krate, None); let doc = utils::get_doc(&class.attrs, None, ctx); if let Some(lt) = class.generics.lifetimes().next() { bail_spanned!( lt.span() => concat!( "#[pyclass] cannot have lifetime parameters. For an explanation, see \ https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#no-lifetime-parameters" ) ); } ensure_spanned!( class.generics.params.is_empty(), class.generics.span() => concat!( "#[pyclass] cannot have generic parameters. For an explanation, see \ https://pyo3.rs/v", env!("CARGO_PKG_VERSION"), "/class.html#no-generic-parameters" ) ); let mut field_options: Vec<(&syn::Field, FieldPyO3Options)> = match &mut class.fields { syn::Fields::Named(fields) => fields .named .iter_mut() .map(|field| { FieldPyO3Options::take_pyo3_options(&mut field.attrs) .map(move |options| (&*field, options)) }) .collect::>()?, syn::Fields::Unnamed(fields) => fields .unnamed .iter_mut() .map(|field| { FieldPyO3Options::take_pyo3_options(&mut field.attrs) .map(move |options| (&*field, options)) }) .collect::>()?, syn::Fields::Unit => { if let Some(attr) = args.options.set_all { return Err(syn::Error::new_spanned(attr, UNIT_SET)); }; if let Some(attr) = args.options.get_all { return Err(syn::Error::new_spanned(attr, UNIT_GET)); }; // No fields for unit struct Vec::new() } }; if let Some(attr) = args.options.get_all { for (_, FieldPyO3Options { get, .. }) in &mut field_options { if let Some(old_get) = get.replace(Annotated::Struct(attr)) { return Err(syn::Error::new(old_get.span(), DUPE_GET)); } } } if let Some(attr) = args.options.set_all { for (_, FieldPyO3Options { set, .. }) in &mut field_options { if let Some(old_set) = set.replace(Annotated::Struct(attr)) { return Err(syn::Error::new(old_set.span(), DUPE_SET)); } } } impl_class(&class.ident, &args, doc, field_options, methods_type, ctx) } enum Annotated { Field(X), Struct(Y), } impl Annotated { fn span(&self) -> Span { match self { Self::Field(x) => x.span(), Self::Struct(y) => y.span(), } } } /// `#[pyo3()]` options for pyclass fields struct FieldPyO3Options { get: Option>, set: Option>, name: Option, } enum FieldPyO3Option { Get(attributes::kw::get), Set(attributes::kw::set), Name(NameAttribute), } impl Parse for FieldPyO3Option { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::get) { input.parse().map(FieldPyO3Option::Get) } else if lookahead.peek(attributes::kw::set) { input.parse().map(FieldPyO3Option::Set) } else if lookahead.peek(attributes::kw::name) { input.parse().map(FieldPyO3Option::Name) } else { Err(lookahead.error()) } } } impl FieldPyO3Options { fn take_pyo3_options(attrs: &mut Vec) -> Result { let mut options = FieldPyO3Options { get: None, set: None, name: None, }; for option in take_pyo3_options(attrs)? { match option { FieldPyO3Option::Get(kw) => { if options.get.replace(Annotated::Field(kw)).is_some() { return Err(syn::Error::new(kw.span(), UNIQUE_GET)); } } FieldPyO3Option::Set(kw) => { if options.set.replace(Annotated::Field(kw)).is_some() { return Err(syn::Error::new(kw.span(), UNIQUE_SET)); } } FieldPyO3Option::Name(name) => { if options.name.replace(name).is_some() { return Err(syn::Error::new(options.name.span(), UNIQUE_NAME)); } } } } Ok(options) } } fn get_class_python_name<'a>(cls: &'a syn::Ident, args: &'a PyClassArgs) -> Cow<'a, syn::Ident> { args.options .name .as_ref() .map(|name_attr| Cow::Borrowed(&name_attr.value.0)) .unwrap_or_else(|| Cow::Owned(cls.unraw())) } fn impl_class( cls: &syn::Ident, args: &PyClassArgs, doc: PythonDoc, field_options: Vec<(&syn::Field, FieldPyO3Options)>, methods_type: PyClassMethodsType, ctx: &Ctx, ) -> syn::Result { let Ctx { pyo3_path, .. } = ctx; let pytypeinfo_impl = impl_pytypeinfo(cls, args, None, ctx); let (default_richcmp, default_richcmp_slot) = pyclass_richcmp(&args.options, &syn::parse_quote!(#cls), ctx)?; let (default_hash, default_hash_slot) = pyclass_hash(&args.options, &syn::parse_quote!(#cls), ctx)?; let mut slots = Vec::new(); slots.extend(default_richcmp_slot); slots.extend(default_hash_slot); let py_class_impl = PyClassImplsBuilder::new( cls, args, methods_type, descriptors_to_items( cls, args.options.rename_all.as_ref(), args.options.frozen, field_options, ctx, )?, slots, ) .doc(doc) .impl_all(ctx)?; Ok(quote! { impl #pyo3_path::types::DerefToPyAny for #cls {} #pytypeinfo_impl #py_class_impl #[doc(hidden)] #[allow(non_snake_case)] impl #cls { #default_richcmp #default_hash } }) } enum PyClassEnum<'a> { Simple(PyClassSimpleEnum<'a>), Complex(PyClassComplexEnum<'a>), } impl<'a> PyClassEnum<'a> { fn new(enum_: &'a mut syn::ItemEnum) -> syn::Result { let has_only_unit_variants = enum_ .variants .iter() .all(|variant| matches!(variant.fields, syn::Fields::Unit)); Ok(if has_only_unit_variants { let simple_enum = PyClassSimpleEnum::new(enum_)?; Self::Simple(simple_enum) } else { let complex_enum = PyClassComplexEnum::new(enum_)?; Self::Complex(complex_enum) }) } } pub fn build_py_enum( enum_: &mut syn::ItemEnum, mut args: PyClassArgs, method_type: PyClassMethodsType, ) -> syn::Result { args.options.take_pyo3_options(&mut enum_.attrs)?; let ctx = &Ctx::new(&args.options.krate, None); if let Some(extends) = &args.options.extends { bail_spanned!(extends.span() => "enums can't extend from other classes"); } else if let Some(subclass) = &args.options.subclass { bail_spanned!(subclass.span() => "enums can't be inherited by other classes"); } else if enum_.variants.is_empty() { bail_spanned!(enum_.brace_token.span.join() => "#[pyclass] can't be used on enums without any variants"); } let doc = utils::get_doc(&enum_.attrs, None, ctx); let enum_ = PyClassEnum::new(enum_)?; impl_enum(enum_, &args, doc, method_type, ctx) } struct PyClassSimpleEnum<'a> { ident: &'a syn::Ident, // The underlying #[repr] of the enum, used to implement __int__ and __richcmp__. // This matters when the underlying representation may not fit in `isize`. repr_type: syn::Ident, variants: Vec>, } impl<'a> PyClassSimpleEnum<'a> { fn new(enum_: &'a mut syn::ItemEnum) -> syn::Result { fn is_numeric_type(t: &syn::Ident) -> bool { [ "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "u128", "i128", "usize", "isize", ] .iter() .any(|&s| t == s) } fn extract_unit_variant_data( variant: &mut syn::Variant, ) -> syn::Result> { use syn::Fields; let ident = match &variant.fields { Fields::Unit => &variant.ident, _ => bail_spanned!(variant.span() => "Must be a unit variant."), }; let options = EnumVariantPyO3Options::take_pyo3_options(&mut variant.attrs)?; Ok(PyClassEnumUnitVariant { ident, options }) } let ident = &enum_.ident; // According to the [reference](https://doc.rust-lang.org/reference/items/enumerations.html), // "Under the default representation, the specified discriminant is interpreted as an isize // value", so `isize` should be enough by default. let mut repr_type = syn::Ident::new("isize", proc_macro2::Span::call_site()); if let Some(attr) = enum_.attrs.iter().find(|attr| attr.path().is_ident("repr")) { let args = attr.parse_args_with(Punctuated::::parse_terminated)?; if let Some(ident) = args .into_iter() .filter_map(|ts| syn::parse2::(ts).ok()) .find(is_numeric_type) { repr_type = ident; } } let variants: Vec<_> = enum_ .variants .iter_mut() .map(extract_unit_variant_data) .collect::>()?; Ok(Self { ident, repr_type, variants, }) } } struct PyClassComplexEnum<'a> { ident: &'a syn::Ident, variants: Vec>, } impl<'a> PyClassComplexEnum<'a> { fn new(enum_: &'a mut syn::ItemEnum) -> syn::Result { let witness = enum_ .variants .iter() .find(|variant| !matches!(variant.fields, syn::Fields::Unit)) .expect("complex enum has a non-unit variant") .ident .to_owned(); let extract_variant_data = |variant: &'a mut syn::Variant| -> syn::Result> { use syn::Fields; let ident = &variant.ident; let options = EnumVariantPyO3Options::take_pyo3_options(&mut variant.attrs)?; let variant = match &variant.fields { Fields::Unit => { bail_spanned!(variant.span() => format!( "Unit variant `{ident}` is not yet supported in a complex enum\n\ = help: change to an empty tuple variant instead: `{ident}()`\n\ = note: the enum is complex because of non-unit variant `{witness}`", ident=ident, witness=witness)) } Fields::Named(fields) => { let fields = fields .named .iter() .map(|field| PyClassEnumVariantNamedField { ident: field.ident.as_ref().expect("named field has an identifier"), ty: &field.ty, span: field.span(), }) .collect(); PyClassEnumVariant::Struct(PyClassEnumStructVariant { ident, fields, options, }) } Fields::Unnamed(types) => { let fields = types .unnamed .iter() .map(|field| PyClassEnumVariantUnnamedField { ty: &field.ty, span: field.span(), }) .collect(); PyClassEnumVariant::Tuple(PyClassEnumTupleVariant { ident, fields, options, }) } }; Ok(variant) }; let ident = &enum_.ident; let variants: Vec<_> = enum_ .variants .iter_mut() .map(extract_variant_data) .collect::>()?; Ok(Self { ident, variants }) } } enum PyClassEnumVariant<'a> { // TODO(mkovaxx): Unit(PyClassEnumUnitVariant<'a>), Struct(PyClassEnumStructVariant<'a>), Tuple(PyClassEnumTupleVariant<'a>), } trait EnumVariant { fn get_ident(&self) -> &syn::Ident; fn get_options(&self) -> &EnumVariantPyO3Options; fn get_python_name(&self, args: &PyClassArgs) -> Cow<'_, syn::Ident> { self.get_options() .name .as_ref() .map(|name_attr| Cow::Borrowed(&name_attr.value.0)) .unwrap_or_else(|| { let name = self.get_ident().unraw(); if let Some(attr) = &args.options.rename_all { let new_name = apply_renaming_rule(attr.value.rule, &name.to_string()); Cow::Owned(Ident::new(&new_name, Span::call_site())) } else { Cow::Owned(name) } }) } } impl<'a> EnumVariant for PyClassEnumVariant<'a> { fn get_ident(&self) -> &syn::Ident { match self { PyClassEnumVariant::Struct(struct_variant) => struct_variant.ident, PyClassEnumVariant::Tuple(tuple_variant) => tuple_variant.ident, } } fn get_options(&self) -> &EnumVariantPyO3Options { match self { PyClassEnumVariant::Struct(struct_variant) => &struct_variant.options, PyClassEnumVariant::Tuple(tuple_variant) => &tuple_variant.options, } } } /// A unit variant has no fields struct PyClassEnumUnitVariant<'a> { ident: &'a syn::Ident, options: EnumVariantPyO3Options, } impl<'a> EnumVariant for PyClassEnumUnitVariant<'a> { fn get_ident(&self) -> &syn::Ident { self.ident } fn get_options(&self) -> &EnumVariantPyO3Options { &self.options } } /// A struct variant has named fields struct PyClassEnumStructVariant<'a> { ident: &'a syn::Ident, fields: Vec>, options: EnumVariantPyO3Options, } struct PyClassEnumTupleVariant<'a> { ident: &'a syn::Ident, fields: Vec>, options: EnumVariantPyO3Options, } struct PyClassEnumVariantNamedField<'a> { ident: &'a syn::Ident, ty: &'a syn::Type, span: Span, } struct PyClassEnumVariantUnnamedField<'a> { ty: &'a syn::Type, span: Span, } /// `#[pyo3()]` options for pyclass enum variants #[derive(Clone, Default)] struct EnumVariantPyO3Options { name: Option, constructor: Option, } enum EnumVariantPyO3Option { Name(NameAttribute), Constructor(ConstructorAttribute), } impl Parse for EnumVariantPyO3Option { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::name) { input.parse().map(EnumVariantPyO3Option::Name) } else if lookahead.peek(attributes::kw::constructor) { input.parse().map(EnumVariantPyO3Option::Constructor) } else { Err(lookahead.error()) } } } impl EnumVariantPyO3Options { fn take_pyo3_options(attrs: &mut Vec) -> Result { let mut options = EnumVariantPyO3Options::default(); take_pyo3_options(attrs)? .into_iter() .try_for_each(|option| options.set_option(option))?; Ok(options) } fn set_option(&mut self, option: EnumVariantPyO3Option) -> syn::Result<()> { macro_rules! set_option { ($key:ident) => { { ensure_spanned!( self.$key.is_none(), $key.span() => concat!("`", stringify!($key), "` may only be specified once") ); self.$key = Some($key); } }; } match option { EnumVariantPyO3Option::Constructor(constructor) => set_option!(constructor), EnumVariantPyO3Option::Name(name) => set_option!(name), } Ok(()) } } fn impl_enum( enum_: PyClassEnum<'_>, args: &PyClassArgs, doc: PythonDoc, methods_type: PyClassMethodsType, ctx: &Ctx, ) -> Result { match enum_ { PyClassEnum::Simple(simple_enum) => { impl_simple_enum(simple_enum, args, doc, methods_type, ctx) } PyClassEnum::Complex(complex_enum) => { impl_complex_enum(complex_enum, args, doc, methods_type, ctx) } } } fn impl_simple_enum( simple_enum: PyClassSimpleEnum<'_>, args: &PyClassArgs, doc: PythonDoc, methods_type: PyClassMethodsType, ctx: &Ctx, ) -> Result { let cls = simple_enum.ident; let ty: syn::Type = syn::parse_quote!(#cls); let variants = simple_enum.variants; let pytypeinfo = impl_pytypeinfo(cls, args, None, ctx); for variant in &variants { ensure_spanned!(variant.options.constructor.is_none(), variant.options.constructor.span() => "`constructor` can't be used on a simple enum variant"); } let (default_repr, default_repr_slot) = { let variants_repr = variants.iter().map(|variant| { let variant_name = variant.ident; // Assuming all variants are unit variants because they are the only type we support. let repr = format!( "{}.{}", get_class_python_name(cls, args), variant.get_python_name(args), ); quote! { #cls::#variant_name => #repr, } }); let mut repr_impl: syn::ImplItemFn = syn::parse_quote! { fn __pyo3__repr__(&self) -> &'static str { match self { #(#variants_repr)* } } }; let repr_slot = generate_default_protocol_slot(&ty, &mut repr_impl, &__REPR__, ctx).unwrap(); (repr_impl, repr_slot) }; let repr_type = &simple_enum.repr_type; let (default_int, default_int_slot) = { // This implementation allows us to convert &T to #repr_type without implementing `Copy` let variants_to_int = variants.iter().map(|variant| { let variant_name = variant.ident; quote! { #cls::#variant_name => #cls::#variant_name as #repr_type, } }); let mut int_impl: syn::ImplItemFn = syn::parse_quote! { fn __pyo3__int__(&self) -> #repr_type { match self { #(#variants_to_int)* } } }; let int_slot = generate_default_protocol_slot(&ty, &mut int_impl, &__INT__, ctx).unwrap(); (int_impl, int_slot) }; let (default_richcmp, default_richcmp_slot) = pyclass_richcmp_simple_enum(&args.options, &ty, repr_type, ctx)?; let (default_hash, default_hash_slot) = pyclass_hash(&args.options, &ty, ctx)?; let mut default_slots = vec![default_repr_slot, default_int_slot]; default_slots.extend(default_richcmp_slot); default_slots.extend(default_hash_slot); let pyclass_impls = PyClassImplsBuilder::new( cls, args, methods_type, simple_enum_default_methods( cls, variants.iter().map(|v| (v.ident, v.get_python_name(args))), ctx, ), default_slots, ) .doc(doc) .impl_all(ctx)?; Ok(quote! { #pytypeinfo #pyclass_impls #[doc(hidden)] #[allow(non_snake_case)] impl #cls { #default_repr #default_int #default_richcmp #default_hash } }) } fn impl_complex_enum( complex_enum: PyClassComplexEnum<'_>, args: &PyClassArgs, doc: PythonDoc, methods_type: PyClassMethodsType, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let cls = complex_enum.ident; let ty: syn::Type = syn::parse_quote!(#cls); // Need to rig the enum PyClass options let args = { let mut rigged_args = args.clone(); // Needs to be frozen to disallow `&mut self` methods, which could break a runtime invariant rigged_args.options.frozen = parse_quote!(frozen); // Needs to be subclassable by the variant PyClasses rigged_args.options.subclass = parse_quote!(subclass); rigged_args }; let ctx = &Ctx::new(&args.options.krate, None); let cls = complex_enum.ident; let variants = complex_enum.variants; let pytypeinfo = impl_pytypeinfo(cls, &args, None, ctx); let (default_richcmp, default_richcmp_slot) = pyclass_richcmp(&args.options, &ty, ctx)?; let (default_hash, default_hash_slot) = pyclass_hash(&args.options, &ty, ctx)?; let mut default_slots = vec![]; default_slots.extend(default_richcmp_slot); default_slots.extend(default_hash_slot); let impl_builder = PyClassImplsBuilder::new( cls, &args, methods_type, complex_enum_default_methods( cls, variants .iter() .map(|v| (v.get_ident(), v.get_python_name(&args))), ctx, ), default_slots, ) .doc(doc); // Need to customize the into_py impl so that it returns the variant PyClass let enum_into_py_impl = { let match_arms: Vec = variants .iter() .map(|variant| { let variant_ident = variant.get_ident(); let variant_cls = gen_complex_enum_variant_class_ident(cls, variant.get_ident()); quote! { #cls::#variant_ident { .. } => { let pyclass_init = #pyo3_path::PyClassInitializer::from(self).add_subclass(#variant_cls); let variant_value = #pyo3_path::Py::new(py, pyclass_init).unwrap(); #pyo3_path::IntoPy::into_py(variant_value, py) } } }) .collect(); quote! { impl #pyo3_path::IntoPy<#pyo3_path::PyObject> for #cls { fn into_py(self, py: #pyo3_path::Python) -> #pyo3_path::PyObject { match self { #(#match_arms)* } } } } }; let pyclass_impls: TokenStream = [ impl_builder.impl_pyclass(ctx), impl_builder.impl_extractext(ctx), enum_into_py_impl, impl_builder.impl_pyclassimpl(ctx)?, impl_builder.impl_add_to_module(ctx), impl_builder.impl_freelist(ctx), ] .into_iter() .collect(); let mut variant_cls_zsts = vec![]; let mut variant_cls_pytypeinfos = vec![]; let mut variant_cls_pyclass_impls = vec![]; let mut variant_cls_impls = vec![]; for variant in variants { let variant_cls = gen_complex_enum_variant_class_ident(cls, variant.get_ident()); let variant_cls_zst = quote! { #[doc(hidden)] #[allow(non_camel_case_types)] struct #variant_cls; }; variant_cls_zsts.push(variant_cls_zst); let variant_args = PyClassArgs { class_kind: PyClassKind::Struct, // TODO(mkovaxx): propagate variant.options options: { let mut rigged_options: PyClassPyO3Options = parse_quote!(extends = #cls, frozen); // If a specific module was given to the base class, use it for all variants. rigged_options.module.clone_from(&args.options.module); rigged_options }, }; let variant_cls_pytypeinfo = impl_pytypeinfo(&variant_cls, &variant_args, None, ctx); variant_cls_pytypeinfos.push(variant_cls_pytypeinfo); let (variant_cls_impl, field_getters, mut slots) = impl_complex_enum_variant_cls(cls, &variant, ctx)?; variant_cls_impls.push(variant_cls_impl); let variant_new = complex_enum_variant_new(cls, variant, ctx)?; slots.push(variant_new); let pyclass_impl = PyClassImplsBuilder::new( &variant_cls, &variant_args, methods_type, field_getters, slots, ) .impl_all(ctx)?; variant_cls_pyclass_impls.push(pyclass_impl); } Ok(quote! { #pytypeinfo #pyclass_impls #[doc(hidden)] #[allow(non_snake_case)] impl #cls { #default_richcmp #default_hash } #(#variant_cls_zsts)* #(#variant_cls_pytypeinfos)* #(#variant_cls_pyclass_impls)* #(#variant_cls_impls)* }) } fn impl_complex_enum_variant_cls( enum_name: &syn::Ident, variant: &PyClassEnumVariant<'_>, ctx: &Ctx, ) -> Result<(TokenStream, Vec, Vec)> { match variant { PyClassEnumVariant::Struct(struct_variant) => { impl_complex_enum_struct_variant_cls(enum_name, struct_variant, ctx) } PyClassEnumVariant::Tuple(tuple_variant) => { impl_complex_enum_tuple_variant_cls(enum_name, tuple_variant, ctx) } } } fn impl_complex_enum_variant_match_args( ctx: &Ctx, variant_cls_type: &syn::Type, field_names: &mut Vec, ) -> (MethodAndMethodDef, syn::ImplItemConst) { let match_args_const_impl: syn::ImplItemConst = { let args_tp = field_names.iter().map(|_| { quote! { &'static str } }); parse_quote! { const __match_args__: ( #(#args_tp,)* ) = ( #(stringify!(#field_names),)* ); } }; let spec = ConstSpec { rust_ident: format_ident!("__match_args__"), attributes: ConstAttributes { is_class_attr: true, name: None, deprecations: Deprecations::new(ctx), }, }; let variant_match_args = gen_py_const(variant_cls_type, &spec, ctx); (variant_match_args, match_args_const_impl) } fn impl_complex_enum_struct_variant_cls( enum_name: &syn::Ident, variant: &PyClassEnumStructVariant<'_>, ctx: &Ctx, ) -> Result<(TokenStream, Vec, Vec)> { let Ctx { pyo3_path, .. } = ctx; let variant_ident = &variant.ident; let variant_cls = gen_complex_enum_variant_class_ident(enum_name, variant.ident); let variant_cls_type = parse_quote!(#variant_cls); let mut field_names: Vec = vec![]; let mut fields_with_types: Vec = vec![]; let mut field_getters = vec![]; let mut field_getter_impls: Vec = vec![]; for field in &variant.fields { let field_name = field.ident; let field_type = field.ty; let field_with_type = quote! { #field_name: #field_type }; let field_getter = complex_enum_variant_field_getter(&variant_cls_type, field_name, field.span, ctx)?; let field_getter_impl = quote! { fn #field_name(slf: #pyo3_path::PyRef) -> #pyo3_path::PyResult<#field_type> { match &*slf.into_super() { #enum_name::#variant_ident { #field_name, .. } => Ok(#field_name.clone()), _ => unreachable!("Wrong complex enum variant found in variant wrapper PyClass"), } } }; field_names.push(field_name.clone()); fields_with_types.push(field_with_type); field_getters.push(field_getter); field_getter_impls.push(field_getter_impl); } let (variant_match_args, match_args_const_impl) = impl_complex_enum_variant_match_args(ctx, &variant_cls_type, &mut field_names); field_getters.push(variant_match_args); let cls_impl = quote! { #[doc(hidden)] #[allow(non_snake_case)] impl #variant_cls { fn __pymethod_constructor__(py: #pyo3_path::Python<'_>, #(#fields_with_types,)*) -> #pyo3_path::PyClassInitializer<#variant_cls> { let base_value = #enum_name::#variant_ident { #(#field_names,)* }; #pyo3_path::PyClassInitializer::from(base_value).add_subclass(#variant_cls) } #match_args_const_impl #(#field_getter_impls)* } }; Ok((cls_impl, field_getters, Vec::new())) } fn impl_complex_enum_tuple_variant_field_getters( ctx: &Ctx, variant: &PyClassEnumTupleVariant<'_>, enum_name: &syn::Ident, variant_cls_type: &syn::Type, variant_ident: &&Ident, field_names: &mut Vec, fields_types: &mut Vec, ) -> Result<(Vec, Vec)> { let Ctx { pyo3_path, .. } = ctx; let mut field_getters = vec![]; let mut field_getter_impls = vec![]; for (index, field) in variant.fields.iter().enumerate() { let field_name = format_ident!("_{}", index); let field_type = field.ty; let field_getter = complex_enum_variant_field_getter(variant_cls_type, &field_name, field.span, ctx)?; // Generate the match arms needed to destructure the tuple and access the specific field let field_access_tokens: Vec<_> = (0..variant.fields.len()) .map(|i| { if i == index { quote! { val } } else { quote! { _ } } }) .collect(); let field_getter_impl: syn::ImplItemFn = parse_quote! { fn #field_name(slf: #pyo3_path::PyRef) -> #pyo3_path::PyResult<#field_type> { match &*slf.into_super() { #enum_name::#variant_ident ( #(#field_access_tokens), *) => Ok(val.clone()), _ => unreachable!("Wrong complex enum variant found in variant wrapper PyClass"), } } }; field_names.push(field_name); fields_types.push(field_type.clone()); field_getters.push(field_getter); field_getter_impls.push(field_getter_impl); } Ok((field_getters, field_getter_impls)) } fn impl_complex_enum_tuple_variant_len( ctx: &Ctx, variant_cls_type: &syn::Type, num_fields: usize, ) -> Result<(MethodAndSlotDef, syn::ImplItemFn)> { let Ctx { pyo3_path, .. } = ctx; let mut len_method_impl: syn::ImplItemFn = parse_quote! { fn __len__(slf: #pyo3_path::PyRef) -> #pyo3_path::PyResult { Ok(#num_fields) } }; let variant_len = generate_default_protocol_slot(variant_cls_type, &mut len_method_impl, &__LEN__, ctx)?; Ok((variant_len, len_method_impl)) } fn impl_complex_enum_tuple_variant_getitem( ctx: &Ctx, variant_cls: &syn::Ident, variant_cls_type: &syn::Type, num_fields: usize, ) -> Result<(MethodAndSlotDef, syn::ImplItemFn)> { let Ctx { pyo3_path, .. } = ctx; let match_arms: Vec<_> = (0..num_fields) .map(|i| { let field_access = format_ident!("_{}", i); quote! { #i => Ok( #pyo3_path::IntoPy::into_py( #variant_cls::#field_access(slf)? , py) ) } }) .collect(); let mut get_item_method_impl: syn::ImplItemFn = parse_quote! { fn __getitem__(slf: #pyo3_path::PyRef, idx: usize) -> #pyo3_path::PyResult< #pyo3_path::PyObject> { let py = slf.py(); match idx { #( #match_arms, )* _ => Err(pyo3::exceptions::PyIndexError::new_err("tuple index out of range")), } } }; let variant_getitem = generate_default_protocol_slot( variant_cls_type, &mut get_item_method_impl, &__GETITEM__, ctx, )?; Ok((variant_getitem, get_item_method_impl)) } fn impl_complex_enum_tuple_variant_cls( enum_name: &syn::Ident, variant: &PyClassEnumTupleVariant<'_>, ctx: &Ctx, ) -> Result<(TokenStream, Vec, Vec)> { let Ctx { pyo3_path, .. } = ctx; let variant_ident = &variant.ident; let variant_cls = gen_complex_enum_variant_class_ident(enum_name, variant.ident); let variant_cls_type = parse_quote!(#variant_cls); let mut slots = vec![]; // represents the index of the field let mut field_names: Vec = vec![]; let mut field_types: Vec = vec![]; let (mut field_getters, field_getter_impls) = impl_complex_enum_tuple_variant_field_getters( ctx, variant, enum_name, &variant_cls_type, variant_ident, &mut field_names, &mut field_types, )?; let num_fields = variant.fields.len(); let (variant_len, len_method_impl) = impl_complex_enum_tuple_variant_len(ctx, &variant_cls_type, num_fields)?; slots.push(variant_len); let (variant_getitem, getitem_method_impl) = impl_complex_enum_tuple_variant_getitem(ctx, &variant_cls, &variant_cls_type, num_fields)?; slots.push(variant_getitem); let (variant_match_args, match_args_method_impl) = impl_complex_enum_variant_match_args(ctx, &variant_cls_type, &mut field_names); field_getters.push(variant_match_args); let cls_impl = quote! { #[doc(hidden)] #[allow(non_snake_case)] impl #variant_cls { fn __pymethod_constructor__(py: #pyo3_path::Python<'_>, #(#field_names : #field_types,)*) -> #pyo3_path::PyClassInitializer<#variant_cls> { let base_value = #enum_name::#variant_ident ( #(#field_names,)* ); #pyo3_path::PyClassInitializer::from(base_value).add_subclass(#variant_cls) } #len_method_impl #getitem_method_impl #match_args_method_impl #(#field_getter_impls)* } }; Ok((cls_impl, field_getters, slots)) } fn gen_complex_enum_variant_class_ident(enum_: &syn::Ident, variant: &syn::Ident) -> syn::Ident { format_ident!("{}_{}", enum_, variant) } fn generate_protocol_slot( cls: &syn::Type, method: &mut syn::ImplItemFn, slot: &SlotDef, name: &str, ctx: &Ctx, ) -> syn::Result { let spec = FnSpec::parse( &mut method.sig, &mut Vec::new(), PyFunctionOptions::default(), ctx, ) .unwrap(); slot.generate_type_slot(&syn::parse_quote!(#cls), &spec, name, ctx) } fn generate_default_protocol_slot( cls: &syn::Type, method: &mut syn::ImplItemFn, slot: &SlotDef, ctx: &Ctx, ) -> syn::Result { let spec = FnSpec::parse( &mut method.sig, &mut Vec::new(), PyFunctionOptions::default(), ctx, ) .unwrap(); let name = spec.name.to_string(); slot.generate_type_slot( &syn::parse_quote!(#cls), &spec, &format!("__default_{}__", name), ctx, ) } fn simple_enum_default_methods<'a>( cls: &'a syn::Ident, unit_variant_names: impl IntoIterator)>, ctx: &Ctx, ) -> Vec { let cls_type = syn::parse_quote!(#cls); let variant_to_attribute = |var_ident: &syn::Ident, py_ident: &syn::Ident| ConstSpec { rust_ident: var_ident.clone(), attributes: ConstAttributes { is_class_attr: true, name: Some(NameAttribute { kw: syn::parse_quote! { name }, value: NameLitStr(py_ident.clone()), }), deprecations: Deprecations::new(ctx), }, }; unit_variant_names .into_iter() .map(|(var, py_name)| gen_py_const(&cls_type, &variant_to_attribute(var, &py_name), ctx)) .collect() } fn complex_enum_default_methods<'a>( cls: &'a syn::Ident, variant_names: impl IntoIterator)>, ctx: &Ctx, ) -> Vec { let cls_type = syn::parse_quote!(#cls); let variant_to_attribute = |var_ident: &syn::Ident, py_ident: &syn::Ident| ConstSpec { rust_ident: var_ident.clone(), attributes: ConstAttributes { is_class_attr: true, name: Some(NameAttribute { kw: syn::parse_quote! { name }, value: NameLitStr(py_ident.clone()), }), deprecations: Deprecations::new(ctx), }, }; variant_names .into_iter() .map(|(var, py_name)| { gen_complex_enum_variant_attr(cls, &cls_type, &variant_to_attribute(var, &py_name), ctx) }) .collect() } pub fn gen_complex_enum_variant_attr( cls: &syn::Ident, cls_type: &syn::Type, spec: &ConstSpec<'_>, ctx: &Ctx, ) -> MethodAndMethodDef { let Ctx { pyo3_path, .. } = ctx; let member = &spec.rust_ident; let wrapper_ident = format_ident!("__pymethod_variant_cls_{}__", member); let deprecations = &spec.attributes.deprecations; let python_name = spec.null_terminated_python_name(ctx); let variant_cls = format_ident!("{}_{}", cls, member); let associated_method = quote! { fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::PyObject> { #deprecations ::std::result::Result::Ok(py.get_type_bound::<#variant_cls>().into_any().unbind()) } }; let method_def = quote! { #pyo3_path::impl_::pyclass::MaybeRuntimePyMethodDef::Static( #pyo3_path::class::PyMethodDefType::ClassAttribute({ #pyo3_path::class::PyClassAttributeDef::new( #python_name, #cls_type::#wrapper_ident ) }) ) }; MethodAndMethodDef { associated_method, method_def, } } fn complex_enum_variant_new<'a>( cls: &'a syn::Ident, variant: PyClassEnumVariant<'a>, ctx: &Ctx, ) -> Result { match variant { PyClassEnumVariant::Struct(struct_variant) => { complex_enum_struct_variant_new(cls, struct_variant, ctx) } PyClassEnumVariant::Tuple(tuple_variant) => { complex_enum_tuple_variant_new(cls, tuple_variant, ctx) } } } fn complex_enum_struct_variant_new<'a>( cls: &'a syn::Ident, variant: PyClassEnumStructVariant<'a>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let variant_cls = format_ident!("{}_{}", cls, variant.ident); let variant_cls_type: syn::Type = parse_quote!(#variant_cls); let arg_py_ident: syn::Ident = parse_quote!(py); let arg_py_type: syn::Type = parse_quote!(#pyo3_path::Python<'_>); let args = { let mut args = vec![ // py: Python<'_> FnArg::Py(PyArg { name: &arg_py_ident, ty: &arg_py_type, }), ]; for field in &variant.fields { args.push(FnArg::Regular(RegularArg { name: Cow::Borrowed(field.ident), ty: field.ty, from_py_with: None, default_value: None, option_wrapped_type: None, })); } args }; let signature = if let Some(constructor) = variant.options.constructor { crate::pyfunction::FunctionSignature::from_arguments_and_attribute( args, constructor.into_signature(), )? } else { crate::pyfunction::FunctionSignature::from_arguments(args)? }; let spec = FnSpec { tp: crate::method::FnType::FnNew, name: &format_ident!("__pymethod_constructor__"), python_name: format_ident!("__new__"), signature, convention: crate::method::CallingConvention::TpNew, text_signature: None, asyncness: None, unsafety: None, deprecations: Deprecations::new(ctx), }; crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec, ctx) } fn complex_enum_tuple_variant_new<'a>( cls: &'a syn::Ident, variant: PyClassEnumTupleVariant<'a>, ctx: &Ctx, ) -> Result { let Ctx { pyo3_path, .. } = ctx; let variant_cls: Ident = format_ident!("{}_{}", cls, variant.ident); let variant_cls_type: syn::Type = parse_quote!(#variant_cls); let arg_py_ident: syn::Ident = parse_quote!(py); let arg_py_type: syn::Type = parse_quote!(#pyo3_path::Python<'_>); let args = { let mut args = vec![FnArg::Py(PyArg { name: &arg_py_ident, ty: &arg_py_type, })]; for (i, field) in variant.fields.iter().enumerate() { args.push(FnArg::Regular(RegularArg { name: std::borrow::Cow::Owned(format_ident!("_{}", i)), ty: field.ty, from_py_with: None, default_value: None, option_wrapped_type: None, })); } args }; let signature = if let Some(constructor) = variant.options.constructor { crate::pyfunction::FunctionSignature::from_arguments_and_attribute( args, constructor.into_signature(), )? } else { crate::pyfunction::FunctionSignature::from_arguments(args)? }; let spec = FnSpec { tp: crate::method::FnType::FnNew, name: &format_ident!("__pymethod_constructor__"), python_name: format_ident!("__new__"), signature, convention: crate::method::CallingConvention::TpNew, text_signature: None, asyncness: None, unsafety: None, deprecations: Deprecations::new(ctx), }; crate::pymethod::impl_py_method_def_new(&variant_cls_type, &spec, ctx) } fn complex_enum_variant_field_getter<'a>( variant_cls_type: &'a syn::Type, field_name: &'a syn::Ident, field_span: Span, ctx: &Ctx, ) -> Result { let signature = crate::pyfunction::FunctionSignature::from_arguments(vec![])?; let self_type = crate::method::SelfType::TryFromBoundRef(field_span); let spec = FnSpec { tp: crate::method::FnType::Getter(self_type.clone()), name: field_name, python_name: field_name.clone(), signature, convention: crate::method::CallingConvention::Noargs, text_signature: None, asyncness: None, unsafety: None, deprecations: Deprecations::new(ctx), }; let property_type = crate::pymethod::PropertyType::Function { self_type: &self_type, spec: &spec, doc: crate::get_doc(&[], None, ctx), }; let getter = crate::pymethod::impl_py_getter_def(variant_cls_type, property_type, ctx)?; Ok(getter) } fn descriptors_to_items( cls: &syn::Ident, rename_all: Option<&RenameAllAttribute>, frozen: Option, field_options: Vec<(&syn::Field, FieldPyO3Options)>, ctx: &Ctx, ) -> syn::Result> { let ty = syn::parse_quote!(#cls); let mut items = Vec::new(); for (field_index, (field, options)) in field_options.into_iter().enumerate() { if let FieldPyO3Options { name: Some(name), get: None, set: None, } = options { return Err(syn::Error::new_spanned(name, USELESS_NAME)); } if options.get.is_some() { let getter = impl_py_getter_def( &ty, PropertyType::Descriptor { field_index, field, python_name: options.name.as_ref(), renaming_rule: rename_all.map(|rename_all| rename_all.value.rule), }, ctx, )?; items.push(getter); } if let Some(set) = options.set { ensure_spanned!(frozen.is_none(), set.span() => "cannot use `#[pyo3(set)]` on a `frozen` class"); let setter = impl_py_setter_def( &ty, PropertyType::Descriptor { field_index, field, python_name: options.name.as_ref(), renaming_rule: rename_all.map(|rename_all| rename_all.value.rule), }, ctx, )?; items.push(setter); }; } Ok(items) } fn impl_pytypeinfo( cls: &syn::Ident, attr: &PyClassArgs, deprecations: Option<&Deprecations<'_>>, ctx: &Ctx, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let cls_name = get_class_python_name(cls, attr).to_string(); let module = if let Some(ModuleAttribute { value, .. }) = &attr.options.module { quote! { ::core::option::Option::Some(#value) } } else { quote! { ::core::option::Option::None } }; #[cfg(feature = "gil-refs")] let has_py_gil_ref = quote! { #[allow(deprecated)] unsafe impl #pyo3_path::type_object::HasPyGilRef for #cls { type AsRefTarget = #pyo3_path::PyCell; } }; #[cfg(not(feature = "gil-refs"))] let has_py_gil_ref = TokenStream::new(); quote! { #has_py_gil_ref unsafe impl #pyo3_path::type_object::PyTypeInfo for #cls { const NAME: &'static str = #cls_name; const MODULE: ::std::option::Option<&'static str> = #module; #[inline] fn type_object_raw(py: #pyo3_path::Python<'_>) -> *mut #pyo3_path::ffi::PyTypeObject { use #pyo3_path::prelude::PyTypeMethods; #deprecations <#cls as #pyo3_path::impl_::pyclass::PyClassImpl>::lazy_type_object() .get_or_init(py) .as_type_ptr() } } } } fn pyclass_richcmp_arms( options: &PyClassPyO3Options, ctx: &Ctx, ) -> std::result::Result { let Ctx { pyo3_path, .. } = ctx; let eq_arms = options .eq .map(|eq| eq.span) .or(options.eq_int.map(|eq_int| eq_int.span)) .map(|span| { quote_spanned! { span => #pyo3_path::pyclass::CompareOp::Eq => { ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val == other, py)) }, #pyo3_path::pyclass::CompareOp::Ne => { ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val != other, py)) }, } }) .unwrap_or_default(); if let Some(ord) = options.ord { ensure_spanned!(options.eq.is_some(), ord.span() => "The `ord` option requires the `eq` option."); } let ord_arms = options .ord .map(|ord| { quote_spanned! { ord.span() => #pyo3_path::pyclass::CompareOp::Gt => { ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val > other, py)) }, #pyo3_path::pyclass::CompareOp::Lt => { ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val < other, py)) }, #pyo3_path::pyclass::CompareOp::Le => { ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val <= other, py)) }, #pyo3_path::pyclass::CompareOp::Ge => { ::std::result::Result::Ok(#pyo3_path::conversion::IntoPy::into_py(self_val >= other, py)) }, } }) .unwrap_or_else(|| quote! { _ => ::std::result::Result::Ok(py.NotImplemented()) }); Ok(quote! { #eq_arms #ord_arms }) } fn pyclass_richcmp_simple_enum( options: &PyClassPyO3Options, cls: &syn::Type, repr_type: &syn::Ident, ctx: &Ctx, ) -> Result<(Option, Option)> { let Ctx { pyo3_path, .. } = ctx; if let Some(eq_int) = options.eq_int { ensure_spanned!(options.eq.is_some(), eq_int.span() => "The `eq_int` option requires the `eq` option."); } let deprecation = (options.eq_int.is_none() && options.eq.is_none()) .then(|| { quote! { #[deprecated( since = "0.22.0", note = "Implicit equality for simple enums is deprecated. Use `#[pyclass(eq, eq_int)` to keep the current behavior." )] const DEPRECATION: () = (); const _: () = DEPRECATION; } }) .unwrap_or_default(); let mut options = options.clone(); if options.eq.is_none() { options.eq_int = Some(parse_quote!(eq_int)); } if options.eq.is_none() && options.eq_int.is_none() { return Ok((None, None)); } let arms = pyclass_richcmp_arms(&options, ctx)?; let eq = options.eq.map(|eq| { quote_spanned! { eq.span() => let self_val = self; if let ::std::result::Result::Ok(other) = #pyo3_path::types::PyAnyMethods::downcast::(other) { let other = &*other.borrow(); return match op { #arms } } } }); let eq_int = options.eq_int.map(|eq_int| { quote_spanned! { eq_int.span() => let self_val = self.__pyo3__int__(); if let ::std::result::Result::Ok(other) = #pyo3_path::types::PyAnyMethods::extract::<#repr_type>(other).or_else(|_| { #pyo3_path::types::PyAnyMethods::downcast::(other).map(|o| o.borrow().__pyo3__int__()) }) { return match op { #arms } } } }); let mut richcmp_impl = parse_quote! { fn __pyo3__generated____richcmp__( &self, py: #pyo3_path::Python, other: &#pyo3_path::Bound<'_, #pyo3_path::PyAny>, op: #pyo3_path::pyclass::CompareOp ) -> #pyo3_path::PyResult<#pyo3_path::PyObject> { #deprecation #eq #eq_int ::std::result::Result::Ok(py.NotImplemented()) } }; let richcmp_slot = if options.eq.is_some() { generate_protocol_slot(cls, &mut richcmp_impl, &__RICHCMP__, "__richcmp__", ctx).unwrap() } else { generate_default_protocol_slot(cls, &mut richcmp_impl, &__RICHCMP__, ctx).unwrap() }; Ok((Some(richcmp_impl), Some(richcmp_slot))) } fn pyclass_richcmp( options: &PyClassPyO3Options, cls: &syn::Type, ctx: &Ctx, ) -> Result<(Option, Option)> { let Ctx { pyo3_path, .. } = ctx; if let Some(eq_int) = options.eq_int { bail_spanned!(eq_int.span() => "`eq_int` can only be used on simple enums.") } let arms = pyclass_richcmp_arms(options, ctx)?; if options.eq.is_some() { let mut richcmp_impl = parse_quote! { fn __pyo3__generated____richcmp__( &self, py: #pyo3_path::Python, other: &#pyo3_path::Bound<'_, #pyo3_path::PyAny>, op: #pyo3_path::pyclass::CompareOp ) -> #pyo3_path::PyResult<#pyo3_path::PyObject> { let self_val = self; if let Ok(other) = #pyo3_path::types::PyAnyMethods::downcast::(other) { let other = &*other.borrow(); match op { #arms } } else { ::std::result::Result::Ok(py.NotImplemented()) } } }; let richcmp_slot = generate_protocol_slot(cls, &mut richcmp_impl, &__RICHCMP__, "__richcmp__", ctx) .unwrap(); Ok((Some(richcmp_impl), Some(richcmp_slot))) } else { Ok((None, None)) } } fn pyclass_hash( options: &PyClassPyO3Options, cls: &syn::Type, ctx: &Ctx, ) -> Result<(Option, Option)> { if options.hash.is_some() { ensure_spanned!( options.frozen.is_some(), options.hash.span() => "The `hash` option requires the `frozen` option."; options.eq.is_some(), options.hash.span() => "The `hash` option requires the `eq` option."; ); } // FIXME: Use hash.map(...).unzip() on MSRV >= 1.66 match options.hash { Some(opt) => { let mut hash_impl = parse_quote_spanned! { opt.span() => fn __pyo3__generated____hash__(&self) -> u64 { let mut s = ::std::collections::hash_map::DefaultHasher::new(); ::std::hash::Hash::hash(self, &mut s); ::std::hash::Hasher::finish(&s) } }; let hash_slot = generate_protocol_slot(cls, &mut hash_impl, &__HASH__, "__hash__", ctx).unwrap(); Ok((Some(hash_impl), Some(hash_slot))) } None => Ok((None, None)), } } /// Implements most traits used by `#[pyclass]`. /// /// Specifically, it implements traits that only depend on class name, /// and attributes of `#[pyclass]`, and docstrings. /// Therefore it doesn't implement traits that depends on struct fields and enum variants. struct PyClassImplsBuilder<'a> { cls: &'a syn::Ident, attr: &'a PyClassArgs, methods_type: PyClassMethodsType, default_methods: Vec, default_slots: Vec, doc: Option, } impl<'a> PyClassImplsBuilder<'a> { fn new( cls: &'a syn::Ident, attr: &'a PyClassArgs, methods_type: PyClassMethodsType, default_methods: Vec, default_slots: Vec, ) -> Self { Self { cls, attr, methods_type, default_methods, default_slots, doc: None, } } fn doc(self, doc: PythonDoc) -> Self { Self { doc: Some(doc), ..self } } fn impl_all(&self, ctx: &Ctx) -> Result { let tokens = [ self.impl_pyclass(ctx), self.impl_extractext(ctx), self.impl_into_py(ctx), self.impl_pyclassimpl(ctx)?, self.impl_add_to_module(ctx), self.impl_freelist(ctx), ] .into_iter() .collect(); Ok(tokens) } fn impl_pyclass(&self, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let cls = self.cls; let frozen = if self.attr.options.frozen.is_some() { quote! { #pyo3_path::pyclass::boolean_struct::True } } else { quote! { #pyo3_path::pyclass::boolean_struct::False } }; quote! { impl #pyo3_path::PyClass for #cls { type Frozen = #frozen; } } } fn impl_extractext(&self, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let cls = self.cls; if self.attr.options.frozen.is_some() { quote! { impl<'a, 'py> #pyo3_path::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a #cls { type Holder = ::std::option::Option<#pyo3_path::PyRef<'py, #cls>>; #[inline] fn extract(obj: &'a #pyo3_path::Bound<'py, #pyo3_path::PyAny>, holder: &'a mut Self::Holder) -> #pyo3_path::PyResult { #pyo3_path::impl_::extract_argument::extract_pyclass_ref(obj, holder) } } } } else { quote! { impl<'a, 'py> #pyo3_path::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a #cls { type Holder = ::std::option::Option<#pyo3_path::PyRef<'py, #cls>>; #[inline] fn extract(obj: &'a #pyo3_path::Bound<'py, #pyo3_path::PyAny>, holder: &'a mut Self::Holder) -> #pyo3_path::PyResult { #pyo3_path::impl_::extract_argument::extract_pyclass_ref(obj, holder) } } impl<'a, 'py> #pyo3_path::impl_::extract_argument::PyFunctionArgument<'a, 'py> for &'a mut #cls { type Holder = ::std::option::Option<#pyo3_path::PyRefMut<'py, #cls>>; #[inline] fn extract(obj: &'a #pyo3_path::Bound<'py, #pyo3_path::PyAny>, holder: &'a mut Self::Holder) -> #pyo3_path::PyResult { #pyo3_path::impl_::extract_argument::extract_pyclass_ref_mut(obj, holder) } } } } } fn impl_into_py(&self, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let cls = self.cls; let attr = self.attr; // If #cls is not extended type, we allow Self->PyObject conversion if attr.options.extends.is_none() { quote! { impl #pyo3_path::IntoPy<#pyo3_path::PyObject> for #cls { fn into_py(self, py: #pyo3_path::Python) -> #pyo3_path::PyObject { #pyo3_path::IntoPy::into_py(#pyo3_path::Py::new(py, self).unwrap(), py) } } } } else { quote! {} } } fn impl_pyclassimpl(&self, ctx: &Ctx) -> Result { let Ctx { pyo3_path, .. } = ctx; let cls = self.cls; let doc = self.doc.as_ref().map_or( LitCStr::empty(ctx).to_token_stream(), PythonDoc::to_token_stream, ); let is_basetype = self.attr.options.subclass.is_some(); let base = match &self.attr.options.extends { Some(extends_attr) => extends_attr.value.clone(), None => parse_quote! { #pyo3_path::PyAny }, }; let is_subclass = self.attr.options.extends.is_some(); let is_mapping: bool = self.attr.options.mapping.is_some(); let is_sequence: bool = self.attr.options.sequence.is_some(); ensure_spanned!( !(is_mapping && is_sequence), self.cls.span() => "a `#[pyclass]` cannot be both a `mapping` and a `sequence`" ); let dict_offset = if self.attr.options.dict.is_some() { quote! { fn dict_offset() -> ::std::option::Option<#pyo3_path::ffi::Py_ssize_t> { ::std::option::Option::Some(#pyo3_path::impl_::pyclass::dict_offset::()) } } } else { TokenStream::new() }; // insert space for weak ref let weaklist_offset = if self.attr.options.weakref.is_some() { quote! { fn weaklist_offset() -> ::std::option::Option<#pyo3_path::ffi::Py_ssize_t> { ::std::option::Option::Some(#pyo3_path::impl_::pyclass::weaklist_offset::()) } } } else { TokenStream::new() }; let thread_checker = if self.attr.options.unsendable.is_some() { quote! { #pyo3_path::impl_::pyclass::ThreadCheckerImpl } } else { quote! { #pyo3_path::impl_::pyclass::SendablePyClass<#cls> } }; let (pymethods_items, inventory, inventory_class) = match self.methods_type { PyClassMethodsType::Specialization => (quote! { collector.py_methods() }, None, None), PyClassMethodsType::Inventory => { // To allow multiple #[pymethods] block, we define inventory types. let inventory_class_name = syn::Ident::new( &format!("Pyo3MethodsInventoryFor{}", cls.unraw()), Span::call_site(), ); ( quote! { ::std::boxed::Box::new( ::std::iter::Iterator::map( #pyo3_path::inventory::iter::<::Inventory>(), #pyo3_path::impl_::pyclass::PyClassInventory::items ) ) }, Some(quote! { type Inventory = #inventory_class_name; }), Some(define_inventory_class(&inventory_class_name, ctx)), ) } }; let default_methods = self .default_methods .iter() .map(|meth| &meth.associated_method) .chain( self.default_slots .iter() .map(|meth| &meth.associated_method), ); let default_method_defs = self.default_methods.iter().map(|meth| &meth.method_def); let default_slot_defs = self.default_slots.iter().map(|slot| &slot.slot_def); let freelist_slots = self.freelist_slots(ctx); let class_mutability = if self.attr.options.frozen.is_some() { quote! { ImmutableChild } } else { quote! { MutableChild } }; let cls = self.cls; let attr = self.attr; let dict = if attr.options.dict.is_some() { quote! { #pyo3_path::impl_::pyclass::PyClassDictSlot } } else { quote! { #pyo3_path::impl_::pyclass::PyClassDummySlot } }; // insert space for weak ref let weakref = if attr.options.weakref.is_some() { quote! { #pyo3_path::impl_::pyclass::PyClassWeakRefSlot } } else { quote! { #pyo3_path::impl_::pyclass::PyClassDummySlot } }; let base_nativetype = if attr.options.extends.is_some() { quote! { ::BaseNativeType } } else { quote! { #pyo3_path::PyAny } }; Ok(quote! { impl #pyo3_path::impl_::pyclass::PyClassImpl for #cls { const IS_BASETYPE: bool = #is_basetype; const IS_SUBCLASS: bool = #is_subclass; const IS_MAPPING: bool = #is_mapping; const IS_SEQUENCE: bool = #is_sequence; type BaseType = #base; type ThreadChecker = #thread_checker; #inventory type PyClassMutability = <<#base as #pyo3_path::impl_::pyclass::PyClassBaseType>::PyClassMutability as #pyo3_path::impl_::pycell::PyClassMutability>::#class_mutability; type Dict = #dict; type WeakRef = #weakref; type BaseNativeType = #base_nativetype; fn items_iter() -> #pyo3_path::impl_::pyclass::PyClassItemsIter { use #pyo3_path::impl_::pyclass::*; let collector = PyClassImplCollector::::new(); static INTRINSIC_ITEMS: PyClassItems = PyClassItems { methods: &[#(#default_method_defs),*], slots: &[#(#default_slot_defs),* #(#freelist_slots),*], }; PyClassItemsIter::new(&INTRINSIC_ITEMS, #pymethods_items) } fn doc(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<&'static ::std::ffi::CStr> { use #pyo3_path::impl_::pyclass::*; static DOC: #pyo3_path::sync::GILOnceCell<::std::borrow::Cow<'static, ::std::ffi::CStr>> = #pyo3_path::sync::GILOnceCell::new(); DOC.get_or_try_init(py, || { let collector = PyClassImplCollector::::new(); build_pyclass_doc(<#cls as #pyo3_path::PyTypeInfo>::NAME, #doc, collector.new_text_signature()) }).map(::std::ops::Deref::deref) } #dict_offset #weaklist_offset fn lazy_type_object() -> &'static #pyo3_path::impl_::pyclass::LazyTypeObject { use #pyo3_path::impl_::pyclass::LazyTypeObject; static TYPE_OBJECT: LazyTypeObject<#cls> = LazyTypeObject::new(); &TYPE_OBJECT } } #[doc(hidden)] #[allow(non_snake_case)] impl #cls { #(#default_methods)* } #inventory_class }) } fn impl_add_to_module(&self, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let cls = self.cls; quote! { impl #cls { #[doc(hidden)] pub const _PYO3_DEF: #pyo3_path::impl_::pymodule::AddClassToModule = #pyo3_path::impl_::pymodule::AddClassToModule::new(); } } } fn impl_freelist(&self, ctx: &Ctx) -> TokenStream { let cls = self.cls; let Ctx { pyo3_path, .. } = ctx; self.attr.options.freelist.as_ref().map_or(quote!{}, |freelist| { let freelist = &freelist.value; quote! { impl #pyo3_path::impl_::pyclass::PyClassWithFreeList for #cls { #[inline] fn get_free_list(py: #pyo3_path::Python<'_>) -> &mut #pyo3_path::impl_::freelist::FreeList<*mut #pyo3_path::ffi::PyObject> { static mut FREELIST: *mut #pyo3_path::impl_::freelist::FreeList<*mut #pyo3_path::ffi::PyObject> = 0 as *mut _; unsafe { if FREELIST.is_null() { FREELIST = ::std::boxed::Box::into_raw(::std::boxed::Box::new( #pyo3_path::impl_::freelist::FreeList::with_capacity(#freelist))); } &mut *FREELIST } } } } }) } fn freelist_slots(&self, ctx: &Ctx) -> Vec { let Ctx { pyo3_path, .. } = ctx; let cls = self.cls; if self.attr.options.freelist.is_some() { vec![ quote! { #pyo3_path::ffi::PyType_Slot { slot: #pyo3_path::ffi::Py_tp_alloc, pfunc: #pyo3_path::impl_::pyclass::alloc_with_freelist::<#cls> as *mut _, } }, quote! { #pyo3_path::ffi::PyType_Slot { slot: #pyo3_path::ffi::Py_tp_free, pfunc: #pyo3_path::impl_::pyclass::free_with_freelist::<#cls> as *mut _, } }, ] } else { Vec::new() } } } fn define_inventory_class(inventory_class_name: &syn::Ident, ctx: &Ctx) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; quote! { #[doc(hidden)] pub struct #inventory_class_name { items: #pyo3_path::impl_::pyclass::PyClassItems, } impl #inventory_class_name { pub const fn new(items: #pyo3_path::impl_::pyclass::PyClassItems) -> Self { Self { items } } } impl #pyo3_path::impl_::pyclass::PyClassInventory for #inventory_class_name { fn items(&self) -> &#pyo3_path::impl_::pyclass::PyClassItems { &self.items } } #pyo3_path::inventory::collect!(#inventory_class_name); } } const UNIQUE_GET: &str = "`get` may only be specified once"; const UNIQUE_SET: &str = "`set` may only be specified once"; const UNIQUE_NAME: &str = "`name` may only be specified once"; const DUPE_SET: &str = "useless `set` - the struct is already annotated with `set_all`"; const DUPE_GET: &str = "useless `get` - the struct is already annotated with `get_all`"; const UNIT_GET: &str = "`get_all` on an unit struct does nothing, because unit structs have no fields"; const UNIT_SET: &str = "`set_all` on an unit struct does nothing, because unit structs have no fields"; const USELESS_NAME: &str = "`name` is useless without `get` or `set`"; pyo3-macros-backend/src/konst.rs0000644000175000017500000000532314661133735017600 0ustar jamespagejamespageuse std::borrow::Cow; use std::ffi::CString; use crate::utils::{Ctx, LitCStr}; use crate::{ attributes::{self, get_pyo3_options, take_attributes, NameAttribute}, deprecations::Deprecations, }; use proc_macro2::{Ident, Span}; use syn::{ ext::IdentExt, parse::{Parse, ParseStream}, spanned::Spanned, Result, }; pub struct ConstSpec<'ctx> { pub rust_ident: syn::Ident, pub attributes: ConstAttributes<'ctx>, } impl ConstSpec<'_> { pub fn python_name(&self) -> Cow<'_, Ident> { if let Some(name) = &self.attributes.name { Cow::Borrowed(&name.value.0) } else { Cow::Owned(self.rust_ident.unraw()) } } /// Null-terminated Python name pub fn null_terminated_python_name(&self, ctx: &Ctx) -> LitCStr { let name = self.python_name().to_string(); LitCStr::new(CString::new(name).unwrap(), Span::call_site(), ctx) } } pub struct ConstAttributes<'ctx> { pub is_class_attr: bool, pub name: Option, pub deprecations: Deprecations<'ctx>, } pub enum PyO3ConstAttribute { Name(NameAttribute), } impl Parse for PyO3ConstAttribute { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::name) { input.parse().map(PyO3ConstAttribute::Name) } else { Err(lookahead.error()) } } } impl<'ctx> ConstAttributes<'ctx> { pub fn from_attrs(attrs: &mut Vec, ctx: &'ctx Ctx) -> syn::Result { let mut attributes = ConstAttributes { is_class_attr: false, name: None, deprecations: Deprecations::new(ctx), }; take_attributes(attrs, |attr| { if attr.path().is_ident("classattr") { ensure_spanned!( matches!(attr.meta, syn::Meta::Path(..)), attr.span() => "`#[classattr]` does not take any arguments" ); attributes.is_class_attr = true; Ok(true) } else if let Some(pyo3_attributes) = get_pyo3_options(attr)? { for pyo3_attr in pyo3_attributes { match pyo3_attr { PyO3ConstAttribute::Name(name) => attributes.set_name(name)?, } } Ok(true) } else { Ok(false) } })?; Ok(attributes) } fn set_name(&mut self, name: NameAttribute) -> Result<()> { ensure_spanned!( self.name.is_none(), name.span() => "`name` may only be specified once" ); self.name = Some(name); Ok(()) } } pyo3-macros-backend/src/pyversions.rs0000644000175000017500000000015714661133735020663 0ustar jamespagejamespageuse pyo3_build_config::PythonVersion; pub const PY_3_9: PythonVersion = PythonVersion { major: 3, minor: 9 }; pyo3-macros-backend/src/frompyobject.rs0000644000175000017500000006665014661133735021157 0ustar jamespagejamespageuse crate::attributes::{self, get_pyo3_options, CrateAttribute, FromPyWithAttribute}; use crate::utils::Ctx; use proc_macro2::TokenStream; use quote::{format_ident, quote, quote_spanned}; use syn::{ parenthesized, parse::{Parse, ParseStream}, parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, DataEnum, DeriveInput, Fields, Ident, LitStr, Result, Token, }; /// Describes derivation input of an enum. struct Enum<'a> { enum_ident: &'a Ident, variants: Vec>, } impl<'a> Enum<'a> { /// Construct a new enum representation. /// /// `data_enum` is the `syn` representation of the input enum, `ident` is the /// `Identifier` of the enum. fn new(data_enum: &'a DataEnum, ident: &'a Ident) -> Result { ensure_spanned!( !data_enum.variants.is_empty(), ident.span() => "cannot derive FromPyObject for empty enum" ); let variants = data_enum .variants .iter() .map(|variant| { let attrs = ContainerOptions::from_attrs(&variant.attrs)?; let var_ident = &variant.ident; Container::new(&variant.fields, parse_quote!(#ident::#var_ident), attrs) }) .collect::>>()?; Ok(Enum { enum_ident: ident, variants, }) } /// Build derivation body for enums. fn build(&self, ctx: &Ctx) -> (TokenStream, TokenStream) { let Ctx { pyo3_path, .. } = ctx; let mut var_extracts = Vec::new(); let mut variant_names = Vec::new(); let mut error_names = Vec::new(); let mut deprecations = TokenStream::new(); for var in &self.variants { let (struct_derive, dep) = var.build(ctx); deprecations.extend(dep); let ext = quote!({ let maybe_ret = || -> #pyo3_path::PyResult { #struct_derive }(); match maybe_ret { ok @ ::std::result::Result::Ok(_) => return ok, ::std::result::Result::Err(err) => err } }); var_extracts.push(ext); variant_names.push(var.path.segments.last().unwrap().ident.to_string()); error_names.push(&var.err_name); } let ty_name = self.enum_ident.to_string(); ( quote!( let errors = [ #(#var_extracts),* ]; ::std::result::Result::Err( #pyo3_path::impl_::frompyobject::failed_to_extract_enum( obj.py(), #ty_name, &[#(#variant_names),*], &[#(#error_names),*], &errors ) ) ), deprecations, ) } } struct NamedStructField<'a> { ident: &'a syn::Ident, getter: Option, from_py_with: Option, } struct TupleStructField { from_py_with: Option, } /// Container Style /// /// Covers Structs, Tuplestructs and corresponding Newtypes. enum ContainerType<'a> { /// Struct Container, e.g. `struct Foo { a: String }` /// /// Variant contains the list of field identifiers and the corresponding extraction call. Struct(Vec>), /// Newtype struct container, e.g. `#[transparent] struct Foo { a: String }` /// /// The field specified by the identifier is extracted directly from the object. StructNewtype(&'a syn::Ident, Option), /// Tuple struct, e.g. `struct Foo(String)`. /// /// Variant contains a list of conversion methods for each of the fields that are directly /// extracted from the tuple. Tuple(Vec), /// Tuple newtype, e.g. `#[transparent] struct Foo(String)` /// /// The wrapped field is directly extracted from the object. TupleNewtype(Option), } /// Data container /// /// Either describes a struct or an enum variant. struct Container<'a> { path: syn::Path, ty: ContainerType<'a>, err_name: String, } impl<'a> Container<'a> { /// Construct a container based on fields, identifier and attributes. /// /// Fails if the variant has no fields or incompatible attributes. fn new(fields: &'a Fields, path: syn::Path, options: ContainerOptions) -> Result { let style = match fields { Fields::Unnamed(unnamed) if !unnamed.unnamed.is_empty() => { let mut tuple_fields = unnamed .unnamed .iter() .map(|field| { let attrs = FieldPyO3Attributes::from_attrs(&field.attrs)?; ensure_spanned!( attrs.getter.is_none(), field.span() => "`getter` is not permitted on tuple struct elements." ); Ok(TupleStructField { from_py_with: attrs.from_py_with, }) }) .collect::>>()?; if tuple_fields.len() == 1 { // Always treat a 1-length tuple struct as "transparent", even without the // explicit annotation. let field = tuple_fields.pop().unwrap(); ContainerType::TupleNewtype(field.from_py_with) } else if options.transparent { bail_spanned!( fields.span() => "transparent structs and variants can only have 1 field" ); } else { ContainerType::Tuple(tuple_fields) } } Fields::Named(named) if !named.named.is_empty() => { let mut struct_fields = named .named .iter() .map(|field| { let ident = field .ident .as_ref() .expect("Named fields should have identifiers"); let mut attrs = FieldPyO3Attributes::from_attrs(&field.attrs)?; if let Some(ref from_item_all) = options.from_item_all { if let Some(replaced) = attrs.getter.replace(FieldGetter::GetItem(None)) { match replaced { FieldGetter::GetItem(Some(item_name)) => { attrs.getter = Some(FieldGetter::GetItem(Some(item_name))); } FieldGetter::GetItem(None) => bail_spanned!(from_item_all.span() => "Useless `item` - the struct is already annotated with `from_item_all`"), FieldGetter::GetAttr(_) => bail_spanned!( from_item_all.span() => "The struct is already annotated with `from_item_all`, `attribute` is not allowed" ), } } } Ok(NamedStructField { ident, getter: attrs.getter, from_py_with: attrs.from_py_with, }) }) .collect::>>()?; if options.transparent { ensure_spanned!( struct_fields.len() == 1, fields.span() => "transparent structs and variants can only have 1 field" ); let field = struct_fields.pop().unwrap(); ensure_spanned!( field.getter.is_none(), field.ident.span() => "`transparent` structs may not have a `getter` for the inner field" ); ContainerType::StructNewtype(field.ident, field.from_py_with) } else { ContainerType::Struct(struct_fields) } } _ => bail_spanned!( fields.span() => "cannot derive FromPyObject for empty structs and variants" ), }; let err_name = options.annotation.map_or_else( || path.segments.last().unwrap().ident.to_string(), |lit_str| lit_str.value(), ); let v = Container { path, ty: style, err_name, }; Ok(v) } fn name(&self) -> String { let mut value = String::new(); for segment in &self.path.segments { if !value.is_empty() { value.push_str("::"); } value.push_str(&segment.ident.to_string()); } value } /// Build derivation body for a struct. fn build(&self, ctx: &Ctx) -> (TokenStream, TokenStream) { match &self.ty { ContainerType::StructNewtype(ident, from_py_with) => { self.build_newtype_struct(Some(ident), from_py_with, ctx) } ContainerType::TupleNewtype(from_py_with) => { self.build_newtype_struct(None, from_py_with, ctx) } ContainerType::Tuple(tups) => self.build_tuple_struct(tups, ctx), ContainerType::Struct(tups) => self.build_struct(tups, ctx), } } fn build_newtype_struct( &self, field_ident: Option<&Ident>, from_py_with: &Option, ctx: &Ctx, ) -> (TokenStream, TokenStream) { let Ctx { pyo3_path, .. } = ctx; let self_ty = &self.path; let struct_name = self.name(); if let Some(ident) = field_ident { let field_name = ident.to_string(); match from_py_with { None => ( quote! { Ok(#self_ty { #ident: #pyo3_path::impl_::frompyobject::extract_struct_field(obj, #struct_name, #field_name)? }) }, TokenStream::new(), ), Some(FromPyWithAttribute { value: expr_path, .. }) => ( quote! { Ok(#self_ty { #ident: #pyo3_path::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, #field_name)? }) }, quote_spanned! { expr_path.span() => const _: () = { fn check_from_py_with() { let e = #pyo3_path::impl_::deprecations::GilRefs::new(); #pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e); e.from_py_with_arg(); } }; }, ), } } else { match from_py_with { None => ( quote!( #pyo3_path::impl_::frompyobject::extract_tuple_struct_field(obj, #struct_name, 0).map(#self_ty) ), TokenStream::new(), ), Some(FromPyWithAttribute { value: expr_path, .. }) => ( quote! ( #pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, obj, #struct_name, 0).map(#self_ty) ), quote_spanned! { expr_path.span() => const _: () = { fn check_from_py_with() { let e = #pyo3_path::impl_::deprecations::GilRefs::new(); #pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e); e.from_py_with_arg(); } }; }, ), } } } fn build_tuple_struct( &self, struct_fields: &[TupleStructField], ctx: &Ctx, ) -> (TokenStream, TokenStream) { let Ctx { pyo3_path, .. } = ctx; let self_ty = &self.path; let struct_name = &self.name(); let field_idents: Vec<_> = (0..struct_fields.len()) .map(|i| format_ident!("arg{}", i)) .collect(); let fields = struct_fields.iter().zip(&field_idents).enumerate().map(|(index, (field, ident))| { match &field.from_py_with { None => quote!( #pyo3_path::impl_::frompyobject::extract_tuple_struct_field(&#ident, #struct_name, #index)? ), Some(FromPyWithAttribute { value: expr_path, .. }) => quote! ( #pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#expr_path as fn(_) -> _, &#ident, #struct_name, #index)? ), } }); let deprecations = struct_fields .iter() .filter_map(|field| { let FromPyWithAttribute { value: expr_path, .. } = field.from_py_with.as_ref()?; Some(quote_spanned! { expr_path.span() => const _: () = { fn check_from_py_with() { let e = #pyo3_path::impl_::deprecations::GilRefs::new(); #pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e); e.from_py_with_arg(); } }; }) }) .collect::(); ( quote!( match #pyo3_path::types::PyAnyMethods::extract(obj) { ::std::result::Result::Ok((#(#field_idents),*)) => ::std::result::Result::Ok(#self_ty(#(#fields),*)), ::std::result::Result::Err(err) => ::std::result::Result::Err(err), } ), deprecations, ) } fn build_struct( &self, struct_fields: &[NamedStructField<'_>], ctx: &Ctx, ) -> (TokenStream, TokenStream) { let Ctx { pyo3_path, .. } = ctx; let self_ty = &self.path; let struct_name = &self.name(); let mut fields: Punctuated = Punctuated::new(); for field in struct_fields { let ident = &field.ident; let field_name = ident.to_string(); let getter = match field.getter.as_ref().unwrap_or(&FieldGetter::GetAttr(None)) { FieldGetter::GetAttr(Some(name)) => { quote!(#pyo3_path::types::PyAnyMethods::getattr(obj, #pyo3_path::intern!(obj.py(), #name))) } FieldGetter::GetAttr(None) => { quote!(#pyo3_path::types::PyAnyMethods::getattr(obj, #pyo3_path::intern!(obj.py(), #field_name))) } FieldGetter::GetItem(Some(syn::Lit::Str(key))) => { quote!(#pyo3_path::types::PyAnyMethods::get_item(obj, #pyo3_path::intern!(obj.py(), #key))) } FieldGetter::GetItem(Some(key)) => { quote!(#pyo3_path::types::PyAnyMethods::get_item(obj, #key)) } FieldGetter::GetItem(None) => { quote!(#pyo3_path::types::PyAnyMethods::get_item(obj, #pyo3_path::intern!(obj.py(), #field_name))) } }; let extractor = match &field.from_py_with { None => { quote!(#pyo3_path::impl_::frompyobject::extract_struct_field(&#getter?, #struct_name, #field_name)?) } Some(FromPyWithAttribute { value: expr_path, .. }) => { quote! (#pyo3_path::impl_::frompyobject::extract_struct_field_with(#expr_path as fn(_) -> _, &#getter?, #struct_name, #field_name)?) } }; fields.push(quote!(#ident: #extractor)); } let deprecations = struct_fields .iter() .filter_map(|field| { let FromPyWithAttribute { value: expr_path, .. } = field.from_py_with.as_ref()?; Some(quote_spanned! { expr_path.span() => const _: () = { fn check_from_py_with() { let e = #pyo3_path::impl_::deprecations::GilRefs::new(); #pyo3_path::impl_::deprecations::inspect_fn(#expr_path, &e); e.from_py_with_arg(); } }; }) }) .collect::(); ( quote!(::std::result::Result::Ok(#self_ty{#fields})), deprecations, ) } } #[derive(Default)] struct ContainerOptions { /// Treat the Container as a Wrapper, directly extract its fields from the input object. transparent: bool, /// Force every field to be extracted from item of source Python object. from_item_all: Option, /// Change the name of an enum variant in the generated error message. annotation: Option, /// Change the path for the pyo3 crate krate: Option, } /// Attributes for deriving FromPyObject scoped on containers. enum ContainerPyO3Attribute { /// Treat the Container as a Wrapper, directly extract its fields from the input object. Transparent(attributes::kw::transparent), /// Force every field to be extracted from item of source Python object. ItemAll(attributes::kw::from_item_all), /// Change the name of an enum variant in the generated error message. ErrorAnnotation(LitStr), /// Change the path for the pyo3 crate Crate(CrateAttribute), } impl Parse for ContainerPyO3Attribute { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::transparent) { let kw: attributes::kw::transparent = input.parse()?; Ok(ContainerPyO3Attribute::Transparent(kw)) } else if lookahead.peek(attributes::kw::from_item_all) { let kw: attributes::kw::from_item_all = input.parse()?; Ok(ContainerPyO3Attribute::ItemAll(kw)) } else if lookahead.peek(attributes::kw::annotation) { let _: attributes::kw::annotation = input.parse()?; let _: Token![=] = input.parse()?; input.parse().map(ContainerPyO3Attribute::ErrorAnnotation) } else if lookahead.peek(Token![crate]) { input.parse().map(ContainerPyO3Attribute::Crate) } else { Err(lookahead.error()) } } } impl ContainerOptions { fn from_attrs(attrs: &[Attribute]) -> Result { let mut options = ContainerOptions::default(); for attr in attrs { if let Some(pyo3_attrs) = get_pyo3_options(attr)? { for pyo3_attr in pyo3_attrs { match pyo3_attr { ContainerPyO3Attribute::Transparent(kw) => { ensure_spanned!( !options.transparent, kw.span() => "`transparent` may only be provided once" ); options.transparent = true; } ContainerPyO3Attribute::ItemAll(kw) => { ensure_spanned!( options.from_item_all.is_none(), kw.span() => "`from_item_all` may only be provided once" ); options.from_item_all = Some(kw); } ContainerPyO3Attribute::ErrorAnnotation(lit_str) => { ensure_spanned!( options.annotation.is_none(), lit_str.span() => "`annotation` may only be provided once" ); options.annotation = Some(lit_str); } ContainerPyO3Attribute::Crate(path) => { ensure_spanned!( options.krate.is_none(), path.span() => "`crate` may only be provided once" ); options.krate = Some(path); } } } } } Ok(options) } } /// Attributes for deriving FromPyObject scoped on fields. #[derive(Clone, Debug)] struct FieldPyO3Attributes { getter: Option, from_py_with: Option, } #[derive(Clone, Debug)] enum FieldGetter { GetItem(Option), GetAttr(Option), } enum FieldPyO3Attribute { Getter(FieldGetter), FromPyWith(FromPyWithAttribute), } impl Parse for FieldPyO3Attribute { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::attribute) { let _: attributes::kw::attribute = input.parse()?; if input.peek(syn::token::Paren) { let content; let _ = parenthesized!(content in input); let attr_name: LitStr = content.parse()?; if !content.is_empty() { return Err(content.error( "expected at most one argument: `attribute` or `attribute(\"name\")`", )); } ensure_spanned!( !attr_name.value().is_empty(), attr_name.span() => "attribute name cannot be empty" ); Ok(FieldPyO3Attribute::Getter(FieldGetter::GetAttr(Some( attr_name, )))) } else { Ok(FieldPyO3Attribute::Getter(FieldGetter::GetAttr(None))) } } else if lookahead.peek(attributes::kw::item) { let _: attributes::kw::item = input.parse()?; if input.peek(syn::token::Paren) { let content; let _ = parenthesized!(content in input); let key = content.parse()?; if !content.is_empty() { return Err( content.error("expected at most one argument: `item` or `item(key)`") ); } Ok(FieldPyO3Attribute::Getter(FieldGetter::GetItem(Some(key)))) } else { Ok(FieldPyO3Attribute::Getter(FieldGetter::GetItem(None))) } } else if lookahead.peek(attributes::kw::from_py_with) { input.parse().map(FieldPyO3Attribute::FromPyWith) } else { Err(lookahead.error()) } } } impl FieldPyO3Attributes { /// Extract the field attributes. fn from_attrs(attrs: &[Attribute]) -> Result { let mut getter = None; let mut from_py_with = None; for attr in attrs { if let Some(pyo3_attrs) = get_pyo3_options(attr)? { for pyo3_attr in pyo3_attrs { match pyo3_attr { FieldPyO3Attribute::Getter(field_getter) => { ensure_spanned!( getter.is_none(), attr.span() => "only one of `attribute` or `item` can be provided" ); getter = Some(field_getter); } FieldPyO3Attribute::FromPyWith(from_py_with_attr) => { ensure_spanned!( from_py_with.is_none(), attr.span() => "`from_py_with` may only be provided once" ); from_py_with = Some(from_py_with_attr); } } } } } Ok(FieldPyO3Attributes { getter, from_py_with, }) } } fn verify_and_get_lifetime(generics: &syn::Generics) -> Result> { let mut lifetimes = generics.lifetimes(); let lifetime = lifetimes.next(); ensure_spanned!( lifetimes.next().is_none(), generics.span() => "FromPyObject can be derived with at most one lifetime parameter" ); Ok(lifetime) } /// Derive FromPyObject for enums and structs. /// /// * Max 1 lifetime specifier, will be tied to `FromPyObject`'s specifier /// * At least one field, in case of `#[transparent]`, exactly one field /// * At least one variant for enums. /// * Fields of input structs and enums must implement `FromPyObject` or be annotated with `from_py_with` /// * Derivation for structs with generic fields like `struct Foo(T)` /// adds `T: FromPyObject` on the derived implementation. pub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result { let mut trait_generics = tokens.generics.clone(); let generics = &tokens.generics; let lt_param = if let Some(lt) = verify_and_get_lifetime(generics)? { lt.clone() } else { trait_generics.params.push(parse_quote!('py)); parse_quote!('py) }; let mut where_clause: syn::WhereClause = parse_quote!(where); for param in generics.type_params() { let gen_ident = ¶m.ident; where_clause .predicates .push(parse_quote!(#gen_ident: FromPyObject<#lt_param>)) } let options = ContainerOptions::from_attrs(&tokens.attrs)?; let ctx = &Ctx::new(&options.krate, None); let Ctx { pyo3_path, .. } = &ctx; let (derives, from_py_with_deprecations) = match &tokens.data { syn::Data::Enum(en) => { if options.transparent || options.annotation.is_some() { bail_spanned!(tokens.span() => "`transparent` or `annotation` is not supported \ at top level for enums"); } let en = Enum::new(en, &tokens.ident)?; en.build(ctx) } syn::Data::Struct(st) => { if let Some(lit_str) = &options.annotation { bail_spanned!(lit_str.span() => "`annotation` is unsupported for structs"); } let ident = &tokens.ident; let st = Container::new(&st.fields, parse_quote!(#ident), options)?; st.build(ctx) } syn::Data::Union(_) => bail_spanned!( tokens.span() => "#[derive(FromPyObject)] is not supported for unions" ), }; let ident = &tokens.ident; Ok(quote!( #[automatically_derived] impl #trait_generics #pyo3_path::FromPyObject<#lt_param> for #ident #generics #where_clause { fn extract_bound(obj: &#pyo3_path::Bound<#lt_param, #pyo3_path::PyAny>) -> #pyo3_path::PyResult { #derives } } #from_py_with_deprecations )) } pyo3-macros-backend/src/module.rs0000644000175000017500000005726114661133735017737 0ustar jamespagejamespage//! Code generation for the function that initializes a python module and adds classes and function. use crate::{ attributes::{ self, kw, take_attributes, take_pyo3_options, CrateAttribute, ModuleAttribute, NameAttribute, SubmoduleAttribute, }, get_doc, pyclass::PyClassPyO3Option, pyfunction::{impl_wrap_pyfunction, PyFunctionOptions}, utils::{Ctx, LitCStr, PyO3CratePath}, }; use proc_macro2::{Span, TokenStream}; use quote::quote; use std::ffi::CString; use syn::{ ext::IdentExt, parse::{Parse, ParseStream}, parse_quote, parse_quote_spanned, punctuated::Punctuated, spanned::Spanned, token::Comma, Item, Meta, Path, Result, }; #[derive(Default)] pub struct PyModuleOptions { krate: Option, name: Option, module: Option, submodule: Option, } impl Parse for PyModuleOptions { fn parse(input: ParseStream<'_>) -> syn::Result { let mut options: PyModuleOptions = Default::default(); options.add_attributes( Punctuated::::parse_terminated(input)?, )?; Ok(options) } } impl PyModuleOptions { fn take_pyo3_options(&mut self, attrs: &mut Vec) -> Result<()> { self.add_attributes(take_pyo3_options(attrs)?) } fn add_attributes( &mut self, attrs: impl IntoIterator, ) -> Result<()> { macro_rules! set_option { ($key:ident) => { { ensure_spanned!( self.$key.is_none(), $key.span() => concat!("`", stringify!($key), "` may only be specified once") ); self.$key = Some($key); } }; } for attr in attrs { match attr { PyModulePyO3Option::Crate(krate) => set_option!(krate), PyModulePyO3Option::Name(name) => set_option!(name), PyModulePyO3Option::Module(module) => set_option!(module), PyModulePyO3Option::Submodule(submodule) => set_option!(submodule), } } Ok(()) } } pub fn pymodule_module_impl( module: &mut syn::ItemMod, mut options: PyModuleOptions, ) -> Result { let syn::ItemMod { attrs, vis, unsafety: _, ident, mod_token, content, semi: _, } = module; let items = if let Some((_, items)) = content { items } else { bail_spanned!(mod_token.span() => "`#[pymodule]` can only be used on inline modules") }; options.take_pyo3_options(attrs)?; let ctx = &Ctx::new(&options.krate, None); let Ctx { pyo3_path, .. } = ctx; let doc = get_doc(attrs, None, ctx); let name = options .name .map_or_else(|| ident.unraw(), |name| name.value.0); let full_name = if let Some(module) = &options.module { format!("{}.{}", module.value.value(), name) } else { name.to_string() }; let mut module_items = Vec::new(); let mut module_items_cfg_attrs = Vec::new(); fn extract_use_items( source: &syn::UseTree, cfg_attrs: &[syn::Attribute], target_items: &mut Vec, target_cfg_attrs: &mut Vec>, ) -> Result<()> { match source { syn::UseTree::Name(name) => { target_items.push(name.ident.clone()); target_cfg_attrs.push(cfg_attrs.to_vec()); } syn::UseTree::Path(path) => { extract_use_items(&path.tree, cfg_attrs, target_items, target_cfg_attrs)? } syn::UseTree::Group(group) => { for tree in &group.items { extract_use_items(tree, cfg_attrs, target_items, target_cfg_attrs)? } } syn::UseTree::Glob(glob) => { bail_spanned!(glob.span() => "#[pymodule] cannot import glob statements") } syn::UseTree::Rename(rename) => { target_items.push(rename.rename.clone()); target_cfg_attrs.push(cfg_attrs.to_vec()); } } Ok(()) } let mut pymodule_init = None; for item in &mut *items { match item { Item::Use(item_use) => { let is_pymodule_export = find_and_remove_attribute(&mut item_use.attrs, "pymodule_export"); if is_pymodule_export { let cfg_attrs = get_cfg_attributes(&item_use.attrs); extract_use_items( &item_use.tree, &cfg_attrs, &mut module_items, &mut module_items_cfg_attrs, )?; } } Item::Fn(item_fn) => { ensure_spanned!( !has_attribute(&item_fn.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); let is_pymodule_init = find_and_remove_attribute(&mut item_fn.attrs, "pymodule_init"); let ident = &item_fn.sig.ident; if is_pymodule_init { ensure_spanned!( !has_attribute(&item_fn.attrs, "pyfunction"), item_fn.span() => "`#[pyfunction]` cannot be used alongside `#[pymodule_init]`" ); ensure_spanned!(pymodule_init.is_none(), item_fn.span() => "only one `#[pymodule_init]` may be specified"); pymodule_init = Some(quote! { #ident(module)?; }); } else if has_attribute(&item_fn.attrs, "pyfunction") || has_attribute_with_namespace( &item_fn.attrs, Some(pyo3_path), &["pyfunction"], ) || has_attribute_with_namespace( &item_fn.attrs, Some(pyo3_path), &["prelude", "pyfunction"], ) { module_items.push(ident.clone()); module_items_cfg_attrs.push(get_cfg_attributes(&item_fn.attrs)); } } Item::Struct(item_struct) => { ensure_spanned!( !has_attribute(&item_struct.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); if has_attribute(&item_struct.attrs, "pyclass") || has_attribute_with_namespace( &item_struct.attrs, Some(pyo3_path), &["pyclass"], ) || has_attribute_with_namespace( &item_struct.attrs, Some(pyo3_path), &["prelude", "pyclass"], ) { module_items.push(item_struct.ident.clone()); module_items_cfg_attrs.push(get_cfg_attributes(&item_struct.attrs)); if !has_pyo3_module_declared::( &item_struct.attrs, "pyclass", |option| matches!(option, PyClassPyO3Option::Module(_)), )? { set_module_attribute(&mut item_struct.attrs, &full_name); } } } Item::Enum(item_enum) => { ensure_spanned!( !has_attribute(&item_enum.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); if has_attribute(&item_enum.attrs, "pyclass") || has_attribute_with_namespace(&item_enum.attrs, Some(pyo3_path), &["pyclass"]) || has_attribute_with_namespace( &item_enum.attrs, Some(pyo3_path), &["prelude", "pyclass"], ) { module_items.push(item_enum.ident.clone()); module_items_cfg_attrs.push(get_cfg_attributes(&item_enum.attrs)); if !has_pyo3_module_declared::( &item_enum.attrs, "pyclass", |option| matches!(option, PyClassPyO3Option::Module(_)), )? { set_module_attribute(&mut item_enum.attrs, &full_name); } } } Item::Mod(item_mod) => { ensure_spanned!( !has_attribute(&item_mod.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); if has_attribute(&item_mod.attrs, "pymodule") || has_attribute_with_namespace(&item_mod.attrs, Some(pyo3_path), &["pymodule"]) || has_attribute_with_namespace( &item_mod.attrs, Some(pyo3_path), &["prelude", "pymodule"], ) { module_items.push(item_mod.ident.clone()); module_items_cfg_attrs.push(get_cfg_attributes(&item_mod.attrs)); if !has_pyo3_module_declared::( &item_mod.attrs, "pymodule", |option| matches!(option, PyModulePyO3Option::Module(_)), )? { set_module_attribute(&mut item_mod.attrs, &full_name); } } } Item::ForeignMod(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::Trait(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::Const(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::Static(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::Macro(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::ExternCrate(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::Impl(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::TraitAlias(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::Type(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } Item::Union(item) => { ensure_spanned!( !has_attribute(&item.attrs, "pymodule_export"), item.span() => "`#[pymodule_export]` may only be used on `use` statements" ); } _ => (), } } let module_def = quote! {{ use #pyo3_path::impl_::pymodule as impl_; const INITIALIZER: impl_::ModuleInitializer = impl_::ModuleInitializer(__pyo3_pymodule); unsafe { impl_::ModuleDef::new( __PYO3_NAME, #doc, INITIALIZER ) } }}; let initialization = module_initialization(&name, ctx, module_def, options.submodule.is_some()); Ok(quote!( #(#attrs)* #vis #mod_token #ident { #(#items)* #initialization fn __pyo3_pymodule(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> { use #pyo3_path::impl_::pymodule::PyAddToModule; #( #(#module_items_cfg_attrs)* #module_items::_PYO3_DEF.add_to_module(module)?; )* #pymodule_init Ok(()) } } )) } /// Generates the function that is called by the python interpreter to initialize the native /// module pub fn pymodule_function_impl( function: &mut syn::ItemFn, mut options: PyModuleOptions, ) -> Result { options.take_pyo3_options(&mut function.attrs)?; process_functions_in_module(&options, function)?; let ctx = &Ctx::new(&options.krate, None); let stmts = std::mem::take(&mut function.block.stmts); let Ctx { pyo3_path, .. } = ctx; let ident = &function.sig.ident; let name = options .name .map_or_else(|| ident.unraw(), |name| name.value.0); let vis = &function.vis; let doc = get_doc(&function.attrs, None, ctx); let initialization = module_initialization(&name, ctx, quote! { MakeDef::make_def() }, false); // Module function called with optional Python<'_> marker as first arg, followed by the module. let mut module_args = Vec::new(); if function.sig.inputs.len() == 2 { module_args.push(quote!(module.py())); } module_args .push(quote!(::std::convert::Into::into(#pyo3_path::impl_::pymethods::BoundRef(module)))); let extractors = function .sig .inputs .iter() .filter_map(|param| { if let syn::FnArg::Typed(pat_type) = param { if let syn::Pat::Ident(pat_ident) = &*pat_type.pat { let ident: &syn::Ident = &pat_ident.ident; return Some([ parse_quote!{ let check_gil_refs = #pyo3_path::impl_::deprecations::GilRefs::new(); }, parse_quote! { let #ident = #pyo3_path::impl_::deprecations::inspect_type(#ident, &check_gil_refs); }, parse_quote_spanned! { pat_type.span() => check_gil_refs.function_arg(); }, ]); } } None }) .flatten(); function.block.stmts = extractors.chain(stmts).collect(); function .attrs .push(parse_quote!(#[allow(clippy::used_underscore_binding)])); Ok(quote! { #[doc(hidden)] #vis mod #ident { #initialization } // Generate the definition inside an anonymous function in the same scope as the original function - // this avoids complications around the fact that the generated module has a different scope // (and `super` doesn't always refer to the outer scope, e.g. if the `#[pymodule] is // inside a function body) #[allow(unknown_lints, non_local_definitions)] impl #ident::MakeDef { const fn make_def() -> #pyo3_path::impl_::pymodule::ModuleDef { fn __pyo3_pymodule(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> { #ident(#(#module_args),*) } const INITIALIZER: #pyo3_path::impl_::pymodule::ModuleInitializer = #pyo3_path::impl_::pymodule::ModuleInitializer(__pyo3_pymodule); unsafe { #pyo3_path::impl_::pymodule::ModuleDef::new( #ident::__PYO3_NAME, #doc, INITIALIZER ) } } } }) } fn module_initialization( name: &syn::Ident, ctx: &Ctx, module_def: TokenStream, is_submodule: bool, ) -> TokenStream { let Ctx { pyo3_path, .. } = ctx; let pyinit_symbol = format!("PyInit_{}", name); let name = name.to_string(); let pyo3_name = LitCStr::new(CString::new(name).unwrap(), Span::call_site(), ctx); let mut result = quote! { #[doc(hidden)] pub const __PYO3_NAME: &'static ::std::ffi::CStr = #pyo3_name; pub(super) struct MakeDef; #[doc(hidden)] pub static _PYO3_DEF: #pyo3_path::impl_::pymodule::ModuleDef = #module_def; }; if !is_submodule { result.extend(quote! { /// This autogenerated function is called by the python interpreter when importing /// the module. #[doc(hidden)] #[export_name = #pyinit_symbol] pub unsafe extern "C" fn __pyo3_init() -> *mut #pyo3_path::ffi::PyObject { #pyo3_path::impl_::trampoline::module_init(|py| _PYO3_DEF.make_module(py)) } }); } result } /// Finds and takes care of the #[pyfn(...)] in `#[pymodule]` fn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn) -> Result<()> { let ctx = &Ctx::new(&options.krate, None); let Ctx { pyo3_path, .. } = ctx; let mut stmts: Vec = Vec::new(); #[cfg(feature = "gil-refs")] let imports = quote!(use #pyo3_path::{PyNativeType, types::PyModuleMethods};); #[cfg(not(feature = "gil-refs"))] let imports = quote!(use #pyo3_path::types::PyModuleMethods;); for mut stmt in func.block.stmts.drain(..) { if let syn::Stmt::Item(Item::Fn(func)) = &mut stmt { if let Some(pyfn_args) = get_pyfn_attr(&mut func.attrs)? { let module_name = pyfn_args.modname; let wrapped_function = impl_wrap_pyfunction(func, pyfn_args.options)?; let name = &func.sig.ident; let statements: Vec = syn::parse_quote! { #wrapped_function { #[allow(unknown_lints, unused_imports, redundant_imports)] #imports #module_name.as_borrowed().add_function(#pyo3_path::wrap_pyfunction!(#name, #module_name.as_borrowed())?)?; } }; stmts.extend(statements); } }; stmts.push(stmt); } func.block.stmts = stmts; Ok(()) } pub struct PyFnArgs { modname: Path, options: PyFunctionOptions, } impl Parse for PyFnArgs { fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let modname = input.parse().map_err( |e| err_spanned!(e.span() => "expected module as first argument to #[pyfn()]"), )?; if input.is_empty() { return Ok(Self { modname, options: Default::default(), }); } let _: Comma = input.parse()?; Ok(Self { modname, options: input.parse()?, }) } } /// Extracts the data from the #[pyfn(...)] attribute of a function fn get_pyfn_attr(attrs: &mut Vec) -> syn::Result> { let mut pyfn_args: Option = None; take_attributes(attrs, |attr| { if attr.path().is_ident("pyfn") { ensure_spanned!( pyfn_args.is_none(), attr.span() => "`#[pyfn] may only be specified once" ); pyfn_args = Some(attr.parse_args()?); Ok(true) } else { Ok(false) } })?; if let Some(pyfn_args) = &mut pyfn_args { pyfn_args .options .add_attributes(take_pyo3_options(attrs)?)?; } Ok(pyfn_args) } fn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec { attrs .iter() .filter(|attr| attr.path().is_ident("cfg")) .cloned() .collect() } fn find_and_remove_attribute(attrs: &mut Vec, ident: &str) -> bool { let mut found = false; attrs.retain(|attr| { if attr.path().is_ident(ident) { found = true; false } else { true } }); found } enum IdentOrStr<'a> { Str(&'a str), Ident(syn::Ident), } impl<'a> PartialEq for IdentOrStr<'a> { fn eq(&self, other: &syn::Ident) -> bool { match self { IdentOrStr::Str(s) => other == s, IdentOrStr::Ident(i) => other == i, } } } fn has_attribute(attrs: &[syn::Attribute], ident: &str) -> bool { has_attribute_with_namespace(attrs, None, &[ident]) } fn has_attribute_with_namespace( attrs: &[syn::Attribute], crate_path: Option<&PyO3CratePath>, idents: &[&str], ) -> bool { let mut segments = vec![]; if let Some(c) = crate_path { match c { PyO3CratePath::Given(paths) => { for p in &paths.segments { segments.push(IdentOrStr::Ident(p.ident.clone())); } } PyO3CratePath::Default => segments.push(IdentOrStr::Str("pyo3")), } }; for i in idents { segments.push(IdentOrStr::Str(i)); } attrs.iter().any(|attr| { segments .iter() .eq(attr.path().segments.iter().map(|v| &v.ident)) }) } fn set_module_attribute(attrs: &mut Vec, module_name: &str) { attrs.push(parse_quote!(#[pyo3(module = #module_name)])); } fn has_pyo3_module_declared( attrs: &[syn::Attribute], root_attribute_name: &str, is_module_option: impl Fn(&T) -> bool + Copy, ) -> Result { for attr in attrs { if (attr.path().is_ident("pyo3") || attr.path().is_ident(root_attribute_name)) && matches!(attr.meta, Meta::List(_)) { for option in &attr.parse_args_with(Punctuated::::parse_terminated)? { if is_module_option(option) { return Ok(true); } } } } Ok(false) } enum PyModulePyO3Option { Submodule(SubmoduleAttribute), Crate(CrateAttribute), Name(NameAttribute), Module(ModuleAttribute), } impl Parse for PyModulePyO3Option { fn parse(input: ParseStream<'_>) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(attributes::kw::name) { input.parse().map(PyModulePyO3Option::Name) } else if lookahead.peek(syn::Token![crate]) { input.parse().map(PyModulePyO3Option::Crate) } else if lookahead.peek(attributes::kw::module) { input.parse().map(PyModulePyO3Option::Module) } else if lookahead.peek(attributes::kw::submodule) { input.parse().map(PyModulePyO3Option::Submodule) } else { Err(lookahead.error()) } } } pyo3-macros-backend/src/deprecations.rs0000644000175000017500000000625614661133735021130 0ustar jamespagejamespageuse crate::{ method::{FnArg, FnSpec}, utils::Ctx, }; use proc_macro2::{Span, TokenStream}; use quote::{quote_spanned, ToTokens}; pub enum Deprecation { PyMethodsNewDeprecatedForm, } impl Deprecation { fn ident(&self, span: Span) -> syn::Ident { let string = match self { Deprecation::PyMethodsNewDeprecatedForm => "PYMETHODS_NEW_DEPRECATED_FORM", }; syn::Ident::new(string, span) } } pub struct Deprecations<'ctx>(Vec<(Deprecation, Span)>, &'ctx Ctx); impl<'ctx> Deprecations<'ctx> { pub fn new(ctx: &'ctx Ctx) -> Self { Deprecations(Vec::new(), ctx) } pub fn push(&mut self, deprecation: Deprecation, span: Span) { self.0.push((deprecation, span)) } } impl<'ctx> ToTokens for Deprecations<'ctx> { fn to_tokens(&self, tokens: &mut TokenStream) { let Self(deprecations, Ctx { pyo3_path, .. }) = self; for (deprecation, span) in deprecations { let pyo3_path = pyo3_path.to_tokens_spanned(*span); let ident = deprecation.ident(*span); quote_spanned!( *span => #[allow(clippy::let_unit_value)] { let _ = #pyo3_path::impl_::deprecations::#ident; } ) .to_tokens(tokens) } } } pub(crate) fn deprecate_trailing_option_default(spec: &FnSpec<'_>) -> TokenStream { if spec.signature.attribute.is_none() && spec.tp.signature_attribute_allowed() && spec.signature.arguments.iter().any(|arg| { if let FnArg::Regular(arg) = arg { arg.option_wrapped_type.is_some() } else { false } }) { use std::fmt::Write; let mut deprecation_msg = String::from( "this function has implicit defaults for the trailing `Option` arguments \n\ = note: these implicit defaults are being phased out \n\ = help: add `#[pyo3(signature = (", ); spec.signature.arguments.iter().for_each(|arg| { match arg { FnArg::Regular(arg) => { if arg.option_wrapped_type.is_some() { write!(deprecation_msg, "{}=None, ", arg.name) } else { write!(deprecation_msg, "{}, ", arg.name) } } FnArg::VarArgs(arg) => write!(deprecation_msg, "{}, ", arg.name), FnArg::KwArgs(arg) => write!(deprecation_msg, "{}, ", arg.name), FnArg::Py(_) | FnArg::CancelHandle(_) => Ok(()), } .expect("writing to `String` should not fail"); }); //remove trailing space and comma deprecation_msg.pop(); deprecation_msg.pop(); deprecation_msg.push_str( "))]` to this function to silence this warning and keep the current behavior", ); quote_spanned! { spec.name.span() => #[deprecated(note = #deprecation_msg)] #[allow(dead_code)] const SIGNATURE: () = (); const _: () = SIGNATURE; } } else { TokenStream::new() } } pyo3-macros-backend/.cargo-checksum.json0000664000175000017500000000335714661133735021160 0ustar jamespagejamespage{"files":{"Cargo.toml":"873568039fc9cd51963b5c2419e3d2c743ac5ecd7b2ec187ed6cd912db3b703d","LICENSE-APACHE":"71073d492e996de196dbe1eb1e4c94c27c014c841b288161265b2efd06d0af28","LICENSE-MIT":"afcbe3b2e6b37172b5a9ca869ee4c0b8cdc09316e5d4384864154482c33e5af6","build.rs":"297616b244181f0f18db54be8cd5762d7fba19298b6221f4cff668a34abd24f2","src/attributes.rs":"12d877f3da48b383dd8d52e2f5b943f77320d92812f785b00342ca89d948af5f","src/deprecations.rs":"6700ea169543ccd769cec9f98cf07d795ac4d5b25469b777cf712dccb18c213b","src/frompyobject.rs":"6a08ecfbf07a03c2b34d3fb7f8c3219f64118998ed04d1e14953bf207e3bf41b","src/konst.rs":"c5dc8d654d31b11b6169ba7705781adb57f01d2489377da8d62882a62c5993ae","src/lib.rs":"68807b8832364c83d88a5a7907f9685068597ce6fc5f14fd91acc055c1be6deb","src/method.rs":"f390ee532a7baeca5b826def184860d00c18f7ef8783d0357b58276aa16a11ed","src/module.rs":"0b00aed691e4a64456dc984d03d5ec8a1b9aaffcd707d182653867750b1b94bb","src/params.rs":"348d18f6be7279a5a13169ff6c887b2e5e015648db6ad53913bbd0111275c9fa","src/pyclass.rs":"6276f4d8f4939892f5355e9b1b6ce765c28b1c236274a89a973c06c60ce1a70a","src/pyfunction.rs":"ba6e89d6c7a166c269f8b9281dadd56075e4924548c2b53423520c24c7154de1","src/pyfunction/signature.rs":"4520beb85bbc52516af498da2c8196a827cb6686a0be977295e65ba55bef8ce7","src/pyimpl.rs":"a37baa4ffd279e35be82ecfb90d96a0c0e6b1b7b9666b18ea4e747cabeeab89c","src/pymethod.rs":"e378f2bcd29c7a640bdbb0911145c647f1cdc88806de0cb2d3d8d1ad0cef478f","src/pyversions.rs":"6a5f4ef1d79ecba950cbd9b29e68e6566aeac3e85ab225e9dbdd0204969f073d","src/quotes.rs":"94680b308ba592529ec46c0348949836c72c3f7d706deb1f7dae3d8d943c017b","src/utils.rs":"895f97bb6f4c3c9add47f1e57d8a32c6e440fafd15fbf7a6e17b36de08811901"},"package":"ec480c0c51ddec81019531705acac51bcdbeae563557c982aa8263bb96880372"}python3-dll-a/0000775000175000017500000000000014661133735014136 5ustar jamespagejamespagepython3-dll-a/README.md0000644000175000017500000001011514661133735015411 0ustar jamespagejamespageStandalone `python3(y).dll` import library generator ==================================================== [![Actions Status](https://github.com/PyO3/python3-dll-a/workflows/Test/badge.svg)](https://github.com/PyO3/python3-dll-a/actions) [![Crate](https://img.shields.io/crates/v/python3-dll-a.svg)](https://crates.io/crates/python3-dll-a) [![Documentation](https://docs.rs/python3-dll-a/badge.svg)](https://docs.rs/python3-dll-a) Generates import libraries for the Python DLL (either `python3.dll` or `python3y.dll`) for MinGW-w64 and MSVC (cross-)compile targets. This crate **does not require** Python 3 distribution files to be present on the (cross-)compile host system. This crate uses the binutils `dlltool` program to generate the Python DLL import libraries for MinGW-w64 targets. Setting `PYO3_MINGW_DLLTOOL` environment variable overrides the default `dlltool` command name for the target. **Note:** MSVC cross-compile targets require either LLVM binutils or Zig to be available on the host system. More specifically, `python3-dll-a` requires `llvm-dlltool` executable to be present in `PATH` when targeting `*-pc-windows-msvc` from Linux. Alternatively, `ZIG_COMMAND` environment variable may be set to e.g. `"zig"` or `"python -m ziglang"`, then `zig dlltool` will be used in place of `llvm-dlltool` (or MinGW binutils). PyO3 integration ---------------- Since version **0.16.5**, the `pyo3` crate implements support for both the Stable ABI and version-specific Python DLL import library generation via its new `generate-import-lib` feature. In this configuration, `python3-dll-a` becomes a `pyo3` crate dependency and is automatically invoked by its build script in both native and cross compilation scenarios. ### Example `Cargo.toml` usage for an `abi3` PyO3 extension module ```toml [dependencies] pyo3 = { version = "0.16.5", features = ["extension-module", "abi3-py37", "generate-import-lib"] } ``` ### Example `Cargo.toml` usage for a standard PyO3 extension module ```toml [dependencies] pyo3 = { version = "0.16.5", features = ["extension-module", "generate-import-lib"] } ``` Standalone build script usage ----------------------------- If an older `pyo3` crate version is used, or a different Python bindings library is required, `python3-dll-a` can be used directly from the crate build script. The examples below assume using an older version of PyO3. ### Example `build.rs` script for an `abi3` PyO3 extension The following cargo build script can be used to cross-compile Stable ABI PyO3 extension modules for Windows (64/32-bit x86 or 64-bit ARM) using either MinGW-w64 or MSVC target environment ABI: ```rust fn main() { if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" { let cross_lib_dir = std::env::var_os("PYO3_CROSS_LIB_DIR") .expect("PYO3_CROSS_LIB_DIR is not set when cross-compiling"); let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); let env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap(); let libdir = std::path::Path::new(&cross_lib_dir); python3_dll_a::generate_implib_for_target(libdir, &arch, &env) .expect("python3.dll import library generator failed"); } } ``` A compatible `python3.dll` import library file named `python3.dll.a` or `python3.lib` will be automatically created in the directory pointed by the `PYO3_CROSS_LIB_DIR` environment variable. ### Example `cargo build` invocation ```sh PYO3_CROSS_LIB_DIR=target/python3-dll cargo build --target x86_64-pc-windows-gnu ``` Generating version-specific `python3y.dll` import libraries ----------------------------------------------------------- As an advanced feature, `python3-dll-a` can generate Python version specific import libraries such as `python39.lib`. See the `ImportLibraryGenerator` builder API description for details. Maintenance ----------- This crate embeds Module-Defitions based on the `stable_abi.toml` file from CPython. The upstream version of this file is located in the [CPython project][cpython] repository under the path `Misc/stable_abi.toml`. [cpython]: https://github.com/python/cpython/blob/main/Misc/stable_abi.toml python3-dll-a/Cargo.toml0000644000175000017500000000202214661133735016060 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "python3-dll-a" version = "0.2.10" authors = [ "Sergey Kvachonok ", "messense ", "Adam Reichold ", ] description = "Standalone python3(y).dll import library generator" readme = "README.md" keywords = [ "build-dependencies", "python", "windows", "mingw", "msvc", ] categories = ["development-tools::build-utils"] license = "MIT" repository = "https://github.com/PyO3/python3-dll-a" [target."cfg(windows)".dependencies.cc] version = "1.0.73" python3-dll-a/src/0000775000175000017500000000000014661133735014725 5ustar jamespagejamespagepython3-dll-a/src/python39.def0000644000175000017500000010515414661133735017106 0ustar jamespagejamespage; ; Definition file of python39.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "python39.dll" EXPORTS PyAST_CompileEx PyAST_CompileObject PyAST_FromNode PyAST_FromNodeObject PyAST_Validate PyArena_AddPyObject PyArena_Free PyArena_Malloc PyArena_New PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyAsyncGen_New PyAsyncGen_Type DATA PyBaseObject_Type DATA PyBool_FromLong PyBool_Type DATA PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_FromContiguous PyBuffer_GetPointer PyBuffer_IsContiguous PyBuffer_Release PyBuffer_SizeFromFormat PyBuffer_ToContiguous PyByteArrayIter_Type DATA PyByteArray_AsString PyByteArray_Concat PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Resize PyByteArray_Size PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyBytes_Type DATA PyCFunction_Call PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_NewEx PyCFunction_Type DATA PyCMethod_New PyCMethod_Type DATA PyCallIter_New PyCallIter_Type DATA PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCapsule_Type DATA PyCell_Get PyCell_New PyCell_Set PyCell_Type DATA PyClassMethodDescr_Type DATA PyClassMethod_New PyClassMethod_Type DATA PyCode_Addr2Line PyCode_New PyCode_NewEmpty PyCode_NewWithPosOnlyArgs PyCode_Optimize PyCode_Type DATA PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_NameReplaceErrors PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_XMLCharRefReplaceErrors PyCompile_OpcodeStackEffect PyCompile_OpcodeStackEffectWithJump PyComplex_AsCComplex PyComplex_FromCComplex PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyComplex_Type DATA PyConfig_Clear PyConfig_InitIsolatedConfig PyConfig_InitPythonConfig PyConfig_Read PyConfig_SetArgv PyConfig_SetBytesArgv PyConfig_SetBytesString PyConfig_SetString PyConfig_SetWideStringList PyContextToken_Type DATA PyContextVar_Get PyContextVar_New PyContextVar_Reset PyContextVar_Set PyContextVar_Type DATA PyContext_Copy PyContext_CopyCurrent PyContext_Enter PyContext_Exit PyContext_New PyContext_Type DATA PyCoro_New PyCoro_Type DATA PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDescr_NewWrapper PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_New PyDictProxy_Type DATA PyDictRevIterItem_Type DATA PyDictRevIterKey_Type DATA PyDictRevIterValue_Type DATA PyDictValues_Type DATA PyDict_Clear PyDict_Contains PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_GetItem PyDict_GetItemString PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_SetDefault PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Type DATA PyDict_Update PyDict_Values PyEllipsis_Type DATA PyEnum_Type DATA PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_FormatV PyErr_GetExcInfo PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_ProgramTextObject PyErr_ResourceWarning PyErr_Restore PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetExcFromWindowsErrWithUnicodeFilename PyErr_SetExcInfo PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetFromErrnoWithFilenameObjects PyErr_SetFromErrnoWithUnicodeFilename PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyErr_SetFromWindowsErrWithUnicodeFilename PyErr_SetImportError PyErr_SetImportErrorSubclass PyErr_SetInterrupt PyErr_SetNone PyErr_SetObject PyErr_SetString PyErr_SyntaxLocation PyErr_SyntaxLocationEx PyErr_SyntaxLocationObject PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnExplicitFormat PyErr_WarnExplicitObject PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_MergeCompilerFlags PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_SetProfile PyEval_SetTrace PyEval_ThreadsInitialized PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_ModuleNotFoundError DATA PyExc_NameError DATA PyExc_NotADirectoryError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_RecursionError DATA PyExc_ReferenceError DATA PyExc_ResourceWarning DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopAsyncIteration DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TimeoutError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_WindowsError DATA PyExc_ZeroDivisionError DATA PyExceptionClass_Name PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_NewStdPrinter PyFile_OpenCode PyFile_OpenCodeObject PyFile_SetOpenCodeHook PyFile_WriteObject PyFile_WriteString PyFilter_Type DATA PyFloat_AsDouble PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFloat_Type DATA PyFrame_BlockPop PyFrame_BlockSetup PyFrame_FastToLocals PyFrame_FastToLocalsWithError PyFrame_GetBack PyFrame_GetCode PyFrame_GetLineNumber PyFrame_LocalsToFast PyFrame_New PyFrame_Type DATA PyFrozenSet_New PyFrozenSet_Type DATA PyFunction_GetAnnotations PyFunction_GetClosure PyFunction_GetCode PyFunction_GetDefaults PyFunction_GetGlobals PyFunction_GetKwDefaults PyFunction_GetModule PyFunction_New PyFunction_NewWithQualName PyFunction_SetAnnotations PyFunction_SetClosure PyFunction_SetDefaults PyFunction_SetKwDefaults PyFunction_Type DATA PyFuture_FromAST PyFuture_FromASTObject PyGC_Collect PyGILState_Check PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyGen_New PyGen_NewWithQualName PyGen_Type DATA PyGetSetDescr_Type DATA PyHash_GetFuncDef PyImport_AddModule PyImport_AddModuleObject PyImport_AppendInittab PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleObject PyImport_ExecCodeModuleWithPathnames PyImport_ExtendInittab PyImport_FrozenModules DATA PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModule PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportFrozenModuleObject PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleLevelObject PyImport_ImportModuleNoBlock PyImport_Inittab DATA PyImport_ReloadModule PyIndex_Check PyInstanceMethod_Function PyInstanceMethod_New PyInstanceMethod_Type DATA PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_Get PyInterpreterState_GetDict PyInterpreterState_GetID PyInterpreterState_Head PyInterpreterState_Main PyInterpreterState_New PyInterpreterState_Next PyInterpreterState_ThreadHead PyIter_Check PyIter_Next PyListIter_Type DATA PyListRevIter_Type DATA PyList_Append PyList_AsTuple PyList_GetItem PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyList_Type DATA PyLongRangeIter_Type DATA PyLong_AsDouble PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnicode PyLong_FromUnicodeObject PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromVoidPtr PyLong_GetInfo PyLong_Type DATA PyMap_Type DATA PyMapping_Check PyMapping_GetItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMarshal_ReadLastObjectFromFile PyMarshal_ReadLongFromFile PyMarshal_ReadObjectFromFile PyMarshal_ReadObjectFromString PyMarshal_ReadShortFromFile PyMarshal_WriteLongToFile PyMarshal_WriteObjectToFile PyMarshal_WriteObjectToString PyMem_Calloc PyMem_Free PyMem_GetAllocator PyMem_Malloc PyMem_RawCalloc PyMem_RawFree PyMem_RawMalloc PyMem_RawRealloc PyMem_Realloc PyMem_SetAllocator PyMem_SetupDebugHooks PyMemberDescr_Type DATA PyMember_GetOne PyMember_SetOne PyMemoryView_FromBuffer PyMemoryView_FromMemory PyMemoryView_FromObject PyMemoryView_GetContiguous PyMemoryView_Type DATA PyMethodDescr_Type DATA PyMethod_Function PyMethod_New PyMethod_Self PyMethod_Type DATA PyModuleDef_Init PyModuleDef_Type DATA PyModule_AddFunctions PyModule_AddIntConstant PyModule_AddObject PyModule_AddStringConstant PyModule_AddType PyModule_Create2 PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetNameObject PyModule_GetState PyModule_New PyModule_NewObject PyModule_SetDocString PyModule_Type DATA PyNode_AddChild PyNode_Compile PyNode_Free PyNode_ListTree PyNode_New PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMatrixMultiply PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_MatrixMultiply PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyODictItems_Type DATA PyODictIter_Type DATA PyODictKeys_Type DATA PyODictValues_Type DATA PyODict_DelItem PyODict_New PyODict_SetItem PyODict_Type DATA PyOS_AfterFork PyOS_FSPath PyOS_InitInterrupts PyOS_InputHook DATA PyOS_InterruptOccurred PyOS_Readline PyOS_ReadlineFunctionPointer DATA PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsCharBuffer PyObject_AsFileDescriptor PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_Bytes PyObject_Call PyObject_CallFinalizer PyObject_CallFinalizerFromDealloc PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallNoArgs PyObject_CallObject PyObject_Calloc PyObject_CheckBuffer PyObject_CheckReadBuffer PyObject_ClearWeakRefs PyObject_CopyData PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_IsFinalized PyObject_GC_IsTracked PyObject_GC_Track PyObject_GC_UnTrack PyObject_GET_WEAKREFS_LISTPTR PyObject_GenericGetAttr PyObject_GenericGetDict PyObject_GenericSetAttr PyObject_GenericSetDict PyObject_GetArenaAllocator PyObject_GetAttr PyObject_GetAttrString PyObject_GetBuffer PyObject_GetItem PyObject_GetIter PyObject_HasAttr PyObject_HasAttrString PyObject_Hash PyObject_HashNotImplemented PyObject_IS_GC PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_LengthHint PyObject_Malloc PyObject_Not PyObject_Print PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetArenaAllocator PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PyObject_VectorcallDict PyObject_VectorcallMethod PyParser_ASTFromFile PyParser_ASTFromFileObject PyParser_ASTFromString PyParser_ASTFromStringObject PyParser_ClearError PyParser_ParseFile PyParser_ParseFileFlags PyParser_ParseFileFlagsEx PyParser_ParseFileObject PyParser_ParseString PyParser_ParseStringFlags PyParser_ParseStringFlagsFilename PyParser_ParseStringFlagsFilenameEx PyParser_ParseStringObject PyParser_SetError PyParser_SimpleParseFile PyParser_SimpleParseFileFlags PyParser_SimpleParseString PyParser_SimpleParseStringFlags PyParser_SimpleParseStringFlagsFilename PyPegen_ASTFromFileObject PyPegen_ASTFromFilename PyPegen_ASTFromString PyPegen_ASTFromStringObject PyPickleBuffer_FromObject PyPickleBuffer_GetBuffer PyPickleBuffer_Release PyPickleBuffer_Type DATA PyPreConfig_InitIsolatedConfig PyPreConfig_InitPythonConfig PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyReversed_Type DATA PyRun_AnyFile PyRun_AnyFileEx PyRun_AnyFileExFlags PyRun_AnyFileFlags PyRun_File PyRun_FileEx PyRun_FileExFlags PyRun_FileFlags PyRun_InteractiveLoop PyRun_InteractiveLoopFlags PyRun_InteractiveOne PyRun_InteractiveOneFlags PyRun_InteractiveOneObject PyRun_SimpleFile PyRun_SimpleFileEx PyRun_SimpleFileExFlags PyRun_SimpleString PyRun_SimpleStringFlags PyRun_String PyRun_StringFlags PySTEntry_Type DATA PyST_GetScope PySeqIter_New PySeqIter_Type DATA PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySetIter_Type DATA PySet_Add PySet_Clear PySet_Contains PySet_Discard PySet_New PySet_Pop PySet_Size PySet_Type DATA PySlice_AdjustIndices PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PySlice_Type DATA PySlice_Unpack PyState_AddModule PyState_FindModule PyState_RemoveModule PyStaticMethod_New PyStaticMethod_Type DATA PyStatus_Error PyStatus_Exception PyStatus_Exit PyStatus_IsError PyStatus_IsExit PyStatus_NoMemory PyStatus_Ok PyStdPrinter_Type DATA PyStructSequence_GetItem PyStructSequence_InitType PyStructSequence_InitType2 PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PySuper_Type DATA PySymtable_Build PySymtable_BuildObject PySymtable_Free PySymtable_Lookup PySys_AddAuditHook PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_AddXOption PySys_Audit PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_GetXOptions PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_Get PyThreadState_GetDict PyThreadState_GetFrame PyThreadState_GetID PyThreadState_GetInterpreter PyThreadState_New PyThreadState_Next PyThreadState_SetAsyncExc PyThreadState_Swap PyThread_GetInfo PyThread_ReInitTLS PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_allocate_lock PyThread_create_key PyThread_delete_key PyThread_delete_key_value PyThread_exit_thread PyThread_free_lock PyThread_get_key_value PyThread_get_stacksize PyThread_get_thread_ident PyThread_get_thread_native_id PyThread_init_thread PyThread_release_lock PyThread_set_key_value PyThread_set_stacksize PyThread_start_new_thread PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyToken_OneChar PyToken_ThreeChars PyToken_TwoChars PyTraceBack_Here PyTraceBack_Print PyTraceBack_Type DATA PyTraceMalloc_Track PyTraceMalloc_Untrack PyTupleIter_Type DATA PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyTuple_Type DATA PyType_ClearCache PyType_FromModuleAndSpec PyType_FromSpec PyType_FromSpecWithBases PyType_GenericAlloc PyType_GenericNew PyType_GetFlags PyType_GetModule PyType_GetModuleState PyType_GetSlot PyType_IsSubtype PyType_Modified PyType_Ready PyType_Type DATA PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_Create PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeIter_Type DATA PyUnicodeTranslateError_Create PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsMBCSString PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8 PyUnicode_AsUTF8AndSize PyUnicode_AsUTF8String PyUnicode_AsUnicode PyUnicode_AsUnicodeAndSize PyUnicode_AsUnicodeCopy PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_AsWideCharString PyUnicode_BuildEncodingMap PyUnicode_Compare PyUnicode_CompareWithASCIIString PyUnicode_Concat PyUnicode_Contains PyUnicode_CopyCharacters PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeCodePageStateful PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_Encode PyUnicode_EncodeASCII PyUnicode_EncodeCharmap PyUnicode_EncodeCodePage PyUnicode_EncodeDecimal PyUnicode_EncodeFSDefault PyUnicode_EncodeLatin1 PyUnicode_EncodeLocale PyUnicode_EncodeMBCS PyUnicode_EncodeRawUnicodeEscape PyUnicode_EncodeUTF16 PyUnicode_EncodeUTF32 PyUnicode_EncodeUTF7 PyUnicode_EncodeUTF8 PyUnicode_EncodeUnicodeEscape PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Fill PyUnicode_Find PyUnicode_FindChar PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromKindAndData PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromUnicode PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetLength PyUnicode_GetMax PyUnicode_GetSize PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_New PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_ReadChar PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Substring PyUnicode_Tailmatch PyUnicode_TransformDecimalToASCII PyUnicode_Translate PyUnicode_TranslateCharmap PyUnicode_Type DATA PyUnicode_WriteChar PyVectorcall_Call PyWeakref_GetObject PyWeakref_NewProxy PyWeakref_NewRef PyWideStringList_Append PyWideStringList_Insert PyWrapperDescr_Type DATA PyWrapper_New PyZip_Type DATA Py_AddPendingCall Py_AtExit Py_BuildValue Py_BytesMain Py_BytesWarningFlag DATA Py_CompileString Py_CompileStringExFlags Py_CompileStringFlags Py_CompileStringObject Py_DebugFlag DATA Py_DecRef Py_DecodeLocale Py_DontWriteBytecodeFlag DATA Py_EncodeLocale Py_EndInterpreter Py_EnterRecursiveCall Py_Exit Py_ExitStatusException Py_FatalError Py_FdIsInteractive Py_FileSystemDefaultEncodeErrors DATA Py_FileSystemDefaultEncoding DATA Py_Finalize Py_FinalizeEx Py_FrozenFlag DATA Py_GenericAlias Py_GenericAliasType DATA Py_GetArgcArgv Py_GetBuildInfo Py_GetCompiler Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_HasFileSystemDefaultEncoding DATA Py_HashRandomizationFlag DATA Py_IgnoreEnvironmentFlag DATA Py_IncRef Py_Initialize Py_InitializeEx Py_InitializeFromConfig Py_InspectFlag DATA Py_InteractiveFlag DATA Py_IsInitialized Py_IsolatedFlag DATA Py_LeaveRecursiveCall Py_LegacyWindowsFSEncodingFlag DATA Py_LegacyWindowsStdioFlag DATA Py_Main Py_MakePendingCalls Py_NewInterpreter Py_NoSiteFlag DATA Py_NoUserSiteDirectory DATA Py_OptimizeFlag DATA Py_PreInitialize Py_PreInitializeFromArgs Py_PreInitializeFromBytesArgs Py_QuietFlag DATA Py_ReprEnter Py_ReprLeave Py_RunMain Py_SetPath Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_SetStandardStreamEncoding Py_SymtableString Py_SymtableStringObject Py_UNICODE_strcat Py_UNICODE_strchr Py_UNICODE_strcmp Py_UNICODE_strcpy Py_UNICODE_strlen Py_UNICODE_strncmp Py_UNICODE_strncpy Py_UNICODE_strrchr Py_UTF8Mode DATA Py_UnbufferedStdioFlag DATA Py_UniversalNewlineFgets Py_VaBuildValue Py_VerboseFlag DATA Py_hexdigits DATA _PyAST_GetDocString _PyAST_Optimize _PyAccu_Accumulate _PyAccu_Destroy _PyAccu_Finish _PyAccu_FinishAsList _PyAccu_Init _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoKwnames _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT _PyArg_Parse_SizeT _PyArg_UnpackKeywords _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyArg_VaParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyArgv_AsWstrList _PyAsyncGenASend_Type DATA _PyAsyncGenAThrow_Type DATA _PyAsyncGenWrappedValue_Type DATA _PyByteArray_empty_string DATA _PyBytesIOBuffer_Type DATA _PyBytesWriter_Alloc _PyBytesWriter_Dealloc _PyBytesWriter_Finish _PyBytesWriter_Init _PyBytesWriter_Prepare _PyBytesWriter_Resize _PyBytesWriter_WriteBytes _PyBytes_DecodeEscape _PyBytes_FormatEx _PyBytes_FromHex _PyBytes_Join _PyBytes_Resize _PyCode_CheckLineNumber _PyCode_ConstantKey _PyCode_GetExtra _PyCode_SetExtra _PyCodecInfo_GetIncrementalDecoder _PyCodecInfo_GetIncrementalEncoder _PyCodec_DecodeText _PyCodec_EncodeText _PyCodec_Forget _PyCodec_Lookup _PyCodec_LookupTextEncoding _PyComplex_FormatAdvancedWriter _PyConfig_InitCompatConfig _PyContext_NewHamtForTests _PyCoroWrapper_Type DATA _PyCrossInterpreterData_Lookup _PyCrossInterpreterData_NewObject _PyCrossInterpreterData_RegisterClass _PyCrossInterpreterData_Release _PyDebugAllocatorStats _PyDictView_Intersect _PyDictView_New _PyDict_CheckConsistency _PyDict_Contains _PyDict_DebugMallocStats _PyDict_DelItemId _PyDict_DelItemIf _PyDict_DelItem_KnownHash _PyDict_GetItemId _PyDict_GetItemIdWithError _PyDict_GetItemStringWithError _PyDict_GetItem_KnownHash _PyDict_HasOnlyStringKeys _PyDict_MaybeUntrack _PyDict_MergeEx _PyDict_NewPresized _PyDict_Next _PyDict_Pop _PyDict_SetItemId _PyDict_SetItem_KnownHash _PyDict_SizeOf _PyErr_BadInternalCall _PyErr_ChainExceptions _PyErr_ChainStackItem _PyErr_CheckSignals _PyErr_CheckSignalsTstate _PyErr_Clear _PyErr_Display _PyErr_ExceptionMatches _PyErr_Fetch _PyErr_Format _PyErr_FormatFromCause _PyErr_FormatFromCauseTstate _PyErr_GetExcInfo _PyErr_GetTopmostException _PyErr_NoMemory _PyErr_NormalizeException _PyErr_Print _PyErr_Restore _PyErr_SetKeyError _PyErr_SetNone _PyErr_SetObject _PyErr_SetString _PyErr_TrySetFromCause _PyErr_WriteUnraisableMsg _PyEval_AddPendingCall _PyEval_CallTracing _PyEval_EvalCodeWithName _PyEval_EvalFrameDefault _PyEval_GetAsyncGenFinalizer _PyEval_GetAsyncGenFirstiter _PyEval_GetBuiltinId _PyEval_GetCoroutineOriginTrackingDepth _PyEval_GetSwitchInterval _PyEval_RequestCodeExtraIndex _PyEval_SetAsyncGenFinalizer _PyEval_SetAsyncGenFirstiter _PyEval_SetCoroutineOriginTrackingDepth _PyEval_SetProfile _PyEval_SetSwitchInterval _PyEval_SetTrace _PyEval_SignalAsyncExc _PyEval_SignalReceived _PyEval_SliceIndex _PyEval_SliceIndexNotNone _PyFloat_DebugMallocStats _PyFloat_FormatAdvancedWriter _PyFloat_Pack2 _PyFloat_Pack4 _PyFloat_Pack8 _PyFloat_Unpack2 _PyFloat_Unpack4 _PyFloat_Unpack8 _PyFrame_DebugMallocStats _PyFunction_Vectorcall _PyGC_CollectIfEnabled _PyGC_CollectNoFail _PyGC_InitState _PyGILState_GetInterpreterStateUnsafe _PyGILState_Reinit _PyGen_FetchStopIterationValue _PyGen_Finalize _PyGen_Send _PyGen_SetStopIterationValue _PyHamtItems_Type DATA _PyHamtKeys_Type DATA _PyHamtValues_Type DATA _PyHamt_ArrayNode_Type DATA _PyHamt_BitmapNode_Type DATA _PyHamt_CollisionNode_Type DATA _PyHamt_Type DATA _PyImport_AcquireLock _PyImport_FindExtensionObject _PyImport_FixupBuiltin _PyImport_FixupExtensionObject _PyImport_GetModuleId _PyImport_IsInitialized _PyImport_ReleaseLock _PyImport_SetModule _PyImport_SetModuleString _PyInterpreterID_LookUp _PyInterpreterID_New _PyInterpreterID_Type DATA _PyInterpreterState_DeleteExceptMain _PyInterpreterState_Enable _PyInterpreterState_GetConfig _PyInterpreterState_GetEvalFrameFunc _PyInterpreterState_GetIDObject _PyInterpreterState_GetMainModule _PyInterpreterState_IDDecref _PyInterpreterState_IDIncref _PyInterpreterState_IDInitref _PyInterpreterState_LookUpID _PyInterpreterState_RequireIDRef _PyInterpreterState_RequiresIDRef _PyInterpreterState_SetEvalFrameFunc _PyList_DebugMallocStats _PyList_Extend _PyLong_AsByteArray _PyLong_AsInt _PyLong_AsTime_t _PyLong_Copy _PyLong_DigitValue DATA _PyLong_DivmodNear _PyLong_Format _PyLong_FormatAdvancedWriter _PyLong_FormatBytesWriter _PyLong_FormatWriter _PyLong_Frexp _PyLong_FromByteArray _PyLong_FromBytes _PyLong_FromNbIndexOrNbInt _PyLong_FromNbInt _PyLong_FromTime_t _PyLong_GCD _PyLong_Lshift _PyLong_New _PyLong_NumBits _PyLong_One DATA _PyLong_Rshift _PyLong_Sign _PyLong_Size_t_Converter _PyLong_UnsignedInt_Converter _PyLong_UnsignedLongLong_Converter _PyLong_UnsignedLong_Converter _PyLong_UnsignedShort_Converter _PyLong_Zero DATA _PyManagedBuffer_Type DATA _PyMem_GetAllocatorName _PyMem_GetCurrentAllocatorName _PyMem_RawStrdup _PyMem_RawWcsdup _PyMem_SetDefaultAllocator _PyMem_SetupAllocators _PyMem_Strdup _PyMethodWrapper_Type DATA _PyModuleSpec_IsInitializing _PyModule_Clear _PyModule_ClearDict _PyModule_CreateInitialized _PyNamespace_New _PyNamespace_Type DATA _PyNode_SizeOf _PyNone_Type DATA _PyNotImplemented_Type DATA _PyOS_InterruptOccurred _PyOS_IsMainThread _PyOS_ReadlineTState DATA _PyOS_SigintEvent _PyOS_URandom _PyOS_URandomNonblock _PyObject_AssertFailed _PyObject_Call _PyObject_CallFunction_SizeT _PyObject_CallMethodId _PyObject_CallMethodIdObjArgs _PyObject_CallMethodId_SizeT _PyObject_CallMethod_SizeT _PyObject_Call_Prepend _PyObject_CheckConsistency _PyObject_CheckCrossInterpreterData _PyObject_DebugMallocStats _PyObject_DebugTypeStats _PyObject_Dump _PyObject_FastCallDictTstate _PyObject_FunctionStr _PyObject_GC_Calloc _PyObject_GC_Malloc _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_GenericGetAttrWithDict _PyObject_GenericSetAttrWithDict _PyObject_GetAttrId _PyObject_GetCrossInterpreterData _PyObject_GetDictPtr _PyObject_GetMethod _PyObject_HasAttrId _PyObject_HasLen _PyObject_IsAbstract _PyObject_IsFreed _PyObject_LookupAttr _PyObject_LookupAttrId _PyObject_LookupSpecial _PyObject_MakeTpCall _PyObject_New _PyObject_NewVar _PyObject_NextNotImplemented _PyObject_RealIsInstance _PyObject_RealIsSubclass _PyObject_SetAttrId _PyParser_Grammar DATA _PyParser_TokenNames DATA _PyPreConfig_InitCompatConfig _PyRuntime DATA _PyRuntimeState_Fini _PyRuntimeState_Init _PyRuntime_Finalize _PyRuntime_Initialize _PySequence_BytesToCharpArray _PySequence_IterSearch _PySet_Dummy DATA _PySet_NextEntry _PySet_Update _PySignal_AfterFork _PySlice_FromIndices _PySlice_GetLongIndices _PyStack_AsDict _PyState_AddModule _PySys_GetObjectId _PySys_GetSizeOf _PySys_SetObjectId _PyThreadState_DeleteCurrent _PyThreadState_DeleteExcept _PyThreadState_GetDict _PyThreadState_Init _PyThreadState_Prealloc _PyThreadState_Swap _PyThreadState_UncheckedGet _PyThread_CurrentFrames _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_noraise _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetPerfCounter _PyTime_GetPerfCounterWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_Init _PyTime_MulDiv _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyTraceMalloc_GetTraceback _PyTraceMalloc_NewReference _PyTraceback_Add _PyTrash_begin _PyTrash_deposit_object _PyTrash_destroy_chain _PyTrash_end _PyTrash_thread_deposit_object _PyTrash_thread_destroy_chain _PyTuple_DebugMallocStats _PyTuple_MaybeUntrack _PyTuple_Resize _PyType_CalculateMetaclass _PyType_CheckConsistency _PyType_GetDocFromInternalDoc _PyType_GetTextSignatureFromInternalDoc _PyType_Lookup _PyType_LookupId _PyType_Name _PyUnicodeTranslateError_Create _PyUnicodeWriter_Dealloc _PyUnicodeWriter_Finish _PyUnicodeWriter_Init _PyUnicodeWriter_PrepareInternal _PyUnicodeWriter_PrepareKindInternal _PyUnicodeWriter_WriteASCIIString _PyUnicodeWriter_WriteChar _PyUnicodeWriter_WriteLatin1String _PyUnicodeWriter_WriteStr _PyUnicodeWriter_WriteSubstring _PyUnicode_AsASCIIString _PyUnicode_AsLatin1String _PyUnicode_AsUTF8String _PyUnicode_AsUnicode _PyUnicode_CheckConsistency _PyUnicode_Copy _PyUnicode_DecodeRawUnicodeEscapeStateful _PyUnicode_DecodeUnicodeEscapeInternal _PyUnicode_DecodeUnicodeEscapeStateful _PyUnicode_EQ _PyUnicode_EncodeCharmap _PyUnicode_EncodeUTF16 _PyUnicode_EncodeUTF32 _PyUnicode_EncodeUTF7 _PyUnicode_EqualToASCIIId _PyUnicode_EqualToASCIIString _PyUnicode_FastCopyCharacters _PyUnicode_FastFill _PyUnicode_FindMaxChar _PyUnicode_FormatAdvancedWriter _PyUnicode_FormatLong _PyUnicode_FromASCII _PyUnicode_FromId _PyUnicode_InsertThousandsGrouping _PyUnicode_IsAlpha _PyUnicode_IsCaseIgnorable _PyUnicode_IsCased _PyUnicode_IsDecimalDigit _PyUnicode_IsDigit _PyUnicode_IsLinebreak _PyUnicode_IsLowercase _PyUnicode_IsNumeric _PyUnicode_IsPrintable _PyUnicode_IsTitlecase _PyUnicode_IsUppercase _PyUnicode_IsWhitespace _PyUnicode_IsXidContinue _PyUnicode_IsXidStart _PyUnicode_JoinArray _PyUnicode_Ready _PyUnicode_ScanIdentifier _PyUnicode_ToDecimalDigit _PyUnicode_ToDigit _PyUnicode_ToFoldedFull _PyUnicode_ToLowerFull _PyUnicode_ToLowercase _PyUnicode_ToNumeric _PyUnicode_ToTitleFull _PyUnicode_ToTitlecase _PyUnicode_ToUpperFull _PyUnicode_ToUppercase _PyUnicode_TransformDecimalAndSpaceToASCII _PyUnicode_XStrip _PyWarnings_Init _PyWeakref_CallableProxyType DATA _PyWeakref_ClearRef _PyWeakref_GetWeakrefCount _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _PyWideStringList_AsList _PyWideStringList_Clear _PyWideStringList_Copy _PyWideStringList_Extend _PyWindowsConsoleIO_Type DATA _Py_BreakPoint _Py_BuildValue_SizeT _Py_CheckFunctionResult _Py_CheckRecursionLimit DATA _Py_CheckRecursiveCall _Py_ClearArgcArgv _Py_ClearStandardStreamEncoding _Py_CoerceLegacyLocale _Py_Dealloc _Py_DecodeLocaleEx _Py_DecodeUTF8Ex _Py_DecodeUTF8_surrogateescape _Py_DisplaySourceLine _Py_EllipsisObject DATA _Py_EncodeLocaleEx _Py_EncodeLocaleRaw _Py_EncodeUTF8Ex _Py_FalseStruct DATA _Py_FatalErrorFormat _Py_FatalErrorFunc _Py_FatalError_TstateNULL _Py_FreeCharPArray _Py_GetAllocatedBlocks _Py_GetConfig _Py_GetConfigsAsDict _Py_GetEnv _Py_GetErrorHandler _Py_GetForceASCII _Py_GetLocaleconvNumeric _Py_HandleSystemExit _Py_HashBytes _Py_HashDouble _Py_HashPointer _Py_HashPointerRaw _Py_HashSecret DATA _Py_InitializeMain _Py_IsCoreInitialized _Py_IsFinalizing _Py_IsLocaleCoercionTarget _Py_LegacyLocaleDetected _Py_Mangle _Py_NewInterpreter _Py_NewReference _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_PackageContext DATA _Py_PreInitializeFromConfig _Py_PreInitializeFromPyArgv _Py_PyAtExit _Py_ResetForceASCII _Py_RestoreSignals _Py_SetLocaleFromEnv _Py_SetProgramFullPath _Py_SourceAsString _Py_SwappedOp DATA _Py_SymtableStringObjectFlags _Py_TrueStruct DATA _Py_UnhandledKeyboardInterrupt DATA _Py_VaBuildStack _Py_VaBuildStack_SizeT _Py_VaBuildValue_SizeT _Py_abspath _Py_add_one_to_index_C _Py_add_one_to_index_F _Py_ascii_whitespace DATA _Py_bit_length _Py_c_abs _Py_c_diff _Py_c_neg _Py_c_pow _Py_c_prod _Py_c_quot _Py_c_sum _Py_convert_optional_to_ssize_t _Py_ctype_table DATA _Py_ctype_tolower DATA _Py_ctype_toupper DATA _Py_device_encoding _Py_dg_dtoa _Py_dg_freedtoa _Py_dg_infinity _Py_dg_stdnan _Py_dg_strtod _Py_dup _Py_fopen _Py_fopen_obj _Py_fstat _Py_fstat_noraise _Py_get_env_flag _Py_get_inheritable _Py_get_xoption _Py_gitidentifier _Py_gitversion _Py_hashtable_clear _Py_hashtable_compare_direct _Py_hashtable_destroy _Py_hashtable_foreach _Py_hashtable_get _Py_hashtable_hash_ptr _Py_hashtable_new _Py_hashtable_new_full _Py_hashtable_set _Py_hashtable_size _Py_hashtable_steal _Py_open _Py_open_noraise _Py_parse_inf_or_nan _Py_path_config DATA _Py_read _Py_set_inheritable _Py_set_inheritable_async_safe _Py_stat _Py_str_to_int _Py_strhex _Py_strhex_bytes _Py_strhex_bytes_with_sep _Py_strhex_with_sep _Py_string_to_number_with_underscores _Py_tracemalloc_config DATA _Py_wfopen _Py_wgetcwd _Py_write _Py_write_noraise python3-dll-a/src/libpypy3.10-c.def0000644000175000017500000006212314661133735017621 0ustar jamespagejamespage; ; Definition file of libpypy3.10-c.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "libpypy3.10-c.dll" EXPORTS HPyInitGlobalContext__debug HPyInitGlobalContext__trace HPyInit__debug HPyInit__trace PyArg_ValidateKeywordArguments PyExpat_XML_DefaultCurrent PyExpat_XML_ErrorString PyExpat_XML_ExpatVersion PyExpat_XML_ExpatVersionInfo PyExpat_XML_ExternalEntityParserCreate PyExpat_XML_FreeContentModel PyExpat_XML_GetBase PyExpat_XML_GetBuffer PyExpat_XML_GetCurrentByteCount PyExpat_XML_GetCurrentByteIndex PyExpat_XML_GetCurrentColumnNumber PyExpat_XML_GetCurrentLineNumber PyExpat_XML_GetErrorCode PyExpat_XML_GetFeatureList PyExpat_XML_GetIdAttributeIndex PyExpat_XML_GetInputContext PyExpat_XML_GetParsingStatus PyExpat_XML_GetSpecifiedAttributeCount PyExpat_XML_MemFree PyExpat_XML_MemMalloc PyExpat_XML_MemRealloc PyExpat_XML_Parse PyExpat_XML_ParseBuffer PyExpat_XML_ParserCreate PyExpat_XML_ParserCreateNS PyExpat_XML_ParserCreate_MM PyExpat_XML_ParserFree PyExpat_XML_ParserReset PyExpat_XML_ResumeParser PyExpat_XML_SetAttlistDeclHandler PyExpat_XML_SetBase PyExpat_XML_SetBillionLaughsAttackProtectionActivationThreshold PyExpat_XML_SetBillionLaughsAttackProtectionMaximumAmplification PyExpat_XML_SetCdataSectionHandler PyExpat_XML_SetCharacterDataHandler PyExpat_XML_SetCommentHandler PyExpat_XML_SetDefaultHandler PyExpat_XML_SetDefaultHandlerExpand PyExpat_XML_SetDoctypeDeclHandler PyExpat_XML_SetElementDeclHandler PyExpat_XML_SetElementHandler PyExpat_XML_SetEncoding PyExpat_XML_SetEndCdataSectionHandler PyExpat_XML_SetEndDoctypeDeclHandler PyExpat_XML_SetEndElementHandler PyExpat_XML_SetEndNamespaceDeclHandler PyExpat_XML_SetEntityDeclHandler PyExpat_XML_SetExternalEntityRefHandler PyExpat_XML_SetExternalEntityRefHandlerArg PyExpat_XML_SetHashSalt PyExpat_XML_SetNamespaceDeclHandler PyExpat_XML_SetNotStandaloneHandler PyExpat_XML_SetNotationDeclHandler PyExpat_XML_SetParamEntityParsing PyExpat_XML_SetProcessingInstructionHandler PyExpat_XML_SetReparseDeferralEnabled PyExpat_XML_SetReturnNSTriplet PyExpat_XML_SetSkippedEntityHandler PyExpat_XML_SetStartCdataSectionHandler PyExpat_XML_SetStartDoctypeDeclHandler PyExpat_XML_SetStartElementHandler PyExpat_XML_SetStartNamespaceDeclHandler PyExpat_XML_SetUnknownEncodingHandler PyExpat_XML_SetUnparsedEntityDeclHandler PyExpat_XML_SetUserData PyExpat_XML_SetXmlDeclHandler PyExpat_XML_StopParser PyExpat_XML_UseForeignDTD PyExpat_XML_UseParserAsHandlerArg PyModule_AddType PyPyAnySet_Check PyPyAnySet_CheckExact PyPyArg_Parse PyPyArg_ParseTuple PyPyArg_ParseTupleAndKeywords PyPyArg_UnpackTuple PyPyArg_VaParse PyPyArg_VaParseTupleAndKeywords PyPyBaseObject_Type DATA PyPyBool_FromLong PyPyBool_Type DATA PyPyBuffer_FillInfo PyPyBuffer_FromContiguous PyPyBuffer_GetPointer PyPyBuffer_IsContiguous PyPyBuffer_Release PyPyBuffer_ToContiguous PyPyBufferable_Type DATA PyPyByteArray_AsString PyPyByteArray_Check PyPyByteArray_CheckExact PyPyByteArray_Concat PyPyByteArray_FromObject PyPyByteArray_FromStringAndSize PyPyByteArray_Resize PyPyByteArray_Size PyPyByteArray_Type DATA PyPyBytes_AS_STRING PyPyBytes_AsString PyPyBytes_AsStringAndSize PyPyBytes_Concat PyPyBytes_ConcatAndDel PyPyBytes_FromFormat PyPyBytes_FromFormatV PyPyBytes_FromObject PyPyBytes_FromString PyPyBytes_FromStringAndSize PyPyBytes_Size PyPyBytes_Type DATA PyPyCFunction_Call PyPyCFunction_Check PyPyCFunction_GetFunction PyPyCFunction_Type DATA PyPyCMethod_New PyPyCallIter_New PyPyCallable_Check PyPyCapsule_GetContext PyPyCapsule_GetDestructor PyPyCapsule_GetName PyPyCapsule_GetPointer PyPyCapsule_Import PyPyCapsule_IsValid PyPyCapsule_New PyPyCapsule_SetContext PyPyCapsule_SetDestructor PyPyCapsule_SetName PyPyCapsule_SetPointer PyPyCapsule_Type DATA PyPyCell_Type DATA PyPyClassMethodDescr_Type DATA PyPyClassMethod_New PyPyClassMethod_Type DATA PyPyCode_Addr2Line PyPyCode_Check PyPyCode_CheckExact PyPyCode_GetNumFree PyPyCode_New PyPyCode_NewEmpty PyPyCodec_Decode PyPyCodec_Decoder PyPyCodec_Encode PyPyCodec_Encoder PyPyCodec_IncrementalDecoder PyPyCodec_IncrementalEncoder PyPyComplex_AsCComplex PyPyComplex_Check PyPyComplex_CheckExact PyPyComplex_FromCComplex PyPyComplex_FromDoubles PyPyComplex_ImagAsDouble PyPyComplex_RealAsDouble PyPyComplex_Type DATA PyPyContextVar_Get PyPyContextVar_New PyPyContextVar_Set PyPyCoro_Check PyPyCoro_CheckExact PyPyDateTimeAPI DATA PyPyDateTime_Check PyPyDateTime_CheckExact PyPyDateTime_DATE_GET_HOUR PyPyDateTime_DATE_GET_MICROSECOND PyPyDateTime_DATE_GET_MINUTE PyPyDateTime_DATE_GET_SECOND PyPyDateTime_DATE_GET_TZINFO PyPyDateTime_DELTA_GET_DAYS PyPyDateTime_DELTA_GET_MICROSECONDS PyPyDateTime_DELTA_GET_SECONDS PyPyDateTime_FromTimestamp PyPyDateTime_GET_DAY PyPyDateTime_GET_FOLD PyPyDateTime_GET_MONTH PyPyDateTime_GET_YEAR PyPyDateTime_TIME_GET_FOLD PyPyDateTime_TIME_GET_HOUR PyPyDateTime_TIME_GET_MICROSECOND PyPyDateTime_TIME_GET_MINUTE PyPyDateTime_TIME_GET_SECOND PyPyDateTime_TIME_GET_TZINFO PyPyDate_Check PyPyDate_CheckExact PyPyDate_FromTimestamp PyPyDelta_Check PyPyDelta_CheckExact PyPyDescr_NewClassMethod PyPyDescr_NewGetSet PyPyDescr_NewMethod PyPyDictKeys_Type DATA PyPyDictProxy_Check PyPyDictProxy_CheckExact PyPyDictProxy_New PyPyDictProxy_Type DATA PyPyDictValues_Type DATA PyPyDict_Clear PyPyDict_Contains PyPyDict_Copy PyPyDict_DelItem PyPyDict_DelItemString PyPyDict_GetItem PyPyDict_GetItemString PyPyDict_GetItemWithError PyPyDict_Items PyPyDict_Keys PyPyDict_Merge PyPyDict_New PyPyDict_Next PyPyDict_SetDefault PyPyDict_SetItem PyPyDict_SetItemString PyPyDict_Size PyPyDict_Type DATA PyPyDict_Update PyPyDict_Values PyPyErr_BadArgument PyPyErr_BadInternalCall PyPyErr_CheckSignals PyPyErr_Clear PyPyErr_Display PyPyErr_ExceptionMatches PyPyErr_Fetch PyPyErr_Format PyPyErr_FormatV PyPyErr_GetExcInfo PyPyErr_GivenExceptionMatches PyPyErr_NewException PyPyErr_NewExceptionWithDoc PyPyErr_NoMemory PyPyErr_NormalizeException PyPyErr_Occurred PyPyErr_Print PyPyErr_PrintEx PyPyErr_Restore PyPyErr_SetExcFromWindowsErrWithFilenameObject PyPyErr_SetExcFromWindowsErrWithFilenameObjects PyPyErr_SetExcInfo PyPyErr_SetFromErrno PyPyErr_SetFromErrnoWithFilename PyPyErr_SetFromErrnoWithFilenameObject PyPyErr_SetFromErrnoWithFilenameObjects PyPyErr_SetFromWindowsErr PyPyErr_SetFromWindowsErrWithFilename PyPyErr_SetNone PyPyErr_SetObject PyPyErr_SetString PyPyErr_Warn PyPyErr_WarnEx PyPyErr_WarnExplicit PyPyErr_WarnFormat PyPyErr_WriteUnraisable PyPyEval_AcquireThread PyPyEval_CallFunction PyPyEval_CallMethod PyPyEval_CallObjectWithKeywords PyPyEval_EvalCode PyPyEval_GetBuiltins PyPyEval_GetFrame PyPyEval_GetGlobals PyPyEval_GetLocals PyPyEval_InitThreads PyPyEval_MergeCompilerFlags PyPyEval_ReleaseThread PyPyEval_RestoreThread PyPyEval_SaveThread PyPyEval_ThreadsInitialized PyPyExc_ArithmeticError DATA PyPyExc_AssertionError DATA PyPyExc_AttributeError DATA PyPyExc_BaseException DATA PyPyExc_BlockingIOError DATA PyPyExc_BrokenPipeError DATA PyPyExc_BufferError DATA PyPyExc_BytesWarning DATA PyPyExc_ChildProcessError DATA PyPyExc_ConnectionAbortedError DATA PyPyExc_ConnectionError DATA PyPyExc_ConnectionRefusedError DATA PyPyExc_ConnectionResetError DATA PyPyExc_DeprecationWarning DATA PyPyExc_EOFError DATA PyPyExc_EncodingWarning DATA PyPyExc_Exception DATA PyPyExc_FileExistsError DATA PyPyExc_FileNotFoundError DATA PyPyExc_FloatingPointError DATA PyPyExc_FutureWarning DATA PyPyExc_GeneratorExit DATA PyPyExc_ImportError DATA PyPyExc_ImportWarning DATA PyPyExc_IndentationError DATA PyPyExc_IndexError DATA PyPyExc_InterruptedError DATA PyPyExc_IsADirectoryError DATA PyPyExc_KeyError DATA PyPyExc_KeyboardInterrupt DATA PyPyExc_LookupError DATA PyPyExc_MemoryError DATA PyPyExc_ModuleNotFoundError DATA PyPyExc_NameError DATA PyPyExc_NotADirectoryError DATA PyPyExc_NotImplementedError DATA PyPyExc_OSError DATA PyPyExc_OverflowError DATA PyPyExc_PendingDeprecationWarning DATA PyPyExc_PermissionError DATA PyPyExc_ProcessLookupError DATA PyPyExc_RecursionError DATA PyPyExc_ReferenceError DATA PyPyExc_ResourceWarning DATA PyPyExc_RuntimeError DATA PyPyExc_RuntimeWarning DATA PyPyExc_StopAsyncIteration DATA PyPyExc_StopIteration DATA PyPyExc_SyntaxError DATA PyPyExc_SyntaxWarning DATA PyPyExc_SystemError DATA PyPyExc_SystemExit DATA PyPyExc_TabError DATA PyPyExc_TimeoutError DATA PyPyExc_TypeError DATA PyPyExc_UnboundLocalError DATA PyPyExc_UnicodeDecodeError DATA PyPyExc_UnicodeEncodeError DATA PyPyExc_UnicodeError DATA PyPyExc_UnicodeTranslateError DATA PyPyExc_UnicodeWarning DATA PyPyExc_UserWarning DATA PyPyExc_ValueError DATA PyPyExc_Warning DATA PyPyExc_ZeroDivisionError DATA PyPyExceptionInstance_Class PyPyException_GetCause PyPyException_GetContext PyPyException_GetTraceback PyPyException_SetCause PyPyException_SetContext PyPyException_SetTraceback PyPyFile_FromFd PyPyFile_FromString PyPyFile_GetLine PyPyFile_WriteObject PyPyFile_WriteString PyPyFloat_AS_DOUBLE PyPyFloat_AsDouble PyPyFloat_Check PyPyFloat_CheckExact PyPyFloat_FromDouble PyPyFloat_FromString PyPyFloat_Type DATA PyPyFrame_New PyPyFrozenSet_Check PyPyFrozenSet_CheckExact PyPyFrozenSet_New PyPyFrozenSet_Type DATA PyPyFunction_Check PyPyFunction_CheckExact PyPyFunction_GetCode PyPyFunction_Type DATA PyPyGC_Disable PyPyGC_Enable PyPyGC_IsEnabled PyPyGILState_Check PyPyGILState_Ensure PyPyGILState_Release PyPyGen_Check PyPyGen_CheckExact PyPyGetSetDescr_Type DATA PyPyImport_AddModule PyPyImport_ExecCodeModule PyPyImport_ExecCodeModuleEx PyPyImport_GetModule PyPyImport_GetModuleDict PyPyImport_Import PyPyImport_ImportModule PyPyImport_ImportModuleLevelObject PyPyImport_ImportModuleNoBlock PyPyImport_ReloadModule PyPyIndex_Check PyPyInstanceMethod_Check PyPyInstanceMethod_Function PyPyInstanceMethod_GET_FUNCTION PyPyInstanceMethod_New PyPyInstanceMethod_Type DATA PyPyInterpreterState_GetID PyPyInterpreterState_Head PyPyInterpreterState_Next PyPyIter_Check PyPyIter_Next PyPyIter_Send PyPyList_Append PyPyList_AsTuple PyPyList_GET_ITEM PyPyList_GET_SIZE PyPyList_GetItem PyPyList_GetSlice PyPyList_Insert PyPyList_New PyPyList_Reverse PyPyList_SET_ITEM PyPyList_SetItem PyPyList_SetSlice PyPyList_Size PyPyList_Sort PyPyList_Type DATA PyPyLong_AsDouble PyPyLong_AsLong PyPyLong_AsLongAndOverflow PyPyLong_AsLongLong PyPyLong_AsLongLongAndOverflow PyPyLong_AsSize_t PyPyLong_AsSsize_t PyPyLong_AsUnsignedLong PyPyLong_AsUnsignedLongLong PyPyLong_AsUnsignedLongLongMask PyPyLong_AsUnsignedLongMask PyPyLong_AsVoidPtr PyPyLong_FromDouble PyPyLong_FromLong PyPyLong_FromLongLong PyPyLong_FromSize_t PyPyLong_FromSsize_t PyPyLong_FromString PyPyLong_FromUnicode PyPyLong_FromUnicodeObject PyPyLong_FromUnsignedLong PyPyLong_FromUnsignedLongLong PyPyLong_FromVoidPtr PyPyLong_Type DATA PyPyMapping_Check PyPyMapping_GetItemString PyPyMapping_HasKey PyPyMapping_HasKeyString PyPyMapping_Items PyPyMapping_Keys PyPyMapping_Length PyPyMapping_SetItemString PyPyMapping_Size PyPyMapping_Values PyPyMarshal_ReadObjectFromString PyPyMarshal_WriteObjectToString PyPyMem_Calloc PyPyMem_Free PyPyMem_Malloc PyPyMem_RawCalloc PyPyMem_RawFree PyPyMem_RawMalloc PyPyMem_RawRealloc PyPyMem_Realloc PyPyMemberDescr_Type DATA PyPyMember_GetOne PyPyMember_SetOne PyPyMemoryView_Check PyPyMemoryView_CheckExact PyPyMemoryView_FromBuffer PyPyMemoryView_FromMemory PyPyMemoryView_FromObject PyPyMemoryView_GetContiguous PyPyMemoryView_Type DATA PyPyMethodDescr_Check PyPyMethodDescr_CheckExact PyPyMethodDescr_Type DATA PyPyMethod_Check PyPyMethod_CheckExact PyPyMethod_Function PyPyMethod_New PyPyMethod_Self PyPyMethod_Type DATA PyPyModuleDef_Init PyPyModule_AddFunctions PyPyModule_AddIntConstant PyPyModule_AddObject PyPyModule_AddObjectRef PyPyModule_AddStringConstant PyPyModule_Check PyPyModule_CheckExact PyPyModule_Create2 PyPyModule_ExecDef PyPyModule_GetDef PyPyModule_GetDict PyPyModule_GetFilenameObject PyPyModule_GetName PyPyModule_GetNameObject PyPyModule_GetState PyPyModule_New PyPyModule_NewObject PyPyModule_Type DATA PyPyNumber_Absolute PyPyNumber_Add PyPyNumber_And PyPyNumber_AsSsize_t PyPyNumber_Check PyPyNumber_Divide PyPyNumber_Divmod PyPyNumber_Float PyPyNumber_FloorDivide PyPyNumber_InPlaceAdd PyPyNumber_InPlaceAnd PyPyNumber_InPlaceDivide PyPyNumber_InPlaceFloorDivide PyPyNumber_InPlaceLshift PyPyNumber_InPlaceMatrixMultiply PyPyNumber_InPlaceMultiply PyPyNumber_InPlaceOr PyPyNumber_InPlacePower PyPyNumber_InPlaceRemainder PyPyNumber_InPlaceRshift PyPyNumber_InPlaceSubtract PyPyNumber_InPlaceTrueDivide PyPyNumber_InPlaceXor PyPyNumber_Index PyPyNumber_Invert PyPyNumber_Long PyPyNumber_Lshift PyPyNumber_MatrixMultiply PyPyNumber_Multiply PyPyNumber_Negative PyPyNumber_Or PyPyNumber_Positive PyPyNumber_Power PyPyNumber_Remainder PyPyNumber_Rshift PyPyNumber_Subtract PyPyNumber_ToBase PyPyNumber_TrueDivide PyPyNumber_Xor PyPyOS_AfterFork PyPyOS_FSPath PyPyOS_InputHook DATA PyPyOS_InterruptOccurred PyPyOS_double_to_string PyPyOS_getsig PyPyOS_setsig PyPyOS_snprintf PyPyOS_string_to_double PyPyOS_vsnprintf PyPyObject_ASCII PyPyObject_AsCharBuffer PyPyObject_AsFileDescriptor PyPyObject_AsReadBuffer PyPyObject_AsWriteBuffer PyPyObject_Bytes PyPyObject_Call PyPyObject_CallFinalizerFromDealloc PyPyObject_CallFunction PyPyObject_CallFunctionObjArgs PyPyObject_CallMethod PyPyObject_CallMethodNoArgs PyPyObject_CallMethodObjArgs PyPyObject_CallMethodOneArg PyPyObject_CallNoArgs PyPyObject_CallObject PyPyObject_CallOneArg PyPyObject_Calloc PyPyObject_CheckReadBuffer PyPyObject_ClearWeakRefs PyPyObject_Del PyPyObject_DelAttr PyPyObject_DelAttrString PyPyObject_DelItem PyPyObject_DelItemString PyPyObject_Dir PyPyObject_Format PyPyObject_Free PyPyObject_GC_Del PyPyObject_GC_IsFinalized PyPyObject_GC_IsTracked PyPyObject_GenericGetAttr PyPyObject_GenericGetDict PyPyObject_GenericSetAttr PyPyObject_GenericSetDict PyPyObject_GetAttr PyPyObject_GetAttrString PyPyObject_GetBuffer PyPyObject_GetItem PyPyObject_GetIter PyPyObject_HasAttr PyPyObject_HasAttrString PyPyObject_Hash PyPyObject_HashNotImplemented PyPyObject_Init PyPyObject_InitVar PyPyObject_IsInstance PyPyObject_IsSubclass PyPyObject_IsTrue PyPyObject_LengthHint PyPyObject_Malloc PyPyObject_Not PyPyObject_Print PyPyObject_Realloc PyPyObject_Repr PyPyObject_RichCompare PyPyObject_RichCompareBool PyPyObject_SelfIter PyPyObject_SetAttr PyPyObject_SetAttrString PyPyObject_SetItem PyPyObject_Size PyPyObject_Str PyPyObject_Type PyPyObject_Unicode PyPyObject_Vectorcall PyPyObject_VectorcallDict PyPyObject_VectorcallMethod PyPyProperty_Type DATA PyPyRange_Type DATA PyPyReversed_Type DATA PyPyRun_File PyPyRun_SimpleString PyPyRun_String PyPyRun_StringFlags PyPySeqIter_New PyPySequence_Check PyPySequence_Concat PyPySequence_Contains PyPySequence_DelItem PyPySequence_DelSlice PyPySequence_Fast PyPySequence_Fast_GET_ITEM PyPySequence_Fast_GET_SIZE PyPySequence_Fast_ITEMS PyPySequence_GetItem PyPySequence_GetSlice PyPySequence_ITEM PyPySequence_InPlaceConcat PyPySequence_InPlaceRepeat PyPySequence_Index PyPySequence_Length PyPySequence_List PyPySequence_Repeat PyPySequence_SetItem PyPySequence_SetSlice PyPySequence_Size PyPySequence_Tuple PyPySet_Add PyPySet_Check PyPySet_CheckExact PyPySet_Clear PyPySet_Contains PyPySet_Discard PyPySet_GET_SIZE PyPySet_New PyPySet_Pop PyPySet_Size PyPySet_Type DATA PyPySlice_AdjustIndices PyPySlice_GetIndices PyPySlice_GetIndicesEx PyPySlice_New PyPySlice_Type DATA PyPySlice_Unpack PyPyState_AddModule PyPyState_FindModule PyPyState_RemoveModule PyPyStaticMethod_New PyPyStaticMethod_Type DATA PyPyStructSequence_GetItem PyPyStructSequence_InitType PyPyStructSequence_InitType2 PyPyStructSequence_New PyPyStructSequence_NewType PyPyStructSequence_SetItem PyPyStructSequence_UnnamedField DATA PyPySys_GetObject PyPySys_SetObject PyPySys_WriteStderr PyPySys_WriteStdout PyPyTZInfo_Check PyPyTZInfo_CheckExact PyPyThreadState_Clear PyPyThreadState_Delete PyPyThreadState_DeleteCurrent PyPyThreadState_Get PyPyThreadState_GetDict PyPyThreadState_New PyPyThreadState_SetAsyncExc PyPyThreadState_Swap PyPyThread_ReInitTLS PyPyThread_acquire_lock PyPyThread_allocate_lock PyPyThread_create_key PyPyThread_delete_key PyPyThread_delete_key_value PyPyThread_exit_thread PyPyThread_free_lock PyPyThread_get_key_value PyPyThread_get_thread_ident PyPyThread_init_thread PyPyThread_release_lock PyPyThread_set_key_value PyPyThread_start_new_thread PyPyTime_Check PyPyTime_CheckExact PyPyTraceBack_Check PyPyTraceBack_Here PyPyTraceBack_Print PyPyTraceBack_Type DATA PyPyTraceMalloc_Track PyPyTraceMalloc_Untrack PyPyTuple_GetItem PyPyTuple_GetSlice PyPyTuple_New PyPyTuple_Pack PyPyTuple_SetItem PyPyTuple_Size PyPyTuple_Type DATA PyPyType_FromModuleAndSpec PyPyType_FromSpec PyPyType_FromSpecWithBases PyPyType_GenericAlloc PyPyType_GenericNew PyPyType_GetModule PyPyType_GetModuleState PyPyType_GetSlot PyPyType_IsSubtype PyPyType_Modified PyPyType_Ready PyPyType_Type DATA PyPyUnicode_Append PyPyUnicode_AppendAndDel PyPyUnicode_AsASCIIString PyPyUnicode_AsEncodedObject PyPyUnicode_AsEncodedString PyPyUnicode_AsLatin1String PyPyUnicode_AsMBCSString PyPyUnicode_AsUCS4 PyPyUnicode_AsUCS4Copy PyPyUnicode_AsUTF16String PyPyUnicode_AsUTF32String PyPyUnicode_AsUTF8 PyPyUnicode_AsUTF8AndSize PyPyUnicode_AsUTF8String PyPyUnicode_AsUnicode PyPyUnicode_AsUnicodeAndSize PyPyUnicode_AsUnicodeEscapeString PyPyUnicode_AsWideChar PyPyUnicode_AsWideCharString PyPyUnicode_Check PyPyUnicode_CheckExact PyPyUnicode_Compare PyPyUnicode_CompareWithASCIIString PyPyUnicode_Concat PyPyUnicode_Contains PyPyUnicode_Count PyPyUnicode_Decode PyPyUnicode_DecodeASCII PyPyUnicode_DecodeFSDefault PyPyUnicode_DecodeFSDefaultAndSize PyPyUnicode_DecodeLatin1 PyPyUnicode_DecodeLocale PyPyUnicode_DecodeLocaleAndSize PyPyUnicode_DecodeMBCS PyPyUnicode_DecodeUTF16 PyPyUnicode_DecodeUTF32 PyPyUnicode_DecodeUTF8 PyPyUnicode_EncodeASCII PyPyUnicode_EncodeCodePage PyPyUnicode_EncodeDecimal PyPyUnicode_EncodeFSDefault PyPyUnicode_EncodeLatin1 PyPyUnicode_EncodeLocale PyPyUnicode_EncodeMBCS PyPyUnicode_EncodeUTF8 PyPyUnicode_FSConverter PyPyUnicode_FSDecoder PyPyUnicode_Find PyPyUnicode_FindChar PyPyUnicode_Format PyPyUnicode_FromEncodedObject PyPyUnicode_FromFormat PyPyUnicode_FromFormatV PyPyUnicode_FromKindAndData PyPyUnicode_FromObject PyPyUnicode_FromOrdinal PyPyUnicode_FromString PyPyUnicode_FromStringAndSize PyPyUnicode_FromUnicode PyPyUnicode_FromWideChar PyPyUnicode_GetDefaultEncoding PyPyUnicode_GetLength PyPyUnicode_GetMax PyPyUnicode_GetSize PyPyUnicode_InternFromString PyPyUnicode_InternInPlace PyPyUnicode_Join PyPyUnicode_New PyPyUnicode_ReadChar PyPyUnicode_Replace PyPyUnicode_Resize PyPyUnicode_Split PyPyUnicode_Splitlines PyPyUnicode_Substring PyPyUnicode_Tailmatch PyPyUnicode_TransformDecimalToASCII PyPyUnicode_Type DATA PyPyUnicode_WriteChar PyPyVectorcall_Call PyPyWeakref_Check PyPyWeakref_CheckProxy PyPyWeakref_CheckRef PyPyWeakref_CheckRefExact PyPyWeakref_GET_OBJECT PyPyWeakref_GetObject PyPyWeakref_LockObject PyPyWeakref_NewProxy PyPyWeakref_NewRef PyPyWrapperDescr_Type DATA PyPy_AddPendingCall PyPy_AtExit PyPy_BuildValue PyPy_BytesWarningFlag DATA PyPy_CompileStringFlags PyPy_DebugFlag DATA PyPy_DecRef PyPy_DontWriteBytecodeFlag DATA PyPy_EnterRecursiveCall PyPy_FatalError PyPy_FindMethod PyPy_FrozenFlag DATA PyPy_GenericAlias PyPy_GetProgramName PyPy_GetRecursionLimit PyPy_GetVersion PyPy_HashRandomizationFlag DATA PyPy_IgnoreEnvironmentFlag DATA PyPy_IncRef PyPy_InspectFlag DATA PyPy_InteractiveFlag DATA PyPy_Is PyPy_IsInitialized PyPy_IsolatedFlag DATA PyPy_LeaveRecursiveCall PyPy_LegacyWindowsStdioFlag DATA PyPy_MakePendingCalls PyPy_NoSiteFlag DATA PyPy_NoUserSiteDirectory DATA PyPy_OptimizeFlag DATA PyPy_QuietFlag DATA PyPy_ReprEnter PyPy_ReprLeave PyPy_SetRecursionLimit PyPy_UNICODE_COPY PyPy_UNICODE_ISALNUM PyPy_UNICODE_ISALPHA PyPy_UNICODE_ISDECIMAL PyPy_UNICODE_ISDIGIT PyPy_UNICODE_ISLINEBREAK PyPy_UNICODE_ISLOWER PyPy_UNICODE_ISNUMERIC PyPy_UNICODE_ISSPACE PyPy_UNICODE_ISTITLE PyPy_UNICODE_ISUPPER PyPy_UNICODE_TODECIMAL PyPy_UNICODE_TODIGIT PyPy_UNICODE_TOLOWER PyPy_UNICODE_TONUMERIC PyPy_UNICODE_TOTITLE PyPy_UNICODE_TOUPPER PyPy_UnbufferedStdioFlag DATA PyPy_VaBuildValue PyPy_VerboseFlag DATA PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyType_GetFlags Py_FileSystemDefaultEncoding DATA _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoKwnames _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_UnpackKeywords _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyExc_ArithmeticError DATA _PyExc_AssertionError DATA _PyExc_AttributeError DATA _PyExc_BaseException DATA _PyExc_BlockingIOError DATA _PyExc_BrokenPipeError DATA _PyExc_BufferError DATA _PyExc_BytesWarning DATA _PyExc_ChildProcessError DATA _PyExc_ConnectionAbortedError DATA _PyExc_ConnectionError DATA _PyExc_ConnectionRefusedError DATA _PyExc_ConnectionResetError DATA _PyExc_DeprecationWarning DATA _PyExc_EOFError DATA _PyExc_EncodingWarning DATA _PyExc_Exception DATA _PyExc_FileExistsError DATA _PyExc_FileNotFoundError DATA _PyExc_FloatingPointError DATA _PyExc_FutureWarning DATA _PyExc_GeneratorExit DATA _PyExc_ImportError DATA _PyExc_ImportWarning DATA _PyExc_IndentationError DATA _PyExc_IndexError DATA _PyExc_InterruptedError DATA _PyExc_IsADirectoryError DATA _PyExc_KeyError DATA _PyExc_KeyboardInterrupt DATA _PyExc_LookupError DATA _PyExc_MemoryError DATA _PyExc_ModuleNotFoundError DATA _PyExc_NameError DATA _PyExc_NotADirectoryError DATA _PyExc_NotImplementedError DATA _PyExc_OSError DATA _PyExc_OverflowError DATA _PyExc_PendingDeprecationWarning DATA _PyExc_PermissionError DATA _PyExc_ProcessLookupError DATA _PyExc_RecursionError DATA _PyExc_ReferenceError DATA _PyExc_ResourceWarning DATA _PyExc_RuntimeError DATA _PyExc_RuntimeWarning DATA _PyExc_StopAsyncIteration DATA _PyExc_StopIteration DATA _PyExc_SyntaxError DATA _PyExc_SyntaxWarning DATA _PyExc_SystemError DATA _PyExc_SystemExit DATA _PyExc_TabError DATA _PyExc_TimeoutError DATA _PyExc_TypeError DATA _PyExc_UnboundLocalError DATA _PyExc_UnicodeDecodeError DATA _PyExc_UnicodeEncodeError DATA _PyExc_UnicodeError DATA _PyExc_UnicodeTranslateError DATA _PyExc_UnicodeWarning DATA _PyExc_UserWarning DATA _PyExc_ValueError DATA _PyExc_Warning DATA _PyExc_ZeroDivisionError DATA _PyLong_AsTime_t _PyLong_FromTime_t _PyPyArg_ParseTupleAndKeywords_SizeT _PyPyArg_ParseTuple_SizeT _PyPyArg_Parse_SizeT _PyPyArg_VaParseTupleAndKeywords_SizeT _PyPyArg_VaParse_SizeT _PyPyBytes_Eq _PyPyBytes_Join _PyPyBytes_Resize _PyPyComplex_AsCComplex _PyPyComplex_FromCComplex _PyPyDateTime_FromDateAndTime _PyPyDateTime_FromDateAndTimeAndFold _PyPyDateTime_FromTimestamp _PyPyDateTime_Import _PyPyDate_FromDate _PyPyDate_FromTimestamp _PyPyDelta_FromDelta _PyPyDict_GetItemStringWithError _PyPyDict_HasOnlyStringKeys _PyPyErr_FormatFromCause _PyPyErr_WriteUnraisableMsg _PyPyEval_GetAsyncGenFinalizer _PyPyEval_GetAsyncGenFirstiter _PyPyEval_SliceIndex _PyPyFloat_Unpack4 _PyPyFloat_Unpack8 _PyPyImport_AcquireLock _PyPyImport_ReleaseLock _PyPyList_Extend _PyPyLong_AsByteArrayO _PyPyLong_AsInt _PyPyLong_FromByteArray _PyPyLong_NumBits _PyPyLong_Sign _PyPyNamespace_New _PyPyNone_Type DATA _PyPyNotImplemented_Type DATA _PyPyObject_CallFunction_SizeT _PyPyObject_CallMethod_SizeT _PyPyObject_FastCall _PyPyObject_GC_Malloc _PyPyObject_GC_New _PyPyObject_GC_NewVar _PyPyObject_GetDictPtr _PyPyObject_New _PyPyObject_NewVar _PyPyPyGC_AddMemoryPressure _PyPyPy_Free _PyPyPy_Malloc _PyPySet_Next _PyPySet_NextEntry _PyPyThreadState_UncheckedGet _PyPyTimeZone_FromTimeZone _PyPyTime_FromTime _PyPyTime_FromTimeAndFold _PyPyTuple_Resize _PyPyType_GetModuleByDef _PyPyType_Lookup _PyPyType_Name _PyPyUnicode_EQ _PyPyUnicode_EqualToASCIIString _PyPyUnicode_Ready _PyPy_BuildValue_SizeT _PyPy_Dealloc _PyPy_EllipsisObject DATA _PyPy_FalseStruct DATA _PyPy_HashDouble _PyPy_HashPointer _PyPy_IsFinalizing _PyPy_NoneStruct DATA _PyPy_NotImplementedStruct DATA _PyPy_PackageContext DATA _PyPy_RestoreSignals _PyPy_TrueStruct DATA _PyPy_VaBuildValue_SizeT _PyPy_get_PyOS_InputHook _PyPy_get_capsule_type _PyPy_object_dealloc _PyPy_setfilesystemdefaultencoding _PyPy_strhex _PyPy_strhex_bytes _PyPy_subtype_dealloc _PyPy_tuple_dealloc _PyPy_tuple_new _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_noraise _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_Init _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _Py_NewReference _Py_VaBuildStack _Py_VaBuildStack_SizeT _pypy_init_executable _pypy_init_free _pypy_init_home get_required_hpy_major_version__debug get_required_hpy_major_version__trace get_required_hpy_minor_version__debug get_required_hpy_minor_version__trace os_readlink_impl os_symlink_impl os_unlink_impl pypy_HPyInit__debug pypy_HPyInit__trace pypy_carefully_make_gil pypy_debug_file DATA pypy_execute_source pypy_execute_source_ptr pypy_hpy_debug_close_handle pypy_hpy_debug_ctx_init pypy_hpy_debug_get_ctx pypy_hpy_debug_open_handle pypy_hpy_debug_set_ctx pypy_hpy_debug_unwrap_handle pypy_hpy_trace_ctx_init pypy_hpy_trace_get_ctx pypy_hpy_trace_get_func_name pypy_hpy_trace_get_nfunc pypy_init_embedded_cffi_module pypy_init_threads pypy_main_startup pypy_setup_home pypy_thread_attach rpython_startup_code python3-dll-a/src/python312.def0000644000175000017500000010762014661133735017160 0ustar jamespagejamespage; ; Definition file of python312.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "python312.dll" EXPORTS PyAIter_Check PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyAsyncGen_New PyAsyncGen_Type DATA PyBaseObject_Type DATA PyBool_FromLong PyBool_Type DATA PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_FromContiguous PyBuffer_GetPointer PyBuffer_IsContiguous PyBuffer_Release PyBuffer_SizeFromFormat PyBuffer_ToContiguous PyByteArrayIter_Type DATA PyByteArray_AsString PyByteArray_Concat PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Resize PyByteArray_Size PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyBytes_Type DATA PyCFunction_Call PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_New PyCFunction_NewEx PyCFunction_Type DATA PyCMethod_New PyCMethod_Type DATA PyCallIter_New PyCallIter_Type DATA PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCapsule_Type DATA PyCell_Get PyCell_New PyCell_Set PyCell_Type DATA PyClassMethodDescr_Type DATA PyClassMethod_New PyClassMethod_Type DATA PyCode_AddWatcher PyCode_Addr2Line PyCode_Addr2Location PyCode_ClearWatcher PyCode_GetCellvars PyCode_GetCode PyCode_GetFreevars PyCode_GetVarnames PyCode_NewEmpty PyCode_Optimize PyCode_Type DATA PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_NameReplaceErrors PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_Unregister PyCodec_XMLCharRefReplaceErrors PyCompile_OpcodeStackEffect PyCompile_OpcodeStackEffectWithJump PyComplex_AsCComplex PyComplex_FromCComplex PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyComplex_Type DATA PyConfig_Clear PyConfig_InitIsolatedConfig PyConfig_InitPythonConfig PyConfig_Read PyConfig_SetArgv PyConfig_SetBytesArgv PyConfig_SetBytesString PyConfig_SetString PyConfig_SetWideStringList PyContextToken_Type DATA PyContextVar_Get PyContextVar_New PyContextVar_Reset PyContextVar_Set PyContextVar_Type DATA PyContext_Copy PyContext_CopyCurrent PyContext_Enter PyContext_Exit PyContext_New PyContext_Type DATA PyCoro_New PyCoro_Type DATA PyDescr_IsData PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDescr_NewWrapper PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_New PyDictProxy_Type DATA PyDictRevIterItem_Type DATA PyDictRevIterKey_Type DATA PyDictRevIterValue_Type DATA PyDictValues_Type DATA PyDict_AddWatcher PyDict_Clear PyDict_ClearWatcher PyDict_Contains PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_GetItem PyDict_GetItemString PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_SetDefault PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Type DATA PyDict_Unwatch PyDict_Update PyDict_Values PyDict_Watch PyEllipsis_Type DATA PyEnum_Type DATA PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_DisplayException PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_FormatV PyErr_GetExcInfo PyErr_GetHandledException PyErr_GetRaisedException PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_ProgramTextObject PyErr_RangedSyntaxLocationObject PyErr_ResourceWarning PyErr_Restore PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetExcInfo PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetFromErrnoWithFilenameObjects PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyErr_SetHandledException PyErr_SetImportError PyErr_SetImportErrorSubclass PyErr_SetInterrupt PyErr_SetInterruptEx PyErr_SetNone PyErr_SetObject PyErr_SetRaisedException PyErr_SetString PyErr_SyntaxLocation PyErr_SyntaxLocationEx PyErr_SyntaxLocationObject PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnExplicitFormat PyErr_WarnExplicitObject PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_MergeCompilerFlags PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_SetProfile PyEval_SetProfileAllThreads PyEval_SetTrace PyEval_SetTraceAllThreads PyEval_ThreadsInitialized PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BaseExceptionGroup DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EncodingWarning DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_ModuleNotFoundError DATA PyExc_NameError DATA PyExc_NotADirectoryError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_RecursionError DATA PyExc_ReferenceError DATA PyExc_ResourceWarning DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopAsyncIteration DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TimeoutError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_WindowsError DATA PyExc_ZeroDivisionError DATA PyExceptionClass_Name PyException_GetArgs PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetArgs PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_NewStdPrinter PyFile_OpenCode PyFile_OpenCodeObject PyFile_SetOpenCodeHook PyFile_WriteObject PyFile_WriteString PyFilter_Type DATA PyFloat_AsDouble PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFloat_Pack2 PyFloat_Pack4 PyFloat_Pack8 PyFloat_Type DATA PyFloat_Unpack2 PyFloat_Unpack4 PyFloat_Unpack8 PyFrame_FastToLocals PyFrame_FastToLocalsWithError PyFrame_GetBack PyFrame_GetBuiltins PyFrame_GetCode PyFrame_GetGenerator PyFrame_GetGlobals PyFrame_GetLasti PyFrame_GetLineNumber PyFrame_GetLocals PyFrame_GetVar PyFrame_GetVarString PyFrame_LocalsToFast PyFrame_New PyFrame_Type DATA PyFrozenSet_New PyFrozenSet_Type DATA PyFunction_AddWatcher PyFunction_ClearWatcher PyFunction_GetAnnotations PyFunction_GetClosure PyFunction_GetCode PyFunction_GetDefaults PyFunction_GetGlobals PyFunction_GetKwDefaults PyFunction_GetModule PyFunction_New PyFunction_NewWithQualName PyFunction_SetAnnotations PyFunction_SetClosure PyFunction_SetDefaults PyFunction_SetKwDefaults PyFunction_SetVectorcall PyFunction_Type DATA PyGC_Collect PyGC_Disable PyGC_Enable PyGC_IsEnabled PyGILState_Check PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyGen_GetCode PyGen_New PyGen_NewWithQualName PyGen_Type DATA PyGetSetDescr_Type DATA PyHash_GetFuncDef PyImport_AddModule PyImport_AddModuleObject PyImport_AppendInittab PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleObject PyImport_ExecCodeModuleWithPathnames PyImport_ExtendInittab PyImport_FrozenModules DATA PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModule PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportFrozenModuleObject PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleLevelObject PyImport_ImportModuleNoBlock PyImport_Inittab DATA PyImport_ReloadModule PyIndex_Check PyInstanceMethod_Function PyInstanceMethod_New PyInstanceMethod_Type DATA PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_Get PyInterpreterState_GetDict PyInterpreterState_GetID PyInterpreterState_Head PyInterpreterState_Main PyInterpreterState_New PyInterpreterState_Next PyInterpreterState_ThreadHead PyIter_Check PyIter_Next PyIter_Send PyListIter_Type DATA PyListRevIter_Type DATA PyList_Append PyList_AsTuple PyList_GetItem PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyList_Type DATA PyLongRangeIter_Type DATA PyLong_AsDouble PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnicodeObject PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromVoidPtr PyLong_GetInfo PyLong_Type DATA PyMap_Type DATA PyMapping_Check PyMapping_GetItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMarshal_ReadLastObjectFromFile PyMarshal_ReadLongFromFile PyMarshal_ReadObjectFromFile PyMarshal_ReadObjectFromString PyMarshal_ReadShortFromFile PyMarshal_WriteLongToFile PyMarshal_WriteObjectToFile PyMarshal_WriteObjectToString PyMem_Calloc PyMem_Free PyMem_GetAllocator PyMem_Malloc PyMem_RawCalloc PyMem_RawFree PyMem_RawMalloc PyMem_RawRealloc PyMem_Realloc PyMem_SetAllocator PyMem_SetupDebugHooks PyMemberDescr_Type DATA PyMember_GetOne PyMember_SetOne PyMemoryView_FromBuffer PyMemoryView_FromMemory PyMemoryView_FromObject PyMemoryView_GetContiguous PyMemoryView_Type DATA PyMethodDescr_Type DATA PyMethod_Function PyMethod_New PyMethod_Self PyMethod_Type DATA PyModuleDef_Init PyModuleDef_Type DATA PyModule_AddFunctions PyModule_AddIntConstant PyModule_AddObject PyModule_AddObjectRef PyModule_AddStringConstant PyModule_AddType PyModule_Create2 PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetNameObject PyModule_GetState PyModule_New PyModule_NewObject PyModule_SetDocString PyModule_Type DATA PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMatrixMultiply PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_MatrixMultiply PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyODictItems_Type DATA PyODictIter_Type DATA PyODictKeys_Type DATA PyODictValues_Type DATA PyODict_DelItem PyODict_New PyODict_SetItem PyODict_Type DATA PyOS_AfterFork PyOS_FSPath PyOS_InputHook DATA PyOS_InterruptOccurred PyOS_Readline PyOS_ReadlineFunctionPointer DATA PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsCharBuffer PyObject_AsFileDescriptor PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_Bytes PyObject_Call PyObject_CallFinalizer PyObject_CallFinalizerFromDealloc PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallNoArgs PyObject_CallObject PyObject_CallOneArg PyObject_Calloc PyObject_CheckBuffer PyObject_CheckReadBuffer PyObject_ClearWeakRefs PyObject_CopyData PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_IsFinalized PyObject_GC_IsTracked PyObject_GC_Track PyObject_GC_UnTrack PyObject_GET_WEAKREFS_LISTPTR PyObject_GenericGetAttr PyObject_GenericGetDict PyObject_GenericSetAttr PyObject_GenericSetDict PyObject_GetAIter PyObject_GetArenaAllocator PyObject_GetAttr PyObject_GetAttrString PyObject_GetBuffer PyObject_GetItem PyObject_GetItemData PyObject_GetIter PyObject_GetTypeData PyObject_HasAttr PyObject_HasAttrString PyObject_Hash PyObject_HashNotImplemented PyObject_IS_GC PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_LengthHint PyObject_Malloc PyObject_Not PyObject_Print PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetArenaAllocator PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PyObject_Vectorcall PyObject_VectorcallDict PyObject_VectorcallMethod PyPickleBuffer_FromObject PyPickleBuffer_GetBuffer PyPickleBuffer_Release PyPickleBuffer_Type DATA PyPreConfig_InitIsolatedConfig PyPreConfig_InitPythonConfig PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyReversed_Type DATA PyRun_AnyFile PyRun_AnyFileEx PyRun_AnyFileExFlags PyRun_AnyFileFlags PyRun_File PyRun_FileEx PyRun_FileExFlags PyRun_FileFlags PyRun_InteractiveLoop PyRun_InteractiveLoopFlags PyRun_InteractiveOne PyRun_InteractiveOneFlags PyRun_InteractiveOneObject PyRun_SimpleFile PyRun_SimpleFileEx PyRun_SimpleFileExFlags PyRun_SimpleString PyRun_SimpleStringFlags PyRun_String PyRun_StringFlags PySeqIter_New PySeqIter_Type DATA PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySetIter_Type DATA PySet_Add PySet_Clear PySet_Contains PySet_Discard PySet_New PySet_Pop PySet_Size PySet_Type DATA PySlice_AdjustIndices PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PySlice_Type DATA PySlice_Unpack PyState_AddModule PyState_FindModule PyState_RemoveModule PyStaticMethod_New PyStaticMethod_Type DATA PyStatus_Error PyStatus_Exception PyStatus_Exit PyStatus_IsError PyStatus_IsExit PyStatus_NoMemory PyStatus_Ok PyStdPrinter_Type DATA PyStructSequence_GetItem PyStructSequence_InitType PyStructSequence_InitType2 PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PyStructSequence_UnnamedField DATA PySuper_Type DATA PySymtable_Lookup PySys_AddAuditHook PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_AddXOption PySys_Audit PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_GetXOptions PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_EnterTracing PyThreadState_Get PyThreadState_GetDict PyThreadState_GetFrame PyThreadState_GetID PyThreadState_GetInterpreter PyThreadState_LeaveTracing PyThreadState_New PyThreadState_Next PyThreadState_SetAsyncExc PyThreadState_Swap PyThread_GetInfo PyThread_ReInitTLS PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_allocate_lock PyThread_create_key PyThread_delete_key PyThread_delete_key_value PyThread_exit_thread PyThread_free_lock PyThread_get_key_value PyThread_get_stacksize PyThread_get_thread_ident PyThread_get_thread_native_id PyThread_init_thread PyThread_release_lock PyThread_set_key_value PyThread_set_stacksize PyThread_start_new_thread PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyTraceBack_Here PyTraceBack_Print PyTraceBack_Type DATA PyTraceMalloc_Track PyTraceMalloc_Untrack PyTupleIter_Type DATA PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyTuple_Type DATA PyType_AddWatcher PyType_ClearCache PyType_ClearWatcher PyType_FromMetaclass PyType_FromModuleAndSpec PyType_FromSpec PyType_FromSpecWithBases PyType_GenericAlloc PyType_GenericNew PyType_GetDict PyType_GetFlags PyType_GetModule PyType_GetModuleByDef PyType_GetModuleState PyType_GetName PyType_GetQualName PyType_GetSlot PyType_GetTypeDataSize PyType_IsSubtype PyType_Modified PyType_Ready PyType_SUPPORTS_WEAKREFS PyType_Type DATA PyType_Unwatch PyType_Watch PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeIter_Type DATA PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsMBCSString PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8 PyUnicode_AsUTF8AndSize PyUnicode_AsUTF8String PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_AsWideCharString PyUnicode_BuildEncodingMap PyUnicode_Compare PyUnicode_CompareWithASCIIString PyUnicode_Concat PyUnicode_Contains PyUnicode_CopyCharacters PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeCodePageStateful PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_EncodeCodePage PyUnicode_EncodeFSDefault PyUnicode_EncodeLocale PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Fill PyUnicode_Find PyUnicode_FindChar PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromKindAndData PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetLength PyUnicode_GetSize PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_New PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_ReadChar PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Substring PyUnicode_Tailmatch PyUnicode_Translate PyUnicode_Type DATA PyUnicode_WriteChar PyUnstable_Code_GetExtra PyUnstable_Code_New PyUnstable_Code_NewWithPosOnlyArgs PyUnstable_Code_SetExtra PyUnstable_Eval_RequestCodeExtraIndex PyUnstable_Exc_PrepReraiseStar PyUnstable_GC_VisitObjects PyUnstable_InterpreterFrame_GetCode PyUnstable_InterpreterFrame_GetLasti PyUnstable_InterpreterFrame_GetLine PyUnstable_Long_CompactValue PyUnstable_Long_IsCompact PyUnstable_Object_GC_NewWithExtraData PyUnstable_PerfMapState_Fini PyUnstable_PerfMapState_Init PyUnstable_Type_AssignVersionTag PyUnstable_WritePerfMapEntry PyVectorcall_Call PyVectorcall_Function PyVectorcall_NARGS PyWeakref_GetObject PyWeakref_NewProxy PyWeakref_NewRef PyWideStringList_Append PyWideStringList_Insert PyWrapperDescr_Type DATA PyWrapper_New PyZip_Type DATA Py_AddPendingCall Py_AtExit Py_BuildValue Py_BytesMain Py_BytesWarningFlag DATA Py_CompileString Py_CompileStringExFlags Py_CompileStringFlags Py_CompileStringObject Py_DebugFlag DATA Py_DecRef Py_DecodeLocale Py_DontWriteBytecodeFlag DATA Py_EncodeLocale Py_EndInterpreter Py_EnterRecursiveCall Py_Exit Py_ExitStatusException Py_FatalError Py_FdIsInteractive Py_FileSystemDefaultEncodeErrors DATA Py_FileSystemDefaultEncoding DATA Py_Finalize Py_FinalizeEx Py_FrozenFlag DATA Py_GETENV Py_GenericAlias Py_GenericAliasType DATA Py_GetArgcArgv Py_GetBuildInfo Py_GetCompiler Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_HasFileSystemDefaultEncoding DATA Py_HashRandomizationFlag DATA Py_IgnoreEnvironmentFlag DATA Py_IncRef Py_Initialize Py_InitializeEx Py_InitializeFromConfig Py_InspectFlag DATA Py_InteractiveFlag DATA Py_Is Py_IsFalse Py_IsInitialized Py_IsNone Py_IsTrue Py_IsolatedFlag DATA Py_LeaveRecursiveCall Py_LegacyWindowsFSEncodingFlag DATA Py_LegacyWindowsStdioFlag DATA Py_Main Py_MakePendingCalls Py_NewInterpreter Py_NewInterpreterFromConfig Py_NewRef Py_NoSiteFlag DATA Py_NoUserSiteDirectory DATA Py_OptimizeFlag DATA Py_PreInitialize Py_PreInitializeFromArgs Py_PreInitializeFromBytesArgs Py_QuietFlag DATA Py_ReprEnter Py_ReprLeave Py_RunMain Py_SetPath Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_SetStandardStreamEncoding Py_UTF8Mode DATA Py_UnbufferedStdioFlag DATA Py_UniversalNewlineFgets Py_VaBuildValue Py_VerboseFlag DATA Py_Version DATA Py_XNewRef Py_hexdigits DATA _PyAST_Compile _PyArena_AddPyObject _PyArena_Free _PyArena_Malloc _PyArena_New _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoKwnames _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT _PyArg_Parse_SizeT _PyArg_UnpackKeywords _PyArg_UnpackKeywordsWithVararg _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyArg_VaParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyArgv_AsWstrList _PyAsyncGenASend_Type DATA _PyAsyncGenAThrow_Type DATA _PyAsyncGenWrappedValue_Type DATA _PyBufferWrapper_Type DATA _PyByteArray_empty_string DATA _PyBytesWriter_Alloc _PyBytesWriter_Dealloc _PyBytesWriter_Finish _PyBytesWriter_Init _PyBytesWriter_Prepare _PyBytesWriter_Resize _PyBytesWriter_WriteBytes _PyBytes_DecodeEscape _PyBytes_Find _PyBytes_FormatEx _PyBytes_FromHex _PyBytes_Join _PyBytes_Repeat _PyBytes_Resize _PyBytes_ReverseFind _PyCode_CheckLineNumber _PyCode_ConstantKey _PyCode_New _PyCode_Validate _PyCodecInfo_GetIncrementalDecoder _PyCodecInfo_GetIncrementalEncoder _PyCodec_DecodeText _PyCodec_EncodeText _PyCodec_Lookup _PyCodec_LookupTextEncoding _PyCompile_Assemble _PyCompile_CodeGen _PyCompile_OptimizeCfg _PyConfig_AsDict _PyConfig_FromDict _PyConfig_InitCompatConfig _PyContext_NewHamtForTests _PyCoroWrapper_Type DATA _PyCrossInterpreterData_Clear _PyCrossInterpreterData_Init _PyCrossInterpreterData_InitWithSize _PyCrossInterpreterData_Lookup _PyCrossInterpreterData_NewObject _PyCrossInterpreterData_RegisterClass _PyCrossInterpreterData_Release _PyCrossInterpreterData_ReleaseAndRawFree _PyCrossInterpreterData_UnregisterClass _PyDeadline_Get _PyDeadline_Init _PyDebugAllocatorStats _PyDictView_Intersect _PyDictView_New _PyDict_CheckConsistency _PyDict_ContainsId _PyDict_Contains_KnownHash _PyDict_DebugMallocStats _PyDict_DelItemId _PyDict_DelItemIf _PyDict_DelItem_KnownHash _PyDict_GetItemIdWithError _PyDict_GetItemStringWithError _PyDict_GetItemWithError _PyDict_GetItem_KnownHash _PyDict_HasOnlyStringKeys _PyDict_MaybeUntrack _PyDict_MergeEx _PyDict_NewPresized _PyDict_Next _PyDict_Pop _PyDict_SetItemId _PyDict_SetItem_KnownHash _PyDict_SizeOf _PyErr_BadInternalCall _PyErr_ChainExceptions _PyErr_ChainExceptions1 _PyErr_ChainStackItem _PyErr_CheckSignals _PyErr_CheckSignalsTstate _PyErr_Clear _PyErr_Display _PyErr_DisplayException _PyErr_ExceptionMatches _PyErr_Fetch _PyErr_Format _PyErr_FormatFromCause _PyErr_FormatFromCauseTstate _PyErr_GetExcInfo _PyErr_GetHandledException _PyErr_GetTopmostException _PyErr_NoMemory _PyErr_NormalizeException _PyErr_Print _PyErr_ProgramDecodedTextObject _PyErr_Restore _PyErr_SetFromPyStatus _PyErr_SetHandledException _PyErr_SetKeyError _PyErr_SetNone _PyErr_SetObject _PyErr_SetString _PyErr_StackItemToExcInfoTuple _PyErr_WriteUnraisableMsg _PyEval_AddPendingCall _PyEval_EvalFrameDefault _PyEval_GetBuiltin _PyEval_GetBuiltinId _PyEval_GetSwitchInterval _PyEval_MakePendingCalls _PyEval_SetProfile _PyEval_SetSwitchInterval _PyEval_SetTrace _PyEval_SignalAsyncExc _PyEval_SignalReceived _PyEval_SliceIndex _PyEval_SliceIndexNotNone _PyExc_CreateExceptionGroup _PyExc_PrepReraiseStar _PyException_AddNote _PyFloat_DebugMallocStats _PyFloat_FormatAdvancedWriter _PyFrame_IsEntryFrame _PyFunction_Vectorcall _PyGILState_GetInterpreterStateUnsafe _PyGen_FetchStopIterationValue _PyGen_Finalize _PyGen_SetStopIterationValue _PyImport_AcquireLock _PyImport_CheckSubinterpIncompatibleExtensionAllowed _PyImport_ClearExtension _PyImport_FixupBuiltin _PyImport_FixupExtensionObject _PyImport_FrozenBootstrap DATA _PyImport_FrozenStdlib DATA _PyImport_FrozenTest DATA _PyImport_GetModuleAttr _PyImport_GetModuleAttrString _PyImport_GetModuleId _PyImport_IsInitialized _PyImport_ReleaseLock _PyImport_SetModule _PyImport_SetModuleString _PyInterpreterID_LookUp _PyInterpreterID_New _PyInterpreterID_Type DATA _PyInterpreterState_Enable _PyInterpreterState_GetConfig _PyInterpreterState_GetConfigCopy _PyInterpreterState_GetEvalFrameFunc _PyInterpreterState_GetIDObject _PyInterpreterState_GetMainModule _PyInterpreterState_HasFeature _PyInterpreterState_IDDecref _PyInterpreterState_IDIncref _PyInterpreterState_IDInitref _PyInterpreterState_IsRunningMain _PyInterpreterState_LookUpID _PyInterpreterState_RequireIDRef _PyInterpreterState_RequiresIDRef _PyInterpreterState_SetConfig _PyInterpreterState_SetEvalFrameFunc _PyInterpreterState_SetNotRunningMain _PyInterpreterState_SetRunningMain _PyList_DebugMallocStats _PyList_Extend _PyLong_AsByteArray _PyLong_AsInt _PyLong_AsTime_t _PyLong_Copy _PyLong_DigitValue DATA _PyLong_DivmodNear _PyLong_FileDescriptor_Converter _PyLong_Format _PyLong_FormatAdvancedWriter _PyLong_FormatBytesWriter _PyLong_FormatWriter _PyLong_Frexp _PyLong_FromByteArray _PyLong_FromBytes _PyLong_FromDigits _PyLong_FromTime_t _PyLong_GCD _PyLong_Lshift _PyLong_New _PyLong_NumBits _PyLong_Rshift _PyLong_Sign _PyLong_Size_t_Converter _PyLong_UnsignedInt_Converter _PyLong_UnsignedLongLong_Converter _PyLong_UnsignedLong_Converter _PyLong_UnsignedShort_Converter _PyManagedBuffer_Type DATA _PyMem_GetAllocatorName _PyMem_GetCurrentAllocatorName _PyMem_RawStrdup _PyMem_RawWcsdup _PyMem_SetDefaultAllocator _PyMem_SetupAllocators _PyMem_Strdup _PyMethodWrapper_Type DATA _PyModuleSpec_IsInitializing _PyModule_Add _PyModule_Clear _PyModule_ClearDict _PyModule_CreateInitialized _PyNamespace_New _PyNamespace_Type DATA _PyNone_Type DATA _PyNotImplemented_Type DATA _PyNumber_Index _PyOS_InterruptOccurred _PyOS_IsMainThread _PyOS_ReadlineTState DATA _PyOS_SigintEvent _PyOS_URandom _PyOS_URandomNonblock _PyObject_AssertFailed _PyObject_Call _PyObject_CallFunction_SizeT _PyObject_CallMethod _PyObject_CallMethodId _PyObject_CallMethodIdObjArgs _PyObject_CallMethodId_SizeT _PyObject_CallMethod_SizeT _PyObject_Call_Prepend _PyObject_CheckConsistency _PyObject_CheckCrossInterpreterData _PyObject_ClearManagedDict _PyObject_DebugMallocStats _PyObject_DebugTypeStats _PyObject_Dump _PyObject_FastCall _PyObject_FastCallDictTstate _PyObject_FunctionStr _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_GenericGetAttrWithDict _PyObject_GenericSetAttrWithDict _PyObject_GetAttrId _PyObject_GetCrossInterpreterData _PyObject_GetDictPtr _PyObject_GetMethod _PyObject_GetState _PyObject_HasLen _PyObject_IsAbstract _PyObject_IsFreed _PyObject_LookupAttr _PyObject_LookupAttrId _PyObject_LookupSpecial _PyObject_LookupSpecialId _PyObject_MakeTpCall _PyObject_New _PyObject_NewVar _PyObject_NextNotImplemented _PyObject_RealIsInstance _PyObject_RealIsSubclass _PyObject_SetAttrId _PyObject_VisitManagedDict _PyParser_TokenNames DATA _PyPathConfig_ClearGlobal _PyPreConfig_InitCompatConfig _PyRun_AnyFileObject _PyRun_InteractiveLoopObject _PyRun_SimpleFileObject _PyRuntime DATA _PyRuntimeState_Fini _PyRuntimeState_Init _PyRuntime_Finalize _PyRuntime_Initialize _PySequence_BytesToCharpArray _PySequence_IterSearch _PySet_Dummy DATA _PySet_NextEntry _PySet_Update _PySlice_FromIndices _PySlice_GetLongIndices _PyStack_AsDict _PyState_AddModule _PyStructSequence_NewType _PySys_GetAttr _PySys_GetSizeOf _PyThreadState_Bind _PyThreadState_DeleteCurrent _PyThreadState_DeleteExcept _PyThreadState_GetCurrent _PyThreadState_GetDict _PyThreadState_Init _PyThreadState_New _PyThreadState_Prealloc _PyThreadState_Swap _PyThreadState_UncheckedGet _PyThread_CurrentExceptions _PyThread_CurrentFrames _PyTime_Add _PyTime_As100Nanoseconds _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanoseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_clamp _PyTime_FromMicrosecondsClamp _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetPerfCounter _PyTime_GetPerfCounterWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_MulDiv _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyToken_OneChar _PyToken_ThreeChars _PyToken_TwoChars _PyTraceBack_FromFrame _PyTraceBack_Print_Indented _PyTraceMalloc_ClearTraces _PyTraceMalloc_GetMemory _PyTraceMalloc_GetObjectTraceback _PyTraceMalloc_GetTraceback _PyTraceMalloc_GetTracebackLimit _PyTraceMalloc_GetTracedMemory _PyTraceMalloc_GetTraces _PyTraceMalloc_Init _PyTraceMalloc_IsTracing _PyTraceMalloc_ResetPeak _PyTraceMalloc_Start _PyTraceMalloc_Stop _PyTraceback_Add _PyTrash_begin _PyTrash_cond _PyTrash_end _PyTuple_DebugMallocStats _PyTuple_MaybeUntrack _PyTuple_Resize _PyType_CalculateMetaclass _PyType_CheckConsistency _PyType_GetDict _PyType_GetDocFromInternalDoc _PyType_GetTextSignatureFromInternalDoc _PyType_Lookup _PyType_LookupId _PyType_Name _PyUnicodeTranslateError_Create _PyUnicodeWriter_Dealloc _PyUnicodeWriter_Finish _PyUnicodeWriter_Init _PyUnicodeWriter_PrepareInternal _PyUnicodeWriter_PrepareKindInternal _PyUnicodeWriter_WriteASCIIString _PyUnicodeWriter_WriteChar _PyUnicodeWriter_WriteLatin1String _PyUnicodeWriter_WriteStr _PyUnicodeWriter_WriteSubstring _PyUnicode_AsASCIIString _PyUnicode_AsLatin1String _PyUnicode_AsUTF8String _PyUnicode_CheckConsistency _PyUnicode_Copy _PyUnicode_DecodeRawUnicodeEscapeStateful _PyUnicode_DecodeUnicodeEscapeInternal _PyUnicode_DecodeUnicodeEscapeStateful _PyUnicode_EQ _PyUnicode_EncodeCharmap _PyUnicode_EncodeUTF16 _PyUnicode_EncodeUTF32 _PyUnicode_EncodeUTF7 _PyUnicode_Equal _PyUnicode_EqualToASCIIId _PyUnicode_EqualToASCIIString _PyUnicode_FastCopyCharacters _PyUnicode_FastFill _PyUnicode_FindMaxChar _PyUnicode_FormatAdvancedWriter _PyUnicode_FormatLong _PyUnicode_FromASCII _PyUnicode_FromId _PyUnicode_InsertThousandsGrouping _PyUnicode_IsAlpha _PyUnicode_IsCaseIgnorable _PyUnicode_IsCased _PyUnicode_IsDecimalDigit _PyUnicode_IsDigit _PyUnicode_IsLinebreak _PyUnicode_IsLowercase _PyUnicode_IsNumeric _PyUnicode_IsPrintable _PyUnicode_IsTitlecase _PyUnicode_IsUppercase _PyUnicode_IsWhitespace _PyUnicode_IsXidContinue _PyUnicode_IsXidStart _PyUnicode_JoinArray _PyUnicode_ScanIdentifier _PyUnicode_ToDecimalDigit _PyUnicode_ToDigit _PyUnicode_ToFoldedFull _PyUnicode_ToLowerFull _PyUnicode_ToLowercase _PyUnicode_ToNumeric _PyUnicode_ToTitleFull _PyUnicode_ToTitlecase _PyUnicode_ToUpperFull _PyUnicode_ToUppercase _PyUnicode_TransformDecimalAndSpaceToASCII _PyUnicode_WideCharString_Converter _PyUnicode_WideCharString_Opt_Converter _PyUnicode_XStrip _PyWarnings_Init _PyWeakref_CallableProxyType DATA _PyWeakref_ClearRef _PyWeakref_GetWeakrefCount _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _PyWideStringList_AsList _PyWideStringList_Clear _PyWideStringList_Copy _PyWideStringList_Extend _Py_AtExit _Py_BreakPoint _Py_BuildValue_SizeT _Py_CheckFunctionResult _Py_CheckRecursiveCall _Py_ClearArgcArgv _Py_ClearStandardStreamEncoding _Py_CoerceLegacyLocale _Py_Dealloc _Py_DecRef _Py_DecodeLocaleEx _Py_DecodeUTF8Ex _Py_DecodeUTF8_surrogateescape _Py_DisplaySourceLine _Py_DumpASCII _Py_DumpDecimal _Py_DumpExtensionModules _Py_DumpHexadecimal _Py_DumpTraceback _Py_DumpTracebackThreads _Py_EllipsisObject DATA _Py_EncodeLocaleEx _Py_EncodeLocaleRaw _Py_EncodeUTF8Ex _Py_FalseStruct DATA _Py_FatalErrorFormat _Py_FatalErrorFunc _Py_FatalRefcountErrorFunc _Py_FdIsInteractive _Py_FreeCharPArray _Py_GetConfig _Py_GetConfigsAsDict _Py_GetEnv _Py_GetErrorHandler _Py_GetForceASCII _Py_GetLocaleEncoding _Py_GetLocaleEncodingObject _Py_GetLocaleconvNumeric _Py_Get_Getpath_CodeObject _Py_HandleSystemExit _Py_HasFileSystemDefaultEncodeErrors DATA _Py_HashBytes _Py_HashDouble _Py_HashPointer _Py_HashPointerRaw _Py_HashSecret DATA _Py_IncRef _Py_InitializeMain _Py_IsCoreInitialized _Py_IsFinalizing _Py_IsInterpreterFinalizing _Py_IsLocaleCoercionTarget _Py_LegacyLocaleDetected _Py_NewReference _Py_NewReferenceNoTotal _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_PreInitializeFromConfig _Py_PreInitializeFromPyArgv _Py_ResetForceASCII _Py_RestoreSignals _Py_SetLocaleFromEnv _Py_SetProgramFullPath _Py_SourceAsString _Py_SwappedOp DATA _Py_TrueStruct DATA _Py_UTF8_Edit_Cost _Py_UniversalNewlineFgetsWithSize _Py_VaBuildStack _Py_VaBuildStack_SizeT _Py_VaBuildValue_SizeT _Py_WriteIndent _Py_WriteIndentedMargin _Py_add_one_to_index_C _Py_add_one_to_index_F _Py_ascii_whitespace DATA _Py_c_abs _Py_c_diff _Py_c_neg _Py_c_pow _Py_c_prod _Py_c_quot _Py_c_sum _Py_closerange _Py_convert_optional_to_ssize_t _Py_ctype_table DATA _Py_ctype_tolower DATA _Py_ctype_toupper DATA _Py_device_encoding _Py_dg_dtoa _Py_dg_freedtoa _Py_dg_strtod _Py_dup _Py_fopen_obj _Py_fstat _Py_fstat_noraise _Py_get_blocking _Py_get_env_flag _Py_get_inheritable _Py_get_osfhandle _Py_get_osfhandle_noraise _Py_get_xoption _Py_gitidentifier _Py_gitversion _Py_hashtable_clear _Py_hashtable_compare_direct _Py_hashtable_destroy _Py_hashtable_foreach _Py_hashtable_get _Py_hashtable_hash_ptr _Py_hashtable_len _Py_hashtable_new _Py_hashtable_new_full _Py_hashtable_set _Py_hashtable_size _Py_hashtable_steal _Py_normpath _Py_open _Py_open_noraise _Py_open_osfhandle _Py_open_osfhandle_noraise _Py_parse_inf_or_nan _Py_read _Py_set_blocking _Py_set_inheritable _Py_set_inheritable_async_safe _Py_stat _Py_str_to_int _Py_strhex _Py_strhex_bytes _Py_strhex_bytes_with_sep _Py_strhex_with_sep _Py_string_to_number_with_underscores _Py_wfopen _Py_wgetcwd _Py_write _Py_write_noraise python3-dll-a/src/lib.rs0000644000175000017500000005047314661133735016050 0ustar jamespagejamespage//! Standalone `python3(y).dll` import library generator //! ==================================================== //! //! Generates import libraries for the Python DLL //! (either `python3.dll` or `python3y.dll`) //! for MinGW-w64 and MSVC (cross-)compile targets. //! //! This crate **does not require** Python 3 distribution files //! to be present on the (cross-)compile host system. //! //! This crate uses the binutils `dlltool` program to generate //! the Python DLL import libraries for MinGW-w64 targets. //! Setting `PYO3_MINGW_DLLTOOL` environment variable overrides //! the default `dlltool` command name for the target. //! //! **Note:** MSVC cross-compile targets require either LLVM binutils //! or Zig to be available on the host system. //! More specifically, `python3-dll-a` requires `llvm-dlltool` executable //! to be present in `PATH` when targeting `*-pc-windows-msvc` from Linux. //! //! Alternatively, `ZIG_COMMAND` environment variable may be set to e.g. `"zig"` //! or `"python -m ziglang"`, then `zig dlltool` will be used in place //! of `llvm-dlltool` (or MinGW binutils). //! //! PyO3 integration //! ---------------- //! //! Since version **0.16.5**, the `pyo3` crate implements support //! for both the Stable ABI and version-specific Python DLL import //! library generation via its new `generate-import-lib` feature. //! //! In this configuration, `python3-dll-a` becomes a `pyo3` crate dependency //! and is automatically invoked by its build script in both native //! and cross compilation scenarios. //! //! ### Example `Cargo.toml` usage for an `abi3` PyO3 extension module //! //! ```toml //! [dependencies] //! pyo3 = { version = "0.16.5", features = ["extension-module", "abi3-py37", "generate-import-lib"] } //! ``` //! //! ### Example `Cargo.toml` usage for a standard PyO3 extension module //! //! ```toml //! [dependencies] //! pyo3 = { version = "0.16.5", features = ["extension-module", "generate-import-lib"] } //! ``` //! //! Standalone build script usage //! ----------------------------- //! //! If an older `pyo3` crate version is used, or a different Python bindings //! library is required, `python3-dll-a` can be used directly //! from the crate build script. //! //! The examples below assume using an older version of PyO3. //! //! ### Example `build.rs` script for an `abi3` PyO3 extension //! //! The following cargo build script can be used to cross-compile Stable ABI //! PyO3 extension modules for Windows (64/32-bit x86 or 64-bit ARM) //! using either MinGW-w64 or MSVC target environment ABI: //! //! ```no_run //! fn main() { //! if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" { //! let cross_lib_dir = std::env::var_os("PYO3_CROSS_LIB_DIR") //! .expect("PYO3_CROSS_LIB_DIR is not set when cross-compiling"); //! let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); //! let env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap(); //! //! let libdir = std::path::Path::new(&cross_lib_dir); //! python3_dll_a::generate_implib_for_target(libdir, &arch, &env) //! .expect("python3.dll import library generator failed"); //! } //! } //! ``` //! //! A compatible `python3.dll` import library file named `python3.dll.a` //! or `python3.lib` will be automatically created in the directory //! pointed by the `PYO3_CROSS_LIB_DIR` environment variable. //! //! ### Example `cargo build` invocation //! //! ```sh //! PYO3_CROSS_LIB_DIR=target/python3-dll cargo build --target x86_64-pc-windows-gnu //! ``` //! //! Generating version-specific `python3y.dll` import libraries //! ----------------------------------------------------------- //! //! As an advanced feature, `python3-dll-a` can generate Python version //! specific import libraries such as `python39.lib`. //! //! See the [`ImportLibraryGenerator`] builder API description for details. #![deny(missing_docs)] #![allow(clippy::needless_doctest_main)] use std::env; use std::fs::{create_dir_all, write}; use std::io::{Error, ErrorKind, Result}; use std::path::{Path, PathBuf}; use std::process::Command; /// Import library file extension for the GNU environment ABI (MinGW-w64) const IMPLIB_EXT_GNU: &str = ".dll.a"; /// Import library file extension for the MSVC environment ABI const IMPLIB_EXT_MSVC: &str = ".lib"; /// Canonical MinGW-w64 `dlltool` program name const DLLTOOL_GNU: &str = "x86_64-w64-mingw32-dlltool"; /// Canonical MinGW-w64 `dlltool` program name (32-bit version) const DLLTOOL_GNU_32: &str = "i686-w64-mingw32-dlltool"; /// Canonical `dlltool` program name for the MSVC environment ABI (LLVM dlltool) const DLLTOOL_MSVC: &str = "llvm-dlltool"; /// Canonical `lib` program name for the MSVC environment ABI (MSVC lib.exe) #[cfg(windows)] const LIB_MSVC: &str = "lib.exe"; /// Python interpreter implementations #[derive(Debug, Clone, Copy)] pub enum PythonImplementation { /// CPython CPython, /// PyPy PyPy, } /// Windows import library generator for Python /// /// Generates `python3.dll` or `pythonXY.dll` import library directly from the /// embedded Python ABI definitions data for the specified compile target. /// /// Example usage /// ------------- /// /// ```no_run /// # use std::path::Path; /// # use python3_dll_a::ImportLibraryGenerator; /// // Generate `python3.dll.a` in "target/python3-dll-a" /// ImportLibraryGenerator::new("x86_64", "gnu") /// .generate(Path::new("target/python3-dll-a")) /// .unwrap(); /// /// // Generate `python3.lib` in "target/python3-lib" /// ImportLibraryGenerator::new("x86_64", "msvc") /// .generate(Path::new("target/python3-lib")) /// .unwrap(); /// /// // Generate `python39.dll.a` in "target/python3-dll-a" /// ImportLibraryGenerator::new("x86_64", "gnu") /// .version(Some((3, 9))) /// .generate(Path::new("target/python3-dll-a")) /// .unwrap(); /// /// // Generate `python38.lib` in "target/python3-lib" /// ImportLibraryGenerator::new("x86_64", "msvc") /// .version(Some((3, 8))) /// .generate(Path::new("target/python3-lib")) /// .unwrap(); /// ``` #[derive(Debug, Clone)] pub struct ImportLibraryGenerator { /// The compile target architecture name (as in `CARGO_CFG_TARGET_ARCH`) arch: String, // The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`) env: String, /// Major and minor Python version (for `pythonXY.dll` only) version: Option<(u8, u8)>, /// Python interpreter implementation implementation: PythonImplementation, } impl ImportLibraryGenerator { /// Creates a new import library generator for the specified compile target. /// /// The compile target architecture name (as in `CARGO_CFG_TARGET_ARCH`) /// is passed in `arch`. /// /// The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`) /// is passed in `env`. pub fn new(arch: &str, env: &str) -> Self { Self { arch: arch.to_string(), env: env.to_string(), version: None, implementation: PythonImplementation::CPython, } } /// Sets major and minor version for the `pythonXY.dll` import library. /// /// The version-agnostic `python3.dll` is generated by default. pub fn version(&mut self, version: Option<(u8, u8)>) -> &mut Self { self.version = version; self } /// Sets Python interpreter implementation pub fn implementation(&mut self, implementation: PythonImplementation) -> &mut Self { self.implementation = implementation; self } /// Generates the Python DLL import library in `out_dir`. /// /// The version-agnostic `python3.dll` import library is generated /// by default unless the version-specific `pythonXY.dll` import /// was requested via `version()`. pub fn generate(&self, out_dir: &Path) -> Result<()> { create_dir_all(out_dir)?; let defpath = self.write_def_file(out_dir)?; // Try to guess the `dlltool` executable name from the target triple. let dlltool_command = DllToolCommand::find_for_target(&self.arch, &self.env)?; // Get the import library file extension from the used `dlltool` flavor. let implib_ext = dlltool_command.implib_file_ext(); let implib_file = self.implib_file_path(out_dir, implib_ext); // Build the complete `dlltool` command with all required arguments. let mut command = dlltool_command.build(&defpath, &implib_file); // Run the selected `dlltool` executable to generate the import library. let status = command.status().map_err(|e| { let msg = format!("{:?} failed with {}", command, e); Error::new(e.kind(), msg) })?; if status.success() { Ok(()) } else { let msg = format!("{:?} failed with {}", command, status); Err(Error::new(ErrorKind::Other, msg)) } } /// Writes out the embedded Python library definitions file to `out_dir`. /// /// Returns the newly created `python3.def` or `pythonXY.def` file path. fn write_def_file(&self, out_dir: &Path) -> Result { let (def_file, def_file_content) = match self.implementation { PythonImplementation::CPython => match self.version { None => ("python3.def", include_str!("python3.def")), Some((3, 7)) => ("python37.def", include_str!("python37.def")), Some((3, 8)) => ("python38.def", include_str!("python38.def")), Some((3, 9)) => ("python39.def", include_str!("python39.def")), Some((3, 10)) => ("python310.def", include_str!("python310.def")), Some((3, 11)) => ("python311.def", include_str!("python311.def")), Some((3, 12)) => ("python312.def", include_str!("python312.def")), Some((3, 13)) => ("python313.def", include_str!("python313.def")), _ => return Err(Error::new(ErrorKind::Other, "Unsupported Python version")), }, PythonImplementation::PyPy => match self.version { Some((3, 7)) => ("libpypy3-c.def", include_str!("libpypy3-c.def")), Some((3, 8)) => ("libpypy3-c.def", include_str!("libpypy3-c.def")), Some((3, 9)) => ("libpypy3.9-c.def", include_str!("libpypy3.9-c.def")), Some((3, 10)) => ("libpypy3.10-c.def", include_str!("libpypy3.10-c.def")), _ => return Err(Error::new(ErrorKind::Other, "Unsupported PyPy version")), }, }; let mut defpath = out_dir.to_owned(); defpath.push(def_file); write(&defpath, def_file_content)?; Ok(defpath) } /// Builds the generated import library file name. /// /// The output file extension is passed in `libext`. /// /// Returns the full import library file path under `out_dir`. fn implib_file_path(&self, out_dir: &Path, libext: &str) -> PathBuf { let libname = match self.version { Some((major, minor)) => { format!("python{}{}{}", major, minor, libext) } None => format!("python3{}", libext), }; let mut libpath = out_dir.to_owned(); libpath.push(libname); libpath } } /// Generates `python3.dll` import library directly from the embedded /// Python Stable ABI definitions data for the specified compile target. /// /// The import library file named `python3.dll.a` or `python3.lib` is created /// in directory `out_dir`. /// /// The compile target architecture name (as in `CARGO_CFG_TARGET_ARCH`) /// is passed in `arch`. /// /// The compile target environment ABI name (as in `CARGO_CFG_TARGET_ENV`) /// is passed in `env`. pub fn generate_implib_for_target(out_dir: &Path, arch: &str, env: &str) -> Result<()> { ImportLibraryGenerator::new(arch, env).generate(out_dir) } /// `dlltool` utility command builder /// /// Supports Visual Studio `lib.exe`, MinGW, LLVM and Zig `dlltool` flavors. #[derive(Debug)] enum DllToolCommand { /// MinGW `dlltool` program (with prefix) Mingw { command: Command }, /// LLVM `llvm-dlltool` program (no prefix) Llvm { command: Command, machine: String }, /// MSVC `lib.exe` program (no prefix) LibExe { command: Command, machine: String }, /// `zig dlltool` wrapper (no prefix) Zig { command: Command, machine: String }, } impl DllToolCommand { /// Attempts to find the best matching `dlltool` flavor for the target. fn find_for_target(arch: &str, env: &str) -> Result { // LLVM tools use their own target architecture names... let machine = match arch { "x86_64" => "i386:x86-64", "x86" => "i386", "aarch64" => "arm64", arch => arch, } .to_owned(); // If `zig cc` is used as the linker, `zig dlltool` is the best choice. if let Some(command) = find_zig() { return Ok(DllToolCommand::Zig { command, machine }); } match env { // 64-bit and 32-bit MinGW-w64 (aka `{x86_64,i686}-pc-windows-gnu`) "gnu" => Ok(DllToolCommand::Mingw { command: get_mingw_dlltool(arch)?, }), // MSVC ABI (multiarch) "msvc" => { if let Some(command) = find_lib_exe(arch) { // MSVC tools use their own target architecture names... let machine = match arch { "x86_64" => "X64", "x86" => "X86", "aarch64" => "ARM64", arch => arch, } .to_owned(); Ok(DllToolCommand::LibExe { command, machine }) } else { let command = Command::new(DLLTOOL_MSVC); Ok(DllToolCommand::Llvm { command, machine }) } } _ => { let msg = format!("Unsupported target env ABI '{}'", env); Err(Error::new(ErrorKind::Other, msg)) } } } /// Returns the import library file extension used by /// this `dlltool` flavor. fn implib_file_ext(&self) -> &'static str { if let DllToolCommand::Mingw { .. } = self { IMPLIB_EXT_GNU } else { IMPLIB_EXT_MSVC } } /// Generates the complete `dlltool` executable invocation command. fn build(self, defpath: &Path, libpath: &Path) -> Command { match self { Self::Mingw { mut command } => { command .arg("--input-def") .arg(defpath) .arg("--output-lib") .arg(libpath); command } Self::Llvm { mut command, machine, } => { command .arg("-m") .arg(machine) .arg("-d") .arg(defpath) .arg("-l") .arg(libpath); command } Self::LibExe { mut command, machine, } => { command .arg(format!("/MACHINE:{}", machine)) .arg(format!("/DEF:{}", defpath.display())) .arg(format!("/OUT:{}", libpath.display())); command } Self::Zig { mut command, machine, } => { // Same as `llvm-dlltool`, but invoked as `zig dlltool`. command .arg("dlltool") .arg("-m") .arg(machine) .arg("-d") .arg(defpath) .arg("-l") .arg(libpath); command } } } } /// Chooses the appropriate MinGW-w64 `dlltool` executable /// for the target architecture. /// /// Examines the user-provided `PYO3_MINGW_DLLTOOL` environment variable first /// and falls back to the default MinGW-w64 arch prefixes. fn get_mingw_dlltool(arch: &str) -> Result { if let Ok(user_dlltool) = env::var("PYO3_MINGW_DLLTOOL") { Ok(Command::new(user_dlltool)) } else { let prefix_dlltool = match arch { // 64-bit MinGW-w64 (aka `x86_64-pc-windows-gnu`) "x86_64" => Ok(DLLTOOL_GNU), // 32-bit MinGW-w64 (aka `i686-pc-windows-gnu`) "x86" => Ok(DLLTOOL_GNU_32), // AArch64? _ => { let msg = format!("Unsupported MinGW target arch '{}'", arch); Err(Error::new(ErrorKind::Other, msg)) } }?; Ok(Command::new(prefix_dlltool)) } } /// Finds the `zig` executable (when built by ``maturin --zig`). /// /// Examines the `ZIG_COMMAND` environment variable /// to find out if `zig cc` is being used as the linker. fn find_zig() -> Option { // `ZIG_COMMAND` may contain simply `zig` or `/usr/bin/zig`, // or a more complex construct like `python3 -m ziglang`. let zig_command = env::var("ZIG_COMMAND").ok()?; // Try to emulate `sh -c ${ZIG_COMMAND}`. let mut zig_cmdlet = zig_command.split_ascii_whitespace(); // Extract the main program component (e.g. `zig` or `python3`). let mut zig = Command::new(zig_cmdlet.next()?); // Append the rest of the commandlet. zig.args(zig_cmdlet); Some(zig) } /// Finds Visual Studio `lib.exe` when running on Windows. #[cfg(windows)] fn find_lib_exe(arch: &str) -> Option { let target = match arch { "x86_64" => "x86_64-pc-windows-msvc", "x86" => "i686-pc-windows-msvc", "aarch64" => "aarch64-pc-windows-msvc", _ => return None, }; cc::windows_registry::find(target, LIB_MSVC) } #[cfg(not(windows))] fn find_lib_exe(_arch: &str) -> Option { None } #[cfg(test)] mod tests { use std::path::PathBuf; use super::*; #[cfg(unix)] #[test] fn generate() { // FIXME: Use "target/" dirs for temporary files. let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); dir.push("target"); dir.push("x86_64-pc-windows-gnu"); dir.push("python3-dll"); ImportLibraryGenerator::new("x86_64", "gnu") .generate(&dir) .unwrap(); for minor in 7..=13 { ImportLibraryGenerator::new("x86_64", "gnu") .version(Some((3, minor))) .generate(&dir) .unwrap(); } // PyPy for minor in 7..=10 { ImportLibraryGenerator::new("x86_64", "gnu") .version(Some((3, minor))) .implementation(PythonImplementation::PyPy) .generate(&dir) .unwrap(); } } #[cfg(unix)] #[test] fn generate_gnu32() { let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); dir.push("target"); dir.push("i686-pc-windows-gnu"); dir.push("python3-dll"); generate_implib_for_target(&dir, "x86", "gnu").unwrap(); } #[test] fn generate_msvc() { let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); dir.push("target"); dir.push("x86_64-pc-windows-msvc"); dir.push("python3-dll"); ImportLibraryGenerator::new("x86_64", "msvc") .generate(&dir) .unwrap(); for minor in 7..=13 { ImportLibraryGenerator::new("x86_64", "msvc") .version(Some((3, minor))) .generate(&dir) .unwrap(); } // PyPy for minor in 7..=10 { ImportLibraryGenerator::new("x86_64", "msvc") .version(Some((3, minor))) .implementation(PythonImplementation::PyPy) .generate(&dir) .unwrap(); } } #[test] fn generate_msvc32() { let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); dir.push("target"); dir.push("i686-pc-windows-msvc"); dir.push("python3-dll"); generate_implib_for_target(&dir, "x86", "msvc").unwrap(); } #[test] fn generate_msvc_arm64() { let mut dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); dir.push("target"); dir.push("aarch64-pc-windows-msvc"); dir.push("python3-dll"); generate_implib_for_target(&dir, "aarch64", "msvc").unwrap(); } } python3-dll-a/src/python310.def0000644000175000017500000010363714661133735017162 0ustar jamespagejamespage; ; Definition file of python310.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "python310.dll" EXPORTS PyAIter_Check PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyAsyncGen_New PyAsyncGen_Type DATA PyBaseObject_Type DATA PyBool_FromLong PyBool_Type DATA PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_FromContiguous PyBuffer_GetPointer PyBuffer_IsContiguous PyBuffer_Release PyBuffer_SizeFromFormat PyBuffer_ToContiguous PyByteArrayIter_Type DATA PyByteArray_AsString PyByteArray_Concat PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Resize PyByteArray_Size PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyBytes_Type DATA PyCFunction_Call PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_New PyCFunction_NewEx PyCFunction_Type DATA PyCMethod_New PyCMethod_Type DATA PyCallIter_New PyCallIter_Type DATA PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCapsule_Type DATA PyCell_Get PyCell_New PyCell_Set PyCell_Type DATA PyClassMethodDescr_Type DATA PyClassMethod_New PyClassMethod_Type DATA PyCode_Addr2Line PyCode_New PyCode_NewEmpty PyCode_NewWithPosOnlyArgs PyCode_Optimize PyCode_Type DATA PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_NameReplaceErrors PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_Unregister PyCodec_XMLCharRefReplaceErrors PyCompile_OpcodeStackEffect PyCompile_OpcodeStackEffectWithJump PyComplex_AsCComplex PyComplex_FromCComplex PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyComplex_Type DATA PyConfig_Clear PyConfig_InitIsolatedConfig PyConfig_InitPythonConfig PyConfig_Read PyConfig_SetArgv PyConfig_SetBytesArgv PyConfig_SetBytesString PyConfig_SetString PyConfig_SetWideStringList PyContextToken_Type DATA PyContextVar_Get PyContextVar_New PyContextVar_Reset PyContextVar_Set PyContextVar_Type DATA PyContext_Copy PyContext_CopyCurrent PyContext_Enter PyContext_Exit PyContext_New PyContext_Type DATA PyCoro_New PyCoro_Type DATA PyDescr_IsData PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDescr_NewWrapper PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_New PyDictProxy_Type DATA PyDictRevIterItem_Type DATA PyDictRevIterKey_Type DATA PyDictRevIterValue_Type DATA PyDictValues_Type DATA PyDict_Clear PyDict_Contains PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_GetItem PyDict_GetItemString PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_SetDefault PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Type DATA PyDict_Update PyDict_Values PyEllipsis_Type DATA PyEnum_Type DATA PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_FormatV PyErr_GetExcInfo PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_ProgramTextObject PyErr_RangedSyntaxLocationObject PyErr_ResourceWarning PyErr_Restore PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetExcFromWindowsErrWithUnicodeFilename PyErr_SetExcInfo PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetFromErrnoWithFilenameObjects PyErr_SetFromErrnoWithUnicodeFilename PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyErr_SetFromWindowsErrWithUnicodeFilename PyErr_SetImportError PyErr_SetImportErrorSubclass PyErr_SetInterrupt PyErr_SetInterruptEx PyErr_SetNone PyErr_SetObject PyErr_SetString PyErr_SyntaxLocation PyErr_SyntaxLocationEx PyErr_SyntaxLocationObject PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnExplicitFormat PyErr_WarnExplicitObject PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_MergeCompilerFlags PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_SetProfile PyEval_SetTrace PyEval_ThreadsInitialized PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EncodingWarning DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_ModuleNotFoundError DATA PyExc_NameError DATA PyExc_NotADirectoryError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_RecursionError DATA PyExc_ReferenceError DATA PyExc_ResourceWarning DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopAsyncIteration DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TimeoutError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_WindowsError DATA PyExc_ZeroDivisionError DATA PyExceptionClass_Name PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_NewStdPrinter PyFile_OpenCode PyFile_OpenCodeObject PyFile_SetOpenCodeHook PyFile_WriteObject PyFile_WriteString PyFilter_Type DATA PyFloat_AsDouble PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFloat_Type DATA PyFrame_BlockPop PyFrame_BlockSetup PyFrame_FastToLocals PyFrame_FastToLocalsWithError PyFrame_GetBack PyFrame_GetCode PyFrame_GetLineNumber PyFrame_LocalsToFast PyFrame_New PyFrame_Type DATA PyFrozenSet_New PyFrozenSet_Type DATA PyFunction_GetAnnotations PyFunction_GetClosure PyFunction_GetCode PyFunction_GetDefaults PyFunction_GetGlobals PyFunction_GetKwDefaults PyFunction_GetModule PyFunction_New PyFunction_NewWithQualName PyFunction_SetAnnotations PyFunction_SetClosure PyFunction_SetDefaults PyFunction_SetKwDefaults PyFunction_Type DATA PyGC_Collect PyGC_Disable PyGC_Enable PyGC_IsEnabled PyGILState_Check PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyGen_New PyGen_NewWithQualName PyGen_Type DATA PyGetSetDescr_Type DATA PyHash_GetFuncDef PyImport_AddModule PyImport_AddModuleObject PyImport_AppendInittab PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleObject PyImport_ExecCodeModuleWithPathnames PyImport_ExtendInittab PyImport_FrozenModules DATA PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModule PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportFrozenModuleObject PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleLevelObject PyImport_ImportModuleNoBlock PyImport_Inittab DATA PyImport_ReloadModule PyIndex_Check PyInstanceMethod_Function PyInstanceMethod_New PyInstanceMethod_Type DATA PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_Get PyInterpreterState_GetDict PyInterpreterState_GetID PyInterpreterState_Head PyInterpreterState_Main PyInterpreterState_New PyInterpreterState_Next PyInterpreterState_ThreadHead PyIter_Check PyIter_Next PyIter_Send PyListIter_Type DATA PyListRevIter_Type DATA PyList_Append PyList_AsTuple PyList_GetItem PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyList_Type DATA PyLongRangeIter_Type DATA PyLong_AsDouble PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnicodeObject PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromVoidPtr PyLong_GetInfo PyLong_Type DATA PyMap_Type DATA PyMapping_Check PyMapping_GetItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMarshal_ReadLastObjectFromFile PyMarshal_ReadLongFromFile PyMarshal_ReadObjectFromFile PyMarshal_ReadObjectFromString PyMarshal_ReadShortFromFile PyMarshal_WriteLongToFile PyMarshal_WriteObjectToFile PyMarshal_WriteObjectToString PyMem_Calloc PyMem_Free PyMem_GetAllocator PyMem_Malloc PyMem_RawCalloc PyMem_RawFree PyMem_RawMalloc PyMem_RawRealloc PyMem_Realloc PyMem_SetAllocator PyMem_SetupDebugHooks PyMemberDescr_Type DATA PyMember_GetOne PyMember_SetOne PyMemoryView_FromBuffer PyMemoryView_FromMemory PyMemoryView_FromObject PyMemoryView_GetContiguous PyMemoryView_Type DATA PyMethodDescr_Type DATA PyMethod_Function PyMethod_New PyMethod_Self PyMethod_Type DATA PyModuleDef_Init PyModuleDef_Type DATA PyModule_AddFunctions PyModule_AddIntConstant PyModule_AddObject PyModule_AddObjectRef PyModule_AddStringConstant PyModule_AddType PyModule_Create2 PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetNameObject PyModule_GetState PyModule_New PyModule_NewObject PyModule_SetDocString PyModule_Type DATA PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMatrixMultiply PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_MatrixMultiply PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyODictItems_Type DATA PyODictIter_Type DATA PyODictKeys_Type DATA PyODictValues_Type DATA PyODict_DelItem PyODict_New PyODict_SetItem PyODict_Type DATA PyOS_AfterFork PyOS_FSPath PyOS_InputHook DATA PyOS_InterruptOccurred PyOS_Readline PyOS_ReadlineFunctionPointer DATA PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsCharBuffer PyObject_AsFileDescriptor PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_Bytes PyObject_Call PyObject_CallFinalizer PyObject_CallFinalizerFromDealloc PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallNoArgs PyObject_CallObject PyObject_Calloc PyObject_CheckBuffer PyObject_CheckReadBuffer PyObject_ClearWeakRefs PyObject_CopyData PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_IsFinalized PyObject_GC_IsTracked PyObject_GC_Track PyObject_GC_UnTrack PyObject_GET_WEAKREFS_LISTPTR PyObject_GenericGetAttr PyObject_GenericGetDict PyObject_GenericSetAttr PyObject_GenericSetDict PyObject_GetAIter PyObject_GetArenaAllocator PyObject_GetAttr PyObject_GetAttrString PyObject_GetBuffer PyObject_GetItem PyObject_GetIter PyObject_HasAttr PyObject_HasAttrString PyObject_Hash PyObject_HashNotImplemented PyObject_IS_GC PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_LengthHint PyObject_Malloc PyObject_Not PyObject_Print PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetArenaAllocator PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PyObject_VectorcallDict PyObject_VectorcallMethod PyPickleBuffer_FromObject PyPickleBuffer_GetBuffer PyPickleBuffer_Release PyPickleBuffer_Type DATA PyPreConfig_InitIsolatedConfig PyPreConfig_InitPythonConfig PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyReversed_Type DATA PyRun_AnyFile PyRun_AnyFileEx PyRun_AnyFileExFlags PyRun_AnyFileFlags PyRun_File PyRun_FileEx PyRun_FileExFlags PyRun_FileFlags PyRun_InteractiveLoop PyRun_InteractiveLoopFlags PyRun_InteractiveOne PyRun_InteractiveOneFlags PyRun_InteractiveOneObject PyRun_SimpleFile PyRun_SimpleFileEx PyRun_SimpleFileExFlags PyRun_SimpleString PyRun_SimpleStringFlags PyRun_String PyRun_StringFlags PySeqIter_New PySeqIter_Type DATA PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySetIter_Type DATA PySet_Add PySet_Clear PySet_Contains PySet_Discard PySet_New PySet_Pop PySet_Size PySet_Type DATA PySlice_AdjustIndices PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PySlice_Type DATA PySlice_Unpack PyState_AddModule PyState_FindModule PyState_RemoveModule PyStaticMethod_New PyStaticMethod_Type DATA PyStatus_Error PyStatus_Exception PyStatus_Exit PyStatus_IsError PyStatus_IsExit PyStatus_NoMemory PyStatus_Ok PyStdPrinter_Type DATA PyStructSequence_GetItem PyStructSequence_InitType PyStructSequence_InitType2 PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PySuper_Type DATA PySymtable_Lookup PySys_AddAuditHook PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_AddXOption PySys_Audit PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_GetXOptions PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_Get PyThreadState_GetDict PyThreadState_GetFrame PyThreadState_GetID PyThreadState_GetInterpreter PyThreadState_New PyThreadState_Next PyThreadState_SetAsyncExc PyThreadState_Swap PyThread_GetInfo PyThread_ReInitTLS PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_allocate_lock PyThread_create_key PyThread_delete_key PyThread_delete_key_value PyThread_exit_thread PyThread_free_lock PyThread_get_key_value PyThread_get_stacksize PyThread_get_thread_ident PyThread_get_thread_native_id PyThread_init_thread PyThread_release_lock PyThread_set_key_value PyThread_set_stacksize PyThread_start_new_thread PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyToken_OneChar PyToken_ThreeChars PyToken_TwoChars PyTraceBack_Here PyTraceBack_Print PyTraceBack_Type DATA PyTraceMalloc_Track PyTraceMalloc_Untrack PyTupleIter_Type DATA PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyTuple_Type DATA PyType_ClearCache PyType_FromModuleAndSpec PyType_FromSpec PyType_FromSpecWithBases PyType_GenericAlloc PyType_GenericNew PyType_GetFlags PyType_GetModule PyType_GetModuleState PyType_GetSlot PyType_IsSubtype PyType_Modified PyType_Ready PyType_Type DATA PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_Create PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeIter_Type DATA PyUnicodeTranslateError_Create PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsMBCSString PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8 PyUnicode_AsUTF8AndSize PyUnicode_AsUTF8String PyUnicode_AsUnicode PyUnicode_AsUnicodeAndSize PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_AsWideCharString PyUnicode_BuildEncodingMap PyUnicode_Compare PyUnicode_CompareWithASCIIString PyUnicode_Concat PyUnicode_Contains PyUnicode_CopyCharacters PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeCodePageStateful PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_Encode PyUnicode_EncodeASCII PyUnicode_EncodeCharmap PyUnicode_EncodeCodePage PyUnicode_EncodeDecimal PyUnicode_EncodeFSDefault PyUnicode_EncodeLatin1 PyUnicode_EncodeLocale PyUnicode_EncodeMBCS PyUnicode_EncodeRawUnicodeEscape PyUnicode_EncodeUTF16 PyUnicode_EncodeUTF32 PyUnicode_EncodeUTF7 PyUnicode_EncodeUTF8 PyUnicode_EncodeUnicodeEscape PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Fill PyUnicode_Find PyUnicode_FindChar PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromKindAndData PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromUnicode PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetLength PyUnicode_GetSize PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_New PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_ReadChar PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Substring PyUnicode_Tailmatch PyUnicode_TransformDecimalToASCII PyUnicode_Translate PyUnicode_TranslateCharmap PyUnicode_Type DATA PyUnicode_WriteChar PyVectorcall_Call PyWeakref_GetObject PyWeakref_NewProxy PyWeakref_NewRef PyWideStringList_Append PyWideStringList_Insert PyWrapperDescr_Type DATA PyWrapper_New PyZip_Type DATA Py_AddPendingCall Py_AtExit Py_BuildValue Py_BytesMain Py_BytesWarningFlag DATA Py_CompileString Py_CompileStringExFlags Py_CompileStringFlags Py_CompileStringObject Py_DebugFlag DATA Py_DecRef Py_DecodeLocale Py_DontWriteBytecodeFlag DATA Py_EncodeLocale Py_EndInterpreter Py_EnterRecursiveCall Py_Exit Py_ExitStatusException Py_FatalError Py_FdIsInteractive Py_FileSystemDefaultEncodeErrors DATA Py_FileSystemDefaultEncoding DATA Py_Finalize Py_FinalizeEx Py_FrozenFlag DATA Py_GenericAlias Py_GenericAliasType DATA Py_GetArgcArgv Py_GetBuildInfo Py_GetCompiler Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_HasFileSystemDefaultEncoding DATA Py_HashRandomizationFlag DATA Py_IgnoreEnvironmentFlag DATA Py_IncRef Py_Initialize Py_InitializeEx Py_InitializeFromConfig Py_InspectFlag DATA Py_InteractiveFlag DATA Py_Is Py_IsFalse Py_IsInitialized Py_IsNone Py_IsTrue Py_IsolatedFlag DATA Py_LeaveRecursiveCall Py_LegacyWindowsFSEncodingFlag DATA Py_LegacyWindowsStdioFlag DATA Py_Main Py_MakePendingCalls Py_NewInterpreter Py_NewRef Py_NoSiteFlag DATA Py_NoUserSiteDirectory DATA Py_OptimizeFlag DATA Py_PreInitialize Py_PreInitializeFromArgs Py_PreInitializeFromBytesArgs Py_QuietFlag DATA Py_ReprEnter Py_ReprLeave Py_RunMain Py_SetPath Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_SetStandardStreamEncoding Py_UTF8Mode DATA Py_UnbufferedStdioFlag DATA Py_UniversalNewlineFgets Py_VaBuildValue Py_VerboseFlag DATA Py_XNewRef Py_hexdigits DATA _PyAST_Compile _PyAccu_Accumulate _PyAccu_Destroy _PyAccu_Finish _PyAccu_FinishAsList _PyAccu_Init _PyArena_AddPyObject _PyArena_Free _PyArena_Malloc _PyArena_New _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoKwnames _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT _PyArg_Parse_SizeT _PyArg_UnpackKeywords _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyArg_VaParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyArgv_AsWstrList _PyAsyncGenASend_Type DATA _PyAsyncGenAThrow_Type DATA _PyAsyncGenWrappedValue_Type DATA _PyByteArray_empty_string DATA _PyBytesIOBuffer_Type DATA _PyBytesWriter_Alloc _PyBytesWriter_Dealloc _PyBytesWriter_Finish _PyBytesWriter_Init _PyBytesWriter_Prepare _PyBytesWriter_Resize _PyBytesWriter_WriteBytes _PyBytes_DecodeEscape _PyBytes_FormatEx _PyBytes_FromHex _PyBytes_Join _PyBytes_Resize _PyCode_CheckLineNumber _PyCode_ConstantKey _PyCode_GetExtra _PyCode_SetExtra _PyCodecInfo_GetIncrementalDecoder _PyCodecInfo_GetIncrementalEncoder _PyCodec_DecodeText _PyCodec_EncodeText _PyCodec_Lookup _PyCodec_LookupTextEncoding _PyComplex_FormatAdvancedWriter _PyConfig_AsDict _PyConfig_FromDict _PyConfig_InitCompatConfig _PyContext_NewHamtForTests _PyCoroWrapper_Type DATA _PyCrossInterpreterData_Lookup _PyCrossInterpreterData_NewObject _PyCrossInterpreterData_RegisterClass _PyCrossInterpreterData_Release _PyDebugAllocatorStats _PyDictView_Intersect _PyDictView_New _PyDict_CheckConsistency _PyDict_ContainsId _PyDict_Contains_KnownHash _PyDict_DebugMallocStats _PyDict_DelItemId _PyDict_DelItemIf _PyDict_DelItem_KnownHash _PyDict_GetItemIdWithError _PyDict_GetItemStringWithError _PyDict_GetItem_KnownHash _PyDict_HasOnlyStringKeys _PyDict_MaybeUntrack _PyDict_MergeEx _PyDict_NewPresized _PyDict_Next _PyDict_Pop _PyDict_SetItemId _PyDict_SetItem_KnownHash _PyDict_SizeOf _PyErr_BadInternalCall _PyErr_ChainExceptions _PyErr_ChainStackItem _PyErr_CheckSignals _PyErr_CheckSignalsTstate _PyErr_Clear _PyErr_Display _PyErr_ExceptionMatches _PyErr_Fetch _PyErr_Format _PyErr_FormatFromCause _PyErr_FormatFromCauseTstate _PyErr_GetExcInfo _PyErr_GetTopmostException _PyErr_NoMemory _PyErr_NormalizeException _PyErr_Print _PyErr_ProgramDecodedTextObject _PyErr_Restore _PyErr_SetKeyError _PyErr_SetNone _PyErr_SetObject _PyErr_SetString _PyErr_TrySetFromCause _PyErr_WriteUnraisableMsg _PyEval_AddPendingCall _PyEval_CallTracing _PyEval_EvalFrameDefault _PyEval_GetAsyncGenFinalizer _PyEval_GetAsyncGenFirstiter _PyEval_GetBuiltinId _PyEval_GetCoroutineOriginTrackingDepth _PyEval_GetSwitchInterval _PyEval_RequestCodeExtraIndex _PyEval_SetAsyncGenFinalizer _PyEval_SetAsyncGenFirstiter _PyEval_SetCoroutineOriginTrackingDepth _PyEval_SetProfile _PyEval_SetSwitchInterval _PyEval_SetTrace _PyEval_SignalAsyncExc _PyEval_SignalReceived _PyEval_SliceIndex _PyEval_SliceIndexNotNone _PyFloat_DebugMallocStats _PyFloat_FormatAdvancedWriter _PyFloat_Pack2 _PyFloat_Pack4 _PyFloat_Pack8 _PyFloat_Unpack2 _PyFloat_Unpack4 _PyFloat_Unpack8 _PyFrame_DebugMallocStats _PyFunction_Vectorcall _PyGILState_GetInterpreterStateUnsafe _PyGen_FetchStopIterationValue _PyGen_Finalize _PyGen_SetStopIterationValue _PyHamtItems_Type DATA _PyHamtKeys_Type DATA _PyHamtValues_Type DATA _PyHamt_ArrayNode_Type DATA _PyHamt_BitmapNode_Type DATA _PyHamt_CollisionNode_Type DATA _PyHamt_Type DATA _PyImport_AcquireLock _PyImport_FindExtensionObject _PyImport_FixupBuiltin _PyImport_FixupExtensionObject _PyImport_GetModuleAttr _PyImport_GetModuleAttrString _PyImport_GetModuleId _PyImport_IsInitialized _PyImport_ReleaseLock _PyImport_SetModule _PyImport_SetModuleString _PyInterpreterID_LookUp _PyInterpreterID_New _PyInterpreterID_Type DATA _PyInterpreterState_Enable _PyInterpreterState_GetConfig _PyInterpreterState_GetConfigCopy _PyInterpreterState_GetEvalFrameFunc _PyInterpreterState_GetIDObject _PyInterpreterState_GetMainModule _PyInterpreterState_IDDecref _PyInterpreterState_IDIncref _PyInterpreterState_IDInitref _PyInterpreterState_LookUpID _PyInterpreterState_RequireIDRef _PyInterpreterState_RequiresIDRef _PyInterpreterState_SetConfig _PyInterpreterState_SetEvalFrameFunc _PyList_DebugMallocStats _PyList_Extend _PyLong_AsByteArray _PyLong_AsInt _PyLong_AsTime_t _PyLong_Copy _PyLong_DigitValue DATA _PyLong_DivmodNear _PyLong_FileDescriptor_Converter _PyLong_Format _PyLong_FormatAdvancedWriter _PyLong_FormatBytesWriter _PyLong_FormatWriter _PyLong_Frexp _PyLong_FromByteArray _PyLong_FromBytes _PyLong_FromTime_t _PyLong_GCD _PyLong_Lshift _PyLong_New _PyLong_NumBits _PyLong_Rshift _PyLong_Sign _PyLong_Size_t_Converter _PyLong_UnsignedInt_Converter _PyLong_UnsignedLongLong_Converter _PyLong_UnsignedLong_Converter _PyLong_UnsignedShort_Converter _PyManagedBuffer_Type DATA _PyMem_GetAllocatorName _PyMem_GetCurrentAllocatorName _PyMem_RawStrdup _PyMem_RawWcsdup _PyMem_SetDefaultAllocator _PyMem_SetupAllocators _PyMem_Strdup _PyMethodWrapper_Type DATA _PyModuleSpec_IsInitializing _PyModule_Clear _PyModule_ClearDict _PyModule_CreateInitialized _PyNamespace_New _PyNamespace_Type DATA _PyNone_Type DATA _PyNotImplemented_Type DATA _PyNumber_Index _PyOS_InterruptOccurred _PyOS_IsMainThread _PyOS_ReadlineTState DATA _PyOS_SigintEvent _PyOS_URandom _PyOS_URandomNonblock _PyObject_AssertFailed _PyObject_Call _PyObject_CallFunction_SizeT _PyObject_CallMethodId _PyObject_CallMethodIdObjArgs _PyObject_CallMethodId_SizeT _PyObject_CallMethod_SizeT _PyObject_Call_Prepend _PyObject_CheckConsistency _PyObject_CheckCrossInterpreterData _PyObject_DebugMallocStats _PyObject_DebugTypeStats _PyObject_Dump _PyObject_FastCallDictTstate _PyObject_FunctionStr _PyObject_GC_Calloc _PyObject_GC_Malloc _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_GenericGetAttrWithDict _PyObject_GenericSetAttrWithDict _PyObject_GetAttrId _PyObject_GetCrossInterpreterData _PyObject_GetDictPtr _PyObject_GetMethod _PyObject_HasLen _PyObject_IsAbstract _PyObject_IsFreed _PyObject_LookupAttr _PyObject_LookupAttrId _PyObject_LookupSpecial _PyObject_MakeTpCall _PyObject_New _PyObject_NewVar _PyObject_NextNotImplemented _PyObject_RealIsInstance _PyObject_RealIsSubclass _PyObject_SetAttrId _PyParser_TokenNames DATA _PyPreConfig_InitCompatConfig _PyRun_AnyFileObject _PyRun_InteractiveLoopObject _PyRun_SimpleFileObject _PyRuntime DATA _PyRuntimeState_Fini _PyRuntimeState_Init _PyRuntime_Finalize _PyRuntime_Initialize _PySequence_BytesToCharpArray _PySequence_IterSearch _PySet_Dummy DATA _PySet_NextEntry _PySet_Update _PySlice_FromIndices _PySlice_GetLongIndices _PyStack_AsDict _PyState_AddModule _PyStructSequence_InitType _PySys_GetObjectId _PySys_GetSizeOf _PySys_SetObjectId _PyThreadState_DeleteCurrent _PyThreadState_DeleteExcept _PyThreadState_GetDict _PyThreadState_Init _PyThreadState_Prealloc _PyThreadState_Swap _PyThreadState_UncheckedGet _PyThread_CurrentExceptions _PyThread_CurrentFrames _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_noraise _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetPerfCounter _PyTime_GetPerfCounterWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_MulDiv _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyTraceMalloc_GetTraceback _PyTraceback_Add _PyTrash_begin _PyTrash_cond _PyTrash_deposit_object _PyTrash_destroy_chain _PyTrash_end _PyTrash_thread_deposit_object _PyTrash_thread_destroy_chain _PyTuple_DebugMallocStats _PyTuple_MaybeUntrack _PyTuple_Resize _PyType_CalculateMetaclass _PyType_CheckConsistency _PyType_GetDocFromInternalDoc _PyType_GetModuleByDef _PyType_GetTextSignatureFromInternalDoc _PyType_Lookup _PyType_LookupId _PyType_Name _PyUnicodeTranslateError_Create _PyUnicodeWriter_Dealloc _PyUnicodeWriter_Finish _PyUnicodeWriter_Init _PyUnicodeWriter_PrepareInternal _PyUnicodeWriter_PrepareKindInternal _PyUnicodeWriter_WriteASCIIString _PyUnicodeWriter_WriteChar _PyUnicodeWriter_WriteLatin1String _PyUnicodeWriter_WriteStr _PyUnicodeWriter_WriteSubstring _PyUnicode_AsASCIIString _PyUnicode_AsLatin1String _PyUnicode_AsUTF8String _PyUnicode_AsUnicode _PyUnicode_CheckConsistency _PyUnicode_Copy _PyUnicode_DecodeRawUnicodeEscapeStateful _PyUnicode_DecodeUnicodeEscapeInternal _PyUnicode_DecodeUnicodeEscapeStateful _PyUnicode_EQ _PyUnicode_EncodeCharmap _PyUnicode_EncodeUTF16 _PyUnicode_EncodeUTF32 _PyUnicode_EncodeUTF7 _PyUnicode_EqualToASCIIId _PyUnicode_EqualToASCIIString _PyUnicode_FastCopyCharacters _PyUnicode_FastFill _PyUnicode_FindMaxChar _PyUnicode_FormatAdvancedWriter _PyUnicode_FormatLong _PyUnicode_FromASCII _PyUnicode_FromId _PyUnicode_InsertThousandsGrouping _PyUnicode_IsAlpha _PyUnicode_IsCaseIgnorable _PyUnicode_IsCased _PyUnicode_IsDecimalDigit _PyUnicode_IsDigit _PyUnicode_IsLinebreak _PyUnicode_IsLowercase _PyUnicode_IsNumeric _PyUnicode_IsPrintable _PyUnicode_IsTitlecase _PyUnicode_IsUppercase _PyUnicode_IsWhitespace _PyUnicode_IsXidContinue _PyUnicode_IsXidStart _PyUnicode_JoinArray _PyUnicode_Ready _PyUnicode_ScanIdentifier _PyUnicode_ToDecimalDigit _PyUnicode_ToDigit _PyUnicode_ToFoldedFull _PyUnicode_ToLowerFull _PyUnicode_ToLowercase _PyUnicode_ToNumeric _PyUnicode_ToTitleFull _PyUnicode_ToTitlecase _PyUnicode_ToUpperFull _PyUnicode_ToUppercase _PyUnicode_TransformDecimalAndSpaceToASCII _PyUnicode_WideCharString_Converter _PyUnicode_WideCharString_Opt_Converter _PyUnicode_XStrip _PyWarnings_Init _PyWeakref_CallableProxyType DATA _PyWeakref_ClearRef _PyWeakref_GetWeakrefCount _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _PyWideStringList_AsList _PyWideStringList_Clear _PyWideStringList_Copy _PyWideStringList_Extend _PyWindowsConsoleIO_Type DATA _Py_BreakPoint _Py_BuildValue_SizeT _Py_CheckFunctionResult _Py_CheckRecursiveCall _Py_ClearArgcArgv _Py_ClearStandardStreamEncoding _Py_CoerceLegacyLocale _Py_Dealloc _Py_DecRef _Py_DecodeLocaleEx _Py_DisplaySourceLine _Py_DumpExtensionModules _Py_EllipsisObject DATA _Py_EncodeLocaleEx _Py_EncodeLocaleRaw _Py_FalseStruct DATA _Py_FatalErrorFormat _Py_FatalErrorFunc _Py_FatalError_TstateNULL _Py_FdIsInteractive _Py_FreeCharPArray _Py_GetAllocatedBlocks _Py_GetConfig _Py_GetConfigsAsDict _Py_GetEnv _Py_GetErrorHandler _Py_GetForceASCII _Py_GetLocaleEncoding _Py_GetLocaleEncodingObject _Py_GetLocaleconvNumeric _Py_HandleSystemExit _Py_HashBytes _Py_HashDouble _Py_HashPointer _Py_HashPointerRaw _Py_HashSecret DATA _Py_IncRef _Py_InitializeMain _Py_IsCoreInitialized _Py_IsFinalizing _Py_IsLocaleCoercionTarget _Py_LegacyLocaleDetected _Py_NewInterpreter _Py_NewReference _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_PackageContext DATA _Py_PreInitializeFromConfig _Py_PreInitializeFromPyArgv _Py_ResetForceASCII _Py_RestoreSignals _Py_SetLocaleFromEnv _Py_SetProgramFullPath _Py_SourceAsString _Py_SwappedOp DATA _Py_TrueStruct DATA _Py_UTF8_Edit_Cost _Py_UnhandledKeyboardInterrupt DATA _Py_VaBuildStack _Py_VaBuildStack_SizeT _Py_VaBuildValue_SizeT _Py_abspath _Py_add_one_to_index_C _Py_add_one_to_index_F _Py_ascii_whitespace DATA _Py_c_abs _Py_c_diff _Py_c_neg _Py_c_pow _Py_c_prod _Py_c_quot _Py_c_sum _Py_closerange _Py_convert_optional_to_ssize_t _Py_ctype_table DATA _Py_ctype_tolower DATA _Py_ctype_toupper DATA _Py_device_encoding _Py_dg_dtoa _Py_dg_freedtoa _Py_dg_infinity _Py_dg_stdnan _Py_dg_strtod _Py_dup _Py_fopen_obj _Py_fstat _Py_fstat_noraise _Py_get_env_flag _Py_get_inheritable _Py_get_osfhandle _Py_get_osfhandle_noraise _Py_get_xoption _Py_gitidentifier _Py_gitversion _Py_hashtable_clear _Py_hashtable_compare_direct _Py_hashtable_destroy _Py_hashtable_foreach _Py_hashtable_get _Py_hashtable_hash_ptr _Py_hashtable_new _Py_hashtable_new_full _Py_hashtable_set _Py_hashtable_size _Py_hashtable_steal _Py_open _Py_open_noraise _Py_open_osfhandle _Py_open_osfhandle_noraise _Py_parse_inf_or_nan _Py_path_config DATA _Py_read _Py_set_inheritable _Py_set_inheritable_async_safe _Py_stat _Py_str_to_int _Py_strhex _Py_strhex_bytes _Py_strhex_bytes_with_sep _Py_strhex_with_sep _Py_string_to_number_with_underscores _Py_tracemalloc_config DATA _Py_wfopen _Py_wgetcwd _Py_write _Py_write_noraise python3-dll-a/src/python313.def0000644000175000017500000010503114661133735017153 0ustar jamespagejamespage; ; Definition file of python313.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "python313.dll" EXPORTS PY_TIMEOUT_MAX DATA PyAIter_Check PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyAsyncGen_New PyAsyncGen_Type DATA PyBaseObject_Type DATA PyBool_FromLong PyBool_Type DATA PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_FromContiguous PyBuffer_GetPointer PyBuffer_IsContiguous PyBuffer_Release PyBuffer_SizeFromFormat PyBuffer_ToContiguous PyByteArrayIter_Type DATA PyByteArray_AsString PyByteArray_Concat PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Resize PyByteArray_Size PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyBytes_Type DATA PyCFunction_Call PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_New PyCFunction_NewEx PyCFunction_Type DATA PyCMethod_New PyCMethod_Type DATA PyCallIter_New PyCallIter_Type DATA PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCapsule_Type DATA PyCell_Get PyCell_New PyCell_Set PyCell_Type DATA PyClassMethodDescr_Type DATA PyClassMethod_New PyClassMethod_Type DATA PyCode_AddWatcher PyCode_Addr2Line PyCode_Addr2Location PyCode_ClearWatcher PyCode_GetCellvars PyCode_GetCode PyCode_GetFreevars PyCode_GetVarnames PyCode_NewEmpty PyCode_Optimize PyCode_Type DATA PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_NameReplaceErrors PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_Unregister PyCodec_XMLCharRefReplaceErrors PyCompile_OpcodeStackEffect PyCompile_OpcodeStackEffectWithJump PyComplex_AsCComplex PyComplex_FromCComplex PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyComplex_Type DATA PyConfig_Clear PyConfig_InitIsolatedConfig PyConfig_InitPythonConfig PyConfig_Read PyConfig_SetArgv PyConfig_SetBytesArgv PyConfig_SetBytesString PyConfig_SetString PyConfig_SetWideStringList PyContextToken_Type DATA PyContextVar_Get PyContextVar_New PyContextVar_Reset PyContextVar_Set PyContextVar_Type DATA PyContext_Copy PyContext_CopyCurrent PyContext_Enter PyContext_Exit PyContext_New PyContext_Type DATA PyCoro_New PyCoro_Type DATA PyDescr_IsData PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDescr_NewWrapper PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_New PyDictProxy_Type DATA PyDictRevIterItem_Type DATA PyDictRevIterKey_Type DATA PyDictRevIterValue_Type DATA PyDictValues_Type DATA PyDict_AddWatcher PyDict_Clear PyDict_ClearWatcher PyDict_Contains PyDict_ContainsString PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_GetItem PyDict_GetItemRef PyDict_GetItemString PyDict_GetItemStringRef PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_Pop PyDict_PopString PyDict_SetDefault PyDict_SetDefaultRef PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Type DATA PyDict_Unwatch PyDict_Update PyDict_Values PyDict_Watch PyEllipsis_Type DATA PyEnum_Type DATA PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_DisplayException PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_FormatUnraisable PyErr_FormatV PyErr_GetExcInfo PyErr_GetHandledException PyErr_GetRaisedException PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_ProgramTextObject PyErr_RangedSyntaxLocationObject PyErr_ResourceWarning PyErr_Restore PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetExcInfo PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetFromErrnoWithFilenameObjects PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyErr_SetHandledException PyErr_SetImportError PyErr_SetImportErrorSubclass PyErr_SetInterrupt PyErr_SetInterruptEx PyErr_SetNone PyErr_SetObject PyErr_SetRaisedException PyErr_SetString PyErr_SyntaxLocation PyErr_SyntaxLocationEx PyErr_SyntaxLocationObject PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnExplicitFormat PyErr_WarnExplicitObject PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFrameBuiltins PyEval_GetFrameGlobals PyEval_GetFrameLocals PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_MergeCompilerFlags PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_SetProfile PyEval_SetProfileAllThreads PyEval_SetTrace PyEval_SetTraceAllThreads PyEval_ThreadsInitialized PyEvent_Wait PyEvent_WaitTimed PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BaseExceptionGroup DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EncodingWarning DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IncompleteInputError DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_InterpreterError DATA PyExc_InterpreterNotFoundError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_ModuleNotFoundError DATA PyExc_NameError DATA PyExc_NotADirectoryError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_PythonFinalizationError DATA PyExc_RecursionError DATA PyExc_ReferenceError DATA PyExc_ResourceWarning DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopAsyncIteration DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TimeoutError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_WindowsError DATA PyExc_ZeroDivisionError DATA PyExceptionClass_Name PyException_GetArgs PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetArgs PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_NewStdPrinter PyFile_OpenCode PyFile_OpenCodeObject PyFile_SetOpenCodeHook PyFile_WriteObject PyFile_WriteString PyFilter_Type DATA PyFloat_AsDouble PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFloat_Pack2 PyFloat_Pack4 PyFloat_Pack8 PyFloat_Type DATA PyFloat_Unpack2 PyFloat_Unpack4 PyFloat_Unpack8 PyFrameLocalsProxy_Type DATA PyFrame_FastToLocals PyFrame_FastToLocalsWithError PyFrame_GetBack PyFrame_GetBuiltins PyFrame_GetCode PyFrame_GetGenerator PyFrame_GetGlobals PyFrame_GetLasti PyFrame_GetLineNumber PyFrame_GetLocals PyFrame_GetVar PyFrame_GetVarString PyFrame_LocalsToFast PyFrame_New PyFrame_Type DATA PyFrozenSet_New PyFrozenSet_Type DATA PyFunction_AddWatcher PyFunction_ClearWatcher PyFunction_GetAnnotations PyFunction_GetClosure PyFunction_GetCode PyFunction_GetDefaults PyFunction_GetGlobals PyFunction_GetKwDefaults PyFunction_GetModule PyFunction_New PyFunction_NewWithQualName PyFunction_SetAnnotations PyFunction_SetClosure PyFunction_SetDefaults PyFunction_SetKwDefaults PyFunction_SetVectorcall PyFunction_Type DATA PyGC_Collect PyGC_Disable PyGC_Enable PyGC_IsEnabled PyGILState_Check PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyGen_GetCode PyGen_New PyGen_NewWithQualName PyGen_Type DATA PyGetSetDescr_Type DATA PyHash_GetFuncDef PyImport_AddModule PyImport_AddModuleObject PyImport_AddModuleRef PyImport_AppendInittab PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleObject PyImport_ExecCodeModuleWithPathnames PyImport_ExtendInittab PyImport_FrozenModules DATA PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModule PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportFrozenModuleObject PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleLevelObject PyImport_ImportModuleNoBlock PyImport_Inittab DATA PyImport_ReloadModule PyIndex_Check PyInstanceMethod_Function PyInstanceMethod_New PyInstanceMethod_Type DATA PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_Get PyInterpreterState_GetDict PyInterpreterState_GetID PyInterpreterState_Head PyInterpreterState_Main PyInterpreterState_New PyInterpreterState_Next PyInterpreterState_ThreadHead PyIter_Check PyIter_Next PyIter_Send PyListIter_Type DATA PyListRevIter_Type DATA PyList_Append PyList_AsTuple PyList_Clear PyList_Extend PyList_GetItem PyList_GetItemRef PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyList_Type DATA PyLongRangeIter_Type DATA PyLong_AsDouble PyLong_AsInt PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsNativeBytes PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromNativeBytes PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnicodeObject PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromUnsignedNativeBytes PyLong_FromVoidPtr PyLong_GetInfo PyLong_Type DATA PyMap_Type DATA PyMapping_Check PyMapping_GetItemString PyMapping_GetOptionalItem PyMapping_GetOptionalItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_HasKeyStringWithError PyMapping_HasKeyWithError PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMarshal_ReadLastObjectFromFile PyMarshal_ReadLongFromFile PyMarshal_ReadObjectFromFile PyMarshal_ReadObjectFromString PyMarshal_ReadShortFromFile PyMarshal_WriteLongToFile PyMarshal_WriteObjectToFile PyMarshal_WriteObjectToString PyMem_Calloc PyMem_Free PyMem_GetAllocator PyMem_Malloc PyMem_RawCalloc PyMem_RawFree PyMem_RawMalloc PyMem_RawRealloc PyMem_Realloc PyMem_SetAllocator PyMem_SetupDebugHooks PyMemberDescr_Type DATA PyMember_GetOne PyMember_SetOne PyMemoryView_FromBuffer PyMemoryView_FromMemory PyMemoryView_FromObject PyMemoryView_GetContiguous PyMemoryView_Type DATA PyMethodDescr_Type DATA PyMethod_Function PyMethod_New PyMethod_Self PyMethod_Type DATA PyModuleDef_Init PyModuleDef_Type DATA PyModule_Add PyModule_AddFunctions PyModule_AddIntConstant PyModule_AddObject PyModule_AddObjectRef PyModule_AddStringConstant PyModule_AddType PyModule_Create2 PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetNameObject PyModule_GetState PyModule_New PyModule_NewObject PyModule_SetDocString PyModule_Type DATA PyMonitoring_EnterScope PyMonitoring_ExitScope PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMatrixMultiply PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_MatrixMultiply PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyODictItems_Type DATA PyODictIter_Type DATA PyODictKeys_Type DATA PyODictValues_Type DATA PyODict_DelItem PyODict_New PyODict_SetItem PyODict_Type DATA PyOS_AfterFork PyOS_FSPath PyOS_InputHook DATA PyOS_InterruptOccurred PyOS_Readline PyOS_ReadlineFunctionPointer DATA PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsCharBuffer PyObject_AsFileDescriptor PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_Bytes PyObject_Call PyObject_CallFinalizer PyObject_CallFinalizerFromDealloc PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallNoArgs PyObject_CallObject PyObject_CallOneArg PyObject_Calloc PyObject_CheckBuffer PyObject_CheckReadBuffer PyObject_ClearManagedDict PyObject_ClearWeakRefs PyObject_CopyData PyObject_DelAttr PyObject_DelAttrString PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_IsFinalized PyObject_GC_IsTracked PyObject_GC_Track PyObject_GC_UnTrack PyObject_GET_WEAKREFS_LISTPTR PyObject_GenericGetAttr PyObject_GenericGetDict PyObject_GenericHash PyObject_GenericSetAttr PyObject_GenericSetDict PyObject_GetAIter PyObject_GetArenaAllocator PyObject_GetAttr PyObject_GetAttrString PyObject_GetBuffer PyObject_GetItem PyObject_GetItemData PyObject_GetIter PyObject_GetOptionalAttr PyObject_GetOptionalAttrString PyObject_GetTypeData PyObject_HasAttr PyObject_HasAttrString PyObject_HasAttrStringWithError PyObject_HasAttrWithError PyObject_Hash PyObject_HashNotImplemented PyObject_IS_GC PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_LengthHint PyObject_Malloc PyObject_Not PyObject_Print PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetArenaAllocator PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PyObject_Vectorcall PyObject_VectorcallDict PyObject_VectorcallMethod PyObject_VisitManagedDict PyPickleBuffer_FromObject PyPickleBuffer_GetBuffer PyPickleBuffer_Release PyPickleBuffer_Type DATA PyPreConfig_InitIsolatedConfig PyPreConfig_InitPythonConfig PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyRefTracer_GetTracer PyRefTracer_SetTracer PyReversed_Type DATA PyRun_AnyFile PyRun_AnyFileEx PyRun_AnyFileExFlags PyRun_AnyFileFlags PyRun_File PyRun_FileEx PyRun_FileExFlags PyRun_FileFlags PyRun_InteractiveLoop PyRun_InteractiveLoopFlags PyRun_InteractiveOne PyRun_InteractiveOneFlags PyRun_InteractiveOneObject PyRun_SimpleFile PyRun_SimpleFileEx PyRun_SimpleFileExFlags PyRun_SimpleString PyRun_SimpleStringFlags PyRun_String PyRun_StringFlags PySeqIter_New PySeqIter_Type DATA PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySetIter_Type DATA PySet_Add PySet_Clear PySet_Contains PySet_Discard PySet_New PySet_Pop PySet_Size PySet_Type DATA PySlice_AdjustIndices PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PySlice_Type DATA PySlice_Unpack PyState_AddModule PyState_FindModule PyState_RemoveModule PyStaticMethod_New PyStaticMethod_Type DATA PyStatus_Error PyStatus_Exception PyStatus_Exit PyStatus_IsError PyStatus_IsExit PyStatus_NoMemory PyStatus_Ok PyStdPrinter_Type DATA PyStructSequence_GetItem PyStructSequence_InitType PyStructSequence_InitType2 PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PyStructSequence_UnnamedField DATA PySuper_Type DATA PySys_AddAuditHook PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_AddXOption PySys_Audit PySys_AuditTuple PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_GetXOptions PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_EnterTracing PyThreadState_Get PyThreadState_GetDict PyThreadState_GetFrame PyThreadState_GetID PyThreadState_GetInterpreter PyThreadState_GetUnchecked PyThreadState_LeaveTracing PyThreadState_New PyThreadState_Next PyThreadState_SetAsyncExc PyThreadState_Swap PyThread_GetInfo PyThread_ParseTimeoutArg PyThread_ReInitTLS PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_acquire_lock_timed_with_retries PyThread_allocate_lock PyThread_create_key PyThread_delete_key PyThread_delete_key_value PyThread_detach_thread PyThread_exit_thread PyThread_free_lock PyThread_get_key_value PyThread_get_stacksize PyThread_get_thread_ident PyThread_get_thread_ident_ex PyThread_get_thread_native_id PyThread_init_thread PyThread_join_thread PyThread_release_lock PyThread_set_key_value PyThread_set_stacksize PyThread_start_joinable_thread PyThread_start_new_thread PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyTime_AsSecondsDouble PyTime_Monotonic PyTime_MonotonicRaw PyTime_PerfCounter PyTime_PerfCounterRaw PyTime_Time PyTime_TimeRaw PyTraceBack_Here PyTraceBack_Print PyTraceBack_Type DATA PyTraceMalloc_Track PyTraceMalloc_Untrack PyTupleIter_Type DATA PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyTuple_Type DATA PyType_AddWatcher PyType_ClearCache PyType_ClearWatcher PyType_FromMetaclass PyType_FromModuleAndSpec PyType_FromSpec PyType_FromSpecWithBases PyType_GenericAlloc PyType_GenericNew PyType_GetDict PyType_GetFlags PyType_GetFullyQualifiedName PyType_GetModule PyType_GetModuleByDef PyType_GetModuleName PyType_GetModuleState PyType_GetName PyType_GetQualName PyType_GetSlot PyType_GetTypeDataSize PyType_IsSubtype PyType_Modified PyType_Ready PyType_SUPPORTS_WEAKREFS PyType_Type DATA PyType_Unwatch PyType_Watch PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeIter_Type DATA PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsMBCSString PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8 PyUnicode_AsUTF8AndSize PyUnicode_AsUTF8String PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_AsWideCharString PyUnicode_BuildEncodingMap PyUnicode_Compare PyUnicode_CompareWithASCIIString PyUnicode_Concat PyUnicode_Contains PyUnicode_CopyCharacters PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeCodePageStateful PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_EncodeCodePage PyUnicode_EncodeFSDefault PyUnicode_EncodeLocale PyUnicode_EqualToUTF8 PyUnicode_EqualToUTF8AndSize PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Fill PyUnicode_Find PyUnicode_FindChar PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromKindAndData PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetLength PyUnicode_GetSize PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_New PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_ReadChar PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Substring PyUnicode_Tailmatch PyUnicode_Translate PyUnicode_Type DATA PyUnicode_WriteChar PyUnstable_AtExit PyUnstable_Code_GetExtra PyUnstable_Code_New PyUnstable_Code_NewWithPosOnlyArgs PyUnstable_Code_SetExtra PyUnstable_CopyPerfMapFile PyUnstable_Eval_RequestCodeExtraIndex PyUnstable_Exc_PrepReraiseStar PyUnstable_ExecutableKinds DATA PyUnstable_GC_VisitObjects PyUnstable_InterpreterFrame_GetCode PyUnstable_InterpreterFrame_GetLasti PyUnstable_InterpreterFrame_GetLine PyUnstable_InterpreterState_GetMainModule PyUnstable_Long_CompactValue PyUnstable_Long_IsCompact PyUnstable_Object_GC_NewWithExtraData PyUnstable_PerfMapState_Fini PyUnstable_PerfMapState_Init PyUnstable_PerfTrampoline_CompileCode PyUnstable_PerfTrampoline_SetPersistAfterFork PyUnstable_Type_AssignVersionTag PyUnstable_WritePerfMapEntry PyVectorcall_Call PyVectorcall_Function PyVectorcall_NARGS PyWeakref_GetObject PyWeakref_GetRef PyWeakref_NewProxy PyWeakref_NewRef PyWideStringList_Append PyWideStringList_Insert PyWrapperDescr_Type DATA PyWrapper_New PyZip_Type DATA Py_AddPendingCall Py_AtExit Py_BuildValue Py_BytesMain Py_BytesWarningFlag DATA Py_CompileString Py_CompileStringExFlags Py_CompileStringFlags Py_CompileStringObject Py_DebugFlag DATA Py_DecRef Py_DecodeLocale Py_DontWriteBytecodeFlag DATA Py_EncodeLocale Py_EndInterpreter Py_EnterRecursiveCall Py_Exit Py_ExitStatusException Py_FatalError Py_FdIsInteractive Py_FileSystemDefaultEncodeErrors DATA Py_FileSystemDefaultEncoding DATA Py_Finalize Py_FinalizeEx Py_FrozenFlag DATA Py_GETENV Py_GenericAlias Py_GenericAliasType DATA Py_GetArgcArgv Py_GetBuildInfo Py_GetCompiler Py_GetConstant Py_GetConstantBorrowed Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_HasFileSystemDefaultEncoding DATA Py_HashPointer Py_HashRandomizationFlag DATA Py_IgnoreEnvironmentFlag DATA Py_IncRef Py_Initialize Py_InitializeEx Py_InitializeFromConfig Py_InspectFlag DATA Py_InteractiveFlag DATA Py_Is Py_IsFalse Py_IsFinalizing Py_IsInitialized Py_IsNone Py_IsTrue Py_IsolatedFlag DATA Py_LeaveRecursiveCall Py_LegacyWindowsFSEncodingFlag DATA Py_LegacyWindowsStdioFlag DATA Py_Main Py_MakePendingCalls Py_NewInterpreter Py_NewInterpreterFromConfig Py_NewRef Py_NoSiteFlag DATA Py_NoUserSiteDirectory DATA Py_OptimizeFlag DATA Py_PreInitialize Py_PreInitializeFromArgs Py_PreInitializeFromBytesArgs Py_QuietFlag DATA Py_ReprEnter Py_ReprLeave Py_RunMain Py_SetPath Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_UTF8Mode DATA Py_UnbufferedStdioFlag DATA Py_UniversalNewlineFgets Py_VaBuildValue Py_VerboseFlag DATA Py_Version DATA Py_XNewRef Py_hexdigits DATA _PyAST_Compile _PyArena_AddPyObject _PyArena_Free _PyArena_Malloc _PyArena_New _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT _PyArg_Parse_SizeT _PyArg_UnpackKeywords _PyArg_UnpackKeywordsWithVararg _PyArg_VaParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyAsyncGenASend_Type DATA _PyBuffer_ReleaseInInterpreter _PyBuffer_ReleaseInInterpreterAndRawFree _PyByteArray_empty_string DATA _PyBytesWriter_Alloc _PyBytesWriter_Dealloc _PyBytesWriter_Finish _PyBytesWriter_Init _PyBytesWriter_Prepare _PyBytesWriter_Resize _PyBytesWriter_WriteBytes _PyBytes_DecodeEscape _PyBytes_Find _PyBytes_Repeat _PyBytes_Resize _PyBytes_ReverseFind _PyCapsule_SetTraverse _PyCode_CheckLineNumber _PyCode_ConstantKey _PyCompile_Assemble _PyCompile_CleanDoc _PyCompile_CodeGen _PyCompile_GetBinaryIntrinsicName _PyCompile_GetUnaryIntrinsicName _PyCompile_OpcodeHasArg _PyCompile_OpcodeHasConst _PyCompile_OpcodeHasExc _PyCompile_OpcodeHasFree _PyCompile_OpcodeHasJump _PyCompile_OpcodeHasLocal _PyCompile_OpcodeHasName _PyCompile_OpcodeIsValid _PyCompile_OptimizeCfg _PyConfig_AsDict _PyConfig_FromDict _PyConfig_InitCompatConfig _PyContext_NewHamtForTests _PyCoro_GetAwaitableIter _PyCriticalSection2_BeginSlow _PyCriticalSection_BeginSlow _PyCriticalSection_Resume _PyCriticalSection_SuspendAll _PyCrossInterpreterData_Clear _PyCrossInterpreterData_Free _PyCrossInterpreterData_Init _PyCrossInterpreterData_InitWithSize _PyCrossInterpreterData_Lookup _PyCrossInterpreterData_New _PyCrossInterpreterData_NewObject _PyCrossInterpreterData_RegisterClass _PyCrossInterpreterData_Release _PyCrossInterpreterData_ReleaseAndRawFree _PyCrossInterpreterData_UnregisterClass _PyDeadline_Get _PyDeadline_Init _PyDict_DelItem_KnownHash _PyDict_FromItems _PyDict_GetItemStringWithError _PyDict_GetItem_KnownHash _PyDict_LoadGlobal _PyDict_MergeEx _PyDict_NewPresized _PyDict_Pop _PyDict_SetItem_KnownHash _PyDict_SetItem_Take2 _PyDict_SizeOf _PyErr_BadInternalCall _PyErr_ChainExceptions1 _PyErr_Clear _PyErr_ExceptionMatches _PyErr_Format _PyErr_FormatFromCause _PyErr_ProgramDecodedTextObject _PyErr_SetFromPyStatus _PyErr_SetKeyError _PyErr_SetString _PyEvalFramePushAndInit _PyEval_AddPendingCall _PyEval_BinaryOps DATA _PyEval_CheckExceptStarTypeValid _PyEval_CheckExceptTypeValid _PyEval_ConversionFuncs DATA _PyEval_EvalFrameDefault _PyEval_ExceptionGroupMatch _PyEval_FormatAwaitableError _PyEval_FormatExcCheckArg _PyEval_FormatExcUnbound _PyEval_FormatKwargsError _PyEval_FrameClearAndPop _PyEval_GetBuiltin _PyEval_MakePendingCalls _PyEval_MatchClass _PyEval_MatchKeys _PyEval_SetProfile _PyEval_SliceIndex _PyEval_SliceIndexNotNone _PyEval_UnpackIterable _PyEvent_IsSet _PyEvent_Notify _PyFloat_ExactDealloc _PyFrame_IsEntryFrame _PyFunction_SetVersion _PyGen_FetchStopIterationValue _PyGen_SetStopIterationValue _PyGen_yf _PyImport_ClearExtension _PyImport_FrozenBootstrap DATA _PyImport_FrozenStdlib DATA _PyImport_FrozenTest DATA _PyImport_GetModuleAttr _PyImport_GetModuleAttrString _PyImport_SetModule _PyInstructionSequence_New _PyInterpreterConfig_AsDict _PyInterpreterConfig_InitFromDict _PyInterpreterConfig_InitFromState _PyInterpreterConfig_UpdateFromDict _PyInterpreterState_FailIfRunningMain _PyInterpreterState_GetConfigCopy _PyInterpreterState_GetEvalFrameFunc _PyInterpreterState_GetIDObject _PyInterpreterState_GetWhence _PyInterpreterState_IDDecref _PyInterpreterState_IDIncref _PyInterpreterState_IDInitref _PyInterpreterState_IsReady _PyInterpreterState_IsRunningMain _PyInterpreterState_LookUpID _PyInterpreterState_LookUpIDObject _PyInterpreterState_New _PyInterpreterState_ObjectToID _PyInterpreterState_RequireIDRef _PyInterpreterState_RequiresIDRef _PyInterpreterState_SetConfig _PyInterpreterState_SetEvalFrameFunc _PyInterpreterState_SetNotRunningMain _PyInterpreterState_SetRunningMain _PyIntrinsics_BinaryFunctions DATA _PyIntrinsics_UnaryFunctions DATA _PyList_AppendTakeRefListResize _PyList_Extend _PyList_FromArraySteal _PyLong_Add _PyLong_AsByteArray _PyLong_AsTime_t _PyLong_Copy _PyLong_DigitValue DATA _PyLong_DivmodNear _PyLong_FileDescriptor_Converter _PyLong_Format _PyLong_Frexp _PyLong_FromByteArray _PyLong_FromDigits _PyLong_FromTime_t _PyLong_GCD _PyLong_Lshift _PyLong_Multiply _PyLong_New _PyLong_NumBits _PyLong_Rshift _PyLong_Sign _PyLong_Size_t_Converter _PyLong_Subtract _PyLong_UnsignedInt_Converter _PyLong_UnsignedLongLong_Converter _PyLong_UnsignedLong_Converter _PyLong_UnsignedShort_Converter _PyMem_GetCurrentAllocatorName _PyMem_Strdup _PyMonitoring_FireBranchEvent _PyMonitoring_FireCRaiseEvent _PyMonitoring_FireCReturnEvent _PyMonitoring_FireCallEvent _PyMonitoring_FireExceptionHandledEvent _PyMonitoring_FireJumpEvent _PyMonitoring_FireLineEvent _PyMonitoring_FirePyResumeEvent _PyMonitoring_FirePyReturnEvent _PyMonitoring_FirePyStartEvent _PyMonitoring_FirePyThrowEvent _PyMonitoring_FirePyUnwindEvent _PyMonitoring_FirePyYieldEvent _PyMonitoring_FireRaiseEvent _PyMonitoring_FireReraiseEvent _PyMonitoring_FireStopIterationEvent _PyMutex_LockSlow _PyMutex_UnlockSlow _PyNamespace_New _PyNone_Type DATA _PyNotImplemented_Type DATA _PyNumber_Index _PyOS_IsMainThread _PyOS_ReadlineTState DATA _PyOS_SigintEvent _PyOS_URandomNonblock _PyObject_AssertFailed _PyObject_CallFunction_SizeT _PyObject_CallMethod _PyObject_CallMethodId _PyObject_CallMethod_SizeT _PyObject_CheckCrossInterpreterData _PyObject_DebugMallocStats _PyObject_Dump _PyObject_FunctionStr _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_GenericGetAttrWithDict _PyObject_GenericSetAttrWithDict _PyObject_GetAttrId _PyObject_GetCrossInterpreterData _PyObject_GetDictPtr _PyObject_GetMethod _PyObject_GetState _PyObject_IsFreed _PyObject_LookupSpecial _PyObject_MakeTpCall _PyObject_New _PyObject_NewVar _PyObject_SetManagedDict _PyOnceFlag_CallOnceSlow _PyParkingLot_AfterFork _PyParkingLot_Park _PyParkingLot_Unpark _PyParkingLot_UnparkAll _PyParser_TokenNames DATA _PyPathConfig_ClearGlobal _PyPreConfig_InitCompatConfig _PyRWMutex_Lock _PyRWMutex_RLock _PyRWMutex_RUnlock _PyRWMutex_Unlock _PyRuntime DATA _PySemaphore_Destroy _PySemaphore_Init _PySemaphore_Wait _PySemaphore_Wakeup _PySeqLock_AbandonWrite _PySeqLock_AfterFork _PySeqLock_BeginRead _PySeqLock_EndRead _PySeqLock_LockWrite _PySeqLock_UnlockWrite _PySet_Contains _PySet_Dummy DATA _PySet_NextEntry _PySet_NextEntryRef _PySet_Update _PySlice_FromIndices _PySlice_GetLongIndices _PyStack_AsDict _PyState_AddModule _PyStaticType_FiniForExtension _PyStaticType_InitForExtension _PyStructSequence_NewType _PySuper_Lookup _PySys_GetAttr _PySys_GetSizeOf _PyThreadState_GetCurrent _PyThreadState_GetDict _PyThreadState_Init _PyThreadState_PopFrame _PyThreadState_Prealloc _PyThread_CurrentFrames _PyTime_AsLong _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_clamp _PyTime_FromLong _PyTime_FromMillisecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_MonotonicWithInfo _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyToken_OneChar _PyToken_ThreeChars _PyToken_TwoChars _PyTraceMalloc_GetTraceback _PyTraceback_Add _PyTrash_thread_deposit_object _PyTrash_thread_destroy_chain _PyTuple_FromArraySteal _PyTuple_Resize _PyType_GetDict _PyType_GetModuleByDef2 _PyType_Lookup _PyType_LookupRef _PyType_Name _PyUnicodeWriter_Dealloc _PyUnicodeWriter_Finish _PyUnicodeWriter_Init _PyUnicodeWriter_PrepareInternal _PyUnicodeWriter_PrepareKindInternal _PyUnicodeWriter_WriteASCIIString _PyUnicodeWriter_WriteChar _PyUnicodeWriter_WriteLatin1String _PyUnicodeWriter_WriteStr _PyUnicodeWriter_WriteSubstring _PyUnicode_AsUTF8NoNUL _PyUnicode_AsUTF8String _PyUnicode_CheckConsistency _PyUnicode_Copy _PyUnicode_DecodeUnicodeEscapeInternal _PyUnicode_EncodeUTF16 _PyUnicode_EncodeUTF32 _PyUnicode_Equal _PyUnicode_EqualToASCIIString _PyUnicode_ExactDealloc _PyUnicode_FromId _PyUnicode_IsAlpha _PyUnicode_IsDecimalDigit _PyUnicode_IsDigit _PyUnicode_IsLinebreak _PyUnicode_IsLowercase _PyUnicode_IsNumeric _PyUnicode_IsPrintable _PyUnicode_IsTitlecase _PyUnicode_IsUppercase _PyUnicode_IsWhitespace _PyUnicode_JoinArray _PyUnicode_ScanIdentifier _PyUnicode_ToDecimalDigit _PyUnicode_ToDigit _PyUnicode_ToLowercase _PyUnicode_ToNumeric _PyUnicode_ToTitlecase _PyUnicode_ToUppercase _PyUnicode_TransformDecimalAndSpaceToASCII _PyUnion_Type DATA _PyWeakref_CallableProxyType DATA _PyWeakref_ClearRef _PyWeakref_IsDead _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _PyXI_ApplyCapturedException _PyXI_ApplyError _PyXI_ApplyNamespace _PyXI_ClearExcInfo _PyXI_EndInterpreter _PyXI_Enter _PyXI_ExcInfoAsObject _PyXI_Exit _PyXI_FillNamespaceFromDict _PyXI_FormatExcInfo _PyXI_FreeNamespace _PyXI_HasCapturedException _PyXI_InitExcInfo _PyXI_NamespaceFromNames _PyXI_NewInterpreter _Py_BreakPoint _Py_BuildValue_SizeT _Py_CheckFunctionResult _Py_CheckRecursiveCall _Py_Dealloc _Py_DecRef _Py_DecodeLocaleEx _Py_DisplaySourceLine _Py_EllipsisObject DATA _Py_EncodeLocaleEx _Py_FalseStruct DATA _Py_FatalErrorFunc _Py_FatalRefcountErrorFunc _Py_GetConfig _Py_GetConfigsAsDict _Py_GetErrorHandler _Py_Get_Getpath_CodeObject _Py_HandlePending _Py_HashBytes _Py_HashDouble _Py_HashSecret DATA _Py_IncRef _Py_InitializeMain _Py_IsInterpreterFinalizing _Py_IsValidFD _Py_MakeCoro _Py_NewReference _Py_NewReferenceNoTotal _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_RestoreSignals _Py_ResurrectReference _Py_SetLocaleFromEnv _Py_SetRefcnt _Py_SwappedOp DATA _Py_TrueStruct DATA _Py_UTF8_Edit_Cost _Py_UniversalNewlineFgetsWithSize _Py_VaBuildValue_SizeT _Py_ascii_whitespace DATA _Py_c_abs _Py_c_diff _Py_c_neg _Py_c_pow _Py_c_prod _Py_c_quot _Py_c_sum _Py_closerange _Py_convert_optional_to_ssize_t _Py_ctype_table DATA _Py_ctype_tolower DATA _Py_ctype_toupper DATA _Py_dup _Py_fopen_obj _Py_fstat _Py_fstat_noraise _Py_get_osfhandle _Py_hashtable_clear _Py_hashtable_compare_direct _Py_hashtable_destroy _Py_hashtable_foreach _Py_hashtable_get _Py_hashtable_hash_ptr _Py_hashtable_len _Py_hashtable_new _Py_hashtable_new_full _Py_hashtable_set _Py_hashtable_size _Py_hashtable_steal _Py_normpath _Py_open _Py_open_noraise _Py_set_inheritable _Py_set_inheritable_async_safe _Py_stat _Py_strhex _Py_strhex_bytes_with_sep _Py_union_type_or _Py_write _Py_write_noraise python3-dll-a/src/python3.def0000644000175000017500000004472014661133735017016 0ustar jamespagejamespageLIBRARY python3.dll EXPORTS PyType_FromSpec PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyBool_FromLong PyByteArray_AsString PyByteArray_Concat PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Resize PyByteArray_Size PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyCFunction_Call PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_NewEx PyCallIter_New PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_XMLCharRefReplaceErrors PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDictProxy_New PyDict_Clear PyDict_Contains PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_GetItem PyDict_GetItemString PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Update PyDict_Values PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_DisplayException PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_Restore PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetInterrupt PyErr_SetNone PyErr_SetObject PyErr_SetString PyErr_SyntaxLocation PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_ThreadsInitialized PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_WriteObject PyFile_WriteString PyFloat_AsDouble PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFrozenSet_New PyGC_Collect PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyImport_AddModule PyImport_AppendInittab PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleWithPathnames PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleNoBlock PyImport_ReloadModule PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_New PyIter_Next PyList_Append PyList_AsTuple PyList_GetItem PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyLong_AsDouble PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromVoidPtr PyLong_GetInfo PyMapping_Check PyMapping_GetItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMem_Free PyMem_Malloc PyMem_Realloc PyMemoryView_FromObject PyMemoryView_GetContiguous PyModule_AddIntConstant PyModule_AddObject PyModule_AddStringConstant PyModule_Create2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetState PyModule_New PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyOS_AfterFork PyOS_InterruptOccurred PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsFileDescriptor PyObject_Bytes PyObject_Call PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallObject PyObject_ClearWeakRefs PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_Track PyObject_GC_UnTrack PyObject_GenericGetAttr PyObject_GenericSetAttr PyObject_GetAttr PyObject_GetAttrString PyObject_GetItem PyObject_GetIter PyObject_HasAttr PyObject_HasAttrString PyObject_Hash PyObject_HashNotImplemented PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_Malloc PyObject_Not PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PySeqIter_New PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySet_Add PySet_Clear PySet_Contains PySet_Discard PySet_New PySet_Pop PySet_Size PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PyState_FindModule PyStructSequence_GetItem PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_Get PyThreadState_GetDict PyThreadState_New PyThreadState_SetAsyncExc PyThreadState_Swap PyTraceBack_Here PyTraceBack_Print PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyType_ClearCache PyType_GenericAlloc PyType_GenericNew PyType_GetFlags PyType_IsSubtype PyType_Modified PyType_Ready PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8String PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_Compare PyUnicode_Concat PyUnicode_Contains PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Find PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetSize PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Tailmatch PyUnicode_Translate PyUnicode_BuildEncodingMap PyUnicode_CompareWithASCIIString PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_EncodeFSDefault PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyWeakref_GetObject PyWeakref_NewProxy PyWeakref_NewRef PyWrapper_New Py_AddPendingCall Py_AtExit Py_BuildValue Py_CompileString Py_DecRef Py_EndInterpreter Py_Exit Py_FatalError Py_Finalize Py_GetBuildInfo Py_GetCompiler Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_IncRef Py_Initialize Py_InitializeEx Py_IsInitialized Py_Main Py_MakePendingCalls Py_NewInterpreter Py_ReprEnter Py_ReprLeave Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_VaBuildValue _PyErr_BadInternalCall _PyObject_CallFunction_SizeT _PyObject_CallMethod_SizeT _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_New _PyObject_NewVar _PyState_AddModule _PyThreadState_Init _PyThreadState_Prealloc _Py_BuildValue_SizeT _Py_CheckRecursiveCall _Py_Dealloc _Py_VaBuildValue_SizeT PyObject_AsCharBuffer PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_CheckReadBuffer PyMarshal_ReadObjectFromString PyMarshal_WriteObjectToString PyMember_GetOne PyMember_SetOne PyThread_ReInitTLS PyThread_create_key PyThread_delete_key PyThread_set_key_value PyThread_get_key_value PyThread_delete_key_value PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_allocate_lock PyThread_exit_thread PyThread_free_lock PyThread_get_stacksize PyThread_get_thread_ident PyThread_get_thread_native_id PyThread_init_thread PyThread_release_lock PyThread_set_stacksize PyThread_start_new_thread PyState_AddModule PyState_RemoveModule PyType_FromSpecWithBases _PyArg_Parse_SizeT _PyArg_ParseTuple_SizeT _PyArg_ParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyArg_VaParseTupleAndKeywords_SizeT PyThread_GetInfo PyCFunction_New PyType_GetSlot PyErr_FormatV PyModuleDef_Init Py_FinalizeEx PyOS_FSPath PyErr_ResourceWarning PyErr_SetImportErrorSubclass PyCodec_NameReplaceErrors PyErr_GetExcInfo PyErr_SetExcInfo PyErr_SetFromErrnoWithFilenameObjects PyErr_SetImportError PyErr_SyntaxLocationEx PyImport_AddModuleObject PyImport_ExecCodeModuleObject PyImport_ImportFrozenModuleObject PyImport_ImportModuleLevelObject PyMem_Calloc PyMemoryView_FromMemory PyModule_AddFunctions PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetNameObject PyModule_NewObject PyModule_SetDocString PyNumber_InPlaceMatrixMultiply PyNumber_MatrixMultiply PyObject_Calloc PyObject_GenericSetDict PySys_AddXOption PySys_GetXOptions PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsWideCharString PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_EncodeLocale PyUnicode_FindChar PyUnicode_GetLength PyUnicode_ReadChar PyUnicode_Substring PyUnicode_WriteChar Py_DecodeLocale Py_EncodeLocale Py_SetPath PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyOS_CheckStack PyUnicode_AsMBCSString PyUnicode_DecodeCodePageStateful PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_EncodeCodePage PySlice_AdjustIndices PySlice_Unpack PyInterpreterState_GetID PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyOS_BeforeFork PyOS_AfterFork_Parent PyOS_AfterFork_Child PyImport_GetModule PyExceptionClass_Name PyIndex_Check PyIter_Check PyInterpreterState_GetDict Py_BytesMain Py_EnterRecursiveCall Py_LeaveRecursiveCall Py_GenericAlias PyCMethod_New PyInterpreterState_Get PyObject_GC_IsFinalized PyObject_GC_IsTracked Py_GetArgcArgv PyIter_Send PyUnicode_AsUTF8AndSize PyObject_GenericGetDict Py_NewRef Py_XNewRef PyModule_AddType PyType_FromModuleAndSpec PyType_GetModule PyType_GetModuleState PyFrame_GetLineNumber PyFrame_GetCode PyObject_CallNoArgs PyThreadState_GetFrame PyThreadState_GetID PyThreadState_GetInterpreter PyModule_AddObjectRef PyCodec_Unregister PyErr_SetInterruptEx Py_Is Py_IsTrue Py_IsFalse Py_IsNone _Py_IncRef _Py_DecRef PyAIter_Check PyObject_GetAIter _Py_NegativeRefcount PyGC_Disable PyGC_Enable PyGC_IsEnabled PyType_GetName PyType_GetQualName PyObject_CheckBuffer PyObject_GetBuffer PyBuffer_GetPointer PyBuffer_SizeFromFormat PyBuffer_ToContiguous PyBuffer_FromContiguous PyObject_CopyData PyBuffer_IsContiguous PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_Release PyMemoryView_FromBuffer PyErr_GetHandledException PyErr_SetHandledException PyType_FromMetaclass PyVectorcall_NARGS PyVectorcall_Call PyErr_GetRaisedException PyErr_SetRaisedException PyException_GetArgs PyException_SetArgs PyObject_Vectorcall PyObject_VectorcallMethod PyObject_GetTypeData PyType_GetTypeDataSize PyImport_AddModuleRef PyWeakref_GetRef PyObject_DelAttr PyObject_DelAttrString PyObject_GetOptionalAttr PyObject_GetOptionalAttrString PyMapping_GetOptionalItem PyMapping_GetOptionalItemString PyModule_Add PyDict_GetItemRef PyDict_GetItemStringRef PyLong_AsInt PyObject_HasAttrWithError PyObject_HasAttrStringWithError PyMapping_HasKeyWithError PyMapping_HasKeyStringWithError Py_IsFinalizing PyUnicode_EqualToUTF8 PyUnicode_EqualToUTF8AndSize PyMem_RawMalloc PyMem_RawCalloc PyMem_RawRealloc PyMem_RawFree PySys_Audit PySys_AuditTuple _Py_SetRefcnt PyList_GetItemRef PyType_GetFullyQualifiedName PyType_GetModuleName Py_GetConstant Py_GetConstantBorrowed PyType_GetModuleByDef PyEval_GetFrameBuiltins PyEval_GetFrameGlobals PyEval_GetFrameLocals Py_TYPE PyBaseObject_Type DATA PyBool_Type DATA PyByteArrayIter_Type DATA PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_Type DATA PyCFunction_Type DATA PyCallIter_Type DATA PyCapsule_Type DATA PyClassMethodDescr_Type DATA PyComplex_Type DATA PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_Type DATA PyDictValues_Type DATA PyDict_Type DATA PyEllipsis_Type DATA PyEnum_Type DATA PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BaseExceptionGroup DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_NameError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_ReferenceError DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_ZeroDivisionError DATA PyFilter_Type DATA PyFloat_Type DATA PyFrozenSet_Type DATA PyGetSetDescr_Type DATA PyListIter_Type DATA PyListRevIter_Type DATA PyList_Type DATA PyLongRangeIter_Type DATA PyLong_Type DATA PyMap_Type DATA PyMemberDescr_Type DATA PyMemoryView_Type DATA PyMethodDescr_Type DATA PyModule_Type DATA PyOS_InputHook DATA PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyReversed_Type DATA PySeqIter_Type DATA PySetIter_Type DATA PySet_Type DATA PySlice_Type DATA PySuper_Type DATA PyTraceBack_Type DATA PyTupleIter_Type DATA PyTuple_Type DATA PyType_Type DATA PyUnicodeIter_Type DATA PyUnicode_Type DATA PyWrapperDescr_Type DATA PyZip_Type DATA Py_FileSystemDefaultEncoding DATA Py_HasFileSystemDefaultEncoding DATA _PyWeakref_CallableProxyType DATA _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _Py_EllipsisObject DATA _Py_FalseStruct DATA _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_SwappedOp DATA _Py_TrueStruct DATA PyModuleDef_Type DATA PyExc_ModuleNotFoundError DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_NotADirectoryError DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_RecursionError DATA PyExc_ResourceWarning DATA PyExc_StopAsyncIteration DATA PyExc_TimeoutError DATA PyExc_WindowsError DATA Py_UTF8Mode DATA PyDictRevIterItem_Type DATA PyDictRevIterKey_Type DATA PyDictRevIterValue_Type DATA Py_GenericAliasType DATA Py_FileSystemDefaultEncodeErrors DATA PyExc_EncodingWarning DATA _Py_RefTotal DATA PyStructSequence_UnnamedField DATA Py_Version DATA python3-dll-a/src/libpypy3-c.def0000644000175000017500000005226214661133735017405 0ustar jamespagejamespage; ; Definition file of libpypy3-c.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "libpypy3-c.dll" EXPORTS HPyInit__debug PyPyAnySet_Check PyPyAnySet_CheckExact PyPyArg_Parse PyPyArg_ParseTuple PyPyArg_ParseTupleAndKeywords PyPyArg_UnpackTuple PyPyArg_VaParse PyPyArg_VaParseTupleAndKeywords PyPyBaseObject_Type DATA PyPyBool_FromLong PyPyBool_Type DATA PyPyBuffer_FillInfo PyPyBuffer_FromContiguous PyPyBuffer_GetPointer PyPyBuffer_IsContiguous PyPyBuffer_Release PyPyBuffer_ToContiguous PyPyBufferable_Type DATA PyPyByteArray_AsString PyPyByteArray_Check PyPyByteArray_CheckExact PyPyByteArray_Concat PyPyByteArray_FromObject PyPyByteArray_FromStringAndSize PyPyByteArray_Resize PyPyByteArray_Size PyPyByteArray_Type DATA PyPyBytes_AS_STRING PyPyBytes_AsString PyPyBytes_AsStringAndSize PyPyBytes_Concat PyPyBytes_ConcatAndDel PyPyBytes_FromFormat PyPyBytes_FromFormatV PyPyBytes_FromObject PyPyBytes_FromString PyPyBytes_FromStringAndSize PyPyBytes_Size PyPyBytes_Type DATA PyPyCFunction_Call PyPyCFunction_Check PyPyCFunction_GetFunction PyPyCFunction_NewEx PyPyCFunction_Type DATA PyPyCallIter_New PyPyCallable_Check PyPyCapsule_GetContext PyPyCapsule_GetDestructor PyPyCapsule_GetName PyPyCapsule_GetPointer PyPyCapsule_Import PyPyCapsule_IsValid PyPyCapsule_New PyPyCapsule_SetContext PyPyCapsule_SetDestructor PyPyCapsule_SetName PyPyCapsule_SetPointer PyPyCapsule_Type DATA PyPyCell_Type DATA PyPyClassMethodDescr_Type DATA PyPyClassMethod_New PyPyClassMethod_Type DATA PyPyCode_Addr2Line PyPyCode_Check PyPyCode_CheckExact PyPyCode_GetNumFree PyPyCode_New PyPyCode_NewEmpty PyPyCodec_Decode PyPyCodec_Decoder PyPyCodec_Encode PyPyCodec_Encoder PyPyCodec_IncrementalDecoder PyPyCodec_IncrementalEncoder PyPyComplex_AsCComplex PyPyComplex_Check PyPyComplex_CheckExact PyPyComplex_FromCComplex PyPyComplex_FromDoubles PyPyComplex_ImagAsDouble PyPyComplex_RealAsDouble PyPyComplex_Type DATA PyPyContextVar_Get PyPyContextVar_New PyPyContextVar_Set PyPyCoro_Check PyPyCoro_CheckExact PyPyDateTimeAPI DATA PyPyDateTime_Check PyPyDateTime_CheckExact PyPyDateTime_DATE_GET_HOUR PyPyDateTime_DATE_GET_MICROSECOND PyPyDateTime_DATE_GET_MINUTE PyPyDateTime_DATE_GET_SECOND PyPyDateTime_DELTA_GET_DAYS PyPyDateTime_DELTA_GET_MICROSECONDS PyPyDateTime_DELTA_GET_SECONDS PyPyDateTime_FromTimestamp PyPyDateTime_GET_DAY PyPyDateTime_GET_FOLD PyPyDateTime_GET_MONTH PyPyDateTime_GET_YEAR PyPyDateTime_TIME_GET_FOLD PyPyDateTime_TIME_GET_HOUR PyPyDateTime_TIME_GET_MICROSECOND PyPyDateTime_TIME_GET_MINUTE PyPyDateTime_TIME_GET_SECOND PyPyDate_Check PyPyDate_CheckExact PyPyDate_FromTimestamp PyPyDelta_Check PyPyDelta_CheckExact PyPyDescr_NewClassMethod PyPyDescr_NewGetSet PyPyDescr_NewMethod PyPyDictKeys_Type DATA PyPyDictProxy_Check PyPyDictProxy_CheckExact PyPyDictProxy_New PyPyDictProxy_Type DATA PyPyDictValues_Type DATA PyPyDict_Clear PyPyDict_Contains PyPyDict_Copy PyPyDict_DelItem PyPyDict_DelItemString PyPyDict_GetItem PyPyDict_GetItemString PyPyDict_GetItemWithError PyPyDict_Items PyPyDict_Keys PyPyDict_Merge PyPyDict_New PyPyDict_Next PyPyDict_SetDefault PyPyDict_SetItem PyPyDict_SetItemString PyPyDict_Size PyPyDict_Type DATA PyPyDict_Update PyPyDict_Values PyPyErr_BadArgument PyPyErr_BadInternalCall PyPyErr_CheckSignals PyPyErr_Clear PyPyErr_Display PyPyErr_ExceptionMatches PyPyErr_Fetch PyPyErr_Format PyPyErr_GetExcInfo PyPyErr_GivenExceptionMatches PyPyErr_NewException PyPyErr_NewExceptionWithDoc PyPyErr_NoMemory PyPyErr_NormalizeException PyPyErr_Occurred PyPyErr_Print PyPyErr_PrintEx PyPyErr_Restore PyPyErr_SetExcInfo PyPyErr_SetFromErrno PyPyErr_SetFromErrnoWithFilename PyPyErr_SetFromErrnoWithFilenameObject PyPyErr_SetFromErrnoWithFilenameObjects PyPyErr_SetFromWindowsErr PyPyErr_SetInterrupt PyPyErr_SetNone PyPyErr_SetObject PyPyErr_SetString PyPyErr_Warn PyPyErr_WarnEx PyPyErr_WarnExplicit PyPyErr_WarnFormat PyPyErr_WriteUnraisable PyPyEval_AcquireThread PyPyEval_CallFunction PyPyEval_CallMethod PyPyEval_CallObjectWithKeywords PyPyEval_EvalCode PyPyEval_GetBuiltins PyPyEval_GetFrame PyPyEval_GetGlobals PyPyEval_GetLocals PyPyEval_InitThreads PyPyEval_MergeCompilerFlags PyPyEval_ReleaseThread PyPyEval_RestoreThread PyPyEval_SaveThread PyPyEval_ThreadsInitialized PyPyExc_ArithmeticError DATA PyPyExc_AssertionError DATA PyPyExc_AttributeError DATA PyPyExc_BaseException DATA PyPyExc_BlockingIOError DATA PyPyExc_BrokenPipeError DATA PyPyExc_BufferError DATA PyPyExc_BytesWarning DATA PyPyExc_ChildProcessError DATA PyPyExc_ConnectionAbortedError DATA PyPyExc_ConnectionError DATA PyPyExc_ConnectionRefusedError DATA PyPyExc_ConnectionResetError DATA PyPyExc_DeprecationWarning DATA PyPyExc_EOFError DATA PyPyExc_Exception DATA PyPyExc_FileExistsError DATA PyPyExc_FileNotFoundError DATA PyPyExc_FloatingPointError DATA PyPyExc_FutureWarning DATA PyPyExc_GeneratorExit DATA PyPyExc_ImportError DATA PyPyExc_ImportWarning DATA PyPyExc_IndentationError DATA PyPyExc_IndexError DATA PyPyExc_InterruptedError DATA PyPyExc_IsADirectoryError DATA PyPyExc_KeyError DATA PyPyExc_KeyboardInterrupt DATA PyPyExc_LookupError DATA PyPyExc_MemoryError DATA PyPyExc_ModuleNotFoundError DATA PyPyExc_NameError DATA PyPyExc_NotADirectoryError DATA PyPyExc_NotImplementedError DATA PyPyExc_OSError DATA PyPyExc_OverflowError DATA PyPyExc_PendingDeprecationWarning DATA PyPyExc_PermissionError DATA PyPyExc_ProcessLookupError DATA PyPyExc_RecursionError DATA PyPyExc_ReferenceError DATA PyPyExc_ResourceWarning DATA PyPyExc_RuntimeError DATA PyPyExc_RuntimeWarning DATA PyPyExc_StopAsyncIteration DATA PyPyExc_StopIteration DATA PyPyExc_SyntaxError DATA PyPyExc_SyntaxWarning DATA PyPyExc_SystemError DATA PyPyExc_SystemExit DATA PyPyExc_TabError DATA PyPyExc_TimeoutError DATA PyPyExc_TypeError DATA PyPyExc_UnboundLocalError DATA PyPyExc_UnicodeDecodeError DATA PyPyExc_UnicodeEncodeError DATA PyPyExc_UnicodeError DATA PyPyExc_UnicodeTranslateError DATA PyPyExc_UnicodeWarning DATA PyPyExc_UserWarning DATA PyPyExc_ValueError DATA PyPyExc_Warning DATA PyPyExc_ZeroDivisionError DATA PyPyExceptionInstance_Class PyPyException_GetCause PyPyException_GetContext PyPyException_GetTraceback PyPyException_SetCause PyPyException_SetContext PyPyException_SetTraceback PyPyFile_FromFd PyPyFile_FromString PyPyFile_GetLine PyPyFile_WriteObject PyPyFile_WriteString PyPyFloat_AS_DOUBLE PyPyFloat_AsDouble PyPyFloat_FromDouble PyPyFloat_FromString PyPyFloat_Type DATA PyPyFrame_New PyPyFrozenSet_Check PyPyFrozenSet_CheckExact PyPyFrozenSet_New PyPyFrozenSet_Type DATA PyPyFunction_Check PyPyFunction_CheckExact PyPyFunction_GetCode PyPyFunction_Type DATA PyPyGILState_Check PyPyGILState_Ensure PyPyGILState_Release PyPyGen_Check PyPyGen_CheckExact PyPyGetSetDescr_Type DATA PyPyImport_AddModule PyPyImport_ExecCodeModule PyPyImport_ExecCodeModuleEx PyPyImport_GetModule PyPyImport_GetModuleDict PyPyImport_Import PyPyImport_ImportModule PyPyImport_ImportModuleLevelObject PyPyImport_ImportModuleNoBlock PyPyImport_ReloadModule PyPyIndex_Check PyPyInstanceMethod_Check PyPyInstanceMethod_Function PyPyInstanceMethod_GET_FUNCTION PyPyInstanceMethod_New PyPyInstanceMethod_Type DATA PyPyInterpreterState_GetID PyPyInterpreterState_Head PyPyInterpreterState_Next PyPyIter_Check PyPyIter_Next PyPyList_Append PyPyList_AsTuple PyPyList_GET_ITEM PyPyList_GET_SIZE PyPyList_GetItem PyPyList_GetSlice PyPyList_Insert PyPyList_New PyPyList_Reverse PyPyList_SET_ITEM PyPyList_SetItem PyPyList_SetSlice PyPyList_Size PyPyList_Sort PyPyList_Type DATA PyPyLong_AsDouble PyPyLong_AsLong PyPyLong_AsLongAndOverflow PyPyLong_AsLongLong PyPyLong_AsLongLongAndOverflow PyPyLong_AsSize_t PyPyLong_AsSsize_t PyPyLong_AsUnsignedLong PyPyLong_AsUnsignedLongLong PyPyLong_AsUnsignedLongLongMask PyPyLong_AsUnsignedLongMask PyPyLong_AsVoidPtr PyPyLong_FromDouble PyPyLong_FromLong PyPyLong_FromLongLong PyPyLong_FromSize_t PyPyLong_FromSsize_t PyPyLong_FromString PyPyLong_FromUnicode PyPyLong_FromUnicodeObject PyPyLong_FromUnsignedLong PyPyLong_FromUnsignedLongLong PyPyLong_FromVoidPtr PyPyLong_Type DATA PyPyMapping_Check PyPyMapping_GetItemString PyPyMapping_HasKey PyPyMapping_HasKeyString PyPyMapping_Items PyPyMapping_Keys PyPyMapping_Length PyPyMapping_SetItemString PyPyMapping_Size PyPyMapping_Values PyPyMarshal_ReadObjectFromString PyPyMarshal_WriteObjectToString PyPyMem_Calloc PyPyMem_Free PyPyMem_Malloc PyPyMem_RawCalloc PyPyMem_RawFree PyPyMem_RawMalloc PyPyMem_RawRealloc PyPyMem_Realloc PyPyMemberDescr_Type DATA PyPyMember_GetOne PyPyMember_SetOne PyPyMemoryView_Check PyPyMemoryView_CheckExact PyPyMemoryView_FromBuffer PyPyMemoryView_FromMemory PyPyMemoryView_FromObject PyPyMemoryView_GetContiguous PyPyMemoryView_Type DATA PyPyMethodDescr_Check PyPyMethodDescr_CheckExact PyPyMethodDescr_Type DATA PyPyMethod_Check PyPyMethod_CheckExact PyPyMethod_Function PyPyMethod_New PyPyMethod_Self PyPyMethod_Type DATA PyPyModuleDef_Init PyPyModule_AddFunctions PyPyModule_AddIntConstant PyPyModule_AddObject PyPyModule_AddStringConstant PyPyModule_Check PyPyModule_CheckExact PyPyModule_Create2 PyPyModule_ExecDef PyPyModule_GetDef PyPyModule_GetDict PyPyModule_GetName PyPyModule_GetState PyPyModule_New PyPyModule_NewObject PyPyModule_Type DATA PyPyNumber_Absolute PyPyNumber_Add PyPyNumber_And PyPyNumber_AsSsize_t PyPyNumber_Check PyPyNumber_Divide PyPyNumber_Divmod PyPyNumber_Float PyPyNumber_FloorDivide PyPyNumber_InPlaceAdd PyPyNumber_InPlaceAnd PyPyNumber_InPlaceDivide PyPyNumber_InPlaceFloorDivide PyPyNumber_InPlaceLshift PyPyNumber_InPlaceMatrixMultiply PyPyNumber_InPlaceMultiply PyPyNumber_InPlaceOr PyPyNumber_InPlacePower PyPyNumber_InPlaceRemainder PyPyNumber_InPlaceRshift PyPyNumber_InPlaceSubtract PyPyNumber_InPlaceTrueDivide PyPyNumber_InPlaceXor PyPyNumber_Index PyPyNumber_Invert PyPyNumber_Long PyPyNumber_Lshift PyPyNumber_MatrixMultiply PyPyNumber_Multiply PyPyNumber_Negative PyPyNumber_Or PyPyNumber_Positive PyPyNumber_Power PyPyNumber_Remainder PyPyNumber_Rshift PyPyNumber_Subtract PyPyNumber_ToBase PyPyNumber_TrueDivide PyPyNumber_Xor PyPyOS_AfterFork PyPyOS_FSPath PyPyOS_InputHook DATA PyPyOS_InterruptOccurred PyPyOS_double_to_string PyPyOS_getsig PyPyOS_setsig PyPyOS_snprintf PyPyOS_string_to_double PyPyOS_vsnprintf PyPyObject_ASCII PyPyObject_AsCharBuffer PyPyObject_AsFileDescriptor PyPyObject_AsReadBuffer PyPyObject_AsWriteBuffer PyPyObject_Bytes PyPyObject_Call PyPyObject_CallFinalizerFromDealloc PyPyObject_CallFunction PyPyObject_CallFunctionObjArgs PyPyObject_CallMethod PyPyObject_CallMethodObjArgs PyPyObject_CallObject PyPyObject_Calloc PyPyObject_CheckReadBuffer PyPyObject_ClearWeakRefs PyPyObject_Del PyPyObject_DelAttr PyPyObject_DelAttrString PyPyObject_DelItem PyPyObject_DelItemString PyPyObject_Dir PyPyObject_Format PyPyObject_Free PyPyObject_GC_Del PyPyObject_GenericGetAttr PyPyObject_GenericGetDict PyPyObject_GenericSetAttr PyPyObject_GenericSetDict PyPyObject_GetAttr PyPyObject_GetAttrString PyPyObject_GetBuffer PyPyObject_GetItem PyPyObject_GetIter PyPyObject_HasAttr PyPyObject_HasAttrString PyPyObject_Hash PyPyObject_HashNotImplemented PyPyObject_Init PyPyObject_InitVar PyPyObject_IsInstance PyPyObject_IsSubclass PyPyObject_IsTrue PyPyObject_LengthHint PyPyObject_Malloc PyPyObject_Not PyPyObject_Print PyPyObject_Realloc PyPyObject_Repr PyPyObject_RichCompare PyPyObject_RichCompareBool PyPyObject_SelfIter PyPyObject_SetAttr PyPyObject_SetAttrString PyPyObject_SetItem PyPyObject_Size PyPyObject_Str PyPyObject_Type PyPyObject_Unicode PyPyProperty_Type DATA PyPyRange_Type DATA PyPyReversed_Type DATA PyPyRun_File PyPyRun_SimpleString PyPyRun_String PyPyRun_StringFlags PyPySeqIter_New PyPySequence_Check PyPySequence_Concat PyPySequence_Contains PyPySequence_DelItem PyPySequence_DelSlice PyPySequence_Fast PyPySequence_Fast_GET_ITEM PyPySequence_Fast_GET_SIZE PyPySequence_Fast_ITEMS PyPySequence_GetItem PyPySequence_GetSlice PyPySequence_ITEM PyPySequence_InPlaceConcat PyPySequence_InPlaceRepeat PyPySequence_Index PyPySequence_Length PyPySequence_List PyPySequence_Repeat PyPySequence_SetItem PyPySequence_SetSlice PyPySequence_Size PyPySequence_Tuple PyPySet_Add PyPySet_Check PyPySet_CheckExact PyPySet_Clear PyPySet_Contains PyPySet_Discard PyPySet_GET_SIZE PyPySet_New PyPySet_Pop PyPySet_Size PyPySet_Type DATA PyPySlice_GetIndices PyPySlice_GetIndicesEx PyPySlice_New PyPySlice_Type DATA PyPySlice_Unpack PyPyStaticMethod_New PyPyStaticMethod_Type DATA PyPyStructSequence_GetItem PyPyStructSequence_InitType PyPyStructSequence_InitType2 PyPyStructSequence_New PyPyStructSequence_NewType PyPyStructSequence_SetItem PyPyStructSequence_UnnamedField DATA PyPySys_GetObject PyPySys_SetObject PyPySys_WriteStderr PyPySys_WriteStdout PyPyTZInfo_Check PyPyTZInfo_CheckExact PyPyThreadState_Clear PyPyThreadState_Delete PyPyThreadState_DeleteCurrent PyPyThreadState_Get PyPyThreadState_GetDict PyPyThreadState_New PyPyThreadState_SetAsyncExc PyPyThreadState_Swap PyPyThread_ReInitTLS PyPyThread_acquire_lock PyPyThread_allocate_lock PyPyThread_create_key PyPyThread_delete_key PyPyThread_delete_key_value PyPyThread_exit_thread PyPyThread_free_lock PyPyThread_get_key_value PyPyThread_get_thread_ident PyPyThread_init_thread PyPyThread_release_lock PyPyThread_set_key_value PyPyThread_start_new_thread PyPyTime_Check PyPyTime_CheckExact PyPyTraceBack_Check PyPyTraceBack_Here PyPyTraceBack_Print PyPyTraceBack_Type DATA PyPyTraceMalloc_Track PyPyTraceMalloc_Untrack PyPyTuple_GetItem PyPyTuple_GetSlice PyPyTuple_New PyPyTuple_Pack PyPyTuple_SetItem PyPyTuple_Size PyPyTuple_Type DATA PyPyType_FromSpec PyPyType_FromSpecWithBases PyPyType_GenericAlloc PyPyType_GenericNew PyPyType_GetSlot PyPyType_IsSubtype PyPyType_Modified PyPyType_Ready PyPyType_Type DATA PyPyUnicode_Append PyPyUnicode_AppendAndDel PyPyUnicode_AsASCIIString PyPyUnicode_AsEncodedObject PyPyUnicode_AsEncodedString PyPyUnicode_AsLatin1String PyPyUnicode_AsMBCSString PyPyUnicode_AsUCS4 PyPyUnicode_AsUCS4Copy PyPyUnicode_AsUTF16String PyPyUnicode_AsUTF32String PyPyUnicode_AsUTF8 PyPyUnicode_AsUTF8AndSize PyPyUnicode_AsUTF8String PyPyUnicode_AsUnicode PyPyUnicode_AsUnicodeAndSize PyPyUnicode_AsUnicodeEscapeString PyPyUnicode_AsWideChar PyPyUnicode_AsWideCharString PyPyUnicode_Check PyPyUnicode_CheckExact PyPyUnicode_Compare PyPyUnicode_CompareWithASCIIString PyPyUnicode_Concat PyPyUnicode_Contains PyPyUnicode_Count PyPyUnicode_Decode PyPyUnicode_DecodeASCII PyPyUnicode_DecodeFSDefault PyPyUnicode_DecodeFSDefaultAndSize PyPyUnicode_DecodeLatin1 PyPyUnicode_DecodeLocale PyPyUnicode_DecodeLocaleAndSize PyPyUnicode_DecodeMBCS PyPyUnicode_DecodeUTF16 PyPyUnicode_DecodeUTF32 PyPyUnicode_DecodeUTF8 PyPyUnicode_EncodeASCII PyPyUnicode_EncodeCodePage PyPyUnicode_EncodeDecimal PyPyUnicode_EncodeFSDefault PyPyUnicode_EncodeLatin1 PyPyUnicode_EncodeLocale PyPyUnicode_EncodeMBCS PyPyUnicode_EncodeUTF8 PyPyUnicode_FSConverter PyPyUnicode_FSDecoder PyPyUnicode_Find PyPyUnicode_FindChar PyPyUnicode_Format PyPyUnicode_FromEncodedObject PyPyUnicode_FromFormat PyPyUnicode_FromFormatV PyPyUnicode_FromKindAndData PyPyUnicode_FromObject PyPyUnicode_FromOrdinal PyPyUnicode_FromString PyPyUnicode_FromStringAndSize PyPyUnicode_FromUnicode PyPyUnicode_FromWideChar PyPyUnicode_GetDefaultEncoding PyPyUnicode_GetLength PyPyUnicode_GetMax PyPyUnicode_GetSize PyPyUnicode_InternFromString PyPyUnicode_InternInPlace PyPyUnicode_Join PyPyUnicode_New PyPyUnicode_ReadChar PyPyUnicode_Replace PyPyUnicode_Resize PyPyUnicode_Split PyPyUnicode_Splitlines PyPyUnicode_Substring PyPyUnicode_Tailmatch PyPyUnicode_TransformDecimalToASCII PyPyUnicode_Type DATA PyPyUnicode_WriteChar PyPyVectorcall_Call PyPyWeakref_Check PyPyWeakref_CheckProxy PyPyWeakref_CheckRef PyPyWeakref_CheckRefExact PyPyWeakref_GET_OBJECT PyPyWeakref_GetObject PyPyWeakref_LockObject PyPyWeakref_NewProxy PyPyWeakref_NewRef PyPyWrapperDescr_Type DATA PyPy_AddPendingCall PyPy_AtExit PyPy_BuildValue PyPy_BytesWarningFlag DATA PyPy_CompileStringFlags PyPy_DebugFlag DATA PyPy_DecRef PyPy_DontWriteBytecodeFlag DATA PyPy_EnterRecursiveCall PyPy_FatalError PyPy_FindMethod PyPy_FrozenFlag DATA PyPy_GetProgramName PyPy_GetRecursionLimit PyPy_GetVersion PyPy_HashRandomizationFlag DATA PyPy_IgnoreEnvironmentFlag DATA PyPy_IncRef PyPy_InspectFlag DATA PyPy_InteractiveFlag DATA PyPy_IsInitialized PyPy_IsolatedFlag DATA PyPy_LeaveRecursiveCall PyPy_LegacyWindowsStdioFlag DATA PyPy_MakePendingCalls PyPy_NoSiteFlag DATA PyPy_NoUserSiteDirectory DATA PyPy_OptimizeFlag DATA PyPy_QuietFlag DATA PyPy_ReprEnter PyPy_ReprLeave PyPy_SetRecursionLimit PyPy_UNICODE_COPY PyPy_UNICODE_ISALNUM PyPy_UNICODE_ISALPHA PyPy_UNICODE_ISDECIMAL PyPy_UNICODE_ISDIGIT PyPy_UNICODE_ISLINEBREAK PyPy_UNICODE_ISLOWER PyPy_UNICODE_ISNUMERIC PyPy_UNICODE_ISSPACE PyPy_UNICODE_ISTITLE PyPy_UNICODE_ISUPPER PyPy_UNICODE_TODECIMAL PyPy_UNICODE_TODIGIT PyPy_UNICODE_TOLOWER PyPy_UNICODE_TONUMERIC PyPy_UNICODE_TOTITLE PyPy_UNICODE_TOUPPER PyPy_UnbufferedStdioFlag DATA PyPy_VaBuildValue PyPy_VerboseFlag DATA PySlice_AdjustIndices PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyType_GetFlags Py_FileSystemDefaultEncoding DATA _PyExc_ArithmeticError DATA _PyExc_AssertionError DATA _PyExc_AttributeError DATA _PyExc_BaseException DATA _PyExc_BlockingIOError DATA _PyExc_BrokenPipeError DATA _PyExc_BufferError DATA _PyExc_BytesWarning DATA _PyExc_ChildProcessError DATA _PyExc_ConnectionAbortedError DATA _PyExc_ConnectionError DATA _PyExc_ConnectionRefusedError DATA _PyExc_ConnectionResetError DATA _PyExc_DeprecationWarning DATA _PyExc_EOFError DATA _PyExc_Exception DATA _PyExc_FileExistsError DATA _PyExc_FileNotFoundError DATA _PyExc_FloatingPointError DATA _PyExc_FutureWarning DATA _PyExc_GeneratorExit DATA _PyExc_ImportError DATA _PyExc_ImportWarning DATA _PyExc_IndentationError DATA _PyExc_IndexError DATA _PyExc_InterruptedError DATA _PyExc_IsADirectoryError DATA _PyExc_KeyError DATA _PyExc_KeyboardInterrupt DATA _PyExc_LookupError DATA _PyExc_MemoryError DATA _PyExc_ModuleNotFoundError DATA _PyExc_NameError DATA _PyExc_NotADirectoryError DATA _PyExc_NotImplementedError DATA _PyExc_OSError DATA _PyExc_OverflowError DATA _PyExc_PendingDeprecationWarning DATA _PyExc_PermissionError DATA _PyExc_ProcessLookupError DATA _PyExc_RecursionError DATA _PyExc_ReferenceError DATA _PyExc_ResourceWarning DATA _PyExc_RuntimeError DATA _PyExc_RuntimeWarning DATA _PyExc_StopAsyncIteration DATA _PyExc_StopIteration DATA _PyExc_SyntaxError DATA _PyExc_SyntaxWarning DATA _PyExc_SystemError DATA _PyExc_SystemExit DATA _PyExc_TabError DATA _PyExc_TimeoutError DATA _PyExc_TypeError DATA _PyExc_UnboundLocalError DATA _PyExc_UnicodeDecodeError DATA _PyExc_UnicodeEncodeError DATA _PyExc_UnicodeError DATA _PyExc_UnicodeTranslateError DATA _PyExc_UnicodeWarning DATA _PyExc_UserWarning DATA _PyExc_ValueError DATA _PyExc_Warning DATA _PyExc_ZeroDivisionError DATA _PyLong_AsTime_t _PyLong_FromTime_t _PyPyArg_NoKeywords _PyPyArg_ParseTupleAndKeywords_SizeT _PyPyArg_ParseTuple_SizeT _PyPyArg_Parse_SizeT _PyPyArg_VaParseTupleAndKeywords_SizeT _PyPyArg_VaParse_SizeT _PyPyBytes_Eq _PyPyBytes_Join _PyPyBytes_Resize _PyPyComplex_AsCComplex _PyPyComplex_FromCComplex _PyPyDateTime_FromDateAndTime _PyPyDateTime_FromDateAndTimeAndFold _PyPyDateTime_FromTimestamp _PyPyDateTime_Import _PyPyDate_FromDate _PyPyDate_FromTimestamp _PyPyDelta_FromDelta _PyPyDict_GetItemStringWithError _PyPyDict_HasOnlyStringKeys _PyPyErr_FormatFromCause _PyPyErr_WriteUnraisableMsg _PyPyEval_SliceIndex _PyPyFloat_Unpack4 _PyPyFloat_Unpack8 _PyPyImport_AcquireLock _PyPyImport_ReleaseLock _PyPyList_Extend _PyPyLong_AsByteArrayO _PyPyLong_FromByteArray _PyPyLong_NumBits _PyPyLong_Sign _PyPyNamespace_New _PyPyNone_Type DATA _PyPyNotImplemented_Type DATA _PyPyObject_CallFunction_SizeT _PyPyObject_CallMethod_SizeT _PyPyObject_CallNoArg _PyPyObject_FastCall _PyPyObject_FastCallDict _PyPyObject_GC_Malloc _PyPyObject_GC_New _PyPyObject_GC_NewVar _PyPyObject_GetDictPtr _PyPyObject_New _PyPyObject_NewVar _PyPyObject_Vectorcall _PyPyPyGC_AddMemoryPressure _PyPyPy_Free _PyPyPy_Malloc _PyPySet_Next _PyPySet_NextEntry _PyPyThreadState_UncheckedGet _PyPyTimeZone_FromTimeZone _PyPyTime_FromTime _PyPyTime_FromTimeAndFold _PyPyTuple_Resize _PyPyType_Lookup _PyPyUnicode_Ready _PyPy_BuildValue_SizeT _PyPy_Dealloc _PyPy_EllipsisObject DATA _PyPy_FalseStruct DATA _PyPy_HashDouble _PyPy_HashPointer _PyPy_IsFinalizing _PyPy_NoneStruct DATA _PyPy_NotImplementedStruct DATA _PyPy_PackageContext DATA _PyPy_RestoreSignals _PyPy_TrueStruct DATA _PyPy_VaBuildValue_SizeT _PyPy_get_PyOS_InputHook _PyPy_get_capsule_type _PyPy_object_dealloc _PyPy_setfilesystemdefaultencoding _PyPy_strhex _PyPy_strhex_bytes _PyPy_subtype_dealloc _PyPy_tuple_dealloc _PyPy_tuple_new _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_noraise _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_Init _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _pypy_init_free _pypy_init_home pypy_HPyInit__debug pypy_carefully_make_gil pypy_debug_file DATA pypy_execute_source pypy_execute_source_ptr pypy_hpy_debug_close_handle pypy_hpy_debug_ctx_init pypy_hpy_debug_get_ctx pypy_hpy_debug_open_handle pypy_hpy_debug_set_ctx pypy_hpy_debug_unwrap_handle pypy_init_embedded_cffi_module pypy_init_threads pypy_main_startup pypy_setup_home pypy_thread_attach rpython_startup_code python3-dll-a/src/libpypy3.9-c.def0000644000175000017500000006142014661133735017550 0ustar jamespagejamespage; ; Definition file of libpypy3.9-c.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "libpypy3.9-c.dll" EXPORTS HPyInitGlobalContext__debug HPyInitGlobalContext__trace HPyInit__debug HPyInit__trace PyArg_ValidateKeywordArguments PyExpat_XML_DefaultCurrent PyExpat_XML_ErrorString PyExpat_XML_ExpatVersion PyExpat_XML_ExpatVersionInfo PyExpat_XML_ExternalEntityParserCreate PyExpat_XML_FreeContentModel PyExpat_XML_GetBase PyExpat_XML_GetBuffer PyExpat_XML_GetCurrentByteCount PyExpat_XML_GetCurrentByteIndex PyExpat_XML_GetCurrentColumnNumber PyExpat_XML_GetCurrentLineNumber PyExpat_XML_GetErrorCode PyExpat_XML_GetFeatureList PyExpat_XML_GetIdAttributeIndex PyExpat_XML_GetInputContext PyExpat_XML_GetParsingStatus PyExpat_XML_GetSpecifiedAttributeCount PyExpat_XML_MemFree PyExpat_XML_MemMalloc PyExpat_XML_MemRealloc PyExpat_XML_Parse PyExpat_XML_ParseBuffer PyExpat_XML_ParserCreate PyExpat_XML_ParserCreateNS PyExpat_XML_ParserCreate_MM PyExpat_XML_ParserFree PyExpat_XML_ParserReset PyExpat_XML_ResumeParser PyExpat_XML_SetAttlistDeclHandler PyExpat_XML_SetBase PyExpat_XML_SetBillionLaughsAttackProtectionActivationThreshold PyExpat_XML_SetBillionLaughsAttackProtectionMaximumAmplification PyExpat_XML_SetCdataSectionHandler PyExpat_XML_SetCharacterDataHandler PyExpat_XML_SetCommentHandler PyExpat_XML_SetDefaultHandler PyExpat_XML_SetDefaultHandlerExpand PyExpat_XML_SetDoctypeDeclHandler PyExpat_XML_SetElementDeclHandler PyExpat_XML_SetElementHandler PyExpat_XML_SetEncoding PyExpat_XML_SetEndCdataSectionHandler PyExpat_XML_SetEndDoctypeDeclHandler PyExpat_XML_SetEndElementHandler PyExpat_XML_SetEndNamespaceDeclHandler PyExpat_XML_SetEntityDeclHandler PyExpat_XML_SetExternalEntityRefHandler PyExpat_XML_SetExternalEntityRefHandlerArg PyExpat_XML_SetHashSalt PyExpat_XML_SetNamespaceDeclHandler PyExpat_XML_SetNotStandaloneHandler PyExpat_XML_SetNotationDeclHandler PyExpat_XML_SetParamEntityParsing PyExpat_XML_SetProcessingInstructionHandler PyExpat_XML_SetReparseDeferralEnabled PyExpat_XML_SetReturnNSTriplet PyExpat_XML_SetSkippedEntityHandler PyExpat_XML_SetStartCdataSectionHandler PyExpat_XML_SetStartDoctypeDeclHandler PyExpat_XML_SetStartElementHandler PyExpat_XML_SetStartNamespaceDeclHandler PyExpat_XML_SetUnknownEncodingHandler PyExpat_XML_SetUnparsedEntityDeclHandler PyExpat_XML_SetUserData PyExpat_XML_SetXmlDeclHandler PyExpat_XML_StopParser PyExpat_XML_UseForeignDTD PyExpat_XML_UseParserAsHandlerArg PyModule_AddType PyPyAnySet_Check PyPyAnySet_CheckExact PyPyArg_Parse PyPyArg_ParseTuple PyPyArg_ParseTupleAndKeywords PyPyArg_UnpackTuple PyPyArg_VaParse PyPyArg_VaParseTupleAndKeywords PyPyBaseObject_Type DATA PyPyBool_FromLong PyPyBool_Type DATA PyPyBuffer_FillInfo PyPyBuffer_FromContiguous PyPyBuffer_GetPointer PyPyBuffer_IsContiguous PyPyBuffer_Release PyPyBuffer_ToContiguous PyPyBufferable_Type DATA PyPyByteArray_AsString PyPyByteArray_Check PyPyByteArray_CheckExact PyPyByteArray_Concat PyPyByteArray_FromObject PyPyByteArray_FromStringAndSize PyPyByteArray_Resize PyPyByteArray_Size PyPyByteArray_Type DATA PyPyBytes_AS_STRING PyPyBytes_AsString PyPyBytes_AsStringAndSize PyPyBytes_Concat PyPyBytes_ConcatAndDel PyPyBytes_FromFormat PyPyBytes_FromFormatV PyPyBytes_FromObject PyPyBytes_FromString PyPyBytes_FromStringAndSize PyPyBytes_Size PyPyBytes_Type DATA PyPyCFunction_Call PyPyCFunction_Check PyPyCFunction_GetFunction PyPyCFunction_Type DATA PyPyCMethod_New PyPyCallIter_New PyPyCallable_Check PyPyCapsule_GetContext PyPyCapsule_GetDestructor PyPyCapsule_GetName PyPyCapsule_GetPointer PyPyCapsule_Import PyPyCapsule_IsValid PyPyCapsule_New PyPyCapsule_SetContext PyPyCapsule_SetDestructor PyPyCapsule_SetName PyPyCapsule_SetPointer PyPyCapsule_Type DATA PyPyCell_Type DATA PyPyClassMethodDescr_Type DATA PyPyClassMethod_New PyPyClassMethod_Type DATA PyPyCode_Addr2Line PyPyCode_Check PyPyCode_CheckExact PyPyCode_GetNumFree PyPyCode_New PyPyCode_NewEmpty PyPyCodec_Decode PyPyCodec_Decoder PyPyCodec_Encode PyPyCodec_Encoder PyPyCodec_IncrementalDecoder PyPyCodec_IncrementalEncoder PyPyComplex_AsCComplex PyPyComplex_Check PyPyComplex_CheckExact PyPyComplex_FromCComplex PyPyComplex_FromDoubles PyPyComplex_ImagAsDouble PyPyComplex_RealAsDouble PyPyComplex_Type DATA PyPyContextVar_Get PyPyContextVar_New PyPyContextVar_Set PyPyCoro_Check PyPyCoro_CheckExact PyPyDateTimeAPI DATA PyPyDateTime_Check PyPyDateTime_CheckExact PyPyDateTime_DATE_GET_HOUR PyPyDateTime_DATE_GET_MICROSECOND PyPyDateTime_DATE_GET_MINUTE PyPyDateTime_DATE_GET_SECOND PyPyDateTime_DELTA_GET_DAYS PyPyDateTime_DELTA_GET_MICROSECONDS PyPyDateTime_DELTA_GET_SECONDS PyPyDateTime_FromTimestamp PyPyDateTime_GET_DAY PyPyDateTime_GET_FOLD PyPyDateTime_GET_MONTH PyPyDateTime_GET_YEAR PyPyDateTime_TIME_GET_FOLD PyPyDateTime_TIME_GET_HOUR PyPyDateTime_TIME_GET_MICROSECOND PyPyDateTime_TIME_GET_MINUTE PyPyDateTime_TIME_GET_SECOND PyPyDate_Check PyPyDate_CheckExact PyPyDate_FromTimestamp PyPyDelta_Check PyPyDelta_CheckExact PyPyDescr_NewClassMethod PyPyDescr_NewGetSet PyPyDescr_NewMethod PyPyDictKeys_Type DATA PyPyDictProxy_Check PyPyDictProxy_CheckExact PyPyDictProxy_New PyPyDictProxy_Type DATA PyPyDictValues_Type DATA PyPyDict_Clear PyPyDict_Contains PyPyDict_Copy PyPyDict_DelItem PyPyDict_DelItemString PyPyDict_GetItem PyPyDict_GetItemString PyPyDict_GetItemWithError PyPyDict_Items PyPyDict_Keys PyPyDict_Merge PyPyDict_New PyPyDict_Next PyPyDict_SetDefault PyPyDict_SetItem PyPyDict_SetItemString PyPyDict_Size PyPyDict_Type DATA PyPyDict_Update PyPyDict_Values PyPyErr_BadArgument PyPyErr_BadInternalCall PyPyErr_CheckSignals PyPyErr_Clear PyPyErr_Display PyPyErr_ExceptionMatches PyPyErr_Fetch PyPyErr_Format PyPyErr_FormatV PyPyErr_GetExcInfo PyPyErr_GivenExceptionMatches PyPyErr_NewException PyPyErr_NewExceptionWithDoc PyPyErr_NoMemory PyPyErr_NormalizeException PyPyErr_Occurred PyPyErr_Print PyPyErr_PrintEx PyPyErr_Restore PyPyErr_SetExcFromWindowsErrWithFilenameObject PyPyErr_SetExcFromWindowsErrWithFilenameObjects PyPyErr_SetExcInfo PyPyErr_SetFromErrno PyPyErr_SetFromErrnoWithFilename PyPyErr_SetFromErrnoWithFilenameObject PyPyErr_SetFromErrnoWithFilenameObjects PyPyErr_SetFromWindowsErr PyPyErr_SetFromWindowsErrWithFilename PyPyErr_SetInterrupt PyPyErr_SetNone PyPyErr_SetObject PyPyErr_SetString PyPyErr_Warn PyPyErr_WarnEx PyPyErr_WarnExplicit PyPyErr_WarnFormat PyPyErr_WriteUnraisable PyPyEval_AcquireThread PyPyEval_CallFunction PyPyEval_CallMethod PyPyEval_CallObjectWithKeywords PyPyEval_EvalCode PyPyEval_GetBuiltins PyPyEval_GetFrame PyPyEval_GetGlobals PyPyEval_GetLocals PyPyEval_InitThreads PyPyEval_MergeCompilerFlags PyPyEval_ReleaseThread PyPyEval_RestoreThread PyPyEval_SaveThread PyPyEval_ThreadsInitialized PyPyExc_ArithmeticError DATA PyPyExc_AssertionError DATA PyPyExc_AttributeError DATA PyPyExc_BaseException DATA PyPyExc_BlockingIOError DATA PyPyExc_BrokenPipeError DATA PyPyExc_BufferError DATA PyPyExc_BytesWarning DATA PyPyExc_ChildProcessError DATA PyPyExc_ConnectionAbortedError DATA PyPyExc_ConnectionError DATA PyPyExc_ConnectionRefusedError DATA PyPyExc_ConnectionResetError DATA PyPyExc_DeprecationWarning DATA PyPyExc_EOFError DATA PyPyExc_Exception DATA PyPyExc_FileExistsError DATA PyPyExc_FileNotFoundError DATA PyPyExc_FloatingPointError DATA PyPyExc_FutureWarning DATA PyPyExc_GeneratorExit DATA PyPyExc_ImportError DATA PyPyExc_ImportWarning DATA PyPyExc_IndentationError DATA PyPyExc_IndexError DATA PyPyExc_InterruptedError DATA PyPyExc_IsADirectoryError DATA PyPyExc_KeyError DATA PyPyExc_KeyboardInterrupt DATA PyPyExc_LookupError DATA PyPyExc_MemoryError DATA PyPyExc_ModuleNotFoundError DATA PyPyExc_NameError DATA PyPyExc_NotADirectoryError DATA PyPyExc_NotImplementedError DATA PyPyExc_OSError DATA PyPyExc_OverflowError DATA PyPyExc_PendingDeprecationWarning DATA PyPyExc_PermissionError DATA PyPyExc_ProcessLookupError DATA PyPyExc_RecursionError DATA PyPyExc_ReferenceError DATA PyPyExc_ResourceWarning DATA PyPyExc_RuntimeError DATA PyPyExc_RuntimeWarning DATA PyPyExc_StopAsyncIteration DATA PyPyExc_StopIteration DATA PyPyExc_SyntaxError DATA PyPyExc_SyntaxWarning DATA PyPyExc_SystemError DATA PyPyExc_SystemExit DATA PyPyExc_TabError DATA PyPyExc_TimeoutError DATA PyPyExc_TypeError DATA PyPyExc_UnboundLocalError DATA PyPyExc_UnicodeDecodeError DATA PyPyExc_UnicodeEncodeError DATA PyPyExc_UnicodeError DATA PyPyExc_UnicodeTranslateError DATA PyPyExc_UnicodeWarning DATA PyPyExc_UserWarning DATA PyPyExc_ValueError DATA PyPyExc_Warning DATA PyPyExc_ZeroDivisionError DATA PyPyExceptionInstance_Class PyPyException_GetCause PyPyException_GetContext PyPyException_GetTraceback PyPyException_SetCause PyPyException_SetContext PyPyException_SetTraceback PyPyFile_FromFd PyPyFile_FromString PyPyFile_GetLine PyPyFile_WriteObject PyPyFile_WriteString PyPyFloat_AS_DOUBLE PyPyFloat_AsDouble PyPyFloat_FromDouble PyPyFloat_FromString PyPyFloat_Type DATA PyPyFrame_New PyPyFrozenSet_Check PyPyFrozenSet_CheckExact PyPyFrozenSet_New PyPyFrozenSet_Type DATA PyPyFunction_Check PyPyFunction_CheckExact PyPyFunction_GetCode PyPyFunction_Type DATA PyPyGILState_Check PyPyGILState_Ensure PyPyGILState_Release PyPyGen_Check PyPyGen_CheckExact PyPyGetSetDescr_Type DATA PyPyImport_AddModule PyPyImport_ExecCodeModule PyPyImport_ExecCodeModuleEx PyPyImport_GetModule PyPyImport_GetModuleDict PyPyImport_Import PyPyImport_ImportModule PyPyImport_ImportModuleLevelObject PyPyImport_ImportModuleNoBlock PyPyImport_ReloadModule PyPyIndex_Check PyPyInstanceMethod_Check PyPyInstanceMethod_Function PyPyInstanceMethod_GET_FUNCTION PyPyInstanceMethod_New PyPyInstanceMethod_Type DATA PyPyInterpreterState_GetID PyPyInterpreterState_Head PyPyInterpreterState_Next PyPyIter_Check PyPyIter_Next PyPyList_Append PyPyList_AsTuple PyPyList_GET_ITEM PyPyList_GET_SIZE PyPyList_GetItem PyPyList_GetSlice PyPyList_Insert PyPyList_New PyPyList_Reverse PyPyList_SET_ITEM PyPyList_SetItem PyPyList_SetSlice PyPyList_Size PyPyList_Sort PyPyList_Type DATA PyPyLong_AsDouble PyPyLong_AsLong PyPyLong_AsLongAndOverflow PyPyLong_AsLongLong PyPyLong_AsLongLongAndOverflow PyPyLong_AsSize_t PyPyLong_AsSsize_t PyPyLong_AsUnsignedLong PyPyLong_AsUnsignedLongLong PyPyLong_AsUnsignedLongLongMask PyPyLong_AsUnsignedLongMask PyPyLong_AsVoidPtr PyPyLong_FromDouble PyPyLong_FromLong PyPyLong_FromLongLong PyPyLong_FromSize_t PyPyLong_FromSsize_t PyPyLong_FromString PyPyLong_FromUnicode PyPyLong_FromUnicodeObject PyPyLong_FromUnsignedLong PyPyLong_FromUnsignedLongLong PyPyLong_FromVoidPtr PyPyLong_Type DATA PyPyMapping_Check PyPyMapping_GetItemString PyPyMapping_HasKey PyPyMapping_HasKeyString PyPyMapping_Items PyPyMapping_Keys PyPyMapping_Length PyPyMapping_SetItemString PyPyMapping_Size PyPyMapping_Values PyPyMarshal_ReadObjectFromString PyPyMarshal_WriteObjectToString PyPyMem_Calloc PyPyMem_Free PyPyMem_Malloc PyPyMem_RawCalloc PyPyMem_RawFree PyPyMem_RawMalloc PyPyMem_RawRealloc PyPyMem_Realloc PyPyMemberDescr_Type DATA PyPyMember_GetOne PyPyMember_SetOne PyPyMemoryView_Check PyPyMemoryView_CheckExact PyPyMemoryView_FromBuffer PyPyMemoryView_FromMemory PyPyMemoryView_FromObject PyPyMemoryView_GetContiguous PyPyMemoryView_Type DATA PyPyMethodDescr_Check PyPyMethodDescr_CheckExact PyPyMethodDescr_Type DATA PyPyMethod_Check PyPyMethod_CheckExact PyPyMethod_Function PyPyMethod_New PyPyMethod_Self PyPyMethod_Type DATA PyPyModuleDef_Init PyPyModule_AddFunctions PyPyModule_AddIntConstant PyPyModule_AddObject PyPyModule_AddStringConstant PyPyModule_Check PyPyModule_CheckExact PyPyModule_Create2 PyPyModule_ExecDef PyPyModule_GetDef PyPyModule_GetDict PyPyModule_GetFilenameObject PyPyModule_GetName PyPyModule_GetNameObject PyPyModule_GetState PyPyModule_New PyPyModule_NewObject PyPyModule_Type DATA PyPyNumber_Absolute PyPyNumber_Add PyPyNumber_And PyPyNumber_AsSsize_t PyPyNumber_Check PyPyNumber_Divide PyPyNumber_Divmod PyPyNumber_Float PyPyNumber_FloorDivide PyPyNumber_InPlaceAdd PyPyNumber_InPlaceAnd PyPyNumber_InPlaceDivide PyPyNumber_InPlaceFloorDivide PyPyNumber_InPlaceLshift PyPyNumber_InPlaceMatrixMultiply PyPyNumber_InPlaceMultiply PyPyNumber_InPlaceOr PyPyNumber_InPlacePower PyPyNumber_InPlaceRemainder PyPyNumber_InPlaceRshift PyPyNumber_InPlaceSubtract PyPyNumber_InPlaceTrueDivide PyPyNumber_InPlaceXor PyPyNumber_Index PyPyNumber_Invert PyPyNumber_Long PyPyNumber_Lshift PyPyNumber_MatrixMultiply PyPyNumber_Multiply PyPyNumber_Negative PyPyNumber_Or PyPyNumber_Positive PyPyNumber_Power PyPyNumber_Remainder PyPyNumber_Rshift PyPyNumber_Subtract PyPyNumber_ToBase PyPyNumber_TrueDivide PyPyNumber_Xor PyPyOS_AfterFork PyPyOS_FSPath PyPyOS_InputHook DATA PyPyOS_InterruptOccurred PyPyOS_double_to_string PyPyOS_getsig PyPyOS_setsig PyPyOS_snprintf PyPyOS_string_to_double PyPyOS_vsnprintf PyPyObject_ASCII PyPyObject_AsCharBuffer PyPyObject_AsFileDescriptor PyPyObject_AsReadBuffer PyPyObject_AsWriteBuffer PyPyObject_Bytes PyPyObject_Call PyPyObject_CallFinalizerFromDealloc PyPyObject_CallFunction PyPyObject_CallFunctionObjArgs PyPyObject_CallMethod PyPyObject_CallMethodNoArgs PyPyObject_CallMethodObjArgs PyPyObject_CallMethodOneArg PyPyObject_CallNoArgs PyPyObject_CallObject PyPyObject_CallOneArg PyPyObject_Calloc PyPyObject_CheckReadBuffer PyPyObject_ClearWeakRefs PyPyObject_Del PyPyObject_DelAttr PyPyObject_DelAttrString PyPyObject_DelItem PyPyObject_DelItemString PyPyObject_Dir PyPyObject_Format PyPyObject_Free PyPyObject_GC_Del PyPyObject_GenericGetAttr PyPyObject_GenericGetDict PyPyObject_GenericSetAttr PyPyObject_GenericSetDict PyPyObject_GetAttr PyPyObject_GetAttrString PyPyObject_GetBuffer PyPyObject_GetItem PyPyObject_GetIter PyPyObject_HasAttr PyPyObject_HasAttrString PyPyObject_Hash PyPyObject_HashNotImplemented PyPyObject_Init PyPyObject_InitVar PyPyObject_IsInstance PyPyObject_IsSubclass PyPyObject_IsTrue PyPyObject_LengthHint PyPyObject_Malloc PyPyObject_Not PyPyObject_Print PyPyObject_Realloc PyPyObject_Repr PyPyObject_RichCompare PyPyObject_RichCompareBool PyPyObject_SelfIter PyPyObject_SetAttr PyPyObject_SetAttrString PyPyObject_SetItem PyPyObject_Size PyPyObject_Str PyPyObject_Type PyPyObject_Unicode PyPyObject_Vectorcall PyPyObject_VectorcallDict PyPyObject_VectorcallMethod PyPyProperty_Type DATA PyPyRange_Type DATA PyPyReversed_Type DATA PyPyRun_File PyPyRun_SimpleString PyPyRun_String PyPyRun_StringFlags PyPySeqIter_New PyPySequence_Check PyPySequence_Concat PyPySequence_Contains PyPySequence_DelItem PyPySequence_DelSlice PyPySequence_Fast PyPySequence_Fast_GET_ITEM PyPySequence_Fast_GET_SIZE PyPySequence_Fast_ITEMS PyPySequence_GetItem PyPySequence_GetSlice PyPySequence_ITEM PyPySequence_InPlaceConcat PyPySequence_InPlaceRepeat PyPySequence_Index PyPySequence_Length PyPySequence_List PyPySequence_Repeat PyPySequence_SetItem PyPySequence_SetSlice PyPySequence_Size PyPySequence_Tuple PyPySet_Add PyPySet_Check PyPySet_CheckExact PyPySet_Clear PyPySet_Contains PyPySet_Discard PyPySet_GET_SIZE PyPySet_New PyPySet_Pop PyPySet_Size PyPySet_Type DATA PyPySlice_GetIndices PyPySlice_GetIndicesEx PyPySlice_New PyPySlice_Type DATA PyPySlice_Unpack PyPyState_AddModule PyPyState_RemoveModule PyPyStaticMethod_New PyPyStaticMethod_Type DATA PyPyStructSequence_GetItem PyPyStructSequence_InitType PyPyStructSequence_InitType2 PyPyStructSequence_New PyPyStructSequence_NewType PyPyStructSequence_SetItem PyPyStructSequence_UnnamedField DATA PyPySys_GetObject PyPySys_SetObject PyPySys_WriteStderr PyPySys_WriteStdout PyPyTZInfo_Check PyPyTZInfo_CheckExact PyPyThreadState_Clear PyPyThreadState_Delete PyPyThreadState_DeleteCurrent PyPyThreadState_Get PyPyThreadState_GetDict PyPyThreadState_New PyPyThreadState_SetAsyncExc PyPyThreadState_Swap PyPyThread_ReInitTLS PyPyThread_acquire_lock PyPyThread_allocate_lock PyPyThread_create_key PyPyThread_delete_key PyPyThread_delete_key_value PyPyThread_exit_thread PyPyThread_free_lock PyPyThread_get_key_value PyPyThread_get_thread_ident PyPyThread_init_thread PyPyThread_release_lock PyPyThread_set_key_value PyPyThread_start_new_thread PyPyTime_Check PyPyTime_CheckExact PyPyTraceBack_Check PyPyTraceBack_Here PyPyTraceBack_Print PyPyTraceBack_Type DATA PyPyTraceMalloc_Track PyPyTraceMalloc_Untrack PyPyTuple_GetItem PyPyTuple_GetSlice PyPyTuple_New PyPyTuple_Pack PyPyTuple_SetItem PyPyTuple_Size PyPyTuple_Type DATA PyPyType_FromModuleAndSpec PyPyType_FromSpec PyPyType_FromSpecWithBases PyPyType_GenericAlloc PyPyType_GenericNew PyPyType_GetModule PyPyType_GetModuleState PyPyType_GetSlot PyPyType_IsSubtype PyPyType_Modified PyPyType_Ready PyPyType_Type DATA PyPyUnicode_Append PyPyUnicode_AppendAndDel PyPyUnicode_AsASCIIString PyPyUnicode_AsEncodedObject PyPyUnicode_AsEncodedString PyPyUnicode_AsLatin1String PyPyUnicode_AsMBCSString PyPyUnicode_AsUCS4 PyPyUnicode_AsUCS4Copy PyPyUnicode_AsUTF16String PyPyUnicode_AsUTF32String PyPyUnicode_AsUTF8 PyPyUnicode_AsUTF8AndSize PyPyUnicode_AsUTF8String PyPyUnicode_AsUnicode PyPyUnicode_AsUnicodeAndSize PyPyUnicode_AsUnicodeEscapeString PyPyUnicode_AsWideChar PyPyUnicode_AsWideCharString PyPyUnicode_Check PyPyUnicode_CheckExact PyPyUnicode_Compare PyPyUnicode_CompareWithASCIIString PyPyUnicode_Concat PyPyUnicode_Contains PyPyUnicode_Count PyPyUnicode_Decode PyPyUnicode_DecodeASCII PyPyUnicode_DecodeFSDefault PyPyUnicode_DecodeFSDefaultAndSize PyPyUnicode_DecodeLatin1 PyPyUnicode_DecodeLocale PyPyUnicode_DecodeLocaleAndSize PyPyUnicode_DecodeMBCS PyPyUnicode_DecodeUTF16 PyPyUnicode_DecodeUTF32 PyPyUnicode_DecodeUTF8 PyPyUnicode_EncodeASCII PyPyUnicode_EncodeCodePage PyPyUnicode_EncodeDecimal PyPyUnicode_EncodeFSDefault PyPyUnicode_EncodeLatin1 PyPyUnicode_EncodeLocale PyPyUnicode_EncodeMBCS PyPyUnicode_EncodeUTF8 PyPyUnicode_FSConverter PyPyUnicode_FSDecoder PyPyUnicode_Find PyPyUnicode_FindChar PyPyUnicode_Format PyPyUnicode_FromEncodedObject PyPyUnicode_FromFormat PyPyUnicode_FromFormatV PyPyUnicode_FromKindAndData PyPyUnicode_FromObject PyPyUnicode_FromOrdinal PyPyUnicode_FromString PyPyUnicode_FromStringAndSize PyPyUnicode_FromUnicode PyPyUnicode_FromWideChar PyPyUnicode_GetDefaultEncoding PyPyUnicode_GetLength PyPyUnicode_GetMax PyPyUnicode_GetSize PyPyUnicode_InternFromString PyPyUnicode_InternInPlace PyPyUnicode_Join PyPyUnicode_New PyPyUnicode_ReadChar PyPyUnicode_Replace PyPyUnicode_Resize PyPyUnicode_Split PyPyUnicode_Splitlines PyPyUnicode_Substring PyPyUnicode_Tailmatch PyPyUnicode_TransformDecimalToASCII PyPyUnicode_Type DATA PyPyUnicode_WriteChar PyPyVectorcall_Call PyPyWeakref_Check PyPyWeakref_CheckProxy PyPyWeakref_CheckRef PyPyWeakref_CheckRefExact PyPyWeakref_GET_OBJECT PyPyWeakref_GetObject PyPyWeakref_LockObject PyPyWeakref_NewProxy PyPyWeakref_NewRef PyPyWrapperDescr_Type DATA PyPy_AddPendingCall PyPy_AtExit PyPy_BuildValue PyPy_BytesWarningFlag DATA PyPy_CompileStringFlags PyPy_DebugFlag DATA PyPy_DecRef PyPy_DontWriteBytecodeFlag DATA PyPy_EnterRecursiveCall PyPy_FatalError PyPy_FindMethod PyPy_FrozenFlag DATA PyPy_GenericAlias PyPy_GetProgramName PyPy_GetRecursionLimit PyPy_GetVersion PyPy_HashRandomizationFlag DATA PyPy_IgnoreEnvironmentFlag DATA PyPy_IncRef PyPy_InspectFlag DATA PyPy_InteractiveFlag DATA PyPy_IsInitialized PyPy_IsolatedFlag DATA PyPy_LeaveRecursiveCall PyPy_LegacyWindowsStdioFlag DATA PyPy_MakePendingCalls PyPy_NoSiteFlag DATA PyPy_NoUserSiteDirectory DATA PyPy_OptimizeFlag DATA PyPy_QuietFlag DATA PyPy_ReprEnter PyPy_ReprLeave PyPy_SetRecursionLimit PyPy_UNICODE_COPY PyPy_UNICODE_ISALNUM PyPy_UNICODE_ISALPHA PyPy_UNICODE_ISDECIMAL PyPy_UNICODE_ISDIGIT PyPy_UNICODE_ISLINEBREAK PyPy_UNICODE_ISLOWER PyPy_UNICODE_ISNUMERIC PyPy_UNICODE_ISSPACE PyPy_UNICODE_ISTITLE PyPy_UNICODE_ISUPPER PyPy_UNICODE_TODECIMAL PyPy_UNICODE_TODIGIT PyPy_UNICODE_TOLOWER PyPy_UNICODE_TONUMERIC PyPy_UNICODE_TOTITLE PyPy_UNICODE_TOUPPER PyPy_UnbufferedStdioFlag DATA PyPy_VaBuildValue PyPy_VerboseFlag DATA PySlice_AdjustIndices PyState_FindModule PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyType_GetFlags Py_FileSystemDefaultEncoding DATA _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoKwnames _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_UnpackKeywords _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyExc_ArithmeticError DATA _PyExc_AssertionError DATA _PyExc_AttributeError DATA _PyExc_BaseException DATA _PyExc_BlockingIOError DATA _PyExc_BrokenPipeError DATA _PyExc_BufferError DATA _PyExc_BytesWarning DATA _PyExc_ChildProcessError DATA _PyExc_ConnectionAbortedError DATA _PyExc_ConnectionError DATA _PyExc_ConnectionRefusedError DATA _PyExc_ConnectionResetError DATA _PyExc_DeprecationWarning DATA _PyExc_EOFError DATA _PyExc_Exception DATA _PyExc_FileExistsError DATA _PyExc_FileNotFoundError DATA _PyExc_FloatingPointError DATA _PyExc_FutureWarning DATA _PyExc_GeneratorExit DATA _PyExc_ImportError DATA _PyExc_ImportWarning DATA _PyExc_IndentationError DATA _PyExc_IndexError DATA _PyExc_InterruptedError DATA _PyExc_IsADirectoryError DATA _PyExc_KeyError DATA _PyExc_KeyboardInterrupt DATA _PyExc_LookupError DATA _PyExc_MemoryError DATA _PyExc_ModuleNotFoundError DATA _PyExc_NameError DATA _PyExc_NotADirectoryError DATA _PyExc_NotImplementedError DATA _PyExc_OSError DATA _PyExc_OverflowError DATA _PyExc_PendingDeprecationWarning DATA _PyExc_PermissionError DATA _PyExc_ProcessLookupError DATA _PyExc_RecursionError DATA _PyExc_ReferenceError DATA _PyExc_ResourceWarning DATA _PyExc_RuntimeError DATA _PyExc_RuntimeWarning DATA _PyExc_StopAsyncIteration DATA _PyExc_StopIteration DATA _PyExc_SyntaxError DATA _PyExc_SyntaxWarning DATA _PyExc_SystemError DATA _PyExc_SystemExit DATA _PyExc_TabError DATA _PyExc_TimeoutError DATA _PyExc_TypeError DATA _PyExc_UnboundLocalError DATA _PyExc_UnicodeDecodeError DATA _PyExc_UnicodeEncodeError DATA _PyExc_UnicodeError DATA _PyExc_UnicodeTranslateError DATA _PyExc_UnicodeWarning DATA _PyExc_UserWarning DATA _PyExc_ValueError DATA _PyExc_Warning DATA _PyExc_ZeroDivisionError DATA _PyLong_AsTime_t _PyLong_FromTime_t _PyPyArg_ParseTupleAndKeywords_SizeT _PyPyArg_ParseTuple_SizeT _PyPyArg_Parse_SizeT _PyPyArg_VaParseTupleAndKeywords_SizeT _PyPyArg_VaParse_SizeT _PyPyBytes_Eq _PyPyBytes_Join _PyPyBytes_Resize _PyPyComplex_AsCComplex _PyPyComplex_FromCComplex _PyPyDateTime_FromDateAndTime _PyPyDateTime_FromDateAndTimeAndFold _PyPyDateTime_FromTimestamp _PyPyDateTime_Import _PyPyDate_FromDate _PyPyDate_FromTimestamp _PyPyDelta_FromDelta _PyPyDict_GetItemStringWithError _PyPyDict_HasOnlyStringKeys _PyPyErr_FormatFromCause _PyPyErr_WriteUnraisableMsg _PyPyEval_GetAsyncGenFinalizer _PyPyEval_GetAsyncGenFirstiter _PyPyEval_SliceIndex _PyPyFloat_Unpack4 _PyPyFloat_Unpack8 _PyPyImport_AcquireLock _PyPyImport_ReleaseLock _PyPyList_Extend _PyPyLong_AsByteArrayO _PyPyLong_AsInt _PyPyLong_FromByteArray _PyPyLong_NumBits _PyPyLong_Sign _PyPyNamespace_New _PyPyNone_Type DATA _PyPyNotImplemented_Type DATA _PyPyObject_CallFunction_SizeT _PyPyObject_CallMethod_SizeT _PyPyObject_FastCall _PyPyObject_GC_Malloc _PyPyObject_GC_New _PyPyObject_GC_NewVar _PyPyObject_GetDictPtr _PyPyObject_New _PyPyObject_NewVar _PyPyPyGC_AddMemoryPressure _PyPyPy_Free _PyPyPy_Malloc _PyPySet_Next _PyPySet_NextEntry _PyPyThreadState_UncheckedGet _PyPyTimeZone_FromTimeZone _PyPyTime_FromTime _PyPyTime_FromTimeAndFold _PyPyTuple_Resize _PyPyType_Lookup _PyPyUnicode_EQ _PyPyUnicode_EqualToASCIIString _PyPyUnicode_Ready _PyPy_BuildValue_SizeT _PyPy_Dealloc _PyPy_EllipsisObject DATA _PyPy_FalseStruct DATA _PyPy_HashDouble _PyPy_HashPointer _PyPy_IsFinalizing _PyPy_NoneStruct DATA _PyPy_NotImplementedStruct DATA _PyPy_PackageContext DATA _PyPy_RestoreSignals _PyPy_TrueStruct DATA _PyPy_VaBuildValue_SizeT _PyPy_get_PyOS_InputHook _PyPy_get_capsule_type _PyPy_object_dealloc _PyPy_setfilesystemdefaultencoding _PyPy_strhex _PyPy_strhex_bytes _PyPy_subtype_dealloc _PyPy_tuple_dealloc _PyPy_tuple_new _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_noraise _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_Init _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyType_Name _Py_VaBuildStack _Py_VaBuildStack_SizeT _pypy_init_executable _pypy_init_free _pypy_init_home get_required_hpy_major_version__debug get_required_hpy_major_version__trace get_required_hpy_minor_version__debug get_required_hpy_minor_version__trace os_readlink_impl os_symlink_impl os_unlink_impl pypy_HPyInit__debug pypy_HPyInit__trace pypy_carefully_make_gil pypy_debug_file DATA pypy_execute_source pypy_execute_source_ptr pypy_hpy_debug_close_handle pypy_hpy_debug_ctx_init pypy_hpy_debug_get_ctx pypy_hpy_debug_open_handle pypy_hpy_debug_set_ctx pypy_hpy_debug_unwrap_handle pypy_hpy_trace_ctx_init pypy_hpy_trace_get_ctx pypy_hpy_trace_get_func_name pypy_hpy_trace_get_nfunc pypy_init_embedded_cffi_module pypy_init_threads pypy_main_startup pypy_setup_home pypy_thread_attach rpython_startup_code python3-dll-a/src/python37.def0000644000175000017500000010107114661133735017076 0ustar jamespagejamespage; ; Definition file of python37.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "python37.dll" EXPORTS PyAST_Compile PyAST_CompileEx PyAST_CompileObject PyAST_FromNode PyAST_FromNodeObject PyAST_Validate PyArena_AddPyObject PyArena_Free PyArena_Malloc PyArena_New PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyAsyncGen_Fini PyAsyncGen_New PyAsyncGen_Type DATA PyBaseObject_Type DATA PyBool_FromLong PyBool_Type DATA PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_FromContiguous PyBuffer_GetPointer PyBuffer_IsContiguous PyBuffer_Release PyBuffer_ToContiguous PyByteArrayIter_Type DATA PyByteArray_AsString PyByteArray_Concat PyByteArray_Fini PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Init PyByteArray_Resize PyByteArray_Size PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_Fini PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyBytes_Type DATA PyCFunction_Call PyCFunction_ClearFreeList PyCFunction_Fini PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_New PyCFunction_NewEx PyCFunction_Type DATA PyCallIter_New PyCallIter_Type DATA PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCapsule_Type DATA PyCell_Get PyCell_New PyCell_Set PyCell_Type DATA PyClassMethodDescr_Type DATA PyClassMethod_New PyClassMethod_Type DATA PyCode_Addr2Line PyCode_New PyCode_NewEmpty PyCode_Optimize PyCode_Type DATA PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_NameReplaceErrors PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_XMLCharRefReplaceErrors PyCompile_OpcodeStackEffect PyComplex_AsCComplex PyComplex_FromCComplex PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyComplex_Type DATA PyContextToken_Type DATA PyContextVar_Get PyContextVar_New PyContextVar_Reset PyContextVar_Set PyContextVar_Type DATA PyContext_ClearFreeList PyContext_Copy PyContext_CopyCurrent PyContext_Enter PyContext_Exit PyContext_New PyContext_Type DATA PyCoro_New PyCoro_Type DATA PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDescr_NewWrapper PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_New PyDictProxy_Type DATA PyDictValues_Type DATA PyDict_Clear PyDict_ClearFreeList PyDict_Contains PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_Fini PyDict_GetItem PyDict_GetItemString PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_SetDefault PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Type DATA PyDict_Update PyDict_Values PyEllipsis_Type DATA PyEnum_Type DATA PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_FormatV PyErr_GetExcInfo PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_ProgramTextObject PyErr_ResourceWarning PyErr_Restore PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetExcFromWindowsErrWithUnicodeFilename PyErr_SetExcInfo PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetFromErrnoWithFilenameObjects PyErr_SetFromErrnoWithUnicodeFilename PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyErr_SetFromWindowsErrWithUnicodeFilename PyErr_SetImportError PyErr_SetImportErrorSubclass PyErr_SetInterrupt PyErr_SetNone PyErr_SetObject PyErr_SetString PyErr_SyntaxLocation PyErr_SyntaxLocationEx PyErr_SyntaxLocationObject PyErr_Warn PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnExplicitFormat PyErr_WarnExplicitObject PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_MergeCompilerFlags PyEval_ReInitThreads PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_SetProfile PyEval_SetTrace PyEval_ThreadsInitialized PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_ModuleNotFoundError DATA PyExc_NameError DATA PyExc_NotADirectoryError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_RecursionError DATA PyExc_ReferenceError DATA PyExc_ResourceWarning DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopAsyncIteration DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TimeoutError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_WindowsError DATA PyExc_ZeroDivisionError DATA PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_NewStdPrinter PyFile_WriteObject PyFile_WriteString PyFilter_Type DATA PyFloat_AsDouble PyFloat_ClearFreeList PyFloat_Fini PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFloat_Type DATA PyFrame_BlockPop PyFrame_BlockSetup PyFrame_ClearFreeList PyFrame_FastToLocals PyFrame_FastToLocalsWithError PyFrame_Fini PyFrame_GetLineNumber PyFrame_LocalsToFast PyFrame_New PyFrame_Type DATA PyFrozenSet_New PyFrozenSet_Type DATA PyFunction_GetAnnotations PyFunction_GetClosure PyFunction_GetCode PyFunction_GetDefaults PyFunction_GetGlobals PyFunction_GetKwDefaults PyFunction_GetModule PyFunction_New PyFunction_NewWithQualName PyFunction_SetAnnotations PyFunction_SetClosure PyFunction_SetDefaults PyFunction_SetKwDefaults PyFunction_Type DATA PyFuture_FromAST PyFuture_FromASTObject PyGC_Collect PyGILState_Check PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyGen_NeedsFinalizing PyGen_New PyGen_NewWithQualName PyGen_Type DATA PyGetSetDescr_Type DATA PyHash_GetFuncDef PyImport_AddModule PyImport_AddModuleObject PyImport_AppendInittab PyImport_Cleanup PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleObject PyImport_ExecCodeModuleWithPathnames PyImport_ExtendInittab PyImport_FrozenModules DATA PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModule PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportFrozenModuleObject PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleLevelObject PyImport_ImportModuleNoBlock PyImport_Inittab DATA PyImport_ReloadModule PyInstanceMethod_Function PyInstanceMethod_New PyInstanceMethod_Type DATA PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_GetID PyInterpreterState_Head PyInterpreterState_Main PyInterpreterState_New PyInterpreterState_Next PyInterpreterState_ThreadHead PyIter_Next PyListIter_Type DATA PyListRevIter_Type DATA PyList_Append PyList_AsTuple PyList_ClearFreeList PyList_Fini PyList_GetItem PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyList_Type DATA PyLongRangeIter_Type DATA PyLong_AsDouble PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnicode PyLong_FromUnicodeObject PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromVoidPtr PyLong_GetInfo PyLong_Type DATA PyMap_Type DATA PyMapping_Check PyMapping_GetItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMarshal_ReadLastObjectFromFile PyMarshal_ReadLongFromFile PyMarshal_ReadObjectFromFile PyMarshal_ReadObjectFromString PyMarshal_ReadShortFromFile PyMarshal_WriteLongToFile PyMarshal_WriteObjectToFile PyMarshal_WriteObjectToString PyMem_Calloc PyMem_Free PyMem_GetAllocator PyMem_Malloc PyMem_RawCalloc PyMem_RawFree PyMem_RawMalloc PyMem_RawRealloc PyMem_Realloc PyMem_SetAllocator PyMem_SetupDebugHooks PyMemberDescr_Type DATA PyMember_GetOne PyMember_SetOne PyMemoryView_FromBuffer PyMemoryView_FromMemory PyMemoryView_FromObject PyMemoryView_GetContiguous PyMemoryView_Type DATA PyMethodDescr_Type DATA PyMethod_ClearFreeList PyMethod_Fini PyMethod_Function PyMethod_New PyMethod_Self PyMethod_Type DATA PyModuleDef_Init PyModuleDef_Type DATA PyModule_AddFunctions PyModule_AddIntConstant PyModule_AddObject PyModule_AddStringConstant PyModule_Create2 PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetNameObject PyModule_GetState PyModule_New PyModule_NewObject PyModule_SetDocString PyModule_Type DATA PyNode_AddChild PyNode_Compile PyNode_Free PyNode_ListTree PyNode_New PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMatrixMultiply PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_MatrixMultiply PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyODictItems_Type DATA PyODictIter_Type DATA PyODictKeys_Type DATA PyODictValues_Type DATA PyODict_DelItem PyODict_New PyODict_SetItem PyODict_Type DATA PyOS_AfterFork PyOS_FSPath PyOS_FiniInterrupts PyOS_InitInterrupts PyOS_InputHook DATA PyOS_InterruptOccurred PyOS_Readline PyOS_ReadlineFunctionPointer DATA PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsCharBuffer PyObject_AsFileDescriptor PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_Bytes PyObject_Call PyObject_CallFinalizer PyObject_CallFinalizerFromDealloc PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallObject PyObject_Calloc PyObject_CheckReadBuffer PyObject_ClearWeakRefs PyObject_CopyData PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_Track PyObject_GC_UnTrack PyObject_GenericGetAttr PyObject_GenericGetDict PyObject_GenericSetAttr PyObject_GenericSetDict PyObject_GetArenaAllocator PyObject_GetAttr PyObject_GetAttrString PyObject_GetBuffer PyObject_GetItem PyObject_GetIter PyObject_HasAttr PyObject_HasAttrString PyObject_Hash PyObject_HashNotImplemented PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_LengthHint PyObject_Malloc PyObject_Not PyObject_Print PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetArenaAllocator PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PyParser_ASTFromFile PyParser_ASTFromFileObject PyParser_ASTFromString PyParser_ASTFromStringObject PyParser_ClearError PyParser_ParseFile PyParser_ParseFileFlags PyParser_ParseFileFlagsEx PyParser_ParseFileObject PyParser_ParseString PyParser_ParseStringFlags PyParser_ParseStringFlagsFilename PyParser_ParseStringFlagsFilenameEx PyParser_ParseStringObject PyParser_SetError PyParser_SimpleParseFile PyParser_SimpleParseFileFlags PyParser_SimpleParseString PyParser_SimpleParseStringFlags PyParser_SimpleParseStringFlagsFilename PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyReversed_Type DATA PyRun_AnyFile PyRun_AnyFileEx PyRun_AnyFileExFlags PyRun_AnyFileFlags PyRun_File PyRun_FileEx PyRun_FileExFlags PyRun_FileFlags PyRun_InteractiveLoop PyRun_InteractiveLoopFlags PyRun_InteractiveOne PyRun_InteractiveOneFlags PyRun_InteractiveOneObject PyRun_SimpleFile PyRun_SimpleFileEx PyRun_SimpleFileExFlags PyRun_SimpleString PyRun_SimpleStringFlags PyRun_String PyRun_StringFlags PySTEntry_Type DATA PyST_GetScope PySeqIter_New PySeqIter_Type DATA PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySetIter_Type DATA PySet_Add PySet_Clear PySet_ClearFreeList PySet_Contains PySet_Discard PySet_Fini PySet_New PySet_Pop PySet_Size PySet_Type DATA PySlice_AdjustIndices PySlice_Fini PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PySlice_Type DATA PySlice_Unpack PyState_AddModule PyState_FindModule PyState_RemoveModule PyStaticMethod_New PyStaticMethod_Type DATA PyStdPrinter_Type DATA PyStructSequence_GetItem PyStructSequence_InitType PyStructSequence_InitType2 PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PySuper_Type DATA PySymtable_Build PySymtable_BuildObject PySymtable_Free PySymtable_Lookup PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_AddXOption PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_GetXOptions PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_Get PyThreadState_GetDict PyThreadState_New PyThreadState_Next PyThreadState_SetAsyncExc PyThreadState_Swap PyThread_GetInfo PyThread_ReInitTLS PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_allocate_lock PyThread_create_key PyThread_delete_key PyThread_delete_key_value PyThread_exit_thread PyThread_free_lock PyThread_get_key_value PyThread_get_stacksize PyThread_get_thread_ident PyThread_init_thread PyThread_release_lock PyThread_set_key_value PyThread_set_stacksize PyThread_start_new_thread PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyToken_OneChar PyToken_ThreeChars PyToken_TwoChars PyTraceBack_Here PyTraceBack_Print PyTraceBack_Type DATA PyTraceMalloc_Track PyTraceMalloc_Untrack PyTupleIter_Type DATA PyTuple_ClearFreeList PyTuple_Fini PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyTuple_Type DATA PyType_ClearCache PyType_FromSpec PyType_FromSpecWithBases PyType_GenericAlloc PyType_GenericNew PyType_GetFlags PyType_GetSlot PyType_IsSubtype PyType_Modified PyType_Ready PyType_Type DATA PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_Create PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeIter_Type DATA PyUnicodeTranslateError_Create PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsMBCSString PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8 PyUnicode_AsUTF8AndSize PyUnicode_AsUTF8String PyUnicode_AsUnicode PyUnicode_AsUnicodeAndSize PyUnicode_AsUnicodeCopy PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_AsWideCharString PyUnicode_BuildEncodingMap PyUnicode_ClearFreeList PyUnicode_Compare PyUnicode_CompareWithASCIIString PyUnicode_Concat PyUnicode_Contains PyUnicode_CopyCharacters PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeCodePageStateful PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_Encode PyUnicode_EncodeASCII PyUnicode_EncodeCharmap PyUnicode_EncodeCodePage PyUnicode_EncodeDecimal PyUnicode_EncodeFSDefault PyUnicode_EncodeLatin1 PyUnicode_EncodeLocale PyUnicode_EncodeMBCS PyUnicode_EncodeRawUnicodeEscape PyUnicode_EncodeUTF16 PyUnicode_EncodeUTF32 PyUnicode_EncodeUTF7 PyUnicode_EncodeUTF8 PyUnicode_EncodeUnicodeEscape PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Fill PyUnicode_Find PyUnicode_FindChar PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromKindAndData PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromUnicode PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetLength PyUnicode_GetMax PyUnicode_GetSize PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_New PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_ReadChar PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Substring PyUnicode_Tailmatch PyUnicode_TransformDecimalToASCII PyUnicode_Translate PyUnicode_TranslateCharmap PyUnicode_Type DATA PyUnicode_WriteChar PyWeakref_GetObject PyWeakref_NewProxy PyWeakref_NewRef PyWrapperDescr_Type DATA PyWrapper_New PyZip_Type DATA Py_AddPendingCall Py_AtExit Py_BuildValue Py_BytesWarningFlag DATA Py_CompileString Py_CompileStringExFlags Py_CompileStringFlags Py_CompileStringObject Py_DebugFlag DATA Py_DecRef Py_DecodeLocale Py_DontWriteBytecodeFlag DATA Py_EncodeLocale Py_EndInterpreter Py_Exit Py_FatalError Py_FdIsInteractive Py_FileSystemDefaultEncodeErrors DATA Py_FileSystemDefaultEncoding DATA Py_Finalize Py_FinalizeEx Py_FrozenFlag DATA Py_GetBuildInfo Py_GetCompiler Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_HasFileSystemDefaultEncoding DATA Py_HashRandomizationFlag DATA Py_IgnoreEnvironmentFlag DATA Py_IncRef Py_Initialize Py_InitializeEx Py_InspectFlag DATA Py_InteractiveFlag DATA Py_IsInitialized Py_IsolatedFlag DATA Py_LegacyWindowsFSEncodingFlag DATA Py_LegacyWindowsStdioFlag DATA Py_Main Py_MakePendingCalls Py_NewInterpreter Py_NoSiteFlag DATA Py_NoUserSiteDirectory DATA Py_OptimizeFlag DATA Py_QuietFlag DATA Py_ReprEnter Py_ReprLeave Py_SetPath Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_SetStandardStreamEncoding Py_SymtableString Py_SymtableStringObject Py_UNICODE_strcat Py_UNICODE_strchr Py_UNICODE_strcmp Py_UNICODE_strcpy Py_UNICODE_strlen Py_UNICODE_strncmp Py_UNICODE_strncpy Py_UNICODE_strrchr Py_UTF8Mode DATA Py_UnbufferedStdioFlag DATA Py_UniversalNewlineFgets Py_VaBuildValue Py_VerboseFlag DATA Py_hexdigits DATA _PyAST_Optimize _PyAccu_Accumulate _PyAccu_Destroy _PyAccu_Finish _PyAccu_FinishAsList _PyAccu_Init _PyArg_NoKeywords _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT _PyArg_Parse_SizeT _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyArg_VaParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyAsyncGenASend_Type DATA _PyAsyncGenAThrow_Type DATA _PyAsyncGenWrappedValue_Type DATA _PyBuiltin_Init _PyByteArray_empty_string DATA _PyBytesWriter_Alloc _PyBytesWriter_Dealloc _PyBytesWriter_Finish _PyBytesWriter_Init _PyBytesWriter_Prepare _PyBytesWriter_Resize _PyBytesWriter_WriteBytes _PyBytes_DecodeEscape _PyBytes_FormatEx _PyBytes_FromHex _PyBytes_Join _PyBytes_Resize _PyCFunction_DebugMallocStats _PyCFunction_FastCallDict _PyCFunction_FastCallKeywords _PyCode_CheckLineNumber _PyCode_ConstantKey _PyCode_GetExtra _PyCode_SetExtra _PyCodecInfo_GetIncrementalDecoder _PyCodecInfo_GetIncrementalEncoder _PyCodec_DecodeText _PyCodec_EncodeText _PyCodec_Forget _PyCodec_Lookup _PyCodec_LookupTextEncoding _PyComplex_FormatAdvancedWriter _PyContext_NewHamtForTests _PyCoreConfig_AsDict _PyCoreConfig_Clear _PyCoreConfig_Copy _PyCoreConfig_Read _PyCoreConfig_SetGlobalConfig _PyCoroWrapper_Type DATA _PyDebugAllocatorStats _PyDictView_Intersect _PyDict_Contains _PyDict_DebugMallocStats _PyDict_DelItemId _PyDict_DelItemIf _PyDict_DelItem_KnownHash _PyDict_GetItemId _PyDict_GetItemIdWithError _PyDict_GetItem_KnownHash _PyDict_HasOnlyStringKeys _PyDict_MaybeUntrack _PyDict_MergeEx _PyDict_NewPresized _PyDict_Next _PyDict_Pop _PyDict_SetItemId _PyDict_SetItem_KnownHash _PyDict_SizeOf _PyErr_BadInternalCall _PyErr_ChainExceptions _PyErr_FormatFromCause _PyErr_SetKeyError _PyErr_TrySetFromCause _PyEval_CallTracing _PyEval_EvalCodeWithName _PyEval_EvalFrameDefault _PyEval_FiniThreads _PyEval_GetAsyncGenFinalizer _PyEval_GetAsyncGenFirstiter _PyEval_GetBuiltinId _PyEval_GetCoroutineOriginTrackingDepth _PyEval_GetCoroutineWrapper _PyEval_GetSwitchInterval _PyEval_Initialize _PyEval_RequestCodeExtraIndex _PyEval_SetAsyncGenFinalizer _PyEval_SetAsyncGenFirstiter _PyEval_SetCoroutineOriginTrackingDepth _PyEval_SetCoroutineWrapper _PyEval_SetSwitchInterval _PyEval_SignalAsyncExc _PyEval_SignalReceived _PyEval_SliceIndex _PyEval_SliceIndexNotNone _PyExc_Fini _PyExc_Init _PyFloat_DebugMallocStats _PyFloat_FormatAdvancedWriter _PyFloat_Init _PyFloat_Pack2 _PyFloat_Pack4 _PyFloat_Pack8 _PyFloat_Unpack2 _PyFloat_Unpack4 _PyFloat_Unpack8 _PyFrame_DebugMallocStats _PyFrame_Init _PyFunction_FastCallDict _PyFunction_FastCallKeywords _PyGC_CollectIfEnabled _PyGC_CollectNoFail _PyGC_DumpShutdownStats _PyGC_Fini _PyGC_Initialize _PyGILState_GetInterpreterStateUnsafe _PyGILState_Reinit _PyGen_FetchStopIterationValue _PyGen_Finalize _PyGen_Send _PyGen_SetStopIterationValue _PyHamtItems_Type DATA _PyHamtKeys_Type DATA _PyHamtValues_Type DATA _PyHamt_ArrayNode_Type DATA _PyHamt_BitmapNode_Type DATA _PyHamt_CollisionNode_Type DATA _PyHamt_Type DATA _PyImportHooks_Init _PyImportZip_Init _PyImport_AcquireLock _PyImport_AddModuleObject _PyImport_FindBuiltin _PyImport_FindExtensionObject _PyImport_FindExtensionObjectEx _PyImport_Fini _PyImport_Fini2 _PyImport_FixupBuiltin _PyImport_FixupExtensionObject _PyImport_GetModuleId _PyImport_Init _PyImport_IsInitialized _PyImport_ReInitLock _PyImport_ReleaseLock _PyImport_SetModule _PyImport_SetModuleString _PyInterpreterState_Enable _PyInterpreterState_IDDecref _PyInterpreterState_IDIncref _PyInterpreterState_IDInitref _PyInterpreterState_LookUpID _PyList_DebugMallocStats _PyList_Extend _PyLong_AsByteArray _PyLong_AsInt _PyLong_AsTime_t _PyLong_Copy _PyLong_DigitValue DATA _PyLong_DivmodNear _PyLong_Format _PyLong_FormatAdvancedWriter _PyLong_FormatBytesWriter _PyLong_FormatWriter _PyLong_Frexp _PyLong_FromByteArray _PyLong_FromBytes _PyLong_FromNbInt _PyLong_FromTime_t _PyLong_GCD _PyLong_New _PyLong_NumBits _PyLong_One DATA _PyLong_Sign _PyLong_Zero DATA _PyMainInterpreterConfig_AsDict _PyMainInterpreterConfig_Clear _PyMainInterpreterConfig_Copy _PyMainInterpreterConfig_Read _PyManagedBuffer_Type DATA _PyMem_GetAllocatorsName _PyMem_RawStrdup _PyMem_RawWcsdup _PyMem_SetDefaultAllocator _PyMem_SetupAllocators _PyMem_Strdup _PyMethodDef_RawFastCallDict _PyMethodDef_RawFastCallKeywords _PyMethodDescr_FastCallKeywords _PyMethodWrapper_Type DATA _PyMethod_DebugMallocStats _PyModule_Clear _PyModule_ClearDict _PyModule_CreateInitialized _PyNamespace_New _PyNamespace_Type DATA _PyNode_SizeOf _PyNone_Type DATA _PyNotImplemented_Type DATA _PyOS_IsMainThread _PyOS_ReadlineTState DATA _PyOS_SigintEvent _PyOS_URandom _PyOS_URandomNonblock _PyObject_CallFunction_SizeT _PyObject_CallMethodId _PyObject_CallMethodIdObjArgs _PyObject_CallMethodId_SizeT _PyObject_CallMethod_SizeT _PyObject_Call_Prepend _PyObject_DebugMallocStats _PyObject_DebugTypeStats _PyObject_Dump _PyObject_FastCallDict _PyObject_FastCallKeywords _PyObject_FastCall_Prepend _PyObject_GC_Calloc _PyObject_GC_Malloc _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_GenericGetAttrWithDict _PyObject_GenericSetAttrWithDict _PyObject_GetAttrId _PyObject_GetBuiltin _PyObject_GetDictPtr _PyObject_HasAttrId _PyObject_HasFastCall _PyObject_HasLen _PyObject_IsAbstract _PyObject_IsFreed _PyObject_LookupAttr _PyObject_LookupAttrId _PyObject_LookupSpecial _PyObject_New _PyObject_NewVar _PyObject_NextNotImplemented _PyObject_RealIsInstance _PyObject_RealIsSubclass _PyObject_SetAttrId _PyParser_Grammar DATA _PyParser_TokenNames DATA _PyPathConfig_Calculate _PyPathConfig_Clear _PyPathConfig_ComputeArgv0 _PyPathConfig_Init _PyRuntime DATA _PyRuntimeState_Fini _PyRuntimeState_Init _PyRuntime_Finalize _PyRuntime_Initialize _PySequence_BytesToCharpArray _PySequence_IterSearch _PySet_Dummy DATA _PySet_NextEntry _PySet_Update _PySignal_AfterFork _PySlice_FromIndices _PySlice_GetLongIndices _PyStack_AsDict _PyStack_AsTuple _PyStack_AsTupleSlice _PyStack_UnpackDict _PyState_AddModule _PyState_ClearModules _PySys_AddWarnOptionWithError _PySys_AddXOptionWithError _PySys_BeginInit _PySys_EndInit _PySys_GetObjectId _PySys_GetSizeOf _PySys_SetObjectId _PyThreadState_DeleteExcept _PyThreadState_Init _PyThreadState_Prealloc _PyThreadState_UncheckedGet _PyThread_CurrentFrames _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_noraise _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetPerfCounter _PyTime_GetPerfCounterWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_Init _PyTime_MulDiv _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyTraceMalloc_GetTraceback _PyTraceback_Add _PyTrash_deposit_object _PyTrash_destroy_chain _PyTrash_thread_deposit_object _PyTrash_thread_destroy_chain _PyTuple_DebugMallocStats _PyTuple_MaybeUntrack _PyTuple_Resize _PyType_CalculateMetaclass _PyType_Fini _PyType_GetDocFromInternalDoc _PyType_GetTextSignatureFromInternalDoc _PyType_Lookup _PyType_LookupId _PyType_Name _PyUnicodeTranslateError_Create _PyUnicodeWriter_Dealloc _PyUnicodeWriter_Finish _PyUnicodeWriter_Init _PyUnicodeWriter_PrepareInternal _PyUnicodeWriter_PrepareKindInternal _PyUnicodeWriter_WriteASCIIString _PyUnicodeWriter_WriteChar _PyUnicodeWriter_WriteLatin1String _PyUnicodeWriter_WriteStr _PyUnicodeWriter_WriteSubstring _PyUnicode_AsASCIIString _PyUnicode_AsKind _PyUnicode_AsLatin1String _PyUnicode_AsUTF8String _PyUnicode_AsUnicode _PyUnicode_ClearStaticStrings _PyUnicode_Copy _PyUnicode_DecodeUnicodeEscape _PyUnicode_EQ _PyUnicode_EncodeCharmap _PyUnicode_EncodeUTF16 _PyUnicode_EncodeUTF32 _PyUnicode_EncodeUTF7 _PyUnicode_EqualToASCIIId _PyUnicode_EqualToASCIIString _PyUnicode_FastCopyCharacters _PyUnicode_FastFill _PyUnicode_FindMaxChar _PyUnicode_FormatAdvancedWriter _PyUnicode_FormatLong _PyUnicode_FromASCII _PyUnicode_FromId _PyUnicode_InsertThousandsGrouping _PyUnicode_IsAlpha _PyUnicode_IsCaseIgnorable _PyUnicode_IsCased _PyUnicode_IsDecimalDigit _PyUnicode_IsDigit _PyUnicode_IsLinebreak _PyUnicode_IsLowercase _PyUnicode_IsNumeric _PyUnicode_IsPrintable _PyUnicode_IsTitlecase _PyUnicode_IsUppercase _PyUnicode_IsWhitespace _PyUnicode_IsXidContinue _PyUnicode_IsXidStart _PyUnicode_JoinArray _PyUnicode_Ready _PyUnicode_ToDecimalDigit _PyUnicode_ToDigit _PyUnicode_ToFoldedFull _PyUnicode_ToLowerFull _PyUnicode_ToLowercase _PyUnicode_ToNumeric _PyUnicode_ToTitleFull _PyUnicode_ToTitlecase _PyUnicode_ToUpperFull _PyUnicode_ToUppercase _PyUnicode_TransformDecimalAndSpaceToASCII _PyUnicode_XStrip _PyWarnings_Init _PyWeakref_CallableProxyType DATA _PyWeakref_ClearRef _PyWeakref_GetWeakrefCount _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _PyWindowsConsoleIO_Type DATA _Py_BreakPoint _Py_BuildValue_SizeT _Py_CheckFunctionResult _Py_CheckRecursionLimit DATA _Py_CheckRecursiveCall _Py_CoerceLegacyLocale _Py_Dealloc _Py_DecodeLocaleEx _Py_DecodeUTF8Ex _Py_DecodeUTF8_surrogateescape _Py_DisplaySourceLine _Py_DumpASCII _Py_DumpDecimal _Py_DumpHexadecimal _Py_DumpTraceback _Py_DumpTracebackThreads _Py_EllipsisObject DATA _Py_EncodeLocaleEx _Py_EncodeLocaleRaw _Py_EncodeUTF8Ex _Py_FalseStruct DATA _Py_FatalInitError _Py_FindEnvConfigValue _Py_FreeCharPArray _Py_GetAllocatedBlocks _Py_GetForceASCII _Py_GetGlobalVariablesAsDict _Py_GetLocaleconvNumeric _Py_HashBytes _Py_HashDouble _Py_HashPointer _Py_HashRandomization_Fini _Py_HashRandomization_Init _Py_HashSecret DATA _Py_InitializeCore _Py_InitializeFromConfig _Py_InitializeMainInterpreter _Py_Initialize_ReadEnvVarsNoAlloc _Py_IsCoreInitialized _Py_IsFinalizing _Py_LegacyLocaleDetected _Py_Mangle _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_PackageContext DATA _Py_PyAtExit _Py_ReadHashSeed _Py_ReleaseInternedUnicodeStrings _Py_ResetForceASCII _Py_RestoreSignals _Py_SetLocaleFromEnv _Py_SetProgramFullPath _Py_SwappedOp DATA _Py_TrueStruct DATA _Py_UnixMain _Py_VaBuildStack _Py_VaBuildStack_SizeT _Py_VaBuildValue_SizeT _Py_add_one_to_index_C _Py_add_one_to_index_F _Py_ascii_whitespace DATA _Py_c_abs _Py_c_diff _Py_c_neg _Py_c_pow _Py_c_prod _Py_c_quot _Py_c_sum _Py_convert_optional_to_ssize_t _Py_ctype_table DATA _Py_ctype_tolower DATA _Py_ctype_toupper DATA _Py_device_encoding _Py_dg_dtoa _Py_dg_freedtoa _Py_dg_infinity _Py_dg_stdnan _Py_dg_strtod _Py_dup _Py_fopen _Py_fopen_obj _Py_fstat _Py_fstat_noraise _Py_get_inheritable _Py_gitidentifier _Py_gitversion _Py_hashtable_clear _Py_hashtable_compare_direct _Py_hashtable_copy _Py_hashtable_destroy _Py_hashtable_foreach _Py_hashtable_get _Py_hashtable_get_entry _Py_hashtable_hash_ptr _Py_hashtable_new _Py_hashtable_new_full _Py_hashtable_pop _Py_hashtable_set _Py_hashtable_size _Py_open _Py_open_noraise _Py_parse_inf_or_nan _Py_path_config DATA _Py_read _Py_set_inheritable _Py_set_inheritable_async_safe _Py_stat _Py_strhex _Py_strhex_bytes _Py_string_to_number_with_underscores _Py_wfopen _Py_wgetcwd _Py_write _Py_write_noraise python3-dll-a/src/python38.def0000644000175000017500000010404714661133735017105 0ustar jamespagejamespage; ; Definition file of python38.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "python38.dll" EXPORTS PyAST_CompileEx PyAST_CompileObject PyAST_FromNode PyAST_FromNodeObject PyAST_Validate PyArena_AddPyObject PyArena_Free PyArena_Malloc PyArena_New PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyAsyncGen_New PyAsyncGen_Type DATA PyBaseObject_Type DATA PyBool_FromLong PyBool_Type DATA PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_FromContiguous PyBuffer_GetPointer PyBuffer_IsContiguous PyBuffer_Release PyBuffer_ToContiguous PyByteArrayIter_Type DATA PyByteArray_AsString PyByteArray_Concat PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Resize PyByteArray_Size PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyBytes_Type DATA PyCFunction_Call PyCFunction_ClearFreeList PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_NewEx PyCFunction_Type DATA PyCallIter_New PyCallIter_Type DATA PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCapsule_Type DATA PyCell_Get PyCell_New PyCell_Set PyCell_Type DATA PyClassMethodDescr_Type DATA PyClassMethod_New PyClassMethod_Type DATA PyCode_Addr2Line PyCode_New PyCode_NewEmpty PyCode_NewWithPosOnlyArgs PyCode_Optimize PyCode_Type DATA PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_NameReplaceErrors PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_XMLCharRefReplaceErrors PyCompile_OpcodeStackEffect PyCompile_OpcodeStackEffectWithJump PyComplex_AsCComplex PyComplex_FromCComplex PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyComplex_Type DATA PyConfig_Clear PyConfig_InitIsolatedConfig PyConfig_InitPythonConfig PyConfig_Read PyConfig_SetArgv PyConfig_SetBytesArgv PyConfig_SetBytesString PyConfig_SetString PyConfig_SetWideStringList PyContextToken_Type DATA PyContextVar_Get PyContextVar_New PyContextVar_Reset PyContextVar_Set PyContextVar_Type DATA PyContext_ClearFreeList PyContext_Copy PyContext_CopyCurrent PyContext_Enter PyContext_Exit PyContext_New PyContext_Type DATA PyCoro_New PyCoro_Type DATA PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDescr_NewWrapper PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_New PyDictProxy_Type DATA PyDictRevIterItem_Type DATA PyDictRevIterKey_Type DATA PyDictRevIterValue_Type DATA PyDictValues_Type DATA PyDict_Clear PyDict_ClearFreeList PyDict_Contains PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_GetItem PyDict_GetItemString PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_SetDefault PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Type DATA PyDict_Update PyDict_Values PyEllipsis_Type DATA PyEnum_Type DATA PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_FormatV PyErr_GetExcInfo PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_ProgramTextObject PyErr_ResourceWarning PyErr_Restore PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetExcFromWindowsErrWithUnicodeFilename PyErr_SetExcInfo PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetFromErrnoWithFilenameObjects PyErr_SetFromErrnoWithUnicodeFilename PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyErr_SetFromWindowsErrWithUnicodeFilename PyErr_SetImportError PyErr_SetImportErrorSubclass PyErr_SetInterrupt PyErr_SetNone PyErr_SetObject PyErr_SetString PyErr_SyntaxLocation PyErr_SyntaxLocationEx PyErr_SyntaxLocationObject PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnExplicitFormat PyErr_WarnExplicitObject PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_MergeCompilerFlags PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_SetProfile PyEval_SetTrace PyEval_ThreadsInitialized PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_ModuleNotFoundError DATA PyExc_NameError DATA PyExc_NotADirectoryError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_RecursionError DATA PyExc_ReferenceError DATA PyExc_ResourceWarning DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopAsyncIteration DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TimeoutError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_WindowsError DATA PyExc_ZeroDivisionError DATA PyExceptionClass_Name PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_NewStdPrinter PyFile_OpenCode PyFile_OpenCodeObject PyFile_SetOpenCodeHook PyFile_WriteObject PyFile_WriteString PyFilter_Type DATA PyFloat_AsDouble PyFloat_ClearFreeList PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFloat_Type DATA PyFrame_BlockPop PyFrame_BlockSetup PyFrame_ClearFreeList PyFrame_FastToLocals PyFrame_FastToLocalsWithError PyFrame_GetLineNumber PyFrame_LocalsToFast PyFrame_New PyFrame_Type DATA PyFrozenSet_New PyFrozenSet_Type DATA PyFunction_GetAnnotations PyFunction_GetClosure PyFunction_GetCode PyFunction_GetDefaults PyFunction_GetGlobals PyFunction_GetKwDefaults PyFunction_GetModule PyFunction_New PyFunction_NewWithQualName PyFunction_SetAnnotations PyFunction_SetClosure PyFunction_SetDefaults PyFunction_SetKwDefaults PyFunction_Type DATA PyFuture_FromAST PyFuture_FromASTObject PyGC_Collect PyGILState_Check PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyGen_NeedsFinalizing PyGen_New PyGen_NewWithQualName PyGen_Type DATA PyGetSetDescr_Type DATA PyHash_GetFuncDef PyImport_AddModule PyImport_AddModuleObject PyImport_AppendInittab PyImport_Cleanup PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleObject PyImport_ExecCodeModuleWithPathnames PyImport_ExtendInittab PyImport_FrozenModules DATA PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModule PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportFrozenModuleObject PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleLevelObject PyImport_ImportModuleNoBlock PyImport_Inittab DATA PyImport_ReloadModule PyIndex_Check PyInstanceMethod_Function PyInstanceMethod_New PyInstanceMethod_Type DATA PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_GetDict PyInterpreterState_GetID PyInterpreterState_Head PyInterpreterState_Main PyInterpreterState_New PyInterpreterState_Next PyInterpreterState_ThreadHead PyIter_Check PyIter_Next PyListIter_Type DATA PyListRevIter_Type DATA PyList_Append PyList_AsTuple PyList_ClearFreeList PyList_GetItem PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyList_Type DATA PyLongRangeIter_Type DATA PyLong_AsDouble PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnicode PyLong_FromUnicodeObject PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromVoidPtr PyLong_GetInfo PyLong_Type DATA PyMap_Type DATA PyMapping_Check PyMapping_GetItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMarshal_ReadLastObjectFromFile PyMarshal_ReadLongFromFile PyMarshal_ReadObjectFromFile PyMarshal_ReadObjectFromString PyMarshal_ReadShortFromFile PyMarshal_WriteLongToFile PyMarshal_WriteObjectToFile PyMarshal_WriteObjectToString PyMem_Calloc PyMem_Free PyMem_GetAllocator PyMem_Malloc PyMem_RawCalloc PyMem_RawFree PyMem_RawMalloc PyMem_RawRealloc PyMem_Realloc PyMem_SetAllocator PyMem_SetupDebugHooks PyMemberDescr_Type DATA PyMember_GetOne PyMember_SetOne PyMemoryView_FromBuffer PyMemoryView_FromMemory PyMemoryView_FromObject PyMemoryView_GetContiguous PyMemoryView_Type DATA PyMethodDescr_Type DATA PyMethod_ClearFreeList PyMethod_Function PyMethod_New PyMethod_Self PyMethod_Type DATA PyModuleDef_Init PyModuleDef_Type DATA PyModule_AddFunctions PyModule_AddIntConstant PyModule_AddObject PyModule_AddStringConstant PyModule_Create2 PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetNameObject PyModule_GetState PyModule_New PyModule_NewObject PyModule_SetDocString PyModule_Type DATA PyNode_AddChild PyNode_Compile PyNode_Free PyNode_ListTree PyNode_New PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMatrixMultiply PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_MatrixMultiply PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyODictItems_Type DATA PyODictIter_Type DATA PyODictKeys_Type DATA PyODictValues_Type DATA PyODict_DelItem PyODict_New PyODict_SetItem PyODict_Type DATA PyOS_AfterFork PyOS_FSPath PyOS_InitInterrupts PyOS_InputHook DATA PyOS_InterruptOccurred PyOS_Readline PyOS_ReadlineFunctionPointer DATA PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsCharBuffer PyObject_AsFileDescriptor PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_Bytes PyObject_Call PyObject_CallFinalizer PyObject_CallFinalizerFromDealloc PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallObject PyObject_Calloc PyObject_CheckReadBuffer PyObject_ClearWeakRefs PyObject_CopyData PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_Track PyObject_GC_UnTrack PyObject_GenericGetAttr PyObject_GenericGetDict PyObject_GenericSetAttr PyObject_GenericSetDict PyObject_GetArenaAllocator PyObject_GetAttr PyObject_GetAttrString PyObject_GetBuffer PyObject_GetItem PyObject_GetIter PyObject_HasAttr PyObject_HasAttrString PyObject_Hash PyObject_HashNotImplemented PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_LengthHint PyObject_Malloc PyObject_Not PyObject_Print PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetArenaAllocator PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PyParser_ASTFromFile PyParser_ASTFromFileObject PyParser_ASTFromString PyParser_ASTFromStringObject PyParser_ClearError PyParser_ParseFile PyParser_ParseFileFlags PyParser_ParseFileFlagsEx PyParser_ParseFileObject PyParser_ParseString PyParser_ParseStringFlags PyParser_ParseStringFlagsFilename PyParser_ParseStringFlagsFilenameEx PyParser_ParseStringObject PyParser_SetError PyParser_SimpleParseFile PyParser_SimpleParseFileFlags PyParser_SimpleParseString PyParser_SimpleParseStringFlags PyParser_SimpleParseStringFlagsFilename PyPickleBuffer_FromObject PyPickleBuffer_GetBuffer PyPickleBuffer_Release PyPickleBuffer_Type DATA PyPreConfig_InitIsolatedConfig PyPreConfig_InitPythonConfig PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyReversed_Type DATA PyRun_AnyFile PyRun_AnyFileEx PyRun_AnyFileExFlags PyRun_AnyFileFlags PyRun_File PyRun_FileEx PyRun_FileExFlags PyRun_FileFlags PyRun_InteractiveLoop PyRun_InteractiveLoopFlags PyRun_InteractiveOne PyRun_InteractiveOneFlags PyRun_InteractiveOneObject PyRun_SimpleFile PyRun_SimpleFileEx PyRun_SimpleFileExFlags PyRun_SimpleString PyRun_SimpleStringFlags PyRun_String PyRun_StringFlags PySTEntry_Type DATA PyST_GetScope PySeqIter_New PySeqIter_Type DATA PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySetIter_Type DATA PySet_Add PySet_Clear PySet_ClearFreeList PySet_Contains PySet_Discard PySet_New PySet_Pop PySet_Size PySet_Type DATA PySlice_AdjustIndices PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PySlice_Type DATA PySlice_Unpack PyState_AddModule PyState_FindModule PyState_RemoveModule PyStaticMethod_New PyStaticMethod_Type DATA PyStatus_Error PyStatus_Exception PyStatus_Exit PyStatus_IsError PyStatus_IsExit PyStatus_NoMemory PyStatus_Ok PyStdPrinter_Type DATA PyStructSequence_GetItem PyStructSequence_InitType PyStructSequence_InitType2 PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PySuper_Type DATA PySymtable_Build PySymtable_BuildObject PySymtable_Free PySymtable_Lookup PySys_AddAuditHook PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_AddXOption PySys_Audit PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_GetXOptions PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_Get PyThreadState_GetDict PyThreadState_New PyThreadState_Next PyThreadState_SetAsyncExc PyThreadState_Swap PyThread_GetInfo PyThread_ReInitTLS PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_allocate_lock PyThread_create_key PyThread_delete_key PyThread_delete_key_value PyThread_exit_thread PyThread_free_lock PyThread_get_key_value PyThread_get_stacksize PyThread_get_thread_ident PyThread_get_thread_native_id PyThread_init_thread PyThread_release_lock PyThread_set_key_value PyThread_set_stacksize PyThread_start_new_thread PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyToken_OneChar PyToken_ThreeChars PyToken_TwoChars PyTraceBack_Here PyTraceBack_Print PyTraceBack_Type DATA PyTraceMalloc_Track PyTraceMalloc_Untrack PyTupleIter_Type DATA PyTuple_ClearFreeList PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyTuple_Type DATA PyType_ClearCache PyType_FromSpec PyType_FromSpecWithBases PyType_GenericAlloc PyType_GenericNew PyType_GetFlags PyType_GetSlot PyType_IsSubtype PyType_Modified PyType_Ready PyType_Type DATA PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_Create PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeIter_Type DATA PyUnicodeTranslateError_Create PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsMBCSString PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8 PyUnicode_AsUTF8AndSize PyUnicode_AsUTF8String PyUnicode_AsUnicode PyUnicode_AsUnicodeAndSize PyUnicode_AsUnicodeCopy PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_AsWideCharString PyUnicode_BuildEncodingMap PyUnicode_ClearFreeList PyUnicode_Compare PyUnicode_CompareWithASCIIString PyUnicode_Concat PyUnicode_Contains PyUnicode_CopyCharacters PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeCodePageStateful PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_Encode PyUnicode_EncodeASCII PyUnicode_EncodeCharmap PyUnicode_EncodeCodePage PyUnicode_EncodeDecimal PyUnicode_EncodeFSDefault PyUnicode_EncodeLatin1 PyUnicode_EncodeLocale PyUnicode_EncodeMBCS PyUnicode_EncodeRawUnicodeEscape PyUnicode_EncodeUTF16 PyUnicode_EncodeUTF32 PyUnicode_EncodeUTF7 PyUnicode_EncodeUTF8 PyUnicode_EncodeUnicodeEscape PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Fill PyUnicode_Find PyUnicode_FindChar PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromKindAndData PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromUnicode PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetLength PyUnicode_GetMax PyUnicode_GetSize PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_New PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_ReadChar PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Substring PyUnicode_Tailmatch PyUnicode_TransformDecimalToASCII PyUnicode_Translate PyUnicode_TranslateCharmap PyUnicode_Type DATA PyUnicode_WriteChar PyVectorcall_Call PyWeakref_GetObject PyWeakref_NewProxy PyWeakref_NewRef PyWideStringList_Append PyWideStringList_Insert PyWrapperDescr_Type DATA PyWrapper_New PyZip_Type DATA Py_AddPendingCall Py_AtExit Py_BuildValue Py_BytesMain Py_BytesWarningFlag DATA Py_CompileString Py_CompileStringExFlags Py_CompileStringFlags Py_CompileStringObject Py_DebugFlag DATA Py_DecRef Py_DecodeLocale Py_DontWriteBytecodeFlag DATA Py_EncodeLocale Py_EndInterpreter Py_Exit Py_ExitStatusException Py_FatalError Py_FdIsInteractive Py_FileSystemDefaultEncodeErrors DATA Py_FileSystemDefaultEncoding DATA Py_Finalize Py_FinalizeEx Py_FrozenFlag DATA Py_GetBuildInfo Py_GetCompiler Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_HasFileSystemDefaultEncoding DATA Py_HashRandomizationFlag DATA Py_IgnoreEnvironmentFlag DATA Py_IncRef Py_Initialize Py_InitializeEx Py_InitializeFromConfig Py_InspectFlag DATA Py_InteractiveFlag DATA Py_IsInitialized Py_IsolatedFlag DATA Py_LegacyWindowsFSEncodingFlag DATA Py_LegacyWindowsStdioFlag DATA Py_Main Py_MakePendingCalls Py_NewInterpreter Py_NoSiteFlag DATA Py_NoUserSiteDirectory DATA Py_OptimizeFlag DATA Py_PreInitialize Py_PreInitializeFromArgs Py_PreInitializeFromBytesArgs Py_QuietFlag DATA Py_ReprEnter Py_ReprLeave Py_RunMain Py_SetPath Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_SetStandardStreamEncoding Py_SymtableString Py_SymtableStringObject Py_UNICODE_strcat Py_UNICODE_strchr Py_UNICODE_strcmp Py_UNICODE_strcpy Py_UNICODE_strlen Py_UNICODE_strncmp Py_UNICODE_strncpy Py_UNICODE_strrchr Py_UTF8Mode DATA Py_UnbufferedStdioFlag DATA Py_UniversalNewlineFgets Py_VaBuildValue Py_VerboseFlag DATA Py_hexdigits DATA _PyAST_GetDocString _PyAST_Optimize _PyAccu_Accumulate _PyAccu_Destroy _PyAccu_Finish _PyAccu_FinishAsList _PyAccu_Init _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT _PyArg_Parse_SizeT _PyArg_UnpackKeywords _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyArg_VaParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyArgv_AsWstrList _PyAsyncGenASend_Type DATA _PyAsyncGenAThrow_Type DATA _PyAsyncGenWrappedValue_Type DATA _PyByteArray_empty_string DATA _PyBytesWriter_Alloc _PyBytesWriter_Dealloc _PyBytesWriter_Finish _PyBytesWriter_Init _PyBytesWriter_Prepare _PyBytesWriter_Resize _PyBytesWriter_WriteBytes _PyBytes_DecodeEscape _PyBytes_FormatEx _PyBytes_FromHex _PyBytes_Join _PyBytes_Resize _PyCFunction_DebugMallocStats _PyCFunction_FastCallDict _PyCode_CheckLineNumber _PyCode_ConstantKey _PyCode_GetExtra _PyCode_SetExtra _PyCodecInfo_GetIncrementalDecoder _PyCodecInfo_GetIncrementalEncoder _PyCodec_DecodeText _PyCodec_EncodeText _PyCodec_Forget _PyCodec_Lookup _PyCodec_LookupTextEncoding _PyComplex_FormatAdvancedWriter _PyConfig_InitCompatConfig _PyContext_NewHamtForTests _PyCoroWrapper_Type DATA _PyCrossInterpreterData_Lookup _PyCrossInterpreterData_NewObject _PyCrossInterpreterData_RegisterClass _PyCrossInterpreterData_Release _PyDebugAllocatorStats _PyDictView_Intersect _PyDictView_New _PyDict_CheckConsistency _PyDict_Contains _PyDict_DebugMallocStats _PyDict_DelItemId _PyDict_DelItemIf _PyDict_DelItem_KnownHash _PyDict_GetItemId _PyDict_GetItemIdWithError _PyDict_GetItemStringWithError _PyDict_GetItem_KnownHash _PyDict_HasOnlyStringKeys _PyDict_MaybeUntrack _PyDict_MergeEx _PyDict_NewPresized _PyDict_Next _PyDict_Pop _PyDict_SetItemId _PyDict_SetItem_KnownHash _PyDict_SizeOf _PyErr_BadInternalCall _PyErr_ChainExceptions _PyErr_CheckSignals _PyErr_Clear _PyErr_Display _PyErr_ExceptionMatches _PyErr_Fetch _PyErr_Format _PyErr_FormatFromCause _PyErr_NormalizeException _PyErr_Print _PyErr_Restore _PyErr_SetKeyError _PyErr_SetNone _PyErr_SetObject _PyErr_SetString _PyErr_TrySetFromCause _PyErr_WriteUnraisableMsg _PyEval_AddPendingCall _PyEval_CallTracing _PyEval_EvalCodeWithName _PyEval_EvalFrameDefault _PyEval_FiniThreads _PyEval_GetAsyncGenFinalizer _PyEval_GetAsyncGenFirstiter _PyEval_GetBuiltinId _PyEval_GetCoroutineOriginTrackingDepth _PyEval_GetSwitchInterval _PyEval_Initialize _PyEval_ReInitThreads _PyEval_RequestCodeExtraIndex _PyEval_SetAsyncGenFinalizer _PyEval_SetAsyncGenFirstiter _PyEval_SetCoroutineOriginTrackingDepth _PyEval_SetSwitchInterval _PyEval_SignalAsyncExc _PyEval_SignalReceived _PyEval_SliceIndex _PyEval_SliceIndexNotNone _PyFloat_DebugMallocStats _PyFloat_FormatAdvancedWriter _PyFloat_Pack2 _PyFloat_Pack4 _PyFloat_Pack8 _PyFloat_Unpack2 _PyFloat_Unpack4 _PyFloat_Unpack8 _PyFrame_DebugMallocStats _PyFunction_FastCallDict _PyFunction_Vectorcall _PyGC_CollectIfEnabled _PyGC_CollectNoFail _PyGC_Initialize _PyGILState_GetInterpreterStateUnsafe _PyGILState_Reinit _PyGen_FetchStopIterationValue _PyGen_Finalize _PyGen_Send _PyGen_SetStopIterationValue _PyHamtItems_Type DATA _PyHamtKeys_Type DATA _PyHamtValues_Type DATA _PyHamt_ArrayNode_Type DATA _PyHamt_BitmapNode_Type DATA _PyHamt_CollisionNode_Type DATA _PyHamt_Type DATA _PyImport_AcquireLock _PyImport_AddModuleObject _PyImport_FindBuiltin _PyImport_FindExtensionObject _PyImport_FindExtensionObjectEx _PyImport_FixupBuiltin _PyImport_FixupExtensionObject _PyImport_GetModuleId _PyImport_IsInitialized _PyImport_ReInitLock _PyImport_ReleaseLock _PyImport_SetModule _PyImport_SetModuleString _PyInterpreterID_LookUp _PyInterpreterID_New _PyInterpreterID_Type DATA _PyInterpreterState_DeleteExceptMain _PyInterpreterState_Enable _PyInterpreterState_Get _PyInterpreterState_GetIDObject _PyInterpreterState_GetMainModule _PyInterpreterState_IDDecref _PyInterpreterState_IDIncref _PyInterpreterState_IDInitref _PyInterpreterState_LookUpID _PyInterpreterState_RequireIDRef _PyInterpreterState_RequiresIDRef _PyList_DebugMallocStats _PyList_Extend _PyLong_AsByteArray _PyLong_AsInt _PyLong_AsTime_t _PyLong_Copy _PyLong_DigitValue DATA _PyLong_DivmodNear _PyLong_Format _PyLong_FormatAdvancedWriter _PyLong_FormatBytesWriter _PyLong_FormatWriter _PyLong_Frexp _PyLong_FromByteArray _PyLong_FromBytes _PyLong_FromNbIndexOrNbInt _PyLong_FromNbInt _PyLong_FromTime_t _PyLong_GCD _PyLong_Lshift _PyLong_New _PyLong_NumBits _PyLong_One DATA _PyLong_Rshift _PyLong_Sign _PyLong_Size_t_Converter _PyLong_UnsignedInt_Converter _PyLong_UnsignedLongLong_Converter _PyLong_UnsignedLong_Converter _PyLong_UnsignedShort_Converter _PyLong_Zero DATA _PyManagedBuffer_Type DATA _PyMem_GetAllocatorName _PyMem_GetCurrentAllocatorName _PyMem_RawStrdup _PyMem_RawWcsdup _PyMem_SetDefaultAllocator _PyMem_SetupAllocators _PyMem_Strdup _PyMethodDef_RawFastCallDict _PyMethodDef_RawFastCallKeywords _PyMethodWrapper_Type DATA _PyMethod_DebugMallocStats _PyModuleSpec_IsInitializing _PyModule_Clear _PyModule_ClearDict _PyModule_CreateInitialized _PyNamespace_New _PyNamespace_Type DATA _PyNode_SizeOf _PyNone_Type DATA _PyNotImplemented_Type DATA _PyOS_InterruptOccurred _PyOS_IsMainThread _PyOS_ReadlineTState DATA _PyOS_SigintEvent _PyOS_URandom _PyOS_URandomNonblock _PyObject_AssertFailed _PyObject_CallFunction_SizeT _PyObject_CallMethodId _PyObject_CallMethodIdObjArgs _PyObject_CallMethodId_SizeT _PyObject_CallMethod_SizeT _PyObject_Call_Prepend _PyObject_CheckConsistency _PyObject_CheckCrossInterpreterData _PyObject_DebugMallocStats _PyObject_DebugTypeStats _PyObject_Dump _PyObject_FastCallDict _PyObject_FastCall_Prepend _PyObject_GC_Calloc _PyObject_GC_Malloc _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_GenericGetAttrWithDict _PyObject_GenericSetAttrWithDict _PyObject_GetAttrId _PyObject_GetCrossInterpreterData _PyObject_GetDictPtr _PyObject_HasAttrId _PyObject_HasLen _PyObject_IsAbstract _PyObject_IsFreed _PyObject_LookupAttr _PyObject_LookupAttrId _PyObject_LookupSpecial _PyObject_MakeTpCall _PyObject_New _PyObject_NewVar _PyObject_NextNotImplemented _PyObject_RealIsInstance _PyObject_RealIsSubclass _PyObject_SetAttrId _PyParser_TokenNames DATA _PyPreConfig_InitCompatConfig _PyRuntime DATA _PyRuntimeState_Fini _PyRuntimeState_Init _PyRuntimeState_ReInitThreads _PyRuntime_Finalize _PyRuntime_Initialize _PySequence_BytesToCharpArray _PySequence_IterSearch _PySet_Dummy DATA _PySet_NextEntry _PySet_Update _PySignal_AfterFork _PySlice_FromIndices _PySlice_GetLongIndices _PyStack_AsDict _PyStack_UnpackDict _PyState_AddModule _PyState_ClearModules _PySys_GetObjectId _PySys_GetSizeOf _PySys_SetObjectId _PyThreadState_DeleteExcept _PyThreadState_Init _PyThreadState_Prealloc _PyThreadState_Swap _PyThreadState_UncheckedGet _PyThread_CurrentFrames _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_noraise _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetPerfCounter _PyTime_GetPerfCounterWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_Init _PyTime_MulDiv _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyTraceMalloc_GetTraceback _PyTraceMalloc_NewReference _PyTraceback_Add _PyTrash_deposit_object _PyTrash_destroy_chain _PyTrash_thread_deposit_object _PyTrash_thread_destroy_chain _PyTuple_DebugMallocStats _PyTuple_MaybeUntrack _PyTuple_Resize _PyType_CalculateMetaclass _PyType_CheckConsistency _PyType_GetDocFromInternalDoc _PyType_GetTextSignatureFromInternalDoc _PyType_Lookup _PyType_LookupId _PyType_Name _PyUnicodeTranslateError_Create _PyUnicodeWriter_Dealloc _PyUnicodeWriter_Finish _PyUnicodeWriter_Init _PyUnicodeWriter_PrepareInternal _PyUnicodeWriter_PrepareKindInternal _PyUnicodeWriter_WriteASCIIString _PyUnicodeWriter_WriteChar _PyUnicodeWriter_WriteLatin1String _PyUnicodeWriter_WriteStr _PyUnicodeWriter_WriteSubstring _PyUnicode_AsASCIIString _PyUnicode_AsKind _PyUnicode_AsLatin1String _PyUnicode_AsUTF8String _PyUnicode_AsUnicode _PyUnicode_CheckConsistency _PyUnicode_ClearStaticStrings _PyUnicode_Copy _PyUnicode_DecodeUnicodeEscape _PyUnicode_EQ _PyUnicode_EncodeCharmap _PyUnicode_EncodeUTF16 _PyUnicode_EncodeUTF32 _PyUnicode_EncodeUTF7 _PyUnicode_EqualToASCIIId _PyUnicode_EqualToASCIIString _PyUnicode_FastCopyCharacters _PyUnicode_FastFill _PyUnicode_FindMaxChar _PyUnicode_FormatAdvancedWriter _PyUnicode_FormatLong _PyUnicode_FromASCII _PyUnicode_FromId _PyUnicode_InsertThousandsGrouping _PyUnicode_IsAlpha _PyUnicode_IsCaseIgnorable _PyUnicode_IsCased _PyUnicode_IsDecimalDigit _PyUnicode_IsDigit _PyUnicode_IsLinebreak _PyUnicode_IsLowercase _PyUnicode_IsNumeric _PyUnicode_IsPrintable _PyUnicode_IsTitlecase _PyUnicode_IsUppercase _PyUnicode_IsWhitespace _PyUnicode_IsXidContinue _PyUnicode_IsXidStart _PyUnicode_JoinArray _PyUnicode_Ready _PyUnicode_ToDecimalDigit _PyUnicode_ToDigit _PyUnicode_ToFoldedFull _PyUnicode_ToLowerFull _PyUnicode_ToLowercase _PyUnicode_ToNumeric _PyUnicode_ToTitleFull _PyUnicode_ToTitlecase _PyUnicode_ToUpperFull _PyUnicode_ToUppercase _PyUnicode_TransformDecimalAndSpaceToASCII _PyUnicode_XStrip _PyWarnings_Init _PyWeakref_CallableProxyType DATA _PyWeakref_ClearRef _PyWeakref_GetWeakrefCount _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _PyWideStringList_AsList _PyWideStringList_Clear _PyWideStringList_Copy _PyWideStringList_Extend _PyWindowsConsoleIO_Type DATA _Py_BreakPoint _Py_BuildValue_SizeT _Py_CheckFunctionResult _Py_CheckRecursionLimit DATA _Py_CheckRecursiveCall _Py_ClearArgcArgv _Py_ClearStandardStreamEncoding _Py_CoerceLegacyLocale _Py_Dealloc _Py_DecodeLocaleEx _Py_DecodeUTF8Ex _Py_DecodeUTF8_surrogateescape _Py_DisplaySourceLine _Py_EllipsisObject DATA _Py_EncodeLocaleEx _Py_EncodeLocaleRaw _Py_EncodeUTF8Ex _Py_FalseStruct DATA _Py_FinishPendingCalls _Py_FreeCharPArray _Py_GetAllocatedBlocks _Py_GetConfigsAsDict _Py_GetEnv _Py_GetErrorHandler _Py_GetForceASCII _Py_GetLocaleconvNumeric _Py_HandleSystemExit _Py_HashBytes _Py_HashDouble _Py_HashPointer _Py_HashSecret DATA _Py_InitializeMain _Py_IsCoreInitialized _Py_IsFinalizing _Py_IsLocaleCoercionTarget _Py_LegacyLocaleDetected _Py_Mangle _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_PackageContext DATA _Py_PreInitializeFromConfig _Py_PreInitializeFromPyArgv _Py_PyAtExit _Py_ResetForceASCII _Py_RestoreSignals _Py_SetLocaleFromEnv _Py_SetProgramFullPath _Py_SourceAsString _Py_SwappedOp DATA _Py_SymtableStringObjectFlags _Py_TrueStruct DATA _Py_UnhandledKeyboardInterrupt DATA _Py_VaBuildStack _Py_VaBuildStack_SizeT _Py_VaBuildValue_SizeT _Py_add_one_to_index_C _Py_add_one_to_index_F _Py_ascii_whitespace DATA _Py_c_abs _Py_c_diff _Py_c_neg _Py_c_pow _Py_c_prod _Py_c_quot _Py_c_sum _Py_convert_optional_to_ssize_t _Py_ctype_table DATA _Py_ctype_tolower DATA _Py_ctype_toupper DATA _Py_device_encoding _Py_dg_dtoa _Py_dg_freedtoa _Py_dg_infinity _Py_dg_stdnan _Py_dg_strtod _Py_dup _Py_fopen _Py_fopen_obj _Py_fstat _Py_fstat_noraise _Py_get_env_flag _Py_get_inheritable _Py_get_xoption _Py_gitidentifier _Py_gitversion _Py_hashtable_clear _Py_hashtable_compare_direct _Py_hashtable_copy _Py_hashtable_destroy _Py_hashtable_foreach _Py_hashtable_get _Py_hashtable_get_entry _Py_hashtable_hash_ptr _Py_hashtable_new _Py_hashtable_new_full _Py_hashtable_pop _Py_hashtable_set _Py_hashtable_size _Py_open _Py_open_noraise _Py_parse_inf_or_nan _Py_path_config DATA _Py_read _Py_set_inheritable _Py_set_inheritable_async_safe _Py_stat _Py_str_to_int _Py_strhex _Py_strhex_bytes _Py_strhex_bytes_with_sep _Py_strhex_with_sep _Py_string_to_number_with_underscores _Py_tracemalloc_config DATA _Py_wfopen _Py_wgetcwd _Py_write _Py_write_noraise python3-dll-a/src/python311.def0000644000175000017500000010426314661133735017157 0ustar jamespagejamespage; ; Definition file of python311.dll ; Automatic generated by gendef ; written by Kai Tietz 2008 ; LIBRARY "python311.dll" EXPORTS PyAIter_Check PyArg_Parse PyArg_ParseTuple PyArg_ParseTupleAndKeywords PyArg_UnpackTuple PyArg_VaParse PyArg_VaParseTupleAndKeywords PyArg_ValidateKeywordArguments PyAsyncGen_New PyAsyncGen_Type DATA PyBaseObject_Type DATA PyBool_FromLong PyBool_Type DATA PyBuffer_FillContiguousStrides PyBuffer_FillInfo PyBuffer_FromContiguous PyBuffer_GetPointer PyBuffer_IsContiguous PyBuffer_Release PyBuffer_SizeFromFormat PyBuffer_ToContiguous PyByteArrayIter_Type DATA PyByteArray_AsString PyByteArray_Concat PyByteArray_FromObject PyByteArray_FromStringAndSize PyByteArray_Resize PyByteArray_Size PyByteArray_Type DATA PyBytesIter_Type DATA PyBytes_AsString PyBytes_AsStringAndSize PyBytes_Concat PyBytes_ConcatAndDel PyBytes_DecodeEscape PyBytes_FromFormat PyBytes_FromFormatV PyBytes_FromObject PyBytes_FromString PyBytes_FromStringAndSize PyBytes_Repr PyBytes_Size PyBytes_Type DATA PyCFunction_Call PyCFunction_GetFlags PyCFunction_GetFunction PyCFunction_GetSelf PyCFunction_New PyCFunction_NewEx PyCFunction_Type DATA PyCMethod_New PyCMethod_Type DATA PyCallIter_New PyCallIter_Type DATA PyCallable_Check PyCapsule_GetContext PyCapsule_GetDestructor PyCapsule_GetName PyCapsule_GetPointer PyCapsule_Import PyCapsule_IsValid PyCapsule_New PyCapsule_SetContext PyCapsule_SetDestructor PyCapsule_SetName PyCapsule_SetPointer PyCapsule_Type DATA PyCell_Get PyCell_New PyCell_Set PyCell_Type DATA PyClassMethodDescr_Type DATA PyClassMethod_New PyClassMethod_Type DATA PyCode_Addr2Line PyCode_Addr2Location PyCode_GetCellvars PyCode_GetCode PyCode_GetFreevars PyCode_GetVarnames PyCode_New PyCode_NewEmpty PyCode_NewWithPosOnlyArgs PyCode_Optimize PyCode_Type DATA PyCodec_BackslashReplaceErrors PyCodec_Decode PyCodec_Decoder PyCodec_Encode PyCodec_Encoder PyCodec_IgnoreErrors PyCodec_IncrementalDecoder PyCodec_IncrementalEncoder PyCodec_KnownEncoding PyCodec_LookupError PyCodec_NameReplaceErrors PyCodec_Register PyCodec_RegisterError PyCodec_ReplaceErrors PyCodec_StreamReader PyCodec_StreamWriter PyCodec_StrictErrors PyCodec_Unregister PyCodec_XMLCharRefReplaceErrors PyCompile_OpcodeStackEffect PyCompile_OpcodeStackEffectWithJump PyComplex_AsCComplex PyComplex_FromCComplex PyComplex_FromDoubles PyComplex_ImagAsDouble PyComplex_RealAsDouble PyComplex_Type DATA PyConfig_Clear PyConfig_InitIsolatedConfig PyConfig_InitPythonConfig PyConfig_Read PyConfig_SetArgv PyConfig_SetBytesArgv PyConfig_SetBytesString PyConfig_SetString PyConfig_SetWideStringList PyContextToken_Type DATA PyContextVar_Get PyContextVar_New PyContextVar_Reset PyContextVar_Set PyContextVar_Type DATA PyContext_Copy PyContext_CopyCurrent PyContext_Enter PyContext_Exit PyContext_New PyContext_Type DATA PyCoro_New PyCoro_Type DATA PyDescr_IsData PyDescr_NewClassMethod PyDescr_NewGetSet PyDescr_NewMember PyDescr_NewMethod PyDescr_NewWrapper PyDictItems_Type DATA PyDictIterItem_Type DATA PyDictIterKey_Type DATA PyDictIterValue_Type DATA PyDictKeys_Type DATA PyDictProxy_New PyDictProxy_Type DATA PyDictRevIterItem_Type DATA PyDictRevIterKey_Type DATA PyDictRevIterValue_Type DATA PyDictValues_Type DATA PyDict_Clear PyDict_Contains PyDict_Copy PyDict_DelItem PyDict_DelItemString PyDict_GetItem PyDict_GetItemString PyDict_GetItemWithError PyDict_Items PyDict_Keys PyDict_Merge PyDict_MergeFromSeq2 PyDict_New PyDict_Next PyDict_SetDefault PyDict_SetItem PyDict_SetItemString PyDict_Size PyDict_Type DATA PyDict_Update PyDict_Values PyEllipsis_Type DATA PyEnum_Type DATA PyErr_BadArgument PyErr_BadInternalCall PyErr_CheckSignals PyErr_Clear PyErr_Display PyErr_ExceptionMatches PyErr_Fetch PyErr_Format PyErr_FormatV PyErr_GetExcInfo PyErr_GetHandledException PyErr_GivenExceptionMatches PyErr_NewException PyErr_NewExceptionWithDoc PyErr_NoMemory PyErr_NormalizeException PyErr_Occurred PyErr_Print PyErr_PrintEx PyErr_ProgramText PyErr_ProgramTextObject PyErr_RangedSyntaxLocationObject PyErr_ResourceWarning PyErr_Restore PyErr_SetExcFromWindowsErr PyErr_SetExcFromWindowsErrWithFilename PyErr_SetExcFromWindowsErrWithFilenameObject PyErr_SetExcFromWindowsErrWithFilenameObjects PyErr_SetExcInfo PyErr_SetFromErrno PyErr_SetFromErrnoWithFilename PyErr_SetFromErrnoWithFilenameObject PyErr_SetFromErrnoWithFilenameObjects PyErr_SetFromWindowsErr PyErr_SetFromWindowsErrWithFilename PyErr_SetHandledException PyErr_SetImportError PyErr_SetImportErrorSubclass PyErr_SetInterrupt PyErr_SetInterruptEx PyErr_SetNone PyErr_SetObject PyErr_SetString PyErr_SyntaxLocation PyErr_SyntaxLocationEx PyErr_SyntaxLocationObject PyErr_WarnEx PyErr_WarnExplicit PyErr_WarnExplicitFormat PyErr_WarnExplicitObject PyErr_WarnFormat PyErr_WriteUnraisable PyEval_AcquireLock PyEval_AcquireThread PyEval_CallFunction PyEval_CallMethod PyEval_CallObjectWithKeywords PyEval_EvalCode PyEval_EvalCodeEx PyEval_EvalFrame PyEval_EvalFrameEx PyEval_GetBuiltins PyEval_GetFrame PyEval_GetFuncDesc PyEval_GetFuncName PyEval_GetGlobals PyEval_GetLocals PyEval_InitThreads PyEval_MergeCompilerFlags PyEval_ReleaseLock PyEval_ReleaseThread PyEval_RestoreThread PyEval_SaveThread PyEval_SetProfile PyEval_SetTrace PyEval_ThreadsInitialized PyExc_ArithmeticError DATA PyExc_AssertionError DATA PyExc_AttributeError DATA PyExc_BaseException DATA PyExc_BaseExceptionGroup DATA PyExc_BlockingIOError DATA PyExc_BrokenPipeError DATA PyExc_BufferError DATA PyExc_BytesWarning DATA PyExc_ChildProcessError DATA PyExc_ConnectionAbortedError DATA PyExc_ConnectionError DATA PyExc_ConnectionRefusedError DATA PyExc_ConnectionResetError DATA PyExc_DeprecationWarning DATA PyExc_EOFError DATA PyExc_EncodingWarning DATA PyExc_EnvironmentError DATA PyExc_Exception DATA PyExc_FileExistsError DATA PyExc_FileNotFoundError DATA PyExc_FloatingPointError DATA PyExc_FutureWarning DATA PyExc_GeneratorExit DATA PyExc_IOError DATA PyExc_ImportError DATA PyExc_ImportWarning DATA PyExc_IndentationError DATA PyExc_IndexError DATA PyExc_InterruptedError DATA PyExc_IsADirectoryError DATA PyExc_KeyError DATA PyExc_KeyboardInterrupt DATA PyExc_LookupError DATA PyExc_MemoryError DATA PyExc_ModuleNotFoundError DATA PyExc_NameError DATA PyExc_NotADirectoryError DATA PyExc_NotImplementedError DATA PyExc_OSError DATA PyExc_OverflowError DATA PyExc_PendingDeprecationWarning DATA PyExc_PermissionError DATA PyExc_ProcessLookupError DATA PyExc_RecursionError DATA PyExc_ReferenceError DATA PyExc_ResourceWarning DATA PyExc_RuntimeError DATA PyExc_RuntimeWarning DATA PyExc_StopAsyncIteration DATA PyExc_StopIteration DATA PyExc_SyntaxError DATA PyExc_SyntaxWarning DATA PyExc_SystemError DATA PyExc_SystemExit DATA PyExc_TabError DATA PyExc_TimeoutError DATA PyExc_TypeError DATA PyExc_UnboundLocalError DATA PyExc_UnicodeDecodeError DATA PyExc_UnicodeEncodeError DATA PyExc_UnicodeError DATA PyExc_UnicodeTranslateError DATA PyExc_UnicodeWarning DATA PyExc_UserWarning DATA PyExc_ValueError DATA PyExc_Warning DATA PyExc_WindowsError DATA PyExc_ZeroDivisionError DATA PyExceptionClass_Name PyException_GetCause PyException_GetContext PyException_GetTraceback PyException_SetCause PyException_SetContext PyException_SetTraceback PyFile_FromFd PyFile_GetLine PyFile_NewStdPrinter PyFile_OpenCode PyFile_OpenCodeObject PyFile_SetOpenCodeHook PyFile_WriteObject PyFile_WriteString PyFilter_Type DATA PyFloat_AsDouble PyFloat_FromDouble PyFloat_FromString PyFloat_GetInfo PyFloat_GetMax PyFloat_GetMin PyFloat_Pack2 PyFloat_Pack4 PyFloat_Pack8 PyFloat_Type DATA PyFloat_Unpack2 PyFloat_Unpack4 PyFloat_Unpack8 PyFrame_FastToLocals PyFrame_FastToLocalsWithError PyFrame_GetBack PyFrame_GetBuiltins PyFrame_GetCode PyFrame_GetGenerator PyFrame_GetGlobals PyFrame_GetLasti PyFrame_GetLineNumber PyFrame_GetLocals PyFrame_LocalsToFast PyFrame_New PyFrame_Type DATA PyFrozenSet_New PyFrozenSet_Type DATA PyFunction_GetAnnotations PyFunction_GetClosure PyFunction_GetCode PyFunction_GetDefaults PyFunction_GetGlobals PyFunction_GetKwDefaults PyFunction_GetModule PyFunction_New PyFunction_NewWithQualName PyFunction_SetAnnotations PyFunction_SetClosure PyFunction_SetDefaults PyFunction_SetKwDefaults PyFunction_Type DATA PyGC_Collect PyGC_Disable PyGC_Enable PyGC_IsEnabled PyGILState_Check PyGILState_Ensure PyGILState_GetThisThreadState PyGILState_Release PyGen_New PyGen_NewWithQualName PyGen_Type DATA PyGetSetDescr_Type DATA PyHash_GetFuncDef PyImport_AddModule PyImport_AddModuleObject PyImport_AppendInittab PyImport_ExecCodeModule PyImport_ExecCodeModuleEx PyImport_ExecCodeModuleObject PyImport_ExecCodeModuleWithPathnames PyImport_ExtendInittab PyImport_FrozenModules DATA PyImport_GetImporter PyImport_GetMagicNumber PyImport_GetMagicTag PyImport_GetModule PyImport_GetModuleDict PyImport_Import PyImport_ImportFrozenModule PyImport_ImportFrozenModuleObject PyImport_ImportModule PyImport_ImportModuleLevel PyImport_ImportModuleLevelObject PyImport_ImportModuleNoBlock PyImport_Inittab DATA PyImport_ReloadModule PyIndex_Check PyInstanceMethod_Function PyInstanceMethod_New PyInstanceMethod_Type DATA PyInterpreterState_Clear PyInterpreterState_Delete PyInterpreterState_Get PyInterpreterState_GetDict PyInterpreterState_GetID PyInterpreterState_Head PyInterpreterState_Main PyInterpreterState_New PyInterpreterState_Next PyInterpreterState_ThreadHead PyIter_Check PyIter_Next PyIter_Send PyListIter_Type DATA PyListRevIter_Type DATA PyList_Append PyList_AsTuple PyList_GetItem PyList_GetSlice PyList_Insert PyList_New PyList_Reverse PyList_SetItem PyList_SetSlice PyList_Size PyList_Sort PyList_Type DATA PyLongRangeIter_Type DATA PyLong_AsDouble PyLong_AsLong PyLong_AsLongAndOverflow PyLong_AsLongLong PyLong_AsLongLongAndOverflow PyLong_AsSize_t PyLong_AsSsize_t PyLong_AsUnsignedLong PyLong_AsUnsignedLongLong PyLong_AsUnsignedLongLongMask PyLong_AsUnsignedLongMask PyLong_AsVoidPtr PyLong_FromDouble PyLong_FromLong PyLong_FromLongLong PyLong_FromSize_t PyLong_FromSsize_t PyLong_FromString PyLong_FromUnicodeObject PyLong_FromUnsignedLong PyLong_FromUnsignedLongLong PyLong_FromVoidPtr PyLong_GetInfo PyLong_Type DATA PyMap_Type DATA PyMapping_Check PyMapping_GetItemString PyMapping_HasKey PyMapping_HasKeyString PyMapping_Items PyMapping_Keys PyMapping_Length PyMapping_SetItemString PyMapping_Size PyMapping_Values PyMarshal_ReadLastObjectFromFile PyMarshal_ReadLongFromFile PyMarshal_ReadObjectFromFile PyMarshal_ReadObjectFromString PyMarshal_ReadShortFromFile PyMarshal_WriteLongToFile PyMarshal_WriteObjectToFile PyMarshal_WriteObjectToString PyMem_Calloc PyMem_Free PyMem_GetAllocator PyMem_Malloc PyMem_RawCalloc PyMem_RawFree PyMem_RawMalloc PyMem_RawRealloc PyMem_Realloc PyMem_SetAllocator PyMem_SetupDebugHooks PyMemberDescr_Type DATA PyMember_GetOne PyMember_SetOne PyMemoryView_FromBuffer PyMemoryView_FromMemory PyMemoryView_FromObject PyMemoryView_GetContiguous PyMemoryView_Type DATA PyMethodDescr_Type DATA PyMethod_Function PyMethod_New PyMethod_Self PyMethod_Type DATA PyModuleDef_Init PyModuleDef_Type DATA PyModule_AddFunctions PyModule_AddIntConstant PyModule_AddObject PyModule_AddObjectRef PyModule_AddStringConstant PyModule_AddType PyModule_Create2 PyModule_ExecDef PyModule_FromDefAndSpec2 PyModule_GetDef PyModule_GetDict PyModule_GetFilename PyModule_GetFilenameObject PyModule_GetName PyModule_GetNameObject PyModule_GetState PyModule_New PyModule_NewObject PyModule_SetDocString PyModule_Type DATA PyNumber_Absolute PyNumber_Add PyNumber_And PyNumber_AsSsize_t PyNumber_Check PyNumber_Divmod PyNumber_Float PyNumber_FloorDivide PyNumber_InPlaceAdd PyNumber_InPlaceAnd PyNumber_InPlaceFloorDivide PyNumber_InPlaceLshift PyNumber_InPlaceMatrixMultiply PyNumber_InPlaceMultiply PyNumber_InPlaceOr PyNumber_InPlacePower PyNumber_InPlaceRemainder PyNumber_InPlaceRshift PyNumber_InPlaceSubtract PyNumber_InPlaceTrueDivide PyNumber_InPlaceXor PyNumber_Index PyNumber_Invert PyNumber_Long PyNumber_Lshift PyNumber_MatrixMultiply PyNumber_Multiply PyNumber_Negative PyNumber_Or PyNumber_Positive PyNumber_Power PyNumber_Remainder PyNumber_Rshift PyNumber_Subtract PyNumber_ToBase PyNumber_TrueDivide PyNumber_Xor PyODictItems_Type DATA PyODictIter_Type DATA PyODictKeys_Type DATA PyODictValues_Type DATA PyODict_DelItem PyODict_New PyODict_SetItem PyODict_Type DATA PyOS_AfterFork PyOS_FSPath PyOS_InputHook DATA PyOS_InterruptOccurred PyOS_Readline PyOS_ReadlineFunctionPointer DATA PyOS_double_to_string PyOS_getsig PyOS_mystricmp PyOS_mystrnicmp PyOS_setsig PyOS_snprintf PyOS_string_to_double PyOS_strtol PyOS_strtoul PyOS_vsnprintf PyObject_ASCII PyObject_AsCharBuffer PyObject_AsFileDescriptor PyObject_AsReadBuffer PyObject_AsWriteBuffer PyObject_Bytes PyObject_Call PyObject_CallFinalizer PyObject_CallFinalizerFromDealloc PyObject_CallFunction PyObject_CallFunctionObjArgs PyObject_CallMethod PyObject_CallMethodObjArgs PyObject_CallNoArgs PyObject_CallObject PyObject_CallOneArg PyObject_Calloc PyObject_CheckBuffer PyObject_CheckReadBuffer PyObject_ClearWeakRefs PyObject_CopyData PyObject_DelItem PyObject_DelItemString PyObject_Dir PyObject_Format PyObject_Free PyObject_GC_Del PyObject_GC_IsFinalized PyObject_GC_IsTracked PyObject_GC_Track PyObject_GC_UnTrack PyObject_GET_WEAKREFS_LISTPTR PyObject_GenericGetAttr PyObject_GenericGetDict PyObject_GenericSetAttr PyObject_GenericSetDict PyObject_GetAIter PyObject_GetArenaAllocator PyObject_GetAttr PyObject_GetAttrString PyObject_GetBuffer PyObject_GetItem PyObject_GetIter PyObject_HasAttr PyObject_HasAttrString PyObject_Hash PyObject_HashNotImplemented PyObject_IS_GC PyObject_Init PyObject_InitVar PyObject_IsInstance PyObject_IsSubclass PyObject_IsTrue PyObject_Length PyObject_LengthHint PyObject_Malloc PyObject_Not PyObject_Print PyObject_Realloc PyObject_Repr PyObject_RichCompare PyObject_RichCompareBool PyObject_SelfIter PyObject_SetArenaAllocator PyObject_SetAttr PyObject_SetAttrString PyObject_SetItem PyObject_Size PyObject_Str PyObject_Type PyObject_Vectorcall PyObject_VectorcallDict PyObject_VectorcallMethod PyPickleBuffer_FromObject PyPickleBuffer_GetBuffer PyPickleBuffer_Release PyPickleBuffer_Type DATA PyPreConfig_InitIsolatedConfig PyPreConfig_InitPythonConfig PyProperty_Type DATA PyRangeIter_Type DATA PyRange_Type DATA PyReversed_Type DATA PyRun_AnyFile PyRun_AnyFileEx PyRun_AnyFileExFlags PyRun_AnyFileFlags PyRun_File PyRun_FileEx PyRun_FileExFlags PyRun_FileFlags PyRun_InteractiveLoop PyRun_InteractiveLoopFlags PyRun_InteractiveOne PyRun_InteractiveOneFlags PyRun_InteractiveOneObject PyRun_SimpleFile PyRun_SimpleFileEx PyRun_SimpleFileExFlags PyRun_SimpleString PyRun_SimpleStringFlags PyRun_String PyRun_StringFlags PySeqIter_New PySeqIter_Type DATA PySequence_Check PySequence_Concat PySequence_Contains PySequence_Count PySequence_DelItem PySequence_DelSlice PySequence_Fast PySequence_GetItem PySequence_GetSlice PySequence_In PySequence_InPlaceConcat PySequence_InPlaceRepeat PySequence_Index PySequence_Length PySequence_List PySequence_Repeat PySequence_SetItem PySequence_SetSlice PySequence_Size PySequence_Tuple PySetIter_Type DATA PySet_Add PySet_Clear PySet_Contains PySet_Discard PySet_New PySet_Pop PySet_Size PySet_Type DATA PySlice_AdjustIndices PySlice_GetIndices PySlice_GetIndicesEx PySlice_New PySlice_Type DATA PySlice_Unpack PyState_AddModule PyState_FindModule PyState_RemoveModule PyStaticMethod_New PyStaticMethod_Type DATA PyStatus_Error PyStatus_Exception PyStatus_Exit PyStatus_IsError PyStatus_IsExit PyStatus_NoMemory PyStatus_Ok PyStdPrinter_Type DATA PyStructSequence_GetItem PyStructSequence_InitType PyStructSequence_InitType2 PyStructSequence_New PyStructSequence_NewType PyStructSequence_SetItem PyStructSequence_UnnamedField DATA PySuper_Type DATA PySymtable_Lookup PySys_AddAuditHook PySys_AddWarnOption PySys_AddWarnOptionUnicode PySys_AddXOption PySys_Audit PySys_FormatStderr PySys_FormatStdout PySys_GetObject PySys_GetXOptions PySys_HasWarnOptions PySys_ResetWarnOptions PySys_SetArgv PySys_SetArgvEx PySys_SetObject PySys_SetPath PySys_WriteStderr PySys_WriteStdout PyThreadState_Clear PyThreadState_Delete PyThreadState_DeleteCurrent PyThreadState_EnterTracing PyThreadState_Get PyThreadState_GetDict PyThreadState_GetFrame PyThreadState_GetID PyThreadState_GetInterpreter PyThreadState_LeaveTracing PyThreadState_New PyThreadState_Next PyThreadState_SetAsyncExc PyThreadState_Swap PyThread_GetInfo PyThread_ReInitTLS PyThread_acquire_lock PyThread_acquire_lock_timed PyThread_allocate_lock PyThread_create_key PyThread_delete_key PyThread_delete_key_value PyThread_exit_thread PyThread_free_lock PyThread_get_key_value PyThread_get_stacksize PyThread_get_thread_ident PyThread_get_thread_native_id PyThread_init_thread PyThread_release_lock PyThread_set_key_value PyThread_set_stacksize PyThread_start_new_thread PyThread_tss_alloc PyThread_tss_create PyThread_tss_delete PyThread_tss_free PyThread_tss_get PyThread_tss_is_created PyThread_tss_set PyToken_OneChar PyToken_ThreeChars PyToken_TwoChars PyTraceBack_Here PyTraceBack_Print PyTraceBack_Type DATA PyTraceMalloc_Track PyTraceMalloc_Untrack PyTupleIter_Type DATA PyTuple_GetItem PyTuple_GetSlice PyTuple_New PyTuple_Pack PyTuple_SetItem PyTuple_Size PyTuple_Type DATA PyType_ClearCache PyType_FromModuleAndSpec PyType_FromSpec PyType_FromSpecWithBases PyType_GenericAlloc PyType_GenericNew PyType_GetFlags PyType_GetModule PyType_GetModuleByDef PyType_GetModuleState PyType_GetName PyType_GetQualName PyType_GetSlot PyType_IsSubtype PyType_Modified PyType_Ready PyType_SUPPORTS_WEAKREFS PyType_Type DATA PyUnicodeDecodeError_Create PyUnicodeDecodeError_GetEncoding PyUnicodeDecodeError_GetEnd PyUnicodeDecodeError_GetObject PyUnicodeDecodeError_GetReason PyUnicodeDecodeError_GetStart PyUnicodeDecodeError_SetEnd PyUnicodeDecodeError_SetReason PyUnicodeDecodeError_SetStart PyUnicodeEncodeError_GetEncoding PyUnicodeEncodeError_GetEnd PyUnicodeEncodeError_GetObject PyUnicodeEncodeError_GetReason PyUnicodeEncodeError_GetStart PyUnicodeEncodeError_SetEnd PyUnicodeEncodeError_SetReason PyUnicodeEncodeError_SetStart PyUnicodeIter_Type DATA PyUnicodeTranslateError_GetEnd PyUnicodeTranslateError_GetObject PyUnicodeTranslateError_GetReason PyUnicodeTranslateError_GetStart PyUnicodeTranslateError_SetEnd PyUnicodeTranslateError_SetReason PyUnicodeTranslateError_SetStart PyUnicode_Append PyUnicode_AppendAndDel PyUnicode_AsASCIIString PyUnicode_AsCharmapString PyUnicode_AsDecodedObject PyUnicode_AsDecodedUnicode PyUnicode_AsEncodedObject PyUnicode_AsEncodedString PyUnicode_AsEncodedUnicode PyUnicode_AsLatin1String PyUnicode_AsMBCSString PyUnicode_AsRawUnicodeEscapeString PyUnicode_AsUCS4 PyUnicode_AsUCS4Copy PyUnicode_AsUTF16String PyUnicode_AsUTF32String PyUnicode_AsUTF8 PyUnicode_AsUTF8AndSize PyUnicode_AsUTF8String PyUnicode_AsUnicode PyUnicode_AsUnicodeAndSize PyUnicode_AsUnicodeEscapeString PyUnicode_AsWideChar PyUnicode_AsWideCharString PyUnicode_BuildEncodingMap PyUnicode_Compare PyUnicode_CompareWithASCIIString PyUnicode_Concat PyUnicode_Contains PyUnicode_CopyCharacters PyUnicode_Count PyUnicode_Decode PyUnicode_DecodeASCII PyUnicode_DecodeCharmap PyUnicode_DecodeCodePageStateful PyUnicode_DecodeFSDefault PyUnicode_DecodeFSDefaultAndSize PyUnicode_DecodeLatin1 PyUnicode_DecodeLocale PyUnicode_DecodeLocaleAndSize PyUnicode_DecodeMBCS PyUnicode_DecodeMBCSStateful PyUnicode_DecodeRawUnicodeEscape PyUnicode_DecodeUTF16 PyUnicode_DecodeUTF16Stateful PyUnicode_DecodeUTF32 PyUnicode_DecodeUTF32Stateful PyUnicode_DecodeUTF7 PyUnicode_DecodeUTF7Stateful PyUnicode_DecodeUTF8 PyUnicode_DecodeUTF8Stateful PyUnicode_DecodeUnicodeEscape PyUnicode_EncodeCodePage PyUnicode_EncodeFSDefault PyUnicode_EncodeLocale PyUnicode_FSConverter PyUnicode_FSDecoder PyUnicode_Fill PyUnicode_Find PyUnicode_FindChar PyUnicode_Format PyUnicode_FromEncodedObject PyUnicode_FromFormat PyUnicode_FromFormatV PyUnicode_FromKindAndData PyUnicode_FromObject PyUnicode_FromOrdinal PyUnicode_FromString PyUnicode_FromStringAndSize PyUnicode_FromUnicode PyUnicode_FromWideChar PyUnicode_GetDefaultEncoding PyUnicode_GetLength PyUnicode_GetSize PyUnicode_InternFromString PyUnicode_InternImmortal PyUnicode_InternInPlace PyUnicode_IsIdentifier PyUnicode_Join PyUnicode_New PyUnicode_Partition PyUnicode_RPartition PyUnicode_RSplit PyUnicode_ReadChar PyUnicode_Replace PyUnicode_Resize PyUnicode_RichCompare PyUnicode_Split PyUnicode_Splitlines PyUnicode_Substring PyUnicode_Tailmatch PyUnicode_Translate PyUnicode_Type DATA PyUnicode_WriteChar PyVectorcall_Call PyVectorcall_Function PyWeakref_GetObject PyWeakref_NewProxy PyWeakref_NewRef PyWideStringList_Append PyWideStringList_Insert PyWrapperDescr_Type DATA PyWrapper_New PyZip_Type DATA Py_AddPendingCall Py_AtExit Py_BuildValue Py_BytesMain Py_BytesWarningFlag DATA Py_CompileString Py_CompileStringExFlags Py_CompileStringFlags Py_CompileStringObject Py_DebugFlag DATA Py_DecRef Py_DecodeLocale Py_DontWriteBytecodeFlag DATA Py_EncodeLocale Py_EndInterpreter Py_EnterRecursiveCall Py_Exit Py_ExitStatusException Py_FatalError Py_FdIsInteractive Py_FileSystemDefaultEncodeErrors DATA Py_FileSystemDefaultEncoding DATA Py_Finalize Py_FinalizeEx Py_FrozenFlag DATA Py_GETENV Py_GenericAlias Py_GenericAliasType DATA Py_GetArgcArgv Py_GetBuildInfo Py_GetCompiler Py_GetCopyright Py_GetExecPrefix Py_GetPath Py_GetPlatform Py_GetPrefix Py_GetProgramFullPath Py_GetProgramName Py_GetPythonHome Py_GetRecursionLimit Py_GetVersion Py_HasFileSystemDefaultEncoding DATA Py_HashRandomizationFlag DATA Py_IgnoreEnvironmentFlag DATA Py_IncRef Py_Initialize Py_InitializeEx Py_InitializeFromConfig Py_InspectFlag DATA Py_InteractiveFlag DATA Py_Is Py_IsFalse Py_IsInitialized Py_IsNone Py_IsTrue Py_IsolatedFlag DATA Py_LeaveRecursiveCall Py_LegacyWindowsFSEncodingFlag DATA Py_LegacyWindowsStdioFlag DATA Py_Main Py_MakePendingCalls Py_NewInterpreter Py_NewRef Py_NoSiteFlag DATA Py_NoUserSiteDirectory DATA Py_OptimizeFlag DATA Py_PreInitialize Py_PreInitializeFromArgs Py_PreInitializeFromBytesArgs Py_QuietFlag DATA Py_ReprEnter Py_ReprLeave Py_RunMain Py_SetPath Py_SetProgramName Py_SetPythonHome Py_SetRecursionLimit Py_SetStandardStreamEncoding Py_UTF8Mode DATA Py_UnbufferedStdioFlag DATA Py_UniversalNewlineFgets Py_VaBuildValue Py_VerboseFlag DATA Py_Version DATA Py_XNewRef Py_hexdigits DATA _PyAST_Compile _PyAccu_Accumulate _PyAccu_Destroy _PyAccu_Finish _PyAccu_FinishAsList _PyAccu_Init _PyArena_AddPyObject _PyArena_Free _PyArena_Malloc _PyArena_New _PyArg_BadArgument _PyArg_CheckPositional _PyArg_NoKeywords _PyArg_NoKwnames _PyArg_NoPositional _PyArg_ParseStack _PyArg_ParseStackAndKeywords _PyArg_ParseStackAndKeywords_SizeT _PyArg_ParseStack_SizeT _PyArg_ParseTupleAndKeywordsFast _PyArg_ParseTupleAndKeywordsFast_SizeT _PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT _PyArg_Parse_SizeT _PyArg_UnpackKeywords _PyArg_UnpackKeywordsWithVararg _PyArg_UnpackStack _PyArg_VaParseTupleAndKeywordsFast _PyArg_VaParseTupleAndKeywordsFast_SizeT _PyArg_VaParseTupleAndKeywords_SizeT _PyArg_VaParse_SizeT _PyArgv_AsWstrList _PyAsyncGenASend_Type DATA _PyAsyncGenAThrow_Type DATA _PyAsyncGenWrappedValue_Type DATA _PyByteArray_empty_string DATA _PyBytesIOBuffer_Type DATA _PyBytesWriter_Alloc _PyBytesWriter_Dealloc _PyBytesWriter_Finish _PyBytesWriter_Init _PyBytesWriter_Prepare _PyBytesWriter_Resize _PyBytesWriter_WriteBytes _PyBytes_DecodeEscape _PyBytes_Find _PyBytes_FormatEx _PyBytes_FromHex _PyBytes_Join _PyBytes_Repeat _PyBytes_Resize _PyBytes_ReverseFind _PyCode_CheckLineNumber _PyCode_ConstantKey _PyCode_GetExtra _PyCode_New _PyCode_SetExtra _PyCode_Validate _PyCodecInfo_GetIncrementalDecoder _PyCodecInfo_GetIncrementalEncoder _PyCodec_DecodeText _PyCodec_EncodeText _PyCodec_Lookup _PyCodec_LookupTextEncoding _PyConfig_AsDict _PyConfig_FromDict _PyConfig_InitCompatConfig _PyContext_NewHamtForTests _PyCoroWrapper_Type DATA _PyCrossInterpreterData_Lookup _PyCrossInterpreterData_NewObject _PyCrossInterpreterData_RegisterClass _PyCrossInterpreterData_Release _PyDeadline_Get _PyDeadline_Init _PyDebugAllocatorStats _PyDictView_Intersect _PyDictView_New _PyDict_CheckConsistency _PyDict_ContainsId _PyDict_Contains_KnownHash _PyDict_DebugMallocStats _PyDict_DelItemId _PyDict_DelItemIf _PyDict_DelItem_KnownHash _PyDict_GetItemIdWithError _PyDict_GetItemStringWithError _PyDict_GetItemWithError _PyDict_GetItem_KnownHash _PyDict_HasOnlyStringKeys _PyDict_MaybeUntrack _PyDict_MergeEx _PyDict_NewPresized _PyDict_Next _PyDict_Pop _PyDict_SetItemId _PyDict_SetItem_KnownHash _PyDict_SizeOf _PyErr_BadInternalCall _PyErr_ChainExceptions _PyErr_ChainStackItem _PyErr_CheckSignals _PyErr_CheckSignalsTstate _PyErr_Clear _PyErr_Display _PyErr_ExceptionMatches _PyErr_Fetch _PyErr_Format _PyErr_FormatFromCause _PyErr_FormatFromCauseTstate _PyErr_GetExcInfo _PyErr_GetHandledException _PyErr_GetTopmostException _PyErr_NoMemory _PyErr_NormalizeException _PyErr_Print _PyErr_ProgramDecodedTextObject _PyErr_Restore _PyErr_SetHandledException _PyErr_SetKeyError _PyErr_SetNone _PyErr_SetObject _PyErr_SetString _PyErr_StackItemToExcInfoTuple _PyErr_TrySetFromCause _PyErr_WriteUnraisableMsg _PyEval_AddPendingCall _PyEval_EvalFrameDefault _PyEval_GetBuiltin _PyEval_GetBuiltinId _PyEval_GetSwitchInterval _PyEval_RequestCodeExtraIndex _PyEval_SetProfile _PyEval_SetSwitchInterval _PyEval_SetTrace _PyEval_SignalAsyncExc _PyEval_SignalReceived _PyEval_SliceIndex _PyEval_SliceIndexNotNone _PyFloat_DebugMallocStats _PyFloat_FormatAdvancedWriter _PyFrame_IsEntryFrame _PyFunction_Vectorcall _PyGILState_GetInterpreterStateUnsafe _PyGen_FetchStopIterationValue _PyGen_Finalize _PyGen_SetStopIterationValue _PyImport_AcquireLock _PyImport_FixupBuiltin _PyImport_FixupExtensionObject _PyImport_FrozenBootstrap DATA _PyImport_FrozenStdlib DATA _PyImport_FrozenTest DATA _PyImport_GetModuleAttr _PyImport_GetModuleAttrString _PyImport_GetModuleId _PyImport_IsInitialized _PyImport_ReleaseLock _PyImport_SetModule _PyImport_SetModuleString _PyInterpreterID_LookUp _PyInterpreterID_New _PyInterpreterID_Type DATA _PyInterpreterState_Enable _PyInterpreterState_GetConfig _PyInterpreterState_GetConfigCopy _PyInterpreterState_GetEvalFrameFunc _PyInterpreterState_GetIDObject _PyInterpreterState_GetMainModule _PyInterpreterState_IDDecref _PyInterpreterState_IDIncref _PyInterpreterState_IDInitref _PyInterpreterState_LookUpID _PyInterpreterState_RequireIDRef _PyInterpreterState_RequiresIDRef _PyInterpreterState_SetConfig _PyInterpreterState_SetEvalFrameFunc _PyList_DebugMallocStats _PyList_Extend _PyLong_AsByteArray _PyLong_AsInt _PyLong_AsTime_t _PyLong_Copy _PyLong_DigitValue DATA _PyLong_DivmodNear _PyLong_FileDescriptor_Converter _PyLong_Format _PyLong_FormatAdvancedWriter _PyLong_FormatBytesWriter _PyLong_FormatWriter _PyLong_Frexp _PyLong_FromByteArray _PyLong_FromBytes _PyLong_FromTime_t _PyLong_GCD _PyLong_Lshift _PyLong_New _PyLong_NumBits _PyLong_Rshift _PyLong_Sign _PyLong_Size_t_Converter _PyLong_UnsignedInt_Converter _PyLong_UnsignedLongLong_Converter _PyLong_UnsignedLong_Converter _PyLong_UnsignedShort_Converter _PyManagedBuffer_Type DATA _PyMem_GetAllocatorName _PyMem_GetCurrentAllocatorName _PyMem_RawStrdup _PyMem_RawWcsdup _PyMem_SetDefaultAllocator _PyMem_SetupAllocators _PyMem_Strdup _PyMethodWrapper_Type DATA _PyModuleSpec_IsInitializing _PyModule_Add _PyModule_Clear _PyModule_ClearDict _PyModule_CreateInitialized _PyNamespace_New _PyNamespace_Type DATA _PyNone_Type DATA _PyNotImplemented_Type DATA _PyNumber_Index _PyOS_InterruptOccurred _PyOS_IsMainThread _PyOS_ReadlineTState DATA _PyOS_SigintEvent _PyOS_URandom _PyOS_URandomNonblock _PyObject_AssertFailed _PyObject_Call _PyObject_CallFunction_SizeT _PyObject_CallMethod _PyObject_CallMethodId _PyObject_CallMethodIdObjArgs _PyObject_CallMethodId_SizeT _PyObject_CallMethod_SizeT _PyObject_Call_Prepend _PyObject_CheckConsistency _PyObject_CheckCrossInterpreterData _PyObject_DebugMallocStats _PyObject_DebugTypeStats _PyObject_Dump _PyObject_FastCall _PyObject_FastCallDictTstate _PyObject_FunctionStr _PyObject_GC_New _PyObject_GC_NewVar _PyObject_GC_Resize _PyObject_GenericGetAttrWithDict _PyObject_GenericSetAttrWithDict _PyObject_GetAttrId _PyObject_GetCrossInterpreterData _PyObject_GetDictPtr _PyObject_GetMethod _PyObject_GetState _PyObject_HasLen _PyObject_IsAbstract _PyObject_IsFreed _PyObject_LookupAttr _PyObject_LookupAttrId _PyObject_LookupSpecial _PyObject_LookupSpecialId _PyObject_MakeTpCall _PyObject_New _PyObject_NewVar _PyObject_NextNotImplemented _PyObject_RealIsInstance _PyObject_RealIsSubclass _PyObject_SetAttrId _PyParser_TokenNames DATA _PyPathConfig_ClearGlobal _PyPreConfig_InitCompatConfig _PyRun_AnyFileObject _PyRun_InteractiveLoopObject _PyRun_SimpleFileObject _PyRuntime DATA _PyRuntimeState_Fini _PyRuntimeState_Init _PyRuntime_Finalize _PyRuntime_Initialize _PySequence_BytesToCharpArray _PySequence_IterSearch _PySet_Dummy DATA _PySet_NextEntry _PySet_Update _PySlice_FromIndices _PySlice_GetLongIndices _PyStack_AsDict _PyState_AddModule _PyStructSequence_InitType _PyStructSequence_NewType _PySys_GetAttr _PySys_GetSizeOf _PyThreadState_DeleteCurrent _PyThreadState_DeleteExcept _PyThreadState_GetDict _PyThreadState_Init _PyThreadState_Prealloc _PyThreadState_SetCurrent _PyThreadState_Swap _PyThreadState_UncheckedGet _PyThread_CurrentExceptions _PyThread_CurrentFrames _PyTime_Add _PyTime_As100Nanoseconds _PyTime_AsMicroseconds _PyTime_AsMilliseconds _PyTime_AsNanoseconds _PyTime_AsNanosecondsObject _PyTime_AsSecondsDouble _PyTime_AsTimeval _PyTime_AsTimevalTime_t _PyTime_AsTimeval_clamp _PyTime_FromMillisecondsObject _PyTime_FromNanoseconds _PyTime_FromNanosecondsObject _PyTime_FromSeconds _PyTime_FromSecondsObject _PyTime_GetMonotonicClock _PyTime_GetMonotonicClockWithInfo _PyTime_GetPerfCounter _PyTime_GetPerfCounterWithInfo _PyTime_GetSystemClock _PyTime_GetSystemClockWithInfo _PyTime_MulDiv _PyTime_ObjectToTime_t _PyTime_ObjectToTimespec _PyTime_ObjectToTimeval _PyTime_gmtime _PyTime_localtime _PyTraceBack_FromFrame _PyTraceBack_Print_Indented _PyTraceMalloc_GetTraceback _PyTraceback_Add _PyTrash_begin _PyTrash_cond _PyTrash_end _PyTuple_DebugMallocStats _PyTuple_MaybeUntrack _PyTuple_Resize _PyType_CalculateMetaclass _PyType_CheckConsistency _PyType_GetDocFromInternalDoc _PyType_GetTextSignatureFromInternalDoc _PyType_Lookup _PyType_LookupId _PyType_Name _PyUnicodeTranslateError_Create _PyUnicodeWriter_Dealloc _PyUnicodeWriter_Finish _PyUnicodeWriter_Init _PyUnicodeWriter_PrepareInternal _PyUnicodeWriter_PrepareKindInternal _PyUnicodeWriter_WriteASCIIString _PyUnicodeWriter_WriteChar _PyUnicodeWriter_WriteLatin1String _PyUnicodeWriter_WriteStr _PyUnicodeWriter_WriteSubstring _PyUnicode_AsASCIIString _PyUnicode_AsLatin1String _PyUnicode_AsUTF8String _PyUnicode_AsUnicode _PyUnicode_CheckConsistency _PyUnicode_Copy _PyUnicode_DecodeRawUnicodeEscapeStateful _PyUnicode_DecodeUnicodeEscapeInternal _PyUnicode_DecodeUnicodeEscapeStateful _PyUnicode_EQ _PyUnicode_EncodeCharmap _PyUnicode_EncodeUTF16 _PyUnicode_EncodeUTF32 _PyUnicode_EncodeUTF7 _PyUnicode_Equal _PyUnicode_EqualToASCIIId _PyUnicode_EqualToASCIIString _PyUnicode_FastCopyCharacters _PyUnicode_FastFill _PyUnicode_FindMaxChar _PyUnicode_FormatAdvancedWriter _PyUnicode_FormatLong _PyUnicode_FromASCII _PyUnicode_FromId _PyUnicode_InsertThousandsGrouping _PyUnicode_IsAlpha _PyUnicode_IsCaseIgnorable _PyUnicode_IsCased _PyUnicode_IsDecimalDigit _PyUnicode_IsDigit _PyUnicode_IsLinebreak _PyUnicode_IsLowercase _PyUnicode_IsNumeric _PyUnicode_IsPrintable _PyUnicode_IsTitlecase _PyUnicode_IsUppercase _PyUnicode_IsWhitespace _PyUnicode_IsXidContinue _PyUnicode_IsXidStart _PyUnicode_JoinArray _PyUnicode_Ready _PyUnicode_ScanIdentifier _PyUnicode_ToDecimalDigit _PyUnicode_ToDigit _PyUnicode_ToFoldedFull _PyUnicode_ToLowerFull _PyUnicode_ToLowercase _PyUnicode_ToNumeric _PyUnicode_ToTitleFull _PyUnicode_ToTitlecase _PyUnicode_ToUpperFull _PyUnicode_ToUppercase _PyUnicode_TransformDecimalAndSpaceToASCII _PyUnicode_WideCharString_Converter _PyUnicode_WideCharString_Opt_Converter _PyUnicode_XStrip _PyWarnings_Init _PyWeakref_CallableProxyType DATA _PyWeakref_ClearRef _PyWeakref_GetWeakrefCount _PyWeakref_ProxyType DATA _PyWeakref_RefType DATA _PyWideStringList_AsList _PyWideStringList_Clear _PyWideStringList_Copy _PyWideStringList_Extend _PyWindowsConsoleIO_Type DATA _Py_BreakPoint _Py_BuildValue_SizeT _Py_CheckFunctionResult _Py_CheckRecursiveCall _Py_ClearArgcArgv _Py_ClearStandardStreamEncoding _Py_CoerceLegacyLocale _Py_Dealloc _Py_DecRef _Py_DecodeLocaleEx _Py_DecodeUTF8Ex _Py_DecodeUTF8_surrogateescape _Py_DisplaySourceLine _Py_DumpASCII _Py_DumpDecimal _Py_DumpExtensionModules _Py_DumpHexadecimal _Py_DumpTraceback _Py_DumpTracebackThreads _Py_EllipsisObject DATA _Py_EncodeLocaleEx _Py_EncodeLocaleRaw _Py_EncodeUTF8Ex _Py_FalseStruct DATA _Py_FatalErrorFormat _Py_FatalErrorFunc _Py_FatalError_TstateNULL _Py_FatalRefcountErrorFunc _Py_FdIsInteractive _Py_FreeCharPArray _Py_GetAllocatedBlocks _Py_GetConfig _Py_GetConfigsAsDict _Py_GetEnv _Py_GetErrorHandler _Py_GetForceASCII _Py_GetLocaleEncoding _Py_GetLocaleEncodingObject _Py_GetLocaleconvNumeric _Py_Get_Getpath_CodeObject _Py_HandleSystemExit _Py_HasFileSystemDefaultEncodeErrors DATA _Py_HashBytes _Py_HashDouble _Py_HashPointer _Py_HashPointerRaw _Py_HashSecret DATA _Py_IncRef _Py_InitializeMain _Py_IsCoreInitialized _Py_IsFinalizing _Py_IsLocaleCoercionTarget _Py_LegacyLocaleDetected _Py_NewInterpreter _Py_NewReference _Py_NoneStruct DATA _Py_NotImplementedStruct DATA _Py_PackageContext DATA _Py_PreInitializeFromConfig _Py_PreInitializeFromPyArgv _Py_ResetForceASCII _Py_RestoreSignals _Py_SetLocaleFromEnv _Py_SetProgramFullPath _Py_SourceAsString _Py_SwappedOp DATA _Py_TrueStruct DATA _Py_UTF8_Edit_Cost _Py_UnhandledKeyboardInterrupt DATA _Py_UniversalNewlineFgetsWithSize _Py_VaBuildStack _Py_VaBuildStack_SizeT _Py_VaBuildValue_SizeT _Py_WriteIndent _Py_WriteIndentedMargin _Py_add_one_to_index_C _Py_add_one_to_index_F _Py_ascii_whitespace DATA _Py_c_abs _Py_c_diff _Py_c_neg _Py_c_pow _Py_c_prod _Py_c_quot _Py_c_sum _Py_closerange _Py_convert_optional_to_ssize_t _Py_ctype_table DATA _Py_ctype_tolower DATA _Py_ctype_toupper DATA _Py_device_encoding _Py_dg_dtoa _Py_dg_freedtoa _Py_dg_infinity _Py_dg_stdnan _Py_dg_strtod _Py_dup _Py_fopen_obj _Py_fstat _Py_fstat_noraise _Py_get_env_flag _Py_get_inheritable _Py_get_osfhandle _Py_get_osfhandle_noraise _Py_get_xoption _Py_gitidentifier _Py_gitversion _Py_hashtable_clear _Py_hashtable_compare_direct _Py_hashtable_destroy _Py_hashtable_foreach _Py_hashtable_get _Py_hashtable_hash_ptr _Py_hashtable_new _Py_hashtable_new_full _Py_hashtable_set _Py_hashtable_size _Py_hashtable_steal _Py_normpath _Py_open _Py_open_noraise _Py_open_osfhandle _Py_open_osfhandle_noraise _Py_parse_inf_or_nan _Py_read _Py_set_inheritable _Py_set_inheritable_async_safe _Py_stat _Py_str_to_int _Py_strhex _Py_strhex_bytes _Py_strhex_bytes_with_sep _Py_strhex_with_sep _Py_string_to_number_with_underscores _Py_tracemalloc_config DATA _Py_wfopen _Py_wgetcwd _Py_write _Py_write_noraise python3-dll-a/CHANGELOG.md0000644000175000017500000000535014661133735015750 0ustar jamespagejamespage# Changelog All notable changes to this project will be documented in this file. ## [0.2.10] - 2024-06-24 ### Features - Add Python 3.13 support in [#72](https://github.com/PyO3/python3-dll-a/pull/72) ## [0.2.9] - 2023-07-04 ### Fixes - Fix PyPy 3.10 support in[#46](https://github.com/PyO3/python3-dll-a/pull/46) ## [0.2.8] - 2023-07-03 ### Features - Add PyPy 3.10 support in [#44](https://github.com/PyO3/python3-dll-a/pull/44) ## [0.2.7] - 2023-05-25 ### Features - Add Python 3.12 support in [#34](https://github.com/PyO3/python3-dll-a/pull/34) ## [0.2.6] - 2022-08-21 ### Features - Add MinGW-w64 `dlltool` program name configuration env var [#31](https://github.com/PyO3/python3-dll-a/pull/31) ## [0.2.5] - 2022-07-14 ### Fixes - Fix PyPy import library name in [#27](https://github.com/PyO3/python3-dll-a/pull/27) ## [0.2.4] - 2022-07-14 ### Features - Add PyPy support in [#25](https://github.com/PyO3/python3-dll-a/pull/25) ## [0.2.3] - 2022-05-17 ### Features - Add `zig dlltool` support in [#18](https://github.com/pyo3/python3-dll-a/pull/18) ### Fixes - Improve error message when `dlltool` is not found in [#17](https://github.com/pyo3/python3-dll-a/pull/17) ## [0.2.2] - 2022-05-10 ### Features - Include `python3.def` itself in the Rust source in [#10](https://github.com/pyo3/python3-dll-a/pull/10) - Add support for generating non-abi3 `pythonXY.dll` in [#15](https://github.com/pyo3/python3-dll-a/pull/15) ### CI - Automate `stable_abi.txt` updates in [#6](https://github.com/pyo3/python3-dll-a/pull/6) ## [0.2.1] - 2022-04-17 ### Features - Add support for `lib.exe` from MSVC when running on Windows in [#2](https://github.com/pyo3/python3-dll-a/pull/2) ### Documentation - Mention the new PyO3 integration feature - Add maintenance section to README ### Miscellaneous Tasks - Update stable_abi.txt to the latest main ### CI - Add `rust.yml` workflow to build and run unit tests - Add `publish.yml` workflow to publish the crate to `crates.io` ## [0.2.0] - 2022-03-21 ### Features - [**breaking**] Use `Path` type for the output directory arg ## [0.1.2] - 2022-03-15 ### Documentation - Document MSVC ABI environment support ### Features - Add support for the LLVM `dlltool` flavor ### Testing - Build import libraries for all targets ## [0.1.1] - 2022-03-14 ### Documentation - Add multi-arch `build.rs` examples ### Features - Add support for the 32-bit target architecture ## [0.1.0] - 2022-02-21 ### Documentation - Add `build.rs` usage examples ### Features - Generate module definition and invoke dlltool - Implement Module-Definition file writing - Implement 'stable_abi.txt' syntax parser ### Miscellaneous Tasks - Add `git-cliff` config file - Add a change log file python3-dll-a/LICENSE0000644000175000017500000000214014661133735015136 0ustar jamespagejamespageMIT License Copyright (c) 2022 Sergey Kvachonok, Adam Reichold, messense Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. python3-dll-a/.cargo-checksum.json0000664000175000017500000000277714661133735020017 0ustar jamespagejamespage{"files":{"CHANGELOG.md":"bdc179734bd31b89503d5d6f51cf3900d4585b711e7de2265f78ec1ced4fe271","Cargo.toml":"d1d29ffb2c25fae9b574f559df9d9bf38ecd508d2daf79ea151e167205fd173e","LICENSE":"c760d1f2e4614d58f2b91cd41b9826457989c09041be0219158b8f7f6d3f8763","README.md":"16e2167c340f72cb3d9509526a7f404ac8f01437ae3247e81a50816b284f1fbc","parse-stable-abi.py":"55f2fcccc6c032fc79489e18ea25f9bcb959024b178c0c2617bd21af3ac1753e","src/lib.rs":"568e2fa7aa6d29abd698486432886ad0afb5087e7f1e0c906ca12efbc6c6cdac","src/libpypy3-c.def":"ab64f647ea9fca04a527323a0659fea7aa98d0211dd08afeb9f9930c7fb3bc10","src/libpypy3.10-c.def":"4728101ec8161721ab5902c09927f85ae6953be34f138052e6a5c2746c29466d","src/libpypy3.9-c.def":"78a089cd710af3e36c7dee1de093d3fce8f9ab164722db338d7f5ccc84643a29","src/python3.def":"aaf4c18181e1171155aad6a21f9bd4a5e992d572defb2ee271ee652cbe605acd","src/python310.def":"97768c0f0810ebd5525989d9cd50e2aed52018c5787c2e1e79c5d66ee67a0913","src/python311.def":"4424125c743d161ca130917a5224b585e52d470ee8f94ad6b63055b922bc69a5","src/python312.def":"3691a8897a688c5d960d4629d09a3dab6517c380aaf6fd6d3fa6f953850034d8","src/python313.def":"07d7d9c1c99cd6b6b92e2b59bff70d3247f802ebd4b34b1a4cbeb921ee20e7a4","src/python37.def":"d28d6e0668c46fa2e6e7b63bd3d4d0fb7b7d19b54df8dadae6d758be8bceb1a6","src/python38.def":"314f1909e903d4bab97c4c582bece194dc936598576c3b9f4d2e9534c9889233","src/python39.def":"db078992c1e0d431b687161bdfdb21865d514dfe1b1d79eef5fbb9de652e376f"},"package":"bd0b78171a90d808b319acfad166c4790d9e9759bbc14ac8273fe133673dd41b"}python3-dll-a/parse-stable-abi.py0000755000175000017500000000121414661133735017622 0ustar jamespagejamespage#!/usr/bin/env python3 # Parses Python Stable ABI symbol definitions from the manifest in the CPython repository located at https://github.com/python/cpython/blob/main/Misc/stable_abi.toml # and produces a definition file following the format described at https://docs.microsoft.com/en-us/cpp/build/reference/module-definition-dot-def-files. import sys import tomli stable_abi = tomli.load(sys.stdin.buffer) print("LIBRARY python3.dll") print("EXPORTS") count = 0 for function in stable_abi["function"].keys(): print(function) count += 1 for data in stable_abi["data"].keys(): print(f"{data} DATA") count += 1 assert count >= 859 quote/0000775000175000017500000000000014661133735012700 5ustar jamespagejamespagequote/README.md0000644000175000017500000002212614661133735014160 0ustar jamespagejamespageRust Quasi-Quoting ================== [github](https://github.com/dtolnay/quote) [crates.io](https://crates.io/crates/quote) [docs.rs](https://docs.rs/quote) [build status](https://github.com/dtolnay/quote/actions?query=branch%3Amaster) This crate provides the [`quote!`] macro for turning Rust syntax tree data structures into tokens of source code. [`quote!`]: https://docs.rs/quote/1.0/quote/macro.quote.html Procedural macros in Rust receive a stream of tokens as input, execute arbitrary Rust code to determine how to manipulate those tokens, and produce a stream of tokens to hand back to the compiler to compile into the caller's crate. Quasi-quoting is a solution to one piece of that — producing tokens to return to the compiler. The idea of quasi-quoting is that we write *code* that we treat as *data*. Within the `quote!` macro, we can write what looks like code to our text editor or IDE. We get all the benefits of the editor's brace matching, syntax highlighting, indentation, and maybe autocompletion. But rather than compiling that as code into the current crate, we can treat it as data, pass it around, mutate it, and eventually hand it back to the compiler as tokens to compile into the macro caller's crate. This crate is motivated by the procedural macro use case, but is a general-purpose Rust quasi-quoting library and is not specific to procedural macros. ```toml [dependencies] quote = "1.0" ``` *Version requirement: Quote supports rustc 1.56 and up.*
[*Release notes*](https://github.com/dtolnay/quote/releases)
## Syntax The quote crate provides a [`quote!`] macro within which you can write Rust code that gets packaged into a [`TokenStream`] and can be treated as data. You should think of `TokenStream` as representing a fragment of Rust source code. [`TokenStream`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.TokenStream.html Within the `quote!` macro, interpolation is done with `#var`. Any type implementing the [`quote::ToTokens`] trait can be interpolated. This includes most Rust primitive types as well as most of the syntax tree types from [`syn`]. [`quote::ToTokens`]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html [`syn`]: https://github.com/dtolnay/syn ```rust let tokens = quote! { struct SerializeWith #generics #where_clause { value: &'a #field_ty, phantom: core::marker::PhantomData<#item_ty>, } impl #generics serde::Serialize for SerializeWith #generics #where_clause { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { #path(self.value, serializer) } } SerializeWith { value: #value, phantom: core::marker::PhantomData::<#item_ty>, } }; ```
## Repetition Repetition is done using `#(...)*` or `#(...),*` similar to `macro_rules!`. This iterates through the elements of any variable interpolated within the repetition and inserts a copy of the repetition body for each one. The variables in an interpolation may be anything that implements `IntoIterator`, including `Vec` or a pre-existing iterator. - `#(#var)*` — no separators - `#(#var),*` — the character before the asterisk is used as a separator - `#( struct #var; )*` — the repetition can contain other things - `#( #k => println!("{}", #v), )*` — even multiple interpolations Note that there is a difference between `#(#var ,)*` and `#(#var),*`—the latter does not produce a trailing comma. This matches the behavior of delimiters in `macro_rules!`.
## Returning tokens to the compiler The `quote!` macro evaluates to an expression of type `proc_macro2::TokenStream`. Meanwhile Rust procedural macros are expected to return the type `proc_macro::TokenStream`. The difference between the two types is that `proc_macro` types are entirely specific to procedural macros and cannot ever exist in code outside of a procedural macro, while `proc_macro2` types may exist anywhere including tests and non-macro code like main.rs and build.rs. This is why even the procedural macro ecosystem is largely built around `proc_macro2`, because that ensures the libraries are unit testable and accessible in non-macro contexts. There is a [`From`]-conversion in both directions so returning the output of `quote!` from a procedural macro usually looks like `tokens.into()` or `proc_macro::TokenStream::from(tokens)`. [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
## Examples ### Combining quoted fragments Usually you don't end up constructing an entire final `TokenStream` in one piece. Different parts may come from different helper functions. The tokens produced by `quote!` themselves implement `ToTokens` and so can be interpolated into later `quote!` invocations to build up a final result. ```rust let type_definition = quote! {...}; let methods = quote! {...}; let tokens = quote! { #type_definition #methods }; ``` ### Constructing identifiers Suppose we have an identifier `ident` which came from somewhere in a macro input and we need to modify it in some way for the macro output. Let's consider prepending the identifier with an underscore. Simply interpolating the identifier next to an underscore will not have the behavior of concatenating them. The underscore and the identifier will continue to be two separate tokens as if you had written `_ x`. ```rust // incorrect quote! { let mut _#ident = 0; } ``` The solution is to build a new identifier token with the correct value. As this is such a common case, the `format_ident!` macro provides a convenient utility for doing so correctly. ```rust let varname = format_ident!("_{}", ident); quote! { let mut #varname = 0; } ``` Alternatively, the APIs provided by Syn and proc-macro2 can be used to directly build the identifier. This is roughly equivalent to the above, but will not handle `ident` being a raw identifier. ```rust let concatenated = format!("_{}", ident); let varname = syn::Ident::new(&concatenated, ident.span()); quote! { let mut #varname = 0; } ``` ### Making method calls Let's say our macro requires some type specified in the macro input to have a constructor called `new`. We have the type in a variable called `field_type` of type `syn::Type` and want to invoke the constructor. ```rust // incorrect quote! { let value = #field_type::new(); } ``` This works only sometimes. If `field_type` is `String`, the expanded code contains `String::new()` which is fine. But if `field_type` is something like `Vec` then the expanded code is `Vec::new()` which is invalid syntax. Ordinarily in handwritten Rust we would write `Vec::::new()` but for macros often the following is more convenient. ```rust quote! { let value = <#field_type>::new(); } ``` This expands to `>::new()` which behaves correctly. A similar pattern is appropriate for trait methods. ```rust quote! { let value = <#field_type as core::default::Default>::default(); } ```
## Hygiene Any interpolated tokens preserve the `Span` information provided by their `ToTokens` implementation. Tokens that originate within a `quote!` invocation are spanned with [`Span::call_site()`]. [`Span::call_site()`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html#method.call_site A different span can be provided explicitly through the [`quote_spanned!`] macro. [`quote_spanned!`]: https://docs.rs/quote/1.0/quote/macro.quote_spanned.html
## Non-macro code generators When using `quote` in a build.rs or main.rs and writing the output out to a file, consider having the code generator pass the tokens through [prettyplease] before writing. This way if an error occurs in the generated code it is convenient for a human to read and debug. Be aware that no kind of hygiene or span information is retained when tokens are written to a file; the conversion from tokens to source code is lossy. Example usage in build.rs: ```rust let output = quote! { ... }; let syntax_tree = syn::parse2(output).unwrap(); let formatted = prettyplease::unparse(&syntax_tree); let out_dir = env::var_os("OUT_DIR").unwrap(); let dest_path = Path::new(&out_dir).join("out.rs"); fs::write(dest_path, formatted).unwrap(); ``` [prettyplease]: https://github.com/dtolnay/prettyplease
#### License Licensed under either of
Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. quote/LICENSE-APACHE0000644000175000017500000002277314661133735014635 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS quote/Cargo.toml0000644000175000017500000000245214661133735014631 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.56" name = "quote" version = "1.0.36" authors = ["David Tolnay "] autobenches = false description = "Quasi-quoting macro quote!(...)" documentation = "https://docs.rs/quote/" readme = "README.md" keywords = [ "macros", "syn", ] categories = ["development-tools::procedural-macro-helpers"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/quote" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [lib] doc-scrape-examples = false [dependencies.proc-macro2] version = "1.0.74" default-features = false [dev-dependencies.rustversion] version = "1.0" [dev-dependencies.trybuild] version = "1.0.66" features = ["diff"] [features] default = ["proc-macro"] proc-macro = ["proc-macro2/proc-macro"] quote/tests/0000775000175000017500000000000014661133735014042 5ustar jamespagejamespagequote/tests/test.rs0000644000175000017500000003126414661133735015373 0ustar jamespagejamespage#![allow( clippy::disallowed_names, clippy::let_underscore_untyped, clippy::shadow_unrelated, clippy::unseparated_literal_suffix, clippy::used_underscore_binding )] extern crate proc_macro; use std::borrow::Cow; use std::collections::BTreeSet; use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, TokenStreamExt}; struct X; impl quote::ToTokens for X { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(Ident::new("X", Span::call_site())); } } #[test] fn test_quote_impl() { let tokens = quote! { impl<'a, T: ToTokens> ToTokens for &'a T { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens) } } }; let expected = concat!( "impl < 'a , T : ToTokens > ToTokens for & 'a T { ", "fn to_tokens (& self , tokens : & mut TokenStream) { ", "(* * self) . to_tokens (tokens) ", "} ", "}" ); assert_eq!(expected, tokens.to_string()); } #[test] fn test_quote_spanned_impl() { let span = Span::call_site(); let tokens = quote_spanned! {span=> impl<'a, T: ToTokens> ToTokens for &'a T { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens) } } }; let expected = concat!( "impl < 'a , T : ToTokens > ToTokens for & 'a T { ", "fn to_tokens (& self , tokens : & mut TokenStream) { ", "(* * self) . to_tokens (tokens) ", "} ", "}" ); assert_eq!(expected, tokens.to_string()); } #[test] fn test_substitution() { let x = X; let tokens = quote!(#x <#x> (#x) [#x] {#x}); let expected = "X < X > (X) [X] { X }"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_iter() { let primes = &[X, X, X, X]; assert_eq!("X X X X", quote!(#(#primes)*).to_string()); assert_eq!("X , X , X , X ,", quote!(#(#primes,)*).to_string()); assert_eq!("X , X , X , X", quote!(#(#primes),*).to_string()); } #[test] fn test_array() { let array: [u8; 40] = [0; 40]; let _ = quote!(#(#array #array)*); let ref_array: &[u8; 40] = &[0; 40]; let _ = quote!(#(#ref_array #ref_array)*); let ref_slice: &[u8] = &[0; 40]; let _ = quote!(#(#ref_slice #ref_slice)*); let array: [X; 2] = [X, X]; // !Copy let _ = quote!(#(#array #array)*); let ref_array: &[X; 2] = &[X, X]; let _ = quote!(#(#ref_array #ref_array)*); let ref_slice: &[X] = &[X, X]; let _ = quote!(#(#ref_slice #ref_slice)*); } #[test] fn test_advanced() { let generics = quote!( <'a, T> ); let where_clause = quote!( where T: Serialize ); let field_ty = quote!(String); let item_ty = quote!(Cow<'a, str>); let path = quote!(SomeTrait::serialize_with); let value = quote!(self.x); let tokens = quote! { struct SerializeWith #generics #where_clause { value: &'a #field_ty, phantom: ::std::marker::PhantomData<#item_ty>, } impl #generics ::serde::Serialize for SerializeWith #generics #where_clause { fn serialize(&self, s: &mut S) -> Result<(), S::Error> where S: ::serde::Serializer { #path(self.value, s) } } SerializeWith { value: #value, phantom: ::std::marker::PhantomData::<#item_ty>, } }; let expected = concat!( "struct SerializeWith < 'a , T > where T : Serialize { ", "value : & 'a String , ", "phantom : :: std :: marker :: PhantomData < Cow < 'a , str > > , ", "} ", "impl < 'a , T > :: serde :: Serialize for SerializeWith < 'a , T > where T : Serialize { ", "fn serialize < S > (& self , s : & mut S) -> Result < () , S :: Error > ", "where S : :: serde :: Serializer ", "{ ", "SomeTrait :: serialize_with (self . value , s) ", "} ", "} ", "SerializeWith { ", "value : self . x , ", "phantom : :: std :: marker :: PhantomData :: < Cow < 'a , str > > , ", "}" ); assert_eq!(expected, tokens.to_string()); } #[test] fn test_integer() { let ii8 = -1i8; let ii16 = -1i16; let ii32 = -1i32; let ii64 = -1i64; let ii128 = -1i128; let iisize = -1isize; let uu8 = 1u8; let uu16 = 1u16; let uu32 = 1u32; let uu64 = 1u64; let uu128 = 1u128; let uusize = 1usize; let tokens = quote! { 1 1i32 1u256 #ii8 #ii16 #ii32 #ii64 #ii128 #iisize #uu8 #uu16 #uu32 #uu64 #uu128 #uusize }; let expected = "1 1i32 1u256 - 1i8 - 1i16 - 1i32 - 1i64 - 1i128 - 1isize 1u8 1u16 1u32 1u64 1u128 1usize"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_floating() { let e32 = 2.345f32; let e64 = 2.345f64; let tokens = quote! { #e32 #e64 }; let expected = concat!("2.345f32 2.345f64"); assert_eq!(expected, tokens.to_string()); } #[test] fn test_char() { let zero = '\u{1}'; let pound = '#'; let quote = '"'; let apost = '\''; let newline = '\n'; let heart = '\u{2764}'; let tokens = quote! { #zero #pound #quote #apost #newline #heart }; let expected = "'\\u{1}' '#' '\"' '\\'' '\\n' '\u{2764}'"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_str() { let s = "\u{1} a 'b \" c"; let tokens = quote!(#s); let expected = "\"\\u{1} a 'b \\\" c\""; assert_eq!(expected, tokens.to_string()); } #[test] fn test_string() { let s = "\u{1} a 'b \" c".to_string(); let tokens = quote!(#s); let expected = "\"\\u{1} a 'b \\\" c\""; assert_eq!(expected, tokens.to_string()); } #[test] fn test_interpolated_literal() { macro_rules! m { ($literal:literal) => { quote!($literal) }; } let tokens = m!(1); let expected = "1"; assert_eq!(expected, tokens.to_string()); let tokens = m!(-1); let expected = "- 1"; assert_eq!(expected, tokens.to_string()); let tokens = m!(true); let expected = "true"; assert_eq!(expected, tokens.to_string()); let tokens = m!(-true); let expected = "- true"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_ident() { let foo = Ident::new("Foo", Span::call_site()); let bar = Ident::new(&format!("Bar{}", 7), Span::call_site()); let tokens = quote!(struct #foo; enum #bar {}); let expected = "struct Foo ; enum Bar7 { }"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_underscore() { let tokens = quote!(let _;); let expected = "let _ ;"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_duplicate() { let ch = 'x'; let tokens = quote!(#ch #ch); let expected = "'x' 'x'"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_fancy_repetition() { let foo = vec!["a", "b"]; let bar = vec![true, false]; let tokens = quote! { #(#foo: #bar),* }; let expected = r#""a" : true , "b" : false"#; assert_eq!(expected, tokens.to_string()); } #[test] fn test_nested_fancy_repetition() { let nested = vec![vec!['a', 'b', 'c'], vec!['x', 'y', 'z']]; let tokens = quote! { #( #(#nested)* ),* }; let expected = "'a' 'b' 'c' , 'x' 'y' 'z'"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_duplicate_name_repetition() { let foo = &["a", "b"]; let tokens = quote! { #(#foo: #foo),* #(#foo: #foo),* }; let expected = r#""a" : "a" , "b" : "b" "a" : "a" , "b" : "b""#; assert_eq!(expected, tokens.to_string()); } #[test] fn test_duplicate_name_repetition_no_copy() { let foo = vec!["a".to_owned(), "b".to_owned()]; let tokens = quote! { #(#foo: #foo),* }; let expected = r#""a" : "a" , "b" : "b""#; assert_eq!(expected, tokens.to_string()); } #[test] fn test_btreeset_repetition() { let mut set = BTreeSet::new(); set.insert("a".to_owned()); set.insert("b".to_owned()); let tokens = quote! { #(#set: #set),* }; let expected = r#""a" : "a" , "b" : "b""#; assert_eq!(expected, tokens.to_string()); } #[test] fn test_variable_name_conflict() { // The implementation of `#(...),*` uses the variable `_i` but it should be // fine, if a little confusing when debugging. let _i = vec!['a', 'b']; let tokens = quote! { #(#_i),* }; let expected = "'a' , 'b'"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_nonrep_in_repetition() { let rep = vec!["a", "b"]; let nonrep = "c"; let tokens = quote! { #(#rep #rep : #nonrep #nonrep),* }; let expected = r#""a" "a" : "c" "c" , "b" "b" : "c" "c""#; assert_eq!(expected, tokens.to_string()); } #[test] fn test_empty_quote() { let tokens = quote!(); assert_eq!("", tokens.to_string()); } #[test] fn test_box_str() { let b = "str".to_owned().into_boxed_str(); let tokens = quote! { #b }; assert_eq!("\"str\"", tokens.to_string()); } #[test] fn test_cow() { let owned: Cow = Cow::Owned(Ident::new("owned", Span::call_site())); let ident = Ident::new("borrowed", Span::call_site()); let borrowed = Cow::Borrowed(&ident); let tokens = quote! { #owned #borrowed }; assert_eq!("owned borrowed", tokens.to_string()); } #[test] fn test_closure() { fn field_i(i: usize) -> Ident { format_ident!("__field{}", i) } let fields = (0usize..3) .map(field_i as fn(_) -> _) .map(|var| quote! { #var }); let tokens = quote! { #(#fields)* }; assert_eq!("__field0 __field1 __field2", tokens.to_string()); } #[test] fn test_append_tokens() { let mut a = quote!(a); let b = quote!(b); a.append_all(b); assert_eq!("a b", a.to_string()); } #[test] fn test_format_ident() { let id0 = format_ident!("Aa"); let id1 = format_ident!("Hello{x}", x = id0); let id2 = format_ident!("Hello{x}", x = 5usize); let id3 = format_ident!("Hello{}_{x}", id0, x = 10usize); let id4 = format_ident!("Aa", span = Span::call_site()); let id5 = format_ident!("Hello{}", Cow::Borrowed("World")); assert_eq!(id0, "Aa"); assert_eq!(id1, "HelloAa"); assert_eq!(id2, "Hello5"); assert_eq!(id3, "HelloAa_10"); assert_eq!(id4, "Aa"); assert_eq!(id5, "HelloWorld"); } #[test] fn test_format_ident_strip_raw() { let id = format_ident!("r#struct"); let my_id = format_ident!("MyId{}", id); let raw_my_id = format_ident!("r#MyId{}", id); assert_eq!(id, "r#struct"); assert_eq!(my_id, "MyIdstruct"); assert_eq!(raw_my_id, "r#MyIdstruct"); } #[test] fn test_outer_line_comment() { let tokens = quote! { /// doc }; let expected = "# [doc = r\" doc\"]"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_inner_line_comment() { let tokens = quote! { //! doc }; let expected = "# ! [doc = r\" doc\"]"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_outer_block_comment() { let tokens = quote! { /** doc */ }; let expected = "# [doc = r\" doc \"]"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_inner_block_comment() { let tokens = quote! { /*! doc */ }; let expected = "# ! [doc = r\" doc \"]"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_outer_attr() { let tokens = quote! { #[inline] }; let expected = "# [inline]"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_inner_attr() { let tokens = quote! { #![no_std] }; let expected = "# ! [no_std]"; assert_eq!(expected, tokens.to_string()); } // https://github.com/dtolnay/quote/issues/130 #[test] fn test_star_after_repetition() { let c = vec!['0', '1']; let tokens = quote! { #( f(#c); )* *out = None; }; let expected = "f ('0') ; f ('1') ; * out = None ;"; assert_eq!(expected, tokens.to_string()); } #[test] fn test_quote_raw_id() { let id = quote!(r#raw_id); assert_eq!(id.to_string(), "r#raw_id"); } #[test] fn test_type_inference_for_span() { trait CallSite { fn get() -> Self; } impl CallSite for Span { fn get() -> Self { Span::call_site() } } let span = Span::call_site(); let _ = quote_spanned!(span=> ...); let delim_span = Group::new(Delimiter::Parenthesis, TokenStream::new()).delim_span(); let _ = quote_spanned!(delim_span=> ...); let inferred = CallSite::get(); let _ = quote_spanned!(inferred=> ...); if false { let proc_macro_span = proc_macro::Span::call_site(); let _ = quote_spanned!(proc_macro_span.into()=> ...); } } quote/tests/compiletest.rs0000644000175000017500000000024614661133735016740 0ustar jamespagejamespage#[rustversion::attr(not(nightly), ignore)] #[cfg_attr(miri, ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/*.rs"); } quote/tests/ui/0000775000175000017500000000000014661133735014457 5ustar jamespagejamespagequote/tests/ui/not-repeatable.rs0000644000175000017500000000015214661133735017723 0ustar jamespagejamespageuse quote::quote; struct Ipv4Addr; fn main() { let ip = Ipv4Addr; let _ = quote! { #(#ip)* }; } quote/tests/ui/not-repeatable.stderr0000644000175000017500000000331414661133735020605 0ustar jamespagejamespageerror[E0599]: the method `quote_into_iter` exists for struct `Ipv4Addr`, but its trait bounds were not satisfied --> tests/ui/not-repeatable.rs:7:13 | 3 | struct Ipv4Addr; | --------------- method `quote_into_iter` not found for this struct because it doesn't satisfy `Ipv4Addr: Iterator`, `Ipv4Addr: ToTokens`, `Ipv4Addr: ext::RepIteratorExt` or `Ipv4Addr: ext::RepToTokensExt` ... 7 | let _ = quote! { #(#ip)* }; | ^^^^^^^^^^^^^^^^^^ method cannot be called on `Ipv4Addr` due to unsatisfied trait bounds | = note: the following trait bounds were not satisfied: `Ipv4Addr: Iterator` which is required by `Ipv4Addr: ext::RepIteratorExt` `&Ipv4Addr: Iterator` which is required by `&Ipv4Addr: ext::RepIteratorExt` `Ipv4Addr: ToTokens` which is required by `Ipv4Addr: ext::RepToTokensExt` `&mut Ipv4Addr: Iterator` which is required by `&mut Ipv4Addr: ext::RepIteratorExt` note: the traits `Iterator` and `ToTokens` must be implemented --> src/to_tokens.rs | | pub trait ToTokens { | ^^^^^^^^^^^^^^^^^^ | ::: $RUST/core/src/iter/traits/iterator.rs | | pub trait Iterator { | ^^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `quote_into_iter`, perhaps you need to implement one of them: candidate #1: `ext::RepAsIteratorExt` candidate #2: `ext::RepIteratorExt` candidate #3: `ext::RepToTokensExt` = note: this error originates in the macro `$crate::quote_bind_into_iter` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info) quote/tests/ui/does-not-have-iter-interpolated-dup.stderr0000644000175000017500000000105714661133735024575 0ustar jamespagejamespageerror[E0308]: mismatched types --> tests/ui/does-not-have-iter-interpolated-dup.rs:8:5 | 8 | quote!(#(#nonrep #nonrep)*); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | expected `HasIterator`, found `ThereIsNoIteratorInRepetition` | expected due to this | here the type of `has_iter` is inferred to be `ThereIsNoIteratorInRepetition` | = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info) quote/tests/ui/does-not-have-iter-interpolated.stderr0000644000175000017500000000103314661133735024001 0ustar jamespagejamespageerror[E0308]: mismatched types --> tests/ui/does-not-have-iter-interpolated.rs:8:5 | 8 | quote!(#(#nonrep)*); | ^^^^^^^^^^^^^^^^^^^ | | | expected `HasIterator`, found `ThereIsNoIteratorInRepetition` | expected due to this | here the type of `has_iter` is inferred to be `ThereIsNoIteratorInRepetition` | = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info) quote/tests/ui/wrong-type-span.rs0000644000175000017500000000015514661133735020076 0ustar jamespagejamespageuse quote::quote_spanned; fn main() { let span = ""; let x = 0i32; quote_spanned!(span=> #x); } quote/tests/ui/wrong-type-span.stderr0000644000175000017500000000053214661133735020754 0ustar jamespagejamespageerror[E0308]: mismatched types --> tests/ui/wrong-type-span.rs:6:5 | 6 | quote_spanned!(span=> #x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | | | expected `Span`, found `&str` | expected due to this | = note: this error originates in the macro `quote_spanned` (in Nightly builds, run with -Z macro-backtrace for more info) quote/tests/ui/does-not-have-iter-interpolated-dup.rs0000644000175000017500000000032114661133735023707 0ustar jamespagejamespageuse quote::quote; fn main() { let nonrep = ""; // Without some protection against repetitions with no iterator somewhere // inside, this would loop infinitely. quote!(#(#nonrep #nonrep)*); } quote/tests/ui/does-not-have-iter.rs0000644000175000017500000000006614661133735020437 0ustar jamespagejamespageuse quote::quote; fn main() { quote!(#(a b)*); } quote/tests/ui/does-not-have-iter-separated.stderr0000644000175000017500000000067414661133735023271 0ustar jamespagejamespageerror[E0308]: mismatched types --> tests/ui/does-not-have-iter-separated.rs:4:5 | 4 | quote!(#(a b),*); | ^^^^^^^^^^^^^^^^ | | | expected `HasIterator`, found `ThereIsNoIteratorInRepetition` | expected due to this | = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info) quote/tests/ui/not-quotable.stderr0000644000175000017500000000126514661133735020320 0ustar jamespagejamespageerror[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied --> tests/ui/not-quotable.rs:6:13 | 6 | let _ = quote! { #ip }; | ^^^^^^^^^^^^^^ | | | the trait `ToTokens` is not implemented for `Ipv4Addr` | required by a bound introduced by this call | = help: the following other types implement trait `ToTokens`: &'a T &'a mut T Box Cow<'a, T> Option Rc RepInterp String and $N others = note: this error originates in the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info) quote/tests/ui/not-quotable.rs0000644000175000017500000000016714661133735017441 0ustar jamespagejamespageuse quote::quote; use std::net::Ipv4Addr; fn main() { let ip = Ipv4Addr::LOCALHOST; let _ = quote! { #ip }; } quote/tests/ui/does-not-have-iter.stderr0000644000175000017500000000066014661133735021316 0ustar jamespagejamespageerror[E0308]: mismatched types --> tests/ui/does-not-have-iter.rs:4:5 | 4 | quote!(#(a b)*); | ^^^^^^^^^^^^^^^ | | | expected `HasIterator`, found `ThereIsNoIteratorInRepetition` | expected due to this | = note: this error originates in the macro `$crate::quote_token_with_context` which comes from the expansion of the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info) quote/tests/ui/does-not-have-iter-interpolated.rs0000644000175000017500000000031114661133735023120 0ustar jamespagejamespageuse quote::quote; fn main() { let nonrep = ""; // Without some protection against repetitions with no iterator somewhere // inside, this would loop infinitely. quote!(#(#nonrep)*); } quote/tests/ui/does-not-have-iter-separated.rs0000644000175000017500000000006714661133735022406 0ustar jamespagejamespageuse quote::quote; fn main() { quote!(#(a b),*); } quote/LICENSE-MIT0000644000175000017500000000177714661133735014346 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. quote/src/0000775000175000017500000000000014661133735013467 5ustar jamespagejamespagequote/src/ext.rs0000644000175000017500000000526314661133735014641 0ustar jamespagejamespageuse super::ToTokens; use core::iter; use proc_macro2::{TokenStream, TokenTree}; /// TokenStream extension trait with methods for appending tokens. /// /// This trait is sealed and cannot be implemented outside of the `quote` crate. pub trait TokenStreamExt: private::Sealed { /// For use by `ToTokens` implementations. /// /// Appends the token specified to this list of tokens. fn append(&mut self, token: U) where U: Into; /// For use by `ToTokens` implementations. /// /// ``` /// # use quote::{quote, TokenStreamExt, ToTokens}; /// # use proc_macro2::TokenStream; /// # /// struct X; /// /// impl ToTokens for X { /// fn to_tokens(&self, tokens: &mut TokenStream) { /// tokens.append_all(&[true, false]); /// } /// } /// /// let tokens = quote!(#X); /// assert_eq!(tokens.to_string(), "true false"); /// ``` fn append_all(&mut self, iter: I) where I: IntoIterator, I::Item: ToTokens; /// For use by `ToTokens` implementations. /// /// Appends all of the items in the iterator `I`, separated by the tokens /// `U`. fn append_separated(&mut self, iter: I, op: U) where I: IntoIterator, I::Item: ToTokens, U: ToTokens; /// For use by `ToTokens` implementations. /// /// Appends all tokens in the iterator `I`, appending `U` after each /// element, including after the last element of the iterator. fn append_terminated(&mut self, iter: I, term: U) where I: IntoIterator, I::Item: ToTokens, U: ToTokens; } impl TokenStreamExt for TokenStream { fn append(&mut self, token: U) where U: Into, { self.extend(iter::once(token.into())); } fn append_all(&mut self, iter: I) where I: IntoIterator, I::Item: ToTokens, { for token in iter { token.to_tokens(self); } } fn append_separated(&mut self, iter: I, op: U) where I: IntoIterator, I::Item: ToTokens, U: ToTokens, { for (i, token) in iter.into_iter().enumerate() { if i > 0 { op.to_tokens(self); } token.to_tokens(self); } } fn append_terminated(&mut self, iter: I, term: U) where I: IntoIterator, I::Item: ToTokens, U: ToTokens, { for token in iter { token.to_tokens(self); term.to_tokens(self); } } } mod private { use proc_macro2::TokenStream; pub trait Sealed {} impl Sealed for TokenStream {} } quote/src/format.rs0000644000175000017500000001127414661133735015330 0ustar jamespagejamespage/// Formatting macro for constructing `Ident`s. /// ///
/// /// # Syntax /// /// Syntax is copied from the [`format!`] macro, supporting both positional and /// named arguments. /// /// Only a limited set of formatting traits are supported. The current mapping /// of format types to traits is: /// /// * `{}` ⇒ [`IdentFragment`] /// * `{:o}` ⇒ [`Octal`](std::fmt::Octal) /// * `{:x}` ⇒ [`LowerHex`](std::fmt::LowerHex) /// * `{:X}` ⇒ [`UpperHex`](std::fmt::UpperHex) /// * `{:b}` ⇒ [`Binary`](std::fmt::Binary) /// /// See [`std::fmt`] for more information. /// ///
/// /// # IdentFragment /// /// Unlike `format!`, this macro uses the [`IdentFragment`] formatting trait by /// default. This trait is like `Display`, with a few differences: /// /// * `IdentFragment` is only implemented for a limited set of types, such as /// unsigned integers and strings. /// * [`Ident`] arguments will have their `r#` prefixes stripped, if present. /// /// [`IdentFragment`]: crate::IdentFragment /// [`Ident`]: proc_macro2::Ident /// ///
/// /// # Hygiene /// /// The [`Span`] of the first `Ident` argument is used as the span of the final /// identifier, falling back to [`Span::call_site`] when no identifiers are /// provided. /// /// ``` /// # use quote::format_ident; /// # let ident = format_ident!("Ident"); /// // If `ident` is an Ident, the span of `my_ident` will be inherited from it. /// let my_ident = format_ident!("My{}{}", ident, "IsCool"); /// assert_eq!(my_ident, "MyIdentIsCool"); /// ``` /// /// Alternatively, the span can be overridden by passing the `span` named /// argument. /// /// ``` /// # use quote::format_ident; /// # const IGNORE_TOKENS: &'static str = stringify! { /// let my_span = /* ... */; /// # }; /// # let my_span = proc_macro2::Span::call_site(); /// format_ident!("MyIdent", span = my_span); /// ``` /// /// [`Span`]: proc_macro2::Span /// [`Span::call_site`]: proc_macro2::Span::call_site /// ///


/// /// # Panics /// /// This method will panic if the resulting formatted string is not a valid /// identifier. /// ///
/// /// # Examples /// /// Composing raw and non-raw identifiers: /// ``` /// # use quote::format_ident; /// let my_ident = format_ident!("My{}", "Ident"); /// assert_eq!(my_ident, "MyIdent"); /// /// let raw = format_ident!("r#Raw"); /// assert_eq!(raw, "r#Raw"); /// /// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw); /// assert_eq!(my_ident_raw, "MyIdentIsRaw"); /// ``` /// /// Integer formatting options: /// ``` /// # use quote::format_ident; /// let num: u32 = 10; /// /// let decimal = format_ident!("Id_{}", num); /// assert_eq!(decimal, "Id_10"); /// /// let octal = format_ident!("Id_{:o}", num); /// assert_eq!(octal, "Id_12"); /// /// let binary = format_ident!("Id_{:b}", num); /// assert_eq!(binary, "Id_1010"); /// /// let lower_hex = format_ident!("Id_{:x}", num); /// assert_eq!(lower_hex, "Id_a"); /// /// let upper_hex = format_ident!("Id_{:X}", num); /// assert_eq!(upper_hex, "Id_A"); /// ``` #[macro_export] macro_rules! format_ident { ($fmt:expr) => { $crate::format_ident_impl!([ $crate::__private::Option::None, $fmt ]) }; ($fmt:expr, $($rest:tt)*) => { $crate::format_ident_impl!([ $crate::__private::Option::None, $fmt ] $($rest)*) }; } #[macro_export] #[doc(hidden)] macro_rules! format_ident_impl { // Final state ([$span:expr, $($fmt:tt)*]) => { $crate::__private::mk_ident( &$crate::__private::format!($($fmt)*), $span, ) }; // Span argument ([$old:expr, $($fmt:tt)*] span = $span:expr) => { $crate::format_ident_impl!([$old, $($fmt)*] span = $span,) }; ([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => { $crate::format_ident_impl!([ $crate::__private::Option::Some::<$crate::__private::Span>($span), $($fmt)* ] $($rest)*) }; // Named argument ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => { $crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,) }; ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => { match $crate::__private::IdentFragmentAdapter(&$arg) { arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*), } }; // Positional argument ([$span:expr, $($fmt:tt)*] $arg:expr) => { $crate::format_ident_impl!([$span, $($fmt)*] $arg,) }; ([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => { match $crate::__private::IdentFragmentAdapter(&$arg) { arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*), } }; } quote/src/ident_fragment.rs0000644000175000017500000000440514661133735017024 0ustar jamespagejamespageuse alloc::borrow::Cow; use core::fmt; use proc_macro2::{Ident, Span}; /// Specialized formatting trait used by `format_ident!`. /// /// [`Ident`] arguments formatted using this trait will have their `r#` prefix /// stripped, if present. /// /// See [`format_ident!`] for more information. /// /// [`format_ident!`]: crate::format_ident pub trait IdentFragment { /// Format this value as an identifier fragment. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result; /// Span associated with this `IdentFragment`. /// /// If non-`None`, may be inherited by formatted identifiers. fn span(&self) -> Option { None } } impl IdentFragment for &T { fn span(&self) -> Option { ::span(*self) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { IdentFragment::fmt(*self, f) } } impl IdentFragment for &mut T { fn span(&self) -> Option { ::span(*self) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { IdentFragment::fmt(*self, f) } } impl IdentFragment for Ident { fn span(&self) -> Option { Some(self.span()) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let id = self.to_string(); if let Some(id) = id.strip_prefix("r#") { fmt::Display::fmt(id, f) } else { fmt::Display::fmt(&id[..], f) } } } impl IdentFragment for Cow<'_, T> where T: IdentFragment + ToOwned + ?Sized, { fn span(&self) -> Option { T::span(self) } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { T::fmt(self, f) } } // Limited set of types which this is implemented for, as we want to avoid types // which will often include non-identifier characters in their `Display` impl. macro_rules! ident_fragment_display { ($($T:ty),*) => { $( impl IdentFragment for $T { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) } } )* }; } ident_fragment_display!(bool, str, String, char); ident_fragment_display!(u8, u16, u32, u64, u128, usize); quote/src/lib.rs0000644000175000017500000013772714661133735014622 0ustar jamespagejamespage//! [![github]](https://github.com/dtolnay/quote) [![crates-io]](https://crates.io/crates/quote) [![docs-rs]](https://docs.rs/quote) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! This crate provides the [`quote!`] macro for turning Rust syntax tree data //! structures into tokens of source code. //! //! [`quote!`]: macro.quote.html //! //! Procedural macros in Rust receive a stream of tokens as input, execute //! arbitrary Rust code to determine how to manipulate those tokens, and produce //! a stream of tokens to hand back to the compiler to compile into the caller's //! crate. Quasi-quoting is a solution to one piece of that — producing //! tokens to return to the compiler. //! //! The idea of quasi-quoting is that we write *code* that we treat as *data*. //! Within the `quote!` macro, we can write what looks like code to our text //! editor or IDE. We get all the benefits of the editor's brace matching, //! syntax highlighting, indentation, and maybe autocompletion. But rather than //! compiling that as code into the current crate, we can treat it as data, pass //! it around, mutate it, and eventually hand it back to the compiler as tokens //! to compile into the macro caller's crate. //! //! This crate is motivated by the procedural macro use case, but is a //! general-purpose Rust quasi-quoting library and is not specific to procedural //! macros. //! //! ```toml //! [dependencies] //! quote = "1.0" //! ``` //! //!
//! //! # Example //! //! The following quasi-quoted block of code is something you might find in [a] //! procedural macro having to do with data structure serialization. The `#var` //! syntax performs interpolation of runtime variables into the quoted tokens. //! Check out the documentation of the [`quote!`] macro for more detail about //! the syntax. See also the [`quote_spanned!`] macro which is important for //! implementing hygienic procedural macros. //! //! [a]: https://serde.rs/ //! [`quote_spanned!`]: macro.quote_spanned.html //! //! ``` //! # use quote::quote; //! # //! # let generics = ""; //! # let where_clause = ""; //! # let field_ty = ""; //! # let item_ty = ""; //! # let path = ""; //! # let value = ""; //! # //! let tokens = quote! { //! struct SerializeWith #generics #where_clause { //! value: &'a #field_ty, //! phantom: core::marker::PhantomData<#item_ty>, //! } //! //! impl #generics serde::Serialize for SerializeWith #generics #where_clause { //! fn serialize(&self, serializer: S) -> Result //! where //! S: serde::Serializer, //! { //! #path(self.value, serializer) //! } //! } //! //! SerializeWith { //! value: #value, //! phantom: core::marker::PhantomData::<#item_ty>, //! } //! }; //! ``` //! //!
//! //! # Non-macro code generators //! //! When using `quote` in a build.rs or main.rs and writing the output out to a //! file, consider having the code generator pass the tokens through //! [prettyplease] before writing. This way if an error occurs in the generated //! code it is convenient for a human to read and debug. //! //! [prettyplease]: https://github.com/dtolnay/prettyplease // Quote types in rustdoc of other crates get linked to here. #![doc(html_root_url = "https://docs.rs/quote/1.0.36")] #![allow( clippy::doc_markdown, clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::module_name_repetitions, // false positive https://github.com/rust-lang/rust-clippy/issues/6983 clippy::wrong_self_convention, )] extern crate alloc; #[cfg(feature = "proc-macro")] extern crate proc_macro; mod ext; mod format; mod ident_fragment; mod to_tokens; // Not public API. #[doc(hidden)] #[path = "runtime.rs"] pub mod __private; pub use crate::ext::TokenStreamExt; pub use crate::ident_fragment::IdentFragment; pub use crate::to_tokens::ToTokens; // Not public API. #[doc(hidden)] pub mod spanned; macro_rules! __quote { ($quote:item) => { /// The whole point. /// /// Performs variable interpolation against the input and produces it as /// [`proc_macro2::TokenStream`]. /// /// Note: for returning tokens to the compiler in a procedural macro, use /// `.into()` on the result to convert to [`proc_macro::TokenStream`]. /// /// [`TokenStream`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.TokenStream.html /// ///
/// /// # Interpolation /// /// Variable interpolation is done with `#var` (similar to `$var` in /// `macro_rules!` macros). This grabs the `var` variable that is currently in /// scope and inserts it in that location in the output tokens. Any type /// implementing the [`ToTokens`] trait can be interpolated. This includes most /// Rust primitive types as well as most of the syntax tree types from the [Syn] /// crate. /// /// [`ToTokens`]: trait.ToTokens.html /// [Syn]: https://github.com/dtolnay/syn /// /// Repetition is done using `#(...)*` or `#(...),*` again similar to /// `macro_rules!`. This iterates through the elements of any variable /// interpolated within the repetition and inserts a copy of the repetition body /// for each one. The variables in an interpolation may be a `Vec`, slice, /// `BTreeSet`, or any `Iterator`. /// /// - `#(#var)*` — no separators /// - `#(#var),*` — the character before the asterisk is used as a separator /// - `#( struct #var; )*` — the repetition can contain other tokens /// - `#( #k => println!("{}", #v), )*` — even multiple interpolations /// ///
/// /// # Hygiene /// /// Any interpolated tokens preserve the `Span` information provided by their /// `ToTokens` implementation. Tokens that originate within the `quote!` /// invocation are spanned with [`Span::call_site()`]. /// /// [`Span::call_site()`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html#method.call_site /// /// A different span can be provided through the [`quote_spanned!`] macro. /// /// [`quote_spanned!`]: macro.quote_spanned.html /// ///
/// /// # Return type /// /// The macro evaluates to an expression of type `proc_macro2::TokenStream`. /// Meanwhile Rust procedural macros are expected to return the type /// `proc_macro::TokenStream`. /// /// The difference between the two types is that `proc_macro` types are entirely /// specific to procedural macros and cannot ever exist in code outside of a /// procedural macro, while `proc_macro2` types may exist anywhere including /// tests and non-macro code like main.rs and build.rs. This is why even the /// procedural macro ecosystem is largely built around `proc_macro2`, because /// that ensures the libraries are unit testable and accessible in non-macro /// contexts. /// /// There is a [`From`]-conversion in both directions so returning the output of /// `quote!` from a procedural macro usually looks like `tokens.into()` or /// `proc_macro::TokenStream::from(tokens)`. /// /// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html /// ///
/// /// # Examples /// /// ### Procedural macro /// /// The structure of a basic procedural macro is as follows. Refer to the [Syn] /// crate for further useful guidance on using `quote!` as part of a procedural /// macro. /// /// [Syn]: https://github.com/dtolnay/syn /// /// ``` /// # #[cfg(any())] /// extern crate proc_macro; /// # extern crate proc_macro2; /// /// # #[cfg(any())] /// use proc_macro::TokenStream; /// # use proc_macro2::TokenStream; /// use quote::quote; /// /// # const IGNORE_TOKENS: &'static str = stringify! { /// #[proc_macro_derive(HeapSize)] /// # }; /// pub fn derive_heap_size(input: TokenStream) -> TokenStream { /// // Parse the input and figure out what implementation to generate... /// # const IGNORE_TOKENS: &'static str = stringify! { /// let name = /* ... */; /// let expr = /* ... */; /// # }; /// # /// # let name = 0; /// # let expr = 0; /// /// let expanded = quote! { /// // The generated impl. /// impl heapsize::HeapSize for #name { /// fn heap_size_of_children(&self) -> usize { /// #expr /// } /// } /// }; /// /// // Hand the output tokens back to the compiler. /// TokenStream::from(expanded) /// } /// ``` /// ///


/// /// ### Combining quoted fragments /// /// Usually you don't end up constructing an entire final `TokenStream` in one /// piece. Different parts may come from different helper functions. The tokens /// produced by `quote!` themselves implement `ToTokens` and so can be /// interpolated into later `quote!` invocations to build up a final result. /// /// ``` /// # use quote::quote; /// # /// let type_definition = quote! {...}; /// let methods = quote! {...}; /// /// let tokens = quote! { /// #type_definition /// #methods /// }; /// ``` /// ///


/// /// ### Constructing identifiers /// /// Suppose we have an identifier `ident` which came from somewhere in a macro /// input and we need to modify it in some way for the macro output. Let's /// consider prepending the identifier with an underscore. /// /// Simply interpolating the identifier next to an underscore will not have the /// behavior of concatenating them. The underscore and the identifier will /// continue to be two separate tokens as if you had written `_ x`. /// /// ``` /// # use proc_macro2::{self as syn, Span}; /// # use quote::quote; /// # /// # let ident = syn::Ident::new("i", Span::call_site()); /// # /// // incorrect /// quote! { /// let mut _#ident = 0; /// } /// # ; /// ``` /// /// The solution is to build a new identifier token with the correct value. As /// this is such a common case, the [`format_ident!`] macro provides a /// convenient utility for doing so correctly. /// /// ``` /// # use proc_macro2::{Ident, Span}; /// # use quote::{format_ident, quote}; /// # /// # let ident = Ident::new("i", Span::call_site()); /// # /// let varname = format_ident!("_{}", ident); /// quote! { /// let mut #varname = 0; /// } /// # ; /// ``` /// /// Alternatively, the APIs provided by Syn and proc-macro2 can be used to /// directly build the identifier. This is roughly equivalent to the above, but /// will not handle `ident` being a raw identifier. /// /// ``` /// # use proc_macro2::{self as syn, Span}; /// # use quote::quote; /// # /// # let ident = syn::Ident::new("i", Span::call_site()); /// # /// let concatenated = format!("_{}", ident); /// let varname = syn::Ident::new(&concatenated, ident.span()); /// quote! { /// let mut #varname = 0; /// } /// # ; /// ``` /// ///


/// /// ### Making method calls /// /// Let's say our macro requires some type specified in the macro input to have /// a constructor called `new`. We have the type in a variable called /// `field_type` of type `syn::Type` and want to invoke the constructor. /// /// ``` /// # use quote::quote; /// # /// # let field_type = quote!(...); /// # /// // incorrect /// quote! { /// let value = #field_type::new(); /// } /// # ; /// ``` /// /// This works only sometimes. If `field_type` is `String`, the expanded code /// contains `String::new()` which is fine. But if `field_type` is something /// like `Vec` then the expanded code is `Vec::new()` which is invalid /// syntax. Ordinarily in handwritten Rust we would write `Vec::::new()` /// but for macros often the following is more convenient. /// /// ``` /// # use quote::quote; /// # /// # let field_type = quote!(...); /// # /// quote! { /// let value = <#field_type>::new(); /// } /// # ; /// ``` /// /// This expands to `>::new()` which behaves correctly. /// /// A similar pattern is appropriate for trait methods. /// /// ``` /// # use quote::quote; /// # /// # let field_type = quote!(...); /// # /// quote! { /// let value = <#field_type as core::default::Default>::default(); /// } /// # ; /// ``` /// ///


/// /// ### Interpolating text inside of doc comments /// /// Neither doc comments nor string literals get interpolation behavior in /// quote: /// /// ```compile_fail /// quote! { /// /// try to interpolate: #ident /// /// /// /// ... /// } /// ``` /// /// ```compile_fail /// quote! { /// #[doc = "try to interpolate: #ident"] /// } /// ``` /// /// Instead the best way to build doc comments that involve variables is by /// formatting the doc string literal outside of quote. /// /// ```rust /// # use proc_macro2::{Ident, Span}; /// # use quote::quote; /// # /// # const IGNORE: &str = stringify! { /// let msg = format!(...); /// # }; /// # /// # let ident = Ident::new("var", Span::call_site()); /// # let msg = format!("try to interpolate: {}", ident); /// quote! { /// #[doc = #msg] /// /// /// /// ... /// } /// # ; /// ``` /// ///


/// /// ### Indexing into a tuple struct /// /// When interpolating indices of a tuple or tuple struct, we need them not to /// appears suffixed as integer literals by interpolating them as [`syn::Index`] /// instead. /// /// [`syn::Index`]: https://docs.rs/syn/2.0/syn/struct.Index.html /// /// ```compile_fail /// let i = 0usize..self.fields.len(); /// /// // expands to 0 + self.0usize.heap_size() + self.1usize.heap_size() + ... /// // which is not valid syntax /// quote! { /// 0 #( + self.#i.heap_size() )* /// } /// ``` /// /// ``` /// # use proc_macro2::{Ident, TokenStream}; /// # use quote::quote; /// # /// # mod syn { /// # use proc_macro2::{Literal, TokenStream}; /// # use quote::{ToTokens, TokenStreamExt}; /// # /// # pub struct Index(usize); /// # /// # impl From for Index { /// # fn from(i: usize) -> Self { /// # Index(i) /// # } /// # } /// # /// # impl ToTokens for Index { /// # fn to_tokens(&self, tokens: &mut TokenStream) { /// # tokens.append(Literal::usize_unsuffixed(self.0)); /// # } /// # } /// # } /// # /// # struct Struct { /// # fields: Vec, /// # } /// # /// # impl Struct { /// # fn example(&self) -> TokenStream { /// let i = (0..self.fields.len()).map(syn::Index::from); /// /// // expands to 0 + self.0.heap_size() + self.1.heap_size() + ... /// quote! { /// 0 #( + self.#i.heap_size() )* /// } /// # } /// # } /// ``` $quote }; } #[cfg(doc)] __quote![ #[macro_export] macro_rules! quote { ($($tt:tt)*) => { ... }; } ]; #[cfg(not(doc))] __quote![ #[macro_export] macro_rules! quote { () => { $crate::__private::TokenStream::new() }; // Special case rule for a single tt, for performance. ($tt:tt) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::quote_token!{$tt _s} _s }}; // Special case rules for two tts, for performance. (# $var:ident) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::ToTokens::to_tokens(&$var, &mut _s); _s }}; ($tt1:tt $tt2:tt) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::quote_token!{$tt1 _s} $crate::quote_token!{$tt2 _s} _s }}; // Rule for any other number of tokens. ($($tt:tt)*) => {{ let mut _s = $crate::__private::TokenStream::new(); $crate::quote_each_token!{_s $($tt)*} _s }}; } ]; macro_rules! __quote_spanned { ($quote_spanned:item) => { /// Same as `quote!`, but applies a given span to all tokens originating within /// the macro invocation. /// ///
/// /// # Syntax /// /// A span expression of type [`Span`], followed by `=>`, followed by the tokens /// to quote. The span expression should be brief — use a variable for /// anything more than a few characters. There should be no space before the /// `=>` token. /// /// [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html /// /// ``` /// # use proc_macro2::Span; /// # use quote::quote_spanned; /// # /// # const IGNORE_TOKENS: &'static str = stringify! { /// let span = /* ... */; /// # }; /// # let span = Span::call_site(); /// # let init = 0; /// /// // On one line, use parentheses. /// let tokens = quote_spanned!(span=> Box::into_raw(Box::new(#init))); /// /// // On multiple lines, place the span at the top and use braces. /// let tokens = quote_spanned! {span=> /// Box::into_raw(Box::new(#init)) /// }; /// ``` /// /// The lack of space before the `=>` should look jarring to Rust programmers /// and this is intentional. The formatting is designed to be visibly /// off-balance and draw the eye a particular way, due to the span expression /// being evaluated in the context of the procedural macro and the remaining /// tokens being evaluated in the generated code. /// ///
/// /// # Hygiene /// /// Any interpolated tokens preserve the `Span` information provided by their /// `ToTokens` implementation. Tokens that originate within the `quote_spanned!` /// invocation are spanned with the given span argument. /// ///
/// /// # Example /// /// The following procedural macro code uses `quote_spanned!` to assert that a /// particular Rust type implements the [`Sync`] trait so that references can be /// safely shared between threads. /// /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// /// ``` /// # use quote::{quote_spanned, TokenStreamExt, ToTokens}; /// # use proc_macro2::{Span, TokenStream}; /// # /// # struct Type; /// # /// # impl Type { /// # fn span(&self) -> Span { /// # Span::call_site() /// # } /// # } /// # /// # impl ToTokens for Type { /// # fn to_tokens(&self, _tokens: &mut TokenStream) {} /// # } /// # /// # let ty = Type; /// # let call_site = Span::call_site(); /// # /// let ty_span = ty.span(); /// let assert_sync = quote_spanned! {ty_span=> /// struct _AssertSync where #ty: Sync; /// }; /// ``` /// /// If the assertion fails, the user will see an error like the following. The /// input span of their type is highlighted in the error. /// /// ```text /// error[E0277]: the trait bound `*const (): std::marker::Sync` is not satisfied /// --> src/main.rs:10:21 /// | /// 10 | static ref PTR: *const () = &(); /// | ^^^^^^^^^ `*const ()` cannot be shared between threads safely /// ``` /// /// In this example it is important for the where-clause to be spanned with the /// line/column information of the user's input type so that error messages are /// placed appropriately by the compiler. $quote_spanned }; } #[cfg(doc)] __quote_spanned![ #[macro_export] macro_rules! quote_spanned { ($span:expr=> $($tt:tt)*) => { ... }; } ]; #[cfg(not(doc))] __quote_spanned![ #[macro_export] macro_rules! quote_spanned { ($span:expr=>) => {{ let _: $crate::__private::Span = $crate::__private::get_span($span).__into_span(); $crate::__private::TokenStream::new() }}; // Special case rule for a single tt, for performance. ($span:expr=> $tt:tt) => {{ let mut _s = $crate::__private::TokenStream::new(); let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span(); $crate::quote_token_spanned!{$tt _s _span} _s }}; // Special case rules for two tts, for performance. ($span:expr=> # $var:ident) => {{ let mut _s = $crate::__private::TokenStream::new(); let _: $crate::__private::Span = $crate::__private::get_span($span).__into_span(); $crate::ToTokens::to_tokens(&$var, &mut _s); _s }}; ($span:expr=> $tt1:tt $tt2:tt) => {{ let mut _s = $crate::__private::TokenStream::new(); let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span(); $crate::quote_token_spanned!{$tt1 _s _span} $crate::quote_token_spanned!{$tt2 _s _span} _s }}; // Rule for any other number of tokens. ($span:expr=> $($tt:tt)*) => {{ let mut _s = $crate::__private::TokenStream::new(); let _span: $crate::__private::Span = $crate::__private::get_span($span).__into_span(); $crate::quote_each_token_spanned!{_s _span $($tt)*} _s }}; } ]; // Extract the names of all #metavariables and pass them to the $call macro. // // in: pounded_var_names!(then!(...) a #b c #( #d )* #e) // out: then!(... b); // then!(... d); // then!(... e); #[macro_export] #[doc(hidden)] macro_rules! pounded_var_names { ($call:ident! $extra:tt $($tts:tt)*) => { $crate::pounded_var_names_with_context!{$call! $extra (@ $($tts)*) ($($tts)* @) } }; } #[macro_export] #[doc(hidden)] macro_rules! pounded_var_names_with_context { ($call:ident! $extra:tt ($($b1:tt)*) ($($curr:tt)*)) => { $( $crate::pounded_var_with_context!{$call! $extra $b1 $curr} )* }; } #[macro_export] #[doc(hidden)] macro_rules! pounded_var_with_context { ($call:ident! $extra:tt $b1:tt ( $($inner:tt)* )) => { $crate::pounded_var_names!{$call! $extra $($inner)*} }; ($call:ident! $extra:tt $b1:tt [ $($inner:tt)* ]) => { $crate::pounded_var_names!{$call! $extra $($inner)*} }; ($call:ident! $extra:tt $b1:tt { $($inner:tt)* }) => { $crate::pounded_var_names!{$call! $extra $($inner)*} }; ($call:ident!($($extra:tt)*) # $var:ident) => { $crate::$call!($($extra)* $var); }; ($call:ident! $extra:tt $b1:tt $curr:tt) => {}; } #[macro_export] #[doc(hidden)] macro_rules! quote_bind_into_iter { ($has_iter:ident $var:ident) => { // `mut` may be unused if $var occurs multiple times in the list. #[allow(unused_mut)] let (mut $var, i) = $var.quote_into_iter(); let $has_iter = $has_iter | i; }; } #[macro_export] #[doc(hidden)] macro_rules! quote_bind_next_or_break { ($var:ident) => { let $var = match $var.next() { Some(_x) => $crate::__private::RepInterp(_x), None => break, }; }; } // The obvious way to write this macro is as a tt muncher. This implementation // does something more complex for two reasons. // // - With a tt muncher it's easy to hit Rust's built-in recursion_limit, which // this implementation avoids because it isn't tail recursive. // // - Compile times for a tt muncher are quadratic relative to the length of // the input. This implementation is linear, so it will be faster // (potentially much faster) for big inputs. However, the constant factors // of this implementation are higher than that of a tt muncher, so it is // somewhat slower than a tt muncher if there are many invocations with // short inputs. // // An invocation like this: // // quote_each_token!(_s a b c d e f g h i j); // // expands to this: // // quote_tokens_with_context!(_s // (@ @ @ @ @ @ a b c d e f g h i j) // (@ @ @ @ @ a b c d e f g h i j @) // (@ @ @ @ a b c d e f g h i j @ @) // (@ @ @ (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) @ @ @) // (@ @ a b c d e f g h i j @ @ @ @) // (@ a b c d e f g h i j @ @ @ @ @) // (a b c d e f g h i j @ @ @ @ @ @) // ); // // which gets transposed and expanded to this: // // quote_token_with_context!(_s @ @ @ @ @ @ a); // quote_token_with_context!(_s @ @ @ @ @ a b); // quote_token_with_context!(_s @ @ @ @ a b c); // quote_token_with_context!(_s @ @ @ (a) b c d); // quote_token_with_context!(_s @ @ a (b) c d e); // quote_token_with_context!(_s @ a b (c) d e f); // quote_token_with_context!(_s a b c (d) e f g); // quote_token_with_context!(_s b c d (e) f g h); // quote_token_with_context!(_s c d e (f) g h i); // quote_token_with_context!(_s d e f (g) h i j); // quote_token_with_context!(_s e f g (h) i j @); // quote_token_with_context!(_s f g h (i) j @ @); // quote_token_with_context!(_s g h i (j) @ @ @); // quote_token_with_context!(_s h i j @ @ @ @); // quote_token_with_context!(_s i j @ @ @ @ @); // quote_token_with_context!(_s j @ @ @ @ @ @); // // Without having used muncher-style recursion, we get one invocation of // quote_token_with_context for each original tt, with three tts of context on // either side. This is enough for the longest possible interpolation form (a // repetition with separator, as in `# (#var) , *`) to be fully represented with // the first or last tt in the middle. // // The middle tt (surrounded by parentheses) is the tt being processed. // // - When it is a `#`, quote_token_with_context can do an interpolation. The // interpolation kind will depend on the three subsequent tts. // // - When it is within a later part of an interpolation, it can be ignored // because the interpolation has already been done. // // - When it is not part of an interpolation it can be pushed as a single // token into the output. // // - When the middle token is an unparenthesized `@`, that call is one of the // first 3 or last 3 calls of quote_token_with_context and does not // correspond to one of the original input tokens, so turns into nothing. #[macro_export] #[doc(hidden)] macro_rules! quote_each_token { ($tokens:ident $($tts:tt)*) => { $crate::quote_tokens_with_context!{$tokens (@ @ @ @ @ @ $($tts)*) (@ @ @ @ @ $($tts)* @) (@ @ @ @ $($tts)* @ @) (@ @ @ $(($tts))* @ @ @) (@ @ $($tts)* @ @ @ @) (@ $($tts)* @ @ @ @ @) ($($tts)* @ @ @ @ @ @) } }; } // See the explanation on quote_each_token. #[macro_export] #[doc(hidden)] macro_rules! quote_each_token_spanned { ($tokens:ident $span:ident $($tts:tt)*) => { $crate::quote_tokens_with_context_spanned!{$tokens $span (@ @ @ @ @ @ $($tts)*) (@ @ @ @ @ $($tts)* @) (@ @ @ @ $($tts)* @ @) (@ @ @ $(($tts))* @ @ @) (@ @ $($tts)* @ @ @ @) (@ $($tts)* @ @ @ @ @) ($($tts)* @ @ @ @ @ @) } }; } // See the explanation on quote_each_token. #[macro_export] #[doc(hidden)] macro_rules! quote_tokens_with_context { ($tokens:ident ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*) ($($curr:tt)*) ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*) ) => { $( $crate::quote_token_with_context!{$tokens $b3 $b2 $b1 $curr $a1 $a2 $a3} )* }; } // See the explanation on quote_each_token. #[macro_export] #[doc(hidden)] macro_rules! quote_tokens_with_context_spanned { ($tokens:ident $span:ident ($($b3:tt)*) ($($b2:tt)*) ($($b1:tt)*) ($($curr:tt)*) ($($a1:tt)*) ($($a2:tt)*) ($($a3:tt)*) ) => { $( $crate::quote_token_with_context_spanned!{$tokens $span $b3 $b2 $b1 $curr $a1 $a2 $a3} )* }; } // See the explanation on quote_each_token. #[macro_export] #[doc(hidden)] macro_rules! quote_token_with_context { // Unparenthesized `@` indicates this call does not correspond to one of the // original input tokens. Ignore it. ($tokens:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {}; // A repetition with no separator. ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{ use $crate::__private::ext::*; let has_iter = $crate::__private::ThereIsNoIteratorInRepetition; $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*} let _: $crate::__private::HasIterator = has_iter; // This is `while true` instead of `loop` because if there are no // iterators used inside of this repetition then the body would not // contain any `break`, so the compiler would emit unreachable code // warnings on anything below the loop. We use has_iter to detect and // fail to compile when there are no iterators, so here we just work // around the unneeded extra warning. while true { $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*} $crate::quote_each_token!{$tokens $($inner)*} } }}; // ... and one step later. ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {}; // ... and one step later. ($tokens:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {}; // A repetition with separator. ($tokens:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{ use $crate::__private::ext::*; let mut _i = 0usize; let has_iter = $crate::__private::ThereIsNoIteratorInRepetition; $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*} let _: $crate::__private::HasIterator = has_iter; while true { $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*} if _i > 0 { $crate::quote_token!{$sep $tokens} } _i += 1; $crate::quote_each_token!{$tokens $($inner)*} } }}; // ... and one step later. ($tokens:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {}; // ... and one step later. ($tokens:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {}; // (A special case for `#(var)**`, where the first `*` is treated as the // repetition symbol and the second `*` is treated as an ordinary token.) ($tokens:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => { // https://github.com/dtolnay/quote/issues/130 $crate::quote_token!{* $tokens} }; // ... and one step later. ($tokens:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {}; // A non-repetition interpolation. ($tokens:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => { $crate::ToTokens::to_tokens(&$var, &mut $tokens); }; // ... and one step later. ($tokens:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {}; // An ordinary token, not part of any interpolation. ($tokens:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => { $crate::quote_token!{$curr $tokens} }; } // See the explanation on quote_each_token, and on the individual rules of // quote_token_with_context. #[macro_export] #[doc(hidden)] macro_rules! quote_token_with_context_spanned { ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt @ $a1:tt $a2:tt $a3:tt) => {}; ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) * $a3:tt) => {{ use $crate::__private::ext::*; let has_iter = $crate::__private::ThereIsNoIteratorInRepetition; $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*} let _: $crate::__private::HasIterator = has_iter; while true { $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*} $crate::quote_each_token_spanned!{$tokens $span $($inner)*} } }}; ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) * $a2:tt $a3:tt) => {}; ($tokens:ident $span:ident $b3:tt # ( $($inner:tt)* ) (*) $a1:tt $a2:tt $a3:tt) => {}; ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) ( $($inner:tt)* ) $sep:tt *) => {{ use $crate::__private::ext::*; let mut _i = 0usize; let has_iter = $crate::__private::ThereIsNoIteratorInRepetition; $crate::pounded_var_names!{quote_bind_into_iter!(has_iter) () $($inner)*} let _: $crate::__private::HasIterator = has_iter; while true { $crate::pounded_var_names!{quote_bind_next_or_break!() () $($inner)*} if _i > 0 { $crate::quote_token_spanned!{$sep $tokens $span} } _i += 1; $crate::quote_each_token_spanned!{$tokens $span $($inner)*} } }}; ($tokens:ident $span:ident $b3:tt $b2:tt # (( $($inner:tt)* )) $sep:tt * $a3:tt) => {}; ($tokens:ident $span:ident $b3:tt # ( $($inner:tt)* ) ($sep:tt) * $a2:tt $a3:tt) => {}; ($tokens:ident $span:ident # ( $($inner:tt)* ) * (*) $a1:tt $a2:tt $a3:tt) => { // https://github.com/dtolnay/quote/issues/130 $crate::quote_token_spanned!{* $tokens $span} }; ($tokens:ident $span:ident # ( $($inner:tt)* ) $sep:tt (*) $a1:tt $a2:tt $a3:tt) => {}; ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt (#) $var:ident $a2:tt $a3:tt) => { $crate::ToTokens::to_tokens(&$var, &mut $tokens); }; ($tokens:ident $span:ident $b3:tt $b2:tt # ($var:ident) $a1:tt $a2:tt $a3:tt) => {}; ($tokens:ident $span:ident $b3:tt $b2:tt $b1:tt ($curr:tt) $a1:tt $a2:tt $a3:tt) => { $crate::quote_token_spanned!{$curr $tokens $span} }; } // These rules are ordered by approximate token frequency, at least for the // first 10 or so, to improve compile times. Having `ident` first is by far the // most important because it's typically 2-3x more common than the next most // common token. // // Separately, we put the token being matched in the very front so that failing // rules may fail to match as quickly as possible. #[macro_export] #[doc(hidden)] macro_rules! quote_token { ($ident:ident $tokens:ident) => { $crate::__private::push_ident(&mut $tokens, stringify!($ident)); }; (:: $tokens:ident) => { $crate::__private::push_colon2(&mut $tokens); }; (( $($inner:tt)* ) $tokens:ident) => { $crate::__private::push_group( &mut $tokens, $crate::__private::Delimiter::Parenthesis, $crate::quote!($($inner)*), ); }; ([ $($inner:tt)* ] $tokens:ident) => { $crate::__private::push_group( &mut $tokens, $crate::__private::Delimiter::Bracket, $crate::quote!($($inner)*), ); }; ({ $($inner:tt)* } $tokens:ident) => { $crate::__private::push_group( &mut $tokens, $crate::__private::Delimiter::Brace, $crate::quote!($($inner)*), ); }; (# $tokens:ident) => { $crate::__private::push_pound(&mut $tokens); }; (, $tokens:ident) => { $crate::__private::push_comma(&mut $tokens); }; (. $tokens:ident) => { $crate::__private::push_dot(&mut $tokens); }; (; $tokens:ident) => { $crate::__private::push_semi(&mut $tokens); }; (: $tokens:ident) => { $crate::__private::push_colon(&mut $tokens); }; (+ $tokens:ident) => { $crate::__private::push_add(&mut $tokens); }; (+= $tokens:ident) => { $crate::__private::push_add_eq(&mut $tokens); }; (& $tokens:ident) => { $crate::__private::push_and(&mut $tokens); }; (&& $tokens:ident) => { $crate::__private::push_and_and(&mut $tokens); }; (&= $tokens:ident) => { $crate::__private::push_and_eq(&mut $tokens); }; (@ $tokens:ident) => { $crate::__private::push_at(&mut $tokens); }; (! $tokens:ident) => { $crate::__private::push_bang(&mut $tokens); }; (^ $tokens:ident) => { $crate::__private::push_caret(&mut $tokens); }; (^= $tokens:ident) => { $crate::__private::push_caret_eq(&mut $tokens); }; (/ $tokens:ident) => { $crate::__private::push_div(&mut $tokens); }; (/= $tokens:ident) => { $crate::__private::push_div_eq(&mut $tokens); }; (.. $tokens:ident) => { $crate::__private::push_dot2(&mut $tokens); }; (... $tokens:ident) => { $crate::__private::push_dot3(&mut $tokens); }; (..= $tokens:ident) => { $crate::__private::push_dot_dot_eq(&mut $tokens); }; (= $tokens:ident) => { $crate::__private::push_eq(&mut $tokens); }; (== $tokens:ident) => { $crate::__private::push_eq_eq(&mut $tokens); }; (>= $tokens:ident) => { $crate::__private::push_ge(&mut $tokens); }; (> $tokens:ident) => { $crate::__private::push_gt(&mut $tokens); }; (<= $tokens:ident) => { $crate::__private::push_le(&mut $tokens); }; (< $tokens:ident) => { $crate::__private::push_lt(&mut $tokens); }; (*= $tokens:ident) => { $crate::__private::push_mul_eq(&mut $tokens); }; (!= $tokens:ident) => { $crate::__private::push_ne(&mut $tokens); }; (| $tokens:ident) => { $crate::__private::push_or(&mut $tokens); }; (|= $tokens:ident) => { $crate::__private::push_or_eq(&mut $tokens); }; (|| $tokens:ident) => { $crate::__private::push_or_or(&mut $tokens); }; (? $tokens:ident) => { $crate::__private::push_question(&mut $tokens); }; (-> $tokens:ident) => { $crate::__private::push_rarrow(&mut $tokens); }; (<- $tokens:ident) => { $crate::__private::push_larrow(&mut $tokens); }; (% $tokens:ident) => { $crate::__private::push_rem(&mut $tokens); }; (%= $tokens:ident) => { $crate::__private::push_rem_eq(&mut $tokens); }; (=> $tokens:ident) => { $crate::__private::push_fat_arrow(&mut $tokens); }; (<< $tokens:ident) => { $crate::__private::push_shl(&mut $tokens); }; (<<= $tokens:ident) => { $crate::__private::push_shl_eq(&mut $tokens); }; (>> $tokens:ident) => { $crate::__private::push_shr(&mut $tokens); }; (>>= $tokens:ident) => { $crate::__private::push_shr_eq(&mut $tokens); }; (* $tokens:ident) => { $crate::__private::push_star(&mut $tokens); }; (- $tokens:ident) => { $crate::__private::push_sub(&mut $tokens); }; (-= $tokens:ident) => { $crate::__private::push_sub_eq(&mut $tokens); }; ($lifetime:lifetime $tokens:ident) => { $crate::__private::push_lifetime(&mut $tokens, stringify!($lifetime)); }; (_ $tokens:ident) => { $crate::__private::push_underscore(&mut $tokens); }; ($other:tt $tokens:ident) => { $crate::__private::parse(&mut $tokens, stringify!($other)); }; } // See the comment above `quote_token!` about the rule ordering. #[macro_export] #[doc(hidden)] macro_rules! quote_token_spanned { ($ident:ident $tokens:ident $span:ident) => { $crate::__private::push_ident_spanned(&mut $tokens, $span, stringify!($ident)); }; (:: $tokens:ident $span:ident) => { $crate::__private::push_colon2_spanned(&mut $tokens, $span); }; (( $($inner:tt)* ) $tokens:ident $span:ident) => { $crate::__private::push_group_spanned( &mut $tokens, $span, $crate::__private::Delimiter::Parenthesis, $crate::quote_spanned!($span=> $($inner)*), ); }; ([ $($inner:tt)* ] $tokens:ident $span:ident) => { $crate::__private::push_group_spanned( &mut $tokens, $span, $crate::__private::Delimiter::Bracket, $crate::quote_spanned!($span=> $($inner)*), ); }; ({ $($inner:tt)* } $tokens:ident $span:ident) => { $crate::__private::push_group_spanned( &mut $tokens, $span, $crate::__private::Delimiter::Brace, $crate::quote_spanned!($span=> $($inner)*), ); }; (# $tokens:ident $span:ident) => { $crate::__private::push_pound_spanned(&mut $tokens, $span); }; (, $tokens:ident $span:ident) => { $crate::__private::push_comma_spanned(&mut $tokens, $span); }; (. $tokens:ident $span:ident) => { $crate::__private::push_dot_spanned(&mut $tokens, $span); }; (; $tokens:ident $span:ident) => { $crate::__private::push_semi_spanned(&mut $tokens, $span); }; (: $tokens:ident $span:ident) => { $crate::__private::push_colon_spanned(&mut $tokens, $span); }; (+ $tokens:ident $span:ident) => { $crate::__private::push_add_spanned(&mut $tokens, $span); }; (+= $tokens:ident $span:ident) => { $crate::__private::push_add_eq_spanned(&mut $tokens, $span); }; (& $tokens:ident $span:ident) => { $crate::__private::push_and_spanned(&mut $tokens, $span); }; (&& $tokens:ident $span:ident) => { $crate::__private::push_and_and_spanned(&mut $tokens, $span); }; (&= $tokens:ident $span:ident) => { $crate::__private::push_and_eq_spanned(&mut $tokens, $span); }; (@ $tokens:ident $span:ident) => { $crate::__private::push_at_spanned(&mut $tokens, $span); }; (! $tokens:ident $span:ident) => { $crate::__private::push_bang_spanned(&mut $tokens, $span); }; (^ $tokens:ident $span:ident) => { $crate::__private::push_caret_spanned(&mut $tokens, $span); }; (^= $tokens:ident $span:ident) => { $crate::__private::push_caret_eq_spanned(&mut $tokens, $span); }; (/ $tokens:ident $span:ident) => { $crate::__private::push_div_spanned(&mut $tokens, $span); }; (/= $tokens:ident $span:ident) => { $crate::__private::push_div_eq_spanned(&mut $tokens, $span); }; (.. $tokens:ident $span:ident) => { $crate::__private::push_dot2_spanned(&mut $tokens, $span); }; (... $tokens:ident $span:ident) => { $crate::__private::push_dot3_spanned(&mut $tokens, $span); }; (..= $tokens:ident $span:ident) => { $crate::__private::push_dot_dot_eq_spanned(&mut $tokens, $span); }; (= $tokens:ident $span:ident) => { $crate::__private::push_eq_spanned(&mut $tokens, $span); }; (== $tokens:ident $span:ident) => { $crate::__private::push_eq_eq_spanned(&mut $tokens, $span); }; (>= $tokens:ident $span:ident) => { $crate::__private::push_ge_spanned(&mut $tokens, $span); }; (> $tokens:ident $span:ident) => { $crate::__private::push_gt_spanned(&mut $tokens, $span); }; (<= $tokens:ident $span:ident) => { $crate::__private::push_le_spanned(&mut $tokens, $span); }; (< $tokens:ident $span:ident) => { $crate::__private::push_lt_spanned(&mut $tokens, $span); }; (*= $tokens:ident $span:ident) => { $crate::__private::push_mul_eq_spanned(&mut $tokens, $span); }; (!= $tokens:ident $span:ident) => { $crate::__private::push_ne_spanned(&mut $tokens, $span); }; (| $tokens:ident $span:ident) => { $crate::__private::push_or_spanned(&mut $tokens, $span); }; (|= $tokens:ident $span:ident) => { $crate::__private::push_or_eq_spanned(&mut $tokens, $span); }; (|| $tokens:ident $span:ident) => { $crate::__private::push_or_or_spanned(&mut $tokens, $span); }; (? $tokens:ident $span:ident) => { $crate::__private::push_question_spanned(&mut $tokens, $span); }; (-> $tokens:ident $span:ident) => { $crate::__private::push_rarrow_spanned(&mut $tokens, $span); }; (<- $tokens:ident $span:ident) => { $crate::__private::push_larrow_spanned(&mut $tokens, $span); }; (% $tokens:ident $span:ident) => { $crate::__private::push_rem_spanned(&mut $tokens, $span); }; (%= $tokens:ident $span:ident) => { $crate::__private::push_rem_eq_spanned(&mut $tokens, $span); }; (=> $tokens:ident $span:ident) => { $crate::__private::push_fat_arrow_spanned(&mut $tokens, $span); }; (<< $tokens:ident $span:ident) => { $crate::__private::push_shl_spanned(&mut $tokens, $span); }; (<<= $tokens:ident $span:ident) => { $crate::__private::push_shl_eq_spanned(&mut $tokens, $span); }; (>> $tokens:ident $span:ident) => { $crate::__private::push_shr_spanned(&mut $tokens, $span); }; (>>= $tokens:ident $span:ident) => { $crate::__private::push_shr_eq_spanned(&mut $tokens, $span); }; (* $tokens:ident $span:ident) => { $crate::__private::push_star_spanned(&mut $tokens, $span); }; (- $tokens:ident $span:ident) => { $crate::__private::push_sub_spanned(&mut $tokens, $span); }; (-= $tokens:ident $span:ident) => { $crate::__private::push_sub_eq_spanned(&mut $tokens, $span); }; ($lifetime:lifetime $tokens:ident $span:ident) => { $crate::__private::push_lifetime_spanned(&mut $tokens, $span, stringify!($lifetime)); }; (_ $tokens:ident $span:ident) => { $crate::__private::push_underscore_spanned(&mut $tokens, $span); }; ($other:tt $tokens:ident $span:ident) => { $crate::__private::parse_spanned(&mut $tokens, $span, stringify!($other)); }; } quote/src/spanned.rs0000644000175000017500000000213014661133735015457 0ustar jamespagejamespageuse crate::ToTokens; use proc_macro2::extra::DelimSpan; use proc_macro2::{Span, TokenStream}; // Not public API other than via the syn crate. Use syn::spanned::Spanned. pub trait Spanned: private::Sealed { fn __span(&self) -> Span; } impl Spanned for Span { fn __span(&self) -> Span { *self } } impl Spanned for DelimSpan { fn __span(&self) -> Span { self.join() } } impl Spanned for T { fn __span(&self) -> Span { join_spans(self.into_token_stream()) } } fn join_spans(tokens: TokenStream) -> Span { let mut iter = tokens.into_iter().map(|tt| tt.span()); let first = match iter.next() { Some(span) => span, None => return Span::call_site(), }; iter.fold(None, |_prev, next| Some(next)) .and_then(|last| first.join(last)) .unwrap_or(first) } mod private { use crate::ToTokens; use proc_macro2::extra::DelimSpan; use proc_macro2::Span; pub trait Sealed {} impl Sealed for Span {} impl Sealed for DelimSpan {} impl Sealed for T {} } quote/src/runtime.rs0000644000175000017500000003754014661133735015527 0ustar jamespagejamespageuse self::get_span::{GetSpan, GetSpanBase, GetSpanInner}; use crate::{IdentFragment, ToTokens, TokenStreamExt}; use core::fmt; use core::iter; use core::ops::BitOr; use proc_macro2::{Group, Ident, Punct, Spacing, TokenTree}; #[doc(hidden)] pub use alloc::format; #[doc(hidden)] pub use core::option::Option; #[doc(hidden)] pub type Delimiter = proc_macro2::Delimiter; #[doc(hidden)] pub type Span = proc_macro2::Span; #[doc(hidden)] pub type TokenStream = proc_macro2::TokenStream; #[doc(hidden)] pub struct HasIterator; // True #[doc(hidden)] pub struct ThereIsNoIteratorInRepetition; // False impl BitOr for ThereIsNoIteratorInRepetition { type Output = ThereIsNoIteratorInRepetition; fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition { ThereIsNoIteratorInRepetition } } impl BitOr for HasIterator { type Output = HasIterator; fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator { HasIterator } } impl BitOr for ThereIsNoIteratorInRepetition { type Output = HasIterator; fn bitor(self, _rhs: HasIterator) -> HasIterator { HasIterator } } impl BitOr for HasIterator { type Output = HasIterator; fn bitor(self, _rhs: HasIterator) -> HasIterator { HasIterator } } /// Extension traits used by the implementation of `quote!`. These are defined /// in separate traits, rather than as a single trait due to ambiguity issues. /// /// These traits expose a `quote_into_iter` method which should allow calling /// whichever impl happens to be applicable. Calling that method repeatedly on /// the returned value should be idempotent. #[doc(hidden)] pub mod ext { use super::RepInterp; use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter}; use crate::ToTokens; use alloc::collections::btree_set::{self, BTreeSet}; use core::slice; /// Extension trait providing the `quote_into_iter` method on iterators. #[doc(hidden)] pub trait RepIteratorExt: Iterator + Sized { fn quote_into_iter(self) -> (Self, HasIter) { (self, HasIter) } } impl RepIteratorExt for T {} /// Extension trait providing the `quote_into_iter` method for /// non-iterable types. These types interpolate the same value in each /// iteration of the repetition. #[doc(hidden)] pub trait RepToTokensExt { /// Pretend to be an iterator for the purposes of `quote_into_iter`. /// This allows repeated calls to `quote_into_iter` to continue /// correctly returning DoesNotHaveIter. fn next(&self) -> Option<&Self> { Some(self) } fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) { (self, DoesNotHaveIter) } } impl RepToTokensExt for T {} /// Extension trait providing the `quote_into_iter` method for types that /// can be referenced as an iterator. #[doc(hidden)] pub trait RepAsIteratorExt<'q> { type Iter: Iterator; fn quote_into_iter(&'q self) -> (Self::Iter, HasIter); } impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a T { type Iter = T::Iter; fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { ::quote_into_iter(*self) } } impl<'q, 'a, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &'a mut T { type Iter = T::Iter; fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { ::quote_into_iter(*self) } } impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] { type Iter = slice::Iter<'q, T>; fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { (self.iter(), HasIter) } } impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec { type Iter = slice::Iter<'q, T>; fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { (self.iter(), HasIter) } } impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet { type Iter = btree_set::Iter<'q, T>; fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { (self.iter(), HasIter) } } impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp { type Iter = T::Iter; fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) { self.0.quote_into_iter() } } } // Helper type used within interpolations to allow for repeated binding names. // Implements the relevant traits, and exports a dummy `next()` method. #[derive(Copy, Clone)] #[doc(hidden)] pub struct RepInterp(pub T); impl RepInterp { // This method is intended to look like `Iterator::next`, and is called when // a name is bound multiple times, as the previous binding will shadow the // original `Iterator` object. This allows us to avoid advancing the // iterator multiple times per iteration. pub fn next(self) -> Option { Some(self.0) } } impl Iterator for RepInterp { type Item = T::Item; fn next(&mut self) -> Option { self.0.next() } } impl ToTokens for RepInterp { fn to_tokens(&self, tokens: &mut TokenStream) { self.0.to_tokens(tokens); } } #[doc(hidden)] #[inline] pub fn get_span(span: T) -> GetSpan { GetSpan(GetSpanInner(GetSpanBase(span))) } mod get_span { use core::ops::Deref; use proc_macro2::extra::DelimSpan; use proc_macro2::Span; pub struct GetSpan(pub(crate) GetSpanInner); pub struct GetSpanInner(pub(crate) GetSpanBase); pub struct GetSpanBase(pub(crate) T); impl GetSpan { #[inline] pub fn __into_span(self) -> Span { ((self.0).0).0 } } impl GetSpanInner { #[inline] pub fn __into_span(&self) -> Span { (self.0).0.join() } } impl GetSpanBase { #[allow(clippy::unused_self)] pub fn __into_span(&self) -> T { unreachable!() } } impl Deref for GetSpan { type Target = GetSpanInner; #[inline] fn deref(&self) -> &Self::Target { &self.0 } } impl Deref for GetSpanInner { type Target = GetSpanBase; #[inline] fn deref(&self) -> &Self::Target { &self.0 } } } #[doc(hidden)] pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) { tokens.append(Group::new(delimiter, inner)); } #[doc(hidden)] pub fn push_group_spanned( tokens: &mut TokenStream, span: Span, delimiter: Delimiter, inner: TokenStream, ) { let mut g = Group::new(delimiter, inner); g.set_span(span); tokens.append(g); } #[doc(hidden)] pub fn parse(tokens: &mut TokenStream, s: &str) { let s: TokenStream = s.parse().expect("invalid token stream"); tokens.extend(iter::once(s)); } #[doc(hidden)] pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) { let s: TokenStream = s.parse().expect("invalid token stream"); tokens.extend(s.into_iter().map(|t| respan_token_tree(t, span))); } // Token tree with every span replaced by the given one. fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree { match &mut token { TokenTree::Group(g) => { let stream = g .stream() .into_iter() .map(|token| respan_token_tree(token, span)) .collect(); *g = Group::new(g.delimiter(), stream); g.set_span(span); } other => other.set_span(span), } token } #[doc(hidden)] pub fn push_ident(tokens: &mut TokenStream, s: &str) { let span = Span::call_site(); push_ident_spanned(tokens, span, s); } #[doc(hidden)] pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) { tokens.append(ident_maybe_raw(s, span)); } #[doc(hidden)] pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) { struct Lifetime<'a> { name: &'a str, state: u8, } impl<'a> Iterator for Lifetime<'a> { type Item = TokenTree; fn next(&mut self) -> Option { match self.state { 0 => { self.state = 1; Some(TokenTree::Punct(Punct::new('\'', Spacing::Joint))) } 1 => { self.state = 2; Some(TokenTree::Ident(Ident::new(self.name, Span::call_site()))) } _ => None, } } } tokens.extend(Lifetime { name: &lifetime[1..], state: 0, }); } #[doc(hidden)] pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) { struct Lifetime<'a> { name: &'a str, span: Span, state: u8, } impl<'a> Iterator for Lifetime<'a> { type Item = TokenTree; fn next(&mut self) -> Option { match self.state { 0 => { self.state = 1; let mut apostrophe = Punct::new('\'', Spacing::Joint); apostrophe.set_span(self.span); Some(TokenTree::Punct(apostrophe)) } 1 => { self.state = 2; Some(TokenTree::Ident(Ident::new(self.name, self.span))) } _ => None, } } } tokens.extend(Lifetime { name: &lifetime[1..], span, state: 0, }); } macro_rules! push_punct { ($name:ident $spanned:ident $char1:tt) => { #[doc(hidden)] pub fn $name(tokens: &mut TokenStream) { tokens.append(Punct::new($char1, Spacing::Alone)); } #[doc(hidden)] pub fn $spanned(tokens: &mut TokenStream, span: Span) { let mut punct = Punct::new($char1, Spacing::Alone); punct.set_span(span); tokens.append(punct); } }; ($name:ident $spanned:ident $char1:tt $char2:tt) => { #[doc(hidden)] pub fn $name(tokens: &mut TokenStream) { tokens.append(Punct::new($char1, Spacing::Joint)); tokens.append(Punct::new($char2, Spacing::Alone)); } #[doc(hidden)] pub fn $spanned(tokens: &mut TokenStream, span: Span) { let mut punct = Punct::new($char1, Spacing::Joint); punct.set_span(span); tokens.append(punct); let mut punct = Punct::new($char2, Spacing::Alone); punct.set_span(span); tokens.append(punct); } }; ($name:ident $spanned:ident $char1:tt $char2:tt $char3:tt) => { #[doc(hidden)] pub fn $name(tokens: &mut TokenStream) { tokens.append(Punct::new($char1, Spacing::Joint)); tokens.append(Punct::new($char2, Spacing::Joint)); tokens.append(Punct::new($char3, Spacing::Alone)); } #[doc(hidden)] pub fn $spanned(tokens: &mut TokenStream, span: Span) { let mut punct = Punct::new($char1, Spacing::Joint); punct.set_span(span); tokens.append(punct); let mut punct = Punct::new($char2, Spacing::Joint); punct.set_span(span); tokens.append(punct); let mut punct = Punct::new($char3, Spacing::Alone); punct.set_span(span); tokens.append(punct); } }; } push_punct!(push_add push_add_spanned '+'); push_punct!(push_add_eq push_add_eq_spanned '+' '='); push_punct!(push_and push_and_spanned '&'); push_punct!(push_and_and push_and_and_spanned '&' '&'); push_punct!(push_and_eq push_and_eq_spanned '&' '='); push_punct!(push_at push_at_spanned '@'); push_punct!(push_bang push_bang_spanned '!'); push_punct!(push_caret push_caret_spanned '^'); push_punct!(push_caret_eq push_caret_eq_spanned '^' '='); push_punct!(push_colon push_colon_spanned ':'); push_punct!(push_colon2 push_colon2_spanned ':' ':'); push_punct!(push_comma push_comma_spanned ','); push_punct!(push_div push_div_spanned '/'); push_punct!(push_div_eq push_div_eq_spanned '/' '='); push_punct!(push_dot push_dot_spanned '.'); push_punct!(push_dot2 push_dot2_spanned '.' '.'); push_punct!(push_dot3 push_dot3_spanned '.' '.' '.'); push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '='); push_punct!(push_eq push_eq_spanned '='); push_punct!(push_eq_eq push_eq_eq_spanned '=' '='); push_punct!(push_ge push_ge_spanned '>' '='); push_punct!(push_gt push_gt_spanned '>'); push_punct!(push_le push_le_spanned '<' '='); push_punct!(push_lt push_lt_spanned '<'); push_punct!(push_mul_eq push_mul_eq_spanned '*' '='); push_punct!(push_ne push_ne_spanned '!' '='); push_punct!(push_or push_or_spanned '|'); push_punct!(push_or_eq push_or_eq_spanned '|' '='); push_punct!(push_or_or push_or_or_spanned '|' '|'); push_punct!(push_pound push_pound_spanned '#'); push_punct!(push_question push_question_spanned '?'); push_punct!(push_rarrow push_rarrow_spanned '-' '>'); push_punct!(push_larrow push_larrow_spanned '<' '-'); push_punct!(push_rem push_rem_spanned '%'); push_punct!(push_rem_eq push_rem_eq_spanned '%' '='); push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>'); push_punct!(push_semi push_semi_spanned ';'); push_punct!(push_shl push_shl_spanned '<' '<'); push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '='); push_punct!(push_shr push_shr_spanned '>' '>'); push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '='); push_punct!(push_star push_star_spanned '*'); push_punct!(push_sub push_sub_spanned '-'); push_punct!(push_sub_eq push_sub_eq_spanned '-' '='); #[doc(hidden)] pub fn push_underscore(tokens: &mut TokenStream) { push_underscore_spanned(tokens, Span::call_site()); } #[doc(hidden)] pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) { tokens.append(Ident::new("_", span)); } // Helper method for constructing identifiers from the `format_ident!` macro, // handling `r#` prefixes. #[doc(hidden)] pub fn mk_ident(id: &str, span: Option) -> Ident { let span = span.unwrap_or_else(Span::call_site); ident_maybe_raw(id, span) } fn ident_maybe_raw(id: &str, span: Span) -> Ident { if let Some(id) = id.strip_prefix("r#") { Ident::new_raw(id, span) } else { Ident::new(id, span) } } // Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!` // macro, and exposes span information from these fragments. // // This struct also has forwarding implementations of the formatting traits // `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within // `format_ident!`. #[derive(Copy, Clone)] #[doc(hidden)] pub struct IdentFragmentAdapter(pub T); impl IdentFragmentAdapter { pub fn span(&self) -> Option { self.0.span() } } impl fmt::Display for IdentFragmentAdapter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { IdentFragment::fmt(&self.0, f) } } impl fmt::Octal for IdentFragmentAdapter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Octal::fmt(&self.0, f) } } impl fmt::LowerHex for IdentFragmentAdapter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } impl fmt::UpperHex for IdentFragmentAdapter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) } } impl fmt::Binary for IdentFragmentAdapter { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Binary::fmt(&self.0, f) } } quote/src/to_tokens.rs0000644000175000017500000001251614661133735016045 0ustar jamespagejamespageuse super::TokenStreamExt; use alloc::borrow::Cow; use alloc::rc::Rc; use core::iter; use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree}; /// Types that can be interpolated inside a `quote!` invocation. /// /// [`quote!`]: macro.quote.html pub trait ToTokens { /// Write `self` to the given `TokenStream`. /// /// The token append methods provided by the [`TokenStreamExt`] extension /// trait may be useful for implementing `ToTokens`. /// /// [`TokenStreamExt`]: trait.TokenStreamExt.html /// /// # Example /// /// Example implementation for a struct representing Rust paths like /// `std::cmp::PartialEq`: /// /// ``` /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream}; /// use quote::{TokenStreamExt, ToTokens}; /// /// pub struct Path { /// pub global: bool, /// pub segments: Vec, /// } /// /// impl ToTokens for Path { /// fn to_tokens(&self, tokens: &mut TokenStream) { /// for (i, segment) in self.segments.iter().enumerate() { /// if i > 0 || self.global { /// // Double colon `::` /// tokens.append(Punct::new(':', Spacing::Joint)); /// tokens.append(Punct::new(':', Spacing::Alone)); /// } /// segment.to_tokens(tokens); /// } /// } /// } /// # /// # pub struct PathSegment; /// # /// # impl ToTokens for PathSegment { /// # fn to_tokens(&self, tokens: &mut TokenStream) { /// # unimplemented!() /// # } /// # } /// ``` fn to_tokens(&self, tokens: &mut TokenStream); /// Convert `self` directly into a `TokenStream` object. /// /// This method is implicitly implemented using `to_tokens`, and acts as a /// convenience method for consumers of the `ToTokens` trait. fn to_token_stream(&self) -> TokenStream { let mut tokens = TokenStream::new(); self.to_tokens(&mut tokens); tokens } /// Convert `self` directly into a `TokenStream` object. /// /// This method is implicitly implemented using `to_tokens`, and acts as a /// convenience method for consumers of the `ToTokens` trait. fn into_token_stream(self) -> TokenStream where Self: Sized, { self.to_token_stream() } } impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens); } } impl<'a, T: ?Sized + ToTokens> ToTokens for &'a mut T { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens); } } impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens); } } impl ToTokens for Box { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens); } } impl ToTokens for Rc { fn to_tokens(&self, tokens: &mut TokenStream) { (**self).to_tokens(tokens); } } impl ToTokens for Option { fn to_tokens(&self, tokens: &mut TokenStream) { if let Some(ref t) = *self { t.to_tokens(tokens); } } } impl ToTokens for str { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(Literal::string(self)); } } impl ToTokens for String { fn to_tokens(&self, tokens: &mut TokenStream) { self.as_str().to_tokens(tokens); } } macro_rules! primitive { ($($t:ident => $name:ident)*) => { $( impl ToTokens for $t { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(Literal::$name(*self)); } } )* }; } primitive! { i8 => i8_suffixed i16 => i16_suffixed i32 => i32_suffixed i64 => i64_suffixed i128 => i128_suffixed isize => isize_suffixed u8 => u8_suffixed u16 => u16_suffixed u32 => u32_suffixed u64 => u64_suffixed u128 => u128_suffixed usize => usize_suffixed f32 => f32_suffixed f64 => f64_suffixed } impl ToTokens for char { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(Literal::character(*self)); } } impl ToTokens for bool { fn to_tokens(&self, tokens: &mut TokenStream) { let word = if *self { "true" } else { "false" }; tokens.append(Ident::new(word, Span::call_site())); } } impl ToTokens for Group { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(self.clone()); } } impl ToTokens for Ident { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(self.clone()); } } impl ToTokens for Punct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(self.clone()); } } impl ToTokens for Literal { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(self.clone()); } } impl ToTokens for TokenTree { fn to_tokens(&self, dst: &mut TokenStream) { dst.append(self.clone()); } } impl ToTokens for TokenStream { fn to_tokens(&self, dst: &mut TokenStream) { dst.extend(iter::once(self.clone())); } fn into_token_stream(self) -> TokenStream { self } } quote/rust-toolchain.toml0000644000175000017500000000004614661133735016546 0ustar jamespagejamespage[toolchain] components = ["rust-src"] quote/.cargo-checksum.json0000664000175000017500000000527014661133735016550 0ustar jamespagejamespage{"files":{"Cargo.toml":"0a98ab1241e7b64caa29c6ff868e2e96e0f74c1ef8b265727f1863a960fa322c","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"626e7079eab0baacf0fcaf3e244f407b2014ebaeca45905d72e8fb8bed18aaea","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/ext.rs":"9881576cac3e476a4bf04f9b601cf9a53b79399fb0ca9634e8b861ac91709843","src/format.rs":"c595015418f35e6992e710441b9999f09b2afe4678b138039d670d100c0bdd86","src/ident_fragment.rs":"0b3e6c2129e55910fd2d240e1e7efba6f1796801d24352d1c0bfbceb0e8b678f","src/lib.rs":"abbc178821e46d0bcd224904a7542ac4582d189f57cd4daf02a54fd772e52a55","src/runtime.rs":"7f37326edaeac2c42ed806b447eeba12e36dd4b1bc25fbf52f8eb23140f3be7a","src/spanned.rs":"3ccf5120593f35787442c0a37d243e802c5262e7f8b35aed503873008ec035c5","src/to_tokens.rs":"1c76311fcc82098e630056d71fd6f3929194ee31b0840e2aa643ed7e78026e3e","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test.rs":"3be80741f84a707376c230d9cf70ce9537caa359691d8d4c34968e28175e4ad7","tests/ui/does-not-have-iter-interpolated-dup.rs":"ad13eea21d4cdd2ab6c082f633392e1ff20fb0d1af5f2177041e0bf7f30da695","tests/ui/does-not-have-iter-interpolated-dup.stderr":"90a4bdb9267535f5d2785940148338d6b7d905548051d2c9c5dcbd58f2c11d8e","tests/ui/does-not-have-iter-interpolated.rs":"83a5b3f240651adcbe4b6e51076d76d653ad439b37442cf4054f1fd3c073f3b7","tests/ui/does-not-have-iter-interpolated.stderr":"ae7c2739554c862b331705e82781aa4687a4375210cef6ae899a4be4a4ec2d97","tests/ui/does-not-have-iter-separated.rs":"fe413c48331d5e3a7ae5fef6a5892a90c72f610d54595879eb49d0a94154ba3f","tests/ui/does-not-have-iter-separated.stderr":"03fd560979ebcd5aa6f83858bc2c3c01ba6546c16335101275505304895c1ae9","tests/ui/does-not-have-iter.rs":"09dc9499d861b63cebb0848b855b78e2dc9497bfde37ba6339f3625ae009a62f","tests/ui/does-not-have-iter.stderr":"d6da483c29e232ced72059bbdf05d31afb1df9e02954edaa9cfaea1ec6df72dc","tests/ui/not-quotable.rs":"5759d0884943417609f28faadc70254a3e2fd3d9bd6ff7297a3fb70a77fafd8a","tests/ui/not-quotable.stderr":"1b5ad13712a35f2f25a159c003956762941b111d540b20ad6a258cdb079a9c95","tests/ui/not-repeatable.rs":"a4b115c04e4e41049a05f5b69450503fbffeba031218b4189cb931839f7f9a9c","tests/ui/not-repeatable.stderr":"bbfb702638374001061251f81d63476851ac28ed743f13db9d65e30dd9bdcf52","tests/ui/wrong-type-span.rs":"6195e35ea844c0c52ba1cff5d790c3a371af6915d137d377834ad984229ef9ea","tests/ui/wrong-type-span.stderr":"cad072e40e0ecc04f375122ae41aede2f0da2a9244492b3fcf70249e59d1b128"},"package":"0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"}rpds/0000775000175000017500000000000014661133735012513 5ustar jamespagejamespagerpds/README.md0000644000175000017500000002343614661133735014000 0ustar jamespagejamespage[![Build Status](https://github.com/orium/rpds/workflows/CI/badge.svg)](https://github.com/orium/rpds/actions?query=workflow%3ACI) [![Code Coverage](https://codecov.io/gh/orium/rpds/branch/main/graph/badge.svg)](https://codecov.io/gh/orium/rpds) [![Dependency status](https://deps.rs/repo/github/orium/rpds/status.svg)](https://deps.rs/repo/github/orium/rpds) [![crates.io](https://img.shields.io/crates/v/rpds.svg)](https://crates.io/crates/rpds) [![Downloads](https://img.shields.io/crates/d/rpds.svg)](https://crates.io/crates/rpds) [![Github stars](https://img.shields.io/github/stars/orium/rpds.svg?logo=github)](https://github.com/orium/rpds/stargazers) [![Documentation](https://docs.rs/rpds/badge.svg)](https://docs.rs/rpds/) [![License](https://img.shields.io/crates/l/rpds.svg)](./LICENSE.md) # Rust Persistent Data Structures Rust Persistent Data Structures provides [fully persistent data structures](https://en.wikipedia.org/wiki/Persistent_data_structure) with structural sharing. ## Setup To use rpds add the following to your `Cargo.toml`: ```toml [dependencies] rpds = "" ``` ## Data structures This crate offers the following data structures: 1. [`List`](#list) 2. [`Vector`](#vector) 3. [`Stack`](#stack) 4. [`Queue`](#queue) 5. [`HashTrieMap`](#hashtriemap) 6. [`HashTrieSet`](#hashtrieset) 7. [`RedBlackTreeMap`](#redblacktreemap) 8. [`RedBlackTreeSet`](#redblacktreeset) ### `List` [![List documentation](https://img.shields.io/badge/doc-List-303070.svg)](https://docs.rs/rpds/latest/rpds/list/struct.List.html) Your classic functional list. #### Example ```rust use rpds::List; let list = List::new().push_front("list"); assert_eq!(list.first(), Some(&"list")); let a_list = list.push_front("a"); assert_eq!(a_list.first(), Some(&"a")); let list_dropped = a_list.drop_first().unwrap(); assert_eq!(list_dropped, list); ``` ### `Vector` [![`Vector` documentation](https://img.shields.io/badge/doc-Vector-303070.svg)](https://docs.rs/rpds/latest/rpds/vector/struct.Vector.html) A sequence that can be indexed. The implementation is described in [Understanding Persistent Vector Part 1](http://hypirion.com/musings/understanding-persistent-vector-pt-1) and [Understanding Persistent Vector Part 2](http://hypirion.com/musings/understanding-persistent-vector-pt-2). #### Example ```rust use rpds::Vector; let vector = Vector::new() .push_back("I’m") .push_back("a") .push_back("vector"); assert_eq!(vector[1], "a"); let screaming_vector = vector .drop_last().unwrap() .push_back("VECTOR!!!"); assert_eq!(screaming_vector[2], "VECTOR!!!"); ``` ### `Stack` [![`Stack` documentation](https://img.shields.io/badge/doc-Stack-303070.svg)](https://docs.rs/rpds/latest/rpds/stack/struct.Stack.html) A LIFO (last in, first out) data structure. This is just a [`List`](#list) in disguise. #### Example ```rust use rpds::Stack; let stack = Stack::new().push("stack"); assert_eq!(stack.peek(), Some(&"stack")); let a_stack = stack.push("a"); assert_eq!(a_stack.peek(), Some(&"a")); let stack_popped = a_stack.pop().unwrap(); assert_eq!(stack_popped, stack); ``` ### `Queue` [![`Queue` documentation](https://img.shields.io/badge/doc-Queue-303070.svg)](https://docs.rs/rpds/latest/rpds/queue/struct.Queue.html) A FIFO (first in, first out) data structure. #### Example ```rust use rpds::Queue; let queue = Queue::new() .enqueue("um") .enqueue("dois") .enqueue("tres"); assert_eq!(queue.peek(), Some(&"um")); let queue_dequeued = queue.dequeue().unwrap(); assert_eq!(queue_dequeued.peek(), Some(&"dois")); ``` ### `HashTrieMap` [![`HashTrieMap` documentation](https://img.shields.io/badge/doc-HashTrieMap-303070.svg)](https://docs.rs/rpds/latest/rpds/map/hash_trie_map/struct.HashTrieMap.html) A map implemented with a [hash array mapped trie](https://en.wikipedia.org/wiki/Hash_array_mapped_trie). See [Ideal Hash Trees](https://infoscience.epfl.ch/record/64398/files/idealhashtrees.pdf) for details. #### Example ```rust use rpds::HashTrieMap; let map_en = HashTrieMap::new() .insert(0, "zero") .insert(1, "one"); assert_eq!(map_en.get(&1), Some(&"one")); let map_pt = map_en .insert(1, "um") .insert(2, "dois"); assert_eq!(map_pt.get(&2), Some(&"dois")); let map_pt_binary = map_pt.remove(&2); assert_eq!(map_pt_binary.get(&2), None); ``` ### `HashTrieSet` [![`HashTrieSet` documentation](https://img.shields.io/badge/doc-HashTrieSet-303070.svg)](https://docs.rs/rpds/latest/rpds/set/hash_trie_set/struct.HashTrieSet.html) A set implemented with a [`HashTrieMap`](#hashtriemap). #### Example ```rust use rpds::HashTrieSet; let set = HashTrieSet::new() .insert("zero") .insert("one"); assert!(set.contains(&"one")); let set_extended = set.insert("two"); assert!(set_extended.contains(&"two")); let set_positive = set_extended.remove(&"zero"); assert!(!set_positive.contains(&"zero")); ``` ### `RedBlackTreeMap` [![`RedBlackTreeMap` documentation](https://img.shields.io/badge/doc-RedBlackTreeMap-303070.svg)](https://docs.rs/rpds/latest/rpds/map/red_black_tree_map/struct.RedBlackTreeMap.html) A map implemented with a [red-black tree](https://en.wikipedia.org/wiki/Red-Black_tree). #### Example ```rust use rpds::RedBlackTreeMap; let map_en = RedBlackTreeMap::new() .insert(0, "zero") .insert(1, "one"); assert_eq!(map_en.get(&1), Some(&"one")); let map_pt = map_en .insert(1, "um") .insert(2, "dois"); assert_eq!(map_pt.get(&2), Some(&"dois")); let map_pt_binary = map_pt.remove(&2); assert_eq!(map_pt_binary.get(&2), None); assert_eq!(map_pt_binary.first(), Some((&0, &"zero"))); ``` ### `RedBlackTreeSet` [![`RedBlackTreeSet` documentation](https://img.shields.io/badge/doc-RedBlackTreeSet-303070.svg)](https://docs.rs/rpds/latest/rpds/set/red_black_tree_set/struct.RedBlackTreeSet.html) A set implemented with a [`RedBlackTreeMap`](#redblacktreemap). #### Example ```rust use rpds::RedBlackTreeSet; let set = RedBlackTreeSet::new() .insert("zero") .insert("one"); assert!(set.contains(&"one")); let set_extended = set.insert("two"); assert!(set_extended.contains(&"two")); let set_positive = set_extended.remove(&"zero"); assert!(!set_positive.contains(&"zero")); assert_eq!(set_positive.first(), Some(&"one")); ``` ## Other features ### Mutable methods When you change a data structure you often do not need its previous versions. For those cases rpds offers you mutable methods which are generally faster: ```rust use rpds::HashTrieSet; let mut set = HashTrieSet::new(); set.insert_mut("zero"); set.insert_mut("one"); let set_0_1 = set.clone(); let set_0_1_2 = set.insert("two"); ``` ### Initialization macros There are convenient initialization macros for all data structures: ```rust use rpds::*; let vector = vector![3, 1, 4, 1, 5]; let map = ht_map!["orange" => "orange", "banana" => "yellow"]; ``` Check the documentation for initialization macros of other data structures. ### Thread safety All data structures in this crate can be shared between threads, but that is an opt-in ability. This is because there is a performance cost to make data structures thread safe. That cost is worth avoiding when you are not actually sharing them between threads. Of course if you try to share a rpds data structure across different threads you can count on the rust compiler to ensure that it is safe to do so. If you are using the version of the data structure that is not thread safe you will get a compile-time error. To create a thread-safe version of any data structure use `new_sync()`: ```rust let vec = Vector::new_sync() .push_back(42); ``` Or use the `_sync` variant of the initialization macro: ```rust let vec = vector_sync!(42); ``` #### Further details Internally the data structures in this crate maintain a lot of reference-counting pointers. These pointers are used both for links between the internal nodes of the data structure as well as for the values it stores. There are two implementations of reference-counting pointers in the standard library: [`Rc`](https://doc.rust-lang.org/stable/alloc/rc/struct.Rc.html) and [`Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html). They behave the same way, but `Arc` allows you to share the data it points to across multiple threads. The downside is that it is significantly slower to clone and drop than `Rc`, and persistent data structures do a lot of those operations. In some microbenchmarks with rpds data structure we can see that using `Rc` instead of `Arc` can make some operations twice as fast! You can see this for yourself by running `cargo bench`. To implement this we parameterize the type of reference-counting pointer (`Rc` or `Arc`) as a type argument of the data structure. We use the [archery](https://github.com/orium/archery/) crate to do this in a convenient way. The pointer type can be parameterized like this: ```rust let vec: Vector = Vector::new_with_ptr_kind(); // ↖ // This will use `Arc` pointers. // Change it to `archery::RcK` to use a `Rc` pointer. ``` ### `no_std` support This crate supports `no_std`. To enable that you need to disable the default feature `std`: ```toml [dependencies] rpds = { version = "", default-features = false } ``` ### Serialization We support serialization through [serde](https://crates.io/crates/serde). To use it enable the `serde` feature. To do so change the rpds dependency in your `Cargo.toml` to ```toml [dependencies] rpds = { version = "", features = ["serde"] } ``` ### Bindings Bindings to use rpds from other programming languages exist. Below is a short list of those known to date. * [rpds.py](https://github.com/crate-py/rpds/) – Python Please feel free to send a pull request should you add support in a new language. rpds/Cargo.toml0000644000175000017500000000466314661133735014452 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.60.0" name = "rpds" version = "1.1.0" authors = ["Diogo Sousa "] include = [ "/src/**/*.rs", "/benches/**/*.rs", "/Cargo.toml", "/LICENSE.md", "/README.md", "/release-notes.md", ] description = "Persistent data structures with structural sharing" homepage = "https://github.com/orium/rpds" documentation = "https://docs.rs/rpds" readme = "README.md" keywords = [ "data-structure", "data-structures", "persistent", "immutable", "no_std", ] categories = ["data-structures"] license = "MPL-2.0" repository = "https://github.com/orium/rpds" [package.metadata.docs.rs] features = ["serde"] [[bench]] name = "std_linked_list" harness = false [[bench]] name = "rpds_list" harness = false [[bench]] name = "rpds_list_sync" harness = false [[bench]] name = "std_vec" harness = false [[bench]] name = "rpds_queue" harness = false [[bench]] name = "rpds_queue_sync" harness = false [[bench]] name = "std_vec_deque" harness = false [[bench]] name = "rpds_vector" harness = false [[bench]] name = "rpds_vector_sync" harness = false [[bench]] name = "std_hash_map" harness = false [[bench]] name = "rpds_hash_trie_map" harness = false [[bench]] name = "rpds_hash_trie_map_sync" harness = false [[bench]] name = "std_btree_map" harness = false [[bench]] name = "rpds_red_black_tree_map" harness = false [[bench]] name = "rpds_red_black_tree_map_sync" harness = false [dependencies.archery] version = "1.1.0" features = ["triomphe"] [dependencies.serde] version = "1.0.149" optional = true default-features = false [dev-dependencies.bincode] version = "1.3.3" [dev-dependencies.criterion] version = "0.5.1" [dev-dependencies.pretty_assertions] version = "1.3.0" [dev-dependencies.rand] version = "0.8.5" [dev-dependencies.static_assertions] version = "1.1.0" [features] default = ["std"] fatal-warnings = [] std = [] [badges.codecov] branch = "main" repository = "orium/rpds" service = "github" rpds/benches/0000775000175000017500000000000014661133735014122 5ustar jamespagejamespagerpds/benches/rpds_red_black_tree_map.rs0000644000175000017500000000633114661133735021303 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::RedBlackTreeMap; use std::hint::black_box; fn rpds_red_black_tree_map_insert(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map insert", move |b| { b.iter(|| { let mut map = RedBlackTreeMap::new(); for i in 0..limit { map = map.insert(i, -(i as isize)); } map }) }); } fn rpds_red_black_tree_map_insert_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map insert mut", move |b| { b.iter(|| { let mut map = RedBlackTreeMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }) }); } fn rpds_red_black_tree_map_remove(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map remove", move |b| { b.iter_with_setup( || { let mut map = RedBlackTreeMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map = map.remove(&i); } map }, ); }); } fn rpds_red_black_tree_map_remove_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map remove mut", move |b| { b.iter_with_setup( || { let mut map = RedBlackTreeMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map.remove_mut(&i); } map }, ); }); } fn rpds_red_black_tree_map_get(c: &mut Criterion) { let limit = 100_000; let mut map = RedBlackTreeMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds red black tree map get", move |b| { b.iter(|| { for i in 0..limit { black_box(map.get(&i)); } }) }); } fn rpds_red_black_tree_map_iterate(c: &mut Criterion) { let limit = 100_000; let mut map = RedBlackTreeMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds red black tree map iterate", move |b| { b.iter(|| { for kv in map.iter() { black_box(kv); } }) }); } criterion_group!( benches, rpds_red_black_tree_map_insert, rpds_red_black_tree_map_insert_mut, rpds_red_black_tree_map_remove, rpds_red_black_tree_map_remove_mut, rpds_red_black_tree_map_get, rpds_red_black_tree_map_iterate ); criterion_main!(benches); rpds/benches/rpds_queue.rs0000644000175000017500000000517014661133735016645 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::Queue; use std::hint::black_box; fn rpds_queue_enqueue(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue enqueue", move |b| { b.iter(|| { let mut queue: Queue = Queue::new(); for i in 0..limit { queue = queue.enqueue(i); } queue }) }); } fn rpds_queue_enqueue_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue enqueue mut", move |b| { b.iter(|| { let mut queue: Queue = Queue::new(); for i in 0..limit { queue.enqueue_mut(i); } queue }) }); } fn rpds_queue_dequeue(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue dequeue", move |b| { b.iter_with_setup( || { let mut queue: Queue = Queue::new(); for i in 0..limit { queue.enqueue_mut(i); } queue }, |mut queue| { for _ in 0..limit { queue = queue.dequeue().unwrap(); } queue }, ); }); } fn rpds_queue_dequeue_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue dequeue mut", move |b| { b.iter_with_setup( || { let mut queue: Queue = Queue::new(); for i in 0..limit { queue.enqueue_mut(i); } queue }, |mut queue| { for _ in 0..limit { queue.dequeue_mut(); } queue }, ); }); } fn rpds_queue_iterate(c: &mut Criterion) { let limit = 100_000; let mut queue: Queue = Queue::new(); for i in 0..limit { queue.enqueue_mut(i); } c.bench_function("rpds queue iterate", move |b| { b.iter(|| { for i in queue.iter() { black_box(i); } }) }); } criterion_group!( benches, rpds_queue_enqueue, rpds_queue_enqueue_mut, rpds_queue_dequeue, rpds_queue_dequeue_mut, rpds_queue_iterate ); criterion_main!(benches); rpds/benches/rpds_hash_trie_map.rs0000644000175000017500000000614114661133735020323 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::HashTrieMap; use std::hint::black_box; fn rpds_hash_trie_map_insert(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds hash trie map insert", move |b| { b.iter(|| { let mut map = HashTrieMap::new(); for i in 0..limit { map = map.insert(i, -(i as isize)); } map }) }); } fn rpds_hash_trie_map_insert_mut(c: &mut Criterion) { let limit = 50_000; c.bench_function("rpds hash trie map insert mut", move |b| { b.iter(|| { let mut map = HashTrieMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }) }); } fn rpds_hash_trie_map_remove(c: &mut Criterion) { let limit = 50_000; c.bench_function("rpds hash trie map remove", move |b| { b.iter_with_setup( || { let mut map = HashTrieMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map = map.remove(&i); } map }, ); }); } fn rpds_hash_trie_map_remove_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds hash trie map remove mut", move |b| { b.iter_with_setup( || { let mut map = HashTrieMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map.remove_mut(&i); } map }, ); }); } fn rpds_hash_trie_map_get(c: &mut Criterion) { let limit = 100_000; let mut map = HashTrieMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds hash trie map get", move |b| { b.iter(|| { for i in 0..limit { black_box(map.get(&i)); } }) }); } fn rpds_hash_trie_map_iterate(c: &mut Criterion) { let limit = 100_000; let mut map = HashTrieMap::new(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds hash trie map iterate", move |b| { b.iter(|| { for kv in map.iter() { black_box(kv); } }) }); } criterion_group!( benches, rpds_hash_trie_map_insert, rpds_hash_trie_map_insert_mut, rpds_hash_trie_map_remove, rpds_hash_trie_map_remove_mut, rpds_hash_trie_map_get, rpds_hash_trie_map_iterate ); criterion_main!(benches); rpds/benches/std_hash_map.rs0000644000175000017500000000415114661133735017121 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use std::collections::HashMap; use std::hint::black_box; fn std_hash_map_insert(c: &mut Criterion) { let limit = 100_000; c.bench_function("std hash map insert", move |b| { b.iter(|| { let mut map: HashMap = HashMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } map }) }); } fn std_hash_map_remove(c: &mut Criterion) { let limit = 100_000; c.bench_function("std hash map remove", move |b| { b.iter_with_setup( || { let mut map = HashMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map.remove(&i); } map }, ); }); } fn std_hash_map_get(c: &mut Criterion) { let limit = 100_000; let mut map: HashMap = HashMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } c.bench_function("std hash map get", move |b| { b.iter(|| { for i in 0..limit { black_box(map.get(&i)); } }) }); } fn std_hash_map_iterate(c: &mut Criterion) { let limit = 100_000; let mut map: HashMap = HashMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } c.bench_function("std hash map iterate", move |b| { b.iter(|| { for kv in &map { black_box(kv); } }) }); } criterion_group!( benches, std_hash_map_insert, std_hash_map_remove, std_hash_map_get, std_hash_map_iterate ); criterion_main!(benches); rpds/benches/std_vec_deque.rs0000644000175000017500000000341514661133735017303 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use std::collections::VecDeque; use std::hint::black_box; fn std_vec_dequeue_push_back(c: &mut Criterion) { let limit = 100_000; c.bench_function("std vec dequeue push back", move |b| { b.iter(|| { let mut deque: VecDeque = VecDeque::new(); for i in 0..limit { deque.push_back(i); } deque }) }); } fn std_vec_dequeue_pop_front(c: &mut Criterion) { let limit = 100_000; c.bench_function("std vec dequeue pop front", move |b| { b.iter_with_setup( || { let mut queue: VecDeque = VecDeque::new(); for i in 0..limit { queue.push_back(i); } queue }, |mut queue| { for _ in 0..limit { queue.pop_front(); } queue }, ); }); } fn std_vec_dequeue_iterate(c: &mut Criterion) { let limit = 100_000; let mut deque: VecDeque = VecDeque::new(); for i in 0..limit { deque.push_back(i); } c.bench_function("std vec dequeue iterate", move |b| { b.iter(|| { for i in deque.iter() { black_box(i); } }) }); } criterion_group!( benches, std_vec_dequeue_push_back, std_vec_dequeue_pop_front, std_vec_dequeue_iterate ); criterion_main!(benches); rpds/benches/rpds_queue_sync.rs0000644000175000017500000000541214661133735017700 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::QueueSync; use std::hint::black_box; fn rpds_queue_sync_enqueue(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue sync enqueue", move |b| { b.iter(|| { let mut queue: QueueSync = QueueSync::new_sync(); for i in 0..limit { queue = queue.enqueue(i); } queue }) }); } fn rpds_queue_sync_enqueue_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue sync enqueue mut", move |b| { b.iter(|| { let mut queue: QueueSync = QueueSync::new_sync(); for i in 0..limit { queue.enqueue_mut(i); } queue }) }); } fn rpds_queue_sync_dequeue(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue sync dequeue", move |b| { b.iter_with_setup( || { let mut queue: QueueSync = QueueSync::new_sync(); for i in 0..limit { queue.enqueue_mut(i); } queue }, |mut queue| { for _ in 0..limit { queue = queue.dequeue().unwrap(); } queue }, ); }); } fn rpds_queue_sync_dequeue_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds queue sync dequeue mut", move |b| { b.iter_with_setup( || { let mut queue: QueueSync = QueueSync::new_sync(); for i in 0..limit { queue.enqueue_mut(i); } queue }, |mut queue| { for _ in 0..limit { queue.dequeue_mut(); } queue }, ); }); } fn rpds_queue_sync_iterate(c: &mut Criterion) { let limit = 1_000_000; let mut queue: QueueSync = QueueSync::new_sync(); for i in 0..limit { queue.enqueue_mut(i); } c.bench_function("rpds queue sync iterate", move |b| { b.iter(|| { for i in queue.iter() { black_box(i); } }) }); } criterion_group!( benches, rpds_queue_sync_enqueue, rpds_queue_sync_enqueue_mut, rpds_queue_sync_dequeue, rpds_queue_sync_dequeue_mut, rpds_queue_sync_iterate ); criterion_main!(benches); rpds/benches/rpds_vector_sync.rs0000644000175000017500000000636214661133735020063 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::VectorSync; use std::hint::black_box; fn rpds_vector_syncpush_back(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector sync push back", move |b| { b.iter(|| { let mut vector: VectorSync = VectorSync::new_sync(); for i in 0..limit { vector = vector.push_back(i); } vector }) }); } fn rpds_vector_syncpush_back_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector sync push back mut", move |b| { b.iter(|| { let mut vector: VectorSync = VectorSync::new_sync(); for i in 0..limit { vector.push_back_mut(i); } vector }) }); } fn rpds_vector_syncdrop_last(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector sync drop last", move |b| { b.iter_with_setup( || { let mut vector: VectorSync = VectorSync::new_sync(); for i in 0..limit { vector.push_back_mut(i); } vector }, |mut vector| { for _ in 0..limit { vector = vector.drop_last().unwrap(); } vector }, ); }); } fn rpds_vector_syncdrop_last_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector sync drop last mut", move |b| { b.iter_with_setup( || { let mut vector: VectorSync = VectorSync::new_sync(); for i in 0..limit { vector.push_back_mut(i); } vector }, |mut vector| { for _ in 0..limit { vector.drop_last_mut(); } vector }, ); }); } fn rpds_vector_syncget(c: &mut Criterion) { let limit = 1_000_000; let mut vector: VectorSync = VectorSync::new_sync(); for i in 0..limit { vector.push_back_mut(i); } c.bench_function("rpds vector sync get", move |b| { b.iter(|| { for i in 0..limit { black_box(vector.get(i)); } }) }); } fn rpds_vector_synciterate(c: &mut Criterion) { let limit = 1_000_000; let mut vector: VectorSync = VectorSync::new_sync(); for i in 0..limit { vector.push_back_mut(i); } c.bench_function("rpds vector sync iterate", move |b| { b.iter(|| { for i in vector.iter() { black_box(i); } }) }); } criterion_group!( benches, rpds_vector_syncpush_back, rpds_vector_syncpush_back_mut, rpds_vector_syncdrop_last, rpds_vector_syncdrop_last_mut, rpds_vector_syncget, rpds_vector_synciterate ); criterion_main!(benches); rpds/benches/std_btree_map.rs0000644000175000017500000000420014661133735017272 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use std::collections::BTreeMap; use std::hint::black_box; fn std_btree_map_insert(c: &mut Criterion) { let limit = 100_000; c.bench_function("std b-tree map insert", move |b| { b.iter(|| { let mut map: BTreeMap = BTreeMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } map }) }); } fn std_btree_map_remove(c: &mut Criterion) { let limit = 100_000; c.bench_function("std btree map remove", move |b| { b.iter_with_setup( || { let mut map = BTreeMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map.remove(&i); } map }, ); }); } fn std_btree_map_get(c: &mut Criterion) { let limit = 100_000; let mut map: BTreeMap = BTreeMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } c.bench_function("std b-tree map get", move |b| { b.iter(|| { for i in 0..limit { black_box(map.get(&i)); } }) }); } fn std_btree_map_iterate(c: &mut Criterion) { let limit = 100_000; let mut map: BTreeMap = BTreeMap::new(); for i in 0..limit { map.insert(i, -(i as isize)); } c.bench_function("std b-tree map iterate", move |b| { b.iter(|| { for kv in &map { black_box(kv); } }) }); } criterion_group!( benches, std_btree_map_insert, std_btree_map_remove, std_btree_map_get, std_btree_map_iterate ); criterion_main!(benches); rpds/benches/std_vec.rs0000644000175000017500000000470514661133735016123 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use std::hint::black_box; fn std_vec_push(c: &mut Criterion) { let limit = 100_000; c.bench_function("std vec push", move |b| { b.iter(|| { let mut vector: Vec = Vec::new(); for i in 0..limit { vector.push(i); } vector }) }); } fn std_vec_pop(c: &mut Criterion) { let limit = 100_000; c.bench_function("std vec pop", move |b| { b.iter_with_setup( || { let mut vector: Vec = Vec::new(); for i in 0..limit { vector.push(i); } vector }, |mut vector| { for _ in 0..limit { vector.pop(); } vector }, ); }); } fn std_vec_reverse(c: &mut Criterion) { let limit = 10_000; c.bench_function("std vec reverse", move |b| { b.iter_with_setup( || { let mut vector: Vec = Vec::new(); for i in 0..limit { vector.push(i); } vector }, |mut vector| { for _ in 0..limit { vector.reverse(); } vector }, ); }); } fn std_vec_get(c: &mut Criterion) { let limit = 100_000; let mut vector: Vec = Vec::new(); for i in 0..limit { vector.push(i); } c.bench_function("std vec get", move |b| { b.iter(|| { for i in 0..limit { black_box(vector.get(i)); } }) }); } fn std_vec_iterate(c: &mut Criterion) { let limit = 100_000; let mut vector: Vec = Vec::new(); for i in 0..limit { vector.push(i); } c.bench_function("std vec iterate", move |b| { b.iter(|| { for i in &vector { black_box(i); } }) }); } criterion_group!(benches, std_vec_push, std_vec_pop, std_vec_reverse, std_vec_get, std_vec_iterate); criterion_main!(benches); rpds/benches/rpds_red_black_tree_map_sync.rs0000644000175000017500000000655714661133735022351 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::RedBlackTreeMapSync; use std::hint::black_box; fn rpds_red_black_tree_map_sync_insert(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map sync insert", move |b| { b.iter(|| { let mut map = RedBlackTreeMapSync::new_sync(); for i in 0..limit { map = map.insert(i, -(i as isize)); } map }) }); } fn rpds_red_black_tree_map_sync_insert_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map sync insert mut", move |b| { b.iter(|| { let mut map = RedBlackTreeMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }) }); } fn rpds_red_black_tree_map_sync_remove(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map sync remove", move |b| { b.iter_with_setup( || { let mut map = RedBlackTreeMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map = map.remove(&i); } map }, ); }); } fn rpds_red_black_tree_map_sync_remove_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds red black tree map sync remove mut", move |b| { b.iter_with_setup( || { let mut map = RedBlackTreeMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map.remove_mut(&i); } map }, ); }); } fn rpds_red_black_tree_map_sync_get(c: &mut Criterion) { let limit = 100_000; let mut map = RedBlackTreeMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds red black tree map sync get", move |b| { b.iter(|| { for i in 0..limit { black_box(map.get(&i)); } }) }); } fn rpds_red_black_tree_map_sync_iterate(c: &mut Criterion) { let limit = 1_000_000; let mut map = RedBlackTreeMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds red black tree map sync iterate", move |b| { b.iter(|| { for kv in map.iter() { black_box(kv); } }) }); } criterion_group!( benches, rpds_red_black_tree_map_sync_insert, rpds_red_black_tree_map_sync_insert_mut, rpds_red_black_tree_map_sync_remove, rpds_red_black_tree_map_sync_remove_mut, rpds_red_black_tree_map_sync_get, rpds_red_black_tree_map_sync_iterate ); criterion_main!(benches); rpds/benches/rpds_hash_trie_map_sync.rs0000644000175000017500000000637114661133735021364 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::HashTrieMapSync; use std::hint::black_box; fn rpds_hash_trie_map_sync_insert(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds hash trie map sync insert", move |b| { b.iter(|| { let mut map = HashTrieMapSync::new_sync(); for i in 0..limit { map = map.insert(i, -(i as isize)); } map }) }); } fn rpds_hash_trie_map_sync_insert_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds hash trie map sync insert mut", move |b| { b.iter(|| { let mut map = HashTrieMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }) }); } fn rpds_hash_trie_map_sync_remove(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds hash trie map sync remove", move |b| { b.iter_with_setup( || { let mut map = HashTrieMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map = map.remove(&i); } map }, ); }); } fn rpds_hash_trie_map_sync_remove_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds hash trie map sync remove mut", move |b| { b.iter_with_setup( || { let mut map = HashTrieMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } map }, |mut map| { for i in 0..limit { map.remove_mut(&i); } map }, ); }); } fn rpds_hash_trie_map_sync_get(c: &mut Criterion) { let limit = 100_000; let mut map = HashTrieMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds hash trie map sync get", move |b| { b.iter(|| { for i in 0..limit { black_box(map.get(&i)); } }) }); } fn rpds_hash_trie_map_sync_iterate(c: &mut Criterion) { let limit = 1_000_000; let mut map = HashTrieMapSync::new_sync(); for i in 0..limit { map.insert_mut(i, -(i as isize)); } c.bench_function("rpds hash trie map sync iterate", move |b| { b.iter(|| { for kv in map.iter() { black_box(kv); } }) }); } criterion_group!( benches, rpds_hash_trie_map_sync_insert, rpds_hash_trie_map_sync_insert_mut, rpds_hash_trie_map_sync_remove, rpds_hash_trie_map_sync_remove_mut, rpds_hash_trie_map_sync_get, rpds_hash_trie_map_sync_iterate ); criterion_main!(benches); rpds/benches/rpds_list_sync.rs0000644000175000017500000000766314661133735017541 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::ListSync; use std::hint::black_box; fn rpds_list_sync_push_front(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list sync push front", move |b| { b.iter(|| { let mut list: ListSync = ListSync::new_sync(); for i in 0..limit { list = list.push_front(i); } list }) }); } fn rpds_list_sync_push_front_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list sync push front mut", move |b| { b.iter(|| { let mut list: ListSync = ListSync::new_sync(); for i in 0..limit { list.push_front_mut(i); } list }) }); } fn rpds_list_sync_drop_first(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list sync drop first", move |b| { b.iter_with_setup( || { let mut list: ListSync = ListSync::new_sync(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list = list.drop_first().unwrap(); } list }, ); }); } fn rpds_list_sync_drop_first_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list sync drop first mut", move |b| { b.iter_with_setup( || { let mut list: ListSync = ListSync::new_sync(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list.drop_first_mut(); } list }, ); }); } fn rpds_list_sync_reverse(c: &mut Criterion) { let limit = 2_000; c.bench_function("rpds list sync reverse", move |b| { b.iter_with_setup( || { let mut list: ListSync = ListSync::new_sync(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list = list.reverse(); } list }, ); }); } fn rpds_list_sync_reverse_mut(c: &mut Criterion) { let limit = 2_000; c.bench_function("rpds list sync reverse mut", move |b| { b.iter_with_setup( || { let mut list: ListSync = ListSync::new_sync(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list.reverse_mut(); } list }, ); }); } fn rpds_list_sync_iterate(c: &mut Criterion) { let limit = 1_000_000; let mut list: ListSync = ListSync::new_sync(); for i in 0..limit { list.push_front_mut(i); } c.bench_function("rpds list sync iterate", move |b| { b.iter(|| { for i in list.iter() { black_box(i); } }) }); } criterion_group!( benches, rpds_list_sync_push_front, rpds_list_sync_push_front_mut, rpds_list_sync_drop_first, rpds_list_sync_drop_first_mut, rpds_list_sync_reverse, rpds_list_sync_reverse_mut, rpds_list_sync_iterate ); criterion_main!(benches); rpds/benches/rpds_vector.rs0000644000175000017500000000611614661133735017024 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::Vector; use std::hint::black_box; fn rpds_vector_push_back(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector push back", move |b| { b.iter(|| { let mut vector: Vector = Vector::new(); for i in 0..limit { vector = vector.push_back(i); } vector }) }); } fn rpds_vector_push_back_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector push back mut", move |b| { b.iter(|| { let mut vector: Vector = Vector::new(); for i in 0..limit { vector.push_back_mut(i); } vector }) }); } fn rpds_vector_drop_last(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector drop last", move |b| { b.iter_with_setup( || { let mut vector: Vector = Vector::new(); for i in 0..limit { vector.push_back_mut(i); } vector }, |mut vector| { for _ in 0..limit { vector = vector.drop_last().unwrap(); } vector }, ); }); } fn rpds_vector_drop_last_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds vector drop last mut", move |b| { b.iter_with_setup( || { let mut vector: Vector = Vector::new(); for i in 0..limit { vector.push_back_mut(i); } vector }, |mut vector| { for _ in 0..limit { vector.drop_last_mut(); } vector }, ); }); } fn rpds_vector_get(c: &mut Criterion) { let limit = 100_000; let mut vector: Vector = Vector::new(); for i in 0..limit { vector.push_back_mut(i); } c.bench_function("rpds vector get", move |b| { b.iter(|| { for i in 0..limit { black_box(vector.get(i)); } }) }); } fn rpds_vector_iterate(c: &mut Criterion) { let limit = 100_000; let mut vector: Vector = Vector::new(); for i in 0..limit { vector.push_back_mut(i); } c.bench_function("rpds vector iterate", move |b| { b.iter(|| { for i in vector.iter() { black_box(i); } }) }); } criterion_group!( benches, rpds_vector_push_back, rpds_vector_push_back_mut, rpds_vector_drop_last, rpds_vector_drop_last_mut, rpds_vector_get, rpds_vector_iterate ); criterion_main!(benches); rpds/benches/std_linked_list.rs0000644000175000017500000000553714661133735017653 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use std::collections::LinkedList; use std::hint::black_box; fn std_linked_list_push_front(c: &mut Criterion) { let limit = 100_000; c.bench_function("std linked list push front", move |b| { b.iter(|| { let mut linked_list: LinkedList = LinkedList::new(); for i in 0..limit { linked_list.push_front(i); } linked_list }) }); } fn std_linked_list_push_back(c: &mut Criterion) { let limit = 100_000; c.bench_function("std linked list push back", move |b| { b.iter(|| { let mut linked_list: LinkedList = LinkedList::new(); for i in 0..limit { linked_list.push_back(i); } linked_list }) }); } fn std_linked_list_pop_front(c: &mut Criterion) { let limit = 100_000; c.bench_function("std linked list pop front", move |b| { b.iter_with_setup( || { let mut linked_list: LinkedList = LinkedList::new(); for i in 0..limit { linked_list.push_back(i); } linked_list }, |mut linked_list| { for _ in 0..limit { linked_list.pop_front(); } linked_list }, ); }); } fn std_linked_list_pop_back(c: &mut Criterion) { let limit = 100_000; c.bench_function("std linked list pop back", move |b| { b.iter_with_setup( || { let mut linked_list: LinkedList = LinkedList::new(); for i in 0..limit { linked_list.push_back(i); } linked_list }, |mut linked_list| { for _ in 0..limit { linked_list.pop_back(); } linked_list }, ); }); } fn std_linked_list_iterate(c: &mut Criterion) { let limit = 100_000; let mut linked_list: LinkedList = LinkedList::new(); for i in 0..limit { linked_list.push_back(i); } c.bench_function("std linked list iterate", move |b| { b.iter(|| { for i in &linked_list { black_box(i); } }) }); } criterion_group!( benches, std_linked_list_push_front, std_linked_list_push_back, std_linked_list_pop_front, std_linked_list_pop_back, std_linked_list_iterate ); criterion_main!(benches); rpds/benches/rpds_list.rs0000644000175000017500000000733614661133735016502 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(feature = "fatal-warnings", deny(warnings))] use criterion::{criterion_group, criterion_main, Criterion}; use rpds::List; use std::hint::black_box; fn rpds_list_push_front(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list push front", move |b| { b.iter(|| { let mut list: List = List::new(); for i in 0..limit { list = list.push_front(i); } list }) }); } fn rpds_list_push_front_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list push front mut", move |b| { b.iter(|| { let mut list: List = List::new(); for i in 0..limit { list.push_front_mut(i); } list }) }); } fn rpds_list_drop_first(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list drop first", move |b| { b.iter_with_setup( || { let mut list: List = List::new(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list = list.drop_first().unwrap(); } list }, ); }); } fn rpds_list_drop_first_mut(c: &mut Criterion) { let limit = 100_000; c.bench_function("rpds list drop first mut", move |b| { b.iter_with_setup( || { let mut list: List = List::new(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list.drop_first_mut(); } list }, ); }); } fn rpds_list_reverse(c: &mut Criterion) { let limit = 10_000; c.bench_function("rpds list reverse", move |b| { b.iter_with_setup( || { let mut list: List = List::new(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list = list.reverse(); } list }, ); }); } fn rpds_list_reverse_mut(c: &mut Criterion) { let limit = 10_000; c.bench_function("rpds list reverse mut", move |b| { b.iter_with_setup( || { let mut list: List = List::new(); for i in 0..limit { list.push_front_mut(i); } list }, |mut list| { for _ in 0..limit { list.reverse_mut(); } list }, ); }); } fn rpds_list_iterate(c: &mut Criterion) { let limit = 100_000; let mut list = List::new(); for i in 0..limit { list.push_front_mut(i); } c.bench_function("rpds list iterate", move |b| { b.iter(|| { for i in list.iter() { black_box(i); } }) }); } criterion_group!( benches, rpds_list_push_front, rpds_list_push_front_mut, rpds_list_drop_first, rpds_list_drop_first_mut, rpds_list_reverse, rpds_list_reverse_mut, rpds_list_iterate ); criterion_main!(benches); rpds/src/0000775000175000017500000000000014661133735013302 5ustar jamespagejamespagerpds/src/set/0000775000175000017500000000000014661133735014075 5ustar jamespagejamespagerpds/src/set/mod.rs0000644000175000017500000000040214661133735015214 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ pub mod hash_trie_set; pub mod red_black_tree_set; rpds/src/set/hash_trie_set/0000775000175000017500000000000014661133735016716 5ustar jamespagejamespagerpds/src/set/hash_trie_set/test.rs0000644000175000017500000002071214661133735020243 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use alloc::vec::Vec; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(HashTrieSetSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_hash_trie_set_sync_is_send_and_sync() -> impl Send + Sync { ht_set_sync!(0) } mod iter { use super::*; use pretty_assertions::assert_eq; #[test] fn test_iter_empty() { let set: HashTrieSet = HashTrieSet::new(); for _ in set.iter() { panic!("iterator should be empty"); } } #[test] fn test_iter() { let mut set = HashTrieSet::new(); let limit: usize = 100; for i in 0..limit { set = set.insert(i); } let mut touched = vec![false; limit]; for v in set.iter() { assert!(!touched[*v]); touched[*v] = true; } assert!(touched.iter().all(|b| *b)); } #[test] fn test_iter_size_hint() { let set = ht_set![0, 1, 2]; let mut iterator = set.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_into_iterator() { let set = ht_set![0, 1, 2]; let mut left = 3; for _ in &set { left -= 1; assert!(left >= 0); } assert_eq!(left, 0); } } #[test] fn test_macro_ht_set() { let set_1 = HashTrieSet::new().insert(1); let set_1_2_3 = HashTrieSet::new().insert(1).insert(2).insert(3); assert_eq!(HashTrieSet::::new(), ht_set![]); assert_eq!(set_1, ht_set![1]); assert_eq!(set_1_2_3, ht_set![1, 2, 3]); } #[test] fn test_insert() { let mut set = HashTrieSet::new(); assert_eq!(set.size(), 0); set = set.insert("foo"); assert_eq!(set.size(), 1); assert!(set.contains("foo")); set = set.insert("bar"); assert_eq!(set.size(), 2); assert!(set.contains("foo")); assert!(set.contains("bar")); set = set.insert("baz"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); set = set.insert("foo"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); } #[test] fn test_insert_mut() { let mut set = HashTrieSet::new(); assert_eq!(set.size(), 0); set.insert_mut("foo"); assert_eq!(set.size(), 1); assert!(set.contains("foo")); set.insert_mut("bar"); assert_eq!(set.size(), 2); assert!(set.contains("foo")); assert!(set.contains("bar")); set.insert_mut("baz"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); set.insert_mut("foo"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); } #[test] fn test_remove() { let mut set = ht_set!["foo", "bar", "mumble", "baz"]; let empty_set: HashTrieSet = HashTrieSet::new(); assert_eq!(empty_set.remove(&3), empty_set); assert_eq!(set.size(), 4); set = set.remove("not-there"); assert_eq!(set.size(), 4); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("mumble")); assert!(set.contains("baz")); set = set.remove("mumble"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(!set.contains("mumble")); assert!(set.contains("baz")); set = set.remove("foo"); assert_eq!(set.size(), 2); assert!(!set.contains("foo")); set = set.remove("baz"); assert_eq!(set.size(), 1); assert!(!set.contains("baz")); set = set.remove("bar"); assert_eq!(set.size(), 0); assert!(!set.contains("bar")); } #[test] fn test_remove_mut() { let mut set = ht_set!["foo", "bar", "mumble", "baz"]; assert_eq!(set.size(), 4); assert!(!set.remove_mut("not-there")); assert_eq!(set.size(), 4); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("mumble")); assert!(set.contains("baz")); assert!(set.remove_mut("mumble")); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(!set.contains("mumble")); assert!(set.contains("baz")); assert!(set.remove_mut("foo")); assert_eq!(set.size(), 2); assert!(!set.contains("foo")); assert!(set.remove_mut("baz")); assert_eq!(set.size(), 1); assert!(!set.contains("baz")); assert!(set.remove_mut("bar")); assert_eq!(set.size(), 0); assert!(!set.contains("bar")); } #[test] fn test_get() { let mut set = HashTrieSet::new(); set = set.insert("foo"); assert_eq!(set.get("foo"), Some(&"foo")); set = set.insert("bar"); assert_eq!(set.get("foo"), Some(&"foo")); assert_eq!(set.get("bar"), Some(&"bar")); } #[test] fn test_is_disjoint() { assert!(!HashTrieSet::is_disjoint(&ht_set![1, 2, 3], &ht_set![1, 2, 3])); assert!(!HashTrieSet::is_disjoint(&ht_set![1, 2, 3], &ht_set![0, 1])); assert!(HashTrieSet::is_disjoint(&ht_set![1, 2, 3, 7, 16], &ht_set![0, 4, 17])); } #[test] fn test_is_subset() { let set = ht_set![1, 2, 3]; assert!(set.is_subset(&set)); assert!(HashTrieSet::is_subset(&ht_set![], &ht_set![1, 2, 3])); assert!(HashTrieSet::is_subset(&ht_set![1, 2, 3], &ht_set![1, 2, 3])); assert!(!HashTrieSet::is_subset(&ht_set![1, 2, 3], &ht_set![1, 2, 5, 6])); assert!(HashTrieSet::is_subset(&ht_set![1, 2, 3], &ht_set![1, 2, 3, 5, 6])); assert!(!HashTrieSet::is_subset(&ht_set![1, 2, 3, 5, 6], &ht_set![1, 2, 3])); } #[test] fn test_is_superset() { let set = ht_set![1, 2, 3]; assert!(set.is_superset(&set)); assert!(HashTrieSet::is_superset(&ht_set![1, 2, 3], &ht_set![])); assert!(HashTrieSet::is_superset(&ht_set![1, 2, 3], &ht_set![1, 2, 3])); assert!(!HashTrieSet::is_superset(&ht_set![1, 2, 5, 6], &ht_set![1, 2, 3])); assert!(HashTrieSet::is_superset(&ht_set![1, 2, 3, 5, 6], &ht_set![1, 2, 3])); assert!(!HashTrieSet::is_superset(&ht_set![1, 2, 3], &ht_set![1, 2, 3, 5, 6])); } #[test] fn test_from_iterator() { let vec: Vec<&str> = vec![("two"), ("five")]; let set: HashTrieSet<&str> = vec.iter().copied().collect(); let expected_set = ht_set!["two", "five"]; assert_eq!(set, expected_set); } #[test] fn test_default() { let set: HashTrieSet = HashTrieSet::default(); assert_eq!(set.size(), 0); assert!(set.is_empty()); } #[test] fn test_display() { let empty_set: HashTrieSet = HashTrieSet::new(); let singleton_set = ht_set!["hi"]; let set = ht_set![5, 12]; assert_eq!(format!("{}", empty_set), "{}"); assert_eq!(format!("{}", singleton_set), "{hi}"); assert!(format!("{set}") == "{5, 12}" || format!("{set}") == "{12, 5}"); } #[test] fn test_eq() { let set_1 = ht_set!["a", "b"]; let set_1_prime = ht_set!["a", "b"]; let set_1_prime_2 = ht_set!["a", "b", "b"]; let set_2 = ht_set!["a", "b", "c"]; assert_eq!(set_1, set_1_prime); assert_eq!(set_1, set_1_prime_2); assert_eq!(set_1, set_1); assert_eq!(set_2, set_2); // We also check this since `assert_ne!()` does not call `ne`. assert!(set_1.ne(&set_2)); } #[test] fn test_eq_pointer_kind_consistent() { let set_a = ht_set!["a"]; let set_a_sync = ht_set_sync!["a"]; let set_b = ht_set!["b"]; let set_b_sync = ht_set_sync!["b"]; assert!(set_a == set_a_sync); assert!(set_a != set_b_sync); assert!(set_b == set_b_sync); } #[test] fn test_clone() { let set = ht_set!["hello", "there"]; let clone = set.clone(); assert_eq!(clone.size(), set.size()); assert!(clone.contains("hello")); assert!(clone.contains("there")); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let set: HashTrieSet = ht_set![5, 6, 7, 8]; let encoded = serialize(&set).unwrap(); let decoded: HashTrieSet = deserialize(&encoded).unwrap(); assert_eq!(set, decoded); } rpds/src/set/hash_trie_set/mod.rs0000644000175000017500000002464714661133735020056 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::map::hash_trie_map; use crate::utils::DefaultBuildHasher; use crate::HashTrieMap; use archery::{ArcTK, RcK, SharedPointerKind}; use core::borrow::Borrow; use core::fmt::Display; use core::hash::BuildHasher; use core::hash::Hash; use core::iter::FromIterator; // TODO Use impl trait instead of this when available. pub type Iter<'a, T, P> = hash_trie_map::IterKeys<'a, T, (), P>; /// Creates a [`HashTrieSet`](crate::HashTrieSet) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let s = HashTrieSet::new() /// .insert(1) /// .insert(2) /// .insert(3); /// /// assert_eq!(ht_set![1, 2, 3], s); /// ``` #[macro_export] macro_rules! ht_set { ($($e:expr),*) => { { #[allow(unused_mut)] let mut s = $crate::HashTrieSet::new(); $( s.insert_mut($e); )* s } }; } /// Creates a [`HashTrieSet`](crate::HashTrieSet) that implements `Sync`, containing the given /// arguments: /// /// ``` /// # use rpds::*; /// # /// let s = HashTrieSet::new_sync() /// .insert(1) /// .insert(2) /// .insert(3); /// /// assert_eq!(ht_set_sync![1, 2, 3], s); /// ``` #[macro_export] macro_rules! ht_set_sync { ($($e:expr),*) => { { #[allow(unused_mut)] let mut s = $crate::HashTrieSet::new_sync(); $( s.insert_mut($e); )* s } }; } /// A persistent set with structural sharing. This implementation uses a /// [hash array mapped trie](https://en.wikipedia.org/wiki/Hash_array_mapped_trie). /// /// # Complexity /// /// Let *n* be the number of elements in the set. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:----------------- | -------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `insert()` | Θ(1) | Θ(n) | /// | `remove()` | Θ(1) | Θ(n) | /// | `get()` | Θ(1) | Θ(n) | /// | `contains()` | Θ(1) | Θ(n) | /// | `size()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(1) | Θ(1) | /// | iterator step | Θ(1) | Θ(1) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This is a thin wrapper around a [`HashTrieMap`](crate::HashTrieMap). #[derive(Debug)] pub struct HashTrieSet where T: Eq + Hash, H: Clone, P: SharedPointerKind, { map: HashTrieMap, } pub type HashTrieSetSync = HashTrieSet; impl HashTrieSet where T: Eq + Hash, { #[must_use] pub fn new() -> HashTrieSet { HashTrieSet { map: HashTrieMap::new_with_hasher_and_ptr_kind(DefaultBuildHasher::default()), } } #[must_use] pub fn new_with_degree(degree: u8) -> HashTrieSet { HashTrieSet::new_with_hasher_and_degree_and_ptr_kind(DefaultBuildHasher::default(), degree) } } impl HashTrieSetSync where T: Eq + Hash, { #[must_use] pub fn new_sync() -> HashTrieSetSync { HashTrieSet { map: HashTrieMap::new_with_hasher_and_ptr_kind(DefaultBuildHasher::default()), } } #[must_use] pub fn new_with_degree_sync(degree: u8) -> HashTrieSetSync { HashTrieSet::new_with_hasher_and_degree_and_ptr_kind(DefaultBuildHasher::default(), degree) } } impl HashTrieSet where T: Eq + Hash, H: Clone, P: SharedPointerKind, { #[must_use] pub fn new_with_hasher_with_ptr_kind(hasher_builder: H) -> HashTrieSet { HashTrieSet { map: HashTrieMap::new_with_hasher_and_ptr_kind(hasher_builder) } } #[must_use] pub fn new_with_hasher_and_degree_and_ptr_kind( hasher_builder: H, degree: u8, ) -> HashTrieSet { HashTrieSet { map: HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(hasher_builder, degree), } } #[must_use] pub fn insert(&self, v: T) -> HashTrieSet { HashTrieSet { map: self.map.insert(v, ()) } } pub fn insert_mut(&mut self, v: T) { self.map.insert_mut(v, ()); } #[must_use] pub fn remove(&self, v: &V) -> HashTrieSet where T: Borrow, V: Hash + Eq, { HashTrieSet { map: self.map.remove(v) } } pub fn remove_mut(&mut self, v: &V) -> bool where T: Borrow, V: Hash + Eq, { self.map.remove_mut(v) } #[must_use] pub fn get(&self, v: &V) -> Option<&T> where T: Borrow, V: Hash + Eq, { self.map.get_key_value(v).map(|(k, _)| k) } #[must_use] pub fn contains(&self, v: &V) -> bool where T: Borrow, V: Hash + Eq, { self.map.contains_key(v) } #[must_use] pub fn is_disjoint(&self, other: &HashTrieSet) -> bool { self.iter().all(|v| !other.contains(v)) } /// Test whether the two sets refer to the same content in memory. /// /// This would return true if you’re comparing a set to itself, /// or if you’re comparing a set to a fresh clone of itself. fn ptr_eq( &self, other: &HashTrieSet, ) -> bool { self.map.ptr_eq(&other.map) } #[must_use] pub fn is_subset(&self, other: &HashTrieSet) -> bool { if self.ptr_eq(other) { return true; } self.size() <= other.size() && self.iter().all(|v| other.contains(v)) } #[must_use] pub fn is_superset(&self, other: &HashTrieSet) -> bool { other.is_subset(self) } #[must_use] #[inline] pub fn size(&self) -> usize { self.map.size() } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.size() == 0 } pub fn iter(&self) -> Iter<'_, T, P> { self.map.keys() } } impl Clone for HashTrieSet where T: Eq + Hash, H: Clone, P: SharedPointerKind, { fn clone(&self) -> HashTrieSet { HashTrieSet { map: self.map.clone() } } } impl Default for HashTrieSet where T: Eq + Hash, H: Default + Clone, P: SharedPointerKind, { fn default() -> HashTrieSet { HashTrieSet::new_with_hasher_with_ptr_kind(H::default()) } } impl PartialEq> for HashTrieSet where T: Hash, H: Clone, P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &HashTrieSet) -> bool { self.map.eq(&other.map) } } impl Eq for HashTrieSet where T: Hash, H: Clone, P: SharedPointerKind, { } impl Display for HashTrieSet where T: Eq + Hash + Display, H: Clone, P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("{")?; for v in self.iter() { if !first { fmt.write_str(", ")?; } v.fmt(fmt)?; first = false; } fmt.write_str("}") } } impl<'a, T, P, H: BuildHasher> IntoIterator for &'a HashTrieSet where T: Eq + Hash, H: Default + Clone, P: SharedPointerKind, { type Item = &'a T; type IntoIter = Iter<'a, T, P>; fn into_iter(self) -> Iter<'a, T, P> { self.iter() } } impl FromIterator for HashTrieSet where T: Eq + Hash, H: BuildHasher + Clone + Default, P: SharedPointerKind, { fn from_iter>(into_iter: I) -> HashTrieSet { let mut set = HashTrieSet::new_with_hasher_with_ptr_kind(Default::default()); for v in into_iter { set.insert_mut(v); } set } } #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; use ::serde::ser::{Serialize, Serializer}; use core::fmt; use core::marker::PhantomData; impl Serialize for HashTrieSet where T: Eq + Hash + Serialize, H: BuildHasher + Clone + Default, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { serializer.collect_seq(self) } } impl<'de, T, P, H> Deserialize<'de> for HashTrieSet where T: Eq + Hash + Deserialize<'de>, H: BuildHasher + Clone + Default, P: SharedPointerKind, { fn deserialize>( deserializer: D, ) -> Result, D::Error> { deserializer.deserialize_seq(HashTrieSetVisitor { _phantom_t: PhantomData, _phantom_h: PhantomData, _phantom_p: PhantomData, }) } } struct HashTrieSetVisitor { _phantom_t: PhantomData, _phantom_h: PhantomData, _phantom_p: PhantomData

, } impl<'de, T, P, H> Visitor<'de> for HashTrieSetVisitor where T: Eq + Hash + Deserialize<'de>, H: BuildHasher + Clone + Default, P: SharedPointerKind, { type Value = HashTrieSet; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a sequence") } fn visit_seq(self, mut seq: A) -> Result, A::Error> where A: SeqAccess<'de>, { let mut set = HashTrieSet::new_with_hasher_with_ptr_kind(Default::default()); while let Some(value) = seq.next_element()? { set.insert_mut(value); } Ok(set) } } } #[cfg(test)] mod test; rpds/src/set/red_black_tree_set/0000775000175000017500000000000014661133735017675 5ustar jamespagejamespagerpds/src/set/red_black_tree_set/test.rs0000644000175000017500000002675014661133735021232 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use alloc::vec::Vec; use core::hash::{Hash, Hasher}; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(RedBlackTreeSetSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_red_black_tree_set_sync_is_send_and_sync() -> impl Send + Sync { rbt_set_sync!(0) } mod iter { use super::*; use pretty_assertions::assert_eq; #[test] fn test_iter_empty() { let set: RedBlackTreeSet = RedBlackTreeSet::new(); for _ in set.iter() { panic!("iterator should be empty"); } } #[test] fn test_iter() { let mut set = RedBlackTreeSet::new(); let limit: usize = 100; for i in 0..limit { set = set.insert(i); } let mut touched = vec![false; limit]; for v in set.iter() { assert!(!touched[*v]); touched[*v] = true; } assert!(touched.iter().all(|b| *b)); } #[test] fn test_iter_size_hint() { let set = rbt_set![0, 1, 2]; let mut iterator = set.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_iter_sorted() { let set = rbt_set![5, 6, 2, 1]; let mut iterator = set.iter(); assert_eq!(iterator.next(), Some(&1)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next(), Some(&5)); assert_eq!(iterator.next(), Some(&6)); assert_eq!(iterator.next(), None); } #[test] fn test_into_iterator() { let set = rbt_set![0, 1, 2]; let mut left = 3; for _ in &set { left -= 1; assert!(left >= 0); } assert_eq!(left, 0); } #[test] fn test_range_iterator() { let set = rbt_set![-20, -12, -8, 0, 2, -10, -7, -3, 5, 8, 10, 13, 17, 20]; let mut iterator = set.range(-7..=13); assert_eq!(iterator.next(), Some(&-7)); assert_eq!(iterator.next(), Some(&-3)); assert_eq!(iterator.next_back(), Some(&13)); assert_eq!(iterator.next_back(), Some(&10)); assert_eq!(iterator.next_back(), Some(&8)); assert_eq!(iterator.next(), Some(&0)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next(), Some(&5)); assert_eq!(iterator.next_back(), None); assert_eq!(iterator.next(), None); } } #[test] fn test_macro_rbt_set() { let set_1 = RedBlackTreeSet::new().insert(1); let set_1_2_3 = RedBlackTreeSet::new().insert(1).insert(2).insert(3); assert_eq!(RedBlackTreeSet::::new(), rbt_set![]); assert_eq!(set_1, rbt_set![1]); assert_eq!(set_1_2_3, rbt_set![1, 2, 3]); } #[test] fn test_insert() { let mut set = RedBlackTreeSet::new(); assert_eq!(set.size(), 0); set = set.insert("foo"); assert_eq!(set.size(), 1); assert!(set.contains("foo")); set = set.insert("bar"); assert_eq!(set.size(), 2); assert!(set.contains("foo")); assert!(set.contains("bar")); set = set.insert("baz"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); set = set.insert("foo"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); } #[test] fn test_insert_mut() { let mut set = RedBlackTreeSet::new(); assert_eq!(set.size(), 0); set.insert_mut("foo"); assert_eq!(set.size(), 1); assert!(set.contains("foo")); set.insert_mut("bar"); assert_eq!(set.size(), 2); assert!(set.contains("foo")); assert!(set.contains("bar")); set.insert_mut("baz"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); set.insert_mut("foo"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("baz")); } #[test] fn test_first() { let set = rbt_set![3, 2, 1]; assert_eq!(set.first(), Some(&1)); } #[test] fn test_last() { let set = rbt_set![3, 2, 1]; assert_eq!(set.last(), Some(&3)); } #[test] fn test_remove() { let mut set = rbt_set!["foo", "bar", "mumble", "baz"]; let empty_set: RedBlackTreeSet = RedBlackTreeSet::new(); assert_eq!(empty_set.remove(&3), empty_set); assert_eq!(set.size(), 4); set = set.remove("not-there"); assert_eq!(set.size(), 4); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("mumble")); assert!(set.contains("baz")); set = set.remove("mumble"); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(!set.contains("mumble")); assert!(set.contains("baz")); set = set.remove("foo"); assert_eq!(set.size(), 2); assert!(!set.contains("foo")); set = set.remove("baz"); assert_eq!(set.size(), 1); assert!(!set.contains("baz")); set = set.remove("bar"); assert_eq!(set.size(), 0); assert!(!set.contains("bar")); } #[test] fn test_remove_mut() { let mut set = rbt_set!["foo", "bar", "mumble", "baz"]; assert_eq!(set.size(), 4); assert!(!set.remove_mut("not-there")); assert_eq!(set.size(), 4); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(set.contains("mumble")); assert!(set.contains("baz")); assert!(set.remove_mut("mumble")); assert_eq!(set.size(), 3); assert!(set.contains("foo")); assert!(set.contains("bar")); assert!(!set.contains("mumble")); assert!(set.contains("baz")); assert!(set.remove_mut("foo")); assert_eq!(set.size(), 2); assert!(!set.contains("foo")); assert!(set.remove_mut("baz")); assert_eq!(set.size(), 1); assert!(!set.contains("baz")); assert!(set.remove_mut("bar")); assert_eq!(set.size(), 0); assert!(!set.contains("bar")); } #[test] fn test_get() { let mut set = RedBlackTreeSet::new(); set = set.insert("foo"); assert_eq!(set.get("foo"), Some(&"foo")); set = set.insert("bar"); assert_eq!(set.get("foo"), Some(&"foo")); assert_eq!(set.get("bar"), Some(&"bar")); } #[test] fn test_is_disjoint() { assert!(!RedBlackTreeSet::is_disjoint(&rbt_set![1, 2, 3], &rbt_set![1, 2, 3])); assert!(!RedBlackTreeSet::is_disjoint(&rbt_set![1, 2, 3], &rbt_set![0, 1])); assert!(RedBlackTreeSet::is_disjoint(&rbt_set![1, 2, 3, 7, 16], &rbt_set![0, 4, 17])); } #[test] fn test_is_subset() { let set = rbt_set![1, 2, 3]; assert!(set.is_subset(&set)); assert!(RedBlackTreeSet::is_subset(&rbt_set![], &rbt_set![1, 2, 3])); assert!(RedBlackTreeSet::is_subset(&rbt_set![1, 2, 3], &rbt_set![1, 2, 3])); assert!(!RedBlackTreeSet::is_subset(&rbt_set![1, 2, 3], &rbt_set![1, 2, 5, 6])); assert!(RedBlackTreeSet::is_subset(&rbt_set![1, 2, 3], &rbt_set![1, 2, 3, 5, 6])); assert!(!RedBlackTreeSet::is_subset(&rbt_set![1, 2, 3, 5, 6], &rbt_set![1, 2, 3])); } #[test] fn test_is_superset() { let set = rbt_set![1, 2, 3]; assert!(set.is_superset(&set)); assert!(RedBlackTreeSet::is_superset(&rbt_set![1, 2, 3], &rbt_set![])); assert!(RedBlackTreeSet::is_superset(&rbt_set![1, 2, 3], &rbt_set![1, 2, 3])); assert!(!RedBlackTreeSet::is_superset(&rbt_set![1, 2, 5, 6], &rbt_set![1, 2, 3])); assert!(RedBlackTreeSet::is_superset(&rbt_set![1, 2, 3, 5, 6], &rbt_set![1, 2, 3])); assert!(!RedBlackTreeSet::is_superset(&rbt_set![1, 2, 3], &rbt_set![1, 2, 3, 5, 6])); } #[test] fn test_from_iterator() { let vec: Vec<&str> = vec![("two"), ("five")]; let set: RedBlackTreeSet<&str> = vec.iter().copied().collect(); let expected_set = rbt_set!["two", "five"]; assert_eq!(set, expected_set); } #[test] fn test_default() { let set: RedBlackTreeSet = RedBlackTreeSet::default(); assert_eq!(set.size(), 0); assert!(set.is_empty()); } #[test] fn test_display() { let empty_set: RedBlackTreeSet = RedBlackTreeSet::new(); let singleton_set = rbt_set!["hi"]; let set = rbt_set![5, 12]; assert_eq!(format!("{}", empty_set), "{}"); assert_eq!(format!("{}", singleton_set), "{hi}"); assert_eq!(format!("{}", set), "{5, 12}"); } #[test] fn test_eq() { let set_1 = rbt_set!["a", "b"]; let set_1_prime = rbt_set!["a", "b"]; let set_1_prime_2 = rbt_set!["a", "b", "b"]; let set_2 = rbt_set!["a", "b", "c"]; assert_eq!(set_1, set_1_prime); assert_eq!(set_1, set_1_prime_2); assert_eq!(set_1, set_1); assert_eq!(set_2, set_2); // We also check this since `assert_ne!()` does not call `ne`. assert!(set_1.ne(&set_2)); } #[test] fn test_eq_pointer_kind_consistent() { let set_a = rbt_set!["a"]; let set_a_sync = rbt_set_sync!["a"]; let set_b = rbt_set!["b"]; let set_b_sync = rbt_set_sync!["b"]; assert!(set_a == set_a_sync); assert!(set_a != set_b_sync); assert!(set_b == set_b_sync); } #[test] fn test_partial_ord() { let set_1 = rbt_set!["a"]; let set_1_prime = rbt_set!["a"]; let set_2 = rbt_set!["b"]; assert_eq!(set_1.partial_cmp(&set_1_prime), Some(Ordering::Equal)); assert_eq!(set_1.partial_cmp(&set_2), Some(Ordering::Less)); assert_eq!(set_2.partial_cmp(&set_1), Some(Ordering::Greater)); } #[test] fn test_ord() { let set_1 = rbt_set!["a"]; let set_1_prime = rbt_set!["a"]; let set_2 = rbt_set!["b"]; assert_eq!(set_1.cmp(&set_1_prime), Ordering::Equal); assert_eq!(set_1.cmp(&set_2), Ordering::Less); assert_eq!(set_2.cmp(&set_1), Ordering::Greater); } #[test] fn test_ord_pointer_kind_consistent() { let set_a = rbt_set!["a"]; let set_a_sync = rbt_set_sync!["a"]; let set_b = rbt_set!["b"]; let set_b_sync = rbt_set_sync!["b"]; assert!(set_a <= set_a_sync); assert!(set_a < set_b_sync); assert!(set_b >= set_b_sync); assert!(set_a_sync >= set_a); assert!(set_b_sync > set_a); assert!(set_b_sync <= set_b); } fn hash(set: &RedBlackTreeSet) -> u64 where P: SharedPointerKind, { #[allow(deprecated)] let mut hasher = core::hash::SipHasher::new(); set.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let set_1 = rbt_set!["a"]; let set_1_prime = rbt_set!["a"]; let set_2 = rbt_set!["b", "a"]; assert_eq!(hash(&set_1), hash(&set_1)); assert_eq!(hash(&set_1), hash(&set_1_prime)); assert_ne!(hash(&set_1), hash(&set_2)); } #[test] fn test_hash_pointer_kind_consistent() { let set = rbt_set!["a"]; let set_sync = rbt_set_sync!["a"]; assert_eq!(hash(&set), hash(&set_sync)); } #[test] fn test_clone() { let set = rbt_set!["hello", "there"]; let clone = set.clone(); assert_eq!(clone.size(), set.size()); assert!(clone.contains("hello")); assert!(clone.contains("there")); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let set: RedBlackTreeSet = rbt_set![5, 6, 7, 8]; let encoded = serialize(&set).unwrap(); let decoded: RedBlackTreeSet = deserialize(&encoded).unwrap(); assert_eq!(set, decoded); } rpds/src/set/red_black_tree_set/mod.rs0000644000175000017500000002665614661133735021037 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::map::red_black_tree_map; use crate::RedBlackTreeMap; use archery::{ArcTK, RcK, SharedPointerKind}; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::Display; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; use core::ops::RangeBounds; // TODO Use impl trait instead of this when available. pub type Iter<'a, T, P> = red_black_tree_map::IterKeys<'a, T, (), P>; pub type RangeIter<'a, T, RB, Q, P> = core::iter::Map, fn((&'a T, &())) -> &'a T>; /// Creates a [`RedBlackTreeSet`](crate::RedBlackTreeSet) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let s = RedBlackTreeSet::new() /// .insert(1) /// .insert(2) /// .insert(3); /// /// assert_eq!(rbt_set![1, 2, 3], s); /// ``` #[macro_export] macro_rules! rbt_set { ($($e:expr),*) => { { #[allow(unused_mut)] let mut s = $crate::RedBlackTreeSet::new(); $( s.insert_mut($e); )* s } }; } /// Creates a [`RedBlackTreeSet`](crate::RedBlackTreeSet) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let s = RedBlackTreeSet::new_sync() /// .insert(1) /// .insert(2) /// .insert(3); /// /// assert_eq!(rbt_set_sync![1, 2, 3], s); /// ``` #[macro_export] macro_rules! rbt_set_sync { ($($e:expr),*) => { { #[allow(unused_mut)] let mut s = $crate::RedBlackTreeSet::new_sync(); $( s.insert_mut($e); )* s } }; } /// A persistent set with structural sharing. This implementation uses a /// [red-black tree](https://en.wikipedia.org/wiki/Red-Black_tree). /// /// # Complexity /// /// Let *n* be the number of elements in the set. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:-------------------------- | ---------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `insert()` | Θ(log(n)) | Θ(log(n)) | /// | `remove()` | Θ(log(n)) | Θ(log(n)) | /// | `get()` | Θ(log(n)) | Θ(log(n)) | /// | `contains()` | Θ(log(n)) | Θ(log(n)) | /// | `size()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(log(n)) | Θ(log(n)) | /// | iterator step | Θ(1) | Θ(log(n)) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This is a thin wrapper around a [`RedBlackTreeMap`](crate::RedBlackTreeMap). #[derive(Debug)] pub struct RedBlackTreeSet where T: Ord, P: SharedPointerKind, { map: RedBlackTreeMap, } pub type RedBlackTreeSetSync = RedBlackTreeSet; impl RedBlackTreeSetSync where T: Ord, { #[must_use] pub fn new_sync() -> RedBlackTreeSetSync { RedBlackTreeSet::new_with_ptr_kind() } } impl RedBlackTreeSet where T: Ord, { #[must_use] pub fn new() -> RedBlackTreeSet { RedBlackTreeSet { map: RedBlackTreeMap::new_with_ptr_kind() } } } impl RedBlackTreeSet where T: Ord, P: SharedPointerKind, { #[must_use] pub fn new_with_ptr_kind() -> RedBlackTreeSet { RedBlackTreeSet { map: RedBlackTreeMap::new_with_ptr_kind() } } #[must_use] pub fn insert(&self, v: T) -> RedBlackTreeSet { RedBlackTreeSet { map: self.map.insert(v, ()) } } pub fn insert_mut(&mut self, v: T) { self.map.insert_mut(v, ()); } #[must_use] pub fn remove(&self, v: &V) -> RedBlackTreeSet where T: Borrow, V: Ord, { RedBlackTreeSet { map: self.map.remove(v) } } pub fn remove_mut(&mut self, v: &V) -> bool where T: Borrow, V: Ord, { self.map.remove_mut(v) } #[must_use] pub fn get(&self, v: &V) -> Option<&T> where T: Borrow, V: Ord, { self.map.get_key_value(v).map(|(k, _)| k) } #[must_use] pub fn contains(&self, v: &V) -> bool where T: Borrow, V: Ord, { self.map.contains_key(v) } #[must_use] pub fn first(&self) -> Option<&T> { self.map.first().map(|(k, _)| k) } #[must_use] pub fn last(&self) -> Option<&T> { self.map.last().map(|(k, _)| k) } #[must_use] pub fn is_disjoint(&self, other: &RedBlackTreeSet) -> bool where PO: SharedPointerKind, { let mut self_it = self.iter(); let mut other_it = other.iter(); let mut v_opt = self_it.next(); let mut u_opt = other_it.next(); while let (Some(v), Some(u)) = (v_opt, u_opt) { match v.cmp(u) { Ordering::Less => v_opt = self_it.next(), Ordering::Equal => return false, Ordering::Greater => u_opt = other_it.next(), } } true } /// Test whether the two sets refer to the same content in memory. /// /// This would return true if you’re comparing a set to itself, /// or if you’re comparing a set to a fresh clone of itself. fn ptr_eq(&self, other: &RedBlackTreeSet) -> bool { self.map.ptr_eq(&other.map) } #[must_use] pub fn is_subset(&self, other: &RedBlackTreeSet) -> bool where PO: SharedPointerKind, { if self.ptr_eq(other) { return true; } if self.size() > other.size() { return false; } let mut other_it = other.iter(); for v in self { loop { match other_it.next() { Some(u) => match u.cmp(v) { Ordering::Less => (), Ordering::Equal => break, Ordering::Greater => return false, }, None => return false, } } } true } #[must_use] pub fn is_superset(&self, other: &RedBlackTreeSet) -> bool where PO: SharedPointerKind, { other.is_subset(self) } #[must_use] #[inline] pub fn size(&self) -> usize { self.map.size() } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.size() == 0 } pub fn iter(&self) -> Iter<'_, T, P> { self.map.keys() } pub fn range(&self, range: RB) -> RangeIter<'_, T, RB, Q, P> where T: Borrow, Q: Ord + ?Sized, RB: RangeBounds, { self.map.range(range).map(|(k, _)| k) } } impl Clone for RedBlackTreeSet where T: Ord, P: SharedPointerKind, { fn clone(&self) -> RedBlackTreeSet { RedBlackTreeSet { map: self.map.clone() } } } impl Default for RedBlackTreeSet where T: Ord, P: SharedPointerKind, { fn default() -> RedBlackTreeSet { RedBlackTreeSet::new_with_ptr_kind() } } impl PartialEq> for RedBlackTreeSet where T: Ord, P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &RedBlackTreeSet) -> bool { self.map.eq(&other.map) } } impl Eq for RedBlackTreeSet where T: Ord, P: SharedPointerKind, { } impl PartialOrd> for RedBlackTreeSet where P: SharedPointerKind, PO: SharedPointerKind, { fn partial_cmp(&self, other: &RedBlackTreeSet) -> Option { self.iter().partial_cmp(other.iter()) } } impl Ord for RedBlackTreeSet where P: SharedPointerKind, { fn cmp(&self, other: &RedBlackTreeSet) -> Ordering { self.iter().cmp(other.iter()) } } impl Hash for RedBlackTreeSet where T: Ord, { fn hash(&self, state: &mut H) { // Add the hash of length so that if two collections are added one after the other it // doesn't hash to the same thing as a single collection with the same elements in the same // order. self.size().hash(state); for e in self { e.hash(state); } } } impl Display for RedBlackTreeSet where T: Ord + Display, P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("{")?; for v in self { if !first { fmt.write_str(", ")?; } v.fmt(fmt)?; first = false; } fmt.write_str("}") } } impl<'a, T, P> IntoIterator for &'a RedBlackTreeSet where T: Ord, P: SharedPointerKind, { type Item = &'a T; type IntoIter = Iter<'a, T, P>; fn into_iter(self) -> Iter<'a, T, P> { self.iter() } } // TODO This can be improved to create a perfectly balanced tree. impl FromIterator for RedBlackTreeSet where T: Ord, P: SharedPointerKind, { fn from_iter>(into_iter: I) -> RedBlackTreeSet { let mut set = RedBlackTreeSet::new_with_ptr_kind(); for v in into_iter { set.insert_mut(v); } set } } #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; use ::serde::ser::{Serialize, Serializer}; use core::fmt; use core::marker::PhantomData; impl Serialize for RedBlackTreeSet where T: Ord + Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { serializer.collect_seq(self) } } impl<'de, T, P> Deserialize<'de> for RedBlackTreeSet where T: Ord + Deserialize<'de>, P: SharedPointerKind, { fn deserialize>( deserializer: D, ) -> Result, D::Error> { deserializer.deserialize_seq(RedBlackTreeSetVisitor { _phantom_t: PhantomData, _phantom_p: PhantomData, }) } } struct RedBlackTreeSetVisitor { _phantom_t: PhantomData, _phantom_p: PhantomData

, } impl<'de, T, P> Visitor<'de> for RedBlackTreeSetVisitor where T: Ord + Deserialize<'de>, P: SharedPointerKind, { type Value = RedBlackTreeSet; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a sequence") } fn visit_seq(self, mut seq: A) -> Result, A::Error> where A: SeqAccess<'de>, { let mut set = RedBlackTreeSet::new_with_ptr_kind(); while let Some(value) = seq.next_element()? { set.insert_mut(value); } Ok(set) } } } #[cfg(test)] mod test; rpds/src/queue/0000775000175000017500000000000014661133735014426 5ustar jamespagejamespagerpds/src/queue/test.rs0000644000175000017500000002676614661133735015772 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(QueueSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_queue_sync_is_send_and_sync() -> impl Send + Sync { queue_sync!(0) } mod lazily_reversed_list_iter { use super::*; use pretty_assertions::assert_eq; #[test] fn test_iter() { let list = list![0, 1, 2]; let mut iterator = LazilyReversedListIter::new(&list); assert_eq!(iterator.next().map(|v| **v), Some(2)); assert_eq!(iterator.next().map(|v| **v), Some(1)); assert_eq!(iterator.next().map(|v| **v), Some(0)); assert_eq!(iterator.next(), None); let empty_list: List = List::new(); let mut iterator = LazilyReversedListIter::new(&empty_list); assert_eq!(iterator.next(), None); } #[test] fn test_iter_size_hint() { let list = list![0, 1, 2]; let mut iterator = LazilyReversedListIter::new(&list); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next(); assert_eq!(iterator.size_hint(), (0, Some(0))); let empty_list: List = List::new(); let iterator = LazilyReversedListIter::new(&empty_list); assert_eq!(iterator.size_hint(), (0, Some(0))); } } mod iter { use super::*; use pretty_assertions::assert_eq; #[test] fn test_iter() { let mut queue = Queue::new(); queue.enqueue_mut(0); queue.enqueue_mut(1); queue.dequeue_mut(); queue.enqueue_mut(2); queue.enqueue_mut(3); let mut iterator = queue.iter(); assert_eq!(iterator.next(), Some(&1)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next(), Some(&3)); assert_eq!(iterator.next(), None); } #[test] fn test_iter_size_hint() { let mut queue = Queue::new(); queue.enqueue_mut(0); queue.enqueue_mut(1); queue.dequeue_mut(); queue.enqueue_mut(2); queue.enqueue_mut(3); let mut iterator = queue.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_into_iterator() { let mut queue = Queue::new(); queue.enqueue_mut(0); queue.enqueue_mut(1); queue.dequeue_mut(); queue.enqueue_mut(2); queue.enqueue_mut(3); let mut expected = 1; let mut left = 3; for n in &queue { left -= 1; assert!(left >= 0); assert_eq!(*n, expected); expected += 1; } assert_eq!(left, 0); } } mod internal { use super::*; use pretty_assertions::assert_eq; #[test] fn test_enqueue_dequeue_mut() { let queue = queue![0, 1, 2, 3]; let mut queue_2 = Queue::new(); queue_2.enqueue_mut(0); queue_2.enqueue_mut(1); queue_2.dequeue_mut(); queue_2.enqueue_mut(2); queue_2.enqueue_mut(3); let mut queue_3 = Queue::new(); queue_3.enqueue_mut(0); queue_3.enqueue_mut(1); queue_3.enqueue_mut(2); queue_3.enqueue_mut(3); queue_3.dequeue_mut(); let list_3_2_1_0 = list![3, 2, 1, 0]; let list_3_2 = list![3, 2]; let list_1 = list![1]; let list_1_2_3 = list![1, 2, 3]; assert!(queue.out_list.is_empty()); assert_eq!(queue.in_list, list_3_2_1_0); assert_eq!(queue_2.out_list, list_1); assert_eq!(queue_2.in_list, list_3_2); assert_eq!(queue_3.out_list, list_1_2_3); assert!(queue_3.in_list.is_empty()); } } #[test] fn test_new() { let empty_queue: Queue = Queue::new(); assert!(empty_queue.in_list.is_empty()); assert!(empty_queue.out_list.is_empty()); assert_eq!(empty_queue.len(), 0); assert!(empty_queue.is_empty()); } #[test] fn test_macro_queue() { let mut queue_1 = Queue::new(); queue_1.enqueue_mut(1); let mut queue_1_2_3 = Queue::new(); queue_1_2_3.enqueue_mut(1); queue_1_2_3.enqueue_mut(2); queue_1_2_3.enqueue_mut(3); assert_eq!(Queue::::new(), queue![]); assert_eq!(queue_1, queue![1]); assert_eq!(queue_1_2_3, queue![1, 2, 3]); } #[test] fn test_peek() { let empty_queue: Queue = Queue::new(); let singleton_queue = queue!["hello"]; let queue = queue![0, 1, 2, 3]; let mut queue_2 = Queue::new(); queue_2.enqueue_mut(0); queue_2.enqueue_mut(1); queue_2.dequeue_mut(); queue_2.enqueue_mut(2); queue_2.enqueue_mut(3); let mut queue_3 = Queue::new(); queue_3.enqueue_mut(0); queue_3.enqueue_mut(1); queue_3.enqueue_mut(2); queue_3.enqueue_mut(3); queue_3.dequeue_mut(); assert_eq!(empty_queue.peek(), None); assert_eq!(singleton_queue.peek(), Some(&"hello")); assert_eq!(queue.peek(), Some(&0)); assert_eq!(queue_2.peek(), Some(&1)); assert_eq!(queue_3.peek(), Some(&1)); } #[test] fn test_dequeue_mut() { let mut empty_queue: Queue = Queue::new(); let mut singleton_queue = queue!["hello"]; let mut queue = queue![0, 1, 2, 3]; let mut queue_2 = Queue::new(); queue_2.enqueue_mut(0); queue_2.enqueue_mut(1); queue_2.dequeue_mut(); queue_2.enqueue_mut(2); queue_2.enqueue_mut(3); let mut queue_3 = Queue::new(); queue_3.enqueue_mut(0); queue_3.enqueue_mut(1); queue_3.enqueue_mut(2); queue_3.enqueue_mut(3); queue_3.dequeue_mut(); empty_queue.dequeue_mut(); assert!(empty_queue.is_empty()); singleton_queue.dequeue_mut(); assert_eq!(singleton_queue.peek(), None); queue.dequeue_mut(); assert_eq!(queue.peek(), Some(&1)); queue_2.dequeue_mut(); assert_eq!(queue_2.peek(), Some(&2)); queue_3.dequeue_mut(); assert_eq!(queue_3.peek(), Some(&2)); } #[test] fn test_dequeue_mut_maintains_len() { let mut queue = queue![0, 1, 2, 3]; let mut queue_2 = Queue::new(); queue_2.enqueue_mut(0); queue_2.enqueue_mut(1); queue_2.dequeue_mut(); queue_2.enqueue_mut(2); queue_2.enqueue_mut(3); let mut queue_3 = Queue::new(); queue_3.enqueue_mut(0); queue_3.enqueue_mut(1); queue_3.enqueue_mut(2); queue_3.enqueue_mut(3); queue_3.dequeue_mut(); assert_eq!(queue.len(), 4); queue.dequeue_mut(); assert_eq!(queue.len(), 3); assert_eq!(queue_2.len(), 3); queue_2.dequeue_mut(); assert_eq!(queue_2.len(), 2); assert_eq!(queue_3.len(), 3); queue_3.dequeue_mut(); assert_eq!(queue_3.len(), 2); } #[test] fn test_dequeue() { let empty_queue: Queue = Queue::new(); let singleton_queue = Queue::new().enqueue("hello"); let queue = Queue::new().enqueue(0).enqueue(1).enqueue(2).enqueue(3); let queue_2 = Queue::new().enqueue(0).enqueue(1).dequeue().unwrap().enqueue(2).enqueue(3); let queue_3 = Queue::new().enqueue(0).enqueue(1).enqueue(2).enqueue(3).dequeue().unwrap(); assert!(empty_queue.dequeue().is_none()); assert_eq!(singleton_queue.dequeue().unwrap().peek(), None); assert_eq!(queue.dequeue().unwrap().peek(), Some(&1)); assert_eq!(queue_2.dequeue().unwrap().peek(), Some(&2)); assert_eq!(queue_3.dequeue().unwrap().peek(), Some(&2)); assert_eq!(queue.len(), 4); assert_eq!(queue.dequeue().unwrap().len(), 3); assert_eq!(queue_2.len(), 3); assert_eq!(queue_2.dequeue().unwrap().len(), 2); assert_eq!(queue_3.len(), 3); assert_eq!(queue_3.dequeue().unwrap().len(), 2); } #[test] fn test_from_iterator() { let vec: Vec = vec![10, 11, 12, 13]; let queue: Queue = vec.iter().copied().collect(); assert!(vec.iter().eq(queue.iter())); } #[test] fn test_default() { let queue: Queue = Queue::default(); assert_eq!(queue.peek(), None); assert!(queue.is_empty()); } #[test] fn test_display() { let empty_queue: Queue = Queue::new(); let singleton_queue = queue!["hello"]; let queue = queue![0, 1, 2, 3]; assert_eq!(format!("{}", empty_queue), "Queue()"); assert_eq!(format!("{}", singleton_queue), "Queue(hello)"); assert_eq!(format!("{}", queue), "Queue(0, 1, 2, 3)"); } #[test] fn test_eq() { let queue_1 = queue!["a", "a"]; let queue_1_prime = queue!["a", "a"]; let queue_2 = queue!["a", "b"]; assert_ne!(queue_1, queue_2); assert_eq!(queue_1, queue_1); assert_eq!(queue_1, queue_1_prime); assert_eq!(queue_2, queue_2); } #[test] fn test_eq_pointer_kind_consistent() { let queue_a = queue!["a"]; let queue_a_sync = queue_sync!["a"]; let queue_b = queue!["b"]; let queue_b_sync = queue_sync!["b"]; assert!(queue_a == queue_a_sync); assert!(queue_a != queue_b_sync); assert!(queue_b == queue_b_sync); } #[test] fn test_partial_ord() { let queue_1 = queue!["a"]; let queue_1_prime = queue!["a"]; let queue_2 = queue!["b"]; let queue_3 = queue![0.0]; let queue_4 = queue![core::f32::NAN]; assert_eq!(queue_1.partial_cmp(&queue_1_prime), Some(Ordering::Equal)); assert_eq!(queue_1.partial_cmp(&queue_2), Some(Ordering::Less)); assert_eq!(queue_2.partial_cmp(&queue_1), Some(Ordering::Greater)); assert_eq!(queue_3.partial_cmp(&queue_4), None); } #[test] fn test_ord() { let queue_1 = queue!["a"]; let queue_1_prime = queue!["a"]; let queue_2 = queue!["b"]; assert_eq!(queue_1.cmp(&queue_1_prime), Ordering::Equal); assert_eq!(queue_1.cmp(&queue_2), Ordering::Less); assert_eq!(queue_2.cmp(&queue_1), Ordering::Greater); } #[test] fn test_ord_pointer_kind_consistent() { let queue_a = queue!["a"]; let queue_a_sync = queue_sync!["a"]; let queue_b = queue!["b"]; let queue_b_sync = queue_sync!["b"]; assert!(queue_a <= queue_a_sync); assert!(queue_a < queue_b_sync); assert!(queue_b >= queue_b_sync); assert!(queue_a_sync >= queue_a); assert!(queue_b_sync > queue_a); assert!(queue_b_sync <= queue_b); } fn hash(queue: &Queue) -> u64 { #[allow(deprecated)] let mut hasher = core::hash::SipHasher::new(); queue.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let queue_1 = queue!["a"]; let queue_1_prime = queue!["a"]; let queue_2 = queue!["a", "b"]; assert_eq!(hash(&queue_1), hash(&queue_1)); assert_eq!(hash(&queue_1), hash(&queue_1_prime)); assert_ne!(hash(&queue_1), hash(&queue_2)); } #[test] fn test_hash_pointer_kind_consistent() { let queue = queue!["a"]; let queue_sync = queue_sync!["a"]; assert_eq!(hash(&queue), hash(&queue_sync)); } #[test] fn test_clone() { let queue = queue!["hello", "there"]; let clone = queue.clone(); assert!(clone.iter().eq(queue.iter())); assert_eq!(clone.len(), queue.len()); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let queue: Queue = queue![5, 6, 7, 8]; let encoded = serialize(&queue).unwrap(); let decoded: Queue = deserialize(&encoded).unwrap(); assert_eq!(queue, decoded); } rpds/src/queue/mod.rs0000644000175000017500000002357014661133735015560 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::List; use alloc::vec::Vec; use archery::*; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::Display; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; // TODO Use impl trait instead of this when available. type IterPtr<'a, T, P> = core::iter::Chain, LazilyReversedListIter<'a, T, P>>; pub type Iter<'a, T, P> = core::iter::Map, fn(&SharedPointer) -> &T>; /// Creates a [`Queue`](crate::Queue) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let q = Queue::new() /// .enqueue(1) /// .enqueue(2) /// .enqueue(3); /// /// assert_eq!(queue![1, 2, 3], q); /// ``` #[macro_export] macro_rules! queue { ($($e:expr),*) => { { #[allow(unused_mut)] let mut q = $crate::Queue::new(); $( q.enqueue_mut($e); )* q } }; } /// Creates a [`Queue`](crate::Queue) that implements `Sync`, containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let q = Queue::new_sync() /// .enqueue(1) /// .enqueue(2) /// .enqueue(3); /// /// assert_eq!(queue_sync![1, 2, 3], q); /// /// fn is_sync() -> impl Sync { /// queue_sync![0, 1, 3] /// } /// ``` #[macro_export] macro_rules! queue_sync { ($($e:expr),*) => { { #[allow(unused_mut)] let mut q = $crate::Queue::new_sync(); $( q.enqueue_mut($e); )* q } }; } /// A persistent queue with structural sharing. /// /// # Complexity /// /// Let *n* be the number of elements in the queue. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:--------------------- | -------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `enqueue()` | Θ(1) | Θ(1) | /// | `dequeue()` | Θ(1) | Θ(n) | /// | `dequeue()` amortized | Θ(1) | Θ(1) | /// | `peek()` | Θ(1) | Θ(1) | /// | `len()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(1) | Θ(1) | /// | iterator step | Θ(1) | Θ(n) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This queue is implemented as described in /// [Immutability in C# Part Four: An Immutable Queue](https://goo.gl/hWyMuS). #[derive(Debug)] pub struct Queue where P: SharedPointerKind, { in_list: List, out_list: List, } pub type QueueSync = Queue; impl QueueSync { #[must_use] pub fn new_sync() -> QueueSync { Queue::new_with_ptr_kind() } } impl Queue { #[must_use] pub fn new() -> Queue { Queue::new_with_ptr_kind() } } impl Queue where P: SharedPointerKind, { #[must_use] pub fn new_with_ptr_kind() -> Queue { Queue { in_list: List::new_with_ptr_kind(), out_list: List::new_with_ptr_kind() } } #[must_use] pub fn peek(&self) -> Option<&T> { if !self.out_list.is_empty() { self.out_list.first() } else { self.in_list.last() } } #[must_use] pub fn dequeue(&self) -> Option> { let mut new_queue = self.clone(); if new_queue.dequeue_mut() { Some(new_queue) } else { None } } pub fn dequeue_mut(&mut self) -> bool { if !self.out_list.is_empty() { self.out_list.drop_first_mut(); true } else if !self.in_list.is_empty() { core::mem::swap(&mut self.in_list, &mut self.out_list); self.out_list.reverse_mut(); self.out_list.drop_first_mut(); true } else { false } } #[must_use] pub fn enqueue(&self, v: T) -> Queue { let mut new_queue = self.clone(); new_queue.enqueue_mut(v); new_queue } pub fn enqueue_mut(&mut self, v: T) { self.in_list.push_front_mut(v); } #[must_use] #[inline] pub fn len(&self) -> usize { self.in_list.len() + self.out_list.len() } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn iter(&self) -> Iter<'_, T, P> { self.iter_ptr().map(|v| v.borrow()) } fn iter_ptr(&self) -> IterPtr<'_, T, P> { self.out_list.iter_ptr().chain(LazilyReversedListIter::new(&self.in_list)) } } impl Default for Queue where P: SharedPointerKind, { fn default() -> Queue { Queue::new_with_ptr_kind() } } impl PartialEq> for Queue where P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &Queue) -> bool { self.len() == other.len() && self.iter().eq(other.iter()) } } impl Eq for Queue where P: SharedPointerKind {} impl, P, PO> PartialOrd> for Queue where P: SharedPointerKind, PO: SharedPointerKind, { fn partial_cmp(&self, other: &Queue) -> Option { self.iter().partial_cmp(other.iter()) } } impl Ord for Queue where P: SharedPointerKind, { fn cmp(&self, other: &Queue) -> Ordering { self.iter().cmp(other.iter()) } } impl Hash for Queue where P: SharedPointerKind, { fn hash(&self, state: &mut H) { // Add the hash of length so that if two collections are added one after the other it // doesn't hash to the same thing as a single collection with the same elements in the same // order. self.len().hash(state); for e in self { e.hash(state); } } } impl Clone for Queue where P: SharedPointerKind, { fn clone(&self) -> Queue { Queue { in_list: self.in_list.clone(), out_list: self.out_list.clone() } } } impl Display for Queue where P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("Queue(")?; for v in self { if !first { fmt.write_str(", ")?; } v.fmt(fmt)?; first = false; } fmt.write_str(")") } } impl<'a, T, P> IntoIterator for &'a Queue where P: SharedPointerKind, { type Item = &'a T; type IntoIter = Iter<'a, T, P>; fn into_iter(self) -> Iter<'a, T, P> { self.iter() } } impl FromIterator for Queue where P: SharedPointerKind, { fn from_iter>(into_iter: I) -> Queue { Queue { out_list: List::from_iter(into_iter), in_list: List::new_with_ptr_kind() } } } pub enum LazilyReversedListIter<'a, T: 'a, P> where P: SharedPointerKind, { Uninitialized { list: &'a List }, Initialized { vec: Vec<&'a SharedPointer>, current: Option }, } impl<'a, T, P> LazilyReversedListIter<'a, T, P> where P: SharedPointerKind, { fn new(list: &List) -> LazilyReversedListIter<'_, T, P> { LazilyReversedListIter::Uninitialized { list } } } impl<'a, T, P> Iterator for LazilyReversedListIter<'a, T, P> where P: SharedPointerKind, { type Item = &'a SharedPointer; fn next(&mut self) -> Option<&'a SharedPointer> { match self { LazilyReversedListIter::Uninitialized { list } => { let len = list.len(); let mut vec: Vec<&'a SharedPointer> = Vec::with_capacity(len); for v in list.iter_ptr() { vec.push(v); } *self = LazilyReversedListIter::Initialized { vec, current: if len > 0 { Some(len - 1) } else { None }, }; self.next() } LazilyReversedListIter::Initialized { ref vec, ref mut current } => { let v = current.map(|i| vec[i]); *current = match *current { Some(0) => None, Some(i) => Some(i - 1), None => None, }; v } } } fn size_hint(&self) -> (usize, Option) { let len = match self { LazilyReversedListIter::Uninitialized { list } => list.len(), LazilyReversedListIter::Initialized { current: Some(i), .. } => i + 1, LazilyReversedListIter::Initialized { current: None, .. } => 0, }; (len, Some(len)) } } impl<'a, T, P> ExactSizeIterator for LazilyReversedListIter<'a, T, P> where P: SharedPointerKind {} #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer}; use ::serde::ser::{Serialize, Serializer}; impl Serialize for Queue where T: Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { serializer.collect_seq(self) } } impl<'de, T, P> Deserialize<'de> for Queue where T: Deserialize<'de>, P: SharedPointerKind, { fn deserialize>(deserializer: D) -> Result, D::Error> { Deserialize::deserialize(deserializer) .map(|list| Queue { out_list: list, in_list: List::new_with_ptr_kind() }) } } } #[cfg(test)] mod test; rpds/src/map/0000775000175000017500000000000014661133735014057 5ustar jamespagejamespagerpds/src/map/red_black_tree_map/0000775000175000017500000000000014661133735017641 5ustar jamespagejamespagerpds/src/map/red_black_tree_map/test.rs0000644000175000017500000017053314661133735021175 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use alloc::vec::Vec; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(RedBlackTreeMapSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_red_black_tree_map_sync_is_send_and_sync() -> impl Send + Sync { rbt_map_sync!(0 => 0) } #[derive(Debug)] enum InvariantViolation { SizeConsistency, BinarySearch, BlackRoot, RedNodeBlackChildren, BlackHeightBalanced, } impl Node where P: SharedPointerKind, { fn count(&self) -> usize { 1 + self.left.as_ref().map_or(0, |l| l.count()) + self.right.as_ref().map_or(0, |r| r.count()) } fn is_black_height_balanced(&self) -> bool { fn black_height(node: &Node) -> Result { let bheight_left = node.left.as_ref().map_or(Ok(0), |l| black_height(l))?; let bheight_right = node.right.as_ref().map_or(Ok(0), |r| black_height(r))?; if bheight_left == bheight_right { let bheight = bheight_right; Ok(bheight + usize::from(node.color == Color::Black)) } else { Err(()) } } black_height(self).is_ok() } fn red_nodes_have_black_children(&self) -> bool { let self_ok = if self.color == Color::Red { self.left.as_ref().map_or(Color::Black, |l| l.color) == Color::Black && self.right.as_ref().map_or(Color::Black, |r| r.color) == Color::Black } else { true }; self_ok && self.left.as_ref().map_or(true, |l| l.red_nodes_have_black_children()) && self.right.as_ref().map_or(true, |r| r.red_nodes_have_black_children()) } fn has_binary_search_property(&self) -> bool where K: Clone + Ord, { fn go( node: &Node, last: &mut Option, ) -> bool { let ok_left = node.left.as_ref().map_or(true, |l| go(l, last)); let new_last = node.entry.key.clone(); let ok_node = last.as_ref().map_or(true, |l| *l < new_last); *last = Some(new_last); let ok_right = node.right.as_ref().map_or(true, |r| go(r, last)); ok_left && ok_node && ok_right } let mut last: Option = None; go(self, &mut last) } fn make_black(self) -> Node { let mut node = self; node.color = Color::Black; node } fn make_red(self) -> Node { let mut node = self; node.color = Color::Red; node } } impl RedBlackTreeMap where K: Ord + Clone, { fn check_consistent(&self) -> Result<(), InvariantViolation> { if !self.root.as_ref().map_or(true, |r| r.has_binary_search_property()) { Result::Err(InvariantViolation::BinarySearch) } else if !self.root.as_ref().map_or(true, |r| r.red_nodes_have_black_children()) { Result::Err(InvariantViolation::RedNodeBlackChildren) } else if !self.root.as_ref().map_or(true, |r| r.is_black_height_balanced()) { Result::Err(InvariantViolation::BlackHeightBalanced) } else if !self.root.as_ref().map_or(true, |r| r.color == Color::Black) { Result::Err(InvariantViolation::BlackRoot) } else if self.root.as_ref().map_or(0, |r| r.count()) != self.size() { Result::Err(InvariantViolation::SizeConsistency) } else { Ok(()) } } } impl PartialEq for Node where K: PartialEq, V: PartialEq, P: SharedPointerKind, { fn eq(&self, other: &Node) -> bool { self.entry == other.entry && self.color == other.color && self.left == other.left && self.right == other.right } } impl Eq for Node where P: SharedPointerKind {} mod node { use super::*; use pretty_assertions::assert_eq; fn dummy_entry(v: T) -> Entry { Entry { key: v.clone(), value: v } } fn dummy_node(v: T) -> Node { Node { entry: SharedPointer::new(dummy_entry(v)), color: Color::Red, left: None, right: None, } } fn dummy_node_with_children( v: T, left: Option>, right: Option>, ) -> Node { Node { entry: SharedPointer::new(dummy_entry(v)), color: Color::Red, left: left.map(SharedPointer::new), right: right.map(SharedPointer::new), } } /// Returns the following tree: /// /// ```text /// ╭───╮ /// │ 1 │ /// ╰───╯ /// ╱ ╲ /// ╱ ╲ /// ╭───╮ ╭───╮ /// │ 0 │ │ 2 │ /// ╰───╯ ╰───╯ /// ╲ /// ╲ /// ╭───╮ /// │ 3 │ /// ╰───╯ /// ``` fn dummy_tree_0_1_2_3() -> Node { let node_0 = dummy_node(0); let node_3 = dummy_node(3); let node_2 = dummy_node_with_children(2, None, Some(node_3)); dummy_node_with_children(1, Some(node_0), Some(node_2)) } #[test] fn test_get() { let tree = dummy_tree_0_1_2_3(); assert_eq!(tree.get(&0).unwrap().value, 0); assert_eq!(tree.get(&1).unwrap().value, 1); assert_eq!(tree.get(&2).unwrap().value, 2); assert_eq!(tree.get(&3).unwrap().value, 3); assert_eq!(tree.get(&4), None); } #[test] fn test_get_mut() { let original = dummy_tree_0_1_2_3(); let mut tree = original.clone(); tree.get_mut(&2).unwrap().value = -2; tree.get_mut(&3).unwrap().value = -3; assert!(tree.get_mut(&4).is_none()); assert_eq!(original.get(&0).unwrap().value, 0); assert_eq!(original.get(&1).unwrap().value, 1); assert_eq!(original.get(&2).unwrap().value, 2); assert_eq!(original.get(&3).unwrap().value, 3); assert_eq!(original.get(&4), None); assert_eq!(tree.get(&0).unwrap().value, 0); assert_eq!(tree.get(&1).unwrap().value, 1); assert_eq!(tree.get(&2).unwrap().value, -2); assert_eq!(tree.get(&3).unwrap().value, -3); assert_eq!(tree.get(&4), None); } #[test] fn test_first() { let tree = dummy_tree_0_1_2_3(); assert_eq!(tree.first().key, 0); } #[test] fn test_last() { let tree = dummy_tree_0_1_2_3(); assert_eq!(tree.last().key, 3); } #[allow(clippy::too_many_lines)] #[test] fn test_balance() { // ╭────────────────────╮ // │ ┌───┐ │ // │ │ │ Red node │ // │ └───┘ │ // ┏━━━┓ │ │ // ┃ z ┃ │ ┏━━━┓ │ // ┗━━━┛ │ ┃ ┃ Black node │ // ╱ ╲ │ ┗━━━┛ │ // ┌───┐ d ╰────────────────────╯ // │ y │ Case 1 // └───┘ ╭──────────────────────────────────────────────────╮ // ╱ ╲ ╰────────────────────────────────────────────────╮ │ // ┌───┐ c │ │ // │ x │ │ │ // └───┘ │ │ // ╱ ╲ │ │ // a b │ │ // │ │ // │ │ // │ │ // ┏━━━┓ │ │ // ┃ z ┃ │ │ // ┗━━━┛ │ │ // ╱ ╲ │ │ // ┌───┐ d Case 2 │ │ // │ x │ ╭─────────────────────────────╲ │ │ // └───┘ ╰────────────────────────────╲ ╲ ╲ ╱ // ╱ ╲ ╲ ╲ // a ┌───┐ ╲ ╲ // │ y │ ╲ ╲ ┌───┐ // └───┘ ╲ ╲ │ y │ // ╱ ╲ ╲ ┃ └───┘ // b c ───┘ ╱ ╲ // ╱ ╲ // ┏━━━┓ ┏━━━┓ // ┃ x ┃ ┃ z ┃ // ┏━━━┓ ┗━━━┛ ┗━━━┛ // ┃ x ┃ ───┐ ╱ ╲ ╱ ╲ // ┗━━━┛ ╱ ┃ ╱ ╲ ╱ ╲ // ╱ ╲ ╱ ╱ a b c d // a ┌───┐ ╱ ╱ // │ z │ ╱ ╱ // └───┘ Case 3 ╱ ╱ ╱ ╲ // ╱ ╲ ╭────────────────────────────╱ ╱ │ │ // ┌───┐ d ╰─────────────────────────────╱ │ │ // │ y │ │ │ // └───┘ │ │ // ╱ ╲ │ │ // b c │ │ // │ │ // │ │ // │ │ // ┏━━━┓ │ │ // ┃ x ┃ │ │ // ┗━━━┛ │ │ // ╱ ╲ │ │ // a ┌───┐ Case 4 │ │ // │ y │ ╭────────────────────────────────────────────────┘ │ // └───┘ ╰──────────────────────────────────────────────────┘ // ╱ ╲ // b ┌───┐ // │ z │ // └───┘ // ╱ ╲ // c d let entry_x = SharedPointer::new(Entry::new('x', ())); let entry_y = SharedPointer::new(Entry::new('y', ())); let entry_z = SharedPointer::new(Entry::new('z', ())); let tree_a = SharedPointer::new(Node::new_black(Entry::new('a', ()))); let tree_b = SharedPointer::new(Node::new_black(Entry::new('b', ()))); let tree_c = SharedPointer::new(Node::new_black(Entry::new('c', ()))); let tree_d = SharedPointer::new(Node::new_black(Entry::new('d', ()))); let mut tree_case_1: Node<_, _, RcK> = Node { entry: SharedPointer::clone(&entry_z), color: Color::Black, left: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_y), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_x), color: Color::Red, left: Some(SharedPointer::clone(&tree_a)), right: Some(SharedPointer::clone(&tree_b)), })), right: Some(SharedPointer::clone(&tree_c)), })), right: Some(SharedPointer::clone(&tree_d)), }; let mut tree_case_2: Node<_, _, RcK> = Node { entry: SharedPointer::clone(&entry_z), color: Color::Black, left: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_x), color: Color::Red, left: Some(SharedPointer::clone(&tree_a)), right: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_y), color: Color::Red, left: Some(SharedPointer::clone(&tree_b)), right: Some(SharedPointer::clone(&tree_c)), })), })), right: Some(SharedPointer::clone(&tree_d)), }; let mut tree_case_3: Node<_, _, RcK> = Node { entry: SharedPointer::clone(&entry_x), color: Color::Black, left: Some(SharedPointer::clone(&tree_a)), right: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_z), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_y), color: Color::Red, left: Some(SharedPointer::clone(&tree_b)), right: Some(SharedPointer::clone(&tree_c)), })), right: Some(SharedPointer::clone(&tree_d)), })), }; let mut tree_case_4: Node<_, _, RcK> = Node { entry: SharedPointer::clone(&entry_x), color: Color::Black, left: Some(SharedPointer::clone(&tree_a)), right: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_y), color: Color::Red, left: Some(SharedPointer::clone(&tree_b)), right: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_z), color: Color::Red, left: Some(SharedPointer::clone(&tree_c)), right: Some(SharedPointer::clone(&tree_d)), })), })), }; let mut tree_none_of_the_above: Node<_, _, RcK> = Node { entry: SharedPointer::clone(&entry_z), color: Color::Black, left: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_y), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_x), color: Color::Black, left: Some(SharedPointer::clone(&tree_a)), right: Some(SharedPointer::clone(&tree_b)), })), right: Some(SharedPointer::clone(&tree_c)), })), right: Some(SharedPointer::clone(&tree_d)), }; let mut tree_balanced: Node<_, _, RcK> = Node { entry: SharedPointer::clone(&entry_y), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_x), color: Color::Black, left: Some(SharedPointer::clone(&tree_a)), right: Some(SharedPointer::clone(&tree_b)), })), right: Some(SharedPointer::new(Node { entry: SharedPointer::clone(&entry_z), color: Color::Black, left: Some(SharedPointer::clone(&tree_c)), right: Some(SharedPointer::clone(&tree_d)), })), }; tree_case_1.balance(); assert_eq!(tree_case_1, tree_balanced.clone()); tree_case_2.balance(); assert_eq!(tree_case_2, tree_balanced.clone()); tree_case_3.balance(); assert_eq!(tree_case_3, tree_balanced.clone()); tree_case_4.balance(); assert_eq!(tree_case_4, tree_balanced.clone()); let tree_none_of_the_above_original = tree_none_of_the_above.clone(); tree_none_of_the_above.balance(); assert_eq!(tree_none_of_the_above, tree_none_of_the_above_original); let tree_balanced_original = tree_balanced.clone(); tree_balanced.balance(); assert_eq!(tree_balanced, tree_balanced_original); } #[test] fn test_insert() { let mut node = None; let is_new_key = Node::insert(&mut node, 0, 1); let expected_node: Node<_, _, RcK> = Node::new_black(Entry::new(0, 1)); assert!(is_new_key); assert_eq!(node.as_ref().map(Borrow::borrow), Some(&expected_node)); let is_new_key = Node::insert(&mut node, 0, 2); let expected_node: Node<_, _, RcK> = Node::new_black(Entry::new(0, 2)); assert!(!is_new_key); assert_eq!(node.as_ref().map(Borrow::borrow), Some(&expected_node)); let is_new_key = Node::insert(&mut node, 10, 3); let expected_node: Node<_, _, RcK> = Node { entry: SharedPointer::new(Entry::new(0, 2)), color: Color::Black, left: None, right: Some(SharedPointer::new(Node { entry: SharedPointer::new(Entry::new(10, 3)), color: Color::Red, left: None, right: None, })), }; assert!(is_new_key); assert_eq!(node.as_ref().map(Borrow::borrow), Some(&expected_node)); let is_new_key = Node::insert(&mut node, 10, 4); let expected_node: Node<_, _, RcK> = Node { entry: SharedPointer::new(Entry::new(0, 2)), color: Color::Black, left: None, right: Some(SharedPointer::new(Node { entry: SharedPointer::new(Entry::new(10, 4)), color: Color::Red, left: None, right: None, })), }; assert!(!is_new_key); assert_eq!(node.as_ref().map(Borrow::borrow), Some(&expected_node)); let is_new_key = Node::insert(&mut node, 5, 5); // It is going to get rebalanced (by case 3). let expected_node: Node<_, _, RcK> = Node { entry: SharedPointer::new(Entry::new(5, 5)), color: Color::Black, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(Entry::new(0, 2)), color: Color::Black, left: None, right: None, })), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(Entry::new(10, 4)), color: Color::Black, left: None, right: None, })), }; assert!(is_new_key); assert_eq!(node.as_ref().map(Borrow::borrow), Some(&expected_node)); let is_new_key = Node::insert(&mut node, 0, 1); // It is going to get rebalanced (by case 3). let expected_node: Node<_, _, RcK> = Node { entry: SharedPointer::new(Entry::new(5, 5)), color: Color::Black, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(Entry::new(0, 1)), color: Color::Black, left: None, right: None, })), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(Entry::new(10, 4)), color: Color::Black, left: None, right: None, })), }; assert!(!is_new_key); assert_eq!(node.as_ref().map(Borrow::borrow), Some(&expected_node)); } #[allow(clippy::too_many_lines)] #[test] fn test_remove_fuse() { let mut node = dummy_node(""); assert!(!Node::remove_fuse(&mut node, None, None)); let right = dummy_node("x"); let expected_node = right.clone(); assert!(Node::remove_fuse(&mut node, None, Some(SharedPointer::new(right)))); assert_eq!(node, expected_node); let left = dummy_node("x"); let expected_node = left.clone(); assert!(Node::remove_fuse(&mut node, Some(SharedPointer::new(left)), None)); assert_eq!(node, expected_node); let left = Node { entry: SharedPointer::new(dummy_entry("a")), color: Color::Black, left: None, right: None, }; let right = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: None, right: Some(SharedPointer::new(dummy_node("c"))), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(left.clone())), right: Some(SharedPointer::new(dummy_node("c"))), }; assert!(Node::remove_fuse( &mut node, Some(SharedPointer::new(left)), Some(SharedPointer::new(right)) )); assert_eq!(node, expected_node); let left = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: None, }; let right = Node { entry: SharedPointer::new(dummy_entry("c")), color: Color::Black, left: None, right: None, }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(right.clone())), }; assert!(Node::remove_fuse( &mut node, Some(SharedPointer::new(left)), Some(SharedPointer::new(right)) )); assert_eq!(node, expected_node); let left = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: None, }; let right = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("c").make_red())), right: Some(SharedPointer::new(dummy_node("d"))), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("c")), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: None, })), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: None, right: Some(SharedPointer::new(dummy_node("d"))), })), }; assert!(Node::remove_fuse( &mut node, Some(SharedPointer::new(left)), Some(SharedPointer::new(right)) )); assert_eq!(node, expected_node); let left = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: None, }; let right = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("c").make_black())), right: Some(SharedPointer::new(dummy_node("d"))), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("c").make_black())), right: Some(SharedPointer::new(dummy_node("d"))), })), }; assert!(Node::remove_fuse( &mut node, Some(SharedPointer::new(left)), Some(SharedPointer::new(right)) )); assert_eq!(node, expected_node); let left = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: None, }; let right = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("c").make_red())), right: Some(SharedPointer::new(dummy_node("d"))), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("c")), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: None, })), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: None, right: Some(SharedPointer::new(dummy_node("d"))), })), }; assert!(Node::remove_fuse( &mut node, Some(SharedPointer::new(left)), Some(SharedPointer::new(right)) )); assert_eq!(node, expected_node); let left = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: None, }; let right = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("c").make_black())), right: Some(SharedPointer::new(dummy_node("d"))), }; let expected_node = { let mut n = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("c").make_black())), right: Some(SharedPointer::new(dummy_node("d"))), })), }; n.remove_balance_left(); n }; assert!(Node::remove_fuse( &mut node, Some(SharedPointer::new(left)), Some(SharedPointer::new(right)) )); assert_eq!(node, expected_node); } #[test] fn test_remove_balance() { let mut node = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, // Irrelevant left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("z")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("c"))), right: Some(SharedPointer::new(dummy_node("d"))), })), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("z")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("c"))), right: Some(SharedPointer::new(dummy_node("d"))), })), }; node.remove_balance(); assert_eq!(node, expected_node); } #[test] fn test_remove_balance_left() { let bl = Node { entry: SharedPointer::new(dummy_entry("bl")), color: Color::Black, left: None, right: None, }; let mut node = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, // Irrelevant left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), right: Some(SharedPointer::new(dummy_node("c"))), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), right: Some(SharedPointer::new(dummy_node("c"))), }; node.remove_balance_left(); assert_eq!(node, expected_node); let mut node = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, // Irrelevant left: Some(SharedPointer::new(bl.clone())), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), }; let expected_node = { let mut n = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(bl.clone())), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), }; n.remove_balance(); n }; node.remove_balance_left(); assert_eq!(node, expected_node); let mut node = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, // Irrelevant left: Some(SharedPointer::new(bl.clone())), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("z")), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), right: Some(SharedPointer::new(dummy_node("c").make_black())), })), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(bl.clone())), right: Some(SharedPointer::new(dummy_node("a"))), })), right: Some(SharedPointer::new({ let mut n = Node { entry: SharedPointer::new(dummy_entry("z")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("b"))), right: Some(SharedPointer::new(dummy_node("c").make_red())), }; n.remove_balance(); n })), }; node.remove_balance_left(); assert_eq!(node, expected_node); } #[test] fn test_remove_balance_right() { let bl = Node { entry: SharedPointer::new(dummy_entry("bl")), color: Color::Black, left: None, right: None, }; let mut node = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, // Irrelevant left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("b"))), right: Some(SharedPointer::new(dummy_node("c"))), })), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("b"))), right: Some(SharedPointer::new(dummy_node("c"))), })), }; node.remove_balance_right(); assert_eq!(node, expected_node); let mut node = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, // Irrelevant left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), right: Some(SharedPointer::new(bl.clone())), }; let expected_node = { let mut n = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a"))), right: Some(SharedPointer::new(dummy_node("b"))), })), right: Some(SharedPointer::new(bl.clone())), }; n.remove_balance(); n }; node.remove_balance_right(); assert_eq!(node, expected_node); let mut node = Node { entry: SharedPointer::new(dummy_entry("z")), color: Color::Black, // Irrelevant left: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Red, left: Some(SharedPointer::new(dummy_node("a").make_black())), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("b"))), right: Some(SharedPointer::new(dummy_node("c"))), })), })), right: Some(SharedPointer::new(bl.clone())), }; let expected_node = Node { entry: SharedPointer::new(dummy_entry("y")), color: Color::Red, left: Some(SharedPointer::new({ let mut n = Node { entry: SharedPointer::new(dummy_entry("x")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("a").make_red())), right: Some(SharedPointer::new(dummy_node("b"))), }; n.remove_balance(); n })), right: Some(SharedPointer::new(Node { entry: SharedPointer::new(dummy_entry("z")), color: Color::Black, left: Some(SharedPointer::new(dummy_node("c"))), right: Some(SharedPointer::new(bl.clone())), })), }; node.remove_balance_right(); assert_eq!(node, expected_node); } } mod internal { use super::*; use alloc::vec::Vec; use pretty_assertions::assert_eq; fn insert_test(values: &[u32]) { let mut map = RedBlackTreeMap::new(); for (i, &v) in values.iter().enumerate() { map.insert_mut(v, 2 * v); let other_v = values[i / 2]; assert_eq!(map.get(&v), Some(&(2 * v))); assert_eq!(map.get(&other_v), Some(&(2 * other_v))); if let Err(error) = map.check_consistent() { panic!( "Consistency error in red-black tree ({:?}). Insertions: {:?}", error, &values[0..=i] ); } } } #[test] fn test_insert_sorted() { let vec: Vec = (0..4092).collect(); insert_test(&vec); } #[test] fn test_insert() { use rand::rngs::StdRng; use rand::seq::SliceRandom; use rand::SeedableRng; let limit = 25_000; let seed: [u8; 32] = [ 24, 73, 23, 5, 34, 57, 253, 46, 245, 73, 23, 155, 137, 250, 46, 46, 217, 3, 55, 157, 137, 250, 46, 46, 217, 3, 55, 157, 34, 135, 34, 123, ]; let mut rng: StdRng = SeedableRng::from_seed(seed); let mut permutation: [u32; 64] = { let mut p: [u32; 64] = [0; 64]; for i in 0..64 { p[i as usize] = i; } p }; for _ in 0..limit { permutation.shuffle(&mut rng); insert_test(&permutation); } } fn remove_test(values_insert: &[u32], values_remove: &[u32]) { let mut map = RedBlackTreeMap::new(); for &v in values_insert { map.insert_mut(v, 2 * v); } for (i, v) in values_remove.iter().enumerate() { map.remove_mut(v); assert!(!map.contains_key(v)); if let Err(error) = map.check_consistent() { panic!("Consistency error in red-black tree ({:?}). Insertions: {:?}. Removals: {:?}", error, &values_insert, &values_remove[0..=i]); } } } #[test] fn test_remove_sorted() { let vec: Vec = (0..4092).collect(); let vec_rev: Vec = (0..4092).rev().collect(); remove_test(&vec, &vec); remove_test(&vec, &vec_rev); } #[test] fn test_remove() { use rand::rngs::StdRng; use rand::seq::SliceRandom; use rand::SeedableRng; let limit = 25_000; let seed: [u8; 32] = [ 24, 73, 23, 5, 34, 57, 253, 46, 245, 73, 23, 155, 137, 250, 46, 46, 217, 3, 55, 157, 137, 250, 46, 46, 217, 3, 55, 157, 34, 135, 34, 123, ]; let mut rng: StdRng = SeedableRng::from_seed(seed); let mut permutation_insert: [u32; 64] = { let mut p: [u32; 64] = [0; 64]; for i in 0..64 { p[i as usize] = i; } p }; let mut permutation_remove: [u32; 64] = permutation_insert; for _ in 0..limit { permutation_insert.shuffle(&mut rng); permutation_remove.shuffle(&mut rng); remove_test(&permutation_insert, &permutation_remove); } } } mod iter { use super::*; use alloc::vec::Vec; use pretty_assertions::assert_eq; #[test] fn test_lg_floor() { assert_eq!(iter_utils::lg_floor(1), 0); assert_eq!(iter_utils::lg_floor(2), 1); assert_eq!(iter_utils::lg_floor(3), 1); assert_eq!(iter_utils::lg_floor(4), 2); assert_eq!(iter_utils::lg_floor(5), 2); assert_eq!(iter_utils::lg_floor(7), 2); assert_eq!(iter_utils::lg_floor(8), 3); assert_eq!(iter_utils::lg_floor(9), 3); assert_eq!(iter_utils::lg_floor(15), 3); assert_eq!(iter_utils::lg_floor(16), 4); assert_eq!(iter_utils::lg_floor(17), 4); } #[test] fn test_iter_empty() { let map: RedBlackTreeMap = RedBlackTreeMap::new(); for _ in map.iter() { panic!("iterator should be empty"); } } #[test] fn test_iter_empty_backwards() { let map: RedBlackTreeMap = RedBlackTreeMap::new(); for _ in map.iter().rev() { panic!("iterator should be empty"); } } #[test] fn test_iter_big_map() { let limit = 512; let mut map = RedBlackTreeMap::new(); let mut expected = 0; let mut left = limit; for i in (0..limit).rev() { map = map.insert(i, 2 * i); } for (k, v) in map.iter() { left -= 1; assert!(left >= 0); assert_eq!(*k, expected); assert_eq!(*v, 2 * expected); expected += 1; } assert_eq!(left, 0); } #[test] fn test_iter_big_map_backwards() { let limit = 512; let mut map = RedBlackTreeMap::new(); let mut expected = limit - 1; let mut left = limit; for i in 0..limit { map = map.insert(i, 2 * i); } for (k, v) in map.iter().rev() { left -= 1; assert!(left >= 0); assert_eq!(*k, expected); assert_eq!(*v, 2 * expected); expected -= 1; } assert_eq!(left, 0); } #[test] fn test_iter_both_directions() { let map = rbt_map![ 0 => 10, 1 => 11, 2 => 12, 3 => 13, 4 => 14, 5 => 15 ]; let mut iterator = map.iter(); assert_eq!(iterator.next(), Some((&0, &10))); assert_eq!(iterator.next_back(), Some((&5, &15))); assert_eq!(iterator.next_back(), Some((&4, &14))); assert_eq!(iterator.next(), Some((&1, &11))); assert_eq!(iterator.next(), Some((&2, &12))); assert_eq!(iterator.next_back(), Some((&3, &13))); assert_eq!(iterator.next_back(), None); assert_eq!(iterator.next(), None); } #[test] fn test_iter_size_hint() { let map = rbt_map![ 0 => 10, 1 => 11, 2 => 12 ]; let mut iterator = map.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next_back(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next_back(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_iter_sorted() { let map = rbt_map![ 5 => (), 6 => (), 2 => (), 1 => () ]; let mut iterator = map.iter(); assert_eq!(iterator.next(), Some((&1, &()))); assert_eq!(iterator.next(), Some((&2, &()))); assert_eq!(iterator.next(), Some((&5, &()))); assert_eq!(iterator.next(), Some((&6, &()))); assert_eq!(iterator.next(), None); } #[test] fn test_iter_keys() { let map = rbt_map![ 0 => 10, 1 => 11, 2 => 12 ]; let mut iter = map.keys(); assert_eq!(iter.next(), Some(&0)); assert_eq!(iter.next(), Some(&1)); assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), None); } #[test] fn test_iter_values() { let map = rbt_map![ 10 => 0, 11 => 1, 12 => 2 ]; let mut iter = map.values(); assert_eq!(iter.next(), Some(&0)); assert_eq!(iter.next(), Some(&1)); assert_eq!(iter.next(), Some(&2)); assert_eq!(iter.next(), None); } #[test] fn test_into_iterator() { let map = rbt_map![ 0 => 0, 1 => 2, 2 => 4, 3 => 6 ]; let mut left = 4; for (expected, (k, v)) in map.into_iter().enumerate() { left -= 1; assert!(left >= 0); assert_eq!(*k, expected); assert_eq!(*v, 2 * expected); } assert_eq!(left, 0); } #[test] fn test_range() { use core::ops::Bound::*; fn cmp + Clone>( map: &RedBlackTreeMap, range: RB, expected: &[(i32, i32)], ) { assert_eq!( map.range(range.clone()).map(|(k, v)| (*k, *v)).collect::>(), expected ); assert_eq!( map.range(range).rev().map(|(k, v)| (*k, *v)).collect::>(), expected.iter().copied().rev().collect::>() ); } let map = rbt_map![ 0 => 0, 1 => 2, 2 => 4, 3 => 6 ]; cmp(&map, .., &[(0, 0), (1, 2), (2, 4), (3, 6)]); cmp(&map, 1.., &[(1, 2), (2, 4), (3, 6)]); cmp(&map, 1..3, &[(1, 2), (2, 4)]); cmp(&map, 1..=3, &[(1, 2), (2, 4), (3, 6)]); cmp(&map, ..3, &[(0, 0), (1, 2), (2, 4)]); cmp(&map, (Excluded(1), Included(3)), &[(2, 4), (3, 6)]); } #[test] fn test_range_empty() { let map = rbt_map![ 0 => 0, 1 => 2, 10 => 20, 11 => 22 ]; assert_eq!(map.range(1..1).next(), None); assert_eq!(map.range(3..10).next(), None); assert_eq!(map.range(..0).next(), None); assert_eq!(map.range(3..=9).next(), None); assert_eq!(map.range(13..).next(), None); } } #[test] fn test_macro_rbt_map() { let set_1 = RedBlackTreeMap::new().insert(1, 2); let set_1_2_3 = RedBlackTreeMap::new().insert(1, 2).insert(2, 3).insert(3, 4); assert_eq!(RedBlackTreeMap::::new(), rbt_map![]); assert_eq!(set_1, rbt_map![1 => 2]); assert_eq!(set_1_2_3, rbt_map![1 => 2, 2 => 3, 3 => 4]); } #[test] fn test_get_key_value() { let mut map = RedBlackTreeMap::new(); map = map.insert("foo", 4); assert_eq!(map.get_key_value("foo"), Some((&"foo", &4))); map = map.insert("bar", 2); assert_eq!(map.get_key_value("foo"), Some((&"foo", &4))); assert_eq!(map.get_key_value("bar"), Some((&"bar", &2))); } #[test] fn test_insert_simple() { let mut map = RedBlackTreeMap::new(); assert_eq!(map.size(), 0); map = map.insert("foo", 4); assert_eq!(map.size(), 1); assert_eq!(map.get("foo"), Some(&4)); map = map.insert("bar", 2); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); map = map.insert("baz", 12); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); map = map.insert("foo", 7); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&7)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); assert!(map.contains_key("baz")); } #[test] fn test_insert() { let mut map = RedBlackTreeMap::new(); // These are relatively small limits. We prefer to do a more hardcore test in the mutable // version. let limit = 5_000; let overwrite_limit = 1_000; for i in 0..limit { map = map.insert(i, -i); assert_eq!(map.size(), (i as usize) + 1); assert_eq!(map.get(&i), Some(&-i)); // Lets also check a previous value. let prev_key = i / 2; assert_eq!(map.get(&prev_key), Some(&-prev_key)); } // Now we test some overwrites. for i in 0..overwrite_limit { assert_eq!(map.get(&i), Some(&-i)); map = map.insert(i, 2 * i); assert_eq!(map.size(), limit as usize); assert_eq!(map.get(&i), Some(&(2 * i))); } } #[test] fn test_insert_mut_simple() { let mut map = RedBlackTreeMap::new(); assert_eq!(map.size(), 0); map.insert_mut("foo", 4); assert_eq!(map.size(), 1); assert_eq!(map.get("foo"), Some(&4)); map.insert_mut("bar", 2); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); map.insert_mut("baz", 12); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); map.insert_mut("foo", 7); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&7)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); assert!(map.contains_key("baz")); } #[test] fn test_insert_mut() { let mut map = RedBlackTreeMap::new(); let limit = 25_000; let overwrite_limit = 5_000; for i in 0..limit { map.insert_mut(i, -i); assert_eq!(map.size(), (i as usize) + 1); assert_eq!(map.get(&i), Some(&-i)); // Lets also check a previous value. let prev_key = i / 2; assert_eq!(map.get(&prev_key), Some(&-prev_key)); } // Now we test some overwrites. for i in 0..overwrite_limit { assert_eq!(map.get(&i), Some(&-i)); map.insert_mut(i, 2 * i); assert_eq!(map.size(), limit as usize); assert_eq!(map.get(&i), Some(&(2 * i))); } } #[test] fn test_contains_key() { let map = rbt_map!["foo" => 7]; assert!(map.contains_key("foo")); assert!(!map.contains_key("baz")); } #[test] fn test_remove_simple() { let mut map = rbt_map![ "foo" => 4, "bar" => 12, "mumble" => 13, "baz" => 42 ]; let empty_map: RedBlackTreeMap = RedBlackTreeMap::new(); assert_eq!(empty_map.remove(&3), empty_map); assert_eq!(map.size(), 4); map = map.remove("not-there"); assert_eq!(map.size(), 4); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), Some(&13)); assert_eq!(map.get("baz"), Some(&42)); map = map.remove("mumble"); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), None); assert_eq!(map.get("baz"), Some(&42)); map = map.remove("foo"); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), None); map = map.remove("baz"); assert_eq!(map.size(), 1); assert_eq!(map.get("baz"), None); map = map.remove("bar"); assert_eq!(map.size(), 0); assert_eq!(map.get("bar"), None); } #[test] fn test_remove() { let mut map = RedBlackTreeMap::new(); // These are relatively small limits. We prefer to do a more hardcore test in the mutable // version. let limit = 5_000; for i in 0..limit { map = map.insert(i, -i); } // Now lets remove half of it. for i in (0..limit / 2).map(|i| 2 * i) { assert_eq!(map.get(&i), Some(&-i)); map = map.remove(&i); assert!(!map.contains_key(&i)); assert_eq!(map.size(), (limit - i / 2 - 1) as usize); // Also check than the previous one is ok. if i > 0 { assert_eq!(map.get(&(i - 1)), Some(&-(i - 1))); } } } #[test] fn test_remove_mut_simple() { let mut map = rbt_map![ "foo" => 4, "bar" => 12, "mumble" => 13, "baz" => 42 ]; assert_eq!(map.size(), 4); assert!(!map.remove_mut("not-there")); assert_eq!(map.size(), 4); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), Some(&13)); assert_eq!(map.get("baz"), Some(&42)); assert!(map.remove_mut("mumble")); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), None); assert_eq!(map.get("baz"), Some(&42)); assert!(map.remove_mut("foo")); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), None); assert!(map.remove_mut("baz")); assert_eq!(map.size(), 1); assert_eq!(map.get("baz"), None); assert!(map.remove_mut("bar")); assert_eq!(map.size(), 0); assert_eq!(map.get("bar"), None); } #[test] fn test_remove_mut() { let mut map = RedBlackTreeMap::new(); let limit = 25_000; for i in 0..limit { map.insert_mut(i, -i); } // Now lets remove half of it. for i in (0..limit / 2).map(|i| 2 * i) { assert_eq!(map.get(&i), Some(&-i)); map.remove_mut(&i); assert!(!map.contains_key(&i)); assert_eq!(map.size(), (limit - i / 2 - 1) as usize); // Also check than the previous one is ok. if i > 0 { assert_eq!(map.get(&(i - 1)), Some(&-(i - 1))); } } } #[test] fn test_first() { let map = rbt_map![5 => "hello", 12 => "there"]; assert_eq!(map.first(), Some((&5, &"hello"))); } #[test] fn test_last() { let map = rbt_map![5 => "hello", 12 => "there"]; assert_eq!(map.last(), Some((&12, &"there"))); } #[test] fn test_index() { let map = rbt_map![5 => "hello", 12 => "there"]; assert_eq!(map[&5], "hello"); assert_eq!(map[&12], "there"); } #[test] fn test_from_iterator() { let vec: Vec<(i32, &str)> = vec![(2, "two"), (5, "five")]; let map: RedBlackTreeMap = vec.iter().copied().collect(); let expected_map = rbt_map![2 => "two", 5 => "five"]; assert_eq!(map, expected_map); } #[test] fn test_default() { let map: RedBlackTreeMap = RedBlackTreeMap::default(); assert_eq!(map.size(), 0); assert!(map.is_empty()); } #[test] fn test_display() { let empty_map: RedBlackTreeMap = RedBlackTreeMap::new(); let singleton_map = rbt_map!["hi" => "hello"]; let map = rbt_map![5 => "hello", 12 => "there"]; assert_eq!(format!("{}", empty_map), "{}"); assert_eq!(format!("{}", singleton_map), "{hi: hello}"); assert_eq!(format!("{}", map), "{5: hello, 12: there}"); } #[test] fn test_eq() { let map_1 = rbt_map!["a" => 0xa, "b" => 0xb]; let map_1_prime = rbt_map!["a" => 0xa, "b" => 0xb]; let map_1_prime_2 = rbt_map!["a" => 0xa, "b" => 0xb, "b" => 0xb]; let map_2 = rbt_map!["a" => 0xa, "b" => 0xb + 1]; let map_3 = rbt_map!["a" => 0xa, "b" => 0xb + 1, "c" => 0xc]; assert_eq!(map_1, map_1_prime); assert_eq!(map_1, map_1_prime_2); assert_eq!(map_1, map_1); assert_eq!(map_2, map_2); // We also check this since `assert_ne!()` does not call `ne`. assert!(map_1.ne(&map_2)); assert!(map_2.ne(&map_3)); } #[test] fn test_eq_pointer_kind_consistent() { let map_a = rbt_map!["a" => 0]; let map_a_sync = rbt_map_sync!["a" => 0]; let map_b = rbt_map!["b" => 1]; let map_b_sync = rbt_map_sync!["b" => 1]; assert!(map_a == map_a_sync); assert!(map_a != map_b_sync); assert!(map_b == map_b_sync); } #[test] fn test_partial_ord() { let map_1 = rbt_map!["a" => 0xa]; let map_1_prime = rbt_map!["a" => 0xa]; let map_2 = rbt_map!["b" => 0xb]; let map_3 = rbt_map![0 => 0.0]; let map_4 = rbt_map![0 => core::f32::NAN]; assert_eq!(map_1.partial_cmp(&map_1_prime), Some(Ordering::Equal)); assert_eq!(map_1.partial_cmp(&map_2), Some(Ordering::Less)); assert_eq!(map_2.partial_cmp(&map_1), Some(Ordering::Greater)); assert_eq!(map_3.partial_cmp(&map_4), None); } #[test] fn test_ord() { let map_1 = rbt_map!["a" => 0xa]; let map_1_prime = rbt_map!["a" => 0xa]; let map_2 = rbt_map!["b" => 0xb]; assert_eq!(map_1.cmp(&map_1_prime), Ordering::Equal); assert_eq!(map_1.cmp(&map_2), Ordering::Less); assert_eq!(map_2.cmp(&map_1), Ordering::Greater); } #[test] fn test_ord_pointer_kind_consistent() { let map_a = rbt_map!["a" => 0]; let map_a_sync = rbt_map_sync!["a" => 0]; let map_b = rbt_map!["b" => 1]; let map_b_sync = rbt_map_sync!["b" => 1]; assert!(map_a <= map_a_sync); assert!(map_a < map_b_sync); assert!(map_b >= map_b_sync); assert!(map_a_sync >= map_a); assert!(map_b_sync > map_a); assert!(map_b_sync <= map_b); } fn hash(map: &RedBlackTreeMap) -> u64 where P: SharedPointerKind, { #[allow(deprecated)] let mut hasher = core::hash::SipHasher::new(); map.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let map_1 = rbt_map!["a" => 0xa]; let map_1_prime = rbt_map!["a" => 0xa]; let map_2 = rbt_map!["b" => 0xb, "a" => 0xa]; assert_eq!(hash(&map_1), hash(&map_1)); assert_eq!(hash(&map_1), hash(&map_1_prime)); assert_ne!(hash(&map_1), hash(&map_2)); } #[test] fn test_hash_pointer_kind_consistent() { let map = rbt_map!["a" => 0]; let map_sync = rbt_map_sync!["a" => 0]; assert_eq!(hash(&map), hash(&map_sync)); } #[test] fn test_clone() { let map = rbt_map!["hello" => 4, "there" => 5]; let clone = map.clone(); assert_eq!(clone.size(), map.size()); assert_eq!(clone.get("hello"), Some(&4)); assert_eq!(clone.get("there"), Some(&5)); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let map: RedBlackTreeMap = rbt_map![5 => 6, 7 => 8, 9 => 10, 11 => 12]; let encoded = serialize(&map).unwrap(); let decoded: RedBlackTreeMap = deserialize(&encoded).unwrap(); assert_eq!(map, decoded); } rpds/src/map/red_black_tree_map/mod.rs0000644000175000017500000014536114661133735020776 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::entry::Entry; use archery::{ArcTK, RcK, SharedPointer, SharedPointerKind}; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::Display; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; use core::marker::PhantomData; use core::ops::{Index, RangeBounds, RangeFull}; // TODO Use impl trait instead of this when available. pub type Iter<'a, K, V, P> = core::iter::Map, fn(&'a SharedPointer, P>) -> (&'a K, &'a V)>; pub type IterKeys<'a, K, V, P> = core::iter::Map, fn((&'a K, &V)) -> &'a K>; pub type IterValues<'a, K, V, P> = core::iter::Map, fn((&K, &'a V)) -> &'a V>; pub type RangeIter<'a, K, V, RB, Q, P> = core::iter::Map< RangeIterPtr<'a, K, V, RB, Q, P>, fn(&'a SharedPointer, P>) -> (&'a K, &'a V), >; /// Creates a [`RedBlackTreeMap`](crate::RedBlackTreeMap) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let m = RedBlackTreeMap::new() /// .insert(1, "one") /// .insert(2, "two") /// .insert(3, "three"); /// /// assert_eq!(rbt_map![1 => "one", 2 => "two", 3 => "three"], m); /// ``` #[macro_export] macro_rules! rbt_map { ($($k:expr => $v:expr),*) => { { #[allow(unused_mut)] let mut m = $crate::RedBlackTreeMap::new(); $( m.insert_mut($k, $v); )* m } }; } /// Creates a [`RedBlackTreeMap`](crate::RedBlackTreeMap) that implements `Sync`, containing the /// given arguments: /// /// ``` /// # use rpds::*; /// # /// let m = RedBlackTreeMap::new_sync() /// .insert(1, "one") /// .insert(2, "two") /// .insert(3, "three"); /// /// assert_eq!(rbt_map_sync![1 => "one", 2 => "two", 3 => "three"], m); /// ``` #[macro_export] macro_rules! rbt_map_sync { ($($k:expr => $v:expr),*) => { { #[allow(unused_mut)] let mut m = $crate::RedBlackTreeMap::new_sync(); $( m.insert_mut($k, $v); )* m } }; } /// A persistent map with structural sharing. This implementation uses a /// [red-black tree](https://en.wikipedia.org/wiki/Red-Black_tree). /// /// # Complexity /// /// Let *n* be the number of elements in the map. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:-------------------------- | ---------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `insert()` | Θ(log(n)) | Θ(log(n)) | /// | `remove()` | Θ(log(n)) | Θ(log(n)) | /// | `get()` | Θ(log(n)) | Θ(log(n)) | /// | `contains_key()` | Θ(log(n)) | Θ(log(n)) | /// | `size()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(log(n)) | Θ(log(n)) | /// | iterator step | Θ(1) | Θ(log(n)) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This implementation uses a [red-black tree](https://en.wikipedia.org/wiki/Red-Black_tree) as /// described in "Purely Functional Data Structures" by Chris Okasaki, page 27. Deletion is /// implemented according to the paper "Red-Black Trees with Types" by Stefan Kahrs /// ([reference implementation](https://www.cs.kent.ac.uk/people/staff/smk/redblack/Untyped.hs)) #[derive(Debug)] pub struct RedBlackTreeMap where P: SharedPointerKind, { root: Option, P>>, size: usize, } pub type RedBlackTreeMapSync = RedBlackTreeMap; #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Color { Red, Black, } #[derive(Debug)] struct Node where P: SharedPointerKind, { entry: SharedPointer, P>, color: Color, left: Option, P>>, right: Option, P>>, } impl Clone for Node where P: SharedPointerKind, { fn clone(&self) -> Node { Node { entry: SharedPointer::clone(&self.entry), color: self.color, left: self.left.clone(), right: self.right.clone(), } } } impl Node where K: Ord, P: SharedPointerKind, { fn new_red(entry: Entry) -> Node { Node { entry: SharedPointer::new(entry), color: Color::Red, left: None, right: None } } fn new_black(entry: Entry) -> Node { Node { entry: SharedPointer::new(entry), color: Color::Black, left: None, right: None } } fn borrow(node: &Option, P>>) -> Option<&Node> { node.as_ref().map(Borrow::borrow) } fn left_color(&self) -> Option { self.left.as_ref().map(|l| l.color) } fn right_color(&self) -> Option { self.right.as_ref().map(|r| r.color) } fn get(&self, key: &Q) -> Option<&Entry> where K: Borrow, Q: Ord, { match key.cmp(self.entry.key.borrow()) { Ordering::Less => self.left.as_ref().and_then(|l| l.get(key)), Ordering::Equal => Some(&self.entry), Ordering::Greater => self.right.as_ref().and_then(|r| r.get(key)), } } fn first(&self) -> &Entry { match self.left { Some(ref l) => l.first(), None => &self.entry, } } fn last(&self) -> &Entry { match self.right { Some(ref r) => r.last(), None => &self.entry, } } /// Balances an unbalanced node. This is a function is described in "Purely Functional /// Data Structures" by Chris Okasaki, page 27. /// /// The transformation is done as the figure below shows. /// /// ```text /// ╭────────────────────╮ /// │ ┌───┐ │ /// │ │ │ Red node │ /// │ └───┘ │ /// ┏━━━┓ │ │ /// ┃ z ┃ │ ┏━━━┓ │ /// ┗━━━┛ │ ┃ ┃ Black node │ /// ╱ ╲ │ ┗━━━┛ │ /// ┌───┐ d ╰────────────────────╯ /// │ y │ Case 1 /// └───┘ ╭──────────────────────────────────────────────────╮ /// ╱ ╲ ╰────────────────────────────────────────────────╮ │ /// ┌───┐ c │ │ /// │ x │ │ │ /// └───┘ │ │ /// ╱ ╲ │ │ /// a b │ │ /// │ │ /// │ │ /// │ │ /// ┏━━━┓ │ │ /// ┃ z ┃ │ │ /// ┗━━━┛ │ │ /// ╱ ╲ │ │ /// ┌───┐ d Case 2 │ │ /// │ x │ ╭─────────────────────────────╲ │ │ /// └───┘ ╰────────────────────────────╲ ╲ ╲ ╱ /// ╱ ╲ ╲ ╲ /// a ┌───┐ ╲ ╲ /// │ y │ ╲ ╲ ┌───┐ /// └───┘ ╲ ╲ │ y │ /// ╱ ╲ ╲ │ └───┘ /// b c ───┘ ╱ ╲ /// ╱ ╲ /// ┏━━━┓ ┏━━━┓ /// ┃ x ┃ ┃ z ┃ /// ┏━━━┓ ┗━━━┛ ┗━━━┛ /// ┃ x ┃ ───┐ ╱ ╲ ╱ ╲ /// ┗━━━┛ ╱ │ ╱ ╲ ╱ ╲ /// ╱ ╲ ╱ ╱ a b c d /// a ┌───┐ ╱ ╱ /// │ z │ ╱ ╱ /// └───┘ Case 3 ╱ ╱ ╱ ╲ /// ╱ ╲ ╭────────────────────────────╱ ╱ │ │ /// ┌───┐ d ╰─────────────────────────────╱ │ │ /// │ y │ │ │ /// └───┘ │ │ /// ╱ ╲ │ │ /// b c │ │ /// │ │ /// │ │ /// │ │ /// ┏━━━┓ │ │ /// ┃ x ┃ │ │ /// ┗━━━┛ │ │ /// ╱ ╲ │ │ /// a ┌───┐ Case 4 │ │ /// │ y │ ╭────────────────────────────────────────────────┘ │ /// └───┘ ╰──────────────────────────────────────────────────┘ /// ╱ ╲ /// b ┌───┐ /// │ z │ /// └───┘ /// ╱ ╲ /// c d /// ``` fn balance(&mut self) { use core::mem::swap; use Color::Black as B; use Color::Red as R; match self.color { B => { let color_l: Option = self.left_color(); let color_l_l: Option = self.left.as_ref().and_then(|l| l.left_color()); let color_l_r: Option = self.left.as_ref().and_then(|l| l.right_color()); let color_r: Option = self.right_color(); let color_r_l: Option = self.right.as_ref().and_then(|r| r.left_color()); let color_r_r: Option = self.right.as_ref().and_then(|r| r.right_color()); match (color_l, color_l_l, color_l_r, color_r, color_r_l, color_r_r) { // Case 1 (Some(R), Some(R), ..) => { let mut node_l_ptr = self.left.take().unwrap(); let node_l: &mut Node = SharedPointer::make_mut(&mut node_l_ptr); let mut node_l_l_ptr = node_l.left.take().unwrap(); let node_l_l: &mut Node = SharedPointer::make_mut(&mut node_l_l_ptr); self.color = Color::Red; node_l.color = Color::Black; node_l_l.color = Color::Black; swap(&mut self.entry, &mut node_l.entry); swap(&mut node_l.left, &mut node_l.right); swap(&mut self.right, &mut node_l.right); self.left = Some(node_l_l_ptr); self.right = Some(node_l_ptr); } // Case 2 (Some(R), _, Some(R), ..) => { let mut node_l_ptr = self.left.take().unwrap(); let node_l: &mut Node = SharedPointer::make_mut(&mut node_l_ptr); let mut node_l_r_ptr = node_l.right.take().unwrap(); let node_l_r: &mut Node = SharedPointer::make_mut(&mut node_l_r_ptr); self.color = Color::Red; node_l.color = Color::Black; node_l_r.color = Color::Black; swap(&mut self.entry, &mut node_l_r.entry); swap(&mut node_l_r.left, &mut node_l_r.right); swap(&mut node_l.right, &mut node_l_r.right); swap(&mut self.right, &mut node_l_r.right); self.right = Some(node_l_r_ptr); self.left = Some(node_l_ptr); } // Case 3 (.., Some(R), Some(R), _) => { let mut node_r_ptr = self.right.take().unwrap(); let node_r: &mut Node = SharedPointer::make_mut(&mut node_r_ptr); let mut node_r_l_ptr = node_r.left.take().unwrap(); let node_r_l: &mut Node = SharedPointer::make_mut(&mut node_r_l_ptr); self.color = Color::Red; node_r.color = Color::Black; node_r_l.color = Color::Black; swap(&mut self.entry, &mut node_r_l.entry); swap(&mut node_r.left, &mut node_r_l.right); swap(&mut node_r_l.left, &mut node_r_l.right); swap(&mut self.left, &mut node_r_l.left); self.left = Some(node_r_l_ptr); self.right = Some(node_r_ptr); } // Case 4 (.., Some(R), _, Some(R)) => { let mut node_r_ptr = self.right.take().unwrap(); let node_r: &mut Node = SharedPointer::make_mut(&mut node_r_ptr); let mut node_r_r_ptr = node_r.right.take().unwrap(); let node_r_r: &mut Node = SharedPointer::make_mut(&mut node_r_r_ptr); self.color = Color::Red; node_r.color = Color::Black; node_r_r.color = Color::Black; swap(&mut self.entry, &mut node_r.entry); swap(&mut node_r.left, &mut node_r.right); swap(&mut self.left, &mut node_r.left); self.right = Some(node_r_r_ptr); self.left = Some(node_r_ptr); } _ => (), } } R => (), } } /// Inserts the entry and returns whether the key is new. fn insert(root: &mut Option, P>>, key: K, value: V) -> bool { fn ins( node: &mut Option, P>>, k: K, v: V, is_root: bool, ) -> bool { match node { Some(node) => { let node = SharedPointer::make_mut(node); let ret = match k.cmp(&node.entry.key) { Ordering::Less => { let is_new_key = ins(&mut node.left, k, v, false); // Small optimization: avoid unnecessary calls to balance. if is_new_key { node.balance(); } is_new_key } Ordering::Equal => { node.entry = SharedPointer::new(Entry::new(k, v)); false } Ordering::Greater => { let is_new_key = ins(&mut node.right, k, v, false); // Small optimization: avoid unnecessary calls to balance. if is_new_key { node.balance(); } is_new_key } }; if is_root { node.color = Color::Black; } ret } None => { *node = if is_root { Some(SharedPointer::new(Node::new_black(Entry::new(k, v)))) } else { Some(SharedPointer::new(Node::new_red(Entry::new(k, v)))) }; true } } } ins(root, key, value, true) } /// Returns `false` if node has no children to merge. fn remove_fuse( node: &mut Node, left: Option, P>>, right: Option, P>>, ) -> bool { use Color::Black as B; use Color::Red as R; use core::mem::swap; match (left, right) { (None, None) => false, (None, Some(r_ptr)) => { crate::utils::replace(node, r_ptr); true } (Some(l_ptr), None) => { crate::utils::replace(node, l_ptr); true } (Some(mut l_ptr), Some(mut r_ptr)) => { match (l_ptr.color, r_ptr.color) { (B, R) => { let r = SharedPointer::make_mut(&mut r_ptr); let rl = r.left.take(); // This will always return `true`. Node::remove_fuse(node, Some(l_ptr), rl); swap(node, r); node.left = Some(r_ptr); } (R, B) => { let l = SharedPointer::make_mut(&mut l_ptr); let lr = l.right.take(); // This will always return `true`. Node::remove_fuse(node, lr, Some(r_ptr)); swap(node, l); node.right = Some(l_ptr); } (R, R) => { let r = SharedPointer::make_mut(&mut r_ptr); let rl = r.left.take(); let l = SharedPointer::make_mut(&mut l_ptr); let lr = l.right.take(); let fused = Node::remove_fuse(node, lr, rl); match node.color { R if fused => { let fl = node.left.take(); let fr = node.right.take(); l.right = fl; r.left = fr; node.left = Some(l_ptr); node.right = Some(r_ptr); } _ => { swap(l, node); if fused { r.left = Some(l_ptr); } node.right = Some(r_ptr); } } } (B, B) => { let r = SharedPointer::make_mut(&mut r_ptr); let rl = r.left.take(); let l = SharedPointer::make_mut(&mut l_ptr); let lr = l.right.take(); let fused = Node::remove_fuse(node, lr, rl); match node.color { R if fused => { let fl = node.left.take(); let fr = node.right.take(); l.right = fl; r.left = fr; node.left = Some(l_ptr); node.right = Some(r_ptr); } _ => { swap(l, node); if fused { r.left = Some(l_ptr); } node.color = Color::Red; node.right = Some(r_ptr); node.remove_balance_left(); } } } }; true } } } fn remove_balance(&mut self) { match (self.left_color(), self.right_color()) { (Some(Color::Red), Some(Color::Red)) => { SharedPointer::make_mut(self.left.as_mut().unwrap()).color = Color::Black; SharedPointer::make_mut(self.right.as_mut().unwrap()).color = Color::Black; self.color = Color::Red; } _ => { // Our `balance()` does nothing unless the color is black, which the caller // must ensure. debug_assert_eq!(self.color, Color::Black); self.balance(); } } } fn remove_balance_left(&mut self) { use Color::Black as B; use Color::Red as R; use core::mem::swap; let color_l: Option = self.left_color(); let color_r: Option = self.right_color(); let color_r_l: Option = self.right.as_ref().and_then(|r| r.left_color()); match (color_l, color_r, color_r_l) { (Some(R), ..) => { let self_l = SharedPointer::make_mut(self.left.as_mut().unwrap()); self.color = Color::Red; self_l.color = Color::Black; } (_, Some(B), _) => { let self_r = SharedPointer::make_mut(self.right.as_mut().unwrap()); self.color = Color::Black; self_r.color = Color::Red; self.remove_balance(); } (_, Some(R), Some(B)) => { let self_r = SharedPointer::make_mut(self.right.as_mut().unwrap()); let mut self_r_l_ptr = self_r.left.take().unwrap(); let self_r_l = SharedPointer::make_mut(&mut self_r_l_ptr); let new_r_l = self_r_l.right.take(); self_r.color = Color::Black; self_r.left = new_r_l; SharedPointer::make_mut(self_r.right.as_mut().unwrap()).color = Color::Red; self_r.remove_balance(); self.color = Color::Red; self_r_l.right = self_r_l.left.take(); self_r_l.left = self.left.take(); swap(&mut self.entry, &mut self_r_l.entry); self.left = Some(self_r_l_ptr); } _ => unreachable!(), } } fn remove_balance_right(&mut self) { use Color::Black as B; use Color::Red as R; use core::mem::swap; let color_r: Option = self.right_color(); let color_l: Option = self.left_color(); let color_l_r: Option = self.left.as_ref().and_then(|l| l.right_color()); match (color_l, color_l_r, color_r) { (.., Some(R)) => { let self_r = SharedPointer::make_mut(self.right.as_mut().unwrap()); self.color = Color::Red; self_r.color = Color::Black; } (Some(B), ..) => { let self_l = SharedPointer::make_mut(self.left.as_mut().unwrap()); self.color = Color::Black; self_l.color = Color::Red; self.remove_balance(); } (Some(R), Some(B), _) => { let self_l = SharedPointer::make_mut(self.left.as_mut().unwrap()); let mut self_l_r_ptr = self_l.right.take().unwrap(); let self_l_r = SharedPointer::make_mut(&mut self_l_r_ptr); let new_l_r = self_l_r.left.take(); self_l.color = Color::Black; self_l.right = new_l_r; SharedPointer::make_mut(self_l.left.as_mut().unwrap()).color = Color::Red; self_l.remove_balance(); self.color = Color::Red; self_l_r.left = self_l_r.right.take(); self_l_r.right = self.right.take(); swap(&mut self.entry, &mut self_l_r.entry); self.right = Some(self_l_r_ptr); } _ => unreachable!(), } } /// Returns `true` if the key was present. /// /// If the node becomes empty `*root` will be set to `None`. fn remove(root: &mut Option, P>>, key: &Q) -> bool where K: Borrow, Q: Ord, { fn del_left(node: &mut Node, k: &Q) -> bool where K: Borrow + Ord, Q: Ord, P: SharedPointerKind, { let original_left_color = node.left_color(); let removed = del(&mut node.left, k, false); node.color = Color::Red; // In case of rebalance the color does not matter. if let Some(Color::Black) = original_left_color { node.remove_balance_left(); } removed } fn del_right(node: &mut Node, k: &Q) -> bool where K: Borrow + Ord, Q: Ord, P: SharedPointerKind, { let original_right_color = node.right_color(); let removed = del(&mut node.right, k, false); node.color = Color::Red; // In case of rebalance the color does not matter. if let Some(Color::Black) = original_right_color { node.remove_balance_right(); } removed } fn del( node: &mut Option, P>>, k: &Q, is_root: bool, ) -> bool where K: Borrow + Ord, Q: Ord, P: SharedPointerKind, { let (removed, make_node_none) = match *node { Some(ref mut node) => { let node = SharedPointer::make_mut(node); let ret = match k.cmp(node.entry.key.borrow()) { Ordering::Less => (del_left(node, k), false), Ordering::Equal => { let left = node.left.take(); let right = node.right.take(); let make_node_none = !Node::remove_fuse(node, left, right); (true, make_node_none) } Ordering::Greater => (del_right(node, k), false), }; if is_root { node.color = Color::Black; } ret } None => (false, false), }; if make_node_none { *node = None; } removed } del(root, key, true) } } impl Node where K: Ord + Clone, V: Clone, P: SharedPointerKind, { fn get_mut(&mut self, key: &Q) -> Option<&mut Entry> where K: Borrow, Q: Ord, { match key.cmp(self.entry.key.borrow()) { Ordering::Less => { self.left.as_mut().and_then(|l| SharedPointer::make_mut(l).get_mut(key)) } Ordering::Equal => Some(SharedPointer::make_mut(&mut self.entry)), Ordering::Greater => { self.right.as_mut().and_then(|r| SharedPointer::make_mut(r).get_mut(key)) } } } } impl RedBlackTreeMapSync where K: Ord, { #[must_use] pub fn new_sync() -> RedBlackTreeMapSync { RedBlackTreeMap::new_with_ptr_kind() } } impl RedBlackTreeMap where K: Ord, { #[must_use] pub fn new() -> RedBlackTreeMap { RedBlackTreeMap::new_with_ptr_kind() } } impl RedBlackTreeMap where K: Ord, P: SharedPointerKind, { #[must_use] pub fn new_with_ptr_kind() -> RedBlackTreeMap { RedBlackTreeMap { root: None, size: 0 } } #[must_use] pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord, { self.root.as_ref().and_then(|r| r.get(key)).map(|e| &e.value) } #[must_use] pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Ord, { self.root.as_ref().and_then(|r| r.get(key)).map(|e| (&e.key, &e.value)) } #[must_use] pub fn first(&self) -> Option<(&K, &V)> { self.root.as_ref().map(|r| r.first()).map(|e| (&e.key, &e.value)) } #[must_use] pub fn last(&self) -> Option<(&K, &V)> { self.root.as_ref().map(|r| r.last()).map(|e| (&e.key, &e.value)) } #[must_use] pub fn insert(&self, key: K, value: V) -> RedBlackTreeMap { let mut new_map = self.clone(); new_map.insert_mut(key, value); new_map } pub fn insert_mut(&mut self, key: K, value: V) { let is_new_key = Node::insert(&mut self.root, key, value); if is_new_key { self.size += 1; } } #[must_use] pub fn remove(&self, key: &Q) -> RedBlackTreeMap where K: Borrow, Q: Ord, { let mut new_map = self.clone(); if new_map.remove_mut(key) { new_map } else { // We want to keep maximum sharing so in case of no change we just `clone()` ourselves. self.clone() } } pub fn remove_mut(&mut self, key: &Q) -> bool where K: Borrow, Q: Ord, { let removed = Node::remove(&mut self.root, key); // Note that unfortunately, even if nothing was removed, we still might have cloned some // part of the tree unnecessarily. if removed { self.size -= 1; } removed } #[must_use] pub fn contains_key(&self, key: &Q) -> bool where K: Borrow, Q: Ord, { self.get(key).is_some() } /// Test whether the two maps refer to the same content in memory. /// /// This would return true if you’re comparing a map to itself, /// or if you’re comparing a map to a fresh clone of itself. pub(crate) fn ptr_eq(&self, other: &RedBlackTreeMap) -> bool { let a = self.root.as_ref().map_or(core::ptr::null(), SharedPointer::as_ptr); // Note how we're casting the raw pointer changing from P to PO // We cannot perform the equality in a type safe way because the root type depends // on P/PO, and we can't pass different types to SharedPtr::same_ptr or std::ptr::eq. let b = other .root .as_ref() .map_or(core::ptr::null(), SharedPointer::as_ptr) .cast::>(); core::ptr::eq(a, b) } #[must_use] #[inline] pub fn size(&self) -> usize { self.size } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.size() == 0 } pub fn iter(&self) -> Iter<'_, K, V, P> { self.iter_ptr().map(|e| (&e.key, &e.value)) } #[must_use] fn iter_ptr(&self) -> IterPtr<'_, K, V, P> { IterPtr::new(self) } pub fn keys(&self) -> IterKeys<'_, K, V, P> { self.iter().map(|(k, _)| k) } pub fn values(&self) -> IterValues<'_, K, V, P> { self.iter().map(|(_, v)| v) } pub fn range(&self, range: RB) -> RangeIter<'_, K, V, RB, Q, P> where K: Borrow, Q: Ord + ?Sized, RB: RangeBounds, { use core::ops::Bound::*; match (range.start_bound(), range.end_bound()) { (Excluded(s), Excluded(e)) if s == e => { panic!("range start and end are equal and excluded") } (Included(s), Included(e)) | (Included(s), Excluded(e)) | (Excluded(s), Included(e)) | (Excluded(s), Excluded(e)) if s > e => { panic!("range start is greater than range end") } (_, _) => RangeIterPtr::new(self, range).map(|e| (&e.key, &e.value)), } } } impl RedBlackTreeMap where K: Ord + Clone, V: Clone, P: SharedPointerKind, { pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Ord, { // Note that unfortunately, even if nothing is found, we still might have cloned some // part of the tree unnecessarily. self.root .as_mut() .and_then(|r| SharedPointer::make_mut(r).get_mut(key).map(|e| &mut e.value)) } } impl<'a, K, Q: ?Sized, V, P> Index<&'a Q> for RedBlackTreeMap where K: Ord + Borrow, Q: Ord, P: SharedPointerKind, { type Output = V; fn index(&self, key: &Q) -> &V { self.get(key).expect("no entry found for key") } } impl Clone for RedBlackTreeMap where K: Ord, P: SharedPointerKind, { fn clone(&self) -> RedBlackTreeMap { RedBlackTreeMap { root: self.root.clone(), size: self.size } } } impl Default for RedBlackTreeMap where K: Ord, P: SharedPointerKind, { fn default() -> RedBlackTreeMap { RedBlackTreeMap::new_with_ptr_kind() } } impl PartialEq> for RedBlackTreeMap where K: Ord, P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &RedBlackTreeMap) -> bool { if self.ptr_eq(other) { return true; } self.size() == other.size() && self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) } } impl Eq for RedBlackTreeMap where K: Ord, P: SharedPointerKind, { } impl PartialOrd> for RedBlackTreeMap where P: SharedPointerKind, PO: SharedPointerKind, { fn partial_cmp(&self, other: &RedBlackTreeMap) -> Option { self.iter().partial_cmp(other.iter()) } } impl Ord for RedBlackTreeMap where P: SharedPointerKind, { fn cmp(&self, other: &RedBlackTreeMap) -> Ordering { self.iter().cmp(other.iter()) } } impl Hash for RedBlackTreeMap where K: Ord, { fn hash(&self, state: &mut H) { // Add the hash of length so that if two collections are added one after the other it // doesn't hash to the same thing as a single collection with the same elements in the same // order. self.size().hash(state); for e in self { e.hash(state); } } } impl Display for RedBlackTreeMap where K: Ord + Display, V: Display, P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("{")?; for (k, v) in self { if !first { fmt.write_str(", ")?; } k.fmt(fmt)?; fmt.write_str(": ")?; v.fmt(fmt)?; first = false; } fmt.write_str("}") } } impl<'a, K, V, P> IntoIterator for &'a RedBlackTreeMap where K: Ord, P: SharedPointerKind, { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V, P>; fn into_iter(self) -> Iter<'a, K, V, P> { self.iter() } } // TODO This can be improved to create a perfectly balanced tree. impl FromIterator<(K, V)> for RedBlackTreeMap where K: Ord, P: SharedPointerKind, { fn from_iter>(into_iter: I) -> RedBlackTreeMap { let mut map = RedBlackTreeMap::new_with_ptr_kind(); for (k, v) in into_iter { map.insert_mut(k, v); } map } } mod iter_utils { use super::{Entry, Node, RedBlackTreeMap}; use alloc::vec::Vec; use archery::{SharedPointer, SharedPointerKind}; use core::borrow::Borrow; use core::ops::Bound; // This is a stack for navigating through the tree. It can be used to go either forwards or // backwards: you choose the direction at construction time, and then every call to `advance` // goes in that direction. #[derive(Debug)] pub struct IterStack<'a, K, V, P> where P: SharedPointerKind, { // The invariant maintained by `stack` depends on whether we are moving forwards or backwards. // In either case, the current node is at the top of the stack. If we are moving forwards, the // rest of the stack consists of those ancestors of the current node that contain the current // node in their left subtree. In other words, the keys in the stack increase as we go from the // top of the stack to the bottom. stack: Vec<&'a Node>, backwards: bool, } impl<'a, K, V, P> IterStack<'a, K, V, P> where K: Ord, P: SharedPointerKind, { pub fn new( map: &'a RedBlackTreeMap, start_bound: Bound<&Q>, end_bound: Bound<&Q>, backwards: bool, ) -> IterStack<'a, K, V, P> where K: Borrow, Q: Ord + ?Sized, { let size = conservative_height(map.size()) + 1; let mut stack = IterStack { stack: Vec::with_capacity(size), backwards }; if let Some(ref root) = map.root { stack.dig_towards(root.borrow(), start_bound, end_bound); } stack.clear_if_finished(start_bound, end_bound); stack } fn clear_if_finished(&mut self, start_bound: Bound<&Q>, end_bound: Bound<&Q>) where K: Borrow, Q: Ord + ?Sized, { use core::ops::Bound::*; if let Some(entry) = self.current() { let in_range = if self.backwards { match start_bound { Included(v) => entry.key.borrow() >= v, Excluded(v) => entry.key.borrow() > v, Unbounded => true, } } else { match end_bound { Included(v) => entry.key.borrow() <= v, Excluded(v) => entry.key.borrow() < v, Unbounded => true, } }; if !in_range { self.stack.clear(); } }; } #[inline] pub fn current(&self) -> Option<&'a SharedPointer, P>> { self.stack.last().map(|node| &node.entry) } fn dig(&mut self) where K: Borrow, Q: Ord + ?Sized, { let child = self.stack.last().and_then(|node| { let c = if self.backwards { &node.right } else { &node.left }; Node::borrow(c) }); if let Some(c) = child { self.stack.push(c); self.dig(); } } fn dig_towards( &mut self, node: &'a Node, start_bound: Bound<&Q>, end_bound: Bound<&Q>, ) where K: Borrow, Q: Ord + ?Sized, { use core::ops::Bound::*; let in_range = if self.backwards { match end_bound { Included(v) => node.entry.key.borrow() <= v, Excluded(v) => node.entry.key.borrow() < v, Unbounded => true, } } else { match start_bound { Included(v) => node.entry.key.borrow() >= v, Excluded(v) => node.entry.key.borrow() > v, Unbounded => true, } }; if in_range { self.stack.push(node); } let child = match (self.backwards, in_range) { (false, true) => &node.left, (false, false) => &node.right, (true, true) => &node.right, (true, false) => &node.left, }; if let Some(c) = child { self.dig_towards(c.borrow(), start_bound, end_bound); } } pub fn advance(&mut self, start_bound: Bound<&Q>, end_bound: Bound<&Q>) where K: Borrow, Q: Ord + ?Sized, { if let Some(node) = self.stack.pop() { let child = if self.backwards { &node.left } else { &node.right }; if let Some(c) = Node::borrow(child) { self.stack.push(c); self.dig(); } self.clear_if_finished(start_bound, end_bound); } } } pub fn lg_floor(size: usize) -> usize { debug_assert!(size > 0); let c: usize = usize::BITS as usize - size.leading_zeros() as usize; c - 1 } pub fn conservative_height(size: usize) -> usize { if size > 0 { 2 * lg_floor(size + 1) } else { 0 } } } #[derive(Debug)] pub struct IterPtr<'a, K, V, P> where P: SharedPointerKind, { range_iter: RangeIterPtr<'a, K, V, RangeFull, K, P>, // Number of elements left in the iterator. size: usize, } impl<'a, K, V, P> IterPtr<'a, K, V, P> where K: Ord, P: SharedPointerKind, { fn new(map: &RedBlackTreeMap) -> IterPtr<'_, K, V, P> { IterPtr { range_iter: RangeIterPtr::new(map, ..), size: map.size } } } impl<'a, K, V, P> Iterator for IterPtr<'a, K, V, P> where K: Ord, P: SharedPointerKind, { type Item = &'a SharedPointer, P>; fn next(&mut self) -> Option<&'a SharedPointer, P>> { if self.size > 0 { self.size -= 1; self.range_iter.next() } else { None } } fn size_hint(&self) -> (usize, Option) { (self.size, Some(self.size)) } } impl<'a, K, V, P> DoubleEndedIterator for IterPtr<'a, K, V, P> where K: Ord, P: SharedPointerKind, { fn next_back(&mut self) -> Option<&'a SharedPointer, P>> { if self.size > 0 { self.size -= 1; self.range_iter.next_back() } else { None } } } impl<'a, K: Ord, V, P> ExactSizeIterator for IterPtr<'a, K, V, P> where P: SharedPointerKind {} #[derive(Debug)] pub struct RangeIterPtr<'a, K, V, RB, Q: ?Sized, P> where P: SharedPointerKind, { map: &'a RedBlackTreeMap, stack_forward: Option>, stack_backward: Option>, range: RB, _q: PhantomData, } impl<'a, K, V, Q, RB, P> RangeIterPtr<'a, K, V, RB, Q, P> where K: Ord + Borrow, Q: Ord + ?Sized, RB: RangeBounds, P: SharedPointerKind, { fn new(map: &'a RedBlackTreeMap, range: RB) -> RangeIterPtr<'_, K, V, RB, Q, P> { RangeIterPtr { map, stack_forward: None, stack_backward: None, range, _q: PhantomData } } fn init_if_needed(&mut self, backwards: bool) { use iter_utils::IterStack; let stack_field = if backwards { &mut self.stack_backward } else { &mut self.stack_forward }; if stack_field.is_none() { *stack_field = Some(IterStack::new( self.map, self.range.start_bound(), self.range.end_bound(), backwards, )); } } fn is_remaining_range_empty(&self) -> bool { match (&self.stack_forward, &self.stack_backward) { (Some(stack_forward), Some(stack_backward)) => { match (stack_forward.current(), stack_backward.current()) { (Some(left), Some(right)) => left.key > right.key, (_, _) => true, } } (_, _) => false, } } fn current_forward(&self) -> Option<&'a SharedPointer, P>> { match self.is_remaining_range_empty() { true => None, false => self.stack_forward.as_ref().unwrap().current(), } } fn advance_forward(&mut self) { self.stack_forward .as_mut() .unwrap() .advance(self.range.start_bound(), self.range.end_bound()); } fn current_backward(&self) -> Option<&'a SharedPointer, P>> { match self.is_remaining_range_empty() { true => None, false => self.stack_backward.as_ref().unwrap().current(), } } fn advance_backward(&mut self) { self.stack_backward .as_mut() .unwrap() .advance(self.range.start_bound(), self.range.end_bound()); } } impl<'a, K, V, RB, Q, P> Iterator for RangeIterPtr<'a, K, V, RB, Q, P> where K: Ord + Borrow, Q: Ord + ?Sized, RB: RangeBounds, P: SharedPointerKind, { type Item = &'a SharedPointer, P>; fn next(&mut self) -> Option { self.init_if_needed(false); let current = self.current_forward(); self.advance_forward(); current } } impl<'a, K, V, RB, Q, P> DoubleEndedIterator for RangeIterPtr<'a, K, V, RB, Q, P> where K: Ord + Borrow, Q: Ord + ?Sized, RB: RangeBounds, P: SharedPointerKind, { fn next_back(&mut self) -> Option<&'a SharedPointer, P>> { self.init_if_needed(true); let current = self.current_backward(); self.advance_backward(); current } } #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer, MapAccess, Visitor}; use ::serde::ser::{Serialize, Serializer}; use core::fmt; use core::marker::PhantomData; impl Serialize for RedBlackTreeMap where K: Ord + Serialize, V: Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { serializer.collect_map(self) } } impl<'de, K, V, P> Deserialize<'de> for RedBlackTreeMap where K: Ord + Deserialize<'de>, V: Deserialize<'de>, P: SharedPointerKind, { fn deserialize>( deserializer: D, ) -> Result, D::Error> { deserializer.deserialize_map(RedBlackTreeMapVisitor { _phantom_entry: PhantomData, _phantom_p: PhantomData, }) } } struct RedBlackTreeMapVisitor where P: SharedPointerKind, { _phantom_entry: PhantomData<(K, V)>, _phantom_p: PhantomData

, } impl<'de, K, V, P> Visitor<'de> for RedBlackTreeMapVisitor where K: Ord + Deserialize<'de>, V: Deserialize<'de>, P: SharedPointerKind, { type Value = RedBlackTreeMap; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a map") } fn visit_map(self, mut map: A) -> Result, A::Error> where A: MapAccess<'de>, { let mut rb_tree_map = RedBlackTreeMap::new_with_ptr_kind(); while let Some((k, v)) = map.next_entry()? { rb_tree_map.insert_mut(k, v); } Ok(rb_tree_map) } } } #[cfg(test)] mod test; rpds/src/map/entry.rs0000644000175000017500000000066414661133735015572 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #[derive(Debug, PartialEq, Eq, Clone)] pub struct Entry { pub key: K, pub value: V, } impl Entry { #[must_use] pub fn new(key: K, value: V) -> Entry { Entry { key, value } } } rpds/src/map/mod.rs0000644000175000017500000000041614661133735015203 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ mod entry; pub mod hash_trie_map; pub mod red_black_tree_map; rpds/src/map/hash_trie_map/0000775000175000017500000000000014661133735016662 5ustar jamespagejamespagerpds/src/map/hash_trie_map/sparse_array_usize/0000775000175000017500000000000014661133735022574 5ustar jamespagejamespagerpds/src/map/hash_trie_map/sparse_array_usize/test.rs0000644000175000017500000000721014661133735024117 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; const USIZE_BITS: usize = usize::BITS as usize; #[test] fn test_new() { let empty_array: SparseArrayUsize = SparseArrayUsize::new(); assert_eq!(empty_array.bitmap, 0); assert_eq!(empty_array.array.len(), 0); assert_eq!(empty_array.array.capacity(), 0, "Capacity of the branch array is wasteful"); } #[test] fn test_set() { let mut array = SparseArrayUsize::new(); assert_eq!(array.size(), 0); assert_eq!(array.get(0), None); assert_eq!(array.get(USIZE_BITS - 1), None); array.set(3, 'a'); assert_eq!(array.size(), 1); assert_eq!(array.get(2), None); assert_eq!(array.get(3), Some(&'a')); assert_eq!(array.get(4), None); array.set(USIZE_BITS - 4, 'b'); assert_eq!(array.size(), 2); assert_eq!(array.get(3), Some(&'a')); assert_eq!(array.get(USIZE_BITS - 4), Some(&'b')); array.set(3, 'c'); assert_eq!(array.size(), 2); assert_eq!(array.get(3), Some(&'c')); assert_eq!(array.get(USIZE_BITS - 4), Some(&'b')); } #[test] fn test_remove() { let mut array = SparseArrayUsize::new(); array.set(3, 'a'); array.set(USIZE_BITS - 4, 'b'); assert_eq!(array.get(3), Some(&'a')); assert_eq!(array.get(USIZE_BITS - 4), Some(&'b')); array.remove(8); assert_eq!(array.get(3), Some(&'a')); assert_eq!(array.get(USIZE_BITS - 4), Some(&'b')); assert_eq!(array.size(), 2); array.remove(3); assert_eq!(array.get(3), None); assert_eq!(array.get(USIZE_BITS - 4), Some(&'b')); assert_eq!(array.size(), 1); array.remove(USIZE_BITS - 4); assert_eq!(array.get(3), None); assert_eq!(array.get(USIZE_BITS - 4), None); assert_eq!(array.size(), 0); } #[test] fn test_first() { let mut array = SparseArrayUsize::new(); assert_eq!(array.first(), None); array.set(8, 'a'); assert_eq!(array.first(), Some(&'a')); array.set(USIZE_BITS - 4, 'b'); assert_eq!(array.first(), Some(&'a')); array.set(2, 'c'); assert_eq!(array.first(), Some(&'c')); array.set(0, 'c'); assert_eq!(array.first(), Some(&'c')); } #[test] fn test_pop() { let mut array = SparseArrayUsize::new(); array.set(USIZE_BITS - 4, 'b'); array.set(8, 'a'); assert_eq!(array.pop(), Some('b')); assert_eq!(array.pop(), Some('a')); assert_eq!(array.pop(), None); } #[test] fn test_map_index() { for i in 0..(usize::BITS as usize) { assert_eq!(sparse_array_usize_utils::map_index(0, i), None); } let bitmap: usize = 0b_1110_0100_0101; assert_eq!(sparse_array_usize_utils::map_index(bitmap, 0), Some(0)); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 1), None); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 2), Some(1)); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 3), None); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 4), None); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 5), None); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 6), Some(2)); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 7), None); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 8), None); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 9), Some(3)); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 10), Some(4)); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 11), Some(5)); assert_eq!(sparse_array_usize_utils::map_index(bitmap, 12), None); } rpds/src/map/hash_trie_map/sparse_array_usize/mod.rs0000644000175000017500000000527214661133735023725 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use alloc::vec::Vec; use core::mem::size_of_val; use core::slice; /// Sparse array of size `8⋅size_of::()`. The space used is proportional to the number of /// elements set. #[derive(Debug, PartialEq, Eq)] pub struct SparseArrayUsize { bitmap: usize, array: Vec, } mod sparse_array_usize_utils { #[inline] pub fn map_index(bitmap: usize, virtual_index: usize) -> Option { if bitmap & (1_usize << virtual_index) == 0 { None } else { let mask = (1_usize << virtual_index) - 1; Some((bitmap & mask).count_ones() as usize) } } } impl SparseArrayUsize { pub fn new() -> SparseArrayUsize { SparseArrayUsize { bitmap: 0, array: Vec::new() } } #[inline] pub fn get(&self, index: usize) -> Option<&T> { debug_assert!(index < 8 * size_of_val(&self.bitmap)); sparse_array_usize_utils::map_index(self.bitmap, index).map(|i| &self.array[i]) } #[inline] pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { debug_assert!(index < 8 * size_of_val(&self.bitmap)); sparse_array_usize_utils::map_index(self.bitmap, index).map(move |i| &mut self.array[i]) } #[inline] pub fn first(&self) -> Option<&T> { self.array.first() } #[inline] pub fn pop(&mut self) -> Option { self.array.pop() } pub fn set(&mut self, index: usize, value: T) { debug_assert!(index < 8 * size_of_val(&self.bitmap)); match sparse_array_usize_utils::map_index(self.bitmap, index) { Some(i) => self.array[i] = value, None => { let new_bitmap = self.bitmap | (1 << index); let i = sparse_array_usize_utils::map_index(new_bitmap, index).unwrap(); self.bitmap = new_bitmap; self.array.insert(i, value); } } } pub fn remove(&mut self, index: usize) { if let Some(i) = sparse_array_usize_utils::map_index(self.bitmap, index) { self.bitmap ^= 1 << index; self.array.remove(i); } } #[inline] pub fn size(&self) -> usize { self.bitmap.count_ones() as usize } pub fn iter(&self) -> slice::Iter<'_, T> { self.array.iter() } } impl Clone for SparseArrayUsize { fn clone(&self) -> SparseArrayUsize { SparseArrayUsize { bitmap: self.bitmap, array: Vec::clone(&self.array) } } } #[cfg(test)] mod test; rpds/src/map/hash_trie_map/test.rs0000644000175000017500000011630714661133735020215 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(HashTrieMapSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_hash_trie_map_sync_is_send_and_sync() -> impl Send + Sync { ht_map_sync!(0 => 0) } impl PartialEq for Bucket where P: SharedPointerKind, { fn eq(&self, other: &Bucket) -> bool { match (self, other) { (Bucket::Single(self_entry), Bucket::Single(other_entry)) => self_entry.eq(other_entry), (Bucket::Collision(self_entry_list), Bucket::Collision(other_entry_list)) => { self_entry_list.eq(other_entry_list) } _ => false, } } } impl Eq for Bucket where P: SharedPointerKind {} impl PartialEq for EntryWithHash where P: SharedPointerKind, { fn eq(&self, other: &EntryWithHash) -> bool { self.entry.eq(&other.entry) } } impl Eq for EntryWithHash where P: SharedPointerKind {} impl PartialEq for Node where P: SharedPointerKind, { fn eq(&self, other: &Node) -> bool { match (self, other) { (Node::Branch(self_children), Node::Branch(other_children)) => { self_children.eq(other_children) } (Node::Leaf(self_bucket), Node::Leaf(other_bucket)) => self_bucket.eq(other_bucket), _ => false, } } } impl Eq for Node where P: SharedPointerKind {} mod bucket { use super::*; use pretty_assertions::assert_eq; #[test] fn test_list_remove_first() { use bucket_utils::list_remove_first; let list_a_b_c = list!['a', 'b', 'c']; let list_b_c = list!['b', 'c']; let list_a_c = list!['a', 'c']; let list_a_b = list!['a', 'b']; let mut list = list_a_b_c.clone(); assert!(list_remove_first(&mut list, |_| false).is_none()); assert_eq!(list, list_a_b_c); let mut list = list_a_b_c.clone(); assert!(list_remove_first(&mut list, |c| *c == 'a').is_some()); assert_eq!(list, list_b_c); let mut list = list_a_b_c.clone(); assert!(list_remove_first(&mut list, |c| *c == 'b').is_some()); assert_eq!(list, list_a_c); let mut list = list_a_b_c; assert!(list_remove_first(&mut list, |c| *c == 'c').is_some()); assert_eq!(list, list_a_b); } #[test] fn test_get() { let hash_builder = crate::utils::DefaultBuildHasher::default(); let entry_a: EntryWithHash<_, _> = EntryWithHash::new(0xAu8, 0, &hash_builder); let entry_b: EntryWithHash<_, _> = EntryWithHash::new(0xBu8, 1, &hash_builder); let entry_c: EntryWithHash<_, _> = EntryWithHash::new(0xCu8, 2, &hash_builder); let bucket_single = Bucket::Single(entry_a.clone()); let bucket_collision = Bucket::Collision(list![entry_b.clone(), entry_a.clone()]); assert_eq!(bucket_single.get(entry_a.key(), entry_a.key_hash), Some(&entry_a)); assert_eq!(bucket_single.get(entry_b.key(), entry_b.key_hash), None); assert_eq!(bucket_collision.get(entry_a.key(), entry_a.key_hash), Some(&entry_a)); assert_eq!(bucket_collision.get(entry_b.key(), entry_b.key_hash), Some(&entry_b)); assert_eq!(bucket_collision.get(entry_c.key(), entry_c.key_hash), None); } #[test] fn test_insert() { let hash_builder = crate::utils::DefaultBuildHasher::default(); let entry_a: EntryWithHash<_, _> = EntryWithHash::new(0xAu8, 0, &hash_builder); let entry_a9: EntryWithHash<_, _> = EntryWithHash::new(0xAu8, 9, &hash_builder); let entry_b: EntryWithHash<_, _> = EntryWithHash::new(0xBu8, 1, &hash_builder); let entry_b9: EntryWithHash<_, _> = EntryWithHash::new(0xBu8, 9, &hash_builder); let entry_c: EntryWithHash<_, _> = EntryWithHash::new(0xCu8, 2, &hash_builder); let entry_d: EntryWithHash<_, _> = EntryWithHash::new(0xDu8, 2, &hash_builder); let bucket_single_a = Bucket::Single(entry_a.clone()); let bucket_single_a9 = Bucket::Single(entry_a9.clone()); let bucket_collision_b_a = Bucket::Collision(list![entry_b.clone(), entry_a.clone()]); let bucket_collision_a_b_c = Bucket::Collision(list![entry_a.clone(), entry_b.clone(), entry_c.clone()]); let bucket_collision_b9_a_c = Bucket::Collision(list![entry_b9.clone(), entry_a.clone(), entry_c.clone()]); let bucket_collision_d_a_b_c = Bucket::Collision(list![entry_d.clone(), entry_a, entry_b.clone(), entry_c]); // Note that we care about the position of the inserted entry: we want it to be in the // beginning of the list as to improve performance with high temporal locality (since // `get()` will try to match according to the list order). The order of the rest of the // list must be preserved for the same reason. let mut bucket = bucket_single_a.clone(); assert!(!bucket.insert(entry_a9)); assert_eq!(bucket, bucket_single_a9); let mut bucket = bucket_single_a; assert!(bucket.insert(entry_b)); assert_eq!(bucket, bucket_collision_b_a); let mut bucket = bucket_collision_a_b_c.clone(); assert!(!bucket.insert(entry_b9)); assert_eq!(bucket, bucket_collision_b9_a_c); let mut bucket = bucket_collision_a_b_c; assert!(bucket.insert(entry_d)); assert_eq!(bucket, bucket_collision_d_a_b_c); } #[test] fn test_remove() { let hash_builder = crate::utils::DefaultBuildHasher::default(); let entry_a: EntryWithHash = EntryWithHash::new(0xAu8, 0, &hash_builder); let entry_b: EntryWithHash = EntryWithHash::new(0xBu8, 1, &hash_builder); let entry_c: EntryWithHash = EntryWithHash::new(0xCu8, 2, &hash_builder); let entry_d: EntryWithHash = EntryWithHash::new(0xDu8, 2, &hash_builder); let bucket_single_a = Bucket::Single(entry_a.clone()); let bucket_collision_b_c = Bucket::Collision(list![entry_b.clone(), entry_c.clone()]); let bucket_collision_a_b_c = Bucket::Collision(list![entry_a.clone(), entry_b.clone(), entry_c]); let mut bucket_ref: Option<&mut Bucket> = None; assert!(!Bucket::remove(&mut bucket_ref, entry_a.key(), entry_a.key_hash)); assert_eq!(bucket_ref, None); let mut bucket = bucket_single_a.clone(); let mut bucket_ref = Some(&mut bucket); assert!(Bucket::remove(&mut bucket_ref, entry_a.key(), entry_a.key_hash)); assert_eq!(bucket_ref, None); let mut bucket = bucket_single_a.clone(); let mut bucket_ref = Some(&mut bucket); assert!(!Bucket::remove(&mut bucket_ref, entry_b.key(), entry_b.key_hash)); assert_eq!(bucket_ref, Some(&mut bucket_single_a.clone())); let mut bucket = bucket_collision_a_b_c.clone(); let mut bucket_ref = Some(&mut bucket); assert!(Bucket::remove(&mut bucket_ref, entry_a.key(), entry_a.key_hash)); assert_eq!(bucket_ref, Some(&mut bucket_collision_b_c.clone())); let mut bucket = bucket_collision_a_b_c.clone(); let mut bucket_ref = Some(&mut bucket); assert!(!Bucket::remove(&mut bucket_ref, entry_d.key(), entry_d.key_hash)); assert_eq!(bucket_ref, Some(&mut bucket_collision_a_b_c.clone())); } } mod hasher_mocks { use super::*; use alloc::boxed::Box; use core::hash::Hasher; use std::collections::BTreeMap; pub struct MockedHashBuilder { byte_map: BTreeMap, } pub struct MockedHasher { last_byte: Option, byte_map: BTreeMap, } impl MockedHashBuilder { pub fn new(byte_map: BTreeMap) -> MockedHashBuilder { MockedHashBuilder { byte_map } } } impl Clone for MockedHashBuilder { fn clone(&self) -> MockedHashBuilder { MockedHashBuilder::new(self.byte_map.clone()) } } impl BuildHasher for MockedHashBuilder { type Hasher = MockedHasher; fn build_hasher(&self) -> MockedHasher { MockedHasher { last_byte: None, byte_map: self.byte_map.clone() } } } impl Hasher for MockedHasher { fn finish(&self) -> HashValue { *self.byte_map.get(self.last_byte.as_ref().unwrap()).unwrap() } fn write(&mut self, bytes: &[u8]) { self.last_byte = self.last_byte.or_else(|| bytes.last().copied()); } } pub struct LimitedHashSpaceHashBuilder { inner_hash_builder: crate::utils::DefaultBuildHasher, hash_space_size: usize, } pub struct LimitedHashSpaceHasher { inner_hasher: Box, hash_space_size: usize, } impl LimitedHashSpaceHashBuilder { pub fn new(hash_space_size: usize) -> LimitedHashSpaceHashBuilder { LimitedHashSpaceHashBuilder { inner_hash_builder: crate::utils::DefaultBuildHasher::default(), hash_space_size, } } } impl Clone for LimitedHashSpaceHashBuilder { fn clone(&self) -> LimitedHashSpaceHashBuilder { LimitedHashSpaceHashBuilder { inner_hash_builder: self.inner_hash_builder.clone(), hash_space_size: self.hash_space_size, } } } impl BuildHasher for LimitedHashSpaceHashBuilder { type Hasher = LimitedHashSpaceHasher; fn build_hasher(&self) -> LimitedHashSpaceHasher { LimitedHashSpaceHasher { inner_hasher: Box::new(self.inner_hash_builder.build_hasher()), hash_space_size: self.hash_space_size, } } } impl Hasher for LimitedHashSpaceHasher { fn finish(&self) -> HashValue { self.inner_hasher.finish() % (self.hash_space_size as HashValue) } fn write(&mut self, bytes: &[u8]) { self.inner_hasher.write(bytes); } } } mod node { use super::*; use hasher_mocks::*; use pretty_assertions::assert_eq; use std::collections::BTreeMap; #[test] fn test_new_empty_branch() { let node: Node = Node::new_empty_branch(); match node { Node::Branch(array) => assert_eq!(array.size(), 0), Node::Leaf(_) => panic!("Invalid node type"), } } #[allow(clippy::unusual_byte_groupings)] #[allow(clippy::unreadable_literal)] #[test] fn test_index_from_hash() { let hash: HashValue = 0b_000100_100011_000010_100001 | (1 << 63); assert_eq!(node_utils::index_from_hash(hash, 0, 64), Some(0b100001)); assert_eq!(node_utils::index_from_hash(hash, 1, 64), Some(0b000010)); assert_eq!(node_utils::index_from_hash(hash, 2, 64), Some(0b100011)); assert_eq!(node_utils::index_from_hash(hash, 3, 64), Some(0b000100)); assert_eq!(node_utils::index_from_hash(hash, 10, 64), Some(0b001000)); assert_eq!(node_utils::index_from_hash(hash, 11, 64), None); assert_eq!(node_utils::index_from_hash(hash, 15, 16), Some(0b1000)); assert_eq!(node_utils::index_from_hash(hash, 16, 16), None); } fn dummy_hash_builder() -> MockedHashBuilder { let hash_mapping: BTreeMap = [ (0xA, 0b_0010_0110), (0xB, 0b_0001_0110), (0xC, 0b_0100_0010), (0xD, 0b_0000_1000 | (0b0111 << 60)), (0xE, 0b_0000_1000 | (0b0111 << 60)), (0x0, 0b_0000_1000 | (0b0111 << 60)), (0x1, 0b_0000_0110 | (0b0101 << 60)), (0x2, 0b_0000_1111 | (0b0111 << 60)), ] .iter() .copied() .collect(); MockedHashBuilder::new(hash_mapping) } /// This constructs the following tree: /// /// ```text /// 0 ··· 2 ··· 6 ··· 8 ··· /// ├───┼───┼───┼───┼───┼───┼───┼───┤ /// │ ∅ │ ∅ │ C │ ∅ │ • │ ∅ │ • │ ∅ │ depth 0 /// └───┴───┴───┴───┴─│─┴───┴─│─┴───┘ /// ╱ ╲ /// ╱ ╲ /// ╱ ╲ /// 0 1 2 ··· 0 1 2 ··· /// ├───┼───┼───┼───┤ ├───┼───┼───┼───┤ /// │ ∅ │ B │ A │ ∅ │ │ • │ ∅ │ ∅ │ ∅ │ depth 1 /// └───┴───┴───┴───┘ └─│─┴───┴───┴───┘ /// │ /// · /// · /// · /// │ /// 0 ··· 7 ··· /// ├───┼───┼─────┼───┤ /// │ ∅ │ ∅ │ D E │ ∅ │ depth 16 (maximum depth) /// └───┴───┴─────┴───┘ /// ``` fn dummy_hash_trie_map() -> HashTrieMap { let hash_builder: MockedHashBuilder = dummy_hash_builder(); let entry_a = EntryWithHash::new(0xAu8, 0, &hash_builder); let entry_b = EntryWithHash::new(0xBu8, 1, &hash_builder); let entry_c = EntryWithHash::new(0xCu8, 2, &hash_builder); let entry_d = EntryWithHash::new(0xDu8, 3, &hash_builder); let entry_e = EntryWithHash::new(0xEu8, 4, &hash_builder); let bucket_a = Bucket::Single(entry_a); let bucket_b = Bucket::Single(entry_b); let bucket_c = Bucket::Single(entry_c); let bucket_de = Bucket::Collision(list![entry_e, entry_d]); let node_depth_1_first = { let mut array = SparseArrayUsize::new(); array.set(1, SharedPointer::new(Node::Leaf(bucket_b))); array.set(2, SharedPointer::new(Node::Leaf(bucket_a))); Node::Branch(array) }; let node_maximum_depth = { let mut array = SparseArrayUsize::new(); array.set(7, SharedPointer::new(Node::Leaf(bucket_de))); Node::Branch(array) }; let maximum_depth_branch = { let mut branch = node_maximum_depth; for _ in 0..14 { let mut array = SparseArrayUsize::new(); array.set(0, SharedPointer::new(branch)); branch = Node::Branch(array); } branch }; let node_root = { let mut array = SparseArrayUsize::new(); array.set(2, SharedPointer::new(Node::Leaf(bucket_c))); array.set(6, SharedPointer::new(node_depth_1_first)); array.set(8, SharedPointer::new(maximum_depth_branch)); Node::Branch(array) }; HashTrieMap { root: SharedPointer::new(node_root), size: 5, degree: 16, hasher_builder: hash_builder, } } #[test] fn test_get() { let map = dummy_hash_trie_map(); assert_eq!(map.get(&0xA), Some(&0)); assert_eq!(map.get(&0xB), Some(&1)); assert_eq!(map.get(&0xC), Some(&2)); assert_eq!(map.get(&0xD), Some(&3)); assert_eq!(map.get(&0xE), Some(&4)); assert_eq!(map.get(&0x0), None); assert_eq!(map.get(&0x1), None); assert_eq!(map.get(&0x2), None); } #[test] fn test_get_mut() { let original = dummy_hash_trie_map(); let mut map = original.clone(); *map.get_mut(&0xB).unwrap() = -1; *map.get_mut(&0xE).unwrap() = -1; assert!(map.get_mut(&0x1).is_none()); assert!(map.get_mut(&0x2).is_none()); assert_eq!(original.get(&0xA), Some(&0)); assert_eq!(original.get(&0xB), Some(&1)); assert_eq!(original.get(&0xC), Some(&2)); assert_eq!(original.get(&0xD), Some(&3)); assert_eq!(original.get(&0xE), Some(&4)); assert_eq!(original.get(&0x0), None); assert_eq!(original.get(&0x1), None); assert_eq!(original.get(&0x2), None); assert_eq!(map.get(&0xA), Some(&0)); assert_eq!(map.get(&0xB), Some(&-1)); assert_eq!(map.get(&0xC), Some(&2)); assert_eq!(map.get(&0xD), Some(&3)); assert_eq!(map.get(&0xE), Some(&-1)); assert_eq!(map.get(&0x0), None); assert_eq!(map.get(&0x1), None); assert_eq!(map.get(&0x2), None); } #[test] fn test_contains_key() { let map = dummy_hash_trie_map(); assert!(map.contains_key(&0xA)); assert!(map.contains_key(&0xE)); assert!(!map.contains_key(&0x0)); } #[test] fn test_insert() { let mut map: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16); assert_eq!(map.size(), 0); map = map.insert(0xA, 10); assert_eq!(map.size(), 1); map = map.insert(0xB, 1); assert_eq!(map.size(), 2); map = map.insert(0xC, 2); assert_eq!(map.size(), 3); map = map.insert(0xD, 3); assert_eq!(map.size(), 4); map = map.insert(0xE, 4); assert_eq!(map.size(), 5); map = map.insert(0xA, 0); assert_eq!(map.size(), 5); assert_eq!(map.get(&0xA), Some(&0)); assert_eq!(map.get(&0xB), Some(&1)); assert_eq!(map.get(&0xC), Some(&2)); assert_eq!(map.get(&0xD), Some(&3)); assert_eq!(map.get(&0xE), Some(&4)); assert_eq!(map.get(&0x0), None); assert_eq!(map.get(&0x1), None); assert_eq!(map.get(&0x2), None); assert_eq!(map.root, dummy_hash_trie_map().root); } #[test] fn test_compress() { let hash_builder: MockedHashBuilder = dummy_hash_builder(); let entry_a: EntryWithHash<_, _> = EntryWithHash::new(0xAu8, 0, &hash_builder); let entry_b: EntryWithHash<_, _> = EntryWithHash::new(0xBu8, 1, &hash_builder); let bucket_a = Bucket::Single(entry_a.clone()); let bucket_b = Bucket::Single(entry_b.clone()); let bucket_a_b = Bucket::Collision(list![entry_a, entry_b]); let empty_branch = Node::::new_empty_branch(); let branch_with_collision = { let mut array = SparseArrayUsize::new(); array.set(4, SharedPointer::new(Node::Leaf(bucket_a_b.clone()))); SharedPointer::<_, RcK>::new(Node::Branch(array)) }; let branch_with_two_subtrees = { let mut array = SparseArrayUsize::new(); array.set(4, SharedPointer::new(Node::Leaf(bucket_a.clone()))); array.set(7, SharedPointer::new(Node::Leaf(bucket_b.clone()))); SharedPointer::<_, RcK>::new(Node::Branch(array)) }; let branch_with_single_bucket = { let mut array = SparseArrayUsize::new(); array.set(4, SharedPointer::new(Node::Leaf(bucket_a.clone()))); Node::Branch(array) }; let branch_with_branch = { let mut array = SparseArrayUsize::new(); array.set(4, SharedPointer::new(Node::::new_empty_branch())); SharedPointer::<_, RcK>::new(Node::Branch(array)) }; let leaf_with_single_bucket_a = SharedPointer::<_, RcK>::new(Node::Leaf(bucket_a.clone())); let leaf_with_collision_bucket_a_b = SharedPointer::<_, RcK>::new(Node::Leaf(bucket_a_b.clone())); let mut node = Node::clone(&empty_branch); node.compress(); assert_eq!(node, empty_branch); let mut node = Node::clone(&branch_with_collision); node.compress(); assert_eq!(node, *branch_with_collision.borrow()); let mut node = Node::clone(&branch_with_two_subtrees); node.compress(); assert_eq!(node, *branch_with_two_subtrees.borrow()); let mut node = Node::clone(&branch_with_single_bucket); node.compress(); assert_eq!(node, *leaf_with_single_bucket_a.borrow()); let mut node = Node::clone(&branch_with_branch); node.compress(); assert_eq!(node, *branch_with_branch.borrow()); let mut node = Node::clone(&leaf_with_single_bucket_a); node.compress(); assert_eq!(node, *leaf_with_single_bucket_a.borrow()); let mut node = Node::clone(&leaf_with_collision_bucket_a_b); node.compress(); assert_eq!(node, *leaf_with_collision_bucket_a_b.borrow()); } #[test] fn test_remove() { let map_a_b_c_d_e: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16) .insert(0xA, 0) .insert(0xB, 1) .insert(0xC, 2) .insert(0xD, 3) .insert(0xE, 4); let map_a_b_d_e: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16) .insert(0xA, 0) .insert(0xB, 1) .insert(0xD, 3) .insert(0xE, 4); let map_a_c_d_e: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16) .insert(0xA, 0) .insert(0xC, 2) .insert(0xD, 3) .insert(0xE, 4); let map_c_d_e: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16) .insert(0xC, 2) .insert(0xD, 3) .insert(0xE, 4); let map_a_b_c_e: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16) .insert(0xA, 0) .insert(0xB, 1) .insert(0xC, 2) .insert(0xE, 4); let map_a_b_c: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16) .insert(0xA, 0) .insert(0xB, 1) .insert(0xC, 2); let map_empty: HashTrieMap<_, _, RcK, _> = HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(dummy_hash_builder(), 16); // Just a sanity check. assert_eq!(map_a_b_c_d_e.root, dummy_hash_trie_map().root); let removed_c = map_a_b_c_d_e.remove(&0xC); let removed_b = map_a_b_c_d_e.remove(&0xB); let removed_b_a = map_a_b_c_d_e.remove(&0xB).remove(&0xA); let removed_d = map_a_b_c_d_e.remove(&0xD); let removed_d_e = map_a_b_c_d_e.remove(&0xD).remove(&0xE); let removed_all = map_a_b_c_d_e.remove(&0xA).remove(&0xB).remove(&0xC).remove(&0xD).remove(&0xE); assert_eq!(removed_c.root, map_a_b_d_e.root); assert_eq!(removed_b.root, map_a_c_d_e.root); assert_eq!(removed_b_a.root, map_c_d_e.root); assert_eq!(removed_d.root, map_a_b_c_e.root); assert_eq!(removed_d_e.root, map_a_b_c.root); assert_eq!(removed_all.root, map_empty.root); assert_eq!(map_a_b_c_d_e.remove(&0x0).root, map_a_b_c_d_e.root); assert_eq!(map_a_b_c_d_e.remove(&0x1).root, map_a_b_c_d_e.root); assert_eq!(map_a_b_c_d_e.remove(&0x2).root, map_a_b_c_d_e.root); } } mod iter { use super::*; use pretty_assertions::assert_eq; #[test] fn test_trie_max_height() { assert_eq!(iter_utils::trie_max_height(2), 64); assert_eq!(iter_utils::trie_max_height(16), 16); assert_eq!(iter_utils::trie_max_height(32), 13); assert_eq!(iter_utils::trie_max_height(64), 11); } #[test] fn test_iter_empty() { let map: HashTrieMap = HashTrieMap::new(); for _ in map.iter() { panic!("iterator should be empty"); } } fn iterator_test(initial_map: HashTrieMap) { let mut map = initial_map; let limit: usize = 50_000; for i in 0..limit { map = map.insert(i as u32, -(i as i32)); } let mut touched = vec![false; limit]; for (k, v) in map.iter() { assert!(!touched[*k as usize]); assert_eq!(*k as i32, -*v); touched[*k as usize] = true; } assert!(touched.iter().all(|b| *b)); } #[test] fn test_iter() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { iterator_test(HashTrieMap::new_with_degree(degree)); } } #[test] fn test_iter_high_collision() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { let hasher = hasher_mocks::LimitedHashSpaceHashBuilder::new(1000); iterator_test(HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(hasher, degree)); } } #[test] fn test_iter_size_hint() { let map = ht_map![0 => 10, 1 => 11, 2 => 12]; let mut iterator = map.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_iter_keys() { let map = ht_map![0 => 10, 1 => 11, 2 => 12]; let mut touched = [false; 3]; for k in map.keys() { assert!(!touched[*k as usize]); touched[*k as usize] = true; } assert!(touched.iter().all(|b| *b)); } #[test] fn test_iter_values() { let map = ht_map![10 => 0, 11 => 1, 12 => 2]; let mut touched = [false; 3]; for v in map.values() { assert!(!touched[*v as usize]); touched[*v as usize] = true; } assert!(touched.iter().all(|b| *b)); } #[test] fn test_into_iterator() { let map = ht_map![0 => 10, 1 => 11, 2 => 12]; let mut left = 3; for _ in &map { left -= 1; assert!(left >= 0); } assert_eq!(left, 0); } } #[test] fn test_macro_ht_map() { let map_1 = HashTrieMap::new().insert(1, 2); let map_1_2_3 = HashTrieMap::new().insert(1, 2).insert(2, 3).insert(3, 4); assert_eq!(HashTrieMap::::new(), ht_map![]); assert_eq!(map_1, ht_map![1 => 2]); assert_eq!(map_1_2_3, ht_map![1 => 2, 2 => 3, 3 => 4]); } #[test] fn test_get_key_value() { let mut map = HashTrieMap::new(); map = map.insert("foo", 4); assert_eq!(map.get_key_value("foo"), Some((&"foo", &4))); map = map.insert("bar", 2); assert_eq!(map.get_key_value("foo"), Some((&"foo", &4))); assert_eq!(map.get_key_value("bar"), Some((&"bar", &2))); } #[test] fn test_insert_simple() { let mut map = HashTrieMap::new(); assert_eq!(map.size(), 0); map = map.insert("foo", 4); assert_eq!(map.size(), 1); assert_eq!(map.get("foo"), Some(&4)); map = map.insert("bar", 2); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); map = map.insert("baz", 12); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); map = map.insert("foo", 7); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&7)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); } fn insert_test(initial_map: HashTrieMap) { let mut map = initial_map; // These are relatively small limits. We prefer to do a more hardcore test in the mutable // version. let limit = 5_000; let overwrite_limit = 1_000; for i in 0..limit { map = map.insert(i, -(i as i32)); assert_eq!(map.size(), (i as usize) + 1); assert_eq!(map.get(&i), Some(&-(i as i32))); // Lets also check a previous value. let prev_key = i / 2; assert_eq!(map.get(&prev_key), Some(&-(prev_key as i32))); } // Now we test some overwrites. for i in 0..overwrite_limit { assert_eq!(map.get(&i), Some(&-(i as i32))); map = map.insert(i, 2 * i as i32); assert_eq!(map.size(), limit as usize); assert_eq!(map.get(&i), Some(&(2 * i as i32))); } } #[test] fn test_insert() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { insert_test(HashTrieMap::new_with_degree(degree)); } } #[test] fn test_insert_high_collision() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { let hasher = hasher_mocks::LimitedHashSpaceHashBuilder::new(1000); insert_test(HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(hasher, degree)); } } #[test] fn test_insert_simple_mut() { let mut map = HashTrieMap::new(); assert_eq!(map.size(), 0); map.insert_mut("foo", 4); assert_eq!(map.size(), 1); assert_eq!(map.get("foo"), Some(&4)); map.insert_mut("bar", 2); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); map.insert_mut("baz", 12); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); map.insert_mut("foo", 7); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&7)); assert_eq!(map.get("bar"), Some(&2)); assert_eq!(map.get("baz"), Some(&12)); } fn insert_test_mut(initial_map: HashTrieMap) { let mut map = initial_map; let limit = 25_000; let overwrite_limit = 5_000; for i in 0..limit { map.insert_mut(i, -(i as i32)); assert_eq!(map.size(), (i as usize) + 1); assert_eq!(map.get(&i), Some(&-(i as i32))); // Lets also check a previous value. let prev_key = i / 2; assert_eq!(map.get(&prev_key), Some(&-(prev_key as i32))); } // Now we test some overwrites. for i in 0..overwrite_limit { assert_eq!(map.get(&i), Some(&-(i as i32))); map.insert_mut(i, 2 * i as i32); assert_eq!(map.size(), limit as usize); assert_eq!(map.get(&i), Some(&(2 * i as i32))); } } #[test] fn test_insert_mut() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { insert_test_mut(HashTrieMap::new_with_degree(degree)); } } #[test] fn test_insert_high_collision_mut() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { let hasher = hasher_mocks::LimitedHashSpaceHashBuilder::new(1000); insert_test_mut(HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(hasher, degree)); } } #[test] fn test_remove_simple() { let mut map = ht_map![ "foo" => 4, "bar" => 12, "mumble" => 13, "baz" => 42 ]; let empty_map: HashTrieMap = HashTrieMap::new(); assert_eq!(empty_map.remove(&3), empty_map); assert_eq!(map.size(), 4); map = map.remove("not-there"); assert_eq!(map.size(), 4); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), Some(&13)); assert_eq!(map.get("baz"), Some(&42)); map = map.remove("mumble"); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), None); assert_eq!(map.get("baz"), Some(&42)); map = map.remove("foo"); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), None); map = map.remove("baz"); assert_eq!(map.size(), 1); assert_eq!(map.get("baz"), None); map = map.remove("bar"); assert_eq!(map.size(), 0); assert_eq!(map.get("bar"), None); } fn remove_test(initial_map: HashTrieMap) { let mut map = initial_map; // These are relatively small limits. We prefer to do a more hardcore test in the mutable // version. let limit = 5_000; for i in 0..limit { map = map.insert(i, -(i as i32)); } // Now lets remove half of it. for i in (0..limit / 2).map(|i| 2 * i) { assert_eq!(map.get(&i), Some(&-(i as i32))); map = map.remove(&i); assert!(!map.contains_key(&i)); assert_eq!(map.size(), (limit - i / 2 - 1) as usize); // Also check than the previous one is ok. if i > 0 { assert_eq!(map.get(&(i - 1)), Some(&-((i - 1) as i32))); } } } #[test] fn test_remove() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { remove_test(HashTrieMap::new_with_degree(degree)); } } #[test] fn test_remove_high_collision() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { let hasher = hasher_mocks::LimitedHashSpaceHashBuilder::new(1000); remove_test(HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(hasher, degree)); } } #[test] fn test_remove_simple_mut() { let mut map = ht_map![ "foo" => 4, "bar" => 12, "mumble" => 13, "baz" => 42 ]; assert_eq!(map.size(), 4); assert!(!map.remove_mut("not-there")); assert_eq!(map.size(), 4); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), Some(&13)); assert_eq!(map.get("baz"), Some(&42)); assert!(map.remove_mut("mumble")); assert_eq!(map.size(), 3); assert_eq!(map.get("foo"), Some(&4)); assert_eq!(map.get("bar"), Some(&12)); assert_eq!(map.get("mumble"), None); assert_eq!(map.get("baz"), Some(&42)); assert!(map.remove_mut("foo")); assert_eq!(map.size(), 2); assert_eq!(map.get("foo"), None); assert!(map.remove_mut("baz")); assert_eq!(map.size(), 1); assert_eq!(map.get("baz"), None); assert!(map.remove_mut("bar")); assert_eq!(map.size(), 0); assert_eq!(map.get("bar"), None); } fn remove_test_mut(initial_map: HashTrieMap) { let mut map = initial_map; let limit = 25_000; for i in 0..limit { map.insert_mut(i, -(i as i32)); } // Now lets remove half of it. for i in (0..limit / 2).map(|i| 2 * i) { assert_eq!(map.get(&i), Some(&-(i as i32))); map.remove_mut(&i); assert!(!map.contains_key(&i)); assert_eq!(map.size(), (limit - i / 2 - 1) as usize); // Also check than the previous one is ok. if i > 0 { assert_eq!(map.get(&(i - 1)), Some(&-((i - 1) as i32))); } } } #[test] fn test_remove_mut() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { remove_test_mut(HashTrieMap::new_with_degree(degree)); } } #[test] fn test_remove_high_collision_mut() { let degrees: Vec = [2, 4, 16, 32, DEFAULT_DEGREE] .into_iter() .filter(|d| *d <= DEFAULT_DEGREE) // we only want valid degrees .collect(); for degree in degrees { let hasher = hasher_mocks::LimitedHashSpaceHashBuilder::new(1000); remove_test_mut(HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(hasher, degree)); } } #[test] fn test_index() { let map = ht_map![5 => "hello", 12 => "there"]; assert_eq!(map[&5], "hello"); assert_eq!(map[&12], "there"); } #[test] fn test_from_iterator() { let vec: Vec<(i32, &str)> = vec![(2, "two"), (5, "five")]; let map: HashTrieMap = vec.iter().copied().collect(); let expected_map = ht_map![2 => "two", 5 => "five"]; assert_eq!(map, expected_map); } #[test] fn test_default() { let map: HashTrieMap = HashTrieMap::default(); assert_eq!(map.size(), 0); assert!(map.is_empty()); } #[test] fn test_display() { let empty_map: HashTrieMap = HashTrieMap::new(); let singleton_map = ht_map!["hi" =>"hello"]; let map = ht_map![5 => "hello", 12 => "there"]; assert_eq!(format!("{}", empty_map), "{}"); assert_eq!(format!("{}", singleton_map), "{hi: hello}"); assert!( format!("{map}") == "{5: hello, 12: there}" || format!("{map}") == "{12: there, 5: hello}" ); } #[test] fn test_eq() { let map_1 = ht_map!["a" => 0xa, "b" => 0xb]; let map_1_prime = ht_map!["a" => 0xa, "b" => 0xb]; let map_1_prime_2 = ht_map!["a" => 0xa, "b" => 0xb, "b" => 0xb]; let map_2 = ht_map!["a" => 0xa, "b" => 0xb + 1]; let map_3 = ht_map!["a" => 0xa, "b" => 0xb + 1, "c" => 0xc]; assert_eq!(map_1, map_1_prime); assert_eq!(map_1, map_1_prime_2); assert_eq!(map_1, map_1); assert_eq!(map_2, map_2); // We also check this since `assert_ne!()` does not call `ne`. assert!(map_1.ne(&map_2)); assert!(map_2.ne(&map_3)); } #[test] fn test_eq_pointer_kind_consistent() { let map_a = ht_map!["a" => 0]; let map_a_sync = ht_map_sync!["a" => 0]; let map_b = ht_map!["b" => 1]; let map_b_sync = ht_map_sync!["b" => 1]; assert!(map_a == map_a_sync); assert!(map_a != map_b_sync); assert!(map_b == map_b_sync); } #[test] fn test_clone() { let map = ht_map!["hello" => 4, "there" => 5]; let clone = map.clone(); assert_eq!(clone.size(), map.size()); assert_eq!(clone.get("hello"), Some(&4)); assert_eq!(clone.get("there"), Some(&5)); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let map: HashTrieMap = ht_map![5 => 6, 7 => 8, 9 => 10, 11 => 12]; let encoded = serialize(&map).unwrap(); let decoded: HashTrieMap = deserialize(&encoded).unwrap(); assert_eq!(map, decoded); } rpds/src/map/hash_trie_map/mod.rs0000644000175000017500000011200014661133735017777 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ mod sparse_array_usize; use super::entry::Entry; use crate::list; use crate::utils::DefaultBuildHasher; use crate::List; use alloc::vec::Vec; use archery::{ArcTK, RcK, SharedPointer, SharedPointerKind}; use core::borrow::Borrow; use core::fmt::Display; use core::hash::BuildHasher; use core::hash::Hash; use core::iter; use core::iter::FromIterator; use core::ops::Index; use core::slice; use sparse_array_usize::SparseArrayUsize; type HashValue = u64; // TODO Use impl trait instead of this when available. pub type Iter<'a, K, V, P> = iter::Map, fn(&'a SharedPointer, P>) -> (&'a K, &'a V)>; pub type IterKeys<'a, K, V, P> = iter::Map, fn((&'a K, &V)) -> &'a K>; pub type IterValues<'a, K, V, P> = iter::Map, fn((&K, &'a V)) -> &'a V>; #[allow(clippy::cast_possible_truncation)] const DEFAULT_DEGREE: u8 = usize::BITS as u8; /// Creates a [`HashTrieMap`](crate::HashTrieMap) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let m = HashTrieMap::new() /// .insert(1, "one") /// .insert(2, "two") /// .insert(3, "three"); /// /// assert_eq!(ht_map![1 => "one", 2 => "two", 3 => "three"], m); /// ``` #[macro_export] macro_rules! ht_map { ($($k:expr => $v:expr),*) => { { #[allow(unused_mut)] let mut m = $crate::HashTrieMap::new(); $( m.insert_mut($k, $v); )* m } }; } /// Creates a [`HashTrieMap`](crate::HashTrieMap) that implements `Sync`, containing the given /// arguments: /// /// ``` /// # use rpds::*; /// # /// let m = HashTrieMap::new_sync() /// .insert(1, "one") /// .insert(2, "two") /// .insert(3, "three"); /// /// assert_eq!(ht_map_sync![1 => "one", 2 => "two", 3 => "three"], m); /// ``` #[macro_export] macro_rules! ht_map_sync { ($($k:expr => $v:expr),*) => { { #[allow(unused_mut)] let mut m = $crate::HashTrieMap::new_sync(); $( m.insert_mut($k, $v); )* m } }; } /// A persistent map with structural sharing. This implementation uses a /// [hash array mapped trie](https://en.wikipedia.org/wiki/Hash_array_mapped_trie). /// /// # Complexity /// /// Let *n* be the number of elements in the map. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:-------------------------- | ---------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `insert()` | Θ(1) | Θ(n) | /// | `remove()` | Θ(1) | Θ(n) | /// | `get()` | Θ(1) | Θ(n) | /// | `contains_key()` | Θ(1) | Θ(n) | /// | `size()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(1) | Θ(1) | /// | iterator step | Θ(1) | Θ(1) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This implementation uses a /// [hash array mapped trie](https://en.wikipedia.org/wiki/Hash_array_mapped_trie). /// Details can be found in /// [Ideal Hash Trees](https://infoscience.epfl.ch/record/64398/files/idealhashtrees.pdf). /// /// See the `Node` documentation for details. #[derive(Debug)] pub struct HashTrieMap where P: SharedPointerKind, { root: SharedPointer, P>, size: usize, degree: u8, hasher_builder: H, } pub type HashTrieMapSync = HashTrieMap; /// This map works like a trie that breaks the hash of the key in segments, and the segments are /// used as the index in the trie branches. /// /// Consider the following example, where we have a tree with degree 16 (e.g. each level uses 4 /// bits of the hash) and the following mapping between keys and their hashes: /// /// | *key* | *hash(key)* | /// | ------- | ---------------------------------:| /// | *A* | `0b_0000_0000_···_0000_0010_0110` | /// | *B* | `0b_0000_0000_···_0000_0001_0110` | /// | *C* | `0b_0000_0000_···_0000_0100_0010` | /// | *D* | `0b_0111_0000_···_0000_0000_1000` | /// | *E* | `0b_0111_0000_···_0000_0000_1000` | /// /// Then the tree will look like this: /// /// ```text /// 0 ··· 2 ··· 6 ··· 8 ··· /// ├───┼───┼───┼───┼───┼───┼───┼───┤ /// │ ∅ │ ∅ │ C │ ∅ │ • │ ∅ │ • │ ∅ │ depth 0 /// └───┴───┴───┴───┴─│─┴───┴─│─┴───┘ /// ╱ ╲ /// ╱ ╲ /// ╱ ╲ /// 0 1 2 ··· 0 1 2 ··· /// ├───┼───┼───┼───┤ ├───┼───┼───┼───┤ /// │ ∅ │ B │ A │ ∅ │ │ • │ ∅ │ ∅ │ ∅ │ depth 1 /// └───┴───┴───┴───┘ └─│─┴───┴───┴───┘ /// │ /// · /// · /// · /// │ /// 0 ··· 7 ··· /// ├───┼───┼─────┼───┤ /// │ ∅ │ ∅ │ D E │ ∅ │ depth 16 (maximum depth) /// └───┴───┴─────┴───┘ /// ``` /// /// Note that we stop the insertion process early when possible. In the example above we did not /// had to expand the tree any further to accommodate *C*, since there is no other entry with a /// hash that starts with `0b0010`. The entries *A* and *B* exemplifies the case where a single /// level is not enough because their hash both start with `0b0110`. In case of a full hash /// collision we dig through all the levels of the tree so we get to the final leaf where a /// collision exists, like we can see in the case of *D* and *E*. /// /// # Invariants /// /// The tree has the following invariants (among others): /// /// 1. The root is the only node that can have zero children. /// 2. A node with a collision can only exist at the maximum depth of the tree. /// 3. A non-root branch always have two or more entries under it (because it could be /// compressed). #[derive(Debug)] enum Node where P: SharedPointerKind, { Branch(SparseArrayUsize, P>>), Leaf(Bucket), } #[derive(Debug)] enum Bucket where P: SharedPointerKind, { Single(EntryWithHash), Collision(List, P>), } #[derive(Debug)] struct EntryWithHash where P: SharedPointerKind, { entry: SharedPointer, P>, key_hash: HashValue, } mod node_utils { use super::HashValue; use core::hash::BuildHasher; use core::hash::Hash; use core::hash::Hasher; use core::mem::size_of_val; /// Returns the index of the array for the given hash on depth `depth`. /// /// When the hash is exhausted, meaning that we are at the maximum depth, this returns `None`. #[inline] pub fn index_from_hash(hash: HashValue, depth: usize, degree: u8) -> Option { debug_assert!(degree.is_power_of_two()); #[allow(clippy::cast_possible_truncation)] let shift = depth as u32 * degree.trailing_zeros(); #[allow(clippy::cast_lossless)] if (shift as usize) < 8 * size_of_val(&hash) { let mask = degree as HashValue - 1; #[allow(clippy::cast_possible_truncation)] Some(((hash >> shift) & mask) as usize) } else { None } } pub fn hash(v: &T, hasher_builder: &H) -> HashValue { let mut hasher = hasher_builder.build_hasher(); v.hash(&mut hasher); hasher.finish() } } impl Node where K: Eq + Hash, P: SharedPointerKind, { fn new_empty_branch() -> Node { Node::Branch(SparseArrayUsize::new()) } fn get( &self, key: &Q, key_hash: HashValue, depth: usize, degree: u8, ) -> Option<&EntryWithHash> where K: Borrow, Q: Hash + Eq, { match self { Node::Branch(subtrees) => { let index: usize = node_utils::index_from_hash(key_hash, depth, degree) .expect("hash cannot be exhausted if we are on a branch"); subtrees .get(index) .and_then(|subtree| subtree.get(key, key_hash, depth + 1, degree)) } Node::Leaf(bucket) => bucket.get(key, key_hash), } } fn get_mut( &mut self, key: &Q, key_hash: HashValue, depth: usize, degree: u8, ) -> Option<&mut EntryWithHash> where K: Borrow, Q: Hash + Eq, { match self { Node::Branch(subtrees) => { let index: usize = node_utils::index_from_hash(key_hash, depth, degree) .expect("hash cannot be exhausted if we are on a branch"); subtrees.get_mut(index).and_then(|subtree| { SharedPointer::make_mut(subtree).get_mut(key, key_hash, depth + 1, degree) }) } Node::Leaf(bucket) => bucket.get_mut(key, key_hash), } } /// Returns a pair with the node with the new entry and whether the key is new. fn insert(&mut self, entry: EntryWithHash, depth: usize, degree: u8) -> bool { match self { Node::Branch(subtrees) => { let index: usize = node_utils::index_from_hash(entry.key_hash, depth, degree) .expect("hash cannot be exhausted if we are on a branch"); match subtrees.get_mut(index) { Some(subtree) => { SharedPointer::make_mut(subtree).insert(entry, depth + 1, degree) } None => { let new_subtree = Node::Leaf(Bucket::Single(entry)); subtrees.set(index, SharedPointer::new(new_subtree)); true } } } Node::Leaf(bucket) => { // If we are at maximum depth then the hash was totally consumed and we have a // collision. let maximum_depth = node_utils::index_from_hash(entry.key_hash, depth, degree).is_none(); let bucket_contains_key: bool = bucket.contains_key(entry.key(), entry.key_hash); match maximum_depth { // We reached a bucket. If the bucket contains the key we are inserting then // we just need to replace it. false if bucket_contains_key => bucket.insert(entry), // We reached a bucket and the key we will insert is not there. We need to // create a `Node::Branch` and insert the elements of the bucket there, as well // as the new element. false => { // TODO This clone should not be needed. let old_entry: EntryWithHash = match bucket { Bucket::Single(e) => e.clone(), Bucket::Collision(_) => unreachable!( "hash is not exhausted, so there cannot be a collision here" ), }; *self = Node::new_empty_branch(); self.insert(old_entry, depth, degree); self.insert(entry, depth, degree); true } // Hash was already totally consumed. This is a collision. true => bucket.insert(entry), } } } } /// Compresses a node. This makes the shallowest tree that is well-formed, i.e. branches with /// a single entry become a leaf with it. fn compress(&mut self) { let new_node = match self { Node::Branch(subtrees) => { match subtrees.size() { 1 => { let compress: bool = { let subtree = subtrees.first().unwrap(); // Keep collision at the bottom of the tree. matches!(subtree.borrow(), Node::Leaf(Bucket::Single(_))) }; match compress { true => subtrees.pop(), false => None, } } _ => None, } } Node::Leaf(_) => None, }; if let Some(node) = new_node { crate::utils::replace(self, node); } } /// Returns `true` if the key was present. fn remove(&mut self, key: &Q, key_hash: HashValue, depth: usize, degree: u8) -> bool where K: Borrow, Q: Hash + Eq, { match self { Node::Branch(subtrees) => { let index: usize = node_utils::index_from_hash(key_hash, depth, degree) .expect("hash cannot be exhausted if we are on a branch"); match subtrees.get_mut(index) { Some(subtree) => { let subtree = SharedPointer::make_mut(subtree); let removed = subtree.remove(key, key_hash, depth + 1, degree); match (subtree.is_empty(), removed) { (_, false) => (), (false, true) => { // Note that we still must call compress because it is possible that // we had a node with just one entry, which was not compressed // because it had a collision. Maybe now we do not have a collision // and we can compress it. self.compress(); } (true, true) => { subtrees.remove(index); self.compress(); } }; removed } None => false, } } Node::Leaf(bucket) => { let mut bucket_ref = Some(bucket); let removed = Bucket::remove(&mut bucket_ref, key, key_hash); if bucket_ref.is_none() { // TODO Most of these empty branches will be dropped very soon. We might // gain some speed if we avoid this. (However, currently no heap // allocation happens anyway.) // We can do something similar to Bucket::remove() where we receive // a `&mut Option<&mut Bucket<_, _>>`. *self = Node::new_empty_branch(); } removed } } } fn is_empty(&self) -> bool { match self { Node::Branch(subtrees) => subtrees.size() == 0, Node::Leaf(Bucket::Single(_)) => false, Node::Leaf(Bucket::Collision(entries)) => { debug_assert!(entries.len() >= 2, "collisions must have at least two entries"); false } } } } impl Clone for Node where K: Eq + Hash, P: SharedPointerKind, { fn clone(&self) -> Node { match self { Node::Branch(subtrees) => Node::Branch(subtrees.clone()), Node::Leaf(bucket) => Node::Leaf(bucket.clone()), } } } mod bucket_utils { use super::*; pub fn list_remove_first bool>( list: &mut List, predicate: F, ) -> Option { let mut before_needle: Vec = Vec::with_capacity(list.len()); let remaining: &mut List = list; let mut removed = None; while !remaining.is_empty() { let e: T = remaining.first().unwrap().clone(); remaining.drop_first_mut(); if predicate(&e) { removed = Some(e); break; } before_needle.push(e); } let new_entries = remaining; while let Some(e) = before_needle.pop() { new_entries.push_front_mut(e); } removed } } impl Bucket where K: Eq + Hash, P: SharedPointerKind, { fn get(&self, key: &Q, key_hash: HashValue) -> Option<&EntryWithHash> where K: Borrow, Q: Hash + Eq, { match self { Bucket::Single(entry) if entry.matches(key, key_hash) => Some(entry), Bucket::Single(_) => None, Bucket::Collision(entries) => entries.iter().find(|e| e.matches(key, key_hash)), } } fn get_mut( &mut self, key: &Q, key_hash: HashValue, ) -> Option<&mut EntryWithHash> where K: Borrow, Q: Hash + Eq, { match self { Bucket::Single(entry) if entry.matches(key, key_hash) => Some(entry), Bucket::Single(_) => None, Bucket::Collision(entries) => { let removed = bucket_utils::list_remove_first(entries, |e| e.matches(key, key_hash)); removed.and_then(|e| { entries.push_front_mut(e); entries.first_mut() }) } } } #[inline] fn contains_key(&self, key: &Q, key_hash: HashValue) -> bool where K: Borrow, Q: Hash + Eq, { self.get(key, key_hash).is_some() } /// Returns `true` if the key is new. /// /// If there is a collision then `entry` will be put on the front of the entries list to /// improve performance with high temporal locality (since `get()` will try to match according /// to the list order). The order of the rest of the list must be preserved for the same /// reason. fn insert(&mut self, entry: EntryWithHash) -> bool { match self { Bucket::Single(existing_entry) if existing_entry.matches(entry.key(), entry.key_hash) => { *existing_entry = entry; false } Bucket::Single(existing_entry) => { let mut entries = List::new_with_ptr_kind(); // TODO In theory we should not need to clone `existing_entry`. entries.push_front_mut(existing_entry.clone()); entries.push_front_mut(entry); *self = Bucket::Collision(entries); true } Bucket::Collision(entries) => { let key_existed = bucket_utils::list_remove_first(entries, |e| { e.matches(entry.key(), entry.key_hash) }) .is_some(); entries.push_front_mut(entry); !key_existed } } } /// Returns `true` if the key was present. /// /// If the bucket becomes empty `bucket` it be set to `None`. fn remove( bucket: &mut Option<&mut Bucket>, key: &Q, key_hash: HashValue, ) -> bool where K: Borrow, Q: Hash + Eq, { match bucket.take() { Some(b) => { match b { Bucket::Single(existing_entry) if existing_entry.matches(key, key_hash) => { // bucket is already `None`. true } Bucket::Single(_) => { // Nothing to change. *bucket = Some(b); false } Bucket::Collision(entries) => { let removed = bucket_utils::list_remove_first(entries, |e| e.matches(key, key_hash)) .is_some(); match entries.len() { 0 => unreachable!( "impossible to have collision with a single or no entry" ), 1 => { let entry = entries.first().unwrap().clone(); *b = Bucket::Single(entry); } _ => (), }; *bucket = Some(b); removed } } } None => false, } } } impl Clone for Bucket where K: Eq + Hash, P: SharedPointerKind, { fn clone(&self) -> Bucket { match self { Bucket::Single(entry) => Bucket::Single(EntryWithHash::clone(entry)), Bucket::Collision(entries) => Bucket::Collision(List::clone(entries)), } } } impl EntryWithHash where K: Eq + Hash, P: SharedPointerKind, { fn new(key: K, value: V, hash_builder: &H) -> EntryWithHash { let key_hash = node_utils::hash(&key, hash_builder); EntryWithHash { entry: SharedPointer::new(Entry::new(key, value)), key_hash } } fn key(&self) -> &K { &self.entry.key } fn value(&self) -> &V { &self.entry.value } #[inline] fn matches(&self, key: &Q, key_hash: HashValue) -> bool where K: Borrow, Q: Hash + Eq, { self.key_hash == key_hash && self.key().borrow() == key } } impl EntryWithHash where K: Eq + Hash + Clone, V: Clone, P: SharedPointerKind, { fn value_mut(&mut self) -> &mut V { &mut SharedPointer::make_mut(&mut self.entry).value } } impl Clone for EntryWithHash where K: Eq + Hash, P: SharedPointerKind, { fn clone(&self) -> EntryWithHash { EntryWithHash { entry: SharedPointer::clone(&self.entry), key_hash: self.key_hash } } } impl HashTrieMap where K: Eq + Hash, { #[must_use] pub fn new() -> HashTrieMap { HashTrieMap::new_with_degree(DEFAULT_DEGREE) } #[must_use] pub fn new_with_degree(degree: u8) -> HashTrieMap { HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(DefaultBuildHasher::default(), degree) } } impl HashTrieMapSync where K: Eq + Hash, { #[must_use] pub fn new_sync() -> HashTrieMapSync { HashTrieMap::new_sync_with_degree(DEFAULT_DEGREE) } #[must_use] pub fn new_sync_with_degree(degree: u8) -> HashTrieMapSync { HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(DefaultBuildHasher::default(), degree) } } impl HashTrieMap where K: Eq + Hash, H: Clone, P: SharedPointerKind, { #[must_use] pub fn new_with_hasher_and_ptr_kind(hasher_builder: H) -> HashTrieMap { HashTrieMap::new_with_hasher_and_degree_and_ptr_kind(hasher_builder, DEFAULT_DEGREE) } #[must_use] pub fn new_with_hasher_and_degree_and_ptr_kind( hasher_builder: H, degree: u8, ) -> HashTrieMap { assert!(degree.is_power_of_two(), "degree must be a power of two"); assert!(degree <= DEFAULT_DEGREE, "degree is too big"); HashTrieMap { root: SharedPointer::new(Node::new_empty_branch()), size: 0, degree, hasher_builder, } } #[must_use] pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Hash + Eq, { let key_hash = node_utils::hash(key, &self.hasher_builder); self.root.get(key, key_hash, 0, self.degree).map(EntryWithHash::value) } #[must_use] pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> where K: Borrow, Q: Hash + Eq, { let key_hash = node_utils::hash(key, &self.hasher_builder); self.root.get(key, key_hash, 0, self.degree).map(|e| (e.key(), e.value())) } #[must_use] pub fn insert(&self, key: K, value: V) -> HashTrieMap { let mut new_map = self.clone(); new_map.insert_mut(key, value); new_map } pub fn insert_mut(&mut self, key: K, value: V) { let entry = EntryWithHash::new(key, value, &self.hasher_builder); let is_new_key = SharedPointer::make_mut(&mut self.root).insert(entry, 0, self.degree); if is_new_key { self.size += 1; } } #[must_use] pub fn remove(&self, key: &Q) -> HashTrieMap where K: Borrow, Q: Hash + Eq, { let mut new_map = self.clone(); if new_map.remove_mut(key) { new_map } else { // We want to keep maximum sharing so in case of no change we just `clone()` ourselves. self.clone() } } pub fn remove_mut(&mut self, key: &Q) -> bool where K: Borrow, Q: Hash + Eq, { let key_hash = node_utils::hash(key, &self.hasher_builder); let removed = SharedPointer::make_mut(&mut self.root).remove(key, key_hash, 0, self.degree); // Note that unfortunately, even if nothing was removed, we still might have cloned some // part of the tree unnecessarily. if removed { self.size -= 1; } removed } #[must_use] pub fn contains_key(&self, key: &Q) -> bool where K: Borrow, Q: Hash + Eq, { self.get(key).is_some() } /// Test whether the two maps refer to the same content in memory. /// /// This would return true if you’re comparing a map to itself, /// or if you’re comparing a map to a fresh clone of itself. pub(crate) fn ptr_eq( &self, other: &HashTrieMap, ) -> bool { let a = SharedPointer::as_ptr(&self.root); // Note how we're casting the raw pointer changing from P to PO // We cannot perform the equality in a type safe way because the root type depends // on P/PO, and we can't pass different types to SharedPtr::same_ptr or std::ptr::eq. let b = SharedPointer::as_ptr(&other.root).cast::>(); core::ptr::eq(a, b) } #[must_use] #[inline] pub fn size(&self) -> usize { self.size } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.size() == 0 } pub fn iter(&self) -> Iter<'_, K, V, P> { self.iter_ptr().map(|e| (&e.key, &e.value)) } #[must_use] fn iter_ptr(&self) -> IterPtr<'_, K, V, P> { IterPtr::new(self) } pub fn keys(&self) -> IterKeys<'_, K, V, P> { self.iter().map(|(k, _)| k) } pub fn values(&self) -> IterValues<'_, K, V, P> { self.iter().map(|(_, v)| v) } } impl HashTrieMap where K: Eq + Hash + Clone, V: Clone, H: Clone, P: SharedPointerKind, { pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Hash + Eq, { // Note that unfortunately, even if nothing is found, we still might have cloned some // part of the tree unnecessarily. let key_hash = node_utils::hash(key, &self.hasher_builder); SharedPointer::make_mut(&mut self.root) .get_mut(key, key_hash, 0, self.degree) .map(EntryWithHash::value_mut) } } impl<'a, K, Q: ?Sized, V, P, H: BuildHasher> Index<&'a Q> for HashTrieMap where K: Eq + Hash + Borrow, Q: Hash + Eq, H: Clone, P: SharedPointerKind, { type Output = V; fn index(&self, key: &Q) -> &V { self.get(key).expect("no entry found for key") } } impl Clone for HashTrieMap where K: Eq + Hash, H: Clone, P: SharedPointerKind, { fn clone(&self) -> HashTrieMap { HashTrieMap { root: SharedPointer::clone(&self.root), size: self.size, degree: self.degree, hasher_builder: self.hasher_builder.clone(), } } } impl Default for HashTrieMap where K: Eq + Hash, H: Default + Clone, P: SharedPointerKind, { fn default() -> HashTrieMap { HashTrieMap::new_with_hasher_and_ptr_kind(H::default()) } } impl PartialEq> for HashTrieMap where K: Hash, H: Clone, P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &HashTrieMap) -> bool { if self.ptr_eq(other) { return true; } self.size() == other.size() && self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) } } impl Eq for HashTrieMap where K: Hash, H: Clone, P: SharedPointerKind, { } impl Display for HashTrieMap where K: Eq + Hash + Display, V: Display, H: Clone, P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("{")?; for (k, v) in self.iter() { if !first { fmt.write_str(", ")?; } k.fmt(fmt)?; fmt.write_str(": ")?; v.fmt(fmt)?; first = false; } fmt.write_str("}") } } impl<'a, K, V, P, H: BuildHasher> IntoIterator for &'a HashTrieMap where K: Eq + Hash, H: Default + Clone, P: SharedPointerKind, { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V, P>; fn into_iter(self) -> Iter<'a, K, V, P> { self.iter() } } impl FromIterator<(K, V)> for HashTrieMap where K: Eq + Hash, H: BuildHasher + Clone + Default, P: SharedPointerKind, { fn from_iter>(into_iter: I) -> HashTrieMap { let mut map = HashTrieMap::new_with_hasher_and_ptr_kind(Default::default()); for (k, v) in into_iter { map.insert_mut(k, v); } map } } #[derive(Debug)] pub struct IterPtr<'a, K, V, P> where P: SharedPointerKind, { stack: Vec>, size: usize, } #[derive(Debug)] enum IterStackElement<'a, K, V, P> where P: SharedPointerKind, { Branch(slice::Iter<'a, SharedPointer, P>>), LeafCollision(list::Iter<'a, EntryWithHash, P>), LeafSingle(iter::Once<&'a SharedPointer, P>>), } impl<'a, K, V, P> IterStackElement<'a, K, V, P> where K: Eq + Hash, P: SharedPointerKind, { #[inline] fn new(node: &Node) -> IterStackElement<'_, K, V, P> { match node { Node::Branch(children) => IterStackElement::Branch(children.iter()), Node::Leaf(Bucket::Collision(entries)) => { IterStackElement::LeafCollision(entries.iter()) } Node::Leaf(Bucket::Single(entry)) => { IterStackElement::LeafSingle(iter::once(&entry.entry)) } } } /// Returns the next `Entry` _or_ the next `IterStackElement` to be pushed into the stack. /// If the result is None the `IterStackElement` should be popped from the stack. #[inline] fn next(&mut self) -> Option, P>, Self>> { match self { IterStackElement::Branch(i) => i.next().map(|node| match &**node { Node::Branch(_) | Node::Leaf(Bucket::Collision(_)) => { Err(IterStackElement::new(node)) } Node::Leaf(Bucket::Single(e)) => Ok(&e.entry), }), IterStackElement::LeafCollision(i) => i.next().map(|i| Ok(&i.entry)), IterStackElement::LeafSingle(i) => i.next().map(Ok), } } } mod iter_utils { use super::HashValue; pub fn trie_max_height(degree: u8) -> usize { let bits_per_level = (degree - 1).count_ones() as usize; let hash_bits = HashValue::BITS as usize; (hash_bits / bits_per_level) + usize::from(hash_bits % bits_per_level > 0) } } impl<'a, K, V, P> IterPtr<'a, K, V, P> where K: Eq + Hash, P: SharedPointerKind, { fn new(map: &HashTrieMap) -> IterPtr<'_, K, V, P> { let mut stack: Vec> = Vec::with_capacity(iter_utils::trie_max_height(map.degree) + 1); if map.size() > 0 { stack.push(IterStackElement::new(map.root.borrow())); } IterPtr { stack, size: map.size() } } } impl<'a, K, V, P> Iterator for IterPtr<'a, K, V, P> where K: Eq + Hash, P: SharedPointerKind, { type Item = &'a SharedPointer, P>; fn next(&mut self) -> Option<&'a SharedPointer, P>> { while let Some(stack_element) = self.stack.last_mut() { match stack_element.next() { Some(Ok(elem)) => { self.size -= 1; return Some(elem); } Some(Err(stack_elem)) => { self.stack.push(stack_elem); } None => { self.stack.pop(); } } } None } #[inline] fn size_hint(&self) -> (usize, Option) { (self.size, Some(self.size)) } } impl<'a, K: Eq + Hash, V, P> ExactSizeIterator for IterPtr<'a, K, V, P> where P: SharedPointerKind {} #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer, MapAccess, Visitor}; use ::serde::ser::{Serialize, Serializer}; use core::fmt; use core::marker::PhantomData; impl Serialize for HashTrieMap where K: Eq + Hash + Serialize, V: Serialize, H: BuildHasher + Clone + Default, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { serializer.collect_map(self) } } impl<'de, K, V, P, H> Deserialize<'de> for HashTrieMap where K: Eq + Hash + Deserialize<'de>, V: Deserialize<'de>, H: BuildHasher + Clone + Default, P: SharedPointerKind, { fn deserialize>( deserializer: D, ) -> Result, D::Error> { deserializer.deserialize_map(HashTrieMapVisitor { _phantom_entry: PhantomData, _phantom_h: PhantomData, _phantom_p: PhantomData, }) } } struct HashTrieMapVisitor where P: SharedPointerKind, { _phantom_entry: PhantomData<(K, V)>, _phantom_h: PhantomData, _phantom_p: PhantomData

, } impl<'de, K, V, P, H> Visitor<'de> for HashTrieMapVisitor where K: Eq + Hash + Deserialize<'de>, V: Deserialize<'de>, H: BuildHasher + Clone + Default, P: SharedPointerKind, { type Value = HashTrieMap; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a map") } fn visit_map(self, mut map: A) -> Result, A::Error> where A: MapAccess<'de>, { let mut hash_trie_map = HashTrieMap::new_with_hasher_and_ptr_kind(Default::default()); while let Some((k, v)) = map.next_entry()? { hash_trie_map.insert_mut(k, v); } Ok(hash_trie_map) } } } #[cfg(test)] mod test; rpds/src/lib.rs0000644000175000017500000002736514661133735014431 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(feature = "fatal-warnings", deny(warnings))] #![deny(clippy::correctness)] #![warn(clippy::pedantic)] #![allow(clippy::match_bool)] #![allow(clippy::if_not_else)] #![allow(clippy::module_name_repetitions)] #![allow(clippy::similar_names)] #![allow(clippy::use_self)] #![allow(clippy::single_match_else)] #![allow(clippy::unnested_or_patterns)] #![allow(clippy::wildcard_imports)] #![allow(clippy::match_same_arms)] #![allow(clippy::missing_panics_doc)] #![allow(clippy::type_complexity)] #![allow(clippy::enum_glob_use)] #![allow(clippy::type_repetition_in_bounds)] // TODO This is only needed because `cargo-rdme` requires a path like `crate::⋯`. Once that limitation is // lifted we can remove this. #![allow(rustdoc::redundant_explicit_links)] // Note: If you change this remember to update `README.md`. To do so run `cargo rdme`. //! Rust Persistent Data Structures provides [fully persistent data structures](https://en.wikipedia.org/wiki/Persistent_data_structure) //! with structural sharing. //! //! # Setup //! //! To use rpds add the following to your `Cargo.toml`: //! //! ```toml //! [dependencies] //! rpds = "" //! ``` //! //! # Data structures //! //! This crate offers the following data structures: //! //! 1. [`List`](#list) //! 2. [`Vector`](#vector) //! 3. [`Stack`](#stack) //! 4. [`Queue`](#queue) //! 5. [`HashTrieMap`](#hashtriemap) //! 6. [`HashTrieSet`](#hashtrieset) //! 7. [`RedBlackTreeMap`](#redblacktreemap) //! 8. [`RedBlackTreeSet`](#redblacktreeset) //! //! ## `List` //! [![List documentation](https://img.shields.io/badge/doc-List-303070.svg)](crate::list::List) //! //! Your classic functional list. //! //! ### Example //! //! ```rust //! use rpds::List; //! //! let list = List::new().push_front("list"); //! //! assert_eq!(list.first(), Some(&"list")); //! //! let a_list = list.push_front("a"); //! //! assert_eq!(a_list.first(), Some(&"a")); //! //! let list_dropped = a_list.drop_first().unwrap(); //! //! assert_eq!(list_dropped, list); //! ``` //! //! ## `Vector` //! [![`Vector` documentation](https://img.shields.io/badge/doc-Vector-303070.svg)](crate::vector::Vector) //! //! A sequence that can be indexed. The implementation is described in //! [Understanding Persistent Vector Part 1](http://hypirion.com/musings/understanding-persistent-vector-pt-1) //! and [Understanding Persistent Vector Part 2](http://hypirion.com/musings/understanding-persistent-vector-pt-2). //! //! ### Example //! //! ```rust //! use rpds::Vector; //! //! let vector = Vector::new() //! .push_back("I’m") //! .push_back("a") //! .push_back("vector"); //! //! assert_eq!(vector[1], "a"); //! //! let screaming_vector = vector //! .drop_last().unwrap() //! .push_back("VECTOR!!!"); //! //! assert_eq!(screaming_vector[2], "VECTOR!!!"); //! ``` //! //! ## `Stack` //! [![`Stack` documentation](https://img.shields.io/badge/doc-Stack-303070.svg)](crate::stack::Stack) //! //! A LIFO (last in, first out) data structure. This is just a [`List`](#list) in disguise. //! //! ### Example //! //! ```rust //! use rpds::Stack; //! //! let stack = Stack::new().push("stack"); //! //! assert_eq!(stack.peek(), Some(&"stack")); //! //! let a_stack = stack.push("a"); //! //! assert_eq!(a_stack.peek(), Some(&"a")); //! //! let stack_popped = a_stack.pop().unwrap(); //! //! assert_eq!(stack_popped, stack); //! ``` //! //! ## `Queue` //! [![`Queue` documentation](https://img.shields.io/badge/doc-Queue-303070.svg)](crate::queue::Queue) //! //! A FIFO (first in, first out) data structure. //! //! ### Example //! //! ```rust //! use rpds::Queue; //! //! let queue = Queue::new() //! .enqueue("um") //! .enqueue("dois") //! .enqueue("tres"); //! //! assert_eq!(queue.peek(), Some(&"um")); //! //! let queue_dequeued = queue.dequeue().unwrap(); //! //! assert_eq!(queue_dequeued.peek(), Some(&"dois")); //! ``` //! //! ## `HashTrieMap` //! [![`HashTrieMap` documentation](https://img.shields.io/badge/doc-HashTrieMap-303070.svg)](crate::map::hash_trie_map::HashTrieMap) //! //! A map implemented with a [hash array mapped trie](https://en.wikipedia.org/wiki/Hash_array_mapped_trie). //! See [Ideal Hash Trees](https://infoscience.epfl.ch/record/64398/files/idealhashtrees.pdf) for //! details. //! //! ### Example //! //! ```rust //! use rpds::HashTrieMap; //! //! let map_en = HashTrieMap::new() //! .insert(0, "zero") //! .insert(1, "one"); //! //! assert_eq!(map_en.get(&1), Some(&"one")); //! //! let map_pt = map_en //! .insert(1, "um") //! .insert(2, "dois"); //! //! assert_eq!(map_pt.get(&2), Some(&"dois")); //! //! let map_pt_binary = map_pt.remove(&2); //! //! assert_eq!(map_pt_binary.get(&2), None); //! ``` //! //! ## `HashTrieSet` //! [![`HashTrieSet` documentation](https://img.shields.io/badge/doc-HashTrieSet-303070.svg)](crate::set::hash_trie_set::HashTrieSet) //! //! A set implemented with a [`HashTrieMap`](#hashtriemap). //! //! ### Example //! //! ```rust //! use rpds::HashTrieSet; //! //! let set = HashTrieSet::new() //! .insert("zero") //! .insert("one"); //! //! assert!(set.contains(&"one")); //! //! let set_extended = set.insert("two"); //! //! assert!(set_extended.contains(&"two")); //! //! let set_positive = set_extended.remove(&"zero"); //! //! assert!(!set_positive.contains(&"zero")); //! ``` //! //! ## `RedBlackTreeMap` //! [![`RedBlackTreeMap` documentation](https://img.shields.io/badge/doc-RedBlackTreeMap-303070.svg)](crate::map::red_black_tree_map::RedBlackTreeMap) //! //! A map implemented with a [red-black tree](https://en.wikipedia.org/wiki/Red-Black_tree). //! //! ### Example //! //! ```rust //! use rpds::RedBlackTreeMap; //! //! let map_en = RedBlackTreeMap::new() //! .insert(0, "zero") //! .insert(1, "one"); //! //! assert_eq!(map_en.get(&1), Some(&"one")); //! //! let map_pt = map_en //! .insert(1, "um") //! .insert(2, "dois"); //! //! assert_eq!(map_pt.get(&2), Some(&"dois")); //! //! let map_pt_binary = map_pt.remove(&2); //! //! assert_eq!(map_pt_binary.get(&2), None); //! //! assert_eq!(map_pt_binary.first(), Some((&0, &"zero"))); //! ``` //! //! ## `RedBlackTreeSet` //! [![`RedBlackTreeSet` documentation](https://img.shields.io/badge/doc-RedBlackTreeSet-303070.svg)](crate::set::red_black_tree_set::RedBlackTreeSet) //! //! A set implemented with a [`RedBlackTreeMap`](#redblacktreemap). //! //! ### Example //! //! ```rust //! use rpds::RedBlackTreeSet; //! //! let set = RedBlackTreeSet::new() //! .insert("zero") //! .insert("one"); //! //! assert!(set.contains(&"one")); //! //! let set_extended = set.insert("two"); //! //! assert!(set_extended.contains(&"two")); //! //! let set_positive = set_extended.remove(&"zero"); //! //! assert!(!set_positive.contains(&"zero")); //! //! assert_eq!(set_positive.first(), Some(&"one")); //! ``` //! //! # Other features //! //! ## Mutable methods //! //! When you change a data structure you often do not need its previous versions. For those cases //! rpds offers you mutable methods which are generally faster: //! //! ```rust //! use rpds::HashTrieSet; //! //! let mut set = HashTrieSet::new(); //! //! set.insert_mut("zero"); //! set.insert_mut("one"); //! //! let set_0_1 = set.clone(); //! let set_0_1_2 = set.insert("two"); //! ``` //! //! ## Initialization macros //! //! There are convenient initialization macros for all data structures: //! //! ```rust //! use rpds::*; //! //! let vector = vector![3, 1, 4, 1, 5]; //! let map = ht_map!["orange" => "orange", "banana" => "yellow"]; //! ``` //! //! Check the documentation for initialization macros of other data structures. //! //! ## Thread safety //! //! All data structures in this crate can be shared between threads, but that is an opt-in ability. //! This is because there is a performance cost to make data structures thread safe. That cost //! is worth avoiding when you are not actually sharing them between threads. //! //! Of course if you try to share a rpds data structure across different threads you can count on //! the rust compiler to ensure that it is safe to do so. If you are using the version of the data //! structure that is not thread safe you will get a compile-time error. //! //! To create a thread-safe version of any data structure use `new_sync()`: //! //! ```rust //! # use rpds::Vector; //! # //! let vec = Vector::new_sync() //! .push_back(42); //! ``` //! //! Or use the `_sync` variant of the initialization macro: //! //! ```rust //! # use rpds::vector_sync; //! # //! let vec = vector_sync!(42); //! ``` //! //! ### Further details //! //! Internally the data structures in this crate maintain a lot of reference-counting pointers. //! These pointers are used both for links between the internal nodes of the data structure as well //! as for the values it stores. //! //! There are two implementations of reference-counting pointers in the standard library: //! [`Rc`](::alloc::rc::Rc) and //! [`Arc`](::alloc::sync::Arc). They behave the same way, but //! `Arc` allows you to share the data it points to across multiple threads. The downside is that //! it is significantly slower to clone and drop than `Rc`, and persistent data structures do a //! lot of those operations. In some microbenchmarks with rpds data structure we can see that //! using `Rc` instead of `Arc` can make some operations twice as fast! You can see this for //! yourself by running `cargo bench`. //! //! To implement this we parameterize the type of reference-counting pointer (`Rc` or `Arc`) as a //! type argument of the data structure. We use the [archery](https://github.com/orium/archery/) //! crate to do this in a convenient way. //! //! The pointer type can be parameterized like this: //! //! ```rust //! # use rpds::Vector; //! # //! let vec: Vector = Vector::new_with_ptr_kind(); //! // ↖ //! // This will use `Arc` pointers. //! // Change it to `archery::RcK` to use a `Rc` pointer. //! ``` //! //! ## `no_std` support //! //! This crate supports `no_std`. To enable that you need to disable the default feature `std`: //! //! ```toml //! [dependencies] //! rpds = { version = "", default-features = false } //! ``` //! //! ## Serialization //! //! We support serialization through [serde](https://crates.io/crates/serde). To use it //! enable the `serde` feature. To do so change the rpds dependency in your `Cargo.toml` to //! //! ```toml //! [dependencies] //! rpds = { version = "", features = ["serde"] } //! ``` //! //! ## Bindings //! //! Bindings to use rpds from other programming languages exist. Below is a short list of those //! known to date. //! //! * [rpds.py](https://github.com/crate-py/rpds/) – Python //! //! Please feel free to send a pull request should you add support in a new language. extern crate alloc; #[cfg(test)] #[macro_use] extern crate std; mod utils; #[macro_use] pub mod list; pub mod map; pub mod queue; pub mod set; pub mod stack; pub mod vector; pub use crate::list::List; pub use crate::list::ListSync; pub use crate::map::hash_trie_map::HashTrieMap; pub use crate::map::hash_trie_map::HashTrieMapSync; pub use crate::map::red_black_tree_map::RedBlackTreeMap; pub use crate::map::red_black_tree_map::RedBlackTreeMapSync; pub use crate::queue::Queue; pub use crate::queue::QueueSync; pub use crate::set::hash_trie_set::HashTrieSet; pub use crate::set::hash_trie_set::HashTrieSetSync; pub use crate::set::red_black_tree_set::RedBlackTreeSet; pub use crate::set::red_black_tree_set::RedBlackTreeSetSync; pub use crate::stack::Stack; pub use crate::stack::StackSync; pub use crate::vector::Vector; pub use crate::vector::VectorSync; rpds/src/vector/0000775000175000017500000000000014661133735014604 5ustar jamespagejamespagerpds/src/vector/test.rs0000644000175000017500000004704614661133735016142 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use alloc::string::String; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(VectorSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_vector_sync_is_send_and_sync() -> impl Send + Sync { vector_sync!(0) } impl PartialEq for Node where P: SharedPointerKind, { fn eq(&self, other: &Node) -> bool { match (self, other) { (Node::Branch(v), Node::Branch(vo)) => v == vo, (Node::Leaf(v), Node::Leaf(vo)) => v == vo, _ => false, } } } impl Eq for Node where P: SharedPointerKind {} mod node { use super::*; use pretty_assertions::assert_eq; #[test] fn test_new_empty_branch() { let node: Node = Node::new_empty_branch(); match node { Node::Branch(a) => { assert_eq!(a.len(), 0); assert_eq!(a.capacity(), 0, "Capacity of the branch array is wasteful"); } Node::Leaf(_) => panic!("Invalid node type"), } } #[test] fn test_new_empty_leaf() { let node: Node = Node::new_empty_leaf(); match node { Node::Leaf(a) => { assert_eq!(a.len(), 0); assert_eq!(a.capacity(), 0, "Capacity of the leaf array is wasteful"); } Node::Branch(_) => panic!("Invalid node type"), } } #[test] fn test_drop_last_single_level() { let mut empty_leaf: Node = Node::new_empty_leaf(); let mut empty_branch: Node = Node::new_empty_branch(); let mut singleton_node: Node = vector![0].root.as_ref().clone(); let mut one_level_node: Node = vector![0, 1].root.as_ref().clone(); assert!(empty_leaf.drop_last()); assert!(empty_branch.drop_last()); assert!(singleton_node.drop_last()); assert!(!one_level_node.drop_last()); assert_eq!(one_level_node.used(), 1); } #[test] fn test_drop_last_multi_level() { let mut node_three: Node = Vector::new_with_bits(1).push_back(0).push_back(1).push_back(2).root.as_ref().clone(); let mut node_four: Node = Vector::new_with_bits(1) .push_back(0) .push_back(1) .push_back(2) .push_back(3) .root .as_ref() .clone(); let node_three_after_drop = { let a_leaf = vec![SharedPointer::new(0), SharedPointer::new(1)]; let leaf = Node::Leaf(a_leaf); let a_branch = vec![SharedPointer::new(leaf)]; Node::Branch(a_branch) }; let node_four_after_drop = { let a_leaf_0 = vec![SharedPointer::new(0), SharedPointer::new(1)]; let leaf_0 = Node::Leaf(a_leaf_0); let a_leaf_1 = { let mut a = Vec::with_capacity(2); a.push(SharedPointer::new(2)); a }; let leaf_1 = Node::Leaf(a_leaf_1); let a_branch = vec![SharedPointer::new(leaf_0), SharedPointer::new(leaf_1)]; Node::Branch(a_branch) }; assert!(!node_three.drop_last()); assert_eq!(node_three, node_three_after_drop); assert!(!node_four.drop_last()); assert_eq!(node_four, node_four_after_drop); } } mod iter { use super::*; use pretty_assertions::assert_eq; #[test] fn test_iter_empty() { let vector: Vector = Vector::new(); for _ in vector.iter() { panic!("iterator should be empty"); } } #[test] fn test_iter_empty_backwards() { let vector: Vector = Vector::new(); for _ in vector.iter().rev() { panic!("iterator should be empty"); } } #[test] fn test_iter_big_vector() { let limit = 32 * 32 * 32 + 1; let mut vector = Vector::new(); let mut expected = 0; let mut left = limit; for i in 0..limit { vector = vector.push_back(i); } for v in vector.iter() { left -= 1; assert!(left >= 0); assert_eq!(*v, expected); expected += 1; } assert_eq!(left, 0); } #[test] fn test_iter_big_vector_backwards() { let limit = 32 * 32 * 32 + 1; let mut vector = Vector::new(); let mut expected = limit - 1; let mut left = limit; for i in 0..limit { vector = vector.push_back(i); } for v in vector.iter().rev() { left -= 1; assert!(left >= 0); assert_eq!(*v, expected); expected -= 1; } assert_eq!(left, 0); } #[test] fn test_iter_backwards() { let vector = vector![0, 1, 2, 3]; let mut expected = 3; let mut left = 4; for n in vector.iter().rev() { left -= 1; assert!(left >= 0); assert_eq!(*n, expected); expected -= 1; } assert_eq!(left, 0); } #[test] fn test_iter_both_directions() { let vector = vector![0, 1, 2, 3, 4, 5]; let mut iterator = vector.iter(); assert_eq!(iterator.next(), Some(&0)); assert_eq!(iterator.next_back(), Some(&5)); assert_eq!(iterator.next_back(), Some(&4)); assert_eq!(iterator.next(), Some(&1)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next_back(), Some(&3)); assert_eq!(iterator.next_back(), None); assert_eq!(iterator.next(), None); } #[test] fn test_iter_size_hint() { let vector = vector![0, 1, 2]; let mut iterator = vector.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next_back(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next_back(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_into_iterator() { let vector = vector![0, 1, 2, 3]; let mut left = 4; for (expected, n) in vector.into_iter().enumerate() { left -= 1; assert!(left >= 0); assert_eq!(*n, expected); } assert_eq!(left, 0); } } mod internal { use super::*; use pretty_assertions::assert_eq; fn dummy_vector_with_length(len: usize) -> Vector { let mut v = Vector::new_with_bits(5); v.length = len; v } #[test] fn test_degree() { use vector_utils::degree; assert_eq!(degree(1), 2); assert_eq!(degree(2), 4); assert_eq!(degree(3), 8); assert_eq!(degree(4), 16); assert_eq!(degree(5), 32); } #[test] fn test_height() { assert_eq!(dummy_vector_with_length(0).height(), 0); assert_eq!(dummy_vector_with_length(5).height(), 0); assert_eq!(dummy_vector_with_length(32).height(), 0); assert_eq!(dummy_vector_with_length(33).height(), 1); assert_eq!(dummy_vector_with_length(64).height(), 1); assert_eq!(dummy_vector_with_length(128).height(), 1); assert_eq!(dummy_vector_with_length(512).height(), 1); assert_eq!(dummy_vector_with_length(1024).height(), 1); assert_eq!(dummy_vector_with_length(1025).height(), 2); assert_eq!(dummy_vector_with_length(32_768).height(), 2); assert_eq!(dummy_vector_with_length(32_769).height(), 3); assert_eq!(dummy_vector_with_length(1_048_576).height(), 3); assert_eq!(dummy_vector_with_length(1_048_577).height(), 4); } #[test] fn test_mask() { use vector_utils::mask; assert_eq!(mask(1), 0b00001); assert_eq!(mask(2), 0b00011); assert_eq!(mask(3), 0b00111); assert_eq!(mask(4), 0b01111); assert_eq!(mask(5), 0b11111); } #[allow(clippy::unusual_byte_groupings)] #[test] fn test_bucket() { use vector_utils::bucket; assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 0), 0b00001); assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 1), 0b00010); assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 2), 0b00011); assert_eq!(bucket(5, 0b_00100_00011_00010_00001, 3), 0b00100); } #[test] fn test_compress_root() { let empty_leaf: Node = Node::new_empty_leaf(); let empty_branch: Node = Node::new_empty_branch(); let singleton_leaf: Node = vector![0].root.as_ref().clone(); let compressed_branch: Node = Vector::new_with_bits(1).push_back(0).push_back(1).push_back(3).root.as_ref().clone(); let (uncompressed_branch, uncompressed_branch_leaf) = { let leaf: Node<_, RcK> = Vector::new_with_bits(1).push_back(0).push_back(1).root.as_ref().clone(); let a_branch = { let mut a = Vec::with_capacity(2); a.push(SharedPointer::new(leaf.clone())); a }; (Node::Branch(a_branch), leaf) }; assert_eq!(Vector::compress_root(&mut empty_leaf.clone()), None); assert_eq!(Vector::compress_root(&mut empty_branch.clone()), None); assert_eq!(Vector::compress_root(&mut singleton_leaf.clone()), None); assert_eq!(Vector::compress_root(&mut compressed_branch.clone()), None); assert_eq!( Vector::compress_root(&mut uncompressed_branch.clone()), Some(SharedPointer::new(uncompressed_branch_leaf)), ); } #[test] fn test_root_max_capacity() { assert_eq!(dummy_vector_with_length(0).root_max_capacity(), 32); assert_eq!(dummy_vector_with_length(5).root_max_capacity(), 32); assert_eq!(dummy_vector_with_length(32).root_max_capacity(), 32); assert_eq!(dummy_vector_with_length(33).root_max_capacity(), 1024); assert_eq!(dummy_vector_with_length(1024).root_max_capacity(), 1024); assert_eq!(dummy_vector_with_length(1025).root_max_capacity(), 32_768); assert_eq!(dummy_vector_with_length(32_768).root_max_capacity(), 32_768); assert_eq!(dummy_vector_with_length(32_769).root_max_capacity(), 1_048_576); } #[test] fn test_is_root_full() { assert!(!dummy_vector_with_length(0).is_root_full()); assert!(!dummy_vector_with_length(5).is_root_full()); assert!(dummy_vector_with_length(32).is_root_full()); assert!(!dummy_vector_with_length(33).is_root_full()); assert!(dummy_vector_with_length(1024).is_root_full()); assert!(!dummy_vector_with_length(1025).is_root_full()); assert!(dummy_vector_with_length(32_768).is_root_full()); assert!(!dummy_vector_with_length(32_769).is_root_full()); } } #[test] fn test_macro_vector() { let vector_1 = Vector::new().push_back(1); let vector_1_2_3 = Vector::new().push_back(1).push_back(2).push_back(3); assert_eq!(Vector::::new(), vector![]); assert_eq!(vector_1, vector![1]); assert_eq!(vector_1_2_3, vector![1, 2, 3]); } #[test] fn test_push_back_adds_element() { let limit = 32 * 32 * 32 + 1; let mut vector: Vector = Vector::new(); for i in 0..limit { vector = vector.push_back(-i); assert_eq!(vector.get(i as usize), Some(&-i)); } } #[test] fn test_push_back_maintains_size() { let limit = 128; let mut vector: Vector = Vector::new(); for i in 0..limit { assert_eq!(vector.len(), i as usize); vector = vector.push_back(-i); } assert_eq!(vector.len(), limit as usize); } #[test] fn test_drop_last_drops_last_element() { let limit = 4 * 4 * 4 * 4 + 1; let mut vector: Vector = Vector::new_with_bits(2); let mut vectors = Vec::with_capacity(limit); for i in 0..limit { vector = vector.push_back(2 * i as i32); vectors.push(vector.clone()); } for _ in 0..limit { let v = vectors.pop().unwrap(); assert_eq!(vector, v); vector = vector.drop_last().unwrap(); } assert_eq!(vector, Vector::new()); } #[test] fn test_drop_last_keeps_vector_consistent() { let limit = 4 * 4 * 4 * 4 * 4 * 4 + 1; let mut vector: Vector = Vector::new_with_bits(2); for i in 0..limit { vector = vector.push_back(2 * i as i32); } for _ in 0..(limit / (4 * 4)) { vector = vector.drop_last().unwrap(); } let new_len = limit - limit / (4 * 4); for i in 0..new_len { assert_eq!(vector.get(i).unwrap(), &(2 * i as i32)); } assert_eq!(vector.get(new_len), None); } #[test] fn test_drop_last_maintains_size() { let limit = 128; let mut vector: Vector = Vector::new(); for i in 0..limit { vector = vector.push_back(-i); } for i in 0..limit { assert_eq!(vector.len(), (limit - i) as usize); vector = vector.drop_last().unwrap(); } assert_eq!(vector.len(), 0); } #[test] fn test_drop_last_on_empty_vector() { let vector: Vector = Vector::new(); assert_eq!(vector.drop_last(), None); } #[test] fn test_set_overwrites() { let limit = 32 * 32 + 1; let mut vector: Vector = Vector::new(); for i in 0..limit { vector = vector.push_back(-i); } vector = vector.set(834, 0).unwrap(); assert_eq!(vector.get(833), Some(&-833)); assert_eq!(vector.get(834), Some(&0)); assert_eq!(vector.get(835), Some(&-835)); assert_eq!(vector.get(limit as usize), None); } #[test] fn test_set_maintains_size() { let limit = 32 * 32 * 32; let mut vector: Vector = Vector::new(); for i in 0..limit { vector = vector.push_back(-i); } for i in 0..limit { vector = vector.set(i as usize, i * i).unwrap(); assert_eq!(vector.len(), limit as usize); } } #[test] fn test_set_out_of_bounds() { let empty_vector: Vector = Vector::new(); let singleton_vector: Vector = vector![0]; assert_eq!(empty_vector.set(0, 0), None); assert_eq!(singleton_vector.set(1, 0), None); } #[test] fn test_get() { let limit = 32 * 32 * 32 + 1; let mut vector = Vector::new(); for i in 0..limit { vector = vector.push_back(i + 1); } assert_eq!(vector.get(0), Some(&1)); assert_eq!(vector.get(2020), Some(&2021)); assert_eq!(vector.get(limit - 1), Some(&limit)); assert_eq!(vector.get(limit), None); } #[test] fn test_index() { let vector = vector![10, 11, 12]; assert_eq!(vector[0], 10); assert_eq!(vector[1], 11); assert_eq!(vector[2], 12); } #[test] fn test_first() { let empty_vector: Vector = Vector::new(); let vector = vector![1]; assert_eq!(empty_vector.first(), None); assert_eq!(vector.first(), Some(&1)); } #[test] fn test_last() { let empty_vector: Vector = Vector::new(); let vector = vector![1, 2]; assert_eq!(empty_vector.last(), None); assert_eq!(vector.last(), Some(&2)); } #[test] fn test_from_iterator() { let vec: Vec = vec![10, 11, 12, 13]; let vector: Vector = vec.iter().copied().collect(); assert!(vec.iter().eq(vector.iter())); } #[test] fn test_default() { let vector: Vector = Vector::default(); assert_eq!(vector.len(), 0); } #[test] fn test_display() { let empty_vector: Vector = Vector::new(); let singleton_vector = vector!["hello"]; let vector = vector![0, 1, 2, 3]; assert_eq!(format!("{}", empty_vector), "[]"); assert_eq!(format!("{}", singleton_vector), "[hello]"); assert_eq!(format!("{}", vector), "[0, 1, 2, 3]"); } #[test] fn test_eq() { let vector_1 = vector!["a", "a"]; let vector_1_prime = vector!["a", "a"]; let vector_2 = vector!["a", "b"]; let vector_3 = vector!["a", "b", "c"]; assert_ne!(vector_1, vector_2); assert_ne!(vector_2, vector_3); assert_eq!(vector_1, vector_1); assert_eq!(vector_1, vector_1_prime); assert_eq!(vector_2, vector_2); // We also check this since `assert_ne!()` does not call `ne`. assert!(vector_1.ne(&vector_2)); assert!(vector_2.ne(&vector_3)); } #[test] fn test_eq_pointer_kind_consistent() { let vector_a = vector!["a"]; let vector_a_sync = vector_sync!["a"]; let vector_b = vector!["b"]; let vector_b_sync = vector_sync!["b"]; assert!(vector_a == vector_a_sync); assert!(vector_a != vector_b_sync); assert!(vector_b == vector_b_sync); } #[test] fn test_partial_ord() { let vector_1 = vector!["a"]; let vector_1_prime = vector!["a"]; let vector_2 = vector!["b"]; let vector_3 = vector![0.0]; let vector_4 = vector![core::f32::NAN]; assert_eq!(vector_1.partial_cmp(&vector_1_prime), Some(Ordering::Equal)); assert_eq!(vector_1.partial_cmp(&vector_2), Some(Ordering::Less)); assert_eq!(vector_2.partial_cmp(&vector_1), Some(Ordering::Greater)); assert_eq!(vector_3.partial_cmp(&vector_4), None); } #[test] fn test_ord() { let vector_1 = vector!["a"]; let vector_1_prime = vector!["a"]; let vector_2 = vector!["b"]; assert_eq!(vector_1.cmp(&vector_1_prime), Ordering::Equal); assert_eq!(vector_1.cmp(&vector_2), Ordering::Less); assert_eq!(vector_2.cmp(&vector_1), Ordering::Greater); } #[test] fn test_ord_pointer_kind_consistent() { let vector_a = vector!["a"]; let vector_a_sync = vector_sync!["a"]; let vector_b = vector!["b"]; let vector_b_sync = vector_sync!["b"]; assert!(vector_a <= vector_a_sync); assert!(vector_a < vector_b_sync); assert!(vector_b >= vector_b_sync); assert!(vector_a_sync >= vector_a); assert!(vector_b_sync > vector_a); assert!(vector_b_sync <= vector_b); } fn hash(vector: &Vector) -> u64 { #[allow(deprecated)] let mut hasher = core::hash::SipHasher::new(); vector.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let vector_1 = vector!["a"]; let vector_1_prime = vector!["a"]; let vector_2 = vector!["a", "b"]; assert_eq!(hash(&vector_1), hash(&vector_1)); assert_eq!(hash(&vector_1), hash(&vector_1_prime)); assert_ne!(hash(&vector_1), hash(&vector_2)); } #[test] fn test_hash_pointer_kind_consistent() { let vector = vector!["a"]; let vector_sync = vector_sync!["a"]; assert_eq!(hash(&vector), hash(&vector_sync)); } #[test] fn test_clone() { let vector = vector!["hello", "there"]; let clone = vector.clone(); assert_eq!(clone.len(), vector.len()); assert!(clone.iter().eq(vector.iter())); } #[test] fn test_index_mut() { let v1 = vector![ String::from("This"), String::from("is"), String::from("where"), String::from("the"), String::from("fun"), String::from("begins!") ]; let mut v2 = v1.clone(); let expected1 = vector!["This", "is", "where", "the", "fun", "begins!"]; let expected2 = vector!["That", "is", "where", "the", "cloning", "BEGINS!"]; v2[0] = "That".into(); v2[4] = String::from("cloning"); v2[5].make_ascii_uppercase(); let len = v2.len(); assert_eq!(v2.get_mut(len), None); assert_eq!(v1, expected1); assert_eq!(v2, expected2); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let vector: Vector = vector![5, 6, 7, 8]; let encoded = serialize(&vector).unwrap(); let decoded: Vector = deserialize(&encoded).unwrap(); assert_eq!(vector, decoded); } rpds/src/vector/mod.rs0000644000175000017500000005563114661133735015741 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use alloc::borrow::Borrow; use alloc::fmt::Display; use alloc::vec::Vec; use archery::*; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; use core::ops::Index; use core::ops::IndexMut; // TODO Use impl trait instead of this when available. pub type Iter<'a, T, P> = core::iter::Map, fn(&SharedPointer) -> &T>; const DEFAULT_BITS: u8 = 5; /// Creates a [`Vector`](crate::Vector) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let v = Vector::new() /// .push_back(1) /// .push_back(2) /// .push_back(3); /// /// assert_eq!(vector![1, 2, 3], v); /// ``` #[macro_export] macro_rules! vector { ($($e:expr),*) => { { #[allow(unused_mut)] let mut v = $crate::Vector::new(); $( v.push_back_mut($e); )* v } }; } /// Creates a [`Vector`](crate::Vector) that implements `Sync`, containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let v = Vector::new_sync() /// .push_back(1) /// .push_back(2) /// .push_back(3); /// /// assert_eq!(vector_sync![1, 2, 3], v); /// ``` #[macro_export] macro_rules! vector_sync { ($($e:expr),*) => { { #[allow(unused_mut)] let mut v = $crate::Vector::new_sync(); $( v.push_back_mut($e); )* v } }; } /// A persistent vector with structural sharing. /// /// # Complexity /// /// Let *n* be the number of elements in the vector. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:-------------------------- | ---------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `set()` | Θ(log(n)) | Θ(log(n)) | /// | `push_back()` | Θ(log(n)) | Θ(log(n)) | /// | `drop_last()` | Θ(log(n)) | Θ(log(n)) | /// | `first()`/`last()`/`get()` | Θ(log(n)) | Θ(log(n)) | /// | `len()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(1) | Θ(1) | /// | iterator step | Θ(1) | Θ(log(n)) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This implementation uses a bitmapped vector trie as described in /// [Understanding Persistent Vector Part 1](http://hypirion.com/musings/understanding-persistent-vector-pt-1) /// and [Understanding Persistent Vector Part 2](http://hypirion.com/musings/understanding-persistent-vector-pt-2). #[derive(Debug)] pub struct Vector where P: SharedPointerKind, { root: SharedPointer, P>, bits: u8, length: usize, } pub type VectorSync = Vector; #[derive(Debug)] enum Node where P: SharedPointerKind, { Branch(Vec, P>>), Leaf(Vec>), } impl Node where P: SharedPointerKind, { fn new_empty_branch() -> Node { Node::Branch(Vec::new()) } fn new_empty_leaf() -> Node { Node::Leaf(Vec::new()) } fn get usize>(&self, index: usize, height: usize, bucket: F) -> &T { let b = bucket(index, height); match self { Node::Branch(a) => a[b].get(index, height - 1, bucket), Node::Leaf(a) => { debug_assert_eq!(height, 0); a[b].as_ref() } } } fn assoc usize>(&mut self, value: T, height: usize, bucket: F) { let b = bucket(height); match self { Node::Leaf(a) => { debug_assert_eq!(height, 0, "cannot have a leaf at this height"); if a.len() == b { a.push(SharedPointer::new(value)); } else { a[b] = SharedPointer::new(value); } } Node::Branch(a) => { debug_assert!(height > 0, "cannot have a branch at this height"); match a.get_mut(b) { Some(subtree) => { SharedPointer::make_mut(subtree).assoc(value, height - 1, bucket); } None => { let mut subtree = if height > 1 { Node::new_empty_branch() } else { Node::new_empty_leaf() }; subtree.assoc(value, height - 1, bucket); a.push(SharedPointer::new(subtree)); } } } } } #[inline] fn is_empty(&self) -> bool { self.used() == 0 } #[inline] fn is_singleton(&self) -> bool { self.used() == 1 } fn used(&self) -> usize { match self { Node::Leaf(a) => a.len(), Node::Branch(a) => a.len(), } } /// Drops the last element. /// /// This will return `true` if the subtree after drop becomes empty (or it already was empty). /// Note that this will prune irrelevant branches, i.e. there will be no branches without /// elements under it. fn drop_last(&mut self) -> bool { if self.is_empty() { return true; } match self { Node::Leaf(a) => { a.pop(); } Node::Branch(a) => { if SharedPointer::make_mut(a.last_mut().unwrap()).drop_last() { a.pop(); } } } self.is_empty() } } impl Node where P: SharedPointerKind, { fn get_mut usize>( &mut self, index: usize, height: usize, bucket: F, ) -> &mut T { let b = bucket(index, height); match *self { Node::Branch(ref mut a) => { SharedPointer::make_mut(&mut a[b]).get_mut(index, height - 1, bucket) } Node::Leaf(ref mut a) => { debug_assert_eq!(height, 0); SharedPointer::make_mut(&mut a[b]) } } } } impl Clone for Node where P: SharedPointerKind, { fn clone(&self) -> Node { match self { Node::Branch(a) => Node::Branch(Vec::clone(a)), Node::Leaf(a) => Node::Leaf(Vec::clone(a)), } } } mod vector_utils { #[inline] pub fn degree(bits: u8) -> usize { 1 << bits } #[inline] pub fn mask(bits: u8) -> usize { degree(bits) - 1 } #[inline] pub fn bucket(bits: u8, index: usize, height: usize) -> usize { (index >> (height * bits as usize)) & mask(bits) } } impl VectorSync { #[must_use] pub fn new_sync() -> VectorSync { Vector::new_with_ptr_kind() } } impl Vector { #[must_use] pub fn new() -> Vector { Vector::new_with_ptr_kind() } } impl Vector where P: SharedPointerKind, { #[must_use] pub fn new_with_ptr_kind() -> Vector { Vector::new_with_bits(DEFAULT_BITS) } #[must_use] pub fn new_with_bits(bits: u8) -> Vector { assert!(bits > 0, "number of bits for the vector must be positive"); Vector { root: SharedPointer::new(Node::new_empty_leaf()), bits, length: 0 } } #[must_use] #[inline] pub fn first(&self) -> Option<&T> { self.get(0) } #[must_use] pub fn last(&self) -> Option<&T> { match self.length { 0 => None, n => self.get(n - 1), } } #[inline] fn height(&self) -> usize { if self.length > 1 { let u: usize = self.length - 1; let c: usize = usize::BITS as usize - u.leading_zeros() as usize; let b: usize = self.bits as usize; c / b + usize::from(c % b > 0) - 1 } else { 0 } } #[must_use] pub fn get(&self, index: usize) -> Option<&T> { if index >= self.length { None } else { Some(self.root.get(index, self.height(), |index, height| { vector_utils::bucket(self.bits, index, height) })) } } #[must_use] pub fn set(&self, index: usize, v: T) -> Option> { let mut new_vector = self.clone(); if new_vector.set_mut(index, v) { Some(new_vector) } else { None } } /// Returns `true` if the operation was successful. pub fn set_mut(&mut self, index: usize, v: T) -> bool { if index >= self.length { false } else { self.assoc(index, v); true } } /// Sets the given index to v. /// /// # Panics /// /// This method will panic if the trie's root doesn't have capacity for the given index. fn assoc(&mut self, index: usize, v: T) { debug_assert!( index < self.root_max_capacity(), "This trie's root cannot support this index" ); let height = self.height(); let bits = self.bits; SharedPointer::make_mut(&mut self.root) .assoc(v, height, |height| vector_utils::bucket(bits, index, height)); let adds_item: bool = index >= self.length; if adds_item { self.length += 1; } } #[inline] fn root_max_capacity(&self) -> usize { /* A Trie's root max capacity is * * degree ** (height + 1) * = (2 ** bits) ** (height + 1) (by def. of degree) * = 2 ** (bits * (height + 1)) * = 1 << (bits * (height + 1)) */ 1 << (self.bits as usize * (self.height() + 1)) } #[inline] fn is_root_full(&self) -> bool { self.length == self.root_max_capacity() } #[must_use] pub fn push_back(&self, v: T) -> Vector { let mut new_vector = self.clone(); new_vector.push_back_mut(v); new_vector } pub fn push_back_mut(&mut self, v: T) { if self.is_root_full() { let mut new_root: Node = Node::new_empty_branch(); match new_root { Node::Branch(ref mut values) => values.push(SharedPointer::clone(&self.root)), Node::Leaf(_) => unreachable!("expected a branch"), } let length = self.length; self.root = SharedPointer::new(new_root); self.length += 1; self.assoc(length, v); } else { let length = self.length; self.assoc(length, v); } } /// Compresses a root. A root is compressed if, whenever there is a branch, it has more than /// one child. /// /// The trie must always have a compressed root. fn compress_root(root: &mut Node) -> Option, P>> { let singleton = root.is_singleton(); match root { Node::Leaf(_) => None, Node::Branch(a) if singleton => a.pop(), Node::Branch(_) => None, } } #[must_use] pub fn drop_last(&self) -> Option> { let mut new_vector = self.clone(); if new_vector.drop_last_mut() { Some(new_vector) } else { None } } pub fn drop_last_mut(&mut self) -> bool { if self.length > 0 { let new_root = { let root = SharedPointer::make_mut(&mut self.root); root.drop_last(); self.length -= 1; Vector::compress_root(root) }; if let Some(new_root) = new_root { self.root = new_root; } true } else { false } } #[must_use] #[inline] pub fn len(&self) -> usize { self.length } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn iter(&self) -> Iter<'_, T, P> { self.iter_ptr().map(|v| v.borrow()) } #[must_use] fn iter_ptr(&self) -> IterPtr<'_, T, P> { IterPtr::new(self) } } impl Vector where P: SharedPointerKind, { /// Gets a mutable reference to an element. If the element is shared, it will be cloned. /// Returns `None` if and only if the given `index` is out of range. #[must_use] pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { if index >= self.length { None } else { let height = self.height(); let bits = self.bits; Some( SharedPointer::make_mut(&mut self.root).get_mut(index, height, |index, height| { vector_utils::bucket(bits, index, height) }), ) } } } impl Index for Vector where P: SharedPointerKind, { type Output = T; fn index(&self, index: usize) -> &T { self.get(index).unwrap_or_else(|| panic!("index out of bounds {index}")) } } impl IndexMut for Vector where P: SharedPointerKind, { fn index_mut(&mut self, index: usize) -> &mut T { self.get_mut(index).unwrap_or_else(|| panic!("index out of bounds {index}")) } } impl Default for Vector where P: SharedPointerKind, { fn default() -> Vector { Vector::new_with_ptr_kind() } } impl, U, P, PO> PartialEq> for Vector where P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &Vector) -> bool { self.length == other.length && self.iter().eq(other.iter()) } } impl Eq for Vector where P: SharedPointerKind {} impl, U, P, PO> PartialOrd> for Vector where P: SharedPointerKind, PO: SharedPointerKind, { fn partial_cmp(&self, other: &Vector) -> Option { self.iter().partial_cmp(other.iter()) } } impl Ord for Vector where P: SharedPointerKind, { fn cmp(&self, other: &Vector) -> Ordering { self.iter().cmp(other.iter()) } } impl Hash for Vector where P: SharedPointerKind, { fn hash(&self, state: &mut H) { // Add the hash of length so that if two collections are added one after the other it doesn't // hash to the same thing as a single collection with the same elements in the same order. self.len().hash(state); for e in self { e.hash(state); } } } impl Clone for Vector where P: SharedPointerKind, { fn clone(&self) -> Vector { Vector { root: SharedPointer::clone(&self.root), bits: self.bits, length: self.length } } } impl Display for Vector where P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("[")?; for v in self { if !first { fmt.write_str(", ")?; } v.fmt(fmt)?; first = false; } fmt.write_str("]") } } impl<'a, T, P> IntoIterator for &'a Vector where P: SharedPointerKind, { type Item = &'a T; type IntoIter = Iter<'a, T, P>; fn into_iter(self) -> Iter<'a, T, P> { self.iter() } } impl FromIterator for Vector where P: SharedPointerKind, { fn from_iter>(into_iter: I) -> Vector { let mut vector = Vector::new_with_ptr_kind(); vector.extend(into_iter); vector } } impl Extend for Vector where P: SharedPointerKind, { fn extend>(&mut self, iter: I) { for elem in iter { self.push_back_mut(elem); } } } pub struct IterPtr<'a, T, P> where P: SharedPointerKind, { vector: &'a Vector, stack_forward: Option>>, stack_backward: Option>>, left_index: usize, // inclusive right_index: usize, // exclusive } struct IterStackElement<'a, T, P> where P: SharedPointerKind, { node: &'a Node, index: isize, } impl<'a, T, P> IterStackElement<'a, T, P> where P: SharedPointerKind, { fn new(node: &Node, backwards: bool) -> IterStackElement<'_, T, P> { #[allow(clippy::cast_possible_wrap)] IterStackElement { node, index: if backwards { node.used() as isize - 1 } else { 0 } } } #[inline] fn current_node(&self) -> &'a Node { #[allow(clippy::cast_sign_loss)] match self.node { Node::Branch(a) => a[self.index as usize].as_ref(), Node::Leaf(_) => panic!("called current node of a branch"), } } #[inline] fn current_elem(&self) -> &'a SharedPointer { #[allow(clippy::cast_sign_loss)] match self.node { Node::Leaf(a) => &a[self.index as usize], Node::Branch(_) => panic!("called current element of a branch"), } } /// Advance and returns `true` if finished. #[inline] fn advance(&mut self, backwards: bool) -> bool { #[allow(clippy::cast_sign_loss)] if backwards { self.index -= 1; self.index < 0 } else { self.index += 1; self.index as usize >= self.node.used() } } } impl<'a, T, P> IterPtr<'a, T, P> where P: SharedPointerKind, { fn new(vector: &Vector) -> IterPtr<'_, T, P> { IterPtr { vector, stack_forward: None, stack_backward: None, left_index: 0, right_index: vector.len(), } } fn dig(stack: &mut Vec>, backwards: bool) { let next_node: &Node = { let stack_top = stack.last().unwrap(); if let Node::Leaf(_) = *stack_top.node { return; } stack_top.current_node() }; stack.push(IterStackElement::new(next_node, backwards)); IterPtr::dig(stack, backwards); } fn init_if_needed(&mut self, backwards: bool) { let stack_field = if backwards { &mut self.stack_backward } else { &mut self.stack_forward }; if stack_field.is_none() { let mut stack: Vec> = Vec::with_capacity(self.vector.height() + 1); stack.push(IterStackElement::new(self.vector.root.borrow(), backwards)); IterPtr::dig(&mut stack, backwards); *stack_field = Some(stack); } } fn advance(stack: &mut Vec>, backwards: bool) { if let Some(mut stack_element) = stack.pop() { let finished = stack_element.advance(backwards); if finished { IterPtr::advance(stack, backwards); } else { stack.push(stack_element); IterPtr::dig(stack, backwards); } } } #[inline] fn current(stack: &[IterStackElement<'a, T, P>]) -> Option<&'a SharedPointer> { stack.last().map(IterStackElement::current_elem) } #[inline] fn non_empty(&self) -> bool { self.left_index < self.right_index } fn advance_forward(&mut self) { if self.non_empty() { IterPtr::advance(self.stack_forward.as_mut().unwrap(), false); self.left_index += 1; } } fn current_forward(&self) -> Option<&'a SharedPointer> { if self.non_empty() { IterPtr::current(self.stack_forward.as_ref().unwrap()) } else { None } } fn advance_backward(&mut self) { if self.non_empty() { IterPtr::advance(self.stack_backward.as_mut().unwrap(), true); self.right_index -= 1; } } fn current_backward(&self) -> Option<&'a SharedPointer> { if self.non_empty() { IterPtr::current(self.stack_backward.as_ref().unwrap()) } else { None } } } impl<'a, T, P> Iterator for IterPtr<'a, T, P> where P: SharedPointerKind, { type Item = &'a SharedPointer; fn next(&mut self) -> Option<&'a SharedPointer> { self.init_if_needed(false); let current = self.current_forward(); self.advance_forward(); current } fn size_hint(&self) -> (usize, Option) { let len = self.right_index - self.left_index; (len, Some(len)) } } impl<'a, T, P> DoubleEndedIterator for IterPtr<'a, T, P> where P: SharedPointerKind, { fn next_back(&mut self) -> Option<&'a SharedPointer> { self.init_if_needed(true); let current = self.current_backward(); self.advance_backward(); current } } impl<'a, T, P> ExactSizeIterator for IterPtr<'a, T, P> where P: SharedPointerKind {} #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; use ::serde::ser::{Serialize, Serializer}; use core::fmt; use core::marker::PhantomData; impl Serialize for Vector where T: Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { serializer.collect_seq(self) } } impl<'de, T, P> Deserialize<'de> for Vector where T: Deserialize<'de>, P: SharedPointerKind, { fn deserialize>(deserializer: D) -> Result, D::Error> { deserializer .deserialize_seq(VectorVisitor { _phantom_t: PhantomData, _phantom_p: PhantomData }) } } struct VectorVisitor { _phantom_t: PhantomData, _phantom_p: PhantomData

, } impl<'de, T, P> Visitor<'de> for VectorVisitor where T: Deserialize<'de>, P: SharedPointerKind, { type Value = Vector; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a sequence") } fn visit_seq(self, mut seq: A) -> Result, A::Error> where A: SeqAccess<'de>, { let mut vector = Vector::new_with_ptr_kind(); while let Some(value) = seq.next_element()? { vector.push_back_mut(value); } Ok(vector) } } } #[cfg(test)] mod test; rpds/src/list/0000775000175000017500000000000014661133735014255 5ustar jamespagejamespagerpds/src/list/test.rs0000644000175000017500000002401414661133735015601 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(ListSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_list_sync_is_send_and_sync() -> impl Send + Sync { list_sync!(0) } mod iter { use super::*; use pretty_assertions::assert_eq; #[test] fn test_iter() { let limit = 1024; let mut list = List::new(); let mut left = limit; for i in 0..limit { list.push_front_mut(i); } for v in list.iter() { left -= 1; assert_eq!(*v, left); } assert_eq!(left, 0); } #[test] fn test_iter_size_hint() { let list = list![0, 1, 2]; let mut iterator = list.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_into_iterator() { let list = list![0, 1, 2, 3]; let mut left = 4; for (expected, n) in list.into_iter().enumerate() { left -= 1; assert!(left >= 0); assert_eq!(*n, expected); } assert_eq!(left, 0); } } #[test] fn test_new() { let empty_list: List = List::new(); assert!(empty_list.head.is_none()); assert_eq!(empty_list.len(), 0); assert!(empty_list.is_empty()); } #[test] fn test_macro_list() { let mut list_1 = List::new(); list_1.push_front_mut(1); let mut list_1_2_3 = List::new(); list_1_2_3.push_front_mut(3); list_1_2_3.push_front_mut(2); list_1_2_3.push_front_mut(1); assert_eq!(List::::new(), list![]); assert_eq!(list_1, list![1]); assert_eq!(list_1_2_3, list![1, 2, 3]); } #[test] fn test_first() { let empty_list: List = List::new(); let singleton_list = list!["hello"]; let list = list![0, 1, 2, 3]; assert_eq!(empty_list.first(), None); assert_eq!(singleton_list.first(), Some(&"hello")); assert_eq!(list.first(), Some(&0)); } #[test] fn test_first_mut() { let a = list![0, 1, 2, 3]; let mut b = a.clone(); *b.first_mut().unwrap() = -1; assert_eq!(a.first(), Some(&0)); assert_eq!(b.first(), Some(&-1)); assert!(a.iter().eq([0, 1, 2, 3].iter())); assert!(b.iter().eq([-1, 1, 2, 3].iter())); } #[test] fn test_last() { let empty_list: List = List::new(); let mut singleton_list = list!["hello"]; let list = list![0, 1, 2, 3]; assert_eq!(empty_list.last(), None); assert_eq!(singleton_list.last(), Some(&"hello")); assert_eq!(list.last(), Some(&3)); singleton_list.drop_first_mut(); assert_eq!(singleton_list.last(), None); } #[test] fn test_drop_first() { let empty_list: List = List::new(); let singleton_list = List::new().push_front("hello"); let list = List::new().push_front(3).push_front(2).push_front(1).push_front(0); assert!(empty_list.is_empty()); assert_eq!(singleton_list.drop_first().unwrap().first(), None); assert_eq!(list.drop_first().unwrap().first(), Some(&1)); assert_eq!(list.len(), 4); assert_eq!(list.drop_first().unwrap().len(), 3); } #[test] fn test_drop_first_mut() { let mut empty_list: List = List::new(); let mut singleton_list = list!["hello"]; let mut list = list![0, 1, 2, 3]; empty_list.drop_first_mut(); assert!(empty_list.is_empty()); singleton_list.drop_first_mut(); assert_eq!(singleton_list.first(), None); list.drop_first_mut(); assert_eq!(list.first(), Some(&1)); assert_eq!(list.len(), 3); } #[test] fn test_reverse() { let empty_list: List = List::new(); let singleton_list = List::new().push_front("hello"); let list = List::new().push_front(3).push_front(2).push_front(1).push_front(0); let list_reversed = List::new().push_front(0).push_front(1).push_front(2).push_front(3); assert_eq!(empty_list.reverse(), empty_list); assert_eq!(empty_list.reverse().last(), None); assert_eq!(singleton_list.reverse(), singleton_list); assert_eq!(singleton_list.reverse().last(), Some(&"hello")); assert_eq!(list.reverse(), list_reversed); assert_eq!(list.reverse().last(), Some(&0)); } #[test] fn test_reverse_mut() { let mut empty_list: List = List::new(); let mut singleton_list = list!["hello"]; let mut list = list![0, 1, 2, 3]; list.reverse_mut(); singleton_list.reverse_mut(); empty_list.reverse_mut(); assert_eq!(empty_list, empty_list); assert_eq!(empty_list.last(), None); assert_eq!(singleton_list, singleton_list); assert_eq!(singleton_list.last(), Some(&"hello")); assert_eq!(list.last(), Some(&0)); } #[test] fn test_from_iterator() { let vec: Vec = vec![10, 11, 12, 13]; let list: List = vec.iter().copied().collect(); assert!(vec.iter().eq(list.iter())); } #[test] fn test_default() { let list: List = List::default(); assert_eq!(list.first(), None); assert_eq!(list.len(), 0); } #[test] fn test_display() { let empty_list: List = List::new(); let singleton_list = list!["hello"]; let list = list![0, 1, 2, 3]; assert_eq!(format!("{}", empty_list), "[]"); assert_eq!(format!("{}", singleton_list), "[hello]"); assert_eq!(format!("{}", list), "[0, 1, 2, 3]"); } #[test] fn test_eq() { let list_1 = list!["a", "a"]; let list_1_prime = list!["a", "a"]; let list_2 = list!["a", "b"]; assert_ne!(list_1, list_2); assert_eq!(list_1, list_1); assert_eq!(list_1, list_1_prime); assert_eq!(list_2, list_2); } #[test] fn test_eq_pointer_kind_consistent() { let list_a = list!["a"]; let list_a_sync = list_sync!["a"]; let list_b = list!["b"]; let list_b_sync = list_sync!["b"]; assert!(list_a == list_a_sync); assert!(list_a != list_b_sync); assert!(list_b == list_b_sync); } #[test] fn test_partial_ord() { let list_1 = list!["a"]; let list_1_prime = list!["a"]; let list_2 = list!["b"]; let list_3 = list![0.0]; let list_4 = list![core::f32::NAN]; assert_eq!(list_1.partial_cmp(&list_1_prime), Some(Ordering::Equal)); assert_eq!(list_1.partial_cmp(&list_2), Some(Ordering::Less)); assert_eq!(list_2.partial_cmp(&list_1), Some(Ordering::Greater)); assert_eq!(list_3.partial_cmp(&list_4), None); } #[test] fn test_ord() { let list_1 = list!["a"]; let list_1_prime = list!["a"]; let list_2 = list!["b"]; assert_eq!(list_1.cmp(&list_1_prime), Ordering::Equal); assert_eq!(list_1.cmp(&list_2), Ordering::Less); assert_eq!(list_2.cmp(&list_1), Ordering::Greater); } #[test] fn test_ord_pointer_kind_consistent() { let list_a = list!["a"]; let list_a_sync = list_sync!["a"]; let list_b = list!["b"]; let list_b_sync = list_sync!["b"]; assert!(list_a <= list_a_sync); assert!(list_a < list_b_sync); assert!(list_b >= list_b_sync); assert!(list_a_sync >= list_a); assert!(list_b_sync > list_a); assert!(list_b_sync <= list_b); } fn hash(list: &List) -> u64 { #[allow(deprecated)] let mut hasher = core::hash::SipHasher::new(); list.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let list_1 = list!["a"]; let list_1_prime = list!["a"]; let list_2 = list!["a", "b"]; assert_eq!(hash(&list_1), hash(&list_1)); assert_eq!(hash(&list_1), hash(&list_1_prime)); assert_ne!(hash(&list_1), hash(&list_2)); } #[test] fn test_hash_pointer_kind_consistent() { let list = list!["a"]; let list_sync = list_sync!["a"]; assert_eq!(hash(&list), hash(&list_sync)); } #[test] fn test_clone() { let list = list!["hello", "there"]; let clone = list.clone(); assert!(clone.iter().eq(list.iter())); assert_eq!(clone.len(), list.len()); assert_eq!(clone.last(), list.last()); } #[allow(clippy::many_single_char_names)] #[test] fn test_drop_list() { // When it is dropped, it will set the variable it owned to false. use core::cell::Cell; struct DropStruct<'a>(&'a Cell); impl<'a> Drop for DropStruct<'a> { fn drop(&mut self) { self.0.set(false); } } // test that we actually dropped the elements let (a, b, c, d, e) = (Cell::new(true), Cell::new(true), Cell::new(true), Cell::new(true), Cell::new(true)); let mut x = List::new(); x.push_front_mut(DropStruct(&a)); x.push_front_mut(DropStruct(&b)); x.push_front_mut(DropStruct(&c)); assert_eq!( vec![a.get(), b.get(), c.get(), d.get(), e.get()], vec![true, true, true, true, true] ); let x2 = x.drop_first().unwrap().drop_first().unwrap(); drop(x); assert_eq!( vec![a.get(), b.get(), c.get(), d.get(), e.get()], vec![true, false, false, true, true] ); let y = x2.push_front(DropStruct(&d)); drop(x2); assert_eq!( vec![a.get(), b.get(), c.get(), d.get(), e.get()], vec![true, false, false, true, true] ); let z = y.push_front(DropStruct(&e)); drop(y); assert_eq!( vec![a.get(), b.get(), c.get(), d.get(), e.get()], vec![true, false, false, true, true] ); drop(z); assert_eq!( vec![a.get(), b.get(), c.get(), d.get(), e.get()], vec![false, false, false, false, false] ); } #[test] fn test_drop_large() { let limit = 1024 * 1024; let mut list = List::new(); for i in 0..limit { list.push_front_mut(i); } } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let list: List = list![5, 6, 7, 8]; let encoded = serialize(&list).unwrap(); let decoded: List = deserialize(&encoded).unwrap(); assert_eq!(list, decoded); } rpds/src/list/mod.rs0000644000175000017500000003214314661133735015403 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use alloc::vec::Vec; use archery::*; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::Display; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; // TODO Use impl trait instead of this when available. pub type Iter<'a, T, P> = core::iter::Map, fn(&SharedPointer) -> &T>; #[doc(hidden)] #[macro_export] macro_rules! list_reverse { ($ptr_kind:ty ; ; $($reversed:expr),*) => { { #[allow(unused_mut)] let mut l: List<_, $ptr_kind> = $crate::List::new_with_ptr_kind(); $( l.push_front_mut($reversed); )* l } }; ($ptr_kind:ty ; $h:expr ; $($reversed:expr),*) => { $crate::list_reverse!($ptr_kind ; ; $h, $($reversed),*) }; ($ptr_kind:ty ; $h:expr, $($t:expr),+ ; $($reversed:expr),*) => { $crate::list_reverse!($ptr_kind ; $($t),* ; $h, $($reversed),*) }; // This is just to handle the cases where this macro is called with an extra comma in the // reserve list, which can happen in a recursive call. ($ptr_kind:ty ; $($t:expr),* ; $($reversed:expr),*,) => { $crate::list_reverse!($ptr_kind ; $($t),* ; $($reversed),*) }; } /// Creates a [`List`](crate::List) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let l = List::new() /// .push_front(3) /// .push_front(2) /// .push_front(1); /// /// assert_eq!(list![1, 2, 3], l); /// ``` #[macro_export] macro_rules! list { ($($e:expr),*) => { $crate::list_reverse!(::archery::RcK ; $($e),* ; ) }; } /// Creates a [`List`](crate::List) that implements `Sync`, containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let l = List::new_sync() /// .push_front(3) /// .push_front(2) /// .push_front(1); /// /// assert_eq!(list_sync![1, 2, 3], l); /// /// fn is_sync() -> impl Sync { /// list_sync![0, 1, 1, 2, 3, 5, 8] /// } /// ``` #[macro_export] macro_rules! list_sync { ($($e:expr),*) => { $crate::list_reverse!(::archery::ArcTK ; $($e),* ; ) }; } /// A persistent list with structural sharing. /// /// # Complexity /// /// Let *n* be the number of elements in the list. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:----------------- | -------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `push_front()` | Θ(1) | Θ(1) | /// | `drop_first()` | Θ(1) | Θ(1) | /// | `reverse()` | Θ(n) | Θ(n) | /// | `first()` | Θ(1) | Θ(1) | /// | `last()` | Θ(1) | Θ(1) | /// | `len()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(1) | Θ(1) | /// | iterator step | Θ(1) | Θ(1) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This is your classic functional list with "cons" and "nil" nodes, with a little extra sauce to /// make some operations more efficient. #[derive(Debug)] pub struct List where P: SharedPointerKind, { head: Option, P>>, last: Option>, length: usize, } #[derive(Debug)] struct Node where P: SharedPointerKind, { value: SharedPointer, next: Option, P>>, } impl Clone for Node where P: SharedPointerKind, { fn clone(&self) -> Node { Node { value: SharedPointer::clone(&self.value), next: self.next.clone() } } } pub type ListSync = List; impl ListSync { #[must_use] pub fn new_sync() -> ListSync { List::new_with_ptr_kind() } } impl List { #[must_use] pub fn new() -> List { List::new_with_ptr_kind() } } impl List where P: SharedPointerKind, { #[must_use] pub fn new_with_ptr_kind() -> List { List { head: None, last: None, length: 0 } } #[must_use] pub fn first(&self) -> Option<&T> { self.head.as_ref().map(|node| node.value.borrow()) } #[must_use] pub fn last(&self) -> Option<&T> { self.last.as_ref().map(Borrow::borrow) } #[must_use] pub fn drop_first(&self) -> Option> { let mut new_list = self.clone(); if new_list.drop_first_mut() { Some(new_list) } else { None } } pub fn drop_first_mut(&mut self) -> bool { self.head.take().map_or(false, |h| { self.head = h.next.clone(); self.length -= 1; if self.length == 0 { self.last = None; } true }) } fn push_front_ptr_mut(&mut self, v: SharedPointer) { if self.length == 0 { self.last = Some(SharedPointer::clone(&v)); } let new_head = Node { value: v, next: self.head.take() }; self.head = Some(SharedPointer::new(new_head)); self.length += 1; } #[must_use] pub fn push_front(&self, v: T) -> List { let mut new_list = self.clone(); new_list.push_front_mut(v); new_list } pub fn push_front_mut(&mut self, v: T) { self.push_front_ptr_mut(SharedPointer::new(v)); } #[must_use] pub fn reverse(&self) -> List { let mut new_list = List::new_with_ptr_kind(); // It is significantly faster to re-implement this here than to clone and call // `reverse_mut()`. The reason is that since this is a linear data structure all nodes will // need to be cloned given that the ref count would be greater than one. for v in self.iter_ptr() { new_list.push_front_ptr_mut(SharedPointer::clone(v)); } new_list } pub fn reverse_mut(&mut self) { self.last = self.head.as_ref().map(|next| SharedPointer::clone(&next.value)); let mut prev: Option, P>> = None; let mut current: Option, P>> = self.head.take(); while let Some(mut curr_ptr) = current { let curr = SharedPointer::make_mut(&mut curr_ptr); let curr_next = curr.next.take(); curr.next = prev.take(); current = curr_next; prev = Some(curr_ptr); } self.head = prev; } #[must_use] #[inline] pub fn len(&self) -> usize { self.length } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn iter(&self) -> Iter<'_, T, P> { self.iter_ptr().map(|v| v.borrow()) } #[must_use] pub(crate) fn iter_ptr(&self) -> IterPtr<'_, T, P> { IterPtr::new(self) } } impl List where T: Clone, P: SharedPointerKind, { #[must_use] pub(crate) fn first_mut(&mut self) -> Option<&mut T> { self.head .as_mut() .map(|node| SharedPointer::make_mut(&mut SharedPointer::make_mut(node).value)) } } impl Default for List where P: SharedPointerKind, { fn default() -> List { List::new_with_ptr_kind() } } impl PartialEq> for List where P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &List) -> bool { self.length == other.length && self.iter().eq(other.iter()) } } impl Eq for List where P: SharedPointerKind {} impl, P, PO> PartialOrd> for List where P: SharedPointerKind, PO: SharedPointerKind, { fn partial_cmp(&self, other: &List) -> Option { self.iter().partial_cmp(other.iter()) } } impl Ord for List where P: SharedPointerKind, { fn cmp(&self, other: &List) -> Ordering { self.iter().cmp(other.iter()) } } impl Hash for List where P: SharedPointerKind, { fn hash(&self, state: &mut H) { // Add the hash of length so that if two collections are added one after the other it doesn't // hash to the same thing as a single collection with the same elements in the same order. self.len().hash(state); for e in self { e.hash(state); } } } impl Clone for List where P: SharedPointerKind, { fn clone(&self) -> List { List { head: self.head.clone(), last: self.last.clone(), length: self.length } } } impl Display for List where P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("[")?; for v in self { if !first { fmt.write_str(", ")?; } v.fmt(fmt)?; first = false; } fmt.write_str("]") } } impl<'a, T, P> IntoIterator for &'a List where P: SharedPointerKind, { type Item = &'a T; type IntoIter = Iter<'a, T, P>; fn into_iter(self) -> Iter<'a, T, P> { self.iter() } } impl FromIterator for List where P: SharedPointerKind, { fn from_iter>(into_iter: I) -> List { let iter = into_iter.into_iter(); let (min_size, max_size_hint) = iter.size_hint(); let mut vec: Vec = Vec::with_capacity(max_size_hint.unwrap_or(min_size)); for e in iter { vec.push(e); } let mut list: List = List::new_with_ptr_kind(); for e in vec.into_iter().rev() { list.push_front_mut(e); } list } } // Drop the list iteratively to prevent stack overflow. impl Drop for List where P: SharedPointerKind, { fn drop(&mut self) { let mut head = self.head.take(); while let Some(node) = head { if let Ok(mut node) = SharedPointer::try_unwrap(node) { head = node.next.take(); } else { break; } } } } #[derive(Debug)] pub struct IterPtr<'a, T, P> where P: SharedPointerKind, { next: Option<&'a Node>, length: usize, } impl<'a, T, P> IterPtr<'a, T, P> where P: SharedPointerKind, { fn new(list: &List) -> IterPtr<'_, T, P> { IterPtr { next: list.head.as_ref().map(AsRef::as_ref), length: list.len() } } } impl<'a, T, P> Iterator for IterPtr<'a, T, P> where P: SharedPointerKind, { type Item = &'a SharedPointer; fn next(&mut self) -> Option<&'a SharedPointer> { match self.next { Some(Node { value: ref v, next: ref t }) => { self.next = t.as_ref().map(AsRef::as_ref); self.length -= 1; Some(v) } None => None, } } fn size_hint(&self) -> (usize, Option) { (self.length, Some(self.length)) } } impl<'a, T, P> ExactSizeIterator for IterPtr<'a, T, P> where P: SharedPointerKind {} #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer, SeqAccess, Visitor}; use ::serde::ser::{Serialize, Serializer}; use core::fmt; use core::marker::PhantomData; impl Serialize for List where T: Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { serializer.collect_seq(self) } } impl<'de, T, P> Deserialize<'de> for List where T: Deserialize<'de>, P: SharedPointerKind, { fn deserialize>(deserializer: D) -> Result, D::Error> { deserializer .deserialize_seq(ListVisitor { _phantom_t: PhantomData, _phantom_p: PhantomData }) } } struct ListVisitor { _phantom_t: PhantomData, _phantom_p: PhantomData

, } impl<'de, T, P> Visitor<'de> for ListVisitor where T: Deserialize<'de>, P: SharedPointerKind, { type Value = List; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("a sequence") } fn visit_seq(self, mut seq: A) -> Result, A::Error> where A: SeqAccess<'de>, { let mut vec: Vec = if let Some(capacity) = seq.size_hint() { Vec::with_capacity(capacity) } else { Vec::new() }; while let Some(value) = seq.next_element()? { vec.push(value); } let mut list: List = List::new_with_ptr_kind(); for value in vec.into_iter().rev() { list.push_front_mut(value); } Ok(list) } } } #[cfg(test)] mod test; rpds/src/utils/0000775000175000017500000000000014661133735014442 5ustar jamespagejamespagerpds/src/utils/test.rs0000644000175000017500000000067214661133735015772 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use archery::RcK; use pretty_assertions::assert_eq; #[test] fn test_replace() { let src: SharedPointer<_, RcK> = SharedPointer::new(3); let mut dest = 0; replace(&mut dest, src); assert_eq!(dest, 3); } rpds/src/utils/mod.rs0000644000175000017500000000155214661133735015570 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use archery::{SharedPointer, SharedPointerKind}; #[cfg(feature = "std")] pub type DefaultBuildHasher = std::collections::hash_map::RandomState; #[cfg(not(feature = "std"))] #[allow(deprecated)] pub type DefaultBuildHasher = core::hash::BuildHasherDefault; /// Assigns the content of `src` to `dest`. pub fn replace(dest: &mut T, mut src: SharedPointer) where P: SharedPointerKind, { // To avoid unnecessary cloning we do this trick. If we have exclusive ownership of the // data pointed to by `src` then no clone is done. core::mem::swap(dest, SharedPointer::make_mut(&mut src)); } #[cfg(test)] mod test; rpds/src/stack/0000775000175000017500000000000014661133735014407 5ustar jamespagejamespagerpds/src/stack/test.rs0000644000175000017500000001524014661133735015734 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use super::*; use alloc::vec::Vec; use pretty_assertions::assert_eq; use static_assertions::assert_impl_all; assert_impl_all!(StackSync: Send, Sync); #[allow(dead_code)] fn compile_time_macro_stack_sync_is_send_and_sync() -> impl Send + Sync { stack_sync!(0) } mod iter { #[test] fn test_iter() { let stack = stack![2, 1, 0]; let mut iterator = stack.iter(); assert_eq!(iterator.next(), Some(&0)); assert_eq!(iterator.next(), Some(&1)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next(), None); } #[test] fn test_iter_size_hint() { let stack = stack![2, 1, 0]; let mut iterator = stack.iter(); assert_eq!(iterator.size_hint(), (3, Some(3))); iterator.next(); assert_eq!(iterator.size_hint(), (2, Some(2))); iterator.next(); assert_eq!(iterator.size_hint(), (1, Some(1))); iterator.next(); assert_eq!(iterator.size_hint(), (0, Some(0))); } #[test] fn test_into_iterator() { let stack = stack![3, 2, 1, 0]; let mut left = 4; for (expected, n) in stack.into_iter().enumerate() { left -= 1; assert!(left >= 0); assert_eq!(*n, expected); } assert_eq!(left, 0); } } #[test] fn test_new() { let empty_stack: Stack = Stack::new(); assert!(empty_stack.list.is_empty()); assert_eq!(empty_stack.size(), 0); assert!(empty_stack.is_empty()); } #[test] fn test_macro_stack() { let mut stack_1 = Stack::new(); stack_1.push_mut(1); let mut stack_1_2_3 = Stack::new(); stack_1_2_3.push_mut(1); stack_1_2_3.push_mut(2); stack_1_2_3.push_mut(3); assert_eq!(Stack::::new(), stack![]); assert_eq!(stack_1, stack![1]); assert_eq!(stack_1_2_3, stack![1, 2, 3]); } #[test] fn test_peek() { let empty_stack: Stack = Stack::new(); let singleton_stack = stack!["hello"]; let stack = stack![3, 2, 1, 0]; assert_eq!(empty_stack.peek(), None); assert_eq!(singleton_stack.peek(), Some(&"hello")); assert_eq!(stack.peek(), Some(&0)); } #[test] fn test_pop_mut() { let mut empty_stack: Stack = Stack::new(); let mut singleton_stack = stack!["hello"]; let mut stack = stack![3, 2, 1, 0]; empty_stack.pop_mut(); assert!(empty_stack.is_empty()); singleton_stack.pop_mut(); assert_eq!(singleton_stack.peek(), None); stack.pop_mut(); assert_eq!(stack.peek(), Some(&1)); assert_eq!(stack.size(), 3); } #[test] fn test_pop() { let empty_stack: Stack = Stack::new(); let singleton_stack = Stack::new().push("hello"); let stack = Stack::new().push(3).push(2).push(1).push(0); assert!(empty_stack.pop().is_none()); assert_eq!(singleton_stack.pop().unwrap().peek(), None); assert_eq!(stack.pop().unwrap().peek(), Some(&1)); assert_eq!(stack.size(), 4); assert_eq!(stack.pop().unwrap().size(), 3); } #[test] fn test_from_iterator() { let vec: Vec = vec![10, 11, 12, 13]; let stack: Stack = vec.iter().copied().collect(); assert!(vec.iter().eq(stack.iter())); } #[test] fn test_default() { let stack: Stack = Stack::default(); assert_eq!(stack.peek(), None); assert!(stack.is_empty()); } #[test] fn test_display() { let empty_stack: Stack = Stack::new(); let singleton_stack = stack!["hello"]; let stack = stack![3, 2, 1, 0]; assert_eq!(format!("{}", empty_stack), "Stack()"); assert_eq!(format!("{}", singleton_stack), "Stack(hello)"); assert_eq!(format!("{}", stack), "Stack(0, 1, 2, 3)"); } #[test] fn test_eq() { let stack_1 = stack!["a", "a"]; let stack_1_prime = stack!["a", "a"]; let stack_2 = stack!["b", "a"]; assert_ne!(stack_1, stack_2); assert_eq!(stack_1, stack_1); assert_eq!(stack_1, stack_1_prime); assert_eq!(stack_2, stack_2); } #[test] fn test_eq_pointer_kind_consistent() { let stack_a = stack!["a"]; let stack_a_sync = stack_sync!["a"]; let stack_b = stack!["b"]; let stack_b_sync = stack_sync!["b"]; assert!(stack_a == stack_a_sync); assert!(stack_a != stack_b_sync); assert!(stack_b == stack_b_sync); } #[test] fn test_partial_ord() { let stack_1 = stack!["a"]; let stack_1_prime = stack!["a"]; let stack_2 = stack!["b"]; let stack_3 = stack![0.0]; let stack_4 = stack![core::f32::NAN]; assert_eq!(stack_1.partial_cmp(&stack_1_prime), Some(Ordering::Equal)); assert_eq!(stack_1.partial_cmp(&stack_2), Some(Ordering::Less)); assert_eq!(stack_2.partial_cmp(&stack_1), Some(Ordering::Greater)); assert_eq!(stack_3.partial_cmp(&stack_4), None); } #[test] fn test_ord() { let stack_1 = stack!["a"]; let stack_1_prime = stack!["a"]; let stack_2 = stack!["b"]; assert_eq!(stack_1.cmp(&stack_1_prime), Ordering::Equal); assert_eq!(stack_1.cmp(&stack_2), Ordering::Less); assert_eq!(stack_2.cmp(&stack_1), Ordering::Greater); } #[test] fn test_ord_pointer_kind_consistent() { let stack_a = stack!["a"]; let stack_a_sync = stack_sync!["a"]; let stack_b = stack!["b"]; let stack_b_sync = stack_sync!["b"]; assert!(stack_a <= stack_a_sync); assert!(stack_a < stack_b_sync); assert!(stack_b >= stack_b_sync); assert!(stack_a_sync >= stack_a); assert!(stack_b_sync > stack_a); assert!(stack_b_sync <= stack_b); } fn hash(stack: &Stack) -> u64 { #[allow(deprecated)] let mut hasher = core::hash::SipHasher::new(); stack.hash(&mut hasher); hasher.finish() } #[test] fn test_hash() { let stack_1 = stack!["a"]; let stack_1_prime = stack!["a"]; let stack_2 = stack!["b", "a"]; assert_eq!(hash(&stack_1), hash(&stack_1)); assert_eq!(hash(&stack_1), hash(&stack_1_prime)); assert_ne!(hash(&stack_1), hash(&stack_2)); } #[test] fn test_hash_pointer_kind_consistent() { let stack = stack!["a"]; let stack_sync = stack_sync!["a"]; assert_eq!(hash(&stack), hash(&stack_sync)); } #[test] fn test_clone() { let stack = stack!["there", "hello"]; let clone = stack.clone(); assert!(clone.iter().eq(stack.iter())); assert_eq!(clone.size(), stack.size()); } #[cfg(feature = "serde")] #[test] fn test_serde() { use bincode::{deserialize, serialize}; let stack: Stack = stack![5, 6, 7, 8]; let encoded = serialize(&stack).unwrap(); let decoded: Stack = deserialize(&encoded).unwrap(); assert_eq!(stack, decoded); } rpds/src/stack/mod.rs0000644000175000017500000001474314661133735015543 0ustar jamespagejamespage/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::List; use archery::*; use core::cmp::Ordering; use core::fmt::Display; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; // TODO Use impl trait for return value when available pub type Iter<'a, T, P> = crate::list::Iter<'a, T, P>; /// Creates a [`Stack`](crate::Stack) containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let mut s = Stack::new() /// .push(1) /// .push(2) /// .push(3); /// /// assert_eq!(stack![1, 2, 3], s); /// ``` #[macro_export] macro_rules! stack { ($($e:expr),*) => { { #[allow(unused_mut)] let mut s = $crate::Stack::new(); $( s.push_mut($e); )* s } }; } /// Creates a [`Stack`](crate::Stack) that implements `Sync`, containing the given arguments: /// /// ``` /// # use rpds::*; /// # /// let mut s = Stack::new_sync() /// .push(1) /// .push(2) /// .push(3); /// /// assert_eq!(stack_sync![1, 2, 3], s); /// /// fn is_sync() -> impl Sync { /// stack_sync![0, 1, 1, 2, 3, 5, 8] /// } /// ``` #[macro_export] macro_rules! stack_sync { ($($e:expr),*) => { { #[allow(unused_mut)] let mut s = $crate::Stack::new_sync(); $( s.push_mut($e); )* s } }; } /// A persistent stack with structural sharing. /// /// # Complexity /// /// Let *n* be the number of elements in the stack. /// /// ## Temporal complexity /// /// | Operation | Average | Worst case | /// |:----------------- | -------:| -----------:| /// | `new()` | Θ(1) | Θ(1) | /// | `push()` | Θ(1) | Θ(1) | /// | `pop()` | Θ(1) | Θ(1) | /// | `peek()` | Θ(1) | Θ(1) | /// | `size()` | Θ(1) | Θ(1) | /// | `clone()` | Θ(1) | Θ(1) | /// | iterator creation | Θ(1) | Θ(1) | /// | iterator step | Θ(1) | Θ(1) | /// | iterator full | Θ(n) | Θ(n) | /// /// # Implementation details /// /// This is a thin wrapper around a [`List`](crate::List). #[derive(Debug)] pub struct Stack where P: SharedPointerKind, { list: List, } pub type StackSync = Stack; impl StackSync { #[must_use] pub fn new_sync() -> StackSync { Stack::new_with_ptr_kind() } } impl Stack { #[must_use] pub fn new() -> Stack { Stack::new_with_ptr_kind() } } impl Stack where P: SharedPointerKind, { #[must_use] pub fn new_with_ptr_kind() -> Stack { Stack { list: List::new_with_ptr_kind() } } #[must_use] pub fn peek(&self) -> Option<&T> { self.list.first() } #[must_use] pub fn pop(&self) -> Option> { let mut new_stack = self.clone(); if new_stack.pop_mut() { Some(new_stack) } else { None } } pub fn pop_mut(&mut self) -> bool { self.list.drop_first_mut() } #[must_use] pub fn push(&self, v: T) -> Stack { let mut new_stack = self.clone(); new_stack.push_mut(v); new_stack } pub fn push_mut(&mut self, v: T) { self.list.push_front_mut(v); } #[must_use] #[inline] pub fn size(&self) -> usize { self.list.len() } #[must_use] #[inline] pub fn is_empty(&self) -> bool { self.list.is_empty() } pub fn iter(&self) -> Iter<'_, T, P> { self.list.iter() } } impl Default for Stack where P: SharedPointerKind, { fn default() -> Stack { Stack::new_with_ptr_kind() } } impl PartialEq> for Stack where P: SharedPointerKind, PO: SharedPointerKind, { fn eq(&self, other: &Stack) -> bool { self.list.eq(&other.list) } } impl Eq for Stack where P: SharedPointerKind {} impl, P, PO> PartialOrd> for Stack where P: SharedPointerKind, PO: SharedPointerKind, { fn partial_cmp(&self, other: &Stack) -> Option { self.list.partial_cmp(&other.list) } } impl Ord for Stack where P: SharedPointerKind, { fn cmp(&self, other: &Stack) -> Ordering { self.list.cmp(&other.list) } } impl Hash for Stack where P: SharedPointerKind, { fn hash(&self, state: &mut H) { self.list.hash(state); } } impl Clone for Stack where P: SharedPointerKind, { fn clone(&self) -> Stack { Stack { list: List::clone(&self.list) } } } impl Display for Stack where P: SharedPointerKind, { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { let mut first = true; fmt.write_str("Stack(")?; for v in self { if !first { fmt.write_str(", ")?; } v.fmt(fmt)?; first = false; } fmt.write_str(")") } } impl<'a, T, P> IntoIterator for &'a Stack where P: SharedPointerKind, { type Item = &'a T; type IntoIter = Iter<'a, T, P>; fn into_iter(self) -> Iter<'a, T, P> { self.list.iter() } } impl FromIterator for Stack where P: SharedPointerKind, { fn from_iter>(into_iter: I) -> Stack { Stack { list: List::from_iter(into_iter) } } } #[cfg(feature = "serde")] pub mod serde { use super::*; use ::serde::de::{Deserialize, Deserializer}; use ::serde::ser::{Serialize, Serializer}; impl Serialize for Stack where T: Serialize, P: SharedPointerKind, { fn serialize(&self, serializer: S) -> Result { self.list.serialize(serializer) } } impl<'de, T, P> Deserialize<'de> for Stack where T: Deserialize<'de>, P: SharedPointerKind, { fn deserialize>(deserializer: D) -> Result, D::Error> { Deserialize::deserialize(deserializer).map(|list| Stack { list }) } } } #[cfg(test)] mod test; rpds/LICENSE.md0000644000175000017500000003627614661133735014133 0ustar jamespagejamespageMozilla Public License Version 2.0 ================================== ### 1. Definitions **1.1. “Contributor”** means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. **1.2. “Contributor Version”** means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. **1.3. “Contribution”** means Covered Software of a particular Contributor. **1.4. “Covered Software”** means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. **1.5. “Incompatible With Secondary Licenses”** means * **(a)** that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or * **(b)** that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. **1.6. “Executable Form”** means any form of the work other than Source Code Form. **1.7. “Larger Work”** means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. **1.8. “License”** means this document. **1.9. “Licensable”** means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. **1.10. “Modifications”** means any of the following: * **(a)** any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or * **(b)** any new file in Source Code Form that contains any Covered Software. **1.11. “Patent Claims” of a Contributor** means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. **1.12. “Secondary License”** means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. **1.13. “Source Code Form”** means the form of the work preferred for making modifications. **1.14. “You” (or “Your”)** means an individual or a legal entity exercising rights under this License. For legal entities, “You” includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, “control” means **(a)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(b)** ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. ### 2. License Grants and Conditions #### 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: * **(a)** under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and * **(b)** under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. #### 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. #### 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: * **(a)** for any code that a Contributor has removed from Covered Software; or * **(b)** for infringements caused by: **(i)** Your and any other third party's modifications of Covered Software, or **(ii)** the combination of its Contributions with other software (except as part of its Contributor Version); or * **(c)** under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). #### 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). #### 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. #### 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. #### 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. ### 3. Responsibilities #### 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. #### 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: * **(a)** such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and * **(b)** You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. #### 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). #### 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. #### 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. ### 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: **(a)** comply with the terms of this License to the maximum extent possible; and **(b)** describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. ### 5. Termination **5.1.** The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated **(a)** provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and **(b)** on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. **5.2.** If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. **5.3.** In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ### 6. Disclaimer of Warranty > Covered Software is provided under this License on an “as is” > basis, without warranty of any kind, either expressed, implied, or > statutory, including, without limitation, warranties that the > Covered Software is free of defects, merchantable, fit for a > particular purpose or non-infringing. The entire risk as to the > quality and performance of the Covered Software is with You. > Should any Covered Software prove defective in any respect, You > (not any Contributor) assume the cost of any necessary servicing, > repair, or correction. This disclaimer of warranty constitutes an > essential part of this License. No use of any Covered Software is > authorized under this License except under this disclaimer. ### 7. Limitation of Liability > Under no circumstances and under no legal theory, whether tort > (including negligence), contract, or otherwise, shall any > Contributor, or anyone who distributes Covered Software as > permitted above, be liable to You for any direct, indirect, > special, incidental, or consequential damages of any character > including, without limitation, damages for lost profits, loss of > goodwill, work stoppage, computer failure or malfunction, or any > and all other commercial damages or losses, even if such party > shall have been informed of the possibility of such damages. This > limitation of liability shall not apply to liability for death or > personal injury resulting from such party's negligence to the > extent applicable law prohibits such limitation. Some > jurisdictions do not allow the exclusion or limitation of > incidental or consequential damages, so this exclusion and > limitation may not apply to You. ### 8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. ### 9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. ### 10. Versions of the License #### 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. #### 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. #### 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). #### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. ## Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. ## Exhibit B - “Incompatible With Secondary Licenses” Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. rpds/.cargo-checksum.json0000664000175000017500000001000114661133735016347 0ustar jamespagejamespage{"files":{"Cargo.toml":"ffea7a0bc3944b0a70195789457f8863e90ac1f634ad190f68864919dd5b73bf","LICENSE.md":"e6b6566f085df5746515c6d7e2edcaec0d2b77d527ac40d91409d783fb6c8508","README.md":"136bb5110d924cd5f93d364d95cbef57ba381b7c2ee782e013d8b42a1ea258aa","benches/rpds_hash_trie_map.rs":"f20835dd57f5eb30a2ed78b3dfac488cd4e186eff0f11b3ac0f5b47e9071e4f9","benches/rpds_hash_trie_map_sync.rs":"550d2b5ab8ee108121140e1c8d42c8939b855597c348abd628a880c058e8cd12","benches/rpds_list.rs":"813310d421bf67b08a1d1eb2c3d4f96c7d4d27d8981f40672ca1d5f668076c53","benches/rpds_list_sync.rs":"ab7e5c618e43449608843bdc5911927ecad3b4f6917606e9309c82bc1fefa645","benches/rpds_queue.rs":"dca51fb3a4bd162f9913a81aad917c020427e8f4568cb5644ade882f679c70fa","benches/rpds_queue_sync.rs":"acb872d1aa76aae91ed863be84948146a98000d5aa7f50544254c3dd333426d2","benches/rpds_red_black_tree_map.rs":"dbf97d9d5d0577cc6bd9253f8bffff6554af6c223a73671ee7948c8a617da139","benches/rpds_red_black_tree_map_sync.rs":"5cf3f5e06c1496f11e234eff18cf07e377a352fd85354b8b976617c08ea8aa35","benches/rpds_vector.rs":"a1f3ee4c6643dc166d6a7b9e6b3ef9b9444a70b9d48a33755a6b352fd1413309","benches/rpds_vector_sync.rs":"3884aedfc2b96b23acea00ae41f7421266efb556c00f82908066693e29b4880c","benches/std_btree_map.rs":"ef52039ba24e3169a46398e03761ca2df70df3854efa92a99b86b3a3ef966fb7","benches/std_hash_map.rs":"21858c193d6e5bf0fea1acbf952bf8b13766044d3f94db3e2ac57aa0d1d10dee","benches/std_linked_list.rs":"c4112927940553305e022a226985a998630c372426ac48316edde4c4587543d3","benches/std_vec.rs":"344a56d1b13924256d161b5657e066985de8b6390db35feb58a252f554ef47d7","benches/std_vec_deque.rs":"8bdaf3b0b3e06191362e7bd1a0a570317a86c4a51fdf15bfbc38455b0de98eac","release-notes.md":"849905e78619975b2d046fb87e341373137e5ec5d807799bcb60bfe5909498ca","src/lib.rs":"d4305016e554150656b38ae22c93b18fbedff834afaf2e3afadf2317316c21e6","src/list/mod.rs":"4735bf3d6364373537a5333ccd8325faecb7e38b78aca8307ee0aa529fdc0145","src/list/test.rs":"d128ed0813aae380781d60619bc100dac86e9a6245e8b0f080eaf8525e9cb7bc","src/map/entry.rs":"9fe13b506476f98bda5209f3398742f2744d00051796e7db2af8707152de33d7","src/map/hash_trie_map/mod.rs":"9103ffb0381c8d751cf414b97772a8442c84f1c9f5d042a0a98629fe7e2027d3","src/map/hash_trie_map/sparse_array_usize/mod.rs":"931c3233bee2ca13510288b7776f32e833abdeeab1cf422067fa6c2e03bb6337","src/map/hash_trie_map/sparse_array_usize/test.rs":"e7626783b66e41d7185dda9beae7b81c4fc9ec52befc9d12f18c90163ce247ce","src/map/hash_trie_map/test.rs":"b4213e5a3da058d0d1249899666f34a945f58a22ba56d3fb688f3bdac76f9dcc","src/map/mod.rs":"845894b4f1959239cb5f8673b3374cb363fd470fccda42ff56a637b9a99f984e","src/map/red_black_tree_map/mod.rs":"96cd3392b40b58f7cec4e53e5aca9e72057ad08629a62346f41456da76c9d41b","src/map/red_black_tree_map/test.rs":"dcc1c852fa6f4df6a9937076e67cd52db4f06297fb723812ffbfe9d867cf9da1","src/queue/mod.rs":"a84864686c2c33c92ae819a13a4689ff8be9b8bf2d84d1a94544f920d06eee13","src/queue/test.rs":"9a807bab5b99bb66fd40e70b26dec719b64d7a3a6a5366f3966adfc67fc1af6e","src/set/hash_trie_set/mod.rs":"14d55b91796ce8a04948eaa957efa436e9a435a3fc282ce77d299b44d547f4d2","src/set/hash_trie_set/test.rs":"78485bcf840dd8ee40bf18033797d46834e3bbce66ce1fb9a2f70bb714256b14","src/set/mod.rs":"2a340cb24bfba57b5eac45788836cab6683b2e9f417caf455622265c19c69d93","src/set/red_black_tree_set/mod.rs":"4d2e0e11545f4141f7cc847ed31bfe1501b420ff18bd8504afe9200ae45ec0f1","src/set/red_black_tree_set/test.rs":"8b77067952f2b2c96698f8b45cb86ec40ff8f2c745cef5afda9524a0cf516c5b","src/stack/mod.rs":"99f014458de35a2a9740ba1cacefa7f9b59043280780be94e5a7d15f1b52c861","src/stack/test.rs":"e46a51fceabbe3149d3c02b7b6b9b29a47c2155d2bfd467bcc5217cb0039b114","src/utils/mod.rs":"6af1f684d3e6378fb1e1af0b54c3947eafc9eaec7e9f58aadb6983e6461c779b","src/utils/test.rs":"c85d08dd2872c5ca28e5546a6953dc1843780d830b2136889e9e49c53d33a633","src/vector/mod.rs":"3e817926858643108321a7f2ed011e1be51c7f43e8ef264585b9e30b90b8930c","src/vector/test.rs":"d5737008b2ee146f357cd40f38aa2df06604998df65a680dd4b5a406bd779312"},"package":"a0e15515d3ce3313324d842629ea4905c25a13f81953eadb88f85516f59290a4"}rpds/release-notes.md0000644000175000017500000000520214661133735015600 0ustar jamespagejamespage# Release notes ## 1.1.0 * Use [triomphe](https://crates.io/crates/triomphe) reference-counting pointer by default in `Sync` data structures, which improves their performance. ## 1.0.1 * Fix the tests of `SparseArrayUsize` on 32-bit computers. This issue did not affect production code which did work correctly on 32-bit platforms. ## 1.0.0 * First stable version. It’s time to commit to a stable release :). * Improved performance of equality check for `{HashTrie,RedBlackTree}Map` and `{HashTrie,RedBlackTree}Set`, as well as subset and superset checks for `{HashTrie,RedBlackTree}Set` when the references are the same. ## 0.13.0 * Updated archery fixing a soundness bug. See issue [#18](https://github.com/orium/archery/issues/18). ## 0.12.0 * Implemented `Hash` for `RedBlackTreeSet`. ## 0.11.0 * Added `{HashTrie,RedBlackTree}Map::get_key_value()` and `{HashTrie,RedBlackTree}Set::get()`. ## 0.10.0 * Improved `{HashTrieMap,HashTrieSet}` iteration performance. ## 0.9.0 * Added `{HashTrie,RedBlackTree}Map::get_mut()`. * Improved `HashTrieMap` performance when using `Rc` pointers. ## 0.8.0 * Added support for `no_std`. ## 0.7.0 * Now the shared pointer type of all data structures use can be parameterizable. See the [Thread safety](./README.md#thread-safety) section in the README for details. ([#7](https://github.com/orium/rpds/issues/7)) * Fix bug where dropping long lists would cause a stack overflow. ([#46](https://github.com/orium/rpds/issues/46)) ## 0.6.0 * Implemented `RedBlackTree{Map,Set}::range()` iterator. * Implemented `IndexMut` and `Vector::get_mut()`. * Added `#[must_use]` to the immutable methods of all data structures. * Improved performance of `List::reverse_mut()`. * Improved performance of `RedBlackTreeSet` serialization. ## 0.5.0 * Mutable methods galore. Now all data structures offer mutable methods. These are generally much faster! * Implemented `Extend` for `Vector`. ## 0.4.0 * Added macros to create data structures with the given values (analog to `vec![]`). * Added `{HashTrieSet,RedBlackTreeSet}::{is_disjoint(),is_subset(),is_superset()}`. ## 0.3.0 * Added support for serialization with serde. * Speed-up `HashTrieMap::remove()` by ~70%. * Speed-up `Vector::push_back()` by ~80%. ## 0.2.0 * Implemented `RedBlackTreeMap` data structure. * Implemented `RedBlackTreeSet` data structure. ## 0.1.0 * Implemented `Queue` data structure. * Implemented `HashTrieSet` data structure. * Implemented `Stack` data structure. * Implemented `List::last()` and `List::reverse()`. ## 0.0.0 * Initial release of rpds. This release contains these data structures: `List`, `Vector`, and `HashTrieMap`. static_assertions/0000775000175000017500000000000014661133735015304 5ustar jamespagejamespagestatic_assertions/README.md0000644000175000017500000001641514661133735016570 0ustar jamespagejamespage[![Banner](https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Banner.png)](https://github.com/nvzqz/static-assertions-rs)

Compile-time assertions for Rust, brought to you by [Nikolai Vazquez](https://twitter.com/NikolaiVazquez). This library lets you ensure correct assumptions about constants, types, and more. See the [docs] and [FAQ](#faq) for more info! ## Installation This crate is available [on crates.io](https://crates.io/crates/static_assertions) and can be used by adding the following to your project's [`Cargo.toml`](https://doc.rust-lang.org/cargo/reference/manifest.html): ```toml [dependencies] static_assertions = "1.1.0" ``` and this to your crate root (`main.rs` or `lib.rs`): ```rust #[macro_use] extern crate static_assertions; ``` ## Usage This crate exposes the following macros: - [`assert_cfg!`] - [`assert_eq_align!`] - [`assert_eq_size!`] - [`assert_eq_size_ptr!`] - [`assert_eq_size_val!`] - [`assert_fields!`] - [`assert_impl_all!`] - [`assert_impl_any!`] - [`assert_impl_one!`] - [`assert_not_impl_all!`] - [`assert_not_impl_any!`] - [`assert_obj_safe!`] - [`assert_trait_sub_all!`] - [`assert_trait_super_all!`] - [`assert_type_eq_all!`] - [`assert_type_ne_all!`] - [`const_assert!`] - [`const_assert_eq!`] - [`const_assert_ne!`] ## FAQ - **Q:** When would I want to use this? **A:** This library is useful for when wanting to ensure properties of constants, types, and traits. Basic examples: - With the release of 1.39, `str::len` can be called in a `const` context. Using [`const_assert!`], one can check that a string generated from elsewhere is of a given size: ```rust const DATA: &str = include_str!("path/to/string.txt"); const_assert!(DATA.len() < 512); ``` - Have a type that absolutely must implement certain traits? With [`assert_impl_all!`], one can ensure this: ```rust struct Foo { value: // ... } assert_impl_all!(Foo: Send, Sync); ``` - **Q:** How can I contribute? **A:** A couple of ways! You can: - Attempt coming up with some form of static analysis that you'd like to see implemented. Create a [new issue] and describe how you'd imagine your assertion to work, with example code to demonstrate. - Implement your own static assertion and create a [pull request]. - Give feedback. What are some pain points? Where is it unpleasant? - Write docs. If you're familiar with how this library works, sharing your knowledge with the rest its users would be great! - **Q:** Will this affect my compiled binary? **A:** Nope! There is zero runtime cost to using this because all checks are at compile-time, and so no code is emitted to run. - **Q:** Will this affect my compile times? **A:** Likely not by anything perceivable. If this is a concern, this library can be put in `dev-dependencies`: ```toml [dev-dependencies] static_assertions = "1.1.0" ``` and then assertions can be conditionally run behind `#[cfg(test)]`: ```rust #[cfg(test)] const_assert_eq!(MEANING_OF_LIFE, 42); ``` However, the assertions will only be checked when running `cargo test`. This somewhat defeats the purpose of catching false static conditions up-front with a compilation failure. - **Q:** What is `const _`? **A:** It's a way of creating an unnamed constant. This is used so that macros can be called from a global scope without requiring a scope-unique label. This library makes use of the side effects of evaluating the `const` expression. See the feature's [tracking issue](https://github.com/rust-lang/rust/issues/54912) and [issue #1](https://github.com/nvzqz/static-assertions-rs/issues/1) for more info. ## Changes See [`CHANGELOG.md`](https://github.com/nvzqz/static-assertions-rs/blob/master/CHANGELOG.md) for a complete list of what has changed from one version to another. ## License This project is released under either: - [MIT License](https://github.com/nvzqz/static-assertions-rs/blob/master/LICENSE-MIT) - [Apache License (Version 2.0)](https://github.com/nvzqz/static-assertions-rs/blob/master/LICENSE-APACHE) at your choosing. [new issue]: https://github.com/nvzqz/static-assertions-rs/issues/new [pull request]: https://github.com/nvzqz/static-assertions-rs/pulls [docs]: https://docs.rs/static_assertions [`assert_cfg!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_cfg.html [`assert_eq_align!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_align.html [`assert_eq_size!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_size.html [`assert_eq_size_ptr!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_size_ptr.html [`assert_eq_size_val!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_eq_size_val.html [`assert_fields!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_fields.html [`assert_impl_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_impl_all.html [`assert_impl_any!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_impl_any.html [`assert_impl_one!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_impl_one.html [`assert_not_impl_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_not_impl_all.html [`assert_not_impl_any!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_not_impl_any.html [`assert_obj_safe!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_obj_safe.html [`assert_trait_sub_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_trait_sub_all.html [`assert_trait_super_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_trait_super_all.html [`assert_type_eq_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_type_eq_all.html [`assert_type_ne_all!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.assert_type_ne_all.html [`const_assert!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.const_assert.html [`const_assert_eq!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.const_assert_eq.html [`const_assert_ne!`]: https://docs.rs/static_assertions/1.1.0/static_assertions/macro.const_assert_ne.html static_assertions/LICENSE-APACHE0000644000175000017500000002613614661133735017236 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. static_assertions/Cargo.toml0000644000175000017500000000260314661133735017233 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "static_assertions" version = "1.1.0" authors = ["Nikolai Vazquez"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "CHANGELOG.md", "LICENSE*"] description = "Compile-time assertions to ensure that invariants are met." homepage = "https://github.com/nvzqz/static-assertions-rs" documentation = "https://docs.rs/static_assertions/" readme = "README.md" keywords = ["assert", "static", "testing"] categories = ["no-std", "rust-patterns", "development-tools::testing"] license = "MIT OR Apache-2.0" repository = "https://github.com/nvzqz/static-assertions-rs" [features] nightly = [] [badges.is-it-maintained-issue-resolution] repository = "nvzqz/static-assertions-rs" [badges.is-it-maintained-open-issues] repository = "nvzqz/static-assertions-rs" [badges.maintenance] status = "passively-maintained" [badges.travis-ci] repository = "nvzqz/static-assertions-rs" static_assertions/LICENSE-MIT0000644000175000017500000000206014661133735016734 0ustar jamespagejamespageMIT License Copyright (c) 2017 Nikolai Vazquez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. static_assertions/src/0000775000175000017500000000000014661133735016073 5ustar jamespagejamespagestatic_assertions/src/assert_cfg.rs0000644000175000017500000000330614661133735020561 0ustar jamespagejamespage/// Asserts that a given configuration is set. /// /// # Examples /// /// A project will simply fail to compile if the given configuration is not set. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// // We're not masochists /// # #[cfg(not(target_pointer_width = "16"))] // Just in case /// assert_cfg!(not(target_pointer_width = "16")); /// ``` /// /// If a project does not support a set of configurations, you may want to /// report why. There is the option of providing a compile error message string: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// # #[cfg(any(unix, windows))] /// assert_cfg!(any(unix, windows), "There is only support for Unix or Windows"); /// /// // User needs to specify a database back-end /// # #[cfg(target_pointer_width = "0")] // Impossible /// assert_cfg!(all(not(all(feature = "mysql", feature = "mongodb")), /// any( feature = "mysql", feature = "mongodb")), /// "Must exclusively use MySQL or MongoDB as database back-end"); /// ``` /// /// Some configurations are impossible. For example, we can't be compiling for /// both macOS _and_ Windows simultaneously: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_cfg!(all(target_os = "macos", /// target_os = "windows"), /// "No, that's not how it works! ಠ_ಠ"); /// ``` #[macro_export] macro_rules! assert_cfg { () => {}; ($($cfg:meta)+, $msg:expr $(,)?) => { #[cfg(not($($cfg)+))] compile_error!($msg); }; ($($cfg:tt)*) => { #[cfg(not($($cfg)*))] compile_error!(concat!("Cfg does not pass: ", stringify!($($cfg)*))); }; } static_assertions/src/assert_eq_align.rs0000644000175000017500000000257514661133735021610 0ustar jamespagejamespage/// Asserts that types are equal in alignment. /// /// This is useful when ensuring that pointer arithmetic is done correctly, or /// when [FFI] requires a type to have the same alignment as some foreign type. /// /// # Examples /// /// A `usize` has the same alignment as any pointer type: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_eq_align!(usize, *const u8, *mut u8); /// ``` /// /// The following passes because `[i32; 4]` has the same alignment as `i32`: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_eq_align!([i32; 4], i32); /// ``` /// /// The following example fails to compile because `i32x4` explicitly has 4 /// times the alignment as `[i32; 4]`: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// # #[allow(non_camel_case_types)] /// #[repr(align(16))] /// struct i32x4([i32; 4]); /// /// assert_eq_align!(i32x4, [i32; 4]); /// ``` /// /// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface #[macro_export] macro_rules! assert_eq_align { ($x:ty, $($xs:ty),+ $(,)?) => { const _: fn() = || { // Assigned instance must match the annotated type or else it will // fail to compile use $crate::_core::mem::align_of; $(let _: [(); align_of::<$x>()] = [(); align_of::<$xs>()];)+ }; }; } static_assertions/src/assert_impl.rs0000644000175000017500000003113614661133735020765 0ustar jamespagejamespage/// Asserts that the type implements exactly one in a set of traits. /// /// Related: /// - [`assert_impl_any!`] /// - [`assert_impl_all!`] /// - [`assert_not_impl_all!`] /// - [`assert_not_impl_any!`] /// /// # Examples /// /// Given some type `Foo`, it is expected to implement either `Snap`, `Crackle`, /// or `Pop`: /// /// ```compile_fail /// # use static_assertions::assert_impl_one; fn main() {} /// struct Foo; /// /// trait Snap {} /// trait Crackle {} /// trait Pop {} /// /// assert_impl_one!(Foo: Snap, Crackle, Pop); /// ``` /// /// If _only_ `Crackle` is implemented, the assertion passes: /// /// ``` /// # use static_assertions::assert_impl_one; fn main() {} /// # struct Foo; /// # trait Snap {} /// # trait Crackle {} /// # trait Pop {} /// impl Crackle for Foo {} /// /// assert_impl_one!(Foo: Snap, Crackle, Pop); /// ``` /// /// If `Snap` or `Pop` is _also_ implemented, the assertion fails: /// /// ```compile_fail /// # use static_assertions::assert_impl_one; fn main() {} /// # struct Foo; /// # trait Snap {} /// # trait Crackle {} /// # trait Pop {} /// # impl Crackle for Foo {} /// impl Pop for Foo {} /// /// assert_impl_one!(Foo: Snap, Crackle, Pop); /// ``` /// /// [`assert_impl_any!`]: macro.assert_impl_any.html /// [`assert_impl_all!`]: macro.assert_impl_all.html /// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html /// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html #[macro_export] macro_rules! assert_impl_one { ($x:ty: $($t:path),+ $(,)?) => { const _: fn() = || { // Generic trait that must be implemented for `$x` exactly once. trait AmbiguousIfMoreThanOne { // Required for actually being able to reference the trait. fn some_item() {} } // Creates multiple scoped `Token` types for each trait `$t`, over // which a specialized `AmbiguousIfMoreThanOne` is // implemented for every type that implements `$t`. $({ #[allow(dead_code)] struct Token; impl AmbiguousIfMoreThanOne for T {} })+ // If there is only one specialized trait impl, type inference with // `_` can be resolved and this can compile. Fails to compile if // `$x` implements more than one `AmbiguousIfMoreThanOne` or // does not implement any at all. let _ = <$x as AmbiguousIfMoreThanOne<_>>::some_item; }; }; } /// Asserts that the type implements _all_ of the given traits. /// /// See [`assert_not_impl_all!`] for achieving the opposite effect. /// /// # Examples /// /// This can be used to ensure types implement auto traits such as [`Send`] and /// [`Sync`], as well as traits with [blanket `impl`s][blanket]. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_all!(u32: Copy, Send); /// assert_impl_all!(&str: Into); /// ``` /// /// The following example fails to compile because raw pointers do not implement /// [`Send`] since they cannot be moved between threads safely: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_all!(*const u8: Send); /// ``` /// /// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods #[macro_export] macro_rules! assert_impl_all { ($type:ty: $($trait:path),+ $(,)?) => { const _: fn() = || { // Only callable when `$type` implements all traits in `$($trait)+`. fn assert_impl_all() {} assert_impl_all::<$type>(); }; }; } /// Asserts that the type implements _any_ of the given traits. /// /// See [`assert_not_impl_any!`] for achieving the opposite effect. /// /// # Examples /// /// `u8` cannot be converted from `u16`, but it can be converted into `u16`: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_any!(u8: From, Into); /// ``` /// /// The unit type cannot be converted from `u8` or `u16`, but it does implement /// [`Send`]: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_any!((): From, From, Send); /// ``` /// /// The following example fails to compile because raw pointers do not implement /// [`Send`] or [`Sync`] since they cannot be moved or shared between threads /// safely: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl_any!(*const u8: Send, Sync); /// ``` /// /// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html #[macro_export] macro_rules! assert_impl_any { ($x:ty: $($t:path),+ $(,)?) => { const _: fn() = || { use $crate::_core::marker::PhantomData; use $crate::_core::ops::Deref; // Fallback to use as the first iterative assignment to `previous`. let previous = AssertImplAnyFallback; struct AssertImplAnyFallback; // Ensures that blanket traits can't impersonate the method. This // prevents a false positive attack where---if a blanket trait is in // scope that has `_static_assertions_impl_any`---the macro will // compile when it shouldn't. // // See https://github.com/nvzqz/static-assertions-rs/issues/19 for // more info. struct ActualAssertImplAnyToken; trait AssertImplAnyToken {} impl AssertImplAnyToken for ActualAssertImplAnyToken {} fn assert_impl_any_token(_: T) {} $(let previous = { struct Wrapper(PhantomData, N); // If the method for this wrapper can't be called then the // compiler will insert a deref and try again. This forwards the // compiler's next attempt to the previous wrapper. impl Deref for Wrapper { type Target = N; fn deref(&self) -> &Self::Target { &self.1 } } // This impl is bounded on the `$t` trait, so the method can // only be called if `$x` implements `$t`. This is why a new // `Wrapper` is defined for each `previous`. impl Wrapper { fn _static_assertions_impl_any(&self) -> ActualAssertImplAnyToken { ActualAssertImplAnyToken } } Wrapper::<$x, _>(PhantomData, previous) };)+ // Attempt to find the method that can actually be called. The found // method must return a type that implements the sealed `Token` // trait, this ensures that blanket trait methods can't cause this // macro to compile. assert_impl_any_token(previous._static_assertions_impl_any()); }; }; } /// Asserts that the type does **not** implement _all_ of the given traits. /// /// This can be used to ensure types do not implement auto traits such as /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. /// /// Note that the combination of all provided traits is required to not be /// implemented. If you want to check that none of multiple traits are /// implemented you should invoke [`assert_not_impl_any!`] instead. /// /// # Examples /// /// Although `u32` implements `From`, it does not implement `Into`: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_not_impl_all!(u32: From, Into); /// ``` /// /// The following example fails to compile since `u32` can be converted into /// `u64`. /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_not_impl_all!(u32: Into); /// ``` /// /// The following compiles because [`Cell`] is not both [`Sync`] _and_ [`Send`]: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// use std::cell::Cell; /// /// assert_not_impl_all!(Cell: Sync, Send); /// ``` /// /// But it is [`Send`], so this fails to compile: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// # std::cell::Cell; /// assert_not_impl_all!(Cell: Send); /// ``` /// /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// [`assert_not_impl_any!`]: macro.assert_not_impl_any.html /// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods #[macro_export] macro_rules! assert_not_impl_all { ($x:ty: $($t:path),+ $(,)?) => { const _: fn() = || { // Generic trait with a blanket impl over `()` for all types. trait AmbiguousIfImpl { // Required for actually being able to reference the trait. fn some_item() {} } impl AmbiguousIfImpl<()> for T {} // Used for the specialized impl when *all* traits in // `$($t)+` are implemented. #[allow(dead_code)] struct Invalid; impl AmbiguousIfImpl for T {} // If there is only one specialized trait impl, type inference with // `_` can be resolved and this can compile. Fails to compile if // `$x` implements `AmbiguousIfImpl`. let _ = <$x as AmbiguousIfImpl<_>>::some_item; }; }; } /// Asserts that the type does **not** implement _any_ of the given traits. /// /// This can be used to ensure types do not implement auto traits such as /// [`Send`] and [`Sync`], as well as traits with [blanket `impl`s][blanket]. /// /// This macro causes a compilation failure if any of the provided individual /// traits are implemented for the type. If you want to check that a combination /// of traits is not implemented you should invoke [`assert_not_impl_all!`] /// instead. For single traits both macros behave the same. /// /// # Examples /// /// If `u32` were to implement `Into` conversions for `usize` _and_ for `u8`, /// the following would fail to compile: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_not_impl_any!(u32: Into, Into); /// ``` /// /// This is also good for simple one-off cases: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_not_impl_any!(&'static mut u8: Copy); /// ``` /// /// The following example fails to compile since `u32` can be converted into /// `u64` even though it can not be converted into a `u16`: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_not_impl_any!(u32: Into, Into); /// ``` /// /// [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html /// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html /// [`assert_not_impl_all!`]: macro.assert_not_impl_all.html /// [blanket]: https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods #[macro_export] macro_rules! assert_not_impl_any { ($x:ty: $($t:path),+ $(,)?) => { const _: fn() = || { // Generic trait with a blanket impl over `()` for all types. trait AmbiguousIfImpl { // Required for actually being able to reference the trait. fn some_item() {} } impl AmbiguousIfImpl<()> for T {} // Creates multiple scoped `Invalid` types for each trait `$t`, over // which a specialized `AmbiguousIfImpl` is implemented for // every type that implements `$t`. $({ #[allow(dead_code)] struct Invalid; impl AmbiguousIfImpl for T {} })+ // If there is only one specialized trait impl, type inference with // `_` can be resolved and this can compile. Fails to compile if // `$x` implements any `AmbiguousIfImpl`. let _ = <$x as AmbiguousIfImpl<_>>::some_item; }; }; } static_assertions/src/assert_trait.rs0000644000175000017500000000604214661133735021145 0ustar jamespagejamespage/// Asserts that the trait is a child of all of the other traits. /// /// Related: /// - [`assert_trait_super_all!`] /// /// # Examples /// /// All types that implement [`Copy`] must implement [`Clone`]: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_trait_sub_all!(Copy: Clone); /// ``` /// /// All types that implement [`Ord`] must implement [`PartialEq`], [`Eq`], and /// [`PartialOrd`]: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_trait_sub_all!(Ord: PartialEq, Eq, PartialOrd); /// ``` /// /// The following example fails to compile because [`Eq`] is not required for /// [`PartialOrd`]: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_trait_sub_all!(PartialOrd: Eq); /// ``` /// /// [`assert_trait_super_all!`]: macro.assert_trait_super_all.html /// /// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html /// [`Ord`]: https://doc.rust-lang.org/std/cmp/trait.Ord.html /// [`PartialOrd`]: https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html /// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html #[macro_export] macro_rules! assert_trait_sub_all { ($sub:path: $($super:path),+ $(,)?) => { const _: () = { // One scope per super-trait. $({ #[allow(non_camel_case_types)] trait __Impl_Implication: $super {} // Can only be implemented for `$sub` types if `$super` is // also implemented. impl __Impl_Implication for T {} })+ }; }; } /// Asserts that the trait is a parent of all of the other traits. /// /// Related: /// - [`assert_trait_sub_all!`] /// /// # Examples /// /// With this, traits `A` and `B` can both be tested to require [`Copy`] on a /// single line: /// /// ``` /// # use static_assertions::assert_trait_super_all; /// trait A: Copy {} /// trait B: Copy {} /// /// assert_trait_super_all!(Copy: A, B); /// ``` /// /// Otherwise, each sub-trait would require its own call to /// [`assert_trait_sub_all!`]: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// # trait A: Copy {} /// # trait B: Copy {} /// assert_trait_sub_all!(A: Copy); /// assert_trait_sub_all!(B: Copy); /// ``` /// /// The following example fails to compile because trait `C` does not require /// [`Copy`]: /// /// ```compile_fail /// # use static_assertions::assert_trait_super_all; /// # trait A: Copy {} /// # trait B: Copy {} /// trait C {} /// /// assert_trait_super_all!(Copy: A, B, C); /// ``` /// /// [`assert_trait_sub_all!`]: macro.assert_trait_sub_all.html /// /// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html #[macro_export(local_inner_macros)] macro_rules! assert_trait_super_all { ($super:path: $($sub:path),+ $(,)?) => { $(assert_trait_sub_all!($sub: $super);)+ }; } static_assertions/src/lib.rs0000644000175000017500000000657214661133735017217 0ustar jamespagejamespage//! [![Banner](https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Banner.png)](https://github.com/nvzqz/static-assertions-rs) //! //! //! //! Assertions to ensure correct assumptions about constants, types, and more. //! //! _All_ checks provided by this crate are performed at [compile-time]. This //! allows for finding errors quickly and early when it comes to ensuring //! certain features or aspects of a codebase. These macros are especially //! important when exposing a public API that requires types to be the same size //! or implement certain traits. //! //! # Usage //! //! This crate is available [on crates.io][crate] and can be used by adding the //! following to your project's [`Cargo.toml`]: //! //! ```toml //! [dependencies] //! static_assertions = "1.1.0" //! ``` //! //! and this to your crate root (`main.rs` or `lib.rs`): //! //! ``` //! #[macro_use] //! extern crate static_assertions; //! # fn main() {} //! ``` //! //! When using [Rust 2018 edition][2018], the following shorthand can help if //! having `#[macro_use]` is undesirable. //! //! ```edition2018 //! extern crate static_assertions as sa; //! //! sa::const_assert!(true); //! ``` //! //! # Examples //! //! Very thorough examples are provided in the docs for //! [each individual macro](#macros). Failure case examples are also documented. //! //! # Changes //! //! See [`CHANGELOG.md`](https://github.com/nvzqz/static-assertions-rs/blob/master/CHANGELOG.md) //! for an exhaustive list of what has changed from one version to another. //! //! # Donate //! //! This project is made freely available (as in free beer), but unfortunately //! not all beer is free! So, if you would like to buy me a beer (or coffee or //! *more*), then consider supporting my work that's benefited your project //! and thousands of others. //! //! //! Become a Patron! //! //! //! Buy me a coffee //! //! //! [Rust 1.37]: https://blog.rust-lang.org/2019/08/15/Rust-1.37.0.html //! [2018]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html#rust-2018 //! [crate]: https://crates.io/crates/static_assertions //! [compile-time]: https://en.wikipedia.org/wiki/Compile_time //! [`Cargo.toml`]: https://doc.rust-lang.org/cargo/reference/manifest.html #![doc(html_root_url = "https://docs.rs/static_assertions/1.1.0")] #![doc(html_logo_url = "https://raw.githubusercontent.com/nvzqz/static-assertions-rs/assets/Icon.png")] #![no_std] #![deny(unused_macros)] #[doc(hidden)] pub extern crate core as _core; mod assert_cfg; mod assert_eq_align; mod assert_eq_size; mod assert_fields; mod assert_impl; mod assert_obj_safe; mod assert_trait; mod assert_type; mod const_assert; static_assertions/src/assert_fields.rs0000644000175000017500000000351114661133735021266 0ustar jamespagejamespage/// Asserts that the type has the given fields. /// /// # Examples /// /// One common use case is when types have fields defined multiple times as a /// result of `#[cfg]`. This can be an issue when exposing a public API. /// /// ``` /// # #[macro_use] extern crate static_assertions; /// pub struct Ty { /// #[cfg(windows)] /// pub val1: u8, /// #[cfg(not(windows))] /// pub val1: usize, /// /// #[cfg(unix)] /// pub val2: u32, /// #[cfg(not(unix))] /// pub val2: usize, /// } /// /// // Always have `val2` regardless of OS /// assert_fields!(Ty: val2); /// ``` /// /// This macro even works with `enum` variants: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// enum Data { /// Val { /// id: i32, /// name: String, /// bytes: [u8; 128], /// }, /// Ptr(*const u8), /// } /// /// assert_fields!(Data::Val: id, bytes); /// ``` /// /// The following example fails to compile because [`Range`] does not have a field named `middle`: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// use std::ops::Range; /// /// assert_fields!(Range: middle); /// ``` /// /// [`Range`]: https://doc.rust-lang.org/std/ops/struct.Range.html #[macro_export] macro_rules! assert_fields { ($t:ident::$v:ident: $($f:ident),+) => { #[allow(unknown_lints, unneeded_field_pattern)] const _: fn() = || { #[allow(dead_code, unreachable_patterns)] fn assert(value: $t) { match value { $($t::$v { $f: _, .. } => {},)+ _ => {} } } }; }; ($t:path: $($f:ident),+) => { #[allow(unknown_lints, unneeded_field_pattern)] const _: fn() = || { $(let $t { $f: _, .. };)+ }; }; } static_assertions/src/assert_obj_safe.rs0000644000175000017500000000451514661133735021575 0ustar jamespagejamespage// FIXME: Link below is required to render in index /// Asserts that the traits support dynamic dispatch /// ([object-safety](https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects)). /// /// This is useful for when changes are made to a trait that accidentally /// prevent it from being used as an [object]. Such a case would be adding a /// generic method and forgetting to add `where Self: Sized` after it. If left /// unnoticed, that mistake will affect crate users and break both forward and /// backward compatibility. /// /// # Examples /// /// When exposing a public API, it's important that traits that could previously /// use dynamic dispatch can still do so in future compatible crate versions. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// trait MySafeTrait { /// fn foo(&self) -> u32; /// } /// /// assert_obj_safe!(std::fmt::Write, MySafeTrait); /// ``` /// /// Works with traits that are not in the calling module: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// mod inner { /// pub trait BasicTrait { /// fn bar(&self); /// } /// assert_obj_safe!(BasicTrait); /// } /// /// assert_obj_safe!(inner::BasicTrait); /// ``` /// /// The following example fails to compile because raw pointers cannot be sent /// between threads safely: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_impl!(*const u8, Send); /// ``` /// /// The following example fails to compile because generics without /// `where Self: Sized` are not allowed in [object-safe][object] trait methods: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// trait MyUnsafeTrait { /// fn baz(&self) -> T; /// } /// /// assert_obj_safe!(MyUnsafeTrait); /// ``` /// /// When we fix that, the previous code will compile: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// trait MyUnsafeTrait { /// fn baz(&self) -> T where Self: Sized; /// } /// /// assert_obj_safe!(MyUnsafeTrait); /// ``` /// /// [object]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#object-safety-is-required-for-trait-objects #[macro_export] macro_rules! assert_obj_safe { ($($xs:path),+ $(,)?) => { $(const _: Option<&$xs> = None;)+ }; } static_assertions/src/assert_eq_size.rs0000644000175000017500000000657214661133735021471 0ustar jamespagejamespage/// Asserts that types are equal in size. /// /// When performing operations such as pointer casts or dealing with [`usize`] /// versus [`u64`] versus [`u32`], the size of your types matter. That is where /// this macro comes into play. /// /// # Alternatives /// /// There also exists [`assert_eq_size_val`](macro.assert_eq_size_val.html) and /// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying /// types to compare, values' sizes can be directly compared against each other. /// /// # Examples /// /// These three types, despite being very different, all have the same size: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_eq_size!([u8; 4], (u16, u16), u32); /// ``` /// /// The following example fails to compile because `u32` has 4 times the size of /// `u8`: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_eq_size!(u32, u8); /// ``` /// /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html /// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html /// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html #[macro_export] macro_rules! assert_eq_size { ($x:ty, $($xs:ty),+ $(,)?) => { const _: fn() = || { $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+ }; }; } /// Asserts that values pointed to are equal in size. /// /// # Examples /// /// This especially is useful for when coercing pointers between different types /// and ensuring the underlying values are the same size. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// fn operation(x: &(u32, u32), y: &[u16; 4]) { /// assert_eq_size_ptr!(x, y); /// // ... /// } /// ``` /// /// The following example fails to compile because byte arrays of different /// lengths have different sizes: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; /// # fn main() { /// static BYTES: &[u8; 4] = &[ /// /* ... */ /// # 0; 4 /// ]; /// /// static TABLE: &[u8; 16] = &[ /// /* ... */ /// # 0; 16 /// ]; /// /// assert_eq_size_ptr!(BYTES, TABLE); /// ``` #[macro_export] macro_rules! assert_eq_size_ptr { ($x:expr, $($xs:expr),+ $(,)?) => { #[allow(unknown_lints, unsafe_code, forget_copy, useless_transmute)] let _ = || unsafe { use $crate::_core::{mem, ptr}; let mut copy = ptr::read($x); $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+ mem::forget(copy); }; } } /// Asserts that values are equal in size. /// /// This macro doesn't consume its arguments and thus works for /// non-[`Clone`]able values. /// /// # Examples /// /// ``` /// # #[macro_use] extern crate static_assertions; /// # fn main() { /// struct Byte(u8); /// /// let x = 10u8; /// let y = Byte(42); // Works for non-cloneable types /// /// assert_eq_size_val!(x, y); /// assert_eq_size_val!(x, y, 0u8); /// # } /// ``` /// /// Even though both values are 0, they are of types with different sizes: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; /// # fn main() { /// assert_eq_size_val!(0u8, 0u32); /// # } /// ``` /// /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html #[macro_export(local_inner_macros)] macro_rules! assert_eq_size_val { ($x:expr, $($xs:expr),+ $(,)?) => { assert_eq_size_ptr!(&$x, $(&$xs),+); } } static_assertions/src/const_assert.rs0000644000175000017500000000566214661133735021157 0ustar jamespagejamespage/// Asserts that constant expressions evaluate to `true`. /// /// Constant expressions can be ensured to have certain properties via this /// macro If the expression evaluates to `false`, the file will fail to compile. /// This is synonymous to [`static_assert` in C++][static_assert]. /// /// # Alternatives /// /// There also exists [`const_assert_eq`](macro.const_assert_eq.html) for /// validating whether a sequence of expressions are equal to one another. /// /// # Examples /// /// A common use case is to guarantee properties about a constant value that's /// generated via meta-programming. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// const VALUE: i32 = // ... /// # 3; /// /// const_assert!(VALUE >= 2); /// ``` /// /// Inputs are type-checked as booleans: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// const_assert!(!0); /// ``` /// /// Despite this being a macro, we see this produces a type error: /// /// ```txt /// | const_assert!(!0); /// | ^^ expected bool, found integral variable /// | /// = note: expected type `bool` /// found type `{integer}` /// ``` /// /// The following fails to compile because multiplying by 5 does not have an /// identity property: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// const_assert!(5 * 5 == 5); /// ``` /// /// [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert #[macro_export] macro_rules! const_assert { ($x:expr $(,)?) => { #[allow(unknown_lints, eq_op)] const _: [(); 0 - !{ const ASSERT: bool = $x; ASSERT } as usize] = []; }; } /// Asserts that constants are equal in value. /// /// # Examples /// /// This works as a shorthand for `const_assert!(a == b)`: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// const TWO: usize = 2; /// /// const_assert_eq!(TWO * TWO, TWO + TWO); /// ``` /// /// Just because 2 × 2 = 2 + 2 doesn't mean it holds true for other numbers: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// const_assert_eq!(4 + 4, 4 * 4); /// ``` #[macro_export(local_inner_macros)] macro_rules! const_assert_eq { ($x:expr, $y:expr $(,)?) => { const_assert!($x == $y); }; } /// Asserts that constants are **not** equal in value. /// /// # Examples /// /// This works as a shorthand for `const_assert!(a != b)`: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// const NUM: usize = 32; /// /// const_assert_ne!(NUM * NUM, 64); /// ``` /// /// The following example fails to compile because 2 is magic and 2 × 2 = 2 + 2: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// const_assert_ne!(2 + 2, 2 * 2); /// ``` #[macro_export(local_inner_macros)] macro_rules! const_assert_ne { ($x:expr, $y:expr $(,)?) => { const_assert!($x != $y); }; } static_assertions/src/assert_type.rs0000644000175000017500000000544614661133735021012 0ustar jamespagejamespage/// Asserts that _all_ types in a list are equal to each other. /// /// # Examples /// /// Often times, type aliases are used to express usage semantics via naming. In /// some cases, the underlying type may differ based on platform. However, other /// types like [`c_float`] will always alias the same type. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// use std::os::raw::c_float; /// /// assert_type_eq_all!(c_float, f32); /// ``` /// /// This macro can also be used to compare types that involve lifetimes! Just /// use `'static` in that case: /// /// ``` /// # #[macro_use] extern crate static_assertions; /// # fn main() { /// type Buf<'a> = &'a [u8]; /// /// assert_type_eq_all!(Buf<'static>, &'static [u8]); /// # } /// ``` /// /// The following example fails to compile because `String` and `str` do not /// refer to the same type: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_type_eq_all!(String, str); /// ``` /// /// This should also work the other way around, regardless of [`Deref`] /// implementations. /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_type_eq_all!(str, String); /// ``` /// /// [`c_float`]: https://doc.rust-lang.org/std/os/raw/type.c_float.html /// [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html #[macro_export] macro_rules! assert_type_eq_all { ($x:ty, $($xs:ty),+ $(,)*) => { const _: fn() = || { $({ trait TypeEq { type This: ?Sized; } impl TypeEq for T { type This = Self; } fn assert_type_eq_all() where T: ?Sized + TypeEq, U: ?Sized, {} assert_type_eq_all::<$x, $xs>(); })+ }; }; } /// Asserts that _all_ types are **not** equal to each other. /// /// # Examples /// /// Rust has all sorts of slices, but they represent different types of data: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_type_ne_all!([u8], [u16], str); /// ``` /// /// The following example fails to compile because [`c_uchar`] is a type alias /// for [`u8`]: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// use std::os::raw::c_uchar; /// /// assert_type_ne_all!(c_uchar, u8, u32); /// ``` /// /// [`c_uchar`]: https://doc.rust-lang.org/std/os/raw/type.c_uchar.html /// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html #[macro_export] macro_rules! assert_type_ne_all { ($x:ty, $($y:ty),+ $(,)?) => { const _: fn() = || { trait MutuallyExclusive {} impl MutuallyExclusive for $x {} $(impl MutuallyExclusive for $y {})+ }; }; } static_assertions/CHANGELOG.md0000644000175000017500000001412514661133735017116 0ustar jamespagejamespage# Changelog [![Crates.io][crate-badge]][crate] All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog] and this project adheres to [Semantic Versioning]. ## [Unreleased] ## [1.1.0] - 2019-11-03 ### Added - `assert_impl_any!` macro - `assert_impl_one!` macro - `assert_trait_sub_all!` macro - `assert_trait_super_all!` macro - Frequently asked questions to `README.md` ### Fixed - `assert_eq_size_val!`, `const_assert_eq!`, and `const_assert_ne!` to export their local inner macros. Not having this prevented them from working when `use`d or called directly via `static_assertions::macro!(...)` ### Removed - Unused `_assert_obj_safe!` from pre-1.0 ## [1.0.0] - 2019-10-02 ### Added - `assert_eq_align!` macro ### Removed - **[breaking]** Labels from macros that needed them 🎉 - Made possible by [`const _`] in Rust 1.37 - **[breaking]** `assert_impl!` macro ### Fixed - `assert_fields!` now works for `enum` types with multiple variants ### Changed - **[breaking]** `const_assert!` macro to only take one expression - Reasoning: when custom error messages are added in the future (via [`assert!`]), having the macro allow for multiple comma-separated expressions may lead to ambiguity - **[breaking]** Trait assertions to use `Type: Trait` syntax - **[breaking]** Field assertions to use `Type: field1, field2` syntax - **[breaking]** Renamed `assert_{ne,eq}_type!` to `assert_type_{ne,eq}_all!` ## [0.3.4] - 2019-06-12 ### Changed - Aliased `assert_impl!` to `assert_impl_all!` and deprecated `assert_impl!` ### Added - `assert_impl_all!` as replacement to `assert_impl!` - `assert_not_impl_all!` and `assert_not_impl_any!` macro counterparts to `assert_impl_all!` ### Fixed - `assert_eq_type!` now works with types involving lifetimes ## [0.3.3] - 2019-06-12 ### Added - `const_assert_ne!` macro counterpart to `const_assert_eq!` ### Fixed - `assert_eq_type!` would pass when types can coerce via `Deref`, such as with `str` and `String` ## [0.3.2] - 2019-05-15 ### Added - A `assert_eq_type!` macro that allows for checking whether inputs are the same concrete type - A `assert_ne_type!` macro for checking whether inputs all refer to different types ### Fixed - `const_assert!` now only takes `bool` values whereas integer (or other type) values could previously be passed ## [0.3.1] - 2018-11-15 ### Fixed - Macros that refer to other internal macros can now be imported when compiling for Rust 2018 ([issue #10](https://github.com/nvzqz/static-assertions-rs/issues/10)) ## [0.3.0] - 2018-11-14 ### Changed - Bumped minimum supported (automatically tested) Rust version to 1.24.0 - Moved message parameter for `assert_cfg!()` to last argument position, making it consistent with other macros ### Removed - No need to use `macro!(label; ...)` syntax when compiling on nightly Rust and enabling the `nightly` feature flag ## [0.2.5] - 2017-12-12 ### Changed - `assert_eq_size_ptr` wraps its code inside of a closure, ensuring that the unsafe code inside never runs - Clippy no longer warns about `unneeded_field_pattern` within `assert_fields` ### Added - Much better documentation with test examples that are guaranteed to fail at compile-time ### Removed - Removed testing features; compile failure tests are now done via doc tests ## [0.2.4] - 2017-12-11 ### Removed - Removed the actual call to `mem::transmute` while still utilizing it for size verification ([Simon Sapin], [#5]) ### Added - `assert_cfg` macro that asserts that the given configuration is set - `assert_fields` macro to assert that a struct type or enum variant has a given field ### Fixed - Allow more generics flexibility in `assert_impl` ## [0.2.3] - 2017-08-24 ### Fixed - Trailing commas are now allowed ### Removed - Removed clippy warnings ## [0.2.2] - 2017-08-13 ### Added - Added `assert_impl` macro to ensure a type implements a given set of traits ## [0.2.1] - 2017-08-13 ### Added - Added `assert_obj_safe` macro for ensuring that a trait is object-safe ## [0.2.0] - 2017-08-12 ### Added - Added `assert_eq_size_ptr` macro ### Fixed - Allow `assert_eq_size`, `const_assert`, and `const_assert_eq` in non-function contexts via providing a unique label [#1] ### Removed - **[Breaking]** Semicolon-separated `assert_eq_size` is no longer allowed ## [0.1.1] - 2017-08-12 ### Added - Added `const_assert_eq` macro ## 0.1.0 - 2017-08-12 Initial release [Simon Sapin]: https://github.com/SimonSapin [`assert!`]: https://doc.rust-lang.org/stable/std/macro.assert.html [`const _`]: https://github.com/rust-lang/rfcs/blob/master/text/2526-const-wildcard.md [#1]: https://github.com/nvzqz/static-assertions-rs/issues/1 [#5]: https://github.com/nvzqz/static-assertions-rs/pull/5 [crate]: https://crates.io/crates/static_assertions [crate-badge]: https://img.shields.io/crates/v/static_assertions.svg [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ [Semantic Versioning]: http://semver.org/spec/v2.0.0.html [Unreleased]: https://github.com/nvzqz/static-assertions-rs/compare/v1.1.0...HEAD [1.1.0]: https://github.com/nvzqz/static-assertions-rs/compare/v1.0.0...v1.1.0 [1.0.0]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.4...v1.0.0 [0.3.4]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.3...v0.3.4 [0.3.3]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/nvzqz/static-assertions-rs/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.5...v0.3.0 [0.2.5]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.4...v0.2.5 [0.2.4]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.3...v0.2.4 [0.2.3]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.2...v0.2.3 [0.2.2]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.1...v0.2.2 [0.2.1]: https://github.com/nvzqz/static-assertions-rs/compare/v0.2.0...v0.2.1 [0.2.0]: https://github.com/nvzqz/static-assertions-rs/compare/v0.1.1...v0.2.0 [0.1.1]: https://github.com/nvzqz/static-assertions-rs/compare/v0.1.0...v0.1.1 static_assertions/.cargo-checksum.json0000664000175000017500000000254414661133735021155 0ustar jamespagejamespage{"files":{"CHANGELOG.md":"750f74f3b520672a81dd2ede5c097cfe972c0da181dd8fd010e7131a3526d4fd","Cargo.toml":"6531dbe3d557e427f9e3510e50cdf3de751a319eece11c9a937b35cfab8744c4","LICENSE-APACHE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","LICENSE-MIT":"ea084a2373ebc1f0902c09266e7bf25a05ab3814c1805bb017ffa7308f90c061","README.md":"88cc779ada8c6e1362c2d095c179284ec2755797729946ebccfe8264fcff0f8e","src/assert_cfg.rs":"ce9230bcc055d8df21ceefbed4233df5e73ecb832829ba23ac8d7f54ec457522","src/assert_eq_align.rs":"f09c4ec30e476446ab337a4a9ed950edf21c780a42ece7613f0ffc20225331ae","src/assert_eq_size.rs":"c06d2ff44e1f7af8a57b7c2fe5a9c69aa2a90d12cd41614c9d4f3ae551cdb64c","src/assert_fields.rs":"9c5baeac0215be557213eec9e80fc00de10a721d9b2c369fece743fcc6ccdc8e","src/assert_impl.rs":"fe5a2fffcbb78f60991bbc590481e74fd0d5f7ed8fa75718644599e1fae117ce","src/assert_obj_safe.rs":"88584809f3aa2dfce966b0adbeb6128191229465d653e57b68f968be001eff03","src/assert_trait.rs":"87b2d4dbd4334d9ace9880b81f3a1fbf91725c5e152b34a74c86457ca40ece30","src/assert_type.rs":"7cd942341efa7ed0b89b5e4fe1faa62bafb537ec6cf72ee6866115daee931885","src/const_assert.rs":"e0dcfe9016e34455f5efcb23500f716386d42b9fb09c6d08566d03dce8249e51","src/lib.rs":"4cbaaff38a6ac16631e774ab5a349056cbd2335ac570aeb46c5616eaf9700c3b"},"package":"a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"}syn/0000775000175000017500000000000014661133735012354 5ustar jamespagejamespagesyn/README.md0000644000175000017500000002423414661133735013636 0ustar jamespagejamespageParser for Rust source code =========================== [github](https://github.com/dtolnay/syn) [crates.io](https://crates.io/crates/syn) [docs.rs](https://docs.rs/syn) [build status](https://github.com/dtolnay/syn/actions?query=branch%3Amaster) Syn is a parsing library for parsing a stream of Rust tokens into a syntax tree of Rust source code. Currently this library is geared toward use in Rust procedural macros, but contains some APIs that may be useful more generally. - **Data structures** — Syn provides a complete syntax tree that can represent any valid Rust source code. The syntax tree is rooted at [`syn::File`] which represents a full source file, but there are other entry points that may be useful to procedural macros including [`syn::Item`], [`syn::Expr`] and [`syn::Type`]. - **Derives** — Of particular interest to derive macros is [`syn::DeriveInput`] which is any of the three legal input items to a derive macro. An example below shows using this type in a library that can derive implementations of a user-defined trait. - **Parsing** — Parsing in Syn is built around [parser functions] with the signature `fn(ParseStream) -> Result`. Every syntax tree node defined by Syn is individually parsable and may be used as a building block for custom syntaxes, or you may dream up your own brand new syntax without involving any of our syntax tree types. - **Location information** — Every token parsed by Syn is associated with a `Span` that tracks line and column information back to the source of that token. These spans allow a procedural macro to display detailed error messages pointing to all the right places in the user's code. There is an example of this below. - **Feature flags** — Functionality is aggressively feature gated so your procedural macros enable only what they need, and do not pay in compile time for all the rest. [`syn::File`]: https://docs.rs/syn/2.0/syn/struct.File.html [`syn::Item`]: https://docs.rs/syn/2.0/syn/enum.Item.html [`syn::Expr`]: https://docs.rs/syn/2.0/syn/enum.Expr.html [`syn::Type`]: https://docs.rs/syn/2.0/syn/enum.Type.html [`syn::DeriveInput`]: https://docs.rs/syn/2.0/syn/struct.DeriveInput.html [parser functions]: https://docs.rs/syn/2.0/syn/parse/index.html *Version requirement: Syn supports rustc 1.61 and up.* [*Release notes*](https://github.com/dtolnay/syn/releases)
## Resources The best way to learn about procedural macros is by writing some. Consider working through [this procedural macro workshop][workshop] to get familiar with the different types of procedural macros. The workshop contains relevant links into the Syn documentation as you work through each project. [workshop]: https://github.com/dtolnay/proc-macro-workshop
## Example of a derive macro The canonical derive macro using Syn looks like this. We write an ordinary Rust function tagged with a `proc_macro_derive` attribute and the name of the trait we are deriving. Any time that derive appears in the user's code, the Rust compiler passes their data structure as tokens into our macro. We get to execute arbitrary Rust code to figure out what to do with those tokens, then hand some tokens back to the compiler to compile into the user's crate. [`TokenStream`]: https://doc.rust-lang.org/proc_macro/struct.TokenStream.html ```toml [dependencies] syn = "2.0" quote = "1.0" [lib] proc-macro = true ``` ```rust use proc_macro::TokenStream; use quote::quote; use syn::{parse_macro_input, DeriveInput}; #[proc_macro_derive(MyMacro)] pub fn my_macro(input: TokenStream) -> TokenStream { // Parse the input tokens into a syntax tree let input = parse_macro_input!(input as DeriveInput); // Build the output, possibly using quasi-quotation let expanded = quote! { // ... }; // Hand the output tokens back to the compiler TokenStream::from(expanded) } ``` The [`heapsize`] example directory shows a complete working implementation of a derive macro. The example derives a `HeapSize` trait which computes an estimate of the amount of heap memory owned by a value. [`heapsize`]: examples/heapsize ```rust pub trait HeapSize { /// Total number of bytes of heap memory owned by `self`. fn heap_size_of_children(&self) -> usize; } ``` The derive macro allows users to write `#[derive(HeapSize)]` on data structures in their program. ```rust #[derive(HeapSize)] struct Demo<'a, T: ?Sized> { a: Box, b: u8, c: &'a str, d: String, } ```
## Spans and error reporting The token-based procedural macro API provides great control over where the compiler's error messages are displayed in user code. Consider the error the user sees if one of their field types does not implement `HeapSize`. ```rust #[derive(HeapSize)] struct Broken { ok: String, bad: std::thread::Thread, } ``` By tracking span information all the way through the expansion of a procedural macro as shown in the `heapsize` example, token-based macros in Syn are able to trigger errors that directly pinpoint the source of the problem. ```console error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied --> src/main.rs:7:5 | 7 | bad: std::thread::Thread, | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `std::thread::Thread` ```
## Parsing a custom syntax The [`lazy-static`] example directory shows the implementation of a `functionlike!(...)` procedural macro in which the input tokens are parsed using Syn's parsing API. [`lazy-static`]: examples/lazy-static The example reimplements the popular `lazy_static` crate from crates.io as a procedural macro. ```rust lazy_static! { static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); } ``` The implementation shows how to trigger custom warnings and error messages on the macro input. ```console warning: come on, pick a more creative name --> src/main.rs:10:16 | 10 | static ref FOO: String = "lazy_static".to_owned(); | ^^^ ```
## Testing When testing macros, we often care not just that the macro can be used successfully but also that when the macro is provided with invalid input it produces maximally helpful error messages. Consider using the [`trybuild`] crate to write tests for errors that are emitted by your macro or errors detected by the Rust compiler in the expanded code following misuse of the macro. Such tests help avoid regressions from later refactors that mistakenly make an error no longer trigger or be less helpful than it used to be. [`trybuild`]: https://github.com/dtolnay/trybuild
## Debugging When developing a procedural macro it can be helpful to look at what the generated code looks like. Use `cargo rustc -- -Zunstable-options --pretty=expanded` or the [`cargo expand`] subcommand. [`cargo expand`]: https://github.com/dtolnay/cargo-expand To show the expanded code for some crate that uses your procedural macro, run `cargo expand` from that crate. To show the expanded code for one of your own test cases, run `cargo expand --test the_test_case` where the last argument is the name of the test file without the `.rs` extension. This write-up by Brandon W Maister discusses debugging in more detail: [Debugging Rust's new Custom Derive system][debugging]. [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/
## Optional features Syn puts a lot of functionality behind optional features in order to optimize compile time for the most common use cases. The following features are available. - **`derive`** *(enabled by default)* — Data structures for representing the possible input to a derive macro, including structs and enums and types. - **`full`** — Data structures for representing the syntax tree of all valid Rust source code, including items and expressions. - **`parsing`** *(enabled by default)* — Ability to parse input tokens into a syntax tree node of a chosen type. - **`printing`** *(enabled by default)* — Ability to print a syntax tree node as tokens of Rust source code. - **`visit`** — Trait for traversing a syntax tree. - **`visit-mut`** — Trait for traversing and mutating in place a syntax tree. - **`fold`** — Trait for transforming an owned syntax tree. - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree types. - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree types. - **`proc-macro`** *(enabled by default)* — Runtime dependency on the dynamic library libproc_macro from rustc toolchain.
## Proc macro shim Syn operates on the token representation provided by the [proc-macro2] crate from crates.io rather than using the compiler's built in proc-macro crate directly. This enables code using Syn to execute outside of the context of a procedural macro, such as in unit tests or build.rs, and we avoid needing incompatible ecosystems for proc macros vs non-macro use cases. In general all of your code should be written against proc-macro2 rather than proc-macro. The one exception is in the signatures of procedural macro entry points, which are required by the language to use `proc_macro::TokenStream`. The proc-macro2 crate will automatically detect and use the compiler's data structures when a procedural macro is active. [proc-macro2]: https://docs.rs/proc-macro2/1.0/proc_macro2/
#### License Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. syn/LICENSE-APACHE0000644000175000017500000002277314661133735014311 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS syn/Cargo.toml0000644000175000017500000001100214661133735014274 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.61" name = "syn" version = "2.0.69" authors = ["David Tolnay "] build = false include = [ "/benches/**", "/Cargo.toml", "/LICENSE-APACHE", "/LICENSE-MIT", "/README.md", "/src/**", "/tests/**", ] autobins = false autoexamples = false autotests = false autobenches = false description = "Parser for Rust source code" documentation = "https://docs.rs/syn" readme = "README.md" keywords = [ "macros", "syn", ] categories = [ "development-tools::procedural-macro-helpers", "parser-implementations", ] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/syn" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [package.metadata.playground] features = [ "full", "visit", "visit-mut", "fold", "extra-traits", ] [lib] name = "syn" path = "src/lib.rs" doc-scrape-examples = false [[test]] name = "regression" path = "tests/regression.rs" [[test]] name = "test_asyncness" path = "tests/test_asyncness.rs" [[test]] name = "test_attribute" path = "tests/test_attribute.rs" [[test]] name = "test_derive_input" path = "tests/test_derive_input.rs" [[test]] name = "test_expr" path = "tests/test_expr.rs" [[test]] name = "test_generics" path = "tests/test_generics.rs" [[test]] name = "test_grouping" path = "tests/test_grouping.rs" [[test]] name = "test_ident" path = "tests/test_ident.rs" [[test]] name = "test_item" path = "tests/test_item.rs" [[test]] name = "test_iterators" path = "tests/test_iterators.rs" [[test]] name = "test_lit" path = "tests/test_lit.rs" [[test]] name = "test_meta" path = "tests/test_meta.rs" [[test]] name = "test_parse_buffer" path = "tests/test_parse_buffer.rs" [[test]] name = "test_parse_quote" path = "tests/test_parse_quote.rs" [[test]] name = "test_parse_stream" path = "tests/test_parse_stream.rs" [[test]] name = "test_pat" path = "tests/test_pat.rs" [[test]] name = "test_path" path = "tests/test_path.rs" [[test]] name = "test_precedence" path = "tests/test_precedence.rs" [[test]] name = "test_receiver" path = "tests/test_receiver.rs" [[test]] name = "test_round_trip" path = "tests/test_round_trip.rs" [[test]] name = "test_shebang" path = "tests/test_shebang.rs" [[test]] name = "test_size" path = "tests/test_size.rs" [[test]] name = "test_stmt" path = "tests/test_stmt.rs" [[test]] name = "test_token_trees" path = "tests/test_token_trees.rs" [[test]] name = "test_ty" path = "tests/test_ty.rs" [[test]] name = "test_visibility" path = "tests/test_visibility.rs" [[test]] name = "zzz_stable" path = "tests/zzz_stable.rs" [[bench]] name = "file" path = "benches/file.rs" required-features = [ "full", "parsing", ] [[bench]] name = "rust" path = "benches/rust.rs" harness = false required-features = [ "full", "parsing", ] [dependencies.proc-macro2] version = "1.0.83" default-features = false [dependencies.quote] version = "1.0.35" optional = true default-features = false [dependencies.unicode-ident] version = "1" [dev-dependencies.anyhow] version = "1" [dev-dependencies.automod] version = "1" [dev-dependencies.insta] version = "1" [dev-dependencies.ref-cast] version = "1" [dev-dependencies.rustversion] version = "1" [dev-dependencies.syn-test-suite] version = "0" [dev-dependencies.termcolor] version = "1" [features] clone-impls = [] default = [ "derive", "parsing", "printing", "clone-impls", "proc-macro", ] derive = [] extra-traits = [] fold = [] full = [] parsing = [] printing = ["dep:quote"] proc-macro = [ "proc-macro2/proc-macro", "quote?/proc-macro", ] test = ["syn-test-suite/all-features"] visit = [] visit-mut = [] [target."cfg(not(miri))".dev-dependencies.flate2] version = "1" [target."cfg(not(miri))".dev-dependencies.rayon] version = "1" [target."cfg(not(miri))".dev-dependencies.reqwest] version = "0.12" features = ["blocking"] [target."cfg(not(miri))".dev-dependencies.tar] version = "0.4.16" [target."cfg(not(miri))".dev-dependencies.walkdir] version = "2.3.2" syn/benches/0000775000175000017500000000000014661133735013763 5ustar jamespagejamespagesyn/benches/rust.rs0000644000175000017500000001224714661133735015332 0ustar jamespagejamespage// $ cargo bench --features full,test --bench rust // // Syn only, useful for profiling: // $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full,test --bench rust #![cfg_attr(not(syn_only), feature(rustc_private))] #![recursion_limit = "1024"] #![allow( clippy::arc_with_non_send_sync, clippy::cast_lossless, clippy::let_underscore_untyped, clippy::manual_let_else, clippy::match_like_matches_macro, clippy::uninlined_format_args, clippy::unnecessary_wraps )] #[macro_use] #[path = "../tests/macros/mod.rs"] mod macros; #[allow(dead_code)] #[path = "../tests/repo/mod.rs"] mod repo; use std::fs; use std::path::Path; use std::time::{Duration, Instant}; #[cfg(not(syn_only))] mod tokenstream_parse { use proc_macro2::TokenStream; use std::path::Path; use std::str::FromStr; pub fn bench(_path: &Path, content: &str) -> Result<(), ()> { TokenStream::from_str(content).map(drop).map_err(drop) } } mod syn_parse { use std::path::Path; pub fn bench(_path: &Path, content: &str) -> Result<(), ()> { syn::parse_file(content).map(drop).map_err(drop) } } #[cfg(not(syn_only))] mod librustc_parse { extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_error_messages; extern crate rustc_errors; extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; use crate::repo; use rustc_data_structures::sync::Lrc; use rustc_error_messages::FluentBundle; use rustc_errors::{emitter::Emitter, translation::Translate, DiagCtxt, DiagInner}; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::FileName; use std::path::Path; pub fn bench(path: &Path, content: &str) -> Result<(), ()> { struct SilentEmitter; impl Emitter for SilentEmitter { fn emit_diagnostic(&mut self, _diag: DiagInner) {} fn source_map(&self) -> Option<&Lrc> { None } } impl Translate for SilentEmitter { fn fluent_bundle(&self) -> Option<&Lrc> { None } fn fallback_fluent_bundle(&self) -> &FluentBundle { panic!("silent emitter attempted to translate a diagnostic"); } } let edition = repo::edition(path).parse().unwrap(); rustc_span::create_session_if_not_set_then(edition, |_| { let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); let emitter = Box::new(SilentEmitter); let handler = DiagCtxt::new(emitter); let sess = ParseSess::with_dcx(handler, source_map); let name = FileName::Custom("bench".to_owned()); let mut parser = rustc_parse::new_parser_from_source_str(&sess, name, content.to_owned()).unwrap(); if let Err(diagnostic) = parser.parse_crate_mod() { diagnostic.cancel(); return Err(()); }; Ok(()) }) } } #[cfg(not(syn_only))] mod read_from_disk { use std::path::Path; pub fn bench(_path: &Path, content: &str) -> Result<(), ()> { let _ = content; Ok(()) } } fn exec(mut codepath: impl FnMut(&Path, &str) -> Result<(), ()>) -> Duration { let begin = Instant::now(); let mut success = 0; let mut total = 0; ["tests/rust/compiler", "tests/rust/library"] .iter() .flat_map(|dir| { walkdir::WalkDir::new(dir) .into_iter() .filter_entry(repo::base_dir_filter) }) .for_each(|entry| { let entry = entry.unwrap(); let path = entry.path(); if path.is_dir() { return; } let content = fs::read_to_string(path).unwrap(); let ok = codepath(path, &content).is_ok(); success += ok as usize; total += 1; if !ok { eprintln!("FAIL {}", path.display()); } }); assert_eq!(success, total); begin.elapsed() } fn main() { repo::clone_rust(); macro_rules! testcases { ($($(#[$cfg:meta])* $name:ident,)*) => { [ $( $(#[$cfg])* (stringify!($name), $name::bench as fn(&Path, &str) -> Result<(), ()>), )* ] }; } #[cfg(not(syn_only))] { let mut lines = 0; let mut files = 0; exec(|_path, content| { lines += content.lines().count(); files += 1; Ok(()) }); eprintln!("\n{} lines in {} files", lines, files); } for (name, f) in testcases!( #[cfg(not(syn_only))] read_from_disk, #[cfg(not(syn_only))] tokenstream_parse, syn_parse, #[cfg(not(syn_only))] librustc_parse, ) { eprint!("{:20}", format!("{}:", name)); let elapsed = exec(f); eprintln!( "elapsed={}.{:03}s", elapsed.as_secs(), elapsed.subsec_millis(), ); } eprintln!(); } syn/benches/file.rs0000644000175000017500000000246314661133735015253 0ustar jamespagejamespage// $ cargo bench --features full,test --bench file #![feature(rustc_private, test)] #![recursion_limit = "1024"] #![allow( clippy::items_after_statements, clippy::manual_let_else, clippy::match_like_matches_macro, clippy::missing_panics_doc, clippy::must_use_candidate, clippy::uninlined_format_args )] extern crate test; #[macro_use] #[path = "../tests/macros/mod.rs"] mod macros; #[allow(dead_code)] #[path = "../tests/repo/mod.rs"] mod repo; use proc_macro2::{Span, TokenStream}; use std::fs; use std::str::FromStr; use syn::parse::{ParseStream, Parser}; use test::Bencher; const FILE: &str = "tests/rust/library/core/src/str/mod.rs"; fn get_tokens() -> TokenStream { repo::clone_rust(); let content = fs::read_to_string(FILE).unwrap(); TokenStream::from_str(&content).unwrap() } #[bench] fn baseline(b: &mut Bencher) { let tokens = get_tokens(); b.iter(|| drop(tokens.clone())); } #[bench] fn create_token_buffer(b: &mut Bencher) { let tokens = get_tokens(); fn immediate_fail(_input: ParseStream) -> syn::Result<()> { Err(syn::Error::new(Span::call_site(), "")) } b.iter(|| immediate_fail.parse2(tokens.clone())); } #[bench] fn parse_file(b: &mut Bencher) { let tokens = get_tokens(); b.iter(|| syn::parse2::(tokens.clone())); } syn/tests/0000775000175000017500000000000014661133735013516 5ustar jamespagejamespagesyn/tests/test_item.rs0000644000175000017500000001763614661133735016074 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use quote::quote; use syn::{Item, ItemTrait}; #[test] fn test_macro_variable_attr() { // mimics the token stream corresponding to `$attr fn f() {}` let tokens = TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })), TokenTree::Ident(Ident::new("fn", Span::call_site())), TokenTree::Ident(Ident::new("f", Span::call_site())), TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), ]); snapshot!(tokens as Item, @r###" Item::Fn { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "test", }, ], }, }, ], vis: Visibility::Inherited, sig: Signature { ident: "f", generics: Generics, output: ReturnType::Default, }, block: Block { stmts: [], }, } "###); } #[test] fn test_negative_impl() { // Rustc parses all of the following. #[cfg(any())] impl ! {} let tokens = quote! { impl ! {} }; snapshot!(tokens as Item, @r###" Item::Impl { generics: Generics, self_ty: Type::Never, } "###); #[cfg(any())] #[rustfmt::skip] impl !Trait {} let tokens = quote! { impl !Trait {} }; snapshot!(tokens as Item, @r###" Item::Impl { generics: Generics, self_ty: Type::Verbatim(`! Trait`), } "###); #[cfg(any())] impl !Trait for T {} let tokens = quote! { impl !Trait for T {} }; snapshot!(tokens as Item, @r###" Item::Impl { generics: Generics, trait_: Some(( Some, Path { segments: [ PathSegment { ident: "Trait", }, ], }, )), self_ty: Type::Path { path: Path { segments: [ PathSegment { ident: "T", }, ], }, }, } "###); #[cfg(any())] #[rustfmt::skip] impl !! {} let tokens = quote! { impl !! {} }; snapshot!(tokens as Item, @r###" Item::Impl { generics: Generics, self_ty: Type::Verbatim(`! !`), } "###); } #[test] fn test_macro_variable_impl() { // mimics the token stream corresponding to `impl $trait for $ty {}` let tokens = TokenStream::from_iter([ TokenTree::Ident(Ident::new("impl", Span::call_site())), TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))), TokenTree::Ident(Ident::new("for", Span::call_site())), TokenTree::Group(Group::new(Delimiter::None, quote!(Type))), TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), ]); snapshot!(tokens as Item, @r###" Item::Impl { generics: Generics, trait_: Some(( None, Path { segments: [ PathSegment { ident: "Trait", }, ], }, )), self_ty: Type::Group { elem: Type::Path { path: Path { segments: [ PathSegment { ident: "Type", }, ], }, }, }, } "###); } #[test] fn test_supertraits() { // Rustc parses all of the following. #[rustfmt::skip] let tokens = quote!(trait Trait where {}); snapshot!(tokens as ItemTrait, @r###" ItemTrait { vis: Visibility::Inherited, ident: "Trait", generics: Generics { where_clause: Some(WhereClause), }, } "###); #[rustfmt::skip] let tokens = quote!(trait Trait: where {}); snapshot!(tokens as ItemTrait, @r###" ItemTrait { vis: Visibility::Inherited, ident: "Trait", generics: Generics { where_clause: Some(WhereClause), }, colon_token: Some, } "###); #[rustfmt::skip] let tokens = quote!(trait Trait: Sized where {}); snapshot!(tokens as ItemTrait, @r###" ItemTrait { vis: Visibility::Inherited, ident: "Trait", generics: Generics { where_clause: Some(WhereClause), }, colon_token: Some, supertraits: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Sized", }, ], }, }), ], } "###); #[rustfmt::skip] let tokens = quote!(trait Trait: Sized + where {}); snapshot!(tokens as ItemTrait, @r###" ItemTrait { vis: Visibility::Inherited, ident: "Trait", generics: Generics { where_clause: Some(WhereClause), }, colon_token: Some, supertraits: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Sized", }, ], }, }), Token![+], ], } "###); } #[test] fn test_type_empty_bounds() { #[rustfmt::skip] let tokens = quote! { trait Foo { type Bar: ; } }; snapshot!(tokens as ItemTrait, @r###" ItemTrait { vis: Visibility::Inherited, ident: "Foo", generics: Generics, items: [ TraitItem::Type { ident: "Bar", generics: Generics, colon_token: Some, }, ], } "###); } #[test] fn test_impl_visibility() { let tokens = quote! { pub default unsafe impl union {} }; snapshot!(tokens as Item, @"Item::Verbatim(`pub default unsafe impl union { }`)"); } #[test] fn test_impl_type_parameter_defaults() { #[cfg(any())] impl () {} let tokens = quote! { impl () {} }; snapshot!(tokens as Item, @r###" Item::Impl { generics: Generics { lt_token: Some, params: [ GenericParam::Type(TypeParam { ident: "T", eq_token: Some, default: Some(Type::Tuple), }), ], gt_token: Some, }, self_ty: Type::Tuple, } "###); } #[test] fn test_impl_trait_trailing_plus() { let tokens = quote! { fn f() -> impl Sized + {} }; snapshot!(tokens as Item, @r###" Item::Fn { vis: Visibility::Inherited, sig: Signature { ident: "f", generics: Generics, output: ReturnType::Type( Type::ImplTrait { bounds: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Sized", }, ], }, }), Token![+], ], }, ), }, block: Block { stmts: [], }, } "###); } syn/tests/test_parse_stream.rs0000644000175000017500000001262414661133735017613 0ustar jamespagejamespage#![allow(clippy::items_after_statements, clippy::let_underscore_untyped)] use proc_macro2::{Delimiter, Group, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::quote; use syn::ext::IdentExt as _; use syn::parse::discouraged::AnyDelimiter; use syn::parse::{ParseStream, Parser as _, Result}; use syn::{parenthesized, token, Ident, Lifetime, Token}; #[test] fn test_peek_punct() { let tokens = quote!(+= + =); fn assert(input: ParseStream) -> Result<()> { assert!(input.peek(Token![+])); assert!(input.peek(Token![+=])); let _: Token![+] = input.parse()?; assert!(input.peek(Token![=])); assert!(!input.peek(Token![==])); assert!(!input.peek(Token![+])); let _: Token![=] = input.parse()?; assert!(input.peek(Token![+])); assert!(!input.peek(Token![+=])); let _: Token![+] = input.parse()?; let _: Token![=] = input.parse()?; Ok(()) } assert.parse2(tokens).unwrap(); } #[test] fn test_peek_lifetime() { // 'static ; let tokens = TokenStream::from_iter([ TokenTree::Punct(Punct::new('\'', Spacing::Joint)), TokenTree::Ident(Ident::new("static", Span::call_site())), TokenTree::Punct(Punct::new(';', Spacing::Alone)), ]); fn assert(input: ParseStream) -> Result<()> { assert!(input.peek(Lifetime)); assert!(input.peek2(Token![;])); assert!(!input.peek2(Token![static])); let _: Lifetime = input.parse()?; assert!(input.peek(Token![;])); let _: Token![;] = input.parse()?; Ok(()) } assert.parse2(tokens).unwrap(); } #[test] fn test_peek_not_lifetime() { // ' static let tokens = TokenStream::from_iter([ TokenTree::Punct(Punct::new('\'', Spacing::Alone)), TokenTree::Ident(Ident::new("static", Span::call_site())), ]); fn assert(input: ParseStream) -> Result<()> { assert!(!input.peek(Lifetime)); assert!(input.parse::>()?.is_none()); let _: TokenTree = input.parse()?; assert!(input.peek(Token![static])); let _: Token![static] = input.parse()?; Ok(()) } assert.parse2(tokens).unwrap(); } #[test] fn test_peek_ident() { let tokens = quote!(static var); fn assert(input: ParseStream) -> Result<()> { assert!(!input.peek(Ident)); assert!(input.peek(Ident::peek_any)); assert!(input.peek(Token![static])); let _: Token![static] = input.parse()?; assert!(input.peek(Ident)); assert!(input.peek(Ident::peek_any)); let _: Ident = input.parse()?; Ok(()) } assert.parse2(tokens).unwrap(); } #[test] fn test_peek_groups() { // pub ( :: ) «∅ ! = ∅» static let tokens = TokenStream::from_iter([ TokenTree::Ident(Ident::new("pub", Span::call_site())), TokenTree::Group(Group::new( Delimiter::Parenthesis, TokenStream::from_iter([ TokenTree::Punct(Punct::new(':', Spacing::Joint)), TokenTree::Punct(Punct::new(':', Spacing::Alone)), ]), )), TokenTree::Group(Group::new( Delimiter::None, TokenStream::from_iter([ TokenTree::Punct(Punct::new('!', Spacing::Alone)), TokenTree::Punct(Punct::new('=', Spacing::Alone)), ]), )), TokenTree::Ident(Ident::new("static", Span::call_site())), ]); fn assert(input: ParseStream) -> Result<()> { assert!(input.peek2(token::Paren)); assert!(input.peek3(token::Group)); assert!(input.peek3(Token![!])); let _: Token![pub] = input.parse()?; assert!(input.peek(token::Paren)); assert!(!input.peek(Token![::])); assert!(!input.peek2(Token![::])); assert!(input.peek2(Token![!])); assert!(input.peek2(token::Group)); assert!(input.peek3(Token![=])); assert!(!input.peek3(Token![static])); let content; parenthesized!(content in input); assert!(content.peek(Token![::])); assert!(content.peek2(Token![:])); assert!(!content.peek3(token::Group)); assert!(!content.peek3(Token![!])); assert!(input.peek(token::Group)); assert!(input.peek(Token![!])); let _: Token![::] = content.parse()?; assert!(input.peek(token::Group)); assert!(input.peek(Token![!])); assert!(input.peek2(Token![=])); assert!(input.peek3(Token![static])); assert!(!input.peek2(Token![static])); let implicit = input.fork(); let explicit = input.fork(); let _: Token![!] = implicit.parse()?; assert!(implicit.peek(Token![=])); assert!(implicit.peek2(Token![static])); let _: Token![=] = implicit.parse()?; assert!(implicit.peek(Token![static])); let (delimiter, _span, grouped) = explicit.parse_any_delimiter()?; assert_eq!(delimiter, Delimiter::None); assert!(grouped.peek(Token![!])); assert!(grouped.peek2(Token![=])); assert!(!grouped.peek3(Token![static])); let _: Token![!] = grouped.parse()?; assert!(grouped.peek(Token![=])); assert!(!grouped.peek2(Token![static])); let _: Token![=] = grouped.parse()?; assert!(!grouped.peek(Token![static])); let _: TokenStream = input.parse()?; Ok(()) } assert.parse2(tokens).unwrap(); } syn/tests/test_grouping.rs0000644000175000017500000000274614661133735016764 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree}; use syn::Expr; #[test] fn test_grouping() { let tokens: TokenStream = TokenStream::from_iter([ TokenTree::Literal(Literal::i32_suffixed(1)), TokenTree::Punct(Punct::new('+', Spacing::Alone)), TokenTree::Group(Group::new( Delimiter::None, TokenStream::from_iter([ TokenTree::Literal(Literal::i32_suffixed(2)), TokenTree::Punct(Punct::new('+', Spacing::Alone)), TokenTree::Literal(Literal::i32_suffixed(3)), ]), )), TokenTree::Punct(Punct::new('*', Spacing::Alone)), TokenTree::Literal(Literal::i32_suffixed(4)), ]); assert_eq!(tokens.to_string(), "1i32 + 2i32 + 3i32 * 4i32"); snapshot!(tokens as Expr, @r###" Expr::Binary { left: Expr::Lit { lit: 1i32, }, op: BinOp::Add, right: Expr::Binary { left: Expr::Group { expr: Expr::Binary { left: Expr::Lit { lit: 2i32, }, op: BinOp::Add, right: Expr::Lit { lit: 3i32, }, }, }, op: BinOp::Mul, right: Expr::Lit { lit: 4i32, }, }, } "###); } syn/tests/common/0000775000175000017500000000000014661133735015006 5ustar jamespagejamespagesyn/tests/common/eq.rs0000644000175000017500000007735414661133735015777 0ustar jamespagejamespage#![allow(unused_macro_rules)] extern crate rustc_ast; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_span; extern crate thin_vec; use rustc_ast::ast::AngleBracketedArg; use rustc_ast::ast::AngleBracketedArgs; use rustc_ast::ast::AnonConst; use rustc_ast::ast::Arm; use rustc_ast::ast::AssocItemConstraint; use rustc_ast::ast::AssocItemConstraintKind; use rustc_ast::ast::AssocItemKind; use rustc_ast::ast::AttrArgs; use rustc_ast::ast::AttrArgsEq; use rustc_ast::ast::AttrId; use rustc_ast::ast::AttrItem; use rustc_ast::ast::AttrKind; use rustc_ast::ast::AttrStyle; use rustc_ast::ast::Attribute; use rustc_ast::ast::BareFnTy; use rustc_ast::ast::BinOpKind; use rustc_ast::ast::BindingMode; use rustc_ast::ast::Block; use rustc_ast::ast::BlockCheckMode; use rustc_ast::ast::BorrowKind; use rustc_ast::ast::BoundAsyncness; use rustc_ast::ast::BoundConstness; use rustc_ast::ast::BoundPolarity; use rustc_ast::ast::ByRef; use rustc_ast::ast::CaptureBy; use rustc_ast::ast::Closure; use rustc_ast::ast::ClosureBinder; use rustc_ast::ast::Const; use rustc_ast::ast::ConstItem; use rustc_ast::ast::CoroutineKind; use rustc_ast::ast::Crate; use rustc_ast::ast::Defaultness; use rustc_ast::ast::Delegation; use rustc_ast::ast::DelegationMac; use rustc_ast::ast::DelimArgs; use rustc_ast::ast::EnumDef; use rustc_ast::ast::Expr; use rustc_ast::ast::ExprField; use rustc_ast::ast::ExprKind; use rustc_ast::ast::Extern; use rustc_ast::ast::FieldDef; use rustc_ast::ast::FloatTy; use rustc_ast::ast::Fn; use rustc_ast::ast::FnDecl; use rustc_ast::ast::FnHeader; use rustc_ast::ast::FnRetTy; use rustc_ast::ast::FnSig; use rustc_ast::ast::ForLoopKind; use rustc_ast::ast::ForeignItemKind; use rustc_ast::ast::ForeignMod; use rustc_ast::ast::FormatAlignment; use rustc_ast::ast::FormatArgPosition; use rustc_ast::ast::FormatArgPositionKind; use rustc_ast::ast::FormatArgs; use rustc_ast::ast::FormatArgsPiece; use rustc_ast::ast::FormatArgument; use rustc_ast::ast::FormatArgumentKind; use rustc_ast::ast::FormatArguments; use rustc_ast::ast::FormatCount; use rustc_ast::ast::FormatDebugHex; use rustc_ast::ast::FormatOptions; use rustc_ast::ast::FormatPlaceholder; use rustc_ast::ast::FormatSign; use rustc_ast::ast::FormatTrait; use rustc_ast::ast::GenBlockKind; use rustc_ast::ast::GenericArg; use rustc_ast::ast::GenericArgs; use rustc_ast::ast::GenericBound; use rustc_ast::ast::GenericParam; use rustc_ast::ast::GenericParamKind; use rustc_ast::ast::Generics; use rustc_ast::ast::Impl; use rustc_ast::ast::ImplPolarity; use rustc_ast::ast::Inline; use rustc_ast::ast::InlineAsm; use rustc_ast::ast::InlineAsmOperand; use rustc_ast::ast::InlineAsmOptions; use rustc_ast::ast::InlineAsmRegOrRegClass; use rustc_ast::ast::InlineAsmSym; use rustc_ast::ast::InlineAsmTemplatePiece; use rustc_ast::ast::IntTy; use rustc_ast::ast::IsAuto; use rustc_ast::ast::Item; use rustc_ast::ast::ItemKind; use rustc_ast::ast::Label; use rustc_ast::ast::Lifetime; use rustc_ast::ast::LitFloatType; use rustc_ast::ast::LitIntType; use rustc_ast::ast::LitKind; use rustc_ast::ast::Local; use rustc_ast::ast::LocalKind; use rustc_ast::ast::MacCall; use rustc_ast::ast::MacCallStmt; use rustc_ast::ast::MacStmtStyle; use rustc_ast::ast::MacroDef; use rustc_ast::ast::MatchKind; use rustc_ast::ast::MetaItem; use rustc_ast::ast::MetaItemKind; use rustc_ast::ast::MetaItemLit; use rustc_ast::ast::MethodCall; use rustc_ast::ast::ModKind; use rustc_ast::ast::ModSpans; use rustc_ast::ast::Movability; use rustc_ast::ast::MutTy; use rustc_ast::ast::Mutability; use rustc_ast::ast::NestedMetaItem; use rustc_ast::ast::NodeId; use rustc_ast::ast::NormalAttr; use rustc_ast::ast::Param; use rustc_ast::ast::ParenthesizedArgs; use rustc_ast::ast::Pat; use rustc_ast::ast::PatField; use rustc_ast::ast::PatFieldsRest; use rustc_ast::ast::PatKind; use rustc_ast::ast::Path; use rustc_ast::ast::PathSegment; use rustc_ast::ast::PolyTraitRef; use rustc_ast::ast::PreciseCapturingArg; use rustc_ast::ast::QSelf; use rustc_ast::ast::RangeEnd; use rustc_ast::ast::RangeLimits; use rustc_ast::ast::RangeSyntax; use rustc_ast::ast::Recovered; use rustc_ast::ast::Safety; use rustc_ast::ast::StaticItem; use rustc_ast::ast::Stmt; use rustc_ast::ast::StmtKind; use rustc_ast::ast::StrLit; use rustc_ast::ast::StrStyle; use rustc_ast::ast::StructExpr; use rustc_ast::ast::StructRest; use rustc_ast::ast::Term; use rustc_ast::ast::Trait; use rustc_ast::ast::TraitBoundModifiers; use rustc_ast::ast::TraitObjectSyntax; use rustc_ast::ast::TraitRef; use rustc_ast::ast::Ty; use rustc_ast::ast::TyAlias; use rustc_ast::ast::TyAliasWhereClause; use rustc_ast::ast::TyAliasWhereClauses; use rustc_ast::ast::TyKind; use rustc_ast::ast::UintTy; use rustc_ast::ast::UnOp; use rustc_ast::ast::UnsafeSource; use rustc_ast::ast::UseTree; use rustc_ast::ast::UseTreeKind; use rustc_ast::ast::Variant; use rustc_ast::ast::VariantData; use rustc_ast::ast::Visibility; use rustc_ast::ast::VisibilityKind; use rustc_ast::ast::WhereBoundPredicate; use rustc_ast::ast::WhereClause; use rustc_ast::ast::WhereEqPredicate; use rustc_ast::ast::WherePredicate; use rustc_ast::ast::WhereRegionPredicate; use rustc_ast::ptr::P; use rustc_ast::token::{ self, CommentKind, Delimiter, IdentIsRaw, Lit, Nonterminal, Token, TokenKind, }; use rustc_ast::tokenstream::{ AttrTokenStream, AttrTokenTree, AttributesData, DelimSpacing, DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenTree, }; use rustc_data_structures::packed::Pu128; use rustc_data_structures::sync::Lrc; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::{ErrorGuaranteed, Span, Symbol, SyntaxContext, DUMMY_SP}; use std::collections::HashMap; use std::hash::{BuildHasher, Hash}; use thin_vec::ThinVec; pub trait SpanlessEq { fn eq(&self, other: &Self) -> bool; } impl SpanlessEq for Box { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&**self, &**other) } } impl SpanlessEq for P { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&**self, &**other) } } impl SpanlessEq for Lrc { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&**self, &**other) } } impl SpanlessEq for Option { fn eq(&self, other: &Self) -> bool { match (self, other) { (None, None) => true, (Some(this), Some(other)) => SpanlessEq::eq(this, other), _ => false, } } } impl SpanlessEq for Result { fn eq(&self, other: &Self) -> bool { match (self, other) { (Ok(this), Ok(other)) => SpanlessEq::eq(this, other), (Err(this), Err(other)) => SpanlessEq::eq(this, other), _ => false, } } } impl SpanlessEq for [T] { fn eq(&self, other: &Self) -> bool { self.len() == other.len() && self.iter().zip(other).all(|(a, b)| SpanlessEq::eq(a, b)) } } impl SpanlessEq for Vec { fn eq(&self, other: &Self) -> bool { <[T] as SpanlessEq>::eq(self, other) } } impl SpanlessEq for ThinVec { fn eq(&self, other: &Self) -> bool { self.len() == other.len() && self .iter() .zip(other.iter()) .all(|(a, b)| SpanlessEq::eq(a, b)) } } impl SpanlessEq for HashMap { fn eq(&self, other: &Self) -> bool { self.len() == other.len() && self.iter().all(|(key, this_v)| { other .get(key) .map_or(false, |other_v| SpanlessEq::eq(this_v, other_v)) }) } } impl SpanlessEq for Spanned { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&self.node, &other.node) } } impl SpanlessEq for (A, B) { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&self.0, &other.0) && SpanlessEq::eq(&self.1, &other.1) } } impl SpanlessEq for (A, B, C) { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(&self.0, &other.0) && SpanlessEq::eq(&self.1, &other.1) && SpanlessEq::eq(&self.2, &other.2) } } macro_rules! spanless_eq_true { ($name:ty) => { impl SpanlessEq for $name { fn eq(&self, _other: &Self) -> bool { true } } }; } spanless_eq_true!(Span); spanless_eq_true!(DelimSpan); spanless_eq_true!(AttrId); spanless_eq_true!(NodeId); spanless_eq_true!(SyntaxContext); spanless_eq_true!(Spacing); macro_rules! spanless_eq_partial_eq { ($name:ty) => { impl SpanlessEq for $name { fn eq(&self, other: &Self) -> bool { PartialEq::eq(self, other) } } }; } spanless_eq_partial_eq!(bool); spanless_eq_partial_eq!(u8); spanless_eq_partial_eq!(u16); spanless_eq_partial_eq!(u32); spanless_eq_partial_eq!(u128); spanless_eq_partial_eq!(usize); spanless_eq_partial_eq!(char); spanless_eq_partial_eq!(String); spanless_eq_partial_eq!(Pu128); spanless_eq_partial_eq!(Symbol); spanless_eq_partial_eq!(CommentKind); spanless_eq_partial_eq!(Delimiter); spanless_eq_partial_eq!(InlineAsmOptions); spanless_eq_partial_eq!(token::LitKind); spanless_eq_partial_eq!(ErrorGuaranteed); macro_rules! spanless_eq_struct { { $($name:ident)::+ $(<$param:ident>)? $([$field:tt $this:ident $other:ident])* $(![$ignore:tt])*; } => { impl $(<$param: SpanlessEq>)* SpanlessEq for $($name)::+ $(<$param>)* { fn eq(&self, other: &Self) -> bool { let $($name)::+ { $($field: $this,)* $($ignore: _,)* } = self; let $($name)::+ { $($field: $other,)* $($ignore: _,)* } = other; true $(&& SpanlessEq::eq($this, $other))* } } }; { $($name:ident)::+ $(<$param:ident>)? $([$field:tt $this:ident $other:ident])* $(![$ignore:tt])*; !$next:tt $($rest:tt)* } => { spanless_eq_struct! { $($name)::+ $(<$param>)* $([$field $this $other])* $(![$ignore])* ![$next]; $($rest)* } }; { $($name:ident)::+ $(<$param:ident>)? $([$field:tt $this:ident $other:ident])* $(![$ignore:tt])*; $next:tt $($rest:tt)* } => { spanless_eq_struct! { $($name)::+ $(<$param>)* $([$field $this $other])* [$next this other] $(![$ignore])*; $($rest)* } }; } macro_rules! spanless_eq_enum { { $($name:ident)::+; $([$($variant:ident)::+; $([$field:tt $this:ident $other:ident])* $(![$ignore:tt])*])* } => { impl SpanlessEq for $($name)::+ { fn eq(&self, other: &Self) -> bool { match self { $( $($variant)::+ { .. } => {} )* } #[allow(unreachable_patterns)] match (self, other) { $( ( $($variant)::+ { $($field: $this,)* $($ignore: _,)* }, $($variant)::+ { $($field: $other,)* $($ignore: _,)* }, ) => { true $(&& SpanlessEq::eq($this, $other))* } )* _ => false, } } } }; { $($name:ident)::+; $([$($variant:ident)::+; $($fields:tt)*])* $next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] (!$i:tt $($field:tt)*) $($rest:tt)* } => { spanless_eq_enum! { $($name)::+; $([$($variant)::+; $($fields)*])* $next [$([$($named)*])* $(![$ignore])* ![$i]] ($($field)*) $($rest)* } }; { $($name:ident)::+; $([$($variant:ident)::+; $($fields:tt)*])* $next:ident [$([$($named:tt)*])* $(![$ignore:tt])*] ($i:tt $($field:tt)*) $($rest:tt)* } => { spanless_eq_enum! { $($name)::+; $([$($variant)::+; $($fields)*])* $next [$([$($named)*])* [$i this other] $(![$ignore])*] ($($field)*) $($rest)* } }; { $($name:ident)::+; $([$($variant:ident)::+; $($fields:tt)*])* $next:ident [$($named:tt)*] () $($rest:tt)* } => { spanless_eq_enum! { $($name)::+; $([$($variant)::+; $($fields)*])* [$($name)::+::$next; $($named)*] $($rest)* } }; { $($name:ident)::+; $([$($variant:ident)::+; $($fields:tt)*])* $next:ident ($($field:tt)*) $($rest:tt)* } => { spanless_eq_enum! { $($name)::+; $([$($variant)::+; $($fields)*])* $next [] ($($field)*) $($rest)* } }; { $($name:ident)::+; $([$($variant:ident)::+; $($fields:tt)*])* $next:ident $($rest:tt)* } => { spanless_eq_enum! { $($name)::+; $([$($variant)::+; $($fields)*])* [$($name)::+::$next;] $($rest)* } }; } spanless_eq_struct!(AngleBracketedArgs; span args); spanless_eq_struct!(AnonConst; id value); spanless_eq_struct!(Arm; attrs pat guard body span id is_placeholder); spanless_eq_struct!(AssocItemConstraint; id ident gen_args kind span); spanless_eq_struct!(AttrItem; unsafety path args tokens); spanless_eq_struct!(AttrTokenStream; 0); spanless_eq_struct!(Attribute; kind id style span); spanless_eq_struct!(AttributesData; attrs tokens); spanless_eq_struct!(BareFnTy; safety ext generic_params decl decl_span); spanless_eq_struct!(BindingMode; 0 1); spanless_eq_struct!(Block; stmts id rules span tokens could_be_bare_literal); spanless_eq_struct!(Closure; binder capture_clause constness coroutine_kind movability fn_decl body !fn_decl_span !fn_arg_span); spanless_eq_struct!(ConstItem; defaultness generics ty expr); spanless_eq_struct!(Crate; attrs items spans id is_placeholder); spanless_eq_struct!(Delegation; id qself path rename body from_glob); spanless_eq_struct!(DelegationMac; qself prefix suffixes body); spanless_eq_struct!(DelimArgs; dspan delim tokens); spanless_eq_struct!(DelimSpacing; open close); spanless_eq_struct!(EnumDef; variants); spanless_eq_struct!(Expr; id kind span attrs !tokens); spanless_eq_struct!(ExprField; attrs id span ident expr is_shorthand is_placeholder); spanless_eq_struct!(FieldDef; attrs id span vis ident ty is_placeholder); spanless_eq_struct!(Fn; defaultness generics sig body); spanless_eq_struct!(FnDecl; inputs output); spanless_eq_struct!(FnHeader; constness coroutine_kind safety ext); spanless_eq_struct!(FnSig; header decl span); spanless_eq_struct!(ForeignMod; safety abi items); spanless_eq_struct!(FormatArgPosition; index kind span); spanless_eq_struct!(FormatArgs; span template arguments); spanless_eq_struct!(FormatArgument; kind expr); spanless_eq_struct!(FormatOptions; width precision alignment fill sign alternate zero_pad debug_hex); spanless_eq_struct!(FormatPlaceholder; argument span format_trait format_options); spanless_eq_struct!(GenericParam; id ident attrs bounds is_placeholder kind !colon_span); spanless_eq_struct!(Generics; params where_clause span); spanless_eq_struct!(Impl; defaultness safety generics constness polarity of_trait self_ty items); spanless_eq_struct!(InlineAsm; template template_strs operands clobber_abis options line_spans); spanless_eq_struct!(InlineAsmSym; id qself path); spanless_eq_struct!(Item; attrs id span vis ident kind !tokens); spanless_eq_struct!(Label; ident); spanless_eq_struct!(Lifetime; id ident); spanless_eq_struct!(Lit; kind symbol suffix); spanless_eq_struct!(Local; id pat ty kind span colon_sp attrs !tokens); spanless_eq_struct!(MacCall; path args); spanless_eq_struct!(MacCallStmt; mac style attrs tokens); spanless_eq_struct!(MacroDef; body macro_rules); spanless_eq_struct!(MetaItem; unsafety path kind span); spanless_eq_struct!(MetaItemLit; symbol suffix kind span); spanless_eq_struct!(MethodCall; seg receiver args !span); spanless_eq_struct!(ModSpans; !inner_span !inject_use_span); spanless_eq_struct!(MutTy; ty mutbl); spanless_eq_struct!(NormalAttr; item tokens); spanless_eq_struct!(ParenthesizedArgs; span inputs inputs_span output); spanless_eq_struct!(Pat; id kind span tokens); spanless_eq_struct!(PatField; ident pat is_shorthand attrs id span is_placeholder); spanless_eq_struct!(Path; span segments tokens); spanless_eq_struct!(PathSegment; ident id args); spanless_eq_struct!(PolyTraitRef; bound_generic_params trait_ref span); spanless_eq_struct!(QSelf; ty path_span position); spanless_eq_struct!(StaticItem; ty safety mutability expr); spanless_eq_struct!(Stmt; id kind span); spanless_eq_struct!(StrLit; symbol suffix symbol_unescaped style span); spanless_eq_struct!(StructExpr; qself path fields rest); spanless_eq_struct!(Token; kind span); spanless_eq_struct!(Trait; safety is_auto generics bounds items); spanless_eq_struct!(TraitBoundModifiers; constness asyncness polarity); spanless_eq_struct!(TraitRef; path ref_id); spanless_eq_struct!(Ty; id kind span tokens); spanless_eq_struct!(TyAlias; defaultness generics where_clauses bounds ty); spanless_eq_struct!(TyAliasWhereClause; !has_where_token span); spanless_eq_struct!(TyAliasWhereClauses; before after !split); spanless_eq_struct!(UseTree; prefix kind span); spanless_eq_struct!(Variant; attrs id span !vis ident data disr_expr is_placeholder); spanless_eq_struct!(Visibility; kind span tokens); spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds); spanless_eq_struct!(WhereClause; has_where_token predicates span); spanless_eq_struct!(WhereEqPredicate; span lhs_ty rhs_ty); spanless_eq_struct!(WhereRegionPredicate; span lifetime bounds); spanless_eq_enum!(AngleBracketedArg; Arg(0) Constraint(0)); spanless_eq_enum!(AssocItemConstraintKind; Equality(term) Bound(bounds)); spanless_eq_enum!(AssocItemKind; Const(0) Fn(0) Type(0) MacCall(0) Delegation(0) DelegationMac(0)); spanless_eq_enum!(AttrArgs; Empty Delimited(0) Eq(0 1)); spanless_eq_enum!(AttrArgsEq; Ast(0) Hir(0)); spanless_eq_enum!(AttrStyle; Outer Inner); spanless_eq_enum!(AttrTokenTree; Token(0 1) Delimited(0 1 2 3) Attributes(0)); spanless_eq_enum!(BinOpKind; Add Sub Mul Div Rem And Or BitXor BitAnd BitOr Shl Shr Eq Lt Le Ne Ge Gt); spanless_eq_enum!(BlockCheckMode; Default Unsafe(0)); spanless_eq_enum!(BorrowKind; Ref Raw); spanless_eq_enum!(BoundAsyncness; Normal Async(0)); spanless_eq_enum!(BoundConstness; Never Always(0) Maybe(0)); spanless_eq_enum!(BoundPolarity; Positive Negative(0) Maybe(0)); spanless_eq_enum!(ByRef; Yes(0) No); spanless_eq_enum!(CaptureBy; Value(move_kw) Ref); spanless_eq_enum!(ClosureBinder; NotPresent For(span generic_params)); spanless_eq_enum!(Const; Yes(0) No); spanless_eq_enum!(Defaultness; Default(0) Final); spanless_eq_enum!(Extern; None Implicit(0) Explicit(0 1)); spanless_eq_enum!(FloatTy; F16 F32 F64 F128); spanless_eq_enum!(FnRetTy; Default(0) Ty(0)); spanless_eq_enum!(ForLoopKind; For ForAwait); spanless_eq_enum!(ForeignItemKind; Static(0) Fn(0) TyAlias(0) MacCall(0)); spanless_eq_enum!(FormatAlignment; Left Right Center); spanless_eq_enum!(FormatArgPositionKind; Implicit Number Named); spanless_eq_enum!(FormatArgsPiece; Literal(0) Placeholder(0)); spanless_eq_enum!(FormatArgumentKind; Normal Named(0) Captured(0)); spanless_eq_enum!(FormatCount; Literal(0) Argument(0)); spanless_eq_enum!(FormatDebugHex; Lower Upper); spanless_eq_enum!(FormatSign; Plus Minus); spanless_eq_enum!(FormatTrait; Display Debug LowerExp UpperExp Octal Pointer Binary LowerHex UpperHex); spanless_eq_enum!(GenBlockKind; Async Gen AsyncGen); spanless_eq_enum!(GenericArg; Lifetime(0) Type(0) Const(0)); spanless_eq_enum!(GenericArgs; AngleBracketed(0) Parenthesized(0) ParenthesizedElided(0)); spanless_eq_enum!(GenericBound; Trait(0 1) Outlives(0) Use(0 1)); spanless_eq_enum!(GenericParamKind; Lifetime Type(default) Const(ty kw_span default)); spanless_eq_enum!(ImplPolarity; Positive Negative(0)); spanless_eq_enum!(Inline; Yes No); spanless_eq_enum!(InlineAsmRegOrRegClass; Reg(0) RegClass(0)); spanless_eq_enum!(InlineAsmTemplatePiece; String(0) Placeholder(operand_idx modifier span)); spanless_eq_enum!(IntTy; Isize I8 I16 I32 I64 I128); spanless_eq_enum!(IsAuto; Yes No); spanless_eq_enum!(LitFloatType; Suffixed(0) Unsuffixed); spanless_eq_enum!(LitIntType; Signed(0) Unsigned(0) Unsuffixed); spanless_eq_enum!(LocalKind; Decl Init(0) InitElse(0 1)); spanless_eq_enum!(MacStmtStyle; Semicolon Braces NoBraces); spanless_eq_enum!(MatchKind; Prefix Postfix); spanless_eq_enum!(MetaItemKind; Word List(0) NameValue(0)); spanless_eq_enum!(ModKind; Loaded(0 1 2) Unloaded); spanless_eq_enum!(Movability; Static Movable); spanless_eq_enum!(Mutability; Mut Not); spanless_eq_enum!(NestedMetaItem; MetaItem(0) Lit(0)); spanless_eq_enum!(PatFieldsRest; Rest None); spanless_eq_enum!(PreciseCapturingArg; Lifetime(0) Arg(0 1)); spanless_eq_enum!(RangeEnd; Included(0) Excluded); spanless_eq_enum!(RangeLimits; HalfOpen Closed); spanless_eq_enum!(Recovered; No Yes(0)); spanless_eq_enum!(Safety; Unsafe(0) Safe(0) Default); spanless_eq_enum!(StmtKind; Let(0) Item(0) Expr(0) Semi(0) Empty MacCall(0)); spanless_eq_enum!(StrStyle; Cooked Raw(0)); spanless_eq_enum!(StructRest; Base(0) Rest(0) None); spanless_eq_enum!(Term; Ty(0) Const(0)); spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2 3)); spanless_eq_enum!(TraitObjectSyntax; Dyn DynStar None); spanless_eq_enum!(UintTy; Usize U8 U16 U32 U64 U128); spanless_eq_enum!(UnOp; Deref Not Neg); spanless_eq_enum!(UnsafeSource; CompilerGenerated UserProvided); spanless_eq_enum!(UseTreeKind; Simple(0) Nested(items span) Glob); spanless_eq_enum!(VariantData; Struct(fields recovered) Tuple(0 1) Unit(0)); spanless_eq_enum!(VisibilityKind; Public Restricted(path id shorthand) Inherited); spanless_eq_enum!(WherePredicate; BoundPredicate(0) RegionPredicate(0) EqPredicate(0)); spanless_eq_enum!(CoroutineKind; Async(span closure_id return_impl_trait_id) Gen(span closure_id return_impl_trait_id) AsyncGen(span closure_id return_impl_trait_id)); spanless_eq_enum!(ExprKind; Array(0) ConstBlock(0) Call(0 1) MethodCall(0) Tup(0) Binary(0 1 2) Unary(0 1) Lit(0) Cast(0 1) Type(0 1) Let(0 1 2 3) If(0 1 2) While(0 1 2) ForLoop(pat iter body label kind) Loop(0 1 2) Match(0 1 2) Closure(0) Block(0 1) Gen(0 1 2 3) Await(0 1) TryBlock(0) Assign(0 1 2) AssignOp(0 1 2) Field(0 1) Index(0 1 2) Underscore Range(0 1 2) Path(0 1) AddrOf(0 1 2) Break(0 1) Continue(0) Ret(0) InlineAsm(0) OffsetOf(0 1) MacCall(0) Struct(0) Repeat(0 1) Paren(0) Try(0) Yield(0) Yeet(0) Become(0) IncludedBytes(0) FormatArgs(0) Err(0) Dummy); spanless_eq_enum!(InlineAsmOperand; In(reg expr) Out(reg late expr) InOut(reg late expr) SplitInOut(reg late in_expr out_expr) Const(anon_const) Sym(sym) Label(block)); spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0) Const(0) Fn(0) Mod(0 1) ForeignMod(0) GlobalAsm(0) TyAlias(0) Enum(0 1) Struct(0 1) Union(0 1) Trait(0) TraitAlias(0 1) Impl(0) MacCall(0) MacroDef(0) Delegation(0) DelegationMac(0)); spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0 1) CStr(0 1) Byte(0) Char(0) Int(0 1) Float(0 1) Bool(0) Err(0)); spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2 3) TupleStruct(0 1 2) Or(0) Path(0 1) Tuple(0) Box(0) Deref(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0) Rest Never Paren(0) MacCall(0) Err(0)); spanless_eq_enum!(TyKind; Slice(0) Array(0 1) Ptr(0) Ref(0 1) BareFn(0) Never Tup(0) AnonStruct(0 1) AnonUnion(0 1) Path(0 1) TraitObject(0 1) ImplTrait(0 1) Paren(0) Typeof(0) Infer ImplicitSelf MacCall(0) CVarArgs Pat(0 1) Dummy Err(0)); impl SpanlessEq for Ident { fn eq(&self, other: &Self) -> bool { self.as_str() == other.as_str() } } impl SpanlessEq for RangeSyntax { fn eq(&self, _other: &Self) -> bool { match self { RangeSyntax::DotDotDot | RangeSyntax::DotDotEq => true, } } } impl SpanlessEq for Param { fn eq(&self, other: &Self) -> bool { let Param { attrs, ty, pat, id, span: _, is_placeholder, } = self; let Param { attrs: attrs2, ty: ty2, pat: pat2, id: id2, span: _, is_placeholder: is_placeholder2, } = other; SpanlessEq::eq(id, id2) && SpanlessEq::eq(is_placeholder, is_placeholder2) && (matches!(ty.kind, TyKind::Err(_)) || matches!(ty2.kind, TyKind::Err(_)) || SpanlessEq::eq(attrs, attrs2) && SpanlessEq::eq(ty, ty2) && SpanlessEq::eq(pat, pat2)) } } impl SpanlessEq for TokenKind { fn eq(&self, other: &Self) -> bool { match (self, other) { (TokenKind::Literal(this), TokenKind::Literal(other)) => SpanlessEq::eq(this, other), (TokenKind::DotDotEq | TokenKind::DotDotDot, _) => match other { TokenKind::DotDotEq | TokenKind::DotDotDot => true, _ => false, }, (TokenKind::Interpolated(this), TokenKind::Interpolated(other)) => { let this = this.as_ref(); let other = other.as_ref(); match (this, other) { (Nonterminal::NtExpr(this), Nonterminal::NtExpr(other)) => { SpanlessEq::eq(this, other) } _ => this == other, } } _ => self == other, } } } impl SpanlessEq for TokenStream { fn eq(&self, other: &Self) -> bool { let mut this_trees = self.trees(); let mut other_trees = other.trees(); loop { let this = match this_trees.next() { None => return other_trees.next().is_none(), Some(tree) => tree, }; let other = match other_trees.next() { None => return false, Some(tree) => tree, }; if SpanlessEq::eq(this, other) { continue; } if let (TokenTree::Token(this, _), TokenTree::Token(other, _)) = (this, other) { if match (&this.kind, &other.kind) { (TokenKind::Literal(this), TokenKind::Literal(other)) => { SpanlessEq::eq(this, other) } (TokenKind::DocComment(_kind, style, symbol), TokenKind::Pound) => { doc_comment(*style, *symbol, &mut other_trees) } (TokenKind::Pound, TokenKind::DocComment(_kind, style, symbol)) => { doc_comment(*style, *symbol, &mut this_trees) } _ => false, } { continue; } } return false; } } } fn doc_comment<'a>( style: AttrStyle, unescaped: Symbol, trees: &mut impl Iterator, ) -> bool { if match style { AttrStyle::Outer => false, AttrStyle::Inner => true, } { match trees.next() { Some(TokenTree::Token( Token { kind: TokenKind::Not, span: _, }, _spacing, )) => {} _ => return false, } } let stream = match trees.next() { Some(TokenTree::Delimited(_span, _spacing, Delimiter::Bracket, stream)) => stream, _ => return false, }; let mut trees = stream.trees(); match trees.next() { Some(TokenTree::Token( Token { kind: TokenKind::Ident(symbol, IdentIsRaw::No), span: _, }, _spacing, )) if *symbol == sym::doc => {} _ => return false, } match trees.next() { Some(TokenTree::Token( Token { kind: TokenKind::Eq, span: _, }, _spacing, )) => {} _ => return false, } match trees.next() { Some(TokenTree::Token(token, _spacing)) => { is_escaped_literal_token(token, unescaped) && trees.next().is_none() } _ => false, } } fn is_escaped_literal_token(token: &Token, unescaped: Symbol) -> bool { match token { Token { kind: TokenKind::Literal(lit), span: _, } => match MetaItemLit::from_token_lit(*lit, DUMMY_SP) { Ok(lit) => is_escaped_literal_meta_item_lit(&lit, unescaped), Err(_) => false, }, Token { kind: TokenKind::Interpolated(nonterminal), span: _, } => match nonterminal.as_ref() { Nonterminal::NtExpr(expr) => match &expr.kind { ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped), _ => false, }, _ => false, }, _ => false, } } fn is_escaped_literal_attr_args(value: &AttrArgsEq, unescaped: Symbol) -> bool { match value { AttrArgsEq::Ast(expr) => match &expr.kind { ExprKind::Lit(lit) => is_escaped_lit(lit, unescaped), _ => false, }, AttrArgsEq::Hir(lit) => is_escaped_literal_meta_item_lit(lit, unescaped), } } fn is_escaped_literal_meta_item_lit(lit: &MetaItemLit, unescaped: Symbol) -> bool { match lit { MetaItemLit { symbol: _, suffix: None, kind, span: _, } => is_escaped_lit_kind(kind, unescaped), _ => false, } } fn is_escaped_lit(lit: &Lit, unescaped: Symbol) -> bool { match lit { Lit { kind: token::LitKind::Str, symbol: _, suffix: None, } => match LitKind::from_token_lit(*lit) { Ok(lit_kind) => is_escaped_lit_kind(&lit_kind, unescaped), _ => false, }, _ => false, } } fn is_escaped_lit_kind(kind: &LitKind, unescaped: Symbol) -> bool { match kind { LitKind::Str(symbol, StrStyle::Cooked) => { symbol.as_str().replace('\r', "") == unescaped.as_str().replace('\r', "") } _ => false, } } impl SpanlessEq for LazyAttrTokenStream { fn eq(&self, other: &Self) -> bool { let this = self.to_attr_token_stream(); let other = other.to_attr_token_stream(); SpanlessEq::eq(&this, &other) } } impl SpanlessEq for AttrKind { fn eq(&self, other: &Self) -> bool { match (self, other) { (AttrKind::Normal(normal), AttrKind::Normal(normal2)) => { SpanlessEq::eq(normal, normal2) } (AttrKind::DocComment(kind, symbol), AttrKind::DocComment(kind2, symbol2)) => { SpanlessEq::eq(kind, kind2) && SpanlessEq::eq(symbol, symbol2) } (AttrKind::DocComment(kind, unescaped), AttrKind::Normal(normal2)) => { match kind { CommentKind::Line | CommentKind::Block => {} } let path = Path::from_ident(Ident::with_dummy_span(sym::doc)); SpanlessEq::eq(&path, &normal2.item.path) && match &normal2.item.args { AttrArgs::Empty | AttrArgs::Delimited(_) => false, AttrArgs::Eq(_span, value) => { is_escaped_literal_attr_args(value, *unescaped) } } } (AttrKind::Normal(_), AttrKind::DocComment(..)) => SpanlessEq::eq(other, self), } } } impl SpanlessEq for FormatArguments { fn eq(&self, other: &Self) -> bool { SpanlessEq::eq(self.all_args(), other.all_args()) } } syn/tests/common/parse.rs0000644000175000017500000000242014661133735016462 0ustar jamespagejamespageextern crate rustc_ast; extern crate rustc_driver; extern crate rustc_expand; extern crate rustc_parse as parse; extern crate rustc_session; extern crate rustc_span; use rustc_ast::ast; use rustc_ast::ptr::P; use rustc_session::parse::ParseSess; use rustc_span::FileName; use std::panic; pub fn librustc_expr(input: &str) -> Option> { match panic::catch_unwind(|| { let locale_resources = rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(); let sess = ParseSess::new(locale_resources); let name = FileName::Custom("test_precedence".to_string()); let mut parser = parse::new_parser_from_source_str(&sess, name, input.to_string()).unwrap(); let presult = parser.parse_expr(); match presult { Ok(expr) => Some(expr), Err(diagnostic) => { diagnostic.emit(); None } } }) { Ok(Some(e)) => Some(e), Ok(None) => None, Err(_) => { errorf!("librustc panicked\n"); None } } } pub fn syn_expr(input: &str) -> Option { match syn::parse_str(input) { Ok(e) => Some(e), Err(msg) => { errorf!("syn failed to parse\n{:?}\n", msg); None } } } syn/tests/common/mod.rs0000644000175000017500000000143214661133735016131 0ustar jamespagejamespage#![allow(dead_code)] #![allow(clippy::module_name_repetitions, clippy::shadow_unrelated)] use rayon::ThreadPoolBuilder; use std::env; pub mod eq; pub mod parse; /// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it. pub fn abort_after() -> usize { match env::var("ABORT_AFTER_FAILURE") { Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"), Err(_) => usize::MAX, } } /// Configure Rayon threadpool. pub fn rayon_init() { let stack_size = match env::var("RUST_MIN_STACK") { Ok(s) => s.parse().expect("failed to parse RUST_MIN_STACK"), Err(_) => 1024 * 1024 * if cfg!(debug_assertions) { 40 } else { 20 }, }; ThreadPoolBuilder::new() .stack_size(stack_size) .build_global() .unwrap(); } syn/tests/regression.rs0000644000175000017500000000020414661133735016236 0ustar jamespagejamespage#![allow(clippy::let_underscore_untyped, clippy::uninlined_format_args)] mod regression { automod::dir!("tests/regression"); } syn/tests/test_round_trip.rs0000644000175000017500000002061014661133735017305 0ustar jamespagejamespage#![cfg(not(syn_disable_nightly_tests))] #![cfg(not(miri))] #![recursion_limit = "1024"] #![feature(rustc_private)] #![allow( clippy::blocks_in_conditions, clippy::manual_assert, clippy::manual_let_else, clippy::match_like_matches_macro, clippy::uninlined_format_args )] extern crate rustc_ast; extern crate rustc_ast_pretty; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_error_messages; extern crate rustc_errors; extern crate rustc_expand; extern crate rustc_parse as parse; extern crate rustc_session; extern crate rustc_span; use crate::common::eq::SpanlessEq; use quote::quote; use rustc_ast::ast::{ AngleBracketedArg, AngleBracketedArgs, Crate, GenericArg, GenericParamKind, Generics, WhereClause, }; use rustc_ast::mut_visit::MutVisitor; use rustc_ast_pretty::pprust; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_error_messages::{DiagMessage, LazyFallbackBundle}; use rustc_errors::{translation, Diag, PResult}; use rustc_session::parse::ParseSess; use rustc_span::FileName; use std::borrow::Cow; use std::fs; use std::panic; use std::path::Path; use std::process; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Instant; #[macro_use] mod macros; mod common; mod repo; #[test] fn test_round_trip() { common::rayon_init(); repo::clone_rust(); let abort_after = common::abort_after(); if abort_after == 0 { panic!("skipping all round_trip tests"); } let failed = AtomicUsize::new(0); repo::for_each_rust_file(|path| test(path, &failed, abort_after)); let failed = failed.load(Ordering::Relaxed); if failed > 0 { panic!("{} failures", failed); } } fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) { let failed = || { let prev_failed = failed.fetch_add(1, Ordering::Relaxed); if prev_failed + 1 >= abort_after { process::exit(1); } }; let content = fs::read_to_string(path).unwrap(); let (back, elapsed) = match panic::catch_unwind(|| { let start = Instant::now(); let result = syn::parse_file(&content); let elapsed = start.elapsed(); result.map(|krate| (quote!(#krate).to_string(), elapsed)) }) { Err(_) => { errorf!("=== {}: syn panic\n", path.display()); failed(); return; } Ok(Err(msg)) => { errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg); failed(); return; } Ok(Ok(result)) => result, }; let edition = repo::edition(path).parse().unwrap(); rustc_span::create_session_if_not_set_then(edition, |_| { let equal = match panic::catch_unwind(|| { let locale_resources = rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(); let sess = ParseSess::new(locale_resources); let before = match librustc_parse(content, &sess) { Ok(before) => before, Err(diagnostic) => { errorf!( "=== {}: ignore - librustc failed to parse original content: {}\n", path.display(), translate_message(&diagnostic), ); diagnostic.cancel(); return Err(true); } }; let after = match librustc_parse(back, &sess) { Ok(after) => after, Err(diagnostic) => { errorf!("=== {}: librustc failed to parse", path.display()); diagnostic.emit(); return Err(false); } }; Ok((before, after)) }) { Err(_) => { errorf!("=== {}: ignoring librustc panic\n", path.display()); true } Ok(Err(equal)) => equal, Ok(Ok((mut before, mut after))) => { normalize(&mut before); normalize(&mut after); if SpanlessEq::eq(&before, &after) { errorf!( "=== {}: pass in {}ms\n", path.display(), elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_nanos()) / 1_000_000 ); true } else { errorf!( "=== {}: FAIL\n{}\n!=\n{}\n", path.display(), pprust::crate_to_string_for_macros(&before), pprust::crate_to_string_for_macros(&after), ); false } } }; if !equal { failed(); } }); } fn librustc_parse(content: String, sess: &ParseSess) -> PResult { static COUNTER: AtomicUsize = AtomicUsize::new(0); let counter = COUNTER.fetch_add(1, Ordering::Relaxed); let name = FileName::Custom(format!("test_round_trip{}", counter)); let mut parser = parse::new_parser_from_source_str(sess, name, content).unwrap(); parser.parse_crate_mod() } fn translate_message(diagnostic: &Diag) -> Cow<'static, str> { thread_local! { static FLUENT_BUNDLE: LazyFallbackBundle = { let locale_resources = rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(); let with_directionality_markers = false; rustc_error_messages::fallback_fluent_bundle(locale_resources, with_directionality_markers) }; } let message = &diagnostic.messages[0].0; let args = translation::to_fluent_args(diagnostic.args.iter()); let (identifier, attr) = match message { DiagMessage::Str(msg) | DiagMessage::Translated(msg) => return msg.clone(), DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr), }; FLUENT_BUNDLE.with(|fluent_bundle| { let message = fluent_bundle .get_message(identifier) .expect("missing diagnostic in fluent bundle"); let value = match attr { Some(attr) => message .get_attribute(attr) .expect("missing attribute in fluent message") .value(), None => message.value().expect("missing value in fluent message"), }; let mut err = Vec::new(); let translated = fluent_bundle.format_pattern(value, Some(&args), &mut err); assert!(err.is_empty()); Cow::Owned(translated.into_owned()) }) } fn normalize(krate: &mut Crate) { struct NormalizeVisitor; impl MutVisitor for NormalizeVisitor { fn visit_angle_bracketed_parameter_data(&mut self, e: &mut AngleBracketedArgs) { #[derive(Ord, PartialOrd, Eq, PartialEq)] enum Group { Lifetimes, TypesAndConsts, Constraints, } e.args.sort_by_key(|arg| match arg { AngleBracketedArg::Arg(arg) => match arg { GenericArg::Lifetime(_) => Group::Lifetimes, GenericArg::Type(_) | GenericArg::Const(_) => Group::TypesAndConsts, }, AngleBracketedArg::Constraint(_) => Group::Constraints, }); for arg in &mut e.args { match arg { AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg), AngleBracketedArg::Constraint(constraint) => { self.visit_assoc_item_constraint(constraint); } } } } fn visit_generics(&mut self, e: &mut Generics) { #[derive(Ord, PartialOrd, Eq, PartialEq)] enum Group { Lifetimes, TypesAndConsts, } e.params.sort_by_key(|param| match param.kind { GenericParamKind::Lifetime => Group::Lifetimes, GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { Group::TypesAndConsts } }); e.params .flat_map_in_place(|param| self.flat_map_generic_param(param)); self.visit_where_clause(&mut e.where_clause); } fn visit_where_clause(&mut self, e: &mut WhereClause) { if e.predicates.is_empty() { e.has_where_token = false; } } } NormalizeVisitor.visit_crate(krate); } syn/tests/test_meta.rs0000644000175000017500000000614414661133735016054 0ustar jamespagejamespage#![allow( clippy::shadow_unrelated, clippy::too_many_lines, clippy::uninlined_format_args )] #[macro_use] mod macros; use syn::{Meta, MetaList, MetaNameValue}; #[test] fn test_parse_meta_item_word() { let input = "hello"; snapshot!(input as Meta, @r###" Meta::Path { segments: [ PathSegment { ident: "hello", }, ], } "###); } #[test] fn test_parse_meta_name_value() { let input = "foo = 5"; let (inner, meta) = (input, input); snapshot!(inner as MetaNameValue, @r###" MetaNameValue { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, value: Expr::Lit { lit: 5, }, } "###); snapshot!(meta as Meta, @r###" Meta::NameValue { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, value: Expr::Lit { lit: 5, }, } "###); assert_eq!(meta, Meta::NameValue(inner)); } #[test] fn test_parse_meta_item_list_lit() { let input = "foo(5)"; let (inner, meta) = (input, input); snapshot!(inner as MetaList, @r###" MetaList { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`5`), } "###); snapshot!(meta as Meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`5`), } "###); assert_eq!(meta, Meta::List(inner)); } #[test] fn test_parse_meta_item_multiple() { let input = "foo(word, name = 5, list(name2 = 6), word2)"; let (inner, meta) = (input, input); snapshot!(inner as MetaList, @r###" MetaList { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`word , name = 5 , list (name2 = 6) , word2`), } "###); snapshot!(meta as Meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`word , name = 5 , list (name2 = 6) , word2`), } "###); assert_eq!(meta, Meta::List(inner)); } #[test] fn test_parse_path() { let input = "::serde::Serialize"; snapshot!(input as Meta, @r###" Meta::Path { leading_colon: Some, segments: [ PathSegment { ident: "serde", }, Token![::], PathSegment { ident: "Serialize", }, ], } "###); } syn/tests/test_asyncness.rs0000644000175000017500000000144614661133735017134 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use syn::{Expr, Item}; #[test] fn test_async_fn() { let input = "async fn process() {}"; snapshot!(input as Item, @r###" Item::Fn { vis: Visibility::Inherited, sig: Signature { asyncness: Some, ident: "process", generics: Generics, output: ReturnType::Default, }, block: Block { stmts: [], }, } "###); } #[test] fn test_async_closure() { let input = "async || {}"; snapshot!(input as Expr, @r###" Expr::Closure { asyncness: Some, output: ReturnType::Default, body: Expr::Block { block: Block { stmts: [], }, }, } "###); } syn/tests/zzz_stable.rs0000644000175000017500000000211214661133735016245 0ustar jamespagejamespage#![cfg(syn_disable_nightly_tests)] use std::io::{self, Write}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; const MSG: &str = "\ ‖ ‖ WARNING: ‖ This is not a nightly compiler so not all tests were able to ‖ run. Syn includes tests that compare Syn's parser against the ‖ compiler's parser, which requires access to unstable librustc ‖ data structures and a nightly compiler. ‖ "; #[test] fn notice() -> io::Result<()> { let header = "WARNING"; let index_of_header = MSG.find(header).unwrap(); let before = &MSG[..index_of_header]; let after = &MSG[index_of_header + header.len()..]; let mut stderr = StandardStream::stderr(ColorChoice::Auto); stderr.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?; write!(&mut stderr, "{}", before)?; stderr.set_color(ColorSpec::new().set_bold(true).set_fg(Some(Color::Yellow)))?; write!(&mut stderr, "{}", header)?; stderr.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)))?; write!(&mut stderr, "{}", after)?; stderr.reset()?; Ok(()) } syn/tests/test_expr.rs0000644000175000017500000004336114661133735016106 0ustar jamespagejamespage#![allow(clippy::single_element_loop, clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group}; use quote::{quote, ToTokens as _}; use std::mem; use syn::punctuated::Punctuated; use syn::visit_mut::{self, VisitMut}; use syn::{parse_quote, token, Expr, ExprRange, ExprTuple, Stmt, Token}; #[test] fn test_expr_parse() { let tokens = quote!(..100u32); snapshot!(tokens as Expr, @r###" Expr::Range { limits: RangeLimits::HalfOpen, end: Some(Expr::Lit { lit: 100u32, }), } "###); let tokens = quote!(..100u32); snapshot!(tokens as ExprRange, @r###" ExprRange { limits: RangeLimits::HalfOpen, end: Some(Expr::Lit { lit: 100u32, }), } "###); } #[test] fn test_await() { // Must not parse as Expr::Field. let tokens = quote!(fut.await); snapshot!(tokens as Expr, @r###" Expr::Await { base: Expr::Path { path: Path { segments: [ PathSegment { ident: "fut", }, ], }, }, } "###); } #[rustfmt::skip] #[test] fn test_tuple_multi_index() { let expected = snapshot!("tuple.0.0" as Expr, @r###" Expr::Field { base: Expr::Field { base: Expr::Path { path: Path { segments: [ PathSegment { ident: "tuple", }, ], }, }, member: Member::Unnamed(Index { index: 0, }), }, member: Member::Unnamed(Index { index: 0, }), } "###); for &input in &[ "tuple .0.0", "tuple. 0.0", "tuple.0 .0", "tuple.0. 0", "tuple . 0 . 0", ] { assert_eq!(expected, syn::parse_str(input).unwrap()); } for tokens in [ quote!(tuple.0.0), quote!(tuple .0.0), quote!(tuple. 0.0), quote!(tuple.0 .0), quote!(tuple.0. 0), quote!(tuple . 0 . 0), ] { assert_eq!(expected, syn::parse2(tokens).unwrap()); } } #[test] fn test_macro_variable_func() { // mimics the token stream corresponding to `$fn()` let path = Group::new(Delimiter::None, quote!(f)); let tokens = quote!(#path()); snapshot!(tokens as Expr, @r###" Expr::Call { func: Expr::Group { expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "f", }, ], }, }, }, } "###); let path = Group::new(Delimiter::None, quote! { #[inside] f }); let tokens = quote!(#[outside] #path()); snapshot!(tokens as Expr, @r###" Expr::Call { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "outside", }, ], }, }, ], func: Expr::Group { expr: Expr::Path { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "inside", }, ], }, }, ], path: Path { segments: [ PathSegment { ident: "f", }, ], }, }, }, } "###); } #[test] fn test_macro_variable_macro() { // mimics the token stream corresponding to `$macro!()` let mac = Group::new(Delimiter::None, quote!(m)); let tokens = quote!(#mac!()); snapshot!(tokens as Expr, @r###" Expr::Macro { mac: Macro { path: Path { segments: [ PathSegment { ident: "m", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(``), }, } "###); } #[test] fn test_macro_variable_struct() { // mimics the token stream corresponding to `$struct {}` let s = Group::new(Delimiter::None, quote! { S }); let tokens = quote!(#s {}); snapshot!(tokens as Expr, @r###" Expr::Struct { path: Path { segments: [ PathSegment { ident: "S", }, ], }, } "###); } #[test] fn test_macro_variable_unary() { // mimics the token stream corresponding to `$expr.method()` where expr is `&self` let inner = Group::new(Delimiter::None, quote!(&self)); let tokens = quote!(#inner.method()); snapshot!(tokens as Expr, @r###" Expr::MethodCall { receiver: Expr::Group { expr: Expr::Reference { expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "self", }, ], }, }, }, }, method: "method", } "###); } #[test] fn test_macro_variable_match_arm() { // mimics the token stream corresponding to `match v { _ => $expr }` let expr = Group::new(Delimiter::None, quote! { #[a] () }); let tokens = quote!(match v { _ => #expr }); snapshot!(tokens as Expr, @r###" Expr::Match { expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "v", }, ], }, }, arms: [ Arm { pat: Pat::Wild, body: Expr::Group { expr: Expr::Tuple { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "a", }, ], }, }, ], }, }, }, ], } "###); let expr = Group::new(Delimiter::None, quote!(loop {} + 1)); let tokens = quote!(match v { _ => #expr }); snapshot!(tokens as Expr, @r###" Expr::Match { expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "v", }, ], }, }, arms: [ Arm { pat: Pat::Wild, body: Expr::Group { expr: Expr::Binary { left: Expr::Loop { body: Block { stmts: [], }, }, op: BinOp::Add, right: Expr::Lit { lit: 1, }, }, }, }, ], } "###); } // https://github.com/dtolnay/syn/issues/1019 #[test] fn test_closure_vs_rangefull() { #[rustfmt::skip] // rustfmt bug: https://github.com/rust-lang/rustfmt/issues/4808 let tokens = quote!(|| .. .method()); snapshot!(tokens as Expr, @r###" Expr::MethodCall { receiver: Expr::Closure { output: ReturnType::Default, body: Expr::Range { limits: RangeLimits::HalfOpen, }, }, method: "method", } "###); } #[test] fn test_postfix_operator_after_cast() { syn::parse_str::("|| &x as T[0]").unwrap_err(); syn::parse_str::("|| () as ()()").unwrap_err(); } #[test] fn test_range_kinds() { syn::parse_str::("..").unwrap(); syn::parse_str::("..hi").unwrap(); syn::parse_str::("lo..").unwrap(); syn::parse_str::("lo..hi").unwrap(); syn::parse_str::("..=").unwrap_err(); syn::parse_str::("..=hi").unwrap(); syn::parse_str::("lo..=").unwrap_err(); syn::parse_str::("lo..=hi").unwrap(); syn::parse_str::("...").unwrap_err(); syn::parse_str::("...hi").unwrap_err(); syn::parse_str::("lo...").unwrap_err(); syn::parse_str::("lo...hi").unwrap_err(); } #[test] fn test_range_precedence() { snapshot!(".. .." as Expr, @r###" Expr::Range { limits: RangeLimits::HalfOpen, end: Some(Expr::Range { limits: RangeLimits::HalfOpen, }), } "###); snapshot!(".. .. ()" as Expr, @r###" Expr::Range { limits: RangeLimits::HalfOpen, end: Some(Expr::Range { limits: RangeLimits::HalfOpen, end: Some(Expr::Tuple), }), } "###); snapshot!("() .. .." as Expr, @r###" Expr::Range { start: Some(Expr::Tuple), limits: RangeLimits::HalfOpen, end: Some(Expr::Range { limits: RangeLimits::HalfOpen, }), } "###); // A range with a lower bound cannot be the upper bound of another range, // and a range with an upper bound cannot be the lower bound of another // range. syn::parse_str::(".. x ..").unwrap_err(); syn::parse_str::("x .. x ..").unwrap_err(); } #[test] fn test_ambiguous_label() { for stmt in [ quote! { return 'label: loop { break 'label 42; }; }, quote! { break ('label: loop { break 'label 42; }); }, quote! { break 1 + 'label: loop { break 'label 42; }; }, quote! { break 'outer 'inner: loop { break 'inner 42; }; }, ] { syn::parse2::(stmt).unwrap(); } for stmt in [ // Parentheses required. See https://github.com/rust-lang/rust/pull/87026. quote! { break 'label: loop { break 'label 42; }; }, ] { syn::parse2::(stmt).unwrap_err(); } } #[test] fn test_extended_interpolated_path() { let path = Group::new(Delimiter::None, quote!(a::b)); let tokens = quote!(if #path {}); snapshot!(tokens as Expr, @r###" Expr::If { cond: Expr::Group { expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "a", }, Token![::], PathSegment { ident: "b", }, ], }, }, }, then_branch: Block { stmts: [], }, } "###); let tokens = quote!(#path {}); snapshot!(tokens as Expr, @r###" Expr::Struct { path: Path { segments: [ PathSegment { ident: "a", }, Token![::], PathSegment { ident: "b", }, ], }, } "###); let tokens = quote!(#path :: c); snapshot!(tokens as Expr, @r###" Expr::Path { path: Path { segments: [ PathSegment { ident: "a", }, Token![::], PathSegment { ident: "b", }, Token![::], PathSegment { ident: "c", }, ], }, } "###); let nested = Group::new(Delimiter::None, quote!(a::b || true)); let tokens = quote!(if #nested && false {}); snapshot!(tokens as Expr, @r###" Expr::If { cond: Expr::Binary { left: Expr::Group { expr: Expr::Binary { left: Expr::Path { path: Path { segments: [ PathSegment { ident: "a", }, Token![::], PathSegment { ident: "b", }, ], }, }, op: BinOp::Or, right: Expr::Lit { lit: Lit::Bool { value: true, }, }, }, }, op: BinOp::And, right: Expr::Lit { lit: Lit::Bool { value: false, }, }, }, then_branch: Block { stmts: [], }, } "###); } #[test] fn test_tuple_comma() { let mut expr = ExprTuple { attrs: Vec::new(), paren_token: token::Paren::default(), elems: Punctuated::new(), }; snapshot!(expr.to_token_stream() as Expr, @"Expr::Tuple"); expr.elems.push_value(parse_quote!(continue)); // Must not parse to Expr::Paren snapshot!(expr.to_token_stream() as Expr, @r###" Expr::Tuple { elems: [ Expr::Continue, Token![,], ], } "###); expr.elems.push_punct(::default()); snapshot!(expr.to_token_stream() as Expr, @r###" Expr::Tuple { elems: [ Expr::Continue, Token![,], ], } "###); expr.elems.push_value(parse_quote!(continue)); snapshot!(expr.to_token_stream() as Expr, @r###" Expr::Tuple { elems: [ Expr::Continue, Token![,], Expr::Continue, ], } "###); expr.elems.push_punct(::default()); snapshot!(expr.to_token_stream() as Expr, @r###" Expr::Tuple { elems: [ Expr::Continue, Token![,], Expr::Continue, Token![,], ], } "###); } #[test] fn test_binop_associativity() { // Left to right. snapshot!("() + () + ()" as Expr, @r###" Expr::Binary { left: Expr::Binary { left: Expr::Tuple, op: BinOp::Add, right: Expr::Tuple, }, op: BinOp::Add, right: Expr::Tuple, } "###); // Right to left. snapshot!("() += () += ()" as Expr, @r###" Expr::Binary { left: Expr::Tuple, op: BinOp::AddAssign, right: Expr::Binary { left: Expr::Tuple, op: BinOp::AddAssign, right: Expr::Tuple, }, } "###); // Parenthesization is required. syn::parse_str::("() == () == ()").unwrap_err(); } #[test] fn test_assign_range_precedence() { // Range has higher precedence as the right-hand of an assignment, but // ambiguous precedence as the left-hand of an assignment. snapshot!("() = () .. ()" as Expr, @r###" Expr::Assign { left: Expr::Tuple, right: Expr::Range { start: Some(Expr::Tuple), limits: RangeLimits::HalfOpen, end: Some(Expr::Tuple), }, } "###); snapshot!("() += () .. ()" as Expr, @r###" Expr::Binary { left: Expr::Tuple, op: BinOp::AddAssign, right: Expr::Range { start: Some(Expr::Tuple), limits: RangeLimits::HalfOpen, end: Some(Expr::Tuple), }, } "###); syn::parse_str::("() .. () = ()").unwrap_err(); syn::parse_str::("() .. () += ()").unwrap_err(); } #[test] fn test_fixup() { struct FlattenParens; impl VisitMut for FlattenParens { fn visit_expr_mut(&mut self, e: &mut Expr) { while let Expr::Paren(paren) = e { *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER); } visit_mut::visit_expr_mut(self, e); } } for tokens in [ quote! { 2 * (1 + 1) }, quote! { 0 + (0 + 0) }, quote! { (a = b) = c }, quote! { (x as i32) < 0 }, quote! { (1 + x as i32) < 0 }, quote! { (1 + 1).abs() }, quote! { (lo..hi)[..] }, quote! { (a..b)..(c..d) }, quote! { (&mut fut).await }, quote! { &mut (x as i32) }, quote! { -(x as i32) }, quote! { if (S {} == 1) {} }, quote! { { (m! {}) - 1 } }, quote! { match m { _ => ({}) - 1 } }, quote! { if let _ = (a && b) && c {} }, quote! { if let _ = (S {}) {} }, quote! { break ('a: loop { break 'a 1 } + 1) }, ] { let original: Expr = syn::parse2(tokens).unwrap(); let mut flat = original.clone(); FlattenParens.visit_expr_mut(&mut flat); let reconstructed: Expr = match syn::parse2(flat.to_token_stream()) { Ok(reconstructed) => reconstructed, Err(err) => panic!("failed to parse `{}`: {}", flat.to_token_stream(), err), }; assert!( original == reconstructed, "original: {}\nreconstructed: {}", original.to_token_stream(), reconstructed.to_token_stream(), ); } } syn/tests/test_lit.rs0000644000175000017500000002435514661133735015722 0ustar jamespagejamespage#![allow( clippy::float_cmp, clippy::needless_raw_string_hashes, clippy::non_ascii_literal, clippy::single_match_else, clippy::uninlined_format_args )] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, Literal, Span, TokenStream, TokenTree}; use quote::ToTokens; use std::ffi::CStr; use std::str::FromStr; use syn::{Lit, LitFloat, LitInt, LitStr}; #[track_caller] fn lit(s: &str) -> Lit { let mut tokens = TokenStream::from_str(s).unwrap().into_iter(); match tokens.next().unwrap() { TokenTree::Literal(lit) => { assert!(tokens.next().is_none()); Lit::new(lit) } wrong => panic!("{:?}", wrong), } } #[test] fn strings() { #[track_caller] fn test_string(s: &str, value: &str) { let s = s.trim(); match lit(s) { Lit::Str(lit) => { assert_eq!(lit.value(), value); let again = lit.into_token_stream().to_string(); if again != s { test_string(&again, value); } } wrong => panic!("{:?}", wrong), } } test_string(r#" "" "#, ""); test_string(r#" "a" "#, "a"); test_string(r#" "\n" "#, "\n"); test_string(r#" "\r" "#, "\r"); test_string(r#" "\t" "#, "\t"); test_string(r#" "🐕" "#, "🐕"); // NOTE: This is an emoji test_string(r#" "\"" "#, "\""); test_string(r#" "'" "#, "'"); test_string(r#" "\u{1F415}" "#, "\u{1F415}"); test_string(r#" "\u{1_2__3_}" "#, "\u{123}"); test_string( "\"contains\nnewlines\\\nescaped newlines\"", "contains\nnewlinesescaped newlines", ); test_string( "\"escaped newline\\\n \x0C unsupported whitespace\"", "escaped newline\x0C unsupported whitespace", ); test_string("r\"raw\nstring\\\nhere\"", "raw\nstring\\\nhere"); test_string("\"...\"q", "..."); test_string("r\"...\"q", "..."); test_string("r##\"...\"##q", "..."); } #[test] fn byte_strings() { #[track_caller] fn test_byte_string(s: &str, value: &[u8]) { let s = s.trim(); match lit(s) { Lit::ByteStr(lit) => { assert_eq!(lit.value(), value); let again = lit.into_token_stream().to_string(); if again != s { test_byte_string(&again, value); } } wrong => panic!("{:?}", wrong), } } test_byte_string(r#" b"" "#, b""); test_byte_string(r#" b"a" "#, b"a"); test_byte_string(r#" b"\n" "#, b"\n"); test_byte_string(r#" b"\r" "#, b"\r"); test_byte_string(r#" b"\t" "#, b"\t"); test_byte_string(r#" b"\"" "#, b"\""); test_byte_string(r#" b"'" "#, b"'"); test_byte_string( "b\"contains\nnewlines\\\nescaped newlines\"", b"contains\nnewlinesescaped newlines", ); test_byte_string("br\"raw\nstring\\\nhere\"", b"raw\nstring\\\nhere"); test_byte_string("b\"...\"q", b"..."); test_byte_string("br\"...\"q", b"..."); test_byte_string("br##\"...\"##q", b"..."); } #[test] fn c_strings() { #[track_caller] fn test_c_string(s: &str, value: &CStr) { let s = s.trim(); match lit(s) { Lit::CStr(lit) => { assert_eq!(*lit.value(), *value); let again = lit.into_token_stream().to_string(); if again != s { test_c_string(&again, value); } } wrong => panic!("{:?}", wrong), } } test_c_string(r#" c"" "#, c""); test_c_string(r#" c"a" "#, c"a"); test_c_string(r#" c"\n" "#, c"\n"); test_c_string(r#" c"\r" "#, c"\r"); test_c_string(r#" c"\t" "#, c"\t"); test_c_string(r#" c"\\" "#, c"\\"); test_c_string(r#" c"\'" "#, c"'"); test_c_string(r#" c"\"" "#, c"\""); test_c_string( "c\"contains\nnewlines\\\nescaped newlines\"", c"contains\nnewlinesescaped newlines", ); test_c_string("cr\"raw\nstring\\\nhere\"", c"raw\nstring\\\nhere"); test_c_string("c\"...\"q", c"..."); test_c_string("cr\"...\"", c"..."); test_c_string("cr##\"...\"##", c"..."); test_c_string( r#" c"hello\x80我叫\u{1F980}" "#, // from the RFC c"hello\x80我叫\u{1F980}", ); } #[test] fn bytes() { #[track_caller] fn test_byte(s: &str, value: u8) { let s = s.trim(); match lit(s) { Lit::Byte(lit) => { assert_eq!(lit.value(), value); let again = lit.into_token_stream().to_string(); assert_eq!(again, s); } wrong => panic!("{:?}", wrong), } } test_byte(r#" b'a' "#, b'a'); test_byte(r#" b'\n' "#, b'\n'); test_byte(r#" b'\r' "#, b'\r'); test_byte(r#" b'\t' "#, b'\t'); test_byte(r#" b'\'' "#, b'\''); test_byte(r#" b'"' "#, b'"'); test_byte(r#" b'a'q "#, b'a'); } #[test] fn chars() { #[track_caller] fn test_char(s: &str, value: char) { let s = s.trim(); match lit(s) { Lit::Char(lit) => { assert_eq!(lit.value(), value); let again = lit.into_token_stream().to_string(); if again != s { test_char(&again, value); } } wrong => panic!("{:?}", wrong), } } test_char(r#" 'a' "#, 'a'); test_char(r#" '\n' "#, '\n'); test_char(r#" '\r' "#, '\r'); test_char(r#" '\t' "#, '\t'); test_char(r#" '🐕' "#, '🐕'); // NOTE: This is an emoji test_char(r#" '\'' "#, '\''); test_char(r#" '"' "#, '"'); test_char(r#" '\u{1F415}' "#, '\u{1F415}'); test_char(r#" 'a'q "#, 'a'); } #[test] fn ints() { #[track_caller] fn test_int(s: &str, value: u64, suffix: &str) { match lit(s) { Lit::Int(lit) => { assert_eq!(lit.base10_digits().parse::().unwrap(), value); assert_eq!(lit.suffix(), suffix); let again = lit.into_token_stream().to_string(); if again != s { test_int(&again, value, suffix); } } wrong => panic!("{:?}", wrong), } } test_int("5", 5, ""); test_int("5u32", 5, "u32"); test_int("0E", 0, "E"); test_int("0ECMA", 0, "ECMA"); test_int("0o0A", 0, "A"); test_int("5_0", 50, ""); test_int("5_____0_____", 50, ""); test_int("0x7f", 127, ""); test_int("0x7F", 127, ""); test_int("0b1001", 9, ""); test_int("0o73", 59, ""); test_int("0x7Fu8", 127, "u8"); test_int("0b1001i8", 9, "i8"); test_int("0o73u32", 59, "u32"); test_int("0x__7___f_", 127, ""); test_int("0x__7___F_", 127, ""); test_int("0b_1_0__01", 9, ""); test_int("0o_7__3", 59, ""); test_int("0x_7F__u8", 127, "u8"); test_int("0b__10__0_1i8", 9, "i8"); test_int("0o__7__________________3u32", 59, "u32"); test_int("0e1\u{5c5}", 0, "e1\u{5c5}"); } #[test] fn floats() { #[track_caller] fn test_float(s: &str, value: f64, suffix: &str) { match lit(s) { Lit::Float(lit) => { assert_eq!(lit.base10_digits().parse::().unwrap(), value); assert_eq!(lit.suffix(), suffix); let again = lit.into_token_stream().to_string(); if again != s { test_float(&again, value, suffix); } } wrong => panic!("{:?}", wrong), } } test_float("5.5", 5.5, ""); test_float("5.5E12", 5.5e12, ""); test_float("5.5e12", 5.5e12, ""); test_float("1.0__3e-12", 1.03e-12, ""); test_float("1.03e+12", 1.03e12, ""); test_float("9e99e99", 9e99, "e99"); test_float("1e_0", 1.0, ""); test_float("0.0ECMA", 0.0, "ECMA"); } #[test] fn negative() { let span = Span::call_site(); assert_eq!("-1", LitInt::new("-1", span).to_string()); assert_eq!("-1i8", LitInt::new("-1i8", span).to_string()); assert_eq!("-1i16", LitInt::new("-1i16", span).to_string()); assert_eq!("-1i32", LitInt::new("-1i32", span).to_string()); assert_eq!("-1i64", LitInt::new("-1i64", span).to_string()); assert_eq!("-1.5", LitFloat::new("-1.5", span).to_string()); assert_eq!("-1.5f32", LitFloat::new("-1.5f32", span).to_string()); assert_eq!("-1.5f64", LitFloat::new("-1.5f64", span).to_string()); } #[test] fn suffix() { #[track_caller] fn get_suffix(token: &str) -> String { let lit = syn::parse_str::(token).unwrap(); match lit { Lit::Str(lit) => lit.suffix().to_owned(), Lit::ByteStr(lit) => lit.suffix().to_owned(), Lit::CStr(lit) => lit.suffix().to_owned(), Lit::Byte(lit) => lit.suffix().to_owned(), Lit::Char(lit) => lit.suffix().to_owned(), Lit::Int(lit) => lit.suffix().to_owned(), Lit::Float(lit) => lit.suffix().to_owned(), _ => unimplemented!(), } } assert_eq!(get_suffix("\"\"s"), "s"); assert_eq!(get_suffix("r\"\"r"), "r"); assert_eq!(get_suffix("r#\"\"#r"), "r"); assert_eq!(get_suffix("b\"\"b"), "b"); assert_eq!(get_suffix("br\"\"br"), "br"); assert_eq!(get_suffix("br#\"\"#br"), "br"); assert_eq!(get_suffix("c\"\"c"), "c"); assert_eq!(get_suffix("cr\"\"cr"), "cr"); assert_eq!(get_suffix("cr#\"\"#cr"), "cr"); assert_eq!(get_suffix("'c'c"), "c"); assert_eq!(get_suffix("b'b'b"), "b"); assert_eq!(get_suffix("1i32"), "i32"); assert_eq!(get_suffix("1_i32"), "i32"); assert_eq!(get_suffix("1.0f32"), "f32"); assert_eq!(get_suffix("1.0_f32"), "f32"); } #[test] fn test_deep_group_empty() { let tokens = TokenStream::from_iter([TokenTree::Group(Group::new( Delimiter::None, TokenStream::from_iter([TokenTree::Group(Group::new( Delimiter::None, TokenStream::from_iter([TokenTree::Literal(Literal::string("hi"))]), ))]), ))]); snapshot!(tokens as Lit, @r#""hi""# ); } #[test] fn test_error() { let err = syn::parse_str::("...").unwrap_err(); assert_eq!("expected string literal", err.to_string()); let err = syn::parse_str::("5").unwrap_err(); assert_eq!("expected string literal", err.to_string()); } syn/tests/test_token_trees.rs0000644000175000017500000000124314661133735017443 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::TokenStream; use quote::quote; use syn::Lit; #[test] fn test_struct() { let input = " #[derive(Debug, Clone)] pub struct Item { pub ident: Ident, pub attrs: Vec, } "; snapshot!(input as TokenStream, @r###" TokenStream( `# [derive (Debug , Clone)] pub struct Item { pub ident : Ident , pub attrs : Vec < Attribute >, }`, ) "###); } #[test] fn test_literal_mangling() { let code = "0_4"; let parsed: Lit = syn::parse_str(code).unwrap(); assert_eq!(code, quote!(#parsed).to_string()); } syn/tests/test_shebang.rs0000644000175000017500000000333514661133735016534 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; #[test] fn test_basic() { let content = "#!/usr/bin/env rustx\nfn main() {}"; let file = syn::parse_file(content).unwrap(); snapshot!(file, @r###" File { shebang: Some("#!/usr/bin/env rustx"), items: [ Item::Fn { vis: Visibility::Inherited, sig: Signature { ident: "main", generics: Generics, output: ReturnType::Default, }, block: Block { stmts: [], }, }, ], } "###); } #[test] fn test_comment() { let content = "#!//am/i/a/comment\n[allow(dead_code)] fn main() {}"; let file = syn::parse_file(content).unwrap(); snapshot!(file, @r###" File { attrs: [ Attribute { style: AttrStyle::Inner, meta: Meta::List { path: Path { segments: [ PathSegment { ident: "allow", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`dead_code`), }, }, ], items: [ Item::Fn { vis: Visibility::Inherited, sig: Signature { ident: "main", generics: Generics, output: ReturnType::Default, }, block: Block { stmts: [], }, }, ], } "###); } syn/tests/test_pat.rs0000644000175000017500000001063214661133735015707 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, TokenStream, TokenTree}; use quote::{quote, ToTokens as _}; use syn::parse::Parser; use syn::punctuated::Punctuated; use syn::{parse_quote, token, Item, Pat, PatTuple, Stmt, Token}; #[test] fn test_pat_ident() { match Pat::parse_single.parse2(quote!(self)).unwrap() { Pat::Ident(_) => (), value => panic!("expected PatIdent, got {:?}", value), } } #[test] fn test_pat_path() { match Pat::parse_single.parse2(quote!(self::CONST)).unwrap() { Pat::Path(_) => (), value => panic!("expected PatPath, got {:?}", value), } } #[test] fn test_leading_vert() { // https://github.com/rust-lang/rust/blob/1.43.0/src/test/ui/or-patterns/remove-leading-vert.rs syn::parse_str::("fn f() {}").unwrap(); syn::parse_str::("fn fun1(| A: E) {}").unwrap_err(); syn::parse_str::("fn fun2(|| A: E) {}").unwrap_err(); syn::parse_str::("let | () = ();").unwrap_err(); syn::parse_str::("let (| A): E;").unwrap(); syn::parse_str::("let (|| A): (E);").unwrap_err(); syn::parse_str::("let (| A,): (E,);").unwrap(); syn::parse_str::("let [| A]: [E; 1];").unwrap(); syn::parse_str::("let [|| A]: [E; 1];").unwrap_err(); syn::parse_str::("let TS(| A): TS;").unwrap(); syn::parse_str::("let TS(|| A): TS;").unwrap_err(); syn::parse_str::("let NS { f: | A }: NS;").unwrap(); syn::parse_str::("let NS { f: || A }: NS;").unwrap_err(); } #[test] fn test_group() { let group = Group::new(Delimiter::None, quote!(Some(_))); let tokens = TokenStream::from_iter([TokenTree::Group(group)]); let pat = Pat::parse_single.parse2(tokens).unwrap(); snapshot!(pat, @r###" Pat::TupleStruct { path: Path { segments: [ PathSegment { ident: "Some", }, ], }, elems: [ Pat::Wild, ], } "###); } #[test] fn test_ranges() { Pat::parse_single.parse_str("..").unwrap(); Pat::parse_single.parse_str("..hi").unwrap(); Pat::parse_single.parse_str("lo..").unwrap(); Pat::parse_single.parse_str("lo..hi").unwrap(); Pat::parse_single.parse_str("..=").unwrap_err(); Pat::parse_single.parse_str("..=hi").unwrap(); Pat::parse_single.parse_str("lo..=").unwrap_err(); Pat::parse_single.parse_str("lo..=hi").unwrap(); Pat::parse_single.parse_str("...").unwrap_err(); Pat::parse_single.parse_str("...hi").unwrap_err(); Pat::parse_single.parse_str("lo...").unwrap_err(); Pat::parse_single.parse_str("lo...hi").unwrap(); Pat::parse_single.parse_str("[lo..]").unwrap_err(); Pat::parse_single.parse_str("[..=hi]").unwrap_err(); Pat::parse_single.parse_str("[(lo..)]").unwrap(); Pat::parse_single.parse_str("[(..=hi)]").unwrap(); Pat::parse_single.parse_str("[lo..=hi]").unwrap(); Pat::parse_single.parse_str("[_, lo.., _]").unwrap_err(); Pat::parse_single.parse_str("[_, ..=hi, _]").unwrap_err(); Pat::parse_single.parse_str("[_, (lo..), _]").unwrap(); Pat::parse_single.parse_str("[_, (..=hi), _]").unwrap(); Pat::parse_single.parse_str("[_, lo..=hi, _]").unwrap(); } #[test] fn test_tuple_comma() { let mut expr = PatTuple { attrs: Vec::new(), paren_token: token::Paren::default(), elems: Punctuated::new(), }; snapshot!(expr.to_token_stream() as Pat, @"Pat::Tuple"); expr.elems.push_value(parse_quote!(_)); // Must not parse to Pat::Paren snapshot!(expr.to_token_stream() as Pat, @r###" Pat::Tuple { elems: [ Pat::Wild, Token![,], ], } "###); expr.elems.push_punct(::default()); snapshot!(expr.to_token_stream() as Pat, @r###" Pat::Tuple { elems: [ Pat::Wild, Token![,], ], } "###); expr.elems.push_value(parse_quote!(_)); snapshot!(expr.to_token_stream() as Pat, @r###" Pat::Tuple { elems: [ Pat::Wild, Token![,], Pat::Wild, ], } "###); expr.elems.push_punct(::default()); snapshot!(expr.to_token_stream() as Pat, @r###" Pat::Tuple { elems: [ Pat::Wild, Token![,], Pat::Wild, Token![,], ], } "###); } syn/tests/macros/0000775000175000017500000000000014661133735015002 5ustar jamespagejamespagesyn/tests/macros/mod.rs0000644000175000017500000000502014661133735016122 0ustar jamespagejamespage#![allow(unused_macros, unused_macro_rules)] #[path = "../debug/mod.rs"] pub mod debug; use std::str::FromStr; use syn::parse::Result; macro_rules! errorf { ($($tt:tt)*) => {{ use ::std::io::Write; let stderr = ::std::io::stderr(); write!(stderr.lock(), $($tt)*).unwrap(); }}; } macro_rules! punctuated { ($($e:expr,)+) => {{ let mut seq = ::syn::punctuated::Punctuated::new(); $( seq.push($e); )+ seq }}; ($($e:expr),+) => { punctuated!($($e,)+) }; } macro_rules! snapshot { ($($args:tt)*) => { snapshot_impl!(() $($args)*) }; } macro_rules! snapshot_impl { (($expr:ident) as $t:ty, @$snapshot:literal) => { let tokens = crate::macros::TryIntoTokens::try_into_tokens($expr).unwrap(); let $expr: $t = syn::parse_quote!(#tokens); let debug = crate::macros::debug::Lite(&$expr); if !cfg!(miri) { #[allow(clippy::needless_raw_string_hashes)] // https://github.com/mitsuhiko/insta/issues/389 { insta::assert_debug_snapshot!(debug, @$snapshot); } } }; (($($expr:tt)*) as $t:ty, @$snapshot:literal) => {{ let tokens = crate::macros::TryIntoTokens::try_into_tokens($($expr)*).unwrap(); let syntax_tree: $t = syn::parse_quote!(#tokens); let debug = crate::macros::debug::Lite(&syntax_tree); if !cfg!(miri) { #[allow(clippy::needless_raw_string_hashes)] { insta::assert_debug_snapshot!(debug, @$snapshot); } } syntax_tree }}; (($($expr:tt)*) , @$snapshot:literal) => {{ let syntax_tree = $($expr)*; let debug = crate::macros::debug::Lite(&syntax_tree); if !cfg!(miri) { #[allow(clippy::needless_raw_string_hashes)] { insta::assert_debug_snapshot!(debug, @$snapshot); } } syntax_tree }}; (($($expr:tt)*) $next:tt $($rest:tt)*) => { snapshot_impl!(($($expr)* $next) $($rest)*) }; } pub trait TryIntoTokens { #[allow(dead_code)] fn try_into_tokens(self) -> Result; } impl<'a> TryIntoTokens for &'a str { fn try_into_tokens(self) -> Result { let tokens = proc_macro2::TokenStream::from_str(self)?; Ok(tokens) } } impl TryIntoTokens for proc_macro2::TokenStream { fn try_into_tokens(self) -> Result { Ok(self) } } syn/tests/test_parse_buffer.rs0000644000175000017500000000562114661133735017570 0ustar jamespagejamespage#![allow(clippy::non_ascii_literal)] use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, TokenStream, TokenTree}; use std::panic; use syn::parse::discouraged::Speculative as _; use syn::parse::{Parse, ParseStream, Parser, Result}; use syn::{parenthesized, Token}; #[test] #[should_panic(expected = "fork was not derived from the advancing parse stream")] fn smuggled_speculative_cursor_between_sources() { struct BreakRules; impl Parse for BreakRules { fn parse(input1: ParseStream) -> Result { let nested = |input2: ParseStream| { input1.advance_to(input2); Ok(Self) }; nested.parse_str("") } } syn::parse_str::("").unwrap(); } #[test] #[should_panic(expected = "fork was not derived from the advancing parse stream")] fn smuggled_speculative_cursor_between_brackets() { struct BreakRules; impl Parse for BreakRules { fn parse(input: ParseStream) -> Result { let a; let b; parenthesized!(a in input); parenthesized!(b in input); a.advance_to(&b); Ok(Self) } } syn::parse_str::("()()").unwrap(); } #[test] #[should_panic(expected = "fork was not derived from the advancing parse stream")] fn smuggled_speculative_cursor_into_brackets() { struct BreakRules; impl Parse for BreakRules { fn parse(input: ParseStream) -> Result { let a; parenthesized!(a in input); input.advance_to(&a); Ok(Self) } } syn::parse_str::("()").unwrap(); } #[test] fn trailing_empty_none_group() { fn parse(input: ParseStream) -> Result<()> { input.parse::()?; let content; parenthesized!(content in input); content.parse::()?; Ok(()) } // `+ ( + «∅ ∅» ) «∅ «∅ ∅» ∅»` let tokens = TokenStream::from_iter([ TokenTree::Punct(Punct::new('+', Spacing::Alone)), TokenTree::Group(Group::new( Delimiter::Parenthesis, TokenStream::from_iter([ TokenTree::Punct(Punct::new('+', Spacing::Alone)), TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())), ]), )), TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())), TokenTree::Group(Group::new( Delimiter::None, TokenStream::from_iter([TokenTree::Group(Group::new( Delimiter::None, TokenStream::new(), ))]), )), ]); parse.parse2(tokens).unwrap(); } #[test] fn test_unwind_safe() { fn parse(input: ParseStream) -> Result { let thread_result = panic::catch_unwind(|| input.parse()); thread_result.unwrap() } parse.parse_str("throw").unwrap(); } syn/tests/test_path.rs0000644000175000017500000000725014661133735016061 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::{quote, ToTokens}; use syn::{parse_quote, Expr, Type, TypePath}; #[test] fn parse_interpolated_leading_component() { // mimics the token stream corresponding to `$mod::rest` let tokens = TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, quote! { first })), TokenTree::Punct(Punct::new(':', Spacing::Joint)), TokenTree::Punct(Punct::new(':', Spacing::Alone)), TokenTree::Ident(Ident::new("rest", Span::call_site())), ]); snapshot!(tokens.clone() as Expr, @r###" Expr::Path { path: Path { segments: [ PathSegment { ident: "first", }, Token![::], PathSegment { ident: "rest", }, ], }, } "###); snapshot!(tokens as Type, @r###" Type::Path { path: Path { segments: [ PathSegment { ident: "first", }, Token![::], PathSegment { ident: "rest", }, ], }, } "###); } #[test] fn print_incomplete_qpath() { // qpath with `as` token let mut ty: TypePath = parse_quote!(::Q); snapshot!(ty.to_token_stream(), @r###" TokenStream(`< Self as A > :: Q`) "###); assert!(ty.path.segments.pop().is_some()); snapshot!(ty.to_token_stream(), @r###" TokenStream(`< Self as A > ::`) "###); assert!(ty.path.segments.pop().is_some()); snapshot!(ty.to_token_stream(), @r###" TokenStream(`< Self >`) "###); assert!(ty.path.segments.pop().is_none()); // qpath without `as` token let mut ty: TypePath = parse_quote!(::A::B); snapshot!(ty.to_token_stream(), @r###" TokenStream(`< Self > :: A :: B`) "###); assert!(ty.path.segments.pop().is_some()); snapshot!(ty.to_token_stream(), @r###" TokenStream(`< Self > :: A ::`) "###); assert!(ty.path.segments.pop().is_some()); snapshot!(ty.to_token_stream(), @r###" TokenStream(`< Self > ::`) "###); assert!(ty.path.segments.pop().is_none()); // normal path let mut ty: TypePath = parse_quote!(Self::A::B); snapshot!(ty.to_token_stream(), @r###" TokenStream(`Self :: A :: B`) "###); assert!(ty.path.segments.pop().is_some()); snapshot!(ty.to_token_stream(), @r###" TokenStream(`Self :: A ::`) "###); assert!(ty.path.segments.pop().is_some()); snapshot!(ty.to_token_stream(), @r###" TokenStream(`Self ::`) "###); assert!(ty.path.segments.pop().is_some()); snapshot!(ty.to_token_stream(), @r###" TokenStream(``) "###); assert!(ty.path.segments.pop().is_none()); } #[test] fn parse_parenthesized_path_arguments_with_disambiguator() { #[rustfmt::skip] let tokens = quote!(dyn FnOnce::() -> !); snapshot!(tokens as Type, @r###" Type::TraitObject { dyn_token: Some, bounds: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "FnOnce", arguments: PathArguments::Parenthesized { output: ReturnType::Type( Type::Never, ), }, }, ], }, }), ], } "###); } syn/tests/debug/0000775000175000017500000000000014661133735014604 5ustar jamespagejamespagesyn/tests/debug/gen.rs0000644000175000017500000061761514661133735015741 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #![allow(repr_transparent_external_private_fields)] #![allow(clippy::match_wildcard_for_single_variants)] use super::{Lite, Present}; use ref_cast::RefCast; use std::fmt::{self, Debug, Display}; impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Abi"); if let Some(val) = &self.value.name { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::LitStr); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("name", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("AngleBracketedGenericArguments"); if self.value.colon2_token.is_some() { formatter.field("colon2_token", &Present); } if !self.value.args.is_empty() { formatter.field("args", Lite(&self.value.args)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Arm"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("pat", Lite(&self.value.pat)); if let Some(val) = &self.value.guard { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::If, Box)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("guard", Print::ref_cast(val)); } formatter.field("body", Lite(&self.value.body)); if self.value.comma.is_some() { formatter.field("comma", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("AssocConst"); formatter.field("ident", Lite(&self.value.ident)); if let Some(val) = &self.value.generics { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::AngleBracketedGenericArguments); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("generics", Print::ref_cast(val)); } formatter.field("value", Lite(&self.value.value)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("AssocType"); formatter.field("ident", Lite(&self.value.ident)); if let Some(val) = &self.value.generics { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::AngleBracketedGenericArguments); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("generics", Print::ref_cast(val)); } formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::AttrStyle::Outer => formatter.write_str("AttrStyle::Outer"), syn::AttrStyle::Inner(_val) => { formatter.write_str("AttrStyle::Inner")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Attribute"); formatter.field("style", Lite(&self.value.style)); formatter.field("meta", Lite(&self.value.meta)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("BareFnArg"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.name { #[derive(RefCast)] #[repr(transparent)] struct Print((proc_macro2::Ident, syn::token::Colon)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("name", Print::ref_cast(val)); } formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("BareVariadic"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.name { #[derive(RefCast)] #[repr(transparent)] struct Print((proc_macro2::Ident, syn::token::Colon)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("name", Print::ref_cast(val)); } if self.value.comma.is_some() { formatter.field("comma", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::BinOp::Add(_val) => { formatter.write_str("BinOp::Add")?; Ok(()) } syn::BinOp::Sub(_val) => { formatter.write_str("BinOp::Sub")?; Ok(()) } syn::BinOp::Mul(_val) => { formatter.write_str("BinOp::Mul")?; Ok(()) } syn::BinOp::Div(_val) => { formatter.write_str("BinOp::Div")?; Ok(()) } syn::BinOp::Rem(_val) => { formatter.write_str("BinOp::Rem")?; Ok(()) } syn::BinOp::And(_val) => { formatter.write_str("BinOp::And")?; Ok(()) } syn::BinOp::Or(_val) => { formatter.write_str("BinOp::Or")?; Ok(()) } syn::BinOp::BitXor(_val) => { formatter.write_str("BinOp::BitXor")?; Ok(()) } syn::BinOp::BitAnd(_val) => { formatter.write_str("BinOp::BitAnd")?; Ok(()) } syn::BinOp::BitOr(_val) => { formatter.write_str("BinOp::BitOr")?; Ok(()) } syn::BinOp::Shl(_val) => { formatter.write_str("BinOp::Shl")?; Ok(()) } syn::BinOp::Shr(_val) => { formatter.write_str("BinOp::Shr")?; Ok(()) } syn::BinOp::Eq(_val) => { formatter.write_str("BinOp::Eq")?; Ok(()) } syn::BinOp::Lt(_val) => { formatter.write_str("BinOp::Lt")?; Ok(()) } syn::BinOp::Le(_val) => { formatter.write_str("BinOp::Le")?; Ok(()) } syn::BinOp::Ne(_val) => { formatter.write_str("BinOp::Ne")?; Ok(()) } syn::BinOp::Ge(_val) => { formatter.write_str("BinOp::Ge")?; Ok(()) } syn::BinOp::Gt(_val) => { formatter.write_str("BinOp::Gt")?; Ok(()) } syn::BinOp::AddAssign(_val) => { formatter.write_str("BinOp::AddAssign")?; Ok(()) } syn::BinOp::SubAssign(_val) => { formatter.write_str("BinOp::SubAssign")?; Ok(()) } syn::BinOp::MulAssign(_val) => { formatter.write_str("BinOp::MulAssign")?; Ok(()) } syn::BinOp::DivAssign(_val) => { formatter.write_str("BinOp::DivAssign")?; Ok(()) } syn::BinOp::RemAssign(_val) => { formatter.write_str("BinOp::RemAssign")?; Ok(()) } syn::BinOp::BitXorAssign(_val) => { formatter.write_str("BinOp::BitXorAssign")?; Ok(()) } syn::BinOp::BitAndAssign(_val) => { formatter.write_str("BinOp::BitAndAssign")?; Ok(()) } syn::BinOp::BitOrAssign(_val) => { formatter.write_str("BinOp::BitOrAssign")?; Ok(()) } syn::BinOp::ShlAssign(_val) => { formatter.write_str("BinOp::ShlAssign")?; Ok(()) } syn::BinOp::ShrAssign(_val) => { formatter.write_str("BinOp::ShrAssign")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Block"); formatter.field("stmts", Lite(&self.value.stmts)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("BoundLifetimes"); if !self.value.lifetimes.is_empty() { formatter.field("lifetimes", Lite(&self.value.lifetimes)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ConstParam"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("ty", Lite(&self.value.ty)); if self.value.eq_token.is_some() { formatter.field("eq_token", &Present); } if let Some(val) = &self.value.default { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Expr); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Constraint"); formatter.field("ident", Lite(&self.value.ident)); if let Some(val) = &self.value.generics { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::AngleBracketedGenericArguments); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("generics", Print::ref_cast(val)); } if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Data::Struct(_val) => { let mut formatter = formatter.debug_struct("Data::Struct"); formatter.field("fields", Lite(&_val.fields)); if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } syn::Data::Enum(_val) => { let mut formatter = formatter.debug_struct("Data::Enum"); if !_val.variants.is_empty() { formatter.field("variants", Lite(&_val.variants)); } formatter.finish() } syn::Data::Union(_val) => { let mut formatter = formatter.debug_struct("Data::Union"); formatter.field("fields", Lite(&_val.fields)); formatter.finish() } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DataEnum"); if !self.value.variants.is_empty() { formatter.field("variants", Lite(&self.value.variants)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DataStruct"); formatter.field("fields", Lite(&self.value.fields)); if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DataUnion"); formatter.field("fields", Lite(&self.value.fields)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DeriveInput"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("data", Lite(&self.value.data)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Expr::Array(_val) => { let mut formatter = formatter.debug_struct("Expr::Array"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if !_val.elems.is_empty() { formatter.field("elems", Lite(&_val.elems)); } formatter.finish() } syn::Expr::Assign(_val) => { let mut formatter = formatter.debug_struct("Expr::Assign"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("left", Lite(&_val.left)); formatter.field("right", Lite(&_val.right)); formatter.finish() } syn::Expr::Async(_val) => { let mut formatter = formatter.debug_struct("Expr::Async"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if _val.capture.is_some() { formatter.field("capture", &Present); } formatter.field("block", Lite(&_val.block)); formatter.finish() } syn::Expr::Await(_val) => { let mut formatter = formatter.debug_struct("Expr::Await"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("base", Lite(&_val.base)); formatter.finish() } syn::Expr::Binary(_val) => { let mut formatter = formatter.debug_struct("Expr::Binary"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("left", Lite(&_val.left)); formatter.field("op", Lite(&_val.op)); formatter.field("right", Lite(&_val.right)); formatter.finish() } syn::Expr::Block(_val) => { let mut formatter = formatter.debug_struct("Expr::Block"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("block", Lite(&_val.block)); formatter.finish() } syn::Expr::Break(_val) => { let mut formatter = formatter.debug_struct("Expr::Break"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Lifetime); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } if let Some(val) = &_val.expr { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("expr", Print::ref_cast(val)); } formatter.finish() } syn::Expr::Call(_val) => { let mut formatter = formatter.debug_struct("Expr::Call"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("func", Lite(&_val.func)); if !_val.args.is_empty() { formatter.field("args", Lite(&_val.args)); } formatter.finish() } syn::Expr::Cast(_val) => { let mut formatter = formatter.debug_struct("Expr::Cast"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("expr", Lite(&_val.expr)); formatter.field("ty", Lite(&_val.ty)); formatter.finish() } syn::Expr::Closure(_val) => { let mut formatter = formatter.debug_struct("Expr::Closure"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.lifetimes { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BoundLifetimes); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetimes", Print::ref_cast(val)); } if _val.constness.is_some() { formatter.field("constness", &Present); } if _val.movability.is_some() { formatter.field("movability", &Present); } if _val.asyncness.is_some() { formatter.field("asyncness", &Present); } if _val.capture.is_some() { formatter.field("capture", &Present); } if !_val.inputs.is_empty() { formatter.field("inputs", Lite(&_val.inputs)); } formatter.field("output", Lite(&_val.output)); formatter.field("body", Lite(&_val.body)); formatter.finish() } syn::Expr::Const(_val) => { let mut formatter = formatter.debug_struct("Expr::Const"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("block", Lite(&_val.block)); formatter.finish() } syn::Expr::Continue(_val) => { let mut formatter = formatter.debug_struct("Expr::Continue"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Lifetime); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.finish() } syn::Expr::Field(_val) => { let mut formatter = formatter.debug_struct("Expr::Field"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("base", Lite(&_val.base)); formatter.field("member", Lite(&_val.member)); formatter.finish() } syn::Expr::ForLoop(_val) => { let mut formatter = formatter.debug_struct("Expr::ForLoop"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("pat", Lite(&_val.pat)); formatter.field("expr", Lite(&_val.expr)); formatter.field("body", Lite(&_val.body)); formatter.finish() } syn::Expr::Group(_val) => { let mut formatter = formatter.debug_struct("Expr::Group"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Expr::If(_val) => { let mut formatter = formatter.debug_struct("Expr::If"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("cond", Lite(&_val.cond)); formatter.field("then_branch", Lite(&_val.then_branch)); if let Some(val) = &_val.else_branch { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Else, Box)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("else_branch", Print::ref_cast(val)); } formatter.finish() } syn::Expr::Index(_val) => { let mut formatter = formatter.debug_struct("Expr::Index"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("expr", Lite(&_val.expr)); formatter.field("index", Lite(&_val.index)); formatter.finish() } syn::Expr::Infer(_val) => { let mut formatter = formatter.debug_struct("Expr::Infer"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.finish() } syn::Expr::Let(_val) => { let mut formatter = formatter.debug_struct("Expr::Let"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("pat", Lite(&_val.pat)); formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Expr::Lit(_val) => { let mut formatter = formatter.debug_struct("Expr::Lit"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("lit", Lite(&_val.lit)); formatter.finish() } syn::Expr::Loop(_val) => { let mut formatter = formatter.debug_struct("Expr::Loop"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("body", Lite(&_val.body)); formatter.finish() } syn::Expr::Macro(_val) => { let mut formatter = formatter.debug_struct("Expr::Macro"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("mac", Lite(&_val.mac)); formatter.finish() } syn::Expr::Match(_val) => { let mut formatter = formatter.debug_struct("Expr::Match"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("expr", Lite(&_val.expr)); if !_val.arms.is_empty() { formatter.field("arms", Lite(&_val.arms)); } formatter.finish() } syn::Expr::MethodCall(_val) => { let mut formatter = formatter.debug_struct("Expr::MethodCall"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("receiver", Lite(&_val.receiver)); formatter.field("method", Lite(&_val.method)); if let Some(val) = &_val.turbofish { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::AngleBracketedGenericArguments); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("turbofish", Print::ref_cast(val)); } if !_val.args.is_empty() { formatter.field("args", Lite(&_val.args)); } formatter.finish() } syn::Expr::Paren(_val) => { let mut formatter = formatter.debug_struct("Expr::Paren"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Expr::Path(_val) => { let mut formatter = formatter.debug_struct("Expr::Path"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&_val.path)); formatter.finish() } syn::Expr::Range(_val) => { let mut formatter = formatter.debug_struct("Expr::Range"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.start { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("start", Print::ref_cast(val)); } formatter.field("limits", Lite(&_val.limits)); if let Some(val) = &_val.end { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("end", Print::ref_cast(val)); } formatter.finish() } syn::Expr::Reference(_val) => { let mut formatter = formatter.debug_struct("Expr::Reference"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if _val.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Expr::Repeat(_val) => { let mut formatter = formatter.debug_struct("Expr::Repeat"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("expr", Lite(&_val.expr)); formatter.field("len", Lite(&_val.len)); formatter.finish() } syn::Expr::Return(_val) => { let mut formatter = formatter.debug_struct("Expr::Return"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.expr { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("expr", Print::ref_cast(val)); } formatter.finish() } syn::Expr::Struct(_val) => { let mut formatter = formatter.debug_struct("Expr::Struct"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&_val.path)); if !_val.fields.is_empty() { formatter.field("fields", Lite(&_val.fields)); } if _val.dot2_token.is_some() { formatter.field("dot2_token", &Present); } if let Some(val) = &_val.rest { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("rest", Print::ref_cast(val)); } formatter.finish() } syn::Expr::Try(_val) => { let mut formatter = formatter.debug_struct("Expr::Try"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Expr::TryBlock(_val) => { let mut formatter = formatter.debug_struct("Expr::TryBlock"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("block", Lite(&_val.block)); formatter.finish() } syn::Expr::Tuple(_val) => { let mut formatter = formatter.debug_struct("Expr::Tuple"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if !_val.elems.is_empty() { formatter.field("elems", Lite(&_val.elems)); } formatter.finish() } syn::Expr::Unary(_val) => { let mut formatter = formatter.debug_struct("Expr::Unary"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("op", Lite(&_val.op)); formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Expr::Unsafe(_val) => { let mut formatter = formatter.debug_struct("Expr::Unsafe"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("block", Lite(&_val.block)); formatter.finish() } syn::Expr::Verbatim(_val) => { formatter.write_str("Expr::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } syn::Expr::While(_val) => { let mut formatter = formatter.debug_struct("Expr::While"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("cond", Lite(&_val.cond)); formatter.field("body", Lite(&_val.body)); formatter.finish() } syn::Expr::Yield(_val) => { let mut formatter = formatter.debug_struct("Expr::Yield"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.expr { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("expr", Print::ref_cast(val)); } formatter.finish() } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprArray"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if !self.value.elems.is_empty() { formatter.field("elems", Lite(&self.value.elems)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprAssign"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("left", Lite(&self.value.left)); formatter.field("right", Lite(&self.value.right)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprAsync"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if self.value.capture.is_some() { formatter.field("capture", &Present); } formatter.field("block", Lite(&self.value.block)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprAwait"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("base", Lite(&self.value.base)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprBinary"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("left", Lite(&self.value.left)); formatter.field("op", Lite(&self.value.op)); formatter.field("right", Lite(&self.value.right)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprBlock"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("block", Lite(&self.value.block)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprBreak"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Lifetime); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } if let Some(val) = &self.value.expr { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("expr", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprCall"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("func", Lite(&self.value.func)); if !self.value.args.is_empty() { formatter.field("args", Lite(&self.value.args)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprCast"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("expr", Lite(&self.value.expr)); formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprClosure"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.lifetimes { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BoundLifetimes); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetimes", Print::ref_cast(val)); } if self.value.constness.is_some() { formatter.field("constness", &Present); } if self.value.movability.is_some() { formatter.field("movability", &Present); } if self.value.asyncness.is_some() { formatter.field("asyncness", &Present); } if self.value.capture.is_some() { formatter.field("capture", &Present); } if !self.value.inputs.is_empty() { formatter.field("inputs", Lite(&self.value.inputs)); } formatter.field("output", Lite(&self.value.output)); formatter.field("body", Lite(&self.value.body)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprConst"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("block", Lite(&self.value.block)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprContinue"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Lifetime); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprField"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("base", Lite(&self.value.base)); formatter.field("member", Lite(&self.value.member)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprForLoop"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("pat", Lite(&self.value.pat)); formatter.field("expr", Lite(&self.value.expr)); formatter.field("body", Lite(&self.value.body)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprGroup"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprIf"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("cond", Lite(&self.value.cond)); formatter.field("then_branch", Lite(&self.value.then_branch)); if let Some(val) = &self.value.else_branch { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Else, Box)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("else_branch", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprIndex"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("expr", Lite(&self.value.expr)); formatter.field("index", Lite(&self.value.index)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprInfer"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprLet"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("pat", Lite(&self.value.pat)); formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprLit"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("lit", Lite(&self.value.lit)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprLoop"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("body", Lite(&self.value.body)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprMacro"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("mac", Lite(&self.value.mac)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprMatch"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("expr", Lite(&self.value.expr)); if !self.value.arms.is_empty() { formatter.field("arms", Lite(&self.value.arms)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprMethodCall"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("receiver", Lite(&self.value.receiver)); formatter.field("method", Lite(&self.value.method)); if let Some(val) = &self.value.turbofish { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::AngleBracketedGenericArguments); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("turbofish", Print::ref_cast(val)); } if !self.value.args.is_empty() { formatter.field("args", Lite(&self.value.args)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprParen"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprPath"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&self.value.path)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprRange"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.start { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("start", Print::ref_cast(val)); } formatter.field("limits", Lite(&self.value.limits)); if let Some(val) = &self.value.end { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("end", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprReference"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if self.value.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprRepeat"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("expr", Lite(&self.value.expr)); formatter.field("len", Lite(&self.value.len)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprReturn"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.expr { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("expr", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprStruct"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&self.value.path)); if !self.value.fields.is_empty() { formatter.field("fields", Lite(&self.value.fields)); } if self.value.dot2_token.is_some() { formatter.field("dot2_token", &Present); } if let Some(val) = &self.value.rest { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("rest", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprTry"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprTryBlock"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("block", Lite(&self.value.block)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprTuple"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if !self.value.elems.is_empty() { formatter.field("elems", Lite(&self.value.elems)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprUnary"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("op", Lite(&self.value.op)); formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprUnsafe"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("block", Lite(&self.value.block)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprWhile"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.label { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Label); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("label", Print::ref_cast(val)); } formatter.field("cond", Lite(&self.value.cond)); formatter.field("body", Lite(&self.value.body)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ExprYield"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.expr { #[derive(RefCast)] #[repr(transparent)] struct Print(Box); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("expr", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Field"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); match self.value.mutability { syn::FieldMutability::None => {} _ => { formatter.field("mutability", Lite(&self.value.mutability)); } } if let Some(val) = &self.value.ident { #[derive(RefCast)] #[repr(transparent)] struct Print(proc_macro2::Ident); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("ident", Print::ref_cast(val)); } if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::FieldMutability::None => formatter.write_str("FieldMutability::None"), _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("FieldPat"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("member", Lite(&self.value.member)); if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } formatter.field("pat", Lite(&self.value.pat)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("FieldValue"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("member", Lite(&self.value.member)); if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Fields::Named(_val) => { let mut formatter = formatter.debug_struct("Fields::Named"); if !_val.named.is_empty() { formatter.field("named", Lite(&_val.named)); } formatter.finish() } syn::Fields::Unnamed(_val) => { let mut formatter = formatter.debug_struct("Fields::Unnamed"); if !_val.unnamed.is_empty() { formatter.field("unnamed", Lite(&_val.unnamed)); } formatter.finish() } syn::Fields::Unit => formatter.write_str("Fields::Unit"), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("FieldsNamed"); if !self.value.named.is_empty() { formatter.field("named", Lite(&self.value.named)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("FieldsUnnamed"); if !self.value.unnamed.is_empty() { formatter.field("unnamed", Lite(&self.value.unnamed)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("File"); if let Some(val) = &self.value.shebang { #[derive(RefCast)] #[repr(transparent)] struct Print(String); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("shebang", Print::ref_cast(val)); } if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if !self.value.items.is_empty() { formatter.field("items", Lite(&self.value.items)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::FnArg::Receiver(_val) => { formatter.write_str("FnArg::Receiver")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::FnArg::Typed(_val) => { formatter.write_str("FnArg::Typed")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::ForeignItem::Fn(_val) => { let mut formatter = formatter.debug_struct("ForeignItem::Fn"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("sig", Lite(&_val.sig)); formatter.finish() } syn::ForeignItem::Static(_val) => { let mut formatter = formatter.debug_struct("ForeignItem::Static"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); match _val.mutability { syn::StaticMutability::None => {} _ => { formatter.field("mutability", Lite(&_val.mutability)); } } formatter.field("ident", Lite(&_val.ident)); formatter.field("ty", Lite(&_val.ty)); formatter.finish() } syn::ForeignItem::Type(_val) => { let mut formatter = formatter.debug_struct("ForeignItem::Type"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.finish() } syn::ForeignItem::Macro(_val) => { let mut formatter = formatter.debug_struct("ForeignItem::Macro"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("mac", Lite(&_val.mac)); if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } syn::ForeignItem::Verbatim(_val) => { formatter.write_str("ForeignItem::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ForeignItemFn"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("sig", Lite(&self.value.sig)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ForeignItemMacro"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("mac", Lite(&self.value.mac)); if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ForeignItemStatic"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); match self.value.mutability { syn::StaticMutability::None => {} _ => { formatter.field("mutability", Lite(&self.value.mutability)); } } formatter.field("ident", Lite(&self.value.ident)); formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ForeignItemType"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::GenericArgument::Lifetime(_val) => { formatter.write_str("GenericArgument::Lifetime")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::GenericArgument::Type(_val) => { formatter.write_str("GenericArgument::Type")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::GenericArgument::Const(_val) => { formatter.write_str("GenericArgument::Const")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::GenericArgument::AssocType(_val) => { formatter.write_str("GenericArgument::AssocType")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::GenericArgument::AssocConst(_val) => { formatter.write_str("GenericArgument::AssocConst")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::GenericArgument::Constraint(_val) => { formatter.write_str("GenericArgument::Constraint")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::GenericParam::Lifetime(_val) => { formatter.write_str("GenericParam::Lifetime")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::GenericParam::Type(_val) => { formatter.write_str("GenericParam::Type")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::GenericParam::Const(_val) => { formatter.write_str("GenericParam::Const")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Generics"); if self.value.lt_token.is_some() { formatter.field("lt_token", &Present); } if !self.value.params.is_empty() { formatter.field("params", Lite(&self.value.params)); } if self.value.gt_token.is_some() { formatter.field("gt_token", &Present); } if let Some(val) = &self.value.where_clause { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::WhereClause); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("where_clause", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::ImplItem::Const(_val) => { let mut formatter = formatter.debug_struct("ImplItem::Const"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); if _val.defaultness.is_some() { formatter.field("defaultness", &Present); } formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.field("ty", Lite(&_val.ty)); formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::ImplItem::Fn(_val) => { let mut formatter = formatter.debug_struct("ImplItem::Fn"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); if _val.defaultness.is_some() { formatter.field("defaultness", &Present); } formatter.field("sig", Lite(&_val.sig)); formatter.field("block", Lite(&_val.block)); formatter.finish() } syn::ImplItem::Type(_val) => { let mut formatter = formatter.debug_struct("ImplItem::Type"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); if _val.defaultness.is_some() { formatter.field("defaultness", &Present); } formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.field("ty", Lite(&_val.ty)); formatter.finish() } syn::ImplItem::Macro(_val) => { let mut formatter = formatter.debug_struct("ImplItem::Macro"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("mac", Lite(&_val.mac)); if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } syn::ImplItem::Verbatim(_val) => { formatter.write_str("ImplItem::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ImplItemConst"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); if self.value.defaultness.is_some() { formatter.field("defaultness", &Present); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("ty", Lite(&self.value.ty)); formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ImplItemFn"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); if self.value.defaultness.is_some() { formatter.field("defaultness", &Present); } formatter.field("sig", Lite(&self.value.sig)); formatter.field("block", Lite(&self.value.block)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ImplItemMacro"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("mac", Lite(&self.value.mac)); if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ImplItemType"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); if self.value.defaultness.is_some() { formatter.field("defaultness", &Present); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { unreachable!() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Index"); formatter.field("index", Lite(&self.value.index)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Item::Const(_val) => { let mut formatter = formatter.debug_struct("Item::Const"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.field("ty", Lite(&_val.ty)); formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Item::Enum(_val) => { let mut formatter = formatter.debug_struct("Item::Enum"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); if !_val.variants.is_empty() { formatter.field("variants", Lite(&_val.variants)); } formatter.finish() } syn::Item::ExternCrate(_val) => { let mut formatter = formatter.debug_struct("Item::ExternCrate"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); if let Some(val) = &_val.rename { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::As, proc_macro2::Ident)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("rename", Print::ref_cast(val)); } formatter.finish() } syn::Item::Fn(_val) => { let mut formatter = formatter.debug_struct("Item::Fn"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("sig", Lite(&_val.sig)); formatter.field("block", Lite(&_val.block)); formatter.finish() } syn::Item::ForeignMod(_val) => { let mut formatter = formatter.debug_struct("Item::ForeignMod"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if _val.unsafety.is_some() { formatter.field("unsafety", &Present); } formatter.field("abi", Lite(&_val.abi)); if !_val.items.is_empty() { formatter.field("items", Lite(&_val.items)); } formatter.finish() } syn::Item::Impl(_val) => { let mut formatter = formatter.debug_struct("Item::Impl"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if _val.defaultness.is_some() { formatter.field("defaultness", &Present); } if _val.unsafety.is_some() { formatter.field("unsafety", &Present); } formatter.field("generics", Lite(&_val.generics)); if let Some(val) = &_val.trait_ { #[derive(RefCast)] #[repr(transparent)] struct Print((Option, syn::Path, syn::token::For)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt( &( &super::Option { present: self.0.0.is_some(), }, Lite(&self.0.1), ), formatter, )?; formatter.write_str(")")?; Ok(()) } } formatter.field("trait_", Print::ref_cast(val)); } formatter.field("self_ty", Lite(&_val.self_ty)); if !_val.items.is_empty() { formatter.field("items", Lite(&_val.items)); } formatter.finish() } syn::Item::Macro(_val) => { let mut formatter = formatter.debug_struct("Item::Macro"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.ident { #[derive(RefCast)] #[repr(transparent)] struct Print(proc_macro2::Ident); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("ident", Print::ref_cast(val)); } formatter.field("mac", Lite(&_val.mac)); if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } syn::Item::Mod(_val) => { let mut formatter = formatter.debug_struct("Item::Mod"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); if _val.unsafety.is_some() { formatter.field("unsafety", &Present); } formatter.field("ident", Lite(&_val.ident)); if let Some(val) = &_val.content { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Brace, Vec)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("content", Print::ref_cast(val)); } if _val.semi.is_some() { formatter.field("semi", &Present); } formatter.finish() } syn::Item::Static(_val) => { let mut formatter = formatter.debug_struct("Item::Static"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); match _val.mutability { syn::StaticMutability::None => {} _ => { formatter.field("mutability", Lite(&_val.mutability)); } } formatter.field("ident", Lite(&_val.ident)); formatter.field("ty", Lite(&_val.ty)); formatter.field("expr", Lite(&_val.expr)); formatter.finish() } syn::Item::Struct(_val) => { let mut formatter = formatter.debug_struct("Item::Struct"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.field("fields", Lite(&_val.fields)); if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } syn::Item::Trait(_val) => { let mut formatter = formatter.debug_struct("Item::Trait"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); if _val.unsafety.is_some() { formatter.field("unsafety", &Present); } if _val.auto_token.is_some() { formatter.field("auto_token", &Present); } if let Some(val) = &_val.restriction { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::ImplRestriction); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("restriction", Print::ref_cast(val)); } formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); if _val.colon_token.is_some() { formatter.field("colon_token", &Present); } if !_val.supertraits.is_empty() { formatter.field("supertraits", Lite(&_val.supertraits)); } if !_val.items.is_empty() { formatter.field("items", Lite(&_val.items)); } formatter.finish() } syn::Item::TraitAlias(_val) => { let mut formatter = formatter.debug_struct("Item::TraitAlias"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); if !_val.bounds.is_empty() { formatter.field("bounds", Lite(&_val.bounds)); } formatter.finish() } syn::Item::Type(_val) => { let mut formatter = formatter.debug_struct("Item::Type"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.field("ty", Lite(&_val.ty)); formatter.finish() } syn::Item::Union(_val) => { let mut formatter = formatter.debug_struct("Item::Union"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.field("fields", Lite(&_val.fields)); formatter.finish() } syn::Item::Use(_val) => { let mut formatter = formatter.debug_struct("Item::Use"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("vis", Lite(&_val.vis)); if _val.leading_colon.is_some() { formatter.field("leading_colon", &Present); } formatter.field("tree", Lite(&_val.tree)); formatter.finish() } syn::Item::Verbatim(_val) => { formatter.write_str("Item::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemConst"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("ty", Lite(&self.value.ty)); formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemEnum"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); if !self.value.variants.is_empty() { formatter.field("variants", Lite(&self.value.variants)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemExternCrate"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); if let Some(val) = &self.value.rename { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::As, proc_macro2::Ident)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("rename", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemFn"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("sig", Lite(&self.value.sig)); formatter.field("block", Lite(&self.value.block)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemForeignMod"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if self.value.unsafety.is_some() { formatter.field("unsafety", &Present); } formatter.field("abi", Lite(&self.value.abi)); if !self.value.items.is_empty() { formatter.field("items", Lite(&self.value.items)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemImpl"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if self.value.defaultness.is_some() { formatter.field("defaultness", &Present); } if self.value.unsafety.is_some() { formatter.field("unsafety", &Present); } formatter.field("generics", Lite(&self.value.generics)); if let Some(val) = &self.value.trait_ { #[derive(RefCast)] #[repr(transparent)] struct Print((Option, syn::Path, syn::token::For)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt( &( &super::Option { present: self.0.0.is_some(), }, Lite(&self.0.1), ), formatter, )?; formatter.write_str(")")?; Ok(()) } } formatter.field("trait_", Print::ref_cast(val)); } formatter.field("self_ty", Lite(&self.value.self_ty)); if !self.value.items.is_empty() { formatter.field("items", Lite(&self.value.items)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemMacro"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.ident { #[derive(RefCast)] #[repr(transparent)] struct Print(proc_macro2::Ident); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("ident", Print::ref_cast(val)); } formatter.field("mac", Lite(&self.value.mac)); if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemMod"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); if self.value.unsafety.is_some() { formatter.field("unsafety", &Present); } formatter.field("ident", Lite(&self.value.ident)); if let Some(val) = &self.value.content { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Brace, Vec)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("content", Print::ref_cast(val)); } if self.value.semi.is_some() { formatter.field("semi", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemStatic"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); match self.value.mutability { syn::StaticMutability::None => {} _ => { formatter.field("mutability", Lite(&self.value.mutability)); } } formatter.field("ident", Lite(&self.value.ident)); formatter.field("ty", Lite(&self.value.ty)); formatter.field("expr", Lite(&self.value.expr)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemStruct"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("fields", Lite(&self.value.fields)); if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemTrait"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); if self.value.unsafety.is_some() { formatter.field("unsafety", &Present); } if self.value.auto_token.is_some() { formatter.field("auto_token", &Present); } if let Some(val) = &self.value.restriction { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::ImplRestriction); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("restriction", Print::ref_cast(val)); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } if !self.value.supertraits.is_empty() { formatter.field("supertraits", Lite(&self.value.supertraits)); } if !self.value.items.is_empty() { formatter.field("items", Lite(&self.value.items)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemTraitAlias"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemType"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemUnion"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("fields", Lite(&self.value.fields)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ItemUse"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("vis", Lite(&self.value.vis)); if self.value.leading_colon.is_some() { formatter.field("leading_colon", &Present); } formatter.field("tree", Lite(&self.value.tree)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Label"); formatter.field("name", Lite(&self.value.name)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Lifetime"); formatter.field("ident", Lite(&self.value.ident)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("LifetimeParam"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("lifetime", Lite(&self.value.lifetime)); if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Lit::Str(_val) => write!(formatter, "{:?}", _val.value()), syn::Lit::ByteStr(_val) => write!(formatter, "{:?}", _val.value()), syn::Lit::CStr(_val) => write!(formatter, "{:?}", _val.value()), syn::Lit::Byte(_val) => write!(formatter, "{:?}", _val.value()), syn::Lit::Char(_val) => write!(formatter, "{:?}", _val.value()), syn::Lit::Int(_val) => write!(formatter, "{}", _val), syn::Lit::Float(_val) => write!(formatter, "{}", _val), syn::Lit::Bool(_val) => { let mut formatter = formatter.debug_struct("Lit::Bool"); formatter.field("value", Lite(&_val.value)); formatter.finish() } syn::Lit::Verbatim(_val) => { formatter.write_str("Lit::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("LitBool"); formatter.field("value", Lite(&self.value.value)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?}", self.value.value()) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?}", self.value.value()) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?}", self.value.value()) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?}", self.value.value()) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}", & self.value) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}", & self.value) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?}", self.value.value()) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Local"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("pat", Lite(&self.value.pat)); if let Some(val) = &self.value.init { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::LocalInit); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("init", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("LocalInit"); formatter.field("expr", Lite(&self.value.expr)); if let Some(val) = &self.value.diverge { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Else, Box)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("diverge", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Macro"); formatter.field("path", Lite(&self.value.path)); formatter.field("delimiter", Lite(&self.value.delimiter)); formatter.field("tokens", Lite(&self.value.tokens)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::MacroDelimiter::Paren(_val) => { formatter.write_str("MacroDelimiter::Paren")?; Ok(()) } syn::MacroDelimiter::Brace(_val) => { formatter.write_str("MacroDelimiter::Brace")?; Ok(()) } syn::MacroDelimiter::Bracket(_val) => { formatter.write_str("MacroDelimiter::Bracket")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Member::Named(_val) => { formatter.write_str("Member::Named")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::Member::Unnamed(_val) => { formatter.write_str("Member::Unnamed")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Meta::Path(_val) => { let mut formatter = formatter.debug_struct("Meta::Path"); if _val.leading_colon.is_some() { formatter.field("leading_colon", &Present); } if !_val.segments.is_empty() { formatter.field("segments", Lite(&_val.segments)); } formatter.finish() } syn::Meta::List(_val) => { let mut formatter = formatter.debug_struct("Meta::List"); formatter.field("path", Lite(&_val.path)); formatter.field("delimiter", Lite(&_val.delimiter)); formatter.field("tokens", Lite(&_val.tokens)); formatter.finish() } syn::Meta::NameValue(_val) => { let mut formatter = formatter.debug_struct("Meta::NameValue"); formatter.field("path", Lite(&_val.path)); formatter.field("value", Lite(&_val.value)); formatter.finish() } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("MetaList"); formatter.field("path", Lite(&self.value.path)); formatter.field("delimiter", Lite(&self.value.delimiter)); formatter.field("tokens", Lite(&self.value.tokens)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("MetaNameValue"); formatter.field("path", Lite(&self.value.path)); formatter.field("value", Lite(&self.value.value)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ParenthesizedGenericArguments"); if !self.value.inputs.is_empty() { formatter.field("inputs", Lite(&self.value.inputs)); } formatter.field("output", Lite(&self.value.output)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Pat::Const(_val) => { formatter.write_str("Pat::Const")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::Pat::Ident(_val) => { let mut formatter = formatter.debug_struct("Pat::Ident"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if _val.by_ref.is_some() { formatter.field("by_ref", &Present); } if _val.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("ident", Lite(&_val.ident)); if let Some(val) = &_val.subpat { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::At, Box)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("subpat", Print::ref_cast(val)); } formatter.finish() } syn::Pat::Lit(_val) => { formatter.write_str("Pat::Lit")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::Pat::Macro(_val) => { formatter.write_str("Pat::Macro")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::Pat::Or(_val) => { let mut formatter = formatter.debug_struct("Pat::Or"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if _val.leading_vert.is_some() { formatter.field("leading_vert", &Present); } if !_val.cases.is_empty() { formatter.field("cases", Lite(&_val.cases)); } formatter.finish() } syn::Pat::Paren(_val) => { let mut formatter = formatter.debug_struct("Pat::Paren"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("pat", Lite(&_val.pat)); formatter.finish() } syn::Pat::Path(_val) => { formatter.write_str("Pat::Path")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::Pat::Range(_val) => { formatter.write_str("Pat::Range")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::Pat::Reference(_val) => { let mut formatter = formatter.debug_struct("Pat::Reference"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if _val.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("pat", Lite(&_val.pat)); formatter.finish() } syn::Pat::Rest(_val) => { let mut formatter = formatter.debug_struct("Pat::Rest"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.finish() } syn::Pat::Slice(_val) => { let mut formatter = formatter.debug_struct("Pat::Slice"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if !_val.elems.is_empty() { formatter.field("elems", Lite(&_val.elems)); } formatter.finish() } syn::Pat::Struct(_val) => { let mut formatter = formatter.debug_struct("Pat::Struct"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&_val.path)); if !_val.fields.is_empty() { formatter.field("fields", Lite(&_val.fields)); } if let Some(val) = &_val.rest { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::PatRest); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("rest", Print::ref_cast(val)); } formatter.finish() } syn::Pat::Tuple(_val) => { let mut formatter = formatter.debug_struct("Pat::Tuple"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if !_val.elems.is_empty() { formatter.field("elems", Lite(&_val.elems)); } formatter.finish() } syn::Pat::TupleStruct(_val) => { let mut formatter = formatter.debug_struct("Pat::TupleStruct"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } if let Some(val) = &_val.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&_val.path)); if !_val.elems.is_empty() { formatter.field("elems", Lite(&_val.elems)); } formatter.finish() } syn::Pat::Type(_val) => { let mut formatter = formatter.debug_struct("Pat::Type"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("pat", Lite(&_val.pat)); formatter.field("ty", Lite(&_val.ty)); formatter.finish() } syn::Pat::Verbatim(_val) => { formatter.write_str("Pat::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } syn::Pat::Wild(_val) => { let mut formatter = formatter.debug_struct("Pat::Wild"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.finish() } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatIdent"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if self.value.by_ref.is_some() { formatter.field("by_ref", &Present); } if self.value.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("ident", Lite(&self.value.ident)); if let Some(val) = &self.value.subpat { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::At, Box)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("subpat", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatOr"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if self.value.leading_vert.is_some() { formatter.field("leading_vert", &Present); } if !self.value.cases.is_empty() { formatter.field("cases", Lite(&self.value.cases)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatParen"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("pat", Lite(&self.value.pat)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatReference"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if self.value.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("pat", Lite(&self.value.pat)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatRest"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatSlice"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if !self.value.elems.is_empty() { formatter.field("elems", Lite(&self.value.elems)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatStruct"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&self.value.path)); if !self.value.fields.is_empty() { formatter.field("fields", Lite(&self.value.fields)); } if let Some(val) = &self.value.rest { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::PatRest); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("rest", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatTuple"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if !self.value.elems.is_empty() { formatter.field("elems", Lite(&self.value.elems)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatTupleStruct"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&self.value.path)); if !self.value.elems.is_empty() { formatter.field("elems", Lite(&self.value.elems)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatType"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("pat", Lite(&self.value.pat)); formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PatWild"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Path"); if self.value.leading_colon.is_some() { formatter.field("leading_colon", &Present); } if !self.value.segments.is_empty() { formatter.field("segments", Lite(&self.value.segments)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::PathArguments::None => formatter.write_str("PathArguments::None"), syn::PathArguments::AngleBracketed(_val) => { let mut formatter = formatter .debug_struct("PathArguments::AngleBracketed"); if _val.colon2_token.is_some() { formatter.field("colon2_token", &Present); } if !_val.args.is_empty() { formatter.field("args", Lite(&_val.args)); } formatter.finish() } syn::PathArguments::Parenthesized(_val) => { let mut formatter = formatter .debug_struct("PathArguments::Parenthesized"); if !_val.inputs.is_empty() { formatter.field("inputs", Lite(&_val.inputs)); } formatter.field("output", Lite(&_val.output)); formatter.finish() } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PathSegment"); formatter.field("ident", Lite(&self.value.ident)); match self.value.arguments { syn::PathArguments::None => {} _ => { formatter.field("arguments", Lite(&self.value.arguments)); } } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PredicateLifetime"); formatter.field("lifetime", Lite(&self.value.lifetime)); if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PredicateType"); if let Some(val) = &self.value.lifetimes { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BoundLifetimes); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetimes", Print::ref_cast(val)); } formatter.field("bounded_ty", Lite(&self.value.bounded_ty)); if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("QSelf"); formatter.field("ty", Lite(&self.value.ty)); formatter.field("position", Lite(&self.value.position)); if self.value.as_token.is_some() { formatter.field("as_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::RangeLimits::HalfOpen(_val) => { formatter.write_str("RangeLimits::HalfOpen")?; Ok(()) } syn::RangeLimits::Closed(_val) => { formatter.write_str("RangeLimits::Closed")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Receiver"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.reference { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::And, Option)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt( { #[derive(RefCast)] #[repr(transparent)] struct Print(Option); impl Debug for Print { fn fmt( &self, formatter: &mut fmt::Formatter, ) -> fmt::Result { match &self.0 { Some(_val) => { formatter.write_str("Some(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } None => formatter.write_str("None"), } } } Print::ref_cast(&self.0.1) }, formatter, )?; formatter.write_str(")")?; Ok(()) } } formatter.field("reference", Print::ref_cast(val)); } if self.value.mutability.is_some() { formatter.field("mutability", &Present); } if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } formatter.field("ty", Lite(&self.value.ty)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::ReturnType::Default => formatter.write_str("ReturnType::Default"), syn::ReturnType::Type(_v0, _v1) => { let mut formatter = formatter.debug_tuple("ReturnType::Type"); formatter.field(Lite(_v1)); formatter.finish() } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Signature"); if self.value.constness.is_some() { formatter.field("constness", &Present); } if self.value.asyncness.is_some() { formatter.field("asyncness", &Present); } if self.value.unsafety.is_some() { formatter.field("unsafety", &Present); } if let Some(val) = &self.value.abi { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Abi); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("abi", Print::ref_cast(val)); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); if !self.value.inputs.is_empty() { formatter.field("inputs", Lite(&self.value.inputs)); } if let Some(val) = &self.value.variadic { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Variadic); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("variadic", Print::ref_cast(val)); } formatter.field("output", Lite(&self.value.output)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::StaticMutability::Mut(_val) => { formatter.write_str("StaticMutability::Mut")?; Ok(()) } syn::StaticMutability::None => formatter.write_str("StaticMutability::None"), _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Stmt::Local(_val) => { let mut formatter = formatter.debug_struct("Stmt::Local"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("pat", Lite(&_val.pat)); if let Some(val) = &_val.init { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::LocalInit); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("init", Print::ref_cast(val)); } formatter.finish() } syn::Stmt::Item(_val) => { formatter.write_str("Stmt::Item")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::Stmt::Expr(_v0, _v1) => { let mut formatter = formatter.debug_tuple("Stmt::Expr"); formatter.field(Lite(_v0)); formatter .field( &super::Option { present: _v1.is_some(), }, ); formatter.finish() } syn::Stmt::Macro(_val) => { let mut formatter = formatter.debug_struct("Stmt::Macro"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("mac", Lite(&_val.mac)); if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("StmtMacro"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("mac", Lite(&self.value.mac)); if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TraitBound"); if self.value.paren_token.is_some() { formatter.field("paren_token", &Present); } match self.value.modifier { syn::TraitBoundModifier::None => {} _ => { formatter.field("modifier", Lite(&self.value.modifier)); } } if let Some(val) = &self.value.lifetimes { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BoundLifetimes); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetimes", Print::ref_cast(val)); } formatter.field("path", Lite(&self.value.path)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::TraitBoundModifier::None => { formatter.write_str("TraitBoundModifier::None") } syn::TraitBoundModifier::Maybe(_val) => { formatter.write_str("TraitBoundModifier::Maybe")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::TraitItem::Const(_val) => { let mut formatter = formatter.debug_struct("TraitItem::Const"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); formatter.field("ty", Lite(&_val.ty)); if let Some(val) = &_val.default { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Eq, syn::Expr)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } formatter.finish() } syn::TraitItem::Fn(_val) => { let mut formatter = formatter.debug_struct("TraitItem::Fn"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("sig", Lite(&_val.sig)); if let Some(val) = &_val.default { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Block); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } syn::TraitItem::Type(_val) => { let mut formatter = formatter.debug_struct("TraitItem::Type"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("ident", Lite(&_val.ident)); formatter.field("generics", Lite(&_val.generics)); if _val.colon_token.is_some() { formatter.field("colon_token", &Present); } if !_val.bounds.is_empty() { formatter.field("bounds", Lite(&_val.bounds)); } if let Some(val) = &_val.default { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Eq, syn::Type)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } formatter.finish() } syn::TraitItem::Macro(_val) => { let mut formatter = formatter.debug_struct("TraitItem::Macro"); if !_val.attrs.is_empty() { formatter.field("attrs", Lite(&_val.attrs)); } formatter.field("mac", Lite(&_val.mac)); if _val.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } syn::TraitItem::Verbatim(_val) => { formatter.write_str("TraitItem::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TraitItemConst"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); formatter.field("ty", Lite(&self.value.ty)); if let Some(val) = &self.value.default { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Eq, syn::Expr)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TraitItemFn"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("sig", Lite(&self.value.sig)); if let Some(val) = &self.value.default { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Block); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TraitItemMacro"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("mac", Lite(&self.value.mac)); if self.value.semi_token.is_some() { formatter.field("semi_token", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TraitItemType"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("generics", Lite(&self.value.generics)); if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } if let Some(val) = &self.value.default { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Eq, syn::Type)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Type::Array(_val) => { let mut formatter = formatter.debug_struct("Type::Array"); formatter.field("elem", Lite(&_val.elem)); formatter.field("len", Lite(&_val.len)); formatter.finish() } syn::Type::BareFn(_val) => { let mut formatter = formatter.debug_struct("Type::BareFn"); if let Some(val) = &_val.lifetimes { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BoundLifetimes); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetimes", Print::ref_cast(val)); } if _val.unsafety.is_some() { formatter.field("unsafety", &Present); } if let Some(val) = &_val.abi { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Abi); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("abi", Print::ref_cast(val)); } if !_val.inputs.is_empty() { formatter.field("inputs", Lite(&_val.inputs)); } if let Some(val) = &_val.variadic { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BareVariadic); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("variadic", Print::ref_cast(val)); } formatter.field("output", Lite(&_val.output)); formatter.finish() } syn::Type::Group(_val) => { let mut formatter = formatter.debug_struct("Type::Group"); formatter.field("elem", Lite(&_val.elem)); formatter.finish() } syn::Type::ImplTrait(_val) => { let mut formatter = formatter.debug_struct("Type::ImplTrait"); if !_val.bounds.is_empty() { formatter.field("bounds", Lite(&_val.bounds)); } formatter.finish() } syn::Type::Infer(_val) => { let mut formatter = formatter.debug_struct("Type::Infer"); formatter.finish() } syn::Type::Macro(_val) => { let mut formatter = formatter.debug_struct("Type::Macro"); formatter.field("mac", Lite(&_val.mac)); formatter.finish() } syn::Type::Never(_val) => { let mut formatter = formatter.debug_struct("Type::Never"); formatter.finish() } syn::Type::Paren(_val) => { let mut formatter = formatter.debug_struct("Type::Paren"); formatter.field("elem", Lite(&_val.elem)); formatter.finish() } syn::Type::Path(_val) => { let mut formatter = formatter.debug_struct("Type::Path"); if let Some(val) = &_val.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&_val.path)); formatter.finish() } syn::Type::Ptr(_val) => { let mut formatter = formatter.debug_struct("Type::Ptr"); if _val.const_token.is_some() { formatter.field("const_token", &Present); } if _val.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("elem", Lite(&_val.elem)); formatter.finish() } syn::Type::Reference(_val) => { let mut formatter = formatter.debug_struct("Type::Reference"); if let Some(val) = &_val.lifetime { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Lifetime); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetime", Print::ref_cast(val)); } if _val.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("elem", Lite(&_val.elem)); formatter.finish() } syn::Type::Slice(_val) => { let mut formatter = formatter.debug_struct("Type::Slice"); formatter.field("elem", Lite(&_val.elem)); formatter.finish() } syn::Type::TraitObject(_val) => { let mut formatter = formatter.debug_struct("Type::TraitObject"); if _val.dyn_token.is_some() { formatter.field("dyn_token", &Present); } if !_val.bounds.is_empty() { formatter.field("bounds", Lite(&_val.bounds)); } formatter.finish() } syn::Type::Tuple(_val) => { let mut formatter = formatter.debug_struct("Type::Tuple"); if !_val.elems.is_empty() { formatter.field("elems", Lite(&_val.elems)); } formatter.finish() } syn::Type::Verbatim(_val) => { formatter.write_str("Type::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeArray"); formatter.field("elem", Lite(&self.value.elem)); formatter.field("len", Lite(&self.value.len)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeBareFn"); if let Some(val) = &self.value.lifetimes { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BoundLifetimes); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetimes", Print::ref_cast(val)); } if self.value.unsafety.is_some() { formatter.field("unsafety", &Present); } if let Some(val) = &self.value.abi { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Abi); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("abi", Print::ref_cast(val)); } if !self.value.inputs.is_empty() { formatter.field("inputs", Lite(&self.value.inputs)); } if let Some(val) = &self.value.variadic { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::BareVariadic); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("variadic", Print::ref_cast(val)); } formatter.field("output", Lite(&self.value.output)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeGroup"); formatter.field("elem", Lite(&self.value.elem)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeImplTrait"); if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeInfer"); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeMacro"); formatter.field("mac", Lite(&self.value.mac)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeNever"); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeParam"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("ident", Lite(&self.value.ident)); if self.value.colon_token.is_some() { formatter.field("colon_token", &Present); } if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } if self.value.eq_token.is_some() { formatter.field("eq_token", &Present); } if let Some(val) = &self.value.default { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Type); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("default", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::TypeParamBound::Trait(_val) => { formatter.write_str("TypeParamBound::Trait")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::TypeParamBound::Lifetime(_val) => { let mut formatter = formatter.debug_struct("TypeParamBound::Lifetime"); formatter.field("ident", Lite(&_val.ident)); formatter.finish() } syn::TypeParamBound::Verbatim(_val) => { formatter.write_str("TypeParamBound::Verbatim")?; formatter.write_str("(`")?; Display::fmt(_val, formatter)?; formatter.write_str("`)")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeParen"); formatter.field("elem", Lite(&self.value.elem)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypePath"); if let Some(val) = &self.value.qself { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::QSelf); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("qself", Print::ref_cast(val)); } formatter.field("path", Lite(&self.value.path)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypePtr"); if self.value.const_token.is_some() { formatter.field("const_token", &Present); } if self.value.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("elem", Lite(&self.value.elem)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeReference"); if let Some(val) = &self.value.lifetime { #[derive(RefCast)] #[repr(transparent)] struct Print(syn::Lifetime); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("lifetime", Print::ref_cast(val)); } if self.value.mutability.is_some() { formatter.field("mutability", &Present); } formatter.field("elem", Lite(&self.value.elem)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeSlice"); formatter.field("elem", Lite(&self.value.elem)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeTraitObject"); if self.value.dyn_token.is_some() { formatter.field("dyn_token", &Present); } if !self.value.bounds.is_empty() { formatter.field("bounds", Lite(&self.value.bounds)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeTuple"); if !self.value.elems.is_empty() { formatter.field("elems", Lite(&self.value.elems)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::UnOp::Deref(_val) => { formatter.write_str("UnOp::Deref")?; Ok(()) } syn::UnOp::Not(_val) => { formatter.write_str("UnOp::Not")?; Ok(()) } syn::UnOp::Neg(_val) => { formatter.write_str("UnOp::Neg")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseGlob"); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseGroup"); if !self.value.items.is_empty() { formatter.field("items", Lite(&self.value.items)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseName"); formatter.field("ident", Lite(&self.value.ident)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UsePath"); formatter.field("ident", Lite(&self.value.ident)); formatter.field("tree", Lite(&self.value.tree)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseRename"); formatter.field("ident", Lite(&self.value.ident)); formatter.field("rename", Lite(&self.value.rename)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::UseTree::Path(_val) => { formatter.write_str("UseTree::Path")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::UseTree::Name(_val) => { formatter.write_str("UseTree::Name")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::UseTree::Rename(_val) => { formatter.write_str("UseTree::Rename")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::UseTree::Glob(_val) => { formatter.write_str("UseTree::Glob")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::UseTree::Group(_val) => { formatter.write_str("UseTree::Group")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Variadic"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } if let Some(val) = &self.value.pat { #[derive(RefCast)] #[repr(transparent)] struct Print((Box, syn::token::Colon)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.0), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("pat", Print::ref_cast(val)); } if self.value.comma.is_some() { formatter.field("comma", &Present); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Variant"); if !self.value.attrs.is_empty() { formatter.field("attrs", Lite(&self.value.attrs)); } formatter.field("ident", Lite(&self.value.ident)); formatter.field("fields", Lite(&self.value.fields)); if let Some(val) = &self.value.discriminant { #[derive(RefCast)] #[repr(transparent)] struct Print((syn::token::Eq, syn::Expr)); impl Debug for Print { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some(")?; Debug::fmt(Lite(&self.0.1), formatter)?; formatter.write_str(")")?; Ok(()) } } formatter.field("discriminant", Print::ref_cast(val)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("VisRestricted"); if self.value.in_token.is_some() { formatter.field("in_token", &Present); } formatter.field("path", Lite(&self.value.path)); formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::Visibility::Public(_val) => { formatter.write_str("Visibility::Public")?; Ok(()) } syn::Visibility::Restricted(_val) => { let mut formatter = formatter.debug_struct("Visibility::Restricted"); if _val.in_token.is_some() { formatter.field("in_token", &Present); } formatter.field("path", Lite(&_val.path)); formatter.finish() } syn::Visibility::Inherited => formatter.write_str("Visibility::Inherited"), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("WhereClause"); if !self.value.predicates.is_empty() { formatter.field("predicates", Lite(&self.value.predicates)); } formatter.finish() } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match &self.value { syn::WherePredicate::Lifetime(_val) => { formatter.write_str("WherePredicate::Lifetime")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } syn::WherePredicate::Type(_val) => { formatter.write_str("WherePredicate::Type")?; formatter.write_str("(")?; Debug::fmt(Lite(_val), formatter)?; formatter.write_str(")")?; Ok(()) } _ => unreachable!(), } } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![abstract]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![&]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![&&]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![&=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![as]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![async]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![@]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![auto]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![await]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![become]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![box]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![break]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![^]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![^=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![:]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![,]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![const]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![continue]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![crate]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![default]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![do]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![$]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![.]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![..]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![...]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![..=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![dyn]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![else]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![enum]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![==]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![extern]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![=>]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![final]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![fn]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![for]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![>=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![>]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![if]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![impl]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![in]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![<-]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![<=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![let]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![loop]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![<]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![macro]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![match]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![-]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![-=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![mod]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![move]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![mut]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![!=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![!]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![|]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![|=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![||]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![override]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![::]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![%]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![%=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![+]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![+=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![#]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![priv]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![pub]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![?]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![->]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![ref]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![return]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![Self]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![self]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![;]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![<<]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![<<=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![>>]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![>>=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![/]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![/=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![*]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![*=]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![static]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![struct]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![super]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![~]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![trait]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![try]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![type]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![typeof]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![_]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![union]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![unsafe]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![unsized]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![use]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![virtual]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![where]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![while]") } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Token![yield]") } } syn/tests/debug/mod.rs0000644000175000017500000000642314661133735015734 0ustar jamespagejamespage#![allow( clippy::no_effect_underscore_binding, clippy::too_many_lines, clippy::used_underscore_binding )] #[rustfmt::skip] mod gen; use proc_macro2::{Ident, Literal, TokenStream}; use ref_cast::RefCast; use std::fmt::{self, Debug}; use std::ops::Deref; use syn::punctuated::Punctuated; #[derive(RefCast)] #[repr(transparent)] pub struct Lite { value: T, } #[allow(non_snake_case)] pub fn Lite(value: &T) -> &Lite { Lite::ref_cast(value) } impl Deref for Lite { type Target = T; fn deref(&self) -> &Self::Target { &self.value } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}", self.value) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}", self.value) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}", self.value) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?}", self.value) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{:?}", self.value.to_string()) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "{}", self.value) } } impl Debug for Lite { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let string = self.value.to_string(); if string.len() <= 80 { write!(formatter, "TokenStream(`{}`)", self.value) } else { formatter .debug_tuple("TokenStream") .field(&format_args!("`{}`", string)) .finish() } } } impl<'a, T> Debug for Lite<&'a T> where Lite: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(Lite(self.value), formatter) } } impl Debug for Lite> where Lite: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(Lite(&*self.value), formatter) } } impl Debug for Lite> where Lite: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_list() .entries(self.value.iter().map(Lite)) .finish() } } impl Debug for Lite> where Lite: Debug, Lite

: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut list = formatter.debug_list(); for pair in self.pairs() { let (node, punct) = pair.into_tuple(); list.entry(Lite(node)); list.entries(punct.map(Lite)); } list.finish() } } struct Present; impl Debug for Present { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Some") } } struct Option { present: bool, } impl Debug for Option { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(if self.present { "Some" } else { "None" }) } } syn/tests/repo/0000775000175000017500000000000014661133735014463 5ustar jamespagejamespagesyn/tests/repo/mod.rs0000644000175000017500000004747614661133735015630 0ustar jamespagejamespage#![allow(clippy::manual_assert)] mod progress; use self::progress::Progress; use anyhow::Result; use flate2::read::GzDecoder; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use std::collections::BTreeSet; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; use tar::Archive; use walkdir::{DirEntry, WalkDir}; const REVISION: &str = "becebb3158149a115cad8a402612e25436a7e37b"; #[rustfmt::skip] static EXCLUDE_FILES: &[&str] = &[ // TODO: explicit tail calls: `become _g()` // https://github.com/dtolnay/syn/issues/1501 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_become_expr.rs", "tests/ui/explicit-tail-calls/return-lifetime-sub.rs", // TODO: non-lifetime binders: `where for<'a, T> &'a Struct: Trait` // https://github.com/dtolnay/syn/issues/1435 "src/tools/rustfmt/tests/source/issue_5721.rs", "src/tools/rustfmt/tests/source/non-lifetime-binders.rs", "src/tools/rustfmt/tests/target/issue_5721.rs", "src/tools/rustfmt/tests/target/non-lifetime-binders.rs", "tests/rustdoc-json/non_lifetime_binders.rs", "tests/rustdoc/inline_cross/auxiliary/non_lifetime_binders.rs", "tests/rustdoc/non_lifetime_binders.rs", // TODO: return type notation: `where T: Trait` // https://github.com/dtolnay/syn/issues/1434 "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_associated_return_type_bounds.rs", "tests/ui/associated-type-bounds/return-type-notation/basic.rs", "tests/ui/associated-type-bounds/return-type-notation/unpretty-parenthesized.rs", "tests/ui/feature-gates/feature-gate-return_type_notation.rs", // TODO: lazy type alias syntax with where-clause in trailing position // https://github.com/dtolnay/syn/issues/1525 "tests/rustdoc/typedef-inner-variants-lazy_type_alias.rs", // TODO: gen blocks and functions // https://github.com/dtolnay/syn/issues/1526 "compiler/rustc_codegen_cranelift/example/gen_block_iterate.rs", "tests/ui/coroutine/async-gen-deduce-yield.rs", "tests/ui/coroutine/async-gen-yield-ty-is-unit.rs", "tests/ui/coroutine/async_gen_fn_iter.rs", "tests/ui/coroutine/gen_block_is_fused_iter.rs", "tests/ui/coroutine/gen_block_is_iter.rs", "tests/ui/coroutine/gen_block_iterate.rs", "tests/ui/coroutine/gen_fn_iter.rs", "tests/ui/coroutine/gen_fn_lifetime_capture.rs", "tests/ui/coroutine/return-types-diverge.rs", "tests/ui/higher-ranked/builtin-closure-like-bounds.rs", "tests/ui/sanitizer/cfi-coroutine.rs", // TODO: `!` as a pattern // https://github.com/dtolnay/syn/issues/1546 "tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs", // TODO: async trait bounds: `impl async Fn()` // https://github.com/dtolnay/syn/issues/1628 "src/tools/miri/tests/pass/async-closure-captures.rs", "src/tools/miri/tests/pass/async-closure-drop.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0211_async_trait_bound.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0212_const_trait_bound.rs", "src/tools/rustfmt/tests/target/asyncness.rs", "tests/codegen/async-closure-debug.rs", "tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs", "tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs", "tests/ui/async-await/async-closures/auxiliary/foreign.rs", "tests/ui/async-await/async-closures/brand.rs", "tests/ui/async-await/async-closures/captures.rs", "tests/ui/async-await/async-closures/constrained-but-no-upvars-yet.rs", "tests/ui/async-await/async-closures/drop.rs", "tests/ui/async-await/async-closures/mangle.rs", "tests/ui/async-await/async-closures/moro-example.rs", "tests/ui/async-await/async-closures/move-is-async-fn.rs", "tests/ui/async-await/async-closures/mut-ref-reborrow.rs", "tests/ui/async-await/async-closures/no-borrow-from-env.rs", "tests/ui/async-await/async-closures/overlapping-projs.rs", "tests/ui/async-await/async-closures/precise-captures.rs", "tests/ui/async-await/async-closures/refd.rs", "tests/ui/async-await/async-closures/signature-deduction.rs", "tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs", "tests/ui/async-await/async-fn/higher-ranked-async-fn.rs", "tests/ui/async-await/async-fn/impl-trait.rs", "tests/ui/async-await/async-fn/project.rs", "tests/ui/async-await/async-fn/sugar.rs", // TODO: mutable by-reference bindings (mut ref) // https://github.com/dtolnay/syn/issues/1629 "src/tools/rustfmt/tests/source/mut_ref.rs", "src/tools/rustfmt/tests/target/mut_ref.rs", "tests/ui/mut/mut-ref.rs", // TODO: postfix match // https://github.com/dtolnay/syn/issues/1630 "src/tools/rustfmt/tests/source/postfix-match/pf-match.rs", "src/tools/rustfmt/tests/target/postfix-match/pf-match.rs", "tests/pretty/postfix-match.rs", "tests/ui/match/postfix-match/no-unused-parens.rs", "tests/ui/match/postfix-match/pf-match-chain.rs", "tests/ui/match/postfix-match/postfix-match.rs", // TODO: delegation // https://github.com/dtolnay/syn/issues/1580 "tests/pretty/delegation.rs", "tests/ui/delegation/explicit-paths-in-traits-pass.rs", "tests/ui/delegation/explicit-paths-pass.rs", "tests/ui/delegation/explicit-paths-signature-pass.rs", "tests/ui/delegation/parse.rs", // TODO: for await // https://github.com/dtolnay/syn/issues/1631 "tests/ui/async-await/for-await-2015.rs", "tests/ui/async-await/for-await-passthrough.rs", "tests/ui/async-await/for-await.rs", // TODO: const trait bound: `T: const Trait` // https://github.com/dtolnay/syn/issues/1632 "tests/ui/generic-const-items/const-trait-impl.rs", "tests/ui/rfcs/rfc-2632-const-trait-impl/const-fns-are-early-bound.rs", "tests/ui/rfcs/rfc-2632-const-trait-impl/const-trait-bounds.rs", "tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs", // TODO: `|| .. .method()` "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0208_closure_range_method_call.rs", "src/tools/rustfmt/tests/source/issue-4808.rs", // Compile-fail expr parameter in const generic position: f::<1 + 2>() "tests/ui/const-generics/early/closing-args-token.rs", "tests/ui/const-generics/early/const-expression-parameter.rs", // Compile-fail variadics in not the last position of a function parameter list "tests/ui/parser/variadic-ffi-syntactic-pass.rs", // Need at least one trait in impl Trait, no such type as impl 'static "tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs", // Negative polarity trait bound: `where T: !Copy` "src/tools/rustfmt/tests/target/negative-bounds.rs", "tests/ui/traits/negative-bounds/supertrait.rs", // Lifetime bound inside for<>: `T: ~const ?for<'a: 'b> Trait<'a>` "tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-syntax.rs", // Const impl that is not a trait impl: `impl ~const T {}` "tests/ui/rfcs/rfc-2632-const-trait-impl/syntax.rs", // Lifetimes and types out of order in angle bracketed path arguments "tests/ui/parser/constraints-before-generic-args-syntactic-pass.rs", // Deprecated anonymous parameter syntax in traits "src/tools/rustfmt/tests/source/trait.rs", "src/tools/rustfmt/tests/target/trait.rs", "tests/ui/issues/issue-13105.rs", "tests/ui/issues/issue-13775.rs", "tests/ui/issues/issue-34074.rs", "tests/ui/proc-macro/trait-fn-args-2015.rs", // Deprecated where-clause location "src/tools/rustfmt/tests/source/issue_4257.rs", "src/tools/rustfmt/tests/source/issue_4911.rs", "src/tools/rustfmt/tests/target/issue_4257.rs", "src/tools/rustfmt/tests/target/issue_4911.rs", "tests/pretty/gat-bounds.rs", "tests/rustdoc/generic-associated-types/gats.rs", // Deprecated trait object syntax with parenthesized generic arguments and no dyn keyword "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0004_value_parameters_no_patterns.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0104_path_fn_trait_args.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0202_typepathfn_with_coloncolon.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0209_bare_dyn_types_with_paren_as_generic_args.rs", "src/tools/rustfmt/tests/source/attrib.rs", "src/tools/rustfmt/tests/source/closure.rs", "src/tools/rustfmt/tests/source/existential_type.rs", "src/tools/rustfmt/tests/source/fn-simple.rs", "src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs", "src/tools/rustfmt/tests/source/issue-4689/one.rs", "src/tools/rustfmt/tests/source/issue-4689/two.rs", "src/tools/rustfmt/tests/source/paths.rs", "src/tools/rustfmt/tests/source/structs.rs", "src/tools/rustfmt/tests/target/attrib.rs", "src/tools/rustfmt/tests/target/closure.rs", "src/tools/rustfmt/tests/target/existential_type.rs", "src/tools/rustfmt/tests/target/fn-simple.rs", "src/tools/rustfmt/tests/target/fn.rs", "src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs", "src/tools/rustfmt/tests/target/issue-4689/one.rs", "src/tools/rustfmt/tests/target/issue-4689/two.rs", "src/tools/rustfmt/tests/target/paths.rs", "src/tools/rustfmt/tests/target/structs.rs", "tests/codegen-units/item-collection/non-generic-closures.rs", "tests/debuginfo/recursive-enum.rs", "tests/pretty/closure-reform-pretty.rs", "tests/run-make/reproducible-build-2/reproducible-build.rs", "tests/run-make/reproducible-build/reproducible-build.rs", "tests/ui/auxiliary/typeid-intrinsic-aux1.rs", "tests/ui/auxiliary/typeid-intrinsic-aux2.rs", "tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs", "tests/ui/lifetimes/auxiliary/lifetime_bound_will_change_warning_lib.rs", "tests/ui/lifetimes/bare-trait-object-borrowck.rs", "tests/ui/lifetimes/bare-trait-object.rs", "tests/ui/parser/bounds-obj-parens.rs", // Invalid unparenthesized range pattern inside slice pattern: `[1..]` "tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs", // Various extensions to Rust syntax made up by rust-analyzer "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0058_range_pat.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0123_param_list_vararg.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0131_existential_type.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0156_fn_def_param.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0015_use_tree.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0029_range_forms.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0055_dot_dot_dot.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0068_item_modifiers.rs", "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rs", "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0038_endless_inclusive_range.rs", "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs", "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs", // Placeholder syntax for "throw expressions" "compiler/rustc_errors/src/translation.rs", "compiler/rustc_expand/src/module.rs", "compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs", "src/tools/clippy/tests/ui/needless_return.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0204_yeet_expr.rs", "tests/pretty/yeet-expr.rs", "tests/ui/try-trait/yeet-for-option.rs", "tests/ui/try-trait/yeet-for-result.rs", // Edition 2015 code using identifiers that are now keywords // TODO: some of these we should probably parse "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0159_try_macro_fallback.rs", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0160_try_macro_rules.rs", "src/tools/rustfmt/tests/source/configs/indent_style/block_call.rs", "src/tools/rustfmt/tests/source/configs/use_try_shorthand/false.rs", "src/tools/rustfmt/tests/source/configs/use_try_shorthand/true.rs", "src/tools/rustfmt/tests/source/issue_1306.rs", "src/tools/rustfmt/tests/source/try-conversion.rs", "src/tools/rustfmt/tests/target/configs/indent_style/block_call.rs", "src/tools/rustfmt/tests/target/configs/use_try_shorthand/false.rs", "src/tools/rustfmt/tests/target/issue-1681.rs", "src/tools/rustfmt/tests/target/issue_1306.rs", "tests/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs", "tests/ui/editions/edition-keywords-2015-2015.rs", "tests/ui/editions/edition-keywords-2015-2018.rs", "tests/ui/lint/lint_pre_expansion_extern_module_aux.rs", "tests/ui/macros/macro-comma-support-rpass.rs", "tests/ui/macros/try-macro.rs", "tests/ui/parser/extern-crate-async.rs", "tests/ui/try-block/try-is-identifier-edition2015.rs", // Excessive nesting "tests/ui/issues/issue-74564-if-expr-stack-overflow.rs", // Testing tools on invalid syntax "src/tools/rustfmt/tests/coverage/target/comments.rs", "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs", "src/tools/rustfmt/tests/parser/issue_4418.rs", "src/tools/rustfmt/tests/parser/stashed-diag.rs", "src/tools/rustfmt/tests/parser/stashed-diag2.rs", "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs", "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs", "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs", "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs", "src/tools/rustfmt/tests/source/type.rs", "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs", "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs", "src/tools/rustfmt/tests/target/type.rs", "tests/run-make/translation/test.rs", "tests/ui/generics/issue-94432-garbage-ice.rs", // Generated file containing a top-level expression, used with `include!` "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs", // Clippy lint lists represented as expressions "src/tools/clippy/clippy_lints/src/lib.deprecated.rs", // Not actually test cases "tests/ui/lint/expansion-time-include.rs", "tests/ui/macros/auxiliary/macro-comma-support.rs", "tests/ui/macros/auxiliary/macro-include-items-expr.rs", "tests/ui/macros/include-single-expr-helper.rs", "tests/ui/macros/include-single-expr-helper-1.rs", "tests/ui/parser/issues/auxiliary/issue-21146-inc.rs", ]; #[rustfmt::skip] static EXCLUDE_DIRS: &[&str] = &[ // Inputs that intentionally do not parse "src/tools/rust-analyzer/crates/parser/test_data/parser/err", "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err", // Inputs that lex but do not necessarily parse "src/tools/rust-analyzer/crates/parser/test_data/lexer", // Inputs that used to crash rust-analyzer, but aren't necessarily supposed to parse "src/tools/rust-analyzer/crates/syntax/test_data/parser/fuzz-failures", "src/tools/rust-analyzer/crates/syntax/test_data/reparse/fuzz-failures", // Inputs that crash rustc, making no claim about whether they are valid Rust "tests/crashes", ]; // Directories in which a .stderr implies the corresponding .rs is not expected // to work. static UI_TEST_DIRS: &[&str] = &["tests/ui", "tests/rustdoc-ui"]; pub fn for_each_rust_file(for_each: impl Fn(&Path) + Sync + Send) { let mut rs_files = BTreeSet::new(); let repo_dir = Path::new("tests/rust"); for entry in WalkDir::new(repo_dir) .into_iter() .filter_entry(base_dir_filter) { let entry = entry.unwrap(); if !entry.file_type().is_dir() { rs_files.insert(entry.into_path()); } } for ui_test_dir in UI_TEST_DIRS { for entry in WalkDir::new(repo_dir.join(ui_test_dir)) { let mut path = entry.unwrap().into_path(); if path.extension() == Some(OsStr::new("stderr")) { loop { rs_files.remove(&path.with_extension("rs")); path = path.with_extension(""); if path.extension().is_none() { break; } } } } } rs_files.par_iter().map(PathBuf::as_path).for_each(for_each); } pub fn base_dir_filter(entry: &DirEntry) -> bool { let path = entry.path(); let mut path_string = path.to_string_lossy(); if cfg!(windows) { path_string = path_string.replace('\\', "/").into(); } let path_string = if path_string == "tests/rust" { return true; } else if let Some(path) = path_string.strip_prefix("tests/rust/") { path } else { panic!("unexpected path in Rust dist: {}", path_string); }; if path.is_dir() { return !EXCLUDE_DIRS.contains(&path_string); } if path.extension() != Some(OsStr::new("rs")) { return false; } !EXCLUDE_FILES.contains(&path_string) } #[allow(dead_code)] pub fn edition(path: &Path) -> &'static str { if path.ends_with("dyn-2015-no-warnings-without-lints.rs") { "2015" } else { "2021" } } pub fn clone_rust() { let needs_clone = match fs::read_to_string("tests/rust/COMMIT") { Err(_) => true, Ok(contents) => contents.trim() != REVISION, }; if needs_clone { download_and_unpack().unwrap(); } let mut missing = String::new(); let test_src = Path::new("tests/rust"); let mut exclude_files_set = BTreeSet::new(); for exclude in EXCLUDE_FILES { if !exclude_files_set.insert(exclude) { panic!("duplicate path in EXCLUDE_FILES: {}", exclude); } for dir in EXCLUDE_DIRS { if Path::new(exclude).starts_with(dir) { panic!("excluded file {} is inside an excluded dir", exclude); } } if !test_src.join(exclude).is_file() { missing += "\ntests/rust/"; missing += exclude; } } let mut exclude_dirs_set = BTreeSet::new(); for exclude in EXCLUDE_DIRS { if !exclude_dirs_set.insert(exclude) { panic!("duplicate path in EXCLUDE_DIRS: {}", exclude); } if !test_src.join(exclude).is_dir() { missing += "\ntests/rust/"; missing += exclude; missing += "/"; } } if !missing.is_empty() { panic!("excluded test file does not exist:{}\n", missing); } } fn download_and_unpack() -> Result<()> { let url = format!( "https://github.com/rust-lang/rust/archive/{}.tar.gz", REVISION ); let response = reqwest::blocking::get(url)?.error_for_status()?; let progress = Progress::new(response); let decoder = GzDecoder::new(progress); let mut archive = Archive::new(decoder); let prefix = format!("rust-{}", REVISION); let tests_rust = Path::new("tests/rust"); if tests_rust.exists() { fs::remove_dir_all(tests_rust)?; } for entry in archive.entries()? { let mut entry = entry?; let path = entry.path()?; if path == Path::new("pax_global_header") { continue; } let relative = path.strip_prefix(&prefix)?; let out = tests_rust.join(relative); entry.unpack(&out)?; } fs::write("tests/rust/COMMIT", REVISION)?; Ok(()) } syn/tests/repo/progress.rs0000644000175000017500000000151414661133735016674 0ustar jamespagejamespageuse std::io::{Read, Result}; use std::time::{Duration, Instant}; pub struct Progress { bytes: usize, tick: Instant, stream: R, } impl Progress { pub fn new(stream: R) -> Self { Progress { bytes: 0, tick: Instant::now() + Duration::from_millis(2000), stream, } } } impl Read for Progress { fn read(&mut self, buf: &mut [u8]) -> Result { let num = self.stream.read(buf)?; self.bytes += num; let now = Instant::now(); if now > self.tick { self.tick = now + Duration::from_millis(500); errorf!("downloading... {} bytes\n", self.bytes); } Ok(num) } } impl Drop for Progress { fn drop(&mut self) { errorf!("done ({} bytes)\n", self.bytes); } } syn/tests/regression/0000775000175000017500000000000014661133735015676 5ustar jamespagejamespagesyn/tests/regression/issue1235.rs0000644000175000017500000000164414661133735017712 0ustar jamespagejamespageuse proc_macro2::{Delimiter, Group}; use quote::quote; #[test] fn main() { // Okay. Rustc allows top-level `static` with no value syntactically, but // not semantically. Syn parses as Item::Verbatim. let tokens = quote! { pub static FOO: usize; pub static BAR: usize; }; let file = syn::parse2::(tokens).unwrap(); println!("{:#?}", file); // Okay. let inner = Group::new( Delimiter::None, quote!(static FOO: usize = 0; pub static BAR: usize = 0), ); let tokens = quote!(pub #inner;); let file = syn::parse2::(tokens).unwrap(); println!("{:#?}", file); // Formerly parser crash. let inner = Group::new( Delimiter::None, quote!(static FOO: usize; pub static BAR: usize), ); let tokens = quote!(pub #inner;); let file = syn::parse2::(tokens).unwrap(); println!("{:#?}", file); } syn/tests/regression/issue1108.rs0000644000175000017500000000014114661133735017700 0ustar jamespagejamespage#[test] fn issue1108() { let data = "impl>::x for"; let _ = syn::parse_file(data); } syn/tests/test_parse_quote.rs0000644000175000017500000000676414661133735017465 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use syn::punctuated::Punctuated; use syn::{parse_quote, Attribute, Field, Lit, Pat, Stmt, Token}; #[test] fn test_attribute() { let attr: Attribute = parse_quote!(#[test]); snapshot!(attr, @r###" Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "test", }, ], }, } "###); let attr: Attribute = parse_quote!(#![no_std]); snapshot!(attr, @r###" Attribute { style: AttrStyle::Inner, meta: Meta::Path { segments: [ PathSegment { ident: "no_std", }, ], }, } "###); } #[test] fn test_field() { let field: Field = parse_quote!(pub enabled: bool); snapshot!(field, @r###" Field { vis: Visibility::Public, ident: Some("enabled"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "bool", }, ], }, }, } "###); let field: Field = parse_quote!(primitive::bool); snapshot!(field, @r###" Field { vis: Visibility::Inherited, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "primitive", }, Token![::], PathSegment { ident: "bool", }, ], }, }, } "###); } #[test] fn test_pat() { let pat: Pat = parse_quote!(Some(false) | None); snapshot!(&pat, @r###" Pat::Or { cases: [ Pat::TupleStruct { path: Path { segments: [ PathSegment { ident: "Some", }, ], }, elems: [ Pat::Lit(ExprLit { lit: Lit::Bool { value: false, }, }), ], }, Token![|], Pat::Ident { ident: "None", }, ], } "###); let boxed_pat: Box = parse_quote!(Some(false) | None); assert_eq!(*boxed_pat, pat); } #[test] fn test_punctuated() { let punctuated: Punctuated = parse_quote!(true | true); snapshot!(punctuated, @r###" [ Lit::Bool { value: true, }, Token![|], Lit::Bool { value: true, }, ] "###); let punctuated: Punctuated = parse_quote!(true | true |); snapshot!(punctuated, @r###" [ Lit::Bool { value: true, }, Token![|], Lit::Bool { value: true, }, Token![|], ] "###); } #[test] fn test_vec_stmt() { let stmts: Vec = parse_quote! { let _; true }; snapshot!(stmts, @r###" [ Stmt::Local { pat: Pat::Wild, }, Stmt::Expr( Expr::Lit { lit: Lit::Bool { value: true, }, }, None, ), ] "###); } syn/tests/test_ident.rs0000644000175000017500000000245014661133735016225 0ustar jamespagejamespageuse proc_macro2::{Ident, Span, TokenStream}; use std::str::FromStr; use syn::Result; #[track_caller] fn parse(s: &str) -> Result { syn::parse2(TokenStream::from_str(s).unwrap()) } #[track_caller] fn new(s: &str) -> Ident { Ident::new(s, Span::call_site()) } #[test] fn ident_parse() { parse("String").unwrap(); } #[test] fn ident_parse_keyword() { parse("abstract").unwrap_err(); } #[test] fn ident_parse_empty() { parse("").unwrap_err(); } #[test] fn ident_parse_lifetime() { parse("'static").unwrap_err(); } #[test] fn ident_parse_underscore() { parse("_").unwrap_err(); } #[test] fn ident_parse_number() { parse("255").unwrap_err(); } #[test] fn ident_parse_invalid() { parse("a#").unwrap_err(); } #[test] fn ident_new() { new("String"); } #[test] fn ident_new_keyword() { new("abstract"); } #[test] #[should_panic(expected = "use Option")] fn ident_new_empty() { new(""); } #[test] #[should_panic(expected = "not a valid Ident")] fn ident_new_lifetime() { new("'static"); } #[test] fn ident_new_underscore() { new("_"); } #[test] #[should_panic(expected = "use Literal instead")] fn ident_new_number() { new("255"); } #[test] #[should_panic(expected = "\"a#\" is not a valid Ident")] fn ident_new_invalid() { new("a#"); } syn/tests/test_attribute.rs0000644000175000017500000001051514661133735017126 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use syn::parse::Parser; use syn::{Attribute, Meta}; #[test] fn test_meta_item_word() { let meta = test("#[foo]"); snapshot!(meta, @r###" Meta::Path { segments: [ PathSegment { ident: "foo", }, ], } "###); } #[test] fn test_meta_item_name_value() { let meta = test("#[foo = 5]"); snapshot!(meta, @r###" Meta::NameValue { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, value: Expr::Lit { lit: 5, }, } "###); } #[test] fn test_meta_item_bool_value() { let meta = test("#[foo = true]"); snapshot!(meta, @r###" Meta::NameValue { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, value: Expr::Lit { lit: Lit::Bool { value: true, }, }, } "###); let meta = test("#[foo = false]"); snapshot!(meta, @r###" Meta::NameValue { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, value: Expr::Lit { lit: Lit::Bool { value: false, }, }, } "###); } #[test] fn test_meta_item_list_lit() { let meta = test("#[foo(5)]"); snapshot!(meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`5`), } "###); } #[test] fn test_meta_item_list_word() { let meta = test("#[foo(bar)]"); snapshot!(meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`bar`), } "###); } #[test] fn test_meta_item_list_name_value() { let meta = test("#[foo(bar = 5)]"); snapshot!(meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`bar = 5`), } "###); } #[test] fn test_meta_item_list_bool_value() { let meta = test("#[foo(bar = true)]"); snapshot!(meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`bar = true`), } "###); } #[test] fn test_meta_item_multiple() { let meta = test("#[foo(word, name = 5, list(name2 = 6), word2)]"); snapshot!(meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`word , name = 5 , list (name2 = 6) , word2`), } "###); } #[test] fn test_bool_lit() { let meta = test("#[foo(true)]"); snapshot!(meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "foo", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`true`), } "###); } #[test] fn test_negative_lit() { let meta = test("#[form(min = -1, max = 200)]"); snapshot!(meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "form", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`min = - 1 , max = 200`), } "###); } fn test(input: &str) -> Meta { let attrs = Attribute::parse_outer.parse_str(input).unwrap(); assert_eq!(attrs.len(), 1); let attr = attrs.into_iter().next().unwrap(); attr.meta } syn/tests/test_iterators.rs0000644000175000017500000000335614661133735017144 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] use syn::punctuated::{Pair, Punctuated}; use syn::Token; #[macro_use] mod macros; macro_rules! check_exact_size_iterator { ($iter:expr) => {{ let iter = $iter; let size_hint = iter.size_hint(); let len = iter.len(); let count = iter.count(); assert_eq!(len, count); assert_eq!(size_hint, (count, Some(count))); }}; } #[test] fn pairs() { let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); check_exact_size_iterator!(p.pairs()); check_exact_size_iterator!(p.pairs_mut()); check_exact_size_iterator!(p.into_pairs()); let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); assert_eq!(p.pairs().next_back().map(Pair::into_value), Some(&4)); assert_eq!( p.pairs_mut().next_back().map(Pair::into_value), Some(&mut 4) ); assert_eq!(p.into_pairs().next_back().map(Pair::into_value), Some(4)); } #[test] fn iter() { let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); check_exact_size_iterator!(p.iter()); check_exact_size_iterator!(p.iter_mut()); check_exact_size_iterator!(p.into_iter()); let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); assert_eq!(p.iter().next_back(), Some(&4)); assert_eq!(p.iter_mut().next_back(), Some(&mut 4)); assert_eq!(p.into_iter().next_back(), Some(4)); } #[test] fn may_dangle() { let p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); for element in &p { if *element == 2 { drop(p); break; } } let mut p: Punctuated<_, Token![,]> = punctuated!(2, 3, 4); for element in &mut p { if *element == 2 { drop(p); break; } } } syn/tests/test_generics.rs0000644000175000017500000002156114661133735016725 0ustar jamespagejamespage#![allow( clippy::manual_let_else, clippy::too_many_lines, clippy::uninlined_format_args )] #[macro_use] mod macros; use quote::quote; use syn::{DeriveInput, ItemFn, TypeParamBound, WhereClause, WherePredicate}; #[test] fn test_split_for_impl() { let input = quote! { struct S<'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug; }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "S", generics: Generics { lt_token: Some, params: [ GenericParam::Lifetime(LifetimeParam { lifetime: Lifetime { ident: "a", }, }), Token![,], GenericParam::Lifetime(LifetimeParam { lifetime: Lifetime { ident: "b", }, colon_token: Some, bounds: [ Lifetime { ident: "a", }, ], }), Token![,], GenericParam::Type(TypeParam { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "may_dangle", }, ], }, }, ], ident: "T", colon_token: Some, bounds: [ TypeParamBound::Lifetime { ident: "a", }, ], eq_token: Some, default: Some(Type::Tuple), }), ], gt_token: Some, where_clause: Some(WhereClause { predicates: [ WherePredicate::Type(PredicateType { bounded_ty: Type::Path { path: Path { segments: [ PathSegment { ident: "T", }, ], }, }, bounds: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Debug", }, ], }, }), ], }), ], }), }, data: Data::Struct { fields: Fields::Unit, semi_token: Some, }, } "###); let generics = input.generics; let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let generated = quote! { impl #impl_generics MyTrait for Test #ty_generics #where_clause {} }; let expected = quote! { impl<'a, 'b: 'a, #[may_dangle] T: 'a> MyTrait for Test<'a, 'b, T> where T: Debug {} }; assert_eq!(generated.to_string(), expected.to_string()); let turbofish = ty_generics.as_turbofish(); let generated = quote! { Test #turbofish }; let expected = quote! { Test::<'a, 'b, T> }; assert_eq!(generated.to_string(), expected.to_string()); } #[test] fn test_ty_param_bound() { let tokens = quote!('a); snapshot!(tokens as TypeParamBound, @r###" TypeParamBound::Lifetime { ident: "a", } "###); let tokens = quote!('_); snapshot!(tokens as TypeParamBound, @r###" TypeParamBound::Lifetime { ident: "_", } "###); let tokens = quote!(Debug); snapshot!(tokens as TypeParamBound, @r###" TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Debug", }, ], }, }) "###); let tokens = quote!(?Sized); snapshot!(tokens as TypeParamBound, @r###" TypeParamBound::Trait(TraitBound { modifier: TraitBoundModifier::Maybe, path: Path { segments: [ PathSegment { ident: "Sized", }, ], }, }) "###); } #[test] fn test_fn_precedence_in_where_clause() { // This should parse as two separate bounds, `FnOnce() -> i32` and `Send` - not // `FnOnce() -> (i32 + Send)`. let input = quote! { fn f() where G: FnOnce() -> i32 + Send, { } }; snapshot!(input as ItemFn, @r###" ItemFn { vis: Visibility::Inherited, sig: Signature { ident: "f", generics: Generics { lt_token: Some, params: [ GenericParam::Type(TypeParam { ident: "G", }), ], gt_token: Some, where_clause: Some(WhereClause { predicates: [ WherePredicate::Type(PredicateType { bounded_ty: Type::Path { path: Path { segments: [ PathSegment { ident: "G", }, ], }, }, bounds: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "FnOnce", arguments: PathArguments::Parenthesized { output: ReturnType::Type( Type::Path { path: Path { segments: [ PathSegment { ident: "i32", }, ], }, }, ), }, }, ], }, }), Token![+], TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Send", }, ], }, }), ], }), Token![,], ], }), }, output: ReturnType::Default, }, block: Block { stmts: [], }, } "###); let where_clause = input.sig.generics.where_clause.as_ref().unwrap(); assert_eq!(where_clause.predicates.len(), 1); let predicate = match &where_clause.predicates[0] { WherePredicate::Type(pred) => pred, _ => panic!("wrong predicate kind"), }; assert_eq!(predicate.bounds.len(), 2, "{:#?}", predicate.bounds); let first_bound = &predicate.bounds[0]; assert_eq!(quote!(#first_bound).to_string(), "FnOnce () -> i32"); let second_bound = &predicate.bounds[1]; assert_eq!(quote!(#second_bound).to_string(), "Send"); } #[test] fn test_where_clause_at_end_of_input() { let input = quote! { where }; snapshot!(input as WhereClause, @"WhereClause"); assert_eq!(input.predicates.len(), 0); } syn/tests/test_receiver.rs0000644000175000017500000002014214661133735016724 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use syn::{parse_quote, TraitItemFn}; #[test] fn test_by_value() { let TraitItemFn { sig, .. } = parse_quote! { fn by_value(self: Self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }) "###); } #[test] fn test_by_mut_value() { let TraitItemFn { sig, .. } = parse_quote! { fn by_mut(mut self: Self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { mutability: Some, colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }) "###); } #[test] fn test_by_ref() { let TraitItemFn { sig, .. } = parse_quote! { fn by_ref(self: &Self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Reference { elem: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }, }) "###); } #[test] fn test_by_box() { let TraitItemFn { sig, .. } = parse_quote! { fn by_box(self: Box); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Box", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }), ], }, }, ], }, }, }) "###); } #[test] fn test_by_pin() { let TraitItemFn { sig, .. } = parse_quote! { fn by_pin(self: Pin); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Pin", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }), ], }, }, ], }, }, }) "###); } #[test] fn test_explicit_type() { let TraitItemFn { sig, .. } = parse_quote! { fn explicit_type(self: Pin); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Pin", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "MyType", }, ], }, }), ], }, }, ], }, }, }) "###); } #[test] fn test_value_shorthand() { let TraitItemFn { sig, .. } = parse_quote! { fn value_shorthand(self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }) "###); } #[test] fn test_mut_value_shorthand() { let TraitItemFn { sig, .. } = parse_quote! { fn mut_value_shorthand(mut self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { mutability: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }) "###); } #[test] fn test_ref_shorthand() { let TraitItemFn { sig, .. } = parse_quote! { fn ref_shorthand(&self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { reference: Some(None), ty: Type::Reference { elem: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }, }) "###); } #[test] fn test_ref_shorthand_with_lifetime() { let TraitItemFn { sig, .. } = parse_quote! { fn ref_shorthand(&'a self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { reference: Some(Some(Lifetime { ident: "a", })), ty: Type::Reference { lifetime: Some(Lifetime { ident: "a", }), elem: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }, }) "###); } #[test] fn test_ref_mut_shorthand() { let TraitItemFn { sig, .. } = parse_quote! { fn ref_mut_shorthand(&mut self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { reference: Some(None), mutability: Some, ty: Type::Reference { mutability: Some, elem: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }, }) "###); } #[test] fn test_ref_mut_shorthand_with_lifetime() { let TraitItemFn { sig, .. } = parse_quote! { fn ref_mut_shorthand(&'a mut self); }; snapshot!(&sig.inputs[0], @r###" FnArg::Receiver(Receiver { reference: Some(Some(Lifetime { ident: "a", })), mutability: Some, ty: Type::Reference { lifetime: Some(Lifetime { ident: "a", }), mutability: Some, elem: Type::Path { path: Path { segments: [ PathSegment { ident: "Self", }, ], }, }, }, }) "###); } syn/tests/test_visibility.rs0000644000175000017500000001171414661133735017314 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::quote; use syn::parse::{Parse, ParseStream}; use syn::{DeriveInput, Result, Visibility}; #[derive(Debug)] struct VisRest { vis: Visibility, rest: TokenStream, } impl Parse for VisRest { fn parse(input: ParseStream) -> Result { Ok(VisRest { vis: input.parse()?, rest: input.parse()?, }) } } macro_rules! assert_vis_parse { ($input:expr, Ok($p:pat)) => { assert_vis_parse!($input, Ok($p) + ""); }; ($input:expr, Ok($p:pat) + $rest:expr) => { let expected = $rest.parse::().unwrap(); let parse: VisRest = syn::parse_str($input).unwrap(); match parse.vis { $p => {} _ => panic!("expected {}, got {:?}", stringify!($p), parse.vis), } // NOTE: Round-trips through `to_string` to avoid potential whitespace // diffs. assert_eq!(parse.rest.to_string(), expected.to_string()); }; ($input:expr, Err) => { syn::parse2::($input.parse().unwrap()).unwrap_err(); }; } #[test] fn test_pub() { assert_vis_parse!("pub", Ok(Visibility::Public(_))); } #[test] fn test_inherited() { assert_vis_parse!("", Ok(Visibility::Inherited)); } #[test] fn test_in() { assert_vis_parse!("pub(in foo::bar)", Ok(Visibility::Restricted(_))); } #[test] fn test_pub_crate() { assert_vis_parse!("pub(crate)", Ok(Visibility::Restricted(_))); } #[test] fn test_pub_self() { assert_vis_parse!("pub(self)", Ok(Visibility::Restricted(_))); } #[test] fn test_pub_super() { assert_vis_parse!("pub(super)", Ok(Visibility::Restricted(_))); } #[test] fn test_missing_in() { assert_vis_parse!("pub(foo::bar)", Ok(Visibility::Public(_)) + "(foo::bar)"); } #[test] fn test_missing_in_path() { assert_vis_parse!("pub(in)", Err); } #[test] fn test_crate_path() { assert_vis_parse!( "pub(crate::A, crate::B)", Ok(Visibility::Public(_)) + "(crate::A, crate::B)" ); } #[test] fn test_junk_after_in() { assert_vis_parse!("pub(in some::path @@garbage)", Err); } #[test] fn test_inherited_vis_named_field() { // mimics `struct S { $vis $field: () }` where $vis is empty let tokens = TokenStream::from_iter([ TokenTree::Ident(Ident::new("struct", Span::call_site())), TokenTree::Ident(Ident::new("S", Span::call_site())), TokenTree::Group(Group::new( Delimiter::Brace, TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())), TokenTree::Group(Group::new(Delimiter::None, quote!(f))), TokenTree::Punct(Punct::new(':', Spacing::Alone)), TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), ]), )), ]); snapshot!(tokens as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Named { named: [ Field { vis: Visibility::Inherited, ident: Some("f"), colon_token: Some, ty: Type::Tuple, }, ], }, }, } "###); } #[test] fn test_inherited_vis_unnamed_field() { // mimics `struct S($vis $ty);` where $vis is empty let tokens = TokenStream::from_iter([ TokenTree::Ident(Ident::new("struct", Span::call_site())), TokenTree::Ident(Ident::new("S", Span::call_site())), TokenTree::Group(Group::new( Delimiter::Parenthesis, TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())), TokenTree::Group(Group::new(Delimiter::None, quote!(str))), ]), )), TokenTree::Punct(Punct::new(';', Spacing::Alone)), ]); snapshot!(tokens as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unnamed { unnamed: [ Field { vis: Visibility::Inherited, ty: Type::Group { elem: Type::Path { path: Path { segments: [ PathSegment { ident: "str", }, ], }, }, }, }, ], }, semi_token: Some, }, } "###); } syn/tests/test_precedence.rs0000644000175000017500000004260014661133735017220 0ustar jamespagejamespage// This test does the following for every file in the rust-lang/rust repo: // // 1. Parse the file using syn into a syn::File. // 2. Extract every syn::Expr from the file. // 3. Print each expr to a string of source code. // 4. Parse the source code using librustc_parse into a rustc_ast::Expr. // 5. For both the syn::Expr and rustc_ast::Expr, crawl the syntax tree to // insert parentheses surrounding every subexpression. // 6. Serialize the fully parenthesized syn::Expr to a string of source code. // 7. Parse the fully parenthesized source code using librustc_parse. // 8. Compare the rustc_ast::Expr resulting from parenthesizing using rustc data // structures vs syn data structures, ignoring spans. If they agree, rustc's // parser and syn's parser have identical handling of expression precedence. #![cfg(not(syn_disable_nightly_tests))] #![cfg(not(miri))] #![recursion_limit = "1024"] #![feature(rustc_private)] #![allow( clippy::blocks_in_conditions, clippy::doc_markdown, clippy::explicit_deref_methods, clippy::let_underscore_untyped, clippy::manual_assert, clippy::manual_let_else, clippy::match_like_matches_macro, clippy::match_wildcard_for_single_variants, clippy::too_many_lines, clippy::uninlined_format_args )] extern crate rustc_ast; extern crate rustc_ast_pretty; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_span; extern crate smallvec; extern crate thin_vec; use crate::common::eq::SpanlessEq; use crate::common::parse; use quote::ToTokens; use rustc_ast::ast; use rustc_ast::ptr::P; use rustc_ast_pretty::pprust; use rustc_span::edition::Edition; use std::fs; use std::path::Path; use std::process; use std::sync::atomic::{AtomicUsize, Ordering}; #[macro_use] mod macros; mod common; mod repo; #[test] fn test_rustc_precedence() { common::rayon_init(); repo::clone_rust(); let abort_after = common::abort_after(); if abort_after == 0 { panic!("skipping all precedence tests"); } let passed = AtomicUsize::new(0); let failed = AtomicUsize::new(0); repo::for_each_rust_file(|path| { let content = fs::read_to_string(path).unwrap(); let (l_passed, l_failed) = match syn::parse_file(&content) { Ok(file) => { let edition = repo::edition(path).parse().unwrap(); let exprs = collect_exprs(file); let (l_passed, l_failed) = test_expressions(path, edition, exprs); errorf!( "=== {}: {} passed | {} failed\n", path.display(), l_passed, l_failed, ); (l_passed, l_failed) } Err(msg) => { errorf!("\nFAIL {} - syn failed to parse: {}\n", path.display(), msg); (0, 1) } }; passed.fetch_add(l_passed, Ordering::Relaxed); let prev_failed = failed.fetch_add(l_failed, Ordering::Relaxed); if prev_failed + l_failed >= abort_after { process::exit(1); } }); let passed = passed.load(Ordering::Relaxed); let failed = failed.load(Ordering::Relaxed); errorf!("\n===== Precedence Test Results =====\n"); errorf!("{} passed | {} failed\n", passed, failed); if failed > 0 { panic!("{} failures", failed); } } fn test_expressions(path: &Path, edition: Edition, exprs: Vec) -> (usize, usize) { let mut passed = 0; let mut failed = 0; rustc_span::create_session_if_not_set_then(edition, |_| { for expr in exprs { let source_code = expr.to_token_stream().to_string(); let librustc_ast = if let Some(e) = librustc_parse_and_rewrite(&source_code) { e } else { failed += 1; errorf!( "\nFAIL {} - librustc failed to parse original\n", path.display(), ); continue; }; let syn_parenthesized_code = syn_parenthesize(expr.clone()).to_token_stream().to_string(); let syn_ast = if let Some(e) = parse::librustc_expr(&syn_parenthesized_code) { e } else { failed += 1; errorf!( "\nFAIL {} - librustc failed to parse parenthesized\n", path.display(), ); continue; }; if !SpanlessEq::eq(&syn_ast, &librustc_ast) { failed += 1; let syn_pretty = pprust::expr_to_string(&syn_ast); let librustc_pretty = pprust::expr_to_string(&librustc_ast); errorf!( "\nFAIL {}\n{}\nsyn != rustc\n{}\n", path.display(), syn_pretty, librustc_pretty, ); continue; } let expr_invisible = make_parens_invisible(expr); let Ok(reparsed_expr_invisible) = syn::parse2(expr_invisible.to_token_stream()) else { failed += 1; errorf!( "\nFAIL {} - syn failed to parse invisible delimiters\n{}\n", path.display(), source_code, ); continue; }; if expr_invisible != reparsed_expr_invisible { failed += 1; errorf!( "\nFAIL {} - mismatch after parsing invisible delimiters\n{}\n", path.display(), source_code, ); continue; } passed += 1; } }); (passed, failed) } fn librustc_parse_and_rewrite(input: &str) -> Option> { parse::librustc_expr(input).map(librustc_parenthesize) } fn librustc_parenthesize(mut librustc_expr: P) -> P { use rustc_ast::ast::{ AssocItem, AssocItemKind, Attribute, BinOpKind, Block, BorrowKind, BoundConstness, Expr, ExprField, ExprKind, GenericArg, GenericBound, Local, LocalKind, Pat, Stmt, StmtKind, StructExpr, StructRest, TraitBoundModifiers, Ty, }; use rustc_ast::mut_visit::{noop_flat_map_item, MutVisitor}; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_span::DUMMY_SP; use smallvec::SmallVec; use std::mem; use std::ops::DerefMut; use thin_vec::ThinVec; struct FullyParenthesize; fn contains_let_chain(expr: &Expr) -> bool { match &expr.kind { ExprKind::Let(..) => true, ExprKind::Binary(binop, left, right) => { binop.node == BinOpKind::And && (contains_let_chain(left) || contains_let_chain(right)) } _ => false, } } fn flat_map_field(mut f: ExprField, vis: &mut T) -> Vec { if f.is_shorthand { noop_visit_expr(&mut f.expr, vis); } else { vis.visit_expr(&mut f.expr); } vec![f] } fn flat_map_stmt(stmt: Stmt, vis: &mut T) -> Vec { let kind = match stmt.kind { // Don't wrap toplevel expressions in statements. StmtKind::Expr(mut e) => { noop_visit_expr(&mut e, vis); StmtKind::Expr(e) } StmtKind::Semi(mut e) => { noop_visit_expr(&mut e, vis); StmtKind::Semi(e) } s => s, }; vec![Stmt { kind, ..stmt }] } fn noop_visit_expr(e: &mut Expr, vis: &mut T) { match &mut e.kind { ExprKind::AddrOf(BorrowKind::Raw, ..) => {} ExprKind::Struct(expr) => { let StructExpr { qself, path, fields, rest, } = expr.deref_mut(); vis.visit_qself(qself); vis.visit_path(path); fields.flat_map_in_place(|field| flat_map_field(field, vis)); if let StructRest::Base(rest) = rest { vis.visit_expr(rest); } } _ => rustc_ast::mut_visit::noop_visit_expr(e, vis), } } impl MutVisitor for FullyParenthesize { fn visit_expr(&mut self, e: &mut P) { noop_visit_expr(e, self); match e.kind { ExprKind::Block(..) | ExprKind::If(..) | ExprKind::Let(..) => {} ExprKind::Binary(..) if contains_let_chain(e) => {} _ => { let inner = mem::replace( e, P(Expr { id: ast::DUMMY_NODE_ID, kind: ExprKind::Dummy, span: DUMMY_SP, attrs: ThinVec::new(), tokens: None, }), ); e.kind = ExprKind::Paren(inner); } } } fn visit_generic_arg(&mut self, arg: &mut GenericArg) { match arg { GenericArg::Lifetime(_lifetime) => {} GenericArg::Type(arg) => self.visit_ty(arg), // Don't wrap unbraced const generic arg as that's invalid syntax. GenericArg::Const(anon_const) => { if let ExprKind::Block(..) = &mut anon_const.value.kind { noop_visit_expr(&mut anon_const.value, self); } } } } fn visit_param_bound(&mut self, bound: &mut GenericBound) { match bound { GenericBound::Trait( _, TraitBoundModifiers { constness: BoundConstness::Maybe(_), .. }, ) | GenericBound::Outlives(..) | GenericBound::Use(..) => {} GenericBound::Trait(ty, _modifier) => self.visit_poly_trait_ref(ty), } } fn visit_block(&mut self, block: &mut P) { self.visit_id(&mut block.id); block .stmts .flat_map_in_place(|stmt| flat_map_stmt(stmt, self)); self.visit_span(&mut block.span); } fn visit_local(&mut self, local: &mut P) { match &mut local.kind { LocalKind::Decl => {} LocalKind::Init(init) => { self.visit_expr(init); } LocalKind::InitElse(init, els) => { self.visit_expr(init); self.visit_block(els); } } } fn flat_map_trait_item(&mut self, item: P) -> SmallVec<[P; 1]> { match &item.kind { AssocItemKind::Const(const_item) if !const_item.generics.params.is_empty() || !const_item.generics.where_clause.predicates.is_empty() => { SmallVec::from([item]) } _ => noop_flat_map_item(item, self), } } fn flat_map_impl_item(&mut self, item: P) -> SmallVec<[P; 1]> { match &item.kind { AssocItemKind::Const(const_item) if !const_item.generics.params.is_empty() || !const_item.generics.where_clause.predicates.is_empty() => { SmallVec::from([item]) } _ => noop_flat_map_item(item, self), } } // We don't want to look at expressions that might appear in patterns or // types yet. We'll look into comparing those in the future. For now // focus on expressions appearing in other places. fn visit_pat(&mut self, pat: &mut P) { let _ = pat; } fn visit_ty(&mut self, ty: &mut P) { let _ = ty; } fn visit_attribute(&mut self, attr: &mut Attribute) { let _ = attr; } } let mut folder = FullyParenthesize; folder.visit_expr(&mut librustc_expr); librustc_expr } fn syn_parenthesize(syn_expr: syn::Expr) -> syn::Expr { use syn::fold::{fold_expr, fold_generic_argument, Fold}; use syn::{token, BinOp, Expr, ExprParen, GenericArgument, MetaNameValue, Pat, Stmt, Type}; struct FullyParenthesize; fn parenthesize(expr: Expr) -> Expr { Expr::Paren(ExprParen { attrs: Vec::new(), expr: Box::new(expr), paren_token: token::Paren::default(), }) } fn needs_paren(expr: &Expr) -> bool { match expr { Expr::Group(_) => unreachable!(), Expr::If(_) | Expr::Unsafe(_) | Expr::Block(_) | Expr::Let(_) => false, Expr::Binary(_) => !contains_let_chain(expr), _ => true, } } fn contains_let_chain(expr: &Expr) -> bool { match expr { Expr::Let(_) => true, Expr::Binary(expr) => { matches!(expr.op, BinOp::And(_)) && (contains_let_chain(&expr.left) || contains_let_chain(&expr.right)) } _ => false, } } impl Fold for FullyParenthesize { fn fold_expr(&mut self, expr: Expr) -> Expr { let needs_paren = needs_paren(&expr); let folded = fold_expr(self, expr); if needs_paren { parenthesize(folded) } else { folded } } fn fold_generic_argument(&mut self, arg: GenericArgument) -> GenericArgument { match arg { GenericArgument::Const(arg) => GenericArgument::Const(match arg { Expr::Block(_) => fold_expr(self, arg), // Don't wrap unbraced const generic arg as that's invalid syntax. _ => arg, }), _ => fold_generic_argument(self, arg), } } fn fold_stmt(&mut self, stmt: Stmt) -> Stmt { match stmt { // Don't wrap toplevel expressions in statements. Stmt::Expr(Expr::Verbatim(_), Some(_)) => stmt, Stmt::Expr(e, semi) => Stmt::Expr(fold_expr(self, e), semi), s => s, } } fn fold_meta_name_value(&mut self, meta: MetaNameValue) -> MetaNameValue { // Don't turn #[p = "..."] into #[p = ("...")]. meta } // We don't want to look at expressions that might appear in patterns or // types yet. We'll look into comparing those in the future. For now // focus on expressions appearing in other places. fn fold_pat(&mut self, pat: Pat) -> Pat { pat } fn fold_type(&mut self, ty: Type) -> Type { ty } } let mut folder = FullyParenthesize; folder.fold_expr(syn_expr) } fn make_parens_invisible(expr: syn::Expr) -> syn::Expr { use syn::fold::{fold_expr, fold_stmt, Fold}; use syn::{token, Expr, ExprGroup, ExprParen, Stmt}; struct MakeParensInvisible; impl Fold for MakeParensInvisible { fn fold_expr(&mut self, mut expr: Expr) -> Expr { if let Expr::Paren(paren) = expr { expr = Expr::Group(ExprGroup { attrs: paren.attrs, group_token: token::Group(paren.paren_token.span.join()), expr: paren.expr, }); } fold_expr(self, expr) } fn fold_stmt(&mut self, stmt: Stmt) -> Stmt { if let Stmt::Expr(expr @ (Expr::Binary(_) | Expr::Cast(_)), None) = stmt { Stmt::Expr( Expr::Paren(ExprParen { attrs: Vec::new(), paren_token: token::Paren::default(), expr: Box::new(fold_expr(self, expr)), }), None, ) } else { fold_stmt(self, stmt) } } } let mut folder = MakeParensInvisible; folder.fold_expr(expr) } /// Walk through a crate collecting all expressions we can find in it. fn collect_exprs(file: syn::File) -> Vec { use syn::fold::Fold; use syn::punctuated::Punctuated; use syn::{token, ConstParam, Expr, ExprTuple, Pat, Path}; struct CollectExprs(Vec); impl Fold for CollectExprs { fn fold_expr(&mut self, expr: Expr) -> Expr { match expr { Expr::Verbatim(_) => {} _ => self.0.push(expr), } Expr::Tuple(ExprTuple { attrs: vec![], elems: Punctuated::new(), paren_token: token::Paren::default(), }) } fn fold_pat(&mut self, pat: Pat) -> Pat { pat } fn fold_path(&mut self, path: Path) -> Path { // Skip traversing into const generic path arguments path } fn fold_const_param(&mut self, const_param: ConstParam) -> ConstParam { const_param } } let mut folder = CollectExprs(vec![]); folder.fold_file(file); folder.0 } syn/tests/test_size.rs0000644000175000017500000000310714661133735016074 0ustar jamespagejamespage// Assumes proc-macro2's "span-locations" feature is off. use std::mem; use syn::{Expr, Item, Lit, Pat, Type}; #[rustversion::attr(before(2022-11-24), ignore = "requires nightly-2022-11-24 or newer")] #[rustversion::attr( since(2022-11-24), cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") )] #[test] fn test_expr_size() { assert_eq!(mem::size_of::(), 176); } #[rustversion::attr(before(2022-09-09), ignore = "requires nightly-2022-09-09 or newer")] #[rustversion::attr( since(2022-09-09), cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") )] #[test] fn test_item_size() { assert_eq!(mem::size_of::(), 352); } #[rustversion::attr(before(2023-04-29), ignore = "requires nightly-2023-04-29 or newer")] #[rustversion::attr( since(2023-04-29), cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") )] #[test] fn test_type_size() { assert_eq!(mem::size_of::(), 224); } #[rustversion::attr(before(2023-04-29), ignore = "requires nightly-2023-04-29 or newer")] #[rustversion::attr( since(2023-04-29), cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") )] #[test] fn test_pat_size() { assert_eq!(mem::size_of::(), 184); } #[rustversion::attr(before(2023-12-20), ignore = "requires nightly-2023-12-20 or newer")] #[rustversion::attr( since(2023-12-20), cfg_attr(not(target_pointer_width = "64"), ignore = "only applicable to 64-bit") )] #[test] fn test_lit_size() { assert_eq!(mem::size_of::(), 24); } syn/tests/test_stmt.rs0000644000175000017500000002027714661133735016120 0ustar jamespagejamespage#![allow( clippy::assertions_on_result_states, clippy::non_ascii_literal, clippy::uninlined_format_args )] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use quote::{quote, ToTokens as _}; use syn::parse::Parser as _; use syn::{Block, Stmt}; #[test] fn test_raw_operator() { let stmt = syn::parse_str::("let _ = &raw const x;").unwrap(); snapshot!(stmt, @r###" Stmt::Local { pat: Pat::Wild, init: Some(LocalInit { expr: Expr::Verbatim(`& raw const x`), }), } "###); } #[test] fn test_raw_variable() { let stmt = syn::parse_str::("let _ = &raw;").unwrap(); snapshot!(stmt, @r###" Stmt::Local { pat: Pat::Wild, init: Some(LocalInit { expr: Expr::Reference { expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "raw", }, ], }, }, }, }), } "###); } #[test] fn test_raw_invalid() { assert!(syn::parse_str::("let _ = &raw x;").is_err()); } #[test] fn test_none_group() { // «∅ async fn f() {} ∅» let tokens = TokenStream::from_iter([TokenTree::Group(Group::new( Delimiter::None, TokenStream::from_iter([ TokenTree::Ident(Ident::new("async", Span::call_site())), TokenTree::Ident(Ident::new("fn", Span::call_site())), TokenTree::Ident(Ident::new("f", Span::call_site())), TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())), ]), ))]); snapshot!(tokens as Stmt, @r###" Stmt::Item(Item::Fn { vis: Visibility::Inherited, sig: Signature { asyncness: Some, ident: "f", generics: Generics, output: ReturnType::Default, }, block: Block { stmts: [], }, }) "###); let tokens = Group::new(Delimiter::None, quote!(let None = None)).to_token_stream(); let stmts = Block::parse_within.parse2(tokens).unwrap(); snapshot!(stmts, @r###" [ Stmt::Expr( Expr::Group { expr: Expr::Let { pat: Pat::Ident { ident: "None", }, expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "None", }, ], }, }, }, }, None, ), ] "###); } #[test] fn test_let_dot_dot() { let tokens = quote! { let .. = 10; }; snapshot!(tokens as Stmt, @r###" Stmt::Local { pat: Pat::Rest, init: Some(LocalInit { expr: Expr::Lit { lit: 10, }, }), } "###); } #[test] fn test_let_else() { let tokens = quote! { let Some(x) = None else { return 0; }; }; snapshot!(tokens as Stmt, @r###" Stmt::Local { pat: Pat::TupleStruct { path: Path { segments: [ PathSegment { ident: "Some", }, ], }, elems: [ Pat::Ident { ident: "x", }, ], }, init: Some(LocalInit { expr: Expr::Path { path: Path { segments: [ PathSegment { ident: "None", }, ], }, }, diverge: Some(Expr::Block { block: Block { stmts: [ Stmt::Expr( Expr::Return { expr: Some(Expr::Lit { lit: 0, }), }, Some, ), ], }, }), }), } "###); } #[test] fn test_macros() { let tokens = quote! { fn main() { macro_rules! mac {} thread_local! { static FOO } println!(""); vec![] } }; snapshot!(tokens as Stmt, @r###" Stmt::Item(Item::Fn { vis: Visibility::Inherited, sig: Signature { ident: "main", generics: Generics, output: ReturnType::Default, }, block: Block { stmts: [ Stmt::Item(Item::Macro { ident: Some("mac"), mac: Macro { path: Path { segments: [ PathSegment { ident: "macro_rules", }, ], }, delimiter: MacroDelimiter::Brace, tokens: TokenStream(``), }, }), Stmt::Macro { mac: Macro { path: Path { segments: [ PathSegment { ident: "thread_local", }, ], }, delimiter: MacroDelimiter::Brace, tokens: TokenStream(`static FOO`), }, }, Stmt::Macro { mac: Macro { path: Path { segments: [ PathSegment { ident: "println", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`""`), }, semi_token: Some, }, Stmt::Expr( Expr::Macro { mac: Macro { path: Path { segments: [ PathSegment { ident: "vec", }, ], }, delimiter: MacroDelimiter::Bracket, tokens: TokenStream(``), }, }, None, ), ], }, }) "###); } #[test] fn test_early_parse_loop() { // The following is an Expr::Loop followed by Expr::Tuple. It is not an // Expr::Call. let tokens = quote! { loop {} () }; let stmts = Block::parse_within.parse2(tokens).unwrap(); snapshot!(stmts, @r###" [ Stmt::Expr( Expr::Loop { body: Block { stmts: [], }, }, None, ), Stmt::Expr( Expr::Tuple, None, ), ] "###); let tokens = quote! { 'a: loop {} () }; let stmts = Block::parse_within.parse2(tokens).unwrap(); snapshot!(stmts, @r###" [ Stmt::Expr( Expr::Loop { label: Some(Label { name: Lifetime { ident: "a", }, }), body: Block { stmts: [], }, }, None, ), Stmt::Expr( Expr::Tuple, None, ), ] "###); } syn/tests/test_ty.rs0000644000175000017500000003006214661133735015556 0ustar jamespagejamespage#![allow(clippy::uninlined_format_args)] #[macro_use] mod macros; use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree}; use quote::{quote, ToTokens as _}; use syn::punctuated::Punctuated; use syn::{parse_quote, token, Token, Type, TypeTuple}; #[test] fn test_mut_self() { syn::parse_str::("fn(mut self)").unwrap(); syn::parse_str::("fn(mut self,)").unwrap(); syn::parse_str::("fn(mut self: ())").unwrap(); syn::parse_str::("fn(mut self: ...)").unwrap_err(); syn::parse_str::("fn(mut self: mut self)").unwrap_err(); syn::parse_str::("fn(mut self::T)").unwrap_err(); } #[test] fn test_macro_variable_type() { // mimics the token stream corresponding to `$ty` let tokens = TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, quote! { ty })), TokenTree::Punct(Punct::new('<', Spacing::Alone)), TokenTree::Ident(Ident::new("T", Span::call_site())), TokenTree::Punct(Punct::new('>', Spacing::Alone)), ]); snapshot!(tokens as Type, @r###" Type::Path { path: Path { segments: [ PathSegment { ident: "ty", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "T", }, ], }, }), ], }, }, ], }, } "###); // mimics the token stream corresponding to `$ty::` let tokens = TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, quote! { ty })), TokenTree::Punct(Punct::new(':', Spacing::Joint)), TokenTree::Punct(Punct::new(':', Spacing::Alone)), TokenTree::Punct(Punct::new('<', Spacing::Alone)), TokenTree::Ident(Ident::new("T", Span::call_site())), TokenTree::Punct(Punct::new('>', Spacing::Alone)), ]); snapshot!(tokens as Type, @r###" Type::Path { path: Path { segments: [ PathSegment { ident: "ty", arguments: PathArguments::AngleBracketed { colon2_token: Some, args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "T", }, ], }, }), ], }, }, ], }, } "###); } #[test] fn test_group_angle_brackets() { // mimics the token stream corresponding to `Option<$ty>` let tokens = TokenStream::from_iter([ TokenTree::Ident(Ident::new("Option", Span::call_site())), TokenTree::Punct(Punct::new('<', Spacing::Alone)), TokenTree::Group(Group::new(Delimiter::None, quote! { Vec })), TokenTree::Punct(Punct::new('>', Spacing::Alone)), ]); snapshot!(tokens as Type, @r###" Type::Path { path: Path { segments: [ PathSegment { ident: "Option", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Group { elem: Type::Path { path: Path { segments: [ PathSegment { ident: "Vec", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "u8", }, ], }, }), ], }, }, ], }, }, }), ], }, }, ], }, } "###); } #[test] fn test_group_colons() { // mimics the token stream corresponding to `$ty::Item` let tokens = TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, quote! { Vec })), TokenTree::Punct(Punct::new(':', Spacing::Joint)), TokenTree::Punct(Punct::new(':', Spacing::Alone)), TokenTree::Ident(Ident::new("Item", Span::call_site())), ]); snapshot!(tokens as Type, @r###" Type::Path { path: Path { segments: [ PathSegment { ident: "Vec", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "u8", }, ], }, }), ], }, }, Token![::], PathSegment { ident: "Item", }, ], }, } "###); let tokens = TokenStream::from_iter([ TokenTree::Group(Group::new(Delimiter::None, quote! { [T] })), TokenTree::Punct(Punct::new(':', Spacing::Joint)), TokenTree::Punct(Punct::new(':', Spacing::Alone)), TokenTree::Ident(Ident::new("Element", Span::call_site())), ]); snapshot!(tokens as Type, @r###" Type::Path { qself: Some(QSelf { ty: Type::Slice { elem: Type::Path { path: Path { segments: [ PathSegment { ident: "T", }, ], }, }, }, position: 0, }), path: Path { leading_colon: Some, segments: [ PathSegment { ident: "Element", }, ], }, } "###); } #[test] fn test_trait_object() { let tokens = quote!(dyn for<'a> Trait<'a> + 'static); snapshot!(tokens as Type, @r###" Type::TraitObject { dyn_token: Some, bounds: [ TypeParamBound::Trait(TraitBound { lifetimes: Some(BoundLifetimes { lifetimes: [ GenericParam::Lifetime(LifetimeParam { lifetime: Lifetime { ident: "a", }, }), ], }), path: Path { segments: [ PathSegment { ident: "Trait", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Lifetime(Lifetime { ident: "a", }), ], }, }, ], }, }), Token![+], TypeParamBound::Lifetime { ident: "static", }, ], } "###); let tokens = quote!(dyn 'a + Trait); snapshot!(tokens as Type, @r###" Type::TraitObject { dyn_token: Some, bounds: [ TypeParamBound::Lifetime { ident: "a", }, Token![+], TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Trait", }, ], }, }), ], } "###); // None of the following are valid Rust types. syn::parse_str::("for<'a> dyn Trait<'a>").unwrap_err(); syn::parse_str::("dyn for<'a> 'a + Trait").unwrap_err(); } #[test] fn test_trailing_plus() { #[rustfmt::skip] let tokens = quote!(impl Trait +); snapshot!(tokens as Type, @r###" Type::ImplTrait { bounds: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Trait", }, ], }, }), Token![+], ], } "###); #[rustfmt::skip] let tokens = quote!(dyn Trait +); snapshot!(tokens as Type, @r###" Type::TraitObject { dyn_token: Some, bounds: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Trait", }, ], }, }), Token![+], ], } "###); #[rustfmt::skip] let tokens = quote!(Trait +); snapshot!(tokens as Type, @r###" Type::TraitObject { bounds: [ TypeParamBound::Trait(TraitBound { path: Path { segments: [ PathSegment { ident: "Trait", }, ], }, }), Token![+], ], } "###); } #[test] fn test_tuple_comma() { let mut expr = TypeTuple { paren_token: token::Paren::default(), elems: Punctuated::new(), }; snapshot!(expr.to_token_stream() as Type, @"Type::Tuple"); expr.elems.push_value(parse_quote!(_)); // Must not parse to Type::Paren snapshot!(expr.to_token_stream() as Type, @r###" Type::Tuple { elems: [ Type::Infer, Token![,], ], } "###); expr.elems.push_punct(::default()); snapshot!(expr.to_token_stream() as Type, @r###" Type::Tuple { elems: [ Type::Infer, Token![,], ], } "###); expr.elems.push_value(parse_quote!(_)); snapshot!(expr.to_token_stream() as Type, @r###" Type::Tuple { elems: [ Type::Infer, Token![,], Type::Infer, ], } "###); expr.elems.push_punct(::default()); snapshot!(expr.to_token_stream() as Type, @r###" Type::Tuple { elems: [ Type::Infer, Token![,], Type::Infer, Token![,], ], } "###); } syn/tests/test_derive_input.rs0000644000175000017500000005252614661133735017630 0ustar jamespagejamespage#![allow( clippy::assertions_on_result_states, clippy::manual_let_else, clippy::too_many_lines, clippy::uninlined_format_args )] #[macro_use] mod macros; use quote::quote; use syn::{Data, DeriveInput}; #[test] fn test_unit() { let input = quote! { struct Unit; }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "Unit", generics: Generics, data: Data::Struct { fields: Fields::Unit, semi_token: Some, }, } "###); } #[test] fn test_struct() { let input = quote! { #[derive(Debug, Clone)] pub struct Item { pub ident: Ident, pub attrs: Vec } }; snapshot!(input as DeriveInput, @r###" DeriveInput { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::List { path: Path { segments: [ PathSegment { ident: "derive", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`Debug , Clone`), }, }, ], vis: Visibility::Public, ident: "Item", generics: Generics, data: Data::Struct { fields: Fields::Named { named: [ Field { vis: Visibility::Public, ident: Some("ident"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Ident", }, ], }, }, }, Token![,], Field { vis: Visibility::Public, ident: Some("attrs"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "Vec", arguments: PathArguments::AngleBracketed { args: [ GenericArgument::Type(Type::Path { path: Path { segments: [ PathSegment { ident: "Attribute", }, ], }, }), ], }, }, ], }, }, }, ], }, }, } "###); snapshot!(&input.attrs[0].meta, @r###" Meta::List { path: Path { segments: [ PathSegment { ident: "derive", }, ], }, delimiter: MacroDelimiter::Paren, tokens: TokenStream(`Debug , Clone`), } "###); } #[test] fn test_union() { let input = quote! { union MaybeUninit { uninit: (), value: T } }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "MaybeUninit", generics: Generics { lt_token: Some, params: [ GenericParam::Type(TypeParam { ident: "T", }), ], gt_token: Some, }, data: Data::Union { fields: FieldsNamed { named: [ Field { vis: Visibility::Inherited, ident: Some("uninit"), colon_token: Some, ty: Type::Tuple, }, Token![,], Field { vis: Visibility::Inherited, ident: Some("value"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "T", }, ], }, }, }, ], }, }, } "###); } #[test] #[cfg(feature = "full")] fn test_enum() { let input = quote! { /// See the std::result module documentation for details. #[must_use] pub enum Result { Ok(T), Err(E), Surprise = 0isize, // Smuggling data into a proc_macro_derive, // in the style of https://github.com/dtolnay/proc-macro-hack ProcMacroHack = (0, "data").0 } }; snapshot!(input as DeriveInput, @r###" DeriveInput { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::NameValue { path: Path { segments: [ PathSegment { ident: "doc", }, ], }, value: Expr::Lit { lit: " See the std::result module documentation for details.", }, }, }, Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "must_use", }, ], }, }, ], vis: Visibility::Public, ident: "Result", generics: Generics { lt_token: Some, params: [ GenericParam::Type(TypeParam { ident: "T", }), Token![,], GenericParam::Type(TypeParam { ident: "E", }), ], gt_token: Some, }, data: Data::Enum { variants: [ Variant { ident: "Ok", fields: Fields::Unnamed { unnamed: [ Field { vis: Visibility::Inherited, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "T", }, ], }, }, }, ], }, }, Token![,], Variant { ident: "Err", fields: Fields::Unnamed { unnamed: [ Field { vis: Visibility::Inherited, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "E", }, ], }, }, }, ], }, }, Token![,], Variant { ident: "Surprise", fields: Fields::Unit, discriminant: Some(Expr::Lit { lit: 0isize, }), }, Token![,], Variant { ident: "ProcMacroHack", fields: Fields::Unit, discriminant: Some(Expr::Field { base: Expr::Tuple { elems: [ Expr::Lit { lit: 0, }, Token![,], Expr::Lit { lit: "data", }, ], }, member: Member::Unnamed(Index { index: 0, }), }), }, ], }, } "###); let meta_items: Vec<_> = input.attrs.into_iter().map(|attr| attr.meta).collect(); snapshot!(meta_items, @r###" [ Meta::NameValue { path: Path { segments: [ PathSegment { ident: "doc", }, ], }, value: Expr::Lit { lit: " See the std::result module documentation for details.", }, }, Meta::Path { segments: [ PathSegment { ident: "must_use", }, ], }, ] "###); } #[test] fn test_attr_with_non_mod_style_path() { let input = quote! { #[inert ] struct S; }; syn::parse2::(input).unwrap_err(); } #[test] fn test_attr_with_mod_style_path_with_self() { let input = quote! { #[foo::self] struct S; }; snapshot!(input as DeriveInput, @r###" DeriveInput { attrs: [ Attribute { style: AttrStyle::Outer, meta: Meta::Path { segments: [ PathSegment { ident: "foo", }, Token![::], PathSegment { ident: "self", }, ], }, }, ], vis: Visibility::Inherited, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unit, semi_token: Some, }, } "###); snapshot!(&input.attrs[0].meta, @r###" Meta::Path { segments: [ PathSegment { ident: "foo", }, Token![::], PathSegment { ident: "self", }, ], } "###); } #[test] fn test_pub_restricted() { // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs let input = quote! { pub(in m) struct Z(pub(in m::n) u8); }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Restricted { in_token: Some, path: Path { segments: [ PathSegment { ident: "m", }, ], }, }, ident: "Z", generics: Generics, data: Data::Struct { fields: Fields::Unnamed { unnamed: [ Field { vis: Visibility::Restricted { in_token: Some, path: Path { segments: [ PathSegment { ident: "m", }, Token![::], PathSegment { ident: "n", }, ], }, }, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "u8", }, ], }, }, }, ], }, semi_token: Some, }, } "###); } #[test] fn test_pub_restricted_crate() { let input = quote! { pub(crate) struct S; }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Restricted { path: Path { segments: [ PathSegment { ident: "crate", }, ], }, }, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unit, semi_token: Some, }, } "###); } #[test] fn test_pub_restricted_super() { let input = quote! { pub(super) struct S; }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Restricted { path: Path { segments: [ PathSegment { ident: "super", }, ], }, }, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unit, semi_token: Some, }, } "###); } #[test] fn test_pub_restricted_in_super() { let input = quote! { pub(in super) struct S; }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Restricted { in_token: Some, path: Path { segments: [ PathSegment { ident: "super", }, ], }, }, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unit, semi_token: Some, }, } "###); } #[test] fn test_fields_on_unit_struct() { let input = quote! { struct S; }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unit, semi_token: Some, }, } "###); let data = match input.data { Data::Struct(data) => data, _ => panic!("expected a struct"), }; assert_eq!(0, data.fields.iter().count()); } #[test] fn test_fields_on_named_struct() { let input = quote! { struct S { foo: i32, pub bar: String, } }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Named { named: [ Field { vis: Visibility::Inherited, ident: Some("foo"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "i32", }, ], }, }, }, Token![,], Field { vis: Visibility::Public, ident: Some("bar"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "String", }, ], }, }, }, Token![,], ], }, }, } "###); let data = match input.data { Data::Struct(data) => data, _ => panic!("expected a struct"), }; snapshot!(data.fields.into_iter().collect::>(), @r###" [ Field { vis: Visibility::Inherited, ident: Some("foo"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "i32", }, ], }, }, }, Field { vis: Visibility::Public, ident: Some("bar"), colon_token: Some, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "String", }, ], }, }, }, ] "###); } #[test] fn test_fields_on_tuple_struct() { let input = quote! { struct S(i32, pub String); }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unnamed { unnamed: [ Field { vis: Visibility::Inherited, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "i32", }, ], }, }, }, Token![,], Field { vis: Visibility::Public, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "String", }, ], }, }, }, ], }, semi_token: Some, }, } "###); let data = match input.data { Data::Struct(data) => data, _ => panic!("expected a struct"), }; snapshot!(data.fields.iter().collect::>(), @r###" [ Field { vis: Visibility::Inherited, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "i32", }, ], }, }, }, Field { vis: Visibility::Public, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "String", }, ], }, }, }, ] "###); } #[test] fn test_ambiguous_crate() { let input = quote! { // The field type is `(crate::X)` not `crate (::X)`. struct S(crate::X); }; snapshot!(input as DeriveInput, @r###" DeriveInput { vis: Visibility::Inherited, ident: "S", generics: Generics, data: Data::Struct { fields: Fields::Unnamed { unnamed: [ Field { vis: Visibility::Inherited, ty: Type::Path { path: Path { segments: [ PathSegment { ident: "crate", }, Token![::], PathSegment { ident: "X", }, ], }, }, }, ], }, semi_token: Some, }, } "###); } syn/LICENSE-MIT0000644000175000017500000000177714661133735014022 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. syn/src/0000775000175000017500000000000014661133735013143 5ustar jamespagejamespagesyn/src/attr.rs0000644000175000017500000006452414661133735014474 0ustar jamespagejamespage#[cfg(feature = "parsing")] use crate::error::Error; #[cfg(feature = "parsing")] use crate::error::Result; use crate::expr::Expr; use crate::mac::MacroDelimiter; #[cfg(feature = "parsing")] use crate::meta::{self, ParseNestedMeta}; #[cfg(feature = "parsing")] use crate::parse::{Parse, ParseStream, Parser}; use crate::path::Path; use crate::token; use proc_macro2::TokenStream; #[cfg(feature = "printing")] use std::iter; #[cfg(feature = "printing")] use std::slice; ast_struct! { /// An attribute, like `#[repr(transparent)]`. /// ///
/// /// # Syntax /// /// Rust has six types of attributes. /// /// - Outer attributes like `#[repr(transparent)]`. These appear outside or /// in front of the item they describe. /// /// - Inner attributes like `#![feature(proc_macro)]`. These appear inside /// of the item they describe, usually a module. /// /// - Outer one-line doc comments like `/// Example`. /// /// - Inner one-line doc comments like `//! Please file an issue`. /// /// - Outer documentation blocks `/** Example */`. /// /// - Inner documentation blocks `/*! Please file an issue */`. /// /// The `style` field of type `AttrStyle` distinguishes whether an attribute /// is outer or inner. /// /// Every attribute has a `path` that indicates the intended interpretation /// of the rest of the attribute's contents. The path and the optional /// additional contents are represented together in the `meta` field of the /// attribute in three possible varieties: /// /// - Meta::Path — attributes whose information content conveys just a /// path, for example the `#[test]` attribute. /// /// - Meta::List — attributes that carry arbitrary tokens after the /// path, surrounded by a delimiter (parenthesis, bracket, or brace). For /// example `#[derive(Copy)]` or `#[precondition(x < 5)]`. /// /// - Meta::NameValue — attributes with an `=` sign after the path, /// followed by a Rust expression. For example `#[path = /// "sys/windows.rs"]`. /// /// All doc comments are represented in the NameValue style with a path of /// "doc", as this is how they are processed by the compiler and by /// `macro_rules!` macros. /// /// ```text /// #[derive(Copy, Clone)] /// ~~~~~~Path /// ^^^^^^^^^^^^^^^^^^^Meta::List /// /// #[path = "sys/windows.rs"] /// ~~~~Path /// ^^^^^^^^^^^^^^^^^^^^^^^Meta::NameValue /// /// #[test] /// ^^^^Meta::Path /// ``` /// ///
/// /// # Parsing from tokens to Attribute /// /// This type does not implement the [`Parse`] trait and thus cannot be /// parsed directly by [`ParseStream::parse`]. Instead use /// [`ParseStream::call`] with one of the two parser functions /// [`Attribute::parse_outer`] or [`Attribute::parse_inner`] depending on /// which you intend to parse. /// /// [`Parse`]: crate::parse::Parse /// [`ParseStream::parse`]: crate::parse::ParseBuffer::parse /// [`ParseStream::call`]: crate::parse::ParseBuffer::call /// /// ``` /// use syn::{Attribute, Ident, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses a unit struct with attributes. /// // /// // #[path = "s.tmpl"] /// // struct S; /// struct UnitStruct { /// attrs: Vec, /// struct_token: Token![struct], /// name: Ident, /// semi_token: Token![;], /// } /// /// impl Parse for UnitStruct { /// fn parse(input: ParseStream) -> Result { /// Ok(UnitStruct { /// attrs: input.call(Attribute::parse_outer)?, /// struct_token: input.parse()?, /// name: input.parse()?, /// semi_token: input.parse()?, /// }) /// } /// } /// ``` /// ///


/// /// # Parsing from Attribute to structured arguments /// /// The grammar of attributes in Rust is very flexible, which makes the /// syntax tree not that useful on its own. In particular, arguments of the /// `Meta::List` variety of attribute are held in an arbitrary `tokens: /// TokenStream`. Macros are expected to check the `path` of the attribute, /// decide whether they recognize it, and then parse the remaining tokens /// according to whatever grammar they wish to require for that kind of /// attribute. Use [`parse_args()`] to parse those tokens into the expected /// data structure. /// /// [`parse_args()`]: Attribute::parse_args /// ///


/// /// # Doc comments /// /// The compiler transforms doc comments, such as `/// comment` and `/*! /// comment */`, into attributes before macros are expanded. Each comment is /// expanded into an attribute of the form `#[doc = r"comment"]`. /// /// As an example, the following `mod` items are expanded identically: /// /// ``` /// # use syn::{ItemMod, parse_quote}; /// let doc: ItemMod = parse_quote! { /// /// Single line doc comments /// /// We write so many! /// /** /// * Multi-line comments... /// * May span many lines /// */ /// mod example { /// //! Of course, they can be inner too /// /*! And fit in a single line */ /// } /// }; /// let attr: ItemMod = parse_quote! { /// #[doc = r" Single line doc comments"] /// #[doc = r" We write so many!"] /// #[doc = r" /// * Multi-line comments... /// * May span many lines /// "] /// mod example { /// #![doc = r" Of course, they can be inner too"] /// #![doc = r" And fit in a single line "] /// } /// }; /// assert_eq!(doc, attr); /// ``` #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Attribute { pub pound_token: Token![#], pub style: AttrStyle, pub bracket_token: token::Bracket, pub meta: Meta, } } impl Attribute { /// Returns the path that identifies the interpretation of this attribute. /// /// For example this would return the `test` in `#[test]`, the `derive` in /// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`. pub fn path(&self) -> &Path { self.meta.path() } /// Parse the arguments to the attribute as a syntax tree. /// /// This is similar to pulling out the `TokenStream` from `Meta::List` and /// doing `syn::parse2::(meta_list.tokens)`, except that using /// `parse_args` the error message has a more useful span when `tokens` is /// empty. /// /// The surrounding delimiters are *not* included in the input to the /// parser. /// /// ```text /// #[my_attr(value < 5)] /// ^^^^^^^^^ what gets parsed /// ``` /// /// # Example /// /// ``` /// use syn::{parse_quote, Attribute, Expr}; /// /// let attr: Attribute = parse_quote! { /// #[precondition(value < 5)] /// }; /// /// if attr.path().is_ident("precondition") { /// let precondition: Expr = attr.parse_args()?; /// // ... /// } /// # anyhow::Ok(()) /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args(&self) -> Result { self.parse_args_with(T::parse) } /// Parse the arguments to the attribute using the given parser. /// /// # Example /// /// ``` /// use syn::{parse_quote, Attribute}; /// /// let attr: Attribute = parse_quote! { /// #[inception { #[brrrrrrraaaaawwwwrwrrrmrmrmmrmrmmmmm] }] /// }; /// /// let bwom = attr.parse_args_with(Attribute::parse_outer)?; /// /// // Attribute does not have a Parse impl, so we couldn't directly do: /// // let bwom: Attribute = attr.parse_args()?; /// # anyhow::Ok(()) /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args_with(&self, parser: F) -> Result { match &self.meta { Meta::Path(path) => Err(crate::error::new2( path.segments.first().unwrap().ident.span(), path.segments.last().unwrap().ident.span(), format!( "expected attribute arguments in parentheses: {}[{}(...)]", parsing::DisplayAttrStyle(&self.style), parsing::DisplayPath(path), ), )), Meta::NameValue(meta) => Err(Error::new( meta.eq_token.span, format_args!( "expected parentheses: {}[{}(...)]", parsing::DisplayAttrStyle(&self.style), parsing::DisplayPath(&meta.path), ), )), Meta::List(meta) => meta.parse_args_with(parser), } } /// Parse the arguments to the attribute, expecting it to follow the /// conventional structure used by most of Rust's built-in attributes. /// /// The [*Meta Item Attribute Syntax*][syntax] section in the Rust reference /// explains the convention in more detail. Not all attributes follow this /// convention, so [`parse_args()`][Self::parse_args] is available if you /// need to parse arbitrarily goofy attribute syntax. /// /// [syntax]: https://doc.rust-lang.org/reference/attributes.html#meta-item-attribute-syntax /// /// # Example /// /// We'll parse a struct, and then parse some of Rust's `#[repr]` attribute /// syntax. /// /// ``` /// use syn::{parenthesized, parse_quote, token, ItemStruct, LitInt}; /// /// let input: ItemStruct = parse_quote! { /// #[repr(C, align(4))] /// pub struct MyStruct(u16, u32); /// }; /// /// let mut repr_c = false; /// let mut repr_transparent = false; /// let mut repr_align = None::; /// let mut repr_packed = None::; /// for attr in &input.attrs { /// if attr.path().is_ident("repr") { /// attr.parse_nested_meta(|meta| { /// // #[repr(C)] /// if meta.path.is_ident("C") { /// repr_c = true; /// return Ok(()); /// } /// /// // #[repr(transparent)] /// if meta.path.is_ident("transparent") { /// repr_transparent = true; /// return Ok(()); /// } /// /// // #[repr(align(N))] /// if meta.path.is_ident("align") { /// let content; /// parenthesized!(content in meta.input); /// let lit: LitInt = content.parse()?; /// let n: usize = lit.base10_parse()?; /// repr_align = Some(n); /// return Ok(()); /// } /// /// // #[repr(packed)] or #[repr(packed(N))], omitted N means 1 /// if meta.path.is_ident("packed") { /// if meta.input.peek(token::Paren) { /// let content; /// parenthesized!(content in meta.input); /// let lit: LitInt = content.parse()?; /// let n: usize = lit.base10_parse()?; /// repr_packed = Some(n); /// } else { /// repr_packed = Some(1); /// } /// return Ok(()); /// } /// /// Err(meta.error("unrecognized repr")) /// })?; /// } /// } /// # anyhow::Ok(()) /// ``` /// /// # Alternatives /// /// In some cases, for attributes which have nested layers of structured /// content, the following less flexible approach might be more convenient: /// /// ``` /// # use syn::{parse_quote, ItemStruct}; /// # /// # let input: ItemStruct = parse_quote! { /// # #[repr(C, align(4))] /// # pub struct MyStruct(u16, u32); /// # }; /// # /// use syn::punctuated::Punctuated; /// use syn::{parenthesized, token, Error, LitInt, Meta, Token}; /// /// let mut repr_c = false; /// let mut repr_transparent = false; /// let mut repr_align = None::; /// let mut repr_packed = None::; /// for attr in &input.attrs { /// if attr.path().is_ident("repr") { /// let nested = attr.parse_args_with(Punctuated::::parse_terminated)?; /// for meta in nested { /// match meta { /// // #[repr(C)] /// Meta::Path(path) if path.is_ident("C") => { /// repr_c = true; /// } /// /// // #[repr(align(N))] /// Meta::List(meta) if meta.path.is_ident("align") => { /// let lit: LitInt = meta.parse_args()?; /// let n: usize = lit.base10_parse()?; /// repr_align = Some(n); /// } /// /// /* ... */ /// /// _ => { /// return Err(Error::new_spanned(meta, "unrecognized repr")); /// } /// } /// } /// } /// } /// # Ok(()) /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_nested_meta( &self, logic: impl FnMut(ParseNestedMeta) -> Result<()>, ) -> Result<()> { self.parse_args_with(meta::parser(logic)) } /// Parses zero or more outer attributes from the stream. /// /// # Example /// /// See /// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute). #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_outer(input: ParseStream) -> Result> { let mut attrs = Vec::new(); while input.peek(Token![#]) { attrs.push(input.call(parsing::single_parse_outer)?); } Ok(attrs) } /// Parses zero or more inner attributes from the stream. /// /// # Example /// /// See /// [*Parsing from tokens to Attribute*](#parsing-from-tokens-to-attribute). #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_inner(input: ParseStream) -> Result> { let mut attrs = Vec::new(); parsing::parse_inner(input, &mut attrs)?; Ok(attrs) } } ast_enum! { /// Distinguishes between attributes that decorate an item and attributes /// that are contained within an item. /// /// # Outer attributes /// /// - `#[repr(transparent)]` /// - `/// # Example` /// - `/** Please file an issue */` /// /// # Inner attributes /// /// - `#![feature(proc_macro)]` /// - `//! # Example` /// - `/*! Please file an issue */` #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum AttrStyle { Outer, Inner(Token![!]), } } ast_enum_of_structs! { /// Content of a compile-time structured attribute. /// /// ## Path /// /// A meta path is like the `test` in `#[test]`. /// /// ## List /// /// A meta list is like the `derive(Copy)` in `#[derive(Copy)]`. /// /// ## NameValue /// /// A name-value meta is like the `path = "..."` in `#[path = /// "sys/windows.rs"]`. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum Meta { Path(Path), /// A structured list within an attribute, like `derive(Copy, Clone)`. List(MetaList), /// A name-value pair within an attribute, like `feature = "nightly"`. NameValue(MetaNameValue), } } ast_struct! { /// A structured list within an attribute, like `derive(Copy, Clone)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct MetaList { pub path: Path, pub delimiter: MacroDelimiter, pub tokens: TokenStream, } } ast_struct! { /// A name-value pair within an attribute, like `feature = "nightly"`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct MetaNameValue { pub path: Path, pub eq_token: Token![=], pub value: Expr, } } impl Meta { /// Returns the path that begins this structured meta item. /// /// For example this would return the `test` in `#[test]`, the `derive` in /// `#[derive(Copy)]`, and the `path` in `#[path = "sys/windows.rs"]`. pub fn path(&self) -> &Path { match self { Meta::Path(path) => path, Meta::List(meta) => &meta.path, Meta::NameValue(meta) => &meta.path, } } /// Error if this is a `Meta::List` or `Meta::NameValue`. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_path_only(&self) -> Result<&Path> { let error_span = match self { Meta::Path(path) => return Ok(path), Meta::List(meta) => meta.delimiter.span().open(), Meta::NameValue(meta) => meta.eq_token.span, }; Err(Error::new(error_span, "unexpected token in attribute")) } /// Error if this is a `Meta::Path` or `Meta::NameValue`. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_list(&self) -> Result<&MetaList> { match self { Meta::List(meta) => Ok(meta), Meta::Path(path) => Err(crate::error::new2( path.segments.first().unwrap().ident.span(), path.segments.last().unwrap().ident.span(), format!( "expected attribute arguments in parentheses: `{}(...)`", parsing::DisplayPath(path), ), )), Meta::NameValue(meta) => Err(Error::new(meta.eq_token.span, "expected `(`")), } } /// Error if this is a `Meta::Path` or `Meta::List`. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_name_value(&self) -> Result<&MetaNameValue> { match self { Meta::NameValue(meta) => Ok(meta), Meta::Path(path) => Err(crate::error::new2( path.segments.first().unwrap().ident.span(), path.segments.last().unwrap().ident.span(), format!( "expected a value for this attribute: `{} = ...`", parsing::DisplayPath(path), ), )), Meta::List(meta) => Err(Error::new(meta.delimiter.span().open(), "expected `=`")), } } } impl MetaList { /// See [`Attribute::parse_args`]. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args(&self) -> Result { self.parse_args_with(T::parse) } /// See [`Attribute::parse_args_with`]. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_args_with(&self, parser: F) -> Result { let scope = self.delimiter.span().close(); crate::parse::parse_scoped(parser, scope, self.tokens.clone()) } /// See [`Attribute::parse_nested_meta`]. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_nested_meta( &self, logic: impl FnMut(ParseNestedMeta) -> Result<()>, ) -> Result<()> { self.parse_args_with(meta::parser(logic)) } } #[cfg(feature = "printing")] pub(crate) trait FilterAttrs<'a> { type Ret: Iterator; fn outer(self) -> Self::Ret; #[cfg(feature = "full")] fn inner(self) -> Self::Ret; } #[cfg(feature = "printing")] impl<'a> FilterAttrs<'a> for &'a [Attribute] { type Ret = iter::Filter, fn(&&Attribute) -> bool>; fn outer(self) -> Self::Ret { fn is_outer(attr: &&Attribute) -> bool { match attr.style { AttrStyle::Outer => true, AttrStyle::Inner(_) => false, } } self.iter().filter(is_outer) } #[cfg(feature = "full")] fn inner(self) -> Self::Ret { fn is_inner(attr: &&Attribute) -> bool { match attr.style { AttrStyle::Inner(_) => true, AttrStyle::Outer => false, } } self.iter().filter(is_inner) } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue}; use crate::error::Result; use crate::expr::{Expr, ExprLit}; use crate::lit::Lit; use crate::parse::discouraged::Speculative as _; use crate::parse::{Parse, ParseStream}; use crate::path::Path; use crate::{mac, token}; use std::fmt::{self, Display}; pub(crate) fn parse_inner(input: ParseStream, attrs: &mut Vec) -> Result<()> { while input.peek(Token![#]) && input.peek2(Token![!]) { attrs.push(input.call(single_parse_inner)?); } Ok(()) } pub(crate) fn single_parse_inner(input: ParseStream) -> Result { let content; Ok(Attribute { pound_token: input.parse()?, style: AttrStyle::Inner(input.parse()?), bracket_token: bracketed!(content in input), meta: content.parse()?, }) } pub(crate) fn single_parse_outer(input: ParseStream) -> Result { let content; Ok(Attribute { pound_token: input.parse()?, style: AttrStyle::Outer, bracket_token: bracketed!(content in input), meta: content.parse()?, }) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Meta { fn parse(input: ParseStream) -> Result { let path = input.call(Path::parse_mod_style)?; parse_meta_after_path(path, input) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for MetaList { fn parse(input: ParseStream) -> Result { let path = input.call(Path::parse_mod_style)?; parse_meta_list_after_path(path, input) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for MetaNameValue { fn parse(input: ParseStream) -> Result { let path = input.call(Path::parse_mod_style)?; parse_meta_name_value_after_path(path, input) } } pub(crate) fn parse_meta_after_path(path: Path, input: ParseStream) -> Result { if input.peek(token::Paren) || input.peek(token::Bracket) || input.peek(token::Brace) { parse_meta_list_after_path(path, input).map(Meta::List) } else if input.peek(Token![=]) { parse_meta_name_value_after_path(path, input).map(Meta::NameValue) } else { Ok(Meta::Path(path)) } } fn parse_meta_list_after_path(path: Path, input: ParseStream) -> Result { let (delimiter, tokens) = mac::parse_delimiter(input)?; Ok(MetaList { path, delimiter, tokens, }) } fn parse_meta_name_value_after_path(path: Path, input: ParseStream) -> Result { let eq_token: Token![=] = input.parse()?; let ahead = input.fork(); let lit: Option = ahead.parse()?; let value = if let (Some(lit), true) = (lit, ahead.is_empty()) { input.advance_to(&ahead); Expr::Lit(ExprLit { attrs: Vec::new(), lit, }) } else if input.peek(Token![#]) && input.peek2(token::Bracket) { return Err(input.error("unexpected attribute inside of attribute")); } else { input.parse()? }; Ok(MetaNameValue { path, eq_token, value, }) } pub(super) struct DisplayAttrStyle<'a>(pub &'a AttrStyle); impl<'a> Display for DisplayAttrStyle<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(match self.0 { AttrStyle::Outer => "#", AttrStyle::Inner(_) => "#!", }) } } pub(super) struct DisplayPath<'a>(pub &'a Path); impl<'a> Display for DisplayPath<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { for (i, segment) in self.0.segments.iter().enumerate() { if i > 0 || self.0.leading_colon.is_some() { formatter.write_str("::")?; } write!(formatter, "{}", segment.ident)?; } Ok(()) } } } #[cfg(feature = "printing")] mod printing { use crate::attr::{AttrStyle, Attribute, MetaList, MetaNameValue}; use proc_macro2::TokenStream; use quote::ToTokens; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Attribute { fn to_tokens(&self, tokens: &mut TokenStream) { self.pound_token.to_tokens(tokens); if let AttrStyle::Inner(b) = &self.style { b.to_tokens(tokens); } self.bracket_token.surround(tokens, |tokens| { self.meta.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for MetaList { fn to_tokens(&self, tokens: &mut TokenStream) { self.path.to_tokens(tokens); self.delimiter.surround(tokens, self.tokens.clone()); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for MetaNameValue { fn to_tokens(&self, tokens: &mut TokenStream) { self.path.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.value.to_tokens(tokens); } } } syn/src/ext.rs0000644000175000017500000000747614661133735014325 0ustar jamespagejamespage//! Extension traits to provide parsing methods on foreign types. use crate::buffer::Cursor; use crate::error::Result; use crate::parse::ParseStream; use crate::parse::Peek; use crate::sealed::lookahead; use crate::token::CustomToken; use proc_macro2::Ident; /// Additional methods for `Ident` not provided by proc-macro2 or libproc_macro. /// /// This trait is sealed and cannot be implemented for types outside of Syn. It /// is implemented only for `proc_macro2::Ident`. pub trait IdentExt: Sized + private::Sealed { /// Parses any identifier including keywords. /// /// This is useful when parsing macro input which allows Rust keywords as /// identifiers. /// /// # Example /// /// ``` /// use syn::{Error, Ident, Result, Token}; /// use syn::ext::IdentExt; /// use syn::parse::ParseStream; /// /// mod kw { /// syn::custom_keyword!(name); /// } /// /// // Parses input that looks like `name = NAME` where `NAME` can be /// // any identifier. /// // /// // Examples: /// // /// // name = anything /// // name = impl /// fn parse_dsl(input: ParseStream) -> Result { /// input.parse::()?; /// input.parse::()?; /// let name = input.call(Ident::parse_any)?; /// Ok(name) /// } /// ``` fn parse_any(input: ParseStream) -> Result; /// Peeks any identifier including keywords. Usage: /// `input.peek(Ident::peek_any)` /// /// This is different from `input.peek(Ident)` which only returns true in /// the case of an ident which is not a Rust keyword. #[allow(non_upper_case_globals)] const peek_any: private::PeekFn = private::PeekFn; /// Strips the raw marker `r#`, if any, from the beginning of an ident. /// /// - unraw(`x`) = `x` /// - unraw(`move`) = `move` /// - unraw(`r#move`) = `move` /// /// # Example /// /// In the case of interop with other languages like Python that have a /// different set of keywords than Rust, we might come across macro input /// that involves raw identifiers to refer to ordinary variables in the /// other language with a name that happens to be a Rust keyword. /// /// The function below appends an identifier from the caller's input onto a /// fixed prefix. Without using `unraw()`, this would tend to produce /// invalid identifiers like `__pyo3_get_r#move`. /// /// ``` /// use proc_macro2::Span; /// use syn::Ident; /// use syn::ext::IdentExt; /// /// fn ident_for_getter(variable: &Ident) -> Ident { /// let getter = format!("__pyo3_get_{}", variable.unraw()); /// Ident::new(&getter, Span::call_site()) /// } /// ``` fn unraw(&self) -> Ident; } impl IdentExt for Ident { fn parse_any(input: ParseStream) -> Result { input.step(|cursor| match cursor.ident() { Some((ident, rest)) => Ok((ident, rest)), None => Err(cursor.error("expected ident")), }) } fn unraw(&self) -> Ident { let string = self.to_string(); if let Some(string) = string.strip_prefix("r#") { Ident::new(string, self.span()) } else { self.clone() } } } impl Peek for private::PeekFn { type Token = private::IdentAny; } impl CustomToken for private::IdentAny { fn peek(cursor: Cursor) -> bool { cursor.ident().is_some() } fn display() -> &'static str { "identifier" } } impl lookahead::Sealed for private::PeekFn {} mod private { use proc_macro2::Ident; pub trait Sealed {} impl Sealed for Ident {} pub struct PeekFn; pub struct IdentAny; impl Copy for PeekFn {} impl Clone for PeekFn { fn clone(&self) -> Self { *self } } } syn/src/custom_keyword.rs0000644000175000017500000001726614661133735016601 0ustar jamespagejamespage/// Define a type that supports parsing and printing a given identifier as if it /// were a keyword. /// /// # Usage /// /// As a convention, it is recommended that this macro be invoked within a /// module called `kw` or `keyword` and that the resulting parser be invoked /// with a `kw::` or `keyword::` prefix. /// /// ``` /// mod kw { /// syn::custom_keyword!(whatever); /// } /// ``` /// /// The generated syntax tree node supports the following operations just like /// any built-in keyword token. /// /// - [Peeking] — `input.peek(kw::whatever)` /// /// - [Parsing] — `input.parse::()?` /// /// - [Printing] — `quote!( ... #whatever_token ... )` /// /// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)` /// /// - Field access to its span — `let sp = whatever_token.span` /// /// [Peeking]: crate::parse::ParseBuffer::peek /// [Parsing]: crate::parse::ParseBuffer::parse /// [Printing]: quote::ToTokens /// [`Span`]: proc_macro2::Span /// /// # Example /// /// This example parses input that looks like `bool = true` or `str = "value"`. /// The key must be either the identifier `bool` or the identifier `str`. If /// `bool`, the value may be either `true` or `false`. If `str`, the value may /// be any string literal. /// /// The symbols `bool` and `str` are not reserved keywords in Rust so these are /// not considered keywords in the `syn::token` module. Like any other /// identifier that is not a keyword, these can be declared as custom keywords /// by crates that need to use them as such. /// /// ``` /// use syn::{LitBool, LitStr, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// mod kw { /// syn::custom_keyword!(bool); /// syn::custom_keyword!(str); /// } /// /// enum Argument { /// Bool { /// bool_token: kw::bool, /// eq_token: Token![=], /// value: LitBool, /// }, /// Str { /// str_token: kw::str, /// eq_token: Token![=], /// value: LitStr, /// }, /// } /// /// impl Parse for Argument { /// fn parse(input: ParseStream) -> Result { /// let lookahead = input.lookahead1(); /// if lookahead.peek(kw::bool) { /// Ok(Argument::Bool { /// bool_token: input.parse::()?, /// eq_token: input.parse()?, /// value: input.parse()?, /// }) /// } else if lookahead.peek(kw::str) { /// Ok(Argument::Str { /// str_token: input.parse::()?, /// eq_token: input.parse()?, /// value: input.parse()?, /// }) /// } else { /// Err(lookahead.error()) /// } /// } /// } /// ``` #[macro_export] macro_rules! custom_keyword { ($ident:ident) => { #[allow(non_camel_case_types)] pub struct $ident { #[allow(dead_code)] pub span: $crate::__private::Span, } #[doc(hidden)] #[allow(dead_code, non_snake_case)] pub fn $ident<__S: $crate::__private::IntoSpans<$crate::__private::Span>>( span: __S, ) -> $ident { $ident { span: $crate::__private::IntoSpans::into_spans(span), } } const _: () = { impl $crate::__private::Default for $ident { fn default() -> Self { $ident { span: $crate::__private::Span::call_site(), } } } $crate::impl_parse_for_custom_keyword!($ident); $crate::impl_to_tokens_for_custom_keyword!($ident); $crate::impl_clone_for_custom_keyword!($ident); $crate::impl_extra_traits_for_custom_keyword!($ident); }; }; } // Not public API. #[cfg(feature = "parsing")] #[doc(hidden)] #[macro_export] macro_rules! impl_parse_for_custom_keyword { ($ident:ident) => { // For peek. impl $crate::__private::CustomToken for $ident { fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool { if let $crate::__private::Some((ident, _rest)) = cursor.ident() { ident == $crate::__private::stringify!($ident) } else { false } } fn display() -> &'static $crate::__private::str { $crate::__private::concat!("`", $crate::__private::stringify!($ident), "`") } } impl $crate::parse::Parse for $ident { fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> { input.step(|cursor| { if let $crate::__private::Some((ident, rest)) = cursor.ident() { if ident == $crate::__private::stringify!($ident) { return $crate::__private::Ok(($ident { span: ident.span() }, rest)); } } $crate::__private::Err(cursor.error($crate::__private::concat!( "expected `", $crate::__private::stringify!($ident), "`", ))) }) } } }; } // Not public API. #[cfg(not(feature = "parsing"))] #[doc(hidden)] #[macro_export] macro_rules! impl_parse_for_custom_keyword { ($ident:ident) => {}; } // Not public API. #[cfg(feature = "printing")] #[doc(hidden)] #[macro_export] macro_rules! impl_to_tokens_for_custom_keyword { ($ident:ident) => { impl $crate::__private::ToTokens for $ident { fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) { let ident = $crate::Ident::new($crate::__private::stringify!($ident), self.span); $crate::__private::TokenStreamExt::append(tokens, ident); } } }; } // Not public API. #[cfg(not(feature = "printing"))] #[doc(hidden)] #[macro_export] macro_rules! impl_to_tokens_for_custom_keyword { ($ident:ident) => {}; } // Not public API. #[cfg(feature = "clone-impls")] #[doc(hidden)] #[macro_export] macro_rules! impl_clone_for_custom_keyword { ($ident:ident) => { impl $crate::__private::Copy for $ident {} #[allow(clippy::expl_impl_clone_on_copy)] impl $crate::__private::Clone for $ident { fn clone(&self) -> Self { *self } } }; } // Not public API. #[cfg(not(feature = "clone-impls"))] #[doc(hidden)] #[macro_export] macro_rules! impl_clone_for_custom_keyword { ($ident:ident) => {}; } // Not public API. #[cfg(feature = "extra-traits")] #[doc(hidden)] #[macro_export] macro_rules! impl_extra_traits_for_custom_keyword { ($ident:ident) => { impl $crate::__private::Debug for $ident { fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::FmtResult { $crate::__private::Formatter::write_str( f, $crate::__private::concat!( "Keyword [", $crate::__private::stringify!($ident), "]", ), ) } } impl $crate::__private::Eq for $ident {} impl $crate::__private::PartialEq for $ident { fn eq(&self, _other: &Self) -> $crate::__private::bool { true } } impl $crate::__private::Hash for $ident { fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {} } }; } // Not public API. #[cfg(not(feature = "extra-traits"))] #[doc(hidden)] #[macro_export] macro_rules! impl_extra_traits_for_custom_keyword { ($ident:ident) => {}; } syn/src/path.rs0000644000175000017500000007445114661133735014456 0ustar jamespagejamespage#[cfg(feature = "parsing")] use crate::error::Result; use crate::expr::Expr; use crate::generics::TypeParamBound; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::punctuated::Punctuated; use crate::token; use crate::ty::{ReturnType, Type}; ast_struct! { /// A path at which a named item is exported (e.g. `std::collections::HashMap`). #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Path { pub leading_colon: Option, pub segments: Punctuated, } } impl From for Path where T: Into, { fn from(segment: T) -> Self { let mut path = Path { leading_colon: None, segments: Punctuated::new(), }; path.segments.push_value(segment.into()); path } } impl Path { /// Determines whether this is a path of length 1 equal to the given /// ident. /// /// For them to compare equal, it must be the case that: /// /// - the path has no leading colon, /// - the number of path segments is 1, /// - the first path segment has no angle bracketed or parenthesized /// path arguments, and /// - the ident of the first path segment is equal to the given one. /// /// # Example /// /// ``` /// use proc_macro2::TokenStream; /// use syn::{Attribute, Error, Meta, Result}; /// /// fn get_serde_meta_item(attr: &Attribute) -> Result> { /// if attr.path().is_ident("serde") { /// match &attr.meta { /// Meta::List(meta) => Ok(Some(&meta.tokens)), /// bad => Err(Error::new_spanned(bad, "unrecognized attribute")), /// } /// } else { /// Ok(None) /// } /// } /// ``` pub fn is_ident(&self, ident: &I) -> bool where I: ?Sized, Ident: PartialEq, { match self.get_ident() { Some(id) => id == ident, None => false, } } /// If this path consists of a single ident, returns the ident. /// /// A path is considered an ident if: /// /// - the path has no leading colon, /// - the number of path segments is 1, and /// - the first path segment has no angle bracketed or parenthesized /// path arguments. pub fn get_ident(&self) -> Option<&Ident> { if self.leading_colon.is_none() && self.segments.len() == 1 && self.segments[0].arguments.is_none() { Some(&self.segments[0].ident) } else { None } } /// An error if this path is not a single ident, as defined in `get_ident`. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn require_ident(&self) -> Result<&Ident> { self.get_ident().ok_or_else(|| { crate::error::new2( self.segments.first().unwrap().ident.span(), self.segments.last().unwrap().ident.span(), "expected this path to be an identifier", ) }) } } ast_struct! { /// A segment of a path together with any path arguments on that segment. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct PathSegment { pub ident: Ident, pub arguments: PathArguments, } } impl From for PathSegment where T: Into, { fn from(ident: T) -> Self { PathSegment { ident: ident.into(), arguments: PathArguments::None, } } } ast_enum! { /// Angle bracketed or parenthesized arguments of a path segment. /// /// ## Angle bracketed /// /// The `<'a, T>` in `std::slice::iter<'a, T>`. /// /// ## Parenthesized /// /// The `(A, B) -> C` in `Fn(A, B) -> C`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum PathArguments { None, /// The `<'a, T>` in `std::slice::iter<'a, T>`. AngleBracketed(AngleBracketedGenericArguments), /// The `(A, B) -> C` in `Fn(A, B) -> C`. Parenthesized(ParenthesizedGenericArguments), } } impl Default for PathArguments { fn default() -> Self { PathArguments::None } } impl PathArguments { pub fn is_empty(&self) -> bool { match self { PathArguments::None => true, PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(), PathArguments::Parenthesized(_) => false, } } pub fn is_none(&self) -> bool { match self { PathArguments::None => true, PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false, } } } ast_enum! { /// An individual generic argument, like `'a`, `T`, or `Item = T`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum GenericArgument { /// A lifetime argument. Lifetime(Lifetime), /// A type argument. Type(Type), /// A const expression. Must be inside of a block. /// /// NOTE: Identity expressions are represented as Type arguments, as /// they are indistinguishable syntactically. Const(Expr), /// A binding (equality constraint) on an associated type: the `Item = /// u8` in `Iterator`. AssocType(AssocType), /// An equality constraint on an associated constant: the `PANIC = /// false` in `Trait`. AssocConst(AssocConst), /// An associated type bound: `Iterator`. Constraint(Constraint), } } ast_struct! { /// Angle bracketed arguments of a path segment: the `` in `HashMap`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct AngleBracketedGenericArguments { pub colon2_token: Option, pub lt_token: Token![<], pub args: Punctuated, pub gt_token: Token![>], } } ast_struct! { /// A binding (equality constraint) on an associated type: the `Item = u8` /// in `Iterator`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct AssocType { pub ident: Ident, pub generics: Option, pub eq_token: Token![=], pub ty: Type, } } ast_struct! { /// An equality constraint on an associated constant: the `PANIC = false` in /// `Trait`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct AssocConst { pub ident: Ident, pub generics: Option, pub eq_token: Token![=], pub value: Expr, } } ast_struct! { /// An associated type bound: `Iterator`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Constraint { pub ident: Ident, pub generics: Option, pub colon_token: Token![:], pub bounds: Punctuated, } } ast_struct! { /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) -> /// C`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ParenthesizedGenericArguments { pub paren_token: token::Paren, /// `(A, B)` pub inputs: Punctuated, /// `C` pub output: ReturnType, } } ast_struct! { /// The explicit Self type in a qualified path: the `T` in `::fmt`. /// /// The actual path, including the trait and the associated item, is stored /// separately. The `position` field represents the index of the associated /// item qualified with this Self type. /// /// ```text /// as a::b::Trait>::AssociatedItem /// ^~~~~~ ~~~~~~~~~~~~~~^ /// ty position = 3 /// /// >::AssociatedItem /// ^~~~~~ ^ /// ty position = 0 /// ``` #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct QSelf { pub lt_token: Token![<], pub ty: Box, pub position: usize, pub as_token: Option, pub gt_token: Token![>], } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::error::Result; #[cfg(feature = "full")] use crate::expr::ExprBlock; use crate::expr::{Expr, ExprPath}; use crate::ext::IdentExt as _; #[cfg(feature = "full")] use crate::generics::TypeParamBound; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::lit::Lit; use crate::parse::{Parse, ParseStream}; #[cfg(feature = "full")] use crate::path::Constraint; use crate::path::{ AngleBracketedGenericArguments, AssocConst, AssocType, GenericArgument, ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, }; use crate::punctuated::Punctuated; use crate::token; use crate::ty::{ReturnType, Type}; #[cfg(not(feature = "full"))] use crate::verbatim; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Path { fn parse(input: ParseStream) -> Result { Self::parse_helper(input, false) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for GenericArgument { fn parse(input: ParseStream) -> Result { if input.peek(Lifetime) && !input.peek2(Token![+]) { return Ok(GenericArgument::Lifetime(input.parse()?)); } if input.peek(Lit) || input.peek(token::Brace) { return const_argument(input).map(GenericArgument::Const); } let mut argument: Type = input.parse()?; match argument { Type::Path(mut ty) if ty.qself.is_none() && ty.path.leading_colon.is_none() && ty.path.segments.len() == 1 && match &ty.path.segments[0].arguments { PathArguments::None | PathArguments::AngleBracketed(_) => true, PathArguments::Parenthesized(_) => false, } => { if let Some(eq_token) = input.parse::>()? { let segment = ty.path.segments.pop().unwrap().into_value(); let ident = segment.ident; let generics = match segment.arguments { PathArguments::None => None, PathArguments::AngleBracketed(arguments) => Some(arguments), PathArguments::Parenthesized(_) => unreachable!(), }; return if input.peek(Lit) || input.peek(token::Brace) { Ok(GenericArgument::AssocConst(AssocConst { ident, generics, eq_token, value: const_argument(input)?, })) } else { Ok(GenericArgument::AssocType(AssocType { ident, generics, eq_token, ty: input.parse()?, })) }; } #[cfg(feature = "full")] if let Some(colon_token) = input.parse::>()? { let segment = ty.path.segments.pop().unwrap().into_value(); return Ok(GenericArgument::Constraint(Constraint { ident: segment.ident, generics: match segment.arguments { PathArguments::None => None, PathArguments::AngleBracketed(arguments) => Some(arguments), PathArguments::Parenthesized(_) => unreachable!(), }, colon_token, bounds: { let mut bounds = Punctuated::new(); loop { if input.peek(Token![,]) || input.peek(Token![>]) { break; } let value: TypeParamBound = input.parse()?; bounds.push_value(value); if !input.peek(Token![+]) { break; } let punct: Token![+] = input.parse()?; bounds.push_punct(punct); } bounds }, })); } argument = Type::Path(ty); } _ => {} } Ok(GenericArgument::Type(argument)) } } pub(crate) fn const_argument(input: ParseStream) -> Result { let lookahead = input.lookahead1(); if input.peek(Lit) { let lit = input.parse()?; return Ok(Expr::Lit(lit)); } if input.peek(Ident) { let ident: Ident = input.parse()?; return Ok(Expr::Path(ExprPath { attrs: Vec::new(), qself: None, path: Path::from(ident), })); } if input.peek(token::Brace) { #[cfg(feature = "full")] { let block: ExprBlock = input.parse()?; return Ok(Expr::Block(block)); } #[cfg(not(feature = "full"))] { let begin = input.fork(); let content; braced!(content in input); content.parse::()?; let verbatim = verbatim::between(&begin, input); return Ok(Expr::Verbatim(verbatim)); } } Err(lookahead.error()) } impl AngleBracketedGenericArguments { /// Parse `::<…>` with mandatory leading `::`. /// /// The ordinary [`Parse`] impl for `AngleBracketedGenericArguments` /// parses optional leading `::`. #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))] pub fn parse_turbofish(input: ParseStream) -> Result { let colon2_token: Token![::] = input.parse()?; Self::do_parse(Some(colon2_token), input) } pub(crate) fn do_parse( colon2_token: Option, input: ParseStream, ) -> Result { Ok(AngleBracketedGenericArguments { colon2_token, lt_token: input.parse()?, args: { let mut args = Punctuated::new(); loop { if input.peek(Token![>]) { break; } let value: GenericArgument = input.parse()?; args.push_value(value); if input.peek(Token![>]) { break; } let punct: Token![,] = input.parse()?; args.push_punct(punct); } args }, gt_token: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for AngleBracketedGenericArguments { fn parse(input: ParseStream) -> Result { let colon2_token: Option = input.parse()?; Self::do_parse(colon2_token, input) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ParenthesizedGenericArguments { fn parse(input: ParseStream) -> Result { let content; Ok(ParenthesizedGenericArguments { paren_token: parenthesized!(content in input), inputs: content.parse_terminated(Type::parse, Token![,])?, output: input.call(ReturnType::without_plus)?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for PathSegment { fn parse(input: ParseStream) -> Result { Self::parse_helper(input, false) } } impl PathSegment { fn parse_helper(input: ParseStream, expr_style: bool) -> Result { if input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![crate]) || cfg!(feature = "full") && input.peek(Token![try]) { let ident = input.call(Ident::parse_any)?; return Ok(PathSegment::from(ident)); } let ident = if input.peek(Token![Self]) { input.call(Ident::parse_any)? } else { input.parse()? }; if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=]) || input.peek(Token![::]) && input.peek3(Token![<]) { Ok(PathSegment { ident, arguments: PathArguments::AngleBracketed(input.parse()?), }) } else { Ok(PathSegment::from(ident)) } } } impl Path { /// Parse a `Path` containing no path arguments on any of its segments. /// /// # Example /// /// ``` /// use syn::{Path, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // A simplified single `use` statement like: /// // /// // use std::collections::HashMap; /// // /// // Note that generic parameters are not allowed in a `use` statement /// // so the following must not be accepted. /// // /// // use a::::c; /// struct SingleUse { /// use_token: Token![use], /// path: Path, /// } /// /// impl Parse for SingleUse { /// fn parse(input: ParseStream) -> Result { /// Ok(SingleUse { /// use_token: input.parse()?, /// path: input.call(Path::parse_mod_style)?, /// }) /// } /// } /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_mod_style(input: ParseStream) -> Result { Ok(Path { leading_colon: input.parse()?, segments: { let mut segments = Punctuated::new(); loop { if !input.peek(Ident) && !input.peek(Token![super]) && !input.peek(Token![self]) && !input.peek(Token![Self]) && !input.peek(Token![crate]) { break; } let ident = Ident::parse_any(input)?; segments.push_value(PathSegment::from(ident)); if !input.peek(Token![::]) { break; } let punct = input.parse()?; segments.push_punct(punct); } if segments.is_empty() { return Err(input.parse::().unwrap_err()); } else if segments.trailing_punct() { return Err(input.error("expected path segment after `::`")); } segments }, }) } pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result { let mut path = Path { leading_colon: input.parse()?, segments: { let mut segments = Punctuated::new(); let value = PathSegment::parse_helper(input, expr_style)?; segments.push_value(value); segments }, }; Path::parse_rest(input, &mut path, expr_style)?; Ok(path) } pub(crate) fn parse_rest( input: ParseStream, path: &mut Self, expr_style: bool, ) -> Result<()> { while input.peek(Token![::]) && !input.peek3(token::Paren) { let punct: Token![::] = input.parse()?; path.segments.push_punct(punct); let value = PathSegment::parse_helper(input, expr_style)?; path.segments.push_value(value); } Ok(()) } pub(crate) fn is_mod_style(&self) -> bool { self.segments .iter() .all(|segment| segment.arguments.is_none()) } } pub(crate) fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option, Path)> { if input.peek(Token![<]) { let lt_token: Token![<] = input.parse()?; let this: Type = input.parse()?; let path = if input.peek(Token![as]) { let as_token: Token![as] = input.parse()?; let path: Path = input.parse()?; Some((as_token, path)) } else { None }; let gt_token: Token![>] = input.parse()?; let colon2_token: Token![::] = input.parse()?; let mut rest = Punctuated::new(); loop { let path = PathSegment::parse_helper(input, expr_style)?; rest.push_value(path); if !input.peek(Token![::]) { break; } let punct: Token![::] = input.parse()?; rest.push_punct(punct); } let (position, as_token, path) = match path { Some((as_token, mut path)) => { let pos = path.segments.len(); path.segments.push_punct(colon2_token); path.segments.extend(rest.into_pairs()); (pos, Some(as_token), path) } None => { let path = Path { leading_colon: Some(colon2_token), segments: rest, }; (0, None, path) } }; let qself = QSelf { lt_token, ty: Box::new(this), position, as_token, gt_token, }; Ok((Some(qself), path)) } else { let path = Path::parse_helper(input, expr_style)?; Ok((None, path)) } } } #[cfg(feature = "printing")] pub(crate) mod printing { use crate::generics; use crate::path::{ AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument, ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, }; use crate::print::TokensOrDefault; #[cfg(feature = "parsing")] use crate::spanned::Spanned; #[cfg(feature = "parsing")] use proc_macro2::Span; use proc_macro2::TokenStream; use quote::ToTokens; use std::cmp; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Path { fn to_tokens(&self, tokens: &mut TokenStream) { self.leading_colon.to_tokens(tokens); self.segments.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PathSegment { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); self.arguments.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PathArguments { fn to_tokens(&self, tokens: &mut TokenStream) { match self { PathArguments::None => {} PathArguments::AngleBracketed(arguments) => { arguments.to_tokens(tokens); } PathArguments::Parenthesized(arguments) => { arguments.to_tokens(tokens); } } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for GenericArgument { #[allow(clippy::match_same_arms)] fn to_tokens(&self, tokens: &mut TokenStream) { match self { GenericArgument::Lifetime(lt) => lt.to_tokens(tokens), GenericArgument::Type(ty) => ty.to_tokens(tokens), GenericArgument::Const(expr) => { generics::printing::print_const_argument(expr, tokens); } GenericArgument::AssocType(assoc) => assoc.to_tokens(tokens), GenericArgument::AssocConst(assoc) => assoc.to_tokens(tokens), GenericArgument::Constraint(constraint) => constraint.to_tokens(tokens), } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for AngleBracketedGenericArguments { fn to_tokens(&self, tokens: &mut TokenStream) { self.colon2_token.to_tokens(tokens); self.lt_token.to_tokens(tokens); // Print lifetimes before types/consts/bindings, regardless of their // order in self.args. let mut trailing_or_empty = true; for param in self.args.pairs() { match param.value() { GenericArgument::Lifetime(_) => { param.to_tokens(tokens); trailing_or_empty = param.punct().is_some(); } GenericArgument::Type(_) | GenericArgument::Const(_) | GenericArgument::AssocType(_) | GenericArgument::AssocConst(_) | GenericArgument::Constraint(_) => {} } } for param in self.args.pairs() { match param.value() { GenericArgument::Type(_) | GenericArgument::Const(_) | GenericArgument::AssocType(_) | GenericArgument::AssocConst(_) | GenericArgument::Constraint(_) => { if !trailing_or_empty { ::default().to_tokens(tokens); } param.to_tokens(tokens); trailing_or_empty = param.punct().is_some(); } GenericArgument::Lifetime(_) => {} } } self.gt_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for AssocType { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.ty.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for AssocConst { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.eq_token.to_tokens(tokens); generics::printing::print_const_argument(&self.value, tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Constraint { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.bounds.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ParenthesizedGenericArguments { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { self.inputs.to_tokens(tokens); }); self.output.to_tokens(tokens); } } pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option, path: &Path) { let qself = match qself { Some(qself) => qself, None => { path.to_tokens(tokens); return; } }; qself.lt_token.to_tokens(tokens); qself.ty.to_tokens(tokens); let pos = cmp::min(qself.position, path.segments.len()); let mut segments = path.segments.pairs(); if pos > 0 { TokensOrDefault(&qself.as_token).to_tokens(tokens); path.leading_colon.to_tokens(tokens); for (i, segment) in segments.by_ref().take(pos).enumerate() { if i + 1 == pos { segment.value().to_tokens(tokens); qself.gt_token.to_tokens(tokens); segment.punct().to_tokens(tokens); } else { segment.to_tokens(tokens); } } } else { qself.gt_token.to_tokens(tokens); path.leading_colon.to_tokens(tokens); } for segment in segments { segment.to_tokens(tokens); } } #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] impl Spanned for QSelf { fn span(&self) -> Span { struct QSelfDelimiters<'a>(&'a QSelf); impl<'a> ToTokens for QSelfDelimiters<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { self.0.lt_token.to_tokens(tokens); self.0.gt_token.to_tokens(tokens); } } QSelfDelimiters(self).span() } } } syn/src/punctuated.rs0000644000175000017500000007500714661133735015674 0ustar jamespagejamespage//! A punctuated sequence of syntax tree nodes separated by punctuation. //! //! Lots of things in Rust are punctuated sequences. //! //! - The fields of a struct are `Punctuated`. //! - The segments of a path are `Punctuated`. //! - The bounds on a generic parameter are `Punctuated`. //! - The arguments to a function call are `Punctuated`. //! //! This module provides a common representation for these punctuated sequences //! in the form of the [`Punctuated`] type. We store a vector of pairs of //! syntax tree node + punctuation, where every node in the sequence is followed //! by punctuation except for possibly the final one. //! //! [`Punctuated`]: Punctuated //! //! ```text //! a_function_call(arg1, arg2, arg3); //! ~~~~^ ~~~~^ ~~~~ //! ``` use crate::drops::{NoDrop, TrivialDrop}; #[cfg(feature = "parsing")] use crate::error::Result; #[cfg(feature = "parsing")] use crate::parse::{Parse, ParseStream}; #[cfg(feature = "parsing")] use crate::token::Token; #[cfg(feature = "extra-traits")] use std::fmt::{self, Debug}; #[cfg(feature = "extra-traits")] use std::hash::{Hash, Hasher}; #[cfg(any(feature = "full", feature = "derive"))] use std::iter; use std::ops::{Index, IndexMut}; use std::option; use std::slice; use std::vec; /// **A punctuated sequence of syntax tree nodes of type `T` separated by /// punctuation of type `P`.** /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub struct Punctuated { inner: Vec<(T, P)>, last: Option>, } impl Punctuated { /// Creates an empty punctuated sequence. pub const fn new() -> Self { Punctuated { inner: Vec::new(), last: None, } } /// Determines whether this punctuated sequence is empty, meaning it /// contains no syntax tree nodes or punctuation. pub fn is_empty(&self) -> bool { self.inner.len() == 0 && self.last.is_none() } /// Returns the number of syntax tree nodes in this punctuated sequence. /// /// This is the number of nodes of type `T`, not counting the punctuation of /// type `P`. pub fn len(&self) -> usize { self.inner.len() + if self.last.is_some() { 1 } else { 0 } } /// Borrows the first element in this sequence. pub fn first(&self) -> Option<&T> { self.iter().next() } /// Mutably borrows the first element in this sequence. pub fn first_mut(&mut self) -> Option<&mut T> { self.iter_mut().next() } /// Borrows the last element in this sequence. pub fn last(&self) -> Option<&T> { self.iter().next_back() } /// Mutably borrows the last element in this sequence. pub fn last_mut(&mut self) -> Option<&mut T> { self.iter_mut().next_back() } /// Borrows the element at the given index. pub fn get(&mut self, index: usize) -> Option<&T> { if let Some((value, _punct)) = self.inner.get(index) { Some(value) } else if index == self.inner.len() { self.last.as_deref() } else { None } } /// Mutably borrows the element at the given index. pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { let inner_len = self.inner.len(); if let Some((value, _punct)) = self.inner.get_mut(index) { Some(value) } else if index == inner_len { self.last.as_deref_mut() } else { None } } /// Returns an iterator over borrowed syntax tree nodes of type `&T`. pub fn iter(&self) -> Iter { Iter { inner: Box::new(NoDrop::new(PrivateIter { inner: self.inner.iter(), last: self.last.as_ref().map(Box::as_ref).into_iter(), })), } } /// Returns an iterator over mutably borrowed syntax tree nodes of type /// `&mut T`. pub fn iter_mut(&mut self) -> IterMut { IterMut { inner: Box::new(NoDrop::new(PrivateIterMut { inner: self.inner.iter_mut(), last: self.last.as_mut().map(Box::as_mut).into_iter(), })), } } /// Returns an iterator over the contents of this sequence as borrowed /// punctuated pairs. pub fn pairs(&self) -> Pairs { Pairs { inner: self.inner.iter(), last: self.last.as_ref().map(Box::as_ref).into_iter(), } } /// Returns an iterator over the contents of this sequence as mutably /// borrowed punctuated pairs. pub fn pairs_mut(&mut self) -> PairsMut { PairsMut { inner: self.inner.iter_mut(), last: self.last.as_mut().map(Box::as_mut).into_iter(), } } /// Returns an iterator over the contents of this sequence as owned /// punctuated pairs. pub fn into_pairs(self) -> IntoPairs { IntoPairs { inner: self.inner.into_iter(), last: self.last.map(|t| *t).into_iter(), } } /// Appends a syntax tree node onto the end of this punctuated sequence. The /// sequence must already have a trailing punctuation, or be empty. /// /// Use [`push`] instead if the punctuated sequence may or may not already /// have trailing punctuation. /// /// [`push`]: Punctuated::push /// /// # Panics /// /// Panics if the sequence is nonempty and does not already have a trailing /// punctuation. pub fn push_value(&mut self, value: T) { assert!( self.empty_or_trailing(), "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation", ); self.last = Some(Box::new(value)); } /// Appends a trailing punctuation onto the end of this punctuated sequence. /// The sequence must be non-empty and must not already have trailing /// punctuation. /// /// # Panics /// /// Panics if the sequence is empty or already has a trailing punctuation. pub fn push_punct(&mut self, punctuation: P) { assert!( self.last.is_some(), "Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation", ); let last = self.last.take().unwrap(); self.inner.push((*last, punctuation)); } /// Removes the last punctuated pair from this sequence, or `None` if the /// sequence is empty. pub fn pop(&mut self) -> Option> { if self.last.is_some() { self.last.take().map(|t| Pair::End(*t)) } else { self.inner.pop().map(|(t, p)| Pair::Punctuated(t, p)) } } /// Removes the trailing punctuation from this punctuated sequence, or /// `None` if there isn't any. pub fn pop_punct(&mut self) -> Option

{ if self.last.is_some() { None } else { let (t, p) = self.inner.pop()?; self.last = Some(Box::new(t)); Some(p) } } /// Determines whether this punctuated sequence ends with a trailing /// punctuation. pub fn trailing_punct(&self) -> bool { self.last.is_none() && !self.is_empty() } /// Returns true if either this `Punctuated` is empty, or it has a trailing /// punctuation. /// /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`. pub fn empty_or_trailing(&self) -> bool { self.last.is_none() } /// Appends a syntax tree node onto the end of this punctuated sequence. /// /// If there is not a trailing punctuation in this sequence when this method /// is called, the default value of punctuation type `P` is inserted before /// the given value of type `T`. pub fn push(&mut self, value: T) where P: Default, { if !self.empty_or_trailing() { self.push_punct(Default::default()); } self.push_value(value); } /// Inserts an element at position `index`. /// /// # Panics /// /// Panics if `index` is greater than the number of elements previously in /// this punctuated sequence. pub fn insert(&mut self, index: usize, value: T) where P: Default, { assert!( index <= self.len(), "Punctuated::insert: index out of range", ); if index == self.len() { self.push(value); } else { self.inner.insert(index, (value, Default::default())); } } /// Clears the sequence of all values and punctuation, making it empty. pub fn clear(&mut self) { self.inner.clear(); self.last = None; } /// Parses zero or more occurrences of `T` separated by punctuation of type /// `P`, with optional trailing punctuation. /// /// Parsing continues until the end of this parse stream. The entire content /// of this parse stream must consist of `T` and `P`. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_terminated(input: ParseStream) -> Result where T: Parse, P: Parse, { Self::parse_terminated_with(input, T::parse) } /// Parses zero or more occurrences of `T` using the given parse function, /// separated by punctuation of type `P`, with optional trailing /// punctuation. /// /// Like [`parse_terminated`], the entire content of this stream is expected /// to be parsed. /// /// [`parse_terminated`]: Punctuated::parse_terminated #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_terminated_with( input: ParseStream, parser: fn(ParseStream) -> Result, ) -> Result where P: Parse, { let mut punctuated = Punctuated::new(); loop { if input.is_empty() { break; } let value = parser(input)?; punctuated.push_value(value); if input.is_empty() { break; } let punct = input.parse()?; punctuated.push_punct(punct); } Ok(punctuated) } /// Parses one or more occurrences of `T` separated by punctuation of type /// `P`, not accepting trailing punctuation. /// /// Parsing continues as long as punctuation `P` is present at the head of /// the stream. This method returns upon parsing a `T` and observing that it /// is not followed by a `P`, even if there are remaining tokens in the /// stream. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_separated_nonempty(input: ParseStream) -> Result where T: Parse, P: Token + Parse, { Self::parse_separated_nonempty_with(input, T::parse) } /// Parses one or more occurrences of `T` using the given parse function, /// separated by punctuation of type `P`, not accepting trailing /// punctuation. /// /// Like [`parse_separated_nonempty`], may complete early without parsing /// the entire content of this stream. /// /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_separated_nonempty_with( input: ParseStream, parser: fn(ParseStream) -> Result, ) -> Result where P: Token + Parse, { let mut punctuated = Punctuated::new(); loop { let value = parser(input)?; punctuated.push_value(value); if !P::peek(input.cursor()) { break; } let punct = input.parse()?; punctuated.push_punct(punct); } Ok(punctuated) } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Punctuated where T: Clone, P: Clone, { fn clone(&self) -> Self { Punctuated { inner: self.inner.clone(), last: self.last.clone(), } } fn clone_from(&mut self, other: &Self) { self.inner.clone_from(&other.inner); self.last.clone_from(&other.last); } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for Punctuated where T: Eq, P: Eq, { } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for Punctuated where T: PartialEq, P: PartialEq, { fn eq(&self, other: &Self) -> bool { let Punctuated { inner, last } = self; *inner == other.inner && *last == other.last } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for Punctuated where T: Hash, P: Hash, { fn hash(&self, state: &mut H) { let Punctuated { inner, last } = self; inner.hash(state); last.hash(state); } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for Punctuated { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut list = f.debug_list(); for (t, p) in &self.inner { list.entry(t); list.entry(p); } if let Some(last) = &self.last { list.entry(last); } list.finish() } } impl FromIterator for Punctuated where P: Default, { fn from_iter>(i: I) -> Self { let mut ret = Punctuated::new(); ret.extend(i); ret } } impl Extend for Punctuated where P: Default, { fn extend>(&mut self, i: I) { for value in i { self.push(value); } } } impl FromIterator> for Punctuated { fn from_iter>>(i: I) -> Self { let mut ret = Punctuated::new(); do_extend(&mut ret, i.into_iter()); ret } } impl Extend> for Punctuated where P: Default, { fn extend>>(&mut self, i: I) { if !self.empty_or_trailing() { self.push_punct(P::default()); } do_extend(self, i.into_iter()); } } fn do_extend(punctuated: &mut Punctuated, i: I) where I: Iterator>, { let mut nomore = false; for pair in i { if nomore { panic!("punctuated extended with items after a Pair::End"); } match pair { Pair::Punctuated(a, b) => punctuated.inner.push((a, b)), Pair::End(a) => { punctuated.last = Some(Box::new(a)); nomore = true; } } } } impl IntoIterator for Punctuated { type Item = T; type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { let mut elements = Vec::with_capacity(self.len()); elements.extend(self.inner.into_iter().map(|pair| pair.0)); elements.extend(self.last.map(|t| *t)); IntoIter { inner: elements.into_iter(), } } } impl<'a, T, P> IntoIterator for &'a Punctuated { type Item = &'a T; type IntoIter = Iter<'a, T>; fn into_iter(self) -> Self::IntoIter { Punctuated::iter(self) } } impl<'a, T, P> IntoIterator for &'a mut Punctuated { type Item = &'a mut T; type IntoIter = IterMut<'a, T>; fn into_iter(self) -> Self::IntoIter { Punctuated::iter_mut(self) } } impl Default for Punctuated { fn default() -> Self { Punctuated::new() } } /// An iterator over borrowed pairs of type `Pair<&T, &P>`. /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub struct Pairs<'a, T: 'a, P: 'a> { inner: slice::Iter<'a, (T, P)>, last: option::IntoIter<&'a T>, } impl<'a, T, P> Iterator for Pairs<'a, T, P> { type Item = Pair<&'a T, &'a P>; fn next(&mut self) -> Option { self.inner .next() .map(|(t, p)| Pair::Punctuated(t, p)) .or_else(|| self.last.next().map(Pair::End)) } fn size_hint(&self) -> (usize, Option) { (self.len(), Some(self.len())) } } impl<'a, T, P> DoubleEndedIterator for Pairs<'a, T, P> { fn next_back(&mut self) -> Option { self.last .next() .map(Pair::End) .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p))) } } impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> { fn len(&self) -> usize { self.inner.len() + self.last.len() } } // No Clone bound on T or P. impl<'a, T, P> Clone for Pairs<'a, T, P> { fn clone(&self) -> Self { Pairs { inner: self.inner.clone(), last: self.last.clone(), } } } /// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`. /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub struct PairsMut<'a, T: 'a, P: 'a> { inner: slice::IterMut<'a, (T, P)>, last: option::IntoIter<&'a mut T>, } impl<'a, T, P> Iterator for PairsMut<'a, T, P> { type Item = Pair<&'a mut T, &'a mut P>; fn next(&mut self) -> Option { self.inner .next() .map(|(t, p)| Pair::Punctuated(t, p)) .or_else(|| self.last.next().map(Pair::End)) } fn size_hint(&self) -> (usize, Option) { (self.len(), Some(self.len())) } } impl<'a, T, P> DoubleEndedIterator for PairsMut<'a, T, P> { fn next_back(&mut self) -> Option { self.last .next() .map(Pair::End) .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p))) } } impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> { fn len(&self) -> usize { self.inner.len() + self.last.len() } } /// An iterator over owned pairs of type `Pair`. /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub struct IntoPairs { inner: vec::IntoIter<(T, P)>, last: option::IntoIter, } impl Iterator for IntoPairs { type Item = Pair; fn next(&mut self) -> Option { self.inner .next() .map(|(t, p)| Pair::Punctuated(t, p)) .or_else(|| self.last.next().map(Pair::End)) } fn size_hint(&self) -> (usize, Option) { (self.len(), Some(self.len())) } } impl DoubleEndedIterator for IntoPairs { fn next_back(&mut self) -> Option { self.last .next() .map(Pair::End) .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p))) } } impl ExactSizeIterator for IntoPairs { fn len(&self) -> usize { self.inner.len() + self.last.len() } } impl Clone for IntoPairs where T: Clone, P: Clone, { fn clone(&self) -> Self { IntoPairs { inner: self.inner.clone(), last: self.last.clone(), } } } /// An iterator over owned values of type `T`. /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub struct IntoIter { inner: vec::IntoIter, } impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { (self.len(), Some(self.len())) } } impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { self.inner.next_back() } } impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { self.inner.len() } } impl Clone for IntoIter where T: Clone, { fn clone(&self) -> Self { IntoIter { inner: self.inner.clone(), } } } /// An iterator over borrowed values of type `&T`. /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub struct Iter<'a, T: 'a> { inner: Box + 'a>>, } trait IterTrait<'a, T: 'a>: Iterator + DoubleEndedIterator + ExactSizeIterator { fn clone_box(&self) -> Box + 'a>>; } struct PrivateIter<'a, T: 'a, P: 'a> { inner: slice::Iter<'a, (T, P)>, last: option::IntoIter<&'a T>, } impl<'a, T, P> TrivialDrop for PrivateIter<'a, T, P> where slice::Iter<'a, (T, P)>: TrivialDrop, option::IntoIter<&'a T>: TrivialDrop, { } #[cfg(any(feature = "full", feature = "derive"))] pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> { Iter { inner: Box::new(NoDrop::new(iter::empty())), } } // No Clone bound on T. impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Self { Iter { inner: self.inner.clone_box(), } } } impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { (self.len(), Some(self.len())) } } impl<'a, T> DoubleEndedIterator for Iter<'a, T> { fn next_back(&mut self) -> Option { self.inner.next_back() } } impl<'a, T> ExactSizeIterator for Iter<'a, T> { fn len(&self) -> usize { self.inner.len() } } impl<'a, T, P> Iterator for PrivateIter<'a, T, P> { type Item = &'a T; fn next(&mut self) -> Option { self.inner .next() .map(|pair| &pair.0) .or_else(|| self.last.next()) } } impl<'a, T, P> DoubleEndedIterator for PrivateIter<'a, T, P> { fn next_back(&mut self) -> Option { self.last .next() .or_else(|| self.inner.next_back().map(|pair| &pair.0)) } } impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> { fn len(&self) -> usize { self.inner.len() + self.last.len() } } // No Clone bound on T or P. impl<'a, T, P> Clone for PrivateIter<'a, T, P> { fn clone(&self) -> Self { PrivateIter { inner: self.inner.clone(), last: self.last.clone(), } } } impl<'a, T, I> IterTrait<'a, T> for I where T: 'a, I: DoubleEndedIterator + ExactSizeIterator + Clone + TrivialDrop + 'a, { fn clone_box(&self) -> Box + 'a>> { Box::new(NoDrop::new(self.clone())) } } /// An iterator over mutably borrowed values of type `&mut T`. /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub struct IterMut<'a, T: 'a> { inner: Box + 'a>>, } trait IterMutTrait<'a, T: 'a>: DoubleEndedIterator + ExactSizeIterator { } struct PrivateIterMut<'a, T: 'a, P: 'a> { inner: slice::IterMut<'a, (T, P)>, last: option::IntoIter<&'a mut T>, } impl<'a, T, P> TrivialDrop for PrivateIterMut<'a, T, P> where slice::IterMut<'a, (T, P)>: TrivialDrop, option::IntoIter<&'a mut T>: TrivialDrop, { } #[cfg(any(feature = "full", feature = "derive"))] pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> { IterMut { inner: Box::new(NoDrop::new(iter::empty())), } } impl<'a, T> Iterator for IterMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option { self.inner.next() } fn size_hint(&self) -> (usize, Option) { (self.len(), Some(self.len())) } } impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { fn next_back(&mut self) -> Option { self.inner.next_back() } } impl<'a, T> ExactSizeIterator for IterMut<'a, T> { fn len(&self) -> usize { self.inner.len() } } impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> { type Item = &'a mut T; fn next(&mut self) -> Option { self.inner .next() .map(|pair| &mut pair.0) .or_else(|| self.last.next()) } } impl<'a, T, P> DoubleEndedIterator for PrivateIterMut<'a, T, P> { fn next_back(&mut self) -> Option { self.last .next() .or_else(|| self.inner.next_back().map(|pair| &mut pair.0)) } } impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> { fn len(&self) -> usize { self.inner.len() + self.last.len() } } impl<'a, T, I> IterMutTrait<'a, T> for I where T: 'a, I: DoubleEndedIterator + ExactSizeIterator + 'a, { } /// A single syntax tree node of type `T` followed by its trailing punctuation /// of type `P` if any. /// /// Refer to the [module documentation] for details about punctuated sequences. /// /// [module documentation]: self pub enum Pair { Punctuated(T, P), End(T), } impl Pair { /// Extracts the syntax tree node from this punctuated pair, discarding the /// following punctuation. pub fn into_value(self) -> T { match self { Pair::Punctuated(t, _) | Pair::End(t) => t, } } /// Borrows the syntax tree node from this punctuated pair. pub fn value(&self) -> &T { match self { Pair::Punctuated(t, _) | Pair::End(t) => t, } } /// Mutably borrows the syntax tree node from this punctuated pair. pub fn value_mut(&mut self) -> &mut T { match self { Pair::Punctuated(t, _) | Pair::End(t) => t, } } /// Borrows the punctuation from this punctuated pair, unless this pair is /// the final one and there is no trailing punctuation. pub fn punct(&self) -> Option<&P> { match self { Pair::Punctuated(_, p) => Some(p), Pair::End(_) => None, } } /// Mutably borrows the punctuation from this punctuated pair, unless the /// pair is the final one and there is no trailing punctuation. /// /// # Example /// /// ``` /// # use proc_macro2::Span; /// # use syn::punctuated::Punctuated; /// # use syn::{parse_quote, Token, TypeParamBound}; /// # /// # let mut punctuated = Punctuated::::new(); /// # let span = Span::call_site(); /// # /// punctuated.insert(0, parse_quote!('lifetime)); /// if let Some(punct) = punctuated.pairs_mut().next().unwrap().punct_mut() { /// punct.span = span; /// } /// ``` pub fn punct_mut(&mut self) -> Option<&mut P> { match self { Pair::Punctuated(_, p) => Some(p), Pair::End(_) => None, } } /// Creates a punctuated pair out of a syntax tree node and an optional /// following punctuation. pub fn new(t: T, p: Option

) -> Self { match p { Some(p) => Pair::Punctuated(t, p), None => Pair::End(t), } } /// Produces this punctuated pair as a tuple of syntax tree node and /// optional following punctuation. pub fn into_tuple(self) -> (T, Option

) { match self { Pair::Punctuated(t, p) => (t, Some(p)), Pair::End(t) => (t, None), } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Pair<&T, &P> { pub fn cloned(self) -> Pair where T: Clone, P: Clone, { match self { Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()), Pair::End(t) => Pair::End(t.clone()), } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Pair where T: Clone, P: Clone, { fn clone(&self) -> Self { match self { Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()), Pair::End(t) => Pair::End(t.clone()), } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for Pair where T: Copy, P: Copy, { } impl Index for Punctuated { type Output = T; fn index(&self, index: usize) -> &Self::Output { if index == self.len() - 1 { match &self.last { Some(t) => t, None => &self.inner[index].0, } } else { &self.inner[index].0 } } } impl IndexMut for Punctuated { fn index_mut(&mut self, index: usize) -> &mut Self::Output { if index == self.len() - 1 { match &mut self.last { Some(t) => t, None => &mut self.inner[index].0, } } else { &mut self.inner[index].0 } } } #[cfg(all(feature = "fold", any(feature = "full", feature = "derive")))] pub(crate) fn fold( punctuated: Punctuated, fold: &mut V, mut f: F, ) -> Punctuated where V: ?Sized, F: FnMut(&mut V, T) -> T, { Punctuated { inner: punctuated .inner .into_iter() .map(|(t, p)| (f(fold, t), p)) .collect(), last: match punctuated.last { Some(t) => Some(Box::new(f(fold, *t))), None => None, }, } } #[cfg(feature = "printing")] mod printing { use crate::punctuated::{Pair, Punctuated}; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Punctuated where T: ToTokens, P: ToTokens, { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.pairs()); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Pair where T: ToTokens, P: ToTokens, { fn to_tokens(&self, tokens: &mut TokenStream) { match self { Pair::Punctuated(a, b) => { a.to_tokens(tokens); b.to_tokens(tokens); } Pair::End(a) => a.to_tokens(tokens), } } } } syn/src/lookahead.rs0000644000175000017500000001214414661133735015440 0ustar jamespagejamespageuse crate::buffer::Cursor; use crate::error::{self, Error}; use crate::sealed::lookahead::Sealed; use crate::span::IntoSpans; use crate::token::Token; use proc_macro2::Span; use std::cell::RefCell; /// Support for checking the next token in a stream to decide how to parse. /// /// An important advantage over [`ParseStream::peek`] is that here we /// automatically construct an appropriate error message based on the token /// alternatives that get peeked. If you are producing your own error message, /// go ahead and use `ParseStream::peek` instead. /// /// Use [`ParseStream::lookahead1`] to construct this object. /// /// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek /// [`ParseStream::lookahead1`]: crate::parse::ParseBuffer::lookahead1 /// /// Consuming tokens from the source stream after constructing a lookahead /// object does not also advance the lookahead object. /// /// # Example /// /// ``` /// use syn::{ConstParam, Ident, Lifetime, LifetimeParam, Result, Token, TypeParam}; /// use syn::parse::{Parse, ParseStream}; /// /// // A generic parameter, a single one of the comma-separated elements inside /// // angle brackets in: /// // /// // fn f() { ... } /// // /// // On invalid input, lookahead gives us a reasonable error message. /// // /// // error: expected one of: identifier, lifetime, `const` /// // | /// // 5 | fn f() {} /// // | ^ /// enum GenericParam { /// Type(TypeParam), /// Lifetime(LifetimeParam), /// Const(ConstParam), /// } /// /// impl Parse for GenericParam { /// fn parse(input: ParseStream) -> Result { /// let lookahead = input.lookahead1(); /// if lookahead.peek(Ident) { /// input.parse().map(GenericParam::Type) /// } else if lookahead.peek(Lifetime) { /// input.parse().map(GenericParam::Lifetime) /// } else if lookahead.peek(Token![const]) { /// input.parse().map(GenericParam::Const) /// } else { /// Err(lookahead.error()) /// } /// } /// } /// ``` pub struct Lookahead1<'a> { scope: Span, cursor: Cursor<'a>, comparisons: RefCell>, } pub(crate) fn new(scope: Span, cursor: Cursor) -> Lookahead1 { Lookahead1 { scope, cursor, comparisons: RefCell::new(Vec::new()), } } fn peek_impl( lookahead: &Lookahead1, peek: fn(Cursor) -> bool, display: fn() -> &'static str, ) -> bool { if peek(lookahead.cursor) { return true; } lookahead.comparisons.borrow_mut().push(display()); false } impl<'a> Lookahead1<'a> { /// Looks at the next token in the parse stream to determine whether it /// matches the requested type of token. /// /// # Syntax /// /// Note that this method does not use turbofish syntax. Pass the peek type /// inside of parentheses. /// /// - `input.peek(Token![struct])` /// - `input.peek(Token![==])` /// - `input.peek(Ident)` *(does not accept keywords)* /// - `input.peek(Ident::peek_any)` /// - `input.peek(Lifetime)` /// - `input.peek(token::Brace)` pub fn peek(&self, token: T) -> bool { let _ = token; peek_impl(self, T::Token::peek, T::Token::display) } /// Triggers an error at the current position of the parse stream. /// /// The error message will identify all of the expected token types that /// have been peeked against this lookahead instance. pub fn error(self) -> Error { let comparisons = self.comparisons.into_inner(); match comparisons.len() { 0 => { if self.cursor.eof() { Error::new(self.scope, "unexpected end of input") } else { Error::new(self.cursor.span(), "unexpected token") } } 1 => { let message = format!("expected {}", comparisons[0]); error::new_at(self.scope, self.cursor, message) } 2 => { let message = format!("expected {} or {}", comparisons[0], comparisons[1]); error::new_at(self.scope, self.cursor, message) } _ => { let join = comparisons.join(", "); let message = format!("expected one of: {}", join); error::new_at(self.scope, self.cursor, message) } } } } /// Types that can be parsed by looking at just one token. /// /// Use [`ParseStream::peek`] to peek one of these types in a parse stream /// without consuming it from the stream. /// /// This trait is sealed and cannot be implemented for types outside of Syn. /// /// [`ParseStream::peek`]: crate::parse::ParseBuffer::peek pub trait Peek: Sealed { // Not public API. #[doc(hidden)] type Token: Token; } impl T, T: Token> Peek for F { type Token = T; } pub enum TokenMarker {} impl IntoSpans for TokenMarker { fn into_spans(self) -> S { match self {} } } impl T, T: Token> Sealed for F {} syn/src/custom_punctuation.rs0000644000175000017500000002165414661133735017462 0ustar jamespagejamespage/// Define a type that supports parsing and printing a multi-character symbol /// as if it were a punctuation token. /// /// # Usage /// /// ``` /// syn::custom_punctuation!(LeftRightArrow, <=>); /// ``` /// /// The generated syntax tree node supports the following operations just like /// any built-in punctuation token. /// /// - [Peeking] — `input.peek(LeftRightArrow)` /// /// - [Parsing] — `input.parse::()?` /// /// - [Printing] — `quote!( ... #lrarrow ... )` /// /// - Construction from a [`Span`] — `let lrarrow = LeftRightArrow(sp)` /// /// - Construction from multiple [`Span`] — `let lrarrow = LeftRightArrow([sp, sp, sp])` /// /// - Field access to its spans — `let spans = lrarrow.spans` /// /// [Peeking]: crate::parse::ParseBuffer::peek /// [Parsing]: crate::parse::ParseBuffer::parse /// [Printing]: quote::ToTokens /// [`Span`]: proc_macro2::Span /// /// # Example /// /// ``` /// use proc_macro2::{TokenStream, TokenTree}; /// use syn::parse::{Parse, ParseStream, Peek, Result}; /// use syn::punctuated::Punctuated; /// use syn::Expr; /// /// syn::custom_punctuation!(PathSeparator, ); /// /// // expr expr expr ... /// struct PathSegments { /// segments: Punctuated, /// } /// /// impl Parse for PathSegments { /// fn parse(input: ParseStream) -> Result { /// let mut segments = Punctuated::new(); /// /// let first = parse_until(input, PathSeparator)?; /// segments.push_value(syn::parse2(first)?); /// /// while input.peek(PathSeparator) { /// segments.push_punct(input.parse()?); /// /// let next = parse_until(input, PathSeparator)?; /// segments.push_value(syn::parse2(next)?); /// } /// /// Ok(PathSegments { segments }) /// } /// } /// /// fn parse_until(input: ParseStream, end: E) -> Result { /// let mut tokens = TokenStream::new(); /// while !input.is_empty() && !input.peek(end) { /// let next: TokenTree = input.parse()?; /// tokens.extend(Some(next)); /// } /// Ok(tokens) /// } /// /// fn main() { /// let input = r#" a::b c::d::e "#; /// let _: PathSegments = syn::parse_str(input).unwrap(); /// } /// ``` #[macro_export] macro_rules! custom_punctuation { ($ident:ident, $($tt:tt)+) => { pub struct $ident { #[allow(dead_code)] pub spans: $crate::custom_punctuation_repr!($($tt)+), } #[doc(hidden)] #[allow(dead_code, non_snake_case)] pub fn $ident<__S: $crate::__private::IntoSpans<$crate::custom_punctuation_repr!($($tt)+)>>( spans: __S, ) -> $ident { let _validate_len = 0 $(+ $crate::custom_punctuation_len!(strict, $tt))*; $ident { spans: $crate::__private::IntoSpans::into_spans(spans) } } const _: () = { impl $crate::__private::Default for $ident { fn default() -> Self { $ident($crate::__private::Span::call_site()) } } $crate::impl_parse_for_custom_punctuation!($ident, $($tt)+); $crate::impl_to_tokens_for_custom_punctuation!($ident, $($tt)+); $crate::impl_clone_for_custom_punctuation!($ident, $($tt)+); $crate::impl_extra_traits_for_custom_punctuation!($ident, $($tt)+); }; }; } // Not public API. #[cfg(feature = "parsing")] #[doc(hidden)] #[macro_export] macro_rules! impl_parse_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => { impl $crate::__private::CustomToken for $ident { fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool { $crate::__private::peek_punct(cursor, $crate::stringify_punct!($($tt)+)) } fn display() -> &'static $crate::__private::str { $crate::__private::concat!("`", $crate::stringify_punct!($($tt)+), "`") } } impl $crate::parse::Parse for $ident { fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> { let spans: $crate::custom_punctuation_repr!($($tt)+) = $crate::__private::parse_punct(input, $crate::stringify_punct!($($tt)+))?; Ok($ident(spans)) } } }; } // Not public API. #[cfg(not(feature = "parsing"))] #[doc(hidden)] #[macro_export] macro_rules! impl_parse_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => {}; } // Not public API. #[cfg(feature = "printing")] #[doc(hidden)] #[macro_export] macro_rules! impl_to_tokens_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => { impl $crate::__private::ToTokens for $ident { fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) { $crate::__private::print_punct($crate::stringify_punct!($($tt)+), &self.spans, tokens) } } }; } // Not public API. #[cfg(not(feature = "printing"))] #[doc(hidden)] #[macro_export] macro_rules! impl_to_tokens_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => {}; } // Not public API. #[cfg(feature = "clone-impls")] #[doc(hidden)] #[macro_export] macro_rules! impl_clone_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => { impl $crate::__private::Copy for $ident {} #[allow(clippy::expl_impl_clone_on_copy)] impl $crate::__private::Clone for $ident { fn clone(&self) -> Self { *self } } }; } // Not public API. #[cfg(not(feature = "clone-impls"))] #[doc(hidden)] #[macro_export] macro_rules! impl_clone_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => {}; } // Not public API. #[cfg(feature = "extra-traits")] #[doc(hidden)] #[macro_export] macro_rules! impl_extra_traits_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => { impl $crate::__private::Debug for $ident { fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::FmtResult { $crate::__private::Formatter::write_str(f, $crate::__private::stringify!($ident)) } } impl $crate::__private::Eq for $ident {} impl $crate::__private::PartialEq for $ident { fn eq(&self, _other: &Self) -> $crate::__private::bool { true } } impl $crate::__private::Hash for $ident { fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {} } }; } // Not public API. #[cfg(not(feature = "extra-traits"))] #[doc(hidden)] #[macro_export] macro_rules! impl_extra_traits_for_custom_punctuation { ($ident:ident, $($tt:tt)+) => {}; } // Not public API. #[doc(hidden)] #[macro_export] macro_rules! custom_punctuation_repr { ($($tt:tt)+) => { [$crate::__private::Span; 0 $(+ $crate::custom_punctuation_len!(lenient, $tt))+] }; } // Not public API. #[doc(hidden)] #[macro_export] #[rustfmt::skip] macro_rules! custom_punctuation_len { ($mode:ident, &) => { 1 }; ($mode:ident, &&) => { 2 }; ($mode:ident, &=) => { 2 }; ($mode:ident, @) => { 1 }; ($mode:ident, ^) => { 1 }; ($mode:ident, ^=) => { 2 }; ($mode:ident, :) => { 1 }; ($mode:ident, ,) => { 1 }; ($mode:ident, $) => { 1 }; ($mode:ident, .) => { 1 }; ($mode:ident, ..) => { 2 }; ($mode:ident, ...) => { 3 }; ($mode:ident, ..=) => { 3 }; ($mode:ident, =) => { 1 }; ($mode:ident, ==) => { 2 }; ($mode:ident, =>) => { 2 }; ($mode:ident, >=) => { 2 }; ($mode:ident, >) => { 1 }; ($mode:ident, <-) => { 2 }; ($mode:ident, <=) => { 2 }; ($mode:ident, <) => { 1 }; ($mode:ident, -) => { 1 }; ($mode:ident, -=) => { 2 }; ($mode:ident, !=) => { 2 }; ($mode:ident, !) => { 1 }; ($mode:ident, |) => { 1 }; ($mode:ident, |=) => { 2 }; ($mode:ident, ||) => { 2 }; ($mode:ident, ::) => { 2 }; ($mode:ident, %) => { 1 }; ($mode:ident, %=) => { 2 }; ($mode:ident, +) => { 1 }; ($mode:ident, +=) => { 2 }; ($mode:ident, #) => { 1 }; ($mode:ident, ?) => { 1 }; ($mode:ident, ->) => { 2 }; ($mode:ident, ;) => { 1 }; ($mode:ident, <<) => { 2 }; ($mode:ident, <<=) => { 3 }; ($mode:ident, >>) => { 2 }; ($mode:ident, >>=) => { 3 }; ($mode:ident, /) => { 1 }; ($mode:ident, /=) => { 2 }; ($mode:ident, *) => { 1 }; ($mode:ident, *=) => { 2 }; ($mode:ident, ~) => { 1 }; (lenient, $tt:tt) => { 0 }; (strict, $tt:tt) => {{ $crate::custom_punctuation_unexpected!($tt); 0 }}; } // Not public API. #[doc(hidden)] #[macro_export] macro_rules! custom_punctuation_unexpected { () => {}; } // Not public API. #[doc(hidden)] #[macro_export] macro_rules! stringify_punct { ($($tt:tt)+) => { $crate::__private::concat!($($crate::__private::stringify!($tt)),+) }; } syn/src/print.rs0000644000175000017500000000060614661133735014645 0ustar jamespagejamespageuse proc_macro2::TokenStream; use quote::ToTokens; pub(crate) struct TokensOrDefault<'a, T: 'a>(pub &'a Option); impl<'a, T> ToTokens for TokensOrDefault<'a, T> where T: ToTokens + Default, { fn to_tokens(&self, tokens: &mut TokenStream) { match self.0 { Some(t) => t.to_tokens(tokens), None => T::default().to_tokens(tokens), } } } syn/src/ty.rs0000644000175000017500000012261214661133735014147 0ustar jamespagejamespageuse crate::attr::Attribute; use crate::expr::Expr; use crate::generics::{BoundLifetimes, TypeParamBound}; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::lit::LitStr; use crate::mac::Macro; use crate::path::{Path, QSelf}; use crate::punctuated::Punctuated; use crate::token; use proc_macro2::TokenStream; ast_enum_of_structs! { /// The possible types that a Rust value could have. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum Type { /// A fixed size array type: `[T; n]`. Array(TypeArray), /// A bare function type: `fn(usize) -> bool`. BareFn(TypeBareFn), /// A type contained within invisible delimiters. Group(TypeGroup), /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or /// a lifetime. ImplTrait(TypeImplTrait), /// Indication that a type should be inferred by the compiler: `_`. Infer(TypeInfer), /// A macro in the type position. Macro(TypeMacro), /// The never type: `!`. Never(TypeNever), /// A parenthesized type equivalent to the inner type. Paren(TypeParen), /// A path like `std::slice::Iter`, optionally qualified with a /// self-type as in ` as SomeTrait>::Associated`. Path(TypePath), /// A raw pointer type: `*const T` or `*mut T`. Ptr(TypePtr), /// A reference type: `&'a T` or `&'a mut T`. Reference(TypeReference), /// A dynamically sized slice type: `[T]`. Slice(TypeSlice), /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a /// trait or a lifetime. TraitObject(TypeTraitObject), /// A tuple type: `(A, B, C, String)`. Tuple(TypeTuple), /// Tokens in type position not interpreted by Syn. Verbatim(TokenStream), // For testing exhaustiveness in downstream code, use the following idiom: // // match ty { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Type::Array(ty) => {...} // Type::BareFn(ty) => {...} // ... // Type::Verbatim(ty) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// A fixed size array type: `[T; n]`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeArray { pub bracket_token: token::Bracket, pub elem: Box, pub semi_token: Token![;], pub len: Expr, } } ast_struct! { /// A bare function type: `fn(usize) -> bool`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeBareFn { pub lifetimes: Option, pub unsafety: Option, pub abi: Option, pub fn_token: Token![fn], pub paren_token: token::Paren, pub inputs: Punctuated, pub variadic: Option, pub output: ReturnType, } } ast_struct! { /// A type contained within invisible delimiters. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeGroup { pub group_token: token::Group, pub elem: Box, } } ast_struct! { /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or /// a lifetime. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeImplTrait { pub impl_token: Token![impl], pub bounds: Punctuated, } } ast_struct! { /// Indication that a type should be inferred by the compiler: `_`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeInfer { pub underscore_token: Token![_], } } ast_struct! { /// A macro in the type position. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeMacro { pub mac: Macro, } } ast_struct! { /// The never type: `!`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeNever { pub bang_token: Token![!], } } ast_struct! { /// A parenthesized type equivalent to the inner type. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeParen { pub paren_token: token::Paren, pub elem: Box, } } ast_struct! { /// A path like `std::slice::Iter`, optionally qualified with a /// self-type as in ` as SomeTrait>::Associated`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypePath { pub qself: Option, pub path: Path, } } ast_struct! { /// A raw pointer type: `*const T` or `*mut T`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypePtr { pub star_token: Token![*], pub const_token: Option, pub mutability: Option, pub elem: Box, } } ast_struct! { /// A reference type: `&'a T` or `&'a mut T`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeReference { pub and_token: Token![&], pub lifetime: Option, pub mutability: Option, pub elem: Box, } } ast_struct! { /// A dynamically sized slice type: `[T]`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeSlice { pub bracket_token: token::Bracket, pub elem: Box, } } ast_struct! { /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a /// trait or a lifetime. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeTraitObject { pub dyn_token: Option, pub bounds: Punctuated, } } ast_struct! { /// A tuple type: `(A, B, C, String)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeTuple { pub paren_token: token::Paren, pub elems: Punctuated, } } ast_struct! { /// The binary interface of a function: `extern "C"`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Abi { pub extern_token: Token![extern], pub name: Option, } } ast_struct! { /// An argument in a function type: the `usize` in `fn(usize) -> bool`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BareFnArg { pub attrs: Vec, pub name: Option<(Ident, Token![:])>, pub ty: Type, } } ast_struct! { /// The variadic argument of a function pointer like `fn(usize, ...)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BareVariadic { pub attrs: Vec, pub name: Option<(Ident, Token![:])>, pub dots: Token![...], pub comma: Option, } } ast_enum! { /// Return type of a function signature. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum ReturnType { /// Return type is not specified. /// /// Functions default to `()` and closures default to type inference. Default, /// A particular type is returned. Type(Token![->], Box), } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::{self, Result}; use crate::ext::IdentExt as _; use crate::generics::{BoundLifetimes, TraitBound, TraitBoundModifier, TypeParamBound}; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::mac::{self, Macro}; use crate::parse::{Parse, ParseStream}; use crate::path; use crate::path::{Path, PathArguments, QSelf}; use crate::punctuated::Punctuated; use crate::token; use crate::ty::{ Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject, TypeTuple, }; use crate::verbatim; use proc_macro2::Span; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Type { fn parse(input: ParseStream) -> Result { let allow_plus = true; let allow_group_generic = true; ambig_ty(input, allow_plus, allow_group_generic) } } impl Type { /// In some positions, types may not contain the `+` character, to /// disambiguate them. For example in the expression `1 as T`, T may not /// contain a `+` character. /// /// This parser does not allow a `+`, while the default parser does. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; let allow_group_generic = true; ambig_ty(input, allow_plus, allow_group_generic) } } pub(crate) fn ambig_ty( input: ParseStream, allow_plus: bool, allow_group_generic: bool, ) -> Result { let begin = input.fork(); if input.peek(token::Group) { let mut group: TypeGroup = input.parse()?; if input.peek(Token![::]) && input.peek3(Ident::peek_any) { if let Type::Path(mut ty) = *group.elem { Path::parse_rest(input, &mut ty.path, false)?; return Ok(Type::Path(ty)); } else { return Ok(Type::Path(TypePath { qself: Some(QSelf { lt_token: Token![<](group.group_token.span), position: 0, as_token: None, gt_token: Token![>](group.group_token.span), ty: group.elem, }), path: Path::parse_helper(input, false)?, })); } } else if input.peek(Token![<]) && allow_group_generic || input.peek(Token![::]) && input.peek3(Token![<]) { if let Type::Path(mut ty) = *group.elem { let arguments = &mut ty.path.segments.last_mut().unwrap().arguments; if arguments.is_none() { *arguments = PathArguments::AngleBracketed(input.parse()?); Path::parse_rest(input, &mut ty.path, false)?; return Ok(Type::Path(ty)); } else { group.elem = Box::new(Type::Path(ty)); } } } return Ok(Type::Group(group)); } let mut lifetimes = None::; let mut lookahead = input.lookahead1(); if lookahead.peek(Token![for]) { lifetimes = input.parse()?; lookahead = input.lookahead1(); if !lookahead.peek(Ident) && !lookahead.peek(Token![fn]) && !lookahead.peek(Token![unsafe]) && !lookahead.peek(Token![extern]) && !lookahead.peek(Token![super]) && !lookahead.peek(Token![self]) && !lookahead.peek(Token![Self]) && !lookahead.peek(Token![crate]) || input.peek(Token![dyn]) { return Err(lookahead.error()); } } if lookahead.peek(token::Paren) { let content; let paren_token = parenthesized!(content in input); if content.is_empty() { return Ok(Type::Tuple(TypeTuple { paren_token, elems: Punctuated::new(), })); } if content.peek(Lifetime) { return Ok(Type::Paren(TypeParen { paren_token, elem: Box::new(Type::TraitObject(content.parse()?)), })); } if content.peek(Token![?]) { return Ok(Type::TraitObject(TypeTraitObject { dyn_token: None, bounds: { let mut bounds = Punctuated::new(); bounds.push_value(TypeParamBound::Trait(TraitBound { paren_token: Some(paren_token), ..content.parse()? })); while let Some(plus) = input.parse()? { bounds.push_punct(plus); bounds.push_value(input.parse()?); } bounds }, })); } let mut first: Type = content.parse()?; if content.peek(Token![,]) { return Ok(Type::Tuple(TypeTuple { paren_token, elems: { let mut elems = Punctuated::new(); elems.push_value(first); elems.push_punct(content.parse()?); while !content.is_empty() { elems.push_value(content.parse()?); if content.is_empty() { break; } elems.push_punct(content.parse()?); } elems }, })); } if allow_plus && input.peek(Token![+]) { loop { let first = match first { Type::Path(TypePath { qself: None, path }) => { TypeParamBound::Trait(TraitBound { paren_token: Some(paren_token), modifier: TraitBoundModifier::None, lifetimes: None, path, }) } Type::TraitObject(TypeTraitObject { dyn_token: None, bounds, }) => { if bounds.len() > 1 || bounds.trailing_punct() { first = Type::TraitObject(TypeTraitObject { dyn_token: None, bounds, }); break; } match bounds.into_iter().next().unwrap() { TypeParamBound::Trait(trait_bound) => { TypeParamBound::Trait(TraitBound { paren_token: Some(paren_token), ..trait_bound }) } other @ (TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_)) => other, } } _ => break, }; return Ok(Type::TraitObject(TypeTraitObject { dyn_token: None, bounds: { let mut bounds = Punctuated::new(); bounds.push_value(first); while let Some(plus) = input.parse()? { bounds.push_punct(plus); bounds.push_value(input.parse()?); } bounds }, })); } } Ok(Type::Paren(TypeParen { paren_token, elem: Box::new(first), })) } else if lookahead.peek(Token![fn]) || lookahead.peek(Token![unsafe]) || lookahead.peek(Token![extern]) { let mut bare_fn: TypeBareFn = input.parse()?; bare_fn.lifetimes = lifetimes; Ok(Type::BareFn(bare_fn)) } else if lookahead.peek(Ident) || input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![Self]) || input.peek(Token![crate]) || lookahead.peek(Token![::]) || lookahead.peek(Token![<]) { let ty: TypePath = input.parse()?; if ty.qself.is_some() { return Ok(Type::Path(ty)); } if input.peek(Token![!]) && !input.peek(Token![!=]) && ty.path.is_mod_style() { let bang_token: Token![!] = input.parse()?; let (delimiter, tokens) = mac::parse_delimiter(input)?; return Ok(Type::Macro(TypeMacro { mac: Macro { path: ty.path, bang_token, delimiter, tokens, }, })); } if lifetimes.is_some() || allow_plus && input.peek(Token![+]) { let mut bounds = Punctuated::new(); bounds.push_value(TypeParamBound::Trait(TraitBound { paren_token: None, modifier: TraitBoundModifier::None, lifetimes, path: ty.path, })); if allow_plus { while input.peek(Token![+]) { bounds.push_punct(input.parse()?); if !(input.peek(Ident::peek_any) || input.peek(Token![::]) || input.peek(Token![?]) || input.peek(Lifetime) || input.peek(token::Paren)) { break; } bounds.push_value(input.parse()?); } } return Ok(Type::TraitObject(TypeTraitObject { dyn_token: None, bounds, })); } Ok(Type::Path(ty)) } else if lookahead.peek(Token![dyn]) { let dyn_token: Token![dyn] = input.parse()?; let dyn_span = dyn_token.span; let star_token: Option = input.parse()?; let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?; return Ok(if star_token.is_some() { Type::Verbatim(verbatim::between(&begin, input)) } else { Type::TraitObject(TypeTraitObject { dyn_token: Some(dyn_token), bounds, }) }); } else if lookahead.peek(token::Bracket) { let content; let bracket_token = bracketed!(content in input); let elem: Type = content.parse()?; if content.peek(Token![;]) { Ok(Type::Array(TypeArray { bracket_token, elem: Box::new(elem), semi_token: content.parse()?, len: content.parse()?, })) } else { Ok(Type::Slice(TypeSlice { bracket_token, elem: Box::new(elem), })) } } else if lookahead.peek(Token![*]) { input.parse().map(Type::Ptr) } else if lookahead.peek(Token![&]) { input.parse().map(Type::Reference) } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) { input.parse().map(Type::Never) } else if lookahead.peek(Token![impl]) { TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait) } else if lookahead.peek(Token![_]) { input.parse().map(Type::Infer) } else if lookahead.peek(Lifetime) { input.parse().map(Type::TraitObject) } else { Err(lookahead.error()) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeSlice { fn parse(input: ParseStream) -> Result { let content; Ok(TypeSlice { bracket_token: bracketed!(content in input), elem: content.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeArray { fn parse(input: ParseStream) -> Result { let content; Ok(TypeArray { bracket_token: bracketed!(content in input), elem: content.parse()?, semi_token: content.parse()?, len: content.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypePtr { fn parse(input: ParseStream) -> Result { let star_token: Token![*] = input.parse()?; let lookahead = input.lookahead1(); let (const_token, mutability) = if lookahead.peek(Token![const]) { (Some(input.parse()?), None) } else if lookahead.peek(Token![mut]) { (None, Some(input.parse()?)) } else { return Err(lookahead.error()); }; Ok(TypePtr { star_token, const_token, mutability, elem: Box::new(input.call(Type::without_plus)?), }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeReference { fn parse(input: ParseStream) -> Result { Ok(TypeReference { and_token: input.parse()?, lifetime: input.parse()?, mutability: input.parse()?, // & binds tighter than +, so we don't allow + here. elem: Box::new(input.call(Type::without_plus)?), }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeBareFn { fn parse(input: ParseStream) -> Result { let args; let mut variadic = None; Ok(TypeBareFn { lifetimes: input.parse()?, unsafety: input.parse()?, abi: input.parse()?, fn_token: input.parse()?, paren_token: parenthesized!(args in input), inputs: { let mut inputs = Punctuated::new(); while !args.is_empty() { let attrs = args.call(Attribute::parse_outer)?; if inputs.empty_or_trailing() && (args.peek(Token![...]) || args.peek(Ident) && args.peek2(Token![:]) && args.peek3(Token![...])) { variadic = Some(parse_bare_variadic(&args, attrs)?); break; } let allow_self = inputs.is_empty(); let arg = parse_bare_fn_arg(&args, allow_self)?; inputs.push_value(BareFnArg { attrs, ..arg }); if args.is_empty() { break; } let comma = args.parse()?; inputs.push_punct(comma); } inputs }, variadic, output: input.call(ReturnType::without_plus)?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeNever { fn parse(input: ParseStream) -> Result { Ok(TypeNever { bang_token: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeInfer { fn parse(input: ParseStream) -> Result { Ok(TypeInfer { underscore_token: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeTuple { fn parse(input: ParseStream) -> Result { let content; let paren_token = parenthesized!(content in input); if content.is_empty() { return Ok(TypeTuple { paren_token, elems: Punctuated::new(), }); } let first: Type = content.parse()?; Ok(TypeTuple { paren_token, elems: { let mut elems = Punctuated::new(); elems.push_value(first); elems.push_punct(content.parse()?); while !content.is_empty() { elems.push_value(content.parse()?); if content.is_empty() { break; } elems.push_punct(content.parse()?); } elems }, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeMacro { fn parse(input: ParseStream) -> Result { Ok(TypeMacro { mac: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypePath { fn parse(input: ParseStream) -> Result { let expr_style = false; let (qself, path) = path::parsing::qpath(input, expr_style)?; Ok(TypePath { qself, path }) } } impl ReturnType { #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; Self::parse(input, allow_plus) } pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result { if input.peek(Token![->]) { let arrow = input.parse()?; let allow_group_generic = true; let ty = ambig_ty(input, allow_plus, allow_group_generic)?; Ok(ReturnType::Type(arrow, Box::new(ty))) } else { Ok(ReturnType::Default) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ReturnType { fn parse(input: ParseStream) -> Result { let allow_plus = true; Self::parse(input, allow_plus) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeTraitObject { fn parse(input: ParseStream) -> Result { let allow_plus = true; Self::parse(input, allow_plus) } } impl TypeTraitObject { #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; Self::parse(input, allow_plus) } // Only allow multiple trait references if allow_plus is true. pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result { let dyn_token: Option = input.parse()?; let dyn_span = match &dyn_token { Some(token) => token.span, None => input.span(), }; let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?; Ok(TypeTraitObject { dyn_token, bounds }) } fn parse_bounds( dyn_span: Span, input: ParseStream, allow_plus: bool, ) -> Result> { let bounds = TypeParamBound::parse_multiple(input, allow_plus)?; let mut last_lifetime_span = None; let mut at_least_one_trait = false; for bound in &bounds { match bound { TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => { at_least_one_trait = true; break; } TypeParamBound::Lifetime(lifetime) => { last_lifetime_span = Some(lifetime.ident.span()); } } } // Just lifetimes like `'a + 'b` is not a TraitObject. if !at_least_one_trait { let msg = "at least one trait is required for an object type"; return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg)); } Ok(bounds) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeImplTrait { fn parse(input: ParseStream) -> Result { let allow_plus = true; Self::parse(input, allow_plus) } } impl TypeImplTrait { #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result { let allow_plus = false; Self::parse(input, allow_plus) } pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result { let impl_token: Token![impl] = input.parse()?; let bounds = TypeParamBound::parse_multiple(input, allow_plus)?; let mut last_lifetime_span = None; let mut at_least_one_trait = false; for bound in &bounds { match bound { TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => { at_least_one_trait = true; break; } TypeParamBound::Lifetime(lifetime) => { last_lifetime_span = Some(lifetime.ident.span()); } } } if !at_least_one_trait { let msg = "at least one trait must be specified"; return Err(error::new2( impl_token.span, last_lifetime_span.unwrap(), msg, )); } Ok(TypeImplTrait { impl_token, bounds }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeGroup { fn parse(input: ParseStream) -> Result { let group = crate::group::parse_group(input)?; Ok(TypeGroup { group_token: group.token, elem: group.content.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeParen { fn parse(input: ParseStream) -> Result { let allow_plus = false; Self::parse(input, allow_plus) } } impl TypeParen { fn parse(input: ParseStream, allow_plus: bool) -> Result { let content; Ok(TypeParen { paren_token: parenthesized!(content in input), elem: Box::new({ let allow_group_generic = true; ambig_ty(&content, allow_plus, allow_group_generic)? }), }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for BareFnArg { fn parse(input: ParseStream) -> Result { let allow_self = false; parse_bare_fn_arg(input, allow_self) } } fn parse_bare_fn_arg(input: ParseStream, allow_self: bool) -> Result { let attrs = input.call(Attribute::parse_outer)?; let begin = input.fork(); let has_mut_self = allow_self && input.peek(Token![mut]) && input.peek2(Token![self]); if has_mut_self { input.parse::()?; } let mut has_self = false; let mut name = if (input.peek(Ident) || input.peek(Token![_]) || { has_self = allow_self && input.peek(Token![self]); has_self }) && input.peek2(Token![:]) && !input.peek2(Token![::]) { let name = input.call(Ident::parse_any)?; let colon: Token![:] = input.parse()?; Some((name, colon)) } else { has_self = false; None }; let ty = if allow_self && !has_self && input.peek(Token![mut]) && input.peek2(Token![self]) { input.parse::()?; input.parse::()?; None } else if has_mut_self && name.is_none() { input.parse::()?; None } else { Some(input.parse()?) }; let ty = match ty { Some(ty) if !has_mut_self => ty, _ => { name = None; Type::Verbatim(verbatim::between(&begin, input)) } }; Ok(BareFnArg { attrs, name, ty }) } fn parse_bare_variadic(input: ParseStream, attrs: Vec) -> Result { Ok(BareVariadic { attrs, name: if input.peek(Ident) || input.peek(Token![_]) { let name = input.call(Ident::parse_any)?; let colon: Token![:] = input.parse()?; Some((name, colon)) } else { None }, dots: input.parse()?, comma: input.parse()?, }) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Abi { fn parse(input: ParseStream) -> Result { Ok(Abi { extern_token: input.parse()?, name: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if input.peek(Token![extern]) { input.parse().map(Some) } else { Ok(None) } } } } #[cfg(feature = "printing")] mod printing { use crate::attr::FilterAttrs; use crate::path; use crate::print::TokensOrDefault; use crate::ty::{ Abi, BareFnArg, BareVariadic, ReturnType, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject, TypeTuple, }; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeSlice { fn to_tokens(&self, tokens: &mut TokenStream) { self.bracket_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeArray { fn to_tokens(&self, tokens: &mut TokenStream) { self.bracket_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); self.semi_token.to_tokens(tokens); self.len.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypePtr { fn to_tokens(&self, tokens: &mut TokenStream) { self.star_token.to_tokens(tokens); match &self.mutability { Some(tok) => tok.to_tokens(tokens), None => { TokensOrDefault(&self.const_token).to_tokens(tokens); } } self.elem.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeReference { fn to_tokens(&self, tokens: &mut TokenStream) { self.and_token.to_tokens(tokens); self.lifetime.to_tokens(tokens); self.mutability.to_tokens(tokens); self.elem.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeBareFn { fn to_tokens(&self, tokens: &mut TokenStream) { self.lifetimes.to_tokens(tokens); self.unsafety.to_tokens(tokens); self.abi.to_tokens(tokens); self.fn_token.to_tokens(tokens); self.paren_token.surround(tokens, |tokens| { self.inputs.to_tokens(tokens); if let Some(variadic) = &self.variadic { if !self.inputs.empty_or_trailing() { let span = variadic.dots.spans[0]; Token![,](span).to_tokens(tokens); } variadic.to_tokens(tokens); } }); self.output.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeNever { fn to_tokens(&self, tokens: &mut TokenStream) { self.bang_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeTuple { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); // If we only have one argument, we need a trailing comma to // distinguish TypeTuple from TypeParen. if self.elems.len() == 1 && !self.elems.trailing_punct() { ::default().to_tokens(tokens); } }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypePath { fn to_tokens(&self, tokens: &mut TokenStream) { path::printing::print_path(tokens, &self.qself, &self.path); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeTraitObject { fn to_tokens(&self, tokens: &mut TokenStream) { self.dyn_token.to_tokens(tokens); self.bounds.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeImplTrait { fn to_tokens(&self, tokens: &mut TokenStream) { self.impl_token.to_tokens(tokens); self.bounds.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeGroup { fn to_tokens(&self, tokens: &mut TokenStream) { self.group_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeParen { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeInfer { fn to_tokens(&self, tokens: &mut TokenStream) { self.underscore_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeMacro { fn to_tokens(&self, tokens: &mut TokenStream) { self.mac.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ReturnType { fn to_tokens(&self, tokens: &mut TokenStream) { match self { ReturnType::Default => {} ReturnType::Type(arrow, ty) => { arrow.to_tokens(tokens); ty.to_tokens(tokens); } } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BareFnArg { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some((name, colon)) = &self.name { name.to_tokens(tokens); colon.to_tokens(tokens); } self.ty.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BareVariadic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some((name, colon)) = &self.name { name.to_tokens(tokens); colon.to_tokens(tokens); } self.dots.to_tokens(tokens); self.comma.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Abi { fn to_tokens(&self, tokens: &mut TokenStream) { self.extern_token.to_tokens(tokens); self.name.to_tokens(tokens); } } } syn/src/gen/0000775000175000017500000000000014661133735013714 5ustar jamespagejamespagesyn/src/gen/visit.rs0000644000175000017500000035711314661133735015430 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #![allow(unused_variables)] #![allow(clippy::needless_pass_by_ref_mut)] #[cfg(any(feature = "full", feature = "derive"))] use crate::punctuated::Punctuated; #[cfg(feature = "full")] macro_rules! full { ($e:expr) => { $e }; } #[cfg(all(feature = "derive", not(feature = "full")))] macro_rules! full { ($e:expr) => { unreachable!() }; } macro_rules! skip { ($($tt:tt)*) => {}; } /// Syntax tree traversal to walk a shared borrow of a syntax tree. /// /// See the [module documentation] for details. /// /// [module documentation]: self pub trait Visit<'ast> { #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_abi(&mut self, i: &'ast crate::Abi) { visit_abi(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_angle_bracketed_generic_arguments( &mut self, i: &'ast crate::AngleBracketedGenericArguments, ) { visit_angle_bracketed_generic_arguments(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_arm(&mut self, i: &'ast crate::Arm) { visit_arm(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_assoc_const(&mut self, i: &'ast crate::AssocConst) { visit_assoc_const(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_assoc_type(&mut self, i: &'ast crate::AssocType) { visit_assoc_type(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_attr_style(&mut self, i: &'ast crate::AttrStyle) { visit_attr_style(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_attribute(&mut self, i: &'ast crate::Attribute) { visit_attribute(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bare_fn_arg(&mut self, i: &'ast crate::BareFnArg) { visit_bare_fn_arg(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bare_variadic(&mut self, i: &'ast crate::BareVariadic) { visit_bare_variadic(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bin_op(&mut self, i: &'ast crate::BinOp) { visit_bin_op(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_block(&mut self, i: &'ast crate::Block) { visit_block(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bound_lifetimes(&mut self, i: &'ast crate::BoundLifetimes) { visit_bound_lifetimes(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_const_param(&mut self, i: &'ast crate::ConstParam) { visit_const_param(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_constraint(&mut self, i: &'ast crate::Constraint) { visit_constraint(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data(&mut self, i: &'ast crate::Data) { visit_data(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_enum(&mut self, i: &'ast crate::DataEnum) { visit_data_enum(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_struct(&mut self, i: &'ast crate::DataStruct) { visit_data_struct(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_union(&mut self, i: &'ast crate::DataUnion) { visit_data_union(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_derive_input(&mut self, i: &'ast crate::DeriveInput) { visit_derive_input(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr(&mut self, i: &'ast crate::Expr) { visit_expr(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_array(&mut self, i: &'ast crate::ExprArray) { visit_expr_array(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_assign(&mut self, i: &'ast crate::ExprAssign) { visit_expr_assign(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_async(&mut self, i: &'ast crate::ExprAsync) { visit_expr_async(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_await(&mut self, i: &'ast crate::ExprAwait) { visit_expr_await(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_binary(&mut self, i: &'ast crate::ExprBinary) { visit_expr_binary(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_block(&mut self, i: &'ast crate::ExprBlock) { visit_expr_block(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_break(&mut self, i: &'ast crate::ExprBreak) { visit_expr_break(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_call(&mut self, i: &'ast crate::ExprCall) { visit_expr_call(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_cast(&mut self, i: &'ast crate::ExprCast) { visit_expr_cast(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_closure(&mut self, i: &'ast crate::ExprClosure) { visit_expr_closure(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_const(&mut self, i: &'ast crate::ExprConst) { visit_expr_const(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_continue(&mut self, i: &'ast crate::ExprContinue) { visit_expr_continue(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_field(&mut self, i: &'ast crate::ExprField) { visit_expr_field(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_for_loop(&mut self, i: &'ast crate::ExprForLoop) { visit_expr_for_loop(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_group(&mut self, i: &'ast crate::ExprGroup) { visit_expr_group(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_if(&mut self, i: &'ast crate::ExprIf) { visit_expr_if(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_index(&mut self, i: &'ast crate::ExprIndex) { visit_expr_index(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_infer(&mut self, i: &'ast crate::ExprInfer) { visit_expr_infer(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_let(&mut self, i: &'ast crate::ExprLet) { visit_expr_let(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_lit(&mut self, i: &'ast crate::ExprLit) { visit_expr_lit(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_loop(&mut self, i: &'ast crate::ExprLoop) { visit_expr_loop(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_macro(&mut self, i: &'ast crate::ExprMacro) { visit_expr_macro(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_match(&mut self, i: &'ast crate::ExprMatch) { visit_expr_match(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_method_call(&mut self, i: &'ast crate::ExprMethodCall) { visit_expr_method_call(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_paren(&mut self, i: &'ast crate::ExprParen) { visit_expr_paren(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_path(&mut self, i: &'ast crate::ExprPath) { visit_expr_path(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_range(&mut self, i: &'ast crate::ExprRange) { visit_expr_range(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_reference(&mut self, i: &'ast crate::ExprReference) { visit_expr_reference(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_repeat(&mut self, i: &'ast crate::ExprRepeat) { visit_expr_repeat(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_return(&mut self, i: &'ast crate::ExprReturn) { visit_expr_return(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_struct(&mut self, i: &'ast crate::ExprStruct) { visit_expr_struct(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_try(&mut self, i: &'ast crate::ExprTry) { visit_expr_try(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_try_block(&mut self, i: &'ast crate::ExprTryBlock) { visit_expr_try_block(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_tuple(&mut self, i: &'ast crate::ExprTuple) { visit_expr_tuple(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_unary(&mut self, i: &'ast crate::ExprUnary) { visit_expr_unary(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_unsafe(&mut self, i: &'ast crate::ExprUnsafe) { visit_expr_unsafe(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_while(&mut self, i: &'ast crate::ExprWhile) { visit_expr_while(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_yield(&mut self, i: &'ast crate::ExprYield) { visit_expr_yield(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_field(&mut self, i: &'ast crate::Field) { visit_field(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_field_mutability(&mut self, i: &'ast crate::FieldMutability) { visit_field_mutability(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_field_pat(&mut self, i: &'ast crate::FieldPat) { visit_field_pat(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_field_value(&mut self, i: &'ast crate::FieldValue) { visit_field_value(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields(&mut self, i: &'ast crate::Fields) { visit_fields(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_named(&mut self, i: &'ast crate::FieldsNamed) { visit_fields_named(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_unnamed(&mut self, i: &'ast crate::FieldsUnnamed) { visit_fields_unnamed(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_file(&mut self, i: &'ast crate::File) { visit_file(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_fn_arg(&mut self, i: &'ast crate::FnArg) { visit_fn_arg(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item(&mut self, i: &'ast crate::ForeignItem) { visit_foreign_item(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_fn(&mut self, i: &'ast crate::ForeignItemFn) { visit_foreign_item_fn(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_macro(&mut self, i: &'ast crate::ForeignItemMacro) { visit_foreign_item_macro(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_static(&mut self, i: &'ast crate::ForeignItemStatic) { visit_foreign_item_static(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_type(&mut self, i: &'ast crate::ForeignItemType) { visit_foreign_item_type(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_generic_argument(&mut self, i: &'ast crate::GenericArgument) { visit_generic_argument(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_generic_param(&mut self, i: &'ast crate::GenericParam) { visit_generic_param(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_generics(&mut self, i: &'ast crate::Generics) { visit_generics(self, i); } fn visit_ident(&mut self, i: &'ast proc_macro2::Ident) { visit_ident(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item(&mut self, i: &'ast crate::ImplItem) { visit_impl_item(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_const(&mut self, i: &'ast crate::ImplItemConst) { visit_impl_item_const(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_fn(&mut self, i: &'ast crate::ImplItemFn) { visit_impl_item_fn(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_macro(&mut self, i: &'ast crate::ImplItemMacro) { visit_impl_item_macro(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_type(&mut self, i: &'ast crate::ImplItemType) { visit_impl_item_type(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_restriction(&mut self, i: &'ast crate::ImplRestriction) { visit_impl_restriction(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_index(&mut self, i: &'ast crate::Index) { visit_index(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item(&mut self, i: &'ast crate::Item) { visit_item(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_const(&mut self, i: &'ast crate::ItemConst) { visit_item_const(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_enum(&mut self, i: &'ast crate::ItemEnum) { visit_item_enum(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_extern_crate(&mut self, i: &'ast crate::ItemExternCrate) { visit_item_extern_crate(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_fn(&mut self, i: &'ast crate::ItemFn) { visit_item_fn(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_foreign_mod(&mut self, i: &'ast crate::ItemForeignMod) { visit_item_foreign_mod(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_impl(&mut self, i: &'ast crate::ItemImpl) { visit_item_impl(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_macro(&mut self, i: &'ast crate::ItemMacro) { visit_item_macro(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_mod(&mut self, i: &'ast crate::ItemMod) { visit_item_mod(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_static(&mut self, i: &'ast crate::ItemStatic) { visit_item_static(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_struct(&mut self, i: &'ast crate::ItemStruct) { visit_item_struct(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_trait(&mut self, i: &'ast crate::ItemTrait) { visit_item_trait(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_trait_alias(&mut self, i: &'ast crate::ItemTraitAlias) { visit_item_trait_alias(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_type(&mut self, i: &'ast crate::ItemType) { visit_item_type(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_union(&mut self, i: &'ast crate::ItemUnion) { visit_item_union(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_use(&mut self, i: &'ast crate::ItemUse) { visit_item_use(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_label(&mut self, i: &'ast crate::Label) { visit_label(self, i); } fn visit_lifetime(&mut self, i: &'ast crate::Lifetime) { visit_lifetime(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_lifetime_param(&mut self, i: &'ast crate::LifetimeParam) { visit_lifetime_param(self, i); } fn visit_lit(&mut self, i: &'ast crate::Lit) { visit_lit(self, i); } fn visit_lit_bool(&mut self, i: &'ast crate::LitBool) { visit_lit_bool(self, i); } fn visit_lit_byte(&mut self, i: &'ast crate::LitByte) { visit_lit_byte(self, i); } fn visit_lit_byte_str(&mut self, i: &'ast crate::LitByteStr) { visit_lit_byte_str(self, i); } fn visit_lit_cstr(&mut self, i: &'ast crate::LitCStr) { visit_lit_cstr(self, i); } fn visit_lit_char(&mut self, i: &'ast crate::LitChar) { visit_lit_char(self, i); } fn visit_lit_float(&mut self, i: &'ast crate::LitFloat) { visit_lit_float(self, i); } fn visit_lit_int(&mut self, i: &'ast crate::LitInt) { visit_lit_int(self, i); } fn visit_lit_str(&mut self, i: &'ast crate::LitStr) { visit_lit_str(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_local(&mut self, i: &'ast crate::Local) { visit_local(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_local_init(&mut self, i: &'ast crate::LocalInit) { visit_local_init(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_macro(&mut self, i: &'ast crate::Macro) { visit_macro(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_macro_delimiter(&mut self, i: &'ast crate::MacroDelimiter) { visit_macro_delimiter(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_member(&mut self, i: &'ast crate::Member) { visit_member(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_meta(&mut self, i: &'ast crate::Meta) { visit_meta(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_meta_list(&mut self, i: &'ast crate::MetaList) { visit_meta_list(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_meta_name_value(&mut self, i: &'ast crate::MetaNameValue) { visit_meta_name_value(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_parenthesized_generic_arguments( &mut self, i: &'ast crate::ParenthesizedGenericArguments, ) { visit_parenthesized_generic_arguments(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat(&mut self, i: &'ast crate::Pat) { visit_pat(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_ident(&mut self, i: &'ast crate::PatIdent) { visit_pat_ident(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_or(&mut self, i: &'ast crate::PatOr) { visit_pat_or(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_paren(&mut self, i: &'ast crate::PatParen) { visit_pat_paren(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_reference(&mut self, i: &'ast crate::PatReference) { visit_pat_reference(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_rest(&mut self, i: &'ast crate::PatRest) { visit_pat_rest(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_slice(&mut self, i: &'ast crate::PatSlice) { visit_pat_slice(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_struct(&mut self, i: &'ast crate::PatStruct) { visit_pat_struct(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_tuple(&mut self, i: &'ast crate::PatTuple) { visit_pat_tuple(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_tuple_struct(&mut self, i: &'ast crate::PatTupleStruct) { visit_pat_tuple_struct(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_type(&mut self, i: &'ast crate::PatType) { visit_pat_type(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_wild(&mut self, i: &'ast crate::PatWild) { visit_pat_wild(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_path(&mut self, i: &'ast crate::Path) { visit_path(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_path_arguments(&mut self, i: &'ast crate::PathArguments) { visit_path_arguments(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_path_segment(&mut self, i: &'ast crate::PathSegment) { visit_path_segment(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_predicate_lifetime(&mut self, i: &'ast crate::PredicateLifetime) { visit_predicate_lifetime(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_predicate_type(&mut self, i: &'ast crate::PredicateType) { visit_predicate_type(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_qself(&mut self, i: &'ast crate::QSelf) { visit_qself(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_range_limits(&mut self, i: &'ast crate::RangeLimits) { visit_range_limits(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_receiver(&mut self, i: &'ast crate::Receiver) { visit_receiver(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_return_type(&mut self, i: &'ast crate::ReturnType) { visit_return_type(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_signature(&mut self, i: &'ast crate::Signature) { visit_signature(self, i); } fn visit_span(&mut self, i: &proc_macro2::Span) { visit_span(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_static_mutability(&mut self, i: &'ast crate::StaticMutability) { visit_static_mutability(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_stmt(&mut self, i: &'ast crate::Stmt) { visit_stmt(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_stmt_macro(&mut self, i: &'ast crate::StmtMacro) { visit_stmt_macro(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_trait_bound(&mut self, i: &'ast crate::TraitBound) { visit_trait_bound(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_trait_bound_modifier(&mut self, i: &'ast crate::TraitBoundModifier) { visit_trait_bound_modifier(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item(&mut self, i: &'ast crate::TraitItem) { visit_trait_item(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_const(&mut self, i: &'ast crate::TraitItemConst) { visit_trait_item_const(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_fn(&mut self, i: &'ast crate::TraitItemFn) { visit_trait_item_fn(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_macro(&mut self, i: &'ast crate::TraitItemMacro) { visit_trait_item_macro(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_type(&mut self, i: &'ast crate::TraitItemType) { visit_trait_item_type(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type(&mut self, i: &'ast crate::Type) { visit_type(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_array(&mut self, i: &'ast crate::TypeArray) { visit_type_array(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_bare_fn(&mut self, i: &'ast crate::TypeBareFn) { visit_type_bare_fn(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_group(&mut self, i: &'ast crate::TypeGroup) { visit_type_group(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_impl_trait(&mut self, i: &'ast crate::TypeImplTrait) { visit_type_impl_trait(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_infer(&mut self, i: &'ast crate::TypeInfer) { visit_type_infer(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_macro(&mut self, i: &'ast crate::TypeMacro) { visit_type_macro(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_never(&mut self, i: &'ast crate::TypeNever) { visit_type_never(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_param(&mut self, i: &'ast crate::TypeParam) { visit_type_param(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_param_bound(&mut self, i: &'ast crate::TypeParamBound) { visit_type_param_bound(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_paren(&mut self, i: &'ast crate::TypeParen) { visit_type_paren(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_path(&mut self, i: &'ast crate::TypePath) { visit_type_path(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_ptr(&mut self, i: &'ast crate::TypePtr) { visit_type_ptr(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_reference(&mut self, i: &'ast crate::TypeReference) { visit_type_reference(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_slice(&mut self, i: &'ast crate::TypeSlice) { visit_type_slice(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_trait_object(&mut self, i: &'ast crate::TypeTraitObject) { visit_type_trait_object(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_tuple(&mut self, i: &'ast crate::TypeTuple) { visit_type_tuple(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_un_op(&mut self, i: &'ast crate::UnOp) { visit_un_op(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_glob(&mut self, i: &'ast crate::UseGlob) { visit_use_glob(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_group(&mut self, i: &'ast crate::UseGroup) { visit_use_group(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_name(&mut self, i: &'ast crate::UseName) { visit_use_name(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_path(&mut self, i: &'ast crate::UsePath) { visit_use_path(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_rename(&mut self, i: &'ast crate::UseRename) { visit_use_rename(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_tree(&mut self, i: &'ast crate::UseTree) { visit_use_tree(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_variadic(&mut self, i: &'ast crate::Variadic) { visit_variadic(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_variant(&mut self, i: &'ast crate::Variant) { visit_variant(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_vis_restricted(&mut self, i: &'ast crate::VisRestricted) { visit_vis_restricted(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_visibility(&mut self, i: &'ast crate::Visibility) { visit_visibility(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_where_clause(&mut self, i: &'ast crate::WhereClause) { visit_where_clause(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_where_predicate(&mut self, i: &'ast crate::WherePredicate) { visit_where_predicate(self, i); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_abi<'ast, V>(v: &mut V, node: &'ast crate::Abi) where V: Visit<'ast> + ?Sized, { skip!(node.extern_token); if let Some(it) = &node.name { v.visit_lit_str(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_angle_bracketed_generic_arguments<'ast, V>( v: &mut V, node: &'ast crate::AngleBracketedGenericArguments, ) where V: Visit<'ast> + ?Sized, { skip!(node.colon2_token); skip!(node.lt_token); for el in Punctuated::pairs(&node.args) { let it = el.value(); v.visit_generic_argument(it); } skip!(node.gt_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_arm<'ast, V>(v: &mut V, node: &'ast crate::Arm) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_pat(&node.pat); if let Some(it) = &node.guard { skip!((it).0); v.visit_expr(&*(it).1); } skip!(node.fat_arrow_token); v.visit_expr(&*node.body); skip!(node.comma); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_assoc_const<'ast, V>(v: &mut V, node: &'ast crate::AssocConst) where V: Visit<'ast> + ?Sized, { v.visit_ident(&node.ident); if let Some(it) = &node.generics { v.visit_angle_bracketed_generic_arguments(it); } skip!(node.eq_token); v.visit_expr(&node.value); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_assoc_type<'ast, V>(v: &mut V, node: &'ast crate::AssocType) where V: Visit<'ast> + ?Sized, { v.visit_ident(&node.ident); if let Some(it) = &node.generics { v.visit_angle_bracketed_generic_arguments(it); } skip!(node.eq_token); v.visit_type(&node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_attr_style<'ast, V>(v: &mut V, node: &'ast crate::AttrStyle) where V: Visit<'ast> + ?Sized, { match node { crate::AttrStyle::Outer => {} crate::AttrStyle::Inner(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_attribute<'ast, V>(v: &mut V, node: &'ast crate::Attribute) where V: Visit<'ast> + ?Sized, { skip!(node.pound_token); v.visit_attr_style(&node.style); skip!(node.bracket_token); v.visit_meta(&node.meta); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bare_fn_arg<'ast, V>(v: &mut V, node: &'ast crate::BareFnArg) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.name { v.visit_ident(&(it).0); skip!((it).1); } v.visit_type(&node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bare_variadic<'ast, V>(v: &mut V, node: &'ast crate::BareVariadic) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.name { v.visit_ident(&(it).0); skip!((it).1); } skip!(node.dots); skip!(node.comma); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bin_op<'ast, V>(v: &mut V, node: &'ast crate::BinOp) where V: Visit<'ast> + ?Sized, { match node { crate::BinOp::Add(_binding_0) => { skip!(_binding_0); } crate::BinOp::Sub(_binding_0) => { skip!(_binding_0); } crate::BinOp::Mul(_binding_0) => { skip!(_binding_0); } crate::BinOp::Div(_binding_0) => { skip!(_binding_0); } crate::BinOp::Rem(_binding_0) => { skip!(_binding_0); } crate::BinOp::And(_binding_0) => { skip!(_binding_0); } crate::BinOp::Or(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitXor(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitAnd(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitOr(_binding_0) => { skip!(_binding_0); } crate::BinOp::Shl(_binding_0) => { skip!(_binding_0); } crate::BinOp::Shr(_binding_0) => { skip!(_binding_0); } crate::BinOp::Eq(_binding_0) => { skip!(_binding_0); } crate::BinOp::Lt(_binding_0) => { skip!(_binding_0); } crate::BinOp::Le(_binding_0) => { skip!(_binding_0); } crate::BinOp::Ne(_binding_0) => { skip!(_binding_0); } crate::BinOp::Ge(_binding_0) => { skip!(_binding_0); } crate::BinOp::Gt(_binding_0) => { skip!(_binding_0); } crate::BinOp::AddAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::SubAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::MulAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::DivAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::RemAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitXorAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitAndAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitOrAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::ShlAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::ShrAssign(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_block<'ast, V>(v: &mut V, node: &'ast crate::Block) where V: Visit<'ast> + ?Sized, { skip!(node.brace_token); for it in &node.stmts { v.visit_stmt(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bound_lifetimes<'ast, V>(v: &mut V, node: &'ast crate::BoundLifetimes) where V: Visit<'ast> + ?Sized, { skip!(node.for_token); skip!(node.lt_token); for el in Punctuated::pairs(&node.lifetimes) { let it = el.value(); v.visit_generic_param(it); } skip!(node.gt_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_const_param<'ast, V>(v: &mut V, node: &'ast crate::ConstParam) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.const_token); v.visit_ident(&node.ident); skip!(node.colon_token); v.visit_type(&node.ty); skip!(node.eq_token); if let Some(it) = &node.default { v.visit_expr(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_constraint<'ast, V>(v: &mut V, node: &'ast crate::Constraint) where V: Visit<'ast> + ?Sized, { v.visit_ident(&node.ident); if let Some(it) = &node.generics { v.visit_angle_bracketed_generic_arguments(it); } skip!(node.colon_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_type_param_bound(it); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data<'ast, V>(v: &mut V, node: &'ast crate::Data) where V: Visit<'ast> + ?Sized, { match node { crate::Data::Struct(_binding_0) => { v.visit_data_struct(_binding_0); } crate::Data::Enum(_binding_0) => { v.visit_data_enum(_binding_0); } crate::Data::Union(_binding_0) => { v.visit_data_union(_binding_0); } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_enum<'ast, V>(v: &mut V, node: &'ast crate::DataEnum) where V: Visit<'ast> + ?Sized, { skip!(node.enum_token); skip!(node.brace_token); for el in Punctuated::pairs(&node.variants) { let it = el.value(); v.visit_variant(it); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_struct<'ast, V>(v: &mut V, node: &'ast crate::DataStruct) where V: Visit<'ast> + ?Sized, { skip!(node.struct_token); v.visit_fields(&node.fields); skip!(node.semi_token); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_union<'ast, V>(v: &mut V, node: &'ast crate::DataUnion) where V: Visit<'ast> + ?Sized, { skip!(node.union_token); v.visit_fields_named(&node.fields); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_derive_input<'ast, V>(v: &mut V, node: &'ast crate::DeriveInput) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); v.visit_ident(&node.ident); v.visit_generics(&node.generics); v.visit_data(&node.data); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr<'ast, V>(v: &mut V, node: &'ast crate::Expr) where V: Visit<'ast> + ?Sized, { match node { crate::Expr::Array(_binding_0) => { full!(v.visit_expr_array(_binding_0)); } crate::Expr::Assign(_binding_0) => { full!(v.visit_expr_assign(_binding_0)); } crate::Expr::Async(_binding_0) => { full!(v.visit_expr_async(_binding_0)); } crate::Expr::Await(_binding_0) => { full!(v.visit_expr_await(_binding_0)); } crate::Expr::Binary(_binding_0) => { v.visit_expr_binary(_binding_0); } crate::Expr::Block(_binding_0) => { full!(v.visit_expr_block(_binding_0)); } crate::Expr::Break(_binding_0) => { full!(v.visit_expr_break(_binding_0)); } crate::Expr::Call(_binding_0) => { v.visit_expr_call(_binding_0); } crate::Expr::Cast(_binding_0) => { v.visit_expr_cast(_binding_0); } crate::Expr::Closure(_binding_0) => { full!(v.visit_expr_closure(_binding_0)); } crate::Expr::Const(_binding_0) => { full!(v.visit_expr_const(_binding_0)); } crate::Expr::Continue(_binding_0) => { full!(v.visit_expr_continue(_binding_0)); } crate::Expr::Field(_binding_0) => { v.visit_expr_field(_binding_0); } crate::Expr::ForLoop(_binding_0) => { full!(v.visit_expr_for_loop(_binding_0)); } crate::Expr::Group(_binding_0) => { v.visit_expr_group(_binding_0); } crate::Expr::If(_binding_0) => { full!(v.visit_expr_if(_binding_0)); } crate::Expr::Index(_binding_0) => { v.visit_expr_index(_binding_0); } crate::Expr::Infer(_binding_0) => { full!(v.visit_expr_infer(_binding_0)); } crate::Expr::Let(_binding_0) => { full!(v.visit_expr_let(_binding_0)); } crate::Expr::Lit(_binding_0) => { v.visit_expr_lit(_binding_0); } crate::Expr::Loop(_binding_0) => { full!(v.visit_expr_loop(_binding_0)); } crate::Expr::Macro(_binding_0) => { v.visit_expr_macro(_binding_0); } crate::Expr::Match(_binding_0) => { full!(v.visit_expr_match(_binding_0)); } crate::Expr::MethodCall(_binding_0) => { v.visit_expr_method_call(_binding_0); } crate::Expr::Paren(_binding_0) => { v.visit_expr_paren(_binding_0); } crate::Expr::Path(_binding_0) => { v.visit_expr_path(_binding_0); } crate::Expr::Range(_binding_0) => { full!(v.visit_expr_range(_binding_0)); } crate::Expr::Reference(_binding_0) => { v.visit_expr_reference(_binding_0); } crate::Expr::Repeat(_binding_0) => { full!(v.visit_expr_repeat(_binding_0)); } crate::Expr::Return(_binding_0) => { full!(v.visit_expr_return(_binding_0)); } crate::Expr::Struct(_binding_0) => { v.visit_expr_struct(_binding_0); } crate::Expr::Try(_binding_0) => { full!(v.visit_expr_try(_binding_0)); } crate::Expr::TryBlock(_binding_0) => { full!(v.visit_expr_try_block(_binding_0)); } crate::Expr::Tuple(_binding_0) => { full!(v.visit_expr_tuple(_binding_0)); } crate::Expr::Unary(_binding_0) => { v.visit_expr_unary(_binding_0); } crate::Expr::Unsafe(_binding_0) => { full!(v.visit_expr_unsafe(_binding_0)); } crate::Expr::Verbatim(_binding_0) => { skip!(_binding_0); } crate::Expr::While(_binding_0) => { full!(v.visit_expr_while(_binding_0)); } crate::Expr::Yield(_binding_0) => { full!(v.visit_expr_yield(_binding_0)); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_array<'ast, V>(v: &mut V, node: &'ast crate::ExprArray) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.bracket_token); for el in Punctuated::pairs(&node.elems) { let it = el.value(); v.visit_expr(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_assign<'ast, V>(v: &mut V, node: &'ast crate::ExprAssign) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.left); skip!(node.eq_token); v.visit_expr(&*node.right); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_async<'ast, V>(v: &mut V, node: &'ast crate::ExprAsync) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.async_token); skip!(node.capture); v.visit_block(&node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_await<'ast, V>(v: &mut V, node: &'ast crate::ExprAwait) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.base); skip!(node.dot_token); skip!(node.await_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_binary<'ast, V>(v: &mut V, node: &'ast crate::ExprBinary) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.left); v.visit_bin_op(&node.op); v.visit_expr(&*node.right); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_block<'ast, V>(v: &mut V, node: &'ast crate::ExprBlock) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.label { v.visit_label(it); } v.visit_block(&node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_break<'ast, V>(v: &mut V, node: &'ast crate::ExprBreak) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.break_token); if let Some(it) = &node.label { v.visit_lifetime(it); } if let Some(it) = &node.expr { v.visit_expr(&**it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_call<'ast, V>(v: &mut V, node: &'ast crate::ExprCall) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.func); skip!(node.paren_token); for el in Punctuated::pairs(&node.args) { let it = el.value(); v.visit_expr(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_cast<'ast, V>(v: &mut V, node: &'ast crate::ExprCast) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.expr); skip!(node.as_token); v.visit_type(&*node.ty); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_closure<'ast, V>(v: &mut V, node: &'ast crate::ExprClosure) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.lifetimes { v.visit_bound_lifetimes(it); } skip!(node.constness); skip!(node.movability); skip!(node.asyncness); skip!(node.capture); skip!(node.or1_token); for el in Punctuated::pairs(&node.inputs) { let it = el.value(); v.visit_pat(it); } skip!(node.or2_token); v.visit_return_type(&node.output); v.visit_expr(&*node.body); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_const<'ast, V>(v: &mut V, node: &'ast crate::ExprConst) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.const_token); v.visit_block(&node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_continue<'ast, V>(v: &mut V, node: &'ast crate::ExprContinue) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.continue_token); if let Some(it) = &node.label { v.visit_lifetime(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_field<'ast, V>(v: &mut V, node: &'ast crate::ExprField) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.base); skip!(node.dot_token); v.visit_member(&node.member); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_for_loop<'ast, V>(v: &mut V, node: &'ast crate::ExprForLoop) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.label { v.visit_label(it); } skip!(node.for_token); v.visit_pat(&*node.pat); skip!(node.in_token); v.visit_expr(&*node.expr); v.visit_block(&node.body); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_group<'ast, V>(v: &mut V, node: &'ast crate::ExprGroup) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.group_token); v.visit_expr(&*node.expr); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_if<'ast, V>(v: &mut V, node: &'ast crate::ExprIf) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.if_token); v.visit_expr(&*node.cond); v.visit_block(&node.then_branch); if let Some(it) = &node.else_branch { skip!((it).0); v.visit_expr(&*(it).1); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_index<'ast, V>(v: &mut V, node: &'ast crate::ExprIndex) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.expr); skip!(node.bracket_token); v.visit_expr(&*node.index); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_infer<'ast, V>(v: &mut V, node: &'ast crate::ExprInfer) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.underscore_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_let<'ast, V>(v: &mut V, node: &'ast crate::ExprLet) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.let_token); v.visit_pat(&*node.pat); skip!(node.eq_token); v.visit_expr(&*node.expr); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_lit<'ast, V>(v: &mut V, node: &'ast crate::ExprLit) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_lit(&node.lit); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_loop<'ast, V>(v: &mut V, node: &'ast crate::ExprLoop) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.label { v.visit_label(it); } skip!(node.loop_token); v.visit_block(&node.body); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_macro<'ast, V>(v: &mut V, node: &'ast crate::ExprMacro) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_macro(&node.mac); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_match<'ast, V>(v: &mut V, node: &'ast crate::ExprMatch) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.match_token); v.visit_expr(&*node.expr); skip!(node.brace_token); for it in &node.arms { v.visit_arm(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_method_call<'ast, V>(v: &mut V, node: &'ast crate::ExprMethodCall) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.receiver); skip!(node.dot_token); v.visit_ident(&node.method); if let Some(it) = &node.turbofish { v.visit_angle_bracketed_generic_arguments(it); } skip!(node.paren_token); for el in Punctuated::pairs(&node.args) { let it = el.value(); v.visit_expr(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_paren<'ast, V>(v: &mut V, node: &'ast crate::ExprParen) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.paren_token); v.visit_expr(&*node.expr); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_path<'ast, V>(v: &mut V, node: &'ast crate::ExprPath) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.qself { v.visit_qself(it); } v.visit_path(&node.path); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_range<'ast, V>(v: &mut V, node: &'ast crate::ExprRange) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.start { v.visit_expr(&**it); } v.visit_range_limits(&node.limits); if let Some(it) = &node.end { v.visit_expr(&**it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_reference<'ast, V>(v: &mut V, node: &'ast crate::ExprReference) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.and_token); skip!(node.mutability); v.visit_expr(&*node.expr); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_repeat<'ast, V>(v: &mut V, node: &'ast crate::ExprRepeat) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.bracket_token); v.visit_expr(&*node.expr); skip!(node.semi_token); v.visit_expr(&*node.len); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_return<'ast, V>(v: &mut V, node: &'ast crate::ExprReturn) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.return_token); if let Some(it) = &node.expr { v.visit_expr(&**it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_struct<'ast, V>(v: &mut V, node: &'ast crate::ExprStruct) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.qself { v.visit_qself(it); } v.visit_path(&node.path); skip!(node.brace_token); for el in Punctuated::pairs(&node.fields) { let it = el.value(); v.visit_field_value(it); } skip!(node.dot2_token); if let Some(it) = &node.rest { v.visit_expr(&**it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_try<'ast, V>(v: &mut V, node: &'ast crate::ExprTry) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_expr(&*node.expr); skip!(node.question_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_try_block<'ast, V>(v: &mut V, node: &'ast crate::ExprTryBlock) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.try_token); v.visit_block(&node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_tuple<'ast, V>(v: &mut V, node: &'ast crate::ExprTuple) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.paren_token); for el in Punctuated::pairs(&node.elems) { let it = el.value(); v.visit_expr(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_unary<'ast, V>(v: &mut V, node: &'ast crate::ExprUnary) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_un_op(&node.op); v.visit_expr(&*node.expr); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_unsafe<'ast, V>(v: &mut V, node: &'ast crate::ExprUnsafe) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.unsafe_token); v.visit_block(&node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_while<'ast, V>(v: &mut V, node: &'ast crate::ExprWhile) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.label { v.visit_label(it); } skip!(node.while_token); v.visit_expr(&*node.cond); v.visit_block(&node.body); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_yield<'ast, V>(v: &mut V, node: &'ast crate::ExprYield) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.yield_token); if let Some(it) = &node.expr { v.visit_expr(&**it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_field<'ast, V>(v: &mut V, node: &'ast crate::Field) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); v.visit_field_mutability(&node.mutability); if let Some(it) = &node.ident { v.visit_ident(it); } skip!(node.colon_token); v.visit_type(&node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_field_mutability<'ast, V>(v: &mut V, node: &'ast crate::FieldMutability) where V: Visit<'ast> + ?Sized, { match node { crate::FieldMutability::None => {} } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_field_pat<'ast, V>(v: &mut V, node: &'ast crate::FieldPat) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_member(&node.member); skip!(node.colon_token); v.visit_pat(&*node.pat); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_field_value<'ast, V>(v: &mut V, node: &'ast crate::FieldValue) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_member(&node.member); skip!(node.colon_token); v.visit_expr(&node.expr); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields<'ast, V>(v: &mut V, node: &'ast crate::Fields) where V: Visit<'ast> + ?Sized, { match node { crate::Fields::Named(_binding_0) => { v.visit_fields_named(_binding_0); } crate::Fields::Unnamed(_binding_0) => { v.visit_fields_unnamed(_binding_0); } crate::Fields::Unit => {} } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_named<'ast, V>(v: &mut V, node: &'ast crate::FieldsNamed) where V: Visit<'ast> + ?Sized, { skip!(node.brace_token); for el in Punctuated::pairs(&node.named) { let it = el.value(); v.visit_field(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_unnamed<'ast, V>(v: &mut V, node: &'ast crate::FieldsUnnamed) where V: Visit<'ast> + ?Sized, { skip!(node.paren_token); for el in Punctuated::pairs(&node.unnamed) { let it = el.value(); v.visit_field(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_file<'ast, V>(v: &mut V, node: &'ast crate::File) where V: Visit<'ast> + ?Sized, { skip!(node.shebang); for it in &node.attrs { v.visit_attribute(it); } for it in &node.items { v.visit_item(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_fn_arg<'ast, V>(v: &mut V, node: &'ast crate::FnArg) where V: Visit<'ast> + ?Sized, { match node { crate::FnArg::Receiver(_binding_0) => { v.visit_receiver(_binding_0); } crate::FnArg::Typed(_binding_0) => { v.visit_pat_type(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item<'ast, V>(v: &mut V, node: &'ast crate::ForeignItem) where V: Visit<'ast> + ?Sized, { match node { crate::ForeignItem::Fn(_binding_0) => { v.visit_foreign_item_fn(_binding_0); } crate::ForeignItem::Static(_binding_0) => { v.visit_foreign_item_static(_binding_0); } crate::ForeignItem::Type(_binding_0) => { v.visit_foreign_item_type(_binding_0); } crate::ForeignItem::Macro(_binding_0) => { v.visit_foreign_item_macro(_binding_0); } crate::ForeignItem::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_fn<'ast, V>(v: &mut V, node: &'ast crate::ForeignItemFn) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); v.visit_signature(&node.sig); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_macro<'ast, V>(v: &mut V, node: &'ast crate::ForeignItemMacro) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_macro(&node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_static<'ast, V>( v: &mut V, node: &'ast crate::ForeignItemStatic, ) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.static_token); v.visit_static_mutability(&node.mutability); v.visit_ident(&node.ident); skip!(node.colon_token); v.visit_type(&*node.ty); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_type<'ast, V>(v: &mut V, node: &'ast crate::ForeignItemType) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.type_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.semi_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_generic_argument<'ast, V>(v: &mut V, node: &'ast crate::GenericArgument) where V: Visit<'ast> + ?Sized, { match node { crate::GenericArgument::Lifetime(_binding_0) => { v.visit_lifetime(_binding_0); } crate::GenericArgument::Type(_binding_0) => { v.visit_type(_binding_0); } crate::GenericArgument::Const(_binding_0) => { v.visit_expr(_binding_0); } crate::GenericArgument::AssocType(_binding_0) => { v.visit_assoc_type(_binding_0); } crate::GenericArgument::AssocConst(_binding_0) => { v.visit_assoc_const(_binding_0); } crate::GenericArgument::Constraint(_binding_0) => { v.visit_constraint(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_generic_param<'ast, V>(v: &mut V, node: &'ast crate::GenericParam) where V: Visit<'ast> + ?Sized, { match node { crate::GenericParam::Lifetime(_binding_0) => { v.visit_lifetime_param(_binding_0); } crate::GenericParam::Type(_binding_0) => { v.visit_type_param(_binding_0); } crate::GenericParam::Const(_binding_0) => { v.visit_const_param(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_generics<'ast, V>(v: &mut V, node: &'ast crate::Generics) where V: Visit<'ast> + ?Sized, { skip!(node.lt_token); for el in Punctuated::pairs(&node.params) { let it = el.value(); v.visit_generic_param(it); } skip!(node.gt_token); if let Some(it) = &node.where_clause { v.visit_where_clause(it); } } pub fn visit_ident<'ast, V>(v: &mut V, node: &'ast proc_macro2::Ident) where V: Visit<'ast> + ?Sized, { v.visit_span(&node.span()); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item<'ast, V>(v: &mut V, node: &'ast crate::ImplItem) where V: Visit<'ast> + ?Sized, { match node { crate::ImplItem::Const(_binding_0) => { v.visit_impl_item_const(_binding_0); } crate::ImplItem::Fn(_binding_0) => { v.visit_impl_item_fn(_binding_0); } crate::ImplItem::Type(_binding_0) => { v.visit_impl_item_type(_binding_0); } crate::ImplItem::Macro(_binding_0) => { v.visit_impl_item_macro(_binding_0); } crate::ImplItem::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_const<'ast, V>(v: &mut V, node: &'ast crate::ImplItemConst) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.defaultness); skip!(node.const_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.colon_token); v.visit_type(&node.ty); skip!(node.eq_token); v.visit_expr(&node.expr); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_fn<'ast, V>(v: &mut V, node: &'ast crate::ImplItemFn) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.defaultness); v.visit_signature(&node.sig); v.visit_block(&node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_macro<'ast, V>(v: &mut V, node: &'ast crate::ImplItemMacro) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_macro(&node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_type<'ast, V>(v: &mut V, node: &'ast crate::ImplItemType) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.defaultness); skip!(node.type_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.eq_token); v.visit_type(&node.ty); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_restriction<'ast, V>(v: &mut V, node: &'ast crate::ImplRestriction) where V: Visit<'ast> + ?Sized, { match *node {} } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_index<'ast, V>(v: &mut V, node: &'ast crate::Index) where V: Visit<'ast> + ?Sized, { skip!(node.index); v.visit_span(&node.span); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item<'ast, V>(v: &mut V, node: &'ast crate::Item) where V: Visit<'ast> + ?Sized, { match node { crate::Item::Const(_binding_0) => { v.visit_item_const(_binding_0); } crate::Item::Enum(_binding_0) => { v.visit_item_enum(_binding_0); } crate::Item::ExternCrate(_binding_0) => { v.visit_item_extern_crate(_binding_0); } crate::Item::Fn(_binding_0) => { v.visit_item_fn(_binding_0); } crate::Item::ForeignMod(_binding_0) => { v.visit_item_foreign_mod(_binding_0); } crate::Item::Impl(_binding_0) => { v.visit_item_impl(_binding_0); } crate::Item::Macro(_binding_0) => { v.visit_item_macro(_binding_0); } crate::Item::Mod(_binding_0) => { v.visit_item_mod(_binding_0); } crate::Item::Static(_binding_0) => { v.visit_item_static(_binding_0); } crate::Item::Struct(_binding_0) => { v.visit_item_struct(_binding_0); } crate::Item::Trait(_binding_0) => { v.visit_item_trait(_binding_0); } crate::Item::TraitAlias(_binding_0) => { v.visit_item_trait_alias(_binding_0); } crate::Item::Type(_binding_0) => { v.visit_item_type(_binding_0); } crate::Item::Union(_binding_0) => { v.visit_item_union(_binding_0); } crate::Item::Use(_binding_0) => { v.visit_item_use(_binding_0); } crate::Item::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_const<'ast, V>(v: &mut V, node: &'ast crate::ItemConst) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.const_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.colon_token); v.visit_type(&*node.ty); skip!(node.eq_token); v.visit_expr(&*node.expr); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_enum<'ast, V>(v: &mut V, node: &'ast crate::ItemEnum) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.enum_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.brace_token); for el in Punctuated::pairs(&node.variants) { let it = el.value(); v.visit_variant(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_extern_crate<'ast, V>(v: &mut V, node: &'ast crate::ItemExternCrate) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.extern_token); skip!(node.crate_token); v.visit_ident(&node.ident); if let Some(it) = &node.rename { skip!((it).0); v.visit_ident(&(it).1); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_fn<'ast, V>(v: &mut V, node: &'ast crate::ItemFn) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); v.visit_signature(&node.sig); v.visit_block(&*node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_foreign_mod<'ast, V>(v: &mut V, node: &'ast crate::ItemForeignMod) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.unsafety); v.visit_abi(&node.abi); skip!(node.brace_token); for it in &node.items { v.visit_foreign_item(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_impl<'ast, V>(v: &mut V, node: &'ast crate::ItemImpl) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.defaultness); skip!(node.unsafety); skip!(node.impl_token); v.visit_generics(&node.generics); if let Some(it) = &node.trait_ { skip!((it).0); v.visit_path(&(it).1); skip!((it).2); } v.visit_type(&*node.self_ty); skip!(node.brace_token); for it in &node.items { v.visit_impl_item(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_macro<'ast, V>(v: &mut V, node: &'ast crate::ItemMacro) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.ident { v.visit_ident(it); } v.visit_macro(&node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_mod<'ast, V>(v: &mut V, node: &'ast crate::ItemMod) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.unsafety); skip!(node.mod_token); v.visit_ident(&node.ident); if let Some(it) = &node.content { skip!((it).0); for it in &(it).1 { v.visit_item(it); } } skip!(node.semi); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_static<'ast, V>(v: &mut V, node: &'ast crate::ItemStatic) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.static_token); v.visit_static_mutability(&node.mutability); v.visit_ident(&node.ident); skip!(node.colon_token); v.visit_type(&*node.ty); skip!(node.eq_token); v.visit_expr(&*node.expr); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_struct<'ast, V>(v: &mut V, node: &'ast crate::ItemStruct) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.struct_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); v.visit_fields(&node.fields); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_trait<'ast, V>(v: &mut V, node: &'ast crate::ItemTrait) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.unsafety); skip!(node.auto_token); if let Some(it) = &node.restriction { v.visit_impl_restriction(it); } skip!(node.trait_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.colon_token); for el in Punctuated::pairs(&node.supertraits) { let it = el.value(); v.visit_type_param_bound(it); } skip!(node.brace_token); for it in &node.items { v.visit_trait_item(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_trait_alias<'ast, V>(v: &mut V, node: &'ast crate::ItemTraitAlias) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.trait_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.eq_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_type_param_bound(it); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_type<'ast, V>(v: &mut V, node: &'ast crate::ItemType) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.type_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.eq_token); v.visit_type(&*node.ty); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_union<'ast, V>(v: &mut V, node: &'ast crate::ItemUnion) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.union_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); v.visit_fields_named(&node.fields); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_use<'ast, V>(v: &mut V, node: &'ast crate::ItemUse) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_visibility(&node.vis); skip!(node.use_token); skip!(node.leading_colon); v.visit_use_tree(&node.tree); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_label<'ast, V>(v: &mut V, node: &'ast crate::Label) where V: Visit<'ast> + ?Sized, { v.visit_lifetime(&node.name); skip!(node.colon_token); } pub fn visit_lifetime<'ast, V>(v: &mut V, node: &'ast crate::Lifetime) where V: Visit<'ast> + ?Sized, { v.visit_span(&node.apostrophe); v.visit_ident(&node.ident); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_lifetime_param<'ast, V>(v: &mut V, node: &'ast crate::LifetimeParam) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_lifetime(&node.lifetime); skip!(node.colon_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_lifetime(it); } } pub fn visit_lit<'ast, V>(v: &mut V, node: &'ast crate::Lit) where V: Visit<'ast> + ?Sized, { match node { crate::Lit::Str(_binding_0) => { v.visit_lit_str(_binding_0); } crate::Lit::ByteStr(_binding_0) => { v.visit_lit_byte_str(_binding_0); } crate::Lit::CStr(_binding_0) => { v.visit_lit_cstr(_binding_0); } crate::Lit::Byte(_binding_0) => { v.visit_lit_byte(_binding_0); } crate::Lit::Char(_binding_0) => { v.visit_lit_char(_binding_0); } crate::Lit::Int(_binding_0) => { v.visit_lit_int(_binding_0); } crate::Lit::Float(_binding_0) => { v.visit_lit_float(_binding_0); } crate::Lit::Bool(_binding_0) => { v.visit_lit_bool(_binding_0); } crate::Lit::Verbatim(_binding_0) => { skip!(_binding_0); } } } pub fn visit_lit_bool<'ast, V>(v: &mut V, node: &'ast crate::LitBool) where V: Visit<'ast> + ?Sized, { skip!(node.value); v.visit_span(&node.span); } pub fn visit_lit_byte<'ast, V>(v: &mut V, node: &'ast crate::LitByte) where V: Visit<'ast> + ?Sized, {} pub fn visit_lit_byte_str<'ast, V>(v: &mut V, node: &'ast crate::LitByteStr) where V: Visit<'ast> + ?Sized, {} pub fn visit_lit_cstr<'ast, V>(v: &mut V, node: &'ast crate::LitCStr) where V: Visit<'ast> + ?Sized, {} pub fn visit_lit_char<'ast, V>(v: &mut V, node: &'ast crate::LitChar) where V: Visit<'ast> + ?Sized, {} pub fn visit_lit_float<'ast, V>(v: &mut V, node: &'ast crate::LitFloat) where V: Visit<'ast> + ?Sized, {} pub fn visit_lit_int<'ast, V>(v: &mut V, node: &'ast crate::LitInt) where V: Visit<'ast> + ?Sized, {} pub fn visit_lit_str<'ast, V>(v: &mut V, node: &'ast crate::LitStr) where V: Visit<'ast> + ?Sized, {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_local<'ast, V>(v: &mut V, node: &'ast crate::Local) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.let_token); v.visit_pat(&node.pat); if let Some(it) = &node.init { v.visit_local_init(it); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_local_init<'ast, V>(v: &mut V, node: &'ast crate::LocalInit) where V: Visit<'ast> + ?Sized, { skip!(node.eq_token); v.visit_expr(&*node.expr); if let Some(it) = &node.diverge { skip!((it).0); v.visit_expr(&*(it).1); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_macro<'ast, V>(v: &mut V, node: &'ast crate::Macro) where V: Visit<'ast> + ?Sized, { v.visit_path(&node.path); skip!(node.bang_token); v.visit_macro_delimiter(&node.delimiter); skip!(node.tokens); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_macro_delimiter<'ast, V>(v: &mut V, node: &'ast crate::MacroDelimiter) where V: Visit<'ast> + ?Sized, { match node { crate::MacroDelimiter::Paren(_binding_0) => { skip!(_binding_0); } crate::MacroDelimiter::Brace(_binding_0) => { skip!(_binding_0); } crate::MacroDelimiter::Bracket(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_member<'ast, V>(v: &mut V, node: &'ast crate::Member) where V: Visit<'ast> + ?Sized, { match node { crate::Member::Named(_binding_0) => { v.visit_ident(_binding_0); } crate::Member::Unnamed(_binding_0) => { v.visit_index(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_meta<'ast, V>(v: &mut V, node: &'ast crate::Meta) where V: Visit<'ast> + ?Sized, { match node { crate::Meta::Path(_binding_0) => { v.visit_path(_binding_0); } crate::Meta::List(_binding_0) => { v.visit_meta_list(_binding_0); } crate::Meta::NameValue(_binding_0) => { v.visit_meta_name_value(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_meta_list<'ast, V>(v: &mut V, node: &'ast crate::MetaList) where V: Visit<'ast> + ?Sized, { v.visit_path(&node.path); v.visit_macro_delimiter(&node.delimiter); skip!(node.tokens); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_meta_name_value<'ast, V>(v: &mut V, node: &'ast crate::MetaNameValue) where V: Visit<'ast> + ?Sized, { v.visit_path(&node.path); skip!(node.eq_token); v.visit_expr(&node.value); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_parenthesized_generic_arguments<'ast, V>( v: &mut V, node: &'ast crate::ParenthesizedGenericArguments, ) where V: Visit<'ast> + ?Sized, { skip!(node.paren_token); for el in Punctuated::pairs(&node.inputs) { let it = el.value(); v.visit_type(it); } v.visit_return_type(&node.output); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat<'ast, V>(v: &mut V, node: &'ast crate::Pat) where V: Visit<'ast> + ?Sized, { match node { crate::Pat::Const(_binding_0) => { v.visit_expr_const(_binding_0); } crate::Pat::Ident(_binding_0) => { v.visit_pat_ident(_binding_0); } crate::Pat::Lit(_binding_0) => { v.visit_expr_lit(_binding_0); } crate::Pat::Macro(_binding_0) => { v.visit_expr_macro(_binding_0); } crate::Pat::Or(_binding_0) => { v.visit_pat_or(_binding_0); } crate::Pat::Paren(_binding_0) => { v.visit_pat_paren(_binding_0); } crate::Pat::Path(_binding_0) => { v.visit_expr_path(_binding_0); } crate::Pat::Range(_binding_0) => { v.visit_expr_range(_binding_0); } crate::Pat::Reference(_binding_0) => { v.visit_pat_reference(_binding_0); } crate::Pat::Rest(_binding_0) => { v.visit_pat_rest(_binding_0); } crate::Pat::Slice(_binding_0) => { v.visit_pat_slice(_binding_0); } crate::Pat::Struct(_binding_0) => { v.visit_pat_struct(_binding_0); } crate::Pat::Tuple(_binding_0) => { v.visit_pat_tuple(_binding_0); } crate::Pat::TupleStruct(_binding_0) => { v.visit_pat_tuple_struct(_binding_0); } crate::Pat::Type(_binding_0) => { v.visit_pat_type(_binding_0); } crate::Pat::Verbatim(_binding_0) => { skip!(_binding_0); } crate::Pat::Wild(_binding_0) => { v.visit_pat_wild(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_ident<'ast, V>(v: &mut V, node: &'ast crate::PatIdent) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.by_ref); skip!(node.mutability); v.visit_ident(&node.ident); if let Some(it) = &node.subpat { skip!((it).0); v.visit_pat(&*(it).1); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_or<'ast, V>(v: &mut V, node: &'ast crate::PatOr) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.leading_vert); for el in Punctuated::pairs(&node.cases) { let it = el.value(); v.visit_pat(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_paren<'ast, V>(v: &mut V, node: &'ast crate::PatParen) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.paren_token); v.visit_pat(&*node.pat); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_reference<'ast, V>(v: &mut V, node: &'ast crate::PatReference) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.and_token); skip!(node.mutability); v.visit_pat(&*node.pat); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_rest<'ast, V>(v: &mut V, node: &'ast crate::PatRest) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.dot2_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_slice<'ast, V>(v: &mut V, node: &'ast crate::PatSlice) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.bracket_token); for el in Punctuated::pairs(&node.elems) { let it = el.value(); v.visit_pat(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_struct<'ast, V>(v: &mut V, node: &'ast crate::PatStruct) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.qself { v.visit_qself(it); } v.visit_path(&node.path); skip!(node.brace_token); for el in Punctuated::pairs(&node.fields) { let it = el.value(); v.visit_field_pat(it); } if let Some(it) = &node.rest { v.visit_pat_rest(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_tuple<'ast, V>(v: &mut V, node: &'ast crate::PatTuple) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.paren_token); for el in Punctuated::pairs(&node.elems) { let it = el.value(); v.visit_pat(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_tuple_struct<'ast, V>(v: &mut V, node: &'ast crate::PatTupleStruct) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.qself { v.visit_qself(it); } v.visit_path(&node.path); skip!(node.paren_token); for el in Punctuated::pairs(&node.elems) { let it = el.value(); v.visit_pat(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_type<'ast, V>(v: &mut V, node: &'ast crate::PatType) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_pat(&*node.pat); skip!(node.colon_token); v.visit_type(&*node.ty); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_wild<'ast, V>(v: &mut V, node: &'ast crate::PatWild) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.underscore_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_path<'ast, V>(v: &mut V, node: &'ast crate::Path) where V: Visit<'ast> + ?Sized, { skip!(node.leading_colon); for el in Punctuated::pairs(&node.segments) { let it = el.value(); v.visit_path_segment(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_path_arguments<'ast, V>(v: &mut V, node: &'ast crate::PathArguments) where V: Visit<'ast> + ?Sized, { match node { crate::PathArguments::None => {} crate::PathArguments::AngleBracketed(_binding_0) => { v.visit_angle_bracketed_generic_arguments(_binding_0); } crate::PathArguments::Parenthesized(_binding_0) => { v.visit_parenthesized_generic_arguments(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_path_segment<'ast, V>(v: &mut V, node: &'ast crate::PathSegment) where V: Visit<'ast> + ?Sized, { v.visit_ident(&node.ident); v.visit_path_arguments(&node.arguments); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_predicate_lifetime<'ast, V>(v: &mut V, node: &'ast crate::PredicateLifetime) where V: Visit<'ast> + ?Sized, { v.visit_lifetime(&node.lifetime); skip!(node.colon_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_lifetime(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_predicate_type<'ast, V>(v: &mut V, node: &'ast crate::PredicateType) where V: Visit<'ast> + ?Sized, { if let Some(it) = &node.lifetimes { v.visit_bound_lifetimes(it); } v.visit_type(&node.bounded_ty); skip!(node.colon_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_type_param_bound(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_qself<'ast, V>(v: &mut V, node: &'ast crate::QSelf) where V: Visit<'ast> + ?Sized, { skip!(node.lt_token); v.visit_type(&*node.ty); skip!(node.position); skip!(node.as_token); skip!(node.gt_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_range_limits<'ast, V>(v: &mut V, node: &'ast crate::RangeLimits) where V: Visit<'ast> + ?Sized, { match node { crate::RangeLimits::HalfOpen(_binding_0) => { skip!(_binding_0); } crate::RangeLimits::Closed(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_receiver<'ast, V>(v: &mut V, node: &'ast crate::Receiver) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.reference { skip!((it).0); if let Some(it) = &(it).1 { v.visit_lifetime(it); } } skip!(node.mutability); skip!(node.self_token); skip!(node.colon_token); v.visit_type(&*node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_return_type<'ast, V>(v: &mut V, node: &'ast crate::ReturnType) where V: Visit<'ast> + ?Sized, { match node { crate::ReturnType::Default => {} crate::ReturnType::Type(_binding_0, _binding_1) => { skip!(_binding_0); v.visit_type(&**_binding_1); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_signature<'ast, V>(v: &mut V, node: &'ast crate::Signature) where V: Visit<'ast> + ?Sized, { skip!(node.constness); skip!(node.asyncness); skip!(node.unsafety); if let Some(it) = &node.abi { v.visit_abi(it); } skip!(node.fn_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.paren_token); for el in Punctuated::pairs(&node.inputs) { let it = el.value(); v.visit_fn_arg(it); } if let Some(it) = &node.variadic { v.visit_variadic(it); } v.visit_return_type(&node.output); } pub fn visit_span<'ast, V>(v: &mut V, node: &proc_macro2::Span) where V: Visit<'ast> + ?Sized, {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_static_mutability<'ast, V>(v: &mut V, node: &'ast crate::StaticMutability) where V: Visit<'ast> + ?Sized, { match node { crate::StaticMutability::Mut(_binding_0) => { skip!(_binding_0); } crate::StaticMutability::None => {} } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_stmt<'ast, V>(v: &mut V, node: &'ast crate::Stmt) where V: Visit<'ast> + ?Sized, { match node { crate::Stmt::Local(_binding_0) => { v.visit_local(_binding_0); } crate::Stmt::Item(_binding_0) => { v.visit_item(_binding_0); } crate::Stmt::Expr(_binding_0, _binding_1) => { v.visit_expr(_binding_0); skip!(_binding_1); } crate::Stmt::Macro(_binding_0) => { v.visit_stmt_macro(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_stmt_macro<'ast, V>(v: &mut V, node: &'ast crate::StmtMacro) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_macro(&node.mac); skip!(node.semi_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_trait_bound<'ast, V>(v: &mut V, node: &'ast crate::TraitBound) where V: Visit<'ast> + ?Sized, { skip!(node.paren_token); v.visit_trait_bound_modifier(&node.modifier); if let Some(it) = &node.lifetimes { v.visit_bound_lifetimes(it); } v.visit_path(&node.path); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_trait_bound_modifier<'ast, V>( v: &mut V, node: &'ast crate::TraitBoundModifier, ) where V: Visit<'ast> + ?Sized, { match node { crate::TraitBoundModifier::None => {} crate::TraitBoundModifier::Maybe(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item<'ast, V>(v: &mut V, node: &'ast crate::TraitItem) where V: Visit<'ast> + ?Sized, { match node { crate::TraitItem::Const(_binding_0) => { v.visit_trait_item_const(_binding_0); } crate::TraitItem::Fn(_binding_0) => { v.visit_trait_item_fn(_binding_0); } crate::TraitItem::Type(_binding_0) => { v.visit_trait_item_type(_binding_0); } crate::TraitItem::Macro(_binding_0) => { v.visit_trait_item_macro(_binding_0); } crate::TraitItem::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_const<'ast, V>(v: &mut V, node: &'ast crate::TraitItemConst) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.const_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.colon_token); v.visit_type(&node.ty); if let Some(it) = &node.default { skip!((it).0); v.visit_expr(&(it).1); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_fn<'ast, V>(v: &mut V, node: &'ast crate::TraitItemFn) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_signature(&node.sig); if let Some(it) = &node.default { v.visit_block(it); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_macro<'ast, V>(v: &mut V, node: &'ast crate::TraitItemMacro) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_macro(&node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_type<'ast, V>(v: &mut V, node: &'ast crate::TraitItemType) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } skip!(node.type_token); v.visit_ident(&node.ident); v.visit_generics(&node.generics); skip!(node.colon_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_type_param_bound(it); } if let Some(it) = &node.default { skip!((it).0); v.visit_type(&(it).1); } skip!(node.semi_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type<'ast, V>(v: &mut V, node: &'ast crate::Type) where V: Visit<'ast> + ?Sized, { match node { crate::Type::Array(_binding_0) => { v.visit_type_array(_binding_0); } crate::Type::BareFn(_binding_0) => { v.visit_type_bare_fn(_binding_0); } crate::Type::Group(_binding_0) => { v.visit_type_group(_binding_0); } crate::Type::ImplTrait(_binding_0) => { v.visit_type_impl_trait(_binding_0); } crate::Type::Infer(_binding_0) => { v.visit_type_infer(_binding_0); } crate::Type::Macro(_binding_0) => { v.visit_type_macro(_binding_0); } crate::Type::Never(_binding_0) => { v.visit_type_never(_binding_0); } crate::Type::Paren(_binding_0) => { v.visit_type_paren(_binding_0); } crate::Type::Path(_binding_0) => { v.visit_type_path(_binding_0); } crate::Type::Ptr(_binding_0) => { v.visit_type_ptr(_binding_0); } crate::Type::Reference(_binding_0) => { v.visit_type_reference(_binding_0); } crate::Type::Slice(_binding_0) => { v.visit_type_slice(_binding_0); } crate::Type::TraitObject(_binding_0) => { v.visit_type_trait_object(_binding_0); } crate::Type::Tuple(_binding_0) => { v.visit_type_tuple(_binding_0); } crate::Type::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_array<'ast, V>(v: &mut V, node: &'ast crate::TypeArray) where V: Visit<'ast> + ?Sized, { skip!(node.bracket_token); v.visit_type(&*node.elem); skip!(node.semi_token); v.visit_expr(&node.len); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_bare_fn<'ast, V>(v: &mut V, node: &'ast crate::TypeBareFn) where V: Visit<'ast> + ?Sized, { if let Some(it) = &node.lifetimes { v.visit_bound_lifetimes(it); } skip!(node.unsafety); if let Some(it) = &node.abi { v.visit_abi(it); } skip!(node.fn_token); skip!(node.paren_token); for el in Punctuated::pairs(&node.inputs) { let it = el.value(); v.visit_bare_fn_arg(it); } if let Some(it) = &node.variadic { v.visit_bare_variadic(it); } v.visit_return_type(&node.output); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_group<'ast, V>(v: &mut V, node: &'ast crate::TypeGroup) where V: Visit<'ast> + ?Sized, { skip!(node.group_token); v.visit_type(&*node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_impl_trait<'ast, V>(v: &mut V, node: &'ast crate::TypeImplTrait) where V: Visit<'ast> + ?Sized, { skip!(node.impl_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_type_param_bound(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_infer<'ast, V>(v: &mut V, node: &'ast crate::TypeInfer) where V: Visit<'ast> + ?Sized, { skip!(node.underscore_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_macro<'ast, V>(v: &mut V, node: &'ast crate::TypeMacro) where V: Visit<'ast> + ?Sized, { v.visit_macro(&node.mac); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_never<'ast, V>(v: &mut V, node: &'ast crate::TypeNever) where V: Visit<'ast> + ?Sized, { skip!(node.bang_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_param<'ast, V>(v: &mut V, node: &'ast crate::TypeParam) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_ident(&node.ident); skip!(node.colon_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_type_param_bound(it); } skip!(node.eq_token); if let Some(it) = &node.default { v.visit_type(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_param_bound<'ast, V>(v: &mut V, node: &'ast crate::TypeParamBound) where V: Visit<'ast> + ?Sized, { match node { crate::TypeParamBound::Trait(_binding_0) => { v.visit_trait_bound(_binding_0); } crate::TypeParamBound::Lifetime(_binding_0) => { v.visit_lifetime(_binding_0); } crate::TypeParamBound::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_paren<'ast, V>(v: &mut V, node: &'ast crate::TypeParen) where V: Visit<'ast> + ?Sized, { skip!(node.paren_token); v.visit_type(&*node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_path<'ast, V>(v: &mut V, node: &'ast crate::TypePath) where V: Visit<'ast> + ?Sized, { if let Some(it) = &node.qself { v.visit_qself(it); } v.visit_path(&node.path); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_ptr<'ast, V>(v: &mut V, node: &'ast crate::TypePtr) where V: Visit<'ast> + ?Sized, { skip!(node.star_token); skip!(node.const_token); skip!(node.mutability); v.visit_type(&*node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_reference<'ast, V>(v: &mut V, node: &'ast crate::TypeReference) where V: Visit<'ast> + ?Sized, { skip!(node.and_token); if let Some(it) = &node.lifetime { v.visit_lifetime(it); } skip!(node.mutability); v.visit_type(&*node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_slice<'ast, V>(v: &mut V, node: &'ast crate::TypeSlice) where V: Visit<'ast> + ?Sized, { skip!(node.bracket_token); v.visit_type(&*node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_trait_object<'ast, V>(v: &mut V, node: &'ast crate::TypeTraitObject) where V: Visit<'ast> + ?Sized, { skip!(node.dyn_token); for el in Punctuated::pairs(&node.bounds) { let it = el.value(); v.visit_type_param_bound(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_tuple<'ast, V>(v: &mut V, node: &'ast crate::TypeTuple) where V: Visit<'ast> + ?Sized, { skip!(node.paren_token); for el in Punctuated::pairs(&node.elems) { let it = el.value(); v.visit_type(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_un_op<'ast, V>(v: &mut V, node: &'ast crate::UnOp) where V: Visit<'ast> + ?Sized, { match node { crate::UnOp::Deref(_binding_0) => { skip!(_binding_0); } crate::UnOp::Not(_binding_0) => { skip!(_binding_0); } crate::UnOp::Neg(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_glob<'ast, V>(v: &mut V, node: &'ast crate::UseGlob) where V: Visit<'ast> + ?Sized, { skip!(node.star_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_group<'ast, V>(v: &mut V, node: &'ast crate::UseGroup) where V: Visit<'ast> + ?Sized, { skip!(node.brace_token); for el in Punctuated::pairs(&node.items) { let it = el.value(); v.visit_use_tree(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_name<'ast, V>(v: &mut V, node: &'ast crate::UseName) where V: Visit<'ast> + ?Sized, { v.visit_ident(&node.ident); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_path<'ast, V>(v: &mut V, node: &'ast crate::UsePath) where V: Visit<'ast> + ?Sized, { v.visit_ident(&node.ident); skip!(node.colon2_token); v.visit_use_tree(&*node.tree); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_rename<'ast, V>(v: &mut V, node: &'ast crate::UseRename) where V: Visit<'ast> + ?Sized, { v.visit_ident(&node.ident); skip!(node.as_token); v.visit_ident(&node.rename); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_tree<'ast, V>(v: &mut V, node: &'ast crate::UseTree) where V: Visit<'ast> + ?Sized, { match node { crate::UseTree::Path(_binding_0) => { v.visit_use_path(_binding_0); } crate::UseTree::Name(_binding_0) => { v.visit_use_name(_binding_0); } crate::UseTree::Rename(_binding_0) => { v.visit_use_rename(_binding_0); } crate::UseTree::Glob(_binding_0) => { v.visit_use_glob(_binding_0); } crate::UseTree::Group(_binding_0) => { v.visit_use_group(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_variadic<'ast, V>(v: &mut V, node: &'ast crate::Variadic) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } if let Some(it) = &node.pat { v.visit_pat(&*(it).0); skip!((it).1); } skip!(node.dots); skip!(node.comma); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_variant<'ast, V>(v: &mut V, node: &'ast crate::Variant) where V: Visit<'ast> + ?Sized, { for it in &node.attrs { v.visit_attribute(it); } v.visit_ident(&node.ident); v.visit_fields(&node.fields); if let Some(it) = &node.discriminant { skip!((it).0); v.visit_expr(&(it).1); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_vis_restricted<'ast, V>(v: &mut V, node: &'ast crate::VisRestricted) where V: Visit<'ast> + ?Sized, { skip!(node.pub_token); skip!(node.paren_token); skip!(node.in_token); v.visit_path(&*node.path); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_visibility<'ast, V>(v: &mut V, node: &'ast crate::Visibility) where V: Visit<'ast> + ?Sized, { match node { crate::Visibility::Public(_binding_0) => { skip!(_binding_0); } crate::Visibility::Restricted(_binding_0) => { v.visit_vis_restricted(_binding_0); } crate::Visibility::Inherited => {} } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_where_clause<'ast, V>(v: &mut V, node: &'ast crate::WhereClause) where V: Visit<'ast> + ?Sized, { skip!(node.where_token); for el in Punctuated::pairs(&node.predicates) { let it = el.value(); v.visit_where_predicate(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_where_predicate<'ast, V>(v: &mut V, node: &'ast crate::WherePredicate) where V: Visit<'ast> + ?Sized, { match node { crate::WherePredicate::Lifetime(_binding_0) => { v.visit_predicate_lifetime(_binding_0); } crate::WherePredicate::Type(_binding_0) => { v.visit_predicate_type(_binding_0); } } } syn/src/gen/eq.rs0000644000175000017500000026130414661133735014673 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #[cfg(any(feature = "derive", feature = "full"))] use crate::tt::TokenStreamHelper; #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Abi {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Abi { fn eq(&self, other: &Self) -> bool { self.name == other.name } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::AngleBracketedGenericArguments {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::AngleBracketedGenericArguments { fn eq(&self, other: &Self) -> bool { self.colon2_token == other.colon2_token && self.args == other.args } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Arm {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Arm { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.pat == other.pat && self.guard == other.guard && self.body == other.body && self.comma == other.comma } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::AssocConst {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::AssocConst { fn eq(&self, other: &Self) -> bool { self.ident == other.ident && self.generics == other.generics && self.value == other.value } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::AssocType {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::AssocType { fn eq(&self, other: &Self) -> bool { self.ident == other.ident && self.generics == other.generics && self.ty == other.ty } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::AttrStyle {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::AttrStyle { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::AttrStyle::Outer, crate::AttrStyle::Outer) => true, (crate::AttrStyle::Inner(_), crate::AttrStyle::Inner(_)) => true, _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Attribute {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Attribute { fn eq(&self, other: &Self) -> bool { self.style == other.style && self.meta == other.meta } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::BareFnArg {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::BareFnArg { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.name == other.name && self.ty == other.ty } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::BareVariadic {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::BareVariadic { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.name == other.name && self.comma == other.comma } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::BinOp {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::BinOp { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::BinOp::Add(_), crate::BinOp::Add(_)) => true, (crate::BinOp::Sub(_), crate::BinOp::Sub(_)) => true, (crate::BinOp::Mul(_), crate::BinOp::Mul(_)) => true, (crate::BinOp::Div(_), crate::BinOp::Div(_)) => true, (crate::BinOp::Rem(_), crate::BinOp::Rem(_)) => true, (crate::BinOp::And(_), crate::BinOp::And(_)) => true, (crate::BinOp::Or(_), crate::BinOp::Or(_)) => true, (crate::BinOp::BitXor(_), crate::BinOp::BitXor(_)) => true, (crate::BinOp::BitAnd(_), crate::BinOp::BitAnd(_)) => true, (crate::BinOp::BitOr(_), crate::BinOp::BitOr(_)) => true, (crate::BinOp::Shl(_), crate::BinOp::Shl(_)) => true, (crate::BinOp::Shr(_), crate::BinOp::Shr(_)) => true, (crate::BinOp::Eq(_), crate::BinOp::Eq(_)) => true, (crate::BinOp::Lt(_), crate::BinOp::Lt(_)) => true, (crate::BinOp::Le(_), crate::BinOp::Le(_)) => true, (crate::BinOp::Ne(_), crate::BinOp::Ne(_)) => true, (crate::BinOp::Ge(_), crate::BinOp::Ge(_)) => true, (crate::BinOp::Gt(_), crate::BinOp::Gt(_)) => true, (crate::BinOp::AddAssign(_), crate::BinOp::AddAssign(_)) => true, (crate::BinOp::SubAssign(_), crate::BinOp::SubAssign(_)) => true, (crate::BinOp::MulAssign(_), crate::BinOp::MulAssign(_)) => true, (crate::BinOp::DivAssign(_), crate::BinOp::DivAssign(_)) => true, (crate::BinOp::RemAssign(_), crate::BinOp::RemAssign(_)) => true, (crate::BinOp::BitXorAssign(_), crate::BinOp::BitXorAssign(_)) => true, (crate::BinOp::BitAndAssign(_), crate::BinOp::BitAndAssign(_)) => true, (crate::BinOp::BitOrAssign(_), crate::BinOp::BitOrAssign(_)) => true, (crate::BinOp::ShlAssign(_), crate::BinOp::ShlAssign(_)) => true, (crate::BinOp::ShrAssign(_), crate::BinOp::ShrAssign(_)) => true, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Block {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Block { fn eq(&self, other: &Self) -> bool { self.stmts == other.stmts } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::BoundLifetimes {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::BoundLifetimes { fn eq(&self, other: &Self) -> bool { self.lifetimes == other.lifetimes } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ConstParam {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ConstParam { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.ident == other.ident && self.ty == other.ty && self.eq_token == other.eq_token && self.default == other.default } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Constraint {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Constraint { fn eq(&self, other: &Self) -> bool { self.ident == other.ident && self.generics == other.generics && self.bounds == other.bounds } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Data {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Data { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Data::Struct(self0), crate::Data::Struct(other0)) => self0 == other0, (crate::Data::Enum(self0), crate::Data::Enum(other0)) => self0 == other0, (crate::Data::Union(self0), crate::Data::Union(other0)) => self0 == other0, _ => false, } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::DataEnum {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::DataEnum { fn eq(&self, other: &Self) -> bool { self.variants == other.variants } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::DataStruct {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::DataStruct { fn eq(&self, other: &Self) -> bool { self.fields == other.fields && self.semi_token == other.semi_token } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::DataUnion {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::DataUnion { fn eq(&self, other: &Self) -> bool { self.fields == other.fields } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::DeriveInput {} #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::DeriveInput { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics && self.data == other.data } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Expr {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Expr { fn eq(&self, other: &Self) -> bool { match (self, other) { #[cfg(feature = "full")] (crate::Expr::Array(self0), crate::Expr::Array(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Assign(self0), crate::Expr::Assign(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Async(self0), crate::Expr::Async(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Await(self0), crate::Expr::Await(other0)) => self0 == other0, (crate::Expr::Binary(self0), crate::Expr::Binary(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Block(self0), crate::Expr::Block(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Break(self0), crate::Expr::Break(other0)) => self0 == other0, (crate::Expr::Call(self0), crate::Expr::Call(other0)) => self0 == other0, (crate::Expr::Cast(self0), crate::Expr::Cast(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Closure(self0), crate::Expr::Closure(other0)) => { self0 == other0 } #[cfg(feature = "full")] (crate::Expr::Const(self0), crate::Expr::Const(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Continue(self0), crate::Expr::Continue(other0)) => { self0 == other0 } (crate::Expr::Field(self0), crate::Expr::Field(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::ForLoop(self0), crate::Expr::ForLoop(other0)) => { self0 == other0 } (crate::Expr::Group(self0), crate::Expr::Group(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::If(self0), crate::Expr::If(other0)) => self0 == other0, (crate::Expr::Index(self0), crate::Expr::Index(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Infer(self0), crate::Expr::Infer(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Let(self0), crate::Expr::Let(other0)) => self0 == other0, (crate::Expr::Lit(self0), crate::Expr::Lit(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Loop(self0), crate::Expr::Loop(other0)) => self0 == other0, (crate::Expr::Macro(self0), crate::Expr::Macro(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Match(self0), crate::Expr::Match(other0)) => self0 == other0, (crate::Expr::MethodCall(self0), crate::Expr::MethodCall(other0)) => { self0 == other0 } (crate::Expr::Paren(self0), crate::Expr::Paren(other0)) => self0 == other0, (crate::Expr::Path(self0), crate::Expr::Path(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Range(self0), crate::Expr::Range(other0)) => self0 == other0, (crate::Expr::Reference(self0), crate::Expr::Reference(other0)) => { self0 == other0 } #[cfg(feature = "full")] (crate::Expr::Repeat(self0), crate::Expr::Repeat(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Return(self0), crate::Expr::Return(other0)) => self0 == other0, (crate::Expr::Struct(self0), crate::Expr::Struct(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Try(self0), crate::Expr::Try(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::TryBlock(self0), crate::Expr::TryBlock(other0)) => { self0 == other0 } #[cfg(feature = "full")] (crate::Expr::Tuple(self0), crate::Expr::Tuple(other0)) => self0 == other0, (crate::Expr::Unary(self0), crate::Expr::Unary(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Unsafe(self0), crate::Expr::Unsafe(other0)) => self0 == other0, (crate::Expr::Verbatim(self0), crate::Expr::Verbatim(other0)) => { TokenStreamHelper(self0) == TokenStreamHelper(other0) } #[cfg(feature = "full")] (crate::Expr::While(self0), crate::Expr::While(other0)) => self0 == other0, #[cfg(feature = "full")] (crate::Expr::Yield(self0), crate::Expr::Yield(other0)) => self0 == other0, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprArray {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprArray { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.elems == other.elems } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprAssign {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprAssign { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.left == other.left && self.right == other.right } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprAsync {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprAsync { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.capture == other.capture && self.block == other.block } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprAwait {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprAwait { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.base == other.base } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprBinary {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprBinary { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.left == other.left && self.op == other.op && self.right == other.right } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprBlock {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprBlock { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.label == other.label && self.block == other.block } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprBreak {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprBreak { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.label == other.label && self.expr == other.expr } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprCall {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprCall { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.func == other.func && self.args == other.args } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprCast {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprCast { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr && self.ty == other.ty } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprClosure {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprClosure { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.lifetimes == other.lifetimes && self.constness == other.constness && self.movability == other.movability && self.asyncness == other.asyncness && self.capture == other.capture && self.inputs == other.inputs && self.output == other.output && self.body == other.body } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprConst {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprConst { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.block == other.block } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprContinue {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprContinue { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.label == other.label } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprField {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprField { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.base == other.base && self.member == other.member } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprForLoop {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprForLoop { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.label == other.label && self.pat == other.pat && self.expr == other.expr && self.body == other.body } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprGroup {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprGroup { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprIf {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprIf { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.cond == other.cond && self.then_branch == other.then_branch && self.else_branch == other.else_branch } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprIndex {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprIndex { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr && self.index == other.index } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprInfer {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprInfer { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprLet {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprLet { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.pat == other.pat && self.expr == other.expr } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprLit {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprLit { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.lit == other.lit } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprLoop {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprLoop { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.label == other.label && self.body == other.body } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprMacro {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprMacro { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.mac == other.mac } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprMatch {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprMatch { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr && self.arms == other.arms } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprMethodCall {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprMethodCall { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.receiver == other.receiver && self.method == other.method && self.turbofish == other.turbofish && self.args == other.args } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprParen {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprParen { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprPath {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprPath { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.qself == other.qself && self.path == other.path } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprRange {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprRange { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.start == other.start && self.limits == other.limits && self.end == other.end } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprReference {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprReference { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.mutability == other.mutability && self.expr == other.expr } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprRepeat {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprRepeat { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr && self.len == other.len } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprReturn {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprReturn { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprStruct {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprStruct { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.qself == other.qself && self.path == other.path && self.fields == other.fields && self.dot2_token == other.dot2_token && self.rest == other.rest } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprTry {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprTry { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprTryBlock {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprTryBlock { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.block == other.block } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprTuple {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprTuple { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.elems == other.elems } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprUnary {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprUnary { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.op == other.op && self.expr == other.expr } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprUnsafe {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprUnsafe { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.block == other.block } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprWhile {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprWhile { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.label == other.label && self.cond == other.cond && self.body == other.body } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ExprYield {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ExprYield { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.expr == other.expr } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Field {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Field { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.mutability == other.mutability && self.ident == other.ident && self.colon_token == other.colon_token && self.ty == other.ty } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FieldMutability {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::FieldMutability { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::FieldMutability::None, crate::FieldMutability::None) => true, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FieldPat {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::FieldPat { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.member == other.member && self.colon_token == other.colon_token && self.pat == other.pat } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FieldValue {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::FieldValue { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.member == other.member && self.colon_token == other.colon_token && self.expr == other.expr } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Fields {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Fields { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Fields::Named(self0), crate::Fields::Named(other0)) => { self0 == other0 } (crate::Fields::Unnamed(self0), crate::Fields::Unnamed(other0)) => { self0 == other0 } (crate::Fields::Unit, crate::Fields::Unit) => true, _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FieldsNamed {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::FieldsNamed { fn eq(&self, other: &Self) -> bool { self.named == other.named } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FieldsUnnamed {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::FieldsUnnamed { fn eq(&self, other: &Self) -> bool { self.unnamed == other.unnamed } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::File {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::File { fn eq(&self, other: &Self) -> bool { self.shebang == other.shebang && self.attrs == other.attrs && self.items == other.items } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::FnArg {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::FnArg { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::FnArg::Receiver(self0), crate::FnArg::Receiver(other0)) => { self0 == other0 } (crate::FnArg::Typed(self0), crate::FnArg::Typed(other0)) => self0 == other0, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ForeignItem {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ForeignItem { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::ForeignItem::Fn(self0), crate::ForeignItem::Fn(other0)) => { self0 == other0 } (crate::ForeignItem::Static(self0), crate::ForeignItem::Static(other0)) => { self0 == other0 } (crate::ForeignItem::Type(self0), crate::ForeignItem::Type(other0)) => { self0 == other0 } (crate::ForeignItem::Macro(self0), crate::ForeignItem::Macro(other0)) => { self0 == other0 } ( crate::ForeignItem::Verbatim(self0), crate::ForeignItem::Verbatim(other0), ) => TokenStreamHelper(self0) == TokenStreamHelper(other0), _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ForeignItemFn {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ForeignItemFn { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.sig == other.sig } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ForeignItemMacro {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ForeignItemMacro { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.mac == other.mac && self.semi_token == other.semi_token } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ForeignItemStatic {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ForeignItemStatic { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.mutability == other.mutability && self.ident == other.ident && self.ty == other.ty } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ForeignItemType {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ForeignItemType { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::GenericArgument {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::GenericArgument { fn eq(&self, other: &Self) -> bool { match (self, other) { ( crate::GenericArgument::Lifetime(self0), crate::GenericArgument::Lifetime(other0), ) => self0 == other0, ( crate::GenericArgument::Type(self0), crate::GenericArgument::Type(other0), ) => self0 == other0, ( crate::GenericArgument::Const(self0), crate::GenericArgument::Const(other0), ) => self0 == other0, ( crate::GenericArgument::AssocType(self0), crate::GenericArgument::AssocType(other0), ) => self0 == other0, ( crate::GenericArgument::AssocConst(self0), crate::GenericArgument::AssocConst(other0), ) => self0 == other0, ( crate::GenericArgument::Constraint(self0), crate::GenericArgument::Constraint(other0), ) => self0 == other0, _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::GenericParam {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::GenericParam { fn eq(&self, other: &Self) -> bool { match (self, other) { ( crate::GenericParam::Lifetime(self0), crate::GenericParam::Lifetime(other0), ) => self0 == other0, (crate::GenericParam::Type(self0), crate::GenericParam::Type(other0)) => { self0 == other0 } (crate::GenericParam::Const(self0), crate::GenericParam::Const(other0)) => { self0 == other0 } _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Generics {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Generics { fn eq(&self, other: &Self) -> bool { self.lt_token == other.lt_token && self.params == other.params && self.gt_token == other.gt_token && self.where_clause == other.where_clause } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ImplItem {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ImplItem { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::ImplItem::Const(self0), crate::ImplItem::Const(other0)) => { self0 == other0 } (crate::ImplItem::Fn(self0), crate::ImplItem::Fn(other0)) => self0 == other0, (crate::ImplItem::Type(self0), crate::ImplItem::Type(other0)) => { self0 == other0 } (crate::ImplItem::Macro(self0), crate::ImplItem::Macro(other0)) => { self0 == other0 } (crate::ImplItem::Verbatim(self0), crate::ImplItem::Verbatim(other0)) => { TokenStreamHelper(self0) == TokenStreamHelper(other0) } _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ImplItemConst {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ImplItemConst { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.defaultness == other.defaultness && self.ident == other.ident && self.generics == other.generics && self.ty == other.ty && self.expr == other.expr } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ImplItemFn {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ImplItemFn { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.defaultness == other.defaultness && self.sig == other.sig && self.block == other.block } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ImplItemMacro {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ImplItemMacro { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.mac == other.mac && self.semi_token == other.semi_token } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ImplItemType {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ImplItemType { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.defaultness == other.defaultness && self.ident == other.ident && self.generics == other.generics && self.ty == other.ty } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ImplRestriction {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ImplRestriction { fn eq(&self, _other: &Self) -> bool { match *self {} } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Item {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Item { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Item::Const(self0), crate::Item::Const(other0)) => self0 == other0, (crate::Item::Enum(self0), crate::Item::Enum(other0)) => self0 == other0, (crate::Item::ExternCrate(self0), crate::Item::ExternCrate(other0)) => { self0 == other0 } (crate::Item::Fn(self0), crate::Item::Fn(other0)) => self0 == other0, (crate::Item::ForeignMod(self0), crate::Item::ForeignMod(other0)) => { self0 == other0 } (crate::Item::Impl(self0), crate::Item::Impl(other0)) => self0 == other0, (crate::Item::Macro(self0), crate::Item::Macro(other0)) => self0 == other0, (crate::Item::Mod(self0), crate::Item::Mod(other0)) => self0 == other0, (crate::Item::Static(self0), crate::Item::Static(other0)) => self0 == other0, (crate::Item::Struct(self0), crate::Item::Struct(other0)) => self0 == other0, (crate::Item::Trait(self0), crate::Item::Trait(other0)) => self0 == other0, (crate::Item::TraitAlias(self0), crate::Item::TraitAlias(other0)) => { self0 == other0 } (crate::Item::Type(self0), crate::Item::Type(other0)) => self0 == other0, (crate::Item::Union(self0), crate::Item::Union(other0)) => self0 == other0, (crate::Item::Use(self0), crate::Item::Use(other0)) => self0 == other0, (crate::Item::Verbatim(self0), crate::Item::Verbatim(other0)) => { TokenStreamHelper(self0) == TokenStreamHelper(other0) } _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemConst {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemConst { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics && self.ty == other.ty && self.expr == other.expr } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemEnum {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemEnum { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics && self.variants == other.variants } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemExternCrate {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemExternCrate { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.rename == other.rename } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemFn {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemFn { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.sig == other.sig && self.block == other.block } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemForeignMod {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemForeignMod { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.unsafety == other.unsafety && self.abi == other.abi && self.items == other.items } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemImpl {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemImpl { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.defaultness == other.defaultness && self.unsafety == other.unsafety && self.generics == other.generics && self.trait_ == other.trait_ && self.self_ty == other.self_ty && self.items == other.items } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemMacro {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemMacro { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.ident == other.ident && self.mac == other.mac && self.semi_token == other.semi_token } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemMod {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemMod { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.unsafety == other.unsafety && self.ident == other.ident && self.content == other.content && self.semi == other.semi } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemStatic {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemStatic { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.mutability == other.mutability && self.ident == other.ident && self.ty == other.ty && self.expr == other.expr } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemStruct {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemStruct { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics && self.fields == other.fields && self.semi_token == other.semi_token } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemTrait {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemTrait { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.unsafety == other.unsafety && self.auto_token == other.auto_token && self.restriction == other.restriction && self.ident == other.ident && self.generics == other.generics && self.colon_token == other.colon_token && self.supertraits == other.supertraits && self.items == other.items } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemTraitAlias {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemTraitAlias { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics && self.bounds == other.bounds } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemType {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemType { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics && self.ty == other.ty } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemUnion {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemUnion { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.ident == other.ident && self.generics == other.generics && self.fields == other.fields } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ItemUse {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ItemUse { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.vis == other.vis && self.leading_colon == other.leading_colon && self.tree == other.tree } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Label {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Label { fn eq(&self, other: &Self) -> bool { self.name == other.name } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LifetimeParam {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::LifetimeParam { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.lifetime == other.lifetime && self.colon_token == other.colon_token && self.bounds == other.bounds } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Lit {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Lit { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Lit::Str(self0), crate::Lit::Str(other0)) => self0 == other0, (crate::Lit::ByteStr(self0), crate::Lit::ByteStr(other0)) => self0 == other0, (crate::Lit::CStr(self0), crate::Lit::CStr(other0)) => self0 == other0, (crate::Lit::Byte(self0), crate::Lit::Byte(other0)) => self0 == other0, (crate::Lit::Char(self0), crate::Lit::Char(other0)) => self0 == other0, (crate::Lit::Int(self0), crate::Lit::Int(other0)) => self0 == other0, (crate::Lit::Float(self0), crate::Lit::Float(other0)) => self0 == other0, (crate::Lit::Bool(self0), crate::Lit::Bool(other0)) => self0 == other0, (crate::Lit::Verbatim(self0), crate::Lit::Verbatim(other0)) => { self0.to_string() == other0.to_string() } _ => false, } } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitBool {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::LitBool { fn eq(&self, other: &Self) -> bool { self.value == other.value } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitByte {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitByteStr {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitCStr {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitChar {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitFloat {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitInt {} #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LitStr {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Local {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Local { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.pat == other.pat && self.init == other.init } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::LocalInit {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::LocalInit { fn eq(&self, other: &Self) -> bool { self.expr == other.expr && self.diverge == other.diverge } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Macro {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Macro { fn eq(&self, other: &Self) -> bool { self.path == other.path && self.delimiter == other.delimiter && TokenStreamHelper(&self.tokens) == TokenStreamHelper(&other.tokens) } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::MacroDelimiter {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::MacroDelimiter { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::MacroDelimiter::Paren(_), crate::MacroDelimiter::Paren(_)) => true, (crate::MacroDelimiter::Brace(_), crate::MacroDelimiter::Brace(_)) => true, (crate::MacroDelimiter::Bracket(_), crate::MacroDelimiter::Bracket(_)) => { true } _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Meta {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Meta { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Meta::Path(self0), crate::Meta::Path(other0)) => self0 == other0, (crate::Meta::List(self0), crate::Meta::List(other0)) => self0 == other0, (crate::Meta::NameValue(self0), crate::Meta::NameValue(other0)) => { self0 == other0 } _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::MetaList {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::MetaList { fn eq(&self, other: &Self) -> bool { self.path == other.path && self.delimiter == other.delimiter && TokenStreamHelper(&self.tokens) == TokenStreamHelper(&other.tokens) } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::MetaNameValue {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::MetaNameValue { fn eq(&self, other: &Self) -> bool { self.path == other.path && self.value == other.value } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ParenthesizedGenericArguments {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ParenthesizedGenericArguments { fn eq(&self, other: &Self) -> bool { self.inputs == other.inputs && self.output == other.output } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Pat {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Pat { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Pat::Const(self0), crate::Pat::Const(other0)) => self0 == other0, (crate::Pat::Ident(self0), crate::Pat::Ident(other0)) => self0 == other0, (crate::Pat::Lit(self0), crate::Pat::Lit(other0)) => self0 == other0, (crate::Pat::Macro(self0), crate::Pat::Macro(other0)) => self0 == other0, (crate::Pat::Or(self0), crate::Pat::Or(other0)) => self0 == other0, (crate::Pat::Paren(self0), crate::Pat::Paren(other0)) => self0 == other0, (crate::Pat::Path(self0), crate::Pat::Path(other0)) => self0 == other0, (crate::Pat::Range(self0), crate::Pat::Range(other0)) => self0 == other0, (crate::Pat::Reference(self0), crate::Pat::Reference(other0)) => { self0 == other0 } (crate::Pat::Rest(self0), crate::Pat::Rest(other0)) => self0 == other0, (crate::Pat::Slice(self0), crate::Pat::Slice(other0)) => self0 == other0, (crate::Pat::Struct(self0), crate::Pat::Struct(other0)) => self0 == other0, (crate::Pat::Tuple(self0), crate::Pat::Tuple(other0)) => self0 == other0, (crate::Pat::TupleStruct(self0), crate::Pat::TupleStruct(other0)) => { self0 == other0 } (crate::Pat::Type(self0), crate::Pat::Type(other0)) => self0 == other0, (crate::Pat::Verbatim(self0), crate::Pat::Verbatim(other0)) => { TokenStreamHelper(self0) == TokenStreamHelper(other0) } (crate::Pat::Wild(self0), crate::Pat::Wild(other0)) => self0 == other0, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatIdent {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatIdent { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.by_ref == other.by_ref && self.mutability == other.mutability && self.ident == other.ident && self.subpat == other.subpat } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatOr {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatOr { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.leading_vert == other.leading_vert && self.cases == other.cases } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatParen {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatParen { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.pat == other.pat } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatReference {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatReference { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.mutability == other.mutability && self.pat == other.pat } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatRest {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatRest { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatSlice {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatSlice { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.elems == other.elems } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatStruct {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatStruct { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.qself == other.qself && self.path == other.path && self.fields == other.fields && self.rest == other.rest } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatTuple {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatTuple { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.elems == other.elems } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatTupleStruct {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatTupleStruct { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.qself == other.qself && self.path == other.path && self.elems == other.elems } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatType {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatType { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.pat == other.pat && self.ty == other.ty } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PatWild {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PatWild { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Path {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Path { fn eq(&self, other: &Self) -> bool { self.leading_colon == other.leading_colon && self.segments == other.segments } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PathArguments {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PathArguments { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::PathArguments::None, crate::PathArguments::None) => true, ( crate::PathArguments::AngleBracketed(self0), crate::PathArguments::AngleBracketed(other0), ) => self0 == other0, ( crate::PathArguments::Parenthesized(self0), crate::PathArguments::Parenthesized(other0), ) => self0 == other0, _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PathSegment {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PathSegment { fn eq(&self, other: &Self) -> bool { self.ident == other.ident && self.arguments == other.arguments } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PredicateLifetime {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PredicateLifetime { fn eq(&self, other: &Self) -> bool { self.lifetime == other.lifetime && self.bounds == other.bounds } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::PredicateType {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::PredicateType { fn eq(&self, other: &Self) -> bool { self.lifetimes == other.lifetimes && self.bounded_ty == other.bounded_ty && self.bounds == other.bounds } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::QSelf {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::QSelf { fn eq(&self, other: &Self) -> bool { self.ty == other.ty && self.position == other.position && self.as_token == other.as_token } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::RangeLimits {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::RangeLimits { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::RangeLimits::HalfOpen(_), crate::RangeLimits::HalfOpen(_)) => true, (crate::RangeLimits::Closed(_), crate::RangeLimits::Closed(_)) => true, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Receiver {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Receiver { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.reference == other.reference && self.mutability == other.mutability && self.colon_token == other.colon_token && self.ty == other.ty } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::ReturnType {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::ReturnType { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::ReturnType::Default, crate::ReturnType::Default) => true, (crate::ReturnType::Type(_, self1), crate::ReturnType::Type(_, other1)) => { self1 == other1 } _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Signature {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Signature { fn eq(&self, other: &Self) -> bool { self.constness == other.constness && self.asyncness == other.asyncness && self.unsafety == other.unsafety && self.abi == other.abi && self.ident == other.ident && self.generics == other.generics && self.inputs == other.inputs && self.variadic == other.variadic && self.output == other.output } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::StaticMutability {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::StaticMutability { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::StaticMutability::Mut(_), crate::StaticMutability::Mut(_)) => true, (crate::StaticMutability::None, crate::StaticMutability::None) => true, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Stmt {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Stmt { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Stmt::Local(self0), crate::Stmt::Local(other0)) => self0 == other0, (crate::Stmt::Item(self0), crate::Stmt::Item(other0)) => self0 == other0, (crate::Stmt::Expr(self0, self1), crate::Stmt::Expr(other0, other1)) => { self0 == other0 && self1 == other1 } (crate::Stmt::Macro(self0), crate::Stmt::Macro(other0)) => self0 == other0, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::StmtMacro {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::StmtMacro { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.mac == other.mac && self.semi_token == other.semi_token } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TraitBound {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TraitBound { fn eq(&self, other: &Self) -> bool { self.paren_token == other.paren_token && self.modifier == other.modifier && self.lifetimes == other.lifetimes && self.path == other.path } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TraitBoundModifier {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TraitBoundModifier { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::TraitBoundModifier::None, crate::TraitBoundModifier::None) => true, ( crate::TraitBoundModifier::Maybe(_), crate::TraitBoundModifier::Maybe(_), ) => true, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TraitItem {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TraitItem { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::TraitItem::Const(self0), crate::TraitItem::Const(other0)) => { self0 == other0 } (crate::TraitItem::Fn(self0), crate::TraitItem::Fn(other0)) => { self0 == other0 } (crate::TraitItem::Type(self0), crate::TraitItem::Type(other0)) => { self0 == other0 } (crate::TraitItem::Macro(self0), crate::TraitItem::Macro(other0)) => { self0 == other0 } (crate::TraitItem::Verbatim(self0), crate::TraitItem::Verbatim(other0)) => { TokenStreamHelper(self0) == TokenStreamHelper(other0) } _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TraitItemConst {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TraitItemConst { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.ident == other.ident && self.generics == other.generics && self.ty == other.ty && self.default == other.default } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TraitItemFn {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TraitItemFn { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.sig == other.sig && self.default == other.default && self.semi_token == other.semi_token } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TraitItemMacro {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TraitItemMacro { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.mac == other.mac && self.semi_token == other.semi_token } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TraitItemType {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TraitItemType { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.ident == other.ident && self.generics == other.generics && self.colon_token == other.colon_token && self.bounds == other.bounds && self.default == other.default } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Type {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Type { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Type::Array(self0), crate::Type::Array(other0)) => self0 == other0, (crate::Type::BareFn(self0), crate::Type::BareFn(other0)) => self0 == other0, (crate::Type::Group(self0), crate::Type::Group(other0)) => self0 == other0, (crate::Type::ImplTrait(self0), crate::Type::ImplTrait(other0)) => { self0 == other0 } (crate::Type::Infer(self0), crate::Type::Infer(other0)) => self0 == other0, (crate::Type::Macro(self0), crate::Type::Macro(other0)) => self0 == other0, (crate::Type::Never(self0), crate::Type::Never(other0)) => self0 == other0, (crate::Type::Paren(self0), crate::Type::Paren(other0)) => self0 == other0, (crate::Type::Path(self0), crate::Type::Path(other0)) => self0 == other0, (crate::Type::Ptr(self0), crate::Type::Ptr(other0)) => self0 == other0, (crate::Type::Reference(self0), crate::Type::Reference(other0)) => { self0 == other0 } (crate::Type::Slice(self0), crate::Type::Slice(other0)) => self0 == other0, (crate::Type::TraitObject(self0), crate::Type::TraitObject(other0)) => { self0 == other0 } (crate::Type::Tuple(self0), crate::Type::Tuple(other0)) => self0 == other0, (crate::Type::Verbatim(self0), crate::Type::Verbatim(other0)) => { TokenStreamHelper(self0) == TokenStreamHelper(other0) } _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeArray {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeArray { fn eq(&self, other: &Self) -> bool { self.elem == other.elem && self.len == other.len } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeBareFn {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeBareFn { fn eq(&self, other: &Self) -> bool { self.lifetimes == other.lifetimes && self.unsafety == other.unsafety && self.abi == other.abi && self.inputs == other.inputs && self.variadic == other.variadic && self.output == other.output } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeGroup {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeGroup { fn eq(&self, other: &Self) -> bool { self.elem == other.elem } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeImplTrait {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeImplTrait { fn eq(&self, other: &Self) -> bool { self.bounds == other.bounds } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeInfer {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeInfer { fn eq(&self, _other: &Self) -> bool { true } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeMacro {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeMacro { fn eq(&self, other: &Self) -> bool { self.mac == other.mac } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeNever {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeNever { fn eq(&self, _other: &Self) -> bool { true } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeParam {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeParam { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.ident == other.ident && self.colon_token == other.colon_token && self.bounds == other.bounds && self.eq_token == other.eq_token && self.default == other.default } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeParamBound {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeParamBound { fn eq(&self, other: &Self) -> bool { match (self, other) { ( crate::TypeParamBound::Trait(self0), crate::TypeParamBound::Trait(other0), ) => self0 == other0, ( crate::TypeParamBound::Lifetime(self0), crate::TypeParamBound::Lifetime(other0), ) => self0 == other0, ( crate::TypeParamBound::Verbatim(self0), crate::TypeParamBound::Verbatim(other0), ) => TokenStreamHelper(self0) == TokenStreamHelper(other0), _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeParen {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeParen { fn eq(&self, other: &Self) -> bool { self.elem == other.elem } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypePath {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypePath { fn eq(&self, other: &Self) -> bool { self.qself == other.qself && self.path == other.path } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypePtr {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypePtr { fn eq(&self, other: &Self) -> bool { self.const_token == other.const_token && self.mutability == other.mutability && self.elem == other.elem } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeReference {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeReference { fn eq(&self, other: &Self) -> bool { self.lifetime == other.lifetime && self.mutability == other.mutability && self.elem == other.elem } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeSlice {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeSlice { fn eq(&self, other: &Self) -> bool { self.elem == other.elem } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeTraitObject {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeTraitObject { fn eq(&self, other: &Self) -> bool { self.dyn_token == other.dyn_token && self.bounds == other.bounds } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::TypeTuple {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::TypeTuple { fn eq(&self, other: &Self) -> bool { self.elems == other.elems } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::UnOp {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::UnOp { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::UnOp::Deref(_), crate::UnOp::Deref(_)) => true, (crate::UnOp::Not(_), crate::UnOp::Not(_)) => true, (crate::UnOp::Neg(_), crate::UnOp::Neg(_)) => true, _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::UseGlob {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::UseGlob { fn eq(&self, _other: &Self) -> bool { true } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::UseGroup {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::UseGroup { fn eq(&self, other: &Self) -> bool { self.items == other.items } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::UseName {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::UseName { fn eq(&self, other: &Self) -> bool { self.ident == other.ident } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::UsePath {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::UsePath { fn eq(&self, other: &Self) -> bool { self.ident == other.ident && self.tree == other.tree } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::UseRename {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::UseRename { fn eq(&self, other: &Self) -> bool { self.ident == other.ident && self.rename == other.rename } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::UseTree {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::UseTree { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::UseTree::Path(self0), crate::UseTree::Path(other0)) => { self0 == other0 } (crate::UseTree::Name(self0), crate::UseTree::Name(other0)) => { self0 == other0 } (crate::UseTree::Rename(self0), crate::UseTree::Rename(other0)) => { self0 == other0 } (crate::UseTree::Glob(self0), crate::UseTree::Glob(other0)) => { self0 == other0 } (crate::UseTree::Group(self0), crate::UseTree::Group(other0)) => { self0 == other0 } _ => false, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Variadic {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Variadic { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.pat == other.pat && self.comma == other.comma } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Variant {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Variant { fn eq(&self, other: &Self) -> bool { self.attrs == other.attrs && self.ident == other.ident && self.fields == other.fields && self.discriminant == other.discriminant } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::VisRestricted {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::VisRestricted { fn eq(&self, other: &Self) -> bool { self.in_token == other.in_token && self.path == other.path } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::Visibility {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::Visibility { fn eq(&self, other: &Self) -> bool { match (self, other) { (crate::Visibility::Public(_), crate::Visibility::Public(_)) => true, ( crate::Visibility::Restricted(self0), crate::Visibility::Restricted(other0), ) => self0 == other0, (crate::Visibility::Inherited, crate::Visibility::Inherited) => true, _ => false, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::WhereClause {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::WhereClause { fn eq(&self, other: &Self) -> bool { self.predicates == other.predicates } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for crate::WherePredicate {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for crate::WherePredicate { fn eq(&self, other: &Self) -> bool { match (self, other) { ( crate::WherePredicate::Lifetime(self0), crate::WherePredicate::Lifetime(other0), ) => self0 == other0, (crate::WherePredicate::Type(self0), crate::WherePredicate::Type(other0)) => { self0 == other0 } _ => false, } } } syn/src/gen/clone.rs0000644000175000017500000022122014661133735015357 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #![allow(clippy::clone_on_copy, clippy::expl_impl_clone_on_copy)] #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Abi { fn clone(&self) -> Self { crate::Abi { extern_token: self.extern_token.clone(), name: self.name.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::AngleBracketedGenericArguments { fn clone(&self) -> Self { crate::AngleBracketedGenericArguments { colon2_token: self.colon2_token.clone(), lt_token: self.lt_token.clone(), args: self.args.clone(), gt_token: self.gt_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Arm { fn clone(&self) -> Self { crate::Arm { attrs: self.attrs.clone(), pat: self.pat.clone(), guard: self.guard.clone(), fat_arrow_token: self.fat_arrow_token.clone(), body: self.body.clone(), comma: self.comma.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::AssocConst { fn clone(&self) -> Self { crate::AssocConst { ident: self.ident.clone(), generics: self.generics.clone(), eq_token: self.eq_token.clone(), value: self.value.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::AssocType { fn clone(&self) -> Self { crate::AssocType { ident: self.ident.clone(), generics: self.generics.clone(), eq_token: self.eq_token.clone(), ty: self.ty.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for crate::AttrStyle {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::AttrStyle { fn clone(&self) -> Self { *self } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Attribute { fn clone(&self) -> Self { crate::Attribute { pound_token: self.pound_token.clone(), style: self.style.clone(), bracket_token: self.bracket_token.clone(), meta: self.meta.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::BareFnArg { fn clone(&self) -> Self { crate::BareFnArg { attrs: self.attrs.clone(), name: self.name.clone(), ty: self.ty.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::BareVariadic { fn clone(&self) -> Self { crate::BareVariadic { attrs: self.attrs.clone(), name: self.name.clone(), dots: self.dots.clone(), comma: self.comma.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for crate::BinOp {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::BinOp { fn clone(&self) -> Self { *self } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Block { fn clone(&self) -> Self { crate::Block { brace_token: self.brace_token.clone(), stmts: self.stmts.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::BoundLifetimes { fn clone(&self) -> Self { crate::BoundLifetimes { for_token: self.for_token.clone(), lt_token: self.lt_token.clone(), lifetimes: self.lifetimes.clone(), gt_token: self.gt_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ConstParam { fn clone(&self) -> Self { crate::ConstParam { attrs: self.attrs.clone(), const_token: self.const_token.clone(), ident: self.ident.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), eq_token: self.eq_token.clone(), default: self.default.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Constraint { fn clone(&self) -> Self { crate::Constraint { ident: self.ident.clone(), generics: self.generics.clone(), colon_token: self.colon_token.clone(), bounds: self.bounds.clone(), } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Data { fn clone(&self) -> Self { match self { crate::Data::Struct(v0) => crate::Data::Struct(v0.clone()), crate::Data::Enum(v0) => crate::Data::Enum(v0.clone()), crate::Data::Union(v0) => crate::Data::Union(v0.clone()), } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::DataEnum { fn clone(&self) -> Self { crate::DataEnum { enum_token: self.enum_token.clone(), brace_token: self.brace_token.clone(), variants: self.variants.clone(), } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::DataStruct { fn clone(&self) -> Self { crate::DataStruct { struct_token: self.struct_token.clone(), fields: self.fields.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::DataUnion { fn clone(&self) -> Self { crate::DataUnion { union_token: self.union_token.clone(), fields: self.fields.clone(), } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::DeriveInput { fn clone(&self) -> Self { crate::DeriveInput { attrs: self.attrs.clone(), vis: self.vis.clone(), ident: self.ident.clone(), generics: self.generics.clone(), data: self.data.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Expr { fn clone(&self) -> Self { match self { #[cfg(feature = "full")] crate::Expr::Array(v0) => crate::Expr::Array(v0.clone()), #[cfg(feature = "full")] crate::Expr::Assign(v0) => crate::Expr::Assign(v0.clone()), #[cfg(feature = "full")] crate::Expr::Async(v0) => crate::Expr::Async(v0.clone()), #[cfg(feature = "full")] crate::Expr::Await(v0) => crate::Expr::Await(v0.clone()), crate::Expr::Binary(v0) => crate::Expr::Binary(v0.clone()), #[cfg(feature = "full")] crate::Expr::Block(v0) => crate::Expr::Block(v0.clone()), #[cfg(feature = "full")] crate::Expr::Break(v0) => crate::Expr::Break(v0.clone()), crate::Expr::Call(v0) => crate::Expr::Call(v0.clone()), crate::Expr::Cast(v0) => crate::Expr::Cast(v0.clone()), #[cfg(feature = "full")] crate::Expr::Closure(v0) => crate::Expr::Closure(v0.clone()), #[cfg(feature = "full")] crate::Expr::Const(v0) => crate::Expr::Const(v0.clone()), #[cfg(feature = "full")] crate::Expr::Continue(v0) => crate::Expr::Continue(v0.clone()), crate::Expr::Field(v0) => crate::Expr::Field(v0.clone()), #[cfg(feature = "full")] crate::Expr::ForLoop(v0) => crate::Expr::ForLoop(v0.clone()), crate::Expr::Group(v0) => crate::Expr::Group(v0.clone()), #[cfg(feature = "full")] crate::Expr::If(v0) => crate::Expr::If(v0.clone()), crate::Expr::Index(v0) => crate::Expr::Index(v0.clone()), #[cfg(feature = "full")] crate::Expr::Infer(v0) => crate::Expr::Infer(v0.clone()), #[cfg(feature = "full")] crate::Expr::Let(v0) => crate::Expr::Let(v0.clone()), crate::Expr::Lit(v0) => crate::Expr::Lit(v0.clone()), #[cfg(feature = "full")] crate::Expr::Loop(v0) => crate::Expr::Loop(v0.clone()), crate::Expr::Macro(v0) => crate::Expr::Macro(v0.clone()), #[cfg(feature = "full")] crate::Expr::Match(v0) => crate::Expr::Match(v0.clone()), crate::Expr::MethodCall(v0) => crate::Expr::MethodCall(v0.clone()), crate::Expr::Paren(v0) => crate::Expr::Paren(v0.clone()), crate::Expr::Path(v0) => crate::Expr::Path(v0.clone()), #[cfg(feature = "full")] crate::Expr::Range(v0) => crate::Expr::Range(v0.clone()), crate::Expr::Reference(v0) => crate::Expr::Reference(v0.clone()), #[cfg(feature = "full")] crate::Expr::Repeat(v0) => crate::Expr::Repeat(v0.clone()), #[cfg(feature = "full")] crate::Expr::Return(v0) => crate::Expr::Return(v0.clone()), crate::Expr::Struct(v0) => crate::Expr::Struct(v0.clone()), #[cfg(feature = "full")] crate::Expr::Try(v0) => crate::Expr::Try(v0.clone()), #[cfg(feature = "full")] crate::Expr::TryBlock(v0) => crate::Expr::TryBlock(v0.clone()), #[cfg(feature = "full")] crate::Expr::Tuple(v0) => crate::Expr::Tuple(v0.clone()), crate::Expr::Unary(v0) => crate::Expr::Unary(v0.clone()), #[cfg(feature = "full")] crate::Expr::Unsafe(v0) => crate::Expr::Unsafe(v0.clone()), crate::Expr::Verbatim(v0) => crate::Expr::Verbatim(v0.clone()), #[cfg(feature = "full")] crate::Expr::While(v0) => crate::Expr::While(v0.clone()), #[cfg(feature = "full")] crate::Expr::Yield(v0) => crate::Expr::Yield(v0.clone()), #[cfg(not(feature = "full"))] _ => unreachable!(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprArray { fn clone(&self) -> Self { crate::ExprArray { attrs: self.attrs.clone(), bracket_token: self.bracket_token.clone(), elems: self.elems.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprAssign { fn clone(&self) -> Self { crate::ExprAssign { attrs: self.attrs.clone(), left: self.left.clone(), eq_token: self.eq_token.clone(), right: self.right.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprAsync { fn clone(&self) -> Self { crate::ExprAsync { attrs: self.attrs.clone(), async_token: self.async_token.clone(), capture: self.capture.clone(), block: self.block.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprAwait { fn clone(&self) -> Self { crate::ExprAwait { attrs: self.attrs.clone(), base: self.base.clone(), dot_token: self.dot_token.clone(), await_token: self.await_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprBinary { fn clone(&self) -> Self { crate::ExprBinary { attrs: self.attrs.clone(), left: self.left.clone(), op: self.op.clone(), right: self.right.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprBlock { fn clone(&self) -> Self { crate::ExprBlock { attrs: self.attrs.clone(), label: self.label.clone(), block: self.block.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprBreak { fn clone(&self) -> Self { crate::ExprBreak { attrs: self.attrs.clone(), break_token: self.break_token.clone(), label: self.label.clone(), expr: self.expr.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprCall { fn clone(&self) -> Self { crate::ExprCall { attrs: self.attrs.clone(), func: self.func.clone(), paren_token: self.paren_token.clone(), args: self.args.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprCast { fn clone(&self) -> Self { crate::ExprCast { attrs: self.attrs.clone(), expr: self.expr.clone(), as_token: self.as_token.clone(), ty: self.ty.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprClosure { fn clone(&self) -> Self { crate::ExprClosure { attrs: self.attrs.clone(), lifetimes: self.lifetimes.clone(), constness: self.constness.clone(), movability: self.movability.clone(), asyncness: self.asyncness.clone(), capture: self.capture.clone(), or1_token: self.or1_token.clone(), inputs: self.inputs.clone(), or2_token: self.or2_token.clone(), output: self.output.clone(), body: self.body.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprConst { fn clone(&self) -> Self { crate::ExprConst { attrs: self.attrs.clone(), const_token: self.const_token.clone(), block: self.block.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprContinue { fn clone(&self) -> Self { crate::ExprContinue { attrs: self.attrs.clone(), continue_token: self.continue_token.clone(), label: self.label.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprField { fn clone(&self) -> Self { crate::ExprField { attrs: self.attrs.clone(), base: self.base.clone(), dot_token: self.dot_token.clone(), member: self.member.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprForLoop { fn clone(&self) -> Self { crate::ExprForLoop { attrs: self.attrs.clone(), label: self.label.clone(), for_token: self.for_token.clone(), pat: self.pat.clone(), in_token: self.in_token.clone(), expr: self.expr.clone(), body: self.body.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprGroup { fn clone(&self) -> Self { crate::ExprGroup { attrs: self.attrs.clone(), group_token: self.group_token.clone(), expr: self.expr.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprIf { fn clone(&self) -> Self { crate::ExprIf { attrs: self.attrs.clone(), if_token: self.if_token.clone(), cond: self.cond.clone(), then_branch: self.then_branch.clone(), else_branch: self.else_branch.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprIndex { fn clone(&self) -> Self { crate::ExprIndex { attrs: self.attrs.clone(), expr: self.expr.clone(), bracket_token: self.bracket_token.clone(), index: self.index.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprInfer { fn clone(&self) -> Self { crate::ExprInfer { attrs: self.attrs.clone(), underscore_token: self.underscore_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprLet { fn clone(&self) -> Self { crate::ExprLet { attrs: self.attrs.clone(), let_token: self.let_token.clone(), pat: self.pat.clone(), eq_token: self.eq_token.clone(), expr: self.expr.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprLit { fn clone(&self) -> Self { crate::ExprLit { attrs: self.attrs.clone(), lit: self.lit.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprLoop { fn clone(&self) -> Self { crate::ExprLoop { attrs: self.attrs.clone(), label: self.label.clone(), loop_token: self.loop_token.clone(), body: self.body.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprMacro { fn clone(&self) -> Self { crate::ExprMacro { attrs: self.attrs.clone(), mac: self.mac.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprMatch { fn clone(&self) -> Self { crate::ExprMatch { attrs: self.attrs.clone(), match_token: self.match_token.clone(), expr: self.expr.clone(), brace_token: self.brace_token.clone(), arms: self.arms.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprMethodCall { fn clone(&self) -> Self { crate::ExprMethodCall { attrs: self.attrs.clone(), receiver: self.receiver.clone(), dot_token: self.dot_token.clone(), method: self.method.clone(), turbofish: self.turbofish.clone(), paren_token: self.paren_token.clone(), args: self.args.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprParen { fn clone(&self) -> Self { crate::ExprParen { attrs: self.attrs.clone(), paren_token: self.paren_token.clone(), expr: self.expr.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprPath { fn clone(&self) -> Self { crate::ExprPath { attrs: self.attrs.clone(), qself: self.qself.clone(), path: self.path.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprRange { fn clone(&self) -> Self { crate::ExprRange { attrs: self.attrs.clone(), start: self.start.clone(), limits: self.limits.clone(), end: self.end.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprReference { fn clone(&self) -> Self { crate::ExprReference { attrs: self.attrs.clone(), and_token: self.and_token.clone(), mutability: self.mutability.clone(), expr: self.expr.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprRepeat { fn clone(&self) -> Self { crate::ExprRepeat { attrs: self.attrs.clone(), bracket_token: self.bracket_token.clone(), expr: self.expr.clone(), semi_token: self.semi_token.clone(), len: self.len.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprReturn { fn clone(&self) -> Self { crate::ExprReturn { attrs: self.attrs.clone(), return_token: self.return_token.clone(), expr: self.expr.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprStruct { fn clone(&self) -> Self { crate::ExprStruct { attrs: self.attrs.clone(), qself: self.qself.clone(), path: self.path.clone(), brace_token: self.brace_token.clone(), fields: self.fields.clone(), dot2_token: self.dot2_token.clone(), rest: self.rest.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprTry { fn clone(&self) -> Self { crate::ExprTry { attrs: self.attrs.clone(), expr: self.expr.clone(), question_token: self.question_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprTryBlock { fn clone(&self) -> Self { crate::ExprTryBlock { attrs: self.attrs.clone(), try_token: self.try_token.clone(), block: self.block.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprTuple { fn clone(&self) -> Self { crate::ExprTuple { attrs: self.attrs.clone(), paren_token: self.paren_token.clone(), elems: self.elems.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprUnary { fn clone(&self) -> Self { crate::ExprUnary { attrs: self.attrs.clone(), op: self.op.clone(), expr: self.expr.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprUnsafe { fn clone(&self) -> Self { crate::ExprUnsafe { attrs: self.attrs.clone(), unsafe_token: self.unsafe_token.clone(), block: self.block.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprWhile { fn clone(&self) -> Self { crate::ExprWhile { attrs: self.attrs.clone(), label: self.label.clone(), while_token: self.while_token.clone(), cond: self.cond.clone(), body: self.body.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ExprYield { fn clone(&self) -> Self { crate::ExprYield { attrs: self.attrs.clone(), yield_token: self.yield_token.clone(), expr: self.expr.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Field { fn clone(&self) -> Self { crate::Field { attrs: self.attrs.clone(), vis: self.vis.clone(), mutability: self.mutability.clone(), ident: self.ident.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FieldMutability { fn clone(&self) -> Self { match self { crate::FieldMutability::None => crate::FieldMutability::None, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FieldPat { fn clone(&self) -> Self { crate::FieldPat { attrs: self.attrs.clone(), member: self.member.clone(), colon_token: self.colon_token.clone(), pat: self.pat.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FieldValue { fn clone(&self) -> Self { crate::FieldValue { attrs: self.attrs.clone(), member: self.member.clone(), colon_token: self.colon_token.clone(), expr: self.expr.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Fields { fn clone(&self) -> Self { match self { crate::Fields::Named(v0) => crate::Fields::Named(v0.clone()), crate::Fields::Unnamed(v0) => crate::Fields::Unnamed(v0.clone()), crate::Fields::Unit => crate::Fields::Unit, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FieldsNamed { fn clone(&self) -> Self { crate::FieldsNamed { brace_token: self.brace_token.clone(), named: self.named.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FieldsUnnamed { fn clone(&self) -> Self { crate::FieldsUnnamed { paren_token: self.paren_token.clone(), unnamed: self.unnamed.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::File { fn clone(&self) -> Self { crate::File { shebang: self.shebang.clone(), attrs: self.attrs.clone(), items: self.items.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::FnArg { fn clone(&self) -> Self { match self { crate::FnArg::Receiver(v0) => crate::FnArg::Receiver(v0.clone()), crate::FnArg::Typed(v0) => crate::FnArg::Typed(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ForeignItem { fn clone(&self) -> Self { match self { crate::ForeignItem::Fn(v0) => crate::ForeignItem::Fn(v0.clone()), crate::ForeignItem::Static(v0) => crate::ForeignItem::Static(v0.clone()), crate::ForeignItem::Type(v0) => crate::ForeignItem::Type(v0.clone()), crate::ForeignItem::Macro(v0) => crate::ForeignItem::Macro(v0.clone()), crate::ForeignItem::Verbatim(v0) => crate::ForeignItem::Verbatim(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ForeignItemFn { fn clone(&self) -> Self { crate::ForeignItemFn { attrs: self.attrs.clone(), vis: self.vis.clone(), sig: self.sig.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ForeignItemMacro { fn clone(&self) -> Self { crate::ForeignItemMacro { attrs: self.attrs.clone(), mac: self.mac.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ForeignItemStatic { fn clone(&self) -> Self { crate::ForeignItemStatic { attrs: self.attrs.clone(), vis: self.vis.clone(), static_token: self.static_token.clone(), mutability: self.mutability.clone(), ident: self.ident.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ForeignItemType { fn clone(&self) -> Self { crate::ForeignItemType { attrs: self.attrs.clone(), vis: self.vis.clone(), type_token: self.type_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::GenericArgument { fn clone(&self) -> Self { match self { crate::GenericArgument::Lifetime(v0) => { crate::GenericArgument::Lifetime(v0.clone()) } crate::GenericArgument::Type(v0) => crate::GenericArgument::Type(v0.clone()), crate::GenericArgument::Const(v0) => { crate::GenericArgument::Const(v0.clone()) } crate::GenericArgument::AssocType(v0) => { crate::GenericArgument::AssocType(v0.clone()) } crate::GenericArgument::AssocConst(v0) => { crate::GenericArgument::AssocConst(v0.clone()) } crate::GenericArgument::Constraint(v0) => { crate::GenericArgument::Constraint(v0.clone()) } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::GenericParam { fn clone(&self) -> Self { match self { crate::GenericParam::Lifetime(v0) => { crate::GenericParam::Lifetime(v0.clone()) } crate::GenericParam::Type(v0) => crate::GenericParam::Type(v0.clone()), crate::GenericParam::Const(v0) => crate::GenericParam::Const(v0.clone()), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Generics { fn clone(&self) -> Self { crate::Generics { lt_token: self.lt_token.clone(), params: self.params.clone(), gt_token: self.gt_token.clone(), where_clause: self.where_clause.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ImplItem { fn clone(&self) -> Self { match self { crate::ImplItem::Const(v0) => crate::ImplItem::Const(v0.clone()), crate::ImplItem::Fn(v0) => crate::ImplItem::Fn(v0.clone()), crate::ImplItem::Type(v0) => crate::ImplItem::Type(v0.clone()), crate::ImplItem::Macro(v0) => crate::ImplItem::Macro(v0.clone()), crate::ImplItem::Verbatim(v0) => crate::ImplItem::Verbatim(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ImplItemConst { fn clone(&self) -> Self { crate::ImplItemConst { attrs: self.attrs.clone(), vis: self.vis.clone(), defaultness: self.defaultness.clone(), const_token: self.const_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), eq_token: self.eq_token.clone(), expr: self.expr.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ImplItemFn { fn clone(&self) -> Self { crate::ImplItemFn { attrs: self.attrs.clone(), vis: self.vis.clone(), defaultness: self.defaultness.clone(), sig: self.sig.clone(), block: self.block.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ImplItemMacro { fn clone(&self) -> Self { crate::ImplItemMacro { attrs: self.attrs.clone(), mac: self.mac.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ImplItemType { fn clone(&self) -> Self { crate::ImplItemType { attrs: self.attrs.clone(), vis: self.vis.clone(), defaultness: self.defaultness.clone(), type_token: self.type_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), eq_token: self.eq_token.clone(), ty: self.ty.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ImplRestriction { fn clone(&self) -> Self { match *self {} } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Index { fn clone(&self) -> Self { crate::Index { index: self.index.clone(), span: self.span.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Item { fn clone(&self) -> Self { match self { crate::Item::Const(v0) => crate::Item::Const(v0.clone()), crate::Item::Enum(v0) => crate::Item::Enum(v0.clone()), crate::Item::ExternCrate(v0) => crate::Item::ExternCrate(v0.clone()), crate::Item::Fn(v0) => crate::Item::Fn(v0.clone()), crate::Item::ForeignMod(v0) => crate::Item::ForeignMod(v0.clone()), crate::Item::Impl(v0) => crate::Item::Impl(v0.clone()), crate::Item::Macro(v0) => crate::Item::Macro(v0.clone()), crate::Item::Mod(v0) => crate::Item::Mod(v0.clone()), crate::Item::Static(v0) => crate::Item::Static(v0.clone()), crate::Item::Struct(v0) => crate::Item::Struct(v0.clone()), crate::Item::Trait(v0) => crate::Item::Trait(v0.clone()), crate::Item::TraitAlias(v0) => crate::Item::TraitAlias(v0.clone()), crate::Item::Type(v0) => crate::Item::Type(v0.clone()), crate::Item::Union(v0) => crate::Item::Union(v0.clone()), crate::Item::Use(v0) => crate::Item::Use(v0.clone()), crate::Item::Verbatim(v0) => crate::Item::Verbatim(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemConst { fn clone(&self) -> Self { crate::ItemConst { attrs: self.attrs.clone(), vis: self.vis.clone(), const_token: self.const_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), eq_token: self.eq_token.clone(), expr: self.expr.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemEnum { fn clone(&self) -> Self { crate::ItemEnum { attrs: self.attrs.clone(), vis: self.vis.clone(), enum_token: self.enum_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), brace_token: self.brace_token.clone(), variants: self.variants.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemExternCrate { fn clone(&self) -> Self { crate::ItemExternCrate { attrs: self.attrs.clone(), vis: self.vis.clone(), extern_token: self.extern_token.clone(), crate_token: self.crate_token.clone(), ident: self.ident.clone(), rename: self.rename.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemFn { fn clone(&self) -> Self { crate::ItemFn { attrs: self.attrs.clone(), vis: self.vis.clone(), sig: self.sig.clone(), block: self.block.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemForeignMod { fn clone(&self) -> Self { crate::ItemForeignMod { attrs: self.attrs.clone(), unsafety: self.unsafety.clone(), abi: self.abi.clone(), brace_token: self.brace_token.clone(), items: self.items.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemImpl { fn clone(&self) -> Self { crate::ItemImpl { attrs: self.attrs.clone(), defaultness: self.defaultness.clone(), unsafety: self.unsafety.clone(), impl_token: self.impl_token.clone(), generics: self.generics.clone(), trait_: self.trait_.clone(), self_ty: self.self_ty.clone(), brace_token: self.brace_token.clone(), items: self.items.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemMacro { fn clone(&self) -> Self { crate::ItemMacro { attrs: self.attrs.clone(), ident: self.ident.clone(), mac: self.mac.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemMod { fn clone(&self) -> Self { crate::ItemMod { attrs: self.attrs.clone(), vis: self.vis.clone(), unsafety: self.unsafety.clone(), mod_token: self.mod_token.clone(), ident: self.ident.clone(), content: self.content.clone(), semi: self.semi.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemStatic { fn clone(&self) -> Self { crate::ItemStatic { attrs: self.attrs.clone(), vis: self.vis.clone(), static_token: self.static_token.clone(), mutability: self.mutability.clone(), ident: self.ident.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), eq_token: self.eq_token.clone(), expr: self.expr.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemStruct { fn clone(&self) -> Self { crate::ItemStruct { attrs: self.attrs.clone(), vis: self.vis.clone(), struct_token: self.struct_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), fields: self.fields.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemTrait { fn clone(&self) -> Self { crate::ItemTrait { attrs: self.attrs.clone(), vis: self.vis.clone(), unsafety: self.unsafety.clone(), auto_token: self.auto_token.clone(), restriction: self.restriction.clone(), trait_token: self.trait_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), colon_token: self.colon_token.clone(), supertraits: self.supertraits.clone(), brace_token: self.brace_token.clone(), items: self.items.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemTraitAlias { fn clone(&self) -> Self { crate::ItemTraitAlias { attrs: self.attrs.clone(), vis: self.vis.clone(), trait_token: self.trait_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), eq_token: self.eq_token.clone(), bounds: self.bounds.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemType { fn clone(&self) -> Self { crate::ItemType { attrs: self.attrs.clone(), vis: self.vis.clone(), type_token: self.type_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), eq_token: self.eq_token.clone(), ty: self.ty.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemUnion { fn clone(&self) -> Self { crate::ItemUnion { attrs: self.attrs.clone(), vis: self.vis.clone(), union_token: self.union_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), fields: self.fields.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ItemUse { fn clone(&self) -> Self { crate::ItemUse { attrs: self.attrs.clone(), vis: self.vis.clone(), use_token: self.use_token.clone(), leading_colon: self.leading_colon.clone(), tree: self.tree.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Label { fn clone(&self) -> Self { crate::Label { name: self.name.clone(), colon_token: self.colon_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::LifetimeParam { fn clone(&self) -> Self { crate::LifetimeParam { attrs: self.attrs.clone(), lifetime: self.lifetime.clone(), colon_token: self.colon_token.clone(), bounds: self.bounds.clone(), } } } #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Lit { fn clone(&self) -> Self { match self { crate::Lit::Str(v0) => crate::Lit::Str(v0.clone()), crate::Lit::ByteStr(v0) => crate::Lit::ByteStr(v0.clone()), crate::Lit::CStr(v0) => crate::Lit::CStr(v0.clone()), crate::Lit::Byte(v0) => crate::Lit::Byte(v0.clone()), crate::Lit::Char(v0) => crate::Lit::Char(v0.clone()), crate::Lit::Int(v0) => crate::Lit::Int(v0.clone()), crate::Lit::Float(v0) => crate::Lit::Float(v0.clone()), crate::Lit::Bool(v0) => crate::Lit::Bool(v0.clone()), crate::Lit::Verbatim(v0) => crate::Lit::Verbatim(v0.clone()), } } } #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::LitBool { fn clone(&self) -> Self { crate::LitBool { value: self.value.clone(), span: self.span.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Local { fn clone(&self) -> Self { crate::Local { attrs: self.attrs.clone(), let_token: self.let_token.clone(), pat: self.pat.clone(), init: self.init.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::LocalInit { fn clone(&self) -> Self { crate::LocalInit { eq_token: self.eq_token.clone(), expr: self.expr.clone(), diverge: self.diverge.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Macro { fn clone(&self) -> Self { crate::Macro { path: self.path.clone(), bang_token: self.bang_token.clone(), delimiter: self.delimiter.clone(), tokens: self.tokens.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::MacroDelimiter { fn clone(&self) -> Self { match self { crate::MacroDelimiter::Paren(v0) => crate::MacroDelimiter::Paren(v0.clone()), crate::MacroDelimiter::Brace(v0) => crate::MacroDelimiter::Brace(v0.clone()), crate::MacroDelimiter::Bracket(v0) => { crate::MacroDelimiter::Bracket(v0.clone()) } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Member { fn clone(&self) -> Self { match self { crate::Member::Named(v0) => crate::Member::Named(v0.clone()), crate::Member::Unnamed(v0) => crate::Member::Unnamed(v0.clone()), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Meta { fn clone(&self) -> Self { match self { crate::Meta::Path(v0) => crate::Meta::Path(v0.clone()), crate::Meta::List(v0) => crate::Meta::List(v0.clone()), crate::Meta::NameValue(v0) => crate::Meta::NameValue(v0.clone()), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::MetaList { fn clone(&self) -> Self { crate::MetaList { path: self.path.clone(), delimiter: self.delimiter.clone(), tokens: self.tokens.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::MetaNameValue { fn clone(&self) -> Self { crate::MetaNameValue { path: self.path.clone(), eq_token: self.eq_token.clone(), value: self.value.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ParenthesizedGenericArguments { fn clone(&self) -> Self { crate::ParenthesizedGenericArguments { paren_token: self.paren_token.clone(), inputs: self.inputs.clone(), output: self.output.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Pat { fn clone(&self) -> Self { match self { crate::Pat::Const(v0) => crate::Pat::Const(v0.clone()), crate::Pat::Ident(v0) => crate::Pat::Ident(v0.clone()), crate::Pat::Lit(v0) => crate::Pat::Lit(v0.clone()), crate::Pat::Macro(v0) => crate::Pat::Macro(v0.clone()), crate::Pat::Or(v0) => crate::Pat::Or(v0.clone()), crate::Pat::Paren(v0) => crate::Pat::Paren(v0.clone()), crate::Pat::Path(v0) => crate::Pat::Path(v0.clone()), crate::Pat::Range(v0) => crate::Pat::Range(v0.clone()), crate::Pat::Reference(v0) => crate::Pat::Reference(v0.clone()), crate::Pat::Rest(v0) => crate::Pat::Rest(v0.clone()), crate::Pat::Slice(v0) => crate::Pat::Slice(v0.clone()), crate::Pat::Struct(v0) => crate::Pat::Struct(v0.clone()), crate::Pat::Tuple(v0) => crate::Pat::Tuple(v0.clone()), crate::Pat::TupleStruct(v0) => crate::Pat::TupleStruct(v0.clone()), crate::Pat::Type(v0) => crate::Pat::Type(v0.clone()), crate::Pat::Verbatim(v0) => crate::Pat::Verbatim(v0.clone()), crate::Pat::Wild(v0) => crate::Pat::Wild(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatIdent { fn clone(&self) -> Self { crate::PatIdent { attrs: self.attrs.clone(), by_ref: self.by_ref.clone(), mutability: self.mutability.clone(), ident: self.ident.clone(), subpat: self.subpat.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatOr { fn clone(&self) -> Self { crate::PatOr { attrs: self.attrs.clone(), leading_vert: self.leading_vert.clone(), cases: self.cases.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatParen { fn clone(&self) -> Self { crate::PatParen { attrs: self.attrs.clone(), paren_token: self.paren_token.clone(), pat: self.pat.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatReference { fn clone(&self) -> Self { crate::PatReference { attrs: self.attrs.clone(), and_token: self.and_token.clone(), mutability: self.mutability.clone(), pat: self.pat.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatRest { fn clone(&self) -> Self { crate::PatRest { attrs: self.attrs.clone(), dot2_token: self.dot2_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatSlice { fn clone(&self) -> Self { crate::PatSlice { attrs: self.attrs.clone(), bracket_token: self.bracket_token.clone(), elems: self.elems.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatStruct { fn clone(&self) -> Self { crate::PatStruct { attrs: self.attrs.clone(), qself: self.qself.clone(), path: self.path.clone(), brace_token: self.brace_token.clone(), fields: self.fields.clone(), rest: self.rest.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatTuple { fn clone(&self) -> Self { crate::PatTuple { attrs: self.attrs.clone(), paren_token: self.paren_token.clone(), elems: self.elems.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatTupleStruct { fn clone(&self) -> Self { crate::PatTupleStruct { attrs: self.attrs.clone(), qself: self.qself.clone(), path: self.path.clone(), paren_token: self.paren_token.clone(), elems: self.elems.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatType { fn clone(&self) -> Self { crate::PatType { attrs: self.attrs.clone(), pat: self.pat.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PatWild { fn clone(&self) -> Self { crate::PatWild { attrs: self.attrs.clone(), underscore_token: self.underscore_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Path { fn clone(&self) -> Self { crate::Path { leading_colon: self.leading_colon.clone(), segments: self.segments.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PathArguments { fn clone(&self) -> Self { match self { crate::PathArguments::None => crate::PathArguments::None, crate::PathArguments::AngleBracketed(v0) => { crate::PathArguments::AngleBracketed(v0.clone()) } crate::PathArguments::Parenthesized(v0) => { crate::PathArguments::Parenthesized(v0.clone()) } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PathSegment { fn clone(&self) -> Self { crate::PathSegment { ident: self.ident.clone(), arguments: self.arguments.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PredicateLifetime { fn clone(&self) -> Self { crate::PredicateLifetime { lifetime: self.lifetime.clone(), colon_token: self.colon_token.clone(), bounds: self.bounds.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::PredicateType { fn clone(&self) -> Self { crate::PredicateType { lifetimes: self.lifetimes.clone(), bounded_ty: self.bounded_ty.clone(), colon_token: self.colon_token.clone(), bounds: self.bounds.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::QSelf { fn clone(&self) -> Self { crate::QSelf { lt_token: self.lt_token.clone(), ty: self.ty.clone(), position: self.position.clone(), as_token: self.as_token.clone(), gt_token: self.gt_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for crate::RangeLimits {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::RangeLimits { fn clone(&self) -> Self { *self } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Receiver { fn clone(&self) -> Self { crate::Receiver { attrs: self.attrs.clone(), reference: self.reference.clone(), mutability: self.mutability.clone(), self_token: self.self_token.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::ReturnType { fn clone(&self) -> Self { match self { crate::ReturnType::Default => crate::ReturnType::Default, crate::ReturnType::Type(v0, v1) => { crate::ReturnType::Type(v0.clone(), v1.clone()) } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Signature { fn clone(&self) -> Self { crate::Signature { constness: self.constness.clone(), asyncness: self.asyncness.clone(), unsafety: self.unsafety.clone(), abi: self.abi.clone(), fn_token: self.fn_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), paren_token: self.paren_token.clone(), inputs: self.inputs.clone(), variadic: self.variadic.clone(), output: self.output.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::StaticMutability { fn clone(&self) -> Self { match self { crate::StaticMutability::Mut(v0) => crate::StaticMutability::Mut(v0.clone()), crate::StaticMutability::None => crate::StaticMutability::None, } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Stmt { fn clone(&self) -> Self { match self { crate::Stmt::Local(v0) => crate::Stmt::Local(v0.clone()), crate::Stmt::Item(v0) => crate::Stmt::Item(v0.clone()), crate::Stmt::Expr(v0, v1) => crate::Stmt::Expr(v0.clone(), v1.clone()), crate::Stmt::Macro(v0) => crate::Stmt::Macro(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::StmtMacro { fn clone(&self) -> Self { crate::StmtMacro { attrs: self.attrs.clone(), mac: self.mac.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TraitBound { fn clone(&self) -> Self { crate::TraitBound { paren_token: self.paren_token.clone(), modifier: self.modifier.clone(), lifetimes: self.lifetimes.clone(), path: self.path.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for crate::TraitBoundModifier {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TraitBoundModifier { fn clone(&self) -> Self { *self } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TraitItem { fn clone(&self) -> Self { match self { crate::TraitItem::Const(v0) => crate::TraitItem::Const(v0.clone()), crate::TraitItem::Fn(v0) => crate::TraitItem::Fn(v0.clone()), crate::TraitItem::Type(v0) => crate::TraitItem::Type(v0.clone()), crate::TraitItem::Macro(v0) => crate::TraitItem::Macro(v0.clone()), crate::TraitItem::Verbatim(v0) => crate::TraitItem::Verbatim(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TraitItemConst { fn clone(&self) -> Self { crate::TraitItemConst { attrs: self.attrs.clone(), const_token: self.const_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), colon_token: self.colon_token.clone(), ty: self.ty.clone(), default: self.default.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TraitItemFn { fn clone(&self) -> Self { crate::TraitItemFn { attrs: self.attrs.clone(), sig: self.sig.clone(), default: self.default.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TraitItemMacro { fn clone(&self) -> Self { crate::TraitItemMacro { attrs: self.attrs.clone(), mac: self.mac.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TraitItemType { fn clone(&self) -> Self { crate::TraitItemType { attrs: self.attrs.clone(), type_token: self.type_token.clone(), ident: self.ident.clone(), generics: self.generics.clone(), colon_token: self.colon_token.clone(), bounds: self.bounds.clone(), default: self.default.clone(), semi_token: self.semi_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Type { fn clone(&self) -> Self { match self { crate::Type::Array(v0) => crate::Type::Array(v0.clone()), crate::Type::BareFn(v0) => crate::Type::BareFn(v0.clone()), crate::Type::Group(v0) => crate::Type::Group(v0.clone()), crate::Type::ImplTrait(v0) => crate::Type::ImplTrait(v0.clone()), crate::Type::Infer(v0) => crate::Type::Infer(v0.clone()), crate::Type::Macro(v0) => crate::Type::Macro(v0.clone()), crate::Type::Never(v0) => crate::Type::Never(v0.clone()), crate::Type::Paren(v0) => crate::Type::Paren(v0.clone()), crate::Type::Path(v0) => crate::Type::Path(v0.clone()), crate::Type::Ptr(v0) => crate::Type::Ptr(v0.clone()), crate::Type::Reference(v0) => crate::Type::Reference(v0.clone()), crate::Type::Slice(v0) => crate::Type::Slice(v0.clone()), crate::Type::TraitObject(v0) => crate::Type::TraitObject(v0.clone()), crate::Type::Tuple(v0) => crate::Type::Tuple(v0.clone()), crate::Type::Verbatim(v0) => crate::Type::Verbatim(v0.clone()), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeArray { fn clone(&self) -> Self { crate::TypeArray { bracket_token: self.bracket_token.clone(), elem: self.elem.clone(), semi_token: self.semi_token.clone(), len: self.len.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeBareFn { fn clone(&self) -> Self { crate::TypeBareFn { lifetimes: self.lifetimes.clone(), unsafety: self.unsafety.clone(), abi: self.abi.clone(), fn_token: self.fn_token.clone(), paren_token: self.paren_token.clone(), inputs: self.inputs.clone(), variadic: self.variadic.clone(), output: self.output.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeGroup { fn clone(&self) -> Self { crate::TypeGroup { group_token: self.group_token.clone(), elem: self.elem.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeImplTrait { fn clone(&self) -> Self { crate::TypeImplTrait { impl_token: self.impl_token.clone(), bounds: self.bounds.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeInfer { fn clone(&self) -> Self { crate::TypeInfer { underscore_token: self.underscore_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeMacro { fn clone(&self) -> Self { crate::TypeMacro { mac: self.mac.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeNever { fn clone(&self) -> Self { crate::TypeNever { bang_token: self.bang_token.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeParam { fn clone(&self) -> Self { crate::TypeParam { attrs: self.attrs.clone(), ident: self.ident.clone(), colon_token: self.colon_token.clone(), bounds: self.bounds.clone(), eq_token: self.eq_token.clone(), default: self.default.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeParamBound { fn clone(&self) -> Self { match self { crate::TypeParamBound::Trait(v0) => crate::TypeParamBound::Trait(v0.clone()), crate::TypeParamBound::Lifetime(v0) => { crate::TypeParamBound::Lifetime(v0.clone()) } crate::TypeParamBound::Verbatim(v0) => { crate::TypeParamBound::Verbatim(v0.clone()) } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeParen { fn clone(&self) -> Self { crate::TypeParen { paren_token: self.paren_token.clone(), elem: self.elem.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypePath { fn clone(&self) -> Self { crate::TypePath { qself: self.qself.clone(), path: self.path.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypePtr { fn clone(&self) -> Self { crate::TypePtr { star_token: self.star_token.clone(), const_token: self.const_token.clone(), mutability: self.mutability.clone(), elem: self.elem.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeReference { fn clone(&self) -> Self { crate::TypeReference { and_token: self.and_token.clone(), lifetime: self.lifetime.clone(), mutability: self.mutability.clone(), elem: self.elem.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeSlice { fn clone(&self) -> Self { crate::TypeSlice { bracket_token: self.bracket_token.clone(), elem: self.elem.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeTraitObject { fn clone(&self) -> Self { crate::TypeTraitObject { dyn_token: self.dyn_token.clone(), bounds: self.bounds.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::TypeTuple { fn clone(&self) -> Self { crate::TypeTuple { paren_token: self.paren_token.clone(), elems: self.elems.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for crate::UnOp {} #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::UnOp { fn clone(&self) -> Self { *self } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::UseGlob { fn clone(&self) -> Self { crate::UseGlob { star_token: self.star_token.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::UseGroup { fn clone(&self) -> Self { crate::UseGroup { brace_token: self.brace_token.clone(), items: self.items.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::UseName { fn clone(&self) -> Self { crate::UseName { ident: self.ident.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::UsePath { fn clone(&self) -> Self { crate::UsePath { ident: self.ident.clone(), colon2_token: self.colon2_token.clone(), tree: self.tree.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::UseRename { fn clone(&self) -> Self { crate::UseRename { ident: self.ident.clone(), as_token: self.as_token.clone(), rename: self.rename.clone(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::UseTree { fn clone(&self) -> Self { match self { crate::UseTree::Path(v0) => crate::UseTree::Path(v0.clone()), crate::UseTree::Name(v0) => crate::UseTree::Name(v0.clone()), crate::UseTree::Rename(v0) => crate::UseTree::Rename(v0.clone()), crate::UseTree::Glob(v0) => crate::UseTree::Glob(v0.clone()), crate::UseTree::Group(v0) => crate::UseTree::Group(v0.clone()), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Variadic { fn clone(&self) -> Self { crate::Variadic { attrs: self.attrs.clone(), pat: self.pat.clone(), dots: self.dots.clone(), comma: self.comma.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Variant { fn clone(&self) -> Self { crate::Variant { attrs: self.attrs.clone(), ident: self.ident.clone(), fields: self.fields.clone(), discriminant: self.discriminant.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::VisRestricted { fn clone(&self) -> Self { crate::VisRestricted { pub_token: self.pub_token.clone(), paren_token: self.paren_token.clone(), in_token: self.in_token.clone(), path: self.path.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::Visibility { fn clone(&self) -> Self { match self { crate::Visibility::Public(v0) => crate::Visibility::Public(v0.clone()), crate::Visibility::Restricted(v0) => { crate::Visibility::Restricted(v0.clone()) } crate::Visibility::Inherited => crate::Visibility::Inherited, } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::WhereClause { fn clone(&self) -> Self { crate::WhereClause { where_token: self.where_token.clone(), predicates: self.predicates.clone(), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for crate::WherePredicate { fn clone(&self) -> Self { match self { crate::WherePredicate::Lifetime(v0) => { crate::WherePredicate::Lifetime(v0.clone()) } crate::WherePredicate::Type(v0) => crate::WherePredicate::Type(v0.clone()), } } } syn/src/gen/fold.rs0000644000175000017500000040620514661133735015213 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #![allow(unreachable_code, unused_variables)] #![allow( clippy::match_wildcard_for_single_variants, clippy::needless_match, clippy::needless_pass_by_ref_mut, )] #[cfg(feature = "full")] macro_rules! full { ($e:expr) => { $e }; } #[cfg(all(feature = "derive", not(feature = "full")))] macro_rules! full { ($e:expr) => { unreachable!() }; } /// Syntax tree traversal to transform the nodes of an owned syntax tree. /// /// See the [module documentation] for details. /// /// [module documentation]: self pub trait Fold { #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_abi(&mut self, i: crate::Abi) -> crate::Abi { fold_abi(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_angle_bracketed_generic_arguments( &mut self, i: crate::AngleBracketedGenericArguments, ) -> crate::AngleBracketedGenericArguments { fold_angle_bracketed_generic_arguments(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_arm(&mut self, i: crate::Arm) -> crate::Arm { fold_arm(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_assoc_const(&mut self, i: crate::AssocConst) -> crate::AssocConst { fold_assoc_const(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_assoc_type(&mut self, i: crate::AssocType) -> crate::AssocType { fold_assoc_type(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_attr_style(&mut self, i: crate::AttrStyle) -> crate::AttrStyle { fold_attr_style(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_attribute(&mut self, i: crate::Attribute) -> crate::Attribute { fold_attribute(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_bare_fn_arg(&mut self, i: crate::BareFnArg) -> crate::BareFnArg { fold_bare_fn_arg(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_bare_variadic(&mut self, i: crate::BareVariadic) -> crate::BareVariadic { fold_bare_variadic(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_bin_op(&mut self, i: crate::BinOp) -> crate::BinOp { fold_bin_op(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_block(&mut self, i: crate::Block) -> crate::Block { fold_block(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_bound_lifetimes( &mut self, i: crate::BoundLifetimes, ) -> crate::BoundLifetimes { fold_bound_lifetimes(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_const_param(&mut self, i: crate::ConstParam) -> crate::ConstParam { fold_const_param(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_constraint(&mut self, i: crate::Constraint) -> crate::Constraint { fold_constraint(self, i) } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_data(&mut self, i: crate::Data) -> crate::Data { fold_data(self, i) } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_data_enum(&mut self, i: crate::DataEnum) -> crate::DataEnum { fold_data_enum(self, i) } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_data_struct(&mut self, i: crate::DataStruct) -> crate::DataStruct { fold_data_struct(self, i) } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_data_union(&mut self, i: crate::DataUnion) -> crate::DataUnion { fold_data_union(self, i) } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn fold_derive_input(&mut self, i: crate::DeriveInput) -> crate::DeriveInput { fold_derive_input(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr(&mut self, i: crate::Expr) -> crate::Expr { fold_expr(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_array(&mut self, i: crate::ExprArray) -> crate::ExprArray { fold_expr_array(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_assign(&mut self, i: crate::ExprAssign) -> crate::ExprAssign { fold_expr_assign(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_async(&mut self, i: crate::ExprAsync) -> crate::ExprAsync { fold_expr_async(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_await(&mut self, i: crate::ExprAwait) -> crate::ExprAwait { fold_expr_await(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_binary(&mut self, i: crate::ExprBinary) -> crate::ExprBinary { fold_expr_binary(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_block(&mut self, i: crate::ExprBlock) -> crate::ExprBlock { fold_expr_block(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_break(&mut self, i: crate::ExprBreak) -> crate::ExprBreak { fold_expr_break(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_call(&mut self, i: crate::ExprCall) -> crate::ExprCall { fold_expr_call(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_cast(&mut self, i: crate::ExprCast) -> crate::ExprCast { fold_expr_cast(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_closure(&mut self, i: crate::ExprClosure) -> crate::ExprClosure { fold_expr_closure(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_const(&mut self, i: crate::ExprConst) -> crate::ExprConst { fold_expr_const(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_continue(&mut self, i: crate::ExprContinue) -> crate::ExprContinue { fold_expr_continue(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_field(&mut self, i: crate::ExprField) -> crate::ExprField { fold_expr_field(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_for_loop(&mut self, i: crate::ExprForLoop) -> crate::ExprForLoop { fold_expr_for_loop(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_group(&mut self, i: crate::ExprGroup) -> crate::ExprGroup { fold_expr_group(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_if(&mut self, i: crate::ExprIf) -> crate::ExprIf { fold_expr_if(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_index(&mut self, i: crate::ExprIndex) -> crate::ExprIndex { fold_expr_index(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_infer(&mut self, i: crate::ExprInfer) -> crate::ExprInfer { fold_expr_infer(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_let(&mut self, i: crate::ExprLet) -> crate::ExprLet { fold_expr_let(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_lit(&mut self, i: crate::ExprLit) -> crate::ExprLit { fold_expr_lit(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_loop(&mut self, i: crate::ExprLoop) -> crate::ExprLoop { fold_expr_loop(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_macro(&mut self, i: crate::ExprMacro) -> crate::ExprMacro { fold_expr_macro(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_match(&mut self, i: crate::ExprMatch) -> crate::ExprMatch { fold_expr_match(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_method_call( &mut self, i: crate::ExprMethodCall, ) -> crate::ExprMethodCall { fold_expr_method_call(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_paren(&mut self, i: crate::ExprParen) -> crate::ExprParen { fold_expr_paren(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_path(&mut self, i: crate::ExprPath) -> crate::ExprPath { fold_expr_path(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_range(&mut self, i: crate::ExprRange) -> crate::ExprRange { fold_expr_range(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_reference(&mut self, i: crate::ExprReference) -> crate::ExprReference { fold_expr_reference(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_repeat(&mut self, i: crate::ExprRepeat) -> crate::ExprRepeat { fold_expr_repeat(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_return(&mut self, i: crate::ExprReturn) -> crate::ExprReturn { fold_expr_return(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_struct(&mut self, i: crate::ExprStruct) -> crate::ExprStruct { fold_expr_struct(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_try(&mut self, i: crate::ExprTry) -> crate::ExprTry { fold_expr_try(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_try_block(&mut self, i: crate::ExprTryBlock) -> crate::ExprTryBlock { fold_expr_try_block(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_tuple(&mut self, i: crate::ExprTuple) -> crate::ExprTuple { fold_expr_tuple(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_expr_unary(&mut self, i: crate::ExprUnary) -> crate::ExprUnary { fold_expr_unary(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_unsafe(&mut self, i: crate::ExprUnsafe) -> crate::ExprUnsafe { fold_expr_unsafe(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_while(&mut self, i: crate::ExprWhile) -> crate::ExprWhile { fold_expr_while(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_expr_yield(&mut self, i: crate::ExprYield) -> crate::ExprYield { fold_expr_yield(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_field(&mut self, i: crate::Field) -> crate::Field { fold_field(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_field_mutability( &mut self, i: crate::FieldMutability, ) -> crate::FieldMutability { fold_field_mutability(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_field_pat(&mut self, i: crate::FieldPat) -> crate::FieldPat { fold_field_pat(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_field_value(&mut self, i: crate::FieldValue) -> crate::FieldValue { fold_field_value(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_fields(&mut self, i: crate::Fields) -> crate::Fields { fold_fields(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_fields_named(&mut self, i: crate::FieldsNamed) -> crate::FieldsNamed { fold_fields_named(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_fields_unnamed(&mut self, i: crate::FieldsUnnamed) -> crate::FieldsUnnamed { fold_fields_unnamed(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_file(&mut self, i: crate::File) -> crate::File { fold_file(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_fn_arg(&mut self, i: crate::FnArg) -> crate::FnArg { fold_fn_arg(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_foreign_item(&mut self, i: crate::ForeignItem) -> crate::ForeignItem { fold_foreign_item(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_foreign_item_fn(&mut self, i: crate::ForeignItemFn) -> crate::ForeignItemFn { fold_foreign_item_fn(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_foreign_item_macro( &mut self, i: crate::ForeignItemMacro, ) -> crate::ForeignItemMacro { fold_foreign_item_macro(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_foreign_item_static( &mut self, i: crate::ForeignItemStatic, ) -> crate::ForeignItemStatic { fold_foreign_item_static(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_foreign_item_type( &mut self, i: crate::ForeignItemType, ) -> crate::ForeignItemType { fold_foreign_item_type(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_generic_argument( &mut self, i: crate::GenericArgument, ) -> crate::GenericArgument { fold_generic_argument(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_generic_param(&mut self, i: crate::GenericParam) -> crate::GenericParam { fold_generic_param(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_generics(&mut self, i: crate::Generics) -> crate::Generics { fold_generics(self, i) } fn fold_ident(&mut self, i: proc_macro2::Ident) -> proc_macro2::Ident { fold_ident(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_impl_item(&mut self, i: crate::ImplItem) -> crate::ImplItem { fold_impl_item(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_impl_item_const(&mut self, i: crate::ImplItemConst) -> crate::ImplItemConst { fold_impl_item_const(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_impl_item_fn(&mut self, i: crate::ImplItemFn) -> crate::ImplItemFn { fold_impl_item_fn(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_impl_item_macro(&mut self, i: crate::ImplItemMacro) -> crate::ImplItemMacro { fold_impl_item_macro(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_impl_item_type(&mut self, i: crate::ImplItemType) -> crate::ImplItemType { fold_impl_item_type(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_impl_restriction( &mut self, i: crate::ImplRestriction, ) -> crate::ImplRestriction { fold_impl_restriction(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_index(&mut self, i: crate::Index) -> crate::Index { fold_index(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item(&mut self, i: crate::Item) -> crate::Item { fold_item(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_const(&mut self, i: crate::ItemConst) -> crate::ItemConst { fold_item_const(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_enum(&mut self, i: crate::ItemEnum) -> crate::ItemEnum { fold_item_enum(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_extern_crate( &mut self, i: crate::ItemExternCrate, ) -> crate::ItemExternCrate { fold_item_extern_crate(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_fn(&mut self, i: crate::ItemFn) -> crate::ItemFn { fold_item_fn(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_foreign_mod( &mut self, i: crate::ItemForeignMod, ) -> crate::ItemForeignMod { fold_item_foreign_mod(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_impl(&mut self, i: crate::ItemImpl) -> crate::ItemImpl { fold_item_impl(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_macro(&mut self, i: crate::ItemMacro) -> crate::ItemMacro { fold_item_macro(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_mod(&mut self, i: crate::ItemMod) -> crate::ItemMod { fold_item_mod(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_static(&mut self, i: crate::ItemStatic) -> crate::ItemStatic { fold_item_static(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_struct(&mut self, i: crate::ItemStruct) -> crate::ItemStruct { fold_item_struct(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_trait(&mut self, i: crate::ItemTrait) -> crate::ItemTrait { fold_item_trait(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_trait_alias( &mut self, i: crate::ItemTraitAlias, ) -> crate::ItemTraitAlias { fold_item_trait_alias(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_type(&mut self, i: crate::ItemType) -> crate::ItemType { fold_item_type(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_union(&mut self, i: crate::ItemUnion) -> crate::ItemUnion { fold_item_union(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_item_use(&mut self, i: crate::ItemUse) -> crate::ItemUse { fold_item_use(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_label(&mut self, i: crate::Label) -> crate::Label { fold_label(self, i) } fn fold_lifetime(&mut self, i: crate::Lifetime) -> crate::Lifetime { fold_lifetime(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_lifetime_param(&mut self, i: crate::LifetimeParam) -> crate::LifetimeParam { fold_lifetime_param(self, i) } fn fold_lit(&mut self, i: crate::Lit) -> crate::Lit { fold_lit(self, i) } fn fold_lit_bool(&mut self, i: crate::LitBool) -> crate::LitBool { fold_lit_bool(self, i) } fn fold_lit_byte(&mut self, i: crate::LitByte) -> crate::LitByte { fold_lit_byte(self, i) } fn fold_lit_byte_str(&mut self, i: crate::LitByteStr) -> crate::LitByteStr { fold_lit_byte_str(self, i) } fn fold_lit_cstr(&mut self, i: crate::LitCStr) -> crate::LitCStr { fold_lit_cstr(self, i) } fn fold_lit_char(&mut self, i: crate::LitChar) -> crate::LitChar { fold_lit_char(self, i) } fn fold_lit_float(&mut self, i: crate::LitFloat) -> crate::LitFloat { fold_lit_float(self, i) } fn fold_lit_int(&mut self, i: crate::LitInt) -> crate::LitInt { fold_lit_int(self, i) } fn fold_lit_str(&mut self, i: crate::LitStr) -> crate::LitStr { fold_lit_str(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_local(&mut self, i: crate::Local) -> crate::Local { fold_local(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_local_init(&mut self, i: crate::LocalInit) -> crate::LocalInit { fold_local_init(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_macro(&mut self, i: crate::Macro) -> crate::Macro { fold_macro(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_macro_delimiter( &mut self, i: crate::MacroDelimiter, ) -> crate::MacroDelimiter { fold_macro_delimiter(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_member(&mut self, i: crate::Member) -> crate::Member { fold_member(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_meta(&mut self, i: crate::Meta) -> crate::Meta { fold_meta(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_meta_list(&mut self, i: crate::MetaList) -> crate::MetaList { fold_meta_list(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_meta_name_value(&mut self, i: crate::MetaNameValue) -> crate::MetaNameValue { fold_meta_name_value(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_parenthesized_generic_arguments( &mut self, i: crate::ParenthesizedGenericArguments, ) -> crate::ParenthesizedGenericArguments { fold_parenthesized_generic_arguments(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat(&mut self, i: crate::Pat) -> crate::Pat { fold_pat(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_ident(&mut self, i: crate::PatIdent) -> crate::PatIdent { fold_pat_ident(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_or(&mut self, i: crate::PatOr) -> crate::PatOr { fold_pat_or(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_paren(&mut self, i: crate::PatParen) -> crate::PatParen { fold_pat_paren(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_reference(&mut self, i: crate::PatReference) -> crate::PatReference { fold_pat_reference(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_rest(&mut self, i: crate::PatRest) -> crate::PatRest { fold_pat_rest(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_slice(&mut self, i: crate::PatSlice) -> crate::PatSlice { fold_pat_slice(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_struct(&mut self, i: crate::PatStruct) -> crate::PatStruct { fold_pat_struct(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_tuple(&mut self, i: crate::PatTuple) -> crate::PatTuple { fold_pat_tuple(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_tuple_struct( &mut self, i: crate::PatTupleStruct, ) -> crate::PatTupleStruct { fold_pat_tuple_struct(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_type(&mut self, i: crate::PatType) -> crate::PatType { fold_pat_type(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_pat_wild(&mut self, i: crate::PatWild) -> crate::PatWild { fold_pat_wild(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_path(&mut self, i: crate::Path) -> crate::Path { fold_path(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_path_arguments(&mut self, i: crate::PathArguments) -> crate::PathArguments { fold_path_arguments(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_path_segment(&mut self, i: crate::PathSegment) -> crate::PathSegment { fold_path_segment(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_predicate_lifetime( &mut self, i: crate::PredicateLifetime, ) -> crate::PredicateLifetime { fold_predicate_lifetime(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_predicate_type(&mut self, i: crate::PredicateType) -> crate::PredicateType { fold_predicate_type(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_qself(&mut self, i: crate::QSelf) -> crate::QSelf { fold_qself(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_range_limits(&mut self, i: crate::RangeLimits) -> crate::RangeLimits { fold_range_limits(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_receiver(&mut self, i: crate::Receiver) -> crate::Receiver { fold_receiver(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_return_type(&mut self, i: crate::ReturnType) -> crate::ReturnType { fold_return_type(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_signature(&mut self, i: crate::Signature) -> crate::Signature { fold_signature(self, i) } fn fold_span(&mut self, i: proc_macro2::Span) -> proc_macro2::Span { fold_span(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_static_mutability( &mut self, i: crate::StaticMutability, ) -> crate::StaticMutability { fold_static_mutability(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_stmt(&mut self, i: crate::Stmt) -> crate::Stmt { fold_stmt(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_stmt_macro(&mut self, i: crate::StmtMacro) -> crate::StmtMacro { fold_stmt_macro(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_trait_bound(&mut self, i: crate::TraitBound) -> crate::TraitBound { fold_trait_bound(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_trait_bound_modifier( &mut self, i: crate::TraitBoundModifier, ) -> crate::TraitBoundModifier { fold_trait_bound_modifier(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_trait_item(&mut self, i: crate::TraitItem) -> crate::TraitItem { fold_trait_item(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_trait_item_const( &mut self, i: crate::TraitItemConst, ) -> crate::TraitItemConst { fold_trait_item_const(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_trait_item_fn(&mut self, i: crate::TraitItemFn) -> crate::TraitItemFn { fold_trait_item_fn(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_trait_item_macro( &mut self, i: crate::TraitItemMacro, ) -> crate::TraitItemMacro { fold_trait_item_macro(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_trait_item_type(&mut self, i: crate::TraitItemType) -> crate::TraitItemType { fold_trait_item_type(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type(&mut self, i: crate::Type) -> crate::Type { fold_type(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_array(&mut self, i: crate::TypeArray) -> crate::TypeArray { fold_type_array(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_bare_fn(&mut self, i: crate::TypeBareFn) -> crate::TypeBareFn { fold_type_bare_fn(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_group(&mut self, i: crate::TypeGroup) -> crate::TypeGroup { fold_type_group(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_impl_trait(&mut self, i: crate::TypeImplTrait) -> crate::TypeImplTrait { fold_type_impl_trait(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_infer(&mut self, i: crate::TypeInfer) -> crate::TypeInfer { fold_type_infer(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_macro(&mut self, i: crate::TypeMacro) -> crate::TypeMacro { fold_type_macro(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_never(&mut self, i: crate::TypeNever) -> crate::TypeNever { fold_type_never(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_param(&mut self, i: crate::TypeParam) -> crate::TypeParam { fold_type_param(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_param_bound( &mut self, i: crate::TypeParamBound, ) -> crate::TypeParamBound { fold_type_param_bound(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_paren(&mut self, i: crate::TypeParen) -> crate::TypeParen { fold_type_paren(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_path(&mut self, i: crate::TypePath) -> crate::TypePath { fold_type_path(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_ptr(&mut self, i: crate::TypePtr) -> crate::TypePtr { fold_type_ptr(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_reference(&mut self, i: crate::TypeReference) -> crate::TypeReference { fold_type_reference(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_slice(&mut self, i: crate::TypeSlice) -> crate::TypeSlice { fold_type_slice(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_trait_object( &mut self, i: crate::TypeTraitObject, ) -> crate::TypeTraitObject { fold_type_trait_object(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_type_tuple(&mut self, i: crate::TypeTuple) -> crate::TypeTuple { fold_type_tuple(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_un_op(&mut self, i: crate::UnOp) -> crate::UnOp { fold_un_op(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_use_glob(&mut self, i: crate::UseGlob) -> crate::UseGlob { fold_use_glob(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_use_group(&mut self, i: crate::UseGroup) -> crate::UseGroup { fold_use_group(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_use_name(&mut self, i: crate::UseName) -> crate::UseName { fold_use_name(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_use_path(&mut self, i: crate::UsePath) -> crate::UsePath { fold_use_path(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_use_rename(&mut self, i: crate::UseRename) -> crate::UseRename { fold_use_rename(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_use_tree(&mut self, i: crate::UseTree) -> crate::UseTree { fold_use_tree(self, i) } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn fold_variadic(&mut self, i: crate::Variadic) -> crate::Variadic { fold_variadic(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_variant(&mut self, i: crate::Variant) -> crate::Variant { fold_variant(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_vis_restricted(&mut self, i: crate::VisRestricted) -> crate::VisRestricted { fold_vis_restricted(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_visibility(&mut self, i: crate::Visibility) -> crate::Visibility { fold_visibility(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_where_clause(&mut self, i: crate::WhereClause) -> crate::WhereClause { fold_where_clause(self, i) } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn fold_where_predicate( &mut self, i: crate::WherePredicate, ) -> crate::WherePredicate { fold_where_predicate(self, i) } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_abi(f: &mut F, node: crate::Abi) -> crate::Abi where F: Fold + ?Sized, { crate::Abi { extern_token: node.extern_token, name: (node.name).map(|it| f.fold_lit_str(it)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_angle_bracketed_generic_arguments( f: &mut F, node: crate::AngleBracketedGenericArguments, ) -> crate::AngleBracketedGenericArguments where F: Fold + ?Sized, { crate::AngleBracketedGenericArguments { colon2_token: node.colon2_token, lt_token: node.lt_token, args: crate::punctuated::fold(node.args, f, F::fold_generic_argument), gt_token: node.gt_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_arm(f: &mut F, node: crate::Arm) -> crate::Arm where F: Fold + ?Sized, { crate::Arm { attrs: fold_vec(node.attrs, f, F::fold_attribute), pat: f.fold_pat(node.pat), guard: (node.guard).map(|it| ((it).0, Box::new(f.fold_expr(*(it).1)))), fat_arrow_token: node.fat_arrow_token, body: Box::new(f.fold_expr(*node.body)), comma: node.comma, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_assoc_const(f: &mut F, node: crate::AssocConst) -> crate::AssocConst where F: Fold + ?Sized, { crate::AssocConst { ident: f.fold_ident(node.ident), generics: (node.generics).map(|it| f.fold_angle_bracketed_generic_arguments(it)), eq_token: node.eq_token, value: f.fold_expr(node.value), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_assoc_type(f: &mut F, node: crate::AssocType) -> crate::AssocType where F: Fold + ?Sized, { crate::AssocType { ident: f.fold_ident(node.ident), generics: (node.generics).map(|it| f.fold_angle_bracketed_generic_arguments(it)), eq_token: node.eq_token, ty: f.fold_type(node.ty), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_attr_style(f: &mut F, node: crate::AttrStyle) -> crate::AttrStyle where F: Fold + ?Sized, { match node { crate::AttrStyle::Outer => crate::AttrStyle::Outer, crate::AttrStyle::Inner(_binding_0) => crate::AttrStyle::Inner(_binding_0), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_attribute(f: &mut F, node: crate::Attribute) -> crate::Attribute where F: Fold + ?Sized, { crate::Attribute { pound_token: node.pound_token, style: f.fold_attr_style(node.style), bracket_token: node.bracket_token, meta: f.fold_meta(node.meta), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_bare_fn_arg(f: &mut F, node: crate::BareFnArg) -> crate::BareFnArg where F: Fold + ?Sized, { crate::BareFnArg { attrs: fold_vec(node.attrs, f, F::fold_attribute), name: (node.name).map(|it| (f.fold_ident((it).0), (it).1)), ty: f.fold_type(node.ty), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_bare_variadic(f: &mut F, node: crate::BareVariadic) -> crate::BareVariadic where F: Fold + ?Sized, { crate::BareVariadic { attrs: fold_vec(node.attrs, f, F::fold_attribute), name: (node.name).map(|it| (f.fold_ident((it).0), (it).1)), dots: node.dots, comma: node.comma, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_bin_op(f: &mut F, node: crate::BinOp) -> crate::BinOp where F: Fold + ?Sized, { match node { crate::BinOp::Add(_binding_0) => crate::BinOp::Add(_binding_0), crate::BinOp::Sub(_binding_0) => crate::BinOp::Sub(_binding_0), crate::BinOp::Mul(_binding_0) => crate::BinOp::Mul(_binding_0), crate::BinOp::Div(_binding_0) => crate::BinOp::Div(_binding_0), crate::BinOp::Rem(_binding_0) => crate::BinOp::Rem(_binding_0), crate::BinOp::And(_binding_0) => crate::BinOp::And(_binding_0), crate::BinOp::Or(_binding_0) => crate::BinOp::Or(_binding_0), crate::BinOp::BitXor(_binding_0) => crate::BinOp::BitXor(_binding_0), crate::BinOp::BitAnd(_binding_0) => crate::BinOp::BitAnd(_binding_0), crate::BinOp::BitOr(_binding_0) => crate::BinOp::BitOr(_binding_0), crate::BinOp::Shl(_binding_0) => crate::BinOp::Shl(_binding_0), crate::BinOp::Shr(_binding_0) => crate::BinOp::Shr(_binding_0), crate::BinOp::Eq(_binding_0) => crate::BinOp::Eq(_binding_0), crate::BinOp::Lt(_binding_0) => crate::BinOp::Lt(_binding_0), crate::BinOp::Le(_binding_0) => crate::BinOp::Le(_binding_0), crate::BinOp::Ne(_binding_0) => crate::BinOp::Ne(_binding_0), crate::BinOp::Ge(_binding_0) => crate::BinOp::Ge(_binding_0), crate::BinOp::Gt(_binding_0) => crate::BinOp::Gt(_binding_0), crate::BinOp::AddAssign(_binding_0) => crate::BinOp::AddAssign(_binding_0), crate::BinOp::SubAssign(_binding_0) => crate::BinOp::SubAssign(_binding_0), crate::BinOp::MulAssign(_binding_0) => crate::BinOp::MulAssign(_binding_0), crate::BinOp::DivAssign(_binding_0) => crate::BinOp::DivAssign(_binding_0), crate::BinOp::RemAssign(_binding_0) => crate::BinOp::RemAssign(_binding_0), crate::BinOp::BitXorAssign(_binding_0) => crate::BinOp::BitXorAssign(_binding_0), crate::BinOp::BitAndAssign(_binding_0) => crate::BinOp::BitAndAssign(_binding_0), crate::BinOp::BitOrAssign(_binding_0) => crate::BinOp::BitOrAssign(_binding_0), crate::BinOp::ShlAssign(_binding_0) => crate::BinOp::ShlAssign(_binding_0), crate::BinOp::ShrAssign(_binding_0) => crate::BinOp::ShrAssign(_binding_0), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_block(f: &mut F, node: crate::Block) -> crate::Block where F: Fold + ?Sized, { crate::Block { brace_token: node.brace_token, stmts: fold_vec(node.stmts, f, F::fold_stmt), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_bound_lifetimes( f: &mut F, node: crate::BoundLifetimes, ) -> crate::BoundLifetimes where F: Fold + ?Sized, { crate::BoundLifetimes { for_token: node.for_token, lt_token: node.lt_token, lifetimes: crate::punctuated::fold(node.lifetimes, f, F::fold_generic_param), gt_token: node.gt_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_const_param(f: &mut F, node: crate::ConstParam) -> crate::ConstParam where F: Fold + ?Sized, { crate::ConstParam { attrs: fold_vec(node.attrs, f, F::fold_attribute), const_token: node.const_token, ident: f.fold_ident(node.ident), colon_token: node.colon_token, ty: f.fold_type(node.ty), eq_token: node.eq_token, default: (node.default).map(|it| f.fold_expr(it)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_constraint(f: &mut F, node: crate::Constraint) -> crate::Constraint where F: Fold + ?Sized, { crate::Constraint { ident: f.fold_ident(node.ident), generics: (node.generics).map(|it| f.fold_angle_bracketed_generic_arguments(it)), colon_token: node.colon_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound), } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_data(f: &mut F, node: crate::Data) -> crate::Data where F: Fold + ?Sized, { match node { crate::Data::Struct(_binding_0) => { crate::Data::Struct(f.fold_data_struct(_binding_0)) } crate::Data::Enum(_binding_0) => crate::Data::Enum(f.fold_data_enum(_binding_0)), crate::Data::Union(_binding_0) => { crate::Data::Union(f.fold_data_union(_binding_0)) } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_data_enum(f: &mut F, node: crate::DataEnum) -> crate::DataEnum where F: Fold + ?Sized, { crate::DataEnum { enum_token: node.enum_token, brace_token: node.brace_token, variants: crate::punctuated::fold(node.variants, f, F::fold_variant), } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_data_struct(f: &mut F, node: crate::DataStruct) -> crate::DataStruct where F: Fold + ?Sized, { crate::DataStruct { struct_token: node.struct_token, fields: f.fold_fields(node.fields), semi_token: node.semi_token, } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_data_union(f: &mut F, node: crate::DataUnion) -> crate::DataUnion where F: Fold + ?Sized, { crate::DataUnion { union_token: node.union_token, fields: f.fold_fields_named(node.fields), } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn fold_derive_input(f: &mut F, node: crate::DeriveInput) -> crate::DeriveInput where F: Fold + ?Sized, { crate::DeriveInput { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), data: f.fold_data(node.data), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr(f: &mut F, node: crate::Expr) -> crate::Expr where F: Fold + ?Sized, { match node { crate::Expr::Array(_binding_0) => { crate::Expr::Array(full!(f.fold_expr_array(_binding_0))) } crate::Expr::Assign(_binding_0) => { crate::Expr::Assign(full!(f.fold_expr_assign(_binding_0))) } crate::Expr::Async(_binding_0) => { crate::Expr::Async(full!(f.fold_expr_async(_binding_0))) } crate::Expr::Await(_binding_0) => { crate::Expr::Await(full!(f.fold_expr_await(_binding_0))) } crate::Expr::Binary(_binding_0) => { crate::Expr::Binary(f.fold_expr_binary(_binding_0)) } crate::Expr::Block(_binding_0) => { crate::Expr::Block(full!(f.fold_expr_block(_binding_0))) } crate::Expr::Break(_binding_0) => { crate::Expr::Break(full!(f.fold_expr_break(_binding_0))) } crate::Expr::Call(_binding_0) => crate::Expr::Call(f.fold_expr_call(_binding_0)), crate::Expr::Cast(_binding_0) => crate::Expr::Cast(f.fold_expr_cast(_binding_0)), crate::Expr::Closure(_binding_0) => { crate::Expr::Closure(full!(f.fold_expr_closure(_binding_0))) } crate::Expr::Const(_binding_0) => { crate::Expr::Const(full!(f.fold_expr_const(_binding_0))) } crate::Expr::Continue(_binding_0) => { crate::Expr::Continue(full!(f.fold_expr_continue(_binding_0))) } crate::Expr::Field(_binding_0) => { crate::Expr::Field(f.fold_expr_field(_binding_0)) } crate::Expr::ForLoop(_binding_0) => { crate::Expr::ForLoop(full!(f.fold_expr_for_loop(_binding_0))) } crate::Expr::Group(_binding_0) => { crate::Expr::Group(f.fold_expr_group(_binding_0)) } crate::Expr::If(_binding_0) => crate::Expr::If(full!(f.fold_expr_if(_binding_0))), crate::Expr::Index(_binding_0) => { crate::Expr::Index(f.fold_expr_index(_binding_0)) } crate::Expr::Infer(_binding_0) => { crate::Expr::Infer(full!(f.fold_expr_infer(_binding_0))) } crate::Expr::Let(_binding_0) => { crate::Expr::Let(full!(f.fold_expr_let(_binding_0))) } crate::Expr::Lit(_binding_0) => crate::Expr::Lit(f.fold_expr_lit(_binding_0)), crate::Expr::Loop(_binding_0) => { crate::Expr::Loop(full!(f.fold_expr_loop(_binding_0))) } crate::Expr::Macro(_binding_0) => { crate::Expr::Macro(f.fold_expr_macro(_binding_0)) } crate::Expr::Match(_binding_0) => { crate::Expr::Match(full!(f.fold_expr_match(_binding_0))) } crate::Expr::MethodCall(_binding_0) => { crate::Expr::MethodCall(f.fold_expr_method_call(_binding_0)) } crate::Expr::Paren(_binding_0) => { crate::Expr::Paren(f.fold_expr_paren(_binding_0)) } crate::Expr::Path(_binding_0) => crate::Expr::Path(f.fold_expr_path(_binding_0)), crate::Expr::Range(_binding_0) => { crate::Expr::Range(full!(f.fold_expr_range(_binding_0))) } crate::Expr::Reference(_binding_0) => { crate::Expr::Reference(f.fold_expr_reference(_binding_0)) } crate::Expr::Repeat(_binding_0) => { crate::Expr::Repeat(full!(f.fold_expr_repeat(_binding_0))) } crate::Expr::Return(_binding_0) => { crate::Expr::Return(full!(f.fold_expr_return(_binding_0))) } crate::Expr::Struct(_binding_0) => { crate::Expr::Struct(f.fold_expr_struct(_binding_0)) } crate::Expr::Try(_binding_0) => { crate::Expr::Try(full!(f.fold_expr_try(_binding_0))) } crate::Expr::TryBlock(_binding_0) => { crate::Expr::TryBlock(full!(f.fold_expr_try_block(_binding_0))) } crate::Expr::Tuple(_binding_0) => { crate::Expr::Tuple(full!(f.fold_expr_tuple(_binding_0))) } crate::Expr::Unary(_binding_0) => { crate::Expr::Unary(f.fold_expr_unary(_binding_0)) } crate::Expr::Unsafe(_binding_0) => { crate::Expr::Unsafe(full!(f.fold_expr_unsafe(_binding_0))) } crate::Expr::Verbatim(_binding_0) => crate::Expr::Verbatim(_binding_0), crate::Expr::While(_binding_0) => { crate::Expr::While(full!(f.fold_expr_while(_binding_0))) } crate::Expr::Yield(_binding_0) => { crate::Expr::Yield(full!(f.fold_expr_yield(_binding_0))) } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_array(f: &mut F, node: crate::ExprArray) -> crate::ExprArray where F: Fold + ?Sized, { crate::ExprArray { attrs: fold_vec(node.attrs, f, F::fold_attribute), bracket_token: node.bracket_token, elems: crate::punctuated::fold(node.elems, f, F::fold_expr), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_assign(f: &mut F, node: crate::ExprAssign) -> crate::ExprAssign where F: Fold + ?Sized, { crate::ExprAssign { attrs: fold_vec(node.attrs, f, F::fold_attribute), left: Box::new(f.fold_expr(*node.left)), eq_token: node.eq_token, right: Box::new(f.fold_expr(*node.right)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_async(f: &mut F, node: crate::ExprAsync) -> crate::ExprAsync where F: Fold + ?Sized, { crate::ExprAsync { attrs: fold_vec(node.attrs, f, F::fold_attribute), async_token: node.async_token, capture: node.capture, block: f.fold_block(node.block), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_await(f: &mut F, node: crate::ExprAwait) -> crate::ExprAwait where F: Fold + ?Sized, { crate::ExprAwait { attrs: fold_vec(node.attrs, f, F::fold_attribute), base: Box::new(f.fold_expr(*node.base)), dot_token: node.dot_token, await_token: node.await_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_binary(f: &mut F, node: crate::ExprBinary) -> crate::ExprBinary where F: Fold + ?Sized, { crate::ExprBinary { attrs: fold_vec(node.attrs, f, F::fold_attribute), left: Box::new(f.fold_expr(*node.left)), op: f.fold_bin_op(node.op), right: Box::new(f.fold_expr(*node.right)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_block(f: &mut F, node: crate::ExprBlock) -> crate::ExprBlock where F: Fold + ?Sized, { crate::ExprBlock { attrs: fold_vec(node.attrs, f, F::fold_attribute), label: (node.label).map(|it| f.fold_label(it)), block: f.fold_block(node.block), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_break(f: &mut F, node: crate::ExprBreak) -> crate::ExprBreak where F: Fold + ?Sized, { crate::ExprBreak { attrs: fold_vec(node.attrs, f, F::fold_attribute), break_token: node.break_token, label: (node.label).map(|it| f.fold_lifetime(it)), expr: (node.expr).map(|it| Box::new(f.fold_expr(*it))), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_call(f: &mut F, node: crate::ExprCall) -> crate::ExprCall where F: Fold + ?Sized, { crate::ExprCall { attrs: fold_vec(node.attrs, f, F::fold_attribute), func: Box::new(f.fold_expr(*node.func)), paren_token: node.paren_token, args: crate::punctuated::fold(node.args, f, F::fold_expr), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_cast(f: &mut F, node: crate::ExprCast) -> crate::ExprCast where F: Fold + ?Sized, { crate::ExprCast { attrs: fold_vec(node.attrs, f, F::fold_attribute), expr: Box::new(f.fold_expr(*node.expr)), as_token: node.as_token, ty: Box::new(f.fold_type(*node.ty)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_closure(f: &mut F, node: crate::ExprClosure) -> crate::ExprClosure where F: Fold + ?Sized, { crate::ExprClosure { attrs: fold_vec(node.attrs, f, F::fold_attribute), lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)), constness: node.constness, movability: node.movability, asyncness: node.asyncness, capture: node.capture, or1_token: node.or1_token, inputs: crate::punctuated::fold(node.inputs, f, F::fold_pat), or2_token: node.or2_token, output: f.fold_return_type(node.output), body: Box::new(f.fold_expr(*node.body)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_const(f: &mut F, node: crate::ExprConst) -> crate::ExprConst where F: Fold + ?Sized, { crate::ExprConst { attrs: fold_vec(node.attrs, f, F::fold_attribute), const_token: node.const_token, block: f.fold_block(node.block), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_continue(f: &mut F, node: crate::ExprContinue) -> crate::ExprContinue where F: Fold + ?Sized, { crate::ExprContinue { attrs: fold_vec(node.attrs, f, F::fold_attribute), continue_token: node.continue_token, label: (node.label).map(|it| f.fold_lifetime(it)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_field(f: &mut F, node: crate::ExprField) -> crate::ExprField where F: Fold + ?Sized, { crate::ExprField { attrs: fold_vec(node.attrs, f, F::fold_attribute), base: Box::new(f.fold_expr(*node.base)), dot_token: node.dot_token, member: f.fold_member(node.member), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_for_loop(f: &mut F, node: crate::ExprForLoop) -> crate::ExprForLoop where F: Fold + ?Sized, { crate::ExprForLoop { attrs: fold_vec(node.attrs, f, F::fold_attribute), label: (node.label).map(|it| f.fold_label(it)), for_token: node.for_token, pat: Box::new(f.fold_pat(*node.pat)), in_token: node.in_token, expr: Box::new(f.fold_expr(*node.expr)), body: f.fold_block(node.body), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_group(f: &mut F, node: crate::ExprGroup) -> crate::ExprGroup where F: Fold + ?Sized, { crate::ExprGroup { attrs: fold_vec(node.attrs, f, F::fold_attribute), group_token: node.group_token, expr: Box::new(f.fold_expr(*node.expr)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_if(f: &mut F, node: crate::ExprIf) -> crate::ExprIf where F: Fold + ?Sized, { crate::ExprIf { attrs: fold_vec(node.attrs, f, F::fold_attribute), if_token: node.if_token, cond: Box::new(f.fold_expr(*node.cond)), then_branch: f.fold_block(node.then_branch), else_branch: (node.else_branch) .map(|it| ((it).0, Box::new(f.fold_expr(*(it).1)))), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_index(f: &mut F, node: crate::ExprIndex) -> crate::ExprIndex where F: Fold + ?Sized, { crate::ExprIndex { attrs: fold_vec(node.attrs, f, F::fold_attribute), expr: Box::new(f.fold_expr(*node.expr)), bracket_token: node.bracket_token, index: Box::new(f.fold_expr(*node.index)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_infer(f: &mut F, node: crate::ExprInfer) -> crate::ExprInfer where F: Fold + ?Sized, { crate::ExprInfer { attrs: fold_vec(node.attrs, f, F::fold_attribute), underscore_token: node.underscore_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_let(f: &mut F, node: crate::ExprLet) -> crate::ExprLet where F: Fold + ?Sized, { crate::ExprLet { attrs: fold_vec(node.attrs, f, F::fold_attribute), let_token: node.let_token, pat: Box::new(f.fold_pat(*node.pat)), eq_token: node.eq_token, expr: Box::new(f.fold_expr(*node.expr)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_lit(f: &mut F, node: crate::ExprLit) -> crate::ExprLit where F: Fold + ?Sized, { crate::ExprLit { attrs: fold_vec(node.attrs, f, F::fold_attribute), lit: f.fold_lit(node.lit), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_loop(f: &mut F, node: crate::ExprLoop) -> crate::ExprLoop where F: Fold + ?Sized, { crate::ExprLoop { attrs: fold_vec(node.attrs, f, F::fold_attribute), label: (node.label).map(|it| f.fold_label(it)), loop_token: node.loop_token, body: f.fold_block(node.body), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_macro(f: &mut F, node: crate::ExprMacro) -> crate::ExprMacro where F: Fold + ?Sized, { crate::ExprMacro { attrs: fold_vec(node.attrs, f, F::fold_attribute), mac: f.fold_macro(node.mac), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_match(f: &mut F, node: crate::ExprMatch) -> crate::ExprMatch where F: Fold + ?Sized, { crate::ExprMatch { attrs: fold_vec(node.attrs, f, F::fold_attribute), match_token: node.match_token, expr: Box::new(f.fold_expr(*node.expr)), brace_token: node.brace_token, arms: fold_vec(node.arms, f, F::fold_arm), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_method_call( f: &mut F, node: crate::ExprMethodCall, ) -> crate::ExprMethodCall where F: Fold + ?Sized, { crate::ExprMethodCall { attrs: fold_vec(node.attrs, f, F::fold_attribute), receiver: Box::new(f.fold_expr(*node.receiver)), dot_token: node.dot_token, method: f.fold_ident(node.method), turbofish: (node.turbofish) .map(|it| f.fold_angle_bracketed_generic_arguments(it)), paren_token: node.paren_token, args: crate::punctuated::fold(node.args, f, F::fold_expr), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_paren(f: &mut F, node: crate::ExprParen) -> crate::ExprParen where F: Fold + ?Sized, { crate::ExprParen { attrs: fold_vec(node.attrs, f, F::fold_attribute), paren_token: node.paren_token, expr: Box::new(f.fold_expr(*node.expr)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_path(f: &mut F, node: crate::ExprPath) -> crate::ExprPath where F: Fold + ?Sized, { crate::ExprPath { attrs: fold_vec(node.attrs, f, F::fold_attribute), qself: (node.qself).map(|it| f.fold_qself(it)), path: f.fold_path(node.path), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_range(f: &mut F, node: crate::ExprRange) -> crate::ExprRange where F: Fold + ?Sized, { crate::ExprRange { attrs: fold_vec(node.attrs, f, F::fold_attribute), start: (node.start).map(|it| Box::new(f.fold_expr(*it))), limits: f.fold_range_limits(node.limits), end: (node.end).map(|it| Box::new(f.fold_expr(*it))), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_reference( f: &mut F, node: crate::ExprReference, ) -> crate::ExprReference where F: Fold + ?Sized, { crate::ExprReference { attrs: fold_vec(node.attrs, f, F::fold_attribute), and_token: node.and_token, mutability: node.mutability, expr: Box::new(f.fold_expr(*node.expr)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_repeat(f: &mut F, node: crate::ExprRepeat) -> crate::ExprRepeat where F: Fold + ?Sized, { crate::ExprRepeat { attrs: fold_vec(node.attrs, f, F::fold_attribute), bracket_token: node.bracket_token, expr: Box::new(f.fold_expr(*node.expr)), semi_token: node.semi_token, len: Box::new(f.fold_expr(*node.len)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_return(f: &mut F, node: crate::ExprReturn) -> crate::ExprReturn where F: Fold + ?Sized, { crate::ExprReturn { attrs: fold_vec(node.attrs, f, F::fold_attribute), return_token: node.return_token, expr: (node.expr).map(|it| Box::new(f.fold_expr(*it))), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_struct(f: &mut F, node: crate::ExprStruct) -> crate::ExprStruct where F: Fold + ?Sized, { crate::ExprStruct { attrs: fold_vec(node.attrs, f, F::fold_attribute), qself: (node.qself).map(|it| f.fold_qself(it)), path: f.fold_path(node.path), brace_token: node.brace_token, fields: crate::punctuated::fold(node.fields, f, F::fold_field_value), dot2_token: node.dot2_token, rest: (node.rest).map(|it| Box::new(f.fold_expr(*it))), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_try(f: &mut F, node: crate::ExprTry) -> crate::ExprTry where F: Fold + ?Sized, { crate::ExprTry { attrs: fold_vec(node.attrs, f, F::fold_attribute), expr: Box::new(f.fold_expr(*node.expr)), question_token: node.question_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_try_block( f: &mut F, node: crate::ExprTryBlock, ) -> crate::ExprTryBlock where F: Fold + ?Sized, { crate::ExprTryBlock { attrs: fold_vec(node.attrs, f, F::fold_attribute), try_token: node.try_token, block: f.fold_block(node.block), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_tuple(f: &mut F, node: crate::ExprTuple) -> crate::ExprTuple where F: Fold + ?Sized, { crate::ExprTuple { attrs: fold_vec(node.attrs, f, F::fold_attribute), paren_token: node.paren_token, elems: crate::punctuated::fold(node.elems, f, F::fold_expr), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_expr_unary(f: &mut F, node: crate::ExprUnary) -> crate::ExprUnary where F: Fold + ?Sized, { crate::ExprUnary { attrs: fold_vec(node.attrs, f, F::fold_attribute), op: f.fold_un_op(node.op), expr: Box::new(f.fold_expr(*node.expr)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_unsafe(f: &mut F, node: crate::ExprUnsafe) -> crate::ExprUnsafe where F: Fold + ?Sized, { crate::ExprUnsafe { attrs: fold_vec(node.attrs, f, F::fold_attribute), unsafe_token: node.unsafe_token, block: f.fold_block(node.block), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_while(f: &mut F, node: crate::ExprWhile) -> crate::ExprWhile where F: Fold + ?Sized, { crate::ExprWhile { attrs: fold_vec(node.attrs, f, F::fold_attribute), label: (node.label).map(|it| f.fold_label(it)), while_token: node.while_token, cond: Box::new(f.fold_expr(*node.cond)), body: f.fold_block(node.body), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_expr_yield(f: &mut F, node: crate::ExprYield) -> crate::ExprYield where F: Fold + ?Sized, { crate::ExprYield { attrs: fold_vec(node.attrs, f, F::fold_attribute), yield_token: node.yield_token, expr: (node.expr).map(|it| Box::new(f.fold_expr(*it))), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_field(f: &mut F, node: crate::Field) -> crate::Field where F: Fold + ?Sized, { crate::Field { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), mutability: f.fold_field_mutability(node.mutability), ident: (node.ident).map(|it| f.fold_ident(it)), colon_token: node.colon_token, ty: f.fold_type(node.ty), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_field_mutability( f: &mut F, node: crate::FieldMutability, ) -> crate::FieldMutability where F: Fold + ?Sized, { match node { crate::FieldMutability::None => crate::FieldMutability::None, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_field_pat(f: &mut F, node: crate::FieldPat) -> crate::FieldPat where F: Fold + ?Sized, { crate::FieldPat { attrs: fold_vec(node.attrs, f, F::fold_attribute), member: f.fold_member(node.member), colon_token: node.colon_token, pat: Box::new(f.fold_pat(*node.pat)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_field_value(f: &mut F, node: crate::FieldValue) -> crate::FieldValue where F: Fold + ?Sized, { crate::FieldValue { attrs: fold_vec(node.attrs, f, F::fold_attribute), member: f.fold_member(node.member), colon_token: node.colon_token, expr: f.fold_expr(node.expr), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_fields(f: &mut F, node: crate::Fields) -> crate::Fields where F: Fold + ?Sized, { match node { crate::Fields::Named(_binding_0) => { crate::Fields::Named(f.fold_fields_named(_binding_0)) } crate::Fields::Unnamed(_binding_0) => { crate::Fields::Unnamed(f.fold_fields_unnamed(_binding_0)) } crate::Fields::Unit => crate::Fields::Unit, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_fields_named(f: &mut F, node: crate::FieldsNamed) -> crate::FieldsNamed where F: Fold + ?Sized, { crate::FieldsNamed { brace_token: node.brace_token, named: crate::punctuated::fold(node.named, f, F::fold_field), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_fields_unnamed( f: &mut F, node: crate::FieldsUnnamed, ) -> crate::FieldsUnnamed where F: Fold + ?Sized, { crate::FieldsUnnamed { paren_token: node.paren_token, unnamed: crate::punctuated::fold(node.unnamed, f, F::fold_field), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_file(f: &mut F, node: crate::File) -> crate::File where F: Fold + ?Sized, { crate::File { shebang: node.shebang, attrs: fold_vec(node.attrs, f, F::fold_attribute), items: fold_vec(node.items, f, F::fold_item), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_fn_arg(f: &mut F, node: crate::FnArg) -> crate::FnArg where F: Fold + ?Sized, { match node { crate::FnArg::Receiver(_binding_0) => { crate::FnArg::Receiver(f.fold_receiver(_binding_0)) } crate::FnArg::Typed(_binding_0) => { crate::FnArg::Typed(f.fold_pat_type(_binding_0)) } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_foreign_item(f: &mut F, node: crate::ForeignItem) -> crate::ForeignItem where F: Fold + ?Sized, { match node { crate::ForeignItem::Fn(_binding_0) => { crate::ForeignItem::Fn(f.fold_foreign_item_fn(_binding_0)) } crate::ForeignItem::Static(_binding_0) => { crate::ForeignItem::Static(f.fold_foreign_item_static(_binding_0)) } crate::ForeignItem::Type(_binding_0) => { crate::ForeignItem::Type(f.fold_foreign_item_type(_binding_0)) } crate::ForeignItem::Macro(_binding_0) => { crate::ForeignItem::Macro(f.fold_foreign_item_macro(_binding_0)) } crate::ForeignItem::Verbatim(_binding_0) => { crate::ForeignItem::Verbatim(_binding_0) } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_foreign_item_fn( f: &mut F, node: crate::ForeignItemFn, ) -> crate::ForeignItemFn where F: Fold + ?Sized, { crate::ForeignItemFn { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), sig: f.fold_signature(node.sig), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_foreign_item_macro( f: &mut F, node: crate::ForeignItemMacro, ) -> crate::ForeignItemMacro where F: Fold + ?Sized, { crate::ForeignItemMacro { attrs: fold_vec(node.attrs, f, F::fold_attribute), mac: f.fold_macro(node.mac), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_foreign_item_static( f: &mut F, node: crate::ForeignItemStatic, ) -> crate::ForeignItemStatic where F: Fold + ?Sized, { crate::ForeignItemStatic { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), static_token: node.static_token, mutability: f.fold_static_mutability(node.mutability), ident: f.fold_ident(node.ident), colon_token: node.colon_token, ty: Box::new(f.fold_type(*node.ty)), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_foreign_item_type( f: &mut F, node: crate::ForeignItemType, ) -> crate::ForeignItemType where F: Fold + ?Sized, { crate::ForeignItemType { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), type_token: node.type_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), semi_token: node.semi_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_generic_argument( f: &mut F, node: crate::GenericArgument, ) -> crate::GenericArgument where F: Fold + ?Sized, { match node { crate::GenericArgument::Lifetime(_binding_0) => { crate::GenericArgument::Lifetime(f.fold_lifetime(_binding_0)) } crate::GenericArgument::Type(_binding_0) => { crate::GenericArgument::Type(f.fold_type(_binding_0)) } crate::GenericArgument::Const(_binding_0) => { crate::GenericArgument::Const(f.fold_expr(_binding_0)) } crate::GenericArgument::AssocType(_binding_0) => { crate::GenericArgument::AssocType(f.fold_assoc_type(_binding_0)) } crate::GenericArgument::AssocConst(_binding_0) => { crate::GenericArgument::AssocConst(f.fold_assoc_const(_binding_0)) } crate::GenericArgument::Constraint(_binding_0) => { crate::GenericArgument::Constraint(f.fold_constraint(_binding_0)) } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_generic_param(f: &mut F, node: crate::GenericParam) -> crate::GenericParam where F: Fold + ?Sized, { match node { crate::GenericParam::Lifetime(_binding_0) => { crate::GenericParam::Lifetime(f.fold_lifetime_param(_binding_0)) } crate::GenericParam::Type(_binding_0) => { crate::GenericParam::Type(f.fold_type_param(_binding_0)) } crate::GenericParam::Const(_binding_0) => { crate::GenericParam::Const(f.fold_const_param(_binding_0)) } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_generics(f: &mut F, node: crate::Generics) -> crate::Generics where F: Fold + ?Sized, { crate::Generics { lt_token: node.lt_token, params: crate::punctuated::fold(node.params, f, F::fold_generic_param), gt_token: node.gt_token, where_clause: (node.where_clause).map(|it| f.fold_where_clause(it)), } } pub fn fold_ident(f: &mut F, node: proc_macro2::Ident) -> proc_macro2::Ident where F: Fold + ?Sized, { let mut node = node; let span = f.fold_span(node.span()); node.set_span(span); node } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_impl_item(f: &mut F, node: crate::ImplItem) -> crate::ImplItem where F: Fold + ?Sized, { match node { crate::ImplItem::Const(_binding_0) => { crate::ImplItem::Const(f.fold_impl_item_const(_binding_0)) } crate::ImplItem::Fn(_binding_0) => { crate::ImplItem::Fn(f.fold_impl_item_fn(_binding_0)) } crate::ImplItem::Type(_binding_0) => { crate::ImplItem::Type(f.fold_impl_item_type(_binding_0)) } crate::ImplItem::Macro(_binding_0) => { crate::ImplItem::Macro(f.fold_impl_item_macro(_binding_0)) } crate::ImplItem::Verbatim(_binding_0) => crate::ImplItem::Verbatim(_binding_0), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_impl_item_const( f: &mut F, node: crate::ImplItemConst, ) -> crate::ImplItemConst where F: Fold + ?Sized, { crate::ImplItemConst { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), defaultness: node.defaultness, const_token: node.const_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), colon_token: node.colon_token, ty: f.fold_type(node.ty), eq_token: node.eq_token, expr: f.fold_expr(node.expr), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_impl_item_fn(f: &mut F, node: crate::ImplItemFn) -> crate::ImplItemFn where F: Fold + ?Sized, { crate::ImplItemFn { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), defaultness: node.defaultness, sig: f.fold_signature(node.sig), block: f.fold_block(node.block), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_impl_item_macro( f: &mut F, node: crate::ImplItemMacro, ) -> crate::ImplItemMacro where F: Fold + ?Sized, { crate::ImplItemMacro { attrs: fold_vec(node.attrs, f, F::fold_attribute), mac: f.fold_macro(node.mac), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_impl_item_type( f: &mut F, node: crate::ImplItemType, ) -> crate::ImplItemType where F: Fold + ?Sized, { crate::ImplItemType { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), defaultness: node.defaultness, type_token: node.type_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), eq_token: node.eq_token, ty: f.fold_type(node.ty), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_impl_restriction( f: &mut F, node: crate::ImplRestriction, ) -> crate::ImplRestriction where F: Fold + ?Sized, { match node {} } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_index(f: &mut F, node: crate::Index) -> crate::Index where F: Fold + ?Sized, { crate::Index { index: node.index, span: f.fold_span(node.span), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item(f: &mut F, node: crate::Item) -> crate::Item where F: Fold + ?Sized, { match node { crate::Item::Const(_binding_0) => { crate::Item::Const(f.fold_item_const(_binding_0)) } crate::Item::Enum(_binding_0) => crate::Item::Enum(f.fold_item_enum(_binding_0)), crate::Item::ExternCrate(_binding_0) => { crate::Item::ExternCrate(f.fold_item_extern_crate(_binding_0)) } crate::Item::Fn(_binding_0) => crate::Item::Fn(f.fold_item_fn(_binding_0)), crate::Item::ForeignMod(_binding_0) => { crate::Item::ForeignMod(f.fold_item_foreign_mod(_binding_0)) } crate::Item::Impl(_binding_0) => crate::Item::Impl(f.fold_item_impl(_binding_0)), crate::Item::Macro(_binding_0) => { crate::Item::Macro(f.fold_item_macro(_binding_0)) } crate::Item::Mod(_binding_0) => crate::Item::Mod(f.fold_item_mod(_binding_0)), crate::Item::Static(_binding_0) => { crate::Item::Static(f.fold_item_static(_binding_0)) } crate::Item::Struct(_binding_0) => { crate::Item::Struct(f.fold_item_struct(_binding_0)) } crate::Item::Trait(_binding_0) => { crate::Item::Trait(f.fold_item_trait(_binding_0)) } crate::Item::TraitAlias(_binding_0) => { crate::Item::TraitAlias(f.fold_item_trait_alias(_binding_0)) } crate::Item::Type(_binding_0) => crate::Item::Type(f.fold_item_type(_binding_0)), crate::Item::Union(_binding_0) => { crate::Item::Union(f.fold_item_union(_binding_0)) } crate::Item::Use(_binding_0) => crate::Item::Use(f.fold_item_use(_binding_0)), crate::Item::Verbatim(_binding_0) => crate::Item::Verbatim(_binding_0), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_const(f: &mut F, node: crate::ItemConst) -> crate::ItemConst where F: Fold + ?Sized, { crate::ItemConst { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), const_token: node.const_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), colon_token: node.colon_token, ty: Box::new(f.fold_type(*node.ty)), eq_token: node.eq_token, expr: Box::new(f.fold_expr(*node.expr)), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_enum(f: &mut F, node: crate::ItemEnum) -> crate::ItemEnum where F: Fold + ?Sized, { crate::ItemEnum { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), enum_token: node.enum_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), brace_token: node.brace_token, variants: crate::punctuated::fold(node.variants, f, F::fold_variant), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_extern_crate( f: &mut F, node: crate::ItemExternCrate, ) -> crate::ItemExternCrate where F: Fold + ?Sized, { crate::ItemExternCrate { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), extern_token: node.extern_token, crate_token: node.crate_token, ident: f.fold_ident(node.ident), rename: (node.rename).map(|it| ((it).0, f.fold_ident((it).1))), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_fn(f: &mut F, node: crate::ItemFn) -> crate::ItemFn where F: Fold + ?Sized, { crate::ItemFn { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), sig: f.fold_signature(node.sig), block: Box::new(f.fold_block(*node.block)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_foreign_mod( f: &mut F, node: crate::ItemForeignMod, ) -> crate::ItemForeignMod where F: Fold + ?Sized, { crate::ItemForeignMod { attrs: fold_vec(node.attrs, f, F::fold_attribute), unsafety: node.unsafety, abi: f.fold_abi(node.abi), brace_token: node.brace_token, items: fold_vec(node.items, f, F::fold_foreign_item), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_impl(f: &mut F, node: crate::ItemImpl) -> crate::ItemImpl where F: Fold + ?Sized, { crate::ItemImpl { attrs: fold_vec(node.attrs, f, F::fold_attribute), defaultness: node.defaultness, unsafety: node.unsafety, impl_token: node.impl_token, generics: f.fold_generics(node.generics), trait_: (node.trait_).map(|it| ((it).0, f.fold_path((it).1), (it).2)), self_ty: Box::new(f.fold_type(*node.self_ty)), brace_token: node.brace_token, items: fold_vec(node.items, f, F::fold_impl_item), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_macro(f: &mut F, node: crate::ItemMacro) -> crate::ItemMacro where F: Fold + ?Sized, { crate::ItemMacro { attrs: fold_vec(node.attrs, f, F::fold_attribute), ident: (node.ident).map(|it| f.fold_ident(it)), mac: f.fold_macro(node.mac), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_mod(f: &mut F, node: crate::ItemMod) -> crate::ItemMod where F: Fold + ?Sized, { crate::ItemMod { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), unsafety: node.unsafety, mod_token: node.mod_token, ident: f.fold_ident(node.ident), content: (node.content).map(|it| ((it).0, fold_vec((it).1, f, F::fold_item))), semi: node.semi, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_static(f: &mut F, node: crate::ItemStatic) -> crate::ItemStatic where F: Fold + ?Sized, { crate::ItemStatic { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), static_token: node.static_token, mutability: f.fold_static_mutability(node.mutability), ident: f.fold_ident(node.ident), colon_token: node.colon_token, ty: Box::new(f.fold_type(*node.ty)), eq_token: node.eq_token, expr: Box::new(f.fold_expr(*node.expr)), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_struct(f: &mut F, node: crate::ItemStruct) -> crate::ItemStruct where F: Fold + ?Sized, { crate::ItemStruct { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), struct_token: node.struct_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), fields: f.fold_fields(node.fields), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_trait(f: &mut F, node: crate::ItemTrait) -> crate::ItemTrait where F: Fold + ?Sized, { crate::ItemTrait { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), unsafety: node.unsafety, auto_token: node.auto_token, restriction: (node.restriction).map(|it| f.fold_impl_restriction(it)), trait_token: node.trait_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), colon_token: node.colon_token, supertraits: crate::punctuated::fold( node.supertraits, f, F::fold_type_param_bound, ), brace_token: node.brace_token, items: fold_vec(node.items, f, F::fold_trait_item), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_trait_alias( f: &mut F, node: crate::ItemTraitAlias, ) -> crate::ItemTraitAlias where F: Fold + ?Sized, { crate::ItemTraitAlias { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), trait_token: node.trait_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), eq_token: node.eq_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_type(f: &mut F, node: crate::ItemType) -> crate::ItemType where F: Fold + ?Sized, { crate::ItemType { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), type_token: node.type_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), eq_token: node.eq_token, ty: Box::new(f.fold_type(*node.ty)), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_union(f: &mut F, node: crate::ItemUnion) -> crate::ItemUnion where F: Fold + ?Sized, { crate::ItemUnion { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), union_token: node.union_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), fields: f.fold_fields_named(node.fields), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_item_use(f: &mut F, node: crate::ItemUse) -> crate::ItemUse where F: Fold + ?Sized, { crate::ItemUse { attrs: fold_vec(node.attrs, f, F::fold_attribute), vis: f.fold_visibility(node.vis), use_token: node.use_token, leading_colon: node.leading_colon, tree: f.fold_use_tree(node.tree), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_label(f: &mut F, node: crate::Label) -> crate::Label where F: Fold + ?Sized, { crate::Label { name: f.fold_lifetime(node.name), colon_token: node.colon_token, } } pub fn fold_lifetime(f: &mut F, node: crate::Lifetime) -> crate::Lifetime where F: Fold + ?Sized, { crate::Lifetime { apostrophe: f.fold_span(node.apostrophe), ident: f.fold_ident(node.ident), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_lifetime_param( f: &mut F, node: crate::LifetimeParam, ) -> crate::LifetimeParam where F: Fold + ?Sized, { crate::LifetimeParam { attrs: fold_vec(node.attrs, f, F::fold_attribute), lifetime: f.fold_lifetime(node.lifetime), colon_token: node.colon_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_lifetime), } } pub fn fold_lit(f: &mut F, node: crate::Lit) -> crate::Lit where F: Fold + ?Sized, { match node { crate::Lit::Str(_binding_0) => crate::Lit::Str(f.fold_lit_str(_binding_0)), crate::Lit::ByteStr(_binding_0) => { crate::Lit::ByteStr(f.fold_lit_byte_str(_binding_0)) } crate::Lit::CStr(_binding_0) => crate::Lit::CStr(f.fold_lit_cstr(_binding_0)), crate::Lit::Byte(_binding_0) => crate::Lit::Byte(f.fold_lit_byte(_binding_0)), crate::Lit::Char(_binding_0) => crate::Lit::Char(f.fold_lit_char(_binding_0)), crate::Lit::Int(_binding_0) => crate::Lit::Int(f.fold_lit_int(_binding_0)), crate::Lit::Float(_binding_0) => crate::Lit::Float(f.fold_lit_float(_binding_0)), crate::Lit::Bool(_binding_0) => crate::Lit::Bool(f.fold_lit_bool(_binding_0)), crate::Lit::Verbatim(_binding_0) => crate::Lit::Verbatim(_binding_0), } } pub fn fold_lit_bool(f: &mut F, node: crate::LitBool) -> crate::LitBool where F: Fold + ?Sized, { crate::LitBool { value: node.value, span: f.fold_span(node.span), } } pub fn fold_lit_byte(f: &mut F, node: crate::LitByte) -> crate::LitByte where F: Fold + ?Sized, { let span = f.fold_span(node.span()); let mut node = node; node.set_span(span); node } pub fn fold_lit_byte_str(f: &mut F, node: crate::LitByteStr) -> crate::LitByteStr where F: Fold + ?Sized, { let span = f.fold_span(node.span()); let mut node = node; node.set_span(span); node } pub fn fold_lit_cstr(f: &mut F, node: crate::LitCStr) -> crate::LitCStr where F: Fold + ?Sized, { let span = f.fold_span(node.span()); let mut node = node; node.set_span(span); node } pub fn fold_lit_char(f: &mut F, node: crate::LitChar) -> crate::LitChar where F: Fold + ?Sized, { let span = f.fold_span(node.span()); let mut node = node; node.set_span(span); node } pub fn fold_lit_float(f: &mut F, node: crate::LitFloat) -> crate::LitFloat where F: Fold + ?Sized, { let span = f.fold_span(node.span()); let mut node = node; node.set_span(span); node } pub fn fold_lit_int(f: &mut F, node: crate::LitInt) -> crate::LitInt where F: Fold + ?Sized, { let span = f.fold_span(node.span()); let mut node = node; node.set_span(span); node } pub fn fold_lit_str(f: &mut F, node: crate::LitStr) -> crate::LitStr where F: Fold + ?Sized, { let span = f.fold_span(node.span()); let mut node = node; node.set_span(span); node } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_local(f: &mut F, node: crate::Local) -> crate::Local where F: Fold + ?Sized, { crate::Local { attrs: fold_vec(node.attrs, f, F::fold_attribute), let_token: node.let_token, pat: f.fold_pat(node.pat), init: (node.init).map(|it| f.fold_local_init(it)), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_local_init(f: &mut F, node: crate::LocalInit) -> crate::LocalInit where F: Fold + ?Sized, { crate::LocalInit { eq_token: node.eq_token, expr: Box::new(f.fold_expr(*node.expr)), diverge: (node.diverge).map(|it| ((it).0, Box::new(f.fold_expr(*(it).1)))), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_macro(f: &mut F, node: crate::Macro) -> crate::Macro where F: Fold + ?Sized, { crate::Macro { path: f.fold_path(node.path), bang_token: node.bang_token, delimiter: f.fold_macro_delimiter(node.delimiter), tokens: node.tokens, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_macro_delimiter( f: &mut F, node: crate::MacroDelimiter, ) -> crate::MacroDelimiter where F: Fold + ?Sized, { match node { crate::MacroDelimiter::Paren(_binding_0) => { crate::MacroDelimiter::Paren(_binding_0) } crate::MacroDelimiter::Brace(_binding_0) => { crate::MacroDelimiter::Brace(_binding_0) } crate::MacroDelimiter::Bracket(_binding_0) => { crate::MacroDelimiter::Bracket(_binding_0) } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_member(f: &mut F, node: crate::Member) -> crate::Member where F: Fold + ?Sized, { match node { crate::Member::Named(_binding_0) => { crate::Member::Named(f.fold_ident(_binding_0)) } crate::Member::Unnamed(_binding_0) => { crate::Member::Unnamed(f.fold_index(_binding_0)) } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_meta(f: &mut F, node: crate::Meta) -> crate::Meta where F: Fold + ?Sized, { match node { crate::Meta::Path(_binding_0) => crate::Meta::Path(f.fold_path(_binding_0)), crate::Meta::List(_binding_0) => crate::Meta::List(f.fold_meta_list(_binding_0)), crate::Meta::NameValue(_binding_0) => { crate::Meta::NameValue(f.fold_meta_name_value(_binding_0)) } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_meta_list(f: &mut F, node: crate::MetaList) -> crate::MetaList where F: Fold + ?Sized, { crate::MetaList { path: f.fold_path(node.path), delimiter: f.fold_macro_delimiter(node.delimiter), tokens: node.tokens, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_meta_name_value( f: &mut F, node: crate::MetaNameValue, ) -> crate::MetaNameValue where F: Fold + ?Sized, { crate::MetaNameValue { path: f.fold_path(node.path), eq_token: node.eq_token, value: f.fold_expr(node.value), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_parenthesized_generic_arguments( f: &mut F, node: crate::ParenthesizedGenericArguments, ) -> crate::ParenthesizedGenericArguments where F: Fold + ?Sized, { crate::ParenthesizedGenericArguments { paren_token: node.paren_token, inputs: crate::punctuated::fold(node.inputs, f, F::fold_type), output: f.fold_return_type(node.output), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat(f: &mut F, node: crate::Pat) -> crate::Pat where F: Fold + ?Sized, { match node { crate::Pat::Const(_binding_0) => crate::Pat::Const(f.fold_expr_const(_binding_0)), crate::Pat::Ident(_binding_0) => crate::Pat::Ident(f.fold_pat_ident(_binding_0)), crate::Pat::Lit(_binding_0) => crate::Pat::Lit(f.fold_expr_lit(_binding_0)), crate::Pat::Macro(_binding_0) => crate::Pat::Macro(f.fold_expr_macro(_binding_0)), crate::Pat::Or(_binding_0) => crate::Pat::Or(f.fold_pat_or(_binding_0)), crate::Pat::Paren(_binding_0) => crate::Pat::Paren(f.fold_pat_paren(_binding_0)), crate::Pat::Path(_binding_0) => crate::Pat::Path(f.fold_expr_path(_binding_0)), crate::Pat::Range(_binding_0) => crate::Pat::Range(f.fold_expr_range(_binding_0)), crate::Pat::Reference(_binding_0) => { crate::Pat::Reference(f.fold_pat_reference(_binding_0)) } crate::Pat::Rest(_binding_0) => crate::Pat::Rest(f.fold_pat_rest(_binding_0)), crate::Pat::Slice(_binding_0) => crate::Pat::Slice(f.fold_pat_slice(_binding_0)), crate::Pat::Struct(_binding_0) => { crate::Pat::Struct(f.fold_pat_struct(_binding_0)) } crate::Pat::Tuple(_binding_0) => crate::Pat::Tuple(f.fold_pat_tuple(_binding_0)), crate::Pat::TupleStruct(_binding_0) => { crate::Pat::TupleStruct(f.fold_pat_tuple_struct(_binding_0)) } crate::Pat::Type(_binding_0) => crate::Pat::Type(f.fold_pat_type(_binding_0)), crate::Pat::Verbatim(_binding_0) => crate::Pat::Verbatim(_binding_0), crate::Pat::Wild(_binding_0) => crate::Pat::Wild(f.fold_pat_wild(_binding_0)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_ident(f: &mut F, node: crate::PatIdent) -> crate::PatIdent where F: Fold + ?Sized, { crate::PatIdent { attrs: fold_vec(node.attrs, f, F::fold_attribute), by_ref: node.by_ref, mutability: node.mutability, ident: f.fold_ident(node.ident), subpat: (node.subpat).map(|it| ((it).0, Box::new(f.fold_pat(*(it).1)))), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_or(f: &mut F, node: crate::PatOr) -> crate::PatOr where F: Fold + ?Sized, { crate::PatOr { attrs: fold_vec(node.attrs, f, F::fold_attribute), leading_vert: node.leading_vert, cases: crate::punctuated::fold(node.cases, f, F::fold_pat), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_paren(f: &mut F, node: crate::PatParen) -> crate::PatParen where F: Fold + ?Sized, { crate::PatParen { attrs: fold_vec(node.attrs, f, F::fold_attribute), paren_token: node.paren_token, pat: Box::new(f.fold_pat(*node.pat)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_reference(f: &mut F, node: crate::PatReference) -> crate::PatReference where F: Fold + ?Sized, { crate::PatReference { attrs: fold_vec(node.attrs, f, F::fold_attribute), and_token: node.and_token, mutability: node.mutability, pat: Box::new(f.fold_pat(*node.pat)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_rest(f: &mut F, node: crate::PatRest) -> crate::PatRest where F: Fold + ?Sized, { crate::PatRest { attrs: fold_vec(node.attrs, f, F::fold_attribute), dot2_token: node.dot2_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_slice(f: &mut F, node: crate::PatSlice) -> crate::PatSlice where F: Fold + ?Sized, { crate::PatSlice { attrs: fold_vec(node.attrs, f, F::fold_attribute), bracket_token: node.bracket_token, elems: crate::punctuated::fold(node.elems, f, F::fold_pat), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_struct(f: &mut F, node: crate::PatStruct) -> crate::PatStruct where F: Fold + ?Sized, { crate::PatStruct { attrs: fold_vec(node.attrs, f, F::fold_attribute), qself: (node.qself).map(|it| f.fold_qself(it)), path: f.fold_path(node.path), brace_token: node.brace_token, fields: crate::punctuated::fold(node.fields, f, F::fold_field_pat), rest: (node.rest).map(|it| f.fold_pat_rest(it)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_tuple(f: &mut F, node: crate::PatTuple) -> crate::PatTuple where F: Fold + ?Sized, { crate::PatTuple { attrs: fold_vec(node.attrs, f, F::fold_attribute), paren_token: node.paren_token, elems: crate::punctuated::fold(node.elems, f, F::fold_pat), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_tuple_struct( f: &mut F, node: crate::PatTupleStruct, ) -> crate::PatTupleStruct where F: Fold + ?Sized, { crate::PatTupleStruct { attrs: fold_vec(node.attrs, f, F::fold_attribute), qself: (node.qself).map(|it| f.fold_qself(it)), path: f.fold_path(node.path), paren_token: node.paren_token, elems: crate::punctuated::fold(node.elems, f, F::fold_pat), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_type(f: &mut F, node: crate::PatType) -> crate::PatType where F: Fold + ?Sized, { crate::PatType { attrs: fold_vec(node.attrs, f, F::fold_attribute), pat: Box::new(f.fold_pat(*node.pat)), colon_token: node.colon_token, ty: Box::new(f.fold_type(*node.ty)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_pat_wild(f: &mut F, node: crate::PatWild) -> crate::PatWild where F: Fold + ?Sized, { crate::PatWild { attrs: fold_vec(node.attrs, f, F::fold_attribute), underscore_token: node.underscore_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_path(f: &mut F, node: crate::Path) -> crate::Path where F: Fold + ?Sized, { crate::Path { leading_colon: node.leading_colon, segments: crate::punctuated::fold(node.segments, f, F::fold_path_segment), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_path_arguments( f: &mut F, node: crate::PathArguments, ) -> crate::PathArguments where F: Fold + ?Sized, { match node { crate::PathArguments::None => crate::PathArguments::None, crate::PathArguments::AngleBracketed(_binding_0) => { crate::PathArguments::AngleBracketed( f.fold_angle_bracketed_generic_arguments(_binding_0), ) } crate::PathArguments::Parenthesized(_binding_0) => { crate::PathArguments::Parenthesized( f.fold_parenthesized_generic_arguments(_binding_0), ) } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_path_segment(f: &mut F, node: crate::PathSegment) -> crate::PathSegment where F: Fold + ?Sized, { crate::PathSegment { ident: f.fold_ident(node.ident), arguments: f.fold_path_arguments(node.arguments), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_predicate_lifetime( f: &mut F, node: crate::PredicateLifetime, ) -> crate::PredicateLifetime where F: Fold + ?Sized, { crate::PredicateLifetime { lifetime: f.fold_lifetime(node.lifetime), colon_token: node.colon_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_lifetime), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_predicate_type( f: &mut F, node: crate::PredicateType, ) -> crate::PredicateType where F: Fold + ?Sized, { crate::PredicateType { lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)), bounded_ty: f.fold_type(node.bounded_ty), colon_token: node.colon_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_qself(f: &mut F, node: crate::QSelf) -> crate::QSelf where F: Fold + ?Sized, { crate::QSelf { lt_token: node.lt_token, ty: Box::new(f.fold_type(*node.ty)), position: node.position, as_token: node.as_token, gt_token: node.gt_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_range_limits(f: &mut F, node: crate::RangeLimits) -> crate::RangeLimits where F: Fold + ?Sized, { match node { crate::RangeLimits::HalfOpen(_binding_0) => { crate::RangeLimits::HalfOpen(_binding_0) } crate::RangeLimits::Closed(_binding_0) => crate::RangeLimits::Closed(_binding_0), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_receiver(f: &mut F, node: crate::Receiver) -> crate::Receiver where F: Fold + ?Sized, { crate::Receiver { attrs: fold_vec(node.attrs, f, F::fold_attribute), reference: (node.reference) .map(|it| ((it).0, ((it).1).map(|it| f.fold_lifetime(it)))), mutability: node.mutability, self_token: node.self_token, colon_token: node.colon_token, ty: Box::new(f.fold_type(*node.ty)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_return_type(f: &mut F, node: crate::ReturnType) -> crate::ReturnType where F: Fold + ?Sized, { match node { crate::ReturnType::Default => crate::ReturnType::Default, crate::ReturnType::Type(_binding_0, _binding_1) => { crate::ReturnType::Type(_binding_0, Box::new(f.fold_type(*_binding_1))) } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_signature(f: &mut F, node: crate::Signature) -> crate::Signature where F: Fold + ?Sized, { crate::Signature { constness: node.constness, asyncness: node.asyncness, unsafety: node.unsafety, abi: (node.abi).map(|it| f.fold_abi(it)), fn_token: node.fn_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), paren_token: node.paren_token, inputs: crate::punctuated::fold(node.inputs, f, F::fold_fn_arg), variadic: (node.variadic).map(|it| f.fold_variadic(it)), output: f.fold_return_type(node.output), } } pub fn fold_span(f: &mut F, node: proc_macro2::Span) -> proc_macro2::Span where F: Fold + ?Sized, { node } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_static_mutability( f: &mut F, node: crate::StaticMutability, ) -> crate::StaticMutability where F: Fold + ?Sized, { match node { crate::StaticMutability::Mut(_binding_0) => { crate::StaticMutability::Mut(_binding_0) } crate::StaticMutability::None => crate::StaticMutability::None, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_stmt(f: &mut F, node: crate::Stmt) -> crate::Stmt where F: Fold + ?Sized, { match node { crate::Stmt::Local(_binding_0) => crate::Stmt::Local(f.fold_local(_binding_0)), crate::Stmt::Item(_binding_0) => crate::Stmt::Item(f.fold_item(_binding_0)), crate::Stmt::Expr(_binding_0, _binding_1) => { crate::Stmt::Expr(f.fold_expr(_binding_0), _binding_1) } crate::Stmt::Macro(_binding_0) => { crate::Stmt::Macro(f.fold_stmt_macro(_binding_0)) } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_stmt_macro(f: &mut F, node: crate::StmtMacro) -> crate::StmtMacro where F: Fold + ?Sized, { crate::StmtMacro { attrs: fold_vec(node.attrs, f, F::fold_attribute), mac: f.fold_macro(node.mac), semi_token: node.semi_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_trait_bound(f: &mut F, node: crate::TraitBound) -> crate::TraitBound where F: Fold + ?Sized, { crate::TraitBound { paren_token: node.paren_token, modifier: f.fold_trait_bound_modifier(node.modifier), lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)), path: f.fold_path(node.path), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_trait_bound_modifier( f: &mut F, node: crate::TraitBoundModifier, ) -> crate::TraitBoundModifier where F: Fold + ?Sized, { match node { crate::TraitBoundModifier::None => crate::TraitBoundModifier::None, crate::TraitBoundModifier::Maybe(_binding_0) => { crate::TraitBoundModifier::Maybe(_binding_0) } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_trait_item(f: &mut F, node: crate::TraitItem) -> crate::TraitItem where F: Fold + ?Sized, { match node { crate::TraitItem::Const(_binding_0) => { crate::TraitItem::Const(f.fold_trait_item_const(_binding_0)) } crate::TraitItem::Fn(_binding_0) => { crate::TraitItem::Fn(f.fold_trait_item_fn(_binding_0)) } crate::TraitItem::Type(_binding_0) => { crate::TraitItem::Type(f.fold_trait_item_type(_binding_0)) } crate::TraitItem::Macro(_binding_0) => { crate::TraitItem::Macro(f.fold_trait_item_macro(_binding_0)) } crate::TraitItem::Verbatim(_binding_0) => crate::TraitItem::Verbatim(_binding_0), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_trait_item_const( f: &mut F, node: crate::TraitItemConst, ) -> crate::TraitItemConst where F: Fold + ?Sized, { crate::TraitItemConst { attrs: fold_vec(node.attrs, f, F::fold_attribute), const_token: node.const_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), colon_token: node.colon_token, ty: f.fold_type(node.ty), default: (node.default).map(|it| ((it).0, f.fold_expr((it).1))), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_trait_item_fn(f: &mut F, node: crate::TraitItemFn) -> crate::TraitItemFn where F: Fold + ?Sized, { crate::TraitItemFn { attrs: fold_vec(node.attrs, f, F::fold_attribute), sig: f.fold_signature(node.sig), default: (node.default).map(|it| f.fold_block(it)), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_trait_item_macro( f: &mut F, node: crate::TraitItemMacro, ) -> crate::TraitItemMacro where F: Fold + ?Sized, { crate::TraitItemMacro { attrs: fold_vec(node.attrs, f, F::fold_attribute), mac: f.fold_macro(node.mac), semi_token: node.semi_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_trait_item_type( f: &mut F, node: crate::TraitItemType, ) -> crate::TraitItemType where F: Fold + ?Sized, { crate::TraitItemType { attrs: fold_vec(node.attrs, f, F::fold_attribute), type_token: node.type_token, ident: f.fold_ident(node.ident), generics: f.fold_generics(node.generics), colon_token: node.colon_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound), default: (node.default).map(|it| ((it).0, f.fold_type((it).1))), semi_token: node.semi_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type(f: &mut F, node: crate::Type) -> crate::Type where F: Fold + ?Sized, { match node { crate::Type::Array(_binding_0) => { crate::Type::Array(f.fold_type_array(_binding_0)) } crate::Type::BareFn(_binding_0) => { crate::Type::BareFn(f.fold_type_bare_fn(_binding_0)) } crate::Type::Group(_binding_0) => { crate::Type::Group(f.fold_type_group(_binding_0)) } crate::Type::ImplTrait(_binding_0) => { crate::Type::ImplTrait(f.fold_type_impl_trait(_binding_0)) } crate::Type::Infer(_binding_0) => { crate::Type::Infer(f.fold_type_infer(_binding_0)) } crate::Type::Macro(_binding_0) => { crate::Type::Macro(f.fold_type_macro(_binding_0)) } crate::Type::Never(_binding_0) => { crate::Type::Never(f.fold_type_never(_binding_0)) } crate::Type::Paren(_binding_0) => { crate::Type::Paren(f.fold_type_paren(_binding_0)) } crate::Type::Path(_binding_0) => crate::Type::Path(f.fold_type_path(_binding_0)), crate::Type::Ptr(_binding_0) => crate::Type::Ptr(f.fold_type_ptr(_binding_0)), crate::Type::Reference(_binding_0) => { crate::Type::Reference(f.fold_type_reference(_binding_0)) } crate::Type::Slice(_binding_0) => { crate::Type::Slice(f.fold_type_slice(_binding_0)) } crate::Type::TraitObject(_binding_0) => { crate::Type::TraitObject(f.fold_type_trait_object(_binding_0)) } crate::Type::Tuple(_binding_0) => { crate::Type::Tuple(f.fold_type_tuple(_binding_0)) } crate::Type::Verbatim(_binding_0) => crate::Type::Verbatim(_binding_0), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_array(f: &mut F, node: crate::TypeArray) -> crate::TypeArray where F: Fold + ?Sized, { crate::TypeArray { bracket_token: node.bracket_token, elem: Box::new(f.fold_type(*node.elem)), semi_token: node.semi_token, len: f.fold_expr(node.len), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_bare_fn(f: &mut F, node: crate::TypeBareFn) -> crate::TypeBareFn where F: Fold + ?Sized, { crate::TypeBareFn { lifetimes: (node.lifetimes).map(|it| f.fold_bound_lifetimes(it)), unsafety: node.unsafety, abi: (node.abi).map(|it| f.fold_abi(it)), fn_token: node.fn_token, paren_token: node.paren_token, inputs: crate::punctuated::fold(node.inputs, f, F::fold_bare_fn_arg), variadic: (node.variadic).map(|it| f.fold_bare_variadic(it)), output: f.fold_return_type(node.output), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_group(f: &mut F, node: crate::TypeGroup) -> crate::TypeGroup where F: Fold + ?Sized, { crate::TypeGroup { group_token: node.group_token, elem: Box::new(f.fold_type(*node.elem)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_impl_trait( f: &mut F, node: crate::TypeImplTrait, ) -> crate::TypeImplTrait where F: Fold + ?Sized, { crate::TypeImplTrait { impl_token: node.impl_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_infer(f: &mut F, node: crate::TypeInfer) -> crate::TypeInfer where F: Fold + ?Sized, { crate::TypeInfer { underscore_token: node.underscore_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_macro(f: &mut F, node: crate::TypeMacro) -> crate::TypeMacro where F: Fold + ?Sized, { crate::TypeMacro { mac: f.fold_macro(node.mac), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_never(f: &mut F, node: crate::TypeNever) -> crate::TypeNever where F: Fold + ?Sized, { crate::TypeNever { bang_token: node.bang_token, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_param(f: &mut F, node: crate::TypeParam) -> crate::TypeParam where F: Fold + ?Sized, { crate::TypeParam { attrs: fold_vec(node.attrs, f, F::fold_attribute), ident: f.fold_ident(node.ident), colon_token: node.colon_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound), eq_token: node.eq_token, default: (node.default).map(|it| f.fold_type(it)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_param_bound( f: &mut F, node: crate::TypeParamBound, ) -> crate::TypeParamBound where F: Fold + ?Sized, { match node { crate::TypeParamBound::Trait(_binding_0) => { crate::TypeParamBound::Trait(f.fold_trait_bound(_binding_0)) } crate::TypeParamBound::Lifetime(_binding_0) => { crate::TypeParamBound::Lifetime(f.fold_lifetime(_binding_0)) } crate::TypeParamBound::Verbatim(_binding_0) => { crate::TypeParamBound::Verbatim(_binding_0) } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_paren(f: &mut F, node: crate::TypeParen) -> crate::TypeParen where F: Fold + ?Sized, { crate::TypeParen { paren_token: node.paren_token, elem: Box::new(f.fold_type(*node.elem)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_path(f: &mut F, node: crate::TypePath) -> crate::TypePath where F: Fold + ?Sized, { crate::TypePath { qself: (node.qself).map(|it| f.fold_qself(it)), path: f.fold_path(node.path), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_ptr(f: &mut F, node: crate::TypePtr) -> crate::TypePtr where F: Fold + ?Sized, { crate::TypePtr { star_token: node.star_token, const_token: node.const_token, mutability: node.mutability, elem: Box::new(f.fold_type(*node.elem)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_reference( f: &mut F, node: crate::TypeReference, ) -> crate::TypeReference where F: Fold + ?Sized, { crate::TypeReference { and_token: node.and_token, lifetime: (node.lifetime).map(|it| f.fold_lifetime(it)), mutability: node.mutability, elem: Box::new(f.fold_type(*node.elem)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_slice(f: &mut F, node: crate::TypeSlice) -> crate::TypeSlice where F: Fold + ?Sized, { crate::TypeSlice { bracket_token: node.bracket_token, elem: Box::new(f.fold_type(*node.elem)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_trait_object( f: &mut F, node: crate::TypeTraitObject, ) -> crate::TypeTraitObject where F: Fold + ?Sized, { crate::TypeTraitObject { dyn_token: node.dyn_token, bounds: crate::punctuated::fold(node.bounds, f, F::fold_type_param_bound), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_type_tuple(f: &mut F, node: crate::TypeTuple) -> crate::TypeTuple where F: Fold + ?Sized, { crate::TypeTuple { paren_token: node.paren_token, elems: crate::punctuated::fold(node.elems, f, F::fold_type), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_un_op(f: &mut F, node: crate::UnOp) -> crate::UnOp where F: Fold + ?Sized, { match node { crate::UnOp::Deref(_binding_0) => crate::UnOp::Deref(_binding_0), crate::UnOp::Not(_binding_0) => crate::UnOp::Not(_binding_0), crate::UnOp::Neg(_binding_0) => crate::UnOp::Neg(_binding_0), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_use_glob(f: &mut F, node: crate::UseGlob) -> crate::UseGlob where F: Fold + ?Sized, { crate::UseGlob { star_token: node.star_token, } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_use_group(f: &mut F, node: crate::UseGroup) -> crate::UseGroup where F: Fold + ?Sized, { crate::UseGroup { brace_token: node.brace_token, items: crate::punctuated::fold(node.items, f, F::fold_use_tree), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_use_name(f: &mut F, node: crate::UseName) -> crate::UseName where F: Fold + ?Sized, { crate::UseName { ident: f.fold_ident(node.ident), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_use_path(f: &mut F, node: crate::UsePath) -> crate::UsePath where F: Fold + ?Sized, { crate::UsePath { ident: f.fold_ident(node.ident), colon2_token: node.colon2_token, tree: Box::new(f.fold_use_tree(*node.tree)), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_use_rename(f: &mut F, node: crate::UseRename) -> crate::UseRename where F: Fold + ?Sized, { crate::UseRename { ident: f.fold_ident(node.ident), as_token: node.as_token, rename: f.fold_ident(node.rename), } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_use_tree(f: &mut F, node: crate::UseTree) -> crate::UseTree where F: Fold + ?Sized, { match node { crate::UseTree::Path(_binding_0) => { crate::UseTree::Path(f.fold_use_path(_binding_0)) } crate::UseTree::Name(_binding_0) => { crate::UseTree::Name(f.fold_use_name(_binding_0)) } crate::UseTree::Rename(_binding_0) => { crate::UseTree::Rename(f.fold_use_rename(_binding_0)) } crate::UseTree::Glob(_binding_0) => { crate::UseTree::Glob(f.fold_use_glob(_binding_0)) } crate::UseTree::Group(_binding_0) => { crate::UseTree::Group(f.fold_use_group(_binding_0)) } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn fold_variadic(f: &mut F, node: crate::Variadic) -> crate::Variadic where F: Fold + ?Sized, { crate::Variadic { attrs: fold_vec(node.attrs, f, F::fold_attribute), pat: (node.pat).map(|it| (Box::new(f.fold_pat(*(it).0)), (it).1)), dots: node.dots, comma: node.comma, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_variant(f: &mut F, node: crate::Variant) -> crate::Variant where F: Fold + ?Sized, { crate::Variant { attrs: fold_vec(node.attrs, f, F::fold_attribute), ident: f.fold_ident(node.ident), fields: f.fold_fields(node.fields), discriminant: (node.discriminant).map(|it| ((it).0, f.fold_expr((it).1))), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_vis_restricted( f: &mut F, node: crate::VisRestricted, ) -> crate::VisRestricted where F: Fold + ?Sized, { crate::VisRestricted { pub_token: node.pub_token, paren_token: node.paren_token, in_token: node.in_token, path: Box::new(f.fold_path(*node.path)), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_visibility(f: &mut F, node: crate::Visibility) -> crate::Visibility where F: Fold + ?Sized, { match node { crate::Visibility::Public(_binding_0) => crate::Visibility::Public(_binding_0), crate::Visibility::Restricted(_binding_0) => { crate::Visibility::Restricted(f.fold_vis_restricted(_binding_0)) } crate::Visibility::Inherited => crate::Visibility::Inherited, } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_where_clause(f: &mut F, node: crate::WhereClause) -> crate::WhereClause where F: Fold + ?Sized, { crate::WhereClause { where_token: node.where_token, predicates: crate::punctuated::fold(node.predicates, f, F::fold_where_predicate), } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn fold_where_predicate( f: &mut F, node: crate::WherePredicate, ) -> crate::WherePredicate where F: Fold + ?Sized, { match node { crate::WherePredicate::Lifetime(_binding_0) => { crate::WherePredicate::Lifetime(f.fold_predicate_lifetime(_binding_0)) } crate::WherePredicate::Type(_binding_0) => { crate::WherePredicate::Type(f.fold_predicate_type(_binding_0)) } } } #[cfg(any(feature = "derive", feature = "full"))] fn fold_vec(vec: Vec, fold: &mut V, mut f: F) -> Vec where V: ?Sized, F: FnMut(&mut V, T) -> T, { vec.into_iter().map(|it| f(fold, it)).collect() } syn/src/gen/debug.rs0000644000175000017500000036266014661133735015363 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #![allow(unknown_lints, non_local_definitions)] use std::fmt::{self, Debug}; #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Abi { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Abi"); formatter.field("extern_token", &self.extern_token); formatter.field("name", &self.name); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::AngleBracketedGenericArguments { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "AngleBracketedGenericArguments") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::AngleBracketedGenericArguments { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("colon2_token", &self.colon2_token); formatter.field("lt_token", &self.lt_token); formatter.field("args", &self.args); formatter.field("gt_token", &self.gt_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Arm { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Arm"); formatter.field("attrs", &self.attrs); formatter.field("pat", &self.pat); formatter.field("guard", &self.guard); formatter.field("fat_arrow_token", &self.fat_arrow_token); formatter.field("body", &self.body); formatter.field("comma", &self.comma); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::AssocConst { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("AssocConst"); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("eq_token", &self.eq_token); formatter.field("value", &self.value); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::AssocType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("AssocType"); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("eq_token", &self.eq_token); formatter.field("ty", &self.ty); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::AttrStyle { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("AttrStyle::")?; match self { crate::AttrStyle::Outer => formatter.write_str("Outer"), crate::AttrStyle::Inner(v0) => { let mut formatter = formatter.debug_tuple("Inner"); formatter.field(v0); formatter.finish() } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Attribute { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Attribute"); formatter.field("pound_token", &self.pound_token); formatter.field("style", &self.style); formatter.field("bracket_token", &self.bracket_token); formatter.field("meta", &self.meta); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::BareFnArg { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("BareFnArg"); formatter.field("attrs", &self.attrs); formatter.field("name", &self.name); formatter.field("ty", &self.ty); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::BareVariadic { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("BareVariadic"); formatter.field("attrs", &self.attrs); formatter.field("name", &self.name); formatter.field("dots", &self.dots); formatter.field("comma", &self.comma); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::BinOp { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("BinOp::")?; match self { crate::BinOp::Add(v0) => { let mut formatter = formatter.debug_tuple("Add"); formatter.field(v0); formatter.finish() } crate::BinOp::Sub(v0) => { let mut formatter = formatter.debug_tuple("Sub"); formatter.field(v0); formatter.finish() } crate::BinOp::Mul(v0) => { let mut formatter = formatter.debug_tuple("Mul"); formatter.field(v0); formatter.finish() } crate::BinOp::Div(v0) => { let mut formatter = formatter.debug_tuple("Div"); formatter.field(v0); formatter.finish() } crate::BinOp::Rem(v0) => { let mut formatter = formatter.debug_tuple("Rem"); formatter.field(v0); formatter.finish() } crate::BinOp::And(v0) => { let mut formatter = formatter.debug_tuple("And"); formatter.field(v0); formatter.finish() } crate::BinOp::Or(v0) => { let mut formatter = formatter.debug_tuple("Or"); formatter.field(v0); formatter.finish() } crate::BinOp::BitXor(v0) => { let mut formatter = formatter.debug_tuple("BitXor"); formatter.field(v0); formatter.finish() } crate::BinOp::BitAnd(v0) => { let mut formatter = formatter.debug_tuple("BitAnd"); formatter.field(v0); formatter.finish() } crate::BinOp::BitOr(v0) => { let mut formatter = formatter.debug_tuple("BitOr"); formatter.field(v0); formatter.finish() } crate::BinOp::Shl(v0) => { let mut formatter = formatter.debug_tuple("Shl"); formatter.field(v0); formatter.finish() } crate::BinOp::Shr(v0) => { let mut formatter = formatter.debug_tuple("Shr"); formatter.field(v0); formatter.finish() } crate::BinOp::Eq(v0) => { let mut formatter = formatter.debug_tuple("Eq"); formatter.field(v0); formatter.finish() } crate::BinOp::Lt(v0) => { let mut formatter = formatter.debug_tuple("Lt"); formatter.field(v0); formatter.finish() } crate::BinOp::Le(v0) => { let mut formatter = formatter.debug_tuple("Le"); formatter.field(v0); formatter.finish() } crate::BinOp::Ne(v0) => { let mut formatter = formatter.debug_tuple("Ne"); formatter.field(v0); formatter.finish() } crate::BinOp::Ge(v0) => { let mut formatter = formatter.debug_tuple("Ge"); formatter.field(v0); formatter.finish() } crate::BinOp::Gt(v0) => { let mut formatter = formatter.debug_tuple("Gt"); formatter.field(v0); formatter.finish() } crate::BinOp::AddAssign(v0) => { let mut formatter = formatter.debug_tuple("AddAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::SubAssign(v0) => { let mut formatter = formatter.debug_tuple("SubAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::MulAssign(v0) => { let mut formatter = formatter.debug_tuple("MulAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::DivAssign(v0) => { let mut formatter = formatter.debug_tuple("DivAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::RemAssign(v0) => { let mut formatter = formatter.debug_tuple("RemAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::BitXorAssign(v0) => { let mut formatter = formatter.debug_tuple("BitXorAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::BitAndAssign(v0) => { let mut formatter = formatter.debug_tuple("BitAndAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::BitOrAssign(v0) => { let mut formatter = formatter.debug_tuple("BitOrAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::ShlAssign(v0) => { let mut formatter = formatter.debug_tuple("ShlAssign"); formatter.field(v0); formatter.finish() } crate::BinOp::ShrAssign(v0) => { let mut formatter = formatter.debug_tuple("ShrAssign"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Block { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Block"); formatter.field("brace_token", &self.brace_token); formatter.field("stmts", &self.stmts); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::BoundLifetimes { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("BoundLifetimes"); formatter.field("for_token", &self.for_token); formatter.field("lt_token", &self.lt_token); formatter.field("lifetimes", &self.lifetimes); formatter.field("gt_token", &self.gt_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ConstParam { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("ConstParam"); formatter.field("attrs", &self.attrs); formatter.field("const_token", &self.const_token); formatter.field("ident", &self.ident); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.field("eq_token", &self.eq_token); formatter.field("default", &self.default); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Constraint { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Constraint"); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("colon_token", &self.colon_token); formatter.field("bounds", &self.bounds); formatter.finish() } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Data { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Data::")?; match self { crate::Data::Struct(v0) => v0.debug(formatter, "Struct"), crate::Data::Enum(v0) => v0.debug(formatter, "Enum"), crate::Data::Union(v0) => v0.debug(formatter, "Union"), } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::DataEnum { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "DataEnum") } } #[cfg(feature = "derive")] impl crate::DataEnum { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("enum_token", &self.enum_token); formatter.field("brace_token", &self.brace_token); formatter.field("variants", &self.variants); formatter.finish() } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::DataStruct { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "DataStruct") } } #[cfg(feature = "derive")] impl crate::DataStruct { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("struct_token", &self.struct_token); formatter.field("fields", &self.fields); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::DataUnion { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "DataUnion") } } #[cfg(feature = "derive")] impl crate::DataUnion { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("union_token", &self.union_token); formatter.field("fields", &self.fields); formatter.finish() } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::DeriveInput { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("DeriveInput"); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("data", &self.data); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Expr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Expr::")?; match self { #[cfg(feature = "full")] crate::Expr::Array(v0) => v0.debug(formatter, "Array"), #[cfg(feature = "full")] crate::Expr::Assign(v0) => v0.debug(formatter, "Assign"), #[cfg(feature = "full")] crate::Expr::Async(v0) => v0.debug(formatter, "Async"), #[cfg(feature = "full")] crate::Expr::Await(v0) => v0.debug(formatter, "Await"), crate::Expr::Binary(v0) => v0.debug(formatter, "Binary"), #[cfg(feature = "full")] crate::Expr::Block(v0) => v0.debug(formatter, "Block"), #[cfg(feature = "full")] crate::Expr::Break(v0) => v0.debug(formatter, "Break"), crate::Expr::Call(v0) => v0.debug(formatter, "Call"), crate::Expr::Cast(v0) => v0.debug(formatter, "Cast"), #[cfg(feature = "full")] crate::Expr::Closure(v0) => v0.debug(formatter, "Closure"), #[cfg(feature = "full")] crate::Expr::Const(v0) => v0.debug(formatter, "Const"), #[cfg(feature = "full")] crate::Expr::Continue(v0) => v0.debug(formatter, "Continue"), crate::Expr::Field(v0) => v0.debug(formatter, "Field"), #[cfg(feature = "full")] crate::Expr::ForLoop(v0) => v0.debug(formatter, "ForLoop"), crate::Expr::Group(v0) => v0.debug(formatter, "Group"), #[cfg(feature = "full")] crate::Expr::If(v0) => v0.debug(formatter, "If"), crate::Expr::Index(v0) => v0.debug(formatter, "Index"), #[cfg(feature = "full")] crate::Expr::Infer(v0) => v0.debug(formatter, "Infer"), #[cfg(feature = "full")] crate::Expr::Let(v0) => v0.debug(formatter, "Let"), crate::Expr::Lit(v0) => v0.debug(formatter, "Lit"), #[cfg(feature = "full")] crate::Expr::Loop(v0) => v0.debug(formatter, "Loop"), crate::Expr::Macro(v0) => v0.debug(formatter, "Macro"), #[cfg(feature = "full")] crate::Expr::Match(v0) => v0.debug(formatter, "Match"), crate::Expr::MethodCall(v0) => v0.debug(formatter, "MethodCall"), crate::Expr::Paren(v0) => v0.debug(formatter, "Paren"), crate::Expr::Path(v0) => v0.debug(formatter, "Path"), #[cfg(feature = "full")] crate::Expr::Range(v0) => v0.debug(formatter, "Range"), crate::Expr::Reference(v0) => v0.debug(formatter, "Reference"), #[cfg(feature = "full")] crate::Expr::Repeat(v0) => v0.debug(formatter, "Repeat"), #[cfg(feature = "full")] crate::Expr::Return(v0) => v0.debug(formatter, "Return"), crate::Expr::Struct(v0) => v0.debug(formatter, "Struct"), #[cfg(feature = "full")] crate::Expr::Try(v0) => v0.debug(formatter, "Try"), #[cfg(feature = "full")] crate::Expr::TryBlock(v0) => v0.debug(formatter, "TryBlock"), #[cfg(feature = "full")] crate::Expr::Tuple(v0) => v0.debug(formatter, "Tuple"), crate::Expr::Unary(v0) => v0.debug(formatter, "Unary"), #[cfg(feature = "full")] crate::Expr::Unsafe(v0) => v0.debug(formatter, "Unsafe"), crate::Expr::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } #[cfg(feature = "full")] crate::Expr::While(v0) => v0.debug(formatter, "While"), #[cfg(feature = "full")] crate::Expr::Yield(v0) => v0.debug(formatter, "Yield"), #[cfg(not(feature = "full"))] _ => unreachable!(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprArray { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprArray") } } #[cfg(feature = "full")] impl crate::ExprArray { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("bracket_token", &self.bracket_token); formatter.field("elems", &self.elems); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprAssign { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprAssign") } } #[cfg(feature = "full")] impl crate::ExprAssign { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("left", &self.left); formatter.field("eq_token", &self.eq_token); formatter.field("right", &self.right); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprAsync { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprAsync") } } #[cfg(feature = "full")] impl crate::ExprAsync { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("async_token", &self.async_token); formatter.field("capture", &self.capture); formatter.field("block", &self.block); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprAwait { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprAwait") } } #[cfg(feature = "full")] impl crate::ExprAwait { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("base", &self.base); formatter.field("dot_token", &self.dot_token); formatter.field("await_token", &self.await_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprBinary { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprBinary") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprBinary { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("left", &self.left); formatter.field("op", &self.op); formatter.field("right", &self.right); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprBlock { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprBlock") } } #[cfg(feature = "full")] impl crate::ExprBlock { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("label", &self.label); formatter.field("block", &self.block); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprBreak { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprBreak") } } #[cfg(feature = "full")] impl crate::ExprBreak { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("break_token", &self.break_token); formatter.field("label", &self.label); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprCall { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprCall") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprCall { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("func", &self.func); formatter.field("paren_token", &self.paren_token); formatter.field("args", &self.args); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprCast { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprCast") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprCast { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("expr", &self.expr); formatter.field("as_token", &self.as_token); formatter.field("ty", &self.ty); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprClosure { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprClosure") } } #[cfg(feature = "full")] impl crate::ExprClosure { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("lifetimes", &self.lifetimes); formatter.field("constness", &self.constness); formatter.field("movability", &self.movability); formatter.field("asyncness", &self.asyncness); formatter.field("capture", &self.capture); formatter.field("or1_token", &self.or1_token); formatter.field("inputs", &self.inputs); formatter.field("or2_token", &self.or2_token); formatter.field("output", &self.output); formatter.field("body", &self.body); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprConst { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprConst") } } #[cfg(feature = "full")] impl crate::ExprConst { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("const_token", &self.const_token); formatter.field("block", &self.block); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprContinue { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprContinue") } } #[cfg(feature = "full")] impl crate::ExprContinue { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("continue_token", &self.continue_token); formatter.field("label", &self.label); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprField { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprField") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprField { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("base", &self.base); formatter.field("dot_token", &self.dot_token); formatter.field("member", &self.member); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprForLoop { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprForLoop") } } #[cfg(feature = "full")] impl crate::ExprForLoop { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("label", &self.label); formatter.field("for_token", &self.for_token); formatter.field("pat", &self.pat); formatter.field("in_token", &self.in_token); formatter.field("expr", &self.expr); formatter.field("body", &self.body); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprGroup { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprGroup") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprGroup { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("group_token", &self.group_token); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprIf { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprIf") } } #[cfg(feature = "full")] impl crate::ExprIf { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("if_token", &self.if_token); formatter.field("cond", &self.cond); formatter.field("then_branch", &self.then_branch); formatter.field("else_branch", &self.else_branch); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprIndex { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprIndex") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprIndex { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("expr", &self.expr); formatter.field("bracket_token", &self.bracket_token); formatter.field("index", &self.index); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprInfer { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprInfer") } } #[cfg(feature = "full")] impl crate::ExprInfer { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("underscore_token", &self.underscore_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprLet { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprLet") } } #[cfg(feature = "full")] impl crate::ExprLet { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("let_token", &self.let_token); formatter.field("pat", &self.pat); formatter.field("eq_token", &self.eq_token); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprLit { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprLit") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprLit { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("lit", &self.lit); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprLoop { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprLoop") } } #[cfg(feature = "full")] impl crate::ExprLoop { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("label", &self.label); formatter.field("loop_token", &self.loop_token); formatter.field("body", &self.body); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprMacro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprMacro") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprMacro { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("mac", &self.mac); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprMatch { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprMatch") } } #[cfg(feature = "full")] impl crate::ExprMatch { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("match_token", &self.match_token); formatter.field("expr", &self.expr); formatter.field("brace_token", &self.brace_token); formatter.field("arms", &self.arms); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprMethodCall { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprMethodCall") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprMethodCall { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("receiver", &self.receiver); formatter.field("dot_token", &self.dot_token); formatter.field("method", &self.method); formatter.field("turbofish", &self.turbofish); formatter.field("paren_token", &self.paren_token); formatter.field("args", &self.args); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprParen { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprParen") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprParen { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("paren_token", &self.paren_token); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprPath { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprPath") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprPath { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("qself", &self.qself); formatter.field("path", &self.path); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprRange { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprRange") } } #[cfg(feature = "full")] impl crate::ExprRange { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("start", &self.start); formatter.field("limits", &self.limits); formatter.field("end", &self.end); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprReference { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprReference") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprReference { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("and_token", &self.and_token); formatter.field("mutability", &self.mutability); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprRepeat { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprRepeat") } } #[cfg(feature = "full")] impl crate::ExprRepeat { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("bracket_token", &self.bracket_token); formatter.field("expr", &self.expr); formatter.field("semi_token", &self.semi_token); formatter.field("len", &self.len); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprReturn { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprReturn") } } #[cfg(feature = "full")] impl crate::ExprReturn { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("return_token", &self.return_token); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprStruct { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprStruct") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprStruct { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("qself", &self.qself); formatter.field("path", &self.path); formatter.field("brace_token", &self.brace_token); formatter.field("fields", &self.fields); formatter.field("dot2_token", &self.dot2_token); formatter.field("rest", &self.rest); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprTry { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprTry") } } #[cfg(feature = "full")] impl crate::ExprTry { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("expr", &self.expr); formatter.field("question_token", &self.question_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprTryBlock { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprTryBlock") } } #[cfg(feature = "full")] impl crate::ExprTryBlock { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("try_token", &self.try_token); formatter.field("block", &self.block); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprTuple { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprTuple") } } #[cfg(feature = "full")] impl crate::ExprTuple { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("paren_token", &self.paren_token); formatter.field("elems", &self.elems); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprUnary { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprUnary") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ExprUnary { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("op", &self.op); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprUnsafe { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprUnsafe") } } #[cfg(feature = "full")] impl crate::ExprUnsafe { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("unsafe_token", &self.unsafe_token); formatter.field("block", &self.block); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprWhile { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprWhile") } } #[cfg(feature = "full")] impl crate::ExprWhile { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("label", &self.label); formatter.field("while_token", &self.while_token); formatter.field("cond", &self.cond); formatter.field("body", &self.body); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ExprYield { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ExprYield") } } #[cfg(feature = "full")] impl crate::ExprYield { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("yield_token", &self.yield_token); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Field { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Field"); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("mutability", &self.mutability); formatter.field("ident", &self.ident); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FieldMutability { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("FieldMutability::")?; match self { crate::FieldMutability::None => formatter.write_str("None"), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FieldPat { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("FieldPat"); formatter.field("attrs", &self.attrs); formatter.field("member", &self.member); formatter.field("colon_token", &self.colon_token); formatter.field("pat", &self.pat); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FieldValue { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("FieldValue"); formatter.field("attrs", &self.attrs); formatter.field("member", &self.member); formatter.field("colon_token", &self.colon_token); formatter.field("expr", &self.expr); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Fields { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Fields::")?; match self { crate::Fields::Named(v0) => v0.debug(formatter, "Named"), crate::Fields::Unnamed(v0) => v0.debug(formatter, "Unnamed"), crate::Fields::Unit => formatter.write_str("Unit"), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FieldsNamed { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "FieldsNamed") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::FieldsNamed { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("brace_token", &self.brace_token); formatter.field("named", &self.named); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FieldsUnnamed { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "FieldsUnnamed") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::FieldsUnnamed { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("paren_token", &self.paren_token); formatter.field("unnamed", &self.unnamed); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::File { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("File"); formatter.field("shebang", &self.shebang); formatter.field("attrs", &self.attrs); formatter.field("items", &self.items); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::FnArg { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("FnArg::")?; match self { crate::FnArg::Receiver(v0) => { let mut formatter = formatter.debug_tuple("Receiver"); formatter.field(v0); formatter.finish() } crate::FnArg::Typed(v0) => { let mut formatter = formatter.debug_tuple("Typed"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ForeignItem { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("ForeignItem::")?; match self { crate::ForeignItem::Fn(v0) => v0.debug(formatter, "Fn"), crate::ForeignItem::Static(v0) => v0.debug(formatter, "Static"), crate::ForeignItem::Type(v0) => v0.debug(formatter, "Type"), crate::ForeignItem::Macro(v0) => v0.debug(formatter, "Macro"), crate::ForeignItem::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ForeignItemFn { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ForeignItemFn") } } #[cfg(feature = "full")] impl crate::ForeignItemFn { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("sig", &self.sig); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ForeignItemMacro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ForeignItemMacro") } } #[cfg(feature = "full")] impl crate::ForeignItemMacro { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("mac", &self.mac); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ForeignItemStatic { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ForeignItemStatic") } } #[cfg(feature = "full")] impl crate::ForeignItemStatic { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("static_token", &self.static_token); formatter.field("mutability", &self.mutability); formatter.field("ident", &self.ident); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ForeignItemType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ForeignItemType") } } #[cfg(feature = "full")] impl crate::ForeignItemType { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("type_token", &self.type_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::GenericArgument { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("GenericArgument::")?; match self { crate::GenericArgument::Lifetime(v0) => { let mut formatter = formatter.debug_tuple("Lifetime"); formatter.field(v0); formatter.finish() } crate::GenericArgument::Type(v0) => { let mut formatter = formatter.debug_tuple("Type"); formatter.field(v0); formatter.finish() } crate::GenericArgument::Const(v0) => { let mut formatter = formatter.debug_tuple("Const"); formatter.field(v0); formatter.finish() } crate::GenericArgument::AssocType(v0) => { let mut formatter = formatter.debug_tuple("AssocType"); formatter.field(v0); formatter.finish() } crate::GenericArgument::AssocConst(v0) => { let mut formatter = formatter.debug_tuple("AssocConst"); formatter.field(v0); formatter.finish() } crate::GenericArgument::Constraint(v0) => { let mut formatter = formatter.debug_tuple("Constraint"); formatter.field(v0); formatter.finish() } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::GenericParam { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("GenericParam::")?; match self { crate::GenericParam::Lifetime(v0) => { let mut formatter = formatter.debug_tuple("Lifetime"); formatter.field(v0); formatter.finish() } crate::GenericParam::Type(v0) => { let mut formatter = formatter.debug_tuple("Type"); formatter.field(v0); formatter.finish() } crate::GenericParam::Const(v0) => { let mut formatter = formatter.debug_tuple("Const"); formatter.field(v0); formatter.finish() } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Generics { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Generics"); formatter.field("lt_token", &self.lt_token); formatter.field("params", &self.params); formatter.field("gt_token", &self.gt_token); formatter.field("where_clause", &self.where_clause); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ImplItem { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("ImplItem::")?; match self { crate::ImplItem::Const(v0) => v0.debug(formatter, "Const"), crate::ImplItem::Fn(v0) => v0.debug(formatter, "Fn"), crate::ImplItem::Type(v0) => v0.debug(formatter, "Type"), crate::ImplItem::Macro(v0) => v0.debug(formatter, "Macro"), crate::ImplItem::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ImplItemConst { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ImplItemConst") } } #[cfg(feature = "full")] impl crate::ImplItemConst { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("defaultness", &self.defaultness); formatter.field("const_token", &self.const_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.field("eq_token", &self.eq_token); formatter.field("expr", &self.expr); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ImplItemFn { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ImplItemFn") } } #[cfg(feature = "full")] impl crate::ImplItemFn { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("defaultness", &self.defaultness); formatter.field("sig", &self.sig); formatter.field("block", &self.block); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ImplItemMacro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ImplItemMacro") } } #[cfg(feature = "full")] impl crate::ImplItemMacro { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("mac", &self.mac); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ImplItemType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ImplItemType") } } #[cfg(feature = "full")] impl crate::ImplItemType { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("defaultness", &self.defaultness); formatter.field("type_token", &self.type_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("eq_token", &self.eq_token); formatter.field("ty", &self.ty); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ImplRestriction { fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result { match *self {} } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Index { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Index"); formatter.field("index", &self.index); formatter.field("span", &self.span); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Item { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Item::")?; match self { crate::Item::Const(v0) => v0.debug(formatter, "Const"), crate::Item::Enum(v0) => v0.debug(formatter, "Enum"), crate::Item::ExternCrate(v0) => v0.debug(formatter, "ExternCrate"), crate::Item::Fn(v0) => v0.debug(formatter, "Fn"), crate::Item::ForeignMod(v0) => v0.debug(formatter, "ForeignMod"), crate::Item::Impl(v0) => v0.debug(formatter, "Impl"), crate::Item::Macro(v0) => v0.debug(formatter, "Macro"), crate::Item::Mod(v0) => v0.debug(formatter, "Mod"), crate::Item::Static(v0) => v0.debug(formatter, "Static"), crate::Item::Struct(v0) => v0.debug(formatter, "Struct"), crate::Item::Trait(v0) => v0.debug(formatter, "Trait"), crate::Item::TraitAlias(v0) => v0.debug(formatter, "TraitAlias"), crate::Item::Type(v0) => v0.debug(formatter, "Type"), crate::Item::Union(v0) => v0.debug(formatter, "Union"), crate::Item::Use(v0) => v0.debug(formatter, "Use"), crate::Item::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemConst { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemConst") } } #[cfg(feature = "full")] impl crate::ItemConst { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("const_token", &self.const_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.field("eq_token", &self.eq_token); formatter.field("expr", &self.expr); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemEnum { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemEnum") } } #[cfg(feature = "full")] impl crate::ItemEnum { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("enum_token", &self.enum_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("brace_token", &self.brace_token); formatter.field("variants", &self.variants); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemExternCrate { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemExternCrate") } } #[cfg(feature = "full")] impl crate::ItemExternCrate { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("extern_token", &self.extern_token); formatter.field("crate_token", &self.crate_token); formatter.field("ident", &self.ident); formatter.field("rename", &self.rename); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemFn { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemFn") } } #[cfg(feature = "full")] impl crate::ItemFn { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("sig", &self.sig); formatter.field("block", &self.block); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemForeignMod { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemForeignMod") } } #[cfg(feature = "full")] impl crate::ItemForeignMod { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("unsafety", &self.unsafety); formatter.field("abi", &self.abi); formatter.field("brace_token", &self.brace_token); formatter.field("items", &self.items); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemImpl { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemImpl") } } #[cfg(feature = "full")] impl crate::ItemImpl { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("defaultness", &self.defaultness); formatter.field("unsafety", &self.unsafety); formatter.field("impl_token", &self.impl_token); formatter.field("generics", &self.generics); formatter.field("trait_", &self.trait_); formatter.field("self_ty", &self.self_ty); formatter.field("brace_token", &self.brace_token); formatter.field("items", &self.items); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemMacro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemMacro") } } #[cfg(feature = "full")] impl crate::ItemMacro { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("ident", &self.ident); formatter.field("mac", &self.mac); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemMod { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemMod") } } #[cfg(feature = "full")] impl crate::ItemMod { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("unsafety", &self.unsafety); formatter.field("mod_token", &self.mod_token); formatter.field("ident", &self.ident); formatter.field("content", &self.content); formatter.field("semi", &self.semi); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemStatic { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemStatic") } } #[cfg(feature = "full")] impl crate::ItemStatic { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("static_token", &self.static_token); formatter.field("mutability", &self.mutability); formatter.field("ident", &self.ident); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.field("eq_token", &self.eq_token); formatter.field("expr", &self.expr); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemStruct { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemStruct") } } #[cfg(feature = "full")] impl crate::ItemStruct { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("struct_token", &self.struct_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("fields", &self.fields); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemTrait { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemTrait") } } #[cfg(feature = "full")] impl crate::ItemTrait { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("unsafety", &self.unsafety); formatter.field("auto_token", &self.auto_token); formatter.field("restriction", &self.restriction); formatter.field("trait_token", &self.trait_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("colon_token", &self.colon_token); formatter.field("supertraits", &self.supertraits); formatter.field("brace_token", &self.brace_token); formatter.field("items", &self.items); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemTraitAlias { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemTraitAlias") } } #[cfg(feature = "full")] impl crate::ItemTraitAlias { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("trait_token", &self.trait_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("eq_token", &self.eq_token); formatter.field("bounds", &self.bounds); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemType") } } #[cfg(feature = "full")] impl crate::ItemType { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("type_token", &self.type_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("eq_token", &self.eq_token); formatter.field("ty", &self.ty); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemUnion { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemUnion") } } #[cfg(feature = "full")] impl crate::ItemUnion { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("union_token", &self.union_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("fields", &self.fields); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ItemUse { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ItemUse") } } #[cfg(feature = "full")] impl crate::ItemUse { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("vis", &self.vis); formatter.field("use_token", &self.use_token); formatter.field("leading_colon", &self.leading_colon); formatter.field("tree", &self.tree); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Label { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Label"); formatter.field("name", &self.name); formatter.field("colon_token", &self.colon_token); formatter.finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Lifetime { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "Lifetime") } } impl crate::Lifetime { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("apostrophe", &self.apostrophe); formatter.field("ident", &self.ident); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::LifetimeParam { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("LifetimeParam"); formatter.field("attrs", &self.attrs); formatter.field("lifetime", &self.lifetime); formatter.field("colon_token", &self.colon_token); formatter.field("bounds", &self.bounds); formatter.finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Lit { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Lit::")?; match self { crate::Lit::Str(v0) => v0.debug(formatter, "Str"), crate::Lit::ByteStr(v0) => v0.debug(formatter, "ByteStr"), crate::Lit::CStr(v0) => v0.debug(formatter, "CStr"), crate::Lit::Byte(v0) => v0.debug(formatter, "Byte"), crate::Lit::Char(v0) => v0.debug(formatter, "Char"), crate::Lit::Int(v0) => v0.debug(formatter, "Int"), crate::Lit::Float(v0) => v0.debug(formatter, "Float"), crate::Lit::Bool(v0) => v0.debug(formatter, "Bool"), crate::Lit::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Local { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "Local") } } #[cfg(feature = "full")] impl crate::Local { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("let_token", &self.let_token); formatter.field("pat", &self.pat); formatter.field("init", &self.init); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::LocalInit { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("LocalInit"); formatter.field("eq_token", &self.eq_token); formatter.field("expr", &self.expr); formatter.field("diverge", &self.diverge); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Macro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Macro"); formatter.field("path", &self.path); formatter.field("bang_token", &self.bang_token); formatter.field("delimiter", &self.delimiter); formatter.field("tokens", &self.tokens); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::MacroDelimiter { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("MacroDelimiter::")?; match self { crate::MacroDelimiter::Paren(v0) => { let mut formatter = formatter.debug_tuple("Paren"); formatter.field(v0); formatter.finish() } crate::MacroDelimiter::Brace(v0) => { let mut formatter = formatter.debug_tuple("Brace"); formatter.field(v0); formatter.finish() } crate::MacroDelimiter::Bracket(v0) => { let mut formatter = formatter.debug_tuple("Bracket"); formatter.field(v0); formatter.finish() } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Member { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Member::")?; match self { crate::Member::Named(v0) => { let mut formatter = formatter.debug_tuple("Named"); formatter.field(v0); formatter.finish() } crate::Member::Unnamed(v0) => { let mut formatter = formatter.debug_tuple("Unnamed"); formatter.field(v0); formatter.finish() } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Meta { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Meta::")?; match self { crate::Meta::Path(v0) => v0.debug(formatter, "Path"), crate::Meta::List(v0) => v0.debug(formatter, "List"), crate::Meta::NameValue(v0) => v0.debug(formatter, "NameValue"), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::MetaList { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "MetaList") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::MetaList { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("path", &self.path); formatter.field("delimiter", &self.delimiter); formatter.field("tokens", &self.tokens); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::MetaNameValue { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "MetaNameValue") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::MetaNameValue { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("path", &self.path); formatter.field("eq_token", &self.eq_token); formatter.field("value", &self.value); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ParenthesizedGenericArguments { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "ParenthesizedGenericArguments") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::ParenthesizedGenericArguments { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("paren_token", &self.paren_token); formatter.field("inputs", &self.inputs); formatter.field("output", &self.output); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Pat { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Pat::")?; match self { crate::Pat::Const(v0) => v0.debug(formatter, "Const"), crate::Pat::Ident(v0) => v0.debug(formatter, "Ident"), crate::Pat::Lit(v0) => v0.debug(formatter, "Lit"), crate::Pat::Macro(v0) => v0.debug(formatter, "Macro"), crate::Pat::Or(v0) => v0.debug(formatter, "Or"), crate::Pat::Paren(v0) => v0.debug(formatter, "Paren"), crate::Pat::Path(v0) => v0.debug(formatter, "Path"), crate::Pat::Range(v0) => v0.debug(formatter, "Range"), crate::Pat::Reference(v0) => v0.debug(formatter, "Reference"), crate::Pat::Rest(v0) => v0.debug(formatter, "Rest"), crate::Pat::Slice(v0) => v0.debug(formatter, "Slice"), crate::Pat::Struct(v0) => v0.debug(formatter, "Struct"), crate::Pat::Tuple(v0) => v0.debug(formatter, "Tuple"), crate::Pat::TupleStruct(v0) => v0.debug(formatter, "TupleStruct"), crate::Pat::Type(v0) => v0.debug(formatter, "Type"), crate::Pat::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } crate::Pat::Wild(v0) => v0.debug(formatter, "Wild"), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatIdent { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatIdent") } } #[cfg(feature = "full")] impl crate::PatIdent { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("by_ref", &self.by_ref); formatter.field("mutability", &self.mutability); formatter.field("ident", &self.ident); formatter.field("subpat", &self.subpat); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatOr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatOr") } } #[cfg(feature = "full")] impl crate::PatOr { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("leading_vert", &self.leading_vert); formatter.field("cases", &self.cases); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatParen { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatParen") } } #[cfg(feature = "full")] impl crate::PatParen { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("paren_token", &self.paren_token); formatter.field("pat", &self.pat); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatReference { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatReference") } } #[cfg(feature = "full")] impl crate::PatReference { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("and_token", &self.and_token); formatter.field("mutability", &self.mutability); formatter.field("pat", &self.pat); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatRest { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatRest") } } #[cfg(feature = "full")] impl crate::PatRest { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("dot2_token", &self.dot2_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatSlice { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatSlice") } } #[cfg(feature = "full")] impl crate::PatSlice { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("bracket_token", &self.bracket_token); formatter.field("elems", &self.elems); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatStruct { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatStruct") } } #[cfg(feature = "full")] impl crate::PatStruct { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("qself", &self.qself); formatter.field("path", &self.path); formatter.field("brace_token", &self.brace_token); formatter.field("fields", &self.fields); formatter.field("rest", &self.rest); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatTuple { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatTuple") } } #[cfg(feature = "full")] impl crate::PatTuple { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("paren_token", &self.paren_token); formatter.field("elems", &self.elems); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatTupleStruct { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatTupleStruct") } } #[cfg(feature = "full")] impl crate::PatTupleStruct { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("qself", &self.qself); formatter.field("path", &self.path); formatter.field("paren_token", &self.paren_token); formatter.field("elems", &self.elems); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatType") } } #[cfg(feature = "full")] impl crate::PatType { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("pat", &self.pat); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PatWild { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "PatWild") } } #[cfg(feature = "full")] impl crate::PatWild { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("underscore_token", &self.underscore_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Path { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "Path") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::Path { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("leading_colon", &self.leading_colon); formatter.field("segments", &self.segments); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PathArguments { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("PathArguments::")?; match self { crate::PathArguments::None => formatter.write_str("None"), crate::PathArguments::AngleBracketed(v0) => { v0.debug(formatter, "AngleBracketed") } crate::PathArguments::Parenthesized(v0) => { v0.debug(formatter, "Parenthesized") } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PathSegment { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PathSegment"); formatter.field("ident", &self.ident); formatter.field("arguments", &self.arguments); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PredicateLifetime { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PredicateLifetime"); formatter.field("lifetime", &self.lifetime); formatter.field("colon_token", &self.colon_token); formatter.field("bounds", &self.bounds); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::PredicateType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("PredicateType"); formatter.field("lifetimes", &self.lifetimes); formatter.field("bounded_ty", &self.bounded_ty); formatter.field("colon_token", &self.colon_token); formatter.field("bounds", &self.bounds); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::QSelf { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("QSelf"); formatter.field("lt_token", &self.lt_token); formatter.field("ty", &self.ty); formatter.field("position", &self.position); formatter.field("as_token", &self.as_token); formatter.field("gt_token", &self.gt_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::RangeLimits { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("RangeLimits::")?; match self { crate::RangeLimits::HalfOpen(v0) => { let mut formatter = formatter.debug_tuple("HalfOpen"); formatter.field(v0); formatter.finish() } crate::RangeLimits::Closed(v0) => { let mut formatter = formatter.debug_tuple("Closed"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Receiver { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Receiver"); formatter.field("attrs", &self.attrs); formatter.field("reference", &self.reference); formatter.field("mutability", &self.mutability); formatter.field("self_token", &self.self_token); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::ReturnType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("ReturnType::")?; match self { crate::ReturnType::Default => formatter.write_str("Default"), crate::ReturnType::Type(v0, v1) => { let mut formatter = formatter.debug_tuple("Type"); formatter.field(v0); formatter.field(v1); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Signature { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Signature"); formatter.field("constness", &self.constness); formatter.field("asyncness", &self.asyncness); formatter.field("unsafety", &self.unsafety); formatter.field("abi", &self.abi); formatter.field("fn_token", &self.fn_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("paren_token", &self.paren_token); formatter.field("inputs", &self.inputs); formatter.field("variadic", &self.variadic); formatter.field("output", &self.output); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::StaticMutability { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("StaticMutability::")?; match self { crate::StaticMutability::Mut(v0) => { let mut formatter = formatter.debug_tuple("Mut"); formatter.field(v0); formatter.finish() } crate::StaticMutability::None => formatter.write_str("None"), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Stmt { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Stmt::")?; match self { crate::Stmt::Local(v0) => v0.debug(formatter, "Local"), crate::Stmt::Item(v0) => { let mut formatter = formatter.debug_tuple("Item"); formatter.field(v0); formatter.finish() } crate::Stmt::Expr(v0, v1) => { let mut formatter = formatter.debug_tuple("Expr"); formatter.field(v0); formatter.field(v1); formatter.finish() } crate::Stmt::Macro(v0) => v0.debug(formatter, "Macro"), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::StmtMacro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "StmtMacro") } } #[cfg(feature = "full")] impl crate::StmtMacro { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("mac", &self.mac); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TraitBound { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TraitBound"); formatter.field("paren_token", &self.paren_token); formatter.field("modifier", &self.modifier); formatter.field("lifetimes", &self.lifetimes); formatter.field("path", &self.path); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TraitBoundModifier { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("TraitBoundModifier::")?; match self { crate::TraitBoundModifier::None => formatter.write_str("None"), crate::TraitBoundModifier::Maybe(v0) => { let mut formatter = formatter.debug_tuple("Maybe"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TraitItem { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("TraitItem::")?; match self { crate::TraitItem::Const(v0) => v0.debug(formatter, "Const"), crate::TraitItem::Fn(v0) => v0.debug(formatter, "Fn"), crate::TraitItem::Type(v0) => v0.debug(formatter, "Type"), crate::TraitItem::Macro(v0) => v0.debug(formatter, "Macro"), crate::TraitItem::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TraitItemConst { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TraitItemConst") } } #[cfg(feature = "full")] impl crate::TraitItemConst { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("const_token", &self.const_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("colon_token", &self.colon_token); formatter.field("ty", &self.ty); formatter.field("default", &self.default); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TraitItemFn { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TraitItemFn") } } #[cfg(feature = "full")] impl crate::TraitItemFn { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("sig", &self.sig); formatter.field("default", &self.default); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TraitItemMacro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TraitItemMacro") } } #[cfg(feature = "full")] impl crate::TraitItemMacro { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("mac", &self.mac); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TraitItemType { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TraitItemType") } } #[cfg(feature = "full")] impl crate::TraitItemType { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("attrs", &self.attrs); formatter.field("type_token", &self.type_token); formatter.field("ident", &self.ident); formatter.field("generics", &self.generics); formatter.field("colon_token", &self.colon_token); formatter.field("bounds", &self.bounds); formatter.field("default", &self.default); formatter.field("semi_token", &self.semi_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Type { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Type::")?; match self { crate::Type::Array(v0) => v0.debug(formatter, "Array"), crate::Type::BareFn(v0) => v0.debug(formatter, "BareFn"), crate::Type::Group(v0) => v0.debug(formatter, "Group"), crate::Type::ImplTrait(v0) => v0.debug(formatter, "ImplTrait"), crate::Type::Infer(v0) => v0.debug(formatter, "Infer"), crate::Type::Macro(v0) => v0.debug(formatter, "Macro"), crate::Type::Never(v0) => v0.debug(formatter, "Never"), crate::Type::Paren(v0) => v0.debug(formatter, "Paren"), crate::Type::Path(v0) => v0.debug(formatter, "Path"), crate::Type::Ptr(v0) => v0.debug(formatter, "Ptr"), crate::Type::Reference(v0) => v0.debug(formatter, "Reference"), crate::Type::Slice(v0) => v0.debug(formatter, "Slice"), crate::Type::TraitObject(v0) => v0.debug(formatter, "TraitObject"), crate::Type::Tuple(v0) => v0.debug(formatter, "Tuple"), crate::Type::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeArray { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeArray") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeArray { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("bracket_token", &self.bracket_token); formatter.field("elem", &self.elem); formatter.field("semi_token", &self.semi_token); formatter.field("len", &self.len); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeBareFn { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeBareFn") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeBareFn { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("lifetimes", &self.lifetimes); formatter.field("unsafety", &self.unsafety); formatter.field("abi", &self.abi); formatter.field("fn_token", &self.fn_token); formatter.field("paren_token", &self.paren_token); formatter.field("inputs", &self.inputs); formatter.field("variadic", &self.variadic); formatter.field("output", &self.output); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeGroup { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeGroup") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeGroup { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("group_token", &self.group_token); formatter.field("elem", &self.elem); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeImplTrait { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeImplTrait") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeImplTrait { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("impl_token", &self.impl_token); formatter.field("bounds", &self.bounds); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeInfer { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeInfer") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeInfer { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("underscore_token", &self.underscore_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeMacro { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeMacro") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeMacro { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("mac", &self.mac); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeNever { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeNever") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeNever { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("bang_token", &self.bang_token); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeParam { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("TypeParam"); formatter.field("attrs", &self.attrs); formatter.field("ident", &self.ident); formatter.field("colon_token", &self.colon_token); formatter.field("bounds", &self.bounds); formatter.field("eq_token", &self.eq_token); formatter.field("default", &self.default); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeParamBound { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("TypeParamBound::")?; match self { crate::TypeParamBound::Trait(v0) => { let mut formatter = formatter.debug_tuple("Trait"); formatter.field(v0); formatter.finish() } crate::TypeParamBound::Lifetime(v0) => v0.debug(formatter, "Lifetime"), crate::TypeParamBound::Verbatim(v0) => { let mut formatter = formatter.debug_tuple("Verbatim"); formatter.field(v0); formatter.finish() } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeParen { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeParen") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeParen { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("paren_token", &self.paren_token); formatter.field("elem", &self.elem); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypePath { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypePath") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypePath { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("qself", &self.qself); formatter.field("path", &self.path); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypePtr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypePtr") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypePtr { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("star_token", &self.star_token); formatter.field("const_token", &self.const_token); formatter.field("mutability", &self.mutability); formatter.field("elem", &self.elem); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeReference { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeReference") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeReference { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("and_token", &self.and_token); formatter.field("lifetime", &self.lifetime); formatter.field("mutability", &self.mutability); formatter.field("elem", &self.elem); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeSlice { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeSlice") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeSlice { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("bracket_token", &self.bracket_token); formatter.field("elem", &self.elem); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeTraitObject { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeTraitObject") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeTraitObject { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("dyn_token", &self.dyn_token); formatter.field("bounds", &self.bounds); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::TypeTuple { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "TypeTuple") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::TypeTuple { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("paren_token", &self.paren_token); formatter.field("elems", &self.elems); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::UnOp { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("UnOp::")?; match self { crate::UnOp::Deref(v0) => { let mut formatter = formatter.debug_tuple("Deref"); formatter.field(v0); formatter.finish() } crate::UnOp::Not(v0) => { let mut formatter = formatter.debug_tuple("Not"); formatter.field(v0); formatter.finish() } crate::UnOp::Neg(v0) => { let mut formatter = formatter.debug_tuple("Neg"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::UseGlob { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseGlob"); formatter.field("star_token", &self.star_token); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::UseGroup { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseGroup"); formatter.field("brace_token", &self.brace_token); formatter.field("items", &self.items); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::UseName { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseName"); formatter.field("ident", &self.ident); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::UsePath { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UsePath"); formatter.field("ident", &self.ident); formatter.field("colon2_token", &self.colon2_token); formatter.field("tree", &self.tree); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::UseRename { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("UseRename"); formatter.field("ident", &self.ident); formatter.field("as_token", &self.as_token); formatter.field("rename", &self.rename); formatter.finish() } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::UseTree { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("UseTree::")?; match self { crate::UseTree::Path(v0) => { let mut formatter = formatter.debug_tuple("Path"); formatter.field(v0); formatter.finish() } crate::UseTree::Name(v0) => { let mut formatter = formatter.debug_tuple("Name"); formatter.field(v0); formatter.finish() } crate::UseTree::Rename(v0) => { let mut formatter = formatter.debug_tuple("Rename"); formatter.field(v0); formatter.finish() } crate::UseTree::Glob(v0) => { let mut formatter = formatter.debug_tuple("Glob"); formatter.field(v0); formatter.finish() } crate::UseTree::Group(v0) => { let mut formatter = formatter.debug_tuple("Group"); formatter.field(v0); formatter.finish() } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Variadic { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Variadic"); formatter.field("attrs", &self.attrs); formatter.field("pat", &self.pat); formatter.field("dots", &self.dots); formatter.field("comma", &self.comma); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Variant { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("Variant"); formatter.field("attrs", &self.attrs); formatter.field("ident", &self.ident); formatter.field("fields", &self.fields); formatter.field("discriminant", &self.discriminant); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::VisRestricted { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "VisRestricted") } } #[cfg(any(feature = "derive", feature = "full"))] impl crate::VisRestricted { fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { let mut formatter = formatter.debug_struct(name); formatter.field("pub_token", &self.pub_token); formatter.field("paren_token", &self.paren_token); formatter.field("in_token", &self.in_token); formatter.field("path", &self.path); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::Visibility { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Visibility::")?; match self { crate::Visibility::Public(v0) => { let mut formatter = formatter.debug_tuple("Public"); formatter.field(v0); formatter.finish() } crate::Visibility::Restricted(v0) => v0.debug(formatter, "Restricted"), crate::Visibility::Inherited => formatter.write_str("Inherited"), } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::WhereClause { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut formatter = formatter.debug_struct("WhereClause"); formatter.field("where_token", &self.where_token); formatter.field("predicates", &self.predicates); formatter.finish() } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for crate::WherePredicate { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("WherePredicate::")?; match self { crate::WherePredicate::Lifetime(v0) => { let mut formatter = formatter.debug_tuple("Lifetime"); formatter.field(v0); formatter.finish() } crate::WherePredicate::Type(v0) => { let mut formatter = formatter.debug_tuple("Type"); formatter.field(v0); formatter.finish() } } } } syn/src/gen/visit_mut.rs0000644000175000017500000036756414661133735016330 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #![allow(unused_variables)] #![allow(clippy::needless_pass_by_ref_mut)] #[cfg(any(feature = "full", feature = "derive"))] use crate::punctuated::Punctuated; #[cfg(feature = "full")] macro_rules! full { ($e:expr) => { $e }; } #[cfg(all(feature = "derive", not(feature = "full")))] macro_rules! full { ($e:expr) => { unreachable!() }; } macro_rules! skip { ($($tt:tt)*) => {}; } /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in /// place. /// /// See the [module documentation] for details. /// /// [module documentation]: self pub trait VisitMut { #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_abi_mut(&mut self, i: &mut crate::Abi) { visit_abi_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_angle_bracketed_generic_arguments_mut( &mut self, i: &mut crate::AngleBracketedGenericArguments, ) { visit_angle_bracketed_generic_arguments_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_arm_mut(&mut self, i: &mut crate::Arm) { visit_arm_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_assoc_const_mut(&mut self, i: &mut crate::AssocConst) { visit_assoc_const_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_assoc_type_mut(&mut self, i: &mut crate::AssocType) { visit_assoc_type_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_attr_style_mut(&mut self, i: &mut crate::AttrStyle) { visit_attr_style_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_attribute_mut(&mut self, i: &mut crate::Attribute) { visit_attribute_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bare_fn_arg_mut(&mut self, i: &mut crate::BareFnArg) { visit_bare_fn_arg_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bare_variadic_mut(&mut self, i: &mut crate::BareVariadic) { visit_bare_variadic_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bin_op_mut(&mut self, i: &mut crate::BinOp) { visit_bin_op_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_block_mut(&mut self, i: &mut crate::Block) { visit_block_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_bound_lifetimes_mut(&mut self, i: &mut crate::BoundLifetimes) { visit_bound_lifetimes_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_const_param_mut(&mut self, i: &mut crate::ConstParam) { visit_const_param_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_constraint_mut(&mut self, i: &mut crate::Constraint) { visit_constraint_mut(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_mut(&mut self, i: &mut crate::Data) { visit_data_mut(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_enum_mut(&mut self, i: &mut crate::DataEnum) { visit_data_enum_mut(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_struct_mut(&mut self, i: &mut crate::DataStruct) { visit_data_struct_mut(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_data_union_mut(&mut self, i: &mut crate::DataUnion) { visit_data_union_mut(self, i); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] fn visit_derive_input_mut(&mut self, i: &mut crate::DeriveInput) { visit_derive_input_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_mut(&mut self, i: &mut crate::Expr) { visit_expr_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_array_mut(&mut self, i: &mut crate::ExprArray) { visit_expr_array_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_assign_mut(&mut self, i: &mut crate::ExprAssign) { visit_expr_assign_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_async_mut(&mut self, i: &mut crate::ExprAsync) { visit_expr_async_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_await_mut(&mut self, i: &mut crate::ExprAwait) { visit_expr_await_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_binary_mut(&mut self, i: &mut crate::ExprBinary) { visit_expr_binary_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_block_mut(&mut self, i: &mut crate::ExprBlock) { visit_expr_block_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_break_mut(&mut self, i: &mut crate::ExprBreak) { visit_expr_break_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_call_mut(&mut self, i: &mut crate::ExprCall) { visit_expr_call_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_cast_mut(&mut self, i: &mut crate::ExprCast) { visit_expr_cast_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_closure_mut(&mut self, i: &mut crate::ExprClosure) { visit_expr_closure_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_const_mut(&mut self, i: &mut crate::ExprConst) { visit_expr_const_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_continue_mut(&mut self, i: &mut crate::ExprContinue) { visit_expr_continue_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_field_mut(&mut self, i: &mut crate::ExprField) { visit_expr_field_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_for_loop_mut(&mut self, i: &mut crate::ExprForLoop) { visit_expr_for_loop_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_group_mut(&mut self, i: &mut crate::ExprGroup) { visit_expr_group_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_if_mut(&mut self, i: &mut crate::ExprIf) { visit_expr_if_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_index_mut(&mut self, i: &mut crate::ExprIndex) { visit_expr_index_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_infer_mut(&mut self, i: &mut crate::ExprInfer) { visit_expr_infer_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_let_mut(&mut self, i: &mut crate::ExprLet) { visit_expr_let_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_lit_mut(&mut self, i: &mut crate::ExprLit) { visit_expr_lit_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_loop_mut(&mut self, i: &mut crate::ExprLoop) { visit_expr_loop_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_macro_mut(&mut self, i: &mut crate::ExprMacro) { visit_expr_macro_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_match_mut(&mut self, i: &mut crate::ExprMatch) { visit_expr_match_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_method_call_mut(&mut self, i: &mut crate::ExprMethodCall) { visit_expr_method_call_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_paren_mut(&mut self, i: &mut crate::ExprParen) { visit_expr_paren_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_path_mut(&mut self, i: &mut crate::ExprPath) { visit_expr_path_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_range_mut(&mut self, i: &mut crate::ExprRange) { visit_expr_range_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_reference_mut(&mut self, i: &mut crate::ExprReference) { visit_expr_reference_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_repeat_mut(&mut self, i: &mut crate::ExprRepeat) { visit_expr_repeat_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_return_mut(&mut self, i: &mut crate::ExprReturn) { visit_expr_return_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_struct_mut(&mut self, i: &mut crate::ExprStruct) { visit_expr_struct_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_try_mut(&mut self, i: &mut crate::ExprTry) { visit_expr_try_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_try_block_mut(&mut self, i: &mut crate::ExprTryBlock) { visit_expr_try_block_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_tuple_mut(&mut self, i: &mut crate::ExprTuple) { visit_expr_tuple_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_expr_unary_mut(&mut self, i: &mut crate::ExprUnary) { visit_expr_unary_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_unsafe_mut(&mut self, i: &mut crate::ExprUnsafe) { visit_expr_unsafe_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_while_mut(&mut self, i: &mut crate::ExprWhile) { visit_expr_while_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_expr_yield_mut(&mut self, i: &mut crate::ExprYield) { visit_expr_yield_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_field_mut(&mut self, i: &mut crate::Field) { visit_field_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_field_mutability_mut(&mut self, i: &mut crate::FieldMutability) { visit_field_mutability_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_field_pat_mut(&mut self, i: &mut crate::FieldPat) { visit_field_pat_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_field_value_mut(&mut self, i: &mut crate::FieldValue) { visit_field_value_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_mut(&mut self, i: &mut crate::Fields) { visit_fields_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_named_mut(&mut self, i: &mut crate::FieldsNamed) { visit_fields_named_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_fields_unnamed_mut(&mut self, i: &mut crate::FieldsUnnamed) { visit_fields_unnamed_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_file_mut(&mut self, i: &mut crate::File) { visit_file_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_fn_arg_mut(&mut self, i: &mut crate::FnArg) { visit_fn_arg_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_mut(&mut self, i: &mut crate::ForeignItem) { visit_foreign_item_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_fn_mut(&mut self, i: &mut crate::ForeignItemFn) { visit_foreign_item_fn_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_macro_mut(&mut self, i: &mut crate::ForeignItemMacro) { visit_foreign_item_macro_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_static_mut(&mut self, i: &mut crate::ForeignItemStatic) { visit_foreign_item_static_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_foreign_item_type_mut(&mut self, i: &mut crate::ForeignItemType) { visit_foreign_item_type_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_generic_argument_mut(&mut self, i: &mut crate::GenericArgument) { visit_generic_argument_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_generic_param_mut(&mut self, i: &mut crate::GenericParam) { visit_generic_param_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_generics_mut(&mut self, i: &mut crate::Generics) { visit_generics_mut(self, i); } fn visit_ident_mut(&mut self, i: &mut proc_macro2::Ident) { visit_ident_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_mut(&mut self, i: &mut crate::ImplItem) { visit_impl_item_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_const_mut(&mut self, i: &mut crate::ImplItemConst) { visit_impl_item_const_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_fn_mut(&mut self, i: &mut crate::ImplItemFn) { visit_impl_item_fn_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_macro_mut(&mut self, i: &mut crate::ImplItemMacro) { visit_impl_item_macro_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_item_type_mut(&mut self, i: &mut crate::ImplItemType) { visit_impl_item_type_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_impl_restriction_mut(&mut self, i: &mut crate::ImplRestriction) { visit_impl_restriction_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_index_mut(&mut self, i: &mut crate::Index) { visit_index_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_mut(&mut self, i: &mut crate::Item) { visit_item_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_const_mut(&mut self, i: &mut crate::ItemConst) { visit_item_const_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_enum_mut(&mut self, i: &mut crate::ItemEnum) { visit_item_enum_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_extern_crate_mut(&mut self, i: &mut crate::ItemExternCrate) { visit_item_extern_crate_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_fn_mut(&mut self, i: &mut crate::ItemFn) { visit_item_fn_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_foreign_mod_mut(&mut self, i: &mut crate::ItemForeignMod) { visit_item_foreign_mod_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_impl_mut(&mut self, i: &mut crate::ItemImpl) { visit_item_impl_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_macro_mut(&mut self, i: &mut crate::ItemMacro) { visit_item_macro_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_mod_mut(&mut self, i: &mut crate::ItemMod) { visit_item_mod_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_static_mut(&mut self, i: &mut crate::ItemStatic) { visit_item_static_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_struct_mut(&mut self, i: &mut crate::ItemStruct) { visit_item_struct_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_trait_mut(&mut self, i: &mut crate::ItemTrait) { visit_item_trait_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_trait_alias_mut(&mut self, i: &mut crate::ItemTraitAlias) { visit_item_trait_alias_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_type_mut(&mut self, i: &mut crate::ItemType) { visit_item_type_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_union_mut(&mut self, i: &mut crate::ItemUnion) { visit_item_union_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_item_use_mut(&mut self, i: &mut crate::ItemUse) { visit_item_use_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_label_mut(&mut self, i: &mut crate::Label) { visit_label_mut(self, i); } fn visit_lifetime_mut(&mut self, i: &mut crate::Lifetime) { visit_lifetime_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_lifetime_param_mut(&mut self, i: &mut crate::LifetimeParam) { visit_lifetime_param_mut(self, i); } fn visit_lit_mut(&mut self, i: &mut crate::Lit) { visit_lit_mut(self, i); } fn visit_lit_bool_mut(&mut self, i: &mut crate::LitBool) { visit_lit_bool_mut(self, i); } fn visit_lit_byte_mut(&mut self, i: &mut crate::LitByte) { visit_lit_byte_mut(self, i); } fn visit_lit_byte_str_mut(&mut self, i: &mut crate::LitByteStr) { visit_lit_byte_str_mut(self, i); } fn visit_lit_cstr_mut(&mut self, i: &mut crate::LitCStr) { visit_lit_cstr_mut(self, i); } fn visit_lit_char_mut(&mut self, i: &mut crate::LitChar) { visit_lit_char_mut(self, i); } fn visit_lit_float_mut(&mut self, i: &mut crate::LitFloat) { visit_lit_float_mut(self, i); } fn visit_lit_int_mut(&mut self, i: &mut crate::LitInt) { visit_lit_int_mut(self, i); } fn visit_lit_str_mut(&mut self, i: &mut crate::LitStr) { visit_lit_str_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_local_mut(&mut self, i: &mut crate::Local) { visit_local_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_local_init_mut(&mut self, i: &mut crate::LocalInit) { visit_local_init_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_macro_mut(&mut self, i: &mut crate::Macro) { visit_macro_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_macro_delimiter_mut(&mut self, i: &mut crate::MacroDelimiter) { visit_macro_delimiter_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_member_mut(&mut self, i: &mut crate::Member) { visit_member_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_meta_mut(&mut self, i: &mut crate::Meta) { visit_meta_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_meta_list_mut(&mut self, i: &mut crate::MetaList) { visit_meta_list_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_meta_name_value_mut(&mut self, i: &mut crate::MetaNameValue) { visit_meta_name_value_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_parenthesized_generic_arguments_mut( &mut self, i: &mut crate::ParenthesizedGenericArguments, ) { visit_parenthesized_generic_arguments_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_mut(&mut self, i: &mut crate::Pat) { visit_pat_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_ident_mut(&mut self, i: &mut crate::PatIdent) { visit_pat_ident_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_or_mut(&mut self, i: &mut crate::PatOr) { visit_pat_or_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_paren_mut(&mut self, i: &mut crate::PatParen) { visit_pat_paren_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_reference_mut(&mut self, i: &mut crate::PatReference) { visit_pat_reference_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_rest_mut(&mut self, i: &mut crate::PatRest) { visit_pat_rest_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_slice_mut(&mut self, i: &mut crate::PatSlice) { visit_pat_slice_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_struct_mut(&mut self, i: &mut crate::PatStruct) { visit_pat_struct_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_tuple_mut(&mut self, i: &mut crate::PatTuple) { visit_pat_tuple_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_tuple_struct_mut(&mut self, i: &mut crate::PatTupleStruct) { visit_pat_tuple_struct_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_type_mut(&mut self, i: &mut crate::PatType) { visit_pat_type_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_pat_wild_mut(&mut self, i: &mut crate::PatWild) { visit_pat_wild_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_path_mut(&mut self, i: &mut crate::Path) { visit_path_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_path_arguments_mut(&mut self, i: &mut crate::PathArguments) { visit_path_arguments_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_path_segment_mut(&mut self, i: &mut crate::PathSegment) { visit_path_segment_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_predicate_lifetime_mut(&mut self, i: &mut crate::PredicateLifetime) { visit_predicate_lifetime_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_predicate_type_mut(&mut self, i: &mut crate::PredicateType) { visit_predicate_type_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_qself_mut(&mut self, i: &mut crate::QSelf) { visit_qself_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_range_limits_mut(&mut self, i: &mut crate::RangeLimits) { visit_range_limits_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_receiver_mut(&mut self, i: &mut crate::Receiver) { visit_receiver_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_return_type_mut(&mut self, i: &mut crate::ReturnType) { visit_return_type_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_signature_mut(&mut self, i: &mut crate::Signature) { visit_signature_mut(self, i); } fn visit_span_mut(&mut self, i: &mut proc_macro2::Span) { visit_span_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_static_mutability_mut(&mut self, i: &mut crate::StaticMutability) { visit_static_mutability_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_stmt_mut(&mut self, i: &mut crate::Stmt) { visit_stmt_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_stmt_macro_mut(&mut self, i: &mut crate::StmtMacro) { visit_stmt_macro_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_trait_bound_mut(&mut self, i: &mut crate::TraitBound) { visit_trait_bound_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_trait_bound_modifier_mut(&mut self, i: &mut crate::TraitBoundModifier) { visit_trait_bound_modifier_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_mut(&mut self, i: &mut crate::TraitItem) { visit_trait_item_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_const_mut(&mut self, i: &mut crate::TraitItemConst) { visit_trait_item_const_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_fn_mut(&mut self, i: &mut crate::TraitItemFn) { visit_trait_item_fn_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_macro_mut(&mut self, i: &mut crate::TraitItemMacro) { visit_trait_item_macro_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_trait_item_type_mut(&mut self, i: &mut crate::TraitItemType) { visit_trait_item_type_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_mut(&mut self, i: &mut crate::Type) { visit_type_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_array_mut(&mut self, i: &mut crate::TypeArray) { visit_type_array_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_bare_fn_mut(&mut self, i: &mut crate::TypeBareFn) { visit_type_bare_fn_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_group_mut(&mut self, i: &mut crate::TypeGroup) { visit_type_group_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_impl_trait_mut(&mut self, i: &mut crate::TypeImplTrait) { visit_type_impl_trait_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_infer_mut(&mut self, i: &mut crate::TypeInfer) { visit_type_infer_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_macro_mut(&mut self, i: &mut crate::TypeMacro) { visit_type_macro_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_never_mut(&mut self, i: &mut crate::TypeNever) { visit_type_never_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_param_mut(&mut self, i: &mut crate::TypeParam) { visit_type_param_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_param_bound_mut(&mut self, i: &mut crate::TypeParamBound) { visit_type_param_bound_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_paren_mut(&mut self, i: &mut crate::TypeParen) { visit_type_paren_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_path_mut(&mut self, i: &mut crate::TypePath) { visit_type_path_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_ptr_mut(&mut self, i: &mut crate::TypePtr) { visit_type_ptr_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_reference_mut(&mut self, i: &mut crate::TypeReference) { visit_type_reference_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_slice_mut(&mut self, i: &mut crate::TypeSlice) { visit_type_slice_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_trait_object_mut(&mut self, i: &mut crate::TypeTraitObject) { visit_type_trait_object_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_type_tuple_mut(&mut self, i: &mut crate::TypeTuple) { visit_type_tuple_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_un_op_mut(&mut self, i: &mut crate::UnOp) { visit_un_op_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_glob_mut(&mut self, i: &mut crate::UseGlob) { visit_use_glob_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_group_mut(&mut self, i: &mut crate::UseGroup) { visit_use_group_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_name_mut(&mut self, i: &mut crate::UseName) { visit_use_name_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_path_mut(&mut self, i: &mut crate::UsePath) { visit_use_path_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_rename_mut(&mut self, i: &mut crate::UseRename) { visit_use_rename_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_use_tree_mut(&mut self, i: &mut crate::UseTree) { visit_use_tree_mut(self, i); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] fn visit_variadic_mut(&mut self, i: &mut crate::Variadic) { visit_variadic_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_variant_mut(&mut self, i: &mut crate::Variant) { visit_variant_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_vis_restricted_mut(&mut self, i: &mut crate::VisRestricted) { visit_vis_restricted_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_visibility_mut(&mut self, i: &mut crate::Visibility) { visit_visibility_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_where_clause_mut(&mut self, i: &mut crate::WhereClause) { visit_where_clause_mut(self, i); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] fn visit_where_predicate_mut(&mut self, i: &mut crate::WherePredicate) { visit_where_predicate_mut(self, i); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_abi_mut(v: &mut V, node: &mut crate::Abi) where V: VisitMut + ?Sized, { skip!(node.extern_token); if let Some(it) = &mut node.name { v.visit_lit_str_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_angle_bracketed_generic_arguments_mut( v: &mut V, node: &mut crate::AngleBracketedGenericArguments, ) where V: VisitMut + ?Sized, { skip!(node.colon2_token); skip!(node.lt_token); for mut el in Punctuated::pairs_mut(&mut node.args) { let it = el.value_mut(); v.visit_generic_argument_mut(it); } skip!(node.gt_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_arm_mut(v: &mut V, node: &mut crate::Arm) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_pat_mut(&mut node.pat); if let Some(it) = &mut node.guard { skip!((it).0); v.visit_expr_mut(&mut *(it).1); } skip!(node.fat_arrow_token); v.visit_expr_mut(&mut *node.body); skip!(node.comma); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_assoc_const_mut(v: &mut V, node: &mut crate::AssocConst) where V: VisitMut + ?Sized, { v.visit_ident_mut(&mut node.ident); if let Some(it) = &mut node.generics { v.visit_angle_bracketed_generic_arguments_mut(it); } skip!(node.eq_token); v.visit_expr_mut(&mut node.value); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_assoc_type_mut(v: &mut V, node: &mut crate::AssocType) where V: VisitMut + ?Sized, { v.visit_ident_mut(&mut node.ident); if let Some(it) = &mut node.generics { v.visit_angle_bracketed_generic_arguments_mut(it); } skip!(node.eq_token); v.visit_type_mut(&mut node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_attr_style_mut(v: &mut V, node: &mut crate::AttrStyle) where V: VisitMut + ?Sized, { match node { crate::AttrStyle::Outer => {} crate::AttrStyle::Inner(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_attribute_mut(v: &mut V, node: &mut crate::Attribute) where V: VisitMut + ?Sized, { skip!(node.pound_token); v.visit_attr_style_mut(&mut node.style); skip!(node.bracket_token); v.visit_meta_mut(&mut node.meta); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bare_fn_arg_mut(v: &mut V, node: &mut crate::BareFnArg) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.name { v.visit_ident_mut(&mut (it).0); skip!((it).1); } v.visit_type_mut(&mut node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bare_variadic_mut(v: &mut V, node: &mut crate::BareVariadic) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.name { v.visit_ident_mut(&mut (it).0); skip!((it).1); } skip!(node.dots); skip!(node.comma); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bin_op_mut(v: &mut V, node: &mut crate::BinOp) where V: VisitMut + ?Sized, { match node { crate::BinOp::Add(_binding_0) => { skip!(_binding_0); } crate::BinOp::Sub(_binding_0) => { skip!(_binding_0); } crate::BinOp::Mul(_binding_0) => { skip!(_binding_0); } crate::BinOp::Div(_binding_0) => { skip!(_binding_0); } crate::BinOp::Rem(_binding_0) => { skip!(_binding_0); } crate::BinOp::And(_binding_0) => { skip!(_binding_0); } crate::BinOp::Or(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitXor(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitAnd(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitOr(_binding_0) => { skip!(_binding_0); } crate::BinOp::Shl(_binding_0) => { skip!(_binding_0); } crate::BinOp::Shr(_binding_0) => { skip!(_binding_0); } crate::BinOp::Eq(_binding_0) => { skip!(_binding_0); } crate::BinOp::Lt(_binding_0) => { skip!(_binding_0); } crate::BinOp::Le(_binding_0) => { skip!(_binding_0); } crate::BinOp::Ne(_binding_0) => { skip!(_binding_0); } crate::BinOp::Ge(_binding_0) => { skip!(_binding_0); } crate::BinOp::Gt(_binding_0) => { skip!(_binding_0); } crate::BinOp::AddAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::SubAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::MulAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::DivAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::RemAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitXorAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitAndAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::BitOrAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::ShlAssign(_binding_0) => { skip!(_binding_0); } crate::BinOp::ShrAssign(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_block_mut(v: &mut V, node: &mut crate::Block) where V: VisitMut + ?Sized, { skip!(node.brace_token); for it in &mut node.stmts { v.visit_stmt_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_bound_lifetimes_mut(v: &mut V, node: &mut crate::BoundLifetimes) where V: VisitMut + ?Sized, { skip!(node.for_token); skip!(node.lt_token); for mut el in Punctuated::pairs_mut(&mut node.lifetimes) { let it = el.value_mut(); v.visit_generic_param_mut(it); } skip!(node.gt_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_const_param_mut(v: &mut V, node: &mut crate::ConstParam) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.const_token); v.visit_ident_mut(&mut node.ident); skip!(node.colon_token); v.visit_type_mut(&mut node.ty); skip!(node.eq_token); if let Some(it) = &mut node.default { v.visit_expr_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_constraint_mut(v: &mut V, node: &mut crate::Constraint) where V: VisitMut + ?Sized, { v.visit_ident_mut(&mut node.ident); if let Some(it) = &mut node.generics { v.visit_angle_bracketed_generic_arguments_mut(it); } skip!(node.colon_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_mut(v: &mut V, node: &mut crate::Data) where V: VisitMut + ?Sized, { match node { crate::Data::Struct(_binding_0) => { v.visit_data_struct_mut(_binding_0); } crate::Data::Enum(_binding_0) => { v.visit_data_enum_mut(_binding_0); } crate::Data::Union(_binding_0) => { v.visit_data_union_mut(_binding_0); } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_enum_mut(v: &mut V, node: &mut crate::DataEnum) where V: VisitMut + ?Sized, { skip!(node.enum_token); skip!(node.brace_token); for mut el in Punctuated::pairs_mut(&mut node.variants) { let it = el.value_mut(); v.visit_variant_mut(it); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_struct_mut(v: &mut V, node: &mut crate::DataStruct) where V: VisitMut + ?Sized, { skip!(node.struct_token); v.visit_fields_mut(&mut node.fields); skip!(node.semi_token); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_data_union_mut(v: &mut V, node: &mut crate::DataUnion) where V: VisitMut + ?Sized, { skip!(node.union_token); v.visit_fields_named_mut(&mut node.fields); } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub fn visit_derive_input_mut(v: &mut V, node: &mut crate::DeriveInput) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); v.visit_data_mut(&mut node.data); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_mut(v: &mut V, node: &mut crate::Expr) where V: VisitMut + ?Sized, { match node { crate::Expr::Array(_binding_0) => { full!(v.visit_expr_array_mut(_binding_0)); } crate::Expr::Assign(_binding_0) => { full!(v.visit_expr_assign_mut(_binding_0)); } crate::Expr::Async(_binding_0) => { full!(v.visit_expr_async_mut(_binding_0)); } crate::Expr::Await(_binding_0) => { full!(v.visit_expr_await_mut(_binding_0)); } crate::Expr::Binary(_binding_0) => { v.visit_expr_binary_mut(_binding_0); } crate::Expr::Block(_binding_0) => { full!(v.visit_expr_block_mut(_binding_0)); } crate::Expr::Break(_binding_0) => { full!(v.visit_expr_break_mut(_binding_0)); } crate::Expr::Call(_binding_0) => { v.visit_expr_call_mut(_binding_0); } crate::Expr::Cast(_binding_0) => { v.visit_expr_cast_mut(_binding_0); } crate::Expr::Closure(_binding_0) => { full!(v.visit_expr_closure_mut(_binding_0)); } crate::Expr::Const(_binding_0) => { full!(v.visit_expr_const_mut(_binding_0)); } crate::Expr::Continue(_binding_0) => { full!(v.visit_expr_continue_mut(_binding_0)); } crate::Expr::Field(_binding_0) => { v.visit_expr_field_mut(_binding_0); } crate::Expr::ForLoop(_binding_0) => { full!(v.visit_expr_for_loop_mut(_binding_0)); } crate::Expr::Group(_binding_0) => { v.visit_expr_group_mut(_binding_0); } crate::Expr::If(_binding_0) => { full!(v.visit_expr_if_mut(_binding_0)); } crate::Expr::Index(_binding_0) => { v.visit_expr_index_mut(_binding_0); } crate::Expr::Infer(_binding_0) => { full!(v.visit_expr_infer_mut(_binding_0)); } crate::Expr::Let(_binding_0) => { full!(v.visit_expr_let_mut(_binding_0)); } crate::Expr::Lit(_binding_0) => { v.visit_expr_lit_mut(_binding_0); } crate::Expr::Loop(_binding_0) => { full!(v.visit_expr_loop_mut(_binding_0)); } crate::Expr::Macro(_binding_0) => { v.visit_expr_macro_mut(_binding_0); } crate::Expr::Match(_binding_0) => { full!(v.visit_expr_match_mut(_binding_0)); } crate::Expr::MethodCall(_binding_0) => { v.visit_expr_method_call_mut(_binding_0); } crate::Expr::Paren(_binding_0) => { v.visit_expr_paren_mut(_binding_0); } crate::Expr::Path(_binding_0) => { v.visit_expr_path_mut(_binding_0); } crate::Expr::Range(_binding_0) => { full!(v.visit_expr_range_mut(_binding_0)); } crate::Expr::Reference(_binding_0) => { v.visit_expr_reference_mut(_binding_0); } crate::Expr::Repeat(_binding_0) => { full!(v.visit_expr_repeat_mut(_binding_0)); } crate::Expr::Return(_binding_0) => { full!(v.visit_expr_return_mut(_binding_0)); } crate::Expr::Struct(_binding_0) => { v.visit_expr_struct_mut(_binding_0); } crate::Expr::Try(_binding_0) => { full!(v.visit_expr_try_mut(_binding_0)); } crate::Expr::TryBlock(_binding_0) => { full!(v.visit_expr_try_block_mut(_binding_0)); } crate::Expr::Tuple(_binding_0) => { full!(v.visit_expr_tuple_mut(_binding_0)); } crate::Expr::Unary(_binding_0) => { v.visit_expr_unary_mut(_binding_0); } crate::Expr::Unsafe(_binding_0) => { full!(v.visit_expr_unsafe_mut(_binding_0)); } crate::Expr::Verbatim(_binding_0) => { skip!(_binding_0); } crate::Expr::While(_binding_0) => { full!(v.visit_expr_while_mut(_binding_0)); } crate::Expr::Yield(_binding_0) => { full!(v.visit_expr_yield_mut(_binding_0)); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_array_mut(v: &mut V, node: &mut crate::ExprArray) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.bracket_token); for mut el in Punctuated::pairs_mut(&mut node.elems) { let it = el.value_mut(); v.visit_expr_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_assign_mut(v: &mut V, node: &mut crate::ExprAssign) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.left); skip!(node.eq_token); v.visit_expr_mut(&mut *node.right); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_async_mut(v: &mut V, node: &mut crate::ExprAsync) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.async_token); skip!(node.capture); v.visit_block_mut(&mut node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_await_mut(v: &mut V, node: &mut crate::ExprAwait) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.base); skip!(node.dot_token); skip!(node.await_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_binary_mut(v: &mut V, node: &mut crate::ExprBinary) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.left); v.visit_bin_op_mut(&mut node.op); v.visit_expr_mut(&mut *node.right); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_block_mut(v: &mut V, node: &mut crate::ExprBlock) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.label { v.visit_label_mut(it); } v.visit_block_mut(&mut node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_break_mut(v: &mut V, node: &mut crate::ExprBreak) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.break_token); if let Some(it) = &mut node.label { v.visit_lifetime_mut(it); } if let Some(it) = &mut node.expr { v.visit_expr_mut(&mut **it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_call_mut(v: &mut V, node: &mut crate::ExprCall) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.func); skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.args) { let it = el.value_mut(); v.visit_expr_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_cast_mut(v: &mut V, node: &mut crate::ExprCast) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.expr); skip!(node.as_token); v.visit_type_mut(&mut *node.ty); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_closure_mut(v: &mut V, node: &mut crate::ExprClosure) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.lifetimes { v.visit_bound_lifetimes_mut(it); } skip!(node.constness); skip!(node.movability); skip!(node.asyncness); skip!(node.capture); skip!(node.or1_token); for mut el in Punctuated::pairs_mut(&mut node.inputs) { let it = el.value_mut(); v.visit_pat_mut(it); } skip!(node.or2_token); v.visit_return_type_mut(&mut node.output); v.visit_expr_mut(&mut *node.body); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_const_mut(v: &mut V, node: &mut crate::ExprConst) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.const_token); v.visit_block_mut(&mut node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_continue_mut(v: &mut V, node: &mut crate::ExprContinue) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.continue_token); if let Some(it) = &mut node.label { v.visit_lifetime_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_field_mut(v: &mut V, node: &mut crate::ExprField) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.base); skip!(node.dot_token); v.visit_member_mut(&mut node.member); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_for_loop_mut(v: &mut V, node: &mut crate::ExprForLoop) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.label { v.visit_label_mut(it); } skip!(node.for_token); v.visit_pat_mut(&mut *node.pat); skip!(node.in_token); v.visit_expr_mut(&mut *node.expr); v.visit_block_mut(&mut node.body); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_group_mut(v: &mut V, node: &mut crate::ExprGroup) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.group_token); v.visit_expr_mut(&mut *node.expr); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_if_mut(v: &mut V, node: &mut crate::ExprIf) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.if_token); v.visit_expr_mut(&mut *node.cond); v.visit_block_mut(&mut node.then_branch); if let Some(it) = &mut node.else_branch { skip!((it).0); v.visit_expr_mut(&mut *(it).1); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_index_mut(v: &mut V, node: &mut crate::ExprIndex) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.expr); skip!(node.bracket_token); v.visit_expr_mut(&mut *node.index); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_infer_mut(v: &mut V, node: &mut crate::ExprInfer) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.underscore_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_let_mut(v: &mut V, node: &mut crate::ExprLet) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.let_token); v.visit_pat_mut(&mut *node.pat); skip!(node.eq_token); v.visit_expr_mut(&mut *node.expr); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_lit_mut(v: &mut V, node: &mut crate::ExprLit) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_lit_mut(&mut node.lit); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_loop_mut(v: &mut V, node: &mut crate::ExprLoop) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.label { v.visit_label_mut(it); } skip!(node.loop_token); v.visit_block_mut(&mut node.body); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_macro_mut(v: &mut V, node: &mut crate::ExprMacro) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_macro_mut(&mut node.mac); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_match_mut(v: &mut V, node: &mut crate::ExprMatch) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.match_token); v.visit_expr_mut(&mut *node.expr); skip!(node.brace_token); for it in &mut node.arms { v.visit_arm_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_method_call_mut(v: &mut V, node: &mut crate::ExprMethodCall) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.receiver); skip!(node.dot_token); v.visit_ident_mut(&mut node.method); if let Some(it) = &mut node.turbofish { v.visit_angle_bracketed_generic_arguments_mut(it); } skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.args) { let it = el.value_mut(); v.visit_expr_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_paren_mut(v: &mut V, node: &mut crate::ExprParen) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.paren_token); v.visit_expr_mut(&mut *node.expr); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_path_mut(v: &mut V, node: &mut crate::ExprPath) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.qself { v.visit_qself_mut(it); } v.visit_path_mut(&mut node.path); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_range_mut(v: &mut V, node: &mut crate::ExprRange) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.start { v.visit_expr_mut(&mut **it); } v.visit_range_limits_mut(&mut node.limits); if let Some(it) = &mut node.end { v.visit_expr_mut(&mut **it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_reference_mut(v: &mut V, node: &mut crate::ExprReference) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.and_token); skip!(node.mutability); v.visit_expr_mut(&mut *node.expr); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_repeat_mut(v: &mut V, node: &mut crate::ExprRepeat) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.bracket_token); v.visit_expr_mut(&mut *node.expr); skip!(node.semi_token); v.visit_expr_mut(&mut *node.len); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_return_mut(v: &mut V, node: &mut crate::ExprReturn) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.return_token); if let Some(it) = &mut node.expr { v.visit_expr_mut(&mut **it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_struct_mut(v: &mut V, node: &mut crate::ExprStruct) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.qself { v.visit_qself_mut(it); } v.visit_path_mut(&mut node.path); skip!(node.brace_token); for mut el in Punctuated::pairs_mut(&mut node.fields) { let it = el.value_mut(); v.visit_field_value_mut(it); } skip!(node.dot2_token); if let Some(it) = &mut node.rest { v.visit_expr_mut(&mut **it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_try_mut(v: &mut V, node: &mut crate::ExprTry) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_expr_mut(&mut *node.expr); skip!(node.question_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_try_block_mut(v: &mut V, node: &mut crate::ExprTryBlock) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.try_token); v.visit_block_mut(&mut node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_tuple_mut(v: &mut V, node: &mut crate::ExprTuple) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.elems) { let it = el.value_mut(); v.visit_expr_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_expr_unary_mut(v: &mut V, node: &mut crate::ExprUnary) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_un_op_mut(&mut node.op); v.visit_expr_mut(&mut *node.expr); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_unsafe_mut(v: &mut V, node: &mut crate::ExprUnsafe) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.unsafe_token); v.visit_block_mut(&mut node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_while_mut(v: &mut V, node: &mut crate::ExprWhile) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.label { v.visit_label_mut(it); } skip!(node.while_token); v.visit_expr_mut(&mut *node.cond); v.visit_block_mut(&mut node.body); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_expr_yield_mut(v: &mut V, node: &mut crate::ExprYield) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.yield_token); if let Some(it) = &mut node.expr { v.visit_expr_mut(&mut **it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_field_mut(v: &mut V, node: &mut crate::Field) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); v.visit_field_mutability_mut(&mut node.mutability); if let Some(it) = &mut node.ident { v.visit_ident_mut(it); } skip!(node.colon_token); v.visit_type_mut(&mut node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_field_mutability_mut(v: &mut V, node: &mut crate::FieldMutability) where V: VisitMut + ?Sized, { match node { crate::FieldMutability::None => {} } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_field_pat_mut(v: &mut V, node: &mut crate::FieldPat) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_member_mut(&mut node.member); skip!(node.colon_token); v.visit_pat_mut(&mut *node.pat); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_field_value_mut(v: &mut V, node: &mut crate::FieldValue) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_member_mut(&mut node.member); skip!(node.colon_token); v.visit_expr_mut(&mut node.expr); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_mut(v: &mut V, node: &mut crate::Fields) where V: VisitMut + ?Sized, { match node { crate::Fields::Named(_binding_0) => { v.visit_fields_named_mut(_binding_0); } crate::Fields::Unnamed(_binding_0) => { v.visit_fields_unnamed_mut(_binding_0); } crate::Fields::Unit => {} } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_named_mut(v: &mut V, node: &mut crate::FieldsNamed) where V: VisitMut + ?Sized, { skip!(node.brace_token); for mut el in Punctuated::pairs_mut(&mut node.named) { let it = el.value_mut(); v.visit_field_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_fields_unnamed_mut(v: &mut V, node: &mut crate::FieldsUnnamed) where V: VisitMut + ?Sized, { skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.unnamed) { let it = el.value_mut(); v.visit_field_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_file_mut(v: &mut V, node: &mut crate::File) where V: VisitMut + ?Sized, { skip!(node.shebang); for it in &mut node.attrs { v.visit_attribute_mut(it); } for it in &mut node.items { v.visit_item_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_fn_arg_mut(v: &mut V, node: &mut crate::FnArg) where V: VisitMut + ?Sized, { match node { crate::FnArg::Receiver(_binding_0) => { v.visit_receiver_mut(_binding_0); } crate::FnArg::Typed(_binding_0) => { v.visit_pat_type_mut(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_mut(v: &mut V, node: &mut crate::ForeignItem) where V: VisitMut + ?Sized, { match node { crate::ForeignItem::Fn(_binding_0) => { v.visit_foreign_item_fn_mut(_binding_0); } crate::ForeignItem::Static(_binding_0) => { v.visit_foreign_item_static_mut(_binding_0); } crate::ForeignItem::Type(_binding_0) => { v.visit_foreign_item_type_mut(_binding_0); } crate::ForeignItem::Macro(_binding_0) => { v.visit_foreign_item_macro_mut(_binding_0); } crate::ForeignItem::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_fn_mut(v: &mut V, node: &mut crate::ForeignItemFn) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); v.visit_signature_mut(&mut node.sig); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_macro_mut(v: &mut V, node: &mut crate::ForeignItemMacro) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_macro_mut(&mut node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_static_mut(v: &mut V, node: &mut crate::ForeignItemStatic) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.static_token); v.visit_static_mutability_mut(&mut node.mutability); v.visit_ident_mut(&mut node.ident); skip!(node.colon_token); v.visit_type_mut(&mut *node.ty); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_foreign_item_type_mut(v: &mut V, node: &mut crate::ForeignItemType) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.type_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.semi_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_generic_argument_mut(v: &mut V, node: &mut crate::GenericArgument) where V: VisitMut + ?Sized, { match node { crate::GenericArgument::Lifetime(_binding_0) => { v.visit_lifetime_mut(_binding_0); } crate::GenericArgument::Type(_binding_0) => { v.visit_type_mut(_binding_0); } crate::GenericArgument::Const(_binding_0) => { v.visit_expr_mut(_binding_0); } crate::GenericArgument::AssocType(_binding_0) => { v.visit_assoc_type_mut(_binding_0); } crate::GenericArgument::AssocConst(_binding_0) => { v.visit_assoc_const_mut(_binding_0); } crate::GenericArgument::Constraint(_binding_0) => { v.visit_constraint_mut(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_generic_param_mut(v: &mut V, node: &mut crate::GenericParam) where V: VisitMut + ?Sized, { match node { crate::GenericParam::Lifetime(_binding_0) => { v.visit_lifetime_param_mut(_binding_0); } crate::GenericParam::Type(_binding_0) => { v.visit_type_param_mut(_binding_0); } crate::GenericParam::Const(_binding_0) => { v.visit_const_param_mut(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_generics_mut(v: &mut V, node: &mut crate::Generics) where V: VisitMut + ?Sized, { skip!(node.lt_token); for mut el in Punctuated::pairs_mut(&mut node.params) { let it = el.value_mut(); v.visit_generic_param_mut(it); } skip!(node.gt_token); if let Some(it) = &mut node.where_clause { v.visit_where_clause_mut(it); } } pub fn visit_ident_mut(v: &mut V, node: &mut proc_macro2::Ident) where V: VisitMut + ?Sized, { let mut span = node.span(); v.visit_span_mut(&mut span); node.set_span(span); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_mut(v: &mut V, node: &mut crate::ImplItem) where V: VisitMut + ?Sized, { match node { crate::ImplItem::Const(_binding_0) => { v.visit_impl_item_const_mut(_binding_0); } crate::ImplItem::Fn(_binding_0) => { v.visit_impl_item_fn_mut(_binding_0); } crate::ImplItem::Type(_binding_0) => { v.visit_impl_item_type_mut(_binding_0); } crate::ImplItem::Macro(_binding_0) => { v.visit_impl_item_macro_mut(_binding_0); } crate::ImplItem::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_const_mut(v: &mut V, node: &mut crate::ImplItemConst) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.defaultness); skip!(node.const_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.colon_token); v.visit_type_mut(&mut node.ty); skip!(node.eq_token); v.visit_expr_mut(&mut node.expr); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_fn_mut(v: &mut V, node: &mut crate::ImplItemFn) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.defaultness); v.visit_signature_mut(&mut node.sig); v.visit_block_mut(&mut node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_macro_mut(v: &mut V, node: &mut crate::ImplItemMacro) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_macro_mut(&mut node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_item_type_mut(v: &mut V, node: &mut crate::ImplItemType) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.defaultness); skip!(node.type_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.eq_token); v.visit_type_mut(&mut node.ty); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_impl_restriction_mut(v: &mut V, node: &mut crate::ImplRestriction) where V: VisitMut + ?Sized, { match *node {} } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_index_mut(v: &mut V, node: &mut crate::Index) where V: VisitMut + ?Sized, { skip!(node.index); v.visit_span_mut(&mut node.span); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_mut(v: &mut V, node: &mut crate::Item) where V: VisitMut + ?Sized, { match node { crate::Item::Const(_binding_0) => { v.visit_item_const_mut(_binding_0); } crate::Item::Enum(_binding_0) => { v.visit_item_enum_mut(_binding_0); } crate::Item::ExternCrate(_binding_0) => { v.visit_item_extern_crate_mut(_binding_0); } crate::Item::Fn(_binding_0) => { v.visit_item_fn_mut(_binding_0); } crate::Item::ForeignMod(_binding_0) => { v.visit_item_foreign_mod_mut(_binding_0); } crate::Item::Impl(_binding_0) => { v.visit_item_impl_mut(_binding_0); } crate::Item::Macro(_binding_0) => { v.visit_item_macro_mut(_binding_0); } crate::Item::Mod(_binding_0) => { v.visit_item_mod_mut(_binding_0); } crate::Item::Static(_binding_0) => { v.visit_item_static_mut(_binding_0); } crate::Item::Struct(_binding_0) => { v.visit_item_struct_mut(_binding_0); } crate::Item::Trait(_binding_0) => { v.visit_item_trait_mut(_binding_0); } crate::Item::TraitAlias(_binding_0) => { v.visit_item_trait_alias_mut(_binding_0); } crate::Item::Type(_binding_0) => { v.visit_item_type_mut(_binding_0); } crate::Item::Union(_binding_0) => { v.visit_item_union_mut(_binding_0); } crate::Item::Use(_binding_0) => { v.visit_item_use_mut(_binding_0); } crate::Item::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_const_mut(v: &mut V, node: &mut crate::ItemConst) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.const_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.colon_token); v.visit_type_mut(&mut *node.ty); skip!(node.eq_token); v.visit_expr_mut(&mut *node.expr); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_enum_mut(v: &mut V, node: &mut crate::ItemEnum) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.enum_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.brace_token); for mut el in Punctuated::pairs_mut(&mut node.variants) { let it = el.value_mut(); v.visit_variant_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_extern_crate_mut(v: &mut V, node: &mut crate::ItemExternCrate) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.extern_token); skip!(node.crate_token); v.visit_ident_mut(&mut node.ident); if let Some(it) = &mut node.rename { skip!((it).0); v.visit_ident_mut(&mut (it).1); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_fn_mut(v: &mut V, node: &mut crate::ItemFn) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); v.visit_signature_mut(&mut node.sig); v.visit_block_mut(&mut *node.block); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_foreign_mod_mut(v: &mut V, node: &mut crate::ItemForeignMod) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.unsafety); v.visit_abi_mut(&mut node.abi); skip!(node.brace_token); for it in &mut node.items { v.visit_foreign_item_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_impl_mut(v: &mut V, node: &mut crate::ItemImpl) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.defaultness); skip!(node.unsafety); skip!(node.impl_token); v.visit_generics_mut(&mut node.generics); if let Some(it) = &mut node.trait_ { skip!((it).0); v.visit_path_mut(&mut (it).1); skip!((it).2); } v.visit_type_mut(&mut *node.self_ty); skip!(node.brace_token); for it in &mut node.items { v.visit_impl_item_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_macro_mut(v: &mut V, node: &mut crate::ItemMacro) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.ident { v.visit_ident_mut(it); } v.visit_macro_mut(&mut node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_mod_mut(v: &mut V, node: &mut crate::ItemMod) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.unsafety); skip!(node.mod_token); v.visit_ident_mut(&mut node.ident); if let Some(it) = &mut node.content { skip!((it).0); for it in &mut (it).1 { v.visit_item_mut(it); } } skip!(node.semi); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_static_mut(v: &mut V, node: &mut crate::ItemStatic) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.static_token); v.visit_static_mutability_mut(&mut node.mutability); v.visit_ident_mut(&mut node.ident); skip!(node.colon_token); v.visit_type_mut(&mut *node.ty); skip!(node.eq_token); v.visit_expr_mut(&mut *node.expr); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_struct_mut(v: &mut V, node: &mut crate::ItemStruct) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.struct_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); v.visit_fields_mut(&mut node.fields); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_trait_mut(v: &mut V, node: &mut crate::ItemTrait) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.unsafety); skip!(node.auto_token); if let Some(it) = &mut node.restriction { v.visit_impl_restriction_mut(it); } skip!(node.trait_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.colon_token); for mut el in Punctuated::pairs_mut(&mut node.supertraits) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } skip!(node.brace_token); for it in &mut node.items { v.visit_trait_item_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_trait_alias_mut(v: &mut V, node: &mut crate::ItemTraitAlias) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.trait_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.eq_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_type_mut(v: &mut V, node: &mut crate::ItemType) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.type_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.eq_token); v.visit_type_mut(&mut *node.ty); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_union_mut(v: &mut V, node: &mut crate::ItemUnion) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.union_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); v.visit_fields_named_mut(&mut node.fields); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_item_use_mut(v: &mut V, node: &mut crate::ItemUse) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_visibility_mut(&mut node.vis); skip!(node.use_token); skip!(node.leading_colon); v.visit_use_tree_mut(&mut node.tree); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_label_mut(v: &mut V, node: &mut crate::Label) where V: VisitMut + ?Sized, { v.visit_lifetime_mut(&mut node.name); skip!(node.colon_token); } pub fn visit_lifetime_mut(v: &mut V, node: &mut crate::Lifetime) where V: VisitMut + ?Sized, { v.visit_span_mut(&mut node.apostrophe); v.visit_ident_mut(&mut node.ident); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_lifetime_param_mut(v: &mut V, node: &mut crate::LifetimeParam) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_lifetime_mut(&mut node.lifetime); skip!(node.colon_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_lifetime_mut(it); } } pub fn visit_lit_mut(v: &mut V, node: &mut crate::Lit) where V: VisitMut + ?Sized, { match node { crate::Lit::Str(_binding_0) => { v.visit_lit_str_mut(_binding_0); } crate::Lit::ByteStr(_binding_0) => { v.visit_lit_byte_str_mut(_binding_0); } crate::Lit::CStr(_binding_0) => { v.visit_lit_cstr_mut(_binding_0); } crate::Lit::Byte(_binding_0) => { v.visit_lit_byte_mut(_binding_0); } crate::Lit::Char(_binding_0) => { v.visit_lit_char_mut(_binding_0); } crate::Lit::Int(_binding_0) => { v.visit_lit_int_mut(_binding_0); } crate::Lit::Float(_binding_0) => { v.visit_lit_float_mut(_binding_0); } crate::Lit::Bool(_binding_0) => { v.visit_lit_bool_mut(_binding_0); } crate::Lit::Verbatim(_binding_0) => { skip!(_binding_0); } } } pub fn visit_lit_bool_mut(v: &mut V, node: &mut crate::LitBool) where V: VisitMut + ?Sized, { skip!(node.value); v.visit_span_mut(&mut node.span); } pub fn visit_lit_byte_mut(v: &mut V, node: &mut crate::LitByte) where V: VisitMut + ?Sized, {} pub fn visit_lit_byte_str_mut(v: &mut V, node: &mut crate::LitByteStr) where V: VisitMut + ?Sized, {} pub fn visit_lit_cstr_mut(v: &mut V, node: &mut crate::LitCStr) where V: VisitMut + ?Sized, {} pub fn visit_lit_char_mut(v: &mut V, node: &mut crate::LitChar) where V: VisitMut + ?Sized, {} pub fn visit_lit_float_mut(v: &mut V, node: &mut crate::LitFloat) where V: VisitMut + ?Sized, {} pub fn visit_lit_int_mut(v: &mut V, node: &mut crate::LitInt) where V: VisitMut + ?Sized, {} pub fn visit_lit_str_mut(v: &mut V, node: &mut crate::LitStr) where V: VisitMut + ?Sized, {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_local_mut(v: &mut V, node: &mut crate::Local) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.let_token); v.visit_pat_mut(&mut node.pat); if let Some(it) = &mut node.init { v.visit_local_init_mut(it); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_local_init_mut(v: &mut V, node: &mut crate::LocalInit) where V: VisitMut + ?Sized, { skip!(node.eq_token); v.visit_expr_mut(&mut *node.expr); if let Some(it) = &mut node.diverge { skip!((it).0); v.visit_expr_mut(&mut *(it).1); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_macro_mut(v: &mut V, node: &mut crate::Macro) where V: VisitMut + ?Sized, { v.visit_path_mut(&mut node.path); skip!(node.bang_token); v.visit_macro_delimiter_mut(&mut node.delimiter); skip!(node.tokens); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_macro_delimiter_mut(v: &mut V, node: &mut crate::MacroDelimiter) where V: VisitMut + ?Sized, { match node { crate::MacroDelimiter::Paren(_binding_0) => { skip!(_binding_0); } crate::MacroDelimiter::Brace(_binding_0) => { skip!(_binding_0); } crate::MacroDelimiter::Bracket(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_member_mut(v: &mut V, node: &mut crate::Member) where V: VisitMut + ?Sized, { match node { crate::Member::Named(_binding_0) => { v.visit_ident_mut(_binding_0); } crate::Member::Unnamed(_binding_0) => { v.visit_index_mut(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_meta_mut(v: &mut V, node: &mut crate::Meta) where V: VisitMut + ?Sized, { match node { crate::Meta::Path(_binding_0) => { v.visit_path_mut(_binding_0); } crate::Meta::List(_binding_0) => { v.visit_meta_list_mut(_binding_0); } crate::Meta::NameValue(_binding_0) => { v.visit_meta_name_value_mut(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_meta_list_mut(v: &mut V, node: &mut crate::MetaList) where V: VisitMut + ?Sized, { v.visit_path_mut(&mut node.path); v.visit_macro_delimiter_mut(&mut node.delimiter); skip!(node.tokens); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_meta_name_value_mut(v: &mut V, node: &mut crate::MetaNameValue) where V: VisitMut + ?Sized, { v.visit_path_mut(&mut node.path); skip!(node.eq_token); v.visit_expr_mut(&mut node.value); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_parenthesized_generic_arguments_mut( v: &mut V, node: &mut crate::ParenthesizedGenericArguments, ) where V: VisitMut + ?Sized, { skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.inputs) { let it = el.value_mut(); v.visit_type_mut(it); } v.visit_return_type_mut(&mut node.output); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_mut(v: &mut V, node: &mut crate::Pat) where V: VisitMut + ?Sized, { match node { crate::Pat::Const(_binding_0) => { v.visit_expr_const_mut(_binding_0); } crate::Pat::Ident(_binding_0) => { v.visit_pat_ident_mut(_binding_0); } crate::Pat::Lit(_binding_0) => { v.visit_expr_lit_mut(_binding_0); } crate::Pat::Macro(_binding_0) => { v.visit_expr_macro_mut(_binding_0); } crate::Pat::Or(_binding_0) => { v.visit_pat_or_mut(_binding_0); } crate::Pat::Paren(_binding_0) => { v.visit_pat_paren_mut(_binding_0); } crate::Pat::Path(_binding_0) => { v.visit_expr_path_mut(_binding_0); } crate::Pat::Range(_binding_0) => { v.visit_expr_range_mut(_binding_0); } crate::Pat::Reference(_binding_0) => { v.visit_pat_reference_mut(_binding_0); } crate::Pat::Rest(_binding_0) => { v.visit_pat_rest_mut(_binding_0); } crate::Pat::Slice(_binding_0) => { v.visit_pat_slice_mut(_binding_0); } crate::Pat::Struct(_binding_0) => { v.visit_pat_struct_mut(_binding_0); } crate::Pat::Tuple(_binding_0) => { v.visit_pat_tuple_mut(_binding_0); } crate::Pat::TupleStruct(_binding_0) => { v.visit_pat_tuple_struct_mut(_binding_0); } crate::Pat::Type(_binding_0) => { v.visit_pat_type_mut(_binding_0); } crate::Pat::Verbatim(_binding_0) => { skip!(_binding_0); } crate::Pat::Wild(_binding_0) => { v.visit_pat_wild_mut(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_ident_mut(v: &mut V, node: &mut crate::PatIdent) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.by_ref); skip!(node.mutability); v.visit_ident_mut(&mut node.ident); if let Some(it) = &mut node.subpat { skip!((it).0); v.visit_pat_mut(&mut *(it).1); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_or_mut(v: &mut V, node: &mut crate::PatOr) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.leading_vert); for mut el in Punctuated::pairs_mut(&mut node.cases) { let it = el.value_mut(); v.visit_pat_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_paren_mut(v: &mut V, node: &mut crate::PatParen) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.paren_token); v.visit_pat_mut(&mut *node.pat); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_reference_mut(v: &mut V, node: &mut crate::PatReference) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.and_token); skip!(node.mutability); v.visit_pat_mut(&mut *node.pat); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_rest_mut(v: &mut V, node: &mut crate::PatRest) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.dot2_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_slice_mut(v: &mut V, node: &mut crate::PatSlice) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.bracket_token); for mut el in Punctuated::pairs_mut(&mut node.elems) { let it = el.value_mut(); v.visit_pat_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_struct_mut(v: &mut V, node: &mut crate::PatStruct) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.qself { v.visit_qself_mut(it); } v.visit_path_mut(&mut node.path); skip!(node.brace_token); for mut el in Punctuated::pairs_mut(&mut node.fields) { let it = el.value_mut(); v.visit_field_pat_mut(it); } if let Some(it) = &mut node.rest { v.visit_pat_rest_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_tuple_mut(v: &mut V, node: &mut crate::PatTuple) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.elems) { let it = el.value_mut(); v.visit_pat_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_tuple_struct_mut(v: &mut V, node: &mut crate::PatTupleStruct) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.qself { v.visit_qself_mut(it); } v.visit_path_mut(&mut node.path); skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.elems) { let it = el.value_mut(); v.visit_pat_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_type_mut(v: &mut V, node: &mut crate::PatType) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_pat_mut(&mut *node.pat); skip!(node.colon_token); v.visit_type_mut(&mut *node.ty); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_pat_wild_mut(v: &mut V, node: &mut crate::PatWild) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.underscore_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_path_mut(v: &mut V, node: &mut crate::Path) where V: VisitMut + ?Sized, { skip!(node.leading_colon); for mut el in Punctuated::pairs_mut(&mut node.segments) { let it = el.value_mut(); v.visit_path_segment_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_path_arguments_mut(v: &mut V, node: &mut crate::PathArguments) where V: VisitMut + ?Sized, { match node { crate::PathArguments::None => {} crate::PathArguments::AngleBracketed(_binding_0) => { v.visit_angle_bracketed_generic_arguments_mut(_binding_0); } crate::PathArguments::Parenthesized(_binding_0) => { v.visit_parenthesized_generic_arguments_mut(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_path_segment_mut(v: &mut V, node: &mut crate::PathSegment) where V: VisitMut + ?Sized, { v.visit_ident_mut(&mut node.ident); v.visit_path_arguments_mut(&mut node.arguments); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_predicate_lifetime_mut(v: &mut V, node: &mut crate::PredicateLifetime) where V: VisitMut + ?Sized, { v.visit_lifetime_mut(&mut node.lifetime); skip!(node.colon_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_lifetime_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_predicate_type_mut(v: &mut V, node: &mut crate::PredicateType) where V: VisitMut + ?Sized, { if let Some(it) = &mut node.lifetimes { v.visit_bound_lifetimes_mut(it); } v.visit_type_mut(&mut node.bounded_ty); skip!(node.colon_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_qself_mut(v: &mut V, node: &mut crate::QSelf) where V: VisitMut + ?Sized, { skip!(node.lt_token); v.visit_type_mut(&mut *node.ty); skip!(node.position); skip!(node.as_token); skip!(node.gt_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_range_limits_mut(v: &mut V, node: &mut crate::RangeLimits) where V: VisitMut + ?Sized, { match node { crate::RangeLimits::HalfOpen(_binding_0) => { skip!(_binding_0); } crate::RangeLimits::Closed(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_receiver_mut(v: &mut V, node: &mut crate::Receiver) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.reference { skip!((it).0); if let Some(it) = &mut (it).1 { v.visit_lifetime_mut(it); } } skip!(node.mutability); skip!(node.self_token); skip!(node.colon_token); v.visit_type_mut(&mut *node.ty); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_return_type_mut(v: &mut V, node: &mut crate::ReturnType) where V: VisitMut + ?Sized, { match node { crate::ReturnType::Default => {} crate::ReturnType::Type(_binding_0, _binding_1) => { skip!(_binding_0); v.visit_type_mut(&mut **_binding_1); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_signature_mut(v: &mut V, node: &mut crate::Signature) where V: VisitMut + ?Sized, { skip!(node.constness); skip!(node.asyncness); skip!(node.unsafety); if let Some(it) = &mut node.abi { v.visit_abi_mut(it); } skip!(node.fn_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.inputs) { let it = el.value_mut(); v.visit_fn_arg_mut(it); } if let Some(it) = &mut node.variadic { v.visit_variadic_mut(it); } v.visit_return_type_mut(&mut node.output); } pub fn visit_span_mut(v: &mut V, node: &mut proc_macro2::Span) where V: VisitMut + ?Sized, {} #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_static_mutability_mut(v: &mut V, node: &mut crate::StaticMutability) where V: VisitMut + ?Sized, { match node { crate::StaticMutability::Mut(_binding_0) => { skip!(_binding_0); } crate::StaticMutability::None => {} } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_stmt_mut(v: &mut V, node: &mut crate::Stmt) where V: VisitMut + ?Sized, { match node { crate::Stmt::Local(_binding_0) => { v.visit_local_mut(_binding_0); } crate::Stmt::Item(_binding_0) => { v.visit_item_mut(_binding_0); } crate::Stmt::Expr(_binding_0, _binding_1) => { v.visit_expr_mut(_binding_0); skip!(_binding_1); } crate::Stmt::Macro(_binding_0) => { v.visit_stmt_macro_mut(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_stmt_macro_mut(v: &mut V, node: &mut crate::StmtMacro) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_macro_mut(&mut node.mac); skip!(node.semi_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_trait_bound_mut(v: &mut V, node: &mut crate::TraitBound) where V: VisitMut + ?Sized, { skip!(node.paren_token); v.visit_trait_bound_modifier_mut(&mut node.modifier); if let Some(it) = &mut node.lifetimes { v.visit_bound_lifetimes_mut(it); } v.visit_path_mut(&mut node.path); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_trait_bound_modifier_mut(v: &mut V, node: &mut crate::TraitBoundModifier) where V: VisitMut + ?Sized, { match node { crate::TraitBoundModifier::None => {} crate::TraitBoundModifier::Maybe(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_mut(v: &mut V, node: &mut crate::TraitItem) where V: VisitMut + ?Sized, { match node { crate::TraitItem::Const(_binding_0) => { v.visit_trait_item_const_mut(_binding_0); } crate::TraitItem::Fn(_binding_0) => { v.visit_trait_item_fn_mut(_binding_0); } crate::TraitItem::Type(_binding_0) => { v.visit_trait_item_type_mut(_binding_0); } crate::TraitItem::Macro(_binding_0) => { v.visit_trait_item_macro_mut(_binding_0); } crate::TraitItem::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_const_mut(v: &mut V, node: &mut crate::TraitItemConst) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.const_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.colon_token); v.visit_type_mut(&mut node.ty); if let Some(it) = &mut node.default { skip!((it).0); v.visit_expr_mut(&mut (it).1); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_fn_mut(v: &mut V, node: &mut crate::TraitItemFn) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_signature_mut(&mut node.sig); if let Some(it) = &mut node.default { v.visit_block_mut(it); } skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_macro_mut(v: &mut V, node: &mut crate::TraitItemMacro) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_macro_mut(&mut node.mac); skip!(node.semi_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_trait_item_type_mut(v: &mut V, node: &mut crate::TraitItemType) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } skip!(node.type_token); v.visit_ident_mut(&mut node.ident); v.visit_generics_mut(&mut node.generics); skip!(node.colon_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } if let Some(it) = &mut node.default { skip!((it).0); v.visit_type_mut(&mut (it).1); } skip!(node.semi_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_mut(v: &mut V, node: &mut crate::Type) where V: VisitMut + ?Sized, { match node { crate::Type::Array(_binding_0) => { v.visit_type_array_mut(_binding_0); } crate::Type::BareFn(_binding_0) => { v.visit_type_bare_fn_mut(_binding_0); } crate::Type::Group(_binding_0) => { v.visit_type_group_mut(_binding_0); } crate::Type::ImplTrait(_binding_0) => { v.visit_type_impl_trait_mut(_binding_0); } crate::Type::Infer(_binding_0) => { v.visit_type_infer_mut(_binding_0); } crate::Type::Macro(_binding_0) => { v.visit_type_macro_mut(_binding_0); } crate::Type::Never(_binding_0) => { v.visit_type_never_mut(_binding_0); } crate::Type::Paren(_binding_0) => { v.visit_type_paren_mut(_binding_0); } crate::Type::Path(_binding_0) => { v.visit_type_path_mut(_binding_0); } crate::Type::Ptr(_binding_0) => { v.visit_type_ptr_mut(_binding_0); } crate::Type::Reference(_binding_0) => { v.visit_type_reference_mut(_binding_0); } crate::Type::Slice(_binding_0) => { v.visit_type_slice_mut(_binding_0); } crate::Type::TraitObject(_binding_0) => { v.visit_type_trait_object_mut(_binding_0); } crate::Type::Tuple(_binding_0) => { v.visit_type_tuple_mut(_binding_0); } crate::Type::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_array_mut(v: &mut V, node: &mut crate::TypeArray) where V: VisitMut + ?Sized, { skip!(node.bracket_token); v.visit_type_mut(&mut *node.elem); skip!(node.semi_token); v.visit_expr_mut(&mut node.len); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_bare_fn_mut(v: &mut V, node: &mut crate::TypeBareFn) where V: VisitMut + ?Sized, { if let Some(it) = &mut node.lifetimes { v.visit_bound_lifetimes_mut(it); } skip!(node.unsafety); if let Some(it) = &mut node.abi { v.visit_abi_mut(it); } skip!(node.fn_token); skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.inputs) { let it = el.value_mut(); v.visit_bare_fn_arg_mut(it); } if let Some(it) = &mut node.variadic { v.visit_bare_variadic_mut(it); } v.visit_return_type_mut(&mut node.output); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_group_mut(v: &mut V, node: &mut crate::TypeGroup) where V: VisitMut + ?Sized, { skip!(node.group_token); v.visit_type_mut(&mut *node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_impl_trait_mut(v: &mut V, node: &mut crate::TypeImplTrait) where V: VisitMut + ?Sized, { skip!(node.impl_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_infer_mut(v: &mut V, node: &mut crate::TypeInfer) where V: VisitMut + ?Sized, { skip!(node.underscore_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_macro_mut(v: &mut V, node: &mut crate::TypeMacro) where V: VisitMut + ?Sized, { v.visit_macro_mut(&mut node.mac); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_never_mut(v: &mut V, node: &mut crate::TypeNever) where V: VisitMut + ?Sized, { skip!(node.bang_token); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_param_mut(v: &mut V, node: &mut crate::TypeParam) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_ident_mut(&mut node.ident); skip!(node.colon_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } skip!(node.eq_token); if let Some(it) = &mut node.default { v.visit_type_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_param_bound_mut(v: &mut V, node: &mut crate::TypeParamBound) where V: VisitMut + ?Sized, { match node { crate::TypeParamBound::Trait(_binding_0) => { v.visit_trait_bound_mut(_binding_0); } crate::TypeParamBound::Lifetime(_binding_0) => { v.visit_lifetime_mut(_binding_0); } crate::TypeParamBound::Verbatim(_binding_0) => { skip!(_binding_0); } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_paren_mut(v: &mut V, node: &mut crate::TypeParen) where V: VisitMut + ?Sized, { skip!(node.paren_token); v.visit_type_mut(&mut *node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_path_mut(v: &mut V, node: &mut crate::TypePath) where V: VisitMut + ?Sized, { if let Some(it) = &mut node.qself { v.visit_qself_mut(it); } v.visit_path_mut(&mut node.path); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_ptr_mut(v: &mut V, node: &mut crate::TypePtr) where V: VisitMut + ?Sized, { skip!(node.star_token); skip!(node.const_token); skip!(node.mutability); v.visit_type_mut(&mut *node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_reference_mut(v: &mut V, node: &mut crate::TypeReference) where V: VisitMut + ?Sized, { skip!(node.and_token); if let Some(it) = &mut node.lifetime { v.visit_lifetime_mut(it); } skip!(node.mutability); v.visit_type_mut(&mut *node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_slice_mut(v: &mut V, node: &mut crate::TypeSlice) where V: VisitMut + ?Sized, { skip!(node.bracket_token); v.visit_type_mut(&mut *node.elem); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_trait_object_mut(v: &mut V, node: &mut crate::TypeTraitObject) where V: VisitMut + ?Sized, { skip!(node.dyn_token); for mut el in Punctuated::pairs_mut(&mut node.bounds) { let it = el.value_mut(); v.visit_type_param_bound_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_type_tuple_mut(v: &mut V, node: &mut crate::TypeTuple) where V: VisitMut + ?Sized, { skip!(node.paren_token); for mut el in Punctuated::pairs_mut(&mut node.elems) { let it = el.value_mut(); v.visit_type_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_un_op_mut(v: &mut V, node: &mut crate::UnOp) where V: VisitMut + ?Sized, { match node { crate::UnOp::Deref(_binding_0) => { skip!(_binding_0); } crate::UnOp::Not(_binding_0) => { skip!(_binding_0); } crate::UnOp::Neg(_binding_0) => { skip!(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_glob_mut(v: &mut V, node: &mut crate::UseGlob) where V: VisitMut + ?Sized, { skip!(node.star_token); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_group_mut(v: &mut V, node: &mut crate::UseGroup) where V: VisitMut + ?Sized, { skip!(node.brace_token); for mut el in Punctuated::pairs_mut(&mut node.items) { let it = el.value_mut(); v.visit_use_tree_mut(it); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_name_mut(v: &mut V, node: &mut crate::UseName) where V: VisitMut + ?Sized, { v.visit_ident_mut(&mut node.ident); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_path_mut(v: &mut V, node: &mut crate::UsePath) where V: VisitMut + ?Sized, { v.visit_ident_mut(&mut node.ident); skip!(node.colon2_token); v.visit_use_tree_mut(&mut *node.tree); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_rename_mut(v: &mut V, node: &mut crate::UseRename) where V: VisitMut + ?Sized, { v.visit_ident_mut(&mut node.ident); skip!(node.as_token); v.visit_ident_mut(&mut node.rename); } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_use_tree_mut(v: &mut V, node: &mut crate::UseTree) where V: VisitMut + ?Sized, { match node { crate::UseTree::Path(_binding_0) => { v.visit_use_path_mut(_binding_0); } crate::UseTree::Name(_binding_0) => { v.visit_use_name_mut(_binding_0); } crate::UseTree::Rename(_binding_0) => { v.visit_use_rename_mut(_binding_0); } crate::UseTree::Glob(_binding_0) => { v.visit_use_glob_mut(_binding_0); } crate::UseTree::Group(_binding_0) => { v.visit_use_group_mut(_binding_0); } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub fn visit_variadic_mut(v: &mut V, node: &mut crate::Variadic) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } if let Some(it) = &mut node.pat { v.visit_pat_mut(&mut *(it).0); skip!((it).1); } skip!(node.dots); skip!(node.comma); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_variant_mut(v: &mut V, node: &mut crate::Variant) where V: VisitMut + ?Sized, { for it in &mut node.attrs { v.visit_attribute_mut(it); } v.visit_ident_mut(&mut node.ident); v.visit_fields_mut(&mut node.fields); if let Some(it) = &mut node.discriminant { skip!((it).0); v.visit_expr_mut(&mut (it).1); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_vis_restricted_mut(v: &mut V, node: &mut crate::VisRestricted) where V: VisitMut + ?Sized, { skip!(node.pub_token); skip!(node.paren_token); skip!(node.in_token); v.visit_path_mut(&mut *node.path); } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_visibility_mut(v: &mut V, node: &mut crate::Visibility) where V: VisitMut + ?Sized, { match node { crate::Visibility::Public(_binding_0) => { skip!(_binding_0); } crate::Visibility::Restricted(_binding_0) => { v.visit_vis_restricted_mut(_binding_0); } crate::Visibility::Inherited => {} } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_where_clause_mut(v: &mut V, node: &mut crate::WhereClause) where V: VisitMut + ?Sized, { skip!(node.where_token); for mut el in Punctuated::pairs_mut(&mut node.predicates) { let it = el.value_mut(); v.visit_where_predicate_mut(it); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "derive", feature = "full"))))] pub fn visit_where_predicate_mut(v: &mut V, node: &mut crate::WherePredicate) where V: VisitMut + ?Sized, { match node { crate::WherePredicate::Lifetime(_binding_0) => { v.visit_predicate_lifetime_mut(_binding_0); } crate::WherePredicate::Type(_binding_0) => { v.visit_predicate_type_mut(_binding_0); } } } syn/src/gen/hash.rs0000644000175000017500000022250014661133735015204 0ustar jamespagejamespage// This file is @generated by syn-internal-codegen. // It is not intended for manual editing. #[cfg(any(feature = "derive", feature = "full"))] use crate::tt::TokenStreamHelper; use std::hash::{Hash, Hasher}; #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Abi { fn hash(&self, state: &mut H) where H: Hasher, { self.name.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::AngleBracketedGenericArguments { fn hash(&self, state: &mut H) where H: Hasher, { self.colon2_token.hash(state); self.args.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Arm { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.pat.hash(state); self.guard.hash(state); self.body.hash(state); self.comma.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::AssocConst { fn hash(&self, state: &mut H) where H: Hasher, { self.ident.hash(state); self.generics.hash(state); self.value.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::AssocType { fn hash(&self, state: &mut H) where H: Hasher, { self.ident.hash(state); self.generics.hash(state); self.ty.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::AttrStyle { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::AttrStyle::Outer => { state.write_u8(0u8); } crate::AttrStyle::Inner(_) => { state.write_u8(1u8); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Attribute { fn hash(&self, state: &mut H) where H: Hasher, { self.style.hash(state); self.meta.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::BareFnArg { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.name.hash(state); self.ty.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::BareVariadic { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.name.hash(state); self.comma.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::BinOp { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::BinOp::Add(_) => { state.write_u8(0u8); } crate::BinOp::Sub(_) => { state.write_u8(1u8); } crate::BinOp::Mul(_) => { state.write_u8(2u8); } crate::BinOp::Div(_) => { state.write_u8(3u8); } crate::BinOp::Rem(_) => { state.write_u8(4u8); } crate::BinOp::And(_) => { state.write_u8(5u8); } crate::BinOp::Or(_) => { state.write_u8(6u8); } crate::BinOp::BitXor(_) => { state.write_u8(7u8); } crate::BinOp::BitAnd(_) => { state.write_u8(8u8); } crate::BinOp::BitOr(_) => { state.write_u8(9u8); } crate::BinOp::Shl(_) => { state.write_u8(10u8); } crate::BinOp::Shr(_) => { state.write_u8(11u8); } crate::BinOp::Eq(_) => { state.write_u8(12u8); } crate::BinOp::Lt(_) => { state.write_u8(13u8); } crate::BinOp::Le(_) => { state.write_u8(14u8); } crate::BinOp::Ne(_) => { state.write_u8(15u8); } crate::BinOp::Ge(_) => { state.write_u8(16u8); } crate::BinOp::Gt(_) => { state.write_u8(17u8); } crate::BinOp::AddAssign(_) => { state.write_u8(18u8); } crate::BinOp::SubAssign(_) => { state.write_u8(19u8); } crate::BinOp::MulAssign(_) => { state.write_u8(20u8); } crate::BinOp::DivAssign(_) => { state.write_u8(21u8); } crate::BinOp::RemAssign(_) => { state.write_u8(22u8); } crate::BinOp::BitXorAssign(_) => { state.write_u8(23u8); } crate::BinOp::BitAndAssign(_) => { state.write_u8(24u8); } crate::BinOp::BitOrAssign(_) => { state.write_u8(25u8); } crate::BinOp::ShlAssign(_) => { state.write_u8(26u8); } crate::BinOp::ShrAssign(_) => { state.write_u8(27u8); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Block { fn hash(&self, state: &mut H) where H: Hasher, { self.stmts.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::BoundLifetimes { fn hash(&self, state: &mut H) where H: Hasher, { self.lifetimes.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ConstParam { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.ident.hash(state); self.ty.hash(state); self.eq_token.hash(state); self.default.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Constraint { fn hash(&self, state: &mut H) where H: Hasher, { self.ident.hash(state); self.generics.hash(state); self.bounds.hash(state); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Data { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Data::Struct(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Data::Enum(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Data::Union(v0) => { state.write_u8(2u8); v0.hash(state); } } } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::DataEnum { fn hash(&self, state: &mut H) where H: Hasher, { self.variants.hash(state); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::DataStruct { fn hash(&self, state: &mut H) where H: Hasher, { self.fields.hash(state); self.semi_token.hash(state); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::DataUnion { fn hash(&self, state: &mut H) where H: Hasher, { self.fields.hash(state); } } #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::DeriveInput { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); self.data.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Expr { fn hash(&self, state: &mut H) where H: Hasher, { match self { #[cfg(feature = "full")] crate::Expr::Array(v0) => { state.write_u8(0u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Assign(v0) => { state.write_u8(1u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Async(v0) => { state.write_u8(2u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Await(v0) => { state.write_u8(3u8); v0.hash(state); } crate::Expr::Binary(v0) => { state.write_u8(4u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Block(v0) => { state.write_u8(5u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Break(v0) => { state.write_u8(6u8); v0.hash(state); } crate::Expr::Call(v0) => { state.write_u8(7u8); v0.hash(state); } crate::Expr::Cast(v0) => { state.write_u8(8u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Closure(v0) => { state.write_u8(9u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Const(v0) => { state.write_u8(10u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Continue(v0) => { state.write_u8(11u8); v0.hash(state); } crate::Expr::Field(v0) => { state.write_u8(12u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::ForLoop(v0) => { state.write_u8(13u8); v0.hash(state); } crate::Expr::Group(v0) => { state.write_u8(14u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::If(v0) => { state.write_u8(15u8); v0.hash(state); } crate::Expr::Index(v0) => { state.write_u8(16u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Infer(v0) => { state.write_u8(17u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Let(v0) => { state.write_u8(18u8); v0.hash(state); } crate::Expr::Lit(v0) => { state.write_u8(19u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Loop(v0) => { state.write_u8(20u8); v0.hash(state); } crate::Expr::Macro(v0) => { state.write_u8(21u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Match(v0) => { state.write_u8(22u8); v0.hash(state); } crate::Expr::MethodCall(v0) => { state.write_u8(23u8); v0.hash(state); } crate::Expr::Paren(v0) => { state.write_u8(24u8); v0.hash(state); } crate::Expr::Path(v0) => { state.write_u8(25u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Range(v0) => { state.write_u8(26u8); v0.hash(state); } crate::Expr::Reference(v0) => { state.write_u8(27u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Repeat(v0) => { state.write_u8(28u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Return(v0) => { state.write_u8(29u8); v0.hash(state); } crate::Expr::Struct(v0) => { state.write_u8(30u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Try(v0) => { state.write_u8(31u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::TryBlock(v0) => { state.write_u8(32u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Tuple(v0) => { state.write_u8(33u8); v0.hash(state); } crate::Expr::Unary(v0) => { state.write_u8(34u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Unsafe(v0) => { state.write_u8(35u8); v0.hash(state); } crate::Expr::Verbatim(v0) => { state.write_u8(36u8); TokenStreamHelper(v0).hash(state); } #[cfg(feature = "full")] crate::Expr::While(v0) => { state.write_u8(37u8); v0.hash(state); } #[cfg(feature = "full")] crate::Expr::Yield(v0) => { state.write_u8(38u8); v0.hash(state); } #[cfg(not(feature = "full"))] _ => unreachable!(), } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprArray { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.elems.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprAssign { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.left.hash(state); self.right.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprAsync { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.capture.hash(state); self.block.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprAwait { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.base.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprBinary { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.left.hash(state); self.op.hash(state); self.right.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprBlock { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.label.hash(state); self.block.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprBreak { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.label.hash(state); self.expr.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprCall { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.func.hash(state); self.args.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprCast { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); self.ty.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprClosure { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.lifetimes.hash(state); self.constness.hash(state); self.movability.hash(state); self.asyncness.hash(state); self.capture.hash(state); self.inputs.hash(state); self.output.hash(state); self.body.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprConst { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.block.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprContinue { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.label.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprField { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.base.hash(state); self.member.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprForLoop { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.label.hash(state); self.pat.hash(state); self.expr.hash(state); self.body.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprGroup { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprIf { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.cond.hash(state); self.then_branch.hash(state); self.else_branch.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprIndex { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); self.index.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprInfer { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprLet { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.pat.hash(state); self.expr.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprLit { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.lit.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprLoop { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.label.hash(state); self.body.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprMacro { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.mac.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprMatch { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); self.arms.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprMethodCall { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.receiver.hash(state); self.method.hash(state); self.turbofish.hash(state); self.args.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprParen { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprPath { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.qself.hash(state); self.path.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprRange { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.start.hash(state); self.limits.hash(state); self.end.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprReference { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.mutability.hash(state); self.expr.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprRepeat { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); self.len.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprReturn { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprStruct { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.qself.hash(state); self.path.hash(state); self.fields.hash(state); self.dot2_token.hash(state); self.rest.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprTry { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprTryBlock { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.block.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprTuple { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.elems.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprUnary { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.op.hash(state); self.expr.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprUnsafe { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.block.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprWhile { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.label.hash(state); self.cond.hash(state); self.body.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ExprYield { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.expr.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Field { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.mutability.hash(state); self.ident.hash(state); self.colon_token.hash(state); self.ty.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FieldMutability { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::FieldMutability::None => { state.write_u8(0u8); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FieldPat { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.member.hash(state); self.colon_token.hash(state); self.pat.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FieldValue { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.member.hash(state); self.colon_token.hash(state); self.expr.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Fields { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Fields::Named(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Fields::Unnamed(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Fields::Unit => { state.write_u8(2u8); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FieldsNamed { fn hash(&self, state: &mut H) where H: Hasher, { self.named.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FieldsUnnamed { fn hash(&self, state: &mut H) where H: Hasher, { self.unnamed.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::File { fn hash(&self, state: &mut H) where H: Hasher, { self.shebang.hash(state); self.attrs.hash(state); self.items.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::FnArg { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::FnArg::Receiver(v0) => { state.write_u8(0u8); v0.hash(state); } crate::FnArg::Typed(v0) => { state.write_u8(1u8); v0.hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ForeignItem { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::ForeignItem::Fn(v0) => { state.write_u8(0u8); v0.hash(state); } crate::ForeignItem::Static(v0) => { state.write_u8(1u8); v0.hash(state); } crate::ForeignItem::Type(v0) => { state.write_u8(2u8); v0.hash(state); } crate::ForeignItem::Macro(v0) => { state.write_u8(3u8); v0.hash(state); } crate::ForeignItem::Verbatim(v0) => { state.write_u8(4u8); TokenStreamHelper(v0).hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ForeignItemFn { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.sig.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ForeignItemMacro { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.mac.hash(state); self.semi_token.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ForeignItemStatic { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.mutability.hash(state); self.ident.hash(state); self.ty.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ForeignItemType { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::GenericArgument { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::GenericArgument::Lifetime(v0) => { state.write_u8(0u8); v0.hash(state); } crate::GenericArgument::Type(v0) => { state.write_u8(1u8); v0.hash(state); } crate::GenericArgument::Const(v0) => { state.write_u8(2u8); v0.hash(state); } crate::GenericArgument::AssocType(v0) => { state.write_u8(3u8); v0.hash(state); } crate::GenericArgument::AssocConst(v0) => { state.write_u8(4u8); v0.hash(state); } crate::GenericArgument::Constraint(v0) => { state.write_u8(5u8); v0.hash(state); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::GenericParam { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::GenericParam::Lifetime(v0) => { state.write_u8(0u8); v0.hash(state); } crate::GenericParam::Type(v0) => { state.write_u8(1u8); v0.hash(state); } crate::GenericParam::Const(v0) => { state.write_u8(2u8); v0.hash(state); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Generics { fn hash(&self, state: &mut H) where H: Hasher, { self.lt_token.hash(state); self.params.hash(state); self.gt_token.hash(state); self.where_clause.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ImplItem { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::ImplItem::Const(v0) => { state.write_u8(0u8); v0.hash(state); } crate::ImplItem::Fn(v0) => { state.write_u8(1u8); v0.hash(state); } crate::ImplItem::Type(v0) => { state.write_u8(2u8); v0.hash(state); } crate::ImplItem::Macro(v0) => { state.write_u8(3u8); v0.hash(state); } crate::ImplItem::Verbatim(v0) => { state.write_u8(4u8); TokenStreamHelper(v0).hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ImplItemConst { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.defaultness.hash(state); self.ident.hash(state); self.generics.hash(state); self.ty.hash(state); self.expr.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ImplItemFn { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.defaultness.hash(state); self.sig.hash(state); self.block.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ImplItemMacro { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.mac.hash(state); self.semi_token.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ImplItemType { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.defaultness.hash(state); self.ident.hash(state); self.generics.hash(state); self.ty.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ImplRestriction { fn hash(&self, _state: &mut H) where H: Hasher, { match *self {} } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Item { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Item::Const(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Item::Enum(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Item::ExternCrate(v0) => { state.write_u8(2u8); v0.hash(state); } crate::Item::Fn(v0) => { state.write_u8(3u8); v0.hash(state); } crate::Item::ForeignMod(v0) => { state.write_u8(4u8); v0.hash(state); } crate::Item::Impl(v0) => { state.write_u8(5u8); v0.hash(state); } crate::Item::Macro(v0) => { state.write_u8(6u8); v0.hash(state); } crate::Item::Mod(v0) => { state.write_u8(7u8); v0.hash(state); } crate::Item::Static(v0) => { state.write_u8(8u8); v0.hash(state); } crate::Item::Struct(v0) => { state.write_u8(9u8); v0.hash(state); } crate::Item::Trait(v0) => { state.write_u8(10u8); v0.hash(state); } crate::Item::TraitAlias(v0) => { state.write_u8(11u8); v0.hash(state); } crate::Item::Type(v0) => { state.write_u8(12u8); v0.hash(state); } crate::Item::Union(v0) => { state.write_u8(13u8); v0.hash(state); } crate::Item::Use(v0) => { state.write_u8(14u8); v0.hash(state); } crate::Item::Verbatim(v0) => { state.write_u8(15u8); TokenStreamHelper(v0).hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemConst { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); self.ty.hash(state); self.expr.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemEnum { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); self.variants.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemExternCrate { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.rename.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemFn { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.sig.hash(state); self.block.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemForeignMod { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.unsafety.hash(state); self.abi.hash(state); self.items.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemImpl { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.defaultness.hash(state); self.unsafety.hash(state); self.generics.hash(state); self.trait_.hash(state); self.self_ty.hash(state); self.items.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemMacro { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.ident.hash(state); self.mac.hash(state); self.semi_token.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemMod { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.unsafety.hash(state); self.ident.hash(state); self.content.hash(state); self.semi.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemStatic { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.mutability.hash(state); self.ident.hash(state); self.ty.hash(state); self.expr.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemStruct { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); self.fields.hash(state); self.semi_token.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemTrait { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.unsafety.hash(state); self.auto_token.hash(state); self.restriction.hash(state); self.ident.hash(state); self.generics.hash(state); self.colon_token.hash(state); self.supertraits.hash(state); self.items.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemTraitAlias { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); self.bounds.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemType { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); self.ty.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemUnion { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.ident.hash(state); self.generics.hash(state); self.fields.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ItemUse { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.vis.hash(state); self.leading_colon.hash(state); self.tree.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Label { fn hash(&self, state: &mut H) where H: Hasher, { self.name.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::LifetimeParam { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.lifetime.hash(state); self.colon_token.hash(state); self.bounds.hash(state); } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Lit { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Lit::Str(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Lit::ByteStr(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Lit::CStr(v0) => { state.write_u8(2u8); v0.hash(state); } crate::Lit::Byte(v0) => { state.write_u8(3u8); v0.hash(state); } crate::Lit::Char(v0) => { state.write_u8(4u8); v0.hash(state); } crate::Lit::Int(v0) => { state.write_u8(5u8); v0.hash(state); } crate::Lit::Float(v0) => { state.write_u8(6u8); v0.hash(state); } crate::Lit::Bool(v0) => { state.write_u8(7u8); v0.hash(state); } crate::Lit::Verbatim(v0) => { state.write_u8(8u8); v0.to_string().hash(state); } } } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::LitBool { fn hash(&self, state: &mut H) where H: Hasher, { self.value.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Local { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.pat.hash(state); self.init.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::LocalInit { fn hash(&self, state: &mut H) where H: Hasher, { self.expr.hash(state); self.diverge.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Macro { fn hash(&self, state: &mut H) where H: Hasher, { self.path.hash(state); self.delimiter.hash(state); TokenStreamHelper(&self.tokens).hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::MacroDelimiter { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::MacroDelimiter::Paren(_) => { state.write_u8(0u8); } crate::MacroDelimiter::Brace(_) => { state.write_u8(1u8); } crate::MacroDelimiter::Bracket(_) => { state.write_u8(2u8); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Meta { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Meta::Path(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Meta::List(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Meta::NameValue(v0) => { state.write_u8(2u8); v0.hash(state); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::MetaList { fn hash(&self, state: &mut H) where H: Hasher, { self.path.hash(state); self.delimiter.hash(state); TokenStreamHelper(&self.tokens).hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::MetaNameValue { fn hash(&self, state: &mut H) where H: Hasher, { self.path.hash(state); self.value.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ParenthesizedGenericArguments { fn hash(&self, state: &mut H) where H: Hasher, { self.inputs.hash(state); self.output.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Pat { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Pat::Const(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Pat::Ident(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Pat::Lit(v0) => { state.write_u8(2u8); v0.hash(state); } crate::Pat::Macro(v0) => { state.write_u8(3u8); v0.hash(state); } crate::Pat::Or(v0) => { state.write_u8(4u8); v0.hash(state); } crate::Pat::Paren(v0) => { state.write_u8(5u8); v0.hash(state); } crate::Pat::Path(v0) => { state.write_u8(6u8); v0.hash(state); } crate::Pat::Range(v0) => { state.write_u8(7u8); v0.hash(state); } crate::Pat::Reference(v0) => { state.write_u8(8u8); v0.hash(state); } crate::Pat::Rest(v0) => { state.write_u8(9u8); v0.hash(state); } crate::Pat::Slice(v0) => { state.write_u8(10u8); v0.hash(state); } crate::Pat::Struct(v0) => { state.write_u8(11u8); v0.hash(state); } crate::Pat::Tuple(v0) => { state.write_u8(12u8); v0.hash(state); } crate::Pat::TupleStruct(v0) => { state.write_u8(13u8); v0.hash(state); } crate::Pat::Type(v0) => { state.write_u8(14u8); v0.hash(state); } crate::Pat::Verbatim(v0) => { state.write_u8(15u8); TokenStreamHelper(v0).hash(state); } crate::Pat::Wild(v0) => { state.write_u8(16u8); v0.hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatIdent { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.by_ref.hash(state); self.mutability.hash(state); self.ident.hash(state); self.subpat.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatOr { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.leading_vert.hash(state); self.cases.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatParen { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.pat.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatReference { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.mutability.hash(state); self.pat.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatRest { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatSlice { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.elems.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatStruct { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.qself.hash(state); self.path.hash(state); self.fields.hash(state); self.rest.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatTuple { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.elems.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatTupleStruct { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.qself.hash(state); self.path.hash(state); self.elems.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatType { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.pat.hash(state); self.ty.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PatWild { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Path { fn hash(&self, state: &mut H) where H: Hasher, { self.leading_colon.hash(state); self.segments.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PathArguments { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::PathArguments::None => { state.write_u8(0u8); } crate::PathArguments::AngleBracketed(v0) => { state.write_u8(1u8); v0.hash(state); } crate::PathArguments::Parenthesized(v0) => { state.write_u8(2u8); v0.hash(state); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PathSegment { fn hash(&self, state: &mut H) where H: Hasher, { self.ident.hash(state); self.arguments.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PredicateLifetime { fn hash(&self, state: &mut H) where H: Hasher, { self.lifetime.hash(state); self.bounds.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::PredicateType { fn hash(&self, state: &mut H) where H: Hasher, { self.lifetimes.hash(state); self.bounded_ty.hash(state); self.bounds.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::QSelf { fn hash(&self, state: &mut H) where H: Hasher, { self.ty.hash(state); self.position.hash(state); self.as_token.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::RangeLimits { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::RangeLimits::HalfOpen(_) => { state.write_u8(0u8); } crate::RangeLimits::Closed(_) => { state.write_u8(1u8); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Receiver { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.reference.hash(state); self.mutability.hash(state); self.colon_token.hash(state); self.ty.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::ReturnType { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::ReturnType::Default => { state.write_u8(0u8); } crate::ReturnType::Type(_, v1) => { state.write_u8(1u8); v1.hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Signature { fn hash(&self, state: &mut H) where H: Hasher, { self.constness.hash(state); self.asyncness.hash(state); self.unsafety.hash(state); self.abi.hash(state); self.ident.hash(state); self.generics.hash(state); self.inputs.hash(state); self.variadic.hash(state); self.output.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::StaticMutability { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::StaticMutability::Mut(_) => { state.write_u8(0u8); } crate::StaticMutability::None => { state.write_u8(1u8); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Stmt { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Stmt::Local(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Stmt::Item(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Stmt::Expr(v0, v1) => { state.write_u8(2u8); v0.hash(state); v1.hash(state); } crate::Stmt::Macro(v0) => { state.write_u8(3u8); v0.hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::StmtMacro { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.mac.hash(state); self.semi_token.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TraitBound { fn hash(&self, state: &mut H) where H: Hasher, { self.paren_token.hash(state); self.modifier.hash(state); self.lifetimes.hash(state); self.path.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TraitBoundModifier { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::TraitBoundModifier::None => { state.write_u8(0u8); } crate::TraitBoundModifier::Maybe(_) => { state.write_u8(1u8); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TraitItem { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::TraitItem::Const(v0) => { state.write_u8(0u8); v0.hash(state); } crate::TraitItem::Fn(v0) => { state.write_u8(1u8); v0.hash(state); } crate::TraitItem::Type(v0) => { state.write_u8(2u8); v0.hash(state); } crate::TraitItem::Macro(v0) => { state.write_u8(3u8); v0.hash(state); } crate::TraitItem::Verbatim(v0) => { state.write_u8(4u8); TokenStreamHelper(v0).hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TraitItemConst { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.ident.hash(state); self.generics.hash(state); self.ty.hash(state); self.default.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TraitItemFn { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.sig.hash(state); self.default.hash(state); self.semi_token.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TraitItemMacro { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.mac.hash(state); self.semi_token.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TraitItemType { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.ident.hash(state); self.generics.hash(state); self.colon_token.hash(state); self.bounds.hash(state); self.default.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Type { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Type::Array(v0) => { state.write_u8(0u8); v0.hash(state); } crate::Type::BareFn(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Type::Group(v0) => { state.write_u8(2u8); v0.hash(state); } crate::Type::ImplTrait(v0) => { state.write_u8(3u8); v0.hash(state); } crate::Type::Infer(v0) => { state.write_u8(4u8); v0.hash(state); } crate::Type::Macro(v0) => { state.write_u8(5u8); v0.hash(state); } crate::Type::Never(v0) => { state.write_u8(6u8); v0.hash(state); } crate::Type::Paren(v0) => { state.write_u8(7u8); v0.hash(state); } crate::Type::Path(v0) => { state.write_u8(8u8); v0.hash(state); } crate::Type::Ptr(v0) => { state.write_u8(9u8); v0.hash(state); } crate::Type::Reference(v0) => { state.write_u8(10u8); v0.hash(state); } crate::Type::Slice(v0) => { state.write_u8(11u8); v0.hash(state); } crate::Type::TraitObject(v0) => { state.write_u8(12u8); v0.hash(state); } crate::Type::Tuple(v0) => { state.write_u8(13u8); v0.hash(state); } crate::Type::Verbatim(v0) => { state.write_u8(14u8); TokenStreamHelper(v0).hash(state); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeArray { fn hash(&self, state: &mut H) where H: Hasher, { self.elem.hash(state); self.len.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeBareFn { fn hash(&self, state: &mut H) where H: Hasher, { self.lifetimes.hash(state); self.unsafety.hash(state); self.abi.hash(state); self.inputs.hash(state); self.variadic.hash(state); self.output.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeGroup { fn hash(&self, state: &mut H) where H: Hasher, { self.elem.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeImplTrait { fn hash(&self, state: &mut H) where H: Hasher, { self.bounds.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeInfer { fn hash(&self, _state: &mut H) where H: Hasher, {} } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeMacro { fn hash(&self, state: &mut H) where H: Hasher, { self.mac.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeNever { fn hash(&self, _state: &mut H) where H: Hasher, {} } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeParam { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.ident.hash(state); self.colon_token.hash(state); self.bounds.hash(state); self.eq_token.hash(state); self.default.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeParamBound { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::TypeParamBound::Trait(v0) => { state.write_u8(0u8); v0.hash(state); } crate::TypeParamBound::Lifetime(v0) => { state.write_u8(1u8); v0.hash(state); } crate::TypeParamBound::Verbatim(v0) => { state.write_u8(2u8); TokenStreamHelper(v0).hash(state); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeParen { fn hash(&self, state: &mut H) where H: Hasher, { self.elem.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypePath { fn hash(&self, state: &mut H) where H: Hasher, { self.qself.hash(state); self.path.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypePtr { fn hash(&self, state: &mut H) where H: Hasher, { self.const_token.hash(state); self.mutability.hash(state); self.elem.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeReference { fn hash(&self, state: &mut H) where H: Hasher, { self.lifetime.hash(state); self.mutability.hash(state); self.elem.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeSlice { fn hash(&self, state: &mut H) where H: Hasher, { self.elem.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeTraitObject { fn hash(&self, state: &mut H) where H: Hasher, { self.dyn_token.hash(state); self.bounds.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::TypeTuple { fn hash(&self, state: &mut H) where H: Hasher, { self.elems.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::UnOp { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::UnOp::Deref(_) => { state.write_u8(0u8); } crate::UnOp::Not(_) => { state.write_u8(1u8); } crate::UnOp::Neg(_) => { state.write_u8(2u8); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::UseGlob { fn hash(&self, _state: &mut H) where H: Hasher, {} } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::UseGroup { fn hash(&self, state: &mut H) where H: Hasher, { self.items.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::UseName { fn hash(&self, state: &mut H) where H: Hasher, { self.ident.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::UsePath { fn hash(&self, state: &mut H) where H: Hasher, { self.ident.hash(state); self.tree.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::UseRename { fn hash(&self, state: &mut H) where H: Hasher, { self.ident.hash(state); self.rename.hash(state); } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::UseTree { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::UseTree::Path(v0) => { state.write_u8(0u8); v0.hash(state); } crate::UseTree::Name(v0) => { state.write_u8(1u8); v0.hash(state); } crate::UseTree::Rename(v0) => { state.write_u8(2u8); v0.hash(state); } crate::UseTree::Glob(v0) => { state.write_u8(3u8); v0.hash(state); } crate::UseTree::Group(v0) => { state.write_u8(4u8); v0.hash(state); } } } } #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Variadic { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.pat.hash(state); self.comma.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Variant { fn hash(&self, state: &mut H) where H: Hasher, { self.attrs.hash(state); self.ident.hash(state); self.fields.hash(state); self.discriminant.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::VisRestricted { fn hash(&self, state: &mut H) where H: Hasher, { self.in_token.hash(state); self.path.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::Visibility { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::Visibility::Public(_) => { state.write_u8(0u8); } crate::Visibility::Restricted(v0) => { state.write_u8(1u8); v0.hash(state); } crate::Visibility::Inherited => { state.write_u8(2u8); } } } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::WhereClause { fn hash(&self, state: &mut H) where H: Hasher, { self.predicates.hash(state); } } #[cfg(any(feature = "derive", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for crate::WherePredicate { fn hash(&self, state: &mut H) where H: Hasher, { match self { crate::WherePredicate::Lifetime(v0) => { state.write_u8(0u8); v0.hash(state); } crate::WherePredicate::Type(v0) => { state.write_u8(1u8); v0.hash(state); } } } } syn/src/derive.rs0000644000175000017500000002121314661133735014764 0ustar jamespagejamespageuse crate::attr::Attribute; use crate::data::{Fields, FieldsNamed, Variant}; use crate::generics::Generics; use crate::ident::Ident; use crate::punctuated::Punctuated; use crate::restriction::Visibility; use crate::token; ast_struct! { /// Data structure sent to a `proc_macro_derive` macro. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DeriveInput { pub attrs: Vec, pub vis: Visibility, pub ident: Ident, pub generics: Generics, pub data: Data, } } ast_enum! { /// The storage of a struct, enum or union data structure. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub enum Data { Struct(DataStruct), Enum(DataEnum), Union(DataUnion), } } ast_struct! { /// A struct input to a `proc_macro_derive` macro. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DataStruct { pub struct_token: Token![struct], pub fields: Fields, pub semi_token: Option, } } ast_struct! { /// An enum input to a `proc_macro_derive` macro. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DataEnum { pub enum_token: Token![enum], pub brace_token: token::Brace, pub variants: Punctuated, } } ast_struct! { /// An untagged union input to a `proc_macro_derive` macro. #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub struct DataUnion { pub union_token: Token![union], pub fields: FieldsNamed, } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::data::{Fields, FieldsNamed, Variant}; use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; use crate::error::Result; use crate::generics::{Generics, WhereClause}; use crate::ident::Ident; use crate::parse::{Parse, ParseStream}; use crate::punctuated::Punctuated; use crate::restriction::Visibility; use crate::token; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for DeriveInput { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis = input.parse::()?; let lookahead = input.lookahead1(); if lookahead.peek(Token![struct]) { let struct_token = input.parse::()?; let ident = input.parse::()?; let generics = input.parse::()?; let (where_clause, fields, semi) = data_struct(input)?; Ok(DeriveInput { attrs, vis, ident, generics: Generics { where_clause, ..generics }, data: Data::Struct(DataStruct { struct_token, fields, semi_token: semi, }), }) } else if lookahead.peek(Token![enum]) { let enum_token = input.parse::()?; let ident = input.parse::()?; let generics = input.parse::()?; let (where_clause, brace, variants) = data_enum(input)?; Ok(DeriveInput { attrs, vis, ident, generics: Generics { where_clause, ..generics }, data: Data::Enum(DataEnum { enum_token, brace_token: brace, variants, }), }) } else if lookahead.peek(Token![union]) { let union_token = input.parse::()?; let ident = input.parse::()?; let generics = input.parse::()?; let (where_clause, fields) = data_union(input)?; Ok(DeriveInput { attrs, vis, ident, generics: Generics { where_clause, ..generics }, data: Data::Union(DataUnion { union_token, fields, }), }) } else { Err(lookahead.error()) } } } pub(crate) fn data_struct( input: ParseStream, ) -> Result<(Option, Fields, Option)> { let mut lookahead = input.lookahead1(); let mut where_clause = None; if lookahead.peek(Token![where]) { where_clause = Some(input.parse()?); lookahead = input.lookahead1(); } if where_clause.is_none() && lookahead.peek(token::Paren) { let fields = input.parse()?; lookahead = input.lookahead1(); if lookahead.peek(Token![where]) { where_clause = Some(input.parse()?); lookahead = input.lookahead1(); } if lookahead.peek(Token![;]) { let semi = input.parse()?; Ok((where_clause, Fields::Unnamed(fields), Some(semi))) } else { Err(lookahead.error()) } } else if lookahead.peek(token::Brace) { let fields = input.parse()?; Ok((where_clause, Fields::Named(fields), None)) } else if lookahead.peek(Token![;]) { let semi = input.parse()?; Ok((where_clause, Fields::Unit, Some(semi))) } else { Err(lookahead.error()) } } pub(crate) fn data_enum( input: ParseStream, ) -> Result<( Option, token::Brace, Punctuated, )> { let where_clause = input.parse()?; let content; let brace = braced!(content in input); let variants = content.parse_terminated(Variant::parse, Token![,])?; Ok((where_clause, brace, variants)) } pub(crate) fn data_union(input: ParseStream) -> Result<(Option, FieldsNamed)> { let where_clause = input.parse()?; let fields = input.parse()?; Ok((where_clause, fields)) } } #[cfg(feature = "printing")] mod printing { use crate::attr::FilterAttrs; use crate::data::Fields; use crate::derive::{Data, DeriveInput}; use crate::print::TokensOrDefault; use proc_macro2::TokenStream; use quote::ToTokens; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for DeriveInput { fn to_tokens(&self, tokens: &mut TokenStream) { for attr in self.attrs.outer() { attr.to_tokens(tokens); } self.vis.to_tokens(tokens); match &self.data { Data::Struct(d) => d.struct_token.to_tokens(tokens), Data::Enum(d) => d.enum_token.to_tokens(tokens), Data::Union(d) => d.union_token.to_tokens(tokens), } self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); match &self.data { Data::Struct(data) => match &data.fields { Fields::Named(fields) => { self.generics.where_clause.to_tokens(tokens); fields.to_tokens(tokens); } Fields::Unnamed(fields) => { fields.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); TokensOrDefault(&data.semi_token).to_tokens(tokens); } Fields::Unit => { self.generics.where_clause.to_tokens(tokens); TokensOrDefault(&data.semi_token).to_tokens(tokens); } }, Data::Enum(data) => { self.generics.where_clause.to_tokens(tokens); data.brace_token.surround(tokens, |tokens| { data.variants.to_tokens(tokens); }); } Data::Union(data) => { self.generics.where_clause.to_tokens(tokens); data.fields.to_tokens(tokens); } } } } } syn/src/parse.rs0000644000175000017500000013330714661133735014630 0ustar jamespagejamespage//! Parsing interface for parsing a token stream into a syntax tree node. //! //! Parsing in Syn is built on parser functions that take in a [`ParseStream`] //! and produce a [`Result`] where `T` is some syntax tree node. Underlying //! these parser functions is a lower level mechanism built around the //! [`Cursor`] type. `Cursor` is a cheaply copyable cursor over a range of //! tokens in a token stream. //! //! [`Result`]: Result //! [`Cursor`]: crate::buffer::Cursor //! //! # Example //! //! Here is a snippet of parsing code to get a feel for the style of the //! library. We define data structures for a subset of Rust syntax including //! enums (not shown) and structs, then provide implementations of the [`Parse`] //! trait to parse these syntax tree data structures from a token stream. //! //! Once `Parse` impls have been defined, they can be called conveniently from a //! procedural macro through [`parse_macro_input!`] as shown at the bottom of //! the snippet. If the caller provides syntactically invalid input to the //! procedural macro, they will receive a helpful compiler error message //! pointing out the exact token that triggered the failure to parse. //! //! [`parse_macro_input!`]: crate::parse_macro_input! //! //! ``` //! # extern crate proc_macro; //! # //! use proc_macro::TokenStream; //! use syn::{braced, parse_macro_input, token, Field, Ident, Result, Token}; //! use syn::parse::{Parse, ParseStream}; //! use syn::punctuated::Punctuated; //! //! enum Item { //! Struct(ItemStruct), //! Enum(ItemEnum), //! } //! //! struct ItemStruct { //! struct_token: Token![struct], //! ident: Ident, //! brace_token: token::Brace, //! fields: Punctuated, //! } //! # //! # enum ItemEnum {} //! //! impl Parse for Item { //! fn parse(input: ParseStream) -> Result { //! let lookahead = input.lookahead1(); //! if lookahead.peek(Token![struct]) { //! input.parse().map(Item::Struct) //! } else if lookahead.peek(Token![enum]) { //! input.parse().map(Item::Enum) //! } else { //! Err(lookahead.error()) //! } //! } //! } //! //! impl Parse for ItemStruct { //! fn parse(input: ParseStream) -> Result { //! let content; //! Ok(ItemStruct { //! struct_token: input.parse()?, //! ident: input.parse()?, //! brace_token: braced!(content in input), //! fields: content.parse_terminated(Field::parse_named, Token![,])?, //! }) //! } //! } //! # //! # impl Parse for ItemEnum { //! # fn parse(input: ParseStream) -> Result { //! # unimplemented!() //! # } //! # } //! //! # const IGNORE: &str = stringify! { //! #[proc_macro] //! # }; //! pub fn my_macro(tokens: TokenStream) -> TokenStream { //! let input = parse_macro_input!(tokens as Item); //! //! /* ... */ //! # TokenStream::new() //! } //! ``` //! //! # The `syn::parse*` functions //! //! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve //! as an entry point for parsing syntax tree nodes that can be parsed in an //! obvious default way. These functions can return any syntax tree node that //! implements the [`Parse`] trait, which includes most types in Syn. //! //! [`syn::parse`]: crate::parse() //! [`syn::parse2`]: crate::parse2() //! [`syn::parse_str`]: crate::parse_str() //! //! ``` //! use syn::Type; //! //! # fn run_parser() -> syn::Result<()> { //! let t: Type = syn::parse_str("std::collections::HashMap")?; //! # Ok(()) //! # } //! # //! # run_parser().unwrap(); //! ``` //! //! The [`parse_quote!`] macro also uses this approach. //! //! [`parse_quote!`]: crate::parse_quote! //! //! # The `Parser` trait //! //! Some types can be parsed in several ways depending on context. For example //! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like //! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`] //! may or may not allow trailing punctuation, and parsing it the wrong way //! would either reject valid input or accept invalid input. //! //! [`Attribute`]: crate::Attribute //! [`Punctuated`]: crate::punctuated //! //! The `Parse` trait is not implemented in these cases because there is no good //! behavior to consider the default. //! //! ```compile_fail //! # extern crate proc_macro; //! # //! # use syn::punctuated::Punctuated; //! # use syn::{PathSegment, Result, Token}; //! # //! # fn f(tokens: proc_macro::TokenStream) -> Result<()> { //! # //! // Can't parse `Punctuated` without knowing whether trailing punctuation //! // should be allowed in this context. //! let path: Punctuated = syn::parse(tokens)?; //! # //! # Ok(()) //! # } //! ``` //! //! In these cases the types provide a choice of parser functions rather than a //! single `Parse` implementation, and those parser functions can be invoked //! through the [`Parser`] trait. //! //! //! ``` //! # extern crate proc_macro; //! # //! use proc_macro::TokenStream; //! use syn::parse::Parser; //! use syn::punctuated::Punctuated; //! use syn::{Attribute, Expr, PathSegment, Result, Token}; //! //! fn call_some_parser_methods(input: TokenStream) -> Result<()> { //! // Parse a nonempty sequence of path segments separated by `::` punctuation //! // with no trailing punctuation. //! let tokens = input.clone(); //! let parser = Punctuated::::parse_separated_nonempty; //! let _path = parser.parse(tokens)?; //! //! // Parse a possibly empty sequence of expressions terminated by commas with //! // an optional trailing punctuation. //! let tokens = input.clone(); //! let parser = Punctuated::::parse_terminated; //! let _args = parser.parse(tokens)?; //! //! // Parse zero or more outer attributes but not inner attributes. //! let tokens = input.clone(); //! let parser = Attribute::parse_outer; //! let _attrs = parser.parse(tokens)?; //! //! Ok(()) //! } //! ``` #[path = "discouraged.rs"] pub mod discouraged; use crate::buffer::{Cursor, TokenBuffer}; use crate::error; use crate::lookahead; use crate::punctuated::Punctuated; use crate::token::Token; use proc_macro2::{Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree}; #[cfg(feature = "printing")] use quote::ToTokens; use std::cell::Cell; use std::fmt::{self, Debug, Display}; #[cfg(feature = "extra-traits")] use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; use std::ops::Deref; use std::panic::{RefUnwindSafe, UnwindSafe}; use std::rc::Rc; use std::str::FromStr; pub use crate::error::{Error, Result}; pub use crate::lookahead::{Lookahead1, Peek}; /// Parsing interface implemented by all types that can be parsed in a default /// way from a token stream. /// /// Refer to the [module documentation] for details about implementing and using /// the `Parse` trait. /// /// [module documentation]: self pub trait Parse: Sized { fn parse(input: ParseStream) -> Result; } /// Input to a Syn parser function. /// /// See the methods of this type under the documentation of [`ParseBuffer`]. For /// an overview of parsing in Syn, refer to the [module documentation]. /// /// [module documentation]: self pub type ParseStream<'a> = &'a ParseBuffer<'a>; /// Cursor position within a buffered token stream. /// /// This type is more commonly used through the type alias [`ParseStream`] which /// is an alias for `&ParseBuffer`. /// /// `ParseStream` is the input type for all parser functions in Syn. They have /// the signature `fn(ParseStream) -> Result`. /// /// ## Calling a parser function /// /// There is no public way to construct a `ParseBuffer`. Instead, if you are /// looking to invoke a parser function that requires `ParseStream` as input, /// you will need to go through one of the public parsing entry points. /// /// - The [`parse_macro_input!`] macro if parsing input of a procedural macro; /// - One of [the `syn::parse*` functions][syn-parse]; or /// - A method of the [`Parser`] trait. /// /// [`parse_macro_input!`]: crate::parse_macro_input! /// [syn-parse]: self#the-synparse-functions pub struct ParseBuffer<'a> { scope: Span, // Instead of Cell> so that ParseBuffer<'a> is covariant in 'a. // The rest of the code in this module needs to be careful that only a // cursor derived from this `cell` is ever assigned to this `cell`. // // Cell> cannot be covariant in 'a because then we could take a // ParseBuffer<'a>, upcast to ParseBuffer<'short> for some lifetime shorter // than 'a, and then assign a Cursor<'short> into the Cell. // // By extension, it would not be safe to expose an API that accepts a // Cursor<'a> and trusts that it lives as long as the cursor currently in // the cell. cell: Cell>, marker: PhantomData>, unexpected: Cell>>>, } impl<'a> Drop for ParseBuffer<'a> { fn drop(&mut self) { if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(self.cursor()) { let (inner, old_span) = inner_unexpected(self); if old_span.is_none() { inner.set(Unexpected::Some(unexpected_span)); } } } } impl<'a> Display for ParseBuffer<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Display::fmt(&self.cursor().token_stream(), f) } } impl<'a> Debug for ParseBuffer<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.cursor().token_stream(), f) } } impl<'a> UnwindSafe for ParseBuffer<'a> {} impl<'a> RefUnwindSafe for ParseBuffer<'a> {} /// Cursor state associated with speculative parsing. /// /// This type is the input of the closure provided to [`ParseStream::step`]. /// /// [`ParseStream::step`]: ParseBuffer::step /// /// # Example /// /// ``` /// use proc_macro2::TokenTree; /// use syn::Result; /// use syn::parse::ParseStream; /// /// // This function advances the stream past the next occurrence of `@`. If /// // no `@` is present in the stream, the stream position is unchanged and /// // an error is returned. /// fn skip_past_next_at(input: ParseStream) -> Result<()> { /// input.step(|cursor| { /// let mut rest = *cursor; /// while let Some((tt, next)) = rest.token_tree() { /// match &tt { /// TokenTree::Punct(punct) if punct.as_char() == '@' => { /// return Ok(((), next)); /// } /// _ => rest = next, /// } /// } /// Err(cursor.error("no `@` was found after this point")) /// }) /// } /// # /// # fn remainder_after_skipping_past_next_at( /// # input: ParseStream, /// # ) -> Result { /// # skip_past_next_at(input)?; /// # input.parse() /// # } /// # /// # use syn::parse::Parser; /// # let remainder = remainder_after_skipping_past_next_at /// # .parse_str("a @ b c") /// # .unwrap(); /// # assert_eq!(remainder.to_string(), "b c"); /// ``` pub struct StepCursor<'c, 'a> { scope: Span, // This field is covariant in 'c. cursor: Cursor<'c>, // This field is contravariant in 'c. Together these make StepCursor // invariant in 'c. Also covariant in 'a. The user cannot cast 'c to a // different lifetime but can upcast into a StepCursor with a shorter // lifetime 'a. // // As long as we only ever construct a StepCursor for which 'c outlives 'a, // this means if ever a StepCursor<'c, 'a> exists we are guaranteed that 'c // outlives 'a. marker: PhantomData) -> Cursor<'a>>, } impl<'c, 'a> Deref for StepCursor<'c, 'a> { type Target = Cursor<'c>; fn deref(&self) -> &Self::Target { &self.cursor } } impl<'c, 'a> Copy for StepCursor<'c, 'a> {} impl<'c, 'a> Clone for StepCursor<'c, 'a> { fn clone(&self) -> Self { *self } } impl<'c, 'a> StepCursor<'c, 'a> { /// Triggers an error at the current position of the parse stream. /// /// The `ParseStream::step` invocation will return this same error without /// advancing the stream state. pub fn error(self, message: T) -> Error { error::new_at(self.scope, self.cursor, message) } } pub(crate) fn advance_step_cursor<'c, 'a>(proof: StepCursor<'c, 'a>, to: Cursor<'c>) -> Cursor<'a> { // Refer to the comments within the StepCursor definition. We use the // fact that a StepCursor<'c, 'a> exists as proof that 'c outlives 'a. // Cursor is covariant in its lifetime parameter so we can cast a // Cursor<'c> to one with the shorter lifetime Cursor<'a>. let _ = proof; unsafe { mem::transmute::, Cursor<'a>>(to) } } pub(crate) fn new_parse_buffer( scope: Span, cursor: Cursor, unexpected: Rc>, ) -> ParseBuffer { ParseBuffer { scope, // See comment on `cell` in the struct definition. cell: Cell::new(unsafe { mem::transmute::>(cursor) }), marker: PhantomData, unexpected: Cell::new(Some(unexpected)), } } pub(crate) enum Unexpected { None, Some(Span), Chain(Rc>), } impl Default for Unexpected { fn default() -> Self { Unexpected::None } } impl Clone for Unexpected { fn clone(&self) -> Self { match self { Unexpected::None => Unexpected::None, Unexpected::Some(span) => Unexpected::Some(*span), Unexpected::Chain(next) => Unexpected::Chain(next.clone()), } } } // We call this on Cell and Cell> where temporarily // swapping in a None is cheap. fn cell_clone(cell: &Cell) -> T { let prev = cell.take(); let ret = prev.clone(); cell.set(prev); ret } fn inner_unexpected(buffer: &ParseBuffer) -> (Rc>, Option) { let mut unexpected = get_unexpected(buffer); loop { match cell_clone(&unexpected) { Unexpected::None => return (unexpected, None), Unexpected::Some(span) => return (unexpected, Some(span)), Unexpected::Chain(next) => unexpected = next, } } } pub(crate) fn get_unexpected(buffer: &ParseBuffer) -> Rc> { cell_clone(&buffer.unexpected).unwrap() } fn span_of_unexpected_ignoring_nones(mut cursor: Cursor) -> Option { if cursor.eof() { return None; } while let Some((inner, _span, rest)) = cursor.group(Delimiter::None) { if let Some(unexpected) = span_of_unexpected_ignoring_nones(inner) { return Some(unexpected); } cursor = rest; } if cursor.eof() { None } else { Some(cursor.span()) } } impl<'a> ParseBuffer<'a> { /// Parses a syntax tree node of type `T`, advancing the position of our /// parse stream past it. pub fn parse(&self) -> Result { T::parse(self) } /// Calls the given parser function to parse a syntax tree node of type `T` /// from this stream. /// /// # Example /// /// The parser below invokes [`Attribute::parse_outer`] to parse a vector of /// zero or more outer attributes. /// /// [`Attribute::parse_outer`]: crate::Attribute::parse_outer /// /// ``` /// use syn::{Attribute, Ident, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses a unit struct with attributes. /// // /// // #[path = "s.tmpl"] /// // struct S; /// struct UnitStruct { /// attrs: Vec, /// struct_token: Token![struct], /// name: Ident, /// semi_token: Token![;], /// } /// /// impl Parse for UnitStruct { /// fn parse(input: ParseStream) -> Result { /// Ok(UnitStruct { /// attrs: input.call(Attribute::parse_outer)?, /// struct_token: input.parse()?, /// name: input.parse()?, /// semi_token: input.parse()?, /// }) /// } /// } /// ``` pub fn call(&self, function: fn(ParseStream) -> Result) -> Result { function(self) } /// Looks at the next token in the parse stream to determine whether it /// matches the requested type of token. /// /// Does not advance the position of the parse stream. /// /// # Syntax /// /// Note that this method does not use turbofish syntax. Pass the peek type /// inside of parentheses. /// /// - `input.peek(Token![struct])` /// - `input.peek(Token![==])` /// - `input.peek(syn::Ident)` *(does not accept keywords)* /// - `input.peek(syn::Ident::peek_any)` /// - `input.peek(Lifetime)` /// - `input.peek(token::Brace)` /// /// # Example /// /// In this example we finish parsing the list of supertraits when the next /// token in the input is either `where` or an opening curly brace. /// /// ``` /// use syn::{braced, token, Generics, Ident, Result, Token, TypeParamBound}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// // Parses a trait definition containing no associated items. /// // /// // trait Marker<'de, T>: A + B<'de> where Box: Clone {} /// struct MarkerTrait { /// trait_token: Token![trait], /// ident: Ident, /// generics: Generics, /// colon_token: Option, /// supertraits: Punctuated, /// brace_token: token::Brace, /// } /// /// impl Parse for MarkerTrait { /// fn parse(input: ParseStream) -> Result { /// let trait_token: Token![trait] = input.parse()?; /// let ident: Ident = input.parse()?; /// let mut generics: Generics = input.parse()?; /// let colon_token: Option = input.parse()?; /// /// let mut supertraits = Punctuated::new(); /// if colon_token.is_some() { /// loop { /// supertraits.push_value(input.parse()?); /// if input.peek(Token![where]) || input.peek(token::Brace) { /// break; /// } /// supertraits.push_punct(input.parse()?); /// } /// } /// /// generics.where_clause = input.parse()?; /// let content; /// let empty_brace_token = braced!(content in input); /// /// Ok(MarkerTrait { /// trait_token, /// ident, /// generics, /// colon_token, /// supertraits, /// brace_token: empty_brace_token, /// }) /// } /// } /// ``` pub fn peek(&self, token: T) -> bool { let _ = token; T::Token::peek(self.cursor()) } /// Looks at the second-next token in the parse stream. /// /// This is commonly useful as a way to implement contextual keywords. /// /// # Example /// /// This example needs to use `peek2` because the symbol `union` is not a /// keyword in Rust. We can't use just `peek` and decide to parse a union if /// the very next token is `union`, because someone is free to write a `mod /// union` and a macro invocation that looks like `union::some_macro! { ... /// }`. In other words `union` is a contextual keyword. /// /// ``` /// use syn::{Ident, ItemUnion, Macro, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses either a union or a macro invocation. /// enum UnionOrMacro { /// // union MaybeUninit { uninit: (), value: T } /// Union(ItemUnion), /// // lazy_static! { ... } /// Macro(Macro), /// } /// /// impl Parse for UnionOrMacro { /// fn parse(input: ParseStream) -> Result { /// if input.peek(Token![union]) && input.peek2(Ident) { /// input.parse().map(UnionOrMacro::Union) /// } else { /// input.parse().map(UnionOrMacro::Macro) /// } /// } /// } /// ``` pub fn peek2(&self, token: T) -> bool { fn peek2(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool { buffer.cursor().skip().map_or(false, peek) } let _ = token; peek2(self, T::Token::peek) } /// Looks at the third-next token in the parse stream. pub fn peek3(&self, token: T) -> bool { fn peek3(buffer: &ParseBuffer, peek: fn(Cursor) -> bool) -> bool { buffer .cursor() .skip() .and_then(Cursor::skip) .map_or(false, peek) } let _ = token; peek3(self, T::Token::peek) } /// Parses zero or more occurrences of `T` separated by punctuation of type /// `P`, with optional trailing punctuation. /// /// Parsing continues until the end of this parse stream. The entire content /// of this parse stream must consist of `T` and `P`. /// /// # Example /// /// ``` /// # use quote::quote; /// # /// use syn::{parenthesized, token, Ident, Result, Token, Type}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// // Parse a simplified tuple struct syntax like: /// // /// // struct S(A, B); /// struct TupleStruct { /// struct_token: Token![struct], /// ident: Ident, /// paren_token: token::Paren, /// fields: Punctuated, /// semi_token: Token![;], /// } /// /// impl Parse for TupleStruct { /// fn parse(input: ParseStream) -> Result { /// let content; /// Ok(TupleStruct { /// struct_token: input.parse()?, /// ident: input.parse()?, /// paren_token: parenthesized!(content in input), /// fields: content.parse_terminated(Type::parse, Token![,])?, /// semi_token: input.parse()?, /// }) /// } /// } /// # /// # let input = quote! { /// # struct S(A, B); /// # }; /// # syn::parse2::(input).unwrap(); /// ``` /// /// # See also /// /// If your separator is anything more complicated than an invocation of the /// `Token!` macro, this method won't be applicable and you can instead /// directly use `Punctuated`'s parser functions: [`parse_terminated`], /// [`parse_separated_nonempty`] etc. /// /// [`parse_terminated`]: Punctuated::parse_terminated /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty /// /// ``` /// use syn::{custom_keyword, Expr, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// mod kw { /// syn::custom_keyword!(fin); /// } /// /// struct Fin(kw::fin, Token![;]); /// /// impl Parse for Fin { /// fn parse(input: ParseStream) -> Result { /// Ok(Self(input.parse()?, input.parse()?)) /// } /// } /// /// struct Thing { /// steps: Punctuated, /// } /// /// impl Parse for Thing { /// fn parse(input: ParseStream) -> Result { /// # if true { /// Ok(Thing { /// steps: Punctuated::parse_terminated(input)?, /// }) /// # } else { /// // or equivalently, this means the same thing: /// # Ok(Thing { /// steps: input.call(Punctuated::parse_terminated)?, /// # }) /// # } /// } /// } /// ``` pub fn parse_terminated( &self, parser: fn(ParseStream) -> Result, separator: P, ) -> Result> where P: Peek, P::Token: Parse, { let _ = separator; Punctuated::parse_terminated_with(self, parser) } /// Returns whether there are no more tokens remaining to be parsed from /// this stream. /// /// This method returns true upon reaching the end of the content within a /// set of delimiters, as well as at the end of the tokens provided to the /// outermost parsing entry point. /// /// # Example /// /// ``` /// use syn::{braced, token, Ident, Item, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parses a Rust `mod m { ... }` containing zero or more items. /// struct Mod { /// mod_token: Token![mod], /// name: Ident, /// brace_token: token::Brace, /// items: Vec, /// } /// /// impl Parse for Mod { /// fn parse(input: ParseStream) -> Result { /// let content; /// Ok(Mod { /// mod_token: input.parse()?, /// name: input.parse()?, /// brace_token: braced!(content in input), /// items: { /// let mut items = Vec::new(); /// while !content.is_empty() { /// items.push(content.parse()?); /// } /// items /// }, /// }) /// } /// } /// ``` pub fn is_empty(&self) -> bool { self.cursor().eof() } /// Constructs a helper for peeking at the next token in this stream and /// building an error message if it is not one of a set of expected tokens. /// /// # Example /// /// ``` /// use syn::{ConstParam, Ident, Lifetime, LifetimeParam, Result, Token, TypeParam}; /// use syn::parse::{Parse, ParseStream}; /// /// // A generic parameter, a single one of the comma-separated elements inside /// // angle brackets in: /// // /// // fn f() { ... } /// // /// // On invalid input, lookahead gives us a reasonable error message. /// // /// // error: expected one of: identifier, lifetime, `const` /// // | /// // 5 | fn f() {} /// // | ^ /// enum GenericParam { /// Type(TypeParam), /// Lifetime(LifetimeParam), /// Const(ConstParam), /// } /// /// impl Parse for GenericParam { /// fn parse(input: ParseStream) -> Result { /// let lookahead = input.lookahead1(); /// if lookahead.peek(Ident) { /// input.parse().map(GenericParam::Type) /// } else if lookahead.peek(Lifetime) { /// input.parse().map(GenericParam::Lifetime) /// } else if lookahead.peek(Token![const]) { /// input.parse().map(GenericParam::Const) /// } else { /// Err(lookahead.error()) /// } /// } /// } /// ``` pub fn lookahead1(&self) -> Lookahead1<'a> { lookahead::new(self.scope, self.cursor()) } /// Forks a parse stream so that parsing tokens out of either the original /// or the fork does not advance the position of the other. /// /// # Performance /// /// Forking a parse stream is a cheap fixed amount of work and does not /// involve copying token buffers. Where you might hit performance problems /// is if your macro ends up parsing a large amount of content more than /// once. /// /// ``` /// # use syn::{Expr, Result}; /// # use syn::parse::ParseStream; /// # /// # fn bad(input: ParseStream) -> Result { /// // Do not do this. /// if input.fork().parse::().is_ok() { /// return input.parse::(); /// } /// # unimplemented!() /// # } /// ``` /// /// As a rule, avoid parsing an unbounded amount of tokens out of a forked /// parse stream. Only use a fork when the amount of work performed against /// the fork is small and bounded. /// /// When complex speculative parsing against the forked stream is /// unavoidable, use [`parse::discouraged::Speculative`] to advance the /// original stream once the fork's parse is determined to have been /// successful. /// /// For a lower level way to perform speculative parsing at the token level, /// consider using [`ParseStream::step`] instead. /// /// [`parse::discouraged::Speculative`]: discouraged::Speculative /// [`ParseStream::step`]: ParseBuffer::step /// /// # Example /// /// The parse implementation shown here parses possibly restricted `pub` /// visibilities. /// /// - `pub` /// - `pub(crate)` /// - `pub(self)` /// - `pub(super)` /// - `pub(in some::path)` /// /// To handle the case of visibilities inside of tuple structs, the parser /// needs to distinguish parentheses that specify visibility restrictions /// from parentheses that form part of a tuple type. /// /// ``` /// # struct A; /// # struct B; /// # struct C; /// # /// struct S(pub(crate) A, pub (B, C)); /// ``` /// /// In this example input the first tuple struct element of `S` has /// `pub(crate)` visibility while the second tuple struct element has `pub` /// visibility; the parentheses around `(B, C)` are part of the type rather /// than part of a visibility restriction. /// /// The parser uses a forked parse stream to check the first token inside of /// parentheses after the `pub` keyword. This is a small bounded amount of /// work performed against the forked parse stream. /// /// ``` /// use syn::{parenthesized, token, Ident, Path, Result, Token}; /// use syn::ext::IdentExt; /// use syn::parse::{Parse, ParseStream}; /// /// struct PubVisibility { /// pub_token: Token![pub], /// restricted: Option, /// } /// /// struct Restricted { /// paren_token: token::Paren, /// in_token: Option, /// path: Path, /// } /// /// impl Parse for PubVisibility { /// fn parse(input: ParseStream) -> Result { /// let pub_token: Token![pub] = input.parse()?; /// /// if input.peek(token::Paren) { /// let ahead = input.fork(); /// let mut content; /// parenthesized!(content in ahead); /// /// if content.peek(Token![crate]) /// || content.peek(Token![self]) /// || content.peek(Token![super]) /// { /// return Ok(PubVisibility { /// pub_token, /// restricted: Some(Restricted { /// paren_token: parenthesized!(content in input), /// in_token: None, /// path: Path::from(content.call(Ident::parse_any)?), /// }), /// }); /// } else if content.peek(Token![in]) { /// return Ok(PubVisibility { /// pub_token, /// restricted: Some(Restricted { /// paren_token: parenthesized!(content in input), /// in_token: Some(content.parse()?), /// path: content.call(Path::parse_mod_style)?, /// }), /// }); /// } /// } /// /// Ok(PubVisibility { /// pub_token, /// restricted: None, /// }) /// } /// } /// ``` pub fn fork(&self) -> Self { ParseBuffer { scope: self.scope, cell: self.cell.clone(), marker: PhantomData, // Not the parent's unexpected. Nothing cares whether the clone // parses all the way unless we `advance_to`. unexpected: Cell::new(Some(Rc::new(Cell::new(Unexpected::None)))), } } /// Triggers an error at the current position of the parse stream. /// /// # Example /// /// ``` /// use syn::{Expr, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Some kind of loop: `while` or `for` or `loop`. /// struct Loop { /// expr: Expr, /// } /// /// impl Parse for Loop { /// fn parse(input: ParseStream) -> Result { /// if input.peek(Token![while]) /// || input.peek(Token![for]) /// || input.peek(Token![loop]) /// { /// Ok(Loop { /// expr: input.parse()?, /// }) /// } else { /// Err(input.error("expected some kind of loop")) /// } /// } /// } /// ``` pub fn error(&self, message: T) -> Error { error::new_at(self.scope, self.cursor(), message) } /// Speculatively parses tokens from this parse stream, advancing the /// position of this stream only if parsing succeeds. /// /// This is a powerful low-level API used for defining the `Parse` impls of /// the basic built-in token types. It is not something that will be used /// widely outside of the Syn codebase. /// /// # Example /// /// ``` /// use proc_macro2::TokenTree; /// use syn::Result; /// use syn::parse::ParseStream; /// /// // This function advances the stream past the next occurrence of `@`. If /// // no `@` is present in the stream, the stream position is unchanged and /// // an error is returned. /// fn skip_past_next_at(input: ParseStream) -> Result<()> { /// input.step(|cursor| { /// let mut rest = *cursor; /// while let Some((tt, next)) = rest.token_tree() { /// match &tt { /// TokenTree::Punct(punct) if punct.as_char() == '@' => { /// return Ok(((), next)); /// } /// _ => rest = next, /// } /// } /// Err(cursor.error("no `@` was found after this point")) /// }) /// } /// # /// # fn remainder_after_skipping_past_next_at( /// # input: ParseStream, /// # ) -> Result { /// # skip_past_next_at(input)?; /// # input.parse() /// # } /// # /// # use syn::parse::Parser; /// # let remainder = remainder_after_skipping_past_next_at /// # .parse_str("a @ b c") /// # .unwrap(); /// # assert_eq!(remainder.to_string(), "b c"); /// ``` pub fn step(&self, function: F) -> Result where F: for<'c> FnOnce(StepCursor<'c, 'a>) -> Result<(R, Cursor<'c>)>, { // Since the user's function is required to work for any 'c, we know // that the Cursor<'c> they return is either derived from the input // StepCursor<'c, 'a> or from a Cursor<'static>. // // It would not be legal to write this function without the invariant // lifetime 'c in StepCursor<'c, 'a>. If this function were written only // in terms of 'a, the user could take our ParseBuffer<'a>, upcast it to // a ParseBuffer<'short> which some shorter lifetime than 'a, invoke // `step` on their ParseBuffer<'short> with a closure that returns // Cursor<'short>, and we would wrongly write that Cursor<'short> into // the Cell intended to hold Cursor<'a>. // // In some cases it may be necessary for R to contain a Cursor<'a>. // Within Syn we solve this using `advance_step_cursor` which uses the // existence of a StepCursor<'c, 'a> as proof that it is safe to cast // from Cursor<'c> to Cursor<'a>. If needed outside of Syn, it would be // safe to expose that API as a method on StepCursor. let (node, rest) = function(StepCursor { scope: self.scope, cursor: self.cell.get(), marker: PhantomData, })?; self.cell.set(rest); Ok(node) } /// Returns the `Span` of the next token in the parse stream, or /// `Span::call_site()` if this parse stream has completely exhausted its /// input `TokenStream`. pub fn span(&self) -> Span { let cursor = self.cursor(); if cursor.eof() { self.scope } else { crate::buffer::open_span_of_group(cursor) } } /// Provides low-level access to the token representation underlying this /// parse stream. /// /// Cursors are immutable so no operations you perform against the cursor /// will affect the state of this parse stream. /// /// # Example /// /// ``` /// use proc_macro2::TokenStream; /// use syn::buffer::Cursor; /// use syn::parse::{ParseStream, Result}; /// /// // Run a parser that returns T, but get its output as TokenStream instead of T. /// // This works without T needing to implement ToTokens. /// fn recognize_token_stream( /// recognizer: fn(ParseStream) -> Result, /// ) -> impl Fn(ParseStream) -> Result { /// move |input| { /// let begin = input.cursor(); /// recognizer(input)?; /// let end = input.cursor(); /// Ok(tokens_between(begin, end)) /// } /// } /// /// // Collect tokens between two cursors as a TokenStream. /// fn tokens_between(begin: Cursor, end: Cursor) -> TokenStream { /// assert!(begin <= end); /// /// let mut cursor = begin; /// let mut tokens = TokenStream::new(); /// while cursor < end { /// let (token, next) = cursor.token_tree().unwrap(); /// tokens.extend(std::iter::once(token)); /// cursor = next; /// } /// tokens /// } /// /// fn main() { /// use quote::quote; /// use syn::parse::{Parse, Parser}; /// use syn::Token; /// /// // Parse syn::Type as a TokenStream, surrounded by angle brackets. /// fn example(input: ParseStream) -> Result { /// let _langle: Token![<] = input.parse()?; /// let ty = recognize_token_stream(syn::Type::parse)(input)?; /// let _rangle: Token![>] = input.parse()?; /// Ok(ty) /// } /// /// let tokens = quote! { u8> }; /// println!("{}", example.parse2(tokens).unwrap()); /// } /// ``` pub fn cursor(&self) -> Cursor<'a> { self.cell.get() } fn check_unexpected(&self) -> Result<()> { match inner_unexpected(self).1 { Some(span) => Err(Error::new(span, "unexpected token")), None => Ok(()), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Box { fn parse(input: ParseStream) -> Result { input.parse().map(Box::new) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if T::peek(input.cursor()) { Ok(Some(input.parse()?)) } else { Ok(None) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TokenStream { fn parse(input: ParseStream) -> Result { input.step(|cursor| Ok((cursor.token_stream(), Cursor::empty()))) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TokenTree { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.token_tree() { Some((tt, rest)) => Ok((tt, rest)), None => Err(cursor.error("expected token tree")), }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Group { fn parse(input: ParseStream) -> Result { input.step(|cursor| { if let Some((group, rest)) = cursor.any_group_token() { if group.delimiter() != Delimiter::None { return Ok((group, rest)); } } Err(cursor.error("expected group token")) }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Punct { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.punct() { Some((punct, rest)) => Ok((punct, rest)), None => Err(cursor.error("expected punctuation token")), }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Literal { fn parse(input: ParseStream) -> Result { input.step(|cursor| match cursor.literal() { Some((literal, rest)) => Ok((literal, rest)), None => Err(cursor.error("expected literal token")), }) } } /// Parser that can parse Rust tokens into a particular syntax tree node. /// /// Refer to the [module documentation] for details about parsing in Syn. /// /// [module documentation]: self pub trait Parser: Sized { type Output; /// Parse a proc-macro2 token stream into the chosen syntax tree node. /// /// This function will check that the input is fully parsed. If there are /// any unparsed tokens at the end of the stream, an error is returned. fn parse2(self, tokens: TokenStream) -> Result; /// Parse tokens of source code into the chosen syntax tree node. /// /// This function will check that the input is fully parsed. If there are /// any unparsed tokens at the end of the stream, an error is returned. #[cfg(feature = "proc-macro")] #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] fn parse(self, tokens: proc_macro::TokenStream) -> Result { self.parse2(proc_macro2::TokenStream::from(tokens)) } /// Parse a string of Rust code into the chosen syntax tree node. /// /// This function will check that the input is fully parsed. If there are /// any unparsed tokens at the end of the string, an error is returned. /// /// # Hygiene /// /// Every span in the resulting syntax tree will be set to resolve at the /// macro call site. fn parse_str(self, s: &str) -> Result { self.parse2(proc_macro2::TokenStream::from_str(s)?) } // Not public API. #[doc(hidden)] fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result { let _ = scope; self.parse2(tokens) } } fn tokens_to_parse_buffer(tokens: &TokenBuffer) -> ParseBuffer { let scope = Span::call_site(); let cursor = tokens.begin(); let unexpected = Rc::new(Cell::new(Unexpected::None)); new_parse_buffer(scope, cursor, unexpected) } impl Parser for F where F: FnOnce(ParseStream) -> Result, { type Output = T; fn parse2(self, tokens: TokenStream) -> Result { let buf = TokenBuffer::new2(tokens); let state = tokens_to_parse_buffer(&buf); let node = self(&state)?; state.check_unexpected()?; if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { Err(Error::new(unexpected_span, "unexpected token")) } else { Ok(node) } } fn __parse_scoped(self, scope: Span, tokens: TokenStream) -> Result { let buf = TokenBuffer::new2(tokens); let cursor = buf.begin(); let unexpected = Rc::new(Cell::new(Unexpected::None)); let state = new_parse_buffer(scope, cursor, unexpected); let node = self(&state)?; state.check_unexpected()?; if let Some(unexpected_span) = span_of_unexpected_ignoring_nones(state.cursor()) { Err(Error::new(unexpected_span, "unexpected token")) } else { Ok(node) } } } pub(crate) fn parse_scoped(f: F, scope: Span, tokens: TokenStream) -> Result { f.__parse_scoped(scope, tokens) } /// An empty syntax tree node that consumes no tokens when parsed. /// /// This is useful for attribute macros that want to ensure they are not /// provided any attribute args. /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use syn::parse_macro_input; /// use syn::parse::Nothing; /// /// # const IGNORE: &str = stringify! { /// #[proc_macro_attribute] /// # }; /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream { /// parse_macro_input!(args as Nothing); /// /// /* ... */ /// # TokenStream::new() /// } /// ``` /// /// ```text /// error: unexpected token /// --> src/main.rs:3:19 /// | /// 3 | #[my_attr(asdf)] /// | ^^^^ /// ``` pub struct Nothing; impl Parse for Nothing { fn parse(_input: ParseStream) -> Result { Ok(Nothing) } } #[cfg(feature = "printing")] #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Nothing { fn to_tokens(&self, tokens: &mut TokenStream) { let _ = tokens; } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Nothing { fn clone(&self) -> Self { *self } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for Nothing {} #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for Nothing { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("Nothing") } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Eq for Nothing {} #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for Nothing { fn eq(&self, _other: &Self) -> bool { true } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for Nothing { fn hash(&self, _state: &mut H) {} } syn/src/parse_macro_input.rs0000644000175000017500000000665014661133735017230 0ustar jamespagejamespage/// Parse the input TokenStream of a macro, triggering a compile error if the /// tokens fail to parse. /// /// Refer to the [`parse` module] documentation for more details about parsing /// in Syn. /// /// [`parse` module]: mod@crate::parse /// ///
/// /// # Intended usage /// /// This macro must be called from a function that returns /// `proc_macro::TokenStream`. Usually this will be your proc macro entry point, /// the function that has the #\[proc_macro\] / #\[proc_macro_derive\] / /// #\[proc_macro_attribute\] attribute. /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use syn::{parse_macro_input, Result}; /// use syn::parse::{Parse, ParseStream}; /// /// struct MyMacroInput { /// /* ... */ /// } /// /// impl Parse for MyMacroInput { /// fn parse(input: ParseStream) -> Result { /// /* ... */ /// # Ok(MyMacroInput {}) /// } /// } /// /// # const IGNORE: &str = stringify! { /// #[proc_macro] /// # }; /// pub fn my_macro(tokens: TokenStream) -> TokenStream { /// let input = parse_macro_input!(tokens as MyMacroInput); /// /// /* ... */ /// # TokenStream::new() /// } /// ``` /// ///
/// /// # Usage with Parser /// /// This macro can also be used with the [`Parser` trait] for types that have /// multiple ways that they can be parsed. /// /// [`Parser` trait]: crate::parse::Parser /// /// ``` /// # extern crate proc_macro; /// # /// # use proc_macro::TokenStream; /// # use syn::{parse_macro_input, Result}; /// # use syn::parse::ParseStream; /// # /// # struct MyMacroInput {} /// # /// impl MyMacroInput { /// fn parse_alternate(input: ParseStream) -> Result { /// /* ... */ /// # Ok(MyMacroInput {}) /// } /// } /// /// # const IGNORE: &str = stringify! { /// #[proc_macro] /// # }; /// pub fn my_macro(tokens: TokenStream) -> TokenStream { /// let input = parse_macro_input!(tokens with MyMacroInput::parse_alternate); /// /// /* ... */ /// # TokenStream::new() /// } /// ``` /// ///
/// /// # Expansion /// /// `parse_macro_input!($variable as $Type)` expands to something like: /// /// ```no_run /// # extern crate proc_macro; /// # /// # macro_rules! doc_test { /// # ($variable:ident as $Type:ty) => { /// match syn::parse::<$Type>($variable) { /// Ok(syntax_tree) => syntax_tree, /// Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()), /// } /// # }; /// # } /// # /// # fn test(input: proc_macro::TokenStream) -> proc_macro::TokenStream { /// # let _ = doc_test!(input as syn::Ident); /// # proc_macro::TokenStream::new() /// # } /// ``` #[macro_export] #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))] macro_rules! parse_macro_input { ($tokenstream:ident as $ty:ty) => { match $crate::parse::<$ty>($tokenstream) { $crate::__private::Ok(data) => data, $crate::__private::Err(err) => { return $crate::__private::TokenStream::from(err.to_compile_error()); } } }; ($tokenstream:ident with $parser:path) => { match $crate::parse::Parser::parse($parser, $tokenstream) { $crate::__private::Ok(data) => data, $crate::__private::Err(err) => { return $crate::__private::TokenStream::from(err.to_compile_error()); } } }; ($tokenstream:ident) => { $crate::parse_macro_input!($tokenstream as _) }; } syn/src/token.rs0000644000175000017500000010653614661133735014642 0ustar jamespagejamespage//! Tokens representing Rust punctuation, keywords, and delimiters. //! //! The type names in this module can be difficult to keep straight, so we //! prefer to use the [`Token!`] macro instead. This is a type-macro that //! expands to the token type of the given token. //! //! [`Token!`]: crate::Token //! //! # Example //! //! The [`ItemStatic`] syntax tree node is defined like this. //! //! [`ItemStatic`]: crate::ItemStatic //! //! ``` //! # use syn::{Attribute, Expr, Ident, Token, Type, Visibility}; //! # //! pub struct ItemStatic { //! pub attrs: Vec, //! pub vis: Visibility, //! pub static_token: Token![static], //! pub mutability: Option, //! pub ident: Ident, //! pub colon_token: Token![:], //! pub ty: Box, //! pub eq_token: Token![=], //! pub expr: Box, //! pub semi_token: Token![;], //! } //! ``` //! //! # Parsing //! //! Keywords and punctuation can be parsed through the [`ParseStream::parse`] //! method. Delimiter tokens are parsed using the [`parenthesized!`], //! [`bracketed!`] and [`braced!`] macros. //! //! [`ParseStream::parse`]: crate::parse::ParseBuffer::parse() //! [`parenthesized!`]: crate::parenthesized! //! [`bracketed!`]: crate::bracketed! //! [`braced!`]: crate::braced! //! //! ``` //! use syn::{Attribute, Result}; //! use syn::parse::{Parse, ParseStream}; //! # //! # enum ItemStatic {} //! //! // Parse the ItemStatic struct shown above. //! impl Parse for ItemStatic { //! fn parse(input: ParseStream) -> Result { //! # use syn::ItemStatic; //! # fn parse(input: ParseStream) -> Result { //! Ok(ItemStatic { //! attrs: input.call(Attribute::parse_outer)?, //! vis: input.parse()?, //! static_token: input.parse()?, //! mutability: input.parse()?, //! ident: input.parse()?, //! colon_token: input.parse()?, //! ty: input.parse()?, //! eq_token: input.parse()?, //! expr: input.parse()?, //! semi_token: input.parse()?, //! }) //! # } //! # unimplemented!() //! } //! } //! ``` //! //! # Other operations //! //! Every keyword and punctuation token supports the following operations. //! //! - [Peeking] — `input.peek(Token![...])` //! //! - [Parsing] — `input.parse::()?` //! //! - [Printing] — `quote!( ... #the_token ... )` //! //! - Construction from a [`Span`] — `let the_token = Token![...](sp)` //! //! - Field access to its span — `let sp = the_token.span` //! //! [Peeking]: crate::parse::ParseBuffer::peek() //! [Parsing]: crate::parse::ParseBuffer::parse() //! [Printing]: https://docs.rs/quote/1.0/quote/trait.ToTokens.html //! [`Span`]: https://docs.rs/proc-macro2/1.0/proc_macro2/struct.Span.html #[cfg(feature = "parsing")] pub(crate) use self::private::CustomToken; use self::private::WithSpan; #[cfg(feature = "parsing")] use crate::buffer::Cursor; #[cfg(feature = "parsing")] use crate::error::Result; #[cfg(feature = "parsing")] use crate::lifetime::Lifetime; #[cfg(feature = "parsing")] use crate::parse::{Parse, ParseStream}; use crate::span::IntoSpans; use proc_macro2::extra::DelimSpan; use proc_macro2::Span; #[cfg(feature = "printing")] use proc_macro2::TokenStream; #[cfg(any(feature = "parsing", feature = "printing"))] use proc_macro2::{Delimiter, Ident}; #[cfg(feature = "parsing")] use proc_macro2::{Literal, Punct, TokenTree}; #[cfg(feature = "printing")] use quote::{ToTokens, TokenStreamExt}; #[cfg(feature = "extra-traits")] use std::cmp; #[cfg(feature = "extra-traits")] use std::fmt::{self, Debug}; #[cfg(feature = "extra-traits")] use std::hash::{Hash, Hasher}; use std::ops::{Deref, DerefMut}; /// Marker trait for types that represent single tokens. /// /// This trait is sealed and cannot be implemented for types outside of Syn. #[cfg(feature = "parsing")] pub trait Token: private::Sealed { // Not public API. #[doc(hidden)] fn peek(cursor: Cursor) -> bool; // Not public API. #[doc(hidden)] fn display() -> &'static str; } pub(crate) mod private { #[cfg(feature = "parsing")] use crate::buffer::Cursor; use proc_macro2::Span; #[cfg(feature = "parsing")] pub trait Sealed {} /// Support writing `token.span` rather than `token.spans[0]` on tokens that /// hold a single span. #[repr(transparent)] #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482 pub struct WithSpan { pub span: Span, } // Not public API. #[doc(hidden)] #[cfg(feature = "parsing")] pub trait CustomToken { fn peek(cursor: Cursor) -> bool; fn display() -> &'static str; } } #[cfg(feature = "parsing")] impl private::Sealed for Ident {} macro_rules! impl_low_level_token { ($display:literal $($path:ident)::+ $get:ident) => { #[cfg(feature = "parsing")] impl Token for $($path)::+ { fn peek(cursor: Cursor) -> bool { cursor.$get().is_some() } fn display() -> &'static str { $display } } #[cfg(feature = "parsing")] impl private::Sealed for $($path)::+ {} }; } impl_low_level_token!("punctuation token" Punct punct); impl_low_level_token!("literal" Literal literal); impl_low_level_token!("token" TokenTree token_tree); impl_low_level_token!("group token" proc_macro2::Group any_group); impl_low_level_token!("lifetime" Lifetime lifetime); #[cfg(feature = "parsing")] impl private::Sealed for T {} #[cfg(feature = "parsing")] impl Token for T { fn peek(cursor: Cursor) -> bool { ::peek(cursor) } fn display() -> &'static str { ::display() } } macro_rules! define_keywords { ($($token:literal pub struct $name:ident)*) => { $( #[doc = concat!('`', $token, '`')] /// /// Don't try to remember the name of this type — use the /// [`Token!`] macro instead. /// /// [`Token!`]: crate::token pub struct $name { pub span: Span, } #[doc(hidden)] #[allow(non_snake_case)] pub fn $name>(span: S) -> $name { $name { span: span.into_spans(), } } impl std::default::Default for $name { fn default() -> Self { $name { span: Span::call_site(), } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for $name {} #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $name { fn clone(&self) -> Self { *self } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(stringify!($name)) } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for $name {} #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $name { fn eq(&self, _other: &$name) -> bool { true } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $name { fn hash(&self, _state: &mut H) {} } #[cfg(feature = "printing")] #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for $name { fn to_tokens(&self, tokens: &mut TokenStream) { printing::keyword($token, self.span, tokens); } } #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for $name { fn parse(input: ParseStream) -> Result { Ok($name { span: parsing::keyword(input, $token)?, }) } } #[cfg(feature = "parsing")] impl Token for $name { fn peek(cursor: Cursor) -> bool { parsing::peek_keyword(cursor, $token) } fn display() -> &'static str { concat!("`", $token, "`") } } #[cfg(feature = "parsing")] impl private::Sealed for $name {} )* }; } macro_rules! impl_deref_if_len_is_1 { ($name:ident/1) => { impl Deref for $name { type Target = WithSpan; fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast::() } } } impl DerefMut for $name { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast::() } } } }; ($name:ident/$len:literal) => {}; } macro_rules! define_punctuation_structs { ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => { $( #[cfg_attr(not(doc), repr(transparent))] #[allow(unknown_lints, repr_transparent_external_private_fields)] // False positive: https://github.com/rust-lang/rust/issues/78586#issuecomment-1722680482 #[doc = concat!('`', $token, '`')] /// /// Usage: #[doc = concat!($usage, '.')] /// /// Don't try to remember the name of this type — use the /// [`Token!`] macro instead. /// /// [`Token!`]: crate::token pub struct $name { pub spans: [Span; $len], } #[doc(hidden)] #[allow(non_snake_case)] pub fn $name>(spans: S) -> $name { $name { spans: spans.into_spans(), } } impl std::default::Default for $name { fn default() -> Self { $name { spans: [Span::call_site(); $len], } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for $name {} #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $name { fn clone(&self) -> Self { *self } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(stringify!($name)) } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for $name {} #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $name { fn eq(&self, _other: &$name) -> bool { true } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $name { fn hash(&self, _state: &mut H) {} } impl_deref_if_len_is_1!($name/$len); )* }; } macro_rules! define_punctuation { ($($token:literal pub struct $name:ident/$len:tt #[doc = $usage:literal])*) => { $( define_punctuation_structs! { $token pub struct $name/$len #[doc = $usage] } #[cfg(feature = "printing")] #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for $name { fn to_tokens(&self, tokens: &mut TokenStream) { printing::punct($token, &self.spans, tokens); } } #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for $name { fn parse(input: ParseStream) -> Result { Ok($name { spans: parsing::punct(input, $token)?, }) } } #[cfg(feature = "parsing")] impl Token for $name { fn peek(cursor: Cursor) -> bool { parsing::peek_punct(cursor, $token) } fn display() -> &'static str { concat!("`", $token, "`") } } #[cfg(feature = "parsing")] impl private::Sealed for $name {} )* }; } macro_rules! define_delimiters { ($($delim:ident pub struct $name:ident #[$doc:meta])*) => { $( #[$doc] pub struct $name { pub span: DelimSpan, } #[doc(hidden)] #[allow(non_snake_case)] pub fn $name>(span: S) -> $name { $name { span: span.into_spans(), } } impl std::default::Default for $name { fn default() -> Self { $name(Span::call_site()) } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for $name {} #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $name { fn clone(&self) -> Self { *self } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(stringify!($name)) } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for $name {} #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $name { fn eq(&self, _other: &$name) -> bool { true } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $name { fn hash(&self, _state: &mut H) {} } impl $name { #[cfg(feature = "printing")] pub fn surround(&self, tokens: &mut TokenStream, f: F) where F: FnOnce(&mut TokenStream), { let mut inner = TokenStream::new(); f(&mut inner); printing::delim(Delimiter::$delim, self.span.join(), tokens, inner); } } #[cfg(feature = "parsing")] impl private::Sealed for $name {} )* }; } define_punctuation_structs! { "_" pub struct Underscore/1 /// wildcard patterns, inferred types, unnamed items in constants, extern crates, use declarations, and destructuring assignment } #[cfg(feature = "printing")] #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Underscore { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(Ident::new("_", self.span)); } } #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Underscore { fn parse(input: ParseStream) -> Result { input.step(|cursor| { if let Some((ident, rest)) = cursor.ident() { if ident == "_" { return Ok((Underscore(ident.span()), rest)); } } if let Some((punct, rest)) = cursor.punct() { if punct.as_char() == '_' { return Ok((Underscore(punct.span()), rest)); } } Err(cursor.error("expected `_`")) }) } } #[cfg(feature = "parsing")] impl Token for Underscore { fn peek(cursor: Cursor) -> bool { if let Some((ident, _rest)) = cursor.ident() { return ident == "_"; } if let Some((punct, _rest)) = cursor.punct() { return punct.as_char() == '_'; } false } fn display() -> &'static str { "`_`" } } #[cfg(feature = "parsing")] impl private::Sealed for Underscore {} /// None-delimited group pub struct Group { pub span: Span, } #[doc(hidden)] #[allow(non_snake_case)] pub fn Group>(span: S) -> Group { Group { span: span.into_spans(), } } impl std::default::Default for Group { fn default() -> Self { Group { span: Span::call_site(), } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Copy for Group {} #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for Group { fn clone(&self) -> Self { *self } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for Group { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("Group") } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl cmp::Eq for Group {} #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for Group { fn eq(&self, _other: &Group) -> bool { true } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for Group { fn hash(&self, _state: &mut H) {} } impl Group { #[cfg(feature = "printing")] pub fn surround(&self, tokens: &mut TokenStream, f: F) where F: FnOnce(&mut TokenStream), { let mut inner = TokenStream::new(); f(&mut inner); printing::delim(Delimiter::None, self.span, tokens, inner); } } #[cfg(feature = "parsing")] impl private::Sealed for Group {} #[cfg(feature = "parsing")] impl Token for Paren { fn peek(cursor: Cursor) -> bool { cursor.group(Delimiter::Parenthesis).is_some() } fn display() -> &'static str { "parentheses" } } #[cfg(feature = "parsing")] impl Token for Brace { fn peek(cursor: Cursor) -> bool { cursor.group(Delimiter::Brace).is_some() } fn display() -> &'static str { "curly braces" } } #[cfg(feature = "parsing")] impl Token for Bracket { fn peek(cursor: Cursor) -> bool { cursor.group(Delimiter::Bracket).is_some() } fn display() -> &'static str { "square brackets" } } #[cfg(feature = "parsing")] impl Token for Group { fn peek(cursor: Cursor) -> bool { cursor.group(Delimiter::None).is_some() } fn display() -> &'static str { "invisible group" } } define_keywords! { "abstract" pub struct Abstract "as" pub struct As "async" pub struct Async "auto" pub struct Auto "await" pub struct Await "become" pub struct Become "box" pub struct Box "break" pub struct Break "const" pub struct Const "continue" pub struct Continue "crate" pub struct Crate "default" pub struct Default "do" pub struct Do "dyn" pub struct Dyn "else" pub struct Else "enum" pub struct Enum "extern" pub struct Extern "final" pub struct Final "fn" pub struct Fn "for" pub struct For "if" pub struct If "impl" pub struct Impl "in" pub struct In "let" pub struct Let "loop" pub struct Loop "macro" pub struct Macro "match" pub struct Match "mod" pub struct Mod "move" pub struct Move "mut" pub struct Mut "override" pub struct Override "priv" pub struct Priv "pub" pub struct Pub "ref" pub struct Ref "return" pub struct Return "Self" pub struct SelfType "self" pub struct SelfValue "static" pub struct Static "struct" pub struct Struct "super" pub struct Super "trait" pub struct Trait "try" pub struct Try "type" pub struct Type "typeof" pub struct Typeof "union" pub struct Union "unsafe" pub struct Unsafe "unsized" pub struct Unsized "use" pub struct Use "virtual" pub struct Virtual "where" pub struct Where "while" pub struct While "yield" pub struct Yield } define_punctuation! { "&" pub struct And/1 /// bitwise and logical AND, borrow, references, reference patterns "&&" pub struct AndAnd/2 /// lazy AND, borrow, references, reference patterns "&=" pub struct AndEq/2 /// bitwise AND assignment "@" pub struct At/1 /// subpattern binding "^" pub struct Caret/1 /// bitwise and logical XOR "^=" pub struct CaretEq/2 /// bitwise XOR assignment ":" pub struct Colon/1 /// various separators "," pub struct Comma/1 /// various separators "$" pub struct Dollar/1 /// macros "." pub struct Dot/1 /// field access, tuple index ".." pub struct DotDot/2 /// range, struct expressions, patterns, range patterns "..." pub struct DotDotDot/3 /// variadic functions, range patterns "..=" pub struct DotDotEq/3 /// inclusive range, range patterns "=" pub struct Eq/1 /// assignment, attributes, various type definitions "==" pub struct EqEq/2 /// equal "=>" pub struct FatArrow/2 /// match arms, macros ">=" pub struct Ge/2 /// greater than or equal to, generics ">" pub struct Gt/1 /// greater than, generics, paths "<-" pub struct LArrow/2 /// unused "<=" pub struct Le/2 /// less than or equal to "<" pub struct Lt/1 /// less than, generics, paths "-" pub struct Minus/1 /// subtraction, negation "-=" pub struct MinusEq/2 /// subtraction assignment "!=" pub struct Ne/2 /// not equal "!" pub struct Not/1 /// bitwise and logical NOT, macro calls, inner attributes, never type, negative impls "|" pub struct Or/1 /// bitwise and logical OR, closures, patterns in match, if let, and while let "|=" pub struct OrEq/2 /// bitwise OR assignment "||" pub struct OrOr/2 /// lazy OR, closures "::" pub struct PathSep/2 /// path separator "%" pub struct Percent/1 /// remainder "%=" pub struct PercentEq/2 /// remainder assignment "+" pub struct Plus/1 /// addition, trait bounds, macro Kleene matcher "+=" pub struct PlusEq/2 /// addition assignment "#" pub struct Pound/1 /// attributes "?" pub struct Question/1 /// question mark operator, questionably sized, macro Kleene matcher "->" pub struct RArrow/2 /// function return type, closure return type, function pointer type ";" pub struct Semi/1 /// terminator for various items and statements, array types "<<" pub struct Shl/2 /// shift left, nested generics "<<=" pub struct ShlEq/3 /// shift left assignment ">>" pub struct Shr/2 /// shift right, nested generics ">>=" pub struct ShrEq/3 /// shift right assignment, nested generics "/" pub struct Slash/1 /// division "/=" pub struct SlashEq/2 /// division assignment "*" pub struct Star/1 /// multiplication, dereference, raw pointers, macro Kleene matcher, use wildcards "*=" pub struct StarEq/2 /// multiplication assignment "~" pub struct Tilde/1 /// unused since before Rust 1.0 } define_delimiters! { Brace pub struct Brace /// `{`…`}` Bracket pub struct Bracket /// `[`…`]` Parenthesis pub struct Paren /// `(`…`)` } /// A type-macro that expands to the name of the Rust type representation of a /// given token. /// /// As a type, `Token!` is commonly used in the type of struct fields, the type /// of a `let` statement, or in turbofish for a `parse` function. /// /// ``` /// use syn::{Ident, Token}; /// use syn::parse::{Parse, ParseStream, Result}; /// /// // `struct Foo;` /// pub struct UnitStruct { /// struct_token: Token![struct], /// ident: Ident, /// semi_token: Token![;], /// } /// /// impl Parse for UnitStruct { /// fn parse(input: ParseStream) -> Result { /// let struct_token: Token![struct] = input.parse()?; /// let ident: Ident = input.parse()?; /// let semi_token = input.parse::()?; /// Ok(UnitStruct { struct_token, ident, semi_token }) /// } /// } /// ``` /// /// As an expression, `Token!` is used for peeking tokens or instantiating /// tokens from a span. /// /// ``` /// # use syn::{Ident, Token}; /// # use syn::parse::{Parse, ParseStream, Result}; /// # /// # struct UnitStruct { /// # struct_token: Token![struct], /// # ident: Ident, /// # semi_token: Token![;], /// # } /// # /// # impl Parse for UnitStruct { /// # fn parse(input: ParseStream) -> Result { /// # unimplemented!() /// # } /// # } /// # /// fn make_unit_struct(name: Ident) -> UnitStruct { /// let span = name.span(); /// UnitStruct { /// struct_token: Token![struct](span), /// ident: name, /// semi_token: Token![;](span), /// } /// } /// /// # fn parse(input: ParseStream) -> Result<()> { /// if input.peek(Token![struct]) { /// let unit_struct: UnitStruct = input.parse()?; /// /* ... */ /// } /// # Ok(()) /// # } /// ``` /// /// See the [token module] documentation for details and examples. /// /// [token module]: crate::token #[macro_export] macro_rules! Token { [abstract] => { $crate::token::Abstract }; [as] => { $crate::token::As }; [async] => { $crate::token::Async }; [auto] => { $crate::token::Auto }; [await] => { $crate::token::Await }; [become] => { $crate::token::Become }; [box] => { $crate::token::Box }; [break] => { $crate::token::Break }; [const] => { $crate::token::Const }; [continue] => { $crate::token::Continue }; [crate] => { $crate::token::Crate }; [default] => { $crate::token::Default }; [do] => { $crate::token::Do }; [dyn] => { $crate::token::Dyn }; [else] => { $crate::token::Else }; [enum] => { $crate::token::Enum }; [extern] => { $crate::token::Extern }; [final] => { $crate::token::Final }; [fn] => { $crate::token::Fn }; [for] => { $crate::token::For }; [if] => { $crate::token::If }; [impl] => { $crate::token::Impl }; [in] => { $crate::token::In }; [let] => { $crate::token::Let }; [loop] => { $crate::token::Loop }; [macro] => { $crate::token::Macro }; [match] => { $crate::token::Match }; [mod] => { $crate::token::Mod }; [move] => { $crate::token::Move }; [mut] => { $crate::token::Mut }; [override] => { $crate::token::Override }; [priv] => { $crate::token::Priv }; [pub] => { $crate::token::Pub }; [ref] => { $crate::token::Ref }; [return] => { $crate::token::Return }; [Self] => { $crate::token::SelfType }; [self] => { $crate::token::SelfValue }; [static] => { $crate::token::Static }; [struct] => { $crate::token::Struct }; [super] => { $crate::token::Super }; [trait] => { $crate::token::Trait }; [try] => { $crate::token::Try }; [type] => { $crate::token::Type }; [typeof] => { $crate::token::Typeof }; [union] => { $crate::token::Union }; [unsafe] => { $crate::token::Unsafe }; [unsized] => { $crate::token::Unsized }; [use] => { $crate::token::Use }; [virtual] => { $crate::token::Virtual }; [where] => { $crate::token::Where }; [while] => { $crate::token::While }; [yield] => { $crate::token::Yield }; [&] => { $crate::token::And }; [&&] => { $crate::token::AndAnd }; [&=] => { $crate::token::AndEq }; [@] => { $crate::token::At }; [^] => { $crate::token::Caret }; [^=] => { $crate::token::CaretEq }; [:] => { $crate::token::Colon }; [,] => { $crate::token::Comma }; [$] => { $crate::token::Dollar }; [.] => { $crate::token::Dot }; [..] => { $crate::token::DotDot }; [...] => { $crate::token::DotDotDot }; [..=] => { $crate::token::DotDotEq }; [=] => { $crate::token::Eq }; [==] => { $crate::token::EqEq }; [=>] => { $crate::token::FatArrow }; [>=] => { $crate::token::Ge }; [>] => { $crate::token::Gt }; [<-] => { $crate::token::LArrow }; [<=] => { $crate::token::Le }; [<] => { $crate::token::Lt }; [-] => { $crate::token::Minus }; [-=] => { $crate::token::MinusEq }; [!=] => { $crate::token::Ne }; [!] => { $crate::token::Not }; [|] => { $crate::token::Or }; [|=] => { $crate::token::OrEq }; [||] => { $crate::token::OrOr }; [::] => { $crate::token::PathSep }; [%] => { $crate::token::Percent }; [%=] => { $crate::token::PercentEq }; [+] => { $crate::token::Plus }; [+=] => { $crate::token::PlusEq }; [#] => { $crate::token::Pound }; [?] => { $crate::token::Question }; [->] => { $crate::token::RArrow }; [;] => { $crate::token::Semi }; [<<] => { $crate::token::Shl }; [<<=] => { $crate::token::ShlEq }; [>>] => { $crate::token::Shr }; [>>=] => { $crate::token::ShrEq }; [/] => { $crate::token::Slash }; [/=] => { $crate::token::SlashEq }; [*] => { $crate::token::Star }; [*=] => { $crate::token::StarEq }; [~] => { $crate::token::Tilde }; [_] => { $crate::token::Underscore }; } // Not public API. #[doc(hidden)] #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::buffer::Cursor; use crate::error::{Error, Result}; use crate::parse::ParseStream; use proc_macro2::{Spacing, Span}; pub(crate) fn keyword(input: ParseStream, token: &str) -> Result { input.step(|cursor| { if let Some((ident, rest)) = cursor.ident() { if ident == token { return Ok((ident.span(), rest)); } } Err(cursor.error(format!("expected `{}`", token))) }) } pub(crate) fn peek_keyword(cursor: Cursor, token: &str) -> bool { if let Some((ident, _rest)) = cursor.ident() { ident == token } else { false } } #[doc(hidden)] pub fn punct(input: ParseStream, token: &str) -> Result<[Span; N]> { let mut spans = [input.span(); N]; punct_helper(input, token, &mut spans)?; Ok(spans) } fn punct_helper(input: ParseStream, token: &str, spans: &mut [Span]) -> Result<()> { input.step(|cursor| { let mut cursor = *cursor; assert_eq!(token.len(), spans.len()); for (i, ch) in token.chars().enumerate() { match cursor.punct() { Some((punct, rest)) => { spans[i] = punct.span(); if punct.as_char() != ch { break; } else if i == token.len() - 1 { return Ok(((), rest)); } else if punct.spacing() != Spacing::Joint { break; } cursor = rest; } None => break, } } Err(Error::new(spans[0], format!("expected `{}`", token))) }) } #[doc(hidden)] pub fn peek_punct(mut cursor: Cursor, token: &str) -> bool { for (i, ch) in token.chars().enumerate() { match cursor.punct() { Some((punct, rest)) => { if punct.as_char() != ch { break; } else if i == token.len() - 1 { return true; } else if punct.spacing() != Spacing::Joint { break; } cursor = rest; } None => break, } } false } } // Not public API. #[doc(hidden)] #[cfg(feature = "printing")] pub(crate) mod printing { use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream}; use quote::TokenStreamExt; #[doc(hidden)] pub fn punct(s: &str, spans: &[Span], tokens: &mut TokenStream) { assert_eq!(s.len(), spans.len()); let mut chars = s.chars(); let mut spans = spans.iter(); let ch = chars.next_back().unwrap(); let span = spans.next_back().unwrap(); for (ch, span) in chars.zip(spans) { let mut op = Punct::new(ch, Spacing::Joint); op.set_span(*span); tokens.append(op); } let mut op = Punct::new(ch, Spacing::Alone); op.set_span(*span); tokens.append(op); } pub(crate) fn keyword(s: &str, span: Span, tokens: &mut TokenStream) { tokens.append(Ident::new(s, span)); } pub(crate) fn delim( delim: Delimiter, span: Span, tokens: &mut TokenStream, inner: TokenStream, ) { let mut g = Group::new(delim, inner); g.set_span(span); tokens.append(g); } } syn/src/data.rs0000644000175000017500000003416214661133735014426 0ustar jamespagejamespageuse crate::attr::Attribute; use crate::expr::Expr; use crate::ident::Ident; use crate::punctuated::{self, Punctuated}; use crate::restriction::{FieldMutability, Visibility}; use crate::token; use crate::ty::Type; ast_struct! { /// An enum variant. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Variant { pub attrs: Vec, /// Name of the variant. pub ident: Ident, /// Content stored in the variant. pub fields: Fields, /// Explicit discriminant: `Variant = 1` pub discriminant: Option<(Token![=], Expr)>, } } ast_enum_of_structs! { /// Data stored within an enum variant or struct. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum Fields { /// Named fields of a struct or struct variant such as `Point { x: f64, /// y: f64 }`. Named(FieldsNamed), /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. Unnamed(FieldsUnnamed), /// Unit struct or unit variant such as `None`. Unit, } } ast_struct! { /// Named fields of a struct or struct variant such as `Point { x: f64, /// y: f64 }`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct FieldsNamed { pub brace_token: token::Brace, pub named: Punctuated, } } ast_struct! { /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct FieldsUnnamed { pub paren_token: token::Paren, pub unnamed: Punctuated, } } impl Fields { /// Get an iterator over the borrowed [`Field`] items in this object. This /// iterator can be used to iterate over a named or unnamed struct or /// variant's fields uniformly. pub fn iter(&self) -> punctuated::Iter { match self { Fields::Unit => crate::punctuated::empty_punctuated_iter(), Fields::Named(f) => f.named.iter(), Fields::Unnamed(f) => f.unnamed.iter(), } } /// Get an iterator over the mutably borrowed [`Field`] items in this /// object. This iterator can be used to iterate over a named or unnamed /// struct or variant's fields uniformly. pub fn iter_mut(&mut self) -> punctuated::IterMut { match self { Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(), Fields::Named(f) => f.named.iter_mut(), Fields::Unnamed(f) => f.unnamed.iter_mut(), } } /// Returns the number of fields. pub fn len(&self) -> usize { match self { Fields::Unit => 0, Fields::Named(f) => f.named.len(), Fields::Unnamed(f) => f.unnamed.len(), } } /// Returns `true` if there are zero fields. pub fn is_empty(&self) -> bool { match self { Fields::Unit => true, Fields::Named(f) => f.named.is_empty(), Fields::Unnamed(f) => f.unnamed.is_empty(), } } } impl IntoIterator for Fields { type Item = Field; type IntoIter = punctuated::IntoIter; fn into_iter(self) -> Self::IntoIter { match self { Fields::Unit => Punctuated::::new().into_iter(), Fields::Named(f) => f.named.into_iter(), Fields::Unnamed(f) => f.unnamed.into_iter(), } } } impl<'a> IntoIterator for &'a Fields { type Item = &'a Field; type IntoIter = punctuated::Iter<'a, Field>; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a> IntoIterator for &'a mut Fields { type Item = &'a mut Field; type IntoIter = punctuated::IterMut<'a, Field>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } ast_struct! { /// A field of a struct or enum variant. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Field { pub attrs: Vec, pub vis: Visibility, pub mutability: FieldMutability, /// Name of the field, if any. /// /// Fields of tuple structs have no names. pub ident: Option, pub colon_token: Option, pub ty: Type, } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant}; use crate::error::Result; use crate::expr::Expr; use crate::ext::IdentExt as _; use crate::ident::Ident; #[cfg(not(feature = "full"))] use crate::parse::discouraged::Speculative as _; use crate::parse::{Parse, ParseStream}; use crate::restriction::{FieldMutability, Visibility}; use crate::token; use crate::ty::Type; use crate::verbatim; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Variant { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let _visibility: Visibility = input.parse()?; let ident: Ident = input.parse()?; let fields = if input.peek(token::Brace) { Fields::Named(input.parse()?) } else if input.peek(token::Paren) { Fields::Unnamed(input.parse()?) } else { Fields::Unit }; let discriminant = if input.peek(Token![=]) { let eq_token: Token![=] = input.parse()?; #[cfg(feature = "full")] let discriminant: Expr = input.parse()?; #[cfg(not(feature = "full"))] let discriminant = { let begin = input.fork(); let ahead = input.fork(); let mut discriminant: Result = ahead.parse(); if discriminant.is_ok() { input.advance_to(&ahead); } else if scan_lenient_discriminant(input).is_ok() { discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input))); } discriminant? }; Some((eq_token, discriminant)) } else { None }; Ok(Variant { attrs, ident, fields, discriminant, }) } } #[cfg(not(feature = "full"))] pub(crate) fn scan_lenient_discriminant(input: ParseStream) -> Result<()> { use crate::expr::Member; use crate::lifetime::Lifetime; use crate::lit::Lit; use crate::lit::LitFloat; use crate::op::{BinOp, UnOp}; use crate::path::{self, AngleBracketedGenericArguments}; use proc_macro2::Delimiter::{self, Brace, Bracket, Parenthesis}; let consume = |delimiter: Delimiter| { Result::unwrap(input.step(|cursor| match cursor.group(delimiter) { Some((_inside, _span, rest)) => Ok((true, rest)), None => Ok((false, *cursor)), })) }; macro_rules! consume { [$token:tt] => { input.parse::>().unwrap().is_some() }; } let mut initial = true; let mut depth = 0usize; loop { if initial { if consume![&] { input.parse::>()?; } else if consume![if] || consume![match] || consume![while] { depth += 1; } else if input.parse::>()?.is_some() || (consume(Brace) || consume(Bracket) || consume(Parenthesis)) || (consume![async] || consume![const] || consume![loop] || consume![unsafe]) && (consume(Brace) || break) { initial = false; } else if consume![let] { while !consume![=] { if !((consume![|] || consume![ref] || consume![mut] || consume![@]) || (consume![!] || input.parse::>()?.is_some()) || (consume![..=] || consume![..] || consume![&] || consume![_]) || (consume(Brace) || consume(Bracket) || consume(Parenthesis))) { path::parsing::qpath(input, true)?; } } } else if input.parse::>()?.is_some() && !consume![:] { break; } else if input.parse::().is_err() { path::parsing::qpath(input, true)?; initial = consume![!] || depth == 0 && input.peek(token::Brace); } } else if input.is_empty() || input.peek(Token![,]) { return Ok(()); } else if depth > 0 && consume(Brace) { if consume![else] && !consume(Brace) { initial = consume![if] || break; } else { depth -= 1; } } else if input.parse::().is_ok() || (consume![..] | consume![=]) { initial = true; } else if consume![.] { if input.parse::>()?.is_none() && (input.parse::()?.is_named() && consume![::]) { AngleBracketedGenericArguments::do_parse(None, input)?; } } else if consume![as] { input.parse::()?; } else if !(consume(Brace) || consume(Bracket) || consume(Parenthesis)) { break; } } Err(input.error("unsupported expression")) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for FieldsNamed { fn parse(input: ParseStream) -> Result { let content; Ok(FieldsNamed { brace_token: braced!(content in input), named: content.parse_terminated(Field::parse_named, Token![,])?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for FieldsUnnamed { fn parse(input: ParseStream) -> Result { let content; Ok(FieldsUnnamed { paren_token: parenthesized!(content in input), unnamed: content.parse_terminated(Field::parse_unnamed, Token![,])?, }) } } impl Field { /// Parses a named (braced struct) field. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_named(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let unnamed_field = cfg!(feature = "full") && input.peek(Token![_]); let ident = if unnamed_field { input.call(Ident::parse_any) } else { input.parse() }?; let colon_token: Token![:] = input.parse()?; let ty: Type = if unnamed_field && (input.peek(Token![struct]) || input.peek(Token![union]) && input.peek2(token::Brace)) { let begin = input.fork(); input.call(Ident::parse_any)?; input.parse::()?; Type::Verbatim(verbatim::between(&begin, input)) } else { input.parse()? }; Ok(Field { attrs, vis, mutability: FieldMutability::None, ident: Some(ident), colon_token: Some(colon_token), ty, }) } /// Parses an unnamed (tuple struct) field. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_unnamed(input: ParseStream) -> Result { Ok(Field { attrs: input.call(Attribute::parse_outer)?, vis: input.parse()?, mutability: FieldMutability::None, ident: None, colon_token: None, ty: input.parse()?, }) } } } #[cfg(feature = "printing")] mod printing { use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant}; use crate::print::TokensOrDefault; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Variant { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(&self.attrs); self.ident.to_tokens(tokens); self.fields.to_tokens(tokens); if let Some((eq_token, disc)) = &self.discriminant { eq_token.to_tokens(tokens); disc.to_tokens(tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for FieldsNamed { fn to_tokens(&self, tokens: &mut TokenStream) { self.brace_token.surround(tokens, |tokens| { self.named.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for FieldsUnnamed { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { self.unnamed.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Field { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(&self.attrs); self.vis.to_tokens(tokens); if let Some(ident) = &self.ident { ident.to_tokens(tokens); TokensOrDefault(&self.colon_token).to_tokens(tokens); } self.ty.to_tokens(tokens); } } } syn/src/verbatim.rs0000644000175000017500000000230014661133735015313 0ustar jamespagejamespageuse crate::parse::ParseStream; use proc_macro2::{Delimiter, TokenStream}; use std::cmp::Ordering; use std::iter; pub(crate) fn between<'a>(begin: ParseStream<'a>, end: ParseStream<'a>) -> TokenStream { let end = end.cursor(); let mut cursor = begin.cursor(); assert!(crate::buffer::same_buffer(end, cursor)); let mut tokens = TokenStream::new(); while cursor != end { let (tt, next) = cursor.token_tree().unwrap(); if crate::buffer::cmp_assuming_same_buffer(end, next) == Ordering::Less { // A syntax node can cross the boundary of a None-delimited group // due to such groups being transparent to the parser in most cases. // Any time this occurs the group is known to be semantically // irrelevant. https://github.com/dtolnay/syn/issues/1235 if let Some((inside, _span, after)) = cursor.group(Delimiter::None) { assert!(next == after); cursor = inside; continue; } else { panic!("verbatim end must not be inside a delimited group"); } } tokens.extend(iter::once(tt)); cursor = next; } tokens } syn/src/generics.rs0000644000175000017500000012502214661133735015310 0ustar jamespagejamespageuse crate::attr::Attribute; use crate::expr::Expr; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::path::Path; use crate::punctuated::{Iter, IterMut, Punctuated}; use crate::token; use crate::ty::Type; use proc_macro2::TokenStream; #[cfg(all(feature = "printing", feature = "extra-traits"))] use std::fmt::{self, Debug}; #[cfg(all(feature = "printing", feature = "extra-traits"))] use std::hash::{Hash, Hasher}; ast_struct! { /// Lifetimes and type parameters attached to a declaration of a function, /// enum, trait, etc. /// /// This struct represents two distinct optional syntactic elements, /// [generic parameters] and [where clause]. In some locations of the /// grammar, there may be other tokens in between these two things. /// /// [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters /// [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Generics { pub lt_token: Option, pub params: Punctuated, pub gt_token: Option]>, pub where_clause: Option, } } ast_enum_of_structs! { /// A generic type parameter, lifetime, or const generic: `T: Into`, /// `'a: 'b`, `const LEN: usize`. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum GenericParam { /// A lifetime parameter: `'a: 'b + 'c + 'd`. Lifetime(LifetimeParam), /// A generic type parameter: `T: Into`. Type(TypeParam), /// A const generic parameter: `const LENGTH: usize`. Const(ConstParam), } } ast_struct! { /// A lifetime definition: `'a: 'b + 'c + 'd`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct LifetimeParam { pub attrs: Vec, pub lifetime: Lifetime, pub colon_token: Option, pub bounds: Punctuated, } } ast_struct! { /// A generic type parameter: `T: Into`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeParam { pub attrs: Vec, pub ident: Ident, pub colon_token: Option, pub bounds: Punctuated, pub eq_token: Option, pub default: Option, } } ast_struct! { /// A const generic parameter: `const LENGTH: usize`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ConstParam { pub attrs: Vec, pub const_token: Token![const], pub ident: Ident, pub colon_token: Token![:], pub ty: Type, pub eq_token: Option, pub default: Option, } } impl Default for Generics { fn default() -> Self { Generics { lt_token: None, params: Punctuated::new(), gt_token: None, where_clause: None, } } } impl Generics { /// Returns an /// Iterator<Item = &LifetimeParam> /// over the lifetime parameters in `self.params`. pub fn lifetimes(&self) -> Lifetimes { Lifetimes(self.params.iter()) } /// Returns an /// Iterator<Item = &mut LifetimeParam> /// over the lifetime parameters in `self.params`. pub fn lifetimes_mut(&mut self) -> LifetimesMut { LifetimesMut(self.params.iter_mut()) } /// Returns an /// Iterator<Item = &TypeParam> /// over the type parameters in `self.params`. pub fn type_params(&self) -> TypeParams { TypeParams(self.params.iter()) } /// Returns an /// Iterator<Item = &mut TypeParam> /// over the type parameters in `self.params`. pub fn type_params_mut(&mut self) -> TypeParamsMut { TypeParamsMut(self.params.iter_mut()) } /// Returns an /// Iterator<Item = &ConstParam> /// over the constant parameters in `self.params`. pub fn const_params(&self) -> ConstParams { ConstParams(self.params.iter()) } /// Returns an /// Iterator<Item = &mut ConstParam> /// over the constant parameters in `self.params`. pub fn const_params_mut(&mut self) -> ConstParamsMut { ConstParamsMut(self.params.iter_mut()) } /// Initializes an empty `where`-clause if there is not one present already. pub fn make_where_clause(&mut self) -> &mut WhereClause { self.where_clause.get_or_insert_with(|| WhereClause { where_token: ::default(), predicates: Punctuated::new(), }) } } pub struct Lifetimes<'a>(Iter<'a, GenericParam>); impl<'a> Iterator for Lifetimes<'a> { type Item = &'a LifetimeParam; fn next(&mut self) -> Option { let next = match self.0.next() { Some(item) => item, None => return None, }; if let GenericParam::Lifetime(lifetime) = next { Some(lifetime) } else { self.next() } } } pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>); impl<'a> Iterator for LifetimesMut<'a> { type Item = &'a mut LifetimeParam; fn next(&mut self) -> Option { let next = match self.0.next() { Some(item) => item, None => return None, }; if let GenericParam::Lifetime(lifetime) = next { Some(lifetime) } else { self.next() } } } pub struct TypeParams<'a>(Iter<'a, GenericParam>); impl<'a> Iterator for TypeParams<'a> { type Item = &'a TypeParam; fn next(&mut self) -> Option { let next = match self.0.next() { Some(item) => item, None => return None, }; if let GenericParam::Type(type_param) = next { Some(type_param) } else { self.next() } } } pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>); impl<'a> Iterator for TypeParamsMut<'a> { type Item = &'a mut TypeParam; fn next(&mut self) -> Option { let next = match self.0.next() { Some(item) => item, None => return None, }; if let GenericParam::Type(type_param) = next { Some(type_param) } else { self.next() } } } pub struct ConstParams<'a>(Iter<'a, GenericParam>); impl<'a> Iterator for ConstParams<'a> { type Item = &'a ConstParam; fn next(&mut self) -> Option { let next = match self.0.next() { Some(item) => item, None => return None, }; if let GenericParam::Const(const_param) = next { Some(const_param) } else { self.next() } } } pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>); impl<'a> Iterator for ConstParamsMut<'a> { type Item = &'a mut ConstParam; fn next(&mut self) -> Option { let next = match self.0.next() { Some(item) => item, None => return None, }; if let GenericParam::Const(const_param) = next { Some(const_param) } else { self.next() } } } /// Returned by `Generics::split_for_impl`. #[cfg(feature = "printing")] #[cfg_attr( docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub struct ImplGenerics<'a>(&'a Generics); /// Returned by `Generics::split_for_impl`. #[cfg(feature = "printing")] #[cfg_attr( docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub struct TypeGenerics<'a>(&'a Generics); /// Returned by `TypeGenerics::as_turbofish`. #[cfg(feature = "printing")] #[cfg_attr( docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub struct Turbofish<'a>(&'a Generics); #[cfg(feature = "printing")] impl Generics { /// Split a type's generics into the pieces required for impl'ing a trait /// for that type. /// /// ``` /// # use proc_macro2::{Span, Ident}; /// # use quote::quote; /// # /// # let generics: syn::Generics = Default::default(); /// # let name = Ident::new("MyType", Span::call_site()); /// # /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); /// quote! { /// impl #impl_generics MyTrait for #name #ty_generics #where_clause { /// // ... /// } /// } /// # ; /// ``` #[cfg_attr( docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) { ( ImplGenerics(self), TypeGenerics(self), self.where_clause.as_ref(), ) } } #[cfg(feature = "printing")] macro_rules! generics_wrapper_impls { ($ty:ident) => { #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl<'a> Clone for $ty<'a> { fn clone(&self) -> Self { $ty(self.0) } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> Debug for $ty<'a> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter .debug_tuple(stringify!($ty)) .field(self.0) .finish() } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> Eq for $ty<'a> {} #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> PartialEq for $ty<'a> { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl<'a> Hash for $ty<'a> { fn hash(&self, state: &mut H) { self.0.hash(state); } } }; } #[cfg(feature = "printing")] generics_wrapper_impls!(ImplGenerics); #[cfg(feature = "printing")] generics_wrapper_impls!(TypeGenerics); #[cfg(feature = "printing")] generics_wrapper_impls!(Turbofish); #[cfg(feature = "printing")] impl<'a> TypeGenerics<'a> { /// Turn a type's generics like `` into a turbofish like `::`. pub fn as_turbofish(&self) -> Turbofish { Turbofish(self.0) } } ast_struct! { /// A set of bound lifetimes: `for<'a, 'b, 'c>`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BoundLifetimes { pub for_token: Token![for], pub lt_token: Token![<], pub lifetimes: Punctuated, pub gt_token: Token![>], } } impl Default for BoundLifetimes { fn default() -> Self { BoundLifetimes { for_token: Default::default(), lt_token: Default::default(), lifetimes: Punctuated::new(), gt_token: Default::default(), } } } impl LifetimeParam { pub fn new(lifetime: Lifetime) -> Self { LifetimeParam { attrs: Vec::new(), lifetime, colon_token: None, bounds: Punctuated::new(), } } } impl From for TypeParam { fn from(ident: Ident) -> Self { TypeParam { attrs: vec![], ident, colon_token: None, bounds: Punctuated::new(), eq_token: None, default: None, } } } ast_enum_of_structs! { /// A trait or lifetime used as a bound on a type parameter. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum TypeParamBound { Trait(TraitBound), Lifetime(Lifetime), Verbatim(TokenStream), } } ast_struct! { /// A trait used as a bound on a type parameter. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TraitBound { pub paren_token: Option, pub modifier: TraitBoundModifier, /// The `for<'a>` in `for<'a> Foo<&'a T>` pub lifetimes: Option, /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>` pub path: Path, } } ast_enum! { /// A modifier on a trait bound, currently only used for the `?` in /// `?Sized`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum TraitBoundModifier { None, Maybe(Token![?]), } } ast_struct! { /// A `where` clause in a definition: `where T: Deserialize<'de>, D: /// 'static`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct WhereClause { pub where_token: Token![where], pub predicates: Punctuated, } } ast_enum_of_structs! { /// A single predicate in a `where` clause: `T: Deserialize<'de>`. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum WherePredicate { /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. Lifetime(PredicateLifetime), /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. Type(PredicateType), } } ast_struct! { /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct PredicateLifetime { pub lifetime: Lifetime, pub colon_token: Token![:], pub bounds: Punctuated, } } ast_struct! { /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct PredicateType { /// Any lifetimes from a `for` binding pub lifetimes: Option, /// The type being bounded pub bounded_ty: Type, pub colon_token: Token![:], /// Trait and lifetime bounds (`Clone+Send+'static`) pub bounds: Punctuated, } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::Result; use crate::ext::IdentExt as _; use crate::generics::{ BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause, WherePredicate, }; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::parse::{Parse, ParseStream}; use crate::path::{self, ParenthesizedGenericArguments, Path, PathArguments}; use crate::punctuated::Punctuated; use crate::token; use crate::ty::Type; use crate::verbatim; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Generics { fn parse(input: ParseStream) -> Result { if !input.peek(Token![<]) { return Ok(Generics::default()); } let lt_token: Token![<] = input.parse()?; let mut params = Punctuated::new(); loop { if input.peek(Token![>]) { break; } let attrs = input.call(Attribute::parse_outer)?; let lookahead = input.lookahead1(); if lookahead.peek(Lifetime) { params.push_value(GenericParam::Lifetime(LifetimeParam { attrs, ..input.parse()? })); } else if lookahead.peek(Ident) { params.push_value(GenericParam::Type(TypeParam { attrs, ..input.parse()? })); } else if lookahead.peek(Token![const]) { params.push_value(GenericParam::Const(ConstParam { attrs, ..input.parse()? })); } else if input.peek(Token![_]) { params.push_value(GenericParam::Type(TypeParam { attrs, ident: input.call(Ident::parse_any)?, colon_token: None, bounds: Punctuated::new(), eq_token: None, default: None, })); } else { return Err(lookahead.error()); } if input.peek(Token![>]) { break; } let punct = input.parse()?; params.push_punct(punct); } let gt_token: Token![>] = input.parse()?; Ok(Generics { lt_token: Some(lt_token), params, gt_token: Some(gt_token), where_clause: None, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for GenericParam { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let lookahead = input.lookahead1(); if lookahead.peek(Ident) { Ok(GenericParam::Type(TypeParam { attrs, ..input.parse()? })) } else if lookahead.peek(Lifetime) { Ok(GenericParam::Lifetime(LifetimeParam { attrs, ..input.parse()? })) } else if lookahead.peek(Token![const]) { Ok(GenericParam::Const(ConstParam { attrs, ..input.parse()? })) } else { Err(lookahead.error()) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LifetimeParam { fn parse(input: ParseStream) -> Result { let has_colon; Ok(LifetimeParam { attrs: input.call(Attribute::parse_outer)?, lifetime: input.parse()?, colon_token: { if input.peek(Token![:]) { has_colon = true; Some(input.parse()?) } else { has_colon = false; None } }, bounds: { let mut bounds = Punctuated::new(); if has_colon { loop { if input.peek(Token![,]) || input.peek(Token![>]) { break; } let value = input.parse()?; bounds.push_value(value); if !input.peek(Token![+]) { break; } let punct = input.parse()?; bounds.push_punct(punct); } } bounds }, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for BoundLifetimes { fn parse(input: ParseStream) -> Result { Ok(BoundLifetimes { for_token: input.parse()?, lt_token: input.parse()?, lifetimes: { let mut lifetimes = Punctuated::new(); while !input.peek(Token![>]) { let attrs = input.call(Attribute::parse_outer)?; let lifetime: Lifetime = input.parse()?; lifetimes.push_value(GenericParam::Lifetime(LifetimeParam { attrs, lifetime, colon_token: None, bounds: Punctuated::new(), })); if input.peek(Token![>]) { break; } lifetimes.push_punct(input.parse()?); } lifetimes }, gt_token: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if input.peek(Token![for]) { input.parse().map(Some) } else { Ok(None) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeParam { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let ident: Ident = input.parse()?; let colon_token: Option = input.parse()?; let mut bounds = Punctuated::new(); if colon_token.is_some() { loop { if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) { break; } let value: TypeParamBound = input.parse()?; bounds.push_value(value); if !input.peek(Token![+]) { break; } let punct: Token![+] = input.parse()?; bounds.push_punct(punct); } } let eq_token: Option = input.parse()?; let default = if eq_token.is_some() { Some(input.parse::()?) } else { None }; Ok(TypeParam { attrs, ident, colon_token, bounds, eq_token, default, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeParamBound { fn parse(input: ParseStream) -> Result { if input.peek(Lifetime) { return input.parse().map(TypeParamBound::Lifetime); } let begin = input.fork(); let content; let (paren_token, content) = if input.peek(token::Paren) { (Some(parenthesized!(content in input)), &content) } else { (None, input) }; let is_tilde_const = cfg!(feature = "full") && content.peek(Token![~]) && content.peek2(Token![const]); if is_tilde_const { content.parse::()?; content.parse::()?; } let mut bound: TraitBound = content.parse()?; bound.paren_token = paren_token; if is_tilde_const { Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input))) } else { Ok(TypeParamBound::Trait(bound)) } } } impl TypeParamBound { pub(crate) fn parse_multiple( input: ParseStream, allow_plus: bool, ) -> Result> { let mut bounds = Punctuated::new(); loop { bounds.push_value(input.parse()?); if !(allow_plus && input.peek(Token![+])) { break; } bounds.push_punct(input.parse()?); if !(input.peek(Ident::peek_any) || input.peek(Token![::]) || input.peek(Token![?]) || input.peek(Lifetime) || input.peek(token::Paren) || input.peek(Token![~])) { break; } } Ok(bounds) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitBound { fn parse(input: ParseStream) -> Result { let modifier: TraitBoundModifier = input.parse()?; let lifetimes: Option = input.parse()?; let mut path: Path = input.parse()?; if path.segments.last().unwrap().arguments.is_empty() && (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren)) { input.parse::>()?; let args: ParenthesizedGenericArguments = input.parse()?; let parenthesized = PathArguments::Parenthesized(args); path.segments.last_mut().unwrap().arguments = parenthesized; } Ok(TraitBound { paren_token: None, modifier, lifetimes, path, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitBoundModifier { fn parse(input: ParseStream) -> Result { if input.peek(Token![?]) { input.parse().map(TraitBoundModifier::Maybe) } else { Ok(TraitBoundModifier::None) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ConstParam { fn parse(input: ParseStream) -> Result { let mut default = None; Ok(ConstParam { attrs: input.call(Attribute::parse_outer)?, const_token: input.parse()?, ident: input.parse()?, colon_token: input.parse()?, ty: input.parse()?, eq_token: { if input.peek(Token![=]) { let eq_token = input.parse()?; default = Some(path::parsing::const_argument(input)?); Some(eq_token) } else { None } }, default, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for WhereClause { fn parse(input: ParseStream) -> Result { Ok(WhereClause { where_token: input.parse()?, predicates: { let mut predicates = Punctuated::new(); loop { if input.is_empty() || input.peek(token::Brace) || input.peek(Token![,]) || input.peek(Token![;]) || input.peek(Token![:]) && !input.peek(Token![::]) || input.peek(Token![=]) { break; } let value = input.parse()?; predicates.push_value(value); if !input.peek(Token![,]) { break; } let punct = input.parse()?; predicates.push_punct(punct); } predicates }, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option { fn parse(input: ParseStream) -> Result { if input.peek(Token![where]) { input.parse().map(Some) } else { Ok(None) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for WherePredicate { fn parse(input: ParseStream) -> Result { if input.peek(Lifetime) && input.peek2(Token![:]) { Ok(WherePredicate::Lifetime(PredicateLifetime { lifetime: input.parse()?, colon_token: input.parse()?, bounds: { let mut bounds = Punctuated::new(); loop { if input.is_empty() || input.peek(token::Brace) || input.peek(Token![,]) || input.peek(Token![;]) || input.peek(Token![:]) || input.peek(Token![=]) { break; } let value = input.parse()?; bounds.push_value(value); if !input.peek(Token![+]) { break; } let punct = input.parse()?; bounds.push_punct(punct); } bounds }, })) } else { Ok(WherePredicate::Type(PredicateType { lifetimes: input.parse()?, bounded_ty: input.parse()?, colon_token: input.parse()?, bounds: { let mut bounds = Punctuated::new(); loop { if input.is_empty() || input.peek(token::Brace) || input.peek(Token![,]) || input.peek(Token![;]) || input.peek(Token![:]) && !input.peek(Token![::]) || input.peek(Token![=]) { break; } let value = input.parse()?; bounds.push_value(value); if !input.peek(Token![+]) { break; } let punct = input.parse()?; bounds.push_punct(punct); } bounds }, })) } } } } #[cfg(feature = "printing")] pub(crate) mod printing { use crate::attr::FilterAttrs; #[cfg(feature = "full")] use crate::expr; use crate::expr::Expr; #[cfg(feature = "full")] use crate::fixup::FixupContext; use crate::generics::{ BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics, TypeParam, WhereClause, }; use crate::print::TokensOrDefault; use crate::token; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Generics { fn to_tokens(&self, tokens: &mut TokenStream) { if self.params.is_empty() { return; } TokensOrDefault(&self.lt_token).to_tokens(tokens); // Print lifetimes before types and consts, regardless of their // order in self.params. let mut trailing_or_empty = true; for param in self.params.pairs() { if let GenericParam::Lifetime(_) = **param.value() { param.to_tokens(tokens); trailing_or_empty = param.punct().is_some(); } } for param in self.params.pairs() { match param.value() { GenericParam::Type(_) | GenericParam::Const(_) => { if !trailing_or_empty { ::default().to_tokens(tokens); trailing_or_empty = true; } param.to_tokens(tokens); } GenericParam::Lifetime(_) => {} } } TokensOrDefault(&self.gt_token).to_tokens(tokens); } } impl<'a> ToTokens for ImplGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if self.0.params.is_empty() { return; } TokensOrDefault(&self.0.lt_token).to_tokens(tokens); // Print lifetimes before types and consts, regardless of their // order in self.params. let mut trailing_or_empty = true; for param in self.0.params.pairs() { if let GenericParam::Lifetime(_) = **param.value() { param.to_tokens(tokens); trailing_or_empty = param.punct().is_some(); } } for param in self.0.params.pairs() { if let GenericParam::Lifetime(_) = **param.value() { continue; } if !trailing_or_empty { ::default().to_tokens(tokens); trailing_or_empty = true; } match param.value() { GenericParam::Lifetime(_) => unreachable!(), GenericParam::Type(param) => { // Leave off the type parameter defaults tokens.append_all(param.attrs.outer()); param.ident.to_tokens(tokens); if !param.bounds.is_empty() { TokensOrDefault(¶m.colon_token).to_tokens(tokens); param.bounds.to_tokens(tokens); } } GenericParam::Const(param) => { // Leave off the const parameter defaults tokens.append_all(param.attrs.outer()); param.const_token.to_tokens(tokens); param.ident.to_tokens(tokens); param.colon_token.to_tokens(tokens); param.ty.to_tokens(tokens); } } param.punct().to_tokens(tokens); } TokensOrDefault(&self.0.gt_token).to_tokens(tokens); } } impl<'a> ToTokens for TypeGenerics<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if self.0.params.is_empty() { return; } TokensOrDefault(&self.0.lt_token).to_tokens(tokens); // Print lifetimes before types and consts, regardless of their // order in self.params. let mut trailing_or_empty = true; for param in self.0.params.pairs() { if let GenericParam::Lifetime(def) = *param.value() { // Leave off the lifetime bounds and attributes def.lifetime.to_tokens(tokens); param.punct().to_tokens(tokens); trailing_or_empty = param.punct().is_some(); } } for param in self.0.params.pairs() { if let GenericParam::Lifetime(_) = **param.value() { continue; } if !trailing_or_empty { ::default().to_tokens(tokens); trailing_or_empty = true; } match param.value() { GenericParam::Lifetime(_) => unreachable!(), GenericParam::Type(param) => { // Leave off the type parameter defaults param.ident.to_tokens(tokens); } GenericParam::Const(param) => { // Leave off the const parameter defaults param.ident.to_tokens(tokens); } } param.punct().to_tokens(tokens); } TokensOrDefault(&self.0.gt_token).to_tokens(tokens); } } impl<'a> ToTokens for Turbofish<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.0.params.is_empty() { ::default().to_tokens(tokens); TypeGenerics(self.0).to_tokens(tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BoundLifetimes { fn to_tokens(&self, tokens: &mut TokenStream) { self.for_token.to_tokens(tokens); self.lt_token.to_tokens(tokens); self.lifetimes.to_tokens(tokens); self.gt_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LifetimeParam { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.lifetime.to_tokens(tokens); if !self.bounds.is_empty() { TokensOrDefault(&self.colon_token).to_tokens(tokens); self.bounds.to_tokens(tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeParam { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.ident.to_tokens(tokens); if !self.bounds.is_empty() { TokensOrDefault(&self.colon_token).to_tokens(tokens); self.bounds.to_tokens(tokens); } if let Some(default) = &self.default { TokensOrDefault(&self.eq_token).to_tokens(tokens); default.to_tokens(tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitBound { fn to_tokens(&self, tokens: &mut TokenStream) { let to_tokens = |tokens: &mut TokenStream| { self.modifier.to_tokens(tokens); self.lifetimes.to_tokens(tokens); self.path.to_tokens(tokens); }; match &self.paren_token { Some(paren) => paren.surround(tokens, to_tokens), None => to_tokens(tokens), } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitBoundModifier { fn to_tokens(&self, tokens: &mut TokenStream) { match self { TraitBoundModifier::None => {} TraitBoundModifier::Maybe(t) => t.to_tokens(tokens), } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ConstParam { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.const_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); if let Some(default) = &self.default { TokensOrDefault(&self.eq_token).to_tokens(tokens); print_const_argument(default, tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for WhereClause { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.predicates.is_empty() { self.where_token.to_tokens(tokens); self.predicates.to_tokens(tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PredicateLifetime { fn to_tokens(&self, tokens: &mut TokenStream) { self.lifetime.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.bounds.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PredicateType { fn to_tokens(&self, tokens: &mut TokenStream) { self.lifetimes.to_tokens(tokens); self.bounded_ty.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.bounds.to_tokens(tokens); } } pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) { match expr { Expr::Lit(expr) => expr.to_tokens(tokens), Expr::Path(expr) if expr.attrs.is_empty() && expr.qself.is_none() && expr.path.get_ident().is_some() => { expr.to_tokens(tokens); } #[cfg(feature = "full")] Expr::Block(expr) => expr.to_tokens(tokens), #[cfg(not(feature = "full"))] Expr::Verbatim(expr) => expr.to_tokens(tokens), // ERROR CORRECTION: Add braces to make sure that the // generated code is valid. _ => token::Brace::default().surround(tokens, |tokens| { #[cfg(feature = "full")] expr::printing::print_expr(expr, tokens, FixupContext::new_stmt()); #[cfg(not(feature = "full"))] expr.to_tokens(tokens); }), } } } syn/src/export.rs0000644000175000017500000000321014661133735015024 0ustar jamespagejamespage#[doc(hidden)] pub use std::clone::Clone; #[doc(hidden)] pub use std::cmp::{Eq, PartialEq}; #[doc(hidden)] pub use std::concat; #[doc(hidden)] pub use std::default::Default; #[doc(hidden)] pub use std::fmt::Debug; #[doc(hidden)] pub use std::hash::{Hash, Hasher}; #[doc(hidden)] pub use std::marker::Copy; #[doc(hidden)] pub use std::option::Option::{None, Some}; #[doc(hidden)] pub use std::result::Result::{Err, Ok}; #[doc(hidden)] pub use std::stringify; #[doc(hidden)] pub type Formatter<'a> = std::fmt::Formatter<'a>; #[doc(hidden)] pub type FmtResult = std::fmt::Result; #[doc(hidden)] pub type bool = std::primitive::bool; #[doc(hidden)] pub type str = std::primitive::str; #[cfg(feature = "printing")] #[doc(hidden)] pub use quote; #[doc(hidden)] pub type Span = proc_macro2::Span; #[doc(hidden)] pub type TokenStream2 = proc_macro2::TokenStream; #[cfg(feature = "parsing")] #[doc(hidden)] pub use crate::group::{parse_braces, parse_brackets, parse_parens}; #[doc(hidden)] pub use crate::span::IntoSpans; #[cfg(all(feature = "parsing", feature = "printing"))] #[doc(hidden)] pub use crate::parse_quote::parse as parse_quote; #[cfg(feature = "parsing")] #[doc(hidden)] pub use crate::token::parsing::{peek_punct, punct as parse_punct}; #[cfg(feature = "printing")] #[doc(hidden)] pub use crate::token::printing::punct as print_punct; #[cfg(feature = "parsing")] #[doc(hidden)] pub use crate::token::private::CustomToken; #[cfg(feature = "proc-macro")] #[doc(hidden)] pub type TokenStream = proc_macro::TokenStream; #[cfg(feature = "printing")] #[doc(hidden)] pub use quote::{ToTokens, TokenStreamExt}; #[doc(hidden)] pub struct private(pub(crate) ()); syn/src/parse_quote.rs0000644000175000017500000001421114661133735016035 0ustar jamespagejamespage/// Quasi-quotation macro that accepts input like the [`quote!`] macro but uses /// type inference to figure out a return type for those tokens. /// /// [`quote!`]: https://docs.rs/quote/1.0/quote/index.html /// /// The return type can be any syntax tree node that implements the [`Parse`] /// trait. /// /// [`Parse`]: crate::parse::Parse /// /// ``` /// use quote::quote; /// use syn::{parse_quote, Stmt}; /// /// fn main() { /// let name = quote!(v); /// let ty = quote!(u8); /// /// let stmt: Stmt = parse_quote! { /// let #name: #ty = Default::default(); /// }; /// /// println!("{:#?}", stmt); /// } /// ``` /// /// *This macro is available only if Syn is built with both the `"parsing"` and /// `"printing"` features.* /// /// # Example /// /// The following helper function adds a bound `T: HeapSize` to every type /// parameter `T` in the input generics. /// /// ``` /// use syn::{parse_quote, Generics, GenericParam}; /// /// // Add a bound `T: HeapSize` to every type parameter T. /// fn add_trait_bounds(mut generics: Generics) -> Generics { /// for param in &mut generics.params { /// if let GenericParam::Type(type_param) = param { /// type_param.bounds.push(parse_quote!(HeapSize)); /// } /// } /// generics /// } /// ``` /// /// # Special cases /// /// This macro can parse the following additional types as a special case even /// though they do not implement the `Parse` trait. /// /// - [`Attribute`] — parses one attribute, allowing either outer like `#[...]` /// or inner like `#![...]` /// - [`Punctuated`] — parses zero or more `T` separated by punctuation /// `P` with optional trailing punctuation /// - [`Vec`] — parses the same as `Block::parse_within` /// /// [`Vec`]: Block::parse_within /// /// # Panics /// /// Panics if the tokens fail to parse as the expected syntax tree type. The /// caller is responsible for ensuring that the input tokens are syntactically /// valid. #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] #[macro_export] macro_rules! parse_quote { ($($tt:tt)*) => { $crate::__private::parse_quote($crate::__private::quote::quote!($($tt)*)) }; } /// This macro is [`parse_quote!`] + [`quote_spanned!`][quote::quote_spanned]. /// /// Please refer to each of their documentation. /// /// # Example /// /// ``` /// use quote::{quote, quote_spanned}; /// use syn::spanned::Spanned; /// use syn::{parse_quote_spanned, ReturnType, Signature}; /// /// // Changes `fn()` to `fn() -> Pin>>`, /// // and `fn() -> T` to `fn() -> Pin>>`, /// // without introducing any call_site() spans. /// fn make_ret_pinned_future(sig: &mut Signature) { /// let ret = match &sig.output { /// ReturnType::Default => quote_spanned!(sig.paren_token.span=> ()), /// ReturnType::Type(_, ret) => quote!(#ret), /// }; /// sig.output = parse_quote_spanned! {ret.span()=> /// -> ::std::pin::Pin<::std::boxed::Box>> /// }; /// } /// ``` #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] #[macro_export] macro_rules! parse_quote_spanned { ($span:expr=> $($tt:tt)*) => { $crate::__private::parse_quote($crate::__private::quote::quote_spanned!($span=> $($tt)*)) }; } //////////////////////////////////////////////////////////////////////////////// // Can parse any type that implements Parse. use crate::error::Result; use crate::parse::{Parse, ParseStream, Parser}; use proc_macro2::TokenStream; // Not public API. #[doc(hidden)] #[track_caller] pub fn parse(token_stream: TokenStream) -> T { let parser = T::parse; match parser.parse2(token_stream) { Ok(t) => t, Err(err) => panic!("{}", err), } } #[doc(hidden)] pub trait ParseQuote: Sized { fn parse(input: ParseStream) -> Result; } impl ParseQuote for T { fn parse(input: ParseStream) -> Result { ::parse(input) } } //////////////////////////////////////////////////////////////////////////////// // Any other types that we want `parse_quote!` to be able to parse. use crate::punctuated::Punctuated; #[cfg(any(feature = "full", feature = "derive"))] use crate::{attr, Attribute, Field, FieldMutability, Ident, Type, Visibility}; #[cfg(feature = "full")] use crate::{Block, Pat, Stmt}; #[cfg(any(feature = "full", feature = "derive"))] impl ParseQuote for Attribute { fn parse(input: ParseStream) -> Result { if input.peek(Token![#]) && input.peek2(Token![!]) { attr::parsing::single_parse_inner(input) } else { attr::parsing::single_parse_outer(input) } } } #[cfg(any(feature = "full", feature = "derive"))] impl ParseQuote for Field { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let ident: Option; let colon_token: Option; let is_named = input.peek(Ident) && input.peek2(Token![:]) && !input.peek2(Token![::]); if is_named { ident = Some(input.parse()?); colon_token = Some(input.parse()?); } else { ident = None; colon_token = None; } let ty: Type = input.parse()?; Ok(Field { attrs, vis, mutability: FieldMutability::None, ident, colon_token, ty, }) } } #[cfg(feature = "full")] impl ParseQuote for Pat { fn parse(input: ParseStream) -> Result { Pat::parse_multi_with_leading_vert(input) } } #[cfg(feature = "full")] impl ParseQuote for Box { fn parse(input: ParseStream) -> Result { ::parse(input).map(Box::new) } } impl ParseQuote for Punctuated { fn parse(input: ParseStream) -> Result { Self::parse_terminated(input) } } #[cfg(feature = "full")] impl ParseQuote for Vec { fn parse(input: ParseStream) -> Result { Block::parse_within(input) } } syn/src/sealed.rs0000644000175000017500000000012714661133735014744 0ustar jamespagejamespage#[cfg(feature = "parsing")] pub(crate) mod lookahead { pub trait Sealed: Copy {} } syn/src/lib.rs0000644000175000017500000010201214661133735014251 0ustar jamespagejamespage//! [![github]](https://github.com/dtolnay/syn) [![crates-io]](https://crates.io/crates/syn) [![docs-rs]](crate) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! Syn is a parsing library for parsing a stream of Rust tokens into a syntax //! tree of Rust source code. //! //! Currently this library is geared toward use in Rust procedural macros, but //! contains some APIs that may be useful more generally. //! //! - **Data structures** — Syn provides a complete syntax tree that can //! represent any valid Rust source code. The syntax tree is rooted at //! [`syn::File`] which represents a full source file, but there are other //! entry points that may be useful to procedural macros including //! [`syn::Item`], [`syn::Expr`] and [`syn::Type`]. //! //! - **Derives** — Of particular interest to derive macros is //! [`syn::DeriveInput`] which is any of the three legal input items to a //! derive macro. An example below shows using this type in a library that can //! derive implementations of a user-defined trait. //! //! - **Parsing** — Parsing in Syn is built around [parser functions] with the //! signature `fn(ParseStream) -> Result`. Every syntax tree node defined //! by Syn is individually parsable and may be used as a building block for //! custom syntaxes, or you may dream up your own brand new syntax without //! involving any of our syntax tree types. //! //! - **Location information** — Every token parsed by Syn is associated with a //! `Span` that tracks line and column information back to the source of that //! token. These spans allow a procedural macro to display detailed error //! messages pointing to all the right places in the user's code. There is an //! example of this below. //! //! - **Feature flags** — Functionality is aggressively feature gated so your //! procedural macros enable only what they need, and do not pay in compile //! time for all the rest. //! //! [`syn::File`]: File //! [`syn::Item`]: Item //! [`syn::Expr`]: Expr //! [`syn::Type`]: Type //! [`syn::DeriveInput`]: DeriveInput //! [parser functions]: mod@parse //! //!
//! //! # Example of a derive macro //! //! The canonical derive macro using Syn looks like this. We write an ordinary //! Rust function tagged with a `proc_macro_derive` attribute and the name of //! the trait we are deriving. Any time that derive appears in the user's code, //! the Rust compiler passes their data structure as tokens into our macro. We //! get to execute arbitrary Rust code to figure out what to do with those //! tokens, then hand some tokens back to the compiler to compile into the //! user's crate. //! //! [`TokenStream`]: proc_macro::TokenStream //! //! ```toml //! [dependencies] //! syn = "2.0" //! quote = "1.0" //! //! [lib] //! proc-macro = true //! ``` //! //! ``` //! # extern crate proc_macro; //! # //! use proc_macro::TokenStream; //! use quote::quote; //! use syn::{parse_macro_input, DeriveInput}; //! //! # const IGNORE_TOKENS: &str = stringify! { //! #[proc_macro_derive(MyMacro)] //! # }; //! pub fn my_macro(input: TokenStream) -> TokenStream { //! // Parse the input tokens into a syntax tree //! let input = parse_macro_input!(input as DeriveInput); //! //! // Build the output, possibly using quasi-quotation //! let expanded = quote! { //! // ... //! }; //! //! // Hand the output tokens back to the compiler //! TokenStream::from(expanded) //! } //! ``` //! //! The [`heapsize`] example directory shows a complete working implementation //! of a derive macro. The example derives a `HeapSize` trait which computes an //! estimate of the amount of heap memory owned by a value. //! //! [`heapsize`]: https://github.com/dtolnay/syn/tree/master/examples/heapsize //! //! ``` //! pub trait HeapSize { //! /// Total number of bytes of heap memory owned by `self`. //! fn heap_size_of_children(&self) -> usize; //! } //! ``` //! //! The derive macro allows users to write `#[derive(HeapSize)]` on data //! structures in their program. //! //! ``` //! # const IGNORE_TOKENS: &str = stringify! { //! #[derive(HeapSize)] //! # }; //! struct Demo<'a, T: ?Sized> { //! a: Box, //! b: u8, //! c: &'a str, //! d: String, //! } //! ``` //! //!


//! //! # Spans and error reporting //! //! The token-based procedural macro API provides great control over where the //! compiler's error messages are displayed in user code. Consider the error the //! user sees if one of their field types does not implement `HeapSize`. //! //! ``` //! # const IGNORE_TOKENS: &str = stringify! { //! #[derive(HeapSize)] //! # }; //! struct Broken { //! ok: String, //! bad: std::thread::Thread, //! } //! ``` //! //! By tracking span information all the way through the expansion of a //! procedural macro as shown in the `heapsize` example, token-based macros in //! Syn are able to trigger errors that directly pinpoint the source of the //! problem. //! //! ```text //! error[E0277]: the trait bound `std::thread::Thread: HeapSize` is not satisfied //! --> src/main.rs:7:5 //! | //! 7 | bad: std::thread::Thread, //! | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HeapSize` is not implemented for `Thread` //! ``` //! //!
//! //! # Parsing a custom syntax //! //! The [`lazy-static`] example directory shows the implementation of a //! `functionlike!(...)` procedural macro in which the input tokens are parsed //! using Syn's parsing API. //! //! [`lazy-static`]: https://github.com/dtolnay/syn/tree/master/examples/lazy-static //! //! The example reimplements the popular `lazy_static` crate from crates.io as a //! procedural macro. //! //! ``` //! # macro_rules! lazy_static { //! # ($($tt:tt)*) => {} //! # } //! # //! lazy_static! { //! static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap(); //! } //! ``` //! //! The implementation shows how to trigger custom warnings and error messages //! on the macro input. //! //! ```text //! warning: come on, pick a more creative name //! --> src/main.rs:10:16 //! | //! 10 | static ref FOO: String = "lazy_static".to_owned(); //! | ^^^ //! ``` //! //!
//! //! # Testing //! //! When testing macros, we often care not just that the macro can be used //! successfully but also that when the macro is provided with invalid input it //! produces maximally helpful error messages. Consider using the [`trybuild`] //! crate to write tests for errors that are emitted by your macro or errors //! detected by the Rust compiler in the expanded code following misuse of the //! macro. Such tests help avoid regressions from later refactors that //! mistakenly make an error no longer trigger or be less helpful than it used //! to be. //! //! [`trybuild`]: https://github.com/dtolnay/trybuild //! //!
//! //! # Debugging //! //! When developing a procedural macro it can be helpful to look at what the //! generated code looks like. Use `cargo rustc -- -Zunstable-options //! --pretty=expanded` or the [`cargo expand`] subcommand. //! //! [`cargo expand`]: https://github.com/dtolnay/cargo-expand //! //! To show the expanded code for some crate that uses your procedural macro, //! run `cargo expand` from that crate. To show the expanded code for one of //! your own test cases, run `cargo expand --test the_test_case` where the last //! argument is the name of the test file without the `.rs` extension. //! //! This write-up by Brandon W Maister discusses debugging in more detail: //! [Debugging Rust's new Custom Derive system][debugging]. //! //! [debugging]: https://quodlibetor.github.io/posts/debugging-rusts-new-custom-derive-system/ //! //!
//! //! # Optional features //! //! Syn puts a lot of functionality behind optional features in order to //! optimize compile time for the most common use cases. The following features //! are available. //! //! - **`derive`** *(enabled by default)* — Data structures for representing the //! possible input to a derive macro, including structs and enums and types. //! - **`full`** — Data structures for representing the syntax tree of all valid //! Rust source code, including items and expressions. //! - **`parsing`** *(enabled by default)* — Ability to parse input tokens into //! a syntax tree node of a chosen type. //! - **`printing`** *(enabled by default)* — Ability to print a syntax tree //! node as tokens of Rust source code. //! - **`visit`** — Trait for traversing a syntax tree. //! - **`visit-mut`** — Trait for traversing and mutating in place a syntax //! tree. //! - **`fold`** — Trait for transforming an owned syntax tree. //! - **`clone-impls`** *(enabled by default)* — Clone impls for all syntax tree //! types. //! - **`extra-traits`** — Debug, Eq, PartialEq, Hash impls for all syntax tree //! types. //! - **`proc-macro`** *(enabled by default)* — Runtime dependency on the //! dynamic library libproc_macro from rustc toolchain. // Syn types in rustdoc of other crates get linked to here. #![doc(html_root_url = "https://docs.rs/syn/2.0.69")] #![cfg_attr(docsrs, feature(doc_cfg))] #![deny(unsafe_op_in_unsafe_fn)] #![allow(non_camel_case_types)] #![cfg_attr(not(check_cfg), allow(unexpected_cfgs))] #![allow( clippy::bool_to_int_with_if, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_ptr_alignment, clippy::default_trait_access, clippy::derivable_impls, clippy::diverging_sub_expression, clippy::doc_markdown, clippy::expl_impl_clone_on_copy, clippy::explicit_auto_deref, clippy::if_not_else, clippy::inherent_to_string, clippy::into_iter_without_iter, clippy::items_after_statements, clippy::large_enum_variant, clippy::let_underscore_untyped, // https://github.com/rust-lang/rust-clippy/issues/10410 clippy::manual_assert, clippy::manual_let_else, clippy::manual_map, clippy::match_like_matches_macro, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wildcard_for_single_variants, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/6984 clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::needless_doctest_main, clippy::needless_pass_by_value, clippy::never_loop, clippy::range_plus_one, clippy::redundant_else, clippy::return_self_not_must_use, clippy::similar_names, clippy::single_match_else, clippy::struct_excessive_bools, clippy::too_many_arguments, clippy::too_many_lines, clippy::trivially_copy_pass_by_ref, clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133 clippy::uninhabited_references, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_unwrap, clippy::used_underscore_binding, clippy::wildcard_imports, )] #[cfg(feature = "proc-macro")] extern crate proc_macro; #[macro_use] mod macros; #[cfg(feature = "parsing")] #[macro_use] mod group; #[macro_use] pub mod token; #[cfg(any(feature = "full", feature = "derive"))] mod attr; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::attr::{AttrStyle, Attribute, Meta, MetaList, MetaNameValue}; mod bigint; #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub mod buffer; #[cfg(any( all(feature = "parsing", feature = "full"), all(feature = "printing", any(feature = "full", feature = "derive")), ))] mod classify; mod custom_keyword; mod custom_punctuation; #[cfg(any(feature = "full", feature = "derive"))] mod data; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant}; #[cfg(any(feature = "full", feature = "derive"))] mod derive; #[cfg(feature = "derive")] #[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use crate::derive::{Data, DataEnum, DataStruct, DataUnion, DeriveInput}; mod drops; mod error; pub use crate::error::{Error, Result}; #[cfg(any(feature = "full", feature = "derive"))] mod expr; #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::expr::{Arm, Label, RangeLimits}; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::expr::{ Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprIndex, ExprLit, ExprMacro, ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprUnary, FieldValue, Index, Member, }; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::expr::{ ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprGroup, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch, ExprRange, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple, ExprUnsafe, ExprWhile, ExprYield, }; #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub mod ext; #[cfg(feature = "full")] mod file; #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::file::File; #[cfg(all(feature = "full", feature = "printing"))] mod fixup; #[cfg(any(feature = "full", feature = "derive"))] mod generics; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::generics::{ BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause, WherePredicate, }; #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] #[cfg_attr( docsrs, doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))) )] pub use crate::generics::{ImplGenerics, Turbofish, TypeGenerics}; mod ident; #[doc(inline)] pub use crate::ident::Ident; #[cfg(feature = "full")] mod item; #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::item::{ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, ImplRestriction, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic, }; mod lifetime; #[doc(inline)] pub use crate::lifetime::Lifetime; mod lit; #[doc(hidden)] // https://github.com/dtolnay/syn/issues/1566 pub use crate::lit::StrStyle; #[doc(inline)] pub use crate::lit::{ Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr, }; #[cfg(feature = "parsing")] mod lookahead; #[cfg(any(feature = "full", feature = "derive"))] mod mac; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::mac::{Macro, MacroDelimiter}; #[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))] #[cfg_attr( docsrs, doc(cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))) )] pub mod meta; #[cfg(any(feature = "full", feature = "derive"))] mod op; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::op::{BinOp, UnOp}; #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub mod parse; #[cfg(all(feature = "parsing", feature = "proc-macro"))] mod parse_macro_input; #[cfg(all(feature = "parsing", feature = "printing"))] mod parse_quote; #[cfg(feature = "full")] mod pat; #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::pat::{ FieldPat, Pat, PatConst, PatIdent, PatLit, PatMacro, PatOr, PatParen, PatPath, PatRange, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, }; #[cfg(any(feature = "full", feature = "derive"))] mod path; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::path::{ AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument, ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, }; #[cfg(all( any(feature = "full", feature = "derive"), any(feature = "parsing", feature = "printing") ))] mod precedence; #[cfg(all(any(feature = "full", feature = "derive"), feature = "printing"))] mod print; pub mod punctuated; #[cfg(any(feature = "full", feature = "derive"))] mod restriction; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::restriction::{FieldMutability, VisRestricted, Visibility}; mod sealed; mod span; #[cfg(all(feature = "parsing", feature = "printing"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] pub mod spanned; #[cfg(feature = "full")] mod stmt; #[cfg(feature = "full")] #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub use crate::stmt::{Block, Local, LocalInit, Stmt, StmtMacro}; mod thread; #[cfg(all(any(feature = "full", feature = "derive"), feature = "extra-traits"))] mod tt; #[cfg(any(feature = "full", feature = "derive"))] mod ty; #[cfg(any(feature = "full", feature = "derive"))] #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub use crate::ty::{ Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject, TypeTuple, }; #[cfg(all(any(feature = "full", feature = "derive"), feature = "parsing"))] mod verbatim; #[cfg(all(feature = "parsing", feature = "full"))] mod whitespace; #[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/6176 mod gen { /// Syntax tree traversal to transform the nodes of an owned syntax tree. /// /// Each method of the [`Fold`] trait is a hook that can be overridden to /// customize the behavior when transforming the corresponding type of node. /// By default, every method recursively visits the substructure of the /// input by invoking the right visitor method of each of its fields. /// /// [`Fold`]: fold::Fold /// /// ``` /// # use syn::{Attribute, BinOp, Expr, ExprBinary}; /// # /// pub trait Fold { /// /* ... */ /// /// fn fold_expr_binary(&mut self, node: ExprBinary) -> ExprBinary { /// fold_expr_binary(self, node) /// } /// /// /* ... */ /// # fn fold_attribute(&mut self, node: Attribute) -> Attribute; /// # fn fold_expr(&mut self, node: Expr) -> Expr; /// # fn fold_bin_op(&mut self, node: BinOp) -> BinOp; /// } /// /// pub fn fold_expr_binary(v: &mut V, node: ExprBinary) -> ExprBinary /// where /// V: Fold + ?Sized, /// { /// ExprBinary { /// attrs: node /// .attrs /// .into_iter() /// .map(|attr| v.fold_attribute(attr)) /// .collect(), /// left: Box::new(v.fold_expr(*node.left)), /// op: v.fold_bin_op(node.op), /// right: Box::new(v.fold_expr(*node.right)), /// } /// } /// /// /* ... */ /// ``` /// ///
/// /// # Example /// /// This fold inserts parentheses to fully parenthesizes any expression. /// /// ``` /// // [dependencies] /// // quote = "1.0" /// // syn = { version = "2.0", features = ["fold", "full"] } /// /// use quote::quote; /// use syn::fold::{fold_expr, Fold}; /// use syn::{token, Expr, ExprParen}; /// /// struct ParenthesizeEveryExpr; /// /// impl Fold for ParenthesizeEveryExpr { /// fn fold_expr(&mut self, expr: Expr) -> Expr { /// Expr::Paren(ExprParen { /// attrs: Vec::new(), /// expr: Box::new(fold_expr(self, expr)), /// paren_token: token::Paren::default(), /// }) /// } /// } /// /// fn main() { /// let code = quote! { a() + b(1) * c.d }; /// let expr: Expr = syn::parse2(code).unwrap(); /// let parenthesized = ParenthesizeEveryExpr.fold_expr(expr); /// println!("{}", quote!(#parenthesized)); /// /// // Output: (((a)()) + (((b)((1))) * ((c).d))) /// } /// ``` #[cfg(feature = "fold")] #[cfg_attr(docsrs, doc(cfg(feature = "fold")))] #[rustfmt::skip] pub mod fold; /// Syntax tree traversal to walk a shared borrow of a syntax tree. /// /// Each method of the [`Visit`] trait is a hook that can be overridden to /// customize the behavior when visiting the corresponding type of node. By /// default, every method recursively visits the substructure of the input /// by invoking the right visitor method of each of its fields. /// /// [`Visit`]: visit::Visit /// /// ``` /// # use syn::{Attribute, BinOp, Expr, ExprBinary}; /// # /// pub trait Visit<'ast> { /// /* ... */ /// /// fn visit_expr_binary(&mut self, node: &'ast ExprBinary) { /// visit_expr_binary(self, node); /// } /// /// /* ... */ /// # fn visit_attribute(&mut self, node: &'ast Attribute); /// # fn visit_expr(&mut self, node: &'ast Expr); /// # fn visit_bin_op(&mut self, node: &'ast BinOp); /// } /// /// pub fn visit_expr_binary<'ast, V>(v: &mut V, node: &'ast ExprBinary) /// where /// V: Visit<'ast> + ?Sized, /// { /// for attr in &node.attrs { /// v.visit_attribute(attr); /// } /// v.visit_expr(&*node.left); /// v.visit_bin_op(&node.op); /// v.visit_expr(&*node.right); /// } /// /// /* ... */ /// ``` /// ///
/// /// # Example /// /// This visitor will print the name of every freestanding function in the /// syntax tree, including nested functions. /// /// ``` /// // [dependencies] /// // quote = "1.0" /// // syn = { version = "2.0", features = ["full", "visit"] } /// /// use quote::quote; /// use syn::visit::{self, Visit}; /// use syn::{File, ItemFn}; /// /// struct FnVisitor; /// /// impl<'ast> Visit<'ast> for FnVisitor { /// fn visit_item_fn(&mut self, node: &'ast ItemFn) { /// println!("Function with name={}", node.sig.ident); /// /// // Delegate to the default impl to visit any nested functions. /// visit::visit_item_fn(self, node); /// } /// } /// /// fn main() { /// let code = quote! { /// pub fn f() { /// fn g() {} /// } /// }; /// /// let syntax_tree: File = syn::parse2(code).unwrap(); /// FnVisitor.visit_file(&syntax_tree); /// } /// ``` /// /// The `'ast` lifetime on the input references means that the syntax tree /// outlives the complete recursive visit call, so the visitor is allowed to /// hold on to references into the syntax tree. /// /// ``` /// use quote::quote; /// use syn::visit::{self, Visit}; /// use syn::{File, ItemFn}; /// /// struct FnVisitor<'ast> { /// functions: Vec<&'ast ItemFn>, /// } /// /// impl<'ast> Visit<'ast> for FnVisitor<'ast> { /// fn visit_item_fn(&mut self, node: &'ast ItemFn) { /// self.functions.push(node); /// visit::visit_item_fn(self, node); /// } /// } /// /// fn main() { /// let code = quote! { /// pub fn f() { /// fn g() {} /// } /// }; /// /// let syntax_tree: File = syn::parse2(code).unwrap(); /// let mut visitor = FnVisitor { functions: Vec::new() }; /// visitor.visit_file(&syntax_tree); /// for f in visitor.functions { /// println!("Function with name={}", f.sig.ident); /// } /// } /// ``` #[cfg(feature = "visit")] #[cfg_attr(docsrs, doc(cfg(feature = "visit")))] #[rustfmt::skip] pub mod visit; /// Syntax tree traversal to mutate an exclusive borrow of a syntax tree in /// place. /// /// Each method of the [`VisitMut`] trait is a hook that can be overridden /// to customize the behavior when mutating the corresponding type of node. /// By default, every method recursively visits the substructure of the /// input by invoking the right visitor method of each of its fields. /// /// [`VisitMut`]: visit_mut::VisitMut /// /// ``` /// # use syn::{Attribute, BinOp, Expr, ExprBinary}; /// # /// pub trait VisitMut { /// /* ... */ /// /// fn visit_expr_binary_mut(&mut self, node: &mut ExprBinary) { /// visit_expr_binary_mut(self, node); /// } /// /// /* ... */ /// # fn visit_attribute_mut(&mut self, node: &mut Attribute); /// # fn visit_expr_mut(&mut self, node: &mut Expr); /// # fn visit_bin_op_mut(&mut self, node: &mut BinOp); /// } /// /// pub fn visit_expr_binary_mut(v: &mut V, node: &mut ExprBinary) /// where /// V: VisitMut + ?Sized, /// { /// for attr in &mut node.attrs { /// v.visit_attribute_mut(attr); /// } /// v.visit_expr_mut(&mut *node.left); /// v.visit_bin_op_mut(&mut node.op); /// v.visit_expr_mut(&mut *node.right); /// } /// /// /* ... */ /// ``` /// ///
/// /// # Example /// /// This mut visitor replace occurrences of u256 suffixed integer literals /// like `999u256` with a macro invocation `bigint::u256!(999)`. /// /// ``` /// // [dependencies] /// // quote = "1.0" /// // syn = { version = "2.0", features = ["full", "visit-mut"] } /// /// use quote::quote; /// use syn::visit_mut::{self, VisitMut}; /// use syn::{parse_quote, Expr, File, Lit, LitInt}; /// /// struct BigintReplace; /// /// impl VisitMut for BigintReplace { /// fn visit_expr_mut(&mut self, node: &mut Expr) { /// if let Expr::Lit(expr) = &node { /// if let Lit::Int(int) = &expr.lit { /// if int.suffix() == "u256" { /// let digits = int.base10_digits(); /// let unsuffixed: LitInt = syn::parse_str(digits).unwrap(); /// *node = parse_quote!(bigint::u256!(#unsuffixed)); /// return; /// } /// } /// } /// /// // Delegate to the default impl to visit nested expressions. /// visit_mut::visit_expr_mut(self, node); /// } /// } /// /// fn main() { /// let code = quote! { /// fn main() { /// let _ = 999u256; /// } /// }; /// /// let mut syntax_tree: File = syn::parse2(code).unwrap(); /// BigintReplace.visit_file_mut(&mut syntax_tree); /// println!("{}", quote!(#syntax_tree)); /// } /// ``` #[cfg(feature = "visit-mut")] #[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))] #[rustfmt::skip] pub mod visit_mut; #[cfg(feature = "clone-impls")] #[rustfmt::skip] mod clone; #[cfg(feature = "extra-traits")] #[rustfmt::skip] mod debug; #[cfg(feature = "extra-traits")] #[rustfmt::skip] mod eq; #[cfg(feature = "extra-traits")] #[rustfmt::skip] mod hash; } #[cfg(feature = "fold")] #[cfg_attr(docsrs, doc(cfg(feature = "fold")))] pub use crate::gen::fold; #[cfg(feature = "visit")] #[cfg_attr(docsrs, doc(cfg(feature = "visit")))] pub use crate::gen::visit; #[cfg(feature = "visit-mut")] #[cfg_attr(docsrs, doc(cfg(feature = "visit-mut")))] pub use crate::gen::visit_mut; // Not public API. #[doc(hidden)] #[path = "export.rs"] pub mod __private; /// Parse tokens of source code into the chosen syntax tree node. /// /// This is preferred over parsing a string because tokens are able to preserve /// information about where in the user's code they were originally written (the /// "span" of the token), possibly allowing the compiler to produce better error /// messages. /// /// This function parses a `proc_macro::TokenStream` which is the type used for /// interop with the compiler in a procedural macro. To parse a /// `proc_macro2::TokenStream`, use [`syn::parse2`] instead. /// /// [`syn::parse2`]: parse2 /// /// # Examples /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use quote::quote; /// use syn::DeriveInput; /// /// # const IGNORE_TOKENS: &str = stringify! { /// #[proc_macro_derive(MyMacro)] /// # }; /// pub fn my_macro(input: TokenStream) -> TokenStream { /// // Parse the tokens into a syntax tree /// let ast: DeriveInput = syn::parse(input).unwrap(); /// /// // Build the output, possibly using quasi-quotation /// let expanded = quote! { /// /* ... */ /// }; /// /// // Convert into a token stream and return it /// expanded.into() /// } /// ``` #[cfg(all(feature = "parsing", feature = "proc-macro"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "proc-macro"))))] pub fn parse(tokens: proc_macro::TokenStream) -> Result { parse::Parser::parse(T::parse, tokens) } /// Parse a proc-macro2 token stream into the chosen syntax tree node. /// /// This function will check that the input is fully parsed. If there are /// any unparsed tokens at the end of the stream, an error is returned. /// /// This function parses a `proc_macro2::TokenStream` which is commonly useful /// when the input comes from a node of the Syn syntax tree, for example the /// body tokens of a [`Macro`] node. When in a procedural macro parsing the /// `proc_macro::TokenStream` provided by the compiler, use [`syn::parse`] /// instead. /// /// [`syn::parse`]: parse() #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse2(tokens: proc_macro2::TokenStream) -> Result { parse::Parser::parse2(T::parse, tokens) } /// Parse a string of Rust code into the chosen syntax tree node. /// /// # Hygiene /// /// Every span in the resulting syntax tree will be set to resolve at the macro /// call site. /// /// # Examples /// /// ``` /// use syn::{Expr, Result}; /// /// fn run() -> Result<()> { /// let code = "assert_eq!(u8::max_value(), 255)"; /// let expr = syn::parse_str::(code)?; /// println!("{:#?}", expr); /// Ok(()) /// } /// # /// # run().unwrap(); /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_str(s: &str) -> Result { parse::Parser::parse_str(T::parse, s) } /// Parse the content of a file of Rust code. /// /// This is different from `syn::parse_str::(content)` in two ways: /// /// - It discards a leading byte order mark `\u{FEFF}` if the file has one. /// - It preserves the shebang line of the file, such as `#!/usr/bin/env rustx`. /// /// If present, either of these would be an error using `from_str`. /// /// # Examples /// /// ```no_run /// use std::error::Error; /// use std::fs::File; /// use std::io::Read; /// /// fn run() -> Result<(), Box> { /// let mut file = File::open("path/to/code.rs")?; /// let mut content = String::new(); /// file.read_to_string(&mut content)?; /// /// let ast = syn::parse_file(&content)?; /// if let Some(shebang) = ast.shebang { /// println!("{}", shebang); /// } /// println!("{} items", ast.items.len()); /// /// Ok(()) /// } /// # /// # run().unwrap(); /// ``` #[cfg(all(feature = "parsing", feature = "full"))] #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))] pub fn parse_file(mut content: &str) -> Result { // Strip the BOM if it is present const BOM: &str = "\u{feff}"; if content.starts_with(BOM) { content = &content[BOM.len()..]; } let mut shebang = None; if content.starts_with("#!") { let rest = whitespace::skip(&content[2..]); if !rest.starts_with('[') { if let Some(idx) = content.find('\n') { shebang = Some(content[..idx].to_string()); content = &content[idx..]; } else { shebang = Some(content.to_string()); content = ""; } } } let mut file: File = parse_str(content)?; file.shebang = shebang; Ok(file) } syn/src/stmt.rs0000644000175000017500000004044414661133735014504 0ustar jamespagejamespageuse crate::attr::Attribute; use crate::expr::Expr; use crate::item::Item; use crate::mac::Macro; use crate::pat::Pat; use crate::token; ast_struct! { /// A braced block containing Rust statements. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Block { pub brace_token: token::Brace, /// Statements in a block pub stmts: Vec, } } ast_enum! { /// A statement, usually ending in a semicolon. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub enum Stmt { /// A local (let) binding. Local(Local), /// An item definition. Item(Item), /// Expression, with or without trailing semicolon. Expr(Expr, Option), /// A macro invocation in statement position. /// /// Syntactically it's ambiguous which other kind of statement this /// macro would expand to. It can be any of local variable (`let`), /// item, or expression. Macro(StmtMacro), } } ast_struct! { /// A local `let` binding: `let x: u64 = s.parse()?`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Local { pub attrs: Vec, pub let_token: Token![let], pub pat: Pat, pub init: Option, pub semi_token: Token![;], } } ast_struct! { /// The expression assigned in a local `let` binding, including optional /// diverging `else` block. /// /// `LocalInit` represents `= s.parse()?` in `let x: u64 = s.parse()?` and /// `= r else { return }` in `let Ok(x) = r else { return }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct LocalInit { pub eq_token: Token![=], pub expr: Box, pub diverge: Option<(Token![else], Box)>, } } ast_struct! { /// A macro invocation in statement position. /// /// Syntactically it's ambiguous which other kind of statement this macro /// would expand to. It can be any of local variable (`let`), item, or /// expression. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct StmtMacro { pub attrs: Vec, pub mac: Macro, pub semi_token: Option, } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::classify; use crate::error::Result; use crate::expr::{Expr, ExprBlock, ExprMacro}; use crate::ident::Ident; use crate::item; use crate::mac::{self, Macro}; use crate::parse::discouraged::Speculative as _; use crate::parse::{Parse, ParseStream}; use crate::pat::{Pat, PatType}; use crate::path::Path; use crate::stmt::{Block, Local, LocalInit, Stmt, StmtMacro}; use crate::token; use crate::ty::Type; use proc_macro2::TokenStream; struct AllowNoSemi(bool); impl Block { /// Parse the body of a block as zero or more statements, possibly /// including one trailing expression. /// /// # Example /// /// ``` /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parse a function with no generics or parameter list. /// // /// // fn playground { /// // let mut x = 1; /// // x += 1; /// // println!("{}", x); /// // } /// struct MiniFunction { /// attrs: Vec, /// fn_token: Token![fn], /// name: Ident, /// brace_token: token::Brace, /// stmts: Vec, /// } /// /// impl Parse for MiniFunction { /// fn parse(input: ParseStream) -> Result { /// let outer_attrs = input.call(Attribute::parse_outer)?; /// let fn_token: Token![fn] = input.parse()?; /// let name: Ident = input.parse()?; /// /// let content; /// let brace_token = braced!(content in input); /// let inner_attrs = content.call(Attribute::parse_inner)?; /// let stmts = content.call(Block::parse_within)?; /// /// Ok(MiniFunction { /// attrs: { /// let mut attrs = outer_attrs; /// attrs.extend(inner_attrs); /// attrs /// }, /// fn_token, /// name, /// brace_token, /// stmts, /// }) /// } /// } /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_within(input: ParseStream) -> Result> { let mut stmts = Vec::new(); loop { while let semi @ Some(_) = input.parse()? { stmts.push(Stmt::Expr(Expr::Verbatim(TokenStream::new()), semi)); } if input.is_empty() { break; } let stmt = parse_stmt(input, AllowNoSemi(true))?; let requires_semicolon = match &stmt { Stmt::Expr(stmt, None) => classify::requires_semi_to_be_stmt(stmt), Stmt::Macro(stmt) => { stmt.semi_token.is_none() && !stmt.mac.delimiter.is_brace() } Stmt::Local(_) | Stmt::Item(_) | Stmt::Expr(_, Some(_)) => false, }; stmts.push(stmt); if input.is_empty() { break; } else if requires_semicolon { return Err(input.error("unexpected token, expected `;`")); } } Ok(stmts) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Block { fn parse(input: ParseStream) -> Result { let content; Ok(Block { brace_token: braced!(content in input), stmts: content.call(Block::parse_within)?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Stmt { fn parse(input: ParseStream) -> Result { let allow_nosemi = AllowNoSemi(false); parse_stmt(input, allow_nosemi) } } fn parse_stmt(input: ParseStream, allow_nosemi: AllowNoSemi) -> Result { let begin = input.fork(); let attrs = input.call(Attribute::parse_outer)?; // brace-style macros; paren and bracket macros get parsed as // expression statements. let ahead = input.fork(); let mut is_item_macro = false; if let Ok(path) = ahead.call(Path::parse_mod_style) { if ahead.peek(Token![!]) { if ahead.peek2(Ident) || ahead.peek2(Token![try]) { is_item_macro = true; } else if ahead.peek2(token::Brace) && !(ahead.peek3(Token![.]) || ahead.peek3(Token![?])) { input.advance_to(&ahead); return stmt_mac(input, attrs, path).map(Stmt::Macro); } } } if input.peek(Token![let]) && !input.peek(token::Group) { stmt_local(input, attrs).map(Stmt::Local) } else if input.peek(Token![pub]) || input.peek(Token![crate]) && !input.peek2(Token![::]) || input.peek(Token![extern]) || input.peek(Token![use]) || input.peek(Token![static]) && (input.peek2(Token![mut]) || input.peek2(Ident) && !(input.peek2(Token![async]) && (input.peek3(Token![move]) || input.peek3(Token![|])))) || input.peek(Token![const]) && !(input.peek2(token::Brace) || input.peek2(Token![static]) || input.peek2(Token![async]) && !(input.peek3(Token![unsafe]) || input.peek3(Token![extern]) || input.peek3(Token![fn])) || input.peek2(Token![move]) || input.peek2(Token![|])) || input.peek(Token![unsafe]) && !input.peek2(token::Brace) || input.peek(Token![async]) && (input.peek2(Token![unsafe]) || input.peek2(Token![extern]) || input.peek2(Token![fn])) || input.peek(Token![fn]) || input.peek(Token![mod]) || input.peek(Token![type]) || input.peek(Token![struct]) || input.peek(Token![enum]) || input.peek(Token![union]) && input.peek2(Ident) || input.peek(Token![auto]) && input.peek2(Token![trait]) || input.peek(Token![trait]) || input.peek(Token![default]) && (input.peek2(Token![unsafe]) || input.peek2(Token![impl])) || input.peek(Token![impl]) || input.peek(Token![macro]) || is_item_macro { let item = item::parsing::parse_rest_of_item(begin, attrs, input)?; Ok(Stmt::Item(item)) } else { stmt_expr(input, allow_nosemi, attrs) } } fn stmt_mac(input: ParseStream, attrs: Vec, path: Path) -> Result { let bang_token: Token![!] = input.parse()?; let (delimiter, tokens) = mac::parse_delimiter(input)?; let semi_token: Option = input.parse()?; Ok(StmtMacro { attrs, mac: Macro { path, bang_token, delimiter, tokens, }, semi_token, }) } fn stmt_local(input: ParseStream, attrs: Vec) -> Result { let let_token: Token![let] = input.parse()?; let mut pat = Pat::parse_single(input)?; if input.peek(Token![:]) { let colon_token: Token![:] = input.parse()?; let ty: Type = input.parse()?; pat = Pat::Type(PatType { attrs: Vec::new(), pat: Box::new(pat), colon_token, ty: Box::new(ty), }); } let init = if let Some(eq_token) = input.parse()? { let eq_token: Token![=] = eq_token; let expr: Expr = input.parse()?; let diverge = if !classify::expr_trailing_brace(&expr) && input.peek(Token![else]) { let else_token: Token![else] = input.parse()?; let diverge = ExprBlock { attrs: Vec::new(), label: None, block: input.parse()?, }; Some((else_token, Box::new(Expr::Block(diverge)))) } else { None }; Some(LocalInit { eq_token, expr: Box::new(expr), diverge, }) } else { None }; let semi_token: Token![;] = input.parse()?; Ok(Local { attrs, let_token, pat, init, semi_token, }) } fn stmt_expr( input: ParseStream, allow_nosemi: AllowNoSemi, mut attrs: Vec, ) -> Result { let mut e = Expr::parse_with_earlier_boundary_rule(input)?; let mut attr_target = &mut e; loop { attr_target = match attr_target { Expr::Assign(e) => &mut e.left, Expr::Binary(e) => &mut e.left, Expr::Cast(e) => &mut e.expr, Expr::Array(_) | Expr::Async(_) | Expr::Await(_) | Expr::Block(_) | Expr::Break(_) | Expr::Call(_) | Expr::Closure(_) | Expr::Const(_) | Expr::Continue(_) | Expr::Field(_) | Expr::ForLoop(_) | Expr::Group(_) | Expr::If(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) | Expr::Struct(_) | Expr::Try(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unary(_) | Expr::Unsafe(_) | Expr::While(_) | Expr::Yield(_) | Expr::Verbatim(_) => break, }; } attrs.extend(attr_target.replace_attrs(Vec::new())); attr_target.replace_attrs(attrs); let semi_token: Option = input.parse()?; match e { Expr::Macro(ExprMacro { attrs, mac }) if semi_token.is_some() || mac.delimiter.is_brace() => { return Ok(Stmt::Macro(StmtMacro { attrs, mac, semi_token, })); } _ => {} } if semi_token.is_some() { Ok(Stmt::Expr(e, semi_token)) } else if allow_nosemi.0 || !classify::requires_semi_to_be_stmt(&e) { Ok(Stmt::Expr(e, None)) } else { Err(input.error("expected semicolon")) } } } #[cfg(feature = "printing")] pub(crate) mod printing { use crate::classify; use crate::expr::{self, Expr}; use crate::fixup::FixupContext; use crate::stmt::{Block, Local, Stmt, StmtMacro}; use crate::token; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Block { fn to_tokens(&self, tokens: &mut TokenStream) { self.brace_token.surround(tokens, |tokens| { tokens.append_all(&self.stmts); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Stmt { fn to_tokens(&self, tokens: &mut TokenStream) { match self { Stmt::Local(local) => local.to_tokens(tokens), Stmt::Item(item) => item.to_tokens(tokens), Stmt::Expr(expr, semi) => { expr::printing::print_expr(expr, tokens, FixupContext::new_stmt()); semi.to_tokens(tokens); } Stmt::Macro(mac) => mac.to_tokens(tokens), } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Local { fn to_tokens(&self, tokens: &mut TokenStream) { expr::printing::outer_attrs_to_tokens(&self.attrs, tokens); self.let_token.to_tokens(tokens); self.pat.to_tokens(tokens); if let Some(init) = &self.init { init.eq_token.to_tokens(tokens); if init.diverge.is_some() && classify::expr_trailing_brace(&init.expr) { token::Paren::default().surround(tokens, |tokens| init.expr.to_tokens(tokens)); } else { init.expr.to_tokens(tokens); } if let Some((else_token, diverge)) = &init.diverge { else_token.to_tokens(tokens); match &**diverge { Expr::Block(diverge) => diverge.to_tokens(tokens), _ => token::Brace::default().surround(tokens, |tokens| { expr::printing::print_expr(diverge, tokens, FixupContext::new_stmt()); }), } } } self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for StmtMacro { fn to_tokens(&self, tokens: &mut TokenStream) { expr::printing::outer_attrs_to_tokens(&self.attrs, tokens); self.mac.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } } syn/src/buffer.rs0000644000175000017500000003636214661133735014772 0ustar jamespagejamespage//! A stably addressed token buffer supporting efficient traversal based on a //! cheaply copyable cursor. // This module is heavily commented as it contains most of the unsafe code in // Syn, and caution should be used when editing it. The public-facing interface // is 100% safe but the implementation is fragile internally. use crate::Lifetime; use proc_macro2::extra::DelimSpan; use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; use std::cmp::Ordering; use std::marker::PhantomData; /// Internal type which is used instead of `TokenTree` to represent a token tree /// within a `TokenBuffer`. enum Entry { // Mimicking types from proc-macro. // Group entries contain the offset to the matching End entry. Group(Group, usize), Ident(Ident), Punct(Punct), Literal(Literal), // End entries contain the offset (negative) to the start of the buffer, and // offset (negative) to the matching Group entry. End(isize, isize), } /// A buffer that can be efficiently traversed multiple times, unlike /// `TokenStream` which requires a deep copy in order to traverse more than /// once. pub struct TokenBuffer { // NOTE: Do not implement clone on this - while the current design could be // cloned, other designs which could be desirable may not be cloneable. entries: Box<[Entry]>, } impl TokenBuffer { fn recursive_new(entries: &mut Vec, stream: TokenStream) { for tt in stream { match tt { TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)), TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)), TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)), TokenTree::Group(group) => { let group_start_index = entries.len(); entries.push(Entry::End(0, 0)); // we replace this below Self::recursive_new(entries, group.stream()); let group_end_index = entries.len(); let group_offset = group_end_index - group_start_index; entries.push(Entry::End( -(group_end_index as isize), -(group_offset as isize), )); entries[group_start_index] = Entry::Group(group, group_offset); } } } } /// Creates a `TokenBuffer` containing all the tokens from the input /// `proc_macro::TokenStream`. #[cfg(feature = "proc-macro")] #[cfg_attr(docsrs, doc(cfg(feature = "proc-macro")))] pub fn new(stream: proc_macro::TokenStream) -> Self { Self::new2(stream.into()) } /// Creates a `TokenBuffer` containing all the tokens from the input /// `proc_macro2::TokenStream`. pub fn new2(stream: TokenStream) -> Self { let mut entries = Vec::new(); Self::recursive_new(&mut entries, stream); entries.push(Entry::End(-(entries.len() as isize), 0)); Self { entries: entries.into_boxed_slice(), } } /// Creates a cursor referencing the first token in the buffer and able to /// traverse until the end of the buffer. pub fn begin(&self) -> Cursor { let ptr = self.entries.as_ptr(); unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) } } } /// A cheaply copyable cursor into a `TokenBuffer`. /// /// This cursor holds a shared reference into the immutable data which is used /// internally to represent a `TokenStream`, and can be efficiently manipulated /// and copied around. /// /// An empty `Cursor` can be created directly, or one may create a `TokenBuffer` /// object and get a cursor to its first token with `begin()`. pub struct Cursor<'a> { // The current entry which the `Cursor` is pointing at. ptr: *const Entry, // This is the only `Entry::End` object which this cursor is allowed to // point at. All other `End` objects are skipped over in `Cursor::create`. scope: *const Entry, // Cursor is covariant in 'a. This field ensures that our pointers are still // valid. marker: PhantomData<&'a Entry>, } impl<'a> Cursor<'a> { /// Creates a cursor referencing a static empty TokenStream. pub fn empty() -> Self { // It's safe in this situation for us to put an `Entry` object in global // storage, despite it not actually being safe to send across threads // (`Ident` is a reference into a thread-local table). This is because // this entry never includes a `Ident` object. // // This wrapper struct allows us to break the rules and put a `Sync` // object in global storage. struct UnsafeSyncEntry(Entry); unsafe impl Sync for UnsafeSyncEntry {} static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0, 0)); Cursor { ptr: &EMPTY_ENTRY.0, scope: &EMPTY_ENTRY.0, marker: PhantomData, } } /// This create method intelligently exits non-explicitly-entered /// `None`-delimited scopes when the cursor reaches the end of them, /// allowing for them to be treated transparently. unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self { // NOTE: If we're looking at a `End`, we want to advance the cursor // past it, unless `ptr == scope`, which means that we're at the edge of // our cursor's scope. We should only have `ptr != scope` at the exit // from None-delimited groups entered with `ignore_none`. while let Entry::End(..) = unsafe { &*ptr } { if ptr == scope { break; } ptr = unsafe { ptr.add(1) }; } Cursor { ptr, scope, marker: PhantomData, } } /// Get the current entry. fn entry(self) -> &'a Entry { unsafe { &*self.ptr } } /// Bump the cursor to point at the next token after the current one. This /// is undefined behavior if the cursor is currently looking at an /// `Entry::End`. /// /// If the cursor is looking at an `Entry::Group`, the bumped cursor will /// point at the first token in the group (with the same scope end). unsafe fn bump_ignore_group(self) -> Cursor<'a> { unsafe { Cursor::create(self.ptr.offset(1), self.scope) } } /// While the cursor is looking at a `None`-delimited group, move it to look /// at the first token inside instead. If the group is empty, this will move /// the cursor past the `None`-delimited group. /// /// WARNING: This mutates its argument. fn ignore_none(&mut self) { while let Entry::Group(group, _) = self.entry() { if group.delimiter() == Delimiter::None { unsafe { *self = self.bump_ignore_group() }; } else { break; } } } /// Checks whether the cursor is currently pointing at the end of its valid /// scope. pub fn eof(self) -> bool { // We're at eof if we're at the end of our scope. self.ptr == self.scope } /// If the cursor is pointing at a `Group` with the given delimiter, returns /// a cursor into that group and one pointing to the next `TokenTree`. pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, DelimSpan, Cursor<'a>)> { // If we're not trying to enter a none-delimited group, we want to // ignore them. We have to make sure to _not_ ignore them when we want // to enter them, of course. For obvious reasons. if delim != Delimiter::None { self.ignore_none(); } if let Entry::Group(group, end_offset) = self.entry() { if group.delimiter() == delim { let span = group.delim_span(); let end_of_group = unsafe { self.ptr.add(*end_offset) }; let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) }; let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; return Some((inside_of_group, span, after_group)); } } None } pub(crate) fn any_group(self) -> Option<(Cursor<'a>, Delimiter, DelimSpan, Cursor<'a>)> { if let Entry::Group(group, end_offset) = self.entry() { let delimiter = group.delimiter(); let span = group.delim_span(); let end_of_group = unsafe { self.ptr.add(*end_offset) }; let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) }; let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; return Some((inside_of_group, delimiter, span, after_group)); } None } pub(crate) fn any_group_token(self) -> Option<(Group, Cursor<'a>)> { if let Entry::Group(group, end_offset) = self.entry() { let end_of_group = unsafe { self.ptr.add(*end_offset) }; let after_group = unsafe { Cursor::create(end_of_group, self.scope) }; return Some((group.clone(), after_group)); } None } /// If the cursor is pointing at a `Ident`, returns it along with a cursor /// pointing at the next `TokenTree`. pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> { self.ignore_none(); match self.entry() { Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })), _ => None, } } /// If the cursor is pointing at a `Punct`, returns it along with a cursor /// pointing at the next `TokenTree`. pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> { self.ignore_none(); match self.entry() { Entry::Punct(punct) if punct.as_char() != '\'' => { Some((punct.clone(), unsafe { self.bump_ignore_group() })) } _ => None, } } /// If the cursor is pointing at a `Literal`, return it along with a cursor /// pointing at the next `TokenTree`. pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> { self.ignore_none(); match self.entry() { Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })), _ => None, } } /// If the cursor is pointing at a `Lifetime`, returns it along with a /// cursor pointing at the next `TokenTree`. pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> { self.ignore_none(); match self.entry() { Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => { let next = unsafe { self.bump_ignore_group() }; let (ident, rest) = next.ident()?; let lifetime = Lifetime { apostrophe: punct.span(), ident, }; Some((lifetime, rest)) } _ => None, } } /// Copies all remaining tokens visible from this cursor into a /// `TokenStream`. pub fn token_stream(self) -> TokenStream { let mut tts = Vec::new(); let mut cursor = self; while let Some((tt, rest)) = cursor.token_tree() { tts.push(tt); cursor = rest; } tts.into_iter().collect() } /// If the cursor is pointing at a `TokenTree`, returns it along with a /// cursor pointing at the next `TokenTree`. /// /// Returns `None` if the cursor has reached the end of its stream. /// /// This method does not treat `None`-delimited groups as transparent, and /// will return a `Group(None, ..)` if the cursor is looking at one. pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> { let (tree, len) = match self.entry() { Entry::Group(group, end_offset) => (group.clone().into(), *end_offset), Entry::Literal(literal) => (literal.clone().into(), 1), Entry::Ident(ident) => (ident.clone().into(), 1), Entry::Punct(punct) => (punct.clone().into(), 1), Entry::End(..) => return None, }; let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) }; Some((tree, rest)) } /// Returns the `Span` of the current token, or `Span::call_site()` if this /// cursor points to eof. pub fn span(mut self) -> Span { match self.entry() { Entry::Group(group, _) => group.span(), Entry::Literal(literal) => literal.span(), Entry::Ident(ident) => ident.span(), Entry::Punct(punct) => punct.span(), Entry::End(_, offset) => { self.ptr = unsafe { self.ptr.offset(*offset) }; if let Entry::Group(group, _) = self.entry() { group.span_close() } else { Span::call_site() } } } } /// Returns the `Span` of the token immediately prior to the position of /// this cursor, or of the current token if there is no previous one. #[cfg(any(feature = "full", feature = "derive"))] pub(crate) fn prev_span(mut self) -> Span { if start_of_buffer(self) < self.ptr { self.ptr = unsafe { self.ptr.offset(-1) }; } self.span() } /// Skip over the next token that is not a None-delimited group, without /// cloning it. Returns `None` if this cursor points to eof. /// /// This method treats `'lifetimes` as a single token. pub(crate) fn skip(mut self) -> Option> { self.ignore_none(); let len = match self.entry() { Entry::End(..) => return None, // Treat lifetimes as a single tt for the purposes of 'skip'. Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => { match unsafe { &*self.ptr.add(1) } { Entry::Ident(_) => 2, _ => 1, } } Entry::Group(_, end_offset) => *end_offset, _ => 1, }; Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) }) } } impl<'a> Copy for Cursor<'a> {} impl<'a> Clone for Cursor<'a> { fn clone(&self) -> Self { *self } } impl<'a> Eq for Cursor<'a> {} impl<'a> PartialEq for Cursor<'a> { fn eq(&self, other: &Self) -> bool { self.ptr == other.ptr } } impl<'a> PartialOrd for Cursor<'a> { fn partial_cmp(&self, other: &Self) -> Option { if same_buffer(*self, *other) { Some(cmp_assuming_same_buffer(*self, *other)) } else { None } } } pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool { a.scope == b.scope } pub(crate) fn same_buffer(a: Cursor, b: Cursor) -> bool { start_of_buffer(a) == start_of_buffer(b) } fn start_of_buffer(cursor: Cursor) -> *const Entry { unsafe { match &*cursor.scope { Entry::End(offset, _) => cursor.scope.offset(*offset), _ => unreachable!(), } } } pub(crate) fn cmp_assuming_same_buffer(a: Cursor, b: Cursor) -> Ordering { a.ptr.cmp(&b.ptr) } pub(crate) fn open_span_of_group(cursor: Cursor) -> Span { match cursor.entry() { Entry::Group(group, _) => group.span_open(), _ => cursor.span(), } } syn/src/classify.rs0000644000175000017500000003337514661133735015337 0ustar jamespagejamespageuse crate::expr::Expr; use crate::generics::TypeParamBound; use crate::path::{Path, PathArguments}; use crate::punctuated::Punctuated; use crate::ty::{ReturnType, Type}; #[cfg(feature = "full")] use proc_macro2::{Delimiter, TokenStream, TokenTree}; use std::ops::ControlFlow; #[cfg(feature = "full")] pub(crate) fn requires_semi_to_be_stmt(expr: &Expr) -> bool { match expr { Expr::Macro(expr) => !expr.mac.delimiter.is_brace(), _ => requires_comma_to_be_match_arm(expr), } } #[cfg(feature = "full")] pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool { match expr { Expr::If(_) | Expr::Match(_) | Expr::Block(_) | Expr::Unsafe(_) // both under ExprKind::Block in rustc | Expr::While(_) | Expr::Loop(_) | Expr::ForLoop(_) | Expr::TryBlock(_) | Expr::Const(_) => false, Expr::Array(_) | Expr::Assign(_) | Expr::Async(_) | Expr::Await(_) | Expr::Binary(_) | Expr::Break(_) | Expr::Call(_) | Expr::Cast(_) | Expr::Closure(_) | Expr::Continue(_) | Expr::Field(_) | Expr::Group(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Macro(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) | Expr::Struct(_) | Expr::Try(_) | Expr::Tuple(_) | Expr::Unary(_) | Expr::Yield(_) | Expr::Verbatim(_) => true } } #[cfg(all(feature = "printing", feature = "full"))] pub(crate) fn confusable_with_adjacent_block(mut expr: &Expr) -> bool { let mut stack = Vec::new(); while let Some(next) = match expr { Expr::Assign(e) => { stack.push(&e.right); Some(&e.left) } Expr::Await(e) => Some(&e.base), Expr::Binary(e) => { stack.push(&e.right); Some(&e.left) } Expr::Break(e) => { if let Some(Expr::Block(_)) = e.expr.as_deref() { return true; } stack.pop() } Expr::Call(e) => Some(&e.func), Expr::Cast(e) => Some(&e.expr), Expr::Closure(e) => Some(&e.body), Expr::Field(e) => Some(&e.base), Expr::Index(e) => Some(&e.expr), Expr::MethodCall(e) => Some(&e.receiver), Expr::Range(e) => { if let Some(Expr::Block(_)) = e.end.as_deref() { return true; } match (&e.start, &e.end) { (Some(start), end) => { stack.extend(end); Some(start) } (None, Some(end)) => Some(end), (None, None) => stack.pop(), } } Expr::Reference(e) => Some(&e.expr), Expr::Return(e) => { if e.expr.is_none() && stack.is_empty() { return true; } stack.pop() } Expr::Struct(_) => return true, Expr::Try(e) => Some(&e.expr), Expr::Unary(e) => Some(&e.expr), Expr::Yield(e) => { if e.expr.is_none() && stack.is_empty() { return true; } stack.pop() } Expr::Array(_) | Expr::Async(_) | Expr::Block(_) | Expr::Const(_) | Expr::Continue(_) | Expr::ForLoop(_) | Expr::Group(_) | Expr::If(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Repeat(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::While(_) => stack.pop(), } { expr = next; } false } #[cfg(feature = "printing")] pub(crate) fn confusable_with_adjacent_lt(mut expr: &Expr) -> bool { loop { match expr { Expr::Binary(e) => expr = &e.right, Expr::Cast(e) => return trailing_unparameterized_path(&e.ty), Expr::Reference(e) => expr = &e.expr, Expr::Unary(e) => expr = &e.expr, Expr::Array(_) | Expr::Assign(_) | Expr::Async(_) | Expr::Await(_) | Expr::Block(_) | Expr::Break(_) | Expr::Call(_) | Expr::Closure(_) | Expr::Const(_) | Expr::Continue(_) | Expr::Field(_) | Expr::ForLoop(_) | Expr::Group(_) | Expr::If(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) | Expr::Repeat(_) | Expr::Return(_) | Expr::Struct(_) | Expr::Try(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::While(_) | Expr::Yield(_) => return false, } } fn trailing_unparameterized_path(mut ty: &Type) -> bool { loop { match ty { Type::BareFn(t) => match &t.output { ReturnType::Default => return false, ReturnType::Type(_, ret) => ty = ret, }, Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) { ControlFlow::Break(trailing_path) => return trailing_path, ControlFlow::Continue(t) => ty = t, }, Type::Path(t) => match last_type_in_path(&t.path) { ControlFlow::Break(trailing_path) => return trailing_path, ControlFlow::Continue(t) => ty = t, }, Type::Ptr(t) => ty = &t.elem, Type::Reference(t) => ty = &t.elem, Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) { ControlFlow::Break(trailing_path) => return trailing_path, ControlFlow::Continue(t) => ty = t, }, Type::Array(_) | Type::Group(_) | Type::Infer(_) | Type::Macro(_) | Type::Never(_) | Type::Paren(_) | Type::Slice(_) | Type::Tuple(_) | Type::Verbatim(_) => return false, } } } fn last_type_in_path(path: &Path) -> ControlFlow { match &path.segments.last().unwrap().arguments { PathArguments::None => ControlFlow::Break(true), PathArguments::AngleBracketed(_) => ControlFlow::Break(false), PathArguments::Parenthesized(arg) => match &arg.output { ReturnType::Default => ControlFlow::Break(false), ReturnType::Type(_, ret) => ControlFlow::Continue(ret), }, } } fn last_type_in_bounds( bounds: &Punctuated, ) -> ControlFlow { match bounds.last().unwrap() { TypeParamBound::Trait(t) => last_type_in_path(&t.path), TypeParamBound::Lifetime(_) | TypeParamBound::Verbatim(_) => ControlFlow::Break(false), } } } /// Whether the expression's first token is the label of a loop/block. #[cfg(all(feature = "printing", feature = "full"))] pub(crate) fn expr_leading_label(mut expr: &Expr) -> bool { loop { match expr { Expr::Block(e) => return e.label.is_some(), Expr::ForLoop(e) => return e.label.is_some(), Expr::Loop(e) => return e.label.is_some(), Expr::While(e) => return e.label.is_some(), Expr::Assign(e) => expr = &e.left, Expr::Await(e) => expr = &e.base, Expr::Binary(e) => expr = &e.left, Expr::Call(e) => expr = &e.func, Expr::Cast(e) => expr = &e.expr, Expr::Field(e) => expr = &e.base, Expr::Index(e) => expr = &e.expr, Expr::MethodCall(e) => expr = &e.receiver, Expr::Range(e) => match &e.start { Some(start) => expr = start, None => return false, }, Expr::Try(e) => expr = &e.expr, Expr::Array(_) | Expr::Async(_) | Expr::Break(_) | Expr::Closure(_) | Expr::Const(_) | Expr::Continue(_) | Expr::Group(_) | Expr::If(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Macro(_) | Expr::Match(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) | Expr::Struct(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unary(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::Yield(_) => return false, } } } /// Whether the expression's last token is `}`. #[cfg(feature = "full")] pub(crate) fn expr_trailing_brace(mut expr: &Expr) -> bool { loop { match expr { Expr::Async(_) | Expr::Block(_) | Expr::Const(_) | Expr::ForLoop(_) | Expr::If(_) | Expr::Loop(_) | Expr::Match(_) | Expr::Struct(_) | Expr::TryBlock(_) | Expr::Unsafe(_) | Expr::While(_) => return true, Expr::Assign(e) => expr = &e.right, Expr::Binary(e) => expr = &e.right, Expr::Break(e) => match &e.expr { Some(e) => expr = e, None => return false, }, Expr::Cast(e) => return type_trailing_brace(&e.ty), Expr::Closure(e) => expr = &e.body, Expr::Let(e) => expr = &e.expr, Expr::Macro(e) => return e.mac.delimiter.is_brace(), Expr::Range(e) => match &e.end { Some(end) => expr = end, None => return false, }, Expr::Reference(e) => expr = &e.expr, Expr::Return(e) => match &e.expr { Some(e) => expr = e, None => return false, }, Expr::Unary(e) => expr = &e.expr, Expr::Verbatim(e) => return tokens_trailing_brace(e), Expr::Yield(e) => match &e.expr { Some(e) => expr = e, None => return false, }, Expr::Array(_) | Expr::Await(_) | Expr::Call(_) | Expr::Continue(_) | Expr::Field(_) | Expr::Group(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Lit(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Repeat(_) | Expr::Try(_) | Expr::Tuple(_) => return false, } } fn type_trailing_brace(mut ty: &Type) -> bool { loop { match ty { Type::BareFn(t) => match &t.output { ReturnType::Default => return false, ReturnType::Type(_, ret) => ty = ret, }, Type::ImplTrait(t) => match last_type_in_bounds(&t.bounds) { ControlFlow::Break(trailing_brace) => return trailing_brace, ControlFlow::Continue(t) => ty = t, }, Type::Macro(t) => return t.mac.delimiter.is_brace(), Type::Path(t) => match last_type_in_path(&t.path) { Some(t) => ty = t, None => return false, }, Type::Ptr(t) => ty = &t.elem, Type::Reference(t) => ty = &t.elem, Type::TraitObject(t) => match last_type_in_bounds(&t.bounds) { ControlFlow::Break(trailing_brace) => return trailing_brace, ControlFlow::Continue(t) => ty = t, }, Type::Verbatim(t) => return tokens_trailing_brace(t), Type::Array(_) | Type::Group(_) | Type::Infer(_) | Type::Never(_) | Type::Paren(_) | Type::Slice(_) | Type::Tuple(_) => return false, } } } fn last_type_in_path(path: &Path) -> Option<&Type> { match &path.segments.last().unwrap().arguments { PathArguments::None | PathArguments::AngleBracketed(_) => None, PathArguments::Parenthesized(arg) => match &arg.output { ReturnType::Default => None, ReturnType::Type(_, ret) => Some(ret), }, } } fn last_type_in_bounds( bounds: &Punctuated, ) -> ControlFlow { match bounds.last().unwrap() { TypeParamBound::Trait(t) => match last_type_in_path(&t.path) { Some(t) => ControlFlow::Continue(t), None => ControlFlow::Break(false), }, TypeParamBound::Lifetime(_) => ControlFlow::Break(false), TypeParamBound::Verbatim(t) => ControlFlow::Break(tokens_trailing_brace(t)), } } fn tokens_trailing_brace(tokens: &TokenStream) -> bool { if let Some(TokenTree::Group(last)) = tokens.clone().into_iter().last() { last.delimiter() == Delimiter::Brace } else { false } } } syn/src/spanned.rs0000644000175000017500000000730314661133735015142 0ustar jamespagejamespage//! A trait that can provide the `Span` of the complete contents of a syntax //! tree node. //! //!
//! //! # Example //! //! Suppose in a procedural macro we have a [`Type`] that we want to assert //! implements the [`Sync`] trait. Maybe this is the type of one of the fields //! of a struct for which we are deriving a trait implementation, and we need to //! be able to pass a reference to one of those fields across threads. //! //! [`Type`]: crate::Type //! [`Sync`]: std::marker::Sync //! //! If the field type does *not* implement `Sync` as required, we want the //! compiler to report an error pointing out exactly which type it was. //! //! The following macro code takes a variable `ty` of type `Type` and produces a //! static assertion that `Sync` is implemented for that type. //! //! ``` //! # extern crate proc_macro; //! # //! use proc_macro::TokenStream; //! use proc_macro2::Span; //! use quote::quote_spanned; //! use syn::Type; //! use syn::spanned::Spanned; //! //! # const IGNORE_TOKENS: &str = stringify! { //! #[proc_macro_derive(MyMacro)] //! # }; //! pub fn my_macro(input: TokenStream) -> TokenStream { //! # let ty = get_a_type(); //! /* ... */ //! //! let assert_sync = quote_spanned! {ty.span()=> //! struct _AssertSync where #ty: Sync; //! }; //! //! /* ... */ //! # input //! } //! # //! # fn get_a_type() -> Type { //! # unimplemented!() //! # } //! ``` //! //! By inserting this `assert_sync` fragment into the output code generated by //! our macro, the user's code will fail to compile if `ty` does not implement //! `Sync`. The errors they would see look like the following. //! //! ```text //! error[E0277]: the trait bound `*const i32: std::marker::Sync` is not satisfied //! --> src/main.rs:10:21 //! | //! 10 | bad_field: *const i32, //! | ^^^^^^^^^^ `*const i32` cannot be shared between threads safely //! ``` //! //! In this technique, using the `Type`'s span for the error message makes the //! error appear in the correct place underlining the right type. //! //!
//! //! # Limitations //! //! The underlying [`proc_macro::Span::join`] method is nightly-only. When //! called from within a procedural macro in a nightly compiler, `Spanned` will //! use `join` to produce the intended span. When not using a nightly compiler, //! only the span of the *first token* of the syntax tree node is returned. //! //! In the common case of wanting to use the joined span as the span of a //! `syn::Error`, consider instead using [`syn::Error::new_spanned`] which is //! able to span the error correctly under the complete syntax tree node without //! needing the unstable `join`. //! //! [`syn::Error::new_spanned`]: crate::Error::new_spanned use proc_macro2::Span; use quote::spanned::Spanned as ToTokens; /// A trait that can provide the `Span` of the complete contents of a syntax /// tree node. /// /// This trait is automatically implemented for all types that implement /// [`ToTokens`] from the `quote` crate, as well as for `Span` itself. /// /// [`ToTokens`]: quote::ToTokens /// /// See the [module documentation] for an example. /// /// [module documentation]: self pub trait Spanned: private::Sealed { /// Returns a `Span` covering the complete contents of this syntax tree /// node, or [`Span::call_site()`] if this node is empty. /// /// [`Span::call_site()`]: proc_macro2::Span::call_site fn span(&self) -> Span; } impl Spanned for T { fn span(&self) -> Span { self.__span() } } mod private { use crate::spanned::ToTokens; pub trait Sealed {} impl Sealed for T {} #[cfg(any(feature = "full", feature = "derive"))] impl Sealed for crate::QSelf {} } syn/src/lit.rs0000644000175000017500000015561614661133735014315 0ustar jamespagejamespage#[cfg(feature = "parsing")] use crate::lookahead; #[cfg(feature = "parsing")] use crate::parse::{Parse, Parser}; use crate::{Error, Result}; use proc_macro2::{Ident, Literal, Span}; #[cfg(feature = "parsing")] use proc_macro2::{TokenStream, TokenTree}; use std::ffi::{CStr, CString}; use std::fmt::{self, Display}; #[cfg(feature = "extra-traits")] use std::hash::{Hash, Hasher}; use std::str::{self, FromStr}; ast_enum_of_structs! { /// A Rust literal such as a string or integer or boolean. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[non_exhaustive] pub enum Lit { /// A UTF-8 string literal: `"foo"`. Str(LitStr), /// A byte string literal: `b"foo"`. ByteStr(LitByteStr), /// A nul-terminated C-string literal: `c"foo"`. CStr(LitCStr), /// A byte literal: `b'f'`. Byte(LitByte), /// A character literal: `'a'`. Char(LitChar), /// An integer literal: `1` or `1u16`. Int(LitInt), /// A floating point literal: `1f64` or `1.0e10f64`. /// /// Must be finite. May not be infinite or NaN. Float(LitFloat), /// A boolean literal: `true` or `false`. Bool(LitBool), /// A raw token literal not interpreted by Syn. Verbatim(Literal), } } ast_struct! { /// A UTF-8 string literal: `"foo"`. pub struct LitStr { repr: Box, } } ast_struct! { /// A byte string literal: `b"foo"`. pub struct LitByteStr { repr: Box, } } ast_struct! { /// A nul-terminated C-string literal: `c"foo"`. pub struct LitCStr { repr: Box, } } ast_struct! { /// A byte literal: `b'f'`. pub struct LitByte { repr: Box, } } ast_struct! { /// A character literal: `'a'`. pub struct LitChar { repr: Box, } } struct LitRepr { token: Literal, suffix: Box, } ast_struct! { /// An integer literal: `1` or `1u16`. pub struct LitInt { repr: Box, } } struct LitIntRepr { token: Literal, digits: Box, suffix: Box, } ast_struct! { /// A floating point literal: `1f64` or `1.0e10f64`. /// /// Must be finite. May not be infinite or NaN. pub struct LitFloat { repr: Box, } } struct LitFloatRepr { token: Literal, digits: Box, suffix: Box, } ast_struct! { /// A boolean literal: `true` or `false`. pub struct LitBool { pub value: bool, pub span: Span, } } impl LitStr { pub fn new(value: &str, span: Span) -> Self { let mut token = Literal::string(value); token.set_span(span); LitStr { repr: Box::new(LitRepr { token, suffix: Box::::default(), }), } } pub fn value(&self) -> String { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_str(&repr); String::from(value) } /// Parse a syntax tree node from the content of this string literal. /// /// All spans in the syntax tree will point to the span of this `LitStr`. /// /// # Example /// /// ``` /// use syn::{Attribute, Error, Expr, Lit, Meta, Path, Result}; /// /// // Parses the path from an attribute that looks like: /// // /// // #[path = "a::b::c"] /// // /// // or returns `None` if the input is some other attribute. /// fn get_path(attr: &Attribute) -> Result> { /// if !attr.path().is_ident("path") { /// return Ok(None); /// } /// /// if let Meta::NameValue(meta) = &attr.meta { /// if let Expr::Lit(expr) = &meta.value { /// if let Lit::Str(lit_str) = &expr.lit { /// return lit_str.parse().map(Some); /// } /// } /// } /// /// let message = "expected #[path = \"...\"]"; /// Err(Error::new_spanned(attr, message)) /// } /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse(&self) -> Result { self.parse_with(T::parse) } /// Invoke parser on the content of this string literal. /// /// All spans in the syntax tree will point to the span of this `LitStr`. /// /// # Example /// /// ``` /// # use proc_macro2::Span; /// # use syn::{LitStr, Result}; /// # /// # fn main() -> Result<()> { /// # let lit_str = LitStr::new("a::b::c", Span::call_site()); /// # /// # const IGNORE: &str = stringify! { /// let lit_str: LitStr = /* ... */; /// # }; /// /// // Parse a string literal like "a::b::c" into a Path, not allowing /// // generic arguments on any of the path segments. /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?; /// # /// # Ok(()) /// # } /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_with(&self, parser: F) -> Result { use proc_macro2::Group; // Token stream with every span replaced by the given one. fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream { stream .into_iter() .map(|token| respan_token_tree(token, span)) .collect() } // Token tree with every span replaced by the given one. fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree { match &mut token { TokenTree::Group(g) => { let stream = respan_token_stream(g.stream(), span); *g = Group::new(g.delimiter(), stream); g.set_span(span); } other => other.set_span(span), } token } // Parse string literal into a token stream with every span equal to the // original literal's span. let span = self.span(); let mut tokens = TokenStream::from_str(&self.value())?; tokens = respan_token_stream(tokens, span); let result = crate::parse::parse_scoped(parser, span, tokens)?; let suffix = self.suffix(); if !suffix.is_empty() { return Err(Error::new( self.span(), format!("unexpected suffix `{}` on string literal", suffix), )); } Ok(result) } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitByteStr { pub fn new(value: &[u8], span: Span) -> Self { let mut token = Literal::byte_string(value); token.set_span(span); LitByteStr { repr: Box::new(LitRepr { token, suffix: Box::::default(), }), } } pub fn value(&self) -> Vec { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_byte_str(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitCStr { pub fn new(value: &CStr, span: Span) -> Self { let mut token = Literal::c_string(value); token.set_span(span); LitCStr { repr: Box::new(LitRepr { token, suffix: Box::::default(), }), } } pub fn value(&self) -> CString { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_c_str(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitByte { pub fn new(value: u8, span: Span) -> Self { let mut token = Literal::u8_suffixed(value); token.set_span(span); LitByte { repr: Box::new(LitRepr { token, suffix: Box::::default(), }), } } pub fn value(&self) -> u8 { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_byte(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitChar { pub fn new(value: char, span: Span) -> Self { let mut token = Literal::character(value); token.set_span(span); LitChar { repr: Box::new(LitRepr { token, suffix: Box::::default(), }), } } pub fn value(&self) -> char { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_char(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitInt { pub fn new(repr: &str, span: Span) -> Self { let (digits, suffix) = match value::parse_lit_int(repr) { Some(parse) => parse, None => panic!("not an integer literal: `{}`", repr), }; let mut token: Literal = repr.parse().unwrap(); token.set_span(span); LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), } } pub fn base10_digits(&self) -> &str { &self.repr.digits } /// Parses the literal into a selected number type. /// /// This is equivalent to `lit.base10_digits().parse()` except that the /// resulting errors will be correctly spanned to point to the literal token /// in the macro input. /// /// ``` /// use syn::LitInt; /// use syn::parse::{Parse, ParseStream, Result}; /// /// struct Port { /// value: u16, /// } /// /// impl Parse for Port { /// fn parse(input: ParseStream) -> Result { /// let lit: LitInt = input.parse()?; /// let value = lit.base10_parse::()?; /// Ok(Port { value }) /// } /// } /// ``` pub fn base10_parse(&self) -> Result where N: FromStr, N::Err: Display, { self.base10_digits() .parse() .map_err(|err| Error::new(self.span(), err)) } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl From for LitInt { fn from(token: Literal) -> Self { let repr = token.to_string(); if let Some((digits, suffix)) = value::parse_lit_int(&repr) { LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), } } else { panic!("not an integer literal: `{}`", repr); } } } impl Display for LitInt { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.repr.token.fmt(formatter) } } impl LitFloat { pub fn new(repr: &str, span: Span) -> Self { let (digits, suffix) = match value::parse_lit_float(repr) { Some(parse) => parse, None => panic!("not a float literal: `{}`", repr), }; let mut token: Literal = repr.parse().unwrap(); token.set_span(span); LitFloat { repr: Box::new(LitFloatRepr { token, digits, suffix, }), } } pub fn base10_digits(&self) -> &str { &self.repr.digits } pub fn base10_parse(&self) -> Result where N: FromStr, N::Err: Display, { self.base10_digits() .parse() .map_err(|err| Error::new(self.span(), err)) } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl From for LitFloat { fn from(token: Literal) -> Self { let repr = token.to_string(); if let Some((digits, suffix)) = value::parse_lit_float(&repr) { LitFloat { repr: Box::new(LitFloatRepr { token, digits, suffix, }), } } else { panic!("not a float literal: `{}`", repr); } } } impl Display for LitFloat { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.repr.token.fmt(formatter) } } impl LitBool { pub fn new(value: bool, span: Span) -> Self { LitBool { value, span } } pub fn value(&self) -> bool { self.value } pub fn span(&self) -> Span { self.span } pub fn set_span(&mut self, span: Span) { self.span = span; } pub fn token(&self) -> Ident { let s = if self.value { "true" } else { "false" }; Ident::new(s, self.span) } } #[cfg(feature = "extra-traits")] mod debug_impls { use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr}; use std::fmt::{self, Debug}; #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitStr") } } impl LitStr { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("token", &format_args!("{}", self.repr.token)) .finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitByteStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitByteStr") } } impl LitByteStr { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("token", &format_args!("{}", self.repr.token)) .finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitCStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitCStr") } } impl LitCStr { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("token", &format_args!("{}", self.repr.token)) .finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitByte { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitByte") } } impl LitByte { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("token", &format_args!("{}", self.repr.token)) .finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitChar { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitChar") } } impl LitChar { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("token", &format_args!("{}", self.repr.token)) .finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitInt { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitInt") } } impl LitInt { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("token", &format_args!("{}", self.repr.token)) .finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitFloat { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitFloat") } } impl LitFloat { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("token", &format_args!("{}", self.repr.token)) .finish() } } #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Debug for LitBool { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.debug(formatter, "LitBool") } } impl LitBool { pub(crate) fn debug(&self, formatter: &mut fmt::Formatter, name: &str) -> fmt::Result { formatter .debug_struct(name) .field("value", &self.value) .finish() } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for LitRepr { fn clone(&self) -> Self { LitRepr { token: self.token.clone(), suffix: self.suffix.clone(), } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for LitIntRepr { fn clone(&self) -> Self { LitIntRepr { token: self.token.clone(), digits: self.digits.clone(), suffix: self.suffix.clone(), } } } #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for LitFloatRepr { fn clone(&self) -> Self { LitFloatRepr { token: self.token.clone(), digits: self.digits.clone(), suffix: self.suffix.clone(), } } } macro_rules! lit_extra_traits { ($ty:ident) => { #[cfg(feature = "clone-impls")] #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))] impl Clone for $ty { fn clone(&self) -> Self { $ty { repr: self.repr.clone(), } } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl PartialEq for $ty { fn eq(&self, other: &Self) -> bool { self.repr.token.to_string() == other.repr.token.to_string() } } #[cfg(feature = "extra-traits")] #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))] impl Hash for $ty { fn hash(&self, state: &mut H) where H: Hasher, { self.repr.token.to_string().hash(state); } } #[cfg(feature = "parsing")] pub_if_not_doc! { #[doc(hidden)] #[allow(non_snake_case)] pub fn $ty(marker: lookahead::TokenMarker) -> $ty { match marker {} } } }; } lit_extra_traits!(LitStr); lit_extra_traits!(LitByteStr); lit_extra_traits!(LitCStr); lit_extra_traits!(LitByte); lit_extra_traits!(LitChar); lit_extra_traits!(LitInt); lit_extra_traits!(LitFloat); #[cfg(feature = "parsing")] pub_if_not_doc! { #[doc(hidden)] #[allow(non_snake_case)] pub fn LitBool(marker: lookahead::TokenMarker) -> LitBool { match marker {} } } /// The style of a string literal, either plain quoted or a raw string like /// `r##"data"##`. #[doc(hidden)] // https://github.com/dtolnay/syn/issues/1566 pub enum StrStyle { /// An ordinary string like `"data"`. Cooked, /// A raw string like `r##"data"##`. /// /// The unsigned integer is the number of `#` symbols used. Raw(usize), } #[cfg(feature = "parsing")] pub_if_not_doc! { #[doc(hidden)] #[allow(non_snake_case)] pub fn Lit(marker: lookahead::TokenMarker) -> Lit { match marker {} } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::buffer::Cursor; use crate::error::Result; use crate::lit::{ value, Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt, LitIntRepr, LitStr, }; use crate::parse::{Parse, ParseStream, Unexpected}; use crate::token::{self, Token}; use proc_macro2::{Literal, Punct, Span}; use std::cell::Cell; use std::rc::Rc; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Lit { fn parse(input: ParseStream) -> Result { input.step(|cursor| { if let Some((lit, rest)) = cursor.literal() { return Ok((Lit::new(lit), rest)); } if let Some((ident, rest)) = cursor.ident() { let value = ident == "true"; if value || ident == "false" { let lit_bool = LitBool { value, span: ident.span(), }; return Ok((Lit::Bool(lit_bool), rest)); } } if let Some((punct, rest)) = cursor.punct() { if punct.as_char() == '-' { if let Some((lit, rest)) = parse_negative_lit(punct, rest) { return Ok((lit, rest)); } } } Err(cursor.error("expected literal")) }) } } fn parse_negative_lit(neg: Punct, cursor: Cursor) -> Option<(Lit, Cursor)> { let (lit, rest) = cursor.literal()?; let mut span = neg.span(); span = span.join(lit.span()).unwrap_or(span); let mut repr = lit.to_string(); repr.insert(0, '-'); if let Some((digits, suffix)) = value::parse_lit_int(&repr) { let mut token: Literal = repr.parse().unwrap(); token.set_span(span); return Some(( Lit::Int(LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), }), rest, )); } let (digits, suffix) = value::parse_lit_float(&repr)?; let mut token: Literal = repr.parse().unwrap(); token.set_span(span); Some(( Lit::Float(LitFloat { repr: Box::new(LitFloatRepr { token, digits, suffix, }), }), rest, )) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitStr { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::Str(lit)) => Ok(lit), _ => Err(head.error("expected string literal")), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitByteStr { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::ByteStr(lit)) => Ok(lit), _ => Err(head.error("expected byte string literal")), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitCStr { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::CStr(lit)) => Ok(lit), _ => Err(head.error("expected C string literal")), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitByte { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::Byte(lit)) => Ok(lit), _ => Err(head.error("expected byte literal")), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitChar { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::Char(lit)) => Ok(lit), _ => Err(head.error("expected character literal")), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitInt { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::Int(lit)) => Ok(lit), _ => Err(head.error("expected integer literal")), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitFloat { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::Float(lit)) => Ok(lit), _ => Err(head.error("expected floating point literal")), } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for LitBool { fn parse(input: ParseStream) -> Result { let head = input.fork(); match input.parse() { Ok(Lit::Bool(lit)) => Ok(lit), _ => Err(head.error("expected boolean literal")), } } } fn peek_impl(cursor: Cursor, peek: fn(ParseStream) -> bool) -> bool { let scope = Span::call_site(); let unexpected = Rc::new(Cell::new(Unexpected::None)); let buffer = crate::parse::new_parse_buffer(scope, cursor, unexpected); peek(&buffer) } macro_rules! impl_token { ($display:literal $name:ty) => { impl Token for $name { fn peek(cursor: Cursor) -> bool { fn peek(input: ParseStream) -> bool { <$name as Parse>::parse(input).is_ok() } peek_impl(cursor, peek) } fn display() -> &'static str { $display } } impl token::private::Sealed for $name {} }; } impl_token!("literal" Lit); impl_token!("string literal" LitStr); impl_token!("byte string literal" LitByteStr); impl_token!("C-string literal" LitCStr); impl_token!("byte literal" LitByte); impl_token!("character literal" LitChar); impl_token!("integer literal" LitInt); impl_token!("floating point literal" LitFloat); impl_token!("boolean literal" LitBool); } #[cfg(feature = "printing")] mod printing { use crate::lit::{LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitInt, LitStr}; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitByteStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitCStr { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitByte { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitChar { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitInt { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitFloat { fn to_tokens(&self, tokens: &mut TokenStream) { self.repr.token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for LitBool { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append(self.token()); } } } mod value { use crate::bigint::BigInt; use crate::lit::{ Lit, LitBool, LitByte, LitByteStr, LitCStr, LitChar, LitFloat, LitFloatRepr, LitInt, LitIntRepr, LitRepr, LitStr, }; use proc_macro2::{Literal, Span}; use std::ascii; use std::char; use std::ffi::CString; use std::ops::{Index, RangeFrom}; impl Lit { /// Interpret a Syn literal from a proc-macro2 literal. pub fn new(token: Literal) -> Self { let repr = token.to_string(); match byte(&repr, 0) { // "...", r"...", r#"..."# b'"' | b'r' => { let (_, suffix) = parse_lit_str(&repr); return Lit::Str(LitStr { repr: Box::new(LitRepr { token, suffix }), }); } b'b' => match byte(&repr, 1) { // b"...", br"...", br#"...#" b'"' | b'r' => { let (_, suffix) = parse_lit_byte_str(&repr); return Lit::ByteStr(LitByteStr { repr: Box::new(LitRepr { token, suffix }), }); } // b'...' b'\'' => { let (_, suffix) = parse_lit_byte(&repr); return Lit::Byte(LitByte { repr: Box::new(LitRepr { token, suffix }), }); } _ => {} }, // c"...", cr"...", cr#"..."# b'c' => { let (_, suffix) = parse_lit_c_str(&repr); return Lit::CStr(LitCStr { repr: Box::new(LitRepr { token, suffix }), }); } // '...' b'\'' => { let (_, suffix) = parse_lit_char(&repr); return Lit::Char(LitChar { repr: Box::new(LitRepr { token, suffix }), }); } b'0'..=b'9' | b'-' => { // 0, 123, 0xFF, 0o77, 0b11 if let Some((digits, suffix)) = parse_lit_int(&repr) { return Lit::Int(LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), }); } // 1.0, 1e-1, 1e+1 if let Some((digits, suffix)) = parse_lit_float(&repr) { return Lit::Float(LitFloat { repr: Box::new(LitFloatRepr { token, digits, suffix, }), }); } } // true, false b't' | b'f' => { if repr == "true" || repr == "false" { return Lit::Bool(LitBool { value: repr == "true", span: token.span(), }); } } b'(' if repr == "(/*ERROR*/)" => return Lit::Verbatim(token), _ => {} } panic!("unrecognized literal: `{}`", repr); } pub fn suffix(&self) -> &str { match self { Lit::Str(lit) => lit.suffix(), Lit::ByteStr(lit) => lit.suffix(), Lit::CStr(lit) => lit.suffix(), Lit::Byte(lit) => lit.suffix(), Lit::Char(lit) => lit.suffix(), Lit::Int(lit) => lit.suffix(), Lit::Float(lit) => lit.suffix(), Lit::Bool(_) | Lit::Verbatim(_) => "", } } pub fn span(&self) -> Span { match self { Lit::Str(lit) => lit.span(), Lit::ByteStr(lit) => lit.span(), Lit::CStr(lit) => lit.span(), Lit::Byte(lit) => lit.span(), Lit::Char(lit) => lit.span(), Lit::Int(lit) => lit.span(), Lit::Float(lit) => lit.span(), Lit::Bool(lit) => lit.span, Lit::Verbatim(lit) => lit.span(), } } pub fn set_span(&mut self, span: Span) { match self { Lit::Str(lit) => lit.set_span(span), Lit::ByteStr(lit) => lit.set_span(span), Lit::CStr(lit) => lit.set_span(span), Lit::Byte(lit) => lit.set_span(span), Lit::Char(lit) => lit.set_span(span), Lit::Int(lit) => lit.set_span(span), Lit::Float(lit) => lit.set_span(span), Lit::Bool(lit) => lit.span = span, Lit::Verbatim(lit) => lit.set_span(span), } } } /// Get the byte at offset idx, or a default of `b'\0'` if we're looking /// past the end of the input buffer. pub(crate) fn byte + ?Sized>(s: &S, idx: usize) -> u8 { let s = s.as_ref(); if idx < s.len() { s[idx] } else { 0 } } fn next_chr(s: &str) -> char { s.chars().next().unwrap_or('\0') } // Returns (content, suffix). pub(crate) fn parse_lit_str(s: &str) -> (Box, Box) { match byte(s, 0) { b'"' => parse_lit_str_cooked(s), b'r' => parse_lit_str_raw(s), _ => unreachable!(), } } // Clippy false positive // https://github.com/rust-lang-nursery/rust-clippy/issues/2329 #[allow(clippy::needless_continue)] fn parse_lit_str_cooked(mut s: &str) -> (Box, Box) { assert_eq!(byte(s, 0), b'"'); s = &s[1..]; let mut content = String::new(); 'outer: loop { let ch = match byte(s, 0) { b'"' => break, b'\\' => { let b = byte(s, 1); s = &s[2..]; match b { b'x' => { let (byte, rest) = backslash_x(s); s = rest; assert!(byte <= 0x7F, "invalid \\x byte in string literal"); char::from_u32(u32::from(byte)).unwrap() } b'u' => { let (ch, rest) = backslash_u(s); s = rest; ch } b'n' => '\n', b'r' => '\r', b't' => '\t', b'\\' => '\\', b'0' => '\0', b'\'' => '\'', b'"' => '"', b'\r' | b'\n' => loop { let b = byte(s, 0); match b { b' ' | b'\t' | b'\n' | b'\r' => s = &s[1..], _ => continue 'outer, } }, b => panic!( "unexpected byte '{}' after \\ character in string literal", ascii::escape_default(b), ), } } b'\r' => { assert_eq!(byte(s, 1), b'\n', "bare CR not allowed in string"); s = &s[2..]; '\n' } _ => { let ch = next_chr(s); s = &s[ch.len_utf8()..]; ch } }; content.push(ch); } assert!(s.starts_with('"')); let content = content.into_boxed_str(); let suffix = s[1..].to_owned().into_boxed_str(); (content, suffix) } fn parse_lit_str_raw(mut s: &str) -> (Box, Box) { assert_eq!(byte(s, 0), b'r'); s = &s[1..]; let mut pounds = 0; while byte(s, pounds) == b'#' { pounds += 1; } assert_eq!(byte(s, pounds), b'"'); let close = s.rfind('"').unwrap(); for end in s[close + 1..close + 1 + pounds].bytes() { assert_eq!(end, b'#'); } let content = s[pounds + 1..close].to_owned().into_boxed_str(); let suffix = s[close + 1 + pounds..].to_owned().into_boxed_str(); (content, suffix) } // Returns (content, suffix). pub(crate) fn parse_lit_byte_str(s: &str) -> (Vec, Box) { assert_eq!(byte(s, 0), b'b'); match byte(s, 1) { b'"' => parse_lit_byte_str_cooked(s), b'r' => parse_lit_byte_str_raw(s), _ => unreachable!(), } } // Clippy false positive // https://github.com/rust-lang-nursery/rust-clippy/issues/2329 #[allow(clippy::needless_continue)] fn parse_lit_byte_str_cooked(mut s: &str) -> (Vec, Box) { assert_eq!(byte(s, 0), b'b'); assert_eq!(byte(s, 1), b'"'); s = &s[2..]; // We're going to want to have slices which don't respect codepoint boundaries. let mut v = s.as_bytes(); let mut out = Vec::new(); 'outer: loop { let byte = match byte(v, 0) { b'"' => break, b'\\' => { let b = byte(v, 1); v = &v[2..]; match b { b'x' => { let (b, rest) = backslash_x(v); v = rest; b } b'n' => b'\n', b'r' => b'\r', b't' => b'\t', b'\\' => b'\\', b'0' => b'\0', b'\'' => b'\'', b'"' => b'"', b'\r' | b'\n' => loop { let byte = byte(v, 0); if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') { v = &v[1..]; } else { continue 'outer; } }, b => panic!( "unexpected byte '{}' after \\ character in byte-string literal", ascii::escape_default(b), ), } } b'\r' => { assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string"); v = &v[2..]; b'\n' } b => { v = &v[1..]; b } }; out.push(byte); } assert_eq!(byte(v, 0), b'"'); let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str(); (out, suffix) } fn parse_lit_byte_str_raw(s: &str) -> (Vec, Box) { assert_eq!(byte(s, 0), b'b'); let (value, suffix) = parse_lit_str_raw(&s[1..]); (String::from(value).into_bytes(), suffix) } // Returns (content, suffix). pub(crate) fn parse_lit_c_str(s: &str) -> (CString, Box) { assert_eq!(byte(s, 0), b'c'); match byte(s, 1) { b'"' => parse_lit_c_str_cooked(s), b'r' => parse_lit_c_str_raw(s), _ => unreachable!(), } } // Clippy false positive // https://github.com/rust-lang-nursery/rust-clippy/issues/2329 #[allow(clippy::needless_continue)] fn parse_lit_c_str_cooked(mut s: &str) -> (CString, Box) { assert_eq!(byte(s, 0), b'c'); assert_eq!(byte(s, 1), b'"'); s = &s[2..]; // We're going to want to have slices which don't respect codepoint boundaries. let mut v = s.as_bytes(); let mut out = Vec::new(); 'outer: loop { let byte = match byte(v, 0) { b'"' => break, b'\\' => { let b = byte(v, 1); v = &v[2..]; match b { b'x' => { let (b, rest) = backslash_x(v); assert!(b != 0, "\\x00 is not allowed in C-string literal"); v = rest; b } b'u' => { let (ch, rest) = backslash_u(v); assert!(ch != '\0', "\\u{{0}} is not allowed in C-string literal"); v = rest; out.extend_from_slice(ch.encode_utf8(&mut [0u8; 4]).as_bytes()); continue 'outer; } b'n' => b'\n', b'r' => b'\r', b't' => b'\t', b'\\' => b'\\', b'\'' => b'\'', b'"' => b'"', b'\r' | b'\n' => loop { let byte = byte(v, 0); if matches!(byte, b' ' | b'\t' | b'\n' | b'\r') { v = &v[1..]; } else { continue 'outer; } }, b => panic!( "unexpected byte '{}' after \\ character in byte literal", ascii::escape_default(b), ), } } b'\r' => { assert_eq!(byte(v, 1), b'\n', "bare CR not allowed in string"); v = &v[2..]; b'\n' } b => { v = &v[1..]; b } }; out.push(byte); } assert_eq!(byte(v, 0), b'"'); let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str(); (CString::new(out).unwrap(), suffix) } fn parse_lit_c_str_raw(s: &str) -> (CString, Box) { assert_eq!(byte(s, 0), b'c'); let (value, suffix) = parse_lit_str_raw(&s[1..]); (CString::new(String::from(value)).unwrap(), suffix) } // Returns (value, suffix). pub(crate) fn parse_lit_byte(s: &str) -> (u8, Box) { assert_eq!(byte(s, 0), b'b'); assert_eq!(byte(s, 1), b'\''); // We're going to want to have slices which don't respect codepoint boundaries. let mut v = s[2..].as_bytes(); let b = match byte(v, 0) { b'\\' => { let b = byte(v, 1); v = &v[2..]; match b { b'x' => { let (b, rest) = backslash_x(v); v = rest; b } b'n' => b'\n', b'r' => b'\r', b't' => b'\t', b'\\' => b'\\', b'0' => b'\0', b'\'' => b'\'', b'"' => b'"', b => panic!( "unexpected byte '{}' after \\ character in byte literal", ascii::escape_default(b), ), } } b => { v = &v[1..]; b } }; assert_eq!(byte(v, 0), b'\''); let suffix = s[s.len() - v.len() + 1..].to_owned().into_boxed_str(); (b, suffix) } // Returns (value, suffix). pub(crate) fn parse_lit_char(mut s: &str) -> (char, Box) { assert_eq!(byte(s, 0), b'\''); s = &s[1..]; let ch = match byte(s, 0) { b'\\' => { let b = byte(s, 1); s = &s[2..]; match b { b'x' => { let (byte, rest) = backslash_x(s); s = rest; assert!(byte <= 0x7F, "invalid \\x byte in character literal"); char::from_u32(u32::from(byte)).unwrap() } b'u' => { let (ch, rest) = backslash_u(s); s = rest; ch } b'n' => '\n', b'r' => '\r', b't' => '\t', b'\\' => '\\', b'0' => '\0', b'\'' => '\'', b'"' => '"', b => panic!( "unexpected byte '{}' after \\ character in character literal", ascii::escape_default(b), ), } } _ => { let ch = next_chr(s); s = &s[ch.len_utf8()..]; ch } }; assert_eq!(byte(s, 0), b'\''); let suffix = s[1..].to_owned().into_boxed_str(); (ch, suffix) } fn backslash_x(s: &S) -> (u8, &S) where S: Index, Output = S> + AsRef<[u8]> + ?Sized, { let mut ch = 0; let b0 = byte(s, 0); let b1 = byte(s, 1); ch += 0x10 * match b0 { b'0'..=b'9' => b0 - b'0', b'a'..=b'f' => 10 + (b0 - b'a'), b'A'..=b'F' => 10 + (b0 - b'A'), _ => panic!("unexpected non-hex character after \\x"), }; ch += match b1 { b'0'..=b'9' => b1 - b'0', b'a'..=b'f' => 10 + (b1 - b'a'), b'A'..=b'F' => 10 + (b1 - b'A'), _ => panic!("unexpected non-hex character after \\x"), }; (ch, &s[2..]) } fn backslash_u(mut s: &S) -> (char, &S) where S: Index, Output = S> + AsRef<[u8]> + ?Sized, { if byte(s, 0) != b'{' { panic!("{}", "expected { after \\u"); } s = &s[1..]; let mut ch = 0; let mut digits = 0; loop { let b = byte(s, 0); let digit = match b { b'0'..=b'9' => b - b'0', b'a'..=b'f' => 10 + b - b'a', b'A'..=b'F' => 10 + b - b'A', b'_' if digits > 0 => { s = &s[1..]; continue; } b'}' if digits == 0 => panic!("invalid empty unicode escape"), b'}' => break, _ => panic!("unexpected non-hex character after \\u"), }; if digits == 6 { panic!("overlong unicode escape (must have at most 6 hex digits)"); } ch *= 0x10; ch += u32::from(digit); digits += 1; s = &s[1..]; } assert!(byte(s, 0) == b'}'); s = &s[1..]; if let Some(ch) = char::from_u32(ch) { (ch, s) } else { panic!("character code {:x} is not a valid unicode character", ch); } } // Returns base 10 digits and suffix. pub(crate) fn parse_lit_int(mut s: &str) -> Option<(Box, Box)> { let negative = byte(s, 0) == b'-'; if negative { s = &s[1..]; } let base = match (byte(s, 0), byte(s, 1)) { (b'0', b'x') => { s = &s[2..]; 16 } (b'0', b'o') => { s = &s[2..]; 8 } (b'0', b'b') => { s = &s[2..]; 2 } (b'0'..=b'9', _) => 10, _ => return None, }; let mut value = BigInt::new(); let mut has_digit = false; 'outer: loop { let b = byte(s, 0); let digit = match b { b'0'..=b'9' => b - b'0', b'a'..=b'f' if base > 10 => b - b'a' + 10, b'A'..=b'F' if base > 10 => b - b'A' + 10, b'_' => { s = &s[1..]; continue; } // If looking at a floating point literal, we don't want to // consider it an integer. b'.' if base == 10 => return None, b'e' | b'E' if base == 10 => { let mut has_exp = false; for (i, b) in s[1..].bytes().enumerate() { match b { b'_' => {} b'-' | b'+' => return None, b'0'..=b'9' => has_exp = true, _ => { let suffix = &s[1 + i..]; if has_exp && crate::ident::xid_ok(suffix) { return None; } else { break 'outer; } } } } if has_exp { return None; } else { break; } } _ => break, }; if digit >= base { return None; } has_digit = true; value *= base; value += digit; s = &s[1..]; } if !has_digit { return None; } let suffix = s; if suffix.is_empty() || crate::ident::xid_ok(suffix) { let mut repr = value.to_string(); if negative { repr.insert(0, '-'); } Some((repr.into_boxed_str(), suffix.to_owned().into_boxed_str())) } else { None } } // Returns base 10 digits and suffix. pub(crate) fn parse_lit_float(input: &str) -> Option<(Box, Box)> { // Rust's floating point literals are very similar to the ones parsed by // the standard library, except that rust's literals can contain // ignorable underscores. Let's remove those underscores. let mut bytes = input.to_owned().into_bytes(); let start = (*bytes.first()? == b'-') as usize; match bytes.get(start)? { b'0'..=b'9' => {} _ => return None, } let mut read = start; let mut write = start; let mut has_dot = false; let mut has_e = false; let mut has_sign = false; let mut has_exponent = false; while read < bytes.len() { match bytes[read] { b'_' => { // Don't increase write read += 1; continue; } b'0'..=b'9' => { if has_e { has_exponent = true; } bytes[write] = bytes[read]; } b'.' => { if has_e || has_dot { return None; } has_dot = true; bytes[write] = b'.'; } b'e' | b'E' => { match bytes[read + 1..] .iter() .find(|b| **b != b'_') .unwrap_or(&b'\0') { b'-' | b'+' | b'0'..=b'9' => {} _ => break, } if has_e { if has_exponent { break; } else { return None; } } has_e = true; bytes[write] = b'e'; } b'-' | b'+' => { if has_sign || has_exponent || !has_e { return None; } has_sign = true; if bytes[read] == b'-' { bytes[write] = bytes[read]; } else { // Omit '+' read += 1; continue; } } _ => break, } read += 1; write += 1; } if has_e && !has_exponent { return None; } let mut digits = String::from_utf8(bytes).unwrap(); let suffix = digits.split_off(read); digits.truncate(write); if suffix.is_empty() || crate::ident::xid_ok(&suffix) { Some((digits.into_boxed_str(), suffix.into_boxed_str())) } else { None } } } syn/src/restriction.rs0000644000175000017500000001362514661133735016063 0ustar jamespagejamespageuse crate::path::Path; use crate::token; ast_enum! { /// The visibility level of an item: inherited or `pub` or /// `pub(restricted)`. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum Visibility { /// A public visibility level: `pub`. Public(Token![pub]), /// A visibility level restricted to some path: `pub(self)` or /// `pub(super)` or `pub(crate)` or `pub(in some::module)`. Restricted(VisRestricted), /// An inherited visibility, which usually means private. Inherited, } } ast_struct! { /// A visibility level restricted to some path: `pub(self)` or /// `pub(super)` or `pub(crate)` or `pub(in some::module)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct VisRestricted { pub pub_token: Token![pub], pub paren_token: token::Paren, pub in_token: Option, pub path: Box, } } ast_enum! { /// Unused, but reserved for RFC 3323 restrictions. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum FieldMutability { None, // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html // // FieldMutability::Restricted(MutRestricted) // // pub struct MutRestricted { // pub mut_token: Token![mut], // pub paren_token: token::Paren, // pub in_token: Option, // pub path: Box, // } } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::error::Result; use crate::ext::IdentExt as _; use crate::ident::Ident; use crate::parse::discouraged::Speculative as _; use crate::parse::{Parse, ParseStream}; use crate::path::Path; use crate::restriction::{VisRestricted, Visibility}; use crate::token; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Visibility { fn parse(input: ParseStream) -> Result { // Recognize an empty None-delimited group, as produced by a $:vis // matcher that matched no tokens. if input.peek(token::Group) { let ahead = input.fork(); let group = crate::group::parse_group(&ahead)?; if group.content.is_empty() { input.advance_to(&ahead); return Ok(Visibility::Inherited); } } if input.peek(Token![pub]) { Self::parse_pub(input) } else { Ok(Visibility::Inherited) } } } impl Visibility { fn parse_pub(input: ParseStream) -> Result { let pub_token = input.parse::()?; if input.peek(token::Paren) { let ahead = input.fork(); let content; let paren_token = parenthesized!(content in ahead); if content.peek(Token![crate]) || content.peek(Token![self]) || content.peek(Token![super]) { let path = content.call(Ident::parse_any)?; // Ensure there are no additional tokens within `content`. // Without explicitly checking, we may misinterpret a tuple // field as a restricted visibility, causing a parse error. // e.g. `pub (crate::A, crate::B)` (Issue #720). if content.is_empty() { input.advance_to(&ahead); return Ok(Visibility::Restricted(VisRestricted { pub_token, paren_token, in_token: None, path: Box::new(Path::from(path)), })); } } else if content.peek(Token![in]) { let in_token: Token![in] = content.parse()?; let path = content.call(Path::parse_mod_style)?; input.advance_to(&ahead); return Ok(Visibility::Restricted(VisRestricted { pub_token, paren_token, in_token: Some(in_token), path: Box::new(path), })); } } Ok(Visibility::Public(pub_token)) } #[cfg(feature = "full")] pub(crate) fn is_some(&self) -> bool { match self { Visibility::Inherited => false, _ => true, } } } } #[cfg(feature = "printing")] mod printing { use crate::restriction::{VisRestricted, Visibility}; use proc_macro2::TokenStream; use quote::ToTokens; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Visibility { fn to_tokens(&self, tokens: &mut TokenStream) { match self { Visibility::Public(pub_token) => pub_token.to_tokens(tokens), Visibility::Restricted(vis_restricted) => vis_restricted.to_tokens(tokens), Visibility::Inherited => {} } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for VisRestricted { fn to_tokens(&self, tokens: &mut TokenStream) { self.pub_token.to_tokens(tokens); self.paren_token.surround(tokens, |tokens| { // TODO: If we have a path which is not "self" or "super" or // "crate", automatically add the "in" token. self.in_token.to_tokens(tokens); self.path.to_tokens(tokens); }); } } } syn/src/precedence.rs0000644000175000017500000001051214661133735015603 0ustar jamespagejamespage#[cfg(feature = "printing")] use crate::expr::Expr; use crate::op::BinOp; #[cfg(all(feature = "printing", feature = "full"))] use crate::ty::ReturnType; use std::cmp::Ordering; // Reference: https://doc.rust-lang.org/reference/expressions.html#expression-precedence pub(crate) enum Precedence { // return, break, closures Any, // = += -= *= /= %= &= |= ^= <<= >>= Assign, // .. ..= Range, // || Or, // && And, // == != < > <= >= Compare, // | BitOr, // ^ BitXor, // & BitAnd, // << >> Shift, // + - Sum, // * / % Product, // as Cast, // unary - * ! & &mut #[cfg(feature = "printing")] Prefix, // paths, loops, function calls, array indexing, field expressions, method calls #[cfg(feature = "printing")] Unambiguous, } impl Precedence { pub(crate) fn of_binop(op: &BinOp) -> Self { match op { BinOp::Add(_) | BinOp::Sub(_) => Precedence::Sum, BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Product, BinOp::And(_) => Precedence::And, BinOp::Or(_) => Precedence::Or, BinOp::BitXor(_) => Precedence::BitXor, BinOp::BitAnd(_) => Precedence::BitAnd, BinOp::BitOr(_) => Precedence::BitOr, BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift, BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Le(_) | BinOp::Ne(_) | BinOp::Ge(_) | BinOp::Gt(_) => Precedence::Compare, BinOp::AddAssign(_) | BinOp::SubAssign(_) | BinOp::MulAssign(_) | BinOp::DivAssign(_) | BinOp::RemAssign(_) | BinOp::BitXorAssign(_) | BinOp::BitAndAssign(_) | BinOp::BitOrAssign(_) | BinOp::ShlAssign(_) | BinOp::ShrAssign(_) => Precedence::Assign, } } #[cfg(feature = "printing")] pub(crate) fn of(e: &Expr) -> Self { match e { #[cfg(feature = "full")] Expr::Closure(e) => match e.output { ReturnType::Default => Precedence::Any, ReturnType::Type(..) => Precedence::Unambiguous, }, Expr::Break(_) | Expr::Return(_) | Expr::Yield(_) => Precedence::Any, Expr::Assign(_) => Precedence::Assign, Expr::Range(_) => Precedence::Range, Expr::Binary(e) => Precedence::of_binop(&e.op), Expr::Cast(_) => Precedence::Cast, Expr::Let(_) | Expr::Reference(_) | Expr::Unary(_) => Precedence::Prefix, Expr::Array(_) | Expr::Async(_) | Expr::Await(_) | Expr::Block(_) | Expr::Call(_) | Expr::Const(_) | Expr::Continue(_) | Expr::Field(_) | Expr::ForLoop(_) | Expr::Group(_) | Expr::If(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Repeat(_) | Expr::Struct(_) | Expr::Try(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::While(_) => Precedence::Unambiguous, #[cfg(not(feature = "full"))] Expr::Closure(_) => unreachable!(), } } #[cfg(feature = "printing")] pub(crate) fn of_rhs(e: &Expr) -> Self { match e { Expr::Break(_) | Expr::Closure(_) | Expr::Return(_) | Expr::Yield(_) => { Precedence::Prefix } #[cfg(feature = "full")] Expr::Range(e) if e.start.is_none() => Precedence::Prefix, _ => Precedence::of(e), } } } impl Copy for Precedence {} impl Clone for Precedence { fn clone(&self) -> Self { *self } } impl PartialEq for Precedence { fn eq(&self, other: &Self) -> bool { *self as u8 == *other as u8 } } impl PartialOrd for Precedence { fn partial_cmp(&self, other: &Self) -> Option { let this = *self as u8; let other = *other as u8; Some(this.cmp(&other)) } } syn/src/op.rs0000644000175000017500000002022114661133735014122 0ustar jamespagejamespageast_enum! { /// A binary operator: `+`, `+=`, `&`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum BinOp { /// The `+` operator (addition) Add(Token![+]), /// The `-` operator (subtraction) Sub(Token![-]), /// The `*` operator (multiplication) Mul(Token![*]), /// The `/` operator (division) Div(Token![/]), /// The `%` operator (modulus) Rem(Token![%]), /// The `&&` operator (logical and) And(Token![&&]), /// The `||` operator (logical or) Or(Token![||]), /// The `^` operator (bitwise xor) BitXor(Token![^]), /// The `&` operator (bitwise and) BitAnd(Token![&]), /// The `|` operator (bitwise or) BitOr(Token![|]), /// The `<<` operator (shift left) Shl(Token![<<]), /// The `>>` operator (shift right) Shr(Token![>>]), /// The `==` operator (equality) Eq(Token![==]), /// The `<` operator (less than) Lt(Token![<]), /// The `<=` operator (less than or equal to) Le(Token![<=]), /// The `!=` operator (not equal to) Ne(Token![!=]), /// The `>=` operator (greater than or equal to) Ge(Token![>=]), /// The `>` operator (greater than) Gt(Token![>]), /// The `+=` operator AddAssign(Token![+=]), /// The `-=` operator SubAssign(Token![-=]), /// The `*=` operator MulAssign(Token![*=]), /// The `/=` operator DivAssign(Token![/=]), /// The `%=` operator RemAssign(Token![%=]), /// The `^=` operator BitXorAssign(Token![^=]), /// The `&=` operator BitAndAssign(Token![&=]), /// The `|=` operator BitOrAssign(Token![|=]), /// The `<<=` operator ShlAssign(Token![<<=]), /// The `>>=` operator ShrAssign(Token![>>=]), } } ast_enum! { /// A unary operator: `*`, `!`, `-`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum UnOp { /// The `*` operator for dereferencing Deref(Token![*]), /// The `!` operator for logical inversion Not(Token![!]), /// The `-` operator for negation Neg(Token![-]), } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::error::Result; use crate::op::{BinOp, UnOp}; use crate::parse::{Parse, ParseStream}; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for BinOp { fn parse(input: ParseStream) -> Result { if input.peek(Token![+=]) { input.parse().map(BinOp::AddAssign) } else if input.peek(Token![-=]) { input.parse().map(BinOp::SubAssign) } else if input.peek(Token![*=]) { input.parse().map(BinOp::MulAssign) } else if input.peek(Token![/=]) { input.parse().map(BinOp::DivAssign) } else if input.peek(Token![%=]) { input.parse().map(BinOp::RemAssign) } else if input.peek(Token![^=]) { input.parse().map(BinOp::BitXorAssign) } else if input.peek(Token![&=]) { input.parse().map(BinOp::BitAndAssign) } else if input.peek(Token![|=]) { input.parse().map(BinOp::BitOrAssign) } else if input.peek(Token![<<=]) { input.parse().map(BinOp::ShlAssign) } else if input.peek(Token![>>=]) { input.parse().map(BinOp::ShrAssign) } else if input.peek(Token![&&]) { input.parse().map(BinOp::And) } else if input.peek(Token![||]) { input.parse().map(BinOp::Or) } else if input.peek(Token![<<]) { input.parse().map(BinOp::Shl) } else if input.peek(Token![>>]) { input.parse().map(BinOp::Shr) } else if input.peek(Token![==]) { input.parse().map(BinOp::Eq) } else if input.peek(Token![<=]) { input.parse().map(BinOp::Le) } else if input.peek(Token![!=]) { input.parse().map(BinOp::Ne) } else if input.peek(Token![>=]) { input.parse().map(BinOp::Ge) } else if input.peek(Token![+]) { input.parse().map(BinOp::Add) } else if input.peek(Token![-]) { input.parse().map(BinOp::Sub) } else if input.peek(Token![*]) { input.parse().map(BinOp::Mul) } else if input.peek(Token![/]) { input.parse().map(BinOp::Div) } else if input.peek(Token![%]) { input.parse().map(BinOp::Rem) } else if input.peek(Token![^]) { input.parse().map(BinOp::BitXor) } else if input.peek(Token![&]) { input.parse().map(BinOp::BitAnd) } else if input.peek(Token![|]) { input.parse().map(BinOp::BitOr) } else if input.peek(Token![<]) { input.parse().map(BinOp::Lt) } else if input.peek(Token![>]) { input.parse().map(BinOp::Gt) } else { Err(input.error("expected binary operator")) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for UnOp { fn parse(input: ParseStream) -> Result { let lookahead = input.lookahead1(); if lookahead.peek(Token![*]) { input.parse().map(UnOp::Deref) } else if lookahead.peek(Token![!]) { input.parse().map(UnOp::Not) } else if lookahead.peek(Token![-]) { input.parse().map(UnOp::Neg) } else { Err(lookahead.error()) } } } } #[cfg(feature = "printing")] mod printing { use crate::op::{BinOp, UnOp}; use proc_macro2::TokenStream; use quote::ToTokens; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BinOp { fn to_tokens(&self, tokens: &mut TokenStream) { match self { BinOp::Add(t) => t.to_tokens(tokens), BinOp::Sub(t) => t.to_tokens(tokens), BinOp::Mul(t) => t.to_tokens(tokens), BinOp::Div(t) => t.to_tokens(tokens), BinOp::Rem(t) => t.to_tokens(tokens), BinOp::And(t) => t.to_tokens(tokens), BinOp::Or(t) => t.to_tokens(tokens), BinOp::BitXor(t) => t.to_tokens(tokens), BinOp::BitAnd(t) => t.to_tokens(tokens), BinOp::BitOr(t) => t.to_tokens(tokens), BinOp::Shl(t) => t.to_tokens(tokens), BinOp::Shr(t) => t.to_tokens(tokens), BinOp::Eq(t) => t.to_tokens(tokens), BinOp::Lt(t) => t.to_tokens(tokens), BinOp::Le(t) => t.to_tokens(tokens), BinOp::Ne(t) => t.to_tokens(tokens), BinOp::Ge(t) => t.to_tokens(tokens), BinOp::Gt(t) => t.to_tokens(tokens), BinOp::AddAssign(t) => t.to_tokens(tokens), BinOp::SubAssign(t) => t.to_tokens(tokens), BinOp::MulAssign(t) => t.to_tokens(tokens), BinOp::DivAssign(t) => t.to_tokens(tokens), BinOp::RemAssign(t) => t.to_tokens(tokens), BinOp::BitXorAssign(t) => t.to_tokens(tokens), BinOp::BitAndAssign(t) => t.to_tokens(tokens), BinOp::BitOrAssign(t) => t.to_tokens(tokens), BinOp::ShlAssign(t) => t.to_tokens(tokens), BinOp::ShrAssign(t) => t.to_tokens(tokens), } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UnOp { fn to_tokens(&self, tokens: &mut TokenStream) { match self { UnOp::Deref(t) => t.to_tokens(tokens), UnOp::Not(t) => t.to_tokens(tokens), UnOp::Neg(t) => t.to_tokens(tokens), } } } } syn/src/error.rs0000644000175000017500000003343114661133735014644 0ustar jamespagejamespage#[cfg(feature = "parsing")] use crate::buffer::Cursor; use crate::thread::ThreadBound; use proc_macro2::{ Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree, }; #[cfg(feature = "printing")] use quote::ToTokens; use std::fmt::{self, Debug, Display}; use std::slice; use std::vec; /// The result of a Syn parser. pub type Result = std::result::Result; /// Error returned when a Syn parser cannot parse the input tokens. /// /// # Error reporting in proc macros /// /// The correct way to report errors back to the compiler from a procedural /// macro is by emitting an appropriately spanned invocation of /// [`compile_error!`] in the generated code. This produces a better diagnostic /// message than simply panicking the macro. /// /// [`compile_error!`]: std::compile_error! /// /// When parsing macro input, the [`parse_macro_input!`] macro handles the /// conversion to `compile_error!` automatically. /// /// [`parse_macro_input!`]: crate::parse_macro_input! /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use syn::parse::{Parse, ParseStream, Result}; /// use syn::{parse_macro_input, ItemFn}; /// /// # const IGNORE: &str = stringify! { /// #[proc_macro_attribute] /// # }; /// pub fn my_attr(args: TokenStream, input: TokenStream) -> TokenStream { /// let args = parse_macro_input!(args as MyAttrArgs); /// let input = parse_macro_input!(input as ItemFn); /// /// /* ... */ /// # TokenStream::new() /// } /// /// struct MyAttrArgs { /// # _k: [(); { stringify! { /// ... /// # }; 0 }] /// } /// /// impl Parse for MyAttrArgs { /// fn parse(input: ParseStream) -> Result { /// # stringify! { /// ... /// # }; /// # unimplemented!() /// } /// } /// ``` /// /// For errors that arise later than the initial parsing stage, the /// [`.to_compile_error()`] or [`.into_compile_error()`] methods can be used to /// perform an explicit conversion to `compile_error!`. /// /// [`.to_compile_error()`]: Error::to_compile_error /// [`.into_compile_error()`]: Error::into_compile_error /// /// ``` /// # extern crate proc_macro; /// # /// # use proc_macro::TokenStream; /// # use syn::{parse_macro_input, DeriveInput}; /// # /// # const IGNORE: &str = stringify! { /// #[proc_macro_derive(MyDerive)] /// # }; /// pub fn my_derive(input: TokenStream) -> TokenStream { /// let input = parse_macro_input!(input as DeriveInput); /// /// // fn(DeriveInput) -> syn::Result /// expand::my_derive(input) /// .unwrap_or_else(syn::Error::into_compile_error) /// .into() /// } /// # /// # mod expand { /// # use proc_macro2::TokenStream; /// # use syn::{DeriveInput, Result}; /// # /// # pub fn my_derive(input: DeriveInput) -> Result { /// # unimplemented!() /// # } /// # } /// ``` pub struct Error { messages: Vec, } struct ErrorMessage { // Span is implemented as an index into a thread-local interner to keep the // size small. It is not safe to access from a different thread. We want // errors to be Send and Sync to play nicely with ecosystem crates for error // handling, so pin the span we're given to its original thread and assume // it is Span::call_site if accessed from any other thread. span: ThreadBound, message: String, } // Cannot use std::ops::Range because that does not implement Copy, // whereas ThreadBound requires a Copy impl as a way to ensure no Drop impls // are involved. struct SpanRange { start: Span, end: Span, } #[cfg(test)] struct _Test where Error: Send + Sync; impl Error { /// Usually the [`ParseStream::error`] method will be used instead, which /// automatically uses the correct span from the current position of the /// parse stream. /// /// Use `Error::new` when the error needs to be triggered on some span other /// than where the parse stream is currently positioned. /// /// [`ParseStream::error`]: crate::parse::ParseBuffer::error /// /// # Example /// /// ``` /// use syn::{Error, Ident, LitStr, Result, Token}; /// use syn::parse::ParseStream; /// /// // Parses input that looks like `name = "string"` where the key must be /// // the identifier `name` and the value may be any string literal. /// // Returns the string literal. /// fn parse_name(input: ParseStream) -> Result { /// let name_token: Ident = input.parse()?; /// if name_token != "name" { /// // Trigger an error not on the current position of the stream, /// // but on the position of the unexpected identifier. /// return Err(Error::new(name_token.span(), "expected `name`")); /// } /// input.parse::()?; /// let s: LitStr = input.parse()?; /// Ok(s) /// } /// ``` pub fn new(span: Span, message: T) -> Self { return new(span, message.to_string()); fn new(span: Span, message: String) -> Error { Error { messages: vec![ErrorMessage { span: ThreadBound::new(SpanRange { start: span, end: span, }), message, }], } } } /// Creates an error with the specified message spanning the given syntax /// tree node. /// /// Unlike the `Error::new` constructor, this constructor takes an argument /// `tokens` which is a syntax tree node. This allows the resulting `Error` /// to attempt to span all tokens inside of `tokens`. While you would /// typically be able to use the `Spanned` trait with the above `Error::new` /// constructor, implementation limitations today mean that /// `Error::new_spanned` may provide a higher-quality error message on /// stable Rust. /// /// When in doubt it's recommended to stick to `Error::new` (or /// `ParseStream::error`)! #[cfg(feature = "printing")] #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] pub fn new_spanned(tokens: T, message: U) -> Self { return new_spanned(tokens.into_token_stream(), message.to_string()); fn new_spanned(tokens: TokenStream, message: String) -> Error { let mut iter = tokens.into_iter(); let start = iter.next().map_or_else(Span::call_site, |t| t.span()); let end = iter.last().map_or(start, |t| t.span()); Error { messages: vec![ErrorMessage { span: ThreadBound::new(SpanRange { start, end }), message, }], } } } /// The source location of the error. /// /// Spans are not thread-safe so this function returns `Span::call_site()` /// if called from a different thread than the one on which the `Error` was /// originally created. pub fn span(&self) -> Span { let SpanRange { start, end } = match self.messages[0].span.get() { Some(span) => *span, None => return Span::call_site(), }; start.join(end).unwrap_or(start) } /// Render the error as an invocation of [`compile_error!`]. /// /// The [`parse_macro_input!`] macro provides a convenient way to invoke /// this method correctly in a procedural macro. /// /// [`compile_error!`]: std::compile_error! /// [`parse_macro_input!`]: crate::parse_macro_input! pub fn to_compile_error(&self) -> TokenStream { self.messages .iter() .map(ErrorMessage::to_compile_error) .collect() } /// Render the error as an invocation of [`compile_error!`]. /// /// [`compile_error!`]: std::compile_error! /// /// # Example /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use syn::{parse_macro_input, DeriveInput, Error}; /// /// # const _: &str = stringify! { /// #[proc_macro_derive(MyTrait)] /// # }; /// pub fn derive_my_trait(input: TokenStream) -> TokenStream { /// let input = parse_macro_input!(input as DeriveInput); /// my_trait::expand(input) /// .unwrap_or_else(Error::into_compile_error) /// .into() /// } /// /// mod my_trait { /// use proc_macro2::TokenStream; /// use syn::{DeriveInput, Result}; /// /// pub(crate) fn expand(input: DeriveInput) -> Result { /// /* ... */ /// # unimplemented!() /// } /// } /// ``` pub fn into_compile_error(self) -> TokenStream { self.to_compile_error() } /// Add another error message to self such that when `to_compile_error()` is /// called, both errors will be emitted together. pub fn combine(&mut self, another: Error) { self.messages.extend(another.messages); } } impl ErrorMessage { fn to_compile_error(&self) -> TokenStream { let (start, end) = match self.span.get() { Some(range) => (range.start, range.end), None => (Span::call_site(), Span::call_site()), }; // ::core::compile_error!($message) TokenStream::from_iter([ TokenTree::Punct({ let mut punct = Punct::new(':', Spacing::Joint); punct.set_span(start); punct }), TokenTree::Punct({ let mut punct = Punct::new(':', Spacing::Alone); punct.set_span(start); punct }), TokenTree::Ident(Ident::new("core", start)), TokenTree::Punct({ let mut punct = Punct::new(':', Spacing::Joint); punct.set_span(start); punct }), TokenTree::Punct({ let mut punct = Punct::new(':', Spacing::Alone); punct.set_span(start); punct }), TokenTree::Ident(Ident::new("compile_error", start)), TokenTree::Punct({ let mut punct = Punct::new('!', Spacing::Alone); punct.set_span(start); punct }), TokenTree::Group({ let mut group = Group::new(Delimiter::Brace, { TokenStream::from_iter([TokenTree::Literal({ let mut string = Literal::string(&self.message); string.set_span(end); string })]) }); group.set_span(end); group }), ]) } } #[cfg(feature = "parsing")] pub(crate) fn new_at(scope: Span, cursor: Cursor, message: T) -> Error { if cursor.eof() { Error::new(scope, format!("unexpected end of input, {}", message)) } else { let span = crate::buffer::open_span_of_group(cursor); Error::new(span, message) } } #[cfg(all(feature = "parsing", any(feature = "full", feature = "derive")))] pub(crate) fn new2(start: Span, end: Span, message: T) -> Error { return new2(start, end, message.to_string()); fn new2(start: Span, end: Span, message: String) -> Error { Error { messages: vec![ErrorMessage { span: ThreadBound::new(SpanRange { start, end }), message, }], } } } impl Debug for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.messages.len() == 1 { formatter .debug_tuple("Error") .field(&self.messages[0]) .finish() } else { formatter .debug_tuple("Error") .field(&self.messages) .finish() } } } impl Debug for ErrorMessage { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { Debug::fmt(&self.message, formatter) } } impl Display for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(&self.messages[0].message) } } impl Clone for Error { fn clone(&self) -> Self { Error { messages: self.messages.clone(), } } } impl Clone for ErrorMessage { fn clone(&self) -> Self { ErrorMessage { span: self.span, message: self.message.clone(), } } } impl Clone for SpanRange { fn clone(&self) -> Self { *self } } impl Copy for SpanRange {} impl std::error::Error for Error {} impl From for Error { fn from(err: LexError) -> Self { Error::new(err.span(), err) } } impl IntoIterator for Error { type Item = Error; type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter { messages: self.messages.into_iter(), } } } pub struct IntoIter { messages: vec::IntoIter, } impl Iterator for IntoIter { type Item = Error; fn next(&mut self) -> Option { Some(Error { messages: vec![self.messages.next()?], }) } } impl<'a> IntoIterator for &'a Error { type Item = Error; type IntoIter = Iter<'a>; fn into_iter(self) -> Self::IntoIter { Iter { messages: self.messages.iter(), } } } pub struct Iter<'a> { messages: slice::Iter<'a, ErrorMessage>, } impl<'a> Iterator for Iter<'a> { type Item = Error; fn next(&mut self) -> Option { Some(Error { messages: vec![self.messages.next()?.clone()], }) } } impl Extend for Error { fn extend>(&mut self, iter: T) { for err in iter { self.combine(err); } } } syn/src/whitespace.rs0000644000175000017500000000406714661133735015652 0ustar jamespagejamespagepub(crate) fn skip(mut s: &str) -> &str { 'skip: while !s.is_empty() { let byte = s.as_bytes()[0]; if byte == b'/' { if s.starts_with("//") && (!s.starts_with("///") || s.starts_with("////")) && !s.starts_with("//!") { if let Some(i) = s.find('\n') { s = &s[i + 1..]; continue; } else { return ""; } } else if s.starts_with("/**/") { s = &s[4..]; continue; } else if s.starts_with("/*") && (!s.starts_with("/**") || s.starts_with("/***")) && !s.starts_with("/*!") { let mut depth = 0; let bytes = s.as_bytes(); let mut i = 0; let upper = bytes.len() - 1; while i < upper { if bytes[i] == b'/' && bytes[i + 1] == b'*' { depth += 1; i += 1; // eat '*' } else if bytes[i] == b'*' && bytes[i + 1] == b'/' { depth -= 1; if depth == 0 { s = &s[i + 2..]; continue 'skip; } i += 1; // eat '/' } i += 1; } return s; } } match byte { b' ' | 0x09..=0x0D => { s = &s[1..]; continue; } b if b <= 0x7F => {} _ => { let ch = s.chars().next().unwrap(); if is_whitespace(ch) { s = &s[ch.len_utf8()..]; continue; } } } return s; } s } fn is_whitespace(ch: char) -> bool { // Rust treats left-to-right mark and right-to-left mark as whitespace ch.is_whitespace() || ch == '\u{200e}' || ch == '\u{200f}' } syn/src/thread.rs0000644000175000017500000000356014661133735014762 0ustar jamespagejamespageuse std::fmt::{self, Debug}; use std::thread::{self, ThreadId}; /// ThreadBound is a Sync-maker and Send-maker that allows accessing a value /// of type T only from the original thread on which the ThreadBound was /// constructed. pub(crate) struct ThreadBound { value: T, thread_id: ThreadId, } unsafe impl Sync for ThreadBound {} // Send bound requires Copy, as otherwise Drop could run in the wrong place. // // Today Copy and Drop are mutually exclusive so `T: Copy` implies `T: !Drop`. // This impl needs to be revisited if that restriction is relaxed in the future. unsafe impl Send for ThreadBound {} impl ThreadBound { pub(crate) fn new(value: T) -> Self { ThreadBound { value, thread_id: thread::current().id(), } } pub(crate) fn get(&self) -> Option<&T> { if thread::current().id() == self.thread_id { Some(&self.value) } else { None } } } impl Debug for ThreadBound { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { match self.get() { Some(value) => Debug::fmt(value, formatter), None => formatter.write_str("unknown"), } } } // Copy the bytes of T, even if the currently running thread is the "wrong" // thread. This is fine as long as the original thread is not simultaneously // mutating this value via interior mutability, which would be a data race. // // Currently `T: Copy` is sufficient to guarantee that T contains no interior // mutability, because _all_ interior mutability in Rust is built on // std::cell::UnsafeCell, which has no Copy impl. This impl needs to be // revisited if that restriction is relaxed in the future. impl Copy for ThreadBound {} impl Clone for ThreadBound { fn clone(&self) -> Self { *self } } syn/src/meta.rs0000644000175000017500000003347114661133735014445 0ustar jamespagejamespage//! Facility for interpreting structured content inside of an `Attribute`. use crate::error::{Error, Result}; use crate::ext::IdentExt as _; use crate::lit::Lit; use crate::parse::{ParseStream, Parser}; use crate::path::{Path, PathSegment}; use crate::punctuated::Punctuated; use proc_macro2::Ident; use std::fmt::Display; /// Make a parser that is usable with `parse_macro_input!` in a /// `#[proc_macro_attribute]` macro. /// /// *Warning:* When parsing attribute args **other than** the /// `proc_macro::TokenStream` input of a `proc_macro_attribute`, you do **not** /// need this function. In several cases your callers will get worse error /// messages if you use this function, because the surrounding delimiter's span /// is concealed from attribute macros by rustc. Use /// [`Attribute::parse_nested_meta`] instead. /// /// [`Attribute::parse_nested_meta`]: crate::Attribute::parse_nested_meta /// /// # Example /// /// This example implements an attribute macro whose invocations look like this: /// /// ``` /// # const IGNORE: &str = stringify! { /// #[tea(kind = "EarlGrey", hot)] /// struct Picard {...} /// # }; /// ``` /// /// The "parameters" supported by the attribute are: /// /// - `kind = "..."` /// - `hot` /// - `with(sugar, milk, ...)`, a comma-separated list of ingredients /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use syn::{parse_macro_input, LitStr, Path}; /// /// # const IGNORE: &str = stringify! { /// #[proc_macro_attribute] /// # }; /// pub fn tea(args: TokenStream, input: TokenStream) -> TokenStream { /// let mut kind: Option = None; /// let mut hot: bool = false; /// let mut with: Vec = Vec::new(); /// let tea_parser = syn::meta::parser(|meta| { /// if meta.path.is_ident("kind") { /// kind = Some(meta.value()?.parse()?); /// Ok(()) /// } else if meta.path.is_ident("hot") { /// hot = true; /// Ok(()) /// } else if meta.path.is_ident("with") { /// meta.parse_nested_meta(|meta| { /// with.push(meta.path); /// Ok(()) /// }) /// } else { /// Err(meta.error("unsupported tea property")) /// } /// }); /// /// parse_macro_input!(args with tea_parser); /// eprintln!("kind={kind:?} hot={hot} with={with:?}"); /// /// /* ... */ /// # TokenStream::new() /// } /// ``` /// /// The `syn::meta` library will take care of dealing with the commas including /// trailing commas, and producing sensible error messages on unexpected input. /// /// ```console /// error: expected `,` /// --> src/main.rs:3:37 /// | /// 3 | #[tea(kind = "EarlGrey", with(sugar = "lol", milk))] /// | ^ /// ``` /// /// # Example /// /// Same as above but we factor out most of the logic into a separate function. /// /// ``` /// # extern crate proc_macro; /// # /// use proc_macro::TokenStream; /// use syn::meta::ParseNestedMeta; /// use syn::parse::{Parser, Result}; /// use syn::{parse_macro_input, LitStr, Path}; /// /// # const IGNORE: &str = stringify! { /// #[proc_macro_attribute] /// # }; /// pub fn tea(args: TokenStream, input: TokenStream) -> TokenStream { /// let mut attrs = TeaAttributes::default(); /// let tea_parser = syn::meta::parser(|meta| attrs.parse(meta)); /// parse_macro_input!(args with tea_parser); /// /// /* ... */ /// # TokenStream::new() /// } /// /// #[derive(Default)] /// struct TeaAttributes { /// kind: Option, /// hot: bool, /// with: Vec, /// } /// /// impl TeaAttributes { /// fn parse(&mut self, meta: ParseNestedMeta) -> Result<()> { /// if meta.path.is_ident("kind") { /// self.kind = Some(meta.value()?.parse()?); /// Ok(()) /// } else /* just like in last example */ /// # { unimplemented!() } /// /// } /// } /// ``` pub fn parser(logic: impl FnMut(ParseNestedMeta) -> Result<()>) -> impl Parser { |input: ParseStream| { if input.is_empty() { Ok(()) } else { parse_nested_meta(input, logic) } } } /// Context for parsing a single property in the conventional syntax for /// structured attributes. /// /// # Examples /// /// Refer to usage examples on the following two entry-points: /// /// - [`Attribute::parse_nested_meta`] if you have an entire `Attribute` to /// parse. Always use this if possible. Generally this is able to produce /// better error messages because `Attribute` holds span information for all /// of the delimiters therein. /// /// - [`syn::meta::parser`] if you are implementing a `proc_macro_attribute` /// macro and parsing the arguments to the attribute macro, i.e. the ones /// written in the same attribute that dispatched the macro invocation. Rustc /// does not pass span information for the surrounding delimiters into the /// attribute macro invocation in this situation, so error messages might be /// less precise. /// /// [`Attribute::parse_nested_meta`]: crate::Attribute::parse_nested_meta /// [`syn::meta::parser`]: crate::meta::parser #[non_exhaustive] pub struct ParseNestedMeta<'a> { pub path: Path, pub input: ParseStream<'a>, } impl<'a> ParseNestedMeta<'a> { /// Used when parsing `key = "value"` syntax. /// /// All it does is advance `meta.input` past the `=` sign in the input. You /// could accomplish the same effect by writing /// `meta.parse::()?`, so at most it is a minor convenience to /// use `meta.value()?`. /// /// # Example /// /// ``` /// use syn::{parse_quote, Attribute, LitStr}; /// /// let attr: Attribute = parse_quote! { /// #[tea(kind = "EarlGrey")] /// }; /// // conceptually: /// if attr.path().is_ident("tea") { // this parses the `tea` /// attr.parse_nested_meta(|meta| { // this parses the `(` /// if meta.path.is_ident("kind") { // this parses the `kind` /// let value = meta.value()?; // this parses the `=` /// let s: LitStr = value.parse()?; // this parses `"EarlGrey"` /// if s.value() == "EarlGrey" { /// // ... /// } /// Ok(()) /// } else { /// Err(meta.error("unsupported attribute")) /// } /// })?; /// } /// # anyhow::Ok(()) /// ``` pub fn value(&self) -> Result> { self.input.parse::()?; Ok(self.input) } /// Used when parsing `list(...)` syntax **if** the content inside the /// nested parentheses is also expected to conform to Rust's structured /// attribute convention. /// /// # Example /// /// ``` /// use syn::{parse_quote, Attribute}; /// /// let attr: Attribute = parse_quote! { /// #[tea(with(sugar, milk))] /// }; /// /// if attr.path().is_ident("tea") { /// attr.parse_nested_meta(|meta| { /// if meta.path.is_ident("with") { /// meta.parse_nested_meta(|meta| { // <--- /// if meta.path.is_ident("sugar") { /// // Here we can go even deeper if needed. /// Ok(()) /// } else if meta.path.is_ident("milk") { /// Ok(()) /// } else { /// Err(meta.error("unsupported ingredient")) /// } /// }) /// } else { /// Err(meta.error("unsupported tea property")) /// } /// })?; /// } /// # anyhow::Ok(()) /// ``` /// /// # Counterexample /// /// If you don't need `parse_nested_meta`'s help in parsing the content /// written within the nested parentheses, keep in mind that you can always /// just parse it yourself from the exposed ParseStream. Rust syntax permits /// arbitrary tokens within those parentheses so for the crazier stuff, /// `parse_nested_meta` is not what you want. /// /// ``` /// use syn::{parenthesized, parse_quote, Attribute, LitInt}; /// /// let attr: Attribute = parse_quote! { /// #[repr(align(32))] /// }; /// /// let mut align: Option = None; /// if attr.path().is_ident("repr") { /// attr.parse_nested_meta(|meta| { /// if meta.path.is_ident("align") { /// let content; /// parenthesized!(content in meta.input); /// align = Some(content.parse()?); /// Ok(()) /// } else { /// Err(meta.error("unsupported repr")) /// } /// })?; /// } /// # anyhow::Ok(()) /// ``` pub fn parse_nested_meta( &self, logic: impl FnMut(ParseNestedMeta) -> Result<()>, ) -> Result<()> { let content; parenthesized!(content in self.input); parse_nested_meta(&content, logic) } /// Report that the attribute's content did not conform to expectations. /// /// The span of the resulting error will cover `meta.path` *and* everything /// that has been parsed so far since it. /// /// There are 2 ways you might call this. First, if `meta.path` is not /// something you recognize: /// /// ``` /// # use syn::Attribute; /// # /// # fn example(attr: &Attribute) -> syn::Result<()> { /// attr.parse_nested_meta(|meta| { /// if meta.path.is_ident("kind") { /// // ... /// Ok(()) /// } else { /// Err(meta.error("unsupported tea property")) /// } /// })?; /// # Ok(()) /// # } /// ``` /// /// In this case, it behaves exactly like /// `syn::Error::new_spanned(&meta.path, "message...")`. /// /// ```console /// error: unsupported tea property /// --> src/main.rs:3:26 /// | /// 3 | #[tea(kind = "EarlGrey", wat = "foo")] /// | ^^^ /// ``` /// /// More usefully, the second place is if you've already parsed a value but /// have decided not to accept the value: /// /// ``` /// # use syn::Attribute; /// # /// # fn example(attr: &Attribute) -> syn::Result<()> { /// use syn::Expr; /// /// attr.parse_nested_meta(|meta| { /// if meta.path.is_ident("kind") { /// let expr: Expr = meta.value()?.parse()?; /// match expr { /// Expr::Lit(expr) => /* ... */ /// # unimplemented!(), /// Expr::Path(expr) => /* ... */ /// # unimplemented!(), /// Expr::Macro(expr) => /* ... */ /// # unimplemented!(), /// _ => Err(meta.error("tea kind must be a string literal, path, or macro")), /// } /// } else /* as above */ /// # { unimplemented!() } /// /// })?; /// # Ok(()) /// # } /// ``` /// /// ```console /// error: tea kind must be a string literal, path, or macro /// --> src/main.rs:3:7 /// | /// 3 | #[tea(kind = async { replicator.await })] /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /// ``` /// /// Often you may want to use `syn::Error::new_spanned` even in this /// situation. In the above code, that would be: /// /// ``` /// # use syn::{Error, Expr}; /// # /// # fn example(expr: Expr) -> syn::Result<()> { /// match expr { /// Expr::Lit(expr) => /* ... */ /// # unimplemented!(), /// Expr::Path(expr) => /* ... */ /// # unimplemented!(), /// Expr::Macro(expr) => /* ... */ /// # unimplemented!(), /// _ => Err(Error::new_spanned(expr, "unsupported expression type for `kind`")), /// } /// # } /// ``` /// /// ```console /// error: unsupported expression type for `kind` /// --> src/main.rs:3:14 /// | /// 3 | #[tea(kind = async { replicator.await })] /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^ /// ``` pub fn error(&self, msg: impl Display) -> Error { let start_span = self.path.segments[0].ident.span(); let end_span = self.input.cursor().prev_span(); crate::error::new2(start_span, end_span, msg) } } pub(crate) fn parse_nested_meta( input: ParseStream, mut logic: impl FnMut(ParseNestedMeta) -> Result<()>, ) -> Result<()> { loop { let path = input.call(parse_meta_path)?; logic(ParseNestedMeta { path, input })?; if input.is_empty() { return Ok(()); } input.parse::()?; if input.is_empty() { return Ok(()); } } } // Like Path::parse_mod_style, but accepts keywords in the path. fn parse_meta_path(input: ParseStream) -> Result { Ok(Path { leading_colon: input.parse()?, segments: { let mut segments = Punctuated::new(); if input.peek(Ident::peek_any) { let ident = Ident::parse_any(input)?; segments.push_value(PathSegment::from(ident)); } else if input.is_empty() { return Err(input.error("expected nested attribute")); } else if input.peek(Lit) { return Err(input.error("unexpected literal in nested attribute, expected ident")); } else { return Err(input.error("unexpected token in nested attribute, expected ident")); } while input.peek(Token![::]) { let punct = input.parse()?; segments.push_punct(punct); let ident = Ident::parse_any(input)?; segments.push_value(PathSegment::from(ident)); } segments }, }) } syn/src/span.rs0000644000175000017500000000225514661133735014454 0ustar jamespagejamespageuse proc_macro2::extra::DelimSpan; use proc_macro2::{Delimiter, Group, Span, TokenStream}; #[doc(hidden)] pub trait IntoSpans { fn into_spans(self) -> S; } impl IntoSpans for Span { fn into_spans(self) -> Span { self } } impl IntoSpans<[Span; 1]> for Span { fn into_spans(self) -> [Span; 1] { [self] } } impl IntoSpans<[Span; 2]> for Span { fn into_spans(self) -> [Span; 2] { [self, self] } } impl IntoSpans<[Span; 3]> for Span { fn into_spans(self) -> [Span; 3] { [self, self, self] } } impl IntoSpans<[Span; 1]> for [Span; 1] { fn into_spans(self) -> [Span; 1] { self } } impl IntoSpans<[Span; 2]> for [Span; 2] { fn into_spans(self) -> [Span; 2] { self } } impl IntoSpans<[Span; 3]> for [Span; 3] { fn into_spans(self) -> [Span; 3] { self } } impl IntoSpans for Span { fn into_spans(self) -> DelimSpan { let mut group = Group::new(Delimiter::None, TokenStream::new()); group.set_span(self); group.delim_span() } } impl IntoSpans for DelimSpan { fn into_spans(self) -> DelimSpan { self } } syn/src/tt.rs0000644000175000017500000000721714661133735014145 0ustar jamespagejamespageuse proc_macro2::{Delimiter, TokenStream, TokenTree}; use std::hash::{Hash, Hasher}; pub(crate) struct TokenTreeHelper<'a>(pub &'a TokenTree); impl<'a> PartialEq for TokenTreeHelper<'a> { fn eq(&self, other: &Self) -> bool { use proc_macro2::Spacing; match (self.0, other.0) { (TokenTree::Group(g1), TokenTree::Group(g2)) => { match (g1.delimiter(), g2.delimiter()) { (Delimiter::Parenthesis, Delimiter::Parenthesis) | (Delimiter::Brace, Delimiter::Brace) | (Delimiter::Bracket, Delimiter::Bracket) | (Delimiter::None, Delimiter::None) => {} _ => return false, } let s1 = g1.stream().into_iter(); let mut s2 = g2.stream().into_iter(); for item1 in s1 { let item2 = match s2.next() { Some(item) => item, None => return false, }; if TokenTreeHelper(&item1) != TokenTreeHelper(&item2) { return false; } } s2.next().is_none() } (TokenTree::Punct(o1), TokenTree::Punct(o2)) => { o1.as_char() == o2.as_char() && match (o1.spacing(), o2.spacing()) { (Spacing::Alone, Spacing::Alone) | (Spacing::Joint, Spacing::Joint) => true, _ => false, } } (TokenTree::Literal(l1), TokenTree::Literal(l2)) => l1.to_string() == l2.to_string(), (TokenTree::Ident(s1), TokenTree::Ident(s2)) => s1 == s2, _ => false, } } } impl<'a> Hash for TokenTreeHelper<'a> { fn hash(&self, h: &mut H) { use proc_macro2::Spacing; match self.0 { TokenTree::Group(g) => { 0u8.hash(h); match g.delimiter() { Delimiter::Parenthesis => 0u8.hash(h), Delimiter::Brace => 1u8.hash(h), Delimiter::Bracket => 2u8.hash(h), Delimiter::None => 3u8.hash(h), } for item in g.stream() { TokenTreeHelper(&item).hash(h); } 0xFFu8.hash(h); // terminator w/ a variant we don't normally hash } TokenTree::Punct(op) => { 1u8.hash(h); op.as_char().hash(h); match op.spacing() { Spacing::Alone => 0u8.hash(h), Spacing::Joint => 1u8.hash(h), } } TokenTree::Literal(lit) => (2u8, lit.to_string()).hash(h), TokenTree::Ident(word) => (3u8, word).hash(h), } } } pub(crate) struct TokenStreamHelper<'a>(pub &'a TokenStream); impl<'a> PartialEq for TokenStreamHelper<'a> { fn eq(&self, other: &Self) -> bool { let left = self.0.clone().into_iter().collect::>(); let right = other.0.clone().into_iter().collect::>(); if left.len() != right.len() { return false; } for (a, b) in left.into_iter().zip(right) { if TokenTreeHelper(&a) != TokenTreeHelper(&b) { return false; } } true } } impl<'a> Hash for TokenStreamHelper<'a> { fn hash(&self, state: &mut H) { let tts = self.0.clone().into_iter().collect::>(); tts.len().hash(state); for tt in tts { TokenTreeHelper(&tt).hash(state); } } } syn/src/lifetime.rs0000644000175000017500000000744614661133735015320 0ustar jamespagejamespage#[cfg(feature = "parsing")] use crate::lookahead; use proc_macro2::{Ident, Span}; use std::cmp::Ordering; use std::fmt::{self, Display}; use std::hash::{Hash, Hasher}; /// A Rust lifetime: `'a`. /// /// Lifetime names must conform to the following rules: /// /// - Must start with an apostrophe. /// - Must not consist of just an apostrophe: `'`. /// - Character after the apostrophe must be `_` or a Unicode code point with /// the XID_Start property. /// - All following characters must be Unicode code points with the XID_Continue /// property. pub struct Lifetime { pub apostrophe: Span, pub ident: Ident, } impl Lifetime { /// # Panics /// /// Panics if the lifetime does not conform to the bulleted rules above. /// /// # Invocation /// /// ``` /// # use proc_macro2::Span; /// # use syn::Lifetime; /// # /// # fn f() -> Lifetime { /// Lifetime::new("'a", Span::call_site()) /// # } /// ``` pub fn new(symbol: &str, span: Span) -> Self { if !symbol.starts_with('\'') { panic!( "lifetime name must start with apostrophe as in \"'a\", got {:?}", symbol ); } if symbol == "'" { panic!("lifetime name must not be empty"); } if !crate::ident::xid_ok(&symbol[1..]) { panic!("{:?} is not a valid lifetime name", symbol); } Lifetime { apostrophe: span, ident: Ident::new(&symbol[1..], span), } } pub fn span(&self) -> Span { self.apostrophe .join(self.ident.span()) .unwrap_or(self.apostrophe) } pub fn set_span(&mut self, span: Span) { self.apostrophe = span; self.ident.set_span(span); } } impl Display for Lifetime { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { "'".fmt(formatter)?; self.ident.fmt(formatter) } } impl Clone for Lifetime { fn clone(&self) -> Self { Lifetime { apostrophe: self.apostrophe, ident: self.ident.clone(), } } } impl PartialEq for Lifetime { fn eq(&self, other: &Lifetime) -> bool { self.ident.eq(&other.ident) } } impl Eq for Lifetime {} impl PartialOrd for Lifetime { fn partial_cmp(&self, other: &Lifetime) -> Option { Some(self.cmp(other)) } } impl Ord for Lifetime { fn cmp(&self, other: &Lifetime) -> Ordering { self.ident.cmp(&other.ident) } } impl Hash for Lifetime { fn hash(&self, h: &mut H) { self.ident.hash(h); } } #[cfg(feature = "parsing")] pub_if_not_doc! { #[doc(hidden)] #[allow(non_snake_case)] pub fn Lifetime(marker: lookahead::TokenMarker) -> Lifetime { match marker {} } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::error::Result; use crate::lifetime::Lifetime; use crate::parse::{Parse, ParseStream}; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Lifetime { fn parse(input: ParseStream) -> Result { input.step(|cursor| { cursor .lifetime() .ok_or_else(|| cursor.error("expected lifetime")) }) } } } #[cfg(feature = "printing")] mod printing { use crate::lifetime::Lifetime; use proc_macro2::{Punct, Spacing, TokenStream}; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Lifetime { fn to_tokens(&self, tokens: &mut TokenStream) { let mut apostrophe = Punct::new('\'', Spacing::Joint); apostrophe.set_span(self.apostrophe); tokens.append(apostrophe); self.ident.to_tokens(tokens); } } } syn/src/drops.rs0000644000175000017500000000262614661133735014644 0ustar jamespagejamespageuse std::iter; use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; use std::option; use std::slice; #[repr(transparent)] pub(crate) struct NoDrop(ManuallyDrop); impl NoDrop { pub(crate) fn new(value: T) -> Self where T: TrivialDrop, { NoDrop(ManuallyDrop::new(value)) } } impl Deref for NoDrop { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for NoDrop { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } pub(crate) trait TrivialDrop {} impl TrivialDrop for iter::Empty {} impl<'a, T> TrivialDrop for slice::Iter<'a, T> {} impl<'a, T> TrivialDrop for slice::IterMut<'a, T> {} impl<'a, T> TrivialDrop for option::IntoIter<&'a T> {} impl<'a, T> TrivialDrop for option::IntoIter<&'a mut T> {} #[test] fn test_needs_drop() { use std::mem::needs_drop; struct NeedsDrop; impl Drop for NeedsDrop { fn drop(&mut self) {} } assert!(needs_drop::()); // Test each of the types with a handwritten TrivialDrop impl above. assert!(!needs_drop::>()); assert!(!needs_drop::>()); assert!(!needs_drop::>()); assert!(!needs_drop::>()); assert!(!needs_drop::>()); } syn/src/ident.rs0000644000175000017500000000610714661133735014616 0ustar jamespagejamespage#[cfg(feature = "parsing")] use crate::lookahead; pub use proc_macro2::Ident; #[cfg(feature = "parsing")] pub_if_not_doc! { #[doc(hidden)] #[allow(non_snake_case)] pub fn Ident(marker: lookahead::TokenMarker) -> Ident { match marker {} } } macro_rules! ident_from_token { ($token:ident) => { impl From for Ident { fn from(token: Token![$token]) -> Ident { Ident::new(stringify!($token), token.span) } } }; } ident_from_token!(self); ident_from_token!(Self); ident_from_token!(super); ident_from_token!(crate); ident_from_token!(extern); impl From for Ident { fn from(token: Token![_]) -> Ident { Ident::new("_", token.span) } } pub(crate) fn xid_ok(symbol: &str) -> bool { let mut chars = symbol.chars(); let first = chars.next().unwrap(); if !(first == '_' || unicode_ident::is_xid_start(first)) { return false; } for ch in chars { if !unicode_ident::is_xid_continue(ch) { return false; } } true } #[cfg(feature = "parsing")] mod parsing { use crate::buffer::Cursor; use crate::error::Result; use crate::parse::{Parse, ParseStream}; use crate::token::Token; use proc_macro2::Ident; fn accept_as_ident(ident: &Ident) -> bool { match ident.to_string().as_str() { "_" | // Based on https://doc.rust-lang.org/1.65.0/reference/keywords.html "abstract" | "as" | "async" | "await" | "become" | "box" | "break" | "const" | "continue" | "crate" | "do" | "dyn" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut" | "override" | "priv" | "pub" | "ref" | "return" | "Self" | "self" | "static" | "struct" | "super" | "trait" | "true" | "try" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" => false, _ => true, } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Ident { fn parse(input: ParseStream) -> Result { input.step(|cursor| { if let Some((ident, rest)) = cursor.ident() { if accept_as_ident(&ident) { Ok((ident, rest)) } else { Err(cursor.error(format_args!( "expected identifier, found keyword `{}`", ident, ))) } } else { Err(cursor.error("expected identifier")) } }) } } impl Token for Ident { fn peek(cursor: Cursor) -> bool { if let Some((ident, _rest)) = cursor.ident() { accept_as_ident(&ident) } else { false } } fn display() -> &'static str { "identifier" } } } syn/src/discouraged.rs0000644000175000017500000002176414661133735016012 0ustar jamespagejamespage//! Extensions to the parsing API with niche applicability. use crate::buffer::Cursor; use crate::error::Result; use crate::parse::{inner_unexpected, ParseBuffer, Unexpected}; use proc_macro2::extra::DelimSpan; use proc_macro2::Delimiter; use std::cell::Cell; use std::mem; use std::rc::Rc; /// Extensions to the `ParseStream` API to support speculative parsing. pub trait Speculative { /// Advance this parse stream to the position of a forked parse stream. /// /// This is the opposite operation to [`ParseStream::fork`]. You can fork a /// parse stream, perform some speculative parsing, then join the original /// stream to the fork to "commit" the parsing from the fork to the main /// stream. /// /// If you can avoid doing this, you should, as it limits the ability to /// generate useful errors. That said, it is often the only way to parse /// syntax of the form `A* B*` for arbitrary syntax `A` and `B`. The problem /// is that when the fork fails to parse an `A`, it's impossible to tell /// whether that was because of a syntax error and the user meant to provide /// an `A`, or that the `A`s are finished and it's time to start parsing /// `B`s. Use with care. /// /// Also note that if `A` is a subset of `B`, `A* B*` can be parsed by /// parsing `B*` and removing the leading members of `A` from the /// repetition, bypassing the need to involve the downsides associated with /// speculative parsing. /// /// [`ParseStream::fork`]: ParseBuffer::fork /// /// # Example /// /// There has been chatter about the possibility of making the colons in the /// turbofish syntax like `path::to::` no longer required by accepting /// `path::to` in expression position. Specifically, according to [RFC /// 2544], [`PathSegment`] parsing should always try to consume a following /// `<` token as the start of generic arguments, and reset to the `<` if /// that fails (e.g. the token is acting as a less-than operator). /// /// This is the exact kind of parsing behavior which requires the "fork, /// try, commit" behavior that [`ParseStream::fork`] discourages. With /// `advance_to`, we can avoid having to parse the speculatively parsed /// content a second time. /// /// This change in behavior can be implemented in syn by replacing just the /// `Parse` implementation for `PathSegment`: /// /// ``` /// # use syn::ext::IdentExt; /// use syn::parse::discouraged::Speculative; /// # use syn::parse::{Parse, ParseStream}; /// # use syn::{Ident, PathArguments, Result, Token}; /// /// pub struct PathSegment { /// pub ident: Ident, /// pub arguments: PathArguments, /// } /// # /// # impl From for PathSegment /// # where /// # T: Into, /// # { /// # fn from(ident: T) -> Self { /// # PathSegment { /// # ident: ident.into(), /// # arguments: PathArguments::None, /// # } /// # } /// # } /// /// impl Parse for PathSegment { /// fn parse(input: ParseStream) -> Result { /// if input.peek(Token![super]) /// || input.peek(Token![self]) /// || input.peek(Token![Self]) /// || input.peek(Token![crate]) /// { /// let ident = input.call(Ident::parse_any)?; /// return Ok(PathSegment::from(ident)); /// } /// /// let ident = input.parse()?; /// if input.peek(Token![::]) && input.peek3(Token![<]) { /// return Ok(PathSegment { /// ident, /// arguments: PathArguments::AngleBracketed(input.parse()?), /// }); /// } /// if input.peek(Token![<]) && !input.peek(Token![<=]) { /// let fork = input.fork(); /// if let Ok(arguments) = fork.parse() { /// input.advance_to(&fork); /// return Ok(PathSegment { /// ident, /// arguments: PathArguments::AngleBracketed(arguments), /// }); /// } /// } /// Ok(PathSegment::from(ident)) /// } /// } /// /// # syn::parse_str::("a").unwrap(); /// ``` /// /// # Drawbacks /// /// The main drawback of this style of speculative parsing is in error /// presentation. Even if the lookahead is the "correct" parse, the error /// that is shown is that of the "fallback" parse. To use the same example /// as the turbofish above, take the following unfinished "turbofish": /// /// ```text /// let _ = f<&'a fn(), for<'a> serde::>(); /// ``` /// /// If this is parsed as generic arguments, we can provide the error message /// /// ```text /// error: expected identifier /// --> src.rs:L:C /// | /// L | let _ = f<&'a fn(), for<'a> serde::>(); /// | ^ /// ``` /// /// but if parsed using the above speculative parsing, it falls back to /// assuming that the `<` is a less-than when it fails to parse the generic /// arguments, and tries to interpret the `&'a` as the start of a labelled /// loop, resulting in the much less helpful error /// /// ```text /// error: expected `:` /// --> src.rs:L:C /// | /// L | let _ = f<&'a fn(), for<'a> serde::>(); /// | ^^ /// ``` /// /// This can be mitigated with various heuristics (two examples: show both /// forks' parse errors, or show the one that consumed more tokens), but /// when you can control the grammar, sticking to something that can be /// parsed LL(3) and without the LL(*) speculative parsing this makes /// possible, displaying reasonable errors becomes much more simple. /// /// [RFC 2544]: https://github.com/rust-lang/rfcs/pull/2544 /// [`PathSegment`]: crate::PathSegment /// /// # Performance /// /// This method performs a cheap fixed amount of work that does not depend /// on how far apart the two streams are positioned. /// /// # Panics /// /// The forked stream in the argument of `advance_to` must have been /// obtained by forking `self`. Attempting to advance to any other stream /// will cause a panic. fn advance_to(&self, fork: &Self); } impl<'a> Speculative for ParseBuffer<'a> { fn advance_to(&self, fork: &Self) { if !crate::buffer::same_scope(self.cursor(), fork.cursor()) { panic!("fork was not derived from the advancing parse stream"); } let (self_unexp, self_sp) = inner_unexpected(self); let (fork_unexp, fork_sp) = inner_unexpected(fork); if !Rc::ptr_eq(&self_unexp, &fork_unexp) { match (fork_sp, self_sp) { // Unexpected set on the fork, but not on `self`, copy it over. (Some(span), None) => { self_unexp.set(Unexpected::Some(span)); } // Unexpected unset. Use chain to propagate errors from fork. (None, None) => { fork_unexp.set(Unexpected::Chain(self_unexp)); // Ensure toplevel 'unexpected' tokens from the fork don't // bubble up the chain by replacing the root `unexpected` // pointer, only 'unexpected' tokens from existing group // parsers should bubble. fork.unexpected .set(Some(Rc::new(Cell::new(Unexpected::None)))); } // Unexpected has been set on `self`. No changes needed. (_, Some(_)) => {} } } // See comment on `cell` in the struct definition. self.cell .set(unsafe { mem::transmute::>(fork.cursor()) }); } } /// Extensions to the `ParseStream` API to support manipulating invisible /// delimiters the same as if they were visible. pub trait AnyDelimiter { /// Returns the delimiter, the span of the delimiter token, and the nested /// contents for further parsing. fn parse_any_delimiter(&self) -> Result<(Delimiter, DelimSpan, ParseBuffer)>; } impl<'a> AnyDelimiter for ParseBuffer<'a> { fn parse_any_delimiter(&self) -> Result<(Delimiter, DelimSpan, ParseBuffer)> { self.step(|cursor| { if let Some((content, delimiter, span, rest)) = cursor.any_group() { let scope = span.close(); let nested = crate::parse::advance_step_cursor(cursor, content); let unexpected = crate::parse::get_unexpected(self); let content = crate::parse::new_parse_buffer(scope, nested, unexpected); Ok(((delimiter, span, content), rest)) } else { Err(cursor.error("expected any delimiter")) } }) } } syn/src/fixup.rs0000644000175000017500000001725614661133735014655 0ustar jamespagejamespageuse crate::classify; use crate::expr::Expr; use crate::precedence::Precedence; pub(crate) struct FixupContext { // Print expression such that it can be parsed back as a statement // consisting of the original expression. // // The effect of this is for binary operators in statement position to set // `leftmost_subexpression_in_stmt` when printing their left-hand operand. // // (match x {}) - 1; // match needs parens when LHS of binary operator // // match x {}; // not when its own statement // stmt: bool, // This is the difference between: // // (match x {}) - 1; // subexpression needs parens // // let _ = match x {} - 1; // no parens // // There are 3 distinguishable contexts in which `print_expr` might be // called with the expression `$match` as its argument, where `$match` // represents an expression of kind `ExprKind::Match`: // // - stmt=false leftmost_subexpression_in_stmt=false // // Example: `let _ = $match - 1;` // // No parentheses required. // // - stmt=false leftmost_subexpression_in_stmt=true // // Example: `$match - 1;` // // Must parenthesize `($match)`, otherwise parsing back the output as a // statement would terminate the statement after the closing brace of // the match, parsing `-1;` as a separate statement. // // - stmt=true leftmost_subexpression_in_stmt=false // // Example: `$match;` // // No parentheses required. leftmost_subexpression_in_stmt: bool, // Print expression such that it can be parsed as a match arm. // // This is almost equivalent to `stmt`, but the grammar diverges a tiny bit // between statements and match arms when it comes to braced macro calls. // Macro calls with brace delimiter terminate a statement without a // semicolon, but do not terminate a match-arm without comma. // // m! {} - 1; // two statements: a macro call followed by -1 literal // // match () { // _ => m! {} - 1, // binary subtraction operator // } // match_arm: bool, // This is almost equivalent to `leftmost_subexpression_in_stmt`, other than // for braced macro calls. // // If we have `m! {} - 1` as an expression, the leftmost subexpression // `m! {}` will need to be parenthesized in the statement case but not the // match-arm case. // // (m! {}) - 1; // subexpression needs parens // // match () { // _ => m! {} - 1, // no parens // } // leftmost_subexpression_in_match_arm: bool, // This is the difference between: // // if let _ = (Struct {}) {} // needs parens // // match () { // () if let _ = Struct {} => {} // no parens // } // parenthesize_exterior_struct_lit: bool, } impl FixupContext { /// The default amount of fixing is minimal fixing. Fixups should be turned /// on in a targeted fashion where needed. pub const NONE: Self = FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, match_arm: false, leftmost_subexpression_in_match_arm: false, parenthesize_exterior_struct_lit: false, }; /// Create the initial fixup for printing an expression in statement /// position. pub fn new_stmt() -> Self { FixupContext { stmt: true, ..FixupContext::NONE } } /// Create the initial fixup for printing an expression as the right-hand /// side of a match arm. pub fn new_match_arm() -> Self { FixupContext { match_arm: true, ..FixupContext::NONE } } /// Create the initial fixup for printing an expression as the "condition" /// of an `if` or `while`. There are a few other positions which are /// grammatically equivalent and also use this, such as the iterator /// expression in `for` and the scrutinee in `match`. pub fn new_condition() -> Self { FixupContext { parenthesize_exterior_struct_lit: true, ..FixupContext::NONE } } /// Transform this fixup into the one that should apply when printing the /// leftmost subexpression of the current expression. /// /// The leftmost subexpression is any subexpression that has the same first /// token as the current expression, but has a different last token. /// /// For example in `$a + $b` and `$a.method()`, the subexpression `$a` is a /// leftmost subexpression. /// /// Not every expression has a leftmost subexpression. For example neither /// `-$a` nor `[$a]` have one. pub fn leftmost_subexpression(self) -> Self { FixupContext { stmt: false, leftmost_subexpression_in_stmt: self.stmt || self.leftmost_subexpression_in_stmt, match_arm: false, leftmost_subexpression_in_match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm, ..self } } /// Transform this fixup into the one that should apply when printing a /// leftmost subexpression followed by a `.` or `?` token, which confer /// different statement boundary rules compared to other leftmost /// subexpressions. pub fn leftmost_subexpression_with_dot(self) -> Self { FixupContext { stmt: self.stmt || self.leftmost_subexpression_in_stmt, leftmost_subexpression_in_stmt: false, match_arm: self.match_arm || self.leftmost_subexpression_in_match_arm, leftmost_subexpression_in_match_arm: false, ..self } } /// Transform this fixup into the one that should apply when printing any /// subexpression that is neither a leftmost subexpression nor surrounded in /// delimiters. /// /// This is for any subexpression that has a different first token than the /// current expression, and is not surrounded by a paren/bracket/brace. For /// example the `$b` in `$a + $b` and `-$b`, but not the one in `[$b]` or /// `$a.f($b)`. pub fn subsequent_subexpression(self) -> Self { FixupContext { stmt: false, leftmost_subexpression_in_stmt: false, match_arm: false, leftmost_subexpression_in_match_arm: false, ..self } } /// Determine whether parentheses are needed around the given expression to /// head off an unintended statement boundary. /// /// The documentation on `FixupContext::leftmost_subexpression_in_stmt` has /// examples. pub fn would_cause_statement_boundary(self, expr: &Expr) -> bool { (self.leftmost_subexpression_in_stmt && !classify::requires_semi_to_be_stmt(expr)) || (self.leftmost_subexpression_in_match_arm && !classify::requires_comma_to_be_match_arm(expr)) } /// Determine whether parentheses are needed around the given `let` /// scrutinee. /// /// In `if let _ = $e {}`, some examples of `$e` that would need parentheses /// are: /// /// - `Struct {}.f()`, because otherwise the `{` would be misinterpreted /// as the opening of the if's then-block. /// /// - `true && false`, because otherwise this would be misinterpreted as a /// "let chain". pub fn needs_group_as_let_scrutinee(self, expr: &Expr) -> bool { self.parenthesize_exterior_struct_lit && classify::confusable_with_adjacent_block(expr) || Precedence::of_rhs(expr) <= Precedence::And } } impl Copy for FixupContext {} impl Clone for FixupContext { fn clone(&self) -> Self { *self } } syn/src/pat.rs0000644000175000017500000007622114661133735014303 0ustar jamespagejamespageuse crate::attr::Attribute; use crate::expr::Member; use crate::ident::Ident; use crate::path::{Path, QSelf}; use crate::punctuated::Punctuated; use crate::token; use crate::ty::Type; use proc_macro2::TokenStream; pub use crate::expr::{ ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath, ExprRange as PatRange, }; ast_enum_of_structs! { /// A pattern in a local binding, function signature, match expression, or /// various other places. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum Pat { /// A const block: `const { ... }`. Const(PatConst), /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. Ident(PatIdent), /// A literal pattern: `0`. Lit(PatLit), /// A macro in pattern position. Macro(PatMacro), /// A pattern that matches any one of a set of cases. Or(PatOr), /// A parenthesized pattern: `(A | B)`. Paren(PatParen), /// A path pattern like `Color::Red`, optionally qualified with a /// self-type. /// /// Unqualified path patterns can legally refer to variants, structs, /// constants or associated constants. Qualified path patterns like /// `::B::C` and `::B::C` can only legally refer to /// associated constants. Path(PatPath), /// A range pattern: `1..=2`. Range(PatRange), /// A reference pattern: `&mut var`. Reference(PatReference), /// The dots in a tuple or slice pattern: `[0, 1, ..]`. Rest(PatRest), /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. Slice(PatSlice), /// A struct or struct variant pattern: `Variant { x, y, .. }`. Struct(PatStruct), /// A tuple pattern: `(a, b)`. Tuple(PatTuple), /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. TupleStruct(PatTupleStruct), /// A type ascription pattern: `foo: f64`. Type(PatType), /// Tokens in pattern position not interpreted by Syn. Verbatim(TokenStream), /// A pattern that matches any value: `_`. Wild(PatWild), // For testing exhaustiveness in downstream code, use the following idiom: // // match pat { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Pat::Box(pat) => {...} // Pat::Ident(pat) => {...} // ... // Pat::Wild(pat) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. /// /// It may also be a unit struct or struct variant (e.g. `None`), or a /// constant; these cannot be distinguished syntactically. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatIdent { pub attrs: Vec, pub by_ref: Option, pub mutability: Option, pub ident: Ident, pub subpat: Option<(Token![@], Box)>, } } ast_struct! { /// A pattern that matches any one of a set of cases. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatOr { pub attrs: Vec, pub leading_vert: Option, pub cases: Punctuated, } } ast_struct! { /// A parenthesized pattern: `(A | B)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatParen { pub attrs: Vec, pub paren_token: token::Paren, pub pat: Box, } } ast_struct! { /// A reference pattern: `&mut var`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatReference { pub attrs: Vec, pub and_token: Token![&], pub mutability: Option, pub pat: Box, } } ast_struct! { /// The dots in a tuple or slice pattern: `[0, 1, ..]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatRest { pub attrs: Vec, pub dot2_token: Token![..], } } ast_struct! { /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatSlice { pub attrs: Vec, pub bracket_token: token::Bracket, pub elems: Punctuated, } } ast_struct! { /// A struct or struct variant pattern: `Variant { x, y, .. }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatStruct { pub attrs: Vec, pub qself: Option, pub path: Path, pub brace_token: token::Brace, pub fields: Punctuated, pub rest: Option, } } ast_struct! { /// A tuple pattern: `(a, b)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTuple { pub attrs: Vec, pub paren_token: token::Paren, pub elems: Punctuated, } } ast_struct! { /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTupleStruct { pub attrs: Vec, pub qself: Option, pub path: Path, pub paren_token: token::Paren, pub elems: Punctuated, } } ast_struct! { /// A type ascription pattern: `foo: f64`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatType { pub attrs: Vec, pub pat: Box, pub colon_token: Token![:], pub ty: Box, } } ast_struct! { /// A pattern that matches any value: `_`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatWild { pub attrs: Vec, pub underscore_token: Token![_], } } ast_struct! { /// A single field in a struct pattern. /// /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct FieldPat { pub attrs: Vec, pub member: Member, pub colon_token: Option, pub pat: Box, } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::{self, Result}; use crate::expr::{ Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits, }; use crate::ext::IdentExt as _; use crate::ident::Ident; use crate::lit::Lit; use crate::mac::{self, Macro}; use crate::parse::{Parse, ParseBuffer, ParseStream}; use crate::pat::{ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, }; use crate::path::{self, Path, QSelf}; use crate::punctuated::Punctuated; use crate::stmt::Block; use crate::token; use crate::verbatim; use proc_macro2::TokenStream; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Pat { /// Parse a pattern that does _not_ involve `|` at the top level. /// /// This parser matches the behavior of the `$:pat_param` macro_rules /// matcher, and on editions prior to Rust 2021, the behavior of /// `$:pat`. /// /// In Rust syntax, some examples of where this syntax would occur are /// in the argument pattern of functions and closures. Patterns using /// `|` are not allowed to occur in these positions. /// /// ```compile_fail /// fn f(Some(_) | None: Option) { /// let _ = |Some(_) | None: Option| {}; /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :( /// } /// ``` /// /// ```console /// error: top-level or-patterns are not allowed in function parameters /// --> src/main.rs:1:6 /// | /// 1 | fn f(Some(_) | None: Option) { /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)` /// ``` pub fn parse_single(input: ParseStream) -> Result { let begin = input.fork(); let lookahead = input.lookahead1(); if lookahead.peek(Ident) && (input.peek2(Token![::]) || input.peek2(Token![!]) || input.peek2(token::Brace) || input.peek2(token::Paren) || input.peek2(Token![..])) || input.peek(Token![self]) && input.peek2(Token![::]) || lookahead.peek(Token![::]) || lookahead.peek(Token![<]) || input.peek(Token![Self]) || input.peek(Token![super]) || input.peek(Token![crate]) { pat_path_or_macro_or_struct_or_range(input) } else if lookahead.peek(Token![_]) { input.call(pat_wild).map(Pat::Wild) } else if input.peek(Token![box]) { pat_box(begin, input) } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const]) { pat_lit_or_range(input) } else if lookahead.peek(Token![ref]) || lookahead.peek(Token![mut]) || input.peek(Token![self]) || input.peek(Ident) { input.call(pat_ident).map(Pat::Ident) } else if lookahead.peek(Token![&]) { input.call(pat_reference).map(Pat::Reference) } else if lookahead.peek(token::Paren) { input.call(pat_paren_or_tuple) } else if lookahead.peek(token::Bracket) { input.call(pat_slice).map(Pat::Slice) } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) { pat_range_half_open(input) } else if lookahead.peek(Token![const]) { input.call(pat_const).map(Pat::Verbatim) } else { Err(lookahead.error()) } } /// Parse a pattern, possibly involving `|`, but not a leading `|`. pub fn parse_multi(input: ParseStream) -> Result { multi_pat_impl(input, None) } /// Parse a pattern, possibly involving `|`, possibly including a /// leading `|`. /// /// This parser matches the behavior of the Rust 2021 edition's `$:pat` /// macro_rules matcher. /// /// In Rust syntax, an example of where this syntax would occur is in /// the pattern of a `match` arm, where the language permits an optional /// leading `|`, although it is not idiomatic to write one there in /// handwritten code. /// /// ``` /// # let wat = None; /// match wat { /// | None | Some(false) => {} /// | Some(true) => {} /// } /// ``` /// /// The compiler accepts it only to facilitate some situations in /// macro-generated code where a macro author might need to write: /// /// ``` /// # macro_rules! doc { /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => { /// match $value { /// $(| $conditions1)* $(| $conditions2)* => $then /// } /// # }; /// # } /// # /// # doc!(true, (true), (false), {}); /// # doc!(true, (), (true, false), {}); /// # doc!(true, (true, false), (), {}); /// ``` /// /// Expressing the same thing correctly in the case that either one (but /// not both) of `$conditions1` and `$conditions2` might be empty, /// without leading `|`, is complex. /// /// Use [`Pat::parse_multi`] instead if you are not intending to support /// macro-generated macro input. pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result { let leading_vert: Option = input.parse()?; multi_pat_impl(input, leading_vert) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for PatType { fn parse(input: ParseStream) -> Result { Ok(PatType { attrs: Vec::new(), pat: Box::new(Pat::parse_single(input)?), colon_token: input.parse()?, ty: input.parse()?, }) } } fn multi_pat_impl(input: ParseStream, leading_vert: Option) -> Result { let mut pat = Pat::parse_single(input)?; if leading_vert.is_some() || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { let mut cases = Punctuated::new(); cases.push_value(pat); while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { let punct = input.parse()?; cases.push_punct(punct); let pat = Pat::parse_single(input)?; cases.push_value(pat); } pat = Pat::Or(PatOr { attrs: Vec::new(), leading_vert, cases, }); } Ok(pat) } fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result { let (qself, path) = path::parsing::qpath(input, true)?; if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) && path.is_mod_style() { let bang_token: Token![!] = input.parse()?; let (delimiter, tokens) = mac::parse_delimiter(input)?; return Ok(Pat::Macro(ExprMacro { attrs: Vec::new(), mac: Macro { path, bang_token, delimiter, tokens, }, })); } if input.peek(token::Brace) { pat_struct(input, qself, path).map(Pat::Struct) } else if input.peek(token::Paren) { pat_tuple_struct(input, qself, path).map(Pat::TupleStruct) } else if input.peek(Token![..]) { pat_range(input, qself, path) } else { Ok(Pat::Path(ExprPath { attrs: Vec::new(), qself, path, })) } } fn pat_wild(input: ParseStream) -> Result { Ok(PatWild { attrs: Vec::new(), underscore_token: input.parse()?, }) } fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result { input.parse::()?; Pat::parse_single(input)?; Ok(Pat::Verbatim(verbatim::between(&begin, input))) } fn pat_ident(input: ParseStream) -> Result { Ok(PatIdent { attrs: Vec::new(), by_ref: input.parse()?, mutability: input.parse()?, ident: { if input.peek(Token![self]) { input.call(Ident::parse_any)? } else { input.parse()? } }, subpat: { if input.peek(Token![@]) { let at_token: Token![@] = input.parse()?; let subpat = Pat::parse_single(input)?; Some((at_token, Box::new(subpat))) } else { None } }, }) } fn pat_tuple_struct( input: ParseStream, qself: Option, path: Path, ) -> Result { let content; let paren_token = parenthesized!(content in input); let mut elems = Punctuated::new(); while !content.is_empty() { let value = Pat::parse_multi_with_leading_vert(&content)?; elems.push_value(value); if content.is_empty() { break; } let punct = content.parse()?; elems.push_punct(punct); } Ok(PatTupleStruct { attrs: Vec::new(), qself, path, paren_token, elems, }) } fn pat_struct(input: ParseStream, qself: Option, path: Path) -> Result { let content; let brace_token = braced!(content in input); let mut fields = Punctuated::new(); let mut rest = None; while !content.is_empty() { let attrs = content.call(Attribute::parse_outer)?; if content.peek(Token![..]) { rest = Some(PatRest { attrs, dot2_token: content.parse()?, }); break; } let mut value = content.call(field_pat)?; value.attrs = attrs; fields.push_value(value); if content.is_empty() { break; } let punct: Token![,] = content.parse()?; fields.push_punct(punct); } Ok(PatStruct { attrs: Vec::new(), qself, path, brace_token, fields, rest, }) } fn field_pat(input: ParseStream) -> Result { let begin = input.fork(); let boxed: Option = input.parse()?; let by_ref: Option = input.parse()?; let mutability: Option = input.parse()?; let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() { input.parse().map(Member::Named) } else { input.parse() }?; if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:]) || !member.is_named() { return Ok(FieldPat { attrs: Vec::new(), member, colon_token: Some(input.parse()?), pat: Box::new(Pat::parse_multi_with_leading_vert(input)?), }); } let ident = match member { Member::Named(ident) => ident, Member::Unnamed(_) => unreachable!(), }; let pat = if boxed.is_some() { Pat::Verbatim(verbatim::between(&begin, input)) } else { Pat::Ident(PatIdent { attrs: Vec::new(), by_ref, mutability, ident: ident.clone(), subpat: None, }) }; Ok(FieldPat { attrs: Vec::new(), member: Member::Named(ident), colon_token: None, pat: Box::new(pat), }) } fn pat_range(input: ParseStream, qself: Option, path: Path) -> Result { let limits = RangeLimits::parse_obsolete(input)?; let end = input.call(pat_range_bound)?; if let (RangeLimits::Closed(_), None) = (&limits, &end) { return Err(input.error("expected range upper bound")); } Ok(Pat::Range(ExprRange { attrs: Vec::new(), start: Some(Box::new(Expr::Path(ExprPath { attrs: Vec::new(), qself, path, }))), limits, end: end.map(PatRangeBound::into_expr), })) } fn pat_range_half_open(input: ParseStream) -> Result { let limits: RangeLimits = input.parse()?; let end = input.call(pat_range_bound)?; if end.is_some() { Ok(Pat::Range(ExprRange { attrs: Vec::new(), start: None, limits, end: end.map(PatRangeBound::into_expr), })) } else { match limits { RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest { attrs: Vec::new(), dot2_token, })), RangeLimits::Closed(_) => Err(input.error("expected range upper bound")), } } } fn pat_paren_or_tuple(input: ParseStream) -> Result { let content; let paren_token = parenthesized!(content in input); let mut elems = Punctuated::new(); while !content.is_empty() { let value = Pat::parse_multi_with_leading_vert(&content)?; if content.is_empty() { if elems.is_empty() && !matches!(value, Pat::Rest(_)) { return Ok(Pat::Paren(PatParen { attrs: Vec::new(), paren_token, pat: Box::new(value), })); } elems.push_value(value); break; } elems.push_value(value); let punct = content.parse()?; elems.push_punct(punct); } Ok(Pat::Tuple(PatTuple { attrs: Vec::new(), paren_token, elems, })) } fn pat_reference(input: ParseStream) -> Result { Ok(PatReference { attrs: Vec::new(), and_token: input.parse()?, mutability: input.parse()?, pat: Box::new(Pat::parse_single(input)?), }) } fn pat_lit_or_range(input: ParseStream) -> Result { let start = input.call(pat_range_bound)?.unwrap(); if input.peek(Token![..]) { let limits = RangeLimits::parse_obsolete(input)?; let end = input.call(pat_range_bound)?; if let (RangeLimits::Closed(_), None) = (&limits, &end) { return Err(input.error("expected range upper bound")); } Ok(Pat::Range(ExprRange { attrs: Vec::new(), start: Some(start.into_expr()), limits, end: end.map(PatRangeBound::into_expr), })) } else { Ok(start.into_pat()) } } // Patterns that can appear on either side of a range pattern. enum PatRangeBound { Const(ExprConst), Lit(ExprLit), Path(ExprPath), } impl PatRangeBound { fn into_expr(self) -> Box { Box::new(match self { PatRangeBound::Const(pat) => Expr::Const(pat), PatRangeBound::Lit(pat) => Expr::Lit(pat), PatRangeBound::Path(pat) => Expr::Path(pat), }) } fn into_pat(self) -> Pat { match self { PatRangeBound::Const(pat) => Pat::Const(pat), PatRangeBound::Lit(pat) => Pat::Lit(pat), PatRangeBound::Path(pat) => Pat::Path(pat), } } } fn pat_range_bound(input: ParseStream) -> Result> { if input.is_empty() || input.peek(Token![|]) || input.peek(Token![=]) || input.peek(Token![:]) && !input.peek(Token![::]) || input.peek(Token![,]) || input.peek(Token![;]) || input.peek(Token![if]) { return Ok(None); } let lookahead = input.lookahead1(); let expr = if lookahead.peek(Lit) { PatRangeBound::Lit(input.parse()?) } else if lookahead.peek(Ident) || lookahead.peek(Token![::]) || lookahead.peek(Token![<]) || lookahead.peek(Token![self]) || lookahead.peek(Token![Self]) || lookahead.peek(Token![super]) || lookahead.peek(Token![crate]) { PatRangeBound::Path(input.parse()?) } else if lookahead.peek(Token![const]) { PatRangeBound::Const(input.parse()?) } else { return Err(lookahead.error()); }; Ok(Some(expr)) } fn pat_slice(input: ParseStream) -> Result { let content; let bracket_token = bracketed!(content in input); let mut elems = Punctuated::new(); while !content.is_empty() { let value = Pat::parse_multi_with_leading_vert(&content)?; match value { Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => { let (start, end) = match pat.limits { RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]), RangeLimits::Closed(dot_dot_eq) => { (dot_dot_eq.spans[0], dot_dot_eq.spans[2]) } }; let msg = "range pattern is not allowed unparenthesized inside slice pattern"; return Err(error::new2(start, end, msg)); } _ => {} } elems.push_value(value); if content.is_empty() { break; } let punct = content.parse()?; elems.push_punct(punct); } Ok(PatSlice { attrs: Vec::new(), bracket_token, elems, }) } fn pat_const(input: ParseStream) -> Result { let begin = input.fork(); input.parse::()?; let content; braced!(content in input); content.call(Attribute::parse_inner)?; content.call(Block::parse_within)?; Ok(verbatim::between(&begin, input)) } } #[cfg(feature = "printing")] mod printing { use crate::attr::FilterAttrs; use crate::pat::{ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, }; use crate::path; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatIdent { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.by_ref.to_tokens(tokens); self.mutability.to_tokens(tokens); self.ident.to_tokens(tokens); if let Some((at_token, subpat)) = &self.subpat { at_token.to_tokens(tokens); subpat.to_tokens(tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatOr { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.leading_vert.to_tokens(tokens); self.cases.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatParen { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.paren_token.surround(tokens, |tokens| { self.pat.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatReference { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.and_token.to_tokens(tokens); self.mutability.to_tokens(tokens); self.pat.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatRest { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.dot2_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatSlice { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.bracket_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); path::printing::print_path(tokens, &self.qself, &self.path); self.brace_token.surround(tokens, |tokens| { self.fields.to_tokens(tokens); // NOTE: We need a comma before the dot2 token if it is present. if !self.fields.empty_or_trailing() && self.rest.is_some() { ::default().to_tokens(tokens); } self.rest.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatTuple { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.paren_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); // If there is only one element, a trailing comma is needed to // distinguish PatTuple from PatParen, unless this is `(..)` // which is a tuple pattern even without comma. if self.elems.len() == 1 && !self.elems.trailing_punct() && !matches!(self.elems[0], Pat::Rest { .. }) { ::default().to_tokens(tokens); } }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatTupleStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); path::printing::print_path(tokens, &self.qself, &self.path); self.paren_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.pat.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatWild { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.underscore_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for FieldPat { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some(colon_token) = &self.colon_token { self.member.to_tokens(tokens); colon_token.to_tokens(tokens); } self.pat.to_tokens(tokens); } } } syn/src/expr.rs0000644000175000017500000040250514661133735014473 0ustar jamespagejamespageuse crate::attr::Attribute; #[cfg(all(feature = "parsing", feature = "full"))] use crate::error::Result; #[cfg(feature = "full")] use crate::generics::BoundLifetimes; use crate::ident::Ident; #[cfg(feature = "full")] use crate::lifetime::Lifetime; use crate::lit::Lit; use crate::mac::Macro; use crate::op::{BinOp, UnOp}; #[cfg(all(feature = "parsing", feature = "full"))] use crate::parse::ParseStream; #[cfg(feature = "full")] use crate::pat::Pat; use crate::path::{AngleBracketedGenericArguments, Path, QSelf}; use crate::punctuated::Punctuated; #[cfg(feature = "full")] use crate::stmt::Block; use crate::token; #[cfg(feature = "full")] use crate::ty::ReturnType; use crate::ty::Type; use proc_macro2::{Span, TokenStream}; #[cfg(feature = "printing")] use quote::IdentFragment; #[cfg(feature = "printing")] use std::fmt::{self, Display}; use std::hash::{Hash, Hasher}; #[cfg(all(feature = "parsing", feature = "full"))] use std::mem; ast_enum_of_structs! { /// A Rust expression. /// /// *This type is available only if Syn is built with the `"derive"` or `"full"` /// feature, but most of the variants are not available unless "full" is enabled.* /// /// # Syntax tree enums /// /// This type is a syntax tree enum. In Syn this and other syntax tree enums /// are designed to be traversed using the following rebinding idiom. /// /// ``` /// # use syn::Expr; /// # /// # fn example(expr: Expr) { /// # const IGNORE: &str = stringify! { /// let expr: Expr = /* ... */; /// # }; /// match expr { /// Expr::MethodCall(expr) => { /// /* ... */ /// } /// Expr::Cast(expr) => { /// /* ... */ /// } /// Expr::If(expr) => { /// /* ... */ /// } /// /// /* ... */ /// # _ => {} /// # } /// # } /// ``` /// /// We begin with a variable `expr` of type `Expr` that has no fields /// (because it is an enum), and by matching on it and rebinding a variable /// with the same name `expr` we effectively imbue our variable with all of /// the data fields provided by the variant that it turned out to be. So for /// example above if we ended up in the `MethodCall` case then we get to use /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`. /// /// This approach avoids repeating the variant names twice on every line. /// /// ``` /// # use syn::{Expr, ExprMethodCall}; /// # /// # fn example(expr: Expr) { /// // Repetitive; recommend not doing this. /// match expr { /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { /// # } /// # _ => {} /// # } /// # } /// ``` /// /// In general, the name to which a syntax tree enum variant is bound should /// be a suitable name for the complete syntax tree enum type. /// /// ``` /// # use syn::{Expr, ExprField}; /// # /// # fn example(discriminant: ExprField) { /// // Binding is called `base` which is the name I would use if I were /// // assigning `*discriminant.base` without an `if let`. /// if let Expr::Tuple(base) = *discriminant.base { /// # } /// # } /// ``` /// /// A sign that you may not be choosing the right variable names is if you /// see names getting repeated in your code, like accessing /// `receiver.receiver` or `pat.pat` or `cond.cond`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum Expr { /// A slice literal expression: `[a, b, c, d]`. Array(ExprArray), /// An assignment expression: `a = compute()`. Assign(ExprAssign), /// An async block: `async { ... }`. Async(ExprAsync), /// An await expression: `fut.await`. Await(ExprAwait), /// A binary operation: `a + b`, `a += b`. Binary(ExprBinary), /// A blocked scope: `{ ... }`. Block(ExprBlock), /// A `break`, with an optional label to break and an optional /// expression. Break(ExprBreak), /// A function call expression: `invoke(a, b)`. Call(ExprCall), /// A cast expression: `foo as f64`. Cast(ExprCast), /// A closure expression: `|a, b| a + b`. Closure(ExprClosure), /// A const block: `const { ... }`. Const(ExprConst), /// A `continue`, with an optional label. Continue(ExprContinue), /// Access of a named struct field (`obj.k`) or unnamed tuple struct /// field (`obj.0`). Field(ExprField), /// A for loop: `for pat in expr { ... }`. ForLoop(ExprForLoop), /// An expression contained within invisible delimiters. /// /// This variant is important for faithfully representing the precedence /// of expressions and is related to `None`-delimited spans in a /// `TokenStream`. Group(ExprGroup), /// An `if` expression with an optional `else` block: `if expr { ... } /// else { ... }`. /// /// The `else` branch expression may only be an `If` or `Block` /// expression, not any of the other types of expression. If(ExprIf), /// A square bracketed indexing expression: `vector[2]`. Index(ExprIndex), /// The inferred value of a const generic argument, denoted `_`. Infer(ExprInfer), /// A `let` guard: `let Some(x) = opt`. Let(ExprLet), /// A literal in place of an expression: `1`, `"foo"`. Lit(ExprLit), /// Conditionless loop: `loop { ... }`. Loop(ExprLoop), /// A macro invocation expression: `format!("{}", q)`. Macro(ExprMacro), /// A `match` expression: `match n { Some(n) => {}, None => {} }`. Match(ExprMatch), /// A method call expression: `x.foo::(a, b)`. MethodCall(ExprMethodCall), /// A parenthesized expression: `(a + b)`. Paren(ExprParen), /// A path like `std::mem::replace` possibly containing generic /// parameters and a qualified self-type. /// /// A plain identifier like `x` is a path of length 1. Path(ExprPath), /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. Range(ExprRange), /// A referencing operation: `&a` or `&mut a`. Reference(ExprReference), /// An array literal constructed from one repeated element: `[0u8; N]`. Repeat(ExprRepeat), /// A `return`, with an optional value to be returned. Return(ExprReturn), /// A struct literal expression: `Point { x: 1, y: 1 }`. /// /// The `rest` provides the value of the remaining fields as in `S { a: /// 1, b: 1, ..rest }`. Struct(ExprStruct), /// A try-expression: `expr?`. Try(ExprTry), /// A try block: `try { ... }`. TryBlock(ExprTryBlock), /// A tuple expression: `(a, b, c, d)`. Tuple(ExprTuple), /// A unary operation: `!x`, `*x`. Unary(ExprUnary), /// An unsafe block: `unsafe { ... }`. Unsafe(ExprUnsafe), /// Tokens in expression position not interpreted by Syn. Verbatim(TokenStream), /// A while loop: `while expr { ... }`. While(ExprWhile), /// A yield expression: `yield expr`. Yield(ExprYield), // For testing exhaustiveness in downstream code, use the following idiom: // // match expr { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Expr::Array(expr) => {...} // Expr::Assign(expr) => {...} // ... // Expr::Yield(expr) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// A slice literal expression: `[a, b, c, d]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprArray #full { pub attrs: Vec, pub bracket_token: token::Bracket, pub elems: Punctuated, } } ast_struct! { /// An assignment expression: `a = compute()`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAssign #full { pub attrs: Vec, pub left: Box, pub eq_token: Token![=], pub right: Box, } } ast_struct! { /// An async block: `async { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAsync #full { pub attrs: Vec, pub async_token: Token![async], pub capture: Option, pub block: Block, } } ast_struct! { /// An await expression: `fut.await`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAwait #full { pub attrs: Vec, pub base: Box, pub dot_token: Token![.], pub await_token: Token![await], } } ast_struct! { /// A binary operation: `a + b`, `a += b`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprBinary { pub attrs: Vec, pub left: Box, pub op: BinOp, pub right: Box, } } ast_struct! { /// A blocked scope: `{ ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprBlock #full { pub attrs: Vec, pub label: Option Trait /// for Data { ... }`. Impl(ItemImpl), /// A macro invocation, which includes `macro_rules!` definitions. Macro(ItemMacro), /// A module or module declaration: `mod m` or `mod m { ... }`. Mod(ItemMod), /// A static item: `static BIKE: Shed = Shed(42)`. Static(ItemStatic), /// A struct definition: `struct Foo { x: A }`. Struct(ItemStruct), /// A trait definition: `pub trait Iterator { ... }`. Trait(ItemTrait), /// A trait alias: `pub trait SharableIterator = Iterator + Sync`. TraitAlias(ItemTraitAlias), /// A type alias: `type Result = std::result::Result`. Type(ItemType), /// A union definition: `union Foo { x: A, y: B }`. Union(ItemUnion), /// A use declaration: `use std::collections::HashMap`. Use(ItemUse), /// Tokens forming an item not interpreted by Syn. Verbatim(TokenStream), // For testing exhaustiveness in downstream code, use the following idiom: // // match item { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Item::Const(item) => {...} // Item::Enum(item) => {...} // ... // Item::Verbatim(item) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// A constant item: `const MAX: u16 = 65535`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemConst { pub attrs: Vec, pub vis: Visibility, pub const_token: Token![const], pub ident: Ident, pub generics: Generics, pub colon_token: Token![:], pub ty: Box, pub eq_token: Token![=], pub expr: Box, pub semi_token: Token![;], } } ast_struct! { /// An enum definition: `enum Foo { A(A), B(B) }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemEnum { pub attrs: Vec, pub vis: Visibility, pub enum_token: Token![enum], pub ident: Ident, pub generics: Generics, pub brace_token: token::Brace, pub variants: Punctuated, } } ast_struct! { /// An `extern crate` item: `extern crate serde`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemExternCrate { pub attrs: Vec, pub vis: Visibility, pub extern_token: Token![extern], pub crate_token: Token![crate], pub ident: Ident, pub rename: Option<(Token![as], Ident)>, pub semi_token: Token![;], } } ast_struct! { /// A free-standing function: `fn process(n: usize) -> Result<()> { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemFn { pub attrs: Vec, pub vis: Visibility, pub sig: Signature, pub block: Box, } } ast_struct! { /// A block of foreign items: `extern "C" { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemForeignMod { pub attrs: Vec, pub unsafety: Option, pub abi: Abi, pub brace_token: token::Brace, pub items: Vec, } } ast_struct! { /// An impl block providing trait or associated items: `impl Trait /// for Data { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemImpl { pub attrs: Vec, pub defaultness: Option, pub unsafety: Option, pub impl_token: Token![impl], pub generics: Generics, /// Trait this impl implements. pub trait_: Option<(Option, Path, Token![for])>, /// The Self type of the impl. pub self_ty: Box, pub brace_token: token::Brace, pub items: Vec, } } ast_struct! { /// A macro invocation, which includes `macro_rules!` definitions. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemMacro { pub attrs: Vec, /// The `example` in `macro_rules! example { ... }`. pub ident: Option, pub mac: Macro, pub semi_token: Option, } } ast_struct! { /// A module or module declaration: `mod m` or `mod m { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemMod { pub attrs: Vec, pub vis: Visibility, pub unsafety: Option, pub mod_token: Token![mod], pub ident: Ident, pub content: Option<(token::Brace, Vec)>, pub semi: Option, } } ast_struct! { /// A static item: `static BIKE: Shed = Shed(42)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemStatic { pub attrs: Vec, pub vis: Visibility, pub static_token: Token![static], pub mutability: StaticMutability, pub ident: Ident, pub colon_token: Token![:], pub ty: Box, pub eq_token: Token![=], pub expr: Box, pub semi_token: Token![;], } } ast_struct! { /// A struct definition: `struct Foo { x: A }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemStruct { pub attrs: Vec, pub vis: Visibility, pub struct_token: Token![struct], pub ident: Ident, pub generics: Generics, pub fields: Fields, pub semi_token: Option, } } ast_struct! { /// A trait definition: `pub trait Iterator { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemTrait { pub attrs: Vec, pub vis: Visibility, pub unsafety: Option, pub auto_token: Option, pub restriction: Option, pub trait_token: Token![trait], pub ident: Ident, pub generics: Generics, pub colon_token: Option, pub supertraits: Punctuated, pub brace_token: token::Brace, pub items: Vec, } } ast_struct! { /// A trait alias: `pub trait SharableIterator = Iterator + Sync`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemTraitAlias { pub attrs: Vec, pub vis: Visibility, pub trait_token: Token![trait], pub ident: Ident, pub generics: Generics, pub eq_token: Token![=], pub bounds: Punctuated, pub semi_token: Token![;], } } ast_struct! { /// A type alias: `type Result = std::result::Result`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemType { pub attrs: Vec, pub vis: Visibility, pub type_token: Token![type], pub ident: Ident, pub generics: Generics, pub eq_token: Token![=], pub ty: Box, pub semi_token: Token![;], } } ast_struct! { /// A union definition: `union Foo { x: A, y: B }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemUnion { pub attrs: Vec, pub vis: Visibility, pub union_token: Token![union], pub ident: Ident, pub generics: Generics, pub fields: FieldsNamed, } } ast_struct! { /// A use declaration: `use std::collections::HashMap`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ItemUse { pub attrs: Vec, pub vis: Visibility, pub use_token: Token![use], pub leading_colon: Option, pub tree: UseTree, pub semi_token: Token![;], } } impl Item { #[cfg(feature = "parsing")] pub(crate) fn replace_attrs(&mut self, new: Vec) -> Vec { match self { Item::Const(ItemConst { attrs, .. }) | Item::Enum(ItemEnum { attrs, .. }) | Item::ExternCrate(ItemExternCrate { attrs, .. }) | Item::Fn(ItemFn { attrs, .. }) | Item::ForeignMod(ItemForeignMod { attrs, .. }) | Item::Impl(ItemImpl { attrs, .. }) | Item::Macro(ItemMacro { attrs, .. }) | Item::Mod(ItemMod { attrs, .. }) | Item::Static(ItemStatic { attrs, .. }) | Item::Struct(ItemStruct { attrs, .. }) | Item::Trait(ItemTrait { attrs, .. }) | Item::TraitAlias(ItemTraitAlias { attrs, .. }) | Item::Type(ItemType { attrs, .. }) | Item::Union(ItemUnion { attrs, .. }) | Item::Use(ItemUse { attrs, .. }) => mem::replace(attrs, new), Item::Verbatim(_) => Vec::new(), } } } impl From for Item { fn from(input: DeriveInput) -> Item { match input.data { Data::Struct(data) => Item::Struct(ItemStruct { attrs: input.attrs, vis: input.vis, struct_token: data.struct_token, ident: input.ident, generics: input.generics, fields: data.fields, semi_token: data.semi_token, }), Data::Enum(data) => Item::Enum(ItemEnum { attrs: input.attrs, vis: input.vis, enum_token: data.enum_token, ident: input.ident, generics: input.generics, brace_token: data.brace_token, variants: data.variants, }), Data::Union(data) => Item::Union(ItemUnion { attrs: input.attrs, vis: input.vis, union_token: data.union_token, ident: input.ident, generics: input.generics, fields: data.fields, }), } } } impl From for DeriveInput { fn from(input: ItemStruct) -> DeriveInput { DeriveInput { attrs: input.attrs, vis: input.vis, ident: input.ident, generics: input.generics, data: Data::Struct(DataStruct { struct_token: input.struct_token, fields: input.fields, semi_token: input.semi_token, }), } } } impl From for DeriveInput { fn from(input: ItemEnum) -> DeriveInput { DeriveInput { attrs: input.attrs, vis: input.vis, ident: input.ident, generics: input.generics, data: Data::Enum(DataEnum { enum_token: input.enum_token, brace_token: input.brace_token, variants: input.variants, }), } } } impl From for DeriveInput { fn from(input: ItemUnion) -> DeriveInput { DeriveInput { attrs: input.attrs, vis: input.vis, ident: input.ident, generics: input.generics, data: Data::Union(DataUnion { union_token: input.union_token, fields: input.fields, }), } } } ast_enum_of_structs! { /// A suffix of an import tree in a `use` item: `Type as Renamed` or `*`. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub enum UseTree { /// A path prefix of imports in a `use` item: `std::...`. Path(UsePath), /// An identifier imported by a `use` item: `HashMap`. Name(UseName), /// An renamed identifier imported by a `use` item: `HashMap as Map`. Rename(UseRename), /// A glob import in a `use` item: `*`. Glob(UseGlob), /// A braced group of imports in a `use` item: `{A, B, C}`. Group(UseGroup), } } ast_struct! { /// A path prefix of imports in a `use` item: `std::...`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UsePath { pub ident: Ident, pub colon2_token: Token![::], pub tree: Box, } } ast_struct! { /// An identifier imported by a `use` item: `HashMap`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseName { pub ident: Ident, } } ast_struct! { /// An renamed identifier imported by a `use` item: `HashMap as Map`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseRename { pub ident: Ident, pub as_token: Token![as], pub rename: Ident, } } ast_struct! { /// A glob import in a `use` item: `*`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseGlob { pub star_token: Token![*], } } ast_struct! { /// A braced group of imports in a `use` item: `{A, B, C}`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct UseGroup { pub brace_token: token::Brace, pub items: Punctuated, } } ast_enum_of_structs! { /// An item within an `extern` block. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum ForeignItem { /// A foreign function in an `extern` block. Fn(ForeignItemFn), /// A foreign static item in an `extern` block: `static ext: u8`. Static(ForeignItemStatic), /// A foreign type in an `extern` block: `type void`. Type(ForeignItemType), /// A macro invocation within an extern block. Macro(ForeignItemMacro), /// Tokens in an `extern` block not interpreted by Syn. Verbatim(TokenStream), // For testing exhaustiveness in downstream code, use the following idiom: // // match item { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // ForeignItem::Fn(item) => {...} // ForeignItem::Static(item) => {...} // ... // ForeignItem::Verbatim(item) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// A foreign function in an `extern` block. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemFn { pub attrs: Vec, pub vis: Visibility, pub sig: Signature, pub semi_token: Token![;], } } ast_struct! { /// A foreign static item in an `extern` block: `static ext: u8`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemStatic { pub attrs: Vec, pub vis: Visibility, pub static_token: Token![static], pub mutability: StaticMutability, pub ident: Ident, pub colon_token: Token![:], pub ty: Box, pub semi_token: Token![;], } } ast_struct! { /// A foreign type in an `extern` block: `type void`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemType { pub attrs: Vec, pub vis: Visibility, pub type_token: Token![type], pub ident: Ident, pub generics: Generics, pub semi_token: Token![;], } } ast_struct! { /// A macro invocation within an extern block. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ForeignItemMacro { pub attrs: Vec, pub mac: Macro, pub semi_token: Option, } } ast_enum_of_structs! { /// An item declaration within the definition of a trait. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum TraitItem { /// An associated constant within the definition of a trait. Const(TraitItemConst), /// An associated function within the definition of a trait. Fn(TraitItemFn), /// An associated type within the definition of a trait. Type(TraitItemType), /// A macro invocation within the definition of a trait. Macro(TraitItemMacro), /// Tokens within the definition of a trait not interpreted by Syn. Verbatim(TokenStream), // For testing exhaustiveness in downstream code, use the following idiom: // // match item { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // TraitItem::Const(item) => {...} // TraitItem::Fn(item) => {...} // ... // TraitItem::Verbatim(item) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// An associated constant within the definition of a trait. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemConst { pub attrs: Vec, pub const_token: Token![const], pub ident: Ident, pub generics: Generics, pub colon_token: Token![:], pub ty: Type, pub default: Option<(Token![=], Expr)>, pub semi_token: Token![;], } } ast_struct! { /// An associated function within the definition of a trait. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemFn { pub attrs: Vec, pub sig: Signature, pub default: Option, pub semi_token: Option, } } ast_struct! { /// An associated type within the definition of a trait. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemType { pub attrs: Vec, pub type_token: Token![type], pub ident: Ident, pub generics: Generics, pub colon_token: Option, pub bounds: Punctuated, pub default: Option<(Token![=], Type)>, pub semi_token: Token![;], } } ast_struct! { /// A macro invocation within the definition of a trait. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct TraitItemMacro { pub attrs: Vec, pub mac: Macro, pub semi_token: Option, } } ast_enum_of_structs! { /// An item within an impl block. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum ImplItem { /// An associated constant within an impl block. Const(ImplItemConst), /// An associated function within an impl block. Fn(ImplItemFn), /// An associated type within an impl block. Type(ImplItemType), /// A macro invocation within an impl block. Macro(ImplItemMacro), /// Tokens within an impl block not interpreted by Syn. Verbatim(TokenStream), // For testing exhaustiveness in downstream code, use the following idiom: // // match item { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // ImplItem::Const(item) => {...} // ImplItem::Fn(item) => {...} // ... // ImplItem::Verbatim(item) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// An associated constant within an impl block. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemConst { pub attrs: Vec, pub vis: Visibility, pub defaultness: Option, pub const_token: Token![const], pub ident: Ident, pub generics: Generics, pub colon_token: Token![:], pub ty: Type, pub eq_token: Token![=], pub expr: Expr, pub semi_token: Token![;], } } ast_struct! { /// An associated function within an impl block. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemFn { pub attrs: Vec, pub vis: Visibility, pub defaultness: Option, pub sig: Signature, pub block: Block, } } ast_struct! { /// An associated type within an impl block. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemType { pub attrs: Vec, pub vis: Visibility, pub defaultness: Option, pub type_token: Token![type], pub ident: Ident, pub generics: Generics, pub eq_token: Token![=], pub ty: Type, pub semi_token: Token![;], } } ast_struct! { /// A macro invocation within an impl block. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ImplItemMacro { pub attrs: Vec, pub mac: Macro, pub semi_token: Option, } } ast_struct! { /// A function signature in a trait or implementation: `unsafe fn /// initialize(&self)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Signature { pub constness: Option, pub asyncness: Option, pub unsafety: Option, pub abi: Option, pub fn_token: Token![fn], pub ident: Ident, pub generics: Generics, pub paren_token: token::Paren, pub inputs: Punctuated, pub variadic: Option, pub output: ReturnType, } } impl Signature { /// A method's `self` receiver, such as `&self` or `self: Box`. pub fn receiver(&self) -> Option<&Receiver> { let arg = self.inputs.first()?; match arg { FnArg::Receiver(receiver) => Some(receiver), FnArg::Typed(_) => None, } } } ast_enum_of_structs! { /// An argument in a function signature: the `n: usize` in `fn f(n: usize)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub enum FnArg { /// The `self` argument of an associated method. Receiver(Receiver), /// A function argument accepted by pattern and type. Typed(PatType), } } ast_struct! { /// The `self` argument of an associated method. /// /// If `colon_token` is present, the receiver is written with an explicit /// type such as `self: Box`. If `colon_token` is absent, the receiver /// is written in shorthand such as `self` or `&self` or `&mut self`. In the /// shorthand case, the type in `ty` is reconstructed as one of `Self`, /// `&Self`, or `&mut Self`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Receiver { pub attrs: Vec, pub reference: Option<(Token![&], Option)>, pub mutability: Option, pub self_token: Token![self], pub colon_token: Option, pub ty: Box, } } impl Receiver { pub fn lifetime(&self) -> Option<&Lifetime> { self.reference.as_ref()?.1.as_ref() } } ast_struct! { /// The variadic argument of a foreign function. /// /// ```rust /// # struct c_char; /// # struct c_int; /// # /// extern "C" { /// fn printf(format: *const c_char, ...) -> c_int; /// // ^^^ /// } /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct Variadic { pub attrs: Vec, pub pat: Option<(Box, Token![:])>, pub dots: Token![...], pub comma: Option, } } ast_enum! { /// The mutability of an `Item::Static` or `ForeignItem::Static`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum StaticMutability { Mut(Token![mut]), None, } } ast_enum! { /// Unused, but reserved for RFC 3323 restrictions. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum ImplRestriction {} // TODO: https://rust-lang.github.io/rfcs/3323-restrictions.html // // pub struct ImplRestriction { // pub impl_token: Token![impl], // pub paren_token: token::Paren, // pub in_token: Option, // pub path: Box, // } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::{self, Attribute}; use crate::derive; use crate::error::{Error, Result}; use crate::expr::Expr; use crate::ext::IdentExt as _; use crate::generics::{Generics, TypeParamBound}; use crate::ident::Ident; use crate::item::{ FnArg, ForeignItem, ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItem, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, Signature, StaticMutability, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, UseTree, Variadic, }; use crate::lifetime::Lifetime; use crate::lit::LitStr; use crate::mac::{self, Macro}; use crate::parse::discouraged::Speculative as _; use crate::parse::{Parse, ParseBuffer, ParseStream}; use crate::pat::{Pat, PatType, PatWild}; use crate::path::Path; use crate::punctuated::Punctuated; use crate::restriction::Visibility; use crate::stmt::Block; use crate::token; use crate::ty::{Abi, ReturnType, Type, TypePath, TypeReference}; use crate::verbatim; use proc_macro2::TokenStream; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Item { fn parse(input: ParseStream) -> Result { let begin = input.fork(); let attrs = input.call(Attribute::parse_outer)?; parse_rest_of_item(begin, attrs, input) } } pub(crate) fn parse_rest_of_item( begin: ParseBuffer, mut attrs: Vec, input: ParseStream, ) -> Result { let ahead = input.fork(); let vis: Visibility = ahead.parse()?; let lookahead = ahead.lookahead1(); let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { let vis: Visibility = input.parse()?; let sig: Signature = input.parse()?; if input.peek(Token![;]) { input.parse::()?; Ok(Item::Verbatim(verbatim::between(&begin, input))) } else { parse_rest_of_fn(input, Vec::new(), vis, sig).map(Item::Fn) } } else if lookahead.peek(Token![extern]) { ahead.parse::()?; let lookahead = ahead.lookahead1(); if lookahead.peek(Token![crate]) { input.parse().map(Item::ExternCrate) } else if lookahead.peek(token::Brace) { input.parse().map(Item::ForeignMod) } else if lookahead.peek(LitStr) { ahead.parse::()?; let lookahead = ahead.lookahead1(); if lookahead.peek(token::Brace) { input.parse().map(Item::ForeignMod) } else { Err(lookahead.error()) } } else { Err(lookahead.error()) } } else if lookahead.peek(Token![use]) { let allow_crate_root_in_path = true; match parse_item_use(input, allow_crate_root_in_path)? { Some(item_use) => Ok(Item::Use(item_use)), None => Ok(Item::Verbatim(verbatim::between(&begin, input))), } } else if lookahead.peek(Token![static]) { let vis = input.parse()?; let static_token = input.parse()?; let mutability = input.parse()?; let ident = input.parse()?; if input.peek(Token![=]) { input.parse::()?; input.parse::()?; input.parse::()?; Ok(Item::Verbatim(verbatim::between(&begin, input))) } else { let colon_token = input.parse()?; let ty = input.parse()?; if input.peek(Token![;]) { input.parse::()?; Ok(Item::Verbatim(verbatim::between(&begin, input))) } else { Ok(Item::Static(ItemStatic { attrs: Vec::new(), vis, static_token, mutability, ident, colon_token, ty, eq_token: input.parse()?, expr: input.parse()?, semi_token: input.parse()?, })) } } } else if lookahead.peek(Token![const]) { let vis = input.parse()?; let const_token: Token![const] = input.parse()?; let lookahead = input.lookahead1(); let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) { input.call(Ident::parse_any)? } else { return Err(lookahead.error()); }; let mut generics: Generics = input.parse()?; let colon_token = input.parse()?; let ty = input.parse()?; let value = if let Some(eq_token) = input.parse::>()? { let expr: Expr = input.parse()?; Some((eq_token, expr)) } else { None }; generics.where_clause = input.parse()?; let semi_token: Token![;] = input.parse()?; match value { Some((eq_token, expr)) if generics.lt_token.is_none() && generics.where_clause.is_none() => { Ok(Item::Const(ItemConst { attrs: Vec::new(), vis, const_token, ident, generics, colon_token, ty, eq_token, expr: Box::new(expr), semi_token, })) } _ => Ok(Item::Verbatim(verbatim::between(&begin, input))), } } else if lookahead.peek(Token![unsafe]) { ahead.parse::()?; let lookahead = ahead.lookahead1(); if lookahead.peek(Token![trait]) || lookahead.peek(Token![auto]) && ahead.peek2(Token![trait]) { input.parse().map(Item::Trait) } else if lookahead.peek(Token![impl]) { let allow_verbatim_impl = true; if let Some(item) = parse_impl(input, allow_verbatim_impl)? { Ok(Item::Impl(item)) } else { Ok(Item::Verbatim(verbatim::between(&begin, input))) } } else if lookahead.peek(Token![extern]) { input.parse().map(Item::ForeignMod) } else if lookahead.peek(Token![mod]) { input.parse().map(Item::Mod) } else { Err(lookahead.error()) } } else if lookahead.peek(Token![mod]) { input.parse().map(Item::Mod) } else if lookahead.peek(Token![type]) { parse_item_type(begin, input) } else if lookahead.peek(Token![struct]) { input.parse().map(Item::Struct) } else if lookahead.peek(Token![enum]) { input.parse().map(Item::Enum) } else if lookahead.peek(Token![union]) && ahead.peek2(Ident) { input.parse().map(Item::Union) } else if lookahead.peek(Token![trait]) { input.call(parse_trait_or_trait_alias) } else if lookahead.peek(Token![auto]) && ahead.peek2(Token![trait]) { input.parse().map(Item::Trait) } else if lookahead.peek(Token![impl]) || lookahead.peek(Token![default]) && !ahead.peek2(Token![!]) { let allow_verbatim_impl = true; if let Some(item) = parse_impl(input, allow_verbatim_impl)? { Ok(Item::Impl(item)) } else { Ok(Item::Verbatim(verbatim::between(&begin, input))) } } else if lookahead.peek(Token![macro]) { input.advance_to(&ahead); parse_macro2(begin, vis, input) } else if vis.is_inherited() && (lookahead.peek(Ident) || lookahead.peek(Token![self]) || lookahead.peek(Token![super]) || lookahead.peek(Token![crate]) || lookahead.peek(Token![::])) { input.parse().map(Item::Macro) } else { Err(lookahead.error()) }?; attrs.extend(item.replace_attrs(Vec::new())); item.replace_attrs(attrs); Ok(item) } struct FlexibleItemType { vis: Visibility, defaultness: Option, type_token: Token![type], ident: Ident, generics: Generics, colon_token: Option, bounds: Punctuated, ty: Option<(Token![=], Type)>, semi_token: Token![;], } enum TypeDefaultness { Optional, Disallowed, } enum WhereClauseLocation { // type Ty where T: 'static = T; BeforeEq, // type Ty = T where T: 'static; AfterEq, // TODO: goes away once the migration period on rust-lang/rust#89122 is over Both, } impl FlexibleItemType { fn parse( input: ParseStream, allow_defaultness: TypeDefaultness, where_clause_location: WhereClauseLocation, ) -> Result { let vis: Visibility = input.parse()?; let defaultness: Option = match allow_defaultness { TypeDefaultness::Optional => input.parse()?, TypeDefaultness::Disallowed => None, }; let type_token: Token![type] = input.parse()?; let ident: Ident = input.parse()?; let mut generics: Generics = input.parse()?; let (colon_token, bounds) = Self::parse_optional_bounds(input)?; match where_clause_location { WhereClauseLocation::BeforeEq | WhereClauseLocation::Both => { generics.where_clause = input.parse()?; } WhereClauseLocation::AfterEq => {} } let ty = Self::parse_optional_definition(input)?; match where_clause_location { WhereClauseLocation::AfterEq | WhereClauseLocation::Both if generics.where_clause.is_none() => { generics.where_clause = input.parse()?; } _ => {} } let semi_token: Token![;] = input.parse()?; Ok(FlexibleItemType { vis, defaultness, type_token, ident, generics, colon_token, bounds, ty, semi_token, }) } fn parse_optional_bounds( input: ParseStream, ) -> Result<(Option, Punctuated)> { let colon_token: Option = input.parse()?; let mut bounds = Punctuated::new(); if colon_token.is_some() { loop { if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) { break; } bounds.push_value(input.parse::()?); if input.peek(Token![where]) || input.peek(Token![=]) || input.peek(Token![;]) { break; } bounds.push_punct(input.parse::()?); } } Ok((colon_token, bounds)) } fn parse_optional_definition(input: ParseStream) -> Result> { let eq_token: Option = input.parse()?; if let Some(eq_token) = eq_token { let definition: Type = input.parse()?; Ok(Some((eq_token, definition))) } else { Ok(None) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let path = input.call(Path::parse_mod_style)?; let bang_token: Token![!] = input.parse()?; let ident: Option = if input.peek(Token![try]) { input.call(Ident::parse_any).map(Some) } else { input.parse() }?; let (delimiter, tokens) = input.call(mac::parse_delimiter)?; let semi_token: Option = if !delimiter.is_brace() { Some(input.parse()?) } else { None }; Ok(ItemMacro { attrs, ident, mac: Macro { path, bang_token, delimiter, tokens, }, semi_token, }) } } fn parse_macro2(begin: ParseBuffer, _vis: Visibility, input: ParseStream) -> Result { input.parse::()?; input.parse::()?; let mut lookahead = input.lookahead1(); if lookahead.peek(token::Paren) { let paren_content; parenthesized!(paren_content in input); paren_content.parse::()?; lookahead = input.lookahead1(); } if lookahead.peek(token::Brace) { let brace_content; braced!(brace_content in input); brace_content.parse::()?; } else { return Err(lookahead.error()); } Ok(Item::Verbatim(verbatim::between(&begin, input))) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemExternCrate { fn parse(input: ParseStream) -> Result { Ok(ItemExternCrate { attrs: input.call(Attribute::parse_outer)?, vis: input.parse()?, extern_token: input.parse()?, crate_token: input.parse()?, ident: { if input.peek(Token![self]) { input.call(Ident::parse_any)? } else { input.parse()? } }, rename: { if input.peek(Token![as]) { let as_token: Token![as] = input.parse()?; let rename: Ident = if input.peek(Token![_]) { Ident::from(input.parse::()?) } else { input.parse()? }; Some((as_token, rename)) } else { None } }, semi_token: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemUse { fn parse(input: ParseStream) -> Result { let allow_crate_root_in_path = false; parse_item_use(input, allow_crate_root_in_path).map(Option::unwrap) } } fn parse_item_use( input: ParseStream, allow_crate_root_in_path: bool, ) -> Result> { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let use_token: Token![use] = input.parse()?; let leading_colon: Option = input.parse()?; let tree = parse_use_tree(input, allow_crate_root_in_path && leading_colon.is_none())?; let semi_token: Token![;] = input.parse()?; let tree = match tree { Some(tree) => tree, None => return Ok(None), }; Ok(Some(ItemUse { attrs, vis, use_token, leading_colon, tree, semi_token, })) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for UseTree { fn parse(input: ParseStream) -> Result { let allow_crate_root_in_path = false; parse_use_tree(input, allow_crate_root_in_path).map(Option::unwrap) } } fn parse_use_tree( input: ParseStream, allow_crate_root_in_path: bool, ) -> Result> { let lookahead = input.lookahead1(); if lookahead.peek(Ident) || lookahead.peek(Token![self]) || lookahead.peek(Token![super]) || lookahead.peek(Token![crate]) || lookahead.peek(Token![try]) { let ident = input.call(Ident::parse_any)?; if input.peek(Token![::]) { Ok(Some(UseTree::Path(UsePath { ident, colon2_token: input.parse()?, tree: Box::new(input.parse()?), }))) } else if input.peek(Token![as]) { Ok(Some(UseTree::Rename(UseRename { ident, as_token: input.parse()?, rename: { if input.peek(Ident) { input.parse()? } else if input.peek(Token![_]) { Ident::from(input.parse::()?) } else { return Err(input.error("expected identifier or underscore")); } }, }))) } else { Ok(Some(UseTree::Name(UseName { ident }))) } } else if lookahead.peek(Token![*]) { Ok(Some(UseTree::Glob(UseGlob { star_token: input.parse()?, }))) } else if lookahead.peek(token::Brace) { let content; let brace_token = braced!(content in input); let mut items = Punctuated::new(); let mut has_any_crate_root_in_path = false; loop { if content.is_empty() { break; } let this_tree_starts_with_crate_root = allow_crate_root_in_path && content.parse::>()?.is_some(); has_any_crate_root_in_path |= this_tree_starts_with_crate_root; match parse_use_tree( &content, allow_crate_root_in_path && !this_tree_starts_with_crate_root, )? { Some(tree) => items.push_value(tree), None => has_any_crate_root_in_path = true, } if content.is_empty() { break; } let comma: Token![,] = content.parse()?; items.push_punct(comma); } if has_any_crate_root_in_path { Ok(None) } else { Ok(Some(UseTree::Group(UseGroup { brace_token, items }))) } } else { Err(lookahead.error()) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemStatic { fn parse(input: ParseStream) -> Result { Ok(ItemStatic { attrs: input.call(Attribute::parse_outer)?, vis: input.parse()?, static_token: input.parse()?, mutability: input.parse()?, ident: input.parse()?, colon_token: input.parse()?, ty: input.parse()?, eq_token: input.parse()?, expr: input.parse()?, semi_token: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemConst { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let const_token: Token![const] = input.parse()?; let lookahead = input.lookahead1(); let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) { input.call(Ident::parse_any)? } else { return Err(lookahead.error()); }; let colon_token: Token![:] = input.parse()?; let ty: Type = input.parse()?; let eq_token: Token![=] = input.parse()?; let expr: Expr = input.parse()?; let semi_token: Token![;] = input.parse()?; Ok(ItemConst { attrs, vis, const_token, ident, generics: Generics::default(), colon_token, ty: Box::new(ty), eq_token, expr: Box::new(expr), semi_token, }) } } fn peek_signature(input: ParseStream) -> bool { let fork = input.fork(); fork.parse::>().is_ok() && fork.parse::>().is_ok() && fork.parse::>().is_ok() && fork.parse::>().is_ok() && fork.peek(Token![fn]) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Signature { fn parse(input: ParseStream) -> Result { let constness: Option = input.parse()?; let asyncness: Option = input.parse()?; let unsafety: Option = input.parse()?; let abi: Option = input.parse()?; let fn_token: Token![fn] = input.parse()?; let ident: Ident = input.parse()?; let mut generics: Generics = input.parse()?; let content; let paren_token = parenthesized!(content in input); let (inputs, variadic) = parse_fn_args(&content)?; let output: ReturnType = input.parse()?; generics.where_clause = input.parse()?; Ok(Signature { constness, asyncness, unsafety, abi, fn_token, ident, generics, paren_token, inputs, variadic, output, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemFn { fn parse(input: ParseStream) -> Result { let outer_attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let sig: Signature = input.parse()?; parse_rest_of_fn(input, outer_attrs, vis, sig) } } fn parse_rest_of_fn( input: ParseStream, mut attrs: Vec, vis: Visibility, sig: Signature, ) -> Result { let content; let brace_token = braced!(content in input); attr::parsing::parse_inner(&content, &mut attrs)?; let stmts = content.call(Block::parse_within)?; Ok(ItemFn { attrs, vis, sig, block: Box::new(Block { brace_token, stmts }), }) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for FnArg { fn parse(input: ParseStream) -> Result { let allow_variadic = false; let attrs = input.call(Attribute::parse_outer)?; match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? { FnArgOrVariadic::FnArg(arg) => Ok(arg), FnArgOrVariadic::Variadic(_) => unreachable!(), } } } enum FnArgOrVariadic { FnArg(FnArg), Variadic(Variadic), } fn parse_fn_arg_or_variadic( input: ParseStream, attrs: Vec, allow_variadic: bool, ) -> Result { let ahead = input.fork(); if let Ok(mut receiver) = ahead.parse::() { input.advance_to(&ahead); receiver.attrs = attrs; return Ok(FnArgOrVariadic::FnArg(FnArg::Receiver(receiver))); } // Hack to parse pre-2018 syntax in // test/ui/rfc-2565-param-attrs/param-attrs-pretty.rs // because the rest of the test case is valuable. if input.peek(Ident) && input.peek2(Token![<]) { let span = input.fork().parse::()?.span(); return Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType { attrs, pat: Box::new(Pat::Wild(PatWild { attrs: Vec::new(), underscore_token: Token![_](span), })), colon_token: Token![:](span), ty: input.parse()?, }))); } let pat = Box::new(Pat::parse_single(input)?); let colon_token: Token![:] = input.parse()?; if allow_variadic { if let Some(dots) = input.parse::>()? { return Ok(FnArgOrVariadic::Variadic(Variadic { attrs, pat: Some((pat, colon_token)), dots, comma: None, })); } } Ok(FnArgOrVariadic::FnArg(FnArg::Typed(PatType { attrs, pat, colon_token, ty: input.parse()?, }))) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Receiver { fn parse(input: ParseStream) -> Result { let reference = if input.peek(Token![&]) { let ampersand: Token![&] = input.parse()?; let lifetime: Option = input.parse()?; Some((ampersand, lifetime)) } else { None }; let mutability: Option = input.parse()?; let self_token: Token![self] = input.parse()?; let colon_token: Option = if reference.is_some() { None } else { input.parse()? }; let ty: Type = if colon_token.is_some() { input.parse()? } else { let mut ty = Type::Path(TypePath { qself: None, path: Path::from(Ident::new("Self", self_token.span)), }); if let Some((ampersand, lifetime)) = reference.as_ref() { ty = Type::Reference(TypeReference { and_token: Token![&](ampersand.span), lifetime: lifetime.clone(), mutability: mutability.as_ref().map(|m| Token![mut](m.span)), elem: Box::new(ty), }); } ty }; Ok(Receiver { attrs: Vec::new(), reference, mutability, self_token, colon_token, ty: Box::new(ty), }) } } fn parse_fn_args( input: ParseStream, ) -> Result<(Punctuated, Option)> { let mut args = Punctuated::new(); let mut variadic = None; let mut has_receiver = false; while !input.is_empty() { let attrs = input.call(Attribute::parse_outer)?; if let Some(dots) = input.parse::>()? { variadic = Some(Variadic { attrs, pat: None, dots, comma: if input.is_empty() { None } else { Some(input.parse()?) }, }); break; } let allow_variadic = true; let arg = match parse_fn_arg_or_variadic(input, attrs, allow_variadic)? { FnArgOrVariadic::FnArg(arg) => arg, FnArgOrVariadic::Variadic(arg) => { variadic = Some(Variadic { comma: if input.is_empty() { None } else { Some(input.parse()?) }, ..arg }); break; } }; match &arg { FnArg::Receiver(receiver) if has_receiver => { return Err(Error::new( receiver.self_token.span, "unexpected second method receiver", )); } FnArg::Receiver(receiver) if !args.is_empty() => { return Err(Error::new( receiver.self_token.span, "unexpected method receiver", )); } FnArg::Receiver(_) => has_receiver = true, FnArg::Typed(_) => {} } args.push_value(arg); if input.is_empty() { break; } let comma: Token![,] = input.parse()?; args.push_punct(comma); } Ok((args, variadic)) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemMod { fn parse(input: ParseStream) -> Result { let mut attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let unsafety: Option = input.parse()?; let mod_token: Token![mod] = input.parse()?; let ident: Ident = if input.peek(Token![try]) { input.call(Ident::parse_any) } else { input.parse() }?; let lookahead = input.lookahead1(); if lookahead.peek(Token![;]) { Ok(ItemMod { attrs, vis, unsafety, mod_token, ident, content: None, semi: Some(input.parse()?), }) } else if lookahead.peek(token::Brace) { let content; let brace_token = braced!(content in input); attr::parsing::parse_inner(&content, &mut attrs)?; let mut items = Vec::new(); while !content.is_empty() { items.push(content.parse()?); } Ok(ItemMod { attrs, vis, unsafety, mod_token, ident, content: Some((brace_token, items)), semi: None, }) } else { Err(lookahead.error()) } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemForeignMod { fn parse(input: ParseStream) -> Result { let mut attrs = input.call(Attribute::parse_outer)?; let unsafety: Option = input.parse()?; let abi: Abi = input.parse()?; let content; let brace_token = braced!(content in input); attr::parsing::parse_inner(&content, &mut attrs)?; let mut items = Vec::new(); while !content.is_empty() { items.push(content.parse()?); } Ok(ItemForeignMod { attrs, unsafety, abi, brace_token, items, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItem { fn parse(input: ParseStream) -> Result { let begin = input.fork(); let mut attrs = input.call(Attribute::parse_outer)?; let ahead = input.fork(); let vis: Visibility = ahead.parse()?; let lookahead = ahead.lookahead1(); let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { let vis: Visibility = input.parse()?; let sig: Signature = input.parse()?; if input.peek(token::Brace) { let content; braced!(content in input); content.call(Attribute::parse_inner)?; content.call(Block::parse_within)?; Ok(ForeignItem::Verbatim(verbatim::between(&begin, input))) } else { Ok(ForeignItem::Fn(ForeignItemFn { attrs: Vec::new(), vis, sig, semi_token: input.parse()?, })) } } else if lookahead.peek(Token![static]) { let vis = input.parse()?; let static_token = input.parse()?; let mutability = input.parse()?; let ident = input.parse()?; let colon_token = input.parse()?; let ty = input.parse()?; if input.peek(Token![=]) { input.parse::()?; input.parse::()?; input.parse::()?; Ok(ForeignItem::Verbatim(verbatim::between(&begin, input))) } else { Ok(ForeignItem::Static(ForeignItemStatic { attrs: Vec::new(), vis, static_token, mutability, ident, colon_token, ty, semi_token: input.parse()?, })) } } else if lookahead.peek(Token![type]) { parse_foreign_item_type(begin, input) } else if vis.is_inherited() && (lookahead.peek(Ident) || lookahead.peek(Token![self]) || lookahead.peek(Token![super]) || lookahead.peek(Token![crate]) || lookahead.peek(Token![::])) { input.parse().map(ForeignItem::Macro) } else { Err(lookahead.error()) }?; let item_attrs = match &mut item { ForeignItem::Fn(item) => &mut item.attrs, ForeignItem::Static(item) => &mut item.attrs, ForeignItem::Type(item) => &mut item.attrs, ForeignItem::Macro(item) => &mut item.attrs, ForeignItem::Verbatim(_) => return Ok(item), }; attrs.append(item_attrs); *item_attrs = attrs; Ok(item) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemFn { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let sig: Signature = input.parse()?; let semi_token: Token![;] = input.parse()?; Ok(ForeignItemFn { attrs, vis, sig, semi_token, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemStatic { fn parse(input: ParseStream) -> Result { Ok(ForeignItemStatic { attrs: input.call(Attribute::parse_outer)?, vis: input.parse()?, static_token: input.parse()?, mutability: input.parse()?, ident: input.parse()?, colon_token: input.parse()?, ty: input.parse()?, semi_token: input.parse()?, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemType { fn parse(input: ParseStream) -> Result { Ok(ForeignItemType { attrs: input.call(Attribute::parse_outer)?, vis: input.parse()?, type_token: input.parse()?, ident: input.parse()?, generics: { let mut generics: Generics = input.parse()?; generics.where_clause = input.parse()?; generics }, semi_token: input.parse()?, }) } } fn parse_foreign_item_type(begin: ParseBuffer, input: ParseStream) -> Result { let FlexibleItemType { vis, defaultness: _, type_token, ident, generics, colon_token, bounds: _, ty, semi_token, } = FlexibleItemType::parse( input, TypeDefaultness::Disallowed, WhereClauseLocation::Both, )?; if colon_token.is_some() || ty.is_some() { Ok(ForeignItem::Verbatim(verbatim::between(&begin, input))) } else { Ok(ForeignItem::Type(ForeignItemType { attrs: Vec::new(), vis, type_token, ident, generics, semi_token, })) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ForeignItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let mac: Macro = input.parse()?; let semi_token: Option = if mac.delimiter.is_brace() { None } else { Some(input.parse()?) }; Ok(ForeignItemMacro { attrs, mac, semi_token, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemType { fn parse(input: ParseStream) -> Result { Ok(ItemType { attrs: input.call(Attribute::parse_outer)?, vis: input.parse()?, type_token: input.parse()?, ident: input.parse()?, generics: { let mut generics: Generics = input.parse()?; generics.where_clause = input.parse()?; generics }, eq_token: input.parse()?, ty: input.parse()?, semi_token: input.parse()?, }) } } fn parse_item_type(begin: ParseBuffer, input: ParseStream) -> Result { let FlexibleItemType { vis, defaultness: _, type_token, ident, generics, colon_token, bounds: _, ty, semi_token, } = FlexibleItemType::parse( input, TypeDefaultness::Disallowed, WhereClauseLocation::BeforeEq, )?; let (eq_token, ty) = match ty { Some(ty) if colon_token.is_none() => ty, _ => return Ok(Item::Verbatim(verbatim::between(&begin, input))), }; Ok(Item::Type(ItemType { attrs: Vec::new(), vis, type_token, ident, generics, eq_token, ty: Box::new(ty), semi_token, })) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemStruct { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis = input.parse::()?; let struct_token = input.parse::()?; let ident = input.parse::()?; let generics = input.parse::()?; let (where_clause, fields, semi_token) = derive::parsing::data_struct(input)?; Ok(ItemStruct { attrs, vis, struct_token, ident, generics: Generics { where_clause, ..generics }, fields, semi_token, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemEnum { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis = input.parse::()?; let enum_token = input.parse::()?; let ident = input.parse::()?; let generics = input.parse::()?; let (where_clause, brace_token, variants) = derive::parsing::data_enum(input)?; Ok(ItemEnum { attrs, vis, enum_token, ident, generics: Generics { where_clause, ..generics }, brace_token, variants, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemUnion { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis = input.parse::()?; let union_token = input.parse::()?; let ident = input.parse::()?; let generics = input.parse::()?; let (where_clause, fields) = derive::parsing::data_union(input)?; Ok(ItemUnion { attrs, vis, union_token, ident, generics: Generics { where_clause, ..generics }, fields, }) } } fn parse_trait_or_trait_alias(input: ParseStream) -> Result { let (attrs, vis, trait_token, ident, generics) = parse_start_of_trait_alias(input)?; let lookahead = input.lookahead1(); if lookahead.peek(token::Brace) || lookahead.peek(Token![:]) || lookahead.peek(Token![where]) { let unsafety = None; let auto_token = None; parse_rest_of_trait( input, attrs, vis, unsafety, auto_token, trait_token, ident, generics, ) .map(Item::Trait) } else if lookahead.peek(Token![=]) { parse_rest_of_trait_alias(input, attrs, vis, trait_token, ident, generics) .map(Item::TraitAlias) } else { Err(lookahead.error()) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemTrait { fn parse(input: ParseStream) -> Result { let outer_attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let unsafety: Option = input.parse()?; let auto_token: Option = input.parse()?; let trait_token: Token![trait] = input.parse()?; let ident: Ident = input.parse()?; let generics: Generics = input.parse()?; parse_rest_of_trait( input, outer_attrs, vis, unsafety, auto_token, trait_token, ident, generics, ) } } fn parse_rest_of_trait( input: ParseStream, mut attrs: Vec, vis: Visibility, unsafety: Option, auto_token: Option, trait_token: Token![trait], ident: Ident, mut generics: Generics, ) -> Result { let colon_token: Option = input.parse()?; let mut supertraits = Punctuated::new(); if colon_token.is_some() { loop { if input.peek(Token![where]) || input.peek(token::Brace) { break; } supertraits.push_value(input.parse()?); if input.peek(Token![where]) || input.peek(token::Brace) { break; } supertraits.push_punct(input.parse()?); } } generics.where_clause = input.parse()?; let content; let brace_token = braced!(content in input); attr::parsing::parse_inner(&content, &mut attrs)?; let mut items = Vec::new(); while !content.is_empty() { items.push(content.parse()?); } Ok(ItemTrait { attrs, vis, unsafety, auto_token, restriction: None, trait_token, ident, generics, colon_token, supertraits, brace_token, items, }) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemTraitAlias { fn parse(input: ParseStream) -> Result { let (attrs, vis, trait_token, ident, generics) = parse_start_of_trait_alias(input)?; parse_rest_of_trait_alias(input, attrs, vis, trait_token, ident, generics) } } fn parse_start_of_trait_alias( input: ParseStream, ) -> Result<(Vec, Visibility, Token![trait], Ident, Generics)> { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let trait_token: Token![trait] = input.parse()?; let ident: Ident = input.parse()?; let generics: Generics = input.parse()?; Ok((attrs, vis, trait_token, ident, generics)) } fn parse_rest_of_trait_alias( input: ParseStream, attrs: Vec, vis: Visibility, trait_token: Token![trait], ident: Ident, mut generics: Generics, ) -> Result { let eq_token: Token![=] = input.parse()?; let mut bounds = Punctuated::new(); loop { if input.peek(Token![where]) || input.peek(Token![;]) { break; } bounds.push_value(input.parse()?); if input.peek(Token![where]) || input.peek(Token![;]) { break; } bounds.push_punct(input.parse()?); } generics.where_clause = input.parse()?; let semi_token: Token![;] = input.parse()?; Ok(ItemTraitAlias { attrs, vis, trait_token, ident, generics, eq_token, bounds, semi_token, }) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItem { fn parse(input: ParseStream) -> Result { let begin = input.fork(); let mut attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let defaultness: Option = input.parse()?; let ahead = input.fork(); let lookahead = ahead.lookahead1(); let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { input.parse().map(TraitItem::Fn) } else if lookahead.peek(Token![const]) { let const_token: Token![const] = ahead.parse()?; let lookahead = ahead.lookahead1(); if lookahead.peek(Ident) || lookahead.peek(Token![_]) { input.advance_to(&ahead); let ident = input.call(Ident::parse_any)?; let mut generics: Generics = input.parse()?; let colon_token: Token![:] = input.parse()?; let ty: Type = input.parse()?; let default = if let Some(eq_token) = input.parse::>()? { let expr: Expr = input.parse()?; Some((eq_token, expr)) } else { None }; generics.where_clause = input.parse()?; let semi_token: Token![;] = input.parse()?; if generics.lt_token.is_none() && generics.where_clause.is_none() { Ok(TraitItem::Const(TraitItemConst { attrs: Vec::new(), const_token, ident, generics, colon_token, ty, default, semi_token, })) } else { return Ok(TraitItem::Verbatim(verbatim::between(&begin, input))); } } else if lookahead.peek(Token![async]) || lookahead.peek(Token![unsafe]) || lookahead.peek(Token![extern]) || lookahead.peek(Token![fn]) { input.parse().map(TraitItem::Fn) } else { Err(lookahead.error()) } } else if lookahead.peek(Token![type]) { parse_trait_item_type(begin.fork(), input) } else if vis.is_inherited() && defaultness.is_none() && (lookahead.peek(Ident) || lookahead.peek(Token![self]) || lookahead.peek(Token![super]) || lookahead.peek(Token![crate]) || lookahead.peek(Token![::])) { input.parse().map(TraitItem::Macro) } else { Err(lookahead.error()) }?; match (vis, defaultness) { (Visibility::Inherited, None) => {} _ => return Ok(TraitItem::Verbatim(verbatim::between(&begin, input))), } let item_attrs = match &mut item { TraitItem::Const(item) => &mut item.attrs, TraitItem::Fn(item) => &mut item.attrs, TraitItem::Type(item) => &mut item.attrs, TraitItem::Macro(item) => &mut item.attrs, TraitItem::Verbatim(_) => unreachable!(), }; attrs.append(item_attrs); *item_attrs = attrs; Ok(item) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemConst { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let const_token: Token![const] = input.parse()?; let lookahead = input.lookahead1(); let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) { input.call(Ident::parse_any)? } else { return Err(lookahead.error()); }; let colon_token: Token![:] = input.parse()?; let ty: Type = input.parse()?; let default = if input.peek(Token![=]) { let eq_token: Token![=] = input.parse()?; let default: Expr = input.parse()?; Some((eq_token, default)) } else { None }; let semi_token: Token![;] = input.parse()?; Ok(TraitItemConst { attrs, const_token, ident, generics: Generics::default(), colon_token, ty, default, semi_token, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemFn { fn parse(input: ParseStream) -> Result { let mut attrs = input.call(Attribute::parse_outer)?; let sig: Signature = input.parse()?; let lookahead = input.lookahead1(); let (brace_token, stmts, semi_token) = if lookahead.peek(token::Brace) { let content; let brace_token = braced!(content in input); attr::parsing::parse_inner(&content, &mut attrs)?; let stmts = content.call(Block::parse_within)?; (Some(brace_token), stmts, None) } else if lookahead.peek(Token![;]) { let semi_token: Token![;] = input.parse()?; (None, Vec::new(), Some(semi_token)) } else { return Err(lookahead.error()); }; Ok(TraitItemFn { attrs, sig, default: brace_token.map(|brace_token| Block { brace_token, stmts }), semi_token, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemType { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let type_token: Token![type] = input.parse()?; let ident: Ident = input.parse()?; let mut generics: Generics = input.parse()?; let (colon_token, bounds) = FlexibleItemType::parse_optional_bounds(input)?; let default = FlexibleItemType::parse_optional_definition(input)?; generics.where_clause = input.parse()?; let semi_token: Token![;] = input.parse()?; Ok(TraitItemType { attrs, type_token, ident, generics, colon_token, bounds, default, semi_token, }) } } fn parse_trait_item_type(begin: ParseBuffer, input: ParseStream) -> Result { let FlexibleItemType { vis, defaultness: _, type_token, ident, generics, colon_token, bounds, ty, semi_token, } = FlexibleItemType::parse( input, TypeDefaultness::Disallowed, WhereClauseLocation::AfterEq, )?; if vis.is_some() { Ok(TraitItem::Verbatim(verbatim::between(&begin, input))) } else { Ok(TraitItem::Type(TraitItemType { attrs: Vec::new(), type_token, ident, generics, colon_token, bounds, default: ty, semi_token, })) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TraitItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let mac: Macro = input.parse()?; let semi_token: Option = if mac.delimiter.is_brace() { None } else { Some(input.parse()?) }; Ok(TraitItemMacro { attrs, mac, semi_token, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ItemImpl { fn parse(input: ParseStream) -> Result { let allow_verbatim_impl = false; parse_impl(input, allow_verbatim_impl).map(Option::unwrap) } } fn parse_impl(input: ParseStream, allow_verbatim_impl: bool) -> Result> { let mut attrs = input.call(Attribute::parse_outer)?; let has_visibility = allow_verbatim_impl && input.parse::()?.is_some(); let defaultness: Option = input.parse()?; let unsafety: Option = input.parse()?; let impl_token: Token![impl] = input.parse()?; let has_generics = input.peek(Token![<]) && (input.peek2(Token![>]) || input.peek2(Token![#]) || (input.peek2(Ident) || input.peek2(Lifetime)) && (input.peek3(Token![:]) || input.peek3(Token![,]) || input.peek3(Token![>]) || input.peek3(Token![=])) || input.peek2(Token![const])); let mut generics: Generics = if has_generics { input.parse()? } else { Generics::default() }; let is_const_impl = allow_verbatim_impl && (input.peek(Token![const]) || input.peek(Token![?]) && input.peek2(Token![const])); if is_const_impl { input.parse::>()?; input.parse::()?; } let begin = input.fork(); let polarity = if input.peek(Token![!]) && !input.peek2(token::Brace) { Some(input.parse::()?) } else { None }; #[cfg(not(feature = "printing"))] let first_ty_span = input.span(); let mut first_ty: Type = input.parse()?; let self_ty: Type; let trait_; let is_impl_for = input.peek(Token![for]); if is_impl_for { let for_token: Token![for] = input.parse()?; let mut first_ty_ref = &first_ty; while let Type::Group(ty) = first_ty_ref { first_ty_ref = &ty.elem; } if let Type::Path(TypePath { qself: None, .. }) = first_ty_ref { while let Type::Group(ty) = first_ty { first_ty = *ty.elem; } if let Type::Path(TypePath { qself: None, path }) = first_ty { trait_ = Some((polarity, path, for_token)); } else { unreachable!(); } } else if !allow_verbatim_impl { #[cfg(feature = "printing")] return Err(Error::new_spanned(first_ty_ref, "expected trait path")); #[cfg(not(feature = "printing"))] return Err(Error::new(first_ty_span, "expected trait path")); } else { trait_ = None; } self_ty = input.parse()?; } else { trait_ = None; self_ty = if polarity.is_none() { first_ty } else { Type::Verbatim(verbatim::between(&begin, input)) }; } generics.where_clause = input.parse()?; let content; let brace_token = braced!(content in input); attr::parsing::parse_inner(&content, &mut attrs)?; let mut items = Vec::new(); while !content.is_empty() { items.push(content.parse()?); } if has_visibility || is_const_impl || is_impl_for && trait_.is_none() { Ok(None) } else { Ok(Some(ItemImpl { attrs, defaultness, unsafety, impl_token, generics, trait_, self_ty: Box::new(self_ty), brace_token, items, })) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItem { fn parse(input: ParseStream) -> Result { let begin = input.fork(); let mut attrs = input.call(Attribute::parse_outer)?; let ahead = input.fork(); let vis: Visibility = ahead.parse()?; let mut lookahead = ahead.lookahead1(); let defaultness = if lookahead.peek(Token![default]) && !ahead.peek2(Token![!]) { let defaultness: Token![default] = ahead.parse()?; lookahead = ahead.lookahead1(); Some(defaultness) } else { None }; let mut item = if lookahead.peek(Token![fn]) || peek_signature(&ahead) { let allow_omitted_body = true; if let Some(item) = parse_impl_item_fn(input, allow_omitted_body)? { Ok(ImplItem::Fn(item)) } else { Ok(ImplItem::Verbatim(verbatim::between(&begin, input))) } } else if lookahead.peek(Token![const]) { input.advance_to(&ahead); let const_token: Token![const] = input.parse()?; let lookahead = input.lookahead1(); let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) { input.call(Ident::parse_any)? } else { return Err(lookahead.error()); }; let mut generics: Generics = input.parse()?; let colon_token: Token![:] = input.parse()?; let ty: Type = input.parse()?; let value = if let Some(eq_token) = input.parse::>()? { let expr: Expr = input.parse()?; Some((eq_token, expr)) } else { None }; generics.where_clause = input.parse()?; let semi_token: Token![;] = input.parse()?; return match value { Some((eq_token, expr)) if generics.lt_token.is_none() && generics.where_clause.is_none() => { Ok(ImplItem::Const(ImplItemConst { attrs, vis, defaultness, const_token, ident, generics, colon_token, ty, eq_token, expr, semi_token, })) } _ => Ok(ImplItem::Verbatim(verbatim::between(&begin, input))), }; } else if lookahead.peek(Token![type]) { parse_impl_item_type(begin, input) } else if vis.is_inherited() && defaultness.is_none() && (lookahead.peek(Ident) || lookahead.peek(Token![self]) || lookahead.peek(Token![super]) || lookahead.peek(Token![crate]) || lookahead.peek(Token![::])) { input.parse().map(ImplItem::Macro) } else { Err(lookahead.error()) }?; { let item_attrs = match &mut item { ImplItem::Const(item) => &mut item.attrs, ImplItem::Fn(item) => &mut item.attrs, ImplItem::Type(item) => &mut item.attrs, ImplItem::Macro(item) => &mut item.attrs, ImplItem::Verbatim(_) => return Ok(item), }; attrs.append(item_attrs); *item_attrs = attrs; } Ok(item) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemConst { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let defaultness: Option = input.parse()?; let const_token: Token![const] = input.parse()?; let lookahead = input.lookahead1(); let ident = if lookahead.peek(Ident) || lookahead.peek(Token![_]) { input.call(Ident::parse_any)? } else { return Err(lookahead.error()); }; let colon_token: Token![:] = input.parse()?; let ty: Type = input.parse()?; let eq_token: Token![=] = input.parse()?; let expr: Expr = input.parse()?; let semi_token: Token![;] = input.parse()?; Ok(ImplItemConst { attrs, vis, defaultness, const_token, ident, generics: Generics::default(), colon_token, ty, eq_token, expr, semi_token, }) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemFn { fn parse(input: ParseStream) -> Result { let allow_omitted_body = false; parse_impl_item_fn(input, allow_omitted_body).map(Option::unwrap) } } fn parse_impl_item_fn( input: ParseStream, allow_omitted_body: bool, ) -> Result> { let mut attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let defaultness: Option = input.parse()?; let sig: Signature = input.parse()?; // Accept functions without a body in an impl block because rustc's // *parser* does not reject them (the compilation error is emitted later // than parsing) and it can be useful for macro DSLs. if allow_omitted_body && input.parse::>()?.is_some() { return Ok(None); } let content; let brace_token = braced!(content in input); attrs.extend(content.call(Attribute::parse_inner)?); let block = Block { brace_token, stmts: content.call(Block::parse_within)?, }; Ok(Some(ImplItemFn { attrs, vis, defaultness, sig, block, })) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemType { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis: Visibility = input.parse()?; let defaultness: Option = input.parse()?; let type_token: Token![type] = input.parse()?; let ident: Ident = input.parse()?; let mut generics: Generics = input.parse()?; let eq_token: Token![=] = input.parse()?; let ty: Type = input.parse()?; generics.where_clause = input.parse()?; let semi_token: Token![;] = input.parse()?; Ok(ImplItemType { attrs, vis, defaultness, type_token, ident, generics, eq_token, ty, semi_token, }) } } fn parse_impl_item_type(begin: ParseBuffer, input: ParseStream) -> Result { let FlexibleItemType { vis, defaultness, type_token, ident, generics, colon_token, bounds: _, ty, semi_token, } = FlexibleItemType::parse( input, TypeDefaultness::Optional, WhereClauseLocation::AfterEq, )?; let (eq_token, ty) = match ty { Some(ty) if colon_token.is_none() => ty, _ => return Ok(ImplItem::Verbatim(verbatim::between(&begin, input))), }; Ok(ImplItem::Type(ImplItemType { attrs: Vec::new(), vis, defaultness, type_token, ident, generics, eq_token, ty, semi_token, })) } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ImplItemMacro { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let mac: Macro = input.parse()?; let semi_token: Option = if mac.delimiter.is_brace() { None } else { Some(input.parse()?) }; Ok(ImplItemMacro { attrs, mac, semi_token, }) } } impl Visibility { fn is_inherited(&self) -> bool { match self { Visibility::Inherited => true, _ => false, } } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for StaticMutability { fn parse(input: ParseStream) -> Result { let mut_token: Option = input.parse()?; Ok(mut_token.map_or(StaticMutability::None, StaticMutability::Mut)) } } } #[cfg(feature = "printing")] mod printing { use crate::attr::FilterAttrs; use crate::data::Fields; use crate::item::{ ForeignItemFn, ForeignItemMacro, ForeignItemStatic, ForeignItemType, ImplItemConst, ImplItemFn, ImplItemMacro, ImplItemType, ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemForeignMod, ItemImpl, ItemMacro, ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse, Receiver, Signature, StaticMutability, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, UseGlob, UseGroup, UseName, UsePath, UseRename, Variadic, }; use crate::mac::MacroDelimiter; use crate::print::TokensOrDefault; use crate::ty::Type; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemExternCrate { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.extern_token.to_tokens(tokens); self.crate_token.to_tokens(tokens); self.ident.to_tokens(tokens); if let Some((as_token, rename)) = &self.rename { as_token.to_tokens(tokens); rename.to_tokens(tokens); } self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemUse { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.use_token.to_tokens(tokens); self.leading_colon.to_tokens(tokens); self.tree.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemStatic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.static_token.to_tokens(tokens); self.mutability.to_tokens(tokens); self.ident.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.expr.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemConst { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.const_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.expr.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.sig.to_tokens(tokens); self.block.brace_token.surround(tokens, |tokens| { tokens.append_all(self.attrs.inner()); tokens.append_all(&self.block.stmts); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemMod { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.unsafety.to_tokens(tokens); self.mod_token.to_tokens(tokens); self.ident.to_tokens(tokens); if let Some((brace, items)) = &self.content { brace.surround(tokens, |tokens| { tokens.append_all(self.attrs.inner()); tokens.append_all(items); }); } else { TokensOrDefault(&self.semi).to_tokens(tokens); } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemForeignMod { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.unsafety.to_tokens(tokens); self.abi.to_tokens(tokens); self.brace_token.surround(tokens, |tokens| { tokens.append_all(self.attrs.inner()); tokens.append_all(&self.items); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.type_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.ty.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemEnum { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.enum_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); self.brace_token.surround(tokens, |tokens| { self.variants.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.struct_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); match &self.fields { Fields::Named(fields) => { self.generics.where_clause.to_tokens(tokens); fields.to_tokens(tokens); } Fields::Unnamed(fields) => { fields.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); TokensOrDefault(&self.semi_token).to_tokens(tokens); } Fields::Unit => { self.generics.where_clause.to_tokens(tokens); TokensOrDefault(&self.semi_token).to_tokens(tokens); } } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemUnion { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.union_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); self.fields.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemTrait { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.unsafety.to_tokens(tokens); self.auto_token.to_tokens(tokens); self.trait_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); if !self.supertraits.is_empty() { TokensOrDefault(&self.colon_token).to_tokens(tokens); self.supertraits.to_tokens(tokens); } self.generics.where_clause.to_tokens(tokens); self.brace_token.surround(tokens, |tokens| { tokens.append_all(self.attrs.inner()); tokens.append_all(&self.items); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemTraitAlias { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.trait_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.bounds.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemImpl { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.defaultness.to_tokens(tokens); self.unsafety.to_tokens(tokens); self.impl_token.to_tokens(tokens); self.generics.to_tokens(tokens); if let Some((polarity, path, for_token)) = &self.trait_ { polarity.to_tokens(tokens); path.to_tokens(tokens); for_token.to_tokens(tokens); } self.self_ty.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); self.brace_token.surround(tokens, |tokens| { tokens.append_all(self.attrs.inner()); tokens.append_all(&self.items); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.mac.path.to_tokens(tokens); self.mac.bang_token.to_tokens(tokens); self.ident.to_tokens(tokens); match &self.mac.delimiter { MacroDelimiter::Paren(paren) => { paren.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens)); } MacroDelimiter::Brace(brace) => { brace.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens)); } MacroDelimiter::Bracket(bracket) => { bracket.surround(tokens, |tokens| self.mac.tokens.to_tokens(tokens)); } } self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UsePath { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); self.colon2_token.to_tokens(tokens); self.tree.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseName { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseRename { fn to_tokens(&self, tokens: &mut TokenStream) { self.ident.to_tokens(tokens); self.as_token.to_tokens(tokens); self.rename.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseGlob { fn to_tokens(&self, tokens: &mut TokenStream) { self.star_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for UseGroup { fn to_tokens(&self, tokens: &mut TokenStream) { self.brace_token.surround(tokens, |tokens| { self.items.to_tokens(tokens); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemConst { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.const_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); if let Some((eq_token, default)) = &self.default { eq_token.to_tokens(tokens); default.to_tokens(tokens); } self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.sig.to_tokens(tokens); match &self.default { Some(block) => { block.brace_token.surround(tokens, |tokens| { tokens.append_all(self.attrs.inner()); tokens.append_all(&block.stmts); }); } None => { TokensOrDefault(&self.semi_token).to_tokens(tokens); } } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.type_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); if !self.bounds.is_empty() { TokensOrDefault(&self.colon_token).to_tokens(tokens); self.bounds.to_tokens(tokens); } if let Some((eq_token, default)) = &self.default { eq_token.to_tokens(tokens); default.to_tokens(tokens); } self.generics.where_clause.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TraitItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.mac.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemConst { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.defaultness.to_tokens(tokens); self.const_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.expr.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.defaultness.to_tokens(tokens); self.sig.to_tokens(tokens); self.block.brace_token.surround(tokens, |tokens| { tokens.append_all(self.attrs.inner()); tokens.append_all(&self.block.stmts); }); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.defaultness.to_tokens(tokens); self.type_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.eq_token.to_tokens(tokens); self.ty.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ImplItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.mac.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemFn { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.sig.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemStatic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.static_token.to_tokens(tokens); self.mutability.to_tokens(tokens); self.ident.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.vis.to_tokens(tokens); self.type_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ForeignItemMacro { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.mac.to_tokens(tokens); self.semi_token.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Signature { fn to_tokens(&self, tokens: &mut TokenStream) { self.constness.to_tokens(tokens); self.asyncness.to_tokens(tokens); self.unsafety.to_tokens(tokens); self.abi.to_tokens(tokens); self.fn_token.to_tokens(tokens); self.ident.to_tokens(tokens); self.generics.to_tokens(tokens); self.paren_token.surround(tokens, |tokens| { self.inputs.to_tokens(tokens); if let Some(variadic) = &self.variadic { if !self.inputs.empty_or_trailing() { ::default().to_tokens(tokens); } variadic.to_tokens(tokens); } }); self.output.to_tokens(tokens); self.generics.where_clause.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Receiver { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some((ampersand, lifetime)) = &self.reference { ampersand.to_tokens(tokens); lifetime.to_tokens(tokens); } self.mutability.to_tokens(tokens); self.self_token.to_tokens(tokens); if let Some(colon_token) = &self.colon_token { colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); } else { let consistent = match (&self.reference, &self.mutability, &*self.ty) { (Some(_), mutability, Type::Reference(ty)) => { mutability.is_some() == ty.mutability.is_some() && match &*ty.elem { Type::Path(ty) => ty.qself.is_none() && ty.path.is_ident("Self"), _ => false, } } (None, _, Type::Path(ty)) => ty.qself.is_none() && ty.path.is_ident("Self"), _ => false, }; if !consistent { ::default().to_tokens(tokens); self.ty.to_tokens(tokens); } } } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Variadic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some((pat, colon)) = &self.pat { pat.to_tokens(tokens); colon.to_tokens(tokens); } self.dots.to_tokens(tokens); self.comma.to_tokens(tokens); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for StaticMutability { fn to_tokens(&self, tokens: &mut TokenStream) { match self { StaticMutability::None => {} StaticMutability::Mut(mut_token) => mut_token.to_tokens(tokens), } } } } syn/src/file.rs0000644000175000017500000000750114661133735014431 0ustar jamespagejamespageuse crate::attr::Attribute; use crate::item::Item; ast_struct! { /// A complete file of Rust source code. /// /// Typically `File` objects are created with [`parse_file`]. /// /// [`parse_file`]: crate::parse_file /// /// # Example /// /// Parse a Rust source file into a `syn::File` and print out a debug /// representation of the syntax tree. /// /// ``` /// use std::env; /// use std::fs::File; /// use std::io::Read; /// use std::process; /// /// fn main() { /// # } /// # /// # fn fake_main() { /// let mut args = env::args(); /// let _ = args.next(); // executable name /// /// let filename = match (args.next(), args.next()) { /// (Some(filename), None) => filename, /// _ => { /// eprintln!("Usage: dump-syntax path/to/filename.rs"); /// process::exit(1); /// } /// }; /// /// let mut file = File::open(&filename).expect("unable to open file"); /// /// let mut src = String::new(); /// file.read_to_string(&mut src).expect("unable to read file"); /// /// let syntax = syn::parse_file(&src).expect("unable to parse file"); /// /// // Debug impl is available if Syn is built with "extra-traits" feature. /// println!("{:#?}", syntax); /// } /// ``` /// /// Running with its own source code as input, this program prints output /// that begins with: /// /// ```text /// File { /// shebang: None, /// attrs: [], /// items: [ /// Use( /// ItemUse { /// attrs: [], /// vis: Inherited, /// use_token: Use, /// leading_colon: None, /// tree: Path( /// UsePath { /// ident: Ident( /// std, /// ), /// colon2_token: Colon2, /// tree: Name( /// UseName { /// ident: Ident( /// env, /// ), /// }, /// ), /// }, /// ), /// semi_token: Semi, /// }, /// ), /// ... /// ``` #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct File { pub shebang: Option, pub attrs: Vec, pub items: Vec, } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::Result; use crate::file::File; use crate::parse::{Parse, ParseStream}; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for File { fn parse(input: ParseStream) -> Result { Ok(File { shebang: None, attrs: input.call(Attribute::parse_inner)?, items: { let mut items = Vec::new(); while !input.is_empty() { items.push(input.parse()?); } items }, }) } } } #[cfg(feature = "printing")] mod printing { use crate::attr::FilterAttrs; use crate::file::File; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt}; #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for File { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.inner()); tokens.append_all(&self.items); } } } syn/src/mac.rs0000644000175000017500000001734514661133735014261 0ustar jamespagejamespage#[cfg(feature = "parsing")] use crate::error::Result; #[cfg(feature = "parsing")] use crate::parse::{Parse, ParseStream, Parser}; use crate::path::Path; use crate::token::{Brace, Bracket, Paren}; use proc_macro2::extra::DelimSpan; #[cfg(feature = "parsing")] use proc_macro2::Delimiter; use proc_macro2::TokenStream; #[cfg(feature = "parsing")] use proc_macro2::TokenTree; ast_struct! { /// A macro invocation: `println!("{}", mac)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Macro { pub path: Path, pub bang_token: Token![!], pub delimiter: MacroDelimiter, pub tokens: TokenStream, } } ast_enum! { /// A grouping token that surrounds a macro body: `m!(...)` or `m!{...}` or `m![...]`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum MacroDelimiter { Paren(Paren), Brace(Brace), Bracket(Bracket), } } impl MacroDelimiter { pub fn span(&self) -> &DelimSpan { match self { MacroDelimiter::Paren(token) => &token.span, MacroDelimiter::Brace(token) => &token.span, MacroDelimiter::Bracket(token) => &token.span, } } #[cfg(all(feature = "full", any(feature = "parsing", feature = "printing")))] pub(crate) fn is_brace(&self) -> bool { match self { MacroDelimiter::Brace(_) => true, MacroDelimiter::Paren(_) | MacroDelimiter::Bracket(_) => false, } } } impl Macro { /// Parse the tokens within the macro invocation's delimiters into a syntax /// tree. /// /// This is equivalent to `syn::parse2::(mac.tokens)` except that it /// produces a more useful span when `tokens` is empty. /// /// # Example /// /// ``` /// use syn::{parse_quote, Expr, ExprLit, Ident, Lit, LitStr, Macro, Token}; /// use syn::ext::IdentExt; /// use syn::parse::{Error, Parse, ParseStream, Result}; /// use syn::punctuated::Punctuated; /// /// // The arguments expected by libcore's format_args macro, and as a /// // result most other formatting and printing macros like println. /// // /// // println!("{} is {number:.prec$}", "x", prec=5, number=0.01) /// struct FormatArgs { /// format_string: Expr, /// positional_args: Vec, /// named_args: Vec<(Ident, Expr)>, /// } /// /// impl Parse for FormatArgs { /// fn parse(input: ParseStream) -> Result { /// let format_string: Expr; /// let mut positional_args = Vec::new(); /// let mut named_args = Vec::new(); /// /// format_string = input.parse()?; /// while !input.is_empty() { /// input.parse::()?; /// if input.is_empty() { /// break; /// } /// if input.peek(Ident::peek_any) && input.peek2(Token![=]) { /// while !input.is_empty() { /// let name: Ident = input.call(Ident::parse_any)?; /// input.parse::()?; /// let value: Expr = input.parse()?; /// named_args.push((name, value)); /// if input.is_empty() { /// break; /// } /// input.parse::()?; /// } /// break; /// } /// positional_args.push(input.parse()?); /// } /// /// Ok(FormatArgs { /// format_string, /// positional_args, /// named_args, /// }) /// } /// } /// /// // Extract the first argument, the format string literal, from an /// // invocation of a formatting or printing macro. /// fn get_format_string(m: &Macro) -> Result { /// let args: FormatArgs = m.parse_body()?; /// match args.format_string { /// Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }) => Ok(lit), /// other => { /// // First argument was not a string literal expression. /// // Maybe something like: println!(concat!(...), ...) /// Err(Error::new_spanned(other, "format string must be a string literal")) /// } /// } /// } /// /// fn main() { /// let invocation = parse_quote! { /// println!("{:?}", Instant::now()) /// }; /// let lit = get_format_string(&invocation).unwrap(); /// assert_eq!(lit.value(), "{:?}"); /// } /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_body(&self) -> Result { self.parse_body_with(T::parse) } /// Parse the tokens within the macro invocation's delimiters using the /// given parser. #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_body_with(&self, parser: F) -> Result { let scope = self.delimiter.span().close(); crate::parse::parse_scoped(parser, scope, self.tokens.clone()) } } #[cfg(feature = "parsing")] pub(crate) fn parse_delimiter(input: ParseStream) -> Result<(MacroDelimiter, TokenStream)> { input.step(|cursor| { if let Some((TokenTree::Group(g), rest)) = cursor.token_tree() { let span = g.delim_span(); let delimiter = match g.delimiter() { Delimiter::Parenthesis => MacroDelimiter::Paren(Paren(span)), Delimiter::Brace => MacroDelimiter::Brace(Brace(span)), Delimiter::Bracket => MacroDelimiter::Bracket(Bracket(span)), Delimiter::None => { return Err(cursor.error("expected delimiter")); } }; Ok(((delimiter, g.stream()), rest)) } else { Err(cursor.error("expected delimiter")) } }) } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::error::Result; use crate::mac::{parse_delimiter, Macro}; use crate::parse::{Parse, ParseStream}; use crate::path::Path; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Macro { fn parse(input: ParseStream) -> Result { let tokens; Ok(Macro { path: input.call(Path::parse_mod_style)?, bang_token: input.parse()?, delimiter: { let (delimiter, content) = parse_delimiter(input)?; tokens = content; delimiter }, tokens, }) } } } #[cfg(feature = "printing")] mod printing { use crate::mac::{Macro, MacroDelimiter}; use crate::token; use proc_macro2::{Delimiter, TokenStream}; use quote::ToTokens; impl MacroDelimiter { pub(crate) fn surround(&self, tokens: &mut TokenStream, inner: TokenStream) { let (delim, span) = match self { MacroDelimiter::Paren(paren) => (Delimiter::Parenthesis, paren.span), MacroDelimiter::Brace(brace) => (Delimiter::Brace, brace.span), MacroDelimiter::Bracket(bracket) => (Delimiter::Bracket, bracket.span), }; token::printing::delim(delim, span.join(), tokens, inner); } } #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Macro { fn to_tokens(&self, tokens: &mut TokenStream) { self.path.to_tokens(tokens); self.bang_token.to_tokens(tokens); self.delimiter.surround(tokens, self.tokens.clone()); } } } syn/src/group.rs0000644000175000017500000001732014661133735014646 0ustar jamespagejamespageuse crate::error::Result; use crate::parse::ParseBuffer; use crate::token; use proc_macro2::extra::DelimSpan; use proc_macro2::Delimiter; // Not public API. #[doc(hidden)] pub struct Parens<'a> { #[doc(hidden)] pub token: token::Paren, #[doc(hidden)] pub content: ParseBuffer<'a>, } // Not public API. #[doc(hidden)] pub struct Braces<'a> { #[doc(hidden)] pub token: token::Brace, #[doc(hidden)] pub content: ParseBuffer<'a>, } // Not public API. #[doc(hidden)] pub struct Brackets<'a> { #[doc(hidden)] pub token: token::Bracket, #[doc(hidden)] pub content: ParseBuffer<'a>, } // Not public API. #[cfg(any(feature = "full", feature = "derive"))] #[doc(hidden)] pub struct Group<'a> { #[doc(hidden)] pub token: token::Group, #[doc(hidden)] pub content: ParseBuffer<'a>, } // Not public API. #[doc(hidden)] pub fn parse_parens<'a>(input: &ParseBuffer<'a>) -> Result> { parse_delimited(input, Delimiter::Parenthesis).map(|(span, content)| Parens { token: token::Paren(span), content, }) } // Not public API. #[doc(hidden)] pub fn parse_braces<'a>(input: &ParseBuffer<'a>) -> Result> { parse_delimited(input, Delimiter::Brace).map(|(span, content)| Braces { token: token::Brace(span), content, }) } // Not public API. #[doc(hidden)] pub fn parse_brackets<'a>(input: &ParseBuffer<'a>) -> Result> { parse_delimited(input, Delimiter::Bracket).map(|(span, content)| Brackets { token: token::Bracket(span), content, }) } #[cfg(any(feature = "full", feature = "derive"))] pub(crate) fn parse_group<'a>(input: &ParseBuffer<'a>) -> Result> { parse_delimited(input, Delimiter::None).map(|(span, content)| Group { token: token::Group(span.join()), content, }) } fn parse_delimited<'a>( input: &ParseBuffer<'a>, delimiter: Delimiter, ) -> Result<(DelimSpan, ParseBuffer<'a>)> { input.step(|cursor| { if let Some((content, span, rest)) = cursor.group(delimiter) { let scope = span.close(); let nested = crate::parse::advance_step_cursor(cursor, content); let unexpected = crate::parse::get_unexpected(input); let content = crate::parse::new_parse_buffer(scope, nested, unexpected); Ok(((span, content), rest)) } else { let message = match delimiter { Delimiter::Parenthesis => "expected parentheses", Delimiter::Brace => "expected curly braces", Delimiter::Bracket => "expected square brackets", Delimiter::None => "expected invisible group", }; Err(cursor.error(message)) } }) } /// Parse a set of parentheses and expose their content to subsequent parsers. /// /// # Example /// /// ``` /// # use quote::quote; /// # /// use syn::{parenthesized, token, Ident, Result, Token, Type}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// // Parse a simplified tuple struct syntax like: /// // /// // struct S(A, B); /// struct TupleStruct { /// struct_token: Token![struct], /// ident: Ident, /// paren_token: token::Paren, /// fields: Punctuated, /// semi_token: Token![;], /// } /// /// impl Parse for TupleStruct { /// fn parse(input: ParseStream) -> Result { /// let content; /// Ok(TupleStruct { /// struct_token: input.parse()?, /// ident: input.parse()?, /// paren_token: parenthesized!(content in input), /// fields: content.parse_terminated(Type::parse, Token![,])?, /// semi_token: input.parse()?, /// }) /// } /// } /// # /// # fn main() { /// # let input = quote! { /// # struct S(A, B); /// # }; /// # syn::parse2::(input).unwrap(); /// # } /// ``` #[macro_export] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] macro_rules! parenthesized { ($content:ident in $cursor:expr) => { match $crate::__private::parse_parens(&$cursor) { $crate::__private::Ok(parens) => { $content = parens.content; parens.token } $crate::__private::Err(error) => { return $crate::__private::Err(error); } } }; } /// Parse a set of curly braces and expose their content to subsequent parsers. /// /// # Example /// /// ``` /// # use quote::quote; /// # /// use syn::{braced, token, Ident, Result, Token, Type}; /// use syn::parse::{Parse, ParseStream}; /// use syn::punctuated::Punctuated; /// /// // Parse a simplified struct syntax like: /// // /// // struct S { /// // a: A, /// // b: B, /// // } /// struct Struct { /// struct_token: Token![struct], /// ident: Ident, /// brace_token: token::Brace, /// fields: Punctuated, /// } /// /// struct Field { /// name: Ident, /// colon_token: Token![:], /// ty: Type, /// } /// /// impl Parse for Struct { /// fn parse(input: ParseStream) -> Result { /// let content; /// Ok(Struct { /// struct_token: input.parse()?, /// ident: input.parse()?, /// brace_token: braced!(content in input), /// fields: content.parse_terminated(Field::parse, Token![,])?, /// }) /// } /// } /// /// impl Parse for Field { /// fn parse(input: ParseStream) -> Result { /// Ok(Field { /// name: input.parse()?, /// colon_token: input.parse()?, /// ty: input.parse()?, /// }) /// } /// } /// # /// # fn main() { /// # let input = quote! { /// # struct S { /// # a: A, /// # b: B, /// # } /// # }; /// # syn::parse2::(input).unwrap(); /// # } /// ``` #[macro_export] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] macro_rules! braced { ($content:ident in $cursor:expr) => { match $crate::__private::parse_braces(&$cursor) { $crate::__private::Ok(braces) => { $content = braces.content; braces.token } $crate::__private::Err(error) => { return $crate::__private::Err(error); } } }; } /// Parse a set of square brackets and expose their content to subsequent /// parsers. /// /// # Example /// /// ``` /// # use quote::quote; /// # /// use proc_macro2::TokenStream; /// use syn::{bracketed, token, Result, Token}; /// use syn::parse::{Parse, ParseStream}; /// /// // Parse an outer attribute like: /// // /// // #[repr(C, packed)] /// struct OuterAttribute { /// pound_token: Token![#], /// bracket_token: token::Bracket, /// content: TokenStream, /// } /// /// impl Parse for OuterAttribute { /// fn parse(input: ParseStream) -> Result { /// let content; /// Ok(OuterAttribute { /// pound_token: input.parse()?, /// bracket_token: bracketed!(content in input), /// content: content.parse()?, /// }) /// } /// } /// # /// # fn main() { /// # let input = quote! { /// # #[repr(C, packed)] /// # }; /// # syn::parse2::(input).unwrap(); /// # } /// ``` #[macro_export] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] macro_rules! bracketed { ($content:ident in $cursor:expr) => { match $crate::__private::parse_brackets(&$cursor) { $crate::__private::Ok(brackets) => { $content = brackets.content; brackets.token } $crate::__private::Err(error) => { return $crate::__private::Err(error); } } }; } syn/src/macros.rs0000644000175000017500000001027114661133735014774 0ustar jamespagejamespage#[cfg_attr( not(any(feature = "full", feature = "derive")), allow(unknown_lints, unused_macro_rules) )] macro_rules! ast_struct { ( $(#[$attr:meta])* $pub:ident $struct:ident $name:ident #full $body:tt ) => { check_keyword_matches!(pub $pub); check_keyword_matches!(struct $struct); #[cfg(feature = "full")] $(#[$attr])* $pub $struct $name $body #[cfg(not(feature = "full"))] $(#[$attr])* $pub $struct $name { _noconstruct: ::std::marker::PhantomData<::proc_macro2::Span>, } #[cfg(all(not(feature = "full"), feature = "printing"))] impl ::quote::ToTokens for $name { fn to_tokens(&self, _: &mut ::proc_macro2::TokenStream) { unreachable!() } } }; ( $(#[$attr:meta])* $pub:ident $struct:ident $name:ident $body:tt ) => { check_keyword_matches!(pub $pub); check_keyword_matches!(struct $struct); $(#[$attr])* $pub $struct $name $body }; } #[cfg(any(feature = "full", feature = "derive"))] macro_rules! ast_enum { ( $(#[$enum_attr:meta])* $pub:ident $enum:ident $name:ident $body:tt ) => { check_keyword_matches!(pub $pub); check_keyword_matches!(enum $enum); $(#[$enum_attr])* $pub $enum $name $body }; } macro_rules! ast_enum_of_structs { ( $(#[$enum_attr:meta])* $pub:ident $enum:ident $name:ident $body:tt ) => { check_keyword_matches!(pub $pub); check_keyword_matches!(enum $enum); $(#[$enum_attr])* $pub $enum $name $body ast_enum_of_structs_impl!($name $body); #[cfg(feature = "printing")] generate_to_tokens!(() tokens $name $body); }; } macro_rules! ast_enum_of_structs_impl { ( $name:ident { $( $(#[cfg $cfg_attr:tt])* $(#[doc $($doc_attr:tt)*])* $variant:ident $( ($member:ident) )*, )* } ) => { $($( ast_enum_from_struct!($name::$variant, $member); )*)* }; } macro_rules! ast_enum_from_struct { // No From for verbatim variants. ($name:ident::Verbatim, $member:ident) => {}; ($name:ident::$variant:ident, $member:ident) => { impl From<$member> for $name { fn from(e: $member) -> $name { $name::$variant(e) } } }; } #[cfg(feature = "printing")] macro_rules! generate_to_tokens { ( ($($arms:tt)*) $tokens:ident $name:ident { $(#[cfg $cfg_attr:tt])* $(#[doc $($doc_attr:tt)*])* $variant:ident, $($next:tt)* } ) => { generate_to_tokens!( ($($arms)* $(#[cfg $cfg_attr])* $name::$variant => {}) $tokens $name { $($next)* } ); }; ( ($($arms:tt)*) $tokens:ident $name:ident { $(#[cfg $cfg_attr:tt])* $(#[doc $($doc_attr:tt)*])* $variant:ident($member:ident), $($next:tt)* } ) => { generate_to_tokens!( ($($arms)* $(#[cfg $cfg_attr])* $name::$variant(_e) => _e.to_tokens($tokens),) $tokens $name { $($next)* } ); }; (($($arms:tt)*) $tokens:ident $name:ident {}) => { #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ::quote::ToTokens for $name { fn to_tokens(&self, $tokens: &mut ::proc_macro2::TokenStream) { match self { $($arms)* } } } }; } // Rustdoc bug: does not respect the doc(hidden) on some items. #[cfg(all(doc, feature = "parsing"))] macro_rules! pub_if_not_doc { ($(#[$m:meta])* $pub:ident $($item:tt)*) => { check_keyword_matches!(pub $pub); $(#[$m])* $pub(crate) $($item)* }; } #[cfg(all(not(doc), feature = "parsing"))] macro_rules! pub_if_not_doc { ($(#[$m:meta])* $pub:ident $($item:tt)*) => { check_keyword_matches!(pub $pub); $(#[$m])* $pub $($item)* }; } macro_rules! check_keyword_matches { (enum enum) => {}; (pub pub) => {}; (struct struct) => {}; } syn/src/bigint.rs0000644000175000017500000000311214661133735014760 0ustar jamespagejamespageuse std::ops::{AddAssign, MulAssign}; // For implementing base10_digits() accessor on LitInt. pub(crate) struct BigInt { digits: Vec, } impl BigInt { pub(crate) fn new() -> Self { BigInt { digits: Vec::new() } } pub(crate) fn to_string(&self) -> String { let mut repr = String::with_capacity(self.digits.len()); let mut has_nonzero = false; for digit in self.digits.iter().rev() { has_nonzero |= *digit != 0; if has_nonzero { repr.push((*digit + b'0') as char); } } if repr.is_empty() { repr.push('0'); } repr } fn reserve_two_digits(&mut self) { let len = self.digits.len(); let desired = len + !self.digits.ends_with(&[0, 0]) as usize + !self.digits.ends_with(&[0]) as usize; self.digits.resize(desired, 0); } } impl AddAssign for BigInt { // Assumes increment <16. fn add_assign(&mut self, mut increment: u8) { self.reserve_two_digits(); let mut i = 0; while increment > 0 { let sum = self.digits[i] + increment; self.digits[i] = sum % 10; increment = sum / 10; i += 1; } } } impl MulAssign for BigInt { // Assumes base <=16. fn mul_assign(&mut self, base: u8) { self.reserve_two_digits(); let mut carry = 0; for digit in &mut self.digits { let prod = *digit * base + carry; *digit = prod % 10; carry = prod / 10; } } } syn/.cargo-checksum.json0000664000175000017500000002043014661133735016217 0ustar jamespagejamespage{"files":{"Cargo.toml":"7c39f64e2dacd73d7ebcaa84269353bc06786c8e8b7f84c3b2d68162b5e4f8a1","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"ae6deb98ea51df4829c0327139a555cc115c6bcf6fb459db0ef0d6a96c4566ec","benches/file.rs":"0a0527c78d849148cbb6118b4d36f72da7d4add865ba1a410e0a1be9e8dbfe0e","benches/rust.rs":"a4b2ac626d36df1e344b1389384a559fb47da291b8ad3aa964d59d93279eebb1","src/attr.rs":"bd959c93f997d5d77ec08a5f580d1d38a391978b916b5bbe82bad4c03e694563","src/bigint.rs":"0299829b2f7a1a798fe2f7bc1680e4a10f9b6f4a852d09af4da2deab466c4242","src/buffer.rs":"86034db43cad263610a86d77cd7f3a170b173f9375659124c2d9daa30b855953","src/classify.rs":"cc5b8003fecdc7606693b2c21ab7df3468bca111a42602b3285569ba47af1e2c","src/custom_keyword.rs":"322114e36ae43a2f8605506fb4568efdbc2986853e2fee74bd10a4ca0fb60c69","src/custom_punctuation.rs":"2ae2339c29b1aff3ab16157d51a3a07bfca594aa38586981534fe07a62cdd9d1","src/data.rs":"7ad7f3c55d9f0b2ff223f3f30602ffa82013c0e7366006b0a9a01193de753db0","src/derive.rs":"f54f8cf9386a2d45186ff3c86ade5dae59e0e337b0198532449190ae8520cff8","src/discouraged.rs":"e89c91924a2db771f75e90ea032c02d6bdd71d5dd7b59fec98eac19e18209108","src/drops.rs":"013385f1dd95663f1afab41abc1e2eea04181998644828935ca564c74d6462ae","src/error.rs":"3b03fd75eee8b0bb646eaf20f7e287345bdc7515ad5286024a2dd1e53c1e7bf2","src/export.rs":"b260cc49da1da3489e7755832bc8015cfad79e84f6c74e237f65ae25a2385e56","src/expr.rs":"e306f64432f4fc2007f1baf9600b7a4914a923d99c2a39ad48b989fd329bfc1e","src/ext.rs":"ed143b029af286e62ceb4310286a4ce894792dd588465face042b4199b39d329","src/file.rs":"39d4ed9c56a7dc0d83259843732c434cd187248a4cde3dba4a98c3b92df6d08f","src/fixup.rs":"ec3f84bb2e09a00d460399ee009c582ce468d294c7a7c930f7677571b5bc985e","src/gen/clone.rs":"36491f5f9e9cad6c4eb354b3331ec2b672607bb26429eba6379d1e9a4919170f","src/gen/debug.rs":"c9b2547663ed9025ba614fb1a70810df1b25f471ebb57abb01de5ab8e4fa8bf0","src/gen/eq.rs":"b5fffca0c3b6c31b3fcc80a7bd8fec65baed982a4e2fb4c8862db6059ab7dea1","src/gen/fold.rs":"345e6a6d9a7d2d09e09cd5857fc903af4202df42f0759a3da118556e98829fd2","src/gen/hash.rs":"447e840245178d0777b4e143b54c356b88962456e80282dcaad1763093709c13","src/gen/visit.rs":"178a6841d7d1974bff8c8c2f9a18e9b77384956841861a50828252bcaef67c18","src/gen/visit_mut.rs":"2a8f9a1c0259060f3fa1d6cab8a1924c1b07d713561aa9562cde8e79a39e66d5","src/generics.rs":"53ba17d13f89d316387c7debb302f703f99d5038921a7272a6d25e6f8bec42ec","src/group.rs":"ddbff97e41315bdf9dfce215a8c00bb4d532827cf794246afde7308b39dc09ca","src/ident.rs":"d6061030fadae9c7dc847e1ee46178d9657d782aad108c7197e8cafe765b3eaa","src/item.rs":"81e2f57843cf2f8df82e314da940a6dda9bfa54e0641dbabe3ca2a7a68c9c5a8","src/lib.rs":"136ef80fb32ac1e981aaeb9346f1eb6954eb74f1ade266e9096dbb296b0f467c","src/lifetime.rs":"5787d5a5dc7e5332b03283a25ae0a9e826464242ca2d149b1a19e7cae9cee34d","src/lit.rs":"8fa6fa2d752bd1bf5a94cd5cbf9becbcba37d491876614ce62dba0f8fc745a3d","src/lookahead.rs":"eae3c1855dfd1f9bca5dd4afba07d41b15f8c108017f9eda3dc515567160a2af","src/mac.rs":"cd85132ab4d302333f771be7a9b40f9281781ae9bcaee0607e0a25547352baaa","src/macros.rs":"e0587f60d510fd0079c60521f6898b61da5857664bd8b450154f83c85c4403c5","src/meta.rs":"969d8ccbdbc6ea2e4928a21831b791c57447b231e1373149e4c63b46f3951801","src/op.rs":"a61757370f802e44efa3c4a1057ae2cd26e64e273f7d76c06d5ffb49602319e2","src/parse.rs":"2a4baaae025237fa3e372e9017b5a07db290554471493ebec54b4f39864398d5","src/parse_macro_input.rs":"e4e22b63d0496d06a4ca17742a22467ed93f08a739081324773828bad63175ee","src/parse_quote.rs":"6f4e5e28622205651bdb23fcf0f0526aef81a7921aaeac2e7a1a1e3b67916fe9","src/pat.rs":"e552911a1712508c672eca35abdf9f81bad3a960f21522eddbc411a6a7070445","src/path.rs":"d77045e5dad382056d67fe31a42bc45b6a02ce044c43287bd38a95e32fd6aead","src/precedence.rs":"f44a468a33c845fd34a36e302846f85654bdba9ae0d6344cd6a3598643268fd0","src/print.rs":"22910bf0521ab868ebd7c62601c55912d12cfb400c65723e08e5cfa3a2d111c0","src/punctuated.rs":"099b00d56e43a1586460cde657928ff407b9d048dbf28752312cac97e042ec8c","src/restriction.rs":"eabb012634ef67aa3c3849c905ab549189461df7fefde2a4b90161c8685f31b2","src/sealed.rs":"6ece3b3dcb30f6bb98b93d83759ca7712ee8592bef9c0511141039c38765db0e","src/span.rs":"0a48e375e5c9768f6f64174a91ba6a255f4b021e2fb3548d8494e617f142601b","src/spanned.rs":"4b9bd65f60ab81922adfd0be8f03b6d50e98da3a5f525f242f9639aec4beac79","src/stmt.rs":"bb4cd196ce23c3fc07fefa47e67a0cd815db4f02ce1192625379d60bd657ffd2","src/thread.rs":"1f1deb1272525ab2af9a36aac4bce8f65b0e315adb1656641fd7075662f49222","src/token.rs":"3625e05bfaaf48adf7685669a59186386862572fa4550c5e94bf9a1febdb069e","src/tt.rs":"a58303a95d08d6bf3f3e09715b9b70a57b91b54774cfc1f00f2848034d2ff5c7","src/ty.rs":"90af4ce1911c91bdfd9ae431def641640daeb0c788c39a2ef024926485e7b2b2","src/verbatim.rs":"87cbe82a90f48efb57ffd09141042698b3e011a21d0d5412154d80324b0a5ef0","src/whitespace.rs":"9cdcbfe9045b259046329a795bc1105ab5a871471a6d3f7318d275ee53f7a825","tests/common/eq.rs":"27620bfcb038e547adb4cbea1b97b5049657ffcc178aefe8bf7fabd3ffbea789","tests/common/mod.rs":"64fb893bc0e7148395fd9ce1f67432b3d8406be29cbd664e2b73585da5ee5719","tests/common/parse.rs":"c173bd515ba1d53b3b676161849fa8df0ae3d5592445843cee65b6628b71ac32","tests/debug/gen.rs":"3ca161a049fe72ff73ead99fbfe78335fdb2ac7c41085fe8cd0c9a0b29995151","tests/debug/mod.rs":"b56136586267ae1812a937b69215dd053ada2c21717771d89dcd3ce52bcb27f5","tests/macros/mod.rs":"64b0da858096e7cf0f772e66bc1787a867e45897d7677de580c0a1f35c0f6852","tests/regression.rs":"e9565ea0efecb4136f099164ffcfa26e1996b0a27fb9c6659e90ad9bdd42e7b6","tests/regression/issue1108.rs":"f32db35244a674e22ff824ca9e5bbec2184e287b59f022db68c418b5878a2edc","tests/regression/issue1235.rs":"a2266b10c3f7c7af5734817ab0a3e8b309b51e7d177b63f26e67e6b744d280b0","tests/repo/mod.rs":"a463bc4786fa211005ef93bf2257d89c8ccd0be621275d9689396a53cb9bf425","tests/repo/progress.rs":"c08d0314a7f3ecf760d471f27da3cd2a500aeb9f1c8331bffb2aa648f9fabf3f","tests/test_asyncness.rs":"8982f6bc4e36510f924e288247473403e72697389ce9dda4e4b5ab0a8e49259f","tests/test_attribute.rs":"b35550a43bbd187bb330997ba36f90c65d8fc489135b1d32ef4547f145cb7612","tests/test_derive_input.rs":"99c4e6e45e3322ea9e269b309059c8a00fda1dcc03aed41f6e7d8c7e0a72fa2b","tests/test_expr.rs":"bb0b0183690605aedb107a777dc84d0b438a8518df875900c21b56d1049b969e","tests/test_generics.rs":"2fcc8575d695b568f3724b3b33d853b8fa6d9864eb816b5e3ca82420682e6155","tests/test_grouping.rs":"1bd63c8ca0b90bd493fb3f927079ab9ddf74d2a78da82db2f638e652d22305d5","tests/test_ident.rs":"d5850e817720e774cd397a46dbc5298c57933823c18e20805e84503fc9387e8f","tests/test_item.rs":"1b8412a5581adf93eaa215785a592f139af8511c954dee283d52dff2718a6cc2","tests/test_iterators.rs":"f4dacb5f3a8e0473dfb0d27f05270d41e79eddb4759b1fad3e88e379b4731e17","tests/test_lit.rs":"01b0acfe03cff16e7c1a45ceb7f4b637e5cbc6145840886ba981b7ed8e83691c","tests/test_meta.rs":"4ae570333f849ed8edec5dd957111a2deb721ede360f1e1ffeeab75380578ad4","tests/test_parse_buffer.rs":"0de6af13ba0345986b18d495063f9b75a1018e8569c34b277f9522c63a6c0941","tests/test_parse_quote.rs":"928176da6ebb449ef01a798f3352c9b181d3077c1266eb008df73876f4013c47","tests/test_parse_stream.rs":"b6b533432173123d6d01d8d2cb33714bc50b30b16ffbb6116f93937221ad4594","tests/test_pat.rs":"f6954a50e62a97ac2bc1ba0cb7a5a1fc53b7b01fb55ffe0176bee3fe1955d460","tests/test_path.rs":"d54350aa91508f8d301f5be3e3a34e03b0615b1a04e8fbbab9840da20161838b","tests/test_precedence.rs":"a26bf99cba2fb24ca49b4e2b922a4417f66b38e56bf7348492b652e81dd5d597","tests/test_receiver.rs":"af64117acd66fbf42edc476f731ecd20c88009d9cb641dbd7a1d6384ae99ae73","tests/test_round_trip.rs":"4c56592f92141d4e3c96c4df5360e4d7084fb5028bea6bc979b175ebcfb3590e","tests/test_shebang.rs":"98e8a6690c04e0aad2893b747593620b51836fe704f50f5c6fe352609837138a","tests/test_size.rs":"03efaf829b80b7db1f831474c1d3ce268914fc499d0e2a7eea03cad04a482974","tests/test_stmt.rs":"bbc305ea888254798b6faf285187d8bc7a955e4402d9a497d4b9d361e0436691","tests/test_token_trees.rs":"d012da9c3c861073711b006bf6ffdc073821fb9fb0a08733628cdae57124d1f5","tests/test_ty.rs":"49fbb880891d4c2e21350e35b914d92aa9a056fbaad9c4afa5242802848fe9c4","tests/test_visibility.rs":"7bd239aef6f6d8173462dbd869064f3fdb9ba71644ac1f62c5d2fbb2568fb986","tests/zzz_stable.rs":"2a862e59cb446235ed99aec0e6ada8e16d3ecc30229b29d825b7c0bbc2602989"},"package":"201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6"}target-lexicon/0000775000175000017500000000000014661133735014470 5ustar jamespagejamespagetarget-lexicon/build.rs0000644000175000017500000001177514661133735016146 0ustar jamespagejamespage//! build.rs file to obtain the host information. // Allow dead code in triple.rs and targets.rs for our purposes here. #![allow(dead_code)] use std::env; use std::fs::File; use std::io::{self, Write}; use std::path::PathBuf; use std::process::Command; use std::str::FromStr; #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(feature = "std")] extern crate std as alloc; // Include triple.rs and targets.rs so we can parse the TARGET environment variable. // targets.rs depends on data_model mod data_model { include!("src/data_model.rs"); } mod triple { include!("src/triple.rs"); } mod targets { include!("src/targets.rs"); } // Stub out `ParseError` to minimally support triple.rs and targets.rs. mod parse_error { #[derive(Debug)] pub enum ParseError { UnrecognizedArchitecture(String), UnrecognizedVendor(String), UnrecognizedOperatingSystem(String), UnrecognizedEnvironment(String), UnrecognizedBinaryFormat(String), UnrecognizedField(String), } } use self::targets::Vendor; use self::triple::Triple; fn main() { let out_dir = PathBuf::from( env::var_os("OUT_DIR").expect("The OUT_DIR environment variable must be set"), ); let target = env::var("TARGET").expect("The TARGET environment variable must be set"); let triple = Triple::from_str(&target).unwrap_or_else(|_| panic!("Invalid target name: '{}'", target)); let out = File::create(out_dir.join("host.rs")).expect("error creating host.rs"); write_host_rs(out, triple).expect("error writing host.rs"); if using_1_40() { println!("cargo:rustc-cfg=feature=\"rust_1_40\""); } } fn using_1_40() -> bool { match (|| { let rustc = env::var_os("RUSTC").unwrap(); let output = Command::new(rustc).arg("--version").output().ok()?; let stdout = if output.status.success() { output.stdout } else { return None; }; std::str::from_utf8(&stdout) .ok()? .split(' ') .nth(1)? .split('.') .nth(1)? .parse::() .ok() })() { Some(version) => version >= 40, None => true, // assume we're using an up-to-date compiler } } fn write_host_rs(mut out: File, triple: Triple) -> io::Result<()> { // The generated Debug implementation for the inner architecture variants // doesn't print the enum name qualifier, so import them here. There // shouldn't be any conflicts because these enums all share a namespace // in the triple string format. writeln!( out, r#" #[allow(unused_imports)] use crate::Aarch64Architecture::*; #[allow(unused_imports)] use crate::ArmArchitecture::*; #[allow(unused_imports)] use crate::CustomVendor; #[allow(unused_imports)] use crate::Mips32Architecture::*; #[allow(unused_imports)] use crate::Mips64Architecture::*; #[allow(unused_imports)] use crate::Riscv32Architecture::*; #[allow(unused_imports)] use crate::Riscv64Architecture::*; #[allow(unused_imports)] use crate::X86_32Architecture::*; /// The `Triple` of the current host. pub const HOST: Triple = Triple {{ architecture: Architecture::{architecture:?}, vendor: Vendor::{vendor}, operating_system: OperatingSystem::{operating_system:?}, environment: Environment::{environment:?}, binary_format: BinaryFormat::{binary_format:?}, }}; impl Architecture {{ /// Return the architecture for the current host. pub const fn host() -> Self {{ Architecture::{architecture:?} }} }} impl Vendor {{ /// Return the vendor for the current host. pub const fn host() -> Self {{ Vendor::{vendor} }} }} impl OperatingSystem {{ /// Return the operating system for the current host. pub const fn host() -> Self {{ OperatingSystem::{operating_system:?} }} }} impl Environment {{ /// Return the environment for the current host. pub const fn host() -> Self {{ Environment::{environment:?} }} }} impl BinaryFormat {{ /// Return the binary format for the current host. pub const fn host() -> Self {{ BinaryFormat::{binary_format:?} }} }} impl Triple {{ /// Return the triple for the current host. pub const fn host() -> Self {{ Self {{ architecture: Architecture::{architecture:?}, vendor: Vendor::{vendor}, operating_system: OperatingSystem::{operating_system:?}, environment: Environment::{environment:?}, binary_format: BinaryFormat::{binary_format:?}, }} }} }}"#, architecture = triple.architecture, vendor = vendor_display(&triple.vendor), operating_system = triple.operating_system, environment = triple.environment, binary_format = triple.binary_format, )?; Ok(()) } fn vendor_display(vendor: &Vendor) -> String { match vendor { Vendor::Custom(custom) => format!("Custom(CustomVendor::Static({:?}))", custom.as_str()), known => format!("{:?}", known), } } target-lexicon/README.md0000644000175000017500000000167514661133735015756 0ustar jamespagejamespageThis is a library for managing targets for compilers and related tools. Currently, the main feature is support for decoding "triples", which are strings that identify a particular target configuration. They're named "triples" because historically they contained three fields, though over time they've added additional fields. This library provides a `Triple` struct containing enums for each of fields of a triple. `Triple` implements `FromStr` and `fmt::Display` so it can be converted to and from the conventional string representation of a triple. `Triple` also has functions for querying a triple's endianness, pointer bit width, and binary format. And, `Triple` and the enum types have `host()` constructors, for targeting the host. It supports all triples currently used by rustc and rustup. It does not support reading JSON target files itself. To use it with a JSON target file, construct a `Triple` using the value of the "llvm-target" field. target-lexicon/examples/0000775000175000017500000000000014661133735016306 5ustar jamespagejamespagetarget-lexicon/examples/misc.rs0000644000175000017500000000062514661133735017610 0ustar jamespagejamespageextern crate target_lexicon; use core::str::FromStr; use target_lexicon::{Triple, HOST}; fn main() { println!("The host triple is {}.", HOST); let e = Triple::from_str("riscv32-unknown-unknown") .expect("expected to recognize the RISC-V target") .endianness() .expect("expected to know the endianness of RISC-V"); println!("The endianness of RISC-V is {:?}.", e); } target-lexicon/examples/host.rs0000644000175000017500000000032014661133735017622 0ustar jamespagejamespageextern crate target_lexicon; use target_lexicon::HOST; fn main() { println!( "{}", HOST.pointer_width() .expect("architecture should be known") .bytes() ); } target-lexicon/Cargo.toml0000644000175000017500000000224414661133735016420 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "target-lexicon" version = "0.12.14" authors = ["Dan Gohman "] description = "Targeting utilities for compilers and related tools" documentation = "https://docs.rs/target-lexicon/" readme = "README.md" keywords = [ "target", "host", "triple", "compiler", "jit", ] categories = ["no-std"] license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/target-lexicon" [dependencies.serde] version = "1.0" optional = true [dev-dependencies.serde_json] version = "1.0" [features] arch_zkasm = [] default = [] serde_support = [ "serde", "std", ] std = [] [badges.maintenance] status = "passively-maintained" target-lexicon/src/0000775000175000017500000000000014661133735015257 5ustar jamespagejamespagetarget-lexicon/src/parse_error.rs0000644000175000017500000000227014661133735020147 0ustar jamespagejamespageuse alloc::string::String; use core::fmt; /// An error returned from parsing a triple. #[derive(Clone, Debug, PartialEq, Eq)] #[allow(missing_docs)] pub enum ParseError { UnrecognizedArchitecture(String), UnrecognizedVendor(String), UnrecognizedOperatingSystem(String), UnrecognizedEnvironment(String), UnrecognizedBinaryFormat(String), UnrecognizedField(String), } impl fmt::Display for ParseError { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { use ParseError::*; match self { UnrecognizedArchitecture(msg) => write!(fmt, "Unrecognized architecture: {}", msg), UnrecognizedVendor(msg) => write!(fmt, "Unrecognized vendor: {}", msg), UnrecognizedOperatingSystem(msg) => { write!(fmt, "Unrecognized operating system: {}", msg) } UnrecognizedEnvironment(msg) => write!(fmt, "Unrecognized environment: {}", msg), UnrecognizedBinaryFormat(msg) => write!(fmt, "Unrecognized binary format: {}", msg), UnrecognizedField(msg) => write!(fmt, "Unrecognized field: {}", msg), } } } #[cfg(feature = "std")] impl std::error::Error for ParseError {} target-lexicon/src/data_model.rs0000644000175000017500000000613014661133735017714 0ustar jamespagejamespage/// The size of a type. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Size { U8, U16, U32, U64, } impl Size { /// Return the number of bits this `Size` represents. pub fn bits(self) -> u8 { use Size::*; match self { U8 => 8, U16 => 16, U32 => 32, U64 => 64, } } /// Return the number of bytes in a size. /// /// A byte is assumed to be 8 bits. pub fn bytes(self) -> u8 { use Size::*; match self { U8 => 1, U16 => 2, U32 => 4, U64 => 8, } } } /// The C data model used on a target. /// /// See also https://en.cppreference.com/w/c/language/arithmetic_types #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "rust_1_40", non_exhaustive)] pub enum CDataModel { /// The data model used most commonly on Win16. `long` and `pointer` are 32 bits. LP32, /// The data model used most commonly on Win32 and 32-bit Unix systems. /// /// `int`, `long`, and `pointer` are all 32 bits. ILP32, /// The data model used most commonly on Win64 /// /// `long long`, and `pointer` are 64 bits. LLP64, /// The data model used most commonly on 64-bit Unix systems /// /// `long`, and `pointer` are 64 bits. LP64, /// A rare data model used on early 64-bit Unix systems /// /// `int`, `long`, and `pointer` are all 64 bits. ILP64, } impl CDataModel { /// The width of a pointer (in the default address space). pub fn pointer_width(self) -> Size { use CDataModel::*; match self { LP32 | ILP32 => Size::U32, LLP64 | LP64 | ILP64 => Size::U64, } } /// The size of a C `short`. This is required to be at least 16 bits. pub fn short_size(self) -> Size { use CDataModel::*; match self { LP32 | ILP32 | LLP64 | LP64 | ILP64 => Size::U16, } } /// The size of a C `int`. This is required to be at least 16 bits. pub fn int_size(self) -> Size { use CDataModel::*; match self { LP32 => Size::U16, ILP32 | LLP64 | LP64 | ILP64 => Size::U32, } } /// The size of a C `long`. This is required to be at least 32 bits. pub fn long_size(self) -> Size { use CDataModel::*; match self { LP32 | ILP32 | LLP64 | ILP64 => Size::U32, LP64 => Size::U64, } } /// The size of a C `long long`. This is required (in C99+) to be at least 64 bits. pub fn long_long_size(self) -> Size { use CDataModel::*; match self { LP32 | ILP32 | LLP64 | ILP64 | LP64 => Size::U64, } } /// The size of a C `float`. pub fn float_size(self) -> Size { // TODO: this is probably wrong on at least one architecture Size::U32 } /// The size of a C `double`. pub fn double_size(self) -> Size { // TODO: this is probably wrong on at least one architecture Size::U64 } } target-lexicon/src/lib.rs0000644000175000017500000000603214661133735016372 0ustar jamespagejamespage//! Target triple support. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] #![warn(unused_import_braces)] #![cfg_attr( feature = "cargo-clippy", warn( clippy::float_arithmetic, clippy::mut_mut, clippy::nonminimal_bool, clippy::option_map_unwrap_or, clippy::option_map_unwrap_or_else, clippy::print_stdout, clippy::unicode_not_nfc, clippy::use_self, ) )] #![cfg_attr(not(feature = "std"), no_std)] #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(feature = "std")] extern crate std as alloc; mod data_model; mod host; mod parse_error; mod targets; #[macro_use] mod triple; pub use self::data_model::{CDataModel, Size}; pub use self::host::HOST; pub use self::parse_error::ParseError; pub use self::targets::{ Aarch64Architecture, Architecture, ArmArchitecture, BinaryFormat, CustomVendor, Environment, Mips32Architecture, Mips64Architecture, OperatingSystem, Riscv32Architecture, Riscv64Architecture, Vendor, X86_32Architecture, }; pub use self::triple::{CallingConvention, Endianness, PointerWidth, Triple}; /// A simple wrapper around `Triple` that provides an implementation of /// `Default` which defaults to `Triple::host()`. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DefaultToHost(pub Triple); impl Default for DefaultToHost { fn default() -> Self { Self(Triple::host()) } } /// A simple wrapper around `Triple` that provides an implementation of /// `Default` which defaults to `Triple::unknown()`. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct DefaultToUnknown(pub Triple); impl Default for DefaultToUnknown { fn default() -> Self { Self(Triple::unknown()) } } // For some reason, the below `serde` impls don't work when they're in the // `triple` module. #[cfg(feature = "serde_support")] impl serde::Serialize for Triple { fn serialize(&self, serializer: S) -> Result { serializer.serialize_str(&self.to_string()) } } #[cfg(feature = "serde_support")] impl<'de> serde::de::Deserialize<'de> for Triple { fn deserialize>(deserializer: D) -> Result { let s = String::deserialize(deserializer)?; s.parse().map_err(serde::de::Error::custom) } } #[cfg(feature = "serde_support")] #[test] fn test_serialize() { let triples: Vec = vec![ "x86_64-unknown-linux-gnu".parse().unwrap(), "i686-pc-windows-gnu".parse().unwrap(), ]; let json = serde_json::to_string(&triples).unwrap(); assert_eq!( json, r#"["x86_64-unknown-linux-gnu","i686-pc-windows-gnu"]"# ); } #[cfg(feature = "serde_support")] #[test] fn test_deserialize() { let triples: Vec = vec![ "x86_64-unknown-linux-gnu".parse().unwrap(), "i686-pc-windows-gnu".parse().unwrap(), ]; let vals: Vec = serde_json::from_str(r#"["x86_64-unknown-linux-gnu","i686-pc-windows-gnu"]"#).unwrap(); assert_eq!(vals, triples); } target-lexicon/src/triple.rs0000644000175000017500000004703114661133735017127 0ustar jamespagejamespage// This file defines the `Triple` type and support code shared by all targets. use crate::data_model::CDataModel; use crate::parse_error::ParseError; use crate::targets::{ default_binary_format, Architecture, ArmArchitecture, BinaryFormat, Environment, OperatingSystem, Riscv32Architecture, Vendor, }; #[cfg(not(feature = "std"))] use alloc::borrow::ToOwned; use core::fmt; use core::str::FromStr; /// The target memory endianness. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Endianness { Little, Big, } /// The width of a pointer (in the default address space). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum PointerWidth { U16, U32, U64, } impl PointerWidth { /// Return the number of bits in a pointer. pub fn bits(self) -> u8 { match self { PointerWidth::U16 => 16, PointerWidth::U32 => 32, PointerWidth::U64 => 64, } } /// Return the number of bytes in a pointer. /// /// For these purposes, there are 8 bits in a byte. pub fn bytes(self) -> u8 { match self { PointerWidth::U16 => 2, PointerWidth::U32 => 4, PointerWidth::U64 => 8, } } } /// The calling convention, which specifies things like which registers are /// used for passing arguments, which registers are callee-saved, and so on. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum CallingConvention { /// "System V", which is used on most Unix-like platfoms. Note that the /// specific conventions vary between hardware architectures; for example, /// x86-32's "System V" is entirely different from x86-64's "System V". SystemV, /// The WebAssembly C ABI. /// https://github.com/WebAssembly/tool-conventions/blob/master/BasicCABI.md WasmBasicCAbi, /// "Windows Fastcall", which is used on Windows. Note that like "System V", /// this varies between hardware architectures. On x86-32 it describes what /// Windows documentation calls "fastcall", and on x86-64 it describes what /// Windows documentation often just calls the Windows x64 calling convention /// (though the compiler still recognizes "fastcall" as an alias for it). WindowsFastcall, /// Apple Aarch64 platforms use their own variant of the common Aarch64 /// calling convention. /// /// AppleAarch64, } /// A target "triple". Historically such things had three fields, though they've /// added additional fields over time. /// /// Note that `Triple` doesn't implement `Default` itself. If you want a type /// which defaults to the host triple, or defaults to unknown-unknown-unknown, /// use `DefaultToHost` or `DefaultToUnknown`, respectively. #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Triple { /// The "architecture" (and sometimes the subarchitecture). pub architecture: Architecture, /// The "vendor" (whatever that means). pub vendor: Vendor, /// The "operating system" (sometimes also the environment). pub operating_system: OperatingSystem, /// The "environment" on top of the operating system (often omitted for /// operating systems with a single predominant environment). pub environment: Environment, /// The "binary format" (rarely used). pub binary_format: BinaryFormat, } impl Triple { /// Return the endianness of this target's architecture. pub fn endianness(&self) -> Result { self.architecture.endianness() } /// Return the pointer width of this target's architecture. /// /// This function is aware of x32 and ilp32 ABIs on 64-bit architectures. pub fn pointer_width(&self) -> Result { // Some ABIs have a different pointer width than the CPU architecture. match self.environment { Environment::Gnux32 | Environment::GnuIlp32 => return Ok(PointerWidth::U32), _ => {} } self.architecture.pointer_width() } /// Return the default calling convention for the given target triple. pub fn default_calling_convention(&self) -> Result { Ok(match self.operating_system { OperatingSystem::Darwin | OperatingSystem::Ios | OperatingSystem::Tvos | OperatingSystem::MacOSX { .. } | OperatingSystem::Watchos => match self.architecture { Architecture::Aarch64(_) => CallingConvention::AppleAarch64, _ => CallingConvention::SystemV, }, OperatingSystem::Aix | OperatingSystem::Bitrig | OperatingSystem::Cloudabi | OperatingSystem::Dragonfly | OperatingSystem::Freebsd | OperatingSystem::Fuchsia | OperatingSystem::Haiku | OperatingSystem::Hermit | OperatingSystem::L4re | OperatingSystem::Linux | OperatingSystem::Netbsd | OperatingSystem::Openbsd | OperatingSystem::Redox | OperatingSystem::Solaris => CallingConvention::SystemV, OperatingSystem::Windows => CallingConvention::WindowsFastcall, OperatingSystem::Nebulet | OperatingSystem::Emscripten | OperatingSystem::Wasi | OperatingSystem::Unknown => match self.architecture { Architecture::Wasm32 => CallingConvention::WasmBasicCAbi, _ => return Err(()), }, _ => return Err(()), }) } /// The C data model for a given target. If the model is not known, returns `Err(())`. pub fn data_model(&self) -> Result { match self.pointer_width()? { PointerWidth::U64 => { if self.operating_system == OperatingSystem::Windows { Ok(CDataModel::LLP64) } else if self.default_calling_convention() == Ok(CallingConvention::SystemV) || self.architecture == Architecture::Wasm64 { Ok(CDataModel::LP64) } else { Err(()) } } PointerWidth::U32 => { if self.operating_system == OperatingSystem::Windows || self.default_calling_convention() == Ok(CallingConvention::SystemV) || self.architecture == Architecture::Wasm32 { Ok(CDataModel::ILP32) } else { Err(()) } } // TODO: on 16-bit machines there is usually a distinction // between near-pointers and far-pointers. // Additionally, code pointers sometimes have a different size than data pointers. // We don't handle this case. PointerWidth::U16 => Err(()), } } /// Return a `Triple` with all unknown fields. pub fn unknown() -> Self { Self { architecture: Architecture::Unknown, vendor: Vendor::Unknown, operating_system: OperatingSystem::Unknown, environment: Environment::Unknown, binary_format: BinaryFormat::Unknown, } } } impl fmt::Display for Triple { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(res) = self.special_case_display(f) { return res; } let implied_binary_format = default_binary_format(&self); write!(f, "{}", self.architecture)?; if self.vendor == Vendor::Unknown && (self.environment != Environment::HermitKernel && self.environment != Environment::LinuxKernel) && ((self.operating_system == OperatingSystem::Linux && (self.environment == Environment::Android || self.environment == Environment::Androideabi || self.environment == Environment::Kernel)) || self.operating_system == OperatingSystem::Fuchsia || self.operating_system == OperatingSystem::Wasi || self.operating_system == OperatingSystem::WasiP1 || self.operating_system == OperatingSystem::WasiP2 || (self.operating_system == OperatingSystem::None_ && (self.architecture == Architecture::Arm(ArmArchitecture::Armv4t) || self.architecture == Architecture::Arm(ArmArchitecture::Armv5te) || self.architecture == Architecture::Arm(ArmArchitecture::Armebv7r) || self.architecture == Architecture::Arm(ArmArchitecture::Armv7a) || self.architecture == Architecture::Arm(ArmArchitecture::Armv7r) || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv4t) || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv5te) || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv6m) || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv7em) || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv7m) || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv8mBase) || self.architecture == Architecture::Arm(ArmArchitecture::Thumbv8mMain) || self.architecture == Architecture::Msp430))) { // As a special case, omit the vendor for Android, Fuchsia, Wasi, and sometimes // None_, depending on the hardware architecture. This logic is entirely // ad-hoc, and is just sufficient to handle the current set of recognized // triples. write!(f, "-{}", self.operating_system)?; } else if self.architecture.is_clever() && self.operating_system == OperatingSystem::Unknown { write!(f, "-{}", self.vendor)?; } else { write!(f, "-{}-{}", self.vendor, self.operating_system)?; } match (&self.vendor, self.operating_system, self.environment) { (Vendor::Nintendo, OperatingSystem::Horizon, Environment::Newlib) | (Vendor::Espressif, OperatingSystem::Espidf, Environment::Newlib) => { // The triple representations of these platforms don't have an environment field. } (_, _, Environment::Unknown) => { // Don't print out the environment if it is unknown. } _ => { write!(f, "-{}", self.environment)?; } } if self.binary_format != implied_binary_format { write!(f, "-{}", self.binary_format)?; } Ok(()) } } impl FromStr for Triple { type Err = ParseError; fn from_str(s: &str) -> Result { if let Some(triple) = Triple::special_case_from_str(s) { return Ok(triple); } let mut parts = s.split('-'); let mut result = Self::unknown(); let mut current_part; current_part = parts.next(); if let Some(s) = current_part { if let Ok(architecture) = Architecture::from_str(s) { result.architecture = architecture; current_part = parts.next(); } else { // Insist that the triple start with a valid architecture. return Err(ParseError::UnrecognizedArchitecture(s.to_owned())); } } let mut has_vendor = false; let mut has_operating_system = false; if let Some(s) = current_part { if let Ok(vendor) = Vendor::from_str(s) { has_vendor = true; result.vendor = vendor; current_part = parts.next(); } } if !has_operating_system { if let Some(s) = current_part { if let Ok(operating_system) = OperatingSystem::from_str(s) { has_operating_system = true; result.operating_system = operating_system; current_part = parts.next(); } } } let mut has_environment = false; if !has_environment { if let Some(s) = current_part { if let Ok(environment) = Environment::from_str(s) { has_environment = true; result.environment = environment; current_part = parts.next(); } } } let mut has_binary_format = false; if let Some(s) = current_part { if let Ok(binary_format) = BinaryFormat::from_str(s) { has_binary_format = true; result.binary_format = binary_format; current_part = parts.next(); } } // The binary format is frequently omitted; if that's the case here, // infer it from the other fields. if !has_binary_format { result.binary_format = default_binary_format(&result); } if let Some(s) = current_part { Err( if !has_vendor && !has_operating_system && !has_environment && !has_binary_format { ParseError::UnrecognizedVendor(s.to_owned()) } else if !has_operating_system && !has_environment && !has_binary_format { ParseError::UnrecognizedOperatingSystem(s.to_owned()) } else if !has_environment && !has_binary_format { ParseError::UnrecognizedEnvironment(s.to_owned()) } else if !has_binary_format { ParseError::UnrecognizedBinaryFormat(s.to_owned()) } else { ParseError::UnrecognizedField(s.to_owned()) }, ) } else { Ok(result) } } } impl Triple { /// Handle special cases in the `Display` implementation. fn special_case_display(&self, f: &mut fmt::Formatter) -> Option { let res = match self { Triple { architecture: Architecture::Arm(ArmArchitecture::Armv6k), vendor: Vendor::Nintendo, operating_system: OperatingSystem::Horizon, .. } => write!(f, "{}-{}-3ds", self.architecture, self.vendor), Triple { architecture: Architecture::Riscv32(Riscv32Architecture::Riscv32imc), vendor: Vendor::Espressif, operating_system: OperatingSystem::Espidf, .. } => write!(f, "{}-esp-{}", self.architecture, self.operating_system), _ => return None, }; Some(res) } /// Handle special cases in the `FromStr` implementation. fn special_case_from_str(s: &str) -> Option { let mut triple = Triple::unknown(); match s { "armv6k-nintendo-3ds" => { triple.architecture = Architecture::Arm(ArmArchitecture::Armv6k); triple.vendor = Vendor::Nintendo; triple.operating_system = OperatingSystem::Horizon; triple.environment = Environment::Newlib; triple.binary_format = default_binary_format(&triple); } "riscv32imc-esp-espidf" => { triple.architecture = Architecture::Riscv32(Riscv32Architecture::Riscv32imc); triple.vendor = Vendor::Espressif; triple.operating_system = OperatingSystem::Espidf; triple.environment = Environment::Newlib; triple.binary_format = default_binary_format(&triple); } _ => return None, } Some(triple) } } /// A convenient syntax for triple literals. /// /// This currently expands to code that just calls `Triple::from_str` and does /// an `expect`, though in the future it would be cool to use procedural macros /// or so to report errors at compile time instead. #[macro_export] macro_rules! triple { ($str:tt) => { <$crate::Triple as core::str::FromStr>::from_str($str).expect("invalid triple literal") }; } #[cfg(test)] mod tests { use super::*; #[test] fn parse_errors() { assert_eq!( Triple::from_str(""), Err(ParseError::UnrecognizedArchitecture("".to_owned())) ); assert_eq!( Triple::from_str("foo"), Err(ParseError::UnrecognizedArchitecture("foo".to_owned())) ); assert_eq!( Triple::from_str("unknown-unknown-foo"), Err(ParseError::UnrecognizedOperatingSystem("foo".to_owned())) ); assert_eq!( Triple::from_str("unknown-unknown-unknown-foo"), Err(ParseError::UnrecognizedEnvironment("foo".to_owned())) ); assert_eq!( Triple::from_str("unknown-unknown-unknown-unknown-foo"), Err(ParseError::UnrecognizedBinaryFormat("foo".to_owned())) ); assert_eq!( Triple::from_str("unknown-unknown-unknown-unknown-unknown-foo"), Err(ParseError::UnrecognizedField("foo".to_owned())) ); } #[test] fn defaults() { assert_eq!( Triple::from_str("unknown-unknown-unknown"), Ok(Triple::unknown()) ); assert_eq!( Triple::from_str("unknown-unknown-unknown-unknown"), Ok(Triple::unknown()) ); assert_eq!( Triple::from_str("unknown-unknown-unknown-unknown-unknown"), Ok(Triple::unknown()) ); } #[test] fn unknown_properties() { assert_eq!(Triple::unknown().endianness(), Err(())); assert_eq!(Triple::unknown().pointer_width(), Err(())); assert_eq!(Triple::unknown().default_calling_convention(), Err(())); } #[test] fn apple_calling_convention() { for triple in &[ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-macabi", "aarch64-apple-tvos", "aarch64-apple-watchos", ] { assert_eq!( Triple::from_str(triple) .unwrap() .default_calling_convention() .unwrap(), CallingConvention::AppleAarch64 ); } for triple in &["aarch64-linux-android", "x86_64-apple-ios"] { assert_eq!( Triple::from_str(triple) .unwrap() .default_calling_convention() .unwrap(), CallingConvention::SystemV ); } } #[test] fn p32_abi() { // Test that special 32-bit pointer ABIs on 64-bit architectures are // reported as having 32-bit pointers. for triple in &[ "x86_64-unknown-linux-gnux32", "aarch64_be-unknown-linux-gnu_ilp32", "aarch64-unknown-linux-gnu_ilp32", ] { assert_eq!( Triple::from_str(triple).unwrap().pointer_width().unwrap(), PointerWidth::U32 ); } // Test that the corresponding ABIs have 64-bit pointers. for triple in &[ "x86_64-unknown-linux-gnu", "aarch64_be-unknown-linux-gnu", "aarch64-unknown-linux-gnu", ] { assert_eq!( Triple::from_str(triple).unwrap().pointer_width().unwrap(), PointerWidth::U64 ); } } } target-lexicon/src/targets.rs0000644000175000017500000015412014661133735017277 0ustar jamespagejamespage// This file defines all the identifier enums and target-aware logic. use crate::triple::{Endianness, PointerWidth, Triple}; use alloc::borrow::Cow; use alloc::boxed::Box; use alloc::format; use alloc::string::String; use core::fmt; use core::hash::{Hash, Hasher}; use core::str::FromStr; /// The "architecture" field, which in some cases also specifies a specific /// subarchitecture. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Architecture { Unknown, Arm(ArmArchitecture), AmdGcn, Aarch64(Aarch64Architecture), Asmjs, Avr, Bpfeb, Bpfel, Hexagon, X86_32(X86_32Architecture), M68k, LoongArch64, Mips32(Mips32Architecture), Mips64(Mips64Architecture), Msp430, Nvptx64, Powerpc, Powerpc64, Powerpc64le, Riscv32(Riscv32Architecture), Riscv64(Riscv64Architecture), S390x, Sparc, Sparc64, Sparcv9, Wasm32, Wasm64, X86_64, /// x86_64 target that only supports Haswell-compatible Intel chips. X86_64h, XTensa, Clever(CleverArchitecture), /// A software machine that produces zero-knowledge proofs of the execution. /// /// See https://wiki.polygon.technology/docs/category/zk-assembly/ #[cfg(feature = "arch_zkasm")] ZkAsm, } #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum ArmArchitecture { Arm, // Generic arm Armeb, Armv4, Armv4t, Armv5t, Armv5te, Armv5tej, Armv6, Armv6j, Armv6k, Armv6z, Armv6kz, Armv6t2, Armv6m, Armv7, Armv7a, Armv7k, Armv7ve, Armv7m, Armv7r, Armv7s, Armv8, Armv8a, Armv8_1a, Armv8_2a, Armv8_3a, Armv8_4a, Armv8_5a, Armv8mBase, Armv8mMain, Armv8r, Armebv7r, Thumbeb, Thumbv4t, Thumbv5te, Thumbv6m, Thumbv7a, Thumbv7em, Thumbv7m, Thumbv7neon, Thumbv8mBase, Thumbv8mMain, } #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Aarch64Architecture { Aarch64, Aarch64be, } // #[cfg_attr(feature = "rust_1_40", non_exhaustive)] // #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] // #[allow(missing_docs)] // pub enum ArmFpu { // Vfp, // Vfpv2, // Vfpv3, // Vfpv3Fp16, // Vfpv3Xd, // Vfpv3XdFp16, // Neon, // NeonVfpv3, // NeonVfpv4, // Vfpv4, // Vfpv4D16, // Fpv4SpD16, // Fpv5SpD16, // Fpv5D16, // FpArmv8, // NeonFpArmv8, // CryptoNeonFpArmv8, // } impl ArmArchitecture { /// Test if this architecture uses the Thumb instruction set. #[rustfmt::skip] pub fn is_thumb(self) -> bool { use ArmArchitecture::*; match self { Arm | Armeb | Armv4 | Armv4t | Armv5t | Armv5te | Armv5tej | Armv6 | Armv6j | Armv6k | Armv6z | Armv6kz | Armv6t2 | Armv6m | Armv7 | Armv7a | Armv7k | Armv7ve | Armv7m | Armv7r | Armv7s | Armv8 | Armv8a | Armv8_1a | Armv8_2a | Armv8_3a | Armv8_4a | Armv8_5a | Armv8mBase | Armv8mMain | Armv8r | Armebv7r => false, Thumbeb | Thumbv4t | Thumbv5te | Thumbv6m | Thumbv7a | Thumbv7em | Thumbv7m | Thumbv7neon | Thumbv8mBase | Thumbv8mMain => true, } } // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> { // } /// Return the pointer bit width of this target's architecture. #[rustfmt::skip] pub fn pointer_width(self) -> PointerWidth { use ArmArchitecture::*; match self { Arm | Armeb | Armv4 | Armv4t | Armv5t | Armv5te | Armv5tej | Armv6 | Armv6j | Armv6k | Armv6z | Armv6kz | Armv6t2 | Armv6m | Armv7 | Armv7a | Armv7k | Armv7ve | Armv7m | Armv7r | Armv7s | Armv8 | Armv8a | Armv8_1a | Armv8_2a | Armv8_3a | Armv8_4a | Armv8_5a | Armv8mBase | Armv8mMain | Armv8r | Armebv7r | Thumbeb | Thumbv4t | Thumbv5te | Thumbv6m | Thumbv7a | Thumbv7em | Thumbv7m | Thumbv7neon | Thumbv8mBase | Thumbv8mMain => PointerWidth::U32, } } /// Return the endianness of this architecture. #[rustfmt::skip] pub fn endianness(self) -> Endianness { use ArmArchitecture::*; match self { Arm | Armv4 | Armv4t | Armv5t | Armv5te | Armv5tej | Armv6 | Armv6j | Armv6k | Armv6z | Armv6kz | Armv6t2 | Armv6m | Armv7 | Armv7a | Armv7k | Armv7ve | Armv7m | Armv7r | Armv7s | Armv8 | Armv8a | Armv8_1a | Armv8_2a | Armv8_3a | Armv8_4a | Armv8_5a | Armv8mBase | Armv8mMain | Armv8r | Thumbv4t | Thumbv5te | Thumbv6m | Thumbv7a | Thumbv7em | Thumbv7m | Thumbv7neon | Thumbv8mBase | Thumbv8mMain => Endianness::Little, Armeb | Armebv7r | Thumbeb => Endianness::Big, } } /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use ArmArchitecture::*; match self { Arm => Cow::Borrowed("arm"), Armeb => Cow::Borrowed("armeb"), Armv4 => Cow::Borrowed("armv4"), Armv4t => Cow::Borrowed("armv4t"), Armv5t => Cow::Borrowed("armv5t"), Armv5te => Cow::Borrowed("armv5te"), Armv5tej => Cow::Borrowed("armv5tej"), Armv6 => Cow::Borrowed("armv6"), Armv6j => Cow::Borrowed("armv6j"), Armv6k => Cow::Borrowed("armv6k"), Armv6z => Cow::Borrowed("armv6z"), Armv6kz => Cow::Borrowed("armv6kz"), Armv6t2 => Cow::Borrowed("armv6t2"), Armv6m => Cow::Borrowed("armv6m"), Armv7 => Cow::Borrowed("armv7"), Armv7a => Cow::Borrowed("armv7a"), Armv7k => Cow::Borrowed("armv7k"), Armv7ve => Cow::Borrowed("armv7ve"), Armv7m => Cow::Borrowed("armv7m"), Armv7r => Cow::Borrowed("armv7r"), Armv7s => Cow::Borrowed("armv7s"), Armv8 => Cow::Borrowed("armv8"), Armv8a => Cow::Borrowed("armv8a"), Armv8_1a => Cow::Borrowed("armv8.1a"), Armv8_2a => Cow::Borrowed("armv8.2a"), Armv8_3a => Cow::Borrowed("armv8.3a"), Armv8_4a => Cow::Borrowed("armv8.4a"), Armv8_5a => Cow::Borrowed("armv8.5a"), Armv8mBase => Cow::Borrowed("armv8m.base"), Armv8mMain => Cow::Borrowed("armv8m.main"), Armv8r => Cow::Borrowed("armv8r"), Thumbeb => Cow::Borrowed("thumbeb"), Thumbv4t => Cow::Borrowed("thumbv4t"), Thumbv5te => Cow::Borrowed("thumbv5te"), Thumbv6m => Cow::Borrowed("thumbv6m"), Thumbv7a => Cow::Borrowed("thumbv7a"), Thumbv7em => Cow::Borrowed("thumbv7em"), Thumbv7m => Cow::Borrowed("thumbv7m"), Thumbv7neon => Cow::Borrowed("thumbv7neon"), Thumbv8mBase => Cow::Borrowed("thumbv8m.base"), Thumbv8mMain => Cow::Borrowed("thumbv8m.main"), Armebv7r => Cow::Borrowed("armebv7r"), } } } impl Aarch64Architecture { /// Test if this architecture uses the Thumb instruction set. pub fn is_thumb(self) -> bool { match self { Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => false, } } // pub fn has_fpu(self) -> Result<&'static [ArmFpu], ()> { // } /// Return the pointer bit width of this target's architecture. /// /// This function is only aware of the CPU architecture so it is not aware /// of ilp32 ABIs. pub fn pointer_width(self) -> PointerWidth { match self { Aarch64Architecture::Aarch64 | Aarch64Architecture::Aarch64be => PointerWidth::U64, } } /// Return the endianness of this architecture. pub fn endianness(self) -> Endianness { match self { Aarch64Architecture::Aarch64 => Endianness::Little, Aarch64Architecture::Aarch64be => Endianness::Big, } } /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use Aarch64Architecture::*; match self { Aarch64 => Cow::Borrowed("aarch64"), Aarch64be => Cow::Borrowed("aarch64_be"), } } } #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum CleverArchitecture { Clever, Clever1_0, } impl CleverArchitecture { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use CleverArchitecture::*; match self { Clever => Cow::Borrowed("clever"), Clever1_0 => Cow::Borrowed("clever1.0"), } } } /// An enum for all 32-bit RISC-V architectures. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Riscv32Architecture { Riscv32, Riscv32gc, Riscv32i, Riscv32im, Riscv32imac, Riscv32imc, } impl Riscv32Architecture { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use Riscv32Architecture::*; match self { Riscv32 => Cow::Borrowed("riscv32"), Riscv32gc => Cow::Borrowed("riscv32gc"), Riscv32i => Cow::Borrowed("riscv32i"), Riscv32im => Cow::Borrowed("riscv32im"), Riscv32imac => Cow::Borrowed("riscv32imac"), Riscv32imc => Cow::Borrowed("riscv32imc"), } } } /// An enum for all 64-bit RISC-V architectures. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Riscv64Architecture { Riscv64, Riscv64gc, Riscv64imac, } impl Riscv64Architecture { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use Riscv64Architecture::*; match self { Riscv64 => Cow::Borrowed("riscv64"), Riscv64gc => Cow::Borrowed("riscv64gc"), Riscv64imac => Cow::Borrowed("riscv64imac"), } } } /// An enum for all 32-bit x86 architectures. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum X86_32Architecture { I386, I586, I686, } impl X86_32Architecture { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use X86_32Architecture::*; match self { I386 => Cow::Borrowed("i386"), I586 => Cow::Borrowed("i586"), I686 => Cow::Borrowed("i686"), } } } /// An enum for all 32-bit MIPS architectures (not just "MIPS32"). #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Mips32Architecture { Mips, Mipsel, Mipsisa32r6, Mipsisa32r6el, } impl Mips32Architecture { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use Mips32Architecture::*; match self { Mips => Cow::Borrowed("mips"), Mipsel => Cow::Borrowed("mipsel"), Mipsisa32r6 => Cow::Borrowed("mipsisa32r6"), Mipsisa32r6el => Cow::Borrowed("mipsisa32r6el"), } } } /// An enum for all 64-bit MIPS architectures (not just "MIPS64"). #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Mips64Architecture { Mips64, Mips64el, Mipsisa64r6, Mipsisa64r6el, } impl Mips64Architecture { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use Mips64Architecture::*; match self { Mips64 => Cow::Borrowed("mips64"), Mips64el => Cow::Borrowed("mips64el"), Mipsisa64r6 => Cow::Borrowed("mipsisa64r6"), Mipsisa64r6el => Cow::Borrowed("mipsisa64r6el"), } } } /// A string for a `Vendor::Custom` that can either be used in `const` /// contexts or hold dynamic strings. #[derive(Clone, Debug, Eq)] pub enum CustomVendor { /// An owned `String`. This supports the general case. Owned(Box), /// A static `str`, so that `CustomVendor` can be constructed in `const` /// contexts. Static(&'static str), } impl CustomVendor { /// Extracts a string slice. pub fn as_str(&self) -> &str { match self { CustomVendor::Owned(s) => s, CustomVendor::Static(s) => s, } } } impl PartialEq for CustomVendor { fn eq(&self, other: &Self) -> bool { self.as_str() == other.as_str() } } impl Hash for CustomVendor { fn hash(&self, state: &mut H) { self.as_str().hash(state) } } /// The "vendor" field, which in practice is little more than an arbitrary /// modifier. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Vendor { Unknown, Amd, Apple, Espressif, Experimental, Fortanix, Ibm, Kmc, Nintendo, Nvidia, Pc, Rumprun, Sun, Uwp, Wrs, /// A custom vendor. "Custom" in this context means that the vendor is /// not specifically recognized by upstream Autotools, LLVM, Rust, or other /// relevant authorities on triple naming. It's useful for people building /// and using locally patched toolchains. /// /// Outside of such patched environments, users of `target-lexicon` should /// treat `Custom` the same as `Unknown` and ignore the string. Custom(CustomVendor), } impl Vendor { /// Extracts a string slice. pub fn as_str(&self) -> &str { use Vendor::*; match self { Unknown => "unknown", Amd => "amd", Apple => "apple", Espressif => "espressif", Experimental => "experimental", Fortanix => "fortanix", Ibm => "ibm", Kmc => "kmc", Nintendo => "nintendo", Nvidia => "nvidia", Pc => "pc", Rumprun => "rumprun", Sun => "sun", Uwp => "uwp", Wrs => "wrs", Custom(name) => name.as_str(), } } } /// The "operating system" field, which sometimes implies an environment, and /// sometimes isn't an actual operating system. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum OperatingSystem { Unknown, Aix, AmdHsa, Bitrig, Cloudabi, Cuda, Darwin, Dragonfly, Emscripten, Espidf, Freebsd, Fuchsia, Haiku, Hermit, Horizon, Illumos, Ios, L4re, Linux, MacOSX { major: u16, minor: u16, patch: u16 }, Nebulet, Netbsd, None_, Openbsd, Psp, Redox, Solaris, SolidAsp3, Tvos, Uefi, VxWorks, Wasi, WasiP1, WasiP2, Watchos, Windows, } impl OperatingSystem { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use OperatingSystem::*; match self { Unknown => Cow::Borrowed("unknown"), Aix => Cow::Borrowed("aix"), AmdHsa => Cow::Borrowed("amdhsa"), Bitrig => Cow::Borrowed("bitrig"), Cloudabi => Cow::Borrowed("cloudabi"), Cuda => Cow::Borrowed("cuda"), Darwin => Cow::Borrowed("darwin"), Dragonfly => Cow::Borrowed("dragonfly"), Emscripten => Cow::Borrowed("emscripten"), Espidf => Cow::Borrowed("espidf"), Freebsd => Cow::Borrowed("freebsd"), Fuchsia => Cow::Borrowed("fuchsia"), Haiku => Cow::Borrowed("haiku"), Hermit => Cow::Borrowed("hermit"), Horizon => Cow::Borrowed("horizon"), Illumos => Cow::Borrowed("illumos"), Ios => Cow::Borrowed("ios"), L4re => Cow::Borrowed("l4re"), Linux => Cow::Borrowed("linux"), MacOSX { major, minor, patch, } => Cow::Owned(format!("macosx{}.{}.{}", major, minor, patch)), Nebulet => Cow::Borrowed("nebulet"), Netbsd => Cow::Borrowed("netbsd"), None_ => Cow::Borrowed("none"), Openbsd => Cow::Borrowed("openbsd"), Psp => Cow::Borrowed("psp"), Redox => Cow::Borrowed("redox"), Solaris => Cow::Borrowed("solaris"), SolidAsp3 => Cow::Borrowed("solid_asp3"), Tvos => Cow::Borrowed("tvos"), Uefi => Cow::Borrowed("uefi"), VxWorks => Cow::Borrowed("vxworks"), Wasi => Cow::Borrowed("wasi"), WasiP1 => Cow::Borrowed("wasip1"), WasiP2 => Cow::Borrowed("wasip2"), Watchos => Cow::Borrowed("watchos"), Windows => Cow::Borrowed("windows"), } } } /// The "environment" field, which specifies an ABI environment on top of the /// operating system. In many configurations, this field is omitted, and the /// environment is implied by the operating system. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum Environment { Unknown, AmdGiz, Android, Androideabi, Eabi, Eabihf, Gnu, Gnuabi64, Gnueabi, Gnueabihf, Gnuspe, Gnux32, GnuIlp32, GnuLlvm, HermitKernel, LinuxKernel, Macabi, Musl, Musleabi, Musleabihf, Muslabi64, Msvc, Newlib, Kernel, Uclibc, Uclibceabi, Uclibceabihf, Sgx, Sim, Softfloat, Spe, Threads, } impl Environment { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use Environment::*; match self { Unknown => Cow::Borrowed("unknown"), AmdGiz => Cow::Borrowed("amdgiz"), Android => Cow::Borrowed("android"), Androideabi => Cow::Borrowed("androideabi"), Eabi => Cow::Borrowed("eabi"), Eabihf => Cow::Borrowed("eabihf"), Gnu => Cow::Borrowed("gnu"), Gnuabi64 => Cow::Borrowed("gnuabi64"), Gnueabi => Cow::Borrowed("gnueabi"), Gnueabihf => Cow::Borrowed("gnueabihf"), Gnuspe => Cow::Borrowed("gnuspe"), Gnux32 => Cow::Borrowed("gnux32"), GnuIlp32 => Cow::Borrowed("gnu_ilp32"), GnuLlvm => Cow::Borrowed("gnullvm"), HermitKernel => Cow::Borrowed("hermitkernel"), LinuxKernel => Cow::Borrowed("linuxkernel"), Macabi => Cow::Borrowed("macabi"), Musl => Cow::Borrowed("musl"), Musleabi => Cow::Borrowed("musleabi"), Musleabihf => Cow::Borrowed("musleabihf"), Muslabi64 => Cow::Borrowed("muslabi64"), Msvc => Cow::Borrowed("msvc"), Newlib => Cow::Borrowed("newlib"), Kernel => Cow::Borrowed("kernel"), Uclibc => Cow::Borrowed("uclibc"), Uclibceabi => Cow::Borrowed("uclibceabi"), Uclibceabihf => Cow::Borrowed("uclibceabihf"), Sgx => Cow::Borrowed("sgx"), Sim => Cow::Borrowed("sim"), Softfloat => Cow::Borrowed("softfloat"), Spe => Cow::Borrowed("spe"), Threads => Cow::Borrowed("threads"), } } } /// The "binary format" field, which is usually omitted, and the binary format /// is implied by the other fields. #[cfg_attr(feature = "rust_1_40", non_exhaustive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[allow(missing_docs)] pub enum BinaryFormat { Unknown, Elf, Coff, Macho, Wasm, Xcoff, } impl BinaryFormat { /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use BinaryFormat::*; match self { Unknown => Cow::Borrowed("unknown"), Elf => Cow::Borrowed("elf"), Coff => Cow::Borrowed("coff"), Macho => Cow::Borrowed("macho"), Wasm => Cow::Borrowed("wasm"), Xcoff => Cow::Borrowed("xcoff"), } } } impl Architecture { /// Return the endianness of this architecture. #[rustfmt::skip] pub fn endianness(self) -> Result { use Architecture::*; match self { Unknown => Err(()), Arm(arm) => Ok(arm.endianness()), Aarch64(aarch) => Ok(aarch.endianness()), AmdGcn | Asmjs | Avr | Bpfel | Hexagon | X86_32(_) | LoongArch64 | Mips64(Mips64Architecture::Mips64el) | Mips32(Mips32Architecture::Mipsel) | Mips32(Mips32Architecture::Mipsisa32r6el) | Mips64(Mips64Architecture::Mipsisa64r6el) | Msp430 | Nvptx64 | Powerpc64le | Riscv32(_) | Riscv64(_) | Wasm32 | Wasm64 | X86_64 | X86_64h | XTensa | Clever(_) => Ok(Endianness::Little), Bpfeb | M68k | Mips32(Mips32Architecture::Mips) | Mips64(Mips64Architecture::Mips64) | Mips32(Mips32Architecture::Mipsisa32r6) | Mips64(Mips64Architecture::Mipsisa64r6) | Powerpc | Powerpc64 | S390x | Sparc | Sparc64 | Sparcv9 => Ok(Endianness::Big), #[cfg(feature="arch_zkasm")] ZkAsm => Ok(Endianness::Big), } } /// Return the pointer bit width of this target's architecture. /// /// This function is only aware of the CPU architecture so it is not aware /// of ilp32 and x32 ABIs. #[rustfmt::skip] pub fn pointer_width(self) -> Result { use Architecture::*; match self { Unknown => Err(()), Avr | Msp430 => Ok(PointerWidth::U16), Arm(arm) => Ok(arm.pointer_width()), Aarch64(aarch) => Ok(aarch.pointer_width()), Asmjs | Hexagon | X86_32(_) | Riscv32(_) | Sparc | Wasm32 | M68k | Mips32(_) | Powerpc | XTensa => Ok(PointerWidth::U32), AmdGcn | Bpfeb | Bpfel | Powerpc64le | Riscv64(_) | X86_64 | X86_64h | Mips64(_) | Nvptx64 | Powerpc64 | S390x | Sparc64 | Sparcv9 | LoongArch64 | Wasm64 | Clever(_) => Ok(PointerWidth::U64), #[cfg(feature="arch_zkasm")] ZkAsm => Ok(PointerWidth::U64), } } /// Checks if this Architecture is some variant of Clever-ISA pub fn is_clever(&self) -> bool { match self { Architecture::Clever(_) => true, _ => false, } } /// Convert into a string pub fn into_str(self) -> Cow<'static, str> { use Architecture::*; match self { Arm(arm) => arm.into_str(), Aarch64(aarch) => aarch.into_str(), Unknown => Cow::Borrowed("unknown"), AmdGcn => Cow::Borrowed("amdgcn"), Asmjs => Cow::Borrowed("asmjs"), Avr => Cow::Borrowed("avr"), Bpfeb => Cow::Borrowed("bpfeb"), Bpfel => Cow::Borrowed("bpfel"), Hexagon => Cow::Borrowed("hexagon"), X86_32(x86_32) => x86_32.into_str(), LoongArch64 => Cow::Borrowed("loongarch64"), M68k => Cow::Borrowed("m68k"), Mips32(mips32) => mips32.into_str(), Mips64(mips64) => mips64.into_str(), Msp430 => Cow::Borrowed("msp430"), Nvptx64 => Cow::Borrowed("nvptx64"), Powerpc => Cow::Borrowed("powerpc"), Powerpc64 => Cow::Borrowed("powerpc64"), Powerpc64le => Cow::Borrowed("powerpc64le"), Riscv32(riscv32) => riscv32.into_str(), Riscv64(riscv64) => riscv64.into_str(), S390x => Cow::Borrowed("s390x"), Sparc => Cow::Borrowed("sparc"), Sparc64 => Cow::Borrowed("sparc64"), Sparcv9 => Cow::Borrowed("sparcv9"), Wasm32 => Cow::Borrowed("wasm32"), Wasm64 => Cow::Borrowed("wasm64"), X86_64 => Cow::Borrowed("x86_64"), X86_64h => Cow::Borrowed("x86_64h"), XTensa => Cow::Borrowed("xtensa"), Clever(ver) => ver.into_str(), #[cfg(feature = "arch_zkasm")] ZkAsm => Cow::Borrowed("zkasm"), } } } /// Return the binary format implied by this target triple, ignoring its /// `binary_format` field. pub(crate) fn default_binary_format(triple: &Triple) -> BinaryFormat { match triple.operating_system { OperatingSystem::None_ => match triple.environment { Environment::Eabi | Environment::Eabihf => BinaryFormat::Elf, _ => BinaryFormat::Unknown, }, OperatingSystem::Aix => BinaryFormat::Xcoff, OperatingSystem::Darwin | OperatingSystem::Ios | OperatingSystem::MacOSX { .. } | OperatingSystem::Watchos | OperatingSystem::Tvos => BinaryFormat::Macho, OperatingSystem::Windows => BinaryFormat::Coff, OperatingSystem::Nebulet | OperatingSystem::Emscripten | OperatingSystem::VxWorks | OperatingSystem::Wasi | OperatingSystem::Unknown => match triple.architecture { Architecture::Wasm32 | Architecture::Wasm64 => BinaryFormat::Wasm, _ => BinaryFormat::Unknown, }, _ => BinaryFormat::Elf, } } impl fmt::Display for ArmArchitecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for Aarch64Architecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for CleverArchitecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for Riscv32Architecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for Riscv64Architecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for X86_32Architecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for Mips32Architecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for Mips64Architecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl fmt::Display for Architecture { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl FromStr for ArmArchitecture { type Err = (); fn from_str(s: &str) -> Result { use ArmArchitecture::*; Ok(match s { "arm" => Arm, "armeb" => Armeb, "armv4" => Armv4, "armv4t" => Armv4t, "armv5t" => Armv5t, "armv5te" => Armv5te, "armv5tej" => Armv5tej, "armv6" => Armv6, "armv6j" => Armv6j, "armv6k" => Armv6k, "armv6z" => Armv6z, "armv6kz" => Armv6kz, "armv6t2" => Armv6t2, "armv6m" => Armv6m, "armv7" => Armv7, "armv7a" => Armv7a, "armv7k" => Armv7k, "armv7ve" => Armv7ve, "armv7m" => Armv7m, "armv7r" => Armv7r, "armv7s" => Armv7s, "armv8" => Armv8, "armv8a" => Armv8a, "armv8.1a" => Armv8_1a, "armv8.2a" => Armv8_2a, "armv8.3a" => Armv8_3a, "armv8.4a" => Armv8_4a, "armv8.5a" => Armv8_5a, "armv8m.base" => Armv8mBase, "armv8m.main" => Armv8mMain, "armv8r" => Armv8r, "thumbeb" => Thumbeb, "thumbv4t" => Thumbv4t, "thumbv5te" => Thumbv5te, "thumbv6m" => Thumbv6m, "thumbv7a" => Thumbv7a, "thumbv7em" => Thumbv7em, "thumbv7m" => Thumbv7m, "thumbv7neon" => Thumbv7neon, "thumbv8m.base" => Thumbv8mBase, "thumbv8m.main" => Thumbv8mMain, "armebv7r" => Armebv7r, _ => return Err(()), }) } } impl FromStr for Aarch64Architecture { type Err = (); fn from_str(s: &str) -> Result { use Aarch64Architecture::*; Ok(match s { "aarch64" => Aarch64, "arm64" => Aarch64, "aarch64_be" => Aarch64be, _ => return Err(()), }) } } impl FromStr for CleverArchitecture { type Err = (); fn from_str(s: &str) -> Result { match s { "clever" => Ok(CleverArchitecture::Clever), "clever1.0" => Ok(CleverArchitecture::Clever1_0), _ => Err(()), } } } impl FromStr for Riscv32Architecture { type Err = (); fn from_str(s: &str) -> Result { use Riscv32Architecture::*; Ok(match s { "riscv32" => Riscv32, "riscv32gc" => Riscv32gc, "riscv32i" => Riscv32i, "riscv32im" => Riscv32im, "riscv32imac" => Riscv32imac, "riscv32imc" => Riscv32imc, _ => return Err(()), }) } } impl FromStr for Riscv64Architecture { type Err = (); fn from_str(s: &str) -> Result { use Riscv64Architecture::*; Ok(match s { "riscv64" => Riscv64, "riscv64gc" => Riscv64gc, "riscv64imac" => Riscv64imac, _ => return Err(()), }) } } impl FromStr for X86_32Architecture { type Err = (); fn from_str(s: &str) -> Result { use X86_32Architecture::*; Ok(match s { "i386" => I386, "i586" => I586, "i686" => I686, _ => return Err(()), }) } } impl FromStr for Mips32Architecture { type Err = (); fn from_str(s: &str) -> Result { use Mips32Architecture::*; Ok(match s { "mips" => Mips, "mipsel" => Mipsel, "mipsisa32r6" => Mipsisa32r6, "mipsisa32r6el" => Mipsisa32r6el, _ => return Err(()), }) } } impl FromStr for Mips64Architecture { type Err = (); fn from_str(s: &str) -> Result { use Mips64Architecture::*; Ok(match s { "mips64" => Mips64, "mips64el" => Mips64el, "mipsisa64r6" => Mipsisa64r6, "mipsisa64r6el" => Mipsisa64r6el, _ => return Err(()), }) } } impl FromStr for Architecture { type Err = (); fn from_str(s: &str) -> Result { use Architecture::*; Ok(match s { "unknown" => Unknown, "amdgcn" => AmdGcn, "asmjs" => Asmjs, "avr" => Avr, "bpfeb" => Bpfeb, "bpfel" => Bpfel, "hexagon" => Hexagon, "loongarch64" => LoongArch64, "m68k" => M68k, "msp430" => Msp430, "nvptx64" => Nvptx64, "powerpc" => Powerpc, "powerpc64" => Powerpc64, "powerpc64le" => Powerpc64le, "s390x" => S390x, "sparc" => Sparc, "sparc64" => Sparc64, "sparcv9" => Sparcv9, "wasm32" => Wasm32, "wasm64" => Wasm64, "x86_64" => X86_64, "x86_64h" => X86_64h, "xtensa" => XTensa, #[cfg(feature = "arch_zkasm")] "zkasm" => ZkAsm, _ => { if let Ok(arm) = ArmArchitecture::from_str(s) { Arm(arm) } else if let Ok(aarch64) = Aarch64Architecture::from_str(s) { Aarch64(aarch64) } else if let Ok(riscv32) = Riscv32Architecture::from_str(s) { Riscv32(riscv32) } else if let Ok(riscv64) = Riscv64Architecture::from_str(s) { Riscv64(riscv64) } else if let Ok(x86_32) = X86_32Architecture::from_str(s) { X86_32(x86_32) } else if let Ok(mips32) = Mips32Architecture::from_str(s) { Mips32(mips32) } else if let Ok(mips64) = Mips64Architecture::from_str(s) { Mips64(mips64) } else if let Ok(clever) = CleverArchitecture::from_str(s) { Clever(clever) } else { return Err(()); } } }) } } impl fmt::Display for Vendor { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(self.as_str()) } } impl FromStr for Vendor { type Err = (); fn from_str(s: &str) -> Result { use Vendor::*; Ok(match s { "unknown" => Unknown, "amd" => Amd, "apple" => Apple, "espressif" => Espressif, "experimental" => Experimental, "fortanix" => Fortanix, "ibm" => Ibm, "kmc" => Kmc, "nintendo" => Nintendo, "nvidia" => Nvidia, "pc" => Pc, "rumprun" => Rumprun, "sun" => Sun, "uwp" => Uwp, "wrs" => Wrs, custom => { #[cfg(not(feature = "std"))] use alloc::borrow::ToOwned; // A custom vendor. Since triple syntax is so loosely defined, // be as conservative as we can to avoid potential ambiguities. // We err on the side of being too strict here, as we can // always relax it if needed. // Don't allow empty string names. if custom.is_empty() { return Err(()); } // Don't allow any other recognized name as a custom vendor, // since vendors can be omitted in some contexts. if Architecture::from_str(custom).is_ok() || OperatingSystem::from_str(custom).is_ok() || Environment::from_str(custom).is_ok() || BinaryFormat::from_str(custom).is_ok() { return Err(()); } // Require the first character to be an ascii lowercase. if !custom.chars().next().unwrap().is_ascii_lowercase() { return Err(()); } // Restrict the set of characters permitted in a custom vendor. let has_restricted = custom.chars().any(|c: char| { !(c.is_ascii_lowercase() || c.is_ascii_digit() || c == '_' || c == '.') }); if has_restricted { return Err(()); } Custom(CustomVendor::Owned(Box::new(custom.to_owned()))) } }) } } impl fmt::Display for OperatingSystem { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use OperatingSystem::*; match *self { MacOSX { major, minor, patch, } => write!(f, "macosx{}.{}.{}", major, minor, patch), os => f.write_str(&os.into_str()), } } } impl FromStr for OperatingSystem { type Err = (); fn from_str(s: &str) -> Result { use OperatingSystem::*; // TODO also parse version number for darwin and ios OSes if s.starts_with("macosx") { // Parse operating system names like `macosx10.7.0`. let s = &s["macosx".len()..]; let mut parts = s.split('.').map(|num| num.parse::()); macro_rules! get_part { () => { if let Some(Ok(part)) = parts.next() { part } else { return Err(()); } }; } let major = get_part!(); let minor = get_part!(); let patch = get_part!(); if parts.next().is_some() { return Err(()); } return Ok(MacOSX { major, minor, patch, }); } Ok(match s { "unknown" => Unknown, "aix" => Aix, "amdhsa" => AmdHsa, "bitrig" => Bitrig, "cloudabi" => Cloudabi, "cuda" => Cuda, "darwin" => Darwin, "dragonfly" => Dragonfly, "emscripten" => Emscripten, "freebsd" => Freebsd, "fuchsia" => Fuchsia, "haiku" => Haiku, "hermit" => Hermit, "horizon" => Horizon, "illumos" => Illumos, "ios" => Ios, "l4re" => L4re, "linux" => Linux, "nebulet" => Nebulet, "netbsd" => Netbsd, "none" => None_, "openbsd" => Openbsd, "psp" => Psp, "redox" => Redox, "solaris" => Solaris, "solid_asp3" => SolidAsp3, "tvos" => Tvos, "uefi" => Uefi, "vxworks" => VxWorks, "wasi" => Wasi, "wasip1" => WasiP1, "wasip2" => WasiP2, "watchos" => Watchos, "windows" => Windows, "espidf" => Espidf, _ => return Err(()), }) } } impl fmt::Display for Environment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl FromStr for Environment { type Err = (); fn from_str(s: &str) -> Result { use Environment::*; Ok(match s { "unknown" => Unknown, "amdgiz" => AmdGiz, "android" => Android, "androideabi" => Androideabi, "eabi" => Eabi, "eabihf" => Eabihf, "gnu" => Gnu, "gnuabi64" => Gnuabi64, "gnueabi" => Gnueabi, "gnueabihf" => Gnueabihf, "gnuspe" => Gnuspe, "gnux32" => Gnux32, "gnu_ilp32" => GnuIlp32, "gnullvm" => GnuLlvm, "hermitkernel" => HermitKernel, "linuxkernel" => LinuxKernel, "macabi" => Macabi, "musl" => Musl, "musleabi" => Musleabi, "musleabihf" => Musleabihf, "muslabi64" => Muslabi64, "msvc" => Msvc, "newlib" => Newlib, "kernel" => Kernel, "uclibc" => Uclibc, "uclibceabi" => Uclibceabi, "uclibceabihf" => Uclibceabihf, "sgx" => Sgx, "sim" => Sim, "softfloat" => Softfloat, "spe" => Spe, "threads" => Threads, _ => return Err(()), }) } } impl fmt::Display for BinaryFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.into_str()) } } impl FromStr for BinaryFormat { type Err = (); fn from_str(s: &str) -> Result { use BinaryFormat::*; Ok(match s { "unknown" => Unknown, "elf" => Elf, "coff" => Coff, "macho" => Macho, "wasm" => Wasm, "xcoff" => Xcoff, _ => return Err(()), }) } } #[cfg(test)] mod tests { use super::*; use alloc::string::ToString; #[test] fn roundtrip_known_triples() { // This list is constructed from: // - targets emitted by "rustup target list" // - targets emitted by "rustc +nightly --print target-list" // - targets contributors have added let targets = [ "aarch64-apple-darwin", "aarch64-apple-ios", "aarch64-apple-ios-macabi", "aarch64-apple-ios-sim", "aarch64-apple-tvos", "aarch64-apple-watchos-sim", "aarch64_be-unknown-linux-gnu", "aarch64_be-unknown-linux-gnu_ilp32", "aarch64_be-unknown-netbsd", "aarch64-fuchsia", "aarch64-kmc-solid_asp3", "aarch64-linux-android", //"aarch64-nintendo-switch-freestanding", // TODO "aarch64-pc-windows-gnullvm", "aarch64-pc-windows-msvc", "aarch64-unknown-cloudabi", "aarch64-unknown-freebsd", "aarch64-unknown-hermit", "aarch64-unknown-linux-gnu", "aarch64-unknown-linux-gnu_ilp32", "aarch64-unknown-linux-musl", "aarch64-unknown-netbsd", "aarch64-unknown-none", "aarch64-unknown-none-softfloat", "aarch64-unknown-openbsd", "aarch64-unknown-redox", "aarch64-unknown-uefi", "aarch64-uwp-windows-msvc", "aarch64-wrs-vxworks", //"arm64_32-apple-watchos", // TODO "armeb-unknown-linux-gnueabi", "amdgcn-amd-amdhsa", "amdgcn-amd-amdhsa-amdgiz", "armebv7r-none-eabi", "armebv7r-none-eabihf", "arm-linux-androideabi", "arm-unknown-linux-gnueabi", "arm-unknown-linux-gnueabihf", "arm-unknown-linux-musleabi", "arm-unknown-linux-musleabihf", "armv4t-none-eabi", "armv4t-unknown-linux-gnueabi", "armv5te-none-eabi", "armv5te-unknown-linux-gnueabi", "armv5te-unknown-linux-musleabi", "armv5te-unknown-linux-uclibceabi", "armv6k-nintendo-3ds", "armv6-unknown-freebsd", "armv6-unknown-netbsd-eabihf", "armv7a-kmc-solid_asp3-eabi", "armv7a-kmc-solid_asp3-eabihf", "armv7a-none-eabi", "armv7a-none-eabihf", "armv7-apple-ios", "armv7k-apple-watchos", "armv7-linux-androideabi", "armv7r-none-eabi", "armv7r-none-eabihf", "armv7s-apple-ios", "armv7-unknown-cloudabi-eabihf", "armv7-unknown-freebsd", "armv7-unknown-linux-gnueabi", "armv7-unknown-linux-gnueabihf", "armv7-unknown-linux-musleabi", "armv7-unknown-linux-musleabihf", "armv7-unknown-linux-uclibceabi", "armv7-unknown-linux-uclibceabihf", "armv7-unknown-netbsd-eabihf", "armv7-wrs-vxworks-eabihf", "asmjs-unknown-emscripten", //"avr-unknown-gnu-atmega328", // TODO "avr-unknown-unknown", "bpfeb-unknown-none", "bpfel-unknown-none", "hexagon-unknown-linux-musl", "i386-apple-ios", "i586-pc-windows-msvc", "i586-unknown-linux-gnu", "i586-unknown-linux-musl", "i686-apple-darwin", "i686-linux-android", "i686-apple-macosx10.7.0", "i686-pc-windows-gnu", "i686-pc-windows-msvc", "i686-unknown-cloudabi", "i686-unknown-dragonfly", "i686-unknown-freebsd", "i686-unknown-haiku", "i686-unknown-linux-gnu", "i686-unknown-linux-musl", "i686-unknown-netbsd", "i686-unknown-openbsd", "i686-unknown-uefi", "i686-uwp-windows-gnu", "i686-uwp-windows-msvc", "i686-wrs-vxworks", "loongarch64-unknown-linux-gnu", "m68k-unknown-linux-gnu", "mips64el-unknown-linux-gnuabi64", "mips64el-unknown-linux-muslabi64", "mips64-openwrt-linux-musl", "mips64-unknown-linux-gnuabi64", "mips64-unknown-linux-muslabi64", "mipsel-sony-psp", "mipsel-unknown-linux-gnu", "mipsel-unknown-linux-musl", "mipsel-unknown-linux-uclibc", "mipsel-unknown-none", "mipsisa32r6el-unknown-linux-gnu", "mipsisa32r6-unknown-linux-gnu", "mipsisa64r6el-unknown-linux-gnuabi64", "mipsisa64r6-unknown-linux-gnuabi64", "mips-unknown-linux-gnu", "mips-unknown-linux-musl", "mips-unknown-linux-uclibc", "msp430-none-elf", "nvptx64-nvidia-cuda", "powerpc64le-unknown-freebsd", "powerpc64le-unknown-linux-gnu", "powerpc64le-unknown-linux-musl", "powerpc64-ibm-aix", "powerpc64-unknown-freebsd", "powerpc64-unknown-linux-gnu", "powerpc64-unknown-linux-musl", "powerpc64-unknown-openbsd", "powerpc64-wrs-vxworks", "powerpc-ibm-aix", "powerpc-unknown-freebsd", "powerpc-unknown-linux-gnu", "powerpc-unknown-linux-gnuspe", "powerpc-unknown-linux-musl", "powerpc-unknown-netbsd", "powerpc-unknown-openbsd", "powerpc-wrs-vxworks", "powerpc-wrs-vxworks-spe", "riscv32gc-unknown-linux-gnu", "riscv32gc-unknown-linux-musl", "riscv32imac-unknown-none-elf", //"riscv32imac-unknown-xous-elf", // TODO "riscv32imc-esp-espidf", "riscv32imc-unknown-none-elf", "riscv32im-unknown-none-elf", "riscv32i-unknown-none-elf", "riscv64gc-unknown-freebsd", "riscv64gc-unknown-linux-gnu", "riscv64gc-unknown-linux-musl", "riscv64gc-unknown-netbsd", "riscv64gc-unknown-none-elf", "riscv64gc-unknown-openbsd", "riscv64imac-unknown-none-elf", "s390x-unknown-linux-gnu", "s390x-unknown-linux-musl", "sparc64-unknown-linux-gnu", "sparc64-unknown-netbsd", "sparc64-unknown-openbsd", "sparc-unknown-linux-gnu", "sparcv9-sun-solaris", "thumbv4t-none-eabi", "thumbv5te-none-eabi", "thumbv6m-none-eabi", "thumbv7a-pc-windows-msvc", "thumbv7a-uwp-windows-msvc", "thumbv7em-none-eabi", "thumbv7em-none-eabihf", "thumbv7m-none-eabi", "thumbv7neon-linux-androideabi", "thumbv7neon-unknown-linux-gnueabihf", "thumbv7neon-unknown-linux-musleabihf", "thumbv8m.base-none-eabi", "thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "wasm32-experimental-emscripten", "wasm32-unknown-emscripten", "wasm32-unknown-unknown", "wasm32-wasi", "wasm32-wasip1-threads", "wasm32-wasip1", "wasm32-wasip2", "wasm64-unknown-unknown", "wasm64-wasi", "x86_64-apple-darwin", "x86_64h-apple-darwin", "x86_64-apple-ios", "x86_64-apple-ios-macabi", "x86_64-apple-tvos", "x86_64-apple-watchos-sim", "x86_64-fortanix-unknown-sgx", "x86_64-fuchsia", "x86_64-linux-android", "x86_64-linux-kernel", // Changed to x86_64-unknown-none-linuxkernel in 1.53.0 "x86_64-apple-macosx10.7.0", "x86_64-pc-solaris", "x86_64-pc-windows-gnu", "x86_64-pc-windows-gnullvm", "x86_64-pc-windows-msvc", "x86_64-rumprun-netbsd", // Removed in 1.53.0 "x86_64-sun-solaris", "x86_64-unknown-bitrig", "x86_64-unknown-cloudabi", "x86_64-unknown-dragonfly", "x86_64-unknown-freebsd", "x86_64-unknown-haiku", "x86_64-unknown-hermit", "x86_64-unknown-hermit-kernel", // Changed to x86_64-unknown-none-hermitkernel in 1.53.0 "x86_64-unknown-illumos", "x86_64-unknown-l4re-uclibc", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-gnux32", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", "x86_64-unknown-none", "x86_64-unknown-none-hermitkernel", "x86_64-unknown-none-linuxkernel", "x86_64-unknown-openbsd", "x86_64-unknown-redox", "x86_64-unknown-uefi", "x86_64-uwp-windows-gnu", "x86_64-uwp-windows-msvc", "x86_64-wrs-vxworks", "xtensa-esp32-espidf", "clever-unknown-elf", #[cfg(feature = "arch_zkasm")] "zkasm-unknown-unknown", ]; for target in targets.iter() { let t = Triple::from_str(target).expect("can't parse target"); assert_ne!(t.architecture, Architecture::Unknown); assert_eq!(t.to_string(), *target, "{:#?}", t); } } #[test] fn thumbv7em_none_eabihf() { let t = Triple::from_str("thumbv7em-none-eabihf").expect("can't parse target"); assert_eq!( t.architecture, Architecture::Arm(ArmArchitecture::Thumbv7em) ); assert_eq!(t.vendor, Vendor::Unknown); assert_eq!(t.operating_system, OperatingSystem::None_); assert_eq!(t.environment, Environment::Eabihf); assert_eq!(t.binary_format, BinaryFormat::Elf); } #[test] fn custom_vendors() { // Test various invalid cases. assert!(Triple::from_str("x86_64--linux").is_err()); assert!(Triple::from_str("x86_64-42-linux").is_err()); assert!(Triple::from_str("x86_64-__customvendor__-linux").is_err()); assert!(Triple::from_str("x86_64-^-linux").is_err()); assert!(Triple::from_str("x86_64- -linux").is_err()); assert!(Triple::from_str("x86_64-CustomVendor-linux").is_err()); assert!(Triple::from_str("x86_64-linux-linux").is_err()); assert!(Triple::from_str("x86_64-x86_64-linux").is_err()); assert!(Triple::from_str("x86_64-elf-linux").is_err()); assert!(Triple::from_str("x86_64-gnu-linux").is_err()); assert!(Triple::from_str("x86_64-linux-customvendor").is_err()); assert!(Triple::from_str("customvendor").is_err()); assert!(Triple::from_str("customvendor-x86_64").is_err()); assert!(Triple::from_str("x86_64-").is_err()); assert!(Triple::from_str("x86_64--").is_err()); // Test various Unicode things. assert!( Triple::from_str("x86_64-𝓬𝓾𝓼𝓽𝓸𝓶𝓿𝓮𝓷𝓭𝓸𝓻-linux").is_err(), "unicode font hazard" ); assert!( Triple::from_str("x86_64-ćúśtőḿvéńdőŕ-linux").is_err(), "diacritical mark stripping hazard" ); assert!( Triple::from_str("x86_64-customvendοr-linux").is_err(), "homoglyph hazard" ); assert!(Triple::from_str("x86_64-customvendor-linux").is_ok()); assert!( Triple::from_str("x86_64-ffi-linux").is_err(), "normalization hazard" ); assert!(Triple::from_str("x86_64-ffi-linux").is_ok()); assert!( Triple::from_str("x86_64-custom‍vendor-linux").is_err(), "zero-width character hazard" ); assert!( Triple::from_str("x86_64-customvendor-linux").is_err(), "BOM hazard" ); // Test some valid cases. let t = Triple::from_str("x86_64-customvendor-linux") .expect("can't parse target with custom vendor"); assert_eq!(t.architecture, Architecture::X86_64); assert_eq!( t.vendor, Vendor::Custom(CustomVendor::Static("customvendor")) ); assert_eq!(t.operating_system, OperatingSystem::Linux); assert_eq!(t.environment, Environment::Unknown); assert_eq!(t.binary_format, BinaryFormat::Elf); assert_eq!(t.to_string(), "x86_64-customvendor-linux"); let t = Triple::from_str("x86_64-customvendor").expect("can't parse target with custom vendor"); assert_eq!(t.architecture, Architecture::X86_64); assert_eq!( t.vendor, Vendor::Custom(CustomVendor::Static("customvendor")) ); assert_eq!(t.operating_system, OperatingSystem::Unknown); assert_eq!(t.environment, Environment::Unknown); assert_eq!(t.binary_format, BinaryFormat::Unknown); assert_eq!( Triple::from_str("unknown-foo"), Ok(Triple { architecture: Architecture::Unknown, vendor: Vendor::Custom(CustomVendor::Static("foo")), operating_system: OperatingSystem::Unknown, environment: Environment::Unknown, binary_format: BinaryFormat::Unknown, }) ); } } target-lexicon/src/host.rs0000644000175000017500000000302514661133735016600 0ustar jamespagejamespageuse crate::{Architecture, BinaryFormat, Environment, OperatingSystem, Triple, Vendor}; // Include the implementations of the `HOST` object containing information // about the current host. include!(concat!(env!("OUT_DIR"), "/host.rs")); #[cfg(test)] mod tests { #[cfg(target_os = "aix")] #[test] fn test_aix() { use super::*; assert_eq!(OperatingSystem::host(), OperatingSystem::Aix); } #[cfg(target_os = "linux")] #[test] fn test_linux() { use super::*; assert_eq!(OperatingSystem::host(), OperatingSystem::Linux); } #[cfg(target_os = "macos")] #[test] fn test_macos() { use super::*; assert_eq!(OperatingSystem::host(), OperatingSystem::Darwin); } #[cfg(windows)] #[test] fn test_windows() { use super::*; assert_eq!(OperatingSystem::host(), OperatingSystem::Windows); } #[cfg(target_pointer_width = "16")] #[test] fn test_ptr16() { use super::*; assert_eq!(Architecture::host().pointer_width().unwrap().bits(), 16); } #[cfg(target_pointer_width = "32")] #[test] fn test_ptr32() { use super::*; assert_eq!(Architecture::host().pointer_width().unwrap().bits(), 32); } #[cfg(target_pointer_width = "64")] #[test] fn test_ptr64() { use super::*; assert_eq!(Architecture::host().pointer_width().unwrap().bits(), 64); } #[test] fn host_object() { use super::*; assert_eq!(HOST, Triple::host()); } } target-lexicon/LICENSE0000644000175000017500000002772314661133735015506 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. target-lexicon/scripts/0000775000175000017500000000000014661133735016157 5ustar jamespagejamespagetarget-lexicon/scripts/rust-targets.sh0000755000175000017500000000032414661133735021157 0ustar jamespagejamespage#!/bin/bash set -euo pipefail rustup target list | sed 's/ (.*//' > list.txt rustc +nightly --print target-list >> list.txt cat list.txt | sort | uniq |sed 's/\(.*\)/ "\1",/' > sorted.txt rm list.txt target-lexicon/.cargo-checksum.json0000664000175000017500000000234214661133735020335 0ustar jamespagejamespage{"files":{"Cargo.lock":"90ce0a611de852399bad6e59c0abcd288fb80f844d8e0c4b3267896fc374633e","Cargo.toml":"530f66eb28bf50df30cb009b773e75ef3f36fea3bc42863497322efcf29410c7","LICENSE":"268872b9816f90fd8e85db5a28d33f8150ebb8dd016653fb39ef1f94f2686bc5","README.md":"c3467056d91be3f59562158ee9604c729b5b5f473efbefb036032803eb76809e","build.rs":"678ba872ef2254e8901d6a00536f64d74d375d919f845113bd3ded709b6edb4a","examples/host.rs":"503bafddfb372123fe4dc0e7b8037808beb5bfe6df60c00d3315922bd3792c6c","examples/misc.rs":"49a579845450b7b020ed5c97dca142fc548725893cbc82f6f750ee0caab2beca","scripts/rust-targets.sh":"89564342916321c5bc35e772d374a7f0af22cc9ae6dcc0027eca48d2269f18cb","src/data_model.rs":"38c0c184ee65b882872298127d9c6878292bd12c139792e82328a5facc2428ae","src/host.rs":"d742406eba58f35c4c9f1041e506bb63d6c0eb752c2e88f4a6646538ef1aba38","src/lib.rs":"d18401920ad8b1bd1bce505c2c9f8bf8724f123919234d6007f80634b3d306d5","src/parse_error.rs":"b3735eabc0fd0a9dfdd6375662f20ec96a79852a00a05a98fb2e421545285e53","src/targets.rs":"5bed8238842e5728e3de8430d936049bef123e493dd8de49e97b9d38a89ad27f","src/triple.rs":"0d5ab67e8ee60b241b8380435718af547b0b2c4f5b8113e80d2586c9dc1adec0"},"package":"e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"}target-lexicon/Cargo.lock0000644000175000017500000000424014661133735016373 0ustar jamespagejamespage# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "proc-macro2" version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "serde" version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "syn" version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "target-lexicon" version = "0.12.14" dependencies = [ "serde", "serde_json", ] [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" triomphe/0000775000175000017500000000000014661133735013372 5ustar jamespagejamespagetriomphe/README.md0000644000175000017500000000227114661133735014651 0ustar jamespagejamespage# Triomphe Fork of Arc. This has the following advantages over std::sync::Arc: * `triomphe::Arc` doesn't support weak references: we save space by excluding the weak reference count, and we don't do extra read-modify-update operations to handle the possibility of weak references. * `triomphe::UniqueArc` allows one to construct a temporarily-mutable `Arc` which can be converted to a regular `triomphe::Arc` later * `triomphe::OffsetArc` can be used transparently from C++ code and is compatible with (and can be converted to/from) `triomphe::Arc` * `triomphe::ArcBorrow` is functionally similar to `&triomphe::Arc`, however in memory it's simply `&T`. This makes it more flexible for FFI; the source of the borrow need not be an `Arc` pinned on the stack (and can instead be a pointer from C++, or an `OffsetArc`). Additionally, this helps avoid pointer-chasing. * `triomphe::Arc` has can be constructed for dynamically-sized types via `from_header_and_iter` * `triomphe::ThinArc` provides thin-pointer `Arc`s to dynamically sized types * `triomphe::ArcUnion` is union of two `triomphe:Arc`s which fits inside one word of memory This crate is a version of `servo_arc` meant for general community use. triomphe/LICENSE-APACHE0000644000175000017500000002514114661133735015317 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. triomphe/Cargo.toml0000644000175000017500000000260514661133735015323 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] rust-version = "1.76" name = "triomphe" version = "0.1.13" authors = [ "Manish Goregaokar ", "The Servo Project Developers", ] description = "A fork of std::sync::Arc with some extra functionality and without weak references (originally servo_arc)" readme = "README.md" keywords = [ "arc", "ffi", "sync", "data-structure", ] categories = [ "concurrency", "data-structures", ] license = "MIT OR Apache-2.0" repository = "https://github.com/Manishearth/triomphe" [package.metadata.docs.rs] all-features = true [dependencies.arc-swap] version = "1.3.0" optional = true [dependencies.serde] version = "1.0" optional = true default-features = false [dependencies.stable_deref_trait] version = "1.1.1" optional = true default-features = false [dependencies.unsize] version = "1.1" optional = true [features] default = [ "serde", "stable_deref_trait", "std", ] std = [] triomphe/LICENSE-MIT0000644000175000017500000000206214661133735015024 0ustar jamespagejamespageMIT License Copyright (c) 2019 Manish Goregaokar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. triomphe/src/0000775000175000017500000000000014661133735014161 5ustar jamespagejamespagetriomphe/src/arc_borrow.rs0000644000175000017500000001226314661133735016670 0ustar jamespagejamespageuse core::marker::PhantomData; use core::mem; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ptr::NonNull; use super::Arc; /// A "borrowed `Arc`". This is a pointer to /// a T that is known to have been allocated within an /// `Arc`. /// /// This is equivalent in guarantees to `&Arc`, however it is /// a bit more flexible. To obtain an `&Arc` you must have /// an `Arc` instance somewhere pinned down until we're done with it. /// It's also a direct pointer to `T`, so using this involves less pointer-chasing /// /// However, C++ code may hand us refcounted things as pointers to T directly, /// so we have to conjure up a temporary `Arc` on the stack each time. The /// same happens for when the object is managed by a `OffsetArc`. /// /// `ArcBorrow` lets us deal with borrows of known-refcounted objects /// without needing to worry about where the `Arc` is. #[derive(Debug, Eq, PartialEq)] #[repr(transparent)] pub struct ArcBorrow<'a, T: ?Sized + 'a>(pub(crate) NonNull, pub(crate) PhantomData<&'a T>); unsafe impl<'a, T: ?Sized + Sync + Send> Send for ArcBorrow<'a, T> {} unsafe impl<'a, T: ?Sized + Sync + Send> Sync for ArcBorrow<'a, T> {} impl<'a, T> Copy for ArcBorrow<'a, T> {} impl<'a, T> Clone for ArcBorrow<'a, T> { #[inline] fn clone(&self) -> Self { *self } } impl<'a, T> ArcBorrow<'a, T> { /// Clone this as an `Arc`. This bumps the refcount. #[inline] pub fn clone_arc(&self) -> Arc { let arc = unsafe { Arc::from_raw(self.0.as_ptr()) }; // addref it! mem::forget(arc.clone()); arc } /// For constructing from a pointer known to be Arc-backed, /// e.g. if we obtain such a pointer over FFI /// // TODO: should from_ptr be relaxed to unsized types? It can't be // converted back to an Arc right now for unsized types. // /// # Safety /// - The pointer to `T` must have come from a Triomphe `Arc`, `UniqueArc`, or `ArcBorrow`. /// - The pointer to `T` must have full provenance over the `Arc`, `UniqueArc`, or `ArcBorrow`, /// in particular it must not have been derived from a `&T` reference, as references immediately /// loose all provenance over the adjacent reference counts. As of this writing, /// of the 3 types, only Trimphe's `Arc` offers a direct API for obtaining such a pointer: /// [`Arc::as_ptr`]. #[inline] pub unsafe fn from_ptr(ptr: *const T) -> Self { unsafe { ArcBorrow(NonNull::new_unchecked(ptr as *mut T), PhantomData) } } /// Compare two `ArcBorrow`s via pointer equality. Will only return /// true if they come from the same allocation #[inline] pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.0 == other.0 } /// The reference count of the underlying `Arc`. /// /// The number does not include borrowed pointers, /// or temporary `Arc` pointers created with functions like /// [`ArcBorrow::with_arc`]. /// /// The function is called `strong_count` to mirror `std::sync::Arc::strong_count`, /// however `triomphe::Arc` does not support weak references. #[inline] pub fn strong_count(this: &Self) -> usize { Self::with_arc(this, |arc| Arc::strong_count(arc)) } /// Temporarily converts |self| into a bonafide Arc and exposes it to the /// provided callback. The refcount is not modified. #[inline] pub fn with_arc(&self, f: F) -> U where F: FnOnce(&Arc) -> U, { // Synthesize transient Arc, which never touches the refcount. let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.0.as_ptr())) }; // Expose the transient Arc to the callback, which may clone it if it wants // and forward the result to the user f(&transient) } /// Similar to deref, but uses the lifetime |a| rather than the lifetime of /// self, which is incompatible with the signature of the Deref trait. #[inline] pub fn get(&self) -> &'a T { unsafe { &*self.0.as_ptr() } } } impl<'a, T> Deref for ArcBorrow<'a, T> { type Target = T; #[inline] fn deref(&self) -> &T { self.get() } } // Safety: // This implementation must guarantee that it is sound to call replace_ptr with an unsized variant // of the pointer retuned in `as_sized_ptr`. We leverage unsizing the contained reference. This // continues to point to the data of an ArcInner. The reference count remains untouched which is // correct since the number of owners did not change. This implies the returned instance fulfills // its safety invariants. #[cfg(feature = "unsize")] unsafe impl<'lt, T: 'lt, U: ?Sized + 'lt> unsize::CoerciblePtr for ArcBorrow<'lt, T> { type Pointee = T; type Output = ArcBorrow<'lt, U>; fn as_sized_ptr(&mut self) -> *mut T { self.0.as_ptr() } unsafe fn replace_ptr(self, new: *mut U) -> ArcBorrow<'lt, U> { let inner = ManuallyDrop::new(self); // Safety: backed by the same Arc that backed `self`. ArcBorrow(inner.0.replace_ptr(new), PhantomData) } } #[test] fn clone_arc_borrow() { let x = Arc::new(42); let b: ArcBorrow<'_, i32> = x.borrow_arc(); let y = b.clone_arc(); assert_eq!(x, y); } triomphe/src/header.rs0000644000175000017500000003140714661133735015762 0ustar jamespagejamespageuse alloc::alloc::Layout; use alloc::boxed::Box; use alloc::string::String; use alloc::vec::Vec; use core::cmp::Ordering; use core::iter::{ExactSizeIterator, Iterator}; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop}; use core::ptr::{self, addr_of_mut}; use core::usize; use super::{Arc, ArcInner}; /// Structure to allow Arc-managing some fixed-sized data and a variably-sized /// slice in a single allocation. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] #[repr(C)] pub struct HeaderSlice { /// The fixed-sized data. pub header: H, /// The dynamically-sized data. pub slice: T, } impl Arc> { /// Creates an Arc for a HeaderSlice using the given header struct and /// iterator to generate the slice. The resulting Arc will be fat. pub fn from_header_and_iter(header: H, mut items: I) -> Self where I: Iterator + ExactSizeIterator, { assert_ne!(mem::size_of::(), 0, "Need to think about ZST"); let num_items = items.len(); let inner = Arc::allocate_for_header_and_slice(num_items); unsafe { // Write the data. // // Note that any panics here (i.e. from the iterator) are safe, since // we'll just leak the uninitialized memory. ptr::write(&mut ((*inner.as_ptr()).data.header), header); let mut current = (*inner.as_ptr()).data.slice.as_mut_ptr(); for _ in 0..num_items { ptr::write( current, items .next() .expect("ExactSizeIterator over-reported length"), ); current = current.offset(1); } assert!( items.next().is_none(), "ExactSizeIterator under-reported length" ); } // Safety: ptr is valid & the inner structure is fully initialized Arc { p: inner, phantom: PhantomData, } } /// Creates an Arc for a HeaderSlice using the given header struct and /// iterator to generate the slice. The resulting Arc will be fat. pub fn from_header_and_slice(header: H, items: &[T]) -> Self where T: Copy, { assert_ne!(mem::size_of::(), 0, "Need to think about ZST"); let num_items = items.len(); let inner = Arc::allocate_for_header_and_slice(num_items); unsafe { // Write the data. ptr::write(&mut ((*inner.as_ptr()).data.header), header); let dst = (*inner.as_ptr()).data.slice.as_mut_ptr(); ptr::copy_nonoverlapping(items.as_ptr(), dst, num_items); } // Safety: ptr is valid & the inner structure is fully initialized Arc { p: inner, phantom: PhantomData, } } /// Creates an Arc for a HeaderSlice using the given header struct and /// vec to generate the slice. The resulting Arc will be fat. pub fn from_header_and_vec(header: H, mut v: Vec) -> Self { let len = v.len(); let inner = Arc::allocate_for_header_and_slice(len); unsafe { // Safety: inner is a valid pointer, so this can't go out of bounds let dst = addr_of_mut!((*inner.as_ptr()).data.header); // Safety: `dst` is valid for writes (just allocated) ptr::write(dst, header); } unsafe { let src = v.as_mut_ptr(); // Safety: inner is a valid pointer, so this can't go out of bounds let dst = addr_of_mut!((*inner.as_ptr()).data.slice) as *mut T; // Safety: // - `src` is valid for reads for `len` (got from `Vec`) // - `dst` is valid for writes for `len` (just allocated, with layout for appropriate slice) // - `src` and `dst` don't overlap (separate allocations) ptr::copy_nonoverlapping(src, dst, len); // Deallocate vec without dropping `T` // // Safety: 0..0 elements are always initialized, 0 <= cap for any cap v.set_len(0); } // Safety: ptr is valid & the inner structure is fully initialized Arc { p: inner, phantom: PhantomData, } } } impl Arc> { /// Creates an Arc for a HeaderSlice using the given header struct and /// a str slice to generate the slice. The resulting Arc will be fat. pub fn from_header_and_str(header: H, string: &str) -> Self { let bytes = Arc::from_header_and_slice(header, string.as_bytes()); // Safety: `ArcInner` and `HeaderSlice` are `repr(C)`, `str` has the same layout as `[u8]`, // thus it's ok to "transmute" between `Arc>` and `Arc>`. // // `bytes` are a valid string since we've just got them from a valid `str`. unsafe { Arc::from_raw_inner(Arc::into_raw_inner(bytes) as _) } } } /// Header data with an inline length. Consumers that use HeaderWithLength as the /// Header type in HeaderSlice can take advantage of ThinArc. #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] #[repr(C)] pub struct HeaderWithLength { /// The fixed-sized data. pub header: H, /// The slice length. pub length: usize, } impl HeaderWithLength { /// Creates a new HeaderWithLength. #[inline] pub fn new(header: H, length: usize) -> Self { HeaderWithLength { header, length } } } impl From>> for Arc { fn from(this: Arc>) -> Self { debug_assert_eq!( Layout::for_value::>(&this), Layout::for_value::(&this.slice) ); // Safety: `HeaderSlice<(), T>` and `T` has the same layout unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) } } } impl From> for Arc> { fn from(this: Arc) -> Self { // Safety: `T` and `HeaderSlice<(), T>` has the same layout unsafe { Arc::from_raw_inner(Arc::into_raw_inner(this) as _) } } } impl From<&[T]> for Arc<[T]> { fn from(slice: &[T]) -> Self { Arc::from_header_and_slice((), slice).into() } } impl From<&str> for Arc { fn from(s: &str) -> Self { Arc::from_header_and_str((), s).into() } } impl From for Arc { fn from(s: String) -> Self { Self::from(&s[..]) } } // FIXME: once `pointer::with_metadata_of` is stable or // implementable on stable without assuming ptr layout // this will be able to accept `T: ?Sized`. impl From> for Arc { fn from(b: Box) -> Self { let layout = Layout::for_value::(&b); // Safety: the closure only changes the type of the pointer let inner = unsafe { Self::allocate_for_layout(layout, |mem| mem as *mut ArcInner) }; unsafe { let src = Box::into_raw(b); // Safety: inner is a valid pointer, so this can't go out of bounds let dst = addr_of_mut!((*inner.as_ptr()).data); // Safety: // - `src` is valid for reads (got from `Box`) // - `dst` is valid for writes (just allocated) // - `src` and `dst` don't overlap (separate allocations) ptr::copy_nonoverlapping(src, dst, 1); // Deallocate box without dropping `T` // // Safety: // - `src` has been got from `Box::into_raw` // - `ManuallyDrop` is guaranteed to have the same layout as `T` drop(Box::>::from_raw(src as _)); } Arc { p: inner, phantom: PhantomData, } } } impl From> for Arc<[T]> { fn from(v: Vec) -> Self { Arc::from_header_and_vec((), v).into() } } pub(crate) type HeaderSliceWithLength = HeaderSlice, T>; impl PartialOrd for HeaderSliceWithLength { fn partial_cmp(&self, other: &Self) -> Option { (&self.header.header, &self.slice).partial_cmp(&(&other.header.header, &other.slice)) } } impl Ord for HeaderSliceWithLength { fn cmp(&self, other: &Self) -> Ordering { (&self.header.header, &self.slice).cmp(&(&other.header.header, &other.slice)) } } #[cfg(test)] mod tests { use alloc::boxed::Box; use alloc::string::String; use alloc::vec; use core::iter; use crate::{Arc, HeaderSlice}; #[test] fn from_header_and_iter_smoke() { let arc = Arc::from_header_and_iter( (42u32, 17u8), IntoIterator::into_iter([1u16, 2, 3, 4, 5, 6, 7]), ); assert_eq!(arc.header, (42, 17)); assert_eq!(arc.slice, [1, 2, 3, 4, 5, 6, 7]); } #[test] fn from_header_and_slice_smoke() { let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16, 2, 3, 4, 5, 6, 7]); assert_eq!(arc.header, (42, 17)); assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]); } #[test] fn from_header_and_vec_smoke() { let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16, 2, 3, 4, 5, 6, 7]); assert_eq!(arc.header, (42, 17)); assert_eq!(arc.slice, [1u16, 2, 3, 4, 5, 6, 7]); } #[test] fn from_header_and_iter_empty() { let arc = Arc::from_header_and_iter((42u32, 17u8), iter::empty::()); assert_eq!(arc.header, (42, 17)); assert_eq!(arc.slice, []); } #[test] fn from_header_and_slice_empty() { let arc = Arc::from_header_and_slice((42u32, 17u8), &[1u16; 0]); assert_eq!(arc.header, (42, 17)); assert_eq!(arc.slice, []); } #[test] fn from_header_and_vec_empty() { let arc = Arc::from_header_and_vec((42u32, 17u8), vec![1u16; 0]); assert_eq!(arc.header, (42, 17)); assert_eq!(arc.slice, []); } #[test] fn issue_13_empty() { crate::Arc::from_header_and_iter((), iter::empty::()); } #[test] fn issue_13_consumption() { let s: &[u8] = &[0u8; 255]; crate::Arc::from_header_and_iter((), s.iter().copied()); } #[test] fn from_header_and_str_smoke() { let a = Arc::from_header_and_str( 42, "The answer to the ultimate question of life, the universe, and everything", ); assert_eq!(a.header, 42); assert_eq!( &a.slice, "The answer to the ultimate question of life, the universe, and everything" ); let empty = Arc::from_header_and_str((), ""); assert_eq!(empty.header, ()); assert_eq!(&empty.slice, ""); } #[test] fn erase_and_create_from_thin_air_header() { let a: Arc> = Arc::from_header_and_slice((), &[12, 17, 16]); let b: Arc<[u32]> = a.into(); assert_eq!(&*b, [12, 17, 16]); let c: Arc> = b.into(); assert_eq!(&c.slice, [12, 17, 16]); assert_eq!(c.header, ()); } #[test] fn from_box_and_vec() { let b = Box::new(String::from("xxx")); let b = Arc::::from(b); assert_eq!(&*b, "xxx"); let v = vec![String::from("1"), String::from("2"), String::from("3")]; let v = Arc::<[_]>::from(v); assert_eq!( &*v, [String::from("1"), String::from("2"), String::from("3")] ); let mut v = vec![String::from("1"), String::from("2"), String::from("3")]; v.reserve(10); let v = Arc::<[_]>::from(v); assert_eq!( &*v, [String::from("1"), String::from("2"), String::from("3")] ); } /// It’s possible to make a generic `Arc` wrapper that supports both: /// /// * `T: !Sized` /// * `Arc::make_mut` if `T: Sized` #[test] fn dst_and_make_mut() { struct MyArc(Arc>); #[derive(Clone)] struct MyHeader { // Very interesting things go here } // MyArc is possible let dst: MyArc = MyArc(Arc::from_header_and_str(MyHeader {}, "example")); assert_eq!(&dst.0.slice, "example"); // `make_mut` is still available when `T: Sized` let mut answer: MyArc = MyArc(Arc::new(HeaderSlice { header: MyHeader {}, // Not actually a slice in this case, // but `HeaderSlice` is required to use `from_header_and_str` // and we want the same `MyArc` to support both cases. slice: 6 * 9, })); let mut_ref = Arc::make_mut(&mut answer.0); mut_ref.slice = 42; } } triomphe/src/offset_arc.rs0000644000175000017500000001125114661133735016640 0ustar jamespagejamespageuse core::fmt; use core::marker::PhantomData; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ptr; use super::{Arc, ArcBorrow}; /// An `Arc`, except it holds a pointer to the T instead of to the /// entire ArcInner. /// /// An `OffsetArc` has the same layout and ABI as a non-null /// `const T*` in C, and may be used in FFI function signatures. /// /// ```text /// Arc OffsetArc /// | | /// v v /// --------------------- /// | RefCount | T (data) | [ArcInner] /// --------------------- /// ``` /// /// This means that this is a direct pointer to /// its contained data (and can be read from by both C++ and Rust), /// but we can also convert it to a "regular" `Arc` by removing the offset. /// /// This is very useful if you have an Arc-containing struct shared between Rust and C++, /// and wish for C++ to be able to read the data behind the `Arc` without incurring /// an FFI call overhead. #[derive(Eq)] #[repr(transparent)] pub struct OffsetArc { pub(crate) ptr: ptr::NonNull, pub(crate) phantom: PhantomData, } unsafe impl Send for OffsetArc {} unsafe impl Sync for OffsetArc {} impl Deref for OffsetArc { type Target = T; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*self.ptr.as_ptr() } } } impl Clone for OffsetArc { #[inline] fn clone(&self) -> Self { Arc::into_raw_offset(self.clone_arc()) } } impl Drop for OffsetArc { fn drop(&mut self) { let _ = Arc::from_raw_offset(OffsetArc { ptr: self.ptr, phantom: PhantomData, }); } } impl fmt::Debug for OffsetArc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl PartialEq for OffsetArc { fn eq(&self, other: &OffsetArc) -> bool { *(*self) == *(*other) } #[allow(clippy::partialeq_ne_impl)] fn ne(&self, other: &OffsetArc) -> bool { *(*self) != *(*other) } } impl OffsetArc { /// Temporarily converts |self| into a bonafide Arc and exposes it to the /// provided callback. The refcount is not modified. #[inline] pub fn with_arc(&self, f: F) -> U where F: FnOnce(&Arc) -> U, { // Synthesize transient Arc, which never touches the refcount of the ArcInner. let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.ptr.as_ptr())) }; // Expose the transient Arc to the callback, which may clone it if it wants // and forward the result to the user f(&transient) } /// If uniquely owned, provide a mutable reference /// Else create a copy, and mutate that /// /// This is functionally the same thing as `Arc::make_mut` #[inline] pub fn make_mut(&mut self) -> &mut T where T: Clone, { unsafe { // extract the OffsetArc as an owned variable. This does not modify // the refcount and we should be careful to not drop `this` let this = ptr::read(self); // treat it as a real Arc, but wrapped in a ManuallyDrop // in case `Arc::make_mut()` panics in the clone impl let mut arc = ManuallyDrop::new(Arc::from_raw_offset(this)); // obtain the mutable reference. Cast away the lifetime since // we have the right lifetime bounds in the parameters. // This may mutate `arc`. let ret = Arc::make_mut(&mut *arc) as *mut _; // Store the possibly-mutated arc back inside, after converting // it to a OffsetArc again. Release the ManuallyDrop. // This also does not modify the refcount or call drop on self ptr::write(self, Arc::into_raw_offset(ManuallyDrop::into_inner(arc))); &mut *ret } } /// Clone it as an `Arc` #[inline] pub fn clone_arc(&self) -> Arc { OffsetArc::with_arc(self, |a| a.clone()) } /// Produce a pointer to the data that can be converted back /// to an `Arc` #[inline] pub fn borrow_arc(&self) -> ArcBorrow<'_, T> { ArcBorrow(self.ptr, PhantomData) } /// The reference count of this `Arc`. /// /// The number does not include borrowed pointers, /// or temporary `Arc` pointers created with functions like /// [`ArcBorrow::with_arc`]. /// /// The function is called `strong_count` to mirror `std::sync::Arc::strong_count`, /// however `triomphe::Arc` does not support weak references. #[inline] pub fn strong_count(this: &Self) -> usize { Self::with_arc(this, |arc| Arc::strong_count(arc)) } } triomphe/src/arc_union.rs0000644000175000017500000001166214661133735016510 0ustar jamespagejamespageuse core::fmt; use core::marker::PhantomData; use core::ptr; use core::usize; use super::{Arc, ArcBorrow}; /// A tagged union that can represent `Arc` or `Arc` while only consuming a /// single word. The type is also `NonNull`, and thus can be stored in an Option /// without increasing size. /// /// This is functionally equivalent to /// `enum ArcUnion { First(Arc), Second(Arc)` but only takes up /// up a single word of stack space. /// /// This could probably be extended to support four types if necessary. pub struct ArcUnion { p: ptr::NonNull<()>, phantom_a: PhantomData, phantom_b: PhantomData, } unsafe impl Send for ArcUnion {} unsafe impl Sync for ArcUnion {} impl PartialEq for ArcUnion { fn eq(&self, other: &Self) -> bool { use crate::ArcUnionBorrow::*; match (self.borrow(), other.borrow()) { (First(x), First(y)) => x == y, (Second(x), Second(y)) => x == y, (_, _) => false, } } } /// This represents a borrow of an `ArcUnion`. #[derive(Debug)] pub enum ArcUnionBorrow<'a, A: 'a, B: 'a> { First(ArcBorrow<'a, A>), Second(ArcBorrow<'a, B>), } impl ArcUnion { unsafe fn new(ptr: *mut ()) -> Self { ArcUnion { p: ptr::NonNull::new_unchecked(ptr), phantom_a: PhantomData, phantom_b: PhantomData, } } /// Returns true if the two values are pointer-equal. #[inline] pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.p == other.p } /// Reference count. #[inline] pub fn strong_count(this: &Self) -> usize { ArcUnionBorrow::strong_count(&this.borrow()) } /// Returns an enum representing a borrow of either A or B. pub fn borrow(&self) -> ArcUnionBorrow { if self.is_first() { let ptr = self.p.as_ptr() as *const A; let borrow = unsafe { ArcBorrow::from_ptr(ptr) }; ArcUnionBorrow::First(borrow) } else { let ptr = ((self.p.as_ptr() as usize) & !0x1) as *const B; let borrow = unsafe { ArcBorrow::from_ptr(ptr) }; ArcUnionBorrow::Second(borrow) } } /// Creates an `ArcUnion` from an instance of the first type. #[inline] pub fn from_first(other: Arc) -> Self { unsafe { Self::new(Arc::into_raw(other) as *mut _) } } /// Creates an `ArcUnion` from an instance of the second type. #[inline] pub fn from_second(other: Arc) -> Self { unsafe { Self::new(((Arc::into_raw(other) as usize) | 0x1) as *mut _) } } /// Returns true if this `ArcUnion` contains the first type. #[inline] pub fn is_first(&self) -> bool { self.p.as_ptr() as usize & 0x1 == 0 } /// Returns true if this `ArcUnion` contains the second type. #[inline] pub fn is_second(&self) -> bool { !self.is_first() } /// Returns a borrow of the first type if applicable, otherwise `None`. pub fn as_first(&self) -> Option> { match self.borrow() { ArcUnionBorrow::First(x) => Some(x), ArcUnionBorrow::Second(_) => None, } } /// Returns a borrow of the second type if applicable, otherwise None. pub fn as_second(&self) -> Option> { match self.borrow() { ArcUnionBorrow::First(_) => None, ArcUnionBorrow::Second(x) => Some(x), } } } impl Clone for ArcUnion { fn clone(&self) -> Self { match self.borrow() { ArcUnionBorrow::First(x) => ArcUnion::from_first(x.clone_arc()), ArcUnionBorrow::Second(x) => ArcUnion::from_second(x.clone_arc()), } } } impl Drop for ArcUnion { fn drop(&mut self) { match self.borrow() { ArcUnionBorrow::First(x) => unsafe { let _ = Arc::from_raw(&*x); }, ArcUnionBorrow::Second(x) => unsafe { let _ = Arc::from_raw(&*x); }, } } } impl fmt::Debug for ArcUnion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.borrow(), f) } } impl<'a, A, B> ArcUnionBorrow<'a, A, B> { /// The reference count of this `Arc`. /// /// The number does not include borrowed pointers, /// or temporary `Arc` pointers created with functions like /// [`ArcBorrow::with_arc`]. /// /// The function is called `strong_count` to mirror `std::sync::Arc::strong_count`, /// however `triomphe::Arc` does not support weak references. #[inline] pub fn strong_count(this: &Self) -> usize { match this { ArcUnionBorrow::First(arc) => ArcBorrow::strong_count(arc), ArcUnionBorrow::Second(arc) => ArcBorrow::strong_count(arc), } } } triomphe/src/arc.rs0000644000175000017500000011203614661133735015275 0ustar jamespagejamespageuse alloc::alloc::handle_alloc_error; use alloc::boxed::Box; use core::alloc::Layout; use core::borrow; use core::cmp::Ordering; use core::convert::From; use core::ffi::c_void; use core::fmt; use core::hash::{Hash, Hasher}; use core::iter::FromIterator; use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; use core::ops::Deref; use core::ptr::{self, NonNull}; use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use core::{isize, usize}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; #[cfg(feature = "stable_deref_trait")] use stable_deref_trait::{CloneStableDeref, StableDeref}; use crate::{abort, ArcBorrow, HeaderSlice, OffsetArc, UniqueArc}; /// A soft limit on the amount of references that may be made to an `Arc`. /// /// Going above this limit will abort your program (although not /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// The object allocated by an `Arc` #[repr(C)] pub(crate) struct ArcInner { pub(crate) count: atomic::AtomicUsize, pub(crate) data: T, } unsafe impl Send for ArcInner {} unsafe impl Sync for ArcInner {} impl ArcInner { /// Compute the offset of the `data` field within `ArcInner`. /// /// # Safety /// /// - The pointer must be created from `Arc::into_raw` or similar functions /// - The pointee must be initialized (`&*value` must not be UB). /// That happens automatically if the pointer comes from `Arc` and type was not changed. /// This is **not** the case, for example, when `Arc` was uninitialized `MaybeUninit` /// and the pointer was cast to `*const T`. unsafe fn offset_of_data(value: *const T) -> usize { // We can use `Layout::for_value_raw` when it is stable. let value = &*value; let layout = Layout::new::(); let (_, offset) = layout.extend(Layout::for_value(value)).unwrap(); offset } } /// An atomically reference counted shared pointer /// /// See the documentation for [`Arc`] in the standard library. Unlike the /// standard library `Arc`, this `Arc` does not support weak reference counting. /// /// [`Arc`]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html #[repr(transparent)] pub struct Arc { pub(crate) p: ptr::NonNull>, pub(crate) phantom: PhantomData, } unsafe impl Send for Arc {} unsafe impl Sync for Arc {} impl Arc { /// Construct an `Arc` #[inline] pub fn new(data: T) -> Self { let ptr = Box::into_raw(Box::new(ArcInner { count: atomic::AtomicUsize::new(1), data, })); unsafe { Arc { p: ptr::NonNull::new_unchecked(ptr), phantom: PhantomData, } } } /// Temporarily converts |self| into a bonafide OffsetArc and exposes it to the /// provided callback. The refcount is not modified. #[inline(always)] pub fn with_raw_offset_arc(&self, f: F) -> U where F: FnOnce(&OffsetArc) -> U, { // Synthesize transient Arc, which never touches the refcount of the ArcInner. // Store transient in `ManuallyDrop`, to leave the refcount untouched. let transient = unsafe { ManuallyDrop::new(Arc::into_raw_offset(ptr::read(self))) }; // Expose the transient Arc to the callback, which may clone it if it wants. f(&transient) } /// Converts an `Arc` into a `OffsetArc`. This consumes the `Arc`, so the refcount /// is not modified. #[inline] pub fn into_raw_offset(a: Self) -> OffsetArc { unsafe { OffsetArc { ptr: ptr::NonNull::new_unchecked(Arc::into_raw(a) as *mut T), phantom: PhantomData, } } } /// Converts a `OffsetArc` into an `Arc`. This consumes the `OffsetArc`, so the refcount /// is not modified. #[inline] pub fn from_raw_offset(a: OffsetArc) -> Self { let a = ManuallyDrop::new(a); let ptr = a.ptr.as_ptr(); unsafe { Arc::from_raw(ptr) } } /// Returns the inner value, if the [`Arc`] has exactly one strong reference. /// /// Otherwise, an [`Err`] is returned with the same [`Arc`] that was /// passed in. /// /// # Examples /// /// ``` /// use triomphe::Arc; /// /// let x = Arc::new(3); /// assert_eq!(Arc::try_unwrap(x), Ok(3)); /// /// let x = Arc::new(4); /// let _y = Arc::clone(&x); /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); /// ``` pub fn try_unwrap(this: Self) -> Result { Self::try_unique(this).map(UniqueArc::into_inner) } } impl Arc<[T]> { /// Reconstruct the `Arc<[T]>` from a raw pointer obtained from `into_raw()`. /// /// [`Arc::from_raw`] should accept unsized types, but this is not trivial to do correctly /// until the feature [`pointer_bytes_offsets`](https://github.com/rust-lang/rust/issues/96283) /// is stabilized. This is stopgap solution for slices. /// /// # Safety /// - The given pointer must be a valid pointer to `[T]` that came from [`Arc::into_raw`]. /// - After `from_raw_slice`, the pointer must not be accessed. pub unsafe fn from_raw_slice(ptr: *const [T]) -> Self { Arc::from_raw(ptr) } } impl Arc { /// Convert the `Arc` to a raw pointer, suitable for use across FFI /// /// Note: This returns a pointer to the data T, which is offset in the allocation. /// /// It is recommended to use OffsetArc for this. #[inline] pub fn into_raw(this: Self) -> *const T { let this = ManuallyDrop::new(this); this.as_ptr() } /// Reconstruct the `Arc` from a raw pointer obtained from into_raw() /// /// Note: This raw pointer will be offset in the allocation and must be preceded /// by the atomic count. /// /// It is recommended to use OffsetArc for this /// /// # Safety /// - The given pointer must be a valid pointer to `T` that came from [`Arc::into_raw`]. /// - After `from_raw`, the pointer must not be accessed. #[inline] pub unsafe fn from_raw(ptr: *const T) -> Self { // To find the corresponding pointer to the `ArcInner` we need // to subtract the offset of the `data` field from the pointer. // SAFETY: `ptr` comes from `ArcInner.data`, so it must be initialized. let offset_of_data = ArcInner::::offset_of_data(ptr); // SAFETY: `from_raw_inner` expects a pointer to the beginning of the allocation, // not a pointer to data part. // `ptr` points to `ArcInner.data`, so subtraction results // in the beginning of the `ArcInner`, which is the beginning of the allocation. let arc_inner_ptr = ptr.byte_sub(offset_of_data); Arc::from_raw_inner(arc_inner_ptr as *mut ArcInner) } /// Returns the raw pointer. /// /// Same as into_raw except `self` isn't consumed. #[inline] pub fn as_ptr(&self) -> *const T { // SAFETY: This cannot go through a reference to `data`, because this method // is used to implement `into_raw`. To reconstruct the full `Arc` from this // pointer, it needs to maintain its full provenance, and not be reduced to // just the contained `T`. unsafe { ptr::addr_of_mut!((*self.ptr()).data) } } /// Produce a pointer to the data that can be converted back /// to an Arc. This is basically an `&Arc`, without the extra indirection. /// It has the benefits of an `&T` but also knows about the underlying refcount /// and can be converted into more `Arc`s if necessary. #[inline] pub fn borrow_arc(&self) -> ArcBorrow<'_, T> { unsafe { ArcBorrow(NonNull::new_unchecked(self.as_ptr() as *mut T), PhantomData) } } /// Returns the address on the heap of the Arc itself -- not the T within it -- for memory /// reporting. pub fn heap_ptr(&self) -> *const c_void { self.p.as_ptr() as *const ArcInner as *const c_void } /// The reference count of this `Arc`. /// /// The number does not include borrowed pointers, /// or temporary `Arc` pointers created with functions like /// [`ArcBorrow::with_arc`]. /// /// The function is called `strong_count` to mirror `std::sync::Arc::strong_count`, /// however `triomphe::Arc` does not support weak references. #[inline] pub fn strong_count(this: &Self) -> usize { this.inner().count.load(Relaxed) } #[inline] pub(super) fn into_raw_inner(this: Self) -> *mut ArcInner { let this = ManuallyDrop::new(this); this.ptr() } /// Construct an `Arc` from an allocated `ArcInner`. /// # Safety /// The `ptr` must point to a valid instance, allocated by an `Arc`. The reference could will /// not be modified. pub(super) unsafe fn from_raw_inner(ptr: *mut ArcInner) -> Self { Arc { p: ptr::NonNull::new_unchecked(ptr), phantom: PhantomData, } } #[inline] pub(super) fn inner(&self) -> &ArcInner { // This unsafety is ok because while this arc is alive we're guaranteed // that the inner pointer is valid. Furthermore, we know that the // `ArcInner` structure itself is `Sync` because the inner data is // `Sync` as well, so we're ok loaning out an immutable pointer to these // contents. unsafe { &*self.ptr() } } // Non-inlined part of `drop`. Just invokes the destructor. #[inline(never)] unsafe fn drop_slow(&mut self) { let _ = Box::from_raw(self.ptr()); } /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to /// [`ptr::eq`]. This function ignores the metadata of `dyn Trait` pointers. #[inline] pub fn ptr_eq(this: &Self, other: &Self) -> bool { ptr::addr_eq(this.ptr(), other.ptr()) } pub(crate) fn ptr(&self) -> *mut ArcInner { self.p.as_ptr() } /// Allocates an `ArcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. /// /// ## Safety /// /// `mem_to_arcinner` must return the same pointer, the only things that can change are /// - its type /// - its metadata /// /// `value_layout` must be correct for `T`. #[allow(unused_unsafe)] pub(super) unsafe fn allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> NonNull> { let layout = Layout::new::>() .extend(value_layout) .unwrap() .0 .pad_to_align(); // Safety: we propagate safety requirements to the caller unsafe { Arc::try_allocate_for_layout(value_layout, mem_to_arcinner) .unwrap_or_else(|_| handle_alloc_error(layout)) } } /// Allocates an `ArcInner` with sufficient space for /// a possibly-unsized inner value where the value has the layout provided, /// returning an error if allocation fails. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. /// /// ## Safety /// /// `mem_to_arcinner` must return the same pointer, the only things that can change are /// - its type /// - its metadata /// /// `value_layout` must be correct for `T`. #[allow(unused_unsafe)] unsafe fn try_allocate_for_layout( value_layout: Layout, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> Result>, ()> { let layout = Layout::new::>() .extend(value_layout) .unwrap() .0 .pad_to_align(); let ptr = NonNull::new(alloc::alloc::alloc(layout)).ok_or(())?; // Initialize the ArcInner let inner = mem_to_arcinner(ptr.as_ptr()); debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout); unsafe { ptr::write(&mut (*inner).count, atomic::AtomicUsize::new(1)); } // Safety: `ptr` is checked to be non-null, // `inner` is the same as `ptr` (per the safety requirements of this function) unsafe { Ok(NonNull::new_unchecked(inner)) } } } impl Arc> { pub(super) fn allocate_for_header_and_slice( len: usize, ) -> NonNull>> { let layout = Layout::new::() .extend(Layout::array::(len).unwrap()) .unwrap() .0 .pad_to_align(); unsafe { // Safety: // - the provided closure does not change the pointer (except for meta & type) // - the provided layout is valid for `HeaderSlice` Arc::allocate_for_layout(layout, |mem| { // Synthesize the fat pointer. We do this by claiming we have a direct // pointer to a [T], and then changing the type of the borrow. The key // point here is that the length portion of the fat pointer applies // only to the number of elements in the dynamically-sized portion of // the type, so the value will be the same whether it points to a [T] // or something else with a [T] as its last member. let fake_slice = ptr::slice_from_raw_parts_mut(mem as *mut T, len); fake_slice as *mut ArcInner> }) } } } impl Arc> { /// Create an Arc contains an `MaybeUninit`. pub fn new_uninit() -> Self { Arc::new(MaybeUninit::::uninit()) } /// Calls `MaybeUninit::write` on the value contained. /// /// ## Panics /// /// If the `Arc` is not unique. #[deprecated( since = "0.1.7", note = "this function previously was UB and now panics for non-unique `Arc`s. Use `UniqueArc::write` instead." )] #[track_caller] pub fn write(&mut self, val: T) -> &mut T { UniqueArc::write(must_be_unique(self), val) } /// Obtain a mutable pointer to the stored `MaybeUninit`. pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit { unsafe { &mut (*self.ptr()).data } } /// # Safety /// /// Must initialize all fields before calling this function. #[inline] pub unsafe fn assume_init(self) -> Arc { Arc::from_raw_inner(ManuallyDrop::new(self).ptr().cast()) } } impl Arc<[MaybeUninit]> { /// Create an Arc contains an array `[MaybeUninit]` of `len`. pub fn new_uninit_slice(len: usize) -> Self { UniqueArc::new_uninit_slice(len).shareable() } /// Obtain a mutable slice to the stored `[MaybeUninit]`. #[deprecated( since = "0.1.8", note = "this function previously was UB and now panics for non-unique `Arc`s. Use `UniqueArc` or `get_mut` instead." )] #[track_caller] pub fn as_mut_slice(&mut self) -> &mut [MaybeUninit] { must_be_unique(self) } /// # Safety /// /// Must initialize all fields before calling this function. #[inline] pub unsafe fn assume_init(self) -> Arc<[T]> { Arc::from_raw_inner(ManuallyDrop::new(self).ptr() as _) } } impl Clone for Arc { #[inline] fn clone(&self) -> Self { // Using a relaxed ordering is alright here, as knowledge of the // original reference prevents other threads from erroneously deleting // the object. // // As explained in the [Boost documentation][1], Increasing the // reference counter can always be done with memory_order_relaxed: New // references to an object can only be formed from an existing // reference, and passing an existing reference from one thread to // another must already provide any required synchronization. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) let old_size = self.inner().count.fetch_add(1, Relaxed); // However we need to guard against massive refcounts in case someone // is `mem::forget`ing Arcs. If we don't do this the count can overflow // and users will use-after free. We racily saturate to `isize::MAX` on // the assumption that there aren't ~2 billion threads incrementing // the reference count at once. This branch will never be taken in // any realistic program. // // We abort because such a program is incredibly degenerate, and we // don't care to support it. if old_size > MAX_REFCOUNT { abort(); } unsafe { Arc { p: ptr::NonNull::new_unchecked(self.ptr()), phantom: PhantomData, } } } } impl Deref for Arc { type Target = T; #[inline] fn deref(&self) -> &T { &self.inner().data } } impl Arc { /// Makes a mutable reference to the `Arc`, cloning if necessary /// /// This is functionally equivalent to [`Arc::make_mut`][mm] from the standard library. /// /// If this `Arc` is uniquely owned, `make_mut()` will provide a mutable /// reference to the contents. If not, `make_mut()` will create a _new_ `Arc` /// with a copy of the contents, update `this` to point to it, and provide /// a mutable reference to its contents. /// /// This is useful for implementing copy-on-write schemes where you wish to /// avoid copying things if your `Arc` is not shared. /// /// [mm]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.make_mut #[inline] pub fn make_mut(this: &mut Self) -> &mut T { if !this.is_unique() { // Another pointer exists; clone *this = Arc::new(T::clone(this)); } unsafe { // This unsafety is ok because we're guaranteed that the pointer // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. &mut (*this.ptr()).data } } /// Makes a `UniqueArc` from an `Arc`, cloning if necessary. /// /// If this `Arc` is uniquely owned, `make_unique()` will provide a `UniqueArc` /// containing `this`. If not, `make_unique()` will create a _new_ `Arc` /// with a copy of the contents, update `this` to point to it, and provide /// a `UniqueArc` to it. /// /// This is useful for implementing copy-on-write schemes where you wish to /// avoid copying things if your `Arc` is not shared. #[inline] pub fn make_unique(this: &mut Self) -> &mut UniqueArc { if !this.is_unique() { // Another pointer exists; clone *this = Arc::new(T::clone(this)); } unsafe { // Safety: this is either unique or just created (which is also unique) UniqueArc::from_arc_ref(this) } } /// If we have the only reference to `T` then unwrap it. Otherwise, clone `T` and return the clone. /// /// Assuming `arc_t` is of type `Arc`, this function is functionally equivalent to `(*arc_t).clone()`, but will avoid cloning the inner value where possible. pub fn unwrap_or_clone(this: Arc) -> T { Self::try_unwrap(this).unwrap_or_else(|this| T::clone(&this)) } } impl Arc { /// Provides mutable access to the contents _if_ the `Arc` is uniquely owned. #[inline] pub fn get_mut(this: &mut Self) -> Option<&mut T> { if this.is_unique() { unsafe { // See make_mut() for documentation of the threadsafety here. Some(&mut (*this.ptr()).data) } } else { None } } /// Provides unique access to the arc _if_ the `Arc` is uniquely owned. pub fn get_unique(this: &mut Self) -> Option<&mut UniqueArc> { Self::try_as_unique(this).ok() } /// Whether or not the `Arc` is uniquely owned (is the refcount 1?). pub fn is_unique(&self) -> bool { // See the extensive discussion in [1] for why this needs to be Acquire. // // [1] https://github.com/servo/servo/issues/21186 Self::count(self) == 1 } /// Gets the number of [`Arc`] pointers to this allocation pub fn count(this: &Self) -> usize { this.inner().count.load(Acquire) } /// Returns a [`UniqueArc`] if the [`Arc`] has exactly one strong reference. /// /// Otherwise, an [`Err`] is returned with the same [`Arc`] that was /// passed in. /// /// # Examples /// /// ``` /// use triomphe::{Arc, UniqueArc}; /// /// let x = Arc::new(3); /// assert_eq!(UniqueArc::into_inner(Arc::try_unique(x).unwrap()), 3); /// /// let x = Arc::new(4); /// let _y = Arc::clone(&x); /// assert_eq!( /// *Arc::try_unique(x).map(UniqueArc::into_inner).unwrap_err(), /// 4, /// ); /// ``` pub fn try_unique(this: Self) -> Result, Self> { if this.is_unique() { // Safety: The current arc is unique and making a `UniqueArc` // from it is sound unsafe { Ok(UniqueArc::from_arc(this)) } } else { Err(this) } } pub(crate) fn try_as_unique(this: &mut Self) -> Result<&mut UniqueArc, &mut Self> { if this.is_unique() { // Safety: The current arc is unique and making a `UniqueArc` // from it is sound unsafe { Ok(UniqueArc::from_arc_ref(this)) } } else { Err(this) } } } impl Drop for Arc { #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize // with other threads unless we are going to delete the object. if self.inner().count.fetch_sub(1, Release) != 1 { return; } // FIXME(bholley): Use the updated comment when [2] is merged. // // This load is needed to prevent reordering of use of the data and // deletion of the data. Because it is marked `Release`, the decreasing // of the reference count synchronizes with this `Acquire` load. This // means that use of the data happens before decreasing the reference // count, which happens before this load, which happens before the // deletion of the data. // // As explained in the [Boost documentation][1], // // > It is important to enforce any possible access to the object in one // > thread (through an existing reference) to *happen before* deleting // > the object in a different thread. This is achieved by a "release" // > operation after dropping a reference (any access to the object // > through this reference must obviously happened before), and an // > "acquire" operation before deleting the object. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) // [2]: https://github.com/rust-lang/rust/pull/41714 self.inner().count.load(Acquire); unsafe { self.drop_slow(); } } } impl PartialEq for Arc { fn eq(&self, other: &Arc) -> bool { // TODO: pointer equality is incorrect if `T` is not `Eq`. Self::ptr_eq(self, other) || *(*self) == *(*other) } #[allow(clippy::partialeq_ne_impl)] fn ne(&self, other: &Arc) -> bool { !Self::ptr_eq(self, other) && *(*self) != *(*other) } } impl PartialOrd for Arc { fn partial_cmp(&self, other: &Arc) -> Option { (**self).partial_cmp(&**other) } fn lt(&self, other: &Arc) -> bool { *(*self) < *(*other) } fn le(&self, other: &Arc) -> bool { *(*self) <= *(*other) } fn gt(&self, other: &Arc) -> bool { *(*self) > *(*other) } fn ge(&self, other: &Arc) -> bool { *(*self) >= *(*other) } } impl Ord for Arc { fn cmp(&self, other: &Arc) -> Ordering { (**self).cmp(&**other) } } impl Eq for Arc {} impl fmt::Display for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&**self, f) } } impl fmt::Debug for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl fmt::Pointer for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.ptr(), f) } } impl Default for Arc { #[inline] fn default() -> Arc { Arc::new(Default::default()) } } impl Hash for Arc { fn hash(&self, state: &mut H) { (**self).hash(state) } } impl From for Arc { #[inline] fn from(t: T) -> Self { Arc::new(t) } } impl FromIterator for Arc<[A]> { fn from_iter>(iter: T) -> Self { UniqueArc::from_iter(iter).shareable() } } impl borrow::Borrow for Arc { #[inline] fn borrow(&self) -> &T { self } } impl AsRef for Arc { #[inline] fn as_ref(&self) -> &T { self } } #[cfg(feature = "stable_deref_trait")] unsafe impl StableDeref for Arc {} #[cfg(feature = "stable_deref_trait")] unsafe impl CloneStableDeref for Arc {} #[cfg(feature = "serde")] impl<'de, T: Deserialize<'de>> Deserialize<'de> for Arc { fn deserialize(deserializer: D) -> Result, D::Error> where D: ::serde::de::Deserializer<'de>, { T::deserialize(deserializer).map(Arc::new) } } #[cfg(feature = "serde")] impl Serialize for Arc { fn serialize(&self, serializer: S) -> Result where S: ::serde::ser::Serializer, { (**self).serialize(serializer) } } // Safety: // This implementation must guarantee that it is sound to call replace_ptr with an unsized variant // of the pointer retuned in `as_sized_ptr`. The basic property of Unsize coercion is that safety // variants and layout is unaffected. The Arc does not rely on any other property of T. This makes // any unsized ArcInner valid for being shared with the sized variant. // This does _not_ mean that any T can be unsized into an U, but rather than if such unsizing is // possible then it can be propagated into the Arc. #[cfg(feature = "unsize")] unsafe impl unsize::CoerciblePtr for Arc { type Pointee = T; type Output = Arc; fn as_sized_ptr(&mut self) -> *mut T { // Returns a pointer to the complete inner. The unsizing itself won't care about the // pointer value and promises not to offset it. self.p.as_ptr() as *mut T } unsafe fn replace_ptr(self, new: *mut U) -> Arc { // Fix the provenance by ensuring that of `self` is used. let inner = ManuallyDrop::new(self); let p = inner.p.as_ptr() as *mut T; // Safety: This points to an ArcInner of the previous self and holds shared ownership since // the old pointer never decremented the reference count. The caller upholds that `new` is // an unsized version of the previous ArcInner. This assumes that unsizing to the fat // pointer tag of an `ArcInner` and `U` is isomorphic under a direct pointer cast since // in reality we unsized *mut T to *mut U at the address of the ArcInner. This is the case // for all currently envisioned unsized types where the tag of T and ArcInner are simply // the same. Arc::from_raw_inner(p.replace_ptr(new) as *mut ArcInner) } } #[track_caller] fn must_be_unique(arc: &mut Arc) -> &mut UniqueArc { match Arc::try_as_unique(arc) { Ok(unique) => unique, Err(this) => panic!("`Arc` must be unique in order for this operation to be safe, there are currently {} copies", Arc::count(this)), } } #[cfg(test)] mod tests { use crate::arc::Arc; use alloc::borrow::ToOwned; use alloc::string::String; use alloc::vec::Vec; use core::iter::FromIterator; use core::mem::MaybeUninit; #[cfg(feature = "unsize")] use unsize::{CoerceUnsize, Coercion}; #[test] fn try_unwrap() { let x = Arc::new(100usize); let y = x.clone(); // The count should be two so `try_unwrap()` should fail assert_eq!(Arc::count(&x), 2); assert!(Arc::try_unwrap(x).is_err()); // Since `x` has now been dropped, the count should be 1 // and `try_unwrap()` should succeed assert_eq!(Arc::count(&y), 1); assert_eq!(Arc::try_unwrap(y), Ok(100)); } #[test] #[cfg(feature = "unsize")] fn coerce_to_slice() { let x = Arc::new([0u8; 4]); let y: Arc<[u8]> = x.clone().unsize(Coercion::to_slice()); assert_eq!((*x).as_ptr(), (*y).as_ptr()); } #[test] #[cfg(feature = "unsize")] fn coerce_to_dyn() { let x: Arc<_> = Arc::new(|| 42u32); let x: Arc<_> = x.unsize(Coercion::<_, dyn Fn() -> u32>::to_fn()); assert_eq!((*x)(), 42); } #[test] #[allow(deprecated)] fn maybeuninit() { let mut arc: Arc> = Arc::new_uninit(); arc.write(999); let arc = unsafe { arc.assume_init() }; assert_eq!(*arc, 999); } #[test] #[allow(deprecated)] #[should_panic = "`Arc` must be unique in order for this operation to be safe"] fn maybeuninit_ub_to_proceed() { let mut uninit = Arc::new_uninit(); let clone = uninit.clone(); let x: &MaybeUninit = &*clone; // This write invalidates `x` reference uninit.write(String::from("nonononono")); // Read invalidated reference to trigger UB let _ = &*x; } #[test] #[allow(deprecated)] #[should_panic = "`Arc` must be unique in order for this operation to be safe"] fn maybeuninit_slice_ub_to_proceed() { let mut uninit = Arc::new_uninit_slice(13); let clone = uninit.clone(); let x: &[MaybeUninit] = &*clone; // This write invalidates `x` reference uninit.as_mut_slice()[0].write(String::from("nonononono")); // Read invalidated reference to trigger UB let _ = &*x; } #[test] fn maybeuninit_array() { let mut arc: Arc<[MaybeUninit<_>]> = Arc::new_uninit_slice(5); assert!(arc.is_unique()); #[allow(deprecated)] for (uninit, index) in arc.as_mut_slice().iter_mut().zip(0..5) { let ptr = uninit.as_mut_ptr(); unsafe { core::ptr::write(ptr, index) }; } let arc = unsafe { arc.assume_init() }; assert!(arc.is_unique()); // Using clone to that the layout generated in new_uninit_slice is compatible // with ArcInner. let arcs = [ arc.clone(), arc.clone(), arc.clone(), arc.clone(), arc.clone(), ]; assert_eq!(6, Arc::count(&arc)); // If the layout is not compatible, then the data might be corrupted. assert_eq!(*arc, [0, 1, 2, 3, 4]); // Drop the arcs and check the count and the content to // make sure it isn't corrupted. drop(arcs); assert!(arc.is_unique()); assert_eq!(*arc, [0, 1, 2, 3, 4]); } #[test] fn roundtrip() { let arc: Arc = Arc::new(0usize); let ptr = Arc::into_raw(arc); unsafe { let _arc = Arc::from_raw(ptr); } } #[test] fn from_iterator_exact_size() { let arc = Arc::from_iter(Vec::from_iter(["ololo".to_owned(), "trololo".to_owned()])); assert_eq!(1, Arc::count(&arc)); assert_eq!(["ololo".to_owned(), "trololo".to_owned()], *arc); } #[test] fn from_iterator_unknown_size() { let arc = Arc::from_iter( Vec::from_iter(["ololo".to_owned(), "trololo".to_owned()]) .into_iter() // Filter is opaque to iterators, so the resulting iterator // will report lower bound of 0. .filter(|_| true), ); assert_eq!(1, Arc::count(&arc)); assert_eq!(["ololo".to_owned(), "trololo".to_owned()], *arc); } #[test] fn roundtrip_slice() { let arc = Arc::from(Vec::from_iter([17, 19])); let ptr = Arc::into_raw(arc); let arc = unsafe { Arc::from_raw_slice(ptr) }; assert_eq!([17, 19], *arc); assert_eq!(1, Arc::count(&arc)); } #[test] fn arc_eq_and_cmp() { [ [("*", &b"AB"[..]), ("*", &b"ab"[..])], [("*", &b"AB"[..]), ("*", &b"a"[..])], [("*", &b"A"[..]), ("*", &b"ab"[..])], [("A", &b"*"[..]), ("a", &b"*"[..])], [("a", &b"*"[..]), ("A", &b"*"[..])], [("AB", &b"*"[..]), ("a", &b"*"[..])], [("A", &b"*"[..]), ("ab", &b"*"[..])], ] .iter() .for_each(|[lt @ (lh, ls), rt @ (rh, rs)]| { let l = Arc::from_header_and_slice(lh, ls); let r = Arc::from_header_and_slice(rh, rs); assert_eq!(l, l); assert_eq!(r, r); assert_ne!(l, r); assert_ne!(r, l); assert_eq!(l <= l, lt <= lt, "{lt:?} <= {lt:?}"); assert_eq!(l >= l, lt >= lt, "{lt:?} >= {lt:?}"); assert_eq!(l < l, lt < lt, "{lt:?} < {lt:?}"); assert_eq!(l > l, lt > lt, "{lt:?} > {lt:?}"); assert_eq!(r <= r, rt <= rt, "{rt:?} <= {rt:?}"); assert_eq!(r >= r, rt >= rt, "{rt:?} >= {rt:?}"); assert_eq!(r < r, rt < rt, "{rt:?} < {rt:?}"); assert_eq!(r > r, rt > rt, "{rt:?} > {rt:?}"); assert_eq!(l < r, lt < rt, "{lt:?} < {rt:?}"); assert_eq!(r > l, rt > lt, "{rt:?} > {lt:?}"); }) } #[test] fn arc_eq_and_partial_cmp() { [ [(0.0, &[0.0, 0.0][..]), (1.0, &[0.0, 0.0][..])], [(1.0, &[0.0, 0.0][..]), (0.0, &[0.0, 0.0][..])], [(0.0, &[0.0][..]), (0.0, &[0.0, 0.0][..])], [(0.0, &[0.0, 0.0][..]), (0.0, &[0.0][..])], [(0.0, &[1.0, 2.0][..]), (0.0, &[10.0, 20.0][..])], ] .iter() .for_each(|[lt @ (lh, ls), rt @ (rh, rs)]| { let l = Arc::from_header_and_slice(lh, ls); let r = Arc::from_header_and_slice(rh, rs); assert_eq!(l, l); assert_eq!(r, r); assert_ne!(l, r); assert_ne!(r, l); assert_eq!(l <= l, lt <= lt, "{lt:?} <= {lt:?}"); assert_eq!(l >= l, lt >= lt, "{lt:?} >= {lt:?}"); assert_eq!(l < l, lt < lt, "{lt:?} < {lt:?}"); assert_eq!(l > l, lt > lt, "{lt:?} > {lt:?}"); assert_eq!(r <= r, rt <= rt, "{rt:?} <= {rt:?}"); assert_eq!(r >= r, rt >= rt, "{rt:?} >= {rt:?}"); assert_eq!(r < r, rt < rt, "{rt:?} < {rt:?}"); assert_eq!(r > r, rt > rt, "{rt:?} > {rt:?}"); assert_eq!(l < r, lt < rt, "{lt:?} < {rt:?}"); assert_eq!(r > l, rt > lt, "{rt:?} > {lt:?}"); }) } #[test] fn test_strong_count() { let arc = Arc::new(17); assert_eq!(1, Arc::strong_count(&arc)); let arc2 = arc.clone(); assert_eq!(2, Arc::strong_count(&arc)); drop(arc); assert_eq!(1, Arc::strong_count(&arc2)); } #[test] fn test_partial_eq_bug() { let float = f32::NAN; assert_ne!(float, float); let arc = Arc::new(f32::NAN); // TODO: this is a bug. assert_eq!(arc, arc); } #[test] fn test_into_raw_from_raw_dst() { trait AnInteger { fn get_me_an_integer(&self) -> u64; } impl AnInteger for u32 { fn get_me_an_integer(&self) -> u64 { *self as u64 } } let arc = Arc::::new(19); let data = Arc::into_raw(arc); let data: *const dyn AnInteger = data as *const _; let arc: Arc = unsafe { Arc::from_raw(data) }; assert_eq!(19, arc.get_me_an_integer()); } #[allow(dead_code)] const fn is_partial_ord() {} #[allow(dead_code)] const fn is_ord() {} // compile-time check that PartialOrd/Ord is correctly derived const _: () = is_partial_ord::>(); const _: () = is_ord::>(); } triomphe/src/thin_arc.rs0000644000175000017500000003553714661133735016331 0ustar jamespagejamespageuse core::cmp::Ordering; use core::ffi::c_void; use core::fmt; use core::hash::{Hash, Hasher}; use core::iter::{ExactSizeIterator, Iterator}; use core::marker::PhantomData; use core::mem::ManuallyDrop; use core::ops::Deref; use core::ptr; use core::usize; use super::{Arc, ArcInner, HeaderSliceWithLength, HeaderWithLength}; /// A "thin" `Arc` containing dynamically sized data /// /// This is functionally equivalent to `Arc<(H, [T])>` /// /// When you create an `Arc` containing a dynamically sized type /// like `HeaderSlice`, the `Arc` is represented on the stack /// as a "fat pointer", where the length of the slice is stored /// alongside the `Arc`'s pointer. In some situations you may wish to /// have a thin pointer instead, perhaps for FFI compatibility /// or space efficiency. /// /// Note that we use `[T; 0]` in order to have the right alignment for `T`. /// /// `ThinArc` solves this by storing the length in the allocation itself, /// via `HeaderSliceWithLength`. #[repr(transparent)] pub struct ThinArc { ptr: ptr::NonNull>>, phantom: PhantomData<(H, T)>, } unsafe impl Send for ThinArc {} unsafe impl Sync for ThinArc {} // Synthesize a fat pointer from a thin pointer. // // See the comment around the analogous operation in from_header_and_iter. #[inline] fn thin_to_thick( thin: *mut ArcInner>, ) -> *mut ArcInner> { let len = unsafe { (*thin).data.header.length }; let fake_slice = ptr::slice_from_raw_parts_mut(thin as *mut T, len); fake_slice as *mut ArcInner> } impl ThinArc { /// Temporarily converts |self| into a bonafide Arc and exposes it to the /// provided callback. The refcount is not modified. #[inline] pub fn with_arc(&self, f: F) -> U where F: FnOnce(&Arc>) -> U, { // Synthesize transient Arc, which never touches the refcount of the ArcInner. let transient = unsafe { ManuallyDrop::new(Arc { p: ptr::NonNull::new_unchecked(thin_to_thick(self.ptr.as_ptr())), phantom: PhantomData, }) }; // Expose the transient Arc to the callback, which may clone it if it wants // and forward the result to the user f(&transient) } /// Creates a `ThinArc` for a HeaderSlice using the given header struct and /// iterator to generate the slice. pub fn from_header_and_iter(header: H, items: I) -> Self where I: Iterator + ExactSizeIterator, { let header = HeaderWithLength::new(header, items.len()); Arc::into_thin(Arc::from_header_and_iter(header, items)) } /// Creates a `ThinArc` for a HeaderSlice using the given header struct and /// a slice to copy. pub fn from_header_and_slice(header: H, items: &[T]) -> Self where T: Copy, { let header = HeaderWithLength::new(header, items.len()); Arc::into_thin(Arc::from_header_and_slice(header, items)) } /// Returns the address on the heap of the ThinArc itself -- not the T /// within it -- for memory reporting. #[inline] pub fn ptr(&self) -> *const c_void { self.ptr.as_ptr() as *const ArcInner as *const c_void } /// Returns the address on the heap of the Arc itself -- not the T within it -- for memory /// reporting. #[inline] pub fn heap_ptr(&self) -> *const c_void { self.ptr() } /// # Safety /// /// Constructs an ThinArc from a raw pointer. /// /// The raw pointer must have been previously returned by a call to /// ThinArc::into_raw. /// /// The user of from_raw has to make sure a specific value of T is only dropped once. /// /// This function is unsafe because improper use may lead to memory unsafety, /// even if the returned ThinArc is never accessed. #[inline] pub unsafe fn from_raw(ptr: *const c_void) -> Self { Self { ptr: ptr::NonNull::new_unchecked(ptr as *mut c_void).cast(), phantom: PhantomData, } } /// Consume ThinArc and returned the wrapped pointer. #[inline] pub fn into_raw(self) -> *const c_void { let this = ManuallyDrop::new(self); this.ptr.cast().as_ptr() } /// Provides a raw pointer to the data. /// The counts are not affected in any way and the ThinArc is not consumed. /// The pointer is valid for as long as there are strong counts in the ThinArc. #[inline] pub fn as_ptr(&self) -> *const c_void { self.ptr() } /// The reference count of this `Arc`. /// /// The number does not include borrowed pointers, /// or temporary `Arc` pointers created with functions like /// [`ArcBorrow::with_arc`](crate::ArcBorrow::with_arc). /// /// The function is called `strong_count` to mirror `std::sync::Arc::strong_count`, /// however `triomphe::Arc` does not support weak references. #[inline] pub fn strong_count(this: &Self) -> usize { Self::with_arc(this, |arc| Arc::strong_count(arc)) } } impl Deref for ThinArc { type Target = HeaderSliceWithLength; #[inline] fn deref(&self) -> &Self::Target { unsafe { &(*thin_to_thick(self.ptr.as_ptr())).data } } } impl Clone for ThinArc { #[inline] fn clone(&self) -> Self { ThinArc::with_arc(self, |a| { // Safety: `a` isn't mutable thus the header length remains valid unsafe { Arc::into_thin_unchecked(a.clone()) } }) } } impl Drop for ThinArc { #[inline] fn drop(&mut self) { let _ = Arc::from_thin(ThinArc { ptr: self.ptr, phantom: PhantomData, }); } } impl Arc> { /// Converts an `Arc` into a `ThinArc`. This consumes the `Arc`, so the refcount /// is not modified. /// /// # Safety /// Assumes that the header length matches the slice length. #[inline] unsafe fn into_thin_unchecked(a: Self) -> ThinArc { let a = ManuallyDrop::new(a); debug_assert_eq!( a.header.length, a.slice.len(), "Length needs to be correct for ThinArc to work" ); let fat_ptr: *mut ArcInner> = a.ptr(); let thin_ptr = fat_ptr as *mut [usize] as *mut usize; ThinArc { ptr: unsafe { ptr::NonNull::new_unchecked( thin_ptr as *mut ArcInner>, ) }, phantom: PhantomData, } } /// Converts an `Arc` into a `ThinArc`. This consumes the `Arc`, so the refcount /// is not modified. #[inline] pub fn into_thin(a: Self) -> ThinArc { assert_eq!( a.header.length, a.slice.len(), "Length needs to be correct for ThinArc to work" ); unsafe { Self::into_thin_unchecked(a) } } /// Converts a `ThinArc` into an `Arc`. This consumes the `ThinArc`, so the refcount /// is not modified. #[inline] pub fn from_thin(a: ThinArc) -> Self { let a = ManuallyDrop::new(a); let ptr = thin_to_thick(a.ptr.as_ptr()); unsafe { Arc { p: ptr::NonNull::new_unchecked(ptr), phantom: PhantomData, } } } } impl PartialEq for ThinArc { #[inline] fn eq(&self, other: &ThinArc) -> bool { ThinArc::with_arc(self, |a| ThinArc::with_arc(other, |b| *a == *b)) } } impl Eq for ThinArc {} impl PartialOrd for ThinArc { #[inline] fn partial_cmp(&self, other: &ThinArc) -> Option { ThinArc::with_arc(self, |a| ThinArc::with_arc(other, |b| a.partial_cmp(b))) } } impl Ord for ThinArc { #[inline] fn cmp(&self, other: &ThinArc) -> Ordering { ThinArc::with_arc(self, |a| ThinArc::with_arc(other, |b| a.cmp(b))) } } impl Hash for ThinArc { fn hash(&self, state: &mut HSR) { ThinArc::with_arc(self, |a| a.hash(state)) } } impl fmt::Debug for ThinArc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl fmt::Pointer for ThinArc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.ptr(), f) } } #[cfg(test)] mod tests { use crate::{Arc, HeaderWithLength, ThinArc}; use alloc::vec; use core::clone::Clone; use core::ops::Drop; use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, SeqCst}; #[derive(PartialEq)] struct Canary(*mut atomic::AtomicUsize); impl Drop for Canary { fn drop(&mut self) { unsafe { (*self.0).fetch_add(1, SeqCst); } } } #[test] fn empty_thin() { let header = HeaderWithLength::new(100u32, 0); let x = Arc::from_header_and_iter(header, core::iter::empty::()); let y = Arc::into_thin(x.clone()); assert_eq!(y.header.header, 100); assert!(y.slice.is_empty()); assert_eq!(x.header.header, 100); assert!(x.slice.is_empty()); } #[test] fn thin_assert_padding() { #[derive(Clone, Default)] #[repr(C)] struct Padded { i: u16, } // The header will have more alignment than `Padded` let header = HeaderWithLength::new(0i32, 2); let items = vec![Padded { i: 0xdead }, Padded { i: 0xbeef }]; let a = ThinArc::from_header_and_iter(header, items.into_iter()); assert_eq!(a.slice.len(), 2); assert_eq!(a.slice[0].i, 0xdead); assert_eq!(a.slice[1].i, 0xbeef); } #[test] #[allow(clippy::redundant_clone, clippy::eq_op)] fn slices_and_thin() { let mut canary = atomic::AtomicUsize::new(0); let c = Canary(&mut canary as *mut atomic::AtomicUsize); let v = vec![5, 6]; let header = HeaderWithLength::new(c, v.len()); { let x = Arc::into_thin(Arc::from_header_and_slice(header, &v)); let y = ThinArc::with_arc(&x, |q| q.clone()); let _ = y.clone(); let _ = x == x; Arc::from_thin(x.clone()); } assert_eq!(canary.load(Acquire), 1); } #[test] #[allow(clippy::redundant_clone, clippy::eq_op)] fn iter_and_thin() { let mut canary = atomic::AtomicUsize::new(0); let c = Canary(&mut canary as *mut atomic::AtomicUsize); let v = vec![5, 6]; let header = HeaderWithLength::new(c, v.len()); { let x = Arc::into_thin(Arc::from_header_and_iter(header, v.into_iter())); let y = ThinArc::with_arc(&x, |q| q.clone()); let _ = y.clone(); let _ = x == x; Arc::from_thin(x.clone()); } assert_eq!(canary.load(Acquire), 1); } #[test] fn into_raw_and_from_raw() { let mut canary = atomic::AtomicUsize::new(0); let c = Canary(&mut canary as *mut atomic::AtomicUsize); let v = vec![5, 6]; let header = HeaderWithLength::new(c, v.len()); { type ThinArcCanary = ThinArc; let x: ThinArcCanary = Arc::into_thin(Arc::from_header_and_iter(header, v.into_iter())); let ptr = x.as_ptr(); assert_eq!(x.into_raw(), ptr); let _x = unsafe { ThinArcCanary::from_raw(ptr) }; } assert_eq!(canary.load(Acquire), 1); } #[test] fn thin_eq_and_cmp() { [ [("*", &b"AB"[..]), ("*", &b"ab"[..])], [("*", &b"AB"[..]), ("*", &b"a"[..])], [("*", &b"A"[..]), ("*", &b"ab"[..])], [("A", &b"*"[..]), ("a", &b"*"[..])], [("a", &b"*"[..]), ("A", &b"*"[..])], [("AB", &b"*"[..]), ("a", &b"*"[..])], [("A", &b"*"[..]), ("ab", &b"*"[..])], ] .iter() .for_each(|[lt @ (lh, ls), rt @ (rh, rs)]| { let l = ThinArc::from_header_and_slice(lh, ls); let r = ThinArc::from_header_and_slice(rh, rs); assert_eq!(l, l); assert_eq!(r, r); assert_ne!(l, r); assert_ne!(r, l); assert_eq!(l <= l, lt <= lt, "{lt:?} <= {lt:?}"); assert_eq!(l >= l, lt >= lt, "{lt:?} >= {lt:?}"); assert_eq!(l < l, lt < lt, "{lt:?} < {lt:?}"); assert_eq!(l > l, lt > lt, "{lt:?} > {lt:?}"); assert_eq!(r <= r, rt <= rt, "{rt:?} <= {rt:?}"); assert_eq!(r >= r, rt >= rt, "{rt:?} >= {rt:?}"); assert_eq!(r < r, rt < rt, "{rt:?} < {rt:?}"); assert_eq!(r > r, rt > rt, "{rt:?} > {rt:?}"); assert_eq!(l < r, lt < rt, "{lt:?} < {rt:?}"); assert_eq!(r > l, rt > lt, "{rt:?} > {lt:?}"); }) } #[test] fn thin_eq_and_partial_cmp() { [ [(0.0, &[0.0, 0.0][..]), (1.0, &[0.0, 0.0][..])], [(1.0, &[0.0, 0.0][..]), (0.0, &[0.0, 0.0][..])], [(0.0, &[0.0][..]), (0.0, &[0.0, 0.0][..])], [(0.0, &[0.0, 0.0][..]), (0.0, &[0.0][..])], [(0.0, &[1.0, 2.0][..]), (0.0, &[10.0, 20.0][..])], ] .iter() .for_each(|[lt @ (lh, ls), rt @ (rh, rs)]| { let l = ThinArc::from_header_and_slice(lh, ls); let r = ThinArc::from_header_and_slice(rh, rs); assert_eq!(l, l); assert_eq!(r, r); assert_ne!(l, r); assert_ne!(r, l); assert_eq!(l <= l, lt <= lt, "{lt:?} <= {lt:?}"); assert_eq!(l >= l, lt >= lt, "{lt:?} >= {lt:?}"); assert_eq!(l < l, lt < lt, "{lt:?} < {lt:?}"); assert_eq!(l > l, lt > lt, "{lt:?} > {lt:?}"); assert_eq!(r <= r, rt <= rt, "{rt:?} <= {rt:?}"); assert_eq!(r >= r, rt >= rt, "{rt:?} >= {rt:?}"); assert_eq!(r < r, rt < rt, "{rt:?} < {rt:?}"); assert_eq!(r > r, rt > rt, "{rt:?} > {rt:?}"); assert_eq!(l < r, lt < rt, "{lt:?} < {rt:?}"); assert_eq!(r > l, rt > lt, "{rt:?} > {lt:?}"); }) } #[allow(dead_code)] const fn is_partial_ord() {} #[allow(dead_code)] const fn is_ord() {} // compile-time check that PartialOrd/Ord is correctly derived const _: () = is_partial_ord::>(); const _: () = is_partial_ord::>(); const _: () = is_partial_ord::>(); const _: () = is_ord::>(); } triomphe/src/lib.rs0000644000175000017500000000516114661133735015276 0ustar jamespagejamespage// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Fork of Arc. This has the following advantages over std::sync::Arc: //! //! * `triomphe::Arc` doesn't support weak references: we save space by excluding the weak reference count, and we don't do extra read-modify-update operations to handle the possibility of weak references. //! * `triomphe::UniqueArc` allows one to construct a temporarily-mutable `Arc` which can be converted to a regular `triomphe::Arc` later //! * `triomphe::OffsetArc` can be used transparently from C++ code and is compatible with (and can be converted to/from) `triomphe::Arc` //! * `triomphe::ArcBorrow` is functionally similar to `&triomphe::Arc`, however in memory it's simply `&T`. This makes it more flexible for FFI; the source of the borrow need not be an `Arc` pinned on the stack (and can instead be a pointer from C++, or an `OffsetArc`). Additionally, this helps avoid pointer-chasing. //! * `triomphe::Arc` has can be constructed for dynamically-sized types via `from_header_and_iter` //! * `triomphe::ThinArc` provides thin-pointer `Arc`s to dynamically sized types //! * `triomphe::ArcUnion` is union of two `triomphe:Arc`s which fits inside one word of memory #![allow(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; #[cfg(feature = "std")] extern crate core; #[cfg(feature = "arc-swap")] extern crate arc_swap; #[cfg(feature = "serde")] extern crate serde; #[cfg(feature = "stable_deref_trait")] extern crate stable_deref_trait; #[cfg(feature = "unsize")] extern crate unsize; mod arc; mod arc_borrow; #[cfg(feature = "arc-swap")] mod arc_swap_support; mod arc_union; mod header; mod iterator_as_exact_size_iterator; mod offset_arc; mod thin_arc; mod unique_arc; pub use arc::*; pub use arc_borrow::*; pub use arc_union::*; pub use header::*; pub use offset_arc::*; pub use thin_arc::*; pub use unique_arc::*; #[cfg(feature = "std")] use std::process::abort; // `no_std`-compatible abort by forcing a panic while already panicking. #[cfg(not(feature = "std"))] #[cold] fn abort() -> ! { struct PanicOnDrop; impl Drop for PanicOnDrop { fn drop(&mut self) { panic!() } } let _double_panicer = PanicOnDrop; panic!(); } triomphe/src/unique_arc.rs0000644000175000017500000002150214661133735016660 0ustar jamespagejamespageuse alloc::vec::Vec; use alloc::{alloc::Layout, boxed::Box}; use core::convert::TryFrom; use core::iter::FromIterator; use core::marker::PhantomData; use core::mem::{ManuallyDrop, MaybeUninit}; use core::ops::{Deref, DerefMut}; use core::ptr::{self, NonNull}; use core::sync::atomic::AtomicUsize; use crate::iterator_as_exact_size_iterator::IteratorAsExactSizeIterator; use crate::HeaderSlice; use super::{Arc, ArcInner}; /// An `Arc` that is known to be uniquely owned /// /// When `Arc`s are constructed, they are known to be /// uniquely owned. In such a case it is safe to mutate /// the contents of the `Arc`. Normally, one would just handle /// this by mutating the data on the stack before allocating the /// `Arc`, however it's possible the data is large or unsized /// and you need to heap-allocate it earlier in such a way /// that it can be freely converted into a regular `Arc` once you're /// done. /// /// `UniqueArc` exists for this purpose, when constructed it performs /// the same allocations necessary for an `Arc`, however it allows mutable access. /// Once the mutation is finished, you can call `.shareable()` and get a regular `Arc` /// out of it. /// /// ```rust /// # use triomphe::UniqueArc; /// let data = [1, 2, 3, 4, 5]; /// let mut x = UniqueArc::new(data); /// x[4] = 7; // mutate! /// let y = x.shareable(); // y is an Arc /// ``` #[repr(transparent)] pub struct UniqueArc(Arc); // Uniquene ownership means that we can support weaker bounds than `T: Send + Sync`. // Thus, these impls can follow the precedent of std's `Box`, not `Arc`. unsafe impl Send for UniqueArc {} unsafe impl Sync for UniqueArc {} impl UniqueArc { #[inline] /// Construct a new UniqueArc pub fn new(data: T) -> Self { UniqueArc(Arc::new(data)) } /// Construct an uninitialized arc #[inline] pub fn new_uninit() -> UniqueArc> { unsafe { let layout = Layout::new::>>(); let ptr = alloc::alloc::alloc(layout); let mut p = NonNull::new(ptr) .unwrap_or_else(|| alloc::alloc::handle_alloc_error(layout)) .cast::>>(); ptr::write(&mut p.as_mut().count, AtomicUsize::new(1)); UniqueArc(Arc { p, phantom: PhantomData, }) } } /// Gets the inner value of the unique arc pub fn into_inner(this: Self) -> T { // Wrap the Arc in a `ManuallyDrop` so that its drop routine never runs let this = ManuallyDrop::new(this.0); debug_assert!( this.is_unique(), "attempted to call `.into_inner()` on a `UniqueArc` with a non-zero ref count", ); // Safety: We have exclusive access to the inner data and the // arc will not perform its drop routine since we've // wrapped it in a `ManuallyDrop` unsafe { Box::from_raw(this.ptr()).data } } } impl UniqueArc { /// Convert to a shareable `Arc` once we're done mutating it #[inline] pub fn shareable(self) -> Arc { self.0 } /// Creates a new [`UniqueArc`] from the given [`Arc`]. /// /// An unchecked alternative to `Arc::try_unique()` /// /// # Safety /// /// The given `Arc` must have a reference count of exactly one /// pub(crate) unsafe fn from_arc(arc: Arc) -> Self { debug_assert_eq!(Arc::count(&arc), 1); Self(arc) } /// Creates a new `&mut `[`UniqueArc`] from the given `&mut `[`Arc`]. /// /// An unchecked alternative to `Arc::try_as_unique()` /// /// # Safety /// /// The given `Arc` must have a reference count of exactly one pub(crate) unsafe fn from_arc_ref(arc: &mut Arc) -> &mut Self { debug_assert_eq!(Arc::count(arc), 1); // Safety: caller guarantees that `arc` is unique, // `UniqueArc` is `repr(transparent)` &mut *(arc as *mut Arc as *mut UniqueArc) } } impl UniqueArc> { /// Calls `MaybeUninit::write` on the contained value. pub fn write(&mut self, val: T) -> &mut T { unsafe { // Casting *mut MaybeUninit -> *mut T is always fine let ptr = self.as_mut_ptr() as *mut T; // Safety: We have exclusive access to the inner data ptr.write(val); // Safety: the pointer was just written to &mut *ptr } } /// Obtain a mutable pointer to the stored `MaybeUninit`. pub fn as_mut_ptr(&mut self) -> *mut MaybeUninit { unsafe { &mut (*self.0.ptr()).data } } /// Convert to an initialized Arc. /// /// # Safety /// /// This function is equivalent to `MaybeUninit::assume_init` and has the /// same safety requirements. You are responsible for ensuring that the `T` /// has actually been initialized before calling this method. #[inline] pub unsafe fn assume_init(this: Self) -> UniqueArc { UniqueArc(Arc { p: ManuallyDrop::new(this).0.p.cast(), phantom: PhantomData, }) } } impl UniqueArc<[MaybeUninit]> { /// Create an Arc contains an array `[MaybeUninit]` of `len`. pub fn new_uninit_slice(len: usize) -> Self { let ptr: NonNull]>>> = Arc::allocate_for_header_and_slice(len); // Safety: // - `ArcInner` is properly allocated and initialized. // - `()` and `[MaybeUninit]` do not require special initialization // - The `Arc` is just created and so -- unique. unsafe { let arc: Arc]>> = Arc::from_raw_inner(ptr.as_ptr()); let arc: Arc<[MaybeUninit]> = arc.into(); UniqueArc(arc) } } /// # Safety /// /// Must initialize all fields before calling this function. #[inline] pub unsafe fn assume_init_slice(Self(this): Self) -> UniqueArc<[T]> { UniqueArc(this.assume_init()) } } impl TryFrom> for UniqueArc { type Error = Arc; fn try_from(arc: Arc) -> Result { Arc::try_unique(arc) } } impl Deref for UniqueArc { type Target = T; #[inline] fn deref(&self) -> &T { &self.0 } } impl DerefMut for UniqueArc { #[inline] fn deref_mut(&mut self) -> &mut T { // We know this to be uniquely owned unsafe { &mut (*self.0.ptr()).data } } } impl FromIterator for UniqueArc<[A]> { fn from_iter>(iter: T) -> Self { let iter = iter.into_iter(); let (lower, upper) = iter.size_hint(); let arc: Arc<[A]> = if Some(lower) == upper { let iter = IteratorAsExactSizeIterator::new(iter); Arc::from_header_and_iter((), iter).into() } else { let vec = iter.collect::>(); Arc::from(vec) }; // Safety: We just created an `Arc`, so it's unique. unsafe { UniqueArc::from_arc(arc) } } } // Safety: // This leverages the correctness of Arc's CoerciblePtr impl. Additionally, we must ensure that // this can not be used to violate the safety invariants of UniqueArc, which require that we can not // duplicate the Arc, such that replace_ptr returns a valid instance. This holds since it consumes // a unique owner of the contained ArcInner. #[cfg(feature = "unsize")] unsafe impl unsize::CoerciblePtr for UniqueArc { type Pointee = T; type Output = UniqueArc; fn as_sized_ptr(&mut self) -> *mut T { // Dispatch to the contained field. unsize::CoerciblePtr::::as_sized_ptr(&mut self.0) } unsafe fn replace_ptr(self, new: *mut U) -> UniqueArc { // Dispatch to the contained field, work around conflict of destructuring and Drop. let inner = ManuallyDrop::new(self); UniqueArc(ptr::read(&inner.0).replace_ptr(new)) } } #[cfg(test)] mod tests { use crate::{Arc, UniqueArc}; use core::{convert::TryFrom, mem::MaybeUninit}; #[test] fn unique_into_inner() { let unique = UniqueArc::new(10u64); assert_eq!(UniqueArc::into_inner(unique), 10); } #[test] fn try_from_arc() { let x = Arc::new(10_000); let y = x.clone(); assert!(UniqueArc::try_from(x).is_err()); assert_eq!( UniqueArc::into_inner(UniqueArc::try_from(y).unwrap()), 10_000, ); } #[test] #[allow(deprecated)] fn maybeuninit_smoke() { let mut arc: UniqueArc> = UniqueArc::new_uninit(); arc.write(999); let arc = unsafe { UniqueArc::assume_init(arc) }; assert_eq!(*arc, 999); } } triomphe/src/iterator_as_exact_size_iterator.rs0000644000175000017500000000240114661133735023165 0ustar jamespagejamespage/// Wrap an iterator and implement `ExactSizeIterator` /// assuming the underlying iterator reports lower bound equal to upper bound. /// /// It does not check the size is reported correctly (except in debug mode). pub(crate) struct IteratorAsExactSizeIterator { iter: I, } impl IteratorAsExactSizeIterator { #[inline] pub(crate) fn new(iter: I) -> Self { let (lower, upper) = iter.size_hint(); debug_assert_eq!( Some(lower), upper, "IteratorAsExactSizeIterator requires size hint lower == upper" ); IteratorAsExactSizeIterator { iter } } } impl Iterator for IteratorAsExactSizeIterator { type Item = I::Item; #[inline] fn next(&mut self) -> Option { self.iter.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl ExactSizeIterator for IteratorAsExactSizeIterator { #[inline] fn len(&self) -> usize { let (lower, upper) = self.iter.size_hint(); debug_assert_eq!( Some(lower), upper, "IteratorAsExactSizeIterator requires size hint lower == upper" ); lower } } triomphe/src/arc_swap_support.rs0000644000175000017500000000150214661133735020116 0ustar jamespagejamespageuse arc_swap::RefCnt; use crate::{Arc, ThinArc}; use core::ffi::c_void; unsafe impl RefCnt for ThinArc { type Base = c_void; #[inline] fn into_ptr(me: Self) -> *mut Self::Base { ThinArc::into_raw(me) as *mut _ } #[inline] fn as_ptr(me: &Self) -> *mut Self::Base { ThinArc::as_ptr(me) as *mut _ } #[inline] unsafe fn from_ptr(ptr: *const Self::Base) -> Self { ThinArc::from_raw(ptr) } } unsafe impl RefCnt for Arc { type Base = T; #[inline] fn into_ptr(me: Self) -> *mut Self::Base { Arc::into_raw(me) as *mut _ } #[inline] fn as_ptr(me: &Self) -> *mut Self::Base { Arc::as_ptr(me) as *mut _ } #[inline] unsafe fn from_ptr(ptr: *const Self::Base) -> Self { Arc::from_raw(ptr) } } triomphe/.cargo-checksum.json0000664000175000017500000000241014661133735017233 0ustar jamespagejamespage{"files":{"Cargo.toml":"09db6f8eb02b05f55d181286808a11b742d1d4e082fb5a6de1554aed94db76b5","LICENSE-APACHE":"a6b7260485462860838b76ad1846d21f1605e6d239141c3aa949a601d992676c","LICENSE-MIT":"15656cc11a8331f28c0986b8ab97220d3e76f98e60ed388b5ffad37dfac4710c","README.md":"31f2d36aba753938cca35a0770f87b14215d6b367a1cd173f183d49242890258","src/arc.rs":"bc5eebc07e27fcacd5d33164d6293c7cc85f601d41bcec166be4970f1f2d8e50","src/arc_borrow.rs":"0e6b0b6cdf6483d123c72a92a2e84e604a5145fbcac804dc8266e6c1e2d2f6c9","src/arc_swap_support.rs":"54213ddea959fec13f1af4efb94271a9b85c531c06649899ddf8d6b939615d05","src/arc_union.rs":"2aa3a7bbf0d28664615f23a24625094633543698a514cf5214bdae1d828fae23","src/header.rs":"75e84b35a127032c00718a613c4953fbceeb46cd8400605d6c0e2a721591ae37","src/iterator_as_exact_size_iterator.rs":"cae199c33fb172eb63455c0290a70ac72a7a9f6d26cf30d691560470b08524a4","src/lib.rs":"43bdf46d4b2db2821d469312d8188e187b1c098e5069327deb5e87f0ec49dbf5","src/offset_arc.rs":"69b7104aad5b9a132f2554573adc6ac1e6cc150c172553487054b7bbe4474cab","src/thin_arc.rs":"96e44edd0f0a84f0f132af4086c4f1f9ffd3a3d420d39296c0622a8f8edea415","src/unique_arc.rs":"5a48934a5ab1d9611c0ef5ac5621bed892a1ab1ccdb87511059d179b7f1d61e2"},"package":"e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369"}unicode-ident/0000775000175000017500000000000014661133735014272 5ustar jamespagejamespageunicode-ident/README.md0000644000175000017500000003032214661133735015547 0ustar jamespagejamespageUnicode ident ============= [github](https://github.com/dtolnay/unicode-ident) [crates.io](https://crates.io/crates/unicode-ident) [docs.rs](https://docs.rs/unicode-ident) [build status](https://github.com/dtolnay/unicode-ident/actions?query=branch%3Amaster) Implementation of [Unicode Standard Annex #31][tr31] for determining which `char` values are valid in programming language identifiers. [tr31]: https://www.unicode.org/reports/tr31/ This crate is a better optimized implementation of the older `unicode-xid` crate. This crate uses less static storage, and is able to classify both ASCII and non-ASCII codepoints with better performance, 2–10× faster than `unicode-xid`.
## Comparison of performance The following table shows a comparison between five Unicode identifier implementations. - `unicode-ident` is this crate; - [`unicode-xid`] is a widely used crate run by the "unicode-rs" org; - `ucd-trie` and `fst` are two data structures supported by the [`ucd-generate`] tool; - [`roaring`] is a Rust implementation of Roaring bitmap. The *static storage* column shows the total size of `static` tables that the crate bakes into your binary, measured in 1000s of bytes. The remaining columns show the **cost per call** to evaluate whether a single `char` has the XID\_Start or XID\_Continue Unicode property, comparing across different ratios of ASCII to non-ASCII codepoints in the input data. [`unicode-xid`]: https://github.com/unicode-rs/unicode-xid [`ucd-generate`]: https://github.com/BurntSushi/ucd-generate [`roaring`]: https://github.com/RoaringBitmap/roaring-rs | | static storage | 0% nonascii | 1% | 10% | 100% nonascii | |---|---|---|---|---|---| | **`unicode-ident`** | 10.1 K | 0.96 ns | 0.95 ns | 1.09 ns | 1.55 ns | | **`unicode-xid`** | 11.5 K | 1.88 ns | 2.14 ns | 3.48 ns | 15.63 ns | | **`ucd-trie`** | 10.2 K | 1.29 ns | 1.28 ns | 1.36 ns | 2.15 ns | | **`fst`** | 139 K | 55.1 ns | 54.9 ns | 53.2 ns | 28.5 ns | | **`roaring`** | 66.1 K | 2.78 ns | 3.09 ns | 3.37 ns | 4.70 ns | Source code for the benchmark is provided in the *bench* directory of this repo and may be repeated by running `cargo criterion`.
## Comparison of data structures #### unicode-xid They use a sorted array of character ranges, and do a binary search to look up whether a given character lands inside one of those ranges. ```rust static XID_Continue_table: [(char, char); 763] = [ ('\u{30}', '\u{39}'), // 0-9 ('\u{41}', '\u{5a}'), // A-Z … ('\u{e0100}', '\u{e01ef}'), ]; ``` The static storage used by this data structure scales with the number of contiguous ranges of identifier codepoints in Unicode. Every table entry consumes 8 bytes, because it consists of a pair of 32-bit `char` values. In some ranges of the Unicode codepoint space, this is quite a sparse representation – there are some ranges where tens of thousands of adjacent codepoints are all valid identifier characters. In other places, the representation is quite inefficient. A characater like `µ` (U+00B5) which is surrounded by non-identifier codepoints consumes 64 bits in the table, while it would be just 1 bit in a dense bitmap. On a system with 64-byte cache lines, binary searching the table touches 7 cache lines on average. Each cache line fits only 8 table entries. Additionally, the branching performed during the binary search is probably mostly unpredictable to the branch predictor. Overall, the crate ends up being about 10× slower on non-ASCII input compared to the fastest crate. A potential improvement would be to pack the table entries more compactly. Rust's `char` type is a 21-bit integer padded to 32 bits, which means every table entry is holding 22 bits of wasted space, adding up to 3.9 K. They could instead fit every table entry into 6 bytes, leaving out some of the padding, for a 25% improvement in space used. With some cleverness it may be possible to fit in 5 bytes or even 4 bytes by storing a low char and an extent, instead of low char and high char. I don't expect that performance would improve much but this could be the most efficient for space across all the libraries, needing only about 7 K to store. #### ucd-trie Their data structure is a compressed trie set specifically tailored for Unicode codepoints. The design is credited to Raph Levien in [rust-lang/rust#33098]. [rust-lang/rust#33098]: https://github.com/rust-lang/rust/pull/33098 ```rust pub struct TrieSet { tree1_level1: &'static [u64; 32], tree2_level1: &'static [u8; 992], tree2_level2: &'static [u64], tree3_level1: &'static [u8; 256], tree3_level2: &'static [u8], tree3_level3: &'static [u64], } ``` It represents codepoint sets using a trie to achieve prefix compression. The final states of the trie are embedded in leaves or "chunks", where each chunk is a 64-bit integer. Each bit position of the integer corresponds to whether a particular codepoint is in the set or not. These chunks are not just a compact representation of the final states of the trie, but are also a form of suffix compression. In particular, if multiple ranges of 64 contiguous codepoints have the same Unicode properties, then they all map to the same chunk in the final level of the trie. Being tailored for Unicode codepoints, this trie is partitioned into three disjoint sets: tree1, tree2, tree3. The first set corresponds to codepoints \[0, 0x800), the second \[0x800, 0x10000) and the third \[0x10000, 0x110000). These partitions conveniently correspond to the space of 1 or 2 byte UTF-8 encoded codepoints, 3 byte UTF-8 encoded codepoints and 4 byte UTF-8 encoded codepoints, respectively. Lookups in this data structure are significantly more efficient than binary search. A lookup touches either 1, 2, or 3 cache lines based on which of the trie partitions is being accessed. One possible performance improvement would be for this crate to expose a way to query based on a UTF-8 encoded string, returning the Unicode property corresponding to the first character in the string. Without such an API, the caller is required to tokenize their UTF-8 encoded input data into `char`, hand the `char` into `ucd-trie`, only for `ucd-trie` to undo that work by converting back into the variable-length representation for trie traversal. #### fst Uses a [finite state transducer][fst]. This representation is built into [ucd-generate] but I am not aware of any advantage over the `ucd-trie` representation. In particular `ucd-trie` is optimized for storing Unicode properties while `fst` is not. [fst]: https://github.com/BurntSushi/fst [ucd-generate]: https://github.com/BurntSushi/ucd-generate As far as I can tell, the main thing that causes `fst` to have large size and slow lookups for this use case relative to `ucd-trie` is that it does not specialize for the fact that only 21 of the 32 bits in a `char` are meaningful. There are some dense arrays in the structure with large ranges that could never possibly be used. #### roaring This crate is a pure-Rust implementation of [Roaring Bitmap], a data structure designed for storing sets of 32-bit unsigned integers. [Roaring Bitmap]: https://roaringbitmap.org/about/ Roaring bitmaps are compressed bitmaps which tend to outperform conventional compressed bitmaps such as WAH, EWAH or Concise. In some instances, they can be hundreds of times faster and they often offer significantly better compression. In this use case the performance was reasonably competitive but still substantially slower than the Unicode-optimized crates. Meanwhile the compression was significantly worse, requiring 6× as much storage for the data structure. I also benchmarked the [`croaring`] crate which is an FFI wrapper around the C reference implementation of Roaring Bitmap. This crate was consistently about 15% slower than pure-Rust `roaring`, which could just be FFI overhead. I did not investigate further. [`croaring`]: https://crates.io/crates/croaring #### unicode-ident This crate is most similar to the `ucd-trie` library, in that it's based on bitmaps stored in the leafs of a trie representation, achieving both prefix compression and suffix compression. The key differences are: - Uses a single 2-level trie, rather than 3 disjoint partitions of different depth each. - Uses significantly larger chunks: 512 bits rather than 64 bits. - Compresses the XID\_Start and XID\_Continue properties together simultaneously, rather than duplicating identical trie leaf chunks across the two. The following diagram show the XID\_Start and XID\_Continue Unicode boolean properties in uncompressed form, in row-major order:
XID_StartXID_Continue
XID_Start bitmap XID_Continue bitmap
Uncompressed, these would take 140 K to store, which is beyond what would be reasonable. However, as you can see there is a large degree of similarity between the two bitmaps and across the rows, which lends well to compression. This crate stores one 512-bit "row" of the above bitmaps in the leaf level of a trie, and a single additional level to index into the leafs. It turns out there are 124 unique 512-bit chunks across the two bitmaps so 7 bits are sufficient to index them. The chunk size of 512 bits is selected as the size that minimizes the total size of the data structure. A smaller chunk, like 256 or 128 bits, would achieve better deduplication but require a larger index. A larger chunk would increase redundancy in the leaf bitmaps. 512 bit chunks are the optimum for total size of the index plus leaf bitmaps. In fact since there are only 124 unique chunks, we can use an 8-bit index with a spare bit to index at the half-chunk level. This achieves an additional 8.5% compression by eliminating redundancies between the second half of any chunk and the first half of any other chunk. Note that this is not the same as using chunks which are half the size, because it does not necessitate raising the size of the trie's first level. In contrast to binary search or the `ucd-trie` crate, performing lookups in this data structure is straight-line code with no need for branching. ```asm is_xid_start: mov eax, edi shr eax, 9 lea rcx, [rip + unicode_ident::tables::TRIE_START] add rcx, rax xor eax, eax cmp edi, 201728 cmovb rax, rcx test rax, rax lea rcx, [rip + .L__unnamed_1] cmovne rcx, rax movzx eax, byte ptr [rcx] shl rax, 5 mov ecx, edi shr ecx, 3 and ecx, 63 add rcx, rax lea rax, [rip + unicode_ident::tables::LEAF] mov al, byte ptr [rax + rcx] and dil, 7 mov ecx, edi shr al, cl and al, 1 ret ```
## License Use of the Unicode Character Database, as this crate does, is governed by the
Unicode License Agreement – Data Files and Software (2016). All intellectual property within this crate that is **not generated** using the Unicode Character Database as input is licensed under either of Apache License, Version 2.0 or MIT license at your option. The **generated** files incorporate tabular data derived from the Unicode Character Database, together with intellectual property from the original source code content of the crate. One must comply with the terms of both the Unicode License Agreement and either of the Apache license or MIT license when those generated files are involved. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be licensed as just described, without any additional terms or conditions. unicode-ident/LICENSE-APACHE0000644000175000017500000002277314661133735016227 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS unicode-ident/LICENSE-UNICODE0000644000175000017500000000441314661133735016363 0ustar jamespagejamespageUNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE See Terms of Use for definitions of Unicode Inc.’s Data Files and Software. NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. COPYRIGHT AND PERMISSION NOTICE Copyright © 1991-2022 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in https://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided that either (a) this copyright and permission notice appear with all copies of the Data Files or Software, or (b) this copyright and permission notice appear in associated Documentation. THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder. unicode-ident/Cargo.toml0000644000175000017500000000307214661133735016222 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" rust-version = "1.31" name = "unicode-ident" version = "1.0.12" authors = ["David Tolnay "] description = "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31" documentation = "https://docs.rs/unicode-ident" readme = "README.md" keywords = [ "unicode", "xid", ] categories = [ "development-tools::procedural-macro-helpers", "no-std", "no-std::no-alloc", ] license = "(MIT OR Apache-2.0) AND Unicode-DFS-2016" repository = "https://github.com/dtolnay/unicode-ident" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [lib] doc-scrape-examples = false [[bench]] name = "xid" harness = false [dev-dependencies.criterion] version = "0.5" default-features = false [dev-dependencies.fst] version = "0.4" [dev-dependencies.rand] version = "0.8" features = ["small_rng"] [dev-dependencies.roaring] version = "0.10" [dev-dependencies.ucd-trie] version = "0.1" default-features = false [dev-dependencies.unicode-xid] version = "0.2.4" unicode-ident/benches/0000775000175000017500000000000014661133735015701 5ustar jamespagejamespageunicode-ident/benches/xid.rs0000644000175000017500000000766414661133735017046 0ustar jamespagejamespage// To run: // // cargo criterion --features criterion/real_blackbox // // This benchmarks each of the different libraries at several ratios of ASCII to // non-ASCII content. There is one additional benchmark labeled "baseline" which // just iterates over characters in a string, converting UTF-8 to 32-bit chars. // // Criterion will show a time in milliseconds. The non-baseline bench functions // each make one million function calls (2 calls per character, 500K characters // in the strings created by gen_string). The "time per call" listed in our // readme is computed by subtracting this baseline from the other bench // functions' time, then dividing by one million (ms -> ns). #![allow(clippy::needless_pass_by_value)] #[path = "../tests/fst/mod.rs"] mod fst; #[path = "../tests/roaring/mod.rs"] mod roaring; #[path = "../tests/trie/mod.rs"] mod trie; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use rand::distributions::{Bernoulli, Distribution, Uniform}; use rand::rngs::SmallRng; use rand::SeedableRng; use std::time::Duration; fn gen_string(p_nonascii: u32) -> String { let mut rng = SmallRng::from_seed([b'!'; 32]); let pick_nonascii = Bernoulli::from_ratio(p_nonascii, 100).unwrap(); let ascii = Uniform::new_inclusive('\0', '\x7f'); let nonascii = Uniform::new_inclusive(0x80 as char, char::MAX); let mut string = String::new(); for _ in 0..500_000 { let distribution = if pick_nonascii.sample(&mut rng) { nonascii } else { ascii }; string.push(distribution.sample(&mut rng)); } string } fn bench(c: &mut Criterion, group_name: &str, string: String) { let mut group = c.benchmark_group(group_name); group.measurement_time(Duration::from_secs(10)); group.bench_function("baseline", |b| { b.iter(|| { for ch in string.chars() { black_box(ch); } }); }); group.bench_function("unicode-ident", |b| { b.iter(|| { for ch in string.chars() { black_box(unicode_ident::is_xid_start(ch)); black_box(unicode_ident::is_xid_continue(ch)); } }); }); group.bench_function("unicode-xid", |b| { b.iter(|| { for ch in string.chars() { black_box(unicode_xid::UnicodeXID::is_xid_start(ch)); black_box(unicode_xid::UnicodeXID::is_xid_continue(ch)); } }); }); group.bench_function("ucd-trie", |b| { b.iter(|| { for ch in string.chars() { black_box(trie::XID_START.contains_char(ch)); black_box(trie::XID_CONTINUE.contains_char(ch)); } }); }); group.bench_function("fst", |b| { let xid_start_fst = fst::xid_start_fst(); let xid_continue_fst = fst::xid_continue_fst(); b.iter(|| { for ch in string.chars() { let ch_bytes = (ch as u32).to_be_bytes(); black_box(xid_start_fst.contains(ch_bytes)); black_box(xid_continue_fst.contains(ch_bytes)); } }); }); group.bench_function("roaring", |b| { let xid_start_bitmap = roaring::xid_start_bitmap(); let xid_continue_bitmap = roaring::xid_continue_bitmap(); b.iter(|| { for ch in string.chars() { black_box(xid_start_bitmap.contains(ch as u32)); black_box(xid_continue_bitmap.contains(ch as u32)); } }); }); group.finish(); } fn bench0(c: &mut Criterion) { bench(c, "0%-nonascii", gen_string(0)); } fn bench1(c: &mut Criterion) { bench(c, "1%-nonascii", gen_string(1)); } fn bench10(c: &mut Criterion) { bench(c, "10%-nonascii", gen_string(10)); } fn bench100(c: &mut Criterion) { bench(c, "100%-nonascii", gen_string(100)); } criterion_group!(benches, bench0, bench1, bench10, bench100); criterion_main!(benches); unicode-ident/tests/0000775000175000017500000000000014661133735015434 5ustar jamespagejamespageunicode-ident/tests/trie/0000775000175000017500000000000014661133735016377 5ustar jamespagejamespageunicode-ident/tests/trie/mod.rs0000644000175000017500000000026314661133735017523 0ustar jamespagejamespage#![allow(clippy::module_inception)] #[allow(dead_code, clippy::redundant_static_lifetimes, clippy::unreadable_literal)] #[rustfmt::skip] mod trie; pub(crate) use self::trie::*; unicode-ident/tests/trie/trie.rs0000644000175000017500000007310614661133735017715 0ustar jamespagejamespage// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY: // // ucd-generate property-bool UCD --include XID_Start,XID_Continue --trie-set // // Unicode version: 15.1.0. // // ucd-generate 0.3.0 is available on crates.io. pub const BY_NAME: &'static [(&'static str, &'static ::ucd_trie::TrieSet)] = &[ ("XID_Continue", XID_CONTINUE), ("XID_Start", XID_START), ]; pub const XID_CONTINUE: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet { tree1_level1: &[ 0x3FF000000000000, 0x7FFFFFE87FFFFFE, 0x4A0040000000000, 0xFF7FFFFFFF7FFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x501F0003FFC3, 0xFFFFFFFFFFFFFFFF, 0xB8DFFFFFFFFFFFFF, 0xFFFFFFFBFFFFD7C0, 0xFFBFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFCFB, 0xFFFFFFFFFFFFFFFF, 0xFFFEFFFFFFFFFFFF, 0xFFFFFFFF027FFFFF, 0xBFFFFFFFFFFE01FF, 0x787FFFFFF00B6, 0xFFFFFFFF07FF0000, 0xFFFFC3FFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x9FFFFDFF9FEFFFFF, 0xFFFFFFFFFFFF0000, 0xFFFFFFFFFFFFE7FF, 0x3FFFFFFFFFFFF, 0x243FFFFFFFFFFFFF, ], tree2_level1: &[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 4, 32, 33, 34, 4, 4, 4, 4, 4, 35, 36, 37, 38, 39, 40, 41, 42, 4, 4, 4, 4, 4, 4, 4, 4, 43, 44, 45, 46, 47, 4, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 4, 61, 4, 62, 63, 64, 65, 66, 4, 4, 4, 4, 4, 4, 4, 4, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 4, 4, 4, 79, 80, 81, 82, 83, 78, 78, 78, 78, 78, 78, 78, 78, 84, 42, 85, 4, 86, 4, 87, 88, 78, 78, 78, 78, 78, 78, 78, 78, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 78, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 89, 90, 4, 4, 4, 4, 91, 92, 4, 93, 94, 4, 95, 96, 97, 62, 4, 98, 99, 100, 4, 101, 102, 103, 4, 104, 105, 106, 4, 107, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 108, 109, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 4, 4, 4, 4, 4, 99, 4, 110, 111, 112, 93, 113, 4, 114, 4, 4, 115, 116, 117, 118, 119, 120, 4, 121, 122, 123, 124, 125, ], tree2_level2: &[ 0x3FFFFFFFFFFF, 0xFFFF07FF0FFFFFFF, 0xFFFFFFFFFF007EFF, 0xFFFFFFFBFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFEFFCFFFFFFFFF, 0xF3C5FDFFFFF99FEF, 0x5003FFCFB080799F, 0xD36DFDFFFFF987EE, 0x3FFFC05E023987, 0xF3EDFDFFFFFBBFEE, 0xFE00FFCF00013BBF, 0xF3EDFDFFFFF99FEE, 0x2FFCFB0E0399F, 0xC3FFC718D63DC7EC, 0xFFC000813DC7, 0xF3FFFDFFFFFDDFFF, 0xFFCF27603DDF, 0xF3EFFDFFFFFDDFEF, 0xEFFCF60603DDF, 0xFFFFFFFFFFFDDFFF, 0xFC00FFCF80F07DDF, 0x2FFBFFFFFC7FFFEE, 0xCFFC0FF5F847F, 0x7FFFFFFFFFFFFFE, 0x3FF7FFF, 0x3FFFFFAFFFFFF7D6, 0xF3FF7F5F, 0xC2A003FF03000001, 0xFFFE1FFFFFFFFEFF, 0x1FFFFFFFFEFFFFDF, 0x40, 0xFFFFFFFFFFFF03FF, 0xFFFFFFFF3FFFFFFF, 0xF7FFFFFFFFFF20BF, 0xFFFFFFFF3D7F3DFF, 0x7F3DFFFFFFFF3DFF, 0xFFFFFFFFFF7FFF3D, 0xFFFFFFFFFF3DFFFF, 0x3FE00E7FFFFFF, 0xFFFFFFFF0000FFFF, 0x3F3FFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE, 0xFFFF9FFFFFFFFFFF, 0xFFFFFFFF07FFFFFE, 0x1FFC7FFFFFFFFFF, 0x1FFFFF803FFFFF, 0xDDFFF000FFFFF, 0x3FF308FFFFF, 0xFFFFFFFF03FFB800, 0x1FFFFFFFFFFFFFF, 0xFFFF07FFFFFFFFFF, 0x3FFFFFFFFFFFFF, 0xFFF0FFF7FFFFFFF, 0x1F3FFFFFFFFFC0, 0xFFFF0FFFFFFFFFFF, 0x7FF03FF, 0xFFFFFFFF0FFFFFFF, 0x9FFFFFFF7FFFFFFF, 0xBFFF008003FF03FF, 0x7FFF, 0xFF80003FF1FFF, 0xFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFE3FF, 0xE7FFFFFFFFFF01FF, 0x7FFFFFFFFF70000, 0xFFFFFFFF3F3FFFFF, 0x3FFFFFFFAAFF3F3F, 0x5FDFFFFFFFFFFFFF, 0x1FDC1FFF0FCF1FDC, 0x8000000000003000, 0x8002000000100001, 0x1FFF0000, 0x1FFE21FFF0000, 0xF3FFFD503F2FFC84, 0xFFFFFFFF000043E0, 0x1FF, 0, 0xFF81FFFFFFFFF, 0xFFFF20BFFFFFFFFF, 0x800080FFFFFFFFFF, 0x7F7F7F7F007FFFFF, 0xFFFFFFFF7F7F7F7F, 0x1F3EFFFE000000E0, 0xFFFFFFFEE67FFFFF, 0xFFFEFFFFFFFFFFE0, 0xFFFFFFFF00007FFF, 0xFFFF000000000000, 0x1FFF, 0x3FFFFFFFFFFF0000, 0xFFFFFFF1FFF, 0xBFF0FFFFFFFFFFFF, 0x3FFFFFFFFFFFF, 0xFFFFFFFCFF800000, 0xFFFFFFFFFFFFF9FF, 0xFFFC000003EB07FF, 0x10FFFFFFFFFF, 0xE8FFFFFF03FF003F, 0xFFFF3FFFFFFFFFFF, 0x1FFFFFFF000FFFFF, 0x7FFFFFFF03FF8001, 0x7FFFFFFFFFFFFF, 0xFC7FFFFF03FF3FFF, 0x7CFFFF38000007, 0xFFFF7F7F007E7E7E, 0xFFFF03FFF7FFFFFF, 0x3FF37FFFFFFFFFF, 0xFFFF000FFFFFFFFF, 0xFFFFFFFFFFFF87F, 0x3FFFFFF, 0x5F7FFDFFE0F8007F, 0xFFFFFFFFFFFFFFDB, 0xFFFFFFFFFFF80000, 0xFFFFFFF03FFFFFFF, 0x3FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFF0000, 0xFFFFFFFFFFFCFFFF, 0x3FF0000000000FF, 0x18FFFF0000FFFF, 0xAA8A00000000E000, 0x1FFFFFFFFFFFFFFF, 0x87FFFFFE03FF0000, 0xFFFFFFE007FFFFFE, 0x7FFFFFFFFFFFFFFF, 0x1CFCFCFC, ], tree3_level1: &[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 9, 10, 11, 12, 13, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 16, 17, 7, 18, 19, 7, 20, 21, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, ], tree3_level2: &[ 0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 17, 4, 2, 2, 2, 2, 18, 19, 20, 4, 21, 22, 23, 24, 25, 4, 26, 4, 27, 28, 29, 30, 31, 32, 33, 4, 2, 34, 35, 35, 36, 4, 4, 4, 4, 4, 37, 38, 39, 40, 41, 42, 2, 43, 3, 44, 45, 46, 2, 47, 48, 49, 50, 51, 52, 53, 4, 4, 2, 54, 2, 55, 4, 4, 56, 57, 2, 58, 59, 60, 61, 62, 4, 4, 3, 4, 63, 64, 65, 66, 67, 68, 69, 70, 71, 59, 4, 4, 4, 4, 72, 73, 74, 4, 75, 76, 77, 4, 4, 4, 4, 78, 79, 80, 81, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 82, 4, 2, 83, 2, 2, 2, 84, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 85, 86, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 87, 88, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 59, 89, 69, 90, 18, 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 2, 93, 94, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 34, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 97, 2, 2, 2, 2, 98, 99, 2, 2, 2, 2, 2, 100, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 101, 102, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 103, 62, 4, 4, 4, 4, 4, 4, 4, 104, 105, 4, 4, 106, 4, 4, 4, 4, 4, 4, 2, 107, 108, 109, 110, 111, 2, 2, 2, 2, 112, 113, 114, 115, 116, 117, 4, 4, 4, 4, 4, 4, 4, 4, 118, 119, 120, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 121, 4, 4, 4, 122, 123, 124, 4, 125, 126, 4, 4, 4, 4, 127, 128, 4, 4, 4, 4, 4, 4, 4, 129, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 130, 2, 2, 2, 131, 2, 132, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 133, 134, 135, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 136, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 137, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 138, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 139, 2, 2, 2, 2, 2, 2, 2, 2, 2, 140, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 140, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 141, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 87, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 87, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, ], tree3_level3: &[ 0xB7FFFF7FFFFFEFFF, 0x3FFF3FFF, 0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF, 0, 0x1FFFFFFFFFFFFF, 0x2000000000000000, 0xFFFFFFFF1FFFFFFF, 0x10001FFFF, 0xFFFFE000FFFFFFFF, 0x7FFFFFFFFFF07FF, 0xFFFFFFFF3FFFFFFF, 0x3EFF0F, 0xFFFF03FF3FFFFFFF, 0xFFFFFFFFF0FFFFF, 0xFFFF00FFFFFFFFFF, 0xF7FF000FFFFFFFFF, 0x1BFBFFFBFFB7F7FF, 0x7FFFFFFFFFFFFF, 0xFF003FFFFF, 0x7FDFFFFFFFFFFBF, 0x91BFFFFFFFFFFD3F, 0x7FFFFF003FFFFF, 0x7FFFFFFF, 0x37FFFF00000000, 0x3FFFFFF003FFFFF, 0xC0FFFFFFFFFFFFFF, 0x873FFFFFFEEFF06F, 0x1FFFFFFF00000000, 0x1FFFFFFF, 0x7FFFFFFEFF, 0x3FFFFFFFFFFFFF, 0x7FFFF003FFFFF, 0x3FFFF, 0x1FF, 0x7FFFFFFFFFFFF, 0x3FF00FFFFFFFFFF, 0x31BFFFFFFFFFF, 0xE000000000000000, 0xFFFF00801FFFFFFF, 0xFFFF00000001FFFF, 0xFFFF00000000003F, 0x7FFFFF0000001F, 0x803FFFC00000007F, 0x3FF01FFFFFF0004, 0xFFDFFFFFFFFFFFFF, 0x4FFFFFFFFF00F0, 0x17FFDE1F, 0xC0FFFFFFFFFBFFFF, 0x3, 0xFFFF01FFBFFFBD7F, 0x3FF07FFFFFFFFFF, 0xFBEDFDFFFFF99FEF, 0x1F1FCFE081399F, 0x3C3FF07FF, 0x3FF00BF, 0xFF3FFFFFFFFFFFFF, 0x3F000001, 0x3FF0011, 0x1FFFFFFFFFFFFFF, 0x3FF, 0x3FF0FFFE7FFFFFF, 0x7F, 0xFFFFFFFF00000000, 0x800003FFFFFFFFFF, 0xF9BFFFFFFF6FF27F, 0x3FF000F, 0xFFFFFCFF00000000, 0x1BFCFFFFFF, 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFF0080, 0xFFFF000023FFFFFF, 0xFF7FFFFFFFFFFDFF, 0xFFFC000003FF0001, 0x7FFEFFFFFCFFFF, 0xB47FFFFFFFFFFB7F, 0xFFFFFDBF03FF00FF, 0x3FF01FB7FFF, 0x7FFFFF00000000, 0xC7FFFFFFFFFDFFFF, 0x3FF0007, 0x1000000000000, 0x3FFFFFF, 0x7FFFFFFFFFFF, 0xF, 0xFFFFFFFFFFFF0000, 0x1FFFFFFFFFFFF, 0xFFFFFFFFFFFF, 0x3FFFFF, 0xFFFF03FF7FFFFFFF, 0x1F3FFFFFFF03FF, 0xE0FFFFF803FF000F, 0xFFFF, 0xFFFFFFFFFFFF87FF, 0xFFFF80FF, 0x3001B00000000, 0xFFFFFFFFFFFFFF, 0x6FEF000000000000, 0x40007FFFFFFFF, 0xFFFF00F000270000, 0xFFFFFFFFFFFFFFF, 0x1FFF07FFFFFFFFFF, 0x63FF01FF, 0xFFFF3FFFFFFFFFFF, 0xF807E3E000000000, 0x3C0000000FE7, 0x1C, 0xFFFFFFFFFFDFFFFF, 0xEBFFDE64DFFFFFFF, 0xFFFFFFFFFFFFFFEF, 0x7BFFFFFFDFDFE7BF, 0xFFFFFFFFFFFDFC5F, 0xFFFFFF3FFFFFFFFF, 0xF7FFFFFFF7FFFFFD, 0xFFDFFFFFFFDFFFFF, 0xFFFF7FFFFFFF7FFF, 0xFFFFFDFFFFFFFDFF, 0xFFFFFFFFFFFFCFF7, 0xF87FFFFFFFFFFFFF, 0x201FFFFFFFFFFF, 0xFFFEF8000010, 0x7E07FFFFFFF, 0xFFFF07DBF9FFFF7F, 0x3FFFFFFFFFFF, 0x8000, 0x3FFF1FFFFFFFFFFF, 0x43FF, 0x7FFFFFFF0000, 0x3FFFFFFFFFFFFFF, 0x3FFFFFFFFFF0000, 0x7FFF6F7F00000000, 0x7F001F, 0x3FF0FFF, 0xAF7FE96FFFFFFEF, 0x5EF7F796AA96EA84, 0xFFFFBEE0FFFFBFF, 0x3FF000000000000, 0xFFFFFFFF, 0xFFFF0003FFFFFFFF, 0xFFFF0001FFFFFFFF, 0x3FFFFFFF, 0xFFFFFFFFFFFF07FF, ], }; pub const XID_START: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet { tree1_level1: &[ 0, 0x7FFFFFE07FFFFFE, 0x420040000000000, 0xFF7FFFFFFF7FFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x501F0003FFC3, 0, 0xB8DF000000000000, 0xFFFFFFFBFFFFD740, 0xFFBFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFC03, 0xFFFFFFFFFFFFFFFF, 0xFFFEFFFFFFFFFFFF, 0xFFFFFFFF027FFFFF, 0x1FF, 0x787FFFFFF0000, 0xFFFFFFFF00000000, 0xFFFEC000000007FF, 0xFFFFFFFFFFFFFFFF, 0x9C00C060002FFFFF, 0xFFFFFFFD0000, 0xFFFFFFFFFFFFE000, 0x2003FFFFFFFFF, 0x43007FFFFFFFC00, ], tree2_level1: &[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 23, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 35, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 35, 35, 35, 35, 35, 35, 35, 35, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 3, 58, 59, 60, 30, 61, 62, 63, 64, 65, 66, 67, 68, 35, 35, 35, 30, 35, 35, 35, 35, 69, 70, 71, 72, 30, 73, 74, 30, 75, 76, 77, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 35, 35, 35, 78, 79, 80, 81, 82, 30, 30, 30, 30, 30, 30, 30, 30, 83, 43, 84, 85, 86, 35, 87, 88, 30, 30, 30, 30, 30, 30, 30, 30, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 30, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 89, 90, 35, 35, 35, 35, 91, 92, 93, 94, 95, 35, 96, 97, 98, 49, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 35, 111, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 112, 113, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 35, 35, 35, 35, 35, 114, 35, 115, 116, 117, 118, 119, 35, 120, 35, 35, 121, 122, 123, 124, 30, 125, 35, 126, 127, 128, 129, 130, ], tree2_level2: &[ 0x110043FFFFF, 0xFFFF07FF01FFFFFF, 0xFFFFFFFF00007EFF, 0x3FF, 0x23FFFFFFFFFFFFF0, 0xFFFE0003FF010000, 0x23C5FDFFFFF99FE1, 0x10030003B0004000, 0x36DFDFFFFF987E0, 0x1C00005E000000, 0x23EDFDFFFFFBBFE0, 0x200000300010000, 0x23EDFDFFFFF99FE0, 0x20003B0000000, 0x3FFC718D63DC7E8, 0x10000, 0x23FFFDFFFFFDDFE0, 0x327000000, 0x23EFFDFFFFFDDFE1, 0x6000360000000, 0x27FFFFFFFFFDDFF0, 0xFC00000380704000, 0x2FFBFFFFFC7FFFE0, 0x7F, 0x5FFFFFFFFFFFE, 0x2005FFAFFFFFF7D6, 0xF000005F, 0x1, 0x1FFFFFFFFEFF, 0x1F00, 0, 0x800007FFFFFFFFFF, 0xFFE1C0623C3F0000, 0xFFFFFFFF00004003, 0xF7FFFFFFFFFF20BF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFF3D7F3DFF, 0x7F3DFFFFFFFF3DFF, 0xFFFFFFFFFF7FFF3D, 0xFFFFFFFFFF3DFFFF, 0x7FFFFFF, 0xFFFFFFFF0000FFFF, 0x3F3FFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE, 0xFFFF9FFFFFFFFFFF, 0xFFFFFFFF07FFFFFE, 0x1FFC7FFFFFFFFFF, 0x3FFFF8003FFFF, 0x1DFFF0003FFFF, 0xFFFFFFFFFFFFF, 0x10800000, 0xFFFFFFFF00000000, 0x1FFFFFFFFFFFFFF, 0xFFFF05FFFFFFFFFF, 0x3FFFFFFFFFFFFF, 0x7FFFFFFF, 0x1F3FFFFFFF0000, 0xFFFF0FFFFFFFFFFF, 0xFFFFFFFF007FFFFF, 0x1FFFFF, 0x8000000000, 0xFFFFFFFFFFFE0, 0x1FE0, 0xFC00C001FFFFFFF8, 0x3FFFFFFFFF, 0xFFFFFFFFF, 0x3FFFFFFFFC00E000, 0xE7FFFFFFFFFF01FF, 0x46FDE0000000000, 0xFFFFFFFF3F3FFFFF, 0x3FFFFFFFAAFF3F3F, 0x5FDFFFFFFFFFFFFF, 0x1FDC1FFF0FCF1FDC, 0x8002000000000000, 0x1FFF0000, 0xF3FFFD503F2FFC84, 0xFFFFFFFF000043E0, 0x1FF, 0xC781FFFFFFFFF, 0xFFFF20BFFFFFFFFF, 0x80FFFFFFFFFF, 0x7F7F7F7F007FFFFF, 0x7F7F7F7F, 0x1F3E03FE000000E0, 0xFFFFFFFEE07FFFFF, 0xF7FFFFFFFFFFFFFF, 0xFFFEFFFFFFFFFFE0, 0xFFFFFFFF00007FFF, 0xFFFF000000000000, 0x1FFF, 0x3FFFFFFFFFFF0000, 0xC00FFFF1FFF, 0x80007FFFFFFFFFFF, 0xFFFFFFFF3FFFFFFF, 0xFFFFFFFFFFFF, 0xFFFFFFFCFF800000, 0xFFFFFFFFFFFFF9FF, 0xFFFC000003EB07FF, 0x7FFFFF7BB, 0xFFFFFFFFFFFFC, 0x68FC000000000000, 0xFFFF003FFFFFFC00, 0x1FFFFFFF0000007F, 0x7FFFFFFFFFFF0, 0x7C00FFDF00008000, 0x1FFFFFFFFFF, 0xC47FFFFF00000FF7, 0x3E62FFFFFFFFFFFF, 0x1C07FF38000005, 0xFFFF7F7F007E7E7E, 0xFFFF03FFF7FFFFFF, 0x7FFFFFFFF, 0xFFFF000FFFFFFFFF, 0xFFFFFFFFFFFF87F, 0xFFFF3FFFFFFFFFFF, 0x3FFFFFF, 0x5F7FFDFFA0F8007F, 0xFFFFFFFFFFFFFFDB, 0x3FFFFFFFFFFFF, 0xFFFFFFFFFFF80000, 0xFFFFFFF03FFFFFFF, 0x3FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFF0000, 0xFFFFFFFFFFFCFFFF, 0x3FF0000000000FF, 0xAA8A000000000000, 0x1FFFFFFFFFFFFFFF, 0x7FFFFFE00000000, 0xFFFFFFC007FFFFFE, 0x7FFFFFFF3FFFFFFF, 0x1CFCFCFC, ], tree3_level1: &[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 9, 10, 5, 11, 12, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 13, 14, 15, 7, 16, 17, 7, 18, 19, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, ], tree3_level2: &[ 0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 16, 4, 2, 2, 2, 2, 17, 18, 19, 4, 20, 21, 22, 23, 24, 4, 25, 4, 26, 27, 28, 29, 30, 31, 32, 4, 2, 33, 34, 34, 35, 4, 4, 4, 4, 4, 36, 4, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 22, 52, 53, 4, 4, 5, 54, 55, 56, 4, 4, 57, 58, 55, 59, 60, 4, 61, 62, 4, 4, 63, 4, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 4, 4, 4, 4, 74, 75, 76, 4, 77, 78, 79, 4, 4, 4, 4, 80, 81, 4, 82, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 83, 4, 2, 57, 2, 2, 2, 84, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 85, 86, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 55, 87, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 73, 88, 89, 90, 55, 91, 76, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 2, 92, 93, 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 33, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 97, 2, 2, 2, 2, 98, 99, 2, 2, 2, 2, 2, 100, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 101, 102, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 103, 104, 105, 106, 107, 2, 2, 2, 2, 108, 109, 110, 111, 112, 113, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 114, 4, 4, 4, 115, 116, 4, 4, 117, 118, 4, 4, 4, 4, 90, 63, 4, 4, 4, 4, 4, 4, 4, 119, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 120, 2, 2, 2, 121, 2, 122, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 123, 124, 125, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 127, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 129, 2, 2, 2, 2, 2, 2, 2, 2, 2, 130, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 130, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 131, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 55, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, ], tree3_level3: &[ 0xB7FFFF7FFFFFEFFF, 0x3FFF3FFF, 0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF, 0, 0x1FFFFFFFFFFFFF, 0xFFFFFFFF1FFFFFFF, 0x1FFFF, 0xFFFFE000FFFFFFFF, 0x3FFFFFFFFF07FF, 0xFFFFFFFF3FFFFFFF, 0x3EFF0F, 0xFFFF00003FFFFFFF, 0xFFFFFFFFF0FFFFF, 0xFFFF00FFFFFFFFFF, 0xF7FF000FFFFFFFFF, 0x1BFBFFFBFFB7F7FF, 0x7FFFFFFFFFFFFF, 0xFF003FFFFF, 0x7FDFFFFFFFFFFBF, 0x91BFFFFFFFFFFD3F, 0x7FFFFF003FFFFF, 0x7FFFFFFF, 0x37FFFF00000000, 0x3FFFFFF003FFFFF, 0xC0FFFFFFFFFFFFFF, 0x3FFFFFFEEF0001, 0x1FFFFFFF00000000, 0x1FFFFFFF, 0x1FFFFFFEFF, 0x3FFFFFFFFFFFFF, 0x7FFFF003FFFFF, 0x3FFFF, 0x1FF, 0x7FFFFFFFFFFFF, 0xFFFFFFFFF, 0x303FFFFFFFFFF, 0xFFFF00801FFFFFFF, 0xFFFF00000000003F, 0xFFFF000000000003, 0x7FFFFF0000001F, 0xFFFFFFFFFFFFF8, 0x26000000000000, 0xFFFFFFFFFFF8, 0x1FFFFFF0000, 0x7FFFFFFFF8, 0x47FFFFFFFF0090, 0x7FFFFFFFFFFF8, 0x1400001E, 0x80000FFFFFFBFFFF, 0x1, 0xFFFF01FFBFFFBD7F, 0x23EDFDFFFFF99FE0, 0x3E0010000, 0x380000780, 0xFFFFFFFFFFFF, 0xB0, 0x7FFFFFFFFFFF, 0xF000000, 0x10, 0x10007FFFFFFFFFF, 0x7FFFFFF, 0x7F, 0xFFFFFFFFFFF, 0xFFFFFFFF00000000, 0x80000000FFFFFFFF, 0x8000FFFFFF6FF27F, 0x2, 0xFFFFFCFF00000000, 0xA0001FFFF, 0x407FFFFFFFFF801, 0xFFFFFFFFF0010000, 0xFFFF0000200003FF, 0x1FFFFFFFFFFFFFF, 0x7FFFFFFFFDFF, 0xFFFC000000000001, 0xFFFF, 0x1FFFFFFFFFB7F, 0xFFFFFDBF00000040, 0x10003FF, 0x7FFFF00000000, 0xFFFFFFFFDFFF4, 0x1000000000000, 0x3FFFFFF, 0xF, 0xFFFFFFFFFFFF0000, 0x1FFFFFFFFFFFF, 0x7E, 0xFFFF00007FFFFFFF, 0x7FFFFFFFFFFFFFFF, 0x3FFFFFFF0000, 0xE0FFFFF80000000F, 0x107FF, 0xFFF80000, 0xB00000000, 0xFFFFFFFFFFFFFF, 0x3FFFFF, 0x6FEF000000000000, 0x40007FFFFFFFF, 0xFFFF00F000270000, 0xFFFFFFFFFFFFFFF, 0x1FFF07FFFFFFFFFF, 0x3FF01FF, 0xFFFFFFFFFFDFFFFF, 0xEBFFDE64DFFFFFFF, 0xFFFFFFFFFFFFFFEF, 0x7BFFFFFFDFDFE7BF, 0xFFFFFFFFFFFDFC5F, 0xFFFFFF3FFFFFFFFF, 0xF7FFFFFFF7FFFFFD, 0xFFDFFFFFFFDFFFFF, 0xFFFF7FFFFFFF7FFF, 0xFFFFFDFFFFFFFDFF, 0xFF7, 0x7E07FFFFFFF, 0xFFFF000000000000, 0x3FFFFFFFFFFF, 0x3F801FFFFFFFFFFF, 0x4000, 0xFFFFFFF0000, 0x7FFF6F7F00000000, 0x1F, 0x80F, 0xAF7FE96FFFFFFEF, 0x5EF7F796AA96EA84, 0xFFFFBEE0FFFFBFF, 0xFFFFFFFF, 0x3FFFFFFFFFFFFFF, 0xFFFF0003FFFFFFFF, 0xFFFF0001FFFFFFFF, 0x3FFFFFFF, 0xFFFFFFFFFFFF07FF, ], }; unicode-ident/tests/roaring/0000775000175000017500000000000014661133735017075 5ustar jamespagejamespageunicode-ident/tests/roaring/mod.rs0000644000175000017500000000076614661133735020231 0ustar jamespagejamespageuse roaring::RoaringBitmap; pub fn xid_start_bitmap() -> RoaringBitmap { let mut bitmap = RoaringBitmap::new(); for ch in '\0'..=char::MAX { if unicode_ident::is_xid_start(ch) { bitmap.insert(ch as u32); } } bitmap } pub fn xid_continue_bitmap() -> RoaringBitmap { let mut bitmap = RoaringBitmap::new(); for ch in '\0'..=char::MAX { if unicode_ident::is_xid_continue(ch) { bitmap.insert(ch as u32); } } bitmap } unicode-ident/tests/tables/0000775000175000017500000000000014661133735016706 5ustar jamespagejamespageunicode-ident/tests/tables/tables.rs0000644000175000017500000005555014661133735020536 0ustar jamespagejamespage// DO NOT EDIT THIS FILE. IT WAS AUTOMATICALLY GENERATED BY: // // ucd-generate property-bool UCD --include XID_Start,XID_Continue // // Unicode version: 15.1.0. // // ucd-generate 0.3.0 is available on crates.io. pub const BY_NAME: &'static [(&'static str, &'static [(u32, u32)])] = &[ ("XID_Continue", XID_CONTINUE), ("XID_Start", XID_START), ]; pub const XID_CONTINUE: &'static [(u32, u32)] = &[ (48, 57), (65, 90), (95, 95), (97, 122), (170, 170), (181, 181), (183, 183), (186, 186), (192, 214), (216, 246), (248, 705), (710, 721), (736, 740), (748, 748), (750, 750), (768, 884), (886, 887), (891, 893), (895, 895), (902, 906), (908, 908), (910, 929), (931, 1013), (1015, 1153), (1155, 1159), (1162, 1327), (1329, 1366), (1369, 1369), (1376, 1416), (1425, 1469), (1471, 1471), (1473, 1474), (1476, 1477), (1479, 1479), (1488, 1514), (1519, 1522), (1552, 1562), (1568, 1641), (1646, 1747), (1749, 1756), (1759, 1768), (1770, 1788), (1791, 1791), (1808, 1866), (1869, 1969), (1984, 2037), (2042, 2042), (2045, 2045), (2048, 2093), (2112, 2139), (2144, 2154), (2160, 2183), (2185, 2190), (2200, 2273), (2275, 2403), (2406, 2415), (2417, 2435), (2437, 2444), (2447, 2448), (2451, 2472), (2474, 2480), (2482, 2482), (2486, 2489), (2492, 2500), (2503, 2504), (2507, 2510), (2519, 2519), (2524, 2525), (2527, 2531), (2534, 2545), (2556, 2556), (2558, 2558), (2561, 2563), (2565, 2570), (2575, 2576), (2579, 2600), (2602, 2608), (2610, 2611), (2613, 2614), (2616, 2617), (2620, 2620), (2622, 2626), (2631, 2632), (2635, 2637), (2641, 2641), (2649, 2652), (2654, 2654), (2662, 2677), (2689, 2691), (2693, 2701), (2703, 2705), (2707, 2728), (2730, 2736), (2738, 2739), (2741, 2745), (2748, 2757), (2759, 2761), (2763, 2765), (2768, 2768), (2784, 2787), (2790, 2799), (2809, 2815), (2817, 2819), (2821, 2828), (2831, 2832), (2835, 2856), (2858, 2864), (2866, 2867), (2869, 2873), (2876, 2884), (2887, 2888), (2891, 2893), (2901, 2903), (2908, 2909), (2911, 2915), (2918, 2927), (2929, 2929), (2946, 2947), (2949, 2954), (2958, 2960), (2962, 2965), (2969, 2970), (2972, 2972), (2974, 2975), (2979, 2980), (2984, 2986), (2990, 3001), (3006, 3010), (3014, 3016), (3018, 3021), (3024, 3024), (3031, 3031), (3046, 3055), (3072, 3084), (3086, 3088), (3090, 3112), (3114, 3129), (3132, 3140), (3142, 3144), (3146, 3149), (3157, 3158), (3160, 3162), (3165, 3165), (3168, 3171), (3174, 3183), (3200, 3203), (3205, 3212), (3214, 3216), (3218, 3240), (3242, 3251), (3253, 3257), (3260, 3268), (3270, 3272), (3274, 3277), (3285, 3286), (3293, 3294), (3296, 3299), (3302, 3311), (3313, 3315), (3328, 3340), (3342, 3344), (3346, 3396), (3398, 3400), (3402, 3406), (3412, 3415), (3423, 3427), (3430, 3439), (3450, 3455), (3457, 3459), (3461, 3478), (3482, 3505), (3507, 3515), (3517, 3517), (3520, 3526), (3530, 3530), (3535, 3540), (3542, 3542), (3544, 3551), (3558, 3567), (3570, 3571), (3585, 3642), (3648, 3662), (3664, 3673), (3713, 3714), (3716, 3716), (3718, 3722), (3724, 3747), (3749, 3749), (3751, 3773), (3776, 3780), (3782, 3782), (3784, 3790), (3792, 3801), (3804, 3807), (3840, 3840), (3864, 3865), (3872, 3881), (3893, 3893), (3895, 3895), (3897, 3897), (3902, 3911), (3913, 3948), (3953, 3972), (3974, 3991), (3993, 4028), (4038, 4038), (4096, 4169), (4176, 4253), (4256, 4293), (4295, 4295), (4301, 4301), (4304, 4346), (4348, 4680), (4682, 4685), (4688, 4694), (4696, 4696), (4698, 4701), (4704, 4744), (4746, 4749), (4752, 4784), (4786, 4789), (4792, 4798), (4800, 4800), (4802, 4805), (4808, 4822), (4824, 4880), (4882, 4885), (4888, 4954), (4957, 4959), (4969, 4977), (4992, 5007), (5024, 5109), (5112, 5117), (5121, 5740), (5743, 5759), (5761, 5786), (5792, 5866), (5870, 5880), (5888, 5909), (5919, 5940), (5952, 5971), (5984, 5996), (5998, 6000), (6002, 6003), (6016, 6099), (6103, 6103), (6108, 6109), (6112, 6121), (6155, 6157), (6159, 6169), (6176, 6264), (6272, 6314), (6320, 6389), (6400, 6430), (6432, 6443), (6448, 6459), (6470, 6509), (6512, 6516), (6528, 6571), (6576, 6601), (6608, 6618), (6656, 6683), (6688, 6750), (6752, 6780), (6783, 6793), (6800, 6809), (6823, 6823), (6832, 6845), (6847, 6862), (6912, 6988), (6992, 7001), (7019, 7027), (7040, 7155), (7168, 7223), (7232, 7241), (7245, 7293), (7296, 7304), (7312, 7354), (7357, 7359), (7376, 7378), (7380, 7418), (7424, 7957), (7960, 7965), (7968, 8005), (8008, 8013), (8016, 8023), (8025, 8025), (8027, 8027), (8029, 8029), (8031, 8061), (8064, 8116), (8118, 8124), (8126, 8126), (8130, 8132), (8134, 8140), (8144, 8147), (8150, 8155), (8160, 8172), (8178, 8180), (8182, 8188), (8204, 8205), (8255, 8256), (8276, 8276), (8305, 8305), (8319, 8319), (8336, 8348), (8400, 8412), (8417, 8417), (8421, 8432), (8450, 8450), (8455, 8455), (8458, 8467), (8469, 8469), (8472, 8477), (8484, 8484), (8486, 8486), (8488, 8488), (8490, 8505), (8508, 8511), (8517, 8521), (8526, 8526), (8544, 8584), (11264, 11492), (11499, 11507), (11520, 11557), (11559, 11559), (11565, 11565), (11568, 11623), (11631, 11631), (11647, 11670), (11680, 11686), (11688, 11694), (11696, 11702), (11704, 11710), (11712, 11718), (11720, 11726), (11728, 11734), (11736, 11742), (11744, 11775), (12293, 12295), (12321, 12335), (12337, 12341), (12344, 12348), (12353, 12438), (12441, 12442), (12445, 12447), (12449, 12543), (12549, 12591), (12593, 12686), (12704, 12735), (12784, 12799), (13312, 19903), (19968, 42124), (42192, 42237), (42240, 42508), (42512, 42539), (42560, 42607), (42612, 42621), (42623, 42737), (42775, 42783), (42786, 42888), (42891, 42954), (42960, 42961), (42963, 42963), (42965, 42969), (42994, 43047), (43052, 43052), (43072, 43123), (43136, 43205), (43216, 43225), (43232, 43255), (43259, 43259), (43261, 43309), (43312, 43347), (43360, 43388), (43392, 43456), (43471, 43481), (43488, 43518), (43520, 43574), (43584, 43597), (43600, 43609), (43616, 43638), (43642, 43714), (43739, 43741), (43744, 43759), (43762, 43766), (43777, 43782), (43785, 43790), (43793, 43798), (43808, 43814), (43816, 43822), (43824, 43866), (43868, 43881), (43888, 44010), (44012, 44013), (44016, 44025), (44032, 55203), (55216, 55238), (55243, 55291), (63744, 64109), (64112, 64217), (64256, 64262), (64275, 64279), (64285, 64296), (64298, 64310), (64312, 64316), (64318, 64318), (64320, 64321), (64323, 64324), (64326, 64433), (64467, 64605), (64612, 64829), (64848, 64911), (64914, 64967), (65008, 65017), (65024, 65039), (65056, 65071), (65075, 65076), (65101, 65103), (65137, 65137), (65139, 65139), (65143, 65143), (65145, 65145), (65147, 65147), (65149, 65149), (65151, 65276), (65296, 65305), (65313, 65338), (65343, 65343), (65345, 65370), (65381, 65470), (65474, 65479), (65482, 65487), (65490, 65495), (65498, 65500), (65536, 65547), (65549, 65574), (65576, 65594), (65596, 65597), (65599, 65613), (65616, 65629), (65664, 65786), (65856, 65908), (66045, 66045), (66176, 66204), (66208, 66256), (66272, 66272), (66304, 66335), (66349, 66378), (66384, 66426), (66432, 66461), (66464, 66499), (66504, 66511), (66513, 66517), (66560, 66717), (66720, 66729), (66736, 66771), (66776, 66811), (66816, 66855), (66864, 66915), (66928, 66938), (66940, 66954), (66956, 66962), (66964, 66965), (66967, 66977), (66979, 66993), (66995, 67001), (67003, 67004), (67072, 67382), (67392, 67413), (67424, 67431), (67456, 67461), (67463, 67504), (67506, 67514), (67584, 67589), (67592, 67592), (67594, 67637), (67639, 67640), (67644, 67644), (67647, 67669), (67680, 67702), (67712, 67742), (67808, 67826), (67828, 67829), (67840, 67861), (67872, 67897), (67968, 68023), (68030, 68031), (68096, 68099), (68101, 68102), (68108, 68115), (68117, 68119), (68121, 68149), (68152, 68154), (68159, 68159), (68192, 68220), (68224, 68252), (68288, 68295), (68297, 68326), (68352, 68405), (68416, 68437), (68448, 68466), (68480, 68497), (68608, 68680), (68736, 68786), (68800, 68850), (68864, 68903), (68912, 68921), (69248, 69289), (69291, 69292), (69296, 69297), (69373, 69404), (69415, 69415), (69424, 69456), (69488, 69509), (69552, 69572), (69600, 69622), (69632, 69702), (69734, 69749), (69759, 69818), (69826, 69826), (69840, 69864), (69872, 69881), (69888, 69940), (69942, 69951), (69956, 69959), (69968, 70003), (70006, 70006), (70016, 70084), (70089, 70092), (70094, 70106), (70108, 70108), (70144, 70161), (70163, 70199), (70206, 70209), (70272, 70278), (70280, 70280), (70282, 70285), (70287, 70301), (70303, 70312), (70320, 70378), (70384, 70393), (70400, 70403), (70405, 70412), (70415, 70416), (70419, 70440), (70442, 70448), (70450, 70451), (70453, 70457), (70459, 70468), (70471, 70472), (70475, 70477), (70480, 70480), (70487, 70487), (70493, 70499), (70502, 70508), (70512, 70516), (70656, 70730), (70736, 70745), (70750, 70753), (70784, 70853), (70855, 70855), (70864, 70873), (71040, 71093), (71096, 71104), (71128, 71133), (71168, 71232), (71236, 71236), (71248, 71257), (71296, 71352), (71360, 71369), (71424, 71450), (71453, 71467), (71472, 71481), (71488, 71494), (71680, 71738), (71840, 71913), (71935, 71942), (71945, 71945), (71948, 71955), (71957, 71958), (71960, 71989), (71991, 71992), (71995, 72003), (72016, 72025), (72096, 72103), (72106, 72151), (72154, 72161), (72163, 72164), (72192, 72254), (72263, 72263), (72272, 72345), (72349, 72349), (72368, 72440), (72704, 72712), (72714, 72758), (72760, 72768), (72784, 72793), (72818, 72847), (72850, 72871), (72873, 72886), (72960, 72966), (72968, 72969), (72971, 73014), (73018, 73018), (73020, 73021), (73023, 73031), (73040, 73049), (73056, 73061), (73063, 73064), (73066, 73102), (73104, 73105), (73107, 73112), (73120, 73129), (73440, 73462), (73472, 73488), (73490, 73530), (73534, 73538), (73552, 73561), (73648, 73648), (73728, 74649), (74752, 74862), (74880, 75075), (77712, 77808), (77824, 78895), (78912, 78933), (82944, 83526), (92160, 92728), (92736, 92766), (92768, 92777), (92784, 92862), (92864, 92873), (92880, 92909), (92912, 92916), (92928, 92982), (92992, 92995), (93008, 93017), (93027, 93047), (93053, 93071), (93760, 93823), (93952, 94026), (94031, 94087), (94095, 94111), (94176, 94177), (94179, 94180), (94192, 94193), (94208, 100343), (100352, 101589), (101632, 101640), (110576, 110579), (110581, 110587), (110589, 110590), (110592, 110882), (110898, 110898), (110928, 110930), (110933, 110933), (110948, 110951), (110960, 111355), (113664, 113770), (113776, 113788), (113792, 113800), (113808, 113817), (113821, 113822), (118528, 118573), (118576, 118598), (119141, 119145), (119149, 119154), (119163, 119170), (119173, 119179), (119210, 119213), (119362, 119364), (119808, 119892), (119894, 119964), (119966, 119967), (119970, 119970), (119973, 119974), (119977, 119980), (119982, 119993), (119995, 119995), (119997, 120003), (120005, 120069), (120071, 120074), (120077, 120084), (120086, 120092), (120094, 120121), (120123, 120126), (120128, 120132), (120134, 120134), (120138, 120144), (120146, 120485), (120488, 120512), (120514, 120538), (120540, 120570), (120572, 120596), (120598, 120628), (120630, 120654), (120656, 120686), (120688, 120712), (120714, 120744), (120746, 120770), (120772, 120779), (120782, 120831), (121344, 121398), (121403, 121452), (121461, 121461), (121476, 121476), (121499, 121503), (121505, 121519), (122624, 122654), (122661, 122666), (122880, 122886), (122888, 122904), (122907, 122913), (122915, 122916), (122918, 122922), (122928, 122989), (123023, 123023), (123136, 123180), (123184, 123197), (123200, 123209), (123214, 123214), (123536, 123566), (123584, 123641), (124112, 124153), (124896, 124902), (124904, 124907), (124909, 124910), (124912, 124926), (124928, 125124), (125136, 125142), (125184, 125259), (125264, 125273), (126464, 126467), (126469, 126495), (126497, 126498), (126500, 126500), (126503, 126503), (126505, 126514), (126516, 126519), (126521, 126521), (126523, 126523), (126530, 126530), (126535, 126535), (126537, 126537), (126539, 126539), (126541, 126543), (126545, 126546), (126548, 126548), (126551, 126551), (126553, 126553), (126555, 126555), (126557, 126557), (126559, 126559), (126561, 126562), (126564, 126564), (126567, 126570), (126572, 126578), (126580, 126583), (126585, 126588), (126590, 126590), (126592, 126601), (126603, 126619), (126625, 126627), (126629, 126633), (126635, 126651), (130032, 130041), (131072, 173791), (173824, 177977), (177984, 178205), (178208, 183969), (183984, 191456), (191472, 192093), (194560, 195101), (196608, 201546), (201552, 205743), (917760, 917999), ]; pub const XID_START: &'static [(u32, u32)] = &[ (65, 90), (97, 122), (170, 170), (181, 181), (186, 186), (192, 214), (216, 246), (248, 705), (710, 721), (736, 740), (748, 748), (750, 750), (880, 884), (886, 887), (891, 893), (895, 895), (902, 902), (904, 906), (908, 908), (910, 929), (931, 1013), (1015, 1153), (1162, 1327), (1329, 1366), (1369, 1369), (1376, 1416), (1488, 1514), (1519, 1522), (1568, 1610), (1646, 1647), (1649, 1747), (1749, 1749), (1765, 1766), (1774, 1775), (1786, 1788), (1791, 1791), (1808, 1808), (1810, 1839), (1869, 1957), (1969, 1969), (1994, 2026), (2036, 2037), (2042, 2042), (2048, 2069), (2074, 2074), (2084, 2084), (2088, 2088), (2112, 2136), (2144, 2154), (2160, 2183), (2185, 2190), (2208, 2249), (2308, 2361), (2365, 2365), (2384, 2384), (2392, 2401), (2417, 2432), (2437, 2444), (2447, 2448), (2451, 2472), (2474, 2480), (2482, 2482), (2486, 2489), (2493, 2493), (2510, 2510), (2524, 2525), (2527, 2529), (2544, 2545), (2556, 2556), (2565, 2570), (2575, 2576), (2579, 2600), (2602, 2608), (2610, 2611), (2613, 2614), (2616, 2617), (2649, 2652), (2654, 2654), (2674, 2676), (2693, 2701), (2703, 2705), (2707, 2728), (2730, 2736), (2738, 2739), (2741, 2745), (2749, 2749), (2768, 2768), (2784, 2785), (2809, 2809), (2821, 2828), (2831, 2832), (2835, 2856), (2858, 2864), (2866, 2867), (2869, 2873), (2877, 2877), (2908, 2909), (2911, 2913), (2929, 2929), (2947, 2947), (2949, 2954), (2958, 2960), (2962, 2965), (2969, 2970), (2972, 2972), (2974, 2975), (2979, 2980), (2984, 2986), (2990, 3001), (3024, 3024), (3077, 3084), (3086, 3088), (3090, 3112), (3114, 3129), (3133, 3133), (3160, 3162), (3165, 3165), (3168, 3169), (3200, 3200), (3205, 3212), (3214, 3216), (3218, 3240), (3242, 3251), (3253, 3257), (3261, 3261), (3293, 3294), (3296, 3297), (3313, 3314), (3332, 3340), (3342, 3344), (3346, 3386), (3389, 3389), (3406, 3406), (3412, 3414), (3423, 3425), (3450, 3455), (3461, 3478), (3482, 3505), (3507, 3515), (3517, 3517), (3520, 3526), (3585, 3632), (3634, 3634), (3648, 3654), (3713, 3714), (3716, 3716), (3718, 3722), (3724, 3747), (3749, 3749), (3751, 3760), (3762, 3762), (3773, 3773), (3776, 3780), (3782, 3782), (3804, 3807), (3840, 3840), (3904, 3911), (3913, 3948), (3976, 3980), (4096, 4138), (4159, 4159), (4176, 4181), (4186, 4189), (4193, 4193), (4197, 4198), (4206, 4208), (4213, 4225), (4238, 4238), (4256, 4293), (4295, 4295), (4301, 4301), (4304, 4346), (4348, 4680), (4682, 4685), (4688, 4694), (4696, 4696), (4698, 4701), (4704, 4744), (4746, 4749), (4752, 4784), (4786, 4789), (4792, 4798), (4800, 4800), (4802, 4805), (4808, 4822), (4824, 4880), (4882, 4885), (4888, 4954), (4992, 5007), (5024, 5109), (5112, 5117), (5121, 5740), (5743, 5759), (5761, 5786), (5792, 5866), (5870, 5880), (5888, 5905), (5919, 5937), (5952, 5969), (5984, 5996), (5998, 6000), (6016, 6067), (6103, 6103), (6108, 6108), (6176, 6264), (6272, 6312), (6314, 6314), (6320, 6389), (6400, 6430), (6480, 6509), (6512, 6516), (6528, 6571), (6576, 6601), (6656, 6678), (6688, 6740), (6823, 6823), (6917, 6963), (6981, 6988), (7043, 7072), (7086, 7087), (7098, 7141), (7168, 7203), (7245, 7247), (7258, 7293), (7296, 7304), (7312, 7354), (7357, 7359), (7401, 7404), (7406, 7411), (7413, 7414), (7418, 7418), (7424, 7615), (7680, 7957), (7960, 7965), (7968, 8005), (8008, 8013), (8016, 8023), (8025, 8025), (8027, 8027), (8029, 8029), (8031, 8061), (8064, 8116), (8118, 8124), (8126, 8126), (8130, 8132), (8134, 8140), (8144, 8147), (8150, 8155), (8160, 8172), (8178, 8180), (8182, 8188), (8305, 8305), (8319, 8319), (8336, 8348), (8450, 8450), (8455, 8455), (8458, 8467), (8469, 8469), (8472, 8477), (8484, 8484), (8486, 8486), (8488, 8488), (8490, 8505), (8508, 8511), (8517, 8521), (8526, 8526), (8544, 8584), (11264, 11492), (11499, 11502), (11506, 11507), (11520, 11557), (11559, 11559), (11565, 11565), (11568, 11623), (11631, 11631), (11648, 11670), (11680, 11686), (11688, 11694), (11696, 11702), (11704, 11710), (11712, 11718), (11720, 11726), (11728, 11734), (11736, 11742), (12293, 12295), (12321, 12329), (12337, 12341), (12344, 12348), (12353, 12438), (12445, 12447), (12449, 12538), (12540, 12543), (12549, 12591), (12593, 12686), (12704, 12735), (12784, 12799), (13312, 19903), (19968, 42124), (42192, 42237), (42240, 42508), (42512, 42527), (42538, 42539), (42560, 42606), (42623, 42653), (42656, 42735), (42775, 42783), (42786, 42888), (42891, 42954), (42960, 42961), (42963, 42963), (42965, 42969), (42994, 43009), (43011, 43013), (43015, 43018), (43020, 43042), (43072, 43123), (43138, 43187), (43250, 43255), (43259, 43259), (43261, 43262), (43274, 43301), (43312, 43334), (43360, 43388), (43396, 43442), (43471, 43471), (43488, 43492), (43494, 43503), (43514, 43518), (43520, 43560), (43584, 43586), (43588, 43595), (43616, 43638), (43642, 43642), (43646, 43695), (43697, 43697), (43701, 43702), (43705, 43709), (43712, 43712), (43714, 43714), (43739, 43741), (43744, 43754), (43762, 43764), (43777, 43782), (43785, 43790), (43793, 43798), (43808, 43814), (43816, 43822), (43824, 43866), (43868, 43881), (43888, 44002), (44032, 55203), (55216, 55238), (55243, 55291), (63744, 64109), (64112, 64217), (64256, 64262), (64275, 64279), (64285, 64285), (64287, 64296), (64298, 64310), (64312, 64316), (64318, 64318), (64320, 64321), (64323, 64324), (64326, 64433), (64467, 64605), (64612, 64829), (64848, 64911), (64914, 64967), (65008, 65017), (65137, 65137), (65139, 65139), (65143, 65143), (65145, 65145), (65147, 65147), (65149, 65149), (65151, 65276), (65313, 65338), (65345, 65370), (65382, 65437), (65440, 65470), (65474, 65479), (65482, 65487), (65490, 65495), (65498, 65500), (65536, 65547), (65549, 65574), (65576, 65594), (65596, 65597), (65599, 65613), (65616, 65629), (65664, 65786), (65856, 65908), (66176, 66204), (66208, 66256), (66304, 66335), (66349, 66378), (66384, 66421), (66432, 66461), (66464, 66499), (66504, 66511), (66513, 66517), (66560, 66717), (66736, 66771), (66776, 66811), (66816, 66855), (66864, 66915), (66928, 66938), (66940, 66954), (66956, 66962), (66964, 66965), (66967, 66977), (66979, 66993), (66995, 67001), (67003, 67004), (67072, 67382), (67392, 67413), (67424, 67431), (67456, 67461), (67463, 67504), (67506, 67514), (67584, 67589), (67592, 67592), (67594, 67637), (67639, 67640), (67644, 67644), (67647, 67669), (67680, 67702), (67712, 67742), (67808, 67826), (67828, 67829), (67840, 67861), (67872, 67897), (67968, 68023), (68030, 68031), (68096, 68096), (68112, 68115), (68117, 68119), (68121, 68149), (68192, 68220), (68224, 68252), (68288, 68295), (68297, 68324), (68352, 68405), (68416, 68437), (68448, 68466), (68480, 68497), (68608, 68680), (68736, 68786), (68800, 68850), (68864, 68899), (69248, 69289), (69296, 69297), (69376, 69404), (69415, 69415), (69424, 69445), (69488, 69505), (69552, 69572), (69600, 69622), (69635, 69687), (69745, 69746), (69749, 69749), (69763, 69807), (69840, 69864), (69891, 69926), (69956, 69956), (69959, 69959), (69968, 70002), (70006, 70006), (70019, 70066), (70081, 70084), (70106, 70106), (70108, 70108), (70144, 70161), (70163, 70187), (70207, 70208), (70272, 70278), (70280, 70280), (70282, 70285), (70287, 70301), (70303, 70312), (70320, 70366), (70405, 70412), (70415, 70416), (70419, 70440), (70442, 70448), (70450, 70451), (70453, 70457), (70461, 70461), (70480, 70480), (70493, 70497), (70656, 70708), (70727, 70730), (70751, 70753), (70784, 70831), (70852, 70853), (70855, 70855), (71040, 71086), (71128, 71131), (71168, 71215), (71236, 71236), (71296, 71338), (71352, 71352), (71424, 71450), (71488, 71494), (71680, 71723), (71840, 71903), (71935, 71942), (71945, 71945), (71948, 71955), (71957, 71958), (71960, 71983), (71999, 71999), (72001, 72001), (72096, 72103), (72106, 72144), (72161, 72161), (72163, 72163), (72192, 72192), (72203, 72242), (72250, 72250), (72272, 72272), (72284, 72329), (72349, 72349), (72368, 72440), (72704, 72712), (72714, 72750), (72768, 72768), (72818, 72847), (72960, 72966), (72968, 72969), (72971, 73008), (73030, 73030), (73056, 73061), (73063, 73064), (73066, 73097), (73112, 73112), (73440, 73458), (73474, 73474), (73476, 73488), (73490, 73523), (73648, 73648), (73728, 74649), (74752, 74862), (74880, 75075), (77712, 77808), (77824, 78895), (78913, 78918), (82944, 83526), (92160, 92728), (92736, 92766), (92784, 92862), (92880, 92909), (92928, 92975), (92992, 92995), (93027, 93047), (93053, 93071), (93760, 93823), (93952, 94026), (94032, 94032), (94099, 94111), (94176, 94177), (94179, 94179), (94208, 100343), (100352, 101589), (101632, 101640), (110576, 110579), (110581, 110587), (110589, 110590), (110592, 110882), (110898, 110898), (110928, 110930), (110933, 110933), (110948, 110951), (110960, 111355), (113664, 113770), (113776, 113788), (113792, 113800), (113808, 113817), (119808, 119892), (119894, 119964), (119966, 119967), (119970, 119970), (119973, 119974), (119977, 119980), (119982, 119993), (119995, 119995), (119997, 120003), (120005, 120069), (120071, 120074), (120077, 120084), (120086, 120092), (120094, 120121), (120123, 120126), (120128, 120132), (120134, 120134), (120138, 120144), (120146, 120485), (120488, 120512), (120514, 120538), (120540, 120570), (120572, 120596), (120598, 120628), (120630, 120654), (120656, 120686), (120688, 120712), (120714, 120744), (120746, 120770), (120772, 120779), (122624, 122654), (122661, 122666), (122928, 122989), (123136, 123180), (123191, 123197), (123214, 123214), (123536, 123565), (123584, 123627), (124112, 124139), (124896, 124902), (124904, 124907), (124909, 124910), (124912, 124926), (124928, 125124), (125184, 125251), (125259, 125259), (126464, 126467), (126469, 126495), (126497, 126498), (126500, 126500), (126503, 126503), (126505, 126514), (126516, 126519), (126521, 126521), (126523, 126523), (126530, 126530), (126535, 126535), (126537, 126537), (126539, 126539), (126541, 126543), (126545, 126546), (126548, 126548), (126551, 126551), (126553, 126553), (126555, 126555), (126557, 126557), (126559, 126559), (126561, 126562), (126564, 126564), (126567, 126570), (126572, 126578), (126580, 126583), (126585, 126588), (126590, 126590), (126592, 126601), (126603, 126619), (126625, 126627), (126629, 126633), (126635, 126651), (131072, 173791), (173824, 177977), (177984, 178205), (178208, 183969), (183984, 191456), (191472, 192093), (194560, 195101), (196608, 201546), (201552, 205743), ]; unicode-ident/tests/tables/mod.rs0000644000175000017500000000022014661133735020023 0ustar jamespagejamespage#![allow(clippy::module_inception)] #[allow(clippy::redundant_static_lifetimes)] #[rustfmt::skip] mod tables; pub(crate) use self::tables::*; unicode-ident/tests/compare.rs0000644000175000017500000000337614661133735017437 0ustar jamespagejamespagemod fst; mod roaring; mod trie; #[test] fn compare_all_implementations() { let xid_start_fst = fst::xid_start_fst(); let xid_continue_fst = fst::xid_continue_fst(); let xid_start_roaring = roaring::xid_start_bitmap(); let xid_continue_roaring = roaring::xid_continue_bitmap(); for ch in '\0'..=char::MAX { let thought_to_be_start = unicode_ident::is_xid_start(ch); let thought_to_be_continue = unicode_ident::is_xid_continue(ch); // unicode-xid // FIXME: unicode-xid does not support Unicode 15.1.0 yet. /* assert_eq!( thought_to_be_start, unicode_xid::UnicodeXID::is_xid_start(ch), "{ch:?}", ); assert_eq!( thought_to_be_continue, unicode_xid::UnicodeXID::is_xid_continue(ch), "{ch:?}", ); */ // ucd-trie assert_eq!( thought_to_be_start, trie::XID_START.contains_char(ch), "{ch:?}", ); assert_eq!( thought_to_be_continue, trie::XID_CONTINUE.contains_char(ch), "{ch:?}", ); // fst assert_eq!( thought_to_be_start, xid_start_fst.contains((ch as u32).to_be_bytes()), "{ch:?}", ); assert_eq!( thought_to_be_continue, xid_continue_fst.contains((ch as u32).to_be_bytes()), "{ch:?}", ); // roaring assert_eq!( thought_to_be_start, xid_start_roaring.contains(ch as u32), "{ch:?}", ); assert_eq!( thought_to_be_continue, xid_continue_roaring.contains(ch as u32), "{ch:?}", ); } } unicode-ident/tests/fst/0000775000175000017500000000000014661133735016230 5ustar jamespagejamespageunicode-ident/tests/fst/xid_continue.fst0000644000175000017500000021704114661133735021441 0ustar jamespagejamespagezyxwvutsrqponmlkjihgfedcba_ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~}|{wvtsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`YVUTSRQPONMLKJIHGFEDCBA@?>=<;:987654321/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpjihgfedcba`[ZYXWVUTSRQPONMLKJIHGFEDCBA@-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqonmlkjihgfcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~utsrqponmlkjihgf^\[ZYQMLKHGBA@?><9865320/.-,+*('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~qonmlkjihgfcba`_]\WVUMLKHGDCBA@?>=<98765320/.-,+*('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~onmlkjihgfcba`]ZYXVUMLKJHGFDCBA@?>=<9876543210/.-,+*('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zonmlkjihgfcba`_WVUTNMLKJHGFDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~YXWVUTSRQPNMLKJIHGFEDCBA@:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Ƽ~}|{zyxwvutsrqlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIGFEDCBA@?>975)('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`]\[ZXVUTSRQPMLKJHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~qponmlkji_^]ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpolkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~srponlkjihgfedcba`SRQPONMLKJIHGFEDCBA@43210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~xwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~tsrqpmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGF;:9876543210+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|{zyxwvutsrqponmlkjihgfedcba`^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~srqponmlkYXWVUTSRQPLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~п}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMIHGFEDCBA@76543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¾}|{zyxwvutsrqponmlkjihgfedcba`_][YWVUTSRQPMLKJIHEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~МqT@?   !"#$%&'()*+,-.~}|{zyxwvutsrqponmlkjihgfedcba`NIHGFE?>=<9876543210/.-,+*(&$   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ogfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210-'%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA<;:9854321/.-,+*)('&%$#"!  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𿾽~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:987654321/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Ќ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~}|{zyxwvutonmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~srqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@,'&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|{zyxwvutsrqponmlkjihgfedcba`SRQPONMLKJIHGFEDCBA@?>=<;:9876543210-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zvutsrqponmlkjihgfedcba`YXWVUTSRQPMLKJIHGFEDCBA@6543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpihgfedcba`_^]\ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210.-,+*)(&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ӱ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFDCA@><;:986543210/.-,+*('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfed]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQP=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~}{ywsqONM43/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¾~}|{zyxwvutsrqponmlkjihgfeZYXWVUTSRQPONMLKJIHGFEDCBA?:9876543210/.-,+*)('&%$#"!  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~`4+ xqxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxLW{x*"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$xxxxxxxxxxxxxxxxxxxxxxxxx&')J,.134xx7C:=<;:98765410-,!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ]\[ZYXWVUTSRQPMLKJIHGFEDCBA@?=<:9876543210/.-,+*)(&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~tsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@  !"#$%&'()*+,-./0123456  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOzyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPJIHGFEDCBA@?>=<;:9876543210/.-   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|zyxwvutsrqpcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210'&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~gfedcba`UTSRQPONMLKJIHGFEDCBA@6543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~vutsrqponmlkjihgfedcba`UTSRQPONMLKJIHGFEDCBA@?<87543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij|{zyxwvutsrqponmlkjihgfedcba`?:98543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~rqponmlkjihgfedcba`UTSRQPONMLKJIHGFEDCBA@543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~9876543210'&%$#"!    !"#$%&'()*+,-./012  !"#$%&'()*+,-./01~}|{zyxwvutsrqpPONMLKJIHGFEDCBA@?>=<;:9876543210'   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ºutsrqponmlkjihgfFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~vsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPGFED?>=<;:987643210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~A@?>76543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~tsrqplkjihgfcba`_^]WPMLKHGDCBA@?>=<;98765320/.-,+*('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVa`_^YXWVUTSRQPJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEYXWVUTSRQPD@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~FEDCBA@9876543210+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~YXWVUTSRQPCBA@?>=<;87543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPG>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrYXWVUTSRQP@?>=<;:986543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjhgedcba`YXWVUTSRQPGFEDCBA@?=<:6543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~YXWVUTSRQPBA@?>:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~nmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~CBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCD  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`aUTSRQPONMLKJIHGFEDCBA@/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFG~}|{zyxwvutsrqpihgfedcba`^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}wvutsrqponmlkjihgfedcYXWVUTSRQPCBA@6543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklm~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@  !"#$%&'()*+,-./0123456789:;<=>?@~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPOJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  ~}|{zyxwvutsrqpgfedURQP2"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|{zyxwvutsrqpjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~FEDCBA@?>=<;:9876543210-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDE~}|{rqponmihgfeDCB~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRPONMLKJFDCBA@>=<;9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpnmlkjihgfedcba`_^]\[ZYXWVUTSRQPNMLKJIHGFEDCBA@?>=<;:987643210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ulkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;6543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~*)('&%   !"#$%mlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210*)('&$#!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdeNIHGFEDCBA@=<;:9876543210,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEF  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY  !"#$%&'()*~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~YXWVUTSRQPKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUV~|{zywvutrqponmljihgdba_][YWTRQONMKIGB;97654210/.-,+*)'$"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ 4~ R  kl]VA,4r #%%%q(d+- /03M568,: =D?@ A"C;EGILzMO(QS.U{WYm\r^_?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefgh i~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ E E ?E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E  E E E E E E E E E E E E E E E E  E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E E ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~0~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~llllllllllllllldlllllllllllllllllll#"!    !"#0$~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ! 9#  }unicode-ident/tests/fst/mod.rs0000644000175000017500000000060114661133735017350 0ustar jamespagejamespage#![allow(clippy::module_name_repetitions)] pub fn xid_start_fst() -> fst::Set<&'static [u8]> { let data = include_bytes!("xid_start.fst"); fst::Set::from(fst::raw::Fst::new(data.as_slice()).unwrap()) } pub fn xid_continue_fst() -> fst::Set<&'static [u8]> { let data = include_bytes!("xid_continue.fst"); fst::Set::from(fst::raw::Fst::new(data.as_slice()).unwrap()) } unicode-ident/tests/fst/xid_start.fst0000644000175000017500000017771714661133735020771 0ustar jamespagejamespagezyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~}|{wvtsrqp  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Ј~}|{zyxwvutsrqponmlkjihgfedcba`YVUTSRQPONMLKJIHGFEDCBA@?>=<;:987654321/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqonJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ʱ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONM/.-,+*)('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpjihgfedcba`XWVUTSRQPONMLKJIHGFEDCBA@($   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ν~}|{zyxwvutsrqa`_^]\[ZYXP=9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~нtsr^\[ZY9865320/.-,+*('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghйqa`_]\=98765320/.-,+*('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZݽa`]ZYX=9876543210/.-,+*('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr~}|{za`_VUTN=:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~FEDCBA@20/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnolkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIGFEDCBA@  !"#$%&'()*+,-./012~}|{zyxwvuponfea]\[ZUTSRQP?*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`]\[ZXVUTSRQPMLKJHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpolkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~׳ponlkjihgfedcba`QPONMLKJIHGFEDCBA@10/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}xwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~tsrqpmlkjihgfedcba`_^]\[ZYXWVUTSRQP   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~TSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMLKJIHGFE3210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~鿾}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZONM#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¾}|{zyxwvutsrqponmlkjihgfedcba`_][YWVUTSRQPMLKJIHEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~q~}|{zyxwvutsrqponmlkjihgfedcba`NIHGFE?>=<9876543210/.-,+*(&$   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ogfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210-'%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA<;:9854321)('&%$#"!  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~𿾽~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:987654321/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Ќ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~nmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@+*   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~򳲱srqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ϲ|{zyxwvutsrqponmlkjihgfedcba`FEDCBA@?>=<;:9876543210%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~zvutsrqponmlkjihgfedcba`KJIHGFEDBA@('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpihgfedcba`_^]\ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210.-,+*)(&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ӱ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFDCA@><;:986543210/.-,+*('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfed]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQP=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~}{ywsq  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~¾~}|{zyxwvutsrqponmlkjihgfZYXWVUTSRQPONMLKJIHGFEDCBA:9876543210/.-,+*)('&%$#"!  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~DO V k  k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k_1 k k k k k k k k k k k k k k k k k k k k k k k k k"$'),.. k_136 89;Q>N@ k-C.FH kKMCO$Q#S UVXZ\^&agcZf]h k n~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:98765410-,!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ]\[ZYXWVUTSRQPMLKJIHGFEDCBA@?=<:9876543210/.-,+*)(&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~tsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@  !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPJIHGFEDCBA@?>=<;:9876543210/.-   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|zyxwvutsrqpcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210'&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~gfedcba`UTSRQPONMLKJIHGFEDCBA@6543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~vutsrqponmlkjihgfedcba`UTSRQPONMLKJIHGFEDCBA@?<87543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghij|{zyxwvutsrqponmlkjihgfedcba`543210/.-,+*)('&%$#"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~rqponmlkjihgfedcba`UTSRQPONMLKJIHGFEDCBA@543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~#"!    !"#$  !"#$%&'()*+,~}|{zyxwvutsrqpEDCBA@?>=<;:9876543210'   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrЯurq76543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~vrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPGD&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@?+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~a`_^]P=98765320/.-,+*('&%$#"!    !"#$%&'()*+,-./012345įa`_JIHG43210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnoخ  !"#$%&'()*+,-./0123D/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]FEDCBA@   !"+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmA?/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]~}|{zyxwvutsrqponmlkjihgfedcba`_^]\P:210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsr@.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLM~}|{zyxwvutsrqponmlkjhgedcba`F0/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY3210/.-,+*)('&%$#"!    !"#$%&'()*+,-./01~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~nmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~CBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCD  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`aFEDCBA/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456FEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGо~}|{zyxwvutsrqp^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}wvutsrqponmlkjihgfedcCBA@/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@  !"#$%&'()*+,-./0123456789:;<=>?@PJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  ~}|{zyxwvutsrqpgfedURQP2"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~|{zyxwvutsrqpjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRPONMLKJFDCBA@>=<;9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqpnmlkjihgfedcba`_^]\[ZYXWVUTSRQPNMLKJIHGFEDCBA@?>=<;:987643210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~*)('&%   !"#$%mlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210  !"#$%&'()*+,-./0123456789:;<=>N=<;:987,+*)('&%$#"!    !"#$%&'()*+,-./012345  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~KCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDE~|{zywvutrqponmljihgdba_][YWTRQONMKIGB;97654210/.-,+*)'$"!   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~8rC - y XdXXXXC"XXXXXXXXXXXXXXXXXXXXXXX6%&t(/*XXݼ,XXM.XXXXݻ/1 35XXX#899d;=J?AB*DEOG0IJLNPRS.UWtY}[T]_Xݦacf%ij0lԼ~}|{zyxwvutsrqponkjihFED43210/%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abc d~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^  ?    ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)('&%$#"!    !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~>>>>>>>>>>>>>>>d>>>>>>>>>>>>>>>>>>>#"!    !"# $&-  cunicode-ident/tests/static_size.rs0000644000175000017500000000463014661133735020324 0ustar jamespagejamespage#![allow(clippy::let_underscore_untyped, clippy::unreadable_literal)] use std::mem::size_of_val; #[test] fn test_size() { #[allow(dead_code)] #[path = "../src/tables.rs"] mod tables; let size = size_of_val(&tables::ASCII_START) + size_of_val(&tables::ASCII_CONTINUE) + size_of_val(&tables::TRIE_START) + size_of_val(&tables::TRIE_CONTINUE) + size_of_val(&tables::LEAF); assert_eq!(10080, size); } #[test] fn test_xid_size() { #[deny(dead_code)] #[path = "tables/mod.rs"] mod tables; let size = size_of_val(tables::XID_START) + size_of_val(tables::XID_CONTINUE); assert_eq!(11544, size); let _ = tables::BY_NAME; } #[cfg(target_pointer_width = "64")] #[test] fn test_trieset_size() { #[deny(dead_code)] #[allow(clippy::redundant_static_lifetimes)] #[path = "trie/trie.rs"] mod trie; let ucd_trie::TrieSet { tree1_level1, tree2_level1, tree2_level2, tree3_level1, tree3_level2, tree3_level3, } = *trie::XID_START; let start_size = size_of_val(trie::XID_START) + size_of_val(tree1_level1) + size_of_val(tree2_level1) + size_of_val(tree2_level2) + size_of_val(tree3_level1) + size_of_val(tree3_level2) + size_of_val(tree3_level3); let ucd_trie::TrieSet { tree1_level1, tree2_level1, tree2_level2, tree3_level1, tree3_level2, tree3_level3, } = *trie::XID_CONTINUE; let continue_size = size_of_val(trie::XID_CONTINUE) + size_of_val(tree1_level1) + size_of_val(tree2_level1) + size_of_val(tree2_level2) + size_of_val(tree3_level1) + size_of_val(tree3_level2) + size_of_val(tree3_level3); assert_eq!(10200, start_size + continue_size); let _ = trie::BY_NAME; } #[test] fn test_fst_size() { let xid_start_fst = include_bytes!("fst/xid_start.fst"); let xid_continue_fst = include_bytes!("fst/xid_continue.fst"); let size = xid_start_fst.len() + xid_continue_fst.len(); assert_eq!(138736, size); } #[test] fn test_roaring_size() { #[path = "roaring/mod.rs"] mod roaring; let xid_start_bitmap = roaring::xid_start_bitmap(); let xid_continue_bitmap = roaring::xid_continue_bitmap(); let size = xid_start_bitmap.serialized_size() + xid_continue_bitmap.serialized_size(); assert_eq!(66104, size); } unicode-ident/LICENSE-MIT0000644000175000017500000000177714661133735015740 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. unicode-ident/src/0000775000175000017500000000000014661133735015061 5ustar jamespagejamespageunicode-ident/src/tables.rs0000644000175000017500000017235614661133735016715 0ustar jamespagejamespage// @generated by ../generate. To regenerate, run the following in the repo root: // // $ curl -LO https://www.unicode.org/Public/zipped/15.0.0/UCD.zip // $ unzip UCD.zip -d UCD // $ cargo run --manifest-path generate/Cargo.toml const T: bool = true; const F: bool = false; #[repr(C, align(8))] pub(crate) struct Align8(pub(crate) T); #[repr(C, align(64))] pub(crate) struct Align64(pub(crate) T); pub(crate) static ASCII_START: Align64<[bool; 128]> = Align64([ F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, F, F, F, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, F, F, F, F, ]); pub(crate) static ASCII_CONTINUE: Align64<[bool; 128]> = Align64([ F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, T, T, T, T, T, T, T, T, T, T, F, F, F, F, F, F, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, F, F, F, T, F, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, F, F, F, F, ]); pub(crate) const CHUNK: usize = 64; pub(crate) static TRIE_START: Align8<[u8; 402]> = Align8([ 0x04, 0x0B, 0x0F, 0x13, 0x17, 0x1B, 0x1F, 0x23, 0x27, 0x2D, 0x31, 0x34, 0x38, 0x3C, 0x40, 0x02, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x4D, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x51, 0x54, 0x58, 0x5C, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x60, 0x64, 0x66, 0x6A, 0x6E, 0x72, 0x28, 0x76, 0x78, 0x7C, 0x80, 0x84, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9E, 0xA2, 0x05, 0x2B, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x99, 0x05, 0x05, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB1, 0x00, 0xB5, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xBB, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC8, 0x00, 0x00, 0x00, 0xAF, 0xCE, 0xD2, 0xD6, 0xBC, 0xDA, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE0, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xE3, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE6, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE1, 0x05, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x05, 0xEB, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE4, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE7, ]); pub(crate) static TRIE_CONTINUE: Align8<[u8; 1793]> = Align8([ 0x08, 0x0D, 0x11, 0x15, 0x19, 0x1D, 0x21, 0x25, 0x2A, 0x2F, 0x31, 0x36, 0x3A, 0x3E, 0x42, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x00, 0x4F, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x51, 0x56, 0x5A, 0x5E, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x64, 0x68, 0x6C, 0x70, 0x74, 0x28, 0x76, 0x7A, 0x7E, 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9B, 0xA0, 0xA4, 0x05, 0x2B, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x99, 0x05, 0x05, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xB3, 0x00, 0xB7, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xBB, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0xAC, 0xC4, 0xC6, 0xCA, 0x00, 0xCC, 0x00, 0xAF, 0xD0, 0xD4, 0xD8, 0xBC, 0xDC, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE0, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xE3, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE6, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE1, 0x05, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x05, 0xEB, 0x00, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE4, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, ]); pub(crate) static LEAF: Align64<[u8; 7584]> = Align64([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xAA, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x5F, 0xDC, 0x1F, 0xCF, 0x0F, 0xFF, 0x1F, 0xDC, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x04, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xA0, 0x04, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x03, 0x00, 0x1F, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xB8, 0x40, 0xD7, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x03, 0x00, 0x1F, 0x50, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xB8, 0xC0, 0xD7, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x87, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xB6, 0x00, 0xFF, 0xFF, 0xFF, 0x87, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x2F, 0x00, 0x60, 0xC0, 0x00, 0x9C, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x02, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x07, 0x30, 0x04, 0x00, 0x00, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x9F, 0xFF, 0xFD, 0xFF, 0x9F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x24, 0xFF, 0xFF, 0x3F, 0x04, 0x10, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0x01, 0xFF, 0x03, 0x00, 0xFE, 0xFF, 0xE1, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xC5, 0x23, 0x00, 0x40, 0x00, 0xB0, 0x03, 0x00, 0x03, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x7E, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFE, 0xFF, 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xC5, 0xF3, 0x9F, 0x79, 0x80, 0xB0, 0xCF, 0xFF, 0x03, 0x50, 0xE0, 0x87, 0xF9, 0xFF, 0xFF, 0xFD, 0x6D, 0x03, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x1C, 0x00, 0xE0, 0xBF, 0xFB, 0xFF, 0xFF, 0xFD, 0xED, 0x23, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x02, 0xE0, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0x23, 0x00, 0x00, 0x00, 0xB0, 0x03, 0x00, 0x02, 0x00, 0xE8, 0xC7, 0x3D, 0xD6, 0x18, 0xC7, 0xFF, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x87, 0xF9, 0xFF, 0xFF, 0xFD, 0x6D, 0xD3, 0x87, 0x39, 0x02, 0x5E, 0xC0, 0xFF, 0x3F, 0x00, 0xEE, 0xBF, 0xFB, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0xBF, 0x3B, 0x01, 0x00, 0xCF, 0xFF, 0x00, 0xFE, 0xEE, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xF3, 0x9F, 0x39, 0xE0, 0xB0, 0xCF, 0xFF, 0x02, 0x00, 0xEC, 0xC7, 0x3D, 0xD6, 0x18, 0xC7, 0xFF, 0xC3, 0xC7, 0x3D, 0x81, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0xE0, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0x23, 0x00, 0x00, 0x00, 0x27, 0x03, 0x00, 0x00, 0x00, 0xE1, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0x23, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x06, 0x00, 0xF0, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00, 0x40, 0x70, 0x80, 0x03, 0x00, 0x00, 0xFC, 0xE0, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xF3, 0xDF, 0x3D, 0x60, 0x27, 0xCF, 0xFF, 0x00, 0x00, 0xEF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0xF3, 0xDF, 0x3D, 0x60, 0x60, 0xCF, 0xFF, 0x0E, 0x00, 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x7D, 0xF0, 0x80, 0xCF, 0xFF, 0x00, 0xFC, 0xEE, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x84, 0x5F, 0xFF, 0xC0, 0xFF, 0x0C, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0x05, 0x20, 0x5F, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x7F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0x3F, 0x5F, 0x7F, 0xFF, 0xF3, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0xFF, 0x03, 0xA0, 0xC2, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF, 0xDF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x80, 0x00, 0x00, 0x3F, 0x3C, 0x62, 0xC0, 0xE1, 0xFF, 0x03, 0x40, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0x7F, 0x3D, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0xFE, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0x01, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xDF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0x01, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0x1F, 0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xDF, 0x0D, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x30, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x0F, 0xFF, 0x0F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0x01, 0xC0, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0x03, 0xFF, 0x03, 0x80, 0x00, 0xFF, 0xBF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x03, 0x00, 0xF8, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0x6F, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xFC, 0x2F, 0x3F, 0x50, 0xFD, 0xFF, 0xF3, 0xE0, 0x43, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x1F, 0xE2, 0xFF, 0x01, 0x00, 0x84, 0xFC, 0x2F, 0x3F, 0x50, 0xFD, 0xFF, 0xF3, 0xE0, 0x43, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x78, 0x0C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x80, 0xFF, 0xFF, 0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0xFE, 0x03, 0x3E, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x3E, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xE6, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0x00, 0x0C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xEB, 0x03, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xEB, 0x03, 0x00, 0x00, 0xFC, 0xFF, 0xBB, 0xF7, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x68, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x80, 0x00, 0x00, 0xDF, 0xFF, 0x00, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF7, 0x0F, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0xC4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62, 0x3E, 0x05, 0x00, 0x00, 0x38, 0xFF, 0x07, 0x1C, 0x00, 0x7E, 0x7E, 0x7E, 0x00, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x38, 0xFF, 0xFF, 0x7C, 0x00, 0x7E, 0x7E, 0x7E, 0x00, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0xF8, 0xA0, 0xFF, 0xFD, 0x7F, 0x5F, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0xF8, 0xE0, 0xFF, 0xFD, 0x7F, 0x5F, 0xDB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x07, 0xFE, 0xFF, 0xFF, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xFF, 0x03, 0xFE, 0xFF, 0xFF, 0x87, 0xFE, 0xFF, 0xFF, 0x07, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFC, 0xFC, 0xFC, 0x1C, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0x3F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xEF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xB7, 0xFF, 0x3F, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xF7, 0xFF, 0xF7, 0xB7, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0xFF, 0xF7, 0xFF, 0xF7, 0xB7, 0xFF, 0xFB, 0xFF, 0xFB, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x91, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x37, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xEF, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xF0, 0xEF, 0xFE, 0xFF, 0xFF, 0x3F, 0x87, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x90, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x1E, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xDE, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0x0F, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0x23, 0x00, 0x00, 0x01, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x03, 0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xFB, 0x9F, 0x39, 0x81, 0xE0, 0xCF, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x80, 0x07, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xC3, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0x0F, 0xFF, 0x03, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x80, 0x7F, 0xF2, 0x6F, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x80, 0x7F, 0xF2, 0x6F, 0xFF, 0xFF, 0xFF, 0xBF, 0xF9, 0x0F, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1B, 0x00, 0x00, 0x00, 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x00, 0x00, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x20, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x23, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x6F, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x01, 0x00, 0xFF, 0x03, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xB4, 0xFF, 0x00, 0xFF, 0x03, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0x7F, 0xFB, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x07, 0x00, 0xF4, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x07, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x07, 0xF8, 0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x0F, 0x00, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x6F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F, 0xFF, 0x01, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F, 0xFF, 0x01, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x64, 0xDE, 0xFF, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xE7, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7B, 0x5F, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xF7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x00, 0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x3F, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0xFF, 0xFF, 0x96, 0xFE, 0xF7, 0x0A, 0x84, 0xEA, 0x96, 0xAA, 0x96, 0xF7, 0xF7, 0x5E, 0xFF, 0xFB, 0xFF, 0x0F, 0xEE, 0xFB, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]); unicode-ident/src/lib.rs0000644000175000017500000003046414661133735016202 0ustar jamespagejamespage//! [![github]](https://github.com/dtolnay/unicode-ident) [![crates-io]](https://crates.io/crates/unicode-ident) [![docs-rs]](https://docs.rs/unicode-ident) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! Implementation of [Unicode Standard Annex #31][tr31] for determining which //! `char` values are valid in programming language identifiers. //! //! [tr31]: https://www.unicode.org/reports/tr31/ //! //! This crate is a better optimized implementation of the older `unicode-xid` //! crate. This crate uses less static storage, and is able to classify both //! ASCII and non-ASCII codepoints with better performance, 2–10× //! faster than `unicode-xid`. //! //!
//! //! ## Comparison of performance //! //! The following table shows a comparison between five Unicode identifier //! implementations. //! //! - `unicode-ident` is this crate; //! - [`unicode-xid`] is a widely used crate run by the "unicode-rs" org; //! - `ucd-trie` and `fst` are two data structures supported by the //! [`ucd-generate`] tool; //! - [`roaring`] is a Rust implementation of Roaring bitmap. //! //! The *static storage* column shows the total size of `static` tables that the //! crate bakes into your binary, measured in 1000s of bytes. //! //! The remaining columns show the **cost per call** to evaluate whether a //! single `char` has the XID\_Start or XID\_Continue Unicode property, //! comparing across different ratios of ASCII to non-ASCII codepoints in the //! input data. //! //! [`unicode-xid`]: https://github.com/unicode-rs/unicode-xid //! [`ucd-generate`]: https://github.com/BurntSushi/ucd-generate //! [`roaring`]: https://github.com/RoaringBitmap/roaring-rs //! //! | | static storage | 0% nonascii | 1% | 10% | 100% nonascii | //! |---|---|---|---|---|---| //! | **`unicode-ident`** | 10.1 K | 0.96 ns | 0.95 ns | 1.09 ns | 1.55 ns | //! | **`unicode-xid`** | 11.5 K | 1.88 ns | 2.14 ns | 3.48 ns | 15.63 ns | //! | **`ucd-trie`** | 10.2 K | 1.29 ns | 1.28 ns | 1.36 ns | 2.15 ns | //! | **`fst`** | 139 K | 55.1 ns | 54.9 ns | 53.2 ns | 28.5 ns | //! | **`roaring`** | 66.1 K | 2.78 ns | 3.09 ns | 3.37 ns | 4.70 ns | //! //! Source code for the benchmark is provided in the *bench* directory of this //! repo and may be repeated by running `cargo criterion`. //! //!
//! //! ## Comparison of data structures //! //! #### unicode-xid //! //! They use a sorted array of character ranges, and do a binary search to look //! up whether a given character lands inside one of those ranges. //! //! ```rust //! # const _: &str = stringify! { //! static XID_Continue_table: [(char, char); 763] = [ //! ('\u{30}', '\u{39}'), // 0-9 //! ('\u{41}', '\u{5a}'), // A-Z //! # " //! … //! # " //! ('\u{e0100}', '\u{e01ef}'), //! ]; //! # }; //! ``` //! //! The static storage used by this data structure scales with the number of //! contiguous ranges of identifier codepoints in Unicode. Every table entry //! consumes 8 bytes, because it consists of a pair of 32-bit `char` values. //! //! In some ranges of the Unicode codepoint space, this is quite a sparse //! representation – there are some ranges where tens of thousands of //! adjacent codepoints are all valid identifier characters. In other places, //! the representation is quite inefficient. A characater like `µ` (U+00B5) //! which is surrounded by non-identifier codepoints consumes 64 bits in the //! table, while it would be just 1 bit in a dense bitmap. //! //! On a system with 64-byte cache lines, binary searching the table touches 7 //! cache lines on average. Each cache line fits only 8 table entries. //! Additionally, the branching performed during the binary search is probably //! mostly unpredictable to the branch predictor. //! //! Overall, the crate ends up being about 10× slower on non-ASCII input //! compared to the fastest crate. //! //! A potential improvement would be to pack the table entries more compactly. //! Rust's `char` type is a 21-bit integer padded to 32 bits, which means every //! table entry is holding 22 bits of wasted space, adding up to 3.9 K. They //! could instead fit every table entry into 6 bytes, leaving out some of the //! padding, for a 25% improvement in space used. With some cleverness it may be //! possible to fit in 5 bytes or even 4 bytes by storing a low char and an //! extent, instead of low char and high char. I don't expect that performance //! would improve much but this could be the most efficient for space across all //! the libraries, needing only about 7 K to store. //! //! #### ucd-trie //! //! Their data structure is a compressed trie set specifically tailored for //! Unicode codepoints. The design is credited to Raph Levien in //! [rust-lang/rust#33098]. //! //! [rust-lang/rust#33098]: https://github.com/rust-lang/rust/pull/33098 //! //! ```rust //! pub struct TrieSet { //! tree1_level1: &'static [u64; 32], //! tree2_level1: &'static [u8; 992], //! tree2_level2: &'static [u64], //! tree3_level1: &'static [u8; 256], //! tree3_level2: &'static [u8], //! tree3_level3: &'static [u64], //! } //! ``` //! //! It represents codepoint sets using a trie to achieve prefix compression. The //! final states of the trie are embedded in leaves or "chunks", where each //! chunk is a 64-bit integer. Each bit position of the integer corresponds to //! whether a particular codepoint is in the set or not. These chunks are not //! just a compact representation of the final states of the trie, but are also //! a form of suffix compression. In particular, if multiple ranges of 64 //! contiguous codepoints have the same Unicode properties, then they all map to //! the same chunk in the final level of the trie. //! //! Being tailored for Unicode codepoints, this trie is partitioned into three //! disjoint sets: tree1, tree2, tree3. The first set corresponds to codepoints //! \[0, 0x800), the second \[0x800, 0x10000) and the third \[0x10000, //! 0x110000). These partitions conveniently correspond to the space of 1 or 2 //! byte UTF-8 encoded codepoints, 3 byte UTF-8 encoded codepoints and 4 byte //! UTF-8 encoded codepoints, respectively. //! //! Lookups in this data structure are significantly more efficient than binary //! search. A lookup touches either 1, 2, or 3 cache lines based on which of the //! trie partitions is being accessed. //! //! One possible performance improvement would be for this crate to expose a way //! to query based on a UTF-8 encoded string, returning the Unicode property //! corresponding to the first character in the string. Without such an API, the //! caller is required to tokenize their UTF-8 encoded input data into `char`, //! hand the `char` into `ucd-trie`, only for `ucd-trie` to undo that work by //! converting back into the variable-length representation for trie traversal. //! //! #### fst //! //! Uses a [finite state transducer][fst]. This representation is built into //! [ucd-generate] but I am not aware of any advantage over the `ucd-trie` //! representation. In particular `ucd-trie` is optimized for storing Unicode //! properties while `fst` is not. //! //! [fst]: https://github.com/BurntSushi/fst //! [ucd-generate]: https://github.com/BurntSushi/ucd-generate //! //! As far as I can tell, the main thing that causes `fst` to have large size //! and slow lookups for this use case relative to `ucd-trie` is that it does //! not specialize for the fact that only 21 of the 32 bits in a `char` are //! meaningful. There are some dense arrays in the structure with large ranges //! that could never possibly be used. //! //! #### roaring //! //! This crate is a pure-Rust implementation of [Roaring Bitmap], a data //! structure designed for storing sets of 32-bit unsigned integers. //! //! [Roaring Bitmap]: https://roaringbitmap.org/about/ //! //! Roaring bitmaps are compressed bitmaps which tend to outperform conventional //! compressed bitmaps such as WAH, EWAH or Concise. In some instances, they can //! be hundreds of times faster and they often offer significantly better //! compression. //! //! In this use case the performance was reasonably competitive but still //! substantially slower than the Unicode-optimized crates. Meanwhile the //! compression was significantly worse, requiring 6× as much storage for //! the data structure. //! //! I also benchmarked the [`croaring`] crate which is an FFI wrapper around the //! C reference implementation of Roaring Bitmap. This crate was consistently //! about 15% slower than pure-Rust `roaring`, which could just be FFI overhead. //! I did not investigate further. //! //! [`croaring`]: https://crates.io/crates/croaring //! //! #### unicode-ident //! //! This crate is most similar to the `ucd-trie` library, in that it's based on //! bitmaps stored in the leafs of a trie representation, achieving both prefix //! compression and suffix compression. //! //! The key differences are: //! //! - Uses a single 2-level trie, rather than 3 disjoint partitions of different //! depth each. //! - Uses significantly larger chunks: 512 bits rather than 64 bits. //! - Compresses the XID\_Start and XID\_Continue properties together //! simultaneously, rather than duplicating identical trie leaf chunks across //! the two. //! //! The following diagram show the XID\_Start and XID\_Continue Unicode boolean //! properties in uncompressed form, in row-major order: //! //! //! //! //! //! //! //!
XID_StartXID_Continue
XID_Start bitmapXID_Continue bitmap
//! //! Uncompressed, these would take 140 K to store, which is beyond what would be //! reasonable. However, as you can see there is a large degree of similarity //! between the two bitmaps and across the rows, which lends well to //! compression. //! //! This crate stores one 512-bit "row" of the above bitmaps in the leaf level //! of a trie, and a single additional level to index into the leafs. It turns //! out there are 124 unique 512-bit chunks across the two bitmaps so 7 bits are //! sufficient to index them. //! //! The chunk size of 512 bits is selected as the size that minimizes the total //! size of the data structure. A smaller chunk, like 256 or 128 bits, would //! achieve better deduplication but require a larger index. A larger chunk //! would increase redundancy in the leaf bitmaps. 512 bit chunks are the //! optimum for total size of the index plus leaf bitmaps. //! //! In fact since there are only 124 unique chunks, we can use an 8-bit index //! with a spare bit to index at the half-chunk level. This achieves an //! additional 8.5% compression by eliminating redundancies between the second //! half of any chunk and the first half of any other chunk. Note that this is //! not the same as using chunks which are half the size, because it does not //! necessitate raising the size of the trie's first level. //! //! In contrast to binary search or the `ucd-trie` crate, performing lookups in //! this data structure is straight-line code with no need for branching. #![no_std] #![doc(html_root_url = "https://docs.rs/unicode-ident/1.0.12")] #![allow(clippy::doc_markdown, clippy::must_use_candidate)] #[rustfmt::skip] mod tables; use crate::tables::{ASCII_CONTINUE, ASCII_START, CHUNK, LEAF, TRIE_CONTINUE, TRIE_START}; pub fn is_xid_start(ch: char) -> bool { if ch.is_ascii() { return ASCII_START.0[ch as usize]; } let chunk = *TRIE_START.0.get(ch as usize / 8 / CHUNK).unwrap_or(&0); let offset = chunk as usize * CHUNK / 2 + ch as usize / 8 % CHUNK; unsafe { LEAF.0.get_unchecked(offset) }.wrapping_shr(ch as u32 % 8) & 1 != 0 } pub fn is_xid_continue(ch: char) -> bool { if ch.is_ascii() { return ASCII_CONTINUE.0[ch as usize]; } let chunk = *TRIE_CONTINUE.0.get(ch as usize / 8 / CHUNK).unwrap_or(&0); let offset = chunk as usize * CHUNK / 2 + ch as usize / 8 % CHUNK; unsafe { LEAF.0.get_unchecked(offset) }.wrapping_shr(ch as u32 % 8) & 1 != 0 } unicode-ident/.cargo-checksum.json0000664000175000017500000000315114661133735020136 0ustar jamespagejamespage{"files":{"Cargo.toml":"7b10355305359d5feefb120329396a8823ce903cd66612d7d27612d51e6ceced","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","LICENSE-UNICODE":"68f5b9f5ea36881a0942ba02f558e9e1faf76cc09cb165ad801744c61b738844","README.md":"eff1f30712e93cc160101c25bf31738448c284b90636deb3e3a651cb9ad20dd1","benches/xid.rs":"a61f61ecc7d5124c759cdeb55ab74470ab69f2f3ca37613da65f16e0e5e33487","src/lib.rs":"2673969775cff349816e3fb30f62476a802523fe4940482288b75bd747cbe748","src/tables.rs":"ffe8e252eabccf261385865cb781b3d76c9f32f6f9503d00196a30fb92d80b29","tests/compare.rs":"62471ffb157744cac6faae1adafdbdf785349d7eb6dc2ff4b4941c9d618397f9","tests/fst/mod.rs":"69a3aaf59acd8bca962ecc6234be56be8c0934ab79b253162f10eb881523901f","tests/fst/xid_continue.fst":"41fc751514b8bde658544d5fe7e100115d299d41897af855934b9f4ebda9d3a2","tests/fst/xid_start.fst":"ffa5e2bfe7dd5f6738fbe4b7a3e6e2083c9777191c54f8291a80d558ec4e2dd2","tests/roaring/mod.rs":"784f65a48477fab7549620c7843c7ad6da533f69a18abca1172f6acb95045e53","tests/static_size.rs":"4524332c1e424cb987d7cee1f47a98aea9ed7b256303a3828eda5aa1d06da240","tests/tables/mod.rs":"e6949172d10fc4b2431ce7546269bfd4f9146454c8c3e31faf5e5d80c16a8ab6","tests/tables/tables.rs":"011404dab8a3958da6e18a1fe9406c191675e6f49bf30ce813e3d05f582e750b","tests/trie/mod.rs":"d4acbb716bcbaf80660039797f45e138ed8bbd66749fa3b19b1a971574679cc9","tests/trie/trie.rs":"3c1ca56062f1b3ffdf2ae2063d3fee8d362b90082778056181b5c95e2e242ad8"},"package":"3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"}unindent/0000775000175000017500000000000014661133735013367 5ustar jamespagejamespageunindent/README.md0000644000175000017500000000477214661133735014656 0ustar jamespagejamespage# Unindent [github](https://github.com/dtolnay/indoc) [crates.io](https://crates.io/crates/unindent) [docs.rs](https://docs.rs/unindent) [build status](https://github.com/dtolnay/indoc/actions?query=branch%3Amaster) This crate provides [`indoc`]'s indentation logic for use with strings that are not statically known at compile time. For unindenting string literals, use `indoc` instead. [`indoc`]: https://github.com/dtolnay/indoc This crate exposes two functions: - `unindent(&str) -> String` - `unindent_bytes(&[u8]) -> Vec` ```rust use unindent::unindent; fn main() { let indented = " line one line two"; assert_eq!("line one\nline two", unindent(indented)); } ``` ## Explanation The following rules characterize the behavior of unindent: 1. Count the leading spaces of each line, ignoring the first line and any lines that are empty or contain spaces only. 2. Take the minimum. 3. If the first line is empty i.e. the string begins with a newline, remove the first line. 4. Remove the computed number of spaces from the beginning of each line. This means there are a few equivalent ways to format the same string, so choose one you like. All of the following result in the string `"line one\nline two\n"`: ``` unindent(" / unindent( / unindent("line one line one / "line one / line two line two / line two / ") ") / ") / ``` ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Indoc by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. unindent/LICENSE-APACHE0000644000175000017500000002277314661133735015324 0ustar jamespagejamespage Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS unindent/Cargo.toml0000644000175000017500000000204514661133735015316 0ustar jamespagejamespage# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "unindent" version = "0.2.3" authors = ["David Tolnay "] description = "Remove a column of leading whitespace from a string" documentation = "https://docs.rs/unindent" readme = "README.md" keywords = [ "heredoc", "nowdoc", "multiline", "string", "literal", ] categories = ["text-processing"] license = "MIT OR Apache-2.0" repository = "https://github.com/dtolnay/indoc" [package.metadata.docs.rs] rustdoc-args = ["--generate-link-to-definition"] targets = ["x86_64-unknown-linux-gnu"] [lib] doc-scrape-examples = false unindent/LICENSE-MIT0000644000175000017500000000177714661133735015035 0ustar jamespagejamespagePermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. unindent/src/0000775000175000017500000000000014661133735014156 5ustar jamespagejamespageunindent/src/lib.rs0000644000175000017500000000341314661133735015271 0ustar jamespagejamespage//! [![github]](https://github.com/dtolnay/indoc) [![crates-io]](https://crates.io/crates/unindent) [![docs-rs]](https://docs.rs/unindent) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs //! //!
//! //! ## Unindent //! //! This crate provides [`indoc`]'s indentation logic for use with strings that //! are not statically known at compile time. For unindenting string literals, //! use `indoc` instead. //! //! [`indoc`]: https://github.com/dtolnay/indoc //! //! This crate exposes two unindent functions and an extension trait: //! //! - `fn unindent(&str) -> String` //! - `fn unindent_bytes(&[u8]) -> Vec` //! - `trait Unindent` //! //! ``` //! use unindent::unindent; //! //! fn main() { //! let indented = " //! line one //! line two"; //! assert_eq!("line one\nline two", unindent(indented)); //! } //! ``` //! //! The `Unindent` extension trait expose the same functionality under an //! extension method. //! //! ``` //! use unindent::Unindent; //! //! fn main() { //! let indented = format!(" //! line {} //! line {}", "one", "two"); //! assert_eq!("line one\nline two", indented.unindent()); //! } //! ``` #![doc(html_root_url = "https://docs.rs/unindent/0.2.3")] #![allow( clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::needless_doctest_main, clippy::trivially_copy_pass_by_ref, clippy::type_complexity )] mod unindent; pub use crate::unindent::*; unindent/src/unindent.rs0000644000175000017500000000574214661133735016356 0ustar jamespagejamespageuse std::slice::Split; pub fn unindent(s: &str) -> String { let preserve_empty_first_line = false; do_unindent(s, preserve_empty_first_line) } // Compute the maximal number of spaces that can be removed from every line, and // remove them. pub fn unindent_bytes(s: &[u8]) -> Vec { let preserve_empty_first_line = false; do_unindent_bytes(s, preserve_empty_first_line) } pub(crate) fn do_unindent(s: &str, preserve_empty_first_line: bool) -> String { let bytes = s.as_bytes(); let unindented = do_unindent_bytes(bytes, preserve_empty_first_line); String::from_utf8(unindented).unwrap() } fn do_unindent_bytes(s: &[u8], preserve_empty_first_line: bool) -> Vec { // Document may start either on the same line as opening quote or // on the next line let ignore_first_line = !preserve_empty_first_line && (s.starts_with(b"\n") || s.starts_with(b"\r\n")); // Largest number of spaces that can be removed from every // non-whitespace-only line after the first let spaces = s .lines() .skip(1) .filter_map(count_spaces) .min() .unwrap_or(0); let mut result = Vec::with_capacity(s.len()); for (i, line) in s.lines().enumerate() { if i > 1 || (i == 1 && !ignore_first_line) { result.push(b'\n'); } if i == 0 { // Do not un-indent anything on same line as opening quote result.extend_from_slice(line); } else if line.len() > spaces { // Whitespace-only lines may have fewer than the number of spaces // being removed result.extend_from_slice(&line[spaces..]); } } result } pub trait Unindent { type Output; fn unindent(&self) -> Self::Output; } impl Unindent for str { type Output = String; fn unindent(&self) -> Self::Output { unindent(self) } } impl Unindent for String { type Output = String; fn unindent(&self) -> Self::Output { unindent(self) } } impl Unindent for [u8] { type Output = Vec; fn unindent(&self) -> Self::Output { unindent_bytes(self) } } impl<'a, T: ?Sized + Unindent> Unindent for &'a T { type Output = T::Output; fn unindent(&self) -> Self::Output { (**self).unindent() } } // Number of leading spaces in the line, or None if the line is entirely spaces. fn count_spaces(line: &[u8]) -> Option { for (i, ch) in line.iter().enumerate() { if *ch != b' ' && *ch != b'\t' { return Some(i); } } None } // Based on core::str::StrExt. trait BytesExt { fn lines(&self) -> Split bool>; } impl BytesExt for [u8] { fn lines(&self) -> Split bool> { fn is_newline(b: &u8) -> bool { *b == b'\n' } let bytestring = if self.starts_with(b"\r\n") { &self[1..] } else { self }; bytestring.split(is_newline as fn(&u8) -> bool) } } unindent/.cargo-checksum.json0000664000175000017500000000110114661133735017224 0ustar jamespagejamespage{"files":{"Cargo.toml":"778373d89103f2c18c12558407a94e2bc382d82ad52747502f405c154d9919f4","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"13fe850f35f99ad1701eb640baada22f5cce3072a9e99006d1e4f7d3e847455d","src/lib.rs":"b335afdaf098418d54687e5ba19eb5465976f14df54e4dffd2eb00eb1558007e","src/unindent.rs":"988a92e473e8f033882e7236bab6d38ece304116f6ac9f6aaf6f25b4bb9f6d27"},"package":"c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"}